/* Last non-groff version: main.c 1.23 (Berkeley) 85/08/05 * * Adapted to GNU troff by Daniel Senderowicz 99/12/29. * * Further refinements by Werner Lemberg 00/02/20. * * * This file contains the main and file system dependent routines for * processing gremlin files into troff input. The program watches input * go by to standard output, only interpreting things between .GS and * .GE lines. Default values (font, size, scale, thickness) may be * overridden with a 'default' command and are further overridden by * commands in the input. * * Inside the GS and GE, commands are accepted to reconfigure the * picture. At most one command may reside on each line, and each * command is followed by a parameter separated by white space. The * commands are as follows, and may be abbreviated down to one character * (with exception of 'scale' and 'stipple' down to "sc" and "st") and * may be upper or lower case. * * default - Make all settings in the current * .GS/.GE the global defaults. * Height, width and file are NOT * saved. * 1, 2, 3, 4 - Set size 1, 2, 3, or 4 (followed * by an integer point size). * roman, italics, bold, special - Set gremlin's fonts to any other * troff font (1 or 2 characters). * stipple, l - Use a stipple font for polygons. * Arg is troff font name. No * default. Can use only one stipple * font per picture. (See below for * stipple font index.) * scale, x - Scale is IN ADDITION to the global * scale factor from the default. * pointscale - Turn on scaling point sizes to * match 'scale' commands. (Optional * operand 'off' to turn it off.) * narrow, medium, thick - Set widths of lines. * file - Set the file name to read the * gremlin picture from. If the file * isn't in the current directory, * the gremlin library is tried. * width, height - These two commands override any * scaling factor that is in effect, * and forces the picture to fit into * either the height or width * specified, whichever makes the * picture smaller. The operand for * these two commands is a * floating-point number in units of * inches. * l (integer ) - Set association between stipple * and a stipple 'character'. * must be in the range 0 to * NSTIPPLES (16) inclusive. The * integer operand is an index in the * stipple font selected. Valid cf * (cifplot) indices are 1-32 * (although 24 is not defined), * valid ug (unigrafix) indices are * 1-14, and valid gs (gray scale) * indices are 0-16. Nonetheless, * any number between 0 and 255 is * accepted since new stipple fonts * may be added. An integer operand * is required. * * Troff number registers used: g1 through g9. g1 is the width of the * picture, and g2 is the height. g3, and g4, save information, g8 and * g9 are used for text processing and g5-g7 are reserved. */ #include "lib.h" #include #include #include // errno #include "gprint.h" #include "device.h" #include "font.h" #include "searchpath.h" #include "macropath.h" #include "errarg.h" #include "error.h" #include "defs.h" extern "C" const char *Version_string; /* database imports */ extern void HGPrintElt(ELT *element, int baseline); extern ELT *DBInit(); extern ELT *DBRead(FILE *file); extern POINT *PTInit(); extern POINT *PTMakePoint(double x, double y, POINT **pplist); #define INIT_FILE_SIZE 50 /* Initial sz of file array from cmd line. */ #define FILE_SIZE_INCR 50 /* Amount to increase array of files by. */ #define SUN_SCALEFACTOR 0.70 /* #define DEFSTIPPLE "gs" */ #define DEFSTIPPLE "cf" /* * This grn implementation emits '.st' requests to control stipple * effects, but groff does not (currently) support any such request. * * This hack disables the emission of such requests, without destroying * the infrastructure necessary to support the feature in the future; to * enable the emission of '.st' requests, at a future date when groff * can support them, simply rewrite the following #define as: * * #define USE_ST_REQUEST stipple * * with accompanying comment: "emit '.st' requests as required". */ #define USE_ST_REQUEST 0 /* never emit '.st' requests */ #define MAXINLINE 100 /* input line length */ #define SCREENtoINCH 0.02 /* scaling factor, screen to inches */ #define BIG 999999999999.0 /* unwieldy large floating number */ /* static char sccsid[] = "@(#) (Berkeley) 8/5/85, 12/28/99"; */ int res; /* the printer's resolution goes here */ int dotshifter; /* for the length of dotted curves */ double linethickness; /* brush styles */ int linmod; int lastx; /* point registers for printing */ int lasty; /* elements */ int lastyline; /* A line's vertical position is NOT */ /* the same after that line is over, */ /* so for a line of drawing commands, */ /* vertical spacing is kept in */ /* lastyline. */ /* These are the default fonts, sizes, line styles, */ /* and thicknesses. They can be modified from a */ /* 'default' command and are reset each time the */ /* start of a picture (.GS) is found. */ const char *deffont[] = {"R", "I", "B", "S"}; int defsize[] = {10, 16, 24, 36}; /* #define BASE_THICKNESS 1.0 */ #define BASE_THICKNESS 0.15 double defthick[STYLES] = {1 * BASE_THICKNESS, 1 * BASE_THICKNESS, 5 * BASE_THICKNESS, 1 * BASE_THICKNESS, 1 * BASE_THICKNESS, 3 * BASE_THICKNESS}; /* int cf_stipple_index[NSTIPPLES + 1] = */ /* {0, 1, 3, 12, 14, 16, 19, 21, 23}; */ /* a logarithmic scale looks better than a linear one for gray shades */ /* */ /* int other_stipple_index[NSTIPPLES + 1] = */ /* {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; */ int cf_stipple_index[NSTIPPLES + 1] = {0, 18, 32, 56, 100, 178, 316, 562, 1000}; /* only 1-8 used */ int other_stipple_index[NSTIPPLES + 1] = {0, 62, 125, 187, 250, 312, 375, 437, 500, 562, 625, 687, 750, 812, 875, 937, 1000}; /* int *defstipple_index = other_stipple_index; */ int *defstipple_index = cf_stipple_index; int style[STYLES] = {DOTTED, DOTDASHED, SOLID, DASHED, SOLID, SOLID}; double scale = 1.0; /* no scaling, default */ int defpoint = 0; /* flag for point size scaling */ char *defstipple = (char *) 0; enum E { OUTLINE, FILL, BOTH } polyfill; /* flag to control filling of polygons */ double adj1 = 0.0; double adj2 = 0.0; double adj3 = 0.0; double adj4 = 0.0; double thick[STYLES]; /* thicknesses set by defaults, then */ /* by commands */ char *tfont[FONTS]; /* fonts originally set to deffont */ /* values, then optionally changed by */ int tsize[SIZES]; /* commands inside grn */ int stipple_index[NSTIPPLES + 1]; /* stipple font file indices */ char *stipple; double xscale; /* scaling factor from individual pictures */ double troffscale; /* scaling factor at output time */ double width; /* user-request maximum width for picture */ /* (in inches) */ double height; /* user-request height */ int pointscale; /* flag for point size scaling */ int setdefault; /* flag for a .GS/.GE to remember all */ /* settings */ int sflag; /* -s flag: sort order (do polyfill first) */ double toppoint; /* remember the picture */ double bottompoint; /* bounds in these variables */ double leftpoint; double rightpoint; int ytop; /* these are integer versions of the above */ int ybottom; /* so not to convert each time they're used */ int xleft; int xright; static int linenum = 0; /* line number of troff input file */ char inputline[MAXINLINE]; /* spot to filter through the file */ char *c1 = inputline; /* c1, c2, and c3 will be used to */ char *c2 = inputline + 1; /* hunt for lines that begin with */ char *c3 = inputline + 2; /* '.GS' by looking individually */ char *c4 = inputline + 3; /* needed for compatibility mode */ char GScommand[MAXINLINE]; /* put user's '.GS' command line here */ char gremlinfile[MAXINLINE]; /* filename to use for a picture */ int SUNFILE = FALSE; /* TRUE if SUN gremlin file */ int compatibility_flag = FALSE; /* TRUE if in compatibility mode */ void getres(); int doinput(FILE *fp); void conv(FILE *fp, int baseline); void savestate(); int has_polygon(ELT *elist); void interpret(char *line); void * grnmalloc(size_t size, const char *what) { void *ptr = 0; ptr = malloc(size); if (!ptr) { fatal("memory allocation failed for %1: %2", what, strerror(errno)); } return ptr; } void usage(FILE *stream) { fprintf(stream, "usage: %s [-Cs] [-M dir] [-F dir] [-T dev] [file ...]\n" "usage: %s {-v | --version}\n" "usage: %s --help\n", program_name, program_name, program_name); } /* Add a new file entry in the array, expanding array if needs be. */ char ** add_file(char **file, char *new_file, int *count, int *cur_size) { if (*count >= *cur_size) { *cur_size += FILE_SIZE_INCR; file = (char **) realloc(file, *cur_size * sizeof(char *)); if (file == NULL) { fatal("unable to extend file array"); } } file[*count] = new_file; *count += 1; return file; } /*--------------------------------------------------------------------* | Routine: main (argument_count, argument_pointer) | | Results: Parses the command line, accumulating input file names, | then reads the inputs, passing it directly to output | until a '.GS' line is read. Main then passes control to | 'conv' to do the gremlin file conversions. *--------------------------------------------------------------------*/ int main(int argc, char **argv) { setlocale(LC_NUMERIC, "C"); program_name = argv[0]; FILE *fp; int k; char c; int gfil = 0; char **file = NULL; int file_cur_size = INIT_FILE_SIZE; char *operand(int *argcp, char ***argvp); file = (char **) grnmalloc(file_cur_size * sizeof(char *), "file array"); while (--argc) { if (**++argv != '-') file = add_file(file, *argv, &gfil, &file_cur_size); else switch (c = (*argv)[1]) { case 0: file = add_file(file, NULL, &gfil, &file_cur_size); break; case 'C': /* compatibility mode */ compatibility_flag = TRUE; break; case 'F': /* font path to find DESC */ font::command_line_font_dir(operand(&argc, &argv)); break; case 'T': /* final output typesetter name */ device = operand(&argc, &argv); break; case 'M': /* set library directory */ macro_path.command_line_dir(operand(&argc, &argv)); break; case 's': /* preserve order of elements */ sflag = 1; break; case '-': if (strcmp(*argv,"--version")==0) { case 'v': printf("GNU grn (groff) version %s\n", Version_string); exit(0); break; } if (strcmp(*argv,"--help")==0) { case '?': usage(stdout); exit(0); break; } // fallthrough default: error("unknown switch: %1", c); usage(stderr); exit(1); } } getres(); /* set the resolution for an output device */ if (gfil == 0) { /* no filename, use standard input */ file[0] = NULL; gfil++; } for (k = 0; k < gfil; k++) { if (file[k] != NULL) { if ((fp = fopen(file[k], "r")) == NULL) fatal("can't open %1", file[k]); } else fp = stdin; while (doinput(fp)) { if (*c1 == '.' && *c2 == 'G' && *c3 == 'S') { if (compatibility_flag || *c4 == '\n' || *c4 == ' ' || *c4 == '\0') conv(fp, linenum); else fputs(inputline, stdout); } else fputs(inputline, stdout); } } return 0; } /*--------------------------------------------------------------------* | Routine: char * operand (& argc, & argv) | | Results: Returns address of the operand given with a command-line | option. It uses either '-Xoperand' or '-X operand', | whichever is present. The program is terminated if no | option is present. | | Side Efct: argc and argv are updated as necessary. *--------------------------------------------------------------------*/ char * operand(int *argcp, char ***argvp) { if ((**argvp)[2]) return (**argvp + 2); /* operand immediately follows */ if ((--*argcp) <= 0) { /* no operand */ error("command-line option operand missing."); exit(8); } return (*(++(*argvp))); /* operand is next word */ } /*--------------------------------------------------------------------* | Routine: getres () | | Results: Sets 'res' to the resolution of the output device. *--------------------------------------------------------------------*/ void getres() { int linepiece; if (0 /* nullptr */ == font::load_desc()) fatal("cannot load 'DESC' description file for device '%1'", device); res = font::res; /* Correct the brush thicknesses based on res */ /* if (res >= 256) { defthick[0] = res >> 8; defthick[1] = res >> 8; defthick[2] = res >> 4; defthick[3] = res >> 8; defthick[4] = res >> 8; defthick[5] = res >> 6; } */ linepiece = res >> 9; for (dotshifter = 0; linepiece; dotshifter++) linepiece = linepiece >> 1; } /*--------------------------------------------------------------------* | Routine: int doinput (file_pointer) | | Results: A line of input is read into 'inputline'. | | Side Efct: "linenum" is incremented. | | Bugs: Lines longer than MAXINLINE are NOT checked, except for | updating 'linenum'. *--------------------------------------------------------------------*/ int doinput(FILE *fp) { if (fgets(inputline, MAXINLINE, fp) == NULL) return 0; if (strchr(inputline, '\n')) /* ++ only if it's a complete line */ linenum++; return 1; } /*--------------------------------------------------------------------* | Routine: initpic ( ) | | Results: Sets all parameters to the normal defaults, possibly | overridden by a setdefault command. Initialize the | picture variables, and output the startup commands to | troff to begin the picture. *--------------------------------------------------------------------*/ void initpic() { int i; for (i = 0; i < STYLES; i++) { /* line thickness defaults */ thick[i] = defthick[i]; } for (i = 0; i < FONTS; i++) { /* font name defaults */ tfont[i] = (char *)deffont[i]; } for (i = 0; i < SIZES; i++) { /* font size defaults */ tsize[i] = defsize[i]; } for (i = 0; i <= NSTIPPLES; i++) { /* stipple font file default */ /* indices */ stipple_index[i] = defstipple_index[i]; } stipple = defstipple; gremlinfile[0] = 0; /* filename is 'null' */ setdefault = 0; /* not the default settings (yet) */ toppoint = BIG; /* set the picture bounds out */ bottompoint = -BIG; /* of range so they'll be set */ leftpoint = BIG; /* by 'savebounds' on input */ rightpoint = -BIG; pointscale = defpoint;/* flag for scaling point sizes default */ xscale = scale; /* default scale of individual pictures */ width = 0.0; /* size specifications input by user */ height = 0.0; linethickness = DEFTHICK; /* brush styles */ linmod = DEFSTYLE; } /*--------------------------------------------------------------------* | Routine: conv (file_pointer, starting_line) | | Results: At this point, we just passed a '.GS' line in the input | file. conv reads the input and calls 'interpret' to | process commands, gathering up information until a '.GE' | line is found. It then calls 'HGPrint' to do the | translation of the gremlin file to troff commands. *--------------------------------------------------------------------*/ void conv(FILE *fp, int baseline) { FILE *gfp = NULL; /* input file pointer */ int done = 0; /* flag to remember if finished */ ELT *e; /* current element pointer */ ELT *PICTURE; /* whole picture data base pointer */ double temp; /* temporary calculating area */ /* POINT ptr; */ /* coordinates of a point to pass to 'mov' */ /* routine */ int flyback; /* flag 'want to end up at the top of the */ /* picture?' */ int compat; /* test character after .GE or .GF */ initpic(); /* set defaults, ranges, etc. */ strcpy(GScommand, inputline); /* save '.GS' line for later */ do { done = !doinput(fp); /* test for EOF */ flyback = (*c3 == 'F'); /* and .GE or .GF */ compat = (compatibility_flag || *c4 == '\n' || *c4 == ' ' || *c4 == '\0'); done |= (*c1 == '.' && *c2 == 'G' && (*c3 == 'E' || flyback) && compat); if (done) { if (setdefault) savestate(); if (!gremlinfile[0]) { if (!setdefault) error("no picture file name at line %1", baseline); return; } char *path; gfp = macro_path.open_file(gremlinfile, &path); if (0 /* nullptr */ == gfp) { error("cannot open picture file '%1'", gremlinfile); return; } PICTURE = DBRead(gfp); /* read picture file */ fclose(gfp); free(path); if (DBNullelt(PICTURE)) return; /* If a request is made to make the */ /* picture fit into a specific area, */ /* set the scale to do that. */ if (stipple == (char *) NULL) /* if user forgot stipple */ if (has_polygon(PICTURE)) /* and picture has a polygon */ stipple = (char *)DEFSTIPPLE; /* then set the default */ if ((temp = bottompoint - toppoint) < 0.1) temp = 0.1; temp = (height != 0.0) ? height / (temp * SCREENtoINCH) : BIG; if ((troffscale = rightpoint - leftpoint) < 0.1) troffscale = 0.1; troffscale = (width != 0.0) ? width / (troffscale * SCREENtoINCH) : BIG; if (temp == BIG && troffscale == BIG) troffscale = xscale; else { if (temp < troffscale) troffscale = temp; } /* here, troffscale is the */ /* picture's scaling factor */ if (pointscale) { int i; /* do point scaling here, when */ /* scale is known, before output */ for (i = 0; i < SIZES; i++) tsize[i] = (int) (troffscale * (double) tsize[i] + 0.5); } /* change to device units */ troffscale *= SCREENtoINCH * res; /* from screen units */ /* Calculate integer versions of the picture limits. */ ytop = (int) (toppoint * troffscale); ybottom = (int) (bottompoint * troffscale); xleft = (int) (leftpoint * troffscale); xright = (int) (rightpoint * troffscale); /* save stuff in number registers, */ /* register g1 = picture width and */ /* register g2 = picture height, */ /* set vertical spacing, no fill, */ /* and break (to make sure picture */ /* starts on left), and put out the */ /* user's '.GS' line. */ printf(".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", xright - xleft, ybottom - ytop, GScommand); if (USE_ST_REQUEST) /* stipple requested for this picture */ printf(".st %s\n", stipple); lastx = xleft; /* note where we are (upper left */ lastyline = lasty = ytop; /* corner of the picture) */ /* Just dump everything in the order it appears. * * If -s command-line option, traverse picture twice: First time, * print only the interiors of filled polygons (as borderless * polygons). Second time, print the outline as series of line * segments. This way, postprocessors that overwrite rather than * merge picture elements (such as Postscript) can still have text * and graphics on a shaded background. */ /* if (sflag) */ if (!sflag) { /* changing the default for filled polygons */ e = PICTURE; polyfill = FILL; while (!DBNullelt(e)) { printf(".mk\n"); if (e->type == POLYGON) HGPrintElt(e, baseline); printf(".rt\n"); lastx = xleft; lastyline = lasty = ytop; e = DBNextElt(e); } } e = PICTURE; /* polyfill = !sflag ? BOTH : OUTLINE; */ polyfill = sflag ? BOTH : OUTLINE; /* changing default */ while (!DBNullelt(e)) { printf(".mk\n"); HGPrintElt(e, baseline); printf(".rt\n"); lastx = xleft; lastyline = lasty = ytop; e = DBNextElt(e); } /* decide where to end picture */ /* I [Senderowicz?] changed everything here. I always use the */ /* combination .mk and .rt, so once finished I just space down */ /* height of the picture that is \n(g2u. */ if (flyback) { /* end picture at upper left */ /* ptr.x = leftpoint; ptr.y = toppoint; */ } else { /* end picture at lower left */ /* ptr.x = leftpoint; ptr.y = bottompoint; */ printf(".sp \\n(g2u\n"); } /* tmove(&ptr); */ /* restore default line parameters */ /* Restore everything to the way it was before the .GS, then */ /* put out the '.GE' line from user */ /* printf("\\D't %du'\\D's %du'\n", DEFTHICK, DEFSTYLE); */ /* groff doesn't understand the \Ds command */ printf("\\D't %du'\n", DEFTHICK); if (flyback) /* make sure we end up at top of */ printf(".sp -1\n"); /* picture if 'flying back' */ if (USE_ST_REQUEST) /* restore stipple to previous */ printf(".st\n"); printf(".br\n" ".ft \\n(g3\n" ".ps \\n(g4\n" "%s", inputline); } else interpret(inputline); /* take commands from the input file */ } while (!done); } /*--------------------------------------------------------------------* | Routine: savestate ( ) | | Results: All the current scaling/font size/font name/thickness/ | pointscale settings are made the defaults. Scaled | point sizes are NOT saved. The scaling is done each | time a new picture is started. | | Side Efct: scale, and def* are modified. *--------------------------------------------------------------------*/ void savestate() { int i; for (i = 0; i < STYLES; i++) /* line thickness defaults */ defthick[i] = thick[i]; for (i = 0; i < FONTS; i++) /* font name defaults */ deffont[i] = tfont[i]; for (i = 0; i < SIZES; i++) /* font size defaults */ defsize[i] = tsize[i]; /* stipple font file default indices */ for (i = 0; i <= NSTIPPLES; i++) defstipple_index[i] = stipple_index[i]; defstipple = stipple; /* if stipple has been set, it's remembered */ scale *= xscale; /* default scale of individual pictures */ defpoint = pointscale;/* flag to scale point sizes from x factors */ } /*--------------------------------------------------------------------* | Routine: savebounds (x_coordinate, y_coordinate) | | Results: Keeps track of the maximum and minimum extent of a | picture in the global variables: left-, right-, top- and | bottompoint. 'savebounds' assumes that the points have | been oriented to the correct direction. No scaling has | taken place, though. *--------------------------------------------------------------------*/ void savebounds(double x, double y) { if (x < leftpoint) leftpoint = x; if (x > rightpoint) rightpoint = x; if (y < toppoint) toppoint = y; if (y > bottompoint) bottompoint = y; } /*--------------------------------------------------------------------* | Routine: interpret (character_string) | | Results: Commands are taken from the input string and performed. | Commands are separated by newlines, and are of the | format: | string1 string2 | where string1 is the command, string2 the argument. | | Side Efct: Font and size strings, plus the gremlin file name and | the width and height variables are set by this routine. *--------------------------------------------------------------------*/ void interpret(char *line) { char str1[MAXINLINE]; char str2[MAXINLINE]; char *chr; int i; double par; str2[0] = '\0'; sscanf(line, "%80s%80s", &str1[0], &str2[0]); for (chr = &str1[0]; *chr; chr++) /* convert command to */ if (isupper(*chr)) *chr = tolower(*chr); /* lower case */ switch (str1[0]) { case '1': case '2': /* font sizes */ case '3': case '4': i = atoi(str2); if (i > 0 && i < 1000) tsize[str1[0] - '1'] = i; else error("bad font size value at line %1", linenum); break; case 'r': /* roman */ if (str2[0] < '0') goto nofont; tfont[0] = (char *) grnmalloc(strlen(str2) + 1, "roman command"); strcpy(tfont[0], str2); break; case 'i': /* italics */ if (str2[0] < '0') goto nofont; tfont[1] = (char *) grnmalloc(strlen(str2) + 1, "italics command"); strcpy(tfont[1], str2); break; case 'b': /* bold */ if (str2[0] < '0') goto nofont; tfont[2] = (char *) grnmalloc(strlen(str2) + 1, "bold command"); strcpy(tfont[2], str2); break; case 's': /* special */ if (str1[1] == 'c') goto scalecommand; /* or scale */ if (str2[0] < '0') { nofont: error("no font name specified in line %1", linenum); break; } if (str1[1] == 't') goto stipplecommand; /* or stipple */ tfont[3] = (char *) grnmalloc(strlen(str2) + 1, "special command"); strcpy(tfont[3], str2); break; case 'l': /* l */ if (isdigit(str1[1])) { /* set stipple index */ int idx = atoi(str1 + 1), val; if (idx < 0 || idx > NSTIPPLES) { error("bad stipple number %1 at line %2", idx, linenum); break; } if (!defstipple_index) defstipple_index = other_stipple_index; val = atoi(str2); if (val >= 0 && val < 256) stipple_index[idx] = val; else error("bad stipple index value at line %1", linenum); break; } stipplecommand: /* set stipple name */ stipple = (char *) grnmalloc(strlen(str2) + 1, "stipple command"); strcpy(stipple, str2); /* if it's a 'known' font (currently only 'cf'), set indices */ if (strcmp(stipple, "cf") == 0) defstipple_index = cf_stipple_index; else defstipple_index = other_stipple_index; for (i = 0; i <= NSTIPPLES; i++) stipple_index[i] = defstipple_index[i]; break; case 'a': /* text adjust */ par = atof(str2); switch (str1[1]) { case '1': adj1 = par; break; case '2': adj2 = par; break; case '3': adj3 = par; break; case '4': adj4 = par; break; default: error("bad adjust command at line %1", linenum); break; } break; case 't': /* thick */ thick[2] = defthick[0] * atof(str2); break; case 'm': /* medium */ thick[5] = defthick[0] * atof(str2); break; case 'n': /* narrow */ thick[0] = thick[1] = thick[3] = thick[4] = defthick[0] * atof(str2); break; case 'x': /* x */ scalecommand: /* scale */ par = atof(str2); if (par > 0.0) xscale *= par; else error("invalid scale value on line %1", linenum); break; case 'f': /* file */ strcpy(gremlinfile, str2); break; case 'w': /* width */ width = atof(str2); if (width < 0.0) width = -width; break; case 'h': /* height */ height = atof(str2); if (height < 0.0) height = -height; break; case 'd': /* defaults */ setdefault = 1; break; case 'p': /* pointscale */ if (strcmp("off", str2)) pointscale = 1; else pointscale = 0; break; default: error("unknown command '%1' on line %2", str1, linenum); exit(8); break; }; } /* * return TRUE if picture contains a polygon * otherwise FALSE */ int has_polygon(ELT *elist) { while (!DBNullelt(elist)) { if (elist->type == POLYGON) return (1); elist = DBNextElt(elist); } return (0); } // Local Variables: // fill-column: 72 // mode: C++ // End: // vim: set cindent noexpandtab shiftwidth=2 textwidth=72: