1 #ifndef lint
2 static char *sccsid = "@(#)dhar.c	1.2	CWI 1.2	10/24/85";
3 #endif
4 /*
5  * Drive the Harris 7500 tyepsetter
6  *		    75XX
7  * Other machines of that harris serie will probably run as well with this
8  *
9  * Author: jaap akkerhuis, Oc 1982, Mathematisch Cetrum.
10  *
11  */
12 /*
13 output language from troff:
14 all numbers are character strings
15 
16 sn	size in points
17 fn	font as number from 1-n
18 cx	ascii character x
19 Cxyz	funny char xyz. terminated by white space
20 Hn	go to absolute horizontal position n
21 Vn	go to absolute vertical position n (down is positive)
22 hn	go n units horizontally (relative)
23 vn	ditto vertically
24 nnc	move right nn, then print c (exactly 2 digits!)
25 		(this wart is an optimization that shrinks output file size
26 		 about 35% and run-time about 15% while preserving ascii-ness)
27 Dt ...\n	draw operation 't':
28 	Dl x y		line from here by x,y
29 	Dc d		circle of diameter d with left side here
30 	De x y		ellipse of axes x,y with left side here
31 	Da x y r	arc counter-clockwise by x,y of radius r
32 	D~ x y x y ...	wiggly line by x,y then x,y ...
33 w	paddable words space -- no action needed
34 nb a	end of line (information only -- no action needed)
35 	b = space before line, a = after
36 p	new page begins -- set v to 0
37 tstring print string as plain text
38 #...\n	comment
39 x ...\n	device control functions:
40 	x i	init
41 	x T s	name of device is s
42 	x r n h v	resolution is n/inch
43 		h = min horizontal motion, v = min vert
44 	x p	pause (can restart)
45 	x s	stop -- done for ever
46 	x t	generate trailer
47 	x f n s	font position n contains font s
48 	x H n	set character height to n
49 	x S n	set slant to N
50 
51 	Subcommands like "i" are often spelled out like "init".
52 */
53 /*
54  * MC:jna
55  * The output language signs { and } are not described
56  *
57  */
58 
59 #include	<stdio.h>
60 #include	<ctype.h>
61 #include	<signal.h>
62 
63 #include "../dev.h"
64 #define	NFONT	10
65 
66 int	output	= 0;	/* do we do output at all? */
67 int	nolist	= 0;	/* output page list if > 0 */
68 int	olist[20];	/* pairs of page numbers */
69 int	spage	= 9999;	/* stop every spage pages */
70 int	scount	= 0;
71 
72 struct	dev	dev;
73 struct Font *fontbase[NFONT+1];
74 short	*pstab;
75 int	nsizes;
76 int	nfonts;
77 int	smnt;	/* index of first special font */
78 int	nchtab;
79 char	*chname;
80 short	*chtab;
81 char	*fitab[NFONT+1];
82 char	*widthtab[NFONT+1];	/* widtab would be a better name */
83 char	*codetab[NFONT+1];	/* device codes */
84 short	*fonttab[NFONT+1];	/*MC:jna optional fontcodes */
85 
86 #define	FATAL	1
87 #define	BMASK	0377
88 #define BYTE	8
89 int	dbg	= 0;
90 int	eflag;
91 int	cflag;
92 int	res;		/* input assumed computed according to this resolution */
93 int	tf = 0;		/* output file will be har.in or standout */
94 char	*fontdir	= "/usr/local/lib/ditroff/font";
95 extern char devname[];
96 
97 #define	abs(n)	((n) >= 0 ? (n) : -(n))
98 
99 int	font	= 1;	/* current font */
100 int	hpos;		/* horizontal position where we are supposed to be next (left = 0) */
101 int	lastw;		/*  width of last printed char, (for t_text()) */
102 int	vpos;		/* current vertical position (down positive) */
103 int	horig;		/* h origin of current block; hpos rel to this */
104 int	vorig;
105 int	htrue	= 0;
106 int	vtrue	= 0;
107 int	DX	= 4;	/* step size in x for drawing */
108 int	DY	= 4;	/* step size in y for drawing */
109 int	drawdot	= '.';	/* draw with this character */
110 int	drawsize = 1;	/* shrink by this factor when drawing */
111 			/* drawsize will be set in t_init as well! */
112 
113 main(argc, argv)
114 char *argv[];
115 {
116 	FILE *fp;
117 	int i;
118 	int done();
119 	while (argc > 1 && argv[1][0] == '-') {
120 		switch (argv[1][1]) {
121 		case 'f':
122 		case 'F':
123 			fontdir = argv[2];
124 			argv++;
125 			argc--;
126 			break;
127 		case 't':
128 			tf = 1;	/* stdout */
129 			break;
130 		case 'o':
131 			outlist(&argv[1][2]);
132 			break;
133 		case 'd':
134 			dbg = atoi(&argv[1][2]);
135 			if (dbg == 0) dbg = 1;
136 			break;
137 		case 's':
138 			spage = atoi(&argv[1][2]);
139 			if (spage <= 0)
140 				spage = 9999;
141 			break;
142 		case 'e':
143 			eflag++;
144 			break;
145 		case 'c':
146 			cflag++;
147 			break;
148 		}
149 		argc--;
150 		argv++;
151 	}
152 				/*
153 				 * Stop every 4 pages to prevent the
154 				 * Harris to Cut the paper every 6 feet,
155 				 * wat will likely to be in the middle of
156 				 * a page. Every for page is proved to be
157 				 * reasonable.
158 				 */
159 	if (spage == 0 || 9999)
160 		spage = 4;
161 
162 	if (signal(SIGINT, done) == SIG_IGN) {
163 		signal(SIGINT, SIG_IGN);
164 		signal(SIGQUIT, SIG_IGN);
165 		signal(SIGHUP, SIG_IGN);
166 	} else {
167 		signal(SIGQUIT, done);
168 		signal(SIGHUP, done);
169 	}
170 	signal(SIGTERM, done);
171 	if (argc <= 1)
172 		conv(stdin);
173 	else
174 		while (--argc > 0) {
175 			if (strcmp(*++argv, "-") == 0)
176 				fp = stdin;
177 			else if ((fp = fopen(*argv, "r")) == NULL)
178 				error(FATAL, "can't open %s", *argv);
179 				conv(fp);
180 			fclose(fp);
181 		}
182 	account();
183 	done();
184 }
185 
186 outlist(s)	/* process list of page numbers to be printed */
187 char *s;
188 {
189 	int n1, n2, i;
190 
191 	nolist = 0;
192 	while (*s) {
193 		n1 = 0;
194 		if (isdigit(*s))
195 			do
196 				n1 = 10 * n1 + *s++ - '0';
197 			while (isdigit(*s));
198 		else
199 			n1 = -9999;
200 		n2 = n1;
201 		if (*s == '-') {
202 			s++;
203 			n2 = 0;
204 			if (isdigit(*s))
205 				do
206 					n2 = 10 * n2 + *s++ - '0';
207 				while (isdigit(*s));
208 			else
209 				n2 = 9999;
210 		}
211 		olist[nolist++] = n1;
212 		olist[nolist++] = n2;
213 		if (*s != '\0')
214 			s++;
215 	}
216 	olist[nolist] = 0;
217 	if (dbg)
218 		for (i=0; i<nolist; i += 2)
219 			printf("%3d %3d\n", olist[i], olist[i+1]);
220 }
221 
222 conv(fp)
223 register FILE *fp;
224 {
225 	register int c, k;
226 	int m, n, i, n1, m1;
227 	char str[100], buf[300];
228 
229 	while ((c = getc(fp)) != EOF) {
230 		switch (c) {
231 		case '\n':	/* when input is text */
232 		case ' ':
233 		case 0:		/* occasional noise creeps in */
234 			break;
235 		case '{':	/* push down current environment */
236 			t_push();
237 			break;
238 		case '}':
239 			t_pop();
240 			break;
241 		case '0': case '1': case '2': case '3': case '4':
242 		case '5': case '6': case '7': case '8': case '9':
243 			/* two motion digits plus a character */
244 			hmot((c-'0')*10 + getc(fp)-'0');
245 			put1(getc(fp));
246 			break;
247 		case 'c':	/* single ascii character */
248 			put1(getc(fp));
249 			break;
250 		case 'C':
251 			fscanf(fp, "%s", str);
252 			put1s(str);
253 			break;
254 		case 't':	/* straight text */
255 			fgets(buf, sizeof(buf), fp);
256 			t_text(buf);
257 			break;
258 		case 'D':	/* draw function */
259 			fgets(buf, sizeof(buf), fp);
260 			switch (buf[0]) {
261 			case 'l':	/* draw a line */
262 				sscanf(buf+1, "%d %d", &n, &m);
263 				drawline(n, m, ".");
264 				break;
265 			case 'c':	/* circle */
266 				sscanf(buf+1, "%d", &n);
267 				drawcirc(n);
268 				break;
269 			case 'e':	/* ellipse */
270 				sscanf(buf+1, "%d %d", &m, &n);
271 				drawellip(m, n);
272 				break;
273 			case 'a':	/* arc */
274 				sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
275 				drawarc(n, m, n1, m1);
276 				break;
277 			case '~':	/* wiggly line */
278 				drawwig(buf+1);
279 				break;
280 			default:
281 				error(FATAL, "unknown drawing function %s\n", buf);
282 				break;
283 			}
284 			break;
285 		case 's':
286 			fscanf(fp, "%d", &n);	/* ignore fractional sizes */
287 			setsize(t_size(n));
288 			break;
289 		case 'f':
290 			fscanf(fp, "%s", str);
291 			setfont(t_font(str));
292 			break;
293 		case 'H':	/* absolute horizontal motion */
294 			/* fscanf(fp, "%d", &n); */
295 			while ((c = getc(fp)) == ' ')
296 				;
297 			k = 0;
298 			do {
299 				k = 10 * k + c - '0';
300 			} while (isdigit(c = getc(fp)));
301 			ungetc(c, fp);
302 			hgoto(k);
303 			break;
304 		case 'h':	/* relative horizontal motion */
305 			/* fscanf(fp, "%d", &n); */
306 			while ((c = getc(fp)) == ' ')
307 				;
308 			k = 0;
309 			do {
310 				k = 10 * k + c - '0';
311 			} while (isdigit(c = getc(fp)));
312 			ungetc(c, fp);
313 			hmot(k);
314 			break;
315 		case 'w':	/* word space */
316 			break;
317 		case 'V':
318 			fscanf(fp, "%d", &n);
319 			vgoto(n);
320 			break;
321 		case 'v':
322 			fscanf(fp, "%d", &n);
323 			vmot(n);
324 			break;
325 		case 'p':	/* new page */
326 			fscanf(fp, "%d", &n);
327 			t_page(n);
328 			break;
329 		case 'n':	/* end of line */
330 			while (getc(fp) != '\n')
331 				;
332 			t_newline();
333 			break;
334 		case '#':	/* comment */
335 			while (getc(fp) != '\n')
336 				;
337 			break;
338 		case 'x':	/* device control */
339 			devcntrl(fp);
340 			break;
341 		default:
342 			error(!FATAL, "unknown input character %o %c\n", c, c);
343 			done();
344 		}
345 	}
346 }
347 
348 devcntrl(fp)	/* interpret device control functions */
349 FILE *fp;
350 {
351         char str[20], str1[50], buf[50];
352 	int c, n;
353 
354 	fscanf(fp, "%s", str);
355 	switch (str[0]) {	/* crude for now */
356 	case 'i':	/* initialize */
357 		fileinit();
358 		t_init(0);
359 		break;
360 	case 'T':	/* device name */
361 		fscanf(fp, "%s", devname);
362 		break;
363 	case 't':	/* trailer */
364 		t_trailer();
365 		break;
366 	case 'p':	/* pause -- can restart */
367 		t_reset('p');
368 		break;
369 	case 's':	/* stop */
370 		t_reset('s');
371 		break;
372 	case 'r':	/* resolution assumed when prepared */
373 		fscanf(fp, "%d", &res);
374 		break;
375 	case 'f':	/* font used */
376 		fscanf(fp, "%d %s", &n, str);
377 		fgets(buf, sizeof buf, fp);	/* in case there's a filename */
378 		ungetc('\n', fp);	/* fgets goes too far */
379 		str1[0] = 0;	/* in case there's nothing to come in */
380 		sscanf(buf, "%s", str1);
381 		loadfont(n, str, str1);
382 		break;
383 	/* these don't belong here... */
384 	case 'H':	/* char height */
385 		fscanf(fp, "%d", &n);
386 		t_charht(t_size(n));
387 		break;
388 	case 'S':	/* slant */
389 		fscanf(fp, "%d", &n);
390 		t_slant(n);
391 		break;
392 	}
393 	while ((c = getc(fp)) != '\n')	/* skip rest of input line */
394 		if (c == EOF)
395 			break;
396 }
397 
398 fileinit()	/* read in font and code files, etc. */
399 {
400 	int i, fin, nw;
401 	char *malloc(), *filebase, *p;
402 	char temp[60];
403 
404 	/* open table for device,
405 	/* read in resolution, size info, font info, etc.
406 	/* and set params
407 	*/
408 	sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname);
409 	if ((fin = open(temp, 0)) < 0)
410 		error(FATAL, "can't open tables for %s\n", temp);
411 	read(fin, &dev, sizeof(struct dev));
412 	nfonts = dev.nfonts;
413 	nsizes = dev.nsizes;
414 	nchtab = dev.nchtab;
415 	filebase = malloc(dev.filesize);	/* enough room for whole file */
416 	read(fin, filebase, dev.filesize);	/* all at once */
417 	pstab = (short *) filebase;
418 	chtab = pstab + nsizes + 1;
419 	chname = (char *) (chtab + dev.nchtab);
420 	p = chname + dev.lchname;
421 	for (i = 1; i <= nfonts; i++) {
422 		fontbase[i] = (struct Font *) p;
423 		nw = *p & BMASK;	/* 1st thing is width count */
424 		if (smnt == 0 && fontbase[i]->specfont == 1)
425 			smnt = i;	/* first special font */
426 		p += sizeof(struct Font);	/* that's what's on the beginning */
427 		widthtab[i] = p;
428 		codetab[i] = p + 2 * nw;
429 		fitab[i] = p + 3 * nw;
430 		p += 3 * nw + dev.nchtab + 128 - 32;
431 		if(fontbase[i]->fonttab == 1) {	/*MC:jna There is a fonttable */
432 			fonttab[i] = (short *)p;	/*MC:jna get it */
433 			p += nw * sizeof( short );	/* and skip it */
434 		}
435 		t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
436 		if(dbg > 2) fontprint(i);
437 	}
438 	/*MC:jna
439 	 *
440 	 * Make space for the font cache for NCH characters
441 	 * also reserve space for fonttable, if any is to come
442          *
443 	 */
444 	fontbase[0] = (struct Font *) malloc(3*255 + dev.nchtab + (128-32) + sizeof (struct Font) + 255 * sizeof( short));
445 	widthtab[0] = (char *) fontbase[0] + sizeof (struct Font);
446 	fontbase[0]->nwfont = 255;
447 	fontbase[0]->fonttab = 2;	/* there is room for a fonttable! */
448 	close(fin);
449 }
450 
451 fontprint(i)	/* debugging print of font i (0,...) */
452 {
453 	int j, k, n;
454 	char *p;
455 
456 	printf("font %d:\n", i);
457 	p = (char *) fontbase[i];
458 	n = fontbase[i]->nwfont & BMASK;
459 	printf("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",
460 		p, n, fontbase[i]->specfont, fontbase[i]->namefont, widthtab[i], fitab[i]);
461 	if( fontbase[i]->fonttab == 1)
462 		printf("base fonttab=0%o\n", fonttab[i]);
463 	printf("widths:\n");
464 	for (j=0; j <= n; j++) {
465 		printf(" %2d", widthtab[i][j] & BMASK);
466 		if (j % 20 == 19) printf("\n");
467 	}
468 	printf("\ncodetab:\n");
469 	for (j=0; j <= n; j++) {
470 		printf(" %2d", codetab[i][j] & BMASK);
471 		if (j % 20 == 19) printf("\n");
472 	}
473 	printf("\nfitab:\n");
474 	for (j=0; j <= dev.nchtab + 128-32; j++) {
475 		printf(" %2d", fitab[i][j] & BMASK);
476 		if (j % 20 == 19) printf("\n");
477 	}
478 	if(fontbase[i]->fonttab == 1) {
479 		printf("\nfonttab:\n");
480 		for (j=0; j <= n; j++) {
481 			printf(" %d", fonttab[i][j] );
482 			if (j % 20 == 19) printf("\n");
483 		}
484 	}
485 	printf("\n");
486 }
487 
488 loadfont(n, s, s1)	/* load font info for font s on position n (0...) */
489 int n;
490 char *s, *s1;
491 {
492 	char temp[60];
493 	int fin, nw, norig, forig;
494 	char *p;
495 
496 	if (n < 0 || n > NFONT)
497 		error(FATAL, "illegal fp command %d %s", n, s);
498 	if (strcmp(s, fontbase[n]->namefont) == 0)
499 		return;
500 	if (s1 == NULL || s1[0] == '\0')
501 		sprintf(temp, "%s/dev%s/%s.out", fontdir, devname, s);
502 	else
503 		sprintf(temp, "%s/%s.out", s1, s);
504 	if ((fin = open(temp, 0)) < 0)
505 		error(FATAL, "can't open font table %s", temp);
506 	norig = fontbase[n]->nwfont & BMASK;
507 	forig = fontbase[n]->fonttab;
508 if(dbg > 3)
509 	printf("nworig, %d, fonttaborig %d\n", norig, forig);
510 	/*
511 	 *MC:jna norig is the original amount of chars in
512 	 * the (premounted) font)
513 	 *
514 	 * first geuss there is no fonttab
515 	 */
516 	read(fin, fontbase[n], 3*norig + nchtab+128-32 + sizeof(struct Font));
517 	if ((fontbase[n]->nwfont & BMASK) > norig || (forig == 0 && fontbase[n]->fonttab == 1))
518 		error(FATAL, "Font %s too big for position %d\n", s, n);
519 		/*
520 		 *MC:jna This means it is wise to make the default mounted
521 		 * fonts larger then any other mounttable fonts.
522 		 * And because of the kludge with the fonttable,
523 		 * Make sure that they all contain fonttables!
524 		 * It will make your life easier.
525 		 */
526 	nw = fontbase[n]->nwfont & BMASK;
527 if(dbg > 3)
528 	printf("nw %d\n", nw);
529 	if(fontbase[n]->fonttab == 1) {
530 		lseek(fin, 0L, 0);
531 		read(fin, fontbase[n], 3*norig + nchtab+128-32 + nw*sizeof(short) + sizeof(struct Font));
532 		/*
533 		 * There turned out to be a fonttab, so we have to read it in
534 		 *MC:jna a bit stupid, but the laziest way (for me)
535 		 */
536 	}
537 	close(fin);
538 	widthtab[n] = (char *) fontbase[n] + sizeof(struct Font);
539 	codetab[n] = (char *) widthtab[n] + 2 * nw;
540 	fitab[n] = (char *) widthtab[n] + 3 * nw;
541 	if(fontbase[n]->fonttab == 1)
542 		fonttab[n] = (short *) (widthtab[n] + 3*nw + nchtab+128-32);
543 	t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
544 	fontbase[n]->nwfont = norig;	/* so can later use full original size */
545 	if(fontbase[n]->fonttab == 0 && forig != 0)
546 		fontbase[n]->fonttab = 2;
547 					/* so we signal that there is place
548 					 * for a fonttab! */
549 
550 	if (dbg > 2) fontprint(n);
551 }
552 
553 done()
554 {
555 	t_reset('s');
556 	exit(0);
557 }
558 
559 extern int ex();
560 
561 /*VARARGS*/
562 error(f, s, a1, a2, a3, a4, a5, a6, a7)
563 int f;
564 {
565 	fprintf(stderr, "dhar: ");
566 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
567 	fprintf(stderr, "\n");
568 	fflush(stderr);
569 	if (f) {
570 		ex();
571 		exit(1);
572 	}
573 }
574 
575 /******************************************************************************
576  ******************************************************************************
577  *
578  * Here begins the stuff that really depends on the harris
579  *
580  * For the time being, no use is made of the ruling functions of the Harris
581  *
582  ******************************************************************************
583  ******************************************************************************
584  */
585 
586 /*
587  * The basic idea is to delay the output as long as possible
588  * until you really have to.
589  * Until that time we just keep a machine status.
590  *
591  */
592 
593 #include "hcodes.h"
594 
595 char	devname[20] = "har";
596 int	fcut;
597 int	nocutting;
598 int	papuse;
599 char	harcode;
600 
601 t_init(reinit)	/* initialize device */
602 int reinit;
603 {
604 	register int i;
605 	extern int size;
606 
607 	hpos = vpos = 0;
608 
609 	if( strcmp( devname, "har") != NULL )
610 		error(FATAL, "This input is not for the harris");
611 
612 	if (!tf)
613 		if ( ( tf = creat("@har.in", 0664)) < 0)
614 			error(FATAL, "Cannot create outputfile");
615 
616 	/* if there is a drawing character, use it */
617 	for ( i = 0; i < nchtab; i++)
618 		if (strcmp(&chname[chtab[i]], "l.") == 0)
619 			break;
620 	if ( i < nchtab) {
621 		drawdot = i + 128;
622 		drawsize = 1;
623 	} else {
624 		drawdot = '.';
625 		drawsize = 3; 	/* 1/3 size */
626 	}
627 
628 	output = 1;
629 
630 	oput(VMV); oput(0); oput(0);
631 				/* See Harris Manual appendix D */
632 	oput(HPO);oput(0);oput(0);
633 
634 		/* some initial size */
635 	size = 10;
636 	putsize();
637 	putfont(999);
638 	oput(STA);oput(0);oput(0360);
639 
640 	if( eflag ) {
641 		operator("Translating");
642 		oput(EST);	/* enable slave Translator */
643 		fprintf(stderr,"Slave code translator enabled\n");
644 	} else
645 		operator("dhar started");
646 
647 	oput(OB0);		/* reset oblique */
648 	oput(NAD);		/* No automatic displacement */
649 	output = 0;
650 }
651 
652 /*
653  * The reason of struct state is never explained by bwk
654  * but it looks like an stack of environments being pushed and popped
655  *
656  */
657 
658 #define	MAXSTATE	5
659 
660 struct state {
661 	int	ssize;
662 	int	sfont;
663 	int	shpos;
664 	int	svpos;
665 	int	shorig;
666 	int	svorig;
667 };
668 struct	state	state[MAXSTATE];
669 struct	state	*statep = state;
670 
671 t_push()	/* begin a new block */
672 {
673 	extern size;
674 
675 	error(!FATAL, "Different environment entered!");
676 	hflush();
677 	statep->ssize = size;
678 	statep->sfont = font;
679 	statep->shorig = horig;
680 	statep->svorig = vorig;
681 	statep->shpos = hpos;
682 	statep->svpos = vpos;
683 	horig = hpos;
684 	vorig = vpos;
685 	hpos = vpos = 0;
686 	if (statep++ >= state+MAXSTATE)
687 		error(FATAL, "{ nested too deep");
688 	hpos = vpos = 0;
689 }
690 
691 t_pop()	/* pop to previous state */
692 {
693 	extern size;
694 	if (--statep < state)
695 		error(FATAL, "extra }");
696 	size = statep->ssize;
697 	font = statep->sfont;
698 	hpos = statep->shpos;
699 	vpos = statep->svpos;
700 	horig = statep->shorig;
701 	vorig = statep->svorig;
702 }
703 
704 int	pageno	= 0;
705 
706 t_page(n)	/* do whatever new page functions */
707 {
708 	int i;
709 
710 	if (output) {
711 		papuse++;
712 		/*
713 		 * accounting in pages, for the time being.
714 		 * New harprot should do the real accounting
715 		 */
716 		if (++scount >= spage) {
717 			t_reset('p');
718 			scount = 0;
719 		}
720 	}
721 	vpos = 0;
722 	output = 1;
723 	++pageno;
724 	if (nolist == 0)
725 		return;	/* no -o specified */
726 	output = 0;
727 	for (i = 0; i < nolist; i += 2)
728 		if (n >= olist[i] && n <= olist[i+1]) {
729 			output = 1;
730 			break;
731 		}
732 }
733 
734 t_newline()	/* do whatever for the end of a line */
735 {
736 	hpos = 0;	/* because we're now back at the left margin */
737 }
738 
739 /*
740  * A PSZ command on the Harris will change the horizontal & vertical size
741  * A HPZ command will change just the Horizontal size.
742  *
743  * so size will contain horizontal size, and versize the vertical
744  */
745 int	size;		/* current sizenumber (a legal index in pstab) */
746 int	horsize;	/* current horizontal size */
747 int	versize;	/* current vertcal size */
748 int	vsizeflag;	/* if set, versize differs from size */
749 
750 t_size(n)	/* convert integer to internal size number*/
751 int n;
752 {
753 	int i;
754 
755 	if (n <= pstab[0])
756 		return(1);
757 	else if (n >= pstab[nsizes-1])
758 		return(nsizes);
759 	for (i = 0; n > pstab[i]; i++)
760 		;
761 	return(i+1);
762 }
763 
764 t_charht(n)	/* set character height to n */
765 int n;
766 {
767 	versize = pstab[n-1];
768 	if( versize != horsize )
769 		vsizeflag = 1;
770 	putsize();
771 }
772 
773 int sltab[]	= {   0,  9,  12,  15, -1};	/* possible slanting factors */
774 int slctab[]	= { OB0, OB1, OB2, OB3 };	/* slanting codes */
775 int slant;		/* current general slanting factor (of slant cmd) */
776 int fslant;		/* slanting factor of current font */
777 
778 /*
779  * current font has to be slanted, the slant will be set to fslant.
780  * if the has been a slant command, the slant will be set to "slant",
781  * overiding the fslant.
782  * if slant is reset to 0, and there fslant != 0, slant will be set to "fslant"
783  *
784  * fslant will be manupulated by setfont (slanting can be an attribute
785  * to a (Harris-)font.
786  *
787  * There are to many slants in this comment
788  */
789 
790 t_slant(n)	/* do slant cmd */
791 int n;
792 {	slant = n;
793 	setslant(n);
794 }
795 
796 setslant(n)	/* set slant to n */
797 int n;
798 {	int j;
799 	static int aslant;	/* the actual slanting factor */
800 
801 	if( n == aslant)
802 		return;
803 	if( n == 0 && fslant) {		/* back to slant of font */
804 		setslant( fslant );
805 		return;
806 	}
807 	for (j = 0; n > ( aslant = sltab[j]); j++)
808 		if ( aslant == -1) {
809 			aslant = sltab[--j];
810 			break;
811 		}
812 	hflush();
813 	oput( slctab[j] );
814 	if (dbg)
815 		printf("slant to %d\n", aslant);
816 }
817 
818 slantfont(n)	/* set fontslant */
819 int n;
820 {
821 	fslant = n;
822 	if(slant)
823 		return;		/* slant of slanting command
824 				 * overrides fslant */
825 	setslant( fslant);	/* set slanting */
826 }
827 
828 t_font(s)	/* convert string to internal font number */
829 char *s;
830 {
831 	int n;
832 
833 	n = atoi(s);
834 	if (n < 0 || n > nfonts)
835 		n = 1;
836 	return(n);
837 }
838 
839 t_text(s)	/* print string s as text, the real \! implemantation */
840 char *s;
841 {
842 	int c, w;
843 	char str[100];
844 
845 	error(!FATAL, "t_text not well implented (yet)!");
846 	if (!output)
847 		return;
848 	while (c = *s++) {
849 		if (c == '\\') {
850 			switch (c = *s++) {
851 			case '\\':
852 			case 'e':
853 				put1('\\');
854 				break;
855 			case '(':
856 				str[0] = *s++;
857 				str[1] = *s++;
858 				str[2] = '\0';
859 				put1s(str);
860 				break;
861 			}
862 		} else {
863 			put1(c);
864 		}
865 		hmot(lastw);
866 		if (dbg) printf("width = %d\n", lastw);
867 	}
868 }
869 
870 t_reset(c)
871 {
872 	int n;
873 
874 	if (output)
875 		/*
876 		 papuse++
877 		 */
878 		 ;
879 	switch(c) {
880 	case 'p':
881 		cut();	/*
882 			 * interpret pauses as comment for cutting
883 			 * the paper
884 			 */
885 		if(dbg)
886 			printf("reset p\n");
887 		break;
888 	case 's':
889 		cut();
890 		nocutting++;
891 		if(dbg)
892 			printf("reset s\n");
893 		ex();
894 		break;
895 	default:
896 		error(!FATAL, "Unknown reset function");
897 		break;
898 	}
899 }
900 
901 cut()
902 {
903 	if (cflag || nocutting)
904 		return;
905 	hflush();
906 	oput(CUT);
907 	hpos = 0;
908 	fcut = 1;
909 	if (dbg)
910 		printf("Cut\n");
911 }
912 
913 account()	/* record paper use */
914 {
915 	/* Don somewhere els */
916 }
917 
918 t_trailer()
919 {
920 }
921 
922 hflush()	/* do the actual motion */
923 {
924 	if (!output)
925 		return;
926 	hor_move( hpos - htrue );
927 }
928 
929 hor_move( amount )
930 int amount;
931 {	int high, low;
932 
933 #ifdef VAX
934 	if ( abs(amount) > 0177777)
935 		error(FATAL, "Impossible escape");
936 #endif
937 	if ( amount == 0 && harcode == 0)
938 		return;		/* really nothing to do */
939 	if(dbg > 1)
940 		printf("h_move %d\n", amount);
941 	low = amount & BMASK;
942 	high = ( amount >> BYTE) & BMASK;
943 	/*
944 	 * if there is a code wating for output,
945 	 * send that one to be output, plus the movement,
946 	 * else send the MAB
947 	 * and the movement
948 	 */
949 	oput( harcode ? harcode : MAB);
950 	harcode = 0;
951 	oput(high);
952 	oput(low);
953 	htrue = hpos;
954 }
955 
956 
957 hmot(n)
958 {
959 	hpos += n;
960 }
961 
962 hgoto(n)
963 {
964 	hpos = n;
965 }
966 
967 vgoto(n)
968 {
969 	vmot(n - vpos);
970 }
971 
972 vmot(n)	/* generate n units of vertical motion */
973 int n;
974 {
975 	if (!output)
976 		return;
977 	if (n != 0) {
978 		ver_move( n );
979 		vpos += n;
980 	}
981 }
982 
983 ver_move( amount )
984 int amount;
985 {	int high, low;
986 
987 #ifdef VAX
988 	if ( abs(amount) > 0177777)
989 		error(FATAL, "Impossible leading");
990 #endif
991 	if(dbg > 1)
992 		printf("v_move %d\n", amount);
993 	low = amount & BMASK;
994 	high = ( amount >> BYTE) & BMASK;
995 	hflush();
996 	oput(VMV);
997 	oput(high);
998 	oput(low);
999 }
1000 
1001 put1s(s)	/* s is a funny char name */
1002 char *s;
1003 {
1004 	int i;
1005 
1006 	if (!output)
1007 		return;
1008 /*
1009 	if(strcmp("ul", s) == 0) {
1010 		set_ul();
1011 		return;
1012 	}
1013 	if(strcmp("ru", s) == 0) {
1014 		set_ru();
1015 		return;
1016 	}
1017 */
1018 	for (i = 0; i < nchtab; i++)
1019 		if (strcmp(&chname[chtab[i]], s) == 0)
1020 			break;
1021 /*
1022 printf("i+128: %d,s: %s, chname: %s\n", i+128, s, &chname[chtab[i]]);
1023 */
1024 	if (i < nchtab)
1025 		put1(i + 128);
1026 	else
1027 		if(dbg)
1028 			printf("Special char %s doesn't exist\n", s);
1029 }
1030 
1031 /*
1032  * The Harris doesn'nt have a proper underrule or rule
1033  *
1034  * Try to generate one with the RULE command.
1035  *
1036  */
1037 
1038 #define UL_DOWN	7	/* 7 half decipoints at pointsize 10 */
1039 
1040 set_ul()
1041 {	int move;
1042 	int tmp;
1043 
1044 	hflush();
1045 	move = UL_DOWN * versize;
1046 	ver_move( move);
1047 	tmp = get_width("ul") / 2;
1048 		/*
1049 		 * we assume that dev.unitwidth is 10, so getwidth
1050 		 * will return the value in half decipoints!
1051 		 */
1052 	set_line(tmp);
1053 	ver_move( -move);
1054 }
1055 
1056 #define RU_DOWN	1	/* 2 half decipoints at pointsize 10 */
1057 
1058 set_ru()
1059 {
1060 	int tmp, move;
1061 
1062 	hflush();
1063 	move = RU_DOWN * versize;
1064 	ver_move( move);
1065 	tmp = get_width("ul") / 2;
1066 	set_line(tmp);
1067 	ver_move( -move);
1068 }
1069 
1070 #define HEIGHT	6	/* thickness (decipoints) at pointsize 10 */
1071 #define MIN_VAL	2	/* Minimum value for rule height & length */
1072 #define MAX_H	720	/* Maximum for height */
1073 #define MAX_L	8160	/* Maximum length of the SMC 68 Pica machine */
1074 
1075 /*
1076  * set line of length decipoints.
1077  */
1078 
1079 set_line( length )
1080 int length;
1081 {
1082 	int height;
1083 	char one, two, three, four;
1084 
1085 	/*
1086 	printf("Line %d decipoints\n", i);
1087 	*/
1088 
1089 	height = (HEIGHT * versize + dev.unitwidth/2) / dev.unitwidth;
1090 	if ( height < MIN_VAL)
1091 		height = MIN_VAL;
1092 	if (height > MAX_H)
1093 		height = MAX_H;
1094 	if (length > MAX_L)
1095 		length = MAX_L;
1096 	if (dbg)
1097 		printf("Line: length %d height %d\n", length, height);
1098 
1099 	one = ( height >> BYTE ) | RUL;
1100 	two = height & BMASK;
1101 	three = length >> BYTE;
1102 	four = length & BMASK;
1103 	oput(one); oput(two); oput(three); oput(four);
1104 }
1105 
1106 /*
1107  * get the width of a char, to be used only by set_ul() and set-ru()
1108  */
1109 
1110 int
1111 get_width( s )
1112 char *s;
1113 {
1114 	int c;
1115 	int width;
1116 	int j, i, k, ofont;
1117 	char *pw;
1118 
1119 	for (c = 0; c < nchtab; c++)
1120 		if (strcmp(&chname[chtab[c]], s) == 0)
1121 			break;
1122 	if (c < nchtab)
1123 		c += 128-32;
1124 	if (c <= 0 || c >= nchtab + 128-32) {
1125 		if (dbg) printf("non-exist 0%o\n", c+32);
1126 		return;
1127 	}
1128 	k = ofont = font;
1129 	i = fitab[font][c] & BMASK;
1130 	if (i != 0) {	/* it's on this font */
1131 		pw = widthtab[font];
1132 	} else if (smnt > 0) {		/* on special (we hope) */
1133 		for (k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1))
1134 			/*
1135 			 * Look for the character, start at the special font
1136 			 * and search further in a wrap around manner
1137 			 */
1138 			if ((i = fitab[k][c] & BMASK) != 0) {
1139 				pw = widthtab[k];
1140 				setfont(k);
1141 				break;
1142 			}
1143 	}
1144 	if (i == 0 || (width = pw[i] & BMASK) == 0 || k > nfonts) {
1145 		/* device drivers do width & 077, not really necessary */
1146 		if (dbg) {
1147 				printf("Width not found \\(%s\n", s);
1148 		}
1149 		return;
1150 	}
1151 	width = (width * horsize + dev.unitwidth/2) / dev.unitwidth;
1152 	if (font != ofont)
1153 		setfont(ofont);
1154 	return( width);
1155 }
1156 
1157 /* font position info: */
1158 
1159 struct {
1160 	char *name;
1161 	int number;
1162 } fontname[NFONT+1];
1163 
1164 put1(c)	/* output char c */
1165 int c;
1166 {
1167 	char *pw;
1168 	register char *p;
1169 	register int i, k;
1170 	int j, ofont, code;
1171 	short f;
1172 
1173 	if (!output)
1174 		return;
1175 	c -= 32;
1176 	if (c <= 0) {
1177 		if (dbg) printf("non-exist 0%o\n", c+32);
1178 		lastw = widthtab[font][0] * pstab[size-1] /dev.unitwidth;
1179 		return;
1180 	}
1181 	k = ofont = font;
1182 	i = fitab[font][c] & BMASK;
1183 	if (i != 0) {	/* it's on this font */
1184 		p = codetab[font];
1185 		pw = widthtab[font];
1186 	} else if (smnt > 0) {		/* on special (we hope) */
1187 		for (k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1))
1188 			/*
1189 			 * Look for the character, start at the special font
1190 			 * and search further in a wrap around manner
1191 			 */
1192 			if ((i = fitab[k][c] & BMASK) != 0) {
1193 				p = codetab[k];
1194 				pw = widthtab[k];
1195 				setfont(k);
1196 				break;
1197 			}
1198 	}
1199 	if (i == 0 || (code = p[i] & BMASK) == 0 || k > nfonts) {
1200 		if (dbg) {
1201 			if (isprint(c+32) && isascii(c+32))
1202 				printf("not found %c\n", c+32);
1203 			else
1204 				printf("not found \\(%s\n", &chname[chtab[c -128+32]]);
1205 		}
1206 		return;
1207 	}
1208 	if (fontbase[k]->fonttab == 1)
1209 		f = fonttab[k][i];
1210 	else
1211 		f = fontname[k].number;
1212 	hflush();
1213 	if (dbg) {
1214 		if (isprint(c+32) && isascii(c+32)) { /* My God! */
1215 			printf("%c %d %d\n", c+32, code, f);
1216 		}
1217 		else
1218 			printf("\\(%s %d %d\n", &chname[chtab[c -128+32]], code, f);
1219 	}
1220 	if(code == 0 || code > 0200) {
1221 		error(FATAL,"Illegal code 0%o found for char %03o\n", code, c+32);
1222 	}
1223 	putcode(code, f);	/* character is < 254 */
1224 	if (font != ofont)	/* char on special font, reset	*/
1225 		setfont(ofont);
1226 	lastw = pw[i] & BMASK;
1227 /*HIRO*/
1228 if( dbg)
1229 	fprintf(stderr,"lastw %d pw[i] %d\n", lastw,pw[i]);
1230 	lastw = (lastw * pstab[size-1] + dev.unitwidth/2) / dev.unitwidth;
1231 }
1232 
1233 putcode(code, f)
1234 char code; short f;
1235 {
1236 	static short phfont;
1237 
1238 #ifdef VAX
1239 	if ( f > 0177777)
1240 		error(FATAL, "Impossible font selected");
1241 #endif
1242 
1243 	if( harcode) {	/* if character pending */
1244 		hflush();	/* update position and flush pending char */
1245 	}
1246 	if ( f != phfont ) {
1247 		if(dbg > 1)
1248 			printf("font to %d\n", f);
1249 		putfont(f);
1250 	}
1251 	harcode = code;
1252 	phfont = f;
1253 }
1254 
1255 putfont(f)
1256 int f;
1257 {	int high, low;
1258 
1259 	low = f & BMASK;
1260 	high = (f >> BYTE ) & BMASK;
1261 	oput(FNT);
1262 	oput(high);
1263 	oput(low);
1264 }
1265 
1266 setsize(n)	/* set point size to a true pointsize */
1267 int n;
1268 {
1269 
1270 	if (!output)
1271 		return;
1272 	horsize = pstab[n-1];
1273 	vsizeflag = 0;
1274 	size = n;
1275 	putsize();
1276 }
1277 
1278 /*
1279  * Do the actual sizechange(s).
1280  */
1281 
1282 putsize()
1283 {
1284 	if(!vsizeflag) {
1285 		flushchar();
1286 		sizecmd( PSZ, horsize);
1287 	}
1288 	else {
1289 		flushchar();
1290 		sizecmd( PSZ, versize);
1291 		sizecmd( HPZ, horsize);
1292 	}
1293 }
1294 
1295 sizecmd( cmd, n)
1296 int	cmd, n;
1297 {
1298 	int i, low, high;
1299 
1300 	i = 10 * n;
1301 	if(dbg)
1302 		printf("size to %d\n", n);
1303 	if( i > 01777)
1304 		error(FATAL, "Impossible pointsize requested");
1305 	low = i & BMASK;
1306 	high = (i >> BYTE) & BMASK;
1307 	if( high > 03 )
1308 		error(FATAL, "system error in point size cmd");
1309 	oput( cmd | high);
1310 	oput(low);
1311 }
1312 
1313 t_fp(n, s, si)	/* font position n now contains font s, intname si */
1314 int n;
1315 char *s, *si;
1316 {
1317 	fontname[n].name = s;
1318 	fontname[n].number = atoi(si);
1319 }
1320 
1321 setfont(n)	/* set font to n (internal)*/
1322 int n;
1323 {
1324 	if (!output)
1325 		return;
1326 	if (n < 0 || n > NFONT)
1327 		error(FATAL, "illegal font %d\n", n);
1328 	font = n;
1329 	slantfont(fontbase[n]->slant & BMASK);
1330 }
1331 
1332 /*
1333 putint(n)
1334 {
1335 	if (dbg) {
1336 		printf("%02d\n", n);
1337 		return;
1338 	}
1339 	putc(n>>8, tf);
1340 	putc(n, tf);
1341 }
1342 */
1343