0
0
mirror of https://github.com/vim/vim.git synced 2025-10-05 05:34:07 -04:00

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 #3708)
This commit is contained in:
Bram Moolenaar
2018-12-27 22:43:08 +01:00
parent b09c684195
commit d385b5d329
2 changed files with 152 additions and 21 deletions

View File

@@ -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, LPNMHDR pnmh)
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
}
}
}

View File

@@ -799,6 +799,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
647,
/**/
646,
/**/