|
|
1.1 ! root 1: #include <copyright.h> ! 2: ! 3: /* $Header: XGetDflt.c,v 10.14 87/09/11 23:19:14 sun Exp $ */ ! 4: /* Copyright (c) 1985, Massachusetts Institute of Technology */ ! 5: ! 6: /* ! 7: * This routine returns options out of the X user preferences file ! 8: * found in XDEFAULT, possibly modified by the .Xdefaults in the user's home ! 9: * directory. It either returns a pointer to ! 10: * the option or returns NULL if option not set. It is patterned after ! 11: * Andrew's file format (why be different for the sake of being different?). ! 12: * Andrew's code was NOT examined before writing this routine. ! 13: * It parses lines of the format "progname.option:value" and returns a pointer ! 14: * to value. ! 15: */ ! 16: ! 17: #include <stdio.h> ! 18: #include <strings.h> ! 19: #include <ctype.h> ! 20: #include "Xlib.h" ! 21: #include "Xutil.h" ! 22: #include "Xlibos.h" ! 23: /* #include "Xdefault.h" */ ! 24: #define XDEFAULTS "/usr/lib/X11/Xdefaults" ! 25: ! 26: #define XOPTIONFILE "/.Xdefaults" /* name in home directory of options ! 27: file. */ ! 28: #define XOPTIONFILE2 "/.X11defaults" /* additional hack; look here first */ ! 29: ! 30: static struct ent { ! 31: struct ent *left; /* next option to left */ ! 32: struct ent *right; /* next option to right */ ! 33: char *oname; /* option name */ ! 34: char *value; /* value for that option */ ! 35: char bal; /* for avl use */ ! 36: } *head; ! 37: ! 38: /*ARGSUSED*/ ! 39: char *XGetDefault(dpy, prog, name) ! 40: Display *dpy; /* display to talk to */ ! 41: char *prog; /* name of program for option */ ! 42: register char *name; /* name of option program wants */ ! 43: { /* to get, for example, "font" */ ! 44: static nent = -1; /* have we been here before? */ ! 45: register struct ent *cur; /* current entry being examined */ ! 46: register int cmp; ! 47: char namebuf[64]; ! 48: register char *pv = namebuf; ! 49: ! 50: strncpy(namebuf, name, sizeof(namebuf)); ! 51: while (*pv) { /* convert upper to lower */ ! 52: if (isupper(*pv)) *pv += 040; ! 53: pv++; ! 54: } ! 55: if (nent == -1) ! 56: nent = ReadFile(prog);/* if not, parse the file.*/ ! 57: if (nent == 0) ! 58: return(NULL); ! 59: cur = head; ! 60: do { ! 61: if ((cmp = strcmp(namebuf, cur->oname)) == 0) ! 62: return(cur->value); ! 63: cur = cmp > 0 ? cur->right : cur->left; ! 64: } while (cur != NULL); ! 65: return(NULL); /* if no match, let him know */ ! 66: } ! 67: ! 68: static ReadFile(prog) ! 69: char *prog; /* program name to match */ ! 70: { ! 71: register char *point,*colon; /* where in the line the keys are */ ! 72: register char *oname, *val; /* new memory for valid option line */ ! 73: register FILE *fptr = NULL; /* preferences file */ ! 74: register char *pv; /* pointer to value for lowering */ ! 75: register int len; ! 76: register int nentries = 0; /* number of entries found */ ! 77: register int first; ! 78: char fname[BUFSIZ]; /* longer than any conceivable size */ ! 79: char line[BUFSIZ]; /* line buffer for each line of file*/ ! 80: char *getenv(); ! 81: char *home = getenv("HOME"); ! 82: ! 83: if ((pv = rindex(prog,'/')) != NULL) ! 84: prog = pv + 1; /* if full path, get last component */ ! 85: for(first = 2 ; first >= 0 ; first--) { ! 86: switch (first) { ! 87: case 2: /* Use any defaults in XDEFAULTS. */ ! 88: fptr = fopen(XDEFAULTS, "r"); ! 89: break; ! 90: ! 91: case 1: ! 92: if (home != NULL) { ! 93: strcpy(fname, home); /* form full path name of file */ ! 94: strcat(fname, XOPTIONFILE); ! 95: fptr = fopen(fname, "r"); ! 96: } else ! 97: fptr = NULL; ! 98: break; ! 99: ! 100: case 0: ! 101: /* read this in last, so entries supercede */ ! 102: if (home != NULL) { /* try home directory */ ! 103: strcpy(fname, home); /* form full path name of file */ ! 104: strcat(fname, XOPTIONFILE2); ! 105: fptr = fopen(fname, "r"); ! 106: } else ! 107: fptr = NULL; ! 108: } ! 109: if(fptr == NULL) ! 110: continue; ! 111: while ( fgets(line, sizeof(line), fptr) != NULL ) { ! 112: if (line[0] == '#') continue; /* comment? */ ! 113: point = index(line,'.'); ! 114: colon = index(line,':'); ! 115: if ( (point == NULL) || (colon == NULL) || (colon < point) ) ! 116: continue; /* both . and : required on line*/ ! 117: *point = 0; ! 118: if ( point != line ) /* check all chars up to '.' */ ! 119: if (strcmp(line, prog) != 0) ! 120: continue; ! 121: ! 122: /* ! 123: * ok, we've passed all the tests, so it is a valid option for ! 124: * this program, or is global option. ! 125: */ ! 126: ! 127: len = strlen(colon); ! 128: if(colon[len-1] == '\n') ! 129: colon[len-1] = '\0'; /* braindamaged fgets call */ ! 130: /* ! 131: * allocate space for text ! 132: */ ! 133: point++; ! 134: len = colon - point; ! 135: for(colon++ ; isspace(*colon) ; colon++); /* skip over spaces */ ! 136: if((oname = (char *)Xmalloc(len + strlen(colon) + 2)) == NULL) { ! 137: fprintf(stderr, "ReadFile: Out of memory\n"); ! 138: exit(1); ! 139: } ! 140: strncpy(oname, point, len); ! 141: oname[len] = 0; ! 142: pv = oname; ! 143: while (*pv) { /* convert upper to lower */ ! 144: if (isupper(*pv)) ! 145: *pv += 040; ! 146: pv++; ! 147: } ! 148: val = oname + len + 1; ! 149: strcpy(val, colon); ! 150: insert(oname, val, &head); ! 151: nentries++; ! 152: } ! 153: fclose(fptr); ! 154: } ! 155: return(nentries); ! 156: } ! 157: ! 158: /* ! 159: * Modified from "Algorithms + Data Structures = Programs", Niklaus Wirth, ! 160: * 1976, section 4.4.7 Balanced Tree Insertion, page 220-221. ! 161: */ ! 162: #define L_EQUILIBRATED 2 ! 163: #define LEFTSLANTED 1 ! 164: #define L_REBALANCE 0 ! 165: ! 166: #define R_EQUILIBRATED 0 ! 167: #define RIGHTSLANTED 1 ! 168: #define R_REBALANCE 2 ! 169: ! 170: static insert(name, val, ent) ! 171: register char *name, *val; ! 172: register struct ent **ent; ! 173: { ! 174: register struct ent *ent1, *ent2; ! 175: register int cmp; ! 176: ! 177: if(*ent == NULL) { /* not in tree, insert it */ ! 178: if((*ent = (struct ent *)Xcalloc(1, sizeof(struct ent))) == ! 179: NULL) { ! 180: fprintf(stderr, "insert: Out of memory\n"); ! 181: exit(1); ! 182: } ! 183: (*ent)->oname = name; ! 184: (*ent)->value = val; ! 185: (*ent)->bal = LEFTSLANTED; ! 186: return(1); ! 187: } ! 188: if((cmp = strcmp(name, (*ent)->oname)) == 0) { /* match */ ! 189: free((*ent)->oname); ! 190: (*ent)->oname = name; ! 191: (*ent)->value = val; ! 192: return(0); ! 193: } ! 194: if(cmp < 0) { ! 195: if(!insert(name, val, &(*ent)->left)) ! 196: return(0); ! 197: /* left branch has grown higher */ ! 198: switch((*ent)->bal) { ! 199: case L_EQUILIBRATED: ! 200: (*ent)->bal = LEFTSLANTED; ! 201: return(0); ! 202: case LEFTSLANTED: ! 203: (*ent)->bal = L_REBALANCE; ! 204: return(1); ! 205: case L_REBALANCE: /* rebalance */ ! 206: if((ent1 = (*ent)->left)->bal == L_REBALANCE) { ! 207: /* single LL rotation */ ! 208: (*ent)->left = ent1->right; ! 209: ent1->right = *ent; ! 210: (*ent)->bal = LEFTSLANTED; ! 211: *ent = ent1; ! 212: } else { ! 213: /* double LR rotation */ ! 214: ent2 = ent1->right; ! 215: ent1->right = ent2->left; ! 216: ent2->left = ent1; ! 217: (*ent)->left = ent2->right; ! 218: ent2->right = *ent; ! 219: (*ent)->bal = (ent2->bal == L_REBALANCE) ? ! 220: L_EQUILIBRATED : LEFTSLANTED; ! 221: ent1->bal = (ent2->bal == L_EQUILIBRATED) ? ! 222: L_REBALANCE : LEFTSLANTED; ! 223: *ent = ent2; ! 224: } ! 225: (*ent)->bal = LEFTSLANTED; ! 226: return(0); ! 227: } ! 228: } ! 229: if(!insert(name, val, &(*ent)->right)) ! 230: return(0); ! 231: /* right branch has grown higher */ ! 232: switch((*ent)->bal) { ! 233: case R_EQUILIBRATED: ! 234: (*ent)->bal = RIGHTSLANTED; ! 235: return(0); ! 236: case RIGHTSLANTED: ! 237: (*ent)->bal = R_REBALANCE; ! 238: return(1); ! 239: case R_REBALANCE: /* rebalance */ ! 240: if((ent1 = (*ent)->right)->bal == R_REBALANCE) { ! 241: /* single RR rotation */ ! 242: (*ent)->right = ent1->left; ! 243: ent1->left = *ent; ! 244: (*ent)->bal = RIGHTSLANTED; ! 245: *ent = ent1; ! 246: } else { ! 247: /* double RL rotation */ ! 248: ent2 = ent1->left; ! 249: ent1->left = ent2->right; ! 250: ent2->right = ent1; ! 251: (*ent)->right = ent2->left; ! 252: ent2->left = *ent; ! 253: (*ent)->bal = (ent2->bal == R_REBALANCE) ? ! 254: R_EQUILIBRATED : RIGHTSLANTED; ! 255: ent1->bal = (ent2->bal == R_EQUILIBRATED) ? ! 256: R_REBALANCE : RIGHTSLANTED; ! 257: *ent = ent2; ! 258: } ! 259: (*ent)->bal = RIGHTSLANTED; ! 260: return(0); ! 261: } ! 262: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.