Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
v6: Also move WM_KEYUP to a separate function.
dlls/shell32/autocomplete.c | 336 ++++++++++++++++++++++++--------------------
1 file changed, 182 insertions(+), 154 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index 9f35ff7..ebbb9ee 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -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;
@@ -128,17 +198,122 @@ static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
}
/*
+ 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;
--
1.9.1