/* 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 # if UNIXV # ifdef TERMIOS # include # else # include # endif # ifdef S5WINSIZE # include /* winsize struct defined in one of these? */ # include # else # undef TIOCGWINSZ /* we can't handle it correctly yet */ # endif # else # include # endif #endif #if TOS # include #endif #if MINT # include #endif #if OSK # include #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 *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 key */ char *EN; /* :EN=: key sequence sent by the key */ char *PU; /* :PU=: key sequence sent by the key */ char *PD; /* :PD=: key sequence sent by the key */ char *KI; /* :kI=: key sequence sent by the 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 # if UNIXV # ifdef TERMIOS static struct termios oldtermio; /* original tty mode */ static struct termios newtermio; /* cbreak/noecho tty mode */ # else static struct termio oldtermio; /* original tty mode */ static struct termio newtermio; /* cbreak/noecho tty mode */ # endif # else static struct sgttyb oldsgttyb; /* original tty mode */ static struct sgttyb newsgttyb; /* cbreak/nl/noecho tty mode */ static int oldint; /* ^C or DEL, the "intr" character */ # ifdef TIOCSLTC static int oldswitch; /* ^Z, the "suspend" character */ static int olddswitch; /* ^Y, the "delayed suspend" char */ static int oldquote; /* ^V, the "quote next char" char */ # endif # endif #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 || MINT write(2, "Environment variable TERM must be set\n", (unsigned)38); exit(2); #endif #if OSK writeln(2, "Environment variable TERM must be set\n", (unsigned)38); exit(2); #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(2); #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 # if UNIXV # ifdef TERMIOS tcgetattr(2, &oldtermio); # else ioctl(2, TCGETA, &oldtermio); # endif # else ioctl(2, TIOCGETP, &oldsgttyb); # endif #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; extern int oldcurs; /* Send any required termination strings. Turn off "raw" mode. */ void suspend_curses() { #if ANY_UNIX && !UNIXV struct tchars tbuf; # ifdef TIOCSLTC struct ltchars ltbuf; # endif #endif #ifndef NO_CURSORSHAPE if (has_CQ) { do_CQ(); oldcurs = 0; } #endif if (has_TE) /* GB */ { do_TE(); } #ifndef NO_COLOR quitcolor(); #endif refresh(); /* change the terminal mode back the way it was */ #if ANY_UNIX # if UNIXV # if TERMIOS tcsetattr(2, TCSADRAIN, &oldtermio); # else ioctl(2, TCSETAW, &oldtermio); # endif # else ioctl(2, TIOCSETP, &oldsgttyb); ioctl(2, TIOCGETC, (struct sgttyb *) &tbuf); tbuf.t_intrc = oldint; ioctl(2, TIOCSETC, (struct sgttyb *) &tbuf); # ifdef TIOCSLTC ioctl(2, TIOCGLTC, <buf); ltbuf.t_suspc = oldswitch; ltbuf.t_dsuspc = olddswitch; ltbuf.t_lnextc = oldquote; ioctl(2, TIOCSLTC, <buf); # endif # endif #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 # if UNIXV ospeed = (oldtermio.c_cflag & CBAUD); 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; # ifdef VSWTCH newtermio.c_cc[VSWTCH] = 0; # endif # ifdef VSUSP newtermio.c_cc[VSUSP] = 0; # endif # ifdef TERMIOS tcsetattr(2, TCSADRAIN, &newtermio); # else ioctl(2, TCSETAW, &newtermio); # endif # else /* BSD or V7 or Coherent or Minix */ struct tchars tbuf; # ifdef TIOCSLTC struct ltchars ltbuf; # endif ospeed = oldsgttyb.sg_ospeed; ERASEKEY = oldsgttyb.sg_erase; newsgttyb = oldsgttyb; newsgttyb.sg_flags |= CBREAK; newsgttyb.sg_flags &= ~(CRMOD|ECHO|XTABS); ioctl(2, TIOCSETP, &newsgttyb); ioctl(2, TIOCGETC, (struct sgttyb *) &tbuf); oldint = tbuf.t_intrc; tbuf.t_intrc = ctrl('C'); /* always use ^C for interrupts */ ioctl(2, TIOCSETC, (struct sgttyb *) &tbuf); # ifdef TIOCSLTC ioctl(2, TIOCGLTC, <buf); oldswitch = ltbuf.t_suspc; ltbuf.t_suspc = 0; /* disable ^Z for elvis */ olddswitch = ltbuf.t_dsuspc; ltbuf.t_dsuspc = 0; /* disable ^Y for elvis */ oldquote = ltbuf.t_lnextc; ltbuf.t_lnextc = 0; /* disable ^V for elvis */ ioctl(2, TIOCSLTC, <buf); # endif # endif #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 as <^H> for VMS */ #endif curses_active = TRUE; } /* If we're supposed to quit quietly, then we're done */ if (quietly) { if (has_TI) /* GB */ { do_TI(); } return; } signal(SIGINT, SIG_IGN); move(LINES - 1, 0); do_SO(); #if VMS qaddstr("\n[Press to continue]"); #else qaddstr("[Press to continue]"); #endif do_SE(); refresh(); ttyread(kbuf, 20, 0); /* in RAW mode, so <20 is very likely */ if (has_TI) { do_TI(); } if (kbuf[0] == ':') { mode = MODE_COLON; addch('\n'); refresh(); } else { mode = MODE_VI; redraw(MARK_UNSET, FALSE); } exwrote = FALSE; #if TURBOC || __GNUC__ 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(2); } } /* 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 */ mayhave(&KU, "ku"); /* up */ mayhave(&KD, "kd"); /* down */ mayhave(&KL, "kl"); /* left */ mayhave(&KR, "kr"); /* right */ if (KR && KR[0]=='\b' && !KR[1]) { /* never use '\b' as a right arrow! */ KR = (char *)0; } 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 } #if MINT extern int __mint; int got_winch; #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. */ int getsize(signo) int signo; { int lines; int cols; #ifdef TIOCGWINSZ struct winsize size; #endif #ifdef SIGWINCH /* reset the signal vector */ # if __GNUC__ signal(SIGWINCH, (void(*)()) getsize); # else signal(SIGWINCH, getsize); # endif #endif /* get the window size, one way or another. */ lines = cols = 0; #ifdef TIOCGWINSZ # if !MINT if (ioctl(2, TIOCGWINSZ, &size) >= 0) # else if (signo) got_winch = 1; /* only MiNT versions >= 0.9 know TIOCGWINSZ; for older versions and when running under vanilla TOS mntlib would return the settings of the ST BIOS screeen driver, and that at least doesn't help when we're not running on the console. -nox */ if (__mint >= 9 && ioctl(2, TIOCGWINSZ, &size) >= 0) # endif { 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 && cols >= 30) { LINES = lines; 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 return 0; } /* 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 . */ 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. */ int 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 */