/*+++*
 *  title:	tinfocap.c
 *  abstract:	termcap emulation routines for terminfo.
 *  author:	T.R.Hageman, Groningen, The Netherlands.
 *  created:	december 1989
 *  modified:	february 1990, IBM AIX extended terminfo support.
 *	11-Jun-92, add SUN and SCO extended terminfo support.
 *	27-May-93, add support for SCO curses.
 *	 2-Jul-93, extract table info to tinfocap.h
 *		(see also RCS Log at end)
 *  description:
 *	Portable termcap-style access to terminfo database.
 *
#if NOTYET
 *	If the compile-time option TI_TERMCAP is #defined, the names of
 *	the termcap routines in this file are prepended with "ti_", and the
 *	standard termcap is also accessed.  The value of TI_TERMCAP determines
 *	whether termcap or terminfo is accessed first:
 *	  TI_TERMCAP > 0	first TERMCAP, then TERMINFO
 *	  TI_TERMCAP < 0	first TERMINFO, then TERMCAP
 *	  TI_TERMCAP = 0	determined at runtime by value of `_ti_termcap'.
#endif
 *
 *  WARNING:
 *	This assumes the conventional SYSV/AT&T terminfo implementation,
 *	i.e., all capability names are #defined in <term.h>,
 *	and are stored in a single structure, referenced by CUR.
 *
 *	The SCO implementation using CURB, CURN, and CURS for separate
 *	flag-, numeric-, and string capability tables is also supported.
 *	(except for printer-describing capabilities)
 *
 *	For other implementations this may not work.
 *
 *---*/

#include <curses.h>
#include <term.h>	/* terminfo header file */
#include "portdefs.h"	/* portability macros. */
#include "tinfocap.h"	/* for global definitions. */

#ifdef RCS_ID
static const char RCSid[] =
	"$Id: tinfocap.c,v 1.3 1993/07/05 00:20:48 tom Exp tom $";
#endif

#ifdef DEBUG
#   include <stdio.h>
#   define DPRINTF(x)	printf x
#else
#   define DPRINTF(x)
#endif

/* Table entry type. */

typedef struct {
	short	id;
	short	offset;
} Where;


/* Define an entry in a capabilities table. */

#define ENTRY(i,d, ti_name, pad_parm, ti_variable) {		\
		TC_ID(i,d),					\
		(short) TI_TO_OFFSET(ti_variable)		\
	},
	/* (Note the trailing comma.) */


/* Determine size of table at compile-time. (don't count zero-termination) */

#define TABLESIZE(tab)		(sizeof(tab) / sizeof(tab[0]) -1)


/* Do a binary search for capability `id' in the table.
   (assumes table is lexically ordered on id) */

static void *_tlookup __(( const char *_(id), const Where *_(table), 
			   size_t _(tablesize) ));
static void *
_tlookup(id, table, size)
const char	*id;
const Where	*table;
size_t		size;
{
	register const Where	*med_p;
	register int	top = 0,
			end = size,
			med;
	register short	key = TC_ID(id[0],id[1]);

	while (top < end) {

		med_p = &table[med = (top + end) >> 1];

		if (key < med_p->id) {
			end = med;
			continue;
		}
		if (key > med_p->id) {
			top = med + 1;
			continue;
		}

		/* Match: return a pointer to the capability. */
		DPRINTF(("[%.2s->%d]=", (char *)&med_p->id, med_p->offset));

		return (void *) OFFSET_TO_TI(med_p->offset);

	}
	DPRINTF(("(nope)\n"));
	return NULL;
}


static const Where FlagTab[] = {
#define TABLE FLAGS
#include "tinfocap.h"
  {0}	/* Zero-terminate (since not all compilers can handle trailing `,') */
};

int
tgetflag(id)
const char	*id;
{
	register char	*found;

	DPRINTF(("flag \"%.2s\"", id));
	if ((found = (char *)_tlookup(id, FlagTab, TABLESIZE(FlagTab))) == NULL)
		return 0;

	DPRINTF((*found ? "YES\n": "NO\n"));
	return (int) *found;
}


static const Where NumTab[] = {
#define TABLE NUMBERS
#include "tinfocap.h"
  {0}	/* Zero-terminate (since not all compilers can handle trailing `,') */
};

int
tgetnum(id)
const char	*id;
{
	/* #insert "tnumtab.h" */
	register short	*found;

	DPRINTF(("num \"%.2s\"", id));
	if ((found = (short *)_tlookup(id, NumTab, TABLESIZE(NumTab))) == NULL)
		return -1;

	DPRINTF(("%d\n", *found));
	return *found;
}


static const Where StrTab[] = {
#define TABLE STRINGS
#include "tinfocap.h"
  {0}	/* Zero-terminate (since not all compilers can handle trailing `,') */
};

char *
tgetstr(id, pp)
const char	*id;
char		**pp;
{
	register char	**found;
	register char	*s, *d;

	DPRINTF(("str \"%.2s\"", id));
	if ((found = (char **)_tlookup(id, StrTab, TABLESIZE(StrTab))) == NULL)
		return NULL;

#ifdef DEBUG
	putchar('"');
	for (s = *found;  *s; ) {
		register int	c = *s++ & 0xff;
		if (c < ' ' || c == 0x7f)
			putchar('^'), c ^= '@';
		if (c >= 0x80)
			printf("\\%03o", c);
		else 
			putchar(c);
	}
	printf("\"\n");
#endif/*DEBUG*/
	
	if (pp && (d = *pp)) {
		for (s = *found; (*d++ = *s++); )
			;
		*pp = d;
	}
	return *found;
}


char *
tgoto(cm, col, line)
const char	*cm;
int		col, line;
{
	extern char *tparm();

	return tparm(cm, line, col);
}


int
tgetent(buf, name)
char		*buf;
const char	*name;
{
	int	result;

	setupterm(name, 1, &result);
	return result;
}

/*======================================================================*
 * $Log: tinfocap.c,v $
 * Revision 1.3  1993/07/05  00:20:48  tom
 * add SCO terminfo support; move actual table definitions to "tinfocap.h".
 *
 *======================================================================*/
