| 42 #include "properties.h" |
42 #include "properties.h" |
| 43 #include <cx/string.h> |
43 #include <cx/string.h> |
| 44 #include <cx/buffer.h> |
44 #include <cx/buffer.h> |
| 45 |
45 |
| 46 #include <cx/hash_map.h> |
46 #include <cx/hash_map.h> |
| 47 #include "ucx_properties.h" |
47 #include <cx/properties.h> |
| 48 |
48 |
| 49 static CxMap *application_properties; |
49 static CxMap *application_properties; |
| 50 static CxMap *language; |
50 static CxMap *language; |
| 51 |
51 |
| 52 #ifndef UI_COCOA |
52 #ifndef UI_COCOA |
| 53 |
53 |
| 54 static char *locales_dir; |
54 static char *locales_dir; |
| 55 static char *pixmaps_dir; |
55 static char *pixmaps_dir; |
| 56 |
56 |
| 57 #endif |
57 static UiBool use_xdg_config_home = TRUE; |
| 58 |
58 |
| |
59 #endif |
| |
60 |
| |
61 static UiBool load_on_startup = TRUE; |
| |
62 static void *properties_data = NULL; |
| |
63 static size_t properties_data_length = 0; |
| |
64 |
| |
65 void ui_load_properties_file_on_startup(UiBool enable) { |
| |
66 load_on_startup = enable; |
| |
67 } |
| |
68 |
| |
69 void ui_set_properties_data(const char *str, size_t len) { |
| |
70 if(str && len > 0) { |
| |
71 properties_data = malloc(len); |
| |
72 memcpy(properties_data, str, len); |
| |
73 } else { |
| |
74 properties_data = NULL; |
| |
75 properties_data_length = 0; |
| |
76 } |
| |
77 } |
| 59 |
78 |
| 60 char* ui_getappdir(void) { |
79 char* ui_getappdir(void) { |
| 61 if(ui_appname() == NULL) { |
80 if(ui_appname() == NULL) { |
| 62 return NULL; |
81 return NULL; |
| 63 } |
82 } |
| 100 cxBufferPutString(&buf, "Library/Application Support/"); |
121 cxBufferPutString(&buf, "Library/Application Support/"); |
| 101 #elif defined(_WIN32) |
122 #elif defined(_WIN32) |
| 102 // on Windows the app dir is $USERPROFILE/AppData/Local/$APPNAME/ |
123 // on Windows the app dir is $USERPROFILE/AppData/Local/$APPNAME/ |
| 103 cxBufferPutString(&buf, "AppData\\Local\\"); |
124 cxBufferPutString(&buf, "AppData\\Local\\"); |
| 104 #else |
125 #else |
| 105 // app dir is $HOME/.$APPNAME/ |
126 if(use_xdg_config_home) { |
| 106 cxBufferPut(&buf, '.'); |
127 // app dir is $HOME/.config/$APPNAME/ |
| |
128 char *xdghome = getenv(UI_XDG_CONFIG_HOME_VAR); |
| |
129 size_t xdghomelen = xdghome ? strlen(xdghome) : 0; |
| |
130 if(xdghome && xdghomelen > 0) { |
| |
131 cxBufferSeek(&buf, 0, SEEK_SET); |
| |
132 cxBufferPutString(&buf, xdghome); |
| |
133 if(xdghome[xdghomelen-1] != '/') { |
| |
134 cxBufferPut(&buf, '/'); |
| |
135 } |
| |
136 } else { |
| |
137 cxBufferPutString(&buf, ".config/"); |
| |
138 } |
| |
139 } else { |
| |
140 cxBufferPut(&buf, '.'); |
| |
141 } |
| |
142 |
| 107 #endif |
143 #endif |
| 108 cxBufferPutString(&buf, appname); |
144 cxBufferPutString(&buf, appname); |
| 109 cxBufferPut(&buf, UI_PATH_SEPARATOR); |
145 cxBufferPut(&buf, UI_PATH_SEPARATOR); |
| 110 |
146 |
| 111 // add file name |
147 // add file name |
| 124 #else |
160 #else |
| 125 return mkdir(path, S_IRWXU); |
161 return mkdir(path, S_IRWXU); |
| 126 #endif |
162 #endif |
| 127 } |
163 } |
| 128 |
164 |
| |
165 static int load_properties(FILE *file, CxMap *map) { |
| |
166 CxProperties prop; |
| |
167 cxPropertiesInitDefault(&prop); |
| |
168 char buf[8192]; |
| |
169 size_t r; |
| |
170 CxPropertiesStatus status = CX_PROPERTIES_NO_ERROR; |
| |
171 while((r = fread(buf, 1, 8192, file)) > 0) { |
| |
172 cxPropertiesFilln(&prop, buf, r); |
| |
173 cxstring key; |
| |
174 cxstring value; |
| |
175 while((status = cxPropertiesNext(&prop, &key, &value)) == CX_PROPERTIES_NO_ERROR) { |
| |
176 cxMapPut(map, key, cx_strdup(value).ptr); |
| |
177 } |
| |
178 if(status > CX_PROPERTIES_OK) { |
| |
179 break; |
| |
180 } |
| |
181 } |
| |
182 return status <= CX_PROPERTIES_NO_DATA ? 0 : 1; |
| |
183 } |
| |
184 |
| 129 void uic_load_app_properties() { |
185 void uic_load_app_properties() { |
| 130 application_properties = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 128); |
186 application_properties = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 128); |
| 131 application_properties->collection.simple_destructor = free; |
187 application_properties->collection.simple_destructor = free; |
| 132 |
188 |
| |
189 if(!load_on_startup) { |
| |
190 if(properties_data) { |
| |
191 CxProperties prop; |
| |
192 cxPropertiesInitDefault(&prop); |
| |
193 |
| |
194 CxPropertiesStatus status = CX_PROPERTIES_NO_ERROR; |
| |
195 cxPropertiesFilln(&prop, properties_data, properties_data_length); |
| |
196 |
| |
197 cxstring key; |
| |
198 cxstring value; |
| |
199 while((status = cxPropertiesNext(&prop, &key, &value)) == CX_PROPERTIES_NO_ERROR) { |
| |
200 cxMapPut(application_properties, key, cx_strdup(value).ptr); |
| |
201 } |
| |
202 |
| |
203 if(status > CX_PROPERTIES_NO_DATA) { |
| |
204 fprintf(stderr, "Error: cannot load properties: %d\n", (int)status); |
| |
205 } else { |
| |
206 cxMapRehash(application_properties); |
| |
207 } |
| |
208 } |
| |
209 return; |
| |
210 } |
| |
211 |
| 133 if(!ui_appname()) { |
212 if(!ui_appname()) { |
| 134 // applications without name cannot load app properties |
213 // applications without name cannot load app properties |
| 135 return; |
214 return; |
| 136 } |
215 } |
| 137 |
216 |
| 138 char *dir = ui_configfile(NULL); |
217 char *dir = ui_configfile(NULL); |
| 139 if(!dir) { |
218 if(!dir) { |
| 140 return; |
219 return; |
| 141 } |
220 } |
| |
221 size_t len = strlen(dir); |
| |
222 if(len < 2) { |
| |
223 return; |
| |
224 } |
| 142 if(ui_mkdir(dir)) { |
225 if(ui_mkdir(dir)) { |
| |
226 if(errno == ENOENT) { |
| |
227 char *parent = strdup(dir); |
| |
228 for(int i=len-2;i>=0;i--) { |
| |
229 if(parent[i] == '/') { |
| |
230 parent[i] = 0; |
| |
231 break; |
| |
232 } |
| |
233 } |
| |
234 // try creating the parent |
| |
235 int err = ui_mkdir(parent); |
| |
236 if(err) { |
| |
237 fprintf(stderr, "Error: Cannot create directory %s: %s\n", parent, strerror(errno)); |
| |
238 free(parent); |
| |
239 free(dir); |
| |
240 return; |
| |
241 } |
| |
242 free(parent); |
| |
243 |
| |
244 // try dir again |
| |
245 if(!ui_mkdir(dir)) { |
| |
246 errno = EEXIST; // success |
| |
247 } |
| |
248 } |
| |
249 |
| 143 if(errno != EEXIST) { |
250 if(errno != EEXIST) { |
| 144 fprintf(stderr, "Ui Error: Cannot create directory %s\n", dir); |
251 fprintf(stderr, "Error: Cannot create directory %s: %s\n", dir, strerror(errno)); |
| 145 free(dir); |
252 free(dir); |
| 146 return; |
253 return; |
| 147 } |
254 } |
| 148 } |
255 } |
| 149 free(dir); |
256 free(dir); |