take stipple map out as default and made it an option
[unix-history] / usr / src / local / ditroff / ditroff.old.okeeffe / grn / main.c
index b911a9b..b26b398 100644 (file)
@@ -1,34 +1,78 @@
-/*     main.c  1.1     (Berkeley) 83/07/21
+/*     main.c  1.24    (Berkeley)      86/04/14
  *
  *     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 interpretting things between .GS
  *
  *     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 interpretting things between .GS
- * and .GE lines.  Default values may be overridden, as in gprint, on the
- * command line and are further overridden by commands in the input.
+ * 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.  A description of the command-line options are
+ * listed below.  A space is NOT required for the operand of an option.
  *
  *     command options are:
  *
  *
  *     command options are:
  *
- *     -1 #    sets point size 1 to #.  also for -2, -3, -4.  Defaults
- *             are 12, 16, 24, 36.
+ *     -L dir  set the library directory to dir.  If a file is not found
+ *             in the current directory, it is looked for in dir (default
+ *             is /usr/lib/gremlib).
  *
  *
- *     -r ss   sets gremlin's roman font to troff font ss.  Also for -i,
- *             -b and -s for italics, bold, and special fonts.  This does
- *             NOT affect font changes imbedded into strings.  A \fI, for
- *             instance, will get the italics font regardless of what -i
- *             is set to.
+ *     -T dev  Prepare output for "dev" printer.  Default is for the varian
+ *     -P dev  and versatec printers.  Devices acceptable are:  ver, var, ip.
  *
  *
- *     -n #    set narrow line thickness to # pixels.  Also for -m (medium)
- *             and -t (thick).
+ *             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.
  *
  *
- *     -x #    scale the picture by x (integer or decimal).
+ *                           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 (one or two 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 pixel 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
+ *                     oldstipplemap  -  use the old-style stipple mapping.
+ *                                       THE FOLLOWING COMMANDS ARE IGNORED
+ *                                       UNLESS OLDSTIPPLEMAP IS SPECIFIED.
+ *     l1, l2, l3, l4, l5, l6, l7, l8  -  set association between stipples
+ *                                       (1 - 8) and the stipple font file
+ *                                       index.  Valid cifplot indices are
+ *                                       1 - 32 (although 24 is not defined)
+ *                                       and valid unigrafix indices are
+ *                                       1 - 64.  Nonetheless, any number
+ *                                       between 0 and 255 is accepted since
+ *                                       new stipple fonts may be added.
+ *                                       An integer operand is required.
  *
  *
- *     -Tdev   Prepare output for "dev" printer.  Default is for the varian
- *             and versatec printers.  Devices acceptable are:  ver, var, ip.
- *
- *     -p      prompt user for fonts, sizes and thicknesses.
+ *     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 <ctype.h>
 #include "gprint.h"
 #include "dev.h"
 
 #include "gprint.h"
 #include "dev.h"
 
@@ -42,26 +86,35 @@ extern ELT *DBInit(), *DBRead();
 extern POINT *PTInit(), *PTMakePoint();
 
 
 extern POINT *PTInit(), *PTMakePoint();
 
 
-char *doinput();
+#ifndef GREMLIB
+#define GREMLIB                "/usr/local/gremlib/"
+#endif
+
+#define SUN_SCALEFACTOR 0.70
 
 
-#define DEVDIR         "/usr/lib/font/dev"
-#define DEFAULTDEV     "var"
+#ifndef DEVDIR
+#define DEVDIR         "/usr/lib/font"
+#endif
+#define DEFAULTDEV     "va"
+#define DEFSTIPPLE     "cf"
 
 #define MAXINLINE      100             /* input line length */
 #define DEFTHICK       3               /* default thicknes */
 #define DEFSTYLE       SOLID           /* default line style */
 
 
 #define MAXINLINE      100             /* input line length */
 #define DEFTHICK       3               /* default thicknes */
 #define DEFSTYLE       SOLID           /* default line style */
 
+#ifdef oldversion
 #define SCREENtoINCH   0.02            /* scaling factor, screen to inches */
 #define SCREENtoINCH   0.02            /* scaling factor, screen to inches */
