1*c2c66affSColin Finck /* Unit tests for treeview.
2*c2c66affSColin Finck  *
3*c2c66affSColin Finck  * Copyright 2005 Krzysztof Foltman
4*c2c66affSColin Finck  * Copyright 2007 Christopher James Peterson
5*c2c66affSColin Finck  *
6*c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7*c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8*c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9*c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10*c2c66affSColin Finck  *
11*c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12*c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*c2c66affSColin Finck  * Lesser General Public License for more details.
15*c2c66affSColin Finck  *
16*c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17*c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18*c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19*c2c66affSColin Finck  */
20*c2c66affSColin Finck 
21*c2c66affSColin Finck #include <stdarg.h>
22*c2c66affSColin Finck #include <stdio.h>
23*c2c66affSColin Finck 
24*c2c66affSColin Finck #include "windef.h"
25*c2c66affSColin Finck #include "winbase.h"
26*c2c66affSColin Finck #include "wingdi.h"
27*c2c66affSColin Finck #include "winuser.h"
28*c2c66affSColin Finck #include "winnls.h"
29*c2c66affSColin Finck #include "winreg.h"
30*c2c66affSColin Finck #include "wine/commctrl.h"
31*c2c66affSColin Finck 
32*c2c66affSColin Finck #include "wine/test.h"
33*c2c66affSColin Finck #include "v6util.h"
34*c2c66affSColin Finck #include "msg.h"
35*c2c66affSColin Finck 
36*c2c66affSColin Finck static const char *TEST_CALLBACK_TEXT = "callback_text";
37*c2c66affSColin Finck 
38*c2c66affSColin Finck static TVITEMA g_item_expanding, g_item_expanded;
39*c2c66affSColin Finck static BOOL g_get_from_expand;
40*c2c66affSColin Finck static BOOL g_get_rect_in_expand;
41*c2c66affSColin Finck static BOOL g_disp_A_to_W;
42*c2c66affSColin Finck static BOOL g_disp_set_stateimage;
43*c2c66affSColin Finck static BOOL g_beginedit_alter_text;
44*c2c66affSColin Finck static HFONT g_customdraw_font;
45*c2c66affSColin Finck static BOOL g_v6;
46*c2c66affSColin Finck 
47*c2c66affSColin Finck #define NUM_MSG_SEQUENCES   3
48*c2c66affSColin Finck #define TREEVIEW_SEQ_INDEX  0
49*c2c66affSColin Finck #define PARENT_SEQ_INDEX    1
50*c2c66affSColin Finck #define PARENT_CD_SEQ_INDEX 2
51*c2c66affSColin Finck 
52*c2c66affSColin Finck #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
53*c2c66affSColin Finck 
54*c2c66affSColin Finck static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
55*c2c66affSColin Finck static struct msg_sequence *item_sequence[1];
56*c2c66affSColin Finck 
57*c2c66affSColin Finck static void flush_events(void)
58*c2c66affSColin Finck {
59*c2c66affSColin Finck     MSG msg;
60*c2c66affSColin Finck     int diff = 200;
61*c2c66affSColin Finck     int min_timeout = 100;
62*c2c66affSColin Finck     DWORD time = GetTickCount() + diff;
63*c2c66affSColin Finck 
64*c2c66affSColin Finck     while (diff > 0)
65*c2c66affSColin Finck     {
66*c2c66affSColin Finck         if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT) break;
67*c2c66affSColin Finck         while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
68*c2c66affSColin Finck         diff = time - GetTickCount();
69*c2c66affSColin Finck     }
70*c2c66affSColin Finck }
71*c2c66affSColin Finck 
72*c2c66affSColin Finck static const struct message FillRootSeq[] = {
73*c2c66affSColin Finck     { TVM_INSERTITEMA, sent },
74*c2c66affSColin Finck     { TVM_INSERTITEMA, sent },
75*c2c66affSColin Finck     { 0 }
76*c2c66affSColin Finck };
77*c2c66affSColin Finck 
78*c2c66affSColin Finck static const struct message rootnone_select_seq[] = {
79*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
80*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
81*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
82*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
83*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
84*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
85*c2c66affSColin Finck     { 0 }
86*c2c66affSColin Finck };
87*c2c66affSColin Finck 
88*c2c66affSColin Finck static const struct message rootchild_select_seq[] = {
89*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
90*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
91*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
92*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
93*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
94*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
95*c2c66affSColin Finck     { 0 }
96*c2c66affSColin Finck };
97*c2c66affSColin Finck 
98*c2c66affSColin Finck static const struct message getitemtext_seq[] = {
99*c2c66affSColin Finck     { TVM_INSERTITEMA, sent },
100*c2c66affSColin Finck     { TVM_GETITEMA, sent },
101*c2c66affSColin Finck     { TVM_DELETEITEM, sent },
102*c2c66affSColin Finck     { 0 }
103*c2c66affSColin Finck };
104*c2c66affSColin Finck 
105*c2c66affSColin Finck static const struct message focus_seq[] = {
106*c2c66affSColin Finck     { TVM_INSERTITEMA, sent },
107*c2c66affSColin Finck     { TVM_INSERTITEMA, sent },
108*c2c66affSColin Finck     { TVM_SELECTITEM, sent|wparam, 9 },
109*c2c66affSColin Finck     /* The following end up out of order in wine */
110*c2c66affSColin Finck     { WM_WINDOWPOSCHANGING, sent|defwinproc },
111*c2c66affSColin Finck     { WM_NCCALCSIZE, sent|wparam|defwinproc, TRUE },
112*c2c66affSColin Finck     { WM_WINDOWPOSCHANGED, sent|defwinproc },
113*c2c66affSColin Finck     { WM_SIZE, sent|defwinproc },
114*c2c66affSColin Finck     { WM_WINDOWPOSCHANGING, sent|defwinproc|optional },
115*c2c66affSColin Finck     { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, TRUE },
116*c2c66affSColin Finck     { WM_WINDOWPOSCHANGED, sent|defwinproc|optional },
117*c2c66affSColin Finck     { WM_SIZE, sent|defwinproc|optional },
118*c2c66affSColin Finck     { WM_PAINT, sent|defwinproc },
119*c2c66affSColin Finck     { WM_NCPAINT, sent|wparam|defwinproc, 1 },
120*c2c66affSColin Finck     { WM_ERASEBKGND, sent|defwinproc },
121*c2c66affSColin Finck     { TVM_EDITLABELA, sent },
122*c2c66affSColin Finck     { WM_COMMAND, sent|wparam|defwinproc, MAKEWPARAM(0, EN_UPDATE) },
123*c2c66affSColin Finck     { WM_COMMAND, sent|wparam|defwinproc, MAKEWPARAM(0, EN_CHANGE) },
124*c2c66affSColin Finck     { WM_PARENTNOTIFY, sent|wparam|defwinproc, MAKEWPARAM(WM_CREATE, 0) },
125*c2c66affSColin Finck     { WM_KILLFOCUS, sent|defwinproc },
126*c2c66affSColin Finck     { WM_PAINT, sent|defwinproc },
127*c2c66affSColin Finck     { WM_IME_SETCONTEXT, sent|defwinproc|optional },
128*c2c66affSColin Finck     { WM_COMMAND, sent|wparam|defwinproc, MAKEWPARAM(0, EN_SETFOCUS) },
129*c2c66affSColin Finck     { WM_ERASEBKGND, sent|defwinproc|optional },
130*c2c66affSColin Finck     { WM_CTLCOLOREDIT, sent|defwinproc|optional },
131*c2c66affSColin Finck     { WM_CTLCOLOREDIT, sent|defwinproc|optional },
132*c2c66affSColin Finck     { 0 }
133*c2c66affSColin Finck };
134*c2c66affSColin Finck 
135*c2c66affSColin Finck static const struct message test_get_set_bkcolor_seq[] = {
136*c2c66affSColin Finck     { TVM_GETBKCOLOR, sent|wparam|lparam, 0, 0 },
137*c2c66affSColin Finck     { TVM_SETBKCOLOR, sent|wparam|lparam, 0, 0 },
138*c2c66affSColin Finck     { TVM_GETBKCOLOR, sent|wparam|lparam, 0, 0 },
139*c2c66affSColin Finck     { TVM_SETBKCOLOR, sent|wparam|lparam, 0, 0x00ffffff },
140*c2c66affSColin Finck     { TVM_GETBKCOLOR, sent|wparam|lparam, 0, 0 },
141*c2c66affSColin Finck     { TVM_SETBKCOLOR, sent|wparam|lparam, 0, -1 },
142*c2c66affSColin Finck     { 0 }
143*c2c66affSColin Finck };
144*c2c66affSColin Finck 
145*c2c66affSColin Finck static const struct message test_get_set_imagelist_seq[] = {
146*c2c66affSColin Finck     { TVM_SETIMAGELIST, sent|wparam|lparam, 0, 0 },
147*c2c66affSColin Finck     { TVM_GETIMAGELIST, sent|wparam|lparam, 0, 0 },
148*c2c66affSColin Finck     { 0 }
149*c2c66affSColin Finck };
150*c2c66affSColin Finck 
151*c2c66affSColin Finck static const struct message test_get_set_indent_seq[] = {
152*c2c66affSColin Finck     { TVM_SETINDENT, sent|wparam|lparam, 0, 0 },
153*c2c66affSColin Finck     { TVM_GETINDENT, sent|wparam|lparam, 0, 0 },
154*c2c66affSColin Finck     /* The actual amount to indent is dependent on the system for this message */
155*c2c66affSColin Finck     { TVM_SETINDENT, sent },
156*c2c66affSColin Finck     { TVM_GETINDENT, sent|wparam|lparam, 0, 0 },
157*c2c66affSColin Finck     { 0 }
158*c2c66affSColin Finck };
159*c2c66affSColin Finck 
160*c2c66affSColin Finck static const struct message test_get_set_insertmarkcolor_seq[] = {
161*c2c66affSColin Finck     { TVM_SETINSERTMARKCOLOR, sent|wparam|lparam, 0, 0 },
162*c2c66affSColin Finck     { TVM_GETINSERTMARKCOLOR, sent|wparam|lparam, 0, 0 },
163*c2c66affSColin Finck     { 0 }
164*c2c66affSColin Finck };
165*c2c66affSColin Finck 
166*c2c66affSColin Finck static const struct message test_get_set_item_seq[] = {
167*c2c66affSColin Finck     { TVM_GETITEMA, sent },
168*c2c66affSColin Finck     { TVM_SETITEMA, sent },
169*c2c66affSColin Finck     { TVM_GETITEMA, sent },
170*c2c66affSColin Finck     { TVM_SETITEMA, sent },
171*c2c66affSColin Finck     { 0 }
172*c2c66affSColin Finck };
173*c2c66affSColin Finck 
174*c2c66affSColin Finck static const struct message test_get_set_itemheight_seq[] = {
175*c2c66affSColin Finck     { TVM_GETITEMHEIGHT, sent|wparam|lparam, 0, 0 },
176*c2c66affSColin Finck     { TVM_SETITEMHEIGHT, sent|wparam|lparam, -1, 0 },
177*c2c66affSColin Finck     { TVM_GETITEMHEIGHT, sent|wparam|lparam, 0, 0 },
178*c2c66affSColin Finck     { TVM_SETITEMHEIGHT, sent|lparam, 0xcccccccc, 0 },
179*c2c66affSColin Finck     { TVM_GETITEMHEIGHT, sent|wparam|lparam|optional, 0, 0 },
180*c2c66affSColin Finck     { TVM_SETITEMHEIGHT, sent|wparam|lparam|optional, 9, 0 },
181*c2c66affSColin Finck     { TVM_GETITEMHEIGHT, sent|wparam|lparam, 0, 0 },
182*c2c66affSColin Finck     { 0 }
183*c2c66affSColin Finck };
184*c2c66affSColin Finck 
185*c2c66affSColin Finck static const struct message test_get_set_scrolltime_seq[] = {
186*c2c66affSColin Finck     { TVM_SETSCROLLTIME, sent|wparam|lparam, 20, 0 },
187*c2c66affSColin Finck     { TVM_GETSCROLLTIME, sent|wparam|lparam, 0, 0 },
188*c2c66affSColin Finck     { 0 }
189*c2c66affSColin Finck };
190*c2c66affSColin Finck 
191*c2c66affSColin Finck static const struct message test_get_set_textcolor_seq[] = {
192*c2c66affSColin Finck     { TVM_GETTEXTCOLOR, sent|wparam|lparam, 0, 0 },
193*c2c66affSColin Finck     { TVM_SETTEXTCOLOR, sent|wparam|lparam, 0, 0 },
194*c2c66affSColin Finck     { TVM_GETTEXTCOLOR, sent|wparam|lparam, 0, 0 },
195*c2c66affSColin Finck     { TVM_SETTEXTCOLOR, sent|wparam|lparam, 0, RGB(255, 255, 255) },
196*c2c66affSColin Finck     { TVM_GETTEXTCOLOR, sent|wparam|lparam, 0, 0 },
197*c2c66affSColin Finck     { TVM_SETTEXTCOLOR, sent|wparam|lparam, 0, CLR_NONE },
198*c2c66affSColin Finck     { 0 }
199*c2c66affSColin Finck };
200*c2c66affSColin Finck 
201*c2c66affSColin Finck static const struct message test_get_set_tooltips_seq[] = {
202*c2c66affSColin Finck     { WM_KILLFOCUS,    sent },
203*c2c66affSColin Finck     { WM_IME_SETCONTEXT, sent|optional },
204*c2c66affSColin Finck     { WM_IME_NOTIFY, sent|optional },
205*c2c66affSColin Finck     { TVM_SETTOOLTIPS, sent|wparam|lparam, 0, 0 },
206*c2c66affSColin Finck     { TVM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
207*c2c66affSColin Finck     { 0 }
208*c2c66affSColin Finck };
209*c2c66affSColin Finck 
210*c2c66affSColin Finck static const struct message test_get_set_unicodeformat_seq[] = {
211*c2c66affSColin Finck     { TVM_SETUNICODEFORMAT, sent|wparam|lparam, TRUE, 0 },
212*c2c66affSColin Finck     { TVM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
213*c2c66affSColin Finck     { TVM_SETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
214*c2c66affSColin Finck     { TVM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
215*c2c66affSColin Finck     { TVM_SETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
216*c2c66affSColin Finck     { 0 }
217*c2c66affSColin Finck };
218*c2c66affSColin Finck 
219*c2c66affSColin Finck static const struct message test_right_click_seq[] = {
220*c2c66affSColin Finck     { WM_RBUTTONDOWN, sent|wparam, MK_RBUTTON },
221*c2c66affSColin Finck     { WM_CAPTURECHANGED, sent|defwinproc },
222*c2c66affSColin Finck     { TVM_GETNEXTITEM, sent|wparam|lparam|defwinproc, TVGN_CARET, 0 },
223*c2c66affSColin Finck     { 0 }
224*c2c66affSColin Finck };
225*c2c66affSColin Finck 
226*c2c66affSColin Finck static const struct message parent_expand_seq[] = {
227*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
228*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
229*c2c66affSColin Finck     { 0 }
230*c2c66affSColin Finck };
231*c2c66affSColin Finck 
232*c2c66affSColin Finck static const struct message parent_expand_kb_seq[] = {
233*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_KEYDOWN },
234*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
235*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
236*c2c66affSColin Finck     { WM_CHANGEUISTATE, sent|optional },
237*c2c66affSColin Finck     { 0 }
238*c2c66affSColin Finck };
239*c2c66affSColin Finck 
240*c2c66affSColin Finck static const struct message parent_collapse_2nd_kb_seq[] = {
241*c2c66affSColin Finck     { WM_NOTIFY, sent|id|optional, 0, 0, TVN_KEYDOWN },
242*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
243*c2c66affSColin Finck     { WM_CHANGEUISTATE, sent|optional },
244*c2c66affSColin Finck     { 0 }
245*c2c66affSColin Finck };
246*c2c66affSColin Finck 
247*c2c66affSColin Finck static const struct message parent_expand_empty_kb_seq[] = {
248*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_KEYDOWN },
249*c2c66affSColin Finck     { WM_CHANGEUISTATE, sent|optional },
250*c2c66affSColin Finck     { 0 }
251*c2c66affSColin Finck };
252*c2c66affSColin Finck 
253*c2c66affSColin Finck static const struct message parent_singleexpand_seq0[] = {
254*c2c66affSColin Finck     /* alpha expands */
255*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
256*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
257*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
258*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
259*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
260*c2c66affSColin Finck     { 0 }
261*c2c66affSColin Finck };
262*c2c66affSColin Finck 
263*c2c66affSColin Finck static const struct message parent_singleexpand_seq1[] = {
264*c2c66affSColin Finck     /* bravo expands */
265*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
266*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
267*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
268*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
269*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
270*c2c66affSColin Finck     { 0 }
271*c2c66affSColin Finck };
272*c2c66affSColin Finck 
273*c2c66affSColin Finck static const struct message parent_singleexpand_seq2[] = {
274*c2c66affSColin Finck     /* delta expands, bravo collapses */
275*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
276*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
277*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
278*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
279*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
280*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
281*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
282*c2c66affSColin Finck     { 0 }
283*c2c66affSColin Finck };
284*c2c66affSColin Finck 
285*c2c66affSColin Finck static const struct message parent_singleexpand_seq3[] = {
286*c2c66affSColin Finck     /* foxtrot expands, alpha and delta collapse */
287*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
288*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
289*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
290*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
291*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
292*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
293*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
294*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
295*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
296*c2c66affSColin Finck     { 0 }
297*c2c66affSColin Finck };
298*c2c66affSColin Finck 
299*c2c66affSColin Finck static const struct message parent_singleexpand_seq4[] = {
300*c2c66affSColin Finck     /* alpha expands, foxtrot collapses */
301*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
302*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
303*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
304*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
305*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
306*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
307*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
308*c2c66affSColin Finck     { 0 }
309*c2c66affSColin Finck };
310*c2c66affSColin Finck 
311*c2c66affSColin Finck static const struct message parent_singleexpand_seq5[] = {
312*c2c66affSColin Finck     /* foxtrot expands while golf is selected, then golf expands and alpha collapses */
313*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
314*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
315*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
316*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
317*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
318*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
319*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
320*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA },
321*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA },
322*c2c66affSColin Finck     { 0 }
323*c2c66affSColin Finck };
324*c2c66affSColin Finck 
325*c2c66affSColin Finck static const struct message parent_singleexpand_seq6[] = {
326*c2c66affSColin Finck     /* hotel does not expand and india does not collapse because they have no children */
327*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
328*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
329*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
330*c2c66affSColin Finck     { 0 }
331*c2c66affSColin Finck };
332*c2c66affSColin Finck 
333*c2c66affSColin Finck static const struct message parent_singleexpand_seq7[] = {
334*c2c66affSColin Finck     /* india does not expand and hotel does not collapse because they have no children */
335*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGINGA },
336*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SELCHANGEDA },
337*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_SINGLEEXPAND },
338*c2c66affSColin Finck     { 0 }
339*c2c66affSColin Finck };
340*c2c66affSColin Finck 
341*c2c66affSColin Finck static const struct message parent_get_dispinfo_seq[] = {
342*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_GETDISPINFOA },
343*c2c66affSColin Finck     { 0 }
344*c2c66affSColin Finck };
345*c2c66affSColin Finck 
346*c2c66affSColin Finck static const struct message empty_seq[] = {
347*c2c66affSColin Finck     { 0 }
348*c2c66affSColin Finck };
349*c2c66affSColin Finck 
350*c2c66affSColin Finck static const struct message parent_cd_seq[] = {
351*c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT },
352*c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT },
353*c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT },
354*c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT },
355*c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT },
356*c2c66affSColin Finck     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT },
357*c2c66affSColin Finck     { 0 }
358*c2c66affSColin Finck };
359*c2c66affSColin Finck 
360*c2c66affSColin Finck static const struct message parent_vk_return_seq[] = {
361*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, TVN_KEYDOWN },
362*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, NM_RETURN },
363*c2c66affSColin Finck     { WM_CHANGEUISTATE, sent|optional },
364*c2c66affSColin Finck     { 0 }
365*c2c66affSColin Finck };
366*c2c66affSColin Finck 
367*c2c66affSColin Finck static const struct message parent_right_click_seq[] = {
368*c2c66affSColin Finck     { WM_NOTIFY, sent|id, 0, 0, NM_RCLICK },
369*c2c66affSColin Finck     { WM_CONTEXTMENU, sent },
370*c2c66affSColin Finck     { 0 }
371*c2c66affSColin Finck };
372*c2c66affSColin Finck 
373*c2c66affSColin Finck static HWND hMainWnd;
374*c2c66affSColin Finck 
375*c2c66affSColin Finck static HTREEITEM hRoot, hChild;
376*c2c66affSColin Finck 
377*c2c66affSColin Finck static int pos = 0;
378*c2c66affSColin Finck static char sequence[256];
379*c2c66affSColin Finck 
380*c2c66affSColin Finck static void Clear(void)
381*c2c66affSColin Finck {
382*c2c66affSColin Finck     pos = 0;
383*c2c66affSColin Finck     sequence[0] = '\0';
384*c2c66affSColin Finck }
385*c2c66affSColin Finck 
386*c2c66affSColin Finck static void AddItem(char ch)
387*c2c66affSColin Finck {
388*c2c66affSColin Finck     sequence[pos++] = ch;
389*c2c66affSColin Finck     sequence[pos] = '\0';
390*c2c66affSColin Finck }
391*c2c66affSColin Finck 
392*c2c66affSColin Finck static void IdentifyItem(HTREEITEM hItem)
393*c2c66affSColin Finck {
394*c2c66affSColin Finck     if (hItem == hRoot) {
395*c2c66affSColin Finck         AddItem('R');
396*c2c66affSColin Finck         return;
397*c2c66affSColin Finck     }
398*c2c66affSColin Finck     if (hItem == hChild) {
399*c2c66affSColin Finck         AddItem('C');
400*c2c66affSColin Finck         return;
401*c2c66affSColin Finck     }
402*c2c66affSColin Finck     if (hItem == NULL) {
403*c2c66affSColin Finck         AddItem('n');
404*c2c66affSColin Finck         return;
405*c2c66affSColin Finck     }
406*c2c66affSColin Finck     AddItem('?');
407*c2c66affSColin Finck }
408*c2c66affSColin Finck 
409*c2c66affSColin Finck /* This function hooks in and records all messages to the treeview control */
410*c2c66affSColin Finck static LRESULT WINAPI TreeviewWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
411*c2c66affSColin Finck {
412*c2c66affSColin Finck     static LONG defwndproc_counter = 0;
413*c2c66affSColin Finck     LRESULT ret;
414*c2c66affSColin Finck     WNDPROC lpOldProc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
415*c2c66affSColin Finck     struct message msg = { 0 };
416*c2c66affSColin Finck 
417*c2c66affSColin Finck     msg.message = message;
418*c2c66affSColin Finck     msg.flags = sent|wparam|lparam;
419*c2c66affSColin Finck     if (defwndproc_counter) msg.flags |= defwinproc;
420*c2c66affSColin Finck     msg.wParam = wParam;
421*c2c66affSColin Finck     msg.lParam = lParam;
422*c2c66affSColin Finck     add_message(sequences, TREEVIEW_SEQ_INDEX, &msg);
423*c2c66affSColin Finck 
424*c2c66affSColin Finck     defwndproc_counter++;
425*c2c66affSColin Finck     ret = CallWindowProcA(lpOldProc, hwnd, message, wParam, lParam);
426*c2c66affSColin Finck     defwndproc_counter--;
427*c2c66affSColin Finck 
428*c2c66affSColin Finck     return ret;
429*c2c66affSColin Finck }
430*c2c66affSColin Finck 
431*c2c66affSColin Finck static HWND create_treeview_control(DWORD style)
432*c2c66affSColin Finck {
433*c2c66affSColin Finck     WNDPROC pOldWndProc;
434*c2c66affSColin Finck     HWND hTree;
435*c2c66affSColin Finck 
436*c2c66affSColin Finck     hTree = CreateWindowExA(WS_EX_CLIENTEDGE, WC_TREEVIEWA, NULL, WS_CHILD|WS_VISIBLE|
437*c2c66affSColin Finck             TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS|TVS_EDITLABELS|style,
438*c2c66affSColin Finck             0, 0, 120, 100, hMainWnd, (HMENU)100, GetModuleHandleA(0), 0);
439*c2c66affSColin Finck 
440*c2c66affSColin Finck     SetFocus(hTree);
441*c2c66affSColin Finck 
442*c2c66affSColin Finck     /* Record the old WNDPROC so we can call it after recording the messages */
443*c2c66affSColin Finck     pOldWndProc = (WNDPROC)SetWindowLongPtrA(hTree, GWLP_WNDPROC, (LONG_PTR)TreeviewWndProc);
444*c2c66affSColin Finck     SetWindowLongPtrA(hTree, GWLP_USERDATA, (LONG_PTR)pOldWndProc);
445*c2c66affSColin Finck 
446*c2c66affSColin Finck     return hTree;
447*c2c66affSColin Finck }
448*c2c66affSColin Finck 
449*c2c66affSColin Finck static void fill_tree(HWND hTree)
450*c2c66affSColin Finck {
451*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
452*c2c66affSColin Finck     static CHAR root[]  = "Root",
453*c2c66affSColin Finck                 child[] = "Child";
454*c2c66affSColin Finck 
455*c2c66affSColin Finck     ins.hParent = TVI_ROOT;
456*c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
457*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
458*c2c66affSColin Finck     U(ins).item.pszText = root;
459*c2c66affSColin Finck     hRoot = TreeView_InsertItemA(hTree, &ins);
460*c2c66affSColin Finck 
461*c2c66affSColin Finck     ins.hParent = hRoot;
462*c2c66affSColin Finck     ins.hInsertAfter = TVI_FIRST;
463*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
464*c2c66affSColin Finck     U(ins).item.pszText = child;
465*c2c66affSColin Finck     hChild = TreeView_InsertItemA(hTree, &ins);
466*c2c66affSColin Finck }
467*c2c66affSColin Finck 
468*c2c66affSColin Finck static void test_fillroot(void)
469*c2c66affSColin Finck {
470*c2c66affSColin Finck     TVITEMA tvi;
471*c2c66affSColin Finck     HWND hTree;
472*c2c66affSColin Finck 
473*c2c66affSColin Finck     hTree = create_treeview_control(0);
474*c2c66affSColin Finck 
475*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
476*c2c66affSColin Finck 
477*c2c66affSColin Finck     fill_tree(hTree);
478*c2c66affSColin Finck 
479*c2c66affSColin Finck     Clear();
480*c2c66affSColin Finck     AddItem('A');
481*c2c66affSColin Finck     ok(hRoot != NULL, "failed to set root\n");
482*c2c66affSColin Finck     AddItem('B');
483*c2c66affSColin Finck     ok(hChild != NULL, "failed to set child\n");
484*c2c66affSColin Finck     AddItem('.');
485*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, FillRootSeq, "FillRoot", FALSE);
486*c2c66affSColin Finck     ok(!strcmp(sequence, "AB."), "Item creation\n");
487*c2c66affSColin Finck 
488*c2c66affSColin Finck     /* UMLPad 1.15 depends on this being not -1 (I_IMAGECALLBACK) */
489*c2c66affSColin Finck     tvi.hItem = hRoot;
490*c2c66affSColin Finck     tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
491*c2c66affSColin Finck     SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&tvi);
492*c2c66affSColin Finck     ok(tvi.iImage == 0, "tvi.iImage=%d\n", tvi.iImage);
493*c2c66affSColin Finck     ok(tvi.iSelectedImage == 0, "tvi.iSelectedImage=%d\n", tvi.iSelectedImage);
494*c2c66affSColin Finck 
495*c2c66affSColin Finck     DestroyWindow(hTree);
496*c2c66affSColin Finck }
497*c2c66affSColin Finck 
498*c2c66affSColin Finck static void test_callback(void)
499*c2c66affSColin Finck {
500*c2c66affSColin Finck     HTREEITEM hRoot;
501*c2c66affSColin Finck     HTREEITEM hItem1, hItem2;
502*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
503*c2c66affSColin Finck     TVITEMA tvi;
504*c2c66affSColin Finck     CHAR test_string[] = "Test_string";
505*c2c66affSColin Finck     static const CHAR test2A[] = "TEST2";
506*c2c66affSColin Finck     CHAR buf[128];
507*c2c66affSColin Finck     HWND hTree;
508*c2c66affSColin Finck     DWORD ret;
509*c2c66affSColin Finck 
510*c2c66affSColin Finck     hTree = create_treeview_control(0);
511*c2c66affSColin Finck 
512*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
513*c2c66affSColin Finck     expect(TRUE, ret);
514*c2c66affSColin Finck     ins.hParent = TVI_ROOT;
515*c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
516*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
517*c2c66affSColin Finck     U(ins).item.pszText = LPSTR_TEXTCALLBACKA;
518*c2c66affSColin Finck     hRoot = TreeView_InsertItemA(hTree, &ins);
519*c2c66affSColin Finck     ok(hRoot != NULL, "failed to set root\n");
520*c2c66affSColin Finck 
521*c2c66affSColin Finck     tvi.hItem = hRoot;
522*c2c66affSColin Finck     tvi.mask = TVIF_TEXT;
523*c2c66affSColin Finck     tvi.pszText = buf;
524*c2c66affSColin Finck     tvi.cchTextMax = sizeof(buf)/sizeof(buf[0]);
525*c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
526*c2c66affSColin Finck     expect(TRUE, ret);
527*c2c66affSColin Finck     ok(strcmp(tvi.pszText, TEST_CALLBACK_TEXT) == 0, "Callback item text mismatch %s vs %s\n",
528*c2c66affSColin Finck         tvi.pszText, TEST_CALLBACK_TEXT);
529*c2c66affSColin Finck 
530*c2c66affSColin Finck     ins.hParent = hRoot;
531*c2c66affSColin Finck     ins.hInsertAfter = TVI_FIRST;
532*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
533*c2c66affSColin Finck     U(ins).item.pszText = test_string;
534*c2c66affSColin Finck     hItem1 = TreeView_InsertItemA(hTree, &ins);
535*c2c66affSColin Finck     ok(hItem1 != NULL, "failed to set Item1\n");
536*c2c66affSColin Finck 
537*c2c66affSColin Finck     tvi.hItem = hItem1;
538*c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
539*c2c66affSColin Finck     expect(TRUE, ret);
540*c2c66affSColin Finck     ok(strcmp(tvi.pszText, test_string) == 0, "Item text mismatch %s vs %s\n",
541*c2c66affSColin Finck         tvi.pszText, test_string);
542*c2c66affSColin Finck 
543*c2c66affSColin Finck     /* undocumented: pszText of NULL also means LPSTR_CALLBACK: */
544*c2c66affSColin Finck     tvi.pszText = NULL;
545*c2c66affSColin Finck     ret = TreeView_SetItemA(hTree, &tvi);
546*c2c66affSColin Finck     expect(TRUE, ret);
547*c2c66affSColin Finck     tvi.pszText = buf;
548*c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
549*c2c66affSColin Finck     expect(TRUE, ret);
550*c2c66affSColin Finck     ok(strcmp(tvi.pszText, TEST_CALLBACK_TEXT) == 0, "Item text mismatch %s vs %s\n",
551*c2c66affSColin Finck         tvi.pszText, TEST_CALLBACK_TEXT);
552*c2c66affSColin Finck 
553*c2c66affSColin Finck     U(ins).item.pszText = NULL;
554*c2c66affSColin Finck     hItem2 = TreeView_InsertItemA(hTree, &ins);
555*c2c66affSColin Finck     ok(hItem2 != NULL, "failed to set Item2\n");
556*c2c66affSColin Finck     tvi.hItem = hItem2;
557*c2c66affSColin Finck     memset(buf, 0, sizeof(buf));
558*c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
559*c2c66affSColin Finck     expect(TRUE, ret);
560*c2c66affSColin Finck     ok(strcmp(tvi.pszText, TEST_CALLBACK_TEXT) == 0, "Item text mismatch %s vs %s\n",
561*c2c66affSColin Finck         tvi.pszText, TEST_CALLBACK_TEXT);
562*c2c66affSColin Finck 
563*c2c66affSColin Finck     /* notification handler changed A->W */
564*c2c66affSColin Finck     g_disp_A_to_W = TRUE;
565*c2c66affSColin Finck     tvi.hItem = hItem2;
566*c2c66affSColin Finck     memset(buf, 0, sizeof(buf));
567*c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
568*c2c66affSColin Finck     expect(TRUE, ret);
569*c2c66affSColin Finck     ok(strcmp(tvi.pszText, test2A) == 0, "got %s, expected %s\n",
570*c2c66affSColin Finck         tvi.pszText, test2A);
571*c2c66affSColin Finck     g_disp_A_to_W = FALSE;
572*c2c66affSColin Finck 
573*c2c66affSColin Finck     /* handler changes state image index */
574*c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_CHECKBOXES);
575*c2c66affSColin Finck 
576*c2c66affSColin Finck     /* clear selection, handler will set selected state */
577*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
578*c2c66affSColin Finck     expect(TRUE, ret);
579*c2c66affSColin Finck 
580*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
581*c2c66affSColin Finck 
582*c2c66affSColin Finck     tvi.hItem = hRoot;
583*c2c66affSColin Finck     tvi.mask = TVIF_STATE;
584*c2c66affSColin Finck     tvi.state = TVIS_SELECTED;
585*c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
586*c2c66affSColin Finck     expect(TRUE, ret);
587*c2c66affSColin Finck     ok(tvi.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", tvi.state);
588*c2c66affSColin Finck 
589*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
590*c2c66affSColin Finck                 "no TVN_GETDISPINFO for a state seq", FALSE);
591*c2c66affSColin Finck 
592*c2c66affSColin Finck     tvi.hItem     = hRoot;
593*c2c66affSColin Finck     tvi.mask      = TVIF_IMAGE | TVIF_STATE;
594*c2c66affSColin Finck     tvi.state     = TVIS_FOCUSED;
595*c2c66affSColin Finck     tvi.stateMask = TVIS_FOCUSED;
596*c2c66affSColin Finck     tvi.iImage    = I_IMAGECALLBACK;
597*c2c66affSColin Finck     ret = TreeView_SetItemA(hTree, &tvi);
598*c2c66affSColin Finck     expect(TRUE, ret);
599*c2c66affSColin Finck 
600*c2c66affSColin Finck     /* ask for item image index through callback - state is also set with state image index */
601*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
602*c2c66affSColin Finck 
603*c2c66affSColin Finck     tvi.hItem = hRoot;
604*c2c66affSColin Finck     tvi.mask = TVIF_IMAGE;
605*c2c66affSColin Finck     tvi.state = 0;
606*c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
607*c2c66affSColin Finck     expect(TRUE, ret);
608*c2c66affSColin Finck     ok(tvi.state == (INDEXTOSTATEIMAGEMASK(1) | TVIS_FOCUSED), "got 0x%x\n", tvi.state);
609*c2c66affSColin Finck 
610*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_get_dispinfo_seq,
611*c2c66affSColin Finck                 "callback for state/overlay image index, noop seq", FALSE);
612*c2c66affSColin Finck 
613*c2c66affSColin Finck     /* ask for image again and overwrite state to some value in handler */
614*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
615*c2c66affSColin Finck 
616*c2c66affSColin Finck     g_disp_set_stateimage = TRUE;
617*c2c66affSColin Finck     tvi.hItem = hRoot;
618*c2c66affSColin Finck     tvi.mask = TVIF_IMAGE;
619*c2c66affSColin Finck     tvi.state = INDEXTOSTATEIMAGEMASK(1);
620*c2c66affSColin Finck     tvi.stateMask = 0;
621*c2c66affSColin Finck     ret = TreeView_GetItemA(hTree, &tvi);
622*c2c66affSColin Finck     expect(TRUE, ret);
623*c2c66affSColin Finck     /* handler sets TVIS_SELECTED as well */
624*c2c66affSColin Finck     ok(tvi.state == (TVIS_FOCUSED | TVIS_SELECTED | INDEXTOSTATEIMAGEMASK(2) | INDEXTOOVERLAYMASK(3)), "got 0x%x\n", tvi.state);
625*c2c66affSColin Finck     g_disp_set_stateimage = FALSE;
626*c2c66affSColin Finck 
627*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_get_dispinfo_seq,
628*c2c66affSColin Finck                 "callback for state/overlay image index seq", FALSE);
629*c2c66affSColin Finck 
630*c2c66affSColin Finck     DestroyWindow(hTree);
631*c2c66affSColin Finck }
632*c2c66affSColin Finck 
633*c2c66affSColin Finck static void test_select(void)
634*c2c66affSColin Finck {
635*c2c66affSColin Finck     BOOL r;
636*c2c66affSColin Finck     HWND hTree;
637*c2c66affSColin Finck 
638*c2c66affSColin Finck     hTree = create_treeview_control(0);
639*c2c66affSColin Finck     fill_tree(hTree);
640*c2c66affSColin Finck 
641*c2c66affSColin Finck     /* root-none select tests */
642*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
643*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
644*c2c66affSColin Finck     expect(TRUE, r);
645*c2c66affSColin Finck     Clear();
646*c2c66affSColin Finck     AddItem('1');
647*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
648*c2c66affSColin Finck     expect(TRUE, r);
649*c2c66affSColin Finck     AddItem('2');
650*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
651*c2c66affSColin Finck     expect(TRUE, r);
652*c2c66affSColin Finck     AddItem('3');
653*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
654*c2c66affSColin Finck     expect(TRUE, r);
655*c2c66affSColin Finck     AddItem('4');
656*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
657*c2c66affSColin Finck     expect(TRUE, r);
658*c2c66affSColin Finck     AddItem('5');
659*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
660*c2c66affSColin Finck     expect(TRUE, r);
661*c2c66affSColin Finck     AddItem('.');
662*c2c66affSColin Finck     ok(!strcmp(sequence, "1(nR)nR23(Rn)Rn45(nR)nR."), "root-none select test\n");
663*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, rootnone_select_seq,
664*c2c66affSColin Finck                 "root-none select seq", FALSE);
665*c2c66affSColin Finck 
666*c2c66affSColin Finck     /* root-child select tests */
667*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
668*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
669*c2c66affSColin Finck     expect(TRUE, r);
670*c2c66affSColin Finck 
671*c2c66affSColin Finck     Clear();
672*c2c66affSColin Finck     AddItem('1');
673*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
674*c2c66affSColin Finck     expect(TRUE, r);
675*c2c66affSColin Finck     AddItem('2');
676*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
677*c2c66affSColin Finck     expect(TRUE, r);
678*c2c66affSColin Finck     AddItem('3');
679*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
680*c2c66affSColin Finck     expect(TRUE, r);
681*c2c66affSColin Finck     AddItem('4');
682*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
683*c2c66affSColin Finck     expect(TRUE, r);
684*c2c66affSColin Finck     AddItem('5');
685*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
686*c2c66affSColin Finck     expect(TRUE, r);
687*c2c66affSColin Finck     AddItem('.');
688*c2c66affSColin Finck     ok(!strcmp(sequence, "1(nR)nR23(RC)RC45(CR)CR."), "root-child select test\n");
689*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, rootchild_select_seq,
690*c2c66affSColin Finck                 "root-child select seq", FALSE);
691*c2c66affSColin Finck 
692*c2c66affSColin Finck     DestroyWindow(hTree);
693*c2c66affSColin Finck }
694*c2c66affSColin Finck 
695*c2c66affSColin Finck static void test_getitemtext(void)
696*c2c66affSColin Finck {
697*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
698*c2c66affSColin Finck     HTREEITEM hChild;
699*c2c66affSColin Finck     TVITEMA tvi;
700*c2c66affSColin Finck     HWND hTree;
701*c2c66affSColin Finck 
702*c2c66affSColin Finck     CHAR szBuffer[80] = "Blah";
703*c2c66affSColin Finck     int nBufferSize = sizeof(szBuffer)/sizeof(CHAR);
704*c2c66affSColin Finck 
705*c2c66affSColin Finck     hTree = create_treeview_control(0);
706*c2c66affSColin Finck     fill_tree(hTree);
707*c2c66affSColin Finck 
708*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
709*c2c66affSColin Finck 
710*c2c66affSColin Finck     /* add an item without TVIF_TEXT mask and pszText == NULL */
711*c2c66affSColin Finck     ins.hParent = hRoot;
712*c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
713*c2c66affSColin Finck     U(ins).item.mask = 0;
714*c2c66affSColin Finck     U(ins).item.pszText = NULL;
715*c2c66affSColin Finck     U(ins).item.cchTextMax = 0;
716*c2c66affSColin Finck     hChild = TreeView_InsertItemA(hTree, &ins);
717*c2c66affSColin Finck     ok(hChild != NULL, "failed to set hChild\n");
718*c2c66affSColin Finck 
719*c2c66affSColin Finck     /* retrieve it with TVIF_TEXT mask */
720*c2c66affSColin Finck     tvi.hItem = hChild;
721*c2c66affSColin Finck     tvi.mask = TVIF_TEXT;
722*c2c66affSColin Finck     tvi.cchTextMax = nBufferSize;
723*c2c66affSColin Finck     tvi.pszText = szBuffer;
724*c2c66affSColin Finck 
725*c2c66affSColin Finck     SendMessageA( hTree, TVM_GETITEMA, 0, (LPARAM)&tvi );
726*c2c66affSColin Finck     ok(!strcmp(szBuffer, ""), "szBuffer=\"%s\", expected \"\"\n", szBuffer);
727*c2c66affSColin Finck     ok(SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hChild), "DeleteItem failed\n");
728*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, getitemtext_seq, "get item text seq", FALSE);
729*c2c66affSColin Finck 
730*c2c66affSColin Finck     DestroyWindow(hTree);
731*c2c66affSColin Finck }
732*c2c66affSColin Finck 
733*c2c66affSColin Finck static void test_focus(void)
734*c2c66affSColin Finck {
735*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
736*c2c66affSColin Finck     static CHAR child1[]  = "Edit",
737*c2c66affSColin Finck                 child2[]  = "A really long string";
738*c2c66affSColin Finck     HTREEITEM hChild1, hChild2;
739*c2c66affSColin Finck     HWND hTree;
740*c2c66affSColin Finck     HWND hEdit;
741*c2c66affSColin Finck 
742*c2c66affSColin Finck     hTree = create_treeview_control(0);
743*c2c66affSColin Finck     fill_tree(hTree);
744*c2c66affSColin Finck 
745*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
746*c2c66affSColin Finck 
747*c2c66affSColin Finck     /* This test verifies that when a label is being edited, scrolling
748*c2c66affSColin Finck      * the treeview does not cause the label to lose focus. To test
749*c2c66affSColin Finck      * this, first some additional entries are added to generate
750*c2c66affSColin Finck      * scrollbars.
751*c2c66affSColin Finck      */
752*c2c66affSColin Finck     ins.hParent = hRoot;
753*c2c66affSColin Finck     ins.hInsertAfter = hChild;
754*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
755*c2c66affSColin Finck     U(ins).item.pszText = child1;
756*c2c66affSColin Finck     hChild1 = TreeView_InsertItemA(hTree, &ins);
757*c2c66affSColin Finck     ok(hChild1 != NULL, "failed to set hChild1\n");
758*c2c66affSColin Finck     ins.hInsertAfter = hChild1;
759*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
760*c2c66affSColin Finck     U(ins).item.pszText = child2;
761*c2c66affSColin Finck     hChild2 = TreeView_InsertItemA(hTree, &ins);
762*c2c66affSColin Finck     ok(hChild2 != NULL, "failed to set hChild2\n");
763*c2c66affSColin Finck 
764*c2c66affSColin Finck     ShowWindow(hMainWnd,SW_SHOW);
765*c2c66affSColin Finck     SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
766*c2c66affSColin Finck     hEdit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hChild);
767*c2c66affSColin Finck     ScrollWindowEx(hTree, -10, 0, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN);
768*c2c66affSColin Finck     ok(GetFocus() == hEdit, "Edit control should have focus\n");
769*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, focus_seq, "focus test", TRUE);
770*c2c66affSColin Finck 
771*c2c66affSColin Finck     DestroyWindow(hTree);
772*c2c66affSColin Finck }
773*c2c66affSColin Finck 
774*c2c66affSColin Finck static void test_get_set_bkcolor(void)
775*c2c66affSColin Finck {
776*c2c66affSColin Finck     COLORREF crColor;
777*c2c66affSColin Finck     HWND hTree;
778*c2c66affSColin Finck 
779*c2c66affSColin Finck     hTree = create_treeview_control(0);
780*c2c66affSColin Finck     fill_tree(hTree);
781*c2c66affSColin Finck 
782*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
783*c2c66affSColin Finck 
784*c2c66affSColin Finck     /* If the value is -1, the control is using the system color for the background color. */
785*c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETBKCOLOR, 0, 0);
786*c2c66affSColin Finck     ok(crColor == ~0u, "Default background color reported as 0x%.8x\n", crColor);
787*c2c66affSColin Finck 
788*c2c66affSColin Finck     /* Test for black background */
789*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETBKCOLOR, 0, RGB(0,0,0));
790*c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETBKCOLOR, 0, 0);
791*c2c66affSColin Finck     ok(crColor == RGB(0,0,0), "Black background color reported as 0x%.8x\n", crColor);
792*c2c66affSColin Finck 
793*c2c66affSColin Finck     /* Test for white background */
794*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETBKCOLOR, 0, RGB(255,255,255));
795*c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETBKCOLOR, 0, 0);
796*c2c66affSColin Finck     ok(crColor == RGB(255,255,255), "White background color reported as 0x%.8x\n", crColor);
797*c2c66affSColin Finck 
798*c2c66affSColin Finck     /* Reset the default background */
799*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETBKCOLOR, 0, -1);
800*c2c66affSColin Finck 
801*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_bkcolor_seq,
802*c2c66affSColin Finck         "test get set bkcolor", FALSE);
803*c2c66affSColin Finck 
804*c2c66affSColin Finck     DestroyWindow(hTree);
805*c2c66affSColin Finck }
806*c2c66affSColin Finck 
807*c2c66affSColin Finck static void test_get_set_imagelist(void)
808*c2c66affSColin Finck {
809*c2c66affSColin Finck     HIMAGELIST himl;
810*c2c66affSColin Finck     HWND hTree;
811*c2c66affSColin Finck 
812*c2c66affSColin Finck     hTree = create_treeview_control(0);
813*c2c66affSColin Finck     fill_tree(hTree);
814*c2c66affSColin Finck 
815*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
816*c2c66affSColin Finck 
817*c2c66affSColin Finck     /* Test a NULL HIMAGELIST */
818*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETIMAGELIST, TVSIL_NORMAL, 0);
819*c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_NORMAL, 0);
820*c2c66affSColin Finck     ok(himl == NULL, "NULL image list, reported as %p, expected 0.\n", himl);
821*c2c66affSColin Finck 
822*c2c66affSColin Finck     /* TODO: Test an actual image list */
823*c2c66affSColin Finck 
824*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_imagelist_seq,
825*c2c66affSColin Finck         "test get imagelist", FALSE);
826*c2c66affSColin Finck 
827*c2c66affSColin Finck     DestroyWindow(hTree);
828*c2c66affSColin Finck }
829*c2c66affSColin Finck 
830*c2c66affSColin Finck static void test_get_set_indent(void)
831*c2c66affSColin Finck {
832*c2c66affSColin Finck     int ulIndent;
833*c2c66affSColin Finck     int ulMinIndent;
834*c2c66affSColin Finck     int ulMoreThanTwiceMin;
835*c2c66affSColin Finck     HWND hTree;
836*c2c66affSColin Finck 
837*c2c66affSColin Finck     hTree = create_treeview_control(0);
838*c2c66affSColin Finck     fill_tree(hTree);
839*c2c66affSColin Finck 
840*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
841*c2c66affSColin Finck 
842*c2c66affSColin Finck     /* Finding the minimum indent */
843*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETINDENT, 0, 0);
844*c2c66affSColin Finck     ulMinIndent = SendMessageA(hTree, TVM_GETINDENT, 0, 0);
845*c2c66affSColin Finck 
846*c2c66affSColin Finck     /* Checking an indent that is more than twice the default indent */
847*c2c66affSColin Finck     ulMoreThanTwiceMin = 2*ulMinIndent+1;
848*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETINDENT, ulMoreThanTwiceMin, 0);
849*c2c66affSColin Finck     ulIndent = SendMessageA(hTree, TVM_GETINDENT, 0, 0);
850*c2c66affSColin Finck     ok(ulIndent == ulMoreThanTwiceMin, "Indent reported as %d, expected %d\n", ulIndent, ulMoreThanTwiceMin);
851*c2c66affSColin Finck 
852*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_indent_seq,
853*c2c66affSColin Finck         "test get set indent", FALSE);
854*c2c66affSColin Finck 
855*c2c66affSColin Finck     DestroyWindow(hTree);
856*c2c66affSColin Finck }
857*c2c66affSColin Finck 
858*c2c66affSColin Finck static void test_get_set_insertmark(void)
859*c2c66affSColin Finck {
860*c2c66affSColin Finck     COLORREF crColor = RGB(0,0,0);
861*c2c66affSColin Finck     HWND hTree;
862*c2c66affSColin Finck 
863*c2c66affSColin Finck     hTree = create_treeview_control(0);
864*c2c66affSColin Finck     fill_tree(hTree);
865*c2c66affSColin Finck 
866*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
867*c2c66affSColin Finck 
868*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETINSERTMARKCOLOR, 0, crColor);
869*c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETINSERTMARKCOLOR, 0, 0);
870*c2c66affSColin Finck     ok(crColor == RGB(0,0,0), "Insert mark color reported as 0x%.8x, expected 0x00000000\n", crColor);
871*c2c66affSColin Finck 
872*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_insertmarkcolor_seq,
873*c2c66affSColin Finck         "test get set insertmark color", FALSE);
874*c2c66affSColin Finck 
875*c2c66affSColin Finck     DestroyWindow(hTree);
876*c2c66affSColin Finck }
877*c2c66affSColin Finck 
878*c2c66affSColin Finck static void test_get_set_item(void)
879*c2c66affSColin Finck {
880*c2c66affSColin Finck     TVITEMA tviRoot = {0};
881*c2c66affSColin Finck     int nBufferSize = 80;
882*c2c66affSColin Finck     char szBuffer[80] = {0};
883*c2c66affSColin Finck     HWND hTree, hTree2;
884*c2c66affSColin Finck     DWORD ret;
885*c2c66affSColin Finck 
886*c2c66affSColin Finck     hTree = create_treeview_control(0);
887*c2c66affSColin Finck     fill_tree(hTree);
888*c2c66affSColin Finck 
889*c2c66affSColin Finck     tviRoot.hItem = hRoot;
890*c2c66affSColin Finck     tviRoot.mask  = TVIF_STATE;
891*c2c66affSColin Finck     tviRoot.state = TVIS_FOCUSED;
892*c2c66affSColin Finck     tviRoot.stateMask = TVIS_FOCUSED;
893*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&tviRoot);
894*c2c66affSColin Finck     expect(TRUE, ret);
895*c2c66affSColin Finck 
896*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
897*c2c66affSColin Finck 
898*c2c66affSColin Finck     /* Test the root item, state is set even when not requested */
899*c2c66affSColin Finck     tviRoot.hItem = hRoot;
900*c2c66affSColin Finck     tviRoot.mask = TVIF_TEXT;
901*c2c66affSColin Finck     tviRoot.state = 0;
902*c2c66affSColin Finck     tviRoot.stateMask = 0;
903*c2c66affSColin Finck     tviRoot.cchTextMax = nBufferSize;
904*c2c66affSColin Finck     tviRoot.pszText = szBuffer;
905*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&tviRoot);
906*c2c66affSColin Finck     expect(TRUE, ret);
907*c2c66affSColin Finck     ok(!strcmp("Root", szBuffer), "GetItem: szBuffer=\"%s\", expected \"Root\"\n", szBuffer);
908*c2c66affSColin Finck     ok(tviRoot.state == TVIS_FOCUSED, "got 0x%0x\n", tviRoot.state);
909*c2c66affSColin Finck 
910*c2c66affSColin Finck     /* Change the root text */
911*c2c66affSColin Finck     lstrcpynA(szBuffer, "Testing123", nBufferSize);
912*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&tviRoot);
913*c2c66affSColin Finck     expect(TRUE, ret);
914*c2c66affSColin Finck     memset(szBuffer, 0, nBufferSize);
915*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&tviRoot);
916*c2c66affSColin Finck     expect(TRUE, ret);
917*c2c66affSColin Finck     ok(!strcmp("Testing123", szBuffer), "GetItem: szBuffer=\"%s\", expected \"Testing123\"\n", szBuffer);
918*c2c66affSColin Finck 
919*c2c66affSColin Finck     /* Reset the root text */
920*c2c66affSColin Finck     memset(szBuffer, 0, nBufferSize);
921*c2c66affSColin Finck     lstrcpynA(szBuffer, "Root", nBufferSize);
922*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&tviRoot);
923*c2c66affSColin Finck     expect(TRUE, ret);
924*c2c66affSColin Finck 
925*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_item_seq,
926*c2c66affSColin Finck         "test get set item", FALSE);
927*c2c66affSColin Finck 
928*c2c66affSColin Finck     /* get item from a different tree */
929*c2c66affSColin Finck     hTree2 = create_treeview_control(0);
930*c2c66affSColin Finck 
931*c2c66affSColin Finck     tviRoot.hItem = hRoot;
932*c2c66affSColin Finck     tviRoot.mask = TVIF_STATE;
933*c2c66affSColin Finck     tviRoot.state = 0;
934*c2c66affSColin Finck     ret = SendMessageA(hTree2, TVM_GETITEMA, 0, (LPARAM)&tviRoot);
935*c2c66affSColin Finck     expect(TRUE, ret);
936*c2c66affSColin Finck     ok(tviRoot.state == TVIS_FOCUSED, "got state 0x%0x\n", tviRoot.state);
937*c2c66affSColin Finck 
938*c2c66affSColin Finck     /* invalid item pointer, nt4 crashes here but later versions just return 0 */
939*c2c66affSColin Finck     tviRoot.hItem = (HTREEITEM)0xdeadbeef;
940*c2c66affSColin Finck     tviRoot.mask = TVIF_STATE;
941*c2c66affSColin Finck     tviRoot.state = 0;
942*c2c66affSColin Finck     ret = SendMessageA(hTree2, TVM_GETITEMA, 0, (LPARAM)&tviRoot);
943*c2c66affSColin Finck     expect(FALSE, ret);
944*c2c66affSColin Finck 
945*c2c66affSColin Finck     DestroyWindow(hTree);
946*c2c66affSColin Finck     DestroyWindow(hTree2);
947*c2c66affSColin Finck }
948*c2c66affSColin Finck 
949*c2c66affSColin Finck static void test_get_set_itemheight(void)
950*c2c66affSColin Finck {
951*c2c66affSColin Finck     int ulOldHeight = 0;
952*c2c66affSColin Finck     int ulNewHeight = 0;
953*c2c66affSColin Finck     HWND hTree;
954*c2c66affSColin Finck 
955*c2c66affSColin Finck     hTree = create_treeview_control(0);
956*c2c66affSColin Finck     fill_tree(hTree);
957*c2c66affSColin Finck 
958*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
959*c2c66affSColin Finck 
960*c2c66affSColin Finck     /* Assuming default height to begin with */
961*c2c66affSColin Finck     ulOldHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
962*c2c66affSColin Finck 
963*c2c66affSColin Finck     /* Explicitly setting and getting the default height */
964*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETITEMHEIGHT, -1, 0);
965*c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
966*c2c66affSColin Finck     ok(ulNewHeight == ulOldHeight, "Default height not set properly, reported %d, expected %d\n", ulNewHeight, ulOldHeight);
967*c2c66affSColin Finck 
968*c2c66affSColin Finck     /* Explicitly setting and getting the height of twice the normal */
969*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETITEMHEIGHT, 2*ulOldHeight, 0);
970*c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
971*c2c66affSColin Finck     ok(ulNewHeight == 2*ulOldHeight, "New height not set properly, reported %d, expected %d\n", ulNewHeight, 2*ulOldHeight);
972*c2c66affSColin Finck 
973*c2c66affSColin Finck     /* Assuming tree doesn't have TVS_NONEVENHEIGHT set, so a set of 9 will round down to 8 */
974*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETITEMHEIGHT, 9, 0);
975*c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
976*c2c66affSColin Finck     ok(ulNewHeight == 8, "Uneven height not set properly, reported %d, expected %d\n", ulNewHeight, 8);
977*c2c66affSColin Finck 
978*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_itemheight_seq,
979*c2c66affSColin Finck         "test get set item height", FALSE);
980*c2c66affSColin Finck 
981*c2c66affSColin Finck     /* without TVS_NONEVENHEIGHT */
982*c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) & ~TVS_NONEVENHEIGHT);
983*c2c66affSColin Finck     /* odd value */
984*c2c66affSColin Finck     ulOldHeight = SendMessageA(hTree, TVM_SETITEMHEIGHT, 3, 0);
985*c2c66affSColin Finck     ok(ulOldHeight == 8, "got %d, expected %d\n", ulOldHeight, 8);
986*c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
987*c2c66affSColin Finck     ok(ulNewHeight == 2, "got %d, expected %d\n", ulNewHeight, 2);
988*c2c66affSColin Finck 
989*c2c66affSColin Finck     ulOldHeight = SendMessageA(hTree, TVM_SETITEMHEIGHT, 4, 0);
990*c2c66affSColin Finck     ok(ulOldHeight == 2, "got %d, expected %d\n", ulOldHeight, 2);
991*c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
992*c2c66affSColin Finck     ok(ulNewHeight == 4, "got %d, expected %d\n", ulNewHeight, 4);
993*c2c66affSColin Finck 
994*c2c66affSColin Finck     /* with TVS_NONEVENHEIGHT */
995*c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_NONEVENHEIGHT);
996*c2c66affSColin Finck     /* odd value */
997*c2c66affSColin Finck     ulOldHeight = SendMessageA(hTree, TVM_SETITEMHEIGHT, 3, 0);
998*c2c66affSColin Finck     ok(ulOldHeight == 4, "got %d, expected %d\n", ulOldHeight, 4);
999*c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
1000*c2c66affSColin Finck     ok(ulNewHeight == 3, "got %d, expected %d\n", ulNewHeight, 3);
1001*c2c66affSColin Finck     /* even value */
1002*c2c66affSColin Finck     ulOldHeight = SendMessageA(hTree, TVM_SETITEMHEIGHT, 10, 0);
1003*c2c66affSColin Finck     ok(ulOldHeight == 3, "got %d, expected %d\n", ulOldHeight, 3);
1004*c2c66affSColin Finck     ulNewHeight = SendMessageA(hTree, TVM_GETITEMHEIGHT, 0, 0);
1005*c2c66affSColin Finck     ok(ulNewHeight == 10, "got %d, expected %d\n", ulNewHeight, 10);
1006*c2c66affSColin Finck 
1007*c2c66affSColin Finck     DestroyWindow(hTree);
1008*c2c66affSColin Finck }
1009*c2c66affSColin Finck 
1010*c2c66affSColin Finck static void test_get_set_scrolltime(void)
1011*c2c66affSColin Finck {
1012*c2c66affSColin Finck     int ulExpectedTime = 20;
1013*c2c66affSColin Finck     int ulTime = 0;
1014*c2c66affSColin Finck     HWND hTree;
1015*c2c66affSColin Finck 
1016*c2c66affSColin Finck     hTree = create_treeview_control(0);
1017*c2c66affSColin Finck     fill_tree(hTree);
1018*c2c66affSColin Finck 
1019*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1020*c2c66affSColin Finck 
1021*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETSCROLLTIME, ulExpectedTime, 0);
1022*c2c66affSColin Finck     ulTime = SendMessageA(hTree, TVM_GETSCROLLTIME, 0, 0);
1023*c2c66affSColin Finck     ok(ulTime == ulExpectedTime, "Scroll time reported as %d, expected %d\n", ulTime, ulExpectedTime);
1024*c2c66affSColin Finck 
1025*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_scrolltime_seq,
1026*c2c66affSColin Finck         "test get set scroll time", FALSE);
1027*c2c66affSColin Finck 
1028*c2c66affSColin Finck     DestroyWindow(hTree);
1029*c2c66affSColin Finck }
1030*c2c66affSColin Finck 
1031*c2c66affSColin Finck static void test_get_set_textcolor(void)
1032*c2c66affSColin Finck {
1033*c2c66affSColin Finck     /* If the value is -1, the control is using the system color for the text color. */
1034*c2c66affSColin Finck     COLORREF crColor;
1035*c2c66affSColin Finck     HWND hTree;
1036*c2c66affSColin Finck 
1037*c2c66affSColin Finck     hTree = create_treeview_control(0);
1038*c2c66affSColin Finck     fill_tree(hTree);
1039*c2c66affSColin Finck 
1040*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1041*c2c66affSColin Finck 
1042*c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETTEXTCOLOR, 0, 0);
1043*c2c66affSColin Finck     ok(crColor == ~0u, "Default text color reported as 0x%.8x\n", crColor);
1044*c2c66affSColin Finck 
1045*c2c66affSColin Finck     /* Test for black text */
1046*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETTEXTCOLOR, 0, RGB(0,0,0));
1047*c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETTEXTCOLOR, 0, 0);
1048*c2c66affSColin Finck     ok(crColor == RGB(0,0,0), "Black text color reported as 0x%.8x\n", crColor);
1049*c2c66affSColin Finck 
1050*c2c66affSColin Finck     /* Test for white text */
1051*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETTEXTCOLOR, 0, RGB(255,255,255));
1052*c2c66affSColin Finck     crColor = SendMessageA(hTree, TVM_GETTEXTCOLOR, 0, 0);
1053*c2c66affSColin Finck     ok(crColor == RGB(255,255,255), "White text color reported as 0x%.8x\n", crColor);
1054*c2c66affSColin Finck 
1055*c2c66affSColin Finck     /* Reset the default text color */
1056*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETTEXTCOLOR, 0, CLR_NONE);
1057*c2c66affSColin Finck 
1058*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_textcolor_seq,
1059*c2c66affSColin Finck         "test get set text color", FALSE);
1060*c2c66affSColin Finck 
1061*c2c66affSColin Finck     DestroyWindow(hTree);
1062*c2c66affSColin Finck }
1063*c2c66affSColin Finck 
1064*c2c66affSColin Finck static void test_get_set_tooltips(void)
1065*c2c66affSColin Finck {
1066*c2c66affSColin Finck     HWND hwndLastToolTip = NULL;
1067*c2c66affSColin Finck     HWND hPopupTreeView;
1068*c2c66affSColin Finck     HWND hTree;
1069*c2c66affSColin Finck 
1070*c2c66affSColin Finck     hTree = create_treeview_control(0);
1071*c2c66affSColin Finck     fill_tree(hTree);
1072*c2c66affSColin Finck 
1073*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1074*c2c66affSColin Finck 
1075*c2c66affSColin Finck     /* show even WS_POPUP treeview don't send NM_TOOLTIPSCREATED */
1076*c2c66affSColin Finck     hPopupTreeView = CreateWindowA(WC_TREEVIEWA, NULL, WS_POPUP|WS_VISIBLE, 0, 0, 100, 100,
1077*c2c66affSColin Finck             hMainWnd, NULL, NULL, NULL);
1078*c2c66affSColin Finck     DestroyWindow(hPopupTreeView);
1079*c2c66affSColin Finck 
1080*c2c66affSColin Finck     /* Testing setting a NULL ToolTip */
1081*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETTOOLTIPS, 0, 0);
1082*c2c66affSColin Finck     hwndLastToolTip = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
1083*c2c66affSColin Finck     ok(hwndLastToolTip == NULL, "NULL tool tip, reported as 0x%p, expected 0.\n", hwndLastToolTip);
1084*c2c66affSColin Finck 
1085*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_tooltips_seq,
1086*c2c66affSColin Finck         "test get set tooltips", TRUE);
1087*c2c66affSColin Finck 
1088*c2c66affSColin Finck     /* TODO: Add a test of an actual tooltip */
1089*c2c66affSColin Finck     DestroyWindow(hTree);
1090*c2c66affSColin Finck }
1091*c2c66affSColin Finck 
1092*c2c66affSColin Finck static void test_get_set_unicodeformat(void)
1093*c2c66affSColin Finck {
1094*c2c66affSColin Finck     BOOL bPreviousSetting;
1095*c2c66affSColin Finck     BOOL bNewSetting;
1096*c2c66affSColin Finck     HWND hTree;
1097*c2c66affSColin Finck 
1098*c2c66affSColin Finck     hTree = create_treeview_control(0);
1099*c2c66affSColin Finck     fill_tree(hTree);
1100*c2c66affSColin Finck 
1101*c2c66affSColin Finck     /* Check that an invalid format returned by NF_QUERY defaults to ANSI */
1102*c2c66affSColin Finck     bPreviousSetting = SendMessageA(hTree, TVM_GETUNICODEFORMAT, 0, 0);
1103*c2c66affSColin Finck     ok(bPreviousSetting == FALSE, "Format should be ANSI.\n");
1104*c2c66affSColin Finck 
1105*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1106*c2c66affSColin Finck 
1107*c2c66affSColin Finck     /* Set to Unicode */
1108*c2c66affSColin Finck     bPreviousSetting = SendMessageA(hTree, TVM_SETUNICODEFORMAT, 1, 0);
1109*c2c66affSColin Finck     bNewSetting = SendMessageA(hTree, TVM_GETUNICODEFORMAT, 0, 0);
1110*c2c66affSColin Finck     ok(bNewSetting == TRUE, "Unicode setting did not work.\n");
1111*c2c66affSColin Finck 
1112*c2c66affSColin Finck     /* Set to ANSI */
1113*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETUNICODEFORMAT, 0, 0);
1114*c2c66affSColin Finck     bNewSetting = SendMessageA(hTree, TVM_GETUNICODEFORMAT, 0, 0);
1115*c2c66affSColin Finck     ok(bNewSetting == FALSE, "ANSI setting did not work.\n");
1116*c2c66affSColin Finck 
1117*c2c66affSColin Finck     /* Revert to original setting */
1118*c2c66affSColin Finck     SendMessageA(hTree, TVM_SETUNICODEFORMAT, bPreviousSetting, 0);
1119*c2c66affSColin Finck 
1120*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_unicodeformat_seq,
1121*c2c66affSColin Finck         "test get set unicode format", FALSE);
1122*c2c66affSColin Finck 
1123*c2c66affSColin Finck     DestroyWindow(hTree);
1124*c2c66affSColin Finck }
1125*c2c66affSColin Finck 
1126*c2c66affSColin Finck static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1127*c2c66affSColin Finck {
1128*c2c66affSColin Finck     static LONG defwndproc_counter = 0;
1129*c2c66affSColin Finck     struct message msg = { 0 };
1130*c2c66affSColin Finck     LRESULT ret;
1131*c2c66affSColin Finck     RECT rect;
1132*c2c66affSColin Finck     HTREEITEM visibleItem;
1133*c2c66affSColin Finck 
1134*c2c66affSColin Finck     msg.message = message;
1135*c2c66affSColin Finck     msg.flags = sent|wparam|lparam;
1136*c2c66affSColin Finck     if (defwndproc_counter) msg.flags |= defwinproc;
1137*c2c66affSColin Finck     msg.wParam = wParam;
1138*c2c66affSColin Finck     msg.lParam = lParam;
1139*c2c66affSColin Finck     if (message == WM_NOTIFY && lParam)
1140*c2c66affSColin Finck         msg.id = ((NMHDR*)lParam)->code;
1141*c2c66affSColin Finck 
1142*c2c66affSColin Finck     /* log system messages, except for painting */
1143*c2c66affSColin Finck     if (message < WM_USER &&
1144*c2c66affSColin Finck         message != WM_PAINT &&
1145*c2c66affSColin Finck         message != WM_ERASEBKGND &&
1146*c2c66affSColin Finck         message != WM_NCPAINT &&
1147*c2c66affSColin Finck         message != WM_NCHITTEST &&
1148*c2c66affSColin Finck         message != WM_GETTEXT &&
1149*c2c66affSColin Finck         message != WM_GETICON &&
1150*c2c66affSColin Finck         message != WM_DEVICECHANGE)
1151*c2c66affSColin Finck     {
1152*c2c66affSColin Finck         add_message(sequences, PARENT_SEQ_INDEX, &msg);
1153*c2c66affSColin Finck     }
1154*c2c66affSColin Finck 
1155*c2c66affSColin Finck     switch(message) {
1156*c2c66affSColin Finck     case WM_NOTIFYFORMAT:
1157*c2c66affSColin Finck     {
1158*c2c66affSColin Finck         /* Make NF_QUERY return an invalid format to show that it defaults to ANSI */
1159*c2c66affSColin Finck         if (lParam == NF_QUERY) return 0;
1160*c2c66affSColin Finck         break;
1161*c2c66affSColin Finck     }
1162*c2c66affSColin Finck 
1163*c2c66affSColin Finck     case WM_NOTIFY:
1164*c2c66affSColin Finck     {
1165*c2c66affSColin Finck         NMHDR *pHdr = (NMHDR *)lParam;
1166*c2c66affSColin Finck 
1167*c2c66affSColin Finck         ok(pHdr->code != NM_TOOLTIPSCREATED, "Treeview should not send NM_TOOLTIPSCREATED\n");
1168*c2c66affSColin Finck         if (pHdr->idFrom == 100)
1169*c2c66affSColin Finck         {
1170*c2c66affSColin Finck             NMTREEVIEWA *pTreeView = (LPNMTREEVIEWA) lParam;
1171*c2c66affSColin Finck             switch(pHdr->code)
1172*c2c66affSColin Finck             {
1173*c2c66affSColin Finck             case TVN_SELCHANGINGA:
1174*c2c66affSColin Finck                 AddItem('(');
1175*c2c66affSColin Finck                 IdentifyItem(pTreeView->itemOld.hItem);
1176*c2c66affSColin Finck                 IdentifyItem(pTreeView->itemNew.hItem);
1177*c2c66affSColin Finck                 break;
1178*c2c66affSColin Finck             case TVN_SELCHANGEDA:
1179*c2c66affSColin Finck                 AddItem(')');
1180*c2c66affSColin Finck                 IdentifyItem(pTreeView->itemOld.hItem);
1181*c2c66affSColin Finck                 IdentifyItem(pTreeView->itemNew.hItem);
1182*c2c66affSColin Finck                 break;
1183*c2c66affSColin Finck             case TVN_GETDISPINFOA: {
1184*c2c66affSColin Finck                 NMTVDISPINFOA *disp = (NMTVDISPINFOA *)lParam;
1185*c2c66affSColin Finck                 if (disp->item.mask & TVIF_TEXT) {
1186*c2c66affSColin Finck                     lstrcpynA(disp->item.pszText, TEST_CALLBACK_TEXT, disp->item.cchTextMax);
1187*c2c66affSColin Finck                 }
1188*c2c66affSColin Finck 
1189*c2c66affSColin Finck                 if (g_disp_A_to_W && (disp->item.mask & TVIF_TEXT)) {
1190*c2c66affSColin Finck                     static const WCHAR testW[] = {'T','E','S','T','2',0};
1191*c2c66affSColin Finck 
1192*c2c66affSColin Finck                     disp->hdr.code = TVN_GETDISPINFOW;
1193*c2c66affSColin Finck                     memcpy(disp->item.pszText, testW, sizeof(testW));
1194*c2c66affSColin Finck                 }
1195*c2c66affSColin Finck 
1196*c2c66affSColin Finck                 if (g_disp_set_stateimage)
1197*c2c66affSColin Finck                 {
1198*c2c66affSColin Finck                     ok(disp->item.mask == TVIF_IMAGE, "got %x\n", disp->item.mask);
1199*c2c66affSColin Finck                     /* both masks set here are necessary to change state bits */
1200*c2c66affSColin Finck                     disp->item.mask |= TVIF_STATE;
1201*c2c66affSColin Finck                     disp->item.state = TVIS_SELECTED | INDEXTOSTATEIMAGEMASK(2) | INDEXTOOVERLAYMASK(3);
1202*c2c66affSColin Finck                     disp->item.stateMask = TVIS_SELECTED | TVIS_OVERLAYMASK | TVIS_STATEIMAGEMASK;
1203*c2c66affSColin Finck                 }
1204*c2c66affSColin Finck 
1205*c2c66affSColin Finck                 break;
1206*c2c66affSColin Finck               }
1207*c2c66affSColin Finck             case TVN_BEGINLABELEDITA:
1208*c2c66affSColin Finck               {
1209*c2c66affSColin Finck                 if (g_beginedit_alter_text)
1210*c2c66affSColin Finck                 {
1211*c2c66affSColin Finck                     static const char* textA = "<edittextaltered>";
1212*c2c66affSColin Finck                     HWND edit;
1213*c2c66affSColin Finck 
1214*c2c66affSColin Finck                     edit = (HWND)SendMessageA(pHdr->hwndFrom, TVM_GETEDITCONTROL, 0, 0);
1215*c2c66affSColin Finck                     ok(IsWindow(edit), "failed to get edit handle\n");
1216*c2c66affSColin Finck                     SetWindowTextA(edit, textA);
1217*c2c66affSColin Finck                 }
1218*c2c66affSColin Finck 
1219*c2c66affSColin Finck                 break;
1220*c2c66affSColin Finck               }
1221*c2c66affSColin Finck 
1222*c2c66affSColin Finck             case TVN_ENDLABELEDITA: return TRUE;
1223*c2c66affSColin Finck             case TVN_ITEMEXPANDINGA:
1224*c2c66affSColin Finck               {
1225*c2c66affSColin Finck                 UINT newmask = pTreeView->itemNew.mask & ~TVIF_CHILDREN;
1226*c2c66affSColin Finck                 ok(newmask ==
1227*c2c66affSColin Finck                    (TVIF_HANDLE | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_PARAM | TVIF_STATE),
1228*c2c66affSColin Finck                    "got wrong mask %x\n", pTreeView->itemNew.mask);
1229*c2c66affSColin Finck                 ok(pTreeView->itemOld.mask == 0,
1230*c2c66affSColin Finck                    "got wrong mask %x\n", pTreeView->itemOld.mask);
1231*c2c66affSColin Finck 
1232*c2c66affSColin Finck                 if (g_get_from_expand)
1233*c2c66affSColin Finck                 {
1234*c2c66affSColin Finck                   g_item_expanding.mask = TVIF_STATE;
1235*c2c66affSColin Finck                   g_item_expanding.hItem = hRoot;
1236*c2c66affSColin Finck                   ret = SendMessageA(pHdr->hwndFrom, TVM_GETITEMA, 0, (LPARAM)&g_item_expanding);
1237*c2c66affSColin Finck                   ok(ret == TRUE, "got %lu\n", ret);
1238*c2c66affSColin Finck                 }
1239*c2c66affSColin Finck                 break;
1240*c2c66affSColin Finck               }
1241*c2c66affSColin Finck             case TVN_ITEMEXPANDEDA:
1242*c2c66affSColin Finck                 ok(pTreeView->itemNew.mask & TVIF_STATE, "got wrong mask %x\n", pTreeView->itemNew.mask);
1243*c2c66affSColin Finck                 ok(pTreeView->itemNew.state & (TVIS_EXPANDED|TVIS_EXPANDEDONCE),
1244*c2c66affSColin Finck                    "got wrong mask %x\n", pTreeView->itemNew.mask);
1245*c2c66affSColin Finck                 ok(pTreeView->itemOld.mask == 0,
1246*c2c66affSColin Finck                    "got wrong mask %x\n", pTreeView->itemOld.mask);
1247*c2c66affSColin Finck 
1248*c2c66affSColin Finck                 if (g_get_from_expand)
1249*c2c66affSColin Finck                 {
1250*c2c66affSColin Finck                   g_item_expanded.mask = TVIF_STATE;
1251*c2c66affSColin Finck                   g_item_expanded.hItem = hRoot;
1252*c2c66affSColin Finck                   ret = SendMessageA(pHdr->hwndFrom, TVM_GETITEMA, 0, (LPARAM)&g_item_expanded);
1253*c2c66affSColin Finck                   ok(ret == TRUE, "got %lu\n", ret);
1254*c2c66affSColin Finck                 }
1255*c2c66affSColin Finck                 if (g_get_rect_in_expand)
1256*c2c66affSColin Finck                 {
1257*c2c66affSColin Finck                   visibleItem = (HTREEITEM)SendMessageA(pHdr->hwndFrom, TVM_GETNEXTITEM,
1258*c2c66affSColin Finck                           TVGN_FIRSTVISIBLE, 0);
1259*c2c66affSColin Finck                   ok(pTreeView->itemNew.hItem == visibleItem, "expanded item == first visible item\n");
1260*c2c66affSColin Finck                   *(HTREEITEM*)&rect = visibleItem;
1261*c2c66affSColin Finck                   ok(SendMessageA(pHdr->hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rect),
1262*c2c66affSColin Finck                           "Failed to get rect for first visible item.\n");
1263*c2c66affSColin Finck                   visibleItem = (HTREEITEM)SendMessageA(pHdr->hwndFrom, TVM_GETNEXTITEM,
1264*c2c66affSColin Finck                           TVGN_NEXTVISIBLE, (LPARAM)visibleItem);
1265*c2c66affSColin Finck                   *(HTREEITEM*)&rect = visibleItem;
1266*c2c66affSColin Finck                   ok(visibleItem != NULL, "There must be a visible item after the first visisble item.\n");
1267*c2c66affSColin Finck                   ok(SendMessageA(pHdr->hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rect),
1268*c2c66affSColin Finck                           "Failed to get rect for second visible item.\n");
1269*c2c66affSColin Finck                 }
1270*c2c66affSColin Finck                 break;
1271*c2c66affSColin Finck             case TVN_DELETEITEMA:
1272*c2c66affSColin Finck             {
1273*c2c66affSColin Finck                 struct message item;
1274*c2c66affSColin Finck 
1275*c2c66affSColin Finck                 ok(pTreeView->itemNew.mask == 0, "got wrong mask 0x%x\n", pTreeView->itemNew.mask);
1276*c2c66affSColin Finck 
1277*c2c66affSColin Finck                 ok(pTreeView->itemOld.mask == (TVIF_HANDLE | TVIF_PARAM), "got wrong mask 0x%x\n", pTreeView->itemOld.mask);
1278*c2c66affSColin Finck                 ok(pTreeView->itemOld.hItem != NULL, "got %p\n", pTreeView->itemOld.hItem);
1279*c2c66affSColin Finck 
1280*c2c66affSColin Finck                 memset(&item, 0, sizeof(item));
1281*c2c66affSColin Finck                 item.lParam = (LPARAM)pTreeView->itemOld.hItem;
1282*c2c66affSColin Finck                 add_message(item_sequence, 0, &item);
1283*c2c66affSColin Finck 
1284*c2c66affSColin Finck                 break;
1285*c2c66affSColin Finck             }
1286*c2c66affSColin Finck             case NM_CUSTOMDRAW:
1287*c2c66affSColin Finck             {
1288*c2c66affSColin Finck                 NMTVCUSTOMDRAW *nmcd = (NMTVCUSTOMDRAW*)lParam;
1289*c2c66affSColin Finck                 COLORREF c0ffee = RGB(0xc0,0xff,0xee), cafe = RGB(0xca,0xfe,0x00);
1290*c2c66affSColin Finck                 COLORREF text = GetTextColor(nmcd->nmcd.hdc), bkgnd = GetBkColor(nmcd->nmcd.hdc);
1291*c2c66affSColin Finck 
1292*c2c66affSColin Finck                 msg.flags |= custdraw;
1293*c2c66affSColin Finck                 msg.stage = nmcd->nmcd.dwDrawStage;
1294*c2c66affSColin Finck                 add_message(sequences, PARENT_CD_SEQ_INDEX, &msg);
1295*c2c66affSColin Finck 
1296*c2c66affSColin Finck                 switch (msg.stage)
1297*c2c66affSColin Finck                 {
1298*c2c66affSColin Finck                 case CDDS_PREPAINT:
1299*c2c66affSColin Finck                     return CDRF_NOTIFYITEMDRAW|CDRF_NOTIFYITEMERASE|CDRF_NOTIFYPOSTPAINT;
1300*c2c66affSColin Finck                 case CDDS_ITEMPREPAINT:
1301*c2c66affSColin Finck                     ok(text == nmcd->clrText || (g_v6 && nmcd->clrText == 0xffffffff),
1302*c2c66affSColin Finck                        "got %08x vs %08x\n", text, nmcd->clrText);
1303*c2c66affSColin Finck                     ok(bkgnd == nmcd->clrTextBk || (g_v6 && nmcd->clrTextBk == 0xffffffff),
1304*c2c66affSColin Finck                        "got %08x vs %08x\n", bkgnd, nmcd->clrTextBk);
1305*c2c66affSColin Finck                     nmcd->clrText = cafe;
1306*c2c66affSColin Finck                     nmcd->clrTextBk = c0ffee;
1307*c2c66affSColin Finck                     SetTextColor(nmcd->nmcd.hdc, c0ffee);
1308*c2c66affSColin Finck                     SetBkColor(nmcd->nmcd.hdc, cafe);
1309*c2c66affSColin Finck                     if (g_customdraw_font)
1310*c2c66affSColin Finck                         SelectObject(nmcd->nmcd.hdc, g_customdraw_font);
1311*c2c66affSColin Finck                     return CDRF_NOTIFYPOSTPAINT|CDRF_NEWFONT;
1312*c2c66affSColin Finck                 case CDDS_ITEMPOSTPAINT:
1313*c2c66affSColin Finck                     /* at the point of post paint notification colors are already restored */
1314*c2c66affSColin Finck                     ok(nmcd->clrText == cafe, "got 0%x\n", nmcd->clrText);
1315*c2c66affSColin Finck                     ok(nmcd->clrTextBk == c0ffee, "got 0%x\n", nmcd->clrTextBk);
1316*c2c66affSColin Finck                     ok(text != cafe, "got 0%x\n", text);
1317*c2c66affSColin Finck                     ok(bkgnd != c0ffee, "got 0%x\n", bkgnd);
1318*c2c66affSColin Finck                     if (g_customdraw_font)
1319*c2c66affSColin Finck                         ok(GetCurrentObject(nmcd->nmcd.hdc, OBJ_FONT) != g_customdraw_font, "got %p\n",
1320*c2c66affSColin Finck                            GetCurrentObject(nmcd->nmcd.hdc, OBJ_FONT));
1321*c2c66affSColin Finck                     break;
1322*c2c66affSColin Finck                 default:
1323*c2c66affSColin Finck                     ;
1324*c2c66affSColin Finck                 }
1325*c2c66affSColin Finck                 break;
1326*c2c66affSColin Finck             }
1327*c2c66affSColin Finck             case NM_RCLICK:
1328*c2c66affSColin Finck             {
1329*c2c66affSColin Finck                 HTREEITEM selected = (HTREEITEM)SendMessageA(((NMHDR *)lParam)->hwndFrom,
1330*c2c66affSColin Finck                                                              TVM_GETNEXTITEM, TVGN_CARET, 0);
1331*c2c66affSColin Finck                 ok(selected == hChild, "child item should still be selected\n");
1332*c2c66affSColin Finck                 break;
1333*c2c66affSColin Finck             }
1334*c2c66affSColin Finck             }
1335*c2c66affSColin Finck         }
1336*c2c66affSColin Finck         break;
1337*c2c66affSColin Finck     }
1338*c2c66affSColin Finck 
1339*c2c66affSColin Finck     case WM_DESTROY:
1340*c2c66affSColin Finck         PostQuitMessage(0);
1341*c2c66affSColin Finck         break;
1342*c2c66affSColin Finck     }
1343*c2c66affSColin Finck 
1344*c2c66affSColin Finck     defwndproc_counter++;
1345*c2c66affSColin Finck     ret = DefWindowProcA(hWnd, message, wParam, lParam);
1346*c2c66affSColin Finck     defwndproc_counter--;
1347*c2c66affSColin Finck 
1348*c2c66affSColin Finck     return ret;
1349*c2c66affSColin Finck }
1350*c2c66affSColin Finck 
1351*c2c66affSColin Finck static void test_expandinvisible(void)
1352*c2c66affSColin Finck {
1353*c2c66affSColin Finck     static CHAR nodeText[][5] = {"0", "1", "2", "3", "4"};
1354*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
1355*c2c66affSColin Finck     HTREEITEM node[5];
1356*c2c66affSColin Finck     RECT dummyRect;
1357*c2c66affSColin Finck     BOOL nodeVisible;
1358*c2c66affSColin Finck     LRESULT ret;
1359*c2c66affSColin Finck     HWND hTree;
1360*c2c66affSColin Finck 
1361*c2c66affSColin Finck     hTree = create_treeview_control(0);
1362*c2c66affSColin Finck 
1363*c2c66affSColin Finck     /* The test builds the following tree and expands node 1, while node 0 is collapsed.
1364*c2c66affSColin Finck      *
1365*c2c66affSColin Finck      * 0
1366*c2c66affSColin Finck      * |- 1
1367*c2c66affSColin Finck      * |  |- 2
1368*c2c66affSColin Finck      * |  |- 3
1369*c2c66affSColin Finck      * |- 4
1370*c2c66affSColin Finck      *
1371*c2c66affSColin Finck      */
1372*c2c66affSColin Finck 
1373*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
1374*c2c66affSColin Finck     ok(ret == TRUE, "ret\n");
1375*c2c66affSColin Finck     ins.hParent = TVI_ROOT;
1376*c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
1377*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
1378*c2c66affSColin Finck     U(ins).item.pszText = nodeText[0];
1379*c2c66affSColin Finck     node[0] = TreeView_InsertItemA(hTree, &ins);
1380*c2c66affSColin Finck     ok(node[0] != NULL, "failed to set node[0]\n");
1381*c2c66affSColin Finck 
1382*c2c66affSColin Finck     ins.hInsertAfter = TVI_LAST;
1383*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
1384*c2c66affSColin Finck     ins.hParent = node[0];
1385*c2c66affSColin Finck 
1386*c2c66affSColin Finck     U(ins).item.pszText = nodeText[1];
1387*c2c66affSColin Finck     node[1] = TreeView_InsertItemA(hTree, &ins);
1388*c2c66affSColin Finck     ok(node[1] != NULL, "failed to set node[1]\n");
1389*c2c66affSColin Finck     U(ins).item.pszText = nodeText[4];
1390*c2c66affSColin Finck     node[4] = TreeView_InsertItemA(hTree, &ins);
1391*c2c66affSColin Finck     ok(node[4] != NULL, "failed to set node[4]\n");
1392*c2c66affSColin Finck 
1393*c2c66affSColin Finck     ins.hParent = node[1];
1394*c2c66affSColin Finck 
1395*c2c66affSColin Finck     U(ins).item.pszText = nodeText[2];
1396*c2c66affSColin Finck     node[2] = TreeView_InsertItemA(hTree, &ins);
1397*c2c66affSColin Finck     ok(node[2] != NULL, "failed to set node[2]\n");
1398*c2c66affSColin Finck     U(ins).item.pszText = nodeText[3];
1399*c2c66affSColin Finck     node[3] = TreeView_InsertItemA(hTree, &ins);
1400*c2c66affSColin Finck     ok(node[3] != NULL, "failed to set node[3]\n");
1401*c2c66affSColin Finck 
1402*c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[1];
1403*c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1404*c2c66affSColin Finck     ok(!nodeVisible, "Node 1 should not be visible.\n");
1405*c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[2];
1406*c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1407*c2c66affSColin Finck     ok(!nodeVisible, "Node 2 should not be visible.\n");
1408*c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[3];
1409*c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1410*c2c66affSColin Finck     ok(!nodeVisible, "Node 3 should not be visible.\n");
1411*c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[4];
1412*c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1413*c2c66affSColin Finck     ok(!nodeVisible, "Node 4 should not be visible.\n");
1414*c2c66affSColin Finck 
1415*c2c66affSColin Finck     ok(SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)node[1]), "Expand of node 1 failed.\n");
1416*c2c66affSColin Finck 
1417*c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[1];
1418*c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1419*c2c66affSColin Finck     ok(!nodeVisible, "Node 1 should not be visible.\n");
1420*c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[2];
1421*c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1422*c2c66affSColin Finck     ok(!nodeVisible, "Node 2 should not be visible.\n");
1423*c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[3];
1424*c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1425*c2c66affSColin Finck     ok(!nodeVisible, "Node 3 should not be visible.\n");
1426*c2c66affSColin Finck     *(HTREEITEM *)&dummyRect = node[4];
1427*c2c66affSColin Finck     nodeVisible = SendMessageA(hTree, TVM_GETITEMRECT, FALSE, (LPARAM)&dummyRect);
1428*c2c66affSColin Finck     ok(!nodeVisible, "Node 4 should not be visible.\n");
1429*c2c66affSColin Finck 
1430*c2c66affSColin Finck     DestroyWindow(hTree);
1431*c2c66affSColin Finck }
1432*c2c66affSColin Finck 
1433*c2c66affSColin Finck static void test_itemedit(void)
1434*c2c66affSColin Finck {
1435*c2c66affSColin Finck     DWORD r;
1436*c2c66affSColin Finck     HWND edit;
1437*c2c66affSColin Finck     TVITEMA item;
1438*c2c66affSColin Finck     CHAR buffA[20];
1439*c2c66affSColin Finck     HWND hTree;
1440*c2c66affSColin Finck 
1441*c2c66affSColin Finck     hTree = create_treeview_control(0);
1442*c2c66affSColin Finck     fill_tree(hTree);
1443*c2c66affSColin Finck 
1444*c2c66affSColin Finck     /* try with null item */
1445*c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, 0);
1446*c2c66affSColin Finck     ok(!IsWindow(edit), "Expected valid handle\n");
1447*c2c66affSColin Finck 
1448*c2c66affSColin Finck     /* trigger edit */
1449*c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1450*c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1451*c2c66affSColin Finck     /* item shouldn't be selected automatically after TVM_EDITLABELA */
1452*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_GETITEMSTATE, (WPARAM)hRoot, TVIS_SELECTED);
1453*c2c66affSColin Finck     expect(0, r);
1454*c2c66affSColin Finck     /* try to cancel with wrong edit handle */
1455*c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), 0);
1456*c2c66affSColin Finck     expect(0, r);
1457*c2c66affSColin Finck     ok(IsWindow(edit), "Expected edit control to be valid\n");
1458*c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1459*c2c66affSColin Finck     expect(0, r);
1460*c2c66affSColin Finck     ok(!IsWindow(edit), "Expected edit control to be destroyed\n");
1461*c2c66affSColin Finck     /* try to cancel without creating edit */
1462*c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), 0);
1463*c2c66affSColin Finck     expect(0, r);
1464*c2c66affSColin Finck 
1465*c2c66affSColin Finck     /* try to cancel with wrong (not null) handle */
1466*c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1467*c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1468*c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hTree);
1469*c2c66affSColin Finck     expect(0, r);
1470*c2c66affSColin Finck     ok(IsWindow(edit), "Expected edit control to be valid\n");
1471*c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1472*c2c66affSColin Finck     expect(0, r);
1473*c2c66affSColin Finck 
1474*c2c66affSColin Finck     /* remove selection after starting edit */
1475*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
1476*c2c66affSColin Finck     expect(TRUE, r);
1477*c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1478*c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1479*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
1480*c2c66affSColin Finck     expect(TRUE, r);
1481*c2c66affSColin Finck     /* alter text */
1482*c2c66affSColin Finck     strcpy(buffA, "x");
1483*c2c66affSColin Finck     r = SendMessageA(edit, WM_SETTEXT, 0, (LPARAM)buffA);
1484*c2c66affSColin Finck     expect(TRUE, r);
1485*c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1486*c2c66affSColin Finck     expect(0, r);
1487*c2c66affSColin Finck     ok(!IsWindow(edit), "Expected edit control to be destroyed\n");
1488*c2c66affSColin Finck     /* check that text is saved */
1489*c2c66affSColin Finck     item.mask = TVIF_TEXT;
1490*c2c66affSColin Finck     item.hItem = hRoot;
1491*c2c66affSColin Finck     item.pszText = buffA;
1492*c2c66affSColin Finck     item.cchTextMax = sizeof(buffA)/sizeof(CHAR);
1493*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1494*c2c66affSColin Finck     expect(TRUE, r);
1495*c2c66affSColin Finck     ok(!strcmp("x", buffA), "Expected item text to change\n");
1496*c2c66affSColin Finck 
1497*c2c66affSColin Finck     /* try A/W messages */
1498*c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1499*c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1500*c2c66affSColin Finck     ok(IsWindowUnicode(edit), "got ansi window\n");
1501*c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1502*c2c66affSColin Finck     expect(0, r);
1503*c2c66affSColin Finck     ok(!IsWindow(edit), "expected invalid handle\n");
1504*c2c66affSColin Finck 
1505*c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELW, 0, (LPARAM)hRoot);
1506*c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1507*c2c66affSColin Finck     ok(IsWindowUnicode(edit), "got ansi window\n");
1508*c2c66affSColin Finck     r = SendMessageA(hTree, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)edit);
1509*c2c66affSColin Finck     expect(0, r);
1510*c2c66affSColin Finck 
1511*c2c66affSColin Finck     /* alter text during TVM_BEGINLABELEDIT, check that it's preserved */
1512*c2c66affSColin Finck     strcpy(buffA, "<root>");
1513*c2c66affSColin Finck 
1514*c2c66affSColin Finck     item.mask = TVIF_TEXT;
1515*c2c66affSColin Finck     item.hItem = hRoot;
1516*c2c66affSColin Finck     item.pszText = buffA;
1517*c2c66affSColin Finck     item.cchTextMax = 0;
1518*c2c66affSColin Finck     r = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
1519*c2c66affSColin Finck     expect(TRUE, r);
1520*c2c66affSColin Finck 
1521*c2c66affSColin Finck     g_beginedit_alter_text = TRUE;
1522*c2c66affSColin Finck     edit = (HWND)SendMessageA(hTree, TVM_EDITLABELA, 0, (LPARAM)hRoot);
1523*c2c66affSColin Finck     ok(IsWindow(edit), "Expected valid handle\n");
1524*c2c66affSColin Finck     g_beginedit_alter_text = FALSE;
1525*c2c66affSColin Finck 
1526*c2c66affSColin Finck     GetWindowTextA(edit, buffA, sizeof(buffA)/sizeof(CHAR));
1527*c2c66affSColin Finck     ok(!strcmp(buffA, "<edittextaltered>"), "got string %s\n", buffA);
1528*c2c66affSColin Finck 
1529*c2c66affSColin Finck     DestroyWindow(hTree);
1530*c2c66affSColin Finck }
1531*c2c66affSColin Finck 
1532*c2c66affSColin Finck static void test_treeview_classinfo(void)
1533*c2c66affSColin Finck {
1534*c2c66affSColin Finck     WNDCLASSA cls;
1535*c2c66affSColin Finck 
1536*c2c66affSColin Finck     memset(&cls, 0, sizeof(cls));
1537*c2c66affSColin Finck     GetClassInfoA(GetModuleHandleA("comctl32.dll"), WC_TREEVIEWA, &cls);
1538*c2c66affSColin Finck     ok(cls.hbrBackground == NULL, "Expected NULL background brush, got %p\n", cls.hbrBackground);
1539*c2c66affSColin Finck     ok(cls.style == (CS_GLOBALCLASS | CS_DBLCLKS), "Expected got %x\n", cls.style);
1540*c2c66affSColin Finck     expect(0, cls.cbClsExtra);
1541*c2c66affSColin Finck }
1542*c2c66affSColin Finck 
1543*c2c66affSColin Finck static void test_get_linecolor(void)
1544*c2c66affSColin Finck {
1545*c2c66affSColin Finck     COLORREF clr;
1546*c2c66affSColin Finck     HWND hTree;
1547*c2c66affSColin Finck 
1548*c2c66affSColin Finck     hTree = create_treeview_control(0);
1549*c2c66affSColin Finck 
1550*c2c66affSColin Finck     /* newly created control has default color */
1551*c2c66affSColin Finck     clr = SendMessageA(hTree, TVM_GETLINECOLOR, 0, 0);
1552*c2c66affSColin Finck     if (clr == 0)
1553*c2c66affSColin Finck         win_skip("TVM_GETLINECOLOR is not supported on comctl32 < 5.80\n");
1554*c2c66affSColin Finck     else
1555*c2c66affSColin Finck         expect(CLR_DEFAULT, clr);
1556*c2c66affSColin Finck 
1557*c2c66affSColin Finck     DestroyWindow(hTree);
1558*c2c66affSColin Finck }
1559*c2c66affSColin Finck 
1560*c2c66affSColin Finck static void test_get_insertmarkcolor(void)
1561*c2c66affSColin Finck {
1562*c2c66affSColin Finck     COLORREF clr;
1563*c2c66affSColin Finck     HWND hTree;
1564*c2c66affSColin Finck 
1565*c2c66affSColin Finck     hTree = create_treeview_control(0);
1566*c2c66affSColin Finck 
1567*c2c66affSColin Finck     /* newly created control has default color */
1568*c2c66affSColin Finck     clr = SendMessageA(hTree, TVM_GETINSERTMARKCOLOR, 0, 0);
1569*c2c66affSColin Finck     if (clr == 0)
1570*c2c66affSColin Finck         win_skip("TVM_GETINSERTMARKCOLOR is not supported on comctl32 < 5.80\n");
1571*c2c66affSColin Finck     else
1572*c2c66affSColin Finck         expect(CLR_DEFAULT, clr);
1573*c2c66affSColin Finck 
1574*c2c66affSColin Finck     DestroyWindow(hTree);
1575*c2c66affSColin Finck }
1576*c2c66affSColin Finck 
1577*c2c66affSColin Finck static void test_expandnotify(void)
1578*c2c66affSColin Finck {
1579*c2c66affSColin Finck     HTREEITEM hitem;
1580*c2c66affSColin Finck     HWND hTree;
1581*c2c66affSColin Finck     BOOL ret;
1582*c2c66affSColin Finck     TVITEMA item;
1583*c2c66affSColin Finck 
1584*c2c66affSColin Finck     hTree = create_treeview_control(0);
1585*c2c66affSColin Finck     fill_tree(hTree);
1586*c2c66affSColin Finck 
1587*c2c66affSColin Finck     item.hItem = hRoot;
1588*c2c66affSColin Finck     item.mask = TVIF_STATE;
1589*c2c66affSColin Finck 
1590*c2c66affSColin Finck     item.state = TVIS_EXPANDED;
1591*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1592*c2c66affSColin Finck     expect(TRUE, ret);
1593*c2c66affSColin Finck     ok((item.state & TVIS_EXPANDED) == 0, "expected collapsed\n");
1594*c2c66affSColin Finck 
1595*c2c66affSColin Finck     /* preselect root node here */
1596*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
1597*c2c66affSColin Finck     expect(TRUE, ret);
1598*c2c66affSColin Finck 
1599*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1600*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hRoot);
1601*c2c66affSColin Finck     expect(FALSE, ret);
1602*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "no collapse notifications", FALSE);
1603*c2c66affSColin Finck 
1604*c2c66affSColin Finck     g_get_from_expand = TRUE;
1605*c2c66affSColin Finck     /* expand */
1606*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1607*c2c66affSColin Finck     g_item_expanding.state = 0xdeadbeef;
1608*c2c66affSColin Finck     g_item_expanded.state = 0xdeadbeef;
1609*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)hRoot);
1610*c2c66affSColin Finck     expect(TRUE, ret);
1611*c2c66affSColin Finck     ok(g_item_expanding.state == TVIS_SELECTED, "got state on TVN_ITEMEXPANDING 0x%08x\n",
1612*c2c66affSColin Finck        g_item_expanding.state);
1613*c2c66affSColin Finck     ok(g_item_expanded.state == (TVIS_SELECTED|TVIS_EXPANDED), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1614*c2c66affSColin Finck        g_item_expanded.state);
1615*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_seq, "expand notifications", FALSE);
1616*c2c66affSColin Finck     g_get_from_expand = FALSE;
1617*c2c66affSColin Finck 
1618*c2c66affSColin Finck     /* check that it's expanded */
1619*c2c66affSColin Finck     item.state = TVIS_EXPANDED;
1620*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1621*c2c66affSColin Finck     expect(TRUE, ret);
1622*c2c66affSColin Finck     ok((item.state & TVIS_EXPANDED) == TVIS_EXPANDED, "expected expanded\n");
1623*c2c66affSColin Finck 
1624*c2c66affSColin Finck     /* collapse */
1625*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1626*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hRoot);
1627*c2c66affSColin Finck     expect(TRUE, ret);
1628*c2c66affSColin Finck     item.state = TVIS_EXPANDED;
1629*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1630*c2c66affSColin Finck     expect(TRUE, ret);
1631*c2c66affSColin Finck     ok((item.state & TVIS_EXPANDED) == 0, "expected collapsed\n");
1632*c2c66affSColin Finck     /* all further collapse/expand attempts won't produce any notifications,
1633*c2c66affSColin Finck        the only way is to reset with all children removed */
1634*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "collapse after expand notifications", FALSE);
1635*c2c66affSColin Finck 
1636*c2c66affSColin Finck     /* try to toggle child that doesn't have children itself */
1637*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1638*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_TOGGLE, (LPARAM)hChild);
1639*c2c66affSColin Finck     expect(FALSE, ret);
1640*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "toggle node without children", FALSE);
1641*c2c66affSColin Finck 
1642*c2c66affSColin Finck     DestroyWindow(hTree);
1643*c2c66affSColin Finck 
1644*c2c66affSColin Finck     /* test TVM_GETITEMRECT inside TVN_ITEMEXPANDED notification */
1645*c2c66affSColin Finck     hTree = create_treeview_control(0);
1646*c2c66affSColin Finck     fill_tree(hTree);
1647*c2c66affSColin Finck     g_get_rect_in_expand = TRUE;
1648*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
1649*c2c66affSColin Finck     expect(TRUE, ret);
1650*c2c66affSColin Finck     g_get_rect_in_expand = FALSE;
1651*c2c66affSColin Finck 
1652*c2c66affSColin Finck     DestroyWindow(hTree);
1653*c2c66affSColin Finck 
1654*c2c66affSColin Finck     /* TVE_TOGGLE acts as any other TVM_EXPAND */
1655*c2c66affSColin Finck     hTree = create_treeview_control(0);
1656*c2c66affSColin Finck     fill_tree(hTree);
1657*c2c66affSColin Finck 
1658*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1659*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_TOGGLE, (LPARAM)hRoot);
1660*c2c66affSColin Finck     expect(TRUE, ret);
1661*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_seq, "toggle node (expand)", FALSE);
1662*c2c66affSColin Finck 
1663*c2c66affSColin Finck     /* toggle again - no notifications */
1664*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1665*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_TOGGLE, (LPARAM)hRoot);
1666*c2c66affSColin Finck     expect(TRUE, ret);
1667*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "toggle node (collapse)", FALSE);
1668*c2c66affSColin Finck 
1669*c2c66affSColin Finck     DestroyWindow(hTree);
1670*c2c66affSColin Finck 
1671*c2c66affSColin Finck     /* some keyboard events are also translated to expand */
1672*c2c66affSColin Finck     hTree = create_treeview_control(0);
1673*c2c66affSColin Finck     fill_tree(hTree);
1674*c2c66affSColin Finck 
1675*c2c66affSColin Finck     /* preselect root node here */
1676*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
1677*c2c66affSColin Finck     expect(TRUE, ret);
1678*c2c66affSColin Finck 
1679*c2c66affSColin Finck     g_get_from_expand = TRUE;
1680*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1681*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_ADD, 0);
1682*c2c66affSColin Finck     expect(FALSE, ret);
1683*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_kb_seq, "expand node", FALSE);
1684*c2c66affSColin Finck     ok(g_item_expanding.state == TVIS_SELECTED, "got state on TVN_ITEMEXPANDING 0x%08x\n",
1685*c2c66affSColin Finck        g_item_expanding.state);
1686*c2c66affSColin Finck     ok(g_item_expanded.state == (TVIS_SELECTED|TVIS_EXPANDED), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1687*c2c66affSColin Finck        g_item_expanded.state);
1688*c2c66affSColin Finck 
1689*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1690*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_ADD, 0);
1691*c2c66affSColin Finck     expect(FALSE, ret);
1692*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_kb_seq, "expand node again", FALSE);
1693*c2c66affSColin Finck     ok(g_item_expanding.state == (TVIS_SELECTED|TVIS_EXPANDED|TVIS_EXPANDEDONCE), "got state on TVN_ITEMEXPANDING 0x%08x\n",
1694*c2c66affSColin Finck        g_item_expanding.state);
1695*c2c66affSColin Finck     ok(g_item_expanded.state == (TVIS_SELECTED|TVIS_EXPANDED|TVIS_EXPANDEDONCE), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1696*c2c66affSColin Finck        g_item_expanded.state);
1697*c2c66affSColin Finck 
1698*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1699*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_SUBTRACT, 0);
1700*c2c66affSColin Finck     expect(FALSE, ret);
1701*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_kb_seq, "collapse node", FALSE);
1702*c2c66affSColin Finck     ok(g_item_expanding.state == (TVIS_SELECTED|TVIS_EXPANDED|TVIS_EXPANDEDONCE), "got state on TVN_ITEMEXPANDING 0x%08x\n",
1703*c2c66affSColin Finck        g_item_expanding.state);
1704*c2c66affSColin Finck     ok(g_item_expanded.state == (TVIS_SELECTED|TVIS_EXPANDEDONCE), "got state on TVN_ITEMEXPANDED 0x%08x\n",
1705*c2c66affSColin Finck        g_item_expanded.state);
1706*c2c66affSColin Finck 
1707*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1708*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_SUBTRACT, 0);
1709*c2c66affSColin Finck     expect(FALSE, ret);
1710*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_collapse_2nd_kb_seq, "collapse node again", FALSE);
1711*c2c66affSColin Finck     ok(g_item_expanding.state == (TVIS_SELECTED|TVIS_EXPANDEDONCE), "got state on TVN_ITEMEXPANDING 0x%08x\n",
1712*c2c66affSColin Finck        g_item_expanding.state);
1713*c2c66affSColin Finck     g_get_from_expand = FALSE;
1714*c2c66affSColin Finck 
1715*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1716*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_ADD, 0);
1717*c2c66affSColin Finck     expect(FALSE, ret);
1718*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_kb_seq, "expand node", FALSE);
1719*c2c66affSColin Finck 
1720*c2c66affSColin Finck     /* go to child */
1721*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_RIGHT, 0);
1722*c2c66affSColin Finck     expect(FALSE, ret);
1723*c2c66affSColin Finck 
1724*c2c66affSColin Finck     /* try to expand child that doesn't have children itself */
1725*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1726*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_ADD, 0);
1727*c2c66affSColin Finck     expect(FALSE, ret);
1728*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_expand_empty_kb_seq, "expand node with no children", FALSE);
1729*c2c66affSColin Finck 
1730*c2c66affSColin Finck     /* stay on current selection and set non-zero children count */
1731*c2c66affSColin Finck     hitem = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0);
1732*c2c66affSColin Finck     ok(hitem != NULL, "got %p\n", hitem);
1733*c2c66affSColin Finck 
1734*c2c66affSColin Finck     item.hItem = hitem;
1735*c2c66affSColin Finck     item.mask = TVIF_CHILDREN;
1736*c2c66affSColin Finck     item.cChildren = 0x80000000;
1737*c2c66affSColin Finck 
1738*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
1739*c2c66affSColin Finck     expect(TRUE, ret);
1740*c2c66affSColin Finck 
1741*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1742*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_KEYDOWN, VK_ADD, 0);
1743*c2c66affSColin Finck     expect(FALSE, ret);
1744*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_collapse_2nd_kb_seq, "expand node with children", FALSE);
1745*c2c66affSColin Finck 
1746*c2c66affSColin Finck     DestroyWindow(hTree);
1747*c2c66affSColin Finck }
1748*c2c66affSColin Finck 
1749*c2c66affSColin Finck static void test_expandedimage(void)
1750*c2c66affSColin Finck {
1751*c2c66affSColin Finck     TVITEMEXA item;
1752*c2c66affSColin Finck     HWND hTree;
1753*c2c66affSColin Finck     BOOL ret;
1754*c2c66affSColin Finck 
1755*c2c66affSColin Finck     hTree = create_treeview_control(0);
1756*c2c66affSColin Finck     fill_tree(hTree);
1757*c2c66affSColin Finck 
1758*c2c66affSColin Finck     item.mask = TVIF_EXPANDEDIMAGE;
1759*c2c66affSColin Finck     item.iExpandedImage = 1;
1760*c2c66affSColin Finck     item.hItem = hRoot;
1761*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
1762*c2c66affSColin Finck     ok(ret, "got %d\n", ret);
1763*c2c66affSColin Finck 
1764*c2c66affSColin Finck     item.mask = TVIF_EXPANDEDIMAGE;
1765*c2c66affSColin Finck     item.iExpandedImage = -1;
1766*c2c66affSColin Finck     item.hItem = hRoot;
1767*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1768*c2c66affSColin Finck     ok(ret, "got %d\n", ret);
1769*c2c66affSColin Finck 
1770*c2c66affSColin Finck     if (item.iExpandedImage != 1)
1771*c2c66affSColin Finck     {
1772*c2c66affSColin Finck         win_skip("TVIF_EXPANDEDIMAGE not supported\n");
1773*c2c66affSColin Finck         DestroyWindow(hTree);
1774*c2c66affSColin Finck         return;
1775*c2c66affSColin Finck     }
1776*c2c66affSColin Finck 
1777*c2c66affSColin Finck     /* test for default iExpandedImage value */
1778*c2c66affSColin Finck     item.mask = TVIF_EXPANDEDIMAGE;
1779*c2c66affSColin Finck     item.iExpandedImage = -1;
1780*c2c66affSColin Finck     item.hItem = hChild;
1781*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
1782*c2c66affSColin Finck     ok(ret, "got %d\n", ret);
1783*c2c66affSColin Finck     ok(item.iExpandedImage == (WORD)I_IMAGENONE, "got %d\n", item.iExpandedImage);
1784*c2c66affSColin Finck 
1785*c2c66affSColin Finck     DestroyWindow(hTree);
1786*c2c66affSColin Finck }
1787*c2c66affSColin Finck 
1788*c2c66affSColin Finck static void test_TVS_SINGLEEXPAND(void)
1789*c2c66affSColin Finck {
1790*c2c66affSColin Finck     HWND hTree;
1791*c2c66affSColin Finck     HTREEITEM alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel, india, juliet;
1792*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
1793*c2c66affSColin Finck     char foo[] = "foo";
1794*c2c66affSColin Finck     char context[32];
1795*c2c66affSColin Finck     int i;
1796*c2c66affSColin Finck     BOOL ret;
1797*c2c66affSColin Finck 
1798*c2c66affSColin Finck     /* build a fairly complex tree
1799*c2c66affSColin Finck      * - TVI_ROOT
1800*c2c66affSColin Finck      *   - alpha
1801*c2c66affSColin Finck      *     - bravo
1802*c2c66affSColin Finck      *       - charlie
1803*c2c66affSColin Finck      *     - delta
1804*c2c66affSColin Finck      *       - echo
1805*c2c66affSColin Finck      *   - foxtrot
1806*c2c66affSColin Finck      *     - golf
1807*c2c66affSColin Finck      *       - hotel
1808*c2c66affSColin Finck      *       - india
1809*c2c66affSColin Finck      *     - juliet
1810*c2c66affSColin Finck      */
1811*c2c66affSColin Finck     struct
1812*c2c66affSColin Finck     {
1813*c2c66affSColin Finck         HTREEITEM *handle;
1814*c2c66affSColin Finck         HTREEITEM *parent;
1815*c2c66affSColin Finck         UINT final_state;
1816*c2c66affSColin Finck     }
1817*c2c66affSColin Finck     items[] =
1818*c2c66affSColin Finck     {
1819*c2c66affSColin Finck         { &alpha,    NULL,      TVIS_EXPANDEDONCE               },
1820*c2c66affSColin Finck         { &bravo,    &alpha,    TVIS_EXPANDEDONCE               },
1821*c2c66affSColin Finck         { &charlie,  &bravo,    0                               },
1822*c2c66affSColin Finck         { &delta,    &alpha,    TVIS_EXPANDEDONCE               },
1823*c2c66affSColin Finck         { &echo,     &delta,    0                               },
1824*c2c66affSColin Finck         { &foxtrot,  NULL,      TVIS_EXPANDEDONCE|TVIS_EXPANDED },
1825*c2c66affSColin Finck         { &golf,     &foxtrot,  TVIS_EXPANDEDONCE|TVIS_EXPANDED },
1826*c2c66affSColin Finck         { &hotel,    &golf,     0                               },
1827*c2c66affSColin Finck         { &india,    &golf,     TVIS_SELECTED                   },
1828*c2c66affSColin Finck         { &juliet,   &foxtrot,  0                               }
1829*c2c66affSColin Finck     };
1830*c2c66affSColin Finck 
1831*c2c66affSColin Finck     struct
1832*c2c66affSColin Finck     {
1833*c2c66affSColin Finck         HTREEITEM *select;
1834*c2c66affSColin Finck         const struct message *sequence;
1835*c2c66affSColin Finck     }
1836*c2c66affSColin Finck     sequence_tests[] =
1837*c2c66affSColin Finck     {
1838*c2c66affSColin Finck         { &alpha,    parent_singleexpand_seq0 },
1839*c2c66affSColin Finck         { &bravo,    parent_singleexpand_seq1 },
1840*c2c66affSColin Finck         { &delta,    parent_singleexpand_seq2 },
1841*c2c66affSColin Finck         { &foxtrot,  parent_singleexpand_seq3 },
1842*c2c66affSColin Finck         { &alpha,    parent_singleexpand_seq4 },
1843*c2c66affSColin Finck         { &golf,     parent_singleexpand_seq5 },
1844*c2c66affSColin Finck         { &hotel,    parent_singleexpand_seq6 },
1845*c2c66affSColin Finck         { &india,    parent_singleexpand_seq7 },
1846*c2c66affSColin Finck         { &india,    empty_seq }
1847*c2c66affSColin Finck     };
1848*c2c66affSColin Finck 
1849*c2c66affSColin Finck     hTree = create_treeview_control(0);
1850*c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_SINGLEEXPAND);
1851*c2c66affSColin Finck     /* to avoid painting related notifications */
1852*c2c66affSColin Finck     ShowWindow(hTree, SW_HIDE);
1853*c2c66affSColin Finck     for (i = 0; i < sizeof(items)/sizeof(items[0]); i++)
1854*c2c66affSColin Finck     {
1855*c2c66affSColin Finck         ins.hParent = items[i].parent ? *items[i].parent : TVI_ROOT;
1856*c2c66affSColin Finck         ins.hInsertAfter = TVI_FIRST;
1857*c2c66affSColin Finck         U(ins).item.mask = TVIF_TEXT;
1858*c2c66affSColin Finck         U(ins).item.pszText = foo;
1859*c2c66affSColin Finck         *items[i].handle = TreeView_InsertItemA(hTree, &ins);
1860*c2c66affSColin Finck     }
1861*c2c66affSColin Finck 
1862*c2c66affSColin Finck     for (i = 0; i < sizeof(sequence_tests)/sizeof(sequence_tests[0]); i++)
1863*c2c66affSColin Finck     {
1864*c2c66affSColin Finck         flush_sequences(sequences, NUM_MSG_SEQUENCES);
1865*c2c66affSColin Finck         ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)(*sequence_tests[i].select));
1866*c2c66affSColin Finck         ok(ret, "got %d\n", ret);
1867*c2c66affSColin Finck         sprintf(context, "singleexpand notifications %d", i);
1868*c2c66affSColin Finck         ok_sequence(sequences, PARENT_SEQ_INDEX, sequence_tests[i].sequence, context, FALSE);
1869*c2c66affSColin Finck     }
1870*c2c66affSColin Finck 
1871*c2c66affSColin Finck     for (i = 0; i < sizeof(items)/sizeof(items[0]); i++)
1872*c2c66affSColin Finck     {
1873*c2c66affSColin Finck         ret = SendMessageA(hTree, TVM_GETITEMSTATE, (WPARAM)(*items[i].handle), 0xFFFF);
1874*c2c66affSColin Finck         ok(ret == items[i].final_state, "singleexpand items[%d]: expected state 0x%x got 0x%x\n",
1875*c2c66affSColin Finck            i, items[i].final_state, ret);
1876*c2c66affSColin Finck     }
1877*c2c66affSColin Finck 
1878*c2c66affSColin Finck     /* a workaround for NT4 that sends expand notifications when nothing is about to expand */
1879*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
1880*c2c66affSColin Finck     ok(ret, "got %d\n", ret);
1881*c2c66affSColin Finck     fill_tree(hTree);
1882*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, 0);
1883*c2c66affSColin Finck     ok(ret, "got %d\n", ret);
1884*c2c66affSColin Finck 
1885*c2c66affSColin Finck     DestroyWindow(hTree);
1886*c2c66affSColin Finck }
1887*c2c66affSColin Finck 
1888*c2c66affSColin Finck static void test_WM_PAINT(void)
1889*c2c66affSColin Finck {
1890*c2c66affSColin Finck     HWND hTree;
1891*c2c66affSColin Finck     COLORREF clr;
1892*c2c66affSColin Finck     LONG ret;
1893*c2c66affSColin Finck     RECT rc;
1894*c2c66affSColin Finck     HDC hdc;
1895*c2c66affSColin Finck 
1896*c2c66affSColin Finck     hTree = create_treeview_control(0);
1897*c2c66affSColin Finck 
1898*c2c66affSColin Finck     clr = SendMessageA(hTree, TVM_SETBKCOLOR, 0, RGB(255, 0, 0));
1899*c2c66affSColin Finck     ok(clr == ~0u, "got %d, expected -1\n", clr);
1900*c2c66affSColin Finck 
1901*c2c66affSColin Finck     hdc = GetDC(hMainWnd);
1902*c2c66affSColin Finck 
1903*c2c66affSColin Finck     GetClientRect(hMainWnd, &rc);
1904*c2c66affSColin Finck     FillRect(hdc, &rc, GetStockObject(BLACK_BRUSH));
1905*c2c66affSColin Finck 
1906*c2c66affSColin Finck     clr = GetPixel(hdc, 1, 1);
1907*c2c66affSColin Finck     ok(clr == RGB(0, 0, 0), "got 0x%x\n", clr);
1908*c2c66affSColin Finck 
1909*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_PAINT, (WPARAM)hdc, 0);
1910*c2c66affSColin Finck     ok(ret == 0, "got %d\n", ret);
1911*c2c66affSColin Finck 
1912*c2c66affSColin Finck     clr = GetPixel(hdc, 1, 1);
1913*c2c66affSColin Finck     ok(clr == RGB(255, 0, 0) || broken(clr == RGB(0, 0, 0)) /* win98 */,
1914*c2c66affSColin Finck         "got 0x%x\n", clr);
1915*c2c66affSColin Finck 
1916*c2c66affSColin Finck     ReleaseDC(hMainWnd, hdc);
1917*c2c66affSColin Finck 
1918*c2c66affSColin Finck     DestroyWindow(hTree);
1919*c2c66affSColin Finck }
1920*c2c66affSColin Finck 
1921*c2c66affSColin Finck static void test_delete_items(void)
1922*c2c66affSColin Finck {
1923*c2c66affSColin Finck     const struct message *msg;
1924*c2c66affSColin Finck     HWND hTree;
1925*c2c66affSColin Finck     HTREEITEM hItem1, hItem2;
1926*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
1927*c2c66affSColin Finck     INT ret;
1928*c2c66affSColin Finck 
1929*c2c66affSColin Finck     static CHAR item1[] = "Item 1";
1930*c2c66affSColin Finck     static CHAR item2[] = "Item 2";
1931*c2c66affSColin Finck 
1932*c2c66affSColin Finck     hTree = create_treeview_control(0);
1933*c2c66affSColin Finck     fill_tree(hTree);
1934*c2c66affSColin Finck 
1935*c2c66affSColin Finck     /* check delete order */
1936*c2c66affSColin Finck     flush_sequences(item_sequence, 1);
1937*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, 0);
1938*c2c66affSColin Finck     ok(ret == TRUE, "got %d\n", ret);
1939*c2c66affSColin Finck 
1940*c2c66affSColin Finck     msg = item_sequence[0]->sequence;
1941*c2c66affSColin Finck     ok(item_sequence[0]->count == 2, "expected 2 items, got %d\n", item_sequence[0]->count);
1942*c2c66affSColin Finck 
1943*c2c66affSColin Finck     if (item_sequence[0]->count == 2)
1944*c2c66affSColin Finck     {
1945*c2c66affSColin Finck       ok(msg[0].lParam == (LPARAM)hChild, "expected %p, got 0x%lx\n", hChild, msg[0].lParam);
1946*c2c66affSColin Finck       ok(msg[1].lParam == (LPARAM)hRoot, "expected %p, got 0x%lx\n", hRoot, msg[1].lParam);
1947*c2c66affSColin Finck     }
1948*c2c66affSColin Finck 
1949*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETCOUNT, 0, 0);
1950*c2c66affSColin Finck     ok(ret == 0, "got %d\n", ret);
1951*c2c66affSColin Finck 
1952*c2c66affSColin Finck     DestroyWindow(hTree);
1953*c2c66affSColin Finck 
1954*c2c66affSColin Finck     /* Regression test for a crash when deleting the first visible item while bRedraw == false. */
1955*c2c66affSColin Finck     hTree = create_treeview_control(0);
1956*c2c66affSColin Finck 
1957*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_SETREDRAW, FALSE, 0);
1958*c2c66affSColin Finck     ok(ret == 0, "got %d\n", ret);
1959*c2c66affSColin Finck 
1960*c2c66affSColin Finck     ins.hParent = TVI_ROOT;
1961*c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
1962*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
1963*c2c66affSColin Finck     U(ins).item.pszText = item1;
1964*c2c66affSColin Finck     hItem1 = TreeView_InsertItemA(hTree, &ins);
1965*c2c66affSColin Finck     ok(hItem1 != NULL, "InsertItem failed\n");
1966*c2c66affSColin Finck 
1967*c2c66affSColin Finck     ins.hParent = TVI_ROOT;
1968*c2c66affSColin Finck     ins.hInsertAfter = hItem1;
1969*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
1970*c2c66affSColin Finck     U(ins).item.pszText = item2;
1971*c2c66affSColin Finck     hItem2 = TreeView_InsertItemA(hTree, &ins);
1972*c2c66affSColin Finck     ok(hItem2 != NULL, "InsertItem failed\n");
1973*c2c66affSColin Finck 
1974*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hItem1);
1975*c2c66affSColin Finck     ok(ret == TRUE, "got %d\n", ret);
1976*c2c66affSColin Finck 
1977*c2c66affSColin Finck     ret = SendMessageA(hTree, WM_SETREDRAW, TRUE, 0);
1978*c2c66affSColin Finck     ok(ret == 0, "got %d\n", ret);
1979*c2c66affSColin Finck 
1980*c2c66affSColin Finck     DestroyWindow(hTree);
1981*c2c66affSColin Finck }
1982*c2c66affSColin Finck 
1983*c2c66affSColin Finck static void test_cchildren(void)
1984*c2c66affSColin Finck {
1985*c2c66affSColin Finck     HWND hTree;
1986*c2c66affSColin Finck     INT ret;
1987*c2c66affSColin Finck     TVITEMA item;
1988*c2c66affSColin Finck 
1989*c2c66affSColin Finck     hTree = create_treeview_control(0);
1990*c2c66affSColin Finck     fill_tree(hTree);
1991*c2c66affSColin Finck 
1992*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hChild);
1993*c2c66affSColin Finck     expect(TRUE, ret);
1994*c2c66affSColin Finck 
1995*c2c66affSColin Finck     /* check cChildren - automatic mode */
1996*c2c66affSColin Finck     item.hItem = hRoot;
1997*c2c66affSColin Finck     item.mask = TVIF_CHILDREN;
1998*c2c66affSColin Finck 
1999*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2000*c2c66affSColin Finck     expect(TRUE, ret);
2001*c2c66affSColin Finck     expect(0, item.cChildren);
2002*c2c66affSColin Finck 
2003*c2c66affSColin Finck     DestroyWindow(hTree);
2004*c2c66affSColin Finck 
2005*c2c66affSColin Finck     /* start over */
2006*c2c66affSColin Finck     hTree = create_treeview_control(0);
2007*c2c66affSColin Finck     fill_tree(hTree);
2008*c2c66affSColin Finck 
2009*c2c66affSColin Finck     /* turn off automatic mode by setting cChildren explicitly */
2010*c2c66affSColin Finck     item.hItem = hRoot;
2011*c2c66affSColin Finck     item.mask = TVIF_CHILDREN;
2012*c2c66affSColin Finck 
2013*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2014*c2c66affSColin Finck     expect(TRUE, ret);
2015*c2c66affSColin Finck     expect(1, item.cChildren);
2016*c2c66affSColin Finck 
2017*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
2018*c2c66affSColin Finck     expect(TRUE, ret);
2019*c2c66affSColin Finck 
2020*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hChild);
2021*c2c66affSColin Finck     expect(TRUE, ret);
2022*c2c66affSColin Finck 
2023*c2c66affSColin Finck     /* check cChildren */
2024*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2025*c2c66affSColin Finck     expect(TRUE, ret);
2026*c2c66affSColin Finck todo_wine
2027*c2c66affSColin Finck     expect(1, item.cChildren);
2028*c2c66affSColin Finck 
2029*c2c66affSColin Finck     DestroyWindow(hTree);
2030*c2c66affSColin Finck }
2031*c2c66affSColin Finck 
2032*c2c66affSColin Finck struct _ITEM_DATA
2033*c2c66affSColin Finck {
2034*c2c66affSColin Finck     HTREEITEM  parent; /* for root value of parent field is unidetified */
2035*c2c66affSColin Finck     HTREEITEM  nextsibling;
2036*c2c66affSColin Finck     HTREEITEM  firstchild;
2037*c2c66affSColin Finck };
2038*c2c66affSColin Finck 
2039*c2c66affSColin Finck static void _check_item(HTREEITEM item, HTREEITEM parent, HTREEITEM nextsibling, HTREEITEM firstchild, int line)
2040*c2c66affSColin Finck {
2041*c2c66affSColin Finck     struct _ITEM_DATA *data = (struct _ITEM_DATA*)item;
2042*c2c66affSColin Finck 
2043*c2c66affSColin Finck     ok_(__FILE__, line)(data->parent == parent, "parent %p, got %p\n", parent, data->parent);
2044*c2c66affSColin Finck     ok_(__FILE__, line)(data->nextsibling == nextsibling, "sibling %p, got %p\n", nextsibling, data->nextsibling);
2045*c2c66affSColin Finck     ok_(__FILE__, line)(data->firstchild == firstchild, "firstchild %p, got %p\n", firstchild, data->firstchild);
2046*c2c66affSColin Finck }
2047*c2c66affSColin Finck 
2048*c2c66affSColin Finck #define check_item(a, b, c, d) _check_item(a, b, c, d, __LINE__)
2049*c2c66affSColin Finck 
2050*c2c66affSColin Finck static void test_htreeitem_layout(void)
2051*c2c66affSColin Finck {
2052*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
2053*c2c66affSColin Finck     HTREEITEM item1, item2;
2054*c2c66affSColin Finck     HWND hTree;
2055*c2c66affSColin Finck 
2056*c2c66affSColin Finck     hTree = create_treeview_control(0);
2057*c2c66affSColin Finck     fill_tree(hTree);
2058*c2c66affSColin Finck 
2059*c2c66affSColin Finck     /* root has some special pointer in parent field */
2060*c2c66affSColin Finck     check_item(hRoot, ((struct _ITEM_DATA*)hRoot)->parent, 0, hChild);
2061*c2c66affSColin Finck     check_item(hChild, hRoot, 0, 0);
2062*c2c66affSColin Finck 
2063*c2c66affSColin Finck     ins.hParent = hChild;
2064*c2c66affSColin Finck     ins.hInsertAfter = TVI_FIRST;
2065*c2c66affSColin Finck     U(ins).item.mask = 0;
2066*c2c66affSColin Finck     item1 = TreeView_InsertItemA(hTree, &ins);
2067*c2c66affSColin Finck 
2068*c2c66affSColin Finck     check_item(item1, hChild, 0, 0);
2069*c2c66affSColin Finck 
2070*c2c66affSColin Finck     ins.hParent = hRoot;
2071*c2c66affSColin Finck     ins.hInsertAfter = TVI_FIRST;
2072*c2c66affSColin Finck     U(ins).item.mask = 0;
2073*c2c66affSColin Finck     item2 = TreeView_InsertItemA(hTree, &ins);
2074*c2c66affSColin Finck 
2075*c2c66affSColin Finck     check_item(item2, hRoot, hChild, 0);
2076*c2c66affSColin Finck 
2077*c2c66affSColin Finck     SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hChild);
2078*c2c66affSColin Finck 
2079*c2c66affSColin Finck     /* without children now */
2080*c2c66affSColin Finck     check_item(hRoot, ((struct _ITEM_DATA*)hRoot)->parent, 0, item2);
2081*c2c66affSColin Finck 
2082*c2c66affSColin Finck     DestroyWindow(hTree);
2083*c2c66affSColin Finck }
2084*c2c66affSColin Finck 
2085*c2c66affSColin Finck static void test_TVS_CHECKBOXES(void)
2086*c2c66affSColin Finck {
2087*c2c66affSColin Finck     HIMAGELIST himl, himl2;
2088*c2c66affSColin Finck     HWND hTree, hTree2;
2089*c2c66affSColin Finck     TVITEMA item;
2090*c2c66affSColin Finck     DWORD ret;
2091*c2c66affSColin Finck     MSG msg;
2092*c2c66affSColin Finck 
2093*c2c66affSColin Finck     hTree = create_treeview_control(0);
2094*c2c66affSColin Finck     fill_tree(hTree);
2095*c2c66affSColin Finck 
2096*c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2097*c2c66affSColin Finck     ok(himl == NULL, "got %p\n", himl);
2098*c2c66affSColin Finck 
2099*c2c66affSColin Finck     item.hItem = hRoot;
2100*c2c66affSColin Finck     item.mask = TVIF_STATE;
2101*c2c66affSColin Finck     item.state = INDEXTOSTATEIMAGEMASK(1);
2102*c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2103*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2104*c2c66affSColin Finck     expect(TRUE, ret);
2105*c2c66affSColin Finck     ok(item.state == 0, "got 0x%x\n", item.state);
2106*c2c66affSColin Finck 
2107*c2c66affSColin Finck     /* set some index for a child */
2108*c2c66affSColin Finck     item.hItem = hChild;
2109*c2c66affSColin Finck     item.mask = TVIF_STATE;
2110*c2c66affSColin Finck     item.state = INDEXTOSTATEIMAGEMASK(4);
2111*c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2112*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
2113*c2c66affSColin Finck     expect(TRUE, ret);
2114*c2c66affSColin Finck 
2115*c2c66affSColin Finck     /* enabling check boxes set all items to 1 state image index */
2116*c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_CHECKBOXES);
2117*c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2118*c2c66affSColin Finck     ok(himl != NULL, "got %p\n", himl);
2119*c2c66affSColin Finck 
2120*c2c66affSColin Finck     himl2 = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2121*c2c66affSColin Finck     ok(himl2 != NULL, "got %p\n", himl2);
2122*c2c66affSColin Finck     ok(himl2 == himl, "got %p, expected %p\n", himl2, himl);
2123*c2c66affSColin Finck 
2124*c2c66affSColin Finck     item.hItem = hRoot;
2125*c2c66affSColin Finck     item.mask = TVIF_STATE;
2126*c2c66affSColin Finck     item.state = 0;
2127*c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2128*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2129*c2c66affSColin Finck     expect(TRUE, ret);
2130*c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2131*c2c66affSColin Finck 
2132*c2c66affSColin Finck     item.hItem = hChild;
2133*c2c66affSColin Finck     item.mask = TVIF_STATE;
2134*c2c66affSColin Finck     item.state = 0;
2135*c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2136*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2137*c2c66affSColin Finck     expect(TRUE, ret);
2138*c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2139*c2c66affSColin Finck 
2140*c2c66affSColin Finck     /* create another control and check its checkbox list */
2141*c2c66affSColin Finck     hTree2 = create_treeview_control(0);
2142*c2c66affSColin Finck     fill_tree(hTree2);
2143*c2c66affSColin Finck 
2144*c2c66affSColin Finck     /* set some index for a child */
2145*c2c66affSColin Finck     item.hItem = hChild;
2146*c2c66affSColin Finck     item.mask = TVIF_STATE;
2147*c2c66affSColin Finck     item.state = INDEXTOSTATEIMAGEMASK(4);
2148*c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2149*c2c66affSColin Finck     ret = SendMessageA(hTree2, TVM_SETITEMA, 0, (LPARAM)&item);
2150*c2c66affSColin Finck     expect(TRUE, ret);
2151*c2c66affSColin Finck 
2152*c2c66affSColin Finck     /* enabling check boxes set all items to 1 state image index */
2153*c2c66affSColin Finck     SetWindowLongA(hTree2, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_CHECKBOXES);
2154*c2c66affSColin Finck     himl2 = (HIMAGELIST)SendMessageA(hTree2, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2155*c2c66affSColin Finck     ok(himl2 != NULL, "got %p\n", himl2);
2156*c2c66affSColin Finck     ok(himl != himl2, "got %p, expected %p\n", himl2, himl);
2157*c2c66affSColin Finck 
2158*c2c66affSColin Finck     DestroyWindow(hTree2);
2159*c2c66affSColin Finck     DestroyWindow(hTree);
2160*c2c66affSColin Finck 
2161*c2c66affSColin Finck     /* the same, but initially created with TVS_CHECKBOXES */
2162*c2c66affSColin Finck     hTree = create_treeview_control(TVS_CHECKBOXES);
2163*c2c66affSColin Finck     fill_tree(hTree);
2164*c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2165*c2c66affSColin Finck     ok(himl == NULL, "got %p\n", himl);
2166*c2c66affSColin Finck 
2167*c2c66affSColin Finck     item.hItem = hRoot;
2168*c2c66affSColin Finck     item.mask = TVIF_STATE;
2169*c2c66affSColin Finck     item.state = 0;
2170*c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2171*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2172*c2c66affSColin Finck     expect(TRUE, ret);
2173*c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2174*c2c66affSColin Finck 
2175*c2c66affSColin Finck     item.hItem = hChild;
2176*c2c66affSColin Finck     item.mask = TVIF_STATE;
2177*c2c66affSColin Finck     item.state = 0;
2178*c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2179*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2180*c2c66affSColin Finck     expect(TRUE, ret);
2181*c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2182*c2c66affSColin Finck 
2183*c2c66affSColin Finck     item.hItem = hChild;
2184*c2c66affSColin Finck     item.mask = TVIF_STATE;
2185*c2c66affSColin Finck     item.state = INDEXTOSTATEIMAGEMASK(2);
2186*c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2187*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
2188*c2c66affSColin Finck     expect(TRUE, ret);
2189*c2c66affSColin Finck 
2190*c2c66affSColin Finck     item.hItem = hChild;
2191*c2c66affSColin Finck     item.mask = TVIF_STATE;
2192*c2c66affSColin Finck     item.state = 0;
2193*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2194*c2c66affSColin Finck     expect(TRUE, ret);
2195*c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(2), "got 0x%x\n", item.state);
2196*c2c66affSColin Finck 
2197*c2c66affSColin Finck     while(GetMessageA(&msg, 0, 0, 0))
2198*c2c66affSColin Finck     {
2199*c2c66affSColin Finck         TranslateMessage(&msg);
2200*c2c66affSColin Finck         DispatchMessageA(&msg);
2201*c2c66affSColin Finck 
2202*c2c66affSColin Finck         if((msg.hwnd == hTree) && (msg.message == WM_PAINT))
2203*c2c66affSColin Finck             break;
2204*c2c66affSColin Finck     }
2205*c2c66affSColin Finck 
2206*c2c66affSColin Finck     item.hItem = hChild;
2207*c2c66affSColin Finck     item.mask = TVIF_STATE;
2208*c2c66affSColin Finck     item.state = 0;
2209*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2210*c2c66affSColin Finck     expect(TRUE, ret);
2211*c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2212*c2c66affSColin Finck 
2213*c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2214*c2c66affSColin Finck     ok(himl != NULL, "got %p\n", himl);
2215*c2c66affSColin Finck 
2216*c2c66affSColin Finck     DestroyWindow(hTree);
2217*c2c66affSColin Finck 
2218*c2c66affSColin Finck     /* check what happens if TVSIL_STATE image list is removed */
2219*c2c66affSColin Finck     hTree = create_treeview_control(0);
2220*c2c66affSColin Finck     fill_tree(hTree);
2221*c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2222*c2c66affSColin Finck     ok(himl == NULL, "got %p\n", himl);
2223*c2c66affSColin Finck 
2224*c2c66affSColin Finck     SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_CHECKBOXES);
2225*c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2226*c2c66affSColin Finck     ok(himl != NULL, "got %p\n", himl);
2227*c2c66affSColin Finck 
2228*c2c66affSColin Finck     himl2 = (HIMAGELIST)SendMessageA(hTree, TVM_SETIMAGELIST, TVSIL_STATE, 0);
2229*c2c66affSColin Finck     ok(himl2 == himl, "got %p\n", himl2);
2230*c2c66affSColin Finck 
2231*c2c66affSColin Finck     himl2 = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2232*c2c66affSColin Finck     ok(himl2 == NULL, "got %p\n", himl2);
2233*c2c66affSColin Finck 
2234*c2c66affSColin Finck     item.hItem = hChild;
2235*c2c66affSColin Finck     item.mask = TVIF_STATE;
2236*c2c66affSColin Finck     item.state = INDEXTOSTATEIMAGEMASK(2);
2237*c2c66affSColin Finck     item.stateMask = TVIS_STATEIMAGEMASK;
2238*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_SETITEMA, 0, (LPARAM)&item);
2239*c2c66affSColin Finck     expect(TRUE, ret);
2240*c2c66affSColin Finck 
2241*c2c66affSColin Finck     item.hItem = hChild;
2242*c2c66affSColin Finck     item.mask = TVIF_STATE;
2243*c2c66affSColin Finck     item.state = 0;
2244*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2245*c2c66affSColin Finck     expect(TRUE, ret);
2246*c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(2), "got 0x%x\n", item.state);
2247*c2c66affSColin Finck 
2248*c2c66affSColin Finck     while(GetMessageA(&msg, 0, 0, 0))
2249*c2c66affSColin Finck     {
2250*c2c66affSColin Finck         TranslateMessage(&msg);
2251*c2c66affSColin Finck         DispatchMessageA(&msg);
2252*c2c66affSColin Finck 
2253*c2c66affSColin Finck         if((msg.hwnd == hTree) && (msg.message == WM_PAINT))
2254*c2c66affSColin Finck             break;
2255*c2c66affSColin Finck     }
2256*c2c66affSColin Finck 
2257*c2c66affSColin Finck     item.hItem = hChild;
2258*c2c66affSColin Finck     item.mask = TVIF_STATE;
2259*c2c66affSColin Finck     item.state = 0;
2260*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
2261*c2c66affSColin Finck     expect(TRUE, ret);
2262*c2c66affSColin Finck     ok(item.state == INDEXTOSTATEIMAGEMASK(1), "got 0x%x\n", item.state);
2263*c2c66affSColin Finck 
2264*c2c66affSColin Finck     himl = (HIMAGELIST)SendMessageA(hTree, TVM_GETIMAGELIST, TVSIL_STATE, 0);
2265*c2c66affSColin Finck     ok(himl != NULL, "got %p\n", himl);
2266*c2c66affSColin Finck 
2267*c2c66affSColin Finck     DestroyWindow(hTree);
2268*c2c66affSColin Finck }
2269*c2c66affSColin Finck 
2270*c2c66affSColin Finck static void test_TVM_GETNEXTITEM(void)
2271*c2c66affSColin Finck {
2272*c2c66affSColin Finck     HTREEITEM item;
2273*c2c66affSColin Finck     HWND hTree;
2274*c2c66affSColin Finck 
2275*c2c66affSColin Finck     hTree = create_treeview_control(0);
2276*c2c66affSColin Finck     fill_tree(hTree);
2277*c2c66affSColin Finck 
2278*c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_ROOT, 0);
2279*c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2280*c2c66affSColin Finck 
2281*c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_ROOT, (LPARAM)TVI_ROOT);
2282*c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2283*c2c66affSColin Finck 
2284*c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_ROOT, (LPARAM)hRoot);
2285*c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2286*c2c66affSColin Finck 
2287*c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_ROOT, (LPARAM)hChild);
2288*c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2289*c2c66affSColin Finck 
2290*c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CHILD, 0);
2291*c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2292*c2c66affSColin Finck 
2293*c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hRoot);
2294*c2c66affSColin Finck     ok(item == hChild, "got %p, expected %p\n", item, hChild);
2295*c2c66affSColin Finck 
2296*c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)TVI_ROOT);
2297*c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2298*c2c66affSColin Finck 
2299*c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_PARENT, 0);
2300*c2c66affSColin Finck     ok(item == NULL, "got %p\n", item);
2301*c2c66affSColin Finck 
2302*c2c66affSColin Finck     item = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hChild);
2303*c2c66affSColin Finck     ok(item == hRoot, "got %p, expected %p\n", item, hRoot);
2304*c2c66affSColin Finck 
2305*c2c66affSColin Finck     DestroyWindow(hTree);
2306*c2c66affSColin Finck }
2307*c2c66affSColin Finck 
2308*c2c66affSColin Finck static void test_TVM_HITTEST(void)
2309*c2c66affSColin Finck {
2310*c2c66affSColin Finck     HWND hTree;
2311*c2c66affSColin Finck     LRESULT ret;
2312*c2c66affSColin Finck     RECT rc;
2313*c2c66affSColin Finck     TVHITTESTINFO ht;
2314*c2c66affSColin Finck 
2315*c2c66affSColin Finck     hTree = create_treeview_control(0);
2316*c2c66affSColin Finck     fill_tree(hTree);
2317*c2c66affSColin Finck 
2318*c2c66affSColin Finck     *(HTREEITEM*)&rc = hRoot;
2319*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMRECT, TRUE, (LPARAM)&rc);
2320*c2c66affSColin Finck     expect(TRUE, (BOOL)ret);
2321*c2c66affSColin Finck 
2322*c2c66affSColin Finck     ht.pt.x = rc.left-1;
2323*c2c66affSColin Finck     ht.pt.y = rc.top;
2324*c2c66affSColin Finck 
2325*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_HITTEST, 0, (LPARAM)&ht);
2326*c2c66affSColin Finck     ok((HTREEITEM)ret == hRoot, "got %p, expected %p\n", (HTREEITEM)ret, hRoot);
2327*c2c66affSColin Finck     ok(ht.hItem == hRoot, "got %p, expected %p\n", ht.hItem, hRoot);
2328*c2c66affSColin Finck     ok(ht.flags == TVHT_ONITEMBUTTON, "got %d, expected %d\n", ht.flags, TVHT_ONITEMBUTTON);
2329*c2c66affSColin Finck 
2330*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)hRoot);
2331*c2c66affSColin Finck     expect(TRUE, (BOOL)ret);
2332*c2c66affSColin Finck 
2333*c2c66affSColin Finck     *(HTREEITEM*)&rc = hChild;
2334*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_GETITEMRECT, TRUE, (LPARAM)&rc);
2335*c2c66affSColin Finck     expect(TRUE, (BOOL)ret);
2336*c2c66affSColin Finck 
2337*c2c66affSColin Finck     ht.pt.x = rc.left-1;
2338*c2c66affSColin Finck     ht.pt.y = rc.top;
2339*c2c66affSColin Finck 
2340*c2c66affSColin Finck     ret = SendMessageA(hTree, TVM_HITTEST, 0, (LPARAM)&ht);
2341*c2c66affSColin Finck     ok((HTREEITEM)ret == hChild, "got %p, expected %p\n", (HTREEITEM)ret, hChild);
2342*c2c66affSColin Finck     ok(ht.hItem == hChild, "got %p, expected %p\n", ht.hItem, hChild);
2343*c2c66affSColin Finck     /* Wine returns item button here, but this item has no button */
2344*c2c66affSColin Finck     todo_wine ok(ht.flags == TVHT_ONITEMINDENT, "got %d, expected %d\n", ht.flags, TVHT_ONITEMINDENT);
2345*c2c66affSColin Finck 
2346*c2c66affSColin Finck     DestroyWindow(hTree);
2347*c2c66affSColin Finck }
2348*c2c66affSColin Finck 
2349*c2c66affSColin Finck static void test_WM_GETDLGCODE(void)
2350*c2c66affSColin Finck {
2351*c2c66affSColin Finck     DWORD code;
2352*c2c66affSColin Finck     HWND hTree;
2353*c2c66affSColin Finck 
2354*c2c66affSColin Finck     hTree = create_treeview_control(0);
2355*c2c66affSColin Finck 
2356*c2c66affSColin Finck     code = SendMessageA(hTree, WM_GETDLGCODE, VK_TAB, 0);
2357*c2c66affSColin Finck     ok(code == (DLGC_WANTCHARS | DLGC_WANTARROWS), "0x%08x\n", code);
2358*c2c66affSColin Finck 
2359*c2c66affSColin Finck     DestroyWindow(hTree);
2360*c2c66affSColin Finck }
2361*c2c66affSColin Finck 
2362*c2c66affSColin Finck static void test_customdraw(void)
2363*c2c66affSColin Finck {
2364*c2c66affSColin Finck     LOGFONTA lf;
2365*c2c66affSColin Finck     HWND hwnd;
2366*c2c66affSColin Finck 
2367*c2c66affSColin Finck     hwnd = create_treeview_control(0);
2368*c2c66affSColin Finck     fill_tree(hwnd);
2369*c2c66affSColin Finck     SendMessageA(hwnd, TVM_EXPAND, TVE_EXPAND, (WPARAM)hRoot);
2370*c2c66affSColin Finck 
2371*c2c66affSColin Finck     /* create additional font, custom draw handler will select it */
2372*c2c66affSColin Finck     SystemParametersInfoA(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
2373*c2c66affSColin Finck     lf.lfHeight *= 2;
2374*c2c66affSColin Finck     g_customdraw_font = CreateFontIndirectA(&lf);
2375*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2376*c2c66affSColin Finck     InvalidateRect(hwnd, NULL, TRUE);
2377*c2c66affSColin Finck     UpdateWindow(hwnd);
2378*c2c66affSColin Finck     ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_cd_seq, "custom draw notifications", FALSE);
2379*c2c66affSColin Finck     DeleteObject(g_customdraw_font);
2380*c2c66affSColin Finck     g_customdraw_font = NULL;
2381*c2c66affSColin Finck 
2382*c2c66affSColin Finck     DestroyWindow(hwnd);
2383*c2c66affSColin Finck }
2384*c2c66affSColin Finck 
2385*c2c66affSColin Finck static void test_WM_KEYDOWN(void)
2386*c2c66affSColin Finck {
2387*c2c66affSColin Finck     static const char *rootA = "root";
2388*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
2389*c2c66affSColin Finck     HTREEITEM hRoot;
2390*c2c66affSColin Finck     HWND hwnd;
2391*c2c66affSColin Finck 
2392*c2c66affSColin Finck     hwnd = create_treeview_control(0);
2393*c2c66affSColin Finck 
2394*c2c66affSColin Finck     ins.hParent = TVI_ROOT;
2395*c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
2396*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2397*c2c66affSColin Finck     U(ins).item.pszText = (char*)rootA;
2398*c2c66affSColin Finck     hRoot = TreeView_InsertItemA(hwnd, &ins);
2399*c2c66affSColin Finck     ok(hRoot != NULL, "got %p\n", hRoot);
2400*c2c66affSColin Finck 
2401*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2402*c2c66affSColin Finck     SendMessageA(hwnd, WM_KEYDOWN, VK_RETURN, 0);
2403*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_vk_return_seq, "WM_KEYDOWN/VK_RETURN parent notification", TRUE);
2404*c2c66affSColin Finck 
2405*c2c66affSColin Finck     DestroyWindow(hwnd);
2406*c2c66affSColin Finck }
2407*c2c66affSColin Finck 
2408*c2c66affSColin Finck static void test_TVS_FULLROWSELECT(void)
2409*c2c66affSColin Finck {
2410*c2c66affSColin Finck     DWORD style;
2411*c2c66affSColin Finck     HWND hwnd;
2412*c2c66affSColin Finck 
2413*c2c66affSColin Finck     /* try to create both with TVS_HASLINES and TVS_FULLROWSELECT */
2414*c2c66affSColin Finck     hwnd = create_treeview_control(TVS_FULLROWSELECT);
2415*c2c66affSColin Finck 
2416*c2c66affSColin Finck     style = GetWindowLongA(hwnd, GWL_STYLE);
2417*c2c66affSColin Finck     ok((style & (TVS_FULLROWSELECT | TVS_HASLINES)) == (TVS_FULLROWSELECT | TVS_HASLINES), "got style 0x%08x\n", style);
2418*c2c66affSColin Finck 
2419*c2c66affSColin Finck     DestroyWindow(hwnd);
2420*c2c66affSColin Finck 
2421*c2c66affSColin Finck     /* create just with TVS_HASLINES, try to enable TVS_FULLROWSELECT later */
2422*c2c66affSColin Finck     hwnd = create_treeview_control(0);
2423*c2c66affSColin Finck 
2424*c2c66affSColin Finck     style = GetWindowLongA(hwnd, GWL_STYLE);
2425*c2c66affSColin Finck     SetWindowLongA(hwnd, GWL_STYLE, style | TVS_FULLROWSELECT);
2426*c2c66affSColin Finck     style = GetWindowLongA(hwnd, GWL_STYLE);
2427*c2c66affSColin Finck     ok(style & TVS_FULLROWSELECT, "got style 0x%08x\n", style);
2428*c2c66affSColin Finck 
2429*c2c66affSColin Finck     DestroyWindow(hwnd);
2430*c2c66affSColin Finck }
2431*c2c66affSColin Finck 
2432*c2c66affSColin Finck static void get_item_names_string(HWND hwnd, HTREEITEM item, char *str)
2433*c2c66affSColin Finck {
2434*c2c66affSColin Finck     TVITEMA tvitem = { 0 };
2435*c2c66affSColin Finck     HTREEITEM child;
2436*c2c66affSColin Finck     char name[16];
2437*c2c66affSColin Finck 
2438*c2c66affSColin Finck     if (!item)
2439*c2c66affSColin Finck     {
2440*c2c66affSColin Finck         item = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
2441*c2c66affSColin Finck         str[0] = 0;
2442*c2c66affSColin Finck     }
2443*c2c66affSColin Finck 
2444*c2c66affSColin Finck     child = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)item);
2445*c2c66affSColin Finck 
2446*c2c66affSColin Finck     tvitem.mask = TVIF_TEXT;
2447*c2c66affSColin Finck     tvitem.hItem = item;
2448*c2c66affSColin Finck     tvitem.pszText = name;
2449*c2c66affSColin Finck     tvitem.cchTextMax = sizeof(name);
2450*c2c66affSColin Finck     SendMessageA(hwnd, TVM_GETITEMA, 0, (LPARAM)&tvitem);
2451*c2c66affSColin Finck     strcat(str, tvitem.pszText);
2452*c2c66affSColin Finck 
2453*c2c66affSColin Finck     while (child != NULL)
2454*c2c66affSColin Finck     {
2455*c2c66affSColin Finck         get_item_names_string(hwnd, child, str);
2456*c2c66affSColin Finck         child = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)child);
2457*c2c66affSColin Finck     }
2458*c2c66affSColin Finck }
2459*c2c66affSColin Finck 
2460*c2c66affSColin Finck static void fill_treeview_sort_test(HWND hwnd)
2461*c2c66affSColin Finck {
2462*c2c66affSColin Finck     static const char *itemnames[] =
2463*c2c66affSColin Finck     {
2464*c2c66affSColin Finck         "root", "Wasp", "Caribou", "Vacuum",
2465*c2c66affSColin Finck         "Ocelot", "Newspaper", "Litter bin"
2466*c2c66affSColin Finck     };
2467*c2c66affSColin Finck 
2468*c2c66affSColin Finck     HTREEITEM root, children[2];
2469*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
2470*c2c66affSColin Finck     unsigned i = 0;
2471*c2c66affSColin Finck 
2472*c2c66affSColin Finck     SendMessageA(hwnd, TVM_DELETEITEM, 0, 0);
2473*c2c66affSColin Finck 
2474*c2c66affSColin Finck     /* root, two children, with two children each */
2475*c2c66affSColin Finck     ins.hParent = TVI_ROOT;
2476*c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
2477*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2478*c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2479*c2c66affSColin Finck     root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2480*c2c66affSColin Finck 
2481*c2c66affSColin Finck     ins.hParent = root;
2482*c2c66affSColin Finck     ins.hInsertAfter = TVI_LAST;
2483*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2484*c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2485*c2c66affSColin Finck     children[0] = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2486*c2c66affSColin Finck 
2487*c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2488*c2c66affSColin Finck     children[1] = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2489*c2c66affSColin Finck 
2490*c2c66affSColin Finck     ins.hParent = children[0];
2491*c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2492*c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2493*c2c66affSColin Finck 
2494*c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2495*c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2496*c2c66affSColin Finck 
2497*c2c66affSColin Finck     ins.hParent = children[1];
2498*c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2499*c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2500*c2c66affSColin Finck 
2501*c2c66affSColin Finck     U(ins).item.pszText = (char *)itemnames[i++];
2502*c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2503*c2c66affSColin Finck }
2504*c2c66affSColin Finck 
2505*c2c66affSColin Finck static void test_TVM_SORTCHILDREN(void)
2506*c2c66affSColin Finck {
2507*c2c66affSColin Finck     static const char *initial_order = "rootWaspVacuumOcelotCaribouNewspaperLitter bin";
2508*c2c66affSColin Finck     static const char *sorted_order = "rootCaribouNewspaperLitter binWaspVacuumOcelot";
2509*c2c66affSColin Finck     TVINSERTSTRUCTA ins;
2510*c2c66affSColin Finck     char buff[256];
2511*c2c66affSColin Finck     HTREEITEM root;
2512*c2c66affSColin Finck     HWND hwnd;
2513*c2c66affSColin Finck     BOOL ret;
2514*c2c66affSColin Finck 
2515*c2c66affSColin Finck     hwnd = create_treeview_control(0);
2516*c2c66affSColin Finck 
2517*c2c66affSColin Finck     /* call on empty tree */
2518*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, 0);
2519*c2c66affSColin Finck     ok(!ret, "Unexpected ret value %d\n", ret);
2520*c2c66affSColin Finck 
2521*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)TVI_ROOT);
2522*c2c66affSColin Finck     ok(!ret, "Unexpected ret value %d\n", ret);
2523*c2c66affSColin Finck 
2524*c2c66affSColin Finck     /* add only root, sort from it */
2525*c2c66affSColin Finck     ins.hParent = TVI_ROOT;
2526*c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
2527*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2528*c2c66affSColin Finck     U(ins).item.pszText = (char *)"root";
2529*c2c66affSColin Finck     root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2530*c2c66affSColin Finck     ok(root != NULL, "Expected root node\n");
2531*c2c66affSColin Finck 
2532*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)root);
2533*c2c66affSColin Finck     ok(!ret, "Unexpected ret value %d\n", ret);
2534*c2c66affSColin Finck 
2535*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root);
2536*c2c66affSColin Finck     ok(!ret, "Unexpected ret value %d\n", ret);
2537*c2c66affSColin Finck 
2538*c2c66affSColin Finck     /* root, two children, with two children each */
2539*c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2540*c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2541*c2c66affSColin Finck     ok(!strcmp(buff, initial_order), "Wrong initial order %s, expected %s\n", buff, initial_order);
2542*c2c66affSColin Finck 
2543*c2c66affSColin Finck     /* with NULL item nothing is sorted */
2544*c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2545*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, 0);
2546*c2c66affSColin Finck todo_wine
2547*c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2548*c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2549*c2c66affSColin Finck     ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, initial_order);
2550*c2c66affSColin Finck 
2551*c2c66affSColin Finck     /* TVI_ROOT as item */
2552*c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2553*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)TVI_ROOT);
2554*c2c66affSColin Finck todo_wine
2555*c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2556*c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2557*c2c66affSColin Finck     ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, initial_order);
2558*c2c66affSColin Finck 
2559*c2c66affSColin Finck     /* zero WPARAM, item is specified */
2560*c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2561*c2c66affSColin Finck     root = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
2562*c2c66affSColin Finck     ok(root != NULL, "Failed to get root item\n");
2563*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)root);
2564*c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2565*c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2566*c2c66affSColin Finck     ok(!strcmp(buff, sorted_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
2567*c2c66affSColin Finck 
2568*c2c66affSColin Finck     /* non-zero WPARAM, NULL item */
2569*c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2570*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, 0);
2571*c2c66affSColin Finck todo_wine
2572*c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2573*c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2574*c2c66affSColin Finck     ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
2575*c2c66affSColin Finck 
2576*c2c66affSColin Finck     /* TVI_ROOT as item */
2577*c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2578*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)TVI_ROOT);
2579*c2c66affSColin Finck todo_wine
2580*c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2581*c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2582*c2c66affSColin Finck     ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
2583*c2c66affSColin Finck 
2584*c2c66affSColin Finck     /* non-zero WPARAM, item is specified */
2585*c2c66affSColin Finck     fill_treeview_sort_test(hwnd);
2586*c2c66affSColin Finck     root = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0);
2587*c2c66affSColin Finck     ok(root != NULL, "Failed to get root item\n");
2588*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root);
2589*c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2590*c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2591*c2c66affSColin Finck     ok(!strcmp(buff, sorted_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order);
2592*c2c66affSColin Finck 
2593*c2c66affSColin Finck     /* case insensitive comparison */
2594*c2c66affSColin Finck     SendMessageA(hwnd, TVM_DELETEITEM, 0, 0);
2595*c2c66affSColin Finck 
2596*c2c66affSColin Finck     ins.hParent = TVI_ROOT;
2597*c2c66affSColin Finck     ins.hInsertAfter = TVI_ROOT;
2598*c2c66affSColin Finck     U(ins).item.mask = TVIF_TEXT;
2599*c2c66affSColin Finck     U(ins).item.pszText = (char *)"root";
2600*c2c66affSColin Finck     root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2601*c2c66affSColin Finck     ok(root != NULL, "Expected root node\n");
2602*c2c66affSColin Finck 
2603*c2c66affSColin Finck     ins.hParent = root;
2604*c2c66affSColin Finck     ins.hInsertAfter = TVI_LAST;
2605*c2c66affSColin Finck     U(ins).item.pszText = (char *)"I1";
2606*c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2607*c2c66affSColin Finck 
2608*c2c66affSColin Finck     ins.hParent = root;
2609*c2c66affSColin Finck     ins.hInsertAfter = TVI_LAST;
2610*c2c66affSColin Finck     U(ins).item.pszText = (char *)"i1";
2611*c2c66affSColin Finck     SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins);
2612*c2c66affSColin Finck 
2613*c2c66affSColin Finck     ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root);
2614*c2c66affSColin Finck     ok(ret, "Unexpected ret value %d\n", ret);
2615*c2c66affSColin Finck     get_item_names_string(hwnd, NULL, buff);
2616*c2c66affSColin Finck     ok(!strcmp(buff, "rootI1i1"), "Wrong sorted order %s\n", buff);
2617*c2c66affSColin Finck 
2618*c2c66affSColin Finck     DestroyWindow(hwnd);
2619*c2c66affSColin Finck }
2620*c2c66affSColin Finck 
2621*c2c66affSColin Finck static void test_right_click(void)
2622*c2c66affSColin Finck {
2623*c2c66affSColin Finck     HWND hTree;
2624*c2c66affSColin Finck     HTREEITEM selected;
2625*c2c66affSColin Finck     RECT rc;
2626*c2c66affSColin Finck     LRESULT result;
2627*c2c66affSColin Finck     POINT pt;
2628*c2c66affSColin Finck 
2629*c2c66affSColin Finck     hTree = create_treeview_control(0);
2630*c2c66affSColin Finck     fill_tree(hTree);
2631*c2c66affSColin Finck 
2632*c2c66affSColin Finck     SendMessageA(hTree, TVM_ENSUREVISIBLE, 0, (LPARAM)hChild);
2633*c2c66affSColin Finck     SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
2634*c2c66affSColin Finck     selected = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0);
2635*c2c66affSColin Finck     ok(selected == hChild, "child item not selected\n");
2636*c2c66affSColin Finck 
2637*c2c66affSColin Finck     *(HTREEITEM *)&rc = hRoot;
2638*c2c66affSColin Finck     result = SendMessageA(hTree, TVM_GETITEMRECT, TRUE, (LPARAM)&rc);
2639*c2c66affSColin Finck     ok(result, "TVM_GETITEMRECT failed\n");
2640*c2c66affSColin Finck 
2641*c2c66affSColin Finck     flush_events();
2642*c2c66affSColin Finck 
2643*c2c66affSColin Finck     pt.x = (rc.left + rc.right) / 2;
2644*c2c66affSColin Finck     pt.y = (rc.top + rc.bottom) / 2;
2645*c2c66affSColin Finck     ClientToScreen(hMainWnd, &pt);
2646*c2c66affSColin Finck 
2647*c2c66affSColin Finck     flush_events();
2648*c2c66affSColin Finck     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2649*c2c66affSColin Finck 
2650*c2c66affSColin Finck     PostMessageA(hTree, WM_RBUTTONDOWN, MK_RBUTTON, MAKELPARAM(pt.x, pt.y));
2651*c2c66affSColin Finck     PostMessageA(hTree, WM_RBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
2652*c2c66affSColin Finck 
2653*c2c66affSColin Finck     flush_events();
2654*c2c66affSColin Finck 
2655*c2c66affSColin Finck     ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_right_click_seq, "right click sequence", FALSE);
2656*c2c66affSColin Finck     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_right_click_seq, "parent right click sequence", FALSE);
2657*c2c66affSColin Finck 
2658*c2c66affSColin Finck     selected = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0);
2659*c2c66affSColin Finck     ok(selected == hChild, "child item should still be selected\n");
2660*c2c66affSColin Finck 
2661*c2c66affSColin Finck     DestroyWindow(hTree);
2662*c2c66affSColin Finck }
2663*c2c66affSColin Finck 
2664*c2c66affSColin Finck START_TEST(treeview)
2665*c2c66affSColin Finck {
2666*c2c66affSColin Finck     HMODULE hComctl32;
2667*c2c66affSColin Finck     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
2668*c2c66affSColin Finck     WNDCLASSA wc;
2669*c2c66affSColin Finck     MSG msg;
2670*c2c66affSColin Finck 
2671*c2c66affSColin Finck     ULONG_PTR ctx_cookie;
2672*c2c66affSColin Finck     HANDLE hCtx;
2673*c2c66affSColin Finck 
2674*c2c66affSColin Finck     hComctl32 = GetModuleHandleA("comctl32.dll");
2675*c2c66affSColin Finck     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
2676*c2c66affSColin Finck     if (pInitCommonControlsEx)
2677*c2c66affSColin Finck     {
2678*c2c66affSColin Finck         INITCOMMONCONTROLSEX iccex;
2679*c2c66affSColin Finck         iccex.dwSize = sizeof(iccex);
2680*c2c66affSColin Finck         iccex.dwICC  = ICC_TREEVIEW_CLASSES;
2681*c2c66affSColin Finck         pInitCommonControlsEx(&iccex);
2682*c2c66affSColin Finck     }
2683*c2c66affSColin Finck     else
2684*c2c66affSColin Finck         InitCommonControls();
2685*c2c66affSColin Finck 
2686*c2c66affSColin Finck     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2687*c2c66affSColin Finck     init_msg_sequences(item_sequence, 1);
2688*c2c66affSColin Finck 
2689*c2c66affSColin Finck     wc.style = CS_HREDRAW | CS_VREDRAW;
2690*c2c66affSColin Finck     wc.cbClsExtra = 0;
2691*c2c66affSColin Finck     wc.cbWndExtra = 0;
2692*c2c66affSColin Finck     wc.hInstance = GetModuleHandleA(NULL);
2693*c2c66affSColin Finck     wc.hIcon = NULL;
2694*c2c66affSColin Finck     wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_IBEAM);
2695*c2c66affSColin Finck     wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
2696*c2c66affSColin Finck     wc.lpszMenuName = NULL;
2697*c2c66affSColin Finck     wc.lpszClassName = "MyTestWnd";
2698*c2c66affSColin Finck     wc.lpfnWndProc = parent_wnd_proc;
2699*c2c66affSColin Finck     RegisterClassA(&wc);
2700*c2c66affSColin Finck 
2701*c2c66affSColin Finck     hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
2702*c2c66affSColin Finck       CW_USEDEFAULT, CW_USEDEFAULT, 130, 105, NULL, NULL, GetModuleHandleA(NULL), 0);
2703*c2c66affSColin Finck 
2704*c2c66affSColin Finck     ok(hMainWnd != NULL, "Failed to create parent window. Tests aborted.\n");
2705*c2c66affSColin Finck     if (!hMainWnd) return;
2706*c2c66affSColin Finck 
2707*c2c66affSColin Finck     test_fillroot();
2708*c2c66affSColin Finck     test_select();
2709*c2c66affSColin Finck     test_getitemtext();
2710*c2c66affSColin Finck     test_focus();
2711*c2c66affSColin Finck     test_get_set_bkcolor();
2712*c2c66affSColin Finck     test_get_set_imagelist();
2713*c2c66affSColin Finck     test_get_set_indent();
2714*c2c66affSColin Finck     test_get_set_insertmark();
2715*c2c66affSColin Finck     test_get_set_item();
2716*c2c66affSColin Finck     test_get_set_itemheight();
2717*c2c66affSColin Finck     test_get_set_scrolltime();
2718*c2c66affSColin Finck     test_get_set_textcolor();
2719*c2c66affSColin Finck     test_get_linecolor();
2720*c2c66affSColin Finck     test_get_insertmarkcolor();
2721*c2c66affSColin Finck     test_get_set_tooltips();
2722*c2c66affSColin Finck     test_get_set_unicodeformat();
2723*c2c66affSColin Finck     test_callback();
2724*c2c66affSColin Finck     test_expandinvisible();
2725*c2c66affSColin Finck     test_itemedit();
2726*c2c66affSColin Finck     test_treeview_classinfo();
2727*c2c66affSColin Finck     test_expandnotify();
2728*c2c66affSColin Finck     test_TVS_SINGLEEXPAND();
2729*c2c66affSColin Finck     test_WM_PAINT();
2730*c2c66affSColin Finck     test_delete_items();
2731*c2c66affSColin Finck     test_cchildren();
2732*c2c66affSColin Finck     test_htreeitem_layout();
2733*c2c66affSColin Finck     test_TVS_CHECKBOXES();
2734*c2c66affSColin Finck     test_TVM_GETNEXTITEM();
2735*c2c66affSColin Finck     test_TVM_HITTEST();
2736*c2c66affSColin Finck     test_WM_GETDLGCODE();
2737*c2c66affSColin Finck     test_customdraw();
2738*c2c66affSColin Finck     test_WM_KEYDOWN();
2739*c2c66affSColin Finck     test_TVS_FULLROWSELECT();
2740*c2c66affSColin Finck     test_TVM_SORTCHILDREN();
2741*c2c66affSColin Finck     test_right_click();
2742*c2c66affSColin Finck 
2743*c2c66affSColin Finck     if (!load_v6_module(&ctx_cookie, &hCtx))
2744*c2c66affSColin Finck     {
2745*c2c66affSColin Finck         DestroyWindow(hMainWnd);
2746*c2c66affSColin Finck         return;
2747*c2c66affSColin Finck     }
2748*c2c66affSColin Finck 
2749*c2c66affSColin Finck     /* comctl32 version 6 tests start here */
2750*c2c66affSColin Finck     g_v6 = TRUE;
2751*c2c66affSColin Finck     test_expandedimage();
2752*c2c66affSColin Finck     test_htreeitem_layout();
2753*c2c66affSColin Finck     test_WM_GETDLGCODE();
2754*c2c66affSColin Finck 
2755*c2c66affSColin Finck     unload_v6_module(ctx_cookie, hCtx);
2756*c2c66affSColin Finck 
2757*c2c66affSColin Finck     PostMessageA(hMainWnd, WM_CLOSE, 0, 0);
2758*c2c66affSColin Finck     while(GetMessageA(&msg, 0, 0, 0))
2759*c2c66affSColin Finck     {
2760*c2c66affSColin Finck         TranslateMessage(&msg);
2761*c2c66affSColin Finck         DispatchMessageA(&msg);
2762*c2c66affSColin Finck     }
2763*c2c66affSColin Finck }
2764