]> icculus.org git repositories - taylor/freespace2.git/blob - src/launcher/launcherini.cpp
Merge branch 'sdl2'
[taylor/freespace2.git] / src / launcher / launcherini.cpp
1
2 /*
3  * Basically the same as osregistry.cpp but without having to be tied into
4  * cfile.
5  *
6  * External function calls should remain identical to what's in core lib so that
7  * the launcher can just include osregistry.h like elsewhere
8  */
9
10
11 #include "pstypes.h"
12 #include "osregistry.h"
13 #include "cfile.h"
14 #include "version.h"
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <ctype.h>
20
21 const char *Osreg_company_name = "Volition";
22 #if defined(MAKE_FS1)
23 const char *Osreg_class_name = "FreeSpaceClass";
24 #else
25 const char *Osreg_class_name = "FreeSpace2Class";
26 #endif
27 #if defined(FS1_DEMO)
28 const char *Osreg_app_name = "FreeSpaceDemo";
29 const char *Osreg_title = "FreeSpace Demo";
30 #define PROFILE_NAME "FreeSpaceDemo.ini"
31 #elif defined(FS2_DEMO)
32 const char *Osreg_app_name = "FreeSpace2Demo";
33 const char *Osreg_title = "FreeSpace 2 Demo";
34 #define PROFILE_NAME "FreeSpace2Demo.ini"
35 #elif defined(OEM_BUILD)
36 const char *Osreg_app_name = "FreeSpace2OEM";
37 const char *Osreg_title = "FreeSpace 2 OEM";
38 #define PROFILE_NAME "FreeSpace2OEM.ini"
39 #elif defined(MAKE_FS1)
40 const char *Osreg_app_name = "FreeSpace";
41 const char *Osreg_title = "FreeSpace";
42 #define PROFILE_NAME "FreeSpace.ini"
43 #else
44 const char *Osreg_app_name = "FreeSpace2";
45 const char *Osreg_title = "FreeSpace 2";
46 #define PROFILE_NAME "FreeSpace2.ini"
47 #endif
48
49 #define DEFAULT_SECTION "Default"
50
51 static int Profile_initted = 0;
52 static char PROFILE_PATH[MAX_PATH_LEN] = { 0 };
53
54
55 typedef struct KeyValue
56 {
57         char *key;
58         char *value;
59         
60         struct KeyValue *next;
61 } KeyValue;
62
63 typedef struct Section
64 {
65         char *name;
66         
67         struct KeyValue *pairs;
68         struct Section *next;
69 } Section;
70         
71 typedef struct Profile
72 {
73         struct Section *sections;
74 } Profile;
75
76 static int profile_init()
77 {
78         if (Profile_initted) {
79                 return 0;
80         }
81
82         char *u_path = SDL_GetPrefPath(Osreg_company_name, Osreg_title);
83
84         // make sure we have something
85         if (u_path == NULL) {
86                 return 1;
87         }
88
89         // size check
90         if ( (strlen(u_path) + strlen(PROFILE_NAME) + 1) >= MAX_PATH_LEN ) {
91                 SDL_free(u_path);
92                 return 1;
93         }
94
95         // set profile location
96         SDL_snprintf(PROFILE_PATH, SDL_arraysize(PROFILE_PATH), "%s%s%s", u_path, DIR_SEPARATOR_STR, PROFILE_NAME);
97
98         // free SDL copy
99         SDL_free(u_path);
100
101         Profile_initted = 1;
102
103         return 0;
104 }
105
106 static char *read_line_from_file(FILE *fp)
107 {
108         char *buf, *buf_start;
109         int buflen, len, eol;
110         
111         buflen = 80;
112         buf = (char *)SDL_malloc(buflen);
113         buf_start = buf;
114         eol = 0;
115         
116         do {
117                 if (buf == NULL) {
118                         return NULL;
119                 }
120                 
121                 if (fgets(buf_start, 80, fp) == NULL) {
122                         if (buf_start == buf) {
123                                 SDL_free(buf);
124                                 return NULL;
125                         } else {
126                                 *buf_start = 0;
127                                 return buf;
128                         }
129                 }
130                 
131                 len = SDL_strlen(buf_start);
132                 
133                 if (buf_start[len-1] == '\n') {
134                         buf_start[len-1] = 0;
135                         eol = 1;
136                 } else {
137                         buflen += 80;
138                         
139                         buf = (char *)SDL_realloc(buf, buflen);
140                         
141                         /* be sure to skip over the proper amount of nulls */
142                         buf_start = buf+(buflen-80)-(buflen/80)+1;
143                 }
144         } while (!eol);
145         
146         return buf;
147 }
148
149 static char *trim_string(char *str)
150 {
151         char *ptr;
152         int len;
153         
154         if (str == NULL)
155                 return NULL;
156         
157         /* kill any comment */
158         ptr = SDL_strchr(str, ';');
159         if (ptr)
160                 *ptr = 0;
161         ptr = SDL_strchr(str, '#');
162         if (ptr)
163                 *ptr = 0;
164         
165         ptr = str;
166         len = SDL_strlen(str);
167         if (len > 0) {
168                 ptr += len-1;
169         }
170         
171         while ((ptr > str) && SDL_isspace(*ptr)) {
172                 ptr--;
173         }
174
175         if (*ptr) {
176                 ptr++;
177                 *ptr = 0;
178         }
179         
180         ptr = str;
181         while (*ptr && SDL_isspace(*ptr)) {
182                 ptr++;
183         }
184         
185         return ptr;
186 }
187
188 static Profile *profile_read()
189 {
190         if ( profile_init() ) {
191                 return NULL;
192         }
193
194         FILE *fp = fopen(PROFILE_PATH, "rt");
195         if (fp == NULL)
196                 return NULL;
197         
198         Profile *profile = (Profile *)SDL_malloc(sizeof(Profile));
199         profile->sections = NULL;
200         
201         Section **sp_ptr = &(profile->sections);
202         Section *sp = NULL;
203
204         KeyValue **kvp_ptr = NULL;
205                 
206         char *str;
207         while ((str = read_line_from_file(fp)) != NULL) {
208                 char *ptr = trim_string(str);
209                 
210                 if (*ptr == '[') {
211                         ptr++;
212                         
213                         char *pend = SDL_strchr(ptr, ']');
214                         if (pend != NULL) {
215                                 // if (pend[1]) { /* trailing garbage! */ }
216                                 
217                                 *pend = 0;                              
218                                 
219                                 if (*ptr) {
220                                         sp = (Section *)SDL_malloc(sizeof(Section));
221                                         sp->next = NULL;
222                                 
223                                         sp->name = SDL_strdup(ptr);
224                                         sp->pairs = NULL;
225                                         
226                                         *sp_ptr = sp;
227                                         sp_ptr = &(sp->next);
228                                         
229                                         kvp_ptr = &(sp->pairs);
230                                 } // else { /* null name! */ }
231                         } // else { /* incomplete section name! */ }
232                 } else {
233                         if (*ptr) {
234                                 char *key = ptr;
235                                 char *value = NULL;
236                                 
237                                 ptr = SDL_strchr(ptr, '=');
238                                 if (ptr != NULL) {
239                                         *ptr = 0;
240                                         ptr++;
241                                         
242                                         value = ptr;
243                                 } // else { /* random garbage! */ }
244                                 
245                                 if (key && *key && value /* && *value */) {
246                                         if (sp != NULL) {
247                                                 KeyValue *kvp = (KeyValue *)SDL_malloc(sizeof(KeyValue));
248                                                 
249                                                 kvp->key = SDL_strdup(key);
250                                                 kvp->value = SDL_strdup(value);
251                                                 
252                                                 kvp->next = NULL;
253                                                 
254                                                 *kvp_ptr = kvp;
255                                                 kvp_ptr = &(kvp->next);
256                                         } // else { /* key/value with no section! */
257                                 } // else { /* malformed key/value entry! */ }
258                         } // else it's just a comment or empty string
259                 }
260                                 
261                 SDL_free(str);
262         }
263         
264         fclose(fp);
265
266         return profile;
267 }
268
269 static void profile_free(Profile *profile)
270 {
271         if (profile == NULL)
272                 return;
273                 
274         Section *sp = profile->sections;
275         while (sp != NULL) {
276                 Section *st = sp;
277                 KeyValue *kvp = sp->pairs;
278                 
279                 while (kvp != NULL) {
280                         KeyValue *kvt = kvp;
281                         
282                         SDL_free(kvp->key);
283                         SDL_free(kvp->value);
284                         
285                         kvp = kvp->next;
286                         SDL_free(kvt);
287                 }
288                 
289                 SDL_free(sp->name);
290                 
291                 sp = sp->next;
292                 SDL_free(st);
293         }
294         
295         SDL_free(profile);
296 }
297
298 static Profile *profile_update(Profile *profile, const char *section, const char *key, const char *value)
299 {
300         if (profile == NULL) {
301                 profile = (Profile *)SDL_malloc(sizeof(Profile));
302                 
303                 profile->sections = NULL;
304         }
305         
306         KeyValue *kvp;
307         
308         Section **sp_ptr = &(profile->sections);
309         Section *sp = profile->sections;
310         while (sp != NULL) {
311                 if (SDL_strcmp(section, sp->name) == 0) {
312                         KeyValue **kvp_ptr = &(sp->pairs);
313                         kvp = sp->pairs;
314                         
315                         while (kvp != NULL) {
316                                 if (SDL_strcmp(key, kvp->key) == 0) {
317                                         SDL_free(kvp->value);
318                                         
319                                         if (value == NULL) {
320                                                 *kvp_ptr = kvp->next;
321                                                 
322                                                 SDL_free(kvp->key);
323                                                 SDL_free(kvp);
324                                         } else {
325                                                 kvp->value = SDL_strdup(value);
326                                         }
327                                         
328                                         /* all done */
329                                         return profile;
330                                 }
331                                 
332                                 kvp_ptr = &(kvp->next);
333                                 kvp = kvp->next;
334                         }
335                         
336                         if (value != NULL) {
337                                 /* key not found */
338                                 kvp = (KeyValue *)SDL_malloc(sizeof(KeyValue));
339                                 kvp->next = NULL;
340                                 kvp->key = SDL_strdup(key);
341                                 kvp->value = SDL_strdup(value);
342                         }
343                                         
344                         *kvp_ptr = kvp;
345                         
346                         /* all done */
347                         return profile;
348                 }
349                 
350                 sp_ptr = &(sp->next);
351                 sp = sp->next;
352         }
353         
354         /* section not found */
355         sp = (Section *)SDL_malloc(sizeof(Section));
356         sp->next = NULL;
357         sp->name = SDL_strdup(section);
358         
359         kvp = (KeyValue *)SDL_malloc(sizeof(KeyValue));
360         kvp->next = NULL;
361         kvp->key = SDL_strdup(key);
362         kvp->value = SDL_strdup(value);
363         
364         sp->pairs = kvp;
365         
366         *sp_ptr = sp;
367         
368         return profile;
369 }
370
371 static const char *profile_get_value(Profile *profile, const char *section, const char *key)
372 {
373         if (profile == NULL)
374                 return NULL;
375         
376         Section *sp = profile->sections;
377         while (sp != NULL) {
378                 if (SDL_strcmp(section, sp->name) == 0) {
379                         KeyValue *kvp = sp->pairs;
380                 
381                         while (kvp != NULL) {
382                                 if (SDL_strcmp(key, kvp->key) == 0) {
383                                         return kvp->value;
384                                 }
385                                 kvp = kvp->next;
386                         }
387                 }
388                 
389                 sp = sp->next;
390         }
391         
392         /* not found */
393         return NULL;
394 }
395
396 static char tmp_string_data[1024];
397
398 static void profile_save(Profile *profile)
399 {
400         FILE *fp;
401
402         if (profile == NULL)
403                 return;
404
405         if ( profile_init() ) {
406                 return;
407         }
408
409         fp = fopen(PROFILE_PATH, "wt");
410         if (fp == NULL)
411                 return;
412         
413         Section *sp = profile->sections;
414         while (sp != NULL) {
415                 SDL_snprintf(tmp_string_data, SDL_arraysize(tmp_string_data), "[%s]\n", sp->name);
416                 fputs(tmp_string_data, fp);
417                 
418                 KeyValue *kvp = sp->pairs;
419                 while (kvp != NULL) {
420                         SDL_snprintf(tmp_string_data, SDL_arraysize(tmp_string_data), "%s=%s\n", kvp->key, kvp->value);
421                         fputs(tmp_string_data, fp);
422                         kvp = kvp->next;
423                 }
424                 
425                 fputc('\n', fp);
426
427                 sp = sp->next;
428         }
429         
430         fclose(fp);
431 }
432
433 const char *os_config_read_string(const char *section, const char *name, const char *default_value)
434 {
435         Profile *p = profile_read();
436
437         if (section == NULL)
438                 section = DEFAULT_SECTION;
439                 
440         const char *ptr = profile_get_value(p, section, name);
441         if ( (ptr != NULL) && SDL_strlen(ptr) ) {
442                 SDL_strlcpy(tmp_string_data, ptr, SDL_arraysize(tmp_string_data));
443                 default_value = tmp_string_data;
444         }
445         
446         profile_free(p);
447         
448         return default_value;
449 }
450
451 unsigned int os_config_read_uint(const char *section, const char *name, unsigned int default_value)
452 {
453         Profile *p = profile_read();
454         
455         if (section == NULL)
456                 section = DEFAULT_SECTION;
457                 
458         const char *ptr = profile_get_value(p, section, name);
459         if ( (ptr != NULL) && SDL_strlen(ptr) ) {
460                 default_value = SDL_atoi(ptr);
461         }
462         
463         profile_free(p);
464         
465         return default_value;
466 }
467
468 void os_config_write_string(const char *section, const char *name, const char *value)
469 {
470         Profile *p = profile_read();
471         
472         if (section == NULL)
473                 section = DEFAULT_SECTION;
474                 
475         p = profile_update(p, section, name, value);
476         profile_save(p);
477         profile_free(p);        
478 }
479
480 void os_config_write_uint(const char *section, const char *name, unsigned int value)
481 {
482         static char buf[21];
483         
484         SDL_snprintf(buf, SDL_arraysize(buf), "%u", value);
485         
486         Profile *p = profile_read();
487
488         if (section == NULL)
489                 section = DEFAULT_SECTION;
490         
491         p = profile_update(p, section, name, buf);
492         profile_save(p);
493         profile_free(p);
494 }