1 #include "xglk.h"
2 #include <X11/Xresource.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 static char *parse_fontnamespec(char *str, fontnamespec_t **result);
7 static int string_to_bool(char *str);
8
9 static XrmOptionDescRec argtable[] = {
10 {"-background", ".background", XrmoptionSepArg, NULL},
11 {"-linkcolor", ".linkColor", XrmoptionSepArg, NULL},
12 {"-foreground", ".foreground", XrmoptionSepArg, NULL},
13 {"-selectcolor", ".selectColor", XrmoptionSepArg, NULL},
14 {"-framecolor", ".frameColor", XrmoptionSepArg, NULL},
15 {"-frameupcolor", ".frameUpColor", XrmoptionSepArg, NULL},
16 {"-framedowncolor", ".frameDownColor", XrmoptionSepArg, NULL},
17 {"-ditherimages", ".ditherImages", XrmoptionSepArg, NULL},
18 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
19 {"-historylength", ".historyLength", XrmoptionSepArg, NULL},
20 {"-defprompt", ".defaultPrompts", XrmoptionSepArg, NULL},
21 {"-savelength", ".textBuffer.saveLength", XrmoptionSepArg, NULL},
22 {"-saveslack", ".textBuffer.saveSlack", XrmoptionSepArg, NULL},
23 {"-colorlinks", ".colorLinks", XrmoptionSepArg, NULL},
24 {"-underlinelinks", ".underlineLinks", XrmoptionSepArg, NULL},
25 {"-marginx", ".Window.margin.x", XrmoptionSepArg, NULL},
26 {"-marginy", ".Window.margin.y", XrmoptionSepArg, NULL},
27 {"-bufmarginx", ".textBuffer.margin.x", XrmoptionSepArg, NULL},
28 {"-bufmarginy", ".textBuffer.margin.y", XrmoptionSepArg, NULL},
29 {"-gridmarginx", ".textGrid.margin.x", XrmoptionSepArg, NULL},
30 {"-gridmarginy", ".textGrid.margin.y", XrmoptionSepArg, NULL},
31 {"-bufbackground", ".textBuffer.background", XrmoptionSepArg, NULL},
32 {"-buflinkcolor", ".textBuffer.linkColor", XrmoptionSepArg, NULL},
33 {"-bufforeground", ".textBuffer.foreground", XrmoptionSepArg, NULL},
34 {"-gridbackground", ".textGrid.background", XrmoptionSepArg, NULL},
35 {"-gridlinkcolor", ".textGrid.linkColor", XrmoptionSepArg, NULL},
36 {"-gridforeground", ".textGrid.foreground", XrmoptionSepArg, NULL},
37 };
38
xglk_init_preferences(int argc,char * argv[],glkunix_startup_t * startdata)39 int xglk_init_preferences(int argc, char *argv[],
40 glkunix_startup_t *startdata)
41 {
42 int ix, jx, val;
43 char *cx;
44 XrmValue xval;
45 XColor xcol;
46 winprefs_t *wprefs;
47 char *resourcestring = XResourceManagerString(xiodpy);
48 XrmDatabase db = NULL;
49 int errflag = FALSE;
50
51 if (resourcestring) {
52 db = XrmGetStringDatabase(resourcestring);
53 }
54
55 XrmParseCommand(&db, argtable,
56 sizeof(argtable) / sizeof(XrmOptionDescRec),
57 "glk", &argc, argv);
58
59 /* Now the program-specific argument parsing. */
60 startdata->argc = 0;
61 startdata->argv = (char **)malloc(argc * sizeof(char *));
62
63 /* Copy in the program name. */
64 startdata->argv[startdata->argc] = argv[0];
65 startdata->argc++;
66
67 for (ix=1; ix<argc && !errflag; ix++) {
68 glkunix_argumentlist_t *argform;
69 int inarglist = FALSE;
70 char *cx;
71
72 for (argform = glkunix_arguments;
73 argform->argtype != glkunix_arg_End && !errflag;
74 argform++) {
75
76 if (argform->name[0] == '\0') {
77 if (argv[ix][0] != '-') {
78 startdata->argv[startdata->argc] = argv[ix];
79 startdata->argc++;
80 inarglist = TRUE;
81 }
82 }
83 else if ((argform->argtype == glkunix_arg_NumberValue)
84 && !strncmp(argv[ix], argform->name, strlen(argform->name))
85 && (cx = argv[ix] + strlen(argform->name))
86 && (atoi(cx) != 0 || cx[0] == '0')) {
87 startdata->argv[startdata->argc] = argv[ix];
88 startdata->argc++;
89 inarglist = TRUE;
90 }
91 else if (!strcmp(argv[ix], argform->name)) {
92 int numeat = 0;
93
94 if (argform->argtype == glkunix_arg_ValueFollows) {
95 if (ix+1 >= argc) {
96 printf("%s: %s must be followed by a value\n",
97 argv[0], argform->name);
98 errflag = TRUE;
99 break;
100 }
101 numeat = 2;
102 }
103 else if (argform->argtype == glkunix_arg_NoValue) {
104 numeat = 1;
105 }
106 else if (argform->argtype == glkunix_arg_ValueCanFollow) {
107 if (ix+1 < argc && argv[ix+1][0] != '-') {
108 numeat = 2;
109 }
110 else {
111 numeat = 1;
112 }
113 }
114 else if (argform->argtype == glkunix_arg_NumberValue) {
115 if (ix+1 >= argc
116 || (atoi(argv[ix+1]) == 0 && argv[ix+1][0] != '0')) {
117 printf("%s: %s must be followed by a number\n",
118 argv[0], argform->name);
119 errflag = TRUE;
120 break;
121 }
122 numeat = 2;
123 }
124 else {
125 errflag = TRUE;
126 break;
127 }
128
129 for (jx=0; jx<numeat; jx++) {
130 startdata->argv[startdata->argc] = argv[ix];
131 startdata->argc++;
132 if (jx+1 < numeat)
133 ix++;
134 }
135 inarglist = TRUE;
136 break;
137 }
138 }
139
140 if (errflag)
141 break;
142 if (!inarglist) {
143 printf("%s: unknown argument: %s\n", argv[0], argv[ix]);
144 errflag = TRUE;
145 break;
146 }
147 }
148
149 if (errflag) {
150 printf("usage: %s [ options ... ]\n", argv[0]);
151 if (glkunix_arguments[0].argtype != glkunix_arg_End) {
152 glkunix_argumentlist_t *argform;
153 printf("game options:\n");
154 for (argform = glkunix_arguments;
155 argform->argtype != glkunix_arg_End;
156 argform++) {
157 printf(" %s\n", argform->desc);
158 }
159 }
160 return FALSE;
161 }
162
163 /* We've survived argument parsing. Go ahead and use the values
164 we've got. */
165 prefs.win_w = 500;
166 prefs.win_h = 600;
167 prefs.win_x = 64;
168 prefs.win_y = 10;
169 if (db && XrmGetResource(db,
170 "glk.geometry", "Glk.Geometry",
171 &cx, &xval)) {
172 XParseGeometry(xval.addr, &prefs.win_x, &prefs.win_y,
173 &prefs.win_w, &prefs.win_h);
174 }
175
176 if (db && XrmGetResource(db,
177 "glk.ditherImages", "Glk.DitherImages",
178 &cx, &xval)) {
179 prefs.ditherimages = string_to_bool(xval.addr);
180 }
181 else {
182 prefs.ditherimages = TRUE;
183 }
184
185 if (db && XrmGetResource(db,
186 "glk.foreground", "Glk.Foreground",
187 &cx, &xval)
188 && XParseColor(xiodpy, xiomap, xval.addr, &xcol)) {
189 XAllocColor(xiodpy, xiomap, &xcol);
190 prefs.forecolor = xcol;
191 }
192 else {
193 xcol.red = xcol.green = xcol.blue = 0;
194 XAllocColor(xiodpy, xiomap, &xcol);
195 prefs.forecolor = xcol;
196 /*prefs.forecolor.pixel = BlackPixel(xiodpy, xioscn);
197 XQueryColor(xiodpy, xiomap, &prefs.forecolor);*/
198 }
199
200 if (db && XrmGetResource(db,
201 "glk.linkColor", "Glk.LinkColor",
202 &cx, &xval)
203 && XParseColor(xiodpy, xiomap, xval.addr, &xcol)) {
204 XAllocColor(xiodpy, xiomap, &xcol);
205 prefs.linkcolor = xcol;
206 }
207 else {
208 xcol.red = xcol.green = 0;
209 xcol.blue = 65535;
210 XAllocColor(xiodpy, xiomap, &xcol);
211 prefs.linkcolor = xcol;
212 }
213
214 if (db && XrmGetResource(db,
215 "glk.background", "Glk.Background",
216 &cx, &xval)
217 && XParseColor(xiodpy, xiomap, xval.addr, &xcol)) {
218 XAllocColor(xiodpy, xiomap, &xcol);
219 prefs.backcolor = xcol;
220 }
221 else {
222 xcol.red = xcol.green = xcol.blue = 65535;
223 XAllocColor(xiodpy, xiomap, &xcol);
224 prefs.backcolor = xcol;
225 /*prefs.backcolor.pixel = WhitePixel(xiodpy, xioscn);
226 XQueryColor(xiodpy, xiomap, &prefs.backcolor);*/
227 }
228
229 if (db && XrmGetResource(db,
230 "glk.selectColor", "Glk.SelectColor",
231 &cx, &xval))
232 XParseColor(xiodpy, xiomap, xval.addr, &xcol);
233 else
234 XParseColor(xiodpy, xiomap, "blue", &xcol);
235 XAllocColor(xiodpy, xiomap, &xcol);
236 prefs.selectcolor = xcol;
237
238 if (db && XrmGetResource(db,
239 "glk.frameColor", "Glk.FrameColor",
240 &cx, &xval))
241 XParseColor(xiodpy, xiomap, xval.addr, &xcol);
242 else
243 XParseColor(xiodpy, xiomap, "grey50", &xcol);
244 XAllocColor(xiodpy, xiomap, &xcol);
245 prefs.techcolor = xcol;
246
247 if (db && XrmGetResource(db,
248 "glk.frameUpColor", "Glk.FrameUpColor",
249 &cx, &xval))
250 XParseColor(xiodpy, xiomap, xval.addr, &xcol);
251 else
252 XParseColor(xiodpy, xiomap, "grey75", &xcol);
253 XAllocColor(xiodpy, xiomap, &xcol);
254 prefs.techucolor = xcol;
255
256 if (db && XrmGetResource(db,
257 "glk.frameDownColor", "Glk.FrameDownColor",
258 &cx, &xval))
259 XParseColor(xiodpy, xiomap, xval.addr, &xcol);
260 else
261 XParseColor(xiodpy, xiomap, "grey25", &xcol);
262 XAllocColor(xiodpy, xiomap, &xcol);
263 prefs.techdcolor = xcol;
264
265 if (db && XrmGetResource(db,
266 "glk.textBuffer.saveLength", "Glk.TextBuffer.SaveLength",
267 &cx, &xval))
268 prefs.buffersize = atoi(xval.addr);
269 else
270 prefs.buffersize = 8000;
271
272 if (db && XrmGetResource(db,
273 "glk.textBuffer.saveSlack", "Glk.TextBuffer.SaveSlack",
274 &cx, &xval))
275 prefs.bufferslack = atoi(xval.addr);
276 else
277 prefs.bufferslack = 1000;
278
279 if (db && XrmGetResource(db,
280 "glk.historyLength", "Glk.HistoryLength",
281 &cx, &xval))
282 prefs.historylength = atoi(xval.addr);
283 else
284 prefs.historylength = 20;
285
286 if (db && XrmGetResource(db,
287 "glk.defaultPrompts", "Glk.DefaultPrompts",
288 &cx, &xval)) {
289 prefs.prompt_defaults = string_to_bool(xval.addr);
290 }
291 else {
292 prefs.prompt_defaults = TRUE;
293 }
294
295 if (db && XrmGetResource(db,
296 "glk.colorLinks", "Glk.ColorLinks",
297 &cx, &xval)) {
298 prefs.colorlinks = string_to_bool(xval.addr);
299 }
300 else {
301 prefs.colorlinks = TRUE;
302 }
303
304 if (db && XrmGetResource(db,
305 "glk.underlineLinks", "Glk.UnderlineLinks",
306 &cx, &xval)) {
307 prefs.underlinelinks = string_to_bool(xval.addr);
308 }
309 else {
310 prefs.underlinelinks = TRUE;
311 }
312
313 for (wprefs = &(prefs.textbuffer);
314 wprefs;
315 wprefs
316 = (((wprefs == &(prefs.textbuffer)) ? &(prefs.textgrid) : NULL))) {
317
318 char classbuf[256];
319 char *instance;
320 if (wprefs == &(prefs.textgrid))
321 instance = "textGrid";
322 else
323 instance = "textBuffer";
324
325 sprintf(classbuf, "%s.%s.margin.x", "glk", instance);
326 if (db && XrmGetResource(db,
327 classbuf, "Glk.Window.Margin.Width",
328 &cx, &xval))
329 val = atoi(xval.addr);
330 else
331 val = 4;
332 wprefs->marginx = val;
333
334 sprintf(classbuf, "%s.%s.margin.y", "glk", instance);
335 if (db && XrmGetResource(db,
336 classbuf, "Glk.Window.Margin.Width",
337 &cx, &xval))
338 val = atoi(xval.addr);
339 else
340 val = 2;
341 wprefs->marginy = val;
342
343 sprintf(classbuf, "%s.%s.foreground", "glk", instance);
344 if (db && XrmGetResource(db,
345 classbuf, "Glk.Window.Foreground",
346 &cx, &xval)
347 && XParseColor(xiodpy, xiomap, xval.addr, &xcol)) {
348 XAllocColor(xiodpy, xiomap, &xcol);
349 }
350 else {
351 xcol = prefs.forecolor;
352 }
353 wprefs->forecolor = xcol;
354
355 sprintf(classbuf, "%s.%s.linkColor", "glk", instance);
356 if (db && XrmGetResource(db,
357 classbuf, "Glk.Window.LinkColor",
358 &cx, &xval)
359 && XParseColor(xiodpy, xiomap, xval.addr, &xcol)) {
360 XAllocColor(xiodpy, xiomap, &xcol);
361 }
362 else {
363 xcol = prefs.linkcolor;
364 }
365 wprefs->linkcolor = xcol;
366
367 sprintf(classbuf, "%s.%s.background", "glk", instance);
368 if (db && XrmGetResource(db,
369 classbuf, "Glk.Window.Background",
370 &cx, &xval)
371 && XParseColor(xiodpy, xiomap, xval.addr, &xcol)) {
372 XAllocColor(xiodpy, xiomap, &xcol);
373 }
374 else {
375 xcol = prefs.backcolor;
376 }
377 wprefs->backcolor = xcol;
378
379 wprefs->sizehint = FALSE;
380 wprefs->fixedhint = FALSE;
381 wprefs->attribhint = FALSE;
382 wprefs->justhint = FALSE;
383 wprefs->indenthint = FALSE;
384 wprefs->colorhint = FALSE;
385
386 for (ix=0; ix<style_NUMSTYLES; ix++) {
387 static char *stylenames[style_NUMSTYLES] = {
388 "normal", "emphasized", "preformatted", "header", "subheader",
389 "alert", "note", "blockQuote", "input", "user1", "user2"
390 };
391 fontprefs_t *fprefs = &(wprefs->style[ix]);
392
393 sprintf(classbuf, "%s.%s.%s.spec", "glk", instance, stylenames[ix]);
394 if (db && XrmGetResource(db,
395 classbuf, "Glk.Window.Style.Spec",
396 &cx, &xval)) {
397 cx = xval.addr;
398 }
399 else {
400 if (wprefs == &(prefs.textbuffer))
401 cx = "%p{-adobe-courier-%w{medium,bold}-%o{r,o}-normal-"
402 "-%s{8,10,12,14,18,24}-*-*-*-*-*-iso8859-1,"
403 "-adobe-times-%w{medium,bold}-%o{r,i}-normal-"
404 "-%s{8,10,12,14,18,24,34}-*-*-*-*-*-iso8859-1}";
405 else
406 cx = "-adobe-courier-%w{medium,bold}-%o{r,o}-normal-"
407 "-%s{8,10,12,14,18,24}-*-*-*-*-*-iso8859-1";
408 }
409 fprefs->specname = cx;
410 parse_fontnamespec(fprefs->specname, &fprefs->spec);
411
412 sprintf(classbuf, "%s.%s.%s.size", "glk", instance, stylenames[ix]);
413 if (db && XrmGetResource(db,
414 classbuf, "Glk.Window.Style.Size",
415 &cx, &xval))
416 val = atoi(xval.addr);
417 else
418 val = 0;
419 fprefs->size = val;
420
421 sprintf(classbuf, "%s.%s.%s.weight", "glk", instance, stylenames[ix]);
422 if (db && XrmGetResource(db,
423 classbuf, "Glk.Window.Style.Weight",
424 &cx, &xval))
425 val = atoi(xval.addr);
426 else
427 val = (ix == style_Input
428 || ix == style_Header
429 || ix == style_Subheader)
430 ? 1 : 0;
431 fprefs->weight = val;
432
433 sprintf(classbuf, "%s.%s.%s.oblique", "glk", instance, stylenames[ix]);
434 if (db && XrmGetResource(db,
435 classbuf, "Glk.Window.Style.Oblique",
436 &cx, &xval))
437 val = atoi(xval.addr);
438 else
439 val = (ix == style_Emphasized) ? 1 : 0;
440 fprefs->oblique = val;
441
442 sprintf(classbuf, "%s.%s.%s.proportional", "glk", instance, stylenames[ix]);
443 if (db && XrmGetResource(db,
444 classbuf, "Glk.Window.Style.Proportional",
445 &cx, &xval))
446 val = atoi(xval.addr);
447 else
448 val = (ix == style_Preformatted || wprefs == &(prefs.textgrid))
449 ? 0 : 1;
450 fprefs->proportional = val;
451
452 sprintf(classbuf, "%s.%s.%s.justify", "glk", instance, stylenames[ix]);
453 if (db && XrmGetResource(db,
454 classbuf, "Glk.Window.Style.Justify",
455 &cx, &xval))
456 val = atoi(xval.addr);
457 else
458 val = 1;
459 fprefs->justify = val;
460
461 sprintf(classbuf, "%s.%s.%s.indent", "glk", instance, stylenames[ix]);
462 if (db && XrmGetResource(db,
463 classbuf, "Glk.Window.Style.Indent",
464 &cx, &xval))
465 val = atoi(xval.addr);
466 else
467 val = 0;
468 fprefs->baseindent = val;
469
470 sprintf(classbuf, "%s.%s.%s.parIndent", "glk", instance, stylenames[ix]);
471 if (db && XrmGetResource(db,
472 classbuf, "Glk.Window.Style.ParIndent",
473 &cx, &xval))
474 val = atoi(xval.addr);
475 else
476 val = 0;
477 fprefs->parindent = val;
478
479 sprintf(classbuf, "%s.%s.%s.foreground", "glk", instance, stylenames[ix]);
480 if (db && XrmGetResource(db,
481 classbuf, "Glk.Window.Style.Foreground",
482 &cx, &xval)
483 && XParseColor(xiodpy, xiomap, xval.addr, &xcol)) {
484 XAllocColor(xiodpy, xiomap, &xcol);
485 }
486 else {
487 xcol = wprefs->forecolor;
488 }
489 fprefs->forecolor = xcol;
490
491 sprintf(classbuf, "%s.%s.%s.linkColor", "glk", instance, stylenames[ix]);
492 if (db && XrmGetResource(db,
493 classbuf, "Glk.Window.Style.LinkColor",
494 &cx, &xval)
495 && XParseColor(xiodpy, xiomap, xval.addr, &xcol)) {
496 XAllocColor(xiodpy, xiomap, &xcol);
497 }
498 else {
499 xcol = wprefs->linkcolor;
500 }
501 fprefs->linkcolor = xcol;
502
503 sprintf(classbuf, "%s.%s.%s.background", "glk", instance, stylenames[ix]);
504 if (db && XrmGetResource(db,
505 classbuf, "Glk.Window.Style.Background",
506 &cx, &xval)
507 && XParseColor(xiodpy, xiomap, xval.addr, &xcol)) {
508 XAllocColor(xiodpy, xiomap, &xcol);
509 }
510 else {
511 xcol = wprefs->backcolor;
512 }
513 fprefs->backcolor = xcol;
514 }
515 }
516
517 if (db)
518 XrmDestroyDatabase(db);
519
520 return TRUE;
521 }
522
string_to_bool(char * str)523 static int string_to_bool(char *str)
524 {
525 if (*str == 'y' || *str == 'Y')
526 return TRUE;
527 if (*str == 't' || *str == 'T')
528 return TRUE;
529 if (*str == '1')
530 return TRUE;
531 if (*str == 'o' || *str == 'O') {
532 if (*str == 'f' || *str == 'F')
533 return TRUE;
534 }
535 return FALSE;
536 }
537
538 typedef struct fontnamespecopt_struct {
539 char key; /* 'w', 'o', 's', 'p' */
540 int numopts;
541 fontnamespec_t **opts;
542 } fontnamespecopt_t;
543
544 #define fnstype_String (0)
545 #define fnstype_Option (1)
546 struct fontnamespec_struct {
547 int type;
548 union {
549 char *str;
550 fontnamespecopt_t *opt;
551 } u;
552 fontnamespec_t *next;
553 };
554
parse_fontnamespec(char * str,fontnamespec_t ** result)555 static char *parse_fontnamespec(char *str, fontnamespec_t **result)
556 {
557 fontnamespec_t **spec;
558 char *bx, *tx;
559
560 *result = NULL;
561 spec = result;
562
563 while (*str && *str != ',' && *str != '}') {
564 *spec = (fontnamespec_t *)malloc(sizeof(fontnamespec_t));
565 (*spec)->next = NULL;
566
567 if (*str == '%') {
568 fontnamespecopt_t *opt =
569 (fontnamespecopt_t *)malloc(sizeof(fontnamespecopt_t));
570 fontnamespec_t *subspec;
571 (*spec)->type = fnstype_Option;
572 opt->numopts = 0;
573 opt->opts = NULL;
574 str++;
575 opt->key = *str;
576 if (*str)
577 str++;
578 while (*str == '{' || *str == ',') {
579 str++;
580 str = parse_fontnamespec(str, &subspec);
581 if (opt->numopts == 0) {
582 opt->numopts++;
583 opt->opts =
584 (fontnamespec_t **)malloc(opt->numopts * sizeof(fontnamespec_t *));
585 }
586 else {
587 opt->numopts++;
588 opt->opts =
589 (fontnamespec_t **)realloc(opt->opts,
590 opt->numopts * sizeof(fontnamespec_t *));
591 }
592 opt->opts[opt->numopts-1] = subspec;
593 }
594 if (*str == '}')
595 str++;
596 (*spec)->u.opt = opt;
597 }
598 else {
599 (*spec)->type = fnstype_String;
600 bx = str;
601 while (*str && *str != ',' && *str != '}' && *str != '%')
602 str++;
603 tx = (char *)malloc(str+1-bx);
604 memcpy(tx, bx, (str-bx));
605 tx[str-bx] = '\0';
606 (*spec)->u.str = tx;
607 }
608
609 spec = &((*spec)->next);
610 }
611
612 return str;
613 }
614
xglk_build_fontname(fontnamespec_t * spec,char * buf,int size,int weight,int oblique,int proportional)615 void xglk_build_fontname(fontnamespec_t *spec, char *buf,
616 int size, int weight, int oblique, int proportional)
617 {
618 char *str = buf;
619 int val;
620
621 while (spec) {
622 switch (spec->type) {
623 case fnstype_String:
624 if (spec->u.str == NULL)
625 break;
626 strcpy(str, spec->u.str);
627 str += strlen(spec->u.str);
628 break;
629 case fnstype_Option:
630 if (spec->u.opt->numopts == 0 || spec->u.opt->opts == NULL)
631 break;
632 switch (spec->u.opt->key) {
633 case 'w':
634 val = weight;
635 break;
636 case 'p':
637 val = proportional;
638 break;
639 case 's':
640 val = size;
641 break;
642 case 'o':
643 val = oblique;
644 break;
645 default:
646 val = 0;
647 break;
648 }
649 val += ((spec->u.opt->numopts-1) / 2); /* rounding down */
650 if (val >= spec->u.opt->numopts)
651 val = spec->u.opt->numopts-1;
652 if (val < 0)
653 val = 0;
654 xglk_build_fontname(spec->u.opt->opts[val], str,
655 size, weight, oblique, proportional);
656 str += strlen(str);
657 break;
658 }
659 spec = spec->next;
660 }
661
662 *str = '\0';
663 }
664