928 lines
19 KiB
C
928 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 */
|