|
|
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.