-#define BIG    100000000000.0          /* unweildly large floating number */
+#endif
 
 
-#define JLEFT          -1              /* justification constants - for the */
-#define JCENTER                0               /*    whole picture - where it will */
-#define JRIGHT         1               /*    get placed within the line */
+double SCREENtoINCH;                   /* scaling factor, screen to inches */
 
 
+#define BIG    999999999999.0          /* unweildly large floating number */
 
 
-char   SccsId[] = "main.c      1.1     83/07/21";
+
+static char sccsid[] = "@(#) (Berkeley) %G%";
 
 char   *printer = DEFAULTDEV;  /* device to look up resolution of */
 
 char   *printer = DEFAULTDEV;  /* device to look up resolution of */
+char   *gremlib = GREMLIB;     /* place to find files after current dir. */
 double res;                    /* that printer's resolution goes here */
 
 int    linethickness;          /* brush styles */
 double res;                    /* that printer's resolution goes here */
 
 int    linethickness;          /* brush styles */
@@ -72,38 +125,33 @@ 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 */
                                /* after that line is over, so for a line of */
                                /* drawing commands, vertical spacing is kept */
                                /* in lastyline */
-double scale = SCREENtoINCH;   /* default scale to map gremlin screen to inches
-                                  (modified by -x command-line option) */
-
-                   /* list of prompts for asking user to set default values */
-char   *prompt[] = {                             /* used only for -p option */
-               "Roman font name? (%s): ",      "Italic font name? (%s): ",
-               "Bold font name? (%s): ",       "Special font name? (%s): ",
-               "font size 1? (%s): ",          "font size 2? (%s): ",
-               "font size 3? (%s): ",          "font size 4? (%s): ",
-       };
-
-                       /* these are the default fonts, sizes, */
-                       /*   line styles, and thicknesses.  These */
-                       /*   can be modified from command-line */
-                       /*   options, and are reset each time the */
-                       /*   start of a picture (.GS) is found. */
-
-char   *defstring[] = {
-               "R\0         ", "I\0         ", "B\0         ", "S\0         ",
-               "10\0        ", "16\0        ", "24\0        ", "36\0        "
-       };
-int    defthick[STYLES] = { 1, 1, 5, 1, 1, 3 };        /* defaults... */
-int    style[STYLES] = { DOTTED, DOTDASHED, SOLID, DASHED, SOLID, SOLID };
+
+                       /* these are the default fonts, sizes, line styles, */
+                       /*   and thicknesses.  These can be modified from a */
+                       /*   "default" command and are reset each time the  */
+                       /*   start of a picture (.GS) is found.             */
+
+char * deffont[] = {  "R", "I", "B", "S"  };
+int    defsize[] = {  10, 16, 24, 36  };
+int    defthick[STYLES] = {  1, 1, 5, 1, 1, 3  };
+int    defstipple_index[NSTIPPLES] = { 1, 3, 12, 14, 16, 19, 21, 23 };
+int    style[STYLES] = {  DOTTED, DOTDASHED, SOLID, DASHED, SOLID, SOLID  };
+double scale = 1.0;            /* no scaling, default */
+int    defpoint = 0;           /* flag for pointsize scaling */
+char *  defstipple = (char *) 0;
+
 int    thick[STYLES];  /* thicknesses set by defaults, then by commands */
 int    thick[STYLES];  /* thicknesses set by defaults, then by commands */
-char   *tfont[FONTS];  /* fonts originally set to defstring values, then */
-char   *tsize[SIZES];  /*    optionally changed by commands inside grn */
+char   *tfont[FONTS];  /* fonts originally set to deffont values, then */
+int    tsize[SIZES];   /*    optionally changed by commands inside grn */
+int    stipple_index[NSTIPPLES];       /* stipple font file indices */
+char *  stipple;
 
 
-int    cfont;          /* current font */
-int    csize;          /* current point size */
+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 */
 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 pointsize scaling */
+int    setdefault;     /* flag for a .GS/.GE to remember all settings */
 
 double toppoint;               /* remember the picture */
 double bottompoint;            /* bounds in these variables */
 
 double toppoint;               /* remember the picture */
 double bottompoint;            /* bounds in these variables */
@@ -121,7 +169,11 @@ 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   GScommand[MAXINLINE];           /* put user's ".GS" command line here */
 char   *c2 = inputline + 1;            /* hunt for lines that begin with */
 char   *c3 = inputline + 2;            /* ".GS" by looking individually */
 char   GScommand[MAXINLINE];           /* put user's ".GS" command line here */
