=?UTF-8?Q?Gabriel=20Iv=C4=83ncescu=20?=: shell32/autocomplete: Use the optional IACList interface and IACList::Expand, if available.

Alexandre Julliard julliard at winehq.org
Wed Oct 17 18:15:43 CDT 2018


Module: wine
Branch: master
Commit: ef2558992201f31ec37c8b54399377c8e6d6d80f
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=ef2558992201f31ec37c8b54399377c8e6d6d80f

Author: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Date:   Tue Oct 16 14:30:45 2018 +0300

shell32/autocomplete: Use the optional IACList interface and IACList::Expand, if available.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/shell32/autocomplete.c | 70 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index 11e9317..dfe7638 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -2,6 +2,7 @@
  *	AutoComplete interfaces implementation.
  *
  *	Copyright 2004	Maxime Bellengé <maxime.bellenge at laposte.net>
+ *	Copyright 2018	Gabriel Ivăncescu <gabrielopcode at gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -68,6 +69,7 @@ typedef struct
     WCHAR *txtbackup;
     WCHAR *quickComplete;
     IEnumString *enumstr;
+    IACList *aclist;
     AUTOCOMPLETEOPTIONS options;
     WCHAR no_fwd_char;
 } IAutoCompleteImpl;
@@ -221,6 +223,49 @@ static LRESULT change_selection(IAutoCompleteImpl *ac, HWND hwnd, UINT key)
     return 0;
 }
 
+static BOOL do_aclist_expand(IAutoCompleteImpl *ac, WCHAR *txt, WCHAR *last_delim)
+{
+    WCHAR c = last_delim[1];
+    last_delim[1] = '\0';
+    IACList_Expand(ac->aclist, txt);
+    last_delim[1] = c;
+    return TRUE;
+}
+
+static BOOL aclist_expand(IAutoCompleteImpl *ac, WCHAR *txt)
+{
+    /* call IACList::Expand only when needed, if the
+       new txt and old_txt require different expansions */
+    WCHAR c, *p, *last_delim, *old_txt = ac->txtbackup;
+    size_t i = 0;
+
+    /* '/' is allowed as a delim for unix paths */
+    static const WCHAR delims[] = { '\\', '/', 0 };
+
+    /* skip the shared prefix */
+    while ((c = tolowerW(txt[i])) == tolowerW(old_txt[i]))
+    {
+        if (c == '\0') return FALSE;
+        i++;
+    }
+
+    /* they differ at this point, check for a delim further in txt */
+    for (last_delim = NULL, p = &txt[i]; (p = strpbrkW(p, delims)) != NULL; p++)
+        last_delim = p;
+    if (last_delim) return do_aclist_expand(ac, txt, last_delim);
+
+    /* txt has no delim after i, check for a delim further in old_txt */
+    if (strpbrkW(&old_txt[i], delims))
+    {
+        /* scan backwards to find the first delim before txt[i] (if any) */
+        while (i--)
+            if (strchrW(delims, txt[i]))
+                return do_aclist_expand(ac, txt, &txt[i]);
+    }
+
+    return FALSE;
+}
+
 static void autoappend_str(IAutoCompleteImpl *ac, WCHAR *text, UINT len, WCHAR *str, HWND hwnd)
 {
     DWORD sel_start;
@@ -268,6 +313,17 @@ static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_
     if (len + 1 != size)
         text = heap_realloc(text, (len + 1) * sizeof(WCHAR));
 
+    /* Reset it here to simplify the logic in aclist_expand for
+       empty strings, since it tracks changes using txtbackup,
+       and Reset needs to be called before IACList::Expand */
+    IEnumString_Reset(ac->enumstr);
+    if (ac->aclist)
+    {
+        aclist_expand(ac, text);
+        if (text[len - 1] == '\\' || text[len - 1] == '/')
+            flag = autoappend_flag_no;
+    }
+
     /* Set txtbackup to point to text itself (which must not be released) */
     heap_free(ac->txtbackup);
     ac->txtbackup = text;
@@ -277,7 +333,6 @@ static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_
         SendMessageW(ac->hwndListBox, WM_SETREDRAW, FALSE, 0);
         SendMessageW(ac->hwndListBox, LB_RESETCONTENT, 0, 0);
     }
-    IEnumString_Reset(ac->enumstr);
     for (cpt = 0;;)
     {
         LPOLESTR strs = NULL;
@@ -607,6 +662,8 @@ static ULONG WINAPI IAutoComplete2_fnRelease(
         heap_free(This->txtbackup);
         if (This->enumstr)
             IEnumString_Release(This->enumstr);
+        if (This->aclist)
+            IACList_Release(This->aclist);
         heap_free(This);
     }
     return refCount;
@@ -663,6 +720,17 @@ static HRESULT WINAPI IAutoComplete2_fnInit(
         return E_NOINTERFACE;
     }
 
+    /* Prevent txtbackup from ever being NULL to simplify aclist_expand */
+    if ((This->txtbackup = heap_alloc_zero(sizeof(WCHAR))) == NULL)
+    {
+        IEnumString_Release(This->enumstr);
+        This->enumstr = NULL;
+        return E_OUTOFMEMORY;
+    }
+
+    if (FAILED (IUnknown_QueryInterface (punkACL, &IID_IACList, (LPVOID*)&This->aclist)))
+        This->aclist = NULL;
+
     This->initialized = TRUE;
     This->hwndEdit = hwndEdit;
 




More information about the wine-cvs mailing list