*** empty log message ***
[emacs.git] / src / xrdb.c
blob681544eb0680d86fe749baf41832a719751c2b01
1 /* Deal with the X Resource Manager.
2 Copyright (C) 1990 Free Software Foundation.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 1, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Written by jla, 4/90 */
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 #ifdef VMS
28 #include "vms-pwd.h"
29 #else
30 #include <pwd.h>
31 #endif
32 #include <sys/stat.h>
33 #include <sys/types.h>
35 #ifdef emacs
36 #include "config.h"
37 #endif
39 extern char *getenv ();
40 extern uid_t getuid ();
41 extern struct passwd *getpwuid ();
42 extern struct passwd *getpwnam ();
44 static char *
45 gethomedir (dirname)
46 char *dirname;
48 int uid;
49 struct passwd *pw;
50 char *ptr;
52 if ((ptr = getenv ("HOME")) == NULL)
54 if ((ptr = getenv ("USER")) != NULL)
55 pw = getpwnam (ptr);
56 else
58 uid = getuid ();
59 pw = getpwuid (uid);
61 if (pw)
62 ptr = pw->pw_dir;
63 else
65 ptr = NULL;
66 *dirname = '\0';
70 if (ptr != NULL)
71 strcpy (dirname, ptr);
73 dirname += strlen (dirname);
74 *dirname = '/';
75 dirname++;
76 *dirname = '\0';
78 return dirname;
81 static int
82 file_p (path)
83 char *path;
85 struct stat status;
87 return (access (path, R_OK) == 0 /* exists and is readable */
88 && stat (path, &status) == 0 /* get the status */
89 && (status.st_mode & S_IFDIR) == 0); /* not a directory */
92 #if 0
93 #define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/"
94 #endif
96 /* Isn't this just disgusting? */
98 #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"
100 static int
101 decode_magic (string, file, return_path)
102 char *string, *file, *return_path;
104 char *p = string;
105 char *t = return_path;
107 while (*p)
109 if (*p == '%')
110 switch (*++p)
112 case '%':
113 *t++ = '%';
114 p++;
115 break;
117 case 'N':
118 case 'T':
119 case 'S':
120 case 'L':
121 case 'l':
122 case 't':
123 case 'c':
124 default:
125 p++;
126 if (*t == '/' && *p == '/')
127 p++;
128 break;
130 else
131 *t++ = *p++;
133 *t = '\0';
134 strcat (return_path, file);
136 if (file_p (return_path))
137 return 1;
139 return_path[0] = '\0';
140 return 0;
143 static int
144 magic_searchpath_decoder (incantation_string, file, return_path)
145 char *incantation_string, *return_path, *file;
147 register char *s = incantation_string;
148 register char *p;
149 register char string[MAXPATHLEN];
151 while (*s)
153 p = s;
155 while (*p && *p != ':')
156 p++;
158 if (*p == ':' && *(p + 1) == ':')
160 bcopy ("%N%S", string, 5);
161 if (decode_magic (string, file, return_path))
162 return 1;
164 s = p + 1;
165 continue;
168 if (p > s)
170 int len = p - s;
172 bcopy (s, string, len);
173 string[len + 1] = '\0';
174 if (decode_magic (string, file, return_path))
175 return 1;
178 if (p)
179 s = p + 1;
180 else
181 return 0;
184 return 0;
187 static XrmDatabase
188 get_system_app (class)
189 char *class;
191 XrmDatabase db;
192 char path[MAXPATHLEN];
193 char *p;
195 if ((p = getenv ("XFILESEARCHPATH")) == NULL)
196 p = X_DEFAULT_SEARCH_PATH;
198 if (! magic_searchpath_decoder (p, class, path))
199 return NULL;
201 db = XrmGetFileDatabase (path);
202 return db;
205 static XrmDatabase
206 get_fallback (display)
207 Display *display;
209 XrmDatabase db;
211 return NULL;
214 static XrmDatabase
215 get_user_app (class)
216 char *class;
218 XrmDatabase db;
219 char *magic_path;
220 char path[MAXPATHLEN];
222 if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL)
224 char homedir[MAXPATHLEN];
225 char *default_magic;
226 char *p;
228 gethomedir (homedir);
230 if ((p = getenv ("XAPPLRESDIR")) == NULL)
232 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
233 magic_path = (char *) alloca ((3 * strlen (homedir))
234 + strlen (default_magic));
235 sprintf (magic_path, default_magic, homedir, homedir, homedir);
237 else
239 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
240 magic_path = (char *) alloca ((3 * strlen (p))
241 + strlen (default_magic)
242 + strlen (homedir));
243 sprintf (magic_path, default_magic, p, p, p, homedir);
247 if (! magic_searchpath_decoder (magic_path, class, path))
248 return NULL;
250 db = XrmGetFileDatabase (path);
251 return db;
254 static XrmDatabase
255 get_user_db (display)
256 Display *display;
258 XrmDatabase db;
259 char *xdefs;
261 xdefs = XResourceManagerString (display);
262 if (xdefs != NULL)
263 db = XrmGetStringDatabase (xdefs);
264 else
266 char xdefault[MAXPATHLEN];
268 gethomedir (xdefault);
269 strcat (xdefault, ".Xdefaults");
270 db = XrmGetFileDatabase (xdefault);
273 return db;
276 static XrmDatabase
277 get_environ_db ()
279 XrmDatabase db;
280 char *p;
281 char path[MAXPATHLEN];
283 if ((p = getenv ("XENVIRONMENT")) == NULL)
285 gethomedir (path);
286 strcat (path, ".Xdefaults-");
287 gethostname (path + strlen (path), MAXPATHLEN - strlen (path));
288 p = path;
291 db = XrmGetFileDatabase (p);
292 return db;
295 /* Types of values that we can find in a database */
297 #define XrmStringType "String" /* String representation */
298 XrmRepresentation x_rm_string; /* Quark representation */
300 /* Load X resources based on the display and a possible -xrm option. */
302 XrmDatabase
303 x_load_resources (display, xrm_string, myclass)
304 Display *display;
305 char *xrm_string, *myclass;
307 char *xdefs;
308 XrmDatabase rdb;
309 XrmDatabase db;
311 x_rm_string = XrmStringToQuark (XrmStringType);
312 XrmInitialize ();
313 rdb = XrmGetStringDatabase ("");
315 /* Get application system defaults */
316 db = get_system_app (myclass);
317 if (db != NULL)
318 XrmMergeDatabases (db, &rdb);
320 /* Get Fallback resources */
321 db = get_fallback (display);
322 if (db != NULL)
323 XrmMergeDatabases (db, &rdb);
325 /* Get application user defaults */
326 db = get_user_app (myclass);
327 if (db != NULL)
328 XrmMergeDatabases (db, &rdb);
330 /* get User defaults */
331 db = get_user_db (display);
332 if (db != NULL)
333 XrmMergeDatabases (db, &rdb);
335 /* Get Environment defaults. */
336 db = get_environ_db ();
337 if (db != NULL)
338 XrmMergeDatabases (db, &rdb);
340 /* Last, merge in any specification from the command line. */
341 if (xrm_string != NULL)
343 db = XrmGetStringDatabase (xrm_string);
344 if (db != NULL)
345 XrmMergeDatabases (db, &rdb);
348 return rdb;
351 /* Retrieve the value of the resource specified by NAME with class CLASS
352 and of type TYPE from database RDB. The value is returned in RET_VALUE. */
355 x_get_resource (rdb, name, class, expected_type, ret_value)
356 XrmDatabase rdb;
357 char *name, *class;
358 XrmRepresentation expected_type;
359 XrmValue *ret_value;
361 XrmValue value;
362 XrmName namelist[100];
363 XrmClass classlist[100];
364 XrmRepresentation type;
366 XrmStringToNameList(name, namelist);
367 XrmStringToClassList(class, classlist);
369 if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
370 && (type == expected_type))
372 if (type == x_rm_string)
373 (char *) ret_value->addr = value.addr;
374 else
375 bcopy (value.addr, ret_value->addr, ret_value->size);
377 return value.size;
380 return 0;
383 /* Retrieve the string resource specified by NAME with CLASS from
384 database RDB. */
386 char *
387 x_get_string_resource (rdb, name, class)
388 XrmDatabase rdb;
389 char *name, *class;
391 XrmValue value;
393 if (x_get_resource (rdb, name, class, x_rm_string, &value))
394 return (char *) value.addr;
396 return (char *) 0;
399 #ifdef TESTRM
400 #include <stdio.h>
401 #include "arg-list.h"
403 static void
404 fatal (msg, prog, x1, x2, x3, x4, x5)
405 char *msg, *prog;
406 int x1, x2, x3, x4, x5;
408 extern int errno;
410 if (errno)
411 perror (prog);
413 (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
414 exit (1);
417 main (argc, argv)
418 int argc;
419 char **argv;
421 Display *display;
422 char *displayname, *resource_string, *class;
423 XrmDatabase xdb;
424 List *arg_list, *lp;
426 arg_list = arg_listify (argc, argv);
428 lp = member ("-d", arg_list);
429 if (!NIL (lp))
430 displayname = car (cdr (lp));
431 else
432 displayname = "localhost:0.0";
434 lp = member ("-xrm", arg_list);
435 if (! NIL (lp))
436 resource_string = car (cdr (lp));
437 else
438 resource_string = (char *) 0;
440 lp = member ("-c", arg_list);
441 if (! NIL (lp))
442 class = car (cdr (lp));
443 else
444 class = "Emacs";
446 free_arglist (arg_list);
450 if (!(display = XOpenDisplay (displayname)))
451 fatal ("Can't open display '%s'\n", XDisplayName (displayname));
453 xdb = x_load_resources (display, resource_string, class);
455 #if 0
456 /* In a real program, you'd want to also do this: */
457 display->db = xdb;
458 #endif
460 while (1)
462 char line[90];
464 printf ("String: ");
465 gets (line);
466 if (strlen (line))
468 char *value = x_get_string_resource (xdb, line, class);
470 if (value != NULL)
471 printf ("\t%s: %s\n\n", line, value);
472 else
473 printf ("\tNo Value.\n\n");
475 else
476 break;
478 printf ("\tExit.\n\n");
480 XCloseDisplay (display);
482 #endif /* TESTRM */