📄 tio.c
字号:
/* tio.c *//* Author: * Steve Kirkendall * 14407 SW Teal Blvd. #C * Beaverton, OR 97005 * kirkenda@cs.pdx.edu *//* This file contains terminal I/O functions */#include "config.h"#include "vi.h"#include "ctype.h"/* This function reads in a line from the terminal. */int vgets(prompt, buf, bsize) char prompt; /* the prompt character, or '\0' for none */ char *buf; /* buffer into which the string is read */ int bsize; /* size of the buffer */{ int len; /* how much we've read so far */ int ch; /* a character from the user */ int quoted; /* is the next char quoted? */ int tab; /* column position of cursor */ char widths[132]; /* widths of characters */ int word; /* index of first letter of word */#ifndef NO_DIGRAPH int erased; /* 0, or first char of a digraph */#endif /* show the prompt */ move(LINES - 1, 0); tab = 0; if (prompt) { addch(prompt); tab = 1; } clrtoeol(); refresh(); /* read in the line */#ifndef NO_DIGRAPH erased =#endif quoted = len = 0; for (;;) {#ifndef NO_ABBR if (quoted || mode == MODE_EX) { ch = getkey(0); } else { /* maybe expand an abbreviation while getting key */ for (word = len; --word >= 0 && isalnum(buf[word]); ) { } word++; ch = getabkey(WHEN_EX, &buf[word], len - word); }#else ch = getkey(0);#endif#ifndef NO_EXTENSIONS if (ch == ctrl('O')) { ch = getkey(quoted ? 0 : WHEN_EX); }#endif /* some special conversions */ if (ch == ctrl('D') && len == 0) ch = ctrl('[');#ifndef NO_DIGRAPH if (*o_digraph && erased != 0 && ch != '\b') { ch = digraph(erased, ch); erased = 0; }#endif /* inhibit detection of special chars (except ^J) after a ^V */ if (quoted && ch != '\n') { ch |= 256; } /* process the character */ switch(ch) { case ctrl('V'): qaddch('^'); qaddch('\b'); quoted = TRUE; break; case ctrl('['): return -1; case '\n':#if OSK case '\l':#else case '\r':#endif clrtoeol(); goto BreakBreak; case '\b': if (len > 0) { len--;#ifndef NO_DIGRAPH erased = buf[len];#endif for (ch = widths[len]; ch > 0; ch--) addch('\b'); if (mode == MODE_EX) { clrtoeol(); } tab -= widths[len]; } else { return -1; } break; default: /* strip off quotation bit */ if (ch & 256) { ch &= ~256; qaddch(' '); qaddch('\b'); } /* add & echo the char */ if (len < bsize - 1) { if (ch == '\t' && !quoted) { widths[len] = *o_tabstop - (tab % *o_tabstop); addstr(" " + 8 - widths[len]); tab += widths[len]; } else if (ch > 0 && ch < ' ') /* > 0 by GB */ { addch('^'); addch(ch + '@'); widths[len] = 2; tab += 2; } else if (ch == '\177') { addch('^'); addch('?'); widths[len] = 2; tab += 2; } else { addch(ch); widths[len] = 1; tab++; } buf[len++] = ch; } else { beep(); } quoted = FALSE; } }BreakBreak: refresh(); buf[len] = '\0'; return len;}static int manymsgs; /* This variable keeps msgs from overwriting each other */static char pmsg[80]; /* previous message (waiting to be displayed) */static int showmsg(){ /* if there is no message to show, then don't */ if (!manymsgs) return FALSE; /* display the message */ move(LINES - 1, 0); if (*pmsg) { standout(); qaddch(' '); qaddstr(pmsg); qaddch(' '); standend(); } clrtoeol(); manymsgs = FALSE; return TRUE;}void endmsgs(){ if (manymsgs) { showmsg(); addch('\n'); }}/* Write a message in an appropriate way. This should really be a varargs * function, but there is no such thing as vwprintw. Hack!!! * * In MODE_EX or MODE_COLON, the message is written immediately, with a * newline at the end. * * In MODE_VI, the message is stored in a character buffer. It is not * displayed until getkey() is called. msg() will call getkey() itself, * if necessary, to prevent messages from being lost. * * msg("") - clears the message line * msg("%s %d", ...) - does a printf onto the message line *//*VARARGS1*/void msg(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7) char *fmt; long arg1, arg2, arg3, arg4, arg5, arg6, arg7;{ if (mode != MODE_VI) { sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7); qaddstr(pmsg); addch('\n'); exrefresh(); } else { /* wait for keypress between consecutive msgs */ if (manymsgs) { getkey(WHEN_MSG); } /* real message */ sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7); if (*fmt) { manymsgs = TRUE; } }}/* This function calls refresh() if the option exrefresh is set */void exrefresh(){ char *scan; /* If this ex command wrote ANYTHING set exwrote so vi's : command * can tell that it must wait for a user keystroke before redrawing. */ for (scan=kbuf; scan<stdscr; scan++) if (*scan == '\n') exwrote = TRUE; /* now we do the refresh thing */ if (*o_exrefresh) { refresh(); } else { wqrefresh(); } if (mode != MODE_VI) { manymsgs = FALSE; }}/* This structure is used to store maps and abbreviations. The distinction * between them is that maps are stored in the list referenced by the "maps" * pointer, while abbreviations are referenced by the "abbrs" pointer. */typedef struct _map{ struct _map *next; /* another abbreviation */ short len; /* length of the "rawin" characters */ short flags; /* various flags */ char *label; /* label of the map/abbr, or NULL */ char *rawin; /* the "rawin" characters */ char *cooked;/* the "cooked" characters */} MAP;static char keybuf[KEYBUFSIZE];static int cend; /* end of input characters */static int user; /* from user through end are chars typed by user */static int next; /* index of the next character to be returned */static MAP *match; /* the matching map, found by countmatch() */static MAP *maps; /* the map table */#ifndef NO_ABBRstatic MAP *abbrs; /* the abbreviation table */#endif/* ring the terminal's bell */void beep(){ /* do a visible/audible bell */ if (*o_flash) { do_VB(); refresh(); } else if (*o_errorbells) { ttywrite("\007", 1); } /* discard any buffered input, and abort macros */ next = user = cend;}/* This function replaces a "rawin" character sequence with the "cooked" version, * by modifying the internal type-ahead buffer. */void execmap(rawlen, cookedstr, visual) int rawlen; /* length of rawin text -- string to delete */ char *cookedstr; /* the cooked text -- string to insert */ int visual; /* boolean -- chars to be executed in visual mode? */{ int cookedlen; char *src, *dst; int i; /* find the length of the cooked string */ cookedlen = strlen(cookedstr);#ifndef NO_EXTENSIONS if (visual) { cookedlen *= 2; }#endif /* if too big to fit in type-ahead buffer, then don't do it */ if (cookedlen + (cend - next) - rawlen > KEYBUFSIZE) { return; } /* shift to make room for cookedstr at the front of keybuf */ src = &keybuf[next + rawlen]; dst = &keybuf[cookedlen]; i = cend - (next + rawlen); if (src >= dst) { while (i-- > 0) { *dst++ = *src++; } } else { src += i; dst += i; while (i-- > 0) { *--dst = *--src; } } /* insert cookedstr, and adjust offsets */ cend += cookedlen - rawlen - next; user += cookedlen - rawlen - next; next = 0; for (dst = keybuf, src = cookedstr; *src; ) {#ifndef NO_EXTENSIONS if (visual) { *dst++ = ctrl('O'); cookedlen--; }#endif *dst++ = *src++; }#ifdef DEBUG2 {#include <stdio.h> FILE *debout; int i; debout = fopen("debug.out", "a"); fprintf(debout, "After execmap(%d, \"%s\", %d)...\n", rawlen, cookedstr, visual); for (i = 0; i < cend; i++) { if (i == next) fprintf(debout, "(next)"); if (i == user) fprintf(debout, "(user)"); if (UCHAR(keybuf[i]) < ' ') fprintf(debout, "^%c", keybuf[i] ^ '@'); else fprintf(debout, "%c", keybuf[i]); } fprintf(debout, "(end)\n"); fclose(debout); }#endif}/* This function calls ttyread(). If necessary, it will also redraw the screen, * change the cursor shape, display the mode, and update the ruler. If the * number of characters read is 0, and we didn't time-out, then it exits because * we've apparently reached the end of an EX script. */static int fillkeybuf(when, timeout) int when; /* mixture of WHEN_XXX flags */ int timeout;/* timeout in 1/10 second increments, or 0 */{ int nkeys;#ifndef NO_SHOWMODE static int oldwhen; /* "when" from last time */ static int oldleft; static long oldtop; static long oldnlines; char *str;#endif#ifndef NO_CURSORSHAPE static int oldcurs;#endif#ifdef DEBUG watch();#endif#ifndef NO_CURSORSHAPE /* make sure the cursor is the right shape */ if (has_CQ) { if (when != oldcurs) { switch (when) { case WHEN_EX: do_CX(); break; case WHEN_VICMD: do_CV(); break; case WHEN_VIINP: do_CI(); break; case WHEN_VIREP: do_CR(); break; } oldcurs = when; } }#endif#ifndef NO_SHOWMODE /* if "showmode" then say which mode we're in */ if (*o_smd && (when & WHENMASK)) { /* redraw the screen before we check to see whether the * "showmode" message needs to be redrawn. */ redraw(cursor, !(when & WHEN_VICMD)); /* now the "topline" test should be valid */ if (when != oldwhen || topline != oldtop || leftcol != oldleft || nlines != oldnlines) { oldwhen = when; oldtop = topline; oldleft = leftcol; oldnlines = nlines; if (when & WHEN_VICMD) str = "Command"; else if (when & WHEN_VIINP) str = " Input "; else if (when & WHEN_VIREP) str = "Replace"; else if (when & WHEN_REP1) str = " Rep 1 "; else if (when & WHEN_CUT) str = "BufName"; else if (when & WHEN_MARK) str = "Mark AZ"; else if (when & WHEN_CHAR) str = "Dest Ch"; else str = (char *)0; if (str) { move(LINES - 1, COLS - 10); standout(); qaddstr(str); standend(); } } }#endif#ifndef NO_EXTENSIONS /* maybe display the ruler */ if (*o_ruler && (when & (WHEN_VICMD|WHEN_VIINP|WHEN_VIREP))) { char buf[20];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -