diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-09-30 23:12:16 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-09-30 23:12:16 +0200 |
commit | 792cf5e1bec04c6d6d70cfbb9ef24c798b469731 (patch) | |
tree | 6981aedd79c3abd88a2d1be8d818e6ecb3ac5791 /src/normal.c | |
parent | 18223a592efa4399e3951c86deeb712a13b05ca5 (diff) | |
download | vim-git-792cf5e1bec04c6d6d70cfbb9ef24c798b469731.tar.gz |
patch 8.1.2104: the normal.c file is too bigv8.1.2104
Problem: The normal.c file is too big.
Solution: Move do_pending_operator() to ops.c. (Yegappan Lakshmanan,
closes #4999).
Diffstat (limited to 'src/normal.c')
-rw-r--r-- | src/normal.c | 993 |
1 files changed, 13 insertions, 980 deletions
diff --git a/src/normal.c b/src/normal.c index 98ec9ef84..1fddeae07 100644 --- a/src/normal.c +++ b/src/normal.c @@ -14,24 +14,14 @@ #include "vim.h" -/* - * The Visual area is remembered for reselection. - */ -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_vcol; /* nr of cols or end col */ -static int VIsual_mode_orig = NUL; /* saved Visual mode */ - +static int VIsual_mode_orig = NUL; // saved Visual mode static int restart_VIsual_select = 0; #ifdef FEAT_EVAL static void set_vcount_ca(cmdarg_T *cap, int *set_prevcount); #endif static int nv_compare(const void *s1, const void *s2); -static void op_colon(oparg_T *oap); -static void op_function(oparg_T *oap); static void unshift_special(cmdarg_T *cap); -static void may_clear_cmdline(void); #ifdef FEAT_CMDL_INFO static void del_from_showcmd(int); #endif @@ -115,7 +105,6 @@ static void nv_wordcmd(cmdarg_T *cap); static void nv_beginline(cmdarg_T *cap); static void adjust_cursor(oparg_T *oap); static void adjust_for_sel(cmdarg_T *cap); -static int unadjust_for_sel(void); static void nv_select(cmdarg_T *cap); static void nv_goto(cmdarg_T *cap); static void nv_normal(cmdarg_T *cap); @@ -139,7 +128,6 @@ static void nv_nbcmd(cmdarg_T *cap); static void nv_drop(cmdarg_T *cap); #endif static void nv_cursorhold(cmdarg_T *cap); -static void get_op_vcol(oparg_T *oap, colnr_T col, int initial); static char *e_noident = N_("E349: No identifier under cursor"); @@ -1295,900 +1283,6 @@ set_vcount_ca(cmdarg_T *cap, int *set_prevcount) #endif /* - * Handle an operator after Visual mode or when the movement is finished. - * "gui_yank" is true when yanking text for the clipboard. - */ - void -do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank) -{ - oparg_T *oap = cap->oap; - pos_T old_cursor; - int empty_region_error; - int restart_edit_save; -#ifdef FEAT_LINEBREAK - int lbr_saved = curwin->w_p_lbr; -#endif - - /* 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_vcol; /* number of cols or end column */ - static long redo_VIsual_count; /* count for Visual operator */ - static int redo_VIsual_arg; /* extra argument */ - int include_line_break = FALSE; - -#if defined(FEAT_CLIPBOARD) - /* - * Yank the visual area into the GUI selection register before we operate - * on it and lose it forever. - * Don't do it if a specific register was specified, so that ""x"*P works. - * 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 || clip_plus.available) - && oap->op_type != OP_NOP - && !gui_yank - && VIsual_active - && !redo_VIsual_busy - && oap->regname == 0) - clip_auto_select(); -#endif - old_cursor = curwin->w_cursor; - - /* - * If an operation is pending, handle it... - */ - if ((finish_op || VIsual_active) && oap->op_type != OP_NOP) - { - // Yank can be redone when 'y' is in 'cpoptions', but not when yanking - // for the clipboard. - int redo_yank = vim_strchr(p_cpo, CPO_YANK) != NULL && !gui_yank; - -#ifdef FEAT_LINEBREAK - /* Avoid a problem with unwanted linebreaks in block mode. */ - if (curwin->w_p_lbr) - curwin->w_valid &= ~VALID_VIRTCOL; - curwin->w_p_lbr = FALSE; -#endif - oap->is_VIsual = VIsual_active; - if (oap->motion_force == 'V') - oap->motion_type = MLINE; - else if (oap->motion_force == 'v') - { - /* If the motion was linewise, "inclusive" will not have been set. - * Use "exclusive" to be consistent. Makes "dvj" work nice. */ - if (oap->motion_type == MLINE) - oap->inclusive = FALSE; - /* If the motion already was characterwise, toggle "inclusive" */ - else if (oap->motion_type == MCHAR) - oap->inclusive = !oap->inclusive; - oap->motion_type = MCHAR; - } - else if (oap->motion_force == Ctrl_V) - { - /* Change line- or characterwise motion into Visual block mode. */ - if (!VIsual_active) - { - VIsual_active = TRUE; - VIsual = oap->start; - } - VIsual_mode = Ctrl_V; - VIsual_select = FALSE; - VIsual_reselect = FALSE; - } - - /* Only redo yank when 'y' flag is in 'cpoptions'. */ - /* Never redo "zf" (define fold). */ - if ((redo_yank || oap->op_type != OP_YANK) - && ((!VIsual_active || oap->motion_force) - /* Also redo Operator-pending Visual mode mappings */ - || (VIsual_active && cap->cmdchar == ':' - && oap->op_type != OP_COLON)) - && cap->cmdchar != 'D' -#ifdef FEAT_FOLDING - && oap->op_type != OP_FOLD - && oap->op_type != OP_FOLDOPEN - && oap->op_type != OP_FOLDOPENREC - && oap->op_type != OP_FOLDCLOSE - && oap->op_type != OP_FOLDCLOSEREC - && oap->op_type != OP_FOLDDEL - && oap->op_type != OP_FOLDDELREC -#endif - ) - { - prep_redo(oap->regname, cap->count0, - get_op_char(oap->op_type), get_extra_op_char(oap->op_type), - oap->motion_force, cap->cmdchar, cap->nchar); - if (cap->cmdchar == '/' || cap->cmdchar == '?') /* was a search */ - { - /* - * If 'cpoptions' does not contain 'r', insert the search - * pattern to really repeat the same command. - */ - if (vim_strchr(p_cpo, CPO_REDO) == NULL) - AppendToRedobuffLit(cap->searchbuf, -1); - AppendToRedobuff(NL_STR); - } - else if (cap->cmdchar == ':') - { - /* do_cmdline() has stored the first typed line in - * "repeat_cmdline". When several lines are typed repeating - * won't be possible. */ - if (repeat_cmdline == NULL) - ResetRedobuff(); - else - { - AppendToRedobuffLit(repeat_cmdline, -1); - AppendToRedobuff(NL_STR); - VIM_CLEAR(repeat_cmdline); - } - } - } - - 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 (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_curswant = MAXCOL; - } - coladvance(curwin->w_curswant); - } - cap->count0 = redo_VIsual_count; - if (redo_VIsual_count != 0) - cap->count1 = redo_VIsual_count; - else - cap->count1 = 1; - } - else if (VIsual_active) - { - if (!gui_yank) - { - /* Save the current VIsual area for '< and '> marks, and "gv" */ - curbuf->b_visual.vi_start = VIsual; - curbuf->b_visual.vi_end = curwin->w_cursor; - curbuf->b_visual.vi_mode = VIsual_mode; - if (VIsual_mode_orig != NUL) - { - curbuf->b_visual.vi_mode = VIsual_mode_orig; - VIsual_mode_orig = NUL; - } - curbuf->b_visual.vi_curswant = curwin->w_curswant; -# ifdef FEAT_EVAL - curbuf->b_visual_mode_eval = VIsual_mode; -# endif - } - - /* In Select mode, a linewise selection is operated upon like a - * characterwise selection. - * Special case: gH<Del> deletes the last line. */ - if (VIsual_select && VIsual_mode == 'V' - && cap->oap->op_type != OP_DELETE) - { - if (LT_POS(VIsual, curwin->w_cursor)) - { - VIsual.col = 0; - curwin->w_cursor.col = - (colnr_T)STRLEN(ml_get(curwin->w_cursor.lnum)); - } - else - { - curwin->w_cursor.col = 0; - VIsual.col = (colnr_T)STRLEN(ml_get(VIsual.lnum)); - } - VIsual_mode = 'v'; - } - /* If 'selection' is "exclusive", backup one character for - * charwise selections. */ - else if (VIsual_mode == 'v') - include_line_break = unadjust_for_sel(); - - oap->start = VIsual; - if (VIsual_mode == 'V') - { - oap->start.col = 0; - oap->start.coladd = 0; - } - } - - /* - * Set oap->start to the first position of the operated text, oap->end - * to the end of the operated text. w_cursor is equal to oap->start. - */ - if (LT_POS(oap->start, curwin->w_cursor)) - { -#ifdef FEAT_FOLDING - /* Include folded lines completely. */ - if (!VIsual_active) - { - if (hasFolding(oap->start.lnum, &oap->start.lnum, NULL)) - oap->start.col = 0; - if ((curwin->w_cursor.col > 0 || oap->inclusive) - && hasFolding(curwin->w_cursor.lnum, NULL, - &curwin->w_cursor.lnum)) - curwin->w_cursor.col = (colnr_T)STRLEN(ml_get_curline()); - } -#endif - oap->end = curwin->w_cursor; - curwin->w_cursor = oap->start; - - /* w_virtcol may have been updated; if the cursor goes back to its - * previous position w_virtcol becomes invalid and isn't updated - * automatically. */ - curwin->w_valid &= ~VALID_VIRTCOL; - } - else - { -#ifdef FEAT_FOLDING - /* Include folded lines completely. */ - if (!VIsual_active && oap->motion_type == MLINE) - { - if (hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, - NULL)) - curwin->w_cursor.col = 0; - if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum)) - oap->start.col = (colnr_T)STRLEN(ml_get(oap->start.lnum)); - } -#endif - oap->end = oap->start; - oap->start = curwin->w_cursor; - } - - /* Just in case lines were deleted that make the position invalid. */ - check_pos(curwin->w_buffer, &oap->end); - oap->line_count = oap->end.lnum - oap->start.lnum + 1; - - /* Set "virtual_op" before resetting VIsual_active. */ - virtual_op = virtual_active(); - - if (VIsual_active || redo_VIsual_busy) - { - get_op_vcol(oap, redo_VIsual_vcol, TRUE); - - if (!redo_VIsual_busy && !gui_yank) - { - /* - * Prepare to reselect and redo Visual: this is based on the - * size of the Visual text - */ - resel_VIsual_mode = VIsual_mode; - if (curwin->w_curswant == MAXCOL) - resel_VIsual_vcol = MAXCOL; - else - { - 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; - } - - /* can't redo yank (unless 'y' is in 'cpoptions') and ":" */ - if ((redo_yank || oap->op_type != OP_YANK) - && oap->op_type != OP_COLON -#ifdef FEAT_FOLDING - && oap->op_type != OP_FOLD - && oap->op_type != OP_FOLDOPEN - && oap->op_type != OP_FOLDOPENREC - && oap->op_type != OP_FOLDCLOSE - && oap->op_type != OP_FOLDCLOSEREC - && oap->op_type != OP_FOLDDEL - && oap->op_type != OP_FOLDDELREC -#endif - && oap->motion_force == NUL - ) - { - /* Prepare for redoing. Only use the nchar field for "r", - * otherwise it might be the second char of the operator. */ - if (cap->cmdchar == 'g' && (cap->nchar == 'n' - || cap->nchar == 'N')) - prep_redo(oap->regname, cap->count0, - get_op_char(oap->op_type), get_extra_op_char(oap->op_type), - oap->motion_force, cap->cmdchar, cap->nchar); - else if (cap->cmdchar != ':') - { - int nchar = oap->op_type == OP_REPLACE ? cap->nchar : NUL; - - /* reverse what nv_replace() did */ - if (nchar == REPLACE_CR_NCHAR) - nchar = CAR; - else if (nchar == REPLACE_NL_NCHAR) - nchar = NL; - prep_redo(oap->regname, 0L, NUL, 'v', - get_op_char(oap->op_type), - get_extra_op_char(oap->op_type), - nchar); - } - if (!redo_VIsual_busy) - { - redo_VIsual_mode = resel_VIsual_mode; - redo_VIsual_vcol = resel_VIsual_vcol; - redo_VIsual_line_count = resel_VIsual_line_count; - redo_VIsual_count = cap->count0; - redo_VIsual_arg = cap->arg; - } - } - - /* - * oap->inclusive defaults to TRUE. - * If oap->end is on a NUL (empty line) oap->inclusive becomes - * FALSE. This makes "d}P" and "v}dP" work the same. - */ - if (oap->motion_force == NUL || oap->motion_type == MLINE) - oap->inclusive = TRUE; - if (VIsual_mode == 'V') - oap->motion_type = MLINE; - else - { - oap->motion_type = MCHAR; - if (VIsual_mode != Ctrl_V && *ml_get_pos(&(oap->end)) == NUL - && (include_line_break || !virtual_op)) - { - 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) - { - ++oap->end.lnum; - oap->end.col = 0; - oap->end.coladd = 0; - ++oap->line_count; - } - } - } - - redo_VIsual_busy = FALSE; - - /* - * Switch Visual off now, so screen updating does - * not show inverted text when the screen is redrawn. - * With OP_YANK and sometimes with OP_COLON and OP_FILTER there is - * no screen redraw, so it is done here to remove the inverted - * part. - */ - if (!gui_yank) - { - VIsual_active = FALSE; -#ifdef FEAT_MOUSE - setmouse(); - mouse_dragging = 0; -#endif - may_clear_cmdline(); - if ((oap->op_type == OP_YANK - || oap->op_type == OP_COLON - || oap->op_type == OP_FUNCTION - || oap->op_type == OP_FILTER) - && oap->motion_force == NUL) - { -#ifdef FEAT_LINEBREAK - /* make sure redrawing is correct */ - curwin->w_p_lbr = lbr_saved; -#endif - redraw_curbuf_later(INVERTED); - } - } - } - - /* Include the trailing byte of a multi-byte char. */ - if (has_mbyte && oap->inclusive) - { - int l; - - l = (*mb_ptr2len)(ml_get_pos(&oap->end)); - if (l > 1) - oap->end.col += l - 1; - } - curwin->w_set_curswant = TRUE; - - /* - * oap->empty is set when start and end are the same. The inclusive - * flag affects this too, unless yanking and the end is on a NUL. - */ - oap->empty = (oap->motion_type == MCHAR - && (!oap->inclusive - || (oap->op_type == OP_YANK - && gchar_pos(&oap->end) == NUL)) - && EQUAL_POS(oap->start, oap->end) - && !(virtual_op && oap->start.coladd != oap->end.coladd)); - /* - * For delete, change and yank, it's an error to operate on an - * empty region, when 'E' included in 'cpoptions' (Vi compatible). - */ - empty_region_error = (oap->empty - && vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL); - - /* Force a redraw when operating on an empty Visual region, when - * 'modifiable is off or creating a fold. */ - if (oap->is_VIsual && (oap->empty || !curbuf->b_p_ma -#ifdef FEAT_FOLDING - || oap->op_type == OP_FOLD -#endif - )) - { -#ifdef FEAT_LINEBREAK - curwin->w_p_lbr = lbr_saved; -#endif - redraw_curbuf_later(INVERTED); - } - - /* - * If the end of an operator is in column one while oap->motion_type - * is MCHAR and oap->inclusive is FALSE, we put op_end after the last - * character in the previous line. If op_start is on or before the - * first non-blank in the line, the operator becomes linewise - * (strange, but that's the way vi does it). - */ - if ( oap->motion_type == MCHAR - && oap->inclusive == FALSE - && !(cap->retval & CA_NO_ADJ_OP_END) - && oap->end.col == 0 - && (!oap->is_VIsual || *p_sel == 'o') - && !oap->block_mode - && oap->line_count > 1) - { - oap->end_adjusted = TRUE; /* remember that we did this */ - --oap->line_count; - --oap->end.lnum; - if (inindent(0)) - oap->motion_type = MLINE; - else - { - oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum)); - if (oap->end.col) - { - --oap->end.col; - oap->inclusive = TRUE; - } - } - } - else - oap->end_adjusted = FALSE; - - switch (oap->op_type) - { - case OP_LSHIFT: - case OP_RSHIFT: - op_shift(oap, TRUE, oap->is_VIsual ? (int)cap->count1 : 1); - auto_format(FALSE, TRUE); - break; - - case OP_JOIN_NS: - case OP_JOIN: - if (oap->line_count < 2) - oap->line_count = 2; - if (curwin->w_cursor.lnum + oap->line_count - 1 > - curbuf->b_ml.ml_line_count) - beep_flush(); - else - { - (void)do_join(oap->line_count, oap->op_type == OP_JOIN, - TRUE, TRUE, TRUE); - auto_format(FALSE, TRUE); - } - break; - - case OP_DELETE: - VIsual_reselect = FALSE; /* don't reselect now */ - if (empty_region_error) - { - vim_beep(BO_OPER); - CancelRedo(); - } - else - { - (void)op_delete(oap); - if (oap->motion_type == MLINE && has_format_option(FO_AUTO)) - u_save_cursor(); /* cursor line wasn't saved yet */ - auto_format(FALSE, TRUE); - } - break; - - case OP_YANK: - if (empty_region_error) - { - if (!gui_yank) - { - vim_beep(BO_OPER); - CancelRedo(); - } - } - else - { -#ifdef FEAT_LINEBREAK - curwin->w_p_lbr = lbr_saved; -#endif - (void)op_yank(oap, FALSE, !gui_yank); - } - check_cursor_col(); - break; - - case OP_CHANGE: - VIsual_reselect = FALSE; /* don't reselect now */ - if (empty_region_error) - { - vim_beep(BO_OPER); - CancelRedo(); - } - else - { - /* This is a new edit command, not a restart. Need to - * remember it to make 'insertmode' work with mappings for - * Visual mode. But do this only once and not when typed and - * 'insertmode' isn't set. */ - if (p_im || !KeyTyped) - restart_edit_save = restart_edit; - else - restart_edit_save = 0; - restart_edit = 0; -#ifdef FEAT_LINEBREAK - /* Restore linebreak, so that when the user edits it looks as - * before. */ - if (curwin->w_p_lbr != lbr_saved) - { - curwin->w_p_lbr = lbr_saved; - get_op_vcol(oap, redo_VIsual_mode, FALSE); - } -#endif - /* Reset finish_op now, don't want it set inside edit(). */ - finish_op = FALSE; - if (op_change(oap)) /* will call edit() */ - cap->retval |= CA_COMMAND_BUSY; - if (restart_edit == 0) - restart_edit = restart_edit_save; - } - break; - - case OP_FILTER: - if (vim_strchr(p_cpo, CPO_FILTER) != NULL) - AppendToRedobuff((char_u *)"!\r"); /* use any last used !cmd */ - else - bangredo = TRUE; /* do_bang() will put cmd in redo buffer */ - /* FALLTHROUGH */ - - case OP_INDENT: - case OP_COLON: - -#if defined(FEAT_LISP) || defined(FEAT_CINDENT) - /* - * If 'equalprg' is empty, do the indenting internally. - */ - if (oap->op_type == OP_INDENT && *get_equalprg() == NUL) - { -# ifdef FEAT_LISP - if (curbuf->b_p_lisp) - { - op_reindent(oap, get_lisp_indent); - break; - } -# endif -# ifdef FEAT_CINDENT - op_reindent(oap, -# ifdef FEAT_EVAL - *curbuf->b_p_inde != NUL ? get_expr_indent : -# endif - get_c_indent); - break; -# endif - } -#endif - - op_colon(oap); - break; - - case OP_TILDE: - case OP_UPPER: - case OP_LOWER: - case OP_ROT13: - if (empty_region_error) - { - vim_beep(BO_OPER); - CancelRedo(); - } - else - op_tilde(oap); - check_cursor_col(); - break; - - case OP_FORMAT: -#if defined(FEAT_EVAL) - if (*curbuf->b_p_fex != NUL) - op_formatexpr(oap); /* use expression */ - else -#endif - if (*p_fp != NUL || *curbuf->b_p_fp != NUL) - op_colon(oap); /* use external command */ - else - op_format(oap, FALSE); /* use internal function */ - break; - - case OP_FORMAT2: - op_format(oap, TRUE); /* use internal function */ - break; - - case OP_FUNCTION: -#ifdef FEAT_LINEBREAK - /* Restore linebreak, so that when the user edits it looks as - * before. */ - curwin->w_p_lbr = lbr_saved; -#endif - op_function(oap); /* call 'operatorfunc' */ - break; - - case OP_INSERT: - case OP_APPEND: - VIsual_reselect = FALSE; /* don't reselect now */ - if (empty_region_error) - { - vim_beep(BO_OPER); - CancelRedo(); - } - else - { - /* This is a new edit command, not a restart. Need to - * remember it to make 'insertmode' work with mappings for - * Visual mode. But do this only once. */ - restart_edit_save = restart_edit; - restart_edit = 0; -#ifdef FEAT_LINEBREAK - /* Restore linebreak, so that when the user edits it looks as - * before. */ - if (curwin->w_p_lbr != lbr_saved) - { - curwin->w_p_lbr = lbr_saved; - get_op_vcol(oap, redo_VIsual_mode, FALSE); - } -#endif - op_insert(oap, cap->count1); -#ifdef FEAT_LINEBREAK - /* Reset linebreak, so that formatting works correctly. */ - curwin->w_p_lbr = FALSE; -#endif - - /* TODO: when inserting in several lines, should format all - * the lines. */ - auto_format(FALSE, TRUE); - - if (restart_edit == 0) - restart_edit = restart_edit_save; - else - cap->retval |= CA_COMMAND_BUSY; - } - break; - - case OP_REPLACE: - VIsual_reselect = FALSE; /* don't reselect now */ - if (empty_region_error) - { - vim_beep(BO_OPER); - CancelRedo(); - } - else - { -#ifdef FEAT_LINEBREAK - /* Restore linebreak, so that when the user edits it looks as - * before. */ - if (curwin->w_p_lbr != lbr_saved) - { - curwin->w_p_lbr = lbr_saved; - get_op_vcol(oap, redo_VIsual_mode, FALSE); - } -#endif - op_replace(oap, cap->nchar); - } - break; - -#ifdef FEAT_FOLDING - case OP_FOLD: - VIsual_reselect = FALSE; /* don't reselect now */ - foldCreate(oap->start.lnum, oap->end.lnum); - break; - - case OP_FOLDOPEN: - case OP_FOLDOPENREC: - case OP_FOLDCLOSE: - case OP_FOLDCLOSEREC: - VIsual_reselect = FALSE; /* don't reselect now */ - opFoldRange(oap->start.lnum, oap->end.lnum, - oap->op_type == OP_FOLDOPEN - || oap->op_type == OP_FOLDOPENREC, - oap->op_type == OP_FOLDOPENREC - || oap->op_type == OP_FOLDCLOSEREC, - oap->is_VIsual); - break; - - case OP_FOLDDEL: - case OP_FOLDDELREC: - VIsual_reselect = FALSE; /* don't reselect now */ - deleteFold(oap->start.lnum, oap->end.lnum, - oap->op_type == OP_FOLDDELREC, oap->is_VIsual); - break; -#endif - case OP_NR_ADD: - case OP_NR_SUB: - if (empty_region_error) - { - vim_beep(BO_OPER); - CancelRedo(); - } - else - { - VIsual_active = TRUE; -#ifdef FEAT_LINEBREAK - curwin->w_p_lbr = lbr_saved; -#endif - op_addsub(oap, cap->count1, redo_VIsual_arg); - VIsual_active = FALSE; - } - check_cursor_col(); - break; - default: - clearopbeep(oap); - } - virtual_op = MAYBE; - if (!gui_yank) - { - /* - * if 'sol' not set, go back to old column for some commands - */ - if (!p_sol && oap->motion_type == MLINE && !oap->end_adjusted - && (oap->op_type == OP_LSHIFT || oap->op_type == OP_RSHIFT - || oap->op_type == OP_DELETE)) - { -#ifdef FEAT_LINEBREAK - curwin->w_p_lbr = FALSE; -#endif - coladvance(curwin->w_curswant = old_col); - } - } - else - { - curwin->w_cursor = old_cursor; - } - oap->block_mode = FALSE; - clearop(oap); - motion_force = NUL; - } -#ifdef FEAT_LINEBREAK - curwin->w_p_lbr = lbr_saved; -#endif -} - -/* - * Handle indent and format operators and visual mode ":". - */ - static void -op_colon(oparg_T *oap) -{ - stuffcharReadbuff(':'); - if (oap->is_VIsual) - stuffReadbuff((char_u *)"'<,'>"); - else - { - /* - * Make the range look nice, so it can be repeated. - */ - if (oap->start.lnum == curwin->w_cursor.lnum) - stuffcharReadbuff('.'); - else - stuffnumReadbuff((long)oap->start.lnum); - if (oap->end.lnum != oap->start.lnum) - { - stuffcharReadbuff(','); - if (oap->end.lnum == curwin->w_cursor.lnum) - stuffcharReadbuff('.'); - else if (oap->end.lnum == curbuf->b_ml.ml_line_count) - stuffcharReadbuff('$'); - else if (oap->start.lnum == curwin->w_cursor.lnum) - { - stuffReadbuff((char_u *)".+"); - stuffnumReadbuff((long)oap->line_count - 1); - } - else - stuffnumReadbuff((long)oap->end.lnum); - } - } - if (oap->op_type != OP_COLON) - stuffReadbuff((char_u *)"!"); - if (oap->op_type == OP_INDENT) - { -#ifndef FEAT_CINDENT - if (*get_equalprg() == NUL) - stuffReadbuff((char_u *)"indent"); - else -#endif - stuffReadbuff(get_equalprg()); - stuffReadbuff((char_u *)"\n"); - } - else if (oap->op_type == OP_FORMAT) - { - if (*curbuf->b_p_fp != NUL) - stuffReadbuff(curbuf->b_p_fp); - else if (*p_fp != NUL) - stuffReadbuff(p_fp); - else - stuffReadbuff((char_u *)"fmt"); - stuffReadbuff((char_u *)"\n']"); - } - - /* - * do_cmdline() does the rest - */ -} - -/* - * Handle the "g@" operator: call 'operatorfunc'. - */ - static void -op_function(oparg_T *oap UNUSED) -{ -#ifdef FEAT_EVAL - typval_T argv[2]; - int save_virtual_op = virtual_op; - - if (*p_opfunc == NUL) - emsg(_("E774: 'operatorfunc' is empty")); - else - { - /* Set '[ and '] marks to text to be operated on. */ - curbuf->b_op_start = oap->start; - curbuf->b_op_end = oap->end; - if (oap->motion_type != MLINE && !oap->inclusive) - /* Exclude the end position. */ - decl(&curbuf->b_op_end); - - argv[0].v_type = VAR_STRING; - if (oap->block_mode) - argv[0].vval.v_string = (char_u *)"block"; - else if (oap->motion_type == MLINE) - argv[0].vval.v_string = (char_u *)"line"; - else - argv[0].vval.v_string = (char_u *)"char"; - argv[1].v_type = VAR_UNKNOWN; - - /* Reset virtual_op so that 'virtualedit' can be changed in the - * function. */ - virtual_op = MAYBE; - - (void)call_func_retnr(p_opfunc, 1, argv); - - virtual_op = save_virtual_op; - } -#else - emsg(_("E775: Eval feature not available")); -#endif -} - -/* * Check if highlighting for visual mode is possible, give a warning message * if not. */ @@ -2273,6 +1367,16 @@ reset_VIsual(void) } } + void +restore_visual_mode(void) +{ + if (VIsual_mode_orig != NUL) + { + curbuf->b_visual.vi_mode = VIsual_mode_orig; + VIsual_mode_orig = NUL; + } +} + /* * Check for a balloon-eval special item to include when searching for an * identifier. When "dir" is BACKWARD "ptr[-1]" must be valid! @@ -2611,7 +1715,7 @@ unshift_special(cmdarg_T *cap) * If the mode is currently displayed clear the command line or update the * command displayed. */ - static void + void may_clear_cmdline(void) { if (mode_displayed) @@ -7606,7 +6710,7 @@ adjust_for_sel(cmdarg_T *cap) * Should check VIsual_mode before calling this. * Returns TRUE when backed up to the previous line. */ - static int + int unadjust_for_sel(void) { pos_T *pp; @@ -8361,74 +7465,3 @@ nv_cursorhold(cmdarg_T *cap) did_cursorhold = TRUE; cap->retval |= CA_COMMAND_BUSY; /* don't call edit() now */ } - -/* - * Calculate start/end virtual columns for operating in block mode. - */ - static void -get_op_vcol( - oparg_T *oap, - colnr_T redo_VIsual_vcol, - int initial) /* when TRUE adjust position for 'selectmode' */ -{ - colnr_T start, end; - - if (VIsual_mode != Ctrl_V - || (!initial && oap->end.col < curwin->w_width)) - return; - - oap->block_mode = TRUE; - - /* prevent from moving onto a trail byte */ - if (has_mbyte) - mb_adjustpos(curwin->w_buffer, &oap->end); - - getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol); - - if (!redo_VIsual_busy) - { - getvvcol(curwin, &(oap->end), &start, NULL, &end); - - if (start < oap->start_vcol) - oap->start_vcol = start; - if (end > oap->end_vcol) - { - if (initial && *p_sel == 'e' && start >= 1 - && start - 1 >= oap->end_vcol) - oap->end_vcol = start - 1; - else - oap->end_vcol = end; - } - } - - /* if '$' was used, get oap->end_vcol from longest line */ - if (curwin->w_curswant == MAXCOL) - { - curwin->w_cursor.col = MAXCOL; - oap->end_vcol = 0; - for (curwin->w_cursor.lnum = oap->start.lnum; - curwin->w_cursor.lnum <= oap->end.lnum; - ++curwin->w_cursor.lnum) - { - getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end); - if (end > oap->end_vcol) - oap->end_vcol = end; - } - } - else if (redo_VIsual_busy) - 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. - * - * (Actually, this does convert column positions into character - * positions) - */ - curwin->w_cursor.lnum = oap->end.lnum; - coladvance(oap->end_vcol); - oap->end = curwin->w_cursor; - - curwin->w_cursor = oap->start; - coladvance(oap->start_vcol); - oap->start = curwin->w_cursor; -} |