ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/prefs.cpp
Revision: 1.14
Committed: 2004-01-12T15:29:22Z (20 years, 10 months ago) by cebix
Branch: MAIN
CVS Tags: nigel-build-16, nigel-build-15
Changes since 1.13: +1 -1 lines
Log Message:
Happy New Year! :)

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * prefs.cpp - Preferences handling
3     *
4 cebix 1.14 * Basilisk II (C) 1997-2004 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 cebix 1.1 }
125    
126    
127     /*
128     * Deinitialize preferences
129     */
130    
131     void PrefsExit(void)
132     {
133     // Free prefs list
134     prefs_node *p = the_prefs, *next;
135     while (p) {
136     next = p->next;
137     free((void *)p->name);
138     free(p->data);
139     delete p;
140     p = next;
141     }
142 cebix 1.12 the_prefs = NULL;
143 cebix 1.11 }
144    
145    
146     /*
147     * Print preferences options help
148     */
149    
150     static void print_options(const prefs_desc *list)
151     {
152     while (list->type != TYPE_END) {
153     if (list->help) {
154     const char *typestr, *defstr;
155     char numstr[32];
156     switch (list->type) {
157     case TYPE_STRING:
158     typestr = "STRING";
159     defstr = PrefsFindString(list->name);
160     if (defstr == NULL)
161     defstr = "none";
162     break;
163     case TYPE_BOOLEAN:
164     typestr = "BOOL";
165     if (PrefsFindBool(list->name))
166     defstr = "true";
167     else
168     defstr = "false";
169     break;
170     case TYPE_INT32:
171     typestr = "NUMBER";
172     sprintf(numstr, "%d", PrefsFindInt32(list->name));
173     defstr = numstr;
174     break;
175     default:
176     typestr = "<unknown>";
177     defstr = "none";
178     break;
179     }
180     printf(" --%s %s\n %s [default=%s]\n", list->name, typestr, list->help, defstr);
181     }
182     list++;
183     }
184     }
185    
186     void PrefsPrintUsage(void)
187     {
188     printf("\nGeneral options:\n");
189     print_options(common_prefs_items);
190     printf("\nPlatform-specific options:\n");
191     print_options(platform_prefs_items);
192     printf("\nBoolean options are specified as '--OPTION true|on|yes' or\n'--OPTION false|off|no'.\n");
193 cebix 1.1 }
194    
195    
196     /*
197     * Find preferences descriptor by keyword
198     */
199    
200     static const prefs_desc *find_prefs_desc(const char *name, const prefs_desc *list)
201     {
202     while (list->type != TYPE_ANY) {
203     if (strcmp(list->name, name) == 0)
204     return list;
205     list++;
206     }
207     return NULL;
208     }
209    
210 cebix 1.9 static const prefs_desc *find_prefs_desc(const char *name)
211     {
212     const prefs_desc *d = find_prefs_desc(name, common_prefs_items);
213     if (d == NULL)
214     d = find_prefs_desc(name, platform_prefs_items);
215     return d;
216     }
217    
218 cebix 1.1
219     /*
220     * Set prefs items
221     */
222    
223     static void add_data(const char *name, prefs_type type, void *data, int size)
224     {
225     void *d = malloc(size);
226     if (d == NULL)
227     return;
228     memcpy(d, data, size);
229     prefs_node *p = new prefs_node;
230     p->next = 0;
231     p->name = strdup(name);
232     p->type = type;
233     p->data = d;
234     if (the_prefs) {
235     prefs_node *prev = the_prefs;
236     while (prev->next)
237     prev = prev->next;
238     prev->next = p;
239     } else
240     the_prefs = p;
241     }
242    
243     void PrefsAddString(const char *name, const char *s)
244     {
245     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
246     }
247    
248     void PrefsAddBool(const char *name, bool b)
249     {
250     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
251     }
252    
253     void PrefsAddInt32(const char *name, int32 val)
254     {
255     add_data(name, TYPE_INT32, &val, sizeof(int32));
256     }
257    
258    
259     /*
260     * Replace prefs items
261     */
262    
263     static prefs_node *find_node(const char *name, prefs_type type, int index = 0)
264     {
265     prefs_node *p = the_prefs;
266     int i = 0;
267     while (p) {
268     if ((type == TYPE_ANY || p->type == type) && !strcmp(p->name, name)) {
269     if (i == index)
270     return p;
271     else
272     i++;
273     }
274     p = p->next;
275     }
276     return NULL;
277     }
278    
279     void PrefsReplaceString(const char *name, const char *s, int index)
280     {
281     prefs_node *p = find_node(name, TYPE_STRING, index);
282     if (p) {
283     free(p->data);
284     p->data = strdup(s);
285     } else
286     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
287     }
288    
289     void PrefsReplaceBool(const char *name, bool b)
290     {
291     prefs_node *p = find_node(name, TYPE_BOOLEAN);
292     if (p)
293     *(bool *)(p->data) = b;
294     else
295     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
296     }
297    
298     void PrefsReplaceInt32(const char *name, int32 val)
299     {
300     prefs_node *p = find_node(name, TYPE_INT32);
301     if (p)
302     *(int32 *)(p->data) = val;
303     else
304     add_data(name, TYPE_INT32, &val, sizeof(int32));
305     }
306    
307    
308     /*
309     * Get prefs items
310     */
311    
312     const char *PrefsFindString(const char *name, int index)
313     {
314     prefs_node *p = find_node(name, TYPE_STRING, index);
315     if (p)
316     return (char *)(p->data);
317     else
318     return NULL;
319     }
320    
321     bool PrefsFindBool(const char *name)
322     {
323     prefs_node *p = find_node(name, TYPE_BOOLEAN, 0);
324     if (p)
325     return *(bool *)(p->data);
326     else
327     return false;
328     }
329    
330     int32 PrefsFindInt32(const char *name)
331     {
332     prefs_node *p = find_node(name, TYPE_INT32, 0);
333     if (p)
334     return *(int32 *)(p->data);
335     else
336     return 0;
337     }
338    
339    
340     /*
341     * Remove prefs items
342     */
343    
344     void PrefsRemoveItem(const char *name, int index)
345     {
346     prefs_node *p = find_node(name, TYPE_ANY, index);
347     if (p) {
348     free((void *)p->name);
349     free(p->data);
350     prefs_node *q = the_prefs;
351     if (q == p) {
352     the_prefs = NULL;
353     delete p;
354     return;
355     }
356     while (q) {
357     if (q->next == p) {
358     q->next = p->next;
359     delete p;
360     return;
361     }
362     q = q->next;
363     }
364     }
365     }
366    
367    
368     /*
369     * Load prefs from stream (utility function for LoadPrefs() implementation)
370     */
371    
372     void LoadPrefsFromStream(FILE *f)
373     {
374     char line[256];
375     while(fgets(line, 255, f)) {
376     // Read line
377     int len = strlen(line);
378     if (len == 0)
379     continue;
380     line[len-1] = 0;
381    
382     // Comments begin with "#" or ";"
383     if (line[0] == '#' || line[0] == ';')
384     continue;
385    
386     // Terminate string after keyword
387     char *p = line;
388     while (!isspace(*p)) p++;
389     *p++ = 0;
390    
391     // Skip whitespace until value
392     while (isspace(*p)) p++;
393     char *keyword = line;
394     char *value = p;
395     int32 i = atol(value);
396    
397 cebix 1.9 // Look for keyword first in prefs item list
398     const prefs_desc *desc = find_prefs_desc(keyword);
399 cebix 1.1 if (desc == NULL) {
400     printf("WARNING: Unknown preferences keyword '%s'\n", keyword);
401     continue;
402     }
403    
404     // Add item to prefs
405     switch (desc->type) {
406     case TYPE_STRING:
407     if (desc->multiple)
408     PrefsAddString(keyword, value);
409     else
410     PrefsReplaceString(keyword, value);
411     break;
412     case TYPE_BOOLEAN:
413     PrefsReplaceBool(keyword, !strcmp(value, "true"));
414     break;
415     case TYPE_INT32:
416     PrefsReplaceInt32(keyword, i);
417     break;
418     default:
419     break;
420     }
421     }
422     }
423    
424    
425     /*
426     * Save settings to stream (utility function for SavePrefs() implementation)
427     */
428    
429     static void write_prefs(FILE *f, const prefs_desc *list)
430     {
431     while (list->type != TYPE_ANY) {
432     switch (list->type) {
433     case TYPE_STRING: {
434     int index = 0;
435     const char *str;
436     while ((str = PrefsFindString(list->name, index++)) != NULL)
437     fprintf(f, "%s %s\n", list->name, str);
438     break;
439     }
440     case TYPE_BOOLEAN:
441     fprintf(f, "%s %s\n", list->name, PrefsFindBool(list->name) ? "true" : "false");
442     break;
443     case TYPE_INT32:
444 cebix 1.7 fprintf(f, "%s %d\n", list->name, PrefsFindInt32(list->name));
445 cebix 1.1 break;
446     default:
447     break;
448     }
449     list++;
450     }
451     }
452    
453     void SavePrefsToStream(FILE *f)
454     {
455     write_prefs(f, common_prefs_items);
456     write_prefs(f, platform_prefs_items);
457     }