1 /*
2 * @(#)startup.c 1.1 10/21/84
3 *
4 * Startup file processing for the SUN Gremlin picture editor.
5 *
6 * Mark Opperman (opcode@monet.BERKELEY)
7 *
8 */
9
10 #include "gremlin.h"
11 #include <vfont.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <ctype.h>
15
16 /* imports from C */
17
18 extern char *malloc();
19 extern FILE *fopen();
20
21 /* imports from path.c */
22
23 extern PSetPath();
24
25 /* imports from graphics files */
26
27 extern char *font_types[]; /* normally "R", "I", "B", "S" */
28 extern font_sizes[]; /* normally 7, 10, 14, 24 */
29 extern char fontdir[]; /* font directory */
30 extern char stippledir[]; /* stipple directory */
31 extern char stippletype[]; /* stipple font type ("ug" or "cf") */
32 extern stipple_index[]; /* stipple font numbers */
33
34 /* imports from main.c */
35
36 extern Artmode; /* point display size */
37 extern CBRUSH; /* current brush */
38 extern CFONT; /* current font */
39 extern CJUST; /* current text justification */
40 extern CSIZE; /* current size */
41 extern CSTIPPLE; /* current stipple pattern */
42 extern Alignment; /* point alignment indicator */
43 extern Adjustment; /* point adjustment mode */
44 extern GravityOn; /* gravity mode flag */
45 extern Gridon; /* grid mode indicator */
46 extern SymbolicLines; /* pr_vector OK for all lines */
47 extern long timeon_s, timeon_ms; /* current set flash on rate */
48 extern long timeoff_s, timeoff_ms; /* current set flash off rate */
49
50 /* locally defined variables */
51
52 #define STon(s) (strncmp(s, "on", 2) == 0)
53
54 int STERROR = FALSE; /* indicates error on startup */
55
56 static char *lines[] = { "broken", "dashed", "dotted",
57 "medium", "narrow", "thick", NULL };
58 static lnum[] = { 2, 4, 1, 6, 5, 3 };
59
60 static char *textpos[JUSTMODES] = { "tl", "tc", "tr",
61 "cl", "cc", "cr",
62 "bl", "bc", "br",
63 "lt", "ct", "rt",
64 "lc", "rc",
65 "lb", "cb", "rb" };
66 static textmode[JUSTMODES] = { TOPLEFT, TOPCENT, TOPRIGHT,
67 CENTLEFT, CENTCENT, CENTRIGHT,
68 BOTLEFT, BOTCENT, BOTRIGHT,
69 TOPLEFT, TOPCENT, TOPRIGHT,
70 CENTLEFT, CENTRIGHT,
71 BOTLEFT, BOTCENT, BOTRIGHT };
72
73 static char *fonts[] = { "bold", "italics", "roman", "special", NULL };
74 static fnum[] = { 3, 2, 1, 4 };
75
76 /* The following are defined to allow creation of the command lookup table. */
77
78 extern ST1(), ST2(), ST3(), ST4(), STB(), STI(), STR(), STS(),
79 STalign(), STbrush(), STflashoff(), STflashon(), STfont(), STfontdir(),
80 STgravity(), STgrid(), SThadjust(), STjustify(), STlittlepoint(),
81 STmadjust(), STpath(), STsize(), STstipple(),
82 STstipple1(), STstipple2(), STstipple3(), STstipple4(),
83 STstipple5(), STstipple6(), STstipple7(), STstipple8(),
84 STstippledir(), STstippletype(), STsymboliclines(), STvadjust();
85
86 /* The following two arrays define the startup commands and the routines
87 that process them. */
88
89 static char *startupcmds[] = {
90 "1",
91 "2",
92 "3",
93 "4",
94 "B",
95 "I",
96 "R",
97 "S",
98 "align",
99 "brush",
100 "flashoff",
101 "flashon",
102 "font",
103 "fontdir",
104 "gravity",
105 "grid",
106 "hadjust",
107 "justify",
108 "l1",
109 "l2",
110 "l3",
111 "l4",
112 "l5",
113 "l6",
114 "l7",
115 "l8",
116 "littlepoint",
117 "madjust",
118 "path",
119 "size",
120 "stipple",
121 "stipple1",
122 "stipple2",
123 "stipple3",
124 "stipple4",
125 "stipple5",
126 "stipple6",
127 "stipple7",
128 "stipple8",
129 "stippledir",
130 "stippletype",
131 "symboliclines",
132 "vadjust",
133 NULL
134 };
135
136 static (*(strtns[]))() = {
137 ST1, /* set size 1 point size */
138 ST2, /* set size 2 point size */
139 ST3, /* set size 3 point size */
140 ST4, /* set size 4 point size */
141 STB, /* set B font type */
142 STI, /* set I font type */
143 STR, /* set R font type */
144 STS, /* set S font type */
145 STalign, /* set point alignment */
146 STbrush, /* set brush */
147 STflashoff, /* set current set flash off time */
148 STflashon, /* set current set flash on time */
149 STfont, /* set font */
150 STfontdir, /* font directory */
151 STgravity, /* toggle gravity */
152 STgrid, /* toggle grid display */
153 SThadjust, /* horizontal adjust */
154 STjustify, /* text justification */
155 STstipple1, /* set stipple #1 index equivalent */
156 STstipple2, /* set stipple #2 index equivalent */
157 STstipple3, /* set stipple #3 index equivalent */
158 STstipple4, /* set stipple #4 index equivalent */
159 STstipple5, /* set stipple #5 index equivalent */
160 STstipple6, /* set stipple #6 index equivalent */
161 STstipple7, /* set stipple #7 index equivalent */
162 STstipple8, /* set stipple #8 index equivalent */
163 STlittlepoint, /* point size */
164 STmadjust, /* manhattan adjust */
165 STpath, /* set path or toggle search mode */
166 STsize, /* character size */
167 STstipple, /* set stipple pattern */
168 STstipple1, /* set stipple #1 index */
169 STstipple2, /* set stipple #2 index */
170 STstipple3, /* set stipple #3 index */
171 STstipple4, /* set stipple #4 index */
172 STstipple5, /* set stipple #5 index */
173 STstipple6, /* set stipple #6 index */
174 STstipple7, /* set stipple #7 index */
175 STstipple8, /* set stipple #8 index */
176 STstippledir, /* stipple directory */
177 STstippletype, /* stipple font file name */
178 STsymboliclines, /* toggle symbolic lines */
179 STvadjust /* vertical adjust */
180 };
181
182
183 /*
184 * Check for .gremlinrc file(s) and process if found.
185 * The only globally accessible routine in this file.
186 */
STgremlinrc(altfile)187 STgremlinrc(altfile)
188 char *altfile; /* alternate startup file */
189 {
190 FILE *fp;
191 struct stat buf;
192 ino_t home_inode, cwd_inode;
193 char home[128];
194
195 /* look in home directory */
196 sprintf(home, "%s/.gremlinrc", getenv("HOME"));
197 fp = fopen(home, "r");
198 if (fp != NULL) {
199 fstat(fileno(fp), &buf);
200 home_inode = buf.st_ino;
201 STstartup(fp);
202 fclose(fp);
203 }
204 else
205 home_inode = 0;
206
207 /* look in current directory */
208 fp = fopen(".gremlinrc", "r");
209 if (fp != NULL) {
210 fstat(fileno(fp), &buf);
211 cwd_inode = buf.st_ino;
212 if (cwd_inode != home_inode) /* not in home directory */
213 STstartup(fp);
214 fclose(fp);
215 }
216
217 /* check for alternate startup file */
218 if (*altfile != '\0') {
219 fp = fopen(altfile, "r");
220 if (fp != NULL) {
221 fstat(fileno(fp), &buf);
222 if ((buf.st_ino != home_inode) && (buf.st_ino != cwd_inode))
223 STstartup(fp);
224 fclose(fp);
225 }
226 }
227 } /* end STgremlinrc */
228
229
230 static
STerror(s)231 STerror(s)
232 register char *s;
233 {
234 char msg[256];
235
236 STERROR = 1;
237 sprintf(msg, "startup: %s", s);
238 TxPutMsg(msg);
239 } /* end STerror */
240
241
242 /*
243 * Do startup processing on open file referenced by fp.
244 */
245 static
STstartup(fp)246 STstartup(fp)
247 register FILE *fp;
248 {
249 register char *s;
250 register i;
251 char buf[256];
252
253 s = fgets(buf, 256, fp);
254 while (s != NULL) {
255 for (i=0; (buf[i] != '\n'); ++i)
256 if (i > 255)
257 break;
258 buf[i] = '\0';
259 STcommand(buf);
260 s = fgets(buf, 400, fp);
261 }
262 } /* end STstartup */
263
264
265 /*
266 * Make a string lower case.
267 */
STtolower(s)268 STtolower(s)
269 register char *s;
270 {
271 register c;
272
273 while ((c = (int) *s) != 0) {
274 if (isupper(c))
275 *s = tolower(c);
276 s++;
277 }
278 }
279
280
281 /*
282 * STlookup searches a table of strings to find one that matches a
283 * given string.
284 *
285 * If str is an unambiguous abbreviation for one of the entries
286 * in table, then the index of the matching entry is returned.
287 * If str is an abbreviation for more than one entry in table,
288 * then -1 is returned. If str doesn't match any entry, then
289 * -2 is returned.
290 *
291 * The search is carried out by using two pointers, one which moves
292 * forward through table from its start, and one which moves backward
293 * through table from its end. The two pointers mark the range of
294 * strings that match the portion of str that we have scanned. When
295 * all of the characters of str have been scanned, then the two
296 * pointers better be identical.
297 */
298 static
STlookup(str,table,next)299 STlookup(str, table, next)
300 char str[]; /* Pointer to a string to be looked up */
301 char *(table[]); /* Pointer to an array of string pointers
302 which are the valid commands. The strings
303 must be ordered monotonically (i.e. all
304 strings whose first characters are identical
305 must be adjacent in the table). */
306 int *next; /* Index to delimiter after search */
307 {
308 char **bot, **top;
309 int match, index;
310
311 match = 0;
312 bot = table;
313 for (top = table; *top != NULL; top++)
314 ;
315 if (top == bot)
316 return(-2);
317 top--;
318
319 for (index=0; ; index++) {
320 *next = index;
321
322 /* Check for the end of string */
323 if (Delimiter(str[index]))
324 return(((bot == top) || Delimiter((*bot)[index])) ? match : -1);
325
326 /*
327 * Move bot up until the string it points to matches str
328 * in the index'th position.
329 * Make match refer to the index of bot in table.
330 */
331
332 while ((*bot)[index] != str[index]) {
333 if (bot == top)
334 return(-2);
335 bot++;
336 match++;
337 }
338
339 /* Move top down until it matches */
340
341 while ((*top)[index] != str[index]) {
342 if (bot == top)
343 return(-2);
344 top--;
345 }
346 }
347 } /* end STlookup */
348
349
350 /*
351 * This routine looks up and executes a startup command.
352 */
353 static
STcommand(line)354 STcommand(line)
355 register char *line;
356 {
357 register index;
358 register char *save;
359 char buf[256];
360 int next;
361
362 if ((*line == '\0') || (*line == '#'))
363 return;
364
365 index = STlookup(save = line, startupcmds, &next);
366
367 if (index >= 0) {
368 line = line + next;
369
370 /* skip to first non-blank */
371 while ((*line == '\t') || (*line == ' '))
372 line++;
373
374 (*(strtns[index]))(line);
375 }
376 else if (index == -1) {
377 sprintf(buf, "ambigous command: %s", save);
378 STerror(buf);
379 }
380 else if (index == -2) {
381 sprintf(buf, "unknown command: %s", save);
382 STerror(buf);
383 }
384 } /* end STcommand */
385
386
387 /*
388 * This routine interprets the string starting at line
389 * as a positive integral numeric parameter. The function
390 * returns the numeric equivalent or -1 it there is some
391 * error in interpreting the string.
392 * NOTE: expects line with at least one non-space character.
393 */
394 static
STgetnum(line)395 STgetnum(line)
396 register char *line;
397 {
398 register i;
399 char num[128];
400 int result;
401
402 for (i=0; !Delimiter(*line); ++i) {
403 num[i] = *line++;
404 if (!isdigit(num[i]))
405 return(-1);
406 }
407
408 num[i] = '\0';
409 (void) sscanf(num, "%d", &result);
410 return(result);
411 } /* end STgetnum */
412
413
414 static
ST1(line)415 ST1(line)
416 register char *line;
417 {
418 register size;
419
420 if (*line == '\0')
421 return;
422
423 size = STgetnum(line);
424 if (size != -1)
425 font_sizes[0] = size;
426 else
427 STerror("bad size 1");
428 }
429
430
431 static
ST2(line)432 ST2(line)
433 register char *line;
434 {
435 register size;
436
437 if (*line == '\0')
438 return;
439
440 size = STgetnum(line);
441 if (size != -1)
442 font_sizes[1] = size;
443 else
444 STerror("bad size 2");
445 }
446
447
448 static
ST3(line)449 ST3(line)
450 register char *line;
451 {
452 register size;
453
454 if (*line == '\0')
455 return;
456
457 size = STgetnum(line);
458 if (size != -1)
459 font_sizes[2] = size;
460 else
461 STerror("bad size 3");
462 }
463
464
465 static
ST4(line)466 ST4(line)
467 register char *line;
468 {
469 register size;
470
471 if (*line == '\0')
472 return;
473
474 size = STgetnum(line);
475 if (size != -1)
476 font_sizes[3] = size;
477 else
478 STerror("bad size 4");
479 }
480
481
482 static
STB(line)483 STB(line)
484 register char *line;
485 {
486 register char *f;
487 register i = 0;
488
489 if (*line == '\0')
490 return;
491
492 f = line;
493 while (!Delimiter(*f))
494 f++, i++;
495
496 f = malloc((unsigned) i+1);
497 strncpy(f, line, i+1);
498 font_types[BFONT] = f;
499 }
500
501
502 static
STI(line)503 STI(line)
504 register char *line;
505 {
506 register char *f;
507 register i = 0;
508
509 if (*line == '\0')
510 return;
511
512 f = line;
513 while (!Delimiter(*f))
514 f++, i++;
515
516 f = malloc((unsigned) i+1);
517 strncpy(f, line, i+1);
518 font_types[IFONT] = f;
519 }
520
521
522 static
STR(line)523 STR(line)
524 register char *line;
525 {
526 register char *f;
527 register i = 0;
528
529 if (*line == '\0')
530 return;
531
532 f = line;
533 while (!Delimiter(*f))
534 f++, i++;
535
536 f = malloc((unsigned) i+1);
537 strncpy(f, line, i+1);
538 font_types[RFONT] = f;
539 }
540
541
542 static
STS(line)543 STS(line)
544 register char *line;
545 {
546 register char *f;
547 register i = 0;
548
549 if (*line == '\0')
550 return;
551
552 f = line;
553 while (!Delimiter(*f))
554 f++, i++;
555
556 f = malloc((unsigned) i+1);
557 strncpy(f, line, i+1);
558 font_types[SFONT] = f;
559 }
560
561
562 static
STalign(line)563 STalign(line)
564 register char *line;
565 {
566 register a;
567 register align = 1;
568
569 if (*line == '\0')
570 return;
571
572 a = STgetnum(line);
573 if (a <= 0)
574 STerror("bad alignment");
575 else {
576 a >>= 1;
577 while (a != 0) {
578 align <<= 1;
579 a >>= 1;
580 }
581 Alignment = (align > 512) ? 512 : align;
582 }
583 }
584
585
586 static
STbrush(line)587 STbrush(line)
588 register char *line;
589 {
590 register newbrush;
591 int index = 0;
592
593 if (*line == '\0')
594 return;
595
596 STtolower(line); /* force argument to lower case */
597
598 if ((newbrush = STlookup(line, lines, &index)) >= 0)
599 CBRUSH = lnum[newbrush];
600 else
601 STerror("bad brush name");
602 }
603
604
605 static
STflashoff(line)606 STflashoff(line)
607 register char *line;
608 {
609 register flashoff;
610 int index = 0;
611
612 if (*line == '\0')
613 return;
614
615 flashoff = STgetnum(line);
616 if (flashoff == -1)
617 STerror("bad flash off time");
618 else {
619 timeoff_s = flashoff / 1000;
620 timeoff_ms = flashoff % 1000;
621 }
622 }
623
624
625 static
STflashon(line)626 STflashon(line)
627 register char *line;
628 {
629 register flashon;
630 int index = 0;
631
632 if (*line == '\0')
633 return;
634
635 flashon = STgetnum(line);
636 if (flashon == -1)
637 STerror("bad flash on time");
638 else {
639 timeon_s = flashon / 1000;
640 timeon_ms = flashon % 1000;
641 }
642 }
643
644
645 static
STfont(line)646 STfont(line)
647 register char *line;
648 {
649 int font;
650 int index = 0;
651
652 if (*line == '\0')
653 return;
654
655 STtolower(line); /* force argument to lower case */
656
657 if ((font = STlookup(line, fonts, &index)) >= 0)
658 CFONT = fnum[font];
659 else
660 STerror("bad font number");
661 }
662
663
664 static
STfontdir(line)665 STfontdir(line)
666 register char *line;
667 {
668 register i = 0;
669
670 if (*line == '\0')
671 return;
672
673 while (!Delimiter(*line))
674 fontdir[i++] = *line++;
675
676 if (fontdir[--i] != '/')
677 fontdir[++i] = '/';
678
679 fontdir[++i] = '\0';
680 }
681
682
683 static
STgravity(line)684 STgravity(line)
685 register char *line;
686 {
687 STtolower(line);
688 GravityOn = STon(line);
689 }
690
691
692 static
STgrid(line)693 STgrid(line)
694 register char *line;
695 {
696 STtolower(line);
697 Gridon = STon(line);
698 }
699
700
701 static
SThadjust(line)702 SThadjust(line)
703 register char *line;
704 {
705 STtolower(line);
706
707 if (STon(line))
708 Adjustment = HORZ;
709 else if (Adjustment == HORZ)
710 Adjustment = NOADJ;
711 /*
712 Adjustment = (Adjustment == HORZ) ? NOADJ : HORZ;
713 */
714 }
715
716
717 static
STjustify(line)718 STjustify(line)
719 register char *line;
720 {
721 int new;
722 int index = 0;
723
724 if (*line == '\0')
725 return;
726
727 STtolower(line); /* force argument to lower case */
728
729 for (new = 0; (strcmp(line, textpos[new]) != 0); ++new) {
730 if (new >= JUSTMODES) {
731 STerror("bad justification mode");
732 return;
733 }
734 }
735
736 CJUST = textmode[new];
737 }
738
739
740 static
STlittlepoint(line)741 STlittlepoint(line)
742 register char *line;
743 {
744 /*
745 Artmode = !Artmode;
746 */
747 STtolower(line);
748 Artmode = STon(line);
749 }
750
751
752 static
STmadjust(line)753 STmadjust(line)
754 register char *line;
755 {
756 STtolower(line); /* force argument to lower case */
757
758 if (STon(line))
759 Adjustment = MAN;
760 else if (Adjustment == MAN)
761 Adjustment = NOADJ;
762 /*
763 Adjustment = (Adjustment == MAN) ? NOADJ : MAN;
764 */
765 }
766
767
768 static
STpath(line)769 STpath(line)
770 register char *line;
771 {
772 if (*line == '\0')
773 return;
774
775 PSetPath(line);
776 }
777
778
779 static
STsize(line)780 STsize(line)
781 register char *line;
782 {
783 int new;
784
785 if (*line == '\0')
786 return;
787
788 new = STgetnum(line);
789
790 if ((new == -1) || (new > NSIZES))
791 STerror("bad font size");
792 else
793 CSIZE = new;
794 }
795
796
797 static
STstipple(line)798 STstipple(line)
799 register char *line;
800 {
801 int newstipple;
802
803 if (*line == '\0')
804 return;
805
806 newstipple = STgetnum(line);
807
808 if ((newstipple == -1) || (newstipple > NSTIPPLES))
809 STerror("bad stipple number");
810 else
811 CSTIPPLE = newstipple;
812 }
813
814
815 static
STstipplenum(line,num)816 STstipplenum(line, num)
817 register char *line;
818 register num;
819 {
820 register index;
821
822 if (*line == '\0')
823 return;
824
825 index = STgetnum(line);
826
827 if ((index == -1) || (index >= NUM_DISPATCH))
828 STerror("bad stipple font index");
829 else
830 stipple_index[num-1] = index;
831 }
832
833
834 static
STstipple1(line)835 STstipple1(line)
836 register char *line;
837 {
838 STstipplenum(line, 1);
839 }
840
841
842 static
STstipple2(line)843 STstipple2(line)
844 register char *line;
845 {
846 STstipplenum(line, 2);
847 }
848
849
850 static
STstipple3(line)851 STstipple3(line)
852 register char *line;
853 {
854 STstipplenum(line, 3);
855 }
856
857
858 static
STstipple4(line)859 STstipple4(line)
860 register char *line;
861 {
862 STstipplenum(line, 4);
863 }
864
865
866 static
STstipple5(line)867 STstipple5(line)
868 register char *line;
869 {
870 STstipplenum(line, 5);
871 }
872
873
874 static
STstipple6(line)875 STstipple6(line)
876 register char *line;
877 {
878 STstipplenum(line, 6);
879 }
880
881
882 static
STstipple7(line)883 STstipple7(line)
884 register char *line;
885 {
886 STstipplenum(line, 7);
887 }
888
889
890 static
STstipple8(line)891 STstipple8(line)
892 register char *line;
893 {
894 STstipplenum(line, 8);
895 }
896
897
898 static
STstippledir(line)899 STstippledir(line)
900 register char *line;
901 {
902 register i = 0;
903
904 if (*line == '\0')
905 return;
906
907 while (!Delimiter(*line))
908 stippledir[i++] = *line++;
909
910 if (stippledir[--i] != '/')
911 stippledir[++i] = '/';
912
913 stippledir[++i] = '\0';
914 }
915
916
917 static
STstippletype(line)918 STstippletype(line)
919 register char *line;
920 {
921 register i = 0;
922
923 if (*line == '\0')
924 return;
925
926 while (!Delimiter(*line))
927 stippletype[i++] = *line++;
928
929 stippletype[i] = '\0';
930 }
931
932
933 static
STsymboliclines(line)934 STsymboliclines(line)
935 register char *line;
936 {
937 /*
938 SymbolicLines = !SymbolicLines;
939 */
940 STtolower(line);
941 SymbolicLines = STon(line);
942 }
943
944
945 static
STvadjust(line)946 STvadjust(line)
947 register char *line;
948 {
949 STtolower(line);
950
951 if (STon(line))
952 Adjustment = VERT;
953 else if (Adjustment == VERT)
954 Adjustment = NOADJ;
955 /*
956 Adjustment = (Adjustment == VERT) ? NOADJ : VERT;
957 */
958 }
959