-char   gremlinfile[50];                /* filename to use for a picture */
+char   gremlinfile[MAXINLINE];         /* filename to use for a picture */
+int    SUNFILE = FALSE;                /* TRUE if SUN gremlin file */
+int    oldstipmap = FALSE;             /* TRUE if old-style stipple mapping */
+
+char *doinput();
 
 
 /*----------------------------------------------------------------------------*
 
 
 /*----------------------------------------------------------------------------*
@@ -131,113 +183,45 @@ char     gremlinfile[50];                /* filename to use for a picture */
  |             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.
  |             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.
- |
- | Bugs:       a -p option ALWAYS reads standard input.  Even if the input
- |             file is coming in that way.
  *----------------------------------------------------------------------------*/
 
 main(argc, argv)
 int argc;
 char **argv;
 {
  *----------------------------------------------------------------------------*/
 
 main(argc, argv)
 int argc;
 char **argv;
 {
-       register FILE *fp = stdin;
+       register FILE *fp;
        register int k;
        register char c;
        register int k;
        register char c;
-       char *file[50], string[50], *arg;
-       float mult;
-       int brsh, gfil = 0;
-
-
-       argc--;
-       argv++;
-       while (argc--) {
-           if (*(arg = *argv++) != '-')
-               file[gfil++] = arg;
-           else switch (c = *++arg) {
-
-               case '1':       /* select sizes */
-               case '2':
-               case '3':
-               case '4':
-                       if (*++arg == '\0' && argc--)
-                           arg = *argv++;
-                       strcpy(defstring[c + FONTS - '1'], arg);
-                       break;
-               case 'r':       /* select Roman font */
-                       if (*++arg == '\0' && argc--)
-                           arg = *argv++;
-                       strcpy(string[0], arg);
-                       break;
-               case 'i':       /* select italics font */
-                       if (*++arg == '\0' && argc--)
-                           arg = *argv++;
-                       strcpy(string[1], arg);
-                       break;
-               case 'b':       /* select bold font */
-                       if (*++arg == '\0' && argc--)
-                           arg = *argv++;
-                       strcpy(string[2], arg);
-                       break;
-               case 's':       /* select special font */
-                       if (*++arg == '\0' && argc--)
-                           arg = *argv++;
-                       strcpy(string[3], arg);
-                       break;
-               case 'n':       /* select narrow brush width */
-                       if (*++arg == '\0' && argc--)
-                           arg = *argv++;
-                       (void) sscanf(arg, "%d", &brsh);
-                       defthick[0]=defthick[1]=defthick[3]=defthick[4] = brsh;
-                       break;
-               case 't':       /* select thick brush width */
-                       if (*++arg == '\0' && argc--)
-                           arg = *argv++;
-                       (void) sscanf(arg, "%d", &brsh);
-                       defthick[2] = brsh;
-                       break;
-               case 'm':       /* select medium brush width */
-                       if (*++arg == '\0' && argc--)
-                           arg = *argv++;
-                       (void) sscanf(arg, "%d", &brsh);
-                       defthick[5] = brsh;
-                       break;
-               case 'x':       /* select scale */
-                       if (*++arg == '\0' && argc--)
-                           arg = *argv++;
-                       sscanf(arg,"%f", &mult);
-                       scale *= mult;
+       register gfil = 0;
+       char *file[50];
+
+       char *operand();
+       char *getenv();
+
+
+       if (fp = (FILE *) getenv("PRINTER")) printer = (char *) fp;
+       if (fp = (FILE *) getenv("TYPESETTER")) printer = (char *) fp;
+       while (--argc) {
+           if (**++argv != '-')
+               file[gfil++] = *argv;
+           else
+             switch (c = (*argv)[1]) {
+
+               case 0:
+                       file[gfil++] = NULL;
                        break;
                        break;
+
+               case 'P':
                case 'T':       /* final output typesetter name */
                case 'T':       /* final output typesetter name */
-                       printer = arg + 1;
+                       printer = operand(&argc, &argv);
                        break;
                        break;
-               case 'p':       /* prompt for font and size parameters */
-                       for (k = 0; k < 8; k++) {
-                           fprintf(stderr, prompt[k], string[k]);
-                           gets(string);
-                           if (*string != '\0') strcpy(string[k], string);
-                       }
-                       fprintf(stderr,"narrow brush size? (%d): ",defthick[0]);
-                       gets(string);
-                       if (*string != '\0') {
-                           sscanf(string, "%d", &brsh);
-                           defthick[0] = defthick[1] = defthick[3]
-                                                       = defthick[4] = brsh;
-                       }
-                       fprintf(stderr,"medium brush size? (%d): ",defthick[5]);
-                       gets(string);
-                       if (*string != '\0') {
-                           sscanf(string, "%d", &brsh);
-                           defthick[5] = brsh;
-                       }
-                       fprintf(stderr, "thick brush size? (%d): ",defthick[2]);
-                       gets(string);
-                       if (*string != '\0') {
-                           sscanf(string, "%d", &brsh);
-                           defthick[2] = brsh;
-                       }
+
+               case 'L':       /* set library directory */
+                       gremlib = operand(&argc, &argv);
                        break;
                        break;
+
                default:
                default:
-                       fprintf(stderr, "unknown switch: %c\n", c);
+                       error("unknown switch: %c", c);
            }
        }
                                /* set the resolution for an output device */
            }
        }
                                /* set the resolution for an output device */
@@ -247,17 +231,12 @@ char **argv;
                file[0] = NULL;
                gfil++;
        }
                file[0] = NULL;
                gfil++;
        }
