diff options
Diffstat (limited to 'src/nvim/edit.c')
| -rw-r--r-- | src/nvim/edit.c | 1664 |
1 files changed, 488 insertions, 1176 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 6583ac8584..095d73f53f 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1,16 +1,17 @@ // 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 - */ +// edit.c: functions for Insert mode #include <assert.h> +#include <ctype.h> #include <inttypes.h> #include <stdbool.h> #include <string.h> +#include <sys/types.h> #include "nvim/ascii.h" +#include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/change.h" #include "nvim/charset.h" @@ -19,20 +20,23 @@ #include "nvim/drawscreen.h" #include "nvim/edit.h" #include "nvim/eval.h" -#include "nvim/event/loop.h" +#include "nvim/eval/typval_defs.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" -#include "nvim/ex_getln.h" #include "nvim/extmark.h" #include "nvim/fileio.h" #include "nvim/fold.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_group.h" #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/insexpand.h" #include "nvim/keycodes.h" -#include "nvim/main.h" +#include "nvim/macros.h" #include "nvim/mapping.h" #include "nvim/mark.h" #include "nvim/mbyte.h" @@ -45,17 +49,18 @@ #include "nvim/ops.h" #include "nvim/option.h" #include "nvim/os/input.h" -#include "nvim/os/time.h" -#include "nvim/path.h" #include "nvim/plines.h" #include "nvim/popupmenu.h" -#include "nvim/quickfix.h" +#include "nvim/pos.h" +#include "nvim/screen.h" #include "nvim/search.h" -#include "nvim/spell.h" #include "nvim/state.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/terminal.h" +#include "nvim/textformat.h" +#include "nvim/textobject.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/vim.h" @@ -81,31 +86,34 @@ typedef struct insert_state { int did_restart_edit; // remember if insert mode was restarted // after a ctrl+o bool nomove; - char_u *ptr; + char *ptr; } InsertState; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "edit.c.generated.h" #endif -#define BACKSPACE_CHAR 1 -#define BACKSPACE_WORD 2 -#define BACKSPACE_WORD_NOT_SPACE 3 -#define BACKSPACE_LINE 4 +enum { + BACKSPACE_CHAR = 1, + BACKSPACE_WORD = 2, + BACKSPACE_WORD_NOT_SPACE = 3, + BACKSPACE_LINE = 4, +}; + +/// Set when doing something for completion that may call edit() recursively, +/// which is not allowed. +static bool compl_busy = false; static colnr_T Insstart_textlen; // length of line when insert started static colnr_T Insstart_blank_vcol; // vcol for first inserted blank static bool update_Insstart_orig = true; // set Insstart_orig to Insstart -static char_u *last_insert = NULL; // the text of the previous insert, - // K_SPECIAL is escaped -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 char *last_insert = NULL; // the text of the previous insert, K_SPECIAL is escaped +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 bool can_cindent; // may do cindenting on this line -static int old_indent = 0; // for ^^D command in insert mode - static int revins_on; // reverse insert mode on static int revins_chars; // how much to skip after edit static int revins_legal; // was the last char 'legal'? @@ -115,8 +123,6 @@ static bool ins_need_undo; // call u_save() before inserting a // char. Set when edit() is called. // after that arrow_used is used. -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 key @@ -143,14 +149,14 @@ static void insert_enter(InsertState *s) pos_T save_cursor = curwin->w_cursor; if (s->cmdchar == 'R') { - s->ptr = (char_u *)"r"; + s->ptr = "r"; } else if (s->cmdchar == 'V') { - s->ptr = (char_u *)"v"; + s->ptr = "v"; } else { - s->ptr = (char_u *)"i"; + s->ptr = "i"; } - set_vim_var_string(VV_INSERTMODE, (char *)s->ptr, 1); + set_vim_var_string(VV_INSERTMODE, s->ptr, 1); set_vim_var_string(VV_CHAR, NULL, -1); ins_apply_autocmds(EVENT_INSERTENTER); @@ -276,7 +282,7 @@ static void insert_enter(InsertState *s) if (s->ptr[1] == NUL) { curwin->w_cursor.col++; } else { - s->i = utfc_ptr2len((char *)s->ptr); + s->i = utfc_ptr2len(s->ptr); if (s->ptr[s->i] == NUL) { curwin->w_cursor.col += s->i; } @@ -321,7 +327,7 @@ static void insert_enter(InsertState *s) if (s->ptr == NULL) { new_insert_skip = 0; } else { - new_insert_skip = (int)STRLEN(s->ptr); + new_insert_skip = (int)strlen(s->ptr); xfree(s->ptr); } @@ -439,8 +445,7 @@ static int insert_check(VimState *state) s->mincol = curwin->w_wcol; validate_cursor_col(); - if ( - curwin->w_wcol < s->mincol - tabstop_at(get_nolist_virtcol(), + if (curwin->w_wcol < s->mincol - tabstop_at(get_nolist_virtcol(), curbuf->b_p_ts, curbuf->b_p_vts_array) && curwin->w_wrow == curwin->w_winrow @@ -448,7 +453,7 @@ static int insert_check(VimState *state) && (curwin->w_cursor.lnum != curwin->w_topline || curwin->w_topfill > 0)) { if (curwin->w_topfill > 0) { - --curwin->w_topfill; + curwin->w_topfill--; } else if (hasFolding(curwin->w_topline, NULL, &s->old_topline)) { set_topline(curwin, s->old_topline + 1); } else { @@ -552,12 +557,12 @@ static int insert_execute(VimState *state, int key) // completion: Add to "compl_leader". if (ins_compl_accept_char(s->c)) { // Trigger InsertCharPre. - char_u *str = do_insert_char_pre(s->c); - char_u *p; + char *str = do_insert_char_pre(s->c); + char *p; if (str != NULL) { for (p = str; *p != NUL; MB_PTR_ADV(p)) { - ins_compl_addleader(utf_ptr2char((char *)p)); + ins_compl_addleader(utf_ptr2char(p)); } xfree(str); } else { @@ -624,16 +629,17 @@ static int insert_execute(VimState *state, int key) } if (cindent_on() && ctrl_x_mode_none()) { + s->line_is_white = inindent(0); // A key name preceded by a bang means this key is not to be // inserted. Skip ahead to the re-indenting below. - // A key name preceded by a star means that indenting has to be - // done before inserting the key. - s->line_is_white = inindent(0); - if (in_cinkeys(s->c, '!', s->line_is_white)) { - insert_do_cindent(s); + if (in_cinkeys(s->c, '!', s->line_is_white) + && stop_arrow() == OK) { + do_c_expr_indent(); return 1; // continue } + // A key name preceded by a star means that indenting has to be + // done before inserting the key. if (can_cindent && in_cinkeys(s->c, '*', s->line_is_white) && stop_arrow() == OK) { do_c_expr_indent(); @@ -901,6 +907,12 @@ check_pum: } pum_want.active = false; } + + if (curbuf->b_u_synced) { + // The K_EVENT, K_COMMAND, or K_LUA caused undo to be synced. + // Need to save the line for undo before inserting the next char. + ins_need_undo = true; + } break; case K_HOME: // <Home> @@ -1090,7 +1102,7 @@ check_pum: // but it is under other ^X modes if (*curbuf->b_p_cpt == NUL && (ctrl_x_mode_normal() || ctrl_x_mode_whole_line()) - && !(compl_cont_status & CONT_LOCAL)) { + && !compl_status_local()) { goto normalchar; } @@ -1109,7 +1121,7 @@ normalchar: if (!p_paste) { // Trigger InsertCharPre. - char *str = (char *)do_insert_char_pre(s->c); + char *str = do_insert_char_pre(s->c); char *p; if (str != NULL) { @@ -1176,9 +1188,11 @@ normalchar: static void insert_do_complete(InsertState *s) { compl_busy = true; + disable_fold_update++; // don't redraw folds here if (ins_complete(s->c, true) == FAIL) { - compl_cont_status = 0; + compl_status_clear(); } + disable_fold_update--; compl_busy = false; can_si = may_do_si(); // allow smartindenting } @@ -1225,9 +1239,8 @@ bool edit(int cmdchar, bool startln, long count) restart_edit = 'i'; force_restart_edit = true; return false; - } else { - return terminal_enter(); } + return terminal_enter(); } // Don't allow inserting in the sandbox. @@ -1283,7 +1296,7 @@ void ins_redraw(bool ready) // a "(". The autocommand may also require a redraw, so it's done // again below, unfortunately. if (syntax_present(curwin) && must_redraw) { - update_screen(0); + update_screen(); } // Make sure curswant is correct, an autocommand may call // getcurpos() @@ -1331,8 +1344,7 @@ void ins_redraw(bool ready) } if (ready) { - // Trigger Scroll if viewport changed. - may_trigger_winscrolled(); + may_trigger_win_scrolled_resized(); } // Trigger BufModified if b_changed_invalid is set. @@ -1345,7 +1357,7 @@ void ins_redraw(bool ready) pum_check_clear(); if (must_redraw) { - update_screen(0); + update_screen(); } else if (clear_cmdline || redraw_cmdline) { showmode(); // clear cmdline and show mode } @@ -1354,9 +1366,7 @@ void ins_redraw(bool ready) emsg_on_display = false; // may remove error message now } -/* - * Handle a CTRL-V or CTRL-Q typed in Insert mode. - */ +// Handle a CTRL-V or CTRL-Q typed in Insert mode. static void ins_ctrl_v(void) { int c; @@ -1386,10 +1396,8 @@ static void ins_ctrl_v(void) revins_legal++; } -/* - * 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. - */ +// 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 @@ -1433,25 +1441,25 @@ void edit_putchar(int c, bool highlight) // 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, pc_bytes, &pc_attr); + grid_getbytes(&curwin->w_grid, pc_row, pc_col, (char *)pc_bytes, &pc_attr); pc_status = PC_STATUS_SET; } grid_putchar(&curwin->w_grid, c, pc_row, pc_col, attr); } } -/// Return the effective prompt for the specified buffer. -char_u *buf_prompt_text(const buf_T *const buf) +/// @return the effective prompt for the specified buffer. +char *buf_prompt_text(const buf_T *const buf) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { if (buf->b_prompt_text == NULL) { - return (char_u *)"% "; + return "% "; } - return (char_u *)buf->b_prompt_text; + return buf->b_prompt_text; } -// Return the effective prompt for the current buffer. -char_u *prompt_text(void) +/// @return the effective prompt for the current buffer. +char *prompt_text(void) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { return buf_prompt_text(curbuf); @@ -1461,17 +1469,17 @@ char_u *prompt_text(void) // Move the cursor to this line. static void init_prompt(int cmdchar_todo) { - char_u *prompt = prompt_text(); - char_u *text; + char *prompt = prompt_text(); + char *text; curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; text = get_cursor_line_ptr(); - if (STRNCMP(text, prompt, STRLEN(prompt)) != 0) { + if (strncmp(text, prompt, strlen(prompt)) != 0) { // prompt is missing, insert it or append a line with it if (*text == NUL) { - ml_replace(curbuf->b_ml.ml_line_count, (char *)prompt, true); + ml_replace(curbuf->b_ml.ml_line_count, prompt, true); } else { - ml_append(curbuf->b_ml.ml_line_count, (char *)prompt, 0, false); + ml_append(curbuf->b_ml.ml_line_count, prompt, 0, false); } curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; coladvance(MAXCOL); @@ -1479,9 +1487,9 @@ static void init_prompt(int cmdchar_todo) } // Insert always starts after the prompt, allow editing text after it. - if (Insstart_orig.lnum != curwin->w_cursor.lnum || Insstart_orig.col != (colnr_T)STRLEN(prompt)) { + if (Insstart_orig.lnum != curwin->w_cursor.lnum || Insstart_orig.col != (colnr_T)strlen(prompt)) { Insstart.lnum = curwin->w_cursor.lnum; - Insstart.col = (colnr_T)STRLEN(prompt); + Insstart.col = (colnr_T)strlen(prompt); Insstart_orig = Insstart; Insstart_textlen = Insstart.col; Insstart_blank_vcol = MAXCOL; @@ -1491,8 +1499,8 @@ static void init_prompt(int cmdchar_todo) if (cmdchar_todo == 'A') { coladvance(MAXCOL); } - if (curwin->w_cursor.col < (colnr_T)STRLEN(prompt)) { - curwin->w_cursor.col = (colnr_T)STRLEN(prompt); + if (curwin->w_cursor.col < (colnr_T)strlen(prompt)) { + curwin->w_cursor.col = (colnr_T)strlen(prompt); } // Make sure the cursor is in a valid position. check_cursor(); @@ -1503,12 +1511,10 @@ bool prompt_curpos_editable(void) FUNC_ATTR_PURE { return curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count - && curwin->w_cursor.col >= (int)STRLEN(prompt_text()); + && curwin->w_cursor.col >= (int)strlen(prompt_text()); } -/* - * Undo the previous edit_putchar(). - */ +// Undo the previous edit_putchar(). void edit_unputchar(void) { if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled) { @@ -1518,16 +1524,13 @@ void edit_unputchar(void) if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) { redrawWinline(curwin, curwin->w_cursor.lnum); } else { - grid_puts(&curwin->w_grid, pc_bytes, pc_row - msg_scrolled, pc_col, - pc_attr); + grid_puts(&curwin->w_grid, (char *)pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr); } } } -/* - * 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. - */ +// 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) { colnr_T save_col; @@ -1540,7 +1543,7 @@ void display_dollar(colnr_T col) curwin->w_cursor.col = col; // If on the last byte of a multi-byte move to the first byte. - char_u *p = get_cursor_line_ptr(); + char *p = get_cursor_line_ptr(); curwin->w_cursor.col -= utf_head_off(p, p + col); curs_columns(curwin, false); // Recompute w_wrow and w_wcol if (curwin->w_wcol < curwin->w_grid.cols) { @@ -1550,11 +1553,9 @@ void display_dollar(colnr_T col) curwin->w_cursor.col = save_col; } -/* - * Call this function before moving the cursor from the normal insert position - * in insert mode. - */ -static void undisplay_dollar(void) +// Call this function before moving the cursor from the normal insert position +// in insert mode. +void undisplay_dollar(void) { if (dollar_vcol >= 0) { dollar_vcol = -1; @@ -1568,7 +1569,7 @@ static void undisplay_dollar(void) /// type == INDENT_DEC decrease indent (for CTRL-D) /// type == INDENT_SET set indent to "amount" /// -/// @param round if TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec). +/// @param round if true, round the indent to 'shiftwidth' (only with _INC and _Dec). /// @param replaced replaced character, put on replace stack /// @param call_changed_bytes call changed_bytes() void change_indent(int type, int amount, int round, int replaced, int call_changed_bytes) @@ -1577,30 +1578,28 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang int last_vcol; int insstart_less; // reduction for Insstart.col int new_cursor_col; - char_u *ptr; + char *ptr; int save_p_list; int start_col; colnr_T vc; colnr_T orig_col = 0; // init for GCC - char_u *new_line, *orig_line = NULL; // init for GCC + char *new_line, *orig_line = NULL; // init for GCC // MODE_VREPLACE state needs to know what the line was like before changing if (State & VREPLACE_FLAG) { - orig_line = vim_strsave(get_cursor_line_ptr()); // Deal with NULL below + orig_line = xstrdup(get_cursor_line_ptr()); // Deal with NULL below orig_col = curwin->w_cursor.col; } // for the following tricks we don't want list mode save_p_list = curwin->w_p_list; - curwin->w_p_list = FALSE; + curwin->w_p_list = false; vc = getvcol_nolist(&curwin->w_cursor); 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. - */ + // 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; // determine offset from first non-blank @@ -1610,10 +1609,8 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang insstart_less = curwin->w_cursor.col; - /* - * If the cursor is in the indent, compute how many screen columns the - * cursor is to the left of the first non-blank. - */ + // If the cursor is in the indent, compute how many screen columns the + // cursor is to the left of the first non-blank. if (new_cursor_col < 0) { vcol = get_indent() - vcol; } @@ -1622,9 +1619,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang start_col = -1; } - /* - * Set the new indent. The cursor will be put on the first non-blank. - */ + // Set the new indent. The cursor will be put on the first non-blank. if (type == INDENT_SET) { (void)set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0); } else { @@ -1639,20 +1634,16 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang } insstart_less -= curwin->w_cursor.col; - /* - * Try to put cursor on same character. - * If the cursor is at or after the first non-blank in the line, - * compute the cursor column relative to the column of the first - * non-blank character. - * If we are not in insert mode, leave the cursor on the first non-blank. - * If the cursor is before the first non-blank, position it relative - * to the first non-blank, counted in screen columns. - */ + // Try to put cursor on same character. + // If the cursor is at or after the first non-blank in the line, + // compute the cursor column relative to the column of the first + // non-blank character. + // If we are not in insert mode, leave the cursor on the first non-blank. + // If the cursor is before the first non-blank, position it relative + // to the first non-blank, counted in screen columns. if (new_cursor_col >= 0) { - /* - * When changing the indent while the cursor is touching it, reset - * Insstart_col to 0. - */ + // When changing the indent while the cursor is touching it, reset + // Insstart_col to 0. if (new_cursor_col == 0) { insstart_less = MAXCOL; } @@ -1660,33 +1651,31 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang } else if (!(State & MODE_INSERT)) { new_cursor_col = curwin->w_cursor.col; } else { - /* - * Compute the screen column where the cursor should be. - */ + // Compute the screen column where the cursor should be. vcol = get_indent() - vcol; curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol); - /* - * Advance the cursor until we reach the right screen column. - */ - vcol = last_vcol = 0; - new_cursor_col = -1; + // Advance the cursor until we reach the right screen column. + last_vcol = 0; ptr = get_cursor_line_ptr(); - while (vcol <= (int)curwin->w_virtcol) { - last_vcol = vcol; - if (new_cursor_col >= 0) { - new_cursor_col += utfc_ptr2len((char *)ptr + new_cursor_col); - } else { - new_cursor_col++; + chartabsize_T cts; + init_chartabsize_arg(&cts, curwin, 0, 0, ptr, ptr); + while (cts.cts_vcol <= (int)curwin->w_virtcol) { + last_vcol = cts.cts_vcol; + if (cts.cts_vcol > 0) { + MB_PTR_ADV(cts.cts_ptr); + } + if (*cts.cts_ptr == NUL) { + break; } - vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol); + cts.cts_vcol += lbr_chartabsize(&cts); } vcol = last_vcol; + new_cursor_col = (int)(cts.cts_ptr - cts.cts_line); + clear_chartabsize_arg(&cts); - /* - * May need to insert spaces to be able to position the cursor on - * the right screen column. - */ + // May need to insert spaces to be able to position the cursor on + // the right screen column. if (vcol != (int)curwin->w_virtcol) { curwin->w_cursor.col = (colnr_T)new_cursor_col; size_t i = (size_t)(curwin->w_virtcol - vcol); @@ -1697,10 +1686,8 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang xfree(ptr); } - /* - * When changing the indent while the cursor is in it, reset - * Insstart_col to 0. - */ + // When changing the indent while the cursor is in it, reset + // Insstart_col to 0. insstart_less = MAXCOL; } @@ -1711,12 +1698,10 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang } else { curwin->w_cursor.col = (colnr_T)new_cursor_col; } - curwin->w_set_curswant = TRUE; + curwin->w_set_curswant = true; changed_cline_bef_curs(); - /* - * May have to adjust the start of the insert. - */ + // May have to adjust the start of the insert. if (State & MODE_INSERT) { if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0) { if ((int)Insstart.col <= insstart_less) { @@ -1757,14 +1742,14 @@ 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 = vim_strsave(get_cursor_line_ptr()); + 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; int new_col = curwin->w_cursor.col; // Put back original line - ml_replace(curwin->w_cursor.lnum, (char *)orig_line, false); + ml_replace(curwin->w_cursor.lnum, orig_line, false); curwin->w_cursor.col = orig_col; curbuf_splice_pending++; @@ -1792,12 +1777,12 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang /// Truncate the space at the end of a line. This is to be used only in an /// insert mode. It handles fixing the replace stack for MODE_REPLACE and /// MODE_VREPLACE modes. -void truncate_spaces(char_u *line) +void truncate_spaces(char *line) { int i; // find start of trailing white space - for (i = (int)STRLEN(line) - 1; i >= 0 && ascii_iswhite(line[i]); i--) { + for (i = (int)strlen(line) - 1; i >= 0 && ascii_iswhite(line[i]); i--) { if (State & REPLACE_FLAG) { replace_join(0); // remove a NUL from the replace stack } @@ -1837,7 +1822,7 @@ static bool del_char_after_col(int limit_col) // composing character. mb_adjust_cursor(); while (curwin->w_cursor.col < (colnr_T)limit_col) { - int l = utf_ptr2len((char *)get_cursor_pos_ptr()); + int l = utf_ptr2len(get_cursor_pos_ptr()); if (l == 0) { // end of line break; @@ -1964,28 +1949,28 @@ 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_u *p; + 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. // Only use mod_mask for special keys, to avoid things like <S-Space>, - // unless 'allow_modmask' is TRUE. + // unless 'allow_modmask' is true. if (mod_mask & MOD_MASK_CMD) { // Command-key never produces a normal key. allow_modmask = true; } if (IS_SPECIAL(c) || (mod_mask && allow_modmask)) { - p = get_special_key_name(c, mod_mask); - len = (int)STRLEN(p); - c = p[len - 1]; + p = (char *)get_special_key_name(c, mod_mask); + len = (int)strlen(p); + c = (uint8_t)p[len - 1]; if (len > 2) { if (stop_arrow() == FAIL) { return; } p[len - 1] = NUL; ins_str(p); - AppendToRedobuffLit((char *)p, -1); + AppendToRedobuffLit(p, -1); ctrlv = false; } } @@ -1994,20 +1979,15 @@ static void insert_special(int c, int allow_modmask, int ctrlv) } } -/* - * Special characters in this context are those that need processing other - * than the simple insertion that can be performed here. This includes ESC - * which terminates the insert, and CR/NL which need special processing to - * open up a new line. This routine tries to optimize insertions performed by - * the "redo", "undo" or "put" commands, so it needs to know when it should - * stop and defer processing to the "normal" mechanism. - * '0' and '^' are special, because they can be followed by CTRL-D. - */ +// Special characters in this context are those that need processing other +// than the simple insertion that can be performed here. This includes ESC +// which terminates the insert, and CR/NL which need special processing to +// open up a new line. This routine tries to optimize insertions performed by +// the "redo", "undo" or "put" commands, so it needs to know when it should +// stop and defer processing to the "normal" mechanism. +// '0' and '^' are special, because they can be followed by CTRL-D. #define ISSPECIAL(c) ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^') -#define WHITECHAR(cc) (ascii_iswhite(cc) \ - && !utf_iscomposing(utf_ptr2char((char *)get_cursor_pos_ptr() + 1))) - /// /// "flags": INSCHAR_FORMAT - force formatting /// INSCHAR_CTRLV - char typed just after CTRL-V @@ -2081,8 +2061,8 @@ void insertchar(int c, int flags, int second_indent) // Need to remove existing (middle) comment leader and insert end // comment leader. First, check what comment leader we can find. - char_u *line = get_cursor_line_ptr(); - int i = get_leader_len((char *)line, &p, false, true); + char *line = get_cursor_line_ptr(); + int i = get_leader_len(line, &p, false, true); if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL) { // Just checking // Skip middle-comment string while (*p && p[-1] != ':') { // find end of middle flags @@ -2115,7 +2095,7 @@ void insertchar(int c, int flags, int second_indent) // Insert the end-comment string, except for the last // character, which will get inserted as normal later. - ins_bytes_len(lead_end, (size_t)(end_len - 1)); + ins_bytes_len((char *)lead_end, (size_t)(end_len - 1)); } } } @@ -2143,11 +2123,11 @@ void insertchar(int c, int flags, int second_indent) && !cindent_on() && !p_ri) { #define INPUT_BUFLEN 100 - char_u buf[INPUT_BUFLEN + 1]; + char buf[INPUT_BUFLEN + 1]; int i; colnr_T virtcol = 0; - buf[0] = (char_u)c; + buf[0] = (char)c; i = 1; if (textwidth > 0) { virtcol = get_nolist_virtcol(); @@ -2163,27 +2143,27 @@ void insertchar(int c, int flags, int second_indent) && MB_BYTE2LEN(c) == 1 && i < INPUT_BUFLEN && (textwidth == 0 - || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth) - && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1]))) { + || (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_u)c; + buf[i++] = (char)c; } do_digraph(-1); // clear digraphs - do_digraph(buf[i - 1]); // may be the start of a digraph + do_digraph((uint8_t)buf[i - 1]); // may be the start of a digraph buf[i] = NUL; ins_str(buf); if (flags & INSCHAR_CTRLV) { - redo_literal(*buf); + redo_literal((uint8_t)(*buf)); i = 1; } else { i = 0; } if (buf[i] != NUL) { - AppendToRedobuffLit((char *)buf + i, -1); + AppendToRedobuffLit(buf + i, -1); } } else { int cc; @@ -2191,9 +2171,9 @@ void insertchar(int c, int flags, int second_indent) if ((cc = utf_char2len(c)) > 1) { char buf[MB_MAXBYTES + 1]; - utf_char2bytes(c, (char *)buf); + utf_char2bytes(c, buf); buf[cc] = NUL; - ins_char_bytes((char_u *)buf, (size_t)cc); + ins_char_bytes(buf, (size_t)cc); AppendCharToRedobuff(c); } else { ins_char(c); @@ -2206,600 +2186,7 @@ void insertchar(int c, int flags, int second_indent) } } -/// Format text at the current insert position. -/// -/// If the INSCHAR_COM_LIST flag is present, then the value of second_indent -/// will be the comment leader length sent to open_line(). -/// -/// @param c character to be inserted (can be NUL) -static void internal_format(int textwidth, int second_indent, int flags, int format_only, int c) -{ - int cc; - int save_char = NUL; - bool haveto_redraw = false; - const bool fo_ins_blank = has_format_option(FO_INS_BLANK); - const bool fo_multibyte = has_format_option(FO_MBYTE_BREAK); - const bool fo_rigor_tw = has_format_option(FO_RIGOROUS_TW); - const bool fo_white_par = has_format_option(FO_WHITE_PAR); - bool first_line = true; - colnr_T leader_len; - bool no_leader = false; - int do_comments = (flags & INSCHAR_DO_COM); - int has_lbr = curwin->w_p_lbr; - - // make sure win_lbr_chartabsize() counts correctly - curwin->w_p_lbr = false; - - /* - * When 'ai' is off we don't want a space under the cursor to be - * deleted. Replace it with an 'x' temporarily. - */ - if (!curbuf->b_p_ai - && !(State & VREPLACE_FLAG)) { - cc = gchar_cursor(); - if (ascii_iswhite(cc)) { - save_char = cc; - pchar_cursor('x'); - } - } - - /* - * Repeat breaking lines, until the current line is not too long. - */ - while (!got_int) { - int startcol; // Cursor column at entry - int wantcol; // column at textwidth border - int foundcol; // column for start of spaces - int end_foundcol = 0; // column for start of word - colnr_T len; - colnr_T virtcol; - int orig_col = 0; - char_u *saved_text = NULL; - colnr_T col; - colnr_T end_col; - bool did_do_comment = false; - - virtcol = get_nolist_virtcol() - + char2cells(c != NUL ? c : gchar_cursor()); - if (virtcol <= (colnr_T)textwidth) { - break; - } - - if (no_leader) { - do_comments = false; - } else if (!(flags & INSCHAR_FORMAT) - && has_format_option(FO_WRAP_COMS)) { - do_comments = true; - } - - // Don't break until after the comment leader - if (do_comments) { - char_u *line = get_cursor_line_ptr(); - leader_len = get_leader_len((char *)line, NULL, false, true); - if (leader_len == 0 && curbuf->b_p_cin) { - // Check for a line comment after code. - int comment_start = check_linecomment(line); - if (comment_start != MAXCOL) { - leader_len = get_leader_len((char *)line + comment_start, NULL, false, true); - if (leader_len != 0) { - leader_len += comment_start; - } - } - } - } else { - leader_len = 0; - } - - // If the line doesn't start with a comment leader, then don't - // start one in a following broken line. Avoids that a %word - // moved to the start of the next line causes all following lines - // to start with %. - if (leader_len == 0) { - no_leader = true; - } - if (!(flags & INSCHAR_FORMAT) - && leader_len == 0 - && !has_format_option(FO_WRAP)) { - break; - } - if ((startcol = curwin->w_cursor.col) == 0) { - break; - } - - // find column of textwidth border - coladvance((colnr_T)textwidth); - wantcol = curwin->w_cursor.col; - - curwin->w_cursor.col = startcol; - foundcol = 0; - int skip_pos = 0; - - /* - * Find position to break at. - * Stop at first entered white when 'formatoptions' has 'v' - */ - while ((!fo_ins_blank && !has_format_option(FO_INS_VI)) - || (flags & INSCHAR_FORMAT) - || curwin->w_cursor.lnum != Insstart.lnum - || curwin->w_cursor.col >= Insstart.col) { - if (curwin->w_cursor.col == startcol && c != NUL) { - cc = c; - } else { - cc = gchar_cursor(); - } - if (WHITECHAR(cc)) { - // remember position of blank just before text - end_col = curwin->w_cursor.col; - - // find start of sequence of blanks - int wcc = 0; // counter for whitespace chars - while (curwin->w_cursor.col > 0 && WHITECHAR(cc)) { - dec_cursor(); - cc = gchar_cursor(); - - // Increment count of how many whitespace chars in this - // group; we only need to know if it's more than one. - if (wcc < 2) { - wcc++; - } - } - if (curwin->w_cursor.col == 0 && WHITECHAR(cc)) { - break; // only spaces in front of text - } - - // Don't break after a period when 'formatoptions' has 'p' and - // there are less than two spaces. - if (has_format_option(FO_PERIOD_ABBR) && cc == '.' && wcc < 2) { - continue; - } - - // Don't break until after the comment leader - if (curwin->w_cursor.col < leader_len) { - break; - } - - if (has_format_option(FO_ONE_LETTER)) { - // do not break after one-letter words - if (curwin->w_cursor.col == 0) { - break; // one-letter word at begin - } - // do not break "#a b" when 'tw' is 2 - if (curwin->w_cursor.col <= leader_len) { - break; - } - col = curwin->w_cursor.col; - dec_cursor(); - cc = gchar_cursor(); - - if (WHITECHAR(cc)) { - continue; // one-letter, continue - } - curwin->w_cursor.col = col; - } - - inc_cursor(); - - end_foundcol = end_col + 1; - foundcol = curwin->w_cursor.col; - if (curwin->w_cursor.col <= (colnr_T)wantcol) { - break; - } - } else if ((cc >= 0x100 || !utf_allow_break_before(cc)) && fo_multibyte) { - int ncc; - bool allow_break; |