[PATCH v7 1/7] shell32/autocomplete: Move the autocomplete processing and WM_KEYUP to separate functions

Gabriel Ivăncescu gabrielopcode at gmail.com
Mon Sep 17 14:23:09 CDT 2018


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---

v7: Add a space after for/switch.

 dlls/shell32/autocomplete.c | 336 ++++++++++++++++++++++++--------------------
 1 file changed, 182 insertions(+), 154 deletions(-)

diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index 9f35ff7..874d831 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -119,6 +119,76 @@ 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)
+{
+    HRESULT hr;
+    UINT cpt;
+
+    SendMessageW(ac->hwndListBox, LB_RESETCONTENT, 0, 0);
+
+    /* Set txtbackup to point to text itself (which must not be released) */
+    heap_free(ac->txtbackup);
+    ac->txtbackup = text;
+
+    if (!displayall && !len)
+        return;
+
+    IEnumString_Reset(ac->enumstr);
+    for (cpt = 0;;)
+    {
+        LPOLESTR strs = NULL;
+        ULONG fetched;
+
+        hr = IEnumString_Next(ac->enumstr, 1, &strs, &fetched);
+        if (hr != S_OK)
+            break;
+
+        if (!strncmpiW(text, strs, len))
+        {
+            if (cpt == 0 && (ac->options & ACO_AUTOAPPEND))
+            {
+                WCHAR buffW[255];
+
+                strcpyW(buffW, text);
+                strcatW(buffW, &strs[len]);
+                SetWindowTextW(hwnd, buffW);
+                SendMessageW(hwnd, EM_SETSEL, len, strlenW(strs));
+                if (!(ac->options & ACO_AUTOSUGGEST))
+                {
+                    CoTaskMemFree(strs);
+                    break;
+                }
+            }
+
+            if (ac->options & ACO_AUTOSUGGEST)
+                SendMessageW(ac->hwndListBox, LB_ADDSTRING, 0, (LPARAM)strs);
+
+            cpt++;
+        }
+
+        CoTaskMemFree(strs);
+    }
+
+    if (ac->options & ACO_AUTOSUGGEST)
+    {
+        if (cpt)
+        {
+            RECT r;
+            UINT height = SendMessageW(ac->hwndListBox, LB_GETITEMHEIGHT, 0, 0);
+            SendMessageW(ac->hwndListBox, LB_CARETOFF, 0, 0);
+            GetWindowRect(hwnd, &r);
+            SetParent(ac->hwndListBox, HWND_DESKTOP);
+            /* It seems that Windows XP displays 7 lines at most
+               and otherwise displays a vertical scroll bar */
+            SetWindowPos(ac->hwndListBox, HWND_TOP,
+                         r.left, r.bottom + 1, r.right - r.left, min(height * 7, height*(cpt+1)),
+                         SWP_SHOWWINDOW );
+        }
+        else
+            ShowWindow(ac->hwndListBox, SW_HIDE);
+    }
+}
+
 static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
 {
     ac->hwndEdit = NULL;
@@ -128,17 +198,122 @@ static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
 }
 
 /*
+   Helper for ACEditSubclassProc
+*/
+static LRESULT ACEditSubclassProc_KeyUp(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;
+                if ((buf = heap_alloc(sz * sizeof(WCHAR))))
+                {
+                    len = format_quick_complete(buf, ac->quickComplete, text, len);
+                    SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)buf);
+                    SendMessageW(hwnd, EM_SETSEL, 0, len);
+                    heap_free(buf);
+                }
+            }
+
+            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;
+        case VK_UP:
+        case VK_DOWN:
+            /* 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 ( (ac->options & (ACO_AUTOSUGGEST | ACO_UPDOWNKEYDROPSLIST))
+                 && (!IsWindowVisible(ac->hwndListBox) && (! *text)) )
+            {
+                /* We must display all the entries */
+                displayall = TRUE;
+            }
+            else
+            {
+                INT count, sel;
+                heap_free(text);
+                if (!IsWindowVisible(ac->hwndListBox))
+                    return 0;
+
+                count = SendMessageW(ac->hwndListBox, LB_GETCOUNT, 0, 0);
+
+                /* Change the selection */
+                sel = SendMessageW(ac->hwndListBox, LB_GETCURSEL, 0, 0);
+                if (wParam == VK_UP)
+                    sel = ((sel - 1) < 0) ? count - 1 : sel - 1;
+                else
+                    sel = ((sel + 1) >= count) ? -1 : sel + 1;
+                SendMessageW(ac->hwndListBox, LB_SETCURSEL, sel, 0);
+                if (sel >= 0)
+                {
+                    WCHAR *msg;
+                    UINT len;
+
+                    len = SendMessageW(ac->hwndListBox, LB_GETTEXTLEN, sel, 0);
+                    if (!(msg = heap_alloc((len + 1) * sizeof(WCHAR))))
+                        return 0;
+                    len = SendMessageW(ac->hwndListBox, LB_GETTEXT, sel, (LPARAM)msg);
+                    SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)msg);
+                    SendMessageW(hwnd, EM_SETSEL, len, len);
+                    heap_free(msg);
+                }
+                else
+                {
+                    UINT len;
+                    SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)ac->txtbackup);
+                    len = strlenW(ac->txtbackup);
+                    SendMessageW(hwnd, EM_SETSEL, len, len);
+                }
+                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;
+    }
+
+    if (len + 1 != size)
+        text = heap_realloc(text, (len + 1) * sizeof(WCHAR));
+
+    autocomplete_text(ac, text, len, hwnd, displayall);
+    return 0;
+}
+
+/*
   Window procedure for autocompletion
  */
 static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
     IAutoCompleteImpl *This = GetPropW(hwnd, autocomplete_propertyW);
