1 /* main.c 1.24 (Berkeley) 86/04/14
2 *
3 * This file contains the main and file system dependent routines
4 * for processing gremlin files into troff input. The program watches
5 * input go by to standard output, only interpretting things between .GS
6 * and .GE lines. Default values (font, size, scale, thickness) may be
7 * overridden with a "default" command and are further overridden by
8 * commands in the input. A description of the command-line options are
9 * listed below. A space is NOT required for the operand of an option.
10 *
11 * command options are:
12 *
13 * -L dir set the library directory to dir. If a file is not found
14 * in the current directory, it is looked for in dir (default
15 * is /usr/lib/gremlib).
16 *
17 * -T dev Prepare output for "dev" printer. Default is for the varian
18 * -P dev and versatec printers. Devices acceptable are: ver, var, ip.
19 *
20 * Inside the GS and GE, commands are accepted to reconfigure
21 * the picture. At most one command may reside on each line, and
22 * each command is followed by a parameter separated by white space.
23 * The commands are as follows, and may be abbreviated down to one
24 * character (with exception of "scale" and "stipple" down to "sc"
25 * and "st") and may be upper or lower case.
26 *
27 * default - make all settings in the current
28 * .GS/.GE the global defaults.
29 * Height, width and file are NOT saved.
30 * 1, 2, 3, 4 - set size 1, 2, 3, or 4 (followed
31 * by an integer point size).
32 * roman, italics, bold, special - set gremlin's fonts to any other
33 * troff font (one or two characters)
34 * stipple, l - use a stipple font for polygons. Arg
35 * is troff font name. No Default. Can
36 * use only one stipple font per picture.
37 * (see below for stipple font index)
38 * scale, x - scale is IN ADDITION to the global
39 * scale factor from the default.
40 * pointscale - turn on scaling point sizes to
41 * match "scale" commands. (optional
42 * operand "off" to turn it off)
43 * narrow, medium, thick - set pixel widths of lines.
44 * file - set the file name to read the
45 * gremlin picture from. If the file
46 * isn't in the current directory, the
47 * gremlin library is tried.
48 * width, height - these two commands override any
49 * scaling factor that is in effect,
50 * and forces the picture to fit into
51 * either the height or width specified,
52 * whichever makes the picture smaller.
53 * The operand for these two commands is
54 * a floating-point number in units of
55 * inches
56 * oldstipplemap - use the old-style stipple mapping.
57 * THE FOLLOWING COMMANDS ARE IGNORED
58 * UNLESS OLDSTIPPLEMAP IS SPECIFIED.
59 * l1, l2, l3, l4, l5, l6, l7, l8 - set association between stipples
60 * (1 - 8) and the stipple font file
61 * index. Valid cifplot indices are
62 * 1 - 32 (although 24 is not defined)
63 * and valid unigrafix indices are
64 * 1 - 64. Nonetheless, any number
65 * between 0 and 255 is accepted since
66 * new stipple fonts may be added.
67 * An integer operand is required.
68 *
69 * Troff number registers used: g1 through g9. g1 is the width of the
70 * picture, and g2 is the height. g3, and g4, save information, g8
71 * and g9 are used for text processing and g5-g7 are reserved.
72 */
73
74
75 #include <ctype.h>
76 #include "gprint.h"
77 #include "dev.h"
78
79 extern char *malloc();
80 extern char *rindex();
81
82 /* database imports */
83
84 extern HGPrintElt();
85 extern ELT *DBInit(), *DBRead();
86 extern POINT *PTInit(), *PTMakePoint();
87
88
89 #ifndef GREMLIB
90 #define GREMLIB "/usr/local/gremlib/"
91 #endif
92
93 #define SUN_SCALEFACTOR 0.70
94
95 #ifndef DEVDIR
96 #define DEVDIR "/usr/lib/font"
97 #endif
98 #define DEFAULTDEV "va"
99 #define DEFSTIPPLE "cf"
100
101 #define MAXINLINE 100 /* input line length */
102 #define DEFTHICK 3 /* default thicknes */
103 #define DEFSTYLE SOLID /* default line style */
104
105 #ifdef oldversion
106 #define SCREENtoINCH 0.02 /* scaling factor, screen to inches */
107 #endif
108
109 double SCREENtoINCH; /* scaling factor, screen to inches */
110
111 #define BIG 999999999999.0 /* unweildly large floating number */
112
113
114 static char sccsid[] = "@(#) (Berkeley) 04/14/86";
115
116 char *printer = DEFAULTDEV; /* device to look up resolution of */
117 char *gremlib = GREMLIB; /* place to find files after current dir. */
118 double res; /* that printer's resolution goes here */
119
120 int linethickness; /* brush styles */
121 int linmod;
122 int lastx; /* point registers for printing elements */
123 int lasty;
124 int lastyline; /* a line's vertical position is NOT the same */
125 /* after that line is over, so for a line of */
126 /* drawing commands, vertical spacing is kept */
127 /* in lastyline */
128
129 /* these are the default fonts, sizes, line styles, */
130 /* and thicknesses. These can be modified from a */
131 /* "default" command and are reset each time the */
132 /* start of a picture (.GS) is found. */
133
134 char * deffont[] = { "R", "I", "B", "S" };
135 int defsize[] = { 10, 16, 24, 36 };
136 int defthick[STYLES] = { 1, 1, 5, 1, 1, 3 };
137 int defstipple_index[NSTIPPLES] = { 1, 3, 12, 14, 16, 19, 21, 23 };
138 int style[STYLES] = { DOTTED, DOTDASHED, SOLID, DASHED, SOLID, SOLID };
139 double scale = 1.0; /* no scaling, default */
140 int defpoint = 0; /* flag for pointsize scaling */
141 char * defstipple = (char *) 0;
142
143 int thick[STYLES]; /* thicknesses set by defaults, then by commands */
144 char *tfont[FONTS]; /* fonts originally set to deffont values, then */
145 int tsize[SIZES]; /* optionally changed by commands inside grn */
146 int stipple_index[NSTIPPLES]; /* stipple font file indices */
147 char * stipple;
148
149 double xscale; /* scaling factor from individual pictures */
150 double troffscale; /* scaling factor at output time */
151 double width; /* user-request maximum width for picture (in inches) */
152 double height; /* user-request height */
153 int pointscale; /* flag for pointsize scaling */
154 int setdefault; /* flag for a .GS/.GE to remember all settings */
155
156 double toppoint; /* remember the picture */
157 double bottompoint; /* bounds in these variables */
158 double leftpoint;
159 double rightpoint;
160
161 int ytop; /* these are integer versions of the above */
162 int ybottom; /* so not to convert each time they're used */
163 int xleft;
164 int xright;
165
166 int linenum = 0; /* line number of input file */
167 char inputline[MAXINLINE]; /* spot to filter through the file */
168 char *c1 = inputline; /* c1, c2, and c3 will be used to */
169 char *c2 = inputline + 1; /* hunt for lines that begin with */
170 char *c3 = inputline + 2; /* ".GS" by looking individually */
171 char GScommand[MAXINLINE]; /* put user's ".GS" command line here */
172 char gremlinfile[MAXINLINE]; /* filename to use for a picture */
173 int SUNFILE = FALSE; /* TRUE if SUN gremlin file */
174 int oldstipmap = FALSE; /* TRUE if old-style stipple mapping */
175
176 char *doinput();
177
178
179 /*----------------------------------------------------------------------------*
180 | Routine: main (argument_count, argument_pointer)
181 |
182 | Results: parses the command line, accumulating input file names, then
183 | reads the inputs, passing it directly to output until a ".GS"
184 | line is read. Main then passes control to "conv" to do the
185 | gremlin file conversions.
186 *----------------------------------------------------------------------------*/
187
main(argc,argv)188 main(argc, argv)
189 int argc;
190 char **argv;
191 {
192 register FILE *fp;
193 register int k;
194 register char c;
195 register gfil = 0;
196 char *file[50];
197
198 char *operand();
199 char *getenv();
200
201
202 if (fp = (FILE *) getenv("PRINTER")) printer = (char *) fp;
203 if (fp = (FILE *) getenv("TYPESETTER")) printer = (char *) fp;
204 while (--argc) {
205 if (**++argv != '-')
206 file[gfil++] = *argv;
207 else
208 switch (c = (*argv)[1]) {
209
210 case 0:
211 file[gfil++] = NULL;
212 break;
213
214 case 'P':
215 case 'T': /* final output typesetter name */
216 printer = operand(&argc, &argv);
217 break;
218
219 case 'L': /* set library directory */
220 gremlib = operand(&argc, &argv);
221 break;
222
223 default:
224 error("unknown switch: %c", c);
225 }
226 }
227 /* set the resolution for an output device */
228 getres(printer); /* named in "printer" */
229
230 if (gfil == 0) { /* no filename, use standard input */
231 file[0] = NULL;
232 gfil++;
233 }
234
235 for (k=0; k<gfil; k++) {
236 if (file[k] != NULL) {
237 if ((fp = fopen(file[k], "r")) == NULL) {
238 error("can't open %s", file[k]);
239 exit(1);
240 }
241 } else {
242 fp = stdin;
243 }
244
245 while (doinput(fp) != NULL) {
246 if (*c1 == '.' && *c2 == 'G' && *c3 == 'S') {
247 conv(fp, linenum);
248 } else {
249 fputs(inputline, stdout);
250 }
251 }
252 }
253 }
254
255
256 /*----------------------------------------------------------------------------*
257 | Routine: error (control_string, args, . . . )
258 |
259 | Results: prints ("grn: ", the control_string + args, "\n") to stderr
260 *----------------------------------------------------------------------------*/
261
262 /* VARARGS1 */
error(s,a1,a2,a3,a4)263 error(s, a1, a2, a3, a4)
264 char * s;
265 {
266 fprintf(stderr, "grn: ");
267 fprintf(stderr, s, a1, a2, a3, a4);
268 fprintf(stderr, "\n");
269 }
270
271
272 /*----------------------------------------------------------------------------*
273 | Routine: char * operand (& argc, & argv)
274 |
275 | Results: returns address of the operand given with a command-line
276 | option. It uses either "-Xoperand" or "-X operand", whichever
277 | is present. The program is terminated if no option is present.
278 |
279 | Side Efct: argc and argv are updated as necessary.
280 *----------------------------------------------------------------------------*/
281
operand(argcp,argvp)282 char *operand(argcp, argvp)
283 int * argcp;
284 char ***argvp;
285 {
286 if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
287 if ((--*argcp) <= 0) { /* no operand */
288 error("command-line option operand missing.");
289 exit(8);
290 }
291 return(*(++(*argvp))); /* operand is next word */
292 }
293
294
295 /*----------------------------------------------------------------------------*
296 | Routine: getres (device_name)
297 |
298 | Results: sets "res" to the resolution of the output device specified
299 | by the string dev.
300 *----------------------------------------------------------------------------*/
301
getres(name)302 getres(name)
303 char *name;
304 {
305 int fin;
306 struct dev device;
307 char temp[60];
308
309 sprintf(temp, "%s/dev%s/DESC.out", DEVDIR, name);
310 if ((fin = open(temp, 0)) < 0) {
311 error("can't open tables for %s", temp);
312 exit(1);
313 }
314 read(fin, &device, sizeof(struct dev));
315 res = (double) device.res;
316 close(fin);
317 }
318
319
320 /*----------------------------------------------------------------------------*
321 | Routine: char * doinput (file_pointer)
322 |
323 | Results: a line of input is read into "inputline".
324 |
325 | Side Efct: "linenum" is incremented.
326 |
327 | Bugs: lines longer than MAXINLINE are NOT checked, except for
328 | updating "linenum"
329 *----------------------------------------------------------------------------*/
330
doinput(fp)331 char *doinput(fp)
332 FILE *fp;
333 {
334 char *k;
335
336
337 if ((k = fgets(inputline, MAXINLINE, fp)) == NULL)
338 return k;
339 if (index (inputline, '\n')) /* ++ only if it's a complete line */
340 linenum++;
341 return (char*) !NULL;
342 }
343
344
345 /*----------------------------------------------------------------------------*
346 | Routine: initpic ( )
347 |
348 | Results: sets all parameters to the normal defaults, possibly overridden
349 | by a setdefault command. Initilaize the picture variables,
350 | and output the startup commands to troff to begin the picture.
351 *----------------------------------------------------------------------------*/
352
initpic()353 initpic()
354 {
355 register int i;
356
357 for (i = 0; i < STYLES; i++) { /* line thickness defaults */
358 thick[i] = defthick[i];
359 }
360 for (i = 0; i < FONTS; i++) { /* font name defaults */
361 tfont[i] = deffont[i];
362 }
363 for (i = 0; i < SIZES; i++) { /* font size defaults */
364 tsize[i] = defsize[i];
365 }
366 for (i = 0; i < NSTIPPLES; i++) { /* stipple font file default indices */
367 stipple_index[i] = defstipple_index[i];
368 }
369 stipple = defstipple;
370
371 gremlinfile[0] = 0; /* filename is "null" */
372 setdefault = 0; /* this is not the default settings (yet) */
373
374 toppoint = BIG; /* set the picture bounds out */
375 bottompoint = -BIG; /* of range so they'll be set */
376 leftpoint = BIG; /* by "savebounds" on input */
377 rightpoint = -BIG;
378
379 pointscale = defpoint; /* Flag for scaling point sizes default. */
380 xscale = scale; /* default scale of individual pictures */
381 width = 0.0; /* size specifications input by user */
382 height = 0.0;
383
384 linethickness = DEFTHICK; /* brush styles */
385 linmod = DEFSTYLE;
386 }
387
388
389 /*----------------------------------------------------------------------------*
390 | Routine: conv (file_pointer, starting_line)
391 |
392 | Results: at this point, we just passed a ".GS" line in the input file.
393 | conv reads the input and calls "interpret" to process commands,
394 | gathering up information until a ".GE" line is found. It then
395 | calls "HGPrint" to do the translation of the gremlin file to
396 | troff commands.
397 *----------------------------------------------------------------------------*/
398
conv(fp,baseline)399 conv(fp, baseline)
400 register FILE *fp;
401 int baseline;
402 {
403 register FILE *gfp = NULL; /* input file pointer */
404 register int done = 0; /* flag to remember if finished */
405 register ELT *e; /* current element pointer */
406 ELT *PICTURE; /* whole picture data base pointer */
407 double temp; /* temporary calculating area */
408 POINT ptr; /* coordinates of a point to pass to "mov" routine */
409 int flyback; /* flag "want to end up at the top of the picture?" */
410
411
412 initpic(); /* set defaults, ranges, etc. */
413 strcpy (GScommand, inputline); /* save ".GS" line for later */
414 do {
415 done = (doinput(fp) == NULL); /* test for EOF */
416 flyback = *c3 == 'F'; /* and .GE or .GF */
417 done |= (*c1 == '.' && *c2 == 'G' && (*c3 == 'E' || flyback));
418
419 if (done) {
420 if (setdefault) savestate();
421
422 if (!gremlinfile[0]) {
423 if(!setdefault)
424 error("at line %d: no picture filename.\n", baseline);
425 return;
426 }
427 if ((gfp = fopen(gremlinfile, "r")) == NULL) {
428 char name[MAXINLINE]; /* if the file isn't in the current */
429 /* directory, try the gremlin library */
430 sprintf(name, "%s%s", gremlib, gremlinfile);
431 if ((gfp = fopen(name, "r")) == NULL) {
432 error("can't open %s", gremlinfile);
433 return;
434 }
435 }
436 PICTURE = DBRead(gfp); /* read picture file */
437 fclose(gfp);
438 if (DBNullelt(PICTURE))
439 return; /* if a request is made to make the */
440 /* picture fit into a specific area, */
441 /* set the scale to do that. */
442
443 SCREENtoINCH = (SUNFILE) ? 0.014 : 0.02;
444
445 if (stipple == (char *) NULL) /* if user forgot stipple */
446 if (has_polygon(PICTURE)) /* and picture has a polygon */
447 stipple = DEFSTIPPLE; /* then set the default */
448
449 if ((temp = bottompoint - toppoint) < 0.1) temp = 0.1;
450 temp = (height != 0.0) ? height / (temp * SCREENtoINCH) : BIG;
451 if ((troffscale = rightpoint - leftpoint) < 0.1) troffscale=0.1;
452 troffscale = (width != 0.0) ?
453 width / (troffscale * SCREENtoINCH) : BIG;
454 if (temp == BIG && troffscale == BIG) {
455 troffscale = xscale;
456 } else {
457 if (temp < troffscale) troffscale = temp;
458 } /* here, troffscale is the */
459 /* picture's scaling factor */
460 if (pointscale) {
461 register int i; /* do pointscaling here, when */
462 /* scale is known, before output */
463
464 for (i = 0; i < SIZES; i++)
465 tsize[i] = (int) (troffscale * (double) tsize[i] + 0.5);
466
467 }
468 /* change to device units */
469 troffscale *= SCREENtoINCH * res; /* from screen units */
470
471 ytop = toppoint * troffscale; /* calculate integer */
472 ybottom = bottompoint * troffscale; /* versions of the */
473 xleft = leftpoint * troffscale; /* picture limits */
474 xright = rightpoint * troffscale;
475 /* save stuff in number registers, */
476 /* register g1 = picture width and */
477 /* register g2 = picture height, */
478 /* set vertical spacing, no fill, */
479 /* and break (to make sure picture */
480 /* starts on left), and put out the */
481 /* user's ".GS" line. */
482 printf(
483 ".br\n.nr g1 %du\n.nr g2 %du\n%s.nr g3 \\n(.f\n.nr g4 \\n(.s\n\\0\n.sp -1\n",
484 xright-xleft, ybottom-ytop, GScommand);
485
486 if (stipple) { /* stipple requested for this picture */
487 printf(".st %s\n", stipple);
488 }
489
490 lastx = xleft; /* note where we are, (upper left */
491 lastyline = lasty = ytop; /* corner of the picture) */
492
493 e = PICTURE;
494 while (!DBNullelt(e)) { /* traverse picture; print elements */
495 HGPrintElt(e, baseline);
496 e = DBNextElt(e);
497 }
498 /* decide where to end picture */
499 if (flyback) { /* end piture at upper left */
500 ptr.x = leftpoint;
501 ptr.y = toppoint;
502 } else { /* end picture at lower left */
503 ptr.x = leftpoint;
504 ptr.y = bottompoint;
505 }
506 tmove(&ptr); /* restore default line parameters, */
507 /* restore everything to the way */
508 /* it was before the .GS, then put */
509 /* out the ".GE" line from user */
510 printf("\\D't %du'\\D's %du'\n", DEFTHICK, DEFSTYLE);
511 if (flyback) { /* make sure we end up at top of */
512 printf(".sp -1\n"); /* picture if "flying back" */
513 }
514 if (stipple) { /* restore stipple to previous */
515 printf(".st\n");
516 }
517 printf(".br\n.ft \\n(g3\n.ps \\n(g4\n%s", inputline);
518 } else {
519 interpret(inputline); /* take commands from the input file */
520 }
521 } while (!done);
522 }
523
524
525 /*----------------------------------------------------------------------------*
526 | Routine: savestate ( )
527 |
528 | Results: all the current scaling / font size / font name / thickness /
529 | pointscale settings are saved to be the defaults. Scaled
530 | point sizes are NOT saved. The scaling is done each time a
531 | new picture is started.
532 |
533 | Side Efct: scale, and def* are modified.
534 *----------------------------------------------------------------------------*/
535
savestate()536 savestate()
537 {
538 register int i;
539
540 for (i = 0; i < STYLES; i++) { /* line thickness defaults */
541 defthick[i] = thick[i];
542 }
543 for (i = 0; i < FONTS; i++) { /* font name defaults */
544 deffont[i] = tfont[i];
545 }
546 for (i = 0; i < SIZES; i++) { /* font size defaults */
547 defsize[i] = tsize[i];
548 }
549 for (i = 0; i < NSTIPPLES; i++) { /* stipple font file default indices */
550 defstipple_index[i] = stipple_index[i];
551 }
552 defstipple = stipple; /* if stipple has been set, it's remembered */
553
554 scale *= xscale; /* default scale of individual pictures */
555 defpoint = pointscale; /* flag for scaling pointsizes from x factors */
556 }
557
558
559 /*----------------------------------------------------------------------------*
560 | Routine: savebounds (x_coordinate, y_coordinate)
561 |
562 | Results: keeps track of the maximum and minimum extent of a picture
563 | in the global variables: left-, right-, top- and bottompoint.
564 | "savebounds" assumes that the points have been oriented to
565 | the correct direction. No scaling has taken place, though.
566 *----------------------------------------------------------------------------*/
567
savebounds(x,y)568 savebounds(x, y)
569 float x;
570 float y;
571 {
572 if (x < leftpoint) leftpoint = x;
573 if (x > rightpoint) rightpoint = x;
574 if (y < toppoint) toppoint = y;
575 if (y > bottompoint) bottompoint = y;
576 }
577
578
579 /*----------------------------------------------------------------------------*
580 | Routine: interpret (character_string)
581 |
582 | Results: commands are taken from the input string and performed.
583 | Commands are separated by the endofline, and are of the
584 | format:
585 | string1 string2
586 |
587 | where string1 is the command and string2 is the argument.
588 |
589 | Side Efct: font and size strings, plus the gremlin file name and the
590 | width and height variables are set by this routine.
591 *----------------------------------------------------------------------------*/
592
interpret(line)593 interpret (line)
594 char *line;
595 {
596 char str1[MAXINLINE];
597 char str2[MAXINLINE];
598 register char *chr;
599 register int i;
600 double par;
601
602 str2[0] = '\0';
603 sscanf(line, "%80s%80s", &str1[0], &str2[0]);
604 for (chr = &str1[0]; *chr; chr++) /* convert command to */
605 if(isupper(*chr)) *chr = tolower(*chr); /* lower case */
606 switch (str1[0]) {
607
608 case '1':
609 case '2': /* font sizes */
610 case '3':
611 case '4':
612 i = atoi(str2);
613 if (i > 0 && i < 1000)
614 tsize[str1[0] - '1'] = i;
615 else
616 error("bad font size value at line %d", linenum);
617 break;
618
619 case 'r': /* roman */
620 if(str2[0] < '0') goto nofont;
621 tfont[0] = malloc(strlen(str2) + 1);
622 strcpy(tfont[0], str2);
623 break;
624
625 case 'i': /* italics */
626 if(str2[0] < '0') goto nofont;
627 tfont[1] = malloc(strlen(str2) + 1);
628 strcpy(tfont[1], str2);
629 break;
630
631 case 'b': /* bold */
632 if(str2[0] < '0') goto nofont;
633 tfont[2] = malloc(strlen(str2) + 1);
634 strcpy(tfont[2], str2);
635 break;
636
637 case 's': /* special */
638 if (str1[1] == 'c') goto scalecommand; /* or scale */
639
640 if(str2[0] < '0') {
641 nofont: error("no fontname specified in line %d", linenum);
642 break;
643 }
644 if (str1[1] == 't') goto stipplecommand; /* or stipple */
645
646 tfont[3] = malloc(strlen(str2) + 1);
647 strcpy(tfont[3], str2);
648 break;
649
650 case 'l': /* l */
651 if ((str1[1] < '1') || (str1[1] > '8'))
652 goto stipplecommand;
653
654 /* else set stipple index */
655 i = atoi(str2);
656 if (i >= 0 && i < 256)
657 stipple_index[str1[1] - '1'] = i;
658 else
659 error("bad stipple index value at line %d", linenum);
660 break;
661
662 stipplecommand: /* stipple */
663 stipple = malloc(strlen(str2) + 1);
664 strcpy(stipple, str2);
665 break;
666
667 case 'o': /* oldstipplemap */
668 oldstipmap = TRUE;
669 break;
670
671 case 't': /* thick */
672 thick[2] = atoi(str2);
673 break;
674
675 case 'm': /* medium */
676 thick[5] = atoi(str2);
677 break;
678
679 case 'n': /* narrow */
680 thick[0] = thick[1] = thick[3] = thick[4] = atoi(str2);
681 break;
682
683 case 'x': /* x */
684 scalecommand: /* scale */
685 par = atof(str2);
686 if (par > 0.0)
687 xscale *= par;
688 else
689 error("illegal scale value on line %d", linenum);
690 break;
691
692 case 'f': /* file */
693 strcpy(gremlinfile, str2);
694 break;
695
696 case 'w': /* width */
697 width = atof(str2);
698 if (width < 0.0) width = -width;
699 break;
700
701 case 'h': /* height */
702 height = atof(str2);
703 if (height < 0.0) height = -height;
704 break;
705
706 case 'd': /* defaults */
707 setdefault = 1;
708 break;
709
710 case 'p': /* pointscale */
711 if (strcmp("off", str2))
712 pointscale = 1;
713 else
714 pointscale = 0;
715 break;
716
717 default:
718 error("unknown command, %s, on line %d", str1, linenum);
719 exit(8);
720 break;
721 };
722 }
723
724
725 /*
726 * return TRUE if picture contains a polygon
727 * otherwise FALSE
728 */
has_polygon(elist)729 has_polygon(elist)
730 register ELT *elist;
731 {
732 while (!DBNullelt(elist)) {
733 if (elist->type == POLYGON)
734 return(1);
735 elist = DBNextElt(elist);
736 }
737
738 return(0);
739 }
740