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