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:
171
src/gui_w32.c
171
src/gui_w32.c
@@ -4367,14 +4367,14 @@ typedef struct _DllVersionInfo
|
|||||||
|
|
||||||
typedef struct tagTOOLINFOA_NEW
|
typedef struct tagTOOLINFOA_NEW
|
||||||
{
|
{
|
||||||
UINT cbSize;
|
UINT cbSize;
|
||||||
UINT uFlags;
|
UINT uFlags;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
UINT_PTR uId;
|
UINT_PTR uId;
|
||||||
RECT rect;
|
RECT rect;
|
||||||
HINSTANCE hinst;
|
HINSTANCE hinst;
|
||||||
LPSTR lpszText;
|
LPSTR lpszText;
|
||||||
LPARAM lParam;
|
LPARAM lParam;
|
||||||
} TOOLINFO_NEW;
|
} TOOLINFO_NEW;
|
||||||
|
|
||||||
typedef struct tagNMTTDISPINFO_NEW
|
typedef struct tagNMTTDISPINFO_NEW
|
||||||
@@ -4387,6 +4387,32 @@ typedef struct tagNMTTDISPINFO_NEW
|
|||||||
LPARAM lParam;
|
LPARAM lParam;
|
||||||
} NMTTDISPINFO_NEW;
|
} 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 *);
|
typedef HRESULT (WINAPI* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
|
||||||
#ifndef TTM_SETMAXTIPWIDTH
|
#ifndef TTM_SETMAXTIPWIDTH
|
||||||
# define TTM_SETMAXTIPWIDTH (WM_USER+24)
|
# define TTM_SETMAXTIPWIDTH (WM_USER+24)
|
||||||
@@ -5502,6 +5528,15 @@ gui_mch_init(void)
|
|||||||
if (RegisterClassW(&wndclassw) == 0)
|
if (RegisterClassW(&wndclassw) == 0)
|
||||||
return FAIL;
|
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
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -5520,15 +5555,16 @@ gui_mch_init(void)
|
|||||||
|
|
||||||
if (RegisterClass(&wndclass) == 0)
|
if (RegisterClass(&wndclass) == 0)
|
||||||
return FAIL;
|
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)
|
if (s_textArea == NULL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -6218,9 +6254,9 @@ RevOut( HDC s_hdc,
|
|||||||
static void
|
static void
|
||||||
draw_line(
|
draw_line(
|
||||||
int x1,
|
int x1,
|
||||||
int y1,
|
int y1,
|
||||||
int x2,
|
int x2,
|
||||||
int y2,
|
int y2,
|
||||||
COLORREF color)
|
COLORREF color)
|
||||||
{
|
{
|
||||||
#if defined(FEAT_DIRECTX)
|
#if defined(FEAT_DIRECTX)
|
||||||
@@ -6241,7 +6277,7 @@ draw_line(
|
|||||||
static void
|
static void
|
||||||
set_pixel(
|
set_pixel(
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
COLORREF color)
|
COLORREF color)
|
||||||
{
|
{
|
||||||
#if defined(FEAT_DIRECTX)
|
#if defined(FEAT_DIRECTX)
|
||||||
@@ -6255,7 +6291,7 @@ set_pixel(
|
|||||||
static void
|
static void
|
||||||
fill_rect(
|
fill_rect(
|
||||||
const RECT *rcp,
|
const RECT *rcp,
|
||||||
HBRUSH hbr,
|
HBRUSH hbr,
|
||||||
COLORREF color)
|
COLORREF color)
|
||||||
{
|
{
|
||||||
#if defined(FEAT_DIRECTX)
|
#if defined(FEAT_DIRECTX)
|
||||||
@@ -8745,12 +8781,95 @@ multiline_balloon_available(void)
|
|||||||
return multiline_tip;
|
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
|
static void
|
||||||
make_tooltip(BalloonEval *beval, char *text, POINT pt)
|
make_tooltip(BalloonEval *beval, char *text, POINT pt)
|
||||||
{
|
{
|
||||||
TOOLINFO *pti;
|
TOOLINFO *pti;
|
||||||
int ToolInfoSize;
|
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)
|
if (multiline_balloon_available() == TRUE)
|
||||||
ToolInfoSize = sizeof(TOOLINFO_NEW);
|
ToolInfoSize = sizeof(TOOLINFO_NEW);
|
||||||
else
|
else
|
||||||
@@ -8961,6 +9080,16 @@ Handle_WM_Notify(HWND hwnd UNUSED, LPNMHDR pnmh)
|
|||||||
info->uFlags |= TTF_DI_SETITEM;
|
info->uFlags |= TTF_DI_SETITEM;
|
||||||
}
|
}
|
||||||
break;
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -799,6 +799,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
647,
|
||||||
/**/
|
/**/
|
||||||
646,
|
646,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user