1*27071Sslatteng /*	main.c	1.24	(Berkeley)	86/04/14
214057Sslatteng  *
314057Sslatteng  *	This file contains the main and file system dependent routines
414057Sslatteng  * for processing gremlin files into troff input.  The program watches
514057Sslatteng  * input go by to standard output, only interpretting things between .GS
615367Sslatteng  * and .GE lines.  Default values (font, size, scale, thickness) may be
715367Sslatteng  * overridden with a "default" command and are further overridden by
815367Sslatteng  * commands in the input.  A description of the command-line options are
915367Sslatteng  * listed below.  A space is NOT required for the operand of an option.
1014057Sslatteng  *
1114057Sslatteng  *	command options are:
1214057Sslatteng  *
1315367Sslatteng  *	-L dir	set the library directory to dir.  If a file is not found
1415367Sslatteng  *		in the current directory, it is looked for in dir (default
1515367Sslatteng  *		is /usr/lib/gremlib).
1614057Sslatteng  *
1714817Sslatteng  *	-T dev	Prepare output for "dev" printer.  Default is for the varian
1815367Sslatteng  *	-P dev	and versatec printers.  Devices acceptable are:  ver, var, ip.
1914057Sslatteng  *
2015367Sslatteng  *		Inside the GS and GE, commands are accepted to reconfigure
2115367Sslatteng  *	    the picture.  At most one command may reside on each line, and
2215367Sslatteng  *	    each command is followed by a parameter separated by white space.
2315367Sslatteng  *	    The commands are as follows, and may be abbreviated down to one
2416546Sslatteng  *	    character (with exception of "scale" and "stipple" down to "sc"
2516546Sslatteng  *	    and "st") and may be upper or lower case.
2615031Sslatteng  *
2715367Sslatteng  *			      default  -  make all settings in the current
2815367Sslatteng  *					  .GS/.GE the global defaults.
2915367Sslatteng  *					  Height, width and file are NOT saved.
3015031Sslatteng  *			   1, 2, 3, 4  -  set size 1, 2, 3, or 4 (followed
3115367Sslatteng  *					  by an integer point size).
3215031Sslatteng  *	roman, italics, bold, special  -  set gremlin's fonts to any other
3315031Sslatteng  *					  troff font (one or two characters)
3416546Sslatteng  *			   stipple, l  -  use a stipple font for polygons.  Arg
3516546Sslatteng  *					  is troff font name.  No Default.  Can
3616546Sslatteng  *					  use only one stipple font per picture.
3717240Sralph  *					  (see below for stipple font index)
3815031Sslatteng  *			     scale, x  -  scale is IN ADDITION to the global
3915367Sslatteng  *					  scale factor from the default.
4015367Sslatteng  *			   pointscale  -  turn on scaling point sizes to
4115367Sslatteng  *					  match "scale" commands.  (optional
4215367Sslatteng  *					  operand "off" to turn it off)
4315031Sslatteng  *		narrow, medium, thick  -  set pixel widths of lines.
4415031Sslatteng  *				 file  -  set the file name to read the
4515367Sslatteng  *					  gremlin picture from.  If the file
4615367Sslatteng  *					  isn't in the current directory, the
4715367Sslatteng  *					  gremlin library is tried.
4815031Sslatteng  *			width, height  -  these two commands override any
4915031Sslatteng  *					  scaling factor that is in effect,
5015031Sslatteng  *					  and forces the picture to fit into
5115031Sslatteng  *					  either the height or width specified,
5215031Sslatteng  *					  whichever makes the picture smaller.
5315031Sslatteng  *					  The operand for these two commands is
5415031Sslatteng  *					  a floating-point number in units of
5515031Sslatteng  *					  inches
56*27071Sslatteng  *		        oldstipplemap  -  use the old-style stipple mapping.
57*27071Sslatteng  *					  THE FOLLOWING COMMANDS ARE IGNORED
58*27071Sslatteng  *					  UNLESS OLDSTIPPLEMAP IS SPECIFIED.
5917240Sralph  *     l1, l2, l3, l4, l5, l6, l7, l8  -  set association between stipples
6017240Sralph  *					  (1 - 8) and the stipple font file
6117240Sralph  *					  index.  Valid cifplot indices are
6217240Sralph  *					  1 - 32 (although 24 is not defined)
6317240Sralph  *					  and valid unigrafix indices are
6417240Sralph  *					  1 - 64.  Nonetheless, any number
6517240Sralph  *					  between 0 and 255 is accepted since
6617240Sralph  *					  new stipple fonts may be added.
6717240Sralph  *					  An integer operand is required.
6815031Sslatteng  *
6915031Sslatteng  *	Troff number registers used:  g1 through g9.  g1 is the width of the
7015185Sslatteng  *	picture, and g2 is the height.  g3, and g4, save information, g8
7115185Sslatteng  *	and g9 are used for text processing and g5-g7 are reserved.
7214057Sslatteng  */
7314057Sslatteng 
7414057Sslatteng 
7514585Sslatteng #include <ctype.h>
7614057Sslatteng #include "gprint.h"
7714057Sslatteng #include "dev.h"
7814057Sslatteng 
7915031Sslatteng extern char *malloc();
8014057Sslatteng extern char *rindex();
8114057Sslatteng 
8214057Sslatteng /* database imports */
8314057Sslatteng 
8414057Sslatteng extern HGPrintElt();
8514057Sslatteng extern ELT *DBInit(), *DBRead();
8614057Sslatteng extern POINT *PTInit(), *PTMakePoint();
8714057Sslatteng 
8814057Sslatteng 
8923936Sslatteng #ifndef GREMLIB
9014062Sslatteng #define GREMLIB		"/usr/local/gremlib/"
9117240Sralph #endif
9217240Sralph 
9317595Sopcode #define SUN_SCALEFACTOR 0.70
9417595Sopcode 
9515873Sslatteng #ifndef DEVDIR
9615185Sslatteng #define DEVDIR		"/usr/lib/font"
9715873Sslatteng #endif
9815185Sslatteng #define DEFAULTDEV	"va"
9917595Sopcode #define DEFSTIPPLE	"cf"
10014057Sslatteng 
10114057Sslatteng #define MAXINLINE	100		/* input line length */
10214057Sslatteng #define DEFTHICK	3		/* default thicknes */
10314057Sslatteng #define DEFSTYLE	SOLID		/* default line style */
10414057Sslatteng 
10517595Sopcode #ifdef oldversion
10614057Sslatteng #define SCREENtoINCH	0.02		/* scaling factor, screen to inches */
10717595Sopcode #endif
10817595Sopcode 
10917595Sopcode double SCREENtoINCH;			/* scaling factor, screen to inches */
11017595Sopcode 
11115367Sslatteng #define BIG	999999999999.0		/* unweildly large floating number */
11214057Sslatteng 
11314057Sslatteng 
114*27071Sslatteng static char sccsid[] = "@(#) (Berkeley) 04/14/86";
11514057Sslatteng 
11614057Sslatteng char	*printer = DEFAULTDEV;	/* device to look up resolution of */
11715367Sslatteng char	*gremlib = GREMLIB;	/* place to find files after current dir. */
11814057Sslatteng double	res;			/* that printer's resolution goes here */
11914057Sslatteng 
12014057Sslatteng int	linethickness;		/* brush styles */
12114057Sslatteng int	linmod;
12214057Sslatteng int	lastx;			/* point registers for printing elements */
12314057Sslatteng int	lasty;
12414057Sslatteng int	lastyline;		/* a line's vertical position is NOT the same */
12514057Sslatteng 				/* after that line is over, so for a line of */
12614057Sslatteng 				/* drawing commands, vertical spacing is kept */
12714057Sslatteng 				/* in lastyline */
12814057Sslatteng 
12915367Sslatteng 			/* these are the default fonts, sizes, line styles, */
13015367Sslatteng 			/*   and thicknesses.  These can be modified from a */
13115367Sslatteng 			/*   "default" command and are reset each time the  */
13215367Sslatteng 			/*   start of a picture (.GS) is found.		    */
13314057Sslatteng 
13415367Sslatteng char *	deffont[] = {  "R", "I", "B", "S"  };
13515367Sslatteng int	defsize[] = {  10, 16, 24, 36  };
13615367Sslatteng int	defthick[STYLES] = {  1, 1, 5, 1, 1, 3  };
13717240Sralph int	defstipple_index[NSTIPPLES] = { 1, 3, 12, 14, 16, 19, 21, 23 };
13815367Sslatteng int	style[STYLES] = {  DOTTED, DOTDASHED, SOLID, DASHED, SOLID, SOLID  };
13915367Sslatteng double	scale = 1.0;		/* no scaling, default */
14015367Sslatteng int	defpoint = 0;		/* flag for pointsize scaling */
14116546Sslatteng char *  defstipple = (char *) 0;
14214057Sslatteng 
14314057Sslatteng int	thick[STYLES];	/* thicknesses set by defaults, then by commands */
14415367Sslatteng char	*tfont[FONTS];	/* fonts originally set to deffont values, then */
14515367Sslatteng int 	tsize[SIZES];	/*    optionally changed by commands inside grn */
14617240Sralph int	stipple_index[NSTIPPLES];	/* stipple font file indices */
14716546Sslatteng char *  stipple;
14814057Sslatteng 
14914585Sslatteng double	xscale;		/* scaling factor from individual pictures */
15014057Sslatteng double	troffscale;	/* scaling factor at output time */
15114057Sslatteng double	width;		/* user-request maximum width for picture (in inches) */
15214057Sslatteng double	height;		/* user-request height */
15315367Sslatteng int	pointscale;	/* flag for pointsize scaling */
15415367Sslatteng int	setdefault;	/* flag for a .GS/.GE to remember all settings */
15514057Sslatteng 
15614057Sslatteng double	toppoint;		/* remember the picture */
15714057Sslatteng double	bottompoint;		/* bounds in these variables */
15814057Sslatteng double	leftpoint;
15914057Sslatteng double	rightpoint;
16014057Sslatteng 
16114057Sslatteng int	ytop;			/* these are integer versions of the above */
16214057Sslatteng int	ybottom;		/* so not to convert each time they're used */
16314057Sslatteng int	xleft;
16414057Sslatteng int	xright;
16514057Sslatteng 
16614057Sslatteng int	linenum = 0;			/* line number of input file */
16714057Sslatteng char	inputline[MAXINLINE];		/* spot to filter through the file */
16814057Sslatteng char	*c1 = inputline;		/* c1, c2, and c3 will be used to */
16914057Sslatteng char	*c2 = inputline + 1;		/* hunt for lines that begin with */
17014057Sslatteng char	*c3 = inputline + 2;		/* ".GS" by looking individually */
17114057Sslatteng char	GScommand[MAXINLINE];		/* put user's ".GS" command line here */
17215873Sslatteng char	gremlinfile[MAXINLINE];		/* filename to use for a picture */
17317240Sralph int	SUNFILE = FALSE;		/* TRUE if SUN gremlin file */
174*27071Sslatteng int	oldstipmap = FALSE;		/* TRUE if old-style stipple mapping */
17514057Sslatteng 
17614817Sslatteng char *doinput();
17714057Sslatteng 
17814817Sslatteng 
17914057Sslatteng /*----------------------------------------------------------------------------*
18014057Sslatteng  | Routine:	main (argument_count, argument_pointer)
18114057Sslatteng  |
18214057Sslatteng  | Results:	parses the command line, accumulating input file names, then
18314057Sslatteng  |		reads the inputs, passing it directly to output until a ".GS"
18414057Sslatteng  |		line is read.  Main then passes control to "conv" to do the
18514057Sslatteng  |		gremlin file conversions.
18614057Sslatteng  *----------------------------------------------------------------------------*/
18714057Sslatteng 
main(argc,argv)18814057Sslatteng main(argc, argv)
18914057Sslatteng int argc;
19014057Sslatteng char **argv;
19114057Sslatteng {
19223741Sslatteng 	register FILE *fp;
19314057Sslatteng 	register int k;
19414057Sslatteng 	register char c;
19515367Sslatteng 	register gfil = 0;
19615367Sslatteng 	char *file[50];
19714057Sslatteng 
19814817Sslatteng 	char *operand();
19923741Sslatteng 	char *getenv();
20014057Sslatteng 
20114057Sslatteng 
20223741Sslatteng 	if (fp = (FILE *) getenv("PRINTER")) printer = (char *) fp;
20323741Sslatteng 	if (fp = (FILE *) getenv("TYPESETTER")) printer = (char *) fp;
20414817Sslatteng 	while (--argc) {
20514817Sslatteng 	    if (**++argv != '-')
20614817Sslatteng 		file[gfil++] = *argv;
20714817Sslatteng 	    else
20814817Sslatteng 	      switch (c = (*argv)[1]) {
20914817Sslatteng 
21023741Sslatteng 		case 0:
21123741Sslatteng 			file[gfil++] = NULL;
21223741Sslatteng 			break;
21323741Sslatteng 
21415185Sslatteng 		case 'P':
21514057Sslatteng 		case 'T':	/* final output typesetter name */
21614817Sslatteng 			printer = operand(&argc, &argv);
21714057Sslatteng 			break;
21815367Sslatteng 
21915367Sslatteng 		case 'L':	/* set library directory */
22015367Sslatteng 			gremlib = operand(&argc, &argv);
22114057Sslatteng 			break;
22215367Sslatteng 
22314057Sslatteng 		default:
22415367Sslatteng 			error("unknown switch: %c", c);
22514057Sslatteng 	    }
22614057Sslatteng 	}
22714057Sslatteng 				/* set the resolution for an output device */
22814057Sslatteng 	getres(printer);	/* named in "printer" */
22914057Sslatteng 
23014057Sslatteng 	if (gfil == 0) {	/* no filename, use standard input */
23114057Sslatteng 		file[0] = NULL;
23214057Sslatteng 		gfil++;
23314057Sslatteng 	}
23414817Sslatteng 
23514057Sslatteng 	for (k=0; k<gfil; k++) {
23614057Sslatteng 		if (file[k] != NULL) {
23714057Sslatteng 			if ((fp = fopen(file[k], "r")) == NULL) {
23815367Sslatteng 			    error("can't open %s", file[k]);
23916188Sslatteng 			    exit(1);
24014057Sslatteng 			}
24114057Sslatteng 		} else {
24214057Sslatteng 			fp = stdin;
24314057Sslatteng 		}
24414057Sslatteng 
24514057Sslatteng 		while (doinput(fp) != NULL) {
24614057Sslatteng 		    if (*c1 == '.' && *c2 == 'G' && *c3 == 'S') {
24714057Sslatteng 			conv(fp, linenum);
24814057Sslatteng 		    } else {
24914057Sslatteng 			fputs(inputline, stdout);
25014057Sslatteng 		    }
25114057Sslatteng 		}
25214057Sslatteng 	}
25314057Sslatteng }
25414057Sslatteng 
25514057Sslatteng 
25614057Sslatteng /*----------------------------------------------------------------------------*
25715367Sslatteng  | Routine:	error (control_string, args, . . . )
25815367Sslatteng  |
25915367Sslatteng  | Results:	prints ("grn: ", the control_string + args, "\n") to stderr
26015367Sslatteng  *----------------------------------------------------------------------------*/
26115367Sslatteng 
26215367Sslatteng /* VARARGS1 */
error(s,a1,a2,a3,a4)26315367Sslatteng error(s, a1, a2, a3, a4)
26415367Sslatteng char *	s;
26515367Sslatteng {
26615367Sslatteng 	fprintf(stderr, "grn: ");
26715367Sslatteng 	fprintf(stderr, s, a1, a2, a3, a4);
26815367Sslatteng 	fprintf(stderr, "\n");
26915367Sslatteng }
27015367Sslatteng 
27115367Sslatteng 
27215367Sslatteng /*----------------------------------------------------------------------------*
27314817Sslatteng  | Routine:	char  * operand (& argc,  & argv)
27414817Sslatteng  |
27514817Sslatteng  | Results:	returns address of the operand given with a command-line
27614817Sslatteng  |		option.  It uses either "-Xoperand" or "-X operand", whichever
27714817Sslatteng  |		is present.  The program is terminated if no option is present.
27814817Sslatteng  |
27914817Sslatteng  | Side Efct:	argc and argv are updated as necessary.
28014817Sslatteng  *----------------------------------------------------------------------------*/
28114817Sslatteng 
operand(argcp,argvp)28214817Sslatteng char *operand(argcp, argvp)
28314817Sslatteng int * argcp;
28414817Sslatteng char ***argvp;
28514817Sslatteng {
28614817Sslatteng 	if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
28714817Sslatteng 	if ((--*argcp) <= 0) {			/* no operand */
28815367Sslatteng 	    error("command-line option operand missing.");
28916188Sslatteng 	    exit(8);
29014817Sslatteng 	}
29114817Sslatteng 	return(*(++(*argvp)));			/* operand is next word */
29214817Sslatteng }
29314817Sslatteng 
29414817Sslatteng 
29514817Sslatteng /*----------------------------------------------------------------------------*
29614057Sslatteng  | Routine:	getres (device_name)
29714057Sslatteng  |
29814057Sslatteng  | Results:	sets "res" to the resolution of the output device specified
29914057Sslatteng  |		by the string dev.
30014057Sslatteng  *----------------------------------------------------------------------------*/
30114057Sslatteng 
getres(name)30214057Sslatteng getres(name)
30314057Sslatteng char *name;
30414057Sslatteng {
30514057Sslatteng 	int fin;
30614057Sslatteng 	struct dev device;
30714057Sslatteng 	char temp[60];
30814057Sslatteng 
30915185Sslatteng 	sprintf(temp, "%s/dev%s/DESC.out", DEVDIR, name);
31014057Sslatteng 	if ((fin = open(temp, 0)) < 0) {
31115367Sslatteng 	    error("can't open tables for %s", temp);
31214057Sslatteng 	    exit(1);
31314057Sslatteng 	}
31414057Sslatteng 	read(fin, &device, sizeof(struct dev));
31514057Sslatteng 	res = (double) device.res;
31614057Sslatteng 	close(fin);
31714057Sslatteng }
31814057Sslatteng 
31914057Sslatteng 
32014057Sslatteng /*----------------------------------------------------------------------------*
32114057Sslatteng  | Routine:	char  * doinput (file_pointer)
32214057Sslatteng  |
32314057Sslatteng  | Results:	a line of input is read into "inputline".
32414057Sslatteng  |
32514057Sslatteng  | Side Efct:	"linenum" is incremented.
32614057Sslatteng  |
32714057Sslatteng  | Bugs:	lines longer than MAXINLINE are NOT checked, except for
32814057Sslatteng  |		updating "linenum"
32914057Sslatteng  *----------------------------------------------------------------------------*/
33014057Sslatteng 
doinput(fp)33114057Sslatteng char *doinput(fp)
33214057Sslatteng FILE *fp;
33314057Sslatteng {
33415367Sslatteng     char *k;
33514057Sslatteng 
33614057Sslatteng 
33714057Sslatteng     if ((k = fgets(inputline, MAXINLINE, fp)) == NULL)
33814057Sslatteng 	return k;
33914057Sslatteng     if (index (inputline, '\n'))	/* ++ only if it's a complete line */
34014057Sslatteng 	linenum++;
34114057Sslatteng     return (char*) !NULL;
34214057Sslatteng }
34314057Sslatteng 
34414057Sslatteng 
34514057Sslatteng /*----------------------------------------------------------------------------*
34614057Sslatteng  | Routine:	initpic ( )
34714057Sslatteng  |
34814057Sslatteng  | Results:	sets all parameters to the normal defaults, possibly overridden
34915367Sslatteng  |		by a setdefault command.  Initilaize the picture variables,
35014057Sslatteng  |		and output the startup commands to troff to begin the picture.
35114057Sslatteng  *----------------------------------------------------------------------------*/
35214057Sslatteng 
initpic()35314057Sslatteng initpic()
35414057Sslatteng {
35514057Sslatteng     register int i;
35614057Sslatteng 
35714057Sslatteng     for (i = 0; i < STYLES; i++) {	/* line thickness defaults */
35814057Sslatteng 	thick[i] = defthick[i];
35914057Sslatteng     }
36014057Sslatteng     for (i = 0; i < FONTS; i++) {	/* font name defaults */
36115367Sslatteng 	tfont[i] = deffont[i];
36214057Sslatteng     }
36314057Sslatteng     for (i = 0; i < SIZES; i++) {	/* font size defaults */
36415367Sslatteng 	tsize[i] = defsize[i];
36514057Sslatteng     }
36617240Sralph     for (i = 0; i < NSTIPPLES; i++) {	/* stipple font file default indices */
36717240Sralph 	stipple_index[i] = defstipple_index[i];
36817240Sralph     }
36916546Sslatteng     stipple = defstipple;
37014057Sslatteng 
37114057Sslatteng     gremlinfile[0] = 0;		/* filename is "null" */
37215367Sslatteng     setdefault = 0;		/* this is not the default settings (yet) */
37314057Sslatteng 
37414057Sslatteng     toppoint = BIG;		/* set the picture bounds out */
37524157Sslatteng     bottompoint = -BIG;		/* of range so they'll be set */
37614057Sslatteng     leftpoint = BIG;		/* by "savebounds" on input */
37724157Sslatteng     rightpoint = -BIG;
37814057Sslatteng 
37915367Sslatteng     pointscale = defpoint;	/* Flag for scaling point sizes default. */
38014585Sslatteng     xscale = scale;		/* default scale of individual pictures */
38114057Sslatteng     width = 0.0;		/* size specifications input by user */
38214057Sslatteng     height = 0.0;
38314057Sslatteng 
38414057Sslatteng     linethickness = DEFTHICK;	/* brush styles */
38514057Sslatteng     linmod = DEFSTYLE;
38614057Sslatteng }
38714057Sslatteng 
38814057Sslatteng 
38914057Sslatteng /*----------------------------------------------------------------------------*
39014057Sslatteng  | Routine:	conv (file_pointer, starting_line)
39114057Sslatteng  |
39214057Sslatteng  | Results:	at this point, we just passed a ".GS" line in the input file.
39314057Sslatteng  |		conv reads the input and calls "interpret" to process commands,
39414057Sslatteng  |		gathering up information until a ".GE" line is found.  It then
39514057Sslatteng  |		calls "HGPrint" to do the translation of the gremlin file to
39614057Sslatteng  |		troff commands.
39714057Sslatteng  *----------------------------------------------------------------------------*/
39814057Sslatteng 
conv(fp,baseline)39914057Sslatteng conv(fp, baseline)
40014057Sslatteng register FILE *fp;
40114057Sslatteng int baseline;
40214057Sslatteng {
40316188Sslatteng 	register FILE *gfp = NULL;	/* input file pointer */
40416188Sslatteng 	register int done = 0;		/* flag to remember if finished */
40516188Sslatteng 	register ELT *e;	/* current element pointer */
40616188Sslatteng 	ELT *PICTURE;		/* whole picture data base pointer */
40716188Sslatteng 	double temp;		/* temporary calculating area */
40816188Sslatteng 	POINT ptr;	/* coordinates of a point to pass to "mov" routine */
40916188Sslatteng 	int flyback;	/* flag "want to end up at the top of the picture?" */
41014057Sslatteng 
41114057Sslatteng 
41214585Sslatteng 	initpic();			/* set defaults, ranges, etc. */
41314585Sslatteng 	strcpy (GScommand, inputline);	/* save ".GS" line for later */
41414057Sslatteng 	do {
41514057Sslatteng 	    done = (doinput(fp) == NULL);		     /* test for EOF */
41616188Sslatteng 	    flyback = *c3 == 'F';			   /* and .GE or .GF */
41716188Sslatteng 	    done |= (*c1 == '.' && *c2 == 'G' && (*c3 == 'E' || flyback));
41814057Sslatteng 
41914057Sslatteng 	    if (done) {
42015367Sslatteng 		if (setdefault) savestate();
42115367Sslatteng 
42214057Sslatteng 		if (!gremlinfile[0]) {
42316188Sslatteng 		    if(!setdefault)
42416188Sslatteng 			error("at line %d: no picture filename.\n", baseline);
42514057Sslatteng 		    return;
42614057Sslatteng 		}
42714057Sslatteng 		if ((gfp = fopen(gremlinfile, "r")) == NULL) {
42815873Sslatteng 		    char name[MAXINLINE]; /* if the file isn't in the current */
42914061Sslatteng 					/* directory, try the gremlin library */
43015367Sslatteng 		    sprintf(name, "%s%s", gremlib, gremlinfile);
43114061Sslatteng 		    if ((gfp = fopen(name, "r")) == NULL) {
43215367Sslatteng 			error("can't open %s", gremlinfile);
43314061Sslatteng 			return;
43414061Sslatteng 		    }
43514057Sslatteng 		}
43614057Sslatteng 		PICTURE = DBRead(gfp);			/* read picture file */
43714057Sslatteng 		fclose(gfp);
43814057Sslatteng 		if (DBNullelt(PICTURE))
43915031Sslatteng 		    return;		/* if a request is made to make the */
44014057Sslatteng 					/* picture fit into a specific area, */
44114057Sslatteng 					/* set the scale to do that. */
44217595Sopcode 
44317595Sopcode 		SCREENtoINCH = (SUNFILE) ? 0.014 : 0.02;
44417595Sopcode 
44517595Sopcode 		if (stipple == (char *) NULL)	/* if user forgot stipple */
44617595Sopcode 		    if (has_polygon(PICTURE))	/* and picture has a polygon */
44717595Sopcode 			stipple = DEFSTIPPLE;	/* then set the default */
44817595Sopcode 
44915031Sslatteng 		if ((temp = bottompoint - toppoint) < 0.1) temp = 0.1;
45015625Sslatteng 		temp = (height != 0.0) ? height / (temp * SCREENtoINCH)  : BIG;
45115031Sslatteng 		if ((troffscale = rightpoint - leftpoint) < 0.1) troffscale=0.1;
45215625Sslatteng 		troffscale = (width != 0.0) ?
45315625Sslatteng 				width / (troffscale * SCREENtoINCH)  : BIG;
45414057Sslatteng 		if (temp == BIG && troffscale == BIG) {
45514585Sslatteng 		    troffscale = xscale;
45614057Sslatteng 		} else {
45714057Sslatteng 		    if (temp < troffscale) troffscale = temp;
45815367Sslatteng 		}				/* here, troffscale is the */
45915367Sslatteng 						/* picture's scaling factor */
46015367Sslatteng 		if (pointscale) {
46115367Sslatteng 		    register int i;		/* do pointscaling here, when */
46215367Sslatteng 					     /* scale is known, before output */
46317595Sopcode 
46415367Sslatteng 		    for (i = 0; i < SIZES; i++)
46515367Sslatteng 			tsize[i] = (int) (troffscale * (double) tsize[i] + 0.5);
46617595Sopcode 
46714057Sslatteng 		}
46815367Sslatteng 						   /* change to device units */
46915367Sslatteng 		troffscale *= SCREENtoINCH * res;	/* from screen units */
47014057Sslatteng 
47114057Sslatteng 		ytop = toppoint * troffscale;		/* calculate integer */
47214057Sslatteng 		ybottom = bottompoint * troffscale;	/* versions of the */
47314057Sslatteng 		xleft = leftpoint * troffscale;		/* picture limits */
47414057Sslatteng 		xright = rightpoint * troffscale;
47514057Sslatteng 					/* save stuff in number registers, */
47615031Sslatteng 					/*   register g1 = picture width and */
47715031Sslatteng 					/*   register g2 = picture height, */
47814057Sslatteng 					/*   set vertical spacing, no fill, */
47914057Sslatteng 					/*   and break (to make sure picture */
48014057Sslatteng 					/*   starts on left), and put out the */
48114057Sslatteng 					/*   user's ".GS" line. */
48216188Sslatteng 		printf(
48316405Sslatteng ".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",
48416188Sslatteng 			xright-xleft, ybottom-ytop, GScommand);
48514057Sslatteng 
48616546Sslatteng 		if (stipple) {		/* stipple requested for this picture */
48716546Sslatteng 		    printf(".st %s\n", stipple);
48816546Sslatteng 		}
48916546Sslatteng 
49014057Sslatteng 		lastx = xleft;		/* note where we are, (upper left */
49114057Sslatteng 		lastyline = lasty = ytop;	/* corner of the picture) */
49214057Sslatteng 
49314057Sslatteng 		e = PICTURE;
49416546Sslatteng 		while (!DBNullelt(e)) {	/* traverse picture;  print elements */
49516546Sslatteng 		    HGPrintElt(e, baseline);
49614057Sslatteng 		    e = DBNextElt(e);
49714057Sslatteng 		}
49816188Sslatteng 				/* decide where to end picture */
49916188Sslatteng 		if (flyback) {		/* end piture at upper left */
50016188Sslatteng 		    ptr.x = leftpoint;
50116188Sslatteng 		    ptr.y = toppoint;
50216188Sslatteng 		} else {		/* end picture at lower left */
50316188Sslatteng 		    ptr.x = leftpoint;
50416188Sslatteng 		    ptr.y = bottompoint;
50516188Sslatteng 		}
50614061Sslatteng 		tmove(&ptr);		/* restore default line parameters, */
50716188Sslatteng 					/* restore everything to the way */
50816188Sslatteng 					/* it was before the .GS, then put */
50916188Sslatteng 					/* out the ".GE" line from user */
51016600Sslatteng 		printf("\\D't %du'\\D's %du'\n", DEFTHICK, DEFSTYLE);
51116600Sslatteng 		if (flyback) {		/* make sure we end up at top of */
51216600Sslatteng 		    printf(".sp -1\n");		/* picture if "flying back" */
51316600Sslatteng 		}
51416546Sslatteng 		if (stipple) {		/* restore stipple to previous */
51516546Sslatteng 		    printf(".st\n");
51616546Sslatteng 		}
51715224Sslatteng 		printf(".br\n.ft \\n(g3\n.ps \\n(g4\n%s", inputline);
51814057Sslatteng 	    } else {
51914057Sslatteng 		interpret(inputline);	/* take commands from the input file */
52014057Sslatteng 	    }
52114057Sslatteng 	} while (!done);
52214057Sslatteng }
52314057Sslatteng 
52414057Sslatteng 
52514057Sslatteng /*----------------------------------------------------------------------------*
52615367Sslatteng  | Routine:	savestate  ( )
52715367Sslatteng  |
52815367Sslatteng  | Results:	all the current  scaling / font size / font name / thickness /
52915367Sslatteng  |		pointscale  settings are saved to be the defaults.  Scaled
53015367Sslatteng  |		point sizes are NOT saved.  The scaling is done each time a
53115367Sslatteng  |		new picture is started.
53215367Sslatteng  |
53316546Sslatteng  | Side Efct:	scale, and def* are modified.
53415367Sslatteng  *----------------------------------------------------------------------------*/
53515367Sslatteng 
savestate()53615367Sslatteng savestate()
53715367Sslatteng {
53815367Sslatteng     register int i;
53915367Sslatteng 
54015367Sslatteng     for (i = 0; i < STYLES; i++) {	/* line thickness defaults */
54115367Sslatteng 	defthick[i] = thick[i];
54215367Sslatteng     }
54315367Sslatteng     for (i = 0; i < FONTS; i++) {	/* font name defaults */
54415367Sslatteng 	deffont[i] = tfont[i];
54515367Sslatteng     }
54615367Sslatteng     for (i = 0; i < SIZES; i++) {	/* font size defaults */
54715367Sslatteng 	defsize[i] = tsize[i];
54815367Sslatteng     }
54917240Sralph     for (i = 0; i < NSTIPPLES; i++) {	/* stipple font file default indices */
55017240Sralph 	defstipple_index[i] = stipple_index[i];
55117240Sralph     }
55216546Sslatteng     defstipple = stipple;	/* if stipple has been set, it's remembered */
55315367Sslatteng 
55415367Sslatteng     scale *= xscale;		/* default scale of individual pictures */
55515367Sslatteng     defpoint = pointscale;	/* flag for scaling pointsizes from x factors */
55615367Sslatteng }
55715367Sslatteng 
55815367Sslatteng 
55915367Sslatteng /*----------------------------------------------------------------------------*
56014057Sslatteng  | Routine:	savebounds (x_coordinate, y_coordinate)
56114057Sslatteng  |
56214057Sslatteng  | Results:	keeps track of the maximum and minimum extent of a picture
56314057Sslatteng  |		in the global variables:  left-, right-, top- and bottompoint.
56414057Sslatteng  |		"savebounds" assumes that the points have been oriented to
56514057Sslatteng  |		the correct direction.  No scaling has taken place, though.
56614057Sslatteng  *----------------------------------------------------------------------------*/
56714057Sslatteng 
savebounds(x,y)56814057Sslatteng savebounds(x, y)
56914057Sslatteng float x;
57014057Sslatteng float y;
57114057Sslatteng {
57215054Sslatteng     if (x < leftpoint) leftpoint = x;
57315054Sslatteng     if (x > rightpoint) rightpoint = x;
57415054Sslatteng     if (y < toppoint) toppoint = y;
57515054Sslatteng     if (y > bottompoint) bottompoint = y;
57614057Sslatteng }
57714057Sslatteng 
57814057Sslatteng 
57914057Sslatteng /*----------------------------------------------------------------------------*
58014057Sslatteng  | Routine:	interpret (character_string)
58114057Sslatteng  |
58214057Sslatteng  | Results:	commands are taken from the input string and performed.
58314585Sslatteng  |		Commands are separated by the endofline, and are of the
58414585Sslatteng  |		format:
58514585Sslatteng  |			string1 string2
58614057Sslatteng  |
58714585Sslatteng  |		where string1 is the command and string2 is the argument.
58814585Sslatteng  |
58914057Sslatteng  | Side Efct:	font and size strings, plus the gremlin file name and the
59014057Sslatteng  |		width and height variables are set by this routine.
59114057Sslatteng  *----------------------------------------------------------------------------*/
59214057Sslatteng 
interpret(line)59314057Sslatteng interpret (line)
59414585Sslatteng char *line;
59514057Sslatteng {
59614585Sslatteng     char str1[MAXINLINE];
59714585Sslatteng     char str2[MAXINLINE];
59814585Sslatteng     register char *chr;
59915367Sslatteng     register int i;
60015367Sslatteng     double par;
60114585Sslatteng 
60215367Sslatteng     str2[0] = '\0';
60315031Sslatteng     sscanf(line, "%80s%80s", &str1[0], &str2[0]);
60414585Sslatteng     for (chr = &str1[0]; *chr; chr++)		/* convert command to */
60514586Sslatteng 	if(isupper(*chr)) *chr = tolower(*chr);		/* lower case */
60614585Sslatteng     switch (str1[0]) {
60714585Sslatteng 
60814585Sslatteng 	case '1':
60914585Sslatteng 	case '2':	/* font sizes */
61014585Sslatteng 	case '3':
61114585Sslatteng 	case '4':
61215367Sslatteng 	    i = atoi(str2);
61315367Sslatteng 	    if (i > 0 && i < 1000)
61415367Sslatteng 		tsize[str1[0] - '1'] = i;
61515367Sslatteng 	    else
61615367Sslatteng 		error("bad font size value at line %d", linenum);
61714585Sslatteng 	    break;
61814585Sslatteng 
61914585Sslatteng 	case 'r':	/* roman */
62015367Sslatteng 	    if(str2[0] < '0') goto nofont;
62115031Sslatteng 	    tfont[0] = malloc(strlen(str2) + 1);
62214585Sslatteng 	    strcpy(tfont[0], str2);
62314585Sslatteng 	    break;
62414585Sslatteng 
62514585Sslatteng 	case 'i':	/* italics */
62615367Sslatteng 	    if(str2[0] < '0') goto nofont;
62715031Sslatteng 	    tfont[1] = malloc(strlen(str2) + 1);
62814585Sslatteng 	    strcpy(tfont[1], str2);
62914585Sslatteng 	    break;
63014585Sslatteng 
63114585Sslatteng 	case 'b':	/* bold */
63215367Sslatteng 	    if(str2[0] < '0') goto nofont;
63315031Sslatteng 	    tfont[2] = malloc(strlen(str2) + 1);
63414585Sslatteng 	    strcpy(tfont[2], str2);
63514585Sslatteng 	    break;
63614585Sslatteng 
63714585Sslatteng 	case 's':	/* special */
63815367Sslatteng 	    if (str1[1] == 'c') goto scalecommand;	/* or scale */
63915367Sslatteng 
64015367Sslatteng 	    if(str2[0] < '0') {
64115367Sslatteng 	nofont:	error("no fontname specified in line %d", linenum);
64215367Sslatteng 		break;
64315367Sslatteng 	    }
64416546Sslatteng 	    if (str1[1] == 't') goto stipplecommand;	/* or stipple */
64516546Sslatteng 
64615031Sslatteng 	    tfont[3] = malloc(strlen(str2) + 1);
64714585Sslatteng 	    strcpy(tfont[3], str2);
64814585Sslatteng 	    break;
64914585Sslatteng 
65016546Sslatteng 	case 'l':	/* l */
65117240Sralph 	    if ((str1[1] < '1') || (str1[1] > '8'))
65217240Sralph 		goto stipplecommand;
65317240Sralph 
65417240Sralph 	    /* else set stipple index */
65517240Sralph 	    i = atoi(str2);
65617240Sralph 	    if (i >= 0 && i < 256)
65717240Sralph 		stipple_index[str1[1] - '1'] = i;
65817240Sralph 	    else
65917240Sralph 		error("bad stipple index value at line %d", linenum);
66017240Sralph 	    break;
66117240Sralph 
66216546Sslatteng 	stipplecommand:	/* stipple */
66316546Sslatteng 	    stipple = malloc(strlen(str2) + 1);
66416546Sslatteng 	    strcpy(stipple, str2);
66516546Sslatteng 	    break;
66616546Sslatteng 
667*27071Sslatteng 	case 'o':	/* oldstipplemap */
668*27071Sslatteng 	    oldstipmap = TRUE;
669*27071Sslatteng 	    break;
670*27071Sslatteng 
67114585Sslatteng 	case 't':	/* thick */
67214585Sslatteng 	    thick[2] = atoi(str2);
67314585Sslatteng 	    break;
67414585Sslatteng 
67514585Sslatteng 	case 'm':	/* medium */
67614585Sslatteng 	    thick[5] = atoi(str2);
67714585Sslatteng 	    break;
67814585Sslatteng 
67914585Sslatteng 	case 'n':	/* narrow */
68014585Sslatteng 	    thick[0] = thick[1] = thick[3] = thick[4] = atoi(str2);
68114585Sslatteng 	    break;
68214585Sslatteng 
68314585Sslatteng 	case 'x':	/* x */
68414585Sslatteng 	scalecommand:	/* scale */
68515367Sslatteng 	    par = atof(str2);
68615367Sslatteng 	    if (par > 0.0)
68715367Sslatteng 		xscale *= par;
68815367Sslatteng 	    else
68915367Sslatteng 		error("illegal scale value on line %d", linenum);
69014585Sslatteng 	    break;
69114585Sslatteng 
69214585Sslatteng 	case 'f':	/* file */
69314585Sslatteng 	    strcpy(gremlinfile, str2);
69414585Sslatteng 	    break;
69514585Sslatteng 
69614585Sslatteng 	case 'w':	/* width */
69714585Sslatteng 	    width = atof(str2);
69814585Sslatteng 	    if (width < 0.0) width = -width;
69914585Sslatteng 	    break;
70014585Sslatteng 
70114585Sslatteng 	case 'h':	/* height */
70214585Sslatteng 	    height = atof(str2);
70314585Sslatteng 	    if (height < 0.0) height = -height;
70414585Sslatteng 	    break;
70514585Sslatteng 
70615367Sslatteng 	case 'd':	/* defaults */
70715367Sslatteng 	    setdefault = 1;
70815367Sslatteng 	    break;
70915367Sslatteng 
71015367Sslatteng 	case 'p':	/* pointscale */
71115367Sslatteng 	    if (strcmp("off", str2))
71215367Sslatteng 		pointscale = 1;
71315367Sslatteng 	    else
71415367Sslatteng 		pointscale = 0;
71515367Sslatteng 	    break;
71615367Sslatteng 
71714585Sslatteng 	default:
71816188Sslatteng 	    error("unknown command, %s, on line %d", str1, linenum);
71916188Sslatteng 	    exit(8);
72014585Sslatteng 	    break;
72114585Sslatteng     };
72214057Sslatteng }
72317595Sopcode 
72417595Sopcode 
72517595Sopcode /*
72617595Sopcode  * return TRUE if picture contains a polygon
72717595Sopcode  * otherwise FALSE
72817595Sopcode  */
has_polygon(elist)72917595Sopcode has_polygon(elist)
73017595Sopcode register ELT *elist;
73117595Sopcode {
73217595Sopcode     while (!DBNullelt(elist)) {
73317595Sopcode 	if (elist->type == POLYGON)
73417595Sopcode 	    return(1);
73517595Sopcode 	elist = DBNextElt(elist);
73617595Sopcode     }
73717595Sopcode 
73817595Sopcode     return(0);
73917595Sopcode }
740