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

# Content
1 /*
2 * prefs.cpp - Preferences handling
3 *
4 * SIDPlayer (C) Copyright 1996-2001 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 options
57 for (int i=1; i<argc; i++) {
58
59 // Options are of the form '--keyword'
60 const char *option = argv[i];
61 if (strlen(option) < 3 || option[0] != '-' || option[1] != '-')
62 continue;
63 const char *keyword = option + 2;
64
65 // Find descriptor for keyword
66 const prefs_desc *d = find_prefs_desc(keyword);
67 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 }
77 const char *value = argv[i];
78 argv[i] = NULL;
79
80 // Add/replace prefs item
81 switch (d->type) {
82 case TYPE_STRING:
83 if (d->multiple)
84 PrefsAddString(keyword, value);
85 else
86 PrefsReplaceString(keyword, value);
87 break;
88
89 case TYPE_BOOLEAN: {
90 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 break;
97 }
98
99 case TYPE_INT32:
100 PrefsReplaceInt32(keyword, atoi(value));
101 break;
102
103 default:
104 break;
105 }
106 }
107
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 }
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 * 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 printf("\nBoolean options are specified as '--OPTION true|on|yes' or\n'--OPTION false|off|no'.\n");
187 }
188
189
190 /*
191 * Find preferences descriptor by keyword
192 */
193
194 static prefs_desc *find_prefs_desc(const char *name, prefs_desc *list)
195 {
196 while (list->type != TYPE_END) {
197 if (strcmp(list->name, name) == 0)
198 return list;
199 list++;
200 }
201 return NULL;
202 }
203
204 static prefs_desc *find_prefs_desc(const char *name)
205 {
206 return find_prefs_desc(name, common_prefs_items);
207 }
208
209
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 p->desc = find_prefs_desc(p->name);
226 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 prefs_desc *d = find_prefs_desc(name);
373 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 }