929 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			929 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* curses.c */
 | 
						|
 | 
						|
/* Author:
 | 
						|
 *	Steve Kirkendall
 | 
						|
 *	14407 SW Teal Blvd. #C
 | 
						|
 *	Beaverton, OR 97005
 | 
						|
 *	kirkenda@cs.pdx.edu
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
/* This file contains the functions & variables needed for a tiny subset of
 | 
						|
 * curses.  The principle advantage of this version of curses is its
 | 
						|
 * extreme speed.  Disadvantages are potentially larger code, few supported
 | 
						|
 * functions, limited compatibility with full curses, and only stdscr.
 | 
						|
 */
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
#include "vi.h"
 | 
						|
 | 
						|
#if ANY_UNIX
 | 
						|
/* The termios/termio/sgtty #ifdefs were a mess, so I removed all but termios.
 | 
						|
 * (KJB)
 | 
						|
 */
 | 
						|
# include	<termios.h>
 | 
						|
# if MINIX
 | 
						|
#  include	<sys/ioctl.h>
 | 
						|
# endif
 | 
						|
#endif
 | 
						|
 | 
						|
#if TOS
 | 
						|
# include	<osbind.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#if OSK
 | 
						|
# include	<sgstat.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#if VMS
 | 
						|
extern int VMS_read_raw;  /* Set in initscr() */
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
extern char	*getenv();
 | 
						|
static void	 starttcap();
 | 
						|
 | 
						|
/* variables, publicly available & used in the macros */
 | 
						|
char	*termtype;	/* name of terminal entry */
 | 
						|
short	ospeed;		/* speed of the tty, eg B2400 */
 | 
						|
#if OSK
 | 
						|
char	PC_;	/* Pad char */
 | 
						|
char	*BC;	/* backspace character string */
 | 
						|
#else
 | 
						|
char	PC;		/* Pad char */
 | 
						|
#endif
 | 
						|
WINDOW	*stdscr;	/* pointer into kbuf[] */
 | 
						|
WINDOW	kbuf[KBSIZ];	/* a very large output buffer */
 | 
						|
int	LINES;		/* :li#: number of rows */
 | 
						|
int	COLS;		/* :co#: number of columns */
 | 
						|
int	AM;		/* :am:  boolean: auto margins? */
 | 
						|
int	PT;		/* :pt:  boolean: physical tabs? */
 | 
						|
char	*VB;		/* :vb=: visible bell */
 | 
						|
char	*UP;		/* :up=: move cursor up */
 | 
						|
char	*SO = "";	/* :so=: standout start */
 | 
						|
char	*SE = "";	/* :se=: standout end */
 | 
						|
char	*US = "";	/* :us=: underline start */
 | 
						|
char	*UE = "";	/* :ue=: underline end */
 | 
						|
char	*MD = "";	/* :md=: bold start */
 | 
						|
char	*ME = "";	/* :me=: bold end */
 | 
						|
char	*AS = "";	/* :as=: alternate (italic) start */
 | 
						|
char	*AE = "";	/* :ae=: alternate (italic) end */
 | 
						|
#ifndef NO_VISIBLE
 | 
						|
char	*MV;		/* :mv=: "visible" selection start */
 | 
						|
#endif
 | 
						|
char	*CM;		/* :cm=: cursor movement */
 | 
						|
char	*CE;		/* :ce=: clear to end of line */
 | 
						|
char	*CD;		/* :cd=: clear to end of screen */
 | 
						|
char	*AL;		/* :al=: add a line */
 | 
						|
char	*DL;		/* :dl=: delete a line */
 | 
						|
#if OSK
 | 
						|
char	*SR_;		/* :sr=: scroll reverse */
 | 
						|
#else
 | 
						|
char	*SR;		/* :sr=: scroll reverse */
 | 
						|
#endif
 | 
						|
char	*KS = "";	/* :ks=: init string for cursor */
 | 
						|
char	*KE = "";	/* :ke=: restore string for cursor */
 | 
						|
char	*KU;		/* :ku=: key sequence sent by up arrow */
 | 
						|
char	*KD;		/* :kd=: key sequence sent by down arrow */
 | 
						|
char	*KL;		/* :kl=: key sequence sent by left arrow */
 | 
						|
char	*KR;		/* :kr=: key sequence sent by right arrow */
 | 
						|
char	*HM;		/* :HM=: key sequence sent by the <Home> key */
 | 
						|
char	*EN;		/* :EN=: key sequence sent by the <End> key */
 | 
						|
char	*PU;		/* :PU=: key sequence sent by the <PgUp> key */
 | 
						|
char	*PD;		/* :PD=: key sequence sent by the <PgDn> key */
 | 
						|
char	*KI;		/* :kI=: key sequence sent by the <Insert> key */
 | 
						|
#ifndef NO_FKEY
 | 
						|
char	*FKEY[NFKEYS];	/* :k0=: ... :k9=: sequences sent by function keys */
 | 
						|
#endif
 | 
						|
char	*IM = "";	/* :im=: insert mode start */
 | 
						|
