Commit | Line | Data |
---|---|---|
f3a0bf5c | 1 | /* Deal with the X Resource Manager. |
ab422c4d PE |
2 | Copyright (C) 1990, 1993-1994, 2000-2013 Free Software Foundation, |
3 | Inc. | |
f3a0bf5c | 4 | |
90324359 GM |
5 | Author: Joseph Arceneaux |
6 | Created: 4/90 | |
7 | ||
3b7ad313 EN |
8 | This file is part of GNU Emacs. |
9 | ||
9ec0b715 | 10 | GNU Emacs is free software: you can redistribute it and/or modify |
f3a0bf5c | 11 | it under the terms of the GNU General Public License as published by |
9ec0b715 GM |
12 | the Free Software Foundation, either version 3 of the License, or |
13 | (at your option) any later version. | |
f3a0bf5c | 14 | |
3b7ad313 | 15 | GNU Emacs is distributed in the hope that it will be useful, |
f3a0bf5c JB |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | GNU General Public License for more details. | |
19 | ||
20 | You should have received a copy of the GNU General Public License | |
9ec0b715 | 21 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ |
f3a0bf5c | 22 | |
18160b98 | 23 | #include <config.h> |
a2a4d43e | 24 | |
dfcf069d | 25 | #include <unistd.h> |
42a2c622 | 26 | #include <errno.h> |
57bda87a | 27 | #include <epaths.h> |
61655b89 | 28 | #include <stdlib.h> |
837255fb JB |
29 | #include <stdio.h> |
30 | ||
b4716021 PE |
31 | #include "lisp.h" |
32 | ||
33 | /* This may include sys/types.h, and that somehow loses | |
34 | if this is not done before the other system files. */ | |
35 | #include "xterm.h" | |
36 | ||
f3a0bf5c JB |
37 | #include <X11/Xlib.h> |
38 | #include <X11/Xatom.h> | |
f3a0bf5c JB |
39 | #include <X11/X.h> |
40 | #include <X11/Xutil.h> | |
41 | #include <X11/Xresource.h> | |
5b9c0a1d | 42 | #ifdef HAVE_PWD_H |
f3a0bf5c | 43 | #include <pwd.h> |
531ff254 | 44 | #endif |
f3a0bf5c | 45 | |
dee186b6 J |
46 | #ifdef USE_MOTIF |
47 | /* For Vdouble_click_time. */ | |
48 | #include "keyboard.h" | |
49 | #endif | |
50 | ||
eec47d6b DN |
51 | char *x_get_string_resource (XrmDatabase rdb, const char *name, |
52 | const char *class); | |
837255fb JB |
53 | |
54 | \f | |
55 | /* X file search path processing. */ | |
56 | ||
57 | ||
58 | /* The string which gets substituted for the %C escape in XFILESEARCHPATH | |
59 | and friends, or zero if none was specified. */ | |
ac64929e | 60 | static char *x_customization_string; |
837255fb JB |
61 | |
62 | ||
63 | /* Return the value of the emacs.customization (Emacs.Customization) | |
64 | resource, for later use in search path decoding. If we find no | |
65 | such resource, return zero. */ | |
2f7c71a1 AS |
66 | static char * |
67 | x_get_customization_string (XrmDatabase db, const char *name, | |
68 | const char *class) | |
837255fb | 69 | { |
38182d90 PE |
70 | char *full_name = alloca (strlen (name) + sizeof "customization" + 3); |
71 | char *full_class = alloca (strlen (class) + sizeof "Customization" + 3); | |
837255fb JB |
72 | char *result; |
73 | ||
74 | sprintf (full_name, "%s.%s", name, "customization"); | |
75 | sprintf (full_class, "%s.%s", class, "Customization"); | |
76 | ||
77 | result = x_get_string_resource (db, full_name, full_class); | |
309f24d1 | 78 | return result ? xstrdup (result) : NULL; |
837255fb JB |
79 | } |
80 | ||
837255fb JB |
81 | /* Expand all the Xt-style %-escapes in STRING, whose length is given |
82 | by STRING_LEN. Here are the escapes we're supposed to recognize: | |
83 | ||
84 | %N The value of the application's class name | |
85 | %T The value of the type parameter ("app-defaults" in this | |
86 | context) | |
87 | %S The value of the suffix parameter ("" in this context) | |
88 | %L The language string associated with the specified display | |
89 | (We use the "LANG" environment variable here, if it's set.) | |
90 | %l The language part of the display's language string | |
91 | (We treat this just like %L. If someone can tell us what | |
92 | we're really supposed to do, dandy.) | |
93 | %t The territory part of the display's language string | |
94 | (This never gets used.) | |
95 | %c The codeset part of the display's language string | |
96 | (This never gets used either.) | |
97 | %C The customization string retrieved from the resource | |
98 | database associated with display. | |
99 | (This is x_customization_string.) | |
100 | ||
73dcdb9f | 101 | Return the resource database if its file was read successfully, and |
837255fb JB |
102 | refers to %L only when the LANG environment variable is set, or |
103 | otherwise provided by X. | |
104 | ||
28154962 PE |
105 | ESCAPED_SUFFIX is postpended to STRING if it is non-zero. |
106 | %-escapes in ESCAPED_SUFFIX are expanded. | |
837255fb JB |
107 | |
108 | Return NULL otherwise. */ | |
109 | ||
73dcdb9f PE |
110 | static XrmDatabase |
111 | magic_db (const char *string, ptrdiff_t string_len, const char *class, | |
112 | const char *escaped_suffix) | |
837255fb | 113 | { |
73dcdb9f | 114 | XrmDatabase db; |
837255fb JB |
115 | char *lang = getenv ("LANG"); |
116 | ||
28154962 | 117 | ptrdiff_t path_size = 100; |
23f86fce | 118 | char *path = xmalloc (path_size); |
28154962 | 119 | ptrdiff_t path_len = 0; |
837255fb | 120 | |
eec47d6b | 121 | const char *p = string; |
837255fb JB |
122 | |
123 | while (p < string + string_len) | |
124 | { | |
125 | /* The chunk we're about to stick on the end of result. */ | |
eec47d6b | 126 | const char *next = NULL; |
28154962 | 127 | ptrdiff_t next_len; |
837255fb JB |
128 | |
129 | if (*p == '%') | |
130 | { | |
131 | p++; | |
132 | ||
133 | if (p >= string + string_len) | |
134 | next_len = 0; | |
135 | else | |
136 | switch (*p) | |
137 | { | |
138 | case '%': | |
139 | next = "%"; | |
140 | next_len = 1; | |
141 | break; | |
142 | ||
143 | case 'C': | |
144 | next = (x_customization_string | |
145 | ? x_customization_string | |
146 | : ""); | |
147 | next_len = strlen (next); | |
148 | break; | |
149 | ||
150 | case 'N': | |
151 | next = class; | |
152 | next_len = strlen (class); | |
153 | break; | |
154 | ||
155 | case 'T': | |
156 | next = "app-defaults"; | |
157 | next_len = strlen (next); | |
158 | break; | |
159 | ||
160 | default: | |
161 | case 'S': | |
162 | next_len = 0; | |
163 | break; | |
164 | ||
165 | case 'L': | |
166 | case 'l': | |
167 | if (! lang) | |
168 | { | |
1b6d8cf0 | 169 | xfree (path); |
837255fb JB |
170 | return NULL; |
171 | } | |
427ec082 | 172 | |
837255fb JB |
173 | next = lang; |
174 | next_len = strlen (next); | |
175 | break; | |
427ec082 | 176 | |
837255fb JB |
177 | case 't': |
178 | case 'c': | |
1b6d8cf0 | 179 | xfree (path); |
837255fb JB |
180 | return NULL; |
181 | } | |
182 | } | |
183 | else | |
184 | next = p, next_len = 1; | |
185 | ||
186 | /* Do we have room for this component followed by a '\0' ? */ | |
28154962 | 187 | if (path_size - path_len <= next_len) |
837255fb | 188 | { |
28154962 | 189 | if (min (PTRDIFF_MAX, SIZE_MAX) / 2 - 1 - path_len < next_len) |
0065d054 | 190 | memory_full (SIZE_MAX); |
837255fb | 191 | path_size = (path_len + next_len + 1) * 2; |
38182d90 | 192 | path = xrealloc (path, path_size); |
837255fb | 193 | } |
427ec082 | 194 | |
72af86bd | 195 | memcpy (path + path_len, next, next_len); |
837255fb JB |
196 | path_len += next_len; |
197 | ||
198 | p++; | |
199 | ||
200 | /* If we've reached the end of the string, append ESCAPED_SUFFIX. */ | |
201 | if (p >= string + string_len && escaped_suffix) | |
202 | { | |
203 | string = escaped_suffix; | |
204 | string_len = strlen (string); | |
205 | p = string; | |
206 | escaped_suffix = NULL; | |
207 | } | |
208 | } | |
209 | ||
837255fb | 210 | path[path_len] = '\0'; |
73dcdb9f PE |
211 | db = XrmGetFileDatabase (path); |
212 | xfree (path); | |
213 | return db; | |
837255fb JB |
214 | } |
215 | ||
216 | ||
f3a0bf5c | 217 | static char * |
971de7fb | 218 | gethomedir (void) |
f3a0bf5c | 219 | { |
f3a0bf5c JB |
220 | struct passwd *pw; |
221 | char *ptr; | |
837255fb | 222 | char *copy; |
f3a0bf5c JB |
223 | |
224 | if ((ptr = getenv ("HOME")) == NULL) | |
225 | { | |
1cac1f6f KH |
226 | if ((ptr = getenv ("LOGNAME")) != NULL |
227 | || (ptr = getenv ("USER")) != NULL) | |
f3a0bf5c JB |
228 | pw = getpwnam (ptr); |
229 | else | |
1cac1f6f | 230 | pw = getpwuid (getuid ()); |
837255fb | 231 | |
f3a0bf5c JB |
232 | if (pw) |
233 | ptr = pw->pw_dir; | |
f3a0bf5c JB |
234 | } |
235 | ||
427ec082 | 236 | if (ptr == NULL) |
8fd0f424 | 237 | return xstrdup ("/"); |
f3a0bf5c | 238 | |
23f86fce | 239 | copy = xmalloc (strlen (ptr) + 2); |
837255fb JB |
240 | strcpy (copy, ptr); |
241 | strcat (copy, "/"); | |
f3a0bf5c | 242 | |
837255fb | 243 | return copy; |
f3a0bf5c JB |
244 | } |
245 | ||
837255fb | 246 | |
837255fb | 247 | /* Find the first element of SEARCH_PATH which exists and is readable, |
427ec082 | 248 | after expanding the %-escapes. Return 0 if we didn't find any, and |
837255fb | 249 | the path name of the one we found otherwise. */ |
f3a0bf5c | 250 | |
73dcdb9f | 251 | static XrmDatabase |
28154962 PE |
252 | search_magic_path (const char *search_path, const char *class, |
253 | const char *escaped_suffix) | |
f3a0bf5c | 254 | { |
eec47d6b | 255 | const char *s, *p; |
d4327fec | 256 | |
837255fb | 257 | for (s = search_path; *s; s = p) |
f3a0bf5c | 258 | { |
837255fb JB |
259 | for (p = s; *p && *p != ':'; p++) |
260 | ; | |
427ec082 | 261 | |
0f2cd61f | 262 | if (p > s) |
f3a0bf5c | 263 | { |
73dcdb9f PE |
264 | XrmDatabase db = magic_db (s, p - s, class, escaped_suffix); |
265 | if (db) | |
266 | return db; | |
f3a0bf5c | 267 | } |
0f2cd61f | 268 | else if (*p == ':') |
f3a0bf5c | 269 | { |
73dcdb9f PE |
270 | static char const ns[] = "%N%S"; |
271 | XrmDatabase db = magic_db (ns, strlen (ns), class, escaped_suffix); | |
272 | if (db) | |
273 | return db; | |
f3a0bf5c JB |
274 | } |
275 | ||
837255fb JB |
276 | if (*p == ':') |
277 | p++; | |
f3a0bf5c JB |
278 | } |
279 | ||
280 | return 0; | |
281 | } | |
282 | \f | |
837255fb JB |
283 | /* Producing databases for individual sources. */ |
284 | ||
f3a0bf5c | 285 | static XrmDatabase |
eec47d6b | 286 | get_system_app (const char *class) |
f3a0bf5c | 287 | { |
42ca4633 | 288 | const char *path; |
f3a0bf5c | 289 | |
837255fb | 290 | path = getenv ("XFILESEARCHPATH"); |
58c7da0c | 291 | if (! path) path = PATH_X_DEFAULTS; |
f3a0bf5c | 292 | |
73dcdb9f | 293 | return search_magic_path (path, class, 0); |
f3a0bf5c JB |
294 | } |
295 | ||
837255fb | 296 | |
f3a0bf5c | 297 | static XrmDatabase |
971de7fb | 298 | get_fallback (Display *display) |
f3a0bf5c | 299 | { |
f3a0bf5c JB |
300 | return NULL; |
301 | } | |
302 | ||
837255fb | 303 | |
f3a0bf5c | 304 | static XrmDatabase |
eec47d6b | 305 | get_user_app (const char *class) |
f3a0bf5c | 306 | { |
73dcdb9f | 307 | XrmDatabase db = 0; |
42ca4633 | 308 | const char *path; |
837255fb JB |
309 | |
310 | /* Check for XUSERFILESEARCHPATH. It is a path of complete file | |
311 | names, not directories. */ | |
73dcdb9f PE |
312 | path = getenv ("XUSERFILESEARCHPATH"); |
313 | if (path) | |
314 | db = search_magic_path (path, class, 0); | |
837255fb | 315 | |
73dcdb9f PE |
316 | if (! db) |
317 | { | |
837255fb JB |
318 | /* Check for APPLRESDIR; it is a path of directories. In each, |
319 | we have to search for LANG/CLASS and then CLASS. */ | |
73dcdb9f PE |
320 | path = getenv ("XAPPLRESDIR"); |
321 | if (path) | |
322 | { | |
323 | db = search_magic_path (path, class, "/%L/%N"); | |
324 | if (!db) | |
325 | db = search_magic_path (path, class, "/%N"); | |
326 | } | |
327 | } | |
427ec082 | 328 | |
73dcdb9f PE |
329 | if (! db) |
330 | { | |
837255fb JB |
331 | /* Check in the home directory. This is a bit of a hack; let's |
332 | hope one's home directory doesn't contain any %-escapes. */ | |
73dcdb9f PE |
333 | char *home = gethomedir (); |
334 | db = search_magic_path (home, class, "%L/%N"); | |
335 | if (! db) | |
336 | db = search_magic_path (home, class, "%N"); | |
337 | xfree (home); | |
f3a0bf5c | 338 | } |
3fa18fb2 | 339 | |
73dcdb9f | 340 | return db; |
f3a0bf5c JB |
341 | } |
342 | ||
837255fb | 343 | |
f3a0bf5c | 344 | static XrmDatabase |
971de7fb | 345 | get_user_db (Display *display) |
f3a0bf5c JB |
346 | { |
347 | XrmDatabase db; | |
348 | char *xdefs; | |
349 | ||
2c8d1900 | 350 | #ifdef PBaseSize /* Cheap way to test for X11R4 or later. */ |
b631f177 JB |
351 | xdefs = XResourceManagerString (display); |
352 | #else | |
a2a4d43e | 353 | xdefs = display->xdefaults; |
b631f177 JB |
354 | #endif |
355 | ||
f3a0bf5c JB |
356 | if (xdefs != NULL) |
357 | db = XrmGetStringDatabase (xdefs); | |
358 | else | |
359 | { | |
837255fb JB |
360 | char *home; |
361 | char *xdefault; | |
f3a0bf5c | 362 | |
837255fb | 363 | home = gethomedir (); |
38182d90 | 364 | xdefault = xmalloc (strlen (home) + sizeof ".Xdefaults"); |
837255fb | 365 | strcpy (xdefault, home); |
f3a0bf5c JB |
366 | strcat (xdefault, ".Xdefaults"); |
367 | db = XrmGetFileDatabase (xdefault); | |
1b6d8cf0 DN |
368 | xfree (home); |
369 | xfree (xdefault); | |
f3a0bf5c JB |
370 | } |
371 | ||
d8717d15 | 372 | #ifdef HAVE_XSCREENRESOURCESTRING |
9b37b1c2 JB |
373 | /* Get the screen-specific resources too. */ |
374 | xdefs = XScreenResourceString (DefaultScreenOfDisplay (display)); | |
375 | if (xdefs != NULL) | |
fdce0b39 JB |
376 | { |
377 | XrmMergeDatabases (XrmGetStringDatabase (xdefs), &db); | |
378 | XFree (xdefs); | |
379 | } | |
9b37b1c2 JB |
380 | #endif |
381 | ||
f3a0bf5c JB |
382 | return db; |
383 | } | |
384 | ||
385 | static XrmDatabase | |
971de7fb | 386 | get_environ_db (void) |
f3a0bf5c JB |
387 | { |
388 | XrmDatabase db; | |
389 | char *p; | |
a3d9c2a4 | 390 | char *path = 0; |
f3a0bf5c JB |
391 | |
392 | if ((p = getenv ("XENVIRONMENT")) == NULL) | |
393 | { | |
a3d9c2a4 PE |
394 | static char const xdefaults[] = ".Xdefaults-"; |
395 | char *home = gethomedir (); | |
61655b89 DA |
396 | char const *host = SSDATA (Vsystem_name); |
397 | ptrdiff_t pathsize = (strlen (home) + sizeof xdefaults | |
398 | + SBYTES (Vsystem_name)); | |
38182d90 | 399 | path = xrealloc (home, pathsize); |
a3d9c2a4 | 400 | strcat (strcat (path, xdefaults), host); |
f3a0bf5c JB |
401 | p = path; |
402 | } | |
403 | ||
404 | db = XrmGetFileDatabase (p); | |
837255fb | 405 | |
1b6d8cf0 | 406 | xfree (path); |
837255fb | 407 | |
f3a0bf5c JB |
408 | return db; |
409 | } | |
410 | \f | |
837255fb JB |
411 | /* External interface. */ |
412 | ||
f3a0bf5c JB |
413 | /* Types of values that we can find in a database */ |
414 | ||
415 | #define XrmStringType "String" /* String representation */ | |
ac64929e | 416 | static XrmRepresentation x_rm_string; /* Quark representation */ |
f3a0bf5c JB |
417 | |
418 | /* Load X resources based on the display and a possible -xrm option. */ | |
419 | ||
420 | XrmDatabase | |
eec47d6b DN |
421 | x_load_resources (Display *display, const char *xrm_string, |
422 | const char *myname, const char *myclass) | |
f3a0bf5c | 423 | { |
837255fb | 424 | XrmDatabase user_database; |
f3a0bf5c JB |
425 | XrmDatabase rdb; |
426 | XrmDatabase db; | |
4da4f201 | 427 | char line[256]; |
6ca30ba4 | 428 | |
72391843 | 429 | #if defined USE_MOTIF || !defined HAVE_XFT || !defined USE_LUCID |
3565b346 | 430 | const char *helv = "-*-helvetica-medium-r-*--*-120-*-*-*-*-iso8859-1"; |
72391843 PE |
431 | #endif |
432 | ||
433 | #ifdef USE_MOTIF | |
eec47d6b | 434 | const char *courier = "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1"; |
8d56e206 | 435 | #endif |
f3a0bf5c JB |
436 | |
437 | x_rm_string = XrmStringToQuark (XrmStringType); | |
082dc211 RS |
438 | #ifndef USE_X_TOOLKIT |
439 | /* pmr@osf.org says this shouldn't be done if USE_X_TOOLKIT. | |
440 | I suspect it's because the toolkit version does this elsewhere. */ | |
f3a0bf5c | 441 | XrmInitialize (); |
082dc211 | 442 | #endif |
f3a0bf5c JB |
443 | rdb = XrmGetStringDatabase (""); |
444 | ||
4da4f201 GM |
445 | /* Add some font defaults. If the font `helv' doesn't exist, widgets |
446 | will use some other default font. */ | |
447 | #ifdef USE_MOTIF | |
427ec082 | 448 | |
cf9b4b0b | 449 | sprintf (line, "%s.pane.background: grey75", myclass); |
06bbf618 | 450 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 451 | sprintf (line, "%s*fontList: %s", myclass, helv); |
4da4f201 | 452 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 453 | sprintf (line, "%s*menu*background: grey75", myclass); |
4da4f201 | 454 | XrmPutLineResource (&rdb, line); |
b6a15240 | 455 | sprintf (line, "%s*menubar*background: grey75", myclass); |
4da4f201 | 456 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 457 | sprintf (line, "%s*verticalScrollBar.background: grey75", myclass); |
4da4f201 | 458 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 459 | sprintf (line, "%s*verticalScrollBar.troughColor: grey75", myclass); |
06bbf618 | 460 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 461 | sprintf (line, "%s.dialog*.background: grey75", myclass); |
4da4f201 | 462 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 463 | sprintf (line, "%s*fsb.Text.background: white", myclass); |
4da4f201 | 464 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 465 | sprintf (line, "%s*fsb.FilterText.background: white", myclass); |
4da4f201 | 466 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 467 | sprintf (line, "%s*fsb*DirList.background: white", myclass); |
4da4f201 | 468 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 469 | sprintf (line, "%s*fsb*ItemsList.background: white", myclass); |
4da4f201 | 470 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 471 | sprintf (line, "%s*fsb*background: grey75", myclass); |
4da4f201 | 472 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 473 | sprintf (line, "%s*fsb.Text.fontList: %s", myclass, courier); |
4da4f201 | 474 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 475 | sprintf (line, "%s*fsb.FilterText.fontList: %s", myclass, courier); |
4da4f201 | 476 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 477 | sprintf (line, "%s*fsb*ItemsList.fontList: %s", myclass, courier); |
4da4f201 | 478 | XrmPutLineResource (&rdb, line); |
cf9b4b0b | 479 | sprintf (line, "%s*fsb*DirList.fontList: %s", myclass, courier); |
4da4f201 GM |
480 | XrmPutLineResource (&rdb, line); |
481 | ||
482 | /* Set double click time of list boxes in the file selection | |
483 | dialog from `double-click-time'. */ | |
484 | if (INTEGERP (Vdouble_click_time) && XINT (Vdouble_click_time) > 0) | |
485 | { | |
c2982e87 | 486 | sprintf (line, "%s*fsb*DirList.doubleClickInterval: %"pI"d", |
cf9b4b0b | 487 | myclass, XFASTINT (Vdouble_click_time)); |
4da4f201 | 488 | XrmPutLineResource (&rdb, line); |
c2982e87 | 489 | sprintf (line, "%s*fsb*ItemsList.doubleClickInterval: %"pI"d", |
cf9b4b0b | 490 | myclass, XFASTINT (Vdouble_click_time)); |
4da4f201 GM |
491 | XrmPutLineResource (&rdb, line); |
492 | } | |
493 | ||
494 | #else /* not USE_MOTIF */ | |
427ec082 | 495 | |
fc6c5dfe | 496 | sprintf (line, "Emacs.dialog*.background: grey75"); |
4da4f201 | 497 | XrmPutLineResource (&rdb, line); |
3928f2b6 JD |
498 | #if !defined (HAVE_XFT) || !defined (USE_LUCID) |
499 | sprintf (line, "Emacs.dialog*.font: %s", helv); | |
500 | XrmPutLineResource (&rdb, line); | |
fc6c5dfe | 501 | sprintf (line, "*XlwMenu*font: %s", helv); |
4da4f201 | 502 | XrmPutLineResource (&rdb, line); |
3928f2b6 | 503 | #endif |
fc6c5dfe | 504 | sprintf (line, "*XlwMenu*background: grey75"); |
4da4f201 | 505 | XrmPutLineResource (&rdb, line); |
fc6c5dfe | 506 | sprintf (line, "Emacs*verticalScrollBar.background: grey75"); |
4da4f201 | 507 | XrmPutLineResource (&rdb, line); |
427ec082 | 508 | |
4da4f201 GM |
509 | #endif /* not USE_MOTIF */ |
510 | ||
837255fb JB |
511 | user_database = get_user_db (display); |
512 | ||
513 | /* Figure out what the "customization string" is, so we can use it | |
514 | to decode paths. */ | |
1b6d8cf0 | 515 | xfree (x_customization_string); |
837255fb JB |
516 | x_customization_string |
517 | = x_get_customization_string (user_database, myname, myclass); | |
518 | ||
f3a0bf5c JB |
519 | /* Get application system defaults */ |
520 | db = get_system_app (myclass); | |
521 | if (db != NULL) | |
522 | XrmMergeDatabases (db, &rdb); | |
523 | ||
524 | /* Get Fallback resources */ | |
525 | db = get_fallback (display); | |
526 | if (db != NULL) | |
527 | XrmMergeDatabases (db, &rdb); | |
528 | ||
529 | /* Get application user defaults */ | |
530 | db = get_user_app (myclass); | |
531 | if (db != NULL) | |
532 | XrmMergeDatabases (db, &rdb); | |
533 | ||
534 | /* get User defaults */ | |
837255fb JB |
535 | if (user_database != NULL) |
536 | XrmMergeDatabases (user_database, &rdb); | |
f3a0bf5c JB |
537 | |
538 | /* Get Environment defaults. */ | |
539 | db = get_environ_db (); | |
540 | if (db != NULL) | |
541 | XrmMergeDatabases (db, &rdb); | |
427ec082 | 542 | |
f3a0bf5c JB |
543 | /* Last, merge in any specification from the command line. */ |
544 | if (xrm_string != NULL) | |
545 | { | |
546 | db = XrmGetStringDatabase (xrm_string); | |
547 | if (db != NULL) | |
548 | XrmMergeDatabases (db, &rdb); | |
549 | } | |
550 | ||
551 | return rdb; | |
552 | } | |
553 | ||
837255fb | 554 | |
f3a0bf5c JB |
555 | /* Retrieve the value of the resource specified by NAME with class CLASS |
556 | and of type TYPE from database RDB. The value is returned in RET_VALUE. */ | |
557 | ||
2f7c71a1 AS |
558 | static int |
559 | x_get_resource (XrmDatabase rdb, const char *name, const char *class, | |
560 | XrmRepresentation expected_type, XrmValue *ret_value) | |
f3a0bf5c JB |
561 | { |
562 | XrmValue value; | |
563 | XrmName namelist[100]; | |
564 | XrmClass classlist[100]; | |
565 | XrmRepresentation type; | |
566 | ||
5e617bc2 JB |
567 | XrmStringToNameList (name, namelist); |
568 | XrmStringToClassList (class, classlist); | |
f3a0bf5c JB |
569 | |
570 | if (XrmQGetResource (rdb, namelist, classlist, &type, &value) == True | |
571 | && (type == expected_type)) | |
572 | { | |
573 | if (type == x_rm_string) | |
41ab0754 | 574 | ret_value->addr = (char *) value.addr; |
f3a0bf5c | 575 | else |
72af86bd | 576 | memcpy (ret_value->addr, value.addr, ret_value->size); |
f3a0bf5c JB |
577 | |
578 | return value.size; | |
579 | } | |
580 | ||
581 | return 0; | |
582 | } | |
583 | ||
584 | /* Retrieve the string resource specified by NAME with CLASS from | |
585 | database RDB. */ | |
586 | ||
587 | char * | |
eec47d6b | 588 | x_get_string_resource (XrmDatabase rdb, const char *name, const char *class) |
f3a0bf5c JB |
589 | { |
590 | XrmValue value; | |
591 | ||
8686ac71 JB |
592 | if (inhibit_x_resources) |
593 | /* --quick was passed, so this is a no-op. */ | |
594 | return NULL; | |
595 | ||
f3a0bf5c JB |
596 | if (x_get_resource (rdb, name, class, x_rm_string, &value)) |
597 | return (char *) value.addr; | |
598 | ||
7d652d97 | 599 | return 0; |
f3a0bf5c JB |
600 | } |
601 | \f | |
837255fb JB |
602 | /* Stand-alone test facilities. */ |
603 | ||
f3a0bf5c | 604 | #ifdef TESTRM |
837255fb JB |
605 | |
606 | typedef char **List; | |
607 | #define arg_listify(len, list) (list) | |
608 | #define car(list) (*(list)) | |
609 | #define cdr(list) (list + 1) | |
610 | #define NIL(list) (! *(list)) | |
611 | #define free_arglist(list) | |
612 | ||
613 | static List | |
1dae0f0a | 614 | member (char *elt, List list) |
837255fb JB |
615 | { |
616 | List p; | |
617 | ||
618 | for (p = list; ! NIL (p); p = cdr (p)) | |
619 | if (! strcmp (elt, car (p))) | |
620 | return p; | |
621 | ||
622 | return p; | |
623 | } | |
f3a0bf5c JB |
624 | |
625 | static void | |
1dae0f0a | 626 | fatal (char *msg, char *prog) |
f3a0bf5c | 627 | { |
4ebbdd67 | 628 | fprintf (stderr, msg, prog); |
1dae0f0a | 629 | exit (1); |
f3a0bf5c JB |
630 | } |
631 | ||
1dae0f0a AS |
632 | int |
633 | main (int argc, char **argv) | |
f3a0bf5c JB |
634 | { |
635 | Display *display; | |
837255fb | 636 | char *displayname, *resource_string, *class, *name; |
f3a0bf5c | 637 | XrmDatabase xdb; |
837255fb | 638 | List arg_list, lp; |
f3a0bf5c JB |
639 | |
640 | arg_list = arg_listify (argc, argv); | |
641 | ||
642 | lp = member ("-d", arg_list); | |
643 | if (!NIL (lp)) | |
644 | displayname = car (cdr (lp)); | |
645 | else | |
646 | displayname = "localhost:0.0"; | |
647 | ||
648 | lp = member ("-xrm", arg_list); | |
7d652d97 | 649 | resource_string = NIL (lp) ? 0 : car (cdr (lp)); |
f3a0bf5c JB |
650 | |
651 | lp = member ("-c", arg_list); | |
652 | if (! NIL (lp)) | |
653 | class = car (cdr (lp)); | |
654 | else | |
655 | class = "Emacs"; | |
656 | ||
837255fb JB |
657 | lp = member ("-n", arg_list); |
658 | if (! NIL (lp)) | |
659 | name = car (cdr (lp)); | |
660 | else | |
661 | name = "emacs"; | |
f3a0bf5c | 662 | |
837255fb | 663 | free_arglist (arg_list); |
f3a0bf5c JB |
664 | |
665 | if (!(display = XOpenDisplay (displayname))) | |
666 | fatal ("Can't open display '%s'\n", XDisplayName (displayname)); | |
667 | ||
837255fb | 668 | xdb = x_load_resources (display, resource_string, name, class); |
f3a0bf5c | 669 | |
f3a0bf5c JB |
670 | /* In a real program, you'd want to also do this: */ |
671 | display->db = xdb; | |
f3a0bf5c JB |
672 | |
673 | while (1) | |
674 | { | |
837255fb JB |
675 | char query_name[90]; |
676 | char query_class[90]; | |
677 | ||
678 | printf ("Name: "); | |
679 | gets (query_name); | |
f3a0bf5c | 680 | |
837255fb | 681 | if (strlen (query_name)) |
f3a0bf5c | 682 | { |
837255fb JB |
683 | char *value; |
684 | ||
685 | printf ("Class: "); | |
686 | gets (query_class); | |
687 | ||
688 | value = x_get_string_resource (xdb, query_name, query_class); | |
f3a0bf5c JB |
689 | |
690 | if (value != NULL) | |
837255fb | 691 | printf ("\t%s(%s): %s\n\n", query_name, query_class, value); |
f3a0bf5c JB |
692 | else |
693 | printf ("\tNo Value.\n\n"); | |
694 | } | |
695 | else | |
696 | break; | |
697 | } | |
698 | printf ("\tExit.\n\n"); | |
699 | ||
700 | XCloseDisplay (display); | |
1dae0f0a AS |
701 | |
702 | return 0; | |
f3a0bf5c JB |
703 | } |
704 | #endif /* TESTRM */ |