Mercurial > emacs
comparison src/xrdb.c @ 4232:f533d585cfc8
Implement search for app-defaults directory and
localized default databases, along with some other functionality
provided by Xt.
#include <stdio.h>, since we call sprintf.
[emacs] (malloc, realloc, free): #define these to xmalloc,
xrealloc, and xfree.
(x_get_string_resource, file_p): Add forward declarations for these.
(x_customization_string): New variable.
(x_get_customization_string): New function.
(gethomedir): Return malloc'ed space of the right size, instead of
writing into a fixed-size buffer; this means that our callers do
not impose an arbitrary limit on file name length.
(magic_file_p): Rewrite of decode_magic; actually do the
substitutions, instead of expanding all %-escapes to "". Support
the customization string. Return 0 or the expanded file name,
instead of just zero or one. Allocate the space for the expanded
file name ourselves, instead of writing into a fixed-size buffer
passed to us; this removes an arbitrary limit.
(search_magic_path): Rewrite of magic_searchpath_decoder. Return
0 or the expanded file name, instead of just zero or one.
Allocate the space for the expanded file name ourselves, instead
of writing into a fixed-size buffer passed to us; this means that
our callers do not impose an arbitrary limit on file name length.
(get_system_app): Changed to work with search_magic_path.
(get_user_app): Rewritten to work with search_magic_path, and not
to assume that the values of XAPPLRESDIR is a single directory.
(get_user_db): Properly use the new version of gethomedir.
(get_environ_db): Remove arbitrary limit on length of host name.
(x_load_resources): Take a new argument, myname.
Call get_user_db early to obtain the customization string.
Changes to stand-alone testing code.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Thu, 22 Jul 1993 22:00:48 +0000 |
parents | e67c6c10dd7c |
children | a4197ae1927d |
comparison
equal
deleted
inserted
replaced
4231:91a883c56382 | 4232:f533d585cfc8 |
---|---|
18 /* Written by jla, 4/90 */ | 18 /* Written by jla, 4/90 */ |
19 | 19 |
20 #ifdef emacs | 20 #ifdef emacs |
21 #include "config.h" | 21 #include "config.h" |
22 #endif | 22 #endif |
23 | |
24 #include <stdio.h> | |
23 | 25 |
24 #if 1 /* I'd really appreciate it if this code could go away... -JimB */ | 26 #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 */ | 27 /* this avoids lossage in the `dual-universe' headers on AT&T SysV X11 */ |
26 #ifdef USG5 | 28 #ifdef USG5 |
27 #define SYSV | 29 #define SYSV |
69 #else | 71 #else |
70 extern struct passwd *getpwuid (); | 72 extern struct passwd *getpwuid (); |
71 extern struct passwd *getpwnam (); | 73 extern struct passwd *getpwnam (); |
72 #endif | 74 #endif |
73 | 75 |
76 /* Make sure not to #include anything after these definitions. Let's | |
77 not step on anyone's prototypes. */ | |
78 #ifdef emacs | |
79 #define malloc xmalloc | |
80 #define realloc xrealloc | |
81 #define free xfree | |
82 #endif | |
83 | |
84 char *x_get_string_resource (); | |
85 static int file_p (); | |
86 | |
87 | |
88 /* X file search path processing. */ | |
89 | |
90 | |
91 /* The string which gets substituted for the %C escape in XFILESEARCHPATH | |
92 and friends, or zero if none was specified. */ | |
93 char *x_customization_string; | |
94 | |
95 | |
96 /* Return the value of the emacs.customization (Emacs.Customization) | |
97 resource, for later use in search path decoding. If we find no | |
98 such resource, return zero. */ | |
99 char * | |
100 x_get_customization_string (db, name, class) | |
101 XrmDatabase db; | |
102 char *name, *class; | |
103 { | |
104 char *full_name | |
105 = (char *) alloca (strlen (name) + sizeof ("customization") + 3); | |
106 char *full_class | |
107 = (char *) alloca (strlen (class) + sizeof ("Customization") + 3); | |
108 char *result; | |
109 | |
110 sprintf (full_name, "%s.%s", name, "customization"); | |
111 sprintf (full_class, "%s.%s", class, "Customization"); | |
112 | |
113 result = x_get_string_resource (db, full_name, full_class); | |
114 | |
115 if (result) | |
116 return strcpy ((char *) malloc (strlen (result) + 1), result); | |
117 else | |
118 return 0; | |
119 } | |
120 | |
121 | |
122 /* Expand all the Xt-style %-escapes in STRING, whose length is given | |
123 by STRING_LEN. Here are the escapes we're supposed to recognize: | |
124 | |
125 %N The value of the application's class name | |
126 %T The value of the type parameter ("app-defaults" in this | |
127 context) | |
128 %S The value of the suffix parameter ("" in this context) | |
129 %L The language string associated with the specified display | |
130 (We use the "LANG" environment variable here, if it's set.) | |
131 %l The language part of the display's language string | |
132 (We treat this just like %L. If someone can tell us what | |
133 we're really supposed to do, dandy.) | |
134 %t The territory part of the display's language string | |
135 (This never gets used.) | |
136 %c The codeset part of the display's language string | |
137 (This never gets used either.) | |
138 %C The customization string retrieved from the resource | |
139 database associated with display. | |
140 (This is x_customization_string.) | |
141 | |
142 Return the expanded file name if it exists and is readable, and | |
143 refers to %L only when the LANG environment variable is set, or | |
144 otherwise provided by X. | |
145 | |
146 ESCAPED_SUFFIX and SUFFIX are postpended to STRING if they are | |
147 non-zero. %-escapes in ESCAPED_SUFFIX are expanded; STRING is left | |
148 alone. | |
149 | |
150 Return NULL otherwise. */ | |
151 | |
74 static char * | 152 static char * |
75 gethomedir (dirname) | 153 magic_file_p (string, string_len, class, escaped_suffix, suffix) |
76 char *dirname; | 154 char *string; |
155 int string_len; | |
156 char *class, *escaped_suffix, *suffix; | |
157 { | |
158 char *lang = getenv ("LANG"); | |
159 | |
160 int path_size = 100; | |
161 char *path = (char *) malloc (path_size); | |
162 int path_len = 0; | |
163 | |
164 char *p = string; | |
165 | |
166 while (p < string + string_len) | |
167 { | |
168 /* The chunk we're about to stick on the end of result. */ | |
169 char *next; | |
170 int next_len; | |
171 | |
172 if (*p == '%') | |
173 { | |
174 p++; | |
175 | |
176 if (p >= string + string_len) | |
177 next_len = 0; | |
178 else | |
179 switch (*p) | |
180 { | |
181 case '%': | |
182 next = "%"; | |
183 next_len = 1; | |
184 break; | |
185 | |
186 case 'C': | |
187 next = (x_customization_string | |
188 ? x_customization_string | |
189 : ""); | |
190 next_len = strlen (next); | |
191 break; | |
192 | |
193 case 'N': | |
194 next = class; | |
195 next_len = strlen (class); | |
196 break; | |
197 | |
198 case 'T': | |
199 next = "app-defaults"; | |
200 next_len = strlen (next); | |
201 break; | |
202 | |
203 default: | |
204 case 'S': | |
205 next_len = 0; | |
206 break; | |
207 | |
208 case 'L': | |
209 case 'l': | |
210 if (! lang) | |
211 { | |
212 free (path); | |
213 return NULL; | |
214 } | |
215 | |
216 next = lang; | |
217 next_len = strlen (next); | |
218 break; | |
219 | |
220 case 't': | |
221 case 'c': | |
222 free (path); | |
223 return NULL; | |
224 } | |
225 } | |
226 else | |
227 next = p, next_len = 1; | |
228 | |
229 /* Do we have room for this component followed by a '\0' ? */ | |
230 if (path_len + next_len + 1 > path_size) | |
231 { | |
232 path_size = (path_len + next_len + 1) * 2; | |
233 path = (char *) realloc (path, path_size); | |
234 } | |
235 | |
236 bcopy (next, path + path_len, next_len); | |
237 path_len += next_len; | |
238 | |
239 p++; | |
240 | |
241 /* If we've reached the end of the string, append ESCAPED_SUFFIX. */ | |
242 if (p >= string + string_len && escaped_suffix) | |
243 { | |
244 string = escaped_suffix; | |
245 string_len = strlen (string); | |
246 p = string; | |
247 escaped_suffix = NULL; | |
248 } | |
249 } | |
250 | |
251 /* Perhaps we should add the SUFFIX now. */ | |
252 if (suffix) | |
253 { | |
254 int suffix_len = strlen (suffix); | |
255 | |
256 if (path_len + suffix_len + 1 > path_size) | |
257 { | |
258 path_size = (path_len + suffix_len + 1); | |
259 path = (char *) realloc (path, path_size); | |
260 } | |
261 | |
262 bcopy (suffix, path + path_len, suffix_len); | |
263 path_len += suffix_len; | |
264 } | |
265 | |
266 path[path_len] = '\0'; | |
267 | |
268 if (! file_p (path)) | |
269 { | |
270 free (path); | |
271 return NULL; | |
272 } | |
273 | |
274 return path; | |
275 } | |
276 | |
277 | |
278 static char * | |
279 gethomedir () | |
77 { | 280 { |
78 int uid; | 281 int uid; |
79 struct passwd *pw; | 282 struct passwd *pw; |
80 char *ptr; | 283 char *ptr; |
284 char *copy; | |
81 | 285 |
82 if ((ptr = getenv ("HOME")) == NULL) | 286 if ((ptr = getenv ("HOME")) == NULL) |
83 { | 287 { |
84 if ((ptr = getenv ("USER")) != NULL) | 288 if ((ptr = getenv ("USER")) != NULL) |
85 pw = getpwnam (ptr); | 289 pw = getpwnam (ptr); |
86 else | 290 else |
87 { | 291 { |
88 uid = getuid (); | 292 uid = getuid (); |
89 pw = getpwuid (uid); | 293 pw = getpwuid (uid); |
90 } | 294 } |
295 | |
91 if (pw) | 296 if (pw) |
92 ptr = pw->pw_dir; | 297 ptr = pw->pw_dir; |
93 else | 298 } |
94 { | 299 |
95 ptr = NULL; | 300 if (ptr == NULL) |
96 *dirname = '\0'; | 301 return "/"; |
97 } | 302 |
98 } | 303 copy = (char *) malloc (strlen (ptr) + 2); |
99 | 304 strcpy (copy, ptr); |
100 if (ptr != NULL) | 305 strcat (copy, "/"); |
101 strcpy (dirname, ptr); | 306 |
102 | 307 return copy; |
103 dirname += strlen (dirname); | 308 } |
104 *dirname = '/'; | 309 |
105 dirname++; | |
106 *dirname = '\0'; | |
107 | |
108 return dirname; | |
109 } | |
110 | 310 |
111 static int | 311 static int |
112 file_p (path) | 312 file_p (path) |
113 char *path; | 313 char *path; |
114 { | 314 { |
117 return (access (path, 4) == 0 /* exists and is readable */ | 317 return (access (path, 4) == 0 /* exists and is readable */ |
118 && stat (path, &status) == 0 /* get the status */ | 318 && stat (path, &status) == 0 /* get the status */ |
119 && (status.st_mode & S_IFDIR) == 0); /* not a directory */ | 319 && (status.st_mode & S_IFDIR) == 0); /* not a directory */ |
120 } | 320 } |
121 | 321 |
122 #if 0 | 322 |
123 #define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/" | 323 /* Find the first element of SEARCH_PATH which exists and is readable, |
124 #endif | 324 after expanding the %-escapes. Return 0 if we didn't find any, and |
125 | 325 the path name of the one we found otherwise. */ |
126 /* Isn't this just disgusting? */ | 326 |
127 | 327 static char * |
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" | 328 search_magic_path (search_path, class, escaped_suffix, suffix) |
129 | 329 char *search_path, *class, *escaped_suffix, *suffix; |
130 static int | 330 { |
131 decode_magic (string, file, return_path) | 331 register char *s, *p; |
132 char *string, *file, *return_path; | 332 |
133 { | 333 for (s = search_path; *s; s = p) |
134 char *p = string; | 334 { |
135 char *t = return_path; | 335 for (p = s; *p && *p != ':'; p++) |
136 | 336 ; |
137 while (*p) | 337 |
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 | |
173 static int | |
174 magic_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; | |
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)); | |
183 | |
184 while (*s) | |
185 { | |
186 p = s; | |
187 | |
188 while (*p && *p != ':') | |
189 p++; | |
190 | |
191 if (*p == ':' && *(p + 1) == ':') | 338 if (*p == ':' && *(p + 1) == ':') |
192 { | 339 { |
193 /* We know string is big enough for this. */ | 340 char *path; |
194 bcopy ("%N%S", string, 5); | 341 |
195 if (decode_magic (string, file, return_path)) | 342 s = "%N%S"; |
196 return 1; | 343 path = magic_file_p (s, strlen (s), class, escaped_suffix, suffix); |
344 if (path) | |
345 return path; | |
197 | 346 |
198 s = p + 1; | 347 s = p + 1; |
199 continue; | 348 continue; |
200 } | 349 } |
201 | 350 |
202 if (p > s) | 351 if (p > s) |
203 { | 352 { |
204 int len = p - s; | 353 char *path = magic_file_p (s, p - s, class, escaped_suffix, suffix); |
205 | 354 if (path) |
206 if (string_size < len+1) | 355 return path; |
207 { | |
208 string_size = 2 * len; | |
209 string = (char *) alloca (string_size * sizeof (*string)); | |
210 } | |
211 bcopy (s, string, len); | |
212 string[len] = '\0'; | |
213 if (decode_magic (string, file, return_path)) | |
214 return 1; | |
215 } | 356 } |
216 | 357 |
217 if (p && *p != 0) | 358 if (*p == ':') |
218 s = p + 1; | 359 p++; |
219 else | |
220 return 0; | |
221 } | 360 } |
222 | 361 |
223 return 0; | 362 return 0; |
224 } | 363 } |
225 | 364 |
365 /* Producing databases for individual sources. */ | |
366 | |
367 #define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/%L/%T/%N%C%S:/usr/lib/X11/%l/%T/%N%C%S:/usr/lib/X11/%T/%N%C%S:/usr/lib/X11/%L/%T/%N%S:/usr/lib/X11/%l/%T/%N%S:/usr/lib/X11/%T/%N%S" | |
368 | |
226 static XrmDatabase | 369 static XrmDatabase |
227 get_system_app (class) | 370 get_system_app (class) |
228 char *class; | 371 char *class; |
229 { | 372 { |
230 XrmDatabase db; | 373 XrmDatabase db = NULL; |
231 char path[MAXPATHLEN]; | 374 char *path; |
232 char *p; | 375 |
233 | 376 path = getenv ("XFILESEARCHPATH"); |
234 if ((p = getenv ("XFILESEARCHPATH")) == NULL) | 377 if (! path) path = X_DEFAULT_SEARCH_PATH; |
235 p = X_DEFAULT_SEARCH_PATH; | 378 |
236 | 379 path = search_magic_path (path, class, 0, 0); |
237 if (! magic_searchpath_decoder (p, class, path)) | 380 if (path) |
238 return NULL; | 381 { |
239 | 382 db = XrmGetFileDatabase (path); |
240 db = XrmGetFileDatabase (path); | 383 free (path); |
384 } | |
385 | |
241 return db; | 386 return db; |
242 } | 387 } |
388 | |
243 | 389 |
244 static XrmDatabase | 390 static XrmDatabase |
245 get_fallback (display) | 391 get_fallback (display) |
246 Display *display; | 392 Display *display; |
247 { | 393 { |
248 XrmDatabase db; | 394 XrmDatabase db; |
249 | 395 |
250 return NULL; | 396 return NULL; |
251 } | 397 } |
252 | 398 |
399 | |
253 static XrmDatabase | 400 static XrmDatabase |
254 get_user_app (class) | 401 get_user_app (class) |
255 char *class; | 402 char *class; |
256 { | 403 { |
257 XrmDatabase db; | 404 char *path; |
258 char *magic_path; | 405 char *file = 0; |
259 char path[MAXPATHLEN]; | 406 |
260 | 407 /* Check for XUSERFILESEARCHPATH. It is a path of complete file |
261 if ((magic_path = getenv ("XUSERFILESEARCHPATH")) == NULL) | 408 names, not directories. */ |
262 { | 409 if (((path = getenv ("XUSERFILESEARCHPATH")) |
263 char homedir[MAXPATHLEN]; | 410 && (file = search_magic_path (path, class, 0, 0))) |
264 char *default_magic; | 411 |
265 char *p; | 412 /* Check for APPLRESDIR; it is a path of directories. In each, |
266 | 413 we have to search for LANG/CLASS and then CLASS. */ |
267 gethomedir (homedir); | 414 || ((path = getenv ("XAPPLRESDIR")) |
268 | 415 && ((file = search_magic_path (path, class, "/%L/%N", 0)) |
269 if ((p = getenv ("XAPPLRESDIR")) == NULL) | 416 || (file = search_magic_path (path, class, "/%N", 0)))) |
270 { | 417 |
271 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N"; | 418 /* Check in the home directory. This is a bit of a hack; let's |
272 magic_path = (char *) alloca ((3 * strlen (homedir)) | 419 hope one's home directory doesn't contain any %-escapes. */ |
273 + strlen (default_magic)); | 420 || (path = gethomedir (), |
274 sprintf (magic_path, default_magic, homedir, homedir, homedir); | 421 ((file = search_magic_path (path, class, "%L/%N", 0)) |
275 } | 422 || (file = search_magic_path (path, class, "%N", 0))))) |
276 else | 423 { |
277 { | 424 XrmDatabase db = XrmGetFileDatabase (file); |
278 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N"; | 425 free (file); |
279 magic_path = (char *) alloca ((3 * strlen (p)) | 426 return db; |
280 + strlen (default_magic) | 427 } |
281 + strlen (homedir)); | 428 else |
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; | 429 return NULL; |
288 | 430 } |
289 db = XrmGetFileDatabase (path); | 431 |
290 return db; | |
291 } | |
292 | 432 |
293 static XrmDatabase | 433 static XrmDatabase |
294 get_user_db (display) | 434 get_user_db (display) |
295 Display *display; | 435 Display *display; |
296 { | 436 { |
305 | 445 |
306 if (xdefs != NULL) | 446 if (xdefs != NULL) |
307 db = XrmGetStringDatabase (xdefs); | 447 db = XrmGetStringDatabase (xdefs); |
308 else | 448 else |
309 { | 449 { |
310 char xdefault[MAXPATHLEN]; | 450 char *home; |
311 | 451 char *xdefault; |
312 gethomedir (xdefault); | 452 |
453 home = gethomedir (); | |
454 xdefault = (char *) malloc (strlen (home) + sizeof (".Xdefaults")); | |
455 strcpy (xdefault, home); | |
313 strcat (xdefault, ".Xdefaults"); | 456 strcat (xdefault, ".Xdefaults"); |
314 db = XrmGetFileDatabase (xdefault); | 457 db = XrmGetFileDatabase (xdefault); |
458 free (home); | |
459 free (xdefault); | |
315 } | 460 } |
316 | 461 |
317 #ifdef XlibSpecificationRelease | 462 #ifdef XlibSpecificationRelease |
318 #if XlibSpecificationRelease >= 5 | 463 #if XlibSpecificationRelease >= 5 |
319 /* Get the screen-specific resources too. */ | 464 /* Get the screen-specific resources too. */ |
332 static XrmDatabase | 477 static XrmDatabase |
333 get_environ_db () | 478 get_environ_db () |
334 { | 479 { |
335 XrmDatabase db; | 480 XrmDatabase db; |
336 char *p; | 481 char *p; |
337 char path[MAXPATHLEN]; | 482 char *path = 0, *home = 0, *host = 0; |
338 | 483 |
339 if ((p = getenv ("XENVIRONMENT")) == NULL) | 484 if ((p = getenv ("XENVIRONMENT")) == NULL) |
340 { | 485 { |
341 gethomedir (path); | 486 home = gethomedir (); |
342 strcat (path, ".Xdefaults-"); | 487 |
343 gethostname (path + strlen (path), MAXPATHLEN - strlen (path)); | 488 { |
489 int host_size = 100; | |
490 host = (char *) malloc (host_size); | |
491 | |
492 for (;;) | |
493 { | |
494 host[host_size - 1] = '\0'; | |
495 gethostname (host, host_size - 1); | |
496 if (strlen (host) < host_size - 1) | |
497 break; | |
498 host = (char *) realloc (host, host_size *= 2); | |
499 } | |
500 } | |
501 | |
502 path = (char *) malloc (strlen (home) | |
503 + sizeof (".Xdefaults-") | |
504 + strlen (host)); | |
505 sprintf (path, "%s%s%s", home, ".Xdefaults-", host); | |
344 p = path; | 506 p = path; |
345 } | 507 } |
346 | 508 |
347 db = XrmGetFileDatabase (p); | 509 db = XrmGetFileDatabase (p); |
510 | |
511 if (path) free (path); | |
512 if (home) free (home); | |
513 if (host) free (host); | |
514 | |
348 return db; | 515 return db; |
349 } | 516 } |
350 | 517 |
518 /* External interface. */ | |
519 | |
351 /* Types of values that we can find in a database */ | 520 /* Types of values that we can find in a database */ |
352 | 521 |
353 #define XrmStringType "String" /* String representation */ | 522 #define XrmStringType "String" /* String representation */ |
354 XrmRepresentation x_rm_string; /* Quark representation */ | 523 XrmRepresentation x_rm_string; /* Quark representation */ |
355 | 524 |
356 /* Load X resources based on the display and a possible -xrm option. */ | 525 /* Load X resources based on the display and a possible -xrm option. */ |
357 | 526 |
358 XrmDatabase | 527 XrmDatabase |
359 x_load_resources (display, xrm_string, myclass) | 528 x_load_resources (display, xrm_string, myname, myclass) |
360 Display *display; | 529 Display *display; |
361 char *xrm_string, *myclass; | 530 char *xrm_string, *myname, *myclass; |
362 { | 531 { |
363 char *xdefs; | 532 char *xdefs; |
533 XrmDatabase user_database; | |
364 XrmDatabase rdb; | 534 XrmDatabase rdb; |
365 XrmDatabase db; | 535 XrmDatabase db; |
366 | 536 |
367 x_rm_string = XrmStringToQuark (XrmStringType); | 537 x_rm_string = XrmStringToQuark (XrmStringType); |
368 XrmInitialize (); | 538 XrmInitialize (); |
369 rdb = XrmGetStringDatabase (""); | 539 rdb = XrmGetStringDatabase (""); |
540 | |
541 user_database = get_user_db (display); | |
542 | |
543 /* Figure out what the "customization string" is, so we can use it | |
544 to decode paths. */ | |
545 if (x_customization_string) | |
546 free (x_customization_string); | |
547 x_customization_string | |
548 = x_get_customization_string (user_database, myname, myclass); | |
370 | 549 |
371 /* Get application system defaults */ | 550 /* Get application system defaults */ |
372 db = get_system_app (myclass); | 551 db = get_system_app (myclass); |
373 if (db != NULL) | 552 if (db != NULL) |
374 XrmMergeDatabases (db, &rdb); | 553 XrmMergeDatabases (db, &rdb); |
382 db = get_user_app (myclass); | 561 db = get_user_app (myclass); |
383 if (db != NULL) | 562 if (db != NULL) |
384 XrmMergeDatabases (db, &rdb); | 563 XrmMergeDatabases (db, &rdb); |
385 | 564 |
386 /* get User defaults */ | 565 /* get User defaults */ |
387 db = get_user_db (display); | 566 if (user_database != NULL) |
388 if (db != NULL) | 567 XrmMergeDatabases (user_database, &rdb); |
389 XrmMergeDatabases (db, &rdb); | |
390 | 568 |
391 /* Get Environment defaults. */ | 569 /* Get Environment defaults. */ |
392 db = get_environ_db (); | 570 db = get_environ_db (); |
393 if (db != NULL) | 571 if (db != NULL) |
394 XrmMergeDatabases (db, &rdb); | 572 XrmMergeDatabases (db, &rdb); |
402 } | 580 } |
403 | 581 |
404 return rdb; | 582 return rdb; |
405 } | 583 } |
406 | 584 |
585 | |
407 /* Retrieve the value of the resource specified by NAME with class CLASS | 586 /* 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. */ | 587 and of type TYPE from database RDB. The value is returned in RET_VALUE. */ |
409 | 588 |
410 int | 589 int |
411 x_get_resource (rdb, name, class, expected_type, ret_value) | 590 x_get_resource (rdb, name, class, expected_type, ret_value) |
450 return (char *) value.addr; | 629 return (char *) value.addr; |
451 | 630 |
452 return (char *) 0; | 631 return (char *) 0; |
453 } | 632 } |
454 | 633 |
634 /* Stand-alone test facilities. */ | |
635 | |
455 #ifdef TESTRM | 636 #ifdef TESTRM |
456 #include <stdio.h> | 637 |
457 #include "arg-list.h" | 638 typedef char **List; |
639 #define arg_listify(len, list) (list) | |
640 #define car(list) (*(list)) | |
641 #define cdr(list) (list + 1) | |
642 #define NIL(list) (! *(list)) | |
643 #define free_arglist(list) | |
644 | |
645 static List | |
646 member (elt, list) | |
647 char *elt; | |
648 List list; | |
649 { | |
650 List p; | |
651 | |
652 for (p = list; ! NIL (p); p = cdr (p)) | |
653 if (! strcmp (elt, car (p))) | |
654 return p; | |
655 | |
656 return p; | |
657 } | |
458 | 658 |
459 static void | 659 static void |
460 fatal (msg, prog, x1, x2, x3, x4, x5) | 660 fatal (msg, prog, x1, x2, x3, x4, x5) |
461 char *msg, *prog; | 661 char *msg, *prog; |
462 int x1, x2, x3, x4, x5; | 662 int x1, x2, x3, x4, x5; |
473 main (argc, argv) | 673 main (argc, argv) |
474 int argc; | 674 int argc; |
475 char **argv; | 675 char **argv; |
476 { | 676 { |
477 Display *display; | 677 Display *display; |
478 char *displayname, *resource_string, *class; | 678 char *displayname, *resource_string, *class, *name; |
479 XrmDatabase xdb; | 679 XrmDatabase xdb; |
480 List *arg_list, *lp; | 680 List arg_list, lp; |
481 | 681 |
482 arg_list = arg_listify (argc, argv); | 682 arg_list = arg_listify (argc, argv); |
483 | 683 |
484 lp = member ("-d", arg_list); | 684 lp = member ("-d", arg_list); |
485 if (!NIL (lp)) | 685 if (!NIL (lp)) |
497 if (! NIL (lp)) | 697 if (! NIL (lp)) |
498 class = car (cdr (lp)); | 698 class = car (cdr (lp)); |
499 else | 699 else |
500 class = "Emacs"; | 700 class = "Emacs"; |
501 | 701 |
702 lp = member ("-n", arg_list); | |
703 if (! NIL (lp)) | |
704 name = car (cdr (lp)); | |
705 else | |
706 name = "emacs"; | |
707 | |
502 free_arglist (arg_list); | 708 free_arglist (arg_list); |
503 | |
504 | |
505 | 709 |
506 if (!(display = XOpenDisplay (displayname))) | 710 if (!(display = XOpenDisplay (displayname))) |
507 fatal ("Can't open display '%s'\n", XDisplayName (displayname)); | 711 fatal ("Can't open display '%s'\n", XDisplayName (displayname)); |
508 | 712 |
509 xdb = x_load_resources (display, resource_string, class); | 713 xdb = x_load_resources (display, resource_string, name, class); |
510 | 714 |
511 #if 0 | |
512 /* In a real program, you'd want to also do this: */ | 715 /* In a real program, you'd want to also do this: */ |
513 display->db = xdb; | 716 display->db = xdb; |
514 #endif | |
515 | 717 |
516 while (1) | 718 while (1) |
517 { | 719 { |
518 char line[90]; | 720 char query_name[90]; |
519 | 721 char query_class[90]; |
520 printf ("String: "); | 722 |
521 gets (line); | 723 printf ("Name: "); |
522 if (strlen (line)) | 724 gets (query_name); |
725 | |
726 if (strlen (query_name)) | |
523 { | 727 { |
524 char *value = x_get_string_resource (xdb, line, class); | 728 char *value; |
729 | |
730 printf ("Class: "); | |
731 gets (query_class); | |
732 | |
733 value = x_get_string_resource (xdb, query_name, query_class); | |
525 | 734 |
526 if (value != NULL) | 735 if (value != NULL) |
527 printf ("\t%s: %s\n\n", line, value); | 736 printf ("\t%s(%s): %s\n\n", query_name, query_class, value); |
528 else | 737 else |
529 printf ("\tNo Value.\n\n"); | 738 printf ("\tNo Value.\n\n"); |
530 } | 739 } |
531 else | 740 else |
532 break; | 741 break; |