summaryrefslogtreecommitdiff
path: root/data/vim/patches/8.1.1103
diff options
context:
space:
mode:
Diffstat (limited to 'data/vim/patches/8.1.1103')
-rw-r--r--data/vim/patches/8.1.11034150
1 files changed, 4150 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.1103 b/data/vim/patches/8.1.1103
new file mode 100644
index 000000000..7cdc909d0
--- /dev/null
+++ b/data/vim/patches/8.1.1103
@@ -0,0 +1,4150 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 8.1.1103
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 8.1.1103
+Problem: MS-Windows: old API calls are no longer needed.
+Solution: Always use the wide functions. (Ken Takata, closes #4199)
+Files: src/glbl_ime.cpp, src/globals.h, src/gui_w32.c, src/misc1.c,
+ src/os_mswin.c, src/os_win32.c, src/vim.h
+
+
+*** ../vim-8.1.1102/src/glbl_ime.cpp 2019-02-17 17:44:36.207875527 +0100
+--- src/glbl_ime.cpp 2019-04-02 22:04:17.785655516 +0200
+***************
+*** 133,146 ****
+
+ if (pIApp == NULL || pIApp->OnDefWindowProc(hWnd, Msg,
+ wParam, lParam, &lResult) != S_OK)
+! {
+! #if defined(MSWIN)
+! if (wide_WindowProc)
+! lResult = DefWindowProcW(hWnd, Msg, wParam, lParam);
+! else
+! #endif
+! lResult = DefWindowProc(hWnd, Msg, wParam, lParam);
+! }
+ return lResult;
+ }
+
+--- 133,139 ----
+
+ if (pIApp == NULL || pIApp->OnDefWindowProc(hWnd, Msg,
+ wParam, lParam, &lResult) != S_OK)
+! lResult = DefWindowProcW(hWnd, Msg, wParam, lParam);
+ return lResult;
+ }
+
+*** ../vim-8.1.1102/src/globals.h 2019-03-30 13:53:26.170425120 +0100
+--- src/globals.h 2019-04-02 22:04:17.785655516 +0200
+***************
+*** 822,831 ****
+ #endif
+ EXTERN int has_mbyte INIT(= 0); /* any multi-byte encoding */
+
+- #if defined(MSWIN)
+- EXTERN int wide_WindowProc INIT(= FALSE); /* use wide WindowProc() */
+- #endif
+-
+ /*
+ * To speed up BYTELEN() we fill a table with the byte lengths whenever
+ * enc_utf8 or enc_dbcs changes.
+--- 822,827 ----
+*** ../vim-8.1.1102/src/gui_w32.c 2019-03-30 18:46:57.352077376 +0100
+--- src/gui_w32.c 2019-04-02 22:10:34.450870828 +0200
+***************
+*** 313,324 ****
+ static int destroying = FALSE; /* call DestroyWindow() ourselves */
+
+ #ifdef MSWIN_FIND_REPLACE
+! static UINT s_findrep_msg = 0; /* set in gui_w[16/32].c */
+! static FINDREPLACE s_findrep_struct;
+! static FINDREPLACEW s_findrep_struct_w;
+ static HWND s_findrep_hwnd = NULL;
+! static int s_findrep_is_find; /* TRUE for find dialog, FALSE
+! for find/replace dialog */
+ #endif
+
+ static HINSTANCE s_hinst = NULL;
+--- 313,323 ----
+ static int destroying = FALSE; /* call DestroyWindow() ourselves */
+
+ #ifdef MSWIN_FIND_REPLACE
+! static UINT s_findrep_msg = 0; // set in gui_w[16/32].c
+! static FINDREPLACEW s_findrep_struct;
+ static HWND s_findrep_hwnd = NULL;
+! static int s_findrep_is_find; // TRUE for find dialog, FALSE
+! // for find/replace dialog
+ #endif
+
+ static HINSTANCE s_hinst = NULL;
+***************
+*** 391,397 ****
+ }
+ #endif
+
+! /* use of WindowProc depends on wide_WindowProc */
+ #define MyWindowProc vim_WindowProc
+
+ extern int current_font_height; /* this is in os_mswin.c */
+--- 390,396 ----
+ }
+ #endif
+
+! /* use of WindowProc depends on Global IME */
+ #define MyWindowProc vim_WindowProc
+
+ extern int current_font_height; /* this is in os_mswin.c */
+***************
+*** 1107,1149 ****
+
+ #ifdef MSWIN_FIND_REPLACE
+ /*
+- * copy useful data from structure LPFINDREPLACE to structure LPFINDREPLACEW
+- */
+- static void
+- findrep_atow(LPFINDREPLACEW lpfrw, LPFINDREPLACE lpfr)
+- {
+- WCHAR *wp;
+-
+- lpfrw->hwndOwner = lpfr->hwndOwner;
+- lpfrw->Flags = lpfr->Flags;
+-
+- wp = enc_to_utf16((char_u *)lpfr->lpstrFindWhat, NULL);
+- wcsncpy(lpfrw->lpstrFindWhat, wp, lpfrw->wFindWhatLen - 1);
+- vim_free(wp);
+-
+- /* the field "lpstrReplaceWith" doesn't need to be copied */
+- }
+-
+- /*
+- * copy useful data from structure LPFINDREPLACEW to structure LPFINDREPLACE
+- */
+- static void
+- findrep_wtoa(LPFINDREPLACE lpfr, LPFINDREPLACEW lpfrw)
+- {
+- char_u *p;
+-
+- lpfr->Flags = lpfrw->Flags;
+-
+- p = utf16_to_enc((short_u*)lpfrw->lpstrFindWhat, NULL);
+- vim_strncpy((char_u *)lpfr->lpstrFindWhat, p, lpfr->wFindWhatLen - 1);
+- vim_free(p);
+-
+- p = utf16_to_enc((short_u*)lpfrw->lpstrReplaceWith, NULL);
+- vim_strncpy((char_u *)lpfr->lpstrReplaceWith, p, lpfr->wReplaceWithLen - 1);
+- vim_free(p);
+- }
+-
+- /*
+ * Handle a Find/Replace window message.
+ */
+ static void
+--- 1106,1111 ----
+***************
+*** 1152,1162 ****
+ int flags = 0;
+ int down;
+
+- /* If the OS is Windows NT, and 'encoding' differs from active codepage:
+- * convert text from wide string. */
+- if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+- findrep_wtoa(&s_findrep_struct, &s_findrep_struct_w);
+-
+ if (s_findrep_struct.Flags & FR_DIALOGTERM)
+ /* Give main window the focus back. */
+ (void)SetFocus(s_hwnd);
+--- 1114,1119 ----
+***************
+*** 1184,1197 ****
+
+ if (flags != 0)
+ {
+ /* Call the generic GUI function to do the actual work. */
+ if (s_findrep_struct.Flags & FR_WHOLEWORD)
+ flags |= FRD_WHOLE_WORD;
+ if (s_findrep_struct.Flags & FR_MATCHCASE)
+ flags |= FRD_MATCH_CASE;
+ down = (s_findrep_struct.Flags & FR_DOWN) != 0;
+! gui_do_findrepl(flags, (char_u *)s_findrep_struct.lpstrFindWhat,
+! (char_u *)s_findrep_struct.lpstrReplaceWith, down);
+ }
+ }
+ #endif
+--- 1141,1160 ----
+
+ if (flags != 0)
+ {
++ char_u *p, *q;
++
+ /* Call the generic GUI function to do the actual work. */
+ if (s_findrep_struct.Flags & FR_WHOLEWORD)
+ flags |= FRD_WHOLE_WORD;
+ if (s_findrep_struct.Flags & FR_MATCHCASE)
+ flags |= FRD_MATCH_CASE;
+ down = (s_findrep_struct.Flags & FR_DOWN) != 0;
+! p = utf16_to_enc(s_findrep_struct.lpstrFindWhat, NULL);
+! q = utf16_to_enc(s_findrep_struct.lpstrReplaceWith, NULL);
+! if (p != NULL && q != NULL)
+! gui_do_findrepl(flags, p, q, down);
+! vim_free(p);
+! vim_free(q);
+ }
+ }
+ #endif
+***************
+*** 1310,1318 ****
+ #ifdef GLOBAL_IME
+ return global_ime_DefWindowProc(hwnd, message, wParam, lParam);
+ #else
+! if (wide_WindowProc)
+! return DefWindowProcW(hwnd, message, wParam, lParam);
+! return DefWindowProc(hwnd, message, wParam, lParam);
+ #endif
+ }
+
+--- 1273,1279 ----
+ #ifdef GLOBAL_IME
+ return global_ime_DefWindowProc(hwnd, message, wParam, lParam);
+ #else
+! return DefWindowProcW(hwnd, message, wParam, lParam);
+ #endif
+ }
+
+***************
+*** 2332,2352 ****
+ int n;
+ int wlen = len;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! /* 'encoding' differs from active codepage: convert text and use wide
+! * function */
+! wstr = enc_to_utf16(str, &wlen);
+! if (wstr != NULL)
+! {
+! n = GetTextExtentPointW(hdc, wstr, wlen, &size);
+! vim_free(wstr);
+! if (n)
+! return size.cx;
+! }
+! }
+
+! return GetTextWidth(hdc, str, len);
+ }
+
+ static void get_work_area(RECT *spi_rect);
+--- 2293,2307 ----
+ int n;
+ int wlen = len;
+
+! wstr = enc_to_utf16(str, &wlen);
+! if (wstr == NULL)
+! return 0;
+
+! n = GetTextExtentPointW(hdc, wstr, wlen, &size);
+! vim_free(wstr);
+! if (n)
+! return size.cx;
+! return 0;
+ }
+
+ static void get_work_area(RECT *spi_rect);
+***************
+*** 2423,2441 ****
+ if (showit)
+ {
+ # ifndef TB_SETUNICODEFORMAT
+! /* For older compilers. We assume this never changes. */
+ # define TB_SETUNICODEFORMAT 0x2005
+ # endif
+! /* Enable/disable unicode support */
+! int uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage);
+! SendMessage(s_toolbarhwnd, TB_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0);
+ ShowWindow(s_toolbarhwnd, SW_SHOW);
+ }
+ else
+ ShowWindow(s_toolbarhwnd, SW_HIDE);
+ }
+
+! /* Then number of bitmaps is fixed. Exit is missing! */
+ #define TOOLBAR_BITMAP_COUNT 31
+
+ #endif
+--- 2378,2396 ----
+ if (showit)
+ {
+ # ifndef TB_SETUNICODEFORMAT
+! // For older compilers. We assume this never changes.
+ # define TB_SETUNICODEFORMAT 0x2005
+ # endif
+! // Enable unicode support
+! SendMessage(s_toolbarhwnd, TB_SETUNICODEFORMAT, (WPARAM)TRUE,
+! (LPARAM)0);
+ ShowWindow(s_toolbarhwnd, SW_SHOW);
+ }
+ else
+ ShowWindow(s_toolbarhwnd, SW_HIDE);
+ }
+
+! /* The number of bitmaps is fixed. Exit is missing! */
+ #define TOOLBAR_BITMAP_COUNT 31
+
+ #endif
+***************
+*** 2444,2483 ****
+ static void
+ add_tabline_popup_menu_entry(HMENU pmenu, UINT item_id, char_u *item_text)
+ {
+! WCHAR *wn = NULL;
+!
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! /* 'encoding' differs from active codepage: convert menu name
+! * and use wide function */
+! wn = enc_to_utf16(item_text, NULL);
+! if (wn != NULL)
+! {
+! MENUITEMINFOW infow;
+!
+! infow.cbSize = sizeof(infow);
+! infow.fMask = MIIM_TYPE | MIIM_ID;
+! infow.wID = item_id;
+! infow.fType = MFT_STRING;
+! infow.dwTypeData = wn;
+! infow.cch = (UINT)wcslen(wn);
+! InsertMenuItemW(pmenu, item_id, FALSE, &infow);
+! vim_free(wn);
+! }
+! }
+
+ if (wn == NULL)
+! {
+! MENUITEMINFO info;
+
+! info.cbSize = sizeof(info);
+! info.fMask = MIIM_TYPE | MIIM_ID;
+! info.wID = item_id;
+! info.fType = MFT_STRING;
+! info.dwTypeData = (LPTSTR)item_text;
+! info.cch = (UINT)STRLEN(item_text);
+! InsertMenuItem(pmenu, item_id, FALSE, &info);
+! }
+ }
+
+ static void
+--- 2399,2419 ----
+ static void
+ add_tabline_popup_menu_entry(HMENU pmenu, UINT item_id, char_u *item_text)
+ {
+! WCHAR *wn;
+! MENUITEMINFOW infow;
+
++ wn = enc_to_utf16(item_text, NULL);
+ if (wn == NULL)
+! return;
+
+! infow.cbSize = sizeof(infow);
+! infow.fMask = MIIM_TYPE | MIIM_ID;
+! infow.wID = item_id;
+! infow.fType = MFT_STRING;
+! infow.dwTypeData = wn;
+! infow.cch = (UINT)wcslen(wn);
+! InsertMenuItemW(pmenu, item_id, FALSE, &infow);
+! vim_free(wn);
+ }
+
+ static void
+***************
+*** 2573,2580 ****
+ int nr = 0;
+ int curtabidx = 0;
+ int tabadded = 0;
+- static int use_unicode = FALSE;
+- int uu;
+ WCHAR *wstr = NULL;
+
+ if (s_tabhwnd == NULL)
+--- 2509,2514 ----
+***************
+*** 2584,2596 ****
+ /* For older compilers. We assume this never changes. */
+ # define CCM_SETUNICODEFORMAT 0x2005
+ #endif
+! uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage);
+! if (uu != use_unicode)
+! {
+! /* Enable/disable unicode support */
+! SendMessage(s_tabhwnd, CCM_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0);
+! use_unicode = uu;
+! }
+
+ tie.mask = TCIF_TEXT;
+ tie.iImage = -1;
+--- 2518,2525 ----
+ /* For older compilers. We assume this never changes. */
+ # define CCM_SETUNICODEFORMAT 0x2005
+ #endif
+! // Enable unicode support
+! SendMessage(s_tabhwnd, CCM_SETUNICODEFORMAT, (WPARAM)TRUE, (LPARAM)0);
+
+ tie.mask = TCIF_TEXT;
+ tie.iImage = -1;
+***************
+*** 2614,2637 ****
+
+ get_tabline_label(tp, FALSE);
+ tie.pszText = (LPSTR)NameBuff;
+! wstr = NULL;
+! if (use_unicode)
+ {
+! /* Need to go through Unicode. */
+! wstr = enc_to_utf16(NameBuff, NULL);
+! if (wstr != NULL)
+! {
+! TCITEMW tiw;
+
+! tiw.mask = TCIF_TEXT;
+! tiw.iImage = -1;
+! tiw.pszText = wstr;
+! SendMessage(s_tabhwnd, TCM_SETITEMW, (WPARAM)nr, (LPARAM)&tiw);
+! vim_free(wstr);
+! }
+ }
+- if (wstr == NULL)
+- TabCtrl_SetItem(s_tabhwnd, nr, &tie);
+ }
+
+ /* Remove any old labels. */
+--- 2543,2560 ----
+
+ get_tabline_label(tp, FALSE);
+ tie.pszText = (LPSTR)NameBuff;
+!
+! wstr = enc_to_utf16(NameBuff, NULL);
+! if (wstr != NULL)
+ {
+! TCITEMW tiw;
+
+! tiw.mask = TCIF_TEXT;
+! tiw.iImage = -1;
+! tiw.pszText = wstr;
+! SendMessage(s_tabhwnd, TCM_SETITEMW, (WPARAM)nr, (LPARAM)&tiw);
+! vim_free(wstr);
+ }
+ }
+
+ /* Remove any old labels. */
+***************
+*** 2720,2727 ****
+ if (wword)
+ s_findrep_struct.Flags |= FR_WHOLEWORD;
+ if (entry_text != NULL && *entry_text != NUL)
+! vim_strncpy((char_u *)s_findrep_struct.lpstrFindWhat, entry_text,
+! s_findrep_struct.wFindWhatLen - 1);
+ vim_free(entry_text);
+ }
+ #endif
+--- 2643,2659 ----
+ if (wword)
+ s_findrep_struct.Flags |= FR_WHOLEWORD;
+ if (entry_text != NULL && *entry_text != NUL)
+! {
+! WCHAR *p = enc_to_utf16(entry_text, NULL);
+! if (p != NULL)
+! {
+! int len = s_findrep_struct.wFindWhatLen - 1;
+!
+! wcsncpy(s_findrep_struct.lpstrFindWhat, p, len);
+! s_findrep_struct.lpstrFindWhat[len] = NUL;
+! vim_free(p);
+! }
+! }
+ vim_free(entry_text);
+ }
+ #endif
+***************
+*** 2729,2735 ****
+ static void
+ set_window_title(HWND hwnd, char *title)
+ {
+! if (title != NULL && enc_codepage >= 0 && enc_codepage != (int)GetACP())
+ {
+ WCHAR *wbuf;
+
+--- 2661,2667 ----
+ static void
+ set_window_title(HWND hwnd, char *title)
+ {
+! if (title != NULL)
+ {
+ WCHAR *wbuf;
+
+***************
+*** 2740,2748 ****
+ SetWindowTextW(hwnd, wbuf);
+ vim_free(wbuf);
+ }
+- return;
+ }
+! (void)SetWindowText(hwnd, (LPCSTR)title);
+ }
+
+ void
+--- 2672,2680 ----
+ SetWindowTextW(hwnd, wbuf);
+ vim_free(wbuf);
+ }
+ }
+! else
+! (void)SetWindowTextW(hwnd, NULL);
+ }
+
+ void
+***************
+*** 2757,2772 ****
+ if (!IsWindow(s_findrep_hwnd))
+ {
+ initialise_findrep(eap->arg);
+! /* If the OS is Windows NT, and 'encoding' differs from active
+! * codepage: convert text and use wide function. */
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! findrep_atow(&s_findrep_struct_w, &s_findrep_struct);
+! s_findrep_hwnd = FindTextW(
+! (LPFINDREPLACEW) &s_findrep_struct_w);
+! }
+! else
+! s_findrep_hwnd = FindText((LPFINDREPLACE) &s_findrep_struct);
+ }
+
+ set_window_title(s_findrep_hwnd, _("Find string"));
+--- 2689,2695 ----
+ if (!IsWindow(s_findrep_hwnd))
+ {
+ initialise_findrep(eap->arg);
+! s_findrep_hwnd = FindTextW((LPFINDREPLACEW) &s_findrep_struct);
+ }
+
+ set_window_title(s_findrep_hwnd, _("Find string"));
+***************
+*** 2790,2804 ****
+ if (!IsWindow(s_findrep_hwnd))
+ {
+ initialise_findrep(eap->arg);
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! findrep_atow(&s_findrep_struct_w, &s_findrep_struct);
+! s_findrep_hwnd = ReplaceTextW(
+! (LPFINDREPLACEW) &s_findrep_struct_w);
+! }
+! else
+! s_findrep_hwnd = ReplaceText(
+! (LPFINDREPLACE) &s_findrep_struct);
+ }
+
+ set_window_title(s_findrep_hwnd, _("Find & Replace"));
+--- 2713,2719 ----
+ if (!IsWindow(s_findrep_hwnd))
+ {
+ initialise_findrep(eap->arg);
+! s_findrep_hwnd = ReplaceTextW((LPFINDREPLACEW) &s_findrep_struct);
+ }
+
+ set_window_title(s_findrep_hwnd, _("Find & Replace"));
+***************
+*** 4147,4153 ****
+ #define USE_SYSMENU_FONT
+
+ #define VIM_NAME "vim"
+- #define VIM_CLASS "Vim"
+ #define VIM_CLASSW L"Vim"
+
+ /* Initial size for the dialog template. For gui_mch_dialog() it's fixed,
+--- 4062,4067 ----
+***************
+*** 5021,5029 ****
+ int
+ gui_mch_init(void)
+ {
+- const char szVimWndClass[] = VIM_CLASS;
+- const char szTextAreaClass[] = "VimTextArea";
+- WNDCLASS wndclass;
+ const WCHAR szVimWndClassW[] = VIM_CLASSW;
+ const WCHAR szTextAreaClassW[] = L"VimTextArea";
+ WNDCLASSW wndclassw;
+--- 4935,4940 ----
+***************
+*** 5073,5122 ****
+ #endif
+ RegisterClassW(&wndclassw)) == 0)
+ return FAIL;
+- else
+- wide_WindowProc = TRUE;
+ }
+
+- if (!wide_WindowProc)
+- if (GetClassInfo(s_hinst, szVimWndClass, &wndclass) == 0)
+- {
+- wndclass.style = CS_DBLCLKS;
+- wndclass.lpfnWndProc = _WndProc;
+- wndclass.cbClsExtra = 0;
+- wndclass.cbWndExtra = 0;
+- wndclass.hInstance = s_hinst;
+- wndclass.hIcon = LoadIcon(wndclass.hInstance, "IDR_VIM");
+- wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+- wndclass.hbrBackground = s_brush;
+- wndclass.lpszMenuName = NULL;
+- wndclass.lpszClassName = szVimWndClass;
+-
+- if ((
+- #ifdef GLOBAL_IME
+- atom =
+- #endif
+- RegisterClass(&wndclass)) == 0)
+- return FAIL;
+- }
+-
+ if (vim_parent_hwnd != NULL)
+ {
+ #ifdef HAVE_TRY_EXCEPT
+ __try
+ {
+ #endif
+! /* Open inside the specified parent window.
+! * TODO: last argument should point to a CLIENTCREATESTRUCT
+! * structure. */
+! s_hwnd = CreateWindowEx(
+ WS_EX_MDICHILD,
+! szVimWndClass, "Vim MSWindows GUI",
+ WS_OVERLAPPEDWINDOW | WS_CHILD
+ | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 0xC000,
+ gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
+ gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y,
+! 100, /* Any value will do */
+! 100, /* Any value will do */
+ vim_parent_hwnd, NULL,
+ s_hinst, NULL);
+ #ifdef HAVE_TRY_EXCEPT
+--- 4984,5009 ----
+ #endif
+ RegisterClassW(&wndclassw)) == 0)
+ return FAIL;
+ }
+
+ if (vim_parent_hwnd != NULL)
+ {
+ #ifdef HAVE_TRY_EXCEPT
+ __try
+ {
+ #endif
+! // Open inside the specified parent window.
+! // TODO: last argument should point to a CLIENTCREATESTRUCT
+! // structure.
+! s_hwnd = CreateWindowExW(
+ WS_EX_MDICHILD,
+! szVimWndClassW, L"Vim MSWindows GUI",
+ WS_OVERLAPPEDWINDOW | WS_CHILD
+ | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 0xC000,
+ gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
+ gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y,
+! 100, // Any value will do
+! 100, // Any value will do
+ vim_parent_hwnd, NULL,
+ s_hinst, NULL);
+ #ifdef HAVE_TRY_EXCEPT
+***************
+*** 5141,5148 ****
+
+ /* Create a window. If win_socket_id is not zero without border and
+ * titlebar, it will be reparented below. */
+! s_hwnd = CreateWindow(
+! szVimWndClass, "Vim MSWindows GUI",
+ (win_socket_id == 0 ? WS_OVERLAPPEDWINDOW : WS_POPUP)
+ | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
+--- 5028,5035 ----
+
+ /* Create a window. If win_socket_id is not zero without border and
+ * titlebar, it will be reparented below. */
+! s_hwnd = CreateWindowW(
+! szVimWndClassW, L"Vim MSWindows GUI",
+ (win_socket_id == 0 ? WS_OVERLAPPEDWINDOW : WS_POPUP)
+ | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
+***************
+*** 5169,5228 ****
+ #endif
+
+ /* Create the text area window */
+! if (wide_WindowProc)
+ {
+! if (GetClassInfoW(s_hinst, szTextAreaClassW, &wndclassw) == 0)
+! {
+! wndclassw.style = CS_OWNDC;
+! wndclassw.lpfnWndProc = _TextAreaWndProc;
+! wndclassw.cbClsExtra = 0;
+! wndclassw.cbWndExtra = 0;
+! wndclassw.hInstance = s_hinst;
+! wndclassw.hIcon = NULL;
+! wndclassw.hCursor = LoadCursor(NULL, IDC_ARROW);
+! wndclassw.hbrBackground = NULL;
+! wndclassw.lpszMenuName = NULL;
+! wndclassw.lpszClassName = szTextAreaClassW;
+!
+! if (RegisterClassW(&wndclassw) == 0)
+! return FAIL;
+! }
+!
+! s_textArea = CreateWindowExW(
+! 0,
+! szTextAreaClassW, L"Vim text area",
+! WS_CHILD | WS_VISIBLE, 0, 0,
+! 100, // Any value will do for now
+! 100, // Any value will do for now
+! s_hwnd, NULL,
+! s_hinst, NULL);
+! }
+! else if (GetClassInfo(s_hinst, szTextAreaClass, &wndclass) == 0)
+! {
+! wndclass.style = CS_OWNDC;
+! wndclass.lpfnWndProc = _TextAreaWndProc;
+! wndclass.cbClsExtra = 0;
+! wndclass.cbWndExtra = 0;
+! wndclass.hInstance = s_hinst;
+! wndclass.hIcon = NULL;
+! wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+! wndclass.hbrBackground = NULL;
+! wndclass.lpszMenuName = NULL;
+! wndclass.lpszClassName = szTextAreaClass;
+
+! if (RegisterClass(&wndclass) == 0)
+ return FAIL;
+-
+- s_textArea = CreateWindowEx(
+- 0,
+- szTextAreaClass, "Vim text area",
+- WS_CHILD | WS_VISIBLE, 0, 0,
+- 100, // Any value will do for now
+- 100, // Any value will do for now
+- s_hwnd, NULL,
+- s_hinst, NULL);
+ }
+
+ if (s_textArea == NULL)
+ return FAIL;
+
+--- 5056,5087 ----
+ #endif
+
+ /* Create the text area window */
+! if (GetClassInfoW(s_hinst, szTextAreaClassW, &wndclassw) == 0)
+ {
+! wndclassw.style = CS_OWNDC;
+! wndclassw.lpfnWndProc = _TextAreaWndProc;
+! wndclassw.cbClsExtra = 0;
+! wndclassw.cbWndExtra = 0;
+! wndclassw.hInstance = s_hinst;
+! wndclassw.hIcon = NULL;
+! wndclassw.hCursor = LoadCursor(NULL, IDC_ARROW);
+! wndclassw.hbrBackground = NULL;
+! wndclassw.lpszMenuName = NULL;
+! wndclassw.lpszClassName = szTextAreaClassW;
+
+! if (RegisterClassW(&wndclassw) == 0)
+ return FAIL;
+ }
+
++ s_textArea = CreateWindowExW(
++ 0,
++ szTextAreaClassW, L"Vim text area",
++ WS_CHILD | WS_VISIBLE, 0, 0,
++ 100, // Any value will do for now
++ 100, // Any value will do for now
++ s_hwnd, NULL,
++ s_hinst, NULL);
++
+ if (s_textArea == NULL)
+ return FAIL;
+
+***************
+*** 5299,5319 ****
+
+ /* Initialise the struct */
+ s_findrep_struct.lStructSize = sizeof(s_findrep_struct);
+! s_findrep_struct.lpstrFindWhat = (LPSTR)alloc(MSWIN_FR_BUFSIZE);
+ s_findrep_struct.lpstrFindWhat[0] = NUL;
+! s_findrep_struct.lpstrReplaceWith = (LPSTR)alloc(MSWIN_FR_BUFSIZE);
+ s_findrep_struct.lpstrReplaceWith[0] = NUL;
+ s_findrep_struct.wFindWhatLen = MSWIN_FR_BUFSIZE;
+ s_findrep_struct.wReplaceWithLen = MSWIN_FR_BUFSIZE;
+- s_findrep_struct_w.lStructSize = sizeof(s_findrep_struct_w);
+- s_findrep_struct_w.lpstrFindWhat =
+- (LPWSTR)alloc(MSWIN_FR_BUFSIZE * sizeof(WCHAR));
+- s_findrep_struct_w.lpstrFindWhat[0] = NUL;
+- s_findrep_struct_w.lpstrReplaceWith =
+- (LPWSTR)alloc(MSWIN_FR_BUFSIZE * sizeof(WCHAR));
+- s_findrep_struct_w.lpstrReplaceWith[0] = NUL;
+- s_findrep_struct_w.wFindWhatLen = MSWIN_FR_BUFSIZE;
+- s_findrep_struct_w.wReplaceWithLen = MSWIN_FR_BUFSIZE;
+ #endif
+
+ #ifdef FEAT_EVAL
+--- 5158,5171 ----
+
+ /* Initialise the struct */
+ s_findrep_struct.lStructSize = sizeof(s_findrep_struct);
+! s_findrep_struct.lpstrFindWhat =
+! (LPWSTR)alloc(MSWIN_FR_BUFSIZE * sizeof(WCHAR));
+ s_findrep_struct.lpstrFindWhat[0] = NUL;
+! s_findrep_struct.lpstrReplaceWith =
+! (LPWSTR)alloc(MSWIN_FR_BUFSIZE * sizeof(WCHAR));
+ s_findrep_struct.lpstrReplaceWith[0] = NUL;
+ s_findrep_struct.wFindWhatLen = MSWIN_FR_BUFSIZE;
+ s_findrep_struct.wReplaceWithLen = MSWIN_FR_BUFSIZE;
+ #endif
+
+ #ifdef FEAT_EVAL
+***************
+*** 6344,6392 ****
+
+ if (menu_is_menubar(menu->name))
+ {
+! WCHAR *wn = NULL;
+!
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! /* 'encoding' differs from active codepage: convert menu name
+! * and use wide function */
+! wn = enc_to_utf16(menu->name, NULL);
+! if (wn != NULL)
+! {
+! MENUITEMINFOW infow;
+!
+! infow.cbSize = sizeof(infow);
+! infow.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID
+! | MIIM_SUBMENU;
+! infow.dwItemData = (long_u)menu;
+! infow.wID = menu->id;
+! infow.fType = MFT_STRING;
+! infow.dwTypeData = wn;
+! infow.cch = (UINT)wcslen(wn);
+! infow.hSubMenu = menu->submenu_id;
+! InsertMenuItemW((parent == NULL)
+! ? s_menuBar : parent->submenu_id,
+! (UINT)pos, TRUE, &infow);
+! vim_free(wn);
+! }
+! }
+
+ if (wn == NULL)
+! {
+! MENUITEMINFO info;
+
+! info.cbSize = sizeof(info);
+! info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID | MIIM_SUBMENU;
+! info.dwItemData = (long_u)menu;
+! info.wID = menu->id;
+! info.fType = MFT_STRING;
+! info.dwTypeData = (LPTSTR)menu->name;
+! info.cch = (UINT)STRLEN(menu->name);
+! info.hSubMenu = menu->submenu_id;
+! InsertMenuItem((parent == NULL)
+! ? s_menuBar : parent->submenu_id,
+! (UINT)pos, TRUE, &info);
+! }
+ }
+
+ /* Fix window size if menu may have wrapped */
+--- 6196,6221 ----
+
+ if (menu_is_menubar(menu->name))
+ {
+! WCHAR *wn;
+! MENUITEMINFOW infow;
+
++ wn = enc_to_utf16(menu->name, NULL);
+ if (wn == NULL)
+! return;
+
+! infow.cbSize = sizeof(infow);
+! infow.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID
+! | MIIM_SUBMENU;
+! infow.dwItemData = (long_u)menu;
+! infow.wID = menu->id;
+! infow.fType = MFT_STRING;
+! infow.dwTypeData = wn;
+! infow.cch = (UINT)wcslen(wn);
+! infow.hSubMenu = menu->submenu_id;
+! InsertMenuItemW((parent == NULL)
+! ? s_menuBar : parent->submenu_id,
+! (UINT)pos, TRUE, &infow);
+! vim_free(wn);
+ }
+
+ /* Fix window size if menu may have wrapped */
+***************
+*** 6499,6525 ****
+ else
+ #endif
+ {
+! WCHAR *wn = NULL;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+! /* 'encoding' differs from active codepage: convert menu item name
+! * and use wide function */
+! wn = enc_to_utf16(menu->name, NULL);
+! if (wn != NULL)
+! {
+! InsertMenuW(parent->submenu_id, (UINT)idx,
+! (menu_is_separator(menu->name)
+! ? MF_SEPARATOR : MF_STRING) | MF_BYPOSITION,
+! (UINT)menu->id, wn);
+! vim_free(wn);
+! }
+ }
+- if (wn == NULL)
+- InsertMenu(parent->submenu_id, (UINT)idx,
+- (menu_is_separator(menu->name) ? MF_SEPARATOR : MF_STRING)
+- | MF_BYPOSITION,
+- (UINT)menu->id, (LPCTSTR)menu->name);
+ #ifdef FEAT_TEAROFF
+ if (IsWindow(parent->tearoff_handle))
+ rebuild_tearoff(parent);
+--- 6328,6344 ----
+ else
+ #endif
+ {
+! WCHAR *wn;
+
+! wn = enc_to_utf16(menu->name, NULL);
+! if (wn != NULL)
+ {
+! InsertMenuW(parent->submenu_id, (UINT)idx,
+! (menu_is_separator(menu->name)
+! ? MF_SEPARATOR : MF_STRING) | MF_BYPOSITION,
+! (UINT)menu->id, wn);
+! vim_free(wn);
+ }
+ #ifdef FEAT_TEAROFF
+ if (IsWindow(parent->tearoff_handle))
+ rebuild_tearoff(parent);
+***************
+*** 6709,6730 ****
+ /* If the edit box exists, copy the string. */
+ if (s_textfield != NULL)
+ {
+! /* If the OS is Windows NT, and 'encoding' differs from active
+! * codepage: use wide function and convert text. */
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *wp = (WCHAR *)alloc(IOSIZE * sizeof(WCHAR));
+! char_u *p;
+
+! GetDlgItemTextW(hwnd, DLG_NONBUTTON_CONTROL + 2, wp, IOSIZE);
+! p = utf16_to_enc(wp, NULL);
+! vim_strncpy(s_textfield, p, IOSIZE);
+! vim_free(p);
+! vim_free(wp);
+! }
+! else
+! GetDlgItemText(hwnd, DLG_NONBUTTON_CONTROL + 2,
+! (LPSTR)s_textfield, IOSIZE);
+ }
+
+ /*
+--- 6528,6541 ----
+ /* If the edit box exists, copy the string. */
+ if (s_textfield != NULL)
+ {
+! WCHAR *wp = (WCHAR *)alloc(IOSIZE * sizeof(WCHAR));
+! char_u *p;
+
+! GetDlgItemTextW(hwnd, DLG_NONBUTTON_CONTROL + 2, wp, IOSIZE);
+! p = utf16_to_enc(wp, NULL);
+! vim_strncpy(s_textfield, p, IOSIZE);
+! vim_free(p);
+! vim_free(wp);
+ }
+
+ /*
+***************
+*** 8411,8417 ****
+ }
+
+ static void
+! make_tooltipw(BalloonEval *beval, char *text, POINT pt)
+ {
+ TOOLINFOW *pti;
+ int ToolInfoSize;
+--- 8222,8228 ----
+ }
+
+ static void
+! make_tooltip(BalloonEval *beval, char *text, POINT pt)
+ {
+ TOOLINFOW *pti;
+ int ToolInfoSize;
+***************
+*** 8473,8549 ****
+ /*
+ * HACK: force tooltip to appear, because it'll not appear until
+ * first mouse move. D*mn M$
+- * Amazingly moving (2, 2) and then (-1, -1) the mouse doesn't move.
+- */
+- mouse_event(MOUSEEVENTF_MOVE, 2, 2, 0, 0);
+- mouse_event(MOUSEEVENTF_MOVE, (DWORD)-1, (DWORD)-1, 0, 0);
+- vim_free(pti);
+- }
+-
+- static void
+- make_tooltip(BalloonEval *beval, char *text, POINT pt)
+- {
+- TOOLINFO *pti;
+- int ToolInfoSize;
+-
+- if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+- {
+- make_tooltipw(beval, text, pt);
+- return;
+- }
+-
+- if (multiline_balloon_available() == TRUE)
+- ToolInfoSize = sizeof(TOOLINFO_NEW);
+- else
+- ToolInfoSize = sizeof(TOOLINFO);
+-
+- pti = (TOOLINFO *)alloc(ToolInfoSize);
+- if (pti == NULL)
+- return;
+-
+- beval->balloon = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS,
+- NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+- beval->target, NULL, s_hinst, NULL);
+-
+- SetWindowPos(beval->balloon, HWND_TOPMOST, 0, 0, 0, 0,
+- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+-
+- pti->cbSize = ToolInfoSize;
+- pti->uFlags = TTF_SUBCLASS;
+- pti->hwnd = beval->target;
+- pti->hinst = 0; /* Don't use string resources */
+- pti->uId = ID_BEVAL_TOOLTIP;
+-
+- if (multiline_balloon_available() == TRUE)
+- {
+- RECT rect;
+- TOOLINFO_NEW *ptin = (TOOLINFO_NEW *)pti;
+- pti->lpszText = LPSTR_TEXTCALLBACK;
+- beval->tofree = vim_strsave((char_u*)text);
+- ptin->lParam = (LPARAM)beval->tofree;
+- if (GetClientRect(s_textArea, &rect)) /* switch multiline tooltips on */
+- SendMessage(beval->balloon, TTM_SETMAXTIPWIDTH, 0,
+- (LPARAM)rect.right);
+- }
+- else
+- pti->lpszText = text; /* do this old way */
+-
+- /* Limit ballooneval bounding rect to CursorPos neighbourhood */
+- pti->rect.left = pt.x - 3;
+- pti->rect.top = pt.y - 3;
+- pti->rect.right = pt.x + 3;
+- pti->rect.bottom = pt.y + 3;
+-
+- SendMessage(beval->balloon, TTM_ADDTOOL, 0, (LPARAM)pti);
+- /* Make tooltip appear sooner */
+- SendMessage(beval->balloon, TTM_SETDELAYTIME, TTDT_INITIAL, 10);
+- /* I've performed some tests and it seems the longest possible life time
+- * of tooltip is 30 seconds */
+- SendMessage(beval->balloon, TTM_SETDELAYTIME, TTDT_AUTOPOP, 30000);
+- /*
+- * HACK: force tooltip to appear, because it'll not appear until
+- * first mouse move. D*mn M$
+ * Amazingly moving (2, 2) and then (-1, -1) the mouse doesn't move.
+ */
+ mouse_event(MOUSEEVENTF_MOVE, 2, 2, 0, 0);
+--- 8284,8289 ----
+*** ../vim-8.1.1102/src/misc1.c 2019-03-30 20:11:45.749471761 +0100
+--- src/misc1.c 2019-04-02 22:11:36.386340616 +0200
+***************
+*** 5670,5680 ****
+ int matches;
+ int len;
+ int starstar = FALSE;
+! static int stardepth = 0; /* depth for "**" expansion */
+! WIN32_FIND_DATA fb;
+! HANDLE hFind = (HANDLE)0;
+ WIN32_FIND_DATAW wfb;
+! WCHAR *wn = NULL; /* UCS-2 name, NULL when not used. */
+ char_u *matchname;
+ int ok;
+
+--- 5670,5679 ----
+ int matches;
+ int len;
+ int starstar = FALSE;
+! static int stardepth = 0; // depth for "**" expansion
+! HANDLE hFind = INVALID_HANDLE_VALUE;
+ WIN32_FIND_DATAW wfb;
+! WCHAR *wn = NULL; // UCS-2 name, NULL when not used.
+ char_u *matchname;
+ int ok;
+
+***************
+*** 5783,5815 ****
+
+ /* Scan all files in the directory with "dir/ *.*" */
+ STRCPY(s, "*.*");
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! /* The active codepage differs from 'encoding'. Attempt using the
+! * wide function. If it fails because it is not implemented fall back
+! * to the non-wide version (for Windows 98) */
+! wn = enc_to_utf16(buf, NULL);
+! if (wn != NULL)
+! {
+! hFind = FindFirstFileW(wn, &wfb);
+! if (hFind == INVALID_HANDLE_VALUE
+! && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+! VIM_CLEAR(wn);
+! }
+! }
+!
+! if (wn == NULL)
+! hFind = FindFirstFile((LPCSTR)buf, &fb);
+ ok = (hFind != INVALID_HANDLE_VALUE);
+
+ while (ok)
+ {
+! if (wn != NULL)
+! p = utf16_to_enc(wfb.cFileName, NULL); /* p is allocated here */
+! else
+! p = (char_u *)fb.cFileName;
+! /* Ignore entries starting with a dot, unless when asked for. Accept
+! * all entries found with "matchname". */
+ if ((p[0] != '.' || starts_with_dot
+ || ((flags & EW_DODOT)
+ && p[1] != NUL && (p[1] != '.' || p[2] != NUL)))
+--- 5782,5797 ----
+
+ /* Scan all files in the directory with "dir/ *.*" */
+ STRCPY(s, "*.*");
+! wn = enc_to_utf16(buf, NULL);
+! if (wn != NULL)
+! hFind = FindFirstFileW(wn, &wfb);
+ ok = (hFind != INVALID_HANDLE_VALUE);
+
+ while (ok)
+ {
+! p = utf16_to_enc(wfb.cFileName, NULL); // p is allocated here
+! // Ignore entries starting with a dot, unless when asked for. Accept
+! // all entries found with "matchname".
+ if ((p[0] != '.' || starts_with_dot
+ || ((flags & EW_DODOT)
+ && p[1] != NUL && (p[1] != '.' || p[2] != NUL)))
+***************
+*** 5851,5863 ****
+ }
+ }
+
+! if (wn != NULL)
+! {
+! vim_free(p);
+! ok = FindNextFileW(hFind, &wfb);
+! }
+! else
+! ok = FindNextFile(hFind, &fb);
+
+ /* If no more matches and no match was used, try expanding the name
+ * itself. Finds the long name of a short filename. */
+--- 5833,5840 ----
+ }
+ }
+
+! vim_free(p);
+! ok = FindNextFileW(hFind, &wfb);
+
+ /* If no more matches and no match was used, try expanding the name
+ * itself. Finds the long name of a short filename. */
+***************
+*** 5865,5879 ****
+ {
+ STRCPY(s, matchname);
+ FindClose(hFind);
+ if (wn != NULL)
+! {
+! vim_free(wn);
+! wn = enc_to_utf16(buf, NULL);
+! if (wn != NULL)
+! hFind = FindFirstFileW(wn, &wfb);
+! }
+! if (wn == NULL)
+! hFind = FindFirstFile((LPCSTR)buf, &fb);
+ ok = (hFind != INVALID_HANDLE_VALUE);
+ VIM_CLEAR(matchname);
+ }
+--- 5842,5853 ----
+ {
+ STRCPY(s, matchname);
+ FindClose(hFind);
++ vim_free(wn);
++ wn = enc_to_utf16(buf, NULL);
+ if (wn != NULL)
+! hFind = FindFirstFileW(wn, &wfb);
+! else
+! hFind = INVALID_HANDLE_VALUE;
+ ok = (hFind != INVALID_HANDLE_VALUE);
+ VIM_CLEAR(matchname);
+ }
+*** ../vim-8.1.1102/src/os_mswin.c 2019-03-30 18:46:57.360077328 +0100
+--- src/os_mswin.c 2019-04-02 22:04:17.789655489 +0200
+***************
+*** 105,111 ****
+ typedef int MOUSE_EVENT_RECORD;
+ typedef int NEWTEXTMETRICW;
+ typedef int PACL;
+! typedef int PRINTDLG;
+ typedef int PSECURITY_DESCRIPTOR;
+ typedef int PSID;
+ typedef int SECURITY_INFORMATION;
+--- 105,111 ----
+ typedef int MOUSE_EVENT_RECORD;
+ typedef int NEWTEXTMETRICW;
+ typedef int PACL;
+! typedef int PRINTDLGW;
+ typedef int PSECURITY_DESCRIPTOR;
+ typedef int PSID;
+ typedef int SECURITY_INFORMATION;
+***************
+*** 282,300 ****
+ # else
+ if (title != NULL)
+ {
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! /* Convert the title from 'encoding' to the active codepage. */
+! WCHAR *wp = enc_to_utf16(title, NULL);
+
+! if (wp != NULL)
+! {
+! SetConsoleTitleW(wp);
+! vim_free(wp);
+! return;
+! }
+! }
+! SetConsoleTitle((LPCSTR)title);
+ }
+ # endif
+ }
+--- 282,295 ----
+ # else
+ if (title != NULL)
+ {
+! WCHAR *wp = enc_to_utf16(title, NULL);
+
+! if (wp == NULL)
+! return;
+!
+! SetConsoleTitleW(wp);
+! vim_free(wp);
+! return;
+ }
+ # endif
+ }
+***************
+*** 359,398 ****
+ else
+ #endif
+ {
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *wname;
+! WCHAR wbuf[MAX_PATH];
+! char_u *cname = NULL;
+!
+! /* Use the wide function:
+! * - convert the fname from 'encoding' to UCS2.
+! * - invoke _wfullpath()
+! * - convert the result from UCS2 to 'encoding'.
+! */
+! wname = enc_to_utf16(fname, NULL);
+! if (wname != NULL && _wfullpath(wbuf, wname, MAX_PATH) != NULL)
+! {
+! cname = utf16_to_enc((short_u *)wbuf, NULL);
+! if (cname != NULL)
+! {
+! vim_strncpy(buf, cname, len - 1);
+! nResult = OK;
+! }
+! }
+! vim_free(wname);
+! vim_free(cname);
+! }
+! if (nResult == FAIL) /* fall back to non-wide function */
+ {
+! if (_fullpath((char *)buf, (const char *)fname, len - 1) == NULL)
+ {
+! /* failed, use relative path name */
+! vim_strncpy(buf, fname, len - 1);
+! }
+! else
+ nResult = OK;
+ }
+ }
+
+ #ifdef USE_FNAME_CASE
+--- 354,375 ----
+ else
+ #endif
+ {
+! WCHAR *wname;
+! WCHAR wbuf[MAX_PATH];
+! char_u *cname = NULL;
+!
+! wname = enc_to_utf16(fname, NULL);
+! if (wname != NULL && _wfullpath(wbuf, wname, MAX_PATH) != NULL)
+ {
+! cname = utf16_to_enc((short_u *)wbuf, NULL);
+! if (cname != NULL)
+ {
+! vim_strncpy(buf, cname, len - 1);
+ nResult = OK;
++ }
+ }
++ vim_free(wname);
++ vim_free(cname);
+ }
+
+ #ifdef USE_FNAME_CASE
+***************
+*** 480,536 ****
+ #endif
+
+ static int
+- stat_symlink_aware(const char *name, stat_T *stp)
+- {
+- #if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__MINGW32__)
+- /* Work around for VC12 or earlier (and MinGW). stat() can't handle
+- * symlinks properly.
+- * VC9 or earlier: stat() doesn't support a symlink at all. It retrieves
+- * status of a symlink itself.
+- * VC10: stat() supports a symlink to a normal file, but it doesn't support
+- * a symlink to a directory (always returns an error).
+- * VC11 and VC12: stat() doesn't return an error for a symlink to a
+- * directory, but it doesn't set S_IFDIR flag.
+- * MinGW: Same as VC9. */
+- WIN32_FIND_DATA findData;
+- HANDLE hFind, h;
+- DWORD attr = 0;
+- BOOL is_symlink = FALSE;
+-
+- hFind = FindFirstFile(name, &findData);
+- if (hFind != INVALID_HANDLE_VALUE)
+- {
+- attr = findData.dwFileAttributes;
+- if ((attr & FILE_ATTRIBUTE_REPARSE_POINT)
+- && (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK))
+- is_symlink = TRUE;
+- FindClose(hFind);
+- }
+- if (is_symlink)
+- {
+- h = CreateFile(name, FILE_READ_ATTRIBUTES,
+- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+- OPEN_EXISTING,
+- (attr & FILE_ATTRIBUTE_DIRECTORY)
+- ? FILE_FLAG_BACKUP_SEMANTICS : 0,
+- NULL);
+- if (h != INVALID_HANDLE_VALUE)
+- {
+- int fd, n;
+-
+- fd = _open_osfhandle((OPEN_OH_ARGTYPE)h, _O_RDONLY);
+- n = _fstat(fd, (struct _stat *)stp);
+- if ((n == 0) && (attr & FILE_ATTRIBUTE_DIRECTORY))
+- stp->st_mode = (stp->st_mode & ~S_IFREG) | S_IFDIR;
+- _close(fd);
+- return n;
+- }
+- }
+- #endif
+- return stat(name, stp);
+- }
+-
+- static int
+ wstat_symlink_aware(const WCHAR *name, stat_T *stp)
+ {
+ #if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__MINGW32__)
+--- 457,462 ----
+***************
+*** 593,598 ****
+--- 519,526 ----
+ * UTF-8. */
+ char_u buf[_MAX_PATH * 3 + 1];
+ char_u *p;
++ WCHAR *wp;
++ int n;
+
+ vim_strncpy((char_u *)buf, (char_u *)name, sizeof(buf) - 1);
+ p = buf + STRLEN(buf);
+***************
+*** 614,632 ****
+ STRCAT(buf, "\\");
+ }
+ }
+- if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+- {
+- WCHAR *wp = enc_to_utf16(buf, NULL);
+- int n;
+
+! if (wp != NULL)
+! {
+! n = wstat_symlink_aware(wp, stp);
+! vim_free(wp);
+! return n;
+! }
+! }
+! return stat_symlink_aware((char *)buf, stp);
+ }
+
+ #if defined(FEAT_GUI_MSWIN) || defined(PROTO)
+--- 542,555 ----
+ STRCAT(buf, "\\");
+ }
+ }
+
+! wp = enc_to_utf16(buf, NULL);
+! if (wp == NULL)
+! return -1;
+!
+! n = wstat_symlink_aware(wp, stp);
+! vim_free(wp);
+! return n;
+ }
+
+ #if defined(FEAT_GUI_MSWIN) || defined(PROTO)
+***************
+*** 758,763 ****
+--- 681,689 ----
+ int
+ mch_chdir(char *path)
+ {
++ WCHAR *p;
++ int n;
++
+ if (path[0] == NUL) /* just checking... */
+ return -1;
+
+***************
+*** 779,798 ****
+ if (*path == NUL) /* drive name only */
+ return 0;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *p = enc_to_utf16((char_u *)path, NULL);
+! int n;
+!
+! if (p != NULL)
+! {
+! n = _wchdir(p);
+! vim_free(p);
+! return n;
+! }
+! }
+
+! return chdir(path); /* let the normal chdir() do the rest */
+ }
+
+
+--- 705,717 ----
+ if (*path == NUL) /* drive name only */
+ return 0;
+
+! p = enc_to_utf16((char_u *)path, NULL);
+! if (p == NULL)
+! return -1;
+
+! n = _wchdir(p);
+! vim_free(p);
+! return n;
+ }
+
+
+***************
+*** 1097,1103 ****
+ */
+
+ static HFONT prt_font_handles[2][2][2];
+! static PRINTDLG prt_dlg;
+ static const int boldface[2] = {FW_REGULAR, FW_BOLD};
+ static TEXTMETRIC prt_tm;
+ static int prt_line_height;
+--- 1016,1022 ----
+ */
+
+ static HFONT prt_font_handles[2][2][2];
+! static PRINTDLGW prt_dlg;
+ static const int boldface[2] = {FW_REGULAR, FW_BOLD};
+ static TEXTMETRIC prt_tm;
+ static int prt_line_height;
+***************
+*** 1119,1136 ****
+ static BOOL
+ vimSetDlgItemText(HWND hDlg, int nIDDlgItem, char_u *s)
+ {
+! WCHAR *wp = NULL;
+ BOOL ret;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! wp = enc_to_utf16(s, NULL);
+! if (wp != NULL)
+! {
+! ret = SetDlgItemTextW(hDlg, nIDDlgItem, wp);
+! vim_free(wp);
+! return ret;
+! }
+! return SetDlgItemText(hDlg, nIDDlgItem, (LPCSTR)s);
+ }
+
+ /*
+--- 1038,1053 ----
+ static BOOL
+ vimSetDlgItemText(HWND hDlg, int nIDDlgItem, char_u *s)
+ {
+! WCHAR *wp;
+ BOOL ret;
+
+! wp = enc_to_utf16(s, NULL);
+! if (wp == NULL)
+! return FALSE;
+!
+! ret = SetDlgItemTextW(hDlg, nIDDlgItem, wp);
+! vim_free(wp);
+! return ret;
+ }
+
+ /*
+***************
+*** 1248,1254 ****
+ {
+ HWND hwndOwner;
+ RECT rc, rcDlg, rcOwner;
+! PRINTDLG *pPD;
+
+ if (uiMsg == WM_INITDIALOG)
+ {
+--- 1165,1171 ----
+ {
+ HWND hwndOwner;
+ RECT rc, rcDlg, rcOwner;
+! PRINTDLGW *pPD;
+
+ if (uiMsg == WM_INITDIALOG)
+ {
+***************
+*** 1280,1286 ****
+ SWP_NOSIZE);
+
+ /* tackle the printdlg copiesctrl problem */
+! pPD = (PRINTDLG *)lParam;
+ pPD->nCopies = (WORD)pPD->lCustData;
+ SetDlgItemInt( hDlg, edt3, pPD->nCopies, FALSE );
+ /* Bring the window to top */
+--- 1197,1203 ----
+ SWP_NOSIZE);
+
+ /* tackle the printdlg copiesctrl problem */
+! pPD = (PRINTDLGW *)lParam;
+ pPD->nCopies = (WORD)pPD->lCustData;
+ SetDlgItemInt( hDlg, edt3, pPD->nCopies, FALSE );
+ /* Bring the window to top */
+***************
+*** 1423,1435 ****
+ int pifBold;
+ int pifUnderline;
+
+! DEVMODE *mem;
+ DEVNAMES *devname;
+ int i;
+
+ bUserAbort = &(psettings->user_abort);
+! vim_memset(&prt_dlg, 0, sizeof(PRINTDLG));
+! prt_dlg.lStructSize = sizeof(PRINTDLG);
+ #ifndef FEAT_GUI
+ GetConsoleHwnd(); /* get value of s_hwnd */
+ #endif
+--- 1340,1352 ----
+ int pifBold;
+ int pifUnderline;
+
+! DEVMODEW *mem;
+ DEVNAMES *devname;
+ int i;
+
+ bUserAbort = &(psettings->user_abort);
+! vim_memset(&prt_dlg, 0, sizeof(PRINTDLGW));
+! prt_dlg.lStructSize = sizeof(PRINTDLGW);
+ #ifndef FEAT_GUI
+ GetConsoleHwnd(); /* get value of s_hwnd */
+ #endif
+***************
+*** 1470,1480 ****
+ else
+ {
+ prt_dlg.Flags |= PD_RETURNDEFAULT;
+! if (PrintDlg(&prt_dlg) == 0)
+ goto init_fail_dlg;
+ }
+ }
+! else if (PrintDlg(&prt_dlg) == 0)
+ goto init_fail_dlg;
+ else
+ {
+--- 1387,1397 ----
+ else
+ {
+ prt_dlg.Flags |= PD_RETURNDEFAULT;
+! if (PrintDlgW(&prt_dlg) == 0)
+ goto init_fail_dlg;
+ }
+ }
+! else if (PrintDlgW(&prt_dlg) == 0)
+ goto init_fail_dlg;
+ else
+ {
+***************
+*** 1510,1516 ****
+ * passed back correctly. It must be retrieved from the
+ * hDevMode struct.
+ */
+! mem = (DEVMODE *)GlobalLock(prt_dlg.hDevMode);
+ if (mem != NULL)
+ {
+ if (mem->dmCopies != 1)
+--- 1427,1433 ----
+ * passed back correctly. It must be retrieved from the
+ * hDevMode struct.
+ */
+! mem = (DEVMODEW *)GlobalLock(prt_dlg.hDevMode);
+ if (mem != NULL)
+ {
+ if (mem->dmCopies != 1)
+***************
+*** 1525,1558 ****
+ devname = (DEVNAMES *)GlobalLock(prt_dlg.hDevNames);
+ if (devname != 0)
+ {
+! char_u *printer_name = (char_u *)devname + devname->wDeviceOffset;
+! char_u *port_name = (char_u *)devname +devname->wOutputOffset;
+ char_u *text = (char_u *)_("to %s on %s");
+! char_u *printer_name_orig = printer_name;
+! char_u *port_name_orig = port_name;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! char_u *to_free = NULL;
+! int maxlen;
+!
+! acp_to_enc(printer_name, (int)STRLEN(printer_name), &to_free,
+! &maxlen);
+! if (to_free != NULL)
+! printer_name = to_free;
+! acp_to_enc(port_name, (int)STRLEN(port_name), &to_free, &maxlen);
+! if (to_free != NULL)
+! port_name = to_free;
+! }
+! prt_name = alloc((unsigned)(STRLEN(printer_name) + STRLEN(port_name)
+! + STRLEN(text)));
+ if (prt_name != NULL)
+ wsprintf((char *)prt_name, (const char *)text,
+ printer_name, port_name);
+! if (printer_name != printer_name_orig)
+! vim_free(printer_name);
+! if (port_name != port_name_orig)
+! vim_free(port_name);
+ }
+ GlobalUnlock(prt_dlg.hDevNames);
+
+--- 1442,1461 ----
+ devname = (DEVNAMES *)GlobalLock(prt_dlg.hDevNames);
+ if (devname != 0)
+ {
+! WCHAR *wprinter_name = (WCHAR *)devname + devname->wDeviceOffset;
+! WCHAR *wport_name = (WCHAR *)devname + devname->wOutputOffset;
+ char_u *text = (char_u *)_("to %s on %s");
+! char_u *printer_name = utf16_to_enc(wprinter_name, NULL);
+! char_u *port_name = utf16_to_enc(wport_name, NULL);
+
+! if (printer_name != NULL && port_name != NULL)
+! prt_name = alloc((unsigned)(STRLEN(printer_name)
+! + STRLEN(port_name) + STRLEN(text)));
+ if (prt_name != NULL)
+ wsprintf((char *)prt_name, (const char *)text,
+ printer_name, port_name);
+! vim_free(printer_name);
+! vim_free(port_name);
+ }
+ GlobalUnlock(prt_dlg.hDevNames);
+
+***************
+*** 1639,1647 ****
+ int
+ mch_print_begin(prt_settings_T *psettings)
+ {
+! int ret;
+ char szBuffer[300];
+! WCHAR *wp = NULL;
+
+ hDlgPrint = CreateDialog(GetModuleHandle(NULL), TEXT("PrintDlgBox"),
+ prt_dlg.hwndOwner, PrintDlgProc);
+--- 1542,1550 ----
+ int
+ mch_print_begin(prt_settings_T *psettings)
+ {
+! int ret = 0;
+ char szBuffer[300];
+! WCHAR *wp;
+
+ hDlgPrint = CreateDialog(GetModuleHandle(NULL), TEXT("PrintDlgBox"),
+ prt_dlg.hwndOwner, PrintDlgProc);
+***************
+*** 1649,1656 ****
+ wsprintf(szBuffer, _("Printing '%s'"), gettail(psettings->jobname));
+ vimSetDlgItemText(hDlgPrint, IDC_PRINTTEXT1, (char_u *)szBuffer);
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! wp = enc_to_utf16(psettings->jobname, NULL);
+ if (wp != NULL)
+ {
+ DOCINFOW di;
+--- 1552,1558 ----
+ wsprintf(szBuffer, _("Printing '%s'"), gettail(psettings->jobname));
+ vimSetDlgItemText(hDlgPrint, IDC_PRINTTEXT1, (char_u *)szBuffer);
+
+! wp = enc_to_utf16(psettings->jobname, NULL);
+ if (wp != NULL)
+ {
+ DOCINFOW di;
+***************
+*** 1661,1675 ****
+ ret = StartDocW(prt_dlg.hDC, &di);
+ vim_free(wp);
+ }
+- else
+- {
+- DOCINFO di;
+-
+- vim_memset(&di, 0, sizeof(di));
+- di.cbSize = sizeof(di);
+- di.lpszDocName = (LPCSTR)psettings->jobname;
+- ret = StartDoc(prt_dlg.hDC, &di);
+- }
+
+ #ifdef FEAT_GUI
+ /* Give focus back to main window (when using MDI). */
+--- 1563,1568 ----
+***************
+*** 1725,1774 ****
+ mch_print_text_out(char_u *p, int len)
+ {
+ SIZE sz;
+! WCHAR *wp = NULL;
+ int wlen = len;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! wp = enc_to_utf16(p, &wlen);
+! if (wp != NULL)
+! {
+! int ret = FALSE;
+
+! TextOutW(prt_dlg.hDC, prt_pos_x + prt_left_margin,
+! prt_pos_y + prt_top_margin, wp, wlen);
+! GetTextExtentPoint32W(prt_dlg.hDC, wp, wlen, &sz);
+! vim_free(wp);
+! prt_pos_x += (sz.cx - prt_tm.tmOverhang);
+! /* This is wrong when printing spaces for a TAB. */
+! if (p[len] != NUL)
+ {
+! wlen = MB_PTR2LEN(p + len);
+! wp = enc_to_utf16(p + len, &wlen);
+! if (wp != NULL)
+! {
+! GetTextExtentPoint32W(prt_dlg.hDC, wp, 1, &sz);
+! ret = (prt_pos_x + prt_left_margin + sz.cx > prt_right_margin);
+! vim_free(wp);
+! }
+ }
+- return ret;
+ }
+! TextOut(prt_dlg.hDC, prt_pos_x + prt_left_margin,
+! prt_pos_y + prt_top_margin,
+! (LPCSTR)p, len);
+! #ifndef FEAT_PROPORTIONAL_FONTS
+! prt_pos_x += len * prt_tm.tmAveCharWidth;
+! return (prt_pos_x + prt_left_margin + prt_tm.tmAveCharWidth
+! + prt_tm.tmOverhang > prt_right_margin);
+! #else
+! GetTextExtentPoint32(prt_dlg.hDC, (LPCSTR)p, len, &sz);
+! prt_pos_x += (sz.cx - prt_tm.tmOverhang);
+! /* This is wrong when printing spaces for a TAB. */
+! if (p[len] == NUL)
+! return FALSE;
+! GetTextExtentPoint32(prt_dlg.hDC, p + len, 1, &sz);
+! return (prt_pos_x + prt_left_margin + sz.cx > prt_right_margin);
+! #endif
+ }
+
+ void
+--- 1618,1649 ----
+ mch_print_text_out(char_u *p, int len)
+ {
+ SIZE sz;
+! WCHAR *wp;
+ int wlen = len;
++ int ret = FALSE;
+
+! wp = enc_to_utf16(p, &wlen);
+! if (wp == NULL)
+! return FALSE;
+
+! TextOutW(prt_dlg.hDC, prt_pos_x + prt_left_margin,
+! prt_pos_y + prt_top_margin, wp, wlen);
+! GetTextExtentPoint32W(prt_dlg.hDC, wp, wlen, &sz);
+! vim_free(wp);
+! prt_pos_x += (sz.cx - prt_tm.tmOverhang);
+! /* This is wrong when printing spaces for a TAB. */
+! if (p[len] != NUL)
+! {
+! wlen = MB_PTR2LEN(p + len);
+! wp = enc_to_utf16(p + len, &wlen);
+! if (wp != NULL)
+ {
+! GetTextExtentPoint32W(prt_dlg.hDC, wp, 1, &sz);
+! ret = (prt_pos_x + prt_left_margin + sz.cx > prt_right_margin);
+! vim_free(wp);
+ }
+ }
+! return ret;
+ }
+
+ void
+***************
+*** 1863,1868 ****
+--- 1738,1744 ----
+ {
+ HANDLE h = INVALID_HANDLE_VALUE;
+ DWORD size;
++ WCHAR *p;
+ char_u *rfname = NULL;
+ FILE_NAME_INFO_ *nameinfo = NULL;
+ WCHAR buff[MAX_PATH], *volnames = NULL;
+***************
+*** 1887,1919 ****
+ return NULL;
+ }
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *p;
+!
+! p = enc_to_utf16(fname, NULL);
+! if (p == NULL)
+! goto fail;
+!
+! if ((GetFileAttributesW(p) & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
+! {
+! vim_free(p);
+! goto fail;
+! }
+
+! h = CreateFileW(p, 0, 0, NULL, OPEN_EXISTING,
+! FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ vim_free(p);
+ }
+- else
+- {
+- if ((GetFileAttributes((char*) fname) &
+- FILE_ATTRIBUTE_REPARSE_POINT) == 0)
+- goto fail;
+
+! h = CreateFile((char*) fname, 0, 0, NULL, OPEN_EXISTING,
+! FILE_FLAG_BACKUP_SEMANTICS, NULL);
+! }
+
+ if (h == INVALID_HANDLE_VALUE)
+ goto fail;
+--- 1763,1781 ----
+ return NULL;
+ }
+
+! p = enc_to_utf16(fname, NULL);
+! if (p == NULL)
+! goto fail;
+
+! if ((GetFileAttributesW(p) & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
+! {
+ vim_free(p);
++ goto fail;
+ }
+
+! h = CreateFileW(p, 0, 0, NULL, OPEN_EXISTING,
+! FILE_FLAG_BACKUP_SEMANTICS, NULL);
+! vim_free(p);
+
+ if (h == INVALID_HANDLE_VALUE)
+ goto fail;
+***************
+*** 1988,1995 ****
+ 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;
+--- 1850,1855 ----
+***************
+*** 2005,2084 ****
+
+ CoInitialize(NULL);
+
+! 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:
+! vim_free(p);
+! goto shortcut_end;
+! }
+ }
+- goto shortcut_end;
+ }
+- // 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);
+--- 1865,1907 ----
+
+ CoInitialize(NULL);
+
+! // 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:
+! vim_free(p);
+ }
+ }
+
+ // Release all interface pointers (both belong to the same object)
+ if (ppf != NULL)
+ ppf->lpVtbl->Release(ppf);
+*** ../vim-8.1.1102/src/os_win32.c 2019-03-30 22:11:17.534968563 +0100
+--- src/os_win32.c 2019-04-02 22:14:38.712846295 +0200
+***************
+*** 586,592 ****
+ static char *null_libintl_textdomain(const char *);
+ static char *null_libintl_bindtextdomain(const char *, const char *);
+ static char *null_libintl_bind_textdomain_codeset(const char *, const char *);
+- static int null_libintl_putenv(const char *);
+ static int null_libintl_wputenv(const wchar_t *);
+
+ static HINSTANCE hLibintlDLL = NULL;
+--- 586,591 ----
+***************
+*** 598,604 ****
+ = null_libintl_bindtextdomain;
+ char *(*dyn_libintl_bind_textdomain_codeset)(const char *, const char *)
+ = null_libintl_bind_textdomain_codeset;
+- int (*dyn_libintl_putenv)(const char *) = null_libintl_putenv;
+ int (*dyn_libintl_wputenv)(const wchar_t *) = null_libintl_wputenv;
+
+ int
+--- 597,602 ----
+***************
+*** 666,680 ****
+ dyn_libintl_bind_textdomain_codeset =
+ null_libintl_bind_textdomain_codeset;
+
+! /* _putenv() function for the libintl.dll is optional. */
+ hmsvcrt = find_imported_module_by_funcname(hLibintlDLL, "getenv");
+ if (hmsvcrt != NULL)
+- {
+- dyn_libintl_putenv = (void *)GetProcAddress(hmsvcrt, "_putenv");
+ dyn_libintl_wputenv = (void *)GetProcAddress(hmsvcrt, "_wputenv");
+- }
+- if (dyn_libintl_putenv == NULL || dyn_libintl_putenv == _putenv)
+- dyn_libintl_putenv = null_libintl_putenv;
+ if (dyn_libintl_wputenv == NULL || dyn_libintl_wputenv == _wputenv)
+ dyn_libintl_wputenv = null_libintl_wputenv;
+
+--- 664,673 ----
+ dyn_libintl_bind_textdomain_codeset =
+ null_libintl_bind_textdomain_codeset;
+
+! /* _wputenv() function for the libintl.dll is optional. */
+ hmsvcrt = find_imported_module_by_funcname(hLibintlDLL, "getenv");
+ if (hmsvcrt != NULL)
+ dyn_libintl_wputenv = (void *)GetProcAddress(hmsvcrt, "_wputenv");
+ if (dyn_libintl_wputenv == NULL || dyn_libintl_wputenv == _wputenv)
+ dyn_libintl_wputenv = null_libintl_wputenv;
+
+***************
+*** 692,698 ****
+ dyn_libintl_textdomain = null_libintl_textdomain;
+ dyn_libintl_bindtextdomain = null_libintl_bindtextdomain;
+ dyn_libintl_bind_textdomain_codeset = null_libintl_bind_textdomain_codeset;
+- dyn_libintl_putenv = null_libintl_putenv;
+ dyn_libintl_wputenv = null_libintl_wputenv;
+ }
+
+--- 685,690 ----
+***************
+*** 734,745 ****
+ }
+
+ static int
+- null_libintl_putenv(const char *envstring UNUSED)
+- {
+- return 0;
+- }
+-
+- static int
+ null_libintl_wputenv(const wchar_t *envstring UNUSED)
+ {
+ return 0;
+--- 726,731 ----
+***************
+*** 2027,2035 ****
+ static int
+ executable_exists(char *name, char_u **path, int use_path)
+ {
+! char *dum;
+! char fname[_MAX_PATH];
+! char *curpath, *newpath;
+ long n;
+
+ if (!use_path)
+--- 2013,2022 ----
+ static int
+ executable_exists(char *name, char_u **path, int use_path)
+ {
+! WCHAR *p;
+! WCHAR fnamew[_MAX_PATH];
+! WCHAR *dumw;
+! WCHAR *wcurpath, *wnewpath;
+ long n;
+
+ if (!use_path)
+***************
+*** 2048,2096 ****
+ return FALSE;
+ }
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *p = enc_to_utf16((char_u *)name, NULL);
+! WCHAR fnamew[_MAX_PATH];
+! WCHAR *dumw;
+! WCHAR *wcurpath, *wnewpath;
+!
+! if (p != NULL)
+! {
+! wcurpath = _wgetenv(L"PATH");
+! wnewpath = (WCHAR*)alloc((unsigned)(wcslen(wcurpath) + 3)
+! * sizeof(WCHAR));
+! if (wnewpath == NULL)
+! return FALSE;
+! wcscpy(wnewpath, L".;");
+! wcscat(wnewpath, wcurpath);
+! n = (long)SearchPathW(wnewpath, p, NULL, _MAX_PATH, fnamew, &dumw);
+! vim_free(wnewpath);
+! vim_free(p);
+! if (n == 0)
+! return FALSE;
+! if (GetFileAttributesW(fnamew) & FILE_ATTRIBUTE_DIRECTORY)
+! return FALSE;
+! if (path != NULL)
+! *path = utf16_to_enc(fnamew, NULL);
+! return TRUE;
+! }
+! }
+
+! curpath = getenv("PATH");
+! newpath = (char*)alloc((unsigned)(STRLEN(curpath) + 3));
+! if (newpath == NULL)
+ return FALSE;
+! STRCPY(newpath, ".;");
+! STRCAT(newpath, curpath);
+! n = (long)SearchPath(newpath, name, NULL, _MAX_PATH, fname, &dum);
+! vim_free(newpath);
+ if (n == 0)
+ return FALSE;
+! if (mch_isdir((char_u *)fname))
+ return FALSE;
+ if (path != NULL)
+! *path = vim_strsave((char_u *)fname);
+ return TRUE;
+ }
+
+--- 2035,2060 ----
+ return FALSE;
+ }
+
+! p = enc_to_utf16((char_u *)name, NULL);
+! if (p == NULL)
+! return FALSE;
+
+! wcurpath = _wgetenv(L"PATH");
+! wnewpath = (WCHAR*)alloc((unsigned)(wcslen(wcurpath) + 3)
+! * sizeof(WCHAR));
+! if (wnewpath == NULL)
+ return FALSE;
+! wcscpy(wnewpath, L".;");
+! wcscat(wnewpath, wcurpath);
+! n = (long)SearchPathW(wnewpath, p, NULL, _MAX_PATH, fnamew, &dumw);
+! vim_free(wnewpath);
+! vim_free(p);
+ if (n == 0)
+ return FALSE;
+! if (GetFileAttributesW(fnamew) & FILE_ATTRIBUTE_DIRECTORY)
+ return FALSE;
+ if (path != NULL)
+! *path = utf16_to_enc(fnamew, NULL);
+ return TRUE;
+ }
+
+***************
+*** 2812,2842 ****
+ char_u *s,
+ int len)
+ {
+! char szUserName[256 + 1]; /* UNLEN is 256 */
+! DWORD cch = sizeof szUserName;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+! WCHAR wszUserName[256 + 1]; /* UNLEN is 256 */
+! DWORD wcch = sizeof(wszUserName) / sizeof(WCHAR);
+
+! if (GetUserNameW(wszUserName, &wcch))
+ {
+! char_u *p = utf16_to_enc(wszUserName, NULL);
+!
+! if (p != NULL)
+! {
+! vim_strncpy(s, p, len - 1);
+! vim_free(p);
+! return OK;
+! }
+ }
+ }
+- if (GetUserName(szUserName, &cch))
+- {
+- vim_strncpy(s, (char_u *)szUserName, len - 1);
+- return OK;
+- }
+ s[0] = NUL;
+ return FAIL;
+ }
+--- 2776,2795 ----
+ char_u *s,
+ int len)
+ {
+! WCHAR wszUserName[256 + 1]; /* UNLEN is 256 */
+! DWORD wcch = sizeof(wszUserName) / sizeof(WCHAR);
+
+! if (GetUserNameW(wszUserName, &wcch))
+ {
+! char_u *p = utf16_to_enc(wszUserName, NULL);
+
+! if (p != NULL)
+ {
+! vim_strncpy(s, p, len - 1);
+! vim_free(p);
+! return OK;
+ }
+ }
+ s[0] = NUL;
+ return FAIL;
+ }
+***************
+*** 2850,2876 ****
+ char_u *s,
+ int len)
+ {
+! DWORD cch = len;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+! WCHAR wszHostName[256 + 1];
+! DWORD wcch = sizeof(wszHostName) / sizeof(WCHAR);
+
+! if (GetComputerNameW(wszHostName, &wcch))
+ {
+! char_u *p = utf16_to_enc(wszHostName, NULL);
+!
+! if (p != NULL)
+! {
+! vim_strncpy(s, p, len - 1);
+! vim_free(p);
+! return;
+! }
+ }
+ }
+- if (!GetComputerName((LPSTR)s, &cch))
+- vim_strncpy(s, (char_u *)"PC (Win32 Vim)", len - 1);
+ }
+
+
+--- 2803,2822 ----
+ char_u *s,
+ int len)
+ {
+! WCHAR wszHostName[256 + 1];
+! DWORD wcch = sizeof(wszHostName) / sizeof(WCHAR);
+
+! if (GetComputerNameW(wszHostName, &wcch))
+ {
+! char_u *p = utf16_to_enc(wszHostName, NULL);
+
+! if (p != NULL)
+ {
+! vim_strncpy(s, p, len - 1);
+! vim_free(p);
+! return;
+ }
+ }
+ }
+
+
+***************
+*** 2893,2900 ****
+ char_u *buf,
+ int len)
+ {
+! char_u abuf[_MAX_PATH + 1];
+! DWORD lfnlen;
+
+ /*
+ * Originally this was:
+--- 2839,2845 ----
+ char_u *buf,
+ int len)
+ {
+! WCHAR wbuf[_MAX_PATH + 1];
+
+ /*
+ * Originally this was:
+***************
+*** 2902,2948 ****
+ * But the Win32s known bug list says that getcwd() doesn't work
+ * so use the Win32 system call instead. <Negri>
+ */
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+! WCHAR wbuf[_MAX_PATH + 1];
+
+! if (GetCurrentDirectoryW(_MAX_PATH, wbuf) != 0)
+ {
+! WCHAR wcbuf[_MAX_PATH + 1];
+! char_u *p = NULL;
+!
+! if (GetLongPathNameW(wbuf, wcbuf, _MAX_PATH) != 0)
+! {
+! p = utf16_to_enc(wcbuf, NULL);
+! if (STRLEN(p) >= (size_t)len)
+! {
+! // long path name is too long, fall back to short one
+! vim_free(p);
+! p = NULL;
+! }
+! }
+! if (p == NULL)
+! p = utf16_to_enc(wbuf, NULL);
+!
+! if (p != NULL)
+ {
+! vim_strncpy(buf, p, len - 1);
+ vim_free(p);
+! return OK;
+ }
+ }
+! return FAIL;
+! }
+! if (GetCurrentDirectory(len, (LPSTR)buf) == 0)
+! return FAIL;
+! lfnlen = GetLongPathNameA((LPCSTR)buf, (LPSTR)abuf, _MAX_PATH);
+! if (lfnlen == 0 || lfnlen >= (DWORD)len)
+! // Failed to get long path name or it's too long: fall back to the
+! // short path name.
+! return OK;
+
+! STRCPY(buf, abuf);
+! return OK;
+ }
+
+ /*
+--- 2847,2878 ----
+ * But the Win32s known bug list says that getcwd() doesn't work
+ * so use the Win32 system call instead. <Negri>
+ */
+! if (GetCurrentDirectoryW(_MAX_PATH, wbuf) != 0)
+ {
+! WCHAR wcbuf[_MAX_PATH + 1];
+! char_u *p = NULL;
+
+! if (GetLongPathNameW(wbuf, wcbuf, _MAX_PATH) != 0)
+ {
+! p = utf16_to_enc(wcbuf, NULL);
+! if (STRLEN(p) >= (size_t)len)
+ {
+! // long path name is too long, fall back to short one
+ vim_free(p);
+! p = NULL;
+ }
+ }
+! if (p == NULL)
+! p = utf16_to_enc(wbuf, NULL);
+
+! if (p != NULL)
+! {
+! vim_strncpy(buf, p, len - 1);
+! vim_free(p);
+! return OK;
+! }
+! }
+! return FAIL;
+ }
+
+ /*
+***************
+*** 2968,2989 ****
+ int
+ mch_setperm(char_u *name, long perm)
+ {
+! long n = -1;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *p = enc_to_utf16(name, NULL);
+
+! if (p != NULL)
+! {
+! n = _wchmod(p, perm);
+! vim_free(p);
+! if (n == -1)
+! return FAIL;
+! }
+! }
+! if (n == -1)
+! n = _chmod((const char *)name, perm);
+ if (n == -1)
+ return FAIL;
+
+--- 2898,2912 ----
+ int
+ mch_setperm(char_u *name, long perm)
+ {
+! long n;
+! WCHAR *p;
+
+! p = enc_to_utf16(name, NULL);
+! if (p == NULL)
+! return FAIL;
+
+! n = _wchmod(p, perm);
+! vim_free(p);
+ if (n == -1)
+ return FAIL;
+
+***************
+*** 3053,3071 ****
+ int
+ mch_mkdir(char_u *name)
+ {
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *p;
+! int retval;
+
+! p = enc_to_utf16(name, NULL);
+! if (p == NULL)
+! return -1;
+! retval = _wmkdir(p);
+! vim_free(p);
+! return retval;
+! }
+! return _mkdir((const char *)name);
+ }
+
+ /*
+--- 2976,2990 ----
+ int
+ mch_mkdir(char_u *name)
+ {
+! WCHAR *p;
+! int retval;
+
+! p = enc_to_utf16(name, NULL);
+! if (p == NULL)
+! return -1;
+! retval = _wmkdir(p);
+! vim_free(p);
+! return retval;
+ }
+
+ /*
+***************
+*** 3075,3093 ****
+ int
+ mch_rmdir(char_u *name)
+ {
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *p;
+! int retval;
+
+! p = enc_to_utf16(name, NULL);
+! if (p == NULL)
+! return -1;
+! retval = _wrmdir(p);
+! vim_free(p);
+! return retval;
+! }
+! return _rmdir((const char *)name);
+ }
+
+ /*
+--- 2994,3008 ----
+ int
+ mch_rmdir(char_u *name)
+ {
+! WCHAR *p;
+! int retval;
+
+! p = enc_to_utf16(name, NULL);
+! if (p == NULL)
+! return -1;
+! retval = _wrmdir(p);
+! vim_free(p);
+! return retval;
+ }
+
+ /*
+***************
+*** 3110,3144 ****
+ {
+ HANDLE hFind;
+ int res = FALSE;
+- WIN32_FIND_DATAA findDataA;
+ DWORD fileFlags = 0, reparseTag = 0;
+! WCHAR *wn = NULL;
+ WIN32_FIND_DATAW findDataW;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! wn = enc_to_utf16(name, NULL);
+! if (wn != NULL)
+! {
+! hFind = FindFirstFileW(wn, &findDataW);
+! vim_free(wn);
+! if (hFind != INVALID_HANDLE_VALUE)
+! {
+! fileFlags = findDataW.dwFileAttributes;
+! reparseTag = findDataW.dwReserved0;
+! }
+! }
+! else
+! {
+! hFind = FindFirstFile((LPCSTR)name, &findDataA);
+! if (hFind != INVALID_HANDLE_VALUE)
+! {
+! fileFlags = findDataA.dwFileAttributes;
+! reparseTag = findDataA.dwReserved0;
+! }
+! }
+
+ if (hFind != INVALID_HANDLE_VALUE)
+ FindClose(hFind);
+
+ if ((fileFlags & FILE_ATTRIBUTE_REPARSE_POINT)
+ && (reparseTag == IO_REPARSE_TAG_SYMLINK
+--- 3025,3046 ----
+ {
+ HANDLE hFind;
+ int res = FALSE;
+ DWORD fileFlags = 0, reparseTag = 0;
+! WCHAR *wn;
+ WIN32_FIND_DATAW findDataW;
+
+! wn = enc_to_utf16(name, NULL);
+! if (wn == NULL)
+! return FALSE;
+
++ hFind = FindFirstFileW(wn, &findDataW);
++ vim_free(wn);
+ if (hFind != INVALID_HANDLE_VALUE)
++ {
++ fileFlags = findDataW.dwFileAttributes;
++ reparseTag = findDataW.dwReserved0;
+ FindClose(hFind);
++ }
+
+ if ((fileFlags & FILE_ATTRIBUTE_REPARSE_POINT)
+ && (reparseTag == IO_REPARSE_TAG_SYMLINK
+***************
+*** 3172,3204 ****
+ {
+ HANDLE hFile;
+ int res = FILEINFO_READ_FAIL;
+! WCHAR *wn = NULL;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! wn = enc_to_utf16(fname, NULL);
+! if (wn == NULL)
+! return FILEINFO_ENC_FAIL;
+! }
+! if (wn != NULL)
+! {
+! hFile = CreateFileW(wn, /* file name */
+! GENERIC_READ, /* access mode */
+! FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */
+! NULL, /* security descriptor */
+! OPEN_EXISTING, /* creation disposition */
+! FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */
+! NULL); /* handle to template file */
+! vim_free(wn);
+! }
+! else
+! hFile = CreateFile((LPCSTR)fname, /* file name */
+! GENERIC_READ, /* access mode */
+! FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */
+! NULL, /* security descriptor */
+! OPEN_EXISTING, /* creation disposition */
+! FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */
+! NULL); /* handle to template file */
+
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+--- 3074,3093 ----
+ {
+ HANDLE hFile;
+ int res = FILEINFO_READ_FAIL;
+! WCHAR *wn;
+
+! wn = enc_to_utf16(fname, NULL);
+! if (wn == NULL)
+! return FILEINFO_ENC_FAIL;
+!
+! hFile = CreateFileW(wn, // file name
+! GENERIC_READ, // access mode
+! FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
+! NULL, // security descriptor
+! OPEN_EXISTING, // creation disposition
+! FILE_FLAG_BACKUP_SEMANTICS, // file attributes
+! NULL); // handle to template file
+! vim_free(wn);
+
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+***************
+*** 3221,3238 ****
+ win32_getattrs(char_u *name)
+ {
+ int attr;
+! WCHAR *p = NULL;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! p = enc_to_utf16(name, NULL);
+
+! if (p != NULL)
+! {
+! attr = GetFileAttributesW(p);
+! vim_free(p);
+! }
+! else
+! attr = GetFileAttributes((char *)name);
+
+ return attr;
+ }
+--- 3110,3123 ----
+ win32_getattrs(char_u *name)
+ {
+ int attr;
+! WCHAR *p;
+
+! p = enc_to_utf16(name, NULL);
+! if (p == NULL)
+! return INVALID_FILE_ATTRIBUTES;
+
+! attr = GetFileAttributesW(p);
+! vim_free(p);
+
+ return attr;
+ }
+***************
+*** 3245,3263 ****
+ static int
+ win32_setattrs(char_u *name, int attrs)
+ {
+! int res;
+! WCHAR *p = NULL;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! p = enc_to_utf16(name, NULL);
+
+! if (p != NULL)
+! {
+! res = SetFileAttributesW(p, attrs);
+! vim_free(p);
+! }
+! else
+! res = SetFileAttributes((char *)name, attrs);
+
+ return res ? 0 : -1;
+ }
+--- 3130,3144 ----
+ static int
+ win32_setattrs(char_u *name, int attrs)
+ {
+! int res;
+! WCHAR *p;
+
+! p = enc_to_utf16(name, NULL);
+! if (p == NULL)
+! return -1;
+
+! res = SetFileAttributesW(p, attrs);
+! vim_free(p);
+
+ return res ? 0 : -1;
+ }
+***************
+*** 3375,3381 ****
+ {
+ HANDLE hFile;
+ int type;
+! WCHAR *wn = NULL;
+
+ /* We can't open a file with a name "\\.\con" or "\\.\prn" and trying to
+ * read from it later will cause Vim to hang. Thus return NODE_WRITABLE
+--- 3256,3262 ----
+ {
+ HANDLE hFile;
+ int type;
+! WCHAR *wn;
+
+ /* We can't open a file with a name "\\.\con" or "\\.\prn" and trying to
+ * read from it later will cause Vim to hang. Thus return NODE_WRITABLE
+***************
+*** 3383,3411 ****
+ if (STRNCMP(name, "\\\\.\\", 4) == 0)
+ return NODE_WRITABLE;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! wn = enc_to_utf16(name, NULL);
+!
+! if (wn != NULL)
+! {
+! hFile = CreateFileW(wn, /* file name */
+! GENERIC_WRITE, /* access mode */
+! 0, /* share mode */
+! NULL, /* security descriptor */
+! OPEN_EXISTING, /* creation disposition */
+! 0, /* file attributes */
+! NULL); /* handle to template file */
+! vim_free(wn);
+! }
+! else
+! hFile = CreateFile((LPCSTR)name, /* file name */
+! GENERIC_WRITE, /* access mode */
+! 0, /* share mode */
+! NULL, /* security descriptor */
+! OPEN_EXISTING, /* creation disposition */
+! 0, /* file attributes */
+! NULL); /* handle to template file */
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return NODE_NORMAL;
+
+--- 3264,3281 ----
+ if (STRNCMP(name, "\\\\.\\", 4) == 0)
+ return NODE_WRITABLE;
+
+! wn = enc_to_utf16(name, NULL);
+! if (wn == NULL)
+! return NODE_NORMAL;
+
++ hFile = CreateFileW(wn, // file name
++ GENERIC_WRITE, // access mode
++ 0, // share mode
++ NULL, // security descriptor
++ OPEN_EXISTING, // creation disposition
++ 0, // file attributes
++ NULL); // handle to template file
++ vim_free(wn);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return NODE_NORMAL;
+
+***************
+*** 3445,3525 ****
+ p = (struct my_acl *)alloc_clear((unsigned)sizeof(struct my_acl));
+ if (p != NULL)
+ {
+! WCHAR *wn = NULL;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! wn = enc_to_utf16(fname, NULL);
+! if (wn != NULL)
+! {
+! /* Try to retrieve the entire security descriptor. */
+! err = GetNamedSecurityInfoW(
+! wn, // Abstract filename
+! SE_FILE_OBJECT, // File Object
+! OWNER_SECURITY_INFORMATION |
+! GROUP_SECURITY_INFORMATION |
+! DACL_SECURITY_INFORMATION |
+! SACL_SECURITY_INFORMATION,
+! &p->pSidOwner, // Ownership information.
+! &p->pSidGroup, // Group membership.
+! &p->pDacl, // Discretionary information.
+! &p->pSacl, // For auditing purposes.
+ &p->pSecurityDescriptor);
+- if (err == ERROR_ACCESS_DENIED ||
+- err == ERROR_PRIVILEGE_NOT_HELD)
+- {
+- /* Retrieve only DACL. */
+- (void)GetNamedSecurityInfoW(
+- wn,
+- SE_FILE_OBJECT,
+- DACL_SECURITY_INFORMATION,
+- NULL,
+- NULL,
+- &p->pDacl,
+- NULL,
+- &p->pSecurityDescriptor);
+- }
+- if (p->pSecurityDescriptor == NULL)
+- {
+- mch_free_acl((vim_acl_T)p);
+- p = NULL;
+- }
+- vim_free(wn);
+ }
+! else
+ {
+! /* Try to retrieve the entire security descriptor. */
+! err = GetNamedSecurityInfo(
+! (LPSTR)fname, // Abstract filename
+! SE_FILE_OBJECT, // File Object
+! OWNER_SECURITY_INFORMATION |
+! GROUP_SECURITY_INFORMATION |
+! DACL_SECURITY_INFORMATION |
+! SACL_SECURITY_INFORMATION,
+! &p->pSidOwner, // Ownership information.
+! &p->pSidGroup, // Group membership.
+! &p->pDacl, // Discretionary information.
+! &p->pSacl, // For auditing purposes.
+! &p->pSecurityDescriptor);
+! if (err == ERROR_ACCESS_DENIED ||
+! err == ERROR_PRIVILEGE_NOT_HELD)
+! {
+! /* Retrieve only DACL. */
+! (void)GetNamedSecurityInfo(
+! (LPSTR)fname,
+! SE_FILE_OBJECT,
+! DACL_SECURITY_INFORMATION,
+! NULL,
+! NULL,
+! &p->pDacl,
+! NULL,
+! &p->pSecurityDescriptor);
+! }
+! if (p->pSecurityDescriptor == NULL)
+! {
+! mch_free_acl((vim_acl_T)p);
+! p = NULL;
+! }
+ }
+ }
+
+ return (vim_acl_T)p;
+--- 3315,3359 ----
+ p = (struct my_acl *)alloc_clear((unsigned)sizeof(struct my_acl));
+ if (p != NULL)
+ {
+! WCHAR *wn;
+!
+! wn = enc_to_utf16(fname, NULL);
+! if (wn == NULL)
+! return NULL;
+
+! // Try to retrieve the entire security descriptor.
+! err = GetNamedSecurityInfoW(
+! wn, // Abstract filename
+! SE_FILE_OBJECT, // File Object
+! OWNER_SECURITY_INFORMATION |
+! GROUP_SECURITY_INFORMATION |
+! DACL_SECURITY_INFORMATION |
+! SACL_SECURITY_INFORMATION,
+! &p->pSidOwner, // Ownership information.
+! &p->pSidGroup, // Group membership.
+! &p->pDacl, // Discretionary information.
+! &p->pSacl, // For auditing purposes.
+! &p->pSecurityDescriptor);
+! if (err == ERROR_ACCESS_DENIED ||
+! err == ERROR_PRIVILEGE_NOT_HELD)
+! {
+! // Retrieve only DACL.
+! (void)GetNamedSecurityInfoW(
+! wn,
+! SE_FILE_OBJECT,
+! DACL_SECURITY_INFORMATION,
+! NULL,
+! NULL,
+! &p->pDacl,
+! NULL,
+ &p->pSecurityDescriptor);
+ }
+! if (p->pSecurityDescriptor == NULL)
+ {
+! mch_free_acl((vim_acl_T)p);
+! p = NULL;
+ }
++ vim_free(wn);
+ }
+
+ return (vim_acl_T)p;
+***************
+*** 3560,3615 ****
+ #ifdef HAVE_ACL
+ struct my_acl *p = (struct my_acl *)acl;
+ SECURITY_INFORMATION sec_info = 0;
+
+! if (p != NULL)
+! {
+! WCHAR *wn = NULL;
+
+! /* Set security flags */
+! if (p->pSidOwner)
+! sec_info |= OWNER_SECURITY_INFORMATION;
+! if (p->pSidGroup)
+! sec_info |= GROUP_SECURITY_INFORMATION;
+! if (p->pDacl)
+! {
+! sec_info |= DACL_SECURITY_INFORMATION;
+! /* Do not inherit its parent's DACL.
+! * If the DACL is inherited, Cygwin permissions would be changed.
+! */
+! if (!is_acl_inherited(p->pDacl))
+! sec_info |= PROTECTED_DACL_SECURITY_INFORMATION;
+! }
+! if (p->pSacl)
+! sec_info |= SACL_SECURITY_INFORMATION;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! wn = enc_to_utf16(fname, NULL);
+! if (wn != NULL)
+! {
+! (void)SetNamedSecurityInfoW(
+! wn, // Abstract filename
+! SE_FILE_OBJECT, // File Object
+! sec_info,
+! p->pSidOwner, // Ownership information.
+! p->pSidGroup, // Group membership.
+! p->pDacl, // Discretionary information.
+! p->pSacl // For auditing purposes.
+! );
+! vim_free(wn);
+! }
+! else
+! {
+! (void)SetNamedSecurityInfo(
+! (LPSTR)fname, // Abstract filename
+! SE_FILE_OBJECT, // File Object
+! sec_info,
+! p->pSidOwner, // Ownership information.
+! p->pSidGroup, // Group membership.
+! p->pDacl, // Discretionary information.
+! p->pSacl // For auditing purposes.
+! );
+! }
+! }
+ #endif
+ }
+
+--- 3394,3434 ----
+ #ifdef HAVE_ACL
+ struct my_acl *p = (struct my_acl *)acl;
+ SECURITY_INFORMATION sec_info = 0;
++ WCHAR *wn;
+
+! if (p == NULL)
+! return;
+
+! wn = enc_to_utf16(fname, NULL);
+! if (wn == NULL)
+! return;
+
+! // Set security flags
+! if (p->pSidOwner)
+! sec_info |= OWNER_SECURITY_INFORMATION;
+! if (p->pSidGroup)
+! sec_info |= GROUP_SECURITY_INFORMATION;
+! if (p->pDacl)
+! {
+! sec_info |= DACL_SECURITY_INFORMATION;
+! // Do not inherit its parent's DACL.
+! // If the DACL is inherited, Cygwin permissions would be changed.
+! if (!is_acl_inherited(p->pDacl))
+! sec_info |= PROTECTED_DACL_SECURITY_INFORMATION;
+! }
+! if (p->pSacl)
+! sec_info |= SACL_SECURITY_INFORMATION;
+!
+! (void)SetNamedSecurityInfoW(
+! wn, // Abstract filename
+! SE_FILE_OBJECT, // File Object
+! sec_info,
+! p->pSidOwner, // Ownership information.
+! p->pSidGroup, // Group membership.
+! p->pDacl, // Discretionary information.
+! p->pSacl // For auditing purposes.
+! );
+! vim_free(wn);
+ #endif
+ }
+
+***************
+*** 3955,4005 ****
+ LPVOID *env,
+ char *cwd)
+ {
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! BOOL ret;
+! WCHAR *wcmd, *wcwd = NULL;
+
+! wcmd = enc_to_utf16((char_u *)cmd, NULL);
+! if (wcmd == NULL)
+! goto fallback;
+! if (cwd != NULL)
+! {
+! wcwd = enc_to_utf16((char_u *)cwd, NULL);
+! if (wcwd == NULL)
+! {
+! vim_free(wcmd);
+! goto fallback;
+! }
+! }
+!
+! ret = CreateProcessW(
+! NULL, /* Executable name */
+! wcmd, /* Command to execute */
+! NULL, /* Process security attributes */
+! NULL, /* Thread security attributes */
+! inherit_handles, /* Inherit handles */
+! flags, /* Creation flags */
+! env, /* Environment */
+! wcwd, /* Current directory */
+! (LPSTARTUPINFOW)si, /* Startup information */
+! pi); /* Process information */
+! vim_free(wcmd);
+! vim_free(wcwd);
+! return ret;
+! }
+! fallback:
+! return CreateProcess(
+! NULL, /* Executable name */
+! cmd, /* Command to execute */
+! NULL, /* Process security attributes */
+! NULL, /* Thread security attributes */
+! inherit_handles, /* Inherit handles */
+! flags, /* Creation flags */
+! env, /* Environment */
+! cwd, /* Current directory */
+! si, /* Startup information */
+! pi); /* Process information */
+ }
+
+
+--- 3774,3807 ----
+ LPVOID *env,
+ char *cwd)
+ {
+! BOOL ret = FALSE;
+! WCHAR *wcmd, *wcwd = NULL;
+
+! wcmd = enc_to_utf16((char_u *)cmd, NULL);
+! if (wcmd == NULL)
+! return FALSE;
+! if (cwd != NULL)
+! {
+! wcwd = enc_to_utf16((char_u *)cwd, NULL);
+! if (wcwd == NULL)
+! goto theend;
+! }
+!
+! ret = CreateProcessW(
+! NULL, // Executable name
+! wcmd, // Command to execute
+! NULL, // Process security attributes
+! NULL, // Thread security attributes
+! inherit_handles, // Inherit handles
+! flags, // Creation flags
+! env, // Environment
+! wcwd, // Current directory
+! (LPSTARTUPINFOW)si, // Startup information
+! pi); // Process information
+! theend:
+! vim_free(wcmd);
+! vim_free(wcwd);
+! return ret;
+ }
+
+
+***************
+*** 4008,4025 ****
+ char *cmd,
+ INT n_show_cmd)
+ {
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *wcmd = enc_to_utf16((char_u *)cmd, NULL);
+! if (wcmd != NULL)
+! {
+! HINSTANCE ret;
+! ret = ShellExecuteW(NULL, NULL, wcmd, NULL, NULL, n_show_cmd);
+! vim_free(wcmd);
+! return ret;
+! }
+! }
+! return ShellExecute(NULL, NULL, cmd, NULL, NULL, n_show_cmd);
+ }
+
+
+--- 3810,3825 ----
+ char *cmd,
+ INT n_show_cmd)
+ {
+! HINSTANCE ret;
+! WCHAR *wcmd;
+!
+! wcmd = enc_to_utf16((char_u *)cmd, NULL);
+! if (wcmd == NULL)
+! return (HINSTANCE) 0;
+!
+! ret = ShellExecuteW(NULL, NULL, wcmd, NULL, NULL, n_show_cmd);
+! vim_free(wcmd);
+! return ret;
+ }
+
+
+***************
+*** 4582,4598 ****
+ static int
+ mch_system(char *cmd, int options)
+ {
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *wcmd = enc_to_utf16((char_u *)cmd, NULL);
+! if (wcmd != NULL)
+! {
+! int ret = _wsystem(wcmd);
+! vim_free(wcmd);
+! return ret;
+! }
+! }
+! return system(cmd);
+ }
+
+ #endif
+--- 4382,4397 ----
+ static int
+ mch_system(char *cmd, int options)
+ {
+! int ret;
+! WCHAR *wcmd;
+!
+! wcmd = enc_to_utf16((char_u *)cmd, NULL);
+! if (wcmd == NULL)
+! return -1;
+!
+! ret = _wsystem(wcmd);
+! vim_free(wcmd);
+! return ret;
+ }
+
+ #endif
+***************
+*** 4692,4742 ****
+ int x = 0;
+ int tmode = cur_tmode;
+ #ifdef FEAT_TITLE
+! char szShellTitle[512];
+! int did_set_title = FALSE;
+
+ /* Change the title to reflect that we are in a subshell. */
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+! WCHAR szShellTitle[512];
+!
+! if (GetConsoleTitleW(szShellTitle,
+! sizeof(szShellTitle)/sizeof(WCHAR) - 4) > 0)
+ {
+! if (cmd == NULL)
+! wcscat(szShellTitle, L" :sh");
+! else
+! {
+! WCHAR *wn = enc_to_utf16((char_u *)cmd, NULL);
+
+! if (wn != NULL)
+! {
+! wcscat(szShellTitle, L" - !");
+! if ((wcslen(szShellTitle) + wcslen(wn) <
+! sizeof(szShellTitle)/sizeof(WCHAR)))
+! wcscat(szShellTitle, wn);
+! SetConsoleTitleW(szShellTitle);
+! vim_free(wn);
+! did_set_title = TRUE;
+! }
+! }
+! }
+! }
+! if (!did_set_title)
+! /* Change the title to reflect that we are in a subshell. */
+! if (GetConsoleTitle(szShellTitle, sizeof(szShellTitle) - 4) > 0)
+! {
+! if (cmd == NULL)
+! strcat(szShellTitle, " :sh");
+! else
+ {
+! strcat(szShellTitle, " - !");
+! if ((strlen(szShellTitle) + strlen((char *)cmd)
+! < sizeof(szShellTitle)))
+! strcat(szShellTitle, (char *)cmd);
+ }
+- SetConsoleTitle(szShellTitle);
+ }
+ #endif
+
+ out_flush();
+--- 4491,4519 ----
+ int x = 0;
+ int tmode = cur_tmode;
+ #ifdef FEAT_TITLE
+! WCHAR szShellTitle[512];
+
+ /* Change the title to reflect that we are in a subshell. */
+! if (GetConsoleTitleW(szShellTitle,
+! sizeof(szShellTitle)/sizeof(WCHAR) - 4) > 0)
+ {
+! if (cmd == NULL)
+! wcscat(szShellTitle, L" :sh");
+! else
+ {
+! WCHAR *wn = enc_to_utf16((char_u *)cmd, NULL);
+
+! if (wn != NULL)
+ {
+! wcscat(szShellTitle, L" - !");
+! if ((wcslen(szShellTitle) + wcslen(wn) <
+! sizeof(szShellTitle)/sizeof(WCHAR)))
+! wcscat(szShellTitle, wn);
+! SetConsoleTitleW(szShellTitle);
+! vim_free(wn);
+ }
+ }
++ }
+ #endif
+
+ out_flush();
+***************
+*** 4936,4953 ****
+ "External commands will not pause after completion.\n"
+ "See :help win32-vimrun for more information.");
+ char *title = _("Vim Warning");
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *wmsg = enc_to_utf16((char_u *)msg, NULL);
+! WCHAR *wtitle = enc_to_utf16((char_u *)title, NULL);
+
+! if (wmsg != NULL && wtitle != NULL)
+! MessageBoxW(NULL, wmsg, wtitle, MB_ICONWARNING);
+! vim_free(wmsg);
+! vim_free(wtitle);
+! }
+! else
+! MessageBox(NULL, msg, title, MB_ICONWARNING);
+ need_vimrun_warning = FALSE;
+ }
+ if (!s_dont_use_vimrun && p_stmp)
+--- 4713,4725 ----
+ "External commands will not pause after completion.\n"
+ "See :help win32-vimrun for more information.");
+ char *title = _("Vim Warning");
+! WCHAR *wmsg = enc_to_utf16((char_u *)msg, NULL);
+! WCHAR *wtitle = enc_to_utf16((char_u *)title, NULL);
+
+! if (wmsg != NULL && wtitle != NULL)
+! MessageBoxW(NULL, wmsg, wtitle, MB_ICONWARNING);
+! vim_free(wmsg);
+! vim_free(wtitle);
+ need_vimrun_warning = FALSE;
+ }
+ if (!s_dont_use_vimrun && p_stmp)
+***************
+*** 5011,5033 ****
+ DWORD dwFlagsAndAttributes)
+ {
+ HANDLE h;
+! WCHAR *wn = NULL;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! wn = enc_to_utf16(fname, NULL);
+! if (wn != NULL)
+! {
+! h = CreateFileW(wn, dwDesiredAccess, dwShareMode,
+! lpSecurityAttributes, dwCreationDisposition,
+! dwFlagsAndAttributes, NULL);
+! vim_free(wn);
+! }
+! }
+ if (wn == NULL)
+! h = CreateFile((LPCSTR)fname, dwDesiredAccess, dwShareMode,
+! lpSecurityAttributes, dwCreationDisposition,
+! dwFlagsAndAttributes, NULL);
+ return h;
+ }
+
+--- 4783,4798 ----
+ DWORD dwFlagsAndAttributes)
+ {
+ HANDLE h;
+! WCHAR *wn;
+
+! wn = enc_to_utf16(fname, NULL);
+ if (wn == NULL)
+! return INVALID_HANDLE_VALUE;
+!
+! h = CreateFileW(wn, dwDesiredAccess, dwShareMode,
+! lpSecurityAttributes, dwCreationDisposition,
+! dwFlagsAndAttributes, NULL);
+! vim_free(wn);
+ return h;
+ }
+
+***************
+*** 6085,6165 ****
+ char_u *pchBuf,
+ DWORD cbToWrite)
+ {
+! COORD coord = g_coord;
+! DWORD written;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+! static WCHAR *unicodebuf = NULL;
+! static int unibuflen = 0;
+! int length;
+! DWORD n, cchwritten, cells;
+!
+! length = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pchBuf, cbToWrite, 0, 0);
+! if (unicodebuf == NULL || length > unibuflen)
+! {
+! vim_free(unicodebuf);
+! unicodebuf = (WCHAR *)lalloc(length * sizeof(WCHAR), FALSE);
+! unibuflen = length;
+! }
+! MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pchBuf, cbToWrite,
+! unicodebuf, unibuflen);
+!
+! cells = mb_string2cells(pchBuf, cbToWrite);
+!
+! if (!USE_VTP)
+! {
+! FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cells,
+! coord, &written);
+! /* When writing fails or didn't write a single character, pretend one
+! * character was written, otherwise we get stuck. */
+! if (WriteConsoleOutputCharacterW(g_hConOut, unicodebuf, length,
+! coord, &cchwritten) == 0
+! || cchwritten == 0 || cchwritten == (DWORD)-1)
+! cchwritten = 1;
+! }
+! else
+! {
+! if (WriteConsoleW(g_hConOut, unicodebuf, length, &cchwritten,
+ NULL) == 0 || cchwritten == 0)
+! cchwritten = 1;
+! }
+
+! if (cchwritten == length)
+! {
+! written = cbToWrite;
+! g_coord.X += (SHORT)cells;
+! }
+! else
+! {
+! char_u *p = pchBuf;
+! for (n = 0; n < cchwritten; n++)
+! MB_CPTR_ADV(p);
+! written = p - pchBuf;
+! g_coord.X += (SHORT)mb_string2cells(pchBuf, written);
+! }
+ }
+ else
+ {
+! if (!USE_VTP)
+! {
+! FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cbToWrite,
+! coord, &written);
+! /* When writing fails or didn't write a single character, pretend one
+! * character was written, otherwise we get stuck. */
+! if (WriteConsoleOutputCharacter(g_hConOut, (LPCSTR)pchBuf, cbToWrite,
+! coord, &written) == 0
+! || written == 0 || written == (DWORD)-1)
+! written = 1;
+! }
+! else
+! {
+! if (WriteConsole(g_hConOut, (LPCSTR)pchBuf, cbToWrite, &written,
+! NULL) == 0 || written == 0)
+! written = 1;
+! }
+!
+! g_coord.X += (SHORT) written;
+ }
+
+ while (g_coord.X > g_srScrollRegion.Right)
+--- 5850,5905 ----
+ char_u *pchBuf,
+ DWORD cbToWrite)
+ {
+! COORD coord = g_coord;
+! DWORD written;
+! DWORD n, cchwritten, cells;
+! static WCHAR *unicodebuf = NULL;
+! static int unibuflen = 0;
+! int length;
+! int cp = enc_utf8 ? CP_UTF8 : enc_codepage;
+!
+! length = MultiByteToWideChar(cp, 0, (LPCSTR)pchBuf, cbToWrite, 0, 0);
+! if (unicodebuf == NULL || length > unibuflen)
+! {
+! vim_free(unicodebuf);
+! unicodebuf = (WCHAR *)lalloc(length * sizeof(WCHAR), FALSE);
+! unibuflen = length;
+! }
+! MultiByteToWideChar(cp, 0, (LPCSTR)pchBuf, cbToWrite,
+! unicodebuf, unibuflen);
+!
+! cells = mb_string2cells(pchBuf, cbToWrite);
+
+! if (!USE_VTP)
+ {
+! FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cells,
+! coord, &written);
+! // When writing fails or didn't write a single character, pretend one
+! // character was written, otherwise we get stuck.
+! if (WriteConsoleOutputCharacterW(g_hConOut, unicodebuf, length,
+! coord, &cchwritten) == 0
+! || cchwritten == 0 || cchwritten == (DWORD)-1)
+! cchwritten = 1;
+! }
+! else
+! {
+! if (WriteConsoleW(g_hConOut, unicodebuf, length, &cchwritten,
+ NULL) == 0 || cchwritten == 0)
+! cchwritten = 1;
+! }
+
+! if (cchwritten == length)
+! {
+! written = cbToWrite;
+! g_coord.X += (SHORT)cells;
+ }
+ else
+ {
+! char_u *p = pchBuf;
+! for (n = 0; n < cchwritten; n++)
+! MB_CPTR_ADV(p);
+! written = p - pchBuf;
+! g_coord.X += (SHORT)mb_string2cells(pchBuf, written);
+ }
+
+ while (g_coord.X > g_srScrollRegion.Right)
+***************
+*** 6518,6524 ****
+ int
+ mch_remove(char_u *name)
+ {
+! WCHAR *wn = NULL;
+ int n;
+
+ /*
+--- 6258,6264 ----
+ int
+ mch_remove(char_u *name)
+ {
+! WCHAR *wn;
+ int n;
+
+ /*
+***************
+*** 6530,6546 ****
+
+ win32_setattrs(name, FILE_ATTRIBUTE_NORMAL);
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! wn = enc_to_utf16(name, NULL);
+! if (wn != NULL)
+! {
+! n = DeleteFileW(wn) ? 0 : -1;
+! vim_free(wn);
+! return n;
+! }
+! }
+! return DeleteFile((LPCSTR)name) ? 0 : -1;
+ }
+
+
+--- 6270,6282 ----
+
+ win32_setattrs(name, FILE_ATTRIBUTE_NORMAL);
+
+! wn = enc_to_utf16(name, NULL);
+! if (wn == NULL)
+! return -1;
+!
+! n = DeleteFileW(wn) ? 0 : -1;
+! vim_free(wn);
+! return n;
+ }
+
+
+***************
+*** 6590,6597 ****
+ }
+
+ /*
+! * Same code as below, but with wide functions and no comments.
+! * Return 0 for success, non-zero for failure.
+ */
+ int
+ mch_wrename(WCHAR *wold, WCHAR *wnew)
+--- 6326,6348 ----
+ }
+
+ /*
+! * mch_wrename() works around a bug in rename (aka MoveFile) in
+! * Windows 95: rename("foo.bar", "foo.bar~") will generate a
+! * file whose short file name is "FOO.BAR" (its long file name will
+! * be correct: "foo.bar~"). Because a file can be accessed by
+! * either its SFN or its LFN, "foo.bar" has effectively been
+! * renamed to "foo.bar", which is not at all what was wanted. This
+! * seems to happen only when renaming files with three-character
+! * extensions by appending a suffix that does not include ".".
+! * Windows NT gets it right, however, with an SFN of "FOO~1.BAR".
+! *
+! * There is another problem, which isn't really a bug but isn't right either:
+! * When renaming "abcdef~1.txt" to "abcdef~1.txt~", the short name can be
+! * "abcdef~1.txt" again. This has been reported on Windows NT 4.0 with
+! * service pack 6. Doesn't seem to happen on Windows 98.
+! *
+! * Like rename(), returns 0 upon success, non-zero upon failure.
+! * Should probably set errno appropriately when errors occur.
+ */
+ int
+ mch_wrename(WCHAR *wold, WCHAR *wnew)
+***************
+*** 6602,6607 ****
+--- 6353,6360 ----
+ WCHAR szNewPath[_MAX_PATH + 1];
+ HANDLE hf;
+
++ // No need to play tricks unless the file name contains a "~" as the
++ // seventh character.
+ p = wold;
+ for (i = 0; wold[i] != NUL; ++i)
+ if ((wold[i] == '/' || wold[i] == '\\' || wold[i] == ':')
+***************
+*** 6610,6642 ****
+--- 6363,6414 ----
+ if ((int)(wold + i - p) < 8 || p[6] != '~')
+ return (MoveFileW(wold, wnew) == 0);
+
++ // Get base path of new file name. Undocumented feature: If pszNewFile is
++ // a directory, no error is returned and pszFilePart will be NULL.
+ if (GetFullPathNameW(wnew, _MAX_PATH, szNewPath, &p) == 0 || p == NULL)
+ return -1;
+ *p = NUL;
+
++ // Get (and create) a unique temporary file name in directory of new file
+ if (GetTempFileNameW(szNewPath, L"VIM", 0, szTempFile) == 0)
+ return -2;
+
++ // blow the temp file away
+ if (!DeleteFileW(szTempFile))
+ return -3;
+
++ // rename old file to the temp file
+ if (!MoveFileW(wold, szTempFile))
+ return -4;
+
++ // now create an empty file called pszOldFile; this prevents the operating
++ // system using pszOldFile as an alias (SFN) if we're renaming within the
++ // same directory. For example, we're editing a file called
++ // filename.asc.txt by its SFN, filena~1.txt. If we rename filena~1.txt
++ // to filena~1.txt~ (i.e., we're making a backup while writing it), the
++ // SFN for filena~1.txt~ will be filena~1.txt, by default, which will
++ // cause all sorts of problems later in buf_write(). So, we create an
++ // empty file called filena~1.txt and the system will have to find some
++ // other SFN for filena~1.txt~, such as filena~2.txt
+ if ((hf = CreateFileW(wold, GENERIC_WRITE, 0, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
+ return -5;
+ if (!CloseHandle(hf))
+ return -6;
+
++ // rename the temp file to the new file
+ if (!MoveFileW(szTempFile, wnew))
+ {
++ // Renaming failed. Rename the file back to its old name, so that it
++ // looks like nothing happened.
+ (void)MoveFileW(szTempFile, wold);
+ return -7;
+ }
+
++ // Seems to be left around on Novell filesystems
+ DeleteFileW(szTempFile);
+
++ // finally, remove the empty old file
+ if (!DeleteFileW(wold))
+ return -8;
+
+***************
+*** 6645,6753 ****
+
+
+ /*
+! * mch_rename() works around a bug in rename (aka MoveFile) in
+! * Windows 95: rename("foo.bar", "foo.bar~") will generate a
+! * file whose short file name is "FOO.BAR" (its long file name will
+! * be correct: "foo.bar~"). Because a file can be accessed by
+! * either its SFN or its LFN, "foo.bar" has effectively been
+! * renamed to "foo.bar", which is not at all what was wanted. This
+! * seems to happen only when renaming files with three-character
+! * extensions by appending a suffix that does not include ".".
+! * Windows NT gets it right, however, with an SFN of "FOO~1.BAR".
+! *
+! * There is another problem, which isn't really a bug but isn't right either:
+! * When renaming "abcdef~1.txt" to "abcdef~1.txt~", the short name can be
+! * "abcdef~1.txt" again. This has been reported on Windows NT 4.0 with
+! * service pack 6. Doesn't seem to happen on Windows 98.
+! *
+ * Like rename(), returns 0 upon success, non-zero upon failure.
+- * Should probably set errno appropriately when errors occur.
+ */
+ int
+ mch_rename(
+ const char *pszOldFile,
+ const char *pszNewFile)
+ {
+- char szTempFile[_MAX_PATH+1];
+- char szNewPath[_MAX_PATH+1];
+- char *pszFilePart;
+- HANDLE hf;
+ WCHAR *wold = NULL;
+ WCHAR *wnew = NULL;
+ int retval = -1;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! wold = enc_to_utf16((char_u *)pszOldFile, NULL);
+! wnew = enc_to_utf16((char_u *)pszNewFile, NULL);
+! if (wold != NULL && wnew != NULL)
+! retval = mch_wrename(wold, wnew);
+! vim_free(wold);
+! vim_free(wnew);
+! return retval;
+! }
+!
+! /*
+! * No need to play tricks unless the file name contains a "~" as the
+! * seventh character.
+! */
+! pszFilePart = (char *)gettail((char_u *)pszOldFile);
+! if (STRLEN(pszFilePart) < 8 || pszFilePart[6] != '~')
+! return rename(pszOldFile, pszNewFile);
+!
+! /* Get base path of new file name. Undocumented feature: If pszNewFile is
+! * a directory, no error is returned and pszFilePart will be NULL. */
+! if (GetFullPathName(pszNewFile, _MAX_PATH, szNewPath, &pszFilePart) == 0
+! || pszFilePart == NULL)
+! return -1;
+! *pszFilePart = NUL;
+!
+! /* Get (and create) a unique temporary file name in directory of new file */
+! if (GetTempFileName(szNewPath, "VIM", 0, szTempFile) == 0)
+! return -2;
+!
+! /* blow the temp file away */
+! if (!DeleteFile(szTempFile))
+! return -3;
+!
+! /* rename old file to the temp file */
+! if (!MoveFile(pszOldFile, szTempFile))
+! return -4;
+!
+! /* now create an empty file called pszOldFile; this prevents the operating
+! * system using pszOldFile as an alias (SFN) if we're renaming within the
+! * same directory. For example, we're editing a file called
+! * filename.asc.txt by its SFN, filena~1.txt. If we rename filena~1.txt
+! * to filena~1.txt~ (i.e., we're making a backup while writing it), the
+! * SFN for filena~1.txt~ will be filena~1.txt, by default, which will
+! * cause all sorts of problems later in buf_write(). So, we create an
+! * empty file called filena~1.txt and the system will have to find some
+! * other SFN for filena~1.txt~, such as filena~2.txt
+! */
+! if ((hf = CreateFile(pszOldFile, GENERIC_WRITE, 0, NULL, CREATE_NEW,
+! FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
+! return -5;
+! if (!CloseHandle(hf))
+! return -6;
+!
+! /* rename the temp file to the new file */
+! if (!MoveFile(szTempFile, pszNewFile))
+! {
+! /* Renaming failed. Rename the file back to its old name, so that it
+! * looks like nothing happened. */
+! (void)MoveFile(szTempFile, pszOldFile);
+!
+! return -7;
+! }
+!
+! /* Seems to be left around on Novell filesystems */
+! DeleteFile(szTempFile);
+!
+! /* finally, remove the empty old file */
+! if (!DeleteFile(pszOldFile))
+! return -8;
+!
+! return 0; /* success */
+ }
+
+ /*
+--- 6417,6441 ----
+
+
+ /*
+! * Converts the filenames to UTF-16, then call mch_wrename().
+ * Like rename(), returns 0 upon success, non-zero upon failure.
+ */
+ int
+ mch_rename(
+ const char *pszOldFile,
+ const char *pszNewFile)
+ {
+ WCHAR *wold = NULL;
+ WCHAR *wnew = NULL;
+ int retval = -1;
+
+! wold = enc_to_utf16((char_u *)pszOldFile, NULL);
+! wnew = enc_to_utf16((char_u *)pszNewFile, NULL);
+! if (wold != NULL && wnew != NULL)
+! retval = mch_wrename(wold, wnew);
+! vim_free(wold);
+! vim_free(wnew);
+! return retval;
+ }
+
+ /*
+***************
+*** 6768,6822 ****
+ {
+ HANDLE hFile;
+ int retval = -1; /* default: fail */
+! WCHAR *wn = NULL;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! wn = enc_to_utf16((char_u *)n, NULL);
+
+ if (mch_isdir((char_u *)n))
+ {
+- char TempName[_MAX_PATH + 16] = "";
+ WCHAR TempNameW[_MAX_PATH + 16] = L"";
+
+ if (p & R_OK)
+ {
+ /* Read check is performed by seeing if we can do a find file on
+ * the directory for any file. */
+! if (wn != NULL)
+! {
+! int i;
+! WIN32_FIND_DATAW d;
+
+! for (i = 0; i < _MAX_PATH && wn[i] != 0; ++i)
+! TempNameW[i] = wn[i];
+! if (TempNameW[i - 1] != '\\' && TempNameW[i - 1] != '/')
+! TempNameW[i++] = '\\';
+! TempNameW[i++] = '*';
+! TempNameW[i++] = 0;
+!
+! hFile = FindFirstFileW(TempNameW, &d);
+! if (hFile == INVALID_HANDLE_VALUE)
+! goto getout;
+! else
+! (void)FindClose(hFile);
+! }
+ else
+- {
+- char *pch;
+- WIN32_FIND_DATA d;
+-
+- vim_strncpy((char_u *)TempName, (char_u *)n, _MAX_PATH);
+- pch = TempName + STRLEN(TempName) - 1;
+- if (*pch != '\\' && *pch != '/')
+- *++pch = '\\';
+- *++pch = '*';
+- *++pch = NUL;
+-
+- hFile = FindFirstFile(TempName, &d);
+- if (hFile == INVALID_HANDLE_VALUE)
+- goto getout;
+ (void)FindClose(hFile);
+- }
+ }
+
+ if (p & W_OK)
+--- 6456,6490 ----
+ {
+ HANDLE hFile;
+ int retval = -1; /* default: fail */
+! WCHAR *wn;
+
+! wn = enc_to_utf16((char_u *)n, NULL);
+! if (wn == NULL)
+! return -1;
+
+ if (mch_isdir((char_u *)n))
+ {
+ WCHAR TempNameW[_MAX_PATH + 16] = L"";
+
+ if (p & R_OK)
+ {
+ /* Read check is performed by seeing if we can do a find file on
+ * the directory for any file. */
+! int i;
+! WIN32_FIND_DATAW d;
+
+! for (i = 0; i < _MAX_PATH && wn[i] != 0; ++i)
+! TempNameW[i] = wn[i];
+! if (TempNameW[i - 1] != '\\' && TempNameW[i - 1] != '/')
+! TempNameW[i++] = '\\';
+! TempNameW[i++] = '*';
+! TempNameW[i++] = 0;
+!
+! hFile = FindFirstFileW(TempNameW, &d);
+! if (hFile == INVALID_HANDLE_VALUE)
+! goto getout;
+ else
+ (void)FindClose(hFile);
+ }
+
+ if (p & W_OK)
+***************
+*** 6825,6843 ****
+ * directories on read-only network shares. However, in
+ * directories whose ACL allows writes but denies deletes will end
+ * up keeping the temporary file :-(. */
+! if (wn != NULL)
+! {
+! if (!GetTempFileNameW(wn, L"VIM", 0, TempNameW))
+! goto getout;
+! else
+! DeleteFileW(TempNameW);
+! }
+ else
+! {
+! if (!GetTempFileName(n, "VIM", 0, TempName))
+! goto getout;
+! mch_remove((char_u *)TempName);
+! }
+ }
+ }
+ else
+--- 6493,6502 ----
+ * directories on read-only network shares. However, in
+ * directories whose ACL allows writes but denies deletes will end
+ * up keeping the temporary file :-(. */
+! if (!GetTempFileNameW(wn, L"VIM", 0, TempNameW))
+! goto getout;
+ else
+! DeleteFileW(TempNameW);
+ }
+ }
+ else
+***************
+*** 6850,6861 ****
+ DWORD access_mode = ((p & W_OK) ? GENERIC_WRITE : 0)
+ | ((p & R_OK) ? GENERIC_READ : 0);
+
+! if (wn != NULL)
+! hFile = CreateFileW(wn, access_mode, share_mode,
+! NULL, OPEN_EXISTING, 0, NULL);
+! else
+! hFile = CreateFile(n, access_mode, share_mode,
+! NULL, OPEN_EXISTING, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ goto getout;
+ CloseHandle(hFile);
+--- 6509,6516 ----
+ DWORD access_mode = ((p & W_OK) ? GENERIC_WRITE : 0)
+ | ((p & R_OK) ? GENERIC_READ : 0);
+
+! hFile = CreateFileW(wn, access_mode, share_mode,
+! NULL, OPEN_EXISTING, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ goto getout;
+ CloseHandle(hFile);
+***************
+*** 6878,6895 ****
+ WCHAR *wn;
+ int f;
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! wn = enc_to_utf16((char_u *)name, NULL);
+! if (wn != NULL)
+! {
+! f = _wopen(wn, flags, mode);
+! vim_free(wn);
+! return f;
+! }
+! }
+! #endif
+
+ /* open() can open a file which name is longer than _MAX_PATH bytes
+ * and shorter than _MAX_PATH characters successfully, but sometimes it
+ * causes unexpected error in another part. We make it an error explicitly
+--- 6533,6546 ----
+ WCHAR *wn;
+ int f;
+
+! wn = enc_to_utf16((char_u *)name, NULL);
+! if (wn == NULL)
+! return -1;
+
++ f = _wopen(wn, flags, mode);
++ vim_free(wn);
++ return f;
++ #else
+ /* open() can open a file which name is longer than _MAX_PATH bytes
+ * and shorter than _MAX_PATH characters successfully, but sometimes it
+ * causes unexpected error in another part. We make it an error explicitly
+***************
+*** 6898,6907 ****
+ return -1;
+
+ return open(name, flags, mode);
+ }
+
+ /*
+! * Version of fopen() that may use UTF-16 file name.
+ */
+ FILE *
+ mch_fopen(const char *name, const char *mode)
+--- 6549,6559 ----
+ return -1;
+
+ return open(name, flags, mode);
++ #endif
+ }
+
+ /*
+! * Version of fopen() that uses UTF-16 file name.
+ */
+ FILE *
+ mch_fopen(const char *name, const char *mode)
+***************
+*** 6909,6949 ****
+ WCHAR *wn, *wm;
+ FILE *f = NULL;
+
+- if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+- {
+ #if defined(DEBUG) && _MSC_VER >= 1400
+! /* Work around an annoying assertion in the Microsoft debug CRT
+! * when mode's text/binary setting doesn't match _get_fmode(). */
+! char newMode = mode[strlen(mode) - 1];
+! int oldMode = 0;
+!
+! _get_fmode(&oldMode);
+! if (newMode == 't')
+! _set_fmode(_O_TEXT);
+! else if (newMode == 'b')
+! _set_fmode(_O_BINARY);
+! #endif
+! wn = enc_to_utf16((char_u *)name, NULL);
+! wm = enc_to_utf16((char_u *)mode, NULL);
+! if (wn != NULL && wm != NULL)
+! f = _wfopen(wn, wm);
+! vim_free(wn);
+! vim_free(wm);
+
+ #if defined(DEBUG) && _MSC_VER >= 1400
+! _set_fmode(oldMode);
+ #endif
+! return f;
+! }
+!
+! /* fopen() can open a file which name is longer than _MAX_PATH bytes
+! * and shorter than _MAX_PATH characters successfully, but sometimes it
+! * causes unexpected error in another part. We make it an error explicitly
+! * here. */
+! if (strlen(name) >= _MAX_PATH)
+! return NULL;
+!
+! return fopen(name, mode);
+ }
+
+ /*
+--- 6561,6589 ----
+ WCHAR *wn, *wm;
+ FILE *f = NULL;
+
+ #if defined(DEBUG) && _MSC_VER >= 1400
+! /* Work around an annoying assertion in the Microsoft debug CRT
+! * when mode's text/binary setting doesn't match _get_fmode(). */
+! char newMode = mode[strlen(mode) - 1];
+! int oldMode = 0;
+!
+! _get_fmode(&oldMode);
+! if (newMode == 't')
+! _set_fmode(_O_TEXT);
+! else if (newMode == 'b')
+! _set_fmode(_O_BINARY);
+! #endif
+! wn = enc_to_utf16((char_u *)name, NULL);
+! wm = enc_to_utf16((char_u *)mode, NULL);
+! if (wn != NULL && wm != NULL)
+! f = _wfopen(wn, wm);
+! vim_free(wn);
+! vim_free(wm);
+
+ #if defined(DEBUG) && _MSC_VER >= 1400
+! _set_fmode(oldMode);
+ #endif
+! return f;
+ }
+
+ /*
+***************
+*** 7418,7423 ****
+--- 7058,7064 ----
+ mch_setenv(char *var, char *value, int x)
+ {
+ char_u *envbuf;
++ WCHAR *p;
+
+ envbuf = alloc((unsigned)(STRLEN(var) + STRLEN(value) + 2));
+ if (envbuf == NULL)
+***************
+*** 7425,7453 ****
+
+ sprintf((char *)envbuf, "%s=%s", var, value);
+
+! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+! {
+! WCHAR *p = enc_to_utf16(envbuf, NULL);
+
+! vim_free(envbuf);
+! if (p == NULL)
+! return -1;
+! _wputenv(p);
+ #ifdef libintl_wputenv
+! libintl_wputenv(p);
+ #endif
+! /* Unlike Un*x systems, we can free the string for _wputenv(). */
+! vim_free(p);
+! }
+! else
+! {
+! _putenv((char *)envbuf);
+! #ifdef libintl_putenv
+! libintl_putenv((char *)envbuf);
+! #endif
+! /* Unlike Un*x systems, we can free the string for _putenv(). */
+! vim_free(envbuf);
+! }
+
+ return 0;
+ }
+--- 7066,7082 ----
+
+ sprintf((char *)envbuf, "%s=%s", var, value);
+
+! p = enc_to_utf16(envbuf, NULL);
+
+! vim_free(envbuf);
+! if (p == NULL)
+! return -1;
+! _wputenv(p);
+ #ifdef libintl_wputenv
+! libintl_wputenv(p);
+ #endif
+! // Unlike Un*x systems, we can free the string for _wputenv().
+! vim_free(p);
+
+ return 0;
+ }
+*** ../vim-8.1.1102/src/vim.h 2019-02-19 21:24:50.559543423 +0100
+--- src/vim.h 2019-04-02 22:04:17.789655489 +0200
+***************
+*** 536,542 ****
+ extern char *(*dyn_libintl_bindtextdomain)(const char *domainname, const char *dirname);
+ extern char *(*dyn_libintl_bind_textdomain_codeset)(const char *domainname, const char *codeset);
+ extern char *(*dyn_libintl_textdomain)(const char *domainname);
+! extern int (*dyn_libintl_putenv)(const char *envstring);
+ #endif
+
+
+--- 536,542 ----
+ extern char *(*dyn_libintl_bindtextdomain)(const char *domainname, const char *dirname);
+ extern char *(*dyn_libintl_bind_textdomain_codeset)(const char *domainname, const char *codeset);
+ extern char *(*dyn_libintl_textdomain)(const char *domainname);
+! extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
+ #endif
+
+
+***************
+*** 559,565 ****
+ # define HAVE_BIND_TEXTDOMAIN_CODESET 1
+ # endif
+ # define textdomain(domain) (*dyn_libintl_textdomain)(domain)
+- # define libintl_putenv(envstring) (*dyn_libintl_putenv)(envstring)
+ # define libintl_wputenv(envstring) (*dyn_libintl_wputenv)(envstring)
+ # else
+ # include <libintl.h>
+--- 559,564 ----
+*** ../vim-8.1.1102/src/version.c 2019-04-02 22:02:28.606347252 +0200
+--- src/version.c 2019-04-02 22:05:50.325066421 +0200
+***************
+*** 773,774 ****
+--- 773,776 ----
+ { /* Add new patch number below this line */
++ /**/
++ 1103,
+ /**/
+
+--
+hundred-and-one symptoms of being an internet addict:
+183. You move your coffeemaker next to your computer.
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
+/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
+\\\ an exciting new programming language -- http://www.Zimbu.org ///
+ \\\ help me help AIDS victims -- http://ICCF-Holland.org ///