home *** CD-ROM | disk | FTP | other *** search
- From: mool@oce.nl (Bram Moolenaar)
- Newsgroups: comp.sources.misc
- Subject: v44i029: vim - Vi IMproved editor, v3.0, Part10/26
- Date: 16 Aug 1994 21:18:14 -0500
- Organization: Sterling Software
- Sender: kent@sparky.sterling.com
- Approved: kent@sparky.sterling.com
- Message-ID: <32rs16$ke4@sparky.sterling.com>
- X-Md4-Signature: 645cc39459ac34c1a4813dce9d1e3c86
-
- Submitted-by: mool@oce.nl (Bram Moolenaar)
- Posting-number: Volume 44, Issue 29
- Archive-name: vim/part10
- Environment: UNIX, AMIGA, MS-DOS, Windows NT
- Supersedes: vim: Volume 41, Issue 50-75
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: vim/doc/digraph.doc.UU vim/src/misccmds.c vim/src/normal.c
- # Wrapped by kent@sparky on Mon Aug 15 21:44:04 1994
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 10 (of 26)."'
- if test -f 'vim/doc/digraph.doc.UU' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vim/doc/digraph.doc.UU'\"
- else
- echo shar: Extracting \"'vim/doc/digraph.doc.UU'\" \(3112 characters\)
- sed "s/^X//" >'vim/doc/digraph.doc.UU' <<'END_OF_FILE'
- Xbegin 644 vim/doc/digraph.doc
- XM5&AE<V4@87)E('1H92!D969A=6QT(&1I9W)A<&@@8VAA<F%C=&5R<R!F;W(@
- XM5FEM+@H*0F5S:61E<R!T:&4@9&EG<F%P:',@;&ES=&5D(&)E;&]W+"!M971A
- XM(&-H87)A8W1E<G,@8V%N(&)E(&5N=&5R960@=VET:"!#5%),+4L*/%-004-%
- XM/B![8VAA<GTN($]N;'D@15-#(&-A;FYO="!B92!U<V5D(&9O<B![8VAA<GTN
- XM(%5S92!#5%),+58@,34U(&9O<B!T:&ES+@H*5&AE(&9I<G-T('1W;R!C:&%R
- XM86-T97)S(&EN(&5A8V@@8V]L=6UN(&%R92!T:&4@8VAA<F%C=&5R<R!Y;W4@
- XM:&%V92!T;R!T>7!E('1O"F5N=&5R(&$@9&EG<F%P:"X*"DEN('1H92!M:61D
- XM;&4@;V8@96%C:"!C;VQU;6X@:7,@=&AE(')E<W5L=&EN9R!C:&%R86-T97(N
- XM(%1H:7,@;6%Y(&)E(&UA;F=L960*:68@>6]U(&QO;VL@870@=&AI<R!F:6QE
- XM(&]N('-O;65T:&EN9R!E;'-E('1H86X@=&AE('-Y<W1E;2!T:&%T('1H97D@
- XM=V5R90IM96%N="!F;W(@;W(@=VAE;B!Y;W4@<')I;G0@:70N"@I4:&4@9&5C
- XM:6UA;"!N=6UB97(@:7,@=&AE($%30TE)(&-O9&4@9F]R('1H92!C:&%R86-T
- XM97(N"@I$969A=6QT(&1I9W)A<&AS(&]N('1H92!!;6EG83H*?B$@H2 Q-C$@
- XM("!C?""B(#$V,B @("0D(*,@,38S(" @;W@@I" Q-C0@("!9+2"E(#$V-2 @
- XM('Q\(*8@,38V(" @<&$@IR Q-C<*(B(@J" Q-C@@("!C3R"I(#$V.2 @(&$M
- XM(*H@,3<P(" @/#P@JR Q-S$@(" M+2"M(#$W,R @(')/(*X@,3<T(" @+3T@
- XMKR Q-S4*?F\@L" Q-S8@(" K+2"Q(#$W-R @(#(R(+(@,3<X(" @,S,@LR Q
- XM-SD@(" G)R"T(#$X," @(&IU(+4@,3@Q(" @<' @MB Q.#(*?BX@MR Q.#,@
- XM(" L+""X(#$X-" @(#$Q(+D@,3@U(" @;RT@NB Q.#8@(" ^/B"[(#$X-R @
- XM(#$T(+P@,3@X(" @,3(@O2 Q.#D*,S0@OB Q.3 @("!^/R"_(#$Y,2 @($%@
- XM(, @,3DR(" @02<@P2 Q.3,@("!!7B#"(#$Y-" @($%^(,,@,3DU(" @02(@
- XMQ" Q.38*04 @Q2 Q.3<@("!!12#&(#$Y." @($,L(,<@,3DY(" @16 @R" R
- XM,# @("!%)R#)(#(P,2 @($5>(,H@,C R(" @12(@RR R,#,*26 @S" R,#0@
- XM("!))R#-(#(P-2 @($E>(,X@,C V(" @22(@SR R,#<@(" M1"#0(#(P." @
- XM($Y^(-$@,C Y(" @3V @TB R,3 *3R<@TR R,3$@("!/7B#4(#(Q,B @($]^
- XM(-4@,C$S(" @3R(@UB R,30@(" O7"#7(#(Q-2 @($\O(-@@,C$V(" @56 @
- XMV2 R,3<*52<@VB R,3@@("!57B#;(#(Q.2 @(%4B(-P@,C(P(" @62<@W2 R
- XM,C$@("!)<"#>(#(R,B @('-S(-\@,C(S(" @86 @X" R,C0*82<@X2 R,C4@
- XM("!A7B#B(#(R-B @(&%^(.,@,C(W(" @82(@Y" R,C@@("!A0"#E(#(R.2 @
- XM(&%E(.8@,C,P(" @8RP@YR R,S$*96 @Z" R,S(@("!E)R#I(#(S,R @(&5>
- XM(.H@,C,T(" @92(@ZR R,S4@("!I8"#L(#(S-B @(&DG(.T@,C,W(" @:5X@
- XM[B R,S@*:2(@[R R,SD@(" M9"#P(#(T," @(&Y^(/$@,C0Q(" @;V @\B R
- XM-#(@("!O)R#S(#(T,R @(&]>(/0@,C0T(" @;WX@]2 R-#4*;R(@]B R-#8@
- XM(" Z+2#W(#(T-R @(&\O(/@@,C0X(" @=6 @^2 R-#D@("!U)R#Z(#(U," @
- XM('5>(/L@,C4Q(" @=2(@_" R-3(*>2<@_2 R-3,@("!I<"#^(#(U-" @('DB
- XM(/\@,C4U"@I$969A=6QT(&1I9W)A<&AS(&]N($U31$]3.@I#+"" (#$R." @
- XM('4B(($@,3(Y(" @92<@@B Q,S @("!A7B"#(#$S,2 @(&$B((0@,3,R(" @
- XM86 @A2 Q,S,@("!A0""&(#$S- IC+""'(#$S-2 @(&5>((@@,3,V(" @92(@
- XMB2 Q,S<@("!E8""*(#$S." @(&DB((L@,3,Y(" @:5X@C" Q-# @("!I8""-
- XM(#$T,0I!(B".(#$T,B @($% ((\@,30S(" @12<@D" Q-#0@("!A92"1(#$T
- XM-2 @($%%()(@,30V(" @;UX@DR Q-#<@("!O(B"4(#$T. IO8""5(#$T.2 @
- XM('5>()8@,34P(" @=6 @ER Q-3$@("!Y(B"8(#$U,B @($\B()D@,34S(" @
- XM52(@FB Q-30@("!C?"";(#$U-0HD)""<(#$U-B @(%DM()T@,34W(" @4'0@
- XMGB Q-3@@("!F9B"?(#$U.2 @(&$G(* @,38P(" @:2<@H2 Q-C$@("!O)R"B
- XM(#$V,@IU)R"C(#$V,R @(&Y^(*0@,38T(" @3GX@I2 Q-C4@("!A82"F(#$V
- XM-B @(&]O(*<@,38W(" @?C\@J" Q-C@@(" M82"I(#$V.0IA+2"J(#$W," @
- XM(#$R(*L@,3<Q(" @,30@K" Q-S(@("!^(2"M(#$W,R @(#P\(*X@,3<T(" @
- XM/CX@KR Q-S4@("!S<R#A(#(R-0IJ=2#F(#(S," @(&\O(.T@,C,W(" @*RT@
- XM\2 R-#$@(" ^/2#R(#(T,B @(#P](/,@,C0S(" @.BT@]B R-#8@("!^?B#W
- X9(#(T-PI^;R#X(#(T." @(#(R(/T@,C4S"C0S
- X
- Xend
- END_OF_FILE
- if test 3112 -ne `wc -c <'vim/doc/digraph.doc.UU'`; then
- echo shar: \"'vim/doc/digraph.doc.UU'\" unpacked with wrong size!
- else
- echo shar: Uudecoding \"'vim/doc/digraph.doc'\" \(2230 characters\)
- cat vim/doc/digraph.doc.UU | uudecode
- if test 2230 -ne `wc -c <'vim/doc/digraph.doc'`; then
- echo shar: \"'vim/doc/digraph.doc'\" uudecoded with wrong size!
- else
- rm vim/doc/digraph.doc.UU
- fi
- fi
- # end of 'vim/doc/digraph.doc.UU'
- fi
- if test -f 'vim/src/misccmds.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vim/src/misccmds.c'\"
- else
- echo shar: Extracting \"'vim/src/misccmds.c'\" \(20128 characters\)
- sed "s/^X//" >'vim/src/misccmds.c' <<'END_OF_FILE'
- X/* vi:ts=4:sw=4
- X *
- X * VIM - Vi IMproved by Bram Moolenaar
- X *
- X * Read the file "credits.txt" for a list of people who contributed.
- X * Read the file "uganda.txt" for copying and usage conditions.
- X */
- X
- X/*
- X * misccmds.c: functions that didn't seem to fit elsewhere
- X */
- X
- X#include "vim.h"
- X#include "globals.h"
- X#include "proto.h"
- X#include "param.h"
- X
- Xstatic void check_status __ARGS((BUF *));
- X
- Xstatic char_u *(si_tab[]) = {(char_u *)"if", (char_u *)"else", (char_u *)"while", (char_u *)"for", (char_u *)"do"};
- X
- X/*
- X * count the size of the indent in the current line
- X */
- X int
- Xget_indent()
- X{
- X register char_u *ptr;
- X register int count = 0;
- X
- X for (ptr = ml_get(curwin->w_cursor.lnum); *ptr; ++ptr)
- X {
- X if (*ptr == TAB) /* count a tab for what it is worth */
- X count += (int)curbuf->b_p_ts - (count % (int)curbuf->b_p_ts);
- X else if (*ptr == ' ')
- X ++count; /* count a space for one */
- X else
- X break;
- X }
- X return (count);
- X}
- X
- X/*
- X * set the indent of the current line
- X * leaves the cursor on the first non-blank in the line
- X */
- X void
- Xset_indent(size, delete)
- X register int size;
- X int delete;
- X{
- X int oldstate = State;
- X register int c;
- X
- X State = INSERT; /* don't want REPLACE for State */
- X curwin->w_cursor.col = 0;
- X if (delete) /* delete old indent */
- X {
- X while ((c = gchar_cursor()), iswhite(c))
- X (void)delchar(FALSE);
- X }
- X if (!curbuf->b_p_et) /* if 'expandtab' is set, don't use TABs */
- X while (size >= (int)curbuf->b_p_ts)
- X {
- X inschar(TAB);
- X size -= (int)curbuf->b_p_ts;
- X }
- X while (size)
- X {
- X inschar(' ');
- X --size;
- X }
- X State = oldstate;
- X}
- X
- X/*
- X * Opencmd
- X *
- X * Add a blank line below or above the current line.
- X *
- X * Return TRUE for success, FALSE for failure
- X */
- X
- X int
- XOpencmd(dir, redraw, delspaces)
- X int dir;
- X int redraw;
- X int delspaces;
- X{
- X char_u *ptr, *p_extra;
- X FPOS old_cursor; /* old cursor position */
- X int newcol = 0; /* new cursor column */
- X int newindent = 0; /* auto-indent of the new line */
- X int n;
- X int truncate = FALSE; /* truncate current line afterwards */
- X int no_si = FALSE; /* reset did_si afterwards */
- X int retval = FALSE; /* return value, default is FAIL */
- X
- X ptr = strsave(ml_get(curwin->w_cursor.lnum));
- X if (ptr == NULL) /* out of memory! */
- X return FALSE;
- X
- X u_clearline(); /* cannot do "U" command when adding lines */
- X did_si = FALSE;
- X if (curbuf->b_p_ai || curbuf->b_p_si)
- X {
- X /*
- X * count white space on current line
- X */
- X newindent = get_indent();
- X if (newindent == 0)
- X newindent = old_indent; /* for ^^D command in insert mode */
- X old_indent = 0;
- X
- X /*
- X * If we just did an auto-indent, then we didn't type anything on the
- X * prior line, and it should be truncated.
- X */
- X if (dir == FORWARD && did_ai)
- X truncate = TRUE;
- X else if (curbuf->b_p_si && *ptr != NUL)
- X {
- X char_u *p;
- X char_u *pp;
- X int i, save;
- X
- X if (dir == FORWARD)
- X {
- X p = ptr + STRLEN(ptr) - 1;
- X while (p > ptr && isspace(*p)) /* find last non-blank in line */
- X --p;
- X if (*p == '{') /* line ends in '{': do indent */
- X {
- X did_si = TRUE;
- X no_si = TRUE;
- X }
- X else /* look for "if" and the like */
- X {
- X p = ptr;
- X skipspace(&p);
- X for (pp = p; islower(*pp); ++pp)
- X ;
- X if (!isidchar(*pp)) /* careful for vars starting with "if" */
- X {
- X save = *pp;
- X *pp = NUL;
- X for (i = sizeof(si_tab)/sizeof(char_u *); --i >= 0; )
- X if (STRCMP(p, si_tab[i]) == 0)
- X {
- X did_si = TRUE;
- X break;
- X }
- X *pp = save;
- X }
- X }
- X }
- X else
- X {
- X p = ptr;
- X skipspace(&p);
- X if (*p == '}') /* if line starts with '}': do indent */
- X did_si = TRUE;
- X }
- X }
- X did_ai = TRUE;
- X if (curbuf->b_p_si)
- X can_si = TRUE;
- X }
- X if (State == INSERT || State == REPLACE) /* only when dir == FORWARD */
- X {
- X p_extra = ptr + curwin->w_cursor.col;
- X if (curbuf->b_p_ai && delspaces)
- X skipspace(&p_extra);
- X if (*p_extra != NUL)
- X did_ai = FALSE; /* append some text, don't trucate now */
- X }
- X else
- X p_extra = (char_u *)""; /* append empty line */
- X
- X old_cursor = curwin->w_cursor;
- X if (dir == BACKWARD)
- X --curwin->w_cursor.lnum;
- X if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_t)0, FALSE) == FAIL)
- X goto theend;
- X mark_adjust(curwin->w_cursor.lnum + 1, MAXLNUM, 1L);
- X if (newindent || did_si)
- X {
- X ++curwin->w_cursor.lnum;
- X if (did_si)
- X {
- X if (p_sr)
- X newindent -= newindent % (int)curbuf->b_p_sw;
- X newindent += (int)curbuf->b_p_sw;
- X }
- X set_indent(newindent, FALSE);
- X newcol = curwin->w_cursor.col;
- X if (no_si)
- X did_si = FALSE;
- X }
- X curwin->w_cursor = old_cursor;
- X
- X if (dir == FORWARD)
- X {
- X if (truncate || State == INSERT || State == REPLACE)
- X {
- X if (truncate)
- X *ptr = NUL;
- X else
- X *(ptr + curwin->w_cursor.col) = NUL; /* truncate current line at cursor */
- X ml_replace(curwin->w_cursor.lnum, ptr, FALSE);
- X ptr = NULL;
- X }
- X
- X /*
- X * Get the cursor to the start of the line, so that 'curwin->w_row' gets
- X * set to the right physical line number for the stuff that
- X * follows...
- X */
- X curwin->w_cursor.col = 0;
- X
- X if (redraw)
- X {
- X n = RedrawingDisabled;
- X RedrawingDisabled = TRUE;
- X cursupdate(); /* don't want it to update srceen */
- X RedrawingDisabled = n;
- X
- X /*
- X * If we're doing an open on the last logical line, then go ahead and
- X * scroll the screen up. Otherwise, just insert a blank line at the
- X * right place. We use calls to plines() in case the cursor is
- X * resting on a long line.
- X */
- X n = curwin->w_row + plines(curwin->w_cursor.lnum);
- X if (n == curwin->w_height)
- X scrollup(1L);
- X else
- X win_ins_lines(curwin, n, 1, TRUE, TRUE);
- X }
- X ++curwin->w_cursor.lnum; /* cursor moves down */
- X }
- X else if (redraw) /* insert physical line above current line */
- X win_ins_lines(curwin, curwin->w_row, 1, TRUE, TRUE);
- X
- X curwin->w_cursor.col = newcol;
- X if (redraw)
- X {
- X updateScreen(VALID_TO_CURSCHAR);
- X cursupdate(); /* update curwin->w_row */
- X }
- X CHANGED;
- X
- X retval = TRUE; /* success! */
- Xtheend:
- X free(ptr);
- X return retval;
- X}
- X
- X/*
- X * plines(p) - return the number of physical screen lines taken by line 'p'
- X */
- X int
- Xplines(p)
- X linenr_t p;
- X{
- X return plines_win(curwin, p);
- X}
- X
- X int
- Xplines_win(wp, p)
- X WIN *wp;
- X linenr_t p;
- X{
- X register long col = 0;
- X register char_u *s;
- X register int lines;
- X
- X if (!wp->w_p_wrap)
- X return 1;
- X
- X s = ml_get_buf(wp->w_buffer, p, FALSE);
- X if (*s == NUL) /* empty line */
- X return 1;
- X
- X while (*s != NUL)
- X col += chartabsize(*s++, col);
- X
- X /*
- X * If list mode is on, then the '$' at the end of the line takes up one
- X * extra column.
- X */
- X if (wp->w_p_list)
- X col += 1;
- X
- X /*
- X * If 'number' mode is on, add another 8.
- X */
- X if (wp->w_p_nu)
- X col += 8;
- X
- X lines = (col + (Columns - 1)) / Columns;
- X if (lines <= wp->w_height)
- X return lines;
- X return (int)(wp->w_height); /* maximum length */
- X}
- X
- X/*
- X * Count the physical lines (rows) for the lines "first" to "last" inclusive.
- X */
- X int
- Xplines_m(first, last)
- X linenr_t first, last;
- X{
- X return plines_m_win(curwin, first, last);
- X}
- X
- X int
- Xplines_m_win(wp, first, last)
- X WIN *wp;
- X linenr_t first, last;
- X{
- X int count = 0;
- X
- X while (first <= last)
- X count += plines_win(wp, first++);
- X return (count);
- X}
- X
- X/*
- X * insert or replace a single character at the cursor position
- X */
- X void
- Xinschar(c)
- X int c;
- X{
- X register char_u *p;
- X int rir0; /* reverse replace in column 0 */
- X char_u *new;
- X char_u *old;
- X int oldlen;
- X int extra;
- X colnr_t col = curwin->w_cursor.col;
- X linenr_t lnum = curwin->w_cursor.lnum;
- X
- X old = ml_get(lnum);
- X oldlen = STRLEN(old) + 1;
- X
- X rir0 = (State == REPLACE && p_ri && col == 0);
- X if (rir0 || State != REPLACE || *(old + col) == NUL)
- X extra = 1;
- X else
- X extra = 0;
- X
- X new = alloc((unsigned)(oldlen + extra));
- X if (new == NULL)
- X return;
- X memmove((char *)new, (char *)old, (size_t)col);
- X p = new + col;
- X memmove((char *)p + extra, (char *)old + col, (size_t)(oldlen - col));
- X if (rir0) /* reverse replace in column 0 */
- X {
- X *(p + 1) = c; /* replace the char that was in column 0 */
- X c = ' '; /* insert a space */
- X extraspace = TRUE;
- X }
- X *p = c;
- X ml_replace(lnum, new, FALSE);
- X
- X /*
- X * If we're in insert mode and showmatch mode is set, then check for
- X * right parens and braces. If there isn't a match, then beep. If there
- X * is a match AND it's on the screen, then flash to it briefly. If it
- X * isn't on the screen, don't do anything.
- X */
- X if (p_sm && State == INSERT && (c == ')' || c == '}' || c == ']'))
- X {
- X FPOS *lpos, csave;
- X
- X if ((lpos = showmatch(NUL)) == NULL) /* no match, so beep */
- X beep();
- X else if (lpos->lnum >= curwin->w_topline)
- X {
- X updateScreen(VALID_TO_CURSCHAR); /* show the new char first */
- X csave = curwin->w_cursor;
- X curwin->w_cursor = *lpos; /* move to matching char */
- X cursupdate();
- X showruler(0);
- X setcursor();
- X cursor_on(); /* make sure that the cursor is shown */
- X flushbuf();
- X vim_delay(); /* brief pause */
- X curwin->w_cursor = csave; /* restore cursor position */
- X cursupdate();
- X }
- X }
- X if (!p_ri) /* normal insert: cursor right */
- X ++curwin->w_cursor.col;
- X else if (State == REPLACE && !rir0) /* reverse replace mode: cursor left */
- X --curwin->w_cursor.col;
- X CHANGED;
- X}
- X
- X/*
- X * insert a string at the cursor position
- X */
- X void
- Xinsstr(s)
- X register char_u *s;
- X{
- X register char_u *old, *new;
- X register int newlen = STRLEN(s);
- X int oldlen;
- X colnr_t col = curwin->w_cursor.col;
- X linenr_t lnum = curwin->w_cursor.lnum;
- X
- X old = ml_get(lnum);
- X oldlen = STRLEN(old);
- X new = alloc((unsigned)(oldlen + newlen + 1));
- X if (new == NULL)
- X return;
- X memmove((char *)new, (char *)old, (size_t)col);
- X memmove((char *)new + col, (char *)s, (size_t)newlen);
- X memmove((char *)new + col + newlen, (char *)old + col, (size_t)(oldlen - col + 1));
- X ml_replace(lnum, new, FALSE);
- X curwin->w_cursor.col += newlen;
- X CHANGED;
- X}
- X
- X/*
- X * delete one character under the cursor
- X *
- X * return FAIL for failure, OK otherwise
- X */
- X int
- Xdelchar(fixpos)
- X int fixpos; /* if TRUE fix the cursor position when done */
- X{
- X char_u *old, *new;
- X int oldlen;
- X linenr_t lnum = curwin->w_cursor.lnum;
- X colnr_t col = curwin->w_cursor.col;
- X int was_alloced;
- X
- X old = ml_get(lnum);
- X oldlen = STRLEN(old);
- X
- X if (col >= oldlen) /* can't do anything (happens with replace mode) */
- X return FAIL;
- X
- X/*
- X * If the old line has been allocated the deleteion can be done in the
- X * existing line. Otherwise a new line has to be allocated
- X */
- X was_alloced = ml_line_alloced(); /* check if old was allocated */
- X if (was_alloced)
- X new = old; /* use same allocated memory */
- X else
- X {
- X new = alloc((unsigned)oldlen); /* need to allocated a new line */
- X if (new == NULL)
- X return FAIL;
- X memmove((char *)new, (char *)old, (size_t)col);
- X }
- X memmove((char *)new + col, (char *)old + col + 1, (size_t)(oldlen - col));
- X if (!was_alloced)
- X ml_replace(lnum, new, FALSE);
- X
- X /*
- X * If we just took off the last character of a non-blank line, we don't
- X * want to end up positioned at the newline.
- X */
- X if (fixpos && curwin->w_cursor.col > 0 && col == oldlen - 1)
- X --curwin->w_cursor.col;
- X
- X CHANGED;
- X return OK;
- X}
- X
- X void
- Xdellines(nlines, dowindow, undo)
- X long nlines; /* number of lines to delete */
- X int dowindow; /* if true, update the window */
- X int undo; /* if true, prepare for undo */
- X{
- X int num_plines = 0;
- X
- X if (nlines <= 0)
- X return;
- X /*
- X * There's no point in keeping the window updated if we're deleting more
- X * than a window's worth of lines.
- X */
- X if (nlines > (curwin->w_height - curwin->w_row) && dowindow)
- X {
- X dowindow = FALSE;
- X /* flaky way to clear rest of window */
- X win_del_lines(curwin, curwin->w_row, curwin->w_height, TRUE, TRUE);
- X }
- X if (undo && !u_savedel(curwin->w_cursor.lnum, nlines))
- X return;
- X
- X mark_adjust(curwin->w_cursor.lnum, curwin->w_cursor.lnum + nlines - 1, MAXLNUM);
- X mark_adjust(curwin->w_cursor.lnum + nlines, MAXLNUM, -nlines);
- X
- X while (nlines-- > 0)
- X {
- X if (bufempty()) /* nothing to delete */
- X break;
- X
- X /*
- X * Set up to delete the correct number of physical lines on the
- X * window
- X */
- X if (dowindow)
- X num_plines += plines(curwin->w_cursor.lnum);
- X
- X ml_delete(curwin->w_cursor.lnum);
- X
- X CHANGED;
- X
- X /* If we delete the last line in the file, stop */
- X if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
- X {
- X curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- X break;
- X }
- X }
- X curwin->w_cursor.col = 0;
- X /*
- X * Delete the correct number of physical lines on the window
- X */
- X if (dowindow && num_plines > 0)
- X win_del_lines(curwin, curwin->w_row, num_plines, TRUE, TRUE);
- X}
- X
- X int
- Xgchar(pos)
- X FPOS *pos;
- X{
- X return (int)(*(ml_get_pos(pos)));
- X}
- X
- X int
- Xgchar_cursor()
- X{
- X return (int)(*(ml_get_cursor()));
- X}
- X
- X/*
- X * Write a character at the current cursor position.
- X * It is directly written into the block.
- X */
- X void
- Xpchar_cursor(c)
- X int c;
- X{
- X *(ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE) + curwin->w_cursor.col) = c;
- X}
- X
- X/*
- X * return TRUE if the cursor is before or on the first non-blank in the line
- X */
- X int
- Xinindent()
- X{
- X register char_u *ptr;
- X register int col;
- X
- X for (col = 0, ptr = ml_get(curwin->w_cursor.lnum); iswhite(*ptr); ++col)
- X ++ptr;
- X if (col >= curwin->w_cursor.col)
- X return TRUE;
- X else
- X return FALSE;
- X}
- X
- X/*
- X * skipspace: skip over ' ' and '\t'.
- X *
- X * note: you must give a pointer to a char_u pointer!
- X */
- X void
- Xskipspace(pp)
- X char_u **pp;
- X{
- X register char_u *p;
- X
- X for (p = *pp; *p == ' ' || *p == '\t'; ++p) /* skip to next non-white */
- X ;
- X *pp = p;
- X}
- X
- X/*
- X * skiptospace: skip over text until ' ' or '\t'.
- X *
- X * note: you must give a pointer to a char_u pointer!
- X */
- X void
- Xskiptospace(pp)
- X char_u **pp;
- X{
- X register char_u *p;
- X
- X for (p = *pp; *p != ' ' && *p != '\t' && *p != NUL; ++p)
- X ;
- X *pp = p;
- X}
- X
- X/*
- X * skiptodigit: skip over text until digit found
- X *
- X * note: you must give a pointer to a char_u pointer!
- X */
- X void
- Xskiptodigit(pp)
- X char_u **pp;
- X{
- X register char_u *p;
- X
- X for (p = *pp; !isdigit(*p) && *p != NUL; ++p)
- X ;
- X *pp = p;
- X}
- X
- X/*
- X * getdigits: get a number from a string and skip over it
- X *
- X * note: you must give a pointer to a char_u pointer!
- X */
- X
- X long
- Xgetdigits(pp)
- X char_u **pp;
- X{
- X register char_u *p;
- X long retval;
- X
- X p = *pp;
- X retval = atol((char *)p);
- X while (isdigit(*p)) /* skip to next non-digit */
- X ++p;
- X *pp = p;
- X return retval;
- X}
- X
- X char_u *
- Xplural(n)
- X long n;
- X{
- X static char_u buf[2] = "s";
- X
- X if (n == 1)
- X return &(buf[1]);
- X return &(buf[0]);
- X}
- X
- X/*
- X * set_Changed is called when something in the current buffer is changed
- X */
- X void
- Xset_Changed()
- X{
- X if (!curbuf->b_changed)
- X {
- X change_warning();
- X curbuf->b_changed = TRUE;
- X check_status(curbuf);
- X }
- X}
- X
- X/*
- X * unset_Changed is called when the changed flag must be reset for buffer 'buf'
- X */
- X void
- Xunset_Changed(buf)
- X BUF *buf;
- X{
- X if (buf->b_changed)
- X {
- X buf->b_changed = 0;
- X check_status(buf);
- X }
- X}
- X
- X/*
- X * check_status: called when the status bars for the buffer 'buf'
- X * need to be updated
- X */
- X static void
- Xcheck_status(buf)
- X BUF *buf;
- X{
- X WIN *wp;
- X int i;
- X
- X i = 0;
- X for (wp = firstwin; wp != NULL; wp = wp->w_next)
- X if (wp->w_buffer == buf && wp->w_status_height)
- X {
- X wp->w_redr_status = TRUE;
- X ++i;
- X }
- X if (i && must_redraw < NOT_VALID) /* redraw later */
- X must_redraw = NOT_VALID;
- X}
- X
- X/*
- X * If the file is readonly, give a warning message with the first change.
- X * Don't use emsg(), because it flushes the macro buffer.
- X * If we have undone all changes b_changed will be FALSE, but b_did_warn
- X * will be TRUE.
- X */
- X void
- Xchange_warning()
- X{
- X if (curbuf->b_did_warn == FALSE && curbuf->b_changed == 0 && curbuf->b_p_ro)
- X {
- X curbuf->b_did_warn = TRUE;
- X MSG("Warning: Changing a readonly file");
- X sleep(1); /* give him some time to think about it */
- X }
- X}
- X
- X/*
- X * ask for a reply from the user, a 'y' or a 'n'.
- X * No other characters are accepted, the message is repeated until a valid
- X * reply is entered or CTRL-C is hit.
- X *
- X * return the 'y' or 'n'
- X */
- X int
- Xask_yesno(str)
- X char_u *str;
- X{
- X int r = ' ';
- X
- X while (r != 'y' && r != 'n')
- X {
- X (void)set_highlight('r'); /* same highlighting as for wait_return */
- X msg_highlight = TRUE;
- X smsg((char_u *)"%s (y/n)?", str);
- X r = vgetc();
- X if (r == Ctrl('C'))
- X r = 'n';
- X msg_outchar(r); /* show what you typed */
- X flushbuf();
- X }
- X return r;
- X}
- X
- X void
- Xmsgmore(n)
- X long n;
- X{
- X long pn;
- X
- X if (global_busy) /* no messages now, wait until global is finished */
- X return;
- X
- X if (n > 0)
- X pn = n;
- X else
- X pn = -n;
- X
- X if (pn > p_report)
- X smsg((char_u *)"%ld %s line%s %s", pn, n > 0 ? "more" : "fewer", plural(pn),
- X got_int ? "(Interrupted)" : "");
- X}
- X
- X/*
- X * give a warning for an error
- X */
- X void
- Xbeep()
- X{
- X flush_buffers(FALSE); /* flush internal buffers */
- X if (p_vb)
- X {
- X if (T_VB && *T_VB)
- X outstr(T_VB);
- X else
- X { /* very primitive visual bell */
- X MSG(" ^G");
- X MSG(" ^G");
- X MSG(" ^G ");
- X MSG(" ^G");
- X MSG(" ");
- X showmode(); /* may have deleted the mode message */
- X }
- X }
- X else
- X outchar('\007');
- X}
- X
- X/*
- X * Expand environment variable with path name.
- X * "~/" is also expanded, like $HOME.
- X * If anything fails no expansion is done and dst equals src.
- X */
- X void
- Xexpand_env(src, dst, dstlen)
- X char_u *src; /* input string e.g. "$HOME/vim.hlp" */
- X char_u *dst; /* where to put the result */
- X int dstlen; /* maximum length of the result */
- X{
- X char_u *tail;
- X int c;
- X char_u *var;
- X
- X if (*src == '$' || (*src == '~' && STRCHR("/ \t\n", src[1]) != NULL))
- X {
- X/*
- X * The variable name is copied into dst temporarily, because it may be
- X * a string in read-only memory.
- X */
- X if (*src == '$')
- X {
- X tail = src + 1;
- X var = dst;
- X c = dstlen - 1;
- X while (c-- > 0 && *tail && isidchar(*tail))
- X *var++ = *tail++;
- X *var = NUL;
- X/*
- X * It is possible that vimgetenv() uses IObuff for the expansion, and that the
- X * 'dst' is also IObuff. This works, as long as 'var' is the first to be copied
- X * to 'dst'!
- X */
- X var = vimgetenv(dst);
- X }
- X else
- X {
- X var = vimgetenv((char_u *)"HOME");
- X tail = src + 1;
- X }
- X if (var && (STRLEN(var) + STRLEN(tail) + 1 < (unsigned)dstlen))
- X {
- X STRCPY(dst, var);
- X STRCAT(dst, tail);
- X return;
- X }
- X }
- X STRNCPY(dst, src, (size_t)dstlen);
- X}
- X
- X/*
- X * Replace home directory by "~/"
- X * If anything fails dst equals src.
- X */
- X void
- Xhome_replace(src, dst, dstlen)
- X char_u *src; /* input file name */
- X char_u *dst; /* where to put the result */
- X int dstlen; /* maximum length of the result */
- X{
- X char_u *home;
- X size_t len;
- X
- X /*
- X * If there is no "HOME" environment variable, or when it
- X * is very short, don't replace anything.
- X */
- X if ((home = vimgetenv((char_u *)"HOME")) == NULL || (len = STRLEN(home)) <= 1)
- X STRNCPY(dst, src, (size_t)dstlen);
- X else
- X {
- X skipspace(&src);
- X while (*src && dstlen > 0)
- X {
- X if (STRNCMP(src, home, len) == 0)
- X {
- X src += len;
- X if (--dstlen > 0)
- X *dst++ = '~';
- X }
- X while (*src && *src != ' ' && --dstlen > 0)
- X *dst++ = *src++;
- X while (*src == ' ' && --dstlen > 0)
- X *dst++ = *src++;
- X }
- X *dst = NUL;
- X }
- X}
- X
- X/*
- X * Compare two file names and return TRUE if they are different files.
- X * For the first name environment variables are expanded
- X */
- X int
- Xfullpathcmp(s1, s2)
- X char_u *s1, *s2;
- X{
- X#ifdef UNIX
- X struct stat st1, st2;
- X char_u buf1[MAXPATHL];
- X
- X expand_env(s1, buf1, MAXPATHL);
- X if (stat((char *)buf1, &st1) == 0 && stat((char *)s2, &st2) == 0 &&
- X st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
- X return FALSE;
- X return TRUE;
- X#else
- X char_u buf1[MAXPATHL];
- X char_u buf2[MAXPATHL];
- X
- X expand_env(s1, buf2, MAXPATHL);
- X if (FullName(buf2, buf1, MAXPATHL) == OK && FullName(s2, buf2, MAXPATHL) == OK)
- X return STRCMP(buf1, buf2);
- X /*
- X * one of the FullNames() failed, file probably doesn't exist.
- X */
- X return TRUE;
- X#endif
- X}
- X
- X/*
- X * get the tail of a path: the file name.
- X */
- X char_u *
- Xgettail(fname)
- X char_u *fname;
- X{
- X register char_u *p1, *p2;
- X
- X for (p1 = p2 = fname; *p2; ++p2) /* find last part of path */
- X {
- X if (ispathsep(*p2))
- X p1 = p2 + 1;
- X }
- X return p1;
- X}
- X
- X/*
- X * return TRUE if 'c' is a path separator.
- X */
- X int
- Xispathsep(c)
- X int c;
- X{
- X#ifdef UNIX
- X return (c == PATHSEP); /* UNIX has ':' inside file names */
- X#else
- X# ifdef MSDOS
- X return (c == ':' || c == PATHSEP || c == '/');
- X# else
- X return (c == ':' || c == PATHSEP);
- X# endif
- X#endif
- X}
- END_OF_FILE
- if test 20128 -ne `wc -c <'vim/src/misccmds.c'`; then
- echo shar: \"'vim/src/misccmds.c'\" unpacked with wrong size!
- fi
- # end of 'vim/src/misccmds.c'
- fi
- 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'\" \(41440 characters\)
- sed "s/^X//" >'vim/src/normal.c' <<'END_OF_FILE'
- X/* vi:ts=4:sw=4
- X *
- X * VIM - Vi IMproved by Bram Moolenaar
- X *
- X * Read the file "credits.txt" for a list of people who contributed.
- X * Read the file "uganda.txt" for copying and usage conditions.
- 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 * 13. Window commands (^W)
- X * 14. extended commands (starting with 'g')
- X */
- X
- X void
- Xnormal()
- X{
- X register int c;
- X long n;
- X int flag = FALSE;
- X int flag2 = FALSE;
- X int type = 0; /* type of operation */
- X int dir = FORWARD; /* search direction */
- X int nchar = NUL;
- X int finish_op;
- X linenr_t Prenum1;
- X char_u searchbuff[CMDBUFFSIZE];/* buffer for search string */
- X FPOS *pos = NULL; /* init for gcc */
- X register char_u *ptr;
- X int command_busy = FALSE;
- X static int didwarn = FALSE; /* warned for broken inversion */
- X int modified = FALSE; /* changed current buffer */
- X int ctrl_w = FALSE; /* got CTRL-W command */
- 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 static long redo_Visual_Prenum; /* Prenum for operator */
- 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
- Xgetcount:
- 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(ctrl_w ? Ctrl('W') : ' ', NUL);
- X c = vgetc();
- X }
- X
- X/*
- X * If we got CTRL-W there may be a/another count
- X */
- X if (c == Ctrl('W') && !ctrl_w)
- X {
- X ctrl_w = TRUE;
- X opnum = Prenum; /* remember first count */
- X Prenum = 0;
- X State = ONLYKEY; /* no mapping for nchar, but keys */
- X premsg(c, NUL);
- X c = vgetc(); /* get next character */
- X goto getcount; /* jump back */
- 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 * for CTRL-W we already got it when looking for a count
- X */
- X if (ctrl_w)
- X {
- X nchar = c;
- X c = Ctrl('W');
- X premsg(c, nchar);
- X }
- X else if (strchr("@zZtTfF[]mg'`\"", 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/*
- X * For commands that don't get another character we can put the State back to
- X * NORMAL and check for a window size change.
- X */
- X if (STRCHR("z:/?", c) == NULL)
- X State = NORMAL;
- 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) == FAIL)
- X CLEAROPBEEP;
- X break;
- X
- X case '@': /* execute a named buffer */
- X CHECKCLEAROP;
- X while (Prenum1--)
- X {
- X if (doexecbuf(nchar) == FAIL)
- X {
- X CLEAROPBEEP;
- X break;
- X }
- 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 curwin->w_p_scroll = (Prenum > curwin->w_height) ? curwin->w_height : Prenum;
- X n = (curwin->w_p_scroll <= curwin->w_height) ? curwin->w_p_scroll : curwin->w_height;
- X if (flag)
- X {
- X curwin->w_topline += n;
- X if (curwin->w_topline > curbuf->b_ml.ml_line_count)
- X curwin->w_topline = curbuf->b_ml.ml_line_count;
- X comp_Botline(curwin); /* compute curwin->w_botline */
- X (void)onedown(n);
- X }
- X else
- X {
- X if (n >= curwin->w_cursor.lnum)
- X n = curwin->w_cursor.lnum - 1;
- X Prenum1 = curwin->w_cursor.lnum - n;
- X scrolldown(n);
- X if (Prenum1 < curwin->w_cursor.lnum)
- X curwin->w_cursor.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 (void)onepage(dir, Prenum1);
- X break;
- X
- X case Ctrl('E'):
- X CHECKCLEAROP;
- X scrollup(Prenum1);
- X /* We may have moved to another line -- webb */
- X coladvance(curwin->w_curswant);
- X updateScreen(VALID);
- X break;
- X
- X case Ctrl('Y'):
- X CHECKCLEAROP;
- X scrolldown(Prenum1);
- X /* We may have moved to another line -- webb */
- X coladvance(curwin->w_curswant);
- 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 if (nchar == DEL)
- X Prenum /= 10;
- X else if (isdigit(nchar))
- X Prenum = Prenum * 10 + (nchar - '0');
- X else if (nchar == CR)
- X {
- X win_setheight((int)Prenum);
- X break;
- X }
- X else
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X }
- X operator = NOP;
- X break;
- X }
- X
- X if (Prenum && Prenum != curwin->w_cursor.lnum) /* line number given */
- X {
- X setpcmark();
- X if (Prenum > curbuf->b_ml.ml_line_count)
- X curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- X else
- X curwin->w_cursor.lnum = Prenum;
- X }
- X State = NORMAL; /* for updateScreen() */
- X switch (nchar)
- X {
- X case NL: /* put curwin->w_cursor at top of screen */
- X case CR:
- X beginline(TRUE);
- X case 't':
- X curwin->w_topline = curwin->w_cursor.lnum;
- X break;
- X
- X case '.': /* put curwin->w_cursor in middle of screen */
- X case 'z':
- X n = (curwin->w_height + plines(curwin->w_cursor.lnum)) / 2;
- X goto dozcmd;
- X
- X case '-': /* put curwin->w_cursor at bottom of screen */
- X case 'b':
- X n = curwin->w_height;
- X /* FALLTHROUGH */
- X
- X dozcmd:
- X {
- X register linenr_t lp = curwin->w_cursor.lnum;
- X register long l = plines(lp);
- X
- X do
- X {
- X curwin->w_topline = lp;
- X if (--lp == 0)
- X break;
- X l += plines(lp);
- X } while (l <= n);
- X }
- X if (nchar != 'z' && nchar != 'b')
- X beginline(TRUE);
- X break;
- X
- X case Ctrl('S'): /* ignore CTRL-S and CTRL-Q to avoid problems */
- X case Ctrl('Q'): /* with terminals that use xon/xoff */
- X break;
- X
- X default:
- X CLEAROPBEEP;
- X }
- X updateScreen(VALID);
- X break;
- X
- X/*
- X * 2: Control commands
- X */
- X case ':':
- X if (VIsual.lnum)
- X goto dooperator;
- X CHECKCLEAROP;
- X /*
- X * translate "count:" into ":.,.+(count - 1)"
- X */
- X if (Prenum)
- X {
- X stuffReadbuff((char_u *)".");
- X if (Prenum > 1)
- X {
- X stuffReadbuff((char_u *)",.+");
- X stuffnumReadbuff((long)Prenum - 1L);
- X }
- X }
- X docmdline(NULL);
- X modified = TRUE;
- 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: /* CTRL-^, short for ":e #" */
- X CHECKCLEAROPQ;
- X (void)buflist_getfile((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((char_u *)":x\n");
- X break;
- X
- X case Ctrl(']'): /* :ta to current identifier */
- X CHECKCLEAROPQ;
- X case '*': /* / to current identifier or string */
- X case '#': /* ? to current identifier or string */
- X case 'K': /* run program for current identifier */
- X {
- X register int col;
- X register int i;
- X
- X /*
- X * if i == 0: try to find an identifier
- X * if i == 1: try to find any string
- X */
- X ptr = ml_get(curwin->w_cursor.lnum);
- X for (i = 0; i < 2; ++i)
- X {
- X /*
- X * skip to start of identifier/string
- X */
- X col = curwin->w_cursor.col;
- X while (ptr[col] != NUL &&
- X (i == 0 ? !isidchar(ptr[col]) : iswhite(ptr[col])))
- X ++col;
- X
- X /*
- X * Back up to start of identifier/string. 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 && (i == 0 ? isidchar(ptr[col - 1]) :
- X (!iswhite(ptr[col - 1]) && !isidchar(ptr[col - 1]))))
- X --col;
- X
- X /*
- X * if identifier found or not '*' or '#' command, stop searching
- X */
- X if (isidchar(ptr[col]) || (c != '*' && c != '#'))
- X break;
- X }
- X /*
- X * did't find an identifier of string
- X */
- X if (ptr[col] == NUL || (!isidchar(ptr[col]) && i == 0))
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X
- X if (Prenum)
- X stuffnumReadbuff(Prenum);
- X switch (c)
- X {
- X case '*':
- X stuffReadbuff((char_u *)"/");
- X goto sow;
- X
- X case '#':
- X stuffReadbuff((char_u *)"?");
- Xsow: if (i == 0)
- X stuffReadbuff((char_u *)"\\<");
- X break;
- X
- X case 'K':
- X stuffReadbuff((char_u *)":! ");
- X stuffReadbuff(p_kp);
- X stuffReadbuff((char_u *)" ");
- X break;
- X default:
- X stuffReadbuff((char_u *)":ta ");
- X }
- X
- X /*
- X * Now grab the chars in the identifier
- X */
- X while (i == 0 ? isidchar(ptr[col]) :
- X (ptr[col] != NUL && !iswhite(ptr[col])))
- X {
- X stuffcharReadbuff(ptr[col]);
- X ++col;
- X }
- X if ((c == '*' || c == '#') && i == 0)
- X stuffReadbuff((char_u *)"\\>");
- X stuffReadbuff((char_u *)"\n");
- X }
- X break;
- X
- X case Ctrl('T'): /* backwards in tag stack */
- X CHECKCLEAROPQ;
- X dotag((char_u *)"", 2, (int)Prenum1);
- X break;
- X
- X/*
- X * Cursor motions
- X */
- X case 'G':
- X mtype = MLINE;
- X setpcmark();
- X if (Prenum == 0 || Prenum > curbuf->b_ml.ml_line_count)
- X curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- X else
- X curwin->w_cursor.lnum = Prenum;
- X beginline(TRUE);
- X break;
- X
- X case 'H':
- X case 'M':
- X if (c == 'M')
- X n = (curwin->w_height - curwin->w_empty_rows) / 2;
- X else
- X n = Prenum;
- X mtype = MLINE;
- X setpcmark();
- X curwin->w_cursor.lnum = curwin->w_topline;
- X while (n && onedown((long)1) == OK)
- X --n;
- X beginline(TRUE);
- X break;
- X
- X case 'L':
- X mtype = MLINE;
- X setpcmark();
- X curwin->w_cursor.lnum = curwin->w_botline - 1;
- X for (n = Prenum; n && oneup((long)1) == OK; 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() == FAIL)
- X {
- X /* space wraps to next line if 'whichwrap' bit 1 set */
- X /* 'l' wraps to next line if 'whichwrap' bit 2 set */
- X /* CURS_RIGHT wraps to next line if 'whichwrap' bit 3 set */
- X if (((c == ' ' && (p_ww & 2)) ||
- X (c == 'l' && (p_ww & 4)) ||
- X (c == K_RARROW && (p_ww & 8))) &&
- X curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
- X {
- X ++curwin->w_cursor.lnum;
- X curwin->w_cursor.col = 0;
- X curwin->w_set_curswant = TRUE;
- X continue;
- X }
- X if (operator == NOP)
- X beep();
- X else
- X {
- X if (lineempty(curwin->w_cursor.lnum))
- X CLEAROPBEEP;
- X else
- X {
- X mincl = TRUE;
- X if (n)
- X beep();
- X }
- X }
- X break;
- X }
- X }
- X break;
- X
- X case Ctrl('H'):
- X case 'h':
- X case K_LARROW:
- X case DEL:
- X mtype = MCHAR;
- X mincl = FALSE;
- X n = Prenum1;
- X while (n--)
- X {
- X if (oneleft() == FAIL)
- X {
- X /* backspace and del wrap to previous line if 'whichwrap'
- X * bit 0 set */
- X /* 'h' wraps to previous line if 'whichwrap' bit 2 set */
- X /* CURS_LEFT wraps to previous line if 'whichwrap' bit 3 set */
- X if ((((c == Ctrl('H') || c == DEL) && (p_ww & 1)) ||
- X (c == 'h' && (p_ww & 4)) ||
- X (c == K_LARROW && (p_ww & 8))) &&
- X curwin->w_cursor.lnum > 1)
- X {
- X --(curwin->w_cursor.lnum);
- X coladvance(MAXCOL);
- X curwin->w_set_curswant = TRUE;
- X continue;
- X }
- X else if (operator != DELETE && operator != CHANGE)
- X beep();
- X else if (Prenum1 == 1)
- X CLEAROPBEEP;
- X break;
- X }
- X }
- 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) == FAIL)
- 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) == FAIL)
- 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 mtype = MLINE;
- X if (onedown((long)(Prenum1 - 1)) == FAIL)
- X CLEAROPBEEP;
- X 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 curwin->w_curswant = (colnr_t)(Prenum - 1);
- X /* keep curswant at the column where we wanted to go, not where
- X we ended; differs is line is too short */
- X curwin->w_set_curswant = FALSE;
- 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 curwin->w_set_curswant = 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 * Another strangeness: When standing on the end of a word "ce" will
- X * change until the end of the next wordt, but "cw" will change only
- X * one character! This is done by setting type to 2.
- X */
- X if (operator == CHANGE && (n = gchar_cursor()) != ' ' && n != TAB &&
- X n != NUL)
- X {
- X mincl = TRUE;
- X flag = FALSE;
- X flag2 = TRUE;
- X }
- X
- Xdowrdcmd:
- X mtype = MCHAR;
- X curwin->w_set_curswant = TRUE;
- X if (flag)
- X n = fwd_word(Prenum1, type, operator != NOP);
- X else
- X n = end_word(Prenum1, type, flag2);
- 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 &&
- X curbuf->b_startop.lnum != curwin->w_cursor.lnum && !lineempty(startop.lnum))
- X {
- X curwin->w_cursor = curbuf->b_startop;
- X while (oneright() == OK)
- X ;
- X mincl = TRUE;
- X }
- X#endif
- X break;
- X
- X case '$':
- X mtype = MCHAR;
- X mincl = TRUE;
- X curwin->w_curswant = MAXCOL; /* so we stay at the end */
- X if (onedown((long)(Prenum1 - 1)) == FAIL)
- 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, searchbuff))
- X {
- X CLEAROP;
- X break;
- X }
- X mtype = MCHAR;
- X mincl = FALSE;
- X curwin->w_set_curswant = TRUE;
- X
- X n = dosearch(c, searchbuff, FALSE, Prenum1, TRUE, 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 curwin->w_set_curswant = TRUE;
- X if (!dosearch(0, NULL, flag, Prenum1, TRUE, 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 if (dir == BACKWARD)
- X mincl = FALSE;
- X else
- X mincl = TRUE;
- X curwin->w_set_curswant = 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 case '[':
- X dir = BACKWARD;
- X /* FALLTHROUGH */
- X
- X case ']':
- X mtype = MCHAR;
- X mincl = FALSE;
- X
- X /*
- X * "[f" or "]f" : Edit file under the cursor (same as "gf")
- X */
- X if ((c == ']' || c == '[') && nchar == 'f')
- X goto gotofile;
- X
- X /*
- X * "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')'
- X */
- X if ((c == '[' && (nchar == '{' || nchar == '(')) ||
- X ((c == ']' && (nchar == '}' || nchar == ')'))))
- X {
- X FPOS old_pos;
- X
- X old_pos = curwin->w_cursor;
- X while (Prenum1--)
- X {
- X if ((pos = showmatch(nchar)) == NULL)
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X curwin->w_cursor = *pos;
- X }
- X curwin->w_cursor = old_pos;
- X if (pos != NULL)
- X {
- X setpcmark();
- X curwin->w_cursor = *pos;
- X curwin->w_set_curswant = TRUE;
- X }
- X break;
- X }
- X
- X /*
- X * "[[", "[]", "]]" and "][": move to start or end of function
- X */
- X if (nchar == '[' || nchar == ']')
- X {
- X if (nchar == c) /* "]]" or "[[" */
- X flag = '{';
- X else
- X flag = '}'; /* "][" or "[]" */
- X
- X curwin->w_set_curswant = TRUE;
- X /*
- X * Imitate strange vi behaviour: When using "]]" with an operator we
- X * also stop at '}'.
- X */
- X if (!findpar(dir, Prenum1, flag,
- X (operator != NOP && dir == FORWARD && flag == '{')))
- X CLEAROPBEEP;
- X break;
- X }
- X
- X /*
- X * "[p" and "]p": put with indent adjustment
- X */
- X if (nchar == 'p')
- X {
- X doput((c == ']') ? FORWARD : BACKWARD, Prenum1, TRUE);
- X modified = TRUE;
- X break;
- X }
- X
- X /*
- X * end of '[' and ']': not a valid nchar
- X */
- X CLEAROPBEEP;
- 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 curwin->w_cursor.lnum = (curbuf->b_ml.ml_line_count * Prenum + 99) / 100;
- X beginline(TRUE);
- X }
- X }
- X else /* % : go to matching paren */
- X {
- X mtype = MCHAR;
- X if ((pos = showmatch(NUL)) == NULL)
- X CLEAROPBEEP;
- X else
- X {
- X setpcmark();
- X curwin->w_cursor = *pos;
- X curwin->w_set_curswant = 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 curwin->w_set_curswant = 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 curwin->w_set_curswant = TRUE;
- X if (!findpar(dir, Prenum1, NUL, FALSE))
- X CLEAROPBEEP;
- X break;
- X
- X/*
- X * 5: Edits
- X */
- X case '.':
- X CHECKCLEAROPQ;
- X if (start_redo(Prenum) == FAIL)
- X CLEAROPBEEP;
- X modified = TRUE;
- 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 curwin->w_set_curswant = TRUE;
- X modified = TRUE;
- X break;
- X
- X case Ctrl('R'):
- X CHECKCLEAROPQ;
- X u_redo((int)Prenum1);
- X curwin->w_set_curswant = TRUE;
- X modified = TRUE;
- X break;
- X
- X case 'U':
- X if (VIsual.lnum)
- X goto dooperator;
- X CHECKCLEAROPQ;
- X u_undoline();
- X curwin->w_set_curswant = TRUE;
- X modified = TRUE;
- X break;
- X
- X case 'r':
- X if (VIsual.lnum)
- X {
- X c = 'c';
- X goto dooperator;
- X }
- X CHECKCLEAROPQ;
- X ptr = ml_get_cursor();
- 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_save_cursor()) /* save line for undo */
- X break;
- X /*
- X * Get ptr again, because u_save will have released the line.
- X * At the same time we let know that the line will be changed.
- X */
- X ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE) + curwin->w_cursor.col;
- X curwin->w_cursor.col += Prenum1 - 1;
- X while (Prenum1--) /* replace the characters */
- X *ptr++ = nchar;
- X curwin->w_set_curswant = TRUE;
- X CHANGED;
- X updateline();
- X modified = TRUE;
- X break;
- X
- X case 'J':
- X if (VIsual.lnum) /* join the visual lines */
- X {
- X if (curwin->w_cursor.lnum > VIsual.lnum)
- X {
- X Prenum = curwin->w_cursor.lnum - VIsual.lnum + 1;
- X curwin->w_cursor.lnum = VIsual.lnum;
- X }
- X else
- X Prenum = VIsual.lnum - curwin->w_cursor.lnum + 1;
- X VIsual.lnum = 0;
- X }
- X CHECKCLEAROP;
- X if (Prenum <= 1)
- X Prenum = 2; /* default for join is two lines! */
- X if (curwin->w_cursor.lnum + Prenum - 1 > curbuf->b_ml.ml_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 modified = 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, FALSE);
- X modified = TRUE;
- X break;
- X
- X case Ctrl('A'): /* add to number */
- X case Ctrl('X'): /* subtract from number */
- X CHECKCLEAROPQ;
- X if (doaddsub((int)c, Prenum1) == OK)
- X prep_redo(Prenum1, c, NUL, NUL);
- X modified = TRUE;
- X break;
- X
- X/*
- X * 6: Inserts
- X */
- X case 'A':
- X curwin->w_set_curswant = TRUE;
- X while (oneright() == OK)
- X ;
- X /* FALLTHROUGH */
- X
- X case 'a':
- X CHECKCLEAROPQ;
- X /* Works just like an 'i'nsert on the next character. */
- X if (u_save_cursor())
- X {
- X if (!lineempty(curwin->w_cursor.lnum))
- X inc_cursor();
- X startinsert(c, FALSE, Prenum1);
- X modified = TRUE;
- 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_save_cursor())
- X {
- X startinsert(c, FALSE, Prenum1);
- X modified = TRUE;
- 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 = curwin->w_cursor.lnum;
- X curwin->w_cursor.lnum = Prenum;
- X if (VIsual.col != VISUALLINE)
- X {
- X n = VIsual.col;
- X VIsual.col = curwin->w_cursor.col;
- X curwin->w_cursor.col = (int)n;
- X curwin->w_set_curswant = TRUE;
- X }
- X break;
- X }
- X CHECKCLEAROP;
- X if (u_save(curwin->w_cursor.lnum, (linenr_t)(curwin->w_cursor.lnum + 1)) &&
- X Opencmd(FORWARD, TRUE, TRUE))
- X {
- X startinsert('o', TRUE, Prenum1);
- X modified = TRUE;
- X command_busy = TRUE;
- X }
- X break;
- X
- X case 'O':
- X CHECKCLEAROPQ;
- X if (u_save((linenr_t)(curwin->w_cursor.lnum - 1), curwin->w_cursor.lnum) && Opencmd(BACKWARD, TRUE, TRUE))
- X {
- X startinsert('O', TRUE, Prenum1);
- X modified = TRUE;
- 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_save_cursor())
- X {
- X startinsert('R', FALSE, Prenum1);
- X modified = TRUE;
- 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(curwin->w_cursor.lnum))
- X {
- X CLEAROPBEEP;
- X break;
- X }
- X prep_redo(Prenum, '~', NUL, NUL);
- X
- X if (!u_save_cursor())
- X break;
- X
- X for (; Prenum1 > 0; --Prenum1)
- X {
- X if (gchar_cursor() == NUL)
- X break;
- X swapchar(&curwin->w_cursor);
- X inc_cursor();
- X }
- X
- X curwin->w_set_curswant = TRUE;
- X CHANGED;
- X updateline();
- X modified = TRUE;
- 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 curbuf->b_startop = curwin->w_cursor;
- 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_u 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_u *(ar[9]) = {(char_u *)"dl", (char_u *)"dh", (char_u *)"d$", (char_u *)"c$", (char_u *)"cl", (char_u *)"cc", (char_u *)"yy", (char_u *)"y$", (char_u *)":s\r"};
- X static char_u *str = (char_u *)"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) == FAIL)
- 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 || pos->lnum == 0)
- X CLEAROPBEEP;
- X else
- X {
- X curwin->w_cursor = *pos;
- X if (flag)
- X beginline(TRUE);
- X }
- X mtype = flag ? MLINE : MCHAR;
- X mincl = FALSE; /* ignored if not MCHAR */
- X curwin->w_set_curswant = 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 curwin->w_set_curswant = TRUE;
- X break;
- X }
- X goto cursormark;
- X
- X/*
- X * 10. Buffer setting
- X */
- X case '"':
- X CHECKCLEAROP;
- X if (nchar != NUL && is_yank_buffer(nchar, FALSE))
- 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 && set_highlight('v') == FAIL)/* cannot highlight */
- X {
- X EMSG("Warning: terminal cannot highlight");
- 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 = curwin->w_cursor;
- X if (resel_Visual_nlines > 1)
- X curwin->w_cursor.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 curwin->w_cursor.col += resel_Visual_col * Prenum - 1;
- X else
- X curwin->w_cursor.col = resel_Visual_col;
- X break;
- X }
- X if (resel_Visual_col == MAXCOL)
- X {
- X curwin->w_curswant = MAXCOL;
- X coladvance(MAXCOL);
- X }
- X else if (Visual_block)
- X coladvance((colnr_t)(curwin->w_virtcol + resel_Visual_col * Prenum - 1));
- X curs_columns(TRUE); /* recompute w_virtcol */
- X updateScreen(NOT_VALID); /* show the inversion */
- X }
- X else
- X {
- X VIsual = curwin->w_cursor;
- 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((char_u *)":st\r"); /* with autowrite */
- X break;
- X
- X/*
- X * 13. Window commands
- X */
- X
- X case Ctrl('W'):
- X CHECKCLEAROP;
- X do_window(nchar, Prenum); /* everything is in window.c */
- X break;
- X
- X/*
- X * 14. extended commands (starting with 'g')
- X */
- X case 'g':
- X switch (nchar)
- X {
- X /*
- X * "gf": goto file, edit file under cursor
- X * "]f" and "[f": can also be used.
- X */
- X case 'f':
- Xgotofile:
- X ptr = file_name_at_cursor();
- X /* do autowrite if necessary */
- X if (curbuf->b_changed && curbuf->b_nwindows <= 1 && !p_hid)
- X autowrite(curbuf);
- X if (ptr != NULL)
- X {
- X setpcmark();
- X stuffReadbuff((char_u *) ":e ");
- X stuffReadbuff(ptr);
- X stuffReadbuff((char_u *) "\n");
- X free(ptr);
- X }
- X else
- X CLEAROPBEEP;
- X break;
- X
- X /*
- X * "gs": goto sleep
- X */
- X case 's': while (Prenum1-- && !got_int)
- X {
- X sleep(1);
- X breakcheck();
- X }
- X break;
- X
- X default: CLEAROPBEEP;
- X break;
- X }
- 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 CLEAROP; /* don't beep */
- X break;
- X }
- X /* Don't drop through and beep if we are canceling a command: */
- X else if (operator != NOP || opnum || Prenum || yankbuffer)
- X {
- X CLEAROP; /* don't beep */
- X break;
- X }
- X /* FALLTHROUGH */
- 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 curbuf->b_startop = curwin->w_cursor;
- X curwin->w_cursor.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 curwin->w_cursor.col += redo_Visual_col - 1;
- X else
- X curwin->w_cursor.col = redo_Visual_col;
- X break;
- X }
- X if (redo_Visual_col == MAXCOL)
- X {
- X curwin->w_curswant = MAXCOL;
- X coladvance(MAXCOL);
- X }
- X Prenum = redo_Visual_Prenum;
- X if (Prenum == 0)
- X Prenum1 = 1L;
- X else
- X Prenum1 = Prenum;
- X }
- X else if (VIsual.lnum)
- X curbuf->b_startop = VIsual;
- X
- X if (lt(curbuf->b_startop, curwin->w_cursor))
- X {
- X curbuf->b_endop = curwin->w_cursor;
- X curwin->w_cursor = curbuf->b_startop;
- X }
- X else
- X {
- X curbuf->b_endop = curbuf->b_startop;
- X curbuf->b_startop = curwin->w_cursor;
- X }
- X nlines = curbuf->b_endop.lnum - curbuf->b_startop.lnum + 1;
- X
- X if (VIsual.lnum || redo_Visual_busy)
- X {
- X if (Visual_block) /* block mode */
- X {
- X startvcol = getvcol(curwin, &(curbuf->b_startop), 2);
- X n = getvcol(curwin, &(curbuf->b_endop), 2);
- X if (n < startvcol)
- X startvcol = (colnr_t)n;
- X
- X /* if '$' was used, get endvcol from longest line */
- X if (curwin->w_curswant == MAXCOL)
- X {
- X curwin->w_cursor.col = MAXCOL;
- X endvcol = 0;
- X for (curwin->w_cursor.lnum = curbuf->b_startop.lnum; curwin->w_cursor.lnum <= curbuf->b_endop.lnum; ++curwin->w_cursor.lnum)
- X if ((n = getvcol(curwin, &curwin->w_cursor, 3)) > endvcol)
- X endvcol = (colnr_t)n;
- X curwin->w_cursor = curbuf->b_startop;
- X }
- X else if (redo_Visual_busy)
- X endvcol = startvcol + redo_Visual_col - 1;
- X else
- X {
- X endvcol = getvcol(curwin, &(curbuf->b_startop), 3);
- X n = getvcol(curwin, &(curbuf->b_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 (curwin->w_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 = curbuf->b_endop.col;
- X else
- X resel_Visual_col = curbuf->b_endop.col - curbuf->b_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 redo_Visual_Prenum = Prenum;
- X }
- X
- X /*
- X * Mincl defaults to TRUE.
- X * If endop is on a NUL (empty line) mincl becomes FALSE
- X * This makes "d}P" and "v}dP" work the same.
- X */
- X mincl = TRUE;
- X if (VIsual.col == VISUALLINE)
- X mtype = MLINE;
- X else
- X {
- X mtype = MCHAR;
- X if (*ml_get_pos(&(curbuf->b_endop)) == NUL)
- X mincl = FALSE;
- X }
- 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 else if (operator == LSHIFT || operator == RSHIFT)
- X Prenum1 = 1L; /* if not visual mode: shift one indent */
- X
- X curwin->w_set_curswant = 1;
- X
- X /* no_op is set when start and end are the same */
- X no_op = (mtype == MCHAR && !mincl && equal(curbuf->b_startop, curbuf->b_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 && curbuf->b_endop.col == 0 && nlines > 1)
- X {
- X --nlines;
- X --curbuf->b_endop.lnum;
- X if (inindent())
- X mtype = MLINE;
- X else
- X {
- X curbuf->b_endop.col = STRLEN(ml_get(curbuf->b_endop.lnum));
- X if (curbuf->b_endop.col)
- X {
- X --curbuf->b_endop.col;
- X mincl = TRUE;
- X }
- X }
- X }
- X switch (operator)
- X {
- X case LSHIFT:
- X case RSHIFT:
- X doshift(operator, TRUE, (int)Prenum1);
- X modified = TRUE;
- X break;
- X
- X case DELETE:
- X if (!no_op)
- X {
- X dodelete();
- X modified = TRUE;
- X }
- X break;
- X
- X case YANK:
- X if (!no_op)
- X (void)doyank(FALSE);
- X break;
- X
- X case CHANGE:
- X dochange();
- X modified = TRUE;
- 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((char *)IObuff, ":%ld,%ld", (long)curbuf->b_startop.lnum, (long)curbuf->b_endop.lnum);
- X stuffReadbuff(IObuff);
- X if (operator != COLON)
- X stuffReadbuff((char_u *)"!");
- X if (operator == INDENT)
- X {
- X stuffReadbuff(p_ep);
- X stuffReadbuff((char_u *)"\n");
- X }
- X else if (operator == FORMAT)
- X {
- X stuffReadbuff(p_fp);
- X stuffReadbuff((char_u *)"\n");
- X }
- X /* docmdline() does the rest */
- X break;
- X
- X case TILDE:
- X case UPPER:
- X case LOWER:
- X if (!no_op)
- X {
- X dotilde();
- X modified = TRUE;
- X }
- X break;
- X
- X case FORMAT:
- X if (*p_fp != NUL)
- X goto dofilter; /* use external command */
- X doformat(); /* use internal function */
- X modified = TRUE;
- 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
- X if (restart_edit && operator == NOP && VIsual.lnum == 0 && !command_busy && stuff_empty() && yankbuffer == 0)
- X {
- X startinsert(restart_edit, FALSE, 1L);
- X modified = TRUE;
- X }
- X
- X checkpcmark(); /* check if we moved since setting pcmark */
- X
- X/*
- X * TEMPORARY: update the other windows for the current buffer if modified
- X */
- X if (modified)
- X {
- X WIN *wp;
- X
- X for (wp = firstwin; wp; wp = wp->w_next)
- X if (wp != curwin && wp->w_buffer == curbuf)
- X {
- X cursor_off();
- X wp->w_redr_type = NOT_VALID;
- X win_update(wp);
- X }
- X }
- 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 * return TRUE if operator was 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 * return TRUE if operator was 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_u buf[40];
- X char_u *p;
- X
- X if (!p_sc || !(KeyTyped || c1 == -1 || c1 == ' '))
- X return;
- X
- X cursor_off();
- X msg_pos((int)Rows - 1, sc_col);
- X if (c1 == -1)
- X msg_outstr((char_u *)" "); /* look in comp_col() for the number of spaces */
- X else
- X {
- X p = buf;
- X if (opnum)
- X {
- X sprintf((char *)p, "%ld", (long)opnum);
- X p = p + STRLEN(buf);
- X }
- X if (yankbuffer)
- X {
- X *p++ = '"';
- X *p++ = yankbuffer;
- X }
- X if (c1 == Ctrl('W')) /* ^W is in between counts */
- X {
- X *p++ = '^';
- X *p++ = 'W';
- X c1 = NUL;
- X }
- X else if (operator == 'z')
- X *p++ = 'z';
- X else if (operator)
- X *p++ = opchars[operator - 1];
- X if (Prenum)
- X {
- X sprintf((char *)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 msg_outstr(buf);
- X }
- X setcursor();
- X /* cursor_on(); */
- X}
- END_OF_FILE
- if test 41440 -ne `wc -c <'vim/src/normal.c'`; then
- echo shar: \"'vim/src/normal.c'\" unpacked with wrong size!
- fi
- # end of 'vim/src/normal.c'
- fi
- echo shar: End of archive 10 \(of 26\).
- cp /dev/null ark10isdone
- 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 26 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 26 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-