comctl32/listview: Update focus index when new item data is already there.
[wine] / dlls / comctl32 / tests / listview.c
1 /*
2  * ListView tests
3  *
4  * Copyright 2006 Mike McCormack for CodeWeavers
5  * Copyright 2007 George Gov
6  * Copyright 2009-2013 Nikolay Sivov
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include <stdio.h>
24 #include <windows.h>
25 #include <commctrl.h>
26
27 #include "wine/test.h"
28 #include "v6util.h"
29 #include "msg.h"
30
31 #define PARENT_SEQ_INDEX       0
32 #define PARENT_FULL_SEQ_INDEX  1
33 #define LISTVIEW_SEQ_INDEX     2
34 #define EDITBOX_SEQ_INDEX      3
35 #define COMBINED_SEQ_INDEX     4
36 #define NUM_MSG_SEQUENCES      5
37
38 #define LISTVIEW_ID 0
39 #define HEADER_ID   1
40
41 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
42 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
43        "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
44
45 static const WCHAR testparentclassW[] =
46     {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
47
48 static HWND hwndparent, hwndparentW;
49 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
50 static BOOL blockEdit;
51 /* return nonzero on NM_HOVER */
52 static BOOL g_block_hover;
53 /* notification data for LVN_ITEMCHANGED */
54 static NMLISTVIEW g_nmlistview;
55 /* notification data for LVN_ITEMCHANGING */
56 static NMLISTVIEW g_nmlistview_changing;
57 /* format reported to control:
58    -1 falls to defproc, anything else returned */
59 static INT notifyFormat;
60 /* indicates we're running < 5.80 version */
61 static BOOL g_is_below_5;
62 /* item data passed to LVN_GETDISPINFOA */
63 static LVITEMA g_itema;
64 /* alter notification code A->W */
65 static BOOL g_disp_A_to_W;
66 /* dispinfo data sent with LVN_LVN_ENDLABELEDIT */
67 static NMLVDISPINFO g_editbox_disp_info;
68 /* when this is set focus will be tested on LVN_DELETEITEM */
69 static BOOL g_focus_test_LVN_DELETEITEM;
70
71 static HWND subclass_editbox(HWND hwndListview);
72
73 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
74
75 static const struct message create_ownerdrawfixed_parent_seq[] = {
76     { WM_NOTIFYFORMAT, sent },
77     { WM_QUERYUISTATE, sent|optional }, /* Win2K and higher */
78     { WM_MEASUREITEM, sent },
79     { WM_PARENTNOTIFY, sent },
80     { 0 }
81 };
82
83 static const struct message redraw_listview_seq[] = {
84     { WM_PAINT,      sent|id,            0, 0, LISTVIEW_ID },
85     { WM_PAINT,      sent|id,            0, 0, HEADER_ID },
86     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, HEADER_ID },
87     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, HEADER_ID },
88     { WM_NOTIFY,     sent|id|defwinproc, 0, 0, LISTVIEW_ID },
89     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, LISTVIEW_ID },
90     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, LISTVIEW_ID },
91     { 0 }
92 };
93
94 static const struct message listview_icon_spacing_seq[] = {
95     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) },
96     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) },
97     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) },
98     { 0 }
99 };
100
101 static const struct message listview_color_seq[] = {
102     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(0,0,0) },
103     { LVM_GETBKCOLOR,     sent },
104     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(0,0,0) },
105     { LVM_GETTEXTCOLOR,   sent },
106     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
107     { LVM_GETTEXTBKCOLOR, sent },
108
109     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(100,50,200) },
110     { LVM_GETBKCOLOR,     sent },
111     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(100,50,200) },
112     { LVM_GETTEXTCOLOR,   sent },
113     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
114     { LVM_GETTEXTBKCOLOR, sent },
115
116     { LVM_SETBKCOLOR,     sent|lparam, 0, CLR_NONE },
117     { LVM_GETBKCOLOR,     sent },
118     { LVM_SETTEXTCOLOR,   sent|lparam, 0, CLR_NONE },
119     { LVM_GETTEXTCOLOR,   sent },
120     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
121     { LVM_GETTEXTBKCOLOR, sent },
122
123     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(255,255,255) },
124     { LVM_GETBKCOLOR,     sent },
125     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(255,255,255) },
126     { LVM_GETTEXTCOLOR,   sent },
127     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
128     { LVM_GETTEXTBKCOLOR, sent },
129     { 0 }
130 };
131
132 static const struct message listview_item_count_seq[] = {
133     { LVM_GETITEMCOUNT,   sent },
134     { LVM_INSERTITEM,     sent },
135     { LVM_INSERTITEM,     sent },
136     { LVM_INSERTITEM,     sent },
137     { LVM_GETITEMCOUNT,   sent },
138     { LVM_DELETEITEM,     sent|wparam, 2 },
139     { WM_NCPAINT,         sent|optional },
140     { WM_ERASEBKGND,      sent|optional },
141     { LVM_GETITEMCOUNT,   sent },
142     { LVM_DELETEALLITEMS, sent },
143     { LVM_GETITEMCOUNT,   sent },
144     { LVM_INSERTITEM,     sent },
145     { LVM_INSERTITEM,     sent },
146     { LVM_GETITEMCOUNT,   sent },
147     { LVM_INSERTITEM,     sent },
148     { LVM_GETITEMCOUNT,   sent },
149     { 0 }
150 };
151
152 static const struct message listview_itempos_seq[] = {
153     { LVM_INSERTITEM,      sent },
154     { LVM_INSERTITEM,      sent },
155     { LVM_INSERTITEM,      sent },
156     { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
157     { WM_NCPAINT,          sent|optional },
158     { WM_ERASEBKGND,       sent|optional },
159     { LVM_GETITEMPOSITION, sent|wparam,        1 },
160     { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
161     { LVM_GETITEMPOSITION, sent|wparam,        2 },
162     { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
163     { LVM_GETITEMPOSITION, sent|wparam,        0 },
164     { 0 }
165 };
166
167 static const struct message listview_ownerdata_switchto_seq[] = {
168     { WM_STYLECHANGING,    sent },
169     { WM_STYLECHANGED,     sent },
170     { 0 }
171 };
172
173 static const struct message listview_getorderarray_seq[] = {
174     { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
175     { HDM_GETORDERARRAY,       sent|id|wparam, 2, 0, HEADER_ID },
176     { 0 }
177 };
178
179 static const struct message empty_seq[] = {
180     { 0 }
181 };
182
183 static const struct message forward_erasebkgnd_parent_seq[] = {
184     { WM_ERASEBKGND, sent },
185     { 0 }
186 };
187
188 static const struct message ownderdata_select_focus_parent_seq[] = {
189     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
190     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
191     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, /* version 4.7x */
192     { 0 }
193 };
194
195 static const struct message ownerdata_setstate_all_parent_seq[] = {
196     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
197     { 0 }
198 };
199
200 static const struct message ownerdata_defocus_all_parent_seq[] = {
201     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
202     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
203     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA },
204     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
205     { 0 }
206 };
207
208 static const struct message ownerdata_deselect_all_parent_seq[] = {
209     { WM_NOTIFY, sent|id, 0, 0, LVN_ODCACHEHINT },
210     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
211     { 0 }
212 };
213
214 static const struct message change_all_parent_seq[] = {
215     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
216     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
217
218     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
219     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
220
221     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
222     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
223
224     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
225     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
226
227     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
228     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
229     { 0 }
230 };
231
232 static const struct message changing_all_parent_seq[] = {
233     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
234     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
235     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
236     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
237     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
238     { 0 }
239 };
240
241 static const struct message textcallback_set_again_parent_seq[] = {
242     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
243     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED  },
244     { 0 }
245 };
246
247 static const struct message single_getdispinfo_parent_seq[] = {
248     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
249     { 0 }
250 };
251
252 static const struct message getitemposition_seq1[] = {
253     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
254     { 0 }
255 };
256
257 static const struct message getitemposition_seq2[] = {
258     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
259     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
260     { 0 }
261 };
262
263 static const struct message getsubitemrect_seq[] = {
264     { LVM_GETSUBITEMRECT, sent|id|wparam, -1, 0, LISTVIEW_ID },
265     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
266     { LVM_GETSUBITEMRECT, sent|id|wparam, 0, 0, LISTVIEW_ID },
267     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
268     { LVM_GETSUBITEMRECT, sent|id|wparam, -10, 0, LISTVIEW_ID },
269     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
270     { LVM_GETSUBITEMRECT, sent|id|wparam, 20, 0, LISTVIEW_ID },
271     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
272     { 0 }
273 };
274
275 static const struct message editbox_create_pos[] = {
276     /* sequence sent after LVN_BEGINLABELEDIT */
277     /* next two are 4.7x specific */
278     { WM_WINDOWPOSCHANGING, sent },
279     { WM_WINDOWPOSCHANGED, sent|optional },
280
281     { WM_WINDOWPOSCHANGING, sent|optional },
282     { WM_NCCALCSIZE, sent },
283     { WM_WINDOWPOSCHANGED, sent },
284     { WM_MOVE, sent|defwinproc },
285     { WM_SIZE, sent|defwinproc },
286     /* the rest is todo, skipped in 4.7x */
287     { WM_WINDOWPOSCHANGING, sent|optional },
288     { WM_WINDOWPOSCHANGED, sent|optional },
289     { 0 }
290 };
291
292 static const struct message scroll_parent_seq[] = {
293     { WM_NOTIFY, sent|id, 0, 0, LVN_BEGINSCROLL },
294     { WM_NOTIFY, sent|id, 0, 0, LVN_ENDSCROLL },
295     { 0 }
296 };
297
298 static const struct message setredraw_seq[] = {
299     { WM_SETREDRAW, sent|id|wparam, FALSE, 0, LISTVIEW_ID },
300     { 0 }
301 };
302
303 static const struct message lvs_ex_transparentbkgnd_seq[] = {
304     { WM_PRINTCLIENT, sent|lparam, 0, PRF_ERASEBKGND },
305     { 0 }
306 };
307
308 static const struct message edit_end_nochange[] = {
309     { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA },
310     { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW },     /* todo */
311     { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS },
312     { 0 }
313 };
314
315 static const struct message hover_parent[] = {
316     { WM_GETDLGCODE, sent }, /* todo_wine */
317     { WM_NOTIFY, sent|id, 0, 0, NM_HOVER },
318     { 0 }
319 };
320
321 static const struct message listview_destroy[] = {
322     { 0x0090, sent|optional }, /* Vista */
323     { WM_PARENTNOTIFY, sent },
324     { WM_SHOWWINDOW, sent },
325     { WM_WINDOWPOSCHANGING, sent },
326     { WM_WINDOWPOSCHANGED, sent|optional },
327     { WM_DESTROY, sent },
328     { WM_NOTIFY, sent|id, 0, 0, LVN_DELETEALLITEMS },
329     { WM_NCDESTROY, sent },
330     { 0 }
331 };
332
333 static const struct message listview_header_changed_seq[] = {
334     { LVM_SETCOLUMNA, sent },
335     { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
336     { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
337     { 0 }
338 };
339
340 static const struct message parent_header_click_seq[] = {
341     { WM_NOTIFY, sent|id, 0, 0, LVN_COLUMNCLICK },
342     { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCLICKA },
343     { 0 }
344 };
345
346 static const struct message parent_header_divider_dclick_seq[] = {
347     { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCHANGINGA },
348     { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW },
349     { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW },
350     { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCHANGEDA },
351     { WM_NOTIFY, sent|id, 0, 0, HDN_DIVIDERDBLCLICKA },
352     { 0 }
353 };
354
355 static const struct message listview_set_imagelist[] = {
356     { LVM_SETIMAGELIST, sent|id, 0, 0, LISTVIEW_ID },
357     { 0 }
358 };
359
360 static const struct message listview_header_set_imagelist[] = {
361     { LVM_SETIMAGELIST, sent|id, 0, 0, LISTVIEW_ID },
362     { HDM_SETIMAGELIST, sent|id, 0, 0, HEADER_ID },
363     { 0 }
364 };
365
366 static const struct message parent_insert_focused_seq[] = {
367     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
368     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
369     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
370     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
371     { WM_NOTIFY, sent|id, 0, 0, LVN_INSERTITEM },
372     { 0 }
373 };
374
375 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
376 {
377     static LONG defwndproc_counter = 0;
378     LRESULT ret;
379     struct message msg;
380
381     msg.message = message;
382     msg.flags = sent|wparam|lparam;
383     if (defwndproc_counter) msg.flags |= defwinproc;
384     msg.wParam = wParam;
385     msg.lParam = lParam;
386     if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
387
388     /* log system messages, except for painting */
389     if (message < WM_USER &&
390         message != WM_PAINT &&
391         message != WM_ERASEBKGND &&
392         message != WM_NCPAINT &&
393         message != WM_NCHITTEST &&
394         message != WM_GETTEXT &&
395         message != WM_GETICON &&
396         message != WM_DEVICECHANGE)
397     {
398         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
399
400         add_message(sequences, PARENT_SEQ_INDEX, &msg);
401         add_message(sequences, COMBINED_SEQ_INDEX, &msg);
402     }
403     add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
404
405     switch (message)
406     {
407       case WM_NOTIFY:
408       {
409           switch (((NMHDR*)lParam)->code)
410           {
411           case LVN_BEGINLABELEDIT:
412           {
413               HWND edit = NULL;
414
415               /* subclass edit box */
416               if (!blockEdit)
417                   edit = subclass_editbox(((NMHDR*)lParam)->hwndFrom);
418
419               if (edit)
420               {
421                   INT len = SendMessageA(edit, EM_GETLIMITTEXT, 0, 0);
422                   ok(len == 259 || broken(len == 260) /* includes NULL in NT4 */,
423                       "text limit %d, expected 259\n", len);
424               }
425
426               return blockEdit;
427           }
428           case LVN_ENDLABELEDIT:
429               {
430               HWND edit;
431
432               /* always accept new item text */
433               NMLVDISPINFO *di = (NMLVDISPINFO*)lParam;
434               g_editbox_disp_info = *di;
435               trace("LVN_ENDLABELEDIT: text=%s\n", di->item.pszText ? di->item.pszText : "(null)");
436
437               /* edit control still available from this notification */
438               edit = (HWND)SendMessageA(((NMHDR*)lParam)->hwndFrom, LVM_GETEDITCONTROL, 0, 0);
439               ok(IsWindow(edit), "expected valid edit control handle\n");
440               ok((GetWindowLongA(edit, GWL_STYLE) & ES_MULTILINE) == 0, "edit is multiline\n");
441
442               return TRUE;
443               }
444           case LVN_BEGINSCROLL:
445           case LVN_ENDSCROLL:
446               {
447               NMLVSCROLL *pScroll = (NMLVSCROLL*)lParam;
448
449               trace("LVN_%sSCROLL: (%d,%d)\n", pScroll->hdr.code == LVN_BEGINSCROLL ?
450                                                "BEGIN" : "END", pScroll->dx, pScroll->dy);
451               }
452               break;
453           case LVN_ITEMCHANGING:
454               {
455                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
456                   g_nmlistview_changing = *nmlv;
457               }
458               break;
459           case LVN_ITEMCHANGED:
460               {
461                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
462                   g_nmlistview = *nmlv;
463               }
464               break;
465           case LVN_GETDISPINFOA:
466               {
467                   NMLVDISPINFOA *dispinfo = (NMLVDISPINFOA*)lParam;
468                   g_itema = dispinfo->item;
469
470                   if (g_disp_A_to_W && (dispinfo->item.mask & LVIF_TEXT))
471                   {
472                       static const WCHAR testW[] = {'T','E','S','T',0};
473                       dispinfo->hdr.code = LVN_GETDISPINFOW;
474                       memcpy(dispinfo->item.pszText, testW, sizeof(testW));
475                   }
476
477                   /* test control buffer size for text, 10 used to mask cases when control
478                      is using caller buffer to process LVM_GETITEM for example */
479                   if (dispinfo->item.mask & LVIF_TEXT && dispinfo->item.cchTextMax > 10)
480                       ok(dispinfo->item.cchTextMax == 260 ||
481                          broken(dispinfo->item.cchTextMax == 264) /* NT4 reports aligned size */,
482                       "buffer size %d\n", dispinfo->item.cchTextMax);
483               }
484               break;
485           case LVN_DELETEITEM:
486               if (g_focus_test_LVN_DELETEITEM)
487               {
488                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
489                   UINT state;
490
491                   state = SendMessageA(((NMHDR*)lParam)->hwndFrom, LVM_GETITEMSTATE, nmlv->iItem, LVIS_FOCUSED);
492                   ok(state == 0, "got state %x\n", state);
493               }
494               break;
495           case NM_HOVER:
496               if (g_block_hover) return 1;
497               break;
498           }
499           break;
500       }
501       case WM_NOTIFYFORMAT:
502       {
503           /* force to return format */
504           if (lParam == NF_QUERY && notifyFormat != -1) return notifyFormat;
505           break;
506       }
507     }
508
509     defwndproc_counter++;
510     ret = DefWindowProcA(hwnd, message, wParam, lParam);
511     defwndproc_counter--;
512
513     return ret;
514 }
515
516 static BOOL register_parent_wnd_class(BOOL Unicode)
517 {
518     WNDCLASSA clsA;
519     WNDCLASSW clsW;
520
521     if (Unicode)
522     {
523         clsW.style = 0;
524         clsW.lpfnWndProc = parent_wnd_proc;
525         clsW.cbClsExtra = 0;
526         clsW.cbWndExtra = 0;
527         clsW.hInstance = GetModuleHandleW(NULL);
528         clsW.hIcon = 0;
529         clsW.hCursor = LoadCursorA(0, IDC_ARROW);
530         clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
531         clsW.lpszMenuName = NULL;
532         clsW.lpszClassName = testparentclassW;
533     }
534     else
535     {
536         clsA.style = 0;
537         clsA.lpfnWndProc = parent_wnd_proc;
538         clsA.cbClsExtra = 0;
539         clsA.cbWndExtra = 0;
540         clsA.hInstance = GetModuleHandleA(NULL);
541         clsA.hIcon = 0;
542         clsA.hCursor = LoadCursorA(0, IDC_ARROW);
543         clsA.hbrBackground = GetStockObject(WHITE_BRUSH);
544         clsA.lpszMenuName = NULL;
545         clsA.lpszClassName = "Listview test parent class";
546     }
547
548     return Unicode ? RegisterClassW(&clsW) : RegisterClassA(&clsA);
549 }
550
551 static HWND create_parent_window(BOOL Unicode)
552 {
553     static const WCHAR nameW[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W',0};
554     HWND hwnd;
555
556     if (!register_parent_wnd_class(Unicode))
557         return NULL;
558
559     blockEdit = FALSE;
560     notifyFormat = -1;
561
562     if (Unicode)
563         hwnd = CreateWindowExW(0, testparentclassW, nameW,
564                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
565                                WS_MAXIMIZEBOX | WS_VISIBLE,
566                                0, 0, 100, 100,
567                                GetDesktopWindow(), NULL, GetModuleHandleW(NULL), NULL);
568     else
569         hwnd = CreateWindowExA(0, "Listview test parent class",
570                                "Listview test parent window",
571                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
572                                WS_MAXIMIZEBOX | WS_VISIBLE,
573                                0, 0, 100, 100,
574                                GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
575     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
576     return hwnd;
577 }
578
579 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
580 {
581     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
582     static LONG defwndproc_counter = 0;
583     LRESULT ret;
584     struct message msg;
585
586     trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
587
588     /* some debug output for style changing */
589     if ((message == WM_STYLECHANGING ||
590          message == WM_STYLECHANGED) && lParam)
591     {
592         STYLESTRUCT *style = (STYLESTRUCT*)lParam;
593         trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
594     }
595
596     msg.message = message;
597     msg.flags = sent|wparam|lparam;
598     if (defwndproc_counter) msg.flags |= defwinproc;
599     msg.wParam = wParam;
600     msg.lParam = lParam;
601     msg.id = LISTVIEW_ID;
602     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
603     add_message(sequences, COMBINED_SEQ_INDEX, &msg);
604
605     defwndproc_counter++;
606     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
607     defwndproc_counter--;
608     return ret;
609 }
610
611 static HWND create_listview_control(DWORD style)
612 {
613     WNDPROC oldproc;
614     HWND hwnd;
615     RECT rect;
616
617     GetClientRect(hwndparent, &rect);
618     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
619                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
620                            0, 0, rect.right, rect.bottom,
621                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
622     ok(hwnd != NULL, "gle=%d\n", GetLastError());
623
624     if (!hwnd) return NULL;
625
626     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
627                                         (LONG_PTR)listview_subclass_proc);
628     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
629
630     return hwnd;
631 }
632
633 /* unicode listview window with specified parent */
634 static HWND create_listview_controlW(DWORD style, HWND parent)
635 {
636     WNDPROC oldproc;
637     HWND hwnd;
638     RECT rect;
639     static const WCHAR nameW[] = {'f','o','o',0};
640
641     GetClientRect(parent, &rect);
642     hwnd = CreateWindowExW(0, WC_LISTVIEWW, nameW,
643                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
644                            0, 0, rect.right, rect.bottom,
645                            parent, NULL, GetModuleHandleW(NULL), NULL);
646     ok(hwnd != NULL, "gle=%d\n", GetLastError());
647
648     if (!hwnd) return NULL;
649
650     oldproc = (WNDPROC)SetWindowLongPtrW(hwnd, GWLP_WNDPROC,
651                                         (LONG_PTR)listview_subclass_proc);
652     SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
653
654     return hwnd;
655 }
656
657 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
658 {
659     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
660     static LONG defwndproc_counter = 0;
661     LRESULT ret;
662     struct message msg;
663
664     trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
665
666     msg.message = message;
667     msg.flags = sent|wparam|lparam;
668     if (defwndproc_counter) msg.flags |= defwinproc;
669     msg.wParam = wParam;
670     msg.lParam = lParam;
671     msg.id = HEADER_ID;
672     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
673
674     defwndproc_counter++;
675     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
676     defwndproc_counter--;
677     return ret;
678 }
679
680 static HWND subclass_header(HWND hwndListview)
681 {
682     WNDPROC oldproc;
683     HWND hwnd;
684
685     hwnd = ListView_GetHeader(hwndListview);
686     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
687                                          (LONG_PTR)header_subclass_proc);
688     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
689
690     return hwnd;
691 }
692
693 static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
694 {
695     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
696     static LONG defwndproc_counter = 0;
697     LRESULT ret;
698     struct message msg;
699
700     msg.message = message;
701     msg.flags = sent|wparam|lparam;
702     if (defwndproc_counter) msg.flags |= defwinproc;
703     msg.wParam = wParam;
704     msg.lParam = lParam;
705     msg.id = 0;
706
707     /* all we need is sizing */
708     if (message == WM_WINDOWPOSCHANGING ||
709         message == WM_NCCALCSIZE ||
710         message == WM_WINDOWPOSCHANGED ||
711         message == WM_MOVE ||
712         message == WM_SIZE)
713     {
714         add_message(sequences, EDITBOX_SEQ_INDEX, &msg);
715     }
716
717     defwndproc_counter++;
718     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
719     defwndproc_counter--;
720     return ret;
721 }
722
723 static HWND subclass_editbox(HWND hwndListview)
724 {
725     WNDPROC oldproc;
726     HWND hwnd;
727
728     hwnd = (HWND)SendMessage(hwndListview, LVM_GETEDITCONTROL, 0, 0);
729     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
730                                          (LONG_PTR)editbox_subclass_proc);
731     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
732
733     return hwnd;
734 }
735
736 /* Performs a single LVM_HITTEST test */
737 static void test_lvm_hittest_(HWND hwnd, INT x, INT y, INT item, UINT flags, UINT broken_flags,
738                               BOOL todo_item, BOOL todo_flags, int line)
739 {
740     LVHITTESTINFO lpht;
741     INT ret;
742
743     lpht.pt.x = x;
744     lpht.pt.y = y;
745     lpht.iSubItem = 10;
746
747     ret = SendMessage(hwnd, LVM_HITTEST, 0, (LPARAM)&lpht);
748
749     if (todo_item)
750     {
751         todo_wine
752         {
753             ok_(__FILE__, line)(ret == item, "Expected %d retval, got %d\n", item, ret);
754             ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
755             ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
756         }
757     }
758     else
759     {
760         ok_(__FILE__, line)(ret == item, "Expected %d retval, got %d\n", item, ret);
761         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
762         ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
763     }
764
765     if (todo_flags)
766     {
767         todo_wine
768             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags);
769     }
770     else if (broken_flags)
771         ok_(__FILE__, line)(lpht.flags == flags || broken(lpht.flags == broken_flags),
772                             "Expected flags %x, got %x\n", flags, lpht.flags);
773     else
774         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags);
775 }
776
777 #define test_lvm_hittest(a,b,c,d,e,f,g,h) test_lvm_hittest_(a,b,c,d,e,f,g,h,__LINE__)
778
779 /* Performs a single LVM_SUBITEMHITTEST test */
780 static void test_lvm_subitemhittest_(HWND hwnd, INT x, INT y, INT item, INT subitem, UINT flags,
781                                      BOOL todo_item, BOOL todo_subitem, BOOL todo_flags, int line)
782 {
783     LVHITTESTINFO lpht;
784     INT ret;
785
786     lpht.pt.x = x;
787     lpht.pt.y = y;
788
789     ret = SendMessage(hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM)&lpht);
790
791     if (todo_item)
792     {
793         todo_wine
794         {
795             ok_(__FILE__, line)(ret == item, "Expected %d retval, got %d\n", item, ret);
796             ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
797         }
798     }
799     else
800     {
801         ok_(__FILE__, line)(ret == item, "Expected %d retval, got %d\n", item, ret);
802         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
803     }
804
805     if (todo_subitem)
806     {
807         todo_wine
808             ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
809     }
810     else
811         ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
812
813     if (todo_flags)
814     {
815         todo_wine
816             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags);
817     }
818     else
819         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags);
820 }
821
822 #define test_lvm_subitemhittest(a,b,c,d,e,f,g,h,i) test_lvm_subitemhittest_(a,b,c,d,e,f,g,h,i,__LINE__)
823
824 static void test_images(void)
825 {
826     HWND hwnd;
827     INT r;
828     LVITEM item;
829     HIMAGELIST himl;
830     HBITMAP hbmp;
831     RECT r1, r2;
832     static CHAR hello[] = "hello";
833
834     himl = ImageList_Create(40, 40, 0, 4, 4);
835     ok(himl != NULL, "failed to create imagelist\n");
836
837     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
838     ok(hbmp != NULL, "failed to create bitmap\n");
839
840     r = ImageList_Add(himl, hbmp, 0);
841     ok(r == 0, "should be zero\n");
842
843     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED, 
844                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
845     ok(hwnd != NULL, "failed to create listview window\n");
846
847     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
848                     LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE);
849
850     ok(r == 0, "should return zero\n");
851
852     r = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
853     ok(r == 0, "should return zero\n");
854
855     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
856     ok(r != 0, "got 0\n");
857
858     /* returns dimensions */
859
860     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
861     ok(r == 0, "should be zero items\n");
862
863     item.mask = LVIF_IMAGE | LVIF_TEXT;
864     item.iItem = 0;
865     item.iSubItem = 1;
866     item.iImage = 0;
867     item.pszText = 0;
868     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
869     ok(r == -1, "should fail\n");
870
871     item.iSubItem = 0;
872     item.pszText = hello;
873     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
874     ok(r == 0, "should not fail\n");
875
876     memset(&r1, 0, sizeof r1);
877     r1.left = LVIR_ICON;
878     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
879     expect(1, r);
880
881     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
882     ok(r == TRUE, "should not fail\n");
883
884     item.iSubItem = 0;
885     item.pszText = hello;
886     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
887     ok(r == 0, "should not fail\n");
888
889     memset(&r2, 0, sizeof r2);
890     r2.left = LVIR_ICON;
891     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
892     expect(1, r);
893
894     ok(!memcmp(&r1, &r2, sizeof r1), "rectangle should be the same\n");
895
896     DestroyWindow(hwnd);
897 }
898
899 static void test_checkboxes(void)
900 {
901     HWND hwnd;
902     LVITEMA item;
903     DWORD r;
904     static CHAR text[]  = "Text",
905                 text2[] = "Text2",
906                 text3[] = "Text3";
907
908     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT, 
909                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
910     ok(hwnd != NULL, "failed to create listview window\n");
911
912     /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
913     item.mask = LVIF_TEXT | LVIF_STATE;
914     item.stateMask = 0xffff;
915     item.state = 0xfccc;
916     item.iItem = 0;
917     item.iSubItem = 0;
918     item.pszText = text;
919     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
920     expect(0, r);
921
922     item.iItem = 0;
923     item.mask = LVIF_STATE;
924     item.stateMask = 0xffff;
925     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
926     expect(1, r);
927     ok(item.state == 0xfccc, "state %x\n", item.state);
928
929     /* Don't set LVIF_STATE */
930     item.mask = LVIF_TEXT;
931     item.stateMask = 0xffff;
932     item.state = 0xfccc;
933     item.iItem = 1;
934     item.iSubItem = 0;
935     item.pszText = text;
936     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
937     expect(1, r);
938
939     item.iItem = 1;
940     item.mask = LVIF_STATE;
941     item.stateMask = 0xffff;
942     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
943     expect(1, r);
944     ok(item.state == 0, "state %x\n", item.state);
945
946     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
947     expect(0, r);
948
949     /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
950     item.iItem = 0;
951     item.mask = LVIF_STATE;
952     item.stateMask = 0xffff;
953     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
954     expect(1, r);
955     if (item.state != 0x1ccc)
956     {
957         win_skip("LVS_EX_CHECKBOXES style is unavailable. Skipping.\n");
958         DestroyWindow(hwnd);
959         return;
960     }
961
962     /* Now add an item without specifying a state and check that its state goes to 0x1000 */
963     item.iItem = 2;
964     item.mask = LVIF_TEXT;
965     item.state = 0;
966     item.pszText = text2;
967     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
968     expect(2, r);
969
970     item.iItem = 2;
971     item.mask = LVIF_STATE;
972     item.stateMask = 0xffff;
973     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
974     expect(1, r);
975     ok(item.state == 0x1000, "state %x\n", item.state);
976
977     /* Add a further item this time specifying a state and still its state goes to 0x1000 */
978     item.iItem = 3;
979     item.mask = LVIF_TEXT | LVIF_STATE;
980     item.stateMask = 0xffff;
981     item.state = 0x2aaa;
982     item.pszText = text3;
983     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
984     expect(3, r);
985
986     item.iItem = 3;
987     item.mask = LVIF_STATE;
988     item.stateMask = 0xffff;
989     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
990     expect(1, r);
991     ok(item.state == 0x1aaa, "state %x\n", item.state);
992
993     /* Set an item's state to checked */
994     item.iItem = 3;
995     item.mask = LVIF_STATE;
996     item.stateMask = 0xf000;
997     item.state = 0x2000;
998     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
999     expect(1, r);
1000
1001     item.iItem = 3;
1002     item.mask = LVIF_STATE;
1003     item.stateMask = 0xffff;
1004     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1005     expect(1, r);
1006     ok(item.state == 0x2aaa, "state %x\n", item.state);
1007
1008     /* Check that only the bits we asked for are returned,
1009      * and that all the others are set to zero
1010      */
1011     item.iItem = 3;
1012     item.mask = LVIF_STATE;
1013     item.stateMask = 0xf000;
1014     item.state = 0xffff;
1015     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1016     expect(1, r);
1017     ok(item.state == 0x2000, "state %x\n", item.state);
1018
1019     /* Set the style again and check that doesn't change an item's state */
1020     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
1021     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
1022
1023     item.iItem = 3;
1024     item.mask = LVIF_STATE;
1025     item.stateMask = 0xffff;
1026     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1027     expect(1, r);
1028     ok(item.state == 0x2aaa, "state %x\n", item.state);
1029
1030     /* Unsetting the checkbox extended style doesn't change an item's state */
1031     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
1032     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
1033
1034     item.iItem = 3;
1035     item.mask = LVIF_STATE;
1036     item.stateMask = 0xffff;
1037     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1038     expect(1, r);
1039     ok(item.state == 0x2aaa, "state %x\n", item.state);
1040
1041     /* Now setting the style again will change an item's state */
1042     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
1043     expect(0, r);
1044
1045     item.iItem = 3;
1046     item.mask = LVIF_STATE;
1047     item.stateMask = 0xffff;
1048     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1049     expect(1, r);
1050     ok(item.state == 0x1aaa, "state %x\n", item.state);
1051
1052     /* Toggle checkbox tests (bug 9934) */
1053     memset (&item, 0xcc, sizeof(item));
1054     item.mask = LVIF_STATE;
1055     item.iItem = 3;
1056     item.iSubItem = 0;
1057     item.state = LVIS_FOCUSED;
1058     item.stateMask = LVIS_FOCUSED;
1059     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1060     expect(1, r);
1061
1062     item.iItem = 3;
1063     item.mask = LVIF_STATE;
1064     item.stateMask = 0xffff;
1065     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1066     expect(1, r);
1067     ok(item.state == 0x1aab, "state %x\n", item.state);
1068
1069     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
1070     expect(0, r);
1071     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
1072     expect(0, r);
1073
1074     item.iItem = 3;
1075     item.mask = LVIF_STATE;
1076     item.stateMask = 0xffff;
1077     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1078     expect(1, r);
1079     ok(item.state == 0x2aab, "state %x\n", item.state);
1080
1081     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
1082     expect(0, r);
1083     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
1084     expect(0, r);
1085
1086     item.iItem = 3;
1087     item.mask = LVIF_STATE;
1088     item.stateMask = 0xffff;
1089     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1090     expect(1, r);
1091     ok(item.state == 0x1aab, "state %x\n", item.state);
1092
1093     DestroyWindow(hwnd);
1094 }
1095
1096 static void insert_column(HWND hwnd, int idx)
1097 {
1098     LVCOLUMN column;
1099     INT rc;
1100
1101     memset(&column, 0xcc, sizeof(column));
1102     column.mask = LVCF_SUBITEM;
1103     column.iSubItem = idx;
1104
1105     rc = ListView_InsertColumn(hwnd, idx, &column);
1106     expect(idx, rc);
1107 }
1108
1109 static void insert_item(HWND hwnd, int idx)
1110 {
1111     static CHAR text[] = "foo";
1112
1113     LVITEMA item;
1114     INT rc;
1115
1116     memset(&item, 0xcc, sizeof (item));
1117     item.mask = LVIF_TEXT;
1118     item.iItem = idx;
1119     item.iSubItem = 0;
1120     item.pszText = text;
1121
1122     rc = ListView_InsertItem(hwnd, &item);
1123     expect(idx, rc);
1124 }
1125
1126 static void test_items(void)
1127 {
1128     const LPARAM lparamTest = 0x42;
1129     static CHAR text[] = "Text";
1130     char buffA[5];
1131     HWND hwnd;
1132     LVITEMA item;
1133     DWORD r;
1134
1135     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
1136                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1137     ok(hwnd != NULL, "failed to create listview window\n");
1138
1139     /*
1140      * Test setting/getting item params
1141      */
1142
1143     /* Set up two columns */
1144     insert_column(hwnd, 0);
1145     insert_column(hwnd, 1);
1146
1147     /* LVIS_SELECTED with zero stateMask */
1148     /* set */
1149     memset (&item, 0, sizeof (item));
1150     item.mask = LVIF_STATE;
1151     item.state = LVIS_SELECTED;
1152     item.stateMask = 0;
1153     item.iItem = 0;
1154     item.iSubItem = 0;
1155     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1156     expect(0, r);
1157     /* get */
1158     memset (&item, 0xcc, sizeof (item));
1159     item.mask = LVIF_STATE;
1160     item.stateMask = LVIS_SELECTED;
1161     item.state = 0;
1162     item.iItem = 0;
1163     item.iSubItem = 0;
1164     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1165     expect(1, r);
1166     ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
1167     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1168
1169     /* LVIS_SELECTED with zero stateMask */
1170     /* set */
1171     memset (&item, 0, sizeof (item));
1172     item.mask = LVIF_STATE;
1173     item.state = LVIS_FOCUSED;
1174     item.stateMask = 0;
1175     item.iItem = 0;
1176     item.iSubItem = 0;
1177     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1178     expect(0, r);
1179     /* get */
1180     memset (&item, 0xcc, sizeof (item));
1181     item.mask = LVIF_STATE;
1182     item.stateMask = LVIS_FOCUSED;
1183     item.state = 0;
1184     item.iItem = 0;
1185     item.iSubItem = 0;
1186     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1187     expect(1, r);
1188     ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
1189     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1190
1191     /* LVIS_CUT with LVIS_FOCUSED stateMask */
1192     /* set */
1193     memset (&item, 0, sizeof (item));
1194     item.mask = LVIF_STATE;
1195     item.state = LVIS_CUT;
1196     item.stateMask = LVIS_FOCUSED;
1197     item.iItem = 0;
1198     item.iSubItem = 0;
1199     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1200     expect(0, r);
1201     /* get */
1202     memset (&item, 0xcc, sizeof (item));
1203     item.mask = LVIF_STATE;
1204     item.stateMask = LVIS_CUT;
1205     item.state = 0;
1206     item.iItem = 0;
1207     item.iSubItem = 0;
1208     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1209     expect(1, r);
1210     ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
1211     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1212
1213     /* Insert an item with just a param */
1214     memset (&item, 0xcc, sizeof (item));
1215     item.mask = LVIF_PARAM;
1216     item.iItem = 0;
1217     item.iSubItem = 0;
1218     item.lParam = lparamTest;
1219     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1220     expect(0, r);
1221
1222     /* Test getting of the param */
1223     memset (&item, 0xcc, sizeof (item));
1224     item.mask = LVIF_PARAM;
1225     item.iItem = 0;
1226     item.iSubItem = 0;
1227     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1228     expect(1, r);
1229     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1230
1231     /* Set up a subitem */
1232     memset (&item, 0xcc, sizeof (item));
1233     item.mask = LVIF_TEXT;
1234     item.iItem = 0;
1235     item.iSubItem = 1;
1236     item.pszText = text;
1237     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1238     expect(1, r);
1239
1240     item.mask = LVIF_TEXT;
1241     item.iItem = 0;
1242     item.iSubItem = 1;
1243     item.pszText = buffA;
1244     item.cchTextMax = sizeof(buffA);
1245     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1246     expect(1, r);
1247     ok(!memcmp(item.pszText, text, sizeof(text)), "got text %s, expected %s\n", item.pszText, text);
1248
1249     /* set up with extra flag */
1250     /* 1. reset subitem text */
1251     item.mask = LVIF_TEXT;
1252     item.iItem = 0;
1253     item.iSubItem = 1;
1254     item.pszText = NULL;
1255     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1256     expect(1, r);
1257
1258     item.mask = LVIF_TEXT;
1259     item.iItem = 0;
1260     item.iSubItem = 1;
1261     item.pszText = buffA;
1262     buffA[0] = 'a';
1263     item.cchTextMax = sizeof(buffA);
1264     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1265     expect(1, r);
1266     ok(item.pszText[0] == 0, "got %p\n", item.pszText);
1267
1268     /* 2. set new text with extra flag specified */
1269     item.mask = LVIF_TEXT | LVIF_DI_SETITEM;
1270     item.iItem = 0;
1271     item.iSubItem = 1;
1272     item.pszText = text;
1273     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1274     ok(r == 1 || broken(r == 0) /* NT4 */, "ret %d\n", r);
1275
1276     if (r == 1)
1277     {
1278         item.mask = LVIF_TEXT;
1279         item.iItem = 0;
1280         item.iSubItem = 1;
1281         item.pszText = buffA;
1282         buffA[0] = 'a';
1283         item.cchTextMax = sizeof(buffA);
1284         r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1285         expect(1, r);
1286         ok(!memcmp(item.pszText, text, sizeof(text)), "got %s, expected %s\n", item.pszText, text);
1287     }
1288
1289     /* Query param from subitem: returns main item param */
1290     memset (&item, 0xcc, sizeof (item));
1291     item.mask = LVIF_PARAM;
1292     item.iItem = 0;
1293     item.iSubItem = 1;
1294     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1295     expect(1, r);
1296     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1297
1298     /* Set up param on first subitem: no effect */
1299     memset (&item, 0xcc, sizeof (item));
1300     item.mask = LVIF_PARAM;
1301     item.iItem = 0;
1302     item.iSubItem = 1;
1303     item.lParam = lparamTest+1;
1304     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1305     expect(0, r);
1306
1307     /* Query param from subitem again: should still return main item param */
1308     memset (&item, 0xcc, sizeof (item));
1309     item.mask = LVIF_PARAM;
1310     item.iItem = 0;
1311     item.iSubItem = 1;
1312     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1313     expect(1, r);
1314     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1315
1316     /**** Some tests of state highlighting ****/
1317     memset (&item, 0xcc, sizeof (item));
1318     item.mask = LVIF_STATE;
1319     item.iItem = 0;
1320     item.iSubItem = 0;
1321     item.state = LVIS_SELECTED;
1322     item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
1323     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1324     expect(1, r);
1325     item.iSubItem = 1;
1326     item.state = LVIS_DROPHILITED;
1327     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1328     expect(1, r);
1329
1330     memset (&item, 0xcc, sizeof (item));
1331     item.mask = LVIF_STATE;
1332     item.iItem = 0;
1333     item.iSubItem = 0;
1334     item.stateMask = -1;
1335     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1336     expect(1, r);
1337     ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
1338     item.iSubItem = 1;
1339     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1340     expect(1, r);
1341     todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
1342
1343     /* some notnull but meaningless masks */
1344     memset (&item, 0, sizeof(item));
1345     item.mask = LVIF_NORECOMPUTE;
1346     item.iItem = 0;
1347     item.iSubItem = 0;
1348     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1349     expect(1, r);
1350     memset (&item, 0, sizeof(item));
1351     item.mask = LVIF_DI_SETITEM;
1352     item.iItem = 0;
1353     item.iSubItem = 0;
1354     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1355     expect(1, r);
1356
1357     /* set text to callback value already having it */
1358     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1359     expect(TRUE, r);
1360     memset (&item, 0, sizeof (item));
1361     item.mask  = LVIF_TEXT;
1362     item.pszText = LPSTR_TEXTCALLBACK;
1363     item.iItem = 0;
1364     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1365     expect(0, r);
1366     memset (&item, 0, sizeof (item));
1367
1368     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1369
1370     item.pszText = LPSTR_TEXTCALLBACK;
1371     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0 , (LPARAM) &item);
1372     expect(TRUE, r);
1373
1374     ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq,
1375                 "check callback text comparison rule", FALSE);
1376
1377     DestroyWindow(hwnd);
1378 }
1379
1380 static void test_columns(void)
1381 {
1382     HWND hwnd;
1383     LVCOLUMNA column;
1384     LVITEMA item;
1385     INT order[2];
1386     CHAR buff[5];
1387     DWORD rc;
1388
1389     hwnd = CreateWindowExA(0, "SysListView32", "foo", LVS_REPORT,
1390                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1391     ok(hwnd != NULL, "failed to create listview window\n");
1392
1393     /* Add a column with no mask */
1394     memset(&column, 0xcc, sizeof(column));
1395     column.mask = 0;
1396     rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&column);
1397     ok(rc == 0, "Inserting column with no mask failed with %d\n", rc);
1398
1399     /* Check its width */
1400     rc = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
1401     ok(rc == 10, "Inserting column with no mask failed to set width to 10 with %d\n", rc);
1402
1403     DestroyWindow(hwnd);
1404
1405     /* LVM_GETCOLUMNORDERARRAY */
1406     hwnd = create_listview_control(LVS_REPORT);
1407     subclass_header(hwnd);
1408
1409     memset(&column, 0, sizeof(column));
1410     column.mask = LVCF_WIDTH;
1411     column.cx = 100;
1412     rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&column);
1413     expect(0, rc);
1414
1415     column.cx = 200;
1416     rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 1, (LPARAM)&column);
1417     expect(1, rc);
1418
1419     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1420
1421     rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
1422     expect(1, rc);
1423     ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
1424     ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
1425
1426     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
1427
1428     /* after column added subitem is considered as present */
1429     insert_item(hwnd, 0);
1430
1431     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1432
1433     item.pszText = buff;
1434     item.cchTextMax = sizeof(buff);
1435     item.iItem = 0;
1436     item.iSubItem = 1;
1437     item.mask = LVIF_TEXT;
1438     memset(&g_itema, 0, sizeof(g_itema));
1439     rc = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
1440     expect(1, rc);
1441     ok(g_itema.iSubItem == 1, "got %d\n", g_itema.iSubItem);
1442
1443     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
1444         "get subitem text after column added", FALSE);
1445
1446     DestroyWindow(hwnd);
1447 }
1448
1449 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1450 static WNDPROC listviewWndProc;
1451 static HIMAGELIST test_create_imagelist;
1452
1453 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1454 {
1455     LRESULT ret;
1456
1457     if (uMsg == WM_CREATE)
1458     {
1459         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
1460         lpcs->style |= LVS_REPORT;
1461     }
1462     ret = CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
1463     if (uMsg == WM_CREATE) SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
1464     return ret;
1465 }
1466
1467 static void test_create(void)
1468 {
1469     HWND hList;
1470     HWND hHeader;
1471     LONG_PTR ret;
1472     LONG r;
1473     LVCOLUMNA col;
1474     RECT rect;
1475     WNDCLASSEX cls;
1476     DWORD style;
1477
1478     cls.cbSize = sizeof(WNDCLASSEX);
1479     ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
1480     listviewWndProc = cls.lpfnWndProc;
1481     cls.lpfnWndProc = create_test_wndproc;
1482     cls.lpszClassName = "MyListView32";
1483     ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
1484
1485     test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
1486     hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1487     ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
1488     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1489
1490     if (!IsWindow(hHeader))
1491     {
1492         /* version 4.0 */
1493         win_skip("LVM_GETHEADER not implemented. Skipping.\n");
1494         DestroyWindow(hList);
1495         return;
1496     }
1497
1498     ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
1499     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1500     DestroyWindow(hList);
1501
1502     /* header isn't created on LVS_ICON and LVS_LIST styles */
1503     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1504                           GetModuleHandle(NULL), 0);
1505     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1506     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1507     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1508     /* insert column */
1509     memset(&col, 0, sizeof(LVCOLUMNA));
1510     col.mask = LVCF_WIDTH;
1511     col.cx = 100;
1512     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1513     expect(0, r);
1514     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1515     ok(IsWindow(hHeader), "Header should be created\n");
1516     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1517     style = GetWindowLong(hHeader, GWL_STYLE);
1518     ok(!(style & HDS_HIDDEN), "Not expected HDS_HIDDEN\n");
1519     DestroyWindow(hList);
1520
1521     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1522                           GetModuleHandle(NULL), 0);
1523     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1524     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1525     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1526     /* insert column */
1527     memset(&col, 0, sizeof(LVCOLUMNA));
1528     col.mask = LVCF_WIDTH;
1529     col.cx = 100;
1530     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1531     expect(0, r);
1532     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1533     ok(IsWindow(hHeader), "Header should be created\n");
1534     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1535     DestroyWindow(hList);
1536
1537     /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1538     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1539                           GetModuleHandle(NULL), 0);
1540     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLongPtr(hList, GWL_STYLE) | LVS_REPORT);
1541     ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
1542     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1543     ok(IsWindow(hHeader), "Header should be created\n");
1544     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) & ~LVS_REPORT);
1545     ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1546     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1547     ok(IsWindow(hHeader), "Header should be created\n");
1548     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1549     DestroyWindow(hList);
1550
1551     /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1552     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1553                           GetModuleHandle(NULL), 0);
1554     ret = SetWindowLongPtr(hList, GWL_STYLE,
1555                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
1556     ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1557     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1558     ok(IsWindow(hHeader), "Header should be created\n");
1559     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1560     ret = SetWindowLongPtr(hList, GWL_STYLE,
1561                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
1562     ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1563     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1564     ok(IsWindow(hHeader), "Header should be created\n");
1565     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1566     DestroyWindow(hList);
1567
1568     /* LVS_REPORT without WS_VISIBLE */
1569     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1570                           GetModuleHandle(NULL), 0);
1571     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1572     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1573     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1574     /* insert column */
1575     memset(&col, 0, sizeof(LVCOLUMNA));
1576     col.mask = LVCF_WIDTH;
1577     col.cx = 100;
1578     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1579     expect(0, r);
1580     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1581     ok(IsWindow(hHeader), "Header should be created\n");
1582     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1583     DestroyWindow(hList);
1584
1585     /* LVS_REPORT without WS_VISIBLE, try to show it */
1586     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1587                           GetModuleHandle(NULL), 0);
1588     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1589     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1590     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1591     ShowWindow(hList, SW_SHOW);
1592     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1593     ok(IsWindow(hHeader), "Header should be created\n");
1594     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1595     DestroyWindow(hList);
1596
1597     /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1598     hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1599                           0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1600     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1601     ok(IsWindow(hHeader), "Header should be created\n");
1602     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1603     /* HDS_DRAGDROP set by default */
1604     ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1605     DestroyWindow(hList);
1606
1607     /* setting LVS_EX_HEADERDRAGDROP creates header */
1608     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1609                           GetModuleHandle(NULL), 0);
1610     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1611     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1612     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1613     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1614     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1615     ok(IsWindow(hHeader) ||
1616        broken(!IsWindow(hHeader)), /* 4.7x common controls */
1617        "Header should be created\n");
1618     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1619     DestroyWindow(hList);
1620
1621     /* setting LVS_EX_GRIDLINES creates header */
1622     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1623                           GetModuleHandle(NULL), 0);
1624     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1625     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1626     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1627     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES);
1628     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1629     ok(IsWindow(hHeader) ||
1630        broken(!IsWindow(hHeader)), /* 4.7x common controls */
1631        "Header should be created\n");
1632     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1633     DestroyWindow(hList);
1634
1635     /* setting LVS_EX_FULLROWSELECT creates header */
1636     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1637                           GetModuleHandle(NULL), 0);
1638     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1639     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1640     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1641     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
1642     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1643     ok(IsWindow(hHeader) ||
1644        broken(!IsWindow(hHeader)), /* 4.7x common controls */
1645        "Header should be created\n");
1646     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1647     DestroyWindow(hList);
1648
1649     /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1650     hList = create_listview_control(LVS_ICON);
1651     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1652     r = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1653     ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1654     DestroyWindow(hList);
1655
1656     /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1657     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1658                           GetModuleHandle(NULL), 0);
1659     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1660     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1661
1662     rect.left = LVIR_BOUNDS;
1663     rect.top  = 1;
1664     rect.right = rect.bottom = -10;
1665     r = SendMessage(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1666     /* right value contains garbage, probably because header columns are not set up */
1667     expect(0, rect.bottom);
1668     expect(1, r);
1669
1670     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1671     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1672     ok(GetDlgItem(hList, 0) == NULL, "NULL dialog item expected\n");
1673
1674     DestroyWindow(hList);
1675
1676     /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1677     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1678     hList = create_listview_control(LVS_OWNERDRAWFIXED | LVS_REPORT);
1679     ok_sequence(sequences, PARENT_SEQ_INDEX, create_ownerdrawfixed_parent_seq,
1680                 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE);
1681     DestroyWindow(hList);
1682 }
1683
1684 static void test_redraw(void)
1685 {
1686     HWND hwnd;
1687     HDC hdc;
1688     BOOL res;
1689     DWORD r;
1690
1691     hwnd = create_listview_control(LVS_REPORT);
1692     subclass_header(hwnd);
1693
1694     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1695
1696     InvalidateRect(hwnd, NULL, TRUE);
1697     UpdateWindow(hwnd);
1698     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1699
1700     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1701
1702     /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1703     /* 1. Without backbuffer */
1704     res = ListView_SetBkColor(hwnd, CLR_NONE);
1705     expect(TRUE, res);
1706
1707     hdc = GetWindowDC(hwndparent);
1708
1709     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1710     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1711     ok(r == 1, "Expected not zero result\n");
1712     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1713                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1714
1715     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1716     expect(TRUE, res);
1717
1718     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1719     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1720     expect(1, r);
1721     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1722                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1723
1724     /* 2. With backbuffer */
1725     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1726                                                      LVS_EX_DOUBLEBUFFER);
1727     res = ListView_SetBkColor(hwnd, CLR_NONE);
1728     expect(TRUE, res);
1729
1730     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1731     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1732     expect(1, r);
1733     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1734                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1735
1736     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1737     expect(TRUE, res);
1738
1739     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1740     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1741     todo_wine expect(1, r);
1742     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1743                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1744
1745     ReleaseDC(hwndparent, hdc);
1746
1747     DestroyWindow(hwnd);
1748 }
1749
1750 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1751 {
1752     COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1753
1754     if(msg == WM_NOTIFY) {
1755         NMHDR *nmhdr = (PVOID)lp;
1756         if(nmhdr->code == NM_CUSTOMDRAW) {
1757             NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
1758             trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
1759             switch(nmlvcd->nmcd.dwDrawStage) {
1760             case CDDS_PREPAINT:
1761                 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1762                 return CDRF_NOTIFYITEMDRAW;
1763             case CDDS_ITEMPREPAINT:
1764                 nmlvcd->clrTextBk = CLR_DEFAULT;
1765                 return CDRF_NOTIFYSUBITEMDRAW;
1766             case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1767                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1768                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1769                 return CDRF_NOTIFYPOSTPAINT;
1770             case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1771                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1772                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1773                 return CDRF_DODEFAULT;
1774             }
1775             return CDRF_DODEFAULT;
1776         }
1777     }
1778
1779     return DefWindowProcA(hwnd, msg, wp, lp);
1780 }
1781
1782 static void test_customdraw(void)
1783 {
1784     HWND hwnd;
1785     WNDPROC oldwndproc;
1786
1787     hwnd = create_listview_control(LVS_REPORT);
1788
1789     insert_column(hwnd, 0);
1790     insert_column(hwnd, 1);
1791     insert_item(hwnd, 0);
1792
1793     oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
1794                                            (LONG_PTR)cd_wndproc);
1795
1796     InvalidateRect(hwnd, NULL, TRUE);
1797     UpdateWindow(hwnd);
1798
1799     SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1800
1801     DestroyWindow(hwnd);
1802 }
1803
1804 static void test_icon_spacing(void)
1805 {
1806     /* LVM_SETICONSPACING */
1807     /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1808
1809     HWND hwnd;
1810     WORD w, h;
1811     INT r;
1812
1813     hwnd = create_listview_control(LVS_ICON);
1814     ok(hwnd != NULL, "failed to create a listview window\n");
1815
1816     r = SendMessage(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, NF_REQUERY);
1817     expect(NFR_ANSI, r);
1818
1819     /* reset the icon spacing to defaults */
1820     SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1821
1822     /* now we can request what the defaults are */
1823     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1824     w = LOWORD(r);
1825     h = HIWORD(r);
1826
1827     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1828
1829     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1830     ok(r == MAKELONG(w, h) ||
1831        broken(r == MAKELONG(w, w)), /* win98 */
1832        "Expected %d, got %d\n", MAKELONG(w, h), r);
1833
1834     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1835     if (r == 0)
1836     {
1837         /* version 4.0 */
1838         win_skip("LVM_SETICONSPACING unimplemented. Skipping.\n");
1839         DestroyWindow(hwnd);
1840         return;
1841     }
1842     expect(MAKELONG(20,30), r);
1843
1844     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1845     expect(MAKELONG(25,35), r);
1846
1847     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1848
1849     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1850     DestroyWindow(hwnd);
1851 }
1852
1853 static void test_color(void)
1854 {
1855     RECT rect;
1856     HWND hwnd;
1857     DWORD r;
1858     int i;
1859
1860     COLORREF color;
1861     COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1862
1863     hwnd = create_listview_control(LVS_REPORT);
1864     ok(hwnd != NULL, "failed to create a listview window\n");
1865
1866     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1867
1868     for (i = 0; i < 4; i++)
1869     {
1870         color = colors[i];
1871
1872         r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
1873         expect(TRUE, r);
1874         r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, 0);
1875         expect(color, r);
1876
1877         r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
1878         expect (TRUE, r);
1879         r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, 0);
1880         expect(color, r);
1881
1882         r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
1883         expect(TRUE, r);
1884         r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, 0);
1885         expect(color, r);
1886     }
1887
1888     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
1889     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1890
1891     /* invalidation test done separately to avoid a message chain mess */
1892     r = ValidateRect(hwnd, NULL);
1893     expect(TRUE, r);
1894     r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, colors[0]);
1895     expect(TRUE, r);
1896
1897     rect.right = rect.bottom = 1;
1898     r = GetUpdateRect(hwnd, &rect, TRUE);
1899     todo_wine expect(FALSE, r);
1900     ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n");
1901
1902     r = ValidateRect(hwnd, NULL);
1903     expect(TRUE, r);
1904     r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, colors[0]);
1905     expect(TRUE, r);
1906
1907     rect.right = rect.bottom = 1;
1908     r = GetUpdateRect(hwnd, &rect, TRUE);
1909     todo_wine expect(FALSE, r);
1910     ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n");
1911
1912     r = ValidateRect(hwnd, NULL);
1913     expect(TRUE, r);
1914     r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, colors[0]);
1915     expect(TRUE, r);
1916
1917     rect.right = rect.bottom = 1;
1918     r = GetUpdateRect(hwnd, &rect, TRUE);
1919     todo_wine expect(FALSE, r);
1920     ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n");
1921
1922     DestroyWindow(hwnd);
1923 }
1924
1925 static void test_item_count(void)
1926 {
1927     /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1928
1929     HWND hwnd;
1930     DWORD r;
1931     HDC hdc;
1932     HFONT hOldFont;
1933     TEXTMETRICA tm;
1934     RECT rect;
1935     INT height;
1936
1937     LVITEM item0;
1938     LVITEM item1;
1939     LVITEM item2;
1940     static CHAR item0text[] = "item0";
1941     static CHAR item1text[] = "item1";
1942     static CHAR item2text[] = "item2";
1943
1944     hwnd = create_listview_control(LVS_REPORT);
1945     ok(hwnd != NULL, "failed to create a listview window\n");
1946
1947     /* resize in dpiaware manner to fit all 3 items added */
1948     hdc = GetDC(0);
1949     hOldFont = SelectObject(hdc, GetStockObject(SYSTEM_FONT));
1950     GetTextMetricsA(hdc, &tm);
1951     /* 2 extra pixels for bounds and header border */
1952     height = tm.tmHeight + 2;
1953     SelectObject(hdc, hOldFont);
1954     ReleaseDC(0, hdc);
1955
1956     GetWindowRect(hwnd, &rect);
1957     /* 3 items + 1 header + 1 to be sure */
1958     MoveWindow(hwnd, 0, 0, rect.right - rect.left, 5 * height, FALSE);
1959
1960     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1961
1962     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1963     expect(0, r);
1964
1965     /* [item0] */
1966     item0.mask = LVIF_TEXT;
1967     item0.iItem = 0;
1968     item0.iSubItem = 0;
1969     item0.pszText = item0text;
1970     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1971     expect(0, r);
1972
1973     /* [item0, item1] */
1974     item1.mask = LVIF_TEXT;
1975     item1.iItem = 1;
1976     item1.iSubItem = 0;
1977     item1.pszText = item1text;
1978     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1979     expect(1, r);
1980
1981     /* [item0, item1, item2] */
1982     item2.mask = LVIF_TEXT;
1983     item2.iItem = 2;
1984     item2.iSubItem = 0;
1985     item2.pszText = item2text;
1986     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1987     expect(2, r);
1988
1989     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1990     expect(3, r);
1991
1992     /* [item0, item1] */
1993     r = SendMessage(hwnd, LVM_DELETEITEM, 2, 0);
1994     expect(TRUE, r);
1995
1996     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1997     expect(2, r);
1998
1999     /* [] */
2000     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
2001     expect(TRUE, r);
2002
2003     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
2004     expect(0, r);
2005
2006     /* [item0] */
2007     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
2008     expect(0, r);
2009
2010     /* [item0, item1] */
2011     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
2012     expect(1, r);
2013
2014     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
2015     expect(2, r);
2016
2017     /* [item0, item1, item2] */
2018     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
2019     expect(2, r);
2020
2021     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
2022     expect(3, r);
2023
2024     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
2025
2026     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2027     DestroyWindow(hwnd);
2028 }
2029
2030 static void test_item_position(void)
2031 {
2032     /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
2033
2034     HWND hwnd;
2035     DWORD r;
2036     POINT position;
2037
2038     LVITEM item0;
2039     LVITEM item1;
2040     LVITEM item2;
2041     static CHAR item0text[] = "item0";
2042     static CHAR item1text[] = "item1";
2043     static CHAR item2text[] = "item2";
2044
2045     hwnd = create_listview_control(LVS_ICON);
2046     ok(hwnd != NULL, "failed to create a listview window\n");
2047
2048     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2049
2050     /* [item0] */
2051     item0.mask = LVIF_TEXT;
2052     item0.iItem = 0;
2053     item0.iSubItem = 0;
2054     item0.pszText = item0text;
2055     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
2056     expect(0, r);
2057
2058     /* [item0, item1] */
2059     item1.mask = LVIF_TEXT;
2060     item1.iItem = 1;
2061     item1.iSubItem = 0;
2062     item1.pszText = item1text;
2063     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
2064     expect(1, r);
2065
2066     /* [item0, item1, item2] */
2067     item2.mask = LVIF_TEXT;
2068     item2.iItem = 2;
2069     item2.iSubItem = 0;
2070     item2.pszText = item2text;
2071     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
2072     expect(2, r);
2073
2074     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
2075     expect(TRUE, r);
2076     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
2077     expect(TRUE, r);
2078     expect2(10, 5, position.x, position.y);
2079
2080     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
2081     expect(TRUE, r);
2082     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
2083     expect(TRUE, r);
2084     expect2(0, 0, position.x, position.y);
2085
2086     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
2087     expect(TRUE, r);
2088     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
2089     expect(TRUE, r);
2090     expect2(20, 20, position.x, position.y);
2091
2092     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
2093
2094     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2095     DestroyWindow(hwnd);
2096 }
2097
2098 static void test_getorigin(void)
2099 {
2100     /* LVM_GETORIGIN */
2101
2102     HWND hwnd;
2103     DWORD r;
2104     POINT position;
2105
2106     position.x = position.y = 0;
2107
2108     hwnd = create_listview_control(LVS_ICON);
2109     ok(hwnd != NULL, "failed to create a listview window\n");
2110     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2111
2112     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
2113     expect(TRUE, r);
2114     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2115     DestroyWindow(hwnd);
2116
2117     hwnd = create_listview_control(LVS_SMALLICON);
2118     ok(hwnd != NULL, "failed to create a listview window\n");
2119     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2120
2121     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
2122     expect(TRUE, r);
2123     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2124     DestroyWindow(hwnd);
2125
2126     hwnd = create_listview_control(LVS_LIST);
2127     ok(hwnd != NULL, "failed to create a listview window\n");
2128     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2129
2130     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
2131     expect(FALSE, r);
2132     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2133     DestroyWindow(hwnd);
2134
2135     hwnd = create_listview_control(LVS_REPORT);
2136     ok(hwnd != NULL, "failed to create a listview window\n");
2137     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2138
2139     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
2140     expect(FALSE, r);
2141     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2142     DestroyWindow(hwnd);
2143 }
2144
2145 static void test_multiselect(void)
2146 {
2147     typedef struct t_select_task
2148     {
2149         const char *descr;
2150         int initPos;
2151         int loopVK;
2152         int count;
2153         int result;
2154     } select_task;
2155
2156     HWND hwnd;
2157     INT r;
2158     int i,j,item_count,selected_count;
2159     static const int items=5;
2160     BYTE kstate[256];
2161     select_task task;
2162     LONG_PTR style;
2163     LVITEMA item;
2164
2165     static struct t_select_task task_list[] = {
2166         { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
2167         { "using VK_UP", -1, VK_UP, -1, -1 },
2168         { "using VK_END", 0, VK_END, 1, -1 },
2169         { "using VK_HOME", -1, VK_HOME, 1, -1 }
2170     };
2171
2172     hwnd = create_listview_control(LVS_REPORT);
2173
2174     for (i = 0; i < items; i++)
2175         insert_item(hwnd, 0);
2176
2177     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
2178     expect(items, item_count);
2179
2180     for (i = 0; i < 4; i++) {
2181         LVITEMA item;
2182
2183         task = task_list[i];
2184
2185         /* deselect all items */
2186         item.state = 0;
2187         item.stateMask = LVIS_SELECTED;
2188         SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2189         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2190
2191         /* set initial position */
2192         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
2193
2194         item.state = LVIS_SELECTED;
2195         item.stateMask = LVIS_SELECTED;
2196         SendMessageA(hwnd, LVM_SETITEMSTATE, task.initPos == -1 ? item_count-1 : task.initPos, (LPARAM)&item);
2197
2198         selected_count = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2199         ok(selected_count == 1, "expected 1, got %d\n", selected_count);
2200
2201         /* Set SHIFT key pressed */
2202         GetKeyboardState(kstate);
2203         kstate[VK_SHIFT]=0x80;
2204         SetKeyboardState(kstate);
2205
2206         for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
2207             r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
2208             expect(0,r);
2209             r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
2210             expect(0,r);
2211         }
2212
2213         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2214
2215         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);
2216
2217         /* Set SHIFT key released */
2218         GetKeyboardState(kstate);
2219         kstate[VK_SHIFT]=0x00;
2220         SetKeyboardState(kstate);
2221     }
2222     DestroyWindow(hwnd);
2223
2224     /* make multiple selection, then switch to LVS_SINGLESEL */
2225     hwnd = create_listview_control(LVS_REPORT);
2226     for (i=0;i<items;i++) {
2227             insert_item(hwnd, 0);
2228     }
2229     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
2230     expect(items,item_count);
2231
2232     /* try with NULL pointer */
2233     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, 0);
2234     expect(FALSE, r);
2235
2236     /* select all, check notifications */
2237     item.state = 0;
2238     item.stateMask = LVIS_SELECTED;
2239     SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2240
2241     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2242
2243     item.stateMask = LVIS_SELECTED;
2244     item.state     = LVIS_SELECTED;
2245     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2246     expect(TRUE, r);
2247
2248     ok_sequence(sequences, PARENT_SEQ_INDEX, change_all_parent_seq,
2249                 "select all notification", FALSE);
2250
2251     /* select all again (all selected already) */
2252     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2253
2254     memset(&g_nmlistview_changing, 0xcc, sizeof(g_nmlistview_changing));
2255
2256     item.stateMask = LVIS_SELECTED;
2257     item.state     = LVIS_SELECTED;
2258     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2259     expect(TRUE, r);
2260
2261     ok(g_nmlistview_changing.uNewState == LVIS_SELECTED, "got 0x%x\n", g_nmlistview_changing.uNewState);
2262     ok(g_nmlistview_changing.uOldState == LVIS_SELECTED, "got 0x%x\n", g_nmlistview_changing.uOldState);
2263     ok(g_nmlistview_changing.uChanged == LVIF_STATE, "got 0x%x\n", g_nmlistview_changing.uChanged);
2264
2265     ok_sequence(sequences, PARENT_SEQ_INDEX, changing_all_parent_seq,
2266                 "select all notification 2", FALSE);
2267
2268     /* deselect all items */
2269     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2270
2271     item.state = 0;
2272     item.stateMask = LVIS_SELECTED;
2273     SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2274
2275     ok_sequence(sequences, PARENT_SEQ_INDEX, change_all_parent_seq,
2276                 "deselect all notification", FALSE);
2277
2278     /* deselect all items again */
2279     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2280     item.state = 0;
2281     item.stateMask = LVIS_SELECTED;
2282     SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2283     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "deselect all notification 2", FALSE);
2284
2285     /* any non-zero state value does the same */
2286     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2287
2288     memset(&g_nmlistview_changing, 0xcc, sizeof(g_nmlistview_changing));
2289
2290     item.stateMask = LVIS_SELECTED;
2291     item.state     = LVIS_CUT;
2292     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2293     expect(TRUE, r);
2294
2295     ok(g_nmlistview_changing.uNewState == 0, "got 0x%x\n", g_nmlistview_changing.uNewState);
2296     ok(g_nmlistview_changing.uOldState == 0, "got 0x%x\n", g_nmlistview_changing.uOldState);
2297     ok(g_nmlistview_changing.uChanged == LVIF_STATE, "got 0x%x\n", g_nmlistview_changing.uChanged);
2298
2299     ok_sequence(sequences, PARENT_SEQ_INDEX, changing_all_parent_seq,
2300                 "set state all notification 3", FALSE);
2301
2302     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2303     for (i = 0; i < 3; i++) {
2304         item.state = LVIS_SELECTED;
2305         item.stateMask = LVIS_SELECTED;
2306         SendMessageA(hwnd, LVM_SETITEMSTATE, i, (LPARAM)&item);
2307     }
2308
2309     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2310     expect(3, r);
2311     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2312     expect(-1, r);
2313
2314     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2315     ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
2316     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
2317     /* check that style is accepted */
2318     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2319     ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
2320
2321     for (i=0;i<3;i++) {
2322         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
2323         ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
2324     }
2325     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2326     expect(3, r);
2327     SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2328     expect(3, r);
2329
2330     /* select one more */
2331     item.state = LVIS_SELECTED;
2332     item.stateMask = LVIS_SELECTED;
2333     SendMessageA(hwnd, LVM_SETITEMSTATE, 3, (LPARAM)&item);
2334
2335     for (i=0;i<3;i++) {
2336         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
2337         ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
2338     }
2339     r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
2340     ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
2341
2342     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2343     expect(1, r);
2344     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2345     expect(-1, r);
2346
2347     /* try to select all on LVS_SINGLESEL */
2348     memset(&item, 0, sizeof(item));
2349     item.stateMask = LVIS_SELECTED;
2350     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2351     expect(TRUE, r);
2352     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2353
2354     item.stateMask = LVIS_SELECTED;
2355     item.state     = LVIS_SELECTED;
2356     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2357     expect(FALSE, r);
2358
2359     r = ListView_GetSelectedCount(hwnd);
2360     expect(0, r);
2361     r = ListView_GetSelectionMark(hwnd);
2362     expect(-1, r);
2363
2364     /* try to deselect all on LVS_SINGLESEL */
2365     item.stateMask = LVIS_SELECTED;
2366     item.state     = LVIS_SELECTED;
2367     r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2368     expect(TRUE, r);
2369
2370     item.stateMask = LVIS_SELECTED;
2371     item.state     = 0;
2372     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2373     expect(TRUE, r);
2374     r = ListView_GetSelectedCount(hwnd);
2375     expect(0, r);
2376
2377     /* 1. selection mark is update when new focused item is set */
2378     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2379     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SINGLESEL);
2380
2381     r = SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2382     expect(-1, r);
2383
2384     item.stateMask = LVIS_FOCUSED;
2385     item.state     = LVIS_FOCUSED;
2386     r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2387     expect(TRUE, r);
2388
2389     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2390     expect(0, r);
2391
2392     /* it's not updated if already set */
2393     item.stateMask = LVIS_FOCUSED;
2394     item.state     = LVIS_FOCUSED;
2395     r = SendMessage(hwnd, LVM_SETITEMSTATE, 1, (LPARAM)&item);
2396     expect(TRUE, r);
2397
2398     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2399     expect(0, r);
2400
2401     r = SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2402     expect(0, r);
2403
2404     item.stateMask = LVIS_FOCUSED;
2405     item.state     = LVIS_FOCUSED;
2406     r = SendMessage(hwnd, LVM_SETITEMSTATE, 1, (LPARAM)&item);
2407     expect(TRUE, r);
2408
2409     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2410     expect(-1, r);
2411
2412     /* need to reset focused item first */
2413     item.stateMask = LVIS_FOCUSED;
2414     item.state     = 0;
2415     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2416     expect(TRUE, r);
2417
2418     item.stateMask = LVIS_FOCUSED;
2419     item.state     = LVIS_FOCUSED;
2420     r = SendMessage(hwnd, LVM_SETITEMSTATE, 2, (LPARAM)&item);
2421     expect(TRUE, r);
2422
2423     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2424     expect(2, r);
2425
2426     item.stateMask = LVIS_FOCUSED;
2427     item.state     = 0;
2428     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2429     expect(TRUE, r);
2430
2431     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2432     expect(2, r);
2433
2434     /* 2. same tests, with LVM_SETITEM */
2435     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2436     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SINGLESEL);
2437
2438     r = SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2439     expect(2, r);
2440
2441     item.stateMask = LVIS_FOCUSED;
2442     item.state     = LVIS_FOCUSED;
2443     item.mask      = LVIF_STATE;
2444     item.iItem = item.iSubItem = 0;
2445     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
2446     expect(TRUE, r);
2447
2448     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2449     expect(0, r);
2450
2451     /* it's not updated if already set */
2452     item.stateMask = LVIS_FOCUSED;
2453     item.state     = LVIS_FOCUSED;
2454     item.mask      = LVIF_STATE;
2455     item.iItem     = 1;
2456     item.iSubItem  = 0;
2457     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
2458     expect(TRUE, r);
2459
2460     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2461     expect(0, r);
2462
2463     r = SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2464     expect(0, r);
2465
2466     item.stateMask = LVIS_FOCUSED;
2467     item.state     = LVIS_FOCUSED;
2468     item.mask      = LVIF_STATE;
2469     item.iItem     = 1;
2470     item.iSubItem  = 0;
2471     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
2472     expect(TRUE, r);
2473
2474     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2475     expect(-1, r);
2476
2477     /* need to reset focused item first */
2478     item.stateMask = LVIS_FOCUSED;
2479     item.state     = 0;
2480     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2481     expect(TRUE, r);
2482
2483     item.stateMask = LVIS_FOCUSED;
2484     item.state     = LVIS_FOCUSED;
2485     item.mask      = LVIF_STATE;
2486     item.iItem     = 2;
2487     item.iSubItem  = 0;
2488     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
2489     expect(TRUE, r);
2490
2491     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2492     expect(2, r);
2493
2494     item.stateMask = LVIS_FOCUSED;
2495     item.state     = 0;
2496     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2497     expect(TRUE, r);
2498
2499     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2500     expect(2, r);
2501
2502     DestroyWindow(hwnd);
2503 }
2504
2505 static void test_subitem_rect(void)
2506 {
2507     HWND hwnd;
2508     DWORD r;
2509     LVCOLUMN col;
2510     RECT rect, rect2;
2511     INT arr[3];
2512
2513     /* test LVM_GETSUBITEMRECT for header */
2514     hwnd = create_listview_control(LVS_REPORT);
2515     ok(hwnd != NULL, "failed to create a listview window\n");
2516     /* add some columns */
2517     memset(&col, 0, sizeof(LVCOLUMN));
2518     col.mask = LVCF_WIDTH;
2519     col.cx = 100;
2520     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
2521     expect(0, r);
2522     col.cx = 150;
2523     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
2524     expect(1, r);
2525     col.cx = 200;
2526     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
2527     expect(2, r);
2528     /* item = -1 means header, subitem index is 1 based */
2529     rect.left = LVIR_BOUNDS;
2530     rect.top  = 0;
2531     rect.right = rect.bottom = 0;
2532     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2533     expect(0, r);
2534
2535     rect.left = LVIR_BOUNDS;
2536     rect.top  = 1;
2537     rect.right = rect.bottom = 0;
2538     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2539     expect(1, r);
2540
2541     expect(100, rect.left);
2542     expect(250, rect.right);
2543     expect(3, rect.top);
2544
2545     rect.left = LVIR_BOUNDS;
2546     rect.top  = 2;
2547     rect.right = rect.bottom = 0;
2548     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2549     expect(1, r);
2550
2551     expect(250, rect.left);
2552     expect(450, rect.right);
2553     expect(3, rect.top);
2554
2555     /* item LVS_REPORT padding isn't applied to subitems */
2556     insert_item(hwnd, 0);
2557
2558     rect.left = LVIR_BOUNDS;
2559     rect.top  = 1;
2560     rect.right = rect.bottom = 0;
2561     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2562     expect(1, r);
2563     expect(100, rect.left);
2564     expect(250, rect.right);
2565
2566     rect.left = LVIR_ICON;
2567     rect.top  = 1;
2568     rect.right = rect.bottom = 0;
2569     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2570     expect(1, r);
2571     /* no icon attached - zero width rectangle, with no left padding */
2572     expect(100, rect.left);
2573     expect(100, rect.right);
2574
2575     rect.left = LVIR_LABEL;
2576     rect.top  = 1;
2577     rect.right = rect.bottom = 0;
2578     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2579     expect(1, r);
2580     /* same as full LVIR_BOUNDS */
2581     expect(100, rect.left);
2582     expect(250, rect.right);
2583
2584     SendMessage(hwnd, LVM_SCROLL, 10, 0);
2585
2586     rect.left = LVIR_BOUNDS;
2587     rect.top  = 1;
2588     rect.right = rect.bottom = 0;
2589     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2590     expect(1, r);
2591     expect(90, rect.left);
2592     expect(240, rect.right);
2593
2594     SendMessage(hwnd, LVM_SCROLL, -10, 0);
2595
2596     /* test header interaction */
2597     subclass_header(hwnd);
2598     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2599
2600     rect.left = LVIR_BOUNDS;
2601     rect.top  = 1;
2602     rect.right = rect.bottom = 0;
2603     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2604     expect(1, r);
2605
2606     rect.left = LVIR_BOUNDS;
2607     rect.top  = 1;
2608     rect.right = rect.bottom = 0;
2609     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2610     expect(1, r);
2611
2612     rect.left = LVIR_BOUNDS;
2613     rect.top  = 1;
2614     rect.right = rect.bottom = 0;
2615     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -10, (LPARAM)&rect);
2616     expect(1, r);
2617
2618     rect.left = LVIR_BOUNDS;
2619     rect.top  = 1;
2620     rect.right = rect.bottom = 0;
2621     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 20, (LPARAM)&rect);
2622     expect(1, r);
2623
2624     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getsubitemrect_seq, "LVM_GETSUBITEMRECT negative index", FALSE);
2625
2626     DestroyWindow(hwnd);
2627
2628     /* test subitem rects after re-arranging columns */
2629     hwnd = create_listview_control(LVS_REPORT);
2630     ok(hwnd != NULL, "failed to create a listview window\n");
2631     memset(&col, 0, sizeof(LVCOLUMN));
2632     col.mask = LVCF_WIDTH;
2633
2634     col.cx = 100;
2635     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
2636     expect(0, r);
2637
2638     col.cx = 200;
2639     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
2640     expect(1, r);
2641
2642     col.cx = 300;
2643     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
2644     expect(2, r);
2645
2646     insert_item(hwnd, 0);
2647     insert_item(hwnd, 1);
2648
2649     /* wrong item is refused for main item */
2650     rect.left = LVIR_BOUNDS;
2651     rect.top  = 0;
2652     rect.right = rect.bottom = -1;
2653     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 2, (LPARAM)&rect);
2654     expect(FALSE, r);
2655
2656     /* for subitems rectangle is calculated even if there's no item added */
2657     rect.left = LVIR_BOUNDS;
2658     rect.top  = 1;
2659     rect.right = rect.bottom = -1;
2660     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 1, (LPARAM)&rect);
2661     expect(TRUE, r);
2662
2663     rect2.left = LVIR_BOUNDS;
2664     rect2.top  = 1;
2665     rect2.right = rect2.bottom = -1;
2666     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 2, (LPARAM)&rect2);
2667     expect(TRUE, r);
2668     expect(rect.right, rect2.right);
2669     expect(rect.left, rect2.left);
2670     expect(rect.bottom, rect2.top);
2671     ok(rect2.bottom > rect2.top, "expected not zero height\n");
2672
2673     arr[0] = 1; arr[1] = 0; arr[2] = 2;
2674     r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 3, (LPARAM)arr);
2675     expect(TRUE, r);
2676
2677     rect.left = LVIR_BOUNDS;
2678     rect.top  = 0;
2679     rect.right = rect.bottom = -1;
2680     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2681     expect(TRUE, r);
2682     expect(0, rect.left);
2683     expect(600, rect.right);
2684
2685     rect.left = LVIR_BOUNDS;
2686     rect.top  = 1;
2687     rect.right = rect.bottom = -1;
2688     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2689     expect(TRUE, r);
2690     expect(0, rect.left);
2691     expect(200, rect.right);
2692
2693     rect2.left = LVIR_BOUNDS;
2694     rect2.top  = 1;
2695     rect2.right = rect2.bottom = -1;
2696     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 1, (LPARAM)&rect2);
2697     expect(TRUE, r);
2698     expect(0, rect2.left);
2699     expect(200, rect2.right);
2700     /* items are of the same height */
2701     ok(rect2.top > 0, "expected positive item height\n");
2702     expect(rect.bottom, rect2.top);
2703     expect(rect.bottom * 2 - rect.top, rect2.bottom);
2704
2705     rect.left = LVIR_BOUNDS;
2706     rect.top  = 2;
2707     rect.right = rect.bottom = -1;
2708     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2709     expect(TRUE, r);
2710     expect(300, rect.left);
2711     expect(600, rect.right);
2712
2713     DestroyWindow(hwnd);
2714
2715     /* try it for non LVS_REPORT style */
2716     hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
2717                          GetModuleHandle(NULL), 0);
2718     rect.left = LVIR_BOUNDS;
2719     rect.top  = 1;
2720     rect.right = rect.bottom = -10;
2721     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2722     expect(0, r);
2723     /* rect is unchanged */
2724     expect(0, rect.left);
2725     expect(-10, rect.right);
2726     expect(1, rect.top);
2727     expect(-10, rect.bottom);
2728     DestroyWindow(hwnd);
2729 }
2730
2731 /* comparison callback for test_sorting */
2732 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
2733 {
2734     if (first == second) return 0;
2735     return (first > second ? 1 : -1);
2736 }
2737
2738 static void test_sorting(void)
2739 {
2740     HWND hwnd;
2741     LVITEMA item = {0};
2742     INT r;
2743     LONG_PTR style;
2744     static CHAR names[][5] = {"A", "B", "C", "D", "0"};
2745     CHAR buff[10];
2746
2747     hwnd = create_listview_control(LVS_REPORT);
2748     ok(hwnd != NULL, "failed to create a listview window\n");
2749
2750     /* insert some items */
2751     item.mask = LVIF_PARAM | LVIF_STATE;
2752     item.state = LVIS_SELECTED;
2753     item.iItem = 0;
2754     item.iSubItem = 0;
2755     item.lParam = 3;
2756     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2757     expect(0, r);
2758
2759     item.mask = LVIF_PARAM;
2760     item.iItem = 1;
2761     item.iSubItem = 0;
2762     item.lParam = 2;
2763     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2764     expect(1, r);
2765
2766     item.mask = LVIF_STATE | LVIF_PARAM;
2767     item.state = LVIS_SELECTED;
2768     item.iItem = 2;
2769     item.iSubItem = 0;
2770     item.lParam = 4;
2771     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2772     expect(2, r);
2773
2774     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2775     expect(-1, r);
2776
2777     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2778     expect(2, r);
2779
2780     r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
2781     expect(TRUE, r);
2782
2783     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2784     expect(2, r);
2785     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2786     expect(-1, r);
2787     r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
2788     expect(0, r);
2789     r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
2790     expect(LVIS_SELECTED, r);
2791     r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
2792     expect(LVIS_SELECTED, r);
2793
2794     DestroyWindow(hwnd);
2795
2796     /* switch to LVS_SORTASCENDING when some items added */
2797     hwnd = create_listview_control(LVS_REPORT);
2798     ok(hwnd != NULL, "failed to create a listview window\n");
2799
2800     item.mask = LVIF_TEXT;
2801     item.iItem = 0;
2802     item.iSubItem = 0;
2803     item.pszText = names[1];
2804     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2805     expect(0, r);
2806
2807     item.mask = LVIF_TEXT;
2808     item.iItem = 1;
2809     item.iSubItem = 0;
2810     item.pszText = names[2];
2811     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2812     expect(1, r);
2813
2814     item.mask = LVIF_TEXT;
2815     item.iItem = 2;
2816     item.iSubItem = 0;
2817     item.pszText = names[0];
2818     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2819     expect(2, r);
2820
2821     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2822     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2823     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2824     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2825
2826     /* no sorting performed when switched to LVS_SORTASCENDING */
2827     item.mask = LVIF_TEXT;
2828     item.iItem = 0;
2829     item.pszText = buff;
2830     item.cchTextMax = sizeof(buff);
2831     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2832     expect(TRUE, r);
2833     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2834
2835     item.iItem = 1;
2836     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2837     expect(TRUE, r);
2838     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2839
2840     item.iItem = 2;
2841     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2842     expect(TRUE, r);
2843     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2844
2845     /* adding new item doesn't resort list */
2846     item.mask = LVIF_TEXT;
2847     item.iItem = 3;
2848     item.iSubItem = 0;
2849     item.pszText = names[3];
2850     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2851     expect(3, r);
2852
2853     item.mask = LVIF_TEXT;
2854     item.iItem = 0;
2855     item.pszText = buff;
2856     item.cchTextMax = sizeof(buff);
2857     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2858     expect(TRUE, r);
2859     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2860
2861     item.iItem = 1;
2862     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2863     expect(TRUE, r);
2864     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2865
2866     item.iItem = 2;
2867     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2868     expect(TRUE, r);
2869     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2870
2871     item.iItem = 3;
2872     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2873     expect(TRUE, r);
2874     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2875
2876     /* corner case - item should be placed at first position */
2877     item.mask = LVIF_TEXT;
2878     item.iItem = 4;
2879     item.iSubItem = 0;
2880     item.pszText = names[4];
2881     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2882     expect(0, r);
2883
2884     item.iItem = 0;
2885     item.pszText = buff;
2886     item.cchTextMax = sizeof(buff);
2887     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2888     expect(TRUE, r);
2889     ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
2890
2891     item.iItem = 1;
2892     item.pszText = buff;
2893     item.cchTextMax = sizeof(buff);
2894     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2895     expect(TRUE, r);
2896     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2897
2898     item.iItem = 2;
2899     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2900     expect(TRUE, r);
2901     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2902
2903     item.iItem = 3;
2904     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2905     expect(TRUE, r);
2906     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2907
2908     item.iItem = 4;
2909     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2910     expect(TRUE, r);
2911     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2912
2913     DestroyWindow(hwnd);
2914 }
2915
2916 static void test_ownerdata(void)
2917 {
2918     static char test_str[] = "test";
2919
2920     HWND hwnd;
2921     LONG_PTR style, ret;
2922     DWORD res;
2923     LVITEMA item;
2924
2925     /* it isn't possible to set LVS_OWNERDATA after creation */
2926     if (g_is_below_5)
2927     {
2928         win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2929     }
2930     else
2931     {
2932         hwnd = create_listview_control(LVS_REPORT);
2933         ok(hwnd != NULL, "failed to create a listview window\n");
2934         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2935         ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
2936
2937         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2938
2939         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2940         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2941         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2942                 "try to switch to LVS_OWNERDATA seq", FALSE);
2943
2944         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2945         ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
2946         DestroyWindow(hwnd);
2947     }
2948
2949     /* try to set LVS_OWNERDATA after creation just having it */
2950     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
2951     ok(hwnd != NULL, "failed to create a listview window\n");
2952     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2953     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2954
2955     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2956
2957     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2958     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2959     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2960                 "try to switch to LVS_OWNERDATA seq", FALSE);
2961     DestroyWindow(hwnd);
2962
2963     /* try to remove LVS_OWNERDATA after creation just having it */
2964     if (g_is_below_5)
2965     {
2966         win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2967     }
2968     else
2969     {
2970         hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
2971         ok(hwnd != NULL, "failed to create a listview window\n");
2972         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2973         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2974
2975         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2976
2977         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
2978         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2979         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2980                 "try to switch to LVS_OWNERDATA seq", FALSE);
2981         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2982         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2983         DestroyWindow(hwnd);
2984     }
2985
2986     /* try select an item */
2987     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
2988     ok(hwnd != NULL, "failed to create a listview window\n");
2989     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2990     expect(1, res);
2991     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2992     expect(0, res);
2993     memset(&item, 0, sizeof(item));
2994     item.stateMask = LVIS_SELECTED;
2995     item.state     = LVIS_SELECTED;
2996     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2997     expect(TRUE, res);
2998     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2999     expect(1, res);
3000     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
3001     expect(1, res);
3002     DestroyWindow(hwnd);
3003
3004     /* LVM_SETITEM and LVM_SETITEMTEXT is unsupported on LVS_OWNERDATA */
3005     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3006     ok(hwnd != NULL, "failed to create a listview window\n");
3007     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
3008     expect(1, res);
3009     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
3010     expect(1, res);
3011     memset(&item, 0, sizeof(item));
3012     item.mask = LVIF_STATE;
3013     item.iItem = 0;
3014     item.stateMask = LVIS_SELECTED;
3015     item.state     = LVIS_SELECTED;
3016     res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3017     expect(FALSE, res);
3018     memset(&item, 0, sizeof(item));
3019     item.pszText = test_str;
3020     res = SendMessageA(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&item);
3021     expect(FALSE, res);
3022     DestroyWindow(hwnd);
3023
3024     /* check notifications after focused/selected changed */
3025     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3026     ok(hwnd != NULL, "failed to create a listview window\n");
3027     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 20, 0);
3028     expect(1, res);
3029
3030     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3031
3032     memset(&item, 0, sizeof(item));
3033     item.stateMask = LVIS_SELECTED;
3034     item.state     = LVIS_SELECTED;
3035     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3036     expect(TRUE, res);
3037
3038     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
3039                 "ownerdata select notification", TRUE);
3040
3041     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3042
3043     memset(&item, 0, sizeof(item));
3044     item.stateMask = LVIS_FOCUSED;
3045     item.state     = LVIS_FOCUSED;
3046     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3047     expect(TRUE, res);
3048
3049     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
3050                 "ownerdata focus notification", TRUE);
3051
3052     /* select all, check notifications */
3053     item.stateMask = LVIS_SELECTED;
3054     item.state     = 0;
3055     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3056     expect(TRUE, res);
3057
3058     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3059
3060     item.stateMask = LVIS_SELECTED;
3061     item.state     = LVIS_SELECTED;
3062
3063     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3064     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3065     expect(TRUE, res);
3066     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3067     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3068     ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState);
3069     ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
3070     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3071     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3072     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3073
3074     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
3075                 "ownerdata select all notification", FALSE);
3076
3077     /* select all again, note that all items are selected already */
3078     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3079     item.stateMask = LVIS_SELECTED;
3080     item.state     = LVIS_SELECTED;
3081
3082     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3083     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3084     expect(TRUE, res);
3085     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3086     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3087     ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState);
3088     ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
3089     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3090     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3091     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3092
3093     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
3094                 "ownerdata select all notification", FALSE);
3095
3096     /* deselect all */
3097     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3098     item.stateMask = LVIS_SELECTED;
3099     item.state     = 0;
3100
3101     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3102     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3103     expect(TRUE, res);
3104     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3105     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3106     ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState);
3107     ok(g_nmlistview.uOldState == LVIS_SELECTED, "got old state 0x%08x\n", g_nmlistview.uOldState);
3108     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3109     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3110     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3111
3112     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
3113                 "ownerdata deselect all notification", TRUE);
3114
3115     /* nothing selected, deselect all again */
3116     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3117     item.stateMask = LVIS_SELECTED;
3118     item.state     = 0;
3119
3120     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3121     expect(TRUE, res);
3122
3123     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "ownerdata deselect all notification", FALSE);
3124
3125     /* select one, then deselect all */
3126     item.stateMask = LVIS_SELECTED;
3127     item.state     = LVIS_SELECTED;
3128     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3129     expect(TRUE, res);
3130     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3131     item.stateMask = LVIS_SELECTED;
3132     item.state     = 0;
3133
3134     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3135     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3136     expect(TRUE, res);
3137     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3138     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3139     ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState);
3140     ok(g_nmlistview.uOldState == LVIS_SELECTED, "got old state 0x%08x\n", g_nmlistview.uOldState);
3141     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3142     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3143     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3144
3145     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
3146                 "ownerdata select all notification", TRUE);
3147
3148     /* remove focused, try to focus all */
3149     item.stateMask = LVIS_FOCUSED;
3150     item.state     = LVIS_FOCUSED;
3151     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3152     expect(TRUE, res);
3153     item.stateMask = LVIS_FOCUSED;
3154     item.state     = 0;
3155     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3156     expect(TRUE, res);
3157     item.stateMask = LVIS_FOCUSED;
3158     res = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
3159     expect(0, res);
3160
3161     /* setting all to focused returns failure value */
3162     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3163     item.stateMask = LVIS_FOCUSED;
3164     item.state     = LVIS_FOCUSED;
3165
3166     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3167     expect(FALSE, res);
3168
3169     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3170                 "ownerdata focus all notification", FALSE);
3171
3172     /* focus single item, remove all */
3173     item.stateMask = LVIS_FOCUSED;
3174     item.state     = LVIS_FOCUSED;
3175     res = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3176     expect(TRUE, res);
3177     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3178     item.stateMask = LVIS_FOCUSED;
3179     item.state     = 0;
3180
3181     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3182     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3183     expect(TRUE, res);
3184     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3185     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3186     ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState);
3187     ok(g_nmlistview.uOldState == LVIS_FOCUSED, "got old state 0x%08x\n", g_nmlistview.uOldState);
3188     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3189     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3190     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3191
3192     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_defocus_all_parent_seq,
3193                 "ownerdata remove focus all notification", TRUE);
3194
3195     /* set all cut */
3196     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3197     item.stateMask = LVIS_CUT;
3198     item.state     = LVIS_CUT;
3199
3200     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3201     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3202     expect(TRUE, res);
3203     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3204     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3205     ok(g_nmlistview.uNewState == LVIS_CUT, "got new state 0x%08x\n", g_nmlistview.uNewState);
3206     ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
3207     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3208     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3209     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3210
3211     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
3212                 "ownerdata cut all notification", FALSE);
3213
3214     /* all marked cut, try again */
3215     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3216     item.stateMask = LVIS_CUT;
3217     item.state     = LVIS_CUT;
3218
3219     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3220     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3221     expect(TRUE, res);
3222     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3223     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3224     ok(g_nmlistview.uNewState == LVIS_CUT, "got new state 0x%08x\n", g_nmlistview.uNewState);
3225     ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
3226     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3227     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3228     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3229
3230     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
3231                 "ownerdata cut all notification #2", FALSE);
3232
3233     DestroyWindow(hwnd);
3234
3235     /* check notifications on LVM_GETITEM */
3236     /* zero callback mask */
3237     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3238     ok(hwnd != NULL, "failed to create a listview window\n");
3239     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
3240     expect(1, res);
3241
3242     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3243
3244     memset(&item, 0, sizeof(item));
3245     item.stateMask = LVIS_SELECTED;
3246     item.mask      = LVIF_STATE;
3247     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3248     expect(TRUE, res);
3249
3250     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3251                 "ownerdata getitem selected state 1", FALSE);
3252
3253     /* non zero callback mask but not we asking for */
3254     res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0);
3255     expect(TRUE, res);
3256
3257     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3258
3259     memset(&item, 0, sizeof(item));
3260     item.stateMask = LVIS_SELECTED;
3261     item.mask      = LVIF_STATE;
3262     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3263     expect(TRUE, res);
3264
3265     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3266                 "ownerdata getitem selected state 2", FALSE);
3267
3268     /* LVIS_OVERLAYMASK callback mask, asking for index */
3269     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3270
3271     memset(&item, 0, sizeof(item));
3272     item.stateMask = LVIS_OVERLAYMASK;
3273     item.mask      = LVIF_STATE;
3274     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3275     expect(TRUE, res);
3276
3277     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
3278                 "ownerdata getitem selected state 2", FALSE);
3279
3280     DestroyWindow(hwnd);
3281
3282     /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
3283     hwnd = create_listview_control(LVS_OWNERDATA | LVS_SORTASCENDING | LVS_REPORT);
3284     ok(hwnd != NULL, "failed to create a listview window\n");
3285     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3286     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
3287     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
3288     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SORTASCENDING);
3289     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3290     ok(!(style & LVS_SORTASCENDING), "Expected LVS_SORTASCENDING not set\n");
3291     DestroyWindow(hwnd);
3292     /* apparently it's allowed to switch these style on after creation */
3293     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3294     ok(hwnd != NULL, "failed to create a listview window\n");
3295     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3296     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
3297     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
3298     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3299     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
3300     DestroyWindow(hwnd);
3301
3302     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3303     ok(hwnd != NULL, "failed to create a listview window\n");
3304     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3305     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
3306     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTDESCENDING);
3307     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3308     ok(style & LVS_SORTDESCENDING, "Expected LVS_SORTDESCENDING to be set\n");
3309     DestroyWindow(hwnd);
3310 }
3311
3312 static void test_norecompute(void)
3313 {
3314     static CHAR testA[] = "test";
3315     CHAR buff[10];
3316     LVITEMA item;
3317     HWND hwnd;
3318     DWORD res;
3319
3320     /* self containing control */
3321     hwnd = create_listview_control(LVS_REPORT);
3322     ok(hwnd != NULL, "failed to create a listview window\n");
3323     memset(&item, 0, sizeof(item));
3324     item.mask = LVIF_TEXT | LVIF_STATE;
3325     item.iItem = 0;
3326     item.stateMask = LVIS_SELECTED;
3327     item.state     = LVIS_SELECTED;
3328     item.pszText   = testA;
3329     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
3330     expect(0, res);
3331     /* retrieve with LVIF_NORECOMPUTE */
3332     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
3333     item.iItem = 0;
3334     item.pszText    = buff;
3335     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
3336     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
3337     expect(TRUE, res);
3338     ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
3339
3340     item.mask = LVIF_TEXT;
3341     item.iItem = 1;
3342     item.pszText = LPSTR_TEXTCALLBACK;
3343     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
3344     expect(1, res);
3345
3346     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
3347     item.iItem = 1;
3348     item.pszText    = buff;
3349     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
3350
3351     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3352     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
3353     expect(TRUE, res);
3354     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
3355        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
3356     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
3357
3358     DestroyWindow(hwnd);
3359
3360     /* LVS_OWNERDATA */
3361     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3362     ok(hwnd != NULL, "failed to create a listview window\n");
3363
3364     item.mask = LVIF_STATE;
3365     item.stateMask = LVIS_SELECTED;
3366     item.state     = LVIS_SELECTED;
3367     item.iItem = 0;
3368     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
3369     expect(0, res);
3370
3371     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
3372     item.iItem = 0;
3373     item.pszText    = buff;
3374     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
3375     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3376     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
3377     expect(TRUE, res);
3378     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
3379        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
3380     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
3381
3382     DestroyWindow(hwnd);
3383 }
3384
3385 static void test_nosortheader(void)
3386 {
3387     HWND hwnd, header;
3388     LONG_PTR style;
3389
3390     hwnd = create_listview_control(LVS_REPORT);
3391     ok(hwnd != NULL, "failed to create a listview window\n");
3392
3393     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
3394     ok(IsWindow(header), "header expected\n");
3395
3396     style = GetWindowLongPtr(header, GWL_STYLE);
3397     ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
3398
3399     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3400     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
3401     /* HDS_BUTTONS retained */
3402     style = GetWindowLongPtr(header, GWL_STYLE);
3403     ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
3404
3405     DestroyWindow(hwnd);
3406
3407     /* create with LVS_NOSORTHEADER */
3408     hwnd = create_listview_control(LVS_NOSORTHEADER | LVS_REPORT);
3409     ok(hwnd != NULL, "failed to create a listview window\n");
3410
3411     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
3412     ok(IsWindow(header), "header expected\n");
3413
3414     style = GetWindowLongPtr(header, GWL_STYLE);
3415     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
3416
3417     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3418     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
3419     /* not changed here */
3420     style = GetWindowLongPtr(header, GWL_STYLE);
3421     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
3422
3423     DestroyWindow(hwnd);
3424 }
3425
3426 static void test_setredraw(void)
3427 {
3428     HWND hwnd;
3429     DWORD_PTR style;
3430     DWORD ret;
3431     HDC hdc;
3432     RECT rect;
3433
3434     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3435     ok(hwnd != NULL, "failed to create a listview window\n");
3436
3437     /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
3438        ListView seems to handle it internally without DefWinProc */
3439
3440     /* default value first */
3441     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
3442     expect(0, ret);
3443     /* disable */
3444     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3445     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
3446     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
3447     expect(0, ret);
3448     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3449     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
3450     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
3451     expect(0, ret);
3452
3453     /* check update rect after redrawing */
3454     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
3455     expect(0, ret);
3456     InvalidateRect(hwnd, NULL, FALSE);
3457     RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW);
3458     rect.right = rect.bottom = 1;
3459     GetUpdateRect(hwnd, &rect, FALSE);
3460     expect(0, rect.right);
3461     expect(0, rect.bottom);
3462
3463     /* WM_ERASEBKGND */
3464     hdc = GetWindowDC(hwndparent);
3465     ret = SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
3466     expect(TRUE, ret);
3467     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
3468     expect(0, ret);
3469     ret = SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
3470     expect(TRUE, ret);
3471     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
3472     expect(0, ret);
3473     ReleaseDC(hwndparent, hdc);
3474
3475     /* check notification messages to show that repainting is disabled */
3476     ret = SendMessage(hwnd, LVM_SETITEMCOUNT, 1, 0);
3477     expect(TRUE, ret);
3478     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
3479     expect(0, ret);
3480     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3481
3482     InvalidateRect(hwnd, NULL, TRUE);
3483     UpdateWindow(hwnd);
3484     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3485                 "redraw after WM_SETREDRAW (FALSE)", FALSE);
3486
3487     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE);
3488     expect(TRUE, ret);
3489     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3490     InvalidateRect(hwnd, NULL, TRUE);
3491     UpdateWindow(hwnd);
3492     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3493                 "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE);
3494
3495     /* message isn't forwarded to header */
3496     subclass_header(hwnd);
3497     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3498     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
3499     expect(0, ret);
3500     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, setredraw_seq,
3501                 "WM_SETREDRAW: not forwarded to header", FALSE);
3502
3503     DestroyWindow(hwnd);
3504 }
3505
3506 static void test_hittest(void)
3507 {
3508     HWND hwnd;
3509     DWORD r;
3510     RECT bounds;
3511     LVITEMA item;
3512     static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST";
3513     POINT pos;
3514     INT x, y, i;
3515     WORD vert;
3516     HIMAGELIST himl, himl2;
3517     HBITMAP hbmp;
3518
3519     hwnd = create_listview_control(LVS_REPORT);
3520     ok(hwnd != NULL, "failed to create a listview window\n");
3521
3522     /* LVS_REPORT with a single subitem (2 columns) */
3523     insert_column(hwnd, 0);
3524     insert_column(hwnd, 1);
3525     insert_item(hwnd, 0);
3526
3527     item.iSubItem = 0;
3528     /* the only purpose of that line is to be as long as a half item rect */
3529     item.pszText  = text;
3530     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&item);
3531     expect(TRUE, r);
3532
3533     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3534     expect(TRUE, r);
3535     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
3536     expect(TRUE, r);
3537
3538     memset(&bounds, 0, sizeof(bounds));
3539     bounds.left = LVIR_BOUNDS;
3540     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds);
3541     expect(1, r);
3542     ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n");
3543     ok(bounds.right - bounds.left > 0, "Expected non zero item width\n");
3544     r = SendMessage(hwnd, LVM_GETITEMSPACING, TRUE, 0);
3545     vert = HIWORD(r);
3546     ok(bounds.bottom - bounds.top == vert,
3547         "Vertical spacing inconsistent (%d != %d)\n", bounds.bottom - bounds.top, vert);
3548     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos);
3549     expect(TRUE, r);
3550
3551     /* LVS_EX_FULLROWSELECT not set, no icons attached */
3552
3553     /* outside columns by x position - valid is [0, 199] */
3554     x = -1;
3555     y = pos.y + (bounds.bottom - bounds.top) / 2;
3556     test_lvm_hittest(hwnd, x, y, -1, LVHT_TOLEFT, 0, FALSE, FALSE);
3557     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3558
3559     x = pos.x + 50; /* column half width */
3560     y = pos.y + (bounds.bottom - bounds.top) / 2;
3561     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, 0, FALSE, FALSE);
3562     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3563     x = pos.x + 150; /* outside column */
3564     y = pos.y + (bounds.bottom - bounds.top) / 2;
3565     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
3566     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3567     y = (bounds.bottom - bounds.top) / 2;
3568     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
3569     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3570     /* outside possible client rectangle (to right) */
3571     x = pos.x + 500;
3572     y = pos.y + (bounds.bottom - bounds.top) / 2;
3573     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
3574     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3575     y = (bounds.bottom - bounds.top) / 2;
3576     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
3577     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3578     /* subitem returned with -1 item too */
3579     x = pos.x + 150;
3580     y = bounds.top - vert;
3581     test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3582     test_lvm_subitemhittest(hwnd, x, y - vert + 1, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3583     /* return values appear to underflow with negative indices */
3584     i = -2;
3585     y = y - vert;
3586     while (i > -10) {
3587         test_lvm_subitemhittest(hwnd, x, y, i, 1, LVHT_ONITEMLABEL, TRUE, FALSE, TRUE);
3588         test_lvm_subitemhittest(hwnd, x, y - vert + 1, i, 1, LVHT_ONITEMLABEL, TRUE, FALSE, TRUE);
3589         y = y - vert;
3590         i--;
3591     }
3592     /* parent client area is 100x100 by default */
3593     MoveWindow(hwnd, 0, 0, 300, 100, FALSE);
3594     x = pos.x + 150; /* outside column */
3595     y = pos.y + (bounds.bottom - bounds.top) / 2;
3596     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, FALSE);
3597     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3598     y = (bounds.bottom - bounds.top) / 2;
3599     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, TRUE);
3600     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3601     /* the same with LVS_EX_FULLROWSELECT */
3602     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
3603     x = pos.x + 150; /* outside column */
3604     y = pos.y + (bounds.bottom - bounds.top) / 2;
3605     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, LVHT_ONITEMLABEL, FALSE, FALSE);
3606     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3607     y = (bounds.bottom - bounds.top) / 2;
3608     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3609     MoveWindow(hwnd, 0, 0, 100, 100, FALSE);
3610     x = pos.x + 150; /* outside column */
3611     y = pos.y + (bounds.bottom - bounds.top) / 2;
3612     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
3613     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3614     y = (bounds.bottom - bounds.top) / 2;
3615     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
3616     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3617     /* outside possible client rectangle (to right) */
3618     x = pos.x + 500;
3619     y = pos.y + (bounds.bottom - bounds.top) / 2;
3620     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
3621     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3622     y = (bounds.bottom - bounds.top) / 2;
3623     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
3624     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3625     /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
3626     himl = ImageList_Create(16, 16, 0, 4, 4);
3627     ok(himl != NULL, "failed to create imagelist\n");
3628     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
3629     ok(hbmp != NULL, "failed to create bitmap\n");
3630     r = ImageList_Add(himl, hbmp, 0);
3631     ok(r == 0, "should be zero\n");
3632     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
3633     ok(hbmp != NULL, "failed to create bitmap\n");
3634     r = ImageList_Add(himl, hbmp, 0);
3635     ok(r == 1, "should be one\n");
3636
3637     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
3638     expect(0, r);
3639
3640     item.mask = LVIF_IMAGE;
3641     item.iImage = 0;
3642     item.iItem = 0;
3643     item.iSubItem = 0;
3644     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3645     expect(TRUE, r);
3646     /* on state icon */
3647     x = pos.x + 8;
3648     y = pos.y + (bounds.bottom - bounds.top) / 2;
3649     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE);
3650     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
3651     y = (bounds.bottom - bounds.top) / 2;
3652     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
3653
3654     /* state icons indices are 1 based, check with valid index */
3655     item.mask = LVIF_STATE;
3656     item.state = INDEXTOSTATEIMAGEMASK(1);
3657     item.stateMask = LVIS_STATEIMAGEMASK;
3658     item.iItem = 0;
3659     item.iSubItem = 0;
3660     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3661     expect(TRUE, r);
3662     /* on state icon */
3663     x = pos.x + 8;
3664     y = pos.y + (bounds.bottom - bounds.top) / 2;
3665     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE);
3666     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
3667     y = (bounds.bottom - bounds.top) / 2;
3668     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
3669
3670     himl2 = (HIMAGELIST)SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, 0);
3671     ok(himl2 == himl, "should return handle\n");
3672
3673     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
3674     expect(0, r);
3675     /* on item icon */
3676     x = pos.x + 8;
3677     y = pos.y + (bounds.bottom - bounds.top) / 2;
3678     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, 0, FALSE, FALSE);
3679     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE);
3680     y = (bounds.bottom - bounds.top) / 2;
3681     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE);
3682
3683     DestroyWindow(hwnd);
3684 }
3685
3686 static void test_getviewrect(void)
3687 {
3688     HWND hwnd;
3689     DWORD r;
3690     RECT rect;
3691     LVITEMA item;
3692
3693     hwnd = create_listview_control(LVS_REPORT);
3694     ok(hwnd != NULL, "failed to create a listview window\n");
3695
3696     /* empty */
3697     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3698     expect(TRUE, r);
3699
3700     insert_column(hwnd, 0);
3701     insert_column(hwnd, 1);
3702
3703     memset(&item, 0, sizeof(item));
3704     item.iItem = 0;
3705     item.iSubItem = 0;
3706     SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3707
3708     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3709     expect(TRUE, r);
3710     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0));
3711     expect(TRUE, r);
3712
3713     rect.left = rect.right = rect.top = rect.bottom = -1;
3714     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3715     expect(TRUE, r);
3716     /* left is set to (2e31-1) - XP SP2 */
3717     expect(0, rect.right);
3718     expect(0, rect.top);
3719     expect(0, rect.bottom);
3720
3721     /* switch to LVS_ICON */
3722     SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~LVS_REPORT);
3723
3724     rect.left = rect.right = rect.top = rect.bottom = -1;
3725     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3726     expect(TRUE, r);
3727     expect(0, rect.left);
3728     expect(0, rect.top);
3729     /* precise value differs for 2k, XP and Vista */
3730     ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom);
3731     ok(rect.right  > 0, "Expected positive right value, got %d\n", rect.right);
3732
3733     DestroyWindow(hwnd);
3734 }
3735
3736 static void test_getitemposition(void)
3737 {
3738     HWND hwnd, header;
3739     DWORD r;
3740     POINT pt;
3741     RECT rect;
3742
3743     hwnd = create_listview_control(LVS_REPORT);
3744     ok(hwnd != NULL, "failed to create a listview window\n");
3745     header = subclass_header(hwnd);
3746
3747     /* LVS_REPORT, single item, no columns added */
3748     insert_item(hwnd, 0);
3749
3750     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3751
3752     pt.x = pt.y = -1;
3753     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3754     expect(TRUE, r);
3755     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE);
3756
3757     /* LVS_REPORT, single item, single column */
3758     insert_column(hwnd, 0);
3759
3760     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3761
3762     pt.x = pt.y = -1;
3763     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3764     expect(TRUE, r);
3765     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE);
3766
3767     memset(&rect, 0, sizeof(rect));
3768     SendMessage(header, HDM_GETITEMRECT, 0, (LPARAM)&rect);
3769     /* some padding? */
3770     expect(2, pt.x);
3771     /* offset by header height */
3772     expect(rect.bottom - rect.top, pt.y);
3773
3774     DestroyWindow(hwnd);
3775 }
3776
3777 static void test_columnscreation(void)
3778 {
3779     HWND hwnd, header;
3780     DWORD r;
3781
3782     hwnd = create_listview_control(LVS_REPORT);
3783     ok(hwnd != NULL, "failed to create a listview window\n");
3784
3785     insert_item(hwnd, 0);
3786
3787     /* headers columns aren't created automatically */
3788     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3789     ok(IsWindow(header), "Expected header handle\n");
3790     r = SendMessage(header, HDM_GETITEMCOUNT, 0, 0);
3791     expect(0, r);
3792
3793     DestroyWindow(hwnd);
3794 }
3795
3796 static void test_getitemrect(void)
3797 {
3798     HWND hwnd;
3799     HIMAGELIST himl, himl_ret;
3800     HBITMAP hbm;
3801     RECT rect;
3802     DWORD r;
3803     LVITEMA item;
3804     LVCOLUMNA col;
3805     INT order[2];
3806     POINT pt;
3807     HDC hdc;
3808
3809     /* rectangle isn't empty for empty text items */
3810     hwnd = create_listview_control(LVS_LIST);
3811     memset(&item, 0, sizeof(item));
3812     item.mask = 0;
3813     item.iItem = 0;
3814     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3815     expect(0, r);
3816     rect.left = LVIR_LABEL;
3817     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3818     expect(TRUE, r);
3819     expect(0, rect.left);
3820     expect(0, rect.top);
3821     hdc = GetDC(hwnd);
3822     todo_wine expect(((GetDeviceCaps(hdc, LOGPIXELSX) + 15) / 16) * 16, rect.right);
3823     ReleaseDC(hwnd, hdc);
3824     DestroyWindow(hwnd);
3825
3826     hwnd = create_listview_control(LVS_REPORT);
3827     ok(hwnd != NULL, "failed to create a listview window\n");
3828
3829     /* empty item */
3830     memset(&item, 0, sizeof(item));
3831     item.iItem = 0;
3832     item.iSubItem = 0;
3833     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3834     expect(0, r);
3835
3836     rect.left = LVIR_BOUNDS;
3837     rect.right = rect.top = rect.bottom = -1;
3838     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3839     expect(TRUE, r);
3840
3841     /* zero width rectangle with no padding */
3842     expect(0, rect.left);
3843     expect(0, rect.right);
3844
3845     insert_column(hwnd, 0);
3846     insert_column(hwnd, 1);
3847
3848     col.mask = LVCF_WIDTH;
3849     col.cx   = 50;
3850     r = SendMessage(hwnd, LVM_SETCOLUMN, 0, (LPARAM)&col);
3851     expect(TRUE, r);
3852
3853     col.mask = LVCF_WIDTH;
3854     col.cx   = 100;
3855     r = SendMessage(hwnd, LVM_SETCOLUMN, 1, (LPARAM)&col);
3856     expect(TRUE, r);
3857
3858     rect.left = LVIR_BOUNDS;
3859     rect.right = rect.top = rect.bottom = -1;
3860     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3861     expect(TRUE, r);
3862
3863     /* still no left padding */
3864     expect(0, rect.left);
3865     expect(150, rect.right);
3866
3867     rect.left = LVIR_SELECTBOUNDS;
3868     rect.right = rect.top = rect.bottom = -1;
3869     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3870     expect(TRUE, r);
3871     /* padding */
3872     expect(2, rect.left);
3873
3874     rect.left = LVIR_LABEL;
3875     rect.right = rect.top = rect.bottom = -1;
3876     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3877     expect(TRUE, r);
3878     /* padding, column width */
3879     expect(2, rect.left);
3880     expect(50, rect.right);
3881
3882     /* no icons attached */
3883     rect.left = LVIR_ICON;
3884     rect.right = rect.top = rect.bottom = -1;
3885     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3886     expect(TRUE, r);
3887     /* padding */
3888     expect(2, rect.left);
3889     expect(2, rect.right);
3890
3891     /* change order */
3892     order[0] = 1; order[1] = 0;
3893     r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
3894     expect(TRUE, r);
3895     pt.x = -1;
3896     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3897     expect(TRUE, r);
3898     /* 1 indexed column width + padding */
3899     expect(102, pt.x);
3900     /* rect is at zero too */
3901     rect.left = LVIR_BOUNDS;
3902     rect.right = rect.top = rect.bottom = -1;
3903     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3904     expect(TRUE, r);
3905     expect(0, rect.left);
3906     /* just width sum */
3907     expect(150, rect.right);
3908
3909     rect.left = LVIR_SELECTBOUNDS;
3910     rect.right = rect.top = rect.bottom = -1;
3911     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3912     expect(TRUE, r);
3913     /* column width + padding */
3914     expect(102, rect.left);
3915
3916     /* back to initial order */
3917     order[0] = 0; order[1] = 1;
3918     r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
3919     expect(TRUE, r);
3920
3921     /* state icons */
3922     himl = ImageList_Create(16, 16, 0, 2, 2);
3923     ok(himl != NULL, "failed to create imagelist\n");
3924     hbm = CreateBitmap(16, 16, 1, 1, NULL);
3925     ok(hbm != NULL, "failed to create bitmap\n");
3926     r = ImageList_Add(himl, hbm, 0);
3927     expect(0, r);
3928     hbm = CreateBitmap(16, 16, 1, 1, NULL);
3929     ok(hbm != NULL, "failed to create bitmap\n");
3930     r = ImageList_Add(himl, hbm, 0);
3931     expect(1, r);
3932
3933     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
3934     expect(0, r);
3935
3936     item.mask = LVIF_STATE;
3937     item.state = INDEXTOSTATEIMAGEMASK(1);
3938     item.stateMask = LVIS_STATEIMAGEMASK;
3939     item.iItem = 0;
3940     item.iSubItem = 0;
3941     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3942     expect(TRUE, r);
3943
3944     /* icon bounds */
3945     rect.left = LVIR_ICON;
3946     rect.right = rect.top = rect.bottom = -1;
3947     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3948     expect(TRUE, r);
3949     /* padding + stateicon width */
3950     expect(18, rect.left);
3951     expect(18, rect.right);
3952     /* label bounds */
3953     rect.left = LVIR_LABEL;
3954     rect.right = rect.top = rect.bottom = -1;
3955     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3956     expect(TRUE, r);
3957     /* padding + stateicon width -> column width */
3958     expect(18, rect.left);
3959     expect(50, rect.right);
3960
3961     himl_ret = (HIMAGELIST)SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, 0);
3962     ok(himl_ret == himl, "got %p, expected %p\n", himl_ret, himl);
3963
3964     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
3965     expect(0, r);
3966
3967     item.mask = LVIF_STATE | LVIF_IMAGE;
3968     item.iImage = 1;
3969     item.state = 0;
3970     item.stateMask = ~0;
3971     item.iItem = 0;
3972     item.iSubItem = 0;
3973     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3974     expect(TRUE, r);
3975
3976     /* icon bounds */
3977     rect.left = LVIR_ICON;
3978     rect.right = rect.top = rect.bottom = -1;
3979     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3980     expect(TRUE, r);
3981     /* padding, icon width */
3982     expect(2, rect.left);
3983     expect(18, rect.right);
3984     /* label bounds */
3985     rect.left = LVIR_LABEL;
3986     rect.right = rect.top = rect.bottom = -1;
3987     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3988     expect(TRUE, r);
3989     /* padding + icon width -> column width */
3990     expect(18, rect.left);
3991     expect(50, rect.right);
3992
3993     /* select bounds */
3994     rect.left = LVIR_SELECTBOUNDS;
3995     rect.right = rect.top = rect.bottom = -1;
3996     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3997     expect(TRUE, r);
3998     /* padding, column width */
3999     expect(2, rect.left);
4000     expect(50, rect.right);
4001
4002     /* try with indentation */
4003     item.mask = LVIF_INDENT;
4004     item.iIndent = 1;
4005     item.iItem = 0;
4006     item.iSubItem = 0;
4007     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
4008     expect(TRUE, r);
4009
4010     /* bounds */
4011     rect.left = LVIR_BOUNDS;
4012     rect.right = rect.top = rect.bottom = -1;
4013     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4014     expect(TRUE, r);
4015     /* padding + 1 icon width, column width */
4016     expect(0, rect.left);
4017     expect(150, rect.right);
4018
4019     /* select bounds */
4020     rect.left = LVIR_SELECTBOUNDS;
4021     rect.right = rect.top = rect.bottom = -1;
4022     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4023     expect(TRUE, r);
4024     /* padding + 1 icon width, column width */
4025     expect(2 + 16, rect.left);
4026     expect(50, rect.right);
4027
4028     /* label bounds */
4029     rect.left = LVIR_LABEL;
4030     rect.right = rect.top = rect.bottom = -1;
4031     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4032     expect(TRUE, r);
4033     /* padding + 2 icon widths, column width */
4034     expect(2 + 16*2, rect.left);
4035     expect(50, rect.right);
4036
4037     /* icon bounds */
4038     rect.left = LVIR_ICON;
4039     rect.right = rect.top = rect.bottom = -1;
4040     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4041     expect(TRUE, r);
4042     /* padding + 1 icon width indentation, icon width */
4043     expect(2 + 16, rect.left);
4044     expect(34, rect.right);
4045
4046     DestroyWindow(hwnd);
4047 }
4048
4049 static void test_editbox(void)
4050 {
4051     static CHAR testitemA[]  = "testitem";
4052     static CHAR testitem1A[] = "testitem_quitelongname";
4053     static CHAR testitem2A[] = "testITEM_quitelongname";
4054     static CHAR buffer[25];
4055     HWND hwnd, hwndedit, hwndedit2, header;
4056     LVITEMA item;
4057     INT r;
4058
4059     hwnd = create_listview_control(LVS_EDITLABELS | LVS_REPORT);
4060     ok(hwnd != NULL, "failed to create a listview window\n");
4061
4062     insert_column(hwnd, 0);
4063
4064     memset(&item, 0, sizeof(item));
4065     item.mask = LVIF_TEXT;
4066     item.pszText = testitemA;
4067     item.iItem = 0;
4068     item.iSubItem = 0;
4069     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
4070     expect(0, r);
4071
4072     /* test notifications without edit created */
4073     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4074     r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)0xdeadbeef);
4075     expect(0, r);
4076     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
4077                 "edit box WM_COMMAND (EN_SETFOCUS), no edit created", FALSE);
4078     /* same thing but with valid window */
4079     hwndedit = CreateWindowA("Edit", "Test edit", WS_VISIBLE | WS_CHILD, 0, 0, 20,
4080                 10, hwnd, (HMENU)1, (HINSTANCE)GetWindowLongPtrA(hwnd, GWLP_HINSTANCE), 0);
4081     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4082     r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)hwndedit);
4083     expect(0, r);
4084     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
4085                 "edit box WM_COMMAND (EN_SETFOCUS), no edit created #2", FALSE);
4086     DestroyWindow(hwndedit);
4087
4088     /* setting focus is necessary */
4089     SetFocus(hwnd);
4090     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4091     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4092
4093     /* test children Z-order after Edit box created */
4094     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
4095     ok(IsWindow(header), "Expected header to be created\n");
4096     ok(GetTopWindow(hwnd) == header, "Expected header to be on top\n");
4097     ok(GetNextWindow(header, GW_HWNDNEXT) == hwndedit, "got %p\n", GetNextWindow(header, GW_HWNDNEXT));
4098
4099     /* modify initial string */
4100     r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
4101     expect(TRUE, r);
4102
4103     /* edit window is resized and repositioned,
4104        check again for Z-order - it should be preserved */
4105     ok(GetTopWindow(hwnd) == header, "Expected header to be on top\n");
4106     ok(GetNextWindow(header, GW_HWNDNEXT) == hwndedit, "got %p\n", GetNextWindow(header, GW_HWNDNEXT));
4107
4108     /* return focus to listview */
4109     SetFocus(hwnd);
4110
4111     memset(&item, 0, sizeof(item));
4112     item.mask = LVIF_TEXT;
4113     item.pszText = buffer;
4114     item.cchTextMax = sizeof(buffer);
4115     item.iItem = 0;
4116     item.iSubItem = 0;
4117     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
4118     expect(TRUE, r);
4119
4120     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
4121
4122     /* send LVM_EDITLABEL on already created edit */
4123     SetFocus(hwnd);
4124     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4125     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4126     /* focus will be set to edit */
4127     ok(GetFocus() == hwndedit, "Expected Edit window to be focused\n");
4128     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4129     ok(IsWindow(hwndedit2), "Expected Edit window to be created\n");
4130
4131     /* creating label disabled when control isn't focused */
4132     SetFocus(0);
4133     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4134     todo_wine ok(hwndedit == NULL, "Expected Edit window not to be created\n");
4135
4136     /* check EN_KILLFOCUS handling */
4137     memset(&item, 0, sizeof(item));
4138     item.pszText = testitemA;
4139     item.iItem = 0;
4140     item.iSubItem = 0;
4141     r = SendMessage(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
4142     expect(TRUE, r);
4143
4144     SetFocus(hwnd);
4145     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4146     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4147     /* modify edit and notify control that it lost focus */
4148     r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
4149     expect(TRUE, r);
4150     g_editbox_disp_info.item.pszText = NULL;
4151     r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
4152     expect(0, r);
4153     ok(g_editbox_disp_info.item.pszText != NULL, "expected notification with not null text\n");
4154
4155     memset(&item, 0, sizeof(item));
4156     item.pszText = buffer;
4157     item.cchTextMax = sizeof(buffer);
4158     item.iItem = 0;
4159     item.iSubItem = 0;
4160     r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
4161     expect(lstrlen(item.pszText), r);
4162     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
4163     ok(!IsWindow(hwndedit), "Expected Edit window to be freed\n");
4164
4165     /* change item name to differ in casing only */
4166     SetFocus(hwnd);
4167     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4168     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4169     /* modify edit and notify control that it lost focus */
4170     r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem2A);
4171     expect(TRUE, r);
4172     g_editbox_disp_info.item.pszText = NULL;
4173     r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
4174     expect(0, r);
4175     ok(g_editbox_disp_info.item.pszText != NULL, "got %p\n", g_editbox_disp_info.item.pszText);
4176
4177     memset(&item, 0, sizeof(item));
4178     item.pszText = buffer;
4179     item.cchTextMax = sizeof(buffer);
4180     item.iItem = 0;
4181     item.iSubItem = 0;
4182     r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
4183     expect(lstrlen(item.pszText), r);
4184     ok(strcmp(buffer, testitem2A) == 0, "got %s, expected %s\n", buffer, testitem2A);
4185     ok(!IsWindow(hwndedit), "Expected Edit window to be freed\n");
4186
4187     /* end edit without saving */
4188     SetFocus(hwnd);
4189     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4190     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4191     r = SendMessage(hwndedit, WM_KEYDOWN, VK_ESCAPE, 0);
4192     expect(0, r);
4193     ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
4194                 "edit box - end edit, no change, escape", TRUE);
4195     /* end edit with saving */
4196     SetFocus(hwnd);
4197     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4198     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4199     r = SendMessage(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
4200     expect(0, r);
4201     ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
4202                 "edit box - end edit, no change, return", TRUE);
4203
4204     memset(&item, 0, sizeof(item));
4205     item.pszText = buffer;
4206     item.cchTextMax = sizeof(buffer);
4207     item.iItem = 0;
4208     item.iSubItem = 0;
4209     r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
4210     expect(lstrlen(item.pszText), r);
4211     ok(strcmp(buffer, testitem2A) == 0, "Expected item text to change\n");
4212
4213     /* LVM_EDITLABEL with -1 destroys current edit */
4214     hwndedit = (HWND)SendMessage(hwnd, LVM_GETEDITCONTROL, 0, 0);
4215     ok(hwndedit == NULL, "Expected Edit window not to be created\n");
4216     /* no edit present */
4217     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
4218     ok(hwndedit == NULL, "Expected Edit window not to be created\n");
4219     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4220     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4221     /* edit present */
4222     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
4223     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
4224     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
4225     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
4226     ok(GetFocus() == hwnd, "Expected List to be focused\n");
4227     /* check another negative value */
4228     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4229     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4230     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
4231     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -2, 0);
4232     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
4233     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
4234     ok(GetFocus() == hwnd, "Expected List to be focused\n");
4235     /* and value greater than max item index */
4236     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4237     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4238     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
4239     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
4240     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, r, 0);
4241     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
4242     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
4243     ok(GetFocus() == hwnd, "Expected List to be focused\n");
4244
4245     /* messaging tests */
4246     SetFocus(hwnd);
4247     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4248     blockEdit = FALSE;
4249     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4250     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4251     /* testing only sizing messages */
4252     ok_sequence(sequences, EDITBOX_SEQ_INDEX, editbox_create_pos,
4253                 "edit box create - sizing", FALSE);
4254
4255     /* WM_COMMAND with EN_KILLFOCUS isn't forwarded to parent */
4256     SetFocus(hwnd);
4257     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4258     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4259     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4260     r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
4261     expect(0, r);
4262     ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
4263                 "edit box WM_COMMAND (EN_KILLFOCUS)", TRUE);
4264
4265     DestroyWindow(hwnd);
4266 }
4267
4268 static void test_notifyformat(void)
4269 {
4270     HWND hwnd, header;
4271     DWORD r;
4272
4273     hwnd = create_listview_control(LVS_REPORT);
4274     ok(hwnd != NULL, "failed to create a listview window\n");
4275
4276     /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
4277        CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
4278     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4279     expect(0, r);
4280     SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
4281     /* set */
4282     r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 1, 0);
4283     expect(0, r);
4284     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4285     if (r == 1)
4286     {
4287         r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 0, 0);
4288         expect(1, r);
4289         r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4290         expect(0, r);
4291     }
4292     else
4293     {
4294         win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
4295         DestroyWindow(hwnd);
4296         return;
4297     }
4298
4299     DestroyWindow(hwnd);
4300
4301     /* test failure in parent WM_NOTIFYFORMAT  */
4302     notifyFormat = 0;
4303     hwnd = create_listview_control(LVS_REPORT);
4304     ok(hwnd != NULL, "failed to create a listview window\n");
4305     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4306     ok(IsWindow(header), "expected header to be created\n");
4307     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4308     expect(0, r);
4309     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
4310     ok( r == 1, "Expected 1, got %d\n", r );
4311     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
4312     ok(r != 0, "Expected valid format\n");
4313
4314     notifyFormat = NFR_UNICODE;
4315     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
4316     expect(NFR_UNICODE, r);
4317     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4318     expect(1, r);
4319     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
4320     ok( r == 1, "Expected 1, got %d\n", r );
4321
4322     notifyFormat = NFR_ANSI;
4323     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
4324     expect(NFR_ANSI, r);
4325     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4326     expect(0, r);
4327     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
4328     ok( r == 1, "Expected 1, got %d\n", r );
4329
4330     DestroyWindow(hwnd);
4331
4332     hwndparentW = create_parent_window(TRUE);
4333     ok(IsWindow(hwndparentW), "Unicode parent creation failed\n");
4334     if (!IsWindow(hwndparentW))  return;
4335
4336     notifyFormat = -1;
4337     hwnd = create_listview_controlW(LVS_REPORT, hwndparentW);
4338     ok(hwnd != NULL, "failed to create a listview window\n");
4339     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4340     ok(IsWindow(header), "expected header to be created\n");
4341     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4342     expect(1, r);
4343     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
4344     expect(1, r);
4345     DestroyWindow(hwnd);
4346     /* receiving error code defaulting to ansi */
4347     notifyFormat = 0;
4348     hwnd = create_listview_controlW(LVS_REPORT, hwndparentW);
4349     ok(hwnd != NULL, "failed to create a listview window\n");
4350     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4351     ok(IsWindow(header), "expected header to be created\n");
4352     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4353     expect(0, r);
4354     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
4355     expect(1, r);
4356     DestroyWindow(hwnd);
4357     /* receiving ansi code from unicode window, use it */
4358     notifyFormat = NFR_ANSI;
4359     hwnd = create_listview_controlW(LVS_REPORT, hwndparentW);
4360     ok(hwnd != NULL, "failed to create a listview window\n");
4361     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4362     ok(IsWindow(header), "expected header to be created\n");
4363     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4364     expect(0, r);
4365     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
4366     expect(1, r);
4367     DestroyWindow(hwnd);
4368     /* unicode listview with ansi parent window */
4369     notifyFormat = -1;
4370     hwnd = create_listview_controlW(LVS_REPORT, hwndparent);
4371     ok(hwnd != NULL, "failed to create a listview window\n");
4372     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4373     ok(IsWindow(header), "expected header to be created\n");
4374     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4375     expect(0, r);
4376     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
4377     expect(1, r);
4378     DestroyWindow(hwnd);
4379     /* unicode listview with ansi parent window, return error code */
4380     notifyFormat = 0;
4381     hwnd = create_listview_controlW(LVS_REPORT, hwndparent);
4382     ok(hwnd != NULL, "failed to create a listview window\n");
4383     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4384     ok(IsWindow(header), "expected header to be created\n");
4385     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4386     expect(0, r);
4387     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
4388     expect(1, r);
4389     DestroyWindow(hwnd);
4390
4391     DestroyWindow(hwndparentW);
4392 }
4393
4394 static void test_indentation(void)
4395 {
4396     HWND hwnd;
4397     LVITEMA item;
4398     DWORD r;
4399
4400     hwnd = create_listview_control(LVS_REPORT);
4401     ok(hwnd != NULL, "failed to create a listview window\n");
4402
4403     memset(&item, 0, sizeof(item));
4404     item.mask = LVIF_INDENT;
4405     item.iItem = 0;
4406     item.iIndent = I_INDENTCALLBACK;
4407     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
4408     expect(0, r);
4409
4410     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4411
4412     item.iItem = 0;
4413     item.mask = LVIF_INDENT;
4414     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
4415     expect(TRUE, r);
4416
4417     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
4418                 "get indent dispinfo", FALSE);
4419
4420     DestroyWindow(hwnd);
4421 }
4422
4423 static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param)
4424 {
4425     return 0;
4426 }
4427
4428 static BOOL is_below_comctl_5(void)
4429 {
4430     HWND hwnd;
4431     BOOL ret;
4432
4433     hwnd = create_listview_control(LVS_REPORT);
4434     ok(hwnd != NULL, "failed to create a listview window\n");
4435     insert_item(hwnd, 0);
4436
4437     ret = SendMessage(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx);
4438
4439     DestroyWindow(hwnd);
4440
4441     return !ret;
4442 }
4443
4444 static void test_get_set_view(void)
4445 {
4446     HWND hwnd;
4447     DWORD ret;
4448     DWORD_PTR style;
4449
4450     /* test style->view mapping */
4451     hwnd = create_listview_control(LVS_REPORT);
4452     ok(hwnd != NULL, "failed to create a listview window\n");
4453
4454     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
4455     expect(LV_VIEW_DETAILS, ret);
4456
4457     style = GetWindowLongPtr(hwnd, GWL_STYLE);
4458     /* LVS_ICON == 0 */
4459     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_REPORT);
4460     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
4461     expect(LV_VIEW_ICON, ret);
4462
4463     style = GetWindowLongPtr(hwnd, GWL_STYLE);
4464     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_SMALLICON);
4465     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
4466     expect(LV_VIEW_SMALLICON, ret);
4467
4468     style = GetWindowLongPtr(hwnd, GWL_STYLE);
4469     SetWindowLongPtr(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST);
4470     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
4471     expect(LV_VIEW_LIST, ret);
4472
4473     /* switching view doesn't touch window style */
4474     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0);
4475     expect(1, ret);
4476     style = GetWindowLongPtr(hwnd, GWL_STYLE);
4477     ok(style & LVS_LIST, "Expected style to be preserved\n");
4478     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0);
4479     expect(1, ret);
4480     style = GetWindowLongPtr(hwnd, GWL_STYLE);
4481     ok(style & LVS_LIST, "Expected style to be preserved\n");
4482     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0);
4483     expect(1, ret);
4484     style = GetWindowLongPtr(hwnd, GWL_STYLE);
4485     ok(style & LVS_LIST, "Expected style to be preserved\n");
4486
4487     DestroyWindow(hwnd);
4488 }
4489
4490 static void test_canceleditlabel(void)
4491 {
4492     HWND hwnd, hwndedit;
4493     DWORD ret;
4494     CHAR buff[10];
4495     LVITEMA itema;
4496     static CHAR test[] = "test";
4497     static const CHAR test1[] = "test1";
4498
4499     hwnd = create_listview_control(LVS_EDITLABELS | LVS_REPORT);
4500     ok(hwnd != NULL, "failed to create a listview window\n");
4501
4502     insert_item(hwnd, 0);
4503
4504     /* try without edit created */
4505     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4506     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
4507     expect(TRUE, ret);
4508     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
4509                 "cancel edit label without edit", FALSE);
4510
4511     /* cancel without data change */
4512     SetFocus(hwnd);
4513     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4514     ok(IsWindow(hwndedit), "Expected edit control to be created\n");
4515     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
4516     expect(TRUE, ret);
4517     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
4518
4519     /* cancel after data change */
4520     memset(&itema, 0, sizeof(itema));
4521     itema.pszText = test;
4522     ret = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&itema);
4523     expect(TRUE, ret);
4524     SetFocus(hwnd);
4525     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
4526     ok(IsWindow(hwndedit), "Expected edit control to be created\n");
4527     ret = SetWindowText(hwndedit, test1);
4528     expect(1, ret);
4529     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
4530     expect(TRUE, ret);
4531     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
4532     memset(&itema, 0, sizeof(itema));
4533     itema.pszText = buff;
4534     itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
4535     ret = SendMessage(hwnd, LVM_GETITEMTEXT, 0, (LPARAM)&itema);
4536     expect(5, ret);
4537     ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
4538
4539     DestroyWindow(hwnd);
4540 }
4541
4542 static void test_mapidindex(void)
4543 {
4544     HWND hwnd;
4545     INT ret;
4546
4547     /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
4548     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
4549     ok(hwnd != NULL, "failed to create a listview window\n");
4550     insert_item(hwnd, 0);
4551     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
4552     expect(-1, ret);
4553     DestroyWindow(hwnd);
4554
4555     hwnd = create_listview_control(LVS_REPORT);
4556     ok(hwnd != NULL, "failed to create a listview window\n");
4557
4558     /* LVM_MAPINDEXTOID with invalid index */
4559     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
4560     expect(-1, ret);
4561
4562     insert_item(hwnd, 0);
4563     insert_item(hwnd, 1);
4564
4565     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, -1, 0);
4566     expect(-1, ret);
4567     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 2, 0);
4568     expect(-1, ret);
4569
4570     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
4571     expect(0, ret);
4572     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
4573     expect(1, ret);
4574     /* remove 0 indexed item, id retained */
4575     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
4576     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
4577     expect(1, ret);
4578     /* new id starts from previous value */
4579     insert_item(hwnd, 1);
4580     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
4581     expect(2, ret);
4582
4583     /* get index by id */
4584     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, -1, 0);
4585     expect(-1, ret);
4586     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 0, 0);
4587     expect(-1, ret);
4588     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 1, 0);
4589     expect(0, ret);
4590     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 2, 0);
4591     expect(1, ret);
4592
4593     DestroyWindow(hwnd);
4594 }
4595
4596 static void test_getitemspacing(void)
4597 {
4598     HWND hwnd;
4599     DWORD ret;
4600     INT cx, cy;
4601     HIMAGELIST himl;
4602     HBITMAP hbmp;
4603     LVITEMA itema;
4604
4605     cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON);
4606     cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
4607
4608     /* LVS_ICON */
4609     hwnd = create_listview_control(LVS_ICON);
4610     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4611 todo_wine {
4612     expect(cx, LOWORD(ret));
4613     expect(cy, HIWORD(ret));
4614 }
4615     /* now try with icons */
4616     himl = ImageList_Create(40, 40, 0, 4, 4);
4617     ok(himl != NULL, "failed to create imagelist\n");
4618     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
4619     ok(hbmp != NULL, "failed to create bitmap\n");
4620     ret = ImageList_Add(himl, hbmp, 0);
4621     expect(0, ret);
4622     ret = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
4623     expect(0, ret);
4624
4625     itema.mask = LVIF_IMAGE;
4626     itema.iImage = 0;
4627     itema.iItem = 0;
4628     itema.iSubItem = 0;
4629     ret = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&itema);
4630     expect(0, ret);
4631     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4632 todo_wine {
4633     /* spacing + icon size returned */
4634     expect(cx + 40, LOWORD(ret));
4635     expect(cy + 40, HIWORD(ret));
4636 }
4637     DestroyWindow(hwnd);
4638     /* LVS_SMALLICON */
4639     hwnd = create_listview_control(LVS_SMALLICON);
4640     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4641 todo_wine {
4642     expect(cx, LOWORD(ret));
4643     expect(cy, HIWORD(ret));
4644 }
4645     DestroyWindow(hwnd);
4646     /* LVS_REPORT */
4647     hwnd = create_listview_control(LVS_REPORT);
4648     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4649 todo_wine {
4650     expect(cx, LOWORD(ret));
4651     expect(cy, HIWORD(ret));
4652 }
4653     DestroyWindow(hwnd);
4654     /* LVS_LIST */
4655     hwnd = create_listview_control(LVS_LIST);
4656     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4657 todo_wine {
4658     expect(cx, LOWORD(ret));
4659     expect(cy, HIWORD(ret));
4660 }
4661     DestroyWindow(hwnd);
4662 }
4663
4664 static void test_getcolumnwidth(void)
4665 {
4666     HWND hwnd;
4667     INT ret;
4668     DWORD_PTR style;
4669     LVCOLUMNA col;
4670     LVITEMA itema;
4671     HDC hdc;
4672
4673     /* default column width */
4674     hwnd = create_listview_control(LVS_ICON);
4675     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
4676     expect(0, ret);
4677     style = GetWindowLong(hwnd, GWL_STYLE);
4678     SetWindowLong(hwnd, GWL_STYLE, style | LVS_LIST);
4679     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
4680     todo_wine expect(8, ret);
4681     style = GetWindowLong(hwnd, GWL_STYLE) & ~LVS_LIST;
4682     SetWindowLong(hwnd, GWL_STYLE, style | LVS_REPORT);
4683     col.mask = 0;
4684     ret = SendMessage(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
4685     expect(0, ret);
4686     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
4687     expect(10, ret);
4688     DestroyWindow(hwnd);
4689
4690     /* default column width with item added */
4691     hwnd = create_listview_control(LVS_LIST);
4692     memset(&itema, 0, sizeof(itema));
4693     SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema);
4694     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
4695     hdc = GetDC(hwnd);
4696     todo_wine expect(((GetDeviceCaps(hdc, LOGPIXELSX) + 15) / 16) * 16, ret);
4697     ReleaseDC(hwnd, hdc);
4698     DestroyWindow(hwnd);
4699 }
4700
4701 static void test_scrollnotify(void)
4702 {
4703     HWND hwnd;
4704     DWORD ret;
4705
4706     hwnd = create_listview_control(LVS_REPORT);
4707
4708     insert_column(hwnd, 0);
4709     insert_column(hwnd, 1);
4710     insert_item(hwnd, 0);
4711
4712     /* make it scrollable - resize */
4713     ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
4714     expect(TRUE, ret);
4715     ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
4716     expect(TRUE, ret);
4717
4718     /* try with dummy call */
4719     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4720     ret = SendMessage(hwnd, LVM_SCROLL, 0, 0);
4721     expect(TRUE, ret);
4722     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
4723                 "scroll notify 1", TRUE);
4724
4725     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4726     ret = SendMessage(hwnd, LVM_SCROLL, 1, 0);
4727     expect(TRUE, ret);
4728     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
4729                 "scroll notify 2", TRUE);
4730
4731     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4732     ret = SendMessage(hwnd, LVM_SCROLL, 1, 1);
4733     expect(TRUE, ret);
4734     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
4735                 "scroll notify 3", TRUE);
4736
4737     DestroyWindow(hwnd);
4738 }
4739
4740 static void test_LVS_EX_TRANSPARENTBKGND(void)
4741 {
4742     HWND hwnd;
4743     DWORD ret;
4744     HDC hdc;
4745
4746     hwnd = create_listview_control(LVS_REPORT);
4747
4748     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
4749     expect(TRUE, ret);
4750
4751     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
4752                                                     LVS_EX_TRANSPARENTBKGND);
4753
4754     ret = SendMessage(hwnd, LVM_GETBKCOLOR, 0, 0);
4755     if (ret != CLR_NONE)
4756     {
4757         win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n");
4758         DestroyWindow(hwnd);
4759         return;
4760     }
4761
4762     /* try to set some back color and check this style bit */
4763     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
4764     expect(TRUE, ret);
4765     ret = SendMessage(hwnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
4766     ok(!(ret & LVS_EX_TRANSPARENTBKGND), "Expected LVS_EX_TRANSPARENTBKGND to unset\n");
4767
4768     /* now test what this style actually does */
4769     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
4770                                                     LVS_EX_TRANSPARENTBKGND);
4771
4772     hdc = GetWindowDC(hwndparent);
4773
4774     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4775     SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
4776     ok_sequence(sequences, PARENT_SEQ_INDEX, lvs_ex_transparentbkgnd_seq,
4777                 "LVS_EX_TRANSPARENTBKGND parent", FALSE);
4778
4779     ReleaseDC(hwndparent, hdc);
4780
4781     DestroyWindow(hwnd);
4782 }
4783
4784 static void test_approximate_viewrect(void)
4785 {
4786     HWND hwnd;
4787     DWORD ret;
4788     HIMAGELIST himl;
4789     HBITMAP hbmp;
4790     LVITEMA itema;
4791     static CHAR test[] = "abracadabra, a very long item label";
4792
4793     hwnd = create_listview_control(LVS_ICON);
4794     himl = ImageList_Create(40, 40, 0, 4, 4);
4795     ok(himl != NULL, "failed to create imagelist\n");
4796     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
4797     ok(hbmp != NULL, "failed to create bitmap\n");
4798     ret = ImageList_Add(himl, hbmp, 0);
4799     expect(0, ret);
4800     ret = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
4801     expect(0, ret);
4802
4803     itema.mask = LVIF_IMAGE;
4804     itema.iImage = 0;
4805     itema.iItem = 0;
4806     itema.iSubItem = 0;
4807     ret = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&itema);
4808     expect(0, ret);
4809
4810     ret = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(75, 75));
4811     if (ret == 0)
4812     {
4813         /* version 4.0 */
4814         win_skip("LVM_SETICONSPACING unimplemented. Skipping.\n");
4815         return;
4816     }
4817
4818     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100));
4819     expect(MAKELONG(77,827), ret);
4820
4821     ret = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(50, 50));
4822     ok(ret != 0, "got 0\n");
4823
4824     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100));
4825     expect(MAKELONG(102,302), ret);
4826
4827     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100));
4828     expect(MAKELONG(52,52), ret);
4829
4830     itema.pszText = test;
4831     ret = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&itema);
4832     expect(TRUE, ret);
4833     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100));
4834     expect(MAKELONG(52,52), ret);
4835
4836     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 0, MAKELPARAM(100,100));
4837     expect(MAKELONG(52,2), ret);
4838     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 1, MAKELPARAM(100,100));
4839     expect(MAKELONG(52,52), ret);
4840     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 2, MAKELPARAM(100,100));
4841     expect(MAKELONG(102,52), ret);
4842     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 3, MAKELPARAM(100,100));
4843     expect(MAKELONG(102,102), ret);
4844     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 4, MAKELPARAM(100,100));
4845     expect(MAKELONG(102,102), ret);
4846     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 5, MAKELPARAM(100,100));
4847     expect(MAKELONG(102,152), ret);
4848     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 6, MAKELPARAM(100,100));
4849     expect(MAKELONG(102,152), ret);
4850     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 7, MAKELPARAM(160,100));
4851     expect(MAKELONG(152,152), ret);
4852
4853     DestroyWindow(hwnd);
4854 }
4855
4856 static void test_finditem(void)
4857 {
4858     LVFINDINFOA fi;
4859     static char f[5];
4860     HWND hwnd;
4861     INT r;
4862
4863     hwnd = create_listview_control(LVS_REPORT);
4864     insert_item(hwnd, 0);
4865
4866     memset(&fi, 0, sizeof(fi));
4867
4868     /* full string search, inserted text was "foo" */
4869     strcpy(f, "foo");
4870     fi.flags = LVFI_STRING;
4871     fi.psz = f;
4872     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4873     expect(0, r);
4874     /* partial string search, inserted text was "foo" */
4875     strcpy(f, "fo");
4876     fi.flags = LVFI_STRING | LVFI_PARTIAL;
4877     fi.psz = f;
4878     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4879     expect(0, r);
4880     /* partial string search, part after start char */
4881     strcpy(f, "oo");
4882     fi.flags = LVFI_STRING | LVFI_PARTIAL;
4883     fi.psz = f;
4884     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4885     expect(-1, r);
4886
4887     /* try with LVFI_SUBSTRING */
4888     strcpy(f, "fo");
4889     fi.flags = LVFI_SUBSTRING;
4890     fi.psz = f;
4891     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4892     if (r == -1)
4893     {
4894         win_skip("LVFI_SUBSTRING not supported\n");
4895         DestroyWindow(hwnd);
4896         return;
4897     }
4898     expect(0, r);
4899     strcpy(f, "f");
4900     fi.flags = LVFI_SUBSTRING;
4901     fi.psz = f;
4902     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4903     expect(0, r);
4904     strcpy(f, "o");
4905     fi.flags = LVFI_SUBSTRING;
4906     fi.psz = f;
4907     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4908     expect(-1, r);
4909
4910     strcpy(f, "f");
4911     fi.flags = LVFI_SUBSTRING | LVFI_STRING;
4912     fi.psz = f;
4913     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4914     expect(0, r);
4915
4916     DestroyWindow(hwnd);
4917 }
4918
4919 static void test_LVS_EX_HEADERINALLVIEWS(void)
4920 {
4921     HWND hwnd, header;
4922     DWORD style;
4923
4924     hwnd = create_listview_control(LVS_ICON);
4925
4926     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
4927                                                     LVS_EX_HEADERINALLVIEWS);
4928
4929     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4930     if (!IsWindow(header))
4931     {
4932         win_skip("LVS_EX_HEADERINALLVIEWS unsupported\n");
4933         DestroyWindow(hwnd);
4934         return;
4935     }
4936
4937     /* LVS_NOCOLUMNHEADER works as before */
4938     style = GetWindowLongA(hwnd, GWL_STYLE);
4939     SetWindowLongW(hwnd, GWL_STYLE, style | LVS_NOCOLUMNHEADER);
4940     style = GetWindowLongA(header, GWL_STYLE);
4941     ok(style & HDS_HIDDEN, "Expected HDS_HIDDEN\n");
4942     style = GetWindowLongA(hwnd, GWL_STYLE);
4943     SetWindowLongW(hwnd, GWL_STYLE, style & ~LVS_NOCOLUMNHEADER);
4944     style = GetWindowLongA(header, GWL_STYLE);
4945     ok(!(style & HDS_HIDDEN), "Expected HDS_HIDDEN to be unset\n");
4946
4947     /* try to remove style */
4948     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, 0);
4949     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4950     ok(IsWindow(header), "Expected header to be created\n");
4951     style = GetWindowLongA(header, GWL_STYLE);
4952     ok(!(style & HDS_HIDDEN), "HDS_HIDDEN not expected\n");
4953
4954     DestroyWindow(hwnd);
4955
4956     /* check other styles */
4957     hwnd = create_listview_control(LVS_LIST);
4958     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
4959                                                     LVS_EX_HEADERINALLVIEWS);
4960     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4961     ok(IsWindow(header), "Expected header to be created\n");
4962     DestroyWindow(hwnd);
4963
4964     hwnd = create_listview_control(LVS_SMALLICON);
4965     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
4966                                                     LVS_EX_HEADERINALLVIEWS);
4967     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4968     ok(IsWindow(header), "Expected header to be created\n");
4969     DestroyWindow(hwnd);
4970
4971     hwnd = create_listview_control(LVS_REPORT);
4972     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
4973                                                     LVS_EX_HEADERINALLVIEWS);
4974     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
4975     ok(IsWindow(header), "Expected header to be created\n");
4976     DestroyWindow(hwnd);
4977 }
4978
4979 static void test_hover(void)
4980 {
4981     HWND hwnd;
4982     DWORD r;
4983
4984     hwnd = create_listview_control(LVS_ICON);
4985
4986     /* test WM_MOUSEHOVER forwarding */
4987     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4988     r = SendMessage(hwnd, WM_MOUSEHOVER, 0, 0);
4989     expect(0, r);
4990     ok_sequence(sequences, PARENT_SEQ_INDEX, hover_parent, "NM_HOVER allow test", TRUE);
4991     g_block_hover = TRUE;
4992     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4993     r = SendMessage(hwnd, WM_MOUSEHOVER, 0, 0);
4994     expect(0, r);
4995     ok_sequence(sequences, PARENT_SEQ_INDEX, hover_parent, "NM_HOVER block test", TRUE);
4996     g_block_hover = FALSE;
4997
4998     r = SendMessage(hwnd, LVM_SETHOVERTIME, 0, 500);
4999     expect(HOVER_DEFAULT, r);
5000     r = SendMessage(hwnd, LVM_GETHOVERTIME, 0, 0);
5001     expect(500, r);
5002
5003     DestroyWindow(hwnd);
5004 }
5005
5006 static void test_destroynotify(void)
5007 {
5008     HWND hwnd;
5009
5010     hwnd = create_listview_control(LVS_REPORT);
5011     ok(hwnd != NULL, "failed to create listview window\n");
5012
5013     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5014     DestroyWindow(hwnd);
5015     ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_destroy, "check destroy order", FALSE);
5016 }
5017
5018 static void test_header_notification(void)
5019 {
5020     static char textA[] = "newtext";
5021     HWND list, header;
5022     HDITEMA item;
5023     NMHEADER nmh;
5024     LVCOLUMNA col;
5025     DWORD ret;
5026     BOOL r;
5027
5028     list = create_listview_control(LVS_REPORT);
5029     ok(list != NULL, "failed to create listview window\n");
5030
5031     memset(&col, 0, sizeof(col));
5032     col.mask = LVCF_WIDTH;
5033     col.cx = 100;
5034     ret = SendMessage(list, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
5035     expect(0, ret);
5036
5037     /* check list parent notification after header item changed,
5038        this test should be placed before header subclassing to avoid
5039        Listview -> Header messages to be logged */
5040     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5041
5042     col.mask = LVCF_TEXT;
5043     col.pszText = textA;
5044     r = SendMessage(list, LVM_SETCOLUMNA, 0, (LPARAM)&col);
5045     expect(TRUE, r);
5046
5047     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_header_changed_seq,
5048                 "header notify, listview", FALSE);
5049     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5050                 "header notify, parent", FALSE);
5051
5052     header = subclass_header(list);
5053
5054     ret = SendMessage(header, HDM_GETITEMCOUNT, 0, 0);
5055     expect(1, ret);
5056
5057     memset(&item, 0, sizeof(item));
5058     item.mask = HDI_WIDTH;
5059     ret = SendMessage(header, HDM_GETITEMA, 0, (LPARAM)&item);
5060     expect(1, ret);
5061     expect(100, item.cxy);
5062
5063     nmh.hdr.hwndFrom = header;
5064     nmh.hdr.idFrom = GetWindowLongPtr(header, GWLP_ID);
5065     nmh.hdr.code = HDN_ITEMCHANGEDA;
5066     nmh.iItem = 0;
5067     nmh.iButton = 0;
5068     item.mask = HDI_WIDTH;
5069     item.cxy = 50;
5070     nmh.pitem = &item;
5071     ret = SendMessage(list, WM_NOTIFY, 0, (LPARAM)&nmh);
5072     expect(0, ret);
5073
5074     DestroyWindow(list);
5075 }
5076
5077 static void test_header_notification2(void)
5078 {
5079     static char textA[] = "newtext";
5080     HWND list, header;
5081     HDITEMW itemW;
5082     NMHEADERW nmhdr;
5083     LVCOLUMNA col;
5084     DWORD ret;
5085     WCHAR buffer[100];
5086     struct message parent_header_notify_seq[] = {
5087         { WM_NOTIFY, sent|id, 0, 0, 0 },
5088         { 0 }
5089     };
5090
5091     list = create_listview_control(LVS_REPORT);
5092     ok(list != NULL, "failed to create listview window\n");
5093
5094     memset(&col, 0, sizeof(col));
5095     col.mask = LVCF_WIDTH | LVCF_TEXT;
5096     col.cx = 100;
5097     col.pszText = textA;
5098     ret = SendMessage(list, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
5099     expect(0, ret);
5100
5101     header = ListView_GetHeader(list);
5102     ok(header != 0, "No header\n");
5103     memset(&itemW, 0, sizeof(itemW));
5104     itemW.mask = HDI_WIDTH | HDI_ORDER | HDI_TEXT;
5105     itemW.pszText = buffer;
5106     itemW.cchTextMax = sizeof(buffer);
5107     ret = SendMessageW(header, HDM_GETITEMW, 0, (LPARAM)&itemW);
5108     expect(1, ret);
5109
5110     nmhdr.hdr.hwndFrom = header;
5111     nmhdr.hdr.idFrom = GetWindowLongPtr(header, GWLP_ID);
5112     nmhdr.iItem = 0;
5113     nmhdr.iButton = 0;
5114     nmhdr.pitem = &itemW;
5115
5116     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5117     nmhdr.hdr.code = HDN_ITEMCHANGINGW;
5118     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5119     parent_header_notify_seq[0].id = HDN_ITEMCHANGINGA;
5120     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5121                 "header notify, parent", TRUE);
5122     todo_wine
5123     ok(nmhdr.hdr.code == HDN_ITEMCHANGINGA, "Expected ANSI notification code\n");
5124     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5125     nmhdr.hdr.code = HDN_ITEMCHANGEDW;
5126     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5127     parent_header_notify_seq[0].id = HDN_ITEMCHANGEDA;
5128     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5129                 "header notify, parent", TRUE);
5130     todo_wine
5131     ok(nmhdr.hdr.code == HDN_ITEMCHANGEDA, "Expected ANSI notification code\n");
5132     /* HDN_ITEMCLICK sets focus to list, which generates messages we don't want to check */
5133     SetFocus(list);
5134     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5135     nmhdr.hdr.code = HDN_ITEMCLICKW;
5136     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5137     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_click_seq,
5138                 "header notify, parent", FALSE);
5139     ok(nmhdr.hdr.code == HDN_ITEMCLICKA, "Expected ANSI notification code\n");
5140     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5141     nmhdr.hdr.code = HDN_ITEMDBLCLICKW;
5142     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5143     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5144                 "header notify, parent", FALSE);
5145     ok(nmhdr.hdr.code == HDN_ITEMDBLCLICKW, "Expected Unicode notification code\n");
5146     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5147     nmhdr.hdr.code = HDN_DIVIDERDBLCLICKW;
5148     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5149     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_divider_dclick_seq,
5150                 "header notify, parent", TRUE);
5151     ok(nmhdr.hdr.code == HDN_DIVIDERDBLCLICKA, "Expected ANSI notification code\n");
5152     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5153     nmhdr.hdr.code = HDN_BEGINTRACKW;
5154     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5155     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5156                 "header notify, parent", FALSE);
5157     ok(nmhdr.hdr.code == HDN_BEGINTRACKW, "Expected Unicode notification code\n");
5158     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5159     nmhdr.hdr.code = HDN_ENDTRACKW;
5160     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5161     parent_header_notify_seq[0].id = HDN_ENDTRACKA;
5162     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5163                 "header notify, parent", FALSE);
5164     ok(nmhdr.hdr.code == HDN_ENDTRACKA, "Expected ANSI notification code\n");
5165     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5166     nmhdr.hdr.code = HDN_TRACKW;
5167     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5168     parent_header_notify_seq[0].id = HDN_TRACKA;
5169     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5170                 "header notify, parent", FALSE);
5171     ok(nmhdr.hdr.code == HDN_TRACKA, "Expected ANSI notification code\n");
5172     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5173     nmhdr.hdr.code = HDN_BEGINDRAG;
5174     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5175     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5176                 "header notify, parent", FALSE);
5177     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5178     nmhdr.hdr.code = HDN_ENDDRAG;
5179     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5180     parent_header_notify_seq[0].id = HDN_ENDDRAG;
5181     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5182                 "header notify, parent", FALSE);
5183     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5184     nmhdr.hdr.code = HDN_FILTERCHANGE;
5185     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5186     parent_header_notify_seq[0].id = HDN_FILTERCHANGE;
5187     parent_header_notify_seq[0].flags |= optional; /* NT4 does not send this message */
5188     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5189                 "header notify, parent", FALSE);
5190     parent_header_notify_seq[0].flags &= ~optional;
5191     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5192     nmhdr.hdr.code = HDN_BEGINFILTEREDIT;
5193     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5194     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5195                 "header notify, parent", FALSE);
5196     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5197     nmhdr.hdr.code = HDN_ENDFILTEREDIT;
5198     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5199     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5200                 "header notify, parent", FALSE);
5201     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5202     nmhdr.hdr.code = HDN_ITEMSTATEICONCLICK;
5203     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5204     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5205                 "header notify, parent", FALSE);
5206     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5207     nmhdr.hdr.code = HDN_ITEMKEYDOWN;
5208     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5209     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5210                 "header notify, parent", FALSE);
5211
5212     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5213
5214     DestroyWindow(list);
5215 }
5216
5217 static void test_createdragimage(void)
5218 {
5219     HIMAGELIST himl;
5220     POINT pt;
5221     HWND list;
5222
5223     list = create_listview_control(LVS_ICON);
5224     ok(list != NULL, "failed to create listview window\n");
5225
5226     insert_item(list, 0);
5227
5228     /* NULL point */
5229     himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, 0);
5230     ok(himl == NULL, "got %p\n", himl);
5231
5232     himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, (LPARAM)&pt);
5233     ok(himl != NULL, "got %p\n", himl);
5234     ImageList_Destroy(himl);
5235
5236     DestroyWindow(list);
5237 }
5238
5239 static void test_dispinfo(void)
5240 {
5241     static const char testA[] = "TEST";
5242     WCHAR buff[10];
5243     LVITEMA item;
5244     HWND hwnd;
5245     DWORD ret;
5246
5247     hwnd = create_listview_control(LVS_ICON);
5248     ok(hwnd != NULL, "failed to create listview window\n");
5249
5250     insert_item(hwnd, 0);
5251
5252     memset(&item, 0, sizeof(item));
5253     item.pszText = LPSTR_TEXTCALLBACKA;
5254     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
5255     expect(1, ret);
5256
5257     g_disp_A_to_W = TRUE;
5258     item.pszText = (char*)buff;
5259     item.cchTextMax = sizeof(buff)/sizeof(WCHAR);
5260     ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
5261     ok(ret == sizeof(testA)-1, "got %d, expected 4\n", ret);
5262     g_disp_A_to_W = FALSE;
5263
5264     ok(memcmp(item.pszText, testA, sizeof(testA)) == 0,
5265         "got %s, expected %s\n", item.pszText, testA);
5266
5267     DestroyWindow(hwnd);
5268 }
5269
5270 static void test_LVM_SETITEMTEXT(void)
5271 {
5272     static char testA[] = "TEST";
5273     LVITEMA item;
5274     HWND hwnd;
5275     DWORD ret;
5276
5277     hwnd = create_listview_control(LVS_ICON);
5278     ok(hwnd != NULL, "failed to create listview window\n");
5279
5280     insert_item(hwnd, 0);
5281
5282     /* null item pointer */
5283     ret = SendMessage(hwnd, LVM_SETITEMTEXTA, 0, 0);
5284     expect(FALSE, ret);
5285
5286     ret = SendMessage(hwnd, LVM_SETITEMTEXTW, 0, 0);
5287     expect(FALSE, ret);
5288
5289     /* index out of bounds */
5290     item.pszText = testA;
5291     item.cchTextMax = 0; /* ignored */
5292     item.iSubItem = 0;
5293
5294     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 1, (LPARAM)&item);
5295     expect(FALSE, ret);
5296
5297     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, -1, (LPARAM)&item);
5298     expect(FALSE, ret);
5299
5300     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
5301     expect(TRUE, ret);
5302
5303     DestroyWindow(hwnd);
5304 }
5305
5306 static void test_imagelists(void)
5307 {
5308     HWND hwnd, header;
5309     HIMAGELIST himl1, himl2, himl3;
5310     LRESULT ret;
5311
5312     himl1 = ImageList_Create(40, 40, 0, 4, 4);
5313     himl2 = ImageList_Create(40, 40, 0, 4, 4);
5314     himl3 = ImageList_Create(40, 40, 0, 4, 4);
5315     ok(himl1 != NULL, "Failed to create imagelist\n");
5316     ok(himl2 != NULL, "Failed to create imagelist\n");
5317     ok(himl3 != NULL, "Failed to create imagelist\n");
5318
5319     hwnd = create_listview_control(LVS_REPORT | LVS_SHAREIMAGELISTS);
5320     header = subclass_header(hwnd);
5321
5322     ok(header != NULL, "Expected header\n");
5323     ret = SendMessage(header, HDM_GETIMAGELIST, 0, 0);
5324     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5325
5326     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5327
5328     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl1);
5329     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5330     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist,
5331                 "set normal image list", FALSE);
5332
5333     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5334
5335     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl2);
5336     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5337     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist,
5338                 "set state image list", TRUE);
5339
5340     ret = SendMessage(header, HDM_GETIMAGELIST, 0, 0);
5341     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5342
5343     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5344
5345     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl3);
5346     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5347     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_header_set_imagelist,
5348                 "set small image list", FALSE);
5349
5350     ret = SendMessage(header, HDM_GETIMAGELIST, 0, 0);
5351     ok((HIMAGELIST)ret == himl3, "Expected imagelist %p, got %p\n", himl3, (HIMAGELIST)ret);
5352     DestroyWindow(hwnd);
5353
5354     hwnd = create_listview_control(WS_VISIBLE | LVS_ICON);
5355
5356     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5357
5358     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl1);
5359     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5360     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist,
5361                 "set normal image list", FALSE);
5362
5363     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5364
5365     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl2);
5366     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5367     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist,
5368                 "set state image list", FALSE);
5369
5370     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5371
5372     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl3);
5373     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5374     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist,
5375                 "set small image list", FALSE);
5376
5377     header = ListView_GetHeader(hwnd);
5378     ok(header == NULL, "Expected no header, got %p\n", header);
5379
5380     SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) | LVS_REPORT);
5381
5382     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
5383     ok(header != NULL, "Expected header, got NULL\n");
5384
5385     ret = SendMessage(header, HDM_GETIMAGELIST, 0, 0);
5386     ok((HIMAGELIST)ret == himl3, "Expected imagelist %p, got %p\n", himl3, (HIMAGELIST)ret);
5387
5388     DestroyWindow(hwnd);
5389 }
5390
5391 static void test_deleteitem(void)
5392 {
5393     LVITEMA item;
5394     UINT state;
5395     HWND hwnd;
5396     BOOL ret;
5397
5398     hwnd = create_listview_control(LVS_REPORT);
5399
5400     insert_item(hwnd, 0);
5401     insert_item(hwnd, 0);
5402     insert_item(hwnd, 0);
5403     insert_item(hwnd, 0);
5404     insert_item(hwnd, 0);
5405
5406     g_focus_test_LVN_DELETEITEM = TRUE;
5407
5408     /* delete focused item (not the last index) */
5409     item.stateMask = LVIS_FOCUSED;
5410     item.state = LVIS_FOCUSED;
5411     ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 2, (LPARAM)&item);
5412     ok(ret == TRUE, "got %d\n", ret);
5413     ret = SendMessageA(hwnd, LVM_DELETEITEM, 2, 0);
5414     ok(ret == TRUE, "got %d\n", ret);
5415     /* next item gets focus */
5416     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_FOCUSED);
5417     ok(state == LVIS_FOCUSED, "got %x\n", state);
5418
5419     /* focus last item and delete it */
5420     item.stateMask = LVIS_FOCUSED;
5421     item.state = LVIS_FOCUSED;
5422     ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 3, (LPARAM)&item);
5423     ok(ret == TRUE, "got %d\n", ret);
5424     ret = SendMessageA(hwnd, LVM_DELETEITEM, 3, 0);
5425     ok(ret == TRUE, "got %d\n", ret);
5426     /* new last item gets focus */
5427     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_FOCUSED);
5428     ok(state == LVIS_FOCUSED, "got %x\n", state);
5429
5430     /* focus first item and delete it */
5431     item.stateMask = LVIS_FOCUSED;
5432     item.state = LVIS_FOCUSED;
5433     ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
5434     ok(ret == TRUE, "got %d\n", ret);
5435     ret = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0);
5436     ok(ret == TRUE, "got %d\n", ret);
5437     /* new first item gets focus */
5438     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
5439     ok(state == LVIS_FOCUSED, "got %x\n", state);
5440
5441     g_focus_test_LVN_DELETEITEM = FALSE;
5442
5443     DestroyWindow(hwnd);
5444 }
5445
5446 static void test_insertitem(void)
5447 {
5448     LVITEMA item;
5449     UINT state;
5450     HWND hwnd;
5451     INT ret;
5452
5453     hwnd = create_listview_control(LVS_REPORT);
5454
5455     /* insert item 0 focused */
5456     item.mask = LVIF_STATE;
5457     item.state = LVIS_FOCUSED;
5458     item.stateMask = LVIS_FOCUSED;
5459     item.iItem = 0;
5460     item.iSubItem = 0;
5461     ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
5462     ok(ret == 0, "got %d\n", ret);
5463
5464     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
5465     ok(state == LVIS_FOCUSED, "got %x\n", state);
5466
5467     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5468
5469     /* insert item 1, focus shift */
5470     item.mask = LVIF_STATE;
5471     item.state = LVIS_FOCUSED;
5472     item.stateMask = LVIS_FOCUSED;
5473     item.iItem = 1;
5474     item.iSubItem = 0;
5475     ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
5476     ok(ret == 1, "got %d\n", ret);
5477
5478     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_insert_focused_seq, "insert focused", TRUE);
5479
5480     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_FOCUSED);
5481     ok(state == LVIS_FOCUSED, "got %x\n", state);
5482
5483     /* insert item 2, no focus shift */
5484     item.mask = LVIF_STATE;
5485     item.state = 0;
5486     item.stateMask = LVIS_FOCUSED;
5487     item.iItem = 2;
5488     item.iSubItem = 0;
5489     ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
5490     ok(ret == 2, "got %d\n", ret);
5491
5492     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_FOCUSED);
5493     ok(state == LVIS_FOCUSED, "got %x\n", state);
5494
5495     DestroyWindow(hwnd);
5496 }
5497
5498 START_TEST(listview)
5499 {
5500     HMODULE hComctl32;
5501     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
5502
5503     ULONG_PTR ctx_cookie;
5504     HANDLE hCtx;
5505     HWND hwnd;
5506
5507     hComctl32 = GetModuleHandleA("comctl32.dll");
5508     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
5509     if (pInitCommonControlsEx)
5510     {
5511         INITCOMMONCONTROLSEX iccex;
5512         iccex.dwSize = sizeof(iccex);
5513         iccex.dwICC  = ICC_LISTVIEW_CLASSES;
5514         pInitCommonControlsEx(&iccex);
5515     }
5516     else
5517         InitCommonControls();
5518
5519     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
5520
5521     hwndparent = create_parent_window(FALSE);
5522     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5523
5524     g_is_below_5 = is_below_comctl_5();
5525
5526     test_header_notification();
5527     test_header_notification2();
5528     test_images();
5529     test_checkboxes();
5530     test_items();
5531     test_create();
5532     test_redraw();
5533     test_customdraw();
5534     test_icon_spacing();
5535     test_color();
5536     test_item_count();
5537     test_item_position();
5538     test_columns();
5539     test_getorigin();
5540     test_multiselect();
5541     test_getitemrect();
5542     test_subitem_rect();
5543     test_sorting();
5544     test_ownerdata();
5545     test_norecompute();
5546     test_nosortheader();
5547     test_setredraw();
5548     test_hittest();
5549     test_getviewrect();
5550     test_getitemposition();
5551     test_columnscreation();
5552     test_editbox();
5553     test_notifyformat();
5554     test_indentation();
5555     test_getitemspacing();
5556     test_getcolumnwidth();
5557     test_approximate_viewrect();
5558     test_finditem();
5559     test_hover();
5560     test_destroynotify();
5561     test_createdragimage();
5562     test_dispinfo();
5563     test_LVM_SETITEMTEXT();
5564     test_imagelists();
5565     test_deleteitem();
5566     test_insertitem();
5567
5568     if (!load_v6_module(&ctx_cookie, &hCtx))
5569     {
5570         DestroyWindow(hwndparent);
5571         return;
5572     }
5573
5574     /* this is a XP SP3 failure workaround */
5575     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
5576                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT,
5577                            0, 0, 100, 100,
5578                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
5579     if (!IsWindow(hwnd))
5580     {
5581         win_skip("FIXME: failed to create ListView window.\n");
5582         unload_v6_module(ctx_cookie, hCtx);
5583         DestroyWindow(hwndparent);
5584         return;
5585     }
5586     else
5587         DestroyWindow(hwnd);
5588
5589     /* comctl32 version 6 tests start here */
5590     test_get_set_view();
5591     test_canceleditlabel();
5592     test_mapidindex();
5593     test_scrollnotify();
5594     test_LVS_EX_TRANSPARENTBKGND();
5595     test_LVS_EX_HEADERINALLVIEWS();
5596     test_deleteitem();
5597     test_multiselect();
5598     test_insertitem();
5599
5600     unload_v6_module(ctx_cookie, hCtx);
5601
5602     DestroyWindow(hwndparent);
5603 }