ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SIDPlayer/src/prefs.cpp
Revision: 1.3
Committed: 2001-01-16T16:53:26Z (23 years, 9 months ago) by cebix
Branch: MAIN
Changes since 1.2: +78 -8 lines
Log Message:
added options help screen for command line version

File Contents

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