quartz: Make dwSamplesProcessed a longlong.
[wine] / dlls / comctl32 / tests / monthcal.c
1 /*
2  * comctl32 month calendar unit tests
3  *
4  * Copyright (C) 2006 Vitaliy Margolen
5  * Copyright (C) 2007 Farshad Agah
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27
28 #include "commctrl.h"
29
30 #include "wine/test.h"
31 #include <assert.h>
32 #include <windows.h>
33 #include "msg.h"
34
35 #define expect(expected, got) ok(expected == got, "Expected %d, got %d\n", expected, got);
36
37 #define NUM_MSG_SEQUENCES   2
38 #define PARENT_SEQ_INDEX    0
39 #define MONTHCAL_SEQ_INDEX  1
40
41 struct subclass_info
42 {
43     WNDPROC oldproc;
44 };
45
46 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
47
48 static const struct message create_parent_window_seq[] = {
49     { WM_GETMINMAXINFO, sent },
50     { WM_NCCREATE, sent },
51     { WM_NCCALCSIZE, sent|wparam, 0 },
52     { WM_CREATE, sent },
53     { WM_SHOWWINDOW, sent|wparam, 1 },
54     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
55     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
56     { WM_ACTIVATEAPP, sent|wparam, 1 },
57     { WM_NCACTIVATE, sent|wparam, 1 },
58     { WM_ACTIVATE, sent|wparam, 1 },
59     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
60     { WM_IME_NOTIFY, sent|defwinproc|optional },
61     { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
62     /* Win9x adds SWP_NOZORDER below */
63     { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
64     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
65     { WM_SIZE, sent },
66     { WM_MOVE, sent },
67     { 0 }
68 };
69
70 static const struct message create_monthcal_control_seq[] = {
71     { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
72     { WM_QUERYUISTATE, sent },
73     { WM_GETFONT, sent },
74     { WM_PARENTNOTIFY, sent|wparam, WM_CREATE},
75     { 0 }
76 };
77
78 static const struct message create_monthcal_multi_sel_style_seq[] = {
79     { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
80     { WM_QUERYUISTATE, sent },
81     { WM_GETFONT, sent },
82     { 0 }
83 };
84
85 static const struct message monthcal_color_seq[] = {
86     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0},
87     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, RGB(0,0,0)},
88     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0},
89     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, RGB(255,255,255)},
90     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0},
91
92     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0},
93     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, RGB(0,0,0)},
94     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0},
95     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, RGB(255,255,255)},
96     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0},
97
98     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TEXT, 0},
99     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TEXT, RGB(0,0,0)},
100     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TEXT, 0},
101     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TEXT, RGB(255,255,255)},
102     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TEXT, 0},
103
104     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0},
105     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, RGB(0,0,0)},
106     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0},
107     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, RGB(255,255,255)},
108     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0},
109
110     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0},
111     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, RGB(0,0,0)},
112     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0},
113     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, RGB(255,255,255)},
114     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0},
115
116     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0},
117     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, RGB(0,0,0)},
118     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0},
119     { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, RGB(255,255,255)},
120     { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0},
121     { 0 }
122 };
123
124 static const struct message monthcal_curr_date_seq[] = {
125     { MCM_SETCURSEL, sent|wparam, 0},
126     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
127     { WM_ERASEBKGND, sent|lparam|defwinproc, 0},
128     { MCM_SETCURSEL, sent|wparam, 0},
129     { MCM_SETCURSEL, sent|wparam, 0},
130     { MCM_GETCURSEL, sent|wparam, 0},
131     { MCM_GETCURSEL, sent|wparam|lparam, 0, 0},
132     { 0 }
133 };
134
135 static const struct message monthcal_first_day_seq[] = {
136     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
137
138     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -5},
139     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
140
141     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -4},
142     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
143
144     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -3},
145     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
146
147     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -2},
148     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
149
150     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -1},
151     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
152
153     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
154     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
155
156     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 1},
157     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
158
159     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 2},
160     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
161
162     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 3},
163     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
164
165     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 4},
166     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
167
168     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 5},
169     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
170
171     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 6},
172     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
173
174     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 7},
175     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
176
177     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 8},
178     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
179
180     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 9},
181     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
182
183     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 10},
184     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
185
186     { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 11},
187     { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
188     { 0 }
189 };
190
191 static const struct message monthcal_unicode_seq[] = {
192     { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
193     { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 1, 0},
194     { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
195     { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
196     { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
197     { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 1, 0},
198     { 0 }
199 };
200
201 static const struct message monthcal_hit_test_seq[] = {
202     { MCM_SETCURSEL, sent|wparam, 0},
203     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
204     { MCM_HITTEST, sent|wparam, 0},
205     { MCM_HITTEST, sent|wparam, 0},
206     { MCM_HITTEST, sent|wparam, 0},
207     { MCM_HITTEST, sent|wparam, 0},
208     { MCM_HITTEST, sent|wparam, 0},
209     { MCM_HITTEST, sent|wparam, 0},
210     { MCM_HITTEST, sent|wparam, 0},
211     { MCM_HITTEST, sent|wparam, 0},
212     { MCM_HITTEST, sent|wparam, 0},
213     { MCM_HITTEST, sent|wparam, 0},
214     { MCM_HITTEST, sent|wparam, 0},
215     { MCM_HITTEST, sent|wparam, 0},
216     { MCM_HITTEST, sent|wparam, 0},
217     { MCM_HITTEST, sent|wparam, 0},
218     { MCM_HITTEST, sent|wparam, 0},
219     { MCM_HITTEST, sent|wparam, 0},
220     { MCM_HITTEST, sent|wparam, 0},
221     { 0 }
222 };
223
224 static const struct message monthcal_todaylink_seq[] = {
225     { MCM_HITTEST, sent|wparam, 0},
226     { MCM_SETTODAY, sent|wparam, 0},
227     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
228     { MCM_GETTODAY, sent|wparam, 0},
229     { WM_LBUTTONDOWN, sent|wparam|lparam, MK_LBUTTON, MAKELONG(70, 370)},
230     { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0},
231     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
232     { MCM_GETCURSEL, sent|wparam, 0},
233     { 0 }
234 };
235
236 static const struct message monthcal_today_seq[] = {
237     { MCM_SETTODAY, sent|wparam, 0},
238     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
239     { MCM_GETTODAY, sent|wparam, 0},
240     { MCM_SETTODAY, sent|wparam, 0},
241     { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
242     { MCM_GETTODAY, sent|wparam, 0},
243     { 0 }
244 };
245
246 static const struct message monthcal_scroll_seq[] = {
247     { MCM_SETMONTHDELTA, sent|wparam|lparam, 2, 0},
248     { MCM_SETMONTHDELTA, sent|wparam|lparam, 3, 0},
249     { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
250     { MCM_SETMONTHDELTA, sent|wparam|lparam, 12, 0},
251     { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
252     { MCM_SETMONTHDELTA, sent|wparam|lparam, 15, 0},
253     { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
254     { MCM_SETMONTHDELTA, sent|wparam|lparam, -5, 0},
255     { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
256     { 0 }
257 };
258
259 static const struct message monthcal_monthrange_seq[] = {
260     { MCM_GETMONTHRANGE, sent|wparam, GMR_VISIBLE},
261     { MCM_GETMONTHRANGE, sent|wparam, GMR_DAYSTATE},
262     { 0 }
263 };
264
265 static const struct message monthcal_max_sel_day_seq[] = {
266     { MCM_SETMAXSELCOUNT, sent|wparam|lparam, 5, 0},
267     { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
268     { MCM_SETMAXSELCOUNT, sent|wparam|lparam, 15, 0},
269     { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
270     { MCM_SETMAXSELCOUNT, sent|wparam|lparam, -1, 0},
271     { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
272     { 0 }
273 };
274
275 /* expected message sequence for parent*/
276 static const struct message destroy_monthcal_parent_msgs_seq[] = {
277     { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY},
278     { 0 }
279 };
280
281 /* expected message sequence for child*/
282 static const struct message destroy_monthcal_child_msgs_seq[] = {
283     { 0x0090, sent|optional }, /* Vista */
284     { WM_SHOWWINDOW, sent|wparam|lparam, 0, 0},
285     { WM_WINDOWPOSCHANGING, sent|wparam, 0},
286     { WM_WINDOWPOSCHANGED, sent|wparam, 0},
287     { WM_DESTROY, sent|wparam|lparam, 0, 0},
288     { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
289     { 0 }
290 };
291
292 static const struct message destroy_monthcal_multi_sel_style_seq[] = {
293     { 0x0090, sent|optional }, /* Vista */
294     { WM_DESTROY, sent|wparam|lparam, 0, 0},
295     { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
296     { 0 }
297 };
298
299 /* expected message sequence for parent window*/
300 static const struct message destroy_parent_seq[] = {
301     { 0x0090, sent|optional }, /* Vista */
302     { WM_WINDOWPOSCHANGING, sent|wparam, 0},
303     { WM_WINDOWPOSCHANGED, sent|wparam, 0},
304     { WM_NCACTIVATE, sent|wparam|lparam, 0, 0},
305     { WM_ACTIVATE, sent|wparam|lparam, 0, 0},
306     { WM_ACTIVATEAPP, sent|wparam, 0},
307     { WM_KILLFOCUS, sent|wparam|lparam, 0, 0},
308     { WM_IME_SETCONTEXT, sent|wparam|optional, 0},
309     { WM_IME_NOTIFY, sent|wparam|lparam|defwinproc|optional, 1, 0},
310     { WM_DESTROY, sent|wparam|lparam, 0, 0},
311     { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
312     { 0 }
313 };
314
315 static void test_monthcal(void)
316 {
317     HWND hwnd;
318     SYSTEMTIME st[2], st1[2];
319     int res, month_range;
320
321     hwnd = CreateWindowA(MONTHCAL_CLASSA, "MonthCal", WS_POPUP | WS_VISIBLE, CW_USEDEFAULT,
322                          0, 300, 300, 0, 0, NULL, NULL);
323     ok(hwnd != NULL, "Failed to create MonthCal\n");
324     GetSystemTime(&st[0]);
325     st[1] = st[0];
326
327     /* Invalid date/time */
328     st[0].wYear  = 2000;
329     /* Time should not matter */
330     st[1].wHour = st[1].wMinute = st[1].wSecond = 70;
331     ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set MAX limit\n");
332     ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n");
333     ok(st1[0].wYear != 2000, "Lover limit changed\n");
334
335     st[1].wMonth = 0;
336     ok(!SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Should have failed to set limits\n");
337     ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n");
338     ok(st1[0].wYear != 2000, "Lover limit changed\n");
339     ok(!SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Should have failed to set MAX limit\n");
340     ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n");
341     ok(st1[0].wYear != 2000, "Lover limit changed\n");
342
343     GetSystemTime(&st[0]);
344     st[0].wDay = 20;
345     st[0].wMonth = 5;
346     st[1] = st[0];
347
348     month_range = SendMessage(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1);
349     st[1].wMonth--;
350     ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Failed to set both min and max limits\n");
351     res = SendMessage(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1);
352     ok(res == month_range, "Invalid month range (%d)\n", res);
353     ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == (GDTR_MIN|GDTR_MAX), "Limits should be set\n");
354
355     st[1].wMonth += 2;
356     ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Failed to set both min and max limits\n");
357     res = SendMessage(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st1);
358     ok(res == month_range, "Invalid month range (%d)\n", res);
359
360     st[1].wYear --;
361     ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Failed to set both min and max limits\n");
362     st[1].wYear += 1;
363     ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Failed to set both min and max limits\n");
364
365     st[1].wMonth -= 3;
366     ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
367     ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "Only MAX limit should be set\n");
368     st[1].wMonth += 4;
369     ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
370     st[1].wYear -= 3;
371     ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
372     st[1].wYear += 4;
373     ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
374     ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "Only MAX limit should be set\n");
375
376     DestroyWindow(hwnd);
377 }
378
379 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
380 {
381     static long defwndproc_counter = 0;
382     LRESULT ret;
383     struct message msg;
384
385     /* do not log painting messages */
386     if (message != WM_PAINT &&
387         message != WM_ERASEBKGND &&
388         message != WM_NCPAINT &&
389         message != WM_NCHITTEST &&
390         message != WM_GETTEXT &&
391         message != WM_GETICON &&
392         message != WM_DEVICECHANGE)
393     {
394         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
395
396         msg.message = message;
397         msg.flags = sent|wparam|lparam;
398         if (defwndproc_counter) msg.flags |= defwinproc;
399         msg.wParam = wParam;
400         msg.lParam = lParam;
401         add_message(sequences, PARENT_SEQ_INDEX, &msg);
402     }
403
404     defwndproc_counter++;
405     ret = DefWindowProcA(hwnd, message, wParam, lParam);
406     defwndproc_counter--;
407
408     return ret;
409 }
410
411 static BOOL register_parent_wnd_class(void)
412 {
413     WNDCLASSA cls;
414
415     cls.style = 0;
416     cls.lpfnWndProc = parent_wnd_proc;
417     cls.cbClsExtra = 0;
418     cls.cbWndExtra = 0;
419     cls.hInstance = GetModuleHandleA(NULL);
420     cls.hIcon = 0;
421     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
422     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
423     cls.lpszMenuName = NULL;
424     cls.lpszClassName = "Month-Cal test parent class";
425     return RegisterClassA(&cls);
426 }
427
428 static HWND create_parent_window(void)
429 {
430     HWND hwnd;
431
432     InitCommonControls();
433
434     /* flush message sequences, so we can check the new sequence by the end of function */
435     flush_sequences(sequences, NUM_MSG_SEQUENCES);
436
437     if (!register_parent_wnd_class())
438         return NULL;
439
440     hwnd = CreateWindowEx(0, "Month-Cal test parent class",
441                           "Month-Cal test parent window",
442                           WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
443                           WS_MAXIMIZEBOX | WS_VISIBLE,
444                           0, 0, 500, 500,
445                           GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
446
447     assert(hwnd);
448
449     /* check for message sequences */
450     ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_window_seq, "create parent window", TRUE);
451
452     return hwnd;
453 }
454
455 static LRESULT WINAPI monthcal_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
456 {
457     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
458     static long defwndproc_counter = 0;
459     LRESULT ret;
460     struct message msg;
461
462     trace("monthcal: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
463
464     msg.message = message;
465     msg.flags = sent|wparam|lparam;
466     if (defwndproc_counter) msg.flags |= defwinproc;
467     msg.wParam = wParam;
468     msg.lParam = lParam;
469     add_message(sequences, MONTHCAL_SEQ_INDEX, &msg);
470
471     defwndproc_counter++;
472     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
473     defwndproc_counter--;
474
475     return ret;
476 }
477
478 static HWND create_monthcal_control(DWORD style, HWND parent_window)
479 {
480     struct subclass_info *info;
481     HWND hwnd;
482
483     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
484     if (!info)
485         return NULL;
486
487     hwnd = CreateWindowEx(0,
488                     MONTHCAL_CLASS,
489                     "",
490                     style,
491                     0, 0, 300, 400,
492                     parent_window, NULL, GetModuleHandleA(NULL), NULL);
493
494     if (!hwnd)
495     {
496         HeapFree(GetProcessHeap(), 0, info);
497         return NULL;
498     }
499
500     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
501                                             (LONG_PTR)monthcal_subclass_proc);
502     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
503
504     return hwnd;
505 }
506
507
508 /* Setter and Getters Tests */
509
510 static void test_monthcal_color(HWND hwnd)
511 {
512     int res, temp;
513
514     flush_sequences(sequences, NUM_MSG_SEQUENCES);
515
516     /* Setter and Getters for color*/
517     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
518     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_BACKGROUND, RGB(0,0,0));
519     expect(temp, res);
520     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
521     expect(RGB(0,0,0), temp);
522     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_BACKGROUND, RGB(255,255,255));
523     expect(temp, res);
524     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
525     expect(RGB(255,255,255), temp);
526
527     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
528     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_MONTHBK, RGB(0,0,0));
529     expect(temp, res);
530     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
531     expect(RGB(0,0,0), temp);
532     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_MONTHBK, RGB(255,255,255));
533     expect(temp, res);
534     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
535     expect(RGB(255,255,255), temp);
536
537     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
538     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TEXT, RGB(0,0,0));
539     expect(temp, res);
540     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
541     expect(RGB(0,0,0), temp);
542     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TEXT, RGB(255,255,255));
543     expect(temp, res);
544     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
545     expect(RGB(255,255,255), temp);
546
547     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
548     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLEBK, RGB(0,0,0));
549     expect(temp, res);
550     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
551     expect(RGB(0,0,0), temp);
552     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLEBK, RGB(255,255,255));
553     expect(temp, res);
554     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
555     expect(RGB(255,255,255), temp);
556
557     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
558     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLETEXT, RGB(0,0,0));
559     expect(temp, res);
560     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
561     expect(RGB(0,0,0), temp);
562     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLETEXT, RGB(255,255,255));
563     expect(temp, res);
564     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
565     expect(RGB(255,255,255), temp);
566
567     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
568     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT, RGB(0,0,0));
569     expect(temp, res);
570     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
571     expect(RGB(0,0,0), temp);
572     res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT, RGB(255,255,255));
573     expect(temp, res);
574     temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
575     expect(RGB(255,255,255), temp);
576
577     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_color_seq, "monthcal color", FALSE);
578 }
579
580 static void test_monthcal_currDate(HWND hwnd)
581 {
582     SYSTEMTIME st_original, st_new, st_test;
583     int res;
584
585     flush_sequences(sequences, NUM_MSG_SEQUENCES);
586
587     /* Setter and Getters for current date selected */
588     st_original.wYear = 2000;
589     st_original.wMonth = 11;
590     st_original.wDay = 28;
591     st_original.wHour = 11;
592     st_original.wMinute = 59;
593     st_original.wSecond = 30;
594     st_original.wMilliseconds = 0;
595     st_original.wDayOfWeek = 0;
596
597     st_new = st_test = st_original;
598
599     /* Should not validate the time */
600     res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
601     expect(1,res);
602
603     /* Overflow matters, check for wDay */
604     st_test.wDay += 4;
605     res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
606     expect(0,res);
607
608     /* correct wDay before checking for wMonth */
609     st_test.wDay -= 4;
610     expect(st_original.wDay, st_test.wDay);
611
612     /* Overflow matters, check for wMonth */
613     st_test.wMonth += 4;
614     res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
615     expect(0,res);
616
617     /* checking if gets the information right, modify st_new */
618     st_new.wYear += 4;
619     st_new.wMonth += 4;
620     st_new.wDay += 4;
621     st_new.wHour += 4;
622     st_new.wMinute += 4;
623     st_new.wSecond += 4;
624
625     res = SendMessage(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new);
626     expect(1, res);
627
628     /* st_new change to st_origin, above settings with overflow */
629     /* should not change the current settings */
630     expect(st_original.wYear, st_new.wYear);
631     expect(st_original.wMonth, st_new.wMonth);
632     expect(st_original.wDay, st_new.wDay);
633     expect(st_original.wHour, st_new.wHour);
634     expect(st_original.wMinute, st_new.wMinute);
635     expect(st_original.wSecond, st_new.wSecond);
636
637     /* lparam cannot be NULL */
638     res = SendMessage(hwnd, MCM_GETCURSEL, 0, (LPARAM) NULL);
639     expect(0, res);
640
641     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_curr_date_seq, "monthcal currDate", TRUE);
642 }
643
644 static void test_monthcal_firstDay(HWND hwnd)
645 {
646     int res, fday, i, prev;
647     TCHAR b[128];
648     LCID lcid = LOCALE_USER_DEFAULT;
649
650     flush_sequences(sequences, NUM_MSG_SEQUENCES);
651
652     /* Setter and Getters for first day of week */
653     /* check for locale first day */
654     if(GetLocaleInfo(lcid, LOCALE_IFIRSTDAYOFWEEK, b, 128)){
655         fday = atoi(b);
656         res = SendMessage(hwnd, MCM_GETFIRSTDAYOFWEEK, 0, 0);
657         expect(fday, res);
658         prev = fday;
659
660         /* checking for the values that actually will be stored as */
661         /* current first day when we set a new value */
662         for (i = -5; i < 12; i++){
663             res = SendMessage(hwnd, MCM_SETFIRSTDAYOFWEEK, 0, (LPARAM) i);
664             expect(prev, res);
665             res = SendMessage(hwnd, MCM_GETFIRSTDAYOFWEEK, 0, 0);
666             prev = res;
667
668             if (i == -1){
669                 expect(MAKELONG(fday, FALSE), res);
670             }else if (i >= 7){
671                 expect(MAKELONG(fday, TRUE), res);
672             }else{
673                 expect(MAKELONG(i, TRUE), res);
674             }
675         }
676
677         ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_first_day_seq, "monthcal firstDay", FALSE);
678
679     }else{
680         skip("Cannot retrieve first day of the week\n");
681     }
682
683 }
684
685 static void test_monthcal_unicode(HWND hwnd)
686 {
687     int res, temp;
688
689     flush_sequences(sequences, NUM_MSG_SEQUENCES);
690
691     /* Setter and Getters for Unicode format */
692
693     /* getting the current settings */
694     temp = SendMessage(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
695
696     /* setting to 1, should return previous settings */
697     res = SendMessage(hwnd, MCM_SETUNICODEFORMAT, 1, 0);
698     expect(temp, res);
699
700     /* current setting is 1, so, should return 1 */
701     res = SendMessage(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
702     todo_wine {expect(1, res);}
703
704     /* setting to 0, should return previous settings */
705     res = SendMessage(hwnd, MCM_SETUNICODEFORMAT, 0, 0);
706     todo_wine {expect(1, res);}
707
708     /* current setting is 0, so, it should return 0 */
709     res = SendMessage(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
710     expect(0, res);
711
712     /* should return previous settings */
713     res = SendMessage(hwnd, MCM_SETUNICODEFORMAT, 1, 0);
714     expect(0, res);
715
716     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_unicode_seq, "monthcal unicode", FALSE);
717 }
718
719 static void test_monthcal_HitTest(HWND hwnd)
720 {
721     MCHITTESTINFO mchit;
722     UINT res;
723     SYSTEMTIME st;
724
725     memset(&mchit, 0, sizeof(MCHITTESTINFO));
726
727     flush_sequences(sequences, NUM_MSG_SEQUENCES);
728
729     st.wYear = 2007;
730     st.wMonth = 4;
731     st.wDay = 11;
732     st.wHour = 1;
733     st.wMinute = 0;
734     st.wSecond = 0;
735     st.wMilliseconds = 0;
736     st.wDayOfWeek = 0;
737
738     res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st);
739     expect(1,res);
740
741     /* (0, 0) is the top left of the control and should not be active */
742     mchit.cbSize = sizeof(MCHITTESTINFO);
743     mchit.pt.x = 0;
744     mchit.pt.y = 0;
745     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
746     expect(0, mchit.pt.x);
747     expect(0, mchit.pt.y);
748     expect(mchit.uHit, res);
749     todo_wine {expect(MCHT_NOWHERE, res);}
750
751     /* (300, 400) is the bottom right of the control and should not be active */
752     mchit.pt.x = 300;
753     mchit.pt.y = 400;
754     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
755     expect(300, mchit.pt.x);
756     expect(400, mchit.pt.y);
757     expect(mchit.uHit, res);
758     todo_wine {expect(MCHT_NOWHERE, res);}
759
760     /* (500, 500) is completely out of the control and should not be active */
761     mchit.pt.x = 500;
762     mchit.pt.y = 500;
763     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
764     expect(500, mchit.pt.x);
765     expect(500, mchit.pt.y);
766     expect(mchit.uHit, res);
767     todo_wine {expect(MCHT_NOWHERE, res);}
768
769     /* (120, 180) is in active area - calendar background */
770     mchit.pt.x = 120;
771     mchit.pt.y = 180;
772     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
773     expect(120, mchit.pt.x);
774     expect(180, mchit.pt.y);
775     expect(mchit.uHit, res);
776     expect(MCHT_CALENDARBK, res);
777
778     /* (50, 40) is in active area - previous month button */
779     mchit.pt.x = 50;
780     mchit.pt.y = 40;
781     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
782     expect(50, mchit.pt.x);
783     expect(40, mchit.pt.y);
784     expect(mchit.uHit, res);
785     todo_wine {expect(MCHT_TITLEBTNPREV, res);}
786
787     /* (90, 40) is in active area - background section of the title */
788     mchit.pt.x = 90;
789     mchit.pt.y = 40;
790     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
791     expect(90, mchit.pt.x);
792     expect(40, mchit.pt.y);
793     expect(mchit.uHit, res);
794     todo_wine {expect(MCHT_TITLE, res);}
795
796     /* (140, 40) is in active area - month section of the title */
797     mchit.pt.x = 140;
798     mchit.pt.y = 40;
799     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
800     expect(140, mchit.pt.x);
801     expect(40, mchit.pt.y);
802     expect(mchit.uHit, res);
803     todo_wine {expect(MCHT_TITLEMONTH, res);}
804
805     /* (250, 40) is in active area - next month button */
806     mchit.pt.x = 250;
807     mchit.pt.y = 40;
808     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
809     expect(250, mchit.pt.x);
810     expect(40, mchit.pt.y);
811     expect(mchit.uHit, res);
812     todo_wine {expect(MCHT_TITLEBTNNEXT, res);}
813
814     /* (70, 70) is in active area - day of the week */
815     mchit.pt.x = 70;
816     mchit.pt.y = 70;
817     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
818     expect(70, mchit.pt.x);
819     expect(70, mchit.pt.y);
820     expect(mchit.uHit, res);
821     todo_wine {expect(MCHT_CALENDARDAY, res);}
822
823     /* (70, 90) is in active area - date from prev month */
824     mchit.pt.x = 70;
825     mchit.pt.y = 90;
826     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
827     expect(70, mchit.pt.x);
828     expect(90, mchit.pt.y);
829     expect(mchit.uHit, res);
830     todo_wine {expect(MCHT_CALENDARDATEPREV, res);}
831
832 #if 0
833     /* (125, 115) is in active area - date from this month */
834     mchit.pt.x = 125;
835     mchit.pt.y = 115;
836     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
837     expect(125, mchit.pt.x);
838     expect(115, mchit.pt.y);
839     expect(mchit.uHit, res);
840     expect(MCHT_CALENDARDATE, res);
841 #endif
842
843     /* (80, 220) is in active area - background section of the title */
844     mchit.pt.x = 80;
845     mchit.pt.y = 220;
846     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
847     expect(80, mchit.pt.x);
848     expect(220, mchit.pt.y);
849     expect(mchit.uHit, res);
850     todo_wine {expect(MCHT_TITLEBK, res);}
851
852     /* (140, 215) is in active area - month section of the title */
853     mchit.pt.x = 140;
854     mchit.pt.y = 215;
855     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
856     expect(140, mchit.pt.x);
857     expect(215, mchit.pt.y);
858     expect(mchit.uHit, res);
859     todo_wine {expect(MCHT_TITLEMONTH, res);}
860
861     /* (170, 215) is in active area - year section of the title */
862     mchit.pt.x = 170;
863     mchit.pt.y = 215;
864     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
865     expect(170, mchit.pt.x);
866     expect(215, mchit.pt.y);
867     expect(mchit.uHit, res);
868     todo_wine {expect(MCHT_TITLEYEAR, res);}
869
870     /* (150, 260) is in active area - date from this month */
871     mchit.pt.x = 150;
872     mchit.pt.y = 260;
873     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
874     expect(150, mchit.pt.x);
875     expect(260, mchit.pt.y);
876     expect(mchit.uHit, res);
877     todo_wine {expect(MCHT_CALENDARDATE, res);}
878
879     /* (150, 350) is in active area - date from next month */
880     mchit.pt.x = 150;
881     mchit.pt.y = 350;
882     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
883     expect(150, mchit.pt.x);
884     expect(350, mchit.pt.y);
885     expect(mchit.uHit, res);
886     todo_wine {expect(MCHT_CALENDARDATENEXT, res);}
887
888     /* (150, 370) is in active area - today link */
889     mchit.pt.x = 150;
890     mchit.pt.y = 370;
891     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
892     expect(150, mchit.pt.x);
893     expect(370, mchit.pt.y);
894     expect(mchit.uHit, res);
895     todo_wine {expect(MCHT_TODAYLINK, res);}
896
897     /* (70, 370) is in active area - today link */
898     mchit.pt.x = 70;
899     mchit.pt.y = 370;
900     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
901     expect(70, mchit.pt.x);
902     expect(370, mchit.pt.y);
903     expect(mchit.uHit, res);
904     todo_wine {expect(MCHT_TODAYLINK, res);}
905
906     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_hit_test_seq, "monthcal hit test", TRUE);
907 }
908
909 static void test_monthcal_todaylink(HWND hwnd)
910 {
911     MCHITTESTINFO mchit;
912     SYSTEMTIME st_test, st_new;
913     BOOL error = FALSE;
914     UINT res;
915
916     memset(&mchit, 0, sizeof(MCHITTESTINFO));
917
918     flush_sequences(sequences, NUM_MSG_SEQUENCES);
919
920     /* (70, 370) is in active area - today link */
921     mchit.cbSize = sizeof(MCHITTESTINFO);
922     mchit.pt.x = 70;
923     mchit.pt.y = 370;
924     res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
925     expect(70, mchit.pt.x);
926     expect(370, mchit.pt.y);
927     expect(mchit.uHit, res);
928     todo_wine {expect(MCHT_TODAYLINK, res);}
929     if (70 != mchit.pt.x || 370 != mchit.pt.y || mchit.uHit != res
930         || MCHT_TODAYLINK != res)
931         error = TRUE;
932
933     st_test.wDay = 1;
934     st_test.wMonth = 1;
935     st_test.wYear = 2005;
936     memset(&st_new, 0, sizeof(SYSTEMTIME));
937
938     SendMessage(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
939
940     res = SendMessage(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
941     expect(1, res);
942     expect(1, st_new.wDay);
943     expect(1, st_new.wMonth);
944     expect(2005, st_new.wYear);
945     if (1 != res || 1 != st_new.wDay || 1 != st_new.wMonth
946         || 2005 != st_new.wYear)
947         error = TRUE;
948
949     if (error) {
950         skip("cannot perform today link test\n");
951         return;
952     }
953
954     res = SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(70, 370));
955     expect(0, res);
956
957     memset(&st_new, 0, sizeof(SYSTEMTIME));
958     res = SendMessage(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new);
959     expect(1, res);
960     expect(1, st_new.wDay);
961     expect(1, st_new.wMonth);
962     expect(2005, st_new.wYear);
963
964     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_todaylink_seq, "monthcal hit test", TRUE);
965 }
966
967 static void test_monthcal_today(HWND hwnd)
968 {
969     SYSTEMTIME st_test, st_new;
970     int res;
971
972     flush_sequences(sequences, NUM_MSG_SEQUENCES);
973
974     /* Setter and Getters for "today" information */
975
976     /* check for overflow, should be ok */
977     st_test.wDay = 38;
978     st_test.wMonth = 38;
979
980     st_new.wDay = 27;
981     st_new.wMonth = 27;
982
983     SendMessage(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
984
985     res = SendMessage(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
986     expect(1, res);
987
988     /* st_test should not change */
989     expect(38, st_test.wDay);
990     expect(38, st_test.wMonth);
991
992     /* st_new should change, overflow does not matter */
993     expect(38, st_new.wDay);
994     expect(38, st_new.wMonth);
995
996     /* check for zero, should be ok*/
997     st_test.wDay = 0;
998     st_test.wMonth = 0;
999
1000     SendMessage(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
1001
1002     res = SendMessage(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
1003     expect(1, res);
1004
1005     /* st_test should not change */
1006     expect(0, st_test.wDay);
1007     expect(0, st_test.wMonth);
1008
1009     /* st_new should change to zero*/
1010     expect(0, st_new.wDay);
1011     expect(0, st_new.wMonth);
1012
1013     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_today_seq, "monthcal today", TRUE);
1014 }
1015
1016 static void test_monthcal_scroll(HWND hwnd)
1017 {
1018     int res;
1019
1020     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1021
1022     /* Setter and Getters for scroll rate */
1023     res = SendMessage(hwnd, MCM_SETMONTHDELTA, 2, 0);
1024     expect(0, res);
1025
1026     res = SendMessage(hwnd, MCM_SETMONTHDELTA, 3, 0);
1027     expect(2, res);
1028     res = SendMessage(hwnd, MCM_GETMONTHDELTA, 0, 0);
1029     expect(3, res);
1030
1031     res = SendMessage(hwnd, MCM_SETMONTHDELTA, 12, 0);
1032     expect(3, res);
1033     res = SendMessage(hwnd, MCM_GETMONTHDELTA, 0, 0);
1034     expect(12, res);
1035
1036     res = SendMessage(hwnd, MCM_SETMONTHDELTA, 15, 0);
1037     expect(12, res);
1038     res = SendMessage(hwnd, MCM_GETMONTHDELTA, 0, 0);
1039     expect(15, res);
1040
1041     res = SendMessage(hwnd, MCM_SETMONTHDELTA, -5, 0);
1042     expect(15, res);
1043     res = SendMessage(hwnd, MCM_GETMONTHDELTA, 0, 0);
1044     expect(-5, res);
1045
1046     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_scroll_seq, "monthcal scroll", FALSE);
1047 }
1048
1049 static void test_monthcal_monthrange(HWND hwnd)
1050 {
1051     int res;
1052     SYSTEMTIME st_visible[2], st_daystate[2];
1053
1054     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1055     st_visible[0].wYear = 0;
1056     st_visible[0].wMonth = 0;
1057     st_visible[0].wDay = 0;
1058     st_daystate[1] = st_daystate[0] = st_visible[1] = st_visible[0];
1059
1060     res = SendMessage(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st_visible);
1061     todo_wine {
1062         expect(2, res);
1063         expect(2000, st_visible[0].wYear);
1064         expect(11, st_visible[0].wMonth);
1065         expect(1, st_visible[0].wDay);
1066         expect(2000, st_visible[1].wYear);
1067         expect(12, st_visible[1].wMonth);
1068         expect(31, st_visible[1].wDay);
1069     }
1070     res = SendMessage(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, (LPARAM)st_daystate);
1071     todo_wine {
1072         expect(4, res);
1073         expect(2000, st_daystate[0].wYear);
1074         expect(10, st_daystate[0].wMonth);
1075         expect(29, st_daystate[0].wDay);
1076         expect(2001, st_daystate[1].wYear);
1077         expect(1, st_daystate[1].wMonth);
1078         expect(6, st_daystate[1].wDay);
1079     }
1080
1081     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_monthrange_seq, "monthcal monthrange", FALSE);
1082 }
1083
1084 static void test_monthcal_MaxSelDay(HWND hwnd)
1085 {
1086     int res;
1087
1088     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1089
1090     /* Setter and Getters for max selected days */
1091     res = SendMessage(hwnd, MCM_SETMAXSELCOUNT, 5, 0);
1092     expect(1, res);
1093     res = SendMessage(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1094     expect(5, res);
1095
1096     res = SendMessage(hwnd, MCM_SETMAXSELCOUNT, 15, 0);
1097     expect(1, res);
1098     res = SendMessage(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1099     expect(15, res);
1100
1101     res = SendMessage(hwnd, MCM_SETMAXSELCOUNT, -1, 0);
1102     todo_wine {expect(0, res);}
1103     res = SendMessage(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
1104     todo_wine {expect(15, res);}
1105
1106     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_max_sel_day_seq, "monthcal MaxSelDay", FALSE);
1107 }
1108
1109
1110 START_TEST(monthcal)
1111 {
1112     HMODULE hComctl32;
1113     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
1114     INITCOMMONCONTROLSEX iccex;
1115     HWND hwnd, parent_wnd;
1116
1117     hComctl32 = GetModuleHandleA("comctl32.dll");
1118     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
1119     if (!pInitCommonControlsEx)
1120     {
1121         skip("InitCommonControlsEx() is missing. Skipping the tests\n");
1122         return;
1123     }
1124     iccex.dwSize = sizeof(iccex);
1125     iccex.dwICC  = ICC_DATE_CLASSES;
1126     pInitCommonControlsEx(&iccex);
1127
1128     test_monthcal();
1129
1130     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
1131
1132     parent_wnd = create_parent_window();
1133
1134     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1135     hwnd = create_monthcal_control(WS_CHILD | WS_BORDER | WS_VISIBLE, parent_wnd);
1136     assert(hwnd);
1137     ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_control_seq, "create monthcal control", TRUE);
1138
1139     SendMessage(hwnd, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
1140
1141     test_monthcal_color(hwnd);
1142     test_monthcal_currDate(hwnd);
1143     test_monthcal_firstDay(hwnd);
1144     test_monthcal_unicode(hwnd);
1145     test_monthcal_today(hwnd);
1146     test_monthcal_scroll(hwnd);
1147     test_monthcal_monthrange(hwnd);
1148     test_monthcal_HitTest(hwnd);
1149     test_monthcal_todaylink(hwnd);
1150
1151     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1152     DestroyWindow(hwnd);
1153     ok_sequence(sequences, PARENT_SEQ_INDEX, destroy_monthcal_parent_msgs_seq, "Destroy monthcal (parent msg)", FALSE);
1154     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_child_msgs_seq, "Destroy monthcal (child msg)", FALSE);
1155
1156     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1157     hwnd = create_monthcal_control(MCS_MULTISELECT, parent_wnd);
1158     assert(hwnd);
1159     ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_multi_sel_style_seq, "create monthcal (multi sel style)", TRUE);
1160
1161     test_monthcal_MaxSelDay(hwnd);
1162
1163     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1164     DestroyWindow(hwnd);
1165     ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_multi_sel_style_seq, "Destroy monthcal (multi sel style)", FALSE);
1166
1167     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1168     DestroyWindow(parent_wnd);
1169     ok_sequence(sequences, PARENT_SEQ_INDEX, destroy_parent_seq, "Destroy parent window", FALSE);
1170 }