(menu_face_change_count): New variable.
[bpt/emacs.git] / src / xrdb.c
CommitLineData
f3a0bf5c 1/* Deal with the X Resource Manager.
3a22ee35 2 Copyright (C) 1990, 1993, 1994 Free Software Foundation.
f3a0bf5c 3
3b7ad313
EN
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
f3a0bf5c 7it under the terms of the GNU General Public License as published by
d4327fec 8the Free Software Foundation; either version 2, or (at your option)
f3a0bf5c
JB
9any later version.
10
3b7ad313 11GNU Emacs is distributed in the hope that it will be useful,
f3a0bf5c
JB
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
3b7ad313
EN
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
f3a0bf5c
JB
20
21/* Written by jla, 4/90 */
22
a2a4d43e 23#ifdef emacs
18160b98 24#include <config.h>
a2a4d43e
JB
25#endif
26
dfcf069d
AS
27#ifdef HAVE_UNISTD_H
28#include <unistd.h>
29#endif
30
57bda87a 31#include <epaths.h>
012c3e71 32
837255fb
JB
33#include <stdio.h>
34
a2a4d43e
JB
35#if 1 /* I'd really appreciate it if this code could go away... -JimB */
36/* this avoids lossage in the `dual-universe' headers on AT&T SysV X11 */
37#ifdef USG5
8f510a71 38#ifndef SYSV
a2a4d43e 39#define SYSV
8f510a71 40#endif
a2a4d43e
JB
41#endif /* USG5 */
42
43#endif /* 1 */
54c908b5 44
f3a0bf5c
JB
45#include <X11/Xlib.h>
46#include <X11/Xatom.h>
dfc35f5f 47#if 0
f3a0bf5c 48#include <X11/Xos.h>
dfc35f5f 49#endif
f3a0bf5c
JB
50#include <X11/X.h>
51#include <X11/Xutil.h>
52#include <X11/Xresource.h>
531ff254
JB
53#ifdef VMS
54#include "vms-pwd.h"
55#else
f3a0bf5c 56#include <pwd.h>
531ff254 57#endif
f3a0bf5c
JB
58#include <sys/stat.h>
59
0f2cd61f
RS
60#if !defined(S_ISDIR) && defined(S_IFDIR)
61#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
62#endif
63
4da4f201
GM
64#include "lisp.h"
65
f3a0bf5c 66extern char *getenv ();
3d5d61ae
JB
67
68/* This does cause trouble on AIX. I'm going to take the comment at
69 face value. */
70#if 0
dfc35f5f
JB
71extern short getuid (); /* If this causes portability problems,
72 I think we should just delete it; it'll
73 default to `int' anyway. */
3d5d61ae
JB
74#endif
75
2d487ae5 76#ifdef DECLARE_GETPWUID_WITH_UID_T
3e0be4d0
RS
77extern struct passwd *getpwuid (uid_t);
78extern struct passwd *getpwnam (const char *);
79#else
f3a0bf5c
JB
80extern struct passwd *getpwuid ();
81extern struct passwd *getpwnam ();
3e0be4d0 82#endif
f3a0bf5c 83
e29ad342
KH
84extern char *get_system_name ();
85
837255fb
JB
86/* Make sure not to #include anything after these definitions. Let's
87 not step on anyone's prototypes. */
88#ifdef emacs
89#define malloc xmalloc
90#define realloc xrealloc
91#define free xfree
92#endif
93
94char *x_get_string_resource ();
95static int file_p ();
96
97\f
98/* X file search path processing. */
99
100
101/* The string which gets substituted for the %C escape in XFILESEARCHPATH
102 and friends, or zero if none was specified. */
103char *x_customization_string;
104
105
106/* Return the value of the emacs.customization (Emacs.Customization)
107 resource, for later use in search path decoding. If we find no
108 such resource, return zero. */
109char *
110x_get_customization_string (db, name, class)
111 XrmDatabase db;
112 char *name, *class;
113{
114 char *full_name
115 = (char *) alloca (strlen (name) + sizeof ("customization") + 3);
116 char *full_class
117 = (char *) alloca (strlen (class) + sizeof ("Customization") + 3);
118 char *result;
119
120 sprintf (full_name, "%s.%s", name, "customization");
121 sprintf (full_class, "%s.%s", class, "Customization");
122
123 result = x_get_string_resource (db, full_name, full_class);
124
125 if (result)
abfc2e5f
RS
126 {
127 char *copy = (char *) malloc (strlen (result) + 1);
128 strcpy (copy, result);
129 return copy;
130 }
837255fb
JB
131 else
132 return 0;
133}
134
135
136/* Expand all the Xt-style %-escapes in STRING, whose length is given
137 by STRING_LEN. Here are the escapes we're supposed to recognize:
138
139 %N The value of the application's class name
140 %T The value of the type parameter ("app-defaults" in this
141 context)
142 %S The value of the suffix parameter ("" in this context)
143 %L The language string associated with the specified display
144 (We use the "LANG" environment variable here, if it's set.)
145 %l The language part of the display's language string
146 (We treat this just like %L. If someone can tell us what
147 we're really supposed to do, dandy.)
148 %t The territory part of the display's language string
149 (This never gets used.)
150 %c The codeset part of the display's language string
151 (This never gets used either.)
152 %C The customization string retrieved from the resource
153 database associated with display.
154 (This is x_customization_string.)
155
156 Return the expanded file name if it exists and is readable, and
157 refers to %L only when the LANG environment variable is set, or
158 otherwise provided by X.
159
160 ESCAPED_SUFFIX and SUFFIX are postpended to STRING if they are
161 non-zero. %-escapes in ESCAPED_SUFFIX are expanded; STRING is left
162 alone.
163
164 Return NULL otherwise. */
165
166static char *
167magic_file_p (string, string_len, class, escaped_suffix, suffix)
168 char *string;
169 int string_len;
170 char *class, *escaped_suffix, *suffix;
171{
172 char *lang = getenv ("LANG");
173
174 int path_size = 100;
175 char *path = (char *) malloc (path_size);
176 int path_len = 0;
177
178 char *p = string;
179
180 while (p < string + string_len)
181 {
182 /* The chunk we're about to stick on the end of result. */
6bbd7a29 183 char *next = NULL;
837255fb
JB
184 int next_len;
185
186 if (*p == '%')
187 {
188 p++;
189
190 if (p >= string + string_len)
191 next_len = 0;
192 else
193 switch (*p)
194 {
195 case '%':
196 next = "%";
197 next_len = 1;
198 break;
199
200 case 'C':
201 next = (x_customization_string
202 ? x_customization_string
203 : "");
204 next_len = strlen (next);
205 break;
206
207 case 'N':
208 next = class;
209 next_len = strlen (class);
210 break;
211
212 case 'T':
213 next = "app-defaults";
214 next_len = strlen (next);
215 break;
216
217 default:
218 case 'S':
219 next_len = 0;
220 break;
221
222 case 'L':
223 case 'l':
224 if (! lang)
225 {
226 free (path);
227 return NULL;
228 }
427ec082 229
837255fb
JB
230 next = lang;
231 next_len = strlen (next);
232 break;
427ec082 233
837255fb
JB
234 case 't':
235 case 'c':
236 free (path);
237 return NULL;
238 }
239 }
240 else
241 next = p, next_len = 1;
242
243 /* Do we have room for this component followed by a '\0' ? */
244 if (path_len + next_len + 1 > path_size)
245 {
246 path_size = (path_len + next_len + 1) * 2;
247 path = (char *) realloc (path, path_size);
248 }
427ec082 249
837255fb
JB
250 bcopy (next, path + path_len, next_len);
251 path_len += next_len;
252
253 p++;
254
255 /* If we've reached the end of the string, append ESCAPED_SUFFIX. */
256 if (p >= string + string_len && escaped_suffix)
257 {
258 string = escaped_suffix;
259 string_len = strlen (string);
260 p = string;
261 escaped_suffix = NULL;
262 }
263 }
264
265 /* Perhaps we should add the SUFFIX now. */
266 if (suffix)
267 {
268 int suffix_len = strlen (suffix);
269
270 if (path_len + suffix_len + 1 > path_size)
271 {
272 path_size = (path_len + suffix_len + 1);
273 path = (char *) realloc (path, path_size);
274 }
275
276 bcopy (suffix, path + path_len, suffix_len);
277 path_len += suffix_len;
278 }
279
280 path[path_len] = '\0';
281
282 if (! file_p (path))
283 {
284 free (path);
285 return NULL;
286 }
287
288 return path;
289}
290
291
f3a0bf5c 292static char *
837255fb 293gethomedir ()
f3a0bf5c 294{
f3a0bf5c
JB
295 struct passwd *pw;
296 char *ptr;
837255fb 297 char *copy;
f3a0bf5c
JB
298
299 if ((ptr = getenv ("HOME")) == NULL)
300 {
1cac1f6f
KH
301 if ((ptr = getenv ("LOGNAME")) != NULL
302 || (ptr = getenv ("USER")) != NULL)
f3a0bf5c
JB
303 pw = getpwnam (ptr);
304 else
1cac1f6f 305 pw = getpwuid (getuid ());
837255fb 306
f3a0bf5c
JB
307 if (pw)
308 ptr = pw->pw_dir;
f3a0bf5c
JB
309 }
310
427ec082 311 if (ptr == NULL)
837255fb 312 return "/";
f3a0bf5c 313
837255fb
JB
314 copy = (char *) malloc (strlen (ptr) + 2);
315 strcpy (copy, ptr);
316 strcat (copy, "/");
f3a0bf5c 317
837255fb 318 return copy;
f3a0bf5c
JB
319}
320
837255fb 321
f3a0bf5c
JB
322static int
323file_p (path)
324 char *path;
325{
326 struct stat status;
327
dfc35f5f 328 return (access (path, 4) == 0 /* exists and is readable */
f3a0bf5c 329 && stat (path, &status) == 0 /* get the status */
0f2cd61f 330 && (S_ISDIR (status.st_mode)) == 0); /* not a directory */
f3a0bf5c
JB
331}
332
f3a0bf5c 333
837255fb 334/* Find the first element of SEARCH_PATH which exists and is readable,
427ec082 335 after expanding the %-escapes. Return 0 if we didn't find any, and
837255fb 336 the path name of the one we found otherwise. */
f3a0bf5c 337
837255fb
JB
338static char *
339search_magic_path (search_path, class, escaped_suffix, suffix)
340 char *search_path, *class, *escaped_suffix, *suffix;
f3a0bf5c 341{
837255fb 342 register char *s, *p;
d4327fec 343
837255fb 344 for (s = search_path; *s; s = p)
f3a0bf5c 345 {
837255fb
JB
346 for (p = s; *p && *p != ':'; p++)
347 ;
427ec082 348
0f2cd61f 349 if (p > s)
f3a0bf5c 350 {
0f2cd61f 351 char *path = magic_file_p (s, p - s, class, escaped_suffix, suffix);
837255fb
JB
352 if (path)
353 return path;
f3a0bf5c 354 }
0f2cd61f 355 else if (*p == ':')
f3a0bf5c 356 {
0f2cd61f
RS
357 char *path;
358
359 s = "%N%S";
360 path = magic_file_p (s, strlen (s), class, escaped_suffix, suffix);
837255fb
JB
361 if (path)
362 return path;
f3a0bf5c
JB
363 }
364
837255fb
JB
365 if (*p == ':')
366 p++;
f3a0bf5c
JB
367 }
368
369 return 0;
370}
371\f
837255fb
JB
372/* Producing databases for individual sources. */
373
f3a0bf5c
JB
374static XrmDatabase
375get_system_app (class)
376 char *class;
377{
837255fb
JB
378 XrmDatabase db = NULL;
379 char *path;
f3a0bf5c 380
837255fb 381 path = getenv ("XFILESEARCHPATH");
58c7da0c 382 if (! path) path = PATH_X_DEFAULTS;
f3a0bf5c 383
837255fb
JB
384 path = search_magic_path (path, class, 0, 0);
385 if (path)
386 {
387 db = XrmGetFileDatabase (path);
388 free (path);
389 }
f3a0bf5c 390
f3a0bf5c
JB
391 return db;
392}
393
837255fb 394
f3a0bf5c
JB
395static XrmDatabase
396get_fallback (display)
397 Display *display;
398{
f3a0bf5c
JB
399 return NULL;
400}
401
837255fb 402
f3a0bf5c
JB
403static XrmDatabase
404get_user_app (class)
405 char *class;
406{
837255fb
JB
407 char *path;
408 char *file = 0;
3fa18fb2 409 char *free_it = 0;
837255fb
JB
410
411 /* Check for XUSERFILESEARCHPATH. It is a path of complete file
412 names, not directories. */
413 if (((path = getenv ("XUSERFILESEARCHPATH"))
414 && (file = search_magic_path (path, class, 0, 0)))
415
416 /* Check for APPLRESDIR; it is a path of directories. In each,
417 we have to search for LANG/CLASS and then CLASS. */
418 || ((path = getenv ("XAPPLRESDIR"))
419 && ((file = search_magic_path (path, class, "/%L/%N", 0))
420 || (file = search_magic_path (path, class, "/%N", 0))))
427ec082 421
837255fb
JB
422 /* Check in the home directory. This is a bit of a hack; let's
423 hope one's home directory doesn't contain any %-escapes. */
3fa18fb2
RS
424 || (free_it = gethomedir (),
425 ((file = search_magic_path (free_it, class, "%L/%N", 0))
426 || (file = search_magic_path (free_it, class, "%N", 0)))))
f3a0bf5c 427 {
837255fb
JB
428 XrmDatabase db = XrmGetFileDatabase (file);
429 free (file);
3fa18fb2
RS
430 if (free_it)
431 free (free_it);
837255fb 432 return db;
f3a0bf5c 433 }
3fa18fb2
RS
434
435 if (free_it)
436 free (free_it);
437 return NULL;
f3a0bf5c
JB
438}
439
837255fb 440
f3a0bf5c
JB
441static XrmDatabase
442get_user_db (display)
443 Display *display;
444{
445 XrmDatabase db;
446 char *xdefs;
447
2c8d1900 448#ifdef PBaseSize /* Cheap way to test for X11R4 or later. */
b631f177
JB
449 xdefs = XResourceManagerString (display);
450#else
a2a4d43e 451 xdefs = display->xdefaults;
b631f177
JB
452#endif
453
f3a0bf5c
JB
454 if (xdefs != NULL)
455 db = XrmGetStringDatabase (xdefs);
456 else
457 {
837255fb
JB
458 char *home;
459 char *xdefault;
f3a0bf5c 460
837255fb
JB
461 home = gethomedir ();
462 xdefault = (char *) malloc (strlen (home) + sizeof (".Xdefaults"));
463 strcpy (xdefault, home);
f3a0bf5c
JB
464 strcat (xdefault, ".Xdefaults");
465 db = XrmGetFileDatabase (xdefault);
837255fb
JB
466 free (home);
467 free (xdefault);
f3a0bf5c
JB
468 }
469
d8717d15 470#ifdef HAVE_XSCREENRESOURCESTRING
9b37b1c2
JB
471 /* Get the screen-specific resources too. */
472 xdefs = XScreenResourceString (DefaultScreenOfDisplay (display));
473 if (xdefs != NULL)
fdce0b39
JB
474 {
475 XrmMergeDatabases (XrmGetStringDatabase (xdefs), &db);
476 XFree (xdefs);
477 }
9b37b1c2
JB
478#endif
479
f3a0bf5c
JB
480 return db;
481}
482
483static XrmDatabase
484get_environ_db ()
485{
486 XrmDatabase db;
487 char *p;
e29ad342 488 char *path = 0, *home = 0, *host;
f3a0bf5c
JB
489
490 if ((p = getenv ("XENVIRONMENT")) == NULL)
491 {
837255fb 492 home = gethomedir ();
e29ad342 493 host = get_system_name ();
837255fb
JB
494 path = (char *) malloc (strlen (home)
495 + sizeof (".Xdefaults-")
496 + strlen (host));
497 sprintf (path, "%s%s%s", home, ".Xdefaults-", host);
f3a0bf5c
JB
498 p = path;
499 }
500
501 db = XrmGetFileDatabase (p);
837255fb
JB
502
503 if (path) free (path);
504 if (home) free (home);
837255fb 505
f3a0bf5c
JB
506 return db;
507}
508\f
837255fb
JB
509/* External interface. */
510
f3a0bf5c
JB
511/* Types of values that we can find in a database */
512
513#define XrmStringType "String" /* String representation */
514XrmRepresentation x_rm_string; /* Quark representation */
515
516/* Load X resources based on the display and a possible -xrm option. */
517
518XrmDatabase
837255fb 519x_load_resources (display, xrm_string, myname, myclass)
f3a0bf5c 520 Display *display;
837255fb 521 char *xrm_string, *myname, *myclass;
f3a0bf5c 522{
837255fb 523 XrmDatabase user_database;
f3a0bf5c
JB
524 XrmDatabase rdb;
525 XrmDatabase db;
4da4f201
GM
526 char line[256];
527 char *helv = "-*-helvetica-medium-r-*--*-120-*-*-*-*-iso8859-1";
8d56e206 528#ifdef USE_MOTIF
4da4f201
GM
529 char *courier = "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1";
530 extern Lisp_Object Vdouble_click_time;
8d56e206 531#endif
f3a0bf5c
JB
532
533 x_rm_string = XrmStringToQuark (XrmStringType);
082dc211
RS
534#ifndef USE_X_TOOLKIT
535 /* pmr@osf.org says this shouldn't be done if USE_X_TOOLKIT.
536 I suspect it's because the toolkit version does this elsewhere. */
f3a0bf5c 537 XrmInitialize ();
082dc211 538#endif
f3a0bf5c
JB
539 rdb = XrmGetStringDatabase ("");
540
4da4f201
GM
541 /* Add some font defaults. If the font `helv' doesn't exist, widgets
542 will use some other default font. */
543#ifdef USE_MOTIF
427ec082 544
06bbf618
GM
545 sprintf (line, "%s.pane.background: grey75", myname);
546 XrmPutLineResource (&rdb, line);
4da4f201
GM
547 sprintf (line, "%s*fontList: %s", myname, helv);
548 XrmPutLineResource (&rdb, line);
549 sprintf (line, "%s*menu*background: grey75", myname);
550 XrmPutLineResource (&rdb, line);
551 sprintf (line, "%s*menubar*background: grey75", myname, helv);
552 XrmPutLineResource (&rdb, line);
553 sprintf (line, "%s*verticalScrollBar.background: grey75", myname);
554 XrmPutLineResource (&rdb, line);
06bbf618
GM
555 sprintf (line, "%s*verticalScrollBar.troughColor: grey75", myname);
556 XrmPutLineResource (&rdb, line);
4da4f201
GM
557 sprintf (line, "%s.dialog*.background: grey75", myname);
558 XrmPutLineResource (&rdb, line);
559 sprintf (line, "%s*fsb.Text.background: white", myname);
560 XrmPutLineResource (&rdb, line);
561 sprintf (line, "%s*fsb.FilterText.background: white", myname);
562 XrmPutLineResource (&rdb, line);
563 sprintf (line, "%s*fsb*DirList.background: white", myname);
564 XrmPutLineResource (&rdb, line);
565 sprintf (line, "%s*fsb*ItemsList.background: white", myname);
566 XrmPutLineResource (&rdb, line);
567 sprintf (line, "%s*fsb*background: grey75", myname);
568 XrmPutLineResource (&rdb, line);
569 sprintf (line, "%s*fsb.Text.fontList: %s", myname, courier);
570 XrmPutLineResource (&rdb, line);
571 sprintf (line, "%s*fsb.FilterText.fontList: %s", myname, courier);
572 XrmPutLineResource (&rdb, line);
573 sprintf (line, "%s*fsb*ItemsList.fontList: %s", myname, courier);
574 XrmPutLineResource (&rdb, line);
575 sprintf (line, "%s*fsb*DirList.fontList: %s", myname, courier);
576 XrmPutLineResource (&rdb, line);
577
578 /* Set double click time of list boxes in the file selection
579 dialog from `double-click-time'. */
580 if (INTEGERP (Vdouble_click_time) && XINT (Vdouble_click_time) > 0)
581 {
582 sprintf (line, "%s*fsb*DirList.doubleClickInterval: %d",
583 myname, XFASTINT (Vdouble_click_time));
584 XrmPutLineResource (&rdb, line);
585 sprintf (line, "%s*fsb*ItemsList.doubleClickInterval: %d",
586 myname, XFASTINT (Vdouble_click_time));
587 XrmPutLineResource (&rdb, line);
588 }
589
590#else /* not USE_MOTIF */
427ec082 591
fc6c5dfe 592 sprintf (line, "Emacs.dialog*.font: %s", helv);
4da4f201 593 XrmPutLineResource (&rdb, line);
fc6c5dfe 594 sprintf (line, "Emacs.dialog*.background: grey75");
4da4f201 595 XrmPutLineResource (&rdb, line);
fc6c5dfe 596 sprintf (line, "*XlwMenu*font: %s", helv);
4da4f201 597 XrmPutLineResource (&rdb, line);
fc6c5dfe 598 sprintf (line, "*XlwMenu*background: grey75");
4da4f201 599 XrmPutLineResource (&rdb, line);
fc6c5dfe 600 sprintf (line, "Emacs*verticalScrollBar.background: grey75");
4da4f201 601 XrmPutLineResource (&rdb, line);
427ec082 602
4da4f201
GM
603#endif /* not USE_MOTIF */
604
837255fb
JB
605 user_database = get_user_db (display);
606
607 /* Figure out what the "customization string" is, so we can use it
608 to decode paths. */
609 if (x_customization_string)
610 free (x_customization_string);
611 x_customization_string
612 = x_get_customization_string (user_database, myname, myclass);
613
f3a0bf5c
JB
614 /* Get application system defaults */
615 db = get_system_app (myclass);
616 if (db != NULL)
617 XrmMergeDatabases (db, &rdb);
618
619 /* Get Fallback resources */
620 db = get_fallback (display);
621 if (db != NULL)
622 XrmMergeDatabases (db, &rdb);
623
624 /* Get application user defaults */
625 db = get_user_app (myclass);
626 if (db != NULL)
627 XrmMergeDatabases (db, &rdb);
628
629 /* get User defaults */
837255fb
JB
630 if (user_database != NULL)
631 XrmMergeDatabases (user_database, &rdb);
f3a0bf5c
JB
632
633 /* Get Environment defaults. */
634 db = get_environ_db ();
635 if (db != NULL)
636 XrmMergeDatabases (db, &rdb);
427ec082 637
f3a0bf5c
JB
638 /* Last, merge in any specification from the command line. */
639 if (xrm_string != NULL)
640 {
641 db = XrmGetStringDatabase (xrm_string);
642 if (db != NULL)
643 XrmMergeDatabases (db, &rdb);
644 }
645
646 return rdb;
647}
648
837255fb 649
f3a0bf5c
JB
650/* Retrieve the value of the resource specified by NAME with class CLASS
651 and of type TYPE from database RDB. The value is returned in RET_VALUE. */
652
653int
654x_get_resource (rdb, name, class, expected_type, ret_value)
655 XrmDatabase rdb;
656 char *name, *class;
657 XrmRepresentation expected_type;
658 XrmValue *ret_value;
659{
660 XrmValue value;
661 XrmName namelist[100];
662 XrmClass classlist[100];
663 XrmRepresentation type;
664
665 XrmStringToNameList(name, namelist);
666 XrmStringToClassList(class, classlist);
667
668 if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
669 && (type == expected_type))
670 {
671 if (type == x_rm_string)
41ab0754 672 ret_value->addr = (char *) value.addr;
f3a0bf5c
JB
673 else
674 bcopy (value.addr, ret_value->addr, ret_value->size);
675
676 return value.size;
677 }
678
679 return 0;
680}
681
682/* Retrieve the string resource specified by NAME with CLASS from
683 database RDB. */
684
685char *
686x_get_string_resource (rdb, name, class)
687 XrmDatabase rdb;
688 char *name, *class;
689{
690 XrmValue value;
691
692 if (x_get_resource (rdb, name, class, x_rm_string, &value))
693 return (char *) value.addr;
694
695 return (char *) 0;
696}
697\f
837255fb
JB
698/* Stand-alone test facilities. */
699
f3a0bf5c 700#ifdef TESTRM
837255fb
JB
701
702typedef char **List;
703#define arg_listify(len, list) (list)
704#define car(list) (*(list))
705#define cdr(list) (list + 1)
706#define NIL(list) (! *(list))
707#define free_arglist(list)
708
709static List
710member (elt, list)
711 char *elt;
712 List list;
713{
714 List p;
715
716 for (p = list; ! NIL (p); p = cdr (p))
717 if (! strcmp (elt, car (p)))
718 return p;
719
720 return p;
721}
f3a0bf5c
JB
722
723static void
724fatal (msg, prog, x1, x2, x3, x4, x5)
725 char *msg, *prog;
726 int x1, x2, x3, x4, x5;
727{
728 extern int errno;
729
730 if (errno)
731 perror (prog);
732
733 (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
734 exit (1);
735}
736
737main (argc, argv)
738 int argc;
739 char **argv;
740{
741 Display *display;
837255fb 742 char *displayname, *resource_string, *class, *name;
f3a0bf5c 743 XrmDatabase xdb;
837255fb 744 List arg_list, lp;
f3a0bf5c
JB
745
746 arg_list = arg_listify (argc, argv);
747
748 lp = member ("-d", arg_list);
749 if (!NIL (lp))
750 displayname = car (cdr (lp));
751 else
752 displayname = "localhost:0.0";
753
754 lp = member ("-xrm", arg_list);
755 if (! NIL (lp))
756 resource_string = car (cdr (lp));
757 else
758 resource_string = (char *) 0;
759
760 lp = member ("-c", arg_list);
761 if (! NIL (lp))
762 class = car (cdr (lp));
763 else
764 class = "Emacs";
765
837255fb
JB
766 lp = member ("-n", arg_list);
767 if (! NIL (lp))
768 name = car (cdr (lp));
769 else
770 name = "emacs";
f3a0bf5c 771
837255fb 772 free_arglist (arg_list);
f3a0bf5c
JB
773
774 if (!(display = XOpenDisplay (displayname)))
775 fatal ("Can't open display '%s'\n", XDisplayName (displayname));
776
837255fb 777 xdb = x_load_resources (display, resource_string, name, class);
f3a0bf5c 778
f3a0bf5c
JB
779 /* In a real program, you'd want to also do this: */
780 display->db = xdb;
f3a0bf5c
JB
781
782 while (1)
783 {
837255fb
JB
784 char query_name[90];
785 char query_class[90];
786
787 printf ("Name: ");
788 gets (query_name);
f3a0bf5c 789
837255fb 790 if (strlen (query_name))
f3a0bf5c 791 {
837255fb
JB
792 char *value;
793
794 printf ("Class: ");
795 gets (query_class);
796
797 value = x_get_string_resource (xdb, query_name, query_class);
f3a0bf5c
JB
798
799 if (value != NULL)
837255fb 800 printf ("\t%s(%s): %s\n\n", query_name, query_class, value);
f3a0bf5c
JB
801 else
802 printf ("\tNo Value.\n\n");
803 }
804 else
805 break;
806 }
807 printf ("\tExit.\n\n");
808
809 XCloseDisplay (display);
810}
811#endif /* TESTRM */