/* t5.c: read data for table */
# include "t.h"

void
gettbl(void)
{
	int	icol, ch;

	cstore = cspace = chspace();
	textflg = 0;
	for (nlin = nslin = 0; gets1(cstore, MAXCHS - (cstore - cspace)); nlin++) {
		stynum[nlin] = nslin;
		if (prefix(".TE", cstore)) {
			leftover = 0;
			break;
		}
		if (prefix(".TC", cstore) || prefix(".T&", cstore)) {
			readspec();
			nslin++;
		}
		if (nlin >= MAXLIN) {
			leftover = cstore;
			break;
		}
		fullbot[nlin] = 0;
		if (cstore[0] == '.' && !isdigit((uchar)cstore[1])) {
			instead[nlin] = cstore;
			while (*cstore++)
				;
			continue;
		} else 
			instead[nlin] = 0;
		if (nodata(nlin)) {
			if (ch = oneh(nlin))
				fullbot[nlin] = ch;
			table[nlin] = (struct colstr *) alocv((ncol + 2) * sizeof(table[0][0]));
			for (icol = 0; icol < ncol; icol++) {
				table[nlin][icol].rcol = "";
				table[nlin][icol].col = "";
			}
			nlin++;
			nslin++;
			fullbot[nlin] = 0;
			instead[nlin] = (char *) 0;
		}
		table[nlin] = (struct colstr *) alocv((ncol + 2) * sizeof(table[0][0]));
		if (cstore[1] == 0)
			switch (cstore[0]) {
			case '_': 
				fullbot[nlin] = '-'; 
				continue;
			case '=': 
				fullbot[nlin] = '='; 
				continue;
			}
		stynum[nlin] = nslin;
		nslin = min(nslin + 1, nclin - 1);
		for (icol = 0; icol < ncol; icol++) {
			table[nlin][icol].col = cstore;
			table[nlin][icol].rcol = 0;
			ch = 1;
			if (match(cstore, "T{")) { /* text follows */
				table[nlin][icol].col = 
				    (char *)(uintptr)gettext(cstore, nlin, icol,
				    font[icol][stynum[nlin]],
				    csize[icol][stynum[nlin]]);
			} else
			 {
				for (; (ch = *cstore) != '\0' && ch != tab; cstore++)
					;
				*cstore++ = '\0';
				switch (ctype(nlin, icol)) /* numerical or alpha, subcol */ {
				case 'n':
					table[nlin][icol].rcol = maknew(table[nlin][icol].col);
					break;
				case 'a':
					table[nlin][icol].rcol = table[nlin][icol].col;
					table[nlin][icol].col = "";
					break;
				}
			}
			while (ctype(nlin, icol + 1) == 's') /* spanning */
				table[nlin][++icol].col = "";
			if (ch == '\0') 
				break;
		}
		while (++icol < ncol + 2) {
			table[nlin][icol].col = "";
			table [nlin][icol].rcol = 0;
		}
		while (*cstore != '\0')
			cstore++;
		if (cstore - cspace + MAXLINLEN > MAXCHS)
			cstore = cspace = chspace();
	}
	last = cstore;
	permute();
	if (textflg) 
		untext();
	return;
}


int
nodata(int il)
{
	int	c;

	for (c = 0; c < ncol; c++) {
		switch (ctype(il, c)) {
		case 'c': 
		case 'n': 
		case 'r': 
		case 'l': 
		case 's': 
		case 'a':
			return(0);
		}
	}
	return(1);
}


int
oneh(int lin)
{
	int	k, icol;

	k = ctype(lin, 0);
	for (icol = 1; icol < ncol; icol++) {
		if (k != ctype(lin, icol))
			return(0);
	}
	return(k);
}


# define SPAN "\\^"

void
permute(void)
{
	int	irow, jcol, is;
	char	*start, *strig;

	for (jcol = 0; jcol < ncol; jcol++) {
		for (irow = 1; irow < nlin; irow++) {
			if (vspand(irow, jcol, 0)) {
				is = prev(irow);
				if (is < 0)
					error("Vertical spanning in first row not allowed");
				start = table[is][jcol].col;
				strig = table[is][jcol].rcol;
				while (irow < nlin && vspand(irow, jcol, 0))
					irow++;
				table[--irow][jcol].col = start;
				table[irow][jcol].rcol = strig;
				while (is < irow) {
					table[is][jcol].rcol = 0;
					table[is][jcol].col = SPAN;
					is = next(is);
				}
			}
		}
	}
}


int
vspand(int ir, int ij, int ifform)
{
	if (ir < 0) 
		return(0);
	if (ir >= nlin)
		return(0);
	if (instead[ir]) 
		return(0);
	if (ifform == 0 && ctype(ir, ij) == '^') 
		return(1);
	if (table[ir][ij].rcol != 0) 
		return(0);
	if (fullbot[ir]) 
		return(0);
	return(vspen(table[ir][ij].col));
}


int
vspen(char *s)
{
	if (s == 0) 
		return(0);
	if (!point(s)) 
		return(0);
	return(match(s, SPAN));
}


