mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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)53995a3825
4c945f4936
This commit is contained in:
parent
fc60d92795
commit
8727f7a6a4
@ -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 */
|
# define CP_UTF8 65001 /* magic number from winnls.h */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Reassigns `strw` to a new, allocated pointer to a UTF16 string.
|
/// Converts string from UTF-8 to UTF-16.
|
||||||
int utf8_to_utf16(const char *str, wchar_t **strw)
|
///
|
||||||
|
/// @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
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
ssize_t wchar_len = 0;
|
// Compute the length needed for the converted UTF-16 string.
|
||||||
|
int bufsize = MultiByteToWideChar(CP_UTF8,
|
||||||
// Compute the length needed to store the converted widechar string.
|
0, // dwFlags: must be 0 for UTF-8
|
||||||
wchar_len = MultiByteToWideChar(CP_UTF8,
|
utf8, // -1: process up to NUL
|
||||||
0, // dwFlags: must be 0 for utf8
|
utf8len,
|
||||||
str, // lpMultiByteStr: string to convert
|
NULL,
|
||||||
-1, // -1 => process up to NUL
|
0); // 0: get length, don't convert
|
||||||
NULL, // lpWideCharStr: converted string
|
if (bufsize == 0) {
|
||||||
0); // 0 => return length, don't convert
|
*utf16 = NULL;
|
||||||
if (wchar_len == 0) {
|
return uv_translate_sys_error(GetLastError());
|
||||||
return GetLastError();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t buf_sz = wchar_len * sizeof(wchar_t);
|
// 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));
|
||||||
|
|
||||||
if (buf_sz == 0) {
|
// Convert to UTF-16.
|
||||||
*strw = NULL;
|
bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
|
||||||
return 0;
|
if (bufsize == 0) {
|
||||||
|
xfree(*utf16);
|
||||||
|
*utf16 = NULL;
|
||||||
|
return uv_translate_sys_error(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
char *buf = xmalloc(buf_sz);
|
(*utf16)[bufsize] = L'\0';
|
||||||
char *pos = buf;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
*strw = (wchar_t *)pos;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2559,10 +2559,11 @@ static int do_more_prompt(int typed_char)
|
|||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
void mch_errmsg(char *str)
|
void mch_errmsg(char *str)
|
||||||
{
|
{
|
||||||
|
assert(str != NULL);
|
||||||
wchar_t *utf16str;
|
wchar_t *utf16str;
|
||||||
int conversion_result = utf8_to_utf16((str), &utf16str);
|
int r = utf8_to_utf16(str, -1, &utf16str);
|
||||||
if (conversion_result != 0) {
|
if (r != 0) {
|
||||||
EMSG2("utf8_to_utf16 failed: %d", conversion_result);
|
fprintf(stderr, "utf8_to_utf16 failed: %d", r);
|
||||||
} else {
|
} else {
|
||||||
fwprintf(stderr, L"%ls", utf16str);
|
fwprintf(stderr, L"%ls", utf16str);
|
||||||
xfree(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.
|
// Give a message. To be used when the UI is not initialized yet.
|
||||||
void mch_msg(char *str)
|
void mch_msg(char *str)
|
||||||
{
|
{
|
||||||
|
assert(str != NULL);
|
||||||
wchar_t *utf16str;
|
wchar_t *utf16str;
|
||||||
int conversion_result = utf8_to_utf16((str), &utf16str);
|
int r = utf8_to_utf16(str, -1, &utf16str);
|
||||||
if (conversion_result != 0) {
|
if (r != 0) {
|
||||||
EMSG2("utf8_to_utf16 failed: %d", conversion_result);
|
fprintf(stderr, "utf8_to_utf16 failed: %d", r);
|
||||||
} else {
|
} else {
|
||||||
wprintf(L"%ls", utf16str);
|
wprintf(L"%ls", utf16str);
|
||||||
xfree(utf16str);
|
xfree(utf16str);
|
||||||
|
@ -1180,12 +1180,10 @@ char *os_resolve_shortcut(const char *fname)
|
|||||||
&IID_IShellLinkW, (void **)&pslw);
|
&IID_IShellLinkW, (void **)&pslw);
|
||||||
if (hr == S_OK) {
|
if (hr == S_OK) {
|
||||||
wchar_t *p;
|
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) {
|
if (conversion_result != 0) {
|
||||||
EMSG2("utf8_to_utf16 failed: %d", conversion_result);
|
EMSG2("utf8_to_utf16 failed: %d", conversion_result);
|
||||||
}
|
} else if (p != NULL) {
|
||||||
|
|
||||||
if (p != NULL) {
|
|
||||||
// Get a pointer to the IPersistFile interface.
|
// Get a pointer to the IPersistFile interface.
|
||||||
hr = pslw->lpVtbl->QueryInterface(
|
hr = pslw->lpVtbl->QueryInterface(
|
||||||
pslw, &IID_IPersistFile, (void **)&ppf);
|
pslw, &IID_IPersistFile, (void **)&ppf);
|
||||||
|
@ -93,9 +93,9 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (proc->cwd != NULL) {
|
if (proc->cwd != NULL) {
|
||||||
status = utf8_to_utf16(proc->cwd, &cwd);
|
status = utf8_to_utf16(proc->cwd, -1, &cwd);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
emsg = "Failed to convert pwd form utf8 to utf16.";
|
emsg = "utf8_to_utf16 failed";
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
|||||||
status = build_cmd_line(proc->argv, &cmd_line,
|
status = build_cmd_line(proc->argv, &cmd_line,
|
||||||
os_shell_is_cmdexe(proc->argv[0]));
|
os_shell_is_cmdexe(proc->argv[0]));
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
emsg = "Failed to convert cmd line form utf8 to utf16.";
|
emsg = "build_cmd_line failed";
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
|||||||
NULL, // Optional environment variables
|
NULL, // Optional environment variables
|
||||||
&err);
|
&err);
|
||||||
if (spawncfg == NULL) {
|
if (spawncfg == NULL) {
|
||||||
emsg = "Failed winpty_spawn_config_new.";
|
emsg = "winpty_spawn_config_new failed";
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,9 +128,9 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
|||||||
&err)) {
|
&err)) {
|
||||||
if (win_err) {
|
if (win_err) {
|
||||||
status = (int)win_err;
|
status = (int)win_err;
|
||||||
emsg = "Failed spawn process.";
|
emsg = "failed to spawn process";
|
||||||
} else {
|
} else {
|
||||||
emsg = "Failed winpty_spawn.";
|
emsg = "winpty_spawn failed";
|
||||||
}
|
}
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -160,11 +160,11 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
|||||||
cleanup:
|
cleanup:
|
||||||
if (status) {
|
if (status) {
|
||||||
// In the case of an error of MultiByteToWideChar or CreateProcessW.
|
// 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);
|
status = os_translate_sys_error(status);
|
||||||
} else if (err != NULL) {
|
} else if (err != NULL) {
|
||||||
status = (int)winpty_error_code(err);
|
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);
|
status = translate_winpty_error(status);
|
||||||
}
|
}
|
||||||
winpty_error_free(err);
|
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);
|
xfree(utf8_cmd_line);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user