quartz: Release outstanding samples in PullPin::PauseProcessing.
[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 static void CheckSize(HWND hwnd, INT width, INT height, const char *msg, int line)
45 {
46     RECT r;
47
48     SendMessage(hwnd, TCM_GETITEMRECT, 0, (LPARAM)&r);
49     if (width >= 0 && height < 0)
50     {
51         ok_(__FILE__,line) (width == r.right - r.left, "%s: Expected width [%d] got [%d]\n",\
52         msg, width, r.right - r.left);
53     }
54     else if (height >= 0 && width < 0)
55     {
56         ok_(__FILE__,line) (height == r.bottom - r.top,  "%s: Expected height [%d] got [%d]\n",\
57         msg, height, r.bottom - r.top);
58     }
59     else
60         ok_(__FILE__,line) ((width  == r.right  - r.left) && (height == r.bottom - r.top ),
61             "%s: Expected [%d,%d] got [%d,%d]\n", msg, width, height,
62             r.right - r.left, r.bottom - r.top);
63 }
64
65 #define CHECKSIZE(hwnd,width,height,msg) CheckSize(hwnd,width,height,msg,__LINE__)
66
67 static void TabCheckSetSize(HWND hwnd, INT set_width, INT set_height, INT exp_width,
68     INT exp_height, const char *msg, int line)
69 {
70     SendMessage(hwnd, TCM_SETITEMSIZE, 0,
71         (LPARAM) MAKELPARAM((set_width >= 0) ? set_width : 0, (set_height >= 0) ? set_height : 0));
72     if (winetest_interactive) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW);
73     CheckSize(hwnd, exp_width, exp_height, msg, line);
74 }
75
76 #define TABCHECKSETSIZE(hwnd,set_width,set_height,exp_width,exp_height,msg) \
77     TabCheckSetSize(hwnd,set_width,set_height,exp_width,exp_height,msg,__LINE__)
78
79 static HFONT hFont;
80 static DRAWITEMSTRUCT g_drawitem;
81 static HWND parent_wnd;
82
83 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
84
85 static const struct message create_parent_wnd_seq[] = {
86     { WM_GETMINMAXINFO, sent },
87     { WM_NCCREATE, sent },
88     { WM_NCCALCSIZE, sent|wparam, 0 },
89     { WM_CREATE, sent },
90     { WM_SHOWWINDOW, sent|wparam, 1 },
91     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
92     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
93     { WM_ACTIVATEAPP, sent|wparam, 1 },
94     { WM_NCACTIVATE, sent|wparam, 1 },
95     { WM_ACTIVATE, sent|wparam, 1 },
96     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
97     { WM_IME_NOTIFY, sent|defwinproc|optional },
98     { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
99     /* Win9x adds SWP_NOZORDER below */
100     { WM_WINDOWPOSCHANGED, sent},
101     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
102     { WM_SIZE, sent },
103     { WM_MOVE, sent },
104     { 0 }
105 };
106
107 static const struct message add_tab_to_parent[] = {
108     { TCM_INSERTITEMA, sent },
109     { TCM_INSERTITEMA, sent|optional },
110     { WM_NOTIFYFORMAT, sent|defwinproc },
111     { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc|optional, 0, 0 },
112     { WM_PARENTNOTIFY, sent|defwinproc },
113     { TCM_INSERTITEMA, sent },
114     { TCM_INSERTITEMA, sent },
115     { TCM_INSERTITEMA, sent },
116     { TCM_INSERTITEMA, sent|optional },
117     { 0 }
118 };
119
120 static const struct message add_tab_to_parent_interactive[] = {
121     { TCM_INSERTITEMA, sent },
122     { TCM_INSERTITEMA, sent },
123     { WM_NOTIFYFORMAT, sent|defwinproc },
124     { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc, 0, 0 },
125     { WM_PARENTNOTIFY, sent|defwinproc },
126     { TCM_INSERTITEMA, sent },
127     { TCM_INSERTITEMA, sent },
128     { TCM_INSERTITEMA, sent },
129     { WM_SHOWWINDOW, sent},
130     { WM_WINDOWPOSCHANGING, sent},
131     { WM_WINDOWPOSCHANGING, sent},
132     { WM_NCACTIVATE, sent},
133     { WM_ACTIVATE, sent},
134     { WM_IME_SETCONTEXT, sent|defwinproc|optional},
135     { WM_IME_NOTIFY, sent|defwinproc|optional},
136     { WM_SETFOCUS, sent|defwinproc},
137     { WM_WINDOWPOSCHANGED, sent},
138     { WM_SIZE, sent},
139     { WM_MOVE, sent},
140     { 0 }
141 };
142
143 static const struct message add_tab_control_parent_seq[] = {
144     { WM_NOTIFYFORMAT, sent },
145     { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 },
146     { 0 }
147 };
148
149 static const struct message add_tab_control_parent_seq_interactive[] = {
150     { WM_NOTIFYFORMAT, sent },
151     { WM_QUERYUISTATE, sent|wparam|lparam, 0, 0 },
152     { WM_WINDOWPOSCHANGING, sent|optional},
153     { WM_NCACTIVATE, sent},
154     { WM_ACTIVATE, sent},
155     { WM_WINDOWPOSCHANGING, sent|optional},
156     { WM_KILLFOCUS, sent},
157     { WM_IME_SETCONTEXT, sent|optional},
158     { WM_IME_NOTIFY, sent|optional},
159     { 0 }
160 };
161
162 static const struct message empty_sequence[] = {
163     { 0 }
164 };
165
166 static const struct message set_min_tab_width_seq[] = {
167     { TCM_SETMINTABWIDTH, sent|wparam, 0 },
168     { TCM_SETMINTABWIDTH, sent|wparam, 0 },
169     { 0 }
170 };
171
172 static const struct message get_item_count_seq[] = {
173     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
174     { 0 }
175 };
176
177 static const struct message get_row_count_seq[] = {
178     { TCM_GETROWCOUNT, sent|wparam|lparam, 0, 0 },
179     { 0 }
180 };
181
182 static const struct message get_item_rect_seq[] = {
183     { TCM_GETITEMRECT, sent },
184     { TCM_GETITEMRECT, sent },
185     { 0 }
186 };
187
188 static const struct message getset_cur_focus_seq[] = {
189     { TCM_SETCURFOCUS, sent|lparam, 0 },
190     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
191     { TCM_SETCURFOCUS, sent|lparam, 0 },
192     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
193     { TCM_SETCURSEL, sent|lparam, 0 },
194     { TCM_SETCURFOCUS, sent|lparam, 0 },
195     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
196     { 0 }
197 };
198
199 static const struct message getset_cur_sel_seq[] = {
200     { TCM_SETCURSEL, sent|lparam, 0 },
201     { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
202     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
203     { TCM_SETCURSEL, sent|lparam, 0 },
204     { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
205     { TCM_SETCURSEL, sent|lparam, 0 },
206     { TCM_SETCURSEL, sent|lparam, 0 },
207     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
208     { 0 }
209 };
210
211 static const struct message getset_extended_style_seq[] = {
212     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
213     { TCM_SETEXTENDEDSTYLE, sent },
214     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
215     { TCM_SETEXTENDEDSTYLE, sent },
216     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
217     { 0 }
218 };
219
220 static const struct message getset_unicode_format_seq[] = {
221     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
222     { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
223     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
224     { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
225     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
226     { 0 }
227 };
228
229 static const struct message getset_item_seq[] = {
230     { TCM_SETITEMA, sent },
231     { TCM_GETITEMA, sent },
232     { TCM_GETITEMA, sent },
233     { 0 }
234 };
235
236 static const struct message getset_tooltip_seq[] = {
237     { WM_NOTIFYFORMAT, sent|optional },
238     { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 },
239     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
240     { WM_NOTIFYFORMAT, sent|optional },
241     { TCM_SETTOOLTIPS, sent|lparam, 0 },
242     { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
243     { TCM_SETTOOLTIPS, sent|lparam, 0 },
244     { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
245     { 0 }
246 };
247
248 static const struct message getset_tooltip_parent_seq[] = {
249     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
250     { 0 }
251 };
252
253 static const struct message insert_focus_seq[] = {
254     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
255     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
256     { TCM_INSERTITEM, sent|wparam, 1 },
257     { WM_NOTIFYFORMAT, sent|defwinproc|optional },
258     { WM_QUERYUISTATE, sent|defwinproc|optional },
259     { WM_PARENTNOTIFY, sent|defwinproc|optional },
260     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
261     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
262     { TCM_INSERTITEM, sent|wparam, 2 },
263     { WM_NOTIFYFORMAT, sent|defwinproc|optional },
264     { WM_QUERYUISTATE, sent|defwinproc|optional, },
265     { WM_PARENTNOTIFY, sent|defwinproc|optional },
266     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
267     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
268     { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
269     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
270     { TCM_INSERTITEM, sent|wparam, 3 },
271     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
272     { 0 }
273 };
274
275 static const struct message delete_focus_seq[] = {
276     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
277     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
278     { TCM_DELETEITEM, sent|wparam|lparam, 1, 0 },
279     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
280     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
281     { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
282     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
283     { TCM_DELETEITEM, sent|wparam|lparam, 0, 0 },
284     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
285     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
286     { 0 }
287 };
288
289
290 static HWND
291 create_tabcontrol (DWORD style, DWORD mask)
292 {
293     HWND handle;
294     TCITEM tcNewTab;
295     static char text1[] = "Tab 1",
296     text2[] = "Wide Tab 2",
297     text3[] = "T 3";
298
299     handle = CreateWindow (
300         WC_TABCONTROLA,
301         "TestTab",
302         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style,
303         10, 10, 300, 100,
304         NULL, NULL, NULL, 0);
305
306     assert (handle);
307
308     SetWindowLong(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style);
309     SendMessage (handle, WM_SETFONT, 0, (LPARAM) hFont);
310
311     tcNewTab.mask = mask;
312     tcNewTab.pszText = text1;
313     tcNewTab.iImage = 0;
314     SendMessage (handle, TCM_INSERTITEM, 0, (LPARAM) &tcNewTab);
315     tcNewTab.pszText = text2;
316     tcNewTab.iImage = 1;
317     SendMessage (handle, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab);
318     tcNewTab.pszText = text3;
319     tcNewTab.iImage = 2;
320     SendMessage (handle, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
321
322     if (winetest_interactive)
323     {
324         ShowWindow (handle, SW_SHOW);
325         RedrawWindow (handle, NULL, 0, RDW_UPDATENOW);
326         Sleep (1000);
327     }
328
329     return handle;
330 }
331
332 static LRESULT WINAPI parentWindowProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
333 {
334     static LONG defwndproc_counter = 0;
335     LRESULT ret;
336     struct message msg;
337
338     /* do not log painting messages */
339     if (message != WM_PAINT &&
340         message != WM_ERASEBKGND &&
341         message != WM_NCPAINT &&
342         message != WM_NCHITTEST &&
343         message != WM_GETTEXT &&
344         message != WM_GETICON &&
345         message != WM_DEVICECHANGE)
346     {
347         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
348
349         msg.message = message;
350         msg.flags = sent|wparam|lparam;
351         if (defwndproc_counter) msg.flags |= defwinproc;
352         msg.wParam = wParam;
353         msg.lParam = lParam;
354         add_message(sequences, PARENT_SEQ_INDEX, &msg);
355     }
356
357     /* dump sent structure data */
358     if (message == WM_DRAWITEM)
359         g_drawitem = *(DRAWITEMSTRUCT*)lParam;
360
361     defwndproc_counter++;
362     ret = DefWindowProcA(hwnd, message, wParam, lParam);
363     defwndproc_counter--;
364
365     return ret;
366 }
367
368 static BOOL registerParentWindowClass(void)
369 {
370     WNDCLASSA cls;
371
372     cls.style = 0;
373     cls.lpfnWndProc = parentWindowProcess;
374     cls.cbClsExtra = 0;
375     cls.cbWndExtra = 0;
376     cls.hInstance = GetModuleHandleA(NULL);
377     cls.hIcon = 0;
378     cls.hCursor = LoadCursorA(0, IDC_ARROW);
379     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
380     cls.lpszMenuName = NULL;
381     cls.lpszClassName = "Tab test parent class";
382     return RegisterClassA(&cls);
383 }
384
385 static HWND createParentWindow(void)
386 {
387     if (!registerParentWindowClass())
388         return NULL;
389
390     return CreateWindowEx(0, "Tab test parent class",
391                           "Tab test parent window",
392                           WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
393                           WS_MAXIMIZEBOX | WS_VISIBLE,
394                           0, 0, 100, 100,
395                           GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
396 }
397
398 static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
399 {
400     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
401     static LONG defwndproc_counter = 0;
402     LRESULT ret;
403     struct message msg;
404
405     /* do not log painting messages */
406     if (message != WM_PAINT &&
407         message != WM_ERASEBKGND &&
408         message != WM_NCPAINT &&
409         message != WM_NCHITTEST &&
410         message != WM_GETTEXT &&
411         message != WM_GETICON &&
412         message != WM_DEVICECHANGE)
413     {
414         trace("tab: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
415
416         msg.message = message;
417         msg.flags = sent|wparam|lparam;
418         if (defwndproc_counter) msg.flags |= defwinproc;
419         msg.wParam = wParam;
420         msg.lParam = lParam;
421         add_message(sequences, TAB_SEQ_INDEX, &msg);
422     }
423
424     defwndproc_counter++;
425     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
426     defwndproc_counter--;
427
428     return ret;
429 }
430
431 static HWND createFilledTabControl(HWND parent_wnd, DWORD style, DWORD mask, INT nTabs)
432 {
433     HWND tabHandle;
434     TCITEM tcNewTab;
435     WNDPROC oldproc;
436     RECT rect;
437     INT i;
438
439     GetClientRect(parent_wnd, &rect);
440
441     tabHandle = CreateWindow (
442         WC_TABCONTROLA,
443         "TestTab",
444         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style,
445         0, 0, rect.right, rect.bottom,
446         parent_wnd, NULL, NULL, 0);
447
448     assert(tabHandle);
449
450     oldproc = (WNDPROC)SetWindowLongPtrA(tabHandle, GWLP_WNDPROC, (LONG_PTR)tabSubclassProcess);
451     SetWindowLongPtrA(tabHandle, GWLP_USERDATA, (LONG_PTR)oldproc);
452
453     tcNewTab.mask = mask;
454
455     for (i = 0; i < nTabs; i++)
456     {
457         char tabName[MAX_TABLEN];
458
459         sprintf(tabName, "Tab %d", i+1);
460         tcNewTab.pszText = tabName;
461         tcNewTab.iImage = i;
462         SendMessage (tabHandle, TCM_INSERTITEM, i, (LPARAM) &tcNewTab);
463     }
464
465     if (winetest_interactive)
466     {
467         ShowWindow (tabHandle, SW_SHOW);
468         RedrawWindow (tabHandle, NULL, 0, RDW_UPDATENOW);
469         Sleep (1000);
470     }
471
472     return tabHandle;
473 }
474
475 static HWND create_tooltip (HWND hTab, char toolTipText[])
476 {
477     HWND hwndTT;
478
479     TOOLINFO ti;
480     LPTSTR lptstr = toolTipText;
481     RECT rect;
482
483     /* Creating a tooltip window*/
484     hwndTT = CreateWindowEx(
485         WS_EX_TOPMOST,
486         TOOLTIPS_CLASS,
487         NULL,
488         WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
489         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
490         hTab, NULL, 0, NULL);
491
492     SetWindowPos(
493         hwndTT,
494         HWND_TOPMOST,
495         0, 0, 0, 0,
496         SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
497
498     GetClientRect (hTab, &rect);
499
500     /* Initialize members of toolinfo*/
501     ti.cbSize = sizeof(TOOLINFO);
502     ti.uFlags = TTF_SUBCLASS;
503     ti.hwnd = hTab;
504     ti.hinst = 0;
505     ti.uId = 0;
506     ti.lpszText = lptstr;
507
508     ti.rect = rect;
509
510     /* Add toolinfo structure to the tooltip control */
511     SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) &ti);
512
513     return hwndTT;
514 }
515
516 static void test_tab(INT nMinTabWidth)
517 {
518     HWND hwTab;
519     RECT rTab;
520     HIMAGELIST himl = ImageList_Create(21, 21, ILC_COLOR, 3, 4);
521     SIZE size;
522     HDC hdc;
523     HFONT hOldFont;
524     INT i, dpi, exp;
525
526     hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
527     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
528     /* Get System default MinTabWidth */
529     if (nMinTabWidth < 0)
530         nMinTabWidth = SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
531
532     hdc = GetDC(hwTab);
533     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
534     hOldFont = SelectObject(hdc, (HFONT)SendMessage(hwTab, WM_GETFONT, 0, 0));
535     GetTextExtentPoint32A(hdc, "Tab 1", strlen("Tab 1"), &size);
536     trace("Tab1 text size: size.cx=%d size.cy=%d\n", size.cx, size.cy);
537     SelectObject(hdc, hOldFont);
538     ReleaseDC(hwTab, hdc);
539
540     trace ("  TCS_FIXEDWIDTH tabs no icon...\n");
541     CHECKSIZE(hwTab, dpi, -1, "default width");
542     TABCHECKSETSIZE(hwTab, 50, 20, 50, 20, "set size");
543     TABCHECKSETSIZE(hwTab, 0, 1, 0, 1, "min size");
544
545     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
546
547     trace ("  TCS_FIXEDWIDTH tabs 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
552     DestroyWindow (hwTab);
553
554     hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS, TCIF_TEXT|TCIF_IMAGE);
555     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
556
557     hdc = GetDC(hwTab);
558     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
559     ReleaseDC(hwTab, hdc);
560     trace ("  TCS_FIXEDWIDTH buttons no icon...\n");
561     CHECKSIZE(hwTab, dpi, -1, "default width");
562     TABCHECKSETSIZE(hwTab, 20, 20, 20, 20, "set size 1");
563     TABCHECKSETSIZE(hwTab, 10, 50, 10, 50, "set size 2");
564     TABCHECKSETSIZE(hwTab, 0, 1, 0, 1, "min size");
565
566     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
567
568     trace ("  TCS_FIXEDWIDTH buttons with icon...\n");
569     TABCHECKSETSIZE(hwTab, 50, 30, 50, 30, "set size > icon");
570     TABCHECKSETSIZE(hwTab, 20, 20, 25, 20, "set size < icon");
571     TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "min size");
572     SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
573     TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "set padding, min size");
574
575     DestroyWindow (hwTab);
576
577     hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM, TCIF_TEXT|TCIF_IMAGE);
578     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
579
580     hdc = GetDC(hwTab);
581     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
582     ReleaseDC(hwTab, hdc);
583     trace ("  TCS_FIXEDWIDTH | TCS_BOTTOM tabs...\n");
584     CHECKSIZE(hwTab, dpi, -1, "no icon, default width");
585
586     TABCHECKSETSIZE(hwTab, 20, 20, 20, 20, "no icon, set size 1");
587     TABCHECKSETSIZE(hwTab, 10, 50, 10, 50, "no icon, set size 2");
588     TABCHECKSETSIZE(hwTab, 0, 1, 0, 1, "no icon, min size");
589
590     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
591
592     TABCHECKSETSIZE(hwTab, 50, 30, 50, 30, "with icon, set size > icon");
593     TABCHECKSETSIZE(hwTab, 20, 20, 25, 20, "with icon, set size < icon");
594     TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "with icon, min size");
595     SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
596     TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "set padding, min size");
597
598     DestroyWindow (hwTab);
599
600     hwTab = create_tabcontrol(0, TCIF_TEXT|TCIF_IMAGE);
601     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
602
603     trace ("  non fixed width, with text...\n");
604     exp = max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth);
605     SendMessage( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
606     ok( rTab.right  - rTab.left == exp || broken(rTab.right  - rTab.left == DEFAULT_MIN_TAB_WIDTH),
607         "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
608
609     for (i=0; i<8; i++)
610     {
611         INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
612
613         SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0);
614         SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i));
615
616         TABCHECKSETSIZE(hwTab, 50, 20, max(size.cx + i*2, nTabWidth), 20, "no icon, set size");
617         TABCHECKSETSIZE(hwTab, 0, 1, max(size.cx + i*2, nTabWidth), 1, "no icon, min size");
618
619         SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
620         nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 3) : nMinTabWidth;
621
622         TABCHECKSETSIZE(hwTab, 50, 30, max(size.cx + 21 + i*3, nTabWidth), 30, "with icon, set size > icon");
623         TABCHECKSETSIZE(hwTab, 20, 20, max(size.cx + 21 + i*3, nTabWidth), 20, "with icon, set size < icon");
624         TABCHECKSETSIZE(hwTab, 0, 1, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size");
625     }
626     DestroyWindow (hwTab);
627
628     hwTab = create_tabcontrol(0, TCIF_IMAGE);
629     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
630
631     trace ("  non fixed width, no text...\n");
632     exp = (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth;
633     SendMessage( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
634     ok( rTab.right  - rTab.left == exp || broken(rTab.right  - rTab.left == DEFAULT_MIN_TAB_WIDTH),
635         "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
636
637     for (i=0; i<8; i++)
638     {
639         INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
640
641         SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0);
642         SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i));
643
644         TABCHECKSETSIZE(hwTab, 50, 20, nTabWidth, 20, "no icon, set size");
645         TABCHECKSETSIZE(hwTab, 0, 1, nTabWidth, 1, "no icon, min size");
646
647         SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
648         if (i > 1 && nMinTabWidth > 0 && nMinTabWidth < DEFAULT_MIN_TAB_WIDTH)
649             nTabWidth += EXTRA_ICON_PADDING *(i-1);
650
651         TABCHECKSETSIZE(hwTab, 50, 30, nTabWidth, 30, "with icon, set size > icon");
652         TABCHECKSETSIZE(hwTab, 20, 20, nTabWidth, 20, "with icon, set size < icon");
653         TABCHECKSETSIZE(hwTab, 0, 1, nTabWidth, 1, "with icon, min size");
654     }
655
656     DestroyWindow (hwTab);
657
658     ImageList_Destroy(himl);
659     DeleteObject(hFont);
660 }
661
662 static void test_width(void)
663 {
664     trace ("Testing with default MinWidth\n");
665     test_tab(-1);
666     trace ("Testing with MinWidth set to -3\n");
667     test_tab(-3);
668     trace ("Testing with MinWidth set to 24\n");
669     test_tab(24);
670     trace ("Testing with MinWidth set to 54\n");
671     test_tab(54);
672     trace ("Testing with MinWidth set to 94\n");
673     test_tab(94);
674 }
675
676 static void test_curfocus(void)
677 {
678     const INT nTabs = 5;
679     INT focusIndex;
680     HWND hTab;
681
682     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
683     ok(hTab != NULL, "Failed to create tab control\n");
684
685     flush_sequences(sequences, NUM_MSG_SEQUENCES);
686
687     /* Testing CurFocus with largest appropriate value */
688     SendMessage(hTab, TCM_SETCURFOCUS, nTabs-1, 0);
689     focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
690     expect(nTabs-1, focusIndex);
691
692     /* Testing CurFocus with negative value */
693     SendMessage(hTab, TCM_SETCURFOCUS, -10, 0);
694     focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
695     expect(-1, focusIndex);
696
697     /* Testing CurFocus with value larger than number of tabs */
698     focusIndex = SendMessage(hTab, TCM_SETCURSEL, 1, 0);
699     expect(-1, focusIndex);
700
701     SendMessage(hTab, TCM_SETCURFOCUS, nTabs+1, 0);
702     focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
703     expect(1, focusIndex);
704
705     ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_focus_seq, "Getset curFoc test sequence", FALSE);
706
707     DestroyWindow(hTab);
708 }
709
710 static void test_cursel(void)
711 {
712     const INT nTabs = 5;
713     INT selectionIndex;
714     INT focusIndex;
715     TCITEM tcItem;
716     HWND hTab;
717
718     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
719     ok(hTab != NULL, "Failed to create tab control\n");
720
721     flush_sequences(sequences, NUM_MSG_SEQUENCES);
722
723     /* Testing CurSel with largest appropriate value */
724     selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs-1, 0);
725     expect(0, selectionIndex);
726     selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
727     expect(nTabs-1, selectionIndex);
728
729     /* Focus should switch with selection */
730     focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
731     expect(nTabs-1, focusIndex);
732
733     /* Testing CurSel with negative value */
734     SendMessage(hTab, TCM_SETCURSEL, -10, 0);
735     selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
736     expect(-1, selectionIndex);
737
738     /* Testing CurSel with value larger than number of tabs */
739     selectionIndex = SendMessage(hTab, TCM_SETCURSEL, 1, 0);
740     expect(-1, selectionIndex);
741
742     selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs+1, 0);
743     expect(-1, selectionIndex);
744     selectionIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
745     expect(1, selectionIndex);
746
747     ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_sel_seq, "Getset curSel test sequence", FALSE);
748     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset curSel test parent sequence", FALSE);
749
750     /* selected item should have TCIS_BUTTONPRESSED state
751        It doesn't depend on button state */
752     memset(&tcItem, 0, sizeof(TCITEM));
753     tcItem.mask = TCIF_STATE;
754     tcItem.dwStateMask = TCIS_BUTTONPRESSED;
755     selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
756     SendMessage(hTab, TCM_GETITEM, selectionIndex, (LPARAM) &tcItem);
757     ok (tcItem.dwState & TCIS_BUTTONPRESSED || broken(tcItem.dwState == 0), /* older comctl32 */
758         "Selected item should have TCIS_BUTTONPRESSED\n");
759
760     DestroyWindow(hTab);
761 }
762
763 static void test_extendedstyle(void)
764 {
765     const INT nTabs = 5;
766     DWORD prevExtendedStyle;
767     DWORD extendedStyle;
768     HWND hTab;
769
770     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
771     ok(hTab != NULL, "Failed to create tab control\n");
772
773     flush_sequences(sequences, NUM_MSG_SEQUENCES);
774
775     /* Testing Flat Separators */
776     extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
777     prevExtendedStyle = SendMessage(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_FLATSEPARATORS);
778     expect(extendedStyle, prevExtendedStyle);
779
780     extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
781     expect(TCS_EX_FLATSEPARATORS, extendedStyle);
782
783     /* Testing Register Drop */
784     prevExtendedStyle = SendMessage(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_REGISTERDROP);
785     expect(extendedStyle, prevExtendedStyle);
786
787     extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
788     todo_wine{
789         expect(TCS_EX_REGISTERDROP, extendedStyle);
790     }
791
792     ok_sequence(sequences, TAB_SEQ_INDEX, getset_extended_style_seq, "Getset extendedStyle test sequence", FALSE);
793     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset extendedStyle test parent sequence", FALSE);
794
795     DestroyWindow(hTab);
796 }
797
798 static void test_unicodeformat(void)
799 {
800     const INT nTabs = 5;
801     INT unicodeFormat;
802     HWND hTab;
803
804     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
805     ok(hTab != NULL, "Failed to create tab control\n");
806
807     flush_sequences(sequences, NUM_MSG_SEQUENCES);
808
809     unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
810     todo_wine{
811         expect(0, unicodeFormat);
812     }
813     unicodeFormat = SendMessage(hTab, TCM_GETUNICODEFORMAT, 0, 0);
814     expect(1, unicodeFormat);
815
816     unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, FALSE, 0);
817     expect(1, unicodeFormat);
818     unicodeFormat = SendMessage(hTab, TCM_GETUNICODEFORMAT, 0, 0);
819     expect(0, unicodeFormat);
820
821     unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
822     expect(0, unicodeFormat);
823
824     ok_sequence(sequences, TAB_SEQ_INDEX, getset_unicode_format_seq, "Getset unicodeFormat test sequence", FALSE);
825     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset unicodeFormat test parent sequence", FALSE);
826
827     DestroyWindow(hTab);
828 }
829
830 static void test_getset_item(void)
831 {
832     char szText[32] = "New Label";
833     const INT nTabs = 5;
834     TCITEM tcItem;
835     LPARAM lparam;
836     DWORD ret;
837     HWND hTab;
838
839     hTab = CreateWindowA(
840         WC_TABCONTROLA,
841         "TestTab",
842         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED,
843         10, 10, 300, 100,
844         parent_wnd, NULL, NULL, 0);
845
846     ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
847
848     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)-1, 0);
849     ok(ret == TRUE, "got %d\n", ret);
850
851     /* set some item data */
852     tcItem.lParam = ~0;
853     tcItem.mask = TCIF_PARAM;
854
855     ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&tcItem);
856     ok(ret == 0, "got %d\n", ret);
857
858     /* all sizeof(LPARAM) returned anyway when using sizeof(LPARAM)-1 size */
859     memset(&lparam, 0xaa, sizeof(lparam));
860     tcItem.lParam = lparam;
861     tcItem.mask = TCIF_PARAM;
862     ret = SendMessage(hTab, TCM_GETITEM, 0, (LPARAM)&tcItem);
863     expect(TRUE, ret);
864     /* everything higher specified size is preserved */
865     memset(&lparam, 0xff, sizeof(lparam)-1);
866     ok(tcItem.lParam == lparam, "Expected 0x%lx, got 0x%lx\n", lparam, tcItem.lParam);
867
868     DestroyWindow(hTab);
869
870     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
871     ok(hTab != NULL, "Failed to create tab control\n");
872
873     /* passing invalid index should result in initialization to zero
874        for members mentioned in mask requested */
875
876     /* valid range here is [0,4] */
877     memset(&tcItem, 0xcc, sizeof(tcItem));
878     tcItem.mask = TCIF_PARAM;
879     ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
880     expect(FALSE, ret);
881     ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
882
883     memset(&tcItem, 0xcc, sizeof(tcItem));
884     tcItem.mask = TCIF_IMAGE;
885     ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
886     expect(FALSE, ret);
887     expect(0, tcItem.iImage);
888
889     memset(&tcItem, 0xcc, sizeof(tcItem));
890     tcItem.mask = TCIF_TEXT;
891     tcItem.pszText = szText;
892     szText[0] = 'a';
893     ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
894     expect(FALSE, ret);
895     expect('a', szText[0]);
896
897     memset(&tcItem, 0xcc, sizeof(tcItem));
898     tcItem.mask = TCIF_STATE;
899     tcItem.dwStateMask = 0;
900     tcItem.dwState = TCIS_BUTTONPRESSED;
901     ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
902     expect(FALSE, ret);
903     ok(tcItem.dwState == 0, "Expected zero dwState, got %u\n", tcItem.dwState);
904
905     memset(&tcItem, 0xcc, sizeof(tcItem));
906     tcItem.mask = TCIF_STATE;
907     tcItem.dwStateMask = TCIS_BUTTONPRESSED;
908     tcItem.dwState = TCIS_BUTTONPRESSED;
909     ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
910     expect(FALSE, ret);
911     ok(tcItem.dwState == 0, "Expected zero dwState\n");
912
913     /* check with negative index to be sure */
914     memset(&tcItem, 0xcc, sizeof(tcItem));
915     tcItem.mask = TCIF_PARAM;
916     ret = SendMessage(hTab, TCM_GETITEM, -1, (LPARAM)&tcItem);
917     expect(FALSE, ret);
918     ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
919
920     memset(&tcItem, 0xcc, sizeof(tcItem));
921     tcItem.mask = TCIF_PARAM;
922     ret = SendMessage(hTab, TCM_GETITEM, -2, (LPARAM)&tcItem);
923     expect(FALSE, ret);
924     ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
925
926     flush_sequences(sequences, NUM_MSG_SEQUENCES);
927
928     tcItem.mask = TCIF_TEXT;
929     tcItem.pszText = &szText[0];
930     tcItem.cchTextMax = sizeof(szText);
931
932     strcpy(szText, "New Label");
933     ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
934     ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
935     expect_str("New Label", tcItem.pszText);
936
937     ok ( SendMessage(hTab, TCM_GETITEM, 1, (LPARAM) &tcItem), "Getting item failed.\n");
938     expect_str("Tab 2", tcItem.pszText);
939
940     ok_sequence(sequences, TAB_SEQ_INDEX, getset_item_seq, "Getset item test sequence", FALSE);
941     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset item test parent sequence", FALSE);
942
943     /* TCIS_BUTTONPRESSED doesn't depend on tab style */
944     memset(&tcItem, 0, sizeof(tcItem));
945     tcItem.mask = TCIF_STATE;
946     tcItem.dwStateMask = TCIS_BUTTONPRESSED;
947     tcItem.dwState = TCIS_BUTTONPRESSED;
948     ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
949     tcItem.dwState = 0;
950     ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
951     if (tcItem.dwState)
952     {
953         ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
954         /* next highlight item, test that dwStateMask actually masks */
955         tcItem.mask = TCIF_STATE;
956         tcItem.dwStateMask = TCIS_HIGHLIGHTED;
957         tcItem.dwState = TCIS_HIGHLIGHTED;
958         ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
959         tcItem.dwState = 0;
960         ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
961         ok (tcItem.dwState == TCIS_HIGHLIGHTED, "TCIS_HIGHLIGHTED should be set.\n");
962         tcItem.mask = TCIF_STATE;
963         tcItem.dwStateMask = TCIS_BUTTONPRESSED;
964         tcItem.dwState = 0;
965         ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
966         ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
967     }
968     else win_skip( "Item state mask not supported\n" );
969
970     DestroyWindow(hTab);
971 }
972
973 static void test_getset_tooltips(void)
974 {
975     char toolTipText[32] = "ToolTip Text Test";
976     const INT nTabs = 5;
977     HWND hTab, toolTip;
978
979     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
980     ok(hTab != NULL, "Failed to create tab control\n");
981
982     flush_sequences(sequences, NUM_MSG_SEQUENCES);
983
984     toolTip = create_tooltip(hTab, toolTipText);
985     SendMessage(hTab, TCM_SETTOOLTIPS, (LPARAM) toolTip, 0);
986     ok (toolTip == (HWND) SendMessage(hTab,TCM_GETTOOLTIPS,0,0), "ToolTip was set incorrectly.\n");
987
988     SendMessage(hTab, TCM_SETTOOLTIPS, 0, 0);
989     ok (NULL  == (HWND) SendMessage(hTab,TCM_GETTOOLTIPS,0,0), "ToolTip was set incorrectly.\n");
990
991     ok_sequence(sequences, TAB_SEQ_INDEX, getset_tooltip_seq, "Getset tooltip test sequence", TRUE);
992     ok_sequence(sequences, PARENT_SEQ_INDEX, getset_tooltip_parent_seq, "Getset tooltip test parent sequence", TRUE);
993
994     DestroyWindow(hTab);
995 }
996
997 static void test_misc(void)
998 {
999     const INT nTabs = 5;
1000     HWND hTab;
1001     RECT rTab;
1002     INT nTabsRetrieved;
1003     INT rowCount;
1004     INT dpi;
1005     HDC hdc;
1006
1007     ok(parent_wnd != NULL, "no parent window!\n");
1008     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1009
1010     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
1011     ok(hTab != NULL, "Failed to create tab control\n");
1012
1013     if(!winetest_interactive)
1014         ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent,
1015                     "Tab sequence, after adding tab control to parent", TRUE);
1016     else
1017         ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent_interactive,
1018                     "Tab sequence, after adding tab control to parent", TRUE);
1019
1020     if(!winetest_interactive)
1021         ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq,
1022                     "Parent after sequence, adding tab control to parent", TRUE);
1023     else
1024         ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq_interactive,
1025                     "Parent after sequence, adding tab control to parent", TRUE);
1026
1027     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1028     ok(SendMessage(hTab, TCM_SETMINTABWIDTH, 0, -1) > 0,"TCM_SETMINTABWIDTH returned < 0\n");
1029     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Set minTabWidth test parent sequence", FALSE);
1030
1031     /* Testing GetItemCount */
1032     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1033     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1034     expect(nTabs, nTabsRetrieved);
1035     ok_sequence(sequences, TAB_SEQ_INDEX, get_item_count_seq, "Get itemCount test sequence", FALSE);
1036     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset itemCount test parent sequence", FALSE);
1037
1038     /* Testing GetRowCount */
1039     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1040     rowCount = SendMessage(hTab, TCM_GETROWCOUNT, 0, 0);
1041     expect(1, rowCount);
1042     ok_sequence(sequences, TAB_SEQ_INDEX, get_row_count_seq, "Get rowCount test sequence", FALSE);
1043     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get rowCount test parent sequence", FALSE);
1044
1045     /* Testing GetItemRect */
1046     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1047     ok(SendMessage(hTab, TCM_GETITEMRECT, 0, (LPARAM) &rTab), "GetItemRect failed.\n");
1048
1049     hdc = GetDC(hTab);
1050     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
1051     ReleaseDC(hTab, hdc);
1052     CHECKSIZE(hTab, dpi, -1 , "Default Width");
1053     ok_sequence(sequences, TAB_SEQ_INDEX, get_item_rect_seq, "Get itemRect test sequence", FALSE);
1054     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get itemRect test parent sequence", FALSE);
1055
1056     DestroyWindow(hTab);
1057 }
1058
1059 static void test_adjustrect(void)
1060 {
1061     HWND hTab;
1062     INT r;
1063
1064     ok(parent_wnd != NULL, "no parent window!\n");
1065
1066     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, 0, 0);
1067     ok(hTab != NULL, "Failed to create tab control\n");
1068
1069     r = SendMessage(hTab, TCM_ADJUSTRECT, FALSE, 0);
1070     expect(-1, r);
1071
1072     r = SendMessage(hTab, TCM_ADJUSTRECT, TRUE, 0);
1073     expect(-1, r);
1074 }
1075
1076 static void test_insert_focus(void)
1077 {
1078     HWND hTab;
1079     INT nTabsRetrieved;
1080     INT r;
1081     TCITEM tcNewTab;
1082     DWORD mask = TCIF_TEXT|TCIF_IMAGE;
1083     static char tabName[] = "TAB";
1084     tcNewTab.mask = mask;
1085     tcNewTab.pszText = tabName;
1086
1087     ok(parent_wnd != NULL, "no parent window!\n");
1088
1089     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, mask, 0);
1090     ok(hTab != NULL, "Failed to create tab control\n");
1091
1092     r = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
1093     expect(-1, r);
1094
1095     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1096
1097     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1098     expect(0, nTabsRetrieved);
1099
1100     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1101     expect(-1, r);
1102
1103     tcNewTab.iImage = 1;
1104     r = SendMessage(hTab, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab);
1105     expect(0, r);
1106
1107     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1108     expect(1, nTabsRetrieved);
1109
1110     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1111     expect(0, r);
1112
1113     tcNewTab.iImage = 2;
1114     r = SendMessage(hTab, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
1115     expect(1, r);
1116
1117     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1118     expect(2, nTabsRetrieved);
1119
1120     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1121     expect(0, r);
1122
1123     r = SendMessage(hTab, TCM_SETCURFOCUS, -1, 0);
1124     expect(0, r);
1125
1126     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1127     expect(-1, r);
1128
1129     tcNewTab.iImage = 3;
1130     r = SendMessage(hTab, TCM_INSERTITEM, 3, (LPARAM) &tcNewTab);
1131     expect(2, r);
1132
1133     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1134     expect(2, r);
1135
1136     ok_sequence(sequences, TAB_SEQ_INDEX, insert_focus_seq, "insert_focus test sequence", FALSE);
1137     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "insert_focus parent test sequence", TRUE);
1138
1139     DestroyWindow(hTab);
1140 }
1141
1142 static void test_delete_focus(void)
1143 {
1144     HWND hTab;
1145     INT nTabsRetrieved;
1146     INT r;
1147
1148     ok(parent_wnd != NULL, "no parent window!\n");
1149
1150     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 2);
1151     ok(hTab != NULL, "Failed to create tab control\n");
1152
1153     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1154
1155     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1156     expect(2, nTabsRetrieved);
1157
1158     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1159     expect(0, r);
1160
1161     r = SendMessage(hTab, TCM_DELETEITEM, 1, 0);
1162     expect(1, r);
1163
1164     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1165     expect(1, nTabsRetrieved);
1166
1167     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1168     expect(0, r);
1169
1170     r = SendMessage(hTab, TCM_SETCURFOCUS, -1, 0);
1171     expect(0, r);
1172
1173     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1174     expect(-1, r);
1175
1176     r = SendMessage(hTab, TCM_DELETEITEM, 0, 0);
1177     expect(1, r);
1178
1179     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1180     expect(0, nTabsRetrieved);
1181
1182     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1183     expect(-1, r);
1184
1185     ok_sequence(sequences, TAB_SEQ_INDEX, delete_focus_seq, "delete_focus test sequence", FALSE);
1186     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "delete_focus parent test sequence", TRUE);
1187
1188     DestroyWindow(hTab);
1189 }
1190
1191 static void test_removeimage(void)
1192 {
1193     static const BYTE bits[32];
1194     HWND hwTab;
1195     INT i;
1196     TCITEM item;
1197     HICON hicon;
1198     HIMAGELIST himl = ImageList_Create(16, 16, ILC_COLOR, 3, 4);
1199
1200     hicon = CreateIcon(NULL, 16, 16, 1, 1, bits, bits);
1201     ImageList_AddIcon(himl, hicon);
1202     ImageList_AddIcon(himl, hicon);
1203     ImageList_AddIcon(himl, hicon);
1204
1205     hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
1206     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
1207
1208     memset(&item, 0, sizeof(TCITEM));
1209     item.mask = TCIF_IMAGE;
1210
1211     for(i = 0; i < 3; i++) {
1212         SendMessage(hwTab, TCM_GETITEM, i, (LPARAM)&item);
1213         expect(i, item.iImage);
1214     }
1215
1216     /* remove image middle image */
1217     SendMessage(hwTab, TCM_REMOVEIMAGE, 1, 0);
1218     expect(2, ImageList_GetImageCount(himl));
1219     item.iImage = -1;
1220     SendMessage(hwTab, TCM_GETITEM, 0, (LPARAM)&item);
1221     expect(0, item.iImage);
1222     item.iImage = 0;
1223     SendMessage(hwTab, TCM_GETITEM, 1, (LPARAM)&item);
1224     expect(-1, item.iImage);
1225     item.iImage = 0;
1226     SendMessage(hwTab, TCM_GETITEM, 2, (LPARAM)&item);
1227     expect(1, item.iImage);
1228     /* remove first image */
1229     SendMessage(hwTab, TCM_REMOVEIMAGE, 0, 0);
1230     expect(1, ImageList_GetImageCount(himl));
1231     item.iImage = 0;
1232     SendMessage(hwTab, TCM_GETITEM, 0, (LPARAM)&item);
1233     expect(-1, item.iImage);
1234     item.iImage = 0;
1235     SendMessage(hwTab, TCM_GETITEM, 1, (LPARAM)&item);
1236     expect(-1, item.iImage);
1237     item.iImage = -1;
1238     SendMessage(hwTab, TCM_GETITEM, 2, (LPARAM)&item);
1239     expect(0, item.iImage);
1240     /* remove the last one */
1241     SendMessage(hwTab, TCM_REMOVEIMAGE, 0, 0);
1242     expect(0, ImageList_GetImageCount(himl));
1243     for(i = 0; i < 3; i++) {
1244         item.iImage = 0;
1245         SendMessage(hwTab, TCM_GETITEM, i, (LPARAM)&item);
1246         expect(-1, item.iImage);
1247     }
1248
1249     DestroyWindow(hwTab);
1250     ImageList_Destroy(himl);
1251     DestroyIcon(hicon);
1252 }
1253
1254 static void test_delete_selection(void)
1255 {
1256     HWND hTab;
1257     DWORD ret;
1258
1259     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
1260     ok(hTab != NULL, "Failed to create tab control\n");
1261
1262     ret = SendMessage(hTab, TCM_SETCURSEL, 3, 0);
1263     expect(0, ret);
1264     ret = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
1265     expect(3, ret);
1266     /* delete selected item - selection goes to -1 */
1267     ret = SendMessage(hTab, TCM_DELETEITEM, 3, 0);
1268     expect(TRUE, ret);
1269
1270     ret = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
1271     expect(-1, ret);
1272
1273     DestroyWindow(hTab);
1274 }
1275
1276 static void test_TCM_SETITEMEXTRA(void)
1277 {
1278     HWND hTab;
1279     DWORD ret;
1280
1281     hTab = CreateWindowA(
1282         WC_TABCONTROLA,
1283         "TestTab",
1284         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH,
1285         10, 10, 300, 100,
1286         parent_wnd, NULL, NULL, 0);
1287
1288     /* zero is valid size too */
1289     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 0, 0);
1290     if (ret == FALSE)
1291     {
1292         win_skip("TCM_SETITEMEXTRA not supported\n");
1293         DestroyWindow(hTab);
1294         return;
1295     }
1296
1297     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, -1, 0);
1298     ok(ret == FALSE, "got %d\n", ret);
1299
1300     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 2, 0);
1301     ok(ret == TRUE, "got %d\n", ret);
1302     DestroyWindow(hTab);
1303
1304     /* it's not possible to change extra data size for control with tabs */
1305     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
1306     ok(hTab != NULL, "Failed to create tab control\n");
1307
1308     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 2, 0);
1309     ok(ret == FALSE, "got %d\n", ret);
1310     DestroyWindow(hTab);
1311 }
1312
1313 static void test_TCS_OWNERDRAWFIXED(void)
1314 {
1315     LPARAM lparam, lparam2;
1316     TCITEMA item;
1317     HWND hTab;
1318     BOOL ret;
1319
1320     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH|TCS_OWNERDRAWFIXED, TCIF_TEXT|TCIF_IMAGE, 4);
1321     ok(hTab != NULL, "Failed to create tab control\n");
1322
1323     ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1324
1325     /* set some item data */
1326     memset(&lparam, 0xde, sizeof(LPARAM));
1327
1328     item.mask = TCIF_PARAM;
1329     item.lParam = lparam;
1330     ret = SendMessageA(hTab, TCM_SETITEMA, 0, (LPARAM)&item);
1331     ok(ret == TRUE, "got %d\n", ret);
1332
1333     memset(&g_drawitem, 0, sizeof(g_drawitem));
1334
1335     ShowWindow(hTab, SW_SHOW);
1336     RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
1337
1338     lparam = 0;
1339     memset(&lparam, 0xde, 4);
1340     ok(g_drawitem.itemData == lparam, "got %lx, expected %lx\n", g_drawitem.itemData, lparam);
1341
1342     DestroyWindow(hTab);
1343
1344     /* now with custom extra data length */
1345     hTab = CreateWindowA(
1346         WC_TABCONTROLA,
1347         "TestTab",
1348         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED,
1349         10, 10, 300, 100,
1350         parent_wnd, NULL, NULL, 0);
1351
1352     ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1353
1354     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)+1, 0);
1355     ok(ret == TRUE, "got %d\n", ret);
1356
1357     /* set some item data */
1358     memset(&lparam, 0xde, sizeof(LPARAM));
1359     item.mask = TCIF_PARAM;
1360     item.lParam = lparam;
1361
1362     ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&item);
1363     ok(ret == 0, "got %d\n", ret);
1364
1365     memset(&g_drawitem, 0, sizeof(g_drawitem));
1366
1367     ShowWindow(hTab, SW_SHOW);
1368     RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
1369
1370     ok(*(ULONG_PTR*)g_drawitem.itemData == lparam, "got %lx, expected %lx\n", g_drawitem.itemData, lparam);
1371
1372     DestroyWindow(hTab);
1373
1374     /* same thing, but size smaller than default */
1375     hTab = CreateWindowA(
1376         WC_TABCONTROLA,
1377         "TestTab",
1378         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED,
1379         10, 10, 300, 100,
1380         parent_wnd, NULL, NULL, 0);
1381
1382     ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1383
1384     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)-1, 0);
1385     ok(ret == TRUE, "got %d\n", ret);
1386
1387     memset(&lparam, 0xde, sizeof(lparam));
1388     item.mask = TCIF_PARAM;
1389     item.lParam = lparam;
1390
1391     ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&item);
1392     ok(ret == 0, "got %d\n", ret);
1393
1394     memset(&g_drawitem, 0, sizeof(g_drawitem));
1395
1396     ShowWindow(hTab, SW_SHOW);
1397     RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
1398
1399     lparam = 0;
1400     memset(&lparam, 0xde, 4);
1401     memset(&lparam2, 0xde, sizeof(LPARAM)-1);
1402     ok(g_drawitem.itemData == lparam || broken(g_drawitem.itemData == lparam2) /* win98 */,
1403         "got 0x%lx, expected 0x%lx\n", g_drawitem.itemData, lparam);
1404
1405     DestroyWindow(hTab);
1406 }
1407
1408 START_TEST(tab)
1409 {
1410     LOGFONTA logfont;
1411
1412     lstrcpyA(logfont.lfFaceName, "Arial");
1413     memset(&logfont, 0, sizeof(logfont));
1414     logfont.lfHeight = -12;
1415     logfont.lfWeight = FW_NORMAL;
1416     logfont.lfCharSet = ANSI_CHARSET;
1417     hFont = CreateFontIndirectA(&logfont);
1418
1419     InitCommonControls();
1420
1421     test_width();
1422
1423     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
1424
1425     parent_wnd = createParentWindow();
1426     ok(parent_wnd != NULL, "Failed to create parent window!\n");
1427
1428     test_curfocus();
1429     test_cursel();
1430     test_extendedstyle();
1431     test_unicodeformat();
1432     test_getset_item();
1433     test_getset_tooltips();
1434     test_misc();
1435
1436     test_adjustrect();
1437
1438     test_insert_focus();
1439     test_delete_focus();
1440     test_delete_selection();
1441     test_removeimage();
1442     test_TCM_SETITEMEXTRA();
1443     test_TCS_OWNERDRAWFIXED();
1444
1445     DestroyWindow(parent_wnd);
1446 }