diff options
Diffstat (limited to 'src/nvim/edit.c')
| -rw-r--r-- | src/nvim/edit.c | 698 |
1 files changed, 244 insertions, 454 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 96df6a3044..71a12ea1b0 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // edit.c: functions for Insert mode #include <assert.h> @@ -10,8 +7,9 @@ #include <string.h> #include <sys/types.h> -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/autocmd.h" +#include "nvim/autocmd_defs.h" #include "nvim/buffer.h" #include "nvim/change.h" #include "nvim/charset.h" @@ -26,17 +24,18 @@ #include "nvim/extmark.h" #include "nvim/fileio.h" #include "nvim/fold.h" +#include "nvim/func_attr.h" #include "nvim/getchar.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/grid.h" -#include "nvim/highlight_defs.h" +#include "nvim/highlight.h" #include "nvim/highlight_group.h" #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/insexpand.h" #include "nvim/keycodes.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/mbyte.h" @@ -48,11 +47,11 @@ #include "nvim/normal.h" #include "nvim/ops.h" #include "nvim/option.h" +#include "nvim/option_vars.h" #include "nvim/os/input.h" #include "nvim/plines.h" #include "nvim/popupmenu.h" -#include "nvim/pos.h" -#include "nvim/screen.h" +#include "nvim/pos_defs.h" #include "nvim/search.h" #include "nvim/state.h" #include "nvim/strings.h" @@ -60,10 +59,10 @@ #include "nvim/terminal.h" #include "nvim/textformat.h" #include "nvim/textobject.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/ui.h" #include "nvim/undo.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #include "nvim/window.h" typedef struct insert_state { @@ -73,7 +72,7 @@ typedef struct insert_state { int cmdchar; int cmdchar_todo; // cmdchar to handle once in init_prompt int startln; - long count; + int count; int c; int lastc; int i; @@ -138,7 +137,7 @@ static void insert_enter(InsertState *s) did_restart_edit = restart_edit; // sleep before redrawing, needed for "CTRL-O :" that results in an // error message - check_for_delay(true); + msg_check_for_delay(true); // set Insstart_orig to Insstart update_Insstart_orig = true; @@ -194,7 +193,7 @@ static void insert_enter(InsertState *s) } } - Insstart_textlen = (colnr_T)linetabsize(get_cursor_line_ptr()); + Insstart_textlen = linetabsize_str(get_cursor_line_ptr()); Insstart_blank_vcol = MAXCOL; if (!did_ai) { @@ -232,8 +231,9 @@ static void insert_enter(InsertState *s) may_trigger_modechanged(); stop_insert_mode = false; - // need to position cursor again when on a TAB - if (gchar_cursor() == TAB) { + // need to position cursor again when on a TAB and + // when on a char with inline virtual text + if (gchar_cursor() == TAB || curbuf->b_virt_text_inline > 0) { curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL); } @@ -355,6 +355,7 @@ static void insert_enter(InsertState *s) ins_apply_autocmds(EVENT_INSERTLEAVE); } did_cursorhold = false; + curbuf->b_last_changedtick = buf_get_changedtick(curbuf); } static int insert_check(VimState *state) @@ -394,6 +395,13 @@ static int insert_check(VimState *state) Insstart_orig = Insstart; } + if (curbuf->terminal) { + // Exit Insert mode and go to Terminal mode. + stop_insert_mode = true; + restart_edit = 'I'; + stuffcharReadbuff(K_NOP); + } + if (stop_insert_mode && !ins_compl_active()) { // ":stopinsert" used s->count = 0; @@ -523,10 +531,6 @@ static int insert_execute(VimState *state, int key) did_cursorhold = true; } - if (p_hkmap && KeyTyped) { - s->c = hkmap(s->c); // Hebrew mode mapping - } - // Special handling of keys while the popup menu is visible or wanted // and the cursor is still in the completed word. Only when there is // a match, skip this when no matches were found. @@ -558,10 +562,9 @@ static int insert_execute(VimState *state, int key) if (ins_compl_accept_char(s->c)) { // Trigger InsertCharPre. char *str = do_insert_char_pre(s->c); - char *p; if (str != NULL) { - for (p = str; *p != NUL; MB_PTR_ADV(p)) { + for (char *p = str; *p != NUL; MB_PTR_ADV(p)) { ins_compl_addleader(utf_ptr2char(p)); } xfree(str); @@ -615,7 +618,9 @@ static int insert_execute(VimState *state, int key) } } - s->c = do_digraph(s->c); + if (s->c != K_EVENT) { + s->c = do_digraph(s->c); + } if ((s->c == Ctrl_V || s->c == Ctrl_Q) && ctrl_x_mode_cmdline()) { insert_do_complete(s); @@ -754,7 +759,7 @@ static int insert_handle_key(InsertState *s) case Ctrl_A: // For ^@ the trailing ESC will end the insert, unless there is an // error. - if (stuff_inserted(NUL, 1L, (s->c == Ctrl_A)) == FAIL + if (stuff_inserted(NUL, 1, (s->c == Ctrl_A)) == FAIL && s->c != Ctrl_A) { return 0; // exit insert mode } @@ -880,14 +885,18 @@ static int insert_handle_key(InsertState *s) case K_EVENT: // some event state_handle_k_event(); + // If CTRL-G U was used apply it to the next typed key. + if (dont_sync_undo == kTrue) { + dont_sync_undo = kNone; + } goto check_pum; - case K_COMMAND: // some command + case K_COMMAND: // <Cmd>command<CR> do_cmdline(NULL, getcmdkeycmd, NULL, 0); goto check_pum; case K_LUA: - map_execute_lua(); + map_execute_lua(false); check_pum: // nvim_select_popupmenu_item() can be called from the handling of @@ -1122,12 +1131,11 @@ normalchar: if (!p_paste) { // Trigger InsertCharPre. char *str = do_insert_char_pre(s->c); - char *p; if (str != NULL) { if (*str != NUL && stop_arrow() != FAIL) { // Insert the new value of v:char literally. - for (p = str; *p != NUL; MB_PTR_ADV(p)) { + for (char *p = str; *p != NUL; MB_PTR_ADV(p)) { s->c = utf_ptr2char(p); if (s->c == CAR || s->c == K_KENTER || s->c == NL) { ins_eol(s->c); @@ -1229,7 +1237,7 @@ static void insert_do_cindent(InsertState *s) /// @param count repeat count for the command /// /// @return true if a CTRL-O command caused the return (insert mode pending). -bool edit(int cmdchar, bool startln, long count) +bool edit(int cmdchar, bool startln, int count) { if (curbuf->terminal) { if (ex_normal_busy) { @@ -1252,12 +1260,14 @@ bool edit(int cmdchar, bool startln, long count) // Don't allow changes in the buffer while editing the cmdline. The // caller of getcmdline() may get confused. // Don't allow recursive insert mode when busy with completion. - if (textlock != 0 || ins_compl_active() || compl_busy || pum_visible()) { + // Allow in dummy buffers since they are only used internally + if (textlock != 0 || ins_compl_active() || compl_busy || pum_visible() + || expr_map_locked()) { emsg(_(e_textlock)); return false; } - InsertState state, *s = &state; + InsertState s[1]; memset(s, 0, sizeof(InsertState)); s->state.execute = insert_execute; s->state.check = insert_check; @@ -1289,7 +1299,8 @@ void ins_redraw(bool ready) // Trigger CursorMoved if the cursor moved. Not when the popup menu is // visible, the command might delete it. if (ready && has_event(EVENT_CURSORMOVEDI) - && !equalpos(curwin->w_last_cursormoved, curwin->w_cursor) + && (last_cursormoved_win != curwin + || !equalpos(last_cursormoved, curwin->w_cursor)) && !pum_visible()) { // Need to update the screen first, to make sure syntax // highlighting is correct after making a change (e.g., inserting @@ -1302,12 +1313,13 @@ void ins_redraw(bool ready) // getcurpos() update_curswant(); ins_apply_autocmds(EVENT_CURSORMOVEDI); - curwin->w_last_cursormoved = curwin->w_cursor; + last_cursormoved_win = curwin; + last_cursormoved = curwin->w_cursor; } - // Trigger TextChangedI if changedtick differs. + // Trigger TextChangedI if changedtick_i differs. if (ready && has_event(EVENT_TEXTCHANGEDI) - && curbuf->b_last_changedtick != buf_get_changedtick(curbuf) + && curbuf->b_last_changedtick_i != buf_get_changedtick(curbuf) && !pum_visible()) { aco_save_T aco; varnumber_T tick = buf_get_changedtick(curbuf); @@ -1316,16 +1328,16 @@ void ins_redraw(bool ready) aucmd_prepbuf(&aco, curbuf); apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, false, curbuf); aucmd_restbuf(&aco); - curbuf->b_last_changedtick = buf_get_changedtick(curbuf); + curbuf->b_last_changedtick_i = buf_get_changedtick(curbuf); if (tick != buf_get_changedtick(curbuf)) { // see ins_apply_autocmds() u_save(curwin->w_cursor.lnum, (linenr_T)(curwin->w_cursor.lnum + 1)); } } - // Trigger TextChangedP if changedtick differs. When the popupmenu closes - // TextChangedI will need to trigger for backwards compatibility, thus use - // different b_last_changedtick* variables. + // Trigger TextChangedP if changedtick_pum differs. When the popupmenu + // closes TextChangedI will need to trigger for backwards compatibility, + // thus use different b_last_changedtick* variables. if (ready && has_event(EVENT_TEXTCHANGEDP) && curbuf->b_last_changedtick_pum != buf_get_changedtick(curbuf) && pum_visible()) { @@ -1355,13 +1367,21 @@ void ins_redraw(bool ready) curbuf->b_changed_invalid = false; } + // Trigger SafeState if nothing is pending. + may_trigger_safestate(ready + && !ins_compl_active() + && !pum_visible()); + pum_check_clear(); + show_cursor_info_later(false); if (must_redraw) { update_screen(); - } else if (clear_cmdline || redraw_cmdline) { - showmode(); // clear cmdline and show mode + } else { + redraw_statuslines(); + if (clear_cmdline || redraw_cmdline || redraw_mode) { + showmode(); // clear cmdline and show mode + } } - show_cursor_info(false); setcursor(); emsg_on_display = false; // may remove error message now } @@ -1369,7 +1389,6 @@ void ins_redraw(bool ready) // Handle a CTRL-V or CTRL-Q typed in Insert mode. static void ins_ctrl_v(void) { - int c; bool did_putchar = false; // may need to redraw when no more chars available now @@ -1384,7 +1403,7 @@ static void ins_ctrl_v(void) add_to_showcmd_c(Ctrl_V); // Do not include modifiers into the key for CTRL-SHIFT-V. - c = get_literal(mod_mask & MOD_MASK_SHIFT); + int c = get_literal(mod_mask & MOD_MASK_SHIFT); if (did_putchar) { // when the line fits in 'columns' the '^' is at the start of the next // line and will not removed by the redraw @@ -1399,20 +1418,19 @@ static void ins_ctrl_v(void) // Put a character directly onto the screen. It's not stored in a buffer. // Used while handling CTRL-K, CTRL-V, etc. in Insert mode. static int pc_status; -#define PC_STATUS_UNSET 0 // pc_bytes was not set -#define PC_STATUS_RIGHT 1 // right half of double-wide char -#define PC_STATUS_LEFT 2 // left half of double-wide char -#define PC_STATUS_SET 3 // pc_bytes was filled -static char_u pc_bytes[MB_MAXBYTES + 1]; // saved bytes +#define PC_STATUS_UNSET 0 // nothing was put on screen +#define PC_STATUS_RIGHT 1 // right half of double-wide char +#define PC_STATUS_LEFT 2 // left half of double-wide char +#define PC_STATUS_SET 3 // pc_schar was filled +static schar_T pc_schar; // saved char static int pc_attr; static int pc_row; static int pc_col; void edit_putchar(int c, bool highlight) { - int attr; - if (curwin->w_grid_alloc.chars != NULL || default_grid.chars != NULL) { + int attr; update_topline(curwin); // just in case w_topline isn't valid validate_cursor(); if (highlight) { @@ -1421,30 +1439,34 @@ void edit_putchar(int c, bool highlight) attr = 0; } pc_row = curwin->w_wrow; - pc_col = 0; pc_status = PC_STATUS_UNSET; + grid_line_start(&curwin->w_grid, pc_row); if (curwin->w_p_rl) { - pc_col += curwin->w_grid.cols - 1 - curwin->w_wcol; - const int fix_col = grid_fix_col(&curwin->w_grid, pc_col, pc_row); + pc_col = curwin->w_grid.cols - 1 - curwin->w_wcol; - if (fix_col != pc_col) { - grid_putchar(&curwin->w_grid, ' ', pc_row, fix_col, attr); + if (grid_line_getchar(pc_col, NULL) == NUL) { + grid_line_put_schar(pc_col - 1, schar_from_ascii(' '), attr); curwin->w_wcol--; pc_status = PC_STATUS_RIGHT; } } else { - pc_col += curwin->w_wcol; - if (grid_lefthalve(&curwin->w_grid, pc_row, pc_col)) { + pc_col = curwin->w_wcol; + + if (grid_line_getchar(pc_col + 1, NULL) == NUL) { + // pc_col is the left half of a double-width char pc_status = PC_STATUS_LEFT; } } // save the character to be able to put it back if (pc_status == PC_STATUS_UNSET) { - grid_getbytes(&curwin->w_grid, pc_row, pc_col, (char *)pc_bytes, &pc_attr); + pc_schar = grid_line_getchar(pc_col, &pc_attr); pc_status = PC_STATUS_SET; } - grid_putchar(&curwin->w_grid, c, pc_row, pc_col, attr); + + char buf[MB_MAXCHAR + 1]; + grid_line_puts(pc_col, buf, utf_char2bytes(c, buf), attr); + grid_line_flush(); } } @@ -1470,10 +1492,9 @@ char *prompt_text(void) static void init_prompt(int cmdchar_todo) { char *prompt = prompt_text(); - char *text; curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; - text = get_cursor_line_ptr(); + char *text = get_cursor_line_ptr(); if (strncmp(text, prompt, strlen(prompt)) != 0) { // prompt is missing, insert it or append a line with it if (*text == NUL) { @@ -1517,29 +1538,32 @@ bool prompt_curpos_editable(void) // Undo the previous edit_putchar(). void edit_unputchar(void) { - if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled) { + if (pc_status != PC_STATUS_UNSET) { if (pc_status == PC_STATUS_RIGHT) { curwin->w_wcol++; } if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) { redrawWinline(curwin, curwin->w_cursor.lnum); } else { - grid_puts(&curwin->w_grid, (char *)pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr); + // TODO(bfredl): this could be smarter and also handle the dubyawidth case + grid_line_start(&curwin->w_grid, pc_row); + grid_line_put_schar(pc_col, pc_schar, pc_attr); + grid_line_flush(); } } } -// Called when p_dollar is set: display a '$' at the end of the changed text -// Only works when cursor is in the line that changes. -void display_dollar(colnr_T col) +/// Called when "$" is in 'cpoptions': display a '$' at the end of the changed +/// text. Only works when cursor is in the line that changes. +void display_dollar(colnr_T col_arg) { - colnr_T save_col; + colnr_T col = col_arg < 0 ? 0 : col_arg; if (!redrawing()) { return; } - save_col = curwin->w_cursor.col; + colnr_T save_col = curwin->w_cursor.col; curwin->w_cursor.col = col; // If on the last byte of a multi-byte move to the first byte. @@ -1574,16 +1598,9 @@ void undisplay_dollar(void) /// @param call_changed_bytes call changed_bytes() void change_indent(int type, int amount, int round, int replaced, int call_changed_bytes) { - int vcol; - int last_vcol; int insstart_less; // reduction for Insstart.col - int new_cursor_col; - char *ptr; - int save_p_list; - int start_col; - colnr_T vc; colnr_T orig_col = 0; // init for GCC - char *new_line, *orig_line = NULL; // init for GCC + char *orig_line = NULL; // init for GCC // MODE_VREPLACE state needs to know what the line was like before changing if (State & VREPLACE_FLAG) { @@ -1592,18 +1609,18 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang } // for the following tricks we don't want list mode - save_p_list = curwin->w_p_list; + int save_p_list = curwin->w_p_list; curwin->w_p_list = false; - vc = getvcol_nolist(&curwin->w_cursor); - vcol = vc; + colnr_T vc = getvcol_nolist(&curwin->w_cursor); + int vcol = vc; // For Replace mode we need to fix the replace stack later, which is only // possible when the cursor is in the indent. Remember the number of // characters before the cursor if it's possible. - start_col = curwin->w_cursor.col; + int start_col = curwin->w_cursor.col; // determine offset from first non-blank - new_cursor_col = curwin->w_cursor.col; + int new_cursor_col = curwin->w_cursor.col; beginline(BL_WHITE); new_cursor_col -= curwin->w_cursor.col; @@ -1656,8 +1673,8 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol); // Advance the cursor until we reach the right screen column. - last_vcol = 0; - ptr = get_cursor_line_ptr(); + int last_vcol = 0; + char *ptr = get_cursor_line_ptr(); chartabsize_T cts; init_chartabsize_arg(&cts, curwin, 0, 0, ptr, ptr); while (cts.cts_vcol <= (int)curwin->w_virtcol) { @@ -1699,7 +1716,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang curwin->w_cursor.col = (colnr_T)new_cursor_col; } curwin->w_set_curswant = true; - changed_cline_bef_curs(); + changed_cline_bef_curs(curwin); // May have to adjust the start of the insert. if (State & MODE_INSERT) { @@ -1742,7 +1759,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang // then put it back again the way we wanted it. if (State & VREPLACE_FLAG) { // Save new line - new_line = xstrdup(get_cursor_line_ptr()); + char *new_line = xstrdup(get_cursor_line_ptr()); // We only put back the new line up to the cursor new_line[curwin->w_cursor.col] = NUL; @@ -1847,9 +1864,7 @@ static bool del_char_after_col(int limit_col) /// @param no_simplify do not include modifiers into the key int get_literal(bool no_simplify) { - int cc; int nc; - int i; bool hex = false; bool octal = false; int unicode = 0; @@ -1859,9 +1874,9 @@ int get_literal(bool no_simplify) } no_mapping++; // don't map the next key hits - cc = 0; - i = 0; - for (;;) { + int cc = 0; + int i = 0; + while (true) { nc = plain_vgetc(); if (!no_simplify) { nc = merge_modifiers(nc, &mod_mask); @@ -1949,9 +1964,6 @@ int get_literal(bool no_simplify) /// @param ctrlv `c` was typed after CTRL-V static void insert_special(int c, int allow_modmask, int ctrlv) { - char *p; - int len; - // Special function key, translate into "<Key>". Up to the last '>' is // inserted with ins_str(), so as not to replace characters in replace // mode. @@ -1961,8 +1973,8 @@ static void insert_special(int c, int allow_modmask, int ctrlv) allow_modmask = true; } if (IS_SPECIAL(c) || (mod_mask && allow_modmask)) { - p = (char *)get_special_key_name(c, mod_mask); - len = (int)strlen(p); + char *p = get_special_key_name(c, mod_mask); + int len = (int)strlen(p); c = (uint8_t)p[len - 1]; if (len > 2) { if (stop_arrow() == FAIL) { @@ -2041,7 +2053,7 @@ void insertchar(int c, int flags, int second_indent) if (*curbuf->b_p_fex != NUL && (flags & INSCHAR_NO_FEX) == 0 && (force_format || virtcol > (colnr_T)textwidth)) { - do_internal = (fex_format(curwin->w_cursor.lnum, 1L, c) != 0); + do_internal = (fex_format(curwin->w_cursor.lnum, 1, c) != 0); // It may be required to save for undo again, e.g. when setline() // was called. ins_need_undo = true; @@ -2057,7 +2069,7 @@ void insertchar(int c, int flags, int second_indent) // Check whether this character should end a comment. if (did_ai && c == end_comment_pending) { - char_u lead_end[COM_MAX_LEN]; // end-comment string + char lead_end[COM_MAX_LEN]; // end-comment string // Need to remove existing (middle) comment leader and insert end // comment leader. First, check what comment leader we can find. @@ -2068,7 +2080,7 @@ void insertchar(int c, int flags, int second_indent) while (*p && p[-1] != ':') { // find end of middle flags p++; } - int middle_len = (int)copy_option_part(&p, (char *)lead_end, COM_MAX_LEN, ","); + int middle_len = (int)copy_option_part(&p, lead_end, COM_MAX_LEN, ","); // Don't count trailing white space for middle_len while (middle_len > 0 && ascii_iswhite(lead_end[middle_len - 1])) { middle_len--; @@ -2078,7 +2090,7 @@ void insertchar(int c, int flags, int second_indent) while (*p && p[-1] != ':') { // find end of end flags p++; } - int end_len = (int)copy_option_part(&p, (char *)lead_end, COM_MAX_LEN, ","); + int end_len = (int)copy_option_part(&p, lead_end, COM_MAX_LEN, ","); // Skip white space before the cursor i = curwin->w_cursor.col; @@ -2089,13 +2101,13 @@ void insertchar(int c, int flags, int second_indent) i -= middle_len; // Check some expected things before we go on - if (i >= 0 && lead_end[end_len - 1] == end_comment_pending) { + if (i >= 0 && (uint8_t)lead_end[end_len - 1] == end_comment_pending) { // Backspace over all the stuff we want to replace backspace_until_column(i); // Insert the end-comment string, except for the last // character, which will get inserted as normal later. - ins_bytes_len((char *)lead_end, (size_t)(end_len - 1)); + ins_bytes_len(lead_end, (size_t)(end_len - 1)); } } } @@ -2146,9 +2158,6 @@ void insertchar(int c, int flags, int second_indent) || (virtcol += byte2cells((uint8_t)buf[i - 1])) < (colnr_T)textwidth) && !(!no_abbr && !vim_iswordc(c) && vim_iswordc((uint8_t)buf[i - 1]))) { c = vgetc(); - if (p_hkmap && KeyTyped) { - c = hkmap(c); // Hebrew mode mapping - } buf[i++] = (char)c; } @@ -2169,7 +2178,7 @@ void insertchar(int c, int flags, int second_indent) int cc; if ((cc = utf_char2len(c)) > 1) { - char buf[MB_MAXBYTES + 1]; + char buf[MB_MAXCHAR + 1]; utf_char2bytes(c, buf); buf[cc] = NUL; @@ -2260,7 +2269,7 @@ int stop_arrow(void) // right, except when nothing was inserted yet. update_Insstart_orig = false; } - Insstart_textlen = (colnr_T)linetabsize(get_cursor_line_ptr()); + Insstart_textlen = linetabsize_str(get_cursor_line_ptr()); if (u_save_cursor() == OK) { arrow_used = false; @@ -2294,26 +2303,24 @@ int stop_arrow(void) /// @param nomove <c-\><c-o>, don't move cursor static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) { - int cc; - char *ptr; - stop_redo_ins(); replace_flush(); // abandon replace stack // Save the inserted text for later redo with ^@ and CTRL-A. // Don't do it when "restart_edit" was set and nothing was inserted, // otherwise CTRL-O w and then <Left> will clear "last_insert". - ptr = get_inserted(); - if (did_restart_edit == 0 || (ptr != NULL - && (int)strlen(ptr) > new_insert_skip)) { + char *ptr = get_inserted(); + int added = ptr == NULL ? 0 : (int)strlen(ptr) - new_insert_skip; + if (did_restart_edit == 0 || added > 0) { xfree(last_insert); last_insert = ptr; - last_insert_skip = new_insert_skip; + last_insert_skip = added < 0 ? 0 : new_insert_skip; } else { xfree(ptr); } if (!arrow_used && end_insert_pos != NULL) { + int cc; // Auto-format now. It may seem strange to do this when stopping an // insertion (or moving the cursor), but it's required when appending // a line and having it end in a space. But only do it when something @@ -2365,7 +2372,7 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) curwin->w_cursor = *end_insert_pos; check_cursor_col(); // make sure it is not past the line - for (;;) { + while (true) { if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) { curwin->w_cursor.col--; } @@ -2413,16 +2420,14 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) // Used for the replace command. void set_last_insert(int c) { - char *s; - xfree(last_insert); last_insert = xmalloc(MB_MAXBYTES * 3 + 5); - s = last_insert; + char *s = last_insert; // Use the CTRL-V only when entering a special char if (c < ' ' || c == DEL) { *s++ = Ctrl_V; } - s = (char *)add_char2buf(c, (char_u *)s); + s = add_char2buf(c, s); *s++ = ESC; *s++ = NUL; last_insert_skip = 0; @@ -2449,15 +2454,16 @@ void beginline(int flags) curwin->w_cursor.coladd = 0; if (flags & (BL_WHITE | BL_SOL)) { - char_u *ptr; + char *ptr; - for (ptr = (char_u *)get_cursor_line_ptr(); ascii_iswhite(*ptr) + for (ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr) && !((flags & BL_FIX) && ptr[1] == NUL); ptr++) { curwin->w_cursor.col++; } } curwin->w_set_curswant = true; } + adjust_skipcol(); } // oneright oneleft cursor_down cursor_up @@ -2469,15 +2475,14 @@ void beginline(int flags) int oneright(void) { char *ptr; - int l; if (virtual_active()) { pos_T prevpos = curwin->w_cursor; // Adjust for multi-wide char (excluding TAB) ptr = get_cursor_pos_ptr(); - coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(utf_ptr2char(ptr))) ? - ptr2cells(ptr) : 1)); + coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(utf_ptr2char(ptr))) + ? ptr2cells(ptr) : 1)); curwin->w_set_curswant = true; // Return OK if the cursor moved, FAIL otherwise (at window edge). return (prevpos.col != curwin->w_cursor.col @@ -2489,7 +2494,7 @@ int oneright(void) return FAIL; // already at the very end } - l = utfc_ptr2len(ptr); + int l = utfc_ptr2len(ptr); // move "l" bytes right, but don't end up on the NUL, unless 'virtualedit' // contains "onemore". @@ -2499,13 +2504,13 @@ int oneright(void) curwin->w_cursor.col += l; curwin->w_set_curswant = true; + adjust_skipcol(); return OK; } int oneleft(void) { if (virtual_active()) { - int width; int v = getviscol(); if (v == 0) { @@ -2513,8 +2518,8 @@ int oneleft(void) } // We might get stuck on 'showbreak', skip over it. - width = 1; - for (;;) { + int width = 1; + while (true) { coladvance(v - width); // getviscol() is slow, skip it when 'showbreak' is empty, // 'breakindent' is not set and there are no multi-byte @@ -2534,6 +2539,7 @@ int oneleft(void) } curwin->w_set_curswant = true; + adjust_skipcol(); return OK; } @@ -2547,20 +2553,16 @@ int oneleft(void) // if the character on the left of the current cursor is a multi-byte // character, move to its first byte mb_adjust_cursor(); + adjust_skipcol(); return OK; } /// Move the cursor up "n" lines in window "wp". /// Takes care of closed folds. -/// Returns the new cursor line or zero for failure. -linenr_T cursor_up_inner(win_T *wp, long n) +void cursor_up_inner(win_T *wp, linenr_T n) { linenr_T lnum = wp->w_cursor.lnum; - // This fails if the cursor is already in the first line. - if (lnum <= 1) { - return 0; - } if (n >= lnum) { lnum = 1; } else if (hasAnyFolding(wp)) { @@ -2586,19 +2588,20 @@ linenr_T cursor_up_inner(win_T *wp, long n) lnum = 1; } } else { - lnum -= (linenr_T)n; + lnum -= n; } wp->w_cursor.lnum = lnum; - return lnum; } /// @param upd_topline When true: update topline -int cursor_up(long n, int upd_topline) +int cursor_up(linenr_T n, int upd_topline) { - if (n > 0 && cursor_up_inner(curwin, n) == 0) { + // This fails if the cursor is already in the first line. + if (n > 0 && curwin->w_cursor.lnum <= 1) { return FAIL; } + cursor_up_inner(curwin, n); // try to advance to the column we want to be at coladvance(curwin->w_curswant); @@ -2612,18 +2615,11 @@ int cursor_up(long n, int upd_topline) /// Move the cursor down "n" lines in window "wp". /// Takes care of closed folds. -/// Returns the new cursor line or zero for failure. -linenr_T cursor_down_inner(win_T *wp, long n) +void cursor_down_inner(win_T *wp, int n) { linenr_T lnum = wp->w_cursor.lnum; linenr_T line_count = wp->w_buffer->b_ml.ml_line_count; - // Move to last line of fold, will fail if it's the end-of-file. - (void)hasFoldingWin(wp, lnum, NULL, &lnum, true, NULL); - // This fails if the cursor is already in the last line. - if (lnum >= line_count) { - return FAIL; - } if (lnum + n >= line_count) { lnum = line_count; } else if (hasAnyFolding(wp)) { @@ -2631,6 +2627,7 @@ linenr_T cursor_down_inner(win_T *wp, long n) // count each sequence of folded lines as one logical line while (n--) { + // Move to last line of fold, will fail if it's the end-of-file. if (hasFoldingWin(wp, lnum, NULL, &last, true, NULL)) { lnum = last + 1; } else { @@ -2648,15 +2645,16 @@ linenr_T cursor_down_inner(win_T *wp, long n) } wp->w_cursor.lnum = lnum; - return lnum; } /// @param upd_topline When true: update topline -int cursor_down(long n, int upd_topline) +int cursor_down(int n, int upd_topline) { - if (n > 0 && cursor_down_inner(curwin, n) == 0) { + // This fails if the cursor is already in the last line. + if (n > 0 && curwin->w_cursor.lnum >= curwin->w_buffer->b_ml.ml_line_count) { return FAIL; } + cursor_down_inner(curwin, n); // try to advance to the column we want to be at coladvance(curwin->w_curswant); @@ -2675,14 +2673,12 @@ int cursor_down(long n, int upd_topline) /// @param c Command character to be inserted /// @param count Repeat this many times /// @param no_esc Don't add an ESC at the end -int stuff_inserted(int c, long count, int no_esc) +int stuff_inserted(int c, int count, int no_esc) { char *esc_ptr; - char *ptr; - char *last_ptr; char last = NUL; - ptr = (char *)get_last_insert(); + char *ptr = get_last_insert(); if (ptr == NULL) { emsg(_(e_noinstext)); return FAIL; @@ -2700,7 +2696,7 @@ int stuff_inserted(int c, long count, int no_esc) // when the last char is either "0" or "^" it will be quoted if no ESC // comes after it OR if it will inserted more than once and "ptr" // starts with ^D. -- Acevedo - last_ptr = (esc_ptr ? esc_ptr : ptr + strlen(ptr)) - 1; + char *last_ptr = (esc_ptr ? esc_ptr : ptr + strlen(ptr)) - 1; if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^') && (no_esc || (*ptr == Ctrl_D && count > 1))) { last = *last_ptr; @@ -2708,7 +2704,7 @@ int stuff_inserted(int c, long count, int no_esc) } do { - stuffReadbuff((const char *)ptr); + stuffReadbuff(ptr); // A trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^". if (last) { stuffReadbuff(last == '0' ? "\026\060\064\070" : "\026^"); @@ -2731,27 +2727,24 @@ int stuff_inserted(int c, long count, int no_esc) return OK; } -char_u *get_last_insert(void) +char *get_last_insert(void) FUNC_ATTR_PURE { if (last_insert == NULL) { return NULL; } - return (char_u *)last_insert + last_insert_skip; + return last_insert + last_insert_skip; } // Get last inserted string, and remove trailing <Esc>. // Returns pointer to allocated memory (must be freed) or NULL. char *get_last_insert_save(void) { - char *s; - int len; - if (last_insert == NULL) { return NULL; } - s = xstrdup(last_insert + last_insert_skip); - len = (int)strlen(s); + char *s = xstrdup(last_insert + last_insert_skip); + int len = (int)strlen(s); if (len > 0 && s[len - 1] == ESC) { // remove trailing ESC s[len - 1] = NUL; } @@ -2793,11 +2786,11 @@ static bool echeck_abbr(int c) // that the NL replaced. The extra one stores the characters after the cursor // that were deleted (always white space). -static char_u *replace_stack = NULL; +static uint8_t *replace_stack = NULL; static ssize_t replace_stack_nr = 0; // next entry in replace stack static ssize_t replace_stack_len = 0; // max. number of entries -/// Push character that is replaced onto the the replace stack. +/// Push character that is replaced onto the replace stack. /// /// replace_offset is normally 0, in which case replace_push will add a new /// character at the end of the stack. If replace_offset is not 0, that many @@ -2814,11 +2807,11 @@ void replace_push(int c) replace_stack_len += 50; replace_stack = xrealloc(replace_stack, (size_t)replace_stack_len); } - char_u *p = replace_stack + replace_stack_nr - replace_offset; + uint8_t *p = replace_stack + replace_stack_nr - replace_offset; if (replace_offset) { memmove(p + 1, p, (size_t)replace_offset); } - *p = (char_u)c; + *p = (uint8_t)c; replace_stack_nr++; } @@ -2829,9 +2822,8 @@ void replace_push(int c) int replace_push_mb(char *p) { int l = utfc_ptr2len(p); - int j; - for (j = l - 1; j >= 0; j--) { + for (int j = l - 1; j >= 0; j--) { replace_push(p[j]); } return l; @@ -2881,14 +2873,12 @@ static void replace_pop_ins(void) static void mb_replace_pop_ins(int cc) { int n; - char_u buf[MB_MAXBYTES + 1]; - int i; - int c; + uint8_t buf[MB_MAXBYTES + 1]; if ((n = MB_BYTE2LEN(cc)) > 1) { - buf[0] = (char_u)cc; - for (i = 1; i < n; i++) { - buf[i] = (char_u)replace_pop(); + buf[0] = (uint8_t)cc; + for (int i = 1; i < n; i++) { + buf[i] = (uint8_t)replace_pop(); } ins_bytes_len((char *)buf, (size_t)n); } else { @@ -2896,8 +2886,8 @@ static void mb_replace_pop_ins(int cc) } // Handle composing chars. - for (;;) { - c = replace_pop(); + while (true) { + int c = replace_pop(); if (c == -1) { // stack empty break; } @@ -2907,16 +2897,16 @@ static void mb_replace_pop_ins(int cc) break; } - buf[0] = (char_u)c; + buf[0] = (uint8_t)c; assert(n > 1); - for (i = 1; i < n; i++) { - buf[i] = (char_u)replace_pop(); + for (int i = 1; i < n; i++) { + buf[i] = (uint8_t)replace_pop(); } if (utf_iscomposing(utf_ptr2char((char *)buf))) { ins_bytes_len((char *)buf, (size_t)n); } else { // Not a composing char, put it back. - for (i = n - 1; i >= 0; i--) { + for (int i = n - 1; i >= 0; i--) { replace_push(buf[i]); } break; @@ -2942,18 +2932,13 @@ static void replace_flush(void) // using composing characters, use del_char_after_col() instead of del_char(). static void replace_do_bs(int limit_col) { - int cc; - int orig_len = 0; - int ins_len; - int orig_vcols = 0; colnr_T start_vcol; - char *p; - int i; - int vcol; const int l_State |