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