shell32/autocomplete: Move the autocomplete processing and WM_KEYUP to separate functions.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Gabriel Ivăncescu 2018-09-17 22:23:09 +03:00 committed by Alexandre Julliard
parent f2a8d53580
commit 779c513462
1 changed files with 182 additions and 154 deletions

View File

@ -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;
@ -127,18 +197,123 @@ static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
IAutoComplete2_Release(&ac->IAutoComplete2_iface);
}
/*
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;