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