UNIXworkcode

/* * 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 "../ui/toolkit.h" #include "properties.h" #include <cx/string.h> #include <cx/buffer.h> #include <cx/hash_map.h> #include "ucx_properties.h" static CxMap *application_properties; static CxMap *language; #ifndef UI_COCOA static char *locales_dir; static char *pixmaps_dir; #endif char* ui_getappdir(void) { if(ui_appname() == NULL) { return NULL; } return ui_configfile(NULL); } #ifndef _WIN32 #define UI_PATH_SEPARATOR '/' #define UI_ENV_HOME "HOME" #else #define UI_PATH_SEPARATOR '\\' #define UI_ENV_HOME "USERPROFILE" #endif char* ui_configfile(char *name) { const char *appname = ui_appname(); if(!appname) { return NULL; } CxBuffer buf; cxBufferInit(&buf, NULL, 128, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); // add base dir char *homeenv = getenv(UI_ENV_HOME); if(homeenv == NULL) { cxBufferDestroy(&buf); return NULL; } cxstring home = cx_str(homeenv); cxBufferWrite(home.ptr, 1, home.length, &buf); if(home.ptr[home.length-1] != UI_PATH_SEPARATOR) { cxBufferPut(&buf, UI_PATH_SEPARATOR); } #ifdef UI_COCOA // on OS X the app dir is $HOME/Library/Application Support/$APPNAME/ cxBufferPutString(&buf, "Library/Application Support/"); #elif defined(_WIN32) // on Windows the app dir is $USERPROFILE/AppData/Local/$APPNAME/ cxBufferPutString(&buf, "AppData\\Local\\"); #else // app dir is $HOME/.$APPNAME/ cxBufferPut(&buf, '.'); #endif cxBufferPutString(&buf, appname); cxBufferPut(&buf, UI_PATH_SEPARATOR); // add file name if(name) { cxBufferPutString(&buf, name); } cxBufferPut(&buf, 0); return buf.space; } 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 = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 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); } int uic_store_app_properties() { char *path = ui_configfile("application.properties"); if(!path) { return 1; } FILE *file = fopen(path, "w"); if(!file) { fprintf(stderr, "Ui Error: Cannot open properties file: %s\n", path); free(path); return 1; } int ret = 0; if(ucx_properties_store(application_properties, file)) { fprintf(stderr, "Ui Error: Cannot store application properties.\n"); ret = 1; } fclose(file); free(path); return ret; } const char* ui_get_property(const char *name) { return cxMapGet(application_properties, name); } void ui_set_property(const char *name, const char *value) { cxMapPut(application_properties, name, (char*)value); } const char* ui_set_default_property(const char *name, const char *value) { const char *v = cxMapGet(application_properties, name); if(!v) { cxMapPut(application_properties, name, (char*)value); v = value; } return v; } int ui_properties_store(void) { return uic_store_app_properties(); } static char* uic_concat_path(const char *base, const char *p, const char *ext) { size_t baselen = strlen(base); CxBuffer *buf = cxBufferCreate(NULL, 32, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); if(baselen > 0) { cxBufferWrite(base, 1, baselen, buf); if(base[baselen - 1] != '/') { cxBufferPut(buf, '/'); } } cxBufferWrite(p, 1, strlen(p), buf); if(ext) { cxBufferWrite(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) { CxMap *lang = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 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); cxMapRehash(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 cxMapGet(language, name); }