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