*** empty log message ***
[emacs.git] / src / xrdb.c
blob930b4d54d43a5e70b22dbbdea22e290b23d690fb
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 #include <pwd.h>
28 #include <sys/stat.h>
30 #ifdef emacs
31 #include "config.h"
32 #endif
34 extern char *getenv ();
35 extern int getuid ();
36 extern struct passwd *getpwuid ();
37 extern struct passwd *getpwnam ();
39 static char *
40 gethomedir (dirname)
41 char *dirname;
43 int uid;
44 struct passwd *pw;
45 char *ptr;
47 if ((ptr = getenv ("HOME")) == NULL)
49 if ((ptr = getenv ("USER")) != NULL)
50 pw = getpwnam (ptr);
51 else
53 uid = getuid ();
54 pw = getpwuid (uid);
56 if (pw)
57 ptr = pw->pw_dir;
58 else
60 ptr = NULL;
61 *dirname = '\0';
65 if (ptr != NULL)
66 strcpy (dirname, ptr);
68 dirname += strlen (dirname);
69 *dirname = '/';
70 dirname++;
71 *dirname = '\0';
73 return dirname;
76 static int
77 file_p (path)
78 char *path;
80 struct stat status;
82 return (access (path, R_OK) == 0 /* exists and is readable */
83 && stat (path, &status) == 0 /* get the status */
84 && (status.st_mode & S_IFDIR) == 0); /* not a directory */
87 #if 0
88 #define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/"
89 #endif
91 /* Isn't this just disgusting? */
93 #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 static int
96 decode_magic (string, file, return_path)
97 char *string, *file, *return_path;
99 char *p = string;
100 char *t = return_path;
102 while (*p)
104 if (*p == '%')
105 switch (*++p)
107 case '%':
108 *t++ = '%';
109 p++;
110 break;
112 case 'N':
113 case 'T':
114 case 'S':
115 case 'L':
116 case 'l':
117 case 't':
118 case 'c':
119 default:
120 p++;
121 if (*t == '/' && *p == '/')
122 p++;
123 break;
125 else
126 *t++ = *p++;
128 *t = '\0';
129 strcat (return_path, file);
131 if (file_p (return_path))
132 return 1;
134 return_path[0] = '\0';
135 return 0;
138 static int
139 magic_searchpath_decoder (incantation_string, file, return_path)
140 char *incantation_string, *return_path, *file;
142 register char *s = incantation_string;
143 register char *p;
144 register char string[MAXPATHLEN];
146 while (*s)
148 p = s;
150 while (*p && *p != ':')
151 p++;
153 if (*p == ':' && *(p + 1) == ':')
155 bcopy ("%N%S", string, 5);
156 if (decode_magic (string, file, return_path))
157 return 1;
159 s = p + 1;
160 continue;
163 if (p > s)
165 int len = p - s;
167 bcopy (s, string, len);
168 string[len + 1] = '\0';
169 if (decode_magic (string, file, return_path))
170 return 1;
173 if (p)
174 s = p + 1;
175 else
176 return 0;
179 return 0;
182 static XrmDatabase
183 get_system_app (class)
184 char *class;
186 XrmDatabase db;
187 char path[MAXPATHLEN];
188 char *p;
190 if ((p = getenv ("XFILESEARCHPATH")) == NULL)
191 p = X_DEFAULT_SEARCH_PATH;
193 if (! magic_searchpath_decoder (p, class, path))
194 return NULL;
196 db = XrmGetFileDatabase (path);
197 return db;
200 static XrmDatabase
201 get_fallback (display)
202 Display *display;
204 XrmDatabase db;
206 return NULL;
209 static XrmDatabase
210 get_user_app (class)
211 char *class;
213 XrmDatabase db;
214 char *magic_path;
215 char path[MAXPATHLEN];
217 if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL)
219 char homedir[MAXPATHLEN];
220 char *default_magic;
221 char *p;
223 gethomedir (homedir);
225 if ((p = getenv ("XAPPLRESDIR")) == NULL)
227 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
228 magic_path = (char *) alloca ((3 * strlen (homedir))
229 + strlen (default_magic));
230 sprintf (magic_path, default_magic, homedir, homedir, homedir);
232 else
234 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
235 magic_path = (char *) alloca ((3 * strlen (p))
236 + strlen (default_magic)
237 + strlen (homedir));
238 sprintf (magic_path, default_magic, p, p, p, homedir);
242 if (! magic_searchpath_decoder (magic_path, class, path))
243 return NULL;
245 db = XrmGetFileDatabase (path);
246 return db;
249 static XrmDatabase
250 get_user_db (display)
251 Display *display;
253 XrmDatabase db;
254 char *xdefs;
256 xdefs = XResourceManagerString (display);
257 if (xdefs != NULL)
258 db = XrmGetStringDatabase (xdefs);
259 else
261 char xdefault[MAXPATHLEN];
263 gethomedir (xdefault);
264 strcat (xdefault, ".Xdefaults");
265 db = XrmGetFileDatabase (xdefault);
268 return db;
271 static XrmDatabase
272 get_environ_db ()
274 XrmDatabase db;
275 char *p;
276 char path[MAXPATHLEN];
278 if ((p = getenv ("XENVIRONMENT")) == NULL)
280 gethomedir (path);
281 strcat (path, ".Xdefaults-");
282 gethostname (path + strlen (path), MAXPATHLEN - strlen (path));
283 p = path;
286 db = XrmGetFileDatabase (p);
287 return db;
290 /* Types of values that we can find in a database */
292 #define XrmStringType "String" /* String representation */
293 XrmRepresentation x_rm_string; /* Quark representation */
295 /* Load X resources based on the display and a possible -xrm option. */
297 XrmDatabase
298 x_load_resources (display, xrm_string, myclass)
299 Display *display;
300 char *xrm_string, *myclass;
302 char *xdefs;
303 XrmDatabase rdb;
304 XrmDatabase db;
306 x_rm_string = XrmStringToQuark (XrmStringType);
307 XrmInitialize ();
308 rdb = XrmGetStringDatabase ("");
310 /* Get application system defaults */
311 db = get_system_app (myclass);
312 if (db != NULL)
313 XrmMergeDatabases (db, &rdb);
315 /* Get Fallback resources */
316 db = get_fallback (display);
317 if (db != NULL)
318 XrmMergeDatabases (db, &rdb);
320 /* Get application user defaults */
321 db = get_user_app (myclass);
322 if (db != NULL)
323 XrmMergeDatabases (db, &rdb);
325 /* get User defaults */
326 db = get_user_db (display);
327 if (db != NULL)
328 XrmMergeDatabases (db, &rdb);
330 /* Get Environment defaults. */
331 db = get_environ_db ();
332 if (db != NULL)
333 XrmMergeDatabases (db, &rdb);
335 /* Last, merge in any specification from the command line. */
336 if (xrm_string != NULL)
338 db = XrmGetStringDatabase (xrm_string);
339 if (db != NULL)
340 XrmMergeDatabases (db, &rdb);
343 return rdb;
346 /* Retrieve the value of the resource specified by NAME with class CLASS
347 and of type TYPE from database RDB. The value is returned in RET_VALUE. */
350 x_get_resource (rdb, name, class, expected_type, ret_value)
351 XrmDatabase rdb;
352 char *name, *class;
353 XrmRepresentation expected_type;
354 XrmValue *ret_value;
356 XrmValue value;
357 XrmName namelist[100];
358 XrmClass classlist[100];
359 XrmRepresentation type;
361 XrmStringToNameList(name, namelist);
362 XrmStringToClassList(class, classlist);
364 if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True
365 && (type == expected_type))
367 if (type == x_rm_string)
368 (char *) ret_value->addr = value.addr;
369 else
370 bcopy (value.addr, ret_value->addr, ret_value->size);
372 return value.size;
375 return 0;
378 /* Retrieve the string resource specified by NAME with CLASS from
379 database RDB. */
381 char *
382 x_get_string_resource (rdb, name, class)
383 XrmDatabase rdb;
384 char *name, *class;
386 XrmValue value;
388 if (x_get_resource (rdb, name, class, x_rm_string, &value))
389 return (char *) value.addr;
391 return (char *) 0;
394 #ifdef TESTRM
395 #include <stdio.h>
396 #include "arg-list.h"
398 static void
399 fatal (msg, prog, x1, x2, x3, x4, x5)
400 char *msg, *prog;
401 int x1, x2, x3, x4, x5;
403 extern int errno;
405 if (errno)
406 perror (prog);
408 (void) fprintf (stderr, msg, prog, x1, x2, x3, x4, x5);
409 exit (1);
412 main (argc, argv)
413 int argc;
414 char **argv;
416 Display *display;
417 char *displayname, *resource_string, *class;
418 XrmDatabase xdb;
419 List *arg_list, *lp;
421 arg_list = arg_listify (argc, argv);
423 lp = member ("-d", arg_list);
424 if (!NIL (lp))
425 displayname = car (cdr (lp));
426 else
427 displayname = "localhost:0.0";
429 lp = member ("-xrm", arg_list);
430 if (! NIL (lp))
431 resource_string = car (cdr (lp));
432 else
433 resource_string = (char *) 0;
435 lp = member ("-c", arg_list);
436 if (! NIL (lp))
437 class = car (cdr (lp));
438 else
439 class = "Emacs";
441 free_arglist (arg_list);
445 if (!(display = XOpenDisplay (displayname)))
446 fatal ("Can't open display '%s'\n", XDisplayName (displayname));
448 xdb = x_load_resources (display, resource_string, class);
450 #if 0
451 /* In a real program, you'd want to also do this: */
452 display->db = xdb;
453 #endif
455 while (1)
457 char line[90];
459 printf ("String: ");
460 gets (line);
461 if (strlen (line))
463 char *value = x_get_string_resource (xdb, line, class);
465 if (value != NULL)
466 printf ("\t%s: %s\n\n", line, value);
467 else
468 printf ("\tNo Value.\n\n");
470 else
471 break;
473 printf ("\tExit.\n\n");
475 XCloseDisplay (display);
477 #endif /* TESTRM */