ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/prefs.cpp
Revision: 1.17
Committed: 2008-01-01T09:40:31Z (16 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.16: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * prefs.cpp - Preferences handling
3     *
4 gbeauche 1.17 * Basilisk II (C) 1997-2008 Christian Bauer
5 cebix 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include <string.h>
22     #include <stdlib.h>
23     #include <stdio.h>
24     #include <ctype.h>
25    
26     #include "sysdeps.h"
27     #include "sys.h"
28     #include "prefs.h"
29    
30    
31 cebix 1.8 // Prefs items are stored in a linked list of these nodes
32 cebix 1.1 struct prefs_node {
33     prefs_node *next;
34     const char *name;
35     prefs_type type;
36     void *data;
37     };
38    
39     // List of prefs nodes
40 cebix 1.9 static prefs_node *the_prefs = NULL;
41    
42     // Prototypes
43     static const prefs_desc *find_prefs_desc(const char *name);
44 cebix 1.1
45    
46     /*
47     * Initialize preferences
48     */
49    
50 cebix 1.11 void PrefsInit(int &argc, char **&argv)
51 cebix 1.1 {
52     // Set defaults
53 cebix 1.8 AddPrefsDefaults();
54 cebix 1.1 AddPlatformPrefsDefaults();
55    
56     // Load preferences from settings file
57     LoadPrefs();
58 cebix 1.9
59 cebix 1.11 // Override prefs with command line options
60     for (int i=1; i<argc; i++) {
61    
62     // Options are of the form '--keyword'
63     const char *option = argv[i];
64     if (strlen(option) < 3 || option[0] != '-' || option[1] != '-')
65 cebix 1.9 continue;
66 cebix 1.11 const char *keyword = option + 2;
67    
68     // Find descriptor for keyword
69 cebix 1.9 const prefs_desc *d = find_prefs_desc(keyword);
70 cebix 1.11 if (d == NULL)
71     continue;
72     argv[i] = NULL;
73    
74     // Get value
75     i++;
76     if (i >= argc) {
77     fprintf(stderr, "Option '%s' must be followed by a value\n", option);
78 cebix 1.9 continue;
79     }
80 cebix 1.11 const char *value = argv[i];
81     argv[i] = NULL;
82 cebix 1.9
83     // Add/replace prefs item
84     switch (d->type) {
85     case TYPE_STRING:
86     if (d->multiple)
87 cebix 1.11 PrefsAddString(keyword, value);
88 cebix 1.9 else
89 cebix 1.11 PrefsReplaceString(keyword, value);
90 cebix 1.9 break;
91    
92 cebix 1.11 case TYPE_BOOLEAN: {
93     if (!strcmp(value, "true") || !strcmp(value, "on") || !strcmp(value, "yes"))
94 cebix 1.9 PrefsReplaceBool(keyword, true);
95 cebix 1.11 else if (!strcmp(value, "false") || !strcmp(value, "off") || !strcmp(value, "no"))
96     PrefsReplaceBool(keyword, false);
97     else
98     fprintf(stderr, "Value for option '%s' must be 'true' or 'false'\n", option);
99 cebix 1.9 break;
100 cebix 1.11 }
101 cebix 1.9
102     case TYPE_INT32:
103 cebix 1.11 PrefsReplaceInt32(keyword, atoi(value));
104 cebix 1.9 break;
105    
106     default:
107     break;
108     }
109     }
110 cebix 1.11
111     // Remove processed arguments
112     for (int i=1; i<argc; i++) {
113     int k;
114     for (k=i; k<argc; k++)
115     if (argv[k] != NULL)
116     break;
117     if (k > i) {
118     k -= i;
119     for (int j=i+k; j<argc; j++)
120     argv[j-k] = argv[j];
121     argc -= k;
122     }
123     }
124 asvitkine 1.16
125     #ifdef SHEEPSHAVER
126     // System specific initialization
127     prefs_init();
128     #endif
129 cebix 1.1 }
130    
131    
132     /*
133     * Deinitialize preferences
134     */
135    
136     void PrefsExit(void)
137     {
138 asvitkine 1.16 #ifdef SHEEPSHAVER
139     // System specific deinitialization
140     prefs_exit();
141     #endif
142    
143 cebix 1.1 // Free prefs list
144     prefs_node *p = the_prefs, *next;
145     while (p) {
146     next = p->next;
147     free((void *)p->name);
148     free(p->data);
149     delete p;
150     p = next;
151     }
152 cebix 1.12 the_prefs = NULL;
153 cebix 1.11 }
154    
155    
156     /*
157     * Print preferences options help
158     */
159    
160     static void print_options(const prefs_desc *list)
161     {
162     while (list->type != TYPE_END) {
163     if (list->help) {
164     const char *typestr, *defstr;
165     char numstr[32];
166     switch (list->type) {
167     case TYPE_STRING:
168     typestr = "STRING";
169     defstr = PrefsFindString(list->name);
170     if (defstr == NULL)
171     defstr = "none";
172     break;
173     case TYPE_BOOLEAN:
174     typestr = "BOOL";
175     if (PrefsFindBool(list->name))
176     defstr = "true";
177     else
178     defstr = "false";
179     break;
180     case TYPE_INT32:
181     typestr = "NUMBER";
182     sprintf(numstr, "%d", PrefsFindInt32(list->name));
183     defstr = numstr;
184     break;
185     default:
186     typestr = "<unknown>";
187     defstr = "none";
188     break;
189     }
190     printf(" --%s %s\n %s [default=%s]\n", list->name, typestr, list->help, defstr);
191     }
192     list++;
193     }
194     }
195    
196     void PrefsPrintUsage(void)
197     {
198     printf("\nGeneral options:\n");
199     print_options(common_prefs_items);
200     printf("\nPlatform-specific options:\n");
201     print_options(platform_prefs_items);
202     printf("\nBoolean options are specified as '--OPTION true|on|yes' or\n'--OPTION false|off|no'.\n");
203 cebix 1.1 }
204    
205    
206     /*
207     * Find preferences descriptor by keyword
208     */
209    
210     static const prefs_desc *find_prefs_desc(const char *name, const prefs_desc *list)
211     {
212     while (list->type != TYPE_ANY) {
213     if (strcmp(list->name, name) == 0)
214     return list;
215     list++;
216     }
217     return NULL;
218     }
219    
220 cebix 1.9 static const prefs_desc *find_prefs_desc(const char *name)
221     {
222     const prefs_desc *d = find_prefs_desc(name, common_prefs_items);
223     if (d == NULL)
224     d = find_prefs_desc(name, platform_prefs_items);
225     return d;
226     }
227    
228 cebix 1.1
229     /*
230     * Set prefs items
231     */
232    
233     static void add_data(const char *name, prefs_type type, void *data, int size)
234     {
235     void *d = malloc(size);
236     if (d == NULL)
237     return;
238     memcpy(d, data, size);
239     prefs_node *p = new prefs_node;
240     p->next = 0;
241     p->name = strdup(name);
242     p->type = type;
243     p->data = d;
244     if (the_prefs) {
245     prefs_node *prev = the_prefs;
246     while (prev->next)
247     prev = prev->next;
248     prev->next = p;
249     } else
250     the_prefs = p;
251     }
252    
253     void PrefsAddString(const char *name, const char *s)
254     {
255     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
256     }
257    
258     void PrefsAddBool(const char *name, bool b)
259     {
260     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
261     }
262    
263     void PrefsAddInt32(const char *name, int32 val)
264     {
265     add_data(name, TYPE_INT32, &val, sizeof(int32));
266     }
267    
268    
269     /*
270     * Replace prefs items
271     */
272    
273     static prefs_node *find_node(const char *name, prefs_type type, int index = 0)
274     {
275     prefs_node *p = the_prefs;
276     int i = 0;
277     while (p) {
278     if ((type == TYPE_ANY || p->type == type) && !strcmp(p->name, name)) {
279     if (i == index)
280     return p;
281     else
282     i++;
283     }
284     p = p->next;
285     }
286     return NULL;
287     }
288    
289     void PrefsReplaceString(const char *name, const char *s, int index)
290     {
291     prefs_node *p = find_node(name, TYPE_STRING, index);
292     if (p) {
293     free(p->data);
294     p->data = strdup(s);
295     } else
296     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
297     }
298    
299     void PrefsReplaceBool(const char *name, bool b)
300     {
301     prefs_node *p = find_node(name, TYPE_BOOLEAN);
302     if (p)
303     *(bool *)(p->data) = b;
304     else
305     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
306     }
307    
308     void PrefsReplaceInt32(const char *name, int32 val)
309     {
310     prefs_node *p = find_node(name, TYPE_INT32);
311     if (p)
312     *(int32 *)(p->data) = val;
313     else
314     add_data(name, TYPE_INT32, &val, sizeof(int32));
315     }
316    
317    
318     /*
319     * Get prefs items
320     */
321    
322     const char *PrefsFindString(const char *name, int index)
323     {
324     prefs_node *p = find_node(name, TYPE_STRING, index);
325     if (p)
326     return (char *)(p->data);
327     else
328     return NULL;
329     }
330    
331     bool PrefsFindBool(const char *name)
332     {
333     prefs_node *p = find_node(name, TYPE_BOOLEAN, 0);
334     if (p)
335     return *(bool *)(p->data);
336     else
337     return false;
338     }
339    
340     int32 PrefsFindInt32(const char *name)
341     {
342     prefs_node *p = find_node(name, TYPE_INT32, 0);
343     if (p)
344     return *(int32 *)(p->data);
345     else
346     return 0;
347     }
348    
349    
350     /*
351     * Remove prefs items
352     */
353    
354     void PrefsRemoveItem(const char *name, int index)
355     {
356     prefs_node *p = find_node(name, TYPE_ANY, index);
357     if (p) {
358     free((void *)p->name);
359     free(p->data);
360     prefs_node *q = the_prefs;
361     if (q == p) {
362     the_prefs = NULL;
363     delete p;
364     return;
365     }
366     while (q) {
367     if (q->next == p) {
368     q->next = p->next;
369     delete p;
370     return;
371     }
372     q = q->next;
373     }
374     }
375     }
376    
377    
378     /*
379     * Load prefs from stream (utility function for LoadPrefs() implementation)
380     */
381    
382     void LoadPrefsFromStream(FILE *f)
383     {
384     char line[256];
385     while(fgets(line, 255, f)) {
386     // Read line
387     int len = strlen(line);
388     if (len == 0)
389     continue;
390     line[len-1] = 0;
391    
392     // Comments begin with "#" or ";"
393     if (line[0] == '#' || line[0] == ';')
394     continue;
395    
396     // Terminate string after keyword
397     char *p = line;
398     while (!isspace(*p)) p++;
399     *p++ = 0;
400    
401     // Skip whitespace until value
402     while (isspace(*p)) p++;
403     char *keyword = line;
404     char *value = p;
405     int32 i = atol(value);
406    
407 cebix 1.9 // Look for keyword first in prefs item list
408     const prefs_desc *desc = find_prefs_desc(keyword);
409 cebix 1.1 if (desc == NULL) {
410     printf("WARNING: Unknown preferences keyword '%s'\n", keyword);
411     continue;
412     }
413    
414     // Add item to prefs
415     switch (desc->type) {
416     case TYPE_STRING:
417     if (desc->multiple)
418     PrefsAddString(keyword, value);
419     else
420     PrefsReplaceString(keyword, value);
421     break;
422     case TYPE_BOOLEAN:
423     PrefsReplaceBool(keyword, !strcmp(value, "true"));
424     break;
425     case TYPE_INT32:
426     PrefsReplaceInt32(keyword, i);
427     break;
428     default:
429     break;
430     }
431     }
432     }
433    
434    
435     /*
436     * Save settings to stream (utility function for SavePrefs() implementation)
437     */
438    
439     static void write_prefs(FILE *f, const prefs_desc *list)
440     {
441     while (list->type != TYPE_ANY) {
442     switch (list->type) {
443     case TYPE_STRING: {
444     int index = 0;
445     const char *str;
446     while ((str = PrefsFindString(list->name, index++)) != NULL)
447     fprintf(f, "%s %s\n", list->name, str);
448     break;
449     }
450     case TYPE_BOOLEAN:
451     fprintf(f, "%s %s\n", list->name, PrefsFindBool(list->name) ? "true" : "false");
452     break;
453     case TYPE_INT32:
454 cebix 1.7 fprintf(f, "%s %d\n", list->name, PrefsFindInt32(list->name));
455 cebix 1.1 break;
456     default:
457     break;
458     }
459     list++;
460     }
461     }
462    
463     void SavePrefsToStream(FILE *f)
464     {
465     write_prefs(f, common_prefs_items);
466     write_prefs(f, platform_prefs_items);
467     }