diff options
Diffstat (limited to 'src/nvim/normal.c')
-rw-r--r-- | src/nvim/normal.c | 789 |
1 files changed, 431 insertions, 358 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 8f4240c062..b88cfb8926 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -451,12 +451,34 @@ static int find_command(int cmdchar) /// message, return true. static bool check_text_locked(oparg_T *oap) { - if (text_locked()) { + if (!text_locked()) { + return false; + } + + if (oap != NULL) { clearopbeep(oap); - text_locked_msg(); + } + text_locked_msg(); + return true; +} + +/// If text is locked, "curbuf->b_ro_locked" or "allbuf_lock" is set: +/// Give an error message, possibly beep and return true. +/// "oap" may be NULL. +static bool check_text_or_curbuf_locked(oparg_T *oap) +{ + if (check_text_locked(oap)) { return true; } - return false; + + if (!curbuf_locked()) { + return false; + } + + if (oap != NULL) { + clearop(oap); + } + return true; } /// Normal state entry point. This is called on: @@ -1107,8 +1129,7 @@ static int normal_execute(VimState *state, int key) goto finish; } - if ((nv_cmds[s->idx].cmd_flags & NV_NCW) - && (check_text_locked(&s->oa) || curbuf_locked())) { + if ((nv_cmds[s->idx].cmd_flags & NV_NCW) && check_text_or_curbuf_locked(&s->oa)) { // this command is not allowed now s->command_finished = true; goto finish; @@ -1505,8 +1526,7 @@ void restore_visual_mode(void) /// @param dir the direction of searching, is either FORWARD or BACKWARD /// @param *colp is in/decremented if "ptr[-dir]" should also be included. /// @param bnp points to a counter for square brackets. -static bool find_is_eval_item(const char_u *const ptr, int *const colp, int *const bnp, - const int dir) +static bool find_is_eval_item(const char *const ptr, int *const colp, int *const bnp, const int dir) { // Accept everything inside []. if ((*ptr == ']' && dir == BACKWARD) || (*ptr == '[' && dir == FORWARD)) { @@ -1614,7 +1634,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text || (find_type & FIND_IDENT)) && (!(find_type & FIND_EVAL) || prevcol == 0 - || !find_is_eval_item((char_u *)ptr + prevcol, &prevcol, &bn, BACKWARD))) { + || !find_is_eval_item(ptr + prevcol, &prevcol, &bn, BACKWARD))) { break; } col = prevcol; @@ -1657,7 +1677,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text : mb_get_class(ptr + col) != 0) || ((find_type & FIND_EVAL) && col <= (int)startcol - && find_is_eval_item((char_u *)ptr + col, &col, &bn, FORWARD)))) { + && find_is_eval_item(ptr + col, &col, &bn, FORWARD)))) { col += utfc_ptr2len(ptr + col); } @@ -1906,7 +1926,7 @@ bool add_to_showcmd(int c) } } - char *p = (char *)transchar(c); + char *p = transchar(c); if (*p == ' ') { STRCPY(p, "<20>"); } @@ -2191,17 +2211,19 @@ static void nv_addsub(cmdarg_T *cap) /// CTRL-F, CTRL-B, etc: Scroll page up or down. static void nv_page(cmdarg_T *cap) { - if (!checkclearop(cap->oap)) { - if (mod_mask & MOD_MASK_CTRL) { - // <C-PageUp>: tab page back; <C-PageDown>: tab page forward - if (cap->arg == BACKWARD) { - goto_tabpage(-(int)cap->count1); - } else { - goto_tabpage((int)cap->count0); - } + if (checkclearop(cap->oap)) { + return; + } + + if (mod_mask & MOD_MASK_CTRL) { + // <C-PageUp>: tab page back; <C-PageDown>: tab page forward + if (cap->arg == BACKWARD) { + goto_tabpage(-(int)cap->count1); } else { - (void)onepage(cap->arg, cap->count1); + goto_tabpage((int)cap->count0); } + } else { + (void)onepage(cap->arg, cap->count1); } } @@ -2213,22 +2235,23 @@ static void nv_gd(oparg_T *oap, int nchar, int thisblock) size_t len; char *ptr; if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0 - || !find_decl((char_u *)ptr, len, nchar == 'd', thisblock, SEARCH_START)) { + || !find_decl(ptr, len, nchar == 'd', thisblock, SEARCH_START)) { clearopbeep(oap); - } else { - if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) { - foldOpenCursor(); - } - // clear any search statistics - if (messaging() && !msg_silent && !shortmess(SHM_SEARCHCOUNT)) { - clear_cmdline = true; - } + return; + } + + if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) { + foldOpenCursor(); + } + // clear any search statistics + if (messaging() && !msg_silent && !shortmess(SHM_SEARCHCOUNT)) { + clear_cmdline = true; } } /// @return true if line[offset] is not inside a C-style comment or string, /// false otherwise. -static bool is_ident(const char_u *line, int offset) +static bool is_ident(const char *line, int offset) { bool incomment = false; int instring = 0; @@ -2236,11 +2259,11 @@ static bool is_ident(const char_u *line, int offset) for (int i = 0; i < offset && line[i] != NUL; i++) { if (instring != 0) { - if (prev != '\\' && line[i] == instring) { + if (prev != '\\' && (uint8_t)line[i] == instring) { instring = 0; } } else if ((line[i] == '"' || line[i] == '\'') && !incomment) { - instring = line[i]; + instring = (uint8_t)line[i]; } else { if (incomment) { if (prev == '*' && line[i] == '/') { @@ -2253,7 +2276,7 @@ static bool is_ident(const char_u *line, int offset) } } - prev = line[i]; + prev = (uint8_t)line[i]; } return incomment == false && instring == 0; @@ -2267,7 +2290,7 @@ static bool is_ident(const char_u *line, int offset) /// @param flags_arg flags passed to searchit() /// /// @return fail when not found. -bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_arg) +bool find_decl(char *ptr, size_t len, bool locally, bool thisblock, int flags_arg) { char *pat; pos_T old_pos; @@ -2285,7 +2308,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_ // Put "\V" before the pattern to avoid that the special meaning of "." // and "~" causes trouble. assert(len <= INT_MAX); - sprintf(pat, vim_iswordp((char *)ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", // NOLINT(runtime/printf) + sprintf(pat, vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", // NOLINT(runtime/printf) (int)len, ptr); old_pos = curwin->w_cursor; save_p_ws = p_ws; @@ -2313,7 +2336,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_ clearpos(&found_pos); for (;;) { t = searchit(curwin, curbuf, &curwin->w_cursor, NULL, FORWARD, - (char_u *)pat, 1L, searchflags, RE_LAST, NULL); + pat, 1L, searchflags, RE_LAST, NULL); if (curwin->w_cursor.lnum >= old_pos.lnum) { t = false; // match after start is failure too } @@ -2346,7 +2369,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_ curwin->w_cursor.col = 0; continue; } - bool valid = is_ident((char_u *)get_cursor_line_ptr(), curwin->w_cursor.col); + bool valid = is_ident(get_cursor_line_ptr(), curwin->w_cursor.col); // If the current position is not a valid identifier and a previous match is // present, favor that one instead. @@ -2527,7 +2550,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist) validate_virtcol(); colnr_T virtcol = curwin->w_virtcol; if (virtcol > (colnr_T)width1 && *get_showbreak_value(curwin) != NUL) { - virtcol -= vim_strsize((char *)get_showbreak_value(curwin)); + virtcol -= vim_strsize(get_showbreak_value(curwin)); } int c = utf_ptr2char(get_cursor_pos_ptr()); @@ -3195,44 +3218,45 @@ static void nv_colon(cmdarg_T *cap) if (VIsual_active && !is_cmdkey && !is_lua) { nv_operator(cap); - } else { - if (cap->oap->op_type != OP_NOP) { - // Using ":" as a movement is charwise exclusive. - cap->oap->motion_type = kMTCharWise; - cap->oap->inclusive = false; - } else if (cap->count0 && !is_cmdkey && !is_lua) { - // translate "count:" into ":.,.+(count - 1)" - stuffcharReadbuff('.'); - if (cap->count0 > 1) { - stuffReadbuff(",.+"); - stuffnumReadbuff(cap->count0 - 1L); - } - } + return; + } - // When typing, don't type below an old message - if (KeyTyped) { - compute_cmdrow(); + if (cap->oap->op_type != OP_NOP) { + // Using ":" as a movement is charwise exclusive. + cap->oap->motion_type = kMTCharWise; + cap->oap->inclusive = false; + } else if (cap->count0 && !is_cmdkey && !is_lua) { + // translate "count:" into ":.,.+(count - 1)" + stuffcharReadbuff('.'); + if (cap->count0 > 1) { + stuffReadbuff(",.+"); + stuffnumReadbuff(cap->count0 - 1L); } + } - if (is_lua) { - cmd_result = map_execute_lua(); - } else { - // get a command line and execute it - cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL, - cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0); - } + // When typing, don't type below an old message + if (KeyTyped) { + compute_cmdrow(); + } - if (cmd_result == false) { - // The Ex command failed, do not execute the operator. - clearop(cap->oap); - } else if (cap->oap->op_type != OP_NOP - && (cap->oap->start.lnum > curbuf->b_ml.ml_line_count - || cap->oap->start.col > - (colnr_T)strlen(ml_get(cap->oap->start.lnum)) - || did_emsg)) { - // The start of the operator has become invalid by the Ex command. - clearopbeep(cap->oap); - } + if (is_lua) { + cmd_result = map_execute_lua(); + } else { + // get a command line and execute it + cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL, + cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0); + } + + if (cmd_result == false) { + // The Ex command failed, do not execute the operator. + clearop(cap->oap); + } else if (cap->oap->op_type != OP_NOP + && (cap->oap->start.lnum > curbuf->b_ml.ml_line_count + || cap->oap->start.col > + (colnr_T)strlen(ml_get(cap->oap->start.lnum)) + || did_emsg)) { + // The start of the operator has become invalid by the Ex command. + clearopbeep(cap->oap); } } @@ -3263,14 +3287,16 @@ static void nv_ctrlh(cmdarg_T *cap) /// CTRL-L: clear screen and redraw. static void nv_clear(cmdarg_T *cap) { - if (!checkclearop(cap->oap)) { - // Clear all syntax states to force resyncing. - syn_stack_free_all(curwin->w_s); - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - wp->w_s->b_syn_slow = false; - } - redraw_later(curwin, UPD_CLEAR); + if (checkclearop(cap->oap)) { + return; + } + + // Clear all syntax states to force resyncing. + syn_stack_free_all(curwin->w_s); + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + wp->w_s->b_syn_slow = false; } + redraw_later(curwin, UPD_CLEAR); } /// CTRL-O: In Select mode: switch to Visual mode for one command. @@ -3301,21 +3327,23 @@ static void nv_hat(cmdarg_T *cap) /// "Z" commands. static void nv_Zet(cmdarg_T *cap) { - if (!checkclearopq(cap->oap)) { - switch (cap->nchar) { - // "ZZ": equivalent to ":x". - case 'Z': - do_cmdline_cmd("x"); - break; + if (checkclearopq(cap->oap)) { + return; + } - // "ZQ": equivalent to ":q!" (Elvis compatible). - case 'Q': - do_cmdline_cmd("q!"); - break; + switch (cap->nchar) { + // "ZZ": equivalent to ":x". + case 'Z': + do_cmdline_cmd("x"); + break; - default: - clearopbeep(cap->oap); - } + // "ZQ": equivalent to ":q!" (Elvis compatible). + case 'Q': + do_cmdline_cmd("q!"); + break; + + default: + clearopbeep(cap->oap); } } @@ -3446,7 +3474,7 @@ static void nv_ident(cmdarg_T *cap) // Allocate buffer to put the command in. Inserting backslashes can // double the length of the word. p_kp / curbuf->b_p_kp could be added // and some numbers. - char *kp = *curbuf->b_p_kp == NUL ? (char *)p_kp : curbuf->b_p_kp; // 'keywordprg' + char *kp = *curbuf->b_p_kp == NUL ? p_kp : curbuf->b_p_kp; // 'keywordprg' bool kp_help = (*kp == NUL || strcmp(kp, ":he") == 0 || strcmp(kp, ":help") == 0); if (kp_help && *skipwhite(ptr) == NUL) { emsg(_(e_noident)); // found white space only @@ -3532,7 +3560,7 @@ static void nv_ident(cmdarg_T *cap) p = buf + strlen(buf); while (n-- > 0) { // put a backslash before \ and some others - if (vim_strchr(aux_ptr, *ptr) != NULL) { + if (vim_strchr(aux_ptr, (uint8_t)(*ptr)) != NULL) { *p++ = '\\'; } // When current byte is a part of multibyte character, copy all @@ -3846,13 +3874,14 @@ static void nv_up(cmdarg_T *cap) // <S-Up> is page up cap->arg = BACKWARD; nv_page(cap); - } else { - cap->oap->motion_type = kMTLineWise; - if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == false) { - clearopbeep(cap->oap); - } else if (cap->arg) { - beginline(BL_WHITE | BL_FIX); - } + return; + } + + cap->oap->motion_type = kMTLineWise; + if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == false) { + clearopbeep(cap->oap); + } else if (cap->arg) { + beginline(BL_WHITE | BL_FIX); } } @@ -3895,15 +3924,11 @@ static void nv_gotofile(cmdarg_T *cap) char *ptr; linenr_T lnum = -1; - if (check_text_locked(cap->oap)) { - return; - } - if (curbuf_locked()) { - clearop(cap->oap); + if (check_text_or_curbuf_locked(cap->oap)) { return; } - ptr = (char *)grab_file_name(cap->count1, &lnum); + ptr = grab_file_name(cap->count1, &lnum); if (ptr != NULL) { // do autowrite if necessary @@ -3972,7 +3997,7 @@ static void nv_search(cmdarg_T *cap) // When using 'incsearch' the cursor may be moved to set a different search // start position. - cap->searchbuf = (char *)getcmdline(cap->cmdchar, cap->count1, 0, true); + cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0, true); if (cap->searchbuf == NULL) { clearop(oap); @@ -4058,22 +4083,23 @@ static void nv_csearch(cmdarg_T *cap) cap->oap->motion_type = kMTCharWise; if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == false) { clearopbeep(cap->oap); - } else { - curwin->w_set_curswant = true; - // Include a Tab for "tx" and for "dfx". - if (gchar_cursor() == TAB && virtual_active() && cap->arg == FORWARD - && (t_cmd || cap->oap->op_type != OP_NOP)) { - colnr_T scol, ecol; + return; + } - getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol); - curwin->w_cursor.coladd = ecol - scol; - } else { - curwin->w_cursor.coladd = 0; - } - adjust_for_sel(cap); - if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP) { - foldOpenCursor(); - } + curwin->w_set_curswant = true; + // Include a Tab for "tx" and for "dfx". + if (gchar_cursor() == TAB && virtual_active() && cap->arg == FORWARD + && (t_cmd || cap->oap->op_type != OP_NOP)) { + colnr_T scol, ecol; + + getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol); + curwin->w_cursor.coladd = ecol - scol; + } else { + curwin->w_cursor.coladd = 0; + } + adjust_for_sel(cap); + if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP) { + foldOpenCursor(); } } @@ -4395,25 +4421,28 @@ static void nv_brace(cmdarg_T *cap) cap->oap->inclusive = false; curwin->w_set_curswant = true; - if (findsent(cap->arg, cap->count1) == false) { + if (findsent(cap->arg, cap->count1) == FAIL) { clearopbeep(cap->oap); - } else { - // Don't leave the cursor on the NUL past end of line. - adjust_cursor(cap->oap); - curwin->w_cursor.coladd = 0; - if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) { - foldOpenCursor(); - } + return; + } + + // Don't leave the cursor on the NUL past end of line. + adjust_cursor(cap->oap); + curwin->w_cursor.coladd = 0; + if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) { + foldOpenCursor(); } } /// "m" command: Mark a position. static void nv_mark(cmdarg_T *cap) { - if (!checkclearop(cap->oap)) { - if (setmark(cap->nchar) == false) { - clearopbeep(cap->oap); - } + if (checkclearop(cap->oap)) { + return; + } + + if (setmark(cap->nchar) == false) { + clearopbeep(cap->oap); } } @@ -4427,11 +4456,12 @@ static void nv_findpar(cmdarg_T *cap) curwin->w_set_curswant = true; if (!findpar(&cap->oap->inclusive, cap->arg, cap->count1, NUL, false)) { clearopbeep(cap->oap); - } else { - curwin->w_cursor.coladd = 0; - if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) { - foldOpenCursor(); - } + return; + } + + curwin->w_cursor.coladd = 0; + if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) { + foldOpenCursor(); } } @@ -4452,14 +4482,16 @@ static void nv_undo(cmdarg_T *cap) /// <Undo> command. static void nv_kundo(cmdarg_T *cap) { - if (!checkclearopq(cap->oap)) { - if (bt_prompt(curbuf)) { - clearopbeep(cap->oap); - return; - } - u_undo((int)cap->count1); - curwin->w_set_curswant = true; + if (checkclearopq(cap->oap)) { + return; } + + if (bt_prompt(curbuf)) { + clearopbeep(cap->oap); + return; + } + u_undo((int)cap->count1); + curwin->w_set_curswant = true; } /// Handle the "r" command. @@ -4670,15 +4702,20 @@ static void nv_Replace(cmdarg_T *cap) VIsual_mode_orig = VIsual_mode; // remember original area for gv VIsual_mode = 'V'; nv_operator(cap); - } else if (!checkclearopq(cap->oap)) { - if (!MODIFIABLE(curbuf)) { - emsg(_(e_modifiable)); - } else { - if (virtual_active()) { - coladvance(getviscol()); - } - invoke_edit(cap, false, cap->arg ? 'V' : 'R', false); + return; + } + + if (checkclearopq(cap->oap)) { + return; + } + + if (!MODIFIABLE(curbuf)) { + emsg(_(e_modifiable)); + } else { + if (virtual_active()) { + coladvance(getviscol()); } + invoke_edit(cap, false, cap->arg ? 'V' : 'R', false); } } @@ -4689,20 +4726,25 @@ static void nv_vreplace(cmdarg_T *cap) cap->cmdchar = 'r'; cap->nchar = cap->extra_char; nv_replace(cap); // Do same as "r" in Visual mode for now - } else if (!checkclearopq(cap->oap)) { - if (!MODIFIABLE(curbuf)) { - emsg(_(e_modifiable)); - } else { - if (cap->extra_char == Ctrl_V) { // get another character - cap->extra_char = get_literal(false); - } - stuffcharReadbuff(cap->extra_char); - stuffcharReadbuff(ESC); - if (virtual_active()) { - coladvance(getviscol()); - } - invoke_edit(cap, true, 'v', false); + return; + } + + if (checkclearopq(cap->oap)) { + return; + } + + if (!MODIFIABLE(curbuf)) { + emsg(_(e_modifiable)); + } else { + if (cap->extra_char == Ctrl_V) { // get another character + cap->extra_char = get_literal(false); + } + stuffcharReadbuff(cap->extra_char); + stuffcharReadbuff(ESC); + if (virtual_active()) { + coladvance(getviscol()); } + invoke_edit(cap, true, 'v', false); } } @@ -4903,42 +4945,44 @@ static void nv_pcmark(cmdarg_T *cap) MarkMoveRes move_res = 0; // Result from moving to the mark const bool old_KeyTyped = KeyTyped; // getting file may reset it. - if (!checkclearopq(cap->oap)) { - if (cap->cmdchar == TAB && mod_mask == MOD_MASK_CTRL) { - if (!goto_tabpage_lastused()) { - clearopbeep(cap->oap); - } - return; - } + if (checkclearopq(cap->oap)) { + return; + } - if (cap->cmdchar == 'g') { - fm = get_changelist(curbuf, curwin, (int)cap->count1); - } else { - fm = get_jumplist(curwin, (int)cap->count1); - flags |= KMarkNoContext | kMarkJumpList; - } - // Changelist and jumplist have their own error messages. Therefore avoid - // calling nv_mark_move_to() when not found to avoid incorrect error - // messages. - if (fm != NULL) { - move_res = nv_mark_move_to(cap, flags, fm); - } else if (cap->cmdchar == 'g') { - if (curbuf->b_changelistlen == 0) { - emsg(_("E664: changelist is empty")); - } else if (cap->count1 < 0) { - emsg(_("E662: At start of changelist")); - } else { - emsg(_("E663: At end of changelist")); - } - } else { + if (cap->cmdchar == TAB && mod_mask == MOD_MASK_CTRL) { + if (!goto_tabpage_lastused()) { clearopbeep(cap->oap); } - if (cap->oap->op_type == OP_NOP - && (move_res & kMarkSwitchedBuf || move_res & kMarkChangedLine) - && (fdo_flags & FDO_MARK) - && old_KeyTyped) { - foldOpenCursor(); + return; + } + + if (cap->cmdchar == 'g') { + fm = get_changelist(curbuf, curwin, (int)cap->count1); + } else { + fm = get_jumplist(curwin, (int)cap->count1); + flags |= KMarkNoContext | kMarkJumpList; + } + // Changelist and jumplist have their own error messages. Therefore avoid + // calling nv_mark_move_to() when not found to avoid incorrect error + // messages. + if (fm != NULL) { + move_res = nv_mark_move_to(cap, flags, fm); + } else if (cap->cmdchar == 'g') { + if (curbuf->b_changelistlen == 0) { + emsg(_("E664: changelist is empty")); + } else if (cap->count1 < 0) { + emsg(_("E662: At start of changelist")); + } else { + emsg(_("E663: At end of changelist")); } + } else { + clearopbeep(cap->oap); + } + if (cap->oap->op_type == OP_NOP + && (move_res & kMarkSwitchedBuf || move_res & kMarkChangedLine) + && (fdo_flags & FDO_MARK) + && old_KeyTyped) { + foldOpenCursor(); } } @@ -5028,9 +5072,13 @@ static void nv_visual(cmdarg_T *cap) curwin->w_curswant = MAXCOL; coladvance(MAXCOL); } else if (VIsual_mode == Ctrl_V) { + // Update curswant on the original line, that is where "col" is valid. + linenr_T lnum = curwin->w_cursor.lnum; + curwin->w_cursor.lnum = VIsual.lnum; update_curswant_force(); assert(cap->count0 >= INT_MIN && cap->count0 <= INT_MAX); curwin->w_curswant += resel_VIsual_vcol * (int)cap->count0 - 1; + curwin->w_cursor.lnum = lnum; coladvance(curwin->w_curswant); } else { curwin->w_set_curswant = true; @@ -5669,42 +5717,46 @@ static void nv_g_cmd(cmdarg_T *cap) /// Handle "o" and "O" commands. static void n_opencmd(cmdarg_T *cap) { - if (!checkclearopq(cap->oap)) { - if (cap->cmdchar == 'O') { - // Open above the first line of a folded sequence of lines - (void)hasFolding(curwin->w_cursor.lnum, - &curwin->w_cursor.lnum, NULL); - } else { - // Open below the last line of a folded sequence of lines - (void)hasFolding(curwin->w_cursor.lnum, - NULL, &curwin->w_cursor.lnum); - } - if (u_save((linenr_T)(curwin->w_cursor.lnum - - (cap->cmdchar == 'O' ? 1 : 0)), - (linenr_T)(curwin->w_cursor.lnum + - (cap->cmdchar == 'o' ? 1 : 0))) - && open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD, - has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM : 0, - 0, NULL)) { - if (win_cursorline_standout(curwin)) { - // force redraw of cursorline - curwin->w_valid &= ~VALID_CROW; - } - invoke_edit(cap, false, cap->cmdchar, true); + if (checkclearopq(cap->oap)) { + return; + } + + if (cap->cmdchar == 'O') { + // Open above the first line of a folded sequence of lines + (void)hasFolding(curwin->w_cursor.lnum, + &curwin->w_cursor.lnum, NULL); + } else { + // Open below the last line of a folded sequence of lines + (void)hasFolding(curwin->w_cursor.lnum, + NULL, &curwin->w_cursor.lnum); + } + if (u_save((linenr_T)(curwin->w_cursor.lnum - + (cap->cmdchar == 'O' ? 1 : 0)), + (linenr_T)(curwin->w_cursor.lnum + + (cap->cmdchar == 'o' ? 1 : 0))) + && open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD, + has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM : 0, + 0, NULL)) { + if (win_cursorline_standout(curwin)) { + // force redraw of cursorline + curwin->w_valid &= ~VALID_CROW; } + invoke_edit(cap, false, cap->cmdchar, true); } } /// "." command: redo last change. static void nv_dot(cmdarg_T *cap) { - if (!checkclearopq(cap->oap)) { - // If "restart_edit" is true, the last but one command is repeated - // instead of the last command (inserting text). This is used for - // CTRL-O <.> in insert mode. - if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == false) { - clearopbeep(cap->oap); - } + if (checkclearopq(cap->oap)) { + return; + } + + // If "restart_edit" is true, the last but one command is repeated + // instead of the last command (inserting text). This is used for + // CTRL-O <.> in insert mode. + if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == false) { + clearopbeep(cap->oap); } } @@ -5728,10 +5780,12 @@ static void nv_redo_or_register(cmdarg_T *cap) return; } - if (!checkclearopq(cap->oap)) { - u_redo((int)cap->count1); - curwin->w_set_curswant = true; + if (checkclearopq(cap->oap)) { + return; } + + u_redo((int)cap->count1); + curwin->w_set_curswant = true; } /// Handle "U" command. @@ -5743,10 +5797,15 @@ static void nv_Undo(cmdarg_T *cap) cap->cmdchar = 'g'; cap->nchar = 'U'; nv_operator(cap); - } else if (!checkclearopq(cap->oap)) { - u_undoline(); - curwin->w_set_curswant = true; + return; } + + if (checkclearopq(cap->oap)) { + return; + } + + u_undoline(); + curwin->w_set_curswant = true; } /// '~' command: If tilde is not an operator and Visual is off: swap case of a @@ -6309,16 +6368,21 @@ static void nv_record(cmdarg_T *cap) cap->cmdchar = 'g'; cap->nchar = 'q'; nv_operator(cap); - } else if (!checkclearop(cap->oap)) { - if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') { - stuffcharReadbuff(cap->nchar); - stuffcharReadbuff(K_CMDWIN); - } else { - // (stop) recording into a named register, unless executing a - // register. - if (reg_executing == 0 && do_record(cap->nchar) == FAIL) { - clearopbeep(cap->oap); - } + return; + } + + if (checkclearop(cap->oap)) { + return; + } + + if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') { + stuffcharReadbuff(cap->nchar); + stuffcharReadbuff(K_CMDWIN); + } else { + // (stop) recording into a named register, unless executing a + // register. + if (reg_executing == 0 && do_record(cap->nchar) == FAIL) { + clearopbeep(cap->oap); } } } @@ -6360,24 +6424,29 @@ static void nv_join(cmdarg_T *cap) { if (VIsual_active) { // join the visual lines nv_operator(cap); - } else if (!checkclearop(cap->oap)) { - if (cap->count0 <= 1) { - cap->count0 = 2; // default for join is two lines! - } - if (curwin->w_cursor.lnum + cap->count0 - 1 > - curbuf->b_ml.ml_line_count) { - // can't join when on the last line - if (cap->count0 <= 2) { - clearopbeep(cap->oap); - return; - } - cap->count0 = curbuf->b_ml.ml_line_count - curwin->w_cursor.lnum + 1; - } + return; + } - prep_redo(cap->oap->regname, cap->count0, - NUL, cap->cmdchar, NUL, NUL, cap->nchar); - do_join((size_t)cap->count0, cap->nchar == NUL, true, true, true); + if (checkclearop(cap->oap)) { + return; } + + if (cap->count0 <= 1) { + cap->count0 = 2; // default for join is two lines! + } + if (curwin->w_cursor.lnum + cap->count0 - 1 > + curbuf->b_ml.ml_line_count) { + // can't join when on the last line + if (cap->count0 <= 2) { + clearopbeep(cap->oap); + return; + } + cap->count0 = curbuf->b_ml.ml_line_count - curwin->w_cursor.lnum + 1; + } + + prep_redo(cap->oap->regname, cap->count0, + NUL, cap->cmdchar, NUL, NUL, cap->nchar); + do_join((size_t)cap->count0, cap->nchar == NUL, true, true, true); } /// "P", "gP", "p" and "gp" commands. @@ -6407,117 +6476,121 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent) } else { clearopbeep(cap->oap); } - } else if (bt_prompt(curbuf) && !prompt_curpos_editable()) { - clearopbeep(cap->oap); - } else { - if (fix_indent) { - dir = (cap->cmdchar == ']' && cap->nchar == 'p') - ? FORWARD : BACKWARD; - flags |= PUT_FIXINDENT; - } else { - dir = (cap->cmdchar == 'P' - || ((cap->cmdchar == 'g' || cap->cmdchar == 'z') - && cap->nchar == 'P')) ? BACKWARD : FORWARD; - } - prep_redo_cmd(cap); - if (cap->cmdchar == 'g') { - flags |= PUT_CURSEND; - } else if (cap->cmdchar == 'z') { - flags |= PUT_BLOCK_INNER; - } + return; + } - if (VIsual_active) { - // Putting in Visual mode: The put text replaces the selected - // text. First delete the selected text, then put the new text. - // Need to save and restore the registers that the delete - // overwrites if the old contents is being put. - was_visual = true; - regname = cap->oap->regname; - bool keep_registers = cap->cmdchar == 'P'; - // '+' and '*' could be the same selection - bool clipoverwrite = (regname == '+' || regname == '*') && (cb_flags & CB_UNNAMEDMASK); - if (regname == 0 || regname == '"' || clipoverwrite - || ascii_isdigit(regname) || regname == '-') { - // The delete might overwrite the register we want to put, save it first - savereg = copy_register(regname); - } + if (bt_prompt(curbuf) && !prompt_curpos_editable()) { + clearopbeep(cap->oap); + return; + } - // To place the cursor correctly after a blockwise put, and to leave the - // text in the correct position when putting over a selection with - // 'virtualedit' and past the end of the line, we use the 'c' operator in - // do_put(), which requires the visual selection to still be active. - if (!VIsual_active || VIsual_mode == 'V' || regname != '.') { - // Now delete the selected text. Avoid messages here. - cap->cmdchar = 'd'; - cap->nchar = NUL; - cap->oap->regname = keep_registers ? '_' : NUL; - msg_silent++; - nv_operator(cap); - do_pending_operator(cap, 0, false); - empty = (curbuf->b_ml.ml_flags & ML_EMPTY); - msg_silent--; + if (fix_indent) { + dir = (cap->cmdchar == ']' && cap->nchar == 'p') + ? FORWARD : BACKWARD; + flags |= PUT_FIXINDENT; + } else { + dir = (cap->cmdchar == 'P' + || ((cap->cmdchar == 'g' || cap->cmdchar == 'z') + && cap->nchar == 'P')) ? BACKWARD : FORWARD; + } + prep_redo_cmd(cap); + if (cap->cmdchar == 'g') { + flags |= PUT_CURSEND; + } else if (cap->cmdchar == 'z') { + flags |= PUT_BLOCK_INNER; + } - // delete PUT_LINE_BACKWARD; - cap->oap->regname = regname; - } + if (VIsual_active) { + // Putting in Visual mode: The put text replaces the selected + // text. First delete the selected text, then put the new text. + // Need to save and restore the registers that the delete + // overwrites if the old contents is being put. + was_visual = true; + regname = cap->oap->regname; + bool keep_registers = cap->cmdchar == 'P'; + // '+' and '*' could be the same selection + bool clipoverwrite = (regname == '+' || regname == '*') && (cb_flags & CB_UNNAMEDMASK); + if (regname == 0 || regname == '"' || clipoverwrite + || ascii_isdigit(regname) || regname == '-') { + // The delete might overwrite the register we want to put, save it first + savereg = copy_register(regname); + } + + // To place the cursor correctly after a blockwise put, and to leave the + // text in the correct position when putting over a selection with + // 'virtualedit' and past the end of the line, we use the 'c' operator in + // do_put(), which requires the visual selection to still be active. + if (!VIsual_active || VIsual_mode == 'V' || regname != '.') { + // Now delete the selected text. Avoid messages here. + cap->cmdchar = 'd'; + cap->nchar = NUL; + cap->oap->regname = keep_registers ? '_' : NUL; + msg_silent++; + nv_operator(cap); + do_pending_operator(cap, 0, false); + empty = (curbuf->b_ml.ml_flags & ML_EMPTY); + msg_silent--; - // When deleted a linewise Visual area, put the register as - // lines to avoid it joined with the next line. When deletion was - // charwise, split a line when putting lines. - if (VIsual_mode == 'V') { - flags |= PUT_LINE; - } else if (VIsual_mode == 'v') { - flags |= PUT_LINE_SPLIT; - } - if (VIsual_mode == Ctrl_V && dir == FORWARD) { - flags |= PUT_LINE_FORWARD; - } - dir = BACKWARD; - if ((VIsual_mode != 'V' - && curwin->w_cursor.col < curbuf->b_op_start.col) - || (VIsual_mode == 'V' - && curwin->w_cursor.lnum < curbuf->b_op_start.lnum)) { - // cursor is at the end of the line or end of file, put - // forward. - dir = FORWARD; - } - // May have been reset in do_put(). - VIsual_active = true; + // delete PUT_LINE_BACKWARD; + cap->oap->regname = regname; } - do_put(cap->oap->regname, savereg, dir, cap->count1, flags); - // If a register was saved, free it - if (savereg != NULL) { - free_register(savereg); - xfree(savereg); + // When deleted a linewise Visual area, put the register as + // lines to avoid it joined with the next line. When deletion was + // charwise, split a line when putting lines. + if (VIsual_mode == 'V') { + flags |= PUT_LINE; + } else if (VIsual_mode == 'v') { + flags |= PUT_LINE_SPLIT; + } + if (VIsual_mode == Ctrl_V && dir == FORWARD) { + flags |= PUT_LINE_FORWARD; + } + dir = BACKWARD; + if ((VIsual_mode != 'V' + && curwin->w_cursor.col < curbuf->b_op_start.col) + || (VIsual_mode == 'V' + && curwin->w_cursor.lnum < curbuf->b_op_start.lnum)) { + // cursor is at the end of the line or end of file, put + // forward. + dir = FORWARD; } + // May have been reset in do_put(). + VIsual_active = true; + } + do_put(cap->oap->regname, savereg, dir, cap->count1, flags); - // What to reselect with "gv"? Selecting the just put text seems to - // be the most useful, since the original text was removed. - if (was_visual) { - curbuf->b_visual.vi_start = curbuf->b_op_start; - curbuf->b_visual.vi_end = curbuf->b_op_end; - // need to adjust cursor position - if (*p_sel == 'e') { - inc(&curbuf->b_visual.vi_end); - } + // If a register was saved, free it + if (savereg != NULL) { + free_register(savereg); + xfree(savereg); + } + + // What to reselect with "gv"? Selecting the just put text seems to + // be the most useful, since the original text was removed. + if (was_visual) { + curbuf->b_visual.vi_start = curbuf->b_op_start; + curbuf->b_visual.vi_end = curbuf->b_op_end; + // need to adjust cursor position + if (*p_sel == 'e') { + inc(&curbuf->b_visual.vi_end); } + } - // When all lines were selected and deleted do_put() leaves an empty - // line that needs to be deleted now. - if (empty && *ml_get(curbuf->b_ml.ml_line_count) == NUL) { - ml_delete(curbuf->b_ml.ml_line_count, true); - deleted_lines(curbuf->b_ml.ml_line_count + 1, 1); + // When all lines were selected and deleted do_put() leaves an empty + // line that needs to be deleted now. + if (empty && *ml_get(curbuf->b_ml.ml_line_count) == NUL) { + ml_delete(curbuf->b_ml.ml_line_count, true); + deleted_lines(curbuf->b_ml.ml_line_count + 1, 1); - // If the cursor was in that line, move it to the end of the last - // line. - if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) { - curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; - coladvance(MAXCOL); - } + // If the cursor was in that line, move it to the end of the last + // line. + if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) { + curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; + coladvance(MAXCOL); } - auto_format(false, true); } + auto_format(false, true); } /// "o" and "O" commands. |