This is termcap.c in view mode; [Download] [Up]
/* SCCS Id: @(#)termcap.c 3.0 88/11/20
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
#define MONATTK_H /* comment line for pre-compiled headers */
/* block some unused #defines to avoid overloading some cpp's */
#include "hack.h" /* for ROWNO, COLNO, *HI, *HE, *AS, *AE */
#include <ctype.h> /* for isdigit() */
#include "termcap.h"
#if (!defined(SYSV) && !defined(HPUX)) || defined(TOS) || defined(UNIXPC)
# ifndef LINT
extern /* it is defined in libtermlib (libtermcap) */
# endif
short ospeed; /* terminal baudrate; used by tputs */
#else
short ospeed = 0; /* gets around "not defined" error message */
#endif
#ifdef ASCIIGRAPH
#ifdef OVLB
boolean IBMgraphics = FALSE;
#endif /* OVLB */
#endif
#ifdef MICROPORT_286_BUG
#define Tgetstr(key) (tgetstr(key,tbuf))
#else
#define Tgetstr(key) (tgetstr(key,&tbufptr))
#endif /* MICROPORT_286_BUG **/
OSTATIC void FDECL(nocmov, (int, int));
#ifdef TEXTCOLOR
# ifdef TERMLIB
static void NDECL(init_hilite);
# endif
#endif
VSTATIC char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE;
VSTATIC char *VS, *VE, *US, *UE;
VSTATIC char *MR, *ME;
#if 0
VSTATIC char *MB, *MH;
VSTATIC char *MD; /* may already be in use below */
#endif
#ifdef TERMLIB
# ifdef TEXTCOLOR
VSTATIC char *MD;
# endif
VSTATIC int SG;
#ifdef OVLB
XSTATIC char PC = '\0';
#else /* OVLB */
OSTATIC char PC;
#endif /* OVLB */
VSTATIC char tbuf[512];
#endif
#ifdef OVLB
static char nullstr[] = "";
#endif /* OVLB */
#ifndef TERMLIB
VSTATIC char tgotobuf[20];
# ifdef TOS
#define tgoto(fmt, x, y) (Sprintf(tgotobuf, fmt, y+' ', x+' '), tgotobuf)
# else
#define tgoto(fmt, x, y) (Sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf)
# endif
#endif /* TERMLIB */
#ifdef OVLB
void
startup()
{
#ifdef TERMLIB
register const char *term;
register char *tptr;
char *tbufptr, *pc;
#endif
register int i;
#ifdef TERMLIB
# ifdef VMS
term = getenv("EMACS_TERM");
if (!term)
term = getenv("NETHACK_TERM");
if (!term)
# endif
term = getenv("TERM");
#endif
/* Set the default map symbols */
(void) memcpy((genericptr_t) showsyms,
(genericptr_t) defsyms, sizeof showsyms);
#ifdef ASCIIGRAPH
/*
* If we're on an IBM box, default to the nice IBM Extended ASCII
* line-drawing characters (codepage 437).
*
* OS/2 defaults to a multilingual character set (codepage 850,
* corresponding to the ISO 8859 character set. We should probably
* do a VioSetCp() call to set the codepage to 437.
*
* Someday we should do a full terminfo(4) check for ACS forms
* characters.
*/
# if !defined(MSDOS) || defined(DECRAINBOW) || defined(OS2)
# ifdef TERMLIB
if (strncmp("AT", term, 2) == 0)
# endif
# endif
{
IBMgraphics = TRUE;
showsyms[S_vwall] = 0xb3; /* meta-3, vertical rule */
showsyms[S_hodoor] = 0xb3;
showsyms[S_hwall] = 0xc4; /* meta-D, horizontal rule */
showsyms[S_vodoor] = 0xc4;
showsyms[S_tlcorn] = 0xda; /* meta-Z, top left corner */
showsyms[S_trcorn] = 0xbf; /* meta-?, top right corner */
showsyms[S_blcorn] = 0xc0; /* meta-@, bottom left */
showsyms[S_brcorn] = 0xd9; /* meta-Y, bottom right */
showsyms[S_crwall] = 0xc5; /* meta-E, cross */
showsyms[S_tuwall] = 0xc1; /* meta-A, T up */
showsyms[S_tdwall] = 0xc2; /* meta-B, T down */
showsyms[S_tlwall] = 0xb4; /* meta-4, T left */
showsyms[S_trwall] = 0xc3; /* meta-C, T right */
showsyms[S_vbeam] = 0xb3; /* meta-3, vertical rule */
showsyms[S_hbeam] = 0xc4; /* meta-D, horizontal rule */
showsyms[S_room] = 0xfa; /* meta-z, centered dot */
showsyms[S_ndoor] = 0xfa;
showsyms[S_pool] = 0xf7; /* meta-w, approx. equals */
showsyms[S_hodoor] = 0xfe; /* meta-~, small centered square */
showsyms[S_vodoor] = 0xfe;
}
#endif /* ASCIIGRAPH */
#ifdef TERMLIB
if(!term)
#endif
#if defined(TOS) && defined(__GNUC__) && defined(TERMLIB)
term = "builtin"; /* library has a default */
#else
# ifdef MACOS
/* dummy termcap for the Mac */
HO = "\033[H";
CL = "\033[2J"; /* a pseudo-ANSI termcap */
CE = "\033[K";
CM = "\033[%d;%dH"; /* not used */
UP = "\033[A";
ND = "\033[C";
XD = "\033[B";
BC = "\033[D";
TI = TE = SE = UE = US = HE = "\033[0m";
SO = "\033[1m";
AS = VS = VE = AE = "";
CO = COLNO;
LI = ROWNO + 3;
/* use special font ? */
{
extern short macflags;
if (macflags & fUseCustomFont)
{
Handle theRes;
unsigned char *sym;
short i;
sym = &showsyms[S_stone];
theRes = GetResource(HACK_DATA,102);
HLock(theRes);
strncpy((char *)sym,(char *)(*theRes),32);
HUnlock(theRes);
ReleaseResource(theRes);
}
}
# ifdef TEXTCOLOR
for (i = 0; i < MAXCOLORS; i++) {
hilites[i] = (char *) alloc(sizeof("E[cc"));
Sprintf(hilites[i], "\033[c%c", (char)(i+'a'));
}
# endif
# else /* MACOS */
# ifdef ANSI_DEFAULT
# ifdef TOS
{
CO = 80; LI = 25;
TI = VS = VE = TE = "";
HO = "\033H";
CL = "\033E"; /* the VT52 termcap */
CE = "\033K";
UP = "\033A";
CM = "\033Y%c%c"; /* used with function tgoto() */
ND = "\033C";
XD = "\033B";
BC = "\033D";
SO = "\033p";
SE = "\033q";
HI = "\033p";
#ifdef TEXTCOLOR
HE = "\033q\033b\017";
for (i = 0; i < SIZE(hilites); i++) {
hilites[i] = (char *) alloc(sizeof("Eb1"));
Sprintf(hilites[i], (i%4)?"\033b%c" : "\033p", i);
}
#else
HE = "\033q";
#endif
}
# else /* TOS */
{
# ifdef DGK
get_scr_size();
if(CO < COLNO || LI < ROWNO+3)
setclipped();
# endif
HO = "\033[H";
CL = "\033[2J"; /* the ANSI termcap */
/* CD = "\033[J"; */
CE = "\033[K";
# ifndef TERMLIB
CM = "\033[%d;%dH";
# else
CM = "\033[%i%d;%dH";
# endif
UP = "\033[A";
ND = "\033[C";
XD = "\033[B";
# ifdef MSDOS /* backspaces are non-destructive */
BC = "\b";
# else
BC = "\033[D";
# endif
HI = SO = "\033[1m";
US = "\033[4m";
MR = "\033[7m";
TI = HE = SE = UE = ME = "\033[0m";
/* strictly, SE should be 2, and UE should be 24,
but we can't trust all ANSI emulators to be
that complete. -3. */
# if !defined(MSDOS) || defined(DECRAINBOW)
AS = "\016";
AE = "\017";
# endif
TE = VS = VE = "";
# ifdef TEXTCOLOR
for (i = 0; i < MAXCOLORS / 2; i++) {
hilites[i] = (char *) alloc(sizeof("\033[0;3%dm"));
hilites[i+BRIGHT] = (char *) alloc(sizeof("\033[1;3%dm"));
# ifdef MSDOS
Sprintf(hilites[i], (i == BLUE ? "\033[1;3%dm" : "\033[0;3%dm"), i);
# else
Sprintf(hilites[i], "\033[0;3%dm", i);
# endif
Sprintf(hilites[i+BRIGHT], "\033[1;3%dm", i);
}
# endif
return;
}
# endif /* TOS */
# else
error("Can't get TERM.");
# endif /* ANSI_DEFAULT */
# endif /* MACOS */
#endif /* __GNUC__ && TOS && TERMCAP */
#ifdef TERMLIB
tptr = (char *) alloc(1024);
tbufptr = tbuf;
if(!strncmp(term, "5620", 4))
flags.nonull = 1; /* this should be a termcap flag */
if(tgetent(tptr, term) < 1)
error("Unknown terminal type: %s.", term);
if(pc = Tgetstr("pc"))
PC = *pc;
# ifdef TERMINFO
if(!(BC = Tgetstr("le"))) {
# else
if(!(BC = Tgetstr("bc"))) {
# endif
# if !defined(MINIMAL_TERM) && !defined(HISX)
if(!tgetflag("bs"))
error("Terminal must backspace.");
# endif
BC = tbufptr;
tbufptr += 2;
*BC = '\b';
}
# ifdef MINIMAL_TERM
HO = NULL;
# else
HO = Tgetstr("ho");
# endif
/*
* LI and CO are set in ioctl.c via a TIOCGWINSZ if available. If
* the kernel has values for either we should use them rather than
* the values from TERMCAP ...
*/
# ifndef DGK
if (!CO) CO = tgetnum("co");
if (!LI) LI = tgetnum("li");
# else
# if defined(TOS) && defined(__GNUC__)
if (!strcmp(term, "builtin"))
get_scr_size();
else {
# endif
CO = tgetnum("co");
LI = tgetnum("li");
if (!LI || !CO) /* if we don't override it */
get_scr_size();
# if defined(TOS) && defined(__GNUC__)
}
# endif
# endif
if(CO < COLNO || LI < ROWNO+3)
setclipped();
if(!(CL = Tgetstr("cl")))
error("Hack needs CL.");
ND = Tgetstr("nd");
if(tgetflag("os"))
error("Hack can't have OS.");
CE = Tgetstr("ce");
UP = Tgetstr("up");
/* It seems that xd is no longer supported, and we should use
a linefeed instead; unfortunately this requires resetting
CRMOD, and many output routines will have to be modified
slightly. Let's leave that till the next release. */
XD = Tgetstr("xd");
/* not: XD = Tgetstr("do"); */
if(!(CM = Tgetstr("cm"))) {
if(!UP && !HO)
error("Hack needs CM or UP or HO.");
Printf("Playing hack on terminals without cm is suspect...\n");
getret();
}
SO = Tgetstr("so");
SE = Tgetstr("se");
US = Tgetstr("us");
UE = Tgetstr("ue");
SG = tgetnum("sg"); /* -1: not fnd; else # of spaces left by so */
if(!SO || !SE || (SG > 0)) SO = SE = US = UE = nullstr;
TI = Tgetstr("ti");
TE = Tgetstr("te");
VS = VE = nullstr;
# ifdef TERMINFO
VS = Tgetstr("eA"); /* enable graphics */
# endif
# if 0
MB = Tgetstr("mb"); /* blink */
MD = Tgetstr("md"); /* boldface */
MH = Tgetstr("mh"); /* dim */
# endif
MR = Tgetstr("mr"); /* reverse */
ME = Tgetstr("me");
/* Get rid of padding numbers for HI and HE. Hope they
* aren't really needed!!! HI and HE are ouputted to the
* pager as a string - so how can you send it NULLS???
* -jsb
*/
HI = (char *) alloc((unsigned)(strlen(SO)+1));
HE = (char *) alloc((unsigned)(strlen(SE)+1));
i = 0;
while(isdigit(SO[i])) i++;
Strcpy(HI, &SO[i]);
i = 0;
while(isdigit(SE[i])) i++;
Strcpy(HE, &SE[i]);
AS = Tgetstr("as");
AE = Tgetstr("ae");
CD = Tgetstr("cd");
# ifdef TEXTCOLOR
MD = Tgetstr("md");
# endif
set_whole_screen(); /* uses LI and CD */
if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n");
free((genericptr_t)tptr);
# ifdef TEXTCOLOR
init_hilite();
# endif
#endif /* TERMLIB */
}
void
start_screen()
{
xputs(TI);
xputs(VS);
#ifdef DECRAINBOW
/* Select normal ASCII and line drawing character sets.
*/
if (flags.DECRainbow) {
xputs("\033(B\033)0");
if (!AS) {
AS = "\016";
AE = "\017";
}
}
#endif /* DECRAINBOW */
}
void
end_screen()
{
clear_screen();
xputs(VE);
xputs(TE);
}
/* Cursor movements */
#ifdef CLIPPING
/* if (x,y) is currently viewable, move the cursor there and return TRUE */
boolean
win_curs(x, y)
int x, y;
{
if (clipping && (x<=clipx || x>=clipxmax || y<=clipy || y>=clipymax))
return FALSE;
y -= clipy;
x -= clipx;
curs(x, y+2);
return TRUE;
}
#endif
void
curs(x, y)
register int x, y; /* not xchar: perhaps xchar is unsigned and
curx-x would be unsigned as well */
{
if (y == cury && x == curx)
return;
if(!ND && (curx != x || x <= 3)) { /* Extremely primitive */
cmov(x, y); /* bunker!wtm */
return;
}
if(abs(cury-y) <= 3 && abs(curx-x) <= 3)
nocmov(x, y);
else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) {
(void) putchar('\r');
curx = 1;
nocmov(x, y);
} else if(!CM) {
nocmov(x, y);
} else
cmov(x, y);
}
#endif /* OVLB */
#ifdef OVL0
XSTATIC void
nocmov(x, y)
int x,y;
{
if (cury > y) {
if(UP) {
while (cury > y) { /* Go up. */
xputs(UP);
cury--;
}
} else if(CM) {
cmov(x, y);
} else if(HO) {
home();
curs(x, y);
} /* else impossible("..."); */
} else if (cury < y) {
if(XD) {
while(cury < y) {
xputs(XD);
cury++;
}
} else if(CM) {
cmov(x, y);
} else {
while(cury < y) {
xputc('\n');
curx = 1;
cury++;
}
}
}
if (curx < x) { /* Go to the right. */
if(!ND) cmov(x, y); else /* bah */
/* should instead print what is there already */
while (curx < x) {
xputs(ND);
curx++;
}
} else if (curx > x) {
while (curx > x) { /* Go to the left. */
xputs(BC);
curx--;
}
}
}
void
cmov(x, y)
register int x, y;
{
#ifdef MACOS
mcurs(x-1, y-1);
#else
xputs(tgoto(CM, x-1, y-1));
#endif
cury = y;
curx = x;
}
void
xputc(c)
char c;
{
#ifdef MACOS
mputc(c);
#else
(void) fputc(c, stdout);
#endif
}
void
xputs(s)
const char *s;
{
#ifndef MACOS
# ifndef TERMLIB
(void) fputs(s, stdout);
# else
# ifdef __STDC__
tputs(s, 1, (int (*)())xputc);
# else
tputs(s, 1, xputc);
# endif
# endif
#else
mputs(s);
#endif
}
void
cl_end() {
if(CE)
xputs(CE);
else { /* no-CE fix - free after Harold Rynes */
/* this looks terrible, especially on a slow terminal
but is better than nothing */
register int cx = curx, cy = cury;
while(curx < CO) {
xputc(' ');
curx++;
}
curs(cx, cy);
}
}
#endif /* OVL0 */
#ifdef OVLB
void
clear_screen() {
xputs(CL);
home();
}
#endif /* OVLB */
#ifdef OVL0
void
home()
{
if(HO)
xputs(HO);
else if(CM)
xputs(tgoto(CM, 0, 0));
else
curs(1, 1); /* using UP ... */
curx = cury = 1;
}
void
standoutbeg()
{
if(SO) xputs(SO);
}
void
standoutend()
{
if(SE) xputs(SE);
}
void
revbeg()
{
if(MR) xputs(MR);
}
#if 0 /* if you need one of these, uncomment it (here and in extern.h) */
void
boldbeg()
{
if(MD) xputs(MD);
}
void
blinkbeg()
{
if(MB) xputs(MB);
}
void
dimbeg()
/* not in most termcap entries */
{
if(MH) xputs(MH);
}
#endif
void
m_end()
{
if(ME) xputs(ME);
}
void
backsp()
{
xputs(BC);
}
void
bell()
{
if (flags.silent) return;
(void) putchar('\007'); /* curx does not change */
(void) fflush(stdout);
}
#ifdef ASCIIGRAPH
void
graph_on() {
if (AS) xputs(AS);
}
void
graph_off() {
if (AE) xputs(AE);
}
#endif
#endif /* OVL0 */
#ifdef OVL1
#if !defined(MSDOS) && !defined(MACOS)
# ifdef VMS
static const short tmspc10[] = { /* from termcap */
0, 2000, 1333, 909, 743, 666, 333, 166, 83, 55, 50, 41, 27, 20, 13, 10,
5
};
# else
static const short tmspc10[] = { /* from termcap */
0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
};
# endif
#endif
void
delay_output() {
/* delay 50 ms - could also use a 'nap'-system call */
/* BUG: if the padding character is visible, as it is on the 5620
then this looks terrible. */
#if defined(MSDOS) || defined(MACOS)
/* simulate the delay with "cursor here" */
register int i;
for (i = 0; i < 3; i++) {
cmov(curx, cury);
(void) fflush(stdout);
}
#else /* MSDOS || MACOS */
if(!flags.nonull)
# ifdef TERMINFO
/* cbosgd!cbcephus!pds for SYS V R2 */
# ifdef __STDC__
tputs("$<50>", 1, (int (*)())xputc);
# else
tputs("$<50>", 1, xputc);
# endif
# else
# ifdef __STDC__
tputs("50", 1, (int (*)())xputc);
# else
tputs("50", 1, xputc);
# endif
# endif
else if(ospeed > 0 && ospeed < SIZE(tmspc10)) if(CM) {
/* delay by sending cm(here) an appropriate number of times */
register int cmlen = strlen(tgoto(CM, curx-1, cury-1));
register int i = 500 + tmspc10[ospeed]/2;
while(i > 0) {
cmov(curx, cury);
i -= cmlen*tmspc10[ospeed];
}
}
#endif /* MSDOS || MACOS */
}
#endif /* OVL1 */
#ifdef OVLB
void
cl_eos() /* free after Robert Viduya */
{ /* must only be called with curx = 1 */
if(CD)
xputs(CD);
else {
register int cx = curx, cy = cury;
while(cury <= LI-2) {
cl_end();
xputc('\n');
curx = 1;
cury++;
}
cl_end();
curs(cx, cy);
}
}
#if defined(TEXTCOLOR) && defined(TERMLIB)
# ifdef UNIX
/*
* Sets up color highlighting, using terminfo(4) escape sequences (highlight
* code found in pri.c). It is assumed that the background color is black.
*/
/* terminfo indexes for the basic colors it guarantees */
#define COLOR_BLACK 1 /* fake out to avoid black on black */
#define COLOR_BLUE 1
#define COLOR_GREEN 2
#define COLOR_CYAN 3
#define COLOR_RED 4
#define COLOR_MAGENTA 5
#define COLOR_YELLOW 6
#define COLOR_WHITE 7
/* map ANSI RGB to terminfo BGR */
const int ti_map[8] = {
COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW,
COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE };
static void
init_hilite()
{
register int c;
# ifdef TERMINFO
char *setf, *scratch;
extern char *tparm();
# endif
for (c = 0; c < MAXCOLORS; c++)
hilites[c] = HI;
# ifdef TERMINFO
if (tgetnum("Co") < 8 || (setf = tgetstr("Sf", 0)) == NULL)
return;
for (c = 0; c < MAXCOLORS / 2; c++) {
scratch = tparm(setf, ti_map[c]);
hilites[c] = (char *) alloc(strlen(scratch) + 1);
hilites[c+BRIGHT] = (char*) alloc(strlen(scratch)+strlen(MD)+1);
Strcpy(hilites[c], scratch);
Strcpy(hilites[c+BRIGHT], MD);
Strcat(hilites[c+BRIGHT], scratch);
}
# endif
}
# else /* UNIX */
/*
* Sets up highlighting sequences, using ANSI escape sequences (highlight code
* found in pri.c). The termcap entry for HI (from SO) is scanned to find the
* background color.
*/
static void
init_hilite()
{
# ifdef TOS
int c;
static char unhilite[] = "\033q\033b3\033c0";
# else
int backg = BLACK, foreg = WHITE, len;
register int c, color;
# endif
for (c = 0; c < SIZE(hilites); c++)
hilites[c] = HI;
# ifdef TOS
hilites[BROWN] = "\033b0\033c1";
hilites[RED] = "\033b1";
hilites[MAGENTA] = hilites[MAGENTA|BRIGHT] = "\033b1\033c2";
hilites[CYAN] = hilites[CYAN|BRIGHT] = "\033b3\033c2";
hilites[BLUE] = hilites[BLUE|BRIGHT] = "\033b2";
hilites[GREEN] = hilites[GREEN|BRIGHT] = "\033b2\033c3";
hilites[GRAY] = "\033b3\033c0";
hilites[ORANGE_COLORED] = "\033b3\033c1";
hilites[YELLOW] = "\033b1\033c3";
hilites[WHITE] = "\033b0\033c3";
HE = unhilite; /* to turn off the color stuff too */
# else /* TOS */
/* find the background color, HI[len] == 'm' */
len = strlen(HI) - 1;
if (HI[len] != 'm' || len < 3) return;
c = 2;
while (c < len) {
if ((color = atoi(&HI[c])) == 0) {
/* this also catches errors */
foreg = WHITE; backg = BLACK;
/*
} else if (color == 1) {
foreg |= BRIGHT;
*/
} else if (color >= 30 && color <= 37) {
foreg = color - 30;
} else if (color >= 40 && color <= 47) {
backg = color - 40;
}
while (isdigit(HI[++c]));
c++;
}
for (c = 0; c < MAXCOLORS / 2; c++)
/* avoid invisibility */
if (foreg != c && backg != c) {
hilites[c] = (char *) alloc(sizeof("\033[0;3%d;4%dm"));
hilites[c+BRIGHT] = (char *) alloc(sizeof("\033[1;3%d;4%dm"));
#ifdef MSDOS /* brighten low-visibility colors */
if (c == BLUE)
Sprintf(hilites[c], "\033[1;3%d;4%dm", c, backg);
else
#endif
Sprintf(hilites[c], "\033[0;3%d;4%dm", c, backg);
Sprintf(hilites[c+BRIGHT], "\033[1;3%d;4%dm", c, backg);
}
# endif /* TOS */
}
# endif /* UNIX */
#endif /* TEXTCOLOR */
#endif /* OVLB */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.