1 #ifndef lint
2 static char sccsid[] = "tc.c	(CWI)	1.1	85/03/26";
3 #endif lint
4 /*
5  *	drive 4014 scope
6  */
7 
8 /*
9 output language from troff:
10 all numbers are character strings
11 
12 sn	size in points
13 fn	font as number from 1-n
14 cx	ascii character x
15 Cxyz	funny char xyz. terminated by white space
16 Hn	go to absolute horizontal position n
17 Vn	go to absolute vertical position n (down is positive)
18 hn	go n units horizontally (relative)
19 vn	ditto vertically
20 nnc	move right nn, then print c (exactly 2 digits!)
21 		(this wart is an optimization that shrinks output file size
22 		 about 35% and run-time about 15% while preserving ascii-ness)
23 Dt ...\n	draw operation 't':
24 	Dl x y		line from here by x,y
25 	Dc d		circle of diameter d with left side here
26 	De x y		ellipse of axes x,y with left side here
27 	Da x y r	arc counter-clockwise by x,y of radius r
28 	D~ x y x y ...	wiggly line by x,y then x,y ...
29 nb a	end of line (information only -- no action needed)
30 	b = space before line, a = after
31 p	new page begins -- set v to 0
32 #...\n	comment
33 x ...\n	device control functions:
34 	x i	init
35 	x T s	name of device is s
36 	x r n h v	resolution is n/inch
37 		h = min horizontal motion, v = min vert
38 	x p	pause (can restart)
39 	x s	stop -- done for ever
40 	x t	generate trailer
41 	x f n s	font position n contains font s
42 	x H n	set character height to n
43 	x S n	set slant to N
44 
45 	Subcommands like "i" are often spelled out like "init".
46 */
47 
48 #include	<stdio.h>
49 #include	<signal.h>
50 #include	<ctype.h>
51 
52 #include "../dev.h"
53 #define	NFONT	10
54 
55 int	output	= 0;	/* do we do output at all? */
56 int	nolist	= 0;	/* output page list if > 0 */
57 int	olist[20];	/* pairs of page numbers */
58 
59 int	erase	= 1;
60 float	aspect	= 1.5;	/* default aspect ratio */
61 int	(*sigint)();
62 int	(*sigquit)();
63 
64 struct dev dev;
65 struct font *fontbase[NFONT];
66 short	psizes[]	={ 11, 16, 22, 36, 0};	/* approx sizes available */
67 short	*pstab		= psizes;
68 int	nsizes	= 4;
69 int	pscode[]	={ ';', ':', '9', '8'};
70 int	nfonts;
71 int	smnt;	/* index of first special font */
72 int	nchtab;
73 char	*chname;
74 short	*chtab;
75 char	*fitab[NFONT];
76 char	*widthtab[NFONT];	/* widtab would be a better name */
77 char	*codetab[NFONT];	/* device codes */
78 
79 #define	FATAL	1
80 #define	BMASK	0377
81 int	keepon 	= 0;
82 int	dbg	= 0;
83 long	lineno	= 0;
84 int	res	= 972;		/* input assumed computed according to this resolution */
85 				/* initial value to avoid 0 divide */
86 FILE	*tf	= stdout;	/* output file */
87 char	*fontdir	= "/usr/lib/font";
88 extern char devname[];
89 
90 FILE *fp	= stdin;	/* input file pointer */
91 
92 main(argc, argv)
93 char *argv[];
94 {
95 	char buf[BUFSIZ];
96 	float atof();
97 	int done();
98 
99 	setbuf(stdout, buf);
100 	while (argc > 1 && argv[1][0] == '-') {
101 		switch (argv[1][1]) {
102 		case 'T':
103 			if (strcmp(&argv[1][2], "cat") == 0) {	/* use the old one */
104 				if (fork() == 0) {
105 					execv("/usr/bin/oldtc", argv);
106 					fprintf(stderr, "tc: can't find oldtc\n");
107 				}
108 				wait();
109 				exit(1);
110 			}
111 			break;
112 		case 'a':
113 			aspect = atof(&argv[1][2]);
114 			break;
115 		case 'e':
116 			erase = 0;
117 			break;
118 		case 'o':
119 			outlist(&argv[1][2]);
120 			break;
121 		case 'd':
122 			dbg = atoi(&argv[1][2]);
123 			if (dbg == 0) dbg = 1;
124 			break;
125 		case 'c':
126 			keepon = 1;
127 			break;
128 		}
129 		argc--;
130 		argv++;
131 	}
132 
133 	sigint = signal(SIGINT, done);
134 	sigquit = signal(SIGQUIT, SIG_IGN);
135 	if (argc <= 1)
136 		conv(stdin);
137 	else
138 		while (--argc > 0) {
139 			if (strcmp(*++argv, "-") == 0)
140 				fp = stdin;
141 			else if ((fp = fopen(*argv, "r")) == NULL)
142 				error(FATAL, "can't open %s", *argv);
143 			conv(fp);
144 			fclose(fp);
145 		}
146 	done();
147 }
148 
149 outlist(s)	/* process list of page numbers to be printed */
150 char *s;
151 {
152 	int n1, n2, i;
153 
154 	nolist = 0;
155 	while (*s) {
156 		n1 = 0;
157 		if (isdigit(*s))
158 			do
159 				n1 = 10 * n1 + *s++ - '0';
160 			while (isdigit(*s));
161 		else
162 			n1 = -9999;
163 		n2 = n1;
164 		if (*s == '-') {
165 			s++;
166 			n2 = 0;
167 			if (isdigit(*s))
168 				do
169 					n2 = 10 * n2 + *s++ - '0';
170 				while (isdigit(*s));
171 			else
172 				n2 = 9999;
173 		}
174 		olist[nolist++] = n1;
175 		olist[nolist++] = n2;
176 		if (*s != '\0')
177 			s++;
178 	}
179 	olist[nolist] = 0;
180 	if (dbg)
181 		for (i=0; i<nolist; i += 2)
182 			printf("%3d %3d\n", olist[i], olist[i+1]);
183 }
184 
185 in_olist(n)	/* is n in olist? */
186 int n;
187 {
188 	int i;
189 
190 	if (nolist == 0)
191 		return(1);	/* everything is included */
192 	for (i = 0; i < nolist; i += 2)
193 		if (n >= olist[i] && n <= olist[i+1])
194 			return(1);
195 	return(0);
196 }
197 
198 conv(fp)
199 register FILE *fp;
200 {
201 	register int c, k;
202 	int m, n, i, n1, m1;
203 	char str[100], buf[300];
204 
205 	while ((c = getc(fp)) != EOF) {
206 		switch (c) {
207 		case '\n':	/* when input is text */
208 			lineno++;
209 		case ' ':
210 		case 0:		/* occasional noise creeps in */
211 			break;
212 		case '{':	/* push down current environment */
213 			t_push();
214 			break;
215 		case '}':
216 			t_pop();
217 			break;
218 		case '0': case '1': case '2': case '3': case '4':
219 		case '5': case '6': case '7': case '8': case '9':
220 			/* two motion digits plus a character */
221 			hmot((c-'0')*10 + getc(fp)-'0');
222 			put1(getc(fp));
223 			break;
224 		case 'c':	/* single ascii character */
225 			put1(getc(fp));
226 			break;
227 		case 'C':
228 			fscanf(fp, "%s", str);
229 			put1s(str);
230 			break;
231 		case 't':	/* straight text */
232 			fgets(buf, sizeof(buf), fp);
233 			lineno++;
234 			t_text(buf);
235 			break;
236 		case 'D':	/* draw function */
237 			fgets(buf, sizeof(buf), fp);
238 			lineno++;
239 			switch (buf[0]) {
240 			case 'l':	/* draw a line */
241 				sscanf(buf+1, "%d %d", &n, &m);
242 				drawline(n, m, ".");
243 				break;
244 			case 'c':	/* circle */
245 				sscanf(buf+1, "%d", &n);
246 				drawcirc(n);
247 				break;
248 			case 'e':	/* ellipse */
249 				sscanf(buf+1, "%d %d", &m, &n);
250 				drawellip(m, n);
251 				break;
252 			case 'a':	/* arc */
253 				sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
254 				drawarc(n, m, n1, m1);
255 				break;
256 			case '~':	/* wiggly line */
257 				drawwig(buf+1);
258 				break;
259 			default:
260 				error(FATAL, "unknown drawing function %s\n", buf);
261 				break;
262 			}
263 			break;
264 		case 's':
265 			fscanf(fp, "%d", &n);	/* ignore fractional sizes */
266 			setsize(t_size(n));
267 			break;
268 		case 'f':
269 			fscanf(fp, "%s", str);
270 			setfont(t_font(str));
271 			break;
272 		case 'H':	/* absolute horizontal motion */
273 			/* fscanf(fp, "%d", &n); */
274 			while ((c = getc(fp)) == ' ')
275 				;
276 			k = 0;
277 			do {
278 				k = 10 * k + c - '0';
279 			} while (isdigit(c = getc(fp)));
280 			ungetc(c, fp);
281 			hgoto(k);
282 			break;
283 		case 'h':	/* relative horizontal motion */
284 			/* fscanf(fp, "%d", &n); */
285 			while ((c = getc(fp)) == ' ')
286 				;
287 			k = 0;
288 			do {
289 				k = 10 * k + c - '0';
290 			} while (isdigit(c = getc(fp)));
291 			ungetc(c, fp);
292 			hmot(k);
293 			break;
294 		case 'w':	/* word space */
295 			break;
296 		case 'V':
297 			fscanf(fp, "%d", &n);
298 			vgoto(n);
299 			break;
300 		case 'v':
301 			fscanf(fp, "%d", &n);
302 			vmot(n);
303 			break;
304 		case 'p':	/* new page */
305 			fscanf(fp, "%d", &n);
306 			t_page(n);
307 			break;
308 		case 'n':	/* end of line */
309 			while (getc(fp) != '\n')
310 				;
311 			t_newline();
312 			break;
313 		case '#':	/* comment */
314 			while (getc(fp) != '\n')
315 				;
316 			lineno++;
317 			break;
318 		case 'x':	/* device control */
319 			devcntrl(fp);
320 			lineno++;
321 			break;
322 		default:
323 			error(!FATAL, "unknown input character %o %c\n", c, c);
324 			while (getc(fp) != '\n')
325 				;
326 		}
327 	}
328 }
329 
330 devcntrl(fp)	/* interpret device control functions */
331 FILE *fp;
332 {
333 	char str[20];
334 	int c, n;
335 
336 	fscanf(fp, "%s", str);
337 	switch (str[0]) {	/* crude for now */
338 	case 'i':	/* initialize */
339 		fileinit();
340 		t_init(0);
341 		break;
342 	case 'T':	/* device name */
343 		fscanf(fp, "%s", devname);
344 		break;
345 	case 't':	/* trailer */
346 		t_trailer();
347 		break;
348 	case 'p':	/* pause -- can restart */
349 		t_reset('p');
350 		break;
351 	case 's':	/* stop */
352 		t_reset('s');
353 		break;
354 	case 'r':	/* resolution assumed when prepared */
355 		fscanf(fp, "%d", &res);
356 		break;
357 	case 'f':	/* font used */
358 		fscanf(fp, "%d %s", &n, str);
359 		loadfont(n, str);
360 		break;
361 	}
362 	while (getc(fp) != '\n')	/* skip rest of input line */
363 		;
364 }
365 
366 fileinit()	/* read in font and code files, etc. */
367 {
368 }
369 
370 fontprint(i)	/* debugging print of font i (0,...) */
371 {
372 }
373 
374 loadcode(n, nw)	/* load codetab on position n (0...); #chars is nw */
375 int n, nw;
376 {
377 }
378 
379 loadfont(n, s)	/* load font info for font s on position n (1...) */
380 int n;
381 char *s;
382 {
383 }
384 
385 #define	ESC	033
386 #define	MAXY	(3071-100)
387 #define	US	037	/* text mode */
388 #define	GS	035	/* graphics mode */
389 #define	FF	014
390 
391 error(f, s, a1, a2, a3, a4, a5, a6, a7) {
392 	fprintf(stderr, "%c%c%c", US, ESC, ';');	/* reset terminal sensibly */
393 	fprintf(stderr, "tc: ");
394 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
395 	fprintf(stderr, " near line %ld\n", lineno);
396 	if (f)
397 		done(2);
398 }
399 
400 
401 /*
402 	Here beginneth all the stuff that really depends
403 	on the 202 (we hope).
404 */
405 
406 
407 char	devname[20]	= "4014";
408 
409 #define	oput(c)	if (output) putchar(c); else;
410 
411 int	stopped = 0;
412 int	ohx	= -1;
413 int	ohy	= -1;
414 int	oxb	= -1;
415 int	oly	= -1;
416 int	olx	= -1;
417 int	skip;
418 int	size	= 1;
419 int	font	= 1;		/* current font */
420 int	hpos;		/* horizontal position where we are supposed to be next (left = 0) */
421 int	vpos;		/* current vertical position (down positive) */
422 
423 int	horig;		/* h origin of current block; hpos rel to this */
424 int	vorig;		/* v origin of current block; vpos rel to this */
425 
426 int	DX	= 10;	/* step size in x for drawing */
427 int	DY	= 10;	/* step size in y for drawing */
428 int	drawdot	= '.';	/* draw with this character */
429 int	drawsize = 1;	/* shrink by this factor when drawing */
430 
431 t_init(reinit)	/* initialize device */
432 int reinit;
433 {
434 	fflush(stdout);
435 	stopped = 0;
436 	if (erase) {
437 		oput(ESC);
438 		oput(FF);
439 		oput(US);
440 	}
441 	hpos = vpos = 0;
442 	setsize(t_size(10));	/* start somewhere */
443 	sendpt();
444 }
445 
446 #define	MAXSTATE	5
447 
448 struct state {
449 	int	ssize;
450 	int	sfont;
451 	int	shpos;
452 	int	svpos;
453 	int	shorig;
454 	int	svorig;
455 };
456 struct	state	state[MAXSTATE];
457 struct	state	*statep = state;
458 
459 t_push()	/* begin a new block */
460 {
461 	hflush();
462 	statep->ssize = size;
463 	statep->sfont = font;
464 	statep->shorig = horig;
465 	statep->svorig = vorig;
466 	statep->shpos = hpos;
467 	statep->svpos = vpos;
468 	horig = hpos;
469 	vorig = vpos;
470 	hpos = vpos = 0;
471 	if (statep++ >= state+MAXSTATE)
472 		error(FATAL, "{ nested too deep");
473 	hpos = vpos = 0;
474 }
475 
476 t_pop()	/* pop to previous state */
477 {
478 	if (--statep < state)
479 		error(FATAL, "extra }");
480 	size = statep->ssize;
481 	font = statep->sfont;
482 	hpos = statep->shpos;
483 	vpos = statep->svpos;
484 	horig = statep->shorig;
485 	vorig = statep->svorig;
486 }
487 
488 int	np;	/* number of pages seen */
489 int	npmax;	/* high-water mark of np */
490 int	pgnum[100];	/* their actual numbers */
491 long	pgadr[100];	/* their seek addresses */
492 
493 t_page(n)	/* do whatever new page functions */
494 {
495 	long ftell();
496 	int c, m, i;
497 	char buf[100], *bp;
498 
499 	pgnum[np++] = n;
500 	pgadr[np] = ftell(fp);
501 	if (np > npmax)
502 		npmax = np;
503 	if (output == 0) {
504 		output = in_olist(n);
505 		t_init(1);
506 		return;
507 	}
508 	/* have just printed something, and seen p<n> for next one */
509 	vgoto(11 * res - 100);
510 	sendpt();
511 	oput(US);
512 	fflush(stdout);
513 
514 
515 	if (keepon) {
516 		t_init(1);
517 		return;
518 	}
519   next:
520 	for (bp = buf; (*bp = readch()); )
521 		if (*bp++ == '\n')
522 			break;
523 	*bp = 0;
524 	switch (buf[0]) {
525 	case 0:
526 		done();
527 		break;
528 	case '\n':
529 		if (stopped)
530 			done();
531 		output = in_olist(n);
532 		t_init(1);
533 		return;
534 	case '!':
535 		callunix(&buf[1]);
536 		fputs("!\n", stderr);
537 		break;
538 	case 'e':
539 		erase = 1 - erase;
540 		break;
541 	case 'a':
542 		aspect = atof(&buf[1]);
543 		break;
544 	case '-':
545 	case 'p':
546 		m = atoi(&buf[1]) + 1;
547 		if (fp == stdin) {
548 			fputs("you can't; it's not a file\n", stderr);
549 			break;
550 		}
551 		if (np - m <= 0) {
552 			fputs("too far back\n", stderr);
553 			break;
554 		}
555 		np -= m;
556 		fseek(fp, pgadr[np], 0);
557 		output = 1;
558 		t_init(1);
559 		return;
560 	case '0': case '1': case '2': case '3': case '4':
561 	case '5': case '6': case '7': case '8': case '9':
562 		m = atoi(&buf[0]);
563 		for (i = 0; i < npmax; i++)
564 			if (m == pgnum[i])
565 				break;
566 		if (i >= npmax || fp == stdin) {
567 			fputs("you can't\n", stderr);
568 			break;
569 		}
570 		np = i + 1;
571 		fseek(fp, pgadr[np], 0);
572 		output = 1;
573 		t_init(1);
574 		return;
575 	case 'o':
576 		outlist(&buf[1]);
577 		output = 0;
578 		t_init(1);
579 		return;
580 	case '?':
581 		fputs("!cmd	unix cmd\n", stderr);
582 		fputs("p	print this page again\n", stderr);
583 		fputs("-n	go back n pages\n", stderr);
584 		fputs("n	print page n (previously printed)\n", stderr);
585 		fputs("o...	set the -o output list to ...\n", stderr);
586 		fputs("en	n=0 -> don't erase; n=1 -> erase\n", stderr);
587 		fputs("an	sets aspect ratio to n\n", stderr);
588 		break;
589 	default:
590 		fputs("?\n", stderr);
591 		break;
592 	}
593 	goto next;
594 }
595 
596 t_newline()	/* do whatever for the end of a line */
597 {
598 	hpos = 0;
599 }
600 
601 t_size(n)	/* convert integer to internal size number*/
602 int n;
603 {
604 	int i;
605 
606 	if (n <= pstab[0])
607 		return(1);
608 	else if (n >= pstab[nsizes-1])
609 		return(nsizes);
610 	for (i = 0; n > pstab[i]; i++)
611 		;
612 	return(i+1);
613 }
614 
615 t_font(s)	/* convert string to internal font number */
616 char *s;
617 {
618 	int n;
619 
620 	n = atoi(s);
621 	if (n < 1 || n > nfonts)
622 		n = 1;
623 	return(n);
624 }
625 
626 t_text(s)	/* print string s as text */
627 char *s;
628 {
629 	int c, w;
630 	char str[100];
631 
632 	if (!output)
633 		return;
634 	w = res / 2 * pstab[size-1] / 72;
635 	while ((c = *s++) != '\n') {
636 		if (c == '\\') {
637 			switch (c = *s++) {
638 			case '\\':
639 			case 'e':
640 				put1('\\');
641 				break;
642 			case '(':
643 				str[0] = *s++;
644 				str[1] = *s++;
645 				str[2] = '\0';
646 				put1s(str);
647 				break;
648 			}
649 		} else {
650 			put1(c);
651 		}
652 		hmot(w);
653 	}
654 }
655 
656 t_reset(c)
657 {
658 	int n;
659 
660 	output = 1;
661 	fflush(stdout);
662 	if (c == 's') {
663 		stopped = 1;
664 		t_page(9999);
665 	}
666 }
667 
668 t_trailer()
669 {
670 }
671 
672 hgoto(n)
673 {
674 	hpos = n;	/* this is where we want to be */
675 			/* before printing a character, */
676 			/* have to make sure it's true */
677 }
678 
679 hmot(n)	/* generate n units of horizontal motion */
680 int n;
681 {
682 	hgoto(hpos + n);
683 }
684 
685 hflush()	/* actual horizontal output occurs here */
686 {
687 	if (output)
688 		sendpt();
689 }
690 
691 vgoto(n)
692 {
693 	vpos = n;
694 }
695 
696 vmot(n)	/* generate n units of vertical motion */
697 int n;
698 {
699 	vgoto(vpos + n);	/* ignores rounding */
700 }
701 
702 put1s(s)	/* s is a funny char name */
703 char *s;
704 {
705 	int i;
706 	char *p;
707 	extern char *spectab[];
708 	static char prev[10] = "";
709 	static int previ;
710 
711 	if (!output)
712 		return;
713 	if (strcmp(s, prev) != 0) {
714 		previ = -1;
715 		for (i = 0; spectab[i] != 0; i += 2)
716 			if (strcmp(spectab[i], s) == 0) {
717 				strcpy(prev, s);
718 				previ = i;
719 				break;
720 			}
721 	}
722 	if (previ >= 0) {
723 		hflush();
724 		oput(US);
725 		for (p = spectab[previ+1]; *p; p++)
726 			oput(*p);
727 	} else
728 		prev[0] = 0;
729 }
730 
731 put1(c)	/* output char c */
732 int c;
733 {
734 	if (!output)
735 		return;
736 	hflush();
737 	oput(US);
738 	oput(c);
739 }
740 
741 setsize(n)	/* set point size to n (internal) */
742 int n;
743 {
744 
745 	if (!output)
746 		return;
747 	if (n == size)
748 		return;	/* already there */
749 	oput(ESC);
750 	oput(pscode[n-1]);
751 	size = n;
752 }
753 
754 t_fp(n, s)	/* font position n now contains font s */
755 int n;
756 char *s;
757 {
758 }
759 
760 setfont(n)	/* set font to n */
761 int n;
762 {
763 }
764 
765 done()
766 {
767 	output = 1;
768 	hgoto(0);
769 	vgoto(11 * res - 100);	/* bottom of page */
770 	sendpt();
771 	oput(US);
772 	oput(ESC);
773 	oput(';');
774 	oput(US);
775 	fflush(stdout);
776 	exit(0);
777 }
778 
779 callunix(line)
780 char line[];
781 {
782 	int rc, status, unixpid;
783 	if( (unixpid=fork())==0 ) {
784 		signal(SIGINT,sigint); signal(SIGQUIT,sigquit);
785 		close(0); dup(2);
786 		execl("/bin/sh", "-sh", "-c", line, 0);
787 		exit(255);
788 	}
789 	else if(unixpid == -1)
790 		return;
791 	else{	signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
792 		while( (rc = wait(&status)) != unixpid && rc != -1 ) ;
793 		signal(SIGINT, done); signal(SIGQUIT,sigquit);
794 	}
795 }
796 readch(){
797 	char c;
798 	if (read(2,&c,1)<1) c=0;
799 	return(c);
800 }
801 sendpt(){
802 	int hy,xb,ly,hx,lx;
803 	int xx, yy;
804 	float fx, fy;
805 
806 
807 	fx = hpos + horig;
808 	fy = vpos + vorig;
809 	xx = (fx * MAXY / 11) / res * aspect + 0.5;
810 	yy = MAXY - (fy * MAXY / 11) / res + 0.5;
811 	oput(GS);
812 	hy = ((yy>>7) & 037);
813 	xb = ((xx & 03) + ((yy<<2) & 014) & 017);
814 	ly = ((yy>>2) & 037);
815 	hx = ((xx>>7) & 037);
816 	lx = ((xx>>2) & 037);
817 	if(hy != ohy)oput(hy | 040);
818 	if(xb != oxb)oput(xb | 0140);
819 	if((ly != oly) || (hx != ohx) || (xb != oxb))
820 		oput(ly | 0140);
821 	if(hx != ohx)oput(hx | 040);
822 	oput(lx | 0100);
823 	ohy = hy;
824 	oxb = xb;
825 	oly = ly;
826 	ohx = hx;
827 	olx = lx;
828 }
829 
830 char *spectab[] ={
831 	"em", "--",
832 	"en", "-",
833 	"hy", "-",
834 	"ff", "ff",
835 	"fi", "fi",
836 	"fl", "fl",
837 	"Fi", "ffi",
838 	"Fl", "ffl",
839 	"ct", "\033\016Z\bM\033\017",	/*cent sign*/
840 	"de", "\033\016J\033\017",	/*degree*/
841 	"dg", "\033\016M\b_\033\017",	/*dagger*/
842 	"rg", "\033\016O\b&\033\017",	/*registered*/
843 	"bu", "\033\016O\b~\033\017",	/*bullet*/
844 	"fm", "'",
845 	"co", "\033\016O\b#\033\017",	/*copyright*/
846 	"sq", "\033\016L\033\017",	/*square*/
847 	"*q", "\033\016(\bM\033\017",	/*psi*/
848 	"*h", "\033\016o\b_\033\017",	/*theta*/
849 	"*n", "v\b)",	/*nu*/
850 	"*m", "\033\016V\b,\033\017",	/*mu*/
851 	"*l", "\033\016)\b?\033\017",	/*lambda*/
852 	"*i", "\033\016I\033\017",	/*iota*/
853 	"*z", "S\b\033\016Z\033\017",	/*zeta*/
854 	"*s", "o\b\'",	/*sigma*/
855 	"*d", "o\b\033\0165\033\017",	/*delta*/
856 	"*b", "\033\016b\033\017",	/*beta*/
857 	"*c", "\033\016e\bc\033\017",	/*xi*/
858 	"*y", "j\b\033\016C\033\017",	/*eta*/
859 	"*f", "\033\016O\bM\033\017",	/*phi*/
860 	"*u", "\033\016(\033\017",	/*upsilon*/
861 	"*k", "\033\016k\033\017",	/*kappa*/
862 	"*p", "T\b\033\016S\033\017",	/*pi*/
863 	"da", "\033\016U\033\017",	/*down arrow*/
864 	"*a", "\033\016A\033\017",	/*alpha*/
865 	"or", "|",
866 	"*x", "l\b/",	/*chi*/
867 	"*e", "\033\016E\033\017",	/*epsilon*/
868 	"*o", "\033\016O\033\017",	/*omicron*/
869 	"<-", "\033\016[\033\017",	/*left arrow*/
870 	"*r", "\033\016R\033\017",	/*rho*/
871 	"ua", "\033\016Y\033\017",	/*up arrow*/
872 	"*t", "\033\016N\033\017",	/*tau*/
873 	"ul", "_",
874 	"ru", "_",
875 	"\\_", "_",
876 	"*Q", "I\b\033\016(\033\017",	/*Psi*/
877 	"bs", "\033\016O\bJ\033\017",	/*bell system sign*/
878 	"if", "\033\016W\bX\033\017",	/*infinity*/
879 	"*g", "`\b/",	/*gamma*/
880 	"ip", "\033\016X\bF\033\017",	/*improper superset*/
881 	"pt", "\033\016A\033\017",	/*proportional to*/
882 	"rh", "\033\016\\\b]\033\017",	/*right hand*/
883 	"*w", "\033\016W\033\017",	/*omega*/
884 	"gr", "\033\016G\033\017",	/*gradient*/
885 	"*F", "I\033\016\bO\033\017",	/*Phi*/
886 	"*H", "O\b=",	/*Theta*/
887 	"*W", "O\b_",	/*Omega*/
888 	"cu", "\033\016V\033\017",	/*cup (union)*/
889 	"rn", "\033\016@\033\017",	/*root en*/
890 	"ts", "s",	/*terminal sigma*/
891 	"*L", "\033\016)\bK\033\017",	/*Lambda*/
892 	"\\-", "-",
893 	"*G", "\033\016S\bK\033\017",	/*Gamma*/
894 	"is", "\033\016i\033\017",	/*integral sign*/
895 	"Sl", "l",
896 	"*P", "\033\016t\b'\033\017",	/*Pi*/
897 	"sb", "\033\016Z\033\017",	/*subset of*/
898 	"sp", "\033\016X\033\017",	/*superset of*/
899 	"ap", "\033\016T\033\017",	/*approximates*/
900 	"pd", "o\b`",	/*partial derivative*/
901 	"*D", "\033\016H\033\017",	/*Delta*/
902 	"sr", "\033\016I\b'\033\017",	/*square root*/
903 	"*S", ">\b\033\016F\b@\033\017",	/*Sigma*/
904 	"~~", "\033\016T\bF\033\017",	/*approx =*/
905 	"*C", "\033\016_\bF\b@\033\017",	/*Xi*/
906 	"sl", "/",
907 	"ca", "\033\016C\033\017",	/*cap (intersection)*/
908 	"U", "\033\016y\033\017",	/*Upsilon*/
909 	"no", "\033\016|\033\017",	/*not*/
910 	"rc", "|",	/*right ceiling (rt of ")*/
911 	"lt", "|",	/*left top (of big curly)*/
912 	"bv", "|",	/*bold vertical*/
913 	"lk", "|",	/*left center of big curly bracket*/
914 	"lb", "|",	/*left bottom*/
915 	"rt", "|",	/*right top*/
916 	"rk", "|",	/*right center of big curly bracket*/
917 	"rb", "|",	/*right bot*/
918 	"rf", "|",	/*right floor (rb of ")*/
919 	"lf", "|",	/*left floor (left bot of big sq bract)*/
920 	"lc", "|",	/*left ceiling (lt of ")*/
921 	"mu", "\033\016=\033\017",	/*multiply*/
922 	"di", "\033\016+\033\017",	/*divide*/
923 	"+-", "+\b_",	/*plus-minus*/
924 	"<=", "\033\016$\033\017",	/*<=*/
925 	">=", "\033\016^\033\017",	/*>=*/
926 	"==", "=\b_",	/*identically equal*/
927 	"!=", "\033\016*\033\017",	/*not equal*/
928 	"aa", "'",
929 	"ga", "`",
930 	"lh", "\033\016|\b[\033\017",	/*left hand*/
931 	"mo", "\033\016c\b_\033\017",	/*member of*/
932 	"es", "\033\016O\b/\033\017",	/*empty set*/
933 	"dd", "\033\016%\bM\033\017",	/*dbl dagger*/
934 	"br", "|",	/*box rule*/
935 	"vr", "|",	/* vertical rule */
936 	"ib", "\033\016Z\bF\033\017",	/*improper subset*/
937 	"ci", "\033\016O\033\017",	/*circle*/
938 	"eq", "=",
939 	"pl", "+",
940 	"mi", "-",
941 	"12", "1/2",
942 	"14", "1/4",
943 	"34", "3/4",
944 	"->", "\033\016]\033\017",	/*right arrow*/
945 	"sc", "g\b\033\016C\033\017",	/*section mark*/
946 	"**", "*",
947 	"l.", ".",
948 	"L.", ".",
949 	"bx", "[\b]",
950 	"ob", "o",	/* open bullet */
951 	"cd", ",",	/* cedilla */
952 	"..", "\033\016!\033\017",	/* umlaut */
953 	0, 0,
954 };
955