xref: /original-bsd/old/tc/tc.c (revision e4dd4c49)
1 static char *sccsid = "@(#)tc.c	4.4 (Berkeley) 01/02/90";
2 /*
3  * Simulate typesetter on 4014
4 */
5 
6 #include <sys/signal.h>
7 #include <paths.h>
8 #include <stdio.h>
9 
10 #define	oput(c) if (pgskip==0) putchar(c); else (c);
11 #define MAXY 3071
12 #define US 037
13 #define GS 035
14 #define ESC 033
15 #define FF 014
16 #define DBL 0200
17 
18 int pl = 11*144;
19 int mpy = 1;
20 int div = 1;
21 char *ap;
22 int ch;
23 int nonumb;
24 int psize = 10;
25 int dfact = 1;
26 int esc;
27 int escd;
28 int verd;
29 int esct;
30 int osize = 02;
31 int size = 02;
32 int rx;
33 int xx;
34 int yy = MAXY+62+48;
35 int leadtot = -31;
36 int ohy = -1;
37 int ohx = -1;
38 int oxb = -1;
39 int oly = -1;
40 int olx = -1;
41 int tflag;
42 int railmag;
43 int lead;
44 int skip;
45 int pgskip;
46 int ksize = ';';
47 int mcase;
48 int stab[] = {010,0,01,07,02,03,04,05,0211,06,0212,0213,0214,0215,0216,0217};
49 int rtab[] = {6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 28, 36, 18};
50 int ktab[] = {';',';',';',';',';',';',':',':','9','9','9','9','8','8','8','9'};
51 int first = 1;
52 int alpha;
53 extern char *asctab[128];
54 extern char *spectab[128];
55 int erase = 1;
56 sig_t sigint, sigquit;
57 
58 main(argc,argv)
59 int argc;
60 char **argv;
61 {
62 	register i, j;
63 	register char *k;
64 	extern void 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 
265 void
266 ex(){
267 	yy = MAXY;
268 	xx = 0;
269 	sendpt();
270 	oput(ESC);
271 	oput(';');
272 	oput(US);
273 	fflush(stdout);
274 	exit(0);
275 }
276 kwait(){
277 	char buf[128]; char *bptr; char c;
278 	if(pgskip) return;
279 next:
280 	bptr=buf;
281 	while((c=readch())&&(c!='\n')) *bptr++=c;
282 	*bptr=0;
283 	if(bptr!=buf){
284 		bptr = buf;
285 		if(*bptr == '!'){callunix(&buf[1]); fputs("!\n", stderr); goto next;}
286 		else switch(*bptr++){
287 			case 'e':
288 				erase = 0;
289 				goto next;
290 			case 's':
291 				ap = &buf[1];
292 				dfact = 1;
293 				pgskip = atoi() + 1;
294 				goto next;
295 			default:
296 				fputs("?\n", stderr);
297 				goto next;
298 		}
299 	}
300 	else if (c==0) ex();
301 	else	return;
302 }
303 callunix(line)
304 char line[];
305 {
306 	int rc, status, unixpid;
307 	if( (unixpid=fork())==0 ) {
308 		signal(SIGINT,sigint); signal(SIGQUIT,sigquit);
309 		close(0); dup(2);
310 		execl(_PATH_BSHELL, "-sh", "-c", line, 0);
311 		exit(255);
312 	}
313 	else if(unixpid == -1)
314 		return;
315 	else{	signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
316 		while( (rc = wait(&status)) != unixpid && rc != -1 ) ;
317 		signal(SIGINT,ex); signal(SIGQUIT,sigquit);
318 	}
319 }
320 readch(){
321 	char c;
322 	if (read(2,&c,1)<1) c=0;
323 	return(c);
324 }
325 sendpt(){
326 	int hy,xb,ly,hx,lx;
327 
328 	oput(GS);
329 	hy = ((yy>>7) & 037);
330 	xb = ((xx & 03) + ((yy<<2) & 014) & 017);
331 	ly = ((yy>>2) & 037);
332 	hx = ((xx>>7) & 037);
333 	lx = ((xx>>2) & 037);
334 	if(hy != ohy)oput(hy | 040);
335 	if(xb != oxb)oput(xb | 0140);
336 	if((ly != oly) || (hx != ohx) || (xb != oxb))
337 		oput(ly | 0140);
338 	if(hx != ohx)oput(hx | 040);
339 	oput(lx | 0100);
340 	ohy = hy;
341 	oxb = xb;
342 	oly = ly;
343 	ohx = hx;
344 	olx = lx;
345 	alpha = 0;
346 	return;
347 }
348 atoi()
349 {
350 	register i, j, acc;
351 	int field, digits;
352 	long dd;
353 	long tscale();
354 
355 	field = digits = acc = 0;
356 a1:
357 	while(((j = (i = getch()) - '0') >= 0) && (j <= 9)){
358 		field++;
359 		digits++;
360 		acc = 10*acc + j;
361 	}
362 	if(i == '.'){
363 		field++;
364 		digits = 0;
365 		goto a1;
366 	}
367 	if(!(ch = i))ch = 'x';
368 	dd = tscale(acc);
369 	acc = dd;
370 	if((field != digits) && (digits > 0)){
371 		j = 1;
372 		while(digits--)j *= 10;
373 		acc = dd/j;
374 	}
375 	nonumb = !field;
376 	ch = 0;
377 	return(acc);
378 }
379 long tscale(n)
380 int n;
381 {
382 	register i, j;
383 
384 	switch(i = getch()){
385 		case 'u':
386 			j = 1;
387 			break;
388 		case 'p':	/*Points*/
389 			j = 6;
390 			break;
391 		case 'i':	/*Inches*/
392 			j = 432;
393 			break;
394 		case 'c':	/*Centimeters; should be 170.0787*/
395 			j = 170;
396 			break;
397 		case 'P':	/*Picas*/
398 			j = 72;
399 			break;
400 		default:
401 			j = dfact;
402 			ch = i;
403 	}
404 	return((long)n*j);
405 }
406 getch(){
407 	register i;
408 
409 	if(ch){
410 		i = ch;
411 		ch = 0;
412 		return(i);
413 	}
414 	return(*ap++);
415 }
416 
417 char *asctab[128] = {
418 "\0",	/*blank*/
419 "h",	/*h*/
420 "t",	/*t*/
421 "n",	/*n*/
422 "m",	/*m*/
423 "l",	/*l*/
424 "i",	/*i*/
425 "z",	/*z*/
426 "s",	/*s*/
427 "d",	/*d*/
428 "b",	/*b*/
429 "x",	/*x*/
430 "f",	/*f*/
431 "j",	/*j*/
432 "u",	/*u*/
433 "k",	/*k*/
434 "\0",	/*blank*/
435 "p",	/*p*/
436 "-",	/*_ 3/4 em dash*/
437 ";",	/*;*/
438 "\0",	/*blank*/
439 "a",	/*a*/
440 "_",	/*rule*/
441 "c",	/*c*/
442 "`",	/*` open*/
443 "e",	/*e*/
444 "\'",	/*' close*/
445 "o",	/*o*/
446 "\0",	/*1/4*/
447 "r",	/*r*/
448 "\0",	/*1/2*/
449 "v",	/*v*/
450 "-",	/*- hyphen*/
451 "w",	/*w*/
452 "q",	/*q*/
453 "/",	/*/*/
454 ".",	/*.*/
455 "g",	/*g*/
456 "\0",	/*3/4*/
457 ",",	/*,*/
458 "&",	/*&*/
459 "y",	/*y*/
460 "\0",	/*blank*/
461 "%",	/*%*/
462 "\0",	/*blank*/
463 "Q",	/*Q*/
464 "T",	/*T*/
465 "O",	/*O*/
466 "H",	/*H*/
467 "N",	/*N*/
468 "M",	/*M*/
469 "L",	/*L*/
470 "R",	/*R*/
471 "G",	/*G*/
472 "I",	/*I*/
473 "P",	/*P*/
474 "C",	/*C*/
475 "V",	/*V*/
476 "E",	/*E*/
477 "Z",	/*Z*/
478 "D",	/*D*/
479 "B",	/*B*/
480 "S",	/*S*/
481 "Y",	/*Y*/
482 "\0",	/*blank*/
483 "F",	/*F*/
484 "X",	/*X*/
485 "A",	/*A*/
486 "W",	/*W*/
487 "J",	/*J*/
488 "U",	/*U*/
489 "K",	/*K*/
490 "0",	/*0*/
491 "1",	/*1*/
492 "2",	/*2*/
493 "3",	/*3*/
494 "4",	/*4*/
495 "5",	/*5*/
496 "6",	/*6*/
497 "7",	/*7*/
498 "8",	/*8*/
499 "9",	/*9*/
500 "*",	/***/
501 "-",	/*minus*/
502 "",	/*fi*/
503 "",	/*fl*/
504 "",	/*ff*/
505 "\033\016Z\bM\033\017",	/*cent sign*/
506 "",	/*ffl*/
507 "",	/*ffi*/
508 "(",	/*(*/
509 ")",	/*)*/
510 "[",	/*[*/
511 "]",	/*]*/
512 "\033\016J\033\017",	/*degree*/
513 "\033\016M\b_\033\017",	/*dagger*/
514 "=",	/*=*/
515 "\033\016O\b&\033\017",	/*registered*/
516 ":",	/*:*/
517 "+",	/*+*/
518 "\0",	/*blank*/
519 "!",	/*!*/
520 "\033\016O\b~\033\017",	/*bullet*/
521 "?",	/*?*/
522 "\'",	/*foot mark*/
523 "|",	/*|*/
524 "\0",	/*blank*/
525 "\033\016O\b#\033\017",	/*copyright*/
526 "\033\016L\033\017",	/*square*/
527 "$" };	/*$*/
528 
529 char *spectab[128] = {
530 "\0",	/*blank*/
531 "\033\016(\bM\033\017",	/*psi*/
532 "\033\016o\b_\033\017",	/*theta*/
533 "v\b)",	/*nu*/
534 "\033\016V\b,\033\017",	/*mu*/
535 "\033\016)\b?\033\017",	/*lambda*/
536 "\033\016I\033\017",	/*iota*/
537 "S\b\033\016Z\033\017",	/*zeta*/
538 "o\b\'",	/*sigma*/
539 "o\b\033\0165\033\017",	/*delta*/
540 "\033\016b\033\017",	/*beta*/
541 "\033\016e\bc\033\017",	/*xi*/
542 "j\b\033\016C\033\017",	/*eta*/
543 "\033\016O\bM\033\017",	/*phi*/
544 "\033\016(\033\017",	/*upsilon*/
545 "\033\016k\033\017",	/*kappa*/
546 "\0",	/*blank*/
547 "T\b\033\016S\033\017",	/*pi*/
548 "@",	/*at-sign*/
549 "\033\016U\033\017",	/*down arrow*/
550 "\0",	/*blank*/
551 "\033\016A\033\017",	/*alpha*/
552 "|",	/*or*/
553 "l\b/",	/*chi*/
554 "\"",	/*"*/
555 "\033\016E\033\017",	/*epsilon*/
556 "=",	/*=*/
557 "\033\016O\033\017",	/*omicron*/
558 "\033\016[\033\017",	/*left arrow*/
559 "\033\016R\033\017",	/*rho*/
560 "\033\016Y\033\017",	/*up arrow*/
561 "\033\016N\033\017",	/*tau*/
562 "_",	/*underrule*/
563 "\\",	/*\*/
564 "I\b\033\016(\033\017",	/*Psi*/
565 "\033\016O\bJ\033\017",	/*bell system sign*/
566 "\033\016W\bX\033\017",	/*infinity*/
567 "`\b/",	/*gamma*/
568 "\033\016X\bF\033\017",	/*improper superset*/
569 "\033\016A\033\017",	/*proportional to*/
570 "\033\016\\\b]\033\017",	/*right hand*/
571 "\033\016W\033\017",	/*omega*/
572 "\0",	/*blank*/
573 "\033\016G\033\017",	/*gradient*/
574 "\0",	/*blank*/
575 "I\033\016\bO\033\017",	/*Phi*/
576 "O\b=",	/*Theta*/
577 "O\b_",	/*Omega*/
578 "\033\016V\033\017",	/*cup (union)*/
579 "\033\016@\033\017",	/*root en*/
580 "s",	/*terminal sigma*/
581 "\033\016)\bK\033\017",	/*Lambda*/
582 "-",	/*minus*/
583 "\033\016S\bK\033\017",	/*Gamma*/
584 "\033\016i\033\017",	/*integral sign*/
585 "\033\016t\b'\033\017",	/*Pi*/
586 "\033\016Z\033\017",	/*subset of*/
587 "\033\016X\033\017",	/*superset of*/
588 "\033\016T\033\017",	/*approximates*/
589 "o\b`",	/*partial derivative*/
590 "\033\016H\033\017",	/*Delta*/
591 "\033\016I\b'\033\017",	/*square root*/
592 ">\b\033\016F\b@\033\017",	/*Sigma*/
593 "\033\016T\bF\033\017",	/*approx =*/
594 "\0",	/*blank*/
595 ">",	/*>*/
596 "\033\016_\bF\b@\033\017",	/*Xi*/
597 "<",	/*<*/
598 "/",	/*slash (longer)*/
599 "\033\016C\033\017",	/*cap (intersection)*/
600 "\033\016y\033\017",	/*Upsilon*/
601 "\033\016|\033\017",	/*not*/
602 "|",	/*right ceiling (rt of ")*/
603 "|",	/*left top (of big curly)*/
604 "|",	/*bold vertical*/
605 "|",	/*left center of big curly bracket*/
606 "|",	/*left bottom*/
607 "|",	/*right top*/
608 "|",	/*right center of big curly bracket*/
609 "|",	/*right bot*/
610 "|",	/*right floor (rb of ")*/
611 "|",	/*left floor (left bot of big sq bract)*/
612 "|",	/*left ceiling (lt of ")*/
613 "\033\016=\033\017",	/*multiply*/
614 "\033\016+\033\017",	/*divide*/
615 "+\b_",	/*plus-minus*/
616 "\033\016$\033\017",	/*<=*/
617 "\033\016^\033\017",	/*>=*/
618 "=\b_",	/*identically equal*/
619 "\033\016*\033\017",	/*not equal*/
620 "{",	/*{*/
621 "}",	/*}*/
622 "\'",	/*' acute accent*/
623 "`",	/*` grave accent*/
624 "^",	/*^*/
625 "#",	/*sharp*/
626 "\033\016|\b[\033\017",	/*left hand*/
627 "\033\016c\b_\033\017",	/*member of*/
628 "~",	/*~*/
629 "\033\016O\b/\033\017",	/*empty set*/
630 "\0",	/*blank*/
631 "\033\016%\bM\033\017",	/*dbl dagger*/
632 "|",	/*box rule*/
633 "*",	/*asterisk*/
634 "\033\016Z\bF\033\017",	/*improper subset*/
635 "\033\016O\033\017",	/*circle*/
636 "\0",	/*blank*/
637 "+",	/*eqn plus*/
638 "\033\016]\033\017",	/*right arrow*/
639 "g\b\033\016C\033\017" };	/*section mark*/
640