mirror of
https://github.com/neovim/neovim.git
synced 2024-12-21 03:35:02 -07:00
Merge #10761 from justinmk/win-utf-libuv-align
utf8_to_utf16, utf16_to_utf8: align with libuv
This commit is contained in:
commit
6261d2658f
@ -237,7 +237,7 @@ int main(int argc, char **argv)
|
||||
char **argv = xmalloc((size_t)argc * sizeof(char *));
|
||||
for (int i = 0; i < argc; i++) {
|
||||
char *buf = NULL;
|
||||
utf16_to_utf8(argv_w[i], &buf);
|
||||
utf16_to_utf8(argv_w[i], -1, &buf);
|
||||
assert(buf);
|
||||
argv[i] = buf;
|
||||
}
|
||||
|
121
src/nvim/mbyte.c
121
src/nvim/mbyte.c
@ -1356,83 +1356,86 @@ 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();
|
||||
// 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());
|
||||
}
|
||||
|
||||
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) {
|
||||
*strw = NULL;
|
||||
return 0;
|
||||
// Convert to UTF-16.
|
||||
bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
|
||||
if (bufsize == 0) {
|
||||
XFREE_CLEAR(*utf16);
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
char *buf = xmalloc(buf_sz);
|
||||
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;
|
||||
|
||||
(*utf16)[bufsize] = L'\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Reassigns `str` to a new, allocated pointer to a UTF8 string.
|
||||
int utf16_to_utf8(const wchar_t *strw, char **str)
|
||||
/// Converts string from UTF-16 to UTF-8.
|
||||
///
|
||||
/// @param utf16 UTF-16 string.
|
||||
/// @param utf16len Length of `utf16`. May be -1 if `utf16` is NUL-terminated.
|
||||
/// @param utf8[out,allocated] NUL-terminated UTF-8 string, or NULL on error
|
||||
/// @return 0 on success, or libuv error code
|
||||
int utf16_to_utf8(const wchar_t *utf16, int utf16len, char **utf8)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
*str = NULL;
|
||||
// Compute the space required to store the string as UTF-8.
|
||||
DWORD utf8_len = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
strw,
|
||||
-1,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (utf8_len == 0) {
|
||||
return GetLastError();
|
||||
// Compute the space needed for the converted UTF-8 string.
|
||||
DWORD bufsize = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
utf16,
|
||||
utf16len,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (bufsize == 0) {
|
||||
*utf8 = NULL;
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
*str = xmallocz(utf8_len);
|
||||
// Allocate the destination buffer adding an extra byte for the terminating
|
||||
// NULL. If `utf16len` is not -1 WideCharToMultiByte will not add it, so
|
||||
// we do it ourselves always, just in case.
|
||||
*utf8 = xmalloc(bufsize + 1);
|
||||
|
||||
// Convert to UTF-8.
|
||||
utf8_len = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
strw,
|
||||
-1,
|
||||
*str,
|
||||
utf8_len,
|
||||
NULL,
|
||||
NULL);
|
||||
if (utf8_len == 0) {
|
||||
XFREE_CLEAR(*str);
|
||||
return GetLastError();
|
||||
bufsize = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
utf16,
|
||||
utf16len,
|
||||
*utf8,
|
||||
bufsize,
|
||||
NULL,
|
||||
NULL);
|
||||
if (bufsize == 0) {
|
||||
XFREE_CLEAR(*utf8);
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
}
|
||||
(*str)[utf8_len] = '\0';
|
||||
|
||||
(*utf8)[bufsize] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -178,7 +178,7 @@ char *os_getenvname_at_index(size_t index)
|
||||
for (wchar_t *it = env; *it != L'\0' || *(it + 1) != L'\0'; it++) {
|
||||
if (index == current_index) {
|
||||
char *utf8_str;
|
||||
int conversion_result = utf16_to_utf8(it, &utf8_str);
|
||||
int conversion_result = utf16_to_utf8(it, -1, &utf8_str);
|
||||
if (conversion_result != 0) {
|
||||
EMSG2("utf16_to_utf8 failed: %d", conversion_result);
|
||||
break;
|
||||
@ -258,7 +258,7 @@ void os_get_hostname(char *hostname, size_t size)
|
||||
host_utf16[host_wsize] = '\0';
|
||||
|
||||
char *host_utf8;
|
||||
int conversion_result = utf16_to_utf8(host_utf16, &host_utf8);
|
||||
int conversion_result = utf16_to_utf8(host_utf16, -1, &host_utf8);
|
||||
if (conversion_result != 0) {
|
||||
EMSG2("utf16_to_utf8 failed: %d", conversion_result);
|
||||
return;
|
||||
|
@ -293,7 +293,7 @@ static bool is_executable(const char *name, char **abspath)
|
||||
/// Checks if file `name` is executable under any of these conditions:
|
||||
/// - extension is in $PATHEXT and `name` is executable
|
||||
/// - result of any $PATHEXT extension appended to `name` is executable
|
||||
static bool is_executable_ext(char *name, char **abspath)
|
||||
static bool is_executable_ext(const char *name, char **abspath)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
const bool is_unix_shell = strstr((char *)path_tail(p_sh), "sh") != NULL;
|
||||
@ -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);
|
||||
if (conversion_result != 0) {
|
||||
EMSG2("utf8_to_utf16 failed: %d", conversion_result);
|
||||
}
|
||||
|
||||
if (p != NULL) {
|
||||
const int r = utf8_to_utf16(fname, -1, &p);
|
||||
if (r != 0) {
|
||||
EMSG2("utf8_to_utf16 failed: %d", r);
|
||||
} else if (p != NULL) {
|
||||
// Get a pointer to the IPersistFile interface.
|
||||
hr = pslw->lpVtbl->QueryInterface(
|
||||
pslw, &IID_IPersistFile, (void **)&ppf);
|
||||
@ -1210,9 +1208,9 @@ char *os_resolve_shortcut(const char *fname)
|
||||
ZeroMemory(wsz, MAX_PATH * sizeof(wchar_t));
|
||||
hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0);
|
||||
if (hr == S_OK && wsz[0] != NUL) {
|
||||
const int conversion_result = utf16_to_utf8(wsz, &rfname);
|
||||
if (conversion_result != 0) {
|
||||
EMSG2("utf16_to_utf8 failed: %d", conversion_result);
|
||||
const int r2 = utf16_to_utf8(wsz, -1, &rfname);
|
||||
if (r2 != 0) {
|
||||
EMSG2("utf16_to_utf8 failed: %d", r2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,6 @@ typedef struct {
|
||||
uv_dirent_t ent; ///< @private The entry information.
|
||||
} Directory;
|
||||
|
||||
/// Converts libuv error (negative int) to error description string.
|
||||
#define os_strerror uv_strerror
|
||||
|
||||
/// Converts system error code to libuv error code.
|
||||
#define os_translate_sys_error uv_translate_sys_error
|
||||
|
||||
// Values returned by os_nodetype()
|
||||
#define NODE_NORMAL 0 // file or directory, check with os_isdir()
|
||||
#define NODE_WRITABLE 1 // something we can write to (character
|
||||
|
@ -32,11 +32,12 @@
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
/// Function to convert libuv error to char * error description
|
||||
///
|
||||
/// negative libuv error codes are returned by a number of os functions.
|
||||
/// Converts libuv error (negative int) to error description string.
|
||||
#define os_strerror uv_strerror
|
||||
|
||||
/// Converts system error code to libuv error code.
|
||||
#define os_translate_sys_error uv_translate_sys_error
|
||||
|
||||
#ifdef WIN32
|
||||
# define os_strtok strtok_s
|
||||
#else
|
||||
|
@ -51,26 +51,26 @@ int pty_process_spawn(PtyProcess *ptyproc)
|
||||
|
||||
cfg = winpty_config_new(WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION, &err);
|
||||
if (cfg == NULL) {
|
||||
emsg = "Failed, winpty_config_new.";
|
||||
emsg = "winpty_config_new failed";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
winpty_config_set_initial_size(cfg, ptyproc->width, ptyproc->height);
|
||||
winpty_object = winpty_open(cfg, &err);
|
||||
if (winpty_object == NULL) {
|
||||
emsg = "Failed, winpty_open.";
|
||||
emsg = "winpty_open failed";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
status = utf16_to_utf8(winpty_conin_name(winpty_object), &in_name);
|
||||
status = utf16_to_utf8(winpty_conin_name(winpty_object), -1, &in_name);
|
||||
if (status != 0) {
|
||||
emsg = "Failed to convert in_name from utf16 to utf8.";
|
||||
emsg = "utf16_to_utf8(winpty_conin_name) failed";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
status = utf16_to_utf8(winpty_conout_name(winpty_object), &out_name);
|
||||
status = utf16_to_utf8(winpty_conout_name(winpty_object), -1, &out_name);
|
||||
if (status != 0) {
|
||||
emsg = "Failed to convert out_name from utf16 to utf8.";
|
||||
emsg = "utf16_to_utf8(winpty_conout_name) failed";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -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(proc->cwd) 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("pty_process_spawn: %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("pty_process_spawn: %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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user