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