1 /* $NetBSD: main.cpp,v 1.2 2018/05/16 13:53:28 joerg Exp $ */ 2 3 /* Last non-groff version: main.c 1.23 (Berkeley) 85/08/05 4 * 5 * Adapted to GNU troff by Daniel Senderowicz 99/12/29. 6 * 7 * Further refinements by Werner Lemberg 00/02/20. 8 * 9 * 10 * This file contains the main and file system dependent routines for 11 * processing gremlin files into troff input. The program watches input go 12 * by to standard output, only interpreting things between .GS and .GE 13 * lines. Default values (font, size, scale, thickness) may be overridden 14 * with a `default' command and are further overridden by commands in the 15 * input. 16 * 17 * Inside the GS and GE, commands are accepted to reconfigure the picture. 18 * At most one command may reside on each line, and each command is followed 19 * by a parameter separated by white space. The commands are as follows, 20 * and may be abbreviated down to one character (with exception of `scale' 21 * and `stipple' down to "sc" and "st") and may be upper or lower case. 22 * 23 * default - Make all settings in the current 24 * .GS/.GE the global defaults. Height, 25 * width and file are NOT saved. 26 * 1, 2, 3, 4 - Set size 1, 2, 3, or 4 (followed by an 27 * integer point size). 28 * roman, italics, bold, special - Set gremlin's fonts to any other troff 29 * font (one or two characters). 30 * stipple, l - Use a stipple font for polygons. Arg 31 * is troff font name. No Default. Can 32 * use only one stipple font per picture. 33 * (See below for stipple font index.) 34 * scale, x - Scale is IN ADDITION to the global 35 * scale factor from the default. 36 * pointscale - Turn on scaling point sizes to match 37 * `scale' commands. (Optional operand 38 * `off' to turn it off.) 39 * narrow, medium, thick - Set widths of lines. 40 * file - Set the file name to read the gremlin 41 * picture from. If the file isn't in 42 * the current directory, the gremlin 43 * library is tried. 44 * width, height - These two commands override any 45 * scaling factor that is in effect, and 46 * forces the picture to fit into either 47 * the height or width specified, 48 * whichever makes the picture smaller. 49 * The operand for these two commands is 50 * a floating-point number in units of 51 * inches. 52 * l<nn> (integer <nn>) - Set association between stipple <nn> 53 * and a stipple `character'. <nn> must 54 * be in the range 0 to NSTIPPLES (16) 55 * inclusive. The integer operand is an 56 * index in the stipple font selected. 57 * Valid cf (cifplot) indices are 1-32 58 * (although 24 is not defined), valid ug 59 * (unigrafix) indices are 1-14, and 60 * valid gs (gray scale) indices are 61 * 0-16. Nonetheless, any number between 62 * 0 and 255 is accepted since new 63 * stipple fonts may be added. An 64 * integer operand is required. 65 * 66 * Troff number registers used: g1 through g9. g1 is the width of the 67 * picture, and g2 is the height. g3, and g4, save information, g8 and g9 68 * are used for text processing and g5-g7 are reserved. 69 */ 70 71 72 #include "lib.h" 73 74 #include <ctype.h> 75 #include <stdlib.h> 76 #include "gprint.h" 77 78 #include "device.h" 79 #include "font.h" 80 #include "searchpath.h" 81 #include "macropath.h" 82 83 #include "errarg.h" 84 #include "error.h" 85 #include "defs.h" 86 87 extern "C" const char *Version_string; 88 89 /* database imports */ 90 91 extern void HGPrintElt(ELT *element, int baseline); 92 extern ELT *DBInit(); 93 extern ELT *DBRead(FILE *file); 94 extern POINT *PTInit(); 95 extern POINT *PTMakePoint(double x, double y, POINT **pplist); 96 97 98 #define SUN_SCALEFACTOR 0.70 99 100 /* #define DEFSTIPPLE "gs" */ 101 #define DEFSTIPPLE "cf" 102 103 #define MAXINLINE 100 /* input line length */ 104 105 #define SCREENtoINCH 0.02 /* scaling factor, screen to inches */ 106 107 #define BIG 999999999999.0 /* unweildly large floating number */ 108 109 110 static char sccsid[] = "@(#) (Berkeley) 8/5/85, 12/28/99"; 111 112 int res; /* the printer's resolution goes here */ 113 114 int dotshifter; /* for the length of dotted curves */ 115 116 double linethickness; /* brush styles */ 117 int linmod; 118 int lastx; /* point registers for printing elements */ 119 int lasty; 120 int lastyline; /* A line's vertical position is NOT the */ 121 /* same after that line is over, so for a */ 122 /* line of drawing commands, vertical */ 123 /* spacing is kept in lastyline */ 124 125 /* These are the default fonts, sizes, line styles, */ 126 /* and thicknesses. They can be modified from a */ 127 /* `default' command and are reset each time the */ 128 /* start of a picture (.GS) is found. */ 129 130 const char *deffont[] = 131 {"R", "I", "B", "S"}; 132 int defsize[] = 133 {10, 16, 24, 36}; 134 /* #define BASE_THICKNESS 1.0 */ 135 #define BASE_THICKNESS 0.15 136 double defthick[STYLES] = 137 {1 * BASE_THICKNESS, 138 1 * BASE_THICKNESS, 139 5 * BASE_THICKNESS, 140 1 * BASE_THICKNESS, 141 1 * BASE_THICKNESS, 142 3 * BASE_THICKNESS}; 143 144 /* int cf_stipple_index[NSTIPPLES + 1] = */ 145 /* {0, 1, 3, 12, 14, 16, 19, 21, 23}; */ 146 /* a logarithmic scale looks better than a linear one for the gray shades */ 147 /* */ 148 /* int other_stipple_index[NSTIPPLES + 1] = */ 149 /* {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; */ 150 151 int cf_stipple_index[NSTIPPLES + 1] = 152 {0, 18, 32, 56, 100, 178, 316, 562, 1000}; /* only 1-8 used */ 153 int other_stipple_index[NSTIPPLES + 1] = 154 {0, 62, 125, 187, 250, 312, 375, 437, 500, 155 562, 625, 687, 750, 812, 875, 937, 1000}; 156 157 /* int *defstipple_index = other_stipple_index; */ 158 int *defstipple_index = cf_stipple_index; 159 160 int style[STYLES] = 161 {DOTTED, DOTDASHED, SOLID, DASHED, SOLID, SOLID}; 162 double scale = 1.0; /* no scaling, default */ 163 int defpoint = 0; /* flag for pointsize scaling */ 164 char *defstipple = (char *) 0; 165 enum E { 166 OUTLINE, FILL, BOTH 167 } polyfill; 168 169 /* flag to controll filling of polygons */ 170 171 double adj1 = 0.0; 172 double adj2 = 0.0; 173 double adj3 = 0.0; 174 double adj4 = 0.0; 175 176 double thick[STYLES]; /* thicknesses set by defaults, then by */ 177 /* commands */ 178 char *tfont[FONTS]; /* fonts originally set to deffont values, */ 179 /* then */ 180 int tsize[SIZES]; /* optionally changed by commands inside */ 181 /* grn */ 182 int stipple_index[NSTIPPLES + 1]; /* stipple font file indices */ 183 char *stipple; 184 185 double xscale; /* scaling factor from individual pictures */ 186 double troffscale; /* scaling factor at output time */ 187 188 double width; /* user-request maximum width for picture */ 189 /* (in inches) */ 190 double height; /* user-request height */ 191 int pointscale; /* flag for pointsize scaling */ 192 int setdefault; /* flag for a .GS/.GE to remember all */ 193 /* settings */ 194 int sflag; /* -s flag: sort order (do polyfill first) */ 195 196 double toppoint; /* remember the picture */ 197 double bottompoint; /* bounds in these variables */ 198 double leftpoint; 199 double rightpoint; 200 201 int ytop; /* these are integer versions of the above */ 202 int ybottom; /* so not to convert each time they're used */ 203 int xleft; 204 int xright; 205 206 int linenum = 0; /* line number of input file */ 207 char inputline[MAXINLINE]; /* spot to filter through the file */ 208 char *c1 = inputline; /* c1, c2, and c3 will be used to */ 209 char *c2 = inputline + 1; /* hunt for lines that begin with */ 210 char *c3 = inputline + 2; /* ".GS" by looking individually */ 211 char *c4 = inputline + 3; /* needed for compatibility mode */ 212 char GScommand[MAXINLINE]; /* put user's ".GS" command line here */ 213 char gremlinfile[MAXINLINE]; /* filename to use for a picture */ 214 int SUNFILE = FALSE; /* TRUE if SUN gremlin file */ 215 int compatibility_flag = FALSE; /* TRUE if in compatibility mode */ 216 217 218 void getres(); 219 int doinput(FILE *fp); 220 void conv(FILE *fp, int baseline); 221 void savestate(); 222 int has_polygon(ELT *elist); 223 void interpret(char *line); 224 225 226 void 227 usage(FILE *stream) 228 { 229 fprintf(stream, 230 "usage: %s [ -vCs ] [ -M dir ] [ -F dir ] [ -T dev ] [ file ]\n", 231 program_name); 232 } 233 234 235 /*----------------------------------------------------------------------------* 236 | Routine: main (argument_count, argument_pointer) 237 | 238 | Results: Parses the command line, accumulating input file names, then 239 | reads the inputs, passing it directly to output until a `.GS' 240 | line is read. Main then passes control to `conv' to do the 241 | gremlin file conversions. 242 *----------------------------------------------------------------------------*/ 243 244 int 245 main(int argc, 246 char **argv) 247 { 248 setlocale(LC_NUMERIC, "C"); 249 program_name = argv[0]; 250 FILE *fp; 251 int k; 252 char c; 253 int gfil = 0; 254 char *file[50]; 255 char *operand(int *argcp, char ***argvp); 256 257 while (--argc) { 258 if (**++argv != '-') 259 file[gfil++] = *argv; 260 else 261 switch (c = (*argv)[1]) { 262 263 case 0: 264 file[gfil++] = NULL; 265 break; 266 267 case 'C': /* compatibility mode */ 268 compatibility_flag = TRUE; 269 break; 270 271 case 'F': /* font path to find DESC */ 272 font::command_line_font_dir(operand(&argc, &argv)); 273 break; 274 275 case 'T': /* final output typesetter name */ 276 device = operand(&argc, &argv); 277 break; 278 279 case 'M': /* set library directory */ 280 macro_path.command_line_dir(operand(&argc, &argv)); 281 break; 282 283 case 's': /* preserve order of elements */ 284 sflag = 1; 285 break; 286 287 case '-': 288 if (strcmp(*argv,"--version")==0) { 289 case 'v': 290 printf("GNU grn (groff) version %s\n", Version_string); 291 exit(0); 292 break; 293 } 294 if (strcmp(*argv,"--help")==0) { 295 case '?': 296 usage(stdout); 297 exit(0); 298 break; 299 } 300 // fallthrough 301 default: 302 error("unknown switch: %1", c); 303 usage(stderr); 304 exit(1); 305 } 306 } 307 308 getres(); /* set the resolution for an output device */ 309 310 if (gfil == 0) { /* no filename, use standard input */ 311 file[0] = NULL; 312 gfil++; 313 } 314 315 for (k = 0; k < gfil; k++) { 316 if (file[k] != NULL) { 317 if ((fp = fopen(file[k], "r")) == NULL) 318 fatal("can't open %1", file[k]); 319 } else 320 fp = stdin; 321 322 while (doinput(fp)) { 323 if (*c1 == '.' && *c2 == 'G' && *c3 == 'S') { 324 if (compatibility_flag || 325 *c4 == '\n' || *c4 == ' ' || *c4 == '\0') 326 conv(fp, linenum); 327 else 328 fputs(inputline, stdout); 329 } else 330 fputs(inputline, stdout); 331 } 332 } 333 334 return 0; 335 } 336 337 338 /*----------------------------------------------------------------------------* 339 | Routine: char * operand (& argc, & argv) 340 | 341 | Results: Returns address of the operand given with a command-line 342 | option. It uses either `-Xoperand' or `-X operand', whichever 343 | is present. The program is terminated if no option is 344 | present. 345 | 346 | Side Efct: argc and argv are updated as necessary. 347 *----------------------------------------------------------------------------*/ 348 349 char * 350 operand(int *argcp, 351 char ***argvp) 352 { 353 if ((**argvp)[2]) 354 return (**argvp + 2); /* operand immediately follows */ 355 if ((--*argcp) <= 0) { /* no operand */ 356 error("command-line option operand missing."); 357 exit(8); 358 } 359 return (*(++(*argvp))); /* operand is next word */ 360 } 361 362 363 /*----------------------------------------------------------------------------* 364 | Routine: getres () 365 | 366 | Results: Sets `res' to the resolution of the output device. 367 *----------------------------------------------------------------------------*/ 368 369 void 370 getres() 371 { 372 int linepiece; 373 374 if (!font::load_desc()) 375 fatal("sorry, I can't continue"); 376 377 res = font::res; 378 379 /* Correct the brush thicknesses based on res */ 380 /* if (res >= 256) { 381 defthick[0] = res >> 8; 382 defthick[1] = res >> 8; 383 defthick[2] = res >> 4; 384 defthick[3] = res >> 8; 385 defthick[4] = res >> 8; 386 defthick[5] = res >> 6; 387 } */ 388 389 linepiece = res >> 9; 390 for (dotshifter = 0; linepiece; dotshifter++) 391 linepiece = linepiece >> 1; 392 } 393 394 395 /*----------------------------------------------------------------------------* 396 | Routine: int doinput (file_pointer) 397 | 398 | Results: A line of input is read into `inputline'. 399 | 400 | Side Efct: "linenum" is incremented. 401 | 402 | Bugs: Lines longer than MAXINLINE are NOT checked, except for 403 | updating `linenum'. 404 *----------------------------------------------------------------------------*/ 405 406 int 407 doinput(FILE *fp) 408 { 409 if (fgets(inputline, MAXINLINE, fp) == NULL) 410 return 0; 411 if (strchr(inputline, '\n')) /* ++ only if it's a complete line */ 412 linenum++; 413 return 1; 414 } 415 416 417 /*----------------------------------------------------------------------------* 418 | Routine: initpic ( ) 419 | 420 | Results: Sets all parameters to the normal defaults, possibly 421 | overridden by a setdefault command. Initialize the picture 422 | variables, and output the startup commands to troff to begin 423 | the picture. 424 *----------------------------------------------------------------------------*/ 425 426 void 427 initpic() 428 { 429 int i; 430 431 for (i = 0; i < STYLES; i++) { /* line thickness defaults */ 432 thick[i] = defthick[i]; 433 } 434 for (i = 0; i < FONTS; i++) { /* font name defaults */ 435 tfont[i] = (char *)deffont[i]; 436 } 437 for (i = 0; i < SIZES; i++) { /* font size defaults */ 438 tsize[i] = defsize[i]; 439 } 440 for (i = 0; i <= NSTIPPLES; i++) { /* stipple font file default indices */ 441 stipple_index[i] = defstipple_index[i]; 442 } 443 stipple = defstipple; 444 445 gremlinfile[0] = 0; /* filename is `null' */ 446 setdefault = 0; /* this is not the default settings (yet) */ 447 448 toppoint = BIG; /* set the picture bounds out */ 449 bottompoint = -BIG; /* of range so they'll be set */ 450 leftpoint = BIG; /* by `savebounds' on input */ 451 rightpoint = -BIG; 452 453 pointscale = defpoint; /* flag for scaling point sizes default */ 454 xscale = scale; /* default scale of individual pictures */ 455 width = 0.0; /* size specifications input by user */ 456 height = 0.0; 457 458 linethickness = DEFTHICK; /* brush styles */ 459 linmod = DEFSTYLE; 460 } 461 462 463 /*----------------------------------------------------------------------------* 464 | Routine: conv (file_pointer, starting_line) 465 | 466 | Results: At this point, we just passed a `.GS' line in the input 467 | file. conv reads the input and calls `interpret' to process 468 | commands, gathering up information until a `.GE' line is 469 | found. It then calls `HGPrint' to do the translation of the 470 | gremlin file to troff commands. 471 *----------------------------------------------------------------------------*/ 472 473 void 474 conv(FILE *fp, 475 int baseline) 476 { 477 FILE *gfp = NULL; /* input file pointer */ 478 int done = 0; /* flag to remember if finished */ 479 ELT *e; /* current element pointer */ 480 ELT *PICTURE; /* whole picture data base pointer */ 481 double temp; /* temporary calculating area */ 482 /* POINT ptr; */ /* coordinates of a point to pass to `mov' */ 483 /* routine */ 484 int flyback; /* flag `want to end up at the top of the */ 485 /* picture?' */ 486 int compat; /* test character after .GE or .GF */ 487 488 489 initpic(); /* set defaults, ranges, etc. */ 490 strcpy(GScommand, inputline); /* save `.GS' line for later */ 491 492 do { 493 done = !doinput(fp); /* test for EOF */ 494 flyback = (*c3 == 'F'); /* and .GE or .GF */ 495 compat = (compatibility_flag || 496 *c4 == '\n' || *c4 == ' ' || *c4 == '\0'); 497 done |= (*c1 == '.' && *c2 == 'G' && (*c3 == 'E' || flyback) && 498 compat); 499 500 if (done) { 501 if (setdefault) 502 savestate(); 503 504 if (!gremlinfile[0]) { 505 if (!setdefault) 506 error("at line %1: no picture filename.\n", baseline); 507 return; 508 } 509 char *path; 510 gfp = macro_path.open_file(gremlinfile, &path); 511 if (!gfp) 512 return; 513 PICTURE = DBRead(gfp); /* read picture file */ 514 fclose(gfp); 515 a_delete path; 516 if (DBNullelt(PICTURE)) 517 return; /* If a request is made to make the */ 518 /* picture fit into a specific area, */ 519 /* set the scale to do that. */ 520 521 if (stipple == (char *) NULL) /* if user forgot stipple */ 522 if (has_polygon(PICTURE)) /* and picture has a polygon */ 523 stipple = (char *)DEFSTIPPLE; /* then set the default */ 524 525 if ((temp = bottompoint - toppoint) < 0.1) 526 temp = 0.1; 527 temp = (height != 0.0) ? height / (temp * SCREENtoINCH) : BIG; 528 if ((troffscale = rightpoint - leftpoint) < 0.1) 529 troffscale = 0.1; 530 troffscale = (width != 0.0) ? 531 width / (troffscale * SCREENtoINCH) : BIG; 532 if (temp == BIG && troffscale == BIG) 533 troffscale = xscale; 534 else { 535 if (temp < troffscale) 536 troffscale = temp; 537 } /* here, troffscale is the */ 538 /* picture's scaling factor */ 539 if (pointscale) { 540 int i; /* do pointscaling here, when */ 541 /* scale is known, before output */ 542 for (i = 0; i < SIZES; i++) 543 tsize[i] = (int) (troffscale * (double) tsize[i] + 0.5); 544 } 545 546 /* change to device units */ 547 troffscale *= SCREENtoINCH * res; /* from screen units */ 548 549 ytop = (int) (toppoint * troffscale); /* calculate integer */ 550 ybottom = (int) (bottompoint * troffscale); /* versions of the */ 551 xleft = (int) (leftpoint * troffscale); /* picture limits */ 552 xright = (int) (rightpoint * troffscale); 553 554 /* save stuff in number registers, */ 555 /* g1 = picture width and */ 556 /* g2 = picture height, */ 557 /* set vertical spacing, no fill, */ 558 /* and break (to make sure picture */ 559 /* starts on left), and put out the */ 560 /* user's `.GS' line. */ 561 printf(".br\n" 562 ".nr g1 %du\n" 563 ".nr g2 %du\n" 564 "%s" 565 ".nr g3 \\n(.f\n" 566 ".nr g4 \\n(.s\n" 567 "\\0\n" 568 ".sp -1\n", 569 xright - xleft, ybottom - ytop, GScommand); 570 571 if (stipple) /* stipple requested for this picture */ 572 printf(".st %s\n", stipple); 573 lastx = xleft; /* note where we are (upper left */ 574 lastyline = lasty = ytop; /* corner of the picture) */ 575 576 /* Just dump everything in the order it appears. 577 * 578 * If -s command-line option, traverse picture twice: First time, 579 * print only the interiors of filled polygons (as borderless 580 * polygons). Second time, print the outline as series of line 581 * segments. This way, postprocessors that overwrite rather than 582 * merge picture elements (such as Postscript) can still have text and 583 * graphics on a shaded background. 584 */ 585 /* if (sflag) */ 586 if (!sflag) { /* changing the default for filled polygons */ 587 e = PICTURE; 588 polyfill = FILL; 589 while (!DBNullelt(e)) { 590 printf(".mk\n"); 591 if (e->type == POLYGON) 592 HGPrintElt(e, baseline); 593 printf(".rt\n"); 594 lastx = xleft; 595 lastyline = lasty = ytop; 596 e = DBNextElt(e); 597 } 598 } 599 e = PICTURE; 600 601 /* polyfill = !sflag ? BOTH : OUTLINE; */ 602 polyfill = sflag ? BOTH : OUTLINE; /* changing the default */ 603 while (!DBNullelt(e)) { 604 printf(".mk\n"); 605 HGPrintElt(e, baseline); 606 printf(".rt\n"); 607 lastx = xleft; 608 lastyline = lasty = ytop; 609 e = DBNextElt(e); 610 } 611 612 /* decide where to end picture */ 613 614 /* I changed everything here. I always use the combination .mk and */ 615 /* .rt so once finished I just space down the heigth of the picture */ 616 /* that is \n(g2u */ 617 if (flyback) { /* end picture at upper left */ 618 /* ptr.x = leftpoint; 619 ptr.y = toppoint; */ 620 } else { /* end picture at lower left */ 621 /* ptr.x = leftpoint; 622 ptr.y = bottompoint; */ 623 printf(".sp \\n(g2u\n"); 624 } 625 626 /* tmove(&ptr); */ /* restore default line parameters */ 627 628 /* restore everything to the way it was before the .GS, then put */ 629 /* out the `.GE' line from user */ 630 631 /* printf("\\D't %du'\\D's %du'\n", DEFTHICK, DEFSTYLE); */ 632 /* groff doesn't understand the \Ds command */ 633 634 printf("\\D't %du'\n", DEFTHICK); 635 if (flyback) /* make sure we end up at top of */ 636 printf(".sp -1\n"); /* picture if `flying back' */ 637 if (stipple) /* restore stipple to previous */ 638 printf(".st\n"); 639 printf(".br\n" 640 ".ft \\n(g3\n" 641 ".ps \\n(g4\n" 642 "%s", inputline); 643 } else 644 interpret(inputline); /* take commands from the input file */ 645 } while (!done); 646 } 647 648 649 /*----------------------------------------------------------------------------* 650 | Routine: savestate ( ) 651 | 652 | Results: all the current scaling / font size / font name / thickness 653 | / pointscale settings are saved to be the defaults. Scaled 654 | point sizes are NOT saved. The scaling is done each time a 655 | new picture is started. 656 | 657 | Side Efct: scale, and def* are modified. 658 *----------------------------------------------------------------------------*/ 659 660 void 661 savestate() 662 { 663 int i; 664 665 for (i = 0; i < STYLES; i++) /* line thickness defaults */ 666 defthick[i] = thick[i]; 667 for (i = 0; i < FONTS; i++) /* font name defaults */ 668 deffont[i] = tfont[i]; 669 for (i = 0; i < SIZES; i++) /* font size defaults */ 670 defsize[i] = tsize[i]; 671 for (i = 0; i <= NSTIPPLES; i++) /* stipple font file default indices */ 672 defstipple_index[i] = stipple_index[i]; 673 674 defstipple = stipple; /* if stipple has been set, it's remembered */ 675 scale *= xscale; /* default scale of individual pictures */ 676 defpoint = pointscale; /* flag for scaling pointsizes from x factors */ 677 } 678 679 680 /*----------------------------------------------------------------------------* 681 | Routine: savebounds (x_coordinate, y_coordinate) 682 | 683 | Results: Keeps track of the maximum and minimum extent of a picture 684 | in the global variables: left-, right-, top- and 685 | bottompoint. `savebounds' assumes that the points have been 686 | oriented to the correct direction. No scaling has taken 687 | place, though. 688 *----------------------------------------------------------------------------*/ 689 690 void 691 savebounds(double x, 692 double y) 693 { 694 if (x < leftpoint) 695 leftpoint = x; 696 if (x > rightpoint) 697 rightpoint = x; 698 if (y < toppoint) 699 toppoint = y; 700 if (y > bottompoint) 701 bottompoint = y; 702 } 703 704 705 /*----------------------------------------------------------------------------* 706 | Routine: interpret (character_string) 707 | 708 | Results: Commands are taken from the input string and performed. 709 | Commands are separated by the endofline, and are of the 710 | format: 711 | string1 string2 712 | 713 | where string1 is the command and string2 is the argument. 714 | 715 | Side Efct: Font and size strings, plus the gremlin file name and the 716 | width and height variables are set by this routine. 717 *----------------------------------------------------------------------------*/ 718 719 void 720 interpret(char *line) 721 { 722 char str1[MAXINLINE]; 723 char str2[MAXINLINE]; 724 char *chr; 725 int i; 726 double par; 727 728 str2[0] = '\0'; 729 sscanf(line, "%80s%80s", &str1[0], &str2[0]); 730 for (chr = &str1[0]; *chr; chr++) /* convert command to */ 731 if (isupper(*chr)) 732 *chr = tolower(*chr); /* lower case */ 733 734 switch (str1[0]) { 735 736 case '1': 737 case '2': /* font sizes */ 738 case '3': 739 case '4': 740 i = atoi(str2); 741 if (i > 0 && i < 1000) 742 tsize[str1[0] - '1'] = i; 743 else 744 error("bad font size value at line %1", linenum); 745 break; 746 747 case 'r': /* roman */ 748 if (str2[0] < '0') 749 goto nofont; 750 tfont[0] = (char *) malloc(strlen(str2) + 1); 751 strcpy(tfont[0], str2); 752 break; 753 754 case 'i': /* italics */ 755 if (str2[0] < '0') 756 goto nofont; 757 tfont[1] = (char *) malloc(strlen(str2) + 1); 758 strcpy(tfont[1], str2); 759 break; 760 761 case 'b': /* bold */ 762 if (str2[0] < '0') 763 goto nofont; 764 tfont[2] = (char *) malloc(strlen(str2) + 1); 765 strcpy(tfont[2], str2); 766 break; 767 768 case 's': /* special */ 769 if (str1[1] == 'c') 770 goto scalecommand; /* or scale */ 771 772 if (str2[0] < '0') { 773 nofont: 774 error("no fontname specified in line %1", linenum); 775 break; 776 } 777 if (str1[1] == 't') 778 goto stipplecommand; /* or stipple */ 779 780 tfont[3] = (char *) malloc(strlen(str2) + 1); 781 strcpy(tfont[3], str2); 782 break; 783 784 case 'l': /* l */ 785 if (isdigit(str1[1])) { /* set stipple index */ 786 int idx = atoi(str1 + 1), val; 787 788 if (idx < 0 || idx > NSTIPPLES) { 789 error("bad stipple number %1 at line %2", idx, linenum); 790 break; 791 } 792 if (!defstipple_index) 793 defstipple_index = other_stipple_index; 794 val = atoi(str2); 795 if (val >= 0 && val < 256) 796 stipple_index[idx] = val; 797 else 798 error("bad stipple index value at line %1", linenum); 799 break; 800 } 801 802 stipplecommand: /* set stipple name */ 803 stipple = (char *) malloc(strlen(str2) + 1); 804 strcpy(stipple, str2); 805 /* if its a `known' font (currently only `cf'), set indicies */ 806 if (strcmp(stipple, "cf") == 0) 807 defstipple_index = cf_stipple_index; 808 else 809 defstipple_index = other_stipple_index; 810 for (i = 0; i <= NSTIPPLES; i++) 811 stipple_index[i] = defstipple_index[i]; 812 break; 813 814 case 'a': /* text adjust */ 815 par = atof(str2); 816 switch (str1[1]) { 817 case '1': 818 adj1 = par; 819 break; 820 case '2': 821 adj2 = par; 822 break; 823 case '3': 824 adj3 = par; 825 break; 826 case '4': 827 adj4 = par; 828 break; 829 default: 830 error("bad adjust command at line %1", linenum); 831 break; 832 } 833 break; 834 835 case 't': /* thick */ 836 thick[2] = defthick[0] * atof(str2); 837 break; 838 839 case 'm': /* medium */ 840 thick[5] = defthick[0] * atof(str2); 841 break; 842 843 case 'n': /* narrow */ 844 thick[0] = thick[1] = thick[3] = thick[4] = 845 defthick[0] * atof(str2); 846 break; 847 848 case 'x': /* x */ 849 scalecommand: /* scale */ 850 par = atof(str2); 851 if (par > 0.0) 852 xscale *= par; 853 else 854 error("invalid scale value on line %1", linenum); 855 break; 856 857 case 'f': /* file */ 858 strcpy(gremlinfile, str2); 859 break; 860 861 case 'w': /* width */ 862 width = atof(str2); 863 if (width < 0.0) 864 width = -width; 865 break; 866 867 case 'h': /* height */ 868 height = atof(str2); 869 if (height < 0.0) 870 height = -height; 871 break; 872 873 case 'd': /* defaults */ 874 setdefault = 1; 875 break; 876 877 case 'p': /* pointscale */ 878 if (strcmp("off", str2)) 879 pointscale = 1; 880 else 881 pointscale = 0; 882 break; 883 884 default: 885 error("unknown command `%1' on line %2", str1, linenum); 886 exit(8); 887 break; 888 }; 889 } 890 891 892 /* 893 * return TRUE if picture contains a polygon 894 * otherwise FALSE 895 */ 896 897 int 898 has_polygon(ELT *elist) 899 { 900 while (!DBNullelt(elist)) { 901 if (elist->type == POLYGON) 902 return (1); 903 elist = DBNextElt(elist); 904 } 905 906 return (0); 907 } 908 909 /* EOF */ 910