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