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 */ 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 684 STgravity(line) 685 register char *line; 686 { 687 STtolower(line); 688 GravityOn = STon(line); 689 } 690 691 692 static 693 STgrid(line) 694 register char *line; 695 { 696 STtolower(line); 697 Gridon = STon(line); 698 } 699 700 701 static 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 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 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 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 769 STpath(line) 770 register char *line; 771 { 772 if (*line == '\0') 773 return; 774 775 PSetPath(line); 776 } 777 778 779 static 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 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 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 835 STstipple1(line) 836 register char *line; 837 { 838 STstipplenum(line, 1); 839 } 840 841 842 static 843 STstipple2(line) 844 register char *line; 845 { 846 STstipplenum(line, 2); 847 } 848 849 850 static 851 STstipple3(line) 852 register char *line; 853 { 854 STstipplenum(line, 3); 855 } 856 857 858 static 859 STstipple4(line) 860 register char *line; 861 { 862 STstipplenum(line, 4); 863 } 864 865 866 static 867 STstipple5(line) 868 register char *line; 869 { 870 STstipplenum(line, 5); 871 } 872 873 874 static 875 STstipple6(line) 876 register char *line; 877 { 878 STstipplenum(line, 6); 879 } 880 881 882 static 883 STstipple7(line) 884 register char *line; 885 { 886 STstipplenum(line, 7); 887 } 888 889 890 static 891 STstipple8(line) 892 register char *line; 893 { 894 STstipplenum(line, 8); 895 } 896 897 898 static 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 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 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 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