home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-12-22 | 35.5 KB | 1,710 lines |
- Newsgroups: comp.sources.misc
- From: mool@oce.nl (Bram Moolenaar)
- Subject: v41i066: vim - Vi IMitation editor, v2.0, Part16/25
- Message-ID: <1993Dec21.172539.1458@sparky.sterling.com>
- X-Md4-Signature: 14b33a5603f6ee21c88032376c8f3445
- Keywords: utility, editor, vi, vim
- Sender: kent@sparky.sterling.com (Kent Landfield)
- Organization: Sterling Software
- Date: Tue, 21 Dec 1993 17:25:39 GMT
- Approved: kent@sparky.sterling.com
-
- Submitted-by: mool@oce.nl (Bram Moolenaar)
- Posting-number: Volume 41, Issue 66
- Archive-name: vim/part16
- Environment: UNIX, AMIGA, MS-DOS
- Supersedes: vim: Volume 37, Issue 1-24
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 16 (of 25)."
- # Contents: vim/src/normal.c
- # Wrapped by mool@oce-rd2 on Wed Dec 15 09:50:07 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'vim/src/normal.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vim/src/normal.c'\"
- else
- echo shar: Extracting \"'vim/src/normal.c'\" \(32142 characters\)
- sed "s/^X//" >'vim/src/normal.c' <<'END_OF_FILE'
- X/* vi:ts=4:sw=4
- X *
- X * VIM - Vi IMproved
- X *
- X * Code Contributions By: Bram Moolenaar mool@oce.nl
- X * Tim Thompson twitch!tjt
- X * Tony Andrews onecom!wldrdg!tony
- X * G. R. (Fred) Walter watmath!watcgl!grwalter
- X */
- X
- X/*
- X * Contains the main routine for processing characters in command mode.
- X * Communicates closely with the code in ops.c to handle the operators.
- X */
- X
- X#include "vim.h"
- X#include "globals.h"
- X#include "proto.h"
- X#include "param.h"
- X
- X#undef EXTERN
- X#undef INIT
- X#define EXTERN
- X#define INIT(x) x
- X#include "ops.h"
- X
- X/*
- X * Generally speaking, every command in normal() should either clear any
- X * pending operator (with CLEAROP), or set the motion type variable.
- X */
- X
- X#define CLEAROP (operator = NOP) /* clear any pending operator */
- X#define CLEAROPBEEP clearopbeep() /* CLEAROP plus a beep() */
- X#define CHECKCLEAROP if (checkclearop()) break;
- X#define CHECKCLEAROPQ if (checkclearopq()) break;
- X
- X/*
- X * If a count is given before the operator, it is saved in opnum.
- X */
- Xstatic linenr_t opnum = 0;
- Xstatic linenr_t Prenum; /* The (optional) number before a command. */
- Xint redo_Visual_busy = FALSE; /* TRUE when redo-ing a visual */
- X
- Xstatic void prep_redo __ARGS((long, int, int, int));
- Xstatic int checkclearop __ARGS((void));
- Xstatic int checkclearopq __ARGS((void));
- Xstatic void clearopbeep __ARGS((void));
- Xstatic void premsg __ARGS((int, int));
- X
- Xextern int restart_edit; /* this is in edit.c */
- X
- X/*
- X * normal
- X *
- X * Execute a command in normal mode.
- X *
- X * This is basically a big switch with the cases arranged in rough categories
- X * in the following order:
- X *
- X * 0. Macros (q, @)
- X * 1. Screen positioning commands (^U, ^D, ^F, ^B, ^E, ^Y, z)
- X * 2. Control commands (:, <help>, ^L, ^G, ^^, ZZ, *, ^], ^T)
- X * 3. Cursor motions (G, H, M, L, l, K_RARROW, , h, K_LARROW, ^H, k, K_UARROW, ^P, +, CR, LF, j, K_DARROW, ^N, _, |, B, b, W, w, E, e, $, ^, 0)
- X * 4. Searches (?, /, n, N, T, t, F, f, ,, ;, ], [, %, (, ), {, })
- X * 5. Edits (., u, K_UNDO, ^R, U, r, J, p, P, ^A, ^S)
- X * 6. Inserts (A, a, I, i, o, O, R)
- X * 7. Operators (~, d, c, y, >, <, !, =, Q)
- X * 8. Abbreviations (x, X, D, C, s, S, Y, &)
- X * 9. Marks (m, ', `, ^O, ^I)
- X * 10. Buffer setting (")
- X * 11. Visual (v, V, ^V)
- X * 12. Suspend (^Z)
- X */
- X
- X void
- Xnormal()
- X{
- X register u_char c;
- X long n;
- X int flag = FALSE;
- X int type = 0; /* used in some operations to modify type */
- X int dir = FORWARD; /* search direction */
- X u_char nchar = NUL;
- X int finish_op;
- X linenr_t Prenum1;
- X char searchbuff[CMDBUFFSIZE]; /* buffer for search string */
- X FPOS *pos;
- X register char *ptr;
- X int command_busy = FALSE;
- X static int didwarn = FALSE; /* warned for broken inversion */
- X
- X /* the visual area is remembered for reselection */
- X static linenr_t resel_Visual_nlines; /* number of lines */
- X static int resel_Visual_type = 0; /* type 'v', 'V' or CTRL-V */
- X static colnr_t resel_Visual_col; /* number of columns or end column */
- X /* the visual area is remembered for redo */
- X static linenr_t redo_Visual_nlines; /* number of lines */
- X static int redo_Visual_type = 0; /* type 'v', 'V' or CTRL-V */
- X static colnr_t redo_Visual_col; /* number of columns or end column */
- X
- X Prenum = 0;
- X /*
- X * If there is an operator pending, then the command we take this time
- X * will terminate it. Finish_op tells us to finish the operation before
- X * returning this time (unless the operation was cancelled).
- X */
- X finish_op = (operator != NOP);
- X
- X if (!finish_op && !yankbuffer)
- X opnum = 0;
- X
- X if (p_sc && (vpeekc() == NUL || KeyTyped == TRUE))
- X premsg(NUL, NUL);
- X State = NORMAL_BUSY;
- X c = vgetc();
- X
- X /* Pick up any leading digits and compute 'Prenum' */
- X while ((c >= '1' && c <= '9') || (Prenum != 0 && (c == DEL || c == '0')))
- X {
- X if (c == DEL)
- X Prenum /= 10;
- X else
- X Prenum = Prenum * 10 + (c - '0');
- X if (Prenum < 0) /* got too large! */
- X Prenum = 999999999;
- X premsg(' ', NUL);
- X c = vgetc();
- X }
- X
- X /*
- X * If we're in the middle of an operator (including after entering a yank
- X * buffer with ") AND we had a count before the
- X * operator, then that count overrides the current value of Prenum. What
- X * this means effectively, is that commands like "3dw" get turned into
- X * "d3w" which makes things fall into place pretty neatly.
- X * If you give a count before AND after the operator, they are multiplied.
- X */
- X if (opnum != 0)
- X {
- X if (Prenum)
- X Prenum *= opnum;
- X else
- X Prenum = opnum;
- X opnum = 0;
- X }
- X
- X Prenum1 = (Prenum == 0 ? 1 : Prenum); /* Prenum often defaults to 1 */
- X premsg(c, NUL);
- X
- X /*
- X * get an additional character if we need one
- X */
- X if (strchr("@zZtTfF[]m'`\"", c) || (c == 'q' && !Recording && !Exec_reg) ||
- X (c == 'r' && !Visual.lnum))
- X {
- X State = NOMAPPING;
- X nchar = vgetc(); /* no macro mapping for this char */
- X premsg(c, nchar);
- X }
- X if (p_sc)
- X flushbuf(); /* flush the premsg() characters onto the screen so we can
- X see them while the command is being executed */
- X
- X if (c != 'z') /* the 'z' command gets another character */
- X {
- X State = NORMAL;
- X script_winsize_pp();
- X }
- X if (nchar == ESC)
- X {
- X CLEAROP;
- X goto normal_end;
- X }
- X switch (c)
- X {
- X
- X/*
- X * 0: Macros
- X */
- X case 'q': /* (stop) recording into a named register */
- X CHECKCLEAROP;
- X /* command is ignored while executing a register */
- X if (!Exec_reg && !dorecord(nchar))
- X CLEAROPBEEP;
- X break;
- X
- X case '@': /* execute a named buffer */
- X CHECKCLEAROP;
- X while (Prenum1--)
- X if (!doexecbuf(nchar))
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X break;
- X
- X/*
- X * 1: Screen positioning commands
- X */
- X case Ctrl('D'):
- X flag = TRUE;
- X
- X case Ctrl('U'):
- X CHECKCLEAROP;
- X if (Prenum)
- X p_scroll = (Prenum > Rows - 1) ? Rows - 1 : Prenum;
- X n = (p_scroll < Rows) ? p_scroll : Rows - 1;
- X if (flag)
- X {
- X Topline += n;
- X if (Topline > line_count)
- X Topline = line_count;
- X comp_Botline(); /* compute Botline */
- X onedown(n);
- X }
- X else
- X {
- X if (n >= Curpos.lnum)
- X n = Curpos.lnum - 1;
- X Prenum1 = Curpos.lnum - n;
- X scrolldown(n);
- X if (Prenum1 < Curpos.lnum)
- X Curpos.lnum = Prenum1;
- X }
- X beginline(TRUE);
- X updateScreen(VALID);
- X break;
- X
- X case Ctrl('B'):
- X case K_SUARROW:
- X dir = BACKWARD;
- X
- X case Ctrl('F'):
- X case K_SDARROW:
- X CHECKCLEAROP;
- X onepage(dir, Prenum1);
- X break;
- X
- X case Ctrl('E'):
- X CHECKCLEAROP;
- X scrollup(Prenum1);
- X updateScreen(VALID);
- X break;
- X
- X case Ctrl('Y'):
- X CHECKCLEAROP;
- X scrolldown(Prenum1);
- X updateScreen(VALID);
- X break;
- X
- X case 'z':
- X CHECKCLEAROP;
- X if (isdigit(nchar))
- X {
- X /*
- X * we misuse some variables to be able to call premsg()
- X */
- X operator = c;
- X opnum = Prenum;
- X Prenum = nchar - '0';
- X for (;;)
- X {
- X premsg(' ', NUL);
- X nchar = vgetc();
- X State = NORMAL;
- X script_winsize_pp();
- X if (nchar == DEL)
- X Prenum /= 10;
- X else if (isdigit(nchar))
- X Prenum = Prenum * 10 + (nchar - '0');
- X else if (nchar == CR)
- X {
- X set_winheight((int)Prenum);
- X break;
- X }
- X else
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X }
- X operator = NOP;
- X break;
- X }
- X
- X if (Prenum) /* line number given */
- X {
- X setpcmark();
- X if (Prenum > line_count)
- X Curpos.lnum = line_count;
- X else
- X Curpos.lnum = Prenum;
- X }
- X State = NORMAL;
- X script_winsize_pp();
- X switch (nchar)
- X {
- X case NL: /* put Curpos at top of screen */
- X case CR:
- X Topline = Curpos.lnum;
- X updateScreen(VALID);
- X break;
- X
- X case '.': /* put Curpos in middle of screen */
- X n = (Rows + plines(Curpos.lnum)) / 2;
- X goto dozcmd;
- X
- X case '-': /* put Curpos at bottom of screen */
- X n = Rows - 1;
- X /* FALLTHROUGH */
- X
- X dozcmd:
- X {
- X register linenr_t lp = Curpos.lnum;
- X register long l = plines(lp);
- X
- X do
- X {
- X Topline = lp;
- X if (--lp == 0)
- X break;
- X l += plines(lp);
- X } while (l <= n);
- X }
- X updateScreen(VALID);
- X beginline(TRUE);
- X break;
- X
- X default:
- X CLEAROPBEEP;
- X }
- X break;
- X
- X/*
- X * 2: Control commands
- X */
- X case ':':
- X if (Visual.lnum)
- X goto dooperator;
- X CHECKCLEAROP;
- X docmdline(NULL);
- X break;
- X
- X case K_HELP:
- X CHECKCLEAROP;
- X help();
- X break;
- X
- X case Ctrl('L'):
- X CHECKCLEAROP;
- X updateScreen(CLEAR);
- X break;
- X
- X case Ctrl('G'):
- X CHECKCLEAROP;
- X fileinfo(did_cd || Prenum); /* print full name if count given or :cd used */
- X break;
- X
- X case K_CCIRCM: /* shorthand command */
- X CHECKCLEAROPQ;
- X getaltfile((int)Prenum, (linenr_t)0, TRUE);
- X break;
- X
- X case 'Z': /* write, if changed, and exit */
- X CHECKCLEAROPQ;
- X if (nchar != 'Z')
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X stuffReadbuff(":x\n");
- X break;
- X
- X case Ctrl(']'): /* :ta to current identifier */
- X CHECKCLEAROPQ;
- X case '*': /* / to current identifier */
- X case '#': /* ? to current identifier */
- X case 'K': /* run program for current identifier */
- X {
- X register int col;
- X
- X ptr = nr2ptr(Curpos.lnum);
- X col = Curpos.col;
- X
- X /*
- X * skip to start of identifier.
- X */
- X while (ptr[col] != NUL && !isidchar(ptr[col]))
- X ++col;
- X
- X /*
- X * Back up to start of identifier. This doesn't match the
- X * real vi but I like it a little better and it shouldn't bother
- X * anyone.
- X */
- X while (col > 0 && isidchar(ptr[col - 1]))
- X --col;
- X
- X if (!isidchar(ptr[col]))
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X
- X if (Prenum)
- X stuffnumReadbuff(Prenum);
- X switch (c)
- X {
- X case '*':
- X stuffReadbuff("/");
- X break;
- X case '#':
- X stuffReadbuff("?");
- X break;
- X case 'K':
- X stuffReadbuff(":! ");
- X stuffReadbuff(p_kp);
- X stuffReadbuff(" ");
- X break;
- X default:
- X stuffReadbuff(":ta ");
- X }
- X
- X /*
- X * Now grab the chars in the identifier
- X */
- X while (isidchar(ptr[col]))
- X {
- X stuffcharReadbuff(ptr[col]);
- X ++col;
- X }
- X stuffReadbuff("\n");
- X }
- X break;
- X
- X case Ctrl('T'): /* backwards in tag stack */
- X CHECKCLEAROPQ;
- X dotag("", 2, (int)Prenum1);
- X break;
- X
- X/*
- X * Cursor motions
- X */
- X case 'G':
- X mtype = MLINE;
- X setpcmark();
- X if (Prenum == 0 || Prenum > line_count)
- X Curpos.lnum = line_count;
- X else
- X Curpos.lnum = Prenum;
- X beginline(TRUE);
- X break;
- X
- X case 'H':
- X case 'M':
- X if (c == 'M')
- X n = (Rows - emptyrows - 1) / 2;
- X else
- X n = Prenum;
- X mtype = MLINE;
- X setpcmark();
- X Curpos.lnum = Topline;
- X while (n && onedown((long)1))
- X --n;
- X beginline(TRUE);
- X break;
- X
- X case 'L':
- X mtype = MLINE;
- X setpcmark();
- X Curpos.lnum = Botline - 1;
- X for (n = Prenum; n && oneup((long)1); n--)
- X ;
- X beginline(TRUE);
- X break;
- X
- X case 'l':
- X case K_RARROW:
- X case ' ':
- X mtype = MCHAR;
- X mincl = FALSE;
- X n = Prenum1;
- X while (n--)
- X {
- X if (!oneright())
- X {
- X if (operator == NOP)
- X beep();
- X else
- X {
- X if (lineempty(Curpos.lnum))
- X CLEAROPBEEP;
- X else
- X {
- X mincl = TRUE;
- X if (n)
- X beep();
- X }
- X }
- X break;
- X }
- X }
- X set_want_col = TRUE;
- X break;
- X
- X case 'h':
- X case K_LARROW:
- X case Ctrl('H'):
- X case DEL:
- X mtype = MCHAR;
- X mincl = FALSE;
- X n = Prenum1;
- X while (n--)
- X {
- X if (!oneleft())
- X {
- X if (operator != DELETE && operator != CHANGE)
- X beep();
- X else if (Prenum1 == 1)
- X CLEAROPBEEP;
- X break;
- X }
- X }
- X set_want_col = TRUE;
- X break;
- X
- X case '-':
- X flag = TRUE;
- X /* FALLTHROUGH */
- X
- X case 'k':
- X case K_UARROW:
- X case Ctrl('P'):
- X mtype = MLINE;
- X if (!oneup(Prenum1))
- X CLEAROPBEEP;
- X else if (flag)
- X beginline(TRUE);
- X break;
- X
- X case '+':
- X case CR:
- X flag = TRUE;
- X /* FALLTHROUGH */
- X
- X case 'j':
- X case K_DARROW:
- X case Ctrl('N'):
- X case NL:
- X mtype = MLINE;
- X if (!onedown(Prenum1))
- X CLEAROPBEEP;
- X else if (flag)
- X beginline(TRUE);
- X break;
- X
- X /*
- X * This is a strange motion command that helps make operators more
- X * logical. It is actually implemented, but not documented in the
- X * real 'vi'. This motion command actually refers to "the current
- X * line". Commands like "dd" and "yy" are really an alternate form of
- X * "d_" and "y_". It does accept a count, so "d3_" works to delete 3
- X * lines.
- X */
- X case '_':
- Xlineop:
- X if (operator == CHANGE && p_ai) /* do not delete the indent */
- X {
- X beginline(TRUE);
- X startop = Curpos;
- X mtype = MCHAR;
- X mincl = TRUE;
- X }
- X else
- X mtype = MLINE;
- X if (!onedown((long)(Prenum1 - 1)))
- X CLEAROPBEEP;
- X else if (mtype == MCHAR) /* 'c' with autoindent */
- X {
- X Curpos.col = MAXCOL; /* put cursor on last char in line */
- X adjustCurpos();
- X }
- X else if (operator != YANK) /* 'Y' does not move cursor */
- X beginline(TRUE);
- X break;
- X
- X case '|':
- X mtype = MCHAR;
- X mincl = TRUE;
- X beginline(FALSE);
- X if (Prenum > 0)
- X coladvance((colnr_t)(Prenum - 1));
- X Curswant = (colnr_t)(Prenum - 1);
- X break;
- X
- X /*
- X * Word Motions
- X */
- X
- X case 'B':
- X type = 1;
- X /* FALLTHROUGH */
- X
- X case 'b':
- X case K_SLARROW:
- X mtype = MCHAR;
- X mincl = FALSE;
- X set_want_col = TRUE;
- X if (bck_word(Prenum1, type))
- X CLEAROPBEEP;
- X break;
- X
- X case 'E':
- X type = 1;
- X /* FALLTHROUGH */
- X
- X case 'e':
- X mincl = TRUE;
- X goto dowrdcmd;
- X
- X case 'W':
- X type = 1;
- X /* FALLTHROUGH */
- X
- X case 'w':
- X case K_SRARROW:
- X mincl = FALSE;
- X flag = TRUE;
- X /*
- X * This is a little strange. To match what the real vi does, we
- X * effectively map 'cw' to 'ce', and 'cW' to 'cE', provided that we are
- X * not on a space or a TAB. This seems
- X * impolite at first, but it's really more what we mean when we say
- X * 'cw'.
- X */
- X if (operator == CHANGE && (n = gcharCurpos()) != ' ' && n != TAB &&
- X n != NUL)
- X {
- X mincl = TRUE;
- X flag = FALSE;
- X }
- X
- Xdowrdcmd:
- X mtype = MCHAR;
- X set_want_col = TRUE;
- X if (flag)
- X n = fwd_word(Prenum1, type, operator != NOP);
- X else
- X n = end_word(Prenum1, type, operator == CHANGE);
- X if (n)
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X#if 0
- X /*
- X * If we do a 'dw' for the last word in a line, we only delete the rest
- X * of the line, not joining the two lines, unless the current line is empty.
- X */
- X if (operator == DELETE && Prenum1 == 1 && startop.lnum != Curpos.lnum &&
- X !lineempty(startop.lnum))
- X {
- X Curpos = startop;
- X while (oneright())
- X ;
- X mincl = TRUE;
- X }
- X#endif
- X break;
- X
- X case '$':
- X mtype = MCHAR;
- X mincl = TRUE;
- X Curswant = MAXCOL; /* so we stay at the end */
- X if (!onedown((long)(Prenum1 - 1)))
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X break;
- X
- X case '^':
- X flag = TRUE;
- X /* FALLTHROUGH */
- X
- X case '0':
- X mtype = MCHAR;
- X mincl = FALSE;
- X beginline(flag);
- X break;
- X
- X/*
- X * 4: Searches
- X */
- X case '?':
- X case '/':
- X if (!getcmdline(c, (u_char *)searchbuff))
- X {
- X CLEAROP;
- X break;
- X }
- X mtype = MCHAR;
- X mincl = FALSE;
- X set_want_col = TRUE;
- X
- X n = dosearch(c, searchbuff, FALSE, Prenum1, TRUE);
- X if (n == 0)
- X CLEAROP;
- X else if (n == 2)
- X mtype = MLINE;
- X break;
- X
- X case 'N':
- X flag = 1;
- X
- X case 'n':
- X mtype = MCHAR;
- X mincl = FALSE;
- X set_want_col = TRUE;
- X if (!dosearch(0, NULL, flag, Prenum1, TRUE))
- X CLEAROP;
- X break;
- X
- X /*
- X * Character searches
- X */
- X case 'T':
- X dir = BACKWARD;
- X /* FALLTHROUGH */
- X
- X case 't':
- X type = 1;
- X goto docsearch;
- X
- X case 'F':
- X dir = BACKWARD;
- X /* FALLTHROUGH */
- X
- X case 'f':
- Xdocsearch:
- X mtype = MCHAR;
- X mincl = TRUE;
- X set_want_col = TRUE;
- X if (!searchc(nchar, dir, type, Prenum1))
- X CLEAROPBEEP;
- X break;
- X
- X case ',':
- X flag = 1;
- X /* FALLTHROUGH */
- X
- X case ';':
- X dir = flag;
- X goto docsearch; /* nchar == NUL, thus repeat previous search */
- X
- X /*
- X * section or C function searches
- X */
- X
- X case '[':
- X dir = BACKWARD;
- X /* FALLTHROUGH */
- X
- X case ']':
- X mtype = MLINE;
- X set_want_col = TRUE;
- X flag = '{';
- X if (nchar != c)
- X {
- X if (nchar == '[' || nchar == ']')
- X flag = '}';
- X else
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X }
- X if (dir == FORWARD && operator != NOP) /* e.g. y]] searches for '}' */
- X flag = '}';
- X if (!findpar(dir, Prenum1, flag))
- X {
- X CLEAROPBEEP;
- X }
- X break;
- X
- X case '%':
- X mincl = TRUE;
- X if (Prenum) /* {cnt}% : goto {cnt} percentage in file */
- X {
- X if (Prenum > 100)
- X CLEAROPBEEP;
- X else
- X {
- X mtype = MLINE;
- X setpcmark();
- X /* round up, so CTRL-G will give same value */
- X Curpos.lnum = (line_count * Prenum + 99) / 100;
- X Curpos.col = 0;
- X }
- X }
- X else /* % : go to matching paren */
- X {
- X mtype = MCHAR;
- X if ((pos = showmatch()) == NULL)
- X CLEAROPBEEP;
- X else
- X {
- X setpcmark();
- X Curpos = *pos;
- X set_want_col = TRUE;
- X }
- X }
- X break;
- X
- X case '(':
- X dir = BACKWARD;
- X /* FALLTHROUGH */
- X
- X case ')':
- X mtype = MCHAR;
- X if (c == ')')
- X mincl = FALSE;
- X else
- X mincl = TRUE;
- X set_want_col = TRUE;
- X
- X if (!findsent(dir, Prenum1))
- X CLEAROPBEEP;
- X break;
- X
- X case '{':
- X dir = BACKWARD;
- X /* FALLTHROUGH */
- X
- X case '}':
- X mtype = MCHAR;
- X mincl = FALSE;
- X set_want_col = TRUE;
- X if (!findpar(dir, Prenum1, NUL))
- X CLEAROPBEEP;
- X break;
- X
- X/*
- X * 5: Edits
- X */
- X case '.':
- X CHECKCLEAROPQ;
- X if (!start_redo(Prenum))
- X CLEAROPBEEP;
- X break;
- X
- X case 'u':
- X if (Visual.lnum)
- X goto dooperator;
- X case K_UNDO:
- X CHECKCLEAROPQ;
- X u_undo((int)Prenum1);
- X set_want_col = TRUE;
- X break;
- X
- X case Ctrl('R'):
- X CHECKCLEAROPQ;
- X u_redo((int)Prenum1);
- X set_want_col = TRUE;
- X break;
- X
- X case 'U':
- X if (Visual.lnum)
- X goto dooperator;
- X CHECKCLEAROPQ;
- X u_undoline();
- X set_want_col = TRUE;
- X break;
- X
- X case 'r':
- X if (Visual.lnum)
- X {
- X c = 'c';
- X goto dooperator;
- X }
- X CHECKCLEAROPQ;
- X ptr = nr2ptr(Curpos.lnum) + Curpos.col;
- X if (strlen(ptr) < (unsigned)Prenum1) /* not enough characters to replace */
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X /*
- X * Replacing with a line break or tab is done by edit(), because it
- X * is complicated.
- X * Other characters are done below to avoid problems with things like
- X * CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
- X */
- X if (nchar == '\r' || nchar == '\n' || nchar == '\t')
- X {
- X prep_redo(Prenum1, 'r', nchar, NUL);
- X stuffnumReadbuff(Prenum1);
- X stuffcharReadbuff('R');
- X stuffcharReadbuff(nchar);
- X stuffcharReadbuff(ESC);
- X break;
- X }
- X
- X if (nchar == Ctrl('V')) /* get another character */
- X {
- X c = Ctrl('V');
- X nchar = get_literal(&type);
- X if (type) /* typeahead */
- X stuffcharReadbuff(type);
- X }
- X else
- X c = NUL;
- X prep_redo(Prenum1, 'r', c, nchar);
- X if (!u_saveCurpos()) /* save line for undo */
- X break;
- X Curpos.col += Prenum1 - 1;
- X while (Prenum1--) /* replace the characters */
- X *ptr++ = nchar;
- X set_want_col = TRUE;
- X CHANGED;
- X updateline();
- X break;
- X
- X case 'J':
- X if (Visual.lnum) /* join the visual lines */
- X {
- X if (Curpos.lnum > Visual.lnum)
- X {
- X Prenum = Curpos.lnum - Visual.lnum + 1;
- X Curpos.lnum = Visual.lnum;
- X }
- X else
- X Prenum = Visual.lnum - Curpos.lnum + 1;
- X Visual.lnum = 0;
- X }
- X CHECKCLEAROP;
- X if (Prenum <= 1)
- X Prenum = 2; /* default for join is two lines! */
- X if (Curpos.lnum + Prenum - 1 > line_count) /* beyond last line */
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X
- X prep_redo(Prenum, 'J', NUL, NUL);
- X dodojoin(Prenum, TRUE, TRUE);
- X break;
- X
- X case 'P':
- X dir = BACKWARD;
- X /* FALLTHROUGH */
- X
- X case 'p':
- X CHECKCLEAROPQ;
- X prep_redo(Prenum, c, NUL, NUL);
- X doput(dir, Prenum1);
- X break;
- X
- X case Ctrl('A'): /* add to number */
- X case Ctrl('S'): /* subtract from number */
- X CHECKCLEAROPQ;
- X if (doaddsub((int)c, Prenum1))
- X prep_redo(Prenum1, c, NUL, NUL);
- X break;
- X
- X/*
- X * 6: Inserts
- X */
- X case 'A':
- X set_want_col = TRUE;
- X while (oneright())
- X ;
- X /* FALLTHROUGH */
- X
- X case 'a':
- X CHECKCLEAROPQ;
- X /* Works just like an 'i'nsert on the next character. */
- X if (u_saveCurpos())
- X {
- X if (!lineempty(Curpos.lnum))
- X incCurpos();
- X startinsert(c, FALSE, Prenum1);
- X command_busy = TRUE;
- X }
- X break;
- X
- X case 'I':
- X beginline(TRUE);
- X /* FALLTHROUGH */
- X
- X case 'i':
- X CHECKCLEAROPQ;
- X if (u_saveCurpos())
- X {
- X startinsert(c, FALSE, Prenum1);
- X command_busy = TRUE;
- X }
- X break;
- X
- X case 'o':
- X if (Visual.lnum) /* switch start and end of visual */
- X {
- X Prenum = Visual.lnum;
- X Visual.lnum = Curpos.lnum;
- X Curpos.lnum = Prenum;
- X if (Visual.col != VISUALLINE)
- X {
- X n = Visual.col;
- X Visual.col = Curpos.col;
- X Curpos.col = (int)n;
- X set_want_col = TRUE;
- X }
- X break;
- X }
- X CHECKCLEAROP;
- X if (u_save(Curpos.lnum, (linenr_t)(Curpos.lnum + 1)) && Opencmd(FORWARD, TRUE, TRUE))
- X {
- X startinsert('o', TRUE, Prenum1);
- X command_busy = TRUE;
- X }
- X break;
- X
- X case 'O':
- X CHECKCLEAROPQ;
- X if (u_save((linenr_t)(Curpos.lnum - 1), Curpos.lnum) && Opencmd(BACKWARD, TRUE, TRUE))
- X {
- X startinsert('O', TRUE, Prenum1);
- X command_busy = TRUE;
- X }
- X break;
- X
- X case 'R':
- X if (Visual.lnum)
- X {
- X c = 'c';
- X Visual.col = VISUALLINE;
- X goto dooperator;
- X }
- X CHECKCLEAROPQ;
- X if (u_saveCurpos())
- X {
- X startinsert('R', FALSE, Prenum1);
- X command_busy = TRUE;
- X }
- X break;
- X
- X/*
- X * 7: Operators
- X */
- X case '~': /* swap case */
- X /*
- X * if tilde is not an operator and Visual is off: swap case
- X * of a single character
- X */
- X if (!p_to && !Visual.lnum)
- X {
- X CHECKCLEAROPQ;
- X if (lineempty(Curpos.lnum))
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X prep_redo(Prenum, '~', NUL, NUL);
- X
- X if (!u_saveCurpos())
- X break;
- X
- X for (; Prenum1 > 0; --Prenum1)
- X {
- X if (gcharCurpos() == NUL)
- X break;
- X swapchar(&Curpos);
- X incCurpos();
- X }
- X
- X set_want_col = TRUE;
- X CHANGED;
- X updateline();
- X break;
- X }
- X /*FALLTHROUGH*/
- X
- X case 'd':
- X case 'c':
- X case 'y':
- X case '>':
- X case '<':
- X case '!':
- X case '=':
- X case 'Q':
- Xdooperator:
- X n = strchr(opchars, c) - opchars + 1;
- X if (n == operator) /* double operator works on lines */
- X goto lineop;
- X CHECKCLEAROP;
- X if (Prenum != 0)
- X opnum = Prenum;
- X startop = Curpos;
- X operator = (int)n;
- X break;
- X
- X/*
- X * 8: Abbreviations
- X */
- X
- X /* when Visual the next commands are operators */
- X case 'S':
- X case 'Y':
- X case 'D':
- X case 'C':
- X case 'x':
- X case 'X':
- X case 's':
- X if (Visual.lnum)
- X {
- X static char trans[] = "ScYyDdCcxdXdsc";
- X
- X if (isupper(c) && !Visual_block) /* uppercase means linewise */
- X Visual.col = VISUALLINE;
- X c = *(strchr(trans, c) + 1);
- X goto dooperator;
- X }
- X
- X case '&':
- X CHECKCLEAROPQ;
- X if (Prenum)
- X stuffnumReadbuff(Prenum);
- X
- X if (c == 'Y' && p_ye)
- X c = 'Z';
- X {
- X static char *(ar[9]) = {"dl", "dh", "d$", "c$", "cl", "cc", "yy", "y$", ":s\r"};
- X static char *str = "xXDCsSYZ&";
- X
- X stuffReadbuff(ar[(int)(strchr(str, c) - str)]);
- X }
- X break;
- X
- X/*
- X * 9: Marks
- X */
- X
- X case 'm':
- X CHECKCLEAROP;
- X if (!setmark(nchar))
- X CLEAROPBEEP;
- X break;
- X
- X case '\'':
- X flag = TRUE;
- X /* FALLTHROUGH */
- X
- X case '`':
- X pos = getmark(nchar, (operator == NOP));
- X if (pos == (FPOS *)-1) /* jumped to other file */
- X {
- X if (flag)
- X beginline(TRUE);
- X break;
- X }
- X
- X if (pos != NULL)
- X setpcmark();
- X
- Xcursormark:
- X if (pos == NULL)
- X CLEAROPBEEP;
- X else
- X {
- X Curpos = *pos;
- X if (flag)
- X beginline(TRUE);
- X }
- X mtype = flag ? MLINE : MCHAR;
- X mincl = FALSE; /* ignored if not MCHAR */
- X set_want_col = TRUE;
- X break;
- X
- X case Ctrl('O'): /* goto older pcmark */
- X Prenum1 = -Prenum1;
- X /* FALLTHROUGH */
- X
- X case Ctrl('I'): /* goto newer pcmark */
- X CHECKCLEAROPQ;
- X pos = movemark((int)Prenum1);
- X if (pos == (FPOS *)-1) /* jump to other file */
- X {
- X set_want_col = TRUE;
- X break;
- X }
- X goto cursormark;
- X
- X/*
- X * 10. Buffer setting
- X */
- X case '"':
- X CHECKCLEAROP;
- X if (isalnum(nchar) || nchar == '.' || nchar == '%' || nchar == '"')
- X {
- X yankbuffer = nchar;
- X opnum = Prenum; /* remember count before '"' */
- X }
- X else
- X CLEAROPBEEP;
- X break;
- X
- X/*
- X * 11. Visual
- X */
- X case 'v':
- X case 'V':
- X case Ctrl('V'):
- X CHECKCLEAROP;
- X Visual_block = FALSE;
- X
- X /* stop Visual */
- X if (Visual.lnum)
- X {
- X Visual.lnum = 0;
- X updateScreen(NOT_VALID); /* delete the inversion */
- X }
- X /* start Visual */
- X else
- X {
- X if (!didwarn && (T_TI == NULL || *T_TI == NUL)) /* cannot invert */
- X {
- X emsg("Warning: terminal cannot invert");
- X didwarn = TRUE;
- X }
- X if (Prenum) /* use previously selected part */
- X {
- X if (!resel_Visual_type) /* there is none */
- X {
- X beep();
- X break;
- X }
- X Visual = Curpos;
- X if (resel_Visual_nlines > 1)
- X Curpos.lnum += resel_Visual_nlines * Prenum - 1;
- X switch (resel_Visual_type)
- X {
- X case 'V': Visual.col = VISUALLINE;
- X break;
- X
- X case Ctrl('V'):
- X Visual_block = TRUE;
- X break;
- X
- X case 'v':
- X if (resel_Visual_nlines <= 1)
- X Curpos.col += resel_Visual_col * Prenum - 1;
- X else
- X Curpos.col = resel_Visual_col;
- X break;
- X }
- X if (resel_Visual_col == MAXCOL)
- X {
- X Curswant = MAXCOL;
- X coladvance(MAXCOL);
- X }
- X else if (Visual_block)
- X coladvance((colnr_t)(Cursvcol + resel_Visual_col * Prenum - 1));
- X updateScreen(NOT_VALID); /* show the inversion */
- X }
- X else
- X {
- X Visual = Curpos;
- X if (c == 'V') /* linewise */
- X Visual.col = VISUALLINE;
- X else if (c == Ctrl('V')) /* blockwise */
- X Visual_block = TRUE;
- X updateline(); /* start the inversion */
- X }
- X }
- X break;
- X
- X/*
- X * 12. Suspend
- X */
- X
- X case Ctrl('Z'):
- X CLEAROP;
- X Visual.lnum = 0; /* stop Visual */
- X stuffReadbuff(":st\r"); /* with autowrite */
- X break;
- X
- X/*
- X * The end
- X */
- X case ESC:
- X if (Visual.lnum)
- X {
- X Visual.lnum = 0; /* stop Visual */
- X updateScreen(NOT_VALID);
- X }
- X
- X default: /* not a known command */
- X CLEAROPBEEP;
- X break;
- X
- X } /* end of switch on command character */
- X
- X/*
- X * if we didn't start or finish an operator, reset yankbuffer, unless we
- X * need it later.
- X */
- X if (!finish_op && !operator && strchr("\"DCYSsXx", c) == NULL)
- X yankbuffer = 0;
- X
- X /*
- X * If an operation is pending, handle it...
- X */
- X if ((Visual.lnum || finish_op) && operator != NOP)
- X {
- X if (operator != YANK && !Visual.lnum) /* can't redo yank */
- X {
- X prep_redo(Prenum, opchars[operator - 1], c, nchar);
- X if (c == '/' || c == '?') /* was a search */
- X {
- X AppendToRedobuff(searchbuff);
- X AppendToRedobuff(NL_STR);
- X }
- X }
- X
- X if (redo_Visual_busy)
- X {
- X startop = Curpos;
- X Curpos.lnum += redo_Visual_nlines - 1;
- X switch (redo_Visual_type)
- X {
- X case 'V': Visual.col = VISUALLINE;
- X break;
- X
- X case Ctrl('V'):
- X Visual_block = TRUE;
- X break;
- X
- X case 'v':
- X if (redo_Visual_nlines <= 1)
- X Curpos.col += redo_Visual_col - 1;
- X else
- X Curpos.col = redo_Visual_col;
- X break;
- X }
- X if (redo_Visual_col == MAXCOL)
- X {
- X Curswant = MAXCOL;
- X coladvance(MAXCOL);
- X }
- X }
- X else if (Visual.lnum)
- X startop = Visual;
- X
- X if (lt(startop, Curpos))
- X {
- X endop = Curpos;
- X Curpos = startop;
- X }
- X else
- X {
- X endop = startop;
- X startop = Curpos;
- X }
- X nlines = endop.lnum - startop.lnum + 1;
- X
- X if (Visual.lnum || redo_Visual_busy)
- X {
- X if (Visual_block) /* block mode */
- X {
- X startvcol = getvcol(&startop, 2);
- X n = getvcol(&endop, 2);
- X if (n < startvcol)
- X startvcol = (colnr_t)n;
- X
- X /* if '$' was used, get endvcol from longest line */
- X if (Curswant == MAXCOL)
- X {
- X Curpos.col = MAXCOL;
- X endvcol = 0;
- X for (Curpos.lnum = startop.lnum; Curpos.lnum <= endop.lnum; ++Curpos.lnum)
- X if ((n = getvcol(&Curpos, 3)) > endvcol)
- X endvcol = (colnr_t)n;
- X Curpos = startop;
- X }
- X else if (redo_Visual_busy)
- X endvcol = startvcol + redo_Visual_col - 1;
- X else
- X {
- X endvcol = getvcol(&startop, 3);
- X n = getvcol(&endop, 3);
- X if (n > endvcol)
- X endvcol = (colnr_t)n;
- X }
- X coladvance(startvcol);
- X }
- X
- X /*
- X * prepare to reselect and redo Visual: this is based on the size
- X * of the Visual text
- X */
- X if (Visual_block)
- X resel_Visual_type = Ctrl('V');
- X else if (Visual.col == VISUALLINE)
- X resel_Visual_type = 'V';
- X else
- X resel_Visual_type = 'v';
- X if (Curswant == MAXCOL)
- X resel_Visual_col = MAXCOL;
- X else if (Visual_block)
- X resel_Visual_col = endvcol - startvcol + 1;
- X else if (nlines > 1)
- X resel_Visual_col = endop.col;
- X else
- X resel_Visual_col = endop.col - startop.col + 1;
- X resel_Visual_nlines = nlines;
- X if (operator != YANK && operator != COLON) /* can't redo yank and : */
- X {
- X prep_redo(0L, 'v', opchars[operator - 1], NUL);
- X redo_Visual_type = resel_Visual_type;
- X redo_Visual_col = resel_Visual_col;
- X redo_Visual_nlines = resel_Visual_nlines;
- X }
- X
- X mincl = TRUE;
- X if (Visual.col == VISUALLINE)
- X mtype = MLINE;
- X else
- X mtype = MCHAR;
- X
- X redo_Visual_busy = FALSE;
- X /*
- X * Switch Visual off now, so screen updating does
- X * not show inverted text when the screen is redrawn.
- X * With YANK and sometimes with COLON and FILTER there is no screen
- X * redraw, so it is done here to remove the inverted part.
- X */
- X Visual.lnum = 0;
- X if (operator == YANK || operator == COLON || operator == FILTER)
- X updateScreen(NOT_VALID);
- X }
- X
- X set_want_col = 1;
- X
- X /* no_op is set when start and end are the same */
- X no_op = (mtype == MCHAR && !mincl && equal(startop, endop));
- X
- X /*
- X * If the end of an operator is in column one while mtype is MCHAR and mincl
- X * is FALSE, we put endop after the last character in the previous line.
- X * If startop is on or before the first non-blank in the line, the operator
- X * becomes linewise (strange, but that's the way vi does it).
- X */
- X if (mtype == MCHAR && mincl == FALSE && endop.col == 0 && nlines > 1)
- X {
- X --nlines;
- X --endop.lnum;
- X if (startinmargin())
- X mtype = MLINE;
- X else
- X {
- X endop.col = strlen(nr2ptr(endop.lnum));
- X if (endop.col)
- X {
- X --endop.col;
- X mincl = TRUE;
- X }
- X }
- X }
- X switch (operator)
- X {
- X case LSHIFT:
- X case RSHIFT:
- X doshift(operator);
- X break;
- X
- X case DELETE:
- X if (!no_op)
- X dodelete();
- X break;
- X
- X case YANK:
- X if (!no_op)
- X doyank(FALSE);
- X break;
- X
- X case CHANGE:
- X dochange();
- X command_busy = TRUE;
- X break;
- X
- X case FILTER:
- X bangredo = TRUE; /* dobang() will put cmd in redo buffer */
- X
- X case INDENT:
- X case COLON:
- Xdofilter:
- X sprintf(IObuff, ":%ld,%ld", (long)startop.lnum, (long)endop.lnum);
- X stuffReadbuff(IObuff);
- X if (operator != COLON)
- X stuffReadbuff("!");
- X if (operator == INDENT)
- X {
- X stuffReadbuff(p_ep);
- X stuffReadbuff("\n");
- X }
- X else if (operator == FORMAT)
- X {
- X stuffReadbuff(p_fp);
- X stuffReadbuff("\n");
- X }
- X /* docmdline() does the rest */
- X break;
- X
- X case TILDE:
- X case UPPER:
- X case LOWER:
- X if (!no_op)
- X dotilde();
- X break;
- X
- X case FORMAT:
- X if (*p_fp != NUL)
- X goto dofilter; /* use external command */
- X doformat(); /* use internal function */
- X break;
- X
- X default:
- X CLEAROPBEEP;
- X }
- X operator = NOP;
- X Visual_block = FALSE;
- X yankbuffer = 0;
- X }
- X
- Xnormal_end:
- X premsg(-1, NUL);
- X if (restart_edit && operator == NOP && Visual.lnum == 0 && !command_busy && stuff_empty() && yankbuffer == 0)
- X startinsert(restart_edit, FALSE, 1L);
- X}
- X
- X static void
- Xprep_redo(num, cmd, c, nchar)
- X long num;
- X int cmd;
- X int c;
- X int nchar;
- X{
- X ResetRedobuff();
- X if (yankbuffer != 0) /* yank from specified buffer */
- X {
- X AppendCharToRedobuff('\"');
- X AppendCharToRedobuff(yankbuffer);
- X }
- X if (num)
- X AppendNumberToRedobuff(num);
- X AppendCharToRedobuff(cmd);
- X if (c != NUL)
- X AppendCharToRedobuff(c);
- X if (nchar != NUL)
- X AppendCharToRedobuff(nchar);
- X}
- X
- X/*
- X * check for operator active
- X */
- X static int
- Xcheckclearop()
- X{
- X if (operator == NOP)
- X return (FALSE);
- X clearopbeep();
- X return (TRUE);
- X}
- X
- X/*
- X * check for operator or Visual active
- X */
- X static int
- Xcheckclearopq()
- X{
- X if (operator == NOP && Visual.lnum == 0)
- X return (FALSE);
- X clearopbeep();
- X return (TRUE);
- X}
- X
- X static void
- Xclearopbeep()
- X{
- X CLEAROP;
- X beep();
- X}
- X
- X/*
- X * display, on the last line of the window, the characters typed before
- X * the last command character, plus 'c1' and 'c2'
- X */
- X static void
- Xpremsg(c1, c2)
- X int c1, c2;
- X{
- X char buf[40];
- X char *p;
- X
- X if (!p_sc || !(KeyTyped || c1 == -1 || c1 == ' '))
- X return;
- X
- X cursor_off();
- X windgoto((int)Rows - 1, sc_col);
- X if (c1 == -1)
- X outstrn(" "); /* look in comp_col() for the number of spaces */
- X else
- X {
- X p = buf;
- X if (opnum)
- X {
- X sprintf(p, "%ld", (long)opnum);
- X p = p + strlen(buf);
- X }
- X if (yankbuffer)
- X {
- X *p++ = '"';
- X *p++ = yankbuffer;
- X }
- X if (operator == 'z')
- X *p++ = 'z';
- X else if (operator)
- X *p++ = opchars[operator - 1];
- X if (Prenum)
- X {
- X sprintf(p, "%ld", (long)Prenum);
- X p = p + strlen(p);
- X }
- X *p = NUL;
- X if (c1)
- X strcpy(p, transchar(c1));
- X if (c2)
- X strcat(p, transchar(c2));
- X buf[10] = NUL; /* truncate at maximal length */
- X outstrn(buf);
- X }
- X setcursor();
- X cursor_on();
- X}
- END_OF_FILE
- if test 32142 -ne `wc -c <'vim/src/normal.c'`; then
- echo shar: \"'vim/src/normal.c'\" unpacked with wrong size!
- fi
- chmod +x 'vim/src/normal.c'
- # end of 'vim/src/normal.c'
- fi
- echo shar: End of archive 16 \(of 25\).
- cp /dev/null ark16isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 25 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
- ===============================================================================
- Bram Moolenaar | DISCLAIMER: This note does not
- Oce Nederland B.V., Research & Development | necessarily represent the position
- p.o. box 101, 5900 MA Venlo | of Oce-Nederland B.V. Therefore
- The Netherlands phone +31 77 594077 | no liability or responsibility for
- UUCP: mool@oce.nl fax +31 77 595473 | whatever will be accepted.
-
- exit 0 # Just in case...
-