Initial commit of pristine erwise source
[erwise] / erwise / Config.c
1 #include "Includes.h"
2
3 #define BUFFER_SIZE 79
4 #ifndef TRUE
5 #define TRUE  1
6 #define FALSE 0
7 #endif
8
9 #define INDENT_STR  "    "
10
11 static char *strdupmax(char *str, int length);
12 static char *parseid(char *str);
13 static char *parsevalue(char *str);
14 static char *readline(FILE * fp);
15
16 static int ConfigLines = 0;
17
18
19 static Config_t Fonts[] =
20 {
21     {RESOURCE, C_FONT_NORMAL, (void *) "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1"},
22     {RESOURCE, C_FONT_LIST, (void *) "8x13"},
23     {RESOURCE, C_FONT_LISTCOMPACT, (void *) "6x13"},
24     {RESOURCE, C_FONT_GLOSSARY, (void *) "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1"},
25     {RESOURCE, C_FONT_GLOSSARYCOMPACT, (void *) "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1"},
26     {RESOURCE, C_FONT_EXAMPLE, (void *) "7x13"},
27     {RESOURCE, C_FONT_LISTING, (void *) "7x13"},
28     {RESOURCE, C_FONT_ADDRESS, (void *) "8x13"},
29     {RESOURCE, C_FONT_HEADER1, (void *) "-adobe-times-medium-r-normal--20-140-100-100-p-96-iso8859-1"},
30     {RESOURCE, C_FONT_HEADER2, (void *) "-adobe-times-medium-r-normal--18-180-75-75-p-94-iso8859-1"},
31     {RESOURCE, C_FONT_HEADER3, (void *) "-adobe-times-medium-r-normal--17-120-100-100-p-84-iso8859-1"},
32     {RESOURCE, C_FONT_HEADER4, (void *) "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"},
33     {RESOURCE, C_FONT_HEADER5, (void *) "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"},
34     {RESOURCE, C_FONT_HEADER6, (void *) "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"},
35     {RESOURCE, C_FONT_HEADER7, (void *) "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"},
36     {EOC, (char *) NULL, (void *) NULL}
37 };
38
39
40 static Config_t GlobalSettings[] =
41 {
42     {RESOURCE, C_TOPMARGIN, (void *) "0"},
43     {RESOURCE, C_BOTTOMMARGIN, (void *) "0"},
44     {RESOURCE, C_LEFTMARGIN, (void *) "0"},
45     {RESOURCE, C_RIGHTMARGIN, (void *) "0"},
46     {RESOURCE, C_FIXEDWIDTHMODE, (void *) "Off"},
47     {RESOURCE, C_FIXEDWIDTH, (void *) "560"},
48     {RESOURCE, C_ONEPAGEMODE, (void *) "Off"},
49     {RESOURCE, C_WIDTH, (void *) "560"},
50     {RESOURCE, C_HEIGHT, (void *) "600"},
51     {RESOURCE, C_DOUBLECLICKTIME, (void *) "500"},
52     {RESOURCE, C_SEARCH, (void *) "Fixed"},
53     {RESOURCE, C_CONTROLPANEL, (void *) "Fixed"},
54     {RESOURCE, C_LIST, (void *) "Fixed"},
55     {RESOURCE, C_RECALL, (void *) "Fixed"},
56     {RESOURCE, C_PAGESETTINGS, (void *) "Fixed"},
57     {EOC, (char *) NULL, (void *) NULL}
58 };
59
60
61 static Config_t Print[] =
62 {
63     {RESOURCE, C_COMMAND, (void *) "lpr"},
64     {RESOURCE, C_FILENAME, (void *) "print.out"},
65     {RESOURCE, C_PRINTTOFILE, (void *) "False"},
66     {RESOURCE, C_TOPMARGIN, (void *) "0"},
67     {RESOURCE, C_BOTTOMMARGIN, (void *) "0"},
68     {RESOURCE, C_LEFTMARGIN, (void *) "0"},
69     {RESOURCE, C_RIGHTMARGIN, (void *) "0"},
70     {RESOURCE, C_WIDTH, (void *) "80"},
71     {EOC, (char *) NULL, (void *) NULL}
72 };
73
74
75 static Config_t Defaults[] =
76 {
77     {DYNAMIC_PTR, C_DEFAULTSTABLE, (void *) NULL},
78     {EOC, (char *) NULL, (void *) NULL}
79 };
80
81
82 static Config_t KeyBindings[] =
83 {
84     {RESOURCE, C_GETPAGE, (void *) "Return"},
85     {RESOURCE, C_PREVWORD, (void *) "Left"},
86     {RESOURCE, C_NEXTWORD, (void *) "Right"},
87     {RESOURCE, C_PREVTAG, (void *) "Up"},
88     {RESOURCE, C_NEXTTAG, (void *) "Down"},
89     {RESOURCE, C_CLOSE, (void *) "^c"},
90     {RESOURCE, C_SEARCH, (void *) "^s"},
91     {RESOURCE, C_SETTINGS, (void *) "S"},
92     {RESOURCE, C_PRINTDOC, (void *) "p"},
93     {RESOURCE, C_LIST, (void *) "L"},
94     {EOC, (char *) NULL, (void *) NULL}
95 };
96
97
98 Config_t Config[] =
99 {
100     {COMMENT, C_COMMENT, (void *) "Erwise configuration file"},
101     {BLOCK, C_FONTS, (void *) &Fonts},
102     {BLOCK, C_KEYBINDINGS, (void *) &KeyBindings},
103     {BLOCK, C_PRINT, (void *) &Print},
104     {BLOCK, C_GLOBALSETTINGS, (void *) &GlobalSettings},
105     {DYNAMIC, C_DEFAULTS, (void *) &Defaults},
106     {EOC, (char *) NULL, (void *) NULL}
107 };
108
109
110 /*
111  * misc routines
112  */
113 static char *
114  strdupmax(str, length)
115 char *str;
116 int length;
117 {
118     char *dup = (char *) NULL;
119
120     if (str) {
121         dup = (char *) malloc((length + 1) * sizeof(char));
122         strncpy(dup, str, length);
123         dup[length] = '\0';
124     }
125     return dup;
126 }
127
128
129 static char *
130  stripnewline(str)
131 char *str;
132 {
133     int length;
134
135     if (str) {
136         length = strlen(str);
137         if (length && (str[length - 1] == '\n'))
138             str[length - 1] = '\0';
139     }
140     return str;
141 }
142
143
144 /*
145  * config's code starts here
146  */
147 static char *
148  readline(fp)
149 FILE *fp;
150 {
151     char buffer[BUFFER_SIZE + 1];
152     char *line = (char *) NULL;
153     char *data;
154     int length = 1;
155
156     line = (char *) malloc(sizeof(char));
157     line[0] = '\0';
158
159     while (!feof(fp) && !strrchr(line, '\n')) {
160         if (data = fgets(buffer, BUFFER_SIZE, fp)) {
161             line =
162                 (char *) realloc(line, (strlen(data) + length) * sizeof(char));
163             strcat(line, data);
164             length = strlen(line) + 1;
165         }
166     }
167 #ifdef DEBUG_CONFIG
168     printf("read line: '%s'\n", line);
169 #endif
170     ConfigLines++;
171     return line;
172 }
173
174
175 /*
176  * returns a copy of id
177  */
178 static char *
179  parseid(str)
180 char *str;
181 {
182     char *ptr, *id = (char *) NULL;
183     int length = 0;
184
185     while (str && *str && isspace(*str))
186         str++;
187     ptr = str;
188     while (str && *str && !isspace(str[length]))
189         length++;
190     id = strdupmax(ptr, length);
191 #ifdef DEBUG_CONFIG
192     printf("id: '%s'\n", id);
193 #endif
194     return id;
195 }
196
197
198 /*
199  * returns a copy of value
200  */
201 static char *
202  parsevalue(str)
203 char *str;
204 {
205     char *ptr;
206     char *value = (char *) NULL;
207
208     if (ptr = strchr(str, '=')) {
209         ptr++;
210         while (ptr && *ptr && isspace(*ptr))
211             ptr++;
212         value = stripnewline(strdup(ptr));
213     }
214     return value;
215 }
216
217
218 static Config_t *
219  getitem(id, table)
220 char *id;
221 Config_t *table;
222 {
223     Config_t *walker;
224
225     walker = table;
226     while (walker && (walker->type != EOC)) {
227         if (!strcmp(id, walker->id))
228             return (walker);
229         walker++;
230     }
231     return ((Config_t *) NULL);
232 }
233
234
235 ConfigType_t
236 getidtype(id, table)
237 char *id;
238 Config_t *table;
239 {
240     Config_t *walker;
241
242     if (!strncmp(id, "{", 1))
243         return (START_OF_BLOCK);
244     if (!strncmp(id, "}", 1))
245         return (END_OF_BLOCK);
246     if (!strncmp(id, "", 1))
247         return (EMPTY);
248     if (!strncmp(id, "#", 1))
249         return (COMMENT);
250
251     if (walker = getitem(id, table))
252         return (walker->type);
253     return (UNKNOWN);
254 }
255
256
257 static char *
258  parsedynamicobject(line)
259 char *line;
260 {
261     char *ptr;
262
263     ptr = line;
264     while (ptr && *ptr && isspace(*ptr))
265         ptr++;
266     return (stripnewline(strdup(ptr)));
267 }
268
269
270 static int restoredynamicblock(fp, table)
271 FILE *fp;
272 Config_t *table;
273 {
274     char *line;
275     char *id;
276     int done = FALSE;
277     char **items = (char **) NULL;
278     int count = 0;
279
280     do {
281         line = readline(fp);
282         if (line[0] == '\0')
283             done = TRUE;
284         else {
285             id = parseid(line);
286             switch (getidtype(id, table)) {
287             case END_OF_BLOCK:
288                 done = TRUE;
289             case START_OF_BLOCK:
290                 break;
291             default:
292                 if (!count) {
293                     count = 1;
294                     items = (char **) malloc(2 * sizeof(char *));
295                 } else {
296                     count++;
297                     items =
298                         (char **) realloc(items, (count + 1) * sizeof(char *));
299                 }
300                 items[count - 1] = parsedynamicobject(line);
301                 items[count] = (char *) NULL;
302 #ifdef DEBUG_CONFIG
303                 printf("added to count[%d] value '%s'\n",
304                        count - 1, items[count - 1]);
305 #endif
306                 break;
307             }
308             free(id);
309         }
310         free(line);
311     } while (!done);
312     table->value = (void *) items;
313     return 0;
314 }
315
316
317 static void *
318  setitemvalue(item, value)
319 Config_t *item;
320 void *value;
321 {
322     void *oldvalue = (void *) NULL;
323
324     switch (item->type) {
325     case DYNAMIC_PTR:
326         oldvalue = item->value;
327         item->value = value;
328         break;
329     case RESOURCE:
330         if (item->value)
331             free(item->value);
332         item->value = value;
333         break;
334     default:
335         /* error recovery - not needed? */
336         fprintf(stderr, "unknown type for given item\n");
337     }
338     return oldvalue;
339 }
340
341
342 static int restoreblock(fp, table)
343 FILE *fp;
344 Config_t *table;
345 {
346     char *id, *value;
347     char *line;
348     int done = FALSE;
349     int ret;
350     Config_t *item;
351     int blockcount = 0;
352     int unknown = FALSE;
353     char *syncline;
354     int syncdone;
355
356 #ifdef DEBUG_CONFIG
357     printf("parsing block\n");
358 #endif
359     while (!feof(fp) && !done) {
360         line = readline(fp);
361         if (line[0] == '\0') {
362             id = (char *) NULL;
363         } else {
364             id = parseid(line);
365             item = getitem(id, table);
366             switch (getidtype(id, table)) {
367             case RESOURCE:
368                 value = parsevalue(line);
369                 /* we don't care about this return value... */
370                 value = setitemvalue(item, (void *) strdup(value));
371                 unknown = FALSE;
372                 break;
373             case BLOCK:
374 #ifdef DEBUG_CONFIG
375                 printf("block: '%s'\n", id);
376 #endif
377                 ret = restoreblock(fp, (Config_t *) item->value);
378                 unknown = FALSE;
379                 break;
380             case START_OF_BLOCK:
381                 if (!unknown)
382                     blockcount++;
383                 else {
384 #ifdef DEBUG_CONFIG
385                     printf("syncing\n");
386 #endif
387                     syncdone = FALSE;
388                     while (!syncdone && !feof(fp) && (syncline = readline(fp))) {
389                         if (strchr(syncline, '}'))
390                             syncdone = TRUE;
391                         free(syncline);
392                     }
393                 }
394                 unknown = FALSE;
395                 break;
396             case END_OF_BLOCK:
397                 blockcount--;
398                 if (blockcount == 0)
399                     done = TRUE;
400                 else
401                     fprintf(stderr, "parse error at line %d\n", ConfigLines);
402                 unknown = FALSE;
403                 break;
404             case DYNAMIC:
405 #ifdef DEBUG_CONFIG
406                 printf("dynamic: '%s'\n", id);
407 #endif
408                 ret = restoredynamicblock(fp, (Config_t *) item->value);
409                 unknown = FALSE;
410                 break;
411             case UNKNOWN:
412                 fprintf(stderr, "Unknown tag type '%s'\n", id);
413                 unknown = TRUE;
414                 break;
415             case EMPTY:
416             case COMMENT:
417             default:
418                 unknown = FALSE;
419                 break;
420             }
421         }
422         free(line);
423     }
424     if (blockcount) {
425         if (blockcount < 0)
426             fprintf(stderr, "missing { at %d\n", ConfigLines);
427         if (blockcount > 0)
428             fprintf(stderr, "missing } at %d\n", ConfigLines);
429     }
430 #ifdef DEBUG_CONFIG
431     printf("end of block\n");
432 #endif
433 }
434
435
436 int ConfigRestore(fp)
437 FILE *fp;
438 {
439     ConfigLines = 0;
440     restoreblock(fp, Config);
441 }
442
443
444 static void indent(fp, depth)
445 FILE *fp;
446 int depth;
447 {
448     while (depth-- > 0)
449         fprintf(fp, INDENT_STR);
450 }
451
452
453 int saveblock(fp, table, depth)
454 FILE *fp;
455 Config_t *table;
456 int depth;
457 {
458     Config_t *walker;
459     char **dynamic_object;
460     int ret;
461
462     walker = table;
463     while (walker && (walker->type != EOC)) {
464         switch (walker->type) {
465         case COMMENT:
466             fprintf(fp, "# %s\n", (char *) walker->value);
467             break;
468         case RESOURCE:
469             indent(fp, depth);
470             fprintf(fp, "%s = %s\n", walker->id, (char *) walker->value);
471             break;
472         case DYNAMIC_PTR:
473             if (dynamic_object = (char **) walker->value)
474                 while (*dynamic_object) {
475                     indent(fp, depth);
476                     fprintf(fp, "%s\n", (char *) *dynamic_object);
477                     dynamic_object++;
478                 }
479             break;
480         case BLOCK:
481         case DYNAMIC:
482             fprintf(fp, "\n");
483             indent(fp, depth);
484             fprintf(fp, "%s\n", walker->id);
485             indent(fp, depth);
486             fprintf(fp, "{\n");
487             if (walker->type == BLOCK)
488                 ret = saveblock(fp, (Config_t *) walker->value, depth + 1);
489             else
490                 ret = saveblock(fp, (Config_t *) walker->value, depth + 1);
491             indent(fp, depth);
492             fprintf(fp, "}\n");
493             break;
494             /*
495              * case DYNAMIC: indent(fp, depth - 1); fprintf(fp, "%s\n",
496              * walker->id); indent(fp, depth - 1); fprintf(fp, "{\n"); ret =
497              * saveblock(fp, (Config_t *)walker->value, depth + 1);
498              * indent(fp, depth - 1); fprintf(fp, "}\n"); break;
499              */
500         default:
501             fprintf(stderr, "unknown type for '%s'\n", walker->id);
502         }
503         walker++;
504     }
505 }
506
507
508 int ConfigSave(fp)
509 FILE *fp;
510 {
511     saveblock(fp, Config, 0);
512     fflush(fp);
513 }
514
515
516 static void configinitloop(table)
517 Config_t *table;
518 {
519     Config_t *walker;
520
521     walker = table;
522     while (walker && (walker->type != EOC)) {
523         switch (walker->type) {
524         case RESOURCE:
525             walker->value = (void *) strdup((char *) walker->value);
526 #ifdef DEBUG_CONFIG
527             printf("init: '%s': '%s'\n", walker->id, (void *) walker->value);
528 #endif
529             break;
530         case BLOCK:
531 #ifdef DEBUG_CONFIG
532             printf("init: table = %s\n", walker->id);
533 #endif
534             configinitloop((Config_t *) walker->value);
535             break;
536         }
537         walker++;
538     }
539 }
540
541
542 void ConfigInit(void)
543 {
544     configinitloop(Config);
545 }
546
547
548 void *
549  ConfigGetValue(tableptr, id)
550 void *tableptr;
551 char *id;
552 {
553     Config_t *table = (Config_t *) tableptr;
554     Config_t *item;
555
556     if (!table)
557         table = Config;
558     if (item = getitem(id, table))
559         return (item->value);
560     return ((void *) NULL);
561 }
562
563
564 void *
565  ConfigSetValue(tableptr, id, value)
566 void *tableptr;
567 char *id;
568 void *value;
569 {
570     Config_t *table = (Config_t *) tableptr;
571     void *ret = (void *) NULL;
572     Config_t *item;
573
574     if (!table)
575         table = Config;
576     if (item = getitem(id, table))
577         switch (item->type) {
578         case RESOURCE:
579             if (item->value)
580                 free(item->value);
581             item->value = value;
582             break;
583         case DYNAMIC_PTR:
584             ret = item->value;
585             item->value = value;
586             break;
587         default:
588             ;
589         }
590     return ret;
591 }