+
        for (k=0; k<gfil; k++) {
                if (file[k] != NULL) {
                        if ((fp = fopen(file[k], "r")) == NULL) {
        for (k=0; k<gfil; k++) {
                if (file[k] != NULL) {
                        if ((fp = fopen(file[k], "r")) == NULL) {
-                           fprintf(stderr, "grn: can't open %s\n", file[k]);
-                           continue;
-                       }
-                       if (k == 0) {
-                               if ((arg = rindex(file[k], '/')) == NULL)
-                                       arg = file[k];
-                               else
-                                       arg++;
+                           error("can't open %s", file[k]);
+                           exit(1);
                        }
                } else {
                        fp = stdin;
                        }
                } else {
                        fp = stdin;
@@ -274,6 +253,45 @@ char **argv;
 }
 
 
 }
 
 
+/*----------------------------------------------------------------------------*
+ | Routine:    error (control_string, args, . . . )
+ |
+ | Results:    prints ("grn: ", the control_string + args, "\n") to stderr
+ *----------------------------------------------------------------------------*/
+
+/* VARARGS1 */
+error(s, a1, a2, a3, a4)
+char * s;
+{
+       fprintf(stderr, "grn: ");
+       fprintf(stderr, s, a1, a2, a3, a4);
+       fprintf(stderr, "\n");
+}
+
+
+/*----------------------------------------------------------------------------*
+ | 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(argcp, argvp)
+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 (device_name)
  |
 /*----------------------------------------------------------------------------*
  | Routine:    getres (device_name)
  |
@@ -288,9 +306,9 @@ char *name;
        struct dev device;
        char temp[60];
 
        struct dev device;
        char temp[60];
 
-       sprintf(temp, "%s%s/DESC.out", DEVDIR, name);
+       sprintf(temp, "%s/dev%s/DESC.out", DEVDIR, name);
        if ((fin = open(temp, 0)) < 0) {
        if ((fin = open(temp, 0)) < 0) {
-           fprintf(stderr, "can't open tables for %s\n", temp);
+           error("can't open tables for %s", temp);
            exit(1);
        }
        read(fin, &device, sizeof(struct dev));
            exit(1);
        }
        read(fin, &device, sizeof(struct dev));
@@ -313,7 +331,7 @@ char *name;
 char *doinput(fp)
 FILE *fp;
 {
 char *doinput(fp)
 FILE *fp;
 {
-    register char *k;
+    char *k;
 
 
     if ((k = fgets(inputline, MAXINLINE, fp)) == NULL)
 
 
     if ((k = fgets(inputline, MAXINLINE, fp)) == NULL)
@@ -328,7 +346,7 @@ FILE *fp;
  | Routine:    initpic ( )
  |
  | Results:    sets all parameters to the normal defaults, possibly overridden
  | Routine:    initpic ( )
  |
  | Results:    sets all parameters to the normal defaults, possibly overridden
- |             by the command line flags.  Initilaize the picture variables,
+ |             by a setdefault command.  Initilaize the picture variables,
  |             and output the startup commands to troff to begin the picture.
  *----------------------------------------------------------------------------*/
 
  |             and output the startup commands to troff to begin the picture.
  *----------------------------------------------------------------------------*/
 
@@ -340,19 +358,26 @@ initpic()
        thick[i] = defthick[i];
     }
     for (i = 0; i < FONTS; i++) {      /* font name defaults */
        thick[i] = defthick[i];
     }
     for (i = 0; i < FONTS; i++) {      /* font name defaults */
-       tfont[i] = defstring[i];
+       tfont[i] = deffont[i];
     }
     for (i = 0; i < SIZES; i++) {      /* font size defaults */
     }
     for (i = 0; i < SIZES; i++) {      /* font size defaults */
-       tsize[i] = defstring[FONTS + i];
+       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" */
 
     gremlinfile[0] = 0;                /* filename is "null" */
+    setdefault = 0;            /* this is not the default settings (yet) */
 
     toppoint = BIG;            /* set the picture bounds out */
 
     toppoint = BIG;            /* set the picture bounds out */
-    bottompoint = 0.0;         /* of range so they'll be set */
+    bottompoint = -BIG;                /* of range so they'll be set */
     leftpoint = BIG;           /* by "savebounds" on input */
     leftpoint = BIG;           /* by "savebounds" on input */
-    rightpoint = 0.0;
+    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;
 
     width = 0.0;               /* size specifications input by user */
     height = 0.0;
 
@@ -375,84 +400,121 @@ conv(fp, baseline)
 register FILE *fp;
 int baseline;
 {
 register FILE *fp;
 int baseline;
 {
-       register FILE *gfp = NULL;
-       register int done = 0;
-       register ELT *e;
-       ELT *PICTURE;
-       double temp;
-       POINT ptr;
+       register FILE *gfp = NULL;      /* input file pointer */
+       register int done = 0;          /* flag to remember if finished */
+       register 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?" */
 
 
 
 
-       strcpy (GScommand, inputline);          /* save ".GS" line for later */
+       initpic();                      /* set defaults, ranges, etc. */
+       strcpy (GScommand, inputline);  /* save ".GS" line for later */
        do {
            done = (doinput(fp) == NULL);                    /* test for EOF */
        do {
            done = (doinput(fp) == NULL);                    /* test for EOF */
-           done |= (*c1 == '.' && *c2 == 'G' && *c3 == 'E');    /*  and .GE */
+           flyback = *c3 == 'F';                          /* and .GE or .GF */
+           done |= (*c1 == '.' && *c2 == 'G' && (*c3 == 'E' || flyback));
 
            if (done) {
 
            if (done) {
+               if (setdefault) savestate();
+
                if (!gremlinfile[0]) {
                if (!gremlinfile[0]) {
-                   fprintf(stderr, "grn: at line %d: no picture filename.\n",
-                                                                   baseline);
+                   if(!setdefault)
+                       error("at line %d: no picture filename.\n", baseline);
                    return;
                }
                if ((gfp = fopen(gremlinfile, "r")) == NULL) {
                    return;
                }
                if ((gfp = fopen(gremlinfile, "r")) == NULL) {
-                   fprintf(stderr, "grn: can't open %s\n", gremlinfile);
-                   return;
+                   char name[MAXINLINE]; /* if the file isn't in the current */
+                                       /* directory, try the gremlin library */
+                   sprintf(name, "%s%s", gremlib, gremlinfile);
+                   if ((gfp = fopen(name, "r")) == NULL) {
+                       error("can't open %s", gremlinfile);
+                       return;
+                   }
                }
                }
-               initpic();              /* set defaults, ranges, etc. */
-
                PICTURE = DBRead(gfp);                  /* read picture file */
                fclose(gfp);
                if (DBNullelt(PICTURE))
                PICTURE = DBRead(gfp);                  /* read picture file */
                fclose(gfp);
                if (DBNullelt(PICTURE))
-                   return;
-                                       /* if a request is made to make the */
+                   return;             /* if a request is made to make the */
                                        /* picture fit into a specific area, */
                                        /* set the scale to do that. */
                                        /* picture fit into a specific area, */
                                        /* set the scale to do that. */
-               temp = (height != 0.0)  ?
-                       SCREENtoINCH * (bottompoint - toppoint) / height  : BIG;
-               troffscale = (width != 0.0)  ?
-                       SCREENtoINCH * (rightpoint - leftpoint) / width  : BIG;
+
+               SCREENtoINCH = (SUNFILE) ? 0.014 : 0.02;
+
+               if (stipple == (char *) NULL)   /* if user forgot stipple */
+                   if (has_polygon(PICTURE))   /* and picture has a polygon */
+                       stipple = 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) {
                if (temp == BIG && troffscale == BIG) {
-                   troffscale = scale;
+                   troffscale = xscale;
                } else {
                    if (temp < troffscale) troffscale = temp;
                } else {
                    if (temp < troffscale) troffscale = temp;
+               }                               /* here, troffscale is the */
+                                               /* picture's scaling factor */
+               if (pointscale) {
+                   register int i;             /* do pointscaling here, when */
+                                            /* scale is known, before output */
+
+                   for (i = 0; i < SIZES; i++)
+                       tsize[i] = (int) (troffscale * (double) tsize[i] + 0.5);
+
                }
                }
-               troffscale *= res;      /* change to device units from inches */
+                                                  /* change to device units */
+               troffscale *= SCREENtoINCH * res;       /* from screen units */
 
                ytop = toppoint * troffscale;           /* calculate integer */
                ybottom = bottompoint * troffscale;     /* versions of the */
                xleft = leftpoint * troffscale;         /* picture limits */
                xright = rightpoint * troffscale;
                                        /* save stuff in number registers, */
 
                ytop = toppoint * troffscale;           /* calculate integer */
                ybottom = bottompoint * troffscale;     /* versions of the */
                xleft = leftpoint * troffscale;         /* picture limits */
                xright = rightpoint * troffscale;
                                        /* save stuff in number registers, */
-                                       /*   register gw = picture width and */
-                                       /*   register gh = picture height, */
+                                       /*   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. */
                                        /*   set vertical spacing, no fill, */
                                        /*   and break (to make sure picture */
                                        /*   starts on left), and put out the */
                                        /*   user's ".GS" line. */
-               printf(".nr g1 \\n(.f\n.nr g2 \\n(.s\n");
-               printf(".nr g3 \\n(.v\n.nr g4 \\n(.u\n");
-               printf(".nr gw %d\n.nr gh %d\n", xright-xleft, ybottom-ytop);
-               printf("%s.br\n.nf\n.vs 0", GScommand);
+               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 (stipple) {          /* 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) */
 
                e = PICTURE;
 
                lastx = xleft;          /* note where we are, (upper left */
                lastyline = lasty = ytop;       /* corner of the picture) */
 
                e = PICTURE;
-               while (!DBNullelt(e)) {
-                   HGPrintElt(e);      /* traverse picture;  print elements */
+               while (!DBNullelt(e)) { /* traverse picture;  print elements */
+                   HGPrintElt(e, baseline);
                    e = DBNextElt(e);
                }
                    e = DBNextElt(e);
                }
-                                       /* end picture at lower left */
-               ptr.x = leftpoint;
-               ptr.y = bottompoint;
-               tmove(&ptr);
-               printf("\\D't %du'\\D's %du'", DEFTHICK, DEFSTYLE);
-               cr ();
-                                       /* put out the ".GE" line from user */
-                                       /* then restore everything to the way */
-                                       /* it was before the .GS */
-               printf("%s.ft \\n(g1\n.ps \\n(g2\n", inputline);
-               printf(".vs \\n(g3u\n.if \\n(g4 .fi\n");
+                               /* decide where to end picture */
+               if (flyback) {          /* end piture at upper left */
+                   ptr.x = leftpoint;
+                   ptr.y = toppoint;
+               } else {                /* end picture at lower left */
+                   ptr.x = leftpoint;
+                   ptr.y = bottompoint;
+               }
+               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);
+               if (flyback) {          /* make sure we end up at top of */
+                   printf(".sp -1\n");         /* picture if "flying back" */
+               }
+               if (stipple) {          /* 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 */
            }
            } else {
                interpret(inputline);   /* take commands from the input file */
            }
@@ -460,6 +522,40 @@ int baseline;
 }
 
 
 }
 
 
+/*----------------------------------------------------------------------------*
+ | Routine:    savestate  ( )
+ |
+ | Results:    all the current  scaling / font size / font name / thickness /
+ |             pointscale  settings are saved to be 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.
+ *----------------------------------------------------------------------------*/
+
+savestate()
+{
+    register 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];
+    }
+    for (i = 0; i < NSTIPPLES; i++) {  /* stipple font file default indices */
+       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 for scaling pointsizes from x factors */
+}
+
+
 /*----------------------------------------------------------------------------*
  | Routine:    savebounds (x_coordinate, y_coordinate)
  |
 /*----------------------------------------------------------------------------*
  | Routine:    savebounds (x_coordinate, y_coordinate)
  |
@@ -473,16 +569,10 @@ savebounds(x, y)
 float x;
 float y;
 {
 float x;
 float y;
 {
-    if (x < leftpoint) {
-       leftpoint = x;
-    } else if (x > rightpoint) {
-       rightpoint = x;
-    }
-    if (y < toppoint) {
-       toppoint = y;
-    } else if (y > bottompoint) {
-       bottompoint = y;
-    }
+    if (x < leftpoint) leftpoint = x;
+    if (x > rightpoint) rightpoint = x;
+    if (y < toppoint) toppoint = y;
+    if (y > bottompoint) bottompoint = y;
 }
 
 
 }
 
 
@@ -490,14 +580,160 @@ float y;
  | Routine:    interpret (character_string)
  |
  | Results:    commands are taken from the input string and performed.
  | Routine:    interpret (character_string)
  |
  | Results:    commands are taken from the input string and performed.
- |             the commands are separated by the endofline or a semicolon.
+ |             Commands are separated by the endofline, and are of the
+ |             format:
+ |                     string1 string2
+ |
+ |             where string1 is the command and string2 is the argument.
  |
  | Side Efct:  font and size strings, plus the gremlin file name and the
  |             width and height variables are set by this routine.
  *----------------------------------------------------------------------------*/
 
 interpret (line)
  |
  | Side Efct:  font and size strings, plus the gremlin file name and the
  |             width and height variables are set by this routine.
  *----------------------------------------------------------------------------*/
 
 interpret (line)
-register char *line;
+char *line;
+{
+    char str1[MAXINLINE];
+    char str2[MAXINLINE];
+    register char *chr;
+    register 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 %d", linenum);
+           break;
+
+       case 'r':       /* roman */
+           if(str2[0] < '0') goto nofont;
+           tfont[0] = malloc(strlen(str2) + 1);
+           strcpy(tfont[0], str2);
+           break;
+
+       case 'i':       /* italics */
+           if(str2[0] < '0') goto nofont;
+           tfont[1] = malloc(strlen(str2) + 1);
+           strcpy(tfont[1], str2);
+           break;
+
+       case 'b':       /* bold */
+           if(str2[0] < '0') goto nofont;
+           tfont[2] = malloc(strlen(str2) + 1);
+           strcpy(tfont[2], str2);
+           break;
+
+       case 's':       /* special */
+           if (str1[1] == 'c') goto scalecommand;      /* or scale */
+
+           if(str2[0] < '0') {
+       nofont: error("no fontname specified in line %d", linenum);
+               break;
+           }
+           if (str1[1] == 't') goto stipplecommand;    /* or stipple */
+
+           tfont[3] = malloc(strlen(str2) + 1);
+           strcpy(tfont[3], str2);
+           break;
+
+       case 'l':       /* l */
+           if ((str1[1] < '1') || (str1[1] > '8'))
+               goto stipplecommand;
+
+           /* else set stipple index */
+           i = atoi(str2);
+           if (i >= 0 && i < 256)
+               stipple_index[str1[1] - '1'] = i;
+           else
+               error("bad stipple index value at line %d", linenum);
+           break;
+
+       stipplecommand: /* stipple */
+           stipple = malloc(strlen(str2) + 1);
+           strcpy(stipple, str2);
+           break;
+
+       case 'o':       /* oldstipplemap */
+           oldstipmap = TRUE;
+           break;
+
+       case 't':       /* thick */
+           thick[2] = atoi(str2);
+           break;
+
+       case 'm':       /* medium */
+           thick[5] = atoi(str2);
+           break;
+
+       case 'n':       /* narrow */
+           thick[0] = thick[1] = thick[3] = thick[4] = atoi(str2);
+           break;
+
+       case 'x':       /* x */
+       scalecommand:   /* scale */
+           par = atof(str2);
+           if (par > 0.0)
+               xscale *= par;
+           else
+               error("illegal scale value on line %d", 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, %s, on line %d", str1, linenum);
+           exit(8);
+           break;
+    };
+}
+
+
+/*
+ * return TRUE if picture contains a polygon
+ * otherwise FALSE
+ */
+has_polygon(elist)
+register ELT *elist;
 {
 {
-    sscanf(line, "%s", gremlinfile);
+    while (!DBNullelt(elist)) {
+       if (elist->type == POLYGON)
+           return(1);
+       elist = DBNextElt(elist);
+    }
+
+    return(0);
 }
 }