diff options
| author | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 21:52:58 +0000 |
|---|---|---|
| committer | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 21:52:58 +0000 |
| commit | 931bffbda3668ddc609fc1da8f9eb576b170aa52 (patch) | |
| tree | d8c1843a95da5ea0bb4acc09f7e37843d9995c86 /src/nvim/message.c | |
| parent | 142d9041391780ac15b89886a54015fdc5c73995 (diff) | |
| parent | 4a8bf24ac690004aedf5540fa440e788459e5e34 (diff) | |
| download | rneovim-userreg.tar.gz rneovim-userreg.tar.bz2 rneovim-userreg.zip | |
Merge remote-tracking branch 'upstream/master' into userreguserreg
Diffstat (limited to 'src/nvim/message.c')
| -rw-r--r-- | src/nvim/message.c | 825 |
1 files changed, 365 insertions, 460 deletions
diff --git a/src/nvim/message.c b/src/nvim/message.c index 7f29b19031..3268ff389a 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // message.c: functions for displaying messages on the command line #include <assert.h> @@ -11,22 +8,23 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/types.h> #include "nvim/api/private/helpers.h" -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/buffer_defs.h" #include "nvim/channel.h" #include "nvim/charset.h" #include "nvim/drawscreen.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" -#include "nvim/eval/typval_defs.h" #include "nvim/event/defs.h" #include "nvim/event/loop.h" #include "nvim/event/multiqueue.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_eval.h" #include "nvim/fileio.h" +#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/gettext.h" @@ -44,16 +42,20 @@ #include "nvim/mouse.h" #include "nvim/ops.h" #include "nvim/option.h" +#include "nvim/option_vars.h" +#include "nvim/os/fs.h" #include "nvim/os/input.h" #include "nvim/os/os.h" -#include "nvim/pos.h" +#include "nvim/os/time.h" +#include "nvim/pos_defs.h" #include "nvim/regexp.h" #include "nvim/runtime.h" -#include "nvim/screen.h" +#include "nvim/state_defs.h" #include "nvim/strings.h" +#include "nvim/types_defs.h" #include "nvim/ui.h" #include "nvim/ui_compositor.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" // To be able to scroll back at the "more" and "hit-enter" prompts we need to // store the displayed text and remember where screen lines start. @@ -64,7 +66,7 @@ struct msgchunk_S { char sb_eol; // true when line ends after this text int sb_msg_col; // column in which text starts int sb_attr; // text attributes - char sb_text[1]; // text to be displayed, actually longer + char sb_text[]; // text to be displayed }; // Magic chars used in confirm dialog strings @@ -142,7 +144,7 @@ static int msg_grid_pos_at_flush = 0; static void ui_ext_msg_set_pos(int row, bool scrolled) { - char buf[MAX_MCO + 1]; + char buf[MB_MAXCHAR + 1]; size_t size = (size_t)utf_char2bytes(curwin->w_p_fcs_chars.msgsep, buf); buf[size] = '\0'; ui_call_msg_set_pos(msg_grid.handle, row, scrolled, @@ -182,7 +184,7 @@ void msg_grid_validate(void) msg_grid.dirty_col = xcalloc((size_t)Rows, sizeof(*msg_grid.dirty_col)); // Tricky: allow resize while pager or ex mode is active - int pos = MAX(max_rows - msg_scrolled, 0); + int pos = (State & MODE_ASKMORE) ? 0 : MAX(max_rows - msg_scrolled, 0); msg_grid.throttled = false; // don't throttle in 'cmdheight' area msg_grid_set_pos(pos, msg_scrolled); ui_comp_put_grid(&msg_grid, pos, 0, msg_grid.rows, msg_grid.cols, @@ -213,17 +215,8 @@ void msg_grid_validate(void) } } -/// Displays the string 's' on the status line -/// When terminal not initialized (yet) os_errmsg(..) is used. -/// -/// @return true if wait_return() not called -int msg(char *s) -{ - return msg_attr_keep(s, 0, false, false); -} - /// Like msg() but keep it silent when 'verbosefile' is set. -int verb_msg(char *s) +int verb_msg(const char *s) { verbose_enter(); int n = msg_attr_keep(s, 0, false, false); @@ -232,14 +225,18 @@ int verb_msg(char *s) return n; } -int msg_attr(const char *s, const int attr) +/// Displays the string 's' on the status line +/// When terminal not initialized (yet) os_errmsg(..) is used. +/// +/// @return true if wait_return() not called +int msg(const char *s, const int attr) FUNC_ATTR_NONNULL_ARG(1) { return msg_attr_keep(s, attr, false, false); } -/// Similar to msg_outtrans_attr, but support newlines and tabs. -void msg_multiline_attr(const char *s, int attr, bool check_int, bool *need_clear) +/// Similar to msg_outtrans, but support newlines and tabs. +void msg_multiline(const char *s, int attr, bool check_int, bool *need_clear) FUNC_ATTR_NONNULL_ALL { const char *next_spec = s; @@ -252,7 +249,7 @@ void msg_multiline_attr(const char *s, int attr, bool check_int, bool *need_clea if (next_spec != NULL) { // Printing all char that are before the char found by strpbrk - msg_outtrans_len_attr(s, (int)(next_spec - s), attr); + msg_outtrans_len(s, (int)(next_spec - s), attr); if (*next_spec != TAB && *need_clear) { msg_clr_eos(); @@ -266,7 +263,7 @@ void msg_multiline_attr(const char *s, int attr, bool check_int, bool *need_clea // Print the rest of the message. We know there is no special // character because strpbrk returned NULL if (*s != NUL) { - msg_outtrans_attr(s, attr); + msg_outtrans(s, attr); } } @@ -279,8 +276,7 @@ void msg_multiattr(HlMessage hl_msg, const char *kind, bool history) msg_ext_set_kind(kind); for (uint32_t i = 0; i < kv_size(hl_msg); i++) { HlMessageChunk chunk = kv_A(hl_msg, i); - msg_multiline_attr((const char *)chunk.text.data, chunk.attr, - true, &need_clear); + msg_multiline(chunk.text.data, chunk.attr, true, &need_clear); } if (history && kv_size(hl_msg)) { add_msg_hist_multiattr(NULL, 0, 0, true, hl_msg); @@ -294,7 +290,6 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline) FUNC_ATTR_NONNULL_ALL { static int entered = 0; - int retval; char *buf = NULL; if (keep && multiline) { @@ -306,7 +301,7 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline) // Skip messages not match ":filter pattern". // Don't filter when there is an error. - if (!emsg_on_display && message_filtered((char *)s)) { + if (!emsg_on_display && message_filtered(s)) { return true; } @@ -334,24 +329,24 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline) // Truncate the message if needed. msg_start(); - buf = msg_strtrunc((char *)s, false); + buf = msg_strtrunc(s, false); if (buf != NULL) { s = buf; } bool need_clear = true; if (multiline) { - msg_multiline_attr(s, attr, false, &need_clear); + msg_multiline(s, attr, false, &need_clear); } else { - msg_outtrans_attr(s, attr); + msg_outtrans(s, attr); } if (need_clear) { msg_clr_eos(); } - retval = msg_end(); + int retval = msg_end(); - if (keep && retval && vim_strsize((char *)s) < (Rows - cmdline_row - 1) * Columns + sc_col) { - set_keep_msg((char *)s, 0); + if (keep && retval && vim_strsize(s) < (Rows - cmdline_row - 1) * Columns + sc_col) { + set_keep_msg(s, 0); } need_fileinfo = false; @@ -366,17 +361,16 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline) /// @return an allocated string or NULL when no truncating is done. /// /// @param force always truncate -char *msg_strtrunc(char *s, int force) +char *msg_strtrunc(const char *s, int force) { char *buf = NULL; - int len; - int room; // May truncate message to avoid a hit-return prompt if ((!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL) && !exmode_active && msg_silent == 0 && !ui_has(kUIMessages)) || force) { - len = vim_strsize(s); + int room; + int len = vim_strsize(s); if (msg_scrolled != 0) { // Use all the columns. room = (Rows - msg_row) * Columns - 1; @@ -397,10 +391,9 @@ char *msg_strtrunc(char *s, int force) /// Truncate a string "s" to "buf" with cell width "room". /// "s" and "buf" may be equal. -void trunc_string(char *s, char *buf, int room_in, int buflen) +void trunc_string(const char *s, char *buf, int room_in, int buflen) { int room = room_in - 3; // "..." takes 3 chars - int half; int len = 0; int e; int i; @@ -416,7 +409,7 @@ void trunc_string(char *s, char *buf, int room_in, int buflen) if (room_in < 3) { room = 0; } - half = room / 2; + int half = room / 2; // First part: Start of the string. for (e = 0; len < half && e < buflen; e++) { @@ -441,7 +434,7 @@ void trunc_string(char *s, char *buf, int room_in, int buflen) // Last part: End of the string. half = i = (int)strlen(s); - for (;;) { + while (true) { do { half = half - utf_head_off(s, s + half - 1) - 1; } while (half > 0 && utf_iscomposing(utf_ptr2char(s + half))); @@ -478,26 +471,19 @@ void trunc_string(char *s, char *buf, int room_in, int buflen) buf[e + 3 + len - 1] = NUL; } else { // can't fit in the "...", just truncate it - buf[e - 1] = NUL; + buf[buflen - 1] = NUL; } } -// Note: Caller of smsg() and smsg_attr() must check the resulting string is -// shorter than IOSIZE!!! - -int smsg(const char *s, ...) - FUNC_ATTR_PRINTF(1, 2) -{ - va_list arglist; - - va_start(arglist, s); - vim_vsnprintf(IObuff, IOSIZE, s, arglist); - va_end(arglist); - - return msg(IObuff); -} - -int smsg_attr(int attr, const char *s, ...) +/// Shows a printf-style message with attributes. +/// +/// Note: Caller must check the resulting string is shorter than IOSIZE!!! +/// +/// @see semsg +/// @see swmsg +/// +/// @param s printf-style format message +int smsg(int attr, const char *s, ...) FUNC_ATTR_PRINTF(2, 3) { va_list arglist; @@ -505,7 +491,7 @@ int smsg_attr(int attr, const char *s, ...) va_start(arglist, s); vim_vsnprintf(IObuff, IOSIZE, s, arglist); va_end(arglist); - return msg_attr((const char *)IObuff, attr); + return msg(IObuff, attr); } int smsg_attr_keep(int attr, const char *s, ...) @@ -516,7 +502,7 @@ int smsg_attr_keep(int attr, const char *s, ...) va_start(arglist, s); vim_vsnprintf(IObuff, IOSIZE, s, arglist); va_end(arglist); - return msg_attr_keep((const char *)IObuff, attr, true, false); + return msg_attr_keep(IObuff, attr, true, false); } // Remember the last sourcing name/lnum used in an error message, so that it @@ -581,10 +567,10 @@ static char *get_emsg_lnum(void) if (SOURCING_NAME != NULL && (other_sourcing_name() || SOURCING_LNUM != last_sourcing_lnum) && SOURCING_LNUM != 0) { - const char *const p = _("line %4ld:"); + const char *const p = _("line %4" PRIdLINENR ":"); const size_t buf_len = 20 + strlen(p); char *const buf = xmalloc(buf_len); - snprintf(buf, buf_len, p, (long)SOURCING_LNUM); + snprintf(buf, buf_len, p, SOURCING_LNUM); return buf; } return NULL; @@ -607,12 +593,12 @@ void msg_source(int attr) char *p = get_emsg_source(); if (p != NULL) { msg_scroll = true; // this will take more than one line - msg_attr(p, attr); + msg(p, attr); xfree(p); } p = get_emsg_lnum(); if (p != NULL) { - msg_attr(p, HL_ATTR(HLF_N)); + msg(p, HL_ATTR(HLF_N)); xfree(p); last_sourcing_lnum = SOURCING_LNUM; // only once for each line } @@ -643,9 +629,8 @@ int emsg_not_now(void) return false; } -static bool emsg_multiline(const char *s, bool multiline) +bool emsg_multiline(const char *s, bool multiline) { - int attr; bool ignore = false; // Skip this if not giving error messages at the moment. @@ -666,7 +651,7 @@ static bool emsg_multiline(const char *s, bool multiline) // be found, the message will be displayed later on.) "ignore" is set // when the message should be ignored completely (used for the // interrupt message). - if (cause_errthrow(s, severe, &ignore)) { + if (cause_errthrow(s, multiline, severe, &ignore)) { if (!ignore) { did_emsg++; } @@ -707,8 +692,8 @@ static bool emsg_multiline(const char *s, bool multiline) // Log (silent) errors as debug messages. if (SOURCING_NAME != NULL && SOURCING_LNUM != 0) { - DLOG("(:silent) %s (%s (line %ld))", - s, SOURCING_NAME, (long)SOURCING_LNUM); + DLOG("(:silent) %s (%s (line %" PRIdLINENR "))", + s, SOURCING_NAME, SOURCING_LNUM); } else { DLOG("(:silent) %s", s); } @@ -718,7 +703,7 @@ static bool emsg_multiline(const char *s, bool multiline) // Log editor errors as INFO. if (SOURCING_NAME != NULL && SOURCING_LNUM != 0) { - ILOG("%s (%s (line %ld))", s, SOURCING_NAME, (long)SOURCING_LNUM); + ILOG("%s (%s (line %" PRIdLINENR "))", s, SOURCING_NAME, SOURCING_LNUM); } else { ILOG("%s", s); } @@ -742,7 +727,7 @@ static bool emsg_multiline(const char *s, bool multiline) } emsg_on_display = true; // remember there is an error message - attr = HL_ATTR(HLF_E); // set highlight mode for error messages + int attr = HL_ATTR(HLF_E); // set highlight mode for error messages if (msg_scrolled != 0) { need_wait_return = true; // needed in case emsg() is called after } // wait_return() has reset need_wait_return @@ -774,10 +759,12 @@ bool emsg(const char *s) void emsg_invreg(int name) { - semsg(_("E354: Invalid register name: '%s'"), transchar(name)); + semsg(_("E354: Invalid register name: '%s'"), transchar_buf(NULL, name)); } /// Print an error message with unknown number of arguments +/// +/// @return whether the message was displayed bool semsg(const char *const fmt, ...) FUNC_ATTR_PRINTF(1, 2) { @@ -864,7 +851,7 @@ void siemsg(const char *s, ...) } /// Give an "Internal error" message. -void internal_error(char *where) +void internal_error(const char *where) { siemsg(_(e_intern2), where); } @@ -888,22 +875,38 @@ void msg_schedule_semsg(const char *const fmt, ...) loop_schedule_deferred(&main_loop, event_create(msg_semsg_event, 1, s)); } +static void msg_semsg_multiline_event(void **argv) +{ + char *s = argv[0]; + (void)emsg_multiline(s, true); + xfree(s); +} + +void msg_schedule_semsg_multiline(const char *const fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vim_vsnprintf(IObuff, IOSIZE, fmt, ap); + va_end(ap); + + char *s = xstrdup(IObuff); + loop_schedule_deferred(&main_loop, event_create(msg_semsg_multiline_event, 1, s)); +} + /// Like msg(), but truncate to a single line if p_shm contains 't', or when /// "force" is true. This truncates in another way as for normal messages. /// Careful: The string may be changed by msg_may_trunc()! /// /// @return a pointer to the printed message, if wait_return() not called. -char *msg_trunc_attr(char *s, bool force, int attr) +char *msg_trunc(char *s, bool force, int attr) { - int n; - // Add message to history before truncating. add_msg_hist(s, -1, attr, false); char *ts = msg_may_trunc(force, s); msg_hist_off = true; - n = msg_attr(ts, attr); + int n = msg(ts, attr); msg_hist_off = false; if (n) { @@ -1009,12 +1012,10 @@ static void add_msg_hist_multiattr(const char *s, int len, int attr, bool multil /// @return FAIL if there are no messages. int delete_first_msg(void) { - struct msg_hist *p; - if (msg_hist_len <= 0) { return FAIL; } - p = first_msg_hist; + struct msg_hist *p = first_msg_hist; first_msg_hist = p->next; if (first_msg_hist == NULL) { // history is becoming empty assert(msg_hist_len == 1); @@ -1028,13 +1029,9 @@ int delete_first_msg(void) } /// :messages command implementation -void ex_messages(void *const eap_p) +void ex_messages(exarg_T *eap) FUNC_ATTR_NONNULL_ALL { - const exarg_T *const eap = (const exarg_T *)eap_p; - struct msg_hist *p; - int c = 0; - if (strcmp(eap->arg, "clear") == 0) { int keep = eap->addr_count == 0 ? 0 : eap->line2; @@ -1049,9 +1046,10 @@ void ex_messages(void *const eap_p) return; } - p = first_msg_hist; + struct msg_hist *p = first_msg_hist; if (eap->addr_count != 0) { + int c = 0; // Count total messages for (; p != NULL && !got_int; p = p->next) { c++; @@ -1072,7 +1070,7 @@ void ex_messages(void *const eap_p) for (; p != NULL; p = p->next) { if (kv_size(p->multiattr) || (p->msg && p->msg[0])) { Array entry = ARRAY_DICT_INIT; - ADD(entry, STRING_OBJ(cstr_to_string(p->kind))); + ADD(entry, CSTR_TO_OBJ(p->kind)); Array content = ARRAY_DICT_INIT; if (kv_size(p->multiattr)) { for (uint32_t i = 0; i < kv_size(p->multiattr); i++) { @@ -1085,7 +1083,7 @@ void ex_messages(void *const eap_p) } else if (p->msg && p->msg[0]) { Array content_entry = ARRAY_DICT_INIT; ADD(content_entry, INTEGER_OBJ(p->attr)); - ADD(content_entry, STRING_OBJ(cstr_to_string((char *)(p->msg)))); + ADD(content_entry, CSTR_TO_OBJ(p->msg)); ADD(content, ARRAY_OBJ(content_entry)); } ADD(entry, ARRAY_OBJ(content)); @@ -1130,8 +1128,6 @@ void msg_end_prompt(void) void wait_return(int redraw) { int c; - int oldState; - int tmpState; int had_got_int; FILE *save_scriptout; @@ -1165,7 +1161,7 @@ void wait_return(int redraw) } redir_off = true; // don't redirect this message - oldState = State; + int oldState = State; if (quit_more) { c = CAR; // just pretend CR was hit quit_more = false; @@ -1226,9 +1222,7 @@ void wait_return(int redraw) } else { msg_didout = false; c = K_IGNORE; - msg_col = - cmdmsg_rl ? Columns - 1 : - 0; + msg_col = 0; } if (quit_more) { c = CAR; // just pretend CR was hit @@ -1253,6 +1247,7 @@ void wait_return(int redraw) || c == K_MOUSEDOWN || c == K_MOUSEUP || c == K_MOUSEMOVE); os_breakcheck(); + // Avoid that the mouse-up event causes visual mode to start. if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE || c == K_X1MOUSE || c == K_X2MOUSE) { @@ -1281,7 +1276,7 @@ void wait_return(int redraw) // If the screen size changed screen_resize() will redraw the screen. // Otherwise the screen is only redrawn if 'redraw' is set and no ':' // typed. - tmpState = State; + int tmpState = State; State = oldState; // restore State before screen_resize() setmouse(); msg_check(); @@ -1329,7 +1324,7 @@ static void hit_return_msg(void) } /// Set "keep_msg" to "s". Free the old value and check for NULL pointer. -void set_keep_msg(char *s, int attr) +void set_keep_msg(const char *s, int attr) { xfree(keep_msg); if (s != NULL && msg_silent == 0) { @@ -1341,9 +1336,17 @@ void set_keep_msg(char *s, int attr) keep_msg_attr = attr; } -void msgmore(long n) +/// Return true if printing messages should currently be done. +bool messaging(void) { - long pn; + // TODO(bfredl): with general support for "async" messages with p_ch, + // this should be re-enabled. + return !(p_lz && char_avail() && !KeyTyped) && (p_ch > 0 || ui_has(kUIMessages)); +} + +void msgmore(int n) +{ + int pn; if (global_busy // no messages now, wait until global is finished || !messaging()) { // 'lazyredraw' set, don't do messages now @@ -1366,17 +1369,17 @@ void msgmore(long n) if (pn > p_report) { if (n > 0) { vim_snprintf(msg_buf, MSG_BUF_LEN, - NGETTEXT("%ld more line", "%ld more lines", pn), + NGETTEXT("%d more line", "%d more lines", pn), pn); } else { vim_snprintf(msg_buf, MSG_BUF_LEN, - NGETTEXT("%ld line less", "%ld fewer lines", pn), + NGETTEXT("%d line less", "%d fewer lines", pn), pn); } if (got_int) { xstrlcat(msg_buf, _(" (Interrupted)"), MSG_BUF_LEN); } - if (msg(msg_buf)) { + if (msg(msg_buf, 0)) { set_keep_msg(msg_buf, 0); keep_msg_more = true; } @@ -1397,7 +1400,11 @@ void msg_ext_set_kind(const char *msg_kind) /// Prepare for outputting characters in the command line. void msg_start(void) { - int did_return = false; + bool did_return = false; + + if (msg_row < cmdline_row) { + msg_row = cmdline_row; + } if (!msg_silent) { XFREE_CLEAR(keep_msg); // don't display old message now @@ -1421,7 +1428,7 @@ void msg_start(void) if (!msg_scroll && full_screen) { // overwrite last message msg_row = cmdline_row; - msg_col = cmdmsg_rl ? Columns - 1 : 0; + msg_col = 0; } else if (msg_didout || (p_ch == 0 && !ui_has(kUIMessages))) { // start message on next line msg_putchar('\n'); did_return = true; @@ -1462,7 +1469,7 @@ void msg_putchar(int c) void msg_putchar_attr(int c, int attr) { - char buf[MB_MAXBYTES + 1]; + char buf[MB_MAXCHAR + 1]; if (IS_SPECIAL(c)) { buf[0] = (char)K_SPECIAL; @@ -1470,33 +1477,33 @@ void msg_putchar_attr(int c, int attr) buf[2] = (char)K_THIRD(c); buf[3] = NUL; } else { - buf[utf_char2bytes(c, (char *)buf)] = NUL; + buf[utf_char2bytes(c, buf)] = NUL; } - msg_puts_attr((const char *)buf, attr); + msg_puts_attr(buf, attr); } -void msg_outnum(long n) +void msg_outnum(int n) { char buf[20]; - snprintf(buf, sizeof(buf), "%ld", n); + snprintf(buf, sizeof(buf), "%d", n); msg_puts(buf); } -void msg_home_replace(char *fname) +void msg_home_replace(const char *fname) { msg_home_replace_attr(fname, 0); } -void msg_home_replace_hl(char *fname) +void msg_home_replace_hl(const char *fname) { msg_home_replace_attr(fname, HL_ATTR(HLF_D)); } -static void msg_home_replace_attr(char *fname, int attr) +static void msg_home_replace_attr(const char *fname, int attr) { char *name = home_replace_save(NULL, fname); - msg_outtrans_attr(name, attr); + msg_outtrans(name, attr); xfree(name); } @@ -1505,44 +1512,33 @@ static void msg_home_replace_attr(char *fname, int attr) /// Use attributes 'attr'. /// /// @return the number of characters it takes on the screen. -int msg_outtrans(char *str) -{ - return msg_outtrans_attr(str, 0); -} - -int msg_outtrans_attr(const char *str, int attr) -{ - return msg_outtrans_len_attr(str, (int)strlen(str), attr); -} - -int msg_outtrans_len(const char *str, int len) +int msg_outtrans(const char *str, int attr) { - return msg_outtrans_len_attr(str, len, 0); + return msg_outtrans_len(str, (int)strlen(str), attr); } /// Output one character at "p". /// Handles multi-byte characters. /// /// @return pointer to the next character. -char *msg_outtrans_one(char *p, int attr) +const char *msg_outtrans_one(const char *p, int attr) { int l; if ((l = utfc_ptr2len(p)) > 1) { - msg_outtrans_len_attr(p, l, attr); + msg_outtrans_len(p, l, attr); return p + l; } - msg_puts_attr((const char *)transchar_byte((uint8_t)(*p)), attr); + msg_puts_attr(transchar_byte_buf(NULL, (uint8_t)(*p)), attr); return p + 1; } -int msg_outtrans_len_attr(const char *msgstr, int len, int attr) +int msg_outtrans_len(const char *msgstr, int len, int attr) { int retval = 0; const char *str = msgstr; const char *plain_start = msgstr; char *s; - int mb_l; int c; int save_got_int = got_int; @@ -1555,17 +1551,18 @@ int msg_outtrans_len_attr(const char *msgstr, int len, int attr) attr &= ~MSG_HIST; } - // If the string starts with a composing character first draw a space on - // which the composing char can be drawn. - if (utf_iscomposing(utf_ptr2char((char *)msgstr))) { - msg_puts_attr(" ", attr); + // When drawing over the command line no need to clear it later or remove + // the mode message. + if (msg_row >= cmdline_row && msg_col == 0) { + clear_cmdline = false; + mode_displayed = false; } // Go over the string. Special characters are translated and printed. // Normal characters are printed several at a time. while (--len >= 0 && !got_int) { // Don't include composing chars after the end. - mb_l = utfc_ptr2len_len(str, len + 1); + int mb_l = utfc_ptr2len_len(str, len + 1); if (mb_l > 1) { c = utf_ptr2char(str); if (vim_isprintc(c)) { @@ -1575,25 +1572,24 @@ int msg_outtrans_len_attr(const char *msgstr, int len, int attr) // Unprintable multi-byte char: print the printable chars so // far and the translation of the unprintable char. if (str > plain_start) { - msg_puts_attr_len(plain_start, str - plain_start, attr); + msg_puts_len(plain_start, str - plain_start, attr); } plain_start = str + mb_l; - msg_puts_attr((const char *)transchar(c), - (attr == 0 ? HL_ATTR(HLF_8) : attr)); + msg_puts_attr(transchar_buf(NULL, c), attr == 0 ? HL_ATTR(HLF_8) : attr); retval += char2cells(c); } len -= mb_l - 1; str += mb_l; } else { - s = (char *)transchar_byte((uint8_t)(*str)); + s = transchar_byte_buf(NULL, (uint8_t)(*str)); if (s[1] != NUL) { // Unprintable char: print the printable chars so far and the // translation of the unprintable char. if (str > plain_start) { - msg_puts_attr_len(plain_start, str - plain_start, attr); + msg_puts_len(plain_start, str - plain_start, attr); } plain_start = str + 1; - msg_puts_attr((const char *)s, attr == 0 ? HL_ATTR(HLF_8) : attr); + msg_puts_attr(s, attr == 0 ? HL_ATTR(HLF_8) : attr); retval += (int)strlen(s); } else { retval++; @@ -1604,7 +1600,7 @@ int msg_outtrans_len_attr(const char *msgstr, int len, int attr) if (str > plain_start && !got_int) { // Print the printable chars at the end. - msg_puts_attr_len(plain_start, str - plain_start, attr); + msg_puts_len(plain_start, str - plain_start, attr); } got_int |= save_got_int; @@ -1612,11 +1608,11 @@ int msg_outtrans_len_attr(const char *msgstr, int len, int attr) return retval; } -void msg_make(char *arg) +void msg_make(const char *arg) { int i; - static char *str = "eeffoc"; - static char *rs = "Plon#dqg#vxjduB"; + static const char *str = "eeffoc"; + static const char *rs = "Plon#dqg#vxjduB"; arg = skipwhite(arg); for (i = 5; *arg && i >= 0; i--) { @@ -1667,9 +1663,9 @@ int msg_outtrans_special(const char *strstart, bool from, int maxlen) } if (text[0] != NUL && text[1] == NUL) { // single-byte character or illegal byte - text = (char *)transchar_byte((uint8_t)text[0]); + text = transchar_byte_buf(NULL, (uint8_t)text[0]); } - const int len = vim_strsize((char *)text); + const int len = vim_strsize(text); if (maxlen > 0 && retval + len >= maxlen) { break; } @@ -1773,7 +1769,7 @@ const char *str2special(const char **const sp, const bool replace_spaces, const || c < ' ' || (replace_spaces && c == ' ') || (replace_lt && c == '<')) { - return (const char *)get_special_key_name(c, modifiers); + return get_special_key_name(c, modifiers); } buf[0] = (char)c; buf[1] = NUL; @@ -1802,20 +1798,20 @@ void str2specialbuf(const char *sp, char *buf, size_t len) } /// print line for :print or :list command -void msg_prt_line(char *s, int list) +void msg_prt_line(const char *s, int list) { int c; int col = 0; int n_extra = 0; int c_extra = 0; int c_final = 0; - char *p_extra = NULL; // init to make SASC shut up + const char *p_extra = NULL; // init to make SASC shut up int n; int attr = 0; - char *lead = NULL; + const char *lead = NULL; bool in_multispace = false; int multispace_pos = 0; - char *trail = NULL; + const char *trail = NULL; int l; if (curwin->w_p_list) { @@ -1878,10 +1874,13 @@ void msg_prt_line(char *s, int list) continue; } else { attr = 0; - c = (unsigned char)(*s++); - in_multispace = c == ' ' && ((col > 0 && s[-2] == ' ') || *s == ' '); - if (!in_multispace) { - multispace_pos = 0; + c = (uint8_t)(*s++); + if (list) { + in_multispace = c == ' ' && (*s == ' ' + || (col > 0 && s[-2] == ' ')); + if (!in_multispace) { + multispace_pos = 0; + } } if (c == TAB && (!list || curwin->w_p_lcs_chars.tab1)) { // tab amount depends on current column @@ -1913,7 +1912,7 @@ void msg_prt_line(char *s, int list) s--; } else if (c != NUL && (n = byte2cells(c)) > 1) { n_extra = n - 1; - p_extra = (char *)transchar_byte(c); + p_extra = transchar_byte_buf(NULL, c); c_extra = NUL; c_final = NUL; c = (unsigned char)(*p_extra++); @@ -1921,7 +1920,7 @@ void msg_prt_line(char *s, int list) // the same in plain text. attr = HL_ATTR(HLF_0); } else if (c == ' ') { - if (list && lead != NULL && s <= lead && in_multispace + if (lead != NULL && s <= lead && in_multispace && curwin->w_p_lcs_chars.leadmultispace != NULL) { c = curwin->w_p_lcs_chars.leadmultispace[multispace_pos++]; if (curwin->w_p_lcs_chars.leadmultispace[multispace_pos] == NUL) { @@ -1934,7 +1933,7 @@ void msg_prt_line(char *s, int list) } else if (trail != NULL && s > trail) { c = curwin->w_p_lcs_chars.trail; attr = HL_ATTR(HLF_0); - } else if (list && in_multispace + } else if (in_multispace && curwin->w_p_lcs_chars.multispace != NULL) { c = curwin->w_p_lcs_chars.multispace[multispace_pos++]; if (curwin->w_p_lcs_chars.multispace[multispace_pos] == NUL) { @@ -1958,40 +1957,6 @@ void msg_prt_line(char *s, int list) msg_clr_eos(); } -/// Use grid_puts() to output one multi-byte character. -/// -/// @return the pointer "s" advanced to the next character. -static char *screen_puts_mbyte(char *s, int l, int attr) -{ - int cw; - attr = hl_combine_attr(HL_ATTR(HLF_MSG), attr); - - msg_didout = true; // remember that line is not empty - cw = utf_ptr2cells(s); - if (cw > 1 - && (cmdmsg_rl ? msg_col <= 1 : msg_col == Columns - 1)) { - // Doesn't fit, print a highlighted '>' to fill it up. - msg_screen_putchar('>', HL_ATTR(HLF_AT)); - return s; - } - - grid_puts_len(&msg_grid_adj, s, l, msg_row, msg_col, attr); - if (cmdmsg_rl) { - msg_col -= cw; - if (msg_col == 0) { - msg_col = Columns; - msg_row++; - } - } else { - msg_col += cw; - if (msg_col >= Columns) { - msg_col = 0; - msg_row++; - } - } - return s + l; -} - /// Output a string to the screen at position msg_row, msg_col. /// Update msg_row and msg_col for the next message. void msg_puts(const char *s) @@ -2007,29 +1972,23 @@ void msg_puts_title(const char *s) /// Show a message in such a way that it always fits in the line. Cut out a /// part in the middle and replace it with "..." when necessary. /// Does not handle multi-byte characters! -void msg_outtrans_long_attr(char *longstr, int attr) -{ - msg_outtrans_long_len_attr(longstr, (int)strlen(longstr), attr); -} - -void msg_outtrans_long_len_attr(char *longstr, int len, int attr) +void msg_outtrans_long(const char *longstr, int attr) { + int len = (int)strlen(longstr); int slen = len; - int room; - - room = Columns - msg_col; + int room = Columns - msg_col; if (len > room && room >= 20) { slen = (room - 3) / 2; - msg_outtrans_len_attr(longstr, slen, attr); + msg_outtrans_len(longstr, slen, attr); msg_puts_attr("...", HL_ATTR(HLF_8)); } - msg_outtrans_len_attr(longstr + len - slen, slen, attr); + msg_outtrans_len(longstr + len - slen, slen, attr); } /// Basic function for writing a message with highlight attributes. void msg_puts_attr(const char *const s, const int attr) { - msg_puts_attr_len(s, -1, attr); + msg_puts_len(s, -1, attr); } /// Write a message with highlight attributes @@ -2037,7 +1996,7 @@ void msg_puts_attr(const char *const s, const int attr) /// @param[in] str NUL-terminated message string. /// @param[in] len Length of the string or -1. /// @param[in] attr Highlight attribute. -void msg_puts_attr_len(const char *const str, const ptrdiff_t len, int attr) +void msg_puts_len(const char *const str, const ptrdiff_t len, int attr) FUNC_ATTR_NONNULL_ALL { assert(len < 0 || memchr(str, 0, (size_t)len) == NULL); @@ -2113,7 +2072,7 @@ void msg_printf_attr(const int attr, const char *const fmt, ...) va_end(ap); msg_scroll = true; - msg_puts_attr_len(msgbuf, (ptrdiff_t)len, attr); + msg_puts_len(msgbuf, (ptrdiff_t)len, attr); } static void msg_ext_emit_chunk(void) @@ -2130,19 +2089,13 @@ static void msg_ext_emit_chunk(void) ADD(msg_ext_chunks, ARRAY_OBJ(chunk)); } -/// The display part of msg_puts_attr_len(). +/// The display part of msg_puts_len(). /// May be called recursively to display scroll-back text. static void msg_puts_display(const char *str, int maxlen, int attr, int recurse) { const char *s = str; - const char *t_s = str; // String from "t_s" to "s" is still todo. - int t_col = 0; // Screen cells todo, 0 when "t_s" not used. - int l; - int cw; - const char *sb_str = (char *)str; + const char *sb_str = str; int sb_col = msg_col; - int wrap; - int did_last_char; did_wait_return = false; @@ -2152,197 +2105,175 @@ static void msg_puts_display(const char *str, int maxlen, int attr, int recurse) msg_ext_last_attr = attr; } // Concat pieces with the same highlight - size_t len = strnlen(str, (size_t)maxlen); // -V781 - ga_concat_len(&msg_ext_last_chunk, (char *)str, len); + size_t len = strnlen(str, (size_t)maxlen); + ga_concat_len(&msg_ext_last_chunk, str, len); msg_ext_cur_len += len; return; } + int print_attr = hl_combine_attr(HL_ATTR(HLF_MSG), attr); msg_grid_validate(); cmdline_was_last_drawn = redrawing_cmdline; - while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL) { - // We are at the end of the screen line when: - |