--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/common/properties.c Wed Dec 09 11:32:01 2020 +0100 @@ -0,0 +1,297 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2017 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <errno.h> + +#include "properties.h" +#include <ucx/string.h> +#include <ucx/buffer.h> +#include <ucx/properties.h> + +static UiProperties *application_properties; +static UiProperties *language; + +#ifndef UI_COCOA + +static char *locales_dir; +static char *pixmaps_dir; + +#endif + +char* ui_getappdir() { + if(ui_appname() == NULL) { + return NULL; + } + + return ui_configfile(NULL); +} + +char* ui_configfile(char *name) { + char *appname = ui_appname(); + if(!appname) { + return NULL; + } + + UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); + + // add base dir + char *homeenv = getenv("HOME"); + if(homeenv == NULL) { + ucx_buffer_free(buf); + return NULL; + } + sstr_t home = sstr(homeenv); + + ucx_buffer_write(home.ptr, 1, home.length, buf); + if(home.ptr[home.length-1] != '/') { + ucx_buffer_putc(buf, '/'); + } + +#ifdef UI_COCOA + // on OS X the app dir is $HOME/Library/Application Support/$APPNAME/ + ucx_buffer_puts(buf, "Library/Application Support/"); +#else + // app dir is $HOME/.$APPNAME/ + ucx_buffer_putc(buf, '.'); +#endif + ucx_buffer_puts(buf, appname); + ucx_buffer_putc(buf, '/'); + + // add file name + if(name) { + ucx_buffer_puts(buf, name); + } + + char *path = buf->space; + free(buf); + return path; +} + +static int ui_mkdir(char *path) { +#ifdef _WIN32 + return mkdir(path); +#else + return mkdir(path, S_IRWXU); +#endif +} + +void uic_load_app_properties() { + application_properties = ucx_map_new(128); + + if(!ui_appname()) { + // applications without name cannot load app properties + return; + } + + char *dir = ui_configfile(NULL); + if(!dir) { + return; + } + if(ui_mkdir(dir)) { + if(errno != EEXIST) { + fprintf(stderr, "Ui Error: Cannot create directory %s\n", dir); + free(dir); + return; + } + } + free(dir); + + char *path = ui_configfile("application.properties"); + if(!path) { + return; + } + + FILE *file = fopen(path, "r"); + if(!file) { + free(path); + return; + } + + if(ucx_properties_load(application_properties, file)) { + fprintf(stderr, "Ui Error: Cannot load application properties.\n"); + } + + fclose(file); + free(path); +} + +void uic_store_app_properties() { + char *path = ui_configfile("application.properties"); + if(!path) { + return; + } + + FILE *file = fopen(path, "w"); + if(!file) { + fprintf(stderr, "Ui Error: Cannot open properties file: %s\n", path); + free(path); + return; + } + + if(ucx_properties_store(application_properties, file)) { + fprintf(stderr, "Ui Error: Cannot store application properties.\n"); + } + + fclose(file); + free(path); +} + + +char* ui_get_property(char *name) { + return ucx_map_cstr_get(application_properties, name); +} + +void ui_set_property(char *name, char *value) { + ucx_map_cstr_put(application_properties, name, value); +} + +void ui_set_default_property(char *name, char *value) { + char *v = ucx_map_cstr_get(application_properties, name); + if(!v) { + ucx_map_cstr_put(application_properties, name, value); + } +} + + + +static char* uic_concat_path(const char *base, const char *p, const char *ext) { + size_t baselen = strlen(base); + + UcxBuffer *buf = ucx_buffer_new(NULL, 32, UCX_BUFFER_AUTOEXTEND); + if(baselen > 0) { + ucx_buffer_write(base, 1, baselen, buf); + if(base[baselen - 1] != '/') { + ucx_buffer_putc(buf, '/'); + } + } + ucx_buffer_write(p, 1, strlen(p), buf); + if(ext) { + ucx_buffer_write(ext, 1, strlen(ext), buf); + } + + char *str = buf->space; + free(buf); + return str; +} + +#ifndef UI_COCOA + +void ui_locales_dir(char *path) { + locales_dir = path; +} + +void ui_pixmaps_dir(char *path) { + pixmaps_dir = path; +} + +char* uic_get_image_path(const char *imgfilename) { + if(pixmaps_dir) { + return uic_concat_path(pixmaps_dir, imgfilename, NULL); + } else { + return NULL; + } +} + +void ui_load_lang(char *locale) { + if(!locale) { + locale = "en_EN"; + } + + char *path = uic_concat_path(locales_dir, locale, ".properties"); + + uic_load_language_file(path); + free(path); +} + +void ui_load_lang_def(char *locale, char *default_locale) { + char tmp[6]; + if(!locale) { + char *lang = getenv("LANG"); + if(lang && strlen(lang) >= 5) { + memcpy(tmp, lang, 5); + tmp[5] = '\0'; + locale = tmp; + } else { + locale = default_locale; + } + } + + char *path = uic_concat_path(locales_dir, locale, ".properties"); + + if(uic_load_language_file(path)) { + if(default_locale) { + ui_load_lang_def(default_locale, NULL); + } else { + // cannot find any language file + fprintf(stderr, "Ui Error: Cannot load language.\n"); + free(path); + exit(-1); + } + } + free(path); +} + +#endif + +int uic_load_language_file(const char *path) { + UcxMap *lang = ucx_map_new(256); + + FILE *file = fopen(path, "r"); + if(!file) { + return 1; + } + + if(ucx_properties_load(lang, file)) { + fprintf(stderr, "Ui Error: Cannot parse language file: %s.\n", path); + } + + fclose(file); + + ucx_map_rehash(lang); + + language = lang; + + return 0; +} + +char* uistr(char *name) { + char *value = uistr_n(name); + return value ? value : "missing string"; +} + +char* uistr_n(char *name) { + if(!language) { + return NULL; + } + return ucx_map_cstr_get(language, name); +} +