ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SIDPlayer/src/prefs.cpp
Revision: 1.5
Committed: 2001-04-01T12:13:49Z (23 years, 7 months ago) by cebix
Branch: MAIN
Changes since 1.4: +42 -48 lines
Log Message:
- PrefsInit() removes processed options
- changes to command line argument handling

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * prefs.cpp - Preferences handling
3     *
4 cebix 1.4 * SIDPlayer (C) Copyright 1996-2001 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 "sys.h"
22    
23     #include <string.h>
24     #include <stdlib.h>
25     #include <stdio.h>
26     #include <ctype.h>
27    
28     #include "prefs.h"
29    
30    
31 cebix 1.2 // 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     prefs_desc *desc;
38     };
39    
40     // List of prefs nodes
41 cebix 1.2 static prefs_node *the_prefs = NULL;
42    
43     // Prototypes
44     static prefs_desc *find_prefs_desc(const char *name);
45 cebix 1.1
46    
47     /*
48     * Initialize preferences
49     */
50    
51 cebix 1.5 void PrefsInit(int &argc, char **&argv)
52 cebix 1.1 {
53 cebix 1.2 // Set defaults
54     AddPrefsDefaults();
55    
56 cebix 1.5 // Override prefs with command line options
57     for (int i=1; i<argc; i++) {
58 cebix 1.2
59 cebix 1.5 // Options are of the form '--keyword'
60     const char *option = argv[i];
61     if (strlen(option) < 3 || option[0] != '-' || option[1] != '-')
62 cebix 1.2 continue;
63 cebix 1.5 const char *keyword = option + 2;
64 cebix 1.3
65     // Find descriptor for keyword
66 cebix 1.2 const prefs_desc *d = find_prefs_desc(keyword);
67 cebix 1.5 if (d == NULL)
68     continue;
69     argv[i] = NULL;
70    
71     // Get value
72     i++;
73     if (i >= argc) {
74     fprintf(stderr, "Option '%s' must be followed by a value\n", option);
75     continue;
76 cebix 1.2 }
77 cebix 1.5 const char *value = argv[i];
78     argv[i] = NULL;
79 cebix 1.1
80 cebix 1.2 // Add/replace prefs item
81     switch (d->type) {
82     case TYPE_STRING:
83     if (d->multiple)
84 cebix 1.5 PrefsAddString(keyword, value);
85 cebix 1.2 else
86 cebix 1.5 PrefsReplaceString(keyword, value);
87 cebix 1.2 break;
88    
89 cebix 1.3 case TYPE_BOOLEAN: {
90 cebix 1.5 if (!strcmp(value, "true") || !strcmp(value, "on") || !strcmp(value, "yes"))
91     PrefsReplaceBool(keyword, true);
92     else if (!strcmp(value, "false") || !strcmp(value, "off") || !strcmp(value, "no"))
93     PrefsReplaceBool(keyword, false);
94     else
95     fprintf(stderr, "Value for option '%s' must be 'true' or 'false'\n", option);
96 cebix 1.2 break;
97 cebix 1.3 }
98 cebix 1.2
99     case TYPE_INT32:
100 cebix 1.5 PrefsReplaceInt32(keyword, atoi(value));
101 cebix 1.2 break;
102    
103     default:
104     break;
105     }
106     }
107 cebix 1.5
108     // Remove processed arguments
109     for (int i=1; i<argc; i++) {
110     int k;
111     for (k=i; k<argc; k++)
112     if (argv[k] != NULL)
113     break;
114     if (k > i) {
115     k -= i;
116     for (int j=i+k; j<argc; j++)
117     argv[j-k] = argv[j];
118     argc -= k;
119     }
120     }
121 cebix 1.1 }
122    
123    
124     /*
125     * Deinitialize preferences
126     */
127    
128     void PrefsExit(void)
129     {
130     // Free prefs list
131     prefs_node *p = the_prefs, *next;
132     while (p) {
133     next = p->next;
134     free((void *)p->name);
135     free(p->data);
136     delete p;
137     p = next;
138     }
139     }
140    
141    
142     /*
143 cebix 1.3 * Print preferences options help
144     */
145    
146     static void print_options(const prefs_desc *list)
147     {
148     while (list->type != TYPE_END) {
149     if (list->help) {
150     const char *typestr, *defstr;
151     char numstr[32];
152     switch (list->type) {
153     case TYPE_STRING:
154     typestr = "STRING";
155     defstr = PrefsFindString(list->name);
156     if (defstr == NULL)
157     defstr = "none";
158     break;
159     case TYPE_BOOLEAN:
160     typestr = "BOOL";
161     if (PrefsFindBool(list->name))
162     defstr = "true";
163     else
164     defstr = "false";
165     break;
166     case TYPE_INT32:
167     typestr = "NUMBER";
168     sprintf(numstr, "%d", PrefsFindInt32(list->name));
169     defstr = numstr;
170     break;
171     default:
172     typestr = "<unknown>";
173     defstr = "none";
174     break;
175     }
176     printf(" --%s %s\n %s [default=%s]\n", list->name, typestr, list->help, defstr);
177     }
178     list++;
179     }
180     }
181    
182     void PrefsPrintUsage(void)
183     {
184     printf("\nGeneral options:\n");
185     print_options(common_prefs_items);
186 cebix 1.5 printf("\nBoolean options are specified as '--OPTION true|on|yes' or\n'--OPTION false|off|no'.\n");
187 cebix 1.3 }
188    
189    
190     /*
191 cebix 1.1 * Find preferences descriptor by keyword
192     */
193    
194     static prefs_desc *find_prefs_desc(const char *name, prefs_desc *list)
195     {
196 cebix 1.3 while (list->type != TYPE_END) {
197 cebix 1.1 if (strcmp(list->name, name) == 0)
198     return list;
199     list++;
200     }
201     return NULL;
202     }
203    
204 cebix 1.2 static prefs_desc *find_prefs_desc(const char *name)
205     {
206     return find_prefs_desc(name, common_prefs_items);
207     }
208    
209 cebix 1.1
210     /*
211     * Set prefs items
212     */
213    
214     static void add_data(const char *name, prefs_type type, void *data, int size)
215     {
216     void *d = malloc(size);
217     if (d == NULL)
218     return;
219     memcpy(d, data, size);
220     prefs_node *p = new prefs_node;
221     p->next = 0;
222     p->name = strdup(name);
223     p->type = type;
224     p->data = d;
225 cebix 1.2 p->desc = find_prefs_desc(p->name);
226 cebix 1.1 if (the_prefs) {
227     prefs_node *prev = the_prefs;
228     while (prev->next)
229     prev = prev->next;
230     prev->next = p;
231     } else
232     the_prefs = p;
233     }
234    
235     void PrefsAddString(const char *name, const char *s)
236     {
237     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
238     }
239    
240     void PrefsAddBool(const char *name, bool b)
241     {
242     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
243     }
244    
245     void PrefsAddInt32(const char *name, int32 val)
246     {
247     add_data(name, TYPE_INT32, &val, sizeof(int32));
248     }
249    
250    
251     /*
252     * Replace prefs items
253     */
254    
255     static prefs_node *find_node(const char *name, prefs_type type, int index = 0)
256     {
257     prefs_node *p = the_prefs;
258     int i = 0;
259     while (p) {
260     if ((type == TYPE_ANY || p->type == type) && !strcmp(p->name, name)) {
261     if (i == index)
262     return p;
263     else
264     i++;
265     }
266     p = p->next;
267     }
268     return NULL;
269     }
270    
271     void PrefsReplaceString(const char *name, const char *s, int index)
272     {
273     prefs_node *p = find_node(name, TYPE_STRING, index);
274     if (p) {
275     if (p->desc && p->desc->func)
276     ((prefs_func_string)(p->desc->func))(name, (const char *)p->data, s);
277     free(p->data);
278     p->data = strdup(s);
279     } else
280     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
281     }
282    
283     void PrefsReplaceBool(const char *name, bool b)
284     {
285     prefs_node *p = find_node(name, TYPE_BOOLEAN);
286     if (p) {
287     if (p->desc && p->desc->func)
288     ((prefs_func_bool)(p->desc->func))(name, *(bool *)(p->data), b);
289     *(bool *)(p->data) = b;
290     } else
291     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
292     }
293    
294     void PrefsReplaceInt32(const char *name, int32 val)
295     {
296     prefs_node *p = find_node(name, TYPE_INT32);
297     if (p) {
298     if (p->desc && p->desc->func)
299     ((prefs_func_int32)(p->desc->func))(name, *(int32 *)(p->data), val);
300     *(int32 *)(p->data) = val;
301     } else
302     add_data(name, TYPE_INT32, &val, sizeof(int32));
303     }
304    
305    
306     /*
307     * Get prefs items
308     */
309    
310     const char *PrefsFindString(const char *name, int index)
311     {
312     prefs_node *p = find_node(name, TYPE_STRING, index);
313     if (p)
314     return (char *)(p->data);
315     else
316     return NULL;
317     }
318    
319     bool PrefsFindBool(const char *name)
320     {
321     prefs_node *p = find_node(name, TYPE_BOOLEAN, 0);
322     if (p)
323     return *(bool *)(p->data);
324     else
325     return false;
326     }
327    
328     int32 PrefsFindInt32(const char *name)
329     {
330     prefs_node *p = find_node(name, TYPE_INT32, 0);
331     if (p)
332     return *(int32 *)(p->data);
333     else
334     return 0;
335     }
336    
337    
338     /*
339     * Remove prefs items
340     */
341    
342     void PrefsRemoveItem(const char *name, int index)
343     {
344     prefs_node *p = find_node(name, TYPE_ANY, index);
345     if (p) {
346     free((void *)p->name);
347     free(p->data);
348     prefs_node *q = the_prefs;
349     if (q == p) {
350     the_prefs = NULL;
351     delete p;
352     return;
353     }
354     while (q) {
355     if (q->next == p) {
356     q->next = p->next;
357     delete p;
358     return;
359     }
360     q = q->next;
361     }
362     }
363     }
364    
365    
366     /*
367     * Set prefs change callback function
368     */
369    
370     static void set_callback(const char *name, prefs_func f)
371     {
372 cebix 1.2 prefs_desc *d = find_prefs_desc(name);
373 cebix 1.1 if (d == NULL)
374     return;
375     d->func = f;
376     }
377    
378     void PrefsSetCallback(const char *name, prefs_func_string f)
379     {
380     set_callback(name, (prefs_func)f);
381     }
382    
383     void PrefsSetCallback(const char *name, prefs_func_bool f)
384     {
385     set_callback(name, (prefs_func)f);
386     }
387    
388     void PrefsSetCallback(const char *name, prefs_func_int32 f)
389     {
390     set_callback(name, (prefs_func)f);
391     }