Mercurial > hg > RemoteEditor > vim7
diff src/normal.c @ 48:67300faee616 v7-3-618
v7-3-618
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 01 Aug 2012 18:08:28 +0900 |
parents | c16898406ff2 |
children |
line wrap: on
line diff
--- a/src/normal.c Wed Aug 01 18:03:06 2012 +0900 +++ b/src/normal.c Wed Aug 01 18:08:28 2012 +0900 @@ -20,15 +20,18 @@ */ static int resel_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */ static linenr_T resel_VIsual_line_count; /* number of lines */ -static colnr_T resel_VIsual_col; /* nr of cols or end col */ +static colnr_T resel_VIsual_vcol; /* nr of cols or end col */ static int restart_VIsual_select = 0; #endif +#ifdef FEAT_EVAL +static void set_vcount_ca __ARGS((cmdarg_T *cap, int *set_prevcount)); +#endif static int -# ifdef __BORLANDC__ -_RTLENTRYF -# endif +#ifdef __BORLANDC__ + _RTLENTRYF +#endif nv_compare __ARGS((const void *s1, const void *s2)); static int find_command __ARGS((int cmdchar)); static void op_colon __ARGS((oparg_T *oap)); @@ -648,6 +651,14 @@ dont_scroll = FALSE; /* allow scrolling here */ #endif +#ifdef FEAT_EVAL + /* Set v:count here, when called from main() and not a stuffed + * command, so that v:count can be used in an expression mapping + * when there is no count. */ + if (toplevel && stuff_empty()) + set_vcount_ca(&ca, &set_prevcount); +#endif + /* * Get the command character from the user. */ @@ -725,15 +736,7 @@ * command, so that v:count can be used in an expression mapping * right after the count. */ if (toplevel && stuff_empty()) - { - long count = ca.count0; - - /* multiply with ca.opcount the same way as below */ - if (ca.opcount != 0) - count = ca.opcount * (count == 0 ? 1 : count); - set_vcount(count, count == 0 ? 1 : count, set_prevcount); - set_prevcount = FALSE; /* only set v:prevcount once */ - } + set_vcount_ca(&ca, &set_prevcount); #endif if (ctrl_w) { @@ -1199,7 +1202,16 @@ { clearop(oap); #ifdef FEAT_EVAL - set_reg_var('"'); + { + int regname = 0; + + /* Adjust the register according to 'clipboard', so that when + * "unnamed" is present it becomes '*' or '+' instead of '"'. */ +# ifdef FEAT_CLIPBOARD + adjust_clip_reg(®name); +# endif + set_reg_var(regname); + } #endif } @@ -1386,6 +1398,26 @@ opcount = ca.opcount; } +#ifdef FEAT_EVAL +/* + * Set v:count and v:count1 according to "cap". + * Set v:prevcount only when "set_prevcount" is TRUE. + */ + static void +set_vcount_ca(cap, set_prevcount) + cmdarg_T *cap; + int *set_prevcount; +{ + long count = cap->count0; + + /* multiply with cap->opcount the same way as above */ + if (cap->opcount != 0) + count = cap->opcount * (count == 0 ? 1 : count); + set_vcount(count, count == 0 ? 1 : count, *set_prevcount); + *set_prevcount = FALSE; /* only set v:prevcount once */ +} +#endif + /* * Handle an operator after visual mode or when the movement is finished */ @@ -1404,7 +1436,7 @@ /* The visual area is remembered for redo */ static int redo_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */ static linenr_T redo_VIsual_line_count; /* number of lines */ - static colnr_T redo_VIsual_col; /* number of cols or end column */ + static colnr_T redo_VIsual_vcol; /* number of cols or end column */ static long redo_VIsual_count; /* count for Visual operator */ # ifdef FEAT_VIRTUALEDIT int include_line_break = FALSE; @@ -1419,7 +1451,7 @@ * This could call do_pending_operator() recursively, but that's OK * because gui_yank will be TRUE for the nested call. */ - if (clip_star.available + if ((clip_star.available || clip_plus.available) && oap->op_type != OP_NOP && !gui_yank # ifdef FEAT_VISUAL @@ -1517,22 +1549,31 @@ #ifdef FEAT_VISUAL if (redo_VIsual_busy) { + /* Redo of an operation on a Visual area. Use the same size from + * redo_VIsual_line_count and redo_VIsual_vcol. */ oap->start = curwin->w_cursor; curwin->w_cursor.lnum += redo_VIsual_line_count - 1; if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; VIsual_mode = redo_VIsual_mode; - if (VIsual_mode == 'v') - { - if (redo_VIsual_line_count <= 1) - curwin->w_cursor.col += redo_VIsual_col - 1; + if (redo_VIsual_vcol == MAXCOL || VIsual_mode == 'v') + { + if (VIsual_mode == 'v') + { + if (redo_VIsual_line_count <= 1) + { + validate_virtcol(); + curwin->w_curswant = + curwin->w_virtcol + redo_VIsual_vcol - 1; + } + else + curwin->w_curswant = redo_VIsual_vcol; + } else - curwin->w_cursor.col = redo_VIsual_col; - } - if (redo_VIsual_col == MAXCOL) - { - curwin->w_curswant = MAXCOL; - coladvance((colnr_T)MAXCOL); + { + curwin->w_curswant = MAXCOL; + } + coladvance(curwin->w_curswant); } cap->count0 = redo_VIsual_count; if (redo_VIsual_count != 0) @@ -1678,7 +1719,7 @@ } } else if (redo_VIsual_busy) - oap->end_vcol = oap->start_vcol + redo_VIsual_col - 1; + oap->end_vcol = oap->start_vcol + redo_VIsual_vcol - 1; /* * Correct oap->end.col and oap->start.col to be the * upper-left and lower-right corner of the block area. @@ -1703,13 +1744,22 @@ */ resel_VIsual_mode = VIsual_mode; if (curwin->w_curswant == MAXCOL) - resel_VIsual_col = MAXCOL; - else if (VIsual_mode == Ctrl_V) - resel_VIsual_col = oap->end_vcol - oap->start_vcol + 1; - else if (oap->line_count > 1) - resel_VIsual_col = oap->end.col; + resel_VIsual_vcol = MAXCOL; else - resel_VIsual_col = oap->end.col - oap->start.col + 1; + { + if (VIsual_mode != Ctrl_V) + getvvcol(curwin, &(oap->end), + NULL, NULL, &oap->end_vcol); + if (VIsual_mode == Ctrl_V || oap->line_count <= 1) + { + if (VIsual_mode != Ctrl_V) + getvvcol(curwin, &(oap->start), + &oap->start_vcol, NULL, NULL); + resel_VIsual_vcol = oap->end_vcol - oap->start_vcol + 1; + } + else + resel_VIsual_vcol = oap->end_vcol; + } resel_VIsual_line_count = oap->line_count; } @@ -1730,14 +1780,22 @@ { /* Prepare for redoing. Only use the nchar field for "r", * otherwise it might be the second char of the operator. */ - prep_redo(oap->regname, 0L, NUL, 'v', - get_op_char(oap->op_type), - get_extra_op_char(oap->op_type), - oap->op_type == OP_REPLACE ? cap->nchar : NUL); + if (cap->cmdchar == 'g' && (cap->nchar == 'n' + || cap->nchar == 'N')) + /* "gn" and "gN" are a bit different */ + prep_redo(oap->regname, 0L, NUL, cap->cmdchar, cap->nchar, + get_op_char(oap->op_type), + get_extra_op_char(oap->op_type)); + else + prep_redo(oap->regname, 0L, NUL, 'v', + get_op_char(oap->op_type), + get_extra_op_char(oap->op_type), + oap->op_type == OP_REPLACE + ? cap->nchar : NUL); if (!redo_VIsual_busy) { redo_VIsual_mode = resel_VIsual_mode; - redo_VIsual_col = resel_VIsual_col; + redo_VIsual_vcol = resel_VIsual_vcol; redo_VIsual_line_count = resel_VIsual_line_count; redo_VIsual_count = cap->count0; } @@ -1763,17 +1821,25 @@ { oap->inclusive = FALSE; /* Try to include the newline, unless it's an operator - * that works on lines only */ - if (*p_sel != 'o' - && !op_on_lines(oap->op_type) - && oap->end.lnum < curbuf->b_ml.ml_line_count) + * that works on lines only. */ + if (*p_sel != 'o' && !op_on_lines(oap->op_type)) { - ++oap->end.lnum; - oap->end.col = 0; + if (oap->end.lnum < curbuf->b_ml.ml_line_count) + { + ++oap->end.lnum; + oap->end.col = 0; # ifdef FEAT_VIRTUALEDIT - oap->end.coladd = 0; + oap->end.coladd = 0; # endif - ++oap->line_count; + ++oap->line_count; + } + else + { + /* Cannot move below the last line, make the op + * inclusive to tell the operation to include the + * line break. */ + oap->inclusive = TRUE; + } } } } @@ -1910,7 +1976,7 @@ beep_flush(); else { - (void)do_join(oap->line_count, oap->op_type == OP_JOIN, TRUE); + (void)do_join(oap->line_count, oap->op_type == OP_JOIN, TRUE, TRUE); auto_format(FALSE, TRUE); } break; @@ -1920,7 +1986,10 @@ VIsual_reselect = FALSE; /* don't reselect now */ #endif if (empty_region_error) + { vim_beep(); + CancelRedo(); + } else { (void)op_delete(oap); @@ -1934,7 +2003,10 @@ if (empty_region_error) { if (!gui_yank) + { vim_beep(); + CancelRedo(); + } } else (void)op_yank(oap, FALSE, !gui_yank); @@ -1946,7 +2018,10 @@ VIsual_reselect = FALSE; /* don't reselect now */ #endif if (empty_region_error) + { vim_beep(); + CancelRedo(); + } else { /* This is a new edit command, not a restart. Need to @@ -2008,7 +2083,10 @@ case OP_LOWER: case OP_ROT13: if (empty_region_error) + { vim_beep(); + CancelRedo(); + } else op_tilde(oap); check_cursor_col(); @@ -2041,7 +2119,10 @@ #endif #ifdef FEAT_VISUALEXTRA if (empty_region_error) + { vim_beep(); + CancelRedo(); + } else { /* This is a new edit command, not a restart. Need to @@ -2071,7 +2152,10 @@ #ifdef FEAT_VISUALEXTRA if (empty_region_error) #endif + { vim_beep(); + CancelRedo(); + } #ifdef FEAT_VISUALEXTRA else op_replace(oap, cap->nchar); @@ -2203,6 +2287,7 @@ { #ifdef FEAT_EVAL char_u *(argv[1]); + int save_virtual_op = virtual_op; if (*p_opfunc == NUL) EMSG(_("E774: 'operatorfunc' is empty")); @@ -2221,7 +2306,14 @@ argv[0] = (char_u *)"line"; else argv[0] = (char_u *)"char"; + + /* Reset virtual_op so that 'virtualedit' can be changed in the + * function. */ + virtual_op = MAYBE; + (void)call_func_retnr(p_opfunc, 1, argv, FALSE); + + virtual_op = save_virtual_op; } #else EMSG(_("E775: Eval feature not available")); @@ -4342,7 +4434,7 @@ break; } #ifdef FEAT_COMMENTS - if (get_leader_len(ml_get_curline(), NULL, FALSE) > 0) + if (get_leader_len(ml_get_curline(), NULL, FALSE, TRUE) > 0) { /* Ignore this line, continue at start of next line. */ ++curwin->w_cursor.lnum; @@ -4501,6 +4593,7 @@ } curwin->w_cursor.lnum++; curwin->w_curswant %= width2; + linelen = linetabsize(ml_get_curline()); } } } @@ -6985,7 +7078,18 @@ for (n = cap->count1; n > 0; --n) { State = REPLACE; - ins_char(cap->nchar); + if (cap->nchar == Ctrl_E || cap->nchar == Ctrl_Y) + { + int c = ins_copychar(curwin->w_cursor.lnum + + (cap->nchar == Ctrl_Y ? -1 : 1)); + if (c != NUL) + ins_char(c); + else + /* will be decremented further down */ + ++curwin->w_cursor.col; + } + else + ins_char(cap->nchar); State = old_State; if (cap->ncharC1 != 0) ins_char(cap->ncharC1); @@ -7007,7 +7111,15 @@ * line will be changed. */ ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE); - ptr[curwin->w_cursor.col] = cap->nchar; + if (cap->nchar == Ctrl_E || cap->nchar == Ctrl_Y) + { + int c = ins_copychar(curwin->w_cursor.lnum + + (cap->nchar == Ctrl_Y ? -1 : 1)); + if (c != NUL) + ptr[curwin->w_cursor.col] = c; + } + else + ptr[curwin->w_cursor.col] = cap->nchar; if (p_sm && msg_silent == 0) showmatch(cap->nchar); ++curwin->w_cursor.col; @@ -7556,13 +7668,9 @@ else /* start Visual mode */ { check_visual_highlight(); - if (cap->count0) /* use previously selected part */ - { - if (resel_VIsual_mode == NUL) /* there is none */ - { - beep_flush(); - return; - } + if (cap->count0 > 0 && resel_VIsual_mode != NUL) + { + /* use previously selected part */ VIsual = curwin->w_cursor; VIsual_active = TRUE; @@ -7590,12 +7698,16 @@ if (VIsual_mode == 'v') { if (resel_VIsual_line_count <= 1) - curwin->w_cursor.col += resel_VIsual_col * cap->count0 - 1; + { + validate_virtcol(); + curwin->w_curswant = curwin->w_virtcol + + resel_VIsual_vcol * cap->count0 - 1; + } else - curwin->w_cursor.col = resel_VIsual_col; - check_cursor_col(); - } - if (resel_VIsual_col == MAXCOL) + curwin->w_curswant = resel_VIsual_vcol; + coladvance(curwin->w_curswant); + } + if (resel_VIsual_vcol == MAXCOL) { curwin->w_curswant = MAXCOL; coladvance((colnr_T)MAXCOL); @@ -7604,7 +7716,7 @@ { validate_virtcol(); curwin->w_curswant = curwin->w_virtcol - + resel_VIsual_col * cap->count0 - 1; + + resel_VIsual_vcol * cap->count0 - 1; coladvance(curwin->w_curswant); } else @@ -7617,6 +7729,16 @@ /* start Select mode when 'selectmode' contains "cmd" */ may_start_select('c'); n_start_visual_mode(cap->cmdchar); + if (VIsual_mode != 'V' && *p_sel == 'e') + ++cap->count1; /* include one more char */ + if (cap->count0 > 0 && --cap->count1 > 0) + { + /* With a count select that many characters or lines. */ + if (VIsual_mode == 'v' || VIsual_mode == Ctrl_V) + nv_right(cap); + else if (VIsual_mode == 'V') + nv_down(cap); + } } } } @@ -7875,6 +7997,18 @@ break; #endif /* FEAT_VISUAL */ + /* "gn", "gN" visually select next/previous search match + * "gn" selects next match + * "gN" selects previous match + */ + case 'N': + case 'n': +#ifdef FEAT_VISUAL + if (!current_search(cap->count1, cap->nchar == 'n')) +#endif + beep_flush(); + break; + /* * "gj" and "gk" two new funny movement keys -- up and down * movement based on *screen* line rather than *file* line. @@ -8279,10 +8413,12 @@ #ifdef FEAT_WINDOWS case 't': - goto_tabpage((int)cap->count0); + if (!checkclearop(oap)) + goto_tabpage((int)cap->count0); break; case 'T': - goto_tabpage(-(int)cap->count1); + if (!checkclearop(oap)) + goto_tabpage(-(int)cap->count1); break; #endif @@ -8529,7 +8665,7 @@ else curwin->w_curswant = 0; /* keep curswant at the column where we wanted to go, not where - we ended; differs if line is too short */ + * we ended; differs if line is too short */ curwin->w_set_curswant = FALSE; } @@ -8741,7 +8877,7 @@ { --pp->col; #ifdef FEAT_MBYTE - mb_adjustpos(pp); + mb_adjustpos(curbuf, pp); #endif } else if (pp->lnum > 1) @@ -9210,7 +9346,7 @@ { prep_redo(cap->oap->regname, cap->count0, NUL, cap->cmdchar, NUL, NUL, cap->nchar); - (void)do_join(cap->count0, cap->nchar == NUL, TRUE); + (void)do_join(cap->count0, cap->nchar == NUL, TRUE, TRUE); } } } @@ -9266,7 +9402,7 @@ # ifdef FEAT_CLIPBOARD adjust_clip_reg(®name); # endif - if (regname == 0 || VIM_ISDIGIT(regname) + if (regname == 0 || regname == '"' || VIM_ISDIGIT(regname) # ifdef FEAT_CLIPBOARD || (clip_unnamed && (regname == '*' || regname == '+')) # endif