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