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