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