Mercurial > molko
diff libcore/core/sys.c @ 241:76afe639fd72
misc: add support for NLS, closes #22510 @4h
While here cleanup the path functions in sys.c/sys.h
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sat, 28 Nov 2020 18:00:05 +0100 |
parents | c9fbb822d269 |
children |
line wrap: on
line diff
--- a/libcore/core/sys.c Fri Nov 27 21:34:07 2020 +0100 +++ b/libcore/core/sys.c Sat Nov 28 18:00:05 2020 +0100 @@ -16,89 +16,76 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "sysconfig.h" + #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <limits.h> +#if defined(_WIN32) +# include <shlwapi.h> +#endif + #include <SDL.h> #include <SDL_image.h> #include <SDL_mixer.h> #include <SDL_ttf.h> -#if !defined(_WIN32) /* Assuming POSIX */ -# include <sys/types.h> -# include <dirent.h> -#endif - #include "error.h" #include "sound.h" #include "sys.h" -#if defined(_WIN32) - -static void -determine(char path[], size_t pathlen) -{ - char *base = SDL_GetBasePath(); +static struct { + char organization[128]; + char name[128]; +} info = { + .organization = "fr.malikania", + .name = "molko" +}; - /* On Windows, the data hierarchy is the same as the project. */ - snprintf(path, pathlen, "%sassets", base); - SDL_free(base); -} +static const char *paths[] = { + [SYS_DIR_BIN] = MOLKO_BINDIR, + [SYS_DIR_DATA] = MOLKO_DATADIR, + [SYS_DIR_LOCALE] = MOLKO_LOCALEDIR +}; -#else /* Assuming POSIX */ +static const char *abspaths[] = { + [SYS_DIR_BIN] = MOLKO_ABS_BINDIR, + [SYS_DIR_DATA] = MOLKO_ABS_DATADIR, + [SYS_DIR_LOCALE] = MOLKO_ABS_LOCALEDIR +}; + +#if defined(_WIN32) static bool is_absolute(const char *path) { - assert(path); - - return path[0] == '/'; + return !PathIsRelativeA(path); } -static void -determine(char path[], size_t pathlen) -{ - char localassets[PATH_MAX]; - char *base = SDL_GetBasePath(); - DIR *dp; - - /* Try assets directory where executable lives. */ - snprintf(localassets, sizeof (localassets), "%sassets", base); +#else - if ((dp = opendir(localassets))) { - snprintf(path, pathlen, "%sassets", base); - closedir(dp); - } else { - /* We are not in the project source directory. */ - if (is_absolute(SHAREDIR)) { - /* SHAREDIR is absolute */ - snprintf(path, pathlen, "%s/molko", SHAREDIR); - } else if (is_absolute(BINDIR)) { - /* SHAREDIR is relative but BINDIR is absolute */ - snprintf(path, pathlen, "%s/%s/molko", PREFIX, SHAREDIR); - } else { - /* SHAREDIR, BINDIR are both relative */ - char *ptr = strstr(base, BINDIR); - - if (ptr) { - *ptr = '\0'; - snprintf(path, pathlen, "%s%s/molko", base, SHAREDIR); - } else { - /* Unable to determine. */ - snprintf(path, pathlen, "."); - } - } - } - - SDL_free(base); +static bool +is_absolute(const char *path) +{ + return path[0] == '/'; } #endif +static char * +normalize(char *str) +{ + for (char *p = str; *p; ++p) + if (*p == '\\') + *p = '/'; + + return str; +} + bool -sys_init(void) +sys_init(const char *organization, const char *name) { #if defined(__MINGW64__) /* On MinGW buffering leads to painful debugging. */ @@ -106,6 +93,9 @@ setbuf(stdout, NULL); #endif + snprintf(info.organization, sizeof (info.organization), "%s", organization); + snprintf(info.name, sizeof (info.name), "%s", name); + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) return errorf("%s", SDL_GetError()); if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) @@ -122,55 +112,97 @@ return true; } -const char * -sys_datadir(void) +static const char * +absolute(const char *which) { static char path[PATH_MAX]; - if (path[0] == '\0') - determine(path, sizeof (path)); + snprintf(path, sizeof (path), "%s", which); - return path; + return normalize(path); } -const char * -sys_datapath(const char *fmt, ...) +static const char * +system_directory(enum sys_dir kind) { - const char *ret; - va_list ap; + static char path[PATH_MAX]; + static char ret[PATH_MAX]; + char *base, *binsect; + + /* 1. Get current binary directory. */ + base = SDL_GetBasePath(); + + /* + * 2. Decompose the path to the given special directory by computing + * relative directory to it from where the binary is located. + * + * Example: + * PREFIX/bin/mlk + * PREFIX/share/molko + * + * The path to the data is ../share/molko starting from the binary. + * + * If path to binary is absolute we can't determine relative paths to + * any other directory and use the absolute one instead. + * + * Also, on some platforms SDL_GetBasePath isn't implemented and returns + * NULL, in that case return the fallback to the installation prefix. + */ + if (is_absolute(paths[SYS_DIR_BIN]) || is_absolute(paths[kind]) || !base) + return absolute(abspaths[kind]); - va_start(ap, fmt); - ret = sys_datapathv(fmt, ap); - va_end(ap); + /* + * 3. Put the base path into the path and remove the value of + * MOLKO_BINDIR. + * + * Example: + * from: /usr/local/bin + * to: /usr/local + */ + snprintf(path, sizeof (path), "%s", base); + SDL_free(base); + + if ((binsect = strstr(path, paths[SYS_DIR_BIN]))) + *binsect = '\0'; + + /* 4. For data directories, we append the program name. */ + if (kind == SYS_DIR_DATA) + snprintf(ret, sizeof (ret), "%s%s/%s", path, paths[kind], info.name); + else + snprintf(ret, sizeof (ret), "%s%s", path, paths[kind]); - return ret; + return normalize(ret); +} + +static const char * +user_directory(enum sys_dir kind) +{ + /* Kept for future use. */ + (void)kind; + + static char path[PATH_MAX]; + char *pref; + + if ((pref = SDL_GetPrefPath(info.organization, info.name))) { + snprintf(path, sizeof (path), "%s", pref); + SDL_free(pref); + } else + snprintf(path, sizeof (path), "./"); + + return NULL; } const char * -sys_datapathv(const char *fmt, va_list ap) +sys_dir(enum sys_dir kind) { - static char path[PATH_MAX]; - char filename[FILENAME_MAX]; - - vsnprintf(filename, sizeof (filename), fmt, ap); - snprintf(path, sizeof (path), "%s/%s", sys_datadir(), filename); - - return path; -} - -const char * -sys_savepath(unsigned int idx) -{ - static char path[PATH_MAX]; - char *pref; - - if ((pref = SDL_GetPrefPath("malikania", "molko"))) { - snprintf(path, sizeof (path), "%ssave-%u", pref, idx); - SDL_free(pref); - } else - snprintf(path, sizeof (path), "save-%u", idx); - - return path; + switch (kind) { + case SYS_DIR_BIN: + case SYS_DIR_DATA: + case SYS_DIR_LOCALE: + return system_directory(kind); + default: + return user_directory(kind); + } } void