📄 curses.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 VMSextern int VMS_read_raw; /* Set in initscr() */#endifextern 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 OSKchar PC_; /* Pad char */char *BC; /* backspace character string */#elsechar PC; /* Pad char */#endifWINDOW *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_VISIBLEchar *MV; /* :mv=: "visible" selection start */#endifchar *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 OSKchar *SR_; /* :sr=: scroll reverse */#elsechar *SR; /* :sr=: scroll reverse */#endifchar *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_FKEYchar *FKEY[NFKEYS]; /* :k0=: ... :k9=: sequences sent by function keys */#endifchar *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 1char *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 */#elsechar *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#endifchar *aend = ""; /* end an attribute -- either UE or ME */char ERASEKEY; /* backspace key taken from ioctl structure */#ifndef NO_COLORchar 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_POPUPchar POPUPcolor[16];# endif# ifndef NO_VISIBLEchar VISIBLEcolor[16];# endif#endif#if ANY_UNIXstatic struct termios oldtermio; /* original tty mode */static struct termios newtermio; /* cbreak/noecho tty mode */#endif#if OSKstatic struct sgbuf oldsgttyb; /* orginal tty mode */static struct sgbuf newsgttyb; /* noecho tty mode */#endifstatic 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -