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, 4 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

# Content
1 /*
2 * prefs.cpp - Preferences handling
3 *
4 * Basilisk II (C) 1997-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 <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 // 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 };
38
39 // List of prefs nodes
40 static prefs_node *the_prefs = NULL;
41
42 // Prototypes
43 static const prefs_desc *find_prefs_desc(const char *name);
44
45
46 /*
47 * Initialize preferences
48 */
49
50 void PrefsInit(int argc, char **argv)
51 {
52 // Set defaults
53 AddPrefsDefaults();
54 AddPlatformPrefsDefaults();
55
56 // Load preferences from settings file
57 LoadPrefs();
58
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 }
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 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
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 // Look for keyword first in prefs item list
333 const prefs_desc *desc = find_prefs_desc(keyword);
334 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 fprintf(f, "%s %d\n", list->name, PrefsFindInt32(list->name));
380 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 }