From 771d42e426c8c634e6907d501502760dc745b6aa Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 29 May 2016 03:40:35 -0400 Subject: os_resolve_shortcut: initial port from Vim source --- src/nvim/buffer.c | 4 +- src/nvim/eval.c | 7 +-- src/nvim/os/fs.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 438a85dd5d..c934d44e70 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -4030,8 +4030,8 @@ void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname) if (!buf->b_p_bin) { char_u *rfname; - /* If the file name is a shortcut file, use the file it links to. */ - rfname = mch_resolve_shortcut(*ffname); + // If the file name is a shortcut file, use the file it links to. + rfname = os_resolve_shortcut(*ffname); if (rfname != NULL) { xfree(*ffname); *ffname = rfname; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 824b298592..7deb1c1bbb 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -13592,11 +13592,12 @@ static void f_resolve(typval_T *argvars, typval_T *rettv) { char_u *v = NULL; - v = mch_resolve_shortcut(p); - if (v != NULL) + v = os_resolve_shortcut(p); + if (v != NULL) { rettv->vval.v_string = v; - else + } else { rettv->vval.v_string = vim_strsave(p); + } } #else # ifdef HAVE_READLINK diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 8c1c80bfad..2199b83108 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -929,3 +929,133 @@ bool os_fileid_equal_fileinfo(const FileID *file_id, && file_id->device_id == file_info->stat.st_dev; } +#ifdef WIN32 +# include +/// When "fname" is the name of a shortcut (*.lnk) resolve the file it points +/// to and return that name in allocated memory. +/// Otherwise NULL is returned. +char_u * os_resolve_shortcut(char_u *fname) +{ + HRESULT hr; + IShellLink *psl = NULL; + IPersistFile *ppf = NULL; + OLECHAR wsz[MAX_PATH]; + WIN32_FIND_DATA ffd; // we get those free of charge + CHAR buf[MAX_PATH]; // could have simply reused 'wsz'... + char_u *rfname = NULL; + int len; + IShellLinkW *pslw = NULL; + WIN32_FIND_DATAW ffdw; // we get those free of charge + + // Check if the file name ends in ".lnk". Avoid calling CoCreateInstance(), + // it's quite slow. + if (fname == NULL) { + return rfname; + } + len = (int)STRLEN(fname); + if (len <= 4 || STRNICMP(fname + len - 4, ".lnk", 4) != 0) { + return rfname; + } + + CoInitialize(NULL); + +# ifdef FEAT_MBYTE + if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) { + // create a link manager object and request its interface + hr = CoCreateInstance( + &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + &IID_IShellLinkW, (void**)&pslw); + if (hr == S_OK) + { + WCHAR *p = enc_to_utf16(fname, NULL); + + if (p != NULL) { + // Get a pointer to the IPersistFile interface. + hr = pslw->lpVtbl->QueryInterface( + pslw, &IID_IPersistFile, (void**)&ppf); + if (hr != S_OK) + goto shortcut_errorw; + + // "load" the name and resolve the link + hr = ppf->lpVtbl->Load(ppf, p, STGM_READ); + if (hr != S_OK) { + goto shortcut_errorw; + } + +# if 0 // This makes Vim wait a long time if the target does not exist. + hr = pslw->lpVtbl->Resolve(pslw, NULL, SLR_NO_UI); + if (hr != S_OK) { + goto shortcut_errorw; + } +# endif + + // Get the path to the link target. + ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR)); + hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0); + if (hr == S_OK && wsz[0] != NUL) { + rfname = utf16_to_enc(wsz, NULL); + } + +shortcut_errorw: + xfree(p); + goto shortcut_end; + } + } + /* Retry with non-wide function (for Windows 98). */ + } +# endif + + // create a link manager object and request its interface + hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + &IID_IShellLink, (void**)&psl); + if (hr != S_OK) { + goto shortcut_end; + } + + // Get a pointer to the IPersistFile interface. + hr = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (void**)&ppf); + if (hr != S_OK) { + goto shortcut_end; + } + + // full path string must be in Unicode. + MultiByteToWideChar(CP_ACP, 0, (LPCSTR)fname, -1, wsz, MAX_PATH); + + // "load" the name and resolve the link + hr = ppf->lpVtbl->Load(ppf, wsz, STGM_READ); + if (hr != S_OK) { + goto shortcut_end; + } + +# if 0 // This makes Vim wait a long time if the target doesn't exist. + hr = psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI); + if (hr != S_OK) { + goto shortcut_end; + } +# endif + + // Get the path to the link target. + ZeroMemory(buf, MAX_PATH); + hr = psl->lpVtbl->GetPath(psl, buf, MAX_PATH, &ffd, 0); + if (hr == S_OK && buf[0] != NUL) { + rfname = vim_strsave((char_u *)buf); + } + +shortcut_end: + // Release all interface pointers (both belong to the same object) + if (ppf != NULL) { + ppf->lpVtbl->Release(ppf); + } + if (psl != NULL) { + psl->lpVtbl->Release(psl); + } +# ifdef FEAT_MBYTE + if (pslw != NULL) { + pslw->lpVtbl->Release(pslw); + } +# endif + + CoUninitialize(); + return rfname; +} +#endif -- cgit From 6b33e9b10348dc05440dbb3e1d55318983ef644f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 29 May 2016 03:59:37 -0400 Subject: utf8_to_utf16: adapt libuv's fs__capture_path --- src/nvim/os/fs.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 2199b83108..cd3cb03afe 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -922,7 +922,7 @@ bool os_fileid_equal(const FileID *file_id_1, const FileID *file_id_2) /// @param file_info Pointer to a `FileInfo` /// @return `true` if the `FileID` and the `FileInfo` represent te same file. bool os_fileid_equal_fileinfo(const FileID *file_id, - const FileInfo *file_info) + const FileInfo *file_info) FUNC_ATTR_NONNULL_ALL { return file_id->inode == file_info->stat.st_ino @@ -931,6 +931,49 @@ bool os_fileid_equal_fileinfo(const FileID *file_id, #ifdef WIN32 # include +#ifndef CP_UTF8 +# define CP_UTF8 65001 /* magic number from winnls.h */ +#endif + +static int utf8_to_utf16(const char *path, const WCHAR **pathw) + FUNC_ATTR_NONNULL_ALL +{ + ssize_t buf_sz = 0, path_len, pathw_len = 0; + + // Compute the length needed to store the converted widechar string. + pathw_len = MultiByteToWideChar(CP_UTF8, + 0, // dwFlags: must be 0 for utf8 + path, // lpMultiByteStr: string to convert + -1, + NULL, // lpWideCharStr: converted string + 0); // 0 => return length, don't convert + if (pathw_len == 0) { + return GetLastError(); + } + + buf_sz += pathw_len * sizeof(WCHAR); + + if (buf_sz == 0) { + *pathw = NULL; + return 0; + } + + char* buf = xmalloc(buf_sz); + char* pos = buf; + + DWORD r = MultiByteToWideChar(CP_UTF8, + 0, + path, + -1, + (WCHAR*) pos, + pathw_len); + assert(r == (DWORD) pathw_len); + *pathw = (WCHAR*) pos; + pos += r * sizeof(WCHAR); + + return 0; +} + /// When "fname" is the name of a shortcut (*.lnk) resolve the file it points /// to and return that name in allocated memory. /// Otherwise NULL is returned. @@ -962,19 +1005,19 @@ char_u * os_resolve_shortcut(char_u *fname) # ifdef FEAT_MBYTE if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) { // create a link manager object and request its interface - hr = CoCreateInstance( - &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - &IID_IShellLinkW, (void**)&pslw); - if (hr == S_OK) - { - WCHAR *p = enc_to_utf16(fname, NULL); + hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + &IID_IShellLinkW, (void**)&pslw); + if (hr == S_OK) { + WCHAR **p; + int len = utf8_to_utf16((char *)fname, p); if (p != NULL) { // Get a pointer to the IPersistFile interface. hr = pslw->lpVtbl->QueryInterface( pslw, &IID_IPersistFile, (void**)&ppf); - if (hr != S_OK) + if (hr != S_OK) { goto shortcut_errorw; + } // "load" the name and resolve the link hr = ppf->lpVtbl->Load(ppf, p, STGM_READ); -- cgit From 618aad3811ab52e06934408788beb163ec2be580 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 29 May 2016 05:10:25 -0400 Subject: os_resolve_shortcut: Remove legacy win16 codepath. --- src/nvim/os/fs.c | 43 +------------------------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index cd3cb03afe..0c1d8c4c8e 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -980,14 +980,13 @@ static int utf8_to_utf16(const char *path, const WCHAR **pathw) char_u * os_resolve_shortcut(char_u *fname) { HRESULT hr; - IShellLink *psl = NULL; IPersistFile *ppf = NULL; OLECHAR wsz[MAX_PATH]; WIN32_FIND_DATA ffd; // we get those free of charge CHAR buf[MAX_PATH]; // could have simply reused 'wsz'... char_u *rfname = NULL; int len; - IShellLinkW *pslw = NULL; + IShellLinkW *pslw = NULL; WIN32_FIND_DATAW ffdw; // we get those free of charge // Check if the file name ends in ".lnk". Avoid calling CoCreateInstance(), @@ -1044,54 +1043,14 @@ shortcut_errorw: goto shortcut_end; } } - /* Retry with non-wide function (for Windows 98). */ } # endif - // create a link manager object and request its interface - hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - &IID_IShellLink, (void**)&psl); - if (hr != S_OK) { - goto shortcut_end; - } - - // Get a pointer to the IPersistFile interface. - hr = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (void**)&ppf); - if (hr != S_OK) { - goto shortcut_end; - } - - // full path string must be in Unicode. - MultiByteToWideChar(CP_ACP, 0, (LPCSTR)fname, -1, wsz, MAX_PATH); - - // "load" the name and resolve the link - hr = ppf->lpVtbl->Load(ppf, wsz, STGM_READ); - if (hr != S_OK) { - goto shortcut_end; - } - -# if 0 // This makes Vim wait a long time if the target doesn't exist. - hr = psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI); - if (hr != S_OK) { - goto shortcut_end; - } -# endif - - // Get the path to the link target. - ZeroMemory(buf, MAX_PATH); - hr = psl->lpVtbl->GetPath(psl, buf, MAX_PATH, &ffd, 0); - if (hr == S_OK && buf[0] != NUL) { - rfname = vim_strsave((char_u *)buf); - } - shortcut_end: // Release all interface pointers (both belong to the same object) if (ppf != NULL) { ppf->lpVtbl->Release(ppf); } - if (psl != NULL) { - psl->lpVtbl->Release(psl); - } # ifdef FEAT_MBYTE if (pslw != NULL) { pslw->lpVtbl->Release(pslw); -- cgit From d96b359410ef59683575ee00f209860f7a879395 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 29 May 2016 05:18:05 -0400 Subject: os_resolve_shortcut: cleanup --- src/nvim/os/fs.c | 102 +++++++++++++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 0c1d8c4c8e..4833ef868e 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -935,41 +935,40 @@ bool os_fileid_equal_fileinfo(const FileID *file_id, # define CP_UTF8 65001 /* magic number from winnls.h */ #endif -static int utf8_to_utf16(const char *path, const WCHAR **pathw) +static int utf8_to_utf16(const char *str, WCHAR **strw) FUNC_ATTR_NONNULL_ALL { - ssize_t buf_sz = 0, path_len, pathw_len = 0; + ssize_t wchar_len = 0; // Compute the length needed to store the converted widechar string. - pathw_len = MultiByteToWideChar(CP_UTF8, + wchar_len = MultiByteToWideChar(CP_UTF8, 0, // dwFlags: must be 0 for utf8 - path, // lpMultiByteStr: string to convert - -1, + str, // lpMultiByteStr: string to convert + -1, // -1 => process up to NUL NULL, // lpWideCharStr: converted string - 0); // 0 => return length, don't convert - if (pathw_len == 0) { + 0); // 0 => return length, don't convert + if (wchar_len == 0) { return GetLastError(); } - buf_sz += pathw_len * sizeof(WCHAR); + ssize_t buf_sz = wchar_len * sizeof(WCHAR); if (buf_sz == 0) { - *pathw = NULL; + *strw = NULL; return 0; } char* buf = xmalloc(buf_sz); char* pos = buf; - DWORD r = MultiByteToWideChar(CP_UTF8, + int r = MultiByteToWideChar(CP_UTF8, 0, - path, + str, -1, (WCHAR*) pos, - pathw_len); - assert(r == (DWORD) pathw_len); - *pathw = (WCHAR*) pos; - pos += r * sizeof(WCHAR); + wchar_len); + assert(r == wchar_len); + *strw = (WCHAR*) pos; return 0; } @@ -982,12 +981,10 @@ char_u * os_resolve_shortcut(char_u *fname) HRESULT hr; IPersistFile *ppf = NULL; OLECHAR wsz[MAX_PATH]; - WIN32_FIND_DATA ffd; // we get those free of charge - CHAR buf[MAX_PATH]; // could have simply reused 'wsz'... char_u *rfname = NULL; int len; IShellLinkW *pslw = NULL; - WIN32_FIND_DATAW ffdw; // we get those free of charge + WIN32_FIND_DATAW ffdw; // Check if the file name ends in ".lnk". Avoid calling CoCreateInstance(), // it's quite slow. @@ -1001,61 +998,56 @@ char_u * os_resolve_shortcut(char_u *fname) CoInitialize(NULL); -# ifdef FEAT_MBYTE - if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) { - // create a link manager object and request its interface - hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - &IID_IShellLinkW, (void**)&pslw); - if (hr == S_OK) { - WCHAR **p; - int len = utf8_to_utf16((char *)fname, p); - - if (p != NULL) { - // Get a pointer to the IPersistFile interface. - hr = pslw->lpVtbl->QueryInterface( - pslw, &IID_IPersistFile, (void**)&ppf); - if (hr != S_OK) { - goto shortcut_errorw; - } + // create a link manager object and request its interface + hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + &IID_IShellLinkW, (void**)&pslw); + if (hr == S_OK) { + WCHAR **p; + //TODO(jkeyes): if this returns non-zero, report the error + (void)utf8_to_utf16((char *)fname, p); + + if (p != NULL) { + // Get a pointer to the IPersistFile interface. + hr = pslw->lpVtbl->QueryInterface( + pslw, &IID_IPersistFile, (void**)&ppf); + if (hr != S_OK) { + goto shortcut_errorw; + } - // "load" the name and resolve the link - hr = ppf->lpVtbl->Load(ppf, p, STGM_READ); - if (hr != S_OK) { - goto shortcut_errorw; - } + // "load" the name and resolve the link + hr = ppf->lpVtbl->Load(ppf, p, STGM_READ); + if (hr != S_OK) { + goto shortcut_errorw; + } # if 0 // This makes Vim wait a long time if the target does not exist. - hr = pslw->lpVtbl->Resolve(pslw, NULL, SLR_NO_UI); - if (hr != S_OK) { - goto shortcut_errorw; - } + hr = pslw->lpVtbl->Resolve(pslw, NULL, SLR_NO_UI); + if (hr != S_OK) { + goto shortcut_errorw; + } # endif - // Get the path to the link target. - ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR)); - hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0); - if (hr == S_OK && wsz[0] != NUL) { - rfname = utf16_to_enc(wsz, NULL); - } + // Get the path to the link target. + ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR)); + hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0); + if (hr == S_OK && wsz[0] != NUL) { + rfname = utf16_to_enc(wsz, NULL); + } shortcut_errorw: - xfree(p); - goto shortcut_end; - } + xfree(p); + goto shortcut_end; } } -# endif shortcut_end: // Release all interface pointers (both belong to the same object) if (ppf != NULL) { ppf->lpVtbl->Release(ppf); } -# ifdef FEAT_MBYTE if (pslw != NULL) { pslw->lpVtbl->Release(pslw); } -# endif CoUninitialize(); return rfname; -- cgit From 23aadb69486fbfc6739dfd8861278f99315023ba Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 29 May 2016 06:09:49 -0400 Subject: utf16_to_utf8 --- src/nvim/os/fs.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 4833ef868e..ce43eb9422 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -973,6 +973,41 @@ static int utf8_to_utf16(const char *str, WCHAR **strw) return 0; } +static int utf16_to_utf8(const WCHAR *strw, char **str) + FUNC_ATTR_NONNULL_ALL +{ + // Compute the space required to store the string as UTF-8. + ssize_t utf8_len = WideCharToMultiByte(CP_UTF8, + 0, + strw, + -1, + NULL, + 0, + NULL, + NULL); + if (utf8_len == 0) { + return GetLastError(); + } + + ssize_t buf_sz = utf8_len * sizeof(char); + char* buf = xmalloc(buf_sz); + char* pos = buf; + + // Convert string to UTF-8. + int r = WideCharToMultiByte(CP_UTF8, + 0, + strw, + -1, + (LPSTR*) pos, + utf8_len, + NULL, + NULL); + assert(r == utf8_len); + *str = pos; + + return 0; +} + /// When "fname" is the name of a shortcut (*.lnk) resolve the file it points /// to and return that name in allocated memory. /// Otherwise NULL is returned. @@ -1002,9 +1037,9 @@ char_u * os_resolve_shortcut(char_u *fname) hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (void**)&pslw); if (hr == S_OK) { - WCHAR **p; + WCHAR *p; //TODO(jkeyes): if this returns non-zero, report the error - (void)utf8_to_utf16((char *)fname, p); + (void)utf8_to_utf16((char *)fname, &p); if (p != NULL) { // Get a pointer to the IPersistFile interface. @@ -1031,7 +1066,8 @@ char_u * os_resolve_shortcut(char_u *fname) ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR)); hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0); if (hr == S_OK && wsz[0] != NUL) { - rfname = utf16_to_enc(wsz, NULL); + //TODO(jkeyes): if this returns non-zero, report the error + (void)utf16_to_utf8(wsz, &rfname); } shortcut_errorw: -- cgit From f2d5ba65b54ff02cef438006d7dabd8de375fa33 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 30 Jul 2016 14:00:06 -0400 Subject: mbyte.c: Move utf8/utf16 functions to mbyte.c --- src/nvim/mbyte.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nvim/os/fs.c | 85 +++++--------------------------------------------------- 2 files changed, 87 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 0ba9f8b076..26d94aa6fa 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1885,6 +1885,86 @@ static int utf_strnicmp(char_u *s1, char_u *s2, size_t n1, size_t n2) return n1 == 0 ? -1 : 1; } +#ifdef WIN32 +#ifndef CP_UTF8 +# define CP_UTF8 65001 /* magic number from winnls.h */ +#endif + +int utf8_to_utf16(const char *str, WCHAR **strw) + 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); + + if (buf_sz == 0) { + *strw = NULL; + return 0; + } + + char *buf = xmalloc(buf_sz); + char *pos = buf; + + int r = MultiByteToWideChar(CP_UTF8, + 0, + str, + -1, + (WCHAR *)pos, + wchar_len); + assert(r == wchar_len); + *strw = (WCHAR *)pos; + + return 0; +} + +int utf16_to_utf8(const WCHAR *strw, char **str) + FUNC_ATTR_NONNULL_ALL +{ + // Compute the space required to store the string as UTF-8. + ssize_t utf8_len = WideCharToMultiByte(CP_UTF8, + 0, + strw, + -1, + NULL, + 0, + NULL, + NULL); + if (utf8_len == 0) { + return GetLastError(); + } + + ssize_t buf_sz = utf8_len * sizeof(char); + char *buf = xmalloc(buf_sz); + char *pos = buf; + + // Convert string to UTF-8. + int r = WideCharToMultiByte(CP_UTF8, + 0, + strw, + -1, + (LPSTR *)pos, + utf8_len, + NULL, + NULL); + assert(r == utf8_len); + *str = pos; + + return 0; +} + +#endif + /* * Version of strnicmp() that handles multi-byte characters. * Needed for Big5, Shift-JIS and UTF-8 encoding. Other DBCS encodings can diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index ce43eb9422..5a990cd042 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -25,6 +25,10 @@ #include "nvim/path.h" #include "nvim/strings.h" +#ifdef WIN32 +#include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 +#endif + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/fs.c.generated.h" #endif @@ -931,82 +935,6 @@ bool os_fileid_equal_fileinfo(const FileID *file_id, #ifdef WIN32 # include -#ifndef CP_UTF8 -# define CP_UTF8 65001 /* magic number from winnls.h */ -#endif - -static int utf8_to_utf16(const char *str, WCHAR **strw) - 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); - - if (buf_sz == 0) { - *strw = NULL; - return 0; - } - - char* buf = xmalloc(buf_sz); - char* pos = buf; - - int r = MultiByteToWideChar(CP_UTF8, - 0, - str, - -1, - (WCHAR*) pos, - wchar_len); - assert(r == wchar_len); - *strw = (WCHAR*) pos; - - return 0; -} - -static int utf16_to_utf8(const WCHAR *strw, char **str) - FUNC_ATTR_NONNULL_ALL -{ - // Compute the space required to store the string as UTF-8. - ssize_t utf8_len = WideCharToMultiByte(CP_UTF8, - 0, - strw, - -1, - NULL, - 0, - NULL, - NULL); - if (utf8_len == 0) { - return GetLastError(); - } - - ssize_t buf_sz = utf8_len * sizeof(char); - char* buf = xmalloc(buf_sz); - char* pos = buf; - - // Convert string to UTF-8. - int r = WideCharToMultiByte(CP_UTF8, - 0, - strw, - -1, - (LPSTR*) pos, - utf8_len, - NULL, - NULL); - assert(r == utf8_len); - *str = pos; - - return 0; -} /// When "fname" is the name of a shortcut (*.lnk) resolve the file it points /// to and return that name in allocated memory. @@ -1035,7 +963,7 @@ char_u * os_resolve_shortcut(char_u *fname) // create a link manager object and request its interface hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - &IID_IShellLinkW, (void**)&pslw); + &IID_IShellLinkW, (void **)&pslw); if (hr == S_OK) { WCHAR *p; //TODO(jkeyes): if this returns non-zero, report the error @@ -1044,7 +972,7 @@ char_u * os_resolve_shortcut(char_u *fname) if (p != NULL) { // Get a pointer to the IPersistFile interface. hr = pslw->lpVtbl->QueryInterface( - pslw, &IID_IPersistFile, (void**)&ppf); + pslw, &IID_IPersistFile, (void **)&ppf); if (hr != S_OK) { goto shortcut_errorw; } @@ -1088,4 +1016,5 @@ shortcut_end: CoUninitialize(); return rfname; } + #endif -- cgit From 02346f9bc7ab432931b059d075f16bfb09f93c1f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 30 Jul 2016 14:09:35 -0400 Subject: os_resolve_shortcut: Report conversion error. --- src/nvim/os/fs.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 5a990cd042..cd943c4843 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -946,6 +946,7 @@ char_u * os_resolve_shortcut(char_u *fname) OLECHAR wsz[MAX_PATH]; char_u *rfname = NULL; int len; + int conversion_result; IShellLinkW *pslw = NULL; WIN32_FIND_DATAW ffdw; @@ -966,8 +967,10 @@ char_u * os_resolve_shortcut(char_u *fname) &IID_IShellLinkW, (void **)&pslw); if (hr == S_OK) { WCHAR *p; - //TODO(jkeyes): if this returns non-zero, report the error - (void)utf8_to_utf16((char *)fname, &p); + int conversion_result = utf8_to_utf16((char *)fname, &p); + if (conversion_result != 0) { + EMSG2("utf8_to_utf16 failed: %s", uv_strerror(conversion_result)); + } if (p != NULL) { // Get a pointer to the IPersistFile interface. @@ -994,8 +997,10 @@ char_u * os_resolve_shortcut(char_u *fname) ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR)); hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0); if (hr == S_OK && wsz[0] != NUL) { - //TODO(jkeyes): if this returns non-zero, report the error - (void)utf16_to_utf8(wsz, &rfname); + int conversion_result = utf16_to_utf8(wsz, &rfname); + if (conversion_result != 0) { + EMSG2("utf16_to_utf8 failed: %s", uv_strerror(conversion_result)); + } } shortcut_errorw: -- cgit