1 /*--------------------------------*-C-*---------------------------------*
2 * File: xdefaults.c
3 *----------------------------------------------------------------------*
4 * Copyright 1997,1998 mj olesen <olesen@me.queensu.ca>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *----------------------------------------------------------------------*/
20 /*----------------------------------------------------------------------*
21 * Originally written:
22 * 1994 Robert Nation <nation@rocket.sanders.lockheed.com>
23 * Modifications:
24 * 1997,1998 mj olesen <olesen@me.queensu.ca>
25 *----------------------------------------------------------------------*/
26 /*----------------------------------------------------------------------*
27 * get resources from ~/.Xdefaults or ~/.Xresources with the memory-saving
28 * default or with XGetDefault() (#define USE_XGETDEFAULT)
29 *
30 * Coding style:
31 * resource strings are indicated by an `rs_' prefix followed by
32 * the resource name.
33 * eg, `rs_saveLines' is the resource string corresponding to
34 * the `saveLines' resource
35 *----------------------------------------------------------------------*/
36
37 #ifndef lint
38 static const char rcsid[] = "$Id: xdefaults.c,v 1.5 2005/12/06 17:08:44 sasha Exp $";
39 #endif
40
41 #include "rxvt.h" /* NECESSARY */
42
43 /* #define DEBUG_RESOURCES */
44
45 /* local functions referenced */
46 /*{{{ local variables */
47 static const char *rs_borderLess = NULL;
48 static const char *rs_loginShell = NULL;
49 static const char *rs_utmpInhibit = NULL;
50 static const char *rs_scrollBar = NULL;
51 static const char *rs_scrollBar_right = NULL;
52 static const char *rs_scrollBar_floating = NULL;
53 static const char *rs_scrollTtyOutput = NULL;
54 static const char *rs_scrollKeypress = NULL;
55
56 #ifdef TRANSPARENT
57 static const char *rs_transparent = NULL;
58 static const char *rs_transparent_sb = NULL;
59 #endif
60
61 #if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
62 static const char *rs_bigfont_key = NULL;
63 static const char *rs_smallfont_key = NULL;
64 #endif
65
66 #ifndef NO_MAPALERT
67 # ifdef MAPALERT_OPTION
68 static const char *rs_mapAlert = NULL;
69 # endif
70 #endif
71 static const char *rs_visualBell = NULL;
72 static const char *rs_reverseVideo = NULL;
73 static const char *rs_cutToBeginningOfLine = NULL;
74
75 #ifdef META8_OPTION
76 static const char *rs_meta8 = NULL;
77 #endif
78 #ifdef MULTICHAR_SET
79 static const char *rs_multichar_encoding = NULL;
80 #endif
81 #ifdef GREEK_SUPPORT
82 static const char *rs_greek_keyboard = NULL;
83 #endif
84 /*}}} */
85
86 /*{{{ monolithic option/resource structure: */
87 /*
88 * `string' options MUST have a usage argument
89 * `switch' and `boolean' options have no argument
90 *
91 * if there's no desc(ription), it won't appear in usage()
92 */
93 static const struct {
94 unsigned long flag;
95 const char **dp; /* data pointer */
96 const char *const kw; /* keyword */
97 const char *const opt; /* option */
98 const char *const arg; /* argument */
99 const char *const desc; /* description */
100 } optList[] = {
101
102 /*
103 * INFO() - descriptive information only
104 * STRG() - command-line option, with/without resource
105 * RSTRG() - resource/long-option
106 * BOOL() - regular boolean `-/+' flag
107 * SWCH() - `-' flag
108 */
109 #define INFO(opt, arg, desc) \
110 {0, NULL, NULL, opt, arg, desc}
111 #define STRG(p, kw, opt, arg, desc) \
112 {0, &p, kw, opt, arg, desc}
113 #define RSTRG(p, kw, arg) \
114 {0, &p, kw, NULL, arg, NULL}
115 #define BOOL(p, kw, opt, flag, desc) \
116 {(Opt_Boolean|flag), &p, kw, opt, NULL, desc}
117 #define SWCH(opt, flag, desc) \
118 {(flag), NULL, NULL, opt, NULL, desc}
119
120 /* convenient macros */
121 #define optList_strlen(i) \
122 (optList[i].flag ? 0 : (optList[i].arg ? strlen (optList[i].arg) : 1))
123 #define optList_isBool(i) \
124 (optList[i].flag & Opt_Boolean)
125 #define optList_isReverse(i) \
126 (optList[i].flag & Opt_Reverse)
127 #define optList_size() \
128 (sizeof(optList) / sizeof(optList[0]))
129
130 STRG(display_name, NULL, "display", "string",
131 "X server to contact"),
132 STRG(rs_term_name, "termName", "tn", "string",
133 "value of the TERM environment variable"),
134 STRG(rs_geometry, "geometry", "geometry", "geometry",
135 "size (in characters) and position"),
136 STRG(display_name, NULL, "d", NULL, NULL), /* short form */
137 STRG(rs_geometry, NULL, "g", NULL, NULL), /* short form */
138 BOOL(rs_reverseVideo, "reverseVideo", "rv", Opt_reverseVideo,
139 "reverse video"),
140 #ifdef _MYSTYLE_
141 STRG(rs_mystyle, "MyStyle", "mst", "name",
142 "MyStyle"),
143 #endif
144 STRG(rs_color[Color_bg], "background", "bg", "color",
145 "background color"),
146 STRG(rs_color[Color_fg], "foreground", "fg", "color",
147 "foreground color"),
148 /* colors: command-line long-option = resource name */
149 RSTRG(rs_color[minCOLOR + 0], "color0", "color"),
150 RSTRG(rs_color[minCOLOR + 1], "color1", "color"),
151 RSTRG(rs_color[minCOLOR + 2], "color2", "color"),
152 RSTRG(rs_color[minCOLOR + 3], "color3", "color"),
153 RSTRG(rs_color[minCOLOR + 4], "color4", "color"),
154 RSTRG(rs_color[minCOLOR + 5], "color5", "color"),
155 RSTRG(rs_color[minCOLOR + 6], "color6", "color"),
156 RSTRG(rs_color[minCOLOR + 7], "color7", "color"),
157 #ifndef NO_BRIGHTCOLOR
158 RSTRG(rs_color[minBrightCOLOR + 0], "color8", "color"),
159 RSTRG(rs_color[minBrightCOLOR + 1], "color9", "color"),
160 RSTRG(rs_color[minBrightCOLOR + 2], "color10", "color"),
161 RSTRG(rs_color[minBrightCOLOR + 3], "color11", "color"),
162 RSTRG(rs_color[minBrightCOLOR + 4], "color12", "color"),
163 RSTRG(rs_color[minBrightCOLOR + 5], "color13", "color"),
164 RSTRG(rs_color[minBrightCOLOR + 6], "color14", "color"),
165 RSTRG(rs_color[minBrightCOLOR + 7], "color15", "color"),
166 #endif /* NO_BRIGHTCOLOR */
167 #ifndef NO_BOLDUNDERLINE
168 RSTRG(rs_color[Color_BD], "colorBD", "color"),
169 RSTRG(rs_color[Color_UL], "colorUL", "color"),
170 #endif /* NO_BOLDUNDERLINE */
171 #ifdef KEEP_SCROLLCOLOR
172 RSTRG(rs_color[Color_scroll], "scrollColor", "color"),
173 RSTRG(rs_color[Color_trough], "troughColor", "color"),
174 #endif /* KEEP_SCROLLCOLOR */
175 #if defined (BACKGROUND_IMAGE) || (MENUBAR_MAX)
176 RSTRG(rs_path, "path", "search path"),
177 #endif /* defined (BACKGROUND_IMAGE) || (MENUBAR_MAX) */
178 #ifdef BACKGROUND_IMAGE
179 STRG(rs_backgroundPixmap,
180 "backgroundPixmap",
181 "pixmap", "file[;geom]", "background pixmap"),
182 #endif /* BACKGROUND_IMAGE */
183 #if defined(BACKGROUND_IMAGE) || defined(TRANSPARENT)
184 STRG(rs_backgroundType,
185 "backgroundType",
186 "bgtype", BGT_ALL, "type of the background pixmap transformation"),
187 STRG(rs_tintType,
188 "tintingType",
189 "tinttype", TINT_TYPE_ALL,
190 "defines function to be used for background tinting"),
191 STRG(rs_shade,
192 "shading",
193 "sh", "%", "make transparent background x% darker"),
194 STRG(rs_color[Color_tint],
195 "tinting",
196 "tint", "color",
197 "tinted transparency color"),
198 #endif
199 STRG(rs_textType,
200 "textType",
201 "txttype", GC_TYPE_ALL,
202 "defines function to be used for text drawing"),
203 #ifdef OFF_FOCUS_FADING
204 STRG(rs_fade,
205 "fading",
206 "fade", "%", "make colors x% darker when aterm is loosing focus."),
207 #endif
208
209 #ifdef BOOL
210 #ifdef TRANSPARENT
211 BOOL(rs_transparent, "transparent", "tr", Opt_transparent,
212 "transparent background"),
213 BOOL(rs_transparent_sb, "transpscrollbar", "trsb", Opt_transparent_sb,
214 "transparent scrollbar"),
215 #endif
216 #endif
217 #if (MENUBAR_MAX)
218 RSTRG(rs_menu, "menu", "name[;tag]"),
219 #endif
220 #ifndef NO_BOLDFONT
221 STRG(rs_boldFont, "boldFont", "fb", "fontname", "bold text font"),
222 #endif
223 STRG(rs_font[0], "font", "fn", "fontname", "normal text font"),
224 /* fonts: command-line option = resource name */
225 #if NFONTS > 1
226 RSTRG(rs_font[1], "font1", "fontname"),
227 #endif
228 #if NFONTS > 2
229 RSTRG(rs_font[2], "font2", "fontname"),
230 #endif
231 #if NFONTS > 3
232 RSTRG(rs_font[3], "font3", "fontname"),
233 #endif
234 #if NFONTS > 4
235 RSTRG(rs_font[4], "font4", "fontname"),
236 #endif
237 #if NFONTS > 5
238 RSTRG(rs_font[5], "font5", "fontname"),
239 #endif
240 #if NFONTS > 6
241 RSTRG(rs_font[6], "font6", "fontname"),
242 #endif
243 #if NFONTS > 7
244 RSTRG(rs_font[7], "font7", "fontname"),
245 #endif
246 #ifdef MULTICHAR_SET
247 STRG(rs_mfont[0], "mfont", "fm", "fontname", "multichar font"),
248
249 /* fonts: command-line option = resource name */
250 # if NFONTS > 1
251 RSTRG(rs_mfont[1], "mfont1", "fontname"),
252 # endif
253 # if NFONTS > 2
254 RSTRG(rs_mfont[2], "mfont2", "fontname"),
255 # endif
256 # if NFONTS > 3
257 RSTRG(rs_mfont[3], "mfont3", "fontname"),
258 # endif
259 # if NFONTS > 4
260 RSTRG(rs_mfont[4], "mfont4", "fontname"),
261 # endif
262 # if NFONTS > 5
263 RSTRG(rs_mfont[5], "mfont5", "fontname"),
264 # endif
265 # if NFONTS > 6
266 RSTRG(rs_mfont[6], "mfont6", "fontname"),
267 # endif
268 # if NFONTS > 7
269 RSTRG(rs_mfont[7], "mfont7", "fontname"),
270 # endif
271 #endif /* MULTICHAR_SET */
272
273 #ifdef MULTICHAR_SET
274 STRG(rs_multichar_encoding, "multichar_encoding", "km", "mode",
275 "multiple-character font encoding; mode = eucj | sjis | big5"),
276 #endif /* MULTICHAR_SET */
277 #ifdef USE_XIM
278 STRG(rs_preeditType, "preeditType", "pt", "style",
279 "input style of input method; style = OverTheSpot | OffTheSpot | Root"),
280 STRG(rs_inputMethod, "inputMethod", "im", "name", "name of input method"),
281 #endif /* USE_XIM */
282 #ifdef GREEK_SUPPORT
283 STRG(rs_greek_keyboard, "greek_keyboard", "grk", "mode",
284 "greek keyboard mapping; mode = iso | ibm"),
285 #endif
286 SWCH("iconic", Opt_iconic, "start iconic"),
287 SWCH("ic", Opt_iconic, NULL), /* short form */
288 STRG(rs_name, NULL, "name", "string",
289 "client instance, icon, and title strings"),
290 STRG(rs_title, "title", "title", "string", "title name for window"),
291 STRG(rs_title, NULL, "T", NULL, NULL), /* short form */
292 STRG(rs_iconName, "iconName", "n", "string", "icon name for window"),
293 #ifndef NO_CURSORCOLOR
294 STRG(rs_color[Color_cursor], "cursorColor", "cr", "color",
295 "cursor color"),
296 /* command-line option = resource name */
297 RSTRG(rs_color[Color_cursor2], "cursorColor2", "color"),
298 #endif /* NO_CURSORCOLOR */
299 STRG(rs_color[Color_pointer], "pointerColor", "pr", "color",
300 "pointer color"),
301 STRG(rs_borderWidth, "borderWidth", "bw", "number",
302 "width of border"),
303 STRG(rs_internal_border, "internalBorder", "ib", "number",
304 "width of the internal border"),
305 STRG(rs_color[Color_border], "borderColor", "bd", "color",
306 "border color"),
307 BOOL(rs_borderLess, "borderLess", "bl", Opt_borderLess, "no decoration"),
308 BOOL(rs_loginShell, "loginShell", "ls", Opt_loginShell, "login shell"),
309 BOOL(rs_scrollBar, "scrollBar", "sb", Opt_scrollBar, "scrollbar"),
310 BOOL(rs_scrollBar_right, "scrollBar_right", "sr", Opt_scrollBar_right,
311 "scrollbar right"),
312 BOOL(rs_scrollBar_floating, "scrollBar_floating", "st",
313 Opt_scrollBar_floating, "scrollbar without a trough"),
314 BOOL(rs_scrollTtyOutput, "scrollTtyOutput", NULL,
315 Opt_scrollTtyOutput, NULL),
316 BOOL(rs_scrollTtyOutput, NULL, "si", Opt_Reverse | Opt_scrollTtyOutput,
317 "scroll-on-tty-output inhibit"),
318 BOOL(rs_scrollKeypress, "scrollKey", "sk",
319 Opt_scrollKeypress, "scroll-on-keypress"),
320 STRG(rs_minBufferWidth, "minBufferWidth", "mbw", "number",
321 "minimum number of columns stored in buffer"),
322 STRG(rs_saveLines, "saveLines", "sl", "number",
323 "number of scrolled lines to save"),
324 #ifdef USE_LINESPACE
325 STRG(rs_lineSpace, "lineSpace", "lsp", "number",
326 "line space"),
327 #endif
328 BOOL(rs_utmpInhibit, "utmpInhibit", "ut", Opt_utmpInhibit,
329 "utmp inhibit"),
330 BOOL(rs_visualBell, "visualBell", "vb", Opt_visualBell, "visual bell"),
331 BOOL(rs_cutToBeginningOfLine, "cutToBeginningOfLine", "cb", Opt_cutToBeginningOfLine,
332 "cut to beginning of line"),
333
334 #ifndef NO_MAPALERT
335 # ifdef MAPALERT_OPTION
336 BOOL(rs_mapAlert, "mapAlert", NULL, Opt_mapAlert, NULL),
337 # endif
338 #endif
339 #ifdef META8_OPTION
340 BOOL(rs_meta8, "meta8", NULL, Opt_meta8, NULL),
341 RSTRG(rs_modifier, "modifier", "string"),
342 #endif
343 #ifndef NO_BACKSPACE_KEY
344 RSTRG(rs_backspace_key, "backspacekey", "string"),
345 #endif
346 #ifndef NO_DELETE_KEY
347 RSTRG(rs_delete_key, "deletekey", "string"),
348 #endif
349 #ifdef PRINTPIPE
350 RSTRG(rs_print_pipe, "print-pipe", "string"),
351 #endif
352 #if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
353 RSTRG(rs_bigfont_key, "bigfont_key", "keysym"),
354 RSTRG(rs_smallfont_key, "smallfont_key", "keysym"),
355 #endif
356 #ifdef CUTCHAR_RESOURCE
357 RSTRG(rs_cutchars, "cutchars", "string"),
358 #endif /* CUTCHAR_RESOURCE */
359 SWCH("C", Opt_console, "intercept console messages"),
360 INFO("e", "command arg ...", "command to execute")
361 };
362
363 #undef INFO
364 #undef STRG
365 #undef RSTRG
366 #undef SWCH
367 #undef BOOL
368 /*}}} */
369
370 /*{{{ list_options: */
371 /*----------------------------------------------------------------------*/
372 /* PROTO */
373 void
list_options()374 list_options()
375 {
376 #define INDENT 30
377 fprintf(stderr, "(");
378 #ifdef BACKGROUND_IMAGE
379 fprintf(stderr, "background image,");
380 #endif
381 #ifdef XPM
382 fprintf(stderr, "XPM,");
383 #endif
384 #ifdef USE_LIBASIMAGE
385 #ifdef JPEG
386 fprintf(stderr, "JPEG,");
387 #endif
388 #ifdef PNG
389 fprintf(stderr, "PNG,");
390 #endif
391 fprintf(stderr, "AfterStep integration,");
392 #ifdef _MYSTYLE_
393 fprintf(stderr, "AfterStep MyStyles,");
394 #else
395 fprintf(stderr, "no AfterStep MyStyles,");
396 #endif
397 #endif
398 #ifdef UTMP_SUPPORT
399 fprintf(stderr, "utmp,");
400 #endif
401 #ifdef MENUBAR
402 fprintf(stderr, "menubar,");
403 #endif
404 #ifdef KANJI
405 fprintf(stderr, "Kanji,");
406 #endif
407 #ifdef ZH
408 fprintf(stderr, "Chinese,");
409 #endif
410 #ifdef THAI
411 fprintf(stderr, "Thai,");
412 #endif
413 #ifdef XTERM_SCROLLBAR
414 fprintf(stderr, "XTerm-scrollbar,");
415 #endif
416 #ifdef GREEK_SUPPORT
417 fprintf(stderr, "Greek,");
418 #endif
419 #ifdef NO_BACKSPACE_KEY
420 fprintf(stderr, "no backspace,");
421 #endif
422 #ifdef NO_DELETE_KEY
423 fprintf(stderr, "no delete,");
424 #endif
425 #ifdef TRANSPARENT
426 fprintf(stderr, "transparency,");
427 #else
428 fprintf(stderr, "no transparency,");
429 # endif
430 #ifdef OFF_FOCUS_FADING
431 fprintf(stderr, "fading,");
432 #else
433 fprintf(stderr, "no fading,");
434 # endif
435 #ifdef NEXT_SCROLLBAR
436 fprintf(stderr, "NeXT scrollbar,");
437 # endif
438 #ifdef NO_RESOURCES
439 fprintf(stderr, "NoResources");
440 #else
441 # ifdef USE_XGETDEFAULT
442 fprintf(stderr, "XGetDefaults");
443 # else
444 fprintf(stderr, ".Xdefaults");
445 # endif
446 #endif
447
448 fprintf(stderr, ")" );
449
450 }
451 /*}}} */
452
453 /*{{{ usage: */
454 /*----------------------------------------------------------------------*/
455 /* PROTO */
456 void
version(int type)457 version(int type)
458 {
459 switch (type) {
460 case 0: /* brief listing */
461 fprintf(stderr, "%s version %s\n", APL_NAME,VERSION);
462 break ;
463 case 1: /* full command-line listing */
464 fprintf(stderr, "%s version %s from %s\n", APL_NAME,VERSION, DATE);
465 list_options();
466 fprintf(stderr, "\n");
467 break ;
468 case 2: /* full resource listing */
469 fprintf(stderr, "%s\n", VERSION);
470 break ;
471 }
472 exit(EXIT_FAILURE);
473 }
474 /*}}} */
475
476 /*{{{ usage: */
477 /*----------------------------------------------------------------------*/
478 /* PROTO */
479 void
usage(int type)480 usage(int type)
481 {
482 int i, col;
483
484 fprintf(stderr, "\nUsage v%s :", VERSION);
485 list_options();
486 fprintf(stderr, "\n%s", APL_NAME);
487
488 switch (type) {
489 case 0: /* brief listing */
490 fprintf(stderr, " [-help][-V]\n");
491 col = 3;
492 for (i = 0; i < optList_size(); i++) {
493 if (optList[i].desc != NULL) {
494 int len = 2;
495
496 if (!optList_isBool(i)) {
497 len = optList_strlen(i);
498 if (len > 0)
499 len++; /* account for space */
500 }
501 len += 4 + strlen(optList[i].opt);
502
503 col += len;
504 if (col > 79) { /* assume regular width */
505 fprintf(stderr, "\n");
506 col = 3 + len;
507 }
508 fprintf(stderr, " [-");
509 if (optList_isBool(i))
510 fprintf(stderr, "/+");
511 fprintf(stderr, "%s", optList[i].opt);
512 if (optList_strlen(i))
513 fprintf(stderr, " %s]", optList[i].arg);
514 else
515 fprintf(stderr, "]");
516 }
517 }
518 fprintf(stderr, "\n\n");
519 break;
520
521 case 1: /* full command-line listing */
522 fprintf(stderr,
523 " [options] [-e command args]\n\n"
524 "where options include:\n");
525
526 for (i = 0; i < optList_size(); i++)
527 if (optList[i].desc != NULL)
528 fprintf(stderr, " %s%s %-*s%s%s\n",
529 (optList_isBool(i) ? "-/+" : "-"),
530 optList[i].opt,
531 (INDENT - strlen(optList[i].opt)
532 + (optList_isBool(i) ? 0 : 2)),
533 (optList[i].arg ? optList[i].arg : ""),
534 (optList_isBool(i) ? "turn on/off " : ""),
535 optList[i].desc);
536 fprintf(stderr, "\n --help to list long-options\n --version for the version information\n\n");
537 break;
538
539 case 2: /* full resource listing */
540 fprintf(stderr,
541 " [options] [-e command args]\n\n"
542 "where resources (long-options) include:\n");
543
544 for (i = 0; i < optList_size(); i++)
545 if (optList[i].kw != NULL)
546 fprintf(stderr, " %s: %*s\n",
547 optList[i].kw,
548 (INDENT - strlen(optList[i].kw)),
549 (optList_isBool(i) ? "boolean" : optList[i].arg));
550
551 #ifdef KEYSYM_RESOURCE
552 fprintf(stderr, " " "keysym.sym" ": %*s\n",
553 (INDENT - strlen("keysym.sym")), "keysym");
554 #endif
555 fprintf(stderr, "\n -help to list options\n -version for the version information with options list\n\n");
556 break;
557 }
558 exit(EXIT_FAILURE);
559 }
560 /*}}} */
561
562 /*{{{ get command-line options before getting resources */
563 /* PROTO */
564 void
get_options(int argc,char * argv[])565 get_options(int argc, char *argv[])
566 {
567 int i, bad_option = 0;
568 static const char *const On = "ON";
569 static const char *const Off = "OFF";
570
571 for (i = 1; i < argc; i++) {
572 int entry, longopt = 0;
573 const char *flag;
574 char *opt = argv[i];
575
576 #ifdef DEBUG_RESOURCES
577 fprintf(stderr, "argv[%d] = %s: ", i, argv[i]);
578 #endif
579 if (*opt == '-') {
580 flag = On;
581 if (*++opt == '-')
582 longopt = *opt++; /* long option */
583 } else if (*opt == '+') {
584 flag = Off;
585 if (*++opt == '+')
586 longopt = *opt++; /* long option */
587 } else {
588 bad_option = 1;
589 print_error("bad option \"%s\"", opt);
590 continue;
591 }
592
593 if (!strcmp(opt, "help"))
594 usage(longopt ? 2 : 1);
595 if (!strcmp(opt, "h"))
596 usage(0);
597 if (!strcmp(opt, "version"))
598 version(longopt ? 2 : 1);
599 if (!strcmp(opt, "V"))
600 version(0);
601
602 /* feature: always try to match long-options */
603 for (entry = 0; entry < optList_size(); entry++)
604 if ((optList[entry].kw && !strcmp(opt, optList[entry].kw)) ||
605 (!longopt &&
606 optList[entry].opt && !strcmp(opt, optList[entry].opt)))
607 break;
608
609 if (entry < optList_size()) {
610 if (optList_isReverse(entry))
611 flag = flag == On ? Off : On;
612 if (optList_strlen(entry)) { /* string value */
613 char *str = argv[++i];
614
615 #ifdef DEBUG_RESOURCES
616 fprintf(stderr, "string (%s,%s) = ",
617 optList[entry].opt ? optList[entry].opt : "nil",
618 optList[entry].kw ? optList[entry].kw : "nil");
619 #endif
620 if (flag == On && str && optList[entry].dp) {
621 #ifdef DEBUG_RESOURCES
622 fprintf(stderr, "\"%s\"\n", str);
623 #endif
624 *(optList[entry].dp) = str;
625
626 /* special cases are handled in main.c:main() to allow
627 * X resources to set these values before we settle for
628 * default values
629 */
630 }
631 #ifdef DEBUG_RESOURCES
632 else
633 fprintf(stderr, "???\n");
634 #endif
635 } else { /* boolean value */
636 #ifdef DEBUG_RESOURCES
637 fprintf(stderr, "boolean (%s,%s) = %s\n",
638 optList[entry].opt, optList[entry].kw, flag);
639 #endif
640 if (flag == On)
641 Options |= (optList[entry].flag);
642 else
643 Options &= ~(optList[entry].flag);
644
645 if (optList[entry].dp)
646 *(optList[entry].dp) = flag;
647 }
648 } else
649 #ifdef KEYSYM_RESOURCE
650 /* if (!strncmp (opt, "keysym.", strlen ("keysym."))) */
651 if (Str_match(opt, "keysym.")) {
652 char *str = argv[++i];
653
654 /*
655 * '7' is strlen("keysym.")
656 */
657 if (str != NULL)
658 parse_keysym(opt + 7, str);
659 } else
660 #endif
661 {
662 /* various old-style options, just ignore
663 * Obsolete since about Jan 96,
664 * so they can probably eventually be removed
665 */
666 const char *msg = "bad";
667
668 if (longopt) {
669 opt--;
670 bad_option = 1;
671 } else if (!strcmp(opt, "7") || !strcmp(opt, "8")
672 #ifdef GREEK_SUPPORT
673 /* obsolete 12 May 1996 (v2.17) */
674 || !Str_match(opt, "grk")
675 #endif
676 )
677 msg = "obsolete";
678 else
679 bad_option = 1;
680
681 print_error("%s option \"%s\"", msg, --opt);
682 }
683 }
684
685 if (bad_option)
686 usage(0);
687 }
688 /*}}} */
689
690 #ifndef NO_RESOURCES
691 /*----------------------------------------------------------------------*/
692 /*{{{ string functions */
693 /*
694 * a replacement for strcasecmp() to avoid linking an entire library
695 */
696 /* PROTO */
697 int
my_strcasecmp(const char * s1,const char * s2)698 my_strcasecmp(const char *s1, const char *s2)
699 {
700 for ( /*nil */ ; (*s1 && *s2); s1++, s2++) {
701 register int c1 = toupper(*s1);
702 register int c2 = toupper(*s2);
703
704 if (c1 != c2)
705 return (c1 - c2);
706 }
707 return (int)(*s1 - *s2);
708 }
709
710 /*}}} */
711
712 # ifdef KEYSYM_RESOURCE
713 /*
714 * Define key from XrmEnumerateDatabase.
715 * quarks will be something like
716 * "rxvt" "keysym" "0xFF01"
717 * value will be a string
718 */
719 /* ARGSUSED */
720 /* PROTO */
721 Bool
define_key(XrmDatabase * database,XrmBindingList bindings,XrmQuarkList quarks,XrmRepresentation * type,XrmValue * value,XPointer closure)722 define_key(XrmDatabase * database, XrmBindingList bindings, XrmQuarkList quarks, XrmRepresentation * type, XrmValue * value, XPointer closure)
723 {
724 int last;
725
726 for (last = 0; quarks[last] != NULLQUARK; last++) /* look for last quark in list */
727 ;
728 last--;
729 parse_keysym(XrmQuarkToString(quarks[last]), (char *)value->addr);
730 return False;
731 }
732
733 /*
734 * look for something like this (XK_Delete)
735 * rxvt*keysym.0xFFFF: "\177"
736 *
737 * arg will be
738 * NULL for ~/.Xdefaults and
739 * non-NULL for command-line options (need to allocate)
740 */
741 /* PROTO */
742 int
parse_keysym(char * str,char * arg)743 parse_keysym(char *str, char *arg)
744 {
745 char *key_string;
746 int n, sym;
747
748 if (arg == NULL) {
749 if ((n = Str_match(str, "keysym.")) == 0)
750 return 0;
751 str += n; /* skip `keysym.' */
752 }
753 /* some scanf() have trouble with a 0x prefix */
754 if (isdigit(str[0])) {
755 if (str[0] == '0' && toupper(str[1]) == 'X')
756 str += 2;
757 if (arg) {
758 if (sscanf(str, (strchr(str, ':') ? "%x:" : "%x"), &sym) != 1)
759 return -1;
760 } else {
761 if (sscanf(str, "%x:", &sym) != 1)
762 return -1;
763
764 /* cue to ':', it's there since sscanf() worked */
765 str = strchr(str, ':');
766 str++;
767 arg = Str_trim(str);
768 if (arg == NULL)
769 return -1;
770 }
771 } else {
772 /*
773 * convert keysym name to keysym number
774 */
775 if (arg == NULL) {
776 arg = str;
777
778 arg = strchr(str, ':');
779 if (arg == NULL)
780 return -1;
781
782 *arg++ = '\0';
783 arg = Str_trim(arg);
784 if (arg == NULL)
785 return -1;
786 }
787 sym = XStringToKeysym(str);
788
789 if (sym == None)
790 return -1;
791 }
792
793 if (sym < 0xFF00 || sym > 0xFFFF) /* we only do extended keys */
794 return -1;
795 sym -= 0xFF00;
796
797 if (KeySym_map[sym] != NULL) /* already set ? */
798 return -1;
799
800 if ((n = strlen(arg)) == 0)
801 return -1;
802
803 key_string = MALLOC((n + 2) * sizeof(char));
804
805 STRCPY(key_string + 1, arg);
806
807 n = Str_escaped(key_string + 1);
808 if (n) {
809 key_string[0] = min(n, 255);
810 KeySym_map[sym] = (unsigned char *) key_string;
811 } else {
812 FREE(key_string);
813 return -1;
814 }
815
816 return 1;
817 }
818 # endif /* KEYSYM_RESOURCE */
819
820 # ifndef USE_XGETDEFAULT
821 /*{{{ get_xdefaults() */
822 /*
823 * the matching algorithm used for memory-save fake resources
824 */
825 /* PROTO */
826 void
get_xdefaults(FILE * stream,const char * name)827 get_xdefaults(FILE * stream, const char *name)
828 {
829 unsigned int len;
830 char *str, buffer[256];
831
832 if (stream == NULL)
833 return;
834 len = strlen(name);
835 while ((str = fgets(buffer, sizeof(buffer), stream)) != NULL) {
836 unsigned int entry, n;
837
838 while (*str && isspace(*str))
839 str++; /* leading whitespace */
840
841 if ((str[len] != '*' && str[len] != '.') ||
842 (len && strncmp(str, name, len)))
843 continue;
844 str += (len + 1); /* skip `name*' or `name.' */
845
846 # ifdef KEYSYM_RESOURCE
847 if (!parse_keysym(str, NULL))
848 # endif /* KEYSYM_RESOURCE */
849 for (entry = 0; entry < optList_size(); entry++) {
850 const char *const kw = optList[entry].kw;
851
852 if (kw == NULL)
853 continue;
854 n = strlen(kw);
855 if (str[n] == ':' && Str_match(str, kw)) {
856 /* skip `keyword:' */
857 str += (n + 1);
858 str = Str_skip_space(str);
859 str = Str_trim(str);
860 n = (str ? strlen(str) : 0);
861 if (n && *(optList[entry].dp) == NULL) {
862 /* not already set */
863 int s;
864 char *p = MALLOC((n + 1) * sizeof(char));
865
866 STRCPY(p, str);
867 *(optList[entry].dp) = p;
868 if (optList_isBool(entry)) {
869 s = my_strcasecmp(p, "TRUE") == 0
870 || my_strcasecmp(p, "YES") == 0
871 || my_strcasecmp(p, "ON") == 0
872 || my_strcasecmp(p, "1") == 0;
873 if (optList_isReverse(entry))
874 s = !s;
875 if (s)
876 Options |= (optList[entry].flag);
877 else {
878 if (my_strcasecmp(str, "FALSE"))
879 print_error("Cannot parse value \"%s\" from resource \"%s\" as boolean",
880 str, kw);
881 Options &= ~(optList[entry].flag);
882 }
883 }
884 }
885 break;
886 }
887 }
888 }
889 rewind(stream);
890 }
891 /*}}} */
892 # endif /* ! USE_XGETDEFAULT */
893 #endif /* NO_RESOURCES */
894
895 /*{{{ read the resources files */
896 /*
897 * using XGetDefault() or the hand-rolled replacement
898 */
899 /* ARGSUSED */
900 /* PROTO */
901 void
extract_resources(Display * display,const char * name)902 extract_resources(Display * display, const char *name)
903 {
904 #ifndef NO_RESOURCES
905 # ifdef USE_XGETDEFAULT
906 /*
907 * get resources using the X library function
908 */
909 int entry;
910
911 # ifdef XrmEnumOneLevel
912 XrmName name_prefix[3];
913 XrmClass class_prefix[3];
914 char *displayResource;
915 XrmDatabase database;
916 char *screenResource;
917 XrmDatabase screenDatabase;
918
919 /*
920 * Get screen-specific resources (X11R5) and merge into common resources.
921 */
922 database = NULL;
923 screenDatabase = NULL;
924 displayResource = XResourceManagerString(display);
925 if (displayResource != NULL)
926 database = XrmGetStringDatabase(displayResource);
927 screenResource = XScreenResourceString(DefaultScreenOfDisplay(display));
928 if (screenResource != NULL)
929 screenDatabase = XrmGetStringDatabase(screenResource);
930 XrmMergeDatabases(screenDatabase, &database);
931 XrmSetDatabase(display, database);
932 # endif
933
934 for (entry = 0; entry < optList_size(); entry++) {
935 int s;
936 char *p, *p0;
937 const char *kw = optList[entry].kw;
938
939 if (kw == NULL || *(optList[entry].dp) != NULL)
940 continue; /* previously set */
941
942 #define STRCMP(x, y) strcmp((const char *)(x), (const char *)(y))
943 p = XGetDefault(display, name, kw);
944 p0 = XGetDefault(display, "!INVALIDPROGRAMMENAMEDONTMATCH!", kw);
945 if (p == NULL || (p0 && STRCMP(p, p0) == 0)) {
946 p = XGetDefault(display, APL_SUBCLASS, kw);
947 if (p == NULL || (p0 && STRCMP(p, p0) == 0))
948 p = XGetDefault(display, APL_CLASS, kw);
949 }
950 if (p == NULL && p0)
951 p = p0;
952 if (p) {
953 *optList[entry].dp = p;
954
955 if (optList_isBool(entry)) {
956 s = my_strcasecmp(p, "TRUE") == 0
957 || my_strcasecmp(p, "YES") == 0
958 || my_strcasecmp(p, "ON") == 0
959 || my_strcasecmp(p, "1") == 0;
960 if (optList_isReverse(entry))
961 s = !s;
962 if (s)
963 Options |= (optList[entry].flag);
964 else {
965 if (my_strcasecmp(p, "FALSE"))
966 print_error("Cannot parse value \"%s\" from resource \"%s\" as boolean",
967 p, kw);
968 Options &= ~(optList[entry].flag);
969 }
970 }
971 }
972 }
973
974 /*
975 * [R5 or later]: enumerate the resource database
976 */
977 # ifdef XrmEnumOneLevel
978 # ifdef KEYSYM_RESOURCE
979 name_prefix[0] = XrmStringToName(name);
980 name_prefix[1] = XrmStringToName("keysym");
981 name_prefix[2] = NULLQUARK;
982 class_prefix[0] = XrmStringToName(APL_SUBCLASS);
983 class_prefix[1] = XrmStringToName("Keysym");
984 class_prefix[2] = NULLQUARK;
985 XrmEnumerateDatabase(XrmGetDatabase(display),
986 name_prefix,
987 class_prefix,
988 XrmEnumOneLevel,
989 define_key,
990 NULL);
991 name_prefix[0] = XrmStringToName(APL_CLASS);
992 name_prefix[1] = XrmStringToName("keysym");
993 class_prefix[0] = XrmStringToName(APL_CLASS);
994 class_prefix[1] = XrmStringToName("Keysym");
995 XrmEnumerateDatabase(XrmGetDatabase(display),
996 name_prefix,
997 class_prefix,
998 XrmEnumOneLevel,
999 define_key,
1000 NULL);
1001 # endif
1002 # endif
1003
1004 # else /* USE_XGETDEFAULT */
1005 /* get resources the hard way, but save lots of memory */
1006 const char *fname[] = { ".Xdefaults", ".Xresources" };
1007 FILE *fd = NULL;
1008 char *home;
1009
1010 if ((home = getenv("HOME")) != NULL) {
1011 int i, len = strlen(home) + 2;
1012 char *f = NULL;
1013
1014 for (i = 0; i < (sizeof(fname) / sizeof(fname[0])); i++) {
1015 f = REALLOC(f, (len + strlen(fname[i])) * sizeof(char));
1016
1017 sprintf(f, "%s/%s", home, fname[i]);
1018
1019 if ((fd = fopen(f, "r")) != NULL)
1020 break;
1021 }
1022 FREE(f);
1023 }
1024 /*
1025 * The normal order to match resources is the following:
1026 * @ global resources (partial match, ~/.Xdefaults)
1027 * @ application file resources (XAPPLOADDIR/Rxvt)
1028 * @ class resources (~/.Xdefaults)
1029 * @ private resources (~/.Xdefaults)
1030 *
1031 * However, for the hand-rolled resources, the matching algorithm
1032 * checks if a resource string value has already been allocated
1033 * and won't overwrite it with (in this case) a less specific
1034 * resource value.
1035 *
1036 * This avoids multiple allocation. Also, when we've called this
1037 * routine command-line string options have already been applied so we
1038 * needn't to allocate for those resources.
1039 *
1040 * So, search in resources from most to least specific.
1041 *
1042 * Also, use a special sub-class so that we can use either or both of
1043 * "XTerm" and "Rxvt" as class names.
1044 */
1045
1046 get_xdefaults(fd, name);
1047 get_xdefaults(fd, APL_SUBCLASS);
1048
1049 # ifdef XAPPLOADDIR
1050 {
1051 FILE *ad = fopen(XAPPLOADDIR "/" APL_SUBCLASS, "r");
1052
1053 if (ad != NULL) {
1054 get_xdefaults(ad, "");
1055 fclose(ad);
1056 }
1057 }
1058 # endif /* XAPPLOADDIR */
1059
1060 get_xdefaults(fd, APL_CLASS);
1061 get_xdefaults(fd, ""); /* partial match */
1062 if (fd != NULL)
1063 fclose(fd);
1064 # endif /* USE_XGETDEFAULT */
1065 #endif /* NO_RESOURCES */
1066
1067 /*
1068 * even without resources, at least do this setup for command-line
1069 * options and command-line long options
1070 */
1071 #ifdef MULTICHAR_SET
1072 set_multichar_encoding(rs_multichar_encoding);
1073 #endif
1074 #ifdef GREEK_SUPPORT
1075 /* this could be a function in grkelot.c */
1076 /* void set_greek_keyboard (const char * str); */
1077 if (rs_greek_keyboard) {
1078 if (!strcmp(rs_greek_keyboard, "iso"))
1079 greek_setmode(GREEK_ELOT928); /* former -grk9 */
1080 else if (!strcmp(rs_greek_keyboard, "ibm"))
1081 greek_setmode(GREEK_IBM437); /* former -grk4 */
1082 }
1083 #endif /* GREEK_SUPPORT */
1084
1085 #define to_keysym(pks,str) do { KeySym sym;\
1086 if (str && ((sym = XStringToKeysym(str)) != 0)) *pks = sym; } while (0)
1087
1088 #if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
1089 to_keysym(&ks_bigfont, rs_bigfont_key);
1090 to_keysym(&ks_smallfont, rs_smallfont_key);
1091 #endif
1092 #undef to_keysym
1093 }
1094 /*}}} */
1095 /*----------------------- end-of-file (C source) -----------------------*/
1096