|
|
1.1 root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2:
3: /* gtk options loading/saving */
4:
5: #define _GNU_SOURCE 1
6: #define _BSD_SOURCE 1
7: #define __EXTENSIONS__ 1
8:
9: #include <stdio.h>
10: #include <string.h>
11: #include <errno.h>
12: #include <stdlib.h>
13:
14: #include "generator.h"
15: #include "gtkopts.h"
16:
17: t_conf *gtkopts_conf = NULL;
18:
19: static const char *gtkopts_default(const char *key);
20:
21: #define CONFLINELEN 1024
22:
23: typedef struct {
24: char *key;
25: char *vals;
26: char *def;
27: char *desc;
28: } t_opts;
29:
30: /* *INDENT-OFF* */
31:
32: static t_opts gtkopts_opts[] = {
33: { "view", "100, 200", "100",
34: "view mode to use in percent" },
35: { "region", "domestic, overseas", "overseas",
36: "hardware region" },
37: { "videostd", "ntsc, pal", "ntsc",
38: "video standard" },
39: { "autodetect", "on, off", "on",
40: "automatic region, videostd detection" },
41: { "plotter", "line, cell", "line",
42: "plotter style - line is slower but much more accurate" },
43: { "interlace", "bob, weave, weave-filter", "weave-filter",
44: "style of de-interlacing to use in 200% view mode" },
45: { "frameskip", "auto, 1..10", "auto",
46: "skip frames to keep up - auto setting needs sound turned on" },
47: { "hborder", "0..32", "8",
48: "horizontal over-scan border surrounding main playing area" },
49: { "vborder", "0..32", "8",
50: "vertical retrace border surrounding main playing area" },
51: { "sound", "on, off", "on",
52: "sound system toggle, also turns off fm and psg (not z80)" },
53: { "z80", "on, off", "on",
54: "z80 cpu" },
55: { "fm", "on, off", "on",
56: "frequency modulation sound generation" },
57: { "psg", "on, off", "on",
58: "programmable sound generation" },
59: { "sound_minfields", "integer", "5",
60: "try to buffer this many fields of sound" },
61: { "sound_maxfields", "integer", "10",
62: "maximum buffered sound fields before blocking (waiting)" },
63: { "loglevel", "integer (0-7)", "1",
64: "logging level" },
65: { "debugsound", "on, off", "off",
66: "extra sound debug logging" },
67: { "statusbar", "on, off", "off",
68: "status bar on main window (fps counter)" },
69: { "key1_a", "gdk keysym", "a",
70: "keyboard player 1 'A' button" },
71: { "key1_b", "gdk keysym", "s",
72: "keyboard player 1 'B' button" },
73: { "key1_c", "gdk keysym", "d",
74: "keyboard player 1 'C' button" },
75: { "key1_up", "gdk keysym", "Up",
76: "keyboard player 1 up" },
77: { "key1_down", "gdk keysym", "Down",
78: "keyboard player 1 down" },
79: { "key1_left", "gdk keysym", "Left",
80: "keyboard player 1 left" },
81: { "key1_right", "gdk keysym", "Right",
82: "keyboard player 1 right" },
83: { "key1_start", "gdk keysym", "Return",
84: "keyboard player 1 start button" },
85: { "key2_a", "gdk keysym", "KP_Divide",
86: "keyboard player 2 'A' button" },
87: { "key2_b", "gdk keysym", "KP_Multiply",
88: "keyboard player 2 'B' button" },
89: { "key2_c", "gdk keysym", "KP_Subtract",
90: "keyboard player 2 'C' button" },
91: { "key2_up", "gdk keysym", "KP_8",
92: "keyboard player 2 up" },
93: { "key2_down", "gdk keysym", "KP_5",
94: "keyboard player 2 down" },
95: { "key2_left", "gdk keysym", "KP_4",
96: "keyboard player 2 left" },
97: { "key2_right", "gdk keysym", "KP_6",
98: "keyboard player 2 right" },
99: { "key2_start", "gdk keysym", "KP_Enter",
100: "keyboard player 2 start button" },
101: { NULL, NULL, NULL, NULL }
102: };
103:
104: /* *INDENT-ON* */
105:
106: int gtkopts_load(const char *file)
107: {
108: char buffer[CONFLINELEN];
109: FILE *fd;
110: char *a, *p, *q, *t;
111: int line = 0;
112: t_conf *conf, *confi;
113:
114: if ((fd = fopen(file, "r")) == NULL) {
115: fprintf(stderr, "%s: unable to open conf '%s' for reading: %s\n",
116: PACKAGE, file, strerror(errno));
117: return -1;
118: }
119: while (fgets(buffer, CONFLINELEN, fd)) {
120: line++;
121: if (buffer[strlen(buffer) - 1] != '\n') {
122: fprintf(stderr, "%s: line %d too long in conf file, ignoring.\n",
123: PACKAGE, line);
124: while ((a = fgets(buffer, CONFLINELEN, fd))) {
125: if (buffer[strlen(buffer) - 1] == '\n')
126: continue;
127: }
128: if (!a)
129: goto finished;
130: continue;
131: }
132: buffer[strlen(buffer) - 1] = '\0';
133: /* remove whitespace off start and end */
134: p = buffer + strlen(buffer) - 1;
135: while (p > buffer && *p == ' ')
136: *p-- = '\0';
137: p = buffer;
138: while (*p == ' ')
139: p++;
140: /* check for comment */
141: if (!*p || *p == '#' || *p == ';')
142: continue;
143: if ((conf = malloc(sizeof(t_conf))) == NULL) {
144: fprintf(stderr, "%s: Out of memory adding to conf\n", PACKAGE);
145: goto error;
146: }
147: q = p;
148: strsep(&q, "=");
149: if (q == NULL) {
150: fprintf(stderr, "%s: line %d not understood in conf file\n", PACKAGE,
151: line);
152: goto error;
153: }
154: /* remove whitespace off end of p and start of q */
155: t = p + strlen(p) - 1;
156: while (t > p && *t == ' ')
157: *t-- = '\0';
158: while (*q == ' ')
159: q++;
160: if ((conf->key = malloc(strlen(p) + 1)) == NULL ||
161: (conf->value = malloc(strlen(q) + 1)) == NULL) {
162: fprintf(stderr, "%s: Out of memory building conf\n", PACKAGE);
163: goto error;
164: }
165: strcpy(conf->key, p);
166: strcpy(conf->value, q);
167: conf->next = NULL;
168: for (confi = gtkopts_conf; confi && confi->next; confi = confi->next);
169: if (!confi)
170: gtkopts_conf = conf;
171: else
172: confi->next = conf;
173: }
174: finished:
175: if (ferror(fd) || fclose(fd)) {
176: fprintf(stderr, "%s: error whilst reading conf: %s\n", PACKAGE,
177: strerror(errno));
178: return -1;
179: }
180: return 0;
181: error:
182: fclose(fd);
183: return -1;
184: }
185:
186: const char *gtkopts_getvalue(const char *key)
187: {
188: t_conf *c;
189: const char *v;
190:
191: for (c = gtkopts_conf; c; c = c->next) {
192: if (!strcasecmp(key, c->key))
193: return c->value;
194: }
195: v = gtkopts_default(key);
196: if (!v)
197: printf("Warning: invalid option '%s' requested.\n", key);
198: return v;
199: }
200:
201: int gtkopts_setvalue(const char *key, const char *value)
202: {
203: t_conf *c;
204: char *n;
205:
206: for (c = gtkopts_conf; c; c = c->next) {
207: if (!strcasecmp(key, c->key)) {
208: if ((n = malloc(strlen(value) + 1)) == NULL)
209: return -1;
210: strcpy(n, value);
211: free(c->value);
212: c->value = n;
213: return 0;
214: }
215: }
216: if ((c = malloc(sizeof(t_conf))) == NULL ||
217: (c->key = malloc(strlen(key) + 1)) == NULL ||
218: (c->value = malloc(strlen(value) + 1)) == NULL)
219: return -1;
220: strcpy(c->key, key);
221: strcpy(c->value, value);
222: c->next = gtkopts_conf;
223: gtkopts_conf = c;
224: return 0;
225: }
226:
227: int gtkopts_save(const char *file)
228: {
229: FILE *fd;
230: t_opts *o;
231:
232: if ((fd = fopen(file, "w")) == NULL) {
233: fprintf(stderr, "%s: unable to open conf '%s' for writing: %s\n",
234: PACKAGE, file, strerror(errno));
235: return -1;
236: }
237: fprintf(fd, "; Generator " VERSION " configuration file\n\n");
238: fprintf(fd, "; for GTK keysyms see include/gtk-1.2/gdk/gdkkeysyms.h\n\n");
239: for (o = gtkopts_opts; o->key; o++) {
240: fprintf(fd, "; %s\n; values: %s\n", o->desc, o->vals);
241: fprintf(fd, "%s = %s\n\n", o->key, gtkopts_getvalue(o->key));
242: }
243: if (fclose(fd)) {
244: fprintf(stderr, "%s: error whilst writing conf: %s\n", PACKAGE,
245: strerror(errno));
246: return -1;
247: }
248: return 0;
249: }
250:
251: static const char *gtkopts_default(const char *key)
252: {
253: t_opts *o;
254:
255: for (o = gtkopts_opts; o->key; o++) {
256: if (!strcasecmp(key, o->key))
257: return o->def;
258: }
259: return NULL;
260: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.