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