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