diff options
Diffstat (limited to 'src')
55 files changed, 2653 insertions, 1809 deletions
diff --git a/src/clint.py b/src/clint.py index c0cedc0e5b..9fd93ce143 100755 --- a/src/clint.py +++ b/src/clint.py @@ -3299,6 +3299,13 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, error(filename, linenum, 'readability/bool', 4, 'Use %s instead of %s.' % (token.lower(), token)) + # Detect MAYBE + match = Search(r'\b(MAYBE)\b', line) + if match: + token = match.group(1) + error(filename, linenum, 'readability/bool', 4, + 'Use kNONE from TriState instead of %s.' % token) + # Detect preincrement/predecrement match = Match(r'^\s*(?:\+\+|--)', line) if match: diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 8ff24b877e..67a4b70c9e 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -31,11 +31,27 @@ # include "api/buffer.c.generated.h" #endif + +/// \defgroup api-buffer +/// +/// Unloaded Buffers:~ +/// +/// Buffers may be unloaded by the |:bunload| command or the buffer's +/// |'bufhidden'| option. When a buffer is unloaded its file contents are freed +/// from memory and vim cannot operate on the buffer lines until it is reloaded +/// (usually by opening the buffer again in a new window). API methods such as +/// |nvim_buf_get_lines()| and |nvim_buf_line_count()| will be affected. +/// +/// You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check +/// whether a buffer is loaded. + + /// Gets the buffer line count /// /// @param buffer Buffer handle /// @param[out] err Error details, if any -/// @return Line count +/// @return Line count, or \`0` if the buffer has been unloaded (see +/// |api-buffer|). Integer nvim_buf_line_count(Buffer buffer, Error *err) FUNC_API_SINCE(1) { @@ -45,6 +61,11 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err) return 0; } + // return sentinel value if the buffer isn't loaded + if (buf->b_ml.ml_mfp == NULL) { + return 0; + } + return buf->b_ml.ml_line_count; } @@ -205,7 +226,8 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer, /// @param end Last line index (exclusive) /// @param strict_indexing Whether out-of-bounds should be an error. /// @param[out] err Error details, if any -/// @return Array of lines +/// @return Array of lines. If the buffer has been unloaded then an empty array +/// will be returned instead. (See |api-buffer|.) ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, Buffer buffer, Integer start, @@ -221,6 +243,11 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, return rv; } + // return sentinel value if the buffer isn't loaded + if (buf->b_ml.ml_mfp == NULL) { + return rv; + } + bool oob = false; start = normalize_index(buf, start, &oob); end = normalize_index(buf, end, &oob); @@ -745,10 +772,27 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err) } } -/// Checks if a buffer is valid +/// Checks if a buffer is valid and loaded. See |api-buffer| for more info +/// about unloaded buffers. +/// +/// @param buffer Buffer handle +/// @return true if the buffer is valid and loaded, false otherwise. +Boolean nvim_buf_is_loaded(Buffer buffer) + FUNC_API_SINCE(5) +{ + Error stub = ERROR_INIT; + buf_T *buf = find_buffer_by_handle(buffer, &stub); + api_clear_error(&stub); + return buf && buf->b_ml.ml_mfp != NULL; +} + +/// Checks if a buffer is valid. +/// +/// @note Even if a buffer is valid it may have been unloaded. See |api-buffer| +/// for more info about unloaded buffers. /// /// @param buffer Buffer handle -/// @return true if the buffer is valid, false otherwise +/// @return true if the buffer is valid, false otherwise. Boolean nvim_buf_is_valid(Buffer buffer) FUNC_API_SINCE(1) { diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index a8d29a3a53..71e04ec0fb 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3220,10 +3220,11 @@ int build_stl_str_hl( // Get the byte value now, in case we need it below. This is more // efficient than making a copy of the line. int byteval; - if (wp->w_cursor.col > (colnr_T)STRLEN(line_ptr)) + if (wp->w_cursor.col > (colnr_T)STRLEN(line_ptr)) { byteval = 0; - else - byteval = (*mb_ptr2char)(line_ptr + wp->w_cursor.col); + } else { + byteval = utf_ptr2char(line_ptr + wp->w_cursor.col); + } int groupdepth = 0; @@ -3603,7 +3604,7 @@ int build_stl_str_hl( // Store the current buffer number as a string variable vim_snprintf((char *)tmp, sizeof(tmp), "%d", curbuf->b_fnum); - set_internal_string_var((char_u *)"actual_curbuf", tmp); + set_internal_string_var((char_u *)"g:actual_curbuf", tmp); buf_T *o_curbuf = curbuf; win_T *o_curwin = curwin; diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 057f99e341..9ff62a80af 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -94,6 +94,7 @@ typedef struct { typedef struct window_S win_T; typedef struct wininfo_S wininfo_T; typedef struct frame_S frame_T; +typedef uint16_t disptick_T; // display tick type // for struct memline (it needs memfile_T) #include "nvim/memline_defs.h" @@ -425,7 +426,7 @@ typedef struct { synstate_T *b_sst_firstfree; int b_sst_freecount; linenr_T b_sst_check_lnum; - uint16_t b_sst_lasttick; /* last display tick */ + disptick_T b_sst_lasttick; // last display tick // for spell checking garray_T b_langp; // list of pointers to slang_T, see spell.c diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 231bff26e8..f1b3be6b46 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1379,7 +1379,7 @@ void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, ptr = ml_get_buf(wp->w_buffer, pos->lnum, false); if (pos->col < (colnr_T)STRLEN(ptr)) { - int c = (*mb_ptr2char)(ptr + pos->col); + int c = utf_ptr2char(ptr + pos->col); if ((c != TAB) && vim_isprintc(c)) { endadd = (colnr_T)(char2cells(c) - 1); if (coladd > endadd) { diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index 177f167d74..0fda941a51 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -476,9 +476,7 @@ bool leftcol_changed(void) int gchar_cursor(void) { - if (has_mbyte) - return (*mb_ptr2char)(get_cursor_pos_ptr()); - return (int)*get_cursor_pos_ptr(); + return utf_ptr2char(get_cursor_pos_ptr()); } /* @@ -507,4 +505,3 @@ char_u *get_cursor_pos_ptr(void) return ml_get_buf(curbuf, curwin->w_cursor.lnum, false) + curwin->w_cursor.col; } - diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 61e0b76558..8699c16351 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -48,9 +48,9 @@ static int diff_flags = DIFF_FILLER; #define LBUFLEN 50 // length of line in diff file -// TRUE when "diff -a" works, FALSE when it doesn't work, MAYBE when not -// checked yet -static int diff_a_works = MAYBE; +// kTrue when "diff -a" works, kFalse when it doesn't work, +// kNone when not checked yet +static TriState diff_a_works = kNone; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -686,9 +686,9 @@ void ex_diffupdate(exarg_T *eap) // there are differences. // May try twice, first with "-a" and then without. int io_error = false; - bool ok = false; + TriState ok = kFalse; for (;;) { - ok = false; + ok = kFalse; FILE *fd = mch_fopen(tmp_orig, "w"); if (fd == NULL) { @@ -722,7 +722,7 @@ void ex_diffupdate(exarg_T *eap) } if (STRNCMP(linebuf, "1c1", 3) == 0) { - ok = TRUE; + ok = kTrue; } } fclose(fd); @@ -739,7 +739,7 @@ void ex_diffupdate(exarg_T *eap) } // If we checked if "-a" works already, break here. - if (diff_a_works != MAYBE) { + if (diff_a_works != kNone) { break; } diff_a_works = ok; @@ -755,7 +755,7 @@ void ex_diffupdate(exarg_T *eap) EMSG(_("E810: Cannot read or write temp files")); } EMSG(_("E97: Cannot create diffs")); - diff_a_works = MAYBE; + diff_a_works = kNone; goto theend; } @@ -830,7 +830,7 @@ static void diff_file(const char *const tmp_orig, const char *const tmp_new, * differences are of no use. Ignore errors, diff returns * non-zero when differences have been found. */ vim_snprintf(cmd, len, "diff %s%s%s%s%s %s", - diff_a_works ? "-a " : "", + diff_a_works == kFalse ? "" : "-a ", "", (diff_flags & DIFF_IWHITE) ? "-b " : "", (diff_flags & DIFF_ICASE) ? "-i " : "", @@ -1486,7 +1486,7 @@ int diff_check(win_T *wp, linenr_T lnum) } // A closed fold never has filler lines. - if (hasFoldingWin(wp, lnum, NULL, NULL, TRUE, NULL)) { + if (hasFoldingWin(wp, lnum, NULL, NULL, true, NULL)) { return 0; } @@ -1793,7 +1793,7 @@ void diff_set_topline(win_T *fromwin, win_T *towin) check_topfill(towin, false); (void)hasFoldingWin(towin, towin->w_topline, &towin->w_topline, - NULL, TRUE, NULL); + NULL, true, NULL); } /// This is called when 'diffopt' is changed. diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index 218a3f0604..c0915224e5 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -1536,7 +1536,7 @@ static int getexactdigraph(int char1, int char2, int meta_char) to = string_convert(&vc, buf, &len); if (to != NULL) { - retval = (*mb_ptr2char)(to); + retval = utf_ptr2char(to); xfree(to); } (void)convert_setup(&vc, NULL, NULL); diff --git a/src/nvim/edit.c b/src/nvim/edit.c index bf80f12bd0..0d99aa8fb2 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -227,7 +227,7 @@ static int last_insert_skip; /* nr of chars in front of previous insert */ static int new_insert_skip; /* nr of chars in front of current insert */ static int did_restart_edit; /* "restart_edit" when calling edit() */ -static int can_cindent; /* may do cindenting on this line */ +static bool can_cindent; // may do cindenting on this line static int old_indent = 0; /* for ^^D command in insert mode */ @@ -240,10 +240,10 @@ static int ins_need_undo; /* call u_save() before inserting a char. Set when edit() is called. after that arrow_used is used. */ -static int did_add_space = FALSE; /* auto_format() added an extra space - under the cursor */ -static int dont_sync_undo = false; // CTRL-G U prevents syncing undo - // for the next left/right cursor +static bool did_add_space = false; // auto_format() added an extra space + // under the cursor +static TriState dont_sync_undo = kFalse; // CTRL-G U prevents syncing undo + // for the next left/right cursor static linenr_T o_lnum = 0; @@ -595,10 +595,10 @@ static int insert_check(VimState *state) s->lastc = s->c; // remember previous char for CTRL-D // After using CTRL-G U the next cursor key will not break undo. - if (dont_sync_undo == MAYBE) { - dont_sync_undo = true; + if (dont_sync_undo == kNone) { + dont_sync_undo = kTrue; } else { - dont_sync_undo = false; + dont_sync_undo = kFalse; } return 1; @@ -997,7 +997,7 @@ static int insert_handle_key(InsertState *s) if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) { ins_s_left(); } else { - ins_left(dont_sync_undo == false); + ins_left(dont_sync_undo == kFalse); } break; @@ -1010,7 +1010,7 @@ static int insert_handle_key(InsertState *s) if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) { ins_s_right(); } else { - ins_right(dont_sync_undo == false); + ins_right(dont_sync_undo == kFalse); } break; @@ -1766,8 +1766,8 @@ change_indent ( /* We only put back the new line up to the cursor */ new_line[curwin->w_cursor.col] = NUL; - /* Put back original line */ - ml_replace(curwin->w_cursor.lnum, orig_line, FALSE); + // Put back original line + ml_replace(curwin->w_cursor.lnum, orig_line, false); curwin->w_cursor.col = orig_col; /* Backspace from cursor to start of line */ @@ -2311,24 +2311,14 @@ static void ins_compl_longest_match(compl_T *match) p = compl_leader; s = match->cp_str; while (*p != NUL) { - if (has_mbyte) { - c1 = mb_ptr2char(p); - c2 = mb_ptr2char(s); - } else { - c1 = *p; - c2 = *s; - } - if (match->cp_icase ? (mb_tolower(c1) != mb_tolower(c2)) - : (c1 != c2)) { + c1 = utf_ptr2char(p); + c2 = utf_ptr2char(s); + + if (match->cp_icase ? (mb_tolower(c1) != mb_tolower(c2)) : (c1 != c2)) { break; } - if (has_mbyte) { - MB_PTR_ADV(p); - MB_PTR_ADV(s); - } else { - ++p; - ++s; - } + MB_PTR_ADV(p); + MB_PTR_ADV(s); } if (*p != NUL) { @@ -4456,7 +4446,7 @@ static int ins_complete(int c, bool enable_pum) int save_w_wrow; int save_w_leftcol; int insert_match; - int save_did_ai = did_ai; + const bool save_did_ai = did_ai; compl_direction = ins_compl_key2dir(c); insert_match = ins_compl_use_match(c); @@ -4464,12 +4454,13 @@ static int ins_complete(int c, bool enable_pum) if (!compl_started) { /* First time we hit ^N or ^P (in a row, I mean) */ - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; - if (stop_arrow() == FAIL) + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; + if (stop_arrow() == FAIL) { return FAIL; + } line = ml_get(curwin->w_cursor.lnum); curs_col = curwin->w_cursor.col; @@ -5269,10 +5260,10 @@ insertchar ( } end_comment_pending = NUL; - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; // If there's any pending input, grab up to INPUT_BUFLEN at once. // This speeds up normal text input considerably. @@ -5367,7 +5358,7 @@ internal_format ( { int cc; int save_char = NUL; - int haveto_redraw = FALSE; + bool haveto_redraw = false; int fo_ins_blank = has_format_option(FO_INS_BLANK); int fo_multibyte = has_format_option(FO_MBYTE_BREAK); int fo_white_par = has_format_option(FO_WHITE_PAR); @@ -5655,13 +5646,13 @@ internal_format ( curwin->w_cursor.col = len; } - haveto_redraw = TRUE; - can_cindent = TRUE; - /* moved the cursor, don't autoindent or cindent now */ - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; + haveto_redraw = true; + can_cindent = true; + // moved the cursor, don't autoindent or cindent now + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; line_breakcheck(); } @@ -5702,8 +5693,8 @@ auto_format ( pos = curwin->w_cursor; old = get_cursor_line_ptr(); - /* may remove added space */ - check_auto_format(FALSE); + // may remove added space + check_auto_format(false); /* Don't format in Insert mode when the cursor is on a trailing blank, the * user might insert normal text next. Also skip formatting when "1" is @@ -5769,12 +5760,13 @@ auto_format ( pnew = vim_strnsave(new, len + 2); pnew[len] = ' '; pnew[len + 1] = NUL; - ml_replace(curwin->w_cursor.lnum, pnew, FALSE); - /* remove the space later */ - did_add_space = TRUE; - } else - /* may remove added space */ - check_auto_format(FALSE); + ml_replace(curwin->w_cursor.lnum, pnew, false); + // remove the space later + did_add_space = true; + } else { + // may remove added space + check_auto_format(false); + } } check_cursor(); @@ -5785,9 +5777,8 @@ auto_format ( * delete it now. The space must be under the cursor, just after the insert * position. */ -static void -check_auto_format ( - int end_insert /* TRUE when ending Insert mode */ +static void check_auto_format( + bool end_insert // true when ending Insert mode ) { int c = ' '; @@ -5795,19 +5786,19 @@ check_auto_format ( if (did_add_space) { cc = gchar_cursor(); - if (!WHITECHAR(cc)) - /* Somehow the space was removed already. */ - did_add_space = FALSE; - else { + if (!WHITECHAR(cc)) { + // Somehow the space was removed already. + did_add_space = false; + } else { if (!end_insert) { inc_cursor(); c = gchar_cursor(); dec_cursor(); } if (c != NUL) { - /* The space is no longer at the end of the line, delete it. */ - del_char(FALSE); - did_add_space = FALSE; + // The space is no longer at the end of the line, delete it. + del_char(false); + did_add_space = false; } } } @@ -6032,8 +6023,8 @@ stop_insert ( } } - /* If a space was inserted for auto-formatting, remove it now. */ - check_auto_format(TRUE); + // If a space was inserted for auto-formatting, remove it now. + check_auto_format(true); /* If we just did an auto-indent, remove the white space from the end * of the line, and put the cursor back. @@ -6052,10 +6043,12 @@ stop_insert ( if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) --curwin->w_cursor.col; cc = gchar_cursor(); - if (!ascii_iswhite(cc)) + if (!ascii_iswhite(cc)) { break; - if (del_char(TRUE) == FAIL) - break; /* should not happen */ + } + if (del_char(true) == FAIL) { + break; // should not happen + } } if (curwin->w_cursor.lnum != tpos.lnum) curwin->w_cursor = tpos; @@ -6080,10 +6073,10 @@ stop_insert ( } } } - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; /* Set '[ and '] to the inserted text. When end_insert_pos is NULL we are * now in a different buffer. */ @@ -6197,12 +6190,10 @@ int oneright(void) /* Adjust for multi-wide char (excluding TAB) */ ptr = get_cursor_pos_ptr(); - coladvance(getviscol() + ((*ptr != TAB && vim_isprintc( - (*mb_ptr2char)(ptr) - )) - ? ptr2cells(ptr) : 1)); - curwin->w_set_curswant = TRUE; - /* Return OK if the cursor moved, FAIL otherwise (at window edge). */ + coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(utf_ptr2char(ptr))) ? + ptr2cells(ptr) : 1)); + curwin->w_set_curswant = true; + // Return OK if the cursor moved, FAIL otherwise (at window edge). return (prevpos.col != curwin->w_cursor.col || prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL; } @@ -6257,10 +6248,10 @@ int oneleft(void) /* Adjust for multi-wide char (not a TAB) */ ptr = get_cursor_pos_ptr(); - if (*ptr != TAB && vim_isprintc( - (*mb_ptr2char)(ptr) - ) && ptr2cells(ptr) > 1) + if (*ptr != TAB && vim_isprintc(utf_ptr2char(ptr)) + && ptr2cells(ptr) > 1) { curwin->w_cursor.coladd = 0; + } } curwin->w_set_curswant = TRUE; @@ -6709,8 +6700,8 @@ static void replace_do_bs(int limit_col) * text aligned. */ curwin->w_cursor.col += ins_len; while (vcol > orig_vcols && gchar_cursor() == ' ') { - del_char(FALSE); - ++orig_vcols; + del_char(false); + orig_vcols++; } curwin->w_cursor.col -= ins_len; } @@ -7174,7 +7165,7 @@ static void ins_ctrl_g(void) case 'U': // Allow one left/right cursor movement with the next char, // without breaking undo. - dont_sync_undo = MAYBE; + dont_sync_undo = kNone; break; /* Unknown CTRL-G command, reserved for future expansion. */ @@ -7452,46 +7443,55 @@ static void ins_shift(int c, int lastc) */ if (c == Ctrl_D && (lastc == '0' || lastc == '^') && curwin->w_cursor.col > 0) { - --curwin->w_cursor.col; - (void)del_char(FALSE); /* delete the '^' or '0' */ - /* In Replace mode, restore the characters that '^' or '0' replaced. */ - if (State & REPLACE_FLAG) + curwin->w_cursor.col--; + (void)del_char(false); // delete the '^' or '0' + // In Replace mode, restore the characters that '^' or '0' replaced. + if (State & REPLACE_FLAG) { replace_pop_ins(); - if (lastc == '^') - old_indent = get_indent(); /* remember curr. indent */ + } + if (lastc == '^') { + old_indent = get_indent(); // remember curr. indent + } change_indent(INDENT_SET, 0, TRUE, 0, TRUE); } else change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE); - if (did_ai && *skipwhite(get_cursor_line_ptr()) != NUL) - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; - can_cindent = FALSE; /* no cindenting after ^D or ^T */ + if (did_ai && *skipwhite(get_cursor_line_ptr()) != NUL) { + did_ai = false; + } + did_si = false; + can_si = false; + can_si_back = false; + can_cindent = false; // no cindenting after ^D or ^T } static void ins_del(void) { - int temp; - - if (stop_arrow() == FAIL) + if (stop_arrow() == FAIL) { return; - if (gchar_cursor() == NUL) { /* delete newline */ - temp = curwin->w_cursor.col; + } + if (gchar_cursor() == NUL) { // delete newline + const int temp = curwin->w_cursor.col; if (!can_bs(BS_EOL) // only if "eol" included || do_join(2, false, true, false, false) == FAIL) { vim_beep(BO_BS); } else { curwin->w_cursor.col = temp; + // Adjust orig_line_count in case more lines have been deleted than + // have been added. That makes sure, that open_line() later + // can access all buffer lines correctly + if (State & VREPLACE_FLAG + && orig_line_count > curbuf->b_ml.ml_line_count) { + orig_line_count = curbuf->b_ml.ml_line_count; + } } } else if (del_char(false) == FAIL) { // delete char under cursor vim_beep(BO_BS); } - did_ai = FALSE; - did_si = FALSE; - can_si = FALSE; - can_si_back = FALSE; + did_ai = false; + did_si = false; + can_si = false; + can_si_back = false; AppendCharToRedobuff(K_DEL); } @@ -7509,8 +7509,9 @@ static void ins_bs_one(colnr_T *vcolp) if (curwin->w_cursor.lnum != Insstart.lnum || curwin->w_cursor.col >= Insstart.col) replace_do_bs(-1); - } else - (void)del_char(FALSE); + } else { + (void)del_char(false); + } } /// Handle Backspace, delete-word and delete-line in Insert mode. @@ -7658,7 +7659,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) State = oldState; } } - did_ai = FALSE; + did_ai = false; } else { /* * Delete character(s) before the cursor. @@ -7774,16 +7775,16 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) else { const bool l_enc_utf8 = enc_utf8; const int l_p_deco = p_deco; - if (l_enc_utf8 && l_p_deco) + if (l_enc_utf8 && l_p_deco) { (void)utfc_ptr2char(get_cursor_pos_ptr(), cpc); - (void)del_char(FALSE); - /* - * If there are combining characters and 'delcombine' is set - * move the cursor back. Don't back up before the base - * character. - */ - if (l_enc_utf8 && l_p_deco && cpc[0] != NUL) + } + (void)del_char(false); + // If there are combining characters and 'delcombine' is set + // move the cursor back. Don't back up before the base + // character. + if (l_enc_utf8 && l_p_deco && cpc[0] != NUL) { inc_cursor(); + } if (revins_chars) { revins_chars--; revins_legal++; @@ -7862,7 +7863,7 @@ static void ins_mouse(int c) curwin = new_curwin; curbuf = curwin->w_buffer; } - can_cindent = TRUE; + can_cindent = true; } /* redraw status lines (in case another window became active) */ @@ -7871,20 +7872,20 @@ static void ins_mouse(int c) static void ins_mousescroll(int dir) { - pos_T tpos; - win_T *old_curwin = curwin; - int did_scroll = FALSE; - - tpos = curwin->w_cursor; + win_T *const old_curwin = curwin; + bool did_scroll = false; + pos_T tpos = curwin->w_cursor; if (mouse_row >= 0 && mouse_col >= 0) { - int row, col; - - row = mouse_row; - col = mouse_col; + int row = mouse_row; + int col = mouse_col; - /* find the window at the pointer coordinates */ - curwin = mouse_find_win(&row, &col); + // find the window at the pointer coordinates + win_T *const wp = mouse_find_win(&row, &col); + if (wp == NULL) { + return; + } + curwin = wp; curbuf = curwin->w_buffer; } if (curwin == old_curwin) @@ -7903,7 +7904,7 @@ static void ins_mousescroll(int dir) } else { mouse_scroll_horiz(dir); } - did_scroll = TRUE; + did_scroll = true; } curwin->w_redr_status = TRUE; @@ -7921,7 +7922,7 @@ static void ins_mousescroll(int dir) if (!equalpos(curwin->w_cursor, tpos)) { start_arrow(&tpos); - can_cindent = TRUE; + can_cindent = true; } } @@ -7954,7 +7955,7 @@ static void ins_left(bool end_change) } else { vim_beep(BO_CRSR); } - dont_sync_undo = false; + dont_sync_undo = kFalse; } static void ins_home(int c) @@ -8039,7 +8040,7 @@ static void ins_right(bool end_change) } else { vim_beep(BO_CRSR); } - dont_sync_undo = false; + dont_sync_undo = kFalse; } static void ins_s_right(void) @@ -8389,8 +8390,8 @@ static bool ins_eol(int c) has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM : 0, old_indent); old_indent = 0; - can_cindent = TRUE; - /* When inserting a line the cursor line must never be in a closed fold. */ + can_cindent = true; + // When inserting a line the cursor line must never be in a closed fold. foldOpenCursor(); return !i; @@ -8494,7 +8495,7 @@ int ins_copychar(linenr_T lnum) if ((colnr_T)temp > curwin->w_virtcol) ptr = prev_ptr; - c = (*mb_ptr2char)(ptr); + c = utf_ptr2char(ptr); if (c == NUL) { vim_beep(BO_COPY); } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 3843245070..9765b04922 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1186,7 +1186,7 @@ int call_vim_function( const char_u *func, int argc, const char_u *const *const argv, - int safe, // use the sandbox + bool safe, // use the sandbox int str_arg_only, // all arguments are strings typval_T *rettv ) @@ -1276,9 +1276,9 @@ varnumber_T call_func_retnr(char_u *func, int argc, /// /// @return [allocated] NULL when calling function fails, allocated string /// otherwise. -char *call_func_retstr(const char *const func, const int argc, - const char_u *const *const argv, - const bool safe) +char *call_func_retstr(const char *const func, int argc, + const char_u *const *argv, + bool safe) FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC { typval_T rettv; @@ -1302,8 +1302,8 @@ char *call_func_retstr(const char *const func, const int argc, /// /// @return [allocated] NULL when calling function fails or return tv is not a /// List, allocated List otherwise. -void *call_func_retlist(char_u *func, int argc, const char_u *const *const argv, - int safe) +void *call_func_retlist(char_u *func, int argc, const char_u *const *argv, + bool safe) { typval_T rettv; @@ -9493,6 +9493,9 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) /* Find the window at the mouse coordinates and compute the * text position. */ win = mouse_find_win(&row, &col); + if (win == NULL) { + return; + } (void)mouse_comp_pos(win, &row, &col, &lnum); for (wp = firstwin; wp != win; wp = wp->w_next) ++winnr; @@ -10207,32 +10210,34 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *oldcurwin; - tabpage_T *tp, *oldtabpage; - dictitem_T *v; + tabpage_T *oldtabpage; bool done = false; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; const char *const varname = tv_get_string_chk(&argvars[1]); - tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); + tabpage_T *const tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); if (tp != NULL && varname != NULL) { // Set tp to be our tabpage, temporarily. Also set the window to the // first window in the tabpage, otherwise the window is not valid. - win_T *window = tp->tp_firstwin == NULL ? firstwin : tp->tp_firstwin; + win_T *const window = tp == curtab || tp->tp_firstwin == NULL + ? firstwin + : tp->tp_firstwin; if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) { // look up the variable // Let gettabvar({nr}, "") return the "t:" dictionary. - v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', - varname, strlen(varname), false); + const dictitem_T *const v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', + varname, strlen(varname), + false); if (v != NULL) { tv_copy(&v->di_tv, rettv); done = true; } } - /* restore previous notion of curwin */ - restore_win(oldcurwin, oldtabpage, TRUE); + // restore previous notion of curwin + restore_win(oldcurwin, oldtabpage, true); } if (!done && argvars[2].v_type != VAR_UNKNOWN) { @@ -15893,7 +15898,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) while (charidx >= 0 && byteidx < len) { if (charidx == 0) { - rettv->vval.v_number = mb_ptr2char((const char_u *)str + byteidx); + rettv->vval.v_number = utf_ptr2char((const char_u *)str + byteidx); break; } charidx--; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 176df58fb9..1420a9aae4 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -716,11 +716,13 @@ void ex_retab(exarg_T *eap) memmove(new_line + start_col + len, ptr + col, (size_t)(old_len - col + 1)); ptr = new_line + start_col; - for (col = 0; col < len; col++) + for (col = 0; col < len; col++) { ptr[col] = (col < num_tabs) ? '\t' : ' '; - ml_replace(lnum, new_line, FALSE); - if (first_line == 0) + } + ml_replace(lnum, new_line, false); + if (first_line == 0) { first_line = lnum; + } last_line = lnum; ptr = new_line; col = start_col + len; @@ -1598,6 +1600,7 @@ void ex_file(exarg_T *eap) // print full file name if :cd used fileinfo(false, false, eap->forceit); } + redraw_tabline = true; } /* @@ -3624,7 +3627,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, // before the cursor. len_change = (int)STRLEN(new_line) - (int)STRLEN(orig_line); curwin->w_cursor.col += len_change; - ml_replace(lnum, new_line, FALSE); + ml_replace(lnum, new_line, false); } search_match_lines = regmatch.endpos[0].lnum @@ -3666,9 +3669,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, msg_col = 0; gotocmdline(TRUE); - /* restore the line */ - if (orig_line != NULL) - ml_replace(lnum, orig_line, FALSE); + // restore the line + if (orig_line != NULL) { + ml_replace(lnum, orig_line, false); + } } need_wait_return = FALSE; /* no hit-return prompt */ @@ -3925,9 +3929,10 @@ skip: prev_matchcol = (colnr_T)STRLEN(sub_firstline) - prev_matchcol; - if (u_savesub(lnum) != OK) + if (u_savesub(lnum) != OK) { break; - ml_replace(lnum, new_start, TRUE); + } + ml_replace(lnum, new_start, true); if (nmatch_tl > 0) { /* @@ -4913,11 +4918,7 @@ void fix_help_buffer(void) { linenr_T lnum; char_u *line; - int in_example = FALSE; - int len; - char_u *fname; - char_u *p; - char_u *rt; + bool in_example = false; // Set filetype to "help". if (STRCMP(curbuf->b_p_ft, "help") != 0) { @@ -4927,9 +4928,9 @@ void fix_help_buffer(void) } if (!syntax_present(curwin)) { - for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) { - line = ml_get_buf(curbuf, lnum, FALSE); - len = (int)STRLEN(line); + for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) { + line = ml_get_buf(curbuf, lnum, false); + const size_t len = STRLEN(line); if (in_example && len > 0 && !ascii_iswhite(line[0])) { /* End of example: non-white or '<' in first column. */ if (line[0] == '<') { @@ -4937,14 +4938,14 @@ void fix_help_buffer(void) line = ml_get_buf(curbuf, lnum, TRUE); line[0] = ' '; } - in_example = FALSE; + in_example = false; } if (!in_example && len > 0) { if (line[len - 1] == '>' && (len == 1 || line[len - 2] == ' ')) { /* blank-out a '>' in the last column (start of example) */ line = ml_get_buf(curbuf, lnum, TRUE); line[len - 1] = ' '; - in_example = TRUE; + in_example = true; } else if (line[len - 1] == '~') { /* blank-out a '~' at the end of line (header marker) */ line = ml_get_buf(curbuf, lnum, TRUE); @@ -4958,7 +4959,7 @@ void fix_help_buffer(void) * In the "help.txt" and "help.abx" file, add the locally added help * files. This uses the very first line in the help file. */ - fname = path_tail(curbuf->b_fname); + char_u *const fname = path_tail(curbuf->b_fname); if (fnamecmp(fname, "help.txt") == 0 || (fnamencmp(fname, "help.", 5) == 0 && ASCII_ISALPHA(fname[5]) @@ -4973,17 +4974,15 @@ void fix_help_buffer(void) /* Go through all directories in 'runtimepath', skipping * $VIMRUNTIME. */ - p = p_rtp; + char_u *p = p_rtp; while (*p != NUL) { copy_option_part(&p, NameBuff, MAXPATHL, ","); - rt = (char_u *)vim_getenv("VIMRUNTIME"); + char_u *const rt = (char_u *)vim_getenv("VIMRUNTIME"); if (rt != NULL && path_full_compare(rt, NameBuff, false) != kEqualFiles) { int fcount; char_u **fnames; - FILE *fd; char_u *s; - int fi; vimconv_T vc; char_u *cp; @@ -5001,29 +5000,24 @@ void fix_help_buffer(void) if (gen_expand_wildcards(1, buff_list, &fcount, &fnames, EW_FILE|EW_SILENT) == OK && fcount > 0) { - int i1; - int i2; - char_u *f1; - char_u *f2; - char_u *t1; - char_u *e1; - char_u *e2; - - /* If foo.abx is found use it instead of foo.txt in - * the same directory. */ - for (i1 = 0; i1 < fcount; ++i1) { - for (i2 = 0; i2 < fcount; ++i2) { - if (i1 == i2) + // If foo.abx is found use it instead of foo.txt in + // the same directory. + for (int i1 = 0; i1 < fcount; i1++) { + for (int i2 = 0; i2 < fcount; i2++) { + if (i1 == i2) { continue; - if (fnames[i1] == NULL || fnames[i2] == NULL) + } + if (fnames[i1] == NULL || fnames[i2] == NULL) { continue; - f1 = fnames[i1]; - f2 = fnames[i2]; - t1 = path_tail(f1); - if (fnamencmp(f1, f2, t1 - f1) != 0) + } + const char_u *const f1 = fnames[i1]; + const char_u *const f2 = fnames[i2]; + const char_u *const t1 = path_tail(f1); + if (fnamencmp(f1, f2, t1 - f1) != 0) { continue; - e1 = vim_strrchr(t1, '.'); - e2 = vim_strrchr(path_tail(f2), '.'); + } + const char_u *const e1 = vim_strrchr(t1, '.'); + const char_u *const e2 = vim_strrchr(path_tail(f2), '.'); if (e1 == NULL || e2 == NULL) { continue; } @@ -5044,10 +5038,12 @@ void fix_help_buffer(void) } } } - for (fi = 0; fi < fcount; ++fi) { - if (fnames[fi] == NULL) + for (int fi = 0; fi < fcount; fi++) { + if (fnames[fi] == NULL) { continue; - fd = mch_fopen((char *)fnames[fi], "r"); + } + + FILE *const fd = mch_fopen((char *)fnames[fi], "r"); if (fd == NULL) { continue; } @@ -5055,9 +5051,9 @@ void fix_help_buffer(void) if (IObuff[0] == '*' && (s = vim_strchr(IObuff + 1, '*')) != NULL) { - int this_utf = MAYBE; - /* Change tag definition to a - * reference and remove <CR>/<NL>. */ + TriState this_utf = kNone; + // Change tag definition to a + // reference and remove <CR>/<NL>. IObuff[0] = '|'; *s = '|'; while (*s != NUL) { @@ -5067,13 +5063,12 @@ void fix_help_buffer(void) * above 127 is found and no * illegal byte sequence is found. */ - if (*s >= 0x80 && this_utf != FALSE) { - int l; - - this_utf = TRUE; - l = utf_ptr2len(s); - if (l == 1) - this_utf = FALSE; + if (*s >= 0x80 && this_utf != kFalse) { + this_utf = kTrue; + const int l = utf_ptr2len(s); + if (l == 1) { + this_utf = kFalse; + } s += l - 1; } ++s; @@ -5082,18 +5077,20 @@ void fix_help_buffer(void) * conversion to the current * 'encoding' may be required. */ vc.vc_type = CONV_NONE; - convert_setup(&vc, (char_u *)( - this_utf == TRUE ? "utf-8" - : "latin1"), p_enc); - if (vc.vc_type == CONV_NONE) - /* No conversion needed. */ + convert_setup( + &vc, + (char_u *)(this_utf == kTrue ? "utf-8" : "latin1"), + p_enc); + if (vc.vc_type == CONV_NONE) { + // No conversion needed. cp = IObuff; - else { - /* Do the conversion. If it fails - * use the unconverted text. */ + } else { + // Do the conversion. If it fails + // use the unconverted text. cp = string_convert(&vc, IObuff, NULL); - if (cp == NULL) + if (cp == NULL) { cp = IObuff; + } } convert_setup(&vc, NULL, NULL); @@ -5138,22 +5135,16 @@ void ex_viusage(exarg_T *eap) /// @param tagname Name of the tags file ("tags" for English, "tags-fr" for /// French) /// @param add_help_tags Whether to add the "help-tags" tag -static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, - bool add_help_tags) +static void helptags_one(char_u *const dir, const char_u *const ext, + const char_u *const tagfname, const bool add_help_tags) { - FILE *fd_tags; - FILE *fd; garray_T ga; int filecount; char_u **files; char_u *p1, *p2; - int fi; char_u *s; - char_u *fname; - int utf8 = MAYBE; - int this_utf8; - int firstline; - int mix = FALSE; /* detected mixed encodings */ + TriState utf8 = kNone; + bool mix = false; // detected mixed encodings // Find all *.txt files. size_t dirlen = STRLCPY(NameBuff, dir, sizeof(NameBuff)); @@ -5186,7 +5177,8 @@ static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, EMSG(_(e_fnametoolong)); return; } - fd_tags = mch_fopen((char *)NameBuff, "w"); + + FILE *const fd_tags = mch_fopen((char *)NameBuff, "w"); if (fd_tags == NULL) { EMSG2(_("E152: Cannot open %s for writing"), NameBuff); FreeWild(filecount, files); @@ -5209,44 +5201,44 @@ static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, /* * Go over all the files and extract the tags. */ - for (fi = 0; fi < filecount && !got_int; ++fi) { - fd = mch_fopen((char *)files[fi], "r"); + for (int fi = 0; fi < filecount && !got_int; fi++) { + FILE *const fd = mch_fopen((char *)files[fi], "r"); if (fd == NULL) { EMSG2(_("E153: Unable to open %s for reading"), files[fi]); continue; } - fname = files[fi] + dirlen + 1; + const char_u *const fname = files[fi] + dirlen + 1; - firstline = TRUE; + bool firstline = true; while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) { if (firstline) { - /* Detect utf-8 file by a non-ASCII char in the first line. */ - this_utf8 = MAYBE; - for (s = IObuff; *s != NUL; ++s) + // Detect utf-8 file by a non-ASCII char in the first line. + TriState this_utf8 = kNone; + for (s = IObuff; *s != NUL; s++) { if (*s >= 0x80) { - int l; - - this_utf8 = TRUE; - l = utf_ptr2len(s); + this_utf8 = kTrue; + const int l = utf_ptr2len(s); if (l == 1) { - /* Illegal UTF-8 byte sequence. */ - this_utf8 = FALSE; + // Illegal UTF-8 byte sequence. + this_utf8 = kFalse; break; } s += l - 1; } - if (this_utf8 == MAYBE) /* only ASCII characters found */ - this_utf8 = FALSE; - if (utf8 == MAYBE) /* first file */ + } + if (this_utf8 == kNone) { // only ASCII characters found + this_utf8 = kFalse; + } + if (utf8 == kNone) { // first file utf8 = this_utf8; - else if (utf8 != this_utf8) { + } else if (utf8 != this_utf8) { EMSG2(_( "E670: Mix of help file encodings within a language: %s"), files[fi]); mix = !got_int; got_int = TRUE; } - firstline = FALSE; + firstline = false; } p1 = vim_strchr(IObuff, '*'); /* find first '*' */ while (p1 != NULL) { @@ -5316,8 +5308,9 @@ static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, } } - if (utf8 == TRUE) + if (utf8 == kTrue) { fprintf(fd_tags, "!_TAG_FILE_ENCODING\tutf-8\t//\n"); + } /* * Write the tags into the file. @@ -5653,7 +5646,7 @@ void ex_sign(exarg_T *eap) // Count cells and check for non-printable chars cells = 0; for (s = arg; s < p; s += (*mb_ptr2len)(s)) { - if (!vim_isprintc((*mb_ptr2char)(s))) { + if (!vim_isprintc(utf_ptr2char(s))) { break; } cells += (*mb_ptr2cells)(s); diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 97369c50d9..3d3d02fd71 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -2899,11 +2899,7 @@ const char * set_one_cmd_context( xp->xp_pattern = skipwhite((const char_u *)arg); p = (const char *)xp->xp_pattern; while (*p != NUL) { - if (has_mbyte) { - c = mb_ptr2char((const char_u *)p); - } else { - c = (uint8_t)(*p); - } + c = utf_ptr2char((const char_u *)p); if (c == '\\' && p[1] != NUL) { p++; } else if (c == '`') { @@ -2921,19 +2917,11 @@ const char * set_one_cmd_context( || ascii_iswhite(c)) { len = 0; /* avoid getting stuck when space is in 'isfname' */ while (*p != NUL) { - if (has_mbyte) { - c = mb_ptr2char((const char_u *)p); - } else { - c = *p; - } + c = utf_ptr2char((const char_u *)p); if (c == '`' || vim_isfilec_or_wc(c)) { break; } - if (has_mbyte) { - len = (size_t)(*mb_ptr2len)((const char_u *)p); - } else { - len = 1; - } + len = (size_t)utfc_ptr2len((const char_u *)p); MB_PTR_ADV(p); } if (in_quote) { @@ -7395,7 +7383,7 @@ static void ex_operators(exarg_T *eap) oa.end.lnum = eap->line2; oa.line_count = eap->line2 - eap->line1 + 1; oa.motion_type = kMTLineWise; - virtual_op = false; + virtual_op = kFalse; if (eap->cmdidx != CMD_yank) { // position cursor for undo setpcmark(); curwin->w_cursor.lnum = eap->line1; @@ -7426,7 +7414,7 @@ static void ex_operators(exarg_T *eap) op_shift(&oa, FALSE, eap->amount); break; } - virtual_op = MAYBE; + virtual_op = kNone; ex_may_print(eap); } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index fd11acff84..1810056a4a 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -201,7 +201,10 @@ static Array cmdline_block = ARRAY_DICT_INIT; /* * Type used by call_user_expand_func */ -typedef void *(*user_expand_func_T)(char_u *, int, char_u **, int); +typedef void *(*user_expand_func_T)(const char_u *, + int, + const char_u * const *, + bool); static histentry_T *(history[HIST_COUNT]) = {NULL, NULL, NULL, NULL, NULL}; static int hisidx[HIST_COUNT] = {-1, -1, -1, -1, -1}; /* lastused entry */ @@ -3324,16 +3327,11 @@ static bool cmdline_paste(int regname, bool literally, bool remcr) /* Locate start of last word in the cmd buffer. */ for (w = ccline.cmdbuff + ccline.cmdpos; w > ccline.cmdbuff; ) { - if (has_mbyte) { - len = (*mb_head_off)(ccline.cmdbuff, w - 1) + 1; - if (!vim_iswordc(mb_ptr2char(w - len))) - break; - w -= len; - } else { - if (!vim_iswordc(w[-1])) - break; - --w; + len = utf_head_off(ccline.cmdbuff, w - 1) + 1; + if (!vim_iswordc(utf_ptr2char(w - len))) { + break; } + w -= len; } len = (int)((ccline.cmdbuff + ccline.cmdpos) - w); if (p_ic ? STRNICMP(w, arg, len) == 0 : STRNCMP(w, arg, len) == 0) @@ -3834,24 +3832,13 @@ ExpandOne ( // Find longest common part if (mode == WILD_LONGEST && xp->xp_numfiles > 0) { - size_t len; - size_t mb_len = 1; - int c0; - int ci; + size_t len = 0; - for (len = 0; xp->xp_files[0][len]; len += mb_len) { - if (has_mbyte) { - mb_len = (* mb_ptr2len)(&xp->xp_files[0][len]); - c0 = (* mb_ptr2char)(&xp->xp_files[0][len]); - } else { - c0 = xp->xp_files[0][len]; - } - for (i = 1; i < xp->xp_numfiles; ++i) { - if (has_mbyte) { - ci =(* mb_ptr2char)(&xp->xp_files[i][len]); - } else { - ci = xp->xp_files[i][len]; - } + for (size_t mb_len; xp->xp_files[0][len]; len += mb_len) { + mb_len = utfc_ptr2len(&xp->xp_files[0][len]); + int c0 = utf_ptr2char(&xp->xp_files[0][len]); + for (i = 1; i < xp->xp_numfiles; i++) { + int ci = utf_ptr2char(&xp->xp_files[i][len]); if (p_fic && (xp->xp_context == EXPAND_DIRECTORIES || xp->xp_context == EXPAND_FILES @@ -5046,7 +5033,10 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func, ccline.cmdprompt = NULL; current_SID = xp->xp_scriptID; - ret = user_expand_func(xp->xp_arg, 3, args, FALSE); + ret = user_expand_func(xp->xp_arg, + 3, + (const char_u * const *)args, + false); ccline = save_ccline; current_SID = save_current_SID; @@ -5062,11 +5052,12 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func, */ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file) { - char_u *e; - garray_T ga; + char_u *e; + garray_T ga; char_u *const retstr = call_user_expand_func( (user_expand_func_T)call_func_retstr, xp, num_file, file); + if (retstr == NULL) { return FAIL; } @@ -6093,7 +6084,7 @@ static int open_cmdwin(void) /* Replace the empty last line with the current command-line and put the * cursor there. */ - ml_replace(curbuf->b_ml.ml_line_count, ccline.cmdbuff, TRUE); + ml_replace(curbuf->b_ml.ml_line_count, ccline.cmdbuff, true); curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; curwin->w_cursor.col = ccline.cmdpos; changed_line_abv_curs(); diff --git a/src/nvim/farsi.c b/src/nvim/farsi.c index 6de84fbf4d..9862c50ab9 100644 --- a/src/nvim/farsi.c +++ b/src/nvim/farsi.c @@ -1081,7 +1081,7 @@ int fkmap(int c) if (gchar_cursor() == _LAM) { chg_l_toXor_X(); - del_char(FALSE); + del_char(false); AppendCharToRedobuff(K_BS); if (!p_ri) { diff --git a/src/nvim/fold.c b/src/nvim/fold.c index ef8750d061..b00c45413a 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -44,14 +44,14 @@ * The info stored in both growarrays is the same: An array of fold_T. */ typedef struct { - linenr_T fd_top; /* first line of fold; for nested fold - * relative to parent */ - linenr_T fd_len; /* number of lines in the fold */ - garray_T fd_nested; /* array of nested folds */ - char fd_flags; /* see below */ - char fd_small; /* TRUE, FALSE or MAYBE: fold smaller than - 'foldminlines'; MAYBE applies to nested - folds too */ + linenr_T fd_top; // first line of fold; for nested fold + // relative to parent + linenr_T fd_len; // number of lines in the fold + garray_T fd_nested; // array of nested folds + char fd_flags; // see below + TriState fd_small; // kTrue, kFalse, or kNone: fold smaller than + // 'foldminlines'; kNone applies to nested + // folds too } fold_T; #define FD_OPEN 0 /* fold is open (nested ones can be closed) */ @@ -76,8 +76,8 @@ typedef struct { this line (copy of "end" of prev. line) */ } fline_T; -/* Flag is set when redrawing is needed. */ -static int fold_changed; +// Flag is set when redrawing is needed. +static bool fold_changed; /* Function used by foldUpdateIEMSRecurse */ typedef void (*LevelGetter)(fline_T *); @@ -147,29 +147,27 @@ int hasAnyFolding(win_T *win) */ bool hasFolding(linenr_T lnum, linenr_T *firstp, linenr_T *lastp) { - return hasFoldingWin(curwin, lnum, firstp, lastp, TRUE, NULL); + return hasFoldingWin(curwin, lnum, firstp, lastp, true, NULL); } /* hasFoldingWin() {{{2 */ bool hasFoldingWin( - win_T *win, - linenr_T lnum, - linenr_T *firstp, - linenr_T *lastp, - int cache, /* when TRUE: use cached values of window */ - foldinfo_T *infop /* where to store fold info */ + win_T *const win, + const linenr_T lnum, + linenr_T *const firstp, + linenr_T *const lastp, + const bool cache, // when true: use cached values of window + foldinfo_T *const infop // where to store fold info ) { - int had_folded = FALSE; + bool had_folded = false; linenr_T first = 0; linenr_T last = 0; linenr_T lnum_rel = lnum; - int x; fold_T *fp; int level = 0; - int use_level = FALSE; - int maybe_small = FALSE; - garray_T *gap; + bool use_level = false; + bool maybe_small = false; int low_level = 0; checkupdate(win); @@ -187,7 +185,7 @@ bool hasFoldingWin( * First look in cached info for displayed lines. This is probably * the fastest, but it can only be used if the entry is still valid. */ - x = find_wl_entry(win, lnum); + const int x = find_wl_entry(win, lnum); if (x >= 0) { first = win->w_lines[x].wl_lnum; last = win->w_lines[x].wl_lastlnum; @@ -199,7 +197,7 @@ bool hasFoldingWin( /* * Recursively search for a fold that contains "lnum". */ - gap = &win->w_folds; + garray_T *gap = &win->w_folds; for (;; ) { if (!foldFind(gap, lnum_rel, &fp)) break; @@ -274,14 +272,11 @@ int foldLevel(linenr_T lnum) return foldLevelWin(curwin, lnum); } -/* lineFolded() {{{2 */ -/* - * Low level function to check if a line is folded. Doesn't use any caching. - * Return TRUE if line is folded. - * Return FALSE if line is not folded. - * Return MAYBE if the line is folded when next to a folded line. - */ -int lineFolded(win_T *win, linenr_T lnum) +// lineFolded() {{{2 +// Low level function to check if a line is folded. Doesn't use any caching. +// Return true if line is folded. +// Return false if line is not folded. +bool lineFolded(win_T *const win, const linenr_T lnum) { return foldedCount(win, lnum, NULL) != 0; } @@ -299,8 +294,9 @@ long foldedCount(win_T *win, linenr_T lnum, foldinfo_T *infop) { linenr_T last; - if (hasFoldingWin(win, lnum, NULL, &last, FALSE, infop)) + if (hasFoldingWin(win, lnum, NULL, &last, false, infop)) { return (long)(last - lnum + 1); + } return 0; } @@ -649,7 +645,7 @@ void foldCreate(linenr_T start, linenr_T end) if (!use_level) curwin->w_fold_manual = true; fp->fd_flags = FD_CLOSED; - fp->fd_small = MAYBE; + fp->fd_small = kNone; /* redraw */ changed_window_setting(); @@ -663,36 +659,31 @@ void foldCreate(linenr_T start, linenr_T end) * When "end" is not 0, delete all folds from "start" to "end". * When "recursive" is TRUE delete recursively. */ -void -deleteFold( - linenr_T start, - linenr_T end, - int recursive, - int had_visual // TRUE when Visual selection used +void deleteFold( + const linenr_T start, + const linenr_T end, + const int recursive, + const bool had_visual // true when Visual selection used ) { - garray_T *gap; fold_T *fp; - garray_T *found_ga; fold_T *found_fp = NULL; linenr_T found_off = 0; - int use_level; - int maybe_small = FALSE; + bool maybe_small = false; int level = 0; linenr_T lnum = start; - linenr_T lnum_off; - int did_one = FALSE; + bool did_one = false; linenr_T first_lnum = MAXLNUM; linenr_T last_lnum = 0; checkupdate(curwin); while (lnum <= end) { - /* Find the deepest fold for "start". */ - gap = &curwin->w_folds; - found_ga = NULL; - lnum_off = 0; - use_level = FALSE; + // Find the deepest fold for "start". + garray_T *gap = &curwin->w_folds; + garray_T *found_ga = NULL; + linenr_T lnum_off = 0; + bool use_level = false; for (;; ) { if (!foldFind(gap, lnum - lnum_off, &fp)) break; @@ -728,7 +719,7 @@ deleteFold( parseMarker(curwin); deleteFoldMarkers(found_fp, recursive, found_off); } - did_one = TRUE; + did_one = true; /* redraw window */ changed_window_setting(); @@ -787,8 +778,8 @@ void foldUpdate(win_T *wp, linenr_T top, linenr_T bot) (void)foldFind(&wp->w_folds, top, &fp); while (fp < (fold_T *)wp->w_folds.ga_data + wp->w_folds.ga_len && fp->fd_top < bot) { - fp->fd_small = MAYBE; - ++fp; + fp->fd_small = kNone; + fp++; } if (foldmethodIsIndent(wp) @@ -831,44 +822,34 @@ void foldUpdateAll(win_T *win) redraw_win_later(win, NOT_VALID); } -/* foldMoveTo() {{{2 */ -/* - * If "updown" is FALSE: Move to the start or end of the fold. - * If "updown" is TRUE: move to fold at the same level. - * If not moved return FAIL. - */ -int -foldMoveTo( - int updown, - int dir, // FORWARD or BACKWARD - long count +// foldMoveTo() {{{2 +// +// If "updown" is false: Move to the start or end of the fold. +// If "updown" is true: move to fold at the same level. +// If not moved return FAIL. +int foldMoveTo( + const bool updown, + const int dir, // FORWARD or BACKWARD + const long count ) { - long n; int retval = FAIL; - linenr_T lnum_off; - linenr_T lnum_found; linenr_T lnum; - int use_level; - int maybe_small; - garray_T *gap; fold_T *fp; - int level; - int last; checkupdate(curwin); - /* Repeat "count" times. */ - for (n = 0; n < count; ++n) { - /* Find nested folds. Stop when a fold is closed. The deepest fold - * that moves the cursor is used. */ - lnum_off = 0; - gap = &curwin->w_folds; - use_level = FALSE; - maybe_small = FALSE; - lnum_found = curwin->w_cursor.lnum; - level = 0; - last = FALSE; + // Repeat "count" times. + for (long n = 0; n < count; n++) { + // Find nested folds. Stop when a fold is closed. The deepest fold + // that moves the cursor is used. + linenr_T lnum_off = 0; + garray_T *gap = &curwin->w_folds; + bool use_level = false; + bool maybe_small = false; + linenr_T lnum_found = curwin->w_cursor.lnum; + int level = 0; + bool last = false; for (;; ) { if (!foldFind(gap, curwin->w_cursor.lnum - lnum_off, &fp)) { if (!updown) @@ -886,14 +867,15 @@ foldMoveTo( } /* don't look for contained folds, they will always move * the cursor too far. */ - last = TRUE; + last = true; } if (!last) { /* Check if this fold is closed. */ if (check_closed(curwin, fp, &use_level, level, - &maybe_small, lnum_off)) - last = TRUE; + &maybe_small, lnum_off)) { + last = true; + } /* "[z" and "]z" stop at closed fold */ if (last && !updown) @@ -1306,25 +1288,21 @@ static void foldOpenNested(fold_T *fpr) } } -/* deleteFoldEntry() {{{2 */ -/* - * Delete fold "idx" from growarray "gap". - * When "recursive" is TRUE also delete all the folds contained in it. - * When "recursive" is FALSE contained folds are moved one level up. - */ -static void deleteFoldEntry(garray_T *gap, int idx, int recursive) +// deleteFoldEntry() {{{2 +// Delete fold "idx" from growarray "gap". +// When "recursive" is true also delete all the folds contained in it. +// When "recursive" is false contained folds are moved one level up. +static void deleteFoldEntry(garray_T *const gap, const int idx, + const bool recursive) { - fold_T *fp; - int i; - fold_T *nfp; - - fp = (fold_T *)gap->ga_data + idx; + fold_T *fp = (fold_T *)gap->ga_data + idx; if (recursive || GA_EMPTY(&fp->fd_nested)) { - /* recursively delete the contained folds */ + // recursively delete the contained folds deleteFoldRecurse(&fp->fd_nested); - --gap->ga_len; - if (idx < gap->ga_len) - memmove(fp, fp + 1, sizeof(fold_T) * (size_t)(gap->ga_len - idx)); + gap->ga_len--; + if (idx < gap->ga_len) { + memmove(fp, fp + 1, sizeof(*fp) * (size_t)(gap->ga_len - idx)); + } } else { /* Move nested folds one level up, to overwrite the fold that is * deleted. */ @@ -1334,22 +1312,24 @@ static void deleteFoldEntry(garray_T *gap, int idx, int recursive) /* Get "fp" again, the array may have been reallocated. */ fp = (fold_T *)gap->ga_data + idx; - /* adjust fd_top and fd_flags for the moved folds */ - nfp = (fold_T *)fp->fd_nested.ga_data; - for (i = 0; i < moved; ++i) { + // adjust fd_top and fd_flags for the moved folds + fold_T *nfp = (fold_T *)fp->fd_nested.ga_data; + for (int i = 0; i < moved; i++) { nfp[i].fd_top += fp->fd_top; if (fp->fd_flags == FD_LEVEL) nfp[i].fd_flags = FD_LEVEL; - if (fp->fd_small == MAYBE) - nfp[i].fd_small = MAYBE; + if (fp->fd_small == kNone) { + nfp[i].fd_small = kNone; + } } - /* move the existing folds down to make room */ - if (idx + 1 < gap->ga_len) + // move the existing folds down to make room + if (idx + 1 < gap->ga_len) { memmove(fp + moved, fp + 1, - sizeof(fold_T) * (size_t)(gap->ga_len - (idx + 1))); - /* move the contained folds one level up */ - memmove(fp, nfp, sizeof(fold_T) * (size_t)moved); + sizeof(*fp) * (size_t)(gap->ga_len - (idx + 1))); + } + // move the contained folds one level up + memmove(fp, nfp, sizeof(*fp) * (size_t)moved); xfree(nfp); gap->ga_len += moved - 1; } @@ -1429,14 +1409,15 @@ static void foldMarkAdjustRecurse(garray_T *gap, linenr_T line1, linenr_T line2, fp->fd_top += amount_after; } else { if (fp->fd_top >= top && last <= line2) { - /* 4. fold completely contained in range */ + // 4. fold completely contained in range if (amount == MAXLNUM) { - /* Deleting lines: delete the fold completely */ - deleteFoldEntry(gap, i, TRUE); - --i; /* adjust index for deletion */ - --fp; - } else + // Deleting lines: delete the fold completely + deleteFoldEntry(gap, i, true); + i--; // adjust index for deletion + fp--; + } else { fp->fd_top += amount; + } } else { if (fp->fd_top < top) { /* 2 or 3: need to correct nested folds too */ @@ -1505,36 +1486,40 @@ static int getDeepestNestingRecurse(garray_T *gap) /* * Check if a fold is closed and update the info needed to check nested folds. */ -static int -check_closed( - win_T *win, - fold_T *fp, - int *use_levelp, // TRUE: outer fold had FD_LEVEL - int level, // folding depth - int *maybe_smallp, // TRUE: outer this had fd_small == MAYBE - linenr_T lnum_off // line number offset for fp->fd_top +static bool check_closed( + win_T *const win, + fold_T *const fp, + bool *const use_levelp, // true: outer fold had FD_LEVEL + const int level, // folding depth + bool *const maybe_smallp, // true: outer this had fd_small == kNone + const linenr_T lnum_off // line number offset for fp->fd_top ) { - int closed = FALSE; + bool closed = false; /* Check if this fold is closed. If the flag is FD_LEVEL this * fold and all folds it contains depend on 'foldlevel'. */ if (*use_levelp || fp->fd_flags == FD_LEVEL) { - *use_levelp = TRUE; - if (level >= win->w_p_fdl) - closed = TRUE; - } else if (fp->fd_flags == FD_CLOSED) - closed = TRUE; - - /* Small fold isn't closed anyway. */ - if (fp->fd_small == MAYBE) - *maybe_smallp = TRUE; + *use_levelp = true; + if (level >= win->w_p_fdl) { + closed = true; + } + } else if (fp->fd_flags == FD_CLOSED) { + closed = true; + } + + // Small fold isn't closed anyway. + if (fp->fd_small == kNone) { + *maybe_smallp = true; + } if (closed) { - if (*maybe_smallp) - fp->fd_small = MAYBE; + if (*maybe_smallp) { + fp->fd_small = kNone; + } checkSmall(win, fp, lnum_off); - if (fp->fd_small == TRUE) - closed = FALSE; + if (fp->fd_small == kTrue) { + closed = false; + } } return closed; } @@ -1545,43 +1530,38 @@ check_closed( */ static void checkSmall( - win_T *wp, - fold_T *fp, - linenr_T lnum_off // offset for fp->fd_top + win_T *const wp, + fold_T *const fp, + const linenr_T lnum_off // offset for fp->fd_top ) { - int count; - int n; - - if (fp->fd_small == MAYBE) { - /* Mark any nested folds to maybe-small */ + if (fp->fd_small == kNone) { + // Mark any nested folds to maybe-small setSmallMaybe(&fp->fd_nested); - if (fp->fd_len > curwin->w_p_fml) - fp->fd_small = FALSE; - else { - count = 0; - for (n = 0; n < fp->fd_len; ++n) { + if (fp->fd_len > curwin->w_p_fml) { + fp->fd_small = kFalse; + } else { + int count = 0; + for (int n = 0; n < fp->fd_len; n++) { count += plines_win_nofold(wp, fp->fd_top + lnum_off + n); if (count > curwin->w_p_fml) { - fp->fd_small = FALSE; + fp->fd_small = kFalse; return; } } - fp->fd_small = TRUE; + fp->fd_small = kTrue; } } } -/* setSmallMaybe() {{{2 */ -/* - * Set small flags in "gap" to MAYBE. - */ +// setSmallMaybe() {{{2 +// Set small flags in "gap" to kNone. static void setSmallMaybe(garray_T *gap) { fold_T *fp = (fold_T *)gap->ga_data; - for (int i = 0; i < gap->ga_len; ++i) { - fp[i].fd_small = MAYBE; + for (int i = 0; i < gap->ga_len; i++) { + fp[i].fd_small = kNone; } } @@ -1707,7 +1687,7 @@ static void foldDelMarker(linenr_T lnum, char_u *marker, size_t markerlen) assert(p >= line); memcpy(newline, line, (size_t)(p - line)); STRCPY(newline + (p - line), p + len); - ml_replace(lnum, newline, FALSE); + ml_replace(lnum, newline, false); } break; } @@ -1783,12 +1763,13 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, if (text != NULL) { /* Replace unprintable characters, if there are any. But * replace a TAB with a space. */ - for (p = text; *p != NUL; ++p) { - int len; + for (p = text; *p != NUL; p++) { + int len = utfc_ptr2len(p); - if (has_mbyte && (len = (*mb_ptr2len)(p)) > 1) { - if (!vim_isprintc((*mb_ptr2char)(p))) + if (len > 1) { + if (!vim_isprintc(utf_ptr2char(p))) { break; + } p += len - 1; } else if (*p == TAB) *p = ' '; @@ -1896,13 +1877,10 @@ void foldtext_cleanup(char_u *str) * Update the folding for window "wp", at least from lines "top" to "bot". * Return TRUE if any folds did change. */ -static void foldUpdateIEMS(win_T *wp, linenr_T top, linenr_T bot) +static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot) { - linenr_T start; - linenr_T end; fline_T fline; void (*getlevel)(fline_T *); - int level; fold_T *fp; /* Avoid problems when being called recursively. */ @@ -1928,12 +1906,13 @@ static void foldUpdateIEMS(win_T *wp, linenr_T top, linenr_T bot) bot += diff_context; } - /* When deleting lines at the end of the buffer "top" can be past the end - * of the buffer. */ - if (top > wp->w_buffer->b_ml.ml_line_count) + // When deleting lines at the end of the buffer "top" can be past the end + // of the buffer. + if (top > wp->w_buffer->b_ml.ml_line_count) { top = wp->w_buffer->b_ml.ml_line_count; + } - fold_changed = FALSE; + fold_changed = false; fline.wp = wp; fline.off = 0; fline.lvl = 0; @@ -1954,8 +1933,8 @@ static void foldUpdateIEMS(win_T *wp, linenr_T top, linenr_T bot) /* Need to get the level of the line above top, it is used if there is * no marker at the top. */ if (top > 1) { - /* Get the fold level at top - 1. */ - level = foldLevelWin(wp, top - 1); + // Get the fold level at top - 1. + const int level = foldLevelWin(wp, top - 1); /* The fold may end just above the top, check for that. */ fline.lnum = top - 1; @@ -2031,11 +2010,12 @@ static void foldUpdateIEMS(win_T *wp, linenr_T top, linenr_T bot) } } - start = fline.lnum; - end = bot; - /* Do at least one line. */ - if (start > end && end < wp->w_buffer->b_ml.ml_line_count) + linenr_T start = fline.lnum; + linenr_T end = bot; + // Do at least one line. + if (start > end && end < wp->w_buffer->b_ml.ml_line_count) { end = start; + } while (!got_int) { /* Always stop at the end of the file ("end" can be past the end of * the file). */ @@ -2126,22 +2106,21 @@ static void foldUpdateIEMS(win_T *wp, linenr_T top, linenr_T bot) * Returns bot, which may have been increased for lines that also need to be * updated as a result of a detected change in the fold. */ -static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, - linenr_T startlnum, fline_T *flp, - LevelGetter getlevel, - linenr_T bot, - char topflags /* containing fold flags */ - ) +static linenr_T foldUpdateIEMSRecurse( + garray_T *const gap, const int level, const linenr_T startlnum, + fline_T *const flp, LevelGetter getlevel, linenr_T bot, + const char topflags // containing fold flags +) { linenr_T ll; fold_T *fp = NULL; fold_T *fp2; int lvl = level; linenr_T startlnum2 = startlnum; - linenr_T firstlnum = flp->lnum; /* first lnum we got */ + const linenr_T firstlnum = flp->lnum; // first lnum we got int i; - int finish = FALSE; - linenr_T linecount = flp->wp->w_buffer->b_ml.ml_line_count - flp->off; + bool finish = false; + const linenr_T linecount = flp->wp->w_buffer->b_ml.ml_line_count - flp->off; int concat; /* @@ -2309,8 +2288,9 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, * found. */ if (getlevel == foldlevelMarker || getlevel == foldlevelExpr - || getlevel == foldlevelSyntax) - finish = TRUE; + || getlevel == foldlevelSyntax) { + finish = true; + } } if (fp->fd_top == startlnum && concat) { i = (int)(fp - (fold_T *)gap->ga_data); @@ -2325,19 +2305,18 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, break; } if (fp->fd_top >= startlnum) { - /* A fold that starts at or after startlnum and stops - * before the new fold must be deleted. Continue - * looking for the next one. */ - deleteFoldEntry(gap, - (int)(fp - (fold_T *)gap->ga_data), TRUE); + // A fold that starts at or after startlnum and stops + // before the new fold must be deleted. Continue + // looking for the next one. + deleteFoldEntry(gap, (int)(fp - (fold_T *)gap->ga_data), true); } else { /* A fold has some lines above startlnum, truncate it * to stop just above startlnum. */ fp->fd_len = startlnum - fp->fd_top; foldMarkAdjustRecurse(&fp->fd_nested, - (linenr_T)fp->fd_len, (linenr_T)MAXLNUM, - (linenr_T)MAXLNUM, 0L); - fold_changed = TRUE; + (linenr_T)fp->fd_len, (linenr_T)MAXLNUM, + (linenr_T)MAXLNUM, 0L); + fold_changed = true; } } else { /* Insert new fold. Careful: ga_data may be NULL and it @@ -2361,14 +2340,15 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, flp->wp->w_fold_manual = true; } else fp->fd_flags = (fp - 1)->fd_flags; - fp->fd_small = MAYBE; - /* If using the "marker", "expr" or "syntax" method, we - * need to continue until the end of the fold is found. */ + fp->fd_small = kNone; + // If using the "marker", "expr" or "syntax" method, we + // need to continue until the end of the fold is found. if (getlevel == foldlevelMarker || getlevel == foldlevelExpr - || getlevel == foldlevelSyntax) - finish = TRUE; - fold_changed = TRUE; + || getlevel == foldlevelSyntax) { + finish = true; + } + fold_changed = true; break; } } @@ -2387,12 +2367,11 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, * Check "fp" for safety. */ if (lvl > level && fp != NULL) { - /* - * There is a nested fold, handle it recursively. - */ - /* At least do one line (can happen when finish is TRUE). */ - if (bot < flp->lnum) + // There is a nested fold, handle it recursively. + // At least do one line (can happen when finish is true). + if (bot < flp->lnum) { bot = flp->lnum; + } /* Line numbers in the nested fold are relative to the start of * this fold. */ @@ -2454,8 +2433,8 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, /* Current fold at least extends until lnum. */ if (fp->fd_len < flp->lnum - fp->fd_top) { fp->fd_len = flp->lnum - fp->fd_top; - fp->fd_small = MAYBE; - fold_changed = TRUE; + fp->fd_small = kNone; + fold_changed = true; } /* Delete contained folds from the end of the last one found until where @@ -2482,8 +2461,9 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, foldSplit(gap, i, flp->lnum, bot); fp = (fold_T *)gap->ga_data + i; } - } else + } else { fp->fd_len = flp->lnum - fp->fd_top; + } fold_changed = true; } } @@ -2502,7 +2482,7 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, (linenr_T)MAXLNUM, (long)(fp2->fd_top - flp->lnum)); fp2->fd_len -= flp->lnum - fp2->fd_top; fp2->fd_top = flp->lnum; - fold_changed = TRUE; + fold_changed = true; } if (lvl >= level) { @@ -2511,8 +2491,8 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, } break; } - fold_changed = TRUE; - deleteFoldEntry(gap, (int)(fp2 - (fold_T *)gap->ga_data), TRUE); + fold_changed = true; + deleteFoldEntry(gap, (int)(fp2 - (fold_T *)gap->ga_data), true); } /* Need to redraw the lines we inspected, which might be further down than @@ -2548,36 +2528,32 @@ static void foldInsert(garray_T *gap, int i) * The caller must first have taken care of any nested folds from "top" to * "bot"! */ -static void foldSplit(garray_T *gap, int i, linenr_T top, linenr_T bot) +static void foldSplit(garray_T *const gap, const int i, const linenr_T top, + const linenr_T bot) { - fold_T *fp; fold_T *fp2; - garray_T *gap1; - garray_T *gap2; - int idx; - int len; /* The fold continues below bot, need to split it. */ foldInsert(gap, i + 1); - fp = (fold_T *)gap->ga_data + i; + fold_T *const fp = (fold_T *)gap->ga_data + i; fp[1].fd_top = bot + 1; // check for wrap around (MAXLNUM, and 32bit) assert(fp[1].fd_top > bot); fp[1].fd_len = fp->fd_len - (fp[1].fd_top - fp->fd_top); fp[1].fd_flags = fp->fd_flags; - fp[1].fd_small = MAYBE; - fp->fd_small = MAYBE; + fp[1].fd_small = kNone; + fp->fd_small = kNone; /* Move nested folds below bot to new fold. There can't be * any between top and bot, they have been removed by the caller. */ - gap1 = &fp->fd_nested; - gap2 = &fp[1].fd_nested; + garray_T *const gap1 = &fp->fd_nested; + garray_T *const gap2 = &fp[1].fd_nested; (void)(foldFind(gap1, bot + 1 - fp->fd_top, &fp2)); - len = (int)((fold_T *)gap1->ga_data + gap1->ga_len - fp2); + const int len = (int)((fold_T *)gap1->ga_data + gap1->ga_len - fp2); if (len > 0) { ga_grow(gap2, len); - for (idx = 0; idx < len; ++idx) { + for (int idx = 0; idx < len; idx++) { ((fold_T *)gap2->ga_data)[idx] = fp2[idx]; ((fold_T *)gap2->ga_data)[idx].fd_top -= fp[1].fd_top - fp->fd_top; @@ -2586,7 +2562,7 @@ static void foldSplit(garray_T *gap, int i, linenr_T top, linenr_T bot) gap1->ga_len -= len; } fp->fd_len = top - fp->fd_top; - fold_changed = TRUE; + fold_changed = true; } /* foldRemove() {{{2 */ @@ -2848,8 +2824,8 @@ static void foldMerge(fold_T *fp1, garray_T *gap, fold_T *fp2) } fp1->fd_len += fp2->fd_len; - deleteFoldEntry(gap, (int)(fp2 - (fold_T *)gap->ga_data), TRUE); - fold_changed = TRUE; + deleteFoldEntry(gap, (int)(fp2 - (fold_T *)gap->ga_data), true); + fold_changed = true; } /* foldlevelIndent() {{{2 */ diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 563608dd1d..b57e1f6558 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -439,7 +439,10 @@ void flush_buffers(int flush_typeahead) ; typebuf.tb_off = MAXMAPLEN; typebuf.tb_len = 0; - } else { /* remove mapped characters at the start only */ + // Reset the flag that text received from a client or from feedkeys() + // was inserted in the typeahead buffer. + typebuf_was_filled = false; + } else { // remove mapped characters at the start only typebuf.tb_off += typebuf.tb_maplen; typebuf.tb_len -= typebuf.tb_maplen; } @@ -698,7 +701,7 @@ static int read_redo(int init, int old_redo) buf[i] = (char_u)c; if (i == n - 1) { // last byte of a character if (n != 1) { - c = (*mb_ptr2char)(buf); + c = utf_ptr2char(buf); } break; } @@ -1077,9 +1080,10 @@ void del_typebuf(int len, int offset) /* Reset the flag that text received from a client or from feedkeys() * was inserted in the typeahead buffer. */ - typebuf_was_filled = FALSE; - if (++typebuf.tb_change_cnt == 0) + typebuf_was_filled = false; + if (++typebuf.tb_change_cnt == 0) { typebuf.tb_change_cnt = 1; + } } /* @@ -1482,7 +1486,7 @@ int vgetc(void) } } no_mapping--; - c = (*mb_ptr2char)(buf); + c = utf_ptr2char(buf); } break; diff --git a/src/nvim/globals.h b/src/nvim/globals.h index d9103f516c..a31f6950e9 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -191,7 +191,7 @@ EXTERN int cmdline_star INIT(= FALSE); /* cmdline is crypted */ EXTERN int exec_from_reg INIT(= FALSE); /* executing register */ -EXTERN int screen_cleared INIT(= FALSE); /* screen has been cleared */ +EXTERN TriState screen_cleared INIT(= kFalse); // screen has been cleared /* * When '$' is included in 'cpoptions' option set: @@ -604,7 +604,7 @@ EXTERN pos_T where_paste_started; * reset when any other editing is done on the line. If an <ESC> or <RETURN> * is received, and did_ai is TRUE, the line is truncated. */ -EXTERN int did_ai INIT(= FALSE); +EXTERN bool did_ai INIT(= false); /* * Column of first char after autoindent. 0 when no autoindent done. Used @@ -632,19 +632,19 @@ EXTERN int did_syncbind INIT(= FALSE); * This flag is set when a smart indent has been performed. When the next typed * character is a '{' the inserted tab will be deleted again. */ -EXTERN int did_si INIT(= FALSE); +EXTERN bool did_si INIT(= false); /* * This flag is set after an auto indent. If the next typed character is a '}' * one indent will be removed. */ -EXTERN int can_si INIT(= FALSE); +EXTERN bool can_si INIT(= false); /* * This flag is set after an "O" command. If the next typed character is a '{' * one indent will be removed. */ -EXTERN int can_si_back INIT(= FALSE); +EXTERN bool can_si_back INIT(= false); // w_cursor before formatting text. EXTERN pos_T saved_cursor INIT(= INIT_POS_T(0, 0, 0)); @@ -942,8 +942,8 @@ EXTERN int no_hlsearch INIT(= FALSE); EXTERN linenr_T printer_page_num; -EXTERN int typebuf_was_filled INIT(= FALSE); /* received text from client - or from feedkeys() */ +EXTERN bool typebuf_was_filled INIT(= false); // received text from client + // or from feedkeys() #ifdef BACKSLASH_IN_FILENAME @@ -952,9 +952,9 @@ EXTERN char psepcN INIT(= '/'); // abnormal path separator character EXTERN char pseps[2] INIT(= { '\\', 0 }); // normal path separator string #endif -/* Set to TRUE when an operator is being executed with virtual editing, MAYBE - * when no operator is being executed, FALSE otherwise. */ -EXTERN int virtual_op INIT(= MAYBE); +// Set to kTrue when an operator is being executed with virtual editing +// kNone when no operator is being executed, kFalse otherwise. +EXTERN TriState virtual_op INIT(= kNone); /* Display tick, incremented for each call to update_screen() */ EXTERN disptick_T display_tick INIT(= 0); diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index e1eb8f0251..a2f48f46aa 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -134,9 +134,9 @@ static int current_syn_id; #define PRCOLOR_BLACK 0 #define PRCOLOR_WHITE 0xffffff -static int curr_italic; -static int curr_bold; -static int curr_underline; +static TriState curr_italic; +static TriState curr_bold; +static TriState curr_underline; static uint32_t curr_bg; static uint32_t curr_fg; static int page_count; @@ -417,7 +417,8 @@ static void prt_set_bg(uint32_t bg) } } -static void prt_set_font(int bold, int italic, int underline) +static void prt_set_font(const TriState bold, const TriState italic, + const TriState underline) { if (curr_bold != bold || curr_italic != italic @@ -429,34 +430,32 @@ static void prt_set_font(int bold, int italic, int underline) } } -/* - * Print the line number in the left margin. - */ -static void prt_line_number(prt_settings_T *psettings, int page_line, linenr_T lnum) +// Print the line number in the left margin. +static void prt_line_number(prt_settings_T *const psettings, + const int page_line, const linenr_T lnum) { - int i; - char_u tbuf[20]; - prt_set_fg(psettings->number.fg_color); prt_set_bg(psettings->number.bg_color); prt_set_font(psettings->number.bold, psettings->number.italic, - psettings->number.underline); - mch_print_start_line(TRUE, page_line); + psettings->number.underline); + mch_print_start_line(true, page_line); - /* Leave two spaces between the number and the text; depends on - * PRINT_NUMBER_WIDTH. */ - sprintf((char *)tbuf, "%6ld", (long)lnum); - for (i = 0; i < 6; i++) + // Leave two spaces between the number and the text; depends on + // PRINT_NUMBER_WIDTH. + char_u tbuf[20]; + snprintf((char *)tbuf, sizeof(tbuf), "%6ld", (long)lnum); + for (int i = 0; i < 6; i++) { (void)mch_print_text_out(&tbuf[i], 1); + } - if (psettings->do_syntax) - /* Set colors for next character. */ + if (psettings->do_syntax) { + // Set colors for next character. current_syn_id = -1; - else { - /* Set colors and font back to normal. */ + } else { + // Set colors and font back to normal. prt_set_fg(PRCOLOR_BLACK); prt_set_bg(PRCOLOR_WHITE); - prt_set_font(FALSE, FALSE, FALSE); + prt_set_font(kFalse, kFalse, kFalse); } } @@ -499,22 +498,20 @@ int prt_get_unit(int idx) return u; } -/* - * Print the page header. - */ -static void prt_header(prt_settings_T *psettings, int pagenum, linenr_T lnum) +// Print the page header. +static void prt_header(prt_settings_T *const psettings, const int pagenum, + const linenr_T lnum) { int width = psettings->chars_per_line; - int page_line; - char_u *tbuf; - char_u *p; - /* Also use the space for the line number. */ - if (prt_use_number()) + // Also use the space for the line number. + if (prt_use_number()) { width += PRINT_NUMBER_WIDTH; + } assert(width >= 0); - tbuf = xmalloc((size_t)width + IOSIZE); + const size_t tbuf_size = (size_t)width + IOSIZE; + char_u *tbuf = xmalloc(tbuf_size); if (*p_header != NUL) { linenr_T tmp_lnum, tmp_topline, tmp_botline; @@ -543,38 +540,40 @@ static void prt_header(prt_settings_T *psettings, int pagenum, linenr_T lnum) curwin->w_cursor.lnum = tmp_lnum; curwin->w_topline = tmp_topline; curwin->w_botline = tmp_botline; - } else - sprintf((char *)tbuf, _("Page %d"), pagenum); + } else { + snprintf((char *)tbuf, tbuf_size, _("Page %d"), pagenum); + } prt_set_fg(PRCOLOR_BLACK); prt_set_bg(PRCOLOR_WHITE); - prt_set_font(TRUE, FALSE, FALSE); + prt_set_font(kTrue, kFalse, kFalse); - /* Use a negative line number to indicate printing in the top margin. */ - page_line = 0 - prt_header_height(); - mch_print_start_line(TRUE, page_line); - for (p = tbuf; *p != NUL; ) { - int l = (*mb_ptr2len)(p); + // Use a negative line number to indicate printing in the top margin. + int page_line = 0 - prt_header_height(); + mch_print_start_line(true, page_line); + for (char_u *p = tbuf; *p != NUL; ) { + const int l = (*mb_ptr2len)(p); assert(l >= 0); if (mch_print_text_out(p, (size_t)l)) { - ++page_line; - if (page_line >= 0) /* out of room in header */ + page_line++; + if (page_line >= 0) { // out of room in header break; - mch_print_start_line(TRUE, page_line); + } + mch_print_start_line(true, page_line); } p += l; } xfree(tbuf); - if (psettings->do_syntax) - /* Set colors for next character. */ + if (psettings->do_syntax) { + // Set colors for next character. current_syn_id = -1; - else { - /* Set colors and font back to normal. */ + } else { + // Set colors and font back to normal. prt_set_fg(PRCOLOR_BLACK); prt_set_bg(PRCOLOR_WHITE); - prt_set_font(FALSE, FALSE, FALSE); + prt_set_font(kFalse, kFalse, kFalse); } } @@ -640,21 +639,19 @@ void ex_hardcopy(exarg_T *eap) else settings.do_syntax = settings.has_color; - /* Set up printing attributes for line numbers */ + // Set up printing attributes for line numbers settings.number.fg_color = PRCOLOR_BLACK; settings.number.bg_color = PRCOLOR_WHITE; - settings.number.bold = FALSE; - settings.number.italic = TRUE; - settings.number.underline = FALSE; - /* - * Syntax highlighting of line numbers. - */ - if (prt_use_number() && settings.do_syntax) { - int id; + settings.number.bold = kFalse; + settings.number.italic = kTrue; + settings.number.underline = kFalse; - id = syn_name2id((char_u *)"LineNr"); - if (id > 0) + // Syntax highlighting of line numbers. + if (prt_use_number() && settings.do_syntax) { + int id = syn_name2id((char_u *)"LineNr"); + if (id > 0) { id = syn_get_final_id(id); + } prt_get_attr(id, &settings.number, settings.modec); } @@ -672,13 +669,13 @@ void ex_hardcopy(exarg_T *eap) /* Set colors and font to normal. */ curr_bg = 0xffffffff; curr_fg = 0xffffffff; - curr_italic = MAYBE; - curr_bold = MAYBE; - curr_underline = MAYBE; + curr_italic = kNone; + curr_bold = kNone; + curr_underline = kNone; prt_set_fg(PRCOLOR_BLACK); prt_set_bg(PRCOLOR_WHITE); - prt_set_font(FALSE, FALSE, FALSE); + prt_set_font(kFalse, kFalse, kFalse); current_syn_id = -1; jobsplit = (printer_opts[OPT_PRINT_JOBSPLIT].present @@ -841,7 +838,7 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T tab_spaces = ppos->lead_spaces; } - mch_print_start_line(0, page_line); + mch_print_start_line(false, page_line); line = ml_get(ppos->file_line); /* @@ -1266,8 +1263,8 @@ static int prt_do_moveto; static int prt_need_font; static int prt_font; static int prt_need_underline; -static int prt_underline; -static int prt_do_underline; +static TriState prt_underline; +static TriState prt_do_underline; static int prt_need_fgcol; static uint32_t prt_fgcol; static int prt_need_bgcol; @@ -2855,7 +2852,7 @@ int mch_print_begin_page(char_u *str) /* We have reset the font attributes, force setting them again. */ curr_bg = 0xffffffff; curr_fg = 0xffffffff; - curr_bold = MAYBE; + curr_bold = kNone; return !prt_file_error; } @@ -2868,11 +2865,12 @@ int mch_print_blank_page(void) static double prt_pos_x = 0; static double prt_pos_y = 0; -void mch_print_start_line(int margin, int page_line) +void mch_print_start_line(const bool margin, const int page_line) { prt_pos_x = prt_left_margin; - if (margin) + if (margin) { prt_pos_x -= prt_number_width; + } prt_pos_y = prt_top_margin - prt_first_line_height - page_line * prt_line_height; @@ -3059,7 +3057,8 @@ int mch_print_text_out(char_u *const textp, size_t len) return need_break; } -void mch_print_set_font(int iBold, int iItalic, int iUnderline) +void mch_print_set_font(const TriState iBold, const TriState iItalic, + const TriState iUnderline) { int font = 0; diff --git a/src/nvim/hardcopy.h b/src/nvim/hardcopy.h index a70b20e6f5..c6a3321b08 100644 --- a/src/nvim/hardcopy.h +++ b/src/nvim/hardcopy.h @@ -2,10 +2,11 @@ #define NVIM_HARDCOPY_H #include <stdint.h> -#include <stdlib.h> // for size_t +#include <stdlib.h> // for size_t -#include "nvim/types.h" // for char_u -#include "nvim/ex_cmds_defs.h" // for exarg_T +#include "nvim/globals.h" // for TriState +#include "nvim/types.h" // for char_u +#include "nvim/ex_cmds_defs.h" // for exarg_T /* * Structure to hold printing color and font attributes. @@ -13,9 +14,9 @@ typedef struct { uint32_t fg_color; uint32_t bg_color; - int bold; - int italic; - int underline; + TriState bold; + TriState italic; + TriState underline; int undercurl; } prt_text_attr_T; diff --git a/src/nvim/macros.h b/src/nvim/macros.h index 7eb58bea2a..b02af723b4 100644 --- a/src/nvim/macros.h +++ b/src/nvim/macros.h @@ -126,7 +126,7 @@ # define MB_CHARLEN(p) mb_charlen(p) # define MB_CHAR2LEN(c) mb_char2len(c) -# define PTR2CHAR(p) mb_ptr2char(p) +# define PTR2CHAR(p) utf_ptr2char(p) # define RESET_BINDING(wp) (wp)->w_p_scb = FALSE; (wp)->w_p_crb = FALSE diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 49e60b5166..b9c91de2a8 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -1470,7 +1470,7 @@ void mark_mb_adjustpos(buf_T *buf, pos_T *lp) // double-wide character. if (lp->coladd == 1 && p[lp->col] != TAB - && vim_isprintc((*mb_ptr2char)(p + lp->col)) + && vim_isprintc(utf_ptr2char(p + lp->col)) && ptr2cells(p + lp->col) > 1) { lp->coladd = 0; } diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 65a1a8246c..7c196831ba 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -674,7 +674,7 @@ int mb_ptr2char_adv(const char_u **const pp) { int c; - c = (*mb_ptr2char)(*pp); + c = utf_ptr2char(*pp); *pp += (*mb_ptr2len)(*pp); return c; } @@ -687,7 +687,7 @@ int mb_cptr2char_adv(const char_u **pp) { int c; - c = (*mb_ptr2char)(*pp); + c = utf_ptr2char(*pp); *pp += utf_ptr2len(*pp); return c; } @@ -1714,7 +1714,7 @@ void mb_check_adjust_col(void *win_) // Reset `coladd` when the cursor would be on the right half of a // double-wide character. if (win->w_cursor.coladd == 1 && p[win->w_cursor.col] != TAB - && vim_isprintc((*mb_ptr2char)(p + win->w_cursor.col)) + && vim_isprintc(utf_ptr2char(p + win->w_cursor.col)) && ptr2cells(p + win->w_cursor.col) > 1) { win->w_cursor.coladd = 0; } diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h index 99aadcacad..a21c08c7fe 100644 --- a/src/nvim/mbyte.h +++ b/src/nvim/mbyte.h @@ -54,7 +54,6 @@ enum { MAX_MCO = 6 }; #define mb_ptr2cells_len utf_ptr2cells_len #define mb_char2cells utf_char2cells #define mb_off2cells utf_off2cells -#define mb_ptr2char utf_ptr2char #define mb_head_off utf_head_off /// Flags for vimconv_T diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 84ceaf0973..9a1e61d40b 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -2378,7 +2378,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, int message) ) set_keep_msg((char_u *)_(no_lines_msg), 0); - i = ml_replace((linenr_T)1, (char_u *)"", TRUE); + i = ml_replace((linenr_T)1, (char_u *)"", true); buf->b_ml.ml_flags |= ML_EMPTY; return i; diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 968962c894..a56aa82f39 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -63,8 +63,8 @@ ex_menu(exarg_T *eap) char_u *p; int i; long pri_tab[MENUDEPTH + 1]; - int enable = MAYBE; /* TRUE for "menu enable", FALSE for "menu - * disable */ + TriState enable = kNone; // kTrue for "menu enable", + // kFalse for "menu disable vimmenu_T menuarg; modes = get_menu_cmd_modes(eap->cmd, eap->forceit, &noremap, &unmenu); @@ -133,10 +133,10 @@ ex_menu(exarg_T *eap) * Check for "disable" or "enable" argument. */ if (STRNCMP(arg, "enable", 6) == 0 && ascii_iswhite(arg[6])) { - enable = TRUE; + enable = kTrue; arg = skipwhite(arg + 6); } else if (STRNCMP(arg, "disable", 7) == 0 && ascii_iswhite(arg[7])) { - enable = FALSE; + enable = kFalse; arg = skipwhite(arg + 7); } @@ -160,22 +160,21 @@ ex_menu(exarg_T *eap) /* * If there is only a menu name, display menus with that name. */ - if (*map_to == NUL && !unmenu && enable == MAYBE) { + if (*map_to == NUL && !unmenu && enable == kNone) { show_menus(menu_path, modes); goto theend; - } else if (*map_to != NUL && (unmenu || enable != MAYBE)) { + } else if (*map_to != NUL && (unmenu || enable != kNone)) { EMSG(_(e_trailing)); goto theend; } - if (enable != MAYBE) { - /* - * Change sensitivity of the menu. - * For the PopUp menu, remove a menu for each mode separately. - * Careful: menu_nable_recurse() changes menu_path. - */ - if (STRCMP(menu_path, "*") == 0) /* meaning: do all menus */ + if (enable != kNone) { + // Change sensitivity of the menu. + // For the PopUp menu, remove a menu for each mode separately. + // Careful: menu_nable_recurse() changes menu_path. + if (STRCMP(menu_path, "*") == 0) { // meaning: do all menus menu_path = (char_u *)""; + } if (menu_is_popup(menu_path)) { for (i = 0; i < MENU_INDEX_TIP; ++i) diff --git a/src/nvim/message.c b/src/nvim/message.c index 46fc9115b4..947cd0735e 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1219,7 +1219,7 @@ int msg_outtrans_len_attr(char_u *msgstr, int len, int attr) // Don't include composing chars after the end. mb_l = utfc_ptr2len_len((char_u *)str, len + 1); if (mb_l > 1) { - c = (*mb_ptr2char)((char_u *)str); + c = utf_ptr2char((char_u *)str); if (vim_isprintc(c)) { // Printable multi-byte char: count the cells. retval += (*mb_ptr2cells)((char_u *)str); @@ -1480,7 +1480,7 @@ void msg_prt_line(char_u *s, int list) col += (*mb_ptr2cells)(s); char buf[MB_MAXBYTES + 1]; if (lcs_nbsp != NUL && list - && (mb_ptr2char(s) == 160 || mb_ptr2char(s) == 0x202f)) { + && (utf_ptr2char(s) == 160 || utf_ptr2char(s) == 0x202f)) { mb_char2bytes(lcs_nbsp, (char_u *)buf); buf[(*mb_ptr2len)((char_u *)buf)] = NUL; } else { @@ -2866,14 +2866,12 @@ do_dialog ( // Make the character lowercase, as chars in "hotkeys" are. c = mb_tolower(c); retval = 1; - for (i = 0; hotkeys[i]; ++i) { - if (has_mbyte) { - if ((*mb_ptr2char)(hotkeys + i) == c) - break; - i += (*mb_ptr2len)(hotkeys + i) - 1; - } else if (hotkeys[i] == c) + for (i = 0; hotkeys[i]; i++) { + if (utf_ptr2char(hotkeys + i) == c) { break; - ++retval; + } + i += utfc_ptr2len(hotkeys + i) - 1; + retval++; } if (hotkeys[i]) break; @@ -2905,25 +2903,13 @@ copy_char ( int lowercase /* make character lower case */ ) { - int len; - int c; - - if (has_mbyte) { - if (lowercase) { - c = mb_tolower((*mb_ptr2char)(from)); - return (*mb_char2bytes)(c, to); - } else { - len = (*mb_ptr2len)(from); - memmove(to, from, (size_t)len); - return len; - } - } else { - if (lowercase) - *to = (char_u)TOLOWER_LOC(*from); - else - *to = *from; - return 1; + if (lowercase) { + int c = mb_tolower(utf_ptr2char(from)); + return utf_char2bytes(c, to); } + int len = utfc_ptr2len(from); + memmove(to, from, (size_t)len); + return len; } #define HAS_HOTKEY_LEN 30 diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 684f486c04..84d8c995a6 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -165,8 +165,8 @@ open_line ( *p_extra = NUL; } - u_clearline(); /* cannot do "U" command when adding lines */ - did_si = FALSE; + u_clearline(); // cannot do "U" command when adding lines + did_si = false; ai_col = 0; /* @@ -286,8 +286,8 @@ open_line ( * checking for "if" and the like. */ if (last_char == '{') { - did_si = TRUE; /* do indent */ - no_si = TRUE; /* don't delete it when '{' typed */ + did_si = true; // do indent + no_si = true; // don't delete it when '{' typed } /* * Look for "if" and the like, use 'cinwords'. @@ -296,7 +296,7 @@ open_line ( */ else if (last_char != ';' && last_char != '}' && cin_is_cinword(ptr)) - did_si = TRUE; + did_si = true; } } else { // dir == BACKWARD // Skip preprocessor directives, unless they are @@ -320,17 +320,19 @@ open_line ( } } p = skipwhite(ptr); - if (*p == '}') /* if line starts with '}': do indent */ - did_si = TRUE; - else /* can delete indent when '{' typed */ - can_si_back = TRUE; + if (*p == '}') { // if line starts with '}': do indent + did_si = true; + } else { // can delete indent when '{' typed + can_si_back = true; + } } curwin->w_cursor = old_cursor; } - if (do_si) - can_si = TRUE; + if (do_si) { + can_si = true; + } - did_ai = TRUE; + did_ai = true; } /* @@ -665,7 +667,7 @@ open_line ( } } - did_si = can_si = FALSE; + did_si = can_si = false; } else if (comment_end != NULL) { // We have finished a comment, so we don't use the leader. // If this was a C-comment and 'ai' or 'si' is set do a normal @@ -699,17 +701,17 @@ open_line ( replace_push(NUL); /* end of extra blanks */ if (curbuf->b_p_ai || (flags & OPENLINE_DELSPACES)) { while ((*p_extra == ' ' || *p_extra == '\t') - && (!enc_utf8 - || !utf_iscomposing(utf_ptr2char(p_extra + 1))) - ) { - if (REPLACE_NORMAL(State)) + && !utf_iscomposing(utf_ptr2char(p_extra + 1))) { + if (REPLACE_NORMAL(State)) { replace_push(*p_extra); - ++p_extra; - ++less_cols_off; + } + p_extra++; + less_cols_off++; } } - if (*p_extra != NUL) - did_ai = FALSE; /* append some text, don't truncate now */ + if (*p_extra != NUL) { + did_ai = false; // append some text, don't truncate now + } /* columns for marks adjusted for removed columns */ less_cols = (int)(p_extra - saved_line); @@ -736,7 +738,7 @@ open_line ( } STRCAT(leader, p_extra); p_extra = leader; - did_ai = TRUE; /* So truncating blanks works with comments */ + did_ai = true; // So truncating blanks works with comments less_cols -= lead_len; } else end_comment_pending = NUL; /* turns out there was no leader */ @@ -769,7 +771,7 @@ open_line ( (void)u_save_cursor(); /* errors are ignored! */ vr_lines_changed++; } - ml_replace(curwin->w_cursor.lnum, p_extra, TRUE); + ml_replace(curwin->w_cursor.lnum, p_extra, true); changed_bytes(curwin->w_cursor.lnum, 0); curwin->w_cursor.lnum--; did_append = FALSE; @@ -812,8 +814,9 @@ open_line ( } } newcol += curwin->w_cursor.col; - if (no_si) - did_si = FALSE; + if (no_si) { + did_si = false; + } } /* @@ -828,12 +831,13 @@ open_line ( if (dir == FORWARD) { if (trunc_line || (State & INSERT)) { - /* truncate current line at cursor */ + // truncate current line at cursor saved_line[curwin->w_cursor.col] = NUL; - /* Remove trailing white space, unless OPENLINE_KEEPTRAIL used. */ - if (trunc_line && !(flags & OPENLINE_KEEPTRAIL)) + // Remove trailing white space, unless OPENLINE_KEEPTRAIL used. + if (trunc_line && !(flags & OPENLINE_KEEPTRAIL)) { truncate_spaces(saved_line); - ml_replace(curwin->w_cursor.lnum, saved_line, FALSE); + } + ml_replace(curwin->w_cursor.lnum, saved_line, false); saved_line = NULL; if (did_append) { changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col, @@ -909,8 +913,8 @@ open_line ( /* Put new line in p_extra */ p_extra = vim_strsave(get_cursor_line_ptr()); - /* Put back original line */ - ml_replace(curwin->w_cursor.lnum, next_line, FALSE); + // Put back original line + ml_replace(curwin->w_cursor.lnum, next_line, false); /* Insert new stuff into line again */ curwin->w_cursor.col = 0; @@ -1203,16 +1207,15 @@ int get_last_leader_offset(char_u *line, char_u **flags) /* * Return the number of window lines occupied by buffer line "lnum". */ -int plines(linenr_T lnum) +int plines(const linenr_T lnum) { - return plines_win(curwin, lnum, TRUE); + return plines_win(curwin, lnum, true); } -int -plines_win ( - win_T *wp, - linenr_T lnum, - int winheight /* when TRUE limit to window height */ +int plines_win( + win_T *const wp, + const linenr_T lnum, + const bool winheight // when true limit to window height ) { /* Check for filler lines above this buffer line. When folded the result @@ -1220,34 +1223,34 @@ plines_win ( return plines_win_nofill(wp, lnum, winheight) + diff_check_fill(wp, lnum); } -int plines_nofill(linenr_T lnum) +int plines_nofill(const linenr_T lnum) { - return plines_win_nofill(curwin, lnum, TRUE); + return plines_win_nofill(curwin, lnum, true); } -int -plines_win_nofill ( - win_T *wp, - linenr_T lnum, - int winheight /* when TRUE limit to window height */ +int plines_win_nofill( + win_T *const wp, + const linenr_T lnum, + const bool winheight // when true limit to window height ) { - int lines; - - if (!wp->w_p_wrap) + if (!wp->w_p_wrap) { return 1; + } - if (wp->w_width == 0) + if (wp->w_width == 0) { return 1; + } - /* A folded lines is handled just like an empty line. */ - /* NOTE: Caller must handle lines that are MAYBE folded. */ - if (lineFolded(wp, lnum) == TRUE) + // A folded lines is handled just like an empty line. + if (lineFolded(wp, lnum)) { return 1; + } - lines = plines_win_nofold(wp, lnum); - if (winheight > 0 && lines > wp->w_height) + const int lines = plines_win_nofold(wp, lnum); + if (winheight && lines > wp->w_height) { return wp->w_height; + } return lines; } @@ -1347,11 +1350,12 @@ int plines_m_win(win_T *wp, linenr_T first, linenr_T last) ++count; /* count 1 for "+-- folded" line */ first += x; } else { - if (first == wp->w_topline) - count += plines_win_nofill(wp, first, TRUE) + wp->w_topfill; - else - count += plines_win(wp, first, TRUE); - ++first; + if (first == wp->w_topline) { + count += plines_win_nofill(wp, first, true) + wp->w_topfill; + } else { + count += plines_win(wp, first, true); + } + first++; } } return count; @@ -1494,8 +1498,8 @@ void ins_char_bytes(char_u *buf, size_t charlen) p[i] = ' '; } - /* Replace the line in the buffer. */ - ml_replace(lnum, newp, FALSE); + // Replace the line in the buffer. + ml_replace(lnum, newp, false); // mark the buffer as changed and prepare for displaying changed_bytes(lnum, (colnr_T)col); @@ -1508,7 +1512,7 @@ void ins_char_bytes(char_u *buf, size_t charlen) && msg_silent == 0 && !ins_compl_active() ) { - showmatch(mb_ptr2char(buf)); + showmatch(utf_ptr2char(buf)); } if (!p_ri || (State & REPLACE_FLAG)) { @@ -1545,19 +1549,17 @@ void ins_str(char_u *s) memmove(newp, oldp, (size_t)col); memmove(newp + col, s, (size_t)newlen); memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1)); - ml_replace(lnum, newp, FALSE); + ml_replace(lnum, newp, false); changed_bytes(lnum, col); curwin->w_cursor.col += newlen; } -/* - * Delete one character under the cursor. - * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line. - * Caller must have prepared for undo. - * - * return FAIL for failure, OK otherwise - */ -int del_char(int fixpos) +// Delete one character under the cursor. +// If "fixpos" is true, don't leave the cursor on the NUL after the line. +// Caller must have prepared for undo. +// +// return FAIL for failure, OK otherwise +int del_char(bool fixpos) { if (has_mbyte) { /* Make sure the cursor is at the start of a character. */ @@ -1663,8 +1665,9 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine) memmove(newp, oldp, (size_t)col); } memmove(newp + col, oldp + col + count, (size_t)movelen); - if (!was_alloced) - ml_replace(lnum, newp, FALSE); + if (!was_alloced) { + ml_replace(lnum, newp, false); + } /* mark the buffer as changed and prepare for displaying */ changed_bytes(lnum, curwin->w_cursor.col); @@ -1745,11 +1748,7 @@ del_lines ( int gchar_pos(pos_T *pos) { - char_u *ptr = ml_get_pos(pos); - - if (has_mbyte) - return (*mb_ptr2char)(ptr); - return (int)*ptr; + return utf_ptr2char(ml_get_pos(pos)); } /* @@ -2385,12 +2384,12 @@ int get_keystroke(void) } break; } - if (has_mbyte) { - if (MB_BYTE2LEN(n) > len) - continue; /* more bytes to get */ - buf[len >= buflen ? buflen - 1 : len] = NUL; - n = (*mb_ptr2char)(buf); + if (MB_BYTE2LEN(n) > len) { + // more bytes to get. + continue; } + buf[len >= buflen ? buflen - 1 : len] = NUL; + n = utf_ptr2char(buf); #ifdef UNIX if (n == intr_char) n = ESC; @@ -2479,7 +2478,7 @@ int prompt_for_number(int *mouse_used) save_cmdline_row = cmdline_row; cmdline_row = 0; save_State = State; - State = CMDLINE; + State = ASKMORE; // prevents a screen update when using a timer i = get_number(TRUE, mouse_used); if (KeyTyped) { @@ -2836,4 +2835,3 @@ int goto_im(void) { return p_im && stuff_empty() && typebuf_typed(); } - diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 8c615f52e7..3c792326a4 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -125,6 +125,9 @@ retnomove: // find the window where the row is in wp = mouse_find_win(&row, &col); + if (wp == NULL) { + return IN_UNKNOWN; + } dragwin = NULL; // winpos and height may change in win_enter()! if (row >= wp->w_height) { // In (or below) status line @@ -427,6 +430,7 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump) // Find the window at screen position "*rowp" and "*colp". The positions are // updated to become relative to the top-left of the window. +// Returns NULL when something is wrong. win_T *mouse_find_win(int *rowp, int *colp) { frame_T *fp; @@ -450,7 +454,14 @@ win_T *mouse_find_win(int *rowp, int *colp) } } } - return fp->fr_win; + // When using a timer that closes a window the window might not actually + // exist. + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp == fp->fr_win) { + return wp; + } + } + return NULL; } /* diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 570368991a..225fe4aa9a 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -2015,7 +2015,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) default: clearopbeep(oap); } - virtual_op = MAYBE; + virtual_op = kNone; if (!gui_yank) { /* * if 'sol' not set, go back to old column for some commands @@ -2090,7 +2090,7 @@ static void op_colon(oparg_T *oap) */ static void op_function(oparg_T *oap) { - int save_virtual_op = virtual_op; + const TriState save_virtual_op = virtual_op; if (*p_opfunc == NUL) EMSG(_("E774: 'operatorfunc' is empty")); @@ -2113,7 +2113,7 @@ static void op_function(oparg_T *oap) // Reset virtual_op so that 'virtualedit' can be changed in the // function. - virtual_op = MAYBE; + virtual_op = kNone; (void)call_func_retnr(p_opfunc, 1, argv, false); @@ -3994,8 +3994,12 @@ static void nv_mousescroll(cmdarg_T *cap) row = mouse_row; col = mouse_col; - /* find the window at the pointer coordinates */ - curwin = mouse_find_win(&row, &col); + // find the window at the pointer coordinates + win_T *const wp = mouse_find_win(&row, &col); + if (wp == NULL) { + return; + } + curwin = wp; curbuf = curwin->w_buffer; } diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 67171cb27e..7defde731a 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -310,30 +310,32 @@ void shift_line( */ static void shift_block(oparg_T *oap, int amount) { - int left = (oap->op_type == OP_LSHIFT); - int oldstate = State; - int total; - char_u *newp, *oldp; - int oldcol = curwin->w_cursor.col; - int p_sw = get_sw_value(curbuf); - int p_ts = (int)curbuf->b_p_ts; + const bool left = (oap->op_type == OP_LSHIFT); + const int oldstate = State; + char_u *newp; + const int oldcol = curwin->w_cursor.col; + const int p_sw = get_sw_value(curbuf); + const int p_ts = (int)curbuf->b_p_ts; struct block_def bd; int incr; - colnr_T ws_vcol; int i = 0, j = 0; - int len; - int old_p_ri = p_ri; + const int old_p_ri = p_ri; p_ri = 0; /* don't want revins in indent */ - State = INSERT; /* don't want REPLACE for State */ - block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE); - if (bd.is_short) + State = INSERT; // don't want REPLACE for State + block_prep(oap, &bd, curwin->w_cursor.lnum, true); + if (bd.is_short) { return; + } + + // total is number of screen columns to be inserted/removed + int total = (int)((unsigned)amount * (unsigned)p_sw); + if ((total / p_sw) != amount) { + return; // multiplication overflow + } - /* total is number of screen columns to be inserted/removed */ - total = amount * p_sw; - oldp = get_cursor_line_ptr(); + char_u *const oldp = get_cursor_line_ptr(); if (!left) { /* @@ -342,8 +344,8 @@ static void shift_block(oparg_T *oap, int amount) * 3. Divvy into TABs & spp * 4. Construct new string */ - total += bd.pre_whitesp; /* all virtual WS up to & incl a split TAB */ - ws_vcol = bd.start_vcol - bd.pre_whitesp; + total += bd.pre_whitesp; // all virtual WS up to & incl a split TAB + colnr_T ws_vcol = bd.start_vcol - bd.pre_whitesp; if (bd.startspaces) { if (has_mbyte) { if ((*mb_ptr2len)(bd.textstart) == 1) { @@ -372,8 +374,8 @@ static void shift_block(oparg_T *oap, int amount) j = total; /* if we're splitting a TAB, allow for it */ bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0); - len = (int)STRLEN(bd.textstart) + 1; - newp = (char_u *) xmalloc((size_t)(bd.textcol + i + j + len)); + const int len = (int)STRLEN(bd.textstart) + 1; + newp = (char_u *)xmalloc((size_t)(bd.textcol + i + j + len)); memset(newp, NUL, (size_t)(bd.textcol + i + j + len)); memmove(newp, oldp, (size_t)bd.textcol); memset(newp + bd.textcol, TAB, (size_t)i); @@ -390,10 +392,7 @@ static void shift_block(oparg_T *oap, int amount) size_t fill; // nr of spaces that replace a TAB size_t new_line_len; // the length of the line after the // block shift - colnr_T block_space_width; - colnr_T shift_amount; char_u *non_white = bd.textstart; - colnr_T non_white_col; /* * Firstly, let's find the first non-whitespace character that is @@ -410,19 +409,20 @@ static void shift_block(oparg_T *oap, int amount) MB_PTR_ADV(non_white); } - /* The character's column is in "bd.start_vcol". */ - non_white_col = bd.start_vcol; + // The character's column is in "bd.start_vcol". + colnr_T non_white_col = bd.start_vcol; while (ascii_iswhite(*non_white)) { incr = lbr_chartabsize_adv(bd.textstart, &non_white, non_white_col); non_white_col += incr; } - block_space_width = non_white_col - oap->start_vcol; - /* We will shift by "total" or "block_space_width", whichever is less. - */ - shift_amount = (block_space_width < total ? block_space_width : total); + const colnr_T block_space_width = non_white_col - oap->start_vcol; + // We will shift by "total" or "block_space_width", whichever is less. + const colnr_T shift_amount = block_space_width < total + ? block_space_width + : total; // The column to which we will shift the text. destination_col = non_white_col - shift_amount; @@ -454,7 +454,7 @@ static void shift_block(oparg_T *oap, int amount) fill = (size_t)(destination_col - verbatim_copy_width); assert(verbatim_copy_end - oldp >= 0); - size_t verbatim_diff = (size_t)(verbatim_copy_end - oldp); + const size_t verbatim_diff = (size_t)(verbatim_copy_end - oldp); // The replacement line will consist of: // - the beginning of the original line up to "verbatim_copy_end", // - "fill" number of spaces, @@ -466,8 +466,8 @@ static void shift_block(oparg_T *oap, int amount) memset(newp + verbatim_diff, ' ', fill); STRMOVE(newp + verbatim_diff + fill, non_white); } - /* replace the line */ - ml_replace(curwin->w_cursor.lnum, newp, FALSE); + // replace the line + ml_replace(curwin->w_cursor.lnum, newp, false); changed_bytes(curwin->w_cursor.lnum, (colnr_T)bd.textcol); State = oldstate; curwin->w_cursor.col = oldcol; @@ -561,7 +561,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def offset += count; STRMOVE(newp + offset, oldp); - ml_replace(lnum, newp, FALSE); + ml_replace(lnum, newp, false); if (lnum == oap->end.lnum) { /* Set "']" mark to the end of the block instead of the end of @@ -1427,10 +1427,11 @@ int op_delete(oparg_T *oap) return FAIL; } - for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; ++lnum) { - block_prep(oap, &bd, lnum, TRUE); - if (bd.textlen == 0) /* nothing to delete */ + for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; lnum++) { + block_prep(oap, &bd, lnum, true); + if (bd.textlen == 0) { // nothing to delete continue; + } /* Adjust cursor position for tab replaced by spaces and 'lbr'. */ if (lnum == curwin->w_cursor.lnum) { @@ -1473,9 +1474,9 @@ int op_delete(oparg_T *oap) } if (u_save_cursor() == FAIL) return FAIL; - if (curbuf->b_p_ai) { /* don't delete indent */ - beginline(BL_WHITE); /* cursor on first non-white */ - did_ai = TRUE; /* delete the indent when ESC hit */ + if (curbuf->b_p_ai) { // don't delete indent + beginline(BL_WHITE); // cursor on first non-white + did_ai = true; // delete the indent when ESC hit ai_col = curwin->w_cursor.col; } else beginline(0); /* cursor in column 0 */ @@ -1656,11 +1657,12 @@ int op_replace(oparg_T *oap, int c) */ if (oap->motion_type == kMTBlockWise) { bd.is_MAX = (curwin->w_curswant == MAXCOL); - for (; curwin->w_cursor.lnum <= oap->end.lnum; ++curwin->w_cursor.lnum) { - curwin->w_cursor.col = 0; /* make sure cursor position is valid */ - block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE); - if (bd.textlen == 0 && (!virtual_op || bd.is_MAX)) - continue; /* nothing to replace */ + for (; curwin->w_cursor.lnum <= oap->end.lnum; curwin->w_cursor.lnum++) { + curwin->w_cursor.col = 0; // make sure cursor position is valid + block_prep(oap, &bd, curwin->w_cursor.lnum, true); + if (bd.textlen == 0 && (!virtual_op || bd.is_MAX)) { + continue; // nothing to replace + } /* n == number of extra chars required * If we split a TAB, it may be replaced by several characters. @@ -1747,8 +1749,8 @@ int op_replace(oparg_T *oap, int c) after_p = (char_u *)xmalloc(after_p_len); memmove(after_p, oldp, after_p_len); } - /* replace the line */ - ml_replace(curwin->w_cursor.lnum, newp, FALSE); + // replace the line + ml_replace(curwin->w_cursor.lnum, newp, false); if (after_p != NULL) { ml_append(curwin->w_cursor.lnum++, after_p, (int)after_p_len, false); appended_lines_mark(curwin->w_cursor.lnum, 1L); @@ -1852,7 +1854,7 @@ void op_tilde(oparg_T *oap) for (; pos.lnum <= oap->end.lnum; pos.lnum++) { int one_change; - block_prep(oap, &bd, pos.lnum, FALSE); + block_prep(oap, &bd, pos.lnum, false); pos.col = bd.textcol; one_change = swapchars(oap->op_type, &pos, bd.textlen); did_change |= one_change; @@ -1956,7 +1958,7 @@ int swapchar(int op_type, pos_T *pos) /* Special handling of German sharp s: change to "SS". */ curwin->w_cursor = *pos; - del_char(FALSE); + del_char(false); ins_char('S'); ins_char('S'); curwin->w_cursor = sp; @@ -2030,8 +2032,8 @@ void op_insert(oparg_T *oap, long count1) --curwin->w_cursor.col; ve_flags = old_ve_flags; } - /* Get the info about the block before entering the text */ - block_prep(oap, &bd, oap->start.lnum, TRUE); + // Get the info about the block before entering the text + block_prep(oap, &bd, oap->start.lnum, true); firstline = ml_get(oap->start.lnum) + bd.textcol; if (oap->op_type == OP_APPEND) firstline += bd.textlen; @@ -2119,7 +2121,7 @@ void op_insert(oparg_T *oap, long count1) * tabs. Get the starting column again and correct the length. * Don't do this when "$" used, end-of-line will have changed. */ - block_prep(oap, &bd2, oap->start.lnum, TRUE); + block_prep(oap, &bd2, oap->start.lnum, true); if (!bd.is_MAX || bd2.textlen < bd.textlen) { if (oap->op_type == OP_APPEND) { pre_textlen += bd2.textlen - bd.textlen; @@ -2178,7 +2180,7 @@ int op_change(oparg_T *oap) if (!p_paste && curbuf->b_p_si && !curbuf->b_p_cin ) - can_si = TRUE; /* It's like opening a new line, do si */ + can_si = true; // It's like opening a new line, do si } /* First delete the text in the region. In an empty buffer only need to @@ -2239,7 +2241,7 @@ int op_change(oparg_T *oap) STRLCPY(ins_text, firstline + bd.textcol, ins_len + 1); for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum; linenr++) { - block_prep(oap, &bd, linenr, TRUE); + block_prep(oap, &bd, linenr, true); if (!bd.is_short || virtual_op) { pos_T vpos; @@ -2263,7 +2265,7 @@ int op_change(oparg_T *oap) offset += ins_len; oldp += bd.textcol; STRMOVE(newp + offset, oldp); - ml_replace(linenr, newp, FALSE); + ml_replace(linenr, newp, false); } } check_cursor(); @@ -3117,10 +3119,10 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) ptr += yanklen; } STRMOVE(ptr, oldp + col); - ml_replace(lnum, newp, FALSE); - /* Place cursor on last putted char. */ + ml_replace(lnum, newp, false); + // Place cursor on last putted char. if (lnum == curwin->w_cursor.lnum) { - /* make sure curwin->w_virtcol is updated */ + // make sure curwin->w_virtcol is updated changed_cline_bef_curs(); curwin->w_cursor.col += (colnr_T)(totlen - 1); } @@ -3164,7 +3166,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) memmove(newp, oldp, (size_t)col); /* append to first line */ memmove(newp + col, y_array[0], (size_t)(yanklen + 1)); - ml_replace(lnum, newp, FALSE); + ml_replace(lnum, newp, false); curwin->w_cursor.lnum = lnum; i = 1; @@ -3620,9 +3622,9 @@ int do_join(size_t count, curr = skipwhite(curr); if (*curr != ')' && currsize != 0 && endcurr1 != TAB && (!has_format_option(FO_MBYTE_JOIN) - || (mb_ptr2char(curr) < 0x100 && endcurr1 < 0x100)) + || (utf_ptr2char(curr) < 0x100 && endcurr1 < 0x100)) && (!has_format_option(FO_MBYTE_JOIN2) - || mb_ptr2char(curr) < 0x100 || endcurr1 < 0x100) + || utf_ptr2char(curr) < 0x100 || endcurr1 < 0x100) ) { /* don't add a space if the line is ending in a space */ if (endcurr1 == ' ') @@ -3639,18 +3641,12 @@ int do_join(size_t count, sumsize += currsize + spaces[t]; endcurr1 = endcurr2 = NUL; if (insert_space && currsize > 0) { - if (has_mbyte) { - cend = curr + currsize; + cend = curr + currsize; + MB_PTR_BACK(curr, cend); + endcurr1 = utf_ptr2char(cend); + if (cend > curr) { MB_PTR_BACK(curr, cend); - endcurr1 = (*mb_ptr2char)(cend); - if (cend > curr) { - MB_PTR_BACK(curr, cend); - endcurr2 = (*mb_ptr2char)(cend); - } - } else { - endcurr1 = *(curr + currsize - 1); - if (currsize > 1) - endcurr2 = *(curr + currsize - 2); + endcurr2 = utf_ptr2char(cend); } } line_breakcheck(); @@ -3693,7 +3689,7 @@ int do_join(size_t count, curr = skipwhite(curr); currsize = (int)STRLEN(curr); } - ml_replace(curwin->w_cursor.lnum, newp, FALSE); + ml_replace(curwin->w_cursor.lnum, newp, false); if (setmark) { // Set the '] mark. @@ -4245,7 +4241,8 @@ int paragraph_start(linenr_T lnum) * - start/endspaces is the number of columns of the first/last yanked char * that are to be yanked. */ -static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, int is_del) +static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, + bool is_del) { int incr = 0; char_u *pend; @@ -5382,8 +5379,8 @@ void cursor_pos_info(dict_T *dict) switch (l_VIsual_mode) { case Ctrl_V: virtual_op = virtual_active(); - block_prep(&oparg, &bd, lnum, 0); - virtual_op = MAYBE; + block_prep(&oparg, &bd, lnum, false); + virtual_op = kNone; s = bd.textstart; len = (long)bd.textlen; break; diff --git a/src/nvim/option.c b/src/nvim/option.c index 50c172b580..8e2264c6a7 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2703,7 +2703,7 @@ did_set_string_option ( if (*p != NUL) x2 = *p++; if (*p != NUL) { - x3 = mb_ptr2char(p); + x3 = utf_ptr2char(p); p += mb_ptr2len(p); } if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) { @@ -6406,22 +6406,25 @@ static void langmap_set(void) ++p; break; } - if (p[0] == '\\' && p[1] != NUL) - ++p; - from = (*mb_ptr2char)(p); + if (p[0] == '\\' && p[1] != NUL) { + p++; + } + from = utf_ptr2char(p); to = NUL; if (p2 == NULL) { MB_PTR_ADV(p); if (p[0] != ',') { - if (p[0] == '\\') - ++p; - to = (*mb_ptr2char)(p); + if (p[0] == '\\') { + p++; + } + to = utf_ptr2char(p); } } else { if (p2[0] != ',') { - if (p2[0] == '\\') - ++p2; - to = (*mb_ptr2char)(p2); + if (p2[0] == '\\') { + p2++; + } + to = utf_ptr2char(p2); } } if (to == NUL) { @@ -6846,66 +6849,37 @@ int get_sts_value(void) */ void find_mps_values(int *initc, int *findc, int *backwards, int switchit) { - char_u *ptr; + char_u *ptr = curbuf->b_p_mps; - ptr = curbuf->b_p_mps; while (*ptr != NUL) { - if (has_mbyte) { - char_u *prev; - - if (mb_ptr2char(ptr) == *initc) { - if (switchit) { - *findc = *initc; - *initc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1); - *backwards = TRUE; - } else { - *findc = mb_ptr2char(ptr + mb_ptr2len(ptr) + 1); - *backwards = FALSE; - } - return; - } - prev = ptr; - ptr += mb_ptr2len(ptr) + 1; - if (mb_ptr2char(ptr) == *initc) { - if (switchit) { - *findc = *initc; - *initc = mb_ptr2char(prev); - *backwards = FALSE; - } else { - *findc = mb_ptr2char(prev); - *backwards = TRUE; - } - return; - } - ptr += mb_ptr2len(ptr); - } else { - if (*ptr == *initc) { - if (switchit) { - *backwards = TRUE; - *findc = *initc; - *initc = ptr[2]; - } else { - *backwards = FALSE; - *findc = ptr[2]; - } - return; + if (utf_ptr2char(ptr) == *initc) { + if (switchit) { + *findc = *initc; + *initc = utf_ptr2char(ptr + utfc_ptr2len(ptr) + 1); + *backwards = true; + } else { + *findc = utf_ptr2char(ptr + utfc_ptr2len(ptr) + 1); + *backwards = false; } - ptr += 2; - if (*ptr == *initc) { - if (switchit) { - *backwards = FALSE; - *findc = *initc; - *initc = ptr[-2]; - } else { - *backwards = TRUE; - *findc = ptr[-2]; - } - return; + return; + } + char_u *prev = ptr; + ptr += utfc_ptr2len(ptr) + 1; + if (utf_ptr2char(ptr) == *initc) { + if (switchit) { + *findc = *initc; + *initc = utf_ptr2char(prev); + *backwards = false; + } else { + *findc = utf_ptr2char(prev); + *backwards = true; } - ++ptr; + return; + } + ptr += utfc_ptr2len(ptr); + if (*ptr == ',') { + ptr++; } - if (*ptr == ',') - ++ptr; } } diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 5ae306e00e..7cd11e5c31 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -2044,9 +2044,9 @@ return { vi_def=true, varname='p_sp', defaults={ - condition='UNIX', - if_true={vi="| tee"}, - if_false={vi=">"}, + condition='WIN32', + if_true={vi=">%s 2>&1"}, + if_false={vi="| tee"}, } }, { diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 664dd3e968..4308c4e87e 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -1044,10 +1044,12 @@ qf_init_ext( if (newlist || qi->qf_curlist == qi->qf_listcount) { // make place for a new list qf_new_list(qi, qf_title); - } else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { + } else { // Adding to existing list, use last entry. adding = true; - old_last = qi->qf_lists[qi->qf_curlist].qf_last; + if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { + old_last = qi->qf_lists[qi->qf_curlist].qf_last; + } } // Use the local value of 'errorformat' if it's set. @@ -2885,6 +2887,7 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) qf_update_win_titlevar(qi); qf_fill_buffer(qi, buf, old_last); + buf_inc_changedtick(buf); if (old_last == NULL) { (void)qf_win_pos_update(qi, 0); @@ -4209,7 +4212,8 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) if (qi->qf_lists[qf_idx].qf_ctx != NULL) { di = tv_dict_item_alloc_len(S_LEN("context")); tv_copy(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv); - if (tv_dict_add(retdict, di) == FAIL) { + status = tv_dict_add(retdict, di); + if (status == FAIL) { tv_dict_item_free(di); } } else { @@ -4398,6 +4402,7 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action) typval_T *ctx = xcalloc(1, sizeof(typval_T)); tv_copy(&di->di_tv, ctx); qi->qf_lists[qf_idx].qf_ctx = ctx; + retval = OK; } return retval; diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index d76da62c6d..be6c43493b 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -772,13 +772,9 @@ static int get_equi_class(char_u **pp) char_u *p = *pp; if (p[1] == '=') { - if (has_mbyte) - l = (*mb_ptr2len)(p + 2); + l = (*mb_ptr2len)(p + 2); if (p[l + 2] == '=' && p[l + 3] == ']') { - if (has_mbyte) - c = mb_ptr2char(p + 2); - else - c = p[2]; + c = utf_ptr2char(p + 2); *pp += l + 4; return c; } @@ -1107,13 +1103,9 @@ static int get_coll_element(char_u **pp) char_u *p = *pp; if (p[0] != NUL && p[1] == '.') { - if (has_mbyte) - l = (*mb_ptr2len)(p + 2); + l = utfc_ptr2len(p + 2); if (p[l + 2] == '.' && p[l + 3] == ']') { - if (has_mbyte) - c = mb_ptr2char(p + 2); - else - c = p[2]; + c = utf_ptr2char(p + 2); *pp += l + 4; return c; } @@ -1299,10 +1291,7 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags) } if (OP(scan) == EXACTLY) { - if (has_mbyte) - r->regstart = (*mb_ptr2char)(OPERAND(scan)); - else - r->regstart = *OPERAND(scan); + r->regstart = utf_ptr2char(OPERAND(scan)); } else if (OP(scan) == BOW || OP(scan) == EOW || OP(scan) == NOTHING @@ -1310,10 +1299,7 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags) || OP(scan) == MCLOSE + 0 || OP(scan) == NCLOSE) { char_u *regnext_scan = regnext(scan); if (OP(regnext_scan) == EXACTLY) { - if (has_mbyte) - r->regstart = (*mb_ptr2char)(OPERAND(regnext_scan)); - else - r->regstart = *OPERAND(regnext_scan); + r->regstart = utf_ptr2char(OPERAND(regnext_scan)); } } @@ -2412,20 +2398,16 @@ collection: break; } } else { - if (has_mbyte) { - int len; - - /* produce a multibyte character, including any - * following composing characters */ - startc = mb_ptr2char(regparse); - len = (*mb_ptr2len)(regparse); - if (enc_utf8 && utf_char2len(startc) != len) - startc = -1; /* composing chars */ - while (--len >= 0) - regc(*regparse++); - } else { - startc = *regparse++; - regc(startc); + // produce a multibyte character, including any + // following composing characters. + startc = utf_ptr2char(regparse); + int len = utfc_ptr2len(regparse); + if (utf_char2len(startc) != len) { + // composing chars + startc = -1; + } + while (--len >= 0) { + regc(*regparse++); } } } @@ -2906,17 +2888,13 @@ static int peekchr(void) * Next character can never be (made) magic? * Then backslashing it won't do anything. */ - if (has_mbyte) - curchr = (*mb_ptr2char)(regparse + 1); - else - curchr = c; + curchr = utf_ptr2char(regparse + 1); } break; } default: - if (has_mbyte) - curchr = (*mb_ptr2char)(regparse); + curchr = utf_ptr2char(regparse); } return curchr; @@ -3466,12 +3444,7 @@ static long bt_regexec_both(char_u *line, /* If there is a "must appear" string, look for it. */ if (prog->regmust != NULL) { - int c; - - if (has_mbyte) - c = (*mb_ptr2char)(prog->regmust); - else - c = *prog->regmust; + int c = utf_ptr2char(prog->regmust); s = line + col; // This is used very often, esp. for ":global". Use two versions of @@ -3502,16 +3475,11 @@ static long bt_regexec_both(char_u *line, /* Simplest case: Anchored match need be tried only once. */ if (prog->reganch) { - int c; - - if (has_mbyte) - c = (*mb_ptr2char)(regline + col); - else - c = regline[col]; + int c = utf_ptr2char(regline + col); if (prog->regstart == NUL || prog->regstart == c || (rex.reg_ic - && (((enc_utf8 && utf_fold(prog->regstart) == utf_fold(c))) + && (utf_fold(prog->regstart) == utf_fold(c) || (c < 255 && prog->regstart < 255 && mb_tolower(prog->regstart) == mb_tolower(c))))) { retval = regtry(prog, col); @@ -3858,12 +3826,10 @@ regmatch ( } else if (rex.reg_line_lbr && WITH_NL(op) && *reginput == '\n') { ADVANCE_REGINPUT(); } else { - if (WITH_NL(op)) + if (WITH_NL(op)) { op -= ADD_NL; - if (has_mbyte) - c = (*mb_ptr2char)(reginput); - else - c = *reginput; + } + c = utf_ptr2char(reginput); switch (op) { case BOL: if (reginput != regline) @@ -5473,8 +5439,8 @@ do_class: } } else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) { scan++; - } else if (has_mbyte && (len = (*mb_ptr2len)(scan)) > 1) { - if ((cstrchr(opnd, (*mb_ptr2char)(scan)) == NULL) == testval) { + } else if ((len = utfc_ptr2len(scan)) > 1) { + if ((cstrchr(opnd, utf_ptr2char(scan)) == NULL) == testval) { break; } scan += len; @@ -6782,18 +6748,18 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, } c = *src++; } - } else if (has_mbyte) - c = mb_ptr2char(src - 1); - - /* Write to buffer, if copy is set. */ - if (func_one != (fptr_T)NULL) - /* Turbo C complains without the typecast */ + } else { + c = utf_ptr2char(src - 1); + } + // Write to buffer, if copy is set. + if (func_one != NULL) { func_one = (fptr_T)(func_one(&cc, c)); - else if (func_all != (fptr_T)NULL) - /* Turbo C complains without the typecast */ + } else if (func_all != NULL) { func_all = (fptr_T)(func_all(&cc, c)); - else /* just copy */ + } else { + // just copy cc = c; + } if (has_mbyte) { int totlen = mb_ptr2len(src - 1); @@ -6878,10 +6844,7 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, } dst += 2; } else { - if (has_mbyte) - c = mb_ptr2char(s); - else - c = *s; + c = utf_ptr2char(s); if (func_one != (fptr_T)NULL) /* Turbo C complains without the typecast */ diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 2eb0ca9313..deef3042d2 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -5030,16 +5030,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, * Run for each character. */ for (;; ) { - int curc; - int clen; - - if (has_mbyte) { - curc = (*mb_ptr2char)(reginput); - clen = (*mb_ptr2len)(reginput); - } else { - curc = *reginput; - clen = 1; - } + int curc = utf_ptr2char(reginput); + int clen = utfc_ptr2len(reginput); if (curc == NUL) { clen = 0; go_to_nextline = false; @@ -5501,7 +5493,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, // We don't care about the order of composing characters. // Get them into cchars[] first. while (len < clen) { - mc = mb_ptr2char(reginput + len); + mc = utf_ptr2char(reginput + len); cchars[ccount++] = mc; len += mb_char2len(mc); if (ccount == MAX_MCO) diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 9f0d8a5080..f7fdc6060d 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -783,16 +783,18 @@ static void win_update(win_T *wp) } } - (void)hasFoldingWin(wp, mod_top, &mod_top, NULL, TRUE, NULL); - if (mod_top > lnumt) + (void)hasFoldingWin(wp, mod_top, &mod_top, NULL, true, NULL); + if (mod_top > lnumt) { mod_top = lnumt; + } - /* Now do the same for the bottom line (one above mod_bot). */ - --mod_bot; - (void)hasFoldingWin(wp, mod_bot, NULL, &mod_bot, TRUE, NULL); - ++mod_bot; - if (mod_bot < lnumb) + // Now do the same for the bottom line (one above mod_bot). + mod_bot--; + (void)hasFoldingWin(wp, mod_bot, NULL, &mod_bot, true, NULL); + mod_bot++; + if (mod_bot < lnumb) { mod_bot = lnumb; + } } /* When a change starts above w_topline and the end is below @@ -833,12 +835,13 @@ static void win_update(win_T *wp) type = VALID; } - /* Trick: we want to avoid clearing the screen twice. screenclear() will - * set "screen_cleared" to TRUE. The special value MAYBE (which is still - * non-zero and thus not FALSE) will indicate that screenclear() was not - * called. */ - if (screen_cleared) - screen_cleared = MAYBE; + // Trick: we want to avoid clearing the screen twice. screenclear() will + // set "screen_cleared" to kTrue. The special value kNone (which is still + // non-zero and thus not kFalse) will indicate that screenclear() was not + // called. + if (screen_cleared) { + screen_cleared = kNone; + } /* * If there are no changes on the screen that require a complete redraw, @@ -875,7 +878,7 @@ static void win_update(win_T *wp) ++j; if (j >= wp->w_height - 2) break; - (void)hasFoldingWin(wp, ln, NULL, &ln, TRUE, NULL); + (void)hasFoldingWin(wp, ln, NULL, &ln, true, NULL); } } else j = wp->w_lines[0].wl_lnum - wp->w_topline; @@ -987,7 +990,7 @@ static void win_update(win_T *wp) * when it won't get updated below. */ if (wp->w_p_diff && bot_start > 0) wp->w_lines[0].wl_size = - plines_win_nofill(wp, wp->w_topline, TRUE) + plines_win_nofill(wp, wp->w_topline, true) + wp->w_topfill; } } @@ -999,14 +1002,16 @@ static void win_update(win_T *wp) if (mid_start == 0) { mid_end = wp->w_height; if (ONE_WINDOW) { - /* Clear the screen when it was not done by win_del_lines() or - * win_ins_lines() above, "screen_cleared" is FALSE or MAYBE - * then. */ - if (screen_cleared != TRUE) + // Clear the screen when it was not done by win_del_lines() or + // win_ins_lines() above, "screen_cleared" is kFalse or kNone + // then. + if (screen_cleared != kTrue) { screenclear(); - /* The screen was cleared, redraw the tab pages line. */ - if (redraw_tabline) + } + // The screen was cleared, redraw the tab pages line. + if (redraw_tabline) { draw_tabline(); + } } } @@ -1014,8 +1019,9 @@ static void win_update(win_T *wp) * cleared (only happens for the first window) or when screenclear() * was called directly above, "must_redraw" will have been set to * NOT_VALID, need to reset it here to avoid redrawing twice. */ - if (screen_cleared == TRUE) + if (screen_cleared == kTrue) { must_redraw = 0; + } } else { /* Not VALID or INVERTED: redraw all lines. */ mid_start = 0; @@ -1303,15 +1309,15 @@ static void win_update(win_T *wp) /* Able to count old number of rows: Count new window * rows, and may insert/delete lines */ j = idx; - for (l = lnum; l < mod_bot; ++l) { - if (hasFoldingWin(wp, l, NULL, &l, TRUE, NULL)) - ++new_rows; - else if (l == wp->w_topline) - new_rows += plines_win_nofill(wp, l, TRUE) - + wp->w_topfill; - else - new_rows += plines_win(wp, l, TRUE); - ++j; + for (l = lnum; l < mod_bot; l++) { + if (hasFoldingWin(wp, l, NULL, &l, true, NULL)) { + new_rows++; + } else if (l == wp->w_topline) { + new_rows += plines_win_nofill(wp, l, true) + wp->w_topfill; + } else { + new_rows += plines_win(wp, l, true); + } + j++; if (new_rows > wp->w_height - row - 2) { /* it's getting too much, must redraw the rest */ new_rows = 9999; @@ -1441,12 +1447,13 @@ static void win_update(win_T *wp) } wp->w_lines[idx].wl_lnum = lnum; - wp->w_lines[idx].wl_valid = TRUE; - if (row > wp->w_height) { /* past end of screen */ - /* we may need the size of that too long line later on */ - if (dollar_vcol == -1) - wp->w_lines[idx].wl_size = plines_win(wp, lnum, TRUE); - ++idx; + wp->w_lines[idx].wl_valid = true; + if (row > wp->w_height) { // past end of screen + // we may need the size of that too long line later on + if (dollar_vcol == -1) { + wp->w_lines[idx].wl_size = plines_win(wp, lnum, true); + } + idx++; break; } if (dollar_vcol == -1) @@ -2190,7 +2197,7 @@ win_line ( match_T *shl; // points to search_hl or a match int shl_flag; // flag to indicate whether search_hl // has been processed or not - int prevcol_hl_flag; // flag to indicate whether prevcol + bool prevcol_hl_flag; // flag to indicate whether prevcol // equals startcol of search_hl or one // of the matches int prev_c = 0; // previous Arabic character @@ -3019,6 +3026,12 @@ win_line ( if (shl != &search_hl && cur != NULL) cur = cur->next; } + // Only highlight one character after the last column. + if (*ptr == NUL + && (did_line_attr >= 1 + || (wp->w_p_list && lcs_eol_one == -1))) { + search_attr = 0; + } } if (diff_hlf != (hlf_T)0) { @@ -3294,8 +3307,7 @@ win_line ( did_emsg = FALSE; syntax_attr = get_syntax_attr((colnr_T)v - 1, - has_spell ? &can_spell : - NULL, FALSE); + has_spell ? &can_spell : NULL, false); if (did_emsg) { wp->w_s->b_syn_error = TRUE; @@ -3668,7 +3680,9 @@ win_line ( // don't do search HL for the rest of the line if ((line_attr_lowprio || line_attr) - && char_attr == search_attr && col > 0) { + && char_attr == search_attr + && (did_line_attr > 1 + || (wp->w_p_list && lcs_eol > 0))) { char_attr = line_attr; } if (diff_hlf == HLF_TXD) { @@ -3827,9 +3841,12 @@ win_line ( || lnum == VIsual.lnum || lnum == curwin->w_cursor.lnum) && c == NUL) - /* highlight 'hlsearch' match at end of line */ - || (prevcol_hl_flag == TRUE && did_line_attr <= 1) - )) { + // highlight 'hlsearch' match at end of line + || (prevcol_hl_flag + && !(wp->w_p_cul && lnum == wp->w_cursor.lnum + && !(wp == curwin && VIsual_active)) + && diff_hlf == (hlf_T)0 + && did_line_attr <= 1))) { int n = 0; if (wp->w_p_rl) { @@ -5521,10 +5538,12 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum) && re_multiline(shl->rm.regprog)) { if (shl->first_lnum == 0) { for (shl->first_lnum = lnum; - shl->first_lnum > wp->w_topline; --shl->first_lnum) - if (hasFoldingWin(wp, shl->first_lnum - 1, - NULL, NULL, TRUE, NULL)) + shl->first_lnum > wp->w_topline; + shl->first_lnum--) { + if (hasFoldingWin(wp, shl->first_lnum - 1, NULL, NULL, true, NULL)) { break; + } + } } if (cur != NULL) { cur->pos.cur = 0; @@ -5797,7 +5816,8 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, // TODO(bfredl): The relevant caller should do this if (row == Rows - 1) { // overwritten the command line redraw_cmdline = true; - if (c1 == ' ' && c2 == ' ') { + if (start_col == 0 && end_col == Columns + && c1 == ' ' && c2 == ' ' && attr == 0) { clear_cmdline = false; // command line has been cleared } if (start_col == 0) { @@ -6068,7 +6088,7 @@ static void screenclear2(void) ui_call_grid_clear(1); // clear the display clear_cmdline = false; mode_displayed = false; - screen_cleared = true; // can use contents of ScreenLines now + screen_cleared = kTrue; // can use contents of ScreenLines now win_rest_invalid(firstwin); redraw_cmdline = TRUE; diff --git a/src/nvim/search.c b/src/nvim/search.c index 578d1fd35a..95929f0eb4 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -1120,8 +1120,8 @@ int do_search( msgbuf = xmalloc(STRLEN(p) + 40); { msgbuf[0] = dirc; - if (enc_utf8 && utf_iscomposing(utf_ptr2char(p))) { - /* Use a space to draw the composing char on. */ + if (utf_iscomposing(utf_ptr2char(p))) { + // Use a space to draw the composing char on. msgbuf[1] = ' '; STRCPY(msgbuf + 2, p); } else @@ -1549,37 +1549,31 @@ static bool find_rawstring_end(char_u *linep, pos_T *startpos, pos_T *endpos) pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) { - static pos_T pos; /* current search position */ - int findc = 0; /* matching brace */ - int c; - int count = 0; /* cumulative number of braces */ - int backwards = false; /* init for gcc */ - int raw_string = false; /* search for raw string */ - int inquote = false; /* true when inside quotes */ - char_u *linep; /* pointer to current line */ + static pos_T pos; // current search position + int findc = 0; // matching brace + int count = 0; // cumulative number of braces + int backwards = false; // init for gcc + bool raw_string = false; // search for raw string + bool inquote = false; // true when inside quotes char_u *ptr; - int do_quotes; /* check for quotes in current line */ - int at_start; /* do_quotes value at start position */ - int hash_dir = 0; /* Direction searched for # things */ - int comment_dir = 0; /* Direction searched for comments */ - pos_T match_pos; /* Where last slash-star was found */ - int start_in_quotes; /* start position is in quotes */ - int traveled = 0; /* how far we've searched so far */ - int ignore_cend = FALSE; /* ignore comment end */ - int cpo_match; /* vi compatible matching */ - int cpo_bsl; /* don't recognize backslashes */ - int match_escaped = 0; /* search for escaped match */ - int dir; /* Direction to search */ - int comment_col = MAXCOL; /* start of / / comment */ - int lispcomm = FALSE; /* inside of Lisp-style comment */ - int lisp = curbuf->b_p_lisp; /* engage Lisp-specific hacks ;) */ + int hash_dir = 0; // Direction searched for # things + int comment_dir = 0; // Direction searched for comments + int traveled = 0; // how far we've searched so far + bool ignore_cend = false; // ignore comment end + int match_escaped = 0; // search for escaped match + int dir; // Direction to search + int comment_col = MAXCOL; // start of / / comment + bool lispcomm = false; // inside of Lisp-style comment + bool lisp = curbuf->b_p_lisp; // engage Lisp-specific hacks ;) pos = curwin->w_cursor; pos.coladd = 0; - linep = ml_get(pos.lnum); + char_u *linep = ml_get(pos.lnum); // pointer to current line - cpo_match = (vim_strchr(p_cpo, CPO_MATCH) != NULL); - cpo_bsl = (vim_strchr(p_cpo, CPO_MATCHBSL) != NULL); + // vi compatible matching + bool cpo_match = (vim_strchr(p_cpo, CPO_MATCH) != NULL); + // don't recognize backslashes + bool cpo_bsl = (vim_strchr(p_cpo, CPO_MATCHBSL) != NULL); /* Direction to search when initc is '/', '*' or '#' */ if (flags & FM_BACKWARD) @@ -1748,13 +1742,16 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) } } - /* This is just guessing: when 'rightleft' is set, search for a matching - * paren/brace in the other direction. */ - if (curwin->w_p_rl && vim_strchr((char_u *)"()[]{}<>", initc) != NULL) + // This is just guessing: when 'rightleft' is set, search for a matching + // paren/brace in the other direction. + if (curwin->w_p_rl && vim_strchr((char_u *)"()[]{}<>", initc) != NULL) { backwards = !backwards; + } - do_quotes = -1; - start_in_quotes = MAYBE; + int do_quotes = -1; // check for quotes in current line + int at_start; // do_quotes value at start position + TriState start_in_quotes = kNone; // start position is in quotes + pos_T match_pos; // Where last slash-star was found clearpos(&match_pos); /* backward search: Check if this line contains a single-line comment */ @@ -1762,8 +1759,9 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) || lisp ) comment_col = check_linecomment(linep); - if (lisp && comment_col != MAXCOL && pos.col > (colnr_T)comment_col) - lispcomm = TRUE; /* find match inside this comment */ + if (lisp && comment_col != MAXCOL && pos.col > (colnr_T)comment_col) { + lispcomm = true; // find match inside this comment + } while (!got_int) { /* * Go to the next position, forward or backward. We could use @@ -1925,26 +1923,29 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) * one for a '\' at the end. */ if (!do_quotes) { - inquote = FALSE; + inquote = false; if (ptr[-1] == '\\') { do_quotes = 1; - if (start_in_quotes == MAYBE) { - /* Do we need to use at_start here? */ - inquote = TRUE; - start_in_quotes = TRUE; - } else if (backwards) - inquote = TRUE; + if (start_in_quotes == kNone) { + // Do we need to use at_start here? + inquote = true; + start_in_quotes = kTrue; + } else if (backwards) { + inquote = true; + } } if (pos.lnum > 1) { ptr = ml_get(pos.lnum - 1); if (*ptr && *(ptr + STRLEN(ptr) - 1) == '\\') { do_quotes = 1; - if (start_in_quotes == MAYBE) { + if (start_in_quotes == kNone) { inquote = at_start; - if (inquote) - start_in_quotes = TRUE; - } else if (!backwards) - inquote = TRUE; + if (inquote) { + start_in_quotes = kTrue; + } + } else if (!backwards) { + inquote = true; + } } /* ml_get() only keeps one line, need to get linep again */ @@ -1952,8 +1953,9 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) } } } - if (start_in_quotes == MAYBE) - start_in_quotes = FALSE; + if (start_in_quotes == kNone) { + start_in_quotes = kFalse; + } /* * If 'smartmatch' is set: @@ -1966,13 +1968,13 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) * inquote if the number of quotes in a line is even, unless this * line or the previous one ends in a '\'. Complicated, isn't it? */ - c = PTR2CHAR(linep + pos.col); + const int c = PTR2CHAR(linep + pos.col); switch (c) { case NUL: /* at end of line without trailing backslash, reset inquote */ if (pos.col == 0 || linep[pos.col - 1] != '\\') { - inquote = FALSE; - start_in_quotes = FALSE; + inquote = false; + start_in_quotes = kFalse; } break; @@ -1987,7 +1989,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) break; if ((((int)pos.col - 1 - col) & 1) == 0) { inquote = !inquote; - start_in_quotes = FALSE; + start_in_quotes = kFalse; } } break; @@ -2039,7 +2041,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) /* Check for match outside of quotes, and inside of * quotes when the start is also inside of quotes. */ - if ((!inquote || start_in_quotes == TRUE) + if ((!inquote || start_in_quotes == kTrue) && (c == initc || c == findc)) { int col, bslcnt = 0; diff --git a/src/nvim/spell.c b/src/nvim/spell.c index cb03257878..1cb679245b 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1956,7 +1956,7 @@ static int count_syllables(slang_T *slang, char_u *word) skip = false; } else { // No recognized syllable item, at least a syllable char then? - c = mb_ptr2char(p); + c = utf_ptr2char(p); len = (*mb_ptr2len)(p); if (vim_strchr(slang->sl_syllable, c) == NULL) skip = false; // No, search for next syllable @@ -2271,7 +2271,7 @@ static void use_midword(slang_T *lp, win_T *wp) int c, l, n; char_u *bp; - c = mb_ptr2char(p); + c = utf_ptr2char(p); l = (*mb_ptr2len)(p); if (c < 256 && l <= 2) wp->w_s->b_spell_ismw[c] = true; @@ -2597,16 +2597,18 @@ static bool spell_iswordp(char_u *p, win_T *wp) if (wp->w_s->b_spell_ismw[*p]) s = p + 1; // skip a mid-word character } else { - c = mb_ptr2char(p); + c = utf_ptr2char(p); if (c < 256 ? wp->w_s->b_spell_ismw[c] : (wp->w_s->b_spell_ismw_mb != NULL - && vim_strchr(wp->w_s->b_spell_ismw_mb, c) != NULL)) + && vim_strchr(wp->w_s->b_spell_ismw_mb, c) != NULL)) { s = p + l; + } } - c = mb_ptr2char(s); - if (c > 255) + c = utf_ptr2char(s); + if (c > 255) { return spell_mb_isword_class(mb_get_class(s), wp); + } return spelltab.st_isw[c]; } @@ -2617,16 +2619,11 @@ static bool spell_iswordp(char_u *p, win_T *wp) // Unlike spell_iswordp() this doesn't check for "midword" characters. bool spell_iswordp_nmw(const char_u *p, win_T *wp) { - int c; - - if (has_mbyte) { - c = mb_ptr2char(p); - if (c > 255) { - return spell_mb_isword_class(mb_get_class(p), wp); - } - return spelltab.st_isw[c]; + int c = utf_ptr2char(p); + if (c > 255) { + return spell_mb_isword_class(mb_get_class(p), wp); } - return spelltab.st_isw[*p]; + return spelltab.st_isw[c]; } // Returns true if word class indicates a word character. @@ -2944,7 +2941,7 @@ void spell_suggest(int count) memmove(p, line, c); STRCPY(p + c, stp->st_word); STRCAT(p, sug.su_badptr + stp->st_orglen); - ml_replace(curwin->w_cursor.lnum, p, FALSE); + ml_replace(curwin->w_cursor.lnum, p, false); curwin->w_cursor.col = c; // For redo we use a change-word command. @@ -3062,7 +3059,7 @@ void ex_spellrepall(exarg_T *eap) memmove(p, line, curwin->w_cursor.col); STRCPY(p + curwin->w_cursor.col, repl_to); STRCAT(p, line + curwin->w_cursor.col + STRLEN(repl_from)); - ml_replace(curwin->w_cursor.lnum, p, FALSE); + ml_replace(curwin->w_cursor.lnum, p, false); changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); if (curwin->w_cursor.lnum != prev_lnum) { @@ -4300,14 +4297,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so && utf_iscomposing(utf_ptr2char(fword + sp->ts_fcharstart))) { sp->ts_score -= SCORE_SUBST - SCORE_SUBCOMP; - } else if (!soundfold - && slang->sl_has_map - && similar_chars(slang, - mb_ptr2char(tword - + sp->ts_twordlen - - sp->ts_tcharlen), - mb_ptr2char(fword - + sp->ts_fcharstart))) { + } else if ( + !soundfold + && slang->sl_has_map + && similar_chars( + slang, + utf_ptr2char(tword + sp->ts_twordlen - sp->ts_tcharlen), + utf_ptr2char(fword + sp->ts_fcharstart))) { // For a similar character adjust score from // SCORE_SUBST to SCORE_SIMILAR. sp->ts_score -= SCORE_SUBST - SCORE_SIMILAR; @@ -4315,8 +4311,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so } else if (sp->ts_isdiff == DIFF_INSERT && sp->ts_twordlen > sp->ts_tcharlen) { p = tword + sp->ts_twordlen - sp->ts_tcharlen; - c = mb_ptr2char(p); - if (enc_utf8 && utf_iscomposing(c)) { + c = utf_ptr2char(p); + if (utf_iscomposing(c)) { // Inserting a composing char doesn't // count that much. sp->ts_score -= SCORE_INS - SCORE_INSCOMP; @@ -4327,7 +4323,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // tree (might seem illogical but does // give better scores). MB_PTR_BACK(tword, p); - if (c == mb_ptr2char(p)) { + if (c == utf_ptr2char(p)) { sp->ts_score -= SCORE_INS - SCORE_INSDUP; } } @@ -4388,19 +4384,14 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // score if the same character is following "nn" -> "n". It's // a bit illogical for soundfold tree but it does give better // results. - if (has_mbyte) { - c = mb_ptr2char(fword + sp->ts_fidx); - stack[depth].ts_fidx += MB_PTR2LEN(fword + sp->ts_fidx); - if (enc_utf8 && utf_iscomposing(c)) { - stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP; - } else if (c == mb_ptr2char(fword + stack[depth].ts_fidx)) { - stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP; - } - } else { - ++stack[depth].ts_fidx; - if (fword[sp->ts_fidx] == fword[sp->ts_fidx + 1]) - stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP; + c = utf_ptr2char(fword + sp->ts_fidx); + stack[depth].ts_fidx += MB_PTR2LEN(fword + sp->ts_fidx); + if (utf_iscomposing(c)) { + stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP; + } else if (c == utf_ptr2char(fword + stack[depth].ts_fidx)) { + stack[depth].ts_score -= SCORE_DEL - SCORE_DELDUP; } + break; } // FALLTHROUGH @@ -4515,22 +4506,14 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so break; } - if (has_mbyte) { - n = MB_CPTR2LEN(p); - c = mb_ptr2char(p); - if (p[n] == NUL) - c2 = NUL; - else if (!soundfold && !spell_iswordp(p + n, curwin)) - c2 = c; // don't swap non-word char - else - c2 = mb_ptr2char(p + n); + n = MB_CPTR2LEN(p); + c = utf_ptr2char(p); + if (p[n] == NUL) { + c2 = NUL; + } else if (!soundfold && !spell_iswordp(p + n, curwin)) { + c2 = c; // don't swap non-word char } else { - if (p[1] == NUL) - c2 = NUL; - else if (!soundfold && !spell_iswordp(p + 1, curwin)) - c2 = c; // don't swap non-word char - else - c2 = p[1]; + c2 = utf_ptr2char(p + n); } // When the second character is NUL we can't swap. @@ -4550,9 +4533,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so if (c2 != NUL && TRY_DEEPER(su, stack, depth, SCORE_SWAP)) { go_deeper(stack, depth, SCORE_SWAP); #ifdef DEBUG_TRIEWALK - sprintf(changename[depth], "%.*s-%s: swap %c and %c", - sp->ts_twordlen, tword, fword + sp->ts_fidx, - c, c2); + snprintf(changename[depth], sizeof(changename[0]), + "%.*s-%s: swap %c and %c", + sp->ts_twordlen, tword, fword + sp->ts_fidx, + c, c2); #endif PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNSWAP; @@ -4576,38 +4560,25 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so case STATE_UNSWAP: // Undo the STATE_SWAP swap: "21" -> "12". p = fword + sp->ts_fidx; - if (has_mbyte) { - n = MB_PTR2LEN(p); - c = mb_ptr2char(p + n); - memmove(p + MB_PTR2LEN(p + n), p, n); - mb_char2bytes(c, p); - } else { - c = *p; - *p = p[1]; - p[1] = c; - } + n = MB_PTR2LEN(p); + c = utf_ptr2char(p + n); + memmove(p + MB_PTR2LEN(p + n), p, n); + mb_char2bytes(c, p); + // FALLTHROUGH case STATE_SWAP3: // Swap two bytes, skipping one: "123" -> "321". We change // "fword" here, it's changed back afterwards at STATE_UNSWAP3. p = fword + sp->ts_fidx; - if (has_mbyte) { - n = MB_CPTR2LEN(p); - c = mb_ptr2char(p); - fl = MB_CPTR2LEN(p + n); - c2 = mb_ptr2char(p + n); - if (!soundfold && !spell_iswordp(p + n + fl, curwin)) - c3 = c; // don't swap non-word char - else - c3 = mb_ptr2char(p + n + fl); + n = MB_CPTR2LEN(p); + c = utf_ptr2char(p); + fl = MB_CPTR2LEN(p + n); + c2 = utf_ptr2char(p + n); + if (!soundfold && !spell_iswordp(p + n + fl, curwin)) { + c3 = c; // don't swap non-word char } else { - c = *p; - c2 = p[1]; - if (!soundfold && !spell_iswordp(p + 2, curwin)) - c3 = c; // don't swap non-word char - else - c3 = p[2]; + c3 = utf_ptr2char(p + n + fl); } // When characters are identical: "121" then SWAP3 result is @@ -4651,22 +4622,15 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so case STATE_UNSWAP3: // Undo STATE_SWAP3: "321" -> "123" p = fword + sp->ts_fidx; - if (has_mbyte) { - n = MB_PTR2LEN(p); - c2 = mb_ptr2char(p + n); - fl = MB_PTR2LEN(p + n); - c = mb_ptr2char(p + n + fl); - tl = MB_PTR2LEN(p + n + fl); - memmove(p + fl + tl, p, n); - mb_char2bytes(c, p); - mb_char2bytes(c2, p + tl); - p = p + tl; - } else { - c = *p; - *p = p[2]; - p[2] = c; - ++p; - } + n = MB_PTR2LEN(p); + c2 = utf_ptr2char(p + n); + fl = MB_PTR2LEN(p + n); + c = utf_ptr2char(p + n + fl); + tl = MB_PTR2LEN(p + n + fl); + memmove(p + fl + tl, p, n); + mb_char2bytes(c, p); + mb_char2bytes(c2, p + tl); + p = p + tl; if (!soundfold && !spell_iswordp(p, curwin)) { // Middle char is not a word char, skip the rotate. First and @@ -4690,21 +4654,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_state = STATE_UNROT3L; ++depth; p = fword + sp->ts_fidx; - if (has_mbyte) { - n = MB_CPTR2LEN(p); - c = mb_ptr2char(p); - fl = MB_CPTR2LEN(p + n); - fl += MB_CPTR2LEN(p + n + fl); - memmove(p, p + n, fl); - mb_char2bytes(c, p + fl); - stack[depth].ts_fidxtry = sp->ts_fidx + n + fl; - } else { - c = *p; - *p = p[1]; - p[1] = p[2]; - p[2] = c; - stack[depth].ts_fidxtry = sp->ts_fidx + 3; - } + n = MB_CPTR2LEN(p); + c = utf_ptr2char(p); + fl = MB_CPTR2LEN(p + n); + fl += MB_CPTR2LEN(p + n + fl); + memmove(p, p + n, fl); + utf_char2bytes(c, p + fl); + stack[depth].ts_fidxtry = sp->ts_fidx + n + fl; } else { PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; @@ -4714,19 +4670,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so case STATE_UNROT3L: // Undo ROT3L: "231" -> "123" p = fword + sp->ts_fidx; - if (has_mbyte) { - n = MB_PTR2LEN(p); - n += MB_PTR2LEN(p + n); - c = mb_ptr2char(p + n); - tl = MB_PTR2LEN(p + n); - memmove(p + tl, p, n); - mb_char2bytes(c, p); - } else { - c = p[2]; - p[2] = p[1]; - p[1] = *p; - *p = c; - } + n = MB_PTR2LEN(p); + n += MB_PTR2LEN(p + n); + c = utf_ptr2char(p + n); + tl = MB_PTR2LEN(p + n); + memmove(p + tl, p, n); + mb_char2bytes(c, p); // Rotate three bytes right: "123" -> "312". We change "fword" // here, it's changed back afterwards at STATE_UNROT3R. @@ -4742,21 +4691,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so sp->ts_state = STATE_UNROT3R; ++depth; p = fword + sp->ts_fidx; - if (has_mbyte) { - n = MB_CPTR2LEN(p); - n += MB_CPTR2LEN(p + n); - c = mb_ptr2char(p + n); - tl = MB_CPTR2LEN(p + n); - memmove(p + tl, p, n); - mb_char2bytes(c, p); - stack[depth].ts_fidxtry = sp->ts_fidx + n + tl; - } else { - c = p[2]; - p[2] = p[1]; - p[1] = *p; - *p = c; - stack[depth].ts_fidxtry = sp->ts_fidx + 3; - } + n = MB_CPTR2LEN(p); + n += MB_CPTR2LEN(p + n); + c = utf_ptr2char(p + n); + tl = MB_CPTR2LEN(p + n); + memmove(p + tl, p, n); + mb_char2bytes(c, p); + stack[depth].ts_fidxtry = sp->ts_fidx + n + tl; } else { PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; @@ -4766,19 +4707,13 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so case STATE_UNROT3R: // Undo ROT3R: "312" -> "123" p = fword + sp->ts_fidx; - if (has_mbyte) { - c = mb_ptr2char(p); - tl = MB_PTR2LEN(p); - n = MB_PTR2LEN(p + tl); - n += MB_PTR2LEN(p + tl + n); - memmove(p, p + tl, n); - mb_char2bytes(c, p + n); - } else { - c = *p; - *p = p[1]; - p[1] = p[2]; - p[2] = c; - } + c = utf_ptr2char(p); + tl = MB_PTR2LEN(p); + n = MB_PTR2LEN(p + tl); + n += MB_PTR2LEN(p + tl + n); + memmove(p, p + tl, n); + mb_char2bytes(c, p + n); + // FALLTHROUGH case STATE_REP_INI: @@ -5604,25 +5539,29 @@ static bool similar_chars(slang_T *slang, int c1, int c2) if (c1 >= 256) { buf[mb_char2bytes(c1, buf)] = 0; hi = hash_find(&slang->sl_map_hash, buf); - if (HASHITEM_EMPTY(hi)) + if (HASHITEM_EMPTY(hi)) { m1 = 0; - else - m1 = mb_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1); - } else + } else { + m1 = utf_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1); + } + } else { m1 = slang->sl_map_array[c1]; - if (m1 == 0) + } + if (m1 == 0) { return false; - + } if (c2 >= 256) { buf[mb_char2bytes(c2, buf)] = 0; hi = hash_find(&slang->sl_map_hash, buf); - if (HASHITEM_EMPTY(hi)) + if (HASHITEM_EMPTY(hi)) { m2 = 0; - else - m2 = mb_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1); - } else + } else { + m2 = utf_ptr2char(hi->hi_key + STRLEN(hi->hi_key) + 1); + } + } else { m2 = slang->sl_map_array[c2]; + } return m1 == m2; } @@ -5659,11 +5598,9 @@ add_suggestion ( break; MB_PTR_BACK(goodword, pgood); MB_PTR_BACK(su->su_badptr, pbad); - if (has_mbyte) { - if (mb_ptr2char(pgood) != mb_ptr2char(pbad)) - break; - } else if (*pgood != *pbad) + if (utf_ptr2char(pgood) != utf_ptr2char(pbad)) { break; + } } if (badlen == 0 && goodlen == 0) @@ -7608,5 +7545,3 @@ int expand_spelling(linenr_T lnum, char_u *pat, char_u ***matchp) *matchp = ga.ga_data; return ga.ga_len; } - - diff --git a/src/nvim/state.c b/src/nvim/state.c index a4b394c9e4..5921bd45bf 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -73,13 +73,13 @@ getkey: } } -/// Return TRUE if in the current mode we need to use virtual. -int virtual_active(void) +/// Return true if in the current mode we need to use virtual. +bool virtual_active(void) { // While an operator is being executed we return "virtual_op", because // VIsual_active has already been reset, thus we can't check for "block" // being used. - if (virtual_op != MAYBE) { + if (virtual_op != kNone) { return virtual_op; } return ve_flags == VE_ALL diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index ff47e443f9..d7c23742ba 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -53,7 +53,7 @@ static bool did_syntax_onoff = false; struct hl_group { char_u *sg_name; ///< highlight group name char_u *sg_name_u; ///< uppercase of sg_name - int sg_cleared; ///< "hi clear" was used + bool sg_cleared; ///< "hi clear" was used int sg_attr; ///< Screen attr @see ATTR_ENTRY int sg_link; ///< link to this highlight group ID int sg_set; ///< combination of flags in \ref SG_SET @@ -62,7 +62,7 @@ struct hl_group { int sg_cterm; ///< "cterm=" highlighting attr int sg_cterm_fg; ///< terminal fg color number + 1 int sg_cterm_bg; ///< terminal bg color number + 1 - int sg_cterm_bold; ///< bold attr was set for light color + bool sg_cterm_bold; ///< bold attr was set for light color // for RGB UIs int sg_gui; ///< "gui=" highlighting attributes ///< (combination of \ref HlAttrFlags) @@ -115,42 +115,42 @@ static int hl_attr_table[] = {HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_UNDERCURL, HL_ITALIC, HL_INVERSE, HL_INVERSE, 0}; -/* - * The patterns that are being searched for are stored in a syn_pattern. - * A match item consists of one pattern. - * A start/end item consists of n start patterns and m end patterns. - * A start/skip/end item consists of n start patterns, one skip pattern and m - * end patterns. - * For the latter two, the patterns are always consecutive: start-skip-end. - * - * A character offset can be given for the matched text (_m_start and _m_end) - * and for the actually highlighted text (_h_start and _h_end). - */ +// The patterns that are being searched for are stored in a syn_pattern. +// A match item consists of one pattern. +// A start/end item consists of n start patterns and m end patterns. +// A start/skip/end item consists of n start patterns, one skip pattern and m +// end patterns. +// For the latter two, the patterns are always consecutive: start-skip-end. +// +// A character offset can be given for the matched text (_m_start and _m_end) +// and for the actually highlighted text (_h_start and _h_end). +// +// Note that ordering of members is optimized to reduce padding. typedef struct syn_pattern { - char sp_type; /* see SPTYPE_ defines below */ - char sp_syncing; /* this item used for syncing */ - int sp_flags; /* see HL_ defines below */ - int sp_cchar; /* conceal substitute character */ - struct sp_syn sp_syn; /* struct passed to in_id_list() */ - short sp_syn_match_id; /* highlight group ID of pattern */ - char_u *sp_pattern; /* regexp to match, pattern */ - regprog_T *sp_prog; /* regexp to match, program */ + char sp_type; // see SPTYPE_ defines below + bool sp_syncing; // this item used for syncing + int16_t sp_syn_match_id; // highlight group ID of pattern + int16_t sp_off_flags; // see below + int sp_offsets[SPO_COUNT]; // offsets + int sp_flags; // see HL_ defines below + int sp_cchar; // conceal substitute character + int sp_ic; // ignore-case flag for sp_prog + int sp_sync_idx; // sync item index (syncing only) + int sp_line_id; // ID of last line where tried + int sp_startcol; // next match in sp_line_id line + int16_t *sp_cont_list; // cont. group IDs, if non-zero + int16_t *sp_next_list; // next group IDs, if non-zero + struct sp_syn sp_syn; // struct passed to in_id_list() + char_u *sp_pattern; // regexp to match, pattern + regprog_T *sp_prog; // regexp to match, program syn_time_T sp_time; - int sp_ic; /* ignore-case flag for sp_prog */ - short sp_off_flags; /* see below */ - int sp_offsets[SPO_COUNT]; /* offsets */ - short *sp_cont_list; /* cont. group IDs, if non-zero */ - short *sp_next_list; /* next group IDs, if non-zero */ - int sp_sync_idx; /* sync item index (syncing only) */ - int sp_line_id; /* ID of last line where tried */ - int sp_startcol; /* next match in sp_line_id line */ } synpat_T; typedef struct syn_cluster_S { - char_u *scl_name; /* syntax cluster name */ - char_u *scl_name_u; /* uppercase of scl_name */ - short *scl_list; /* IDs in this syntax cluster */ + char_u *scl_name; // syntax cluster name + char_u *scl_name_u; // uppercase of scl_name + int16_t *scl_list; // IDs in this syntax cluster } syn_cluster_T; /* @@ -159,27 +159,27 @@ typedef struct syn_cluster_S { * (The end positions have the column number of the next char) */ typedef struct state_item { - int si_idx; /* index of syntax pattern or - KEYWORD_IDX */ - int si_id; /* highlight group ID for keywords */ - int si_trans_id; /* idem, transparency removed */ - int si_m_lnum; /* lnum of the match */ - int si_m_startcol; /* starting column of the match */ - lpos_T si_m_endpos; /* just after end posn of the match */ - lpos_T si_h_startpos; /* start position of the highlighting */ - lpos_T si_h_endpos; /* end position of the highlighting */ - lpos_T si_eoe_pos; /* end position of end pattern */ - int si_end_idx; /* group ID for end pattern or zero */ - int si_ends; /* if match ends before si_m_endpos */ - int si_attr; /* attributes in this state */ - long si_flags; /* HL_HAS_EOL flag in this state, and - * HL_SKIP* for si_next_list */ - int si_seqnr; /* sequence number */ - int si_cchar; /* substitution character for conceal */ - short *si_cont_list; /* list of contained groups */ - short *si_next_list; /* nextgroup IDs after this item ends */ - reg_extmatch_T *si_extmatch; /* \z(...\) matches from start - * pattern */ + int si_idx; // index of syntax pattern or + // KEYWORD_IDX + int si_id; // highlight group ID for keywords + int si_trans_id; // idem, transparency removed + int si_m_lnum; // lnum of the match + int si_m_startcol; // starting column of the match + lpos_T si_m_endpos; // just after end posn of the match + lpos_T si_h_startpos; // start position of the highlighting + lpos_T si_h_endpos; // end position of the highlighting + lpos_T si_eoe_pos; // end position of end pattern + int si_end_idx; // group ID for end pattern or zero + int si_ends; // if match ends before si_m_endpos + int si_attr; // attributes in this state + long si_flags; // HL_HAS_EOL flag in this state, and + // HL_SKIP* for si_next_list + int si_seqnr; // sequence number + int si_cchar; // substitution character for conceal + int16_t *si_cont_list; // list of contained groups + int16_t *si_next_list; // nextgroup IDs after this item ends + reg_extmatch_T *si_extmatch; // \z(...\) matches from start + // pattern } stateitem_T; /* @@ -187,14 +187,14 @@ typedef struct state_item { * very often. */ typedef struct { - int flags; /* flags for contained and transparent */ - int keyword; /* TRUE for ":syn keyword" */ - int *sync_idx; /* syntax item for "grouphere" argument, NULL - if not allowed */ - char has_cont_list; /* TRUE if "cont_list" can be used */ - short *cont_list; /* group IDs for "contains" argument */ - short *cont_in_list; /* group IDs for "containedin" argument */ - short *next_list; /* group IDs for "nextgroup" argument */ + int flags; // flags for contained and transparent + bool keyword; // true for ":syn keyword" + int *sync_idx; // syntax item for "grouphere" argument, NULL + // if not allowed + bool has_cont_list; // true if "cont_list" can be used + int16_t *cont_list; // group IDs for "contains" argument + int16_t *cont_in_list; // group IDs for "containedin" argument + int16_t *next_list; // group IDs for "nextgroup" argument } syn_opt_arg_T; typedef struct { @@ -318,9 +318,10 @@ static int keepend_level = -1; static char msg_no_items[] = N_("No Syntax items defined for this buffer"); -#define KEYWORD_IDX -1 /* value of si_idx for keywords */ -#define ID_LIST_ALL (short *)-1 /* valid of si_cont_list for containing all - but contained groups */ +// value of si_idx for keywords +#define KEYWORD_IDX -1 +// valid of si_cont_list for containing all but contained groups +#define ID_LIST_ALL (int16_t *)-1 static int next_seqnr = 1; /* value to use for si_seqnr */ @@ -363,9 +364,9 @@ static int current_state_stored = 0; /* TRUE if stored current state static int current_finished = 0; /* current line has been finished */ static garray_T current_state /* current stack of state_items */ = GA_EMPTY_INIT_VALUE; -static short *current_next_list = NULL; /* when non-zero, nextgroup list */ -static int current_next_flags = 0; /* flags for current_next_list */ -static int current_line_id = 0; /* unique number for current line */ +static int16_t *current_next_list = NULL; // when non-zero, nextgroup list +static int current_next_flags = 0; // flags for current_next_list +static int current_line_id = 0; // unique number for current line #define CUR_STATE(idx) ((stateitem_T *)(current_state.ga_data))[idx] @@ -1525,32 +1526,26 @@ int syntax_check_changed(linenr_T lnum) */ static bool syn_finish_line( - bool syncing // called for syncing + const bool syncing // called for syncing ) { - stateitem_T *cur_si; - colnr_T prev_current_col; - while (!current_finished) { - (void)syn_current_attr(syncing, FALSE, NULL, FALSE); - /* - * When syncing, and found some item, need to check the item. - */ + (void)syn_current_attr(syncing, false, NULL, false); + + // When syncing, and found some item, need to check the item. if (syncing && current_state.ga_len) { - /* - * Check for match with sync item. - */ - cur_si = &CUR_STATE(current_state.ga_len - 1); + // Check for match with sync item. + const stateitem_T *const cur_si = &CUR_STATE(current_state.ga_len - 1); if (cur_si->si_idx >= 0 && (SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags & (HL_SYNC_HERE|HL_SYNC_THERE))) { return true; } - /* syn_current_attr() will have skipped the check for an item - * that ends here, need to do that now. Be careful not to go - * past the NUL. */ - prev_current_col = current_col; + // syn_current_attr() will have skipped the check for an item + // that ends here, need to do that now. Be careful not to go + // past the NUL. + const colnr_T prev_current_col = current_col; if (syn_getcurline()[current_col] != NUL) { current_col++; } @@ -1573,9 +1568,9 @@ syn_finish_line( */ int get_syntax_attr( - colnr_T col, - bool *can_spell, - int keep_state /* keep state of char at "col" */ + const colnr_T col, + bool *const can_spell, + const bool keep_state // keep state of char at "col" ) { int attr = 0; @@ -1609,9 +1604,9 @@ get_syntax_attr( * Skip from the current column to "col", get the attributes for "col". */ while (current_col <= col) { - attr = syn_current_attr(FALSE, TRUE, can_spell, - current_col == col ? keep_state : FALSE); - ++current_col; + attr = syn_current_attr(false, true, can_spell, + current_col == col ? keep_state : false); + current_col++; } return attr; @@ -1620,42 +1615,37 @@ get_syntax_attr( /* * Get syntax attributes for current_lnum, current_col. */ -static int -syn_current_attr( - int syncing, // When 1: called for syncing - int displaying, // result will be displayed - bool *can_spell, // return: do spell checking - int keep_state // keep syntax stack afterwards +static int syn_current_attr( + const bool syncing, // When true: called for syncing + const bool displaying, // result will be displayed + bool *const can_spell, // return: do spell checking + const bool keep_state // keep syntax stack afterwards ) { - int syn_id; - lpos_T endpos; /* was: char_u *endp; */ - lpos_T hl_startpos; /* was: int hl_startcol; */ + lpos_T endpos; // was: char_u *endp; + lpos_T hl_startpos; // was: int hl_startcol; lpos_T hl_endpos; - lpos_T eos_pos; /* end-of-start match (start region) */ - lpos_T eoe_pos; /* end-of-end pattern */ - int end_idx; /* group ID for end pattern */ - synpat_T *spp; + lpos_T eos_pos; // end-of-start match (start region) + lpos_T eoe_pos; // end-of-end pattern + int end_idx; // group ID for end pattern stateitem_T *cur_si, *sip = NULL; int startcol; int endcol; long flags; int cchar; - short *next_list; - int found_match; /* found usable match */ - static int try_next_column = FALSE; /* must try in next col */ - int do_keywords; + int16_t *next_list; + bool found_match; // found usable match + static bool try_next_column = false; // must try in next col regmmatch_T regmatch; lpos_T pos; - int lc_col; reg_extmatch_T *cur_extmatch = NULL; char_u buf_chartab[32]; // chartab array for syn iskeyword char_u *line; // current line. NOTE: becomes invalid after // looking for a pattern match! - /* variables for zero-width matches that have a "nextgroup" argument */ - int keep_next_list; - int zero_width_next_list = FALSE; + // variables for zero-width matches that have a "nextgroup" argument + bool keep_next_list; + bool zero_width_next_list = false; garray_T zero_width_next_ga; /* @@ -1690,13 +1680,13 @@ syn_current_attr( */ if (try_next_column) { next_match_idx = -1; - try_next_column = FALSE; + try_next_column = false; } - /* Only check for keywords when not syncing and there are some. */ - do_keywords = !syncing - && (syn_block->b_keywtab.ht_used > 0 - || syn_block->b_keywtab_ic.ht_used > 0); + // Only check for keywords when not syncing and there are some. + const bool do_keywords = !syncing + && (syn_block->b_keywtab.ht_used > 0 + || syn_block->b_keywtab_ic.ht_used > 0); /* Init the list of zero-width matches with a nextlist. This is used to * avoid matching the same item in the same position twice. */ @@ -1711,9 +1701,9 @@ syn_current_attr( * column. */ do { - found_match = FALSE; - keep_next_list = FALSE; - syn_id = 0; + found_match = false; + keep_next_list = false; + int syn_id = 0; /* * 1. Check for a current state. @@ -1806,7 +1796,7 @@ syn_current_attr( next_match_idx = 0; /* no match in this line yet */ next_match_col = MAXCOL; for (int idx = syn_block->b_syn_patterns.ga_len; --idx >= 0; ) { - spp = &(SYN_ITEMS(syn_block)[idx]); + synpat_T *const spp = &(SYN_ITEMS(syn_block)[idx]); if ( spp->sp_syncing == syncing && (displaying || !(spp->sp_flags & HL_DISPLAY)) && (spp->sp_type == SPTYPE_MATCH @@ -1827,13 +1817,14 @@ syn_current_attr( continue; spp->sp_line_id = current_line_id; - lc_col = current_col - spp->sp_offsets[SPO_LC_OFF]; - if (lc_col < 0) + colnr_T lc_col = current_col - spp->sp_offsets[SPO_LC_OFF]; + if (lc_col < 0) { lc_col = 0; + } regmatch.rmm_ic = spp->sp_ic; regmatch.regprog = spp->sp_prog; - int r = syn_regexec(®match, current_lnum, (colnr_T)lc_col, + int r = syn_regexec(®match, current_lnum, lc_col, IF_SYN_TIME(&spp->sp_time)); spp->sp_prog = regmatch.regprog; if (!r) { @@ -1872,7 +1863,7 @@ syn_current_attr( * column, because it may match from there. */ if (did_match_already(idx, &zero_width_next_ga)) { - try_next_column = TRUE; + try_next_column = true; continue; } @@ -1934,9 +1925,9 @@ syn_current_attr( * If an empty string is matched, may need * to try matching again at next column. */ - if (regmatch.startpos[0].col - == regmatch.endpos[0].col) - try_next_column = TRUE; + if (regmatch.startpos[0].col == regmatch.endpos[0].col) { + try_next_column = true; + } continue; } } @@ -1981,8 +1972,8 @@ syn_current_attr( && lspp->sp_next_list != NULL) { current_next_list = lspp->sp_next_list; current_next_flags = lspp->sp_flags; - keep_next_list = TRUE; - zero_width_next_list = TRUE; + keep_next_list = true; + zero_width_next_list = true; /* Add the index to a list, so that we can check * later that we don't match it again (and cause an @@ -2025,8 +2016,9 @@ syn_current_attr( */ current_next_list = NULL; next_match_idx = -1; - if (!zero_width_next_list) - found_match = TRUE; + if (!zero_width_next_list) { + found_match = true; + } } } while (found_match); @@ -2931,39 +2923,35 @@ static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T * The caller must check if a keyword can start at startcol. * Return its ID if found, 0 otherwise. */ -static int -check_keyword_id( - char_u *line, - int startcol, /* position in line to check for keyword */ - int *endcolp, /* return: character after found keyword */ - long *flagsp, /* return: flags of matching keyword */ - short **next_listp, /* return: next_list of matching keyword */ - stateitem_T *cur_si, /* item at the top of the stack */ - int *ccharp /* conceal substitution char */ +static int check_keyword_id( + char_u *const line, + const int startcol, // position in line to check for keyword + int *const endcolp, // return: character after found keyword + long *const flagsp, // return: flags of matching keyword + int16_t **const next_listp, // return: next_list of matching keyword + stateitem_T *const cur_si, // item at the top of the stack + int *const ccharp // conceal substitution char ) { - char_u *kwp; - int kwlen; - char_u keyword[MAXKEYWLEN + 1]; /* assume max. keyword len is 80 */ - - /* Find first character after the keyword. First character was already - * checked. */ - kwp = line + startcol; - kwlen = 0; + // Find first character after the keyword. First character was already + // checked. + char_u *const kwp = line + startcol; + int kwlen = 0; do { - if (has_mbyte) + if (has_mbyte) { kwlen += (*mb_ptr2len)(kwp + kwlen); - else - ++kwlen; + } else { + kwlen++; + } } while (vim_iswordp_buf(kwp + kwlen, syn_buf)); - if (kwlen > MAXKEYWLEN) + if (kwlen > MAXKEYWLEN) { return 0; + } - /* - * Must make a copy of the keyword, so we can add a NUL and make it - * lowercase. - */ + // Must make a copy of the keyword, so we can add a NUL and make it + // lowercase. + char_u keyword[MAXKEYWLEN + 1]; // assume max. keyword len is 80 STRLCPY(keyword, kwp, kwlen + 1); keyentry_T *kp = NULL; @@ -3321,12 +3309,10 @@ static void syn_cmd_clear(exarg_T *eap, int syncing) EMSG2(_("E391: No such syntax cluster: %s"), arg); break; } else { - /* - * We can't physically delete a cluster without changing - * the IDs of other clusters, so we do the next best thing - * and make it empty. - */ - short scl_id = id - SYNID_CLUSTER; + // We can't physically delete a cluster without changing + // the IDs of other clusters, so we do the next best thing + // and make it empty. + int scl_id = id - SYNID_CLUSTER; xfree(SYN_CLSTR(curwin->w_s)[scl_id].scl_list); SYN_CLSTR(curwin->w_s)[scl_id].scl_list = NULL; @@ -3349,7 +3335,7 @@ static void syn_cmd_clear(exarg_T *eap, int syncing) /* * Clear one syntax group for the current buffer. */ -static void syn_clear_one(int id, int syncing) +static void syn_clear_one(const int id, const bool syncing) { synpat_T *spp; @@ -3491,8 +3477,8 @@ syn_cmd_list( /* * No argument: List all group IDs and all syntax clusters. */ - for (int id = 1; id <= highlight_ga.ga_len && !got_int; ++id) { - syn_list_one(id, syncing, FALSE); + for (int id = 1; id <= highlight_ga.ga_len && !got_int; id++) { + syn_list_one(id, syncing, false); } for (int id = 0; id < curwin->w_s->b_syn_clusters.ga_len && !got_int; ++id) { syn_list_cluster(id); @@ -3511,10 +3497,11 @@ syn_cmd_list( syn_list_cluster(id - SYNID_CLUSTER); } else { int id = syn_namen2id(arg, (int)(arg_end - arg)); - if (id == 0) + if (id == 0) { EMSG2(_(e_nogroup), arg); - else - syn_list_one(id, syncing, TRUE); + } else { + syn_list_one(id, syncing, true); + } } arg = skipwhite(arg_end); } @@ -3558,14 +3545,12 @@ static int last_matchgroup; */ static void syn_list_one( - int id, - int syncing, /* when TRUE: list syncing items */ - int link_only /* when TRUE; list link-only too */ + const int id, + const bool syncing, // when true: list syncing items + const bool link_only // when true; list link-only too ) { - int attr; - int did_header = FALSE; - synpat_T *spp; + bool did_header = false; static struct name_list namelist1[] = { {HL_DISPLAY, "display"}, @@ -3588,23 +3573,26 @@ syn_list_one( {0, NULL} }; - attr = HL_ATTR(HLF_D); // highlight like directories + const int attr = HL_ATTR(HLF_D); // highlight like directories - /* list the keywords for "id" */ + // list the keywords for "id" if (!syncing) { - did_header = syn_list_keywords(id, &curwin->w_s->b_keywtab, FALSE, attr); + did_header = syn_list_keywords(id, &curwin->w_s->b_keywtab, false, attr); did_header = syn_list_keywords(id, &curwin->w_s->b_keywtab_ic, - did_header, attr); + did_header, attr); } - /* list the patterns for "id" */ - for (int idx = 0; idx < curwin->w_s->b_syn_patterns.ga_len && !got_int; ++idx) { - spp = &(SYN_ITEMS(curwin->w_s)[idx]); - if (spp->sp_syn.id != id || spp->sp_syncing != syncing) + // list the patterns for "id" + for (int idx = 0; + idx < curwin->w_s->b_syn_patterns.ga_len && !got_int; + idx++) { + const synpat_T *const spp = &(SYN_ITEMS(curwin->w_s)[idx]); + if (spp->sp_syn.id != id || spp->sp_syncing != syncing) { continue; + } (void)syn_list_header(did_header, 999, id); - did_header = TRUE; + did_header = true; last_matchgroup = 0; if (spp->sp_type == SPTYPE_MATCH) { put_pattern("match", ' ', spp, attr); @@ -3695,15 +3683,13 @@ static void syn_list_cluster(int id) } } -static void put_id_list(const char *name, - short *list, // NOLINT(runtime/int) - int attr) +static void put_id_list(const char *const name, + const int16_t *const list, + const int attr) { - short *p; - msg_puts_attr(name, attr); msg_putchar('='); - for (p = list; *p; ++p) { + for (const int16_t *p = list; *p; p++) { if (*p >= SYNID_ALLBUT && *p < SYNID_TOP) { if (p[1]) { msg_puts("ALLBUT"); @@ -3715,7 +3701,7 @@ static void put_id_list(const char *name, } else if (*p >= SYNID_CONTAINED && *p < SYNID_CLUSTER) { msg_puts("CONTAINED"); } else if (*p >= SYNID_CLUSTER) { - short scl_id = *p - SYNID_CLUSTER; + int scl_id = *p - SYNID_CLUSTER; msg_putchar('@'); msg_outtrans(SYN_CLSTR(curwin->w_s)[scl_id].scl_name); @@ -3727,12 +3713,10 @@ static void put_id_list(const char *name, msg_putchar(' '); } -static void put_pattern(char *s, int c, synpat_T *spp, int attr) +static void put_pattern(const char *const s, const int c, + const synpat_T *const spp, const int attr) { - long n; - int mask; - int first; - static char *sepchars = "/+=-#@\"|'^&"; + static const char *const sepchars = "/+=-#@\"|'^&"; int i; /* May have to write "matchgroup=group" */ @@ -3761,10 +3745,10 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr) msg_outtrans(spp->sp_pattern); msg_putchar(sepchars[i]); - /* output any pattern options */ - first = TRUE; - for (i = 0; i < SPO_COUNT; ++i) { - mask = (1 << i); + // output any pattern options + bool first = true; + for (i = 0; i < SPO_COUNT; i++) { + const int mask = (1 << i); if (!(spp->sp_off_flags & (mask + (mask << SPO_COUNT)))) { continue; } @@ -3772,7 +3756,7 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr) msg_putchar(','); // Separate with commas. } msg_puts(spo_name_tab[i]); - n = spp->sp_offsets[i]; + const long n = spp->sp_offsets[i]; if (i != SPO_LC_OFF) { if (spp->sp_off_flags & mask) msg_putchar('s'); @@ -3781,47 +3765,40 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr) if (n > 0) msg_putchar('+'); } - if (n || i == SPO_LC_OFF) + if (n || i == SPO_LC_OFF) { msg_outnum(n); - first = FALSE; + } + first = false; } msg_putchar(' '); } -/* - * List or clear the keywords for one syntax group. - * Return TRUE if the header has been printed. - */ -static int -syn_list_keywords( - int id, - hashtab_T *ht, - int did_header, /* header has already been printed */ - int attr +// List or clear the keywords for one syntax group. +// Return true if the header has been printed. +static bool syn_list_keywords( + const int id, + const hashtab_T *const ht, + bool did_header, // header has already been printed + const int attr ) { int outlen; - hashitem_T *hi; - keyentry_T *kp; - int todo; int prev_contained = 0; - short *prev_next_list = NULL; - short *prev_cont_in_list = NULL; + const int16_t *prev_next_list = NULL; + const int16_t *prev_cont_in_list = NULL; int prev_skipnl = 0; int prev_skipwhite = 0; int prev_skipempty = 0; - /* - * Unfortunately, this list of keywords is not sorted on alphabet but on - * hash value... - */ - todo = (int)ht->ht_used; - for (hi = ht->ht_array; todo > 0 && !got_int; ++hi) { + // Unfortunately, this list of keywords is not sorted on alphabet but on + // hash value... + size_t todo = ht->ht_used; + for (const hashitem_T *hi = ht->ht_array; todo > 0 && !got_int; hi++) { if (HASHITEM_EMPTY(hi)) { continue; } - --todo; - for (kp = HI2KE(hi); kp != NULL && !got_int; kp = kp->ke_next) { + todo--; + for (keyentry_T *kp = HI2KE(hi); kp != NULL && !got_int; kp = kp->ke_next) { if (kp->k_syn.id == id) { if (prev_contained != (kp->flags & HL_CONTAINED) || prev_skipnl != (kp->flags & HL_SKIPNL) @@ -3841,7 +3818,7 @@ syn_list_keywords( prev_skipwhite = 0; prev_skipempty = 0; } - did_header = TRUE; + did_header = true; if (prev_contained != (kp->flags & HL_CONTAINED)) { msg_puts_attr("contained", attr); msg_putchar(' '); @@ -3952,19 +3929,19 @@ static void clear_keywtab(hashtab_T *ht) /// @param flags flags for this keyword /// @param cont_in_list containedin for this keyword /// @param next_list nextgroup for this keyword -static void add_keyword(char_u *name, - int id, - int flags, - short *cont_in_list, - short *next_list, - int conceal_char) +static void add_keyword(char_u *const name, + const int id, + const int flags, + int16_t *const cont_in_list, + int16_t *const next_list, + const int conceal_char) { char_u name_folded[MAXKEYWLEN + 1]; - char_u *name_ic = (curwin->w_s->b_syn_ic) - ? str_foldcase(name, (int)STRLEN(name), name_folded, sizeof(name_folded)) - : name; + const char_u *const name_ic = (curwin->w_s->b_syn_ic) + ? str_foldcase(name, (int)STRLEN(name), name_folded, sizeof(name_folded)) + : name; - keyentry_T *kp = xmalloc(sizeof(keyentry_T) + STRLEN(name_ic)); + keyentry_T *const kp = xmalloc(sizeof(keyentry_T) + STRLEN(name_ic)); STRCPY(kp->keyword, name_ic); kp->k_syn.id = id; kp->k_syn.inc_tag = current_syn_inc_tag; @@ -3976,11 +3953,12 @@ static void add_keyword(char_u *name, } kp->next_list = copy_id_list(next_list); - hash_T hash = hash_hash(kp->keyword); - hashtab_T *ht = (curwin->w_s->b_syn_ic) ? &curwin->w_s->b_keywtab_ic - : &curwin->w_s->b_keywtab; - hashitem_T *hi = hash_lookup(ht, (const char *)kp->keyword, - STRLEN(kp->keyword), hash); + const hash_T hash = hash_hash(kp->keyword); + hashtab_T *const ht = (curwin->w_s->b_syn_ic) + ? &curwin->w_s->b_keywtab_ic + : &curwin->w_s->b_keywtab; + hashitem_T *const hi = hash_lookup(ht, (const char *)kp->keyword, + STRLEN(kp->keyword), hash); // even though it looks like only the kp->keyword member is // being used here, vim uses some pointer trickery to get the orignal @@ -4123,13 +4101,9 @@ get_syn_options( return NULL; } } else if (flagtab[fidx].argtype == 11 && arg[5] == '=') { - /* cchar=? */ - if (has_mbyte) { - *conceal_char = mb_ptr2char(arg + 6); - arg += mb_ptr2len(arg + 6) - 1; - } else { - *conceal_char = arg[6]; - } + // cchar=? + *conceal_char = utf_ptr2char(arg + 6); + arg += mb_ptr2len(arg + 6) - 1; if (!vim_isprintc_strict(*conceal_char)) { EMSG(_("E844: invalid cchar value")); return NULL; @@ -4191,8 +4165,8 @@ static void syn_incl_toplevel(int id, int *flagsp) return; *flagsp |= HL_CONTAINED; if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER) { - /* We have to alloc this, because syn_combine_list() will free it. */ - short *grp_list = xmalloc(2 * sizeof(short)); + // We have to alloc this, because syn_combine_list() will free it. + int16_t *grp_list = xmalloc(2 * sizeof(*grp_list)); int tlg_id = curwin->w_s->b_syn_topgrp - SYNID_CLUSTER; grp_list[0] = id; @@ -4407,9 +4381,9 @@ syn_cmd_match( /* Get options before the pattern */ syn_opt_arg.flags = 0; - syn_opt_arg.keyword = FALSE; + syn_opt_arg.keyword = false; syn_opt_arg.sync_idx = syncing ? &sync_idx : NULL; - syn_opt_arg.has_cont_list = TRUE; + syn_opt_arg.has_cont_list = true; syn_opt_arg.cont_list = NULL; syn_opt_arg.cont_in_list = NULL; syn_opt_arg.next_list = NULL; @@ -4529,9 +4503,9 @@ syn_cmd_region( init_syn_patterns(); syn_opt_arg.flags = 0; - syn_opt_arg.keyword = FALSE; + syn_opt_arg.keyword = false; syn_opt_arg.sync_idx = NULL; - syn_opt_arg.has_cont_list = TRUE; + syn_opt_arg.has_cont_list = true; syn_opt_arg.cont_list = NULL; syn_opt_arg.cont_in_list = NULL; syn_opt_arg.next_list = NULL; @@ -4709,30 +4683,25 @@ syn_cmd_region( } } -/* - * A simple syntax group ID comparison function suitable for use in qsort() - */ -static int syn_compare_stub(const void *v1, const void *v2) +// A simple syntax group ID comparison function suitable for use in qsort() +static int syn_compare_stub(const void *const v1, const void *const v2) { - const short *s1 = v1; - const short *s2 = v2; + const int16_t *const s1 = v1; + const int16_t *const s2 = v2; return *s1 > *s2 ? 1 : *s1 < *s2 ? -1 : 0; } -/* - * Combines lists of syntax clusters. - * *clstr1 and *clstr2 must both be allocated memory; they will be consumed. - */ -static void syn_combine_list(short **clstr1, short **clstr2, int list_op) +// Combines lists of syntax clusters. +// *clstr1 and *clstr2 must both be allocated memory; they will be consumed. +static void syn_combine_list(int16_t **const clstr1, int16_t **const clstr2, + const int list_op) { - int count1 = 0; - int count2 = 0; - short *g1; - short *g2; - short *clstr = NULL; - int count; - int round; + size_t count1 = 0; + size_t count2 = 0; + const int16_t *g1; + const int16_t *g2; + int16_t *clstr = NULL; /* * Handle degenerate cases. @@ -4749,27 +4718,25 @@ static void syn_combine_list(short **clstr1, short **clstr2, int list_op) return; } - for (g1 = *clstr1; *g1; g1++) - ++count1; - for (g2 = *clstr2; *g2; g2++) - ++count2; + for (g1 = *clstr1; *g1; g1++) { + count1++; + } + for (g2 = *clstr2; *g2; g2++) { + count2++; + } - /* - * For speed purposes, sort both lists. - */ - qsort(*clstr1, (size_t)count1, sizeof(short), syn_compare_stub); - qsort(*clstr2, (size_t)count2, sizeof(short), syn_compare_stub); + // For speed purposes, sort both lists. + qsort(*clstr1, count1, sizeof(**clstr1), syn_compare_stub); + qsort(*clstr2, count2, sizeof(**clstr2), syn_compare_stub); - /* - * We proceed in two passes; in round 1, we count the elements to place - * in the new list, and in round 2, we allocate and populate the new - * list. For speed, we use a mergesort-like method, adding the smaller - * of the current elements in each list to the new list. - */ - for (round = 1; round <= 2; round++) { + // We proceed in two passes; in round 1, we count the elements to place + // in the new list, and in round 2, we allocate and populate the new + // list. For speed, we use a mergesort-like method, adding the smaller + // of the current elements in each list to the new list. + for (int round = 1; round <= 2; round++) { g1 = *clstr1; g2 = *clstr2; - count = 0; + int count = 0; /* * First, loop through the lists until one of them is empty. @@ -4821,7 +4788,7 @@ static void syn_combine_list(short **clstr1, short **clstr2, int list_op) clstr = NULL; break; } - clstr = xmalloc((count + 1) * sizeof(short)); + clstr = xmalloc((count + 1) * sizeof(*clstr)); clstr[count] = 0; } } @@ -4926,9 +4893,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing) char_u *arg = eap->arg; char_u *group_name_end; char_u *rest; - int scl_id; - short *clstr_list; - int got_clstr = FALSE; + bool got_clstr = false; int opt_len; int list_op; @@ -4939,9 +4904,10 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing) rest = get_group_name(arg, &group_name_end); if (rest != NULL) { - scl_id = syn_check_cluster(arg, (int)(group_name_end - arg)); - if (scl_id == 0) + int scl_id = syn_check_cluster(arg, (int)(group_name_end - arg)); + if (scl_id == 0) { return; + } scl_id -= SYNID_CLUSTER; for (;; ) { @@ -4960,7 +4926,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing) } else break; - clstr_list = NULL; + int16_t *clstr_list = NULL; if (get_id_list(&rest, opt_len, &clstr_list, eap->skip) == FAIL) { EMSG2(_(e_invarg2), rest); break; @@ -5218,35 +5184,28 @@ static void syn_cmd_sync(exarg_T *eap, int syncing) */ static int get_id_list( - char_u **arg, - int keylen, // length of keyword - int16_t **list, // where to store the resulting list, if not - // NULL, the list is silently skipped! - int skip + char_u **const arg, + const int keylen, // length of keyword + int16_t **const list, // where to store the resulting list, if not + // NULL, the list is silently skipped! + const bool skip ) { char_u *p = NULL; char_u *end; - int round; - int count; int total_count = 0; - short *retval = NULL; - char_u *name; + int16_t *retval = NULL; regmatch_T regmatch; int id; - int failed = FALSE; - - /* - * We parse the list twice: - * round == 1: count the number of items, allocate the array. - * round == 2: fill the array with the items. - * In round 1 new groups may be added, causing the number of items to - * grow when a regexp is used. In that case round 1 is done once again. - */ - for (round = 1; round <= 2; ++round) { - /* - * skip "contains" - */ + bool failed = false; + + // We parse the list twice: + // round == 1: count the number of items, allocate the array. + // round == 2: fill the array with the items. + // In round 1 new groups may be added, causing the number of items to + // grow when a regexp is used. In that case round 1 is done once again. + for (int round = 1; round <= 2; round++) { + // skip "contains" p = skipwhite(*arg + keylen); if (*p != '=') { EMSG2(_("E405: Missing equal sign: %s"), *arg); @@ -5258,14 +5217,12 @@ get_id_list( break; } - /* - * parse the arguments after "contains" - */ - count = 0; + // parse the arguments after "contains" + int count = 0; do { - for (end = p; *end && !ascii_iswhite(*end) && *end != ','; ++end) - ; - name = xmalloc((int)(end - p + 3)); /* leave room for "^$" */ + for (end = p; *end && !ascii_iswhite(*end) && *end != ','; end++) { + } + char_u *const name = xmalloc((int)(end - p + 3)); // leave room for "^$" STRLCPY(name + 1, p, end - p + 1); if ( STRCMP(name + 1, "ALLBUT") == 0 || STRCMP(name + 1, "ALL") == 0 @@ -5273,7 +5230,7 @@ get_id_list( || STRCMP(name + 1, "CONTAINED") == 0) { if (TOUPPER_ASC(**arg) != 'C') { EMSG2(_("E407: %s not allowed here"), name + 1); - failed = TRUE; + failed = true; xfree(name); break; } @@ -5309,7 +5266,7 @@ get_id_list( STRCAT(name, "$"); regmatch.regprog = vim_regcomp(name, RE_MAGIC); if (regmatch.regprog == NULL) { - failed = TRUE; + failed = true; xfree(name); break; } @@ -5340,7 +5297,7 @@ get_id_list( xfree(name); if (id == 0) { EMSG2(_("E409: Unknown group name: %s"), p); - failed = TRUE; + failed = true; break; } if (id > 0) { @@ -5363,8 +5320,8 @@ get_id_list( if (failed) break; if (round == 1) { - retval = xmalloc((count + 1) * sizeof(short)); - retval[count] = 0; /* zero means end of the list */ + retval = xmalloc((count + 1) * sizeof(*retval)); + retval[count] = 0; // zero means end of the list total_count = count; } } @@ -5386,20 +5343,18 @@ get_id_list( /* * Make a copy of an ID list. */ -static short *copy_id_list(short *list) +static int16_t *copy_id_list(const int16_t *const list) { - int len; - int count; - short *retval; - - if (list == NULL) + if (list == NULL) { return NULL; + } - for (count = 0; list[count]; ++count) - ; - len = (count + 1) * sizeof(short); - retval = xmalloc(len); - memmove(retval, list, (size_t)len); + int count; + for (count = 0; list[count]; count++) { + } + const size_t len = (count + 1) * sizeof(int16_t); + int16_t *const retval = xmalloc(len); + memmove(retval, list, len); return retval; } @@ -6385,6 +6340,90 @@ int load_colors(char_u *name) return retval; } +static char *(color_names[28]) = { + "Black", "DarkBlue", "DarkGreen", "DarkCyan", + "DarkRed", "DarkMagenta", "Brown", "DarkYellow", + "Gray", "Grey", "LightGray", "LightGrey", + "DarkGray", "DarkGrey", + "Blue", "LightBlue", "Green", "LightGreen", + "Cyan", "LightCyan", "Red", "LightRed", "Magenta", + "LightMagenta", "Yellow", "LightYellow", "White", "NONE" }; + // indices: + // 0, 1, 2, 3, + // 4, 5, 6, 7, + // 8, 9, 10, 11, + // 12, 13, + // 14, 15, 16, 17, + // 18, 19, 20, 21, 22, + // 23, 24, 25, 26, 27 +static int color_numbers_16[28] = { 0, 1, 2, 3, + 4, 5, 6, 6, + 7, 7, 7, 7, + 8, 8, + 9, 9, 10, 10, + 11, 11, 12, 12, 13, + 13, 14, 14, 15, -1 }; +// for xterm with 88 colors... +static int color_numbers_88[28] = { 0, 4, 2, 6, + 1, 5, 32, 72, + 84, 84, 7, 7, + 82, 82, + 12, 43, 10, 61, + 14, 63, 9, 74, 13, + 75, 11, 78, 15, -1 }; +// for xterm with 256 colors... +static int color_numbers_256[28] = { 0, 4, 2, 6, + 1, 5, 130, 130, + 248, 248, 7, 7, + 242, 242, + 12, 81, 10, 121, + 14, 159, 9, 224, 13, + 225, 11, 229, 15, -1 }; +// for terminals with less than 16 colors... +static int color_numbers_8[28] = { 0, 4, 2, 6, + 1, 5, 3, 3, + 7, 7, 7, 7, + 0+8, 0+8, + 4+8, 4+8, 2+8, 2+8, + 6+8, 6+8, 1+8, 1+8, 5+8, + 5+8, 3+8, 3+8, 7+8, -1 }; + +// Lookup the "cterm" value to be used for color with index "idx" in +// color_names[]. +// "boldp" will be set to TRUE or FALSE for a foreground color when using 8 +// colors, otherwise it will be unchanged. +int lookup_color(const int idx, const bool foreground, TriState *const boldp) +{ + int color = color_numbers_16[idx]; + + // Use the _16 table to check if it's a valid color name. + if (color < 0) { + return -1; + } + + if (t_colors == 8) { + // t_Co is 8: use the 8 colors table + color = color_numbers_8[idx]; + if (foreground) { + // set/reset bold attribute to get light foreground + // colors (on some terminals, e.g. "linux") + if (color & 8) { + *boldp = kTrue; + } else { + *boldp = kFalse; + } + } + color &= 7; // truncate to 8 colors + } else if (t_colors == 16) { + color = color_numbers_8[idx]; + } else if (t_colors == 88) { + color = color_numbers_88[idx]; + } else if (t_colors >= 256) { + color = color_numbers_256[idx]; + } + return color; +} + /// Handle ":highlight" command /// @@ -6408,12 +6447,14 @@ void do_highlight(const char *line, const bool forceit, const bool init) int attr; int id; int idx; - int dodefault = FALSE; - int doclear = FALSE; - int dolink = FALSE; - int error = FALSE; + struct hl_group item_before; + bool dodefault = false; + bool doclear = false; + bool dolink = false; + bool error = false; int color; bool is_normal_group = false; // "Normal" group + bool did_highlight_changed = false; // If no argument, list current highlighting. if (ends_excmd((uint8_t)(*line))) { @@ -6496,19 +6537,22 @@ void do_highlight(const char *line, const bool forceit, const bool init) if (sourcing_name == NULL && !dodefault) { EMSG(_("E414: group has settings, highlight link ignored")); } - } else { - if (!init) + } else if (HL_TABLE()[from_id - 1].sg_link != to_id + || HL_TABLE()[from_id - 1].sg_scriptID != current_SID + || HL_TABLE()[from_id - 1].sg_cleared) { + if (!init) { HL_TABLE()[from_id - 1].sg_set |= SG_LINK; + } HL_TABLE()[from_id - 1].sg_link = to_id; HL_TABLE()[from_id - 1].sg_scriptID = current_SID; HL_TABLE()[from_id - 1].sg_cleared = false; redraw_all_later(SOME_VALID); + + // Only call highlight changed() once after multiple changes + need_highlight_changed = true; } } - // Only call highlight_changed() once, after sourcing a syntax file. - need_highlight_changed = true; - return; } @@ -6544,13 +6588,16 @@ void do_highlight(const char *line, const bool forceit, const bool init) return; } + // Make a copy so we can check if any attribute actually changed + item_before = HL_TABLE()[idx]; is_normal_group = (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0); // Clear the highlighting for ":hi clear {group}" and ":hi clear". if (doclear || (forceit && init)) { highlight_clear(idx); - if (!doclear) + if (!doclear) { HL_TABLE()[idx].sg_set = 0; + } } char *key = NULL; @@ -6651,7 +6698,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) HL_TABLE()[idx].sg_set |= SG_CTERM; } HL_TABLE()[idx].sg_cterm = attr; - HL_TABLE()[idx].sg_cterm_bold = FALSE; + HL_TABLE()[idx].sg_cterm_bold = false; } } else if (*key == 'G') { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) { @@ -6673,7 +6720,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) * flag was set for a light color, reset it now */ if (key[5] == 'F' && HL_TABLE()[idx].sg_cterm_bold) { HL_TABLE()[idx].sg_cterm &= ~HL_BOLD; - HL_TABLE()[idx].sg_cterm_bold = FALSE; + HL_TABLE()[idx].sg_cterm_bold = false; } if (ascii_isdigit(*arg)) { @@ -6695,60 +6742,6 @@ void do_highlight(const char *line, const bool forceit, const bool init) break; } } else { - static const char *color_names[] = { - "Black", "DarkBlue", "DarkGreen", "DarkCyan", - "DarkRed", "DarkMagenta", "Brown", "DarkYellow", - "Gray", "Grey", - "LightGray", "LightGrey", "DarkGray", "DarkGrey", - "Blue", "LightBlue", "Green", "LightGreen", - "Cyan", "LightCyan", "Red", "LightRed", "Magenta", - "LightMagenta", "Yellow", "LightYellow", "White", - "NONE" - }; - static const int color_numbers_16[] = { - 0, 1, 2, 3, - 4, 5, 6, 6, - 7, 7, - 7, 7, 8, 8, - 9, 9, 10, 10, - 11, 11, 12, 12, 13, - 13, 14, 14, 15, - -1 - }; - // For xterm with 88 colors: - static int color_numbers_88[] = { - 0, 4, 2, 6, - 1, 5, 32, 72, - 84, 84, - 7, 7, 82, 82, - 12, 43, 10, 61, - 14, 63, 9, 74, 13, - 75, 11, 78, 15, - -1 - }; - // For xterm with 256 colors: - static int color_numbers_256[] = { - 0, 4, 2, 6, - 1, 5, 130, 130, - 248, 248, - 7, 7, 242, 242, - 12, 81, 10, 121, - 14, 159, 9, 224, 13, - 225, 11, 229, 15, - -1 - }; - // For terminals with less than 16 colors: - static int color_numbers_8[28] = { - 0, 4, 2, 6, - 1, 5, 3, 3, - 7, 7, - 7, 7, 0+8, 0+8, - 4+8, 4+8, 2+8, 2+8, - 6+8, 6+8, 1+8, 1+8, 5+8, - 5+8, 3+8, 3+8, 7+8, - -1 - }; - // Reduce calls to STRICMP a bit, it can be slow. off = TOUPPER_ASC(*arg); for (i = ARRAY_SIZE(color_names); --i >= 0; ) { @@ -6764,32 +6757,16 @@ void do_highlight(const char *line, const bool forceit, const bool init) break; } - // Use the _16 table to check if it's a valid color name. - color = color_numbers_16[i]; - if (color >= 0) { - if (t_colors == 8) { - // t_Co is 8: use the 8 colors table. - color = color_numbers_8[i]; - if (key[5] == 'F') { - /* set/reset bold attribute to get light foreground - * colors (on some terminals, e.g. "linux") */ - if (color & 8) { - HL_TABLE()[idx].sg_cterm |= HL_BOLD; - HL_TABLE()[idx].sg_cterm_bold = true; - } else { - HL_TABLE()[idx].sg_cterm &= ~HL_BOLD; - } - } - color &= 7; // truncate to 8 colors - } else if (t_colors == 16 || t_colors == 88 || t_colors >= 256) { - if (t_colors == 88) { - color = color_numbers_88[i]; - } else if (t_colors >= 256) { - color = color_numbers_256[i]; - } else { - color = color_numbers_8[i]; - } - } + TriState bold = kNone; + color = lookup_color(i, key[5] == 'F', &bold); + + // set/reset bold attribute to get light foreground + // colors (on some terminals, e.g. "linux") + if (bold == kTrue) { + HL_TABLE()[idx].sg_cterm |= HL_BOLD; + HL_TABLE()[idx].sg_cterm_bold = true; + } else if (bold == kFalse) { + HL_TABLE()[idx].sg_cterm &= ~HL_BOLD; } } // Add one to the argument, to avoid zero. Zero is used for @@ -6828,8 +6805,9 @@ void do_highlight(const char *line, const bool forceit, const bool init) } } else if (strcmp(key, "GUIFG") == 0) { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) { - if (!init) + if (!init) { HL_TABLE()[idx].sg_set |= SG_GUI; + } xfree(HL_TABLE()[idx].sg_rgb_fg_name); if (strcmp(arg, "NONE")) { @@ -6846,8 +6824,9 @@ void do_highlight(const char *line, const bool forceit, const bool init) } } else if (STRCMP(key, "GUIBG") == 0) { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) { - if (!init) + if (!init) { HL_TABLE()[idx].sg_set |= SG_GUI; + } xfree(HL_TABLE()[idx].sg_rgb_bg_name); if (STRCMP(arg, "NONE") != 0) { @@ -6864,8 +6843,9 @@ void do_highlight(const char *line, const bool forceit, const bool init) } } else if (strcmp(key, "GUISP") == 0) { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) { - if (!init) + if (!init) { HL_TABLE()[idx].sg_set |= SG_GUI; + } xfree(HL_TABLE()[idx].sg_rgb_sp_name); if (strcmp(arg, "NONE") != 0) { @@ -6917,17 +6897,23 @@ void do_highlight(const char *line, const bool forceit, const bool init) // redraw below will still handle usages of guibg=fg etc. ui_default_colors_set(); } + did_highlight_changed = true; + redraw_all_later(NOT_VALID); } else { set_hl_attr(idx); } HL_TABLE()[idx].sg_scriptID = current_SID; - redraw_all_later(NOT_VALID); } xfree(key); xfree(arg); - // Only call highlight_changed() once, after sourcing a syntax file - need_highlight_changed = true; + // Only call highlight_changed() once, after a sequence of highlight + // commands, and only if an attribute actually changed + if (memcmp(&HL_TABLE()[idx], &item_before, sizeof(item_before)) != 0 + && !did_highlight_changed) { + redraw_all_later(NOT_VALID); + need_highlight_changed = true; + } } #if defined(EXITFREE) @@ -6980,7 +6966,7 @@ static void highlight_clear(int idx) HL_TABLE()[idx].sg_attr = 0; HL_TABLE()[idx].sg_cterm = 0; - HL_TABLE()[idx].sg_cterm_bold = FALSE; + HL_TABLE()[idx].sg_cterm_bold = false; HL_TABLE()[idx].sg_cterm_fg = 0; HL_TABLE()[idx].sg_cterm_bg = 0; HL_TABLE()[idx].sg_gui = 0; @@ -7008,12 +6994,10 @@ static void highlight_clear(int idx) #define LIST_INT 3 /// @} -static void highlight_list_one(int id) +static void highlight_list_one(const int id) { - struct hl_group *sgp; - int didh = FALSE; - - sgp = &HL_TABLE()[id - 1]; /* index is ID minus one */ + struct hl_group *const sgp = &HL_TABLE()[id - 1]; // index is ID minus one + bool didh = false; didh = highlight_list_arg(id, didh, LIST_ATTR, sgp->sg_cterm, NULL, "cterm"); @@ -7050,24 +7034,24 @@ static void highlight_list_one(int id) /// @param type one of \ref LIST_XXX /// @param iarg integer argument used if \p type == LIST_INT /// @param sarg string used if \p type == LIST_STRING -static int highlight_list_arg(int id, int didh, int type, int iarg, - char_u *sarg, const char *name) +static bool highlight_list_arg( + const int id, bool didh, const int type, int iarg, + char_u *const sarg, const char *const name) { char_u buf[100]; - char_u *ts; - int i; - if (got_int) - return FALSE; + if (got_int) { + return false; + } if (type == LIST_STRING ? (sarg != NULL) : (iarg != 0)) { - ts = buf; - if (type == LIST_INT) - sprintf((char *)buf, "%d", iarg - 1); - else if (type == LIST_STRING) + char_u *ts = buf; + if (type == LIST_INT) { + snprintf((char *)buf, sizeof(buf), "%d", iarg - 1); + } else if (type == LIST_STRING) { ts = sarg; - else { /* type == LIST_ATTR */ + } else { // type == LIST_ATTR buf[0] = NUL; - for (i = 0; hl_attr_table[i] != 0; ++i) { + for (int i = 0; hl_attr_table[i] != 0; i++) { if (iarg & hl_attr_table[i]) { if (buf[0] != NUL) xstrlcat((char *)buf, ",", 100); @@ -7077,9 +7061,8 @@ static int highlight_list_arg(int id, int didh, int type, int iarg, } } - (void)syn_list_header(didh, - (int)(vim_strsize(ts) + STRLEN(name) + 1), id); - didh = TRUE; + (void)syn_list_header(didh, (int)(vim_strsize(ts) + STRLEN(name) + 1), id); + didh = true; if (!got_int) { if (*name != NUL) { MSG_PUTS_ATTR(name, HL_ATTR(HLF_D)); @@ -7197,11 +7180,11 @@ const char *highlight_color(const int id, const char *const what, /// @param outlen length of string that comes /// @param id highlight group id /// @return true when started a new line. -static int -syn_list_header(int did_header, int outlen, int id) +static bool syn_list_header(const bool did_header, const int outlen, + const int id) { int endcol = 19; - int newline = TRUE; + bool newline = true; if (!did_header) { msg_putchar('\n'); @@ -7212,11 +7195,13 @@ syn_list_header(int did_header, int outlen, int id) endcol = 15; } else if (msg_col + outlen + 1 >= Columns) { msg_putchar('\n'); - if (got_int) - return TRUE; + if (got_int) { + return true; + } } else { - if (msg_col >= endcol) /* wrap around is like starting a new line */ - newline = FALSE; + if (msg_col >= endcol) { // wrap around is like starting a new line + newline = false; + } } if (msg_col >= endcol) /* output at least one space */ diff --git a/src/nvim/syntax.h b/src/nvim/syntax.h index f8282955a6..9fbad74f64 100644 --- a/src/nvim/syntax.h +++ b/src/nvim/syntax.h @@ -3,6 +3,7 @@ #include <stdbool.h> +#include "nvim/globals.h" #include "nvim/buffer_defs.h" #include "nvim/ex_cmds_defs.h" diff --git a/src/nvim/syntax_defs.h b/src/nvim/syntax_defs.h index 63089a62af..5ee0611d58 100644 --- a/src/nvim/syntax_defs.h +++ b/src/nvim/syntax_defs.h @@ -14,13 +14,11 @@ typedef struct syn_state synstate_T; #include "nvim/buffer_defs.h" #include "nvim/regexp_defs.h" -typedef unsigned short disptick_T; /* display tick type */ - /* struct passed to in_id_list() */ struct sp_syn { - int inc_tag; /* ":syn include" unique tag */ - short id; /* highlight group ID of item */ - short *cont_in_list; /* cont.in group IDs, if non-zero */ + int inc_tag; // ":syn include" unique tag + int16_t id; // highlight group ID of item + int16_t *cont_in_list; // cont.in group IDs, if non-zero }; /* @@ -29,12 +27,12 @@ struct sp_syn { typedef struct keyentry keyentry_T; struct keyentry { - keyentry_T *ke_next; /* next entry with identical "keyword[]" */ - struct sp_syn k_syn; /* struct passed to in_id_list() */ - short *next_list; /* ID list for next match (if non-zero) */ + keyentry_T *ke_next; // next entry with identical "keyword[]" + struct sp_syn k_syn; // struct passed to in_id_list() + int16_t *next_list; // ID list for next match (if non-zero) int flags; - int k_char; /* conceal substitute character */ - char_u keyword[1]; /* actually longer */ + int k_char; // conceal substitute character + char_u keyword[1]; // actually longer }; /* @@ -59,13 +57,13 @@ struct syn_state { bufstate_T sst_stack[SST_FIX_STATES]; /* short state stack */ garray_T sst_ga; /* growarray for long state stack */ } sst_union; - int sst_next_flags; /* flags for sst_next_list */ - int sst_stacksize; /* number of states on the stack */ - short *sst_next_list; /* "nextgroup" list in this state - * (this is a copy, don't free it! */ - disptick_T sst_tick; /* tick when last displayed */ - linenr_T sst_change_lnum; /* when non-zero, change in this line - * may have made the state invalid */ + int sst_next_flags; // flags for sst_next_list + int sst_stacksize; // number of states on the stack + int16_t *sst_next_list; // "nextgroup" list in this state + // (this is a copy, don't free it! + disptick_T sst_tick; // tick when last displayed + linenr_T sst_change_lnum; // when non-zero, change in this line + // may have made the state invalid }; #endif // NVIM_SYNTAX_DEFS_H diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 0379235ec0..361db47fc7 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -60,12 +60,14 @@ NEW_TESTS ?= \ test_fnameescape.res \ test_fold.res \ test_ga.res \ + test_getvar.res \ test_glob2regpat.res \ test_gf.res \ test_gn.res \ test_hardcopy.res \ test_help_tagjump.res \ test_hide.res \ + test_highlight.res \ test_history.res \ test_hlsearch.res \ test_increment.res \ diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index 8014b76af7..44c01cfeff 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -243,6 +243,7 @@ let s:flaky = [ \ 'Test_quoteplus()', \ 'Test_quotestar()', \ 'Test_reltime()', + \ 'Test_repeat_three()', \ 'Test_terminal_composing_unicode()', \ 'Test_terminal_redir_file()', \ 'Test_terminal_tmap()', diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim index f3cc7da70f..51bf8ce0fc 100644 --- a/src/nvim/testdir/setup.vim +++ b/src/nvim/testdir/setup.vim @@ -33,4 +33,5 @@ if has('win32') let $TERM = '' let &shell = empty($COMSPEC) ? exepath('cmd.exe') : $COMSPEC set shellcmdflag=/s/c shellxquote=\" shellredir=>%s\ 2>&1 + let &shellpipe = &shellredir endif diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index d026221dac..238dbe8d90 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -4,6 +4,7 @@ source test_assign.vim source test_cd.vim source test_changedtick.vim +source test_compiler.vim source test_cursor_func.vim source test_ex_undo.vim source test_ex_z.vim diff --git a/src/nvim/testdir/test_compiler.vim b/src/nvim/testdir/test_compiler.vim new file mode 100644 index 0000000000..84fba0f9a4 --- /dev/null +++ b/src/nvim/testdir/test_compiler.vim @@ -0,0 +1,49 @@ +" Test the :compiler command + +func Test_compiler() + if !executable('perl') + return + endif + + e Xfoo.pl + compiler perl + call assert_equal('perl', b:current_compiler) + call assert_fails('let g:current_compiler', 'E121:') + + call setline(1, ['#!/usr/bin/perl -w', 'use strict;', 'my $foo=1']) + w! + call feedkeys(":make\<CR>\<CR>", 'tx') + call assert_fails('clist', 'E42:') + + call setline(1, ['#!/usr/bin/perl -w', 'use strict;', '$foo=1']) + w! + call feedkeys(":make\<CR>\<CR>", 'tx') + let a=execute('clist') + call assert_match("\n 1 Xfoo.pl:3: Global symbol \"\$foo\" " + \ . "requires explicit package name", a) + + call delete('Xfoo.pl') + bw! +endfunc + +func Test_compiler_without_arg() + let a=split(execute('compiler')) + call assert_match(expand('^.*runtime/compiler/ant.vim$'), a[0]) + call assert_match(expand('^.*runtime/compiler/bcc.vim$'), a[1]) + call assert_match(expand('^.*runtime/compiler/xmlwf.vim$'), a[-1]) +endfunc + +func Test_compiler_completion() + call feedkeys(":compiler \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_match('^"compiler ant bcc .* xmlwf$', @:) + + call feedkeys(":compiler p\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"compiler pbx perl php pylint pyunit', @:) + + call feedkeys(":compiler! p\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"compiler! pbx perl php pylint pyunit', @:) +endfunc + +func Test_compiler_error() + call assert_fails('compiler doesnotexist', 'E666:') +endfunc diff --git a/src/nvim/testdir/test_getvar.vim b/src/nvim/testdir/test_getvar.vim new file mode 100644 index 0000000000..d6b6b69aa8 --- /dev/null +++ b/src/nvim/testdir/test_getvar.vim @@ -0,0 +1,104 @@ +" Tests for getwinvar(), gettabvar() and gettabwinvar(). +func Test_var() + " Use strings to test for memory leaks. First, check that in an empty + " window, gettabvar() returns the correct value + let t:testvar='abcd' + call assert_equal('abcd', gettabvar(1, 'testvar')) + call assert_equal('abcd', gettabvar(1, 'testvar')) + + " test for getwinvar() + let w:var_str = "Dance" + let def_str = "Chance" + call assert_equal('Dance', getwinvar(1, 'var_str')) + call assert_equal('Dance', getwinvar(1, 'var_str', def_str)) + call assert_equal({'var_str': 'Dance'}, getwinvar(1, '')) + call assert_equal({'var_str': 'Dance'}, getwinvar(1, '', def_str)) + unlet w:var_str + call assert_equal('Chance', getwinvar(1, 'var_str', def_str)) + call assert_equal({}, getwinvar(1, '')) + call assert_equal({}, getwinvar(1, '', def_str)) + call assert_equal('', getwinvar(9, '')) + call assert_equal('Chance', getwinvar(9, '', def_str)) + call assert_equal(0, getwinvar(1, '&nu')) + call assert_equal(0, getwinvar(1, '&nu', 1)) + unlet def_str + + " test for gettabvar() + tabnew + tabnew + let t:var_list = [1, 2, 3] + let t:other = 777 + let def_list = [4, 5, 6, 7] + tabrewind + call assert_equal([1, 2, 3], gettabvar(3, 'var_list')) + call assert_equal([1, 2, 3], gettabvar(3, 'var_list', def_list)) + call assert_equal({'var_list': [1, 2, 3], 'other': 777}, gettabvar(3, '')) + call assert_equal({'var_list': [1, 2, 3], 'other': 777}, + \ gettabvar(3, '', def_list)) + + tablast + unlet t:var_list + tabrewind + call assert_equal([4, 5, 6, 7], gettabvar(3, 'var_list', def_list)) + call assert_equal('', gettabvar(9, '')) + call assert_equal([4, 5, 6, 7], gettabvar(9, '', def_list)) + call assert_equal('', gettabvar(3, '&nu')) + call assert_equal([4, 5, 6, 7], gettabvar(3, '&nu', def_list)) + unlet def_list + tabonly + + " test for gettabwinvar() + tabnew + tabnew + tabprev + split + split + wincmd w + vert split + wincmd w + let w:var_dict = {'dict': 'tabwin'} + let def_dict = {'dict2': 'newval'} + wincmd b + tabrewind + call assert_equal({'dict': 'tabwin'}, gettabwinvar(2, 3, 'var_dict')) + call assert_equal({'dict': 'tabwin'}, + \ gettabwinvar(2, 3, 'var_dict', def_dict)) + call assert_equal({'var_dict': {'dict': 'tabwin'}}, gettabwinvar(2, 3, '')) + call assert_equal({'var_dict': {'dict': 'tabwin'}}, + \ gettabwinvar(2, 3, '', def_dict)) + + tabnext + 3wincmd w + unlet w:var_dict + tabrewind + call assert_equal({'dict2': 'newval'}, + \ gettabwinvar(2, 3, 'var_dict', def_dict)) + call assert_equal({}, gettabwinvar(2, 3, '')) + call assert_equal({}, gettabwinvar(2, 3, '', def_dict)) + call assert_equal("", gettabwinvar(2, 9, '')) + call assert_equal({'dict2': 'newval'}, gettabwinvar(2, 9, '', def_dict)) + call assert_equal('', gettabwinvar(9, 3, '')) + call assert_equal({'dict2': 'newval'}, gettabwinvar(9, 3, '', def_dict)) + + unlet def_dict + + call assert_equal('', gettabwinvar(2, 3, '&nux')) + call assert_equal(1, gettabwinvar(2, 3, '&nux', 1)) + tabonly +endfunc + +" It was discovered that "gettabvar()" would fail if called from within the +" tabline when the user closed a window. This test confirms the fix. +func Test_gettabvar_in_tabline() + let t:var_str = 'value' + + set tabline=%{assert_equal('value',gettabvar(1,'var_str'))} + set showtabline=2 + + " Simulate the user opening a split (which becomes window #1) and then + " closing the split, which triggers the redrawing of the tabline. + leftabove split + redrawstatus! + close + redrawstatus! +endfunc diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim new file mode 100644 index 0000000000..33df79581c --- /dev/null +++ b/src/nvim/testdir/test_highlight.vim @@ -0,0 +1,535 @@ +" Tests for ":highlight" and highlighting. + +source view_util.vim + +func Test_highlight() + " basic test if ":highlight" doesn't crash + highlight + hi Search + + " test setting colors. + " test clearing one color and all doesn't generate error or warning + silent! hi NewGroup term=bold cterm=italic ctermfg=DarkBlue ctermbg=Grey gui= guifg=#00ff00 guibg=Cyan + silent! hi Group2 term= cterm= + hi Group3 term=underline cterm=bold + + let res = split(execute("hi NewGroup"), "\n")[0] + " filter ctermfg and ctermbg, the numbers depend on the terminal + let res = substitute(res, 'ctermfg=\d*', 'ctermfg=2', '') + let res = substitute(res, 'ctermbg=\d*', 'ctermbg=3', '') + call assert_equal("NewGroup xxx cterm=italic ctermfg=2 ctermbg=3", + \ res) + call assert_equal("Group2 xxx cleared", + \ split(execute("hi Group2"), "\n")[0]) + call assert_equal("Group3 xxx cterm=bold", + \ split(execute("hi Group3"), "\n")[0]) + + hi clear NewGroup + call assert_equal("NewGroup xxx cleared", + \ split(execute("hi NewGroup"), "\n")[0]) + call assert_equal("Group2 xxx cleared", + \ split(execute("hi Group2"), "\n")[0]) + hi Group2 NONE + call assert_equal("Group2 xxx cleared", + \ split(execute("hi Group2"), "\n")[0]) + hi clear + call assert_equal("Group3 xxx cleared", + \ split(execute("hi Group3"), "\n")[0]) + call assert_fails("hi Crash term='asdf", "E475:") +endfunc + +function! HighlightArgs(name) + return 'hi ' . substitute(split(execute('hi ' . a:name), '\n')[0], '\<xxx\>', '', '') +endfunction + +function! IsColorable() + return has('gui_running') || str2nr(&t_Co) >= 8 +endfunction + +function! HiCursorLine() + let hiCursorLine = HighlightArgs('CursorLine') + if has('gui_running') + let guibg = matchstr(hiCursorLine, 'guibg=\w\+') + let hi_ul = 'hi CursorLine gui=underline guibg=NONE' + let hi_bg = 'hi CursorLine gui=NONE ' . guibg + else + let hi_ul = 'hi CursorLine cterm=underline ctermbg=NONE' + let hi_bg = 'hi CursorLine cterm=NONE ctermbg=Gray' + endif + return [hiCursorLine, hi_ul, hi_bg] +endfunction + +function! Check_lcs_eol_attrs(attrs, row, col) + let save_lcs = &lcs + set list + + call assert_equal(a:attrs, ScreenAttrs(a:row, a:col)[0]) + + set nolist + let &lcs = save_lcs +endfunction + +func Test_highlight_eol_with_cursorline() + let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine() + + call NewWindow('topleft 5', 20) + call setline(1, 'abcd') + call matchadd('Search', '\n') + + " expected: + " 'abcd ' + " ^^^^ ^^^^^ no highlight + " ^ 'Search' highlight + let attrs0 = ScreenAttrs(1, 10)[0] + call assert_equal(repeat([attrs0[0]], 4), attrs0[0:3]) + call assert_equal(repeat([attrs0[0]], 5), attrs0[5:9]) + call assert_notequal(attrs0[0], attrs0[4]) + + setlocal cursorline + + " underline + exe hi_ul + + " expected: + " 'abcd ' + " ^^^^ underline + " ^ 'Search' highlight with underline + " ^^^^^ underline + let attrs = ScreenAttrs(1, 10)[0] + call assert_equal(repeat([attrs[0]], 4), attrs[0:3]) + call assert_equal([attrs[4]] + repeat([attrs[5]], 5), attrs[4:9]) + call assert_notequal(attrs[0], attrs[4]) + call assert_notequal(attrs[4], attrs[5]) + call assert_notequal(attrs0[0], attrs[0]) + call assert_notequal(attrs0[4], attrs[4]) + call Check_lcs_eol_attrs(attrs, 1, 10) + + if IsColorable() + " bg-color + exe hi_bg + + " expected: + " 'abcd ' + " ^^^^ bg-color of 'CursorLine' + " ^ 'Search' highlight + " ^^^^^ bg-color of 'CursorLine' + let attrs = ScreenAttrs(1, 10)[0] + call assert_equal(repeat([attrs[0]], 4), attrs[0:3]) + call assert_equal(repeat([attrs[5]], 5), attrs[5:9]) + call assert_equal(attrs0[4], attrs[4]) + call assert_notequal(attrs[0], attrs[4]) + call assert_notequal(attrs[4], attrs[5]) + call assert_notequal(attrs0[0], attrs[0]) + call assert_notequal(attrs0[5], attrs[5]) + call Check_lcs_eol_attrs(attrs, 1, 10) + endif + + call CloseWindow() + exe hiCursorLine +endfunc + +func Test_highlight_eol_with_cursorline_vertsplit() + if !has('vertsplit') + return + endif + + let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine() + + call NewWindow('topleft 5', 5) + call setline(1, 'abcd') + call matchadd('Search', '\n') + + let expected = "abcd |abcd " + let actual = ScreenLines(1, 15)[0] + call assert_equal(expected, actual) + + " expected: + " 'abcd |abcd ' + " ^^^^ ^^^^^^^^^ no highlight + " ^ 'Search' highlight + " ^ 'VertSplit' highlight + let attrs0 = ScreenAttrs(1, 15)[0] + call assert_equal(repeat([attrs0[0]], 4), attrs0[0:3]) + call assert_equal(repeat([attrs0[0]], 9), attrs0[6:14]) + call assert_notequal(attrs0[0], attrs0[4]) + call assert_notequal(attrs0[0], attrs0[5]) + call assert_notequal(attrs0[4], attrs0[5]) + + setlocal cursorline + + " expected: + " 'abcd |abcd ' + " ^^^^ underline + " ^ 'Search' highlight with underline + " ^ 'VertSplit' highlight + " ^^^^^^^^^ no highlight + + " underline + exe hi_ul + + let actual = ScreenLines(1, 15)[0] + call assert_equal(expected, actual) + + let attrs = ScreenAttrs(1, 15)[0] + call assert_equal(repeat([attrs[0]], 4), attrs[0:3]) + call assert_equal(repeat([attrs[6]], 9), attrs[6:14]) + call assert_equal(attrs0[5:14], attrs[5:14]) + call assert_notequal(attrs[0], attrs[4]) + call assert_notequal(attrs[0], attrs[5]) + call assert_notequal(attrs[0], attrs[6]) + call assert_notequal(attrs[4], attrs[5]) + call assert_notequal(attrs[5], attrs[6]) + call assert_notequal(attrs0[0], attrs[0]) + call assert_notequal(attrs0[4], attrs[4]) + call Check_lcs_eol_attrs(attrs, 1, 15) + + if IsColorable() + " bg-color + exe hi_bg + + let actual = ScreenLines(1, 15)[0] + call assert_equal(expected, actual) + + let attrs = ScreenAttrs(1, 15)[0] + call assert_equal(repeat([attrs[0]], 4), attrs[0:3]) + call assert_equal(repeat([attrs[6]], 9), attrs[6:14]) + call assert_equal(attrs0[5:14], attrs[5:14]) + call assert_notequal(attrs[0], attrs[4]) + call assert_notequal(attrs[0], attrs[5]) + call assert_notequal(attrs[0], attrs[6]) + call assert_notequal(attrs[4], attrs[5]) + call assert_notequal(attrs[5], attrs[6]) + call assert_notequal(attrs0[0], attrs[0]) + call assert_equal(attrs0[4], attrs[4]) + call Check_lcs_eol_attrs(attrs, 1, 15) + endif + + call CloseWindow() + exe hiCursorLine +endfunc + +func Test_highlight_eol_with_cursorline_rightleft() + if !has('rightleft') + return + endif + + let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine() + + call NewWindow('topleft 5', 10) + setlocal rightleft + call setline(1, 'abcd') + call matchadd('Search', '\n') + let attrs0 = ScreenAttrs(1, 10)[0] + + setlocal cursorline + + " underline + exe hi_ul + + " expected: + " ' dcba' + " ^^^^ underline + " ^ 'Search' highlight with underline + " ^^^^^ underline + let attrs = ScreenAttrs(1, 10)[0] + call assert_equal(repeat([attrs[9]], 4), attrs[6:9]) + call assert_equal(repeat([attrs[4]], 5) + [attrs[5]], attrs[0:5]) + call assert_notequal(attrs[9], attrs[5]) + call assert_notequal(attrs[4], attrs[5]) + call assert_notequal(attrs0[9], attrs[9]) + call assert_notequal(attrs0[5], attrs[5]) + call Check_lcs_eol_attrs(attrs, 1, 10) + + if IsColorable() + " bg-color + exe hi_bg + + " expected: + " ' dcba' + " ^^^^ bg-color of 'CursorLine' + " ^ 'Search' highlight + " ^^^^^ bg-color of 'CursorLine' + let attrs = ScreenAttrs(1, 10)[0] + call assert_equal(repeat([attrs[9]], 4), attrs[6:9]) + call assert_equal(repeat([attrs[4]], 5), attrs[0:4]) + call assert_equal(attrs0[5], attrs[5]) + call assert_notequal(attrs[9], attrs[5]) + call assert_notequal(attrs[5], attrs[4]) + call assert_notequal(attrs0[9], attrs[9]) + call assert_notequal(attrs0[4], attrs[4]) + call Check_lcs_eol_attrs(attrs, 1, 10) + endif + + call CloseWindow() + exe hiCursorLine +endfunc + +func Test_highlight_eol_with_cursorline_linewrap() + let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine() + + call NewWindow('topleft 5', 10) + call setline(1, [repeat('a', 51) . 'bcd', '']) + call matchadd('Search', '\n') + + setlocal wrap + normal! gg$ + let attrs0 = ScreenAttrs(5, 10)[0] + setlocal cursorline + + " underline + exe hi_ul + + " expected: + " 'abcd ' + " ^^^^ underline + " ^ 'Search' highlight with underline + " ^^^^^ underline + let attrs = ScreenAttrs(5, 10)[0] + call assert_equal(repeat([attrs[0]], 4), attrs[0:3]) + call assert_equal([attrs[4]] + repeat([attrs[5]], 5), attrs[4:9]) + call assert_notequal(attrs[0], attrs[4]) + call assert_notequal(attrs[4], attrs[5]) + call assert_notequal(attrs0[0], attrs[0]) + call assert_notequal(attrs0[4], attrs[4]) + call Check_lcs_eol_attrs(attrs, 5, 10) + + if IsColorable() + " bg-color + exe hi_bg + + " expected: + " 'abcd ' + " ^^^^ bg-color of 'CursorLine' + " ^ 'Search' highlight + " ^^^^^ bg-color of 'CursorLine' + let attrs = ScreenAttrs(5, 10)[0] + call assert_equal(repeat([attrs[0]], 4), attrs[0:3]) + call assert_equal(repeat([attrs[5]], 5), attrs[5:9]) + call assert_equal(attrs0[4], attrs[4]) + call assert_notequal(attrs[0], attrs[4]) + call assert_notequal(attrs[4], attrs[5]) + call assert_notequal(attrs0[0], attrs[0]) + call assert_notequal(attrs0[5], attrs[5]) + call Check_lcs_eol_attrs(attrs, 5, 10) + endif + + setlocal nocursorline nowrap + normal! gg$ + let attrs0 = ScreenAttrs(1, 10)[0] + setlocal cursorline + + " underline + exe hi_ul + + " expected: + " 'aaabcd ' + " ^^^^^^ underline + " ^ 'Search' highlight with underline + " ^^^ underline + let attrs = ScreenAttrs(1, 10)[0] + call assert_equal(repeat([attrs[0]], 6), attrs[0:5]) + call assert_equal([attrs[6]] + repeat([attrs[7]], 3), attrs[6:9]) + call assert_notequal(attrs[0], attrs[6]) + call assert_notequal(attrs[6], attrs[7]) + call assert_notequal(attrs0[0], attrs[0]) + call assert_notequal(attrs0[6], attrs[6]) + call Check_lcs_eol_attrs(attrs, 1, 10) + + if IsColorable() + " bg-color + exe hi_bg + + " expected: + " 'aaabcd ' + " ^^^^^^ bg-color of 'CursorLine' + " ^ 'Search' highlight + " ^^^ bg-color of 'CursorLine' + let attrs = ScreenAttrs(1, 10)[0] + call assert_equal(repeat([attrs[0]], 6), attrs[0:5]) + call assert_equal(repeat([attrs[7]], 3), attrs[7:9]) + call assert_equal(attrs0[6], attrs[6]) + call assert_notequal(attrs[0], attrs[6]) + call assert_notequal(attrs[6], attrs[7]) + call assert_notequal(attrs0[0], attrs[0]) + call assert_notequal(attrs0[7], attrs[7]) + call Check_lcs_eol_attrs(attrs, 1, 10) + endif + + call CloseWindow() + exe hiCursorLine +endfunc + +func Test_highlight_eol_with_cursorline_sign() + if !has('signs') + return + endif + + let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine() + + call NewWindow('topleft 5', 10) + call setline(1, 'abcd') + call matchadd('Search', '\n') + + sign define Sign text=>> + exe 'sign place 1 line=1 name=Sign buffer=' . bufnr('') + let attrs0 = ScreenAttrs(1, 10)[0] + setlocal cursorline + + " underline + exe hi_ul + + " expected: + " '>>abcd ' + " ^^ sign + " ^^^^ underline + " ^ 'Search' highlight with underline + " ^^^ underline + let attrs = ScreenAttrs(1, 10)[0] + call assert_equal(repeat([attrs[2]], 4), attrs[2:5]) + call assert_equal([attrs[6]] + repeat([attrs[7]], 3), attrs[6:9]) + call assert_notequal(attrs[2], attrs[6]) + call assert_notequal(attrs[6], attrs[7]) + call assert_notequal(attrs0[2], attrs[2]) + call assert_notequal(attrs0[6], attrs[6]) + call Check_lcs_eol_attrs(attrs, 1, 10) + + if IsColorable() + " bg-color + exe hi_bg + + " expected: + " '>>abcd ' + " ^^ sign + " ^^^^ bg-color of 'CursorLine' + " ^ 'Search' highlight + " ^^^ bg-color of 'CursorLine' + let attrs = ScreenAttrs(1, 10)[0] + call assert_equal(repeat([attrs[2]], 4), attrs[2:5]) + call assert_equal(repeat([attrs[7]], 3), attrs[7:9]) + call assert_equal(attrs0[6], attrs[6]) + call assert_notequal(attrs[2], attrs[6]) + call assert_notequal(attrs[6], attrs[7]) + call assert_notequal(attrs0[2], attrs[2]) + call assert_notequal(attrs0[7], attrs[7]) + call Check_lcs_eol_attrs(attrs, 1, 10) + endif + + sign unplace 1 + call CloseWindow() + exe hiCursorLine +endfunc + +func Test_highlight_eol_with_cursorline_breakindent() + if !has('linebreak') + return + endif + + let [hiCursorLine, hi_ul, hi_bg] = HiCursorLine() + + call NewWindow('topleft 5', 10) + setlocal breakindent breakindentopt=min:0,shift:1 showbreak=> + call setline(1, ' ' . repeat('a', 9) . 'bcd') + call matchadd('Search', '\n') + let attrs0 = ScreenAttrs(2, 10)[0] + setlocal cursorline + + " underline + exe hi_ul + + " expected: + " ' >bcd ' + " ^^^ breakindent and showbreak + " ^^^ underline + " ^ 'Search' highlight with underline + " ^^^ underline + let attrs = ScreenAttrs(2, 10)[0] + call assert_equal(repeat([attrs[0]], 2), attrs[0:1]) + call assert_equal(repeat([attrs[3]], 3), attrs[3:5]) + call assert_equal([attrs[6]] + repeat([attrs[7]], 3), attrs[6:9]) + call assert_equal(attrs0[0], attrs[0]) + call assert_notequal(attrs[0], attrs[2]) + call assert_notequal(attrs[2], attrs[3]) + call assert_notequal(attrs[3], attrs[6]) + call assert_notequal(attrs[6], attrs[7]) + call assert_notequal(attrs0[2], attrs[2]) + call assert_notequal(attrs0[3], attrs[3]) + call assert_notequal(attrs0[6], attrs[6]) + call Check_lcs_eol_attrs(attrs, 2, 10) + + if IsColorable() + " bg-color + exe hi_bg + + " expected: + " ' >bcd ' + " ^^^ breakindent and showbreak + " ^^^ bg-color of 'CursorLine' + " ^ 'Search' highlight + " ^^^ bg-color of 'CursorLine' + let attrs = ScreenAttrs(2, 10)[0] + call assert_equal(repeat([attrs[0]], 2), attrs[0:1]) + call assert_equal(repeat([attrs[3]], 3), attrs[3:5]) + call assert_equal(repeat([attrs[7]], 3), attrs[7:9]) + call assert_equal(attrs0[0], attrs[0]) + call assert_equal(attrs0[6], attrs[6]) + call assert_notequal(attrs[0], attrs[2]) + call assert_notequal(attrs[2], attrs[3]) + call assert_notequal(attrs[3], attrs[6]) + call assert_notequal(attrs[6], attrs[7]) + call assert_notequal(attrs0[2], attrs[2]) + call assert_notequal(attrs0[3], attrs[3]) + call assert_notequal(attrs0[7], attrs[7]) + call Check_lcs_eol_attrs(attrs, 2, 10) + endif + + call CloseWindow() + set showbreak= + exe hiCursorLine +endfunc + +func Test_highlight_eol_on_diff() + call setline(1, ['abcd', '']) + call matchadd('Search', '\n') + let attrs0 = ScreenAttrs(1, 10)[0] + + diffthis + botright new + diffthis + + " expected: + " ' abcd ' + " ^^ sign + " ^^^^ ^^^ 'DiffAdd' highlight + " ^ 'Search' highlight + let attrs = ScreenAttrs(1, 10)[0] + call assert_equal(repeat([attrs[0]], 2), attrs[0:1]) + call assert_equal(repeat([attrs[2]], 4), attrs[2:5]) + call assert_equal(repeat([attrs[2]], 3), attrs[7:9]) + call assert_equal(attrs0[4], attrs[6]) + call assert_notequal(attrs[0], attrs[2]) + call assert_notequal(attrs[0], attrs[6]) + call assert_notequal(attrs[2], attrs[6]) + call Check_lcs_eol_attrs(attrs, 1, 10) + + bwipe! + diffoff +endfunc + +func Test_termguicolors() + if !exists('+termguicolors') + return + endif + if has('vtp') && !has('vcon') + " Win32: 'guicolors' doesn't work without virtual console. + call assert_fails('set termguicolors', 'E954:') + return + endif + + " Basic test that setting 'termguicolors' works with one color. + set termguicolors + redraw + set t_Co=1 + redraw + set t_Co=0 + redraw +endfunc diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 8d2c61f6f0..33abb69ca6 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -1702,7 +1702,8 @@ func Xproperty_tests(cchar) Xopen wincmd p call g:Xsetlist([{'filename':'foo', 'lnum':27}]) - call g:Xsetlist([], 'a', {'title' : 'Sample'}) + let s = g:Xsetlist([], 'a', {'title' : 'Sample'}) + call assert_equal(0, s) let d = g:Xgetlist({"title":1}) call assert_equal('Sample', d.title) @@ -1756,7 +1757,8 @@ func Xproperty_tests(cchar) endif " Context related tests - call g:Xsetlist([], 'a', {'context':[1,2,3]}) + let s = g:Xsetlist([], 'a', {'context':[1,2,3]}) + call assert_equal(0, s) call test_garbagecollect_now() let d = g:Xgetlist({'context':1}) call assert_equal([1,2,3], d.context) @@ -1821,8 +1823,9 @@ func Xproperty_tests(cchar) " Test for setting/getting items Xexpr "" let qfprev = g:Xgetlist({'nr':0}) - call g:Xsetlist([], ' ', {'title':'Green', + let s = g:Xsetlist([], ' ', {'title':'Green', \ 'items' : [{'filename':'F1', 'lnum':10}]}) + call assert_equal(0, s) let qfcur = g:Xgetlist({'nr':0}) call assert_true(qfcur.nr == qfprev.nr + 1) let l = g:Xgetlist({'items':1}) @@ -2242,3 +2245,27 @@ func Test_resize_from_copen() augroup! QF_Test endtry endfunc + +" Tests for the quickfix buffer b:changedtick variable +func Xchangedtick_tests(cchar) + call s:setup_commands(a:cchar) + + new | only + + Xexpr "" | Xexpr "" | Xexpr "" + + Xopen + Xolder + Xolder + Xaddexpr "F1:10:Line10" + Xaddexpr "F2:20:Line20" + call g:Xsetlist([{"filename":"F3", "lnum":30, "text":"Line30"}], 'a') + call g:Xsetlist([], 'f') + call assert_equal(8, getbufvar('%', 'changedtick')) + Xclose +endfunc + +func Test_changedtick() + call Xchangedtick_tests('c') + call Xchangedtick_tests('l') +endfunc diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim index 0f2e7e493e..756a455ebd 100644 --- a/src/nvim/testdir/test_visual.vim +++ b/src/nvim/testdir/test_visual.vim @@ -17,6 +17,14 @@ func Test_block_shift_multibyte() q! endfunc +func Test_block_shift_overflow() + " This used to cause a multiplication overflow followed by a crash. + new + normal ii + exe "normal \<C-V>876543210>" + q! +endfunc + func Test_Visual_ctrl_o() new call setline(1, ['one', 'two', 'three']) @@ -118,9 +126,34 @@ func Test_blockwise_visual() enew! endfunc +" Test swapping corners in blockwise visual mode with o and O +func Test_blockwise_visual_o_O() + enew! + + exe "norm! 10i.\<Esc>Y4P3lj\<C-V>4l2jr " + exe "norm! gvO\<Esc>ra" + exe "norm! gvO\<Esc>rb" + exe "norm! gvo\<C-c>rc" + exe "norm! gvO\<C-c>rd" + + call assert_equal(['..........', + \ '...c d..', + \ '... ..', + \ '...a b..', + \ '..........'], getline(1, '$')) + + enew! +endfun + " Test Virtual replace mode. func Test_virtual_replace() throw 'skipped: TODO: ' + if exists('&t_kD') + let save_t_kD = &t_kD + endif + if exists('&t_kb') + let save_t_kb = &t_kb + endif exe "set t_kD=\<C-V>x7f t_kb=\<C-V>x08" enew! exe "normal a\nabcdefghi\njk\tlmn\n opq rst\n\<C-D>uvwxyz" @@ -151,4 +184,96 @@ func Test_virtual_replace() call assert_equal(['AB......CDEFGHI.Jkl', \ 'AB IJKLMNO QRst'], getline(12, 13)) enew! + set noai bs&vim + if exists('save_t_kD') + let &t_kD = save_t_kD + endif + if exists('save_t_kb') + let &t_kb = save_t_kb + endif +endfunc + +" Test Virtual replace mode. +func Test_virtual_replace2() + enew! + set bs=2 + exe "normal a\nabcdefghi\njk\tlmn\n opq rst\n\<C-D>uvwxyz" + call cursor(1,1) + " Test 1: Test that del deletes the newline + exe "normal gR0\<del> 1\nA\nBCDEFGHIJ\n\tKL\nMNO\nPQR" + call assert_equal(['0 1', + \ 'A', + \ 'BCDEFGHIJ', + \ ' KL', + \ 'MNO', + \ 'PQR', + \ ], getline(1, 6)) + " Test 2: + " a newline is not deleted, if no newline has been added in virtual replace mode + %d_ + call setline(1, ['abcd', 'efgh', 'ijkl']) + call cursor(2,1) + exe "norm! gR1234\<cr>5\<bs>\<bs>\<bs>" + call assert_equal(['abcd', + \ '123h', + \ 'ijkl'], getline(1, '$')) + " Test 3: + " a newline is deleted, if a newline has been inserted before in virtual replace mode + %d_ + call setline(1, ['abcd', 'efgh', 'ijkl']) + call cursor(2,1) + exe "norm! gR1234\<cr>\<cr>56\<bs>\<bs>\<bs>" + call assert_equal(['abcd', + \ '1234', + \ 'ijkl'], getline(1, '$')) + " Test 4: + " delete add a newline, delete it, add it again and check undo + %d_ + call setline(1, ['abcd', 'efgh', 'ijkl']) + call cursor(2,1) + " break undo sequence explicitly + let &ul = &ul + exe "norm! gR1234\<cr>\<bs>\<del>56\<cr>" + let &ul = &ul + call assert_equal(['abcd', + \ '123456', + \ ''], getline(1, '$')) + norm! u + call assert_equal(['abcd', + \ 'efgh', + \ 'ijkl'], getline(1, '$')) + " clean up + %d_ + set bs&vim +endfunc + +" Test for Visual mode not being reset causing E315 error. +func TriggerTheProblem() + " At this point there is no visual selection because :call reset it. + " Let's restore the selection: + normal gv + '<,'>del _ + try + exe "normal \<Esc>" + catch /^Vim\%((\a\+)\)\=:E315/ + echom 'Snap! E315 error!' + let g:msg = 'Snap! E315 error!' + endtry +endfunc + +func Test_visual_mode_reset() + set belloff=all + enew + let g:msg = "Everything's fine." + enew + setl buftype=nofile + call append(line('$'), 'Delete this line.') + + " NOTE: this has to be done by a call to a function because executing :del + " the ex-way will require the colon operator which resets the visual mode + " thus preventing the problem: + exe "normal! GV:call TriggerTheProblem()\<CR>" + call assert_equal("Everything's fine.", g:msg) + + set belloff& endfunc diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index 139d29a48b..ad60c8d3c7 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -17,7 +17,7 @@ func Test_window_cmd_ls0_with_split() endfunc func Test_window_cmd_cmdwin_with_vsp() - let efmt='Expected 0 but got %d (in ls=%d, %s window)' + let efmt = 'Expected 0 but got %d (in ls=%d, %s window)' for v in range(0, 2) exec "set ls=" . v vsplit @@ -417,4 +417,92 @@ func Test_window_newtab() endfunc +" Tests for adjusting window and contents +func GetScreenStr(row) + let str = "" + for c in range(1,3) + let str .= nr2char(screenchar(a:row, c)) + endfor + return str +endfunc + +func Test_window_contents() + enew! | only | new + call setline(1, range(1,256)) + + exe "norm! \<C-W>t\<C-W>=1Gzt\<C-W>w\<C-W>+" + redraw + let s3 = GetScreenStr(1) + wincmd p + call assert_equal(1, line("w0")) + call assert_equal('1 ', s3) + + exe "norm! \<C-W>t\<C-W>=50Gzt\<C-W>w\<C-W>+" + redraw + let s3 = GetScreenStr(1) + wincmd p + call assert_equal(50, line("w0")) + call assert_equal('50 ', s3) + + exe "norm! \<C-W>t\<C-W>=59Gzt\<C-W>w\<C-W>+" + redraw + let s3 = GetScreenStr(1) + wincmd p + call assert_equal(59, line("w0")) + call assert_equal('59 ', s3) + + bwipeout! + call test_garbagecollect_now() +endfunc + +func Test_access_freed_mem() + " This was accessing freed memory + au * 0 vs xxx + arg 0 + argadd + all + all + au! + bwipe xxx +endfunc + +func Test_visual_cleared_after_window_split() + new | only! + let smd_save = &showmode + set showmode + let ls_save = &laststatus + set laststatus=1 + call setline(1, ['a', 'b', 'c', 'd', '']) + norm! G + exe "norm! kkvk" + redraw + exe "norm! \<C-W>v" + redraw + " check if '-- VISUAL --' disappeared from command line + let columns = range(1, &columns) + let cmdlinechars = map(columns, 'nr2char(screenchar(&lines, v:val))') + let cmdline = join(cmdlinechars, '') + let cmdline_ltrim = substitute(cmdline, '^\s*', "", "") + let mode_shown = substitute(cmdline_ltrim, '\s*$', "", "") + call assert_equal('', mode_shown) + let &showmode = smd_save + let &laststatus = ls_save + bwipe! +endfunc + +func Test_winrestcmd() + 2split + 3vsplit + let a = winrestcmd() + call assert_equal(2, winheight(0)) + call assert_equal(3, winwidth(0)) + wincmd = + call assert_notequal(2, winheight(0)) + call assert_notequal(3, winwidth(0)) + exe a + call assert_equal(2, winheight(0)) + call assert_equal(3, winwidth(0)) + only +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/view_util.vim b/src/nvim/testdir/view_util.vim index eb92630761..29ea073f97 100644 --- a/src/nvim/testdir/view_util.vim +++ b/src/nvim/testdir/view_util.vim @@ -1,5 +1,10 @@ " Functions about view shared by several tests +" Only load this script once. +if exists('*ScreenLines') + finish +endif + " ScreenLines(lnum, width) or " ScreenLines([start, end], width) function! ScreenLines(lnum, width) abort @@ -18,6 +23,22 @@ function! ScreenLines(lnum, width) abort return lines endfunction +function! ScreenAttrs(lnum, width) abort + redraw! + if type(a:lnum) == v:t_list + let start = a:lnum[0] + let end = a:lnum[1] + else + let start = a:lnum + let end = a:lnum + endif + let attrs = [] + for l in range(start, end) + let attrs += [map(range(1, a:width), 'screenattr(l, v:val)')] + endfor + return attrs +endfunction + function! NewWindow(height, width) abort exe a:height . 'new' exe a:width . 'vsp' diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 2055b4879e..f4eb50b3b5 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -2233,10 +2233,11 @@ static void u_undoredo(int undo, bool do_buf_event) * If the file is empty, there is an empty line 1 that we * should get rid of, by replacing it with the new line */ - if (empty_buffer && lnum == 0) - ml_replace((linenr_T)1, uep->ue_array[i], TRUE); - else + if (empty_buffer && lnum == 0) { + ml_replace((linenr_T)1, uep->ue_array[i], true); + } else { ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE); + } xfree(uep->ue_array[i]); } xfree((char_u *)uep->ue_array); @@ -2902,7 +2903,7 @@ void u_undoline(void) curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL) return; oldp = u_save_line(curbuf->b_u_line_lnum); - ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE); + ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, true); changed_bytes(curbuf->b_u_line_lnum, 0); xfree(curbuf->b_u_line_ptr); curbuf->b_u_line_ptr = oldp; diff --git a/src/nvim/window.c b/src/nvim/window.c index 274bf72f3b..8239061a0c 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2296,6 +2296,9 @@ winframe_remove ( if (frp2->fr_win != NULL) frp2->fr_win->w_frame = frp2->fr_parent; frp = frp2->fr_parent; + if (topframe->fr_child == frp2) { + topframe->fr_child = frp; + } xfree(frp2); frp2 = frp->fr_parent; @@ -2317,6 +2320,9 @@ winframe_remove ( break; } } + if (topframe->fr_child == frp) { + topframe->fr_child = frp2; + } xfree(frp); } } @@ -2959,7 +2965,6 @@ static int win_alloc_firstwin(win_T *oldwin) topframe = curwin->w_frame; topframe->fr_width = Columns; topframe->fr_height = Rows - p_ch; - topframe->fr_win = curwin; return OK; } @@ -3970,18 +3975,20 @@ win_remove ( tabpage_T *tp /* tab page "win" is in, NULL for current */ ) { - if (wp->w_prev != NULL) + if (wp->w_prev != NULL) { wp->w_prev->w_next = wp->w_next; - else if (tp == NULL) - firstwin = wp->w_next; - else + } else if (tp == NULL) { + firstwin = curtab->tp_firstwin = wp->w_next; + } else { tp->tp_firstwin = wp->w_next; - if (wp->w_next != NULL) + } + if (wp->w_next != NULL) { wp->w_next->w_prev = wp->w_prev; - else if (tp == NULL) - lastwin = wp->w_prev; - else + } else if (tp == NULL) { + lastwin = curtab->tp_lastwin = wp->w_prev; + } else { tp->tp_lastwin = wp->w_prev; + } } /* @@ -4015,12 +4022,18 @@ static void frame_insert(frame_T *before, frame_T *frp) */ static void frame_remove(frame_T *frp) { - if (frp->fr_prev != NULL) + if (frp->fr_prev != NULL) { frp->fr_prev->fr_next = frp->fr_next; - else + } else { frp->fr_parent->fr_child = frp->fr_next; - if (frp->fr_next != NULL) + // special case: topframe->fr_child == frp + if (topframe->fr_child == frp) { + topframe->fr_child = frp->fr_next; + } + } + if (frp->fr_next != NULL) { frp->fr_next->fr_prev = frp->fr_prev; + } } @@ -4848,8 +4861,8 @@ void scroll_to_fraction(win_T *wp, int prev_height) sline = wp->w_wrow - line_size; if (sline >= 0) { - /* Make sure the whole cursor line is visible, if possible. */ - int rows = plines_win(wp, lnum, FALSE); + // Make sure the whole cursor line is visible, if possible. + const int rows = plines_win(wp, lnum, false); if (sline > wp->w_height - rows) { sline = wp->w_height - rows; @@ -4884,12 +4897,13 @@ void scroll_to_fraction(win_T *wp, int prev_height) --sline; break; } - --lnum; - if (lnum == wp->w_topline) - line_size = plines_win_nofill(wp, lnum, TRUE) + lnum--; + if (lnum == wp->w_topline) { + line_size = plines_win_nofill(wp, lnum, true) + wp->w_topfill; - else - line_size = plines_win(wp, lnum, TRUE); + } else { + line_size = plines_win(wp, lnum, true); + } sline -= line_size; } @@ -5488,12 +5502,10 @@ int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage return OK; } -/* - * Restore current tabpage and window saved by switch_win(), if still valid. - * When "no_display" is TRUE the display won't be affected, no redraw is - * triggered. - */ -void restore_win(win_T *save_curwin, tabpage_T *save_curtab, int no_display) +// Restore current tabpage and window saved by switch_win(), if still valid. +// When "no_display" is true the display won't be affected, no redraw is +// triggered. +void restore_win(win_T *save_curwin, tabpage_T *save_curtab, bool no_display) { if (save_curtab != NULL && valid_tabpage(save_curtab)) { if (no_display) { @@ -5608,7 +5620,7 @@ int match_add(win_T *wp, const char *const grp, const char *const pat, m->match.rmm_maxcol = 0; m->conceal_char = 0; if (conceal_char != NULL) { - m->conceal_char = (*mb_ptr2char)((const char_u *)conceal_char); + m->conceal_char = utf_ptr2char((const char_u *)conceal_char); } // Set up position matches |