comctl32/listview: Add support for LVFI_SUBSTRING.
[wine] / dlls / comctl32 / tests / listview.c
1 /*
2  * ListView tests
3  *
4  * Copyright 2006 Mike McCormack for CodeWeavers
5  * Copyright 2007 George Gov
6  * Copyright 2009 Nikolay Sivov
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include <stdio.h>
24 #include <windows.h>
25 #include <commctrl.h>
26
27 #include "wine/test.h"
28 #include "v6util.h"
29 #include "msg.h"
30
31 #define PARENT_SEQ_INDEX       0
32 #define PARENT_FULL_SEQ_INDEX  1
33 #define LISTVIEW_SEQ_INDEX     2
34 #define EDITBOX_SEQ_INDEX      3
35 #define NUM_MSG_SEQUENCES      4
36
37 #define LISTVIEW_ID 0
38 #define HEADER_ID   1
39
40 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
41 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
42        "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
43
44 static const WCHAR testparentclassW[] =
45     {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
46
47 HWND hwndparent, hwndparentW;
48 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
49 BOOL blockEdit;
50 /* dumps LVN_ITEMCHANGED message data */
51 static BOOL g_dump_itemchanged;
52 /* format reported to control:
53    -1 falls to defproc, anything else returned */
54 INT  notifyFormat;
55 /* indicates we're running < 5.80 version */
56 BOOL g_is_below_5;
57
58 static HWND subclass_editbox(HWND hwndListview);
59
60 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
61
62 static const struct message create_ownerdrawfixed_parent_seq[] = {
63     { WM_NOTIFYFORMAT, sent },
64     { WM_QUERYUISTATE, sent|optional }, /* Win2K and higher */
65     { WM_MEASUREITEM, sent },
66     { WM_PARENTNOTIFY, sent },
67     { 0 }
68 };
69
70 static const struct message redraw_listview_seq[] = {
71     { WM_PAINT,      sent|id,            0, 0, LISTVIEW_ID },
72     { WM_PAINT,      sent|id,            0, 0, HEADER_ID },
73     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, HEADER_ID },
74     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, HEADER_ID },
75     { WM_NOTIFY,     sent|id|defwinproc, 0, 0, LISTVIEW_ID },
76     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, LISTVIEW_ID },
77     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, LISTVIEW_ID },
78     { 0 }
79 };
80
81 static const struct message listview_icon_spacing_seq[] = {
82     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) },
83     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) },
84     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) },
85     { 0 }
86 };
87
88 static const struct message listview_color_seq[] = {
89     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(0,0,0) },
90     { LVM_GETBKCOLOR,     sent },
91     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(0,0,0) },
92     { LVM_GETTEXTCOLOR,   sent },
93     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
94     { LVM_GETTEXTBKCOLOR, sent },
95
96     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(100,50,200) },
97     { LVM_GETBKCOLOR,     sent },
98     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(100,50,200) },
99     { LVM_GETTEXTCOLOR,   sent },
100     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
101     { LVM_GETTEXTBKCOLOR, sent },
102
103     { LVM_SETBKCOLOR,     sent|lparam, 0, CLR_NONE },
104     { LVM_GETBKCOLOR,     sent },
105     { LVM_SETTEXTCOLOR,   sent|lparam, 0, CLR_NONE },
106     { LVM_GETTEXTCOLOR,   sent },
107     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
108     { LVM_GETTEXTBKCOLOR, sent },
109
110     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(255,255,255) },
111     { LVM_GETBKCOLOR,     sent },
112     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(255,255,255) },
113     { LVM_GETTEXTCOLOR,   sent },
114     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
115     { LVM_GETTEXTBKCOLOR, sent },
116     { 0 }
117 };
118
119 static const struct message listview_item_count_seq[] = {
120     { LVM_GETITEMCOUNT,   sent },
121     { LVM_INSERTITEM,     sent },
122     { LVM_INSERTITEM,     sent },
123     { LVM_INSERTITEM,     sent },
124     { LVM_GETITEMCOUNT,   sent },
125     { LVM_DELETEITEM,     sent|wparam, 2 },
126     { WM_NCPAINT,         sent|optional },
127     { WM_ERASEBKGND,      sent|optional },
128     { LVM_GETITEMCOUNT,   sent },
129     { LVM_DELETEALLITEMS, sent },
130     { LVM_GETITEMCOUNT,   sent },
131     { LVM_INSERTITEM,     sent },
132     { LVM_INSERTITEM,     sent },
133     { LVM_GETITEMCOUNT,   sent },
134     { LVM_INSERTITEM,     sent },
135     { LVM_GETITEMCOUNT,   sent },
136     { 0 }
137 };
138
139 static const struct message listview_itempos_seq[] = {
140     { LVM_INSERTITEM,      sent },
141     { LVM_INSERTITEM,      sent },
142     { LVM_INSERTITEM,      sent },
143     { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
144     { WM_NCPAINT,          sent|optional },
145     { WM_ERASEBKGND,       sent|optional },
146     { LVM_GETITEMPOSITION, sent|wparam,        1 },
147     { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
148     { LVM_GETITEMPOSITION, sent|wparam,        2 },
149     { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
150     { LVM_GETITEMPOSITION, sent|wparam,        0 },
151     { 0 }
152 };
153
154 static const struct message listview_ownerdata_switchto_seq[] = {
155     { WM_STYLECHANGING,    sent },
156     { WM_STYLECHANGED,     sent },
157     { 0 }
158 };
159
160 static const struct message listview_getorderarray_seq[] = {
161     { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
162     { HDM_GETORDERARRAY,       sent|id|wparam, 2, 0, HEADER_ID },
163     { 0 }
164 };
165
166 static const struct message empty_seq[] = {
167     { 0 }
168 };
169
170 static const struct message forward_erasebkgnd_parent_seq[] = {
171     { WM_ERASEBKGND, sent },
172     { 0 }
173 };
174
175 static const struct message ownderdata_select_focus_parent_seq[] = {
176     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
177     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
178     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, /* version 4.7x */
179     { 0 }
180 };
181
182 static const struct message ownerdata_setstate_all_parent_seq[] = {
183     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
184     { 0 }
185 };
186
187 static const struct message ownerdata_defocus_all_parent_seq[] = {
188     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
189     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
190     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA },
191     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
192     { 0 }
193 };
194
195 static const struct message ownerdata_deselect_all_parent_seq[] = {
196     { WM_NOTIFY, sent|id, 0, 0, LVN_ODCACHEHINT },
197     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
198     { 0 }
199 };
200
201 static const struct message select_all_parent_seq[] = {
202     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
203     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
204
205     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
206     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
207
208     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
209     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
210
211     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
212     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
213
214     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
215     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
216     { 0 }
217 };
218
219 static const struct message textcallback_set_again_parent_seq[] = {
220     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
221     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED  },
222     { 0 }
223 };
224
225 static const struct message single_getdispinfo_parent_seq[] = {
226     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
227     { 0 }
228 };
229
230 static const struct message getitemposition_seq1[] = {
231     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
232     { 0 }
233 };
234
235 static const struct message getitemposition_seq2[] = {
236     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
237     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
238     { 0 }
239 };
240
241 static const struct message editbox_create_pos[] = {
242     /* sequence sent after LVN_BEGINLABELEDIT */
243     /* next two are 4.7x specific */
244     { WM_WINDOWPOSCHANGING, sent },
245     { WM_WINDOWPOSCHANGED, sent|optional },
246
247     { WM_WINDOWPOSCHANGING, sent|optional },
248     { WM_NCCALCSIZE, sent },
249     { WM_WINDOWPOSCHANGED, sent },
250     { WM_MOVE, sent|defwinproc },
251     { WM_SIZE, sent|defwinproc },
252     /* the rest is todo, skipped in 4.7x */
253     { WM_WINDOWPOSCHANGING, sent|optional },
254     { WM_WINDOWPOSCHANGED, sent|optional },
255     { 0 }
256 };
257
258 static const struct message scroll_parent_seq[] = {
259     { WM_NOTIFY, sent|id, 0, 0, LVN_BEGINSCROLL },
260     { WM_NOTIFY, sent|id, 0, 0, LVN_ENDSCROLL },
261     { 0 }
262 };
263
264 static const struct message setredraw_seq[] = {
265     { WM_SETREDRAW, sent|id|wparam, FALSE, 0, LISTVIEW_ID },
266     { 0 }
267 };
268
269 static const struct message lvs_ex_transparentbkgnd_seq[] = {
270     { WM_PRINTCLIENT, sent|lparam, 0, PRF_ERASEBKGND },
271     { 0 }
272 };
273
274 static const struct message edit_end_nochange[] = {
275     { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA },
276     { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW },     /* todo */
277     { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS },
278     { 0 }
279 };
280
281 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
282 {
283     static LONG defwndproc_counter = 0;
284     LRESULT ret;
285     struct message msg;
286
287     msg.message = message;
288     msg.flags = sent|wparam|lparam;
289     if (defwndproc_counter) msg.flags |= defwinproc;
290     msg.wParam = wParam;
291     msg.lParam = lParam;
292     if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
293
294     /* log system messages, except for painting */
295     if (message < WM_USER &&
296         message != WM_PAINT &&
297         message != WM_ERASEBKGND &&
298         message != WM_NCPAINT &&
299         message != WM_NCHITTEST &&
300         message != WM_GETTEXT &&
301         message != WM_GETICON &&
302         message != WM_DEVICECHANGE)
303     {
304         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
305
306         add_message(sequences, PARENT_SEQ_INDEX, &msg);
307     }
308     add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
309
310     switch (message)
311     {
312       case WM_NOTIFY:
313       {
314           switch (((NMHDR*)lParam)->code)
315           {
316           case LVN_BEGINLABELEDIT:
317               /* subclass edit box */
318               if (!blockEdit)
319                   subclass_editbox(((NMHDR*)lParam)->hwndFrom);
320
321               return blockEdit;
322
323           case LVN_ENDLABELEDIT:
324               {
325               /* always accept new item text */
326               NMLVDISPINFO *di = (NMLVDISPINFO*)lParam;
327               trace("LVN_ENDLABELEDIT: text=%s\n", di->item.pszText);
328               return TRUE;
329               }
330           case LVN_BEGINSCROLL:
331           case LVN_ENDSCROLL:
332               {
333               NMLVSCROLL *pScroll = (NMLVSCROLL*)lParam;
334
335               trace("LVN_%sSCROLL: (%d,%d)\n", pScroll->hdr.code == LVN_BEGINSCROLL ?
336                                                "BEGIN" : "END", pScroll->dx, pScroll->dy);
337               }
338               break;
339           case LVN_ITEMCHANGED:
340               if (g_dump_itemchanged)
341               {
342                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
343                   trace("LVN_ITEMCHANGED: item=%d,new=%x,old=%x,changed=%x\n",
344                          nmlv->iItem, nmlv->uNewState, nmlv->uOldState, nmlv->uChanged);
345               }
346               break;
347           }
348           break;
349       }
350       case WM_NOTIFYFORMAT:
351       {
352           /* force to return format */
353           if (lParam == NF_QUERY && notifyFormat != -1) return notifyFormat;
354           break;
355       }
356     }
357
358     defwndproc_counter++;
359     ret = DefWindowProcA(hwnd, message, wParam, lParam);
360     defwndproc_counter--;
361
362     return ret;
363 }
364
365 static BOOL register_parent_wnd_class(BOOL Unicode)
366 {
367     WNDCLASSA clsA;
368     WNDCLASSW clsW;
369
370     if (Unicode)
371     {
372         clsW.style = 0;
373         clsW.lpfnWndProc = parent_wnd_proc;
374         clsW.cbClsExtra = 0;
375         clsW.cbWndExtra = 0;
376         clsW.hInstance = GetModuleHandleW(NULL);
377         clsW.hIcon = 0;
378         clsW.hCursor = LoadCursorA(0, IDC_ARROW);
379         clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
380         clsW.lpszMenuName = NULL;
381         clsW.lpszClassName = testparentclassW;
382     }
383     else
384     {
385         clsA.style = 0;
386         clsA.lpfnWndProc = parent_wnd_proc;
387         clsA.cbClsExtra = 0;
388         clsA.cbWndExtra = 0;
389         clsA.hInstance = GetModuleHandleA(NULL);
390         clsA.hIcon = 0;
391         clsA.hCursor = LoadCursorA(0, IDC_ARROW);
392         clsA.hbrBackground = GetStockObject(WHITE_BRUSH);
393         clsA.lpszMenuName = NULL;
394         clsA.lpszClassName = "Listview test parent class";
395     }
396
397     return Unicode ? RegisterClassW(&clsW) : RegisterClassA(&clsA);
398 }
399
400 static HWND create_parent_window(BOOL Unicode)
401 {
402     static const WCHAR nameW[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W'};
403     HWND hwnd;
404
405     if (!register_parent_wnd_class(Unicode))
406         return NULL;
407
408     blockEdit = FALSE;
409     notifyFormat = -1;
410
411     if (Unicode)
412         hwnd = CreateWindowExW(0, testparentclassW, nameW,
413                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
414                                WS_MAXIMIZEBOX | WS_VISIBLE,
415                                0, 0, 100, 100,
416                                GetDesktopWindow(), NULL, GetModuleHandleW(NULL), NULL);
417     else
418         hwnd = CreateWindowExA(0, "Listview test parent class",
419                                "Listview test parent window",
420                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
421                                WS_MAXIMIZEBOX | WS_VISIBLE,
422                                0, 0, 100, 100,
423                                GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
424     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
425     return hwnd;
426 }
427
428 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
429 {
430     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
431     static LONG defwndproc_counter = 0;
432     LRESULT ret;
433     struct message msg;
434
435     trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
436
437     /* some debug output for style changing */
438     if ((message == WM_STYLECHANGING ||
439          message == WM_STYLECHANGED) && lParam)
440     {
441         STYLESTRUCT *style = (STYLESTRUCT*)lParam;
442         trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
443     }
444
445     msg.message = message;
446     msg.flags = sent|wparam|lparam;
447     if (defwndproc_counter) msg.flags |= defwinproc;
448     msg.wParam = wParam;
449     msg.lParam = lParam;
450     msg.id = LISTVIEW_ID;
451     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
452
453     defwndproc_counter++;
454     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
455     defwndproc_counter--;
456     return ret;
457 }
458
459 static HWND create_listview_control(DWORD style)
460 {
461     WNDPROC oldproc;
462     HWND hwnd;
463     RECT rect;
464
465     GetClientRect(hwndparent, &rect);
466     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
467                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
468                            0, 0, rect.right, rect.bottom,
469                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
470     ok(hwnd != NULL, "gle=%d\n", GetLastError());
471
472     if (!hwnd) return NULL;
473
474     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
475                                         (LONG_PTR)listview_subclass_proc);
476     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
477
478     return hwnd;
479 }
480
481 /* unicode listview window with specified parent */
482 static HWND create_listview_controlW(DWORD style, HWND parent)
483 {
484     WNDPROC oldproc;
485     HWND hwnd;
486     RECT rect;
487     static const WCHAR nameW[] = {'f','o','o',0};
488
489     GetClientRect(parent, &rect);
490     hwnd = CreateWindowExW(0, WC_LISTVIEWW, nameW,
491                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
492                            0, 0, rect.right, rect.bottom,
493                            parent, NULL, GetModuleHandleW(NULL), NULL);
494     ok(hwnd != NULL, "gle=%d\n", GetLastError());
495
496     if (!hwnd) return NULL;
497
498     oldproc = (WNDPROC)SetWindowLongPtrW(hwnd, GWLP_WNDPROC,
499                                         (LONG_PTR)listview_subclass_proc);
500     SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
501
502     return hwnd;
503 }
504
505 static HWND create_custom_listview_control(DWORD style)
506 {
507     WNDPROC oldproc;
508     HWND hwnd;
509     RECT rect;
510
511     GetClientRect(hwndparent, &rect);
512     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
513                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
514                            0, 0, rect.right, rect.bottom,
515                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
516     ok(hwnd != NULL, "gle=%d\n", GetLastError());
517
518     if (!hwnd) return NULL;
519
520     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
521                                          (LONG_PTR)listview_subclass_proc);
522     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
523
524     return hwnd;
525 }
526
527 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
528 {
529     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
530     static LONG defwndproc_counter = 0;
531     LRESULT ret;
532     struct message msg;
533
534     trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
535
536     msg.message = message;
537     msg.flags = sent|wparam|lparam;
538     if (defwndproc_counter) msg.flags |= defwinproc;
539     msg.wParam = wParam;
540     msg.lParam = lParam;
541     msg.id = HEADER_ID;
542     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
543
544     defwndproc_counter++;
545     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
546     defwndproc_counter--;
547     return ret;
548 }
549
550 static HWND subclass_header(HWND hwndListview)
551 {
552     WNDPROC oldproc;
553     HWND hwnd;
554
555     hwnd = ListView_GetHeader(hwndListview);
556     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
557                                          (LONG_PTR)header_subclass_proc);
558     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
559
560     return hwnd;
561 }
562
563 static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
564 {
565     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
566     static LONG defwndproc_counter = 0;
567     LRESULT ret;
568     struct message msg;
569
570     msg.message = message;
571     msg.flags = sent|wparam|lparam;
572     if (defwndproc_counter) msg.flags |= defwinproc;
573     msg.wParam = wParam;
574     msg.lParam = lParam;
575
576     /* all we need is sizing */
577     if (message == WM_WINDOWPOSCHANGING ||
578         message == WM_NCCALCSIZE ||
579         message == WM_WINDOWPOSCHANGED ||
580         message == WM_MOVE ||
581         message == WM_SIZE)
582     {
583         add_message(sequences, EDITBOX_SEQ_INDEX, &msg);
584     }
585
586     defwndproc_counter++;
587     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
588     defwndproc_counter--;
589     return ret;
590 }
591
592 static HWND subclass_editbox(HWND hwndListview)
593 {
594     WNDPROC oldproc;
595     HWND hwnd;
596
597     hwnd = (HWND)SendMessage(hwndListview, LVM_GETEDITCONTROL, 0, 0);
598     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
599                                          (LONG_PTR)editbox_subclass_proc);
600     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
601
602     return hwnd;
603 }
604
605 /* Performs a single LVM_HITTEST test */
606 static void test_lvm_hittest(HWND hwnd, INT x, INT y, INT item, UINT flags, UINT broken_flags,
607                              BOOL todo_item, BOOL todo_flags, int line)
608 {
609     LVHITTESTINFO lpht;
610     DWORD ret;
611
612     lpht.pt.x = x;
613     lpht.pt.y = y;
614     lpht.iSubItem = 10;
615
616     trace("hittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
617     ret = SendMessage(hwnd, LVM_HITTEST, 0, (LPARAM)&lpht);
618
619     if (todo_item)
620     {
621         todo_wine
622         {
623             ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
624             ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
625             ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
626         }
627     }
628     else
629     {
630         ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
631         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
632         ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
633     }
634
635     if (todo_flags)
636     {
637         todo_wine
638             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
639     }
640     else if (broken_flags)
641         ok_(__FILE__, line)(lpht.flags == flags || broken(lpht.flags == broken_flags),
642                             "Expected flags %x, got %x\n", flags, lpht.flags);
643     else
644         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
645 }
646
647 /* Performs a single LVM_SUBITEMHITTEST test */
648 static void test_lvm_subitemhittest(HWND hwnd, INT x, INT y, INT item, INT subitem, UINT flags,
649                                     BOOL todo_item, BOOL todo_subitem, BOOL todo_flags, int line)
650 {
651     LVHITTESTINFO lpht;
652     DWORD ret;
653
654     lpht.pt.x = x;
655     lpht.pt.y = y;
656
657     trace("subhittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
658     ret = SendMessage(hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM)&lpht);
659
660     if (todo_item)
661     {
662         todo_wine
663         {
664             ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
665             ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
666         }
667     }
668     else
669     {
670         ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
671         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
672     }
673
674     if (todo_subitem)
675     {
676         todo_wine
677             ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
678     }
679     else
680         ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
681
682     if (todo_flags)
683     {
684         todo_wine
685             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
686     }
687     else
688         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
689 }
690
691 static void test_images(void)
692 {
693     HWND hwnd;
694     DWORD r;
695     LVITEM item;
696     HIMAGELIST himl;
697     HBITMAP hbmp;
698     RECT r1, r2;
699     static CHAR hello[] = "hello";
700
701     himl = ImageList_Create(40, 40, 0, 4, 4);
702     ok(himl != NULL, "failed to create imagelist\n");
703
704     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
705     ok(hbmp != NULL, "failed to create bitmap\n");
706
707     r = ImageList_Add(himl, hbmp, 0);
708     ok(r == 0, "should be zero\n");
709
710     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED, 
711                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
712     ok(hwnd != NULL, "failed to create listview window\n");
713
714     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
715                     LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE);
716
717     ok(r == 0, "should return zero\n");
718
719     r = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
720     ok(r == 0, "should return zero\n");
721
722     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
723     /* returns dimensions */
724
725     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
726     ok(r == 0, "should be zero items\n");
727
728     item.mask = LVIF_IMAGE | LVIF_TEXT;
729     item.iItem = 0;
730     item.iSubItem = 1;
731     item.iImage = 0;
732     item.pszText = 0;
733     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
734     ok(r == -1, "should fail\n");
735
736     item.iSubItem = 0;
737     item.pszText = hello;
738     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
739     ok(r == 0, "should not fail\n");
740
741     memset(&r1, 0, sizeof r1);
742     r1.left = LVIR_ICON;
743     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
744
745     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
746     ok(r == TRUE, "should not fail\n");
747
748     item.iSubItem = 0;
749     item.pszText = hello;
750     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
751     ok(r == 0, "should not fail\n");
752
753     memset(&r2, 0, sizeof r2);
754     r2.left = LVIR_ICON;
755     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
756
757     ok(!memcmp(&r1, &r2, sizeof r1), "rectangle should be the same\n");
758
759     DestroyWindow(hwnd);
760 }
761
762 static void test_checkboxes(void)
763 {
764     HWND hwnd;
765     LVITEMA item;
766     DWORD r;
767     static CHAR text[]  = "Text",
768                 text2[] = "Text2",
769                 text3[] = "Text3";
770
771     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT, 
772                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
773     ok(hwnd != NULL, "failed to create listview window\n");
774
775     /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
776     item.mask = LVIF_TEXT | LVIF_STATE;
777     item.stateMask = 0xffff;
778     item.state = 0xfccc;
779     item.iItem = 0;
780     item.iSubItem = 0;
781     item.pszText = text;
782     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
783     ok(r == 0, "ret %d\n", r);
784
785     item.iItem = 0;
786     item.mask = LVIF_STATE;
787     item.stateMask = 0xffff;
788     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
789     ok(item.state == 0xfccc, "state %x\n", item.state);
790
791     /* Don't set LVIF_STATE */
792     item.mask = LVIF_TEXT;
793     item.stateMask = 0xffff;
794     item.state = 0xfccc;
795     item.iItem = 1;
796     item.iSubItem = 0;
797     item.pszText = text;
798     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
799     ok(r == 1, "ret %d\n", r);
800
801     item.iItem = 1;
802     item.mask = LVIF_STATE;
803     item.stateMask = 0xffff;
804     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
805     ok(item.state == 0, "state %x\n", item.state);
806
807     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
808     ok(r == 0, "should return zero\n");
809
810     /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
811     item.iItem = 0;
812     item.mask = LVIF_STATE;
813     item.stateMask = 0xffff;
814     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
815     if (item.state != 0x1ccc)
816     {
817         win_skip("LVS_EX_CHECKBOXES style is unavailable. Skipping.\n");
818         DestroyWindow(hwnd);
819         return;
820     }
821
822     /* Now add an item without specifying a state and check that its state goes to 0x1000 */
823     item.iItem = 2;
824     item.mask = LVIF_TEXT;
825     item.state = 0;
826     item.pszText = text2;
827     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
828     ok(r == 2, "ret %d\n", r);
829
830     item.iItem = 2;
831     item.mask = LVIF_STATE;
832     item.stateMask = 0xffff;
833     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
834     ok(item.state == 0x1000, "state %x\n", item.state);
835
836     /* Add a further item this time specifying a state and still its state goes to 0x1000 */
837     item.iItem = 3;
838     item.mask = LVIF_TEXT | LVIF_STATE;
839     item.stateMask = 0xffff;
840     item.state = 0x2aaa;
841     item.pszText = text3;
842     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
843     ok(r == 3, "ret %d\n", r);
844
845     item.iItem = 3;
846     item.mask = LVIF_STATE;
847     item.stateMask = 0xffff;
848     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
849     ok(item.state == 0x1aaa, "state %x\n", item.state);
850
851     /* Set an item's state to checked */
852     item.iItem = 3;
853     item.mask = LVIF_STATE;
854     item.stateMask = 0xf000;
855     item.state = 0x2000;
856     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
857
858     item.iItem = 3;
859     item.mask = LVIF_STATE;
860     item.stateMask = 0xffff;
861     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
862     ok(item.state == 0x2aaa, "state %x\n", item.state);
863
864     /* Check that only the bits we asked for are returned,
865      * and that all the others are set to zero
866      */
867     item.iItem = 3;
868     item.mask = LVIF_STATE;
869     item.stateMask = 0xf000;
870     item.state = 0xffff;
871     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
872     ok(item.state == 0x2000, "state %x\n", item.state);
873
874     /* Set the style again and check that doesn't change an item's state */
875     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
876     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
877
878     item.iItem = 3;
879     item.mask = LVIF_STATE;
880     item.stateMask = 0xffff;
881     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
882     ok(item.state == 0x2aaa, "state %x\n", item.state);
883
884     /* Unsetting the checkbox extended style doesn't change an item's state */
885     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
886     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
887
888     item.iItem = 3;
889     item.mask = LVIF_STATE;
890     item.stateMask = 0xffff;
891     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
892     ok(item.state == 0x2aaa, "state %x\n", item.state);
893
894     /* Now setting the style again will change an item's state */
895     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
896     ok(r == 0, "ret %x\n", r);
897
898     item.iItem = 3;
899     item.mask = LVIF_STATE;
900     item.stateMask = 0xffff;
901     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
902     ok(item.state == 0x1aaa, "state %x\n", item.state);
903
904     /* Toggle checkbox tests (bug 9934) */
905     memset (&item, 0xcc, sizeof(item));
906     item.mask = LVIF_STATE;
907     item.iItem = 3;
908     item.iSubItem = 0;
909     item.state = LVIS_FOCUSED;
910     item.stateMask = LVIS_FOCUSED;
911     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
912     expect(1, r);
913
914     item.iItem = 3;
915     item.mask = LVIF_STATE;
916     item.stateMask = 0xffff;
917     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
918     ok(item.state == 0x1aab, "state %x\n", item.state);
919
920     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
921     expect(0, r);
922     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
923     expect(0, r);
924
925     item.iItem = 3;
926     item.mask = LVIF_STATE;
927     item.stateMask = 0xffff;
928     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
929     ok(item.state == 0x2aab, "state %x\n", item.state);
930
931     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
932     expect(0, r);
933     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
934     expect(0, r);
935
936     item.iItem = 3;
937     item.mask = LVIF_STATE;
938     item.stateMask = 0xffff;
939     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
940     ok(item.state == 0x1aab, "state %x\n", item.state);
941
942     DestroyWindow(hwnd);
943 }
944
945 static void insert_column(HWND hwnd, int idx)
946 {
947     LVCOLUMN column;
948     DWORD rc;
949
950     memset(&column, 0xcc, sizeof(column));
951     column.mask = LVCF_SUBITEM;
952     column.iSubItem = idx;
953
954     rc = ListView_InsertColumn(hwnd, idx, &column);
955     expect(idx, rc);
956 }
957
958 static void insert_item(HWND hwnd, int idx)
959 {
960     static CHAR text[] = "foo";
961
962     LVITEMA item;
963     DWORD rc;
964
965     memset(&item, 0xcc, sizeof (item));
966     item.mask = LVIF_TEXT;
967     item.iItem = idx;
968     item.iSubItem = 0;
969     item.pszText = text;
970
971     rc = ListView_InsertItem(hwnd, &item);
972     expect(idx, rc);
973 }
974
975 static void test_items(void)
976 {
977     const LPARAM lparamTest = 0x42;
978     HWND hwnd;
979     LVITEMA item;
980     DWORD r;
981     static CHAR text[] = "Text";
982
983     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
984                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
985     ok(hwnd != NULL, "failed to create listview window\n");
986
987     /*
988      * Test setting/getting item params
989      */
990
991     /* Set up two columns */
992     insert_column(hwnd, 0);
993     insert_column(hwnd, 1);
994
995     /* LVIS_SELECTED with zero stateMask */
996     /* set */
997     memset (&item, 0, sizeof (item));
998     item.mask = LVIF_STATE;
999     item.state = LVIS_SELECTED;
1000     item.stateMask = 0;
1001     item.iItem = 0;
1002     item.iSubItem = 0;
1003     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1004     ok(r == 0, "ret %d\n", r);
1005     /* get */
1006     memset (&item, 0xcc, sizeof (item));
1007     item.mask = LVIF_STATE;
1008     item.stateMask = LVIS_SELECTED;
1009     item.state = 0;
1010     item.iItem = 0;
1011     item.iSubItem = 0;
1012     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1013     ok(r != 0, "ret %d\n", r);
1014     ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
1015     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1016
1017     /* LVIS_SELECTED with zero stateMask */
1018     /* set */
1019     memset (&item, 0, sizeof (item));
1020     item.mask = LVIF_STATE;
1021     item.state = LVIS_FOCUSED;
1022     item.stateMask = 0;
1023     item.iItem = 0;
1024     item.iSubItem = 0;
1025     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1026     ok(r == 0, "ret %d\n", r);
1027     /* get */
1028     memset (&item, 0xcc, sizeof (item));
1029     item.mask = LVIF_STATE;
1030     item.stateMask = LVIS_FOCUSED;
1031     item.state = 0;
1032     item.iItem = 0;
1033     item.iSubItem = 0;
1034     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1035     ok(r != 0, "ret %d\n", r);
1036     ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
1037     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1038
1039     /* LVIS_CUT with LVIS_FOCUSED stateMask */
1040     /* set */
1041     memset (&item, 0, sizeof (item));
1042     item.mask = LVIF_STATE;
1043     item.state = LVIS_CUT;
1044     item.stateMask = LVIS_FOCUSED;
1045     item.iItem = 0;
1046     item.iSubItem = 0;
1047     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1048     ok(r == 0, "ret %d\n", r);
1049     /* get */
1050     memset (&item, 0xcc, sizeof (item));
1051     item.mask = LVIF_STATE;
1052     item.stateMask = LVIS_CUT;
1053     item.state = 0;
1054     item.iItem = 0;
1055     item.iSubItem = 0;
1056     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1057     ok(r != 0, "ret %d\n", r);
1058     ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
1059     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1060
1061     /* Insert an item with just a param */
1062     memset (&item, 0xcc, sizeof (item));
1063     item.mask = LVIF_PARAM;
1064     item.iItem = 0;
1065     item.iSubItem = 0;
1066     item.lParam = lparamTest;
1067     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1068     ok(r == 0, "ret %d\n", r);
1069
1070     /* Test getting of the param */
1071     memset (&item, 0xcc, sizeof (item));
1072     item.mask = LVIF_PARAM;
1073     item.iItem = 0;
1074     item.iSubItem = 0;
1075     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1076     ok(r != 0, "ret %d\n", r);
1077     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1078
1079     /* Set up a subitem */
1080     memset (&item, 0xcc, sizeof (item));
1081     item.mask = LVIF_TEXT;
1082     item.iItem = 0;
1083     item.iSubItem = 1;
1084     item.pszText = text;
1085     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1086     ok(r != 0, "ret %d\n", r);
1087
1088     /* Query param from subitem: returns main item param */
1089     memset (&item, 0xcc, sizeof (item));
1090     item.mask = LVIF_PARAM;
1091     item.iItem = 0;
1092     item.iSubItem = 1;
1093     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1094     ok(r != 0, "ret %d\n", r);
1095     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1096
1097     /* Set up param on first subitem: no effect */
1098     memset (&item, 0xcc, sizeof (item));
1099     item.mask = LVIF_PARAM;
1100     item.iItem = 0;
1101     item.iSubItem = 1;
1102     item.lParam = lparamTest+1;
1103     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1104     ok(r == 0, "ret %d\n", r);
1105
1106     /* Query param from subitem again: should still return main item param */
1107     memset (&item, 0xcc, sizeof (item));
1108     item.mask = LVIF_PARAM;
1109     item.iItem = 0;
1110     item.iSubItem = 1;
1111     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1112     ok(r != 0, "ret %d\n", r);
1113     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1114
1115     /**** Some tests of state highlighting ****/
1116     memset (&item, 0xcc, sizeof (item));
1117     item.mask = LVIF_STATE;
1118     item.iItem = 0;
1119     item.iSubItem = 0;
1120     item.state = LVIS_SELECTED;
1121     item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
1122     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1123     ok(r != 0, "ret %d\n", r);
1124     item.iSubItem = 1;
1125     item.state = LVIS_DROPHILITED;
1126     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1127     ok(r != 0, "ret %d\n", r);
1128
1129     memset (&item, 0xcc, sizeof (item));
1130     item.mask = LVIF_STATE;
1131     item.iItem = 0;
1132     item.iSubItem = 0;
1133     item.stateMask = -1;
1134     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1135     ok(r != 0, "ret %d\n", r);
1136     ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
1137     item.iSubItem = 1;
1138     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1139     ok(r != 0, "ret %d\n", r);
1140     todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
1141
1142     /* some notnull but meaningless masks */
1143     memset (&item, 0, sizeof(item));
1144     item.mask = LVIF_NORECOMPUTE;
1145     item.iItem = 0;
1146     item.iSubItem = 0;
1147     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1148     ok(r != 0, "ret %d\n", r);
1149     memset (&item, 0, sizeof(item));
1150     item.mask = LVIF_DI_SETITEM;
1151     item.iItem = 0;
1152     item.iSubItem = 0;
1153     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1154     ok(r != 0, "ret %d\n", r);
1155
1156     /* set text to callback value already having it */
1157     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1158     expect(TRUE, r);
1159     memset (&item, 0, sizeof (item));
1160     item.mask  = LVIF_TEXT;
1161     item.pszText = LPSTR_TEXTCALLBACK;
1162     item.iItem = 0;
1163     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1164     ok(r == 0, "ret %d\n", r);
1165     memset (&item, 0, sizeof (item));
1166
1167     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1168
1169     item.pszText = LPSTR_TEXTCALLBACK;
1170     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0 , (LPARAM) &item);
1171     expect(TRUE, r);
1172
1173     ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq,
1174                 "check callback text comparison rule", FALSE);
1175
1176     DestroyWindow(hwnd);
1177 }
1178
1179 static void test_columns(void)
1180 {
1181     HWND hwnd, hwndheader;
1182     LVCOLUMN column;
1183     DWORD rc;
1184     INT order[2];
1185
1186     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
1187                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1188     ok(hwnd != NULL, "failed to create listview window\n");
1189
1190     /* Add a column with no mask */
1191     memset(&column, 0xcc, sizeof(column));
1192     column.mask = 0;
1193     rc = ListView_InsertColumn(hwnd, 0, &column);
1194     ok(rc==0, "Inserting column with no mask failed with %d\n", rc);
1195
1196     /* Check its width */
1197     rc = ListView_GetColumnWidth(hwnd, 0);
1198     ok(rc==10 ||
1199        broken(rc==0), /* win9x */
1200        "Inserting column with no mask failed to set width to 10 with %d\n", rc);
1201
1202     DestroyWindow(hwnd);
1203
1204     /* LVM_GETCOLUMNORDERARRAY */
1205     hwnd = create_listview_control(0);
1206     hwndheader = subclass_header(hwnd);
1207
1208     memset(&column, 0, sizeof(column));
1209     column.mask = LVCF_WIDTH;
1210     column.cx = 100;
1211     rc = ListView_InsertColumn(hwnd, 0, &column);
1212     ok(rc == 0, "Inserting column failed with %d\n", rc);
1213
1214     column.cx = 200;
1215     rc = ListView_InsertColumn(hwnd, 1, &column);
1216     ok(rc == 1, "Inserting column failed with %d\n", rc);
1217
1218     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1219
1220     rc = SendMessage(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
1221     ok(rc != 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
1222     ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
1223     ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
1224
1225     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
1226
1227     DestroyWindow(hwnd);
1228 }
1229 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1230 static WNDPROC listviewWndProc;
1231 static HIMAGELIST test_create_imagelist;
1232
1233 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1234 {
1235     LRESULT ret;
1236
1237     if (uMsg == WM_CREATE)
1238     {
1239         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
1240         lpcs->style |= LVS_REPORT;
1241     }
1242     ret = CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
1243     if (uMsg == WM_CREATE) SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
1244     return ret;
1245 }
1246
1247 static void test_create(void)
1248 {
1249     HWND hList;
1250     HWND hHeader;
1251     LONG_PTR ret;
1252     LONG r;
1253     LVCOLUMNA col;
1254     RECT rect;
1255     WNDCLASSEX cls;
1256     cls.cbSize = sizeof(WNDCLASSEX);
1257     ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
1258     listviewWndProc = cls.lpfnWndProc;
1259     cls.lpfnWndProc = create_test_wndproc;
1260     cls.lpszClassName = "MyListView32";
1261     ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
1262
1263     test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
1264     hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1265     ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
1266     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1267
1268     if (!IsWindow(hHeader))
1269     {
1270         /* version 4.0 */
1271         win_skip("LVM_GETHEADER not implemented. Skipping.\n");
1272         DestroyWindow(hList);
1273         return;
1274     }
1275
1276     ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
1277     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1278     DestroyWindow(hList);
1279
1280     /* header isn't created on LVS_ICON and LVS_LIST styles */
1281     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1282                           GetModuleHandle(NULL), 0);
1283     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1284     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1285     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1286     /* insert column */
1287     memset(&col, 0, sizeof(LVCOLUMNA));
1288     col.mask = LVCF_WIDTH;
1289     col.cx = 100;
1290     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1291     ok(r == 0, "Expected 0 column's inserted\n");
1292     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1293     ok(IsWindow(hHeader), "Header should be created\n");
1294     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1295     DestroyWindow(hList);
1296
1297     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1298                           GetModuleHandle(NULL), 0);
1299     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1300     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1301     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1302     /* insert column */
1303     memset(&col, 0, sizeof(LVCOLUMNA));
1304     col.mask = LVCF_WIDTH;
1305     col.cx = 100;
1306     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1307     ok(r == 0, "Expected 0 column's inserted\n");
1308     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1309     ok(IsWindow(hHeader), "Header should be created\n");
1310     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1311     DestroyWindow(hList);
1312
1313     /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1314     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1315                           GetModuleHandle(NULL), 0);
1316     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLongPtr(hList, GWL_STYLE) | LVS_REPORT);
1317     ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
1318     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1319     ok(IsWindow(hHeader), "Header should be created\n");
1320     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) & ~LVS_REPORT);
1321     ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1322     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1323     ok(IsWindow(hHeader), "Header should be created\n");
1324     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1325     DestroyWindow(hList);
1326
1327     /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1328     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1329                           GetModuleHandle(NULL), 0);
1330     ret = SetWindowLongPtr(hList, GWL_STYLE,
1331                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
1332     ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1333     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1334     ok(IsWindow(hHeader), "Header should be created\n");
1335     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1336     ret = SetWindowLongPtr(hList, GWL_STYLE,
1337                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
1338     ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1339     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1340     ok(IsWindow(hHeader), "Header should be created\n");
1341     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1342     DestroyWindow(hList);
1343
1344     /* LVS_REPORT without WS_VISIBLE */
1345     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1346                           GetModuleHandle(NULL), 0);
1347     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1348     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1349     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1350     /* insert column */
1351     memset(&col, 0, sizeof(LVCOLUMNA));
1352     col.mask = LVCF_WIDTH;
1353     col.cx = 100;
1354     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1355     ok(r == 0, "Expected 0 column's inserted\n");
1356     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1357     ok(IsWindow(hHeader), "Header should be created\n");
1358     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1359     DestroyWindow(hList);
1360
1361     /* LVS_REPORT without WS_VISIBLE, try to show it */
1362     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1363                           GetModuleHandle(NULL), 0);
1364     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1365     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1366     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1367     ShowWindow(hList, SW_SHOW);
1368     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1369     ok(IsWindow(hHeader), "Header should be created\n");
1370     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1371     DestroyWindow(hList);
1372
1373     /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1374     hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1375                           0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1376     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1377     ok(IsWindow(hHeader), "Header should be created\n");
1378     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1379     /* HDS_DRAGDROP set by default */
1380     ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1381     DestroyWindow(hList);
1382
1383     /* setting LVS_EX_HEADERDRAGDROP creates header */
1384     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1385                           GetModuleHandle(NULL), 0);
1386     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1387     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1388     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1389     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1390     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1391     ok(IsWindow(hHeader) ||
1392        broken(!IsWindow(hHeader)), /* 4.7x common controls */
1393        "Header should be created\n");
1394     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1395     DestroyWindow(hList);
1396
1397     /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1398     hList = create_custom_listview_control(0);
1399     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1400     r = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1401     ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1402     DestroyWindow(hList);
1403
1404     /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1405     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1406                           GetModuleHandle(NULL), 0);
1407     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1408     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1409
1410     rect.left = LVIR_BOUNDS;
1411     rect.top  = 1;
1412     rect.right = rect.bottom = -10;
1413     r = SendMessage(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1414     ok(r != 0, "Expected not-null LRESULT\n");
1415
1416     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1417     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1418     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1419
1420     DestroyWindow(hList);
1421
1422     /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1423     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1424     hList = create_listview_control(LVS_OWNERDRAWFIXED);
1425     ok_sequence(sequences, PARENT_SEQ_INDEX, create_ownerdrawfixed_parent_seq,
1426                 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE);
1427     DestroyWindow(hList);
1428 }
1429
1430 static void test_redraw(void)
1431 {
1432     HWND hwnd, hwndheader;
1433     HDC hdc;
1434     BOOL res;
1435     DWORD r;
1436
1437     hwnd = create_listview_control(0);
1438     hwndheader = subclass_header(hwnd);
1439
1440     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1441
1442     trace("invalidate & update\n");
1443     InvalidateRect(hwnd, NULL, TRUE);
1444     UpdateWindow(hwnd);
1445     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1446
1447     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1448
1449     /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1450     /* 1. Without backbuffer */
1451     res = ListView_SetBkColor(hwnd, CLR_NONE);
1452     expect(TRUE, res);
1453
1454     hdc = GetWindowDC(hwndparent);
1455
1456     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1457     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1458     ok(r != 0, "Expected not zero result\n");
1459     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1460                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1461
1462     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1463     expect(TRUE, res);
1464
1465     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1466     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1467     ok(r != 0, "Expected not zero result\n");
1468     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1469                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1470
1471     /* 2. With backbuffer */
1472     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1473                                                      LVS_EX_DOUBLEBUFFER);
1474     res = ListView_SetBkColor(hwnd, CLR_NONE);
1475     expect(TRUE, res);
1476
1477     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1478     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1479     ok(r != 0, "Expected not zero result\n");
1480     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1481                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1482
1483     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1484     expect(TRUE, res);
1485
1486     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1487     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1488     todo_wine ok(r != 0, "Expected not zero result\n");
1489     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1490                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1491
1492     ReleaseDC(hwndparent, hdc);
1493
1494     DestroyWindow(hwnd);
1495 }
1496
1497 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1498 {
1499     COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1500
1501     if(msg == WM_NOTIFY) {
1502         NMHDR *nmhdr = (PVOID)lp;
1503         if(nmhdr->code == NM_CUSTOMDRAW) {
1504             NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
1505             trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
1506             switch(nmlvcd->nmcd.dwDrawStage) {
1507             case CDDS_PREPAINT:
1508                 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1509                 return CDRF_NOTIFYITEMDRAW;
1510             case CDDS_ITEMPREPAINT:
1511                 nmlvcd->clrTextBk = CLR_DEFAULT;
1512                 return CDRF_NOTIFYSUBITEMDRAW;
1513             case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1514                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1515                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1516                 return CDRF_NOTIFYPOSTPAINT;
1517             case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1518                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1519                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1520                 return CDRF_DODEFAULT;
1521             }
1522             return CDRF_DODEFAULT;
1523         }
1524     }
1525
1526     return DefWindowProcA(hwnd, msg, wp, lp);
1527 }
1528
1529 static void test_customdraw(void)
1530 {
1531     HWND hwnd;
1532     WNDPROC oldwndproc;
1533
1534     hwnd = create_listview_control(0);
1535
1536     insert_column(hwnd, 0);
1537     insert_column(hwnd, 1);
1538     insert_item(hwnd, 0);
1539
1540     oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
1541                                            (LONG_PTR)cd_wndproc);
1542
1543     InvalidateRect(hwnd, NULL, TRUE);
1544     UpdateWindow(hwnd);
1545
1546     SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1547
1548     DestroyWindow(hwnd);
1549 }
1550
1551 static void test_icon_spacing(void)
1552 {
1553     /* LVM_SETICONSPACING */
1554     /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1555
1556     HWND hwnd;
1557     WORD w, h;
1558     DWORD r;
1559
1560     hwnd = create_custom_listview_control(LVS_ICON);
1561     ok(hwnd != NULL, "failed to create a listview window\n");
1562
1563     r = SendMessage(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, (LPARAM)NF_REQUERY);
1564     expect(NFR_ANSI, r);
1565
1566     /* reset the icon spacing to defaults */
1567     SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1568
1569     /* now we can request what the defaults are */
1570     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1571     w = LOWORD(r);
1572     h = HIWORD(r);
1573
1574     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1575
1576     trace("test icon spacing\n");
1577
1578     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1579     ok(r == MAKELONG(w, h) ||
1580        broken(r == MAKELONG(w, w)), /* win98 */
1581        "Expected %d, got %d\n", MAKELONG(w, h), r);
1582
1583     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1584     if (r == 0)
1585     {
1586         /* version 4.0 */
1587         win_skip("LVM_SETICONSPACING unimplemented. Skipping.\n");
1588         DestroyWindow(hwnd);
1589         return;
1590     }
1591     expect(MAKELONG(20,30), r);
1592
1593     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1594     expect(MAKELONG(25,35), r);
1595
1596     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1597
1598     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1599     DestroyWindow(hwnd);
1600 }
1601
1602 static void test_color(void)
1603 {
1604     /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1605
1606     HWND hwnd;
1607     DWORD r;
1608     int i;
1609
1610     COLORREF color;
1611     COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1612
1613     hwnd = create_listview_control(0);
1614     ok(hwnd != NULL, "failed to create a listview window\n");
1615
1616     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1617
1618     trace("test color seq\n");
1619     for (i = 0; i < 4; i++)
1620     {
1621         color = colors[i];
1622
1623         r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
1624         expect(TRUE, r);
1625         r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, color);
1626         expect(color, r);
1627
1628         r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
1629         expect (TRUE, r);
1630         r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, color);
1631         expect(color, r);
1632
1633         r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
1634         expect(TRUE, r);
1635         r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, color);
1636         expect(color, r);
1637     }
1638
1639     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
1640
1641     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1642     DestroyWindow(hwnd);
1643 }
1644
1645 static void test_item_count(void)
1646 {
1647     /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1648
1649     HWND hwnd;
1650     DWORD r;
1651     HDC hdc;
1652     HFONT hOldFont;
1653     TEXTMETRICA tm;
1654     RECT rect;
1655     INT height;
1656
1657     LVITEM item0;
1658     LVITEM item1;
1659     LVITEM item2;
1660     static CHAR item0text[] = "item0";
1661     static CHAR item1text[] = "item1";
1662     static CHAR item2text[] = "item2";
1663
1664     hwnd = create_listview_control(0);
1665     ok(hwnd != NULL, "failed to create a listview window\n");
1666
1667     /* resize in dpiaware manner to fit all 3 items added */
1668     hdc = GetDC(0);
1669     hOldFont = SelectObject(hdc, GetStockObject(SYSTEM_FONT));
1670     GetTextMetricsA(hdc, &tm);
1671     /* 2 extra pixels for bounds and header border */
1672     height = tm.tmHeight + 2;
1673     SelectObject(hdc, hOldFont);
1674     ReleaseDC(0, hdc);
1675
1676     GetWindowRect(hwnd, &rect);
1677     /* 3 items + 1 header + 1 to be sure */
1678     MoveWindow(hwnd, 0, 0, rect.right - rect.left, 5 * height, FALSE);
1679
1680     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1681
1682     trace("test item count\n");
1683
1684     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1685     expect(0, r);
1686
1687     /* [item0] */
1688     item0.mask = LVIF_TEXT;
1689     item0.iItem = 0;
1690     item0.iSubItem = 0;
1691     item0.pszText = item0text;
1692     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1693     expect(0, r);
1694
1695     /* [item0, item1] */
1696     item1.mask = LVIF_TEXT;
1697     item1.iItem = 1;
1698     item1.iSubItem = 0;
1699     item1.pszText = item1text;
1700     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1701     expect(1, r);
1702
1703     /* [item0, item1, item2] */
1704     item2.mask = LVIF_TEXT;
1705     item2.iItem = 2;
1706     item2.iSubItem = 0;
1707     item2.pszText = item2text;
1708     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1709     expect(2, r);
1710
1711     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1712     expect(3, r);
1713
1714     /* [item0, item1] */
1715     r = SendMessage(hwnd, LVM_DELETEITEM, 2, 0);
1716     expect(TRUE, r);
1717
1718     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1719     expect(2, r);
1720
1721     /* [] */
1722     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1723     expect(TRUE, r);
1724
1725     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1726     expect(0, r);
1727
1728     /* [item0] */
1729     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1730     expect(0, r);
1731
1732     /* [item0, item1] */
1733     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1734     expect(1, r);
1735
1736     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1737     expect(2, r);
1738
1739     /* [item0, item1, item2] */
1740     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1741     expect(2, r);
1742
1743     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1744     expect(3, r);
1745
1746     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
1747
1748     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1749     DestroyWindow(hwnd);
1750 }
1751
1752 static void test_item_position(void)
1753 {
1754     /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1755
1756     HWND hwnd;
1757     DWORD r;
1758     POINT position;
1759
1760     LVITEM item0;
1761     LVITEM item1;
1762     LVITEM item2;
1763     static CHAR item0text[] = "item0";
1764     static CHAR item1text[] = "item1";
1765     static CHAR item2text[] = "item2";
1766
1767     hwnd = create_custom_listview_control(LVS_ICON);
1768     ok(hwnd != NULL, "failed to create a listview window\n");
1769
1770     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1771
1772     trace("test item position\n");
1773
1774     /* [item0] */
1775     item0.mask = LVIF_TEXT;
1776     item0.iItem = 0;
1777     item0.iSubItem = 0;
1778     item0.pszText = item0text;
1779     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1780     expect(0, r);
1781
1782     /* [item0, item1] */
1783     item1.mask = LVIF_TEXT;
1784     item1.iItem = 1;
1785     item1.iSubItem = 0;
1786     item1.pszText = item1text;
1787     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1788     expect(1, r);
1789
1790     /* [item0, item1, item2] */
1791     item2.mask = LVIF_TEXT;
1792     item2.iItem = 2;
1793     item2.iSubItem = 0;
1794     item2.pszText = item2text;
1795     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1796     expect(2, r);
1797
1798     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
1799     expect(TRUE, r);
1800     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
1801     expect(TRUE, r);
1802     expect2(10, 5, position.x, position.y);
1803
1804     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
1805     expect(TRUE, r);
1806     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
1807     expect(TRUE, r);
1808     expect2(0, 0, position.x, position.y);
1809
1810     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
1811     expect(TRUE, r);
1812     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
1813     expect(TRUE, r);
1814     expect2(20, 20, position.x, position.y);
1815
1816     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
1817
1818     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1819     DestroyWindow(hwnd);
1820 }
1821
1822 static void test_getorigin(void)
1823 {
1824     /* LVM_GETORIGIN */
1825
1826     HWND hwnd;
1827     DWORD r;
1828     POINT position;
1829
1830     position.x = position.y = 0;
1831
1832     hwnd = create_custom_listview_control(LVS_ICON);
1833     ok(hwnd != NULL, "failed to create a listview window\n");
1834     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1835     trace("test get origin results\n");
1836     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1837     expect(TRUE, r);
1838     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1839     DestroyWindow(hwnd);
1840
1841     hwnd = create_custom_listview_control(LVS_SMALLICON);
1842     ok(hwnd != NULL, "failed to create a listview window\n");
1843     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1844     trace("test get origin results\n");
1845     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1846     expect(TRUE, r);
1847     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1848     DestroyWindow(hwnd);
1849
1850     hwnd = create_custom_listview_control(LVS_LIST);
1851     ok(hwnd != NULL, "failed to create a listview window\n");
1852     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1853     trace("test get origin results\n");
1854     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1855     expect(FALSE, r);
1856     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1857     DestroyWindow(hwnd);
1858
1859     hwnd = create_custom_listview_control(LVS_REPORT);
1860     ok(hwnd != NULL, "failed to create a listview window\n");
1861     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1862     trace("test get origin results\n");
1863     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1864     expect(FALSE, r);
1865     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1866     DestroyWindow(hwnd);
1867
1868 }
1869
1870 static void test_multiselect(void)
1871 {
1872     typedef struct t_select_task
1873     {
1874         const char *descr;
1875         int initPos;
1876         int loopVK;
1877         int count;
1878         int result;
1879     } select_task;
1880
1881     HWND hwnd;
1882     DWORD r;
1883     int i,j,item_count,selected_count;
1884     static const int items=5;
1885     BYTE kstate[256];
1886     select_task task;
1887     LONG_PTR style;
1888     LVITEMA item;
1889
1890     static struct t_select_task task_list[] = {
1891         { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
1892         { "using VK_UP", -1, VK_UP, -1, -1 },
1893         { "using VK_END", 0, VK_END, 1, -1 },
1894         { "using VK_HOME", -1, VK_HOME, 1, -1 }
1895     };
1896
1897
1898     hwnd = create_listview_control(0);
1899
1900     for (i=0;i<items;i++) {
1901             insert_item(hwnd, 0);
1902     }
1903
1904     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1905
1906     expect(items,item_count);
1907
1908     for (i=0;i<4;i++) {
1909         task = task_list[i];
1910
1911         /* deselect all items */
1912         ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1913         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1914
1915         /* set initial position */
1916         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
1917         ListView_SetItemState(hwnd,(task.initPos == -1 ? item_count -1 : task.initPos),LVIS_SELECTED ,LVIS_SELECTED);
1918
1919         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1920
1921         ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
1922
1923         /* Set SHIFT key pressed */
1924         GetKeyboardState(kstate);
1925         kstate[VK_SHIFT]=0x80;
1926         SetKeyboardState(kstate);
1927
1928         for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
1929             r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
1930             expect(0,r);
1931             r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
1932             expect(0,r);
1933         }
1934
1935         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1936
1937         ok((task.result == -1 ? item_count : task.result) == selected_count, "Failed multiple selection %s. There should be %d selected items (is %d)\n", task.descr, item_count, selected_count);
1938
1939         /* Set SHIFT key released */
1940         GetKeyboardState(kstate);
1941         kstate[VK_SHIFT]=0x00;
1942         SetKeyboardState(kstate);
1943     }
1944     DestroyWindow(hwnd);
1945
1946     /* make multiple selection, then switch to LVS_SINGLESEL */
1947     hwnd = create_listview_control(0);
1948     for (i=0;i<items;i++) {
1949             insert_item(hwnd, 0);
1950     }
1951     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1952     expect(items,item_count);
1953
1954     /* try with NULL pointer */
1955     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)NULL);
1956     expect(FALSE, r);
1957
1958     /* select all, check notifications */
1959     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1960
1961     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1962
1963     item.stateMask = LVIS_SELECTED;
1964     item.state     = LVIS_SELECTED;
1965     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1966     expect(TRUE, r);
1967
1968     ok_sequence(sequences, PARENT_SEQ_INDEX, select_all_parent_seq,
1969                 "select all notification", FALSE);
1970
1971     /* deselect all items */
1972     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1973     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1974     for (i=0;i<3;i++) {
1975         ListView_SetItemState(hwnd, i, LVIS_SELECTED, LVIS_SELECTED);
1976     }
1977
1978     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1979     expect(3, r);
1980     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1981     expect(-1, r);
1982
1983     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1984     ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
1985     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
1986     /* check that style is accepted */
1987     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1988     ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
1989
1990     for (i=0;i<3;i++) {
1991         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1992         ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1993     }
1994     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1995     expect(3, r);
1996     SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1997     expect(3, r);
1998
1999     /* select one more */
2000     ListView_SetItemState(hwnd, 3, LVIS_SELECTED, LVIS_SELECTED);
2001
2002     for (i=0;i<3;i++) {
2003         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
2004         ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
2005     }
2006     r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
2007     ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
2008
2009     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2010     expect(1, r);
2011     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2012     expect(-1, r);
2013
2014     /* try to select all on LVS_SINGLESEL */
2015     memset(&item, 0, sizeof(item));
2016     item.stateMask = LVIS_SELECTED;
2017     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2018     expect(TRUE, r);
2019     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2020
2021     item.stateMask = LVIS_SELECTED;
2022     item.state     = LVIS_SELECTED;
2023     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2024     expect(FALSE, r);
2025
2026     r = ListView_GetSelectedCount(hwnd);
2027     expect(0, r);
2028     r = ListView_GetSelectionMark(hwnd);
2029     expect(-1, r);
2030
2031     /* try to deselect all on LVS_SINGLESEL */
2032     item.stateMask = LVIS_SELECTED;
2033     item.state     = LVIS_SELECTED;
2034     r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2035     expect(TRUE, r);
2036
2037     item.stateMask = LVIS_SELECTED;
2038     item.state     = 0;
2039     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2040     expect(TRUE, r);
2041     r = ListView_GetSelectedCount(hwnd);
2042     expect(0, r);
2043
2044     DestroyWindow(hwnd);
2045 }
2046
2047 static void test_subitem_rect(void)
2048 {
2049     HWND hwnd;
2050     DWORD r;
2051     LVCOLUMN col;
2052     RECT rect;
2053
2054     /* test LVM_GETSUBITEMRECT for header */
2055     hwnd = create_listview_control(0);
2056     ok(hwnd != NULL, "failed to create a listview window\n");
2057     /* add some columns */
2058     memset(&col, 0, sizeof(LVCOLUMN));
2059     col.mask = LVCF_WIDTH;
2060     col.cx = 100;
2061     r = -1;
2062     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
2063     expect(0, r);
2064     col.cx = 150;
2065     r = -1;
2066     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
2067     expect(1, r);
2068     col.cx = 200;
2069     r = -1;
2070     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
2071     expect(2, r);
2072     /* item = -1 means header, subitem index is 1 based */
2073     rect.left = LVIR_BOUNDS;
2074     rect.top  = 0;
2075     rect.right = rect.bottom = 0;
2076     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2077     expect(0, r);
2078
2079     rect.left = LVIR_BOUNDS;
2080     rect.top  = 1;
2081     rect.right = rect.bottom = 0;
2082     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2083
2084     ok(r != 0, "Expected not-null LRESULT\n");
2085     expect(100, rect.left);
2086     expect(250, rect.right);
2087 todo_wine
2088     expect(3, rect.top);
2089
2090     rect.left = LVIR_BOUNDS;
2091     rect.top  = 2;
2092     rect.right = rect.bottom = 0;
2093     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2094
2095     ok(r != 0, "Expected not-null LRESULT\n");
2096     expect(250, rect.left);
2097     expect(450, rect.right);
2098 todo_wine
2099     expect(3, rect.top);
2100
2101     /* item LVS_REPORT padding isn't applied to subitems */
2102     insert_item(hwnd, 0);
2103
2104     rect.left = LVIR_BOUNDS;
2105     rect.top  = 1;
2106     rect.right = rect.bottom = 0;
2107     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2108     ok(r != 0, "Expected not-null LRESULT\n");
2109     expect(100, rect.left);
2110     expect(250, rect.right);
2111
2112     rect.left = LVIR_ICON;
2113     rect.top  = 1;
2114     rect.right = rect.bottom = 0;
2115     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2116     ok(r != 0, "Expected not-null LRESULT\n");
2117     /* no icon attached - zero width rectangle, with no left padding */
2118     expect(100, rect.left);
2119     expect(100, rect.right);
2120
2121     rect.left = LVIR_LABEL;
2122     rect.top  = 1;
2123     rect.right = rect.bottom = 0;
2124     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2125     ok(r != 0, "Expected not-null LRESULT\n");
2126     /* same as full LVIR_BOUNDS */
2127     expect(100, rect.left);
2128     expect(250, rect.right);
2129
2130     DestroyWindow(hwnd);
2131
2132     /* try it for non LVS_REPORT style */
2133     hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
2134                          GetModuleHandle(NULL), 0);
2135     rect.left = LVIR_BOUNDS;
2136     rect.top  = 1;
2137     rect.right = rect.bottom = -10;
2138     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2139     ok(r == 0, "Expected not-null LRESULT\n");
2140     /* rect is unchanged */
2141     expect(0, rect.left);
2142     expect(-10, rect.right);
2143     expect(1, rect.top);
2144     expect(-10, rect.bottom);
2145     DestroyWindow(hwnd);
2146 }
2147
2148 /* comparison callback for test_sorting */
2149 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
2150 {
2151     if (first == second) return 0;
2152     return (first > second ? 1 : -1);
2153 }
2154
2155 static void test_sorting(void)
2156 {
2157     HWND hwnd;
2158     LVITEMA item = {0};
2159     DWORD r;
2160     LONG_PTR style;
2161     static CHAR names[][5] = {"A", "B", "C", "D", "0"};
2162     CHAR buff[10];
2163
2164     hwnd = create_listview_control(0);
2165     ok(hwnd != NULL, "failed to create a listview window\n");
2166
2167     /* insert some items */
2168     item.mask = LVIF_PARAM | LVIF_STATE;
2169     item.state = LVIS_SELECTED;
2170     item.iItem = 0;
2171     item.iSubItem = 0;
2172     item.lParam = 3;
2173     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2174     expect(0, r);
2175
2176     item.mask = LVIF_PARAM;
2177     item.iItem = 1;
2178     item.iSubItem = 0;
2179     item.lParam = 2;
2180     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2181     expect(1, r);
2182
2183     item.mask = LVIF_STATE | LVIF_PARAM;
2184     item.state = LVIS_SELECTED;
2185     item.iItem = 2;
2186     item.iSubItem = 0;
2187     item.lParam = 4;
2188     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2189     expect(2, r);
2190
2191     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2192     expect(-1, r);
2193
2194     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2195     expect(2, r);
2196
2197     r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
2198     expect(TRUE, r);
2199
2200     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2201     expect(2, r);
2202     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2203     expect(-1, r);
2204     r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
2205     expect(0, r);
2206     r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
2207     expect(LVIS_SELECTED, r);
2208     r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
2209     expect(LVIS_SELECTED, r);
2210
2211     DestroyWindow(hwnd);
2212
2213     /* switch to LVS_SORTASCENDING when some items added */
2214     hwnd = create_listview_control(0);
2215     ok(hwnd != NULL, "failed to create a listview window\n");
2216
2217     item.mask = LVIF_TEXT;
2218     item.iItem = 0;
2219     item.iSubItem = 0;
2220     item.pszText = names[1];
2221     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2222     expect(0, r);
2223
2224     item.mask = LVIF_TEXT;
2225     item.iItem = 1;
2226     item.iSubItem = 0;
2227     item.pszText = names[2];
2228     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2229     expect(1, r);
2230
2231     item.mask = LVIF_TEXT;
2232     item.iItem = 2;
2233     item.iSubItem = 0;
2234     item.pszText = names[0];
2235     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2236     expect(2, r);
2237
2238     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2239     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2240     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2241     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2242
2243     /* no sorting performed when switched to LVS_SORTASCENDING */
2244     item.mask = LVIF_TEXT;
2245     item.iItem = 0;
2246     item.pszText = buff;
2247     item.cchTextMax = sizeof(buff);
2248     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2249     expect(TRUE, r);
2250     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2251
2252     item.iItem = 1;
2253     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2254     expect(TRUE, r);
2255     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2256
2257     item.iItem = 2;
2258     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2259     expect(TRUE, r);
2260     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2261
2262     /* adding new item doesn't resort list */
2263     item.mask = LVIF_TEXT;
2264     item.iItem = 3;
2265     item.iSubItem = 0;
2266     item.pszText = names[3];
2267     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2268     expect(3, r);
2269
2270     item.mask = LVIF_TEXT;
2271     item.iItem = 0;
2272     item.pszText = buff;
2273     item.cchTextMax = sizeof(buff);
2274     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2275     expect(TRUE, r);
2276     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2277
2278     item.iItem = 1;
2279     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2280     expect(TRUE, r);
2281     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2282
2283     item.iItem = 2;
2284     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2285     expect(TRUE, r);
2286     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2287
2288     item.iItem = 3;
2289     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2290     expect(TRUE, r);
2291     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2292
2293     /* corner case - item should be placed at first position */
2294     item.mask = LVIF_TEXT;
2295     item.iItem = 4;
2296     item.iSubItem = 0;
2297     item.pszText = names[4];
2298     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2299     expect(0, r);
2300
2301     item.iItem = 0;
2302     item.pszText = buff;
2303     item.cchTextMax = sizeof(buff);
2304     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2305     expect(TRUE, r);
2306     ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
2307
2308     item.iItem = 1;
2309     item.pszText = buff;
2310     item.cchTextMax = sizeof(buff);
2311     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2312     expect(TRUE, r);
2313     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2314
2315     item.iItem = 2;
2316     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2317     expect(TRUE, r);
2318     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2319
2320     item.iItem = 3;
2321     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2322     expect(TRUE, r);
2323     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2324
2325     item.iItem = 4;
2326     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2327     expect(TRUE, r);
2328     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2329
2330     DestroyWindow(hwnd);
2331 }
2332
2333 static void test_ownerdata(void)
2334 {
2335     HWND hwnd;
2336     LONG_PTR style, ret;
2337     DWORD res;
2338     LVITEMA item;
2339
2340     /* it isn't possible to set LVS_OWNERDATA after creation */
2341     if (g_is_below_5)
2342     {
2343         win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2344     }
2345     else
2346     {
2347         hwnd = create_listview_control(0);
2348         ok(hwnd != NULL, "failed to create a listview window\n");
2349         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2350         ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
2351
2352         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2353
2354         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2355         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2356         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2357                 "try to switch to LVS_OWNERDATA seq", FALSE);
2358
2359         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2360         ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
2361         DestroyWindow(hwnd);
2362     }
2363
2364     /* try to set LVS_OWNERDATA after creation just having it */
2365     hwnd = create_listview_control(LVS_OWNERDATA);
2366     ok(hwnd != NULL, "failed to create a listview window\n");
2367     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2368     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2369
2370     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2371
2372     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2373     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2374     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2375                 "try to switch to LVS_OWNERDATA seq", FALSE);
2376     DestroyWindow(hwnd);
2377
2378     /* try to remove LVS_OWNERDATA after creation just having it */
2379     if (g_is_below_5)
2380     {
2381         win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2382     }
2383     else
2384     {
2385         hwnd = create_listview_control(LVS_OWNERDATA);
2386         ok(hwnd != NULL, "failed to create a listview window\n");
2387         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2388         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2389
2390         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2391
2392         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
2393         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2394         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2395                 "try to switch to LVS_OWNERDATA seq", FALSE);
2396         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2397         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2398         DestroyWindow(hwnd);
2399     }
2400
2401     /* try select an item */
2402     hwnd = create_listview_control(LVS_OWNERDATA);
2403     ok(hwnd != NULL, "failed to create a listview window\n");
2404     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2405     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2406     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2407     expect(0, res);
2408     memset(&item, 0, sizeof(item));
2409     item.stateMask = LVIS_SELECTED;
2410     item.state     = LVIS_SELECTED;
2411     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2412     expect(TRUE, res);
2413     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2414     expect(1, res);
2415     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2416     expect(1, res);
2417     DestroyWindow(hwnd);
2418
2419     /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2420     hwnd = create_listview_control(LVS_OWNERDATA);
2421     ok(hwnd != NULL, "failed to create a listview window\n");
2422     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2423     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2424     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2425     expect(1, res);
2426     memset(&item, 0, sizeof(item));
2427     item.mask = LVIF_STATE;
2428     item.iItem = 0;
2429     item.stateMask = LVIS_SELECTED;
2430     item.state     = LVIS_SELECTED;
2431     res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2432     expect(FALSE, res);
2433     DestroyWindow(hwnd);
2434
2435     /* check notifications after focused/selected changed */
2436     hwnd = create_listview_control(LVS_OWNERDATA);
2437     ok(hwnd != NULL, "failed to create a listview window\n");
2438     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 20, 0);
2439     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2440
2441     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2442
2443     memset(&item, 0, sizeof(item));
2444     item.stateMask = LVIS_SELECTED;
2445     item.state     = LVIS_SELECTED;
2446     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2447     expect(TRUE, res);
2448
2449     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2450                 "ownerdata select notification", TRUE);
2451
2452     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2453
2454     memset(&item, 0, sizeof(item));
2455     item.stateMask = LVIS_FOCUSED;
2456     item.state     = LVIS_FOCUSED;
2457     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2458     expect(TRUE, res);
2459
2460     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2461                 "ownerdata focus notification", TRUE);
2462
2463     /* select all, check notifications */
2464     item.stateMask = LVIS_SELECTED;
2465     item.state     = 0;
2466     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2467     expect(TRUE, res);
2468
2469     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2470
2471     item.stateMask = LVIS_SELECTED;
2472     item.state     = LVIS_SELECTED;
2473
2474     g_dump_itemchanged = TRUE;
2475     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2476     expect(TRUE, res);
2477     g_dump_itemchanged = FALSE;
2478
2479     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2480                 "ownerdata select all notification", TRUE);
2481
2482     /* select all again, note that all items are selected already */
2483     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2484     item.stateMask = LVIS_SELECTED;
2485     item.state     = LVIS_SELECTED;
2486     g_dump_itemchanged = TRUE;
2487     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2488     expect(TRUE, res);
2489     g_dump_itemchanged = FALSE;
2490     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2491                 "ownerdata select all notification", TRUE);
2492     /* deselect all */
2493     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2494     item.stateMask = LVIS_SELECTED;
2495     item.state     = 0;
2496     g_dump_itemchanged = TRUE;
2497     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2498     expect(TRUE, res);
2499     g_dump_itemchanged = FALSE;
2500     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
2501                 "ownerdata deselect all notification", TRUE);
2502
2503     /* select one, then deselect all */
2504     item.stateMask = LVIS_SELECTED;
2505     item.state     = LVIS_SELECTED;
2506     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2507     expect(TRUE, res);
2508     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2509     item.stateMask = LVIS_SELECTED;
2510     item.state     = 0;
2511     g_dump_itemchanged = TRUE;
2512     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2513     expect(TRUE, res);
2514     g_dump_itemchanged = FALSE;
2515     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
2516                 "ownerdata select all notification", TRUE);
2517
2518     /* remove focused, try to focus all */
2519     item.stateMask = LVIS_FOCUSED;
2520     item.state     = LVIS_FOCUSED;
2521     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2522     expect(TRUE, res);
2523     item.stateMask = LVIS_FOCUSED;
2524     item.state     = 0;
2525     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2526     expect(TRUE, res);
2527     item.stateMask = LVIS_FOCUSED;
2528     res = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
2529     expect(0, res);
2530     /* setting all to focused returns failure value */
2531     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2532     item.stateMask = LVIS_FOCUSED;
2533     item.state     = LVIS_FOCUSED;
2534     g_dump_itemchanged = TRUE;
2535     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2536     expect(FALSE, res);
2537     g_dump_itemchanged = FALSE;
2538     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2539                 "ownerdata focus all notification", FALSE);
2540     /* focus single item, remove all */
2541     item.stateMask = LVIS_FOCUSED;
2542     item.state     = LVIS_FOCUSED;
2543     res = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2544     expect(TRUE, res);
2545     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2546     item.stateMask = LVIS_FOCUSED;
2547     item.state     = 0;
2548     g_dump_itemchanged = TRUE;
2549     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2550     expect(TRUE, res);
2551     g_dump_itemchanged = FALSE;
2552     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_defocus_all_parent_seq,
2553                 "ownerdata remove focus all notification", TRUE);
2554     /* set all cut */
2555     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2556     item.stateMask = LVIS_CUT;
2557     item.state     = LVIS_CUT;
2558     g_dump_itemchanged = TRUE;
2559     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2560     expect(TRUE, res);
2561     g_dump_itemchanged = FALSE;
2562     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2563                 "ownerdata cut all notification", TRUE);
2564     /* all marked cut, try again */
2565     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2566     item.stateMask = LVIS_CUT;
2567     item.state     = LVIS_CUT;
2568     g_dump_itemchanged = TRUE;
2569     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2570     expect(TRUE, res);
2571     g_dump_itemchanged = FALSE;
2572     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2573                 "ownerdata cut all notification #2", TRUE);
2574
2575     DestroyWindow(hwnd);
2576
2577     /* check notifications on LVM_GETITEM */
2578     /* zero callback mask */
2579     hwnd = create_listview_control(LVS_OWNERDATA);
2580     ok(hwnd != NULL, "failed to create a listview window\n");
2581     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2582     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2583
2584     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2585
2586     memset(&item, 0, sizeof(item));
2587     item.stateMask = LVIS_SELECTED;
2588     item.mask      = LVIF_STATE;
2589     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2590     expect(TRUE, res);
2591
2592     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2593                 "ownerdata getitem selected state 1", FALSE);
2594
2595     /* non zero callback mask but not we asking for */
2596     res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0);
2597     expect(TRUE, res);
2598
2599     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2600
2601     memset(&item, 0, sizeof(item));
2602     item.stateMask = LVIS_SELECTED;
2603     item.mask      = LVIF_STATE;
2604     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2605     expect(TRUE, res);
2606
2607     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2608                 "ownerdata getitem selected state 2", FALSE);
2609
2610     /* LVIS_OVERLAYMASK callback mask, asking for index */
2611     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2612
2613     memset(&item, 0, sizeof(item));
2614     item.stateMask = LVIS_OVERLAYMASK;
2615     item.mask      = LVIF_STATE;
2616     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2617     expect(TRUE, res);
2618
2619     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
2620                 "ownerdata getitem selected state 2", FALSE);
2621
2622     DestroyWindow(hwnd);
2623
2624     /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
2625     hwnd = create_listview_control(LVS_OWNERDATA | LVS_SORTASCENDING);
2626     ok(hwnd != NULL, "failed to create a listview window\n");
2627     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2628     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2629     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2630     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SORTASCENDING);
2631     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2632     ok(!(style & LVS_SORTASCENDING), "Expected LVS_SORTASCENDING not set\n");
2633     DestroyWindow(hwnd);
2634     /* apparently it's allowed to switch these style on after creation */
2635     hwnd = create_listview_control(LVS_OWNERDATA);
2636     ok(hwnd != NULL, "failed to create a listview window\n");
2637     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2638     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2639     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2640     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2641     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2642     DestroyWindow(hwnd);
2643
2644     hwnd = create_listview_control(LVS_OWNERDATA);
2645     ok(hwnd != NULL, "failed to create a listview window\n");
2646     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2647     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2648     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTDESCENDING);
2649     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2650     ok(style & LVS_SORTDESCENDING, "Expected LVS_SORTDESCENDING to be set\n");
2651     DestroyWindow(hwnd);
2652 }
2653
2654 static void test_norecompute(void)
2655 {
2656     static CHAR testA[] = "test";
2657     CHAR buff[10];
2658     LVITEMA item;
2659     HWND hwnd;
2660     DWORD res;
2661
2662     /* self containing control */
2663     hwnd = create_listview_control(0);
2664     ok(hwnd != NULL, "failed to create a listview window\n");
2665     memset(&item, 0, sizeof(item));
2666     item.mask = LVIF_TEXT | LVIF_STATE;
2667     item.iItem = 0;
2668     item.stateMask = LVIS_SELECTED;
2669     item.state     = LVIS_SELECTED;
2670     item.pszText   = testA;
2671     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2672     expect(0, res);
2673     /* retrieve with LVIF_NORECOMPUTE */
2674     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2675     item.iItem = 0;
2676     item.pszText    = buff;
2677     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2678     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2679     expect(TRUE, res);
2680     ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
2681
2682     item.mask = LVIF_TEXT;
2683     item.iItem = 1;
2684     item.pszText = LPSTR_TEXTCALLBACK;
2685     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2686     expect(1, res);
2687
2688     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2689     item.iItem = 1;
2690     item.pszText    = buff;
2691     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2692
2693     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2694     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2695     expect(TRUE, res);
2696     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2697        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2698     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
2699
2700     DestroyWindow(hwnd);
2701
2702     /* LVS_OWNERDATA */
2703     hwnd = create_listview_control(LVS_OWNERDATA);
2704     ok(hwnd != NULL, "failed to create a listview window\n");
2705
2706     item.mask = LVIF_STATE;
2707     item.stateMask = LVIS_SELECTED;
2708     item.state     = LVIS_SELECTED;
2709     item.iItem = 0;
2710     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2711     expect(0, res);
2712
2713     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2714     item.iItem = 0;
2715     item.pszText    = buff;
2716     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2717     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2718     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2719     expect(TRUE, res);
2720     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2721        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2722     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
2723
2724     DestroyWindow(hwnd);
2725 }
2726
2727 static void test_nosortheader(void)
2728 {
2729     HWND hwnd, header;
2730     LONG_PTR style;
2731
2732     hwnd = create_listview_control(0);
2733     ok(hwnd != NULL, "failed to create a listview window\n");
2734
2735     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2736     ok(IsWindow(header), "header expected\n");
2737
2738     style = GetWindowLongPtr(header, GWL_STYLE);
2739     ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
2740
2741     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2742     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
2743     /* HDS_BUTTONS retained */
2744     style = GetWindowLongPtr(header, GWL_STYLE);
2745     ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
2746
2747     DestroyWindow(hwnd);
2748
2749     /* create with LVS_NOSORTHEADER */
2750     hwnd = create_listview_control(LVS_NOSORTHEADER);
2751     ok(hwnd != NULL, "failed to create a listview window\n");
2752
2753     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2754     ok(IsWindow(header), "header expected\n");
2755
2756     style = GetWindowLongPtr(header, GWL_STYLE);
2757     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2758
2759     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2760     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
2761     /* not changed here */
2762     style = GetWindowLongPtr(header, GWL_STYLE);
2763     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2764
2765     DestroyWindow(hwnd);
2766 }
2767
2768 static void test_setredraw(void)
2769 {
2770     HWND hwnd;
2771     DWORD_PTR style;
2772     DWORD ret;
2773     HDC hdc;
2774     RECT rect;
2775
2776     hwnd = create_listview_control(LVS_OWNERDATA);
2777     ok(hwnd != NULL, "failed to create a listview window\n");
2778
2779     /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
2780        ListView seems to handle it internally without DefWinProc */
2781
2782     /* default value first */
2783     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2784     expect(0, ret);
2785     /* disable */
2786     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2787     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2788     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2789     expect(0, ret);
2790     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2791     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2792     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2793     expect(0, ret);
2794
2795     /* check update rect after redrawing */
2796     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2797     expect(0, ret);
2798     InvalidateRect(hwnd, NULL, FALSE);
2799     RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW);
2800     rect.right = rect.bottom = 1;
2801     GetUpdateRect(hwnd, &rect, FALSE);
2802     expect(0, rect.right);
2803     expect(0, rect.bottom);
2804
2805     /* WM_ERASEBKGND */
2806     hdc = GetWindowDC(hwndparent);
2807     ret = SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
2808     expect(TRUE, ret);
2809     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2810     expect(0, ret);
2811     ret = SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
2812     expect(TRUE, ret);
2813     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2814     expect(0, ret);
2815     ReleaseDC(hwndparent, hdc);
2816
2817     /* check notification messages to show that repainting is disabled */
2818     ret = SendMessage(hwnd, LVM_SETITEMCOUNT, 1, 0);
2819     expect(TRUE, ret);
2820     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2821     expect(0, ret);
2822     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2823
2824     InvalidateRect(hwnd, NULL, TRUE);
2825     UpdateWindow(hwnd);
2826     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2827                 "redraw after WM_SETREDRAW (FALSE)", FALSE);
2828
2829     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE);
2830     expect(TRUE, ret);
2831     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2832     InvalidateRect(hwnd, NULL, TRUE);
2833     UpdateWindow(hwnd);
2834     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2835                 "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE);
2836
2837     /* message isn't forwarded to header */
2838     subclass_header(hwnd);
2839     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2840     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2841     expect(0, ret);
2842     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, setredraw_seq,
2843                 "WM_SETREDRAW: not forwarded to header", FALSE);
2844
2845     DestroyWindow(hwnd);
2846 }
2847
2848 static void test_hittest(void)
2849 {
2850     HWND hwnd;
2851     DWORD r;
2852     RECT bounds;
2853     LVITEMA item;
2854     static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST";
2855     POINT pos;
2856     INT x, y;
2857     HIMAGELIST himl, himl2;
2858     HBITMAP hbmp;
2859
2860     hwnd = create_listview_control(0);
2861     ok(hwnd != NULL, "failed to create a listview window\n");
2862
2863     /* LVS_REPORT with a single subitem (2 columns) */
2864     insert_column(hwnd, 0);
2865     insert_column(hwnd, 1);
2866     insert_item(hwnd, 0);
2867
2868     item.iSubItem = 0;
2869     /* the only purpose of that line is to be as long as a half item rect */
2870     item.pszText  = text;
2871     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&item);
2872     expect(TRUE, r);
2873
2874     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
2875     expect(TRUE, r);
2876     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
2877     expect(TRUE, r);
2878
2879     memset(&bounds, 0, sizeof(bounds));
2880     bounds.left = LVIR_BOUNDS;
2881     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds);
2882     ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n");
2883     ok(bounds.right - bounds.left > 0, "Expected non zero item width\n");
2884     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos);
2885     expect(TRUE, r);
2886
2887     /* LVS_EX_FULLROWSELECT not set, no icons attached */
2888     x = pos.x + 50; /* column half width */
2889     y = pos.y + (bounds.bottom - bounds.top) / 2;
2890     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, 0, FALSE, FALSE, __LINE__);
2891     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2892     x = pos.x + 150; /* outside column */
2893     y = pos.y + (bounds.bottom - bounds.top) / 2;
2894     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2895     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2896     y = (bounds.bottom - bounds.top) / 2;
2897     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2898     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2899     /* outside possible client rectangle (to right) */
2900     x = pos.x + 500;
2901     y = pos.y + (bounds.bottom - bounds.top) / 2;
2902     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2903     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2904     y = (bounds.bottom - bounds.top) / 2;
2905     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2906     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2907     /* subitem returned with -1 item too */
2908     x = pos.x + 150;
2909     y = -10;
2910     test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2911     /* parent client area is 100x100 by default */
2912     MoveWindow(hwnd, 0, 0, 300, 100, FALSE);
2913     x = pos.x + 150; /* outside column */
2914     y = pos.y + (bounds.bottom - bounds.top) / 2;
2915     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, FALSE, __LINE__);
2916     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2917     y = (bounds.bottom - bounds.top) / 2;
2918     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, TRUE, __LINE__);
2919     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2920     /* the same with LVS_EX_FULLROWSELECT */
2921     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
2922     x = pos.x + 150; /* outside column */
2923     y = pos.y + (bounds.bottom - bounds.top) / 2;
2924     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, LVHT_ONITEMLABEL, FALSE, FALSE, __LINE__);
2925     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2926     y = (bounds.bottom - bounds.top) / 2;
2927     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2928     MoveWindow(hwnd, 0, 0, 100, 100, FALSE);
2929     x = pos.x + 150; /* outside column */
2930     y = pos.y + (bounds.bottom - bounds.top) / 2;
2931     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2932     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2933     y = (bounds.bottom - bounds.top) / 2;
2934     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2935     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2936     /* outside possible client rectangle (to right) */
2937     x = pos.x + 500;
2938     y = pos.y + (bounds.bottom - bounds.top) / 2;
2939     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2940     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2941     y = (bounds.bottom - bounds.top) / 2;
2942     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2943     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2944     /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
2945     himl = ImageList_Create(16, 16, 0, 4, 4);
2946     ok(himl != NULL, "failed to create imagelist\n");
2947     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2948     ok(hbmp != NULL, "failed to create bitmap\n");
2949     r = ImageList_Add(himl, hbmp, 0);
2950     ok(r == 0, "should be zero\n");
2951     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2952     ok(hbmp != NULL, "failed to create bitmap\n");
2953     r = ImageList_Add(himl, hbmp, 0);
2954     ok(r == 1, "should be one\n");
2955
2956     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
2957     ok(r == 0, "should return zero\n");
2958
2959     item.mask = LVIF_IMAGE;
2960     item.iImage = 0;
2961     item.iItem = 0;
2962     item.iSubItem = 0;
2963     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2964     expect(TRUE, r);
2965     /* on state icon */
2966     x = pos.x + 8;
2967     y = pos.y + (bounds.bottom - bounds.top) / 2;
2968     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE, __LINE__);
2969     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2970     y = (bounds.bottom - bounds.top) / 2;
2971     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2972
2973     /* state icons indices are 1 based, check with valid index */
2974     item.mask = LVIF_STATE;
2975     item.state = INDEXTOSTATEIMAGEMASK(1);
2976     item.stateMask = LVIS_STATEIMAGEMASK;
2977     item.iItem = 0;
2978     item.iSubItem = 0;
2979     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2980     expect(TRUE, r);
2981     /* on state icon */
2982     x = pos.x + 8;
2983     y = pos.y + (bounds.bottom - bounds.top) / 2;
2984     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE, __LINE__);
2985     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2986     y = (bounds.bottom - bounds.top) / 2;
2987     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2988
2989     himl2 = (HIMAGELIST)SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
2990     ok(himl2 == himl, "should return handle\n");
2991
2992     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
2993     ok(r == 0, "should return zero\n");
2994     /* on item icon */
2995     x = pos.x + 8;
2996     y = pos.y + (bounds.bottom - bounds.top) / 2;
2997     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, 0, FALSE, FALSE, __LINE__);
2998     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
2999     y = (bounds.bottom - bounds.top) / 2;
3000     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
3001
3002     DestroyWindow(hwnd);
3003 }
3004
3005 static void test_getviewrect(void)
3006 {
3007     HWND hwnd;
3008     DWORD r;
3009     RECT rect;
3010     LVITEMA item;
3011
3012     hwnd = create_listview_control(0);
3013     ok(hwnd != NULL, "failed to create a listview window\n");
3014
3015     /* empty */
3016     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3017     expect(TRUE, r);
3018
3019     insert_column(hwnd, 0);
3020     insert_column(hwnd, 1);
3021
3022     memset(&item, 0, sizeof(item));
3023     item.iItem = 0;
3024     item.iSubItem = 0;
3025     SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3026
3027     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3028     expect(TRUE, r);
3029     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0));
3030     expect(TRUE, r);
3031
3032     rect.left = rect.right = rect.top = rect.bottom = -1;
3033     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3034     expect(TRUE, r);
3035     /* left is set to (2e31-1) - XP SP2 */
3036     expect(0, rect.right);
3037     expect(0, rect.top);
3038     expect(0, rect.bottom);
3039
3040     /* switch to LVS_ICON */
3041     SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~LVS_REPORT);
3042
3043     rect.left = rect.right = rect.top = rect.bottom = -1;
3044     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3045     expect(TRUE, r);
3046     expect(0, rect.left);
3047     expect(0, rect.top);
3048     /* precise value differs for 2k, XP and Vista */
3049     ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom);
3050     ok(rect.right  > 0, "Expected positive right value, got %d\n", rect.right);
3051
3052     DestroyWindow(hwnd);
3053 }
3054
3055 static void test_getitemposition(void)
3056 {
3057     HWND hwnd, header;
3058     DWORD r;
3059     POINT pt;
3060     RECT rect;
3061
3062     hwnd = create_listview_control(0);
3063     ok(hwnd != NULL, "failed to create a listview window\n");
3064     header = subclass_header(hwnd);
3065
3066     /* LVS_REPORT, single item, no columns added */
3067     insert_item(hwnd, 0);
3068
3069     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3070
3071     pt.x = pt.y = -1;
3072     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3073     expect(TRUE, r);
3074     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE);
3075
3076     /* LVS_REPORT, single item, single column */
3077     insert_column(hwnd, 0);
3078
3079     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3080
3081     pt.x = pt.y = -1;
3082     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3083     expect(TRUE, r);
3084     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE);
3085
3086     memset(&rect, 0, sizeof(rect));
3087     SendMessage(header, HDM_GETITEMRECT, 0, (LPARAM)&rect);
3088     /* some padding? */
3089     expect(2, pt.x);
3090     /* offset by header height */
3091     expect(rect.bottom - rect.top, pt.y);
3092
3093     DestroyWindow(hwnd);
3094 }
3095
3096 static void test_columnscreation(void)
3097 {
3098     HWND hwnd, header;
3099     DWORD r;
3100
3101     hwnd = create_listview_control(0);
3102     ok(hwnd != NULL, "failed to create a listview window\n");
3103
3104     insert_item(hwnd, 0);
3105
3106     /* headers columns aren't created automatically */
3107     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3108     ok(IsWindow(header), "Expected header handle\n");
3109     r = SendMessage(header, HDM_GETITEMCOUNT, 0, 0);
3110     expect(0, r);
3111
3112     DestroyWindow(hwnd);
3113 }
3114
3115 static void test_getitemrect(void)
3116 {
3117     HWND hwnd;
3118     HIMAGELIST himl;
3119     HBITMAP hbm;
3120     RECT rect;
3121     DWORD r;
3122     LVITEMA item;
3123     LVCOLUMNA col;
3124     INT order[2];
3125     POINT pt;
3126
3127     hwnd = create_listview_control(0);
3128     ok(hwnd != NULL, "failed to create a listview window\n");
3129
3130     /* empty item */
3131     memset(&item, 0, sizeof(item));
3132     item.iItem = 0;
3133     item.iSubItem = 0;
3134     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3135     expect(0, r);
3136
3137     rect.left = LVIR_BOUNDS;
3138     rect.right = rect.top = rect.bottom = -1;
3139     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3140     expect(TRUE, r);
3141
3142     /* zero width rectangle with no padding */
3143     expect(0, rect.left);
3144     expect(0, rect.right);
3145
3146     insert_column(hwnd, 0);
3147     insert_column(hwnd, 1);
3148
3149     col.mask = LVCF_WIDTH;
3150     col.cx   = 50;
3151     r = SendMessage(hwnd, LVM_SETCOLUMN, 0, (LPARAM)&col);
3152     expect(TRUE, r);
3153
3154     col.mask = LVCF_WIDTH;
3155     col.cx   = 100;
3156     r = SendMessage(hwnd, LVM_SETCOLUMN, 1, (LPARAM)&col);
3157     expect(TRUE, r);
3158
3159     rect.left = LVIR_BOUNDS;
3160     rect.right = rect.top = rect.bottom = -1;
3161     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3162     expect(TRUE, r);
3163
3164     /* still no left padding */
3165     expect(0, rect.left);
3166     expect(150, rect.right);
3167
3168     rect.left = LVIR_SELECTBOUNDS;
3169     rect.right = rect.top = rect.bottom = -1;
3170     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3171     expect(TRUE, r);
3172     /* padding */
3173     expect(2, rect.left);
3174
3175     rect.left = LVIR_LABEL;
3176     rect.right = rect.top = rect.bottom = -1;
3177     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3178     expect(TRUE, r);
3179     /* padding, column width */
3180     expect(2, rect.left);
3181     expect(50, rect.right);
3182
3183     /* no icons attached */
3184     rect.left = LVIR_ICON;
3185     rect.right = rect.top = rect.bottom = -1;
3186     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3187     expect(TRUE, r);
3188     /* padding */
3189     expect(2, rect.left);
3190     expect(2, rect.right);
3191
3192     /* change order */
3193     order[0] = 1; order[1] = 0;
3194     r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
3195     expect(TRUE, r);
3196     pt.x = -1;
3197     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3198     expect(TRUE, r);
3199     /* 1 indexed column width + padding */
3200     expect(102, pt.x);
3201     /* rect is at zero too */
3202     rect.left = LVIR_BOUNDS;
3203     rect.right = rect.top = rect.bottom = -1;
3204     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3205     expect(TRUE, r);
3206     expect(0, rect.left);
3207     /* just width sum */
3208     expect(150, rect.right);
3209
3210     rect.left = LVIR_SELECTBOUNDS;
3211     rect.right = rect.top = rect.bottom = -1;
3212     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3213     expect(TRUE, r);
3214     /* column width + padding */
3215     expect(102, rect.left);
3216
3217     /* back to initial order */
3218     order[0] = 0; order[1] = 1;
3219     r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
3220     expect(TRUE, r);
3221
3222     /* state icons */
3223     himl = ImageList_Create(16, 16, 0, 2, 2);
3224     ok(himl != NULL, "failed to create imagelist\n");
3225     hbm = CreateBitmap(16, 16, 1, 1, NULL);
3226     ok(hbm != NULL, "failed to create bitmap\n");
3227     r = ImageList_Add(himl, hbm, 0);
3228     ok(r == 0, "should be zero\n");
3229     hbm = CreateBitmap(16, 16, 1, 1, NULL);
3230     ok(hbm != NULL, "failed to create bitmap\n");
3231     r = ImageList_Add(himl, hbm, 0);
3232     ok(r == 1, "should be one\n");
3233
3234     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
3235     ok(r == 0, "should return zero\n");
3236
3237     item.mask = LVIF_STATE;
3238     item.state = INDEXTOSTATEIMAGEMASK(1);
3239     item.stateMask = LVIS_STATEIMAGEMASK;
3240     item.iItem = 0;
3241     item.iSubItem = 0;
3242     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3243     expect(TRUE, r);
3244
3245     /* icon bounds */
3246     rect.left = LVIR_ICON;
3247     rect.right = rect.top = rect.bottom = -1;
3248     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3249     expect(TRUE, r);
3250     /* padding + stateicon width */
3251     expect(18, rect.left);
3252     expect(18, rect.right);
3253     /* label bounds */
3254     rect.left = LVIR_LABEL;
3255     rect.right = rect.top = rect.bottom = -1;
3256     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3257     expect(TRUE, r);
3258     /* padding + stateicon width -> column width */
3259     expect(18, rect.left);
3260     expect(50, rect.right);
3261
3262     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
3263     ok(r != 0, "should return current list handle\n");
3264
3265     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
3266     ok(r == 0, "should return zero\n");
3267
3268     item.mask = LVIF_STATE | LVIF_IMAGE;
3269     item.iImage = 1;
3270     item.state = 0;
3271     item.stateMask = ~0;
3272     item.iItem = 0;
3273     item.iSubItem = 0;
3274     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3275     expect(TRUE, r);
3276
3277     /* icon bounds */
3278     rect.left = LVIR_ICON;
3279     rect.right = rect.top = rect.bottom = -1;
3280     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3281     expect(TRUE, r);
3282     /* padding, icon width */
3283     expect(2, rect.left);
3284     expect(18, rect.right);
3285     /* label bounds */
3286     rect.left = LVIR_LABEL;
3287     rect.right = rect.top = rect.bottom = -1;
3288     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3289     expect(TRUE, r);
3290     /* padding + icon width -> column width */
3291     expect(18, rect.left);
3292     expect(50, rect.right);
3293
3294     /* select bounds */
3295     rect.left = LVIR_SELECTBOUNDS;
3296     rect.right = rect.top = rect.bottom = -1;
3297     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3298     expect(TRUE, r);
3299     /* padding, column width */
3300     expect(2, rect.left);
3301     expect(50, rect.right);
3302
3303     /* try with indentation */
3304     item.mask = LVIF_INDENT;
3305     item.iIndent = 1;
3306     item.iItem = 0;
3307     item.iSubItem = 0;
3308     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3309     expect(TRUE, r);
3310
3311     /* bounds */
3312     rect.left = LVIR_BOUNDS;
3313     rect.right = rect.top = rect.bottom = -1;
3314     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3315     expect(TRUE, r);
3316     /* padding + 1 icon width, column width */
3317     expect(0, rect.left);
3318     expect(150, rect.right);
3319
3320     /* select bounds */
3321     rect.left = LVIR_SELECTBOUNDS;
3322     rect.right = rect.top = rect.bottom = -1;
3323     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3324     expect(TRUE, r);
3325     /* padding + 1 icon width, column width */
3326     expect(2 + 16, rect.left);
3327     expect(50, rect.right);
3328
3329     /* label bounds */
3330     rect.left = LVIR_LABEL;
3331     rect.right = rect.top = rect.bottom = -1;
3332     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3333     expect(TRUE, r);
3334     /* padding + 2 icon widths, column width */
3335     expect(2 + 16*2, rect.left);
3336     expect(50, rect.right);
3337
3338     /* icon bounds */
3339     rect.left = LVIR_ICON;
3340     rect.right = rect.top = rect.bottom = -1;
3341     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3342     expect(TRUE, r);
3343     /* padding + 1 icon width indentation, icon width */
3344     expect(2 + 16, rect.left);
3345     expect(34, rect.right);
3346
3347
3348     DestroyWindow(hwnd);
3349 }
3350
3351 static void test_editbox(void)
3352 {
3353     HWND hwnd, hwndedit, hwndedit2;
3354     LVITEMA item;
3355     DWORD r;
3356     static CHAR testitemA[]  = "testitem";
3357     static CHAR testitem1A[] = "testitem1";
3358     static CHAR buffer[10];
3359
3360     hwnd = create_listview_control(LVS_EDITLABELS);
3361     ok(hwnd != NULL, "failed to create a listview window\n");
3362
3363     insert_column(hwnd, 0);
3364
3365     memset(&item, 0, sizeof(item));
3366     item.mask = LVIF_TEXT;
3367     item.pszText = testitemA;
3368     item.iItem = 0;
3369     item.iSubItem = 0;
3370     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3371     expect(0, r);
3372
3373     /* setting focus is necessary */
3374     SetFocus(hwnd);
3375     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3376     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3377
3378     /* modify initial string */
3379     r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
3380     expect(TRUE, r);
3381     /* return focus to listview */
3382     SetFocus(hwnd);
3383
3384     memset(&item, 0, sizeof(item));
3385     item.mask = LVIF_TEXT;
3386     item.pszText = buffer;
3387     item.cchTextMax = 10;
3388     item.iItem = 0;
3389     item.iSubItem = 0;
3390     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3391     expect(TRUE, r);
3392
3393     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3394
3395     /* send LVM_EDITLABEL on already created edit */
3396     SetFocus(hwnd);
3397     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3398     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3399     /* focus will be set to edit */
3400     ok(GetFocus() == hwndedit, "Expected Edit window to be focused\n");
3401     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3402     ok(IsWindow(hwndedit2), "Expected Edit window to be created\n");
3403
3404     /* creating label disabled when control isn't focused */
3405     SetFocus(0);
3406     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3407     todo_wine ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3408
3409     /* check EN_KILLFOCUS handling */
3410     memset(&item, 0, sizeof(item));
3411     item.pszText = testitemA;
3412     item.iItem = 0;
3413     item.iSubItem = 0;
3414     r = SendMessage(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
3415     expect(TRUE, r);
3416
3417     SetFocus(hwnd);
3418     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3419     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3420     /* modify edit and notify control that it lost focus */
3421     r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
3422     expect(TRUE, r);
3423     r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
3424     expect(0, r);
3425     memset(&item, 0, sizeof(item));
3426     item.pszText = buffer;
3427     item.cchTextMax = 10;
3428     item.iItem = 0;
3429     item.iSubItem = 0;
3430     r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
3431     expect(lstrlen(item.pszText), r);
3432     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3433     ok(!IsWindow(hwndedit), "Expected Edit window to be freed\n");
3434     /* end edit without saving */
3435     SetFocus(hwnd);
3436     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3437     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3438     r = SendMessage(hwndedit, WM_KEYDOWN, VK_ESCAPE, 0);
3439     expect(0, r);
3440     ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
3441                 "edit box - end edit, no change, escape", TRUE);
3442     /* end edit with saving */
3443     SetFocus(hwnd);
3444     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3445     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3446     r = SendMessage(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
3447     expect(0, r);
3448     ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
3449                 "edit box - end edit, no change, return", TRUE);
3450
3451     memset(&item, 0, sizeof(item));
3452     item.pszText = buffer;
3453     item.cchTextMax = 10;
3454     item.iItem = 0;
3455     item.iSubItem = 0;
3456     r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
3457     expect(lstrlen(item.pszText), r);
3458     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3459
3460     /* LVM_EDITLABEL with -1 destroys current edit */
3461     hwndedit = (HWND)SendMessage(hwnd, LVM_GETEDITCONTROL, 0, 0);
3462     ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3463     /* no edit present */
3464     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
3465     ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3466     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3467     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3468     /* edit present */
3469     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3470     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
3471     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3472     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3473     ok(GetFocus() == hwnd, "Expected List to be focused\n");
3474     /* check another negative value */
3475     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3476     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3477     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3478     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -2, 0);
3479     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3480     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3481     ok(GetFocus() == hwnd, "Expected List to be focused\n");
3482     /* and value greater than max item index */
3483     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3484     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3485     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3486     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
3487     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, r, 0);
3488     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3489     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3490     ok(GetFocus() == hwnd, "Expected List to be focused\n");
3491
3492     /* messaging tests */
3493     SetFocus(hwnd);
3494     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3495     blockEdit = FALSE;
3496     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3497     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3498     /* testing only sizing messages */
3499     ok_sequence(sequences, EDITBOX_SEQ_INDEX, editbox_create_pos,
3500                 "edit box create - sizing", FALSE);
3501
3502     /* WM_COMMAND with EN_KILLFOCUS isn't forwared to parent */
3503     SetFocus(hwnd);
3504     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3505     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3506     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3507     r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
3508     expect(0, r);
3509     ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
3510                 "edit box WM_COMMAND (EN_KILLFOCUS)", TRUE);
3511
3512     DestroyWindow(hwnd);
3513 }
3514
3515 static void test_notifyformat(void)
3516 {
3517     HWND hwnd, header;
3518     DWORD r;
3519
3520     hwnd = create_listview_control(0);
3521     ok(hwnd != NULL, "failed to create a listview window\n");
3522
3523     /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
3524        CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
3525     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3526     expect(0, r);
3527     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
3528     /* set */
3529     r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 1, 0);
3530     expect(0, r);
3531     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3532     if (r == 1)
3533     {
3534         r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 0, 0);
3535         expect(1, r);
3536         r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3537         expect(0, r);
3538     }
3539     else
3540     {
3541         win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
3542         DestroyWindow(hwnd);
3543         return;
3544     }
3545
3546     DestroyWindow(hwnd);
3547
3548     /* test failure in parent WM_NOTIFYFORMAT  */
3549     notifyFormat = 0;
3550     hwnd = create_listview_control(0);
3551     ok(hwnd != NULL, "failed to create a listview window\n");
3552     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3553     ok(IsWindow(header), "expected header to be created\n");
3554     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3555     expect(0, r);
3556     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3557     ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
3558     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
3559     ok(r != 0, "Expected valid format\n");
3560
3561     notifyFormat = NFR_UNICODE;
3562     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
3563     expect(NFR_UNICODE, r);
3564     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3565     expect(1, r);
3566     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3567     ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
3568
3569     notifyFormat = NFR_ANSI;
3570     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
3571     expect(NFR_ANSI, r);
3572     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3573     expect(0, r);
3574     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3575     ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
3576
3577     DestroyWindow(hwnd);
3578
3579     /* try different unicode window combination and defaults */
3580     if (!GetModuleHandleW(NULL))
3581     {
3582         win_skip("Additional notify format tests are incompatible with Win9x\n");
3583         return;
3584     }
3585
3586     hwndparentW = create_parent_window(TRUE);
3587     ok(IsWindow(hwndparentW), "Unicode parent creation failed\n");
3588     if (!IsWindow(hwndparentW))  return;
3589
3590     notifyFormat = -1;
3591     hwnd = create_listview_controlW(0, hwndparentW);
3592     ok(hwnd != NULL, "failed to create a listview window\n");
3593     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3594     ok(IsWindow(header), "expected header to be created\n");
3595     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3596     expect(1, r);
3597     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3598     expect(1, r);
3599     DestroyWindow(hwnd);
3600     /* receiving error code defaulting to ansi */
3601     notifyFormat = 0;
3602     hwnd = create_listview_controlW(0, hwndparentW);
3603     ok(hwnd != NULL, "failed to create a listview window\n");
3604     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3605     ok(IsWindow(header), "expected header to be created\n");
3606     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3607     expect(0, r);
3608     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3609     expect(1, r);
3610     DestroyWindow(hwnd);
3611     /* receiving ansi code from unicode window, use it */
3612     notifyFormat = NFR_ANSI;
3613     hwnd = create_listview_controlW(0, hwndparentW);
3614     ok(hwnd != NULL, "failed to create a listview window\n");
3615     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3616     ok(IsWindow(header), "expected header to be created\n");
3617     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3618     expect(0, r);
3619     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3620     expect(1, r);
3621     DestroyWindow(hwnd);
3622     /* unicode listview with ansi parent window */
3623     notifyFormat = -1;
3624     hwnd = create_listview_controlW(0, hwndparent);
3625     ok(hwnd != NULL, "failed to create a listview window\n");
3626     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3627     ok(IsWindow(header), "expected header to be created\n");
3628     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3629     expect(0, r);
3630     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3631     expect(1, r);
3632     DestroyWindow(hwnd);
3633     /* unicode listview with ansi parent window, return error code */
3634     notifyFormat = 0;
3635     hwnd = create_listview_controlW(0, hwndparent);
3636     ok(hwnd != NULL, "failed to create a listview window\n");
3637     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3638     ok(IsWindow(header), "expected header to be created\n");
3639     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3640     expect(0, r);
3641     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3642     expect(1, r);
3643     DestroyWindow(hwnd);
3644
3645     DestroyWindow(hwndparentW);
3646 }
3647
3648 static void test_indentation(void)
3649 {
3650     HWND hwnd;
3651     LVITEMA item;
3652     DWORD r;
3653
3654     hwnd = create_listview_control(0);
3655     ok(hwnd != NULL, "failed to create a listview window\n");
3656
3657     memset(&item, 0, sizeof(item));
3658     item.mask = LVIF_INDENT;
3659     item.iItem = 0;
3660     item.iIndent = I_INDENTCALLBACK;
3661     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3662     expect(0, r);
3663
3664     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3665
3666     item.iItem = 0;
3667     item.mask = LVIF_INDENT;
3668     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
3669     expect(TRUE, r);
3670
3671     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
3672                 "get indent dispinfo", FALSE);
3673
3674     DestroyWindow(hwnd);
3675 }
3676
3677 static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param)
3678 {
3679     return 0;
3680 }
3681
3682 static BOOL is_below_comctl_5(void)
3683 {
3684     HWND hwnd;
3685     BOOL ret;
3686
3687     hwnd = create_listview_control(0);
3688     ok(hwnd != NULL, "failed to create a listview window\n");
3689     insert_item(hwnd, 0);
3690
3691     ret = SendMessage(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx);
3692
3693     DestroyWindow(hwnd);
3694
3695     return !ret;
3696 }
3697
3698 static void test_get_set_view(void)
3699 {
3700     HWND hwnd;
3701     DWORD ret;
3702     DWORD_PTR style;
3703
3704     /* test style->view mapping */
3705     hwnd = create_listview_control(0);
3706     ok(hwnd != NULL, "failed to create a listview window\n");
3707
3708     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3709     expect(LV_VIEW_DETAILS, ret);
3710
3711     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3712     /* LVS_ICON == 0 */
3713     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_REPORT);
3714     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3715     expect(LV_VIEW_ICON, ret);
3716
3717     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3718     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_SMALLICON);
3719     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3720     expect(LV_VIEW_SMALLICON, ret);
3721
3722     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3723     SetWindowLongPtr(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST);
3724     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3725     expect(LV_VIEW_LIST, ret);
3726
3727     /* switching view doesn't touch window style */
3728     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0);
3729     expect(1, ret);
3730     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3731     ok(style & LVS_LIST, "Expected style to be preserved\n");
3732     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0);
3733     expect(1, ret);
3734     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3735     ok(style & LVS_LIST, "Expected style to be preserved\n");
3736     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0);
3737     expect(1, ret);
3738     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3739     ok(style & LVS_LIST, "Expected style to be preserved\n");
3740
3741     DestroyWindow(hwnd);
3742 }
3743
3744 static void test_canceleditlabel(void)
3745 {
3746     HWND hwnd, hwndedit;
3747     DWORD ret;
3748     CHAR buff[10];
3749     LVITEMA itema;
3750     static CHAR test[] = "test";
3751     static const CHAR test1[] = "test1";
3752
3753     hwnd = create_listview_control(LVS_EDITLABELS);
3754     ok(hwnd != NULL, "failed to create a listview window\n");
3755
3756     insert_item(hwnd, 0);
3757
3758     /* try without edit created */
3759     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3760     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3761     expect(TRUE, ret);
3762     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3763                 "cancel edit label without edit", FALSE);
3764
3765     /* cancel without data change */
3766     SetFocus(hwnd);
3767     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3768     ok(IsWindow(hwndedit), "Expected edit control to be created\n");
3769     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3770     expect(TRUE, ret);
3771     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
3772
3773     /* cancel after data change */
3774     memset(&itema, 0, sizeof(itema));
3775     itema.pszText = test;
3776     ret = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&itema);
3777     expect(TRUE, ret);
3778     SetFocus(hwnd);
3779     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3780     ok(IsWindow(hwndedit), "Expected edit control to be created\n");
3781     ret = SetWindowText(hwndedit, test1);
3782     ok(ret != 0, "Expected edit text to change\n");
3783     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3784     expect(TRUE, ret);
3785     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
3786     memset(&itema, 0, sizeof(itema));
3787     itema.pszText = buff;
3788     itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
3789     ret = SendMessage(hwnd, LVM_GETITEMTEXT, 0, (LPARAM)&itema);
3790     expect(5, ret);
3791     ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
3792
3793     DestroyWindow(hwnd);
3794 }
3795
3796 static void test_mapidindex(void)
3797 {
3798     HWND hwnd;
3799     DWORD ret;
3800
3801     /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
3802     hwnd = create_listview_control(LVS_OWNERDATA);
3803     ok(hwnd != NULL, "failed to create a listview window\n");
3804     insert_item(hwnd, 0);
3805     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3806     expect(-1, ret);
3807     DestroyWindow(hwnd);
3808
3809     hwnd = create_listview_control(0);
3810     ok(hwnd != NULL, "failed to create a listview window\n");
3811
3812     /* LVM_MAPINDEXTOID with invalid index */
3813     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3814     expect(-1, ret);
3815
3816     insert_item(hwnd, 0);
3817     insert_item(hwnd, 1);
3818
3819     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, -1, 0);
3820     expect(-1, ret);
3821     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 2, 0);
3822     expect(-1, ret);
3823
3824     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3825     expect(0, ret);
3826     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
3827     expect(1, ret);
3828     /* remove 0 indexed item, id retained */
3829     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
3830     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3831     expect(1, ret);
3832     /* new id starts from previous value */
3833     insert_item(hwnd, 1);
3834     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
3835     expect(2, ret);
3836
3837     /* get index by id */
3838     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, -1, 0);
3839     expect(-1, ret);
3840     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 0, 0);
3841     expect(-1, ret);
3842     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 1, 0);
3843     expect(0, ret);
3844     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 2, 0);
3845     expect(1, ret);
3846
3847     DestroyWindow(hwnd);
3848 }
3849
3850 static void test_getitemspacing(void)
3851 {
3852     HWND hwnd;
3853     DWORD ret;
3854     INT cx, cy;
3855     HIMAGELIST himl;
3856     HBITMAP hbmp;
3857     LVITEMA itema;
3858
3859     cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON);
3860     cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
3861
3862     /* LVS_ICON */
3863     hwnd = create_custom_listview_control(0);
3864     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3865 todo_wine {
3866     expect(cx, LOWORD(ret));
3867     expect(cy, HIWORD(ret));
3868 }
3869     /* now try with icons */
3870     himl = ImageList_Create(40, 40, 0, 4, 4);
3871     ok(himl != NULL, "failed to create imagelist\n");
3872     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
3873     ok(hbmp != NULL, "failed to create bitmap\n");
3874     ret = ImageList_Add(himl, hbmp, 0);
3875     expect(0, ret);
3876     ret = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
3877     expect(0, ret);
3878
3879     itema.mask = LVIF_IMAGE;
3880     itema.iImage = 0;
3881     itema.iItem = 0;
3882     itema.iSubItem = 0;
3883     ret = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&itema);
3884     expect(0, ret);
3885     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3886 todo_wine {
3887     /* spacing + icon size returned */
3888     expect(cx + 40, LOWORD(ret));
3889     expect(cy + 40, HIWORD(ret));
3890 }
3891     DestroyWindow(hwnd);
3892     /* LVS_SMALLICON */
3893     hwnd = create_custom_listview_control(LVS_SMALLICON);
3894     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3895 todo_wine {
3896     expect(cx, LOWORD(ret));
3897     expect(cy, HIWORD(ret));
3898 }
3899     DestroyWindow(hwnd);
3900     /* LVS_REPORT */
3901     hwnd = create_custom_listview_control(LVS_REPORT);
3902     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3903 todo_wine {
3904     expect(cx, LOWORD(ret));
3905     expect(cy, HIWORD(ret));
3906 }
3907     DestroyWindow(hwnd);
3908     /* LVS_LIST */
3909     hwnd = create_custom_listview_control(LVS_LIST);
3910     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3911 todo_wine {
3912     expect(cx, LOWORD(ret));
3913     expect(cy, HIWORD(ret));
3914 }
3915     DestroyWindow(hwnd);
3916 }
3917
3918 static void test_getcolumnwidth(void)
3919 {
3920     HWND hwnd;
3921     DWORD ret;
3922     DWORD_PTR style;
3923     LVCOLUMNA col;
3924
3925     /* default column width */
3926     hwnd = create_custom_listview_control(0);
3927     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3928     expect(0, ret);
3929     style = GetWindowLong(hwnd, GWL_STYLE);
3930     SetWindowLong(hwnd, GWL_STYLE, style | LVS_LIST);
3931     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3932     todo_wine expect(8, ret);
3933     style = GetWindowLong(hwnd, GWL_STYLE) & ~LVS_LIST;
3934     SetWindowLong(hwnd, GWL_STYLE, style | LVS_REPORT);
3935     col.mask = 0;
3936     ret = SendMessage(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
3937     expect(0, ret);
3938     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3939     expect(10, ret);
3940     DestroyWindow(hwnd);
3941 }
3942
3943 static void test_scrollnotify(void)
3944 {
3945     HWND hwnd;
3946     DWORD ret;
3947
3948     hwnd = create_listview_control(0);
3949
3950     insert_column(hwnd, 0);
3951     insert_column(hwnd, 1);
3952     insert_item(hwnd, 0);
3953
3954     /* make it scrollable - resize */
3955     ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3956     expect(TRUE, ret);
3957     ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
3958     expect(TRUE, ret);
3959
3960     /* try with dummy call */
3961     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3962     ret = SendMessage(hwnd, LVM_SCROLL, 0, 0);
3963     expect(TRUE, ret);
3964     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3965                 "scroll notify 1", TRUE);
3966
3967     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3968     ret = SendMessage(hwnd, LVM_SCROLL, 1, 0);
3969     expect(TRUE, ret);
3970     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3971                 "scroll notify 2", TRUE);
3972
3973     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3974     ret = SendMessage(hwnd, LVM_SCROLL, 1, 1);
3975     expect(TRUE, ret);
3976     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3977                 "scroll notify 3", TRUE);
3978
3979     DestroyWindow(hwnd);
3980 }
3981
3982 static void test_LVS_EX_TRANSPARENTBKGND(void)
3983 {
3984     HWND hwnd;
3985     DWORD ret;
3986     HDC hdc;
3987
3988     hwnd = create_listview_control(0);
3989
3990     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
3991     expect(TRUE, ret);
3992
3993     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
3994                                                     LVS_EX_TRANSPARENTBKGND);
3995
3996     ret = SendMessage(hwnd, LVM_GETBKCOLOR, 0, 0);
3997     if (ret != CLR_NONE)
3998     {
3999         win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n");
4000         DestroyWindow(hwnd);
4001         return;
4002     }
4003
4004     /* try to set some back color and check this style bit */
4005     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
4006     expect(TRUE, ret);
4007     ret = SendMessage(hwnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
4008     ok(!(ret & LVS_EX_TRANSPARENTBKGND), "Expected LVS_EX_TRANSPARENTBKGND to unset\n");
4009
4010     /* now test what this style actually does */
4011     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
4012                                                     LVS_EX_TRANSPARENTBKGND);
4013
4014     hdc = GetWindowDC(hwndparent);
4015
4016     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4017     SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
4018     ok_sequence(sequences, PARENT_SEQ_INDEX, lvs_ex_transparentbkgnd_seq,
4019                 "LVS_EX_TRANSPARENTBKGND parent", FALSE);
4020
4021     ReleaseDC(hwndparent, hdc);
4022
4023     DestroyWindow(hwnd);
4024 }
4025
4026 static void test_approximate_viewrect(void)
4027 {
4028     HWND hwnd;
4029     DWORD ret;
4030     INT cx, cy;
4031     HIMAGELIST himl;
4032     HBITMAP hbmp;
4033     LVITEMA itema;
4034     static CHAR test[] = "abracadabra, a very long item label";
4035
4036     cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON);
4037     cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
4038
4039     hwnd = create_custom_listview_control(LVS_ICON);
4040     himl = ImageList_Create(40, 40, 0, 4, 4);
4041     ok(himl != NULL, "failed to create imagelist\n");
4042     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
4043     ok(hbmp != NULL, "failed to create bitmap\n");
4044     ret = ImageList_Add(himl, hbmp, 0);
4045     expect(0, ret);
4046     ret = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
4047     expect(0, ret);
4048
4049     itema.mask = LVIF_IMAGE;
4050     itema.iImage = 0;
4051     itema.iItem = 0;
4052     itema.iSubItem = 0;
4053     ret = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&itema);
4054     expect(0, ret);
4055
4056     ret = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(75, 75));
4057     if (ret == 0)
4058     {
4059         /* version 4.0 */
4060         win_skip("LVM_SETICONSPACING unimplemented. Skipping.\n");
4061         return;
4062     }
4063
4064     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100));
4065     ok(MAKELONG(77,827)==ret,"Incorrect Approximate rect\n");
4066
4067     ret = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(50, 50));
4068     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100));
4069     ok(MAKELONG(102,302)==ret,"Incorrect Approximate rect\n");
4070
4071     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100));
4072     ok(MAKELONG(52,52)==ret,"Incorrect Approximate rect\n");
4073
4074     itema.pszText = test;
4075     ret = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&itema);
4076     expect(TRUE, ret);
4077     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100));
4078     ok(MAKELONG(52,52)==ret,"Incorrect Approximate rect\n");
4079
4080     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 0, MAKELPARAM(100,100));
4081     ok(MAKELONG(52,2)==ret,"Incorrect Approximate rect\n");
4082     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 1, MAKELPARAM(100,100));
4083     ok(MAKELONG(52,52)==ret,"Incorrect Approximate rect\n");
4084     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 2, MAKELPARAM(100,100));
4085     ok(MAKELONG(102,52)==ret,"Incorrect Approximate rect\n");
4086     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 3, MAKELPARAM(100,100));
4087     ok(MAKELONG(102,102)==ret,"Incorrect Approximate rect\n");
4088     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 4, MAKELPARAM(100,100));
4089     ok(MAKELONG(102,102)==ret,"Incorrect Approximate rect\n");
4090     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 5, MAKELPARAM(100,100));
4091     ok(MAKELONG(102,152)==ret,"Incorrect Approximate rect\n");
4092     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 6, MAKELPARAM(100,100));
4093     ok(MAKELONG(102,152)==ret,"Incorrect Approximate rect\n");
4094     ret = SendMessage(hwnd, LVM_APPROXIMATEVIEWRECT, 7, MAKELPARAM(160,100));
4095     ok(MAKELONG(152,152)==ret,"Incorrect Approximate rect\n");
4096
4097     DestroyWindow(hwnd);
4098 }
4099
4100 static void test_finditem(void)
4101 {
4102     LVFINDINFOA fi;
4103     static char f[5];
4104     HWND hwnd;
4105     DWORD r;
4106
4107     hwnd = create_listview_control(0);
4108     insert_item(hwnd, 0);
4109
4110     memset(&fi, 0, sizeof(fi));
4111
4112     /* full string search, inserted text was "foo" */
4113     strcpy(f, "foo");
4114     fi.flags = LVFI_STRING;
4115     fi.psz = f;
4116     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4117     expect(0, r);
4118     /* partial string search, inserted text was "foo" */
4119     strcpy(f, "fo");
4120     fi.flags = LVFI_STRING | LVFI_PARTIAL;
4121     fi.psz = f;
4122     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4123     expect(0, r);
4124     /* partial string search, part after start char */
4125     strcpy(f, "oo");
4126     fi.flags = LVFI_STRING | LVFI_PARTIAL;
4127     fi.psz = f;
4128     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4129     expect(-1, r);
4130
4131     /* try with LVFI_SUBSTRING */
4132     strcpy(f, "fo");
4133     fi.flags = LVFI_SUBSTRING;
4134     fi.psz = f;
4135     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4136     if (r == -1)
4137     {
4138         win_skip("LVFI_SUBSTRING not supported\n");
4139         DestroyWindow(hwnd);
4140         return;
4141     }
4142     expect(0, r);
4143     strcpy(f, "f");
4144     fi.flags = LVFI_SUBSTRING;
4145     fi.psz = f;
4146     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4147     expect(0, r);
4148     strcpy(f, "o");
4149     fi.flags = LVFI_SUBSTRING;
4150     fi.psz = f;
4151     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4152     expect(-1, r);
4153
4154     strcpy(f, "f");
4155     fi.flags = LVFI_SUBSTRING | LVFI_STRING;
4156     fi.psz = f;
4157     r = SendMessage(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
4158     expect(0, r);
4159
4160     DestroyWindow(hwnd);
4161 }
4162
4163 START_TEST(listview)
4164 {
4165     HMODULE hComctl32;
4166     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
4167
4168     ULONG_PTR ctx_cookie;
4169     HANDLE hCtx;
4170     HWND hwnd;
4171
4172     hComctl32 = GetModuleHandleA("comctl32.dll");
4173     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
4174     if (pInitCommonControlsEx)
4175     {
4176         INITCOMMONCONTROLSEX iccex;
4177         iccex.dwSize = sizeof(iccex);
4178         iccex.dwICC  = ICC_LISTVIEW_CLASSES;
4179         pInitCommonControlsEx(&iccex);
4180     }
4181     else
4182         InitCommonControls();
4183
4184     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
4185
4186     hwndparent = create_parent_window(FALSE);
4187     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4188
4189     g_is_below_5 = is_below_comctl_5();
4190
4191     test_images();
4192     test_checkboxes();
4193     test_items();
4194     test_create();
4195     test_redraw();
4196     test_customdraw();
4197     test_icon_spacing();
4198     test_color();
4199     test_item_count();
4200     test_item_position();
4201     test_columns();
4202     test_getorigin();
4203     test_multiselect();
4204     test_getitemrect();
4205     test_subitem_rect();
4206     test_sorting();
4207     test_ownerdata();
4208     test_norecompute();
4209     test_nosortheader();
4210     test_setredraw();
4211     test_hittest();
4212     test_getviewrect();
4213     test_getitemposition();
4214     test_columnscreation();
4215     test_editbox();
4216     test_notifyformat();
4217     test_indentation();
4218     test_getitemspacing();
4219     test_getcolumnwidth();
4220     test_approximate_viewrect();
4221     test_finditem();
4222
4223     if (!load_v6_module(&ctx_cookie, &hCtx))
4224     {
4225         DestroyWindow(hwndparent);
4226         return;
4227     }
4228
4229     /* this is a XP SP3 failure workaround */
4230     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
4231                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT,
4232                            0, 0, 100, 100,
4233                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
4234     if (!IsWindow(hwnd))
4235     {
4236         win_skip("FIXME: failed to create ListView window.\n");
4237         unload_v6_module(ctx_cookie, hCtx);
4238         DestroyWindow(hwndparent);
4239         return;
4240     }
4241     else
4242         DestroyWindow(hwnd);
4243
4244     /* comctl32 version 6 tests start here */
4245     test_get_set_view();
4246     test_canceleditlabel();
4247     test_mapidindex();
4248     test_scrollnotify();
4249     test_LVS_EX_TRANSPARENTBKGND();
4250
4251     unload_v6_module(ctx_cookie, hCtx);
4252
4253     DestroyWindow(hwndparent);
4254 }