|
|
1.1 root 1: /* $Header: Xrm.c,v 1.2 87/09/03 18:19:16 newman Exp $ */
2: #ifndef lint
3: static char *sccsid = "@(#)Xrm.c 1.11 3/20/87";
4: #endif lint
5:
6: /*
7: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
8: *
9: * All Rights Reserved
10: *
11: * Permission to use, copy, modify, and distribute this software and its
12: * documentation for any purpose and without fee is hereby granted,
13: * provided that the above copyright notice appear in all copies and that
14: * both that copyright notice and this permission notice appear in
15: * supporting documentation, and that the name of Digital Equipment
16: * Corporation not be used in advertising or publicity pertaining to
17: * distribution of the software without specific, written prior permission.
18: *
19: *
20: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26: * SOFTWARE.
27: */
28:
29:
30: #include "Xlib.h"
31: #include "Xlibos.h"
32: #include "Xresource.h"
33: #include "XrmConvert.h"
34: #include "Quarks.h"
35: #include <stdio.h>
36: #include <ctype.h>
37:
38: extern void bcopy();
39:
40: typedef void (*DBEnumProc)();
41:
42: #define HASHSIZE 64
43: #define HASHMASK 63
44: #define HashIndex(quark) (quark & HASHMASK)
45:
46: /*
47: typedef struct _XrmHashBucketRec *XrmHashBucket;
48: */
49: typedef struct _XrmHashBucketRec {
50: XrmHashBucket next;
51: XrmQuark quark;
52: XrmResourceDataBase db;
53: } XrmHashBucketRec;
54:
55: /*
56: typedef XrmHashBucket *XrmHashTable;
57: */
58:
59: /*
60: typedef XrmHashTable XrmSearchList[];
61: */
62:
63: typedef struct _XrmResourceDataBase {
64: XrmRepresentation type;
65: XrmValue val;
66: XrmHashBucket *hashTable;
67: } XrmResourceDataBaseRec;
68:
69:
70: static XrmResourceDataBase rdb = NULL;
71:
72: static Bool FindName(quark, hashTable, ppBucket)
73: register XrmQuark quark;
74: XrmHashTable hashTable;
75: XrmHashBucket **ppBucket;
76: {
77: /* search hashTable (which must be non-NULL) for quark.
78: If found, *ppBucket is the address of the XrmHashBucket that points to it.
79: If not, *ppBucket is the address of the hashTable entry that should
80: point to a new XrmHashBucket; **ppBucket is the XrmHashBucket it
81: should point to.
82: */
83:
84: register XrmHashBucket *pBucket, *pStartBucket;
85:
86: pBucket = pStartBucket = &hashTable[HashIndex(quark)];
87:
88: while ((*pBucket) != NULL) {
89: if ((*pBucket)->quark == quark) {
90: *ppBucket = pBucket;
91: return True;
92: }
93: pBucket = &((*pBucket)->next);
94: }
95: *ppBucket = pStartBucket;
96: return False;
97: }
98:
99:
100: static void SetValue(type, val, pdb)
101: XrmRepresentation type;
102: XrmValue val;
103: XrmResourceDataBase *pdb;
104: {
105: register XrmResourceDataBase db = *pdb;
106:
107: if (db == NULL) {
108: *pdb = db = (XrmResourceDataBase) Xmalloc (sizeof(XrmResourceDataBaseRec));
109: db->type = NULLQUARK;
110: db->val.addr = NULL;
111: db->val.size = 0;
112: db->hashTable = NULL;
113: }
114:
115: db->type = type;
116: if (db->val.addr != NULL)
117: Xfree((char *)db->val.addr);
118: db->val.addr = (caddr_t) Xmalloc(val.size);
119: bcopy((char *)val.addr, (char *)db->val.addr, (int) val.size);
120: db->val.size = val.size;
121: }
122:
123: static void MakeNewDb(quarks, type, val, pdb)
124: register XrmQuarkList quarks;
125: XrmRepresentation type;
126: XrmValue val;
127: XrmResourceDataBase *pdb;
128: {
129: register XrmResourceDataBase db;
130: register XrmHashBucket *pBucket, bucket;
131:
132: /* make a new database tree rooted at *pdb, initialized with quark/val */
133: /* quarks[0] can be NULLQUARK, in which case just set the value */
134:
135: for (; *quarks != NULLQUARK; quarks++) {
136: db = *pdb = (XrmResourceDataBase) Xmalloc(sizeof(XrmResourceDataBaseRec));
137: db->type = NULLQUARK;
138: db->val.size = 0;
139: db->val.addr = NULL;
140: db->hashTable = (XrmHashTable) Xmalloc(sizeof(XrmHashBucket) * HASHSIZE);
141: bzero((char *) db->hashTable, sizeof(XrmHashBucket) * HASHSIZE);
142: pBucket = &(db->hashTable[HashIndex(*quarks)]);
143: *pBucket = bucket = (XrmHashBucket) Xmalloc(sizeof(XrmHashBucketRec));
144: bucket->next = NULL;
145: bucket->quark = *quarks;
146: bucket->db = NULL;
147: pdb = &(bucket->db);
148: }
149:
150: SetValue(type, val, pdb);
151: }
152:
153: static void AddNameToLevel(quarks, pBucket, type, val)
154: XrmQuarkList quarks;
155: XrmHashBucket *pBucket;
156: XrmRepresentation type;
157: XrmValue val;
158: {
159: /* add a new bucket to this level at pBucket */
160:
161: register XrmHashBucket bucket;
162:
163: /* Prepend new bucket to front of list */
164: bucket = (XrmHashBucket) Xmalloc(sizeof(XrmHashBucketRec));
165: bucket->next = *pBucket;
166: *pBucket = bucket;
167: bucket->quark = *quarks;
168: bucket->db = NULL;
169:
170: MakeNewDb(&quarks[1], type, val, &(bucket->db));
171:
172: }
173:
174: static void PutEntry(quarks, type, val, db)
175: register XrmQuarkList quarks;
176: XrmRepresentation type;
177: XrmValue val;
178: register XrmResourceDataBase *db;
179: {
180: XrmHashBucket *pBucket;
181:
182: for (; *quarks != NULLQUARK; quarks++) {
183: if (*db == NULL) {
184: MakeNewDb(quarks, type, val, db);
185: return;
186: }
187: if (! FindName(*quarks, (*db)->hashTable, &pBucket)) {
188: AddNameToLevel(quarks, pBucket, type, val);
189: return;
190: }
191: db = &((*pBucket)->db);
192: }
193:
194: /* update value for entry i */
195: SetValue(type, val, db);
196:
197: }
198:
199: static Bool GetEntry(names, classes, type, val, hashTable)
200: register XrmNameList names;
201: register XrmClassList classes;
202: XrmRepresentation *type;
203: XrmValue *val;
204: register XrmHashTable hashTable;
205: {
206: register XrmHashBucket bucket;
207: register XrmHashTable nextHashTable;
208:
209: for (; *names != NULLQUARK; names++, classes++) {
210: bucket = hashTable[HashIndex(*names)];
211: while (bucket != NULL) {
212: if (bucket->quark == *names) {
213: if (names[1] == NULLQUARK) {
214: *val = bucket->db->val;
215: /* Must be leaf node with data, else doesn't really match */
216: if ((*val).addr) {
217: *type = bucket->db->type;
218: return True;
219: } else
220: return False;
221: } else if ((nextHashTable = bucket->db->hashTable)
222: && GetEntry(names+1, classes+1, type, val, nextHashTable)) {
223: return True;
224: } else {
225: break;
226: }
227: }
228: bucket = bucket->next;
229: }
230: bucket = hashTable[HashIndex(*classes)];
231: while (bucket != NULL) {
232: if (bucket->quark == *classes) {
233: if (classes[1] == NULLQUARK) {
234: *val = bucket->db->val;
235: /* Must be leaf node with data, else doesn't really match */
236: if ((*val).addr) {
237: *type = bucket->db->type;
238: return True;
239: } else
240: return False;
241: } else if ((nextHashTable = bucket->db->hashTable)
242: && GetEntry(names+1, classes+1, type, val, nextHashTable)) {
243: return True;
244: } else {
245: break;
246: }
247: }
248: bucket = bucket->next;
249: }
250: }
251: return False;
252: }
253:
254:
255: static int searchListCount;
256:
257: static void GetSearchList(names, classes, searchList, hashTable)
258: register XrmNameList names;
259: register XrmClassList classes;
260: XrmSearchList searchList;
261: register XrmHashTable hashTable;
262: {
263: register XrmHashBucket bucket;
264: register XrmHashTable nextHashTable;
265:
266: for (; *names != NULLQUARK; names++, classes++) {
267: bucket = hashTable[HashIndex(*names)];
268: while (bucket != NULL) {
269: if (bucket->quark == *names) {
270: nextHashTable = bucket->db->hashTable;
271: if (nextHashTable) {
272: if (names[1] != NULLQUARK)
273: GetSearchList(names+1,classes+1,
274: searchList,nextHashTable);
275: searchList[searchListCount++] = nextHashTable;
276: }
277: break;
278: }
279: bucket = bucket->next;
280: }
281: bucket = hashTable[HashIndex(*classes)];
282: while (bucket != NULL) {
283: if (bucket->quark == *classes) {
284: nextHashTable = bucket->db->hashTable;
285: if (nextHashTable) {
286: if (classes[1] != NULLQUARK)
287: GetSearchList(names+1,classes+1,
288: searchList,nextHashTable);
289: searchList[searchListCount++] = nextHashTable;
290: }
291: break;
292: }
293: bucket = bucket->next;
294: }
295: }
296: }
297:
298: void XrmGetSearchList(names, classes, searchList)
299: XrmNameList names;
300: XrmClassList classes;
301: XrmSearchList searchList; /* RETURN */
302: {
303: searchListCount = 0;
304: if (rdb && rdb->hashTable) {
305: GetSearchList(names, classes, searchList, rdb->hashTable);
306: searchList[searchListCount++] = rdb->hashTable;
307: }
308: searchList[searchListCount] = NULL;
309: }
310:
311: void XrmGetSearchResource(dpy, searchList, name, class, type, pVal)
312: Display *dpy;
313: register XrmSearchList searchList;
314: register XrmName name;
315: register XrmClass class;
316: XrmAtom type;
317: XrmValue *pVal; /* RETURN */
318: {
319: register XrmHashBucket bucket;
320: register int nameHash = HashIndex(name);
321: register int classHash = HashIndex(class);
322:
323: for (; (*searchList) != NULL; searchList++) {
324: bucket = (*searchList)[nameHash];
325: while (bucket != NULL) {
326: if (bucket->quark == name) {
327: if (bucket->db->val.addr != NULL) {
328: /* Leaf node, it really matches */
329: _XrmConvert(dpy, bucket->db->type, bucket->db->val,
330: XrmAtomToRepresentation(type), pVal);
331: return;
332: }
333: break;
334: }
335: bucket = bucket->next;
336: }
337: bucket = (*searchList)[classHash];
338: while (bucket != NULL) {
339: if (bucket->quark == class) {
340: if (bucket->db->val.addr != NULL) {
341: /* Leaf node, it really matches */
342: _XrmConvert(dpy, bucket->db->type, bucket->db->val,
343: XrmAtomToRepresentation(type), pVal);
344: return;
345: }
346: break;
347: }
348: bucket = bucket->next;
349: }
350: }
351: (*pVal).addr = NULL;
352: (*pVal).size = 0;
353: }
354:
355:
356: void XrmPutResource(quarks, type, value)
357: XrmQuarkList quarks;
358: XrmRepresentation type;
359: XrmValue value;
360: {
361: PutEntry(quarks, type, value, &rdb);
362: }
363:
364: void XrmSetCurrentDataBase(db)
365: XrmResourceDataBase db;
366: {
367: rdb = db;
368: }
369:
370: void XrmGetCurrentDataBase(db)
371: XrmResourceDataBase *db;
372: {
373: if (db != NULL)
374: *db = rdb;
375: }
376:
377: void XrmGetDataBase(magicCookie, db)
378: FILE *magicCookie;
379: XrmResourceDataBase *db;
380: {
381: char buf[1000], *s, *valStr;
382: XrmQuark nl[100];
383: int i;
384: XrmResourceDataBase odb = rdb;
385: XrmValue val;
386:
387: *db = NULL;
388: if (magicCookie == NULL)
389: return;
390:
391: rdb = NULL;
392: for (;;) {
393: s = fgets(buf, sizeof(buf), magicCookie);
394: if (s == NULL) break;
395: for (; isspace(s[0]); s++) ;
396: if ((s[0] == '\0') || (s[0] == '#')) continue;
397: i = strlen(s);
398: if (s[i-1] == '\n') s[i-1] = '\0';
399: for (i=0 ; ; i++) {
400: if (s[i] == '\0') {
401: valStr = "";
402: break;
403: }
404: if ((s[i] == ':') || isspace(s[i])) {
405: valStr = &s[i+1];
406: for (; isspace(valStr[0]); valStr++) ;
407: s[i] = '\0';
408: break;
409: }
410: }
411: XrmStringToQuarkList(s, nl);
412: val.size = strlen(valStr)+1;
413: val.addr = (caddr_t) valStr;
414: XrmPutResource(&nl[0], XrmQString, val);
415: }
416: *db = rdb;
417: rdb = odb;
418: }
419:
420: static void Enum(quarks, count, db, cd, proc)
421: XrmQuarkList quarks;
422: unsigned count;
423: XrmResourceDataBase db;
424: unspecified cd;
425: DBEnumProc proc;
426: {
427: unsigned int i;
428: XrmHashBucket bucket;
429:
430: if (db == NULL) return;
431: if (db->hashTable != NULL) {
432: quarks[count+1] = NULLQUARK;
433: for (i=0; i < HASHSIZE; i++) {
434: bucket = db->hashTable[i];
435: while (bucket != NULL) {
436: quarks[count] = bucket->quark;
437: Enum(quarks, count+1, bucket->db, cd, proc);
438: bucket = bucket->next;
439: }
440: }
441: }
442: quarks[count] = NULLQUARK;
443: if (db->val.addr != NULL) proc(quarks, db->type, db->val, cd);
444: }
445:
446: static void EnumerateDataBase(db, cd, proc)
447: XrmResourceDataBase db;
448: unspecified cd;
449: DBEnumProc proc;
450: {
451: XrmQuark nl[100];
452: Enum(nl, 0, db, cd, proc);
453: }
454:
455: void PrintQuark(quark)
456: XrmQuark quark;
457: {
458: (void) printf("%s", XrmQuarkToAtom(quark));
459: }
460:
461: void PrintQuarkList(quarks)
462: XrmQuarkList quarks;
463: {
464: Bool firstNameSeen;
465:
466: for (firstNameSeen = False; (*quarks) != NULLQUARK; quarks++) {
467: if (firstNameSeen) (void) printf(".");
468: firstNameSeen = True;
469: PrintQuark(*quarks);
470: }
471: }
472:
473: static void DumpEntry(quarks, type, val, stream)
474: XrmQuarkList quarks;
475: XrmRepresentation type;
476: XrmValue val;
477: FILE *stream;
478: {
479:
480: register unsigned int i;
481:
482: for (i=0; quarks[i] != NULLQUARK; i++) {
483: if (i != 0) (void) fprintf(stream, ".");
484: (void) fprintf(stream, "%s", XrmQuarkToAtom(*quarks));
485: }
486: if (type == XrmQString) {
487: (void) fprintf(stream, ":\t%s\n", val.addr);
488: } else {
489: (void) fprintf(stream, "!%s:\t", XrmRepresentationToAtom(type));
490: for (i = 0; i < val.size; i++)
491: (void) fprintf(stream, "%02x", (int) val.addr[i]);
492: (void) fprintf(stream, "\n");
493: }
494: }
495:
496: void XrmPutDataBase(magicCookie, db)
497: FILE *magicCookie;
498: XrmResourceDataBase db;
499: {
500: EnumerateDataBase(db, (unspecified) magicCookie, DumpEntry);
501: }
502:
503: void XrmMergeDataBases(new, into)
504: XrmResourceDataBase new, *into;
505: {
506: EnumerateDataBase(new, (unspecified) into, PutEntry);
507: }
508:
509: void XrmGetResource(dpy, names, classes, destType, val)
510: Display *dpy;
511: XrmNameList names;
512: XrmClassList classes;
513: XrmRepresentation destType;
514: XrmValue *val;
515: {
516: XrmRepresentation fromType;
517: XrmValue from;
518:
519: if (rdb && rdb->hashTable
520: && GetEntry(names, classes, &fromType, &from, rdb->hashTable)) {
521: _XrmConvert(dpy, fromType, from, destType, val);
522: } else {
523: (*val).addr = NULL;
524: (*val).size = 0;
525: }
526: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.