2 * Tests for autocomplete
4 * Copyright 2008 Jan de Mooij
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/heap.h"
32 #include "wine/test.h"
34 static HWND hMainWnd
, hEdit
;
35 static HINSTANCE hinst
;
36 static int killfocus_count
;
38 static void test_invalid_init(void)
45 /* AutoComplete instance */
46 hr
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
,
47 &IID_IAutoComplete
, (void **)&ac
);
48 if (hr
== REGDB_E_CLASSNOTREG
)
50 win_skip("CLSID_AutoComplete is not registered\n");
53 ok(hr
== S_OK
, "no IID_IAutoComplete (0x%08x)\n", hr
);
55 /* AutoComplete source */
56 hr
= CoCreateInstance(&CLSID_ACLMulti
, NULL
, CLSCTX_INPROC_SERVER
,
57 &IID_IACList
, (void **)&acSource
);
58 if (hr
== REGDB_E_CLASSNOTREG
)
60 win_skip("CLSID_ACLMulti is not registered\n");
61 IAutoComplete_Release(ac
);
64 ok(hr
== S_OK
, "no IID_IACList (0x%08x)\n", hr
);
66 edit_control
= CreateWindowExA(0, "EDIT", "Some text", 0, 10, 10, 300, 300,
67 hMainWnd
, NULL
, hinst
, NULL
);
68 ok(edit_control
!= NULL
, "Can't create edit control\n");
70 /* The refcount of acSource would be incremented on older Windows. */
71 hr
= IAutoComplete_Init(ac
, NULL
, acSource
, NULL
, NULL
);
72 ok(hr
== E_INVALIDARG
||
73 broken(hr
== S_OK
), /* Win2k/XP/Win2k3 */
74 "Init returned 0x%08x\n", hr
);
75 if (hr
== E_INVALIDARG
)
79 IUnknown_AddRef(acSource
);
80 ref
= IUnknown_Release(acSource
);
81 ok(ref
== 1, "Expected AutoComplete source refcount to be 1, got %d\n", ref
);
86 /* Older Windows versions never check the window handle, while newer
87 * versions only check for NULL. Subsequent attempts to initialize the
88 * object after this call succeeds would fail, because initialization
89 * state is determined by whether a non-NULL window handle is stored. */
90 hr
= IAutoComplete_Init(ac
, (HWND
)0xdeadbeef, acSource
, NULL
, NULL
);
91 ok(hr
== S_OK
, "Init returned 0x%08x\n", hr
);
93 /* Tests crash on older Windows. */
94 hr
= IAutoComplete_Init(ac
, NULL
, NULL
, NULL
, NULL
);
95 ok(hr
== E_INVALIDARG
, "Init returned 0x%08x\n", hr
);
97 hr
= IAutoComplete_Init(ac
, edit_control
, NULL
, NULL
, NULL
);
98 ok(hr
== E_INVALIDARG
, "Init returned 0x%08x\n", hr
);
101 /* bind to edit control */
102 hr
= IAutoComplete_Init(ac
, edit_control
, acSource
, NULL
, NULL
);
103 ok(hr
== S_OK
, "Init returned 0x%08x\n", hr
);
105 /* try invalid parameters after successful initialization .*/
106 hr
= IAutoComplete_Init(ac
, NULL
, NULL
, NULL
, NULL
);
107 ok(hr
== E_INVALIDARG
||
108 hr
== E_FAIL
, /* Win2k/XP/Win2k3 */
109 "Init returned 0x%08x\n", hr
);
111 hr
= IAutoComplete_Init(ac
, NULL
, acSource
, NULL
, NULL
);
112 ok(hr
== E_INVALIDARG
||
113 hr
== E_FAIL
, /* Win2k/XP/Win2k3 */
114 "Init returned 0x%08x\n", hr
);
116 hr
= IAutoComplete_Init(ac
, edit_control
, NULL
, NULL
, NULL
);
117 ok(hr
== E_INVALIDARG
||
118 hr
== E_FAIL
, /* Win2k/XP/Win2k3 */
119 "Init returned 0x%08x\n", hr
);
121 /* try initializing twice on the same control */
122 hr
= IAutoComplete_Init(ac
, edit_control
, acSource
, NULL
, NULL
);
123 ok(hr
== E_FAIL
, "Init returned 0x%08x\n", hr
);
125 /* try initializing with a different control */
126 hr
= IAutoComplete_Init(ac
, hEdit
, acSource
, NULL
, NULL
);
127 ok(hr
== E_FAIL
, "Init returned 0x%08x\n", hr
);
129 DestroyWindow(edit_control
);
131 /* try initializing with a different control after
132 * destroying the original initialization control */
133 hr
= IAutoComplete_Init(ac
, hEdit
, acSource
, NULL
, NULL
);
134 ok(hr
== E_UNEXPECTED
||
135 hr
== E_FAIL
, /* Win2k/XP/Win2k3 */
136 "Init returned 0x%08x\n", hr
);
138 IUnknown_Release(acSource
);
139 IAutoComplete_Release(ac
);
141 static IAutoComplete
*test_init(void)
144 IAutoComplete
*ac
, *ac2
;
148 /* AutoComplete instance */
149 r
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
,
150 &IID_IAutoComplete
, (LPVOID
*)&ac
);
151 if (r
== REGDB_E_CLASSNOTREG
)
153 win_skip("CLSID_AutoComplete is not registered\n");
156 ok(r
== S_OK
, "no IID_IAutoComplete (0x%08x)\n", r
);
158 /* AutoComplete source */
159 r
= CoCreateInstance(&CLSID_ACLMulti
, NULL
, CLSCTX_INPROC_SERVER
,
160 &IID_IACList
, (LPVOID
*)&acSource
);
161 if (r
== REGDB_E_CLASSNOTREG
)
163 win_skip("CLSID_ACLMulti is not registered\n");
164 IAutoComplete_Release(ac
);
167 ok(r
== S_OK
, "no IID_IACList (0x%08x)\n", r
);
169 user_data
= GetWindowLongPtrA(hEdit
, GWLP_USERDATA
);
170 ok(user_data
== 0, "Expected the edit control user data to be zero\n");
172 /* bind to edit control */
173 r
= IAutoComplete_Init(ac
, hEdit
, acSource
, NULL
, NULL
);
174 ok(r
== S_OK
, "Init returned 0x%08x\n", r
);
176 user_data
= GetWindowLongPtrA(hEdit
, GWLP_USERDATA
);
177 ok(user_data
== 0, "Expected the edit control user data to be zero\n");
179 /* bind a different object to the same edit control */
180 r
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
,
181 &IID_IAutoComplete
, (LPVOID
*)&ac2
);
182 ok(r
== S_OK
, "no IID_IAutoComplete (0x%08x)\n", r
);
184 r
= IAutoComplete_Init(ac2
, hEdit
, acSource
, NULL
, NULL
);
185 ok(r
== S_OK
, "Init returned 0x%08x\n", r
);
186 IAutoComplete_Release(ac2
);
188 IUnknown_Release(acSource
);
193 static void test_killfocus(void)
195 /* Test if WM_KILLFOCUS messages are handled properly by checking if
196 * the parent receives an EN_KILLFOCUS message. */
200 ok(killfocus_count
== 1, "Expected one EN_KILLFOCUS message, got: %d\n", killfocus_count
);
203 static LRESULT CALLBACK
MyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
207 /* create edit control */
208 hEdit
= CreateWindowExA(0, "EDIT", "Some text", 0, 10, 10, 300, 300,
209 hWnd
, NULL
, hinst
, NULL
);
210 ok(hEdit
!= NULL
, "Can't create edit control\n");
213 if(HIWORD(wParam
) == EN_KILLFOCUS
)
217 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
220 static void createMainWnd(void)
223 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
226 wc
.hInstance
= GetModuleHandleA(NULL
);
228 wc
.hCursor
= LoadCursorA(NULL
, (LPSTR
)IDC_IBEAM
);
229 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
230 wc
.lpszMenuName
= NULL
;
231 wc
.lpszClassName
= "MyTestWnd";
232 wc
.lpfnWndProc
= MyWndProc
;
235 hMainWnd
= CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW
,
236 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
239 static WNDPROC HijackerWndProc_prev
;
240 static const WCHAR HijackerWndProc_txt
[] = {'H','i','j','a','c','k','e','d',0};
241 static LRESULT CALLBACK
HijackerWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
246 size_t len
= min(wParam
, ARRAY_SIZE(HijackerWndProc_txt
));
247 memcpy((void*)lParam
, HijackerWndProc_txt
, len
* sizeof(WCHAR
));
250 case WM_GETTEXTLENGTH
:
251 return ARRAY_SIZE(HijackerWndProc_txt
) - 1;
253 return CallWindowProcW(HijackerWndProc_prev
, hWnd
, msg
, wParam
, lParam
);
256 static LRESULT CALLBACK
HijackerWndProc2(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
263 lParam
= (LPARAM
)HijackerWndProc_txt
;
266 return CallWindowProcW(HijackerWndProc_prev
, hWnd
, msg
, wParam
, lParam
);
269 struct string_enumerator
271 IEnumString IEnumString_iface
;
272 IACList IACList_iface
;
279 WCHAR last_expand
[32];
282 static struct string_enumerator
*impl_from_IEnumString(IEnumString
*iface
)
284 return CONTAINING_RECORD(iface
, struct string_enumerator
, IEnumString_iface
);
287 static HRESULT WINAPI
string_enumerator_QueryInterface(IEnumString
*iface
, REFIID riid
, void **ppv
)
289 struct string_enumerator
*this = impl_from_IEnumString(iface
);
290 if (IsEqualGUID(riid
, &IID_IEnumString
) || IsEqualGUID(riid
, &IID_IUnknown
))
291 *ppv
= &this->IEnumString_iface
;
292 else if (IsEqualGUID(riid
, &IID_IACList
))
293 *ppv
= &this->IACList_iface
;
297 return E_NOINTERFACE
;
300 IUnknown_AddRef(&this->IEnumString_iface
);
304 static ULONG WINAPI
string_enumerator_AddRef(IEnumString
*iface
)
306 struct string_enumerator
*this = impl_from_IEnumString(iface
);
308 ULONG ref
= InterlockedIncrement(&this->ref
);
313 static ULONG WINAPI
string_enumerator_Release(IEnumString
*iface
)
315 struct string_enumerator
*this = impl_from_IEnumString(iface
);
317 ULONG ref
= InterlockedDecrement(&this->ref
);
325 static HRESULT WINAPI
string_enumerator_Next(IEnumString
*iface
, ULONG num
, LPOLESTR
*strings
, ULONG
*num_returned
)
327 struct string_enumerator
*this = impl_from_IEnumString(iface
);
331 for (i
= 0; i
< num
; i
++)
333 if (this->cur
>= this->data_len
)
336 len
= lstrlenW(this->data
[this->cur
]) + 1;
338 strings
[i
] = CoTaskMemAlloc(len
* sizeof(WCHAR
));
339 memcpy(strings
[i
], this->data
[this->cur
], len
* sizeof(WCHAR
));
348 static HRESULT WINAPI
string_enumerator_Reset(IEnumString
*iface
)
350 struct string_enumerator
*this = impl_from_IEnumString(iface
);
358 static HRESULT WINAPI
string_enumerator_Skip(IEnumString
*iface
, ULONG num
)
360 struct string_enumerator
*this = impl_from_IEnumString(iface
);
367 static HRESULT WINAPI
string_enumerator_Clone(IEnumString
*iface
, IEnumString
**out
)
373 static IEnumStringVtbl string_enumerator_vtbl
=
375 string_enumerator_QueryInterface
,
376 string_enumerator_AddRef
,
377 string_enumerator_Release
,
378 string_enumerator_Next
,
379 string_enumerator_Skip
,
380 string_enumerator_Reset
,
381 string_enumerator_Clone
384 static struct string_enumerator
*impl_from_IACList(IACList
*iface
)
386 return CONTAINING_RECORD(iface
, struct string_enumerator
, IACList_iface
);
389 static HRESULT WINAPI
aclist_QueryInterface(IACList
*iface
, REFIID riid
, void **ppv
)
391 return string_enumerator_QueryInterface(&impl_from_IACList(iface
)->IEnumString_iface
, riid
, ppv
);
394 static ULONG WINAPI
aclist_AddRef(IACList
*iface
)
396 return string_enumerator_AddRef(&impl_from_IACList(iface
)->IEnumString_iface
);
399 static ULONG WINAPI
aclist_Release(IACList
*iface
)
401 return string_enumerator_Release(&impl_from_IACList(iface
)->IEnumString_iface
);
404 static HRESULT WINAPI
aclist_Expand(IACList
*iface
, const WCHAR
*expand
)
406 struct string_enumerator
*this = impl_from_IACList(iface
);
408 /* see what we get called with and how many times,
409 don't actually do any expansion of the strings */
410 memcpy(this->last_expand
, expand
, min((lstrlenW(expand
) + 1)*sizeof(WCHAR
), sizeof(this->last_expand
)));
411 this->last_expand
[ARRAY_SIZE(this->last_expand
) - 1] = '\0';
417 static IACListVtbl aclist_vtbl
=
419 aclist_QueryInterface
,
425 static HRESULT
string_enumerator_create(void **ppv
, WCHAR
**suggestions
, int count
)
427 struct string_enumerator
*object
;
429 object
= heap_alloc_zero(sizeof(*object
));
430 object
->IEnumString_iface
.lpVtbl
= &string_enumerator_vtbl
;
431 object
->IACList_iface
.lpVtbl
= &aclist_vtbl
;
433 object
->data
= suggestions
;
434 object
->data_len
= count
;
437 *ppv
= &object
->IEnumString_iface
;
442 static void dispatch_messages(void)
446 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
448 TranslateMessage(&msg
);
449 DispatchMessageA(&msg
);
453 #define check_dropdown(acdropdown, hwnd_edit, list, list_num) check_dropdown_(__FILE__, __LINE__, acdropdown, hwnd_edit, list, list_num)
454 static void check_dropdown_(const char *file
, UINT line
, IAutoCompleteDropDown
*acdropdown
, HWND hwnd_edit
, WCHAR
**list
, UINT list_num
)
461 hr
= IAutoCompleteDropDown_GetDropDownStatus(acdropdown
, &flags
, &str
);
462 ok_(file
, line
)(hr
== S_OK
, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr
);
463 if (hr
!= S_OK
) return;
464 if (list_num
) ok_(file
, line
)(flags
& ACDD_VISIBLE
, "AutoComplete DropDown not visible\n");
467 ok_(file
, line
)(!(flags
& ACDD_VISIBLE
), "AutoComplete DropDown visible\n");
470 ok_(file
, line
)(str
== NULL
, "Expected (null), got %s\n", wine_dbgstr_w(str
));
477 for (i
= 0; i
<= list_num
; i
++)
480 SendMessageW(hwnd_edit
, WM_KEYDOWN
, VK_DOWN
, 0);
481 SendMessageW(hwnd_edit
, WM_KEYUP
, VK_DOWN
, 0xc0000000);
482 hr
= IAutoCompleteDropDown_GetDropDownStatus(acdropdown
, &flags
, &str
);
483 ok_(file
, line
)(hr
== S_OK
, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr
);
484 ok_(file
, line
)(flags
& ACDD_VISIBLE
, "AutoComplete DropDown not visible\n");
488 ok_(file
, line
)(str
&& !lstrcmpW(list
[i
], str
), "Expected %s, got %s\n",
489 wine_dbgstr_w(list
[i
]), wine_dbgstr_w(str
));
491 ok_(file
, line
)(str
== NULL
, "Expected (null), got %s\n", wine_dbgstr_w(str
));
497 static void test_aclist_expand(HWND hwnd_edit
, void *enumerator
, IAutoCompleteDropDown
*acdropdown
)
499 struct string_enumerator
*obj
= (struct string_enumerator
*)enumerator
;
500 static WCHAR str1
[] = {'t','e','s','t',0};
501 static WCHAR str1a
[] = {'t','e','s','t','\\',0};
502 static WCHAR str2
[] = {'t','e','s','t','\\','f','o','o','\\','b','a','r','\\','b','a',0};
503 static WCHAR str2a
[] = {'t','e','s','t','\\','f','o','o','\\','b','a','r','\\',0};
504 static WCHAR str2b
[] = {'t','e','s','t','\\','f','o','o','\\','b','a','r','\\','b','a','z','_','b','b','q','\\',0};
508 ok(obj
->num_expand
== 0, "Expected 0 expansions, got %u\n", obj
->num_expand
);
509 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)str1
);
510 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(str1
) - 1, ARRAY_SIZE(str1
) - 1);
511 SendMessageW(hwnd_edit
, WM_CHAR
, '\\', 1);
513 ok(obj
->num_expand
== 1, "Expected 1 expansion, got %u\n", obj
->num_expand
);
514 ok(lstrcmpW(obj
->last_expand
, str1a
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1a
), wine_dbgstr_w(obj
->last_expand
));
515 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
516 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)str2
);
517 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(str2
) - 1, ARRAY_SIZE(str2
) - 1);
518 SendMessageW(hwnd_edit
, WM_CHAR
, 'z', 1);
520 ok(obj
->num_expand
== 2, "Expected 2 expansions, got %u\n", obj
->num_expand
);
521 ok(lstrcmpW(obj
->last_expand
, str2a
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str2a
), wine_dbgstr_w(obj
->last_expand
));
522 ok(obj
->num_resets
== 2, "Expected 2 resets, got %u\n", obj
->num_resets
);
524 SendMessageW(hwnd_edit
, WM_CHAR
, '_', 1);
525 SendMessageW(hwnd_edit
, WM_CHAR
, 'b', 1);
528 SendMessageW(hwnd_edit
, WM_CHAR
, 'b', 1);
529 SendMessageW(hwnd_edit
, WM_CHAR
, 'q', 1);
531 ok(obj
->num_expand
== 2, "Expected 2 expansions, got %u\n", obj
->num_expand
);
532 ok(obj
->num_resets
== 2, "Expected 2 resets, got %u\n", obj
->num_resets
);
533 SendMessageW(hwnd_edit
, WM_CHAR
, '\\', 1);
535 ok(obj
->num_expand
== 3, "Expected 3 expansions, got %u\n", obj
->num_expand
);
536 ok(lstrcmpW(obj
->last_expand
, str2b
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str2b
), wine_dbgstr_w(obj
->last_expand
));
537 ok(obj
->num_resets
== 3, "Expected 3 resets, got %u\n", obj
->num_resets
);
538 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(str1a
) - 1, -1);
539 SendMessageW(hwnd_edit
, WM_CHAR
, 'x', 1);
540 SendMessageW(hwnd_edit
, WM_CHAR
, 'y', 1);
542 ok(obj
->num_expand
== 4, "Expected 4 expansions, got %u\n", obj
->num_expand
);
543 ok(lstrcmpW(obj
->last_expand
, str1a
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1a
), wine_dbgstr_w(obj
->last_expand
));
544 ok(obj
->num_resets
== 4, "Expected 4 resets, got %u\n", obj
->num_resets
);
545 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(str1
) - 1, -1);
546 SendMessageW(hwnd_edit
, WM_CHAR
, 'x', 1);
548 ok(obj
->num_expand
== 4, "Expected 4 expansions, got %u\n", obj
->num_expand
);
549 ok(obj
->num_resets
== 5, "Expected 5 resets, got %u\n", obj
->num_resets
);
550 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)str1a
);
551 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(str1a
) - 1, ARRAY_SIZE(str1a
) - 1);
552 SendMessageW(hwnd_edit
, WM_CHAR
, 'f', 1);
554 ok(obj
->num_expand
== 5, "Expected 5 expansions, got %u\n", obj
->num_expand
);
555 ok(lstrcmpW(obj
->last_expand
, str1a
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1a
), wine_dbgstr_w(obj
->last_expand
));
556 ok(obj
->num_resets
== 6, "Expected 6 resets, got %u\n", obj
->num_resets
);
557 hr
= IAutoCompleteDropDown_ResetEnumerator(acdropdown
);
558 ok(hr
== S_OK
, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr
);
559 SendMessageW(hwnd_edit
, WM_CHAR
, 'o', 1);
561 ok(obj
->num_expand
== 6, "Expected 6 expansions, got %u\n", obj
->num_expand
);
562 ok(lstrcmpW(obj
->last_expand
, str1a
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1a
), wine_dbgstr_w(obj
->last_expand
));
563 ok(obj
->num_resets
== 7, "Expected 7 resets, got %u\n", obj
->num_resets
);
566 static void test_prefix_filtering(HWND hwnd_edit
)
568 static WCHAR htt
[] = {'h','t','t',0};
569 static WCHAR www
[] = {'w','w','w','.',0};
570 static WCHAR str0
[] = {'w','w','w','.','a','x',0};
571 static WCHAR str1
[] = {'h','t','t','p','s',':','/','/','w','w','w','.','a','c',0};
572 static WCHAR str2
[] = {'a','a',0};
573 static WCHAR str3
[] = {'a','b',0};
574 static WCHAR str4
[] = {'h','t','t','p',':','/','/','a','0',0};
575 static WCHAR str5
[] = {'h','t','t','p','s',':','/','/','h','t','a',0};
576 static WCHAR str6
[] = {'h','f','o','o',0};
577 static WCHAR str7
[] = {'h','t','t','p',':','/','/','w','w','w','.','a','d','d',0};
578 static WCHAR str8
[] = {'w','w','w','.','w','w','w','.','?',0};
579 static WCHAR str9
[] = {'h','t','t','p',':','/','/','a','b','c','.','a','a','.','c','o','m',0};
580 static WCHAR str10
[]= {'f','t','p',':','/','/','a','b','c',0};
581 static WCHAR str11
[]= {'f','i','l','e',':','/','/','a','a',0};
582 static WCHAR str12
[]= {'f','t','p',':','/','/','w','w','w','.','a','a',0};
583 static WCHAR
*suggestions
[] = { str0
, str1
, str2
, str3
, str4
, str5
, str6
, str7
, str8
, str9
, str10
, str11
, str12
};
584 static WCHAR
*sorted1
[] = { str4
, str2
, str3
, str9
, str1
, str7
, str0
};
585 static WCHAR
*sorted2
[] = { str3
, str9
};
586 static WCHAR
*sorted3
[] = { str1
, str7
, str0
};
587 static WCHAR
*sorted4
[] = { str6
, str5
};
588 static WCHAR
*sorted5
[] = { str5
};
589 static WCHAR
*sorted6
[] = { str4
, str9
};
590 static WCHAR
*sorted7
[] = { str11
, str10
, str12
};
591 IUnknown
*enumerator
;
592 IAutoComplete2
*autocomplete
;
593 IAutoCompleteDropDown
*acdropdown
;
597 hr
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAutoComplete2
, (void**)&autocomplete
);
598 ok(hr
== S_OK
, "CoCreateInstance failed: %x\n", hr
);
600 hr
= IAutoComplete2_QueryInterface(autocomplete
, &IID_IAutoCompleteDropDown
, (LPVOID
*)&acdropdown
);
601 ok(hr
== S_OK
, "No IAutoCompleteDropDown interface: %x\n", hr
);
603 string_enumerator_create((void**)&enumerator
, suggestions
, ARRAY_SIZE(suggestions
));
605 hr
= IAutoComplete2_SetOptions(autocomplete
, ACO_FILTERPREFIXES
| ACO_AUTOSUGGEST
| ACO_AUTOAPPEND
);
606 ok(hr
== S_OK
, "IAutoComplete2_SetOptions failed: %x\n", hr
);
607 hr
= IAutoComplete2_Init(autocomplete
, hwnd_edit
, enumerator
, NULL
, NULL
);
608 ok(hr
== S_OK
, "IAutoComplete_Init failed: %x\n", hr
);
610 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
611 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
613 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
614 ok(lstrcmpW(str4
+ 7, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str4
+ 7), wine_dbgstr_w(buffer
));
615 check_dropdown(acdropdown
, hwnd_edit
, sorted1
, ARRAY_SIZE(sorted1
));
617 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
618 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
619 SendMessageW(hwnd_edit
, WM_CHAR
, 'b', 1);
621 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
622 ok(lstrcmpW(str3
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str3
), wine_dbgstr_w(buffer
));
623 check_dropdown(acdropdown
, hwnd_edit
, sorted2
, ARRAY_SIZE(sorted2
));
624 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
625 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
626 SendMessageW(hwnd_edit
, WM_CHAR
, 'b', 1);
627 SendMessageW(hwnd_edit
, WM_CHAR
, 'c', 1);
629 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
630 ok(lstrcmpW(str9
+ 7, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str9
+ 7), wine_dbgstr_w(buffer
));
632 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)www
);
633 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(www
) - 1, ARRAY_SIZE(www
) - 1);
634 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
636 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
637 ok(lstrcmpW(str1
+ 8, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1
+ 8), wine_dbgstr_w(buffer
));
638 check_dropdown(acdropdown
, hwnd_edit
, sorted3
, ARRAY_SIZE(sorted3
));
639 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)www
);
640 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(www
) - 1, ARRAY_SIZE(www
) - 1);
641 SendMessageW(hwnd_edit
, WM_CHAR
, 'w', 1);
643 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
644 ok(lstrcmpW(str8
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str8
), wine_dbgstr_w(buffer
));
646 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
647 SendMessageW(hwnd_edit
, WM_CHAR
, 'h', 1);
649 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
650 ok(lstrcmpW(str6
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str6
), wine_dbgstr_w(buffer
));
651 check_dropdown(acdropdown
, hwnd_edit
, sorted4
, ARRAY_SIZE(sorted4
));
652 SendMessageW(hwnd_edit
, WM_CHAR
, 't', 1);
653 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
654 ok(lstrcmpW(str5
+ 8, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str5
+ 8), wine_dbgstr_w(buffer
));
655 check_dropdown(acdropdown
, hwnd_edit
, sorted5
, ARRAY_SIZE(sorted5
));
656 SendMessageW(hwnd_edit
, WM_CHAR
, 't', 1);
657 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
658 ok(lstrcmpW(htt
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(htt
), wine_dbgstr_w(buffer
));
659 check_dropdown(acdropdown
, hwnd_edit
, NULL
, 0);
660 SendMessageW(hwnd_edit
, WM_CHAR
, 'p', 1);
661 SendMessageW(hwnd_edit
, WM_CHAR
, ':', 1);
662 SendMessageW(hwnd_edit
, WM_CHAR
, '/', 1);
663 SendMessageW(hwnd_edit
, WM_CHAR
, '/', 1);
664 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
666 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
667 ok(lstrcmpW(str4
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str4
), wine_dbgstr_w(buffer
));
668 check_dropdown(acdropdown
, hwnd_edit
, sorted6
, ARRAY_SIZE(sorted6
));
669 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, 2);
670 SendMessageW(hwnd_edit
, WM_CHAR
, 'H', 1);
672 check_dropdown(acdropdown
, hwnd_edit
, NULL
, 0);
673 SendMessageW(hwnd_edit
, WM_CHAR
, 't', 1);
675 check_dropdown(acdropdown
, hwnd_edit
, sorted6
, ARRAY_SIZE(sorted6
));
677 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
678 SendMessageW(hwnd_edit
, WM_CHAR
, 'F', 1);
680 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
681 check_dropdown(acdropdown
, hwnd_edit
, sorted7
, ARRAY_SIZE(sorted7
));
682 SendMessageW(hwnd_edit
, WM_CHAR
, 'i', 1);
683 SendMessageW(hwnd_edit
, WM_CHAR
, 'L', 1);
684 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
685 check_dropdown(acdropdown
, hwnd_edit
, sorted7
, 1);
687 IAutoCompleteDropDown_Release(acdropdown
);
688 IAutoComplete2_Release(autocomplete
);
689 IUnknown_Release(enumerator
);
692 static void test_custom_source(void)
694 static WCHAR str_alpha
[] = {'t','e','s','t','1',0};
695 static WCHAR str_alpha2
[] = {'t','e','s','t','2',0};
696 static WCHAR str_beta
[] = {'a','u','t','o',' ','c','o','m','p','l','e','t','e',0};
697 static WCHAR str_au
[] = {'a','u',0};
698 static WCHAR str_aut
[] = {'a','u','t',0};
699 static WCHAR
*suggestions
[] = { str_alpha
, str_alpha2
, str_beta
};
700 struct string_enumerator
*obj
;
701 IUnknown
*enumerator
;
702 IAutoComplete2
*autocomplete
;
703 IAutoCompleteDropDown
*acdropdown
;
709 ShowWindow(hMainWnd
, SW_SHOW
);
711 hwnd_edit
= CreateWindowA("Edit", "", WS_OVERLAPPED
| WS_VISIBLE
| WS_CHILD
| WS_BORDER
, 50, 5, 200, 20, hMainWnd
, 0, NULL
, 0);
713 hr
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAutoComplete2
, (void**)&autocomplete
);
714 ok(hr
== S_OK
, "CoCreateInstance failed: %x\n", hr
);
716 hr
= IAutoComplete2_QueryInterface(autocomplete
, &IID_IAutoCompleteDropDown
, (LPVOID
*)&acdropdown
);
717 ok(hr
== S_OK
, "No IAutoCompleteDropDown interface: %x\n", hr
);
719 string_enumerator_create((void**)&enumerator
, suggestions
, ARRAY_SIZE(suggestions
));
720 obj
= (struct string_enumerator
*)enumerator
;
722 hr
= IAutoComplete2_SetOptions(autocomplete
, ACO_AUTOSUGGEST
| ACO_AUTOAPPEND
);
723 ok(hr
== S_OK
, "IAutoComplete2_SetOptions failed: %x\n", hr
);
724 hr
= IAutoCompleteDropDown_ResetEnumerator(acdropdown
);
725 ok(hr
== S_OK
, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr
);
726 hr
= IAutoComplete2_Init(autocomplete
, hwnd_edit
, enumerator
, NULL
, NULL
);
727 ok(hr
== S_OK
, "IAutoComplete_Init failed: %x\n", hr
);
730 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
731 SendMessageW(hwnd_edit
, WM_CHAR
, 'u', 1);
733 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
734 ok(lstrcmpW(str_beta
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_beta
), wine_dbgstr_w(buffer
));
735 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
736 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
737 SendMessageW(hwnd_edit
, WM_CHAR
, '\b', 1);
739 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
740 ok(buffer
[0] == '\0', "Expected empty string, got %s\n", wine_dbgstr_w(buffer
));
741 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
742 hr
= IAutoCompleteDropDown_ResetEnumerator(acdropdown
);
743 ok(hr
== S_OK
, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr
);
744 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
747 /* hijack the window procedure */
748 HijackerWndProc_prev
= (WNDPROC
)SetWindowLongPtrW(hwnd_edit
, GWLP_WNDPROC
, (LONG_PTR
)HijackerWndProc
);
749 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
750 ok(lstrcmpW(HijackerWndProc_txt
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(HijackerWndProc_txt
), wine_dbgstr_w(buffer
));
752 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
753 SendMessageW(hwnd_edit
, WM_CHAR
, 'u', 1);
754 SetWindowLongPtrW(hwnd_edit
, GWLP_WNDPROC
, (LONG_PTR
)HijackerWndProc_prev
);
756 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
757 ok(lstrcmpW(str_au
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_au
), wine_dbgstr_w(buffer
));
758 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
759 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
760 SendMessageW(hwnd_edit
, WM_CHAR
, '\b', 1);
762 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
763 ok(buffer
[0] == '\0', "Expected empty string, got %s\n", wine_dbgstr_w(buffer
));
764 hr
= IAutoCompleteDropDown_ResetEnumerator(acdropdown
);
765 ok(hr
== S_OK
, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr
);
767 HijackerWndProc_prev
= (WNDPROC
)SetWindowLongPtrW(hwnd_edit
, GWLP_WNDPROC
, (LONG_PTR
)HijackerWndProc2
);
768 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
769 SendMessageW(hwnd_edit
, WM_CHAR
, 'u', 1);
770 SetWindowLongPtrW(hwnd_edit
, GWLP_WNDPROC
, (LONG_PTR
)HijackerWndProc_prev
);
772 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
773 ok(lstrcmpW(str_beta
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_beta
), wine_dbgstr_w(buffer
));
774 ok(obj
->num_resets
== 2, "Expected 2 resets, got %u\n", obj
->num_resets
);
777 hr
= IAutoCompleteDropDown_GetDropDownStatus(acdropdown
, &flags
, NULL
);
778 ok(hr
== S_OK
, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr
);
779 ok(flags
& ACDD_VISIBLE
, "AutoComplete DropDown should be visible\n");
780 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)str_au
);
782 hr
= IAutoCompleteDropDown_GetDropDownStatus(acdropdown
, &flags
, NULL
);
783 ok(hr
== S_OK
, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr
);
784 ok(!(flags
& ACDD_VISIBLE
), "AutoComplete DropDown should have been hidden\n");
785 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)str_aut
);
787 hr
= IAutoCompleteDropDown_GetDropDownStatus(acdropdown
, &flags
, NULL
);
788 ok(hr
== S_OK
, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr
);
789 ok(!(flags
& ACDD_VISIBLE
), "AutoComplete DropDown should be hidden\n");
790 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
791 ok(lstrcmpW(str_aut
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_aut
), wine_dbgstr_w(buffer
));
793 test_aclist_expand(hwnd_edit
, enumerator
, acdropdown
);
796 hr
= IAutoCompleteDropDown_ResetEnumerator(acdropdown
);
797 ok(hr
== S_OK
, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr
);
798 SendMessageW(hwnd_edit
, WM_CHAR
, 'x', 1);
800 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
801 SendMessageW(hwnd_edit
, WM_CHAR
, 'x', 1);
803 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
805 IAutoCompleteDropDown_Release(acdropdown
);
806 IAutoComplete2_Release(autocomplete
);
807 IUnknown_Release(enumerator
);
809 test_prefix_filtering(hwnd_edit
);
811 ShowWindow(hMainWnd
, SW_HIDE
);
812 DestroyWindow(hwnd_edit
);
815 START_TEST(autocomplete
)
823 r
= CoInitialize(NULL
);
824 ok(r
== S_OK
, "CoInitialize failed (0x%08x). Tests aborted.\n", r
);
829 ok(hMainWnd
!= NULL
, "Failed to create parent window. Tests aborted.\n");
830 if (!hMainWnd
) return;
832 /* Move the cursor away from the dropdown listbox */
833 GetWindowRect(hMainWnd
, &win_rect
);
834 GetCursorPos(&orig_pos
);
835 SetCursorPos(win_rect
.left
, win_rect
.top
);
843 test_custom_source();
846 while(GetMessageA(&msg
,0,0,0)) {
847 TranslateMessage(&msg
);
848 DispatchMessageA(&msg
);
851 IAutoComplete_Release(ac
);
854 SetCursorPos(orig_pos
.x
, orig_pos
.y
);
855 DestroyWindow(hEdit
);
856 DestroyWindow(hMainWnd
);