char	*IC = "";	/* :ic=: insert the following character */
 | 
						|
char	*EI = "";	/* :ei=: insert mode end */
 | 
						|
char	*DC;		/* :dc=: delete a character */
 | 
						|
char	*TI = "";	/* :ti=: terminal init */	/* GB */
 | 
						|
char	*TE = "";	/* :te=: terminal exit */	/* GB */
 | 
						|
#ifndef NO_CURSORSHAPE
 | 
						|
#if 1
 | 
						|
char	*CQ = (char *)0;/* :cQ=: normal cursor */
 | 
						|
char	*CX = (char *)1;/* :cX=: cursor used for EX command/entry */
 | 
						|
char	*CV = (char *)2;/* :cV=: cursor used for VI command mode */
 | 
						|
char	*CI = (char *)3;/* :cI=: cursor used for VI input mode */
 | 
						|
char	*CR = (char *)4;/* :cR=: cursor used for VI replace mode */
 | 
						|
#else
 | 
						|
char	*CQ = "";	/* :cQ=: normal cursor */
 | 
						|
char	*CX = "";	/* :cX=: cursor used for EX command/entry */
 | 
						|
char	*CV = "";	/* :cV=: cursor used for VI command mode */
 | 
						|
char	*CI = "";	/* :cI=: cursor used for VI input mode */
 | 
						|
char	*CR = "";	/* :cR=: cursor used for VI replace mode */
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
char	*aend = "";	/* end an attribute -- either UE or ME */
 | 
						|
char	ERASEKEY;	/* backspace key taken from ioctl structure */
 | 
						|
#ifndef NO_COLOR
 | 
						|
char	normalcolor[16];
 | 
						|
char	SOcolor[16];
 | 
						|
char	SEcolor[16];
 | 
						|
char	UScolor[16];
 | 
						|
char	UEcolor[16];
 | 
						|
char	MDcolor[16];
 | 
						|
char	MEcolor[16];
 | 
						|
char	AScolor[16];
 | 
						|
char	AEcolor[16];
 | 
						|
# ifndef NO_POPUP
 | 
						|
char	POPUPcolor[16];
 | 
						|
# endif
 | 
						|
# ifndef NO_VISIBLE
 | 
						|
char	VISIBLEcolor[16];
 | 
						|
# endif
 | 
						|
#endif
 | 
						|
 | 
						|
#if ANY_UNIX
 | 
						|
static struct termios	oldtermio;	/* original tty mode */
 | 
						|
static struct termios	newtermio;	/* cbreak/noecho tty mode */
 | 
						|
#endif
 | 
						|
 | 
						|
#if OSK
 | 
						|
static struct sgbuf	oldsgttyb;	/* orginal tty mode */
 | 
						|
static struct sgbuf	newsgttyb;	/* noecho tty mode */
 | 
						|
#endif
 | 
						|
 | 
						|
static char	*capbuf;	/* capability string buffer */
 | 
						|
 | 
						|
 | 
						|
/* Initialize the Curses package. */
 | 
						|
void initscr()
 | 
						|
{
 | 
						|
	/* make sure TERM variable is set */
 | 
						|
	termtype = getenv("TERM");
 | 
						|
 | 
						|
#if VMS
 | 
						|
	/* VMS getenv() handles TERM as a environment setting.  Foreign 
 | 
						|
	 * terminal support can be implemented by setting the ELVIS_TERM
 | 
						|
	 * logical or symbol to match a tinytcap entry.
 | 
						|
	 */
 | 
						|
	if (!strcmp(termtype,"unknown"))
 | 
						|
		termtype = getenv("ELVIS_TERM");
 | 
						|
#endif
 | 
						|
#if MSDOS
 | 
						|
	/* For MS-DOS, if TERM is unset we can default to "pcbios", or
 | 
						|
	 * maybe "rainbow".
 | 
						|
	 */
 | 
						|
	if (!termtype)
 | 
						|
	{
 | 
						|
#ifdef RAINBOW
 | 
						|
		if (*(unsigned char far*)(0xffff000eL) == 6   /* Rainbow 100a */
 | 
						|
		 || *(unsigned char far*)(0xffff000eL) == 148)/* Rainbow 100b */
 | 
						|
		{
 | 
						|
			termtype = "rainbow";
 | 
						|
		}
 | 
						|
		else
 | 
						|
#endif
 | 
						|
			termtype = "pcbios";
 | 
						|
	}
 | 
						|
	if (!strcmp(termtype, "pcbios"))
 | 
						|
#else
 | 
						|
	if (!termtype)
 | 
						|
#endif
 | 
						|
	{
 | 
						|
#if ANY_UNIX
 | 
						|
		write(2, "Environment variable TERM must be set\n", (unsigned)38);
 | 
						|
		exit(1);
 | 
						|
#endif
 | 
						|
#if OSK
 | 
						|
		writeln(2, "Environment variable TERM must be set\n", (unsigned)38);
 | 
						|
		exit(1);
 | 
						|
#endif
 | 
						|
#if AMIGA
 | 
						|
		termtype = TERMTYPE;
 | 
						|
		starttcap(termtype);
 | 
						|
#endif
 | 
						|
#if MSDOS
 | 
						|
		starttcap("pcbios");
 | 
						|
#endif
 | 
						|
#if TOS
 | 
						|
		termtype = "vt52";
 | 
						|
		starttcap(termtype);
 | 
						|
#endif
 | 
						|
#if VMS
 | 
						|
		write(2, "UNKNOWN terminal: define ELVIS_TERM\n", (unsigned)36);
 | 
						|
		exit(1);
 | 
						|
#endif
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
#if MSDOS
 | 
						|
		*o_pcbios = 0;
 | 
						|
#endif
 | 
						|
		/* start termcap stuff */
 | 
						|
		starttcap(termtype);
 | 
						|
	}
 | 
						|
 | 
						|
	/* create stdscr and curscr */
 | 
						|
	stdscr = kbuf;
 | 
						|
 | 
						|
	/* change the terminal mode to cbreak/noecho */
 | 
						|
#if ANY_UNIX
 | 
						|
	tcgetattr(2, &oldtermio);
 | 
						|
#endif
 | 
						|
 | 
						|
#if OSK
 | 
						|
	_gs_opt(0, &oldsgttyb);
 | 
						|
#endif
 | 
						|
 | 
						|
#if VMS
 | 
						|
	VMS_read_raw = 1;   /* cbreak/noecho */
 | 
						|
	vms_open_tty();
 | 
						|
#endif
 | 
						|
	resume_curses(TRUE);
 | 
						|
}
 | 
						|
 | 
						|
