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