aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJim Blandy1993-07-22 22:00:48 +0000
committerJim Blandy1993-07-22 22:00:48 +0000
commit837255fb4917faca45395dbbe703935a42763abc (patch)
tree5fd68f12f9f0a0afea3a6202d233b64ad08051aa /src
parent312c9964678f05111d577958e661f5be06f4643a (diff)
downloademacs-837255fb4917faca45395dbbe703935a42763abc.tar.gz
emacs-837255fb4917faca45395dbbe703935a42763abc.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/xrdb.c533
1 files changed, 371 insertions, 162 deletions
diff --git a/src/xrdb.c b/src/xrdb.c
index f7825a4a60f..106eccaba4c 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -21,6 +21,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21#include "config.h" 21#include "config.h"
22#endif 22#endif
23 23
24#include <stdio.h>
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
@@ -71,13 +73,215 @@ extern struct passwd *getpwuid ();
71extern struct passwd *getpwnam (); 73extern 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
84char *x_get_string_resource ();
85static 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. */
93char *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. */
99char *
100x_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
152static char *
153magic_file_p (string, string_len, class, escaped_suffix, suffix)
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
74static char * 278static char *
75gethomedir (dirname) 279gethomedir ()
76 char *dirname;
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 {
@@ -88,26 +292,22 @@ gethomedir (dirname)
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
94 {
95 ptr = NULL;
96 *dirname = '\0';
97 }
98 } 298 }
99 299
100 if (ptr != NULL) 300 if (ptr == NULL)
101 strcpy (dirname, ptr); 301 return "/";
102 302
103 dirname += strlen (dirname); 303 copy = (char *) malloc (strlen (ptr) + 2);
104 *dirname = '/'; 304 strcpy (copy, ptr);
105 dirname++; 305 strcat (copy, "/");
106 *dirname = '\0';
107 306
108 return dirname; 307 return copy;
109} 308}
110 309
310
111static int 311static int
112file_p (path) 312file_p (path)
113 char *path; 313 char *path;
@@ -119,81 +319,30 @@ file_p (path)
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
123#define X_DEFAULT_SEARCH_PATH "/usr/lib/X11/"
124#endif
125 322
126/* Isn't this just disgusting? */ 323/* Find the first element of SEARCH_PATH which exists and is readable,
324 after expanding the %-escapes. Return 0 if we didn't find any, and
325 the path name of the one we found otherwise. */
127 326
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" 327static char *
129 328search_magic_path (search_path, class, escaped_suffix, suffix)
130static int 329 char *search_path, *class, *escaped_suffix, *suffix;
131decode_magic (string, file, return_path)
132 char *string, *file, *return_path;
133{
134 char *p = string;
135 char *t = return_path;
136
137 while (*p)
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
173static int
174magic_searchpath_decoder (incantation_string, file, return_path)
175 char *incantation_string, *return_path, *file;
176{ 330{
177 register char *s = incantation_string; 331 register char *s, *p;
178 register char *p;
179 332
180 /* Must be big enough for "%N%S". */ 333 for (s = search_path; *s; s = p)
181 register int string_size = MAXPATHLEN;
182 register char *string = (char *) alloca (string_size * sizeof (*string));
183
184 while (*s)
185 { 334 {
186 p = s; 335 for (p = s; *p && *p != ':'; p++)
187 336 ;
188 while (*p && *p != ':') 337
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;
@@ -201,46 +350,43 @@ magic_searchpath_decoder (incantation_string, file, return_path)
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
226static XrmDatabase 369static XrmDatabase
227get_system_app (class) 370get_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;
233 375
234 if ((p = getenv ("XFILESEARCHPATH")) == NULL) 376 path = getenv ("XFILESEARCHPATH");
235 p = X_DEFAULT_SEARCH_PATH; 377 if (! path) path = X_DEFAULT_SEARCH_PATH;
236 378
237 if (! magic_searchpath_decoder (p, class, path)) 379 path = search_magic_path (path, class, 0, 0);
238 return NULL; 380 if (path)
381 {
382 db = XrmGetFileDatabase (path);
383 free (path);
384 }
239 385
240 db = XrmGetFileDatabase (path);
241 return db; 386 return db;
242} 387}
243 388
389
244static XrmDatabase 390static XrmDatabase
245get_fallback (display) 391get_fallback (display)
246 Display *display; 392 Display *display;
@@ -250,46 +396,40 @@ get_fallback (display)
250 return NULL; 396 return NULL;
251} 397}
252 398
399
253static XrmDatabase 400static XrmDatabase
254get_user_app (class) 401get_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. */
409 if (((path = getenv ("XUSERFILESEARCHPATH"))
410 && (file = search_magic_path (path, class, 0, 0)))
411
412 /* Check for APPLRESDIR; it is a path of directories. In each,
413 we have to search for LANG/CLASS and then CLASS. */
414 || ((path = getenv ("XAPPLRESDIR"))
415 && ((file = search_magic_path (path, class, "/%L/%N", 0))
416 || (file = search_magic_path (path, class, "/%N", 0))))
417
418 /* Check in the home directory. This is a bit of a hack; let's
419 hope one's home directory doesn't contain any %-escapes. */
420 || (path = gethomedir (),
421 ((file = search_magic_path (path, class, "%L/%N", 0))
422 || (file = search_magic_path (path, class, "%N", 0)))))
262 { 423 {
263 char homedir[MAXPATHLEN]; 424 XrmDatabase db = XrmGetFileDatabase (file);
264 char *default_magic; 425 free (file);
265 char *p; 426 return db;
266
267 gethomedir (homedir);
268
269 if ((p = getenv ("XAPPLRESDIR")) == NULL)
270 {
271 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N";
272 magic_path = (char *) alloca ((3 * strlen (homedir))
273 + strlen (default_magic));
274 sprintf (magic_path, default_magic, homedir, homedir, homedir);
275 }
276 else
277 {
278 default_magic = "%s/%%L/%%N:%s/%%l/%%N:%s/%%N:%s/%%N";
279 magic_path = (char *) alloca ((3 * strlen (p))
280 + strlen (default_magic)
281 + strlen (homedir));
282 sprintf (magic_path, default_magic, p, p, p, homedir);
283 }
284 } 427 }
285 428 else
286 if (! magic_searchpath_decoder (magic_path, class, path))
287 return NULL; 429 return NULL;
288
289 db = XrmGetFileDatabase (path);
290 return db;
291} 430}
292 431
432
293static XrmDatabase 433static XrmDatabase
294get_user_db (display) 434get_user_db (display)
295 Display *display; 435 Display *display;
@@ -307,11 +447,16 @@ get_user_db (display)
307 db = XrmGetStringDatabase (xdefs); 447 db = XrmGetStringDatabase (xdefs);
308 else 448 else
309 { 449 {
310 char xdefault[MAXPATHLEN]; 450 char *home;
451 char *xdefault;
311 452
312 gethomedir (xdefault); 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
@@ -334,20 +479,44 @@ 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 */
@@ -356,11 +525,12 @@ XrmRepresentation x_rm_string; /* Quark representation */
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
358XrmDatabase 527XrmDatabase
359x_load_resources (display, xrm_string, myclass) 528x_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
@@ -368,6 +538,15 @@ x_load_resources (display, xrm_string, myclass)
368 XrmInitialize (); 538 XrmInitialize ();
369 rdb = XrmGetStringDatabase (""); 539 rdb = XrmGetStringDatabase ("");
370 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);
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)
@@ -384,9 +563,8 @@ x_load_resources (display, xrm_string, myclass)
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 ();
@@ -404,6 +582,7 @@ x_load_resources (display, xrm_string, myclass)
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
@@ -452,9 +631,30 @@ x_get_string_resource (rdb, name, class)
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" 638typedef 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
645static List
646member (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
459static void 659static void
460fatal (msg, prog, x1, x2, x3, x4, x5) 660fatal (msg, prog, x1, x2, x3, x4, x5)
@@ -475,9 +675,9 @@ main (argc, argv)
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
@@ -499,32 +699,41 @@ main (argc, argv)
499 else 699 else
500 class = "Emacs"; 700 class = "Emacs";
501 701
502 free_arglist (arg_list); 702 lp = member ("-n", arg_list);
503 703 if (! NIL (lp))
704 name = car (cdr (lp));
705 else
706 name = "emacs";
504 707
708 free_arglist (arg_list);
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];
721 char query_class[90];
722
723 printf ("Name: ");
724 gets (query_name);
519 725
520 printf ("String: "); 726 if (strlen (query_name))
521 gets (line);
522 if (strlen (line))
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 }