ui/common/properties.c

changeset 0
2483f517c562
child 29
3fc287f06305
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/properties.c	Sun Jan 21 16:30:18 2024 +0100
@@ -0,0 +1,299 @@
+/*
+ * 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 <cx/string.h>
+#include <cx/buffer.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() {
+    if(ui_appname() == NULL) {
+        return NULL;
+    }
+    
+    return ui_configfile(NULL);
+}
+
+char* ui_configfile(char *name) {
+    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("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] != '/') {
+        cxBufferPut(&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/
+    cxBufferPut(&buf, '.');
+#endif
+    cxBufferPutString(&buf, appname);
+    cxBufferPut(&buf, '/');
+    
+    // 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);
+}
+
+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 cxMapGet(application_properties, name);
+}
+
+void ui_set_property(char *name, char *value) {
+    cxMapPut(application_properties, name, value);
+}
+
+void ui_set_default_property(char *name, char *value) {
+    char *v = cxMapGet(application_properties, name);
+    if(!v) {
+        cxMapPut(application_properties, name, value);
+    }
+}
+
+
+
+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);
+}
+

mercurial