msctf: Use FAILED instead of !SUCCEDED.
[wine] / dlls / comctl32 / tests / listview.c
1 /*
2  * ListView tests
3  *
4  * Copyright 2006 Mike McCormack for CodeWeavers
5  * Copyright 2007 George Gov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdio.h>
23 #include <windows.h>
24 #include <commctrl.h>
25
26 #include "wine/test.h"
27 #include "msg.h"
28
29 #define PARENT_SEQ_INDEX       0
30 #define PARENT_FULL_SEQ_INDEX  1
31 #define LISTVIEW_SEQ_INDEX     2
32 #define NUM_MSG_SEQUENCES      3
33
34 #define LISTVIEW_ID 0
35 #define HEADER_ID   1
36
37 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
38 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
39        "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
40
41 HWND hwndparent;
42
43 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
44
45 static const struct message create_parent_wnd_seq[] = {
46     { WM_GETMINMAXINFO,     sent },
47     { WM_NCCREATE,          sent },
48     { WM_NCCALCSIZE,        sent|wparam, 0 },
49     { WM_CREATE,            sent },
50     { WM_SHOWWINDOW,        sent|wparam, 1 },
51     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
52     { WM_QUERYNEWPALETTE,   sent|optional },
53     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
54     { WM_WINDOWPOSCHANGED,  sent|optional },
55     { WM_NCCALCSIZE,        sent|wparam|optional, 1 },
56     { WM_ACTIVATEAPP,       sent|wparam, 1 },
57     { WM_NCACTIVATE,        sent|wparam, 1 },
58     { WM_ACTIVATE,          sent|wparam, 1 },
59     { WM_IME_SETCONTEXT,    sent|wparam|defwinproc|optional, 1 },
60     { WM_IME_NOTIFY,        sent|defwinproc|optional },
61     { WM_SETFOCUS,          sent|wparam|defwinproc, 0 },
62     /* Win9x adds SWP_NOZORDER below */
63     { WM_WINDOWPOSCHANGED,  sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
64     { WM_NCCALCSIZE,        sent|wparam|optional, 1 },
65     { WM_SIZE,              sent },
66     { WM_MOVE,              sent },
67     { 0 }
68 };
69
70 static const struct message redraw_listview_seq[] = {
71     { WM_PAINT,      sent|id,            0, 0, LISTVIEW_ID },
72     { WM_PAINT,      sent|id,            0, 0, HEADER_ID },
73     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, HEADER_ID },
74     { WM_ERASEBKGND, sent|id|defwinproc, 0, 0, HEADER_ID },
75     { WM_NOTIFY,     sent|id|defwinproc, 0, 0, LISTVIEW_ID },
76     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, LISTVIEW_ID },
77     { WM_ERASEBKGND, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
78     { 0 }
79 };
80
81 static const struct message listview_icon_spacing_seq[] = {
82     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) },
83     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) },
84     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) },
85     { 0 }
86 };
87
88 static const struct message listview_color_seq[] = {
89     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(0,0,0) },
90     { LVM_GETBKCOLOR,     sent },
91     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(0,0,0) },
92     { LVM_GETTEXTCOLOR,   sent },
93     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
94     { LVM_GETTEXTBKCOLOR, sent },
95
96     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(100,50,200) },
97     { LVM_GETBKCOLOR,     sent },
98     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(100,50,200) },
99     { LVM_GETTEXTCOLOR,   sent },
100     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
101     { LVM_GETTEXTBKCOLOR, sent },
102
103     { LVM_SETBKCOLOR,     sent|lparam, 0, CLR_NONE },
104     { LVM_GETBKCOLOR,     sent },
105     { LVM_SETTEXTCOLOR,   sent|lparam, 0, CLR_NONE },
106     { LVM_GETTEXTCOLOR,   sent },
107     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
108     { LVM_GETTEXTBKCOLOR, sent },
109
110     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(255,255,255) },
111     { LVM_GETBKCOLOR,     sent },
112     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(255,255,255) },
113     { LVM_GETTEXTCOLOR,   sent },
114     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
115     { LVM_GETTEXTBKCOLOR, sent },
116     { 0 }
117 };
118
119 static const struct message listview_item_count_seq[] = {
120     { LVM_GETITEMCOUNT,   sent },
121     { LVM_INSERTITEM,     sent },
122     { LVM_INSERTITEM,     sent },
123     { LVM_INSERTITEM,     sent },
124     { LVM_GETITEMCOUNT,   sent },
125     { LVM_DELETEITEM,     sent|wparam, 2 },
126     { LVM_GETITEMCOUNT,   sent },
127     { LVM_DELETEALLITEMS, sent },
128     { LVM_GETITEMCOUNT,   sent },
129     { LVM_INSERTITEM,     sent },
130     { LVM_INSERTITEM,     sent },
131     { LVM_GETITEMCOUNT,   sent },
132     { LVM_INSERTITEM,     sent },
133     { LVM_GETITEMCOUNT,   sent },
134     { 0 }
135 };
136
137 static const struct message listview_itempos_seq[] = {
138     { LVM_INSERTITEM,      sent },
139     { LVM_INSERTITEM,      sent },
140     { LVM_INSERTITEM,      sent },
141     { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
142     { LVM_GETITEMPOSITION, sent|wparam,        1 },
143     { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
144     { LVM_GETITEMPOSITION, sent|wparam,        2 },
145     { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
146     { LVM_GETITEMPOSITION, sent|wparam,        0 },
147     { 0 }
148 };
149
150 static const struct message listview_ownerdata_switchto_seq[] = {
151     { WM_STYLECHANGING,    sent },
152     { WM_STYLECHANGED,     sent },
153     { 0 }
154 };
155
156 static const struct message listview_getorderarray_seq[] = {
157     { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
158     { HDM_GETORDERARRAY,       sent|id|wparam, 2, 0, HEADER_ID },
159     { 0 }
160 };
161
162 static const struct message empty_seq[] = {
163     { 0 }
164 };
165
166 static const struct message forward_erasebkgnd_parent_seq[] = {
167     { WM_ERASEBKGND, sent },
168     { 0 }
169 };
170
171 static const struct message ownderdata_select_focus_parent_seq[] = {
172     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
173     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
174     { 0 }
175 };
176
177 static const struct message textcallback_set_again_parent_seq[] = {
178     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
179     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED  },
180     { 0 }
181 };
182
183 static const struct message single_getdispinfo_parent_seq[] = {
184     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
185     { 0 }
186 };
187
188 struct subclass_info
189 {
190     WNDPROC oldproc;
191 };
192
193 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
194 {
195     static LONG defwndproc_counter = 0;
196     LRESULT ret;
197     struct message msg;
198
199     msg.message = message;
200     msg.flags = sent|wparam|lparam;
201     if (defwndproc_counter) msg.flags |= defwinproc;
202     msg.wParam = wParam;
203     msg.lParam = lParam;
204     if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
205
206     /* log system messages, except for painting */
207     if (message < WM_USER &&
208         message != WM_PAINT &&
209         message != WM_ERASEBKGND &&
210         message != WM_NCPAINT &&
211         message != WM_NCHITTEST &&
212         message != WM_GETTEXT &&
213         message != WM_GETICON &&
214         message != WM_DEVICECHANGE)
215     {
216         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
217
218         add_message(sequences, PARENT_SEQ_INDEX, &msg);
219     }
220     add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
221
222     defwndproc_counter++;
223     ret = DefWindowProcA(hwnd, message, wParam, lParam);
224     defwndproc_counter--;
225
226     return ret;
227 }
228
229 static BOOL register_parent_wnd_class(void)
230 {
231     WNDCLASSA cls;
232
233     cls.style = 0;
234     cls.lpfnWndProc = parent_wnd_proc;
235     cls.cbClsExtra = 0;
236     cls.cbWndExtra = 0;
237     cls.hInstance = GetModuleHandleA(NULL);
238     cls.hIcon = 0;
239     cls.hCursor = LoadCursorA(0, IDC_ARROW);
240     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
241     cls.lpszMenuName = NULL;
242     cls.lpszClassName = "Listview test parent class";
243     return RegisterClassA(&cls);
244 }
245
246 static HWND create_parent_window(void)
247 {
248     if (!register_parent_wnd_class())
249         return NULL;
250
251     return CreateWindowEx(0, "Listview test parent class",
252                           "Listview test parent window",
253                           WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
254                           WS_MAXIMIZEBOX | WS_VISIBLE,
255                           0, 0, 100, 100,
256                           GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
257 }
258
259 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
260 {
261     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
262     static LONG defwndproc_counter = 0;
263     LRESULT ret;
264     struct message msg;
265
266     trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
267
268     /* some debug output for style changing */
269     if ((message == WM_STYLECHANGING ||
270          message == WM_STYLECHANGED) && lParam)
271     {
272         STYLESTRUCT *style = (STYLESTRUCT*)lParam;
273         trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
274     }
275
276     msg.message = message;
277     msg.flags = sent|wparam|lparam;
278     if (defwndproc_counter) msg.flags |= defwinproc;
279     msg.wParam = wParam;
280     msg.lParam = lParam;
281     msg.id = LISTVIEW_ID;
282     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
283
284     defwndproc_counter++;
285     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
286     defwndproc_counter--;
287     return ret;
288 }
289
290 static HWND create_listview_control(DWORD style)
291 {
292     struct subclass_info *info;
293     HWND hwnd;
294     RECT rect;
295
296     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
297     if (!info)
298         return NULL;
299
300     GetClientRect(hwndparent, &rect);
301     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
302                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
303                            0, 0, rect.right, rect.bottom,
304                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
305     ok(hwnd != NULL, "gle=%d\n", GetLastError());
306
307     if (!hwnd)
308     {
309         HeapFree(GetProcessHeap(), 0, info);
310         return NULL;
311     }
312
313     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
314                                             (LONG_PTR)listview_subclass_proc);
315     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
316
317     return hwnd;
318 }
319
320 static HWND create_custom_listview_control(DWORD style)
321 {
322     struct subclass_info *info;
323     HWND hwnd;
324     RECT rect;
325
326     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
327     if (!info)
328         return NULL;
329
330     GetClientRect(hwndparent, &rect);
331     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
332                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
333                            0, 0, rect.right, rect.bottom,
334                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
335     ok(hwnd != NULL, "gle=%d\n", GetLastError());
336
337     if (!hwnd)
338     {
339         HeapFree(GetProcessHeap(), 0, info);
340         return NULL;
341     }
342
343     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
344                                             (LONG_PTR)listview_subclass_proc);
345     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
346
347     return hwnd;
348 }
349
350 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
351 {
352     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
353     static LONG defwndproc_counter = 0;
354     LRESULT ret;
355     struct message msg;
356
357     trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
358
359     msg.message = message;
360     msg.flags = sent|wparam|lparam;
361     if (defwndproc_counter) msg.flags |= defwinproc;
362     msg.wParam = wParam;
363     msg.lParam = lParam;
364     msg.id = HEADER_ID;
365     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
366
367     defwndproc_counter++;
368     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
369     defwndproc_counter--;
370     return ret;
371 }
372
373 static HWND subclass_header(HWND hwndListview)
374 {
375     struct subclass_info *info;
376     HWND hwnd;
377
378     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
379     if (!info)
380         return NULL;
381
382     hwnd = ListView_GetHeader(hwndListview);
383     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
384                                             (LONG_PTR)header_subclass_proc);
385     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
386
387     return hwnd;
388 }
389
390 static void test_images(void)
391 {
392     HWND hwnd;
393     DWORD r;
394     LVITEM item;
395     HIMAGELIST himl;
396     HBITMAP hbmp;
397     RECT r1, r2;
398     static CHAR hello[] = "hello";
399
400     himl = ImageList_Create(40, 40, 0, 4, 4);
401     ok(himl != NULL, "failed to create imagelist\n");
402
403     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
404     ok(hbmp != NULL, "failed to create bitmap\n");
405
406     r = ImageList_Add(himl, hbmp, 0);
407     ok(r == 0, "should be zero\n");
408
409     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED, 
410                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
411     ok(hwnd != NULL, "failed to create listview window\n");
412
413     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
414                     LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE);
415
416     ok(r == 0, "should return zero\n");
417
418     r = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
419     ok(r == 0, "should return zero\n");
420
421     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
422     /* returns dimensions */
423
424     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
425     ok(r == 0, "should be zero items\n");
426
427     item.mask = LVIF_IMAGE | LVIF_TEXT;
428     item.iItem = 0;
429     item.iSubItem = 1;
430     item.iImage = 0;
431     item.pszText = 0;
432     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
433     ok(r == -1, "should fail\n");
434
435     item.iSubItem = 0;
436     item.pszText = hello;
437     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
438     ok(r == 0, "should not fail\n");
439
440     memset(&r1, 0, sizeof r1);
441     r1.left = LVIR_ICON;
442     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
443
444     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
445     ok(r == TRUE, "should not fail\n");
446
447     item.iSubItem = 0;
448     item.pszText = hello;
449     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
450     ok(r == 0, "should not fail\n");
451
452     memset(&r2, 0, sizeof r2);
453     r2.left = LVIR_ICON;
454     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
455
456     ok(!memcmp(&r1, &r2, sizeof r1), "rectangle should be the same\n");
457
458     DestroyWindow(hwnd);
459 }
460
461 static void test_checkboxes(void)
462 {
463     HWND hwnd;
464     LVITEMA item;
465     DWORD r;
466     static CHAR text[]  = "Text",
467                 text2[] = "Text2",
468                 text3[] = "Text3";
469
470     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT, 
471                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
472     ok(hwnd != NULL, "failed to create listview window\n");
473
474     /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
475     item.mask = LVIF_TEXT | LVIF_STATE;
476     item.stateMask = 0xffff;
477     item.state = 0xfccc;
478     item.iItem = 0;
479     item.iSubItem = 0;
480     item.pszText = text;
481     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
482     ok(r == 0, "ret %d\n", r);
483
484     item.iItem = 0;
485     item.mask = LVIF_STATE;
486     item.stateMask = 0xffff;
487     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
488     ok(item.state == 0xfccc, "state %x\n", item.state);
489
490     /* Don't set LVIF_STATE */
491     item.mask = LVIF_TEXT;
492     item.stateMask = 0xffff;
493     item.state = 0xfccc;
494     item.iItem = 1;
495     item.iSubItem = 0;
496     item.pszText = text;
497     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
498     ok(r == 1, "ret %d\n", r);
499
500     item.iItem = 1;
501     item.mask = LVIF_STATE;
502     item.stateMask = 0xffff;
503     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
504     ok(item.state == 0, "state %x\n", item.state);
505
506     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
507     ok(r == 0, "should return zero\n");
508
509     /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
510     item.iItem = 0;
511     item.mask = LVIF_STATE;
512     item.stateMask = 0xffff;
513     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
514     ok(item.state == 0x1ccc, "state %x\n", item.state);
515
516     /* Now add an item without specifying a state and check that its state goes to 0x1000 */
517     item.iItem = 2;
518     item.mask = LVIF_TEXT;
519     item.state = 0;
520     item.pszText = text2;
521     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
522     ok(r == 2, "ret %d\n", r);
523
524     item.iItem = 2;
525     item.mask = LVIF_STATE;
526     item.stateMask = 0xffff;
527     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
528     ok(item.state == 0x1000, "state %x\n", item.state);
529
530     /* Add a further item this time specifying a state and still its state goes to 0x1000 */
531     item.iItem = 3;
532     item.mask = LVIF_TEXT | LVIF_STATE;
533     item.stateMask = 0xffff;
534     item.state = 0x2aaa;
535     item.pszText = text3;
536     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
537     ok(r == 3, "ret %d\n", r);
538
539     item.iItem = 3;
540     item.mask = LVIF_STATE;
541     item.stateMask = 0xffff;
542     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
543     ok(item.state == 0x1aaa, "state %x\n", item.state);
544
545     /* Set an item's state to checked */
546     item.iItem = 3;
547     item.mask = LVIF_STATE;
548     item.stateMask = 0xf000;
549     item.state = 0x2000;
550     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
551
552     item.iItem = 3;
553     item.mask = LVIF_STATE;
554     item.stateMask = 0xffff;
555     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
556     ok(item.state == 0x2aaa, "state %x\n", item.state);
557
558     /* Check that only the bits we asked for are returned,
559      * and that all the others are set to zero
560      */
561     item.iItem = 3;
562     item.mask = LVIF_STATE;
563     item.stateMask = 0xf000;
564     item.state = 0xffff;
565     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
566     ok(item.state == 0x2000, "state %x\n", item.state);
567
568     /* Set the style again and check that doesn't change an item's state */
569     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
570     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
571
572     item.iItem = 3;
573     item.mask = LVIF_STATE;
574     item.stateMask = 0xffff;
575     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
576     ok(item.state == 0x2aaa, "state %x\n", item.state);
577
578     /* Unsetting the checkbox extended style doesn't change an item's state */
579     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
580     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
581
582     item.iItem = 3;
583     item.mask = LVIF_STATE;
584     item.stateMask = 0xffff;
585     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
586     ok(item.state == 0x2aaa, "state %x\n", item.state);
587
588     /* Now setting the style again will change an item's state */
589     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
590     ok(r == 0, "ret %x\n", r);
591
592     item.iItem = 3;
593     item.mask = LVIF_STATE;
594     item.stateMask = 0xffff;
595     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
596     ok(item.state == 0x1aaa, "state %x\n", item.state);
597
598     /* Toggle checkbox tests (bug 9934) */
599     memset (&item, 0xcc, sizeof(item));
600     item.mask = LVIF_STATE;
601     item.iItem = 3;
602     item.iSubItem = 0;
603     item.state = LVIS_FOCUSED;
604     item.stateMask = LVIS_FOCUSED;
605     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
606     expect(1, r);
607
608     item.iItem = 3;
609     item.mask = LVIF_STATE;
610     item.stateMask = 0xffff;
611     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
612     ok(item.state == 0x1aab, "state %x\n", item.state);
613
614     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
615     expect(0, r);
616     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
617     expect(0, r);
618
619     item.iItem = 3;
620     item.mask = LVIF_STATE;
621     item.stateMask = 0xffff;
622     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
623     ok(item.state == 0x2aab, "state %x\n", item.state);
624
625     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
626     expect(0, r);
627     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
628     expect(0, r);
629
630     item.iItem = 3;
631     item.mask = LVIF_STATE;
632     item.stateMask = 0xffff;
633     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
634     ok(item.state == 0x1aab, "state %x\n", item.state);
635
636     DestroyWindow(hwnd);
637 }
638
639 static void insert_column(HWND hwnd, int idx)
640 {
641     LVCOLUMN column;
642     DWORD rc;
643
644     memset(&column, 0xcc, sizeof(column));
645     column.mask = LVCF_SUBITEM;
646     column.iSubItem = idx;
647
648     rc = ListView_InsertColumn(hwnd, idx, &column);
649     expect(idx, rc);
650 }
651
652 static void insert_item(HWND hwnd, int idx)
653 {
654     static CHAR text[] = "foo";
655
656     LVITEMA item;
657     DWORD rc;
658
659     memset(&item, 0xcc, sizeof (item));
660     item.mask = LVIF_TEXT;
661     item.iItem = idx;
662     item.iSubItem = 0;
663     item.pszText = text;
664
665     rc = ListView_InsertItem(hwnd, &item);
666     expect(idx, rc);
667 }
668
669 static void test_items(void)
670 {
671     const LPARAM lparamTest = 0x42;
672     HWND hwnd;
673     LVITEMA item;
674     DWORD r;
675     static CHAR text[] = "Text";
676
677     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
678                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
679     ok(hwnd != NULL, "failed to create listview window\n");
680
681     /*
682      * Test setting/getting item params
683      */
684
685     /* Set up two columns */
686     insert_column(hwnd, 0);
687     insert_column(hwnd, 1);
688
689     /* LVIS_SELECTED with zero stateMask */
690     /* set */
691     memset (&item, 0, sizeof (item));
692     item.mask = LVIF_STATE;
693     item.state = LVIS_SELECTED;
694     item.stateMask = 0;
695     item.iItem = 0;
696     item.iSubItem = 0;
697     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
698     ok(r == 0, "ret %d\n", r);
699     /* get */
700     memset (&item, 0xcc, sizeof (item));
701     item.mask = LVIF_STATE;
702     item.stateMask = LVIS_SELECTED;
703     item.state = 0;
704     item.iItem = 0;
705     item.iSubItem = 0;
706     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
707     ok(r != 0, "ret %d\n", r);
708     ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
709     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
710
711     /* LVIS_SELECTED with zero stateMask */
712     /* set */
713     memset (&item, 0, sizeof (item));
714     item.mask = LVIF_STATE;
715     item.state = LVIS_FOCUSED;
716     item.stateMask = 0;
717     item.iItem = 0;
718     item.iSubItem = 0;
719     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
720     ok(r == 0, "ret %d\n", r);
721     /* get */
722     memset (&item, 0xcc, sizeof (item));
723     item.mask = LVIF_STATE;
724     item.stateMask = LVIS_FOCUSED;
725     item.state = 0;
726     item.iItem = 0;
727     item.iSubItem = 0;
728     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
729     ok(r != 0, "ret %d\n", r);
730     ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
731     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
732
733     /* LVIS_CUT with LVIS_FOCUSED stateMask */
734     /* set */
735     memset (&item, 0, sizeof (item));
736     item.mask = LVIF_STATE;
737     item.state = LVIS_CUT;
738     item.stateMask = LVIS_FOCUSED;
739     item.iItem = 0;
740     item.iSubItem = 0;
741     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
742     ok(r == 0, "ret %d\n", r);
743     /* get */
744     memset (&item, 0xcc, sizeof (item));
745     item.mask = LVIF_STATE;
746     item.stateMask = LVIS_CUT;
747     item.state = 0;
748     item.iItem = 0;
749     item.iSubItem = 0;
750     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
751     ok(r != 0, "ret %d\n", r);
752     ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
753     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
754
755     /* Insert an item with just a param */
756     memset (&item, 0xcc, sizeof (item));
757     item.mask = LVIF_PARAM;
758     item.iItem = 0;
759     item.iSubItem = 0;
760     item.lParam = lparamTest;
761     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
762     ok(r == 0, "ret %d\n", r);
763
764     /* Test getting of the param */
765     memset (&item, 0xcc, sizeof (item));
766     item.mask = LVIF_PARAM;
767     item.iItem = 0;
768     item.iSubItem = 0;
769     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
770     ok(r != 0, "ret %d\n", r);
771     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
772
773     /* Set up a subitem */
774     memset (&item, 0xcc, sizeof (item));
775     item.mask = LVIF_TEXT;
776     item.iItem = 0;
777     item.iSubItem = 1;
778     item.pszText = text;
779     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
780     ok(r != 0, "ret %d\n", r);
781
782     /* Query param from subitem: returns main item param */
783     memset (&item, 0xcc, sizeof (item));
784     item.mask = LVIF_PARAM;
785     item.iItem = 0;
786     item.iSubItem = 1;
787     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
788     ok(r != 0, "ret %d\n", r);
789     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
790
791     /* Set up param on first subitem: no effect */
792     memset (&item, 0xcc, sizeof (item));
793     item.mask = LVIF_PARAM;
794     item.iItem = 0;
795     item.iSubItem = 1;
796     item.lParam = lparamTest+1;
797     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
798     ok(r == 0, "ret %d\n", r);
799
800     /* Query param from subitem again: should still return main item param */
801     memset (&item, 0xcc, sizeof (item));
802     item.mask = LVIF_PARAM;
803     item.iItem = 0;
804     item.iSubItem = 1;
805     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
806     ok(r != 0, "ret %d\n", r);
807     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
808
809     /**** Some tests of state highlighting ****/
810     memset (&item, 0xcc, sizeof (item));
811     item.mask = LVIF_STATE;
812     item.iItem = 0;
813     item.iSubItem = 0;
814     item.state = LVIS_SELECTED;
815     item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
816     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
817     ok(r != 0, "ret %d\n", r);
818     item.iSubItem = 1;
819     item.state = LVIS_DROPHILITED;
820     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
821     ok(r != 0, "ret %d\n", r);
822
823     memset (&item, 0xcc, sizeof (item));
824     item.mask = LVIF_STATE;
825     item.iItem = 0;
826     item.iSubItem = 0;
827     item.stateMask = -1;
828     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
829     ok(r != 0, "ret %d\n", r);
830     ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
831     item.iSubItem = 1;
832     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
833     ok(r != 0, "ret %d\n", r);
834     todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
835
836     /* some notnull but meaningless masks */
837     memset (&item, 0, sizeof(item));
838     item.mask = LVIF_NORECOMPUTE;
839     item.iItem = 0;
840     item.iSubItem = 0;
841     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
842     ok(r != 0, "ret %d\n", r);
843     memset (&item, 0, sizeof(item));
844     item.mask = LVIF_DI_SETITEM;
845     item.iItem = 0;
846     item.iSubItem = 0;
847     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
848     ok(r != 0, "ret %d\n", r);
849
850     /* set text to callback value already having it */
851     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
852     expect(TRUE, r);
853     memset (&item, 0, sizeof (item));
854     item.mask  = LVIF_TEXT;
855     item.pszText = LPSTR_TEXTCALLBACK;
856     item.iItem = 0;
857     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
858     ok(r == 0, "ret %d\n", r);
859     memset (&item, 0, sizeof (item));
860
861     flush_sequences(sequences, NUM_MSG_SEQUENCES);
862
863     item.pszText = LPSTR_TEXTCALLBACK;
864     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0 , (LPARAM) &item);
865     expect(TRUE, r);
866
867     ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq,
868                 "check callback text comparison rule", TRUE);
869
870     DestroyWindow(hwnd);
871 }
872
873 static void test_columns(void)
874 {
875     HWND hwnd, hwndheader;
876     LVCOLUMN column;
877     DWORD rc;
878     INT order[2];
879
880     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
881                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
882     ok(hwnd != NULL, "failed to create listview window\n");
883
884     /* Add a column with no mask */
885     memset(&column, 0xcc, sizeof(column));
886     column.mask = 0;
887     rc = ListView_InsertColumn(hwnd, 0, &column);
888     ok(rc==0, "Inserting column with no mask failed with %d\n", rc);
889
890     /* Check its width */
891     rc = ListView_GetColumnWidth(hwnd, 0);
892     ok(rc==10 ||
893        broken(rc==0), /* win9x */
894        "Inserting column with no mask failed to set width to 10 with %d\n", rc);
895
896     DestroyWindow(hwnd);
897
898     /* LVM_GETCOLUMNORDERARRAY */
899     hwnd = create_listview_control(0);
900     hwndheader = subclass_header(hwnd);
901
902     memset(&column, 0, sizeof(column));
903     column.mask = LVCF_WIDTH;
904     column.cx = 100;
905     rc = ListView_InsertColumn(hwnd, 0, &column);
906     ok(rc == 0, "Inserting column failed with %d\n", rc);
907
908     column.cx = 200;
909     rc = ListView_InsertColumn(hwnd, 1, &column);
910     ok(rc == 1, "Inserting column failed with %d\n", rc);
911
912     flush_sequences(sequences, NUM_MSG_SEQUENCES);
913
914     rc = SendMessage(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
915     ok(rc != 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
916     ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
917     ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
918
919     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
920
921     DestroyWindow(hwnd);
922 }
923 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
924 static WNDPROC listviewWndProc;
925 static HIMAGELIST test_create_imagelist;
926
927 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
928 {
929     LRESULT ret;
930
931     if (uMsg == WM_CREATE)
932     {
933         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
934         lpcs->style |= LVS_REPORT;
935     }
936     ret = CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
937     if (uMsg == WM_CREATE) SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
938     return ret;
939 }
940
941 static void test_create(void)
942 {
943     HWND hList;
944     HWND hHeader;
945     LONG_PTR ret;
946     LONG r;
947     LVCOLUMNA col;
948     RECT rect;
949     WNDCLASSEX cls;
950     cls.cbSize = sizeof(WNDCLASSEX);
951     ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
952     listviewWndProc = cls.lpfnWndProc;
953     cls.lpfnWndProc = create_test_wndproc;
954     cls.lpszClassName = "MyListView32";
955     ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
956
957     test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
958     hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
959     ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
960     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
961     ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
962     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
963     DestroyWindow(hList);
964
965     /* header isn't created on LVS_ICON and LVS_LIST styles */
966     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
967                           GetModuleHandle(NULL), 0);
968     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
969     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
970     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
971     /* insert column */
972     memset(&col, 0, sizeof(LVCOLUMNA));
973     col.mask = LVCF_WIDTH;
974     col.cx = 100;
975     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
976     ok(r == 0, "Expected 0 column's inserted\n");
977     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
978     ok(IsWindow(hHeader), "Header should be created\n");
979     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
980     DestroyWindow(hList);
981
982     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
983                           GetModuleHandle(NULL), 0);
984     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
985     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
986     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
987     /* insert column */
988     memset(&col, 0, sizeof(LVCOLUMNA));
989     col.mask = LVCF_WIDTH;
990     col.cx = 100;
991     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
992     ok(r == 0, "Expected 0 column's inserted\n");
993     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
994     ok(IsWindow(hHeader), "Header should be created\n");
995     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
996     DestroyWindow(hList);
997
998     /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
999     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1000                           GetModuleHandle(NULL), 0);
1001     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLongPtr(hList, GWL_STYLE) | LVS_REPORT);
1002     ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
1003     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1004     ok(IsWindow(hHeader), "Header should be created\n");
1005     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) & ~LVS_REPORT);
1006     ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1007     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1008     ok(IsWindow(hHeader), "Header should be created\n");
1009     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1010     DestroyWindow(hList);
1011
1012     /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1013     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1014                           GetModuleHandle(NULL), 0);
1015     ret = SetWindowLongPtr(hList, GWL_STYLE,
1016                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
1017     ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1018     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1019     ok(IsWindow(hHeader), "Header should be created\n");
1020     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1021     ret = SetWindowLongPtr(hList, GWL_STYLE,
1022                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
1023     ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1024     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1025     ok(IsWindow(hHeader), "Header should be created\n");
1026     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1027     DestroyWindow(hList);
1028
1029     /* LVS_REPORT without WS_VISIBLE */
1030     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1031                           GetModuleHandle(NULL), 0);
1032     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1033     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1034     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1035     /* insert column */
1036     memset(&col, 0, sizeof(LVCOLUMNA));
1037     col.mask = LVCF_WIDTH;
1038     col.cx = 100;
1039     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1040     ok(r == 0, "Expected 0 column's inserted\n");
1041     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1042     ok(IsWindow(hHeader), "Header should be created\n");
1043     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1044     DestroyWindow(hList);
1045
1046     /* LVS_REPORT without WS_VISIBLE, try to show it */
1047     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1048                           GetModuleHandle(NULL), 0);
1049     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1050     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1051     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1052     ShowWindow(hList, SW_SHOW);
1053     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1054     ok(IsWindow(hHeader), "Header should be created\n");
1055     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1056     DestroyWindow(hList);
1057
1058     /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1059     hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1060                           0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1061     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1062     ok(IsWindow(hHeader), "Header should be created\n");
1063     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1064     /* HDS_DRAGDROP set by default */
1065     ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1066     DestroyWindow(hList);
1067
1068     /* setting LVS_EX_HEADERDRAGDROP creates header */
1069     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1070                           GetModuleHandle(NULL), 0);
1071     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1072     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1073     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1074     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1075     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1076     ok(IsWindow(hHeader), "Header should be created\n");
1077     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1078     DestroyWindow(hList);
1079
1080     /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1081     hList = create_custom_listview_control(0);
1082     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1083     r = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1084     ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1085     DestroyWindow(hList);
1086
1087     /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1088     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1089                           GetModuleHandle(NULL), 0);
1090     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1091     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1092
1093     rect.left = LVIR_BOUNDS;
1094     rect.top  = 1;
1095     rect.right = rect.bottom = -10;
1096     r = SendMessage(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1097     ok(r != 0, "Expected not-null LRESULT\n");
1098
1099     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1100     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1101     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1102
1103     DestroyWindow(hList);
1104 }
1105
1106 static void test_redraw(void)
1107 {
1108     HWND hwnd, hwndheader;
1109     HDC hdc;
1110     BOOL res;
1111     DWORD r;
1112
1113     hwnd = create_listview_control(0);
1114     hwndheader = subclass_header(hwnd);
1115
1116     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1117
1118     trace("invalidate & update\n");
1119     InvalidateRect(hwnd, NULL, TRUE);
1120     UpdateWindow(hwnd);
1121     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1122
1123     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1124
1125     /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1126     /* 1. Without backbuffer */
1127     res = ListView_SetBkColor(hwnd, CLR_NONE);
1128     expect(TRUE, res);
1129
1130     hdc = GetWindowDC(hwndparent);
1131
1132     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1133     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1134     ok(r != 0, "Expected not zero result\n");
1135     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1136                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1137
1138     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1139     expect(TRUE, res);
1140
1141     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1142     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1143     ok(r != 0, "Expected not zero result\n");
1144     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1145                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1146
1147     /* 2. With backbuffer */
1148     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1149                                                      LVS_EX_DOUBLEBUFFER);
1150     res = ListView_SetBkColor(hwnd, CLR_NONE);
1151     expect(TRUE, res);
1152
1153     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1154     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1155     ok(r != 0, "Expected not zero result\n");
1156     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1157                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1158
1159     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1160     expect(TRUE, res);
1161
1162     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1163     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1164     todo_wine ok(r != 0, "Expected not zero result\n");
1165     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1166                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1167
1168     ReleaseDC(hwndparent, hdc);
1169
1170     DestroyWindow(hwnd);
1171 }
1172
1173 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1174 {
1175     COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1176
1177     if(msg == WM_NOTIFY) {
1178         NMHDR *nmhdr = (PVOID)lp;
1179         if(nmhdr->code == NM_CUSTOMDRAW) {
1180             NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
1181             trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
1182             switch(nmlvcd->nmcd.dwDrawStage) {
1183             case CDDS_PREPAINT:
1184                 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1185                 return CDRF_NOTIFYITEMDRAW;
1186             case CDDS_ITEMPREPAINT:
1187                 nmlvcd->clrTextBk = CLR_DEFAULT;
1188                 return CDRF_NOTIFYSUBITEMDRAW;
1189             case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1190                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1191                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1192                 return CDRF_NOTIFYPOSTPAINT;
1193             case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1194                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1195                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1196                 return CDRF_DODEFAULT;
1197             }
1198             return CDRF_DODEFAULT;
1199         }
1200     }
1201
1202     return DefWindowProcA(hwnd, msg, wp, lp);
1203 }
1204
1205 static void test_customdraw(void)
1206 {
1207     HWND hwnd;
1208     WNDPROC oldwndproc;
1209
1210     hwnd = create_listview_control(0);
1211
1212     insert_column(hwnd, 0);
1213     insert_column(hwnd, 1);
1214     insert_item(hwnd, 0);
1215
1216     oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
1217                                            (LONG_PTR)cd_wndproc);
1218
1219     InvalidateRect(hwnd, NULL, TRUE);
1220     UpdateWindow(hwnd);
1221
1222     SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1223
1224     DestroyWindow(hwnd);
1225 }
1226
1227 static void test_icon_spacing(void)
1228 {
1229     /* LVM_SETICONSPACING */
1230     /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1231
1232     HWND hwnd;
1233     WORD w, h;
1234     DWORD r;
1235
1236     hwnd = create_custom_listview_control(LVS_ICON);
1237     ok(hwnd != NULL, "failed to create a listview window\n");
1238
1239     r = SendMessage(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, (LPARAM)NF_REQUERY);
1240     expect(NFR_ANSI, r);
1241
1242     /* reset the icon spacing to defaults */
1243     SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1244
1245     /* now we can request what the defaults are */
1246     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1247     w = LOWORD(r);
1248     h = HIWORD(r);
1249
1250     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1251
1252     trace("test icon spacing\n");
1253
1254     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1255     ok(r == MAKELONG(w, h) ||
1256        broken(r == MAKELONG(w, w)), /* win98 */
1257        "Expected %d, got %d\n", MAKELONG(w, h), r);
1258
1259     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1260     expect(MAKELONG(20,30), r);
1261
1262     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1263     expect(MAKELONG(25,35), r);
1264
1265     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1266
1267     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1268     DestroyWindow(hwnd);
1269 }
1270
1271 static void test_color(void)
1272 {
1273     /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1274
1275     HWND hwnd;
1276     DWORD r;
1277     int i;
1278
1279     COLORREF color;
1280     COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1281
1282     hwnd = create_listview_control(0);
1283     ok(hwnd != NULL, "failed to create a listview window\n");
1284
1285     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1286
1287     trace("test color seq\n");
1288     for (i = 0; i < 4; i++)
1289     {
1290         color = colors[i];
1291
1292         r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
1293         expect(TRUE, r);
1294         r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, color);
1295         expect(color, r);
1296
1297         r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
1298         expect (TRUE, r);
1299         r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, color);
1300         expect(color, r);
1301
1302         r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
1303         expect(TRUE, r);
1304         r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, color);
1305         expect(color, r);
1306     }
1307
1308     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
1309
1310     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1311     DestroyWindow(hwnd);
1312 }
1313
1314 static void test_item_count(void)
1315 {
1316     /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1317
1318     HWND hwnd;
1319     DWORD r;
1320
1321     LVITEM item0;
1322     LVITEM item1;
1323     LVITEM item2;
1324     static CHAR item0text[] = "item0";
1325     static CHAR item1text[] = "item1";
1326     static CHAR item2text[] = "item2";
1327
1328     hwnd = create_listview_control(0);
1329     ok(hwnd != NULL, "failed to create a listview window\n");
1330
1331     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1332
1333     trace("test item count\n");
1334
1335     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1336     expect(0, r);
1337
1338     /* [item0] */
1339     item0.mask = LVIF_TEXT;
1340     item0.iItem = 0;
1341     item0.iSubItem = 0;
1342     item0.pszText = item0text;
1343     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1344     expect(0, r);
1345
1346     /* [item0, item1] */
1347     item1.mask = LVIF_TEXT;
1348     item1.iItem = 1;
1349     item1.iSubItem = 0;
1350     item1.pszText = item1text;
1351     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1352     expect(1, r);
1353
1354     /* [item0, item1, item2] */
1355     item2.mask = LVIF_TEXT;
1356     item2.iItem = 2;
1357     item2.iSubItem = 0;
1358     item2.pszText = item2text;
1359     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1360     expect(2, r);
1361
1362     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1363     expect(3, r);
1364
1365     /* [item0, item1] */
1366     r = SendMessage(hwnd, LVM_DELETEITEM, 2, 0);
1367     expect(TRUE, r);
1368
1369     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1370     expect(2, r);
1371
1372     /* [] */
1373     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1374     expect(TRUE, r);
1375
1376     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1377     expect(0, r);
1378
1379     /* [item0] */
1380     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1381     expect(0, r);
1382
1383     /* [item0, item1] */
1384     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1385     expect(1, r);
1386
1387     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1388     expect(2, r);
1389
1390     /* [item0, item1, item2] */
1391     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1392     expect(2, r);
1393
1394     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1395     expect(3, r);
1396
1397     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
1398
1399     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1400     DestroyWindow(hwnd);
1401 }
1402
1403 static void test_item_position(void)
1404 {
1405     /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1406
1407     HWND hwnd;
1408     DWORD r;
1409     POINT position;
1410
1411     LVITEM item0;
1412     LVITEM item1;
1413     LVITEM item2;
1414     static CHAR item0text[] = "item0";
1415     static CHAR item1text[] = "item1";
1416     static CHAR item2text[] = "item2";
1417
1418     hwnd = create_custom_listview_control(LVS_ICON);
1419     ok(hwnd != NULL, "failed to create a listview window\n");
1420
1421     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1422
1423     trace("test item position\n");
1424
1425     /* [item0] */
1426     item0.mask = LVIF_TEXT;
1427     item0.iItem = 0;
1428     item0.iSubItem = 0;
1429     item0.pszText = item0text;
1430     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1431     expect(0, r);
1432
1433     /* [item0, item1] */
1434     item1.mask = LVIF_TEXT;
1435     item1.iItem = 1;
1436     item1.iSubItem = 0;
1437     item1.pszText = item1text;
1438     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1439     expect(1, r);
1440
1441     /* [item0, item1, item2] */
1442     item2.mask = LVIF_TEXT;
1443     item2.iItem = 2;
1444     item2.iSubItem = 0;
1445     item2.pszText = item2text;
1446     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1447     expect(2, r);
1448
1449     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
1450     expect(TRUE, r);
1451     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
1452     expect(TRUE, r);
1453     expect2(10, 5, position.x, position.y);
1454
1455     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
1456     expect(TRUE, r);
1457     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
1458     expect(TRUE, r);
1459     expect2(0, 0, position.x, position.y);
1460
1461     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
1462     expect(TRUE, r);
1463     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
1464     expect(TRUE, r);
1465     expect2(20, 20, position.x, position.y);
1466
1467     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
1468
1469     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1470     DestroyWindow(hwnd);
1471 }
1472
1473 static void test_getorigin(void)
1474 {
1475     /* LVM_GETORIGIN */
1476
1477     HWND hwnd;
1478     DWORD r;
1479     POINT position;
1480
1481     position.x = position.y = 0;
1482
1483     hwnd = create_custom_listview_control(LVS_ICON);
1484     ok(hwnd != NULL, "failed to create a listview window\n");
1485     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1486     trace("test get origin results\n");
1487     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1488     expect(TRUE, r);
1489     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1490     DestroyWindow(hwnd);
1491
1492     hwnd = create_custom_listview_control(LVS_SMALLICON);
1493     ok(hwnd != NULL, "failed to create a listview window\n");
1494     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1495     trace("test get origin results\n");
1496     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1497     expect(TRUE, r);
1498     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1499     DestroyWindow(hwnd);
1500
1501     hwnd = create_custom_listview_control(LVS_LIST);
1502     ok(hwnd != NULL, "failed to create a listview window\n");
1503     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1504     trace("test get origin results\n");
1505     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1506     expect(FALSE, r);
1507     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1508     DestroyWindow(hwnd);
1509
1510     hwnd = create_custom_listview_control(LVS_REPORT);
1511     ok(hwnd != NULL, "failed to create a listview window\n");
1512     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1513     trace("test get origin results\n");
1514     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1515     expect(FALSE, r);
1516     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1517     DestroyWindow(hwnd);
1518
1519 }
1520
1521 static void test_multiselect(void)
1522 {
1523     typedef struct t_select_task
1524     {
1525         const char *descr;
1526         int initPos;
1527         int loopVK;
1528         int count;
1529         int result;
1530     } select_task;
1531
1532     HWND hwnd;
1533     DWORD r;
1534     int i,j,item_count,selected_count;
1535     static const int items=5;
1536     BYTE kstate[256];
1537     select_task task;
1538     LONG_PTR style;
1539     LVITEMA item;
1540
1541     static struct t_select_task task_list[] = {
1542         { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
1543         { "using VK_UP", -1, VK_UP, -1, -1 },
1544         { "using VK_END", 0, VK_END, 1, -1 },
1545         { "using VK_HOME", -1, VK_HOME, 1, -1 }
1546     };
1547
1548
1549     hwnd = create_listview_control(0);
1550
1551     for (i=0;i<items;i++) {
1552             insert_item(hwnd, 0);
1553     }
1554
1555     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1556
1557     expect(items,item_count);
1558
1559     for (i=0;i<4;i++) {
1560         task = task_list[i];
1561
1562         /* deselect all items */
1563         ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1564         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1565
1566         /* set initial position */
1567         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
1568         ListView_SetItemState(hwnd,(task.initPos == -1 ? item_count -1 : task.initPos),LVIS_SELECTED ,LVIS_SELECTED);
1569
1570         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1571
1572         ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
1573
1574         /* Set SHIFT key pressed */
1575         GetKeyboardState(kstate);
1576         kstate[VK_SHIFT]=0x80;
1577         SetKeyboardState(kstate);
1578
1579         for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
1580             r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
1581             expect(0,r);
1582             r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
1583             expect(0,r);
1584         }
1585
1586         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1587
1588         ok((task.result == -1 ? item_count : task.result) == selected_count, "Failed multiple selection %s. There should be %d selected items (is %d)\n", task.descr, item_count, selected_count);
1589
1590         /* Set SHIFT key released */
1591         GetKeyboardState(kstate);
1592         kstate[VK_SHIFT]=0x00;
1593         SetKeyboardState(kstate);
1594     }
1595     DestroyWindow(hwnd);
1596
1597     /* make multiple selection, then switch to LVS_SINGLESEL */
1598     hwnd = create_listview_control(0);
1599     for (i=0;i<items;i++) {
1600             insert_item(hwnd, 0);
1601     }
1602     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1603     expect(items,item_count);
1604     /* deselect all items */
1605     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1606     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1607     for (i=0;i<3;i++) {
1608         ListView_SetItemState(hwnd, i, LVIS_SELECTED, LVIS_SELECTED);
1609     }
1610
1611     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1612     expect(3, r);
1613     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1614 todo_wine
1615     expect(-1, r);
1616
1617     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1618     ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
1619     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
1620     /* check that style is accepted */
1621     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1622     ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
1623
1624     for (i=0;i<3;i++) {
1625         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1626         ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1627     }
1628     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1629     expect(3, r);
1630     SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1631     expect(3, r);
1632
1633     /* select one more */
1634     ListView_SetItemState(hwnd, 3, LVIS_SELECTED, LVIS_SELECTED);
1635
1636     for (i=0;i<3;i++) {
1637         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1638         ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
1639     }
1640     r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
1641     ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1642
1643     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1644     expect(1, r);
1645     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1646 todo_wine
1647     expect(-1, r);
1648
1649     /* try to select all on LVS_SINGLESEL */
1650     memset(&item, 0, sizeof(item));
1651     item.stateMask = LVIS_SELECTED;
1652     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1653     expect(TRUE, r);
1654     ListView_SetSelectionMark(hwnd, -1);
1655
1656     item.stateMask = LVIS_SELECTED;
1657     item.state     = LVIS_SELECTED;
1658     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1659     expect(FALSE, r);
1660
1661     r = ListView_GetSelectedCount(hwnd);
1662     expect(0, r);
1663     r = ListView_GetSelectionMark(hwnd);
1664     expect(-1, r);
1665
1666     /* try to deselect all on LVS_SINGLESEL */
1667     item.stateMask = LVIS_SELECTED;
1668     item.state     = LVIS_SELECTED;
1669     r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
1670     expect(TRUE, r);
1671
1672     item.stateMask = LVIS_SELECTED;
1673     item.state     = 0;
1674     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1675     expect(TRUE, r);
1676     r = ListView_GetSelectedCount(hwnd);
1677     expect(0, r);
1678
1679     DestroyWindow(hwnd);
1680 }
1681
1682 static void test_subitem_rect(void)
1683 {
1684     HWND hwnd;
1685     DWORD r;
1686     LVCOLUMN col;
1687     RECT rect;
1688
1689     /* test LVM_GETSUBITEMRECT for header */
1690     hwnd = create_listview_control(0);
1691     ok(hwnd != NULL, "failed to create a listview window\n");
1692     /* add some columns */
1693     memset(&col, 0, sizeof(LVCOLUMN));
1694     col.mask = LVCF_WIDTH;
1695     col.cx = 100;
1696     r = -1;
1697     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1698     expect(0, r);
1699     col.cx = 150;
1700     r = -1;
1701     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
1702     expect(1, r);
1703     col.cx = 200;
1704     r = -1;
1705     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
1706     expect(2, r);
1707     /* item = -1 means header, subitem index is 1 based */
1708     rect.left = LVIR_BOUNDS;
1709     rect.top  = 0;
1710     rect.right = rect.bottom = 0;
1711     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1712     expect(0, r);
1713
1714     rect.left = LVIR_BOUNDS;
1715     rect.top  = 1;
1716     rect.right = rect.bottom = 0;
1717     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1718
1719     ok(r != 0, "Expected not-null LRESULT\n");
1720     expect(100, rect.left);
1721     expect(250, rect.right);
1722 todo_wine
1723     expect(3, rect.top);
1724
1725     rect.left = LVIR_BOUNDS;
1726     rect.top  = 2;
1727     rect.right = rect.bottom = 0;
1728     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1729
1730     ok(r != 0, "Expected not-null LRESULT\n");
1731     expect(250, rect.left);
1732     expect(450, rect.right);
1733 todo_wine
1734     expect(3, rect.top);
1735
1736     DestroyWindow(hwnd);
1737
1738     /* try it for non LVS_REPORT style */
1739     hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
1740                          GetModuleHandle(NULL), 0);
1741     rect.left = LVIR_BOUNDS;
1742     rect.top  = 1;
1743     rect.right = rect.bottom = -10;
1744     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1745     ok(r == 0, "Expected not-null LRESULT\n");
1746     /* rect is unchanged */
1747     expect(0, rect.left);
1748     expect(-10, rect.right);
1749     expect(1, rect.top);
1750     expect(-10, rect.bottom);
1751     DestroyWindow(hwnd);
1752 }
1753
1754 /* comparison callback for test_sorting */
1755 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
1756 {
1757     if (first == second) return 0;
1758     return (first > second ? 1 : -1);
1759 }
1760
1761 static void test_sorting(void)
1762 {
1763     HWND hwnd;
1764     LVITEMA item = {0};
1765     DWORD r;
1766     LONG_PTR style;
1767     static CHAR names[][5] = {"A", "B", "C", "D", "0"};
1768     CHAR buff[10];
1769
1770     hwnd = create_listview_control(0);
1771     ok(hwnd != NULL, "failed to create a listview window\n");
1772
1773     /* insert some items */
1774     item.mask = LVIF_PARAM | LVIF_STATE;
1775     item.state = LVIS_SELECTED;
1776     item.iItem = 0;
1777     item.iSubItem = 0;
1778     item.lParam = 3;
1779     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1780     expect(0, r);
1781
1782     item.mask = LVIF_PARAM;
1783     item.iItem = 1;
1784     item.iSubItem = 0;
1785     item.lParam = 2;
1786     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1787     expect(1, r);
1788
1789     item.mask = LVIF_STATE | LVIF_PARAM;
1790     item.state = LVIS_SELECTED;
1791     item.iItem = 2;
1792     item.iSubItem = 0;
1793     item.lParam = 4;
1794     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1795     expect(2, r);
1796
1797     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1798     expect(-1, r);
1799
1800     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1801     expect(2, r);
1802
1803     r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
1804     expect(TRUE, r);
1805
1806     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1807     expect(2, r);
1808     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1809     expect(-1, r);
1810     r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
1811     expect(0, r);
1812     r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
1813     expect(LVIS_SELECTED, r);
1814     r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
1815     expect(LVIS_SELECTED, r);
1816
1817     DestroyWindow(hwnd);
1818
1819     /* switch to LVS_SORTASCENDING when some items added */
1820     hwnd = create_listview_control(0);
1821     ok(hwnd != NULL, "failed to create a listview window\n");
1822
1823     item.mask = LVIF_TEXT;
1824     item.iItem = 0;
1825     item.iSubItem = 0;
1826     item.pszText = names[1];
1827     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1828     expect(0, r);
1829
1830     item.mask = LVIF_TEXT;
1831     item.iItem = 1;
1832     item.iSubItem = 0;
1833     item.pszText = names[2];
1834     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1835     expect(1, r);
1836
1837     item.mask = LVIF_TEXT;
1838     item.iItem = 2;
1839     item.iSubItem = 0;
1840     item.pszText = names[0];
1841     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1842     expect(2, r);
1843
1844     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1845     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
1846     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1847     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
1848
1849     /* no sorting performed when switched to LVS_SORTASCENDING */
1850     item.mask = LVIF_TEXT;
1851     item.iItem = 0;
1852     item.pszText = buff;
1853     item.cchTextMax = sizeof(buff);
1854     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1855     expect(TRUE, r);
1856     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1857
1858     item.iItem = 1;
1859     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1860     expect(TRUE, r);
1861     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1862
1863     item.iItem = 2;
1864     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1865     expect(TRUE, r);
1866     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1867
1868     /* adding new item doesn't resort list */
1869     item.mask = LVIF_TEXT;
1870     item.iItem = 3;
1871     item.iSubItem = 0;
1872     item.pszText = names[3];
1873     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1874     expect(3, r);
1875
1876     item.mask = LVIF_TEXT;
1877     item.iItem = 0;
1878     item.pszText = buff;
1879     item.cchTextMax = sizeof(buff);
1880     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1881     expect(TRUE, r);
1882     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1883
1884     item.iItem = 1;
1885     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1886     expect(TRUE, r);
1887     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1888
1889     item.iItem = 2;
1890     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1891     expect(TRUE, r);
1892     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1893
1894     item.iItem = 3;
1895     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1896     expect(TRUE, r);
1897     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
1898
1899     /* corner case - item should be placed at first position */
1900     item.mask = LVIF_TEXT;
1901     item.iItem = 4;
1902     item.iSubItem = 0;
1903     item.pszText = names[4];
1904     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1905     expect(0, r);
1906
1907     item.iItem = 0;
1908     item.pszText = buff;
1909     item.cchTextMax = sizeof(buff);
1910     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1911     expect(TRUE, r);
1912     ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
1913
1914     item.iItem = 1;
1915     item.pszText = buff;
1916     item.cchTextMax = sizeof(buff);
1917     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1918     expect(TRUE, r);
1919     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1920
1921     item.iItem = 2;
1922     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1923     expect(TRUE, r);
1924     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1925
1926     item.iItem = 3;
1927     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1928     expect(TRUE, r);
1929     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1930
1931     item.iItem = 4;
1932     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1933     expect(TRUE, r);
1934     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
1935
1936     DestroyWindow(hwnd);
1937 }
1938
1939 static void test_ownerdata(void)
1940 {
1941     HWND hwnd;
1942     LONG_PTR style, ret;
1943     DWORD res;
1944     LVITEMA item;
1945
1946     /* it isn't possible to set LVS_OWNERDATA after creation */
1947     hwnd = create_listview_control(0);
1948     ok(hwnd != NULL, "failed to create a listview window\n");
1949     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1950     ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
1951
1952     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1953
1954     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
1955     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1956     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1957                 "try to switch to LVS_OWNERDATA seq", FALSE);
1958
1959     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1960     ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
1961     DestroyWindow(hwnd);
1962
1963     /* try to set LVS_OWNERDATA after creation just having it */
1964     hwnd = create_listview_control(LVS_OWNERDATA);
1965     ok(hwnd != NULL, "failed to create a listview window\n");
1966     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1967     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1968
1969     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1970
1971     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
1972     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1973     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1974                 "try to switch to LVS_OWNERDATA seq", FALSE);
1975     DestroyWindow(hwnd);
1976
1977     /* try to remove LVS_OWNERDATA after creation just having it */
1978     hwnd = create_listview_control(LVS_OWNERDATA);
1979     ok(hwnd != NULL, "failed to create a listview window\n");
1980     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1981     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1982
1983     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1984
1985     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
1986     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1987     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1988                 "try to switch to LVS_OWNERDATA seq", FALSE);
1989     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1990     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1991     DestroyWindow(hwnd);
1992
1993     /* try select an item */
1994     hwnd = create_listview_control(LVS_OWNERDATA);
1995     ok(hwnd != NULL, "failed to create a listview window\n");
1996     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
1997     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
1998     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1999     expect(0, res);
2000     memset(&item, 0, sizeof(item));
2001     item.stateMask = LVIS_SELECTED;
2002     item.state     = LVIS_SELECTED;
2003     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2004     expect(TRUE, res);
2005     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2006     expect(1, res);
2007     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2008     expect(1, res);
2009     DestroyWindow(hwnd);
2010
2011     /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2012     hwnd = create_listview_control(LVS_OWNERDATA);
2013     ok(hwnd != NULL, "failed to create a listview window\n");
2014     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2015     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2016     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2017     expect(1, res);
2018     memset(&item, 0, sizeof(item));
2019     item.mask = LVIF_STATE;
2020     item.iItem = 0;
2021     item.stateMask = LVIS_SELECTED;
2022     item.state     = LVIS_SELECTED;
2023     res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2024     expect(FALSE, res);
2025     DestroyWindow(hwnd);
2026
2027     /* check notifications after focused/selected changed */
2028     hwnd = create_listview_control(LVS_OWNERDATA);
2029     ok(hwnd != NULL, "failed to create a listview window\n");
2030     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2031     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2032
2033     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2034
2035     memset(&item, 0, sizeof(item));
2036     item.stateMask = LVIS_SELECTED;
2037     item.state     = LVIS_SELECTED;
2038     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2039     expect(TRUE, res);
2040
2041     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2042                 "ownerdata select notification", TRUE);
2043
2044     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2045
2046     memset(&item, 0, sizeof(item));
2047     item.stateMask = LVIS_FOCUSED;
2048     item.state     = LVIS_FOCUSED;
2049     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2050     expect(TRUE, res);
2051
2052     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2053                 "ownerdata focus notification", TRUE);
2054     DestroyWindow(hwnd);
2055
2056     /* check notifications on LVM_GETITEM */
2057     /* zero callback mask */
2058     hwnd = create_listview_control(LVS_OWNERDATA);
2059     ok(hwnd != NULL, "failed to create a listview window\n");
2060     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2061     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2062
2063     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2064
2065     memset(&item, 0, sizeof(item));
2066     item.stateMask = LVIS_SELECTED;
2067     item.mask      = LVIF_STATE;
2068     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2069     expect(TRUE, res);
2070
2071     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2072                 "ownerdata getitem selected state 1", FALSE);
2073
2074     /* non zero callback mask but not we asking for */
2075     res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0);
2076     expect(TRUE, res);
2077
2078     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2079
2080     memset(&item, 0, sizeof(item));
2081     item.stateMask = LVIS_SELECTED;
2082     item.mask      = LVIF_STATE;
2083     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2084     expect(TRUE, res);
2085
2086     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2087                 "ownerdata getitem selected state 2", FALSE);
2088
2089     /* LVIS_OVERLAYMASK callback mask, asking for index */
2090     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2091
2092     memset(&item, 0, sizeof(item));
2093     item.stateMask = LVIS_OVERLAYMASK;
2094     item.mask      = LVIF_STATE;
2095     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2096     expect(TRUE, res);
2097
2098     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
2099                 "ownerdata getitem selected state 2", FALSE);
2100
2101     DestroyWindow(hwnd);
2102 }
2103
2104 static void test_norecompute(void)
2105 {
2106     static CHAR testA[] = "test";
2107     CHAR buff[10];
2108     LVITEMA item;
2109     HWND hwnd;
2110     DWORD res;
2111
2112     /* self containing control */
2113     hwnd = create_listview_control(0);
2114     ok(hwnd != NULL, "failed to create a listview window\n");
2115     memset(&item, 0, sizeof(item));
2116     item.mask = LVIF_TEXT | LVIF_STATE;
2117     item.iItem = 0;
2118     item.stateMask = LVIS_SELECTED;
2119     item.state     = LVIS_SELECTED;
2120     item.pszText   = testA;
2121     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2122     expect(0, res);
2123     /* retrieve with LVIF_NORECOMPUTE */
2124     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2125     item.iItem = 0;
2126     item.pszText    = buff;
2127     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2128     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2129     expect(TRUE, res);
2130     ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
2131
2132     item.mask = LVIF_TEXT;
2133     item.iItem = 1;
2134     item.pszText = LPSTR_TEXTCALLBACK;
2135     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2136     expect(1, res);
2137
2138     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2139     item.iItem = 1;
2140     item.pszText    = buff;
2141     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2142
2143     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2144     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2145     expect(TRUE, res);
2146     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2147        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2148     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
2149
2150     DestroyWindow(hwnd);
2151
2152     /* LVS_OWNERDATA */
2153     hwnd = create_listview_control(LVS_OWNERDATA);
2154     ok(hwnd != NULL, "failed to create a listview window\n");
2155
2156     item.mask = LVIF_STATE;
2157     item.stateMask = LVIS_SELECTED;
2158     item.state     = LVIS_SELECTED;
2159     item.iItem = 0;
2160     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2161     expect(0, res);
2162
2163     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2164     item.iItem = 0;
2165     item.pszText    = buff;
2166     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2167     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2168     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2169     expect(TRUE, res);
2170     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2171        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2172     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
2173
2174     DestroyWindow(hwnd);
2175 }
2176
2177 static void test_nosortheader(void)
2178 {
2179     HWND hwnd, header;
2180     LONG_PTR style;
2181
2182     hwnd = create_listview_control(0);
2183     ok(hwnd != NULL, "failed to create a listview window\n");
2184
2185     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2186     ok(IsWindow(header), "header expected\n");
2187
2188     style = GetWindowLongPtr(header, GWL_STYLE);
2189     ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
2190
2191     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2192     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
2193     /* HDS_BUTTONS retained */
2194     style = GetWindowLongPtr(header, GWL_STYLE);
2195     ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
2196
2197     DestroyWindow(hwnd);
2198
2199     /* create with LVS_NOSORTHEADER */
2200     hwnd = create_listview_control(LVS_NOSORTHEADER);
2201     ok(hwnd != NULL, "failed to create a listview window\n");
2202
2203     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2204     ok(IsWindow(header), "header expected\n");
2205
2206     style = GetWindowLongPtr(header, GWL_STYLE);
2207     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2208
2209     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2210     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
2211     /* not changed here */
2212     style = GetWindowLongPtr(header, GWL_STYLE);
2213     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2214
2215     DestroyWindow(hwnd);
2216 }
2217
2218 START_TEST(listview)
2219 {
2220     HMODULE hComctl32;
2221     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
2222
2223     hComctl32 = GetModuleHandleA("comctl32.dll");
2224     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
2225     if (pInitCommonControlsEx)
2226     {
2227         INITCOMMONCONTROLSEX iccex;
2228         iccex.dwSize = sizeof(iccex);
2229         iccex.dwICC  = ICC_LISTVIEW_CLASSES;
2230         pInitCommonControlsEx(&iccex);
2231     }
2232     else
2233         InitCommonControls();
2234
2235     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2236
2237     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2238     hwndparent = create_parent_window();
2239     ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create parent window", TRUE);
2240     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2241
2242     test_images();
2243     test_checkboxes();
2244     test_items();
2245     test_create();
2246     test_redraw();
2247     test_customdraw();
2248     test_icon_spacing();
2249     test_color();
2250     test_item_count();
2251     test_item_position();
2252     test_columns();
2253     test_getorigin();
2254     test_multiselect();
2255     test_subitem_rect();
2256     test_sorting();
2257     test_ownerdata();
2258     test_norecompute();
2259     test_nosortheader();
2260 }