From: jwalz Date: Sat, 5 Jan 2002 21:06:02 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: MOVE2GIT~3561 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f4ed144a008bfe7b545deeb2c3621e319f1bd226;p=nethack *** empty log message *** --- diff --git a/win/tty/termcap.c b/win/tty/termcap.c new file mode 100644 index 000000000..590c66b85 --- /dev/null +++ b/win/tty/termcap.c @@ -0,0 +1,1172 @@ +/* SCCS Id: @(#)termcap.c 3.3 2000/07/10 */ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" + +#if defined (TTY_GRAPHICS) && !defined(NO_TERMS) + +#include "wintty.h" + +#include "tcap.h" + + +#ifdef MICROPORT_286_BUG +#define Tgetstr(key) (tgetstr(key,tbuf)) +#else +#define Tgetstr(key) (tgetstr(key,&tbufptr)) +#endif /* MICROPORT_286_BUG **/ + +static char * FDECL(s_atr2str, (int)); +static char * FDECL(e_atr2str, (int)); + +void FDECL(cmov, (int, int)); +void FDECL(nocmov, (int, int)); +#if defined(TEXTCOLOR) && defined(TERMLIB) +# ifdef OVLB +# if !defined(UNIX) || !defined(TERMINFO) +# ifndef TOS +static void FDECL(analyze_seq, (char *, int *, int *)); +# endif +# endif +static void NDECL(init_hilite); +static void NDECL(kill_hilite); +# endif /* OVLB */ +#endif + +#ifdef OVLB + /* (see tcap.h) -- nh_CM, nh_ND, nh_CD, nh_HI,nh_HE, nh_US,nh_UE, + ul_hack */ +struct tc_lcl_data tc_lcl_data = { 0, 0, 0, 0,0, 0,0, FALSE }; +#endif /* OVLB */ + +STATIC_VAR char *HO, *CL, *CE, *UP, *XD, *BC, *SO, *SE, *TI, *TE; +STATIC_VAR char *VS, *VE; +STATIC_VAR char *ME; +STATIC_VAR char *MR; +#if 0 +STATIC_VAR char *MB, *MH; +STATIC_VAR char *MD; /* may already be in use below */ +#endif +#ifdef TERMLIB +# ifdef TEXTCOLOR +STATIC_VAR char *MD; +# endif +STATIC_VAR int SG; +#ifdef OVLB +STATIC_OVL char PC = '\0'; +#else /* OVLB */ +STATIC_DCL char PC; +#endif /* OVLB */ +STATIC_VAR char tbuf[512]; +#endif + +#ifdef TEXTCOLOR +# ifdef TOS +const char *hilites[CLR_MAX]; /* terminal escapes for the various colors */ +# else +char NEARDATA *hilites[CLR_MAX]; /* terminal escapes for the various colors */ +# endif +#endif + +#ifdef OVLB +static char *KS = (char *)0, *KE = (char *)0; /* keypad sequences */ +static char nullstr[] = ""; +#endif /* OVLB */ + +#if defined(ASCIIGRAPH) && !defined(NO_TERMS) +extern boolean HE_resets_AS; +#endif + +#ifndef TERMLIB +STATIC_VAR 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 +tty_startup(wid, hgt) +int *wid, *hgt; +{ + register int i; +#ifdef TERMLIB + register const char *term; + register char *tptr; + char *tbufptr, *pc; + +# ifdef VMS + term = verify_termcap(); + if (!term) +# endif + term = getenv("TERM"); + +# if defined(TOS) && defined(__GNUC__) + if (!term) + term = "builtin"; /* library has a default */ +# endif + if (!term) +#endif +#ifndef ANSI_DEFAULT + error("Can't get TERM."); +#else +# ifdef TOS + { + CO = 80; LI = 25; + TI = VS = VE = TE = nullstr; + HO = "\033H"; + CE = "\033K"; /* the VT52 termcap */ + UP = "\033A"; + nh_CM = "\033Y%c%c"; /* used with function tgoto() */ + nh_ND = "\033C"; + XD = "\033B"; + BC = "\033D"; + SO = "\033p"; + SE = "\033q"; + /* HI and HE will be updated in init_hilite if we're using color */ + nh_HI = "\033p"; + nh_HE = "\033q"; + *wid = CO; + *hgt = LI; + CL = "\033E"; /* last thing set */ + return; + } +# else /* TOS */ + { +# ifdef MICRO + get_scr_size(); +# ifdef CLIPPING + if(CO < COLNO || LI < ROWNO+3) + setclipped(); +# endif +# endif + HO = "\033[H"; +/* nh_CD = "\033[J"; */ + CE = "\033[K"; /* the ANSI termcap */ +# ifndef TERMLIB + nh_CM = "\033[%d;%dH"; +# else + nh_CM = "\033[%i%d;%dH"; +# endif + UP = "\033[A"; + nh_ND = "\033[C"; + XD = "\033[B"; +# ifdef MICRO /* backspaces are non-destructive */ + BC = "\b"; +# else + BC = "\033[D"; +# endif + nh_HI = SO = "\033[1m"; + nh_US = "\033[4m"; + MR = "\033[7m"; + TI = nh_HE = ME = SE = nh_UE = "\033[0m"; + /* strictly, SE should be 2, and nh_UE should be 24, + but we can't trust all ANSI emulators to be + that complete. -3. */ +# ifndef MICRO + AS = "\016"; + AE = "\017"; +# endif + TE = VS = VE = nullstr; +# ifdef TEXTCOLOR + for (i = 0; i < CLR_MAX / 2; i++) + if (i != CLR_BLACK) { + hilites[i|BRIGHT] = (char *) alloc(sizeof("\033[1;3%dm")); + Sprintf(hilites[i|BRIGHT], "\033[1;3%dm", i); + if (i != CLR_GRAY) +# ifdef MICRO + if (i == CLR_BLUE) hilites[CLR_BLUE] = hilites[CLR_BLUE|BRIGHT]; + else +# endif + { + hilites[i] = (char *) alloc(sizeof("\033[0;3%dm")); + Sprintf(hilites[i], "\033[0;3%dm", i); + } + } +# endif + *wid = CO; + *hgt = LI; + CL = "\033[2J"; /* last thing set */ + return; + } +# endif /* TOS */ +#endif /* ANSI_DEFAULT */ + +#ifdef TERMLIB + tptr = (char *) alloc(1024); + + tbufptr = tbuf; + if(!strncmp(term, "5620", 4)) + flags.null = FALSE; /* this should be a termcap flag */ + if(tgetent(tptr, term) < 1) { + char buf[BUFSZ]; + (void) strncpy(buf, term, + (BUFSZ - 1) - (sizeof("Unknown terminal type: . "))); + buf[BUFSZ-1] = '\0'; + error("Unknown terminal type: %s.", term); + } + if ((pc = Tgetstr("pc")) != 0) + PC = *pc; + + if(!(BC = Tgetstr("le"))) /* both termcap and terminfo use le */ +# ifdef TERMINFO + error("Terminal must backspace."); +# else + if(!(BC = Tgetstr("bc"))) { /* termcap also uses bc/bs */ +# ifndef MINIMAL_TERM + if(!tgetflag("bs")) + error("Terminal must backspace."); +# endif + BC = tbufptr; + tbufptr += 2; + *BC = '\b'; + } +# endif + +# ifdef MINIMAL_TERM + HO = (char *)0; +# 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 MICRO + 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 +# ifdef CLIPPING + if(CO < COLNO || LI < ROWNO+3) + setclipped(); +# endif + nh_ND = Tgetstr("nd"); + if(tgetflag("os")) + error("NetHack can't have OS."); + if(tgetflag("ul")) + ul_hack = TRUE; + 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(!(nh_CM = Tgetstr("cm"))) { + if(!UP && !HO) + error("NetHack needs CM or UP or HO."); + tty_raw_print("Playing NetHack on terminals without CM is suspect."); + tty_wait_synch(); + } + SO = Tgetstr("so"); + SE = Tgetstr("se"); + nh_US = Tgetstr("us"); + nh_UE = Tgetstr("ue"); + SG = tgetnum("sg"); /* -1: not fnd; else # of spaces left by so */ + if(!SO || !SE || (SG > 0)) SO = SE = nh_US = nh_UE = nullstr; + TI = Tgetstr("ti"); + TE = Tgetstr("te"); + VS = VE = nullstr; +# ifdef TERMINFO + VS = Tgetstr("eA"); /* enable graphics */ +# endif + KS = Tgetstr("ks"); /* keypad start (special mode) */ + KE = Tgetstr("ke"); /* keypad end (ordinary mode [ie, digits]) */ + MR = Tgetstr("mr"); /* reverse */ +# if 0 + MB = Tgetstr("mb"); /* blink */ + MD = Tgetstr("md"); /* boldface */ + MH = Tgetstr("mh"); /* dim */ +# endif + ME = Tgetstr("me"); /* turn off all attributes */ + if (!ME || (SE == nullstr)) ME = SE; /* default to SE value */ + + /* Get rid of padding numbers for nh_HI and nh_HE. Hope they + * aren't really needed!!! nh_HI and nh_HE are outputted to the + * pager as a string - so how can you send it NULs??? + * -jsb + */ + nh_HI = (char *) alloc((unsigned)(strlen(SO)+1)); + nh_HE = (char *) alloc((unsigned)(strlen(ME)+1)); + i = 0; + while (digit(SO[i])) i++; + Strcpy(nh_HI, &SO[i]); + i = 0; + while (digit(ME[i])) i++; + Strcpy(nh_HE, &ME[i]); + AS = Tgetstr("as"); + AE = Tgetstr("ae"); + nh_CD = Tgetstr("cd"); +# ifdef TEXTCOLOR + MD = Tgetstr("md"); +# endif +# ifdef TEXTCOLOR +# if defined(TOS) && defined(__GNUC__) + if (!strcmp(term, "builtin") || !strcmp(term, "tw52") || + !strcmp(term, "st52")) { + init_hilite(); + } +# else + init_hilite(); +# endif +# endif + *wid = CO; + *hgt = LI; + if (!(CL = Tgetstr("cl"))) /* last thing set */ + error("NetHack needs CL."); + if ((int)(tbufptr - tbuf) > (int)(sizeof tbuf)) + error("TERMCAP entry too big...\n"); + free((genericptr_t)tptr); +#endif /* TERMLIB */ +} + +/* note: at present, this routine is not part of the formal window interface */ +/* deallocate resources prior to final termination */ +void +tty_shutdown() +{ +#if defined(TEXTCOLOR) && defined(TERMLIB) + kill_hilite(); +#endif + /* we don't attempt to clean up individual termcap variables [yet?] */ + return; +} + +void +tty_number_pad(state) +int state; +{ + switch (state) { + case -1: /* activate keypad mode (escape sequences) */ + if (KS && *KS) xputs(KS); + break; + case 1: /* activate numeric mode for keypad (digits) */ + if (KE && *KE) xputs(KE); + break; + case 0: /* don't need to do anything--leave terminal as-is */ + default: + break; + } +} + +#ifdef TERMLIB +extern void NDECL((*decgraphics_mode_callback)); /* defined in drawing.c */ +static void NDECL(tty_decgraphics_termcap_fixup); + +/* + We call this routine whenever DECgraphics mode is enabled, even if it + has been previously set, in case the user manages to reset the fonts. + The actual termcap fixup only needs to be done once, but we can't + call xputs() from the option setting or graphics assigning routines, + so this is a convenient hook. + */ +static void +tty_decgraphics_termcap_fixup() +{ + static char ctrlN[] = "\016"; + static char ctrlO[] = "\017"; + static char appMode[] = "\033="; + static char numMode[] = "\033>"; + + /* these values are missing from some termcaps */ + if (!AS) AS = ctrlN; /* ^N (shift-out [graphics font]) */ + if (!AE) AE = ctrlO; /* ^O (shift-in [regular font]) */ + if (!KS) KS = appMode; /* ESC= (application keypad mode) */ + if (!KE) KE = numMode; /* ESC> (numeric keypad mode) */ + /* + * Select the line-drawing character set as the alternate font. + * Do not select NA ASCII as the primary font since people may + * reasonably be using the UK character set. + */ + if (iflags.DECgraphics) xputs("\033)0"); +#ifdef PC9800 + init_hilite(); +#endif + +#if defined(ASCIIGRAPH) && !defined(NO_TERMS) + /* some termcaps suffer from the bizarre notion that resetting + video attributes should also reset the chosen character set */ + { + const char *nh_he = nh_HE, *ae = AE; + int he_limit, ae_length; + + if (digit(*ae)) { /* skip over delay prefix, if any */ + do ++ae; while (digit(*ae)); + if (*ae == '.') { ++ae; if (digit(*ae)) ++ae; } + if (*ae == '*') ++ae; + } + /* can't use nethack's case-insensitive strstri() here, and some old + systems don't have strstr(), so use brute force substring search */ + ae_length = strlen(ae), he_limit = strlen(nh_he); + while (he_limit >= ae_length) { + if (strncmp(nh_he, ae, ae_length) == 0) { + HE_resets_AS = TRUE; + break; + } + ++nh_he, --he_limit; + } + } +#endif +} +#endif /* TERMLIB */ + +#if defined(ASCIIGRAPH) && defined(PC9800) +extern void NDECL((*ibmgraphics_mode_callback)); /* defined in drawing.c */ +#endif + +#ifdef PC9800 +extern void NDECL((*ascgraphics_mode_callback)); /* defined in drawing.c */ +static void NDECL(tty_ascgraphics_hilite_fixup); + +static void +tty_ascgraphics_hilite_fixup() +{ + register int c; + + for (c = 0; c < CLR_MAX / 2; c++) + if (c != CLR_BLACK) { + hilites[c|BRIGHT] = (char *) alloc(sizeof("\033[1;3%dm")); + Sprintf(hilites[c|BRIGHT], "\033[1;3%dm", c); + if (c != CLR_GRAY) { + hilites[c] = (char *) alloc(sizeof("\033[0;3%dm")); + Sprintf(hilites[c], "\033[0;3%dm", c); + } + } +} +#endif /* PC9800 */ + +void +tty_start_screen() +{ + xputs(TI); + xputs(VS); +#ifdef PC9800 + if (!iflags.IBMgraphics && !iflags.DECgraphics) + tty_ascgraphics_hilite_fixup(); + /* set up callback in case option is not set yet but toggled later */ + ascgraphics_mode_callback = tty_ascgraphics_hilite_fixup; +# ifdef ASCIIGRAPH + if (iflags.IBMgraphics) init_hilite(); + /* set up callback in case option is not set yet but toggled later */ + ibmgraphics_mode_callback = init_hilite; +# endif +#endif /* PC9800 */ + +#ifdef TERMLIB + if (iflags.DECgraphics) tty_decgraphics_termcap_fixup(); + /* set up callback in case option is not set yet but toggled later */ + decgraphics_mode_callback = tty_decgraphics_termcap_fixup; +#endif + if (iflags.num_pad) tty_number_pad(1); /* make keypad send digits */ +} + +void +tty_end_screen() +{ + clear_screen(); + xputs(VE); + xputs(TE); +} + +/* Cursor movements */ + +#endif /* OVLB */ + +#ifdef OVL0 +/* Note to OVLx tinkerers. The placement of this overlay controls the location + of the function xputc(). This function is not currently in trampoli.[ch] + files for what is deemed to be performance reasons. If this define is moved + and or xputc() is taken out of the ROOT overlay, then action must be taken + in trampoli.[ch]. */ + +void +nocmov(x, y) +int x,y; +{ + if ((int) ttyDisplay->cury > y) { + if(UP) { + while ((int) ttyDisplay->cury > y) { /* Go up. */ + xputs(UP); + ttyDisplay->cury--; + } + } else if(nh_CM) { + cmov(x, y); + } else if(HO) { + home(); + tty_curs(BASE_WINDOW, x+1, y); + } /* else impossible("..."); */ + } else if ((int) ttyDisplay->cury < y) { + if(XD) { + while((int) ttyDisplay->cury < y) { + xputs(XD); + ttyDisplay->cury++; + } + } else if(nh_CM) { + cmov(x, y); + } else { + while((int) ttyDisplay->cury < y) { + xputc('\n'); + ttyDisplay->curx = 0; + ttyDisplay->cury++; + } + } + } + if ((int) ttyDisplay->curx < x) { /* Go to the right. */ + if(!nh_ND) cmov(x, y); else /* bah */ + /* should instead print what is there already */ + while ((int) ttyDisplay->curx < x) { + xputs(nh_ND); + ttyDisplay->curx++; + } + } else if ((int) ttyDisplay->curx > x) { + while ((int) ttyDisplay->curx > x) { /* Go to the left. */ + xputs(BC); + ttyDisplay->curx--; + } + } +} + +void +cmov(x, y) +register int x, y; +{ + xputs(tgoto(nh_CM, x, y)); + ttyDisplay->cury = y; + ttyDisplay->curx = x; +} + +/* See note at OVLx ifdef above. xputc() is a special function. */ +void +xputc(c) +#if defined(apollo) +int c; +#else +char c; +#endif +{ + (void) putchar(c); +} + +void +xputs(s) +const char *s; +{ +# ifndef TERMLIB + (void) fputs(s, stdout); +# else +# if defined(NHSTDC) || defined(ULTRIX_PROTO) + tputs(s, 1, (int (*)())xputc); +# else + tputs(s, 1, xputc); +# endif +# 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 = ttyDisplay->curx+1; + + while(cx < CO) { + xputc(' '); + cx++; + } + tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1, + (int)ttyDisplay->cury); + } +} + +#endif /* OVL0 */ +#ifdef OVLB + +void +clear_screen() +{ + /* note: if CL is null, then termcap initialization failed, + so don't attempt screen-oriented I/O during final cleanup. + */ + if (CL) { + xputs(CL); + home(); + } +} + +#endif /* OVLB */ +#ifdef OVL0 + +void +home() +{ + if(HO) + xputs(HO); + else if(nh_CM) + xputs(tgoto(nh_CM, 0, 0)); + else + tty_curs(BASE_WINDOW, 1, 0); /* using UP ... */ + ttyDisplay->curx = ttyDisplay->cury = 0; +} + +void +standoutbeg() +{ + if(SO) xputs(SO); +} + +void +standoutend() +{ + if(SE) xputs(SE); +} + +#if 0 /* if you need one of these, uncomment it (here and in extern.h) */ +void +revbeg() +{ + if(MR) xputs(MR); +} + +void +boldbeg() +{ + if(MD) xputs(MD); +} + +void +blinkbeg() +{ + if(MB) xputs(MB); +} + +void +dimbeg() +/* not in most termcap entries */ +{ + if(MH) xputs(MH); +} + +void +m_end() +{ + if(ME) xputs(ME); +} +#endif + +#endif /* OVL0 */ +#ifdef OVLB + +void +backsp() +{ + xputs(BC); +} + +void +tty_nhbell() +{ + if (flags.silent) return; + (void) putchar('\007'); /* curx does not change */ + (void) fflush(stdout); +} + +#endif /* OVLB */ +#ifdef OVL0 + +#ifdef ASCIIGRAPH +void +graph_on() { + if (AS) xputs(AS); +} + +void +graph_off() { + if (AE) xputs(AE); +} +#endif + +#endif /* OVL0 */ +#ifdef OVL1 + +#if !defined(MICRO) +# 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 + +/* delay 50 ms */ +void +tty_delay_output() +{ +#if defined(MICRO) + register int i; +#endif +#ifdef TIMED_DELAY + if (flags.nap) { + (void) fflush(stdout); + msleep(50); /* sleep for 50 milliseconds */ + return; + } +#endif +#if defined(MICRO) + /* simulate the delay with "cursor here" */ + for (i = 0; i < 3; i++) { + cmov(ttyDisplay->curx, ttyDisplay->cury); + (void) fflush(stdout); + } +#else /* MICRO */ + /* BUG: if the padding character is visible, as it is on the 5620 + then this looks terrible. */ + if(flags.null) +# ifdef TERMINFO + /* cbosgd!cbcephus!pds for SYS V R2 */ +# ifdef NHSTDC + tputs("$<50>", 1, (int (*)())xputc); +# else + tputs("$<50>", 1, xputc); +# endif +# else +# if defined(NHSTDC) || defined(ULTRIX_PROTO) + tputs("50", 1, (int (*)())xputc); +# else + tputs("50", 1, xputc); +# endif +# endif + + else if(ospeed > 0 && ospeed < SIZE(tmspc10) && nh_CM) { + /* delay by sending cm(here) an appropriate number of times */ + register int cmlen = strlen(tgoto(nh_CM, ttyDisplay->curx, + ttyDisplay->cury)); + register int i = 500 + tmspc10[ospeed]/2; + + while(i > 0) { + cmov((int)ttyDisplay->curx, (int)ttyDisplay->cury); + i -= cmlen*tmspc10[ospeed]; + } + } +#endif /* MICRO */ +} + +#endif /* OVL1 */ +#ifdef OVLB + +void +cl_eos() /* free after Robert Viduya */ +{ /* must only be called with curx = 1 */ + + if(nh_CD) + xputs(nh_CD); + else { + register int cy = ttyDisplay->cury+1; + while(cy <= LI-2) { + cl_end(); + xputc('\n'); + cy++; + } + cl_end(); + tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1, + (int)ttyDisplay->cury); + } +} + +#if defined(TEXTCOLOR) && defined(TERMLIB) +# if defined(UNIX) && defined(TERMINFO) +/* + * Sets up color highlighting, using terminfo(4) escape sequences. + * + * Having never seen a terminfo system without curses, we assume this + * inclusion is safe. On systems with color terminfo, it should define + * the 8 COLOR_FOOs, and avoid us having to guess whether this particular + * terminfo uses BGR or RGB for its indexes. + * + * If we don't get the definitions, then guess. Original color terminfos + * used BGR for the original Sf (setf, Standard foreground) codes, but + * there was a near-total lack of user documentation, so some subsequent + * terminfos, such as early Linux ncurses and SCO UNIX, used RGB. Possibly + * as a result of the confusion, AF (setaf, ANSI Foreground) codes were + * introduced, but this caused yet more confusion. Later Linux ncurses + * have BGR Sf, RGB AF, and RGB COLOR_FOO, which appears to be the SVR4 + * standard. We could switch the colors around when using Sf with ncurses, + * which would help things on later ncurses and hurt things on early ncurses. + * We'll try just preferring AF and hoping it always agrees with COLOR_FOO, + * and falling back to Sf if AF isn't defined. + * + * In any case, treat black specially so we don't try to display black + * characters on the assumed black background. + */ + + /* `curses' is aptly named; various versions don't like these + macros used elsewhere within nethack; fortunately they're + not needed beyond this point, so we don't need to worry + about reconstructing them after the header file inclusion. */ +#undef delay_output +#undef TRUE +#undef FALSE +#define m_move curses_m_move /* Some curses.h decl m_move(), not used here */ + +#include + +#ifndef LINUX +extern char *tparm(); +#endif + +# ifdef COLOR_BLACK /* trust include file */ +#undef COLOR_BLACK +# else +# ifndef _M_UNIX /* guess BGR */ +#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 +# else /* guess RGB */ +#define COLOR_RED 1 +#define COLOR_GREEN 2 +#define COLOR_YELLOW 3 +#define COLOR_BLUE 4 +#define COLOR_MAGENTA 5 +#define COLOR_CYAN 6 +#define COLOR_WHITE 7 +# endif +# endif +#define COLOR_BLACK COLOR_BLUE + +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; + char *setf, *scratch; + + for (c = 0; c < SIZE(hilites); c++) + hilites[c] = nh_HI; + hilites[CLR_GRAY] = hilites[NO_COLOR] = (char *)0; + + if (tgetnum("Co") < 8 + || ((setf = tgetstr("AF", (char **)0)) == (char *)0 + && (setf = tgetstr("Sf", (char **)0)) == (char *)0)) + return; + + for (c = 0; c < CLR_MAX / 2; c++) { + scratch = tparm(setf, ti_map[c]); + if (c != CLR_GRAY) { + hilites[c] = (char *) alloc(strlen(scratch) + 1); + Strcpy(hilites[c], scratch); + } + if (c != CLR_BLACK) { + hilites[c|BRIGHT] = (char*) alloc(strlen(scratch)+strlen(MD)+1); + Strcpy(hilites[c|BRIGHT], MD); + Strcat(hilites[c|BRIGHT], scratch); + } + + } +} + +# else /* UNIX && TERMINFO */ + +# ifndef TOS +/* find the foreground and background colors set by nh_HI or nh_HE */ +static void +analyze_seq (str, fg, bg) +char *str; +int *fg, *bg; +{ + register int c, code; + int len; + +# ifdef MICRO + *fg = CLR_GRAY; *bg = CLR_BLACK; +# else + *fg = *bg = NO_COLOR; +# endif + + c = (str[0] == '\233') ? 1 : 2; /* index of char beyond esc prefix */ + len = strlen(str) - 1; /* length excluding attrib suffix */ + if ((c != 1 && (str[0] != '\033' || str[1] != '[')) || + (len - c) < 1 || str[len] != 'm') + return; + + while (c < len) { + if ((code = atoi(&str[c])) == 0) { /* reset */ + /* this also catches errors */ +# ifdef MICRO + *fg = CLR_GRAY; *bg = CLR_BLACK; +# else + *fg = *bg = NO_COLOR; +# endif + } else if (code == 1) { /* bold */ + *fg |= BRIGHT; +# if 0 + /* I doubt we'll ever resort to using blinking characters, + unless we want a pulsing glow for something. But, in case + we do... - 3. */ + } else if (code == 5) { /* blinking */ + *fg |= BLINK; + } else if (code == 25) { /* stop blinking */ + *fg &= ~BLINK; +# endif + } else if (code == 7 || code == 27) { /* reverse */ + code = *fg & ~BRIGHT; + *fg = *bg | (*fg & BRIGHT); + *bg = code; + } else if (code >= 30 && code <= 37) { /* hi_foreground RGB */ + *fg = code - 30; + } else if (code >= 40 && code <= 47) { /* hi_background RGB */ + *bg = code - 40; + } + while (digit(str[++c])); + c++; + } +} +# endif + +/* + * Sets up highlighting sequences, using ANSI escape sequences (highlight code + * found in print.c). The nh_HI and nh_HE sequences (usually from SO) are + * scanned to find foreground and background colors. + */ + +static void +init_hilite() +{ + register int c; +# ifdef TOS + extern unsigned long tos_numcolors; /* in tos.c */ + static char NOCOL[] = "\033b0", COLHE[] = "\033q\033b0"; + + if (tos_numcolors <= 2) { + return; + } +/* Under TOS, the "bright" and "dim" colors are reversed. Moreover, + * on the Falcon the dim colors are *really* dim; so we make most + * of the colors the bright versions, with a few exceptions where + * the dim ones look OK. + */ + hilites[0] = NOCOL; + for (c = 1; c < SIZE(hilites); c++) { + char *foo; + foo = (char *) alloc(sizeof("\033b0")); + if (tos_numcolors > 4) + Sprintf(foo, "\033b%c", (c&~BRIGHT)+'0'); + else + Strcpy(foo, "\033b0"); + hilites[c] = foo; + } + + if (tos_numcolors == 4) { + TI = "\033b0\033c3\033E\033e"; + TE = "\033b3\033c0\033J"; + nh_HE = COLHE; + hilites[CLR_GREEN] = hilites[CLR_GREEN|BRIGHT] = "\033b2"; + hilites[CLR_RED] = hilites[CLR_RED|BRIGHT] = "\033b1"; + } else { + sprintf(hilites[CLR_BROWN], "\033b%c", (CLR_BROWN^BRIGHT)+'0'); + sprintf(hilites[CLR_GREEN], "\033b%c", (CLR_GREEN^BRIGHT)+'0'); + + TI = "\033b0\033c\017\033E\033e"; + TE = "\033b\017\033c0\033J"; + nh_HE = COLHE; + hilites[CLR_WHITE] = hilites[CLR_BLACK] = NOCOL; + hilites[NO_COLOR] = hilites[CLR_GRAY]; + } + +# else /* TOS */ + + int backg, foreg, hi_backg, hi_foreg; + + for (c = 0; c < SIZE(hilites); c++) + hilites[c] = nh_HI; + hilites[CLR_GRAY] = hilites[NO_COLOR] = (char *)0; + + analyze_seq(nh_HI, &hi_foreg, &hi_backg); + analyze_seq(nh_HE, &foreg, &backg); + + for (c = 0; c < SIZE(hilites); c++) + /* avoid invisibility */ + if ((backg & ~BRIGHT) != c) { +# ifdef MICRO + if (c == CLR_BLUE) continue; +# endif + if (c == foreg) + hilites[c] = (char *)0; + else if (c != hi_foreg || backg != hi_backg) { + hilites[c] = (char *) alloc(sizeof("\033[%d;3%d;4%dm")); + Sprintf(hilites[c], "\033[%d", !!(c & BRIGHT)); + if ((c | BRIGHT) != (foreg | BRIGHT)) + Sprintf(eos(hilites[c]), ";3%d", c & ~BRIGHT); + if (backg != CLR_BLACK) + Sprintf(eos(hilites[c]), ";4%d", backg & ~BRIGHT); + Strcat(hilites[c], "m"); + } + } + +# ifdef MICRO + /* brighten low-visibility colors */ + hilites[CLR_BLUE] = hilites[CLR_BLUE|BRIGHT]; +# endif +# endif /* TOS */ +} +# endif /* UNIX */ + +static void +kill_hilite() +{ +# ifndef TOS + register int c; + + for (c = 0; c < CLR_MAX / 2; c++) { + if (hilites[c|BRIGHT] == hilites[c]) hilites[c|BRIGHT] = 0; + if (hilites[c] && (hilites[c] != nh_HI)) + free((genericptr_t) hilites[c]), hilites[c] = 0; + if (hilites[c|BRIGHT] && (hilites[c|BRIGHT] != nh_HI)) + free((genericptr_t) hilites[c|BRIGHT]), hilites[c|BRIGHT] = 0; + } +# endif + return; +} +#endif /* TEXTCOLOR */ + + +static char nulstr[] = ""; + +static char * +s_atr2str(n) +int n; +{ + switch (n) { + case ATR_ULINE: + if(nh_US) return nh_US; + case ATR_BOLD: + case ATR_BLINK: + return nh_HI; + case ATR_INVERSE: + return MR; + } + return nulstr; +} + +static char * +e_atr2str(n) +int n; +{ + switch (n) { + case ATR_ULINE: + if(nh_UE) return nh_UE; + case ATR_BOLD: + case ATR_BLINK: + return nh_HE; + case ATR_INVERSE: + return ME; + } + return nulstr; +} + + +void +term_start_attr(attr) +int attr; +{ + if (attr) { + xputs(s_atr2str(attr)); + } +} + + +void +term_end_attr(attr) +int attr; +{ + if(attr) { + xputs(e_atr2str(attr)); + } +} + + +void +term_start_raw_bold() +{ + xputs(nh_HI); +} + + +void +term_end_raw_bold() +{ + xputs(nh_HE); +} + + +#ifdef TEXTCOLOR + +void +term_end_color() +{ + xputs(nh_HE); +} + + +void +term_start_color(color) +int color; +{ + xputs(hilites[color]); +} + + +int +has_color(color) +int color; +{ +#ifdef X11_GRAPHICS + /* XXX has_color() should be added to windowprocs */ + if (windowprocs.name != NULL && + !strcmpi(windowprocs.name, "X11")) return TRUE; +#endif +#ifdef AMII_GRAPHICS + /* hilites[] not used */ + return iflags.use_color; +#endif + return hilites[color] != (char *)0; +} + +#endif /* TEXTCOLOR */ + +#endif /* OVLB */ + +#endif /* TTY_GRAPHICS */ + +/*termcap.c*/