-    HRESULT hr;
-    WCHAR *hwndText;
-    UINT len, size, cpt;
-    RECT r;
-    BOOL displayall = FALSE;
-    int height, sel;
 
     if (!This->enabled) return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
 
@@ -155,154 +330,7 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
             }
             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);
-
-            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;
-                        if ((buf = heap_alloc(sz * sizeof(WCHAR))))
-                        {
-                            len = format_quick_complete(buf, This->quickComplete, hwndText, len);
-                            SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)buf);
-                            SendMessageW(hwnd, EM_SETSEL, 0, len);
-                            heap_free(buf);
-                        }
-                    }
-
-                    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;
-                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.
-                       - 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)) {
-                            int count;
-
-                            count = SendMessageW(This->hwndListBox, LB_GETCOUNT, 0, 0);
-                            /* Change the selection */
-                            sel = SendMessageW(This->hwndListBox, LB_GETCURSEL, 0, 0);
-                            if (wParam == VK_UP)
-                                sel = ((sel-1) < 0) ? count-1 : sel-1;
-                            else
-                                sel = ((sel+1) >= count) ? -1 : sel+1;
-                            SendMessageW(This->hwndListBox, LB_SETCURSEL, sel, 0);
-                            if (sel != -1) {
-                                WCHAR *msg;
-                                int len;
-
-                                len = SendMessageW(This->hwndListBox, LB_GETTEXTLEN, sel, 0);
-                                if (!(msg = heap_alloc((len + 1) * sizeof(WCHAR))))
-                                    return 0;
-                                len = SendMessageW(This->hwndListBox, LB_GETTEXT, sel, (LPARAM)msg);
-                                SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)msg);
-                                SendMessageW(hwnd, EM_SETSEL, len, len);
-                                heap_free(msg);
-                            } else {
-                                UINT len;
-                                SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)This->txtbackup);
-                                len = strlenW(This->txtbackup);
-                                SendMessageW(hwnd, EM_SETSEL, len, len);
-                            }
-                        }
-                        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;
-            }
-
-            if (len + 1 != size)
-                hwndText = heap_realloc(hwndText, (len + 1) * sizeof(WCHAR));
-
-            SendMessageW(This->hwndListBox, LB_RESETCONTENT, 0, 0);
-
-            /* Set txtbackup to point to hwndText itself (which must not be released) */
-            heap_free(This->txtbackup);
-            This->txtbackup = hwndText;
-
-            if (!displayall && !len)
-                break;
-
-            IEnumString_Reset(This->enumstr);
-            for(cpt = 0;;) {
-                LPOLESTR strs = NULL;
-                ULONG fetched;
-
-                hr = IEnumString_Next(This->enumstr, 1, &strs, &fetched);
-                if (hr != S_OK)
-                    break;
-
-                if (!strncmpiW(hwndText, strs, len)) {
-                    if (cpt == 0 && (This->options & ACO_AUTOAPPEND)) {
-                        WCHAR buffW[255];
-
-                        strcpyW(buffW, hwndText);
-                        strcatW(buffW, &strs[len]);
-                        SetWindowTextW(hwnd, buffW);
-                        SendMessageW(hwnd, EM_SETSEL, len, strlenW(strs));
-                        if (!(This->options & ACO_AUTOSUGGEST)) {
-                            CoTaskMemFree(strs);
-                            break;
-                        }
-                    }
-
-                    if (This->options & ACO_AUTOSUGGEST)
-                        SendMessageW(This->hwndListBox, LB_ADDSTRING, 0, (LPARAM)strs);
-
-                    cpt++;
-                }
-
-                CoTaskMemFree(strs);
-            }
-
-            if (This->options & ACO_AUTOSUGGEST) {
-                if (cpt) {
-                    height = SendMessageW(This->hwndListBox, LB_GETITEMHEIGHT, 0, 0);
-                    SendMessageW(This->hwndListBox, LB_CARETOFF, 0, 0);
-                    GetWindowRect(hwnd, &r);
-                    SetParent(This->hwndListBox, HWND_DESKTOP);
-                    /* It seems that Windows XP displays 7 lines at most
-                       and otherwise displays a vertical scroll bar */
-                    SetWindowPos(This->hwndListBox, HWND_TOP,
-                                 r.left, r.bottom + 1, r.right - r.left, min(height * 7, height*(cpt+1)),
-                                 SWP_SHOWWINDOW );
-                } else {
-                    ShowWindow(This->hwndListBox, SW_HIDE);
-                }
-            }
-
-            break;
+            return ACEditSubclassProc_KeyUp(This, hwnd, uMsg, wParam, lParam);
         case WM_DESTROY:
         {
             WNDPROC proc = This->wpOrigEditProc;
-- 
1.9.1




More information about the wine-devel mailing list