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