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