/* Shut down the Curses package. */
 | 
						|
void endwin()
 | 
						|
{
 | 
						|
	/* change the terminal mode back the way it was */
 | 
						|
	suspend_curses();
 | 
						|
#if AMIGA
 | 
						|
	amiclosewin();
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int curses_active = FALSE;
 | 
						|
 | 
						|
/* Send any required termination strings.  Turn off "raw" mode. */
 | 
						|
void suspend_curses()
 | 
						|
{
 | 
						|
#ifndef NO_CURSORSHAPE
 | 
						|
	if (has_CQ)
 | 
						|
	{
 | 
						|
		do_CQ();
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	if (has_TE)					/* GB */
 | 
						|
	{
 | 
						|
		do_TE();
 | 
						|
	}
 | 
						|
	if (has_KE)
 | 
						|
	{
 | 
						|
		do_KE();
 | 
						|
	}
 | 
						|
#ifndef NO_COLOR
 | 
						|
	quitcolor();
 | 
						|
#endif
 | 
						|
	refresh();
 | 
						|
 | 
						|
	/* change the terminal mode back the way it was */
 | 
						|
#if ANY_UNIX
 | 
						|
	tcsetattr(2, TCSADRAIN, &oldtermio);
 | 
						|
#endif
 | 
						|
#if OSK
 | 
						|
	_ss_opt(0, &oldsgttyb);
 | 
						|
#endif
 | 
						|
#if AMIGA
 | 
						|
	ttyshutdown();
 | 
						|
#endif
 | 
						|
#if MSDOS
 | 
						|
	raw_set_stdio(FALSE);
 | 
						|
#endif
 | 
						|
 | 
						|
#if VMS
 | 
						|
	VMS_read_raw = 0;
 | 
						|
#endif
 | 
						|
	curses_active = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* put the terminal in RAW mode.  If "quietly" is FALSE, then ask the user
 | 
						|
 * to hit a key, and wait for keystroke before returning.
 | 
						|
 */
 | 
						|
void resume_curses(quietly)
 | 
						|
	int	quietly;
 | 
						|
{
 | 
						|
	if (!curses_active)
 | 
						|
	{
 | 
						|
		/* change the terminal mode to cbreak/noecho */
 | 
						|
#if ANY_UNIX
 | 
						|
		ospeed = cfgetospeed(&oldtermio);
 | 
						|
		ERASEKEY = oldtermio.c_cc[VERASE];
 | 
						|
		newtermio = oldtermio;
 | 
						|
		newtermio.c_iflag &= (IXON|IXOFF|IXANY|ISTRIP|IGNBRK);
 | 
						|
		newtermio.c_oflag &= ~OPOST;
 | 
						|
		newtermio.c_lflag &= ISIG;
 | 
						|
		newtermio.c_cc[VINTR] = ctrl('C'); /* always use ^C for interrupts */
 | 
						|
		newtermio.c_cc[VMIN] = 1;
 | 
						|
		newtermio.c_cc[VTIME] = 0;
 | 
						|
		newtermio.c_cc[VSUSP] = 0;
 | 
						|
		tcsetattr(2, TCSADRAIN, &newtermio);
 | 
						|
#endif
 | 
						|
#if OSK
 | 
						|
		newsgttyb = oldsgttyb;
 | 
						|
		newsgttyb.sg_echo = 0;
 | 
						|
		newsgttyb.sg_eofch = 0;
 | 
						|
		newsgttyb.sg_kbach = 0;
 | 
						|
		newsgttyb.sg_kbich = ctrl('C');
 | 
						|
		_ss_opt(0, &newsgttyb);
 | 
						|
		ospeed = oldsgttyb.sg_baud;
 | 
						|
		ERASEKEY = oldsgttyb.sg_bspch;
 | 
						|
#endif
 | 
						|
#if AMIGA
 | 
						|
		/* turn on window resize and RAW */
 | 
						|
		ttysetup();
 | 
						|
#endif
 | 
						|
#if MSDOS
 | 
						|
		raw_set_stdio(TRUE);
 | 
						|
#endif
 | 
						|
 | 
						|
#if VMS
 | 
						|
		VMS_read_raw = 1;
 | 
						|
		{ int c;
 | 
						|
			read(0,&c,0);   /* Flush the tty buffer. */
 | 
						|
		}
 | 
						|
		ERASEKEY = '\177';  /* Accept <DEL> as <^H> for VMS */
 | 
						|
#endif
 | 
						|
 | 
						|
		if (has_TI)					/* GB */
 | 
						|
		{
 | 
						|
			do_TI();
 | 
						|
		}
 | 
						|
		if (has_KS)
 | 
						|
		{
 | 
						|
			do_KS();
 | 
						|
		}
 | 
						|
 | 
						|
		curses_active = TRUE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* If we're supposed to quit quietly, then we're done */
 | 
						|
	if (quietly)
 | 
						|
	{
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	signal(SIGINT, SIG_IGN);
 | 
						|
 | 
						|
	move(LINES - 1, 0);
 | 
						|
	do_SO();
 | 
						|
#if VMS
 | 
						|
	qaddstr("\n[Press <RETURN> to continue]");
 | 
						|
#else
 | 
						|
	qaddstr("[Press <RETURN> to continue]");
 | 
						|
#endif
 | 
						|
	do_SE();
 | 
						|
	refresh();
 | 
						|
	ttyread(kbuf, 20, 0); /* in RAW mode, so <20 is very likely */
 | 
						|
	if (kbuf[0] == ':')
 | 
						|
	{
 | 
						|
		mode = MODE_COLON;
 | 
						|
		addch('\n');
 | 
						|
		refresh();
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		mode = MODE_VI;
 | 
						|
		redraw(MARK_UNSET, FALSE);
 | 
						|
	}	
 | 
						|
	exwrote = FALSE;
 | 
						|
 | 
						|
#if TURBOC || __GNUC__ || _ANSI
 | 
						|
	signal(SIGINT, (void(*)()) trapint);
 | 
						|
#else
 | 
						|
	signal(SIGINT, trapint);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
/* This function fetches an optional string from termcap */
 | 
						|
static void mayhave(T, s)
 | 
						|
	char	**T;	/* where to store the returned pointer */
 | 
						|
	char	*s;	/* name of the capability */
 | 
						|
{
 | 
						|
	char	*val;
 | 
						|
 | 
						|
	val = tgetstr(s, &capbuf);
 | 
						|
	if (val)
 | 
						|
	{
 | 
						|
		*T = val;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* This function fetches a required string from termcap */
 | 
						|
static void musthave(T, s)
 | 
						|
	char	**T;	/* where to store the returned pointer */
 | 
						|
	char	*s;	/* name of the capability */
 | 
						|
{
 | 
						|
	mayhave(T, s);
 | 
						|
	if (!*T)
 | 
						|
	{
 | 
						|
		write(2, "This termcap entry lacks the :", (unsigned)30);
 | 
						|
		write(2, s, (unsigned)2);
 | 
						|
		write(2, "=: capability\n", (unsigned)14);
 | 
						|
#if OSK
 | 
						|
		write(2, "\l", 1);
 | 
						|
#endif
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* This function fetches a pair of strings from termcap.  If one of them is
 | 
						|
 * missing, then the other one is ignored.
 | 
						|
 */
 | 
						|
static void pair(T, U, sT, sU)
 | 
						|
	char	**T;	/* where to store the first pointer */
 | 
						|
	char	**U;	/* where to store the second pointer */
 | 
						|
	char	*sT;	/* name of the first capability */
 | 
						|
	char	*sU;	/* name of the second capability */
 | 
						|
{
 | 
						|
	mayhave(T, sT);
 | 
						|
	mayhave(U, sU);
 | 
						|
	if (!**T || !**U)
 | 
						|
	{
 | 
						|
		*T = *U = "";
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Read everything from termcap */
 | 
						|
static void starttcap(term)
 | 
						|
	char	*term;
 | 
						|
{
 | 
						|
	static char	cbmem[800];
 | 
						|
 | 
						|
	/* allocate memory for capbuf */
 | 
						|
	capbuf = cbmem;
 | 
						|
 | 
						|
	/* get the termcap entry */
 | 
						|
	switch (tgetent(kbuf, term))
 | 
						|
	{
 | 
						|
	  case -1:
 | 
						|
		write(2, "Can't read /etc/termcap\n", (unsigned)24);
 | 
						|
#if OSK
 | 
						|
		write(2, "\l", 1);
 | 
						|
#endif
 | 
						|
		exit(2);
 | 
						|
 | 
						|
	  case 0:
 | 
						|
		write(2, "Unrecognized TERM type\n", (unsigned)23);
 | 
						|
#if OSK
 | 
						|
		write(2, "\l", 1);
 | 
						|
#endif
 | 
						|
		exit(3);
 | 
						|
	}
 | 
						|
 | 
						|
	/* get strings */
 | 
						|
	musthave(&UP, "up");
 | 
						|
	mayhave(&VB, "vb");
 | 
						|
	musthave(&CM, "cm");
 | 
						|
	pair(&SO, &SE, "so", "se");
 | 
						|
	mayhave(&TI, "ti");
 | 
						|
	mayhave(&TE, "te");
 | 
						|
	if (tgetnum("ug") <= 0)
 | 
						|
	{
 | 
						|
		pair(&US, &UE, "us", "ue");
 | 
						|
		pair(&MD, &ME, "md", "me");
 | 
						|
 | 
						|
		/* get italics, or have it default to underline */
 | 
						|
		pair(&AS, &AE, "as", "ae");
 | 
						|
		if (!*AS)
 | 
						|
		{
 | 
						|
			AS = US;
 | 
						|
			AE = UE;
 | 
						|
		}
 | 
						|
	}
 | 
						|
#ifndef NO_VISIBLE
 | 
						|
	MV = SO; /* by default */
 | 
						|
	mayhave(&MV, "mv");
 | 
						|
#endif
 | 
						|
	mayhave(&AL, "al");
 | 
						|
	mayhave(&DL, "dl");
 | 
						|
	musthave(&CE, "ce");
 | 
						|
	mayhave(&CD, "cd");
 | 
						|
#if OSK
 | 
						|
	mayhave(&SR_, "sr");
 | 
						|
#else	
 | 
						|
	mayhave(&SR, "sr");
 | 
						|
#endif
 | 
						|
	pair(&IM, &EI, "im", "ei");
 | 
						|
	mayhave(&IC, "ic");
 | 
						|
	mayhave(&DC, "dc");
 | 
						|
 | 
						|
	/* other termcap stuff */
 | 
						|
	AM = (tgetflag("am") && !tgetflag("xn"));
 | 
						|
	PT = tgetflag("pt");
 | 
						|
#if AMIGA
 | 
						|
	amiopenwin(termtype);	/* Must run this before ttysetup(); */
 | 
						|
	ttysetup();	/* Must run this before getsize(0); */
 | 
						|
#endif
 | 
						|
	getsize(0);
 | 
						|
 | 
						|
	/* Key sequences */
 | 
						|
	pair(&KS, &KE, "ks", "ke");
 | 
						|
	mayhave(&KU, "ku");		/* up */
 | 
						|
	mayhave(&KD, "kd");		/* down */
 | 
						|
	mayhave(&KL, "kl");		/* left */
 | 
						|
	mayhave(&KR, "kr");		/* right */
 | 
						|
	mayhave(&PU, "kP");		/* PgUp */
 | 
						|
	mayhave(&PD, "kN");		/* PgDn */
 | 
						|
	mayhave(&HM, "kh");		/* Home */
 | 
						|
	mayhave(&EN, "kH");		/* End */
 | 
						|
	mayhave(&KI, "kI");		/* Insert */
 | 
						|
#ifndef CRUNCH
 | 
						|
	if (!PU) mayhave(&PU, "K2");	/* "3x3 pad" names for PgUp, etc. */
 | 
						|
	if (!PD) mayhave(&PD, "K5");
 | 
						|
	if (!HM) mayhave(&HM, "K1");
 | 
						|
	if (!EN) mayhave(&EN, "K4");
 | 
						|
 | 
						|
	mayhave(&PU, "PU");		/* old XENIX names for PgUp, etc. */
 | 
						|
	mayhave(&PD, "PD");		/* (overrides others, if used.) */
 | 
						|
	mayhave(&HM, "HM");
 | 
						|
	mayhave(&EN, "EN");
 | 
						|
#endif
 | 
						|
#ifndef NO_FKEY
 | 
						|
	mayhave(&FKEY[0], "k0");		/* function key codes */
 | 
						|
	mayhave(&FKEY[1], "k1");
 | 
						|
	mayhave(&FKEY[2], "k2");
 | 
						|
	mayhave(&FKEY[3], "k3");
 | 
						|
	mayhave(&FKEY[4], "k4");
 | 
						|
	mayhave(&FKEY[5], "k5");
 | 
						|
	mayhave(&FKEY[6], "k6");
 | 
						|
	mayhave(&FKEY[7], "k7");
 | 
						|
	mayhave(&FKEY[8], "k8");
 | 
						|
	mayhave(&FKEY[9], "k9");
 | 
						|
# ifndef NO_SHIFT_FKEY
 | 
						|
	mayhave(&FKEY[10], "s0");		/* shift function key codes */
 | 
						|
	mayhave(&FKEY[11], "s1");
 | 
						|
	mayhave(&FKEY[12], "s2");
 | 
						|
	mayhave(&FKEY[13], "s3");
 | 
						|
	mayhave(&FKEY[14], "s4");
 | 
						|
	mayhave(&FKEY[15], "s5");
 | 
						|
	mayhave(&FKEY[16], "s6");
 | 
						|
	mayhave(&FKEY[17], "s7");
 | 
						|
	mayhave(&FKEY[18], "s8");
 | 
						|
	mayhave(&FKEY[19], "s9");
 | 
						|
#  ifndef NO_CTRL_FKEY
 | 
						|
	mayhave(&FKEY[20], "c0");		/* control function key codes */
 | 
						|
	mayhave(&FKEY[21], "c1");
 | 
						|
	mayhave(&FKEY[22], "c2");
 | 
						|
	mayhave(&FKEY[23], "c3");
 | 
						|
	mayhave(&FKEY[24], "c4");
 | 
						|
	mayhave(&FKEY[25], "c5");
 | 
						|
	mayhave(&FKEY[26], "c6");
 | 
						|
	mayhave(&FKEY[27], "c7");
 | 
						|
	mayhave(&FKEY[28], "c8");
 | 
						|
	mayhave(&FKEY[29], "c9");
 | 
						|
#   ifndef NO_ALT_FKEY
 | 
						|
	mayhave(&FKEY[30], "a0");		/* alt function key codes */
 | 
						|
	mayhave(&FKEY[31], "a1");
 | 
						|
	mayhave(&FKEY[32], "a2");
 | 
						|
	mayhave(&FKEY[33], "a3");
 | 
						|
	mayhave(&FKEY[34], "a4");
 | 
						|
	mayhave(&FKEY[35], "a5");
 | 
						|
	mayhave(&FKEY[36], "a6");
 | 
						|
	mayhave(&FKEY[37], "a7");
 | 
						|
	mayhave(&FKEY[38], "a8");
 | 
						|
	mayhave(&FKEY[39], "a9");
 | 
						|
#   endif
 | 
						|
#  endif
 | 
						|
# endif
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef NO_CURSORSHAPE
 | 
						|
	/* cursor shapes */
 | 
						|
	CQ = tgetstr("cQ", &capbuf);
 | 
						|
	if (has_CQ)
 | 
						|
	{
 | 
						|
		CX = tgetstr("cX", &capbuf);
 | 
						|
		if (!CX) CX = CQ;
 | 
						|
		CV = tgetstr("cV", &capbuf);
 | 
						|
		if (!CV) CV = CQ;
 | 
						|
		CI = tgetstr("cI", &capbuf);
 | 
						|
		if (!CI) CI = CQ;
 | 
						|
		CR = tgetstr("cR", &capbuf);
 | 
						|
		if (!CR) CR = CQ;
 | 
						|
	}
 | 
						|
# ifndef CRUNCH
 | 
						|
	else
 | 
						|
	{
 | 
						|
		CQ = CV = "";
 | 
						|
		pair(&CQ, &CV, "ve", "vs");
 | 
						|
		CX = CI = CR = CQ;
 | 
						|
	}
 | 
						|
# endif /* !CRUNCH */
 | 
						|
#endif /* !NO_CURSORSHAPE */
 | 
						|
 | 
						|
#ifndef NO_COLOR
 | 
						|
	strcpy(SOcolor, SO);
 | 
						|
	strcpy(SEcolor, SE);
 | 
						|
	strcpy(AScolor, AS);
 | 
						|
	strcpy(AEcolor, AE);
 | 
						|
	strcpy(MDcolor, MD);
 | 
						|
	strcpy(MEcolor, ME);
 | 
						|
	strcpy(UScolor, US);
 | 
						|
	strcpy(UEcolor, UE);
 | 
						|
# ifndef NO_POPUP
 | 
						|
	strcpy(POPUPcolor, SO);
 | 
						|
# endif
 | 
						|
# ifndef NO_VISIBLE
 | 
						|
	strcpy(VISIBLEcolor, MV);
 | 
						|
# endif
 | 
						|
#endif
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* This function gets the window size.  It uses the TIOCGWINSZ ioctl call if
 | 
						|
 * your system has it, or tgetnum("li") and tgetnum("co") if it doesn't.
 | 
						|
 * This function is called once during initialization, and thereafter it is
 | 
						|
 * called whenever the SIGWINCH signal is sent to this process.
 | 
						|
 */
 | 
						|
void getsize(signo)
 | 
						|
	int	signo;
 | 
						|
{
 | 
						|
	int	lines;
 | 
						|
	int	cols;
 | 
						|
#ifdef TIOCGWINSZ
 | 
						|
	struct winsize size;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef SIGWINCH
 | 
						|
	/* reset the signal vector */
 | 
						|
	signal(SIGWINCH, getsize);
 | 
						|
#endif
 | 
						|
 | 
						|
	/* get the window size, one way or another. */
 | 
						|
	lines = cols = 0;
 | 
						|
#ifdef TIOCGWINSZ
 | 
						|
	if (ioctl(2, TIOCGWINSZ, &size) >= 0)
 | 
						|
	{
 | 
						|
		lines = size.ws_row;
 | 
						|
		cols = size.ws_col;
 | 
						|
	}
 | 
						|
#endif
 | 
						|
#if AMIGA
 | 
						|
	/* Amiga gets window size by asking the console.device */
 | 
						|
	if (!strcmp(TERMTYPE, termtype))
 | 
						|
	{
 | 
						|
	    auto long len;
 | 
						|
	    auto char buf[30];
 | 
						|
	    
 | 
						|
	    Write(Output(), "\2330 q", 4); /* Ask the console.device */
 | 
						|
	    len = Read(Input(), buf, 29);
 | 
						|
	    buf[len] = '\000';
 | 
						|
	    sscanf(&buf[5], "%d;%d", &lines, &cols);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	if ((lines == 0 || cols == 0) && signo == 0)
 | 
						|
	{
 | 
						|
		LINES = tgetnum("li");
 | 
						|
		COLS = tgetnum("co");
 | 
						|
	}
 | 
						|
#if MSDOS
 | 
						|
# ifdef RAINBOW
 | 
						|
	if (!strcmp(termtype, "rainbow"))
 | 
						|
	{
 | 
						|
		/* Determine whether Rainbow is in 80-column or 132-column mode */
 | 
						|
		cols = *(unsigned char far *)0xee000f57L;
 | 
						|
	}
 | 
						|
	else
 | 
						|
# endif
 | 
						|
	{
 | 
						|
		lines = v_rows();
 | 
						|
		cols = v_cols();
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	if (lines >= 2)
 | 
						|
	{
 | 
						|
		LINES = lines;
 | 
						|
	}
 | 
						|
 | 
						|
	if (cols >= 30)
 | 
						|
	{
 | 
						|
		COLS = cols;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Make sure we got values that we can live with */
 | 
						|
	if (LINES < 2 || COLS < 30)
 | 
						|
	{
 | 
						|
		write(2, "Screen too small\n", (unsigned)17);
 | 
						|
#if OSK
 | 
						|
		write(2, "\l", 1);
 | 
						|
#endif
 | 
						|
		endwin();
 | 
						|
		exit(2);
 | 
						|
	}
 | 
						|
 | 
						|
#if AMIGA
 | 
						|
	if (*o_lines != LINES || *o_columns != COLS)
 | 
						|
	{
 | 
						|
		*o_lines = LINES;
 | 
						|
		*o_columns = COLS;
 | 
						|
	}
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* This is a function version of addch() -- it is used by tputs() */
 | 
						|
int faddch(ch)
 | 
						|
	int	ch;
 | 
						|
{
 | 
						|
	addch(ch);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* This function quickly adds a string to the output queue.  It does *NOT*
 | 
						|
 * convert \n into <CR><LF>.
 | 
						|
 */
 | 
						|
void qaddstr(str)
 | 
						|
	char	*str;
 | 
						|
{
 | 
						|
	REG char *s_, *d_;
 | 
						|
 | 
						|
#if MSDOS
 | 
						|
	if (o_pcbios[0])
 | 
						|
	{
 | 
						|
		while (*str)
 | 
						|
			qaddch(*str++);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	for (s_=(str), d_=stdscr; *d_++ = *s_++; )
 | 
						|
	{
 | 
						|
	}
 | 
						|
	stdscr = d_ - 1;
 | 
						|
}
 | 
						|
 | 
						|
/* Output the ESC sequence needed to go into any video mode, if supported */
 | 
						|
void attrset(a)
 | 
						|
	int	a;
 | 
						|
{
 | 
						|
	do_aend();
 | 
						|
	if (a == A_BOLD)
 | 
						|
	{
 | 
						|
		do_MD();
 | 
						|
		aend = ME;
 | 
						|
	}
 | 
						|
	else if (a == A_UNDERLINE)
 | 
						|
	{
 | 
						|
		do_US();
 | 
						|
		aend = UE;
 | 
						|
	}
 | 
						|
	else if (a == A_ALTCHARSET)
 | 
						|
	{
 | 
						|
		do_AS();
 | 
						|
		aend = AE;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		aend = "";
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Insert a single character into the display */
 | 
						|
void insch(ch)
 | 
						|
	int	ch;
 | 
						|
{
 | 
						|
	if (has_IM)
 | 
						|
		do_IM();
 | 
						|
	do_IC();
 | 
						|
	qaddch(ch);
 | 
						|
	if (has_EI)
 | 
						|
		do_EI();
 | 
						|
}
 | 
						|
 | 
						|
void wrefresh()
 | 
						|
{
 | 
						|
	if (stdscr != kbuf)
 | 
						|
	{
 | 
						|
		VOIDBIOS(;,ttywrite(kbuf, (unsigned)(stdscr - kbuf)));
 | 
						|
		stdscr = kbuf;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void wqrefresh()
 | 
						|
{
 | 
						|
	if (stdscr - kbuf > 2000)
 | 
						|
	{
 | 
						|
		VOIDBIOS(stdscr = kbuf,
 | 
						|
		{
 | 
						|
			ttywrite(kbuf, (unsigned)(stdscr - kbuf)); 
 | 
						|
			stdscr = kbuf;
 | 
						|
		});
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
#ifndef NO_COLOR
 | 
						|
/* This function is called during termination.  It resets color modes */
 | 
						|
int ansiquit()
 | 
						|
{
 | 
						|
	/* if ANSI color terminal, then reset the colors */
 | 
						|
	if (!strcmp(UP, "\033[A"))
 | 
						|
	{
 | 
						|
		tputs("\033[37;40m\033[m", 1, faddch);
 | 
						|
		clrtoeol();
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* This sets the color strings that work for ANSI terminals.  If the TERMCAP
 | 
						|
 * doesn't look like an ANSI terminal, then it returns FALSE.  If the colors
 | 
						|
 * aren't understood, it also returns FALSE.  If all goes well, it returns TRUE
 | 
						|
 */
 | 
						|
int ansicolor(cmode, attrbyte)
 | 
						|
	int	cmode;		/* mode to set, e.g. A_NORMAL */
 | 
						|
	int	attrbyte;	/* IBM PC attribute byte */
 | 
						|
{
 | 
						|
	char	temp[16];	/* hold the new mode string */
 | 
						|
 | 
						|
	/* if not ANSI-ish, then fail */
 | 
						|
	if (strcmp(UP, "\033[A") && strcmp(UP, "\033OA"))
 | 
						|
	{
 | 
						|
		msg("Don't know how to set colors for this terminal");
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	/* construct the color string */
 | 
						|
	sprintf(temp, "\033[m\033[3%c;4%c%s%sm",
 | 
						|
		"04261537"[attrbyte & 0x07],
 | 
						|
		"04261537"[(attrbyte >> 4) & 0x07],
 | 
						|
		(attrbyte & 0x08) ? ";1" : "",
 | 
						|
		(attrbyte & 0x80) ? ";5" : "");
 | 
						|
 | 
						|
	/* stick it in the right place */
 | 
						|
	switch (cmode)
 | 
						|
	{
 | 
						|
	  case A_NORMAL:
 | 
						|
		if (!strcmp(MEcolor, normalcolor))
 | 
						|
			strcpy(MEcolor, temp);
 | 
						|
		if (!strcmp(UEcolor, normalcolor))
 | 
						|
			strcpy(UEcolor, temp);
 | 
						|
		if (!strcmp(AEcolor, normalcolor))
 | 
						|
			strcpy(AEcolor, temp);
 | 
						|
		if (!strcmp(SEcolor, normalcolor))
 | 
						|
			strcpy(SEcolor, temp);
 | 
						|
 | 
						|
		strcpy(normalcolor, temp);
 | 
						|
		tputs(normalcolor, 1, faddch);
 | 
						|
		break;
 | 
						|
 | 
						|
	  case A_BOLD:
 | 
						|
		strcpy(MDcolor, temp);
 | 
						|
		strcpy(MEcolor, normalcolor);
 | 
						|
		break;
 | 
						|
 | 
						|
	  case A_UNDERLINE:
 | 
						|
		strcpy(UScolor, temp);
 | 
						|
		strcpy(UEcolor, normalcolor);
 | 
						|
		break;
 | 
						|
 | 
						|
	  case A_ALTCHARSET:
 | 
						|
		strcpy(AScolor, temp);
 | 
						|
		strcpy(AEcolor, normalcolor);
 | 
						|
		break;
 | 
						|
 | 
						|
	  case A_STANDOUT:
 | 
						|
		strcpy(SOcolor, temp);
 | 
						|
		strcpy(SEcolor, normalcolor);
 | 
						|
		break;
 | 
						|
 | 
						|
#ifndef NO_POPUP
 | 
						|
	  case A_POPUP:
 | 
						|
		strcpy(POPUPcolor, temp);
 | 
						|
		break;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef NO_VISIBLE
 | 
						|
	  case A_VISIBLE:
 | 
						|
		strcpy(VISIBLEcolor, temp);
 | 
						|
		break;
 | 
						|
#endif
 | 
						|
	}
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* This function outputs the ESC sequence needed to switch the screen back
 | 
						|
 * to "normal" mode.  On color terminals which haven't had their color set
 | 
						|
 * yet, this is one of the termcap strings; for color terminals that really
 | 
						|
 * have had colors defined, we just the "normal color" escape sequence.
 | 
						|
 */
 | 
						|
endcolor()
 | 
						|
{
 | 
						|
	if (aend == ME)
 | 
						|
		tputs(MEcolor, 1, faddch);
 | 
						|
	else if (aend == UE)
 | 
						|
		tputs(UEcolor, 1, faddch);
 | 
						|
	else if (aend == AE)
 | 
						|
		tputs(AEcolor, 1, faddch);
 | 
						|
	else if (aend == SE)
 | 
						|
		tputs(SEcolor, 1, faddch);
 | 
						|
	aend = "";
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#endif /* !NO_COLOR */
 |