[PATCH v6 2/6] shell32/autocomplete: Redesign the window proc to trigger on key presses instead of key release
Gabriel Ivăncescu
gabrielopcode at gmail.com
Fri Sep 14 06:00:32 CDT 2018
AutoComplete currently shows up when the user releases a key, which is
wrong. Windows does it when the user presses a key, so use both WM_KEYDOWN
and WM_CHAR and redesign it so that it matches Windows behavior.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
v6: Use an enum instead of BOOL for the autoappend flag.
dlls/shell32/autocomplete.c | 116 +++++++++++++++++++++++++-------------------
1 file changed, 66 insertions(+), 50 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index ebbb9ee..b9ec228 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -79,6 +79,13 @@ typedef struct
AUTOCOMPLETEOPTIONS options;
} IAutoCompleteImpl;
+enum autoappend_flag
+{
+ autoappend_flag_yes,
+ autoappend_flag_no,
+ autoappend_flag_displayempty
+};
+
static const WCHAR autocomplete_propertyW[] = {'W','i','n','e',' ','A','u','t','o',
'c','o','m','p','l','e','t','e',' ',
'c','o','n','t','r','o','l',0};
@@ -119,10 +126,25 @@ static size_t format_quick_complete(WCHAR *dst, const WCHAR *qc, const WCHAR *st
return dst - base;
}
-static void autocomplete_text(IAutoCompleteImpl *ac, WCHAR *text, UINT len, HWND hwnd, BOOL displayall)
+static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_flag flag)
{
HRESULT hr;
- UINT cpt;
+ WCHAR *text;
+ UINT cpt, size, len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
+
+ if (flag != autoappend_flag_displayempty && len == 0)
+ {
+ if (ac->options & ACO_AUTOSUGGEST)
+ ShowWindow(ac->hwndListBox, SW_HIDE);
+ return;
+ }
+
+ size = len + 1;
+ if (!(text = heap_alloc(size * sizeof(WCHAR))))
+ return;
+ len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)text);
+ if (len + 1 != size)
+ text = heap_realloc(text, (len + 1) * sizeof(WCHAR));
SendMessageW(ac->hwndListBox, LB_RESETCONTENT, 0, 0);
@@ -130,9 +152,6 @@ static void autocomplete_text(IAutoCompleteImpl *ac, WCHAR *text, UINT len, HWND
heap_free(ac->txtbackup);
ac->txtbackup = text;
- if (!displayall && !len)
- return;
-
IEnumString_Reset(ac->enumstr);
for(cpt = 0;;)
{
@@ -145,7 +164,7 @@ static void autocomplete_text(IAutoCompleteImpl *ac, WCHAR *text, UINT len, HWND
if (!strncmpiW(text, strs, len))
{
- if (cpt == 0 && (ac->options & ACO_AUTOAPPEND))
+ if (cpt == 0 && flag == autoappend_flag_yes)
{
WCHAR buffW[255];
@@ -200,27 +219,23 @@ static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
/*
Helper for ACEditSubclassProc
*/
-static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
+static LRESULT ACEditSubclassProc_KeyDown(IAutoCompleteImpl *ac, HWND hwnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
{
- WCHAR *text;
- UINT len, size;
- BOOL displayall = FALSE;
-
- len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
- size = len + 1;
- if (!(text = heap_alloc(size * sizeof(WCHAR))))
- return 0;
- len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)text);
-
switch(wParam)
{
case VK_RETURN:
/* If quickComplete is set and control is pressed, replace the string */
if (ac->quickComplete && (GetKeyState(VK_CONTROL) & 0x8000))
{
- WCHAR *buf;
- size_t sz = strlenW(ac->quickComplete) + 1 + len;
+ WCHAR *text, *buf;
+ size_t sz;
+ UINT len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
+ if (!(text = heap_alloc((len + 1) * sizeof(WCHAR))))
+ return 0;
+ len = SendMessageW(hwnd, WM_GETTEXT, len + 1, (LPARAM)text);
+ sz = strlenW(ac->quickComplete) + 1 + len;
+
if ((buf = heap_alloc(sz * sizeof(WCHAR))))
{
len = format_quick_complete(buf, ac->quickComplete, text, len);
@@ -228,16 +243,16 @@ static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT u
SendMessageW(hwnd, EM_SETSEL, 0, len);
heap_free(buf);
}
+
+ if (ac->options & ACO_AUTOSUGGEST)
+ ShowWindow(ac->hwndListBox, SW_HIDE);
+ heap_free(text);
+ return 0;
}
if (ac->options & ACO_AUTOSUGGEST)
ShowWindow(ac->hwndListBox, SW_HIDE);
- heap_free(text);
- return 0;
- case VK_LEFT:
- case VK_RIGHT:
- heap_free(text);
- return 0;
+ break;
case VK_UP:
case VK_DOWN:
/* Two cases here:
@@ -245,19 +260,20 @@ static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT u
set, display it with all the entries, without selecting any
- if the listbox is visible, change the selection
*/
- if ( (ac->options & (ACO_AUTOSUGGEST | ACO_UPDOWNKEYDROPSLIST))
- && (!IsWindowVisible(ac->hwndListBox) && (! *text)) )
+ if (!(ac->options & ACO_AUTOSUGGEST))
+ break;
+
+ if (!IsWindowVisible(ac->hwndListBox))
{
- /* We must display all the entries */
- displayall = TRUE;
+ if (ac->options & ACO_UPDOWNKEYDROPSLIST)
+ {
+ autocomplete_text(ac, hwnd, autoappend_flag_displayempty);
+ return 0;
+ }
}
else
{
INT count, sel;
- heap_free(text);
- if (!IsWindowVisible(ac->hwndListBox))
- return 0;
-
count = SendMessageW(ac->hwndListBox, LB_GETCOUNT, 0, 0);
/* Change the selection */
@@ -290,22 +306,14 @@ static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT u
return 0;
}
break;
- case VK_BACK:
case VK_DELETE:
- if ((! *text) && (ac->options & ACO_AUTOSUGGEST))
- {
- heap_free(text);
- ShowWindow(ac->hwndListBox, SW_HIDE);
- return CallWindowProcW(ac->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
- }
- break;
+ {
+ LRESULT ret = CallWindowProcW(ac->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
+ autocomplete_text(ac, hwnd, autoappend_flag_no);
+ return ret;
+ }
}
-
- if (len + 1 != size)
- text = heap_realloc(text, (len + 1) * sizeof(WCHAR));
-
- autocomplete_text(ac, text, len, hwnd, displayall);
- return 0;
+ return CallWindowProcW(ac->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
}
/*
@@ -314,6 +322,7 @@ static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT u
static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
IAutoCompleteImpl *This = GetPropW(hwnd, autocomplete_propertyW);
+ LRESULT ret;
if (!This->enabled) return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
@@ -329,8 +338,15 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
ShowWindow(This->hwndListBox, SW_HIDE);
}
return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
- case WM_KEYUP:
- return ACEditSubclassProc_KeyUp(This, hwnd, uMsg, wParam, lParam);
+ case WM_KEYDOWN:
+ return ACEditSubclassProc_KeyDown(This, hwnd, uMsg, wParam, lParam);
+ case WM_CHAR:
+ case WM_UNICHAR:
+ ret = CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
+ autocomplete_text(This, hwnd, (This->options & ACO_AUTOAPPEND) &&
+ (wParam >= ' ' || wParam == 0x16 /* ^V (paste) */)
+ ? autoappend_flag_yes : autoappend_flag_no);
+ return ret;
case WM_DESTROY:
{
WNDPROC proc = This->wpOrigEditProc;
--
1.9.1
More information about the wine-devel
mailing list