BSD 4 release
[unix-history] / usr / src / cmd / tc.c
static char *sccsid = "@(#)tc.c 4.1 (Berkeley) 10/1/80";
/*
* Simulate typesetter on 4014
*/
#include <signal.h>
#include <stdio.h>
#define oput(c) if (pgskip==0) putchar(c); else;
#define MAXY 3071
#define US 037
#define GS 035
#define ESC 033
#define FF 014
#define DBL 0200
int pl = 11*144;
int mpy = 1;
int div = 1;
char *ap;
int ch;
int nonumb;
int psize = 10;
int dfact = 1;
int esc;
int escd;
int verd;
int esct;
int osize = 02;
int size = 02;
int rx;
int xx;
int yy = MAXY+62+48;
int leadtot = -31;
int ohy = -1;
int ohx = -1;
int oxb = -1;
int oly = -1;
int olx = -1;
int tflag;
int railmag;
int lead;
int skip;
int pgskip;
int ksize = ';';
int mcase;
int stab[] = {010,0,01,07,02,03,04,05,0211,06,0212,0213,0214,0215,0216,0217};
int rtab[] = {6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 28, 36, 18};
int ktab[] = {';',';',';',';',';',';',':',':','9','9','9','9','8','8','8','9'};
int first = 1;
int alpha;
extern char *asctab[128];
extern char *spectab[128];
int erase = 1;
int (*sigint)();
int (*sigquit)();
main(argc,argv)
int argc;
char **argv;
{
register i, j;
register char *k;
extern ex();
while((--argc > 0) && ((++argv)[0][0]=='-')){
switch(argv[0][1]){
case 'p':
ap = &argv[0][2];
dfact = 72;
if(i = atoi())pl = i/3;
continue;
case 't':
tflag++;
continue;
case 's':
ap = &argv[0][2];
dfact = 1;
pgskip = atoi();
continue;
default:
dfact = 1;
ap = &argv[0][1];
if(i = atoi())mpy = i;
if(i = atoi())div = i;
continue;
}
}
if(argc){
if (freopen(argv[0], "r", stdin) == NULL) {
fprintf(stderr, "tc: cannot open %s\n", argv[0]);
exit(1);
}
}
sigint = signal(SIGINT, ex);
sigquit = signal(SIGQUIT, SIG_IGN);
while((i = getchar()) != EOF){
if(!i)continue;
if(i & 0200){
esc += (~i) & 0177;
continue;
}
if(esc){
if(escd)esc = -esc;
esct += esc;
xx += (esc*mpy + rx)/div;
rx = (esc*mpy + rx)%div;
sendpt();
esc = 0;
}
switch(i){
case 0100: /*init*/
escd = verd = mcase = railmag = xx = 0;
yy = MAXY + 48;
leadtot = -31;
ohy = oxb = oly = ohx = olx = -1;
oput(US);
fflush(stdout);
if(!first && !tflag)kwait();
if(first){
first = 0;
yy += 62;
}
init();
continue;
case 0101: /*lower rail*/
railmag &= ~01;
continue;
case 0102: /*upper rail*/
railmag |= 01;
continue;
case 0103: /*upper mag*/
railmag |= 02;
continue;
case 0104: /*lower mag*/
railmag &= ~02;
continue;
case 0105: /*lower case*/
mcase = 0;
continue;
case 0106: /*upper case*/
mcase = 0100;
continue;
case 0107: /*escape forward*/
escd = 0;
continue;
case 0110: /*escape backward*/
escd = 1;
continue;
case 0111: /*stop*/
continue;
case 0112: /*lead forward*/
verd = 0;
continue;
case 0113: /*undefined*/
continue;
case 0114: /*lead backward*/
verd = 1;
continue;
case 0115: /*undefined*/
case 0116:
case 0117:
continue;
}
if((i & 0340) == 0140){ /*leading*/
lead = (~i) & 037;
if(verd)lead = -lead;
if((leadtot += lead) > pl){
leadtot = lead;
oput(US);
fflush(stdout);
if(!tflag)kwait();
yy = MAXY;
if(pgskip)--pgskip;
init();
continue;
}
if(skip)continue;
if((yy -= (lead<<1)) < 0){
skip++;
yy = 0;
}else sendpt();
continue;
}
if((i & 0360) == 0120){ /*size change*/
i &= 017;
for(j = 0; i != (stab[j] & 017); j++);
osize = size;
size = stab[j];
psize = rtab[j];
ksize = ktab[j];
oput(ESC);
oput(ksize);
i = 0;
if(!(osize & DBL) && (size & DBL))i = -55;
else if((osize & DBL) && !(size & DBL))i = 55;
if(escd)i = -i;
esc += i;
continue;
}
if(i & 0300)continue;
i = (i & 077) | mcase;
if(railmag != 03)k = asctab[i];
else k = spectab[i];
if(alpha)sendpt();
if(*k!='\0'){
oput(US);
while(*k & 0377)oput(*k++);
alpha++;
continue;
}else{
if(railmag != 03){
switch(i){
case 0124: lig("fi"); break;
case 0125: lig("fl"); break;
case 0126: lig("ff"); break;
case 0130: lig("ffl"); break;
case 0131: lig("ffi"); break;
default: continue;
}
}
continue;
}
}
ex();
}
lig(x)
char *x;
{
register i, j;
register char *k;
j = 0;
k = x;
oput(US);
oput(*k++);
i = psize * 8 * mpy / (div * 6); /* 8/36 em */
while(*k){
xx += i;
j += i;
sendpt();
oput(US);
oput(*k++);
}
xx -= j;
sendpt();
}
init(){
fflush(stdout);
if(erase){
oput(ESC);
oput(FF);
}else erase = 1;
oput(ESC);
oput(ksize);
/*delay about a second*/
/* let the system do it...
for(i = 960; i > 0; i--)oput(GS);
*/
skip = 0;
sendpt();
}
ex(){
yy = MAXY;
xx = 0;
sendpt();
oput(ESC);
oput(';');
oput(US);
fflush(stdout);
exit(0);
}
kwait(){
char buf[128]; char *bptr; char c;
if(pgskip) return;
next:
bptr=buf;
while((c=readch())&&(c!='\n')) *bptr++=c;
*bptr=0;
if(bptr!=buf){
bptr = buf;
if(*bptr == '!'){callunix(&buf[1]); fputs("!\n", stderr); goto next;}
else switch(*bptr++){
case 'e':
erase = 0;
goto next;
case 's':
ap = &buf[1];
dfact = 1;
pgskip = atoi() + 1;
goto next;
default:
fputs("?\n", stderr);
goto next;
}
}
else if (c==0) ex();
else return;
}
callunix(line)
char line[];
{
int rc, status, unixpid;
if( (unixpid=fork())==0 ) {
signal(SIGINT,sigint); signal(SIGQUIT,sigquit);
close(0); dup(2);
execl("/bin/sh", "-sh", "-c", line, 0);
exit(255);
}
else if(unixpid == -1)
return;
else{ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
while( (rc = wait(&status)) != unixpid && rc != -1 ) ;
signal(SIGINT,ex); signal(SIGQUIT,sigquit);
}
}
readch(){
char c;
if (read(2,&c,1)<1) c=0;
return(c);
}
sendpt(){
int hy,xb,ly,hx,lx;
oput(GS);
hy = ((yy>>7) & 037);
xb = ((xx & 03) + ((yy<<2) & 014) & 017);
ly = ((yy>>2) & 037);
hx = ((xx>>7) & 037);
lx = ((xx>>2) & 037);
if(hy != ohy)oput(hy | 040);
if(xb != oxb)oput(xb | 0140);
if((ly != oly) || (hx != ohx) || (xb != oxb))
oput(ly | 0140);
if(hx != ohx)oput(hx | 040);
oput(lx | 0100);
ohy = hy;
oxb = xb;
oly = ly;
ohx = hx;
olx = lx;
alpha = 0;
return;
}
atoi()
{
register i, j, acc;
int field, digits;
long dd;
long tscale();
field = digits = acc = 0;
a1:
while(((j = (i = getch()) - '0') >= 0) && (j <= 9)){
field++;
digits++;
acc = 10*acc + j;
}
if(i == '.'){
field++;
digits = 0;
goto a1;
}
if(!(ch = i))ch = 'x';
dd = tscale(acc);
acc = dd;
if((field != digits) && (digits > 0)){
j = 1;
while(digits--)j *= 10;
acc = dd/j;
}
nonumb = !field;
ch = 0;
return(acc);
}
long tscale(n)
int n;
{
register i, j;
switch(i = getch()){
case 'u':
j = 1;
break;
case 'p': /*Points*/
j = 6;
break;
case 'i': /*Inches*/
j = 432;
break;
case 'c': /*Centimeters; should be 170.0787*/
j = 170;
break;
case 'P': /*Picas*/
j = 72;
break;
default:
j = dfact;
ch = i;
}
return((long)n*j);
}
getch(){
register i;
if(ch){
i = ch;
ch = 0;
return(i);
}
return(*ap++);
}
char *asctab[128] = {
"\0", /*blank*/
"h", /*h*/
"t", /*t*/
"n", /*n*/
"m", /*m*/
"l", /*l*/
"i", /*i*/
"z", /*z*/
"s", /*s*/
"d", /*d*/
"b", /*b*/
"x", /*x*/
"f", /*f*/
"j", /*j*/
"u", /*u*/
"k", /*k*/
"\0", /*blank*/
"p", /*p*/
"-", /*_ 3/4 em dash*/
";", /*;*/
"\0", /*blank*/
"a", /*a*/
"_", /*rule*/
"c", /*c*/
"`", /*` open*/
"e", /*e*/
"\'", /*' close*/
"o", /*o*/
"\0", /*1/4*/
"r", /*r*/
"\0", /*1/2*/
"v", /*v*/
"-", /*- hyphen*/
"w", /*w*/
"q", /*q*/
"/", /*/*/
".", /*.*/
"g", /*g*/
"\0", /*3/4*/
",", /*,*/
"&", /*&*/
"y", /*y*/
"\0", /*blank*/
"%", /*%*/
"\0", /*blank*/
"Q", /*Q*/
"T", /*T*/
"O", /*O*/
"H", /*H*/
"N", /*N*/
"M", /*M*/
"L", /*L*/
"R", /*R*/
"G", /*G*/
"I", /*I*/
"P", /*P*/
"C", /*C*/
"V", /*V*/
"E", /*E*/
"Z", /*Z*/
"D", /*D*/
"B", /*B*/
"S", /*S*/
"Y", /*Y*/
"\0", /*blank*/
"F", /*F*/
"X", /*X*/
"A", /*A*/
"W", /*W*/
"J", /*J*/
"U", /*U*/
"K", /*K*/
"0", /*0*/
"1", /*1*/
"2", /*2*/
"3", /*3*/
"4", /*4*/
"5", /*5*/
"6", /*6*/
"7", /*7*/
"8", /*8*/
"9", /*9*/
"*", /***/
"-", /*minus*/
"", /*fi*/
"", /*fl*/
"", /*ff*/
"\033\016Z\bM\033\017", /*cent sign*/
"", /*ffl*/
"", /*ffi*/
"(", /*(*/
")", /*)*/
"[", /*[*/
"]", /*]*/
"\033\016J\033\017", /*degree*/
"\033\016M\b_\033\017", /*dagger*/
"=", /*=*/
"\033\016O\b&\033\017", /*registered*/
":", /*:*/
"+", /*+*/
"\0", /*blank*/
"!", /*!*/
"\033\016O\b~\033\017", /*bullet*/
"?", /*?*/
"\'", /*foot mark*/
"|", /*|*/
"\0", /*blank*/
"\033\016O\b#\033\017", /*copyright*/
"\033\016L\033\017", /*square*/
"$" }; /*$*/
char *spectab[128] = {
"\0", /*blank*/
"\033\016(\bM\033\017", /*psi*/
"\033\016o\b_\033\017", /*theta*/
"v\b)", /*nu*/
"\033\016V\b,\033\017", /*mu*/
"\033\016)\b?\033\017", /*lambda*/
"\033\016I\033\017", /*iota*/
"S\b\033\016Z\033\017", /*zeta*/
"o\b\'", /*sigma*/
"o\b\033\0165\033\017", /*delta*/
"\033\016b\033\017", /*beta*/
"\033\016e\bc\033\017", /*xi*/
"j\b\033\016C\033\017", /*eta*/
"\033\016O\bM\033\017", /*phi*/
"\033\016(\033\017", /*upsilon*/
"\033\016k\033\017", /*kappa*/
"\0", /*blank*/
"T\b\033\016S\033\017", /*pi*/
"@", /*at-sign*/
"\033\016U\033\017", /*down arrow*/
"\0", /*blank*/
"\033\016A\033\017", /*alpha*/
"|", /*or*/
"l\b/", /*chi*/
"\"", /*"*/
"\033\016E\033\017", /*epsilon*/
"=", /*=*/
"\033\016O\033\017", /*omicron*/
"\033\016[\033\017", /*left arrow*/
"\033\016R\033\017", /*rho*/
"\033\016Y\033\017", /*up arrow*/
"\033\016N\033\017", /*tau*/
"_", /*underrule*/
"\\", /*\*/
"I\b\033\016(\033\017", /*Psi*/
"\033\016O\bJ\033\017", /*bell system sign*/
"\033\016W\bX\033\017", /*infinity*/
"`\b/", /*gamma*/
"\033\016X\bF\033\017", /*improper superset*/
"\033\016A\033\017", /*proportional to*/
"\033\016\\\b]\033\017", /*right hand*/
"\033\016W\033\017", /*omega*/
"\0", /*blank*/
"\033\016G\033\017", /*gradient*/
"\0", /*blank*/
"I\033\016\bO\033\017", /*Phi*/
"O\b=", /*Theta*/
"O\b_", /*Omega*/
"\033\016V\033\017", /*cup (union)*/
"\033\016@\033\017", /*root en*/
"s", /*terminal sigma*/
"\033\016)\bK\033\017", /*Lambda*/
"-", /*minus*/
"\033\016S\bK\033\017", /*Gamma*/
"\033\016i\033\017", /*integral sign*/
"\033\016t\b'\033\017", /*Pi*/
"\033\016Z\033\017", /*subset of*/
"\033\016X\033\017", /*superset of*/
"\033\016T\033\017", /*approximates*/
"o\b`", /*partial derivative*/
"\033\016H\033\017", /*Delta*/
"\033\016I\b'\033\017", /*square root*/
">\b\033\016F\b@\033\017", /*Sigma*/
"\033\016T\bF\033\017", /*approx =*/
"\0", /*blank*/
">", /*>*/
"\033\016_\bF\b@\033\017", /*Xi*/
"<", /*<*/
"/", /*slash (longer)*/
"\033\016C\033\017", /*cap (intersection)*/
"\033\016y\033\017", /*Upsilon*/
"\033\016|\033\017", /*not*/
"|", /*right ceiling (rt of ")*/
"|", /*left top (of big curly)*/
"|", /*bold vertical*/
"|", /*left center of big curly bracket*/
"|", /*left bottom*/
"|", /*right top*/
"|", /*right center of big curly bracket*/
"|", /*right bot*/
"|", /*right floor (rb of ")*/
"|", /*left floor (left bot of big sq bract)*/
"|", /*left ceiling (lt of ")*/
"\033\016=\033\017", /*multiply*/
"\033\016+\033\017", /*divide*/
"+\b_", /*plus-minus*/
"\033\016$\033\017", /*<=*/
"\033\016^\033\017", /*>=*/
"=\b_", /*identically equal*/
"\033\016*\033\017", /*not equal*/
"{", /*{*/
"}", /*}*/
"\'", /*' acute accent*/
"`", /*` grave accent*/
"^", /*^*/
"#", /*sharp*/
"\033\016|\b[\033\017", /*left hand*/
"\033\016c\b_\033\017", /*member of*/
"~", /*~*/
"\033\016O\b/\033\017", /*empty set*/
"\0", /*blank*/
"\033\016%\bM\033\017", /*dbl dagger*/
"|", /*box rule*/
"*", /*asterisk*/
"\033\016Z\bF\033\017", /*improper subset*/
"\033\016O\033\017", /*circle*/
"\0", /*blank*/
"+", /*eqn plus*/
"\033\016]\033\017", /*right arrow*/
"g\b\033\016C\033\017" }; /*section mark*/