Sync usage with man page.
[netbsd-mini2440.git] / gnu / dist / groff / src / preproc / grn / main.cpp
blob01b85f619652546f1a3499f3db2eac2a6a67af5d
1 /* $NetBSD$ */
3 /* Last non-groff version: main.c 1.23 (Berkeley) 85/08/05
5 * Adapted to GNU troff by Daniel Senderowicz 99/12/29.
7 * Further refinements by Werner Lemberg 00/02/20.
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.
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.
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.
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.
72 #include "lib.h"
74 #include <ctype.h>
75 #include <stdlib.h>
76 #include "gprint.h"
78 #include "device.h"
79 #include "font.h"
80 #include "searchpath.h"
81 #include "macropath.h"
83 #include "errarg.h"
84 #include "error.h"
85 #include "defs.h"
87 extern "C" const char *Version_string;
89 /* database imports */
91 extern void HGPrintElt(ELT *element, int baseline);
92 extern ELT *DBInit();
93 extern ELT *DBRead(register FILE *file);
94 extern POINT *PTInit();
95 extern POINT *PTMakePoint(double x, double y, POINT **pplist);
98 #define SUN_SCALEFACTOR 0.70
100 /* #define DEFSTIPPLE "gs" */
101 #define DEFSTIPPLE "cf"
103 #define MAXINLINE 100 /* input line length */
105 #define SCREENtoINCH 0.02 /* scaling factor, screen to inches */
107 #define BIG 999999999999.0 /* unweildly large floating number */
110 static char sccsid[] = "@(#) (Berkeley) 8/5/85, 12/28/99";
112 int res; /* the printer's resolution goes here */
114 int dotshifter; /* for the length of dotted curves */
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 */
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. */
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};
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}; */
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};
157 /* int *defstipple_index = other_stipple_index; */
158 int *defstipple_index = cf_stipple_index;
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;
169 /* flag to controll filling of polygons */
171 double adj1 = 0.0;
172 double adj2 = 0.0;
173 double adj3 = 0.0;
174 double adj4 = 0.0;
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;
185 double xscale; /* scaling factor from individual pictures */
186 double troffscale; /* scaling factor at output time */
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) */
196 double toppoint; /* remember the picture */
197 double bottompoint; /* bounds in these variables */
198 double leftpoint;
199 double rightpoint;
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;
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 */
218 void getres();
219 int doinput(FILE *fp);
220 void conv(register FILE *fp, int baseline);
221 void savestate();
222 int has_polygon(register ELT *elist);
223 void interpret(char *line);
226 void
227 usage(FILE *stream)
229 fprintf(stream,
230 "usage: %s [ -vCs ] [ -M dir ] [ -F dir ] [ -T dev ] [ file ]\n",
231 program_name);
235 /*----------------------------------------------------------------------------*
236 | Routine: main (argument_count, argument_pointer)
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 *----------------------------------------------------------------------------*/
245 main(int argc,
246 char **argv)
248 setlocale(LC_NUMERIC, "C");
249 program_name = argv[0];
250 register FILE *fp;
251 register int k;
252 register char c;
253 register int gfil = 0;
254 char *file[50];
255 char *operand(int *argcp, char ***argvp);
257 while (--argc) {
258 if (**++argv != '-')
259 file[gfil++] = *argv;
260 else
261 switch (c = (*argv)[1]) {
263 case 0:
264 file[gfil++] = NULL;
265 break;
267 case 'C': /* compatibility mode */
268 compatibility_flag = TRUE;
269 break;
271 case 'F': /* font path to find DESC */
272 font::command_line_font_dir(operand(&argc, &argv));
273 break;
275 case 'T': /* final output typesetter name */
276 device = operand(&argc, &argv);
277 break;
279 case 'M': /* set library directory */
280 macro_path.command_line_dir(operand(&argc, &argv));
281 break;
283 case 's': /* preserve order of elements */
284 sflag = 1;
285 break;
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;
294 if (strcmp(*argv,"--help")==0) {
295 case '?':
296 usage(stdout);
297 exit(0);
298 break;
300 // fallthrough
301 default:
302 error("unknown switch: %1", c);
303 usage(stderr);
304 exit(1);
308 getres(); /* set the resolution for an output device */
310 if (gfil == 0) { /* no filename, use standard input */
311 file[0] = NULL;
312 gfil++;
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;
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);
334 return 0;
338 /*----------------------------------------------------------------------------*
339 | Routine: char * operand (& argc, & argv)
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.
346 | Side Efct: argc and argv are updated as necessary.
347 *----------------------------------------------------------------------------*/
349 char *
350 operand(int *argcp,
351 char ***argvp)
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);
359 return (*(++(*argvp))); /* operand is next word */
363 /*----------------------------------------------------------------------------*
364 | Routine: getres ()
366 | Results: Sets `res' to the resolution of the output device.
367 *----------------------------------------------------------------------------*/
369 void
370 getres()
372 int linepiece;
374 if (!font::load_desc())
375 fatal("sorry, I can't continue");
377 res = font::res;
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 } */
389 linepiece = res >> 9;
390 for (dotshifter = 0; linepiece; dotshifter++)
391 linepiece = linepiece >> 1;
395 /*----------------------------------------------------------------------------*
396 | Routine: int doinput (file_pointer)
398 | Results: A line of input is read into `inputline'.
400 | Side Efct: "linenum" is incremented.
402 | Bugs: Lines longer than MAXINLINE are NOT checked, except for
403 | updating `linenum'.
404 *----------------------------------------------------------------------------*/
407 doinput(FILE *fp)
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;
417 /*----------------------------------------------------------------------------*
418 | Routine: initpic ( )
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 *----------------------------------------------------------------------------*/
426 void
427 initpic()
429 register int i;
431 for (i = 0; i < STYLES; i++) { /* line thickness defaults */
432 thick[i] = defthick[i];
434 for (i = 0; i < FONTS; i++) { /* font name defaults */
435 tfont[i] = (char *)deffont[i];
437 for (i = 0; i < SIZES; i++) { /* font size defaults */
438 tsize[i] = defsize[i];
440 for (i = 0; i <= NSTIPPLES; i++) { /* stipple font file default indices */
441 stipple_index[i] = defstipple_index[i];
443 stipple = defstipple;
445 gremlinfile[0] = 0; /* filename is `null' */
446 setdefault = 0; /* this is not the default settings (yet) */
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;
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;
458 linethickness = DEFTHICK; /* brush styles */
459 linmod = DEFSTYLE;
463 /*----------------------------------------------------------------------------*
464 | Routine: conv (file_pointer, starting_line)
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 *----------------------------------------------------------------------------*/
473 void
474 conv(register FILE *fp,
475 int baseline)
477 register FILE *gfp = NULL; /* input file pointer */
478 register int done = 0; /* flag to remember if finished */
479 register 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 */
489 initpic(); /* set defaults, ranges, etc. */
490 strcpy(GScommand, inputline); /* save `.GS' line for later */
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);
500 if (done) {
501 if (setdefault)
502 savestate();
504 if (!gremlinfile[0]) {
505 if (!setdefault)
506 error("at line %1: no picture filename.\n", baseline);
507 return;
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. */
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 */
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 register 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);
546 /* change to device units */
547 troffscale *= SCREENtoINCH * res; /* from screen units */
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);
554 /* save stuff in number registers, */
555 /* register g1 = picture width and */
556 /* register 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);
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) */
576 /* Just dump everything in the order it appears.
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.
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);
599 e = PICTURE;
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);
612 /* decide where to end picture */
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");
626 /* tmove(&ptr); */ /* restore default line parameters */
628 /* restore everything to the way it was before the .GS, then put */
629 /* out the `.GE' line from user */
631 /* printf("\\D't %du'\\D's %du'\n", DEFTHICK, DEFSTYLE); */
632 /* groff doesn't understand the \Ds command */
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);
649 /*----------------------------------------------------------------------------*
650 | Routine: savestate ( )
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.
657 | Side Efct: scale, and def* are modified.
658 *----------------------------------------------------------------------------*/
660 void
661 savestate()
663 register int i;
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];
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 */
680 /*----------------------------------------------------------------------------*
681 | Routine: savebounds (x_coordinate, y_coordinate)
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 *----------------------------------------------------------------------------*/
690 void
691 savebounds(double x,
692 double y)
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;
705 /*----------------------------------------------------------------------------*
706 | Routine: interpret (character_string)
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
713 | where string1 is the command and string2 is the argument.
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 *----------------------------------------------------------------------------*/
719 void
720 interpret(char *line)
722 char str1[MAXINLINE];
723 char str2[MAXINLINE];
724 register char *chr;
725 register int i;
726 double par;
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 */
734 switch (str1[0]) {
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;
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;
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;
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;
768 case 's': /* special */
769 if (str1[1] == 'c')
770 goto scalecommand; /* or scale */
772 if (str2[0] < '0') {
773 nofont:
774 error("no fontname specified in line %1", linenum);
775 break;
777 if (str1[1] == 't')
778 goto stipplecommand; /* or stipple */
780 tfont[3] = (char *) malloc(strlen(str2) + 1);
781 strcpy(tfont[3], str2);
782 break;
784 case 'l': /* l */
785 if (isdigit(str1[1])) { /* set stipple index */
786 int idx = atoi(str1 + 1), val;
788 if (idx < 0 || idx > NSTIPPLES) {
789 error("bad stipple number %1 at line %2", idx, linenum);
790 break;
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;
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;
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;
833 break;
835 case 't': /* thick */
836 thick[2] = defthick[0] * atof(str2);
837 break;
839 case 'm': /* medium */
840 thick[5] = defthick[0] * atof(str2);
841 break;
843 case 'n': /* narrow */
844 thick[0] = thick[1] = thick[3] = thick[4] =
845 defthick[0] * atof(str2);
846 break;
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;
857 case 'f': /* file */
858 strcpy(gremlinfile, str2);
859 break;
861 case 'w': /* width */
862 width = atof(str2);
863 if (width < 0.0)
864 width = -width;
865 break;
867 case 'h': /* height */
868 height = atof(str2);
869 if (height < 0.0)
870 height = -height;
871 break;
873 case 'd': /* defaults */
874 setdefault = 1;
875 break;
877 case 'p': /* pointscale */
878 if (strcmp("off", str2))
879 pointscale = 1;
880 else
881 pointscale = 0;
882 break;
884 default:
885 error("unknown command `%1' on line %2", str1, linenum);
886 exit(8);
887 break;
893 * return TRUE if picture contains a polygon
894 * otherwise FALSE
898 has_polygon(register ELT *elist)
900 while (!DBNullelt(elist)) {
901 if (elist->type == POLYGON)
902 return (1);
903 elist = DBNextElt(elist);
906 return (0);
909 /* EOF */