# HG changeset patch # User Bram Moolenaar # Date 1545947107 -3600 # Node ID 71b762af30c386da53feec703fdccdc4ef95847e # Parent 2979ce4f34511b03351dc4d7cbcb84b7d1bff104 patch 8.1.0647: MS-Windows: balloon_show() does not handle wide characters commit https://github.com/vim/vim/commit/d385b5d329a6a98539fa21cfb60ed632cd03d544 Author: Bram Moolenaar Date: Thu Dec 27 22:43:08 2018 +0100 patch 8.1.0647: MS-Windows: balloon_show() does not handle wide characters Problem: MS-Windows: balloon_show() does not handle wide characters. Solution: Use CreateWindowExW(). (Yasuhiro Matsumoto, closes https://github.com/vim/vim/issues/3708) diff --git a/src/gui_w32.c b/src/gui_w32.c --- a/src/gui_w32.c +++ b/src/gui_w32.c @@ -4367,14 +4367,14 @@ typedef struct _DllVersionInfo typedef struct tagTOOLINFOA_NEW { - UINT cbSize; - UINT uFlags; - HWND hwnd; - UINT_PTR uId; - RECT rect; - HINSTANCE hinst; - LPSTR lpszText; - LPARAM lParam; + UINT cbSize; + UINT uFlags; + HWND hwnd; + UINT_PTR uId; + RECT rect; + HINSTANCE hinst; + LPSTR lpszText; + LPARAM lParam; } TOOLINFO_NEW; typedef struct tagNMTTDISPINFO_NEW @@ -4387,6 +4387,32 @@ typedef struct tagNMTTDISPINFO_NEW LPARAM lParam; } NMTTDISPINFO_NEW; +#ifdef FEAT_MBYTE +typedef struct tagTOOLINFOW_NEW +{ + UINT cbSize; + UINT uFlags; + HWND hwnd; + UINT_PTR uId; + RECT rect; + HINSTANCE hinst; + LPWSTR lpszText; + LPARAM lParam; + void *lpReserved; +} TOOLINFOW_NEW; + +typedef struct tagNMTTDISPINFOW_NEW +{ + NMHDR hdr; + LPWSTR lpszText; + WCHAR szText[80]; + HINSTANCE hinst; + UINT uFlags; + LPARAM lParam; +} NMTTDISPINFOW_NEW; + +#endif + typedef HRESULT (WINAPI* DLLGETVERSIONPROC)(DLLVERSIONINFO *); #ifndef TTM_SETMAXTIPWIDTH # define TTM_SETMAXTIPWIDTH (WM_USER+24) @@ -5502,6 +5528,15 @@ gui_mch_init(void) 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 #endif @@ -5520,15 +5555,16 @@ gui_mch_init(void) 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); + + 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; @@ -6218,9 +6254,9 @@ RevOut( HDC s_hdc, static void draw_line( int x1, - int y1, - int x2, - int y2, + int y1, + int x2, + int y2, COLORREF color) { #if defined(FEAT_DIRECTX) @@ -6241,7 +6277,7 @@ draw_line( static void set_pixel( int x, - int y, + int y, COLORREF color) { #if defined(FEAT_DIRECTX) @@ -6255,7 +6291,7 @@ set_pixel( static void fill_rect( const RECT *rcp, - HBRUSH hbr, + HBRUSH hbr, COLORREF color) { #if defined(FEAT_DIRECTX) @@ -8745,12 +8781,95 @@ multiline_balloon_available(void) return multiline_tip; } +#ifdef FEAT_MBYTE + static void +make_tooltipw(BalloonEval *beval, char *text, POINT pt) +{ + TOOLINFOW *pti; + int ToolInfoSize; + WCHAR *tofree = NULL; + + if (multiline_balloon_available() == TRUE) + ToolInfoSize = sizeof(TOOLINFOW_NEW); + else + ToolInfoSize = sizeof(TOOLINFOW); + + pti = (TOOLINFOW *)alloc(ToolInfoSize); + if (pti == NULL) + return; + + beval->balloon = CreateWindowExW(WS_EX_TOPMOST, TOOLTIPS_CLASSW, + 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; + TOOLINFOW_NEW *ptin = (TOOLINFOW_NEW *)pti; + pti->lpszText = LPSTR_TEXTCALLBACKW; + tofree = enc_to_utf16((char_u*)text, NULL); + ptin->lParam = (LPARAM)tofree; + // switch multiline tooltips on + if (GetClientRect(s_textArea, &rect)) + SendMessageW(beval->balloon, TTM_SETMAXTIPWIDTH, 0, + (LPARAM)rect.right); + } + else + { + // do this old way + tofree = enc_to_utf16((char_u*)text, NULL); + pti->lpszText = tofree; + } + + // 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; + + SendMessageW(beval->balloon, TTM_ADDTOOLW, 0, (LPARAM)pti); + // Make tooltip appear sooner. + SendMessageW(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. + SendMessageW(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); + mouse_event(MOUSEEVENTF_MOVE, (DWORD)-1, (DWORD)-1, 0, 0); + vim_free(pti); + if (tofree != NULL) + vim_free(tofree); +} +#endif + static void make_tooltip(BalloonEval *beval, char *text, POINT pt) { TOOLINFO *pti; int ToolInfoSize; +#ifdef FEAT_MBYTE + if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { + make_tooltipw(beval, text, pt); + return; + } +#endif + if (multiline_balloon_available() == TRUE) ToolInfoSize = sizeof(TOOLINFO_NEW); else @@ -8961,6 +9080,16 @@ Handle_WM_Notify(HWND hwnd UNUSED, LPNMH info->uFlags |= TTF_DI_SETITEM; } break; +#ifdef FEAT_MBYTE + case TTN_GETDISPINFOW: + { + // if we get here then we have new common controls + NMTTDISPINFOW_NEW *info = (NMTTDISPINFOW_NEW *)pnmh; + info->lpszText = (LPWSTR)info->lParam; + info->uFlags |= TTF_DI_SETITEM; + } + break; +#endif } } } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -800,6 +800,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 647, +/**/ 646, /**/ 645,