diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2019-08-13 05:47:58 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2019-08-15 00:28:41 +0200 |
commit | 8727f7a6a4ef10ce7536fbc003ef13b768f1aa91 (patch) | |
tree | 8b577b3e7b8e997341bbad3747dd19f7015da216 /src | |
parent | fc60d92795d20f3f3c498b97aae5e46a71cafa8d (diff) | |
download | rneovim-8727f7a6a4ef10ce7536fbc003ef13b768f1aa91.tar.gz rneovim-8727f7a6a4ef10ce7536fbc003ef13b768f1aa91.tar.bz2 rneovim-8727f7a6a4ef10ce7536fbc003ef13b768f1aa91.zip |
utf8_to_utf16: align with libuv
- take a size parameter
- always NUL-terminate the result
- return libuv error code
- handle error in caller only (avoid redundant messages)
https://github.com/libuv/libuv/commit/53995a3825d23eacd01e2bcfa35642c4a188d32b
https://github.com/libuv/libuv/commit/4c945f49365ab4d6e1b07bf0ef2893455dc04622
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/mbyte.c | 60 | ||||
-rw-r--r-- | src/nvim/message.c | 14 | ||||
-rw-r--r-- | src/nvim/os/fs.c | 6 | ||||
-rw-r--r-- | src/nvim/os/pty_process_win.c | 18 |
4 files changed, 47 insertions, 51 deletions
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index fae7635d34..e40beed0dd 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1356,45 +1356,41 @@ static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1, # define CP_UTF8 65001 /* magic number from winnls.h */ #endif -/// Reassigns `strw` to a new, allocated pointer to a UTF16 string. -int utf8_to_utf16(const char *str, wchar_t **strw) +/// Converts string from UTF-8 to UTF-16. +/// +/// @param utf8 UTF-8 string. +/// @param utf8len Length of `utf8`. May be -1 if `utf8` is NUL-terminated. +/// @param utf16[out,allocated] NUL-terminated UTF-16 string, or NULL on error +/// @return 0 on success, or libuv error code +int utf8_to_utf16(const char *utf8, int utf8len, wchar_t **utf16) FUNC_ATTR_NONNULL_ALL { - ssize_t wchar_len = 0; - - // Compute the length needed to store the converted widechar string. - wchar_len = MultiByteToWideChar(CP_UTF8, - 0, // dwFlags: must be 0 for utf8 - str, // lpMultiByteStr: string to convert - -1, // -1 => process up to NUL - NULL, // lpWideCharStr: converted string - 0); // 0 => return length, don't convert - if (wchar_len == 0) { - return GetLastError(); - } - - ssize_t buf_sz = wchar_len * sizeof(wchar_t); - - if (buf_sz == 0) { - *strw = NULL; - return 0; + // Compute the length needed for the converted UTF-16 string. + int bufsize = MultiByteToWideChar(CP_UTF8, + 0, // dwFlags: must be 0 for UTF-8 + utf8, // -1: process up to NUL + utf8len, + NULL, + 0); // 0: get length, don't convert + if (bufsize == 0) { + *utf16 = NULL; + return uv_translate_sys_error(GetLastError()); } - char *buf = xmalloc(buf_sz); - char *pos = buf; + // Allocate the destination buffer adding an extra byte for the terminating + // NULL. If `utf8len` is not -1 MultiByteToWideChar will not add it, so + // we do it ourselves always, just in case. + *utf16 = xmalloc(sizeof(wchar_t) * (bufsize + 1)); - int r = MultiByteToWideChar(CP_UTF8, - 0, - str, - -1, - (wchar_t *)pos, - wchar_len); - assert(r == wchar_len); - if (r != wchar_len) { - EMSG2("MultiByteToWideChar failed: %d", r); + // Convert to UTF-16. + bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize); + if (bufsize == 0) { + xfree(*utf16); + *utf16 = NULL; + return uv_translate_sys_error(GetLastError()); } - *strw = (wchar_t *)pos; + (*utf16)[bufsize] = L'\0'; return 0; } diff --git a/src/nvim/message.c b/src/nvim/message.c index b043df17d3..6e935022ca 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -2559,10 +2559,11 @@ static int do_more_prompt(int typed_char) #if defined(WIN32) void mch_errmsg(char *str) { + assert(str != NULL); wchar_t *utf16str; - int conversion_result = utf8_to_utf16((str), &utf16str); - if (conversion_result != 0) { - EMSG2("utf8_to_utf16 failed: %d", conversion_result); + int r = utf8_to_utf16(str, -1, &utf16str); + if (r != 0) { + fprintf(stderr, "utf8_to_utf16 failed: %d", r); } else { fwprintf(stderr, L"%ls", utf16str); xfree(utf16str); @@ -2572,10 +2573,11 @@ void mch_errmsg(char *str) // Give a message. To be used when the UI is not initialized yet. void mch_msg(char *str) { + assert(str != NULL); wchar_t *utf16str; - int conversion_result = utf8_to_utf16((str), &utf16str); - if (conversion_result != 0) { - EMSG2("utf8_to_utf16 failed: %d", conversion_result); + int r = utf8_to_utf16(str, -1, &utf16str); + if (r != 0) { + fprintf(stderr, "utf8_to_utf16 failed: %d", r); } else { wprintf(L"%ls", utf16str); xfree(utf16str); diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index dcb3ef7c4a..615ab143b2 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -1180,12 +1180,10 @@ char *os_resolve_shortcut(const char *fname) &IID_IShellLinkW, (void **)&pslw); if (hr == S_OK) { wchar_t *p; - const int conversion_result = utf8_to_utf16(fname, &p); + const int conversion_result = utf8_to_utf16(fname, len, &p); if (conversion_result != 0) { EMSG2("utf8_to_utf16 failed: %d", conversion_result); - } - - if (p != NULL) { + } else if (p != NULL) { // Get a pointer to the IPersistFile interface. hr = pslw->lpVtbl->QueryInterface( pslw, &IID_IPersistFile, (void **)&ppf); diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c index 290668bca3..ef48da953a 100644 --- a/src/nvim/os/pty_process_win.c +++ b/src/nvim/os/pty_process_win.c @@ -93,9 +93,9 @@ int pty_process_spawn(PtyProcess *ptyproc) } if (proc->cwd != NULL) { - status = utf8_to_utf16(proc->cwd, &cwd); + status = utf8_to_utf16(proc->cwd, -1, &cwd); if (status != 0) { - emsg = "Failed to convert pwd form utf8 to utf16."; + emsg = "utf8_to_utf16 failed"; goto cleanup; } } @@ -103,7 +103,7 @@ int pty_process_spawn(PtyProcess *ptyproc) status = build_cmd_line(proc->argv, &cmd_line, os_shell_is_cmdexe(proc->argv[0])); if (status != 0) { - emsg = "Failed to convert cmd line form utf8 to utf16."; + emsg = "build_cmd_line failed"; goto cleanup; } @@ -115,7 +115,7 @@ int pty_process_spawn(PtyProcess *ptyproc) NULL, // Optional environment variables &err); if (spawncfg == NULL) { - emsg = "Failed winpty_spawn_config_new."; + emsg = "winpty_spawn_config_new failed"; goto cleanup; } @@ -128,9 +128,9 @@ int pty_process_spawn(PtyProcess *ptyproc) &err)) { if (win_err) { status = (int)win_err; - emsg = "Failed spawn process."; + emsg = "failed to spawn process"; } else { - emsg = "Failed winpty_spawn."; + emsg = "winpty_spawn failed"; } goto cleanup; } @@ -160,11 +160,11 @@ int pty_process_spawn(PtyProcess *ptyproc) cleanup: if (status) { // In the case of an error of MultiByteToWideChar or CreateProcessW. - ELOG("%s error code: %d", emsg, status); + ELOG("%s: error code: %d", emsg, status); status = os_translate_sys_error(status); } else if (err != NULL) { status = (int)winpty_error_code(err); - ELOG("%s error code: %d", emsg, status); + ELOG("%s: error code: %d", emsg, status); status = translate_winpty_error(status); } winpty_error_free(err); @@ -308,7 +308,7 @@ static int build_cmd_line(char **argv, wchar_t **cmd_line, bool is_cmdexe) } } - int result = utf8_to_utf16(utf8_cmd_line, cmd_line); + int result = utf8_to_utf16(utf8_cmd_line, -1, cmd_line); xfree(utf8_cmd_line); return result; } |