xref: /original-bsd/old/tc/tc.c (revision 68aed273)
1 static char *sccsid = "@(#)tc.c	4.2 (Berkeley) 07/06/81";
2 /*
3  * Simulate typesetter on 4014
4 */
5 
6 #include <signal.h>
7 #include <stdio.h>
8 
9 #define	oput(c) if (pgskip==0) putchar(c); else (c);
10 #define MAXY 3071
11 #define US 037
12 #define GS 035
13 #define ESC 033
14 #define FF 014
15 #define DBL 0200
16 
17 int pl = 11*144;
18 int mpy = 1;
19 int div = 1;
20 char *ap;
21 int ch;
22 int nonumb;
23 int psize = 10;
24 int dfact = 1;
25 int esc;
26 int escd;
27 int verd;
28 int esct;
29 int osize = 02;
30 int size = 02;
31 int rx;
32 int xx;
33 int yy = MAXY+62+48;
34 int leadtot = -31;
35 int ohy = -1;
36 int ohx = -1;
37 int oxb = -1;
38 int oly = -1;
39 int olx = -1;
40 int tflag;
41 int railmag;
42 int lead;
43 int skip;
44 int pgskip;
45 int ksize = ';';
46 int mcase;
47 int stab[] = {010,0,01,07,02,03,04,05,0211,06,0212,0213,0214,0215,0216,0217};
48 int rtab[] = {6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 28, 36, 18};
49 int ktab[] = {';',';',';',';',';',';',':',':','9','9','9','9','8','8','8','9'};
50 int first = 1;
51 int alpha;
52 extern char *asctab[128];
53 extern char *spectab[128];
54 int erase = 1;
55 int	(*sigint)();
56 int	(*sigquit)();
57 
58 main(argc,argv)
59 int argc;
60 char **argv;
61 {
62 	register i, j;
63 	register char *k;
64 	extern ex();
65 
66 	while((--argc > 0) && ((++argv)[0][0]=='-')){
67 		switch(argv[0][1]){
68 			case 'p':
69 				ap = &argv[0][2];
70 				dfact = 72;
71 				if(i = atoi())pl = i/3;
72 				continue;
73 			case 't':
74 				tflag++;
75 				continue;
76 			case 's':
77 				ap = &argv[0][2];
78 				dfact = 1;
79 				pgskip = atoi();
80 				continue;
81 			default:
82 				dfact = 1;
83 				ap = &argv[0][1];
84 				if(i = atoi())mpy = i;
85 				if(i = atoi())div = i;
86 				continue;
87 		}
88 	}
89 	if(argc){
90 		if (freopen(argv[0], "r", stdin) == NULL) {
91 			fprintf(stderr, "tc: cannot open %s\n", argv[0]);
92 			exit(1);
93 		}
94 	}
95 	sigint = signal(SIGINT, ex);
96 	sigquit = signal(SIGQUIT, SIG_IGN);
97 	while((i = getchar()) != EOF){
98 		if(!i)continue;
99 		if(i & 0200){
100 			esc += (~i) & 0177;
101 			continue;
102 		}
103 		if(esc){
104 			if(escd)esc = -esc;
105 			esct += esc;
106 			xx += (esc*mpy + rx)/div;
107 			rx = (esc*mpy + rx)%div;
108 			sendpt();
109 			esc = 0;
110 		}
111 		switch(i){
112 			case 0100:	/*init*/
113 				escd = verd = mcase = railmag = xx = 0;
114 				yy = MAXY + 48;
115 				leadtot = -31;
116 				ohy = oxb = oly = ohx = olx = -1;
117 				oput(US);
118 				fflush(stdout);
119 				if(!first && !tflag)kwait();
120 				if(first){
121 					first = 0;
122 					yy += 62;
123 				}
124 				init();
125 				continue;
126 			case 0101:	/*lower rail*/
127 				railmag &= ~01;
128 				continue;
129 			case 0102:	/*upper rail*/
130 				railmag |= 01;
131 				continue;
132 			case 0103:	/*upper mag*/
133 				railmag |= 02;
134 				continue;
135 			case 0104:	/*lower mag*/
136 				railmag &= ~02;
137 				continue;
138 			case 0105:	/*lower case*/
139 				mcase = 0;
140 				continue;
141 			case 0106:	/*upper case*/
142 				mcase = 0100;
143 				continue;
144 			case 0107:	/*escape forward*/
145 				escd = 0;
146 				continue;
147 			case 0110:	/*escape backward*/
148 				escd = 1;
149 				continue;
150 			case 0111:	/*stop*/
151 				continue;
152 			case 0112:	/*lead forward*/
153 				verd = 0;
154 				continue;
155 			case 0113:	/*undefined*/
156 				continue;
157 			case 0114:	/*lead backward*/
158 				verd = 1;
159 				continue;
160 			case 0115:	/*undefined*/
161 			case 0116:
162 			case 0117:
163 				continue;
164 		}
165 		if((i & 0340) == 0140){	/*leading*/
166 			lead = (~i) & 037;
167 			if(verd)lead = -lead;
168 			if((leadtot += lead) > pl){
169 				leadtot = lead;
170 				oput(US);
171 				fflush(stdout);
172 				if(!tflag)kwait();
173 				yy = MAXY;
174 				if(pgskip)--pgskip;
175 				init();
176 				continue;
177 			}
178 			if(skip)continue;
179 			if((yy -= (lead<<1)) < 0){
180 				skip++;
181 				yy = 0;
182 			}else sendpt();
183 			continue;
184 		}
185 		if((i & 0360) == 0120){	/*size change*/
186 			i &= 017;
187 			for(j = 0; i != (stab[j] & 017); j++);
188 			osize = size;
189 			size = stab[j];
190 			psize = rtab[j];
191 			ksize = ktab[j];
192 			oput(ESC);
193 			oput(ksize);
194 			i = 0;
195 			if(!(osize & DBL) && (size & DBL))i = -55;
196 			else if((osize & DBL) && !(size & DBL))i = 55;
197 			if(escd)i = -i;
198 			esc += i;
199 			continue;
200 		}
201 		if(i & 0300)continue;
202 		i = (i & 077) | mcase;
203 		if(railmag != 03)k = asctab[i];
204 		else k = spectab[i];
205 		if(alpha)sendpt();
206 		if(*k!='\0'){
207 			oput(US);
208 			while(*k & 0377)oput(*k++);
209 			alpha++;
210 			continue;
211 		}else{
212 			if(railmag != 03){
213 				switch(i){
214 				case 0124: lig("fi"); break;
215 				case 0125: lig("fl"); break;
216 				case 0126: lig("ff"); break;
217 				case 0130: lig("ffl"); break;
218 				case 0131: lig("ffi"); break;
219 				default: continue;
220 				}
221 			}
222 			continue;
223 		}
224 	}
225 	ex();
226 }
227 lig(x)
228 char *x;
229 {
230 	register i, j;
231 	register char *k;
232 
233 	j = 0;
234 	k = x;
235 	oput(US);
236 	oput(*k++);
237 	i = psize * 8 * mpy / (div * 6); /* 8/36 em */
238 	while(*k){
239 		xx += i;
240 		j += i;
241 		sendpt();
242 		oput(US);
243 		oput(*k++);
244 	}
245 	xx -= j;
246 	sendpt();
247 }
248 init(){
249 
250 	fflush(stdout);
251 	if(erase){
252 		oput(ESC);
253 		oput(FF);
254 	}else erase = 1;
255 	oput(ESC);
256 	oput(ksize);
257 	/*delay about a second*/
258 /* let the system do it...
259 	for(i = 960; i > 0; i--)oput(GS);
260 */
261 	skip = 0;
262 	sendpt();
263 }
264 ex(){
265 	yy = MAXY;
266 	xx = 0;
267 	sendpt();
268 	oput(ESC);
269 	oput(';');
270 	oput(US);
271 	fflush(stdout);
272 	exit(0);
273 }
274 kwait(){
275 	char buf[128]; char *bptr; char c;
276 	if(pgskip) return;
277 next:
278 	bptr=buf;
279 	while((c=readch())&&(c!='\n')) *bptr++=c;
280 	*bptr=0;
281 	if(bptr!=buf){
282 		bptr = buf;
283 		if(*bptr == '!'){callunix(&buf[1]); fputs("!\n", stderr); goto next;}
284 		else switch(*bptr++){
285 			case 'e':
286 				erase = 0;
287 				goto next;
288 			case 's':
289 				ap = &buf[1];
290 				dfact = 1;
291 				pgskip = atoi() + 1;
292 				goto next;
293 			default:
294 				fputs("?\n", stderr);
295 				goto next;
296 		}
297 	}
298 	else if (c==0) ex();
299 	else	return;
300 }
301 callunix(line)
302 char line[];
303 {
304 	int rc, status, unixpid;
305 	if( (unixpid=fork())==0 ) {
306 		signal(SIGINT,sigint); signal(SIGQUIT,sigquit);
307 		close(0); dup(2);
308 		execl("/bin/sh", "-sh", "-c", line, 0);
309 		exit(255);
310 	}
311 	else if(unixpid == -1)
312 		return;
313 	else{	signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
314 		while( (rc = wait(&status)) != unixpid && rc != -1 ) ;
315 		signal(SIGINT,ex); signal(SIGQUIT,sigquit);
316 	}
317 }
318 readch(){
319 	char c;
320 	if (read(2,&c,1)<1) c=0;
321 	return(c);
322 }
323 sendpt(){
324 	int hy,xb,ly,hx,lx;
325 
326 	oput(GS);
327 	hy = ((yy>>7) & 037);
328 	xb = ((xx & 03) + ((yy<<2) & 014) & 017);
329 	ly = ((yy>>2) & 037);
330 	hx = ((xx>>7) & 037);
331 	lx = ((xx>>2) & 037);
332 	if(hy != ohy)oput(hy | 040);
333 	if(xb != oxb)oput(xb | 0140);
334 	if((ly != oly) || (hx != ohx) || (xb != oxb))
335 		oput(ly | 0140);
336 	if(hx != ohx)oput(hx | 040);
337 	oput(lx | 0100);
338 	ohy = hy;
339 	oxb = xb;
340 	oly = ly;
341 	ohx = hx;
342 	olx = lx;
343 	alpha = 0;
344 	return;
345 }
346 atoi()
347 {
348 	register i, j, acc;
349 	int field, digits;
350 	long dd;
351 	long tscale();
352 
353 	field = digits = acc = 0;
354 a1:
355 	while(((j = (i = getch()) - '0') >= 0) && (j <= 9)){
356 		field++;
357 		digits++;
358 		acc = 10*acc + j;
359 	}
360 	if(i == '.'){
361 		field++;
362 		digits = 0;
363 		goto a1;
364 	}
365 	if(!(ch = i))ch = 'x';
366 	dd = tscale(acc);
367 	acc = dd;
368 	if((field != digits) && (digits > 0)){
369 		j = 1;
370 		while(digits--)j *= 10;
371 		acc = dd/j;
372 	}
373 	nonumb = !field;
374 	ch = 0;
375 	return(acc);
376 }
377 long tscale(n)
378 int n;
379 {
380 	register i, j;
381 
382 	switch(i = getch()){
383 		case 'u':
384 			j = 1;
385 			break;
386 		case 'p':	/*Points*/
387 			j = 6;
388 			break;
389 		case 'i':	/*Inches*/
390 			j = 432;
391 			break;
392 		case 'c':	/*Centimeters; should be 170.0787*/
393 			j = 170;
394 			break;
395 		case 'P':	/*Picas*/
396 			j = 72;
397 			break;
398 		default:
399 			j = dfact;
400 			ch = i;
401 	}
402 	return((long)n*j);
403 }
404 getch(){
405 	register i;
406 
407 	if(ch){
408 		i = ch;
409 		ch = 0;
410 		return(i);
411 	}
412 	return(*ap++);
413 }
414 
415 char *asctab[128] = {
416 "\0",	/*blank*/
417 "h",	/*h*/
418 "t",	/*t*/
419 "n",	/*n*/
420 "m",	/*m*/
421 "l",	/*l*/
422 "i",	/*i*/
423 "z",	/*z*/
424 "s",	/*s*/
425 "d",	/*d*/
426 "b",	/*b*/
427 "x",	/*x*/
428 "f",	/*f*/
429 "j",	/*j*/
430 "u",	/*u*/
431 "k",	/*k*/
432 "\0",	/*blank*/
433 "p",	/*p*/
434 "-",	/*_ 3/4 em dash*/
435 ";",	/*;*/
436 "\0",	/*blank*/
437 "a",	/*a*/
438 "_",	/*rule*/
439 "c",	/*c*/
440 "`",	/*` open*/
441 "e",	/*e*/
442 "\'",	/*' close*/
443 "o",	/*o*/
444 "\0",	/*1/4*/
445 "r",	/*r*/
446 "\0",	/*1/2*/
447 "v",	/*v*/
448 "-",	/*- hyphen*/
449 "w",	/*w*/
450 "q",	/*q*/
451 "/",	/*/*/
452 ".",	/*.*/
453 "g",	/*g*/
454 "\0",	/*3/4*/
455 ",",	/*,*/
456 "&",	/*&*/
457 "y",	/*y*/
458 "\0",	/*blank*/
459 "%",	/*%*/
460 "\0",	/*blank*/
461 "Q",	/*Q*/
462 "T",	/*T*/
463 "O",	/*O*/
464 "H",	/*H*/
465 "N",	/*N*/
466 "M",	/*M*/
467 "L",	/*L*/
468 "R",	/*R*/
469 "G",	/*G*/
470 "I",	/*I*/
471 "P",	/*P*/
472 "C",	/*C*/
473 "V",	/*V*/
474 "E",	/*E*/
475 "Z",	/*Z*/
476 "D",	/*D*/
477 "B",	/*B*/
478 "S",	/*S*/
479 "Y",	/*Y*/
480 "\0",	/*blank*/
481 "F",	/*F*/
482 "X",	/*X*/
483 "A",	/*A*/
484 "W",	/*W*/
485 "J",	/*J*/
486 "U",	/*U*/
487 "K",	/*K*/
488 "0",	/*0*/
489 "1",	/*1*/
490 "2",	/*2*/
491 "3",	/*3*/
492 "4",	/*4*/
493 "5",	/*5*/
494 "6",	/*6*/
495 "7",	/*7*/
496 "8",	/*8*/
497 "9",	/*9*/
498 "*",	/***/
499 "-",	/*minus*/
500 "",	/*fi*/
501 "",	/*fl*/
502 "",	/*ff*/
503 "\033\016Z\bM\033\017",	/*cent sign*/
504 "",	/*ffl*/
505 "",	/*ffi*/
506 "(",	/*(*/
507 ")",	/*)*/
508 "[",	/*[*/
509 "]",	/*]*/
510 "\033\016J\033\017",	/*degree*/
511 "\033\016M\b_\033\017",	/*dagger*/
512 "=",	/*=*/
513 "\033\016O\b&\033\017",	/*registered*/
514 ":",	/*:*/
515 "+",	/*+*/
516 "\0",	/*blank*/
517 "!",	/*!*/
518 "\033\016O\b~\033\017",	/*bullet*/
519 "?",	/*?*/
520 "\'",	/*foot mark*/
521 "|",	/*|*/
522 "\0",	/*blank*/
523 "\033\016O\b#\033\017",	/*copyright*/
524 "\033\016L\033\017",	/*square*/
525 "$" };	/*$*/
526 
527 char *spectab[128] = {
528 "\0",	/*blank*/
529 "\033\016(\bM\033\017",	/*psi*/
530 "\033\016o\b_\033\017",	/*theta*/
531 "v\b)",	/*nu*/
532 "\033\016V\b,\033\017",	/*mu*/
533 "\033\016)\b?\033\017",	/*lambda*/
534 "\033\016I\033\017",	/*iota*/
535 "S\b\033\016Z\033\017",	/*zeta*/
536 "o\b\'",	/*sigma*/
537 "o\b\033\0165\033\017",	/*delta*/
538 "\033\016b\033\017",	/*beta*/
539 "\033\016e\bc\033\017",	/*xi*/
540 "j\b\033\016C\033\017",	/*eta*/
541 "\033\016O\bM\033\017",	/*phi*/
542 "\033\016(\033\017",	/*upsilon*/
543 "\033\016k\033\017",	/*kappa*/
544 "\0",	/*blank*/
545 "T\b\033\016S\033\017",	/*pi*/
546 "@",	/*at-sign*/
547 "\033\016U\033\017",	/*down arrow*/
548 "\0",	/*blank*/
549 "\033\016A\033\017",	/*alpha*/
550 "|",	/*or*/
551 "l\b/",	/*chi*/
552 "\"",	/*"*/
553 "\033\016E\033\017",	/*epsilon*/
554 "=",	/*=*/
555 "\033\016O\033\017",	/*omicron*/
556 "\033\016[\033\017",	/*left arrow*/
557 "\033\016R\033\017",	/*rho*/
558 "\033\016Y\033\017",	/*up arrow*/
559 "\033\016N\033\017",	/*tau*/
560 "_",	/*underrule*/
561 "\\",	/*\*/
562 "I\b\033\016(\033\017",	/*Psi*/
563 "\033\016O\bJ\033\017",	/*bell system sign*/
564 "\033\016W\bX\033\017",	/*infinity*/
565 "`\b/",	/*gamma*/
566 "\033\016X\bF\033\017",	/*improper superset*/
567 "\033\016A\033\017",	/*proportional to*/
568 "\033\016\\\b]\033\017",	/*right hand*/
569 "\033\016W\033\017",	/*omega*/
570 "\0",	/*blank*/
571 "\033\016G\033\017",	/*gradient*/
572 "\0",	/*blank*/
573 "I\033\016\bO\033\017",	/*Phi*/
574 "O\b=",	/*Theta*/
575 "O\b_",	/*Omega*/
576 "\033\016V\033\017",	/*cup (union)*/
577 "\033\016@\033\017",	/*root en*/
578 "s",	/*terminal sigma*/
579 "\033\016)\bK\033\017",	/*Lambda*/
580 "-",	/*minus*/
581 "\033\016S\bK\033\017",	/*Gamma*/
582 "\033\016i\033\017",	/*integral sign*/
583 "\033\016t\b'\033\017",	/*Pi*/
584 "\033\016Z\033\017",	/*subset of*/
585 "\033\016X\033\017",	/*superset of*/
586 "\033\016T\033\017",	/*approximates*/
587 "o\b`",	/*partial derivative*/
588 "\033\016H\033\017",	/*Delta*/
589 "\033\016I\b'\033\017",	/*square root*/
590 ">\b\033\016F\b@\033\017",	/*Sigma*/
591 "\033\016T\bF\033\017",	/*approx =*/
592 "\0",	/*blank*/
593 ">",	/*>*/
594 "\033\016_\bF\b@\033\017",	/*Xi*/
595 "<",	/*<*/
596 "/",	/*slash (longer)*/
597 "\033\016C\033\017",	/*cap (intersection)*/
598 "\033\016y\033\017",	/*Upsilon*/
599 "\033\016|\033\017",	/*not*/
600 "|",	/*right ceiling (rt of ")*/
601 "|",	/*left top (of big curly)*/
602 "|",	/*bold vertical*/
603 "|",	/*left center of big curly bracket*/
604 "|",	/*left bottom*/
605 "|",	/*right top*/
606 "|",	/*right center of big curly bracket*/
607 "|",	/*right bot*/
608 "|",	/*right floor (rb of ")*/
609 "|",	/*left floor (left bot of big sq bract)*/
610 "|",	/*left ceiling (lt of ")*/
611 "\033\016=\033\017",	/*multiply*/
612 "\033\016+\033\017",	/*divide*/
613 "+\b_",	/*plus-minus*/
614 "\033\016$\033\017",	/*<=*/
615 "\033\016^\033\017",	/*>=*/
616 "=\b_",	/*identically equal*/
617 "\033\016*\033\017",	/*not equal*/
618 "{",	/*{*/
619 "}",	/*}*/
620 "\'",	/*' acute accent*/
621 "`",	/*` grave accent*/
622 "^",	/*^*/
623 "#",	/*sharp*/
624 "\033\016|\b[\033\017",	/*left hand*/
625 "\033\016c\b_\033\017",	/*member of*/
626 "~",	/*~*/
627 "\033\016O\b/\033\017",	/*empty set*/
628 "\0",	/*blank*/
629 "\033\016%\bM\033\017",	/*dbl dagger*/
630 "|",	/*box rule*/
631 "*",	/*asterisk*/
632 "\033\016Z\bF\033\017",	/*improper subset*/
633 "\033\016O\033\017",	/*circle*/
634 "\0",	/*blank*/
635 "+",	/*eqn plus*/
636 "\033\016]\033\017",	/*right arrow*/
637 "g\b\033\016C\033\017" };	/*section mark*/
638