1*b8908d5bSslatteng /* @(#)dterm.c 1.14 (Berkeley) 02/26/85"
2af45d5e6Sslatteng *
3af45d5e6Sslatteng * Converts ditroff output to text on a terminal. It is NOT meant to
4af45d5e6Sslatteng * produce readable output, but is to show one how one's paper is (in
5af45d5e6Sslatteng * general) formatted - what will go where on which page.
6af45d5e6Sslatteng *
7af45d5e6Sslatteng * options:
8af45d5e6Sslatteng *
9af45d5e6Sslatteng * -hn set horizontal resolution to n (in characters per inch;
10af45d5e6Sslatteng * default is 10.0).
11af45d5e6Sslatteng *
12af45d5e6Sslatteng * -vn set vertical resolution (default is 6.0).
13af45d5e6Sslatteng *
14af45d5e6Sslatteng * -ln set maximum output line-length to n (default is 79).
15af45d5e6Sslatteng *
16af45d5e6Sslatteng * -olist output page list - as in troff.
17af45d5e6Sslatteng *
18af45d5e6Sslatteng * -c continue at end of page. Default is to stop at the end
19af45d5e6Sslatteng * of each page, print "dterm:" and wait for a command.
20af45d5e6Sslatteng * Type ? to get a list of available commands.
21af45d5e6Sslatteng *
22ce133b5eSslatteng * -m print margins. Default action is to cut printing area down
23ce133b5eSslatteng * to only the part of the page with information on it.
24ce133b5eSslatteng *
25083ff42bSslatteng * -a make the output readable - i.e. print like a "troff -a" with
26083ff42bSslatteng * no character overlap, and one space 'tween words
27083ff42bSslatteng *
286e5cc3e6Sslatteng * -L put a form feed (^L) at the end of each page
296e5cc3e6Sslatteng *
30ce133b5eSslatteng * -w sets h = 20, v = 12, l = 131, also sets -c, -m and -L to allow
316e5cc3e6Sslatteng * for extra-wide printouts on the printer.
3218573097Sslatteng *
3318573097Sslatteng * -fxxx get special character definition file "xxx". Default is
34*b8908d5bSslatteng * FONTDIR/devter/specfile.
35af45d5e6Sslatteng */
36af45d5e6Sslatteng
37af45d5e6Sslatteng
38af45d5e6Sslatteng #include <stdio.h>
39af45d5e6Sslatteng #include <ctype.h>
40af45d5e6Sslatteng #include <math.h>
41af45d5e6Sslatteng
42af45d5e6Sslatteng
43af45d5e6Sslatteng #define FATAL 1
44bb5743b1Sslatteng #define PGWIDTH 266 /* WAY too big - for good measure */
45bb5743b1Sslatteng #define PGHEIGHT 220
46af45d5e6Sslatteng #define LINELEN 78
47*b8908d5bSslatteng #define SPECFILE "devter/specfile"
48*b8908d5bSslatteng #ifndef FONTDIR
49*b8908d5bSslatteng #define FONTDIR "/usr/lib/font"
50*b8908d5bSslatteng #endif
51af45d5e6Sslatteng
52af45d5e6Sslatteng #define hgoto(n) hpos = n
53af45d5e6Sslatteng #define vgoto(n) vpos = n
54af45d5e6Sslatteng #define hmot(n) hpos += n
55af45d5e6Sslatteng #define vmot(n) vpos += n
56af45d5e6Sslatteng
57af45d5e6Sslatteng #define sgn(n) ((n > 0) ? 1 : ((n < 0) ? -1 : 0))
58af45d5e6Sslatteng #define abs(n) ((n) >= 0 ? (n) : -(n))
59af45d5e6Sslatteng #define max(x,y) ((x) > (y) ? (x) : (y))
60af45d5e6Sslatteng #define min(x,y) ((x) < (y) ? (x) : (y))
61af45d5e6Sslatteng #define sqr(x) (long int)(x)*(x)
62af45d5e6Sslatteng
63af45d5e6Sslatteng
64*b8908d5bSslatteng char SccsId [] = "@(#)dterm.c 1.14 (Berkeley) 02/26/85";
65af45d5e6Sslatteng
6618573097Sslatteng char **spectab; /* here go the special characters */
67*b8908d5bSslatteng char specfile[100] = FONTDIR;/* place to look up special characters */
6818573097Sslatteng char *malloc();
696e5cc3e6Sslatteng char *operand();
70af45d5e6Sslatteng
71bb5743b1Sslatteng int keepon = 0; /* flags: Don't stop at the end of each page? */
72bb5743b1Sslatteng int clearsc = 0; /* Put out form feed at each page? */
73bb5743b1Sslatteng int output = 0; /* Do we do output at all? */
74bb5743b1Sslatteng int nolist = 0; /* Output page list if > 0 */
75ce133b5eSslatteng int margin = 0; /* Print blank margins? */
76083ff42bSslatteng int ascii = 0; /* make the output "readable"? */
77af45d5e6Sslatteng int olist[20]; /* pairs of page numbers */
78af45d5e6Sslatteng
7918573097Sslatteng float hscale = 10.0; /* characters and lines per inch for output */
8018573097Sslatteng float vscale = 6.0; /* device (defaults are for printer) */
81af45d5e6Sslatteng FILE *fp = stdin; /* input file pointer */
82af45d5e6Sslatteng
83af45d5e6Sslatteng char pagebuf[PGHEIGHT][PGWIDTH];
84af45d5e6Sslatteng int minh = PGWIDTH;
85af45d5e6Sslatteng int maxh = 0;
86af45d5e6Sslatteng int minv = PGHEIGHT;
87af45d5e6Sslatteng int maxv = 0;
88af45d5e6Sslatteng int linelen = LINELEN;
89af45d5e6Sslatteng
90af45d5e6Sslatteng int hpos; /* horizontal position to be next (left = 0) */
91af45d5e6Sslatteng int vpos; /* current vertical position (down positive) */
92af45d5e6Sslatteng
93af45d5e6Sslatteng int np; /* number of pages seen */
94af45d5e6Sslatteng int npmax; /* high-water mark of np */
95af45d5e6Sslatteng int pgnum[40]; /* their actual numbers */
96af45d5e6Sslatteng long pgadr[40]; /* their seek addresses */
97af45d5e6Sslatteng
9818573097Sslatteng int DP; /* step size for drawing */
99bb5743b1Sslatteng int maxdots = 3200; /* maximum number of dots in an object */
100af45d5e6Sslatteng
101af45d5e6Sslatteng
102af45d5e6Sslatteng
main(argc,argv)103af45d5e6Sslatteng main(argc, argv)
104af45d5e6Sslatteng int argc;
105af45d5e6Sslatteng char **argv;
106af45d5e6Sslatteng {
107*b8908d5bSslatteng strcat(specfile, "/");
108*b8908d5bSslatteng strcat(specfile, SPECFILE);
1096e5cc3e6Sslatteng while (--argc > 0 && **++argv == '-') {
1106e5cc3e6Sslatteng switch ((*argv)[1]) {
11118573097Sslatteng case 'f': /* special character filepath */
112*b8908d5bSslatteng strncpy(specfile, operand(&argc, &argv), 100);
11318573097Sslatteng break;
11418573097Sslatteng case 'l': /* output line length */
1156e5cc3e6Sslatteng linelen = atoi(operand(&argc, &argv)) - 1;
116af45d5e6Sslatteng break;
11718573097Sslatteng case 'h': /* horizontal scale (char/inch) */
1186e5cc3e6Sslatteng hscale = atof(operand(&argc, &argv));
119af45d5e6Sslatteng break;
12018573097Sslatteng case 'v': /* vertical scale (char/inch) */
1216e5cc3e6Sslatteng vscale = atof(operand(&argc, &argv));
122af45d5e6Sslatteng break;
12318573097Sslatteng case 'o': /* output list */
1246e5cc3e6Sslatteng outlist(operand(&argc, &argv));
125af45d5e6Sslatteng break;
126bb5743b1Sslatteng case 'c': /* continue at endofpage */
1276e5cc3e6Sslatteng keepon = !keepon;
128af45d5e6Sslatteng break;
129ce133b5eSslatteng case 'm': /* print margins */
130ce133b5eSslatteng margin = !margin;
131ce133b5eSslatteng break;
132083ff42bSslatteng case 'a': /* readable mode */
133083ff42bSslatteng ascii = !ascii;
134083ff42bSslatteng break;
135bb5743b1Sslatteng case 'L': /* form feed after each page */
1366e5cc3e6Sslatteng clearsc = !clearsc;
137bb5743b1Sslatteng break;
138bb5743b1Sslatteng case 'w': /* "wide" printer format */
139b15ec68bSslatteng hscale = 16.0;
140b15ec68bSslatteng vscale = 9.6;
141af45d5e6Sslatteng linelen = 131;
142af45d5e6Sslatteng keepon = 1;
143bb5743b1Sslatteng clearsc = 1;
144af45d5e6Sslatteng break;
145af45d5e6Sslatteng }
146af45d5e6Sslatteng }
147af45d5e6Sslatteng
1486e5cc3e6Sslatteng if (argc < 1)
149af45d5e6Sslatteng conv(stdin);
150af45d5e6Sslatteng else
1516e5cc3e6Sslatteng while (argc--) {
152af45d5e6Sslatteng if (strcmp(*argv, "-") == 0)
153af45d5e6Sslatteng fp = stdin;
154af45d5e6Sslatteng else if ((fp = fopen(*argv, "r")) == NULL)
155af45d5e6Sslatteng error(FATAL, "can't open %s", *argv);
156af45d5e6Sslatteng conv(fp);
157af45d5e6Sslatteng fclose(fp);
158af45d5e6Sslatteng argv++;
159af45d5e6Sslatteng }
160af45d5e6Sslatteng done();
161af45d5e6Sslatteng }
162af45d5e6Sslatteng
163af45d5e6Sslatteng
1646e5cc3e6Sslatteng /*----------------------------------------------------------------------------*
1656e5cc3e6Sslatteng | Routine: char * operand (& argc, & argv)
1666e5cc3e6Sslatteng |
1676e5cc3e6Sslatteng | Results: returns address of the operand given with a command-line
1686e5cc3e6Sslatteng | option. It uses either "-Xoperand" or "-X operand", whichever
1696e5cc3e6Sslatteng | is present. The program is terminated if no option is present.
1706e5cc3e6Sslatteng |
1716e5cc3e6Sslatteng | Side Efct: argc and argv are updated as necessary.
1726e5cc3e6Sslatteng *----------------------------------------------------------------------------*/
1736e5cc3e6Sslatteng
operand(argcp,argvp)1746e5cc3e6Sslatteng char *operand(argcp, argvp)
1756e5cc3e6Sslatteng int * argcp;
1766e5cc3e6Sslatteng char ***argvp;
1776e5cc3e6Sslatteng {
1786e5cc3e6Sslatteng if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
1796e5cc3e6Sslatteng if ((--*argcp) <= 0) { /* operand next word */
1806e5cc3e6Sslatteng fprintf (stderr, "command-line option operand missing.\n");
1816e5cc3e6Sslatteng exit(1);
1826e5cc3e6Sslatteng }
1836e5cc3e6Sslatteng return(*(++(*argvp))); /* no operand */
1846e5cc3e6Sslatteng }
1856e5cc3e6Sslatteng
1866e5cc3e6Sslatteng
outlist(s)187af45d5e6Sslatteng outlist(s) /* process list of page numbers to be printed */
188af45d5e6Sslatteng char *s;
189af45d5e6Sslatteng {
190af45d5e6Sslatteng int n1, n2, i;
191af45d5e6Sslatteng
192af45d5e6Sslatteng nolist = 0;
193af45d5e6Sslatteng while (*s) {
194af45d5e6Sslatteng n1 = 0;
195af45d5e6Sslatteng if (isdigit(*s))
196af45d5e6Sslatteng do
197af45d5e6Sslatteng n1 = 10 * n1 + *s++ - '0';
198af45d5e6Sslatteng while (isdigit(*s));
199af45d5e6Sslatteng else
200af45d5e6Sslatteng n1 = -9999;
201af45d5e6Sslatteng n2 = n1;
202af45d5e6Sslatteng if (*s == '-') {
203af45d5e6Sslatteng s++;
204af45d5e6Sslatteng n2 = 0;
205af45d5e6Sslatteng if (isdigit(*s))
206af45d5e6Sslatteng do
207af45d5e6Sslatteng n2 = 10 * n2 + *s++ - '0';
208af45d5e6Sslatteng while (isdigit(*s));
209af45d5e6Sslatteng else
210af45d5e6Sslatteng n2 = 9999;
211af45d5e6Sslatteng }
212af45d5e6Sslatteng olist[nolist++] = n1;
213af45d5e6Sslatteng olist[nolist++] = n2;
214af45d5e6Sslatteng if (*s != '\0')
215af45d5e6Sslatteng s++;
216af45d5e6Sslatteng }
217af45d5e6Sslatteng olist[nolist] = 0;
218af45d5e6Sslatteng }
219af45d5e6Sslatteng
220af45d5e6Sslatteng
in_olist(n)221af45d5e6Sslatteng in_olist(n) /* is n in olist? */
222af45d5e6Sslatteng int n;
223af45d5e6Sslatteng {
224af45d5e6Sslatteng int i;
225af45d5e6Sslatteng
226af45d5e6Sslatteng if (nolist == 0)
227af45d5e6Sslatteng return(1); /* everything is included */
228af45d5e6Sslatteng for (i = 0; i < nolist; i += 2)
229af45d5e6Sslatteng if (n >= olist[i] && n <= olist[i+1])
230af45d5e6Sslatteng return(1);
231af45d5e6Sslatteng return(0);
232af45d5e6Sslatteng }
233af45d5e6Sslatteng
234af45d5e6Sslatteng
conv(fp)235af45d5e6Sslatteng conv(fp)
236af45d5e6Sslatteng register FILE *fp;
237af45d5e6Sslatteng {
238af45d5e6Sslatteng register int c;
239af45d5e6Sslatteng int m, n, i, n1, m1;
240af45d5e6Sslatteng char str[100], buf[300];
241af45d5e6Sslatteng
242af45d5e6Sslatteng while ((c = getc(fp)) != EOF) {
243af45d5e6Sslatteng switch (c) {
244af45d5e6Sslatteng case '\n': /* when input is text */
245af45d5e6Sslatteng case '\t':
246af45d5e6Sslatteng case ' ':
247af45d5e6Sslatteng case 0:
248af45d5e6Sslatteng break;
249af45d5e6Sslatteng
250af45d5e6Sslatteng case '0': case '1': case '2': case '3': case '4':
251af45d5e6Sslatteng case '5': case '6': case '7': case '8': case '9':
252af45d5e6Sslatteng /* two motion digits plus a character */
253083ff42bSslatteng if (ascii) {
254083ff42bSslatteng hmot((int)hscale);
255083ff42bSslatteng getc(fp);
256083ff42bSslatteng } else {
257af45d5e6Sslatteng hmot((c-'0')*10 + getc(fp)-'0');
258083ff42bSslatteng }
259af45d5e6Sslatteng put1(getc(fp));
260af45d5e6Sslatteng break;
261af45d5e6Sslatteng
262af45d5e6Sslatteng case 'c': /* single ascii character */
263af45d5e6Sslatteng put1(getc(fp));
264af45d5e6Sslatteng break;
265af45d5e6Sslatteng
266af45d5e6Sslatteng case 'C': /* funny character */
267af45d5e6Sslatteng fscanf(fp, "%s", str);
268af45d5e6Sslatteng put1s(str);
269af45d5e6Sslatteng break;
270af45d5e6Sslatteng
271af45d5e6Sslatteng case 't': /* straight text */
272af45d5e6Sslatteng fgets(buf, sizeof(buf), fp);
273af45d5e6Sslatteng t_text(buf);
274af45d5e6Sslatteng break;
275af45d5e6Sslatteng
276af45d5e6Sslatteng case 'D': /* draw function */
277af45d5e6Sslatteng fgets(buf, sizeof(buf), fp);
278af45d5e6Sslatteng switch (buf[0]) {
279af45d5e6Sslatteng case 'l': /* draw a line */
280af45d5e6Sslatteng sscanf(buf+1, "%d %d", &n, &m);
2815839e65eSslatteng drawline(n, m);
282af45d5e6Sslatteng break;
283af45d5e6Sslatteng case 'c': /* circle */
284af45d5e6Sslatteng sscanf(buf+1, "%d", &n);
285af45d5e6Sslatteng drawcirc(n);
286af45d5e6Sslatteng break;
287af45d5e6Sslatteng case 'e': /* ellipse */
288af45d5e6Sslatteng sscanf(buf+1, "%d %d", &m, &n);
289af45d5e6Sslatteng drawellip(m, n);
290af45d5e6Sslatteng break;
291af45d5e6Sslatteng case 'a': /* arc */
292af45d5e6Sslatteng sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
293af45d5e6Sslatteng drawarc(n, m, n1, m1);
294af45d5e6Sslatteng break;
295007e314bSslatteng case 'q': /* versatec polygon - ignore */
296007e314bSslatteng while (buf[strlen(buf) - 1] != '\n')
297007e314bSslatteng if (fgets(buf, sizeof(buf), fp) == NULL)
298007e314bSslatteng error(FATAL,"unexpected end of input");
299007e314bSslatteng break;
300007e314bSslatteng case 'P': /* unbordered */
3015839e65eSslatteng case 'p': /* polygon */
3025839e65eSslatteng sscanf(buf+1, "%d", &n);
3035839e65eSslatteng n = 1;
3045839e65eSslatteng while(buf[n++] == ' ');
3055839e65eSslatteng while(isdigit(buf[n])) n++;
3065839e65eSslatteng drawwig(buf+n, 1);
3075839e65eSslatteng break;
308af45d5e6Sslatteng case 'g': /* "gremlin" curve */
309af45d5e6Sslatteng case '~': /* wiggly line */
3105839e65eSslatteng drawwig(buf+1, 0);
311af45d5e6Sslatteng break;
312af45d5e6Sslatteng case 't': /* thickness - not important */
313af45d5e6Sslatteng case 's': /* style - not important */
314af45d5e6Sslatteng break;
315af45d5e6Sslatteng default:
316af45d5e6Sslatteng error(FATAL,"unknown drawing command %s\n",buf);
317af45d5e6Sslatteng break;
318af45d5e6Sslatteng }
319af45d5e6Sslatteng break;
3205839e65eSslatteng case 'i': /* stipple pattern request - ignored */
321af45d5e6Sslatteng case 's': /* point size - ignored */
322af45d5e6Sslatteng fscanf(fp, "%d", &n);
323af45d5e6Sslatteng break;
324af45d5e6Sslatteng
325af45d5e6Sslatteng case 'f': /* font request - ignored */
326af45d5e6Sslatteng fscanf(fp, "%s", str);
327af45d5e6Sslatteng break;
328af45d5e6Sslatteng
329af45d5e6Sslatteng case 'H': /* absolute horizontal motion */
330af45d5e6Sslatteng fscanf(fp, "%d", &n);
331af45d5e6Sslatteng hgoto(n);
332af45d5e6Sslatteng break;
333af45d5e6Sslatteng
334af45d5e6Sslatteng case 'h': /* relative horizontal motion */
335af45d5e6Sslatteng fscanf(fp, "%d", &n);
336af45d5e6Sslatteng hmot(n);
337af45d5e6Sslatteng break;
338af45d5e6Sslatteng
339af45d5e6Sslatteng case 'w': /* word space */
340083ff42bSslatteng if (ascii) {
341083ff42bSslatteng hmot((int)hscale);
342083ff42bSslatteng }
343af45d5e6Sslatteng break;
344af45d5e6Sslatteng
345af45d5e6Sslatteng case 'V': /* absolute vertical motion */
346af45d5e6Sslatteng fscanf(fp, "%d", &n);
347af45d5e6Sslatteng vgoto(n);
348af45d5e6Sslatteng break;
349af45d5e6Sslatteng
350af45d5e6Sslatteng case 'v': /* relative vertical motion */
351af45d5e6Sslatteng fscanf(fp, "%d", &n);
352af45d5e6Sslatteng vmot(n);
353af45d5e6Sslatteng break;
354af45d5e6Sslatteng
355af45d5e6Sslatteng case 'p': /* new page */
356af45d5e6Sslatteng fscanf(fp, "%d", &n);
357af45d5e6Sslatteng t_page(n);
358af45d5e6Sslatteng break;
359af45d5e6Sslatteng
360ce133b5eSslatteng case 'P': /* new span (ignored) */
361ce133b5eSslatteng fscanf(fp, "%d", &n);
362ce133b5eSslatteng break;
363ce133b5eSslatteng
364af45d5e6Sslatteng case 'n': /* end of line */
365af45d5e6Sslatteng hpos = 0;
366af45d5e6Sslatteng case '#': /* comment */
367af45d5e6Sslatteng while (getc(fp) != '\n')
368af45d5e6Sslatteng ;
369af45d5e6Sslatteng break;
370af45d5e6Sslatteng
371af45d5e6Sslatteng case 'x': /* device control */
372af45d5e6Sslatteng devcntrl(fp);
373af45d5e6Sslatteng break;
374af45d5e6Sslatteng
375af45d5e6Sslatteng default:
376af45d5e6Sslatteng error(!FATAL, "unknown input character %o %c\n", c, c);
377af45d5e6Sslatteng done();
378af45d5e6Sslatteng }
379af45d5e6Sslatteng }
380af45d5e6Sslatteng }
381af45d5e6Sslatteng
382af45d5e6Sslatteng
devcntrl(fp)383af45d5e6Sslatteng devcntrl(fp) /* interpret device control functions */
384af45d5e6Sslatteng FILE *fp;
385af45d5e6Sslatteng {
386af45d5e6Sslatteng int c, n;
387af45d5e6Sslatteng char str[20];
388af45d5e6Sslatteng
389af45d5e6Sslatteng fscanf(fp, "%s", str);
390af45d5e6Sslatteng switch (str[0]) { /* crude for now */
391af45d5e6Sslatteng case 'i': /* initialize */
392af45d5e6Sslatteng t_init(0);
393af45d5e6Sslatteng break;
394af45d5e6Sslatteng case 'r': /* resolution assumed when prepared */
395af45d5e6Sslatteng fscanf(fp, "%d", &n);
396af45d5e6Sslatteng hscale = (float) n / hscale;
397af45d5e6Sslatteng vscale = (float) n / vscale;
398bb5743b1Sslatteng DP = min (hscale, vscale); /* guess the drawing */
399bb5743b1Sslatteng DP = max (DP, 1); /* resolution */
400bb5743b1Sslatteng break;
401af45d5e6Sslatteng case 'f': /* font used */
402af45d5e6Sslatteng case 'T': /* device name */
403af45d5e6Sslatteng case 't': /* trailer */
404af45d5e6Sslatteng case 'p': /* pause -- can restart */
405af45d5e6Sslatteng case 's': /* stop */
406af45d5e6Sslatteng break;
407af45d5e6Sslatteng }
408af45d5e6Sslatteng while (getc(fp) != '\n') /* skip rest of input line */
409af45d5e6Sslatteng ;
410af45d5e6Sslatteng }
411af45d5e6Sslatteng
412af45d5e6Sslatteng /* error printing routine - first argument is a "fatal" flag */
error(f,s,a1,a2,a3,a4,a5,a6,a7)413af45d5e6Sslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7) {
414af45d5e6Sslatteng fprintf(stderr, "dterm: ");
415af45d5e6Sslatteng fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
416af45d5e6Sslatteng fprintf(stderr, "\n");
417af45d5e6Sslatteng if (f) exit(1);
418af45d5e6Sslatteng }
419af45d5e6Sslatteng
420af45d5e6Sslatteng
t_init(reinit)421af45d5e6Sslatteng t_init(reinit) /* initialize device */
422af45d5e6Sslatteng int reinit;
423af45d5e6Sslatteng {
42418573097Sslatteng register int i;
42518573097Sslatteng register int j;
42618573097Sslatteng register FILE *fp; /* file to look up special characters */
42718573097Sslatteng register char *charptr; /* string pointer to step through specials */
42818573097Sslatteng register char *tabptr; /* string pointer for spectab setting */
42918573097Sslatteng char specials[5000]; /* intermediate input buffer (made bigger */
43018573097Sslatteng /* than we'll EVER use... */
43118573097Sslatteng
432af45d5e6Sslatteng
433af45d5e6Sslatteng fflush(stdout);
434af45d5e6Sslatteng hpos = vpos = 0;
435af45d5e6Sslatteng for (i = 0; i < PGHEIGHT; i++)
436af45d5e6Sslatteng for (j = 0; j < PGWIDTH; j++)
437af45d5e6Sslatteng pagebuf[i][j] = ' ';
438af45d5e6Sslatteng minh = PGWIDTH;
439af45d5e6Sslatteng maxh = 0;
440af45d5e6Sslatteng minv = PGHEIGHT;
441af45d5e6Sslatteng maxv = 0;
44218573097Sslatteng
44318573097Sslatteng if (reinit) return; /* if this is the first time, read */
44418573097Sslatteng /* special character table file. */
44518573097Sslatteng if ((fp = fopen (specfile, "r")) != NULL) {
44618573097Sslatteng charptr = &specials[0];
44726bd01f2Sslatteng for (i = 2; fscanf(fp, "%s", charptr) != EOF; i++) {
44818573097Sslatteng charptr += strlen(charptr) + 1;
44918573097Sslatteng }
45018573097Sslatteng fclose(fp);
45118573097Sslatteng *charptr++ = '\0'; /* ending strings */
45218573097Sslatteng *charptr++ = '\0';
45318573097Sslatteng /* allocate table */
45418573097Sslatteng spectab = (char **) malloc(i * sizeof(char*));
45518573097Sslatteng spectab[0] = tabptr = malloc(j = (int) (charptr - &specials[0]));
45618573097Sslatteng
45718573097Sslatteng /* copy whole table */
45818573097Sslatteng for (charptr = &specials[0]; j--; *tabptr++ = *charptr++);
45918573097Sslatteng
46026bd01f2Sslatteng tabptr = spectab[0]; /* set up pointers to table */
46118573097Sslatteng for (j = 0; i--; j++) {
46218573097Sslatteng spectab[j] = tabptr;
46318573097Sslatteng tabptr += strlen(tabptr) + 1;
46418573097Sslatteng }
46518573097Sslatteng
46618573097Sslatteng } else { /* didn't find table - allocate a null one */
46718573097Sslatteng
46818573097Sslatteng error (!FATAL, "Can't open special character file: %s", specfile);
46918573097Sslatteng spectab = (char **) malloc(2 * sizeof(char*));
47018573097Sslatteng spectab[0] = malloc (2);
47118573097Sslatteng spectab[1] = spectab[0] + 1;
47218573097Sslatteng *spectab[0] = '\0';
47318573097Sslatteng *spectab[1] = '\0';
47418573097Sslatteng }
475af45d5e6Sslatteng }
476af45d5e6Sslatteng
477af45d5e6Sslatteng
478af45d5e6Sslatteng /* just got "p#" command. print the current page and */
t_page(n)479af45d5e6Sslatteng t_page(n) /* do whatever new page functions */
480af45d5e6Sslatteng {
481af45d5e6Sslatteng long ftell();
482af45d5e6Sslatteng int c, m, i;
483af45d5e6Sslatteng char buf[100], *bp;
484af45d5e6Sslatteng
485af45d5e6Sslatteng pgnum[np++] = n;
486af45d5e6Sslatteng pgadr[np] = ftell(fp);
487af45d5e6Sslatteng if (np > npmax)
488af45d5e6Sslatteng npmax = np;
489af45d5e6Sslatteng if (output == 0) {
490af45d5e6Sslatteng output = in_olist(n);
491af45d5e6Sslatteng t_init(1);
492af45d5e6Sslatteng return;
493af45d5e6Sslatteng }
494af45d5e6Sslatteng
495af45d5e6Sslatteng putpage();
496af45d5e6Sslatteng fflush(stdout);
497af45d5e6Sslatteng
498bb5743b1Sslatteng if (clearsc) putchar('');
499af45d5e6Sslatteng if (keepon) {
500af45d5e6Sslatteng t_init(1);
501af45d5e6Sslatteng return;
502af45d5e6Sslatteng }
503af45d5e6Sslatteng next:
504af45d5e6Sslatteng for (bp = buf; (*bp = readch()); )
505af45d5e6Sslatteng if (*bp++ == '\n')
506af45d5e6Sslatteng break;
507af45d5e6Sslatteng *bp = 0;
508af45d5e6Sslatteng switch (buf[0]) {
509af45d5e6Sslatteng case 0:
510af45d5e6Sslatteng done();
511af45d5e6Sslatteng break;
512af45d5e6Sslatteng case '\n':
513af45d5e6Sslatteng output = in_olist(n);
514af45d5e6Sslatteng t_init(1);
515af45d5e6Sslatteng return;
516af45d5e6Sslatteng case '-':
517af45d5e6Sslatteng case 'p':
518af45d5e6Sslatteng m = atoi(&buf[1]) + 1;
519af45d5e6Sslatteng if (fp == stdin) {
520af45d5e6Sslatteng fputs("you can't; it's not a file\n", stderr);
521af45d5e6Sslatteng break;
522af45d5e6Sslatteng }
523af45d5e6Sslatteng if (np - m <= 0) {
524af45d5e6Sslatteng fputs("too far back\n", stderr);
525af45d5e6Sslatteng break;
526af45d5e6Sslatteng }
527af45d5e6Sslatteng np -= m;
528af45d5e6Sslatteng fseek(fp, pgadr[np], 0);
529af45d5e6Sslatteng output = 1;
530af45d5e6Sslatteng t_init(1);
531af45d5e6Sslatteng return;
532af45d5e6Sslatteng case '0': case '1': case '2': case '3': case '4':
533af45d5e6Sslatteng case '5': case '6': case '7': case '8': case '9':
534af45d5e6Sslatteng m = atoi(&buf[0]);
535af45d5e6Sslatteng for (i = 0; i < npmax; i++)
536af45d5e6Sslatteng if (m == pgnum[i])
537af45d5e6Sslatteng break;
538af45d5e6Sslatteng if (i >= npmax || fp == stdin) {
539af45d5e6Sslatteng fputs("you can't\n", stderr);
540af45d5e6Sslatteng break;
541af45d5e6Sslatteng }
542af45d5e6Sslatteng np = i + 1;
543af45d5e6Sslatteng fseek(fp, pgadr[np], 0);
544af45d5e6Sslatteng output = 1;
545af45d5e6Sslatteng t_init(1);
546af45d5e6Sslatteng return;
547af45d5e6Sslatteng case 'o':
548af45d5e6Sslatteng outlist(&buf[1]);
549af45d5e6Sslatteng output = 0;
550af45d5e6Sslatteng t_init(1);
551af45d5e6Sslatteng return;
552af45d5e6Sslatteng case '?':
553af45d5e6Sslatteng fputs("p print this page again\n", stderr);
554af45d5e6Sslatteng fputs("-n go back n pages\n", stderr);
555af45d5e6Sslatteng fputs("n print page n (previously printed)\n", stderr);
556af45d5e6Sslatteng fputs("o... set the -o output list to ...\n", stderr);
557af45d5e6Sslatteng break;
558af45d5e6Sslatteng default:
559af45d5e6Sslatteng fputs("?\n", stderr);
560af45d5e6Sslatteng break;
561af45d5e6Sslatteng }
562af45d5e6Sslatteng goto next;
563af45d5e6Sslatteng }
564af45d5e6Sslatteng
565af45d5e6Sslatteng /* print the contents of the current page. puts out */
putpage()566af45d5e6Sslatteng putpage() /* only the part of the page that's been written on */
567ce133b5eSslatteng { /* unless "margin" is set. */
568af45d5e6Sslatteng int i, j, k;
569af45d5e6Sslatteng
570af45d5e6Sslatteng fflush(stdout);
571ce133b5eSslatteng if (margin) minv = minh = 0;
572af45d5e6Sslatteng for (i = minv; i <= maxv; i++) {
573af45d5e6Sslatteng for (k = maxh; pagebuf[i][k] == ' '; k--)
574af45d5e6Sslatteng ;
575af45d5e6Sslatteng if (k > minh + linelen)
576af45d5e6Sslatteng k = minh + linelen;
577af45d5e6Sslatteng for (j = minh; j <= k; j++)
578af45d5e6Sslatteng putchar(pagebuf[i][j]);
579af45d5e6Sslatteng putchar('\n');
580af45d5e6Sslatteng }
581af45d5e6Sslatteng fflush(stdout);
582af45d5e6Sslatteng }
583af45d5e6Sslatteng
584af45d5e6Sslatteng
t_text(s)585af45d5e6Sslatteng t_text(s) /* print string s as text */
586af45d5e6Sslatteng char *s;
587af45d5e6Sslatteng {
588af45d5e6Sslatteng int c;
589af45d5e6Sslatteng char str[100];
590af45d5e6Sslatteng
591af45d5e6Sslatteng if (!output)
592af45d5e6Sslatteng return;
593af45d5e6Sslatteng while ((c = *s++) != '\n') {
594af45d5e6Sslatteng if (c == '\\') {
595af45d5e6Sslatteng switch (c = *s++) {
596af45d5e6Sslatteng case '\\':
597af45d5e6Sslatteng case 'e':
598af45d5e6Sslatteng put1('\\');
599af45d5e6Sslatteng break;
600af45d5e6Sslatteng case '(':
601af45d5e6Sslatteng str[0] = *s++;
602af45d5e6Sslatteng str[1] = *s++;
603af45d5e6Sslatteng str[2] = '\0';
604af45d5e6Sslatteng put1s(str);
605af45d5e6Sslatteng break;
606af45d5e6Sslatteng }
607af45d5e6Sslatteng } else {
608af45d5e6Sslatteng put1(c);
609af45d5e6Sslatteng }
610083ff42bSslatteng hmot((int)hscale);
611af45d5e6Sslatteng }
612af45d5e6Sslatteng }
613af45d5e6Sslatteng
614af45d5e6Sslatteng
put1s(s)615af45d5e6Sslatteng put1s(s) /* s is a funny char name */
616af45d5e6Sslatteng char *s;
617af45d5e6Sslatteng {
618af45d5e6Sslatteng int i;
619af45d5e6Sslatteng char *p;
620af45d5e6Sslatteng static char prev[10] = "";
621af45d5e6Sslatteng static int previ;
622af45d5e6Sslatteng
623af45d5e6Sslatteng if (!output)
624af45d5e6Sslatteng return;
625af45d5e6Sslatteng if (strcmp(s, prev) != 0) {
626af45d5e6Sslatteng previ = -1;
62718573097Sslatteng for (i = 0; *spectab[i] != '\0'; i += 2)
628af45d5e6Sslatteng if (strcmp(spectab[i], s) == 0) {
629af45d5e6Sslatteng strcpy(prev, s);
630af45d5e6Sslatteng previ = i;
631af45d5e6Sslatteng break;
632af45d5e6Sslatteng }
633af45d5e6Sslatteng }
634af45d5e6Sslatteng if (previ >= 0) {
635083ff42bSslatteng for (hmot((int)-hscale), p = spectab[previ+1]; *p; p++) {
636083ff42bSslatteng hmot((int)hscale);
637af45d5e6Sslatteng store(*p);
638083ff42bSslatteng }
639af45d5e6Sslatteng } else
64018573097Sslatteng prev[0] = '\0';
641af45d5e6Sslatteng }
642af45d5e6Sslatteng
643af45d5e6Sslatteng
put1(c)644af45d5e6Sslatteng put1(c) /* output char c */
645af45d5e6Sslatteng int c;
646af45d5e6Sslatteng {
647af45d5e6Sslatteng if (!output)
648af45d5e6Sslatteng return;
649af45d5e6Sslatteng store(c);
650af45d5e6Sslatteng }
651af45d5e6Sslatteng
652af45d5e6Sslatteng
done()653af45d5e6Sslatteng done()
654af45d5e6Sslatteng {
655af45d5e6Sslatteng output = 1;
656af45d5e6Sslatteng putpage();
657af45d5e6Sslatteng fflush(stdout);
658af45d5e6Sslatteng exit(0);
659af45d5e6Sslatteng }
660af45d5e6Sslatteng
661af45d5e6Sslatteng
readch()662af45d5e6Sslatteng readch ()
663af45d5e6Sslatteng {
664af45d5e6Sslatteng int c;
665af45d5e6Sslatteng static FILE *rcf;
666af45d5e6Sslatteng static nbol; /* 0 if at beginning of a line */
667af45d5e6Sslatteng
668af45d5e6Sslatteng if (rcf == NULL) {
669af45d5e6Sslatteng rcf = fopen ("/dev/tty", "r");
670af45d5e6Sslatteng setbuf (rcf, NULL);
671af45d5e6Sslatteng }
672af45d5e6Sslatteng
673af45d5e6Sslatteng if (!nbol)
674af45d5e6Sslatteng fprintf (stderr, "dterm: "); /* issue prompt */
675af45d5e6Sslatteng if ((c = getc (rcf)) == EOF)
676af45d5e6Sslatteng return 0;
677af45d5e6Sslatteng nbol = (c != '\n');
678af45d5e6Sslatteng return c;
679af45d5e6Sslatteng }
680af45d5e6Sslatteng
681af45d5e6Sslatteng
store(c)682af45d5e6Sslatteng store(c) /* put 'c' in the page at (hpos, vpos) */
683af45d5e6Sslatteng {
684af45d5e6Sslatteng register int i;
685af45d5e6Sslatteng register int j;
686af45d5e6Sslatteng
687af45d5e6Sslatteng
688af45d5e6Sslatteng i = hpos / hscale; /* scale the position to page coordinates */
689af45d5e6Sslatteng j = vpos / vscale;
690af45d5e6Sslatteng
691af45d5e6Sslatteng if (i >= PGWIDTH) i = PGWIDTH - 1; /* don't go over the edge */
692af45d5e6Sslatteng else if (i < 0) i = 0;
693af45d5e6Sslatteng if (j >= PGHEIGHT) j = PGHEIGHT - 1;
694af45d5e6Sslatteng else if (j < 0) j = 0;
695af45d5e6Sslatteng
696af45d5e6Sslatteng pagebuf[j][i] = c; /* write the character */
697af45d5e6Sslatteng
698af45d5e6Sslatteng if (i > maxh) maxh = i; /* update the page bounds */
699af45d5e6Sslatteng if (i < minh) minh = i;
700af45d5e6Sslatteng if (j > maxv) maxv = j;
701af45d5e6Sslatteng if (j < minv) minv = j;
702af45d5e6Sslatteng }
703af45d5e6Sslatteng
704af45d5e6Sslatteng
drawline(dx,dy)7055839e65eSslatteng drawline(dx, dy) /* draw line from here to dx, dy using s */
706af45d5e6Sslatteng int dx, dy;
707af45d5e6Sslatteng {
708af45d5e6Sslatteng register int xd;
709af45d5e6Sslatteng register int yd;
710af45d5e6Sslatteng register int i;
711af45d5e6Sslatteng register int numdots;
712af45d5e6Sslatteng int dirmot, perp;
713af45d5e6Sslatteng int motincr, perpincr;
714af45d5e6Sslatteng int ohpos, ovpos;
715af45d5e6Sslatteng float val, slope;
716af45d5e6Sslatteng float incrway;
717af45d5e6Sslatteng
718af45d5e6Sslatteng ohpos = hpos;
719af45d5e6Sslatteng ovpos = vpos;
720af45d5e6Sslatteng xd = dx / DP;
721af45d5e6Sslatteng yd = dy / DP;
722af45d5e6Sslatteng if (xd == 0) {
723af45d5e6Sslatteng numdots = abs (yd);
724af45d5e6Sslatteng numdots = min(numdots, maxdots);
725af45d5e6Sslatteng motincr = DP * sgn (yd);
726eea66e16Sslatteng put1('|');
727af45d5e6Sslatteng for (i = 0; i < numdots; i++) {
728af45d5e6Sslatteng vmot(motincr);
729eea66e16Sslatteng put1('|');
730af45d5e6Sslatteng }
731af45d5e6Sslatteng } else
732af45d5e6Sslatteng if (yd == 0) {
733af45d5e6Sslatteng numdots = abs (xd);
734bb5743b1Sslatteng numdots = min(numdots, maxdots);
735af45d5e6Sslatteng motincr = DP * sgn (xd);
736eea66e16Sslatteng put1('-');
737af45d5e6Sslatteng for (i = 0; i < numdots; i++) {
738af45d5e6Sslatteng hmot(motincr);
739eea66e16Sslatteng put1('-');
740af45d5e6Sslatteng }
741af45d5e6Sslatteng } else {
742af45d5e6Sslatteng if (abs (xd) > abs (yd)) {
743af45d5e6Sslatteng val = slope = (float) xd/yd;
744af45d5e6Sslatteng numdots = abs (xd);
745af45d5e6Sslatteng dirmot = 'h';
746af45d5e6Sslatteng perp = 'v';
747af45d5e6Sslatteng motincr = DP * sgn (xd);
748af45d5e6Sslatteng perpincr = DP * sgn (yd);
749af45d5e6Sslatteng } else {
750af45d5e6Sslatteng val = slope = (float) yd/xd;
751af45d5e6Sslatteng numdots = abs (yd);
752af45d5e6Sslatteng dirmot = 'v';
753af45d5e6Sslatteng perp = 'h';
754af45d5e6Sslatteng motincr = DP * sgn (yd);
755af45d5e6Sslatteng perpincr = DP * sgn (xd);
756af45d5e6Sslatteng }
75718573097Sslatteng numdots = min(numdots, maxdots);
758af45d5e6Sslatteng incrway = sgn ((int) slope);
759eea66e16Sslatteng put1('*');
760af45d5e6Sslatteng for (i = 0; i < numdots; i++) {
761af45d5e6Sslatteng val -= incrway;
762af45d5e6Sslatteng if (dirmot == 'h')
763af45d5e6Sslatteng hmot(motincr);
764af45d5e6Sslatteng else
765af45d5e6Sslatteng vmot(motincr);
766af45d5e6Sslatteng if (val * slope < 0) {
767af45d5e6Sslatteng if (perp == 'h')
768af45d5e6Sslatteng hmot(perpincr);
769af45d5e6Sslatteng else
770af45d5e6Sslatteng vmot(perpincr);
771af45d5e6Sslatteng val += slope;
772af45d5e6Sslatteng }
773eea66e16Sslatteng put1('*');
774af45d5e6Sslatteng }
775af45d5e6Sslatteng }
776af45d5e6Sslatteng hgoto(ohpos + dx);
777af45d5e6Sslatteng vgoto(ovpos + dy);
778af45d5e6Sslatteng }
779af45d5e6Sslatteng
780af45d5e6Sslatteng
drawwig(s,poly)7815839e65eSslatteng drawwig(s, poly) /* draw wiggly line or polygon, if "poly" set */
782af45d5e6Sslatteng char *s;
7835839e65eSslatteng int poly;
784af45d5e6Sslatteng {
785af45d5e6Sslatteng int x[50], y[50], xp, yp, pxp, pyp;
786af45d5e6Sslatteng float t1, t2, t3, w;
787af45d5e6Sslatteng int i, j, numdots, N;
788af45d5e6Sslatteng char temp[50], *p, *getstr();
789af45d5e6Sslatteng
790af45d5e6Sslatteng p = s;
791af45d5e6Sslatteng for (N = 2; (p=getstr(p,temp)) != NULL && N < sizeof(x)/sizeof(x[0]);) {
792af45d5e6Sslatteng x[N] = atoi(temp);
793af45d5e6Sslatteng p = getstr(p, temp);
794af45d5e6Sslatteng y[N++] = atoi(temp);
795af45d5e6Sslatteng }
7965839e65eSslatteng if (poly) {
7975839e65eSslatteng for (i = 2; i < N; i++)
7985839e65eSslatteng drawline(x[i], y[i]);
7995839e65eSslatteng return;
8005839e65eSslatteng }
801af45d5e6Sslatteng x[0] = x[1] = hpos;
802af45d5e6Sslatteng y[0] = y[1] = vpos;
803af45d5e6Sslatteng for (i = 1; i < N; i++) {
804af45d5e6Sslatteng x[i+1] += x[i];
805af45d5e6Sslatteng y[i+1] += y[i];
806af45d5e6Sslatteng }
807af45d5e6Sslatteng x[N] = x[N-1];
808af45d5e6Sslatteng y[N] = y[N-1];
809af45d5e6Sslatteng pxp = pyp = -9999;
810af45d5e6Sslatteng for (i = 0; i < N-1; i++) { /* interval */
811af45d5e6Sslatteng numdots = (dist(x[i], y[i], x[i+1], y[i+1])
812af45d5e6Sslatteng + dist(x[i+1], y[i+1], x[i+2], y[i+2])) / 2;
813af45d5e6Sslatteng numdots /= DP;
814af45d5e6Sslatteng numdots = min(numdots, maxdots);
815af45d5e6Sslatteng for (j = 0; j < numdots; j++) { /* points within */
816af45d5e6Sslatteng w = (float) j / numdots;
817af45d5e6Sslatteng t1 = 0.5 * w * w;
818af45d5e6Sslatteng w = w - 0.5;
819af45d5e6Sslatteng t2 = 0.75 - w * w;
820af45d5e6Sslatteng w = w - 0.5;
821af45d5e6Sslatteng t3 = 0.5 * w * w;
822af45d5e6Sslatteng xp = t1 * x[i+2] + t2 * x[i+1] + t3 * x[i] + 0.5;
823af45d5e6Sslatteng yp = t1 * y[i+2] + t2 * y[i+1] + t3 * y[i] + 0.5;
824af45d5e6Sslatteng if (xp != pxp || yp != pyp) {
825af45d5e6Sslatteng hgoto(xp);
826af45d5e6Sslatteng vgoto(yp);
827eea66e16Sslatteng put1('*');
828af45d5e6Sslatteng pxp = xp;
829af45d5e6Sslatteng pyp = yp;
830af45d5e6Sslatteng }
831af45d5e6Sslatteng }
832af45d5e6Sslatteng }
833af45d5e6Sslatteng }
834af45d5e6Sslatteng
835af45d5e6Sslatteng
836af45d5e6Sslatteng /* copy next non-blank string from p to temp, update p */
837af45d5e6Sslatteng
getstr(p,temp)838af45d5e6Sslatteng char *getstr(p, temp)
839af45d5e6Sslatteng char *p, *temp;
840af45d5e6Sslatteng {
841af45d5e6Sslatteng while (*p == ' ' || *p == '\t' || *p == '\n')
842af45d5e6Sslatteng p++;
843af45d5e6Sslatteng if (*p == '\0') {
844af45d5e6Sslatteng temp[0] = 0;
845af45d5e6Sslatteng return(NULL);
846af45d5e6Sslatteng }
847af45d5e6Sslatteng while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
848af45d5e6Sslatteng *temp++ = *p++;
849af45d5e6Sslatteng *temp = '\0';
850af45d5e6Sslatteng return(p);
851af45d5e6Sslatteng }
852af45d5e6Sslatteng
853af45d5e6Sslatteng
drawcirc(d)854af45d5e6Sslatteng drawcirc(d)
855af45d5e6Sslatteng {
856af45d5e6Sslatteng int xc, yc;
857af45d5e6Sslatteng
858af45d5e6Sslatteng xc = hpos;
859af45d5e6Sslatteng yc = vpos;
860af45d5e6Sslatteng conicarc(hpos + d/2, -vpos, hpos, -vpos, hpos, -vpos, d/2, d/2);
861af45d5e6Sslatteng hgoto(xc + d); /* circle goes to right side */
862af45d5e6Sslatteng vgoto(yc);
863af45d5e6Sslatteng }
864af45d5e6Sslatteng
865af45d5e6Sslatteng
dist(x1,y1,x2,y2)866af45d5e6Sslatteng dist(x1, y1, x2, y2) /* integer distance from x1,y1 to x2,y2 */
867af45d5e6Sslatteng {
868af45d5e6Sslatteng float dx, dy;
869af45d5e6Sslatteng
870af45d5e6Sslatteng dx = x2 - x1;
871af45d5e6Sslatteng dy = y2 - y1;
872af45d5e6Sslatteng return sqrt(dx*dx + dy*dy) + 0.5;
873af45d5e6Sslatteng }
874af45d5e6Sslatteng
875af45d5e6Sslatteng
drawarc(dx1,dy1,dx2,dy2)876af45d5e6Sslatteng drawarc(dx1, dy1, dx2, dy2)
877af45d5e6Sslatteng {
878af45d5e6Sslatteng int x0, y0, x2, y2, r;
879af45d5e6Sslatteng
880af45d5e6Sslatteng x0 = hpos + dx1; /* center */
881af45d5e6Sslatteng y0 = vpos + dy1;
882af45d5e6Sslatteng x2 = x0 + dx2; /* "to" */
883af45d5e6Sslatteng y2 = y0 + dy2;
884af45d5e6Sslatteng r = sqrt((float) dx1 * dx1 + (float) dy1 * dy1) + 0.5;
885af45d5e6Sslatteng conicarc(x0, -y0, hpos, -vpos, x2, -y2, r, r);
886af45d5e6Sslatteng }
887af45d5e6Sslatteng
888af45d5e6Sslatteng
drawellip(a,b)889af45d5e6Sslatteng drawellip(a, b)
890af45d5e6Sslatteng {
891af45d5e6Sslatteng int xc, yc;
892af45d5e6Sslatteng
893af45d5e6Sslatteng xc = hpos;
894af45d5e6Sslatteng yc = vpos;
895af45d5e6Sslatteng conicarc(hpos + a/2, -vpos, hpos, -vpos, hpos, -vpos, a/2, b/2);
896af45d5e6Sslatteng hgoto(xc + a);
897af45d5e6Sslatteng vgoto(yc);
898af45d5e6Sslatteng }
899af45d5e6Sslatteng
900af45d5e6Sslatteng
conicarc(x,y,x0,y0,x1,y1,a,b)901af45d5e6Sslatteng conicarc(x, y, x0, y0, x1, y1, a, b)
902af45d5e6Sslatteng {
903af45d5e6Sslatteng /* based on Bresenham, CACM Feb 77, pp 102-3 by Chris Van Wyk */
904af45d5e6Sslatteng /* capitalized vars are an internal reference frame */
905af45d5e6Sslatteng long dotcount = 0;
906af45d5e6Sslatteng int xs, ys, xt, yt, Xs, Ys, qs, Xt, Yt, qt,
907af45d5e6Sslatteng M1x, M1y, M2x, M2y, M3x, M3y,
908af45d5e6Sslatteng Q, move, Xc, Yc;
909af45d5e6Sslatteng int ox1, oy1;
910af45d5e6Sslatteng long delta;
911af45d5e6Sslatteng float xc, yc;
912af45d5e6Sslatteng float radius, slope;
913af45d5e6Sslatteng float xstep, ystep;
914af45d5e6Sslatteng
915af45d5e6Sslatteng ox1 = x1;
916af45d5e6Sslatteng oy1 = y1;
917af45d5e6Sslatteng if (a != b) /* an arc of an ellipse; internally, think of circle */
918af45d5e6Sslatteng if (a > b) {
919af45d5e6Sslatteng xstep = (float)a / b;
920af45d5e6Sslatteng ystep = 1;
921af45d5e6Sslatteng radius = b;
922af45d5e6Sslatteng } else {
923af45d5e6Sslatteng xstep = 1;
924af45d5e6Sslatteng ystep = (float)b / a;
925af45d5e6Sslatteng radius = a;
926af45d5e6Sslatteng }
927af45d5e6Sslatteng else {
928af45d5e6Sslatteng /* a circular arc; radius computed from center and first point */
929af45d5e6Sslatteng xstep = ystep = 1;
930af45d5e6Sslatteng radius = sqrt((float)(sqr(x0 - x) + sqr(y0 - y)));
931af45d5e6Sslatteng }
932af45d5e6Sslatteng
933af45d5e6Sslatteng xc = x0;
934af45d5e6Sslatteng yc = y0;
935af45d5e6Sslatteng /* now, use start and end point locations to figure out
936af45d5e6Sslatteng the angle at which start and end happen; use these
937af45d5e6Sslatteng angles with known radius to figure out where start
938af45d5e6Sslatteng and end should be
939af45d5e6Sslatteng */
940af45d5e6Sslatteng slope = atan2((double)(y0 - y), (double)(x0 - x) );
941af45d5e6Sslatteng if (slope == 0.0 && x0 < x)
942af45d5e6Sslatteng slope = 3.14159265;
943af45d5e6Sslatteng x0 = x + radius * cos(slope) + 0.5;
944af45d5e6Sslatteng y0 = y + radius * sin(slope) + 0.5;
945af45d5e6Sslatteng slope = atan2((double)(y1 - y), (double)(x1 - x));
946af45d5e6Sslatteng if (slope == 0.0 && x1 < x)
947af45d5e6Sslatteng slope = 3.14159265;
948af45d5e6Sslatteng x1 = x + radius * cos(slope) + 0.5;
949af45d5e6Sslatteng y1 = y + radius * sin(slope) + 0.5;
950af45d5e6Sslatteng /* step 2: translate to zero-centered circle */
951af45d5e6Sslatteng xs = x0 - x;
952af45d5e6Sslatteng ys = y0 - y;
953af45d5e6Sslatteng xt = x1 - x;
954af45d5e6Sslatteng yt = y1 - y;
955af45d5e6Sslatteng /* step 3: normalize to first quadrant */
956af45d5e6Sslatteng if (xs < 0)
957af45d5e6Sslatteng if (ys < 0) {
958af45d5e6Sslatteng Xs = abs(ys);
959af45d5e6Sslatteng Ys = abs(xs);
960af45d5e6Sslatteng qs = 3;
961af45d5e6Sslatteng M1x = 0;
962af45d5e6Sslatteng M1y = -1;
963af45d5e6Sslatteng M2x = 1;
964af45d5e6Sslatteng M2y = -1;
965af45d5e6Sslatteng M3x = 1;
966af45d5e6Sslatteng M3y = 0;
967af45d5e6Sslatteng } else {
968af45d5e6Sslatteng Xs = abs(xs);
969af45d5e6Sslatteng Ys = abs(ys);
970af45d5e6Sslatteng qs = 2;
971af45d5e6Sslatteng M1x = -1;
972af45d5e6Sslatteng M1y = 0;
973af45d5e6Sslatteng M2x = -1;
974af45d5e6Sslatteng M2y = -1;
975af45d5e6Sslatteng M3x = 0;
976af45d5e6Sslatteng M3y = -1;
977af45d5e6Sslatteng }
978af45d5e6Sslatteng else if (ys < 0) {
979af45d5e6Sslatteng Xs = abs(xs);
980af45d5e6Sslatteng Ys = abs(ys);
981af45d5e6Sslatteng qs = 0;
982af45d5e6Sslatteng M1x = 1;
983af45d5e6Sslatteng M1y = 0;
984af45d5e6Sslatteng M2x = 1;
985af45d5e6Sslatteng M2y = 1;
986af45d5e6Sslatteng M3x = 0;
987af45d5e6Sslatteng M3y = 1;
988af45d5e6Sslatteng } else {
989af45d5e6Sslatteng Xs = abs(ys);
990af45d5e6Sslatteng Ys = abs(xs);
991af45d5e6Sslatteng qs = 1;
992af45d5e6Sslatteng M1x = 0;
993af45d5e6Sslatteng M1y = 1;
994af45d5e6Sslatteng M2x = -1;
995af45d5e6Sslatteng M2y = 1;
996af45d5e6Sslatteng M3x = -1;
997af45d5e6Sslatteng M3y = 0;
998af45d5e6Sslatteng }
999af45d5e6Sslatteng
1000af45d5e6Sslatteng Xc = Xs;
1001af45d5e6Sslatteng Yc = Ys;
1002af45d5e6Sslatteng if (xt < 0)
1003af45d5e6Sslatteng if (yt < 0) {
1004af45d5e6Sslatteng Xt = abs(yt);
1005af45d5e6Sslatteng Yt = abs(xt);
1006af45d5e6Sslatteng qt = 3;
1007af45d5e6Sslatteng } else {
1008af45d5e6Sslatteng Xt = abs(xt);
1009af45d5e6Sslatteng Yt = abs(yt);
1010af45d5e6Sslatteng qt = 2;
1011af45d5e6Sslatteng }
1012af45d5e6Sslatteng else if (yt < 0) {
1013af45d5e6Sslatteng Xt = abs(xt);
1014af45d5e6Sslatteng Yt = abs(yt);
1015af45d5e6Sslatteng qt = 0;
1016af45d5e6Sslatteng } else {
1017af45d5e6Sslatteng Xt = abs(yt);
1018af45d5e6Sslatteng Yt = abs(xt);
1019af45d5e6Sslatteng qt = 1;
1020af45d5e6Sslatteng }
1021af45d5e6Sslatteng
1022af45d5e6Sslatteng /* step 4: calculate number of quadrant crossings */
1023af45d5e6Sslatteng if (((4 + qt - qs) % 4 == 0) && (Xt <= Xs) && (Yt >= Ys))
1024af45d5e6Sslatteng Q = 3;
1025af45d5e6Sslatteng else
1026af45d5e6Sslatteng Q = (4 + qt - qs) % 4 - 1;
1027af45d5e6Sslatteng /* step 5: calculate initial decision difference */
1028af45d5e6Sslatteng delta = sqr(Xs + 1) + sqr(Ys - 1) - sqr(xs) - sqr(ys);
1029af45d5e6Sslatteng /* here begins the work of drawing. */
1030af45d5e6Sslatteng while ((Q >= 0) || ((Q > -2) && ((Xt > Xc) && (Yt < Yc)))) {
1031eea66e16Sslatteng if (dotcount++ % DP == 0) {
1032eea66e16Sslatteng hgoto((int)xc);
1033eea66e16Sslatteng vmot(-vpos-((int)yc));
1034eea66e16Sslatteng put1('*');
1035eea66e16Sslatteng }
1036af45d5e6Sslatteng if (Yc < 0.5) {
1037af45d5e6Sslatteng /* reinitialize */
1038af45d5e6Sslatteng Xs = Xc = 0;
1039af45d5e6Sslatteng Ys = Yc = sqrt((float)(sqr(xs) + sqr(ys)));
1040af45d5e6Sslatteng delta = sqr(Xs + 1) + sqr(Ys - 1) - sqr(xs) - sqr(ys);
1041af45d5e6Sslatteng Q--;
1042af45d5e6Sslatteng M1x = M3x;
1043af45d5e6Sslatteng M1y = M3y;
1044af45d5e6Sslatteng {
1045af45d5e6Sslatteng int T;
1046af45d5e6Sslatteng T = M2y;
1047af45d5e6Sslatteng M2y = M2x;
1048af45d5e6Sslatteng M2x = -T;
1049af45d5e6Sslatteng T = M3y;
1050af45d5e6Sslatteng M3y = M3x;
1051af45d5e6Sslatteng M3x = -T;
1052af45d5e6Sslatteng }
1053af45d5e6Sslatteng } else {
1054af45d5e6Sslatteng if (delta <= 0)
1055af45d5e6Sslatteng if (2 * delta + 2 * Yc - 1 <= 0)
1056af45d5e6Sslatteng move = 1;
1057af45d5e6Sslatteng else
1058af45d5e6Sslatteng move = 2;
1059af45d5e6Sslatteng else if (2 * delta - 2 * Xc - 1 <= 0)
1060af45d5e6Sslatteng move = 2;
1061af45d5e6Sslatteng else
1062af45d5e6Sslatteng move = 3;
1063af45d5e6Sslatteng switch (move) {
1064af45d5e6Sslatteng case 1:
1065af45d5e6Sslatteng Xc++;
1066af45d5e6Sslatteng delta += 2 * Xc + 1;
1067af45d5e6Sslatteng xc += M1x * xstep;
1068af45d5e6Sslatteng yc += M1y * ystep;
1069af45d5e6Sslatteng break;
1070af45d5e6Sslatteng case 2:
1071af45d5e6Sslatteng Xc++;
1072af45d5e6Sslatteng Yc--;
1073af45d5e6Sslatteng delta += 2 * Xc - 2 * Yc + 2;
1074af45d5e6Sslatteng xc += M2x * xstep;
1075af45d5e6Sslatteng yc += M2y * ystep;
1076af45d5e6Sslatteng break;
1077af45d5e6Sslatteng case 3:
1078af45d5e6Sslatteng Yc--;
1079af45d5e6Sslatteng delta -= 2 * Yc + 1;
1080af45d5e6Sslatteng xc += M3x * xstep;
1081af45d5e6Sslatteng yc += M3y * ystep;
1082af45d5e6Sslatteng break;
1083af45d5e6Sslatteng }
1084af45d5e6Sslatteng }
1085af45d5e6Sslatteng }
10865839e65eSslatteng drawline((int)xc-ox1,(int)yc-oy1);
1087af45d5e6Sslatteng }
1088