UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2017 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <sys/stat.h> 33 #include <errno.h> 34 35 #include "properties.h" 36 #include <ucx/string.h> 37 #include <ucx/buffer.h> 38 #include <ucx/properties.h> 39 40 static UiProperties *application_properties; 41 static UiProperties *language; 42 43 #ifndef UI_COCOA 44 45 static char *locales_dir; 46 static char *pixmaps_dir; 47 48 #endif 49 50 char* ui_getappdir() { 51 if(ui_appname() == NULL) { 52 return NULL; 53 } 54 55 return ui_configfile(NULL); 56 } 57 58 char* ui_configfile(char *name) { 59 char *appname = ui_appname(); 60 if(!appname) { 61 return NULL; 62 } 63 64 UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND); 65 66 // add base dir 67 char *homeenv = getenv("HOME"); 68 if(homeenv == NULL) { 69 ucx_buffer_free(buf); 70 return NULL; 71 } 72 sstr_t home = sstr(homeenv); 73 74 ucx_buffer_write(home.ptr, 1, home.length, buf); 75 if(home.ptr[home.length-1] != '/') { 76 ucx_buffer_putc(buf, '/'); 77 } 78 79 #ifdef UI_COCOA 80 // on OS X the app dir is $HOME/Library/Application Support/$APPNAME/ 81 ucx_buffer_puts(buf, "Library/Application Support/"); 82 #else 83 // app dir is $HOME/.$APPNAME/ 84 ucx_buffer_putc(buf, '.'); 85 #endif 86 ucx_buffer_puts(buf, appname); 87 ucx_buffer_putc(buf, '/'); 88 89 // add file name 90 if(name) { 91 ucx_buffer_puts(buf, name); 92 } 93 94 char *path = buf->space; 95 free(buf); 96 return path; 97 } 98 99 static int ui_mkdir(char *path) { 100 #ifdef _WIN32 101 return mkdir(path); 102 #else 103 return mkdir(path, S_IRWXU); 104 #endif 105 } 106 107 void uic_load_app_properties() { 108 application_properties = ucx_map_new(128); 109 110 if(!ui_appname()) { 111 // applications without name cannot load app properties 112 return; 113 } 114 115 char *dir = ui_configfile(NULL); 116 if(!dir) { 117 return; 118 } 119 if(ui_mkdir(dir)) { 120 if(errno != EEXIST) { 121 fprintf(stderr, "Ui Error: Cannot create directory %s\n", dir); 122 free(dir); 123 return; 124 } 125 } 126 free(dir); 127 128 char *path = ui_configfile("application.properties"); 129 if(!path) { 130 return; 131 } 132 133 FILE *file = fopen(path, "r"); 134 if(!file) { 135 free(path); 136 return; 137 } 138 139 if(ucx_properties_load(application_properties, file)) { 140 fprintf(stderr, "Ui Error: Cannot load application properties.\n"); 141 } 142 143 fclose(file); 144 free(path); 145 } 146 147 void uic_store_app_properties() { 148 char *path = ui_configfile("application.properties"); 149 if(!path) { 150 return; 151 } 152 153 FILE *file = fopen(path, "w"); 154 if(!file) { 155 fprintf(stderr, "Ui Error: Cannot open properties file: %s\n", path); 156 free(path); 157 return; 158 } 159 160 if(ucx_properties_store(application_properties, file)) { 161 fprintf(stderr, "Ui Error: Cannot store application properties.\n"); 162 } 163 164 fclose(file); 165 free(path); 166 } 167 168 169 char* ui_get_property(char *name) { 170 return ucx_map_cstr_get(application_properties, name); 171 } 172 173 void ui_set_property(char *name, char *value) { 174 ucx_map_cstr_put(application_properties, name, value); 175 } 176 177 void ui_set_default_property(char *name, char *value) { 178 char *v = ucx_map_cstr_get(application_properties, name); 179 if(!v) { 180 ucx_map_cstr_put(application_properties, name, value); 181 } 182 } 183 184 185 186 static char* uic_concat_path(const char *base, const char *p, const char *ext) { 187 size_t baselen = strlen(base); 188 189 UcxBuffer *buf = ucx_buffer_new(NULL, 32, UCX_BUFFER_AUTOEXTEND); 190 if(baselen > 0) { 191 ucx_buffer_write(base, 1, baselen, buf); 192 if(base[baselen - 1] != '/') { 193 ucx_buffer_putc(buf, '/'); 194 } 195 } 196 ucx_buffer_write(p, 1, strlen(p), buf); 197 if(ext) { 198 ucx_buffer_write(ext, 1, strlen(ext), buf); 199 } 200 201 char *str = buf->space; 202 free(buf); 203 return str; 204 } 205 206 #ifndef UI_COCOA 207 208 void ui_locales_dir(char *path) { 209 locales_dir = path; 210 } 211 212 void ui_pixmaps_dir(char *path) { 213 pixmaps_dir = path; 214 } 215 216 char* uic_get_image_path(const char *imgfilename) { 217 if(pixmaps_dir) { 218 return uic_concat_path(pixmaps_dir, imgfilename, NULL); 219 } else { 220 return NULL; 221 } 222 } 223 224 void ui_load_lang(char *locale) { 225 if(!locale) { 226 locale = "en_EN"; 227 } 228 229 char *path = uic_concat_path(locales_dir, locale, ".properties"); 230 231 uic_load_language_file(path); 232 free(path); 233 } 234 235 void ui_load_lang_def(char *locale, char *default_locale) { 236 char tmp[6]; 237 if(!locale) { 238 char *lang = getenv("LANG"); 239 if(lang && strlen(lang) >= 5) { 240 memcpy(tmp, lang, 5); 241 tmp[5] = '\0'; 242 locale = tmp; 243 } else { 244 locale = default_locale; 245 } 246 } 247 248 char *path = uic_concat_path(locales_dir, locale, ".properties"); 249 250 if(uic_load_language_file(path)) { 251 if(default_locale) { 252 ui_load_lang_def(default_locale, NULL); 253 } else { 254 // cannot find any language file 255 fprintf(stderr, "Ui Error: Cannot load language.\n"); 256 free(path); 257 exit(-1); 258 } 259 } 260 free(path); 261 } 262 263 #endif 264 265 int uic_load_language_file(const char *path) { 266 UcxMap *lang = ucx_map_new(256); 267 268 FILE *file = fopen(path, "r"); 269 if(!file) { 270 return 1; 271 } 272 273 if(ucx_properties_load(lang, file)) { 274 fprintf(stderr, "Ui Error: Cannot parse language file: %s.\n", path); 275 } 276 277 fclose(file); 278 279 ucx_map_rehash(lang); 280 281 language = lang; 282 283 return 0; 284 } 285 286 char* uistr(char *name) { 287 char *value = uistr_n(name); 288 return value ? value : "missing string"; 289 } 290 291 char* uistr_n(char *name) { 292 if(!language) { 293 return NULL; 294 } 295 return ucx_map_cstr_get(language, name); 296 } 297 298