1*18122Sslatteng /* @(#)dterm.c	1.14	(Berkeley)	02/26/85"
214087Sslatteng  *
314087Sslatteng  *	Converts ditroff output to text on a terminal.  It is NOT meant to
414087Sslatteng  *	produce readable output, but is to show one how one's paper is (in
514087Sslatteng  *	general) formatted - what will go where on which page.
614087Sslatteng  *
714087Sslatteng  *	options:
814087Sslatteng  *
914087Sslatteng  *	  -hn	set horizontal resolution to n (in characters per inch;
1014087Sslatteng  *		default is 10.0).
1114087Sslatteng  *
1214087Sslatteng  *	  -vn	set vertical resolution (default is 6.0).
1314087Sslatteng  *
1414087Sslatteng  *	  -ln	set maximum output line-length to n (default is 79).
1514087Sslatteng  *
1614087Sslatteng  *	-olist	output page list - as in troff.
1714087Sslatteng  *
1814087Sslatteng  *	  -c	continue at end of page.  Default is to stop at the end
1914087Sslatteng  *		of each page, print "dterm:" and wait for a command.
2014087Sslatteng  *		Type ? to get a list of available commands.
2114087Sslatteng  *
2215279Sslatteng  *	  -m	print margins.  Default action is to cut printing area down
2315279Sslatteng  *		to only the part of the page with information on it.
2415279Sslatteng  *
2516847Sslatteng  *	  -a	make the output readable - i.e. print like a "troff -a" with
2616847Sslatteng  *		no character overlap, and one space 'tween words
2716847Sslatteng  *
2814822Sslatteng  *	  -L	put a form feed (^L) at the end of each page
2914645Sslatteng  *
3015279Sslatteng  *	  -w	sets h = 20, v = 12, l = 131, also sets -c, -m and -L to allow
3114822Sslatteng  *		for extra-wide printouts on the printer.
3214822Sslatteng  *
3314645Sslatteng  *	-fxxx	get special character definition file "xxx".  Default is
34*18122Sslatteng  *		FONTDIR/devter/specfile.
3514087Sslatteng  */
3614087Sslatteng 
3714087Sslatteng 
3814087Sslatteng #include	<stdio.h>
3914087Sslatteng #include	<ctype.h>
4014087Sslatteng #include	<math.h>
4114087Sslatteng 
4214087Sslatteng 
4314087Sslatteng #define	FATAL		1
4414816Sslatteng #define	PGWIDTH		266		/* WAY too big - for good measure */
4514816Sslatteng #define	PGHEIGHT	220
4614087Sslatteng #define LINELEN		78
47*18122Sslatteng #define SPECFILE	"devter/specfile"
48*18122Sslatteng #ifndef FONTDIR
49*18122Sslatteng #define FONTDIR		"/usr/lib/font"
50*18122Sslatteng #endif
5114087Sslatteng 
5214087Sslatteng #define hgoto(n)	hpos = n
5314087Sslatteng #define vgoto(n)	vpos = n
5414087Sslatteng #define hmot(n)		hpos += n
5514087Sslatteng #define vmot(n)		vpos += n
5614087Sslatteng 
5714087Sslatteng #define	sgn(n)		((n > 0) ? 1 : ((n < 0) ? -1 : 0))
5814087Sslatteng #define	abs(n)		((n) >= 0 ? (n) : -(n))
5914087Sslatteng #define	max(x,y)	((x) > (y) ? (x) : (y))
6014087Sslatteng #define	min(x,y)	((x) < (y) ? (x) : (y))
6114087Sslatteng #define sqr(x)		(long int)(x)*(x)
6214087Sslatteng 
6314087Sslatteng 
64*18122Sslatteng char	SccsId [] = "@(#)dterm.c	1.14	(Berkeley)	02/26/85";
6514087Sslatteng 
6614645Sslatteng char	**spectab;		/* here go the special characters */
67*18122Sslatteng char	specfile[100] = FONTDIR;/* place to look up special characters */
6814645Sslatteng char	*malloc();
6914822Sslatteng char	*operand();
7014087Sslatteng 
7114816Sslatteng int 	keepon	= 0;	/* flags:  Don't stop at the end of each page? */
7214816Sslatteng int	clearsc = 0;		/* Put out form feed at each page? */
7314816Sslatteng int	output	= 0;		/* Do we do output at all? */
7414816Sslatteng int	nolist	= 0;		/* Output page list if > 0 */
7515279Sslatteng int	margin	= 0;		/* Print blank margins? */
7616847Sslatteng int	ascii	= 0;		/* make the output "readable"? */
7714645Sslatteng int	olist[20];		/* pairs of page numbers */
7814087Sslatteng 
7914645Sslatteng float	hscale	= 10.0;		/* characters and lines per inch for output */
8014645Sslatteng float	vscale	= 6.0;		/*	device (defaults are for printer) */
8114645Sslatteng FILE	*fp = stdin;		/* input file pointer */
8214087Sslatteng 
8314087Sslatteng char	pagebuf[PGHEIGHT][PGWIDTH];
8414087Sslatteng int	minh	= PGWIDTH;
8514087Sslatteng int	maxh	= 0;
8614087Sslatteng int	minv	= PGHEIGHT;
8714087Sslatteng int	maxv	= 0;
8814087Sslatteng int	linelen = LINELEN;
8914087Sslatteng 
9014087Sslatteng int	hpos;		/* horizontal position to be next (left = 0) */
9114087Sslatteng int	vpos;		/* current vertical position (down positive) */
9214087Sslatteng 
9314087Sslatteng int	np;		/* number of pages seen */
9414087Sslatteng int	npmax;		/* high-water mark of np */
9514087Sslatteng int	pgnum[40];	/* their actual numbers */
9614087Sslatteng long	pgadr[40];	/* their seek addresses */
9714087Sslatteng 
9814645Sslatteng int	DP;			/* step size for drawing */
9914816Sslatteng int	maxdots	= 3200;		/* maximum number of dots in an object */
10014087Sslatteng 
10114087Sslatteng 
10214087Sslatteng 
main(argc,argv)10314087Sslatteng main(argc, argv)
10414087Sslatteng int argc;
10514087Sslatteng char **argv;
10614087Sslatteng {
107*18122Sslatteng 	strcat(specfile, "/");
108*18122Sslatteng 	strcat(specfile, SPECFILE);
10914822Sslatteng 	while (--argc > 0 && **++argv == '-') {
11014822Sslatteng 	    switch ((*argv)[1]) {
11114645Sslatteng 		case 'f':		/* special character filepath */
112*18122Sslatteng 			strncpy(specfile, operand(&argc, &argv), 100);
11314645Sslatteng 			break;
11414645Sslatteng 		case 'l':		/* output line length */
11514822Sslatteng 			linelen = atoi(operand(&argc, &argv)) - 1;
11614087Sslatteng 			break;
11714645Sslatteng 		case 'h':		/* horizontal scale (char/inch) */
11814822Sslatteng 			hscale = atof(operand(&argc, &argv));
11914087Sslatteng 			break;
12014645Sslatteng 		case 'v':		/* vertical scale (char/inch) */
12114822Sslatteng 			vscale = atof(operand(&argc, &argv));
12214087Sslatteng 			break;
12314645Sslatteng 		case 'o':		/* output list */
12414822Sslatteng 			outlist(operand(&argc, &argv));
12514087Sslatteng 			break;
12614816Sslatteng 		case 'c':		/* continue at endofpage */
12714822Sslatteng 			keepon = !keepon;
12814087Sslatteng 			break;
12915279Sslatteng 		case 'm':		/* print margins */
13015279Sslatteng 			margin = !margin;
13115279Sslatteng 			break;
13216847Sslatteng 		case 'a':		/* readable mode */
13316847Sslatteng 			ascii = !ascii;
13416847Sslatteng 			break;
13514816Sslatteng 		case 'L':		/* form feed after each page */
13614822Sslatteng 			clearsc = !clearsc;
13714816Sslatteng 			break;
13814816Sslatteng  		case 'w':		/* "wide" printer format */
13914090Sslatteng 			hscale = 16.0;
14014090Sslatteng 			vscale = 9.6;
14114087Sslatteng 			linelen = 131;
14214087Sslatteng 			keepon = 1;
14314816Sslatteng 			clearsc = 1;
14414087Sslatteng 			break;
14514087Sslatteng 	    }
14614087Sslatteng 	}
14714087Sslatteng 
14814822Sslatteng 	if (argc < 1)
14914087Sslatteng 		conv(stdin);
15014087Sslatteng 	else
15114822Sslatteng 		while (argc--) {
15214087Sslatteng 			if (strcmp(*argv, "-") == 0)
15314087Sslatteng 				fp = stdin;
15414087Sslatteng 			else if ((fp = fopen(*argv, "r")) == NULL)
15514087Sslatteng 				error(FATAL, "can't open %s", *argv);
15614087Sslatteng 			conv(fp);
15714087Sslatteng 			fclose(fp);
15814087Sslatteng 			argv++;
15914087Sslatteng 		}
16014087Sslatteng 	done();
16114087Sslatteng }
16214087Sslatteng 
16314087Sslatteng 
16414822Sslatteng /*----------------------------------------------------------------------------*
16514822Sslatteng  | Routine:	char  * operand (& argc,  & argv)
16614822Sslatteng  |
16714822Sslatteng  | Results:	returns address of the operand given with a command-line
16814822Sslatteng  |		option.  It uses either "-Xoperand" or "-X operand", whichever
16914822Sslatteng  |		is present.  The program is terminated if no option is present.
17014822Sslatteng  |
17114822Sslatteng  | Side Efct:	argc and argv are updated as necessary.
17214822Sslatteng  *----------------------------------------------------------------------------*/
17314822Sslatteng 
operand(argcp,argvp)17414822Sslatteng char *operand(argcp, argvp)
17514822Sslatteng int * argcp;
17614822Sslatteng char ***argvp;
17714822Sslatteng {
17814822Sslatteng 	if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
17914822Sslatteng 	if ((--*argcp) <= 0) {			/* operand next word */
18014822Sslatteng 	    fprintf (stderr, "command-line option operand missing.\n");
18114822Sslatteng 	    exit(1);
18214822Sslatteng 	}
18314822Sslatteng 	return(*(++(*argvp)));			/* no operand */
18414822Sslatteng }
18514822Sslatteng 
18614822Sslatteng 
outlist(s)18714087Sslatteng outlist(s)	/* process list of page numbers to be printed */
18814087Sslatteng char *s;
18914087Sslatteng {
19014087Sslatteng 	int n1, n2, i;
19114087Sslatteng 
19214087Sslatteng 	nolist = 0;
19314087Sslatteng 	while (*s) {
19414087Sslatteng 		n1 = 0;
19514087Sslatteng 		if (isdigit(*s))
19614087Sslatteng 			do
19714087Sslatteng 				n1 = 10 * n1 + *s++ - '0';
19814087Sslatteng 			while (isdigit(*s));
19914087Sslatteng 		else
20014087Sslatteng 			n1 = -9999;
20114087Sslatteng 		n2 = n1;
20214087Sslatteng 		if (*s == '-') {
20314087Sslatteng 			s++;
20414087Sslatteng 			n2 = 0;
20514087Sslatteng 			if (isdigit(*s))
20614087Sslatteng 				do
20714087Sslatteng 					n2 = 10 * n2 + *s++ - '0';
20814087Sslatteng 				while (isdigit(*s));
20914087Sslatteng 			else
21014087Sslatteng 				n2 = 9999;
21114087Sslatteng 		}
21214087Sslatteng 		olist[nolist++] = n1;
21314087Sslatteng 		olist[nolist++] = n2;
21414087Sslatteng 		if (*s != '\0')
21514087Sslatteng 			s++;
21614087Sslatteng 	}
21714087Sslatteng 	olist[nolist] = 0;
21814087Sslatteng }
21914087Sslatteng 
22014087Sslatteng 
in_olist(n)22114087Sslatteng in_olist(n)	/* is n in olist? */
22214087Sslatteng int n;
22314087Sslatteng {
22414087Sslatteng 	int i;
22514087Sslatteng 
22614087Sslatteng 	if (nolist == 0)
22714087Sslatteng 		return(1);	/* everything is included */
22814087Sslatteng 	for (i = 0; i < nolist; i += 2)
22914087Sslatteng 		if (n >= olist[i] && n <= olist[i+1])
23014087Sslatteng 			return(1);
23114087Sslatteng 	return(0);
23214087Sslatteng }
23314087Sslatteng 
23414087Sslatteng 
conv(fp)23514087Sslatteng conv(fp)
23614087Sslatteng register FILE *fp;
23714087Sslatteng {
23814087Sslatteng 	register int c;
23914087Sslatteng 	int m, n, i, n1, m1;
24014087Sslatteng 	char str[100], buf[300];
24114087Sslatteng 
24214087Sslatteng 	while ((c = getc(fp)) != EOF) {
24314087Sslatteng 		switch (c) {
24414087Sslatteng 		case '\n':	/* when input is text */
24514087Sslatteng 		case '\t':
24614087Sslatteng 		case ' ':
24714087Sslatteng 		case 0:
24814087Sslatteng 			break;
24914087Sslatteng 
25014087Sslatteng 		case '0': case '1': case '2': case '3': case '4':
25114087Sslatteng 		case '5': case '6': case '7': case '8': case '9':
25214087Sslatteng 				/* two motion digits plus a character */
25316847Sslatteng 			if (ascii) {
25416847Sslatteng 			    hmot((int)hscale);
25516847Sslatteng 			    getc(fp);
25616847Sslatteng 			} else {
25716847Sslatteng 			    hmot((c-'0')*10 + getc(fp)-'0');
25816847Sslatteng 			}
25914087Sslatteng 			put1(getc(fp));
26014087Sslatteng 			break;
26114087Sslatteng 
26214087Sslatteng 		case 'c':	/* single ascii character */
26314087Sslatteng 			put1(getc(fp));
26414087Sslatteng 			break;
26514087Sslatteng 
26614087Sslatteng 		case 'C':	/* funny character */
26714087Sslatteng 			fscanf(fp, "%s", str);
26814087Sslatteng 			put1s(str);
26914087Sslatteng 			break;
27014087Sslatteng 
27114087Sslatteng 		case 't':	/* straight text */
27214087Sslatteng 			fgets(buf, sizeof(buf), fp);
27314087Sslatteng 			t_text(buf);
27414087Sslatteng 			break;
27514087Sslatteng 
27614087Sslatteng 		case 'D':	/* draw function */
27714087Sslatteng 			fgets(buf, sizeof(buf), fp);
27814087Sslatteng 			switch (buf[0]) {
27914087Sslatteng 			case 'l':	/* draw a line */
28014087Sslatteng 				sscanf(buf+1, "%d %d", &n, &m);
28116389Sslatteng 				drawline(n, m);
28214087Sslatteng 				break;
28314087Sslatteng 			case 'c':	/* circle */
28414087Sslatteng 				sscanf(buf+1, "%d", &n);
28514087Sslatteng 				drawcirc(n);
28614087Sslatteng 				break;
28714087Sslatteng 			case 'e':	/* ellipse */
28814087Sslatteng 				sscanf(buf+1, "%d %d", &m, &n);
28914087Sslatteng 				drawellip(m, n);
29014087Sslatteng 				break;
29114087Sslatteng 			case 'a':	/* arc */
29214087Sslatteng 				sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
29314087Sslatteng 				drawarc(n, m, n1, m1);
29414087Sslatteng 				break;
29516505Sslatteng 			case 'q':	/* versatec polygon - ignore */
29616505Sslatteng 				while (buf[strlen(buf) - 1] != '\n')
29716505Sslatteng 				    if (fgets(buf, sizeof(buf), fp) == NULL)
29816505Sslatteng 					error(FATAL,"unexpected end of input");
29916505Sslatteng 				break;
30016505Sslatteng 			case 'P':	/* unbordered */
30116389Sslatteng 			case 'p':	/* polygon */
30216389Sslatteng 				sscanf(buf+1, "%d", &n);
30316389Sslatteng 				n = 1;
30416389Sslatteng 				while(buf[n++] == ' ');
30516389Sslatteng 				while(isdigit(buf[n])) n++;
30616389Sslatteng 				drawwig(buf+n, 1);
30716389Sslatteng 				break;
30814087Sslatteng 			case 'g':	/* "gremlin" curve */
30914087Sslatteng 			case '~':	/* wiggly line */
31016389Sslatteng 				drawwig(buf+1, 0);
31114087Sslatteng 				break;
31214087Sslatteng 			case 't':	/* thickness - not important */
31314087Sslatteng 			case 's':	/* style - not important */
31414087Sslatteng 				break;
31514087Sslatteng 			default:
31614087Sslatteng 				error(FATAL,"unknown drawing command %s\n",buf);
31714087Sslatteng 				break;
31814087Sslatteng 			}
31914087Sslatteng 			break;
32016389Sslatteng 		case 'i':	/* stipple pattern request - ignored */
32114087Sslatteng 		case 's':	/* point size - ignored */
32214087Sslatteng 			fscanf(fp, "%d", &n);
32314087Sslatteng 			break;
32414087Sslatteng 
32514087Sslatteng 		case 'f':	/* font request - ignored */
32614087Sslatteng 			fscanf(fp, "%s", str);
32714087Sslatteng 			break;
32814087Sslatteng 
32914087Sslatteng 		case 'H':	/* absolute horizontal motion */
33014087Sslatteng 			fscanf(fp, "%d", &n);
33114087Sslatteng 			hgoto(n);
33214087Sslatteng 			break;
33314087Sslatteng 
33414087Sslatteng 		case 'h':	/* relative horizontal motion */
33514087Sslatteng 			fscanf(fp, "%d", &n);
33614087Sslatteng 			hmot(n);
33714087Sslatteng 			break;
33814087Sslatteng 
33914087Sslatteng 		case 'w':	/* word space */
34016847Sslatteng 			if (ascii) {
34116847Sslatteng 			    hmot((int)hscale);
34216847Sslatteng 			}
34314087Sslatteng 			break;
34414087Sslatteng 
34514087Sslatteng 		case 'V':	/* absolute vertical motion */
34614087Sslatteng 			fscanf(fp, "%d", &n);
34714087Sslatteng 			vgoto(n);
34814087Sslatteng 			break;
34914087Sslatteng 
35014087Sslatteng 		case 'v':	/* relative vertical motion */
35114087Sslatteng 			fscanf(fp, "%d", &n);
35214087Sslatteng 			vmot(n);
35314087Sslatteng 			break;
35414087Sslatteng 
35514087Sslatteng 		case 'p':	/* new page */
35614087Sslatteng 			fscanf(fp, "%d", &n);
35714087Sslatteng 			t_page(n);
35814087Sslatteng 			break;
35914087Sslatteng 
36015279Sslatteng 		case 'P':	/* new span (ignored) */
36115279Sslatteng 			fscanf(fp, "%d", &n);
36215279Sslatteng 			break;
36315279Sslatteng 
36414087Sslatteng 		case 'n':	/* end of line */
36514087Sslatteng 			hpos = 0;
36614087Sslatteng 		case '#':	/* comment */
36714087Sslatteng 			while (getc(fp) != '\n')
36814087Sslatteng 				;
36914087Sslatteng 			break;
37014087Sslatteng 
37114087Sslatteng 		case 'x':	/* device control */
37214087Sslatteng 			devcntrl(fp);
37314087Sslatteng 			break;
37414087Sslatteng 
37514087Sslatteng 		default:
37614087Sslatteng 			error(!FATAL, "unknown input character %o %c\n", c, c);
37714087Sslatteng 			done();
37814087Sslatteng 		}
37914087Sslatteng 	}
38014087Sslatteng }
38114087Sslatteng 
38214087Sslatteng 
devcntrl(fp)38314087Sslatteng devcntrl(fp)	/* interpret device control functions */
38414087Sslatteng FILE *fp;
38514087Sslatteng {
38614087Sslatteng 	int c, n;
38714087Sslatteng 	char str[20];
38814087Sslatteng 
38914087Sslatteng 	fscanf(fp, "%s", str);
39014087Sslatteng 	switch (str[0]) {	/* crude for now */
39114087Sslatteng 	case 'i':	/* initialize */
39214087Sslatteng 		t_init(0);
39314087Sslatteng 		break;
39414087Sslatteng 	case 'r':	/* resolution assumed when prepared */
39514087Sslatteng 		fscanf(fp, "%d", &n);
39614087Sslatteng 		hscale = (float) n / hscale;
39714087Sslatteng 		vscale = (float) n / vscale;
39814816Sslatteng 		DP = min (hscale, vscale);	/* guess the drawing */
39914816Sslatteng 		DP = max (DP, 1);		/* resolution */
40014816Sslatteng 		break;
40114087Sslatteng 	case 'f':	/* font used */
40214087Sslatteng 	case 'T':	/* device name */
40314087Sslatteng 	case 't':	/* trailer */
40414087Sslatteng 	case 'p':	/* pause -- can restart */
40514087Sslatteng 	case 's':	/* stop */
40614087Sslatteng 		break;
40714087Sslatteng 	}
40814087Sslatteng 	while (getc(fp) != '\n')	/* skip rest of input line */
40914087Sslatteng 		;
41014087Sslatteng }
41114087Sslatteng 
41214087Sslatteng 		/* error printing routine - first argument is a "fatal" flag */
error(f,s,a1,a2,a3,a4,a5,a6,a7)41314087Sslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7) {
41414087Sslatteng     fprintf(stderr, "dterm: ");
41514087Sslatteng     fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
41614087Sslatteng     fprintf(stderr, "\n");
41714087Sslatteng     if (f) exit(1);
41814087Sslatteng }
41914087Sslatteng 
42014087Sslatteng 
t_init(reinit)42114087Sslatteng t_init(reinit)	/* initialize device */
42214087Sslatteng int reinit;
42314087Sslatteng {
42414645Sslatteng 	register int i;
42514645Sslatteng 	register int j;
42614645Sslatteng 	register FILE *fp;	/* file to look up special characters */
42714645Sslatteng 	register char *charptr;	/* string pointer to step through specials */
42814645Sslatteng 	register char *tabptr;	/* string pointer for spectab setting */
42914645Sslatteng 	char specials[5000];	/* intermediate input buffer (made bigger */
43014645Sslatteng 				/*   than we'll EVER use... */
43114087Sslatteng 
43214645Sslatteng 
43314087Sslatteng 	fflush(stdout);
43414087Sslatteng 	hpos = vpos = 0;
43514087Sslatteng 	for (i = 0; i < PGHEIGHT; i++)
43614087Sslatteng 		for (j = 0; j < PGWIDTH; j++)
43714087Sslatteng 			pagebuf[i][j] = ' ';
43814087Sslatteng 	minh = PGWIDTH;
43914087Sslatteng 	maxh = 0;
44014087Sslatteng 	minv = PGHEIGHT;
44114087Sslatteng 	maxv = 0;
44214645Sslatteng 
44314645Sslatteng 	if (reinit) return;		/* if this is the first time, read */
44414645Sslatteng 					/* special character table file. */
44514645Sslatteng 	if ((fp = fopen (specfile, "r")) != NULL) {
44614645Sslatteng 	    charptr = &specials[0];
44714923Sslatteng 	    for (i = 2; fscanf(fp, "%s", charptr) != EOF; i++) {
44814645Sslatteng 		charptr += strlen(charptr) + 1;
44914645Sslatteng 	    }
45014645Sslatteng 	    fclose(fp);
45114645Sslatteng 	    *charptr++ = '\0';			/* ending strings */
45214645Sslatteng 	    *charptr++ = '\0';
45314645Sslatteng 						/* allocate table */
45414645Sslatteng 	    spectab = (char **) malloc(i * sizeof(char*));
45514645Sslatteng 	    spectab[0] = tabptr = malloc(j = (int) (charptr - &specials[0]));
45614645Sslatteng 
45714645Sslatteng 						/* copy whole table */
45814645Sslatteng 	    for (charptr = &specials[0]; j--; *tabptr++ = *charptr++);
45914645Sslatteng 
46014923Sslatteng 	    tabptr = spectab[0];		/* set up pointers to table */
46114645Sslatteng 	    for (j = 0; i--; j++) {
46214645Sslatteng 		spectab[j] = tabptr;
46314645Sslatteng 		tabptr += strlen(tabptr) + 1;
46414645Sslatteng 	    }
46514645Sslatteng 
46614645Sslatteng 	} else {	/* didn't find table - allocate a null one */
46714645Sslatteng 
46814645Sslatteng 	    error (!FATAL, "Can't open special character file: %s", specfile);
46914645Sslatteng 	    spectab = (char **) malloc(2 * sizeof(char*));
47014645Sslatteng 	    spectab[0] = malloc (2);
47114645Sslatteng 	    spectab[1] = spectab[0] + 1;
47214645Sslatteng 	    *spectab[0] = '\0';
47314645Sslatteng 	    *spectab[1] = '\0';
47414645Sslatteng 	}
47514087Sslatteng }
47614087Sslatteng 
47714087Sslatteng 
47814087Sslatteng 		/* just got "p#" command.  print the current page and */
t_page(n)47914087Sslatteng t_page(n)	/* do whatever new page functions */
48014087Sslatteng {
48114087Sslatteng 	long ftell();
48214087Sslatteng 	int c, m, i;
48314087Sslatteng 	char buf[100], *bp;
48414087Sslatteng 
48514087Sslatteng 	pgnum[np++] = n;
48614087Sslatteng 	pgadr[np] = ftell(fp);
48714087Sslatteng 	if (np > npmax)
48814087Sslatteng 		npmax = np;
48914087Sslatteng 	if (output == 0) {
49014087Sslatteng 		output = in_olist(n);
49114087Sslatteng 		t_init(1);
49214087Sslatteng 		return;
49314087Sslatteng 	}
49414087Sslatteng 
49514087Sslatteng 	putpage();
49614087Sslatteng 	fflush(stdout);
49714087Sslatteng 
49814816Sslatteng 	if (clearsc) putchar('');
49914087Sslatteng 	if (keepon) {
50014087Sslatteng 		t_init(1);
50114087Sslatteng 		return;
50214087Sslatteng 	}
50314087Sslatteng   next:
50414087Sslatteng 	for (bp = buf; (*bp = readch()); )
50514087Sslatteng 		if (*bp++ == '\n')
50614087Sslatteng 			break;
50714087Sslatteng 	*bp = 0;
50814087Sslatteng 	switch (buf[0]) {
50914087Sslatteng 	case 0:
51014087Sslatteng 		done();
51114087Sslatteng 		break;
51214087Sslatteng 	case '\n':
51314087Sslatteng 		output = in_olist(n);
51414087Sslatteng 		t_init(1);
51514087Sslatteng 		return;
51614087Sslatteng 	case '-':
51714087Sslatteng 	case 'p':
51814087Sslatteng 		m = atoi(&buf[1]) + 1;
51914087Sslatteng 		if (fp == stdin) {
52014087Sslatteng 			fputs("you can't; it's not a file\n", stderr);
52114087Sslatteng 			break;
52214087Sslatteng 		}
52314087Sslatteng 		if (np - m <= 0) {
52414087Sslatteng 			fputs("too far back\n", stderr);
52514087Sslatteng 			break;
52614087Sslatteng 		}
52714087Sslatteng 		np -= m;
52814087Sslatteng 		fseek(fp, pgadr[np], 0);
52914087Sslatteng 		output = 1;
53014087Sslatteng 		t_init(1);
53114087Sslatteng 		return;
53214087Sslatteng 	case '0': case '1': case '2': case '3': case '4':
53314087Sslatteng 	case '5': case '6': case '7': case '8': case '9':
53414087Sslatteng 		m = atoi(&buf[0]);
53514087Sslatteng 		for (i = 0; i < npmax; i++)
53614087Sslatteng 			if (m == pgnum[i])
53714087Sslatteng 				break;
53814087Sslatteng 		if (i >= npmax || fp == stdin) {
53914087Sslatteng 			fputs("you can't\n", stderr);
54014087Sslatteng 			break;
54114087Sslatteng 		}
54214087Sslatteng 		np = i + 1;
54314087Sslatteng 		fseek(fp, pgadr[np], 0);
54414087Sslatteng 		output = 1;
54514087Sslatteng 		t_init(1);
54614087Sslatteng 		return;
54714087Sslatteng 	case 'o':
54814087Sslatteng 		outlist(&buf[1]);
54914087Sslatteng 		output = 0;
55014087Sslatteng 		t_init(1);
55114087Sslatteng 		return;
55214087Sslatteng 	case '?':
55314087Sslatteng 		fputs("p	print this page again\n", stderr);
55414087Sslatteng 		fputs("-n	go back n pages\n", stderr);
55514087Sslatteng 		fputs("n	print page n (previously printed)\n", stderr);
55614087Sslatteng 		fputs("o...	set the -o output list to ...\n", stderr);
55714087Sslatteng 		break;
55814087Sslatteng 	default:
55914087Sslatteng 		fputs("?\n", stderr);
56014087Sslatteng 		break;
56114087Sslatteng 	}
56214087Sslatteng 	goto next;
56314087Sslatteng }
56414087Sslatteng 
56514087Sslatteng 			/* print the contents of the current page.  puts out */
putpage()56614087Sslatteng putpage()		/* only the part of the page that's been written on */
56715279Sslatteng {			/* unless "margin" is set. */
56814087Sslatteng 	int i, j, k;
56914087Sslatteng 
57014087Sslatteng 	fflush(stdout);
57115279Sslatteng 	if (margin) minv = minh = 0;
57214087Sslatteng 	for (i = minv; i <= maxv; i++) {
57314087Sslatteng 		for (k = maxh; pagebuf[i][k] == ' '; k--)
57414087Sslatteng 			;
57514087Sslatteng 		if (k > minh + linelen)
57614087Sslatteng 			k = minh + linelen;
57714087Sslatteng 		for (j = minh; j <= k; j++)
57814087Sslatteng 			putchar(pagebuf[i][j]);
57914087Sslatteng 		putchar('\n');
58014087Sslatteng 	}
58114087Sslatteng 	fflush(stdout);
58214087Sslatteng }
58314087Sslatteng 
58414087Sslatteng 
t_text(s)58514087Sslatteng t_text(s)		/* print string s as text */
58614087Sslatteng char *s;
58714087Sslatteng {
58814087Sslatteng 	int c;
58914087Sslatteng 	char str[100];
59014087Sslatteng 
59114087Sslatteng 	if (!output)
59214087Sslatteng 		return;
59314087Sslatteng 	while ((c = *s++) != '\n') {
59414087Sslatteng 		if (c == '\\') {
59514087Sslatteng 			switch (c = *s++) {
59614087Sslatteng 			case '\\':
59714087Sslatteng 			case 'e':
59814087Sslatteng 				put1('\\');
59914087Sslatteng 				break;
60014087Sslatteng 			case '(':
60114087Sslatteng 				str[0] = *s++;
60214087Sslatteng 				str[1] = *s++;
60314087Sslatteng 				str[2] = '\0';
60414087Sslatteng 				put1s(str);
60514087Sslatteng 				break;
60614087Sslatteng 			}
60714087Sslatteng 		} else {
60814087Sslatteng 			put1(c);
60914087Sslatteng 		}
61016847Sslatteng 		hmot((int)hscale);
61114087Sslatteng 	}
61214087Sslatteng }
61314087Sslatteng 
61414087Sslatteng 
put1s(s)61514087Sslatteng put1s(s)	/* s is a funny char name */
61614087Sslatteng char *s;
61714087Sslatteng {
61814087Sslatteng 	int i;
61914087Sslatteng 	char *p;
62014087Sslatteng 	static char prev[10] = "";
62114087Sslatteng 	static int previ;
62214087Sslatteng 
62314087Sslatteng 	if (!output)
62414087Sslatteng 		return;
62514087Sslatteng 	if (strcmp(s, prev) != 0) {
62614087Sslatteng 		previ = -1;
62714645Sslatteng 		for (i = 0; *spectab[i] != '\0'; i += 2)
62814087Sslatteng 			if (strcmp(spectab[i], s) == 0) {
62914087Sslatteng 				strcpy(prev, s);
63014087Sslatteng 				previ = i;
63114087Sslatteng 				break;
63214087Sslatteng 			}
63314087Sslatteng 	}
63414087Sslatteng 	if (previ >= 0) {
63516847Sslatteng 		for (hmot((int)-hscale), p = spectab[previ+1]; *p; p++) {
63616847Sslatteng 			hmot((int)hscale);
63714087Sslatteng 			store(*p);
63816847Sslatteng 		}
63914087Sslatteng 	} else
64014645Sslatteng 		prev[0] = '\0';
64114087Sslatteng }
64214087Sslatteng 
64314087Sslatteng 
put1(c)64414087Sslatteng put1(c)			/* output char c */
64514087Sslatteng int c;
64614087Sslatteng {
64714087Sslatteng 	if (!output)
64814087Sslatteng 		return;
64914087Sslatteng 	store(c);
65014087Sslatteng }
65114087Sslatteng 
65214087Sslatteng 
done()65314087Sslatteng done()
65414087Sslatteng {
65514087Sslatteng 	output = 1;
65614087Sslatteng 	putpage();
65714087Sslatteng 	fflush(stdout);
65814087Sslatteng 	exit(0);
65914087Sslatteng }
66014087Sslatteng 
66114087Sslatteng 
readch()66214087Sslatteng readch ()
66314087Sslatteng {
66414087Sslatteng 	int c;
66514087Sslatteng 	static FILE *rcf;
66614087Sslatteng 	static nbol;	/* 0 if at beginning of a line */
66714087Sslatteng 
66814087Sslatteng 	if (rcf == NULL) {
66914087Sslatteng 		rcf = fopen ("/dev/tty", "r");
67014087Sslatteng 		setbuf (rcf, NULL);
67114087Sslatteng 	}
67214087Sslatteng 
67314087Sslatteng 	if (!nbol)
67414087Sslatteng 		fprintf (stderr, "dterm: ");	/* issue prompt */
67514087Sslatteng 	if ((c = getc (rcf)) == EOF)
67614087Sslatteng 		return 0;
67714087Sslatteng 	nbol = (c != '\n');
67814087Sslatteng 	return c;
67914087Sslatteng }
68014087Sslatteng 
68114087Sslatteng 
store(c)68214087Sslatteng store(c)		/* put 'c' in the page at (hpos, vpos) */
68314087Sslatteng {
68414087Sslatteng 	register int i;
68514087Sslatteng 	register int j;
68614087Sslatteng 
68714087Sslatteng 
68814087Sslatteng 	i = hpos / hscale;	/* scale the position to page coordinates */
68914087Sslatteng 	j = vpos / vscale;
69014087Sslatteng 
69114087Sslatteng 	if (i >= PGWIDTH) i = PGWIDTH - 1;	/* don't go over the edge */
69214087Sslatteng 	else if (i < 0) i = 0;
69314087Sslatteng 	if (j >= PGHEIGHT) j = PGHEIGHT - 1;
69414087Sslatteng 	else if (j < 0) j = 0;
69514087Sslatteng 
69614087Sslatteng 	pagebuf[j][i] = c;		/* write the character */
69714087Sslatteng 
69814087Sslatteng 	if (i > maxh) maxh = i;		/* update the page bounds */
69914087Sslatteng 	if (i < minh) minh = i;
70014087Sslatteng 	if (j > maxv) maxv = j;
70114087Sslatteng 	if (j < minv) minv = j;
70214087Sslatteng }
70314087Sslatteng 
70414087Sslatteng 
drawline(dx,dy)70516389Sslatteng drawline(dx, dy)	/* draw line from here to dx, dy using s */
70614087Sslatteng int dx, dy;
70714087Sslatteng {
70814087Sslatteng 	register int xd;
70914087Sslatteng 	register int yd;
71014087Sslatteng 	register int i;
71114087Sslatteng 	register int numdots;
71214087Sslatteng 	int dirmot, perp;
71314087Sslatteng 	int motincr, perpincr;
71414087Sslatteng 	int ohpos, ovpos;
71514087Sslatteng 	float val, slope;
71614087Sslatteng 	float incrway;
71714087Sslatteng 
71814087Sslatteng 	ohpos = hpos;
71914087Sslatteng 	ovpos = vpos;
72014087Sslatteng 	xd = dx / DP;
72114087Sslatteng 	yd = dy / DP;
72214087Sslatteng 	if (xd == 0) {
72314087Sslatteng 		numdots = abs (yd);
72414087Sslatteng 		numdots = min(numdots, maxdots);
72514087Sslatteng 		motincr = DP * sgn (yd);
72616286Sslatteng 		put1('|');
72714087Sslatteng 		for (i = 0; i < numdots; i++) {
72814087Sslatteng 			vmot(motincr);
72916286Sslatteng 			put1('|');
73014087Sslatteng 		}
73114087Sslatteng 	} else
73214087Sslatteng 	if (yd == 0) {
73314087Sslatteng 		numdots = abs (xd);
73414816Sslatteng 		numdots = min(numdots, maxdots);
73514087Sslatteng 		motincr = DP * sgn (xd);
73616286Sslatteng 		put1('-');
73714087Sslatteng 		for (i = 0; i < numdots; i++) {
73814087Sslatteng 			hmot(motincr);
73916286Sslatteng 			put1('-');
74014087Sslatteng 		}
74114087Sslatteng 	} else {
74214087Sslatteng 	    if (abs (xd) > abs (yd)) {
74314087Sslatteng 		val = slope = (float) xd/yd;
74414087Sslatteng 		numdots = abs (xd);
74514087Sslatteng 		dirmot = 'h';
74614087Sslatteng 		perp = 'v';
74714087Sslatteng 		motincr = DP * sgn (xd);
74814087Sslatteng 		perpincr = DP * sgn (yd);
74914087Sslatteng 	    } else {
75014087Sslatteng 		val = slope = (float) yd/xd;
75114087Sslatteng 		numdots = abs (yd);
75214087Sslatteng 		dirmot = 'v';
75314087Sslatteng 		perp = 'h';
75414087Sslatteng 		motincr = DP * sgn (yd);
75514087Sslatteng 		perpincr = DP * sgn (xd);
75614087Sslatteng 	    }
75714645Sslatteng 	    numdots = min(numdots, maxdots);
75814087Sslatteng 	    incrway = sgn ((int) slope);
75916286Sslatteng 	    put1('*');
76014087Sslatteng 	    for (i = 0; i < numdots; i++) {
76114087Sslatteng 		val -= incrway;
76214087Sslatteng 		if (dirmot == 'h')
76314087Sslatteng 			hmot(motincr);
76414087Sslatteng 		else
76514087Sslatteng 			vmot(motincr);
76614087Sslatteng 		if (val * slope < 0) {
76714087Sslatteng 			if (perp == 'h')
76814087Sslatteng 				hmot(perpincr);
76914087Sslatteng 			else
77014087Sslatteng 				vmot(perpincr);
77114087Sslatteng 			val += slope;
77214087Sslatteng 		}
77316286Sslatteng 		put1('*');
77414087Sslatteng 	    }
77514087Sslatteng 	}
77614087Sslatteng 	hgoto(ohpos + dx);
77714087Sslatteng 	vgoto(ovpos + dy);
77814087Sslatteng }
77914087Sslatteng 
78014087Sslatteng 
drawwig(s,poly)78116389Sslatteng drawwig(s, poly)	/* draw wiggly line or polygon, if "poly" set */
78214087Sslatteng char *s;
78316389Sslatteng int poly;
78414087Sslatteng {
78514087Sslatteng 	int x[50], y[50], xp, yp, pxp, pyp;
78614087Sslatteng 	float t1, t2, t3, w;
78714087Sslatteng 	int i, j, numdots, N;
78814087Sslatteng 	char temp[50], *p, *getstr();
78914087Sslatteng 
79014087Sslatteng 	p = s;
79114087Sslatteng 	for (N = 2; (p=getstr(p,temp)) != NULL && N < sizeof(x)/sizeof(x[0]);) {
79214087Sslatteng 		x[N] = atoi(temp);
79314087Sslatteng 		p = getstr(p, temp);
79414087Sslatteng 		y[N++] = atoi(temp);
79514087Sslatteng 	}
79616389Sslatteng 	if (poly) {
79716389Sslatteng 		for (i = 2; i < N; i++)
79816389Sslatteng 			drawline(x[i], y[i]);
79916389Sslatteng 		return;
80016389Sslatteng 	}
80114087Sslatteng 	x[0] = x[1] = hpos;
80214087Sslatteng 	y[0] = y[1] = vpos;
80314087Sslatteng 	for (i = 1; i < N; i++) {
80414087Sslatteng 		x[i+1] += x[i];
80514087Sslatteng 		y[i+1] += y[i];
80614087Sslatteng 	}
80714087Sslatteng 	x[N] = x[N-1];
80814087Sslatteng 	y[N] = y[N-1];
80914087Sslatteng 	pxp = pyp = -9999;
81014087Sslatteng 	for (i = 0; i < N-1; i++) {	/* interval */
81114087Sslatteng 		numdots = (dist(x[i], y[i], x[i+1], y[i+1])
81214087Sslatteng 			     + dist(x[i+1], y[i+1], x[i+2], y[i+2])) / 2;
81314087Sslatteng 		numdots /= DP;
81414087Sslatteng 		numdots = min(numdots, maxdots);
81514087Sslatteng 		for (j = 0; j < numdots; j++) {	/* points within */
81614087Sslatteng 			w = (float) j / numdots;
81714087Sslatteng 			t1 = 0.5 * w * w;
81814087Sslatteng 			w = w - 0.5;
81914087Sslatteng 			t2 = 0.75 - w * w;
82014087Sslatteng 			w = w - 0.5;
82114087Sslatteng 			t3 = 0.5 * w * w;
82214087Sslatteng 			xp = t1 * x[i+2] + t2 * x[i+1] + t3 * x[i] + 0.5;
82314087Sslatteng 			yp = t1 * y[i+2] + t2 * y[i+1] + t3 * y[i] + 0.5;
82414087Sslatteng 			if (xp != pxp || yp != pyp) {
82514087Sslatteng 				hgoto(xp);
82614087Sslatteng 				vgoto(yp);
82716286Sslatteng 				put1('*');
82814087Sslatteng 				pxp = xp;
82914087Sslatteng 				pyp = yp;
83014087Sslatteng 			}
83114087Sslatteng 		}
83214087Sslatteng 	}
83314087Sslatteng }
83414087Sslatteng 
83514087Sslatteng 
83614087Sslatteng /* copy next non-blank string from p to temp, update p */
83714087Sslatteng 
getstr(p,temp)83814087Sslatteng char *getstr(p, temp)
83914087Sslatteng char *p, *temp;
84014087Sslatteng {
84114087Sslatteng 	while (*p == ' ' || *p == '\t' || *p == '\n')
84214087Sslatteng 		p++;
84314087Sslatteng 	if (*p == '\0') {
84414087Sslatteng 		temp[0] = 0;
84514087Sslatteng 		return(NULL);
84614087Sslatteng 	}
84714087Sslatteng 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
84814087Sslatteng 		*temp++ = *p++;
84914087Sslatteng 	*temp = '\0';
85014087Sslatteng 	return(p);
85114087Sslatteng }
85214087Sslatteng 
85314087Sslatteng 
drawcirc(d)85414087Sslatteng drawcirc(d)
85514087Sslatteng {
85614087Sslatteng 	int xc, yc;
85714087Sslatteng 
85814087Sslatteng 	xc = hpos;
85914087Sslatteng 	yc = vpos;
86014087Sslatteng 	conicarc(hpos + d/2, -vpos, hpos, -vpos, hpos, -vpos, d/2, d/2);
86114087Sslatteng 	hgoto(xc + d);	/* circle goes to right side */
86214087Sslatteng 	vgoto(yc);
86314087Sslatteng }
86414087Sslatteng 
86514087Sslatteng 
dist(x1,y1,x2,y2)86614087Sslatteng dist(x1, y1, x2, y2)	/* integer distance from x1,y1 to x2,y2 */
86714087Sslatteng {
86814087Sslatteng 	float dx, dy;
86914087Sslatteng 
87014087Sslatteng 	dx = x2 - x1;
87114087Sslatteng 	dy = y2 - y1;
87214087Sslatteng 	return sqrt(dx*dx + dy*dy) + 0.5;
87314087Sslatteng }
87414087Sslatteng 
87514087Sslatteng 
drawarc(dx1,dy1,dx2,dy2)87614087Sslatteng drawarc(dx1, dy1, dx2, dy2)
87714087Sslatteng {
87814087Sslatteng 	int x0, y0, x2, y2, r;
87914087Sslatteng 
88014087Sslatteng 	x0 = hpos + dx1;	/* center */
88114087Sslatteng 	y0 = vpos + dy1;
88214087Sslatteng 	x2 = x0 + dx2;	/* "to" */
88314087Sslatteng 	y2 = y0 + dy2;
88414087Sslatteng 	r = sqrt((float) dx1 * dx1 + (float) dy1 * dy1) + 0.5;
88514087Sslatteng 	conicarc(x0, -y0, hpos, -vpos, x2, -y2, r, r);
88614087Sslatteng }
88714087Sslatteng 
88814087Sslatteng 
drawellip(a,b)88914087Sslatteng drawellip(a, b)
89014087Sslatteng {
89114087Sslatteng 	int xc, yc;
89214087Sslatteng 
89314087Sslatteng 	xc = hpos;
89414087Sslatteng 	yc = vpos;
89514087Sslatteng 	conicarc(hpos + a/2, -vpos, hpos, -vpos, hpos, -vpos, a/2, b/2);
89614087Sslatteng 	hgoto(xc + a);
89714087Sslatteng 	vgoto(yc);
89814087Sslatteng }
89914087Sslatteng 
90014087Sslatteng 
conicarc(x,y,x0,y0,x1,y1,a,b)90114087Sslatteng conicarc(x, y, x0, y0, x1, y1, a, b)
90214087Sslatteng {
90314087Sslatteng 		/* based on Bresenham, CACM Feb 77, pp 102-3 by Chris Van Wyk */
90414087Sslatteng 		/* capitalized vars are an internal reference frame */
90514087Sslatteng 	long dotcount = 0;
90614087Sslatteng 	int	xs, ys, xt, yt, Xs, Ys, qs, Xt, Yt, qt,
90714087Sslatteng 		M1x, M1y, M2x, M2y, M3x, M3y,
90814087Sslatteng 		Q, move, Xc, Yc;
90914087Sslatteng 	int ox1, oy1;
91014087Sslatteng 	long	delta;
91114087Sslatteng 	float	xc, yc;
91214087Sslatteng 	float	radius, slope;
91314087Sslatteng 	float	xstep, ystep;
91414087Sslatteng 
91514087Sslatteng 	ox1 = x1;
91614087Sslatteng 	oy1 = y1;
91714087Sslatteng 	if (a != b)	/* an arc of an ellipse; internally, think of circle */
91814087Sslatteng 		if (a > b) {
91914087Sslatteng 			xstep = (float)a / b;
92014087Sslatteng 			ystep = 1;
92114087Sslatteng 			radius = b;
92214087Sslatteng 		} else {
92314087Sslatteng 			xstep = 1;
92414087Sslatteng 			ystep = (float)b / a;
92514087Sslatteng 			radius = a;
92614087Sslatteng 		}
92714087Sslatteng 	else {
92814087Sslatteng 	    /* a circular arc; radius computed from center and first point */
92914087Sslatteng 		xstep = ystep = 1;
93014087Sslatteng 		radius = sqrt((float)(sqr(x0 - x) + sqr(y0 - y)));
93114087Sslatteng 	}
93214087Sslatteng 
93314087Sslatteng 	xc = x0;
93414087Sslatteng 	yc = y0;
93514087Sslatteng 	/* now, use start and end point locations to figure out
93614087Sslatteng 	the angle at which start and end happen; use these
93714087Sslatteng 	angles with known radius to figure out where start
93814087Sslatteng 	and end should be
93914087Sslatteng 	*/
94014087Sslatteng 	slope = atan2((double)(y0 - y), (double)(x0 - x) );
94114087Sslatteng 	if (slope == 0.0 && x0 < x)
94214087Sslatteng 		slope = 3.14159265;
94314087Sslatteng 	x0 = x + radius * cos(slope) + 0.5;
94414087Sslatteng 	y0 = y + radius * sin(slope) + 0.5;
94514087Sslatteng 	slope = atan2((double)(y1 - y), (double)(x1 - x));
94614087Sslatteng 	if (slope == 0.0 && x1 < x)
94714087Sslatteng 		slope = 3.14159265;
94814087Sslatteng 	x1 = x + radius * cos(slope) + 0.5;
94914087Sslatteng 	y1 = y + radius * sin(slope) + 0.5;
95014087Sslatteng 	/* step 2: translate to zero-centered circle */
95114087Sslatteng 	xs = x0 - x;
95214087Sslatteng 	ys = y0 - y;
95314087Sslatteng 	xt = x1 - x;
95414087Sslatteng 	yt = y1 - y;
95514087Sslatteng 	/* step 3: normalize to first quadrant */
95614087Sslatteng 	if (xs < 0)
95714087Sslatteng 		if (ys < 0) {
95814087Sslatteng 			Xs = abs(ys);
95914087Sslatteng 			Ys = abs(xs);
96014087Sslatteng 			qs = 3;
96114087Sslatteng 			M1x = 0;
96214087Sslatteng 			M1y = -1;
96314087Sslatteng 			M2x = 1;
96414087Sslatteng 			M2y = -1;
96514087Sslatteng 			M3x = 1;
96614087Sslatteng 			M3y = 0;
96714087Sslatteng 		} else {
96814087Sslatteng 			Xs = abs(xs);
96914087Sslatteng 			Ys = abs(ys);
97014087Sslatteng 			qs = 2;
97114087Sslatteng 			M1x = -1;
97214087Sslatteng 			M1y = 0;
97314087Sslatteng 			M2x = -1;
97414087Sslatteng 			M2y = -1;
97514087Sslatteng 			M3x = 0;
97614087Sslatteng 			M3y = -1;
97714087Sslatteng 		}
97814087Sslatteng 	else if (ys < 0) {
97914087Sslatteng 		Xs = abs(xs);
98014087Sslatteng 		Ys = abs(ys);
98114087Sslatteng 		qs = 0;
98214087Sslatteng 		M1x = 1;
98314087Sslatteng 		M1y = 0;
98414087Sslatteng 		M2x = 1;
98514087Sslatteng 		M2y = 1;
98614087Sslatteng 		M3x = 0;
98714087Sslatteng 		M3y = 1;
98814087Sslatteng 	} else {
98914087Sslatteng 		Xs = abs(ys);
99014087Sslatteng 		Ys = abs(xs);
99114087Sslatteng 		qs = 1;
99214087Sslatteng 		M1x = 0;
99314087Sslatteng 		M1y = 1;
99414087Sslatteng 		M2x = -1;
99514087Sslatteng 		M2y = 1;
99614087Sslatteng 		M3x = -1;
99714087Sslatteng 		M3y = 0;
99814087Sslatteng 	}
99914087Sslatteng 
100014087Sslatteng 	Xc = Xs;
100114087Sslatteng 	Yc = Ys;
100214087Sslatteng 	if (xt < 0)
100314087Sslatteng 		if (yt < 0) {
100414087Sslatteng 			Xt = abs(yt);
100514087Sslatteng 			Yt = abs(xt);
100614087Sslatteng 			qt = 3;
100714087Sslatteng 		} else {
100814087Sslatteng 			Xt = abs(xt);
100914087Sslatteng 			Yt = abs(yt);
101014087Sslatteng 			qt = 2;
101114087Sslatteng 		}
101214087Sslatteng 	else if (yt < 0) {
101314087Sslatteng 		Xt = abs(xt);
101414087Sslatteng 		Yt = abs(yt);
101514087Sslatteng 		qt = 0;
101614087Sslatteng 	} else {
101714087Sslatteng 		Xt = abs(yt);
101814087Sslatteng 		Yt = abs(xt);
101914087Sslatteng 		qt = 1;
102014087Sslatteng 	}
102114087Sslatteng 
102214087Sslatteng 		/* step 4: calculate number of quadrant crossings */
102314087Sslatteng 	if (((4 + qt - qs) % 4 == 0) && (Xt <= Xs) && (Yt >= Ys))
102414087Sslatteng 		Q = 3;
102514087Sslatteng 	else
102614087Sslatteng 		Q = (4 + qt - qs) % 4 - 1;
102714087Sslatteng 		/* step 5: calculate initial decision difference */
102814087Sslatteng 	delta = sqr(Xs + 1) + sqr(Ys - 1) - sqr(xs) - sqr(ys);
102914087Sslatteng 				/* here begins the work of drawing. */
103014087Sslatteng 	while ((Q >= 0) || ((Q > -2) && ((Xt > Xc) && (Yt < Yc)))) {
103116286Sslatteng 		if (dotcount++ % DP == 0) {
103216286Sslatteng 			hgoto((int)xc);
103316286Sslatteng 			vmot(-vpos-((int)yc));
103416286Sslatteng 			put1('*');
103516286Sslatteng 		}
103614087Sslatteng 		if (Yc < 0.5) {
103714087Sslatteng 			/* reinitialize */
103814087Sslatteng 			Xs = Xc = 0;
103914087Sslatteng 			Ys = Yc = sqrt((float)(sqr(xs) + sqr(ys)));
104014087Sslatteng 			delta = sqr(Xs + 1) + sqr(Ys - 1) - sqr(xs) - sqr(ys);
104114087Sslatteng 			Q--;
104214087Sslatteng 			M1x = M3x;
104314087Sslatteng 			M1y = M3y;
104414087Sslatteng 			 {
104514087Sslatteng 				int	T;
104614087Sslatteng 				T = M2y;
104714087Sslatteng 				M2y = M2x;
104814087Sslatteng 				M2x = -T;
104914087Sslatteng 				T = M3y;
105014087Sslatteng 				M3y = M3x;
105114087Sslatteng 				M3x = -T;
105214087Sslatteng 			}
105314087Sslatteng 		} else {
105414087Sslatteng 			if (delta <= 0)
105514087Sslatteng 				if (2 * delta + 2 * Yc - 1 <= 0)
105614087Sslatteng 					move = 1;
105714087Sslatteng 				else
105814087Sslatteng 					move = 2;
105914087Sslatteng 			else if (2 * delta - 2 * Xc - 1 <= 0)
106014087Sslatteng 				move = 2;
106114087Sslatteng 			else
106214087Sslatteng 				move = 3;
106314087Sslatteng 			switch (move) {
106414087Sslatteng 			case 1:
106514087Sslatteng 				Xc++;
106614087Sslatteng 				delta += 2 * Xc + 1;
106714087Sslatteng 				xc += M1x * xstep;
106814087Sslatteng 				yc += M1y * ystep;
106914087Sslatteng 				break;
107014087Sslatteng 			case 2:
107114087Sslatteng 				Xc++;
107214087Sslatteng 				Yc--;
107314087Sslatteng 				delta += 2 * Xc - 2 * Yc + 2;
107414087Sslatteng 				xc += M2x * xstep;
107514087Sslatteng 				yc += M2y * ystep;
107614087Sslatteng 				break;
107714087Sslatteng 			case 3:
107814087Sslatteng 				Yc--;
107914087Sslatteng 				delta -= 2 * Yc + 1;
108014087Sslatteng 				xc += M3x * xstep;
108114087Sslatteng 				yc += M3y * ystep;
108214087Sslatteng 				break;
108314087Sslatteng 			}
108414087Sslatteng 		}
108514087Sslatteng 	}
108616389Sslatteng 	drawline((int)xc-ox1,(int)yc-oy1);
108714087Sslatteng }
1088