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