avrt: Add initial stub implementation.
[wine] / dlls / comctl32 / tests / tab.c
1 /* Unit test suite for tab control.
2  *
3  * Copyright 2003 Vitaliy Margolen
4  * Copyright 2007 Hagop Hagopian
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <assert.h>
22 #include <windows.h>
23 #include <commctrl.h>
24 #include <stdio.h>
25
26 #include "wine/test.h"
27 #include "msg.h"
28
29 #define DEFAULT_MIN_TAB_WIDTH 54
30 #define TAB_PADDING_X 6
31 #define EXTRA_ICON_PADDING 3
32 #define MAX_TABLEN 32
33
34 #define NUM_MSG_SEQUENCES  2
35 #define PARENT_SEQ_INDEX   0
36 #define TAB_SEQ_INDEX      1
37
38 #define expect(expected, got) ok ( expected == got, "Expected %d, got %d\n", expected, got)
39 #define expect_str(expected, got)\
40  ok ( strcmp(expected, got) == 0, "Expected '%s', got '%s'\n", expected, got)
41
42 #define TabWidthPadded(padd_x, num) (DEFAULT_MIN_TAB_WIDTH - (TAB_PADDING_X - (padd_x)) * num)
43
44 #define TabCheckSetSize(hwnd, SetWidth, SetHeight, ExpWidth, ExpHeight, Msg)\
45     SendMessage (hwnd, TCM_SETITEMSIZE, 0,\
46         (LPARAM) MAKELPARAM((SetWidth >= 0) ? SetWidth:0, (SetHeight >= 0) ? SetHeight:0));\
47     if (winetest_interactive) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW);\
48     CheckSize(hwnd, ExpWidth, ExpHeight, Msg);
49
50 #define CheckSize(hwnd,width,height,msg)\
51     SendMessage (hwnd, TCM_GETITEMRECT, 0, (LPARAM) &rTab);\
52     if ((width  >= 0) && (height < 0))\
53         ok (width  == rTab.right  - rTab.left, "%s: Expected width [%d] got [%d]\n",\
54         msg, (int)width,  rTab.right  - rTab.left);\
55     else if ((height >= 0) && (width  < 0))\
56         ok (height == rTab.bottom - rTab.top,  "%s: Expected height [%d] got [%d]\n",\
57         msg, (int)height, rTab.bottom - rTab.top);\
58     else\
59         ok ((width  == rTab.right  - rTab.left) &&\
60             (height == rTab.bottom - rTab.top ),\
61             "%s: Expected [%d,%d] got [%d,%d]\n", msg, (int)width, (int)height,\
62             rTab.right - rTab.left, rTab.bottom - rTab.top);
63
64 static HFONT hFont = 0;
65
66 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
67
68 static const struct message create_parent_wnd_seq[] = {
69     { WM_GETMINMAXINFO, sent },
70     { WM_NCCREATE, sent },
71     { WM_NCCALCSIZE, sent|wparam, 0 },
72     { WM_CREATE, sent },
73     { WM_SHOWWINDOW, sent|wparam, 1 },
74     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
75     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
76     { WM_ACTIVATEAPP, sent|wparam, 1 },
77     { WM_NCACTIVATE, sent|wparam, 1 },
78     { WM_ACTIVATE, sent|wparam, 1 },
79     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
80     { WM_IME_NOTIFY, sent|defwinproc|optional },
81     { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
82     /* Win9x adds SWP_NOZORDER below */
83     { WM_WINDOWPOSCHANGED, sent},
84     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
85     { WM_SIZE, sent },
86     { WM_MOVE, sent },
87     { 0 }
88 };
89
90 static const struct message add_tab_to_parent[] = {
91     { TCM_INSERTITEMA, sent },
92     { TCM_INSERTITEMA, sent|optional },
93     { WM_NOTIFYFORMAT, sent|defwinproc },
94     { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc|optional, 0, 0 },
95     { WM_PARENTNOTIFY, sent|defwinproc },
96     { TCM_INSERTITEMA, sent },
97     { TCM_INSERTITEMA, sent },
98     { TCM_INSERTITEMA, sent },
99     { TCM_INSERTITEMA, sent|optional },
100     { 0 }
101 };
102
103 static const struct message add_tab_to_parent_interactive[] = {
104     { TCM_INSERTITEMA, sent },
105     { TCM_INSERTITEMA, sent },
106     { WM_NOTIFYFORMAT, sent|defwinproc },
107     { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc, 0, 0 },
108     { WM_PARENTNOTIFY, sent|defwinproc },
109     { TCM_INSERTITEMA, sent },
110     { TCM_INSERTITEMA, sent },
111     { TCM_INSERTITEMA, sent },
112     { WM_SHOWWINDOW, sent},
113     { WM_WINDOWPOSCHANGING, sent},
114     { WM_WINDOWPOSCHANGING, sent},
115     { WM_NCACTIVATE, sent},
116     { WM_ACTIVATE, sent},
117     { WM_IME_SETCONTEXT, sent|defwinproc|optional},
118     { WM_IME_NOTIFY, sent|defwinproc|optional},
119     { WM_SETFOCUS, sent|defwinproc},
120     { WM_WINDOWPOSCHANGED, sent},
121     { WM_SIZE, sent},
122     { WM_MOVE, sent},
123     { 0 }
124 };
125
126 static const struct message add_tab_control_parent_seq[] = {
127     { WM_NOTIFYFORMAT, sent },
128     { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 },
129     { 0 }
130 };
131
132 static const struct message add_tab_control_parent_seq_interactive[] = {
133     { WM_NOTIFYFORMAT, sent },
134     { WM_QUERYUISTATE, sent|wparam|lparam, 0, 0 },
135     { WM_WINDOWPOSCHANGING, sent|optional},
136     { WM_NCACTIVATE, sent},
137     { WM_ACTIVATE, sent},
138     { WM_WINDOWPOSCHANGING, sent|optional},
139     { WM_KILLFOCUS, sent},
140     { WM_IME_SETCONTEXT, sent|optional},
141     { WM_IME_NOTIFY, sent|optional},
142     { 0 }
143 };
144
145 static const struct message empty_sequence[] = {
146     { 0 }
147 };
148
149 static const struct message set_min_tab_width_seq[] = {
150     { TCM_SETMINTABWIDTH, sent|wparam, 0 },
151     { TCM_SETMINTABWIDTH, sent|wparam, 0 },
152     { 0 }
153 };
154
155 static const struct message get_item_count_seq[] = {
156     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
157     { 0 }
158 };
159
160 static const struct message get_row_count_seq[] = {
161     { TCM_GETROWCOUNT, sent|wparam|lparam, 0, 0 },
162     { 0 }
163 };
164
165 static const struct message get_item_rect_seq[] = {
166     { TCM_GETITEMRECT, sent },
167     { TCM_GETITEMRECT, sent },
168     { 0 }
169 };
170
171 static const struct message getset_cur_focus_seq[] = {
172     { TCM_SETCURFOCUS, sent|lparam, 0 },
173     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
174     { TCM_SETCURFOCUS, sent|lparam, 0 },
175     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
176     { TCM_SETCURSEL, sent|lparam, 0 },
177     { TCM_SETCURFOCUS, sent|lparam, 0 },
178     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
179     { 0 }
180 };
181
182 static const struct message getset_cur_sel_seq[] = {
183     { TCM_SETCURSEL, sent|lparam, 0 },
184     { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
185     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
186     { TCM_SETCURSEL, sent|lparam, 0 },
187     { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
188     { TCM_SETCURSEL, sent|lparam, 0 },
189     { TCM_SETCURSEL, sent|lparam, 0 },
190     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
191     { 0 }
192 };
193
194 static const struct message getset_extended_style_seq[] = {
195     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
196     { TCM_SETEXTENDEDSTYLE, sent },
197     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
198     { TCM_SETEXTENDEDSTYLE, sent },
199     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
200     { 0 }
201 };
202
203 static const struct message getset_unicode_format_seq[] = {
204     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
205     { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
206     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
207     { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
208     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
209     { 0 }
210 };
211
212 static const struct message getset_item_seq[] = {
213     { TCM_SETITEMA, sent },
214     { TCM_GETITEMA, sent },
215     { TCM_GETITEMA, sent },
216     { 0 }
217 };
218
219 static const struct message getset_tooltip_seq[] = {
220     { WM_NOTIFYFORMAT, sent|optional },
221     { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 },
222     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
223     { WM_NOTIFYFORMAT, sent|optional },
224     { TCM_SETTOOLTIPS, sent|lparam, 0 },
225     { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
226     { TCM_SETTOOLTIPS, sent|lparam, 0 },
227     { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
228     { 0 }
229 };
230
231 static const struct message getset_tooltip_parent_seq[] = {
232     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
233     { 0 }
234 };
235
236 static const struct message insert_focus_seq[] = {
237     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
238     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
239     { TCM_INSERTITEM, sent|wparam, 1 },
240     { WM_NOTIFYFORMAT, sent|defwinproc|optional },
241     { WM_QUERYUISTATE, sent|defwinproc|optional },
242     { WM_PARENTNOTIFY, sent|defwinproc|optional },
243     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
244     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
245     { TCM_INSERTITEM, sent|wparam, 2 },
246     { WM_NOTIFYFORMAT, sent|defwinproc|optional },
247     { WM_QUERYUISTATE, sent|defwinproc|optional, },
248     { WM_PARENTNOTIFY, sent|defwinproc|optional },
249     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
250     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
251     { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
252     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
253     { TCM_INSERTITEM, sent|wparam, 3 },
254     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
255     { 0 }
256 };
257
258 static const struct message delete_focus_seq[] = {
259     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
260     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
261     { TCM_DELETEITEM, sent|wparam|lparam, 1, 0 },
262     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
263     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
264     { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
265     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
266     { TCM_DELETEITEM, sent|wparam|lparam, 0, 0 },
267     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
268     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
269     { 0 }
270 };
271
272
273 static HWND
274 create_tabcontrol (DWORD style, DWORD mask)
275 {
276     HWND handle;
277     TCITEM tcNewTab;
278     static char text1[] = "Tab 1",
279     text2[] = "Wide Tab 2",
280     text3[] = "T 3";
281
282     handle = CreateWindow (
283         WC_TABCONTROLA,
284         "TestTab",
285         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style,
286         10, 10, 300, 100,
287         NULL, NULL, NULL, 0);
288
289     assert (handle);
290
291     SetWindowLong(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style);
292     SendMessage (handle, WM_SETFONT, 0, (LPARAM) hFont);
293
294     tcNewTab.mask = mask;
295     tcNewTab.pszText = text1;
296     tcNewTab.iImage = 0;
297     SendMessage (handle, TCM_INSERTITEM, 0, (LPARAM) &tcNewTab);
298     tcNewTab.pszText = text2;
299     tcNewTab.iImage = 1;
300     SendMessage (handle, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab);
301     tcNewTab.pszText = text3;
302     tcNewTab.iImage = 2;
303     SendMessage (handle, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
304
305     if (winetest_interactive)
306     {
307         ShowWindow (handle, SW_SHOW);
308         RedrawWindow (handle, NULL, 0, RDW_UPDATENOW);
309         Sleep (1000);
310     }
311
312     return handle;
313 }
314
315 static LRESULT WINAPI parentWindowProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
316 {
317     static LONG defwndproc_counter = 0;
318     LRESULT ret;
319     struct message msg;
320
321     /* do not log painting messages */
322     if (message != WM_PAINT &&
323         message != WM_ERASEBKGND &&
324         message != WM_NCPAINT &&
325         message != WM_NCHITTEST &&
326         message != WM_GETTEXT &&
327         message != WM_GETICON &&
328         message != WM_DEVICECHANGE)
329     {
330         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
331
332         msg.message = message;
333         msg.flags = sent|wparam|lparam;
334         if (defwndproc_counter) msg.flags |= defwinproc;
335         msg.wParam = wParam;
336         msg.lParam = lParam;
337         add_message(sequences, PARENT_SEQ_INDEX, &msg);
338     }
339
340     defwndproc_counter++;
341     ret = DefWindowProcA(hwnd, message, wParam, lParam);
342     defwndproc_counter--;
343
344     return ret;
345 }
346
347 static BOOL registerParentWindowClass(void)
348 {
349     WNDCLASSA cls;
350
351     cls.style = 0;
352     cls.lpfnWndProc = parentWindowProcess;
353     cls.cbClsExtra = 0;
354     cls.cbWndExtra = 0;
355     cls.hInstance = GetModuleHandleA(NULL);
356     cls.hIcon = 0;
357     cls.hCursor = LoadCursorA(0, IDC_ARROW);
358     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
359     cls.lpszMenuName = NULL;
360     cls.lpszClassName = "Tab test parent class";
361     return RegisterClassA(&cls);
362 }
363
364 static HWND createParentWindow(void)
365 {
366     if (!registerParentWindowClass())
367         return NULL;
368
369     return CreateWindowEx(0, "Tab test parent class",
370                           "Tab test parent window",
371                           WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
372                           WS_MAXIMIZEBOX | WS_VISIBLE,
373                           0, 0, 100, 100,
374                           GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
375 }
376
377 static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
378 {
379     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
380     static LONG defwndproc_counter = 0;
381     LRESULT ret;
382     struct message msg;
383
384     /* do not log painting messages */
385     if (message != WM_PAINT &&
386         message != WM_ERASEBKGND &&
387         message != WM_NCPAINT &&
388         message != WM_NCHITTEST &&
389         message != WM_GETTEXT &&
390         message != WM_GETICON &&
391         message != WM_DEVICECHANGE)
392     {
393         trace("tab: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
394
395         msg.message = message;
396         msg.flags = sent|wparam|lparam;
397         if (defwndproc_counter) msg.flags |= defwinproc;
398         msg.wParam = wParam;
399         msg.lParam = lParam;
400         add_message(sequences, TAB_SEQ_INDEX, &msg);
401     }
402
403     defwndproc_counter++;
404     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
405     defwndproc_counter--;
406
407     return ret;
408 }
409
410 static HWND createFilledTabControl(HWND parent_wnd, DWORD style, DWORD mask, INT nTabs)
411 {
412     HWND tabHandle;
413     TCITEM tcNewTab;
414     WNDPROC oldproc;
415     RECT rect;
416     INT i;
417
418     GetClientRect(parent_wnd, &rect);
419
420     tabHandle = CreateWindow (
421         WC_TABCONTROLA,
422         "TestTab",
423         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style,
424         0, 0, rect.right, rect.bottom,
425         parent_wnd, NULL, NULL, 0);
426
427     assert(tabHandle);
428
429     oldproc = (WNDPROC)SetWindowLongPtrA(tabHandle, GWLP_WNDPROC, (LONG_PTR)tabSubclassProcess);
430     SetWindowLongPtrA(tabHandle, GWLP_USERDATA, (LONG_PTR)oldproc);
431
432     tcNewTab.mask = mask;
433
434     for (i = 0; i < nTabs; i++)
435     {
436         char tabName[MAX_TABLEN];
437
438         sprintf(tabName, "Tab %d", i+1);
439         tcNewTab.pszText = tabName;
440         tcNewTab.iImage = i;
441         SendMessage (tabHandle, TCM_INSERTITEM, i, (LPARAM) &tcNewTab);
442     }
443
444     if (winetest_interactive)
445     {
446         ShowWindow (tabHandle, SW_SHOW);
447         RedrawWindow (tabHandle, NULL, 0, RDW_UPDATENOW);
448         Sleep (1000);
449     }
450
451     return tabHandle;
452 }
453
454 static HWND create_tooltip (HWND hTab, char toolTipText[])
455 {
456     HWND hwndTT;
457
458     TOOLINFO ti;
459     LPTSTR lptstr = toolTipText;
460     RECT rect;
461
462     /* Creating a tooltip window*/
463     hwndTT = CreateWindowEx(
464         WS_EX_TOPMOST,
465         TOOLTIPS_CLASS,
466         NULL,
467         WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
468         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
469         hTab, NULL, 0, NULL);
470
471     SetWindowPos(
472         hwndTT,
473         HWND_TOPMOST,
474         0, 0, 0, 0,
475         SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
476
477     GetClientRect (hTab, &rect);
478
479     /* Initialize members of toolinfo*/
480     ti.cbSize = sizeof(TOOLINFO);
481     ti.uFlags = TTF_SUBCLASS;
482     ti.hwnd = hTab;
483     ti.hinst = 0;
484     ti.uId = 0;
485     ti.lpszText = lptstr;
486
487     ti.rect = rect;
488
489     /* Add toolinfo structure to the tooltip control */
490     SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) &ti);
491
492     return hwndTT;
493 }
494
495 static void test_tab(INT nMinTabWidth)
496 {
497     HWND hwTab;
498     RECT rTab;
499     HIMAGELIST himl = ImageList_Create(21, 21, ILC_COLOR, 3, 4);
500     SIZE size;
501     HDC hdc;
502     HFONT hOldFont;
503     INT i, dpi, exp;
504
505     hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
506     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
507     /* Get System default MinTabWidth */
508     if (nMinTabWidth < 0)
509         nMinTabWidth = SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
510
511     hdc = GetDC(hwTab);
512     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
513     hOldFont = SelectObject(hdc, (HFONT)SendMessage(hwTab, WM_GETFONT, 0, 0));
514     GetTextExtentPoint32A(hdc, "Tab 1", strlen("Tab 1"), &size);
515     trace("Tab1 text size: size.cx=%d size.cy=%d\n", size.cx, size.cy);
516     SelectObject(hdc, hOldFont);
517     ReleaseDC(hwTab, hdc);
518
519     trace ("  TCS_FIXEDWIDTH tabs no icon...\n");
520     CheckSize(hwTab, dpi, -1, "default width");
521     TabCheckSetSize(hwTab, 50, 20, 50, 20, "set size");
522     TabCheckSetSize(hwTab, 0, 1, 0, 1, "min size");
523
524     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
525
526     trace ("  TCS_FIXEDWIDTH tabs with icon...\n");
527     TabCheckSetSize(hwTab, 50, 30, 50, 30, "set size > icon");
528     TabCheckSetSize(hwTab, 20, 20, 25, 20, "set size < icon");
529     TabCheckSetSize(hwTab, 0, 1, 25, 1, "min size");
530
531     DestroyWindow (hwTab);
532
533     hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS, TCIF_TEXT|TCIF_IMAGE);
534     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
535
536     hdc = GetDC(hwTab);
537     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
538     ReleaseDC(hwTab, hdc);
539     trace ("  TCS_FIXEDWIDTH buttons no icon...\n");
540     CheckSize(hwTab, dpi, -1, "default width");
541     TabCheckSetSize(hwTab, 20, 20, 20, 20, "set size 1");
542     TabCheckSetSize(hwTab, 10, 50, 10, 50, "set size 2");
543     TabCheckSetSize(hwTab, 0, 1, 0, 1, "min size");
544
545     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
546
547     trace ("  TCS_FIXEDWIDTH buttons with icon...\n");
548     TabCheckSetSize(hwTab, 50, 30, 50, 30, "set size > icon");
549     TabCheckSetSize(hwTab, 20, 20, 25, 20, "set size < icon");
550     TabCheckSetSize(hwTab, 0, 1, 25, 1, "min size");
551     SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
552     TabCheckSetSize(hwTab, 0, 1, 25, 1, "set padding, min size");
553
554     DestroyWindow (hwTab);
555
556     hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM, TCIF_TEXT|TCIF_IMAGE);
557     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
558
559     hdc = GetDC(hwTab);
560     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
561     ReleaseDC(hwTab, hdc);
562     trace ("  TCS_FIXEDWIDTH | TCS_BOTTOM tabs...\n");
563     CheckSize(hwTab, dpi, -1, "no icon, default width");
564
565     TabCheckSetSize(hwTab, 20, 20, 20, 20, "no icon, set size 1");
566     TabCheckSetSize(hwTab, 10, 50, 10, 50, "no icon, set size 2");
567     TabCheckSetSize(hwTab, 0, 1, 0, 1, "no icon, min size");
568
569     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
570
571     TabCheckSetSize(hwTab, 50, 30, 50, 30, "with icon, set size > icon");
572     TabCheckSetSize(hwTab, 20, 20, 25, 20, "with icon, set size < icon");
573     TabCheckSetSize(hwTab, 0, 1, 25, 1, "with icon, min size");
574     SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
575     TabCheckSetSize(hwTab, 0, 1, 25, 1, "set padding, min size");
576
577     DestroyWindow (hwTab);
578
579     hwTab = create_tabcontrol(0, TCIF_TEXT|TCIF_IMAGE);
580     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
581
582     trace ("  non fixed width, with text...\n");
583     exp = max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth);
584     SendMessage( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
585     ok( rTab.right  - rTab.left == exp || broken(rTab.right  - rTab.left == DEFAULT_MIN_TAB_WIDTH),
586         "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
587
588     for (i=0; i<8; i++)
589     {
590         INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
591
592         SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0);
593         SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i));
594
595         TabCheckSetSize(hwTab, 50, 20, max(size.cx + i*2, nTabWidth), 20, "no icon, set size");
596         TabCheckSetSize(hwTab, 0, 1, max(size.cx + i*2, nTabWidth), 1, "no icon, min size");
597
598         SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
599         nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 3) : nMinTabWidth;
600
601         TabCheckSetSize(hwTab, 50, 30, max(size.cx + 21 + i*3, nTabWidth), 30, "with icon, set size > icon");
602         TabCheckSetSize(hwTab, 20, 20, max(size.cx + 21 + i*3, nTabWidth), 20, "with icon, set size < icon");
603         TabCheckSetSize(hwTab, 0, 1, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size");
604     }
605     DestroyWindow (hwTab);
606
607     hwTab = create_tabcontrol(0, TCIF_IMAGE);
608     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
609
610     trace ("  non fixed width, no text...\n");
611     exp = (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth;
612     SendMessage( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
613     ok( rTab.right  - rTab.left == exp || broken(rTab.right  - rTab.left == DEFAULT_MIN_TAB_WIDTH),
614         "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
615
616     for (i=0; i<8; i++)
617     {
618         INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
619
620         SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0);
621         SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i));
622
623         TabCheckSetSize(hwTab, 50, 20, nTabWidth, 20, "no icon, set size");
624         TabCheckSetSize(hwTab, 0, 1, nTabWidth, 1, "no icon, min size");
625
626         SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
627         if (i > 1 && nMinTabWidth > 0 && nMinTabWidth < DEFAULT_MIN_TAB_WIDTH)
628             nTabWidth += EXTRA_ICON_PADDING *(i-1);
629
630         TabCheckSetSize(hwTab, 50, 30, nTabWidth, 30, "with icon, set size > icon");
631         TabCheckSetSize(hwTab, 20, 20, nTabWidth, 20, "with icon, set size < icon");
632         TabCheckSetSize(hwTab, 0, 1, nTabWidth, 1, "with icon, min size");
633     }
634
635     DestroyWindow (hwTab);
636
637     ImageList_Destroy(himl);
638     DeleteObject(hFont);
639 }
640
641 static void test_getters_setters(HWND parent_wnd, INT nTabs)
642 {
643     HWND hTab;
644     RECT rTab;
645     INT nTabsRetrieved;
646     INT rowCount;
647     INT dpi;
648     HDC hdc;
649
650     ok(parent_wnd != NULL, "no parent window!\n");
651     flush_sequences(sequences, NUM_MSG_SEQUENCES);
652
653     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
654     ok(hTab != NULL, "Failed to create tab control\n");
655
656     if(!winetest_interactive)
657         ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent,
658                     "Tab sequence, after adding tab control to parent", TRUE);
659     else
660         ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent_interactive,
661                     "Tab sequence, after adding tab control to parent", TRUE);
662
663     if(!winetest_interactive)
664         ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq,
665                     "Parent after sequence, adding tab control to parent", TRUE);
666     else
667         ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq_interactive,
668                     "Parent after sequence, adding tab control to parent", TRUE);
669
670     flush_sequences(sequences, NUM_MSG_SEQUENCES);
671     ok(SendMessage(hTab, TCM_SETMINTABWIDTH, 0, -1) > 0,"TCM_SETMINTABWIDTH returned < 0\n");
672     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Set minTabWidth test parent sequence", FALSE);
673
674     /* Testing GetItemCount */
675     flush_sequences(sequences, NUM_MSG_SEQUENCES);
676     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
677     expect(nTabs, nTabsRetrieved);
678     ok_sequence(sequences, TAB_SEQ_INDEX, get_item_count_seq, "Get itemCount test sequence", FALSE);
679     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset itemCount test parent sequence", FALSE);
680
681     /* Testing GetRowCount */
682     flush_sequences(sequences, NUM_MSG_SEQUENCES);
683     rowCount = SendMessage(hTab, TCM_GETROWCOUNT, 0, 0);
684     expect(1, rowCount);
685     ok_sequence(sequences, TAB_SEQ_INDEX, get_row_count_seq, "Get rowCount test sequence", FALSE);
686     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get rowCount test parent sequence", FALSE);
687
688     /* Testing GetItemRect */
689     flush_sequences(sequences, NUM_MSG_SEQUENCES);
690     ok(SendMessage(hTab, TCM_GETITEMRECT, 0, (LPARAM) &rTab), "GetItemRect failed.\n");
691
692     hdc = GetDC(hTab);
693     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
694     ReleaseDC(hTab, hdc);
695     CheckSize(hTab, dpi, -1 , "Default Width");
696     ok_sequence(sequences, TAB_SEQ_INDEX, get_item_rect_seq, "Get itemRect test sequence", FALSE);
697     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get itemRect test parent sequence", FALSE);
698
699     /* Testing CurFocus */
700     {
701         INT focusIndex;
702
703         flush_sequences(sequences, NUM_MSG_SEQUENCES);
704
705         /* Testing CurFocus with largest appropriate value */
706         SendMessage(hTab, TCM_SETCURFOCUS, nTabs-1, 0);
707         focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
708             expect(nTabs-1, focusIndex);
709
710         /* Testing CurFocus with negative value */
711         SendMessage(hTab, TCM_SETCURFOCUS, -10, 0);
712         focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
713             expect(-1, focusIndex);
714
715         /* Testing CurFocus with value larger than number of tabs */
716         focusIndex = SendMessage(hTab, TCM_SETCURSEL, 1, 0);
717         todo_wine{
718             expect(-1, focusIndex);
719         }
720
721         SendMessage(hTab, TCM_SETCURFOCUS, nTabs+1, 0);
722         focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
723             expect(1, focusIndex);
724
725         ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_focus_seq, "Getset curFoc test sequence", FALSE);
726     }
727
728     /* Testing CurSel */
729     {
730         INT selectionIndex;
731         INT focusIndex;
732         TCITEM tcItem;
733
734         flush_sequences(sequences, NUM_MSG_SEQUENCES);
735
736         /* Testing CurSel with largest appropriate value */
737         selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs-1, 0);
738             expect(1, selectionIndex);
739         selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
740             expect(nTabs-1, selectionIndex);
741
742         /* Focus should switch with selection */
743         focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
744             expect(nTabs-1, focusIndex);
745
746         /* Testing CurSel with negative value */
747         SendMessage(hTab, TCM_SETCURSEL, -10, 0);
748         selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
749             expect(-1, selectionIndex);
750
751         /* Testing CurSel with value larger than number of tabs */
752         selectionIndex = SendMessage(hTab, TCM_SETCURSEL, 1, 0);
753             expect(-1, selectionIndex);
754
755         selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs+1, 0);
756             expect(-1, selectionIndex);
757         selectionIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
758             expect(1, selectionIndex);
759
760         ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_sel_seq, "Getset curSel test sequence", FALSE);
761         ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset curSel test parent sequence", FALSE);
762
763         /* selected item should have TCIS_BUTTONPRESSED state
764            It doesn't depend on button state */
765         memset(&tcItem, 0, sizeof(TCITEM));
766         tcItem.mask = TCIF_STATE;
767         tcItem.dwStateMask = TCIS_BUTTONPRESSED;
768         selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
769         SendMessage(hTab, TCM_GETITEM, selectionIndex, (LPARAM) &tcItem);
770         ok (tcItem.dwState & TCIS_BUTTONPRESSED || broken(tcItem.dwState == 0), /* older comctl32 */
771             "Selected item should have TCIS_BUTTONPRESSED\n");
772     }
773
774     /* Testing ExtendedStyle */
775     {
776         DWORD prevExtendedStyle;
777         DWORD extendedStyle;
778
779         flush_sequences(sequences, NUM_MSG_SEQUENCES);
780
781         /* Testing Flat Separators */
782         extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
783         prevExtendedStyle = SendMessage(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_FLATSEPARATORS);
784         expect(extendedStyle, prevExtendedStyle);
785
786         extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
787         expect(TCS_EX_FLATSEPARATORS, extendedStyle);
788
789         /* Testing Register Drop */
790         prevExtendedStyle = SendMessage(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_REGISTERDROP);
791             expect(extendedStyle, prevExtendedStyle);
792
793         extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
794         todo_wine{
795             expect(TCS_EX_REGISTERDROP, extendedStyle);
796         }
797
798         ok_sequence(sequences, TAB_SEQ_INDEX, getset_extended_style_seq, "Getset extendedStyle test sequence", FALSE);
799         ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset extendedStyle test parent sequence", FALSE);
800     }
801
802     /* Testing UnicodeFormat */
803     {
804         INT unicodeFormat;
805
806         flush_sequences(sequences, NUM_MSG_SEQUENCES);
807
808         unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
809         todo_wine{
810             expect(0, unicodeFormat);
811         }
812         unicodeFormat = SendMessage(hTab, TCM_GETUNICODEFORMAT, 0, 0);
813             expect(1, unicodeFormat);
814
815         unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, FALSE, 0);
816             expect(1, unicodeFormat);
817         unicodeFormat = SendMessage(hTab, TCM_GETUNICODEFORMAT, 0, 0);
818             expect(0, unicodeFormat);
819
820         unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
821             expect(0, unicodeFormat);
822
823         ok_sequence(sequences, TAB_SEQ_INDEX, getset_unicode_format_seq, "Getset unicodeFormat test sequence", FALSE);
824         ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset unicodeFormat test parent sequence", FALSE);
825     }
826
827     /* Testing GetSet Item */
828     {
829         TCITEM tcItem;
830         DWORD ret;
831         char szText[32] = "New Label";
832
833         /* passing invalid index should result in initialization to zero
834            for members mentioned in mask requested */
835
836         /* valid range here is [0,4] */
837         memset(&tcItem, 0xcc, sizeof(tcItem));
838         tcItem.mask = TCIF_PARAM;
839         ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
840         expect(FALSE, ret);
841         ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
842
843         memset(&tcItem, 0xcc, sizeof(tcItem));
844         tcItem.mask = TCIF_IMAGE;
845         ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
846         expect(FALSE, ret);
847         expect(0, tcItem.iImage);
848
849         memset(&tcItem, 0xcc, sizeof(tcItem));
850         tcItem.mask = TCIF_TEXT;
851         tcItem.pszText = szText;
852         szText[0] = 'a';
853         ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
854         expect(FALSE, ret);
855         expect('a', szText[0]);
856
857         memset(&tcItem, 0xcc, sizeof(tcItem));
858         tcItem.mask = TCIF_STATE;
859         tcItem.dwStateMask = 0;
860         tcItem.dwState = TCIS_BUTTONPRESSED;
861         ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
862         expect(FALSE, ret);
863         ok(tcItem.dwState == 0, "Expected zero dwState, got %u\n", tcItem.dwState);
864
865         memset(&tcItem, 0xcc, sizeof(tcItem));
866         tcItem.mask = TCIF_STATE;
867         tcItem.dwStateMask = TCIS_BUTTONPRESSED;
868         tcItem.dwState = TCIS_BUTTONPRESSED;
869         ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
870         expect(FALSE, ret);
871         ok(tcItem.dwState == 0, "Expected zero dwState\n");
872
873         /* check with negative index to be sure */
874         memset(&tcItem, 0xcc, sizeof(tcItem));
875         tcItem.mask = TCIF_PARAM;
876         ret = SendMessage(hTab, TCM_GETITEM, -1, (LPARAM)&tcItem);
877         expect(FALSE, ret);
878         ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
879
880         memset(&tcItem, 0xcc, sizeof(tcItem));
881         tcItem.mask = TCIF_PARAM;
882         ret = SendMessage(hTab, TCM_GETITEM, -2, (LPARAM)&tcItem);
883         expect(FALSE, ret);
884         ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
885
886         flush_sequences(sequences, NUM_MSG_SEQUENCES);
887
888         tcItem.mask = TCIF_TEXT;
889         tcItem.pszText = &szText[0];
890         tcItem.cchTextMax = sizeof(szText);
891
892         strcpy(szText, "New Label");
893         ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
894         ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
895         expect_str("New Label", tcItem.pszText);
896
897         ok ( SendMessage(hTab, TCM_GETITEM, 1, (LPARAM) &tcItem), "Getting item failed.\n");
898         expect_str("Tab 2", tcItem.pszText);
899
900         ok_sequence(sequences, TAB_SEQ_INDEX, getset_item_seq, "Getset item test sequence", FALSE);
901         ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset item test parent sequence", FALSE);
902
903         /* TCIS_BUTTONPRESSED doesn't depend on tab style */
904         memset(&tcItem, 0, sizeof(tcItem));
905         tcItem.mask = TCIF_STATE;
906         tcItem.dwStateMask = TCIS_BUTTONPRESSED;
907         tcItem.dwState = TCIS_BUTTONPRESSED;
908         ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
909         tcItem.dwState = 0;
910         ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
911         if (tcItem.dwState)
912         {
913             ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
914             /* next highlight item, test that dwStateMask actually masks */
915             tcItem.mask = TCIF_STATE;
916             tcItem.dwStateMask = TCIS_HIGHLIGHTED;
917             tcItem.dwState = TCIS_HIGHLIGHTED;
918             ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
919             tcItem.dwState = 0;
920             ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
921             ok (tcItem.dwState == TCIS_HIGHLIGHTED, "TCIS_HIGHLIGHTED should be set.\n");
922             tcItem.mask = TCIF_STATE;
923             tcItem.dwStateMask = TCIS_BUTTONPRESSED;
924             tcItem.dwState = 0;
925             ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
926             ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
927         }
928         else win_skip( "Item state mask not supported\n" );
929     }
930
931     /* Testing GetSet ToolTip */
932     {
933         HWND toolTip;
934         char toolTipText[32] = "ToolTip Text Test";
935
936         flush_sequences(sequences, NUM_MSG_SEQUENCES);
937
938         toolTip = create_tooltip(hTab, toolTipText);
939         SendMessage(hTab, TCM_SETTOOLTIPS, (LPARAM) toolTip, 0);
940         ok (toolTip == (HWND) SendMessage(hTab,TCM_GETTOOLTIPS,0,0), "ToolTip was set incorrectly.\n");
941
942         SendMessage(hTab, TCM_SETTOOLTIPS, 0, 0);
943         ok (NULL  == (HWND) SendMessage(hTab,TCM_GETTOOLTIPS,0,0), "ToolTip was set incorrectly.\n");
944
945         ok_sequence(sequences, TAB_SEQ_INDEX, getset_tooltip_seq, "Getset tooltip test sequence", TRUE);
946         ok_sequence(sequences, PARENT_SEQ_INDEX, getset_tooltip_parent_seq, "Getset tooltip test parent sequence", TRUE);
947     }
948
949     DestroyWindow(hTab);
950 }
951
952 static void test_adjustrect(HWND parent_wnd)
953 {
954     HWND hTab;
955     INT r;
956
957     ok(parent_wnd != NULL, "no parent window!\n");
958
959     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, 0, 0);
960     ok(hTab != NULL, "Failed to create tab control\n");
961
962     r = SendMessage(hTab, TCM_ADJUSTRECT, FALSE, 0);
963     expect(-1, r);
964
965     r = SendMessage(hTab, TCM_ADJUSTRECT, TRUE, 0);
966     expect(-1, r);
967 }
968 static void test_insert_focus(HWND parent_wnd)
969 {
970     HWND hTab;
971     INT nTabsRetrieved;
972     INT r;
973     TCITEM tcNewTab;
974     DWORD mask = TCIF_TEXT|TCIF_IMAGE;
975     static char tabName[] = "TAB";
976     tcNewTab.mask = mask;
977     tcNewTab.pszText = tabName;
978
979     ok(parent_wnd != NULL, "no parent window!\n");
980
981     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, mask, 0);
982     ok(hTab != NULL, "Failed to create tab control\n");
983
984     flush_sequences(sequences, NUM_MSG_SEQUENCES);
985
986     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
987     expect(0, nTabsRetrieved);
988
989     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
990     expect(-1, r);
991
992     tcNewTab.iImage = 1;
993     r = SendMessage(hTab, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab);
994     expect(0, r);
995
996     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
997     expect(1, nTabsRetrieved);
998
999     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1000     expect(0, r);
1001
1002     tcNewTab.iImage = 2;
1003     r = SendMessage(hTab, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
1004     expect(1, r);
1005
1006     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1007     expect(2, nTabsRetrieved);
1008
1009     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1010     expect(0, r);
1011
1012     r = SendMessage(hTab, TCM_SETCURFOCUS, -1, 0);
1013     expect(0, r);
1014
1015     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1016     expect(-1, r);
1017
1018     tcNewTab.iImage = 3;
1019     r = SendMessage(hTab, TCM_INSERTITEM, 3, (LPARAM) &tcNewTab);
1020     expect(2, r);
1021
1022     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1023     expect(2, r);
1024
1025     ok_sequence(sequences, TAB_SEQ_INDEX, insert_focus_seq, "insert_focus test sequence", FALSE);
1026     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "insert_focus parent test sequence", FALSE);
1027
1028     DestroyWindow(hTab);
1029 }
1030
1031 static void test_delete_focus(HWND parent_wnd)
1032 {
1033     HWND hTab;
1034     INT nTabsRetrieved;
1035     INT r;
1036
1037     ok(parent_wnd != NULL, "no parent window!\n");
1038
1039     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 2);
1040     ok(hTab != NULL, "Failed to create tab control\n");
1041
1042     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1043
1044     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1045     expect(2, nTabsRetrieved);
1046
1047     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1048     expect(0, r);
1049
1050     r = SendMessage(hTab, TCM_DELETEITEM, 1, 0);
1051     expect(1, r);
1052
1053     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1054     expect(1, nTabsRetrieved);
1055
1056     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1057     expect(0, r);
1058
1059     r = SendMessage(hTab, TCM_SETCURFOCUS, -1, 0);
1060     expect(0, r);
1061
1062     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1063     expect(-1, r);
1064
1065     r = SendMessage(hTab, TCM_DELETEITEM, 0, 0);
1066     expect(1, r);
1067
1068     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1069     expect(0, nTabsRetrieved);
1070
1071     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1072     expect(-1, r);
1073
1074     ok_sequence(sequences, TAB_SEQ_INDEX, delete_focus_seq, "delete_focus test sequence", FALSE);
1075     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "delete_focus parent test sequence", FALSE);
1076
1077     DestroyWindow(hTab);
1078 }
1079
1080 static void test_removeimage(HWND parent_wnd)
1081 {
1082     static const BYTE bits[32];
1083     HWND hwTab;
1084     INT i;
1085     TCITEM item;
1086     HICON hicon;
1087     HIMAGELIST himl = ImageList_Create(16, 16, ILC_COLOR, 3, 4);
1088
1089     hicon = CreateIcon(NULL, 16, 16, 1, 1, bits, bits);
1090     ImageList_AddIcon(himl, hicon);
1091     ImageList_AddIcon(himl, hicon);
1092     ImageList_AddIcon(himl, hicon);
1093
1094     hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
1095     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
1096
1097     memset(&item, 0, sizeof(TCITEM));
1098     item.mask = TCIF_IMAGE;
1099
1100     for(i = 0; i < 3; i++) {
1101         SendMessage(hwTab, TCM_GETITEM, i, (LPARAM)&item);
1102         expect(i, item.iImage);
1103     }
1104
1105     /* remove image middle image */
1106     SendMessage(hwTab, TCM_REMOVEIMAGE, 1, 0);
1107     expect(2, ImageList_GetImageCount(himl));
1108     item.iImage = -1;
1109     SendMessage(hwTab, TCM_GETITEM, 0, (LPARAM)&item);
1110     expect(0, item.iImage);
1111     item.iImage = 0;
1112     SendMessage(hwTab, TCM_GETITEM, 1, (LPARAM)&item);
1113     expect(-1, item.iImage);
1114     item.iImage = 0;
1115     SendMessage(hwTab, TCM_GETITEM, 2, (LPARAM)&item);
1116     expect(1, item.iImage);
1117     /* remove first image */
1118     SendMessage(hwTab, TCM_REMOVEIMAGE, 0, 0);
1119     expect(1, ImageList_GetImageCount(himl));
1120     item.iImage = 0;
1121     SendMessage(hwTab, TCM_GETITEM, 0, (LPARAM)&item);
1122     expect(-1, item.iImage);
1123     item.iImage = 0;
1124     SendMessage(hwTab, TCM_GETITEM, 1, (LPARAM)&item);
1125     expect(-1, item.iImage);
1126     item.iImage = -1;
1127     SendMessage(hwTab, TCM_GETITEM, 2, (LPARAM)&item);
1128     expect(0, item.iImage);
1129     /* remove the last one */
1130     SendMessage(hwTab, TCM_REMOVEIMAGE, 0, 0);
1131     expect(0, ImageList_GetImageCount(himl));
1132     for(i = 0; i < 3; i++) {
1133         item.iImage = 0;
1134         SendMessage(hwTab, TCM_GETITEM, i, (LPARAM)&item);
1135         expect(-1, item.iImage);
1136     }
1137
1138     DestroyWindow(hwTab);
1139     ImageList_Destroy(himl);
1140     DestroyIcon(hicon);
1141 }
1142
1143 START_TEST(tab)
1144 {
1145     HWND parent_wnd;
1146     LOGFONTA logfont;
1147
1148     lstrcpyA(logfont.lfFaceName, "Arial");
1149     memset(&logfont, 0, sizeof(logfont));
1150     logfont.lfHeight = -12;
1151     logfont.lfWeight = FW_NORMAL;
1152     logfont.lfCharSet = ANSI_CHARSET;
1153     hFont = CreateFontIndirectA(&logfont);
1154
1155     InitCommonControls();
1156
1157     trace ("Testing with default MinWidth\n");
1158     test_tab(-1);
1159     trace ("Testing with MinWidth set to -3\n");
1160     test_tab(-3);
1161     trace ("Testing with MinWidth set to 24\n");
1162     test_tab(24);
1163     trace ("Testing with MinWidth set to 54\n");
1164     test_tab(54);
1165     trace ("Testing with MinWidth set to 94\n");
1166     test_tab(94);
1167
1168     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
1169
1170     parent_wnd = createParentWindow();
1171     ok(parent_wnd != NULL, "Failed to create parent window!\n");
1172
1173     /* Testing getters and setters with 5 tabs */
1174     test_getters_setters(parent_wnd, 5);
1175
1176     test_adjustrect(parent_wnd);
1177
1178     test_insert_focus(parent_wnd);
1179     test_delete_focus(parent_wnd);
1180     test_removeimage(parent_wnd);
1181
1182     DestroyWindow(parent_wnd);
1183 }