[PATCH v5 3/7] shell32/autocomplete: Redesign the window proc to trigger on key presses instead of key release
Huw Davies
huw at codeweavers.com
Thu Sep 13 05:37:29 CDT 2018
On Wed, Sep 12, 2018 at 10:42:17PM +0300, Gabriel Ivăncescu wrote:
> 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)
Not that it really matters, because this isn't going to go in as it is, but
having noautoappend as a tri-state is fine, except you can't declare it as a
BOOL and use FALSE, TRUE and 2 as its states. You'd want an enum.
Huw.
>
> 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