/**************************************************************
 *
 *	CRISP - Custom Reduced Instruction Set Programmers Editor
 *
 *	(C) Paul Fox, 1989
 *
 *    Please See COPYRIGHT notice.
 *
 **************************************************************/
# include	"list.h"

# define	TBUFSIZ		2048
# define	MAX_ENTRIES	256

int	tnamchk PROTO((char *, char *));
char	*tgetstr();
int	tgetent1 PROTO((char *, char *, int));
static int	compile_termcap();
extern char	*ggetenv();
static	char	*ubuf;		/* User's termcap buffer.		*/
static struct tc {
	int	name;
	char	*entry;
	}	*tc;
static	int	ent_count = 0;

int
tgetent(bp, name)
char	*bp;
char	*name;
{	char	buf[64];
	char	*p;
	char	*cp;

	ubuf = bp;
	tc = (struct tc *) chk_alloc(MAX_ENTRIES * sizeof (struct tc));
	if (tgetent1(bp, name, TRUE) == 0)
		return 0;
	p = buf;
	if ((cp = tgetstr("tc", &p)) == NULL)
		return 1;
	tgetent1(ubuf + strlen(ubuf), cp, FALSE);

	return 1;
}
int
tgetent1(bp, name, first_time)
char	*bp;
char	*name;
int	first_time;
{	int	fd;
	char	buf[TBUFSIZ];
	register char *cp;
	register char	*bp1 = &buf[TBUFSIZ];
	int	cnt = -1;
	char	*filename;
	char	*term = ggetenv("TERM");
	extern char *termcap_dir;
	
	/***********************************************/
	/*   If   user   has   BTERMCAP   environment  */
	/*   variable defined then use that instead.   */
	/***********************************************/
	filename = ggetenv("BTERMCAP");
	if (filename == NULL)
		filename = ggetenv("TERMCAP");

	if (filename == NULL || !first_time)
		filename = termcap_dir;
	else if (filename[0] != '/' && filename[0] != '[' && filename[1] != ':') {
		if (strcmp(term, name) == 0) {
			strncpy(bp, filename, TBUFSIZ);
			compile_termcap();
			return 1;
			}
		filename = termcap_dir;
		}
	if ((fd = open(filename, O_RDONLY)) < 0)
		return -1;
	while (1) {
		cp = bp;
		while (1) {
			if (--cnt <= 0) {
				if ((cnt = read(fd, buf, TBUFSIZ)) <= 0) {
					close(fd);
					fd = -1;
					break;
					}
				bp1 = buf;
				}
			if ((*cp++ = *bp1++) == '\n') {
				cp--;
				if (cp == bp)
					break;
				if (cp > bp && cp[-1] != '\\')
					break;
				cp--;
				continue;
				}
			}
		*cp = NULL;
		if (tnamchk(bp, name)) {
			if (fd > 0)
				close(fd);
			return 1;
			}
		if (fd < 0)
			return 0;
		}

	
}
int
tnamchk(bp, name)
register char	*bp;
char	*name;
{	register char	*cp;

	while (1) {
		for (cp = name; *bp == *cp; )
			bp++, cp++;
		if (*cp == NULL && (*bp == '|' || *bp == ':'))
			break;
		while (*bp && *bp != '|' && *bp != ':')
			bp++;
		if (*bp != '|')
			return 0;
		bp++;
		}
	compile_termcap();
	return 1;
}
void
close_termcap()
{
	chk_free((char *) tc);
}
static  int
compile_termcap()
{	register char *cp;

	for (cp = ubuf; *cp && ent_count < MAX_ENTRIES; ) {
		while (*cp != ':' && *cp)
			cp++;
		if (*cp) {
			tc[ent_count].entry = ++cp;
			tc[ent_count++].name = (*cp << 8) | cp[1];
			}
		}

	return 1;
}
int
tgetnum(id)
register char	*id;
{	register char	*bp = ubuf;

	while (*bp) {
		while (*bp != ':' && *bp)
			bp++;
		if (*bp && bp[1] == id[0] && bp[2] == id[1] && bp[3] == '#')
			return atoi(bp+4);
		bp++;
		}
	return 0;
}
int
tgetflag(id)
register char	*id;
{	register char	*bp = ubuf;

	while (*bp) {
		while (*bp != ':' && *bp)
			bp++;
		if (*bp && bp[1] == id[0] && bp[2] == id[1])
			return 1;
		bp++;
		}
	return 0;
}
char *
tgetstr(id, area)
char	*id;
char	**area;
{	register int	ltc = (*id << 8) | (id[1] & 0xff);
	register int	i = ent_count;
	register char	*dp = *area;
	char	*init_area = *area;
	struct tc *tcp = tc;
	char	*tcopy_string();
	char	*cp;

	for (; i-- > 0; tcp++) {
		if (tcp->name != ltc)
			continue;
		if (tcp->entry[2] == '=') {
			/*------------------------------
			 *   Remove delays at beginning of string.
			 *------------------------------*/
			for (cp = tcp->entry + 3; isdigit(*cp); )
				cp++;
			*area = tcopy_string(dp, cp, ':');
			return init_area;
			}
		}
	return NULL;
}
int
tputs(cp, affcnt, outc)
char	*cp;
int	affcnt;
int	(*outc)();
{
	while (*cp)
		(*outc)(*cp++);
	return 0;
}
char *
tgoto(str, col, row)
register char	*str;
int	col;
int	row;
{	static char buf[32];
	register char	*cp = buf;
	int	arg[2];
	register int	*argp = arg;
	int	t;

	arg[0] = row;
	arg[1] = col;

	while (*str) {
		if (*str != '%') {
			*cp++ = *str++;
			continue;
			}
		str++;
		switch (*str++) {
			case '+':
				*argp += *str++;
				/* Fall into ... */
			case '.':	/* Code change thanks to john@hcrvax.uucp */
				*cp++ = (char) *argp++;
				break;
			case '2':	
				sprintf(cp, "%02d", *argp++);
				cp += 2;
				break;
			case '3':	
				sprintf(cp, "%03d", *argp++);
				cp += 3;
				break;
			case 'B':
				*argp = (16 * (*argp / 10)) + (*argp % 10);
				break;
			case 'D':
				*argp = (*argp - 2 * (*argp % 16));
				break;
			case 'd':	
				sprintf(cp, "%d", *argp++);
				cp += strlen(cp);
				break;
			case '>':	
				if (*argp > *str)
					*argp += str[1];
				str += 2;
				break;
			case 'i':	arg[0]++, arg[1]++;
					break;
			case 'n':
				arg[0] ^= 0140;
				arg[1] ^= 0140;
				break;
			case 'r':	t = arg[0];
					arg[0] = arg[1];
					arg[1] = t;
					break;
			case '%':	*cp++ = '%';
					break;
			default:
					*cp++ = *str;
			}
		}
	*cp = NULL;
	return buf;

}
