diff options
Diffstat (limited to 'tree/src/vi/ex-070224/ex_vmain.c')
| -rw-r--r-- | tree/src/vi/ex-070224/ex_vmain.c | 1460 |
1 files changed, 0 insertions, 1460 deletions
diff --git a/tree/src/vi/ex-070224/ex_vmain.c b/tree/src/vi/ex-070224/ex_vmain.c deleted file mode 100644 index 8bdfa3f..0000000 --- a/tree/src/vi/ex-070224/ex_vmain.c +++ /dev/null @@ -1,1460 +0,0 @@ -/* - * This code contains changes by - * Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved. - * - * Conditions 1, 2, and 4 and the no-warranty notice below apply - * to these changes. - * - * - * Copyright (c) 1980, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * Redistributions of source code and documentation must retain the - * above copyright notice, this list of conditions and the following - * disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed or owned by Caldera - * International, Inc. - * Neither the name of Caldera International, Inc. nor the names of - * other contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA - * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE - * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef lint -#ifdef DOSCCS -static char sccsid[] = "@(#)ex_vmain.c 1.34 (gritter) 8/6/05"; -#endif -#endif - -/* from ex_vmain.c 7.7 (Berkeley) 6/7/85 */ - -#include "ex.h" -#include "ex_tty.h" -#include "ex_vis.h" - -/* - * This is the main routine for visual. - * We here decode the count and possible named buffer specification - * preceding a command and interpret a few of the commands. - * Commands which involve a target (i.e. an operator) are decoded - * in the routine operate in ex_voperate.c. - */ - -#define forbid(a) { if (a) goto fonfon; } - -void -vmain(void) -{ - int c, cnt, i; - cell esave[TUBECOLS]; - char *oglobp; - short d; - line *addr, *odot; - int ind, nlput; - int shouldpo = 0; - int onumber = 0, olist = 0; - int (*OPline)(int, int) = NULL; - int (*OPutchar)(int) = NULL; - - CLOBBGRD(c); - CLOBBGRD(cnt); - CLOBBGRD(i); - CLOBBGRD(oglobp); - CLOBBGRD(addr); - CLOBBGRD(shouldpo); - CLOBBGRD(onumber); - CLOBBGRD(olist); - CLOBBGRD(OPline); - CLOBBGRD(OPutchar); - - vch_mac = VC_NOTINMAC; - - /* - * If we started as a vi command (on the command line) - * then go process initial commands (recover, next or tag). - */ - if (initev) { - oglobp = globp; - globp = initev; - hadcnt = cnt = 0; - i = tchng; - addr = dot; - goto doinit; - } - - /* - * NB: - * - * The current line is always in the line buffer linebuf, - * and the cursor at the position cursor. You should do - * a vsave() before moving off the line to make sure the disk - * copy is updated if it has changed, and a getDOT() to get - * the line back if you mung linebuf. The motion - * routines in ex_vwind.c handle most of this. - */ - for (;;) { - /* - * Decode a visual command. - * First sync the temp file if there has been a reasonable - * amount of change. Clear state for decoding of next - * command. - */ - TSYNC(); - vglobp = 0; - vreg = 0; - hold = 0; - seenprompt = 1; - wcursor = 0; - Xhadcnt = hadcnt = 0; - Xcnt = cnt = 1; - splitw = 0; - if (i = holdupd) { - if (state == VISUAL) - ignore(peekkey()); - holdupd = 0; -/* - if (LINE(0) < ZERO) { - vclear(); - vcnt = 0; - i = 3; - } -*/ - if (state != VISUAL) { - vcnt = 0; - vsave(); - vrepaint(cursor); - } else if (i == 3) - vredraw(WTOP); - else - vsync(WTOP); - vfixcurs(); - } - - /* - * Gobble up counts and named buffer specifications. - */ - for (;;) { -looptop: -#ifdef MDEBUG - if (trace) - fprintf(trace, "pc=%c",peekkey()); -#endif - if (xisdigit(peekkey()) && peekkey() != '0') { - hadcnt = 1; - cnt = vgetcnt(); - forbid (cnt <= 0); - } - if (peekkey() != '"') - break; - ignore(getkey()), c = getkey(); - /* - * Buffer names be letters or digits. - * But not '0' as that is the source of - * an 'empty' named buffer spec in the routine - * kshift (see ex_temp.c). - */ - forbid (c == '0' || !xisalpha(c) && !xisdigit(c)); - vreg = c; - } -reread: - /* - * Come to reread from below after some macro expansions. - * The call to map allows use of function key pads - * by performing a terminal dependent mapping of inputs. - */ -#ifdef MDEBUG - if (trace) - fprintf(trace,"pcb=%c,",peekkey()); -#endif - op = getkey(); - maphopcnt = 0; - do { - /* - * Keep mapping the char as long as it changes. - * This allows for double mappings, e.g., q to #, - * #1 to something else. - */ - c = op; - op = map(c,arrows); -#ifdef MDEBUG - if (trace) - fprintf(trace,"pca=%c,",c); -#endif - /* - * Maybe the mapped to char is a count. If so, we have - * to go back to the "for" to interpret it. Likewise - * for a buffer name. - */ - if ((xisdigit(c) && c!='0') || c == '"') { - ungetkey(c); - goto looptop; - } - if (!value(REMAP)) { - c = op; - break; - } - if (++maphopcnt > 256) - error(catgets(catd, 1, 225, - "Infinite macro loop")); - } while (c != op); - - /* - * Begin to build an image of this command for possible - * later repeat in the buffer workcmd. It will be copied - * to lastcmd by the routine setLAST - * if/when completely specified. - */ - lastcp = workcmd; - if (!vglobp) - *lastcp++ = c; - - /* - * First level command decode. - */ - if (c == ATTN) - goto case_ATTN; - switch (c) { - - /* - * ^L Clear screen e.g. after transmission error. - */ - - /* - * ^R Retype screen, getting rid of @ lines. - * If in open, equivalent to ^L. - * On terminals where the right arrow key sends - * ^L we make ^R act like ^L, since there is no - * way to get ^L. These terminals (adm31, tvi) - * are intelligent so ^R is useless. Soroc - * will probably foul this up, but nobody has - * one of them. - */ - case CTRL('l'): - case CTRL('r'): - if (c == CTRL('l') || (KR && *KR==CTRL('l'))) { - vclear(); - vdirty(0, vcnt); - } - if (state != VISUAL) { - /* - * Get a clean line, throw away the - * memory of what is displayed now, - * and move back onto the current line. - */ - vclean(); - vcnt = 0; - vmoveto(dot, cursor, 0); - continue; - } - vredraw(WTOP); - /* - * Weird glitch -- when we enter visual - * in a very small window we may end up with - * no lines on the screen because the line - * at the top is too long. This forces the screen - * to be expanded to make room for it (after - * we have printed @'s ick showing we goofed). - */ - if (vcnt == 0) - vrepaint(cursor); - vfixcurs(); - continue; - - /* - * $ Escape just cancels the current command - * with a little feedback. - */ - case ESCAPE: - beep(); - continue; - - /* - * @ Macros. Bring in the macro and put it - * in vmacbuf, point vglobp there and punt. - */ - case '@': - c = getesc(); - if (c == 0) - continue; - if (c == '@') - c = lastmac; - if (xisupper(c)) - c = xtolower(c); - forbid(!xislower(c)); - lastmac = c; - vsave(); - CATCH - char tmpbuf[BUFSIZ]; - - regbuf(c,tmpbuf,sizeof(vmacbuf)); - macpush(tmpbuf, 1); - ONERR - lastmac = 0; - splitw = 0; - getDOT(); - vrepaint(cursor); - continue; - ENDCATCH - vmacp = vmacbuf; - goto reread; - - /* - * . Repeat the last (modifying) open/visual command. - */ - case '.': - /* - * Check that there was a last command, and - * take its count and named buffer unless they - * were given anew. Special case if last command - * referenced a numeric named buffer -- increment - * the number and go to a named buffer again. - * This allows a sequence like "1pu.u.u... - * to successively look for stuff in the kill chain - * much as one does in EMACS with C-Y and M-Y. - */ - forbid (lastcmd[0] == 0); - if (hadcnt) - lastcnt = cnt; - if (vreg) - lastreg = vreg; - else if (xisdigit(lastreg) && lastreg < '9') - lastreg++; - vreg = lastreg; - cnt = lastcnt; - hadcnt = lasthad; - vglobp = lastcmd; - goto reread; - - /* - * ^U Scroll up. A count sticks around for - * future scrolls as the scroll amount. - * Attempt to hold the indentation from the - * top of the screen (in logical lines). - * - * BUG: A ^U near the bottom of the screen - * on a dumb terminal (which can't roll back) - * causes the screen to be cleared and then - * redrawn almost as it was. In this case - * one should simply move the cursor. - */ - case CTRL('u'): - if (hadcnt) - vSCROLL = cnt; - cnt = vSCROLL; - if (state == VISUAL) - ind = vcline, cnt += ind; - else - ind = 0; - vmoving = 0; - vup(cnt, ind, 1); - vnline(NOSTR); - continue; - - /* - * ^D Scroll down. Like scroll up. - */ - case CTRL('d'): -#ifdef TRACE - if (trace) - fprintf(trace, "before vdown in ^D, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol)); -#endif - if (hadcnt) - vSCROLL = cnt; - cnt = vSCROLL; - if (state == VISUAL) - ind = vcnt - vcline - 1, cnt += ind; - else - ind = 0; - vmoving = 0; - vdown(cnt, ind, 1); -#ifdef TRACE - if (trace) - fprintf(trace, "before vnline in ^D, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol)); -#endif - vnline(NOSTR); -#ifdef TRACE - if (trace) - fprintf(trace, "after vnline in ^D, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol)); -#endif - continue; - - /* - * ^E Glitch the screen down (one) line. - * Cursor left on same line in file. - */ - case CTRL('e'): - if (state != VISUAL) - continue; - if (!hadcnt) - cnt = 1; - /* Bottom line of file already on screen */ - forbid(lineDOL()-lineDOT() <= vcnt-1-vcline); - ind = vcnt - vcline - 1 + cnt; - vdown(ind, ind, 1); - vnline(cursor); - continue; - - /* - * ^Y Like ^E but up - */ - case CTRL('y'): - if (state != VISUAL) - continue; - if (!hadcnt) - cnt = 1; - forbid(lineDOT()-1<=vcline); /* line 1 already there */ - ind = vcline + cnt; - vup(ind, ind, 1); - vnline(cursor); - continue; - - - /* - * m Mark position in mark register given - * by following letter. Return is - * accomplished via ' or `; former - * to beginning of line where mark - * was set, latter to column where marked. - */ - case 'm': - /* - * Getesc is generally used when a character - * is read as a latter part of a command - * to allow one to hit rubout/escape to cancel - * what you have typed so far. These characters - * are mapped to 0 by the subroutine. - */ - c = getesc(); - if (c == 0) - continue; - - /* - * Markreg checks that argument is a letter - * and also maps ' and ` to the end of the range - * to allow '' or `` to reference the previous - * context mark. - */ - c = markreg(c); - forbid (c == 0); - vsave(); - names[c - 'a'] = (*dot &~ 01); - ncols[c - 'a'] = cursor; - anymarks = 1; - continue; - - /* - * ^F Window forwards, with 2 lines of continuity. - * Count repeats. - */ - case CTRL('f'): - vsave(); - if (vcnt > 2) { - addr = dot + (vcnt - vcline) - 2 + (cnt-1)*basWLINES; - forbid(addr > dol); - dot = (line*)addr; - vcnt = vcline = 0; - } - vzop(0, 0, '+'); - continue; - - /* - * ^B Window backwards, with 2 lines of continuity. - * Inverse of ^F. - */ - case CTRL('b'): - vsave(); - odot = dot; - if (one + vcline != dot && vcnt > 2) { - addr = dot - vcline + 2 - (cnt-1)*basWLINES; - forbid (addr <= zero); - vcnt = vcline = 0; - do { - dot = addr; - vzop(0, 0, '^'); - /* - * When a single line fills the - * entire screen, ^B can become - * a no-op without the loop. - */ - } while (dot == odot && --addr > zero); - } else - vzop(0, 0, '^'); - continue; - - /* - * z Screen adjustment, taking a following character: - * z<CR> current line to top - * z<NL> like z<CR> - * z- current line to bottom - * also z+, z^ like ^F and ^B. - * A preceding count is line to use rather - * than current line. A count between z and - * specifier character changes the screen size - * for the redraw. - * - */ - case 'z': - if (state == VISUAL) { - i = vgetcnt(); - if (i > 0) - vsetsiz(i); - c = getesc(); - if (c == 0) - continue; - } - vsave(); - vzop(hadcnt, cnt, c); - continue; - - /* - * Y Yank lines, abbreviation for y_ or yy. - * Yanked lines can be put later if no - * changes intervene, or can be put in named - * buffers and put anytime in this session. - */ - case 'Y': - ungetkey('_'); - c = 'y'; - break; - - /* - * J Join lines, 2 by default. Count is number - * of lines to join (no join operator sorry.) - */ - case 'J': - forbid (dot == dol); - if (cnt == 1) - cnt = 2; - if (cnt > (i = dol - dot + 1)) - cnt = i; - vsave(); - vmacchng(1); - setLAST(); - cursor = strend(linebuf); - vremote(cnt, join, 0); - notenam = "join"; - vmoving = 0; - killU(); - vreplace(vcline, cnt, 1); - if (!*cursor && cursor > linebuf) - cursor += skipleft(linebuf, cursor); - if (notecnt == 2) - notecnt = 0; - vrepaint(cursor); - continue; - - /* - * S Substitute text for whole lines, abbrev for c_. - * Count is number of lines to change. - */ - case 'S': - ungetkey('_'); - c = 'c'; - break; - - /* - * O Create a new line above current and accept new - * input text, to an escape, there. - * A count specifies, for dumb terminals when - * slowopen is not set, the number of physical - * line space to open on the screen. - * - * o Like O, but opens lines below. - */ - case 'O': - case 'o': - vmacchng(1); - voOpen(c, cnt); - continue; - - /* - * C Change text to end of line, short for c$. - */ - case 'C': - if (*cursor) { - ungetkey('$'), c = 'c'; - break; - } - goto appnd; - - /* - * ~ Switch case of letter under cursor - */ - case '~': - vswitch(cnt); - continue; - - - /* - * A Append at end of line, short for $a. - */ - case 'A': - operate('$', 1); -appnd: - c = 'a'; - /* fall into ... */ - - /* - * a Appends text after cursor. Text can continue - * through arbitrary number of lines. - */ - case 'a': - if (*cursor) { - if (state == HARDOPEN) { - int c, n; - nextc(c, cursor, n); - putchar(c); - cursor += n; - } else - cursor += skipright(linebuf, cursor); - } - goto insrt; - - /* - * I Insert at beginning of whitespace of line, - * short for ^i. - */ - case 'I': - operate('^', 1); - c = 'i'; - /* fall into ... */ - - /* - * R Replace characters, one for one, by input - * (logically), like repeated r commands. - * - * BUG: This is like the typeover mode of many other - * editors, and is only rarely useful. Its - * implementation is a hack in a low level - * routine and it doesn't work very well, e.g. - * you can't move around within a R, etc. - */ - case 'R': - /* fall into... */ - - /* - * i Insert text to an escape in the buffer. - * Text is arbitrary. This command reminds of - * the i command in bare teco. - */ - case 'i': -insrt: - /* - * Common code for all the insertion commands. - * Save for redo, position cursor, prepare for append - * at command and in visual undo. Note that nothing - * is doomed, unless R when all is, and save the - * current line in a the undo temporary buffer. - */ - vmacchng(1); - setLAST(); - vcursat(cursor); - prepapp(); - vnoapp(); - doomed = c == 'R' ? 10000 : 0; - if(FIXUNDO) - vundkind = VCHNG; - vmoving = 0; - CP(vutmp, linebuf); - - /* - * If this is a repeated command, then suppress - * fake insert mode on dumb terminals which looks - * ridiculous and wastes lots of time even at 9600B. - */ - if (vglobp) - hold = HOLDQIK; - vappend(c, cnt, 0); - continue; - - /* - * ^? An attention, normally a ^?, just beeps. - * If you are a vi command within ex, then - * two ATTN's will drop you back to command mode. - */ -case_ATTN: - beep(); - if (initev || peekkey() != ATTN) - continue; - /* fall into... */ - - /* - * ^\ A quit always gets command mode. - */ - case QUIT: - /* - * Have to be careful if we were called - * g/xxx/vi - * since a return will just start up again. - * So we simulate an interrupt. - */ - if (inglobal) - onintr(SIGINT); - /* fall into... */ - -#ifdef notdef - /* - * q Quit back to command mode, unless called as - * vi on command line in which case dont do it - */ - case 'q': /* quit */ - if (initev) { - vsave(); - CATCH - error(catgets(catd, 1, 226, - "Q gets ex command mode, :q leaves vi")); - ENDCATCH - splitw = 0; - getDOT(); - vrepaint(cursor); - continue; - } -#endif - /* fall into... */ - - /* - * Q Is like q, but always gets to command mode - * even if command line invocation was as vi. - */ - case 'Q': - vsave(); - /* - * If we are in the middle of a macro, throw away - * the rest and fix up undo. - * This code copied from getbr(). - */ - if (vmacp) { - vmacp = 0; - if (inopen == -1) /* don't screw up undo for esc esc */ - vundkind = VMANY; - inopen = 1; /* restore old setting now that macro done */ - } - return; - - - /* - * ZZ Like :x - */ - case 'Z': - forbid(getkey() != 'Z'); - oglobp = globp; - globp = "x"; - vclrech(0); - goto gogo; - - /* - * P Put back text before cursor or before current - * line. If text was whole lines goes back - * as whole lines. If part of a single line - * or parts of whole lines splits up current - * line to form many new lines. - * May specify a named buffer, or the delete - * saving buffers 1-9. - * - * p Like P but after rather than before. - */ - case 'P': - case 'p': - vmoving = 0; -#ifdef notdef - forbid (!vreg && value(UNDOMACRO) && inopen < 0); -#endif - /* - * If previous delete was partial line, use an - * append or insert to put it back so as to - * use insert mode on intelligent terminals. - */ - if (!vreg && DEL[0]) { - forbid ((DEL[0] & (QUOTE|TRIM)) == OVERBUF); - vglobp = DEL; - ungetkey(c == 'p' ? 'a' : 'i'); - goto reread; - } - - /* - * If a register wasn't specified, then make - * sure there is something to put back. - */ - forbid (!vreg && unddol == dol); - /* - * If we just did a macro the whole buffer is in - * the undo save area. We don't want to put THAT. - */ - forbid (vundkind == VMANY && undkind==UNDALL); - vsave(); - vmacchng(1); - setLAST(); - i = 0; - if (vreg && partreg(vreg) || !vreg && pkill[0]) { - /* - * Restoring multiple lines which were partial - * lines; will leave cursor in middle - * of line after shoving restored text in to - * split the current line. - */ - i++; - if (c == 'p' && *cursor) - cursor += skipright(linebuf, cursor); - } else { - /* - * In whole line case, have to back up dot - * for P; also want to clear cursor so - * cursor will eventually be positioned - * at the beginning of the first put line. - */ - cursor = 0; - if (c == 'P') { - dot--, vcline--; - c = 'p'; - } - } - killU(); - - /* - * The call to putreg can potentially - * bomb since there may be nothing in a named buffer. - * We thus put a catch in here. If we didn't and - * there was an error we would end up in command mode. - */ - addr = dol; /* old dol */ - CATCH - vremote(1, vreg ? putreg : put, vreg); - ONERR - if (vreg == -1) { - splitw = 0; - if (op == 'P') - dot++, vcline++; - goto pfixup; - } - ENDCATCH - splitw = 0; - nlput = dol - addr + 1; - if (!i) { - /* - * Increment undap1, undap2 to make up - * for their incorrect initialization in the - * routine vremote before calling put/putreg. - */ - if (FIXUNDO) - undap1++, undap2++; - vcline++; - nlput--; - - /* - * After a put want current line first line, - * and dot was made the last line put in code - * run so far. This is why we increment vcline - * above and decrease dot here. - */ - dot -= nlput - 1; - } -#ifdef TRACE - if (trace) - fprintf(trace, "vreplace(%d, %d, %d), undap1=%d, undap2=%d, dot=%d\n", vcline, i, nlput, lineno(undap1), lineno(undap2), lineno(dot)); -#endif - vreplace(vcline, i, nlput); - if (state != VISUAL) { - /* - * Special case in open mode. - * Force action on the screen when a single - * line is put even if it is identical to - * the current line, e.g. on YP; otherwise - * you can't tell anything happened. - */ - vjumpto(dot, cursor, '.'); - continue; - } -pfixup: - vrepaint(cursor); - vfixcurs(); - continue; - - /* - * ^^ Return to previous file. - * Like a :e #, and thus can be used after a - * "No Write" diagnostic. - */ - case CTRL('^'): - forbid (hadcnt); - vsave(); - ckaw(); - oglobp = globp; - if (value(AUTOWRITE)) - globp = "e! #"; - else - globp = "e #"; - goto gogo; - - /* - * ^] Takes word after cursor as tag, and then does - * tag command. Read ``go right to''. - */ - case CTRL(']'): - grabtag(); - oglobp = globp; - globp = "tag"; - goto gogo; - - /* - * & Like :& - */ - case '&': - oglobp = globp; - globp = "&"; - goto gogo; - - /* - * ^G Bring up a status line at the bottom of - * the screen, like a :file command. - * - * BUG: Was ^S but doesn't work in cbreak mode - */ - case CTRL('g'): - oglobp = globp; - globp = "file"; -gogo: - addr = dot; - vsave(); - goto doinit; - -#ifdef SIGTSTP - /* - * ^Z: suspend editor session and temporarily return - * to shell. Only works with Berkeley/IIASA process - * control in kernel. - */ - case CTRL('z'): - forbid(dosusp == 0 || !ldisc); - vsave(); - oglobp = globp; - globp = "stop"; - goto gogo; -#endif - - /* - * : Read a command from the echo area and - * execute it in command mode. - */ - case ':': - forbid (hadcnt); - vsave(); - i = tchng; - addr = dot; - if (readecho(c)) { - esave[0] = 0; - goto fixup; - } - getDOT(); - /* - * Use the visual undo buffer to store the global - * string for command mode, since it is idle right now. - */ - oglobp = globp; - CP(vutmp, genbuf+1); - globp = vutmp; -doinit: - esave[0] = 0; - fixech(); - - /* - * Have to finagle around not to lose last - * character after this command (when run from ex - * command mode). This is clumsy. - */ - d = peekc; ungetchar(0); - if (shouldpo) { - /* - * So after a "Hit return..." ":", we do - * another "Hit return..." the next time - */ - pofix(); - shouldpo = 0; - } - CATCH - /* - * Save old values of options so we can - * notice when they change; switch into - * cooked mode so we are interruptible. - */ - onumber = value(NUMBER); - olist = value(LIST); - OPline = Pline; - OPutchar = Putchar; - commands(1, 1); - if (dot == zero && dol > zero) - dot = one; - ONERR - copy(esave, vtube[WECHO], - TUBECOLS * sizeof *esave); - ENDCATCH - fixol(); - Pline = OPline; - Putchar = OPutchar; - ungetchar(d); - if (globp && tflag < 0) { - tflag = 0; - goto doinit; - } - globp = oglobp; - - /* - * If we ended up with no lines in the buffer, make - * a line, and don't consider the buffer changed. - */ - if (dot == zero) { - fixzero(); - /*synced();*/ - } - splitw = 0; - - /* - * Special case: did list/number options change? - */ - if (onumber != value(NUMBER)) - setnumb(value(NUMBER)); - if (olist != value(LIST)) - setlist(value(LIST)); - -fixup: - /* - * If a change occurred, other than - * a write which clears changes, then - * we should allow an undo even if . - * didn't move. - * - * BUG: You can make this wrong by - * tricking around with multiple commands - * on one line of : escape, and including - * a write command there, but its not - * worth worrying about. - */ - if (FIXUNDO && tchng && tchng != i) - vundkind = VMANY, cursor = 0; - - /* - * If we are about to do another :, hold off - * updating of screen. - */ - if (vcnt < 0 && Peekkey == ':') { - getDOT(); - shouldpo = 1; - continue; - } - shouldpo = 0; - - /* - * In the case where the file being edited is - * new; e.g. if the initial state hasn't been - * saved yet, then do so now. - */ - if (unddol == truedol) { - vundkind = VNONE; - Vlines = lineDOL(); - if (!inglobal) - savevis(); - addr = zero; - vcnt = 0; - if (esave[0] == 0) - copy(esave, vtube[WECHO], - TUBECOLS * sizeof *esave); - } - - /* - * If the current line moved reset the cursor position. - */ - if (dot != addr) { - vmoving = 0; - cursor = 0; - } - - /* - * If current line is not on screen or if we are - * in open mode and . moved, then redraw. - */ - i = vcline + (dot - addr); - if (i < 0 || i >= vcnt && i >= -vcnt || state != VISUAL && dot != addr) { - if (state == CRTOPEN) - vup1(); - if (vcnt > 0) - vcnt = 0; - vjumpto(dot, (char *) 0, '.'); - } else { - /* - * Current line IS on screen. - * If we did a [Hit return...] then - * restore vcnt and clear screen if in visual - */ - vcline = i; - if (vcnt < 0) { - vcnt = -vcnt; - if (state == VISUAL) - vclear(); - else if (state == CRTOPEN) { - vcnt = 0; - } - } - - /* - * Limit max value of vcnt based on $ - */ - i = vcline + lineDOL() - lineDOT() + 1; - if (i < vcnt) - vcnt = i; - - /* - * Dirty and repaint. - */ - vdirty(0, TLINES); - vrepaint(cursor); - } - - /* - * If in visual, put back the echo area - * if it was clobberred. - */ - if (state == VISUAL) { - int sdc = destcol, sdl = destline; - - splitw++; - vigoto(WECHO, 0); - for (i = 0; i < TUBECOLS - 1; i++) { - if (esave[i] == 0) - break; - vputchar(esave[i]); - } - splitw = 0; - vgoto(sdl, sdc); - } - continue; - - /* - * u undo the last changing command. - */ - case 'u': - vundo(1); - continue; - - /* - * U restore current line to initial state. - */ - case 'U': - vUndo(); - continue; - -fonfon: - beep(); - vmacp = 0; - inopen = 1; /* might have been -1 */ - continue; - } - - /* - * Rest of commands are decoded by the operate - * routine. - */ - operate(c, cnt); - } -} - -/* - * Grab the word after the cursor so we can look for it as a tag. - */ -void -grabtag(void) -{ - register char *cp, *dp; - - cp = vpastwh(cursor); - if (*cp) { - dp = lasttag; - do { - if (dp < &lasttag[sizeof lasttag - 2]) - *dp++ = *cp; - cp++; - } while (isalpha(*cp&0377) || isdigit(*cp&0377) - || *cp == '_' -#ifdef LISPCODE - || (value(LISP) && *cp == '-') -#endif /* LISPCODE */ - ); - *dp++ = 0; - } -} - -/* - * Before appending lines, set up addr1 and - * the command mode undo information. - */ -void -prepapp(void) -{ - - addr1 = dot; - deletenone(); - addr1++; - appendnone(); -} - -/* - * Execute function f with the address bounds addr1 - * and addr2 surrounding cnt lines starting at dot. - */ -void -vremote(int cnt, void (*f)(int), int arg) -{ - register int oing = inglobal; - - addr1 = dot; - addr2 = dot + cnt - 1; - inglobal = 0; - if (FIXUNDO) - undap1 = undap2 = dot; - (*f)(arg); - inglobal = oing; - if (FIXUNDO) - vundkind = VMANY; - vmcurs = 0; -} - -/* - * Save the current contents of linebuf, if it has changed. - */ -void -vsave(void) -{ - char *temp = smalloc(LBSIZE); - - CP(temp, linebuf); - if (FIXUNDO && vundkind == VCHNG || vundkind == VCAPU) { - /* - * If the undo state is saved in the temporary buffer - * vutmp, then we sync this into the temp file so that - * we will be able to undo even after we have moved off - * the line. It would be possible to associate a line - * with vutmp but we assume that vutmp is only associated - * with line dot (e.g. in case ':') above, so beware. - */ - prepapp(); - CP(linebuf, vutmp); - putmark(dot); - vremote(1, yank, 0); - vundkind = VMCHNG; - notecnt = 0; - undkind = UNDCHANGE; - } - /* - * Get the line out of the temp file and do nothing if it hasn't - * changed. This may seem like a loss, but the line will - * almost always be in a read buffer so this may well avoid disk i/o. - */ - getDOT(); - if (strcmp(linebuf, temp) == 0) { - free(temp); - return; - } - strcLIN(temp); - putmark(dot); - free(temp); -} - -#undef forbid -#define forbid(a) if (a) { beep(); return; } - -/* - * Do a z operation. - * Code here is rather long, and very uninteresting. - */ -void -vzop(int hadcnt, int cnt, register int c) -{ - register line *addr; - - if (state != VISUAL) { - /* - * Z from open; always like a z=. - * This code is a mess and should be cleaned up. - */ - vmoveitup(1, 1); - vgoto(outline, 0); - ostop(normf); - setoutt(); - addr2 = dot; - vclear(); - destline = WECHO; - zop2(Xhadcnt ? Xcnt : value(WINDOW) - 1, '='); - if (state == CRTOPEN) - putnl(); - putNFL(); - termreset(); - Outchar = vputchar; - ignore(ostart()); - vcnt = 0; - outline = destline = 0; - vjumpto(dot, cursor, 0); - return; - } - if (hadcnt) { - addr = zero + cnt; - if (addr < one) - addr = one; - if (addr > dol) - addr = dol; - markit(addr); - } else - switch (c) { - - case '+': - addr = dot + vcnt - vcline; - break; - - case '^': - addr = dot - vcline - 1; - forbid (addr < one); - c = '-'; - break; - - default: - addr = dot; - break; - } - switch (c) { - - case '.': - case '-': - break; - - case '^': - forbid (addr <= one); - break; - - case '+': - if ((vtube[WLINES-1][0] == '~' && vtube[WLINES-1][1] == 0) || - dot == dol) { - forbid (addr >= dol); - } else { - if (addr > dol) - addr = dol; - } - /* fall into ... */ - - case CR: - case NL: - c = CR; - break; - - default: - beep(); - return; - } - vmoving = 0; - vjumpto(addr, NOSTR, c); -} - -cell * -str2cell(cell *dst, register char *src) -{ - register cell *cp = dst; - -#ifdef MB - if (mb_cur_max > 1) { - int c, n; - do { - nextc(c, src, n); - src += n; - *cp++ = c; - } while (src[-n]); - } else -#endif /* MB */ - while (*cp++ = *src++ & 0377); - return dst; -} - -char * -cell2str(char *dst, register cell *src) -{ - register char *cp = dst; - - while (*cp++ = *src++); - return dst; -} - -cell * -cellcpy(cell *dst, register cell *src) -{ - register cell *cp = dst; - - while (*cp++ = *src++); - return dst; -} - -size_t -cellen(register cell *cp) -{ - register size_t sz = 0; - - while (*cp++) - sz++; - return sz; -} - -cell * -cellcat(cell *dst, register cell *src) -{ - register cell *cp = dst; - - while (*cp) - cp++; - cellcpy(cp, src); - return dst; -} |
