ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/prefs.cpp
Revision: 1.9
Committed: 2001-01-04T19:50:22Z (23 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.8: +67 -38 lines
Log Message:
- removed the INT16 prefs item type; use INT32 instead
- AmigaOS/Unix: it's now possible to specify preferences items on the
  command line
- Unix: command line options now take "--"-prefix, e.g. "--rominfo"

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * prefs.cpp - Preferences handling
3     *
4 cebix 1.4 * Basilisk II (C) 1997-2000 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.9 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     // Override prefs with command line arguments
60     argc--; argv++;
61     for (; argc>0; argc--, argv++) {
62    
63     // Arguments are of the form '--keyword'
64     if (strlen(*argv) < 3 || argv[0][0] != '-' || argv[0][1] != '-') {
65     printf("WARNING: Unrecognized argument '%s'\n", *argv);
66     continue;
67     }
68     const char *keyword = *argv + 2;
69     const prefs_desc *d = find_prefs_desc(keyword);
70     if (d == NULL) {
71     printf("WARNING: Unrecognized argument '%s'\n", *argv);
72     continue;
73     }
74    
75     // Add/replace prefs item
76     switch (d->type) {
77     case TYPE_STRING:
78     if (argc < 2) {
79     printf("WARNING: Argument '%s' must be followed by value\n", *argv);
80     break;
81     }
82     argc--; argv++;
83     if (d->multiple)
84     PrefsAddString(keyword, *argv);
85     else
86     PrefsReplaceString(keyword, *argv);
87     break;
88    
89     case TYPE_BOOLEAN:
90     if (argc > 1 && argv[1][0] != '-') {
91     argc--; argv++;
92     PrefsReplaceBool(keyword, !strcmp(*argv, "true") || !strcmp(*argv, "on"));
93     } else
94     PrefsReplaceBool(keyword, true);
95     break;
96    
97     case TYPE_INT32:
98     if (argc < 2) {
99     printf("WARNING: Argument '%s' must be followed by value\n", *argv);
100     break;
101     }
102     argc--; argv++;
103     PrefsReplaceInt32(keyword, atoi(*argv));
104     break;
105    
106     default:
107     break;
108     }
109     }
110 cebix 1.1 }
111    
112    
113     /*
114     * Deinitialize preferences
115     */
116    
117     void PrefsExit(void)
118     {
119     // Free prefs list
120     prefs_node *p = the_prefs, *next;
121     while (p) {
122     next = p->next;
123     free((void *)p->name);
124     free(p->data);
125     delete p;
126     p = next;
127     }
128     }
129    
130    
131     /*
132     * Find preferences descriptor by keyword
133     */
134    
135     static const prefs_desc *find_prefs_desc(const char *name, const prefs_desc *list)
136     {
137     while (list->type != TYPE_ANY) {
138     if (strcmp(list->name, name) == 0)
139     return list;
140     list++;
141     }
142     return NULL;
143     }
144    
145 cebix 1.9 static const prefs_desc *find_prefs_desc(const char *name)
146     {
147     const prefs_desc *d = find_prefs_desc(name, common_prefs_items);
148     if (d == NULL)
149     d = find_prefs_desc(name, platform_prefs_items);
150     return d;
151     }
152    
153 cebix 1.1
154     /*
155     * Set prefs items
156     */
157    
158     static void add_data(const char *name, prefs_type type, void *data, int size)
159     {
160     void *d = malloc(size);
161     if (d == NULL)
162     return;
163     memcpy(d, data, size);
164     prefs_node *p = new prefs_node;
165     p->next = 0;
166     p->name = strdup(name);
167     p->type = type;
168     p->data = d;
169     if (the_prefs) {
170     prefs_node *prev = the_prefs;
171     while (prev->next)
172     prev = prev->next;
173     prev->next = p;
174     } else
175     the_prefs = p;
176     }
177    
178     void PrefsAddString(const char *name, const char *s)
179     {
180     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
181     }
182    
183     void PrefsAddBool(const char *name, bool b)
184     {
185     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
186     }
187    
188     void PrefsAddInt32(const char *name, int32 val)
189     {
190     add_data(name, TYPE_INT32, &val, sizeof(int32));
191     }
192    
193    
194     /*
195     * Replace prefs items
196     */
197    
198     static prefs_node *find_node(const char *name, prefs_type type, int index = 0)
199     {
200     prefs_node *p = the_prefs;
201     int i = 0;
202     while (p) {
203     if ((type == TYPE_ANY || p->type == type) && !strcmp(p->name, name)) {
204     if (i == index)
205     return p;
206     else
207     i++;
208     }
209     p = p->next;
210     }
211     return NULL;
212     }
213    
214     void PrefsReplaceString(const char *name, const char *s, int index)
215     {
216     prefs_node *p = find_node(name, TYPE_STRING, index);
217     if (p) {
218     free(p->data);
219     p->data = strdup(s);
220     } else
221     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
222     }
223    
224     void PrefsReplaceBool(const char *name, bool b)
225     {
226     prefs_node *p = find_node(name, TYPE_BOOLEAN);
227     if (p)
228     *(bool *)(p->data) = b;
229     else
230     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
231     }
232    
233     void PrefsReplaceInt32(const char *name, int32 val)
234     {
235     prefs_node *p = find_node(name, TYPE_INT32);
236     if (p)
237     *(int32 *)(p->data) = val;
238     else
239     add_data(name, TYPE_INT32, &val, sizeof(int32));
240     }
241    
242    
243     /*
244     * Get prefs items
245     */
246    
247     const char *PrefsFindString(const char *name, int index)
248     {
249     prefs_node *p = find_node(name, TYPE_STRING, index);
250     if (p)
251     return (char *)(p->data);
252     else
253     return NULL;
254     }
255    
256     bool PrefsFindBool(const char *name)
257     {
258     prefs_node *p = find_node(name, TYPE_BOOLEAN, 0);
259     if (p)
260     return *(bool *)(p->data);
261     else
262     return false;
263     }
264    
265     int32 PrefsFindInt32(const char *name)
266     {
267     prefs_node *p = find_node(name, TYPE_INT32, 0);
268     if (p)
269     return *(int32 *)(p->data);
270     else
271     return 0;
272     }
273    
274    
275     /*
276     * Remove prefs items
277     */
278    
279     void PrefsRemoveItem(const char *name, int index)
280     {
281     prefs_node *p = find_node(name, TYPE_ANY, index);
282     if (p) {
283     free((void *)p->name);
284     free(p->data);
285     prefs_node *q = the_prefs;
286     if (q == p) {
287     the_prefs = NULL;
288     delete p;
289     return;
290     }
291     while (q) {
292     if (q->next == p) {
293     q->next = p->next;
294     delete p;
295     return;
296     }
297     q = q->next;
298     }
299     }
300     }
301    
302    
303     /*
304     * Load prefs from stream (utility function for LoadPrefs() implementation)
305     */
306    
307     void LoadPrefsFromStream(FILE *f)
308     {
309     char line[256];
310     while(fgets(line, 255, f)) {
311     // Read line
312     int len = strlen(line);
313     if (len == 0)
314     continue;
315     line[len-1] = 0;
316    
317     // Comments begin with "#" or ";"
318     if (line[0] == '#' || line[0] == ';')
319     continue;
320    
321     // Terminate string after keyword
322     char *p = line;
323     while (!isspace(*p)) p++;
324     *p++ = 0;
325    
326     // Skip whitespace until value
327     while (isspace(*p)) p++;
328     char *keyword = line;
329     char *value = p;
330     int32 i = atol(value);
331    
332 cebix 1.9 // Look for keyword first in prefs item list
333     const prefs_desc *desc = find_prefs_desc(keyword);
334 cebix 1.1 if (desc == NULL) {
335     printf("WARNING: Unknown preferences keyword '%s'\n", keyword);
336     continue;
337     }
338    
339     // Add item to prefs
340     switch (desc->type) {
341     case TYPE_STRING:
342     if (desc->multiple)
343     PrefsAddString(keyword, value);
344     else
345     PrefsReplaceString(keyword, value);
346     break;
347     case TYPE_BOOLEAN:
348     PrefsReplaceBool(keyword, !strcmp(value, "true"));
349     break;
350     case TYPE_INT32:
351     PrefsReplaceInt32(keyword, i);
352     break;
353     default:
354     break;
355     }
356     }
357     }
358    
359    
360     /*
361     * Save settings to stream (utility function for SavePrefs() implementation)
362     */
363    
364     static void write_prefs(FILE *f, const prefs_desc *list)
365     {
366     while (list->type != TYPE_ANY) {
367     switch (list->type) {
368     case TYPE_STRING: {
369     int index = 0;
370     const char *str;
371     while ((str = PrefsFindString(list->name, index++)) != NULL)
372     fprintf(f, "%s %s\n", list->name, str);
373     break;
374     }
375     case TYPE_BOOLEAN:
376     fprintf(f, "%s %s\n", list->name, PrefsFindBool(list->name) ? "true" : "false");
377     break;
378     case TYPE_INT32:
379 cebix 1.7 fprintf(f, "%s %d\n", list->name, PrefsFindInt32(list->name));
380 cebix 1.1 break;
381     default:
382     break;
383     }
384     list++;
385     }
386     }
387    
388     void SavePrefsToStream(FILE *f)
389     {
390     write_prefs(f, common_prefs_items);
391     write_prefs(f, platform_prefs_items);
392     }