[PATCH v2 6/7] shell32/autocomplete: Use the optional IACList interface and IACList::Expand, if available
Gabriel Ivăncescu
gabrielopcode at gmail.com
Fri Sep 28 06:44:11 CDT 2018
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
This enables Total Commander to show full paths on many edit boxes, like
on Windows, instead of just the current directory's entries.
I couldn't get the / delimiter to work at all on Windows XP, so MSDN is
probably wrong here. Despite that, I've actually added support for it in
this patch, as a Wine extension, to help with unix-style paths autocompletion
since we also support those.
dlls/shell32/autocomplete.c | 73 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 2 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index 43c93ef..cd2abd3 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
@@ -24,7 +25,7 @@
- ACO_AUTOSUGGEST style
- ACO_UPDOWNKEYDROPSLIST style
- ACO_USETAB style
-
+ - IACList::Expand
- Handle pwzsRegKeyPath and pwszQuickComplete in Init
TODO:
@@ -76,6 +77,7 @@ typedef struct
WCHAR *txtbackup;
WCHAR *quickComplete;
IEnumString *enumstr;
+ IACList *aclist;
AUTOCOMPLETEOPTIONS options;
UCHAR no_fwd_char;
} IAutoCompleteImpl;
@@ -229,6 +231,54 @@ static LRESULT change_selection(IAutoCompleteImpl *ac, HWND hwnd, UINT key)
return 0;
}
+static void aclist_expand(IAutoCompleteImpl *ac, WCHAR *txt)
+{
+ /* call IACList::Expand only when needed
+ '/' is allowed as a delim for unix paths */
+ WCHAR c, *p, *last_delim, *old_txt = ac->txtbackup;
+ size_t i = 0;
+
+ /* skip the shared prefix */
+ while ((c = tolowerW(txt[i])) == tolowerW(old_txt[i]))
+ {
+ if (c == '\0') return;
+ i++;
+ }
+
+ /* they differ at this point, check for a delim further in txt */
+ last_delim = NULL;
+ for (p = &txt[i]; *p != '\0'; p++)
+ if (*p == '\\' || *p == '/')
+ last_delim = p;
+ if (last_delim)
+ goto expand;
+
+ /* txt has no delim after i, check for a delim further in old_txt */
+ for (p = &old_txt[i]; *p != '\0'; p++)
+ if (*p == '\\' || *p == '/')
+ {
+ /* find the delim before i (if any) */
+ while (i--)
+ {
+ if (txt[i] == '\\' || txt[i] == '/')
+ {
+ last_delim = &txt[i];
+ goto expand;
+ }
+ }
+ break; /* Windows doesn't expand without a delim */
+ }
+
+ /* they differ, but without any different delims, so no need to expand */
+ return;
+
+expand:
+ c = last_delim[1];
+ last_delim[1] = '\0';
+ IACList_Expand(ac->aclist, txt);
+ last_delim[1] = c;
+}
+
static void autoappend_str(IAutoCompleteImpl *ac, WCHAR *text, UINT len, WCHAR *str, HWND hwnd)
{
DWORD sel_start;
@@ -276,6 +326,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;
@@ -285,7 +346,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;
@@ -615,6 +675,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;
@@ -671,6 +733,13 @@ 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)
+ return E_OUTOFMEMORY;
+
+ if (FAILED (IUnknown_QueryInterface (punkACL, &IID_IACList, (LPVOID*)&This->aclist)))
+ This->aclist = NULL;
+
This->initialized = TRUE;
This->hwndEdit = hwndEdit;
--
1.9.1
More information about the wine-devel
mailing list