sh.edit.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 3,065 行 · 第 1/4 页
C
3,065 行
vadone: *gcursor = 0; Outchar = OO; return (gcursor);}/* * Update line. Output the line from cp to eol. */updateline(cp) register char *cp;{ for (; *cp; ) exputchar(*cp++);}junk(c) register int c;{ if (c >= ' ' && c != DELETE) return (0); switch (c) { case '\t': case '\n': case '\f': return (0); default: return (1); }}/* * Vmaxrep determines the maximum repetitition factor * allowed that will yield total line length less than * LBSIZE characters. */vmaxrep(ch, cnt) char ch; register int cnt;{ register int len, replen; if (cnt > LBSIZE - 2) cnt = LBSIZE - 2; replen = strlen(genbuf); len = strlen(linebuf); if (len + cnt * replen <= LBSIZE - 2) return (cnt); cnt = (LBSIZE - 2 - len) / replen; if (cnt == 0) { error("Line too long"); } return (cnt);}/* * Clear to the end of the current physical line */vclreol(){ register int i; int col; if (CE) { col = destcol; vgoto(destcol,0); vputp(CE, 1); if (UP) { for (i = col/COLUMNS +1; i <= markline; i++) { vgoto(0,i); vputp(CE, 1); } markline = strlen(linebuf)/COLUMNS; } return; } /* * No clear to end of line capability, so * calculate the number of blanks needed and put them out. */ vgoto(destcol,0); for (i = markeol - strend(linebuf); i > 0; i--) { exputchar(' '); } markeol = strend(linebuf);}/* * Gather up some more text from an insert. * If the insertion buffer oveflows, then destroy * the repeatability of the insert. */addtext(cp) char *cp;{ if (vglobp) return; addto(INS, cp); if (INS[0] == NULL) lastcmd[0] = 0;}/* * Put text from cursor upto wcursor in BUF. * Used to put back deletes. */setBUF(BUF) register char *BUF;{ register int c; register char *wp = wcursor; c = *wp; *wp = 0; BUF[0] = 0; addto(BUF, cursor); *wp = c;}addto(buf, str) register char *buf, *str;{ if (strlen(buf) + strlen(str) + 1 >= VBSIZE) { buf[0] = NULL; return; } (void)strcat(buf, str);}/* * A complete command has been defined for * the purposes of repeat, so copy it from * the working to the previous command buffer. */setLAST(){ if (vglobp || vmacp) return; lasthad = Xhadcnt; lastcnt = Xcnt; *lastcp = 0; CP(lastcmd, workcmd);}Copy(to, from, size) register char *from, *to; register int size;{ if (size > 0) do *to++ = *from++; while (--size > 0);}/* * Find matching paren-like items: ({[ ]}). */lmatchp(){ register int i; register char *parens, *cp; for (cp = cursor; !any(*cp, "({[)}]");) if (*cp++ == 0) return (0); parens = any(*cp, "()") ? "()" : any(*cp, "[]") ? "[]" : "{}"; if (*cp == parens[1]) { dir = -1; } else { dir = 1; } wcursor = cp; i = lskipbal(parens); return (i);}/* * Find the matching paren-like object */lskipbal(parens) register char *parens;{ register int level = dir; register int c; do { if (!lnext()) { return (0); } c = *wcursor; if (c == parens[1]) level--; else if (c == parens[0]) level++; } while (level); return (1);}/************************************************************* * Input routines. *************************************************************//* * Return the key. */ungetkey(c) int c;{ if (Peekkey != ATTN) Peekkey = c;}/* * Return a keystroke, but never a ^@. */getkey(){ register int c; do { c = getbr(); if (c==0) beep(); } while (c == 0); return (c);}jmp_buf readbuf;int doingread = 0;/* * Get a keystroke, including a ^@. * If a key was returned with ungetkey, that * comes back first. Next comes unread input (e.g. * from repeating commands with .), and finally new * keystrokes. */getbr(){ char ch; register int c;#define BEEHIVE#ifdef BEEHIVE static char Peek2key;#endifgetATTN: if (Peekkey) { c = Peekkey; Peekkey = 0; return (c); }#ifdef BEEHIVE if (Peek2key) { c = Peek2key; Peek2key = 0; return (c); }#endif if (vglobp) { if (*vglobp) return (lastvgk = *vglobp++); lastvgk = 0; return (ESCAPE); } if (vmacp) { if (*vmacp) return(*vmacp++); /* End of a macro or set of nested macros */ vmacp = 0; } flusho(); if (setjmp(readbuf)) goto getATTN; doingread = 1; c = read(SHIN, &ch, 1); doingread = 0; if (c != 1) { if (errno == EINTR) goto getATTN; error("Input read error"); } c = ch & (QUOTE|TRIM);#ifdef BEEHIVE if (XB && c == ESCAPE) { if (read(SHIN, &Peek2key, 1) != 1) goto getATTN; Peek2key &= (QUOTE|TRIM); switch (Peek2key) { case 'C': /* SPOW mode sometimes sends \EC for space */ c = ' '; Peek2key = 0; break; case 'q': /* f2 -> ^C */ c = CTRL(c); Peek2key = 0; break; case 'p': /* f1 -> esc */ Peek2key = 0; break; } }#endif lastvgk = 0; return (c);}/* * Get a key, but if a delete, quit or attention * is typed return 0 so we will abort a partial command. */getesc(){ register int c; c = getkey(); switch (c) { case CTRL(v): case CTRL(q): c = getkey(); return (c); case ATTN: case QUIT: ungetkey(c); return (0); case ESCAPE: return (0); } return (c);}/* * Peek at the next keystroke. */peekkey(){ Peekkey = getkey(); return (Peekkey);}/* * Get a count from the keyed input stream. * A zero count is indistinguishable from no count. */vgetcnt(){ register int c, cnt; cnt = 0; for (;;) { c = getkey(); if (!isdigit(c)) break; cnt *= 10, cnt += c - '0'; } ungetkey(c); Xhadcnt = 1; Xcnt = cnt; return(cnt);}/* * fastpeekkey is just like peekkey but insists the character come in * fast (within 1 second). This will succeed if it is the 2nd char of * a machine generated sequence (such as a function pad from an escape * flavor terminal) but fail for a human hitting escape then waiting. */fastpeekkey(){ int trapalarm(); int (*Oint)(); register int c; /* * We force this to die in 1 second. * This is pretty reliable (VMUNIX rounds it to .5 - 1.5 secs, * but due to system delays * there are times when arrow keys or very fast typing get counted * as separate. */ Oint = (int (*)())signal(SIGINT, trapalarm); signal(SIGALRM, trapalarm); alarm(1); CATCH c = peekkey(); alarm(0); ONERR c = 0; ENDCATCH signal(SIGINT,Oint); return(c);}trapalarm() { alarm(0); if (vcatch) longjmp(vreslab,1);}/************************************************************* * Terminal output and line formatting routines. *************************************************************//* * Format c for printing. Handle funnies of upper case terminals * and crocky hazeltines which don't have ~. */normchar(c) register short c;{ register char *colp; c &= (QUOTE|TRIM); if (c == '~' && HZ) { normchar('\\'); c = '^'; } if (c < ' ' && (c != '\b') || c == DELETE) c = ' '; else if (UPPERCASE) if (isupper(c)) { outchar('\\'); c = tolower(c); } else { colp = "({)}!|^~'`"; while (*colp++) if (c == *colp++) { outchar('\\'); c = colp[-2]; break; } } outchar(c);}/* * Normal line output, no numbering. */normline(){ register char *cp; for (cp = linebuf; *cp;) exputchar(*cp++);}/* * The output buffer is initialized with a useful error * message so we don't have to keep it in data space. */static char linb[66];char *exlinp = linb;/* * Indirect to current definition of putchar. */exputchar(c) int c;{ (*Putchar)(c);}exflush(){ flush1(); flush2();}/* * Flush from small line buffer into output buffer. * Work here is destroying motion into positions, and then * letting fgoto do the optimized motion. */flush1(){ register char *lp; register short c; *exlinp = 0; lp = linb; while (*lp) switch (c = *lp++) { case '\r': destcol = 0; continue; case '\b': if (destcol) destcol--; continue; case '\t': case ' ': destcol++; continue; case '\n': destcol = 0; continue; default: fgoto(); for (;;) { if (AM == 0 && outcol == COLUMNS) fgoto(); c &= (QUOTE|TRIM); putch(c); if (c == '\b') { outcol--; destcol--; } else if (c >= ' ' && c != DELETE) { outcol++; destcol++; if (outcol % COLUMNS == 0) putch('\r'), putch('\n'); } c = *lp++; if (c <= ' ') break; } --lp; continue; } exlinp = linb;}flush2(){ fgoto(); flusho();}char *obp = obuf;flusho(){ if (obp != obuf) { write(SHOUT, obuf, obp - obuf); obp = obuf; }}putch(c) int c;{ *obp++ = c & (QUOTE|TRIM); if (obp >= &obuf[sizeof obuf]) flusho();}/* * Put with padding */putpad(cp) char *cp;{ exflush(); tputs(cp, 0, putch);}/* * Insert character c at current cursor position. */vinschar(c) int c;{ vputchar(c);}/* * Put the character c on the screen at the current cursor position. */vputchar(c) register int c;{ c &= (QUOTE|TRIM); if (destcol >= COLUMNS) { if (UP) { destline += destcol / COLUMNS; destcol %= COLUMNS; } else destcol = COLUMNS - 1; } switch (c) { case '\t': c = ' '; /* fall into ... */ default: if (outcol != destcol) vgoto(destcol,destline); vputc(c); destcol++, outcol++; }}/* * Put a character */vputch(c) int c;{ vputc(c);}/************************************************************* * Cursor Motion Routines *************************************************************/vmove(){ vsetcurs(wcursor);}/* * Compute the column position implied by the cursor at ``nc'', * and move the cursor there. */vsetcurs(nc) register char *nc;{ register int col; col = column(nc); vgoto(col,0); cursor = nc;}column(cp) char *cp;{ return(cp - linebuf);}/* * Move cursor to column x. */vgoto(x,y) register int x,y;{ /* * Fold the possibly too large value of x. */ if (x >= COLUMNS) { if (UP) { y += x / COLUMNS; x %= COLUMNS; } else x = COLUMNS - 1; } destcol = x; destline = y; fgoto();}/* * Sync the position of the output cursor. */fgoto(){ if (destcol >= COLUMNS) { if (UP) { destline += destcol /COLUMNS; destcol %= COLUMNS; } else destcol = COLUMNS - 1; } plod(0); outcol = destcol; outline = destline;}/* * Move (slowly) to destination. * Just use character printing (move right), and backspace (move left). */static int plodcnt, plodflg;plodput(c){ if (plodflg) plodcnt--; else putch(c);}plod(cnt){ register int c; register int index; plodcnt = plodflg = cnt; /* * Move down, if necessary, to desired line */ if ((outline < destline) && UP) { plodput('\r'); outcol = 0; while (outline < destline) { plodput('\n'); outline++; } } /* * Move up, if necessary, to desired line */ while (outline > destline) { outline--; tputs(UP,0,plodput); } /* * Move left, if necessary, to desired column */ while (outcol > destcol) { if (plodcnt < 0) goto out; outcol--; if (BC) tputs(BC, 0, plodput); else plodput('\b'); } /* * Now move to the right, if necessary. */ index = outcol + outline * COLUMNS; while (outcol < destcol) { /* * Move one char to the right. We only use ND space * if repositioning the cursor during insert and we can * have more than 80 chars (tty has upline (UP) capability). * Otherwise it's faster to just print the char we are * moving over. There are various exceptions, however. * If the char is a null or a tab we want to print a space. * Other random chars we use space for instead, too. */ if ( (c=linebuf[index]) < ' ') c = ' '; if (insmode && UP && ND) tputs(ND, 0, plodput); else plodput(c); index++; outcol++; if (plodcnt < 0) break; }out: return(plodcnt);}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?