On Wed, Sep 12, 2018 at 10:42:17PM +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@gmail.com
Compared to version 4 of the patch, noautoappend and displayall have been collapsed into one parameter to reduce clutter when calling the function, since the latter implies the former (uses value 2 since it's only used in one place at the beginning of the function); to me it's better than seeing stuff like TRUE, FALSE or TRUE, TRUE (of course can be changed to that, if needed... just a preference here)
Not that it really matters, because this isn't going to go in as it is, but having noautoappend as a tri-state is fine, except you can't declare it as a BOOL and use FALSE, TRUE and 2 as its states. You'd want an enum.
Huw.
dlls/shell32/autocomplete.c | 108 ++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 49 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c index 63fdf3d..71259af 100644 --- a/dlls/shell32/autocomplete.c +++ b/dlls/shell32/autocomplete.c @@ -119,10 +119,25 @@ 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) +static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, BOOL noautoappend) { HRESULT hr;
- UINT cpt;
WCHAR *text;
UINT cpt, size, len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
if (noautoappend != 2 && len == 0)
{
if (ac->options & ACO_AUTOSUGGEST)
ShowWindow(ac->hwndListBox, SW_HIDE);
return;
}
size = len + 1;
if (!(text = heap_alloc(size * sizeof(WCHAR))))
return;
len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)text);
if (len + 1 != size)
text = heap_realloc(text, (len + 1) * sizeof(WCHAR));
SendMessageW(ac->hwndListBox, LB_RESETCONTENT, 0, 0);
@@ -130,9 +145,6 @@ static void autocomplete_text(IAutoCompleteImpl *ac, WCHAR *text, UINT len, HWND heap_free(ac->txtbackup); ac->txtbackup = text;
- if (!displayall && !len)
return;
- IEnumString_Reset(ac->enumstr); for(cpt = 0;;) {
@@ -145,7 +157,7 @@ static void autocomplete_text(IAutoCompleteImpl *ac, WCHAR *text, UINT len, HWND
if (!strncmpiW(text, strs, len)) {
if (cpt == 0 && (ac->options & ACO_AUTOAPPEND))
if (cpt == 0 && noautoappend == FALSE) { WCHAR buffW[255];
@@ -203,9 +215,7 @@ static void destroy_autocomplete_object(IAutoCompleteImpl *ac) static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { IAutoCompleteImpl *This = GetPropW(hwnd, autocomplete_propertyW);
- WCHAR *hwndText;
- UINT len, size;
- BOOL displayall = FALSE;
LRESULT ret;
if (!This->enabled) return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
@@ -221,20 +231,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;
WCHAR *hwndText, *buf;
size_t sz;
UINT len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
if (!(hwndText = heap_alloc((len + 1) * sizeof(WCHAR))))
return 0;
len = SendMessageW(hwnd, WM_GETTEXT, len + 1, (LPARAM)hwndText);
sz = strlenW(This->quickComplete) + 1 + len;
if ((buf = heap_alloc(sz * sizeof(WCHAR)))) { len = format_quick_complete(buf, This->quickComplete, hwndText, len);
@@ -242,32 +252,35 @@ 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)) )
if (This->options & ACO_AUTOSUGGEST) {
/* We must display all the entries */
displayall = TRUE;
} else {
heap_free(hwndText);
if (IsWindowVisible(This->hwndListBox)) {
if (!IsWindowVisible(This->hwndListBox))
{
if (This->options & ACO_UPDOWNKEYDROPSLIST)
{
autocomplete_text(This, hwnd, 2);
return 0;
}
}
else
{ int count, sel; count = SendMessageW(This->hwndListBox, LB_GETCOUNT, 0, 0);
@@ -295,25 +308,22 @@ 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);
autocomplete_text(This, hwnd, TRUE);
return ret; }
if (len + 1 != size)
hwndText = heap_realloc(hwndText, (len + 1) * sizeof(WCHAR));
autocomplete_text(This, hwndText, len, hwnd, displayall);
break;
return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
case WM_CHAR:
case WM_UNICHAR:
ret = CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
autocomplete_text(This, hwnd, (wParam < ' ' && wParam != 0x16 /* ^V (paste) */)
|| !(This->options & ACO_AUTOAPPEND));
return ret; case WM_DESTROY: { WNDPROC proc = This->wpOrigEditProc;
-- 1.9.1