[PATCH v4 07/10] shell32/autocomplete: Redesign the window proc to trigger on key presses instead of key release

Huw Davies huw at codeweavers.com
Tue Sep 11 06:54:59 CDT 2018


On Mon, Sep 10, 2018 at 10:09:37PM +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>
> ---
>  dlls/shell32/autocomplete.c | 97 +++++++++++++++++++++++++++------------------
>  1 file changed, 58 insertions(+), 39 deletions(-)
> 
> diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
> index 7421679..49cf37a 100644
> --- a/dlls/shell32/autocomplete.c
> +++ b/dlls/shell32/autocomplete.c
> @@ -134,10 +134,11 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
>  {
>      IAutoCompleteImpl *This = GetPropW(hwnd, autocomplete_propertyW);
>      HRESULT hr;
> +    LRESULT ret;
>      WCHAR *hwndText;
>      UINT len, size, cpt;
>      RECT r;
> -    BOOL displayall = FALSE;
> +    BOOLEAN displayall = FALSE, noautoappend = !(This->options & ACO_AUTOAPPEND);
>      int height, sel;
>  
>      if (!This->enabled) return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
> @@ -154,20 +155,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;
> +                        size_t sz;
> +                        len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0) + 1;  /* include NUL */
> +                        if (!(hwndText = heap_alloc(len * sizeof(WCHAR))))
> +                            return 0;
> +                        len = SendMessageW(hwnd, WM_GETTEXT, len, (LPARAM)hwndText);
> +                        sz = strlenW(This->quickComplete) + 1 + len;
> +
>                          if ((buf = heap_alloc(sz * sizeof(WCHAR))))
>                          {
>                              len = format_quick_complete(buf, This->quickComplete, hwndText, len);
> @@ -175,32 +176,31 @@ 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)) )
> -                    {
> -                         /* We must display all the entries */
> -                         displayall = TRUE;
> -                    } else {
> -                        heap_free(hwndText);
> -                        if (IsWindowVisible(This->hwndListBox)) {
> +                    if (This->options & ACO_AUTOSUGGEST) {
> +                        if (!IsWindowVisible(This->hwndListBox)) {
> +                            if (This->options & ACO_UPDOWNKEYDROPSLIST) {
> +                                ret = 0;
> +                                displayall = TRUE;
> +                                noautoappend = TRUE;
> +                                goto handle_char;

No.  I'm not signing off on this.  You're going to have to come on with
a much cleaner way to do this.

> +                            }
> +                        } else {
>                              int count;
>  
>                              count = SendMessageW(This->hwndListBox, LB_GETCOUNT, 0, 0);
> @@ -228,20 +228,40 @@ 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);
> +                    goto handle_control_char;
> +            }
> +            return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
> +        case WM_CHAR:
> +        case WM_UNICHAR:
> +            ret = CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
> +            if (wParam < ' ')
> +            {
> +              handle_control_char:
> +                len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
> +                if ((This->options & ACO_AUTOSUGGEST) && len == 0)
> +                {
> +                    ShowWindow(This->hwndListBox, SW_HIDE);
> +                    return ret;
> +                }
> +                if (wParam != 0x16 /* ^V (paste) */)
> +                    noautoappend = TRUE;
> +            }
> +            else
> +            {
> +              handle_char:
> +                len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
>              }
>  
> +            size = len + 1;
> +            if (!(hwndText = heap_alloc(size * sizeof(WCHAR))))
> +                return ret;
> +            len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)hwndText);
>              if (len + 1 != size)
>                  hwndText = heap_realloc(hwndText, len + 1);
>  
> @@ -252,7 +272,7 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
>              This->txtbackup = hwndText;
>  
>              if (!displayall && !len)
> -                break;
> +                return ret;
>  
>              IEnumString_Reset(This->enumstr);
>              for(cpt = 0;;) {
> @@ -264,7 +284,7 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
>                      break;
>  
>                  if (!strncmpiW(hwndText, strs, len)) {
> -                    if (cpt == 0 && (This->options & ACO_AUTOAPPEND)) {
> +                    if (cpt == 0 && noautoappend == FALSE) {
>                          WCHAR buffW[255];
>  
>                          strcpyW(buffW, hwndText);
> @@ -301,8 +321,7 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
>                      ShowWindow(This->hwndListBox, SW_HIDE);
>                  }
>              }
> -
> -            break;
> +            return ret;
>          case WM_DESTROY:
>          {
>              WNDPROC proc = This->wpOrigEditProc;
> -- 
> 1.9.1
> 
> 
> 



More information about the wine-devel mailing list