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