#include "tdef.hd"
#include "strs.hd"

/*
troff6.c

width functions, sizes and fonts
*/

#ifndef INCORE
extern struct envblock eblock;
#else
extern struct envblock eblock[NEV];
extern int ev;
#endif
extern struct datablock dblock;

#ifdef ebcdic
extern char *fname();
#endif
extern int *cstk[], cstkl;
extern int tch[];
extern int ch_CMASK;
extern long atoi0();
extern int eschar;
extern int widthp;
extern int xpts;
extern int xfont;
extern int code;
extern int smnt;
extern int setwdf;
extern int cs;
extern int ccs;
extern int xbitf;
extern int mfont;
extern int mpts;
extern int pfont;
extern int ppts;
extern int oldbits;
extern int nonumb;
extern int noscale;
extern int nlflg;
extern int nform;
extern int dfact;
extern int vflag;
extern int lg;
extern char fontfile[];
extern int ffi;
extern int bd;
extern int level;
extern int ch;
extern int res;
extern filedes ptid;
extern char ftR[],ftI[],ftB[],ftS[];
int trflg;
char *fontab[] = {ftR, ftI, ftB, ftS};
int fontlab[] = {'R','I','B','S',0};
char pstab[] = {6,7,8,9,10,11,12,14,16,18,20,22,24,28,36,0};
char psctab[] = {010,000,001,007,002,003,004,005,0211,006,
		0212,0213,0214,0215,0216,0};
int cstab[4], ccstab[4];
int bdtab[4];
int sbold = 0;
int spsz = 0;
struct fz {
	char sign;
	char size;
	int fzinc;
	} fz[4];
width(c)
int c;
{
	register i,j,k;

	j = c;
	k = 0;
	if(j & MOT){
		if(j & VMOT)goto rtn;
		k = j & ~MOTV;
		if(j & NMOT)k = -k;
		goto rtn;
	}
	if((i = (j & CMASK)) == 010){
		k = -widthp;
		goto rtn;
	}
	if(i == PRESC)i = eschar;
	if((i == ohc) ||
	   (i >= 0370))goto rtn;
	if((j>>BYTE) == oldbits){
		xfont = pfont;
		xpts = ppts;
	}else xbits(j);
	if(j & ZBIT)goto rtn;
	if(!trflg)i = trtab[i] & BMASK;
	if((i -= 32) < 0)goto rtn;
	k = getcw(i);
	if(bd)k += bd - 1;
	if(cs)k = cs;
	widthp = k;
rtn:
	xbitf = trflg = 0;
	return(k);
}
getcw(i)
int i;
{
	register j,k;
	register char *p;
	int x;
	extern char codetab[];

	bd = 0;
	if((code = codetab[i])  & 0200){
		if(smnt){
			p = fontab[smnt-1];
			if(xfont == (sbold-1))bd = bdtab[smnt-1];
			goto g0;
		}
		code = 0;
		k = 36;
		goto g1;
	}
	p = fontab[xfont];
g0:
	if(!i)k = spacesz;
	else k = *(p + i) & BMASK;
	if(setwdf)v_ct |= ((k>>6) & 3);
g1:
	k = (j = (k&077)*(xpts&077))/6;
	if((j%6) >= 3)k++;
	if(cs = cstab[xfont]){
		if(ccs = ccstab[xfont])x = ccs; else x = xpts;
		cs = (j = (cs&077)*(x&077))/6;
		if((j%6) >= 3)cs++;
	}
	if(!bd)bd = bdtab[xfont];
	return(k);
}
xbits(i)
int i;
{
	register j, k;

	j = i >> BYTE;
	xfont = (j>>1) & 03;
	if(k = (j>>3) & 017){
		xpts = pstab[--k];
		if(psctab[k] < 0)xpts |= DBL;
		oldbits = j;
		pfont = xfont;
		ppts = xpts;
		goto rtn;
	}
	switch(xbitf){
		case 0:
			xfont = font;
			xpts = pts;
			break;
		case 1:
			xfont = pfont;
			xpts = ppts;
			break;
		case 2:
			xfont = mfont;
			xpts = mpts;
	}
rtn:
	xbitf = 0;
}
setch(){
	register i,*j,k;
	extern int chtab[];

	if((i = getrq()) == 0)return(0);
	for(j=chtab;*j != i;j++)if(*(j++) == 0)return(0);
	k = *(++j) | chbits;
	return(k);
}
find(i,j)
int i,j[];
{
	register k;

	if(((k = i-'0') >= 1) && (k <= 4) && (k != smnt))return(--k);
	for(k=0; j[k] != i; k++)if(j[k] == 0)return(-1);
	return(k);
}
caseps(){
	register i;

	if(skip())i = apts1;
	else{
		noscale++;
		i = inumb(&apts);
		noscale = 0;
		if(nonumb)return;
	}
	casps1(i);
}
casps1(i)
int i;
{
	if(i <= 0)return;
	if(fz[font].size){
		i = getfz(font, i);
	}
	apts1 = apts;
	apts = i;
	pts1 = pts;
	pts = findps(i & 077);
	mchbits();
}
findps(i)
int i;
{
	register j, k;

	for(j=0; i > (k = pstab[j]);j++)if(!k){k=pstab[--j];break;}
	if(psctab[j] < 0)k |= DBL;
	return(k);
}
mchbits(){
	register i, j, k;

	spbits = 0;
	i = pts & 077;
	for(j=0; i > (k = pstab[j]);j++)if(!k){k=pstab[--j];break;}
	chbits = (((++j)<<2) | font) << (BYTE + 1);
	sps = width(' ' | chbits);
	if(font == (spsz-1)){
		i = findps(getfz(smnt-1, apts + fz[font].fzinc));
		for(j=0; i > (k = pstab[j]);j++)if(!k){k=pstab[--j];break;}
		spbits = (((++j)<<2) | font) << (BYTE + 1);
	}
}
getfz(x,y)
int x, y;
{
	register i, j;

	i = fz[x].size;
	j = fz[x].sign;
	if(i || j){
		if(j == '+')i += y;
		else if(j == '-')i = y - i;
	}
	fz[x].fzinc = y - i;
	return(i);
}
setps(){
	register i,j;

	if((((i=getch() & CMASK) == '+')  || (i == '-')) &&
	  (((j=(ch = getch() & CMASK) - '0') >= 0) && (j <= 9))){
		if(i == '-')j = -j;
		ch = 0;
		casps1(apts+j);
		return;
	}
	if((i -= '0') == 0){
		casps1(apts1);
		return;
	}
	if((i > 0) && (i <= 9)){
		if((i <= 3) &&
		  ((j=(ch = getch() & CMASK) - '0') >= 0) && (j <= 9)){
			i = 10*i +j;
			ch = 0;
		}
		casps1(i);
	}
}
caseft(){
	skip();
	setfont(1);
}
setfont(a)
int a;
{
	register i,j;

	if(a)i = getrq();
		else i = getsn();
	if(!i || (i == 'P'))
		j = font1;
	    else if ((i == 'S') || ((j = find(i,fontlab)) == -1)) return;
	font1 = font;
	font = j;
	i = 0;
	if(fz[font1].size){
		i++;
		casps1(apts + fz[font1].fzinc);
	}else if(fz[font].size){
		i++;
		casps1(apts);
	}
	if(!i)mchbits();
}
setwd(){
	register i, base, wid;
	int delim, em, k;
	int savlevel, savhp, savapts, savapts1, savfont, savfont1,
		savpts, savpts1;

	base = v_st = v_sb = wid = v_ct = 0;
	if((delim = getch() & CMASK) & MOT)return;
	savhp = v_hp;
	savlevel = level;
	v_hp = level = 0;
	savapts = apts;
	savapts1 = apts1;
	savfont = font;
	savfont1 = font1;
	savpts = pts;
	savpts1 = pts1;
	setwdf++;
	while ((i = getch()) && (ch_CMASK != delim) && !nlflg) {
		wid += width(i);
		if(!(i & MOT)){
			em = (xpts & 077)*6;
		}else if(i & VMOT){
			k = i & ~MOTV;
			if(i & NMOT)k = -k;
			base -= k;
			em = 0;
		}else continue;
		if(base < v_sb)v_sb = base;
		if((k=base + em) > v_st)v_st = k;
	}
	nform = 0;
	setn1(wid);
	v_hp = savhp;
	level = savlevel;
	apts = savapts;
	apts1 = savapts1;
	font = savfont;
	font1 = savfont1;
	pts = savpts;
	pts1 = savpts1;
	mchbits();
	setwdf = 0;
}
mot(){
	register i, j;

	j = HOR;
	getch(); /*eat delim*/
	if(i = atoi()){
		if(vflag)j = VERT;
		i = makem(quant(i,j));
	}
	getch();
	vflag = 0;
	dfact = 1;
	return(i);
}
sethl(k)
int k;
{
	register i;

	i = 3 * (pts & 077);
	if(k == 'u')i = -i;
	else if(k == 'r')i = -2*i;
	vflag++;
	i = makem(i);
	vflag = 0;
	return(i);
}
makem(i)
int i;
{
	register j;

	if((j = i) < 0)j = -j;
	j = (j & ~MOTV) | MOT;
	if(i < 0)j |= NMOT;
	if(vflag)j |= VMOT;
	return(j);
}
getlg(i)
int i;
{
	register j, k;

	switch((j = getch0()) & CMASK){
		case 'f':
			if(lg!=2){switch((k =getch0()) & CMASK){
					case 'i':
						j = 0214;
						break;
					case 'l':
						j = 0215;
						break;
					default:
						setch0(k);
						j = 0213;
				}
			}else j = 0213;
			break;
		case 'l':
			j = 0212;
			break;
		case 'i':
			j = 0211;
			break;
		default:
			setch0(j);
			j = i;
	}
	return((i & ~CMASK) | j);
}
caselg(){

	lg = 1;
	if(skip())return;
	lg = atoi();
}
casefp(){
	register i, j;
	int chr;

	skip();
	if(((i = (getch() & CMASK) - '0' -1) < 0) || (i >3)) {
		prstr("fp: bad font position\n");
		return;	}
	if(skip() || !(j = getrq())){prstr("fp: no font name\n"); return;}
	fontfile[ffi] = j & BMASK;
	fontfile[ffi+1] = j>>BYTE;
#ifdef tso
	if (fontfile[ffi+1])	{
		fontfile[ffi+2] = '.';	/* fudge file name (to ftxx.f) */
		fontfile[ffi+3] = 'f';	}
	    else	{
		fontfile[ffi+1] = '.';
		fontfile[ffi+2] = 'f';	}
#endif
	getfont(i,0);		/* read in font table */
	if(i == (smnt-1)){smnt = 0; sbold = 0; spsz = 0;}
	if((fontlab[i] = j) == 'S')smnt = i + 1;
	bdtab[i] = cstab[i] = ccstab[i] = 0;
	fz[i].fzinc = fz[i].sign = fz[i].size = 0;
#ifndef tso
	if(ptid != 1){
#endif
		prstr("Mount font ");
		aprstr(&fontfile[ffi]);
		prstr(" on ");
		chr = PAIR((i + '1'),0);
		aprstr(&chr);
		prstr("\n");
#ifndef tso
	}
#endif
}
getfont(pos,new)
int pos,new;
{
	register filedes k;

#ifdef unix
	if((k = open(fontfile,0)) < 0){
#endif
#ifdef tso
	if ((k = fopen(fname(fontfile),"r,BINARY"))==NULL) {
#endif
		if (!new) prstr("Non-existent font type");
		    else  prstr("Unknown output device");
	c0:
		prstr("\n");
		done(-1);
	}
#ifdef unix
	if(read(k,fontab[pos],256-32) != 256-32){
#endif
#ifdef tso
	if (fread((char *)fontab[pos],1,256-32,k) != 256-32) {
#endif
		prstr("Cannot read font file");
		goto c0;
	}
#ifdef unix
	close(k);
#endif
#ifdef tso
	fclose(k);
#endif
}
casecs(){
	register i, j;

	noscale++;
	skip();
	if(!(i=getrq()) ||
	  ((i = find(i,fontlab)) < 0))goto rtn;
	skip();
	cstab[i] = atoi();
	skip();
	j = atoi();
	if(!nonumb)ccstab[i] = findps(j);
rtn:
	noscale = 0;
}
casebd(){
	register i, j, k;

	k = 0;
bd0:
	if(skip() || !(i = getrq()) ||
	  ((j = find(i,fontlab))  == -1)){
		if(k)goto bd1;
		else return;
	}
	if(j == (smnt-1)){
		k = smnt;
		goto bd0;
	}
	if(k){
		sbold = j + 1;
		j = k -1;
	}
bd1:
	skip();
	noscale++;
	bdtab[j] = atoi();
	noscale = 0;
}
casevs(){
	register i;

	skip();
	vflag++;
	dfact = 6; /*default scaling is points!*/
	res = VERT;
	i = inumb(&lss);
	if(nonumb)i = lss1;
	if(i < VERT)i = VERT;
	lss1 = lss;
	lss = i;
}
casess(){
	register i;

	noscale++;
	skip();
	if(i = atoi()){
		spacesz = i& 0177;
		sps = width(' ' | chbits);
	}
	noscale = 0;
}
xlss(){
	register i, j;

	getch();
	dfact = lss;
	i = quant(atoi(),VERT);
	dfact = 1;
	getch();
	if((j = i) < 0)j = -j;
	setch0(((j & 03700)<<3) | HX);
	if(i < 0) setch0(tch[0] | 040000);
	return(((j & 077)<<9) | LX);
}

casepi()	{}
