1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 "../ui/toolkit.h"
36
37
38 #include "properties.h"
39 #include <cx/string.h>
40 #include <cx/buffer.h>
41
42 #include <cx/hash_map.h>
43 #include "ucx_properties.h"
44
45 static CxMap *application_properties;
46 static CxMap *language;
47
48 #ifndef UI_COCOA
49
50 static char *locales_dir;
51 static char *pixmaps_dir;
52
53 #endif
54
55
56 char* ui_getappdir(
void) {
57 if(ui_appname() ==
NULL) {
58 return NULL;
59 }
60
61 return ui_configfile(
NULL);
62 }
63
64 #ifndef _WIN32
65 #define UI_PATH_SEPARATOR '/'
66 #define UI_ENV_HOME "HOME"
67 #else
68 #define UI_PATH_SEPARATOR '\\'
69 #define UI_ENV_HOME "USERPROFILE"
70 #endif
71
72 char* ui_configfile(
char *name) {
73 const char *appname = ui_appname();
74 if(!appname) {
75 return NULL;
76 }
77
78 CxBuffer buf;
79 cxBufferInit(&buf,
NULL,
128, cxDefaultAllocator,
CX_BUFFER_FREE_CONTENTS|
CX_BUFFER_AUTO_EXTEND);
80
81
82 char *homeenv = getenv(
UI_ENV_HOME);
83 if(homeenv ==
NULL) {
84 cxBufferDestroy(&buf);
85 return NULL;
86 }
87 cxstring home = cx_str(homeenv);
88
89 cxBufferWrite(home.ptr,
1, home.length, &buf);
90 if(home.ptr[home.length-
1] !=
UI_PATH_SEPARATOR) {
91 cxBufferPut(&buf,
UI_PATH_SEPARATOR);
92 }
93
94 #ifdef UI_COCOA
95
96 cxBufferPutString(&buf,
"Library/Application Support/");
97 #elif defined(
_WIN32)
98
99 cxBufferPutString(&buf,
"AppData\\Local\\");
100 #else
101
102 cxBufferPut(&buf,
'.');
103 #endif
104 cxBufferPutString(&buf, appname);
105 cxBufferPut(&buf,
UI_PATH_SEPARATOR);
106
107
108 if(name) {
109 cxBufferPutString(&buf, name);
110 }
111
112 cxBufferPut(&buf,
0);
113
114 return buf.space;
115 }
116
117 static int ui_mkdir(
char *path) {
118 #ifdef _WIN32
119 return mkdir(path);
120 #else
121 return mkdir(path,
S_IRWXU);
122 #endif
123 }
124
125 void uic_load_app_properties() {
126 application_properties = cxHashMapCreate(cxDefaultAllocator,
CX_STORE_POINTERS,
128);
127
128 if(!ui_appname()) {
129
130 return;
131 }
132
133 char *dir = ui_configfile(
NULL);
134 if(!dir) {
135 return;
136 }
137 if(ui_mkdir(dir)) {
138 if(errno !=
EEXIST) {
139 fprintf(stderr,
"Ui Error: Cannot create directory %s\n", dir);
140 free(dir);
141 return;
142 }
143 }
144 free(dir);
145
146 char *path = ui_configfile(
"application.properties");
147 if(!path) {
148 return;
149 }
150
151 FILE *file = fopen(path,
"r");
152 if(!file) {
153 free(path);
154 return;
155 }
156
157 if(ucx_properties_load(application_properties, file)) {
158 fprintf(stderr,
"Ui Error: Cannot load application properties.\n");
159 }
160
161 fclose(file);
162 free(path);
163 }
164
165 int uic_store_app_properties() {
166 char *path = ui_configfile(
"application.properties");
167 if(!path) {
168 return 1;
169 }
170
171 FILE *file = fopen(path,
"w");
172 if(!file) {
173 fprintf(stderr,
"Ui Error: Cannot open properties file: %s\n", path);
174 free(path);
175 return 1;
176 }
177
178 int ret =
0;
179 if(ucx_properties_store(application_properties, file)) {
180 fprintf(stderr,
"Ui Error: Cannot store application properties.\n");
181 ret =
1;
182 }
183
184 fclose(file);
185 free(path);
186
187 return ret;
188 }
189
190
191 const char* ui_get_property(
const char *name) {
192 return cxMapGet(application_properties, name);
193 }
194
195 void ui_set_property(
const char *name,
const char *value) {
196 cxMapPut(application_properties, name, (
char*)value);
197 }
198
199 const char* ui_set_default_property(
const char *name,
const char *value) {
200 const char *v = cxMapGet(application_properties, name);
201 if(!v) {
202 cxMapPut(application_properties, name, (
char*)value);
203 v = value;
204 }
205 return v;
206 }
207
208 int ui_properties_store(
void) {
209 return uic_store_app_properties();
210 }
211
212
213 static char* uic_concat_path(
const char *base,
const char *p,
const char *ext) {
214 size_t baselen = strlen(base);
215
216 CxBuffer *buf = cxBufferCreate(
NULL,
32, cxDefaultAllocator,
CX_BUFFER_FREE_CONTENTS|
CX_BUFFER_AUTO_EXTEND);
217 if(baselen >
0) {
218 cxBufferWrite(base,
1, baselen, buf);
219 if(base[baselen -
1] !=
'/') {
220 cxBufferPut(buf,
'/');
221 }
222 }
223 cxBufferWrite(p,
1, strlen(p), buf);
224 if(ext) {
225 cxBufferWrite(ext,
1, strlen(ext), buf);
226 }
227
228 char *str = buf->space;
229 free(buf);
230 return str;
231 }
232
233 #ifndef UI_COCOA
234
235 void ui_locales_dir(
char *path) {
236 locales_dir = path;
237 }
238
239 void ui_pixmaps_dir(
char *path) {
240 pixmaps_dir = path;
241 }
242
243 char* uic_get_image_path(
const char *imgfilename) {
244 if(pixmaps_dir) {
245 return uic_concat_path(pixmaps_dir, imgfilename,
NULL);
246 }
else {
247 return NULL;
248 }
249 }
250
251 void ui_load_lang(
char *locale) {
252 if(!locale) {
253 locale =
"en_EN";
254 }
255
256 char *path = uic_concat_path(locales_dir, locale,
".properties");
257
258 uic_load_language_file(path);
259 free(path);
260 }
261
262 void ui_load_lang_def(
char *locale,
char *default_locale) {
263 char tmp[
6];
264 if(!locale) {
265 char *lang = getenv(
"LANG");
266 if(lang && strlen(lang) >=
5) {
267 memcpy(tmp, lang,
5);
268 tmp[
5] =
'\0';
269 locale = tmp;
270 }
else {
271 locale = default_locale;
272 }
273 }
274
275 char *path = uic_concat_path(locales_dir, locale,
".properties");
276
277 if(uic_load_language_file(path)) {
278 if(default_locale) {
279 ui_load_lang_def(default_locale,
NULL);
280 }
else {
281
282 fprintf(stderr,
"Ui Error: Cannot load language.\n");
283 free(path);
284 exit(-
1);
285 }
286 }
287 free(path);
288 }
289
290 #endif
291
292 int uic_load_language_file(
const char *path) {
293 CxMap *lang = cxHashMapCreate(cxDefaultAllocator,
CX_STORE_POINTERS,
256);
294
295 FILE *file = fopen(path,
"r");
296 if(!file) {
297 return 1;
298 }
299
300 if(ucx_properties_load(lang, file)) {
301 fprintf(stderr,
"Ui Error: Cannot parse language file: %s.\n", path);
302 }
303
304 fclose(file);
305
306 cxMapRehash(lang);
307
308 language = lang;
309
310 return 0;
311 }
312
313 char* uistr(
char *name) {
314 char *value = uistr_n(name);
315 return value ? value :
"missing string";
316 }
317
318 char* uistr_n(
char *name) {
319 if(!language) {
320 return NULL;
321 }
322 return cxMapGet(language, name);
323 }
324