[PATCH 17/17] shell32/autocomplete: Use the optional IACList interface and IACList::Expand, if available
Gabriel Ivăncescu
gabrielopcode at gmail.com
Wed Sep 5 11:13:19 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.
After this patch series, it now matches Windows behavior very closely,
and it finally makes AutoComplete useable for me. :)
dlls/shell32/autocomplete.c | 75 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 73 insertions(+), 2 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index c145dc0..5262a9f 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
@@ -23,7 +24,7 @@
- ACO_AUTOAPPEND style
- ACO_AUTOSUGGEST style
- ACO_UPDOWNKEYDROPSLIST style
-
+ - IACList::Expand
- Handle pwzsRegKeyPath and pwszQuickComplete in Init
TODO:
@@ -78,6 +79,7 @@ typedef struct
WCHAR *txtbackup;
WCHAR *quickComplete;
IEnumString *enumstr;
+ IACList *aclist;
} IAutoCompleteImpl;
static const WCHAR autocomplete_propertyW[] = {'W','i','n','e',' ','A','u','t','o',
@@ -117,6 +119,61 @@ static void hide_listbox(IAutoCompleteImpl *ac, HWND hwnd)
send_to_LB(ac, hwnd, LB_RESETCONTENT, 0, 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 */
+ p = &txt[i];
+ while (*p != '\0') {
+ if (*p == '\\' || *p == '/') {
+ last_delim = p;
+ do {
+ p++;
+ if (*p == '\\' || *p == '/')
+ last_delim = p;
+ } while(*p != '\0');
+ goto expand;
+ }
+ p++;
+ }
+
+ /* txt has no delim after i, check for a delim further in old_txt */
+ p = &old_txt[i];
+ while (*p != '\0') {
+ 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 */
+ }
+ p++;
+ }
+
+ /* 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 destroy_autocomplete_object(IAutoCompleteImpl *ac)
{
ac->hwndEdit = NULL;
@@ -295,6 +352,16 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
if (len+1 != old_len)
hwndText = heap_realloc(hwndText, len+1);
+ /* 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(This->enumstr);
+ if (This->aclist) {
+ aclist_expand(This, hwndText);
+ if (hwndText[len-1] == '\\' || hwndText[len-1] == '/')
+ noautoappend = TRUE;
+ }
+
/* Set txtbackup to point to hwndText itself (which must not be released) */
heap_free(This->txtbackup);
This->txtbackup = hwndText;
@@ -306,7 +373,6 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
send_to_LB(This, This->hwndListBox, WM_SETREDRAW, FALSE, 0);
send_to_LB(This, This->hwndListBox, LB_RESETCONTENT, 0, 0);
}
- IEnumString_Reset(This->enumstr);
for(cpt = 0;;) {
LPOLESTR strs = NULL;
ULONG fetched;
@@ -504,6 +570,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;
@@ -567,6 +635,9 @@ static HRESULT WINAPI IAutoComplete2_fnInit(
return E_NOINTERFACE;
}
+ 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