From 9609f327daee70fbb6752bde41a1accc5e38a65b Mon Sep 17 00:00:00 2001 From: erw7 Date: Wed, 1 May 2019 06:10:42 +0900 Subject: [PATCH] Fix garbled problem with msg_puts_printf on Windows --- src/nvim/message.c | 14 ++++++++------ src/nvim/vim.h | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/nvim/message.c b/src/nvim/message.c index 5188824901..86a9904392 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -2303,18 +2303,19 @@ int msg_use_printf(void) static void msg_puts_printf(const char *str, const ptrdiff_t maxlen) { const char *s = str; - char buf[4]; + char buf[7]; char *p; while ((maxlen < 0 || s - str < maxlen) && *s != NUL) { + int len = utf_ptr2len((const char_u *)s); if (!(silent_mode && p_verbose == 0)) { // NL --> CR NL translation (for Unix, not for "--version") p = &buf[0]; if (*s == '\n' && !info_message) { *p++ = '\r'; } - *p++ = *s; - *p = '\0'; + memcpy(p, s, len); + *(p + len) = '\0'; if (info_message) { mch_msg(buf); } else { @@ -2323,20 +2324,21 @@ static void msg_puts_printf(const char *str, const ptrdiff_t maxlen) } // primitive way to compute the current column + int cw = utf_char2cells(utf_ptr2char((const char_u *)s)); if (cmdmsg_rl) { if (*s == '\r' || *s == '\n') { msg_col = Columns - 1; } else { - msg_col--; + msg_col -= cw; } } else { if (*s == '\r' || *s == '\n') { msg_col = 0; } else { - msg_col++; + msg_col += cw; } } - s++; + s += len; } msg_didout = true; // assume that line is not empty } diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 3e0a5907be..d74427ef26 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -35,6 +35,10 @@ enum { NUMBUFLEN = 65 }; #include "nvim/gettext.h" +#ifdef WIN32 +# include "nvim/mbyte.h" // for utf8_to_utf16 +#endif + // special attribute addition: Put message in history #define MSG_HIST 0x1000 @@ -287,9 +291,34 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext() // functions of these names. The declarations would break if the defines had // been seen at that stage. But it must be before globals.h, where error_ga // is declared. -#define mch_errmsg(str) fprintf(stderr, "%s", (str)) +#ifdef WIN32 +# define mch_errmsg(str) \ + do { \ + wchar_t *utf16str; \ + int conversion_result = utf8_to_utf16((str), &utf16str); \ + if (conversion_result != 0) { \ + EMSG2("utf8_to_utf16 failed: %d", conversion_result); \ + } else { \ + fwprintf(stderr, L"%ls", utf16str); \ + xfree(utf16str); \ + } \ + } while (0) +# define mch_msg(str) \ + do { \ + wchar_t *utf16str; \ + int conversion_result = utf8_to_utf16((str), &utf16str); \ + if (conversion_result != 0) { \ + EMSG2("utf8_to_utf16 failed: %d", conversion_result); \ + } else { \ + wprintf(L"%ls", utf16str); \ + xfree(utf16str); \ + } \ + } while (0) +#else +# define mch_errmsg(str) fprintf(stderr, "%s", (str)) +# define mch_msg(str) printf("%s", (str)) +#endif #define display_errors() fflush(stderr) -#define mch_msg(str) printf("%s", (str)) #include "nvim/globals.h" // global variables and messages #include "nvim/buffer_defs.h" // buffer and windows