*** empty log message ***
[dana/urxvt.git] / src / xdefaults.C
1 /*--------------------------------*-C-*---------------------------------*
2  * File:        xdefaults.c
3  *----------------------------------------------------------------------*
4  * $Id: xdefaults.C,v 1.15 2004-03-03 04:07:52 pcg Exp $
5  *
6  * All portions of code are copyright by their respective author/s.
7  * Copyright (c) 1994      Robert Nation <nation@rocket.sanders.lockheed.com>
8  *                              - original version
9  * Copyright (c) 1997,1998 mj olesen <olesen@me.queensu.ca>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *----------------------------------------------------------------------*/
25 /*----------------------------------------------------------------------*
26  * get resources from ~/.Xdefaults or ~/.Xresources with the memory-saving
27  * default or with XGetDefault() (#define USE_XGETDEFAULT)
28  *----------------------------------------------------------------------*/
29
30 #include "../config.h"          /* NECESSARY */
31 #include "rxvt.h"               /* NECESSARY */
32 #include "version.h"
33 #include "xdefaults.intpro"     /* PROTOS for internal routines */
34
35 /* #define DEBUG_RESOURCES */
36
37 static const char *const xnames[2] = { ".Xdefaults", ".Xresources" };
38
39 /*{{{ monolithic option/resource structure: */
40 /*
41  * `string' options MUST have a usage argument
42  * `switch' and `boolean' options have no argument
43  * if there's no desc (ription), it won't appear in rxvt_usage ()
44  */
45
46 /* INFO () - descriptive information only */
47 #define INFO(opt, arg, desc)                                    \
48     {0, -1, NULL, (opt), (arg), (desc)}
49
50 /* STRG () - command-line option, with/without resource */
51 #define STRG(rsp, kw, opt, arg, desc)                           \
52     {0, (rsp), (kw), (opt), (arg), (desc)}
53
54 /* RSTRG () - resource/long-option */
55 #define RSTRG(rsp, kw, arg)                                     \
56     {0, (rsp), (kw), NULL, (arg), NULL}
57
58 /* BOOL () - regular boolean `-/+' flag */
59 #define BOOL(rsp, kw, opt, flag, desc)                          \
60     { (Opt_Boolean| (flag)), (rsp), (kw), (opt), NULL, (desc)}
61
62 /* SWCH () - `-' flag */
63 #define SWCH(opt, flag, desc)                                   \
64     { (flag), -1, NULL, (opt), NULL, (desc)}
65
66 /* convenient macros */
67 #define optList_strlen(i)                                               \
68     (optList[i].flag ? 0 : (optList[i].arg ? STRLEN (optList[i].arg) : 1))
69 #define optList_isBool(i)                                               \
70     (optList[i].flag & Opt_Boolean)
71 #define optList_isReverse(i)                                            \
72     (optList[i].flag & Opt_Reverse)
73 #define optList_size()                                                  \
74     (sizeof (optList) / sizeof (optList[0]))
75
76 static const struct
77   {
78     const unsigned long flag;   /* Option flag */
79     const int       doff;       /* data offset */
80     const char     *kw;         /* keyword */
81     const char     *opt;        /* option */
82     const char     *arg;        /* argument */
83     const char     *desc;       /* description */
84   }
85 optList[] = {
86               STRG (Rs_display_name, NULL, "d", NULL, NULL),    /* short form */
87               STRG (Rs_display_name, NULL, "display", "string", "X server to contact"),
88               STRG (Rs_term_name, "termName", "tn", "string",
89                    "value of the TERM environment variable"),
90               STRG (Rs_geometry, NULL, "g", NULL, NULL),        /* short form */
91               STRG (Rs_geometry, "geometry", "geometry", "geometry",
92                    "size (in characters) and position"),
93               SWCH ("C", Opt_console, "intercept console messages"),
94               SWCH ("iconic", Opt_iconic, "start iconic"),
95               SWCH ("ic", Opt_iconic, NULL),    /* short form */
96               BOOL (Rs_reverseVideo, "reverseVideo", "rv", Opt_reverseVideo,
97                    "reverse video"),
98               BOOL (Rs_loginShell, "loginShell", "ls", Opt_loginShell, "login shell"),
99               BOOL (Rs_jumpScroll, "jumpScroll", "j", Opt_jumpScroll, "jump scrolling"),
100 #ifdef HAVE_SCROLLBARS
101               BOOL (Rs_scrollBar, "scrollBar", "sb", Opt_scrollBar, "scrollbar"),
102               BOOL (Rs_scrollBar_right, "scrollBar_right", "sr", Opt_scrollBar_right,
103                    "scrollbar right"),
104               BOOL (Rs_scrollBar_floating, "scrollBar_floating", "st",
105                    Opt_scrollBar_floating, "scrollbar without a trough"),
106 #endif
107               BOOL (Rs_scrollTtyOutput, "scrollTtyOutput", NULL, Opt_scrollTtyOutput,
108                    NULL),
109               BOOL (Rs_scrollTtyOutput, NULL, "si", Opt_Reverse | Opt_scrollTtyOutput,
110                    "scroll-on-tty-output inhibit"),
111               BOOL (Rs_scrollTtyKeypress, "scrollTtyKeypress", "sk", Opt_scrollTtyKeypress,
112                    "scroll-on-keypress"),
113               BOOL (Rs_scrollWithBuffer, "scrollWithBuffer", "sw", Opt_scrollWithBuffer,
114                    "scroll-with-buffer"),
115 #ifdef TRANSPARENT
116               BOOL (Rs_transparent, "inheritPixmap", "ip", Opt_transparent,
117                    "inherit parent pixmap"),
118               BOOL (Rs_transparent_all, "inheritPixmapforce", "ipf", Opt_transparent_all,
119                    "forcefully inherit root pixmap"),
120               SWCH ("tr", Opt_transparent, NULL),
121 #endif
122               BOOL (Rs_utmpInhibit, "utmpInhibit", "ut", Opt_utmpInhibit, "utmp inhibit"),
123 #ifndef NO_BELL
124               BOOL (Rs_visualBell, "visualBell", "vb", Opt_visualBell, "visual bell"),
125 # if ! defined(NO_MAPALERT) && defined(MAPALERT_OPTION)
126               BOOL (Rs_mapAlert, "mapAlert", NULL, Opt_mapAlert, NULL),
127 # endif
128 #endif
129 #ifdef META8_OPTION
130               BOOL (Rs_meta8, "meta8", NULL, Opt_meta8, NULL),
131 #endif
132 #ifdef MOUSE_WHEEL
133               BOOL (Rs_mouseWheelScrollPage, "mouseWheelScrollPage", NULL, Opt_mouseWheelScrollPage,
134                    NULL),
135 #endif
136 #ifndef NO_FRILLS
137               BOOL (Rs_tripleclickwords, "tripleclickwords", "tcw", Opt_tripleclickwords,
138                    "triple click word selection"),
139 #endif
140 #ifdef CURSOR_BLINK
141               BOOL (Rs_cursorBlink, "cursorBlink", "bc", Opt_cursorBlink, "blinking cursor"),
142 #endif
143 #ifdef POINTER_BLANK
144               BOOL (Rs_pointerBlank, "pointerBlank", "pb", Opt_pointerBlank, "switch off pointer after delay"),
145 #endif
146               STRG (Rs_color + Color_bg, "background", "bg", "color", "background color"),
147               STRG (Rs_color + Color_fg, "foreground", "fg", "color", "foreground color"),
148               RSTRG (Rs_color + minCOLOR + 0, "color0", "color"),
149               RSTRG (Rs_color + minCOLOR + 1, "color1", "color"),
150               RSTRG (Rs_color + minCOLOR + 2, "color2", "color"),
151               RSTRG (Rs_color + minCOLOR + 3, "color3", "color"),
152               RSTRG (Rs_color + minCOLOR + 4, "color4", "color"),
153               RSTRG (Rs_color + minCOLOR + 5, "color5", "color"),
154               RSTRG (Rs_color + minCOLOR + 6, "color6", "color"),
155               RSTRG (Rs_color + minCOLOR + 7, "color7", "color"),
156 #ifndef NO_BRIGHTCOLOR
157               RSTRG (Rs_color + minBrightCOLOR + 0, "color8", "color"),
158               RSTRG (Rs_color + minBrightCOLOR + 1, "color9", "color"),
159               RSTRG (Rs_color + minBrightCOLOR + 2, "color10", "color"),
160               RSTRG (Rs_color + minBrightCOLOR + 3, "color11", "color"),
161               RSTRG (Rs_color + minBrightCOLOR + 4, "color12", "color"),
162               RSTRG (Rs_color + minBrightCOLOR + 5, "color13", "color"),
163               RSTRG (Rs_color + minBrightCOLOR + 6, "color14", "color"),
164               RSTRG (Rs_color + minBrightCOLOR + 7, "color15", "color"),
165 #endif                          /* NO_BRIGHTCOLOR */
166 #ifndef NO_BOLD_UNDERLINE_REVERSE
167               RSTRG (Rs_color + Color_BD, "colorBD", "color"),
168               RSTRG (Rs_color + Color_UL, "colorUL", "color"),
169               RSTRG (Rs_color + Color_RV, "colorRV", "color"),
170 #endif                          /* ! NO_BOLD_UNDERLINE_REVERSE */
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 #ifdef OPTION_HC
176               STRG (Rs_color + Color_HC, "highlightColor", "hc", "color", "highlight color"),
177 #endif
178 #if defined (XPM_BACKGROUND) || (MENUBAR_MAX)
179               RSTRG (Rs_path, "path", "search path"),
180 #endif                          /* defined (XPM_BACKGROUND) || (MENUBAR_MAX) */
181 #ifdef XPM_BACKGROUND
182               STRG (Rs_backgroundPixmap, "backgroundPixmap", "pixmap", "file[;geom]",
183                    "background pixmap"),
184 #endif                          /* XPM_BACKGROUND */
185 #if (MENUBAR_MAX)
186               RSTRG (Rs_menu, "menu", "name[;tag]"),
187 #endif
188               STRG (Rs_font, "font", "fn", "fontname", "normal text font"),
189               /* fonts: command-line option = resource name */
190 #ifdef USE_XIM
191               STRG (Rs_inputMethod, "inputMethod", "im", "name", "name of input method"),
192               STRG (Rs_preeditType, "preeditType", "pt", "style",
193                    "input style: style = OverTheSpot|OffTheSpot|Root"),
194 #if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
195               STRG (Rs_imLocale, "imLocale", "imlocale", "string", "locale to use for input method"),
196 #endif
197 #endif                          /* USE_XIM */
198               STRG (Rs_name, NULL, "name", "string",
199                    "client instance, icon, and title strings"),
200               STRG (Rs_title, "title", "title", "string", "title name for window"),
201               STRG (Rs_title, NULL, "T", NULL, NULL),   /* short form */
202               STRG (Rs_iconName, "iconName", "n", "string", "icon name for window"),
203 #ifndef NO_CURSORCOLOR
204               STRG (Rs_color + Color_cursor, "cursorColor", "cr", "color", "cursor color"),
205               /* command-line option = resource name */
206               RSTRG (Rs_color + Color_cursor2, "cursorColor2", "color"),
207 #endif                          /* NO_CURSORCOLOR */
208               STRG (Rs_color + Color_pointer, "pointerColor", "pr", "color",
209                    "pointer color"),
210               STRG (Rs_color + Color_border, "borderColor", "bd", "color",
211                    "border color"),
212               STRG (Rs_saveLines, "saveLines", "sl", "number",
213                    "number of scrolled lines to save"),
214 #ifndef NO_FRILLS
215               STRG (Rs_ext_bwidth, "externalBorder", "w", "number",
216                    "external border in pixels"),
217               STRG (Rs_ext_bwidth, NULL, "bw", NULL, NULL),
218               STRG (Rs_ext_bwidth, NULL, "borderwidth", NULL, NULL),
219               STRG (Rs_int_bwidth, "internalBorder", "b", "number",
220                    "internal border in pixels"),
221 #endif
222 #ifndef NO_LINESPACE
223               STRG (Rs_lineSpace, "lineSpace", "lsp", "number",
224                    "number of extra pixels between rows"),
225 #endif
226               STRG (Rs_scrollBar_thickness, "thickness", "sbt", "number",
227                    "scrollbar thickness/width in pixels"),
228 #ifdef POINTER_BLANK
229               RSTRG (Rs_pointerBlankDelay, "pointerBlankDelay", "number"),
230 #endif
231 #ifndef NO_BACKSPACE_KEY
232               RSTRG (Rs_backspace_key, "backspacekey", "string"),
233 #endif
234 #ifndef NO_DELETE_KEY
235               RSTRG (Rs_delete_key, "deletekey", "string"),
236 #endif
237               RSTRG (Rs_selectstyle, "selectstyle", "mode"),
238               RSTRG (Rs_scrollstyle, "scrollstyle", "mode"),
239 #ifdef HAVE_SCROLLBARS
240               RSTRG (Rs_scrollBar_align, "scrollBar_align", "mode"),
241 #endif
242 #ifdef PRINTPIPE
243               RSTRG (Rs_print_pipe, "print-pipe", "string"),
244 #endif
245 #if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
246               RSTRG (Rs_bigfont_key, "bigfont_key", "keysym"),
247               RSTRG (Rs_smallfont_key, "smallfont_key", "keysym"),
248 #endif
249               STRG (Rs_modifier, "modifier", "mod", "modifier",
250                    "meta modifier = alt|meta|hyper|super|mod1|...|mod5"),
251               INFO ("xrm", "string", "X resource"),
252 #ifdef CUTCHAR_RESOURCE
253               RSTRG (Rs_cutchars, "cutchars", "string"),
254 #endif                          /* CUTCHAR_RESOURCE */
255 #ifdef ACS_ASCII
256               RSTRG (Rs_acs_chars, "acsChars", "string"),
257 #endif                          /* ACS_ASCII */
258               RSTRG (Rs_answerbackstring, "answerbackString", "string"),
259               INFO ("e", "command arg ...", "command to execute")
260             };
261
262 #undef INFO
263 #undef STRG
264 #undef RSTRG
265 #undef SWCH
266 #undef BOOL
267 /*}}} */
268
269 static const char releasestring[] = "Rxvt v" VERSION " - released: " DATE "\n";
270 static const char optionsstring[] = "Options: "
271 #if defined(XPM_BACKGROUND)
272                                     "XPM,"
273 #endif
274 #if defined(TRANSPARENT)
275                                     "transparent,"
276 #endif
277 #if defined(UTMP_SUPPORT)
278                                     "utmp,"
279 #endif
280 #if defined(MENUBAR)
281                                     "menubar,"
282 #endif
283 #if !defined(NO_FRILLS)
284                                     "frills,"
285 #endif
286 #if !defined(NO_LINESPACE)
287                                     "linespace,"
288 #endif
289 #if defined(PREFER_24BIT)
290                                     "24bit,"
291 #endif
292 #if defined(USE_XIM)
293                                     "XIM,"
294 #endif
295                                     "scrollbars="
296 #if !defined(HAVE_SCROLLBARS)
297                                     "NONE"
298 #else
299 # if defined(PLAIN_SCROLLBAR)
300                                     "plain"
301 #  if defined(RXVT_SCROLLBAR) || defined(NEXT_SCROLLBAR) || defined(XTERM_SCROLLBAR)
302                                     "+"
303 #  endif
304 # endif
305 # if defined(RXVT_SCROLLBAR)
306                                     "rxvt"
307 #  if defined(NEXT_SCROLLBAR) || defined(XTERM_SCROLLBAR)
308                                     "+"
309 #  endif
310 # endif
311 # if defined(NEXT_SCROLLBAR)
312                                     "NeXT"
313 #  if defined(XTERM_SCROLLBAR)
314                                     "+"
315 #  endif
316 # endif
317 # if defined(XTERM_SCROLLBAR)
318                                     "xterm"
319 # endif
320 #endif
321                                     ","
322 #if defined(NO_BACKSPACE_KEY)
323                                     "no_backspace,"
324 #endif
325 #if defined(NO_DELETE_KEY)
326                                     "no_delete,"
327 #endif
328 #if !defined(NO_STRINGS)
329                                     "strings,"
330 #endif
331 #if defined(TTY_256COLOR)
332                                     "256colour,"
333 #endif
334 #if defined(NO_RESOURCES)
335                                     "NoResources"
336 #else
337 # if defined(USE_XGETDEFAULT)
338                                     "XGetDefaults"
339 # else
340                                     ".Xdefaults"
341 # endif
342 #endif
343                                     "\nUsage: ";                /* Usage */
344
345 #define INDENT 18
346
347 /*{{{ usage: */
348 /*----------------------------------------------------------------------*/
349 static void
350 rxvt_usage (int type)
351 {
352   unsigned int    i, col;
353
354   write (STDERR_FILENO, releasestring, sizeof (releasestring) - 1);
355   write (STDERR_FILENO, optionsstring, sizeof (optionsstring) - 1);
356   write (STDERR_FILENO, RESNAME, sizeof (RESNAME) - 1);
357
358   switch (type)
359     {
360       case 0:                   /* brief listing */
361         fprintf (stderr, " [-help] [--help]\n");
362         for (col = 1, i = 0; i < optList_size (); i++)
363           if (optList[i].desc != NULL)
364             {
365               int             len = 0;
366
367               if (!optList_isBool (i))
368                 {
369                   len = optList_strlen (i);
370                   if (len > 0)
371                     len++;      /* account for space */
372                 }
373 #ifdef DEBUG_STRICT
374               assert (optList[i].opt != NULL);
375 #endif
376               len += 4 + STRLEN (optList[i].opt) + (optList_isBool (i) ? 2: 0);
377               col += len;
378               if (col > 79)
379                 {       /* assume regular width */
380                   putc ('\n', stderr);
381                   col = 1 + len;
382                 }
383               fprintf (stderr, " [-%s%s", (optList_isBool (i) ? "/+" : ""),
384                       optList[i].opt);
385               if (optList_strlen (i))
386                 fprintf (stderr, " %s]", optList[i].arg);
387               else
388                 fprintf (stderr, "]");
389             }
390         break;
391
392       case 1:                   /* full command-line listing */
393         fprintf (stderr, " [options] [-e command args]\n\n"
394                 "where options include:\n");
395         for (i = 0; i < optList_size (); i++)
396           if (optList[i].desc != NULL)
397             {
398 #ifdef DEBUG_STRICT
399               assert (optList[i].opt != NULL);
400 #endif
401               fprintf (stderr, "  %s%s %-*s%s%s\n",
402                       (optList_isBool (i) ? "-/+" : "-"), optList[i].opt,
403                       (INDENT - STRLEN (optList[i].opt)
404                        + (optList_isBool (i) ? 0 : 2)),
405                       (optList[i].arg ? optList[i].arg : ""),
406                       (optList_isBool (i) ? "turn on/off " : ""),
407                       optList[i].desc);
408             }
409         fprintf (stderr, "\n  --help to list long-options");
410         break;
411
412       case 2:                   /* full resource listing */
413         fprintf (stderr,
414                 " [options] [-e command args]\n\n"
415                 "where resources (long-options) include:\n");
416
417         for (i = 0; i < optList_size (); i++)
418           if (optList[i].kw != NULL)
419             fprintf (stderr, "  %s: %*s%s\n",
420                     optList[i].kw,
421                     (INDENT - STRLEN (optList[i].kw)), "", /* XXX */
422                     (optList_isBool (i) ? "boolean" : optList[i].arg));
423 #ifdef KEYSYM_RESOURCE
424         fprintf (stderr, "  " "keysym.sym" ": %*s%s\n",
425                 (INDENT - sizeof ("keysym.sym") + 1), "", /* XXX */
426                 "keysym");
427 #endif
428         fprintf (stderr, "\n  -help to list options");
429         break;
430     }
431   fprintf (stderr, "\n\n");
432   exit (EXIT_FAILURE);
433   /* NOTREACHED */
434 }
435
436 /*}}} */
437
438 /*{{{ get command-line options before getting resources */
439 void
440 rxvt_term::get_options (int argc, const char *const *argv)
441 {
442   int             i, bad_option = 0;
443   static const char On[3] = "ON", Off[4] = "OFF";
444
445   for (i = 1; i < argc; i++)
446     {
447       unsigned int    entry, longopt = 0;
448       const char     *flag, *opt;
449
450       opt = argv[i];
451 #ifdef DEBUG_RESOURCES
452       fprintf (stderr, "argv[%d] = %s: ", i, opt);
453 #endif
454       if (*opt == '-')
455         {
456           flag = On;
457           if (*++opt == '-')
458             longopt = *opt++;   /* long option */
459         }
460       else if (*opt == '+')
461         {
462           flag = Off;
463           if (*++opt == '+')
464             longopt = *opt++;   /* long option */
465         }
466       else
467         {
468           bad_option = 1;
469           rxvt_print_error ("bad option \"%s\"", opt);
470           continue;
471         }
472
473       if (!STRCMP (opt, "help"))
474         rxvt_usage (longopt ? 2 : 1);
475       if (!STRCMP (opt, "h"))
476         rxvt_usage (0);
477
478       /* feature: always try to match long-options */
479       for (entry = 0; entry < optList_size (); entry++)
480         if ((optList[entry].kw && !STRCMP (opt, optList[entry].kw))
481             || (!longopt
482                 && optList[entry].opt && !STRCMP (opt, optList[entry].opt)))
483           break;
484
485       if (entry < optList_size ())
486         {
487           if (optList_isReverse (entry))
488             flag = flag == On ? Off : On;
489           if (optList_strlen (entry))
490             {   /* string value */
491               const char *str = argv[++i];
492
493 #ifdef DEBUG_RESOURCES
494               fprintf (stderr, "string (%s,%s) = ",
495                       optList[entry].opt ? optList[entry].opt : "nil",
496                       optList[entry].kw ? optList[entry].kw : "nil");
497 #endif
498               if (flag == On && str && (optList[entry].doff != -1))
499                 {
500 #ifdef DEBUG_RESOURCES
501                   fprintf (stderr, "\"%s\"\n", str);
502 #endif
503                   rs[optList[entry].doff] = str;
504                   /*
505                    * special cases are handled in main.c:main () to allow
506                    * X resources to set these values before we settle for
507                    * default values
508                    */
509                 }
510 #ifdef DEBUG_RESOURCES
511               else
512                 fprintf (stderr, "???\n");
513 #endif
514
515             }
516           else
517             {           /* boolean value */
518 #ifdef DEBUG_RESOURCES
519               fprintf (stderr, "boolean (%s,%s) = %s\n",
520                       optList[entry].opt, optList[entry].kw, flag);
521 #endif
522               if (flag == On)
523                 Options |= (optList[entry].flag);
524               else
525                 Options &= ~ (optList[entry].flag);
526
527               if (optList[entry].doff != -1)
528                 rs[optList[entry].doff] = flag;
529             }
530         }
531       else
532 #ifdef KEYSYM_RESOURCE
533         /* if (!STRNCMP (opt, "keysym.", sizeof ("keysym.") - 1)) */
534         if (rxvt_Str_match (opt, "keysym."))
535           {
536             const char     *str = argv[++i];
537
538             if (str != NULL)
539               parse_keysym (opt + sizeof ("keysym.") - 1, str);
540           }
541         else
542 #endif
543           bad_option = 1;
544     }
545
546   if (bad_option)
547     rxvt_usage (0);
548 }
549
550 /*}}} */
551
552 #ifndef NO_RESOURCES
553 /*----------------------------------------------------------------------*/
554
555 # ifdef KEYSYM_RESOURCE
556 /*
557  * Define key from XrmEnumerateDatabase.
558  *   quarks will be something like
559  *      "rxvt" "keysym" "0xFF01"
560  *   value will be a string
561  */
562 /* ARGSUSED */
563 int
564 rxvt_define_key (XrmDatabase *database __attribute__((unused)),
565                  XrmBindingList bindings __attribute__((unused)),
566                  XrmQuarkList quarks,
567                  XrmRepresentation *type __attribute__((unused)),
568                  XrmValue *value,
569                  XPointer closure __attribute__((unused)))
570 {
571   int             last;
572
573   for (last = 0; quarks[last] != NULLQUARK; last++)     /* look for last quark in list */
574     ;
575   last--;
576   GET_R->parse_keysym (XrmQuarkToString (quarks[last]), (char *)value->addr);//D//TODO
577   return False;
578 }
579
580 /*
581  * look for something like this (XK_Delete)
582  * rxvt*keysym.0xFFFF: "\177"
583  *
584  * arg will be
585  *      NULL for ~/.Xdefaults and
586  *      non-NULL for command-line options (need to allocate)
587  */
588 #define NEWARGLIM       500     /* `reasonable' size */
589 int
590 rxvt_term::parse_keysym (const char *str, const char *arg)
591 {
592   int             n, sym;
593   char           *key_string, *newarg = NULL;
594   char            newargstr[NEWARGLIM];
595
596   if (arg == NULL)
597     {
598       if ((n = rxvt_Str_match (str, "keysym.")) == 0)
599         return 0;
600       str += n;         /* skip `keysym.' */
601     }
602   /* some scanf () have trouble with a 0x prefix */
603   if (isdigit (str[0]))
604     {
605       if (str[0] == '0' && toupper (str[1]) == 'X')
606         str += 2;
607       if (arg)
608         {
609           if (sscanf (str, (STRCHR (str, ':') ? "%x:" : "%x"), &sym) != 1)
610             return -1;
611         }
612       else
613         {
614           if (sscanf (str, "%x:", &sym) != 1)
615             return -1;
616
617           /* cue to ':', it's there since sscanf () worked */
618           STRNCPY (newargstr, STRCHR (str, ':') + 1, NEWARGLIM - 1);
619           newargstr[NEWARGLIM - 1] = '\0';
620           newarg = newargstr;
621         }
622     }
623   else
624     {
625       /*
626        * convert keysym name to keysym number
627        */
628       STRNCPY (newargstr, str, NEWARGLIM - 1);
629       newargstr[NEWARGLIM - 1] = '\0';
630       if (arg == NULL)
631         {
632           if ((newarg = STRCHR (newargstr, ':')) == NULL)
633             return -1;
634           *newarg++ = '\0';     /* terminate keysym name */
635         }
636       if ((sym = XStringToKeysym (newargstr)) == None)
637         return -1;
638     }
639
640   if (sym < 0xFF00 || sym > 0xFFFF)     /* we only do extended keys */
641     return -1;
642   sym &= 0xFF;
643   if (Keysym_map[sym] != NULL)  /* already set ? */
644     return -1;
645
646   if (newarg == NULL)
647     {
648       STRNCPY (newargstr, arg, NEWARGLIM - 1);
649       newargstr[NEWARGLIM - 1] = '\0';
650       newarg = newargstr;
651     }
652   rxvt_Str_trim (newarg);
653   if (*newarg == '\0' || (n = rxvt_Str_escaped (newarg)) == 0)
654     return -1;
655   MIN_IT (n, 255);
656   key_string = (char *)rxvt_malloc ((n + 1) * sizeof (char));
657
658   key_string[0] = n;
659   STRNCPY (key_string + 1, newarg, n);
660   Keysym_map[sym] = (unsigned char *)key_string;
661
662   return 1;
663 }
664
665 # endif                         /* KEYSYM_RESOURCE */
666
667 # ifndef USE_XGETDEFAULT
668 /*{{{ rxvt_get_xdefaults () */
669 /*
670  * the matching algorithm used for memory-save fake resources
671  */
672 void
673 rxvt_term::get_xdefaults (FILE *stream, const char *name)
674 {
675   unsigned int    len;
676   char           *str, buffer[256];
677
678   if (stream == NULL)
679     return;
680   len = STRLEN (name);
681   while ((str = fgets (buffer, sizeof (buffer), stream)) != NULL)
682     {
683       unsigned int    entry, n;
684
685       while (*str && isspace (*str))
686         str++;          /* leading whitespace */
687
688       if ((str[len] != '*' && str[len] != '.')
689           || (len && STRNCMP (str, name, len)))
690         continue;
691       str += (len + 1); /* skip `name*' or `name.' */
692
693 # ifdef KEYSYM_RESOURCE
694       if (!parse_keysym (str, NULL))
695 # endif                         /* KEYSYM_RESOURCE */
696         for (entry = 0; entry < optList_size (); entry++)
697           {
698             const char     *kw = optList[entry].kw;
699
700             if (kw == NULL)
701               continue;
702             n = STRLEN (kw);
703             if (str[n] == ':' && rxvt_Str_match (str, kw))
704               {
705                 /* skip `keyword:' */
706                 str += (n + 1);
707                 rxvt_Str_trim (str);
708                 n = STRLEN (str);
709                 if (n && rs[optList[entry].doff] == NULL)
710                   {
711                     /* not already set */
712                     int             s;
713                     char           *p = (char *)rxvt_malloc ((n + 1) * sizeof (char));
714
715                     STRCPY (p, str);
716                     rs[optList[entry].doff] = p;
717                     if (optList_isBool (entry))
718                       {
719                         s = STRCASECMP (str, "TRUE") == 0
720                             || STRCASECMP (str, "YES") == 0
721                             || STRCASECMP (str, "ON") == 0
722                             || STRCASECMP (str, "1") == 0;
723                         if (optList_isReverse (entry))
724                           s = !s;
725                         if (s)
726                           Options |= (optList[entry].flag);
727                         else
728                           Options &= ~ (optList[entry].flag);
729                       }
730                   }
731                 break;
732               }
733           }
734     }
735   rewind (stream);
736 }
737
738 /*}}} */
739 # endif                         /* ! USE_XGETDEFAULT */
740 #endif                          /* NO_RESOURCES */
741
742 /*{{{ read the resources files */
743 /*
744  * using XGetDefault () or the hand-rolled replacement
745  */
746 /* ARGSUSED */
747 void
748 rxvt_term::extract_resources (Display *display __attribute__ ((unused)), const char *name)
749 {
750 #ifndef NO_RESOURCES
751
752 # if defined XAPPLOADDIR
753 #  if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
754   /* Compute the path of the possibly available localized Rxvt file */
755   char           *localepath = NULL;
756
757   if (locale != NULL)
758     {   /* XXX: must limit length of string */
759       localepath = (char *)rxvt_malloc (256);
760       sprintf (localepath, XAPPLOADDIRLOCALE "/" RESCLASS,
761               (int) (258 - sizeof (XAPPLOADDIRLOCALE) - sizeof (RESCLASS)),
762               locale);  /* 258 = 255 + 4 (-.*s) - 1 (/) */
763     }
764
765   {
766 #  endif
767 # endif
768
769 # ifdef USE_XGETDEFAULT
770     /*
771      * get resources using the X library function
772      */
773     int             entry;
774
775 #  ifdef XrmEnumOneLevel
776     int             i;
777     char           *displayResource, *xe;
778     XrmName         name_prefix[3];
779     XrmClass        class_prefix[3];
780     XrmDatabase     database, rdb1;
781     char            fname[1024];
782
783     XrmInitialize ();
784     database = NULL;
785
786     /* Get any Xserver defaults */
787
788     displayResource = XResourceManagerString (display);
789     if (displayResource != NULL)
790       database = XrmGetStringDatabase (displayResource);
791
792 #   ifdef HAVE_EXTRA_XRESOURCE_FILES
793     /* Add in ~/.Xdefaults or ~/.Xresources */
794     {
795       char           *ptr;
796
797       if ((ptr = (char *)getenv ("HOME")) == NULL)
798         ptr = ".";
799
800       for (i = 0; i < (sizeof (xnames) / sizeof (xnames[0])); i++)
801         {
802           sprintf (fname, "%-.*s/%s", sizeof (fname) - STRLEN (xnames[i]) - 2,
803                   ptr, xnames[i]);
804           if ((rdb1 = XrmGetFileDatabase (fname)) != NULL)
805             {
806               XrmMergeDatabases (rdb1, &database);
807 #    ifndef HAVE_BOTH_XRESOURCE_FILES
808               break;
809 #    endif
810
811             }
812         }
813     }
814 #   endif
815
816     /* Add in XENVIRONMENT file */
817
818     if ((xe = (char *)getenv ("XENVIRONMENT")) != NULL
819         && (rdb1 = XrmGetFileDatabase (xe)) != NULL)
820       XrmMergeDatabases (rdb1, &database);
821
822     /* Add in Rxvt file */
823 #   if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
824     if (localepath == NULL || (rdb1 = XrmGetFileDatabase (localepath)) == NULL)
825 #   endif
826       rdb1 = XrmGetFileDatabase (XAPPLOADDIR "/" RESCLASS);
827
828     if (rdb1 != NULL)
829       XrmMergeDatabases (rdb1, &database);
830
831     /* Add in $XAPPLRESDIR/Rxvt only; not bothering with XUSERFILESEARCHPATH */
832     if ((xe = (char *)getenv ("XAPPLRESDIR")) != NULL)
833       {
834         sprintf (fname, "%-.*s/" RESCLASS, sizeof (fname)
835                 - sizeof (RESCLASS) - 2, xe);
836         if ((rdb1 = XrmGetFileDatabase (fname)) != NULL)
837           XrmMergeDatabases (rdb1, &database);
838       }
839
840     XrmSetDatabase (display, database);
841 #  endif
842
843     /*
844      * Query resources for options that affect us
845      */
846     for (entry = 0; entry < optList_size (); entry++)
847       {
848         int             s;
849         char           *p, *p0;
850         const char     *kw = optList[entry].kw;
851
852         if (kw == NULL || rs[optList[entry].doff] != NULL)
853           continue;             /* previously set */
854
855         p = XGetDefault (display, name, kw);
856         p0 = XGetDefault (display, "!INVALIDPROGRAMMENAMEDONTMATCH!", kw);
857         if (p == NULL || (p0 && STRCMP (p, p0) == 0))
858           {
859             p = XGetDefault (display, RESCLASS, kw);
860 #ifdef RESFALLBACK
861             if (p == NULL || (p0 && STRCMP (p, p0) == 0))
862               p = XGetDefault (display, RESFALLBACK, kw);
863 #endif
864           }
865
866         if (p == NULL && p0)
867           p = p0;
868
869         if (p)
870           {
871             rs[optList[entry].doff] = p;
872
873             if (optList_isBool (entry))
874               {
875                 s = STRCASECMP (p, "TRUE") == 0
876                     || STRCASECMP (p, "YES") == 0
877                     || STRCASECMP (p, "ON") == 0
878                     || STRCASECMP (p, "1") == 0;
879                 if (optList_isReverse (entry))
880                   s = !s;
881                 if (s)
882                   Options |= (optList[entry].flag);
883                 else
884                   Options &= ~ (optList[entry].flag);
885               }
886           }
887       }
888
889     /*
890      * [R5 or later]: enumerate the resource database
891      */
892 #  ifdef XrmEnumOneLevel
893 #   ifdef KEYSYM_RESOURCE
894     name_prefix[0] = XrmStringToName (name);
895     name_prefix[1] = XrmStringToName ("keysym");
896     name_prefix[2] = NULLQUARK;
897     class_prefix[0] = XrmStringToName (RESCLASS);
898     class_prefix[1] = XrmStringToName ("Keysym");
899     class_prefix[2] = NULLQUARK;
900     /* XXX: Need to check sizeof (rxvt_t) == sizeof (XPointer) */
901     XrmEnumerateDatabase (XrmGetDatabase (display), name_prefix, class_prefix,
902                           XrmEnumOneLevel, rxvt_define_key, NULL);
903 #    ifdef RESFALLBACK
904     name_prefix[0] = XrmStringToName (RESFALLBACK);
905     name_prefix[1] = XrmStringToName ("keysym");
906     class_prefix[0] = XrmStringToName (RESFALLBACK);
907     class_prefix[1] = XrmStringToName ("Keysym");
908     /* XXX: Need to check sizeof (rxvt_t) == sizeof (XPointer) */
909     XrmEnumerateDatabase (XrmGetDatabase (display), name_prefix, class_prefix,
910                           XrmEnumOneLevel, rxvt_define_key, NULL);
911 #    endif
912 #   endif
913 #  endif
914
915 # else                          /* USE_XGETDEFAULT */
916     /* get resources the hard way, but save lots of memory */
917     FILE           *fd = NULL;
918     char           *home;
919
920     if ((home = getenv ("HOME")) != NULL)
921       {
922         unsigned int    i, len = STRLEN (home) + 2;
923         char           *f = NULL;
924
925         for (i = 0; i < (sizeof (xnames) / sizeof (xnames[0])); i++)
926           {
927             f = (char *)rxvt_realloc (f, (len + STRLEN (xnames[i])) * sizeof (char));
928
929             sprintf (f, "%s/%s", home, xnames[i]);
930
931             if ((fd = fopen (f, "r")) != NULL)
932               break;
933           }
934         free (f);
935       }
936     /*
937     * The normal order to match resources is the following:
938     * @ global resources (partial match, ~/.Xdefaults)
939     * @ application file resources (XAPPLOADDIR/Rxvt)
940     * @ class resources (~/.Xdefaults)
941     * @ private resources (~/.Xdefaults)
942     *
943     * However, for the hand-rolled resources, the matching algorithm
944     * checks if a resource string value has already been allocated
945     * and won't overwrite it with (in this case) a less specific
946     * resource value.
947     *
948     * This avoids multiple allocation.  Also, when we've called this
949     * routine command-line string options have already been applied so we
950     * needn't to allocate for those resources.
951     *
952     * So, search in resources from most to least specific.
953     *
954     * Also, use a special sub-class so that we can use either or both of
955     * "XTerm" and "Rxvt" as class names.
956     */
957
958     get_xdefaults (fd, name);
959     get_xdefaults (fd, RESCLASS);
960 #  ifdef RESFALLBACK
961     get_xdefaults (fd, RESFALLBACK);
962 #  endif
963
964 #  if defined(XAPPLOADDIR) && defined(USE_XAPPLOADDIR)
965
966     {
967       FILE           *ad = NULL;
968
969 #   if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
970       if (localepath == NULL || (ad = fopen (localepath, "r")) == NULL)
971 #   endif
972         ad = fopen (XAPPLOADDIR "/" RESCLASS, "r");
973       if (ad != NULL)
974         {
975           get_xdefaults (ad, RESCLASS);
976           get_xdefaults (ad, "");
977           fclose (ad);
978         }
979     }
980 #  endif                        /* XAPPLOADDIR */
981
982     get_xdefaults (fd, "");     /* partial match */
983     if (fd != NULL)
984       fclose (fd);
985 # endif                         /* USE_XGETDEFAULT */
986
987 # if defined XAPPLOADDIR
988 #  if defined(HAVE_XSETLOCALE) || defined(HAVE_SETLOCALE)
989
990   }
991
992   /* Free the path of the possibly available localized Rxvt file */
993   free (localepath);
994 #  endif
995 # endif
996
997 #endif                          /* NO_RESOURCES */
998
999   /*
1000    * even without resources, at least do this setup for command-line
1001    * options and command-line long options
1002    */
1003
1004 #if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
1005   KeySym          sym;
1006
1007   if (rs[Rs_bigfont_key]
1008       && ((sym = XStringToKeysym (rs[Rs_bigfont_key])) != 0))
1009     ks_bigfont = sym;
1010   if (rs[Rs_smallfont_key]
1011       && ((sym = XStringToKeysym (rs[Rs_smallfont_key])) != 0))
1012     ks_smallfont = sym;
1013 #endif
1014 }
1015
1016 /*}}} */
1017 /*----------------------- end-of-file (C source) -----------------------*/