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