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