/***

    termcap lib

    1994.3.18	make by ken

***/
#include    <stdio.h>
#include    <stdlib.h>
#include    <ctype.h>
#include    <string.h>

#define	ERR		(-1)
#define	FALSE		0
#define	TRUE		1

#define	TERMCAP		termcap_file

extern	char	*termcap_file;

static	char	*tbuff = NULL;

void	tsetent(char *ent)
{
    tbuff = ent;
}
int	tgetent(char *buff, char *name)
{
    int n;
    int ch;
    int len;
    FILE *fp;
    char *p;

    tbuff = NULL;
    len = strlen(name);

    if ( (p = TERMCAP) == NULL && (p = getenv("TERMCAP")) == NULL )
	return ERR;
    if ( (fp = fopen(p, "r")) == NULL )
	return ERR;

    for ( ; ; ) {
	n = 0;
	while ( (ch = getc(fp)) != EOF ) {
	    if ( ch == '\n' ) {
		if ( n > 0 && buff[n - 1] == '\\' ) {
		    n--;
		    continue;
		}
		break;
	    } else if ( n == 0 && ch == '#' ) {
		while ( (ch = getc(fp)) != EOF && ch != '\n' )
		    ;
		ungetc(ch, fp);
	    } else if ( n < BUFSIZ )
		buff[n++] = ch;
	}
	buff[n] = '\0';

	if ( n == 0 && ch == EOF ) {
	    fclose(fp);
	    return FALSE;
	}

	if ( strncmp(buff, name, len) == 0 &&
		(buff[len] == ':' || buff[len] == '|') ) {
	    fclose(fp);
	    tbuff = buff;
	    return TRUE;
	}
    }
}
static	char	*tgetd(char *str, int *val)
{
    int n;
    int ch = 0;

    if ( *str == 'x' ) {
	str++;
	for ( n = 0 ; n < 2 && isxdigit(*str) ; n++ ) {
	    if ( isdigit(*str) )
		ch = ch * 16 + *str - '0';
	    else
		ch = ch * 16 + toupper(*str) - 'A' + 10;
	    str++;
	}
    } else if ( *str == '0' ) {
	str++;
	for ( n = 0 ; n < 3 && *str >= '0' && *str <= '7' ; n++ )
	    ch = ch * 8 + *(str++) - '0';
    } else if ( isdigit(*str) ) {
	for ( n = 0 ; n < 3 && isdigit(*str) ; n++ )
		ch = ch * 10 + *(str++) - '0';
    } else
	ch = *(str++);
    *val = ch;
    return str;
}
static	char	*tgetc(char *str, int *val)
{
    int n;
    int ch;

    switch(*str) {
    case '\\':
	str++;
	switch(*str) {
	case 'E': ch = '\033'; str++; break;
	case 'F': ch = '\034'; str++; break;
	case 'G': ch = '\035'; str++; break;
	case 'H': ch = '\036'; str++; break;
	case 'I': ch = '\037'; str++; break;
	case 'b': ch = '\010'; str++; break;
	case 't': ch = '\011'; str++; break;
	case 'n': ch = '\012'; str++; break;
	case 'h': ch = '\013'; str++; break;
	case 'c': ch = '\014'; str++; break;
	case 'r': ch = '\015'; str++; break;
	case 'e': ch = '\016'; str++; break;
	case 'f': ch = '\017'; str++; break;
	default: str = tgetd(str, &ch); break;
	}
	break;
    case '^':
	str++;
	if ( *str >= 'A' && *str <= 'Z' )
	    ch = *str - '@';
	else
	    ch = '^';
	break;
    default:
	ch = *(str++);
	break;
    }

    *val = ch;
    return str;
}
static	char	*tskip(char *p)
{
    int n;

    while ( *p != '\0' ) {
	if ( *p == ':' )
	    return ++p;
	p = tgetc(p, &n);
    }
    return p;
}
int	tgetnum(char *id)
{
    int n;
    char *p;

    if ( (p = tbuff) == NULL )
	return ERR;

    for ( ; ; ) {
	p = tskip(p);
	if ( *p == '\0' )
	    return ERR;
	if ( p[0] != id[0] || p[1] != id[1] || p[2] != '#' )
	    continue;
	p += 3;
	if ( *p == '0' ) {
	    for ( n = 0 ; *p >= 0 && *p <= '7' ; p++ )
		n = n * 8 + *p - '0';
	} else {
	    for ( n = 0 ; isdigit(*p) ; p++ )
		n = n * 10 + *p - '0';
	}
	return n;
    }
}
int	tgetflag(char *id)
{
    char *p;

    if ( (p = tbuff) == NULL )
	return ERR;

    for ( ; ; ) {
	p = tskip(p);
	if ( *p == '\0' )
	    return ERR;
	if ( p[0] != id[0] || p[1] != id[1] )
	    continue;

	if ( p[2] == ':' )
	    return TRUE;
	else if ( p[2] == '@' )
	    return FALSE;
    }
}
char	*tgetstr(char *id, char **area)
{
    int n;
    char *p;
    char *s;

    if ( (p = tbuff) == NULL )
	return NULL;

    for ( ; ; ) {
	p = tskip(p);
	if ( *p == '\0' )
	    return NULL;
	if ( p[0] != id[0] || p[1] != id[1] )
	    continue;

	if ( p[2] == '@' )
	    return NULL;
	else if ( p[2] != '=' )
	    continue;
	p += 3;

	s = *area;
	while ( *p != '\0' && *p != ':' ) {
	    p = tgetc(p, &n);
	    *(s++) = n;
	}
	*(s++) = '\0';
	p = *area;
	*area = s;
	return p;
    }
}
void	tputs(char *str, int ac, void (*put)(int ch))
{
    if ( ac < 1 || put == (void (*))0 )
	return;
    while ( *str != '\0' )
	(*put)(*(str++));
}
/****************
	%%					%
	%[[:]+-# ][0-9[.0-9]][doxXs]		pop printf
	%c					pop
	%p[1-9]					push [1-9]
	%P[a-z]					push [a-z]
	%g[a-z]					pop [a-z]
	%'c'					push 'c'
	%{0-9}					push {0-9}
	%l					strlen pop
	%+ %- %* %/ %m				+,-,*,/,% pop ? pop push
	%& %| %^				&,|,^ pop ? pop push
	%i					inc

not support
	%= %> %<				=,>,< pop ? pop push
	%A %O					&&,|| pop ? pop push
	%! %~					pop ? push
	%? ... %t ... %e ... %;			if then else fi
*****************/

#define	STKSIZ	16

static	int	inchar(int ch, char *ptn)
{
    int n;
    for ( n = 0 ; ptn[n] != '\0' ; n++ ) {
	if ( ch == ptn[n] )
	    return n;
    }
    return (-1);
}
char	*tgoto(char *str, int x, int y)
{
    int n;
    int len = 0;
    int ent = 0;
    int stk[STKSIZ];
    char stc[STKSIZ];
    char dmy[32];
    static int dat[26];
    static char tmp[BUFSIZ + 2];

    while ( ent < STKSIZ && len < BUFSIZ && *str != 0 ) {
	if ( *str == '%' ) {
	    switch(*(++str)) {
	    case '%':
		tmp[len++] = *(str++);
		break;
	    case 'c':
		tmp[len++] = (char)(stk[--ent]);
		str++;
		break;
	    case 'p':
		switch(str[1]) {
		case '1': stk[ent++] = x; break;
		case '2': stk[ent++] = y; break;
		}
		str += 2;
		break;
	    case 'P':
		dat[str[1] - 'a'] = stk[--ent];
		str += 2;
		break;
	    case 'g':
		stk[ent++] = dat[str[1] - 'a'];
		str += 2;
		break;
	    case '\'':
		str = tgetc(str + 1, &n);
		stk[ent++] = n;
		break;
	    case '{':
		str = tgetd(str + 1, &n);
		stk[ent++] = n;
		if ( *str == '}' )
		    str++;
		break;
	    case 'l':
		stk[ent] = ent;
		ent++;
		str++;
		break;
	    case '+':
		stk[ent-2] = stk[ent-2] + stk[ent-1];
		ent--;
		str++;
		break;
	    case '-':
		stk[ent-2] = stk[ent-2] - stk[ent-1];
		ent--;
		str++;
		break;
	    case '*':
		stk[ent-2] = stk[ent-2] * stk[ent-1];
		ent--;
		str++;
		break;
	    case '/':
		stk[ent-2] = stk[ent-2] / stk[ent-1];
		ent--;
		str++;
		break;
	    case 'm':
		stk[ent-2] = stk[ent-2] % stk[ent-1];
		ent--;
		str++;
		break;
	    case '&':
		stk[ent-2] = stk[ent-2] & stk[ent-1];
		ent--;
		str++;
		break;
	    case '|':
		stk[ent-2] = stk[ent-2] | stk[ent-1];
		ent--;
		str++;
		break;
	    case '^':
		stk[ent-2] = stk[ent-2] ^ stk[ent-1];
		ent--;
		str++;
		break;
	    case '~':
		stk[ent-1] = ~(stk[ent-1]);
		str++;
		break;
	    case 'i':
		x += 1;
		y += 1;
		str++;
		break;
	    default:
		n = 0;
		dmy[n++] = '%';
		tmp[len] = '\0';

		if ( *str == ':' )
		    str++;
		if ( inchar(*str, "+-# ") >= 0 )
		    dmy[n++] = *(str++);
		while ( isdigit(*str) )
		    dmy[n++] = *(str++);
		if ( *str == '.' )
		    dmy[n++] = *(str++);
		while ( isdigit(*str) )
		    dmy[n++] = *(str++);

		if ( inchar(*str, "doxX") >= 0 ) {
		    dmy[n++] = *(str++);
		    dmy[n] = '\0';
		    sprintf(tmp + len, dmy, stk[--ent]);
		} else if ( *str == 's' ) {
		    dmy[n++] = *(str++);
		    dmy[n] = '\0';
		    for ( n = 0 ; n < ent ; n++ )
			stc[n] = (char)(stk[n]);
		    stc[n] = '\0';
		    sprintf(tmp + len, dmy, stc);
		    ent = 0;
		}

		while ( tmp[len] != '\0' )
		    len++;
		break;
	    }
	} else
	    tmp[len++] = *(str++);
    }
    tmp[len] = '\0';
    return tmp;
}
