diff options
Diffstat (limited to 'src/nvim/edit.c')
-rw-r--r-- | src/nvim/edit.c | 510 |
1 files changed, 269 insertions, 241 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c index bf80f12bd0..d20660bfb9 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -227,7 +227,7 @@ static int last_insert_skip; /* nr of chars in front of previous insert */ static int new_insert_skip; /* nr of chars in front of current insert */ static int did_restart_edit; /* "restart_edit" when calling edit() */ -static int can_cindent; /* may do cindenting on this line */ +static bool can_cindent; // may do cindenting on this line static int old_indent = 0; /* for ^^D command in insert mode */ @@ -240,10 +240,10 @@ static int ins_need_undo; /* call u_save() before inserting a char. Set when edit() is called. after that arrow_used is used. */ -static int did_add_space = FALSE; /* auto_format() added an extra space - under the cursor */ -static int dont_sync_undo = false; // CTRL-G U prevents syncing undo - // for the next left/right cursor +static bool did_add_space = false; // auto_format() added an extra space + // under the cursor +static TriState dont_sync_undo = kFalse; // CTRL-G U prevents syncing undo + // for the next left/right cursor static linenr_T o_lnum = 0; @@ -276,7 +276,7 @@ static void insert_enter(InsertState *s) set_vim_var_string(VV_INSERTMODE, (char *) s->ptr, 1); set_vim_var_string(VV_CHAR, NULL, -1); - apply_autocmds(EVENT_INSERTENTER, NULL, NULL, false, curbuf); + ins_apply_autocmds(EVENT_INSERTENTER); // Make sure the cursor didn't move. Do call check_cursor_col() in // case the text was modified. Since Insert mode was not started yet @@ -298,7 +298,7 @@ static void insert_enter(InsertState *s) // Check if the cursor line needs redrawing before changing State. If // 'concealcursor' is "n" it needs to be redrawn without concealing. - conceal_check_cursur_line(); + conceal_check_cursor_line(); // When doing a paste with the middle mouse button, Insstart is set to // where the paste started. @@ -468,8 +468,11 @@ static void insert_enter(InsertState *s) } foldUpdateAfterInsert(); - if (s->cmdchar != 'r' && s->cmdchar != 'v') { - apply_autocmds(EVENT_INSERTLEAVE, NULL, NULL, false, curbuf); + // When CTRL-C was typed got_int will be set, with the result + // that the autocommands won't be executed. When mapped got_int + // is not set, but let's keep the behavior the same. + if (s->cmdchar != 'r' && s->cmdchar != 'v' && s->c != Ctrl_C) { + ins_apply_autocmds(EVENT_INSERTLEAVE); } did_cursorhold = false; } @@ -595,10 +598,10 @@ static int insert_check(VimState *state) s->lastc = s->c; // remember previous char for CTRL-D // After using CTRL-G U the next cursor key will not break undo. - if (dont_sync_undo == MAYBE) { - dont_sync_undo = true; + if (dont_sync_undo == kNone) { + dont_sync_undo = kTrue; } else { - dont_sync_undo = false; + dont_sync_undo = kFalse; } return 1; @@ -775,7 +778,7 @@ static int insert_handle_key(InsertState *s) if (echeck_abbr(ESC + ABBR_OFF)) { break; } - // FALLTHROUGH + FALLTHROUGH; case Ctrl_C: // End input mode if (s->c == Ctrl_C && cmdwin_type != 0) { @@ -851,7 +854,7 @@ static int insert_handle_key(InsertState *s) if (mod_mask != MOD_MASK_CTRL) { goto normalchar; } - // FALLTHROUGH + FALLTHROUGH; case K_ZERO: // Insert the previously inserted text. case NUL: case Ctrl_A: @@ -890,7 +893,7 @@ static int insert_handle_key(InsertState *s) insert_do_complete(s); break; } - // FALLTHROUGH + FALLTHROUGH; case Ctrl_T: // Make indent one shiftwidth greater. if (s->c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS) { @@ -997,7 +1000,7 @@ static int insert_handle_key(InsertState *s) if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) { ins_s_left(); } else { - ins_left(dont_sync_undo == false); + ins_left(dont_sync_undo == kFalse); } break; @@ -1010,7 +1013,7 @@ static int insert_handle_key(InsertState *s) if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) { ins_s_right(); } else { - ins_right(dont_sync_undo == false); + ins_right(dont_sync_undo == kFalse); } break; @@ -1062,7 +1065,7 @@ static int insert_handle_key(InsertState *s) case K_S_TAB: // When not mapped, use like a normal TAB s->c = TAB; - // FALLTHROUGH + FALLTHROUGH; case TAB: // TAB or Complete patterns along path if (ctrl_x_mode == CTRL_X_PATH_PATTERNS) { @@ -1078,7 +1081,7 @@ static int insert_handle_key(InsertState *s) case K_KENTER: // <Enter> s->c = CAR; - // FALLTHROUGH + FALLTHROUGH; case CAR: case NL: // In a quickfix window a <CR> jumps to the error under the @@ -1096,7 +1099,7 @@ static int insert_handle_key(InsertState *s) cmdwin_result = CAR; return 0; } - if (ins_eol(s->c) && !p_im) { + if (!ins_eol(s->c) && !p_im) { return 0; // out of memory } auto_format(false, false); @@ -1157,7 +1160,7 @@ static int insert_handle_key(InsertState *s) } goto normalchar; } - // FALLTHROUGH + FALLTHROUGH; case Ctrl_P: // Do previous/next pattern completion case Ctrl_N: @@ -1376,7 +1379,7 @@ ins_redraw ( // Make sure curswant is correct, an autocommand may call // getcurpos() update_curswant(); - apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, false, curbuf); + ins_apply_autocmds(EVENT_CURSORMOVEDI); } if (curwin->w_p_cole > 0) { conceal_old_cursor_line = last_cursormoved.lnum; @@ -1390,8 +1393,18 @@ ins_redraw ( if (ready && has_event(EVENT_TEXTCHANGEDI) && curbuf->b_last_changedtick != buf_get_changedtick(curbuf) && !pum_visible()) { + aco_save_T aco; + varnumber_T tick = buf_get_changedtick(curbuf); + + // save and restore curwin and curbuf, in case the autocmd changes them + aucmd_prepbuf(&aco, curbuf); apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, false, curbuf); + aucmd_restbuf(&aco); curbuf->b_last_changedtick = 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 @@ -1400,8 +1413,18 @@ ins_redraw ( if (ready && has_event(EVENT_TEXTCHANGEDP) && curbuf->b_last_changedtick_pum != buf_get_changedtick(curbuf) && pum_visible()) { - apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, false, curbuf); - curbuf->b_last_changedtick_pum = buf_get_changedtick(curbuf); + aco_save_T aco; + varnumber_T tick = buf_get_changedtick(curbuf); + + // save and restore curwin and curbuf, in case the autocmd changes them + aucmd_prepbuf(&aco, curbuf); + apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, false, curbuf); + aucmd_restbuf(&aco); + curbuf->b_last_changedtick_pum = 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)); + } } if (must_redraw) @@ -1514,12 +1537,14 @@ void edit_putchar(int c, int highlight) void edit_unputchar(void) { if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled) { - if (pc_status == PC_STATUS_RIGHT) - ++curwin->w_wcol; - if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) - redrawWinline(curwin->w_cursor.lnum, FALSE); - else + 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, false); + } else { screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr); + } } } @@ -1536,14 +1561,11 @@ void display_dollar(colnr_T col) save_col = curwin->w_cursor.col; curwin->w_cursor.col = col; - if (has_mbyte) { - char_u *p; - /* If on the last byte of a multi-byte move to the first byte. */ - p = get_cursor_line_ptr(); - curwin->w_cursor.col -= (*mb_head_off)(p, p + col); - } - curs_columns(FALSE); /* recompute w_wrow and w_wcol */ + // If on the last byte of a multi-byte move to the first byte. + char_u *p = get_cursor_line_ptr(); + curwin->w_cursor.col -= utf_head_off(p, p + col); + curs_columns(false); // Recompute w_wrow and w_wcol if (curwin->w_wcol < curwin->w_width) { edit_putchar('$', FALSE); dollar_vcol = curwin->w_virtcol; @@ -1559,7 +1581,7 @@ static void undisplay_dollar(void) { if (dollar_vcol >= 0) { dollar_vcol = -1; - redrawWinline(curwin->w_cursor.lnum, FALSE); + redrawWinline(curwin, curwin->w_cursor.lnum, false); } } @@ -1766,8 +1788,8 @@ change_indent ( /* We only put back the new line up to the cursor */ new_line[curwin->w_cursor.col] = NUL; - /* Put back original line */ - ml_replace(curwin->w_cursor.lnum, orig_line, FALSE); + // Put back original line + ml_replace(curwin->w_cursor.lnum, orig_line, false); curwin->w_cursor.col = orig_col; /* Backspace from cursor to start of line */ @@ -2114,11 +2136,7 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int char_u *p = IObuff; i = 0; while (i < actual_len && (p - IObuff + 6) < IOSIZE) { - if (has_mbyte) { - p += (*mb_char2bytes)(wca[i++], p); - } else { - *(p++) = wca[i++]; - } + p += utf_char2bytes(wca[i++], p); } *p = NUL; } @@ -2311,24 +2329,14 @@ static void ins_compl_longest_match(compl_T *match) p = compl_leader; s = match->cp_str; while (*p != NUL) { - if (has_mbyte) { - c1 = mb_ptr2char(p); - c2 = mb_ptr2char(s); - } else { - c1 = *p; - c2 = *s; - } - if (match->cp_icase ? (mb_tolower(c1) != mb_tolower(c2)) - : (c1 != c2)) { + c1 = utf_ptr2char(p); + c2 = utf_ptr2char(s); + + if (match->cp_icase ? (mb_tolower(c1) != mb_tolower(c2)) : (c1 != c2)) { break; } - if (has_mbyte) { - MB_PTR_ADV(p); - MB_PTR_ADV(s); - } else { - ++p; - ++s; - } + MB_PTR_ADV(p); + MB_PTR_ADV(s); } if (*p != NUL) { @@ -3077,10 +3085,10 @@ static void ins_compl_addleader(int c) if (stop_arrow() == FAIL) { return; } - if (has_mbyte && (cc = (*mb_char2len)(c)) > 1) { + if ((cc = utf_char2len(c)) > 1) { char_u buf[MB_MAXBYTES + 1]; - (*mb_char2bytes)(c, buf); + utf_char2bytes(c, buf); buf[cc] = NUL; ins_char_bytes(buf, cc); } else { @@ -3264,7 +3272,7 @@ static bool ins_compl_prep(int c) compl_cont_status |= CONT_LOCAL; else if (compl_cont_mode != 0) compl_cont_status &= ~CONT_LOCAL; - /* FALLTHROUGH */ + FALLTHROUGH; default: /* If we have typed at least 2 ^X's... for modes != 0, we set * compl_cont_status = 0 (eg, as if we had just started ^X @@ -3402,12 +3410,12 @@ static bool ins_compl_prep(int c) do_c_expr_indent(); /* Trigger the CompleteDone event to give scripts a chance to act * upon the completion. */ - apply_autocmds(EVENT_COMPLETEDONE, NULL, NULL, FALSE, curbuf); + ins_apply_autocmds(EVENT_COMPLETEDONE); } } else if (ctrl_x_mode == CTRL_X_LOCAL_MSG) /* Trigger the CompleteDone event to give scripts a chance to act * upon the (possibly failed) completion. */ - apply_autocmds(EVENT_COMPLETEDONE, NULL, NULL, FALSE, curbuf); + ins_apply_autocmds(EVENT_COMPLETEDONE); /* reset continue_* if we left expansion-mode, if we stay they'll be * (re)set properly in ins_complete() */ @@ -3438,10 +3446,10 @@ static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg) } if (compl_orig_text != NULL) { p = compl_orig_text; - for (len = 0; p[len] != NUL && p[len] == ptr[len]; ++len) - ; - if (len > 0) - len -= (*mb_head_off)(p, p + len); + for (len = 0; p[len] != NUL && p[len] == ptr[len]; len++) {} + if (len > 0) { + len -= utf_head_off(p, p + len); + } for (p += len; *p != NUL; MB_PTR_ADV(p)) { AppendCharToRedobuff(K_BS); } @@ -4456,7 +4464,7 @@ static int ins_complete(int c, bool enable_pum) int save_w_wrow; int save_w_leftcol; int insert_match; - int save_did_ai = did_ai; + const bool save_did_ai = did_ai; compl_direction = ins_compl_key2dir(c); insert_match = ins_compl_use_match(c); @@ -4464,12 +4472,13 @@ static int ins_complete(int c, bool enable_pum) if (!compl_started) { /* First time we hit ^N or ^P (in a row, I mean) */ - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; - if (stop_arrow() == FAIL) + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; + if (stop_arrow() == FAIL) { return FAIL; + } line = ml_get(curwin->w_cursor.lnum); curs_col = curwin->w_cursor.col; @@ -4495,7 +4504,7 @@ static int ins_complete(int c, bool enable_pum) * first non_blank in the line, if it is not a wordchar * include it to get a better pattern, but then we don't * want the "\\<" prefix, check it bellow */ - compl_col = (colnr_T)(skipwhite(line) - line); + compl_col = (colnr_T)getwhitecols(line); compl_startpos.col = compl_col; compl_startpos.lnum = curwin->w_cursor.lnum; compl_cont_status &= ~CONT_SOL; /* clear SOL if present */ @@ -4576,24 +4585,17 @@ static int ins_complete(int c, bool enable_pum) compl_col += curs_col; compl_length = 0; } else { - /* Search the point of change class of multibyte character - * or not a word single byte character backward. */ - if (has_mbyte) { - int base_class; - int head_off; - - startcol -= (*mb_head_off)(line, line + startcol); - base_class = mb_get_class(line + startcol); - while (--startcol >= 0) { - head_off = (*mb_head_off)(line, line + startcol); - if (base_class != mb_get_class(line + startcol - - head_off)) - break; - startcol -= head_off; + // Search the point of change class of multibyte character + // or not a word single byte character backward. + startcol -= utf_head_off(line, line + startcol); + int base_class = mb_get_class(line + startcol); + while (--startcol >= 0) { + int head_off = utf_head_off(line, line + startcol); + if (base_class != mb_get_class(line + startcol - head_off)) { + break; } - } else - while (--startcol >= 0 && vim_iswordc(line[startcol])) - ; + startcol -= head_off; + } compl_col += ++startcol; compl_length = (int)curs_col - startcol; if (compl_length == 1) { @@ -4614,7 +4616,7 @@ static int ins_complete(int c, bool enable_pum) } } } else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode)) { - compl_col = (colnr_T)(skipwhite(line) - line); + compl_col = (colnr_T)getwhitecols(line); compl_length = (int)curs_col - (int)compl_col; if (compl_length < 0) /* cursor in indent: empty pattern */ compl_length = 0; @@ -4968,16 +4970,16 @@ static unsigned quote_meta(char_u *dest, char_u *src, int len) if (ctrl_x_mode == CTRL_X_DICTIONARY || ctrl_x_mode == CTRL_X_THESAURUS) break; - // fallthrough + FALLTHROUGH; case '~': if (!p_magic) /* quote these only if magic is set */ break; - // fallthrough + FALLTHROUGH; case '\\': if (ctrl_x_mode == CTRL_X_DICTIONARY || ctrl_x_mode == CTRL_X_THESAURUS) break; - // fallthrough + FALLTHROUGH; case '^': // currently it's not needed. case '$': m++; @@ -5269,10 +5271,10 @@ insertchar ( } end_comment_pending = NUL; - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; // If there's any pending input, grab up to INPUT_BUFLEN at once. // This speeds up normal text input considerably. @@ -5333,10 +5335,10 @@ insertchar ( } else { int cc; - if (has_mbyte && (cc = (*mb_char2len)(c)) > 1) { + if ((cc = utf_char2len(c)) > 1) { char_u buf[MB_MAXBYTES + 1]; - (*mb_char2bytes)(c, buf); + utf_char2bytes(c, buf); buf[cc] = NUL; ins_char_bytes(buf, cc); AppendCharToRedobuff(c); @@ -5367,7 +5369,7 @@ internal_format ( { int cc; int save_char = NUL; - int haveto_redraw = FALSE; + bool haveto_redraw = false; int fo_ins_blank = has_format_option(FO_INS_BLANK); int fo_multibyte = has_format_option(FO_MBYTE_BREAK); int fo_white_par = has_format_option(FO_WHITE_PAR); @@ -5655,13 +5657,13 @@ internal_format ( curwin->w_cursor.col = len; } - haveto_redraw = TRUE; - can_cindent = TRUE; - /* moved the cursor, don't autoindent or cindent now */ - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; + haveto_redraw = true; + can_cindent = true; + // moved the cursor, don't autoindent or cindent now + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; line_breakcheck(); } @@ -5702,8 +5704,8 @@ auto_format ( pos = curwin->w_cursor; old = get_cursor_line_ptr(); - /* may remove added space */ - check_auto_format(FALSE); + // may remove added space + check_auto_format(false); /* Don't format in Insert mode when the cursor is on a trailing blank, the * user might insert normal text next. Also skip formatting when "1" is @@ -5769,12 +5771,13 @@ auto_format ( pnew = vim_strnsave(new, len + 2); pnew[len] = ' '; pnew[len + 1] = NUL; - ml_replace(curwin->w_cursor.lnum, pnew, FALSE); - /* remove the space later */ - did_add_space = TRUE; - } else - /* may remove added space */ - check_auto_format(FALSE); + ml_replace(curwin->w_cursor.lnum, pnew, false); + // remove the space later + did_add_space = true; + } else { + // may remove added space + check_auto_format(false); + } } check_cursor(); @@ -5785,9 +5788,8 @@ auto_format ( * delete it now. The space must be under the cursor, just after the insert * position. */ -static void -check_auto_format ( - int end_insert /* TRUE when ending Insert mode */ +static void check_auto_format( + bool end_insert // true when ending Insert mode ) { int c = ' '; @@ -5795,19 +5797,19 @@ check_auto_format ( if (did_add_space) { cc = gchar_cursor(); - if (!WHITECHAR(cc)) - /* Somehow the space was removed already. */ - did_add_space = FALSE; - else { + if (!WHITECHAR(cc)) { + // Somehow the space was removed already. + did_add_space = false; + } else { if (!end_insert) { inc_cursor(); c = gchar_cursor(); dec_cursor(); } if (c != NUL) { - /* The space is no longer at the end of the line, delete it. */ - del_char(FALSE); - did_add_space = FALSE; + // The space is no longer at the end of the line, delete it. + del_char(false); + did_add_space = false; } } } @@ -5912,7 +5914,7 @@ static void check_spell_redraw(void) linenr_T lnum = spell_redraw_lnum; spell_redraw_lnum = 0; - redrawWinline(lnum, FALSE); + redrawWinline(curwin, lnum, false); } } @@ -6032,8 +6034,8 @@ stop_insert ( } } - /* If a space was inserted for auto-formatting, remove it now. */ - check_auto_format(TRUE); + // If a space was inserted for auto-formatting, remove it now. + check_auto_format(true); /* If we just did an auto-indent, remove the white space from the end * of the line, and put the cursor back. @@ -6052,10 +6054,12 @@ stop_insert ( if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) --curwin->w_cursor.col; cc = gchar_cursor(); - if (!ascii_iswhite(cc)) + if (!ascii_iswhite(cc)) { break; - if (del_char(TRUE) == FAIL) - break; /* should not happen */ + } + if (del_char(true) == FAIL) { + break; // should not happen + } } if (curwin->w_cursor.lnum != tpos.lnum) curwin->w_cursor = tpos; @@ -6080,10 +6084,10 @@ stop_insert ( } } } - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; /* Set '[ and '] to the inserted text. When end_insert_pos is NULL we are * now in a different buffer. */ @@ -6197,12 +6201,10 @@ int oneright(void) /* Adjust for multi-wide char (excluding TAB) */ ptr = get_cursor_pos_ptr(); - coladvance(getviscol() + ((*ptr != TAB && vim_isprintc( - (*mb_ptr2char)(ptr) - )) - ? ptr2cells(ptr) : 1)); - curwin->w_set_curswant = TRUE; - /* Return OK if the cursor moved, FAIL otherwise (at window edge). */ + 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 || prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL; } @@ -6257,10 +6259,10 @@ int oneleft(void) /* Adjust for multi-wide char (not a TAB) */ ptr = get_cursor_pos_ptr(); - if (*ptr != TAB && vim_isprintc( - (*mb_ptr2char)(ptr) - ) && ptr2cells(ptr) > 1) + if (*ptr != TAB && vim_isprintc(utf_ptr2char(ptr)) + && ptr2cells(ptr) > 1) { curwin->w_cursor.coladd = 0; + } } curwin->w_set_curswant = TRUE; @@ -6407,8 +6409,10 @@ stuff_inserted ( /* may want to stuff the command character, to start Insert mode */ if (c != NUL) stuffcharReadbuff(c); - if ((esc_ptr = (char_u *)vim_strrchr(ptr, ESC)) != NULL) - *esc_ptr = NUL; /* remove the ESC */ + if ((esc_ptr = STRRCHR(ptr, ESC)) != NULL) { + // remove the ESC. + *esc_ptr = NUL; + } /* 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" @@ -6709,8 +6713,8 @@ static void replace_do_bs(int limit_col) * text aligned. */ curwin->w_cursor.col += ins_len; while (vcol > orig_vcols && gchar_cursor() == ' ') { - del_char(FALSE); - ++orig_vcols; + del_char(false); + orig_vcols++; } curwin->w_cursor.col -= ins_len; } @@ -6906,7 +6910,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) p = look + STRLEN(look); if ((try_match || try_match_word) && curwin->w_cursor.col >= (colnr_T)(p - look)) { - int match = FALSE; + bool match = false; if (keytyped == KEY_COMPLETE) { char_u *s; @@ -6931,29 +6935,30 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) && (icase ? mb_strnicmp(s, look, (size_t)(p - look)) : STRNCMP(s, look, p - look)) == 0) - match = TRUE; - } else - /* TODO: multi-byte */ - if (keytyped == (int)p[-1] || (icase && keytyped < 256 - && TOLOWER_LOC(keytyped) == - TOLOWER_LOC((int)p[-1]))) { - line = get_cursor_pos_ptr(); - assert(p >= look && (uintmax_t)(p - look) <= SIZE_MAX); - if ((curwin->w_cursor.col == (colnr_T)(p - look) - || !vim_iswordc(line[-(p - look) - 1])) - && (icase - ? mb_strnicmp(line - (p - look), look, (size_t)(p - look)) - : STRNCMP(line - (p - look), look, p - look)) - == 0) - match = TRUE; + match = true; + } else { + // TODO(@brammool): multi-byte + if (keytyped == (int)p[-1] + || (icase && keytyped < 256 + && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1]))) { + line = get_cursor_pos_ptr(); + assert(p >= look && (uintmax_t)(p - look) <= SIZE_MAX); + if ((curwin->w_cursor.col == (colnr_T)(p - look) + || !vim_iswordc(line[-(p - look) - 1])) + && (icase + ? mb_strnicmp(line - (p - look), look, (size_t)(p - look)) + : STRNCMP(line - (p - look), look, p - look)) == 0) { + match = true; + } + } } if (match && try_match_word && !try_match) { /* "0=word": Check if there are only blanks before the * word. */ - line = get_cursor_line_ptr(); - if ((int)(skipwhite(line) - line) != - (int)(curwin->w_cursor.col - (p - look))) - match = FALSE; + if (getwhitecols_curline() != + (int)(curwin->w_cursor.col - (p - look))) { + match = false; + } } if (match) { return true; @@ -7174,7 +7179,7 @@ static void ins_ctrl_g(void) case 'U': // Allow one left/right cursor movement with the next char, // without breaking undo. - dont_sync_undo = MAYBE; + dont_sync_undo = kNone; break; /* Unknown CTRL-G command, reserved for future expansion. */ @@ -7368,7 +7373,7 @@ static bool ins_start_select(int c) case K_KPAGEDOWN: if (!(mod_mask & MOD_MASK_SHIFT)) break; - // FALLTHROUGH + FALLTHROUGH; case K_S_LEFT: case K_S_RIGHT: case K_S_UP: @@ -7406,7 +7411,7 @@ static void ins_insert(int replaceState) set_vim_var_string(VV_INSERTMODE, ((State & REPLACE_FLAG) ? "i" : replaceState == VREPLACE ? "v" : "r"), 1); - apply_autocmds(EVENT_INSERTCHANGE, NULL, NULL, false, curbuf); + ins_apply_autocmds(EVENT_INSERTCHANGE); if (State & REPLACE_FLAG) { State = INSERT | (State & LANGMAP); } else { @@ -7452,46 +7457,55 @@ static void ins_shift(int c, int lastc) */ if (c == Ctrl_D && (lastc == '0' || lastc == '^') && curwin->w_cursor.col > 0) { - --curwin->w_cursor.col; - (void)del_char(FALSE); /* delete the '^' or '0' */ - /* In Replace mode, restore the characters that '^' or '0' replaced. */ - if (State & REPLACE_FLAG) + curwin->w_cursor.col--; + (void)del_char(false); // delete the '^' or '0' + // In Replace mode, restore the characters that '^' or '0' replaced. + if (State & REPLACE_FLAG) { replace_pop_ins(); - if (lastc == '^') - old_indent = get_indent(); /* remember curr. indent */ + } + if (lastc == '^') { + old_indent = get_indent(); // remember curr. indent + } change_indent(INDENT_SET, 0, TRUE, 0, TRUE); } else change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE); - if (did_ai && *skipwhite(get_cursor_line_ptr()) != NUL) - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; - can_cindent = FALSE; /* no cindenting after ^D or ^T */ + if (did_ai && *skipwhite(get_cursor_line_ptr()) != NUL) { + did_ai = false; + } + did_si = false; + can_si = false; + can_si_back = false; + can_cindent = false; // no cindenting after ^D or ^T } static void ins_del(void) { - int temp; - - if (stop_arrow() == FAIL) + if (stop_arrow() == FAIL) { return; - if (gchar_cursor() == NUL) { /* delete newline */ - temp = curwin->w_cursor.col; + } + if (gchar_cursor() == NUL) { // delete newline + const int temp = curwin->w_cursor.col; if (!can_bs(BS_EOL) // only if "eol" included || do_join(2, false, true, false, false) == FAIL) { vim_beep(BO_BS); } else { curwin->w_cursor.col = temp; + // Adjust orig_line_count in case more lines have been deleted than + // have been added. That makes sure, that open_line() later + // can access all buffer lines correctly + if (State & VREPLACE_FLAG + && orig_line_count > curbuf->b_ml.ml_line_count) { + orig_line_count = curbuf->b_ml.ml_line_count; + } } } else if (del_char(false) == FAIL) { // delete char under cursor vim_beep(BO_BS); } - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; AppendCharToRedobuff(K_DEL); } @@ -7509,8 +7523,9 @@ static void ins_bs_one(colnr_T *vcolp) if (curwin->w_cursor.lnum != Insstart.lnum || curwin->w_cursor.col >= Insstart.col) replace_do_bs(-1); - } else - (void)del_char(FALSE); + } else { + (void)del_char(false); + } } /// Handle Backspace, delete-word and delete-line in Insert mode. @@ -7658,7 +7673,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) State = oldState; } } - did_ai = FALSE; + did_ai = false; } else { /* * Delete character(s) before the cursor. @@ -7774,16 +7789,16 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) else { const bool l_enc_utf8 = enc_utf8; const int l_p_deco = p_deco; - if (l_enc_utf8 && l_p_deco) + if (l_enc_utf8 && l_p_deco) { (void)utfc_ptr2char(get_cursor_pos_ptr(), cpc); - (void)del_char(FALSE); - /* - * If there are combining characters and 'delcombine' is set - * move the cursor back. Don't back up before the base - * character. - */ - if (l_enc_utf8 && l_p_deco && cpc[0] != NUL) + } + (void)del_char(false); + // If there are combining characters and 'delcombine' is set + // move the cursor back. Don't back up before the base + // character. + if (l_enc_utf8 && l_p_deco && cpc[0] != NUL) { inc_cursor(); + } if (revins_chars) { revins_chars--; revins_legal++; @@ -7862,7 +7877,7 @@ static void ins_mouse(int c) curwin = new_curwin; curbuf = curwin->w_buffer; } - can_cindent = TRUE; + can_cindent = true; } /* redraw status lines (in case another window became active) */ @@ -7871,20 +7886,20 @@ static void ins_mouse(int c) static void ins_mousescroll(int dir) { - pos_T tpos; - win_T *old_curwin = curwin; - int did_scroll = FALSE; - - tpos = curwin->w_cursor; + win_T *const old_curwin = curwin; + bool did_scroll = false; + pos_T tpos = curwin->w_cursor; if (mouse_row >= 0 && mouse_col >= 0) { - int row, col; + int row = mouse_row; + int col = mouse_col; - row = mouse_row; - col = mouse_col; - - /* find the window at the pointer coordinates */ - curwin = mouse_find_win(&row, &col); + // find the window at the pointer coordinates + win_T *const wp = mouse_find_win(&row, &col); + if (wp == NULL) { + return; + } + curwin = wp; curbuf = curwin->w_buffer; } if (curwin == old_curwin) @@ -7903,7 +7918,7 @@ static void ins_mousescroll(int dir) } else { mouse_scroll_horiz(dir); } - did_scroll = TRUE; + did_scroll = true; } curwin->w_redr_status = TRUE; @@ -7921,7 +7936,7 @@ static void ins_mousescroll(int dir) if (!equalpos(curwin->w_cursor, tpos)) { start_arrow(&tpos); - can_cindent = TRUE; + can_cindent = true; } } @@ -7954,7 +7969,7 @@ static void ins_left(bool end_change) } else { vim_beep(BO_CRSR); } - dont_sync_undo = false; + dont_sync_undo = kFalse; } static void ins_home(int c) @@ -8039,7 +8054,7 @@ static void ins_right(bool end_change) } else { vim_beep(BO_CRSR); } - dont_sync_undo = false; + dont_sync_undo = kFalse; } static void ins_s_right(void) @@ -8344,14 +8359,14 @@ static bool ins_tab(void) /// Handle CR or NL in insert mode. /// -/// @return true when it can't undo. +/// @return false when it can't undo. static bool ins_eol(int c) { if (echeck_abbr(c + ABBR_OFF)) { - return false; + return true; } if (stop_arrow() == FAIL) { - return true; + return false; } undisplay_dollar(); @@ -8389,11 +8404,11 @@ static bool ins_eol(int c) has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM : 0, old_indent); old_indent = 0; - can_cindent = TRUE; - /* When inserting a line the cursor line must never be in a closed fold. */ + can_cindent = true; + // When inserting a line the cursor line must never be in a closed fold. foldOpenCursor(); - return !i; + return i; } /* @@ -8494,7 +8509,7 @@ int ins_copychar(linenr_T lnum) if ((colnr_T)temp > curwin->w_virtcol) ptr = prev_ptr; - c = (*mb_ptr2char)(ptr); + c = utf_ptr2char(ptr); if (c == NUL) { vim_beep(BO_COPY); } @@ -8646,24 +8661,20 @@ static char_u *do_insert_char_pre(int c) if (!has_event(EVENT_INSERTCHARPRE)) { return NULL; } - if (has_mbyte) { - buf[(*mb_char2bytes)(c, (char_u *) buf)] = NUL; - } else { - buf[0] = c; - buf[1] = NUL; - } + buf[utf_char2bytes(c, (char_u *)buf)] = NUL; // Lock the text to avoid weird things from happening. textlock++; set_vim_var_string(VV_CHAR, buf, -1); char_u *res = NULL; - if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf)) { - /* Get the value of v:char. It may be empty or more than one - * character. Only use it when changed, otherwise continue with the - * original character to avoid breaking autoindent. */ - if (STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0) + if (ins_apply_autocmds(EVENT_INSERTCHARPRE)) { + // Get the value of v:char. It may be empty or more than one + // character. Only use it when changed, otherwise continue with the + // original character to avoid breaking autoindent. + if (STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0) { res = vim_strsave(get_vim_var_str(VV_CHAR)); + } } set_vim_var_string(VV_CHAR, NULL, -1); @@ -8672,6 +8683,23 @@ static char_u *do_insert_char_pre(int c) return res; } +/// Trigger "event" and take care of fixing undo. +static int ins_apply_autocmds(event_T event) +{ + varnumber_T tick = buf_get_changedtick(curbuf); + int r; + + r = apply_autocmds(event, NULL, NULL, false, curbuf); + + // If u_savesub() was called then we are not prepared to start + // a new line. Call u_save() with no contents to fix that. + if (tick != buf_get_changedtick(curbuf)) { + u_save(curwin->w_cursor.lnum, (linenr_T)(curwin->w_cursor.lnum + 1)); + } + + return r; +} + static void show_pum(int prev_w_wrow, int prev_w_leftcol) { // RedrawingDisabled may be set when invoked through complete(). |