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