[PATCH v5 3/7] shell32/autocomplete: Redesign the window proc to trigger on key presses instead of key release
Gabriel Ivăncescu
gabrielopcode at gmail.com
Wed Sep 12 14:42:17 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>
---
Compared to version 4 of the patch, noautoappend and displayall have been
collapsed into one parameter to reduce clutter when calling the function,
since the latter implies the former (uses value 2 since it's only used in
one place at the beginning of the function); to me it's better than seeing
stuff like TRUE, FALSE or TRUE, TRUE (of course can be changed to that,
if needed... just a preference here)
dlls/shell32/autocomplete.c | 108 ++++++++++++++++++++++++--------------------
1 file changed, 59 insertions(+), 49 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index 63fdf3d..71259af 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -119,10 +119,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, BOOL noautoappend)
{
HRESULT hr;
- UINT cpt;
+ WCHAR *text;
+ UINT cpt, size, len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
+
+ if (noautoappend != 2 && 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 +145,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 +157,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 && noautoappend == FALSE)
{
WCHAR buffW[255];
@@ -203,9 +215,7 @@ static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
IAutoCompleteImpl *This = GetPropW(hwnd, autocomplete_propertyW);
- WCHAR *hwndText;
- UINT len, size;
- BOOL displayall = FALSE;
+ LRESULT ret;
if (!This->enabled) return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
@@ -221,20 +231,20 @@ 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:
- len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
- size = len + 1;
- if (!(hwndText = heap_alloc(size * sizeof(WCHAR))))
- return 0;
- len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)hwndText);
-
+ case WM_KEYDOWN:
switch(wParam) {
case VK_RETURN:
/* If quickComplete is set and control is pressed, replace the string */
if (This->quickComplete && (GetKeyState(VK_CONTROL) & 0x8000))
{
- WCHAR *buf;
- size_t sz = strlenW(This->quickComplete) + 1 + len;
+ WCHAR *hwndText, *buf;
+ size_t sz;
+ UINT len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
+ if (!(hwndText = heap_alloc((len + 1) * sizeof(WCHAR))))
+ return 0;
+ len = SendMessageW(hwnd, WM_GETTEXT, len + 1, (LPARAM)hwndText);
+ sz = strlenW(This->quickComplete) + 1 + len;
+
if ((buf = heap_alloc(sz * sizeof(WCHAR))))
{
len = format_quick_complete(buf, This->quickComplete, hwndText, len);
@@ -242,32 +252,35 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
SendMessageW(hwnd, EM_SETSEL, 0, len);
heap_free(buf);
}
+
+ if (This->options & ACO_AUTOSUGGEST)
+ ShowWindow(This->hwndListBox, SW_HIDE);
+ heap_free(hwndText);
+ return 0;
}
if (This->options & ACO_AUTOSUGGEST)
ShowWindow(This->hwndListBox, SW_HIDE);
- heap_free(hwndText);
- return 0;
- case VK_LEFT:
- case VK_RIGHT:
- heap_free(hwndText);
- return 0;
+ break;
case VK_UP:
case VK_DOWN:
- /* Two cases here :
- - if the listbox is not visible, displays it
- with all the entries if the style ACO_UPDOWNKEYDROPSLIST
- is present but does not select anything.
+ /* Two cases here:
+ - if the listbox is not visible and ACO_UPDOWNKEYDROPSLIST is
+ set, display it with all the entries, without selecting any
- if the listbox is visible, change the selection
*/
- if ( (This->options & (ACO_AUTOSUGGEST | ACO_UPDOWNKEYDROPSLIST))
- && (!IsWindowVisible(This->hwndListBox) && (! *hwndText)) )
+ if (This->options & ACO_AUTOSUGGEST)
{
- /* We must display all the entries */
- displayall = TRUE;
- } else {
- heap_free(hwndText);
- if (IsWindowVisible(This->hwndListBox)) {
+ if (!IsWindowVisible(This->hwndListBox))
+ {
+ if (This->options & ACO_UPDOWNKEYDROPSLIST)
+ {
+ autocomplete_text(This, hwnd, 2);
+ return 0;
+ }
+ }
+ else
+ {
int count, sel;
count = SendMessageW(This->hwndListBox, LB_GETCOUNT, 0, 0);
@@ -295,25 +308,22 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
len = strlenW(This->txtbackup);
SendMessageW(hwnd, EM_SETSEL, len, len);
}
+ return 0;
}
- return 0;
}
break;
- case VK_BACK:
case VK_DELETE:
- if ((! *hwndText) && (This->options & ACO_AUTOSUGGEST)) {
- heap_free(hwndText);
- ShowWindow(This->hwndListBox, SW_HIDE);
- return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
- }
- break;
+ ret = CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
+ autocomplete_text(This, hwnd, TRUE);
+ return ret;
}
-
- if (len + 1 != size)
- hwndText = heap_realloc(hwndText, (len + 1) * sizeof(WCHAR));
-
- autocomplete_text(This, hwndText, len, hwnd, displayall);
- break;
+ return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
+ case WM_CHAR:
+ case WM_UNICHAR:
+ ret = CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
+ autocomplete_text(This, hwnd, (wParam < ' ' && wParam != 0x16 /* ^V (paste) */)
+ || !(This->options & ACO_AUTOAPPEND));
+ return ret;
case WM_DESTROY:
{
WNDPROC proc = This->wpOrigEditProc;
--
1.9.1
More information about the wine-devel
mailing list