*** empty log message ***
[bpt/emacs.git] / src / xrdb.c
CommitLineData
f3a0bf5c
JB
1/* Deal with the X Resource Manager.
2 Copyright (C) 1990 Free Software Foundation.
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
6the Free Software Foundation; either version 1, or (at your option)
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
20#include <X11/Xlib.h>
21#include <X11/Xatom.h>
22#include <X11/Xos.h>
23#include <X11/X.h>
24#include <X11/Xutil.h>
25#include <X11/Xresource.h>
26#include <sys/param.h>
27#include <pwd.h>
28#include <sys/stat.h>
265a9e55 29#include <sys/types.h>
f3a0bf5c
JB
30
31#ifdef emacs
32#include "config.h"
33#endif
34
35extern char *getenv ();
265a9e55 36extern uid_t getuid ();
f3a0bf5c
JB
37extern struct passwd *getpwuid ();
38extern struct passwd *getpwnam ();
39
40static char *
41gethomedir (dirname)
42 char *dirname;
43{
44 int uid;
45 struct passwd *pw;
46 char *ptr;
47
48 if ((ptr = getenv ("HOME")) == NULL)
49 {
50 if ((ptr = getenv ("USER")) != NULL)
51 pw = getpwnam (ptr);
52 else
53 {
54 uid = getuid ();
55 pw = getpwuid (uid);
56 }
57 if (pw)
58 ptr = pw->pw_dir;
59 else
60 {
61 ptr = NULL;
62 *dirname = '\0';
63 }
64 }
65
66 if (ptr != NULL)
67 strcpy (dirname, ptr);
68
69 dirname += strlen (dirname);
70 *dirname = '/';
71 dirname++;
72 *dirname = '\0';
73
74 return dirname;
75}
76
77static int
78file_p (path)
79 char *path;
80{
81 struct stat status;
82
83 return (access (path, R_OK) == 0 /* exists and is readable */
84 && stat (path, &status) == 0 /* get the status */
85 && (status.st_mode & S_IFDIR) == 0); /* not a directory */
86}
87
88#if 0
89#define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/"
90#endif
91
92/* Isn't this just disgusting? */
93
94#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"
95
96static int
97decode_magic (string, file, return_path)
98 char *string, *file, *return_path;
99{
100 char *p = string;
101 char *t = return_path;
102
103 while (*p)
104 {
105 if (*p == '%')
106 switch (*++p)
107 {
108 case '%':
109 *t++ = '%';
110 p++;
111 break;
112
113 case 'N':
114 case 'T':
115 case 'S':
116 case 'L':
117 case 'l':
118 case 't':
119 case 'c':
120 default:
121 p++;
122 if (*t == '/' && *p == '/')
123 p++;
124 break;
125 }
126 else
127 *t++ = *p++;
128 }
129 *t = '\0';
130 strcat (return_path, file);
131
132 if (file_p (return_path))
133 return 1;
134
135 return_path[0] = '\0';
136 return 0;
137}
138
139static int
140magic_searchpath_decoder (incantation_string, file, return_path)
141 char *incantation_string, *return_path, *file;
142{
143 register char *s = incantation_string;
144 register char *p;
145 register char string[MAXPATHLEN];
146
147 while (*s)
148 {
149 p = s;
150
151 while (*p && *p != ':')
152 p++;
153
154 if (*p == ':' && *(p + 1) == ':')
155 {
156 bcopy ("%N%S", string, 5);
157 if (decode_magic (string, file, return_path))
158 return 1;
159
160 s = p + 1;
161 continue;
162 }
163
164 if (p > s)
165 {
166 int len = p - s;
167
168 bcopy (s, string, len);
169 string[len + 1] = '\0';
170 if (decode_magic (string, file, return_path))
171 return 1;
172 }
173
174 if (p)
175 s = p + 1;
176 else
177 return 0;
178 }
179
180 return 0;
181}
182\f
183static XrmDatabase
184get_system_app (class)
185 char *class;
186{
187 XrmDatabase db;
188 char path[MAXPATHLEN];
189 char *p;
190
191 if ((p = getenv ("XFILESEARCHPATH")) == NULL)
192 p = X_DEFAULT_SEARCH_PATH;
193
194 if (! magic_searchpath_decoder (p, class, path))
195 return NULL;
196
197 db = XrmGetFileDatabase (path);
198 return db;
199}
200
201static XrmDatabase
202get_fallback (display)
203 Display *display;
204{
205 XrmDatabase db;
206
207 return NULL;
208}
209
210static XrmDatabase
211get_user_app (class)
212 char *class;
213{
214 XrmDatabase db;
215 char *magic_path;
216 char path[MAXPATHLEN];
217
218 if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL)
219 {
220 char homedir[MAXPATHLEN];
221 char *default_magic;
222 char *p;
223
224 gethomedir (homedir);
225
226 if ((p = getenv ("XAPPLRESDIR")) == NULL)
227 {
228 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
229 magic_path = (char *) alloca ((3 * strlen (homedir))
230 + strlen (default_magic));
231 sprintf (magic_path, default_magic, homedir, homedir, homedir);
232 }
233 else
234 {
235 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
236 magic_path = (char *) alloca ((3 * strlen (p))
237 + strlen (default_magic)
238 + strlen (homedir));
239 sprintf (magic_path, default_magic, p, p, p, homedir);
240 }
241 }
242
243 if (! magic_searchpath_decoder (magic_path, class, path))
244 return NULL;
245
246 db = XrmGetFileDatabase (path);
247 return db;
248}
249
250static XrmDatabase
251get_user_db (display)
252 Display *display;
253{
254 XrmDatabase db;
255 char *xdefs;
256
257 xdefs = XResourceManagerString (display);
258 if (xdefs != NULL)
259 db = XrmGetStringDatabase (xdefs);
260 else
261 {
262 char xdefault[MAXPATHLEN];
263
264 gethomedir (xdefault);
265 strcat (xdefault, ".Xdefaults");
266 db = XrmGetFileDatabase (xdefault);
267 }
268
269 return db;
270}
271
272static XrmDatabase
273get_environ_db ()
274{
275 XrmDatabase db;
276 char *p;
277 char path[MAXPATHLEN];
278
279 if ((p = getenv ("XENVIRONMENT")) == NULL)
280 {
281 gethomedir (path);
282 strcat (path, ".Xdefaults-");
283 gethostname (path + strlen (path), MAXPATHLEN - strlen (path));
284 p = path;
285 }
286
287 db = XrmGetFileDatabase (p);
288 return db;
289}
290\f
291/* Types of values that we can find in a database */
292
293#define XrmStringType "String" /* String representation */
294XrmRepresentation x_rm_string; /* Quark representation */
295
296/* Load X resources based on the display and a possible -xrm option. */
297
298XrmDatabase
299x_load_resources (display, xrm_string, myclass)
300 Display *display;
301 char *xrm_string, *myclass;
302{
303 char *xdefs;
304 XrmDatabase rdb;
305 XrmDatabase db;
306
307 x_rm_string = XrmStringToQuark (XrmStringType);
308 XrmInitialize ();
309 rdb = XrmGetStringDatabase ("");
310
311 /* Get application system defaults */
312 db = get_system_app (myclass);
313 if (db != NULL)
314 XrmMergeDatabases (db, &rdb);
315
316 /* Get Fallback resources */
317 db = get_fallback (display);
318 if (db != NULL)
319 XrmMergeDatabases (db, &rdb);
320
321 /* Get application user defaults */
322 db = get_user_app (myclass);
323 if (db != NULL)
324 XrmMergeDatabases (db, &rdb);
325
326 /* get User defaults */
327 db = get_user_db (display);
328 if (db != NULL)
329 XrmMergeDatabases (db, &rdb);
330
331 /* Get Environment defaults. */
332 db = get_environ_db ();
333 if (db != NULL)
334 XrmMergeDatabases (db, &rdb);
335
336 /* Last, merge in any specification from the command line. */
337 if (xrm_string != NULL)
338 {
339 db = XrmGetStringDatabase (xrm_string);
340 if (db != NULL)
341 XrmMergeDatabases (db, &rdb);
342 }
343
344 return rdb;
345}
346
347/* Retrieve the value of the resource specified by NAME with class CLASS
348 and of type TYPE from database RDB. The value is returned in RET_VALUE. */
349
350int
351x_get_resource (rdb, name, class, expected_type, ret_value)
352 XrmDatabase rdb;
353 char *name, *class;
354 XrmRepresentation expected_type;
355 XrmValue *ret_value;
356{
357 XrmValue value;
358 XrmName namelist[100];
359 XrmClass classlist[100];
360 XrmRepresentation type;
361
362 XrmStringToNameList(name, namelist);
363 XrmStringToClassList(class, classlist);
364
365 if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
366 && (type == expected_type))
367 {
368 if (type == x_rm_string)
369 (char *) ret_value->addr = value.addr;
370 else
371 bcopy (value.addr, ret_value->addr, ret_value->size);
372
373 return value.size;
374 }
375
376 return 0;
377}
378
379/* Retrieve the string resource specified by NAME with CLASS from
380 database RDB. */
381
382char *
383x_get_string_resource (rdb, name, class)
384 XrmDatabase rdb;
385 char *name, *class;
386{
387 XrmValue value;
388
389 if (x_get_resource (rdb, name, class, x_rm_string, &value))
390 return (char *) value.addr;
391
392 return (char *) 0;
393}
394\f
395#ifdef TESTRM
396#include <stdio.h>
397#include "arg-list.h"
398
399static void
400fatal (msg, prog, x1, x2, x3, x4, x5)
401 char *msg, *prog;
402 int x1, x2, x3, x4, x5;
403{
404 extern int errno;
405
406 if (errno)
407 perror (prog);
408
409 (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
410 exit (1);
411}
412
413main (argc, argv)
414 int argc;
415 char **argv;
416{
417 Display *display;
418 char *displayname, *resource_string, *class;
419 XrmDatabase xdb;
420 List *arg_list, *lp;
421
422 arg_list = arg_listify (argc, argv);
423
424 lp = member ("-d", arg_list);
425 if (!NIL (lp))
426 displayname = car (cdr (lp));
427 else
428 displayname = "localhost:0.0";
429
430 lp = member ("-xrm", arg_list);
431 if (! NIL (lp))
432 resource_string = car (cdr (lp));
433 else
434 resource_string = (char *) 0;
435
436 lp = member ("-c", arg_list);
437 if (! NIL (lp))
438 class = car (cdr (lp));
439 else
440 class = "Emacs";
441
442 free_arglist (arg_list);
443
444
445
446 if (!(display = XOpenDisplay (displayname)))
447 fatal ("Can't open display '%s'\n", XDisplayName (displayname));
448
449 xdb = x_load_resources (display, resource_string, class);
450
451#if 0
452 /* In a real program, you'd want to also do this: */
453 display->db = xdb;
454#endif
455
456 while (1)
457 {
458 char line[90];
459
460 printf ("String: ");
461 gets (line);
462 if (strlen (line))
463 {
464 char *value = x_get_string_resource (xdb, line, class);
465
466 if (value != NULL)
467 printf ("\t%s: %s\n\n", line, value);
468 else
469 printf ("\tNo Value.\n\n");
470 }
471 else
472 break;
473 }
474 printf ("\tExit.\n\n");
475
476 XCloseDisplay (display);
477}
478#endif /* TESTRM */