diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:44:05 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:44:05 +0000 |
commit | d318611dd6f23fcfedd50e9b9e24620b102ba96a (patch) | |
tree | 8b9eef82ca40fdd5a8deeabf07572074c236095d /src/preproc/grn/main.cpp | |
parent | Initial commit. (diff) | |
download | groff-upstream.tar.xz groff-upstream.zip |
Adding upstream version 1.23.0.upstream/1.23.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/preproc/grn/main.cpp | 977 |
1 files changed, 977 insertions, 0 deletions
diff --git a/src/preproc/grn/main.cpp b/src/preproc/grn/main.cpp new file mode 100644 index 0000000..6d6d586 --- /dev/null +++ b/src/preproc/grn/main.cpp @@ -0,0 +1,977 @@ +/* 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<nn> (integer <nn>) - Set association between stipple + * <nn> and a stipple 'character'. + * <nn> 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 <ctype.h> +#include <stdlib.h> +#include <errno.h> // 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: |