(Fget_buffer_process): Delete doc string from
[bpt/emacs.git] / src / xrdb.c
CommitLineData
f3a0bf5c 1/* Deal with the X Resource Manager.
c6c5df7f 2 Copyright (C) 1990, 1993 Free Software Foundation.
f3a0bf5c
JB
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
d4327fec 6the Free Software Foundation; either version 2, or (at your option)
f3a0bf5c
JB
7any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; see the file COPYING. If not, write to
16the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18/* Written by jla, 4/90 */
19
a2a4d43e
JB
20#ifdef emacs
21#include "config.h"
22#endif
23
24#if 1 /* I'd really appreciate it if this code could go away... -JimB */
25/* this avoids lossage in the `dual-universe' headers on AT&T SysV X11 */
26#ifdef USG5
27#define SYSV
28#include <unistd.h>
29#endif /* USG5 */
30
31#endif /* 1 */
54c908b5
JB
32
33/* This should be included before the X include files; otherwise, we get
34 warnings about redefining NULL under BSD 4.3. */
35#include <sys/param.h>
36
f3a0bf5c
JB
37#include <X11/Xlib.h>
38#include <X11/Xatom.h>
dfc35f5f 39#if 0
f3a0bf5c 40#include <X11/Xos.h>
dfc35f5f 41#endif
f3a0bf5c
JB
42#include <X11/X.h>
43#include <X11/Xutil.h>
44#include <X11/Xresource.h>
531ff254
JB
45#ifdef VMS
46#include "vms-pwd.h"
47#else
f3a0bf5c 48#include <pwd.h>
531ff254 49#endif
f3a0bf5c
JB
50#include <sys/stat.h>
51
a2a4d43e
JB
52#ifndef MAXPATHLEN
53#define MAXPATHLEN 256
f3a0bf5c
JB
54#endif
55
56extern char *getenv ();
3d5d61ae
JB
57
58/* This does cause trouble on AIX. I'm going to take the comment at
59 face value. */
60#if 0
dfc35f5f
JB
61extern short getuid (); /* If this causes portability problems,
62 I think we should just delete it; it'll
63 default to `int' anyway. */
3d5d61ae
JB
64#endif
65
3e0be4d0
RS
66#ifdef __bsdi__
67extern struct passwd *getpwuid (uid_t);
68extern struct passwd *getpwnam (const char *);
69#else
f3a0bf5c
JB
70extern struct passwd *getpwuid ();
71extern struct passwd *getpwnam ();
3e0be4d0 72#endif
f3a0bf5c
JB
73
74static char *
75gethomedir (dirname)
76 char *dirname;
77{
78 int uid;
79 struct passwd *pw;
80 char *ptr;
81
82 if ((ptr = getenv ("HOME")) == NULL)
83 {
84 if ((ptr = getenv ("USER")) != NULL)
85 pw = getpwnam (ptr);
86 else
87 {
88 uid = getuid ();
89 pw = getpwuid (uid);
90 }
91 if (pw)
92 ptr = pw->pw_dir;
93 else
94 {
95 ptr = NULL;
96 *dirname = '\0';
97 }
98 }
99
100 if (ptr != NULL)
101 strcpy (dirname, ptr);
102
103 dirname += strlen (dirname);
104 *dirname = '/';
105 dirname++;
106 *dirname = '\0';
107
108 return dirname;
109}
110
111static int
112file_p (path)
113 char *path;
114{
115 struct stat status;
116
dfc35f5f 117 return (access (path, 4) == 0 /* exists and is readable */
f3a0bf5c
JB
118 && stat (path, &status) == 0 /* get the status */
119 && (status.st_mode & S_IFDIR) == 0); /* not a directory */
120}
121
122#if 0
123#define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/"
124#endif
125
126/* Isn't this just disgusting? */
127
128#define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/%L/%T/%N%S:/usr/lib/X11/%l/%T/%N%S:/usr/lib/X11/%T/%N%S"
129
130static int
131decode_magic (string, file, return_path)
132 char *string, *file, *return_path;
133{
134 char *p = string;
135 char *t = return_path;
136
137 while (*p)
138 {
139 if (*p == '%')
140 switch (*++p)
141 {
142 case '%':
143 *t++ = '%';
144 p++;
145 break;
146
147 case 'N':
148 case 'T':
149 case 'S':
150 case 'L':
151 case 'l':
152 case 't':
153 case 'c':
154 default:
155 p++;
156 if (*t == '/' && *p == '/')
157 p++;
158 break;
159 }
160 else
161 *t++ = *p++;
162 }
163 *t = '\0';
164 strcat (return_path, file);
165
166 if (file_p (return_path))
167 return 1;
168
169 return_path[0] = '\0';
170 return 0;
171}
172
173static int
174magic_searchpath_decoder (incantation_string, file, return_path)
175 char *incantation_string, *return_path, *file;
176{
177 register char *s = incantation_string;
178 register char *p;
d4327fec
JB
179
180 /* Must be big enough for "%N%S". */
181 register int string_size = MAXPATHLEN;
182 register char *string = (char *) alloca (string_size * sizeof (*string));
f3a0bf5c
JB
183
184 while (*s)
185 {
186 p = s;
187
188 while (*p && *p != ':')
189 p++;
190
191 if (*p == ':' && *(p + 1) == ':')
192 {
d4327fec 193 /* We know string is big enough for this. */
f3a0bf5c
JB
194 bcopy ("%N%S", string, 5);
195 if (decode_magic (string, file, return_path))
196 return 1;
197
198 s = p + 1;
199 continue;
200 }
201
202 if (p > s)
203 {
204 int len = p - s;
205
d4327fec
JB
206 if (string_size < len+1)
207 {
208 string_size = 2 * len;
209 string = (char *) alloca (string_size * sizeof (*string));
210 }
f3a0bf5c 211 bcopy (s, string, len);
44bbb3e0 212 string[len] = '\0';
f3a0bf5c
JB
213 if (decode_magic (string, file, return_path))
214 return 1;
215 }
216
44bbb3e0 217 if (p && *p != 0)
f3a0bf5c
JB
218 s = p + 1;
219 else
220 return 0;
221 }
222
223 return 0;
224}
225\f
226static XrmDatabase
227get_system_app (class)
228 char *class;
229{
230 XrmDatabase db;
231 char path[MAXPATHLEN];
232 char *p;
233
234 if ((p = getenv ("XFILESEARCHPATH")) == NULL)
235 p = X_DEFAULT_SEARCH_PATH;
236
237 if (! magic_searchpath_decoder (p, class, path))
238 return NULL;
239
240 db = XrmGetFileDatabase (path);
241 return db;
242}
243
244static XrmDatabase
245get_fallback (display)
246 Display *display;
247{
248 XrmDatabase db;
249
250 return NULL;
251}
252
253static XrmDatabase
254get_user_app (class)
255 char *class;
256{
257 XrmDatabase db;
258 char *magic_path;
259 char path[MAXPATHLEN];
260
261 if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL)
262 {
263 char homedir[MAXPATHLEN];
264 char *default_magic;
265 char *p;
266
267 gethomedir (homedir);
268
269 if ((p = getenv ("XAPPLRESDIR")) == NULL)
270 {
271 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
272 magic_path = (char *) alloca ((3 * strlen (homedir))
273 + strlen (default_magic));
274 sprintf (magic_path, default_magic, homedir, homedir, homedir);
275 }
276 else
277 {
278 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
279 magic_path = (char *) alloca ((3 * strlen (p))
280 + strlen (default_magic)
281 + strlen (homedir));
282 sprintf (magic_path, default_magic, p, p, p, homedir);
283 }
284 }
285
286 if (! magic_searchpath_decoder (magic_path, class, path))
287 return NULL;
288
289 db = XrmGetFileDatabase (path);
290 return db;
291}
292
293static XrmDatabase
294get_user_db (display)
295 Display *display;
296{
297 XrmDatabase db;
298 char *xdefs;
299
2c8d1900 300#ifdef PBaseSize /* Cheap way to test for X11R4 or later. */
b631f177
JB
301 xdefs = XResourceManagerString (display);
302#else
a2a4d43e 303 xdefs = display->xdefaults;
b631f177
JB
304#endif
305
f3a0bf5c
JB
306 if (xdefs != NULL)
307 db = XrmGetStringDatabase (xdefs);
308 else
309 {
310 char xdefault[MAXPATHLEN];
311
312 gethomedir (xdefault);
313 strcat (xdefault, ".Xdefaults");
314 db = XrmGetFileDatabase (xdefault);
315 }
316
9b37b1c2
JB
317#ifdef XlibSpecificationRelease
318#if XlibSpecificationRelease >= 5
319 /* Get the screen-specific resources too. */
320 xdefs = XScreenResourceString (DefaultScreenOfDisplay (display));
321 if (xdefs != NULL)
fdce0b39
JB
322 {
323 XrmMergeDatabases (XrmGetStringDatabase (xdefs), &db);
324 XFree (xdefs);
325 }
9b37b1c2
JB
326#endif
327#endif
328
f3a0bf5c
JB
329 return db;
330}
331
332static XrmDatabase
333get_environ_db ()
334{
335 XrmDatabase db;
336 char *p;
337 char path[MAXPATHLEN];
338
339 if ((p = getenv ("XENVIRONMENT")) == NULL)
340 {
341 gethomedir (path);
342 strcat (path, ".Xdefaults-");
343 gethostname (path + strlen (path), MAXPATHLEN - strlen (path));
344 p = path;
345 }
346
347 db = XrmGetFileDatabase (p);
348 return db;
349}
350\f
351/* Types of values that we can find in a database */
352
353#define XrmStringType "String" /* String representation */
354XrmRepresentation x_rm_string; /* Quark representation */
355
356/* Load X resources based on the display and a possible -xrm option. */
357
358XrmDatabase
359x_load_resources (display, xrm_string, myclass)
360 Display *display;
361 char *xrm_string, *myclass;
362{
363 char *xdefs;
364 XrmDatabase rdb;
365 XrmDatabase db;
366
367 x_rm_string = XrmStringToQuark (XrmStringType);
368 XrmInitialize ();
369 rdb = XrmGetStringDatabase ("");
370
371 /* Get application system defaults */
372 db = get_system_app (myclass);
373 if (db != NULL)
374 XrmMergeDatabases (db, &rdb);
375
376 /* Get Fallback resources */
377 db = get_fallback (display);
378 if (db != NULL)
379 XrmMergeDatabases (db, &rdb);
380
381 /* Get application user defaults */
382 db = get_user_app (myclass);
383 if (db != NULL)
384 XrmMergeDatabases (db, &rdb);
385
386 /* get User defaults */
387 db = get_user_db (display);
388 if (db != NULL)
389 XrmMergeDatabases (db, &rdb);
390
391 /* Get Environment defaults. */
392 db = get_environ_db ();
393 if (db != NULL)
394 XrmMergeDatabases (db, &rdb);
395
396 /* Last, merge in any specification from the command line. */
397 if (xrm_string != NULL)
398 {
399 db = XrmGetStringDatabase (xrm_string);
400 if (db != NULL)
401 XrmMergeDatabases (db, &rdb);
402 }
403
404 return rdb;
405}
406
407/* Retrieve the value of the resource specified by NAME with class CLASS
408 and of type TYPE from database RDB. The value is returned in RET_VALUE. */
409
410int
411x_get_resource (rdb, name, class, expected_type, ret_value)
412 XrmDatabase rdb;
413 char *name, *class;
414 XrmRepresentation expected_type;
415 XrmValue *ret_value;
416{
417 XrmValue value;
418 XrmName namelist[100];
419 XrmClass classlist[100];
420 XrmRepresentation type;
421
422 XrmStringToNameList(name, namelist);
423 XrmStringToClassList(class, classlist);
424
425 if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
426 && (type == expected_type))
427 {
428 if (type == x_rm_string)
41ab0754 429 ret_value->addr = (char *) value.addr;
f3a0bf5c
JB
430 else
431 bcopy (value.addr, ret_value->addr, ret_value->size);
432
433 return value.size;
434 }
435
436 return 0;
437}
438
439/* Retrieve the string resource specified by NAME with CLASS from
440 database RDB. */
441
442char *
443x_get_string_resource (rdb, name, class)
444 XrmDatabase rdb;
445 char *name, *class;
446{
447 XrmValue value;
448
449 if (x_get_resource (rdb, name, class, x_rm_string, &value))
450 return (char *) value.addr;
451
452 return (char *) 0;
453}
454\f
455#ifdef TESTRM
456#include <stdio.h>
457#include "arg-list.h"
458
459static void
460fatal (msg, prog, x1, x2, x3, x4, x5)
461 char *msg, *prog;
462 int x1, x2, x3, x4, x5;
463{
464 extern int errno;
465
466 if (errno)
467 perror (prog);
468
469 (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
470 exit (1);
471}
472
473main (argc, argv)
474 int argc;
475 char **argv;
476{
477 Display *display;
478 char *displayname, *resource_string, *class;
479 XrmDatabase xdb;
480 List *arg_list, *lp;
481
482 arg_list = arg_listify (argc, argv);
483
484 lp = member ("-d", arg_list);
485 if (!NIL (lp))
486 displayname = car (cdr (lp));
487 else
488 displayname = "localhost:0.0";
489
490 lp = member ("-xrm", arg_list);
491 if (! NIL (lp))
492 resource_string = car (cdr (lp));
493 else
494 resource_string = (char *) 0;
495
496 lp = member ("-c", arg_list);
497 if (! NIL (lp))
498 class = car (cdr (lp));
499 else
500 class = "Emacs";
501
502 free_arglist (arg_list);
503
504
505
506 if (!(display = XOpenDisplay (displayname)))
507 fatal ("Can't open display '%s'\n", XDisplayName (displayname));
508
509 xdb = x_load_resources (display, resource_string, class);
510
511#if 0
512 /* In a real program, you'd want to also do this: */
513 display->db = xdb;
514#endif
515
516 while (1)
517 {
518 char line[90];
519
520 printf ("String: ");
521 gets (line);
522 if (strlen (line))
523 {
524 char *value = x_get_string_resource (xdb, line, class);
525
526 if (value != NULL)
527 printf ("\t%s: %s\n\n", line, value);
528 else
529 printf ("\tNo Value.\n\n");
530 }
531 else
532 break;
533 }
534 printf ("\tExit.\n\n");
535
536 XCloseDisplay (display);
537}
538#endif /* TESTRM */