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; - - // Break after or before a multi-byte character. - if (curwin->w_cursor.col != startcol) { - // Don't break until after the comment leader - if (curwin->w_cursor.col < leader_len) { - break; - } - col = curwin->w_cursor.col; - inc_cursor(); - ncc = gchar_cursor(); - allow_break = utf_allow_break(cc, ncc); - - // If we have already checked this position, skip! - if (curwin->w_cursor.col != skip_pos && allow_break) { - foundcol = curwin->w_cursor.col; - end_foundcol = foundcol; - if (curwin->w_cursor.col <= (colnr_T)wantcol) { - break; - } - } - curwin->w_cursor.col = col; - } - - if (curwin->w_cursor.col == 0) { - break; - } - - ncc = cc; - col = curwin->w_cursor.col; - - dec_cursor(); - cc = gchar_cursor(); - - if (WHITECHAR(cc)) { - continue; // break with space - } - // Don't break until after the comment leader. - if (curwin->w_cursor.col < leader_len) { - break; - } - - curwin->w_cursor.col = col; - skip_pos = curwin->w_cursor.col; - - allow_break = utf_allow_break(cc, ncc); - - // Must handle this to respect line break prohibition. - if (allow_break) { - foundcol = curwin->w_cursor.col; - end_foundcol = foundcol; - } - if (curwin->w_cursor.col <= (colnr_T)wantcol) { - const bool ncc_allow_break = utf_allow_break_before(ncc); - - if (allow_break) { - break; - } - if (!ncc_allow_break && !fo_rigor_tw) { - // Enable at most 1 punct hang outside of textwidth. - if (curwin->w_cursor.col == startcol) { - // We are inserting a non-breakable char, postpone - // line break check to next insert. - end_foundcol = foundcol = 0; - break; - } - - // Neither cc nor ncc is NUL if we are here, so - // it's safe to inc_cursor. - col = curwin->w_cursor.col; - - inc_cursor(); - cc = ncc; - ncc = gchar_cursor(); - // handle insert - ncc = (ncc != NUL) ? ncc : c; - - allow_break = utf_allow_break(cc, ncc); - - if (allow_break) { - // Break only when we are not at end of line. - end_foundcol = foundcol = ncc == NUL? 0 : curwin->w_cursor.col; - break; - } - curwin->w_cursor.col = col; - } - } - } - if (curwin->w_cursor.col == 0) { - break; - } - dec_cursor(); - } - - if (foundcol == 0) { // no spaces, cannot break line - curwin->w_cursor.col = startcol; - break; - } - - // Going to break the line, remove any "$" now. - undisplay_dollar(); - - // Offset between cursor position and line break is used by replace - // stack functions. MODE_VREPLACE does not use this, and backspaces - // over the text instead. - if (State & VREPLACE_FLAG) { - orig_col = startcol; // Will start backspacing from here - } else { - replace_offset = startcol - end_foundcol; - } - - /* - * adjust startcol for spaces that will be deleted and - * characters that will remain on top line - */ - curwin->w_cursor.col = foundcol; - while ((cc = gchar_cursor(), WHITECHAR(cc)) - && (!fo_white_par || curwin->w_cursor.col < startcol)) { - inc_cursor(); - } - startcol -= curwin->w_cursor.col; - if (startcol < 0) { - startcol = 0; - } - - if (State & VREPLACE_FLAG) { - // In MODE_VREPLACE state, we will backspace over the text to be - // wrapped, so save a copy now to put on the next line. - saved_text = vim_strsave(get_cursor_pos_ptr()); - curwin->w_cursor.col = orig_col; - saved_text[startcol] = NUL; - - // Backspace over characters that will move to the next line - if (!fo_white_par) { - backspace_until_column(foundcol); - } - } else { - // put cursor after pos. to break line - if (!fo_white_par) { - curwin->w_cursor.col = foundcol; - } - } - - /* - * Split the line just before the margin. - * Only insert/delete lines, but don't really redraw the window. - */ - open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX - + (fo_white_par ? OPENLINE_KEEPTRAIL : 0) - + (do_comments ? OPENLINE_DO_COM : 0) - + OPENLINE_FORMAT - + ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0), - ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent), - &did_do_comment); - if (!(flags & INSCHAR_COM_LIST)) { - old_indent = 0; - } - - // If a comment leader was inserted, may also do this on a following - // line. - if (did_do_comment) { - no_leader = false; - } - - replace_offset = 0; - if (first_line) { - if (!(flags & INSCHAR_COM_LIST)) { - // This section is for auto-wrap of numeric lists. When not - // in insert mode (i.e. format_lines()), the INSCHAR_COM_LIST - // flag will be set and open_line() will handle it (as seen - // above). The code here (and in get_number_indent()) will - // recognize comments if needed... - if (second_indent < 0 && has_format_option(FO_Q_NUMBER)) { - second_indent = get_number_indent(curwin->w_cursor.lnum - 1); - } - if (second_indent >= 0) { - if (State & VREPLACE_FLAG) { - change_indent(INDENT_SET, second_indent, false, NUL, true); - } else if (leader_len > 0 && second_indent - leader_len > 0) { - int padding = second_indent - leader_len; - - // We started at the first_line of a numbered list - // that has a comment. the open_line() function has - // inserted the proper comment leader and positioned - // the cursor at the end of the split line. Now we - // add the additional whitespace needed after the - // comment leader for the numbered list. - for (int i = 0; i < padding; i++) { - ins_str((char_u *)" "); - } - changed_bytes(curwin->w_cursor.lnum, leader_len); - } else { - (void)set_indent(second_indent, SIN_CHANGED); - } - } - } - first_line = false; - } - - if (State & VREPLACE_FLAG) { - // In MODE_VREPLACE state we have backspaced over the text to be - // moved, now we re-insert it into the new line. - ins_bytes(saved_text); - xfree(saved_text); - } else { - /* - * Check if cursor is not past the NUL off the line, cindent - * may have added or removed indent. - */ - curwin->w_cursor.col += startcol; - len = (colnr_T)STRLEN(get_cursor_line_ptr()); - if (curwin->w_cursor.col > len) { - 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; - line_breakcheck(); - } - - if (save_char != NUL) { // put back space after cursor - pchar_cursor((char_u)save_char); - } - - curwin->w_p_lbr = has_lbr; - - if (!format_only && haveto_redraw) { - update_topline(curwin); - redraw_curbuf_later(VALID); - } -} - -/// Called after inserting or deleting text: When 'formatoptions' includes the -/// 'a' flag format from the current line until the end of the paragraph. -/// Keep the cursor at the same position relative to the text. -/// The caller must have saved the cursor line for undo, following ones will be -/// saved here. -/// -/// @param trailblank when true also format with trailing blank -/// @param prev_line may start in previous line -void auto_format(bool trailblank, bool prev_line) -{ - pos_T pos; - colnr_T len; - char_u *old; - char_u *new, *pnew; - int wasatend; - int cc; - - if (!has_format_option(FO_AUTO)) { - return; - } - - pos = curwin->w_cursor; - old = get_cursor_line_ptr(); - - // 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 - // in 'formatoptions' and there is a single character before the cursor. - // Otherwise the line would be broken and when typing another non-white - // next they are not joined back together. - wasatend = (pos.col == (colnr_T)STRLEN(old)); - if (*old != NUL && !trailblank && wasatend) { - dec_cursor(); - cc = gchar_cursor(); - if (!WHITECHAR(cc) && curwin->w_cursor.col > 0 - && has_format_option(FO_ONE_LETTER)) { - dec_cursor(); - } - cc = gchar_cursor(); - if (WHITECHAR(cc)) { - curwin->w_cursor = pos; - return; - } - curwin->w_cursor = pos; - } - - // With the 'c' flag in 'formatoptions' and 't' missing: only format - // comments. - if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP) - && get_leader_len((char *)old, NULL, false, true) == 0) { - return; - } - - /* - * May start formatting in a previous line, so that after "x" a word is - * moved to the previous line if it fits there now. Only when this is not - * the start of a paragraph. - */ - if (prev_line && !paragraph_start(curwin->w_cursor.lnum)) { - --curwin->w_cursor.lnum; - if (u_save_cursor() == FAIL) { - return; - } - } - - /* - * Do the formatting and restore the cursor position. "saved_cursor" will - * be adjusted for the text formatting. - */ - saved_cursor = pos; - format_lines((linenr_T) - 1, false); - curwin->w_cursor = saved_cursor; - saved_cursor.lnum = 0; - - if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) { - // "cannot happen" - curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; - coladvance(MAXCOL); - } else { - check_cursor_col(); - } - - // Insert mode: If the cursor is now after the end of the line while it - // previously wasn't, the line was broken. Because of the rule above we - // need to add a space when 'w' is in 'formatoptions' to keep a paragraph - // formatted. - if (!wasatend && has_format_option(FO_WHITE_PAR)) { - new = get_cursor_line_ptr(); - len = (colnr_T)STRLEN(new); - if (curwin->w_cursor.col == len) { - pnew = vim_strnsave(new, (size_t)len + 2); - pnew[len] = ' '; - pnew[len + 1] = NUL; - ml_replace(curwin->w_cursor.lnum, (char *)pnew, false); - // remove the space later - did_add_space = true; - } else { - // may remove added space - check_auto_format(false); - } - } - - check_cursor(); -} - -/// When an extra space was added to continue a paragraph for auto-formatting, -/// delete it now. The space must be under the cursor, just after the insert -/// position. -/// -/// @param end_insert true when ending Insert mode -static void check_auto_format(bool end_insert) -{ - int c = ' '; - int cc; - - if (did_add_space) { - cc = gchar_cursor(); - 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; - } - } - } -} - -/// Find out textwidth to be used for formatting: -/// if 'textwidth' option is set, use it -/// else if 'wrapmargin' option is set, use curwin->w_width_inner-'wrapmargin' -/// if invalid value, use 0. -/// Set default to window width (maximum 79) for "gq" operator. -/// -/// @param ff force formatting (for "gq" command) -int comp_textwidth(bool ff) -{ - int textwidth = (int)curbuf->b_p_tw; - if (textwidth == 0 && curbuf->b_p_wm) { - // The width is the window width minus 'wrapmargin' minus all the - // things that add to the margin. - textwidth = curwin->w_width_inner - (int)curbuf->b_p_wm; - if (cmdwin_type != 0) { - textwidth -= 1; - } - textwidth -= win_fdccol_count(curwin); - textwidth -= win_signcol_count(curwin); - - if (curwin->w_p_nu || curwin->w_p_rnu) { - textwidth -= 8; - } - } - if (textwidth < 0) { - textwidth = 0; - } - if (ff && textwidth == 0) { - textwidth = curwin->w_width_inner - 1; - if (textwidth > 79) { - textwidth = 79; - } - } - return textwidth; -} - -/* - * Put a character in the redo buffer, for when just after a CTRL-V. - */ +// Put a character in the redo buffer, for when just after a CTRL-V. static void redo_literal(int c) { char buf[10]; @@ -2849,10 +2236,8 @@ static void start_arrow_common(pos_T *end_insert_pos, bool end_change) check_spell_redraw(); } -/* - * If we skipped highlighting word at cursor, do it now. - * It may be skipped again, thus reset spell_redraw_lnum first. - */ +// If we skipped highlighting word at cursor, do it now. +// It may be skipped again, thus reset spell_redraw_lnum first. static void check_spell_redraw(void) { if (spell_redraw_lnum != 0) { @@ -2863,11 +2248,9 @@ static void check_spell_redraw(void) } } -/* - * stop_arrow() is called before a change is made in insert mode. - * If an arrow key has been used, start a new insertion. - * Returns FAIL if undo is impossible, shouldn't insert then. - */ +// stop_arrow() is called before a change is made in insert mode. +// If an arrow key has been used, start a new insertion. +// Returns FAIL if undo is impossible, shouldn't insert then. int stop_arrow(void) { if (arrow_used) { @@ -2912,19 +2295,17 @@ int stop_arrow(void) static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) { int cc; - char_u *ptr; + 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". - */ + // 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)) { + && (int)strlen(ptr) > new_insert_skip)) { xfree(last_insert); last_insert = ptr; last_insert_skip = new_insert_skip; @@ -2958,8 +2339,8 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) if (gchar_cursor() != NUL) { inc_cursor(); } - /* If the cursor is still at the same character, also keep - * the "coladd". */ + // If the cursor is still at the same character, also keep + // the "coladd". if (gchar_cursor() == NUL && curwin->w_cursor.lnum == tpos.lnum && curwin->w_cursor.col == tpos.col) { @@ -2986,7 +2367,7 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) check_cursor_col(); // make sure it is not past the line for (;;) { if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) { - --curwin->w_cursor.col; + curwin->w_cursor.col--; } cc = gchar_cursor(); if (!ascii_iswhite(cc)) { @@ -3003,7 +2384,7 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) tpos = curwin->w_cursor; tpos.col++; if (cc != NUL && gchar_pos(&tpos) == NUL) { - ++curwin->w_cursor.col; // put cursor back on the NUL + curwin->w_cursor.col++; // put cursor back on the NUL } } @@ -3028,13 +2409,11 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) } } -/* - * Set the last inserted text to a single character. - * Used for the replace command. - */ +// Set the last inserted text to a single character. +// Used for the replace command. void set_last_insert(int c) { - char_u *s; + char *s; xfree(last_insert); last_insert = xmalloc(MB_MAXBYTES * 3 + 5); @@ -3043,7 +2422,7 @@ void set_last_insert(int c) if (c < ' ' || c == DEL) { *s++ = Ctrl_V; } - s = add_char2buf(c, s); + s = (char *)add_char2buf(c, (char_u *)s); *s++ = ESC; *s++ = NUL; last_insert_skip = 0; @@ -3056,13 +2435,11 @@ void free_last_insert(void) } #endif -/* - * move cursor to start of line - * if flags & BL_WHITE move to first non-white - * if flags & BL_SOL move to first non-white if startofline is set, - * otherwise keep "curswant" column - * if flags & BL_FIX don't leave the cursor on a NUL. - */ +// move cursor to start of line +// if flags & BL_WHITE move to first non-white +// if flags & BL_SOL move to first non-white if startofline is set, +// otherwise keep "curswant" column +// if flags & BL_FIX don't leave the cursor on a NUL. void beginline(int flags) { if ((flags & BL_SOL) && !p_sol) { @@ -3074,22 +2451,20 @@ void beginline(int flags) if (flags & (BL_WHITE | BL_SOL)) { char_u *ptr; - for (ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr) - && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr) { - ++curwin->w_cursor.col; + for (ptr = (char_u *)get_cursor_line_ptr(); ascii_iswhite(*ptr) + && !((flags & BL_FIX) && ptr[1] == NUL); ptr++) { + curwin->w_cursor.col++; } } - curwin->w_set_curswant = TRUE; + curwin->w_set_curswant = true; } } -/* - * oneright oneleft cursor_down cursor_up - * - * Move one char {right,left,down,up}. - * Doesn't move onto the NUL past the end of the line, unless it is allowed. - * Return OK when successful, FAIL when we hit a line of file boundary. - */ +// oneright oneleft cursor_down cursor_up +// +// Move one char {right,left,down,up}. +// Doesn't move onto the NUL past the end of the line, unless it is allowed. +// Return OK when successful, FAIL when we hit a line of file boundary. int oneright(void) { @@ -3100,7 +2475,7 @@ int oneright(void) pos_T prevpos = curwin->w_cursor; // Adjust for multi-wide char (excluding TAB) - ptr = (char *)get_cursor_pos_ptr(); + ptr = get_cursor_pos_ptr(); coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(utf_ptr2char(ptr))) ? ptr2cells(ptr) : 1)); curwin->w_set_curswant = true; @@ -3109,7 +2484,7 @@ int oneright(void) || prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL; } - ptr = (char *)get_cursor_pos_ptr(); + ptr = get_cursor_pos_ptr(); if (*ptr == NUL) { return FAIL; // already at the very end } @@ -3123,7 +2498,7 @@ int oneright(void) } curwin->w_cursor.col += l; - curwin->w_set_curswant = TRUE; + curwin->w_set_curswant = true; return OK; } @@ -3152,13 +2527,13 @@ int oneleft(void) if (curwin->w_cursor.coladd == 1) { // Adjust for multi-wide char (not a TAB) - char *ptr = (char *)get_cursor_pos_ptr(); + char *ptr = get_cursor_pos_ptr(); if (*ptr != TAB && vim_isprintc(utf_ptr2char(ptr)) && ptr2cells(ptr) > 1) { curwin->w_cursor.coladd = 0; } } - curwin->w_set_curswant = TRUE; + curwin->w_set_curswant = true; return OK; } @@ -3166,8 +2541,8 @@ int oneleft(void) return FAIL; } - curwin->w_set_curswant = TRUE; - --curwin->w_cursor.col; + curwin->w_set_curswant = true; + curwin->w_cursor.col--; // if the character on the left of the current cursor is a multi-byte // character, move to its first byte @@ -3175,98 +2550,112 @@ int oneleft(void) return OK; } -/// @oaram upd_topline When TRUE: update topline -int cursor_up(long n, int upd_topline) +/// 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) { - linenr_T lnum; + linenr_T lnum = wp->w_cursor.lnum; - if (n > 0) { - lnum = curwin->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)) { + // Count each sequence of folded lines as one logical line. - // This fails if the cursor is already in the first line. - if (lnum <= 1) { - return FAIL; - } - if (n >= lnum) { - lnum = 1; - } else if (hasAnyFolding(curwin)) { - /* - * Count each sequence of folded lines as one logical line. - */ - // go to the start of the current fold - (void)hasFolding(lnum, &lnum, NULL); - - while (n--) { - // move up one line - lnum--; - if (lnum <= 1) { - break; - } - // If we entered a fold, move to the beginning, unless in - // Insert mode or when 'foldopen' contains "all": it will open - // in a moment. - if (n > 0 || !((State & MODE_INSERT) || (fdo_flags & FDO_ALL))) { - (void)hasFolding(lnum, &lnum, NULL); - } + // go to the start of the current fold + (void)hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL); + + while (n--) { + // move up one line + lnum--; + if (lnum <= 1) { + break; } - if (lnum < 1) { - lnum = 1; + // If we entered a fold, move to the beginning, unless in + // Insert mode or when 'foldopen' contains "all": it will open + // in a moment. + if (n > 0 || !((State & MODE_INSERT) || (fdo_flags & FDO_ALL))) { + (void)hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL); } - } else { - lnum -= (linenr_T)n; } - curwin->w_cursor.lnum = lnum; + if (lnum < 1) { + lnum = 1; + } + } else { + lnum -= (linenr_T)n; + } + + wp->w_cursor.lnum = lnum; + return lnum; +} + +/// @param upd_topline When true: update topline +int cursor_up(long n, int upd_topline) +{ + if (n > 0 && cursor_up_inner(curwin, n) == 0) { + return FAIL; } // try to advance to the column we want to be at coladvance(curwin->w_curswant); if (upd_topline) { - update_topline(curwin); // make sure curwin->w_topline is valid + update_topline(curwin); // make sure curwin->w_topline is valid } return OK; } -/// Cursor down a number of logical lines. -/// -/// @param upd_topline When TRUE: update topline -int cursor_down(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) { - linenr_T lnum; - - if (n > 0) { - lnum = curwin->w_cursor.lnum; - // Move to last line of fold, will fail if it's the end-of-file. - (void)hasFolding(lnum, NULL, &lnum); + linenr_T lnum = wp->w_cursor.lnum; + linenr_T line_count = wp->w_buffer->b_ml.ml_line_count; - // This fails if the cursor is already in the last line. - if (lnum >= curbuf->b_ml.ml_line_count) { - return FAIL; - } - if (lnum + n >= curbuf->b_ml.ml_line_count) { - lnum = curbuf->b_ml.ml_line_count; - } else if (hasAnyFolding(curwin)) { - linenr_T last; + // 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)) { + linenr_T last; - // count each sequence of folded lines as one logical line - while (n--) { - if (hasFolding(lnum, NULL, &last)) { - lnum = last + 1; - } else { - lnum++; - } - if (lnum >= curbuf->b_ml.ml_line_count) { - break; - } + // count each sequence of folded lines as one logical line + while (n--) { + if (hasFoldingWin(wp, lnum, NULL, &last, true, NULL)) { + lnum = last + 1; + } else { + lnum++; } - if (lnum > curbuf->b_ml.ml_line_count) { - lnum = curbuf->b_ml.ml_line_count; + if (lnum >= line_count) { + break; } - } else { - lnum += (linenr_T)n; } - curwin->w_cursor.lnum = lnum; + if (lnum > line_count) { + lnum = line_count; + } + } else { + lnum += (linenr_T)n; + } + + wp->w_cursor.lnum = lnum; + return lnum; +} + +/// @param upd_topline When true: update topline +int cursor_down(long n, int upd_topline) +{ + if (n > 0 && cursor_down_inner(curwin, n) == 0) { + return FAIL; } // try to advance to the column we want to be at @@ -3288,12 +2677,12 @@ int cursor_down(long n, int upd_topline) /// @param no_esc Don't add an ESC at the end int stuff_inserted(int c, long count, int no_esc) { - char_u *esc_ptr; - char_u *ptr; - char_u *last_ptr; - char_u last = NUL; + char *esc_ptr; + char *ptr; + char *last_ptr; + char last = NUL; - ptr = get_last_insert(); + ptr = (char *)get_last_insert(); if (ptr == NULL) { emsg(_(e_noinstext)); return FAIL; @@ -3303,7 +2692,7 @@ int stuff_inserted(int c, long count, int no_esc) if (c != NUL) { stuffcharReadbuff(c); } - if ((esc_ptr = STRRCHR(ptr, ESC)) != NULL) { + if ((esc_ptr = strrchr(ptr, ESC)) != NULL) { // remove the ESC. *esc_ptr = NUL; } @@ -3311,7 +2700,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; + 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; @@ -3348,23 +2737,21 @@ char_u *get_last_insert(void) if (last_insert == NULL) { return NULL; } - return last_insert + last_insert_skip; + return (char_u *)last_insert + last_insert_skip; } -/* - * Get last inserted string, and remove trailing <Esc>. - * Returns pointer to allocated memory (must be freed) or NULL. - */ -char_u *get_last_insert_save(void) +// 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_u *s; + char *s; int len; if (last_insert == NULL) { return NULL; } - s = vim_strsave(last_insert + last_insert_skip); - len = (int)STRLEN(s); + s = xstrdup(last_insert + last_insert_skip); + len = (int)strlen(s); if (len > 0 && s[len - 1] == ESC) { // remove trailing ESC s[len - 1] = NUL; } @@ -3393,20 +2780,18 @@ static bool echeck_abbr(int c) curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0); } -/* - * replace-stack functions - * - * When replacing characters, the replaced characters are remembered for each - * new character. This is used to re-insert the old text when backspacing. - * - * There is a NUL headed list of characters for each character that is - * currently in the file after the insertion point. When BS is used, one NUL - * headed list is put back for the deleted character. - * - * For a newline, there are two NUL headed lists. One contains the characters - * that the NL replaced. The extra one stores the characters after the cursor - * that were deleted (always white space). - */ +// replace-stack functions +// +// When replacing characters, the replaced characters are remembered for each +// new character. This is used to re-insert the old text when backspacing. +// +// There is a NUL headed list of characters for each character that is +// currently in the file after the insertion point. When BS is used, one NUL +// headed list is put back for the deleted character. +// +// For a newline, there are two NUL headed lists. One contains the characters +// 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 ssize_t replace_stack_nr = 0; // next entry in replace stack @@ -3437,17 +2822,16 @@ void replace_push(int c) replace_stack_nr++; } -/* - * Push a character onto the replace stack. Handles a multi-byte character in - * reverse byte order, so that the first byte is popped off first. - * Return the number of bytes done (includes composing characters). - */ -int replace_push_mb(char_u *p) +/// Push a character onto the replace stack. Handles a multi-byte character in +/// reverse byte order, so that the first byte is popped off first. +/// +/// @return the number of bytes done (includes composing characters). +int replace_push_mb(char *p) { - int l = utfc_ptr2len((char *)p); + int l = utfc_ptr2len(p); int j; - for (j = l - 1; j >= 0; --j) { + for (j = l - 1; j >= 0; j--) { replace_push(p[j]); } return l; @@ -3492,10 +2876,8 @@ static void replace_pop_ins(void) State = oldState; } -/* - * Insert bytes popped from the replace stack. "cc" is the first byte. If it - * indicates a multi-byte char, pop the other bytes too. - */ +// Insert bytes popped from the replace stack. "cc" is the first byte. If it +// indicates a multi-byte char, pop the other bytes too. static void mb_replace_pop_ins(int cc) { int n; @@ -3508,7 +2890,7 @@ static void mb_replace_pop_ins(int cc) for (i = 1; i < n; i++) { buf[i] = (char_u)replace_pop(); } - ins_bytes_len(buf, (size_t)n); + ins_bytes_len((char *)buf, (size_t)n); } else { ins_char(cc); } @@ -3531,7 +2913,7 @@ static void mb_replace_pop_ins(int cc) buf[i] = (char_u)replace_pop(); } if (utf_iscomposing(utf_ptr2char((char *)buf))) { - ins_bytes_len(buf, (size_t)n); + ins_bytes_len((char *)buf, (size_t)n); } else { // Not a composing char, put it back. for (i = n - 1; i >= 0; i--) { @@ -3542,10 +2924,8 @@ static void mb_replace_pop_ins(int cc) } } -/* - * make the replace stack empty - * (called when exiting replace mode) - */ +// make the replace stack empty +// (called when exiting replace mode) static void replace_flush(void) { XFREE_CLEAR(replace_stack); @@ -3553,15 +2933,13 @@ static void replace_flush(void) replace_stack_nr = 0; } -/* - * Handle doing a BS for one character. - * cc < 0: replace stack empty, just move cursor - * cc == 0: character was inserted, delete it - * cc > 0: character was replaced, put cc (first byte of original char) back - * and check for more characters to be put back - * When "limit_col" is >= 0, don't delete before this column. Matters when - * using composing characters, use del_char_after_col() instead of del_char(). - */ +// Handle doing a BS for one character. +// cc < 0: replace stack empty, just move cursor +// cc == 0: character was inserted, delete it +// cc > 0: character was replaced, put cc (first byte of original char) back +// and check for more characters to be put back +// When "limit_col" is >= 0, don't delete before this column. Matters when +// using composing characters, use del_char_after_col() instead of del_char(). static void replace_do_bs(int limit_col) { int cc; @@ -3569,7 +2947,7 @@ static void replace_do_bs(int limit_col) int ins_len; int orig_vcols = 0; colnr_T start_vcol; - char_u *p; + char *p; int i; int vcol; const int l_State = State; @@ -3584,7 +2962,7 @@ static void replace_do_bs(int limit_col) } (void)del_char_after_col(limit_col); if (l_State & VREPLACE_FLAG) { - orig_len = (int)STRLEN(get_cursor_pos_ptr()); + orig_len = (int)strlen(get_cursor_pos_ptr()); } replace_push(cc); replace_pop_ins(); @@ -3592,11 +2970,11 @@ static void replace_do_bs(int limit_col) if (l_State & VREPLACE_FLAG) { // Get the number of screen cells used by the inserted characters p = get_cursor_pos_ptr(); - ins_len = (int)STRLEN(p) - orig_len; + ins_len = (int)strlen(p) - orig_len; vcol = start_vcol; for (i = 0; i < ins_len; i++) { vcol += win_chartabsize(curwin, p + i, vcol); - i += utfc_ptr2len((char *)p) - 1; + i += utfc_ptr2len(p) - 1; } vcol -= start_vcol; @@ -3624,40 +3002,10 @@ bool cindent_on(void) return !p_paste && (curbuf->b_p_cin || *curbuf->b_p_inde != NUL); } -/* - * Re-indent the current line, based on the current contents of it and the - * surrounding lines. Fixing the cursor position seems really easy -- I'm very - * confused what all the part that handles Control-T is doing that I'm not. - * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent. - */ -void fixthisline(IndentGetter get_the_indent) -{ - int amount = get_the_indent(); - - if (amount >= 0) { - change_indent(INDENT_SET, amount, false, 0, true); - if (linewhite(curwin->w_cursor.lnum)) { - did_ai = true; // delete the indent if the line stays empty - } - } -} - -void fix_indent(void) -{ - if (p_paste) { - return; - } - if (curbuf->b_p_lisp && curbuf->b_p_ai) { - fixthisline(get_lisp_indent); - } else if (cindent_on()) { - do_c_expr_indent(); - } -} - /// Check that "cinkeys" contains the key "keytyped", /// when == '*': Only if key is preceded with '*' (indent before insert) /// when == '!': Only if key is preceded with '!' (don't insert) -/// when == ' ': Only if key is not preceded with '*' (indent afterwards) +/// when == ' ': Only if key is not preceded with '*' or '!' (indent afterwards) /// /// "keytyped" can have a few special values: /// KEY_OPEN_FORW : @@ -3669,11 +3017,11 @@ void fix_indent(void) /// @param line_is_empty when true, accept keys with '0' before them. bool in_cinkeys(int keytyped, int when, bool line_is_empty) { - char_u *look; + char *look; int try_match; int try_match_word; - char_u *p; - char_u *line; + char *p; + char *line; bool icase; if (keytyped == NUL) { @@ -3687,17 +3035,15 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) look = curbuf->b_p_cink; // 'indentexpr' empty: use 'cinkeys' } while (*look) { - /* - * Find out if we want to try a match with this key, depending on - * 'when' and a '*' or '!' before the key. - */ + // Find out if we want to try a match with this key, depending on + // 'when' and a '*' or '!' before the key. switch (when) { case '*': try_match = (*look == '*'); break; case '!': try_match = (*look == '!'); break; default: - try_match = (*look != '*'); break; + try_match = (*look != '*') && (*look != '!'); break; } if (*look == '*' || *look == '!') { look++; @@ -3740,8 +3086,8 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) } else if (*look == 'e') { if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4) { p = get_cursor_line_ptr(); - if ((char_u *)skipwhite((char *)p) == p + curwin->w_cursor.col - 4 - && STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0) { + if (skipwhite(p) == p + curwin->w_cursor.col - 4 + && strncmp(p + curwin->w_cursor.col - 4, "else", 4) == 0) { return true; } } @@ -3780,12 +3126,12 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) // make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>, // <:> and <!> so that people can re-indent on o, O, e, 0, <, // >, *, : and ! keys if they really really want to. - if (vim_strchr("<>!*oOe0:", look[1]) != NULL + if (vim_strchr("<>!*oOe0:", (uint8_t)look[1]) != NULL && keytyped == look[1]) { return true; } - if (keytyped == get_special_key_code(look + 1)) { + if (keytyped == get_special_key_code((char_u *)look + 1)) { return true; } } @@ -3804,19 +3150,19 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) } else { icase = false; } - p = (char_u *)vim_strchr((char *)look, ','); + p = vim_strchr(look, ','); if (p == NULL) { - p = look + STRLEN(look); + p = look + strlen(look); } if ((try_match || try_match_word) && curwin->w_cursor.col >= (colnr_T)(p - look)) { bool match = false; if (keytyped == KEY_COMPLETE) { - char_u *n, *s; + char *n, *s; - /* Just completed a word, check if it starts with "look". - * search back for the start of a word. */ + // Just completed a word, check if it starts with "look". + // search back for the start of a word. line = get_cursor_line_ptr(); for (s = line + curwin->w_cursor.col; s > line; s = n) { n = mb_prevptr(line, s); @@ -3828,28 +3174,28 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) if (s + (p - look) <= line + curwin->w_cursor.col && (icase ? mb_strnicmp(s, look, (size_t)(p - look)) - : STRNCMP(s, look, p - look)) == 0) { + : strncmp(s, look, (size_t)(p - look))) == 0) { match = true; } } else { // TODO(@brammool): multi-byte - if (keytyped == (int)p[-1] + if (keytyped == (int)(uint8_t)p[-1] || (icase && keytyped < 256 - && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1]))) { + && TOLOWER_LOC(keytyped) == TOLOWER_LOC((uint8_t)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])) + || !vim_iswordc((uint8_t)line[-(p - look) - 1])) && (icase ? mb_strnicmp(line - (p - look), look, (size_t)(p - look)) - : STRNCMP(line - (p - look), look, p - look)) == 0) { + : strncmp(line - (p - look), look, (size_t)(p - look))) == 0) { match = true; } } } if (match && try_match_word && !try_match) { - /* "0=word": Check if there are only blanks before the - * word. */ + // "0=word": Check if there are only blanks before the + // word. if (getwhitecols_curline() != (int)(curwin->w_cursor.col - (p - look))) { match = false; @@ -3863,7 +3209,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) // Ok, it's a boring generic character. } else { - if (try_match && *look == keytyped) { + if (try_match && (uint8_t)(*look) == keytyped) { return true; } if (*look != NUL) { @@ -3871,17 +3217,13 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) } } - /* - * Skip over ", ". - */ + // Skip over ", ". look = skip_to_option_part(look); } return false; } -/* - * Map Hebrew keyboard when in hkmap mode. - */ +// Map Hebrew keyboard when in hkmap mode. int hkmap(int c) FUNC_ATTR_PURE { @@ -3983,9 +3325,7 @@ static void ins_reg(void) int literally = 0; int vis_active = VIsual_active; - /* - * If we are going to wait for a character, show a '"'. - */ + // If we are going to wait for a character, show a '"'. pc_status = PC_STATUS_UNSET; if (redrawing() && !char_avail()) { // may need to redraw when no more chars available now @@ -4000,13 +3340,13 @@ static void ins_reg(void) no_mapping++; allow_keys++; regname = plain_vgetc(); - LANGMAP_ADJUST(regname, TRUE); + LANGMAP_ADJUST(regname, true); if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P) { // Get a third key for literal register insertion literally = regname; add_to_showcmd_c(literally); regname = plain_vgetc(); - LANGMAP_ADJUST(regname, TRUE); + LANGMAP_ADJUST(regname, true); } no_mapping--; allow_keys--; @@ -4044,7 +3384,7 @@ static void ins_reg(void) need_redraw = true; // remove the '"' } else if (stop_insert_mode) { // When the '=' register was used and a function was invoked that - // did ":stopinsert" then stuff_empty() returns FALSE but we won't + // did ":stopinsert" then stuff_empty() returns false but we won't // insert anything, need to remove the '"' need_redraw = true; } @@ -4067,9 +3407,7 @@ static void ins_reg(void) } } -/* - * CTRL-G commands in Insert mode. - */ +// CTRL-G commands in Insert mode. static void ins_ctrl_g(void) { int c; @@ -4123,9 +3461,7 @@ static void ins_ctrl_g(void) } } -/* - * CTRL-^ in Insert mode. - */ +// CTRL-^ in Insert mode. static void ins_ctrl_hat(void) { if (map_to_exists_mode("", MODE_LANGMAP, false)) { @@ -4138,7 +3474,7 @@ static void ins_ctrl_hat(void) State |= MODE_LANGMAP; } } - set_iminsert_global(); + set_iminsert_global(curbuf); showmode(); // Show/unshow value of 'keymap' in status lines. status_redraw_curbuf(); @@ -4169,10 +3505,8 @@ static bool ins_esc(long *count, int cmdchar, bool nomove) AppendToRedobuff(ESC_STR); } - /* - * Repeating insert may take a long time. Check for - * interrupt now and then. - */ + // Repeating insert may take a long time. Check for + // interrupt now and then. if (*count > 0) { line_breakcheck(); if (got_int) { @@ -4195,7 +3529,7 @@ static bool ins_esc(long *count, int cmdchar, bool nomove) // Repeat the insert return false; } - stop_insert(&curwin->w_cursor, TRUE, nomove); + stop_insert(&curwin->w_cursor, true, nomove); undisplay_dollar(); } @@ -4215,10 +3549,8 @@ static bool ins_esc(long *count, int cmdchar, bool nomove) RESET_FMARK(&curbuf->b_last_insert, curwin->w_cursor, curbuf->b_fnum, view); } - /* - * The cursor should end up on the last inserted character. - * Don't do it for CTRL-O, unless past the end of the line. - */ + // The cursor should end up on the last inserted character. + // Don't do it for CTRL-O, unless past the end of the line. if (!nomove && (curwin->w_cursor.col != 0 || curwin->w_cursor.coladd > 0) && (restart_edit == NUL || (gchar_cursor() == NUL && !VIsual_active)) @@ -4256,15 +3588,13 @@ static bool ins_esc(long *count, int cmdchar, bool nomove) return true; } -/* - * Toggle language: hkmap and revins_on. - * Move to end of reverse inserted text. - */ +// Toggle language: hkmap and revins_on. +// Move to end of reverse inserted text. static void ins_ctrl_(void) { if (revins_on && revins_chars && revins_scol >= 0) { while (gchar_cursor() != NUL && revins_chars--) { - ++curwin->w_cursor.col; + curwin->w_cursor.col++; } } p_ri = !p_ri; @@ -4326,14 +3656,11 @@ static bool ins_start_select(int c) return false; } -/* - * <Insert> key in Insert mode: toggle insert/replace mode. - */ +// <Insert> key in Insert mode: toggle insert/replace mode. static void ins_insert(int replaceState) { set_vim_var_string(VV_INSERTMODE, ((State & REPLACE_FLAG) ? "i" : - replaceState == MODE_VREPLACE ? "v" : - "r"), 1); + replaceState == MODE_VREPLACE ? "v" : "r"), 1); ins_apply_autocmds(EVENT_INSERTCHANGE); if (State & REPLACE_FLAG) { State = MODE_INSERT | (State & MODE_LANGMAP); @@ -4346,9 +3673,7 @@ static void ins_insert(int replaceState) ui_cursor_shape(); // may show different cursor shape } -/* - * Pressed CTRL-O in Insert mode. - */ +// Pressed CTRL-O in Insert mode. static void ins_ctrl_o(void) { if (State & VREPLACE_FLAG) { @@ -4365,13 +3690,11 @@ static void ins_ctrl_o(void) } } -/* - * If the cursor is on an indent, ^T/^D insert/delete one - * shiftwidth. Otherwise ^T/^D behave like a "<<" or ">>". - * Always round the indent to 'shiftwidth', this is compatible - * with vi. But vi only supports ^T and ^D after an - * autoindent, we support it everywhere. - */ +// If the cursor is on an indent, ^T/^D insert/delete one +// shiftwidth. Otherwise ^T/^D behave like a "<<" or ">>". +// Always round the indent to 'shiftwidth', this is compatible +// with vi. But vi only supports ^T and ^D after an +// autoindent, we support it everywhere. static void ins_shift(int c, int lastc) { if (stop_arrow() == FAIL) { @@ -4379,9 +3702,7 @@ static void ins_shift(int c, int lastc) } AppendCharToRedobuff(c); - /* - * 0^D and ^^D: remove all indent. - */ + // 0^D and ^^D: remove all indent. if (c == Ctrl_D && (lastc == '0' || lastc == '^') && curwin->w_cursor.col > 0) { curwin->w_cursor.col--; @@ -4393,12 +3714,12 @@ static void ins_shift(int c, int lastc) if (lastc == '^') { old_indent = get_indent(); // remember curr. indent } - change_indent(INDENT_SET, 0, TRUE, 0, TRUE); + change_indent(INDENT_SET, 0, true, 0, true); } else { - change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE); + change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, true, 0, true); } - if (did_ai && *skipwhite((char *)get_cursor_line_ptr()) != NUL) { + if (did_ai && *skipwhite(get_cursor_line_ptr()) != NUL) { did_ai = false; } did_si = false; @@ -4437,9 +3758,7 @@ static void ins_del(void) AppendCharToRedobuff(K_DEL); } -/* - * Delete one character for ins_bs(). - */ +// Delete one character for ins_bs(). static void ins_bs_one(colnr_T *vcolp) { dec_cursor(); @@ -4532,13 +3851,11 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) return false; } Insstart.lnum--; - Insstart.col = (colnr_T)STRLEN(ml_get(Insstart.lnum)); + Insstart.col = (colnr_T)strlen(ml_get(Insstart.lnum)); } - /* - * In replace mode: - * cc < 0: NL was inserted, delete it - * cc >= 0: NL was replaced, put original characters back - */ + // In replace mode: + // cc < 0: NL was inserted, delete it + // cc >= 0: NL was replaced, put original characters back cc = -1; if (State & REPLACE_FLAG) { cc = replace_pop(); // returns -1 if NL was inserted @@ -4558,16 +3875,16 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) // again when auto-formatting. if (has_format_option(FO_AUTO) && has_format_option(FO_WHITE_PAR)) { - char_u *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, true); + char *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, true); int len; - len = (int)STRLEN(ptr); + len = (int)strlen(ptr); if (len > 0 && ptr[len - 1] == ' ') { ptr[len - 1] = NUL; } } - do_join(2, FALSE, FALSE, FALSE, false); + do_join(2, false, false, false, false); if (temp == NUL && gchar_cursor() != NUL) { inc_cursor(); } @@ -4618,9 +3935,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) curwin->w_cursor.col = save_col; } - /* - * Handle deleting one 'shiftwidth' or 'softtabstop'. - */ + // Handle deleting one 'shiftwidth' or 'softtabstop'. if (mode == BACKSPACE_CHAR && ((p_sta && in_indent) || ((get_sts_value() != 0 @@ -4654,7 +3969,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) // delete characters until we are at or before want_vcol while (vcol > want_vcol && curwin->w_cursor.col > 0 - && (cc = *(get_cursor_pos_ptr() - 1), ascii_iswhite(cc))) { + && (cc = (uint8_t)(*(get_cursor_pos_ptr() - 1)), ascii_iswhite(cc))) { ins_bs_one(&vcol); } @@ -4669,7 +3984,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) if (State & VREPLACE_FLAG) { ins_char(' '); } else { - ins_str((char_u *)" "); + ins_str(" "); if ((State & REPLACE_FLAG)) { replace_push(NUL); } @@ -4841,7 +4156,7 @@ static void ins_mousescroll(int dir) if (dir == MSCR_DOWN || dir == MSCR_UP) { if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) { scroll_redraw(dir, (long)(curwin->w_botline - curwin->w_topline)); - } else { + } else if (p_mousescroll_vert > 0) { scroll_redraw(dir, p_mousescroll_vert); } } else { @@ -4849,7 +4164,7 @@ static void ins_mousescroll(int dir) } } - curwin->w_redr_status = TRUE; + curwin->w_redr_status = true; curwin = old_curwin; curbuf = curwin->w_buffer; @@ -4880,7 +4195,7 @@ static void ins_left(void) revins_legal++; } revins_chars++; - } else if (vim_strchr((char *)p_ww, '[') != NULL && curwin->w_cursor.lnum > 1) { + } else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1) { // if 'whichwrap' set for cursor in insert mode may go to previous line. // always break undo when moving upwards/downwards, else undo may break start_arrow(&tpos); @@ -4966,14 +4281,14 @@ static void ins_right(void) if (virtual_active()) { oneright(); } else { - curwin->w_cursor.col += utfc_ptr2len((char *)get_cursor_pos_ptr()); + curwin->w_cursor.col += utfc_ptr2len(get_cursor_pos_ptr()); } revins_legal++; if (revins_chars) { revins_chars--; } - } else if (vim_strchr((char *)p_ww, ']') != NULL + } else if (vim_strchr(p_ww, ']') != NULL && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) { // if 'whichwrap' set for cursor in insert mode, may move the // cursor to the next line @@ -5017,13 +4332,13 @@ static void ins_up(bool startcol) undisplay_dollar(); tpos = curwin->w_cursor; - if (cursor_up(1L, TRUE) == OK) { + if (cursor_up(1L, true) == OK) { if (startcol) { coladvance(getvcol_nolist(&Insstart)); } if (old_topline != curwin->w_topline || old_topfill != curwin->w_topfill) { - redraw_later(curwin, VALID); + redraw_later(curwin, UPD_VALID); } start_arrow(&tpos); can_cindent = true; @@ -5065,13 +4380,13 @@ static void ins_down(bool startcol) undisplay_dollar(); tpos = curwin->w_cursor; - if (cursor_down(1L, TRUE) == OK) { + if (cursor_down(1L, true) == OK) { if (startcol) { coladvance(getvcol_nolist(&Insstart)); } if (old_topline != curwin->w_topline || old_topfill != curwin->w_topfill) { - redraw_later(curwin, VALID); + redraw_later(curwin, UPD_VALID); } start_arrow(&tpos); can_cindent = true; @@ -5175,21 +4490,19 @@ static bool ins_tab(void) if (State & VREPLACE_FLAG) { ins_char(' '); } else { - ins_str((char_u *)" "); + ins_str(" "); if (State & REPLACE_FLAG) { // no char replaced replace_push(NUL); } } } - /* - * When 'expandtab' not set: Replace spaces by TABs where possible. - */ + // When 'expandtab' not set: Replace spaces by TABs where possible. if (!curbuf->b_p_et && (tabstop_count(curbuf->b_p_vsts_array) > 0 || get_sts_value() > 0 || (p_sta && ind))) { - char_u *ptr; - char_u *saved_line = NULL; // init for GCC + char *ptr; + char *saved_line = NULL; // init for GCC pos_T pos; pos_T fpos; pos_T *cursor; @@ -5202,7 +4515,7 @@ static bool ins_tab(void) if (State & VREPLACE_FLAG) { pos = curwin->w_cursor; cursor = &pos; - saved_line = vim_strsave(get_cursor_line_ptr()); + saved_line = xstrdup(get_cursor_line_ptr()); ptr = saved_line + pos.col; } else { ptr = get_cursor_pos_ptr(); @@ -5233,11 +4546,15 @@ static bool ins_tab(void) getvcol(curwin, &fpos, &vcol, NULL, NULL); getvcol(curwin, cursor, &want_vcol, NULL, NULL); + char *tab = "\t"; + chartabsize_T cts; + init_chartabsize_arg(&cts, curwin, 0, vcol, tab, tab); + // Use as many TABs as possible. Beware of 'breakindent', 'showbreak' // and 'linebreak' adding extra virtual columns. while (ascii_iswhite(*ptr)) { - i = lbr_chartabsize(NULL, (char_u *)"\t", vcol); - if (vcol + i > want_vcol) { + i = lbr_chartabsize(&cts); + if (cts.cts_vcol + i > want_vcol) { break; } if (*ptr != TAB) { @@ -5252,19 +4569,24 @@ static bool ins_tab(void) } fpos.col++; ptr++; - vcol += i; + cts.cts_vcol += i; } + vcol = cts.cts_vcol; + clear_chartabsize_arg(&cts); if (change_col >= 0) { int repl_off = 0; - char_u *line = ptr; - // Skip over the spaces we need. - while (vcol < want_vcol && *ptr == ' ') { - vcol += lbr_chartabsize(line, ptr, vcol); - ptr++; + init_chartabsize_arg(&cts, curwin, 0, vcol, ptr, ptr); + while (cts.cts_vcol < want_vcol && *cts.cts_ptr == ' ') { + cts.cts_vcol += lbr_chartabsize(&cts); + cts.cts_ptr++; repl_off++; } + ptr = cts.cts_ptr; + vcol = cts.cts_vcol; + clear_chartabsize_arg(&cts); + if (vcol > want_vcol) { // Must have a char with 'showbreak' just before it. ptr--; @@ -5275,7 +4597,7 @@ static bool ins_tab(void) // Delete following spaces. i = cursor->col - fpos.col; if (i > 0) { - STRMOVE(ptr, ptr + i); + STRMOVE(ptr, (char *)ptr + i); // correct replace stack. if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG)) { @@ -5326,11 +4648,9 @@ bool ins_eol(int c) } undisplay_dollar(); - /* - * Strange Vi behaviour: In Replace mode, typing a NL will not delete the - * character under the cursor. Only push a NUL on the replace stack, - * nothing to put back when the NL is deleted. - */ + // Strange Vi behaviour: In Replace mode, typing a NL will not delete the + // character under the cursor. Only push a NUL on the replace stack, + // nothing to put back when the NL is deleted. if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG)) { replace_push(NUL); @@ -5349,7 +4669,7 @@ bool ins_eol(int c) // NL in reverse insert will always start in the end of current line. if (revins_on) { - curwin->w_cursor.col += (colnr_T)STRLEN(get_cursor_pos_ptr()); + curwin->w_cursor.col += (colnr_T)strlen(get_cursor_pos_ptr()); } AppendToRedobuff(NL_STR); @@ -5364,11 +4684,9 @@ bool ins_eol(int c) return i; } -/* - * Handle digraph in insert mode. - * Returns character still to be inserted, or NUL when nothing remaining to be - * done. - */ +// Handle digraph in insert mode. +// Returns character still to be inserted, or NUL when nothing remaining to be +// done. static int ins_digraph(void) { int c; @@ -5400,7 +4718,7 @@ static int ins_digraph(void) if (IS_SPECIAL(c) || mod_mask) { // special key clear_showcmd(); - insert_special(c, TRUE, FALSE); + insert_special(c, true, false); return NUL; } if (c != ESC) { @@ -5437,16 +4755,13 @@ static int ins_digraph(void) return NUL; } -/* - * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line. - * Returns the char to be inserted, or NUL if none found. - */ +// Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line. +// Returns the char to be inserted, or NUL if none found. int ins_copychar(linenr_T lnum) { int c; - int temp; - char_u *ptr, *prev_ptr; - char_u *line; + char *ptr, *prev_ptr; + char *line; if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) { vim_beep(BO_COPY); @@ -5454,28 +4769,32 @@ int ins_copychar(linenr_T lnum) } // try to advance to the cursor column - temp = 0; - line = ptr = ml_get(lnum); - prev_ptr = ptr; + line = ml_get(lnum); + prev_ptr = line; validate_virtcol(); - while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL) { - prev_ptr = ptr; - temp += lbr_chartabsize_adv(line, &ptr, (colnr_T)temp); + + chartabsize_T cts; + init_chartabsize_arg(&cts, curwin, lnum, 0, line, line); + while (cts.cts_vcol < curwin->w_virtcol && *cts.cts_ptr != NUL) { + prev_ptr = cts.cts_ptr; + cts.cts_vcol += lbr_chartabsize_adv(&cts); } - if ((colnr_T)temp > curwin->w_virtcol) { + + if (cts.cts_vcol > curwin->w_virtcol) { ptr = prev_ptr; + } else { + ptr = cts.cts_ptr; } + clear_chartabsize_arg(&cts); - c = utf_ptr2char((char *)ptr); + c = utf_ptr2char(ptr); if (c == NUL) { vim_beep(BO_COPY); } return c; } -/* - * CTRL-Y or CTRL-E typed in Insert mode. - */ +// CTRL-Y or CTRL-E typed in Insert mode. static int ins_ctrl_ey(int tc) { int c = tc; @@ -5486,7 +4805,7 @@ static int ins_ctrl_ey(int tc) } else { scrollup_clamp(); } - redraw_later(curwin, VALID); + redraw_later(curwin, UPD_VALID); } else { c = ins_copychar(curwin->w_cursor.lnum + (c == Ctrl_Y ? -1 : 1)); if (c != NUL) { @@ -5501,7 +4820,7 @@ static int ins_ctrl_ey(int tc) } tw_save = curbuf->b_p_tw; curbuf->b_p_tw = -1; - insert_special(c, TRUE, FALSE); + insert_special(c, true, false); curbuf->b_p_tw = tw_save; revins_chars++; revins_legal++; @@ -5512,31 +4831,25 @@ static int ins_ctrl_ey(int tc) return c; } -/* - * Try to do some very smart auto-indenting. - * Used when inserting a "normal" character. - */ +// Try to do some very smart auto-indenting. +// Used when inserting a "normal" character. static void ins_try_si(int c) { pos_T *pos, old_pos; - char_u *ptr; + char *ptr; int i; bool temp; - /* - * do some very smart indenting when entering '{' or '}' - */ + // do some very smart indenting when entering '{' or '}' if (((did_si || can_si_back) && c == '{') || (can_si && c == '}' && inindent(0))) { // for '}' set indent equal to indent of line containing matching '{' if (c == '}' && (pos = findmatch(NULL, '{')) != NULL) { old_pos = curwin->w_cursor; - /* - * If the matching '{' has a ')' immediately before it (ignoring - * white-space), then line up with the start of the line - * containing the matching '(' if there is one. This handles the - * case where an "if (..\n..) {" statement continues over multiple - * lines -- webb - */ + // If the matching '{' has a ')' immediately before it (ignoring + // white-space), then line up with the start of the line + // containing the matching '(' if there is one. This handles the + // case where an "if (..\n..) {" statement continues over multiple + // lines -- webb ptr = ml_get(pos->lnum); i = pos->col; if (i > 0) { // skip blanks before '{' @@ -5550,7 +4863,7 @@ static void ins_try_si(int c) i = get_indent(); curwin->w_cursor = old_pos; if (State & VREPLACE_FLAG) { - change_indent(INDENT_SET, i, FALSE, NUL, TRUE); + change_indent(INDENT_SET, i, false, NUL, true); } else { (void)set_indent(i, SIN_CHANGED); } @@ -5562,7 +4875,7 @@ static void ins_try_si(int c) old_pos = curwin->w_cursor; i = get_indent(); while (curwin->w_cursor.lnum > 1) { - ptr = (char_u *)skipwhite((char *)ml_get(--(curwin->w_cursor.lnum))); + ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum))); // ignore empty lines and lines starting with '#'. if (*ptr != '#' && *ptr != NUL) { @@ -5575,14 +4888,12 @@ static void ins_try_si(int c) curwin->w_cursor = old_pos; } if (temp) { - shift_line(TRUE, FALSE, 1, TRUE); + shift_line(true, false, 1, true); } } } - /* - * set indent of '#' always to 0 - */ + // set indent of '#' always to 0 if (curwin->w_cursor.col > 0 && can_si && c == '#' && inindent(0)) { // remember current indent for next line old_indent = get_indent(); @@ -5595,10 +4906,8 @@ static void ins_try_si(int c) } } -/* - * Get the value that w_virtcol would have when 'list' is off. - * Unless 'cpo' contains the 'L' flag. - */ +// Get the value that w_virtcol would have when 'list' is off. +// Unless 'cpo' contains the 'L' flag. colnr_T get_nolist_virtcol(void) { // check validity of cursor in current buffer @@ -5613,13 +4922,11 @@ colnr_T get_nolist_virtcol(void) return curwin->w_virtcol; } -/* - * Handle the InsertCharPre autocommand. - * "c" is the character that was typed. - * Return a pointer to allocated memory with the replacement string. - * Return NULL to continue inserting "c". - */ -static char_u *do_insert_char_pre(int c) +// Handle the InsertCharPre autocommand. +// "c" is the character that was typed. +// Return a pointer to allocated memory with the replacement string. +// Return NULL to continue inserting "c". +static char *do_insert_char_pre(int c) { char buf[MB_MAXBYTES + 1]; const int save_State = State; @@ -5634,13 +4941,13 @@ static char_u *do_insert_char_pre(int c) textlock++; set_vim_var_string(VV_CHAR, buf, -1); - char_u *res = NULL; + char *res = NULL; 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((char_u *)get_vim_var_str(VV_CHAR)); + if (strcmp(buf, get_vim_var_str(VV_CHAR)) != 0) { + res = xstrdup(get_vim_var_str(VV_CHAR)); } } @@ -5653,11 +4960,16 @@ static char_u *do_insert_char_pre(int c) return res; } -bool can_cindent_get(void) +bool get_can_cindent(void) { return can_cindent; } +void set_can_cindent(bool val) +{ + can_cindent = val; +} + /// Trigger "event" and take care of fixing undo. int ins_apply_autocmds(event_T event) { |