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