ReactOS 0.4.15-dev-8058-ga7cbb60
monthcal.c
Go to the documentation of this file.
1/*
2 * Month calendar control
3 *
4 * Copyright 1998, 1999 Eric Kohl (ekohl@abo.rhein-zeitung.de)
5 * Copyright 1999 Alex Priem (alexp@sci.kun.nl)
6 * Copyright 1999 Chris Morgan <cmorgan@wpi.edu> and
7 * James Abbatiello <abbeyj@wpi.edu>
8 * Copyright 2000 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
9 * Copyright 2009-2011 Nikolay Sivov
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 *
25 * TODO:
26 * -- MCM_[GS]ETUNICODEFORMAT
27 * -- handle resources better (doesn't work now);
28 * -- take care of internationalization.
29 * -- keyboard handling.
30 * -- search for FIXME
31 */
32
33#include <math.h>
34#include <stdarg.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38
39#include "windef.h"
40#include "winbase.h"
41#include "wingdi.h"
42#include "winuser.h"
43#include "winnls.h"
44#include "commctrl.h"
45#include "comctl32.h"
46#include "uxtheme.h"
47#include "vssym32.h"
48#include "wine/unicode.h"
49#include "wine/debug.h"
50#include "wine/heap.h"
51
53
54/* FIXME: Inspect */
55#define MCS_NOSELCHANGEONNAV 0x0100
56
57#define MC_SEL_LBUTUP 1 /* Left button released */
58#define MC_SEL_LBUTDOWN 2 /* Left button pressed in calendar */
59#define MC_PREVPRESSED 4 /* Prev month button pressed */
60#define MC_NEXTPRESSED 8 /* Next month button pressed */
61#define MC_PREVNEXTMONTHDELAY 350 /* when continuously pressing `next/prev
62 month', wait 350 ms before going
63 to the next/prev month */
64#define MC_TODAYUPDATEDELAY 120000 /* time between today check for update (2 min) */
66#define MC_PREVNEXTMONTHTIMER 1 /* Timer IDs */
67#define MC_TODAYUPDATETIMER 2
68
69#define MC_CALENDAR_PADDING 6
71/* convert from days to 100 nanoseconds unit - used as FILETIME unit */
72#define DAYSTO100NSECS(days) (((ULONGLONG)(days))*24*60*60*10000000)
73
76 PenRed = 0,
79};
80
87};
89/* single calendar data */
90typedef struct _CALENDAR_INFO
92 RECT title; /* rect for the header above the calendar */
93 RECT titlemonth; /* the 'month name' text in the header */
94 RECT titleyear; /* the 'year number' text in the header */
95 RECT wdays; /* week days at top */
96 RECT days; /* calendar area */
97 RECT weeknums; /* week numbers at left side */
99 SYSTEMTIME month;/* contains calendar main month/year */
101
102typedef struct
104 HWND hwndSelf;
105 DWORD dwStyle; /* cached GWL_STYLE */
108 HBRUSH brushes[BrushLast];
109 HPEN pens[PenLast];
112 HFONT hBoldFont;
113 int textHeight;
114 int height_increment;
115 int width_increment;
116 INT delta; /* scroll rate; # of months that the */
117 /* control moves when user clicks a scroll button */
118 int firstDay; /* Start month calendar with firstDay's day,
119 stored in SYSTEMTIME format */
120 BOOL firstDaySet; /* first week day differs from locale defined */
121
122 BOOL isUnicode; /* value set with MCM_SETUNICODE format */
124 MONTHDAYSTATE *monthdayState;
125 SYSTEMTIME todaysDate;
126 BOOL todaySet; /* Today was forced with MCM_SETTODAY */
127 int status; /* See MC_SEL flags */
128 SYSTEMTIME firstSel; /* first selected day */
129 INT maxSelCount;
130 SYSTEMTIME minSel; /* contains single selection when used without MCS_MULTISELECT */
132 SYSTEMTIME focusedSel; /* date currently focused with mouse movement */
133 DWORD rangeValid;
134 SYSTEMTIME minDate;
135 SYSTEMTIME maxDate;
137 RECT titlebtnnext; /* the `next month' button in the header */
138 RECT titlebtnprev; /* the `prev month' button in the header */
139 RECT todayrect; /* `today: xx/xx/xx' text rect */
140 HWND hwndNotify; /* Window to receive the notifications */
141 HWND hWndYearEdit; /* Window Handle of edit box to handle years */
142 HWND hWndYearUpDown;/* Window Handle of updown box to handle years */
143 WNDPROC EditWndProc; /* original Edit window procedure */
145 CALENDAR_INFO *calendars;
146 SIZE dim; /* [cx,cy] - dimensions of calendars matrix, row/column count */
148
149static const WCHAR themeClass[] = { 'S','c','r','o','l','l','b','a','r',0 };
151/* empty SYSTEMTIME const */
152static const SYSTEMTIME st_null;
153/* valid date limits */
154static const SYSTEMTIME max_allowed_date = { /* wYear */ 9999, /* wMonth */ 12, /* wDayOfWeek */ 0, /* wDay */ 31 };
155static const SYSTEMTIME min_allowed_date = { /* wYear */ 1752, /* wMonth */ 9, /* wDayOfWeek */ 0, /* wDay */ 14 };
157/* Prev/Next buttons */
159{
162};
164/* helper functions */
165static inline INT MONTHCAL_GetCalCount(const MONTHCAL_INFO *infoPtr)
166{
167 return infoPtr->dim.cx * infoPtr->dim.cy;
168}
170/* send a single MCN_SELCHANGE notification */
171static inline void MONTHCAL_NotifySelectionChange(const MONTHCAL_INFO *infoPtr)
172{
173 NMSELCHANGE nmsc;
174
175 nmsc.nmhdr.hwndFrom = infoPtr->hwndSelf;
177 nmsc.nmhdr.code = MCN_SELCHANGE;
178 nmsc.stSelStart = infoPtr->minSel;
179 nmsc.stSelStart.wDayOfWeek = 0;
180 if(infoPtr->dwStyle & MCS_MULTISELECT){
181 nmsc.stSelEnd = infoPtr->maxSel;
182 nmsc.stSelEnd.wDayOfWeek = 0;
183 }
184 else
185 nmsc.stSelEnd = st_null;
186
187 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
188}
190/* send a single MCN_SELECT notification */
191static inline void MONTHCAL_NotifySelect(const MONTHCAL_INFO *infoPtr)
192{
193 NMSELCHANGE nmsc;
194
195 nmsc.nmhdr.hwndFrom = infoPtr->hwndSelf;
197 nmsc.nmhdr.code = MCN_SELECT;
198 nmsc.stSelStart = infoPtr->minSel;
199 nmsc.stSelStart.wDayOfWeek = 0;
200 if(infoPtr->dwStyle & MCS_MULTISELECT){
201 nmsc.stSelEnd = infoPtr->maxSel;
202 nmsc.stSelEnd.wDayOfWeek = 0;
203 }
204 else
205 nmsc.stSelEnd = st_null;
206
207 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
209
210static inline int MONTHCAL_MonthDiff(const SYSTEMTIME *left, const SYSTEMTIME *right)
211{
212 return (right->wYear - left->wYear)*12 + right->wMonth - left->wMonth;
213}
214
215/* returns the number of days in any given month, checking for leap days */
216/* January is 1, December is 12 */
217int MONTHCAL_MonthLength(int month, int year)
218{
219 const int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
220 /* Wrap around, this eases handling. Getting length only we shouldn't care
221 about year change here cause January and December have
222 the same day quantity */
223 if(month == 0)
224 month = 12;
225 else if(month == 13)
226 month = 1;
227
228 /* special case for calendar transition year */
229 if(month == min_allowed_date.wMonth && year == min_allowed_date.wYear) return 19;
230
231 /* if we have a leap year add 1 day to February */
232 /* a leap year is a year either divisible by 400 */
233 /* or divisible by 4 and not by 100 */
234 if(month == 2) { /* February */
235 return mdays[month - 1] + ((year%400 == 0) ? 1 : ((year%100 != 0) &&
236 (year%4 == 0)) ? 1 : 0);
237 }
238 else {
239 return mdays[month - 1];
240 }
241}
243/* compares timestamps using date part only */
244static inline BOOL MONTHCAL_IsDateEqual(const SYSTEMTIME *first, const SYSTEMTIME *second)
245{
246 return (first->wYear == second->wYear) && (first->wMonth == second->wMonth) &&
247 (first->wDay == second->wDay);
248}
250/* make sure that date fields are valid */
252{
253 if (time->wMonth < 1 || time->wMonth > 12 )
254 return FALSE;
255 if (time->wDay == 0 || time->wDay > MONTHCAL_MonthLength(time->wMonth, time->wYear))
256 return FALSE;
257
258 return TRUE;
259}
260
261/* Copies timestamp part only.
262 *
263 * PARAMETERS
264 *
265 * [I] from : source date
266 * [O] to : dest date
267 */
268static void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to)
269{
270 to->wHour = from->wHour;
271 to->wMinute = from->wMinute;
272 to->wSecond = from->wSecond;
273}
274
275/* Copies date part only.
276 *
277 * PARAMETERS
278 *
279 * [I] from : source date
280 * [O] to : dest date
281 */
282static void MONTHCAL_CopyDate(const SYSTEMTIME *from, SYSTEMTIME *to)
283{
284 to->wYear = from->wYear;
285 to->wMonth = from->wMonth;
286 to->wDay = from->wDay;
287 to->wDayOfWeek = from->wDayOfWeek;
288}
289
290/* Compares two dates in SYSTEMTIME format
291 *
292 * PARAMETERS
293 *
294 * [I] first : pointer to valid first date data to compare
295 * [I] second : pointer to valid second date data to compare
296 *
297 * RETURN VALUE
298 *
299 * -1 : first < second
300 * 0 : first == second
301 * 1 : first > second
302 *
303 * Note that no date validation performed, already validated values expected.
304 */
306{
307 FILETIME ft_first, ft_second;
308
309 SystemTimeToFileTime(first, &ft_first);
310 SystemTimeToFileTime(second, &ft_second);
311
312 return CompareFileTime(&ft_first, &ft_second);
314
315static LONG MONTHCAL_CompareMonths(const SYSTEMTIME *first, const SYSTEMTIME *second)
316{
317 SYSTEMTIME st_first, st_second;
318
319 st_first = st_second = st_null;
320 MONTHCAL_CopyDate(first, &st_first);
321 MONTHCAL_CopyDate(second, &st_second);
322 st_first.wDay = st_second.wDay = 1;
323
324 return MONTHCAL_CompareSystemTime(&st_first, &st_second);
326
327static LONG MONTHCAL_CompareDate(const SYSTEMTIME *first, const SYSTEMTIME *second)
328{
329 SYSTEMTIME st_first, st_second;
330
331 st_first = st_second = st_null;
332 MONTHCAL_CopyDate(first, &st_first);
333 MONTHCAL_CopyDate(second, &st_second);
334
335 return MONTHCAL_CompareSystemTime(&st_first, &st_second);
336}
337
338/* Checks largest possible date range and configured one
339 *
340 * PARAMETERS
341 *
342 * [I] infoPtr : valid pointer to control data
343 * [I] date : pointer to valid date data to check
344 * [I] fix : make date fit valid range
345 *
346 * RETURN VALUE
347 *
348 * TRUE - date within largest and configured range
349 * FALSE - date is outside largest or configured range
350 */
352 SYSTEMTIME *date, BOOL fix)
353{
354 const SYSTEMTIME *fix_st = NULL;
355
357 fix_st = &max_allowed_date;
358 }
360 fix_st = &min_allowed_date;
361 }
362 else {
363 if(infoPtr->rangeValid & GDTR_MAX) {
364 if((MONTHCAL_CompareSystemTime(date, &infoPtr->maxDate) == 1)) {
365 fix_st = &infoPtr->maxDate;
366 }
367 }
368
369 if(infoPtr->rangeValid & GDTR_MIN) {
370 if((MONTHCAL_CompareSystemTime(date, &infoPtr->minDate) == -1)) {
371 fix_st = &infoPtr->minDate;
372 }
373 }
374 }
375
376 if (fix && fix_st) {
377 date->wYear = fix_st->wYear;
378 date->wMonth = fix_st->wMonth;
379 }
380
381 return !fix_st;
382}
383
384/* Checks passed range width with configured maximum selection count
385 *
386 * PARAMETERS
387 *
388 * [I] infoPtr : valid pointer to control data
389 * [I] range0 : pointer to valid date data (requested bound)
390 * [I] range1 : pointer to valid date data (primary bound)
391 * [O] adjust : returns adjusted range bound to fit maximum range (optional)
392 *
393 * Adjust value computed basing on primary bound and current maximum selection
394 * count. For simple range check (without adjusted value required) (range0, range1)
395 * relation means nothing.
396 *
397 * RETURN VALUE
398 *
399 * TRUE - range is shorter or equal to maximum
400 * FALSE - range is larger than maximum
401 */
402static BOOL MONTHCAL_IsSelRangeValid(const MONTHCAL_INFO *infoPtr,
403 const SYSTEMTIME *range0,
404 const SYSTEMTIME *range1,
405 SYSTEMTIME *adjust)
406{
407 ULARGE_INTEGER ul_range0, ul_range1, ul_diff;
408 FILETIME ft_range0, ft_range1;
409 LONG cmp;
410
411 SystemTimeToFileTime(range0, &ft_range0);
412 SystemTimeToFileTime(range1, &ft_range1);
413
414 ul_range0.u.LowPart = ft_range0.dwLowDateTime;
415 ul_range0.u.HighPart = ft_range0.dwHighDateTime;
416 ul_range1.u.LowPart = ft_range1.dwLowDateTime;
417 ul_range1.u.HighPart = ft_range1.dwHighDateTime;
418
419 cmp = CompareFileTime(&ft_range0, &ft_range1);
420
421 if(cmp == 1)
422 ul_diff.QuadPart = ul_range0.QuadPart - ul_range1.QuadPart;
423 else
424 ul_diff.QuadPart = -ul_range0.QuadPart + ul_range1.QuadPart;
425
426 if(ul_diff.QuadPart >= DAYSTO100NSECS(infoPtr->maxSelCount)) {
427
428 if(adjust) {
429 if(cmp == 1)
430 ul_range0.QuadPart = ul_range1.QuadPart + DAYSTO100NSECS(infoPtr->maxSelCount - 1);
431 else
432 ul_range0.QuadPart = ul_range1.QuadPart - DAYSTO100NSECS(infoPtr->maxSelCount - 1);
433
434 ft_range0.dwLowDateTime = ul_range0.u.LowPart;
435 ft_range0.dwHighDateTime = ul_range0.u.HighPart;
436 FileTimeToSystemTime(&ft_range0, adjust);
437 }
438
439 return FALSE;
440 }
441 else return TRUE;
442}
443
444/* Used in MCM_SETRANGE/MCM_SETSELRANGE to determine resulting time part.
445 Milliseconds are intentionally not validated. */
447{
448 if((time->wHour > 24) || (time->wMinute > 59) || (time->wSecond > 59))
449 return FALSE;
450 else
451 return TRUE;
452}
453
454/* Note:Depending on DST, this may be offset by a day.
455 Need to find out if we're on a DST place & adjust the clock accordingly.
456 Above function assumes we have a valid data.
457 Valid for year>1752; 1 <= d <= 31, 1 <= m <= 12.
458 0 = Sunday.
459*/
460
461/* Returns the day in the week
462 *
463 * PARAMETERS
464 * [i] date : input date
465 * [I] inplace : set calculated value back to date structure
466 *
467 * RETURN VALUE
468 * day of week in SYSTEMTIME format: (0 == sunday,..., 6 == saturday)
469 */
471{
472 SYSTEMTIME st = st_null;
473 FILETIME ft;
474
476
477 SystemTimeToFileTime(&st, &ft);
478 FileTimeToSystemTime(&ft, &st);
479
480 if (inplace) date->wDayOfWeek = st.wDayOfWeek;
481
482 return st.wDayOfWeek;
483}
485/* add/subtract 'months' from date */
486static inline void MONTHCAL_GetMonth(SYSTEMTIME *date, INT months)
487{
488 INT length, m = date->wMonth + months;
489
490 date->wYear += m > 0 ? (m - 1) / 12 : m / 12 - 1;
491 date->wMonth = m > 0 ? (m - 1) % 12 + 1 : 12 + m % 12;
492 /* fix moving from last day in a month */
493 length = MONTHCAL_MonthLength(date->wMonth, date->wYear);
494 if(date->wDay > length) date->wDay = length;
496}
498/* properly updates date to point on next month */
499static inline void MONTHCAL_GetNextMonth(SYSTEMTIME *date)
500{
502}
504/* properly updates date to point on prev month */
505static inline void MONTHCAL_GetPrevMonth(SYSTEMTIME *date)
506{
508}
510/* Returns full date for a first currently visible day */
511static void MONTHCAL_GetMinDate(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date)
512{
513 /* zero indexed calendar has the earliest date */
514 SYSTEMTIME st_first = infoPtr->calendars[0].month;
515 INT firstDay;
516
517 st_first.wDay = 1;
518 firstDay = MONTHCAL_CalculateDayOfWeek(&st_first, FALSE);
519
520 *date = infoPtr->calendars[0].month;
522
523 date->wDay = MONTHCAL_MonthLength(date->wMonth, date->wYear) +
524 (infoPtr->firstDay - firstDay) % 7 + 1;
525
526 if(date->wDay > MONTHCAL_MonthLength(date->wMonth, date->wYear))
527 date->wDay -= 7;
528
529 /* fix day of week */
531}
533/* Returns full date for a last currently visible day */
534static void MONTHCAL_GetMaxDate(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date)
535{
536 /* the latest date is in latest calendar */
537 SYSTEMTIME st, *lt_month = &infoPtr->calendars[MONTHCAL_GetCalCount(infoPtr)-1].month;
538 INT first_day;
539
540 *date = *lt_month;
541 st = *lt_month;
542
543 /* day of week of first day of current month */
544 st.wDay = 1;
545 first_day = MONTHCAL_CalculateDayOfWeek(&st, FALSE);
546
549
550 /* last calendar starts with some date from previous month that not displayed */
552 (infoPtr->firstDay - first_day) % 7 + 1;
553 if (st.wDay > MONTHCAL_MonthLength(st.wMonth, st.wYear)) st.wDay -= 7;
554
555 /* Use month length to get max day. 42 means max day count in calendar area */
556 date->wDay = 42 - (MONTHCAL_MonthLength(st.wMonth, st.wYear) - st.wDay + 1) -
557 MONTHCAL_MonthLength(lt_month->wMonth, lt_month->wYear);
558
559 /* fix day of week */
561}
562
563/* From a given point calculate the row, column and day in the calendar,
564 'day == 0' means the last day of the last month. */
565static int MONTHCAL_GetDayFromPos(const MONTHCAL_INFO *infoPtr, POINT pt, INT calIdx)
566{
567 SYSTEMTIME st = infoPtr->calendars[calIdx].month;
568 int firstDay, col, row;
569 RECT client;
570
571 GetClientRect(infoPtr->hwndSelf, &client);
572
573 /* if the point is outside the x bounds of the window put it at the boundary */
574 if (pt.x > client.right) pt.x = client.right;
575
576 col = (pt.x - infoPtr->calendars[calIdx].days.left ) / infoPtr->width_increment;
577 row = (pt.y - infoPtr->calendars[calIdx].days.top ) / infoPtr->height_increment;
578
579 st.wDay = 1;
580 firstDay = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7;
581 return col + 7 * row - firstDay;
582}
583
584/* Get day position for given date and calendar
585 *
586 * PARAMETERS
587 *
588 * [I] infoPtr : pointer to control data
589 * [I] date : date value
590 * [O] col : day column (zero based)
591 * [O] row : week column (zero based)
592 * [I] calIdx : calendar index
593 */
594static void MONTHCAL_GetDayPos(const MONTHCAL_INFO *infoPtr, const SYSTEMTIME *date,
595 INT *col, INT *row, INT calIdx)
596{
597 SYSTEMTIME st = infoPtr->calendars[calIdx].month;
598 INT first;
599
600 st.wDay = 1;
601 first = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7;
602
603 if (calIdx == 0 || calIdx == MONTHCAL_GetCalCount(infoPtr)-1) {
604 const SYSTEMTIME *cal = &infoPtr->calendars[calIdx].month;
606
607 /* previous month */
608 if (cmp == -1) {
609 *col = (first - MONTHCAL_MonthLength(date->wMonth, cal->wYear) + date->wDay) % 7;
610 *row = 0;
611 return;
612 }
613
614 /* next month calculation is same as for current, just add current month length */
615 if (cmp == 1)
616 first += MONTHCAL_MonthLength(cal->wMonth, cal->wYear);
617 }
618
619 *col = (date->wDay + first) % 7;
620 *row = (date->wDay + first - *col) / 7;
621}
623/* returns bounding box for day in given position in given calendar */
624static inline void MONTHCAL_GetDayRectI(const MONTHCAL_INFO *infoPtr, RECT *r,
625 INT col, INT row, INT calIdx)
626{
627 r->left = infoPtr->calendars[calIdx].days.left + col * infoPtr->width_increment;
628 r->right = r->left + infoPtr->width_increment;
629 r->top = infoPtr->calendars[calIdx].days.top + row * infoPtr->height_increment;
630 r->bottom = r->top + infoPtr->textHeight;
631}
632
633/* Returns bounding box for given date
634 *
635 * NOTE: when calendar index is unknown pass -1
636 */
637static BOOL MONTHCAL_GetDayRect(const MONTHCAL_INFO *infoPtr, const SYSTEMTIME *date, RECT *r, INT calIdx)
638{
639 INT col, row;
640
642 {
644 return FALSE;
645 }
646
647 if (calIdx == -1)
648 {
650
651 if (cmp <= 0)
652 calIdx = 0;
653 else
654 {
656 if (cmp >= 0)
657 calIdx = MONTHCAL_GetCalCount(infoPtr)-1;
658 else
659 {
660 for (calIdx = 1; calIdx < MONTHCAL_GetCalCount(infoPtr)-1; calIdx++)
661 if (MONTHCAL_CompareMonths(date, &infoPtr->calendars[calIdx].month) == 0)
662 break;
663 }
664 }
665 }
666
667 MONTHCAL_GetDayPos(infoPtr, date, &col, &row, calIdx);
668 MONTHCAL_GetDayRectI(infoPtr, r, col, row, calIdx);
669
670 return TRUE;
671}
673static LRESULT
675{
676 INT range;
677
678 TRACE("flag=%d, st=%p\n", flag, st);
679
680 switch (flag) {
681 case GMR_VISIBLE:
682 {
683 if (st)
684 {
685 st[0] = infoPtr->calendars[0].month;
686 st[1] = infoPtr->calendars[MONTHCAL_GetCalCount(infoPtr)-1].month;
687
688 if (st[0].wMonth == min_allowed_date.wMonth &&
690 {
691 st[0].wDay = min_allowed_date.wDay;
692 }
693 else
694 st[0].wDay = 1;
696
697 st[1].wDay = MONTHCAL_MonthLength(st[1].wMonth, st[1].wYear);
699 }
700
701 range = MONTHCAL_GetCalCount(infoPtr);
702 break;
703 }
704 case GMR_DAYSTATE:
705 {
706 if (st)
707 {
708 MONTHCAL_GetMinDate(infoPtr, &st[0]);
709 MONTHCAL_GetMaxDate(infoPtr, &st[1]);
710 }
711 /* include two partially visible months */
712 range = MONTHCAL_GetCalCount(infoPtr) + 2;
713 break;
714 }
715 default:
716 WARN("Unknown flag value, got %d\n", flag);
717 range = 0;
718 }
719
720 return range;
721}
722
723/* Focused day helper:
724
725 - set focused date to given value;
726 - reset to zero value if NULL passed;
727 - invalidate previous and new day rectangle only if needed.
728
729 Returns TRUE if focused day changed, FALSE otherwise.
730*/
731static BOOL MONTHCAL_SetDayFocus(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *st)
732{
733 RECT r;
734
735 if(st)
736 {
737 /* there's nothing to do if it's the same date,
738 mouse move within same date rectangle case */
739 if(MONTHCAL_IsDateEqual(&infoPtr->focusedSel, st)) return FALSE;
740
741 /* invalidate old focused day */
742 if (MONTHCAL_GetDayRect(infoPtr, &infoPtr->focusedSel, &r, -1))
743 InvalidateRect(infoPtr->hwndSelf, &r, FALSE);
744
745 infoPtr->focusedSel = *st;
746 }
747
748 /* On set invalidates new day, on reset clears previous focused day. */
749 if (MONTHCAL_GetDayRect(infoPtr, &infoPtr->focusedSel, &r, -1))
750 InvalidateRect(infoPtr->hwndSelf, &r, FALSE);
751
752 if(!st && MONTHCAL_ValidateDate(&infoPtr->focusedSel))
753 infoPtr->focusedSel = st_null;
754
755 return TRUE;
756}
758/* draw today boundary box for specified rectangle */
759static void MONTHCAL_Circle(const MONTHCAL_INFO *infoPtr, HDC hdc, const RECT *r)
760{
761 HPEN old_pen = SelectObject(hdc, infoPtr->pens[PenRed]);
762 HBRUSH old_brush;
763
765 Rectangle(hdc, r->left, r->top, r->right, r->bottom);
766
767 SelectObject(hdc, old_brush);
768 SelectObject(hdc, old_pen);
769}
770
771/* Draw today day mark rectangle
772 *
773 * [I] hdc : context to draw in
774 * [I] date : day to mark with rectangle
776 */
777static void MONTHCAL_CircleDay(const MONTHCAL_INFO *infoPtr, HDC hdc,
778 const SYSTEMTIME *date)
779{
780 RECT r;
781
782 MONTHCAL_GetDayRect(infoPtr, date, &r, -1);
783 MONTHCAL_Circle(infoPtr, hdc, &r);
785
786static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEMTIME *st,
787 int bold, const PAINTSTRUCT *ps)
788{
789 static const WCHAR fmtW[] = { '%','d',0 };
790 WCHAR buf[10];
791 RECT r, r_temp;
792 COLORREF oldCol = 0;
793 COLORREF oldBk = 0;
794 INT old_bkmode, selection;
795
796 /* no need to check styles: when selection is not valid, it is set to zero.
797 1 < day < 31, so everything is OK */
798 MONTHCAL_GetDayRect(infoPtr, st, &r, -1);
799 if(!IntersectRect(&r_temp, &(ps->rcPaint), &r)) return;
800
801 if ((MONTHCAL_CompareDate(st, &infoPtr->minSel) >= 0) &&
802 (MONTHCAL_CompareDate(st, &infoPtr->maxSel) <= 0))
803 {
804 TRACE("%d %d %d\n", st->wDay, infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
805 TRACE("%s\n", wine_dbgstr_rect(&r));
806 oldCol = SetTextColor(hdc, infoPtr->colors[MCSC_MONTHBK]);
807 oldBk = SetBkColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]);
808 FillRect(hdc, &r, infoPtr->brushes[BrushTitle]);
809
810 selection = 1;
811 }
812 else
813 selection = 0;
814
815 SelectObject(hdc, bold ? infoPtr->hBoldFont : infoPtr->hFont);
816
817 old_bkmode = SetBkMode(hdc, TRANSPARENT);
818 wsprintfW(buf, fmtW, st->wDay);
820 SetBkMode(hdc, old_bkmode);
821
822 if (selection)
823 {
824 SetTextColor(hdc, oldCol);
825 SetBkColor(hdc, oldBk);
826 }
828
830{
831 HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
832 RECT *r = button == DIRECTION_FORWARD ? &infoPtr->titlebtnnext : &infoPtr->titlebtnprev;
833 BOOL pressed = button == DIRECTION_FORWARD ? infoPtr->status & MC_NEXTPRESSED :
834 infoPtr->status & MC_PREVPRESSED;
835 if (theme)
836 {
837 static const int states[] = {
838 /* Prev button */
840 /* Next button */
842 };
843 int stateNum = button == DIRECTION_FORWARD ? 3 : 0;
844 if (pressed)
845 stateNum += 1;
846 else
847 {
848 if (infoPtr->dwStyle & WS_DISABLED) stateNum += 2;
849 }
850 DrawThemeBackground (theme, hdc, SBP_ARROWBTN, states[stateNum], r, NULL);
851 }
852 else
853 {
855 if (pressed)
857 else
858 {
859 if (infoPtr->dwStyle & WS_DISABLED) style |= DFCS_INACTIVE;
860 }
861
863 }
864}
866/* paint a title with buttons and month/year string */
867static void MONTHCAL_PaintTitle(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
868{
869 static const WCHAR mmmmW[] = {'M','M','M','M',0};
870 static const WCHAR mmmW[] = {'M','M','M',0};
871 static const WCHAR mmW[] = {'M','M',0};
872 static const WCHAR fmtyearW[] = {'%','l','d',0};
873 static const WCHAR fmtmmW[] = {'%','0','2','d',0};
874 static const WCHAR fmtmW[] = {'%','d',0};
875 RECT *title = &infoPtr->calendars[calIdx].title;
876 const SYSTEMTIME *st = &infoPtr->calendars[calIdx].month;
877 WCHAR monthW[80], strW[80], fmtW[80], yearW[6] /* valid year range is 1601-30827 */;
878 int yearoffset, monthoffset, shiftX;
879 SIZE sz;
880
881 /* fill header box */
882 FillRect(hdc, title, infoPtr->brushes[BrushTitle]);
883
884 /* month/year string */
885 SetBkColor(hdc, infoPtr->colors[MCSC_TITLEBK]);
887 SelectObject(hdc, infoPtr->hBoldFont);
888
889 /* draw formatted date string */
892
893 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SYEARMONTH, fmtW, ARRAY_SIZE(fmtW));
894 wsprintfW(yearW, fmtyearW, st->wYear);
895
896 /* month is trickier as it's possible to have different format pictures, we'll
897 test for M, MM, MMM, and MMMM */
898 if (strstrW(fmtW, mmmmW))
900 else if (strstrW(fmtW, mmmW))
902 else if (strstrW(fmtW, mmW))
903 wsprintfW(monthW, fmtmmW, st->wMonth);
904 else
905 wsprintfW(monthW, fmtmW, st->wMonth);
906
907 /* update hit boxes */
908 yearoffset = 0;
909 while (strW[yearoffset])
910 {
911 if (!strncmpW(&strW[yearoffset], yearW, strlenW(yearW)))
912 break;
913 yearoffset++;
914 }
915
916 monthoffset = 0;
917 while (strW[monthoffset])
918 {
919 if (!strncmpW(&strW[monthoffset], monthW, strlenW(monthW)))
920 break;
921 monthoffset++;
922 }
923
924 /* for left limits use offsets */
925 sz.cx = 0;
926 if (yearoffset)
927 GetTextExtentPoint32W(hdc, strW, yearoffset, &sz);
928 infoPtr->calendars[calIdx].titleyear.left = sz.cx;
929
930 sz.cx = 0;
931 if (monthoffset)
932 GetTextExtentPoint32W(hdc, strW, monthoffset, &sz);
933 infoPtr->calendars[calIdx].titlemonth.left = sz.cx;
934
935 /* for right limits use actual string parts lengths */
936 GetTextExtentPoint32W(hdc, &strW[yearoffset], strlenW(yearW), &sz);
937 infoPtr->calendars[calIdx].titleyear.right = infoPtr->calendars[calIdx].titleyear.left + sz.cx;
938
939 GetTextExtentPoint32W(hdc, monthW, strlenW(monthW), &sz);
940 infoPtr->calendars[calIdx].titlemonth.right = infoPtr->calendars[calIdx].titlemonth.left + sz.cx;
941
942 /* Finally translate rectangles to match center aligned string,
943 hit rectangles are relative to title rectangle before translation. */
945 shiftX = (title->right - title->left - sz.cx) / 2 + title->left;
946 OffsetRect(&infoPtr->calendars[calIdx].titleyear, shiftX, 0);
947 OffsetRect(&infoPtr->calendars[calIdx].titlemonth, shiftX, 0);
949
950static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
951{
952 const SYSTEMTIME *date = &infoPtr->calendars[calIdx].month;
953 static const WCHAR fmt_weekW[] = { '%','d',0 };
954 INT mindays, weeknum, weeknum1, startofprescal;
955 INT i, prev_month;
956 SYSTEMTIME st;
957 WCHAR buf[80];
958 HPEN old_pen;
959 RECT r;
960
961 if (!(infoPtr->dwStyle & MCS_WEEKNUMBERS)) return;
962
963 MONTHCAL_GetMinDate(infoPtr, &st);
964 startofprescal = st.wDay;
965 st = *date;
966
967 prev_month = date->wMonth - 1;
968 if(prev_month == 0) prev_month = 12;
969
970 /*
971 Rules what week to call the first week of a new year:
972 LOCALE_IFIRSTWEEKOFYEAR == 0 (e.g US?):
973 The week containing Jan 1 is the first week of year
974 LOCALE_IFIRSTWEEKOFYEAR == 2 (e.g. Germany):
975 First week of year must contain 4 days of the new year
976 LOCALE_IFIRSTWEEKOFYEAR == 1 (what countries?)
977 The first week of the year must contain only days of the new year
978 */
980 weeknum = atoiW(buf);
981 switch (weeknum)
982 {
983 case 1: mindays = 6;
984 break;
985 case 2: mindays = 3;
986 break;
987 case 0: mindays = 0;
988 break;
989 default:
990 WARN("Unknown LOCALE_IFIRSTWEEKOFYEAR value %d, defaulting to 0\n", weeknum);
991 mindays = 0;
992 }
993
994 if (date->wMonth == 1)
995 {
996 /* calculate all those exceptions for January */
997 st.wDay = st.wMonth = 1;
998 weeknum1 = MONTHCAL_CalculateDayOfWeek(&st, FALSE);
999 if ((infoPtr->firstDay - weeknum1) % 7 > mindays)
1000 weeknum = 1;
1001 else
1002 {
1003 weeknum = 0;
1004 for(i = 0; i < 11; i++)
1005 weeknum += MONTHCAL_MonthLength(i+1, date->wYear - 1);
1006
1007 weeknum += startofprescal + 7;
1008 weeknum /= 7;
1009 st.wYear -= 1;
1010 weeknum1 = MONTHCAL_CalculateDayOfWeek(&st, FALSE);
1011 if ((infoPtr->firstDay - weeknum1) % 7 > mindays) weeknum++;
1012 }
1013 }
1014 else
1015 {
1016 weeknum = 0;
1017 for(i = 0; i < prev_month - 1; i++)
1018 weeknum += MONTHCAL_MonthLength(i+1, date->wYear);
1019
1020 weeknum += startofprescal + 7;
1021 weeknum /= 7;
1022 st.wDay = st.wMonth = 1;
1023 weeknum1 = MONTHCAL_CalculateDayOfWeek(&st, FALSE);
1024 if ((infoPtr->firstDay - weeknum1) % 7 > mindays) weeknum++;
1025 }
1026
1027 r = infoPtr->calendars[calIdx].weeknums;
1028
1029 /* erase whole week numbers area */
1030 FillRect(hdc, &r, infoPtr->brushes[BrushMonth]);
1031 SetTextColor(hdc, infoPtr->colors[MCSC_TITLEBK]);
1032
1033 /* reduce rectangle to one week number */
1034 r.bottom = r.top + infoPtr->height_increment;
1035
1036 for(i = 0; i < 6; i++) {
1037 if((i == 0) && (weeknum > 50))
1038 {
1039 wsprintfW(buf, fmt_weekW, weeknum);
1040 weeknum = 0;
1041 }
1042 else if((i == 5) && (weeknum > 47))
1043 {
1044 wsprintfW(buf, fmt_weekW, 1);
1045 }
1046 else
1047 wsprintfW(buf, fmt_weekW, weeknum + i);
1048
1050 OffsetRect(&r, 0, infoPtr->height_increment);
1051 }
1052
1053 /* line separator for week numbers column */
1054 old_pen = SelectObject(hdc, infoPtr->pens[PenText]);
1055 MoveToEx(hdc, infoPtr->calendars[calIdx].weeknums.right, infoPtr->calendars[calIdx].weeknums.top + 3 , NULL);
1056 LineTo(hdc, infoPtr->calendars[calIdx].weeknums.right, infoPtr->calendars[calIdx].weeknums.bottom);
1057 SelectObject(hdc, old_pen);
1058}
1060/* bottom today date */
1061static void MONTHCAL_PaintTodayTitle(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
1062{
1063 static const WCHAR fmt_todayW[] = { '%','s',' ','%','s',0 };
1064 WCHAR buf_todayW[30], buf_dateW[20], buf[80];
1065 RECT text_rect, box_rect;
1066 HFONT old_font;
1067 INT col;
1068
1069 if(infoPtr->dwStyle & MCS_NOTODAY) return;
1070
1071 LoadStringW(COMCTL32_hModule, IDM_TODAY, buf_todayW, ARRAY_SIZE(buf_todayW));
1072 col = infoPtr->dwStyle & MCS_NOTODAYCIRCLE ? 0 : 1;
1073 if (infoPtr->dwStyle & MCS_WEEKNUMBERS) col--;
1074 /* label is located below first calendar last row */
1075 MONTHCAL_GetDayRectI(infoPtr, &text_rect, col, 6, infoPtr->dim.cx * infoPtr->dim.cy - infoPtr->dim.cx);
1076 box_rect = text_rect;
1077
1078 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &infoPtr->todaysDate, NULL, buf_dateW, ARRAY_SIZE(buf_dateW));
1079 old_font = SelectObject(hdc, infoPtr->hBoldFont);
1080 SetTextColor(hdc, infoPtr->colors[MCSC_TEXT]);
1081
1082 wsprintfW(buf, fmt_todayW, buf_todayW, buf_dateW);
1085
1086 if(!(infoPtr->dwStyle & MCS_NOTODAYCIRCLE)) {
1087 OffsetRect(&box_rect, -infoPtr->width_increment, 0);
1088 MONTHCAL_Circle(infoPtr, hdc, &box_rect);
1089 }
1090
1091 SelectObject(hdc, old_font);
1092}
1094/* today mark + focus */
1095static void MONTHCAL_PaintFocusAndCircle(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
1096{
1097 /* circle today date if only it's in fully visible month */
1098 if (!(infoPtr->dwStyle & MCS_NOTODAYCIRCLE))
1099 {
1100 INT i;
1101
1102 for (i = 0; i < MONTHCAL_GetCalCount(infoPtr); i++)
1103 if (!MONTHCAL_CompareMonths(&infoPtr->todaysDate, &infoPtr->calendars[i].month))
1104 {
1105 MONTHCAL_CircleDay(infoPtr, hdc, &infoPtr->todaysDate);
1106 break;
1107 }
1108 }
1109
1110 if (!MONTHCAL_IsDateEqual(&infoPtr->focusedSel, &st_null))
1111 {
1112 RECT r;
1113 MONTHCAL_GetDayRect(infoPtr, &infoPtr->focusedSel, &r, -1);
1114 DrawFocusRect(hdc, &r);
1115 }
1116}
1118/* months before first calendar month and after last calendar month */
1119static void MONTHCAL_PaintLeadTrailMonths(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
1120{
1121 INT mask, index;
1122 UINT length;
1123 SYSTEMTIME st_max, st;
1124
1125 if (infoPtr->dwStyle & MCS_NOTRAILINGDATES) return;
1126
1128
1129 /* draw prev month */
1130 MONTHCAL_GetMinDate(infoPtr, &st);
1131 mask = 1 << (st.wDay-1);
1132 /* December and January both 31 days long, so no worries if wrapped */
1134 infoPtr->calendars[0].month.wYear);
1135 index = 0;
1136 while(st.wDay <= length)
1137 {
1138 MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[index] & mask, ps);
1139 mask <<= 1;
1140 st.wDay++;
1141 }
1142
1143 /* draw next month */
1144 st = infoPtr->calendars[MONTHCAL_GetCalCount(infoPtr)-1].month;
1145 st.wDay = 1;
1147 MONTHCAL_GetMaxDate(infoPtr, &st_max);
1148 mask = 1;
1149 index = MONTHCAL_GetMonthRange(infoPtr, GMR_DAYSTATE, 0)-1;
1150 while(st.wDay <= st_max.wDay)
1151 {
1152 MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[index] & mask, ps);
1153 mask <<= 1;
1154 st.wDay++;
1155 }
1157
1158static int get_localized_dayname(const MONTHCAL_INFO *infoPtr, unsigned int day, WCHAR *buff, unsigned int count)
1159{
1160 LCTYPE lctype;
1161
1162 if (infoPtr->dwStyle & MCS_SHORTDAYSOFWEEK)
1163 lctype = LOCALE_SSHORTESTDAYNAME1 + day;
1164 else
1165 lctype = LOCALE_SABBREVDAYNAME1 + day;
1166
1167 return GetLocaleInfoW(LOCALE_USER_DEFAULT, lctype, buff, count);
1168}
1170/* paint a calendar area */
1171static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
1172{
1173 const SYSTEMTIME *date = &infoPtr->calendars[calIdx].month;
1174 INT i, j;
1175 UINT length;
1176 RECT r, fill_bk_rect;
1177 SYSTEMTIME st;
1178 WCHAR buf[80];
1179 HPEN old_pen;
1180 int mask;
1181
1182 /* fill whole days area - from week days area to today note rectangle */
1183 fill_bk_rect = infoPtr->calendars[calIdx].wdays;
1184 fill_bk_rect.bottom = infoPtr->calendars[calIdx].days.bottom +
1185 (infoPtr->todayrect.bottom - infoPtr->todayrect.top);
1186
1187 FillRect(hdc, &fill_bk_rect, infoPtr->brushes[BrushMonth]);
1188
1189 /* draw line under day abbreviations */
1190 old_pen = SelectObject(hdc, infoPtr->pens[PenText]);
1191 MoveToEx(hdc, infoPtr->calendars[calIdx].days.left + 3,
1192 infoPtr->calendars[calIdx].title.bottom + infoPtr->textHeight + 1, NULL);
1193 LineTo(hdc, infoPtr->calendars[calIdx].days.right - 3,
1194 infoPtr->calendars[calIdx].title.bottom + infoPtr->textHeight + 1);
1195 SelectObject(hdc, old_pen);
1196
1197 infoPtr->calendars[calIdx].wdays.left = infoPtr->calendars[calIdx].days.left =
1198 infoPtr->calendars[calIdx].weeknums.right;
1199
1200 /* draw day abbreviations */
1201 SelectObject(hdc, infoPtr->hFont);
1202 SetBkColor(hdc, infoPtr->colors[MCSC_MONTHBK]);
1203 SetTextColor(hdc, infoPtr->colors[MCSC_TITLEBK]);
1204 /* rectangle to draw a single day abbreviation within */
1205 r = infoPtr->calendars[calIdx].wdays;
1206 r.right = r.left + infoPtr->width_increment;
1207
1208 i = infoPtr->firstDay;
1209 for(j = 0; j < 7; j++) {
1210 get_localized_dayname(infoPtr, (i + j + 6) % 7, buf, ARRAY_SIZE(buf));
1212 OffsetRect(&r, infoPtr->width_increment, 0);
1213 }
1214
1215 /* draw current month */
1216 SetTextColor(hdc, infoPtr->colors[MCSC_TEXT]);
1217 st = *date;
1218 st.wDay = 1;
1219 mask = 1;
1220 length = MONTHCAL_MonthLength(date->wMonth, date->wYear);
1221 while(st.wDay <= length)
1222 {
1223 MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[calIdx+1] & mask, ps);
1224 mask <<= 1;
1225 st.wDay++;
1226 }
1228
1229static void MONTHCAL_Refresh(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
1230{
1231 COLORREF old_text_clr, old_bk_clr;
1232 HFONT old_font;
1233 INT i;
1234
1236 old_bk_clr = GetBkColor(hdc);
1237 old_font = GetCurrentObject(hdc, OBJ_FONT);
1238
1239 for (i = 0; i < MONTHCAL_GetCalCount(infoPtr); i++)
1240 {
1241 RECT *title = &infoPtr->calendars[i].title;
1242 RECT r;
1243
1244 /* draw title, redraw all its elements */
1245 if (IntersectRect(&r, &(ps->rcPaint), title))
1246 MONTHCAL_PaintTitle(infoPtr, hdc, ps, i);
1247
1248 /* draw calendar area */
1249 UnionRect(&r, &infoPtr->calendars[i].wdays, &infoPtr->todayrect);
1250 if (IntersectRect(&r, &(ps->rcPaint), &r))
1251 MONTHCAL_PaintCalendar(infoPtr, hdc, ps, i);
1252
1253 /* week numbers */
1254 MONTHCAL_PaintWeeknumbers(infoPtr, hdc, ps, i);
1255 }
1256
1257 /* partially visible months */
1258 MONTHCAL_PaintLeadTrailMonths(infoPtr, hdc, ps);
1259
1260 /* focus and today rectangle */
1261 MONTHCAL_PaintFocusAndCircle(infoPtr, hdc, ps);
1262
1263 /* today at the bottom left */
1264 MONTHCAL_PaintTodayTitle(infoPtr, hdc, ps);
1265
1266 /* navigation buttons */
1269
1270 /* restore context */
1271 SetBkColor(hdc, old_bk_clr);
1272 SelectObject(hdc, old_font);
1273 SetTextColor(hdc, old_text_clr);
1274}
1276static LRESULT
1278{
1279 TRACE("rect %p\n", rect);
1280
1281 if(!rect) return FALSE;
1282
1283 *rect = infoPtr->calendars[0].title;
1284 rect->bottom = infoPtr->calendars[0].days.bottom + infoPtr->todayrect.bottom -
1285 infoPtr->todayrect.top;
1286
1287 AdjustWindowRect(rect, infoPtr->dwStyle, FALSE);
1288
1289 /* minimal rectangle is zero based */
1290 OffsetRect(rect, -rect->left, -rect->top);
1291
1292 TRACE("%s\n", wine_dbgstr_rect(rect));
1293
1294 return TRUE;
1295}
1297static COLORREF
1299{
1300 TRACE("%p, %d\n", infoPtr, index);
1301
1302 if (index > MCSC_TRAILINGTEXT) return -1;
1303 return infoPtr->colors[index];
1304}
1306static LRESULT
1308{
1309 enum CachedBrush type;
1310 COLORREF prev;
1311
1312 TRACE("%p, %d: color %08x\n", infoPtr, index, color);
1313
1314 if (index > MCSC_TRAILINGTEXT) return -1;
1315
1316 prev = infoPtr->colors[index];
1317 infoPtr->colors[index] = color;
1318
1319 /* update cached brush */
1320 switch (index)
1321 {
1322 case MCSC_BACKGROUND:
1324 break;
1325 case MCSC_TITLEBK:
1326 type = BrushTitle;
1327 break;
1328 case MCSC_MONTHBK:
1329 type = BrushMonth;
1330 break;
1331 default:
1332 type = BrushLast;
1333 }
1334
1335 if (type != BrushLast)
1336 {
1337 DeleteObject(infoPtr->brushes[type]);
1338 infoPtr->brushes[type] = CreateSolidBrush(color);
1339 }
1340
1341 /* update cached pen */
1342 if (index == MCSC_TEXT)
1343 {
1344 DeleteObject(infoPtr->pens[PenText]);
1345 infoPtr->pens[PenText] = CreatePen(PS_SOLID, 1, infoPtr->colors[index]);
1346 }
1347
1349 return prev;
1350}
1352static LRESULT
1354{
1355 TRACE("\n");
1356
1357 if(infoPtr->delta)
1358 return infoPtr->delta;
1359
1360 return MONTHCAL_GetMonthRange(infoPtr, GMR_VISIBLE, NULL);
1361}
1362
1364static LRESULT
1366{
1367 INT prev = infoPtr->delta;
1368
1369 TRACE("delta %d\n", delta);
1370
1371 infoPtr->delta = delta;
1372 return prev;
1373}
1374
1376static inline LRESULT
1378{
1379 int day;
1380
1381 /* convert from SYSTEMTIME to locale format */
1382 day = (infoPtr->firstDay >= 0) ? (infoPtr->firstDay+6)%7 : infoPtr->firstDay;
1383
1384 return MAKELONG(day, infoPtr->firstDaySet);
1385}
1386
1387
1388/* Sets the first day of the week that will appear in the control
1389 *
1390 *
1391 * PARAMETERS:
1392 * [I] infoPtr : valid pointer to control data
1393 * [I] day : day number to set as new first day (0 == Monday,...,6 == Sunday)
1394 *
1395 *
1396 * RETURN VALUE:
1397 * Low word contains previous first day,
1398 * high word indicates was first day forced with this message before or is
1399 * locale defined (TRUE - was forced, FALSE - wasn't).
1400 *
1401 * FIXME: this needs to be implemented properly in MONTHCAL_Refresh()
1402 * FIXME: we need more error checking here
1404static LRESULT
1406{
1407 LRESULT prev = MONTHCAL_GetFirstDayOfWeek(infoPtr);
1408 int new_day;
1409
1410 TRACE("%d\n", day);
1411
1412 if(day == -1)
1413 {
1414 WCHAR buf[80];
1415
1417 TRACE("%s %d\n", debugstr_w(buf), strlenW(buf));
1418
1419 new_day = atoiW(buf);
1420
1421 infoPtr->firstDaySet = FALSE;
1422 }
1423 else if(day >= 7)
1424 {
1425 new_day = 6; /* max first day allowed */
1426 infoPtr->firstDaySet = TRUE;
1427 }
1428 else
1429 {
1430 /* Native behaviour for that case is broken: invalid date number >31
1431 got displayed at (0,0) position, current month starts always from
1432 (1,0) position. Should be implemented here as well only if there's
1433 nothing else to do. */
1434 if (day < -1)
1435 FIXME("No bug compatibility for day=%d\n", day);
1436
1437 new_day = day;
1438 infoPtr->firstDaySet = TRUE;
1439 }
1440
1441 /* convert from locale to SYSTEMTIME format */
1442 infoPtr->firstDay = (new_day >= 0) ? (++new_day) % 7 : new_day;
1443
1444 InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
1445
1446 return prev;
1447}
1449static LRESULT
1451{
1452 return(infoPtr->todayrect.right - infoPtr->todayrect.left);
1453}
1455static LRESULT
1457{
1458 FILETIME ft_min, ft_max;
1459
1460 TRACE("%x %p\n", limits, range);
1461
1462 if ((limits & GDTR_MIN && !MONTHCAL_ValidateDate(&range[0])) ||
1463 (limits & GDTR_MAX && !MONTHCAL_ValidateDate(&range[1])))
1464 return FALSE;
1465
1466 infoPtr->rangeValid = 0;
1467 infoPtr->minDate = infoPtr->maxDate = st_null;
1468
1469 if (limits & GDTR_MIN)
1470 {
1471 if (!MONTHCAL_ValidateTime(&range[0]))
1472 MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[0]);
1473
1474 infoPtr->minDate = range[0];
1475 infoPtr->rangeValid |= GDTR_MIN;
1476 }
1477 if (limits & GDTR_MAX)
1478 {
1479 if (!MONTHCAL_ValidateTime(&range[1]))
1480 MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[1]);
1481
1482 infoPtr->maxDate = range[1];
1483 infoPtr->rangeValid |= GDTR_MAX;
1484 }
1485
1486 /* Only one limit set - we are done */
1487 if ((infoPtr->rangeValid & (GDTR_MIN | GDTR_MAX)) != (GDTR_MIN | GDTR_MAX))
1488 return TRUE;
1489
1490 SystemTimeToFileTime(&infoPtr->maxDate, &ft_max);
1491 SystemTimeToFileTime(&infoPtr->minDate, &ft_min);
1492
1493 if (CompareFileTime(&ft_min, &ft_max) >= 0)
1494 {
1495 if ((limits & (GDTR_MIN | GDTR_MAX)) == (GDTR_MIN | GDTR_MAX))
1496 {
1497 /* Native swaps limits only when both limits are being set. */
1498 SYSTEMTIME st_tmp = infoPtr->minDate;
1499 infoPtr->minDate = infoPtr->maxDate;
1500 infoPtr->maxDate = st_tmp;
1501 }
1502 else
1503 {
1504 /* reset the other limit */
1505 if (limits & GDTR_MIN) infoPtr->maxDate = st_null;
1506 if (limits & GDTR_MAX) infoPtr->minDate = st_null;
1507 infoPtr->rangeValid &= limits & GDTR_MIN ? ~GDTR_MAX : ~GDTR_MIN;
1508 }
1509 }
1510
1511 return TRUE;
1512}
1513
1515static LRESULT
1517{
1518 TRACE("%p\n", range);
1519
1520 if (!range) return 0;
1521
1522 range[1] = infoPtr->maxDate;
1523 range[0] = infoPtr->minDate;
1524
1525 return infoPtr->rangeValid;
1526}
1527
1529static LRESULT
1530MONTHCAL_SetDayState(const MONTHCAL_INFO *infoPtr, INT months, MONTHDAYSTATE *states)
1531{
1532 TRACE("%p %d %p\n", infoPtr, months, states);
1533
1534 if (!(infoPtr->dwStyle & MCS_DAYSTATE)) return 0;
1535 if (months != MONTHCAL_GetMonthRange(infoPtr, GMR_DAYSTATE, 0)) return 0;
1536
1537 memcpy(infoPtr->monthdayState, states, months*sizeof(MONTHDAYSTATE));
1538
1539 return 1;
1540}
1542static LRESULT
1543MONTHCAL_GetCurSel(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
1544{
1545 TRACE("%p\n", curSel);
1546 if(!curSel) return FALSE;
1547 if(infoPtr->dwStyle & MCS_MULTISELECT) return FALSE;
1548
1549 *curSel = infoPtr->minSel;
1550 TRACE("%d/%d/%d\n", curSel->wYear, curSel->wMonth, curSel->wDay);
1551 return TRUE;
1552}
1554static LRESULT
1556{
1557 SYSTEMTIME prev = infoPtr->minSel, selection;
1558 INT diff;
1559 WORD day;
1560
1561 TRACE("%p\n", curSel);
1562 if(!curSel) return FALSE;
1563 if(infoPtr->dwStyle & MCS_MULTISELECT) return FALSE;
1564
1565 if(!MONTHCAL_ValidateDate(curSel)) return FALSE;
1566 /* exit earlier if selection equals current */
1567 if (MONTHCAL_IsDateEqual(&infoPtr->minSel, curSel)) return TRUE;
1568
1569 selection = *curSel;
1570 selection.wHour = selection.wMinute = selection.wSecond = selection.wMilliseconds = 0;
1572
1573 if(!MONTHCAL_IsDateInValidRange(infoPtr, &selection, FALSE)) return FALSE;
1574
1575 /* scroll calendars only if we have to */
1576 diff = MONTHCAL_MonthDiff(&infoPtr->calendars[MONTHCAL_GetCalCount(infoPtr)-1].month, curSel);
1577 if (diff <= 0)
1578 {
1579 diff = MONTHCAL_MonthDiff(&infoPtr->calendars[0].month, curSel);
1580 if (diff > 0) diff = 0;
1581 }
1582
1583 if (diff != 0)
1584 {
1585 INT i;
1586
1587 for (i = 0; i < MONTHCAL_GetCalCount(infoPtr); i++)
1588 MONTHCAL_GetMonth(&infoPtr->calendars[i].month, diff);
1589 }
1590
1591 /* we need to store time part as it is */
1592 selection = *curSel;
1594 infoPtr->minSel = infoPtr->maxSel = selection;
1595
1596 /* if selection is still in current month, reduce rectangle */
1597 day = prev.wDay;
1598 prev.wDay = curSel->wDay;
1599 if (MONTHCAL_IsDateEqual(&prev, curSel))
1600 {
1601 RECT r_prev, r_new;
1602
1603 prev.wDay = day;
1604 MONTHCAL_GetDayRect(infoPtr, &prev, &r_prev, -1);
1605 MONTHCAL_GetDayRect(infoPtr, curSel, &r_new, -1);
1606
1607 InvalidateRect(infoPtr->hwndSelf, &r_prev, FALSE);
1608 InvalidateRect(infoPtr->hwndSelf, &r_new, FALSE);
1609 }
1610 else
1611 InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
1612
1613 return TRUE;
1614}
1615
1617static LRESULT
1619{
1620 return infoPtr->maxSelCount;
1621}
1622
1624static LRESULT
1626{
1627 TRACE("%d\n", max);
1628
1629 if(!(infoPtr->dwStyle & MCS_MULTISELECT)) return FALSE;
1630 if(max <= 0) return FALSE;
1631
1632 infoPtr->maxSelCount = max;
1633
1634 return TRUE;
1635}
1636
1638static LRESULT
1640{
1641 TRACE("%p\n", range);
1642
1643 if(!range) return FALSE;
1644
1645 if(infoPtr->dwStyle & MCS_MULTISELECT)
1646 {
1647 range[1] = infoPtr->maxSel;
1648 range[0] = infoPtr->minSel;
1649 TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
1650 return TRUE;
1651 }
1652
1653 return FALSE;
1654}
1655
1657static LRESULT
1659{
1660 SYSTEMTIME old_range[2];
1661 INT diff;
1662
1663 TRACE("%p\n", range);
1664
1665 if(!range || !(infoPtr->dwStyle & MCS_MULTISELECT)) return FALSE;
1666
1667 /* adjust timestamps */
1670
1671 /* maximum range exceeded */
1672 if(!MONTHCAL_IsSelRangeValid(infoPtr, &range[0], &range[1], NULL)) return FALSE;
1673
1674 old_range[0] = infoPtr->minSel;
1675 old_range[1] = infoPtr->maxSel;
1676
1677 /* swap if min > max */
1678 if(MONTHCAL_CompareSystemTime(&range[0], &range[1]) <= 0)
1679 {
1680 infoPtr->minSel = range[0];
1681 infoPtr->maxSel = range[1];
1682 }
1683 else
1684 {
1685 infoPtr->minSel = range[1];
1686 infoPtr->maxSel = range[0];
1687 }
1688
1689 diff = MONTHCAL_MonthDiff(&infoPtr->calendars[MONTHCAL_GetCalCount(infoPtr)-1].month, &infoPtr->maxSel);
1690 if (diff < 0)
1691 {
1692 diff = MONTHCAL_MonthDiff(&infoPtr->calendars[0].month, &infoPtr->maxSel);
1693 if (diff > 0) diff = 0;
1694 }
1695
1696 if (diff != 0)
1697 {
1698 INT i;
1699
1700 for (i = 0; i < MONTHCAL_GetCalCount(infoPtr); i++)
1701 MONTHCAL_GetMonth(&infoPtr->calendars[i].month, diff);
1702 }
1703
1704 /* update day of week */
1707
1708 /* redraw if bounds changed */
1709 /* FIXME: no actual need to redraw everything */
1710 if(!MONTHCAL_IsDateEqual(&old_range[0], &range[0]) ||
1711 !MONTHCAL_IsDateEqual(&old_range[1], &range[1]))
1712 {
1713 InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
1714 }
1715
1716 TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
1717 return TRUE;
1718}
1719
1721static LRESULT
1722MONTHCAL_GetToday(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *today)
1723{
1724 TRACE("%p\n", today);
1725
1726 if(!today) return FALSE;
1727 *today = infoPtr->todaysDate;
1728 return TRUE;
1729}
1730
1731/* Internal helper for MCM_SETTODAY handler and auto update timer handler
1732 *
1733 * RETURN VALUE
1734 *
1735 * TRUE - today date changed
1736 * FALSE - today date isn't changed
1738static BOOL
1739MONTHCAL_UpdateToday(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *today)
1740{
1741 RECT rect;
1742
1743 if (MONTHCAL_IsDateEqual(today, &infoPtr->todaysDate))
1744 return FALSE;
1745
1746 /* Invalidate old and new today day rectangle, and today label. */
1747 if (MONTHCAL_GetDayRect(infoPtr, &infoPtr->todaysDate, &rect, -1))
1748 InvalidateRect(infoPtr->hwndSelf, &rect, FALSE);
1749
1750 if (MONTHCAL_GetDayRect(infoPtr, today, &rect, -1))
1751 InvalidateRect(infoPtr->hwndSelf, &rect, FALSE);
1752
1753 infoPtr->todaysDate = *today;
1754
1755 InvalidateRect(infoPtr->hwndSelf, &infoPtr->todayrect, FALSE);
1756 return TRUE;
1757}
1758
1759/* MCM_SETTODAT handler */
1760static LRESULT
1761MONTHCAL_SetToday(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *today)
1762{
1763 TRACE("%p\n", today);
1764
1765 if (today)
1766 {
1767 /* remember if date was set successfully */
1768 if (MONTHCAL_UpdateToday(infoPtr, today)) infoPtr->todaySet = TRUE;
1769 }
1770
1771 return 0;
1772}
1774/* returns calendar index containing specified point, or -1 if it's background */
1775static INT MONTHCAL_GetCalendarFromPoint(const MONTHCAL_INFO *infoPtr, const POINT *pt)
1776{
1777 RECT r;
1778 INT i;
1779
1780 for (i = 0; i < MONTHCAL_GetCalCount(infoPtr); i++)
1781 {
1782 /* whole bounding rectangle allows some optimization to compute */
1783 r.left = infoPtr->calendars[i].title.left;
1784 r.top = infoPtr->calendars[i].title.top;
1785 r.bottom = infoPtr->calendars[i].days.bottom;
1786 r.right = infoPtr->calendars[i].days.right;
1787
1788 if (PtInRect(&r, *pt)) return i;
1789 }
1790
1791 return -1;
1793
1795{
1796 dest->uHit = src->uHit;
1797 dest->st = src->st;
1798
1799 if (dest->cbSize == sizeof(MCHITTESTINFO))
1800 memcpy(&dest->rc, &src->rc, sizeof(MCHITTESTINFO) - MCHITTESTINFO_V1_SIZE);
1801
1802 return src->uHit;
1803}
1805static LRESULT
1806MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht)
1807{
1808 MCHITTESTINFO htinfo;
1809 SYSTEMTIME *ht_month;
1810 INT day, calIdx;
1811
1812 if(!lpht || lpht->cbSize < MCHITTESTINFO_V1_SIZE) return -1;
1813
1814 htinfo.st = st_null;
1815
1816 /* we should preserve passed fields if hit area doesn't need them */
1817 if (lpht->cbSize == sizeof(MCHITTESTINFO))
1818 memcpy(&htinfo.rc, &lpht->rc, sizeof(MCHITTESTINFO) - MCHITTESTINFO_V1_SIZE);
1819
1820 /* guess in what calendar we are */
1821 calIdx = MONTHCAL_GetCalendarFromPoint(infoPtr, &lpht->pt);
1822 if (calIdx == -1)
1823 {
1824 if (PtInRect(&infoPtr->todayrect, lpht->pt))
1825 {
1826 htinfo.uHit = MCHT_TODAYLINK;
1827 htinfo.rc = infoPtr->todayrect;
1828 }
1829 else
1830 /* outside of calendar area? What's left must be background :-) */
1831 htinfo.uHit = MCHT_CALENDARBK;
1832
1833 return fill_hittest_info(&htinfo, lpht);
1834 }
1835
1836 /* are we in the header? */
1837 if (PtInRect(&infoPtr->calendars[calIdx].title, lpht->pt)) {
1838 /* FIXME: buttons hittesting could be optimized cause maximum
1839 two calendars have buttons */
1840 if (calIdx == 0 && PtInRect(&infoPtr->titlebtnprev, lpht->pt))
1841 {
1842 htinfo.uHit = MCHT_TITLEBTNPREV;
1843 htinfo.rc = infoPtr->titlebtnprev;
1844 }
1845 else if (PtInRect(&infoPtr->titlebtnnext, lpht->pt))
1846 {
1847 htinfo.uHit = MCHT_TITLEBTNNEXT;
1848 htinfo.rc = infoPtr->titlebtnnext;
1849 }
1850 else if (PtInRect(&infoPtr->calendars[calIdx].titlemonth, lpht->pt))
1851 {
1852 htinfo.uHit = MCHT_TITLEMONTH;
1853 htinfo.rc = infoPtr->calendars[calIdx].titlemonth;
1854 htinfo.iOffset = calIdx;
1855 }
1856 else if (PtInRect(&infoPtr->calendars[calIdx].titleyear, lpht->pt))
1857 {
1858 htinfo.uHit = MCHT_TITLEYEAR;
1859 htinfo.rc = infoPtr->calendars[calIdx].titleyear;
1860 htinfo.iOffset = calIdx;
1861 }
1862 else
1863 {
1864 htinfo.uHit = MCHT_TITLE;
1865 htinfo.rc = infoPtr->calendars[calIdx].title;
1866 htinfo.iOffset = calIdx;
1867 }
1868
1869 return fill_hittest_info(&htinfo, lpht);
1870 }
1871
1872 ht_month = &infoPtr->calendars[calIdx].month;
1873 /* days area (including week days and week numbers) */
1874 day = MONTHCAL_GetDayFromPos(infoPtr, lpht->pt, calIdx);
1875 if (PtInRect(&infoPtr->calendars[calIdx].wdays, lpht->pt))
1876 {
1877 htinfo.uHit = MCHT_CALENDARDAY;
1878 htinfo.iOffset = calIdx;
1879 htinfo.st.wYear = ht_month->wYear;
1880 htinfo.st.wMonth = (day < 1) ? ht_month->wMonth -1 : ht_month->wMonth;
1881 htinfo.st.wDay = (day < 1) ?
1882 MONTHCAL_MonthLength(ht_month->wMonth-1, ht_month->wYear) - day : day;
1883
1884 MONTHCAL_GetDayPos(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow, calIdx);
1885 }
1886 else if(PtInRect(&infoPtr->calendars[calIdx].weeknums, lpht->pt))
1887 {
1888 htinfo.uHit = MCHT_CALENDARWEEKNUM;
1889 htinfo.st.wYear = ht_month->wYear;
1890 htinfo.iOffset = calIdx;
1891
1892 if (day < 1)
1893 {
1894 htinfo.st.wMonth = ht_month->wMonth - 1;
1895 htinfo.st.wDay = MONTHCAL_MonthLength(ht_month->wMonth-1, ht_month->wYear) - day;
1896 }
1897 else if (day > MONTHCAL_MonthLength(ht_month->wMonth, ht_month->wYear))
1898 {
1899 htinfo.st.wMonth = ht_month->wMonth + 1;
1900 htinfo.st.wDay = day - MONTHCAL_MonthLength(ht_month->wMonth, ht_month->wYear);
1901 }
1902 else
1903 {
1904 htinfo.st.wMonth = ht_month->wMonth;
1905 htinfo.st.wDay = day;
1906 }
1907 }
1908 else if(PtInRect(&infoPtr->calendars[calIdx].days, lpht->pt))
1909 {
1910 htinfo.iOffset = calIdx;
1911 htinfo.st.wDay = ht_month->wDay;
1912 htinfo.st.wYear = ht_month->wYear;
1913 htinfo.st.wMonth = ht_month->wMonth;
1914 /* previous month only valid for first calendar */
1915 if (day < 1 && calIdx == 0)
1916 {
1917 htinfo.uHit = MCHT_CALENDARDATEPREV;
1918 MONTHCAL_GetPrevMonth(&htinfo.st);
1919 htinfo.st.wDay = MONTHCAL_MonthLength(htinfo.st.wMonth, htinfo.st.wYear) + day;
1920 }
1921 /* next month only valid for last calendar */
1922 else if (day > MONTHCAL_MonthLength(ht_month->wMonth, ht_month->wYear) &&
1923 calIdx == MONTHCAL_GetCalCount(infoPtr)-1)
1924 {
1925 htinfo.uHit = MCHT_CALENDARDATENEXT;
1926 MONTHCAL_GetNextMonth(&htinfo.st);
1927 htinfo.st.wDay = day - MONTHCAL_MonthLength(ht_month->wMonth, ht_month->wYear);
1928 }
1929 /* multiple calendars case - blank areas for previous/next month */
1930 else if (day < 1 || day > MONTHCAL_MonthLength(ht_month->wMonth, ht_month->wYear))
1931 {
1932 htinfo.uHit = MCHT_CALENDARBK;
1933 }
1934 else
1935 {
1936 htinfo.uHit = MCHT_CALENDARDATE;
1937 htinfo.st.wDay = day;
1938 }
1939
1940 MONTHCAL_GetDayPos(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow, calIdx);
1941 MONTHCAL_GetDayRectI(infoPtr, &htinfo.rc, htinfo.iCol, htinfo.iRow, calIdx);
1942 /* always update day of week */
1944 }
1945
1946 return fill_hittest_info(&htinfo, lpht);
1947}
1949/* MCN_GETDAYSTATE notification helper */
1950static void MONTHCAL_NotifyDayState(MONTHCAL_INFO *infoPtr)
1951{
1953 NMDAYSTATE nmds;
1954
1955 if (!(infoPtr->dwStyle & MCS_DAYSTATE)) return;
1956
1957 nmds.nmhdr.hwndFrom = infoPtr->hwndSelf;
1958 nmds.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
1959 nmds.nmhdr.code = MCN_GETDAYSTATE;
1960 nmds.cDayState = MONTHCAL_GetMonthRange(infoPtr, GMR_DAYSTATE, 0);
1961 nmds.prgDayState = state = heap_alloc_zero(nmds.cDayState * sizeof(MONTHDAYSTATE));
1962
1963 MONTHCAL_GetMinDate(infoPtr, &nmds.stStart);
1964 nmds.stStart.wDay = 1;
1965
1966 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmds.nmhdr.idFrom, (LPARAM)&nmds);
1967 memcpy(infoPtr->monthdayState, nmds.prgDayState,
1969
1971}
1973/* no valid range check performed */
1974static void MONTHCAL_Scroll(MONTHCAL_INFO *infoPtr, INT delta, BOOL keep_selection)
1975{
1976 INT i, selIdx = -1;
1977
1978 for(i = 0; i < MONTHCAL_GetCalCount(infoPtr); i++)
1979 {
1980 /* save selection position to shift it later */
1981 if (selIdx == -1 && MONTHCAL_CompareMonths(&infoPtr->minSel, &infoPtr->calendars[i].month) == 0)
1982 selIdx = i;
1983
1984 MONTHCAL_GetMonth(&infoPtr->calendars[i].month, delta);
1985 }
1986
1987 if (keep_selection)
1988 return;
1989
1990 /* selection is always shifted to first calendar */
1991 if (infoPtr->dwStyle & MCS_MULTISELECT)
1992 {
1993 SYSTEMTIME range[2];
1994
1995 MONTHCAL_GetSelRange(infoPtr, range);
1996 MONTHCAL_GetMonth(&range[0], delta - selIdx);
1997 MONTHCAL_GetMonth(&range[1], delta - selIdx);
1998 MONTHCAL_SetSelRange(infoPtr, range);
1999 }
2000 else
2001 {
2002 SYSTEMTIME st = infoPtr->minSel;
2003
2004 MONTHCAL_GetMonth(&st, delta - selIdx);
2005 MONTHCAL_SetCurSel(infoPtr, &st);
2006 }
2008
2009static void MONTHCAL_GoToMonth(MONTHCAL_INFO *infoPtr, enum nav_direction direction)
2010{
2011 INT delta = infoPtr->delta ? infoPtr->delta : MONTHCAL_GetCalCount(infoPtr);
2012 BOOL keep_selection;
2013 SYSTEMTIME st;
2014
2015 TRACE("%s\n", direction == DIRECTION_BACKWARD ? "back" : "fwd");
2016
2017 /* check if change allowed by range set */
2018 if(direction == DIRECTION_BACKWARD)
2019 {
2020 st = infoPtr->calendars[0].month;
2021 MONTHCAL_GetMonth(&st, -delta);
2022 }
2023 else
2024 {
2025 st = infoPtr->calendars[MONTHCAL_GetCalCount(infoPtr)-1].month;
2026 MONTHCAL_GetMonth(&st, delta);
2027 }
2028
2029 if(!MONTHCAL_IsDateInValidRange(infoPtr, &st, FALSE)) return;
2030
2031 keep_selection = infoPtr->dwStyle & MCS_NOSELCHANGEONNAV;
2032 MONTHCAL_Scroll(infoPtr, direction == DIRECTION_BACKWARD ? -delta : delta, keep_selection);
2033 MONTHCAL_NotifyDayState(infoPtr);
2034 if (!keep_selection)
2036}
2038static LRESULT
2040{
2041 HMENU hMenu;
2042 POINT menupoint;
2043 WCHAR buf[32];
2044
2045 hMenu = CreatePopupMenu();
2047 AppendMenuW(hMenu, MF_STRING|MF_ENABLED, 1, buf);
2048 menupoint.x = (short)LOWORD(lParam);
2049 menupoint.y = (short)HIWORD(lParam);
2050 ClientToScreen(infoPtr->hwndSelf, &menupoint);
2052 menupoint.x, menupoint.y, 0, infoPtr->hwndSelf, NULL))
2053 {
2054 if (infoPtr->dwStyle & MCS_MULTISELECT)
2055 {
2056 SYSTEMTIME range[2];
2057
2058 range[0] = range[1] = infoPtr->todaysDate;
2059 MONTHCAL_SetSelRange(infoPtr, range);
2060 }
2061 else
2062 MONTHCAL_SetCurSel(infoPtr, &infoPtr->todaysDate);
2063
2065 MONTHCAL_NotifySelect(infoPtr);
2066 }
2067
2068 return 0;
2069}
2070
2071/***
2072 * DESCRIPTION:
2073 * Subclassed edit control windproc function
2074 *
2075 * PARAMETER(S):
2076 * [I] hwnd : the edit window handle
2077 * [I] uMsg : the message that is to be processed
2078 * [I] wParam : first message parameter
2079 * [I] lParam : second message parameter
2081 */
2083{
2085
2086 TRACE("(hwnd=%p, uMsg=%x, wParam=%lx, lParam=%lx)\n",
2087 hwnd, uMsg, wParam, lParam);
2088
2089 switch (uMsg)
2090 {
2091 case WM_GETDLGCODE:
2093
2094 case WM_DESTROY:
2095 {
2096 WNDPROC editProc = infoPtr->EditWndProc;
2097 infoPtr->EditWndProc = NULL;
2099 return CallWindowProcW(editProc, hwnd, uMsg, wParam, lParam);
2100 }
2101
2102 case WM_KILLFOCUS:
2103 break;
2104
2105 case WM_KEYDOWN:
2106 if ((VK_ESCAPE == (INT)wParam) || (VK_RETURN == (INT)wParam))
2107 break;
2108
2109 default:
2110 return CallWindowProcW(infoPtr->EditWndProc, hwnd, uMsg, wParam, lParam);
2111 }
2112
2113 SendMessageW(infoPtr->hWndYearUpDown, WM_CLOSE, 0, 0);
2114 SendMessageW(hwnd, WM_CLOSE, 0, 0);
2115 return 0;
2116}
2118/* creates updown control and edit box */
2119static void MONTHCAL_EditYear(MONTHCAL_INFO *infoPtr, INT calIdx)
2120{
2121 RECT *rc = &infoPtr->calendars[calIdx].titleyear;
2122 RECT *title = &infoPtr->calendars[calIdx].title;
2123
2124 infoPtr->hWndYearEdit =
2126 rc->left + 3, (title->bottom + title->top - infoPtr->textHeight) / 2,
2127 rc->right - rc->left + 4,
2128 infoPtr->textHeight, infoPtr->hwndSelf,
2129 NULL, NULL, NULL);
2130
2132
2133 infoPtr->hWndYearUpDown =
2136 rc->right + 7, (title->bottom + title->top - infoPtr->textHeight) / 2,
2137 18, infoPtr->textHeight, infoPtr->hwndSelf,
2138 NULL, NULL, NULL);
2139
2140 /* attach edit box */
2144 SendMessageW(infoPtr->hWndYearUpDown, UDM_SETPOS, 0, infoPtr->calendars[calIdx].month.wYear);
2145
2146 /* subclass edit box */
2149
2150 SetFocus(infoPtr->hWndYearEdit);
2151}
2153static LRESULT
2155{
2157 DWORD hit;
2158
2159 /* Actually we don't need input focus for calendar, this is used to kill
2160 year updown and its buddy edit box */
2161 if (IsWindow(infoPtr->hWndYearUpDown))
2162 {
2163 SetFocus(infoPtr->hwndSelf);
2164 return 0;
2165 }
2166
2167 SetCapture(infoPtr->hwndSelf);
2168
2169 ht.cbSize = sizeof(MCHITTESTINFO);
2170 ht.pt.x = (short)LOWORD(lParam);
2171 ht.pt.y = (short)HIWORD(lParam);
2172
2173 hit = MONTHCAL_HitTest(infoPtr, &ht);
2174
2175 TRACE("%x at %s\n", hit, wine_dbgstr_point(&ht.pt));
2176
2177 switch(hit)
2178 {
2179 case MCHT_TITLEBTNNEXT:
2181 infoPtr->status = MC_NEXTPRESSED;
2183 InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
2184 return 0;
2185
2186 case MCHT_TITLEBTNPREV:
2188 infoPtr->status = MC_PREVPRESSED;
2190 InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
2191 return 0;
2192
2193 case MCHT_TITLEMONTH:
2194 {
2195 HMENU hMenu = CreatePopupMenu();
2196 WCHAR buf[32];
2197 POINT menupoint;
2198 INT i;
2199
2200 for (i = 0; i < 12; i++)
2201 {
2203 AppendMenuW(hMenu, MF_STRING|MF_ENABLED, i + 1, buf);
2204 }
2205 menupoint.x = ht.pt.x;
2206 menupoint.y = ht.pt.y;
2207 ClientToScreen(infoPtr->hwndSelf, &menupoint);
2209 menupoint.x, menupoint.y, 0, infoPtr->hwndSelf, NULL);
2210
2211 if ((i > 0) && (i < 13) && infoPtr->calendars[ht.iOffset].month.wMonth != i)
2212 {
2213 INT delta = i - infoPtr->calendars[ht.iOffset].month.wMonth;
2214 SYSTEMTIME st;
2215
2216 /* check if change allowed by range set */
2217 st = delta < 0 ? infoPtr->calendars[0].month :
2218 infoPtr->calendars[MONTHCAL_GetCalCount(infoPtr)-1].month;
2219 MONTHCAL_GetMonth(&st, delta);
2220
2221 if (MONTHCAL_IsDateInValidRange(infoPtr, &st, FALSE))
2222 {
2223 MONTHCAL_Scroll(infoPtr, delta, FALSE);
2224 MONTHCAL_NotifyDayState(infoPtr);
2226 InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
2227 }
2228 }
2229 return 0;
2230 }
2231 case MCHT_TITLEYEAR:
2232 {
2233 MONTHCAL_EditYear(infoPtr, ht.iOffset);
2234 return 0;
2235 }
2236 case MCHT_TODAYLINK:
2237 {
2238 if (infoPtr->dwStyle & MCS_MULTISELECT)
2239 {
2240 SYSTEMTIME range[2];
2241
2242 range[0] = range[1] = infoPtr->todaysDate;
2243 MONTHCAL_SetSelRange(infoPtr, range);
2244 }
2245 else
2246 MONTHCAL_SetCurSel(infoPtr, &infoPtr->todaysDate);
2247
2249 MONTHCAL_NotifySelect(infoPtr);
2250 return 0;
2251 }
2254 case MCHT_CALENDARDATE:
2255 {
2256 SYSTEMTIME st[2];
2257
2258 MONTHCAL_CopyDate(&ht.st, &infoPtr->firstSel);
2259
2260 st[0] = st[1] = ht.st;
2261 /* clear selection range */
2262 MONTHCAL_SetSelRange(infoPtr, st);
2263
2264 infoPtr->status = MC_SEL_LBUTDOWN;
2265 MONTHCAL_SetDayFocus(infoPtr, &ht.st);
2266 return 0;
2267 }
2268 }
2269
2270 return 1;
2271}
2272
2274static LRESULT
2276{
2277 NMHDR nmhdr;
2279 DWORD hit;
2280
2281 TRACE("\n");
2282
2283 if(infoPtr->status & (MC_PREVPRESSED | MC_NEXTPRESSED)) {
2284 RECT *r;
2285
2287 r = infoPtr->status & MC_PREVPRESSED ? &infoPtr->titlebtnprev : &infoPtr->titlebtnnext;
2288 infoPtr->status &= ~(MC_PREVPRESSED | MC_NEXTPRESSED);
2289
2290 InvalidateRect(infoPtr->hwndSelf, r, FALSE);
2291 }
2292
2294
2295 /* always send NM_RELEASEDCAPTURE notification */
2296 nmhdr.hwndFrom = infoPtr->hwndSelf;
2297 nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
2298 nmhdr.code = NM_RELEASEDCAPTURE;
2299 TRACE("Sent notification from %p to %p\n", infoPtr->hwndSelf, infoPtr->hwndNotify);
2300
2301 SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr);
2302
2303 if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0;
2304
2305 ht.cbSize = sizeof(MCHITTESTINFO);
2306 ht.pt.x = (short)LOWORD(lParam);
2307 ht.pt.y = (short)HIWORD(lParam);
2308 hit = MONTHCAL_HitTest(infoPtr, &ht);
2309
2310 infoPtr->status = MC_SEL_LBUTUP;
2311 MONTHCAL_SetDayFocus(infoPtr, NULL);
2312
2314 {
2315 SYSTEMTIME sel = infoPtr->minSel;
2316
2317 /* will be invalidated here */
2318 MONTHCAL_SetCurSel(infoPtr, &ht.st);
2319
2320 /* send MCN_SELCHANGE only if new date selected */
2321 if (!MONTHCAL_IsDateEqual(&sel, &ht.st))
2323
2324 MONTHCAL_NotifySelect(infoPtr);
2325 }
2326
2327 return 0;
2328}
2329
2331static LRESULT
2333{
2334 TRACE("%ld\n", id);
2335
2336 switch(id) {
2340 InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
2341 break;
2343 {
2344 SYSTEMTIME st;
2345
2346 if(infoPtr->todaySet) return 0;
2347
2348 GetLocalTime(&st);
2349 MONTHCAL_UpdateToday(infoPtr, &st);
2350
2351 /* notification sent anyway */
2353
2354 return 0;
2355 }
2356 default:
2357 ERR("got unknown timer %ld\n", id);
2358 break;
2359 }
2360
2361 return 0;
2362}
2363
2365static LRESULT
2367{
2369 SYSTEMTIME st_ht;
2370 INT hit;
2371 RECT r;
2372
2373 if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0;
2374
2375 ht.cbSize = sizeof(MCHITTESTINFO);
2376 ht.pt.x = (short)LOWORD(lParam);
2377 ht.pt.y = (short)HIWORD(lParam);
2378 ht.iOffset = -1;
2379
2380 hit = MONTHCAL_HitTest(infoPtr, &ht);
2381
2382 /* not on the calendar date numbers? bail out */
2383 TRACE("hit:%x\n",hit);
2385 {
2386 MONTHCAL_SetDayFocus(infoPtr, NULL);
2387 return 0;
2388 }
2389
2390 st_ht = ht.st;
2391
2392 /* if pointer is over focused day still there's nothing to do */
2393 if(!MONTHCAL_SetDayFocus(infoPtr, &ht.st)) return 0;
2394
2395 MONTHCAL_GetDayRect(infoPtr, &ht.st, &r, ht.iOffset);
2396
2397 if(infoPtr->dwStyle & MCS_MULTISELECT) {
2398 SYSTEMTIME st[2];
2399
2400 MONTHCAL_GetSelRange(infoPtr, st);
2401
2402 /* If we're still at the first selected date and range is empty, return.
2403 If range isn't empty we should change range to a single firstSel */
2404 if(MONTHCAL_IsDateEqual(&infoPtr->firstSel, &st_ht) &&
2405 MONTHCAL_IsDateEqual(&st[0], &st[1])) goto done;
2406
2407 MONTHCAL_IsSelRangeValid(infoPtr, &st_ht, &infoPtr->firstSel, &st_ht);
2408
2409 st[0] = infoPtr->firstSel;
2410 /* we should overwrite timestamp here */
2411 MONTHCAL_CopyDate(&st_ht, &st[1]);
2412
2413 /* bounds will be swapped here if needed */
2414 MONTHCAL_SetSelRange(infoPtr, st);
2415
2416 return 0;
2417 }
2418
2419done:
2420
2421 /* FIXME: this should specify a rectangle containing only the days that changed
2422 using InvalidateRect */
2423 InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
2424
2425 return 0;
2426}
2427
2429static LRESULT
2430MONTHCAL_Paint(MONTHCAL_INFO *infoPtr, HDC hdc_paint)
2431{
2432 HDC hdc;
2433 PAINTSTRUCT ps;
2434
2435 if (hdc_paint)
2436 {
2437 GetClientRect(infoPtr->hwndSelf, &ps.rcPaint);
2438 hdc = hdc_paint;
2439 }
2440 else
2441 hdc = BeginPaint(infoPtr->hwndSelf, &ps);
2442
2443 MONTHCAL_Refresh(infoPtr, hdc, &ps);
2444 if (!hdc_paint) EndPaint(infoPtr->hwndSelf, &ps);
2445 return 0;
2446}
2448static LRESULT
2450{
2451 RECT rc;
2452
2453 if (!GetClipBox(hdc, &rc)) return FALSE;
2454
2455 FillRect(hdc, &rc, infoPtr->brushes[BrushBackground]);
2456
2457 return TRUE;
2458}
2460static LRESULT
2462{
2463 FIXME("Partial Stub: (hdc=%p options=0x%08x)\n", hdc, options);
2464
2465 if ((options & PRF_CHECKVISIBLE) && !IsWindowVisible(infoPtr->hwndSelf))
2466 return 0;
2467
2468 if (options & PRF_ERASEBKGND)
2469 MONTHCAL_EraseBkgnd(infoPtr, hdc);
2470
2471 if (options & PRF_CLIENT)
2472 MONTHCAL_Paint(infoPtr, hdc);
2473
2474 return 0;
2475}
2477static LRESULT
2478MONTHCAL_SetFocus(const MONTHCAL_INFO *infoPtr)
2479{
2480 TRACE("\n");
2481
2482 InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
2483
2484 return 0;
2485}
2487/* sets the size information */
2488static void MONTHCAL_UpdateSize(MONTHCAL_INFO *infoPtr)
2489{
2490 static const WCHAR O0W[] = { '0','0',0 };
2491 RECT *title=&infoPtr->calendars[0].title;
2492 RECT *prev=&infoPtr->titlebtnprev;
2493 RECT *next=&infoPtr->titlebtnnext;
2494 RECT *titlemonth=&infoPtr->calendars[0].titlemonth;
2495 RECT *titleyear=&infoPtr->calendars[0].titleyear;
2496 RECT *wdays=&infoPtr->calendars[0].wdays;
2497 RECT *weeknumrect=&infoPtr->calendars[0].weeknums;
2498 RECT *days=&infoPtr->calendars[0].days;
2499 RECT *todayrect=&infoPtr->todayrect;
2500
2501 INT xdiv, dx, dy, i, j, x, y, c_dx, c_dy;
2502 WCHAR buff[80];
2504 INT day_width;
2505 RECT client;
2506 HFONT font;
2507 SIZE size;
2508 HDC hdc;
2509
2510 GetClientRect(infoPtr->hwndSelf, &client);
2511
2512 hdc = GetDC(infoPtr->hwndSelf);
2513 font = SelectObject(hdc, infoPtr->hFont);
2514
2515 /* get the height and width of each day's text */
2517 infoPtr->textHeight = tm.tmHeight + tm.tmExternalLeading + tm.tmInternalLeading;
2518
2519 /* find widest day name for current locale and font */
2520 day_width = 0;
2521 for (i = 0; i < 7; i++)
2522 {
2523 SIZE sz;
2524
2525 if (get_localized_dayname(infoPtr, i, buff, ARRAY_SIZE(buff)))
2526 {
2528 if (sz.cx > day_width) day_width = sz.cx;
2529 }
2530 else /* locale independent fallback on failure */
2531 {
2532 static const WCHAR sunW[] = { 'S','u','n' };
2533 GetTextExtentPoint32W(hdc, sunW, ARRAY_SIZE(sunW), &sz);
2534 day_width = sz.cx;
2535 break;
2536 }
2537 }
2538
2539 day_width += 2;
2540
2541 /* recalculate the height and width increments and offsets */
2542 size.cx = 0;
2543 GetTextExtentPoint32W(hdc, O0W, 2, &size);
2544
2545 /* restore the originally selected font */
2547 ReleaseDC(infoPtr->hwndSelf, hdc);
2548
2549 xdiv = (infoPtr->dwStyle & MCS_WEEKNUMBERS) ? 8 : 7;
2550
2551 infoPtr->width_increment = max(day_width, size.cx * 2 + 4);
2552 infoPtr->height_increment = infoPtr->textHeight;
2553
2554 /* calculate title area */
2555 title->top = 0;
2556 title->bottom = 3 * infoPtr->height_increment / 2;
2557 title->left = 0;
2558 title->right = infoPtr->width_increment * xdiv;
2559
2560 /* set the dimensions of the next and previous buttons and center */
2561 /* the month text vertically */
2562 prev->top = next->top = title->top + 4;
2563 prev->bottom = next->bottom = title->bottom - 4;
2564 prev->left = title->left + 4;
2565 prev->right = prev->left + (title->bottom - title->top);
2566 next->right = title->right - 4;
2567 next->left = next->right - (title->bottom - title->top);
2568
2569 /* titlemonth->left and right change based upon the current month
2570 and are recalculated in refresh as the current month may change
2571 without the control being resized */
2572 titlemonth->top = titleyear->top = title->top + (infoPtr->height_increment)/2;
2573 titlemonth->bottom = titleyear->bottom = title->bottom - (infoPtr->height_increment)/2;
2574
2575 /* week numbers */
2576 weeknumrect->left = 0;
2577 weeknumrect->right = infoPtr->dwStyle & MCS_WEEKNUMBERS ? prev->right : 0;
2578
2579 /* days abbreviated names */
2580 wdays->left = days->left = weeknumrect->right;
2581 wdays->right = days->right = wdays->left + 7 * infoPtr->width_increment;
2582 wdays->top = title->bottom;
2583 wdays->bottom = wdays->top + infoPtr->height_increment;
2584
2585 days->top = weeknumrect->top = wdays->bottom;
2586 days->bottom = weeknumrect->bottom = days->top + 6 * infoPtr->height_increment;
2587
2588 todayrect->left = 0;
2589 todayrect->right = title->right;
2590 todayrect->top = days->bottom;
2591 todayrect->bottom = days->bottom + infoPtr->height_increment;
2592
2593 /* compute calendar count, update all calendars */
2594 x = (client.right + MC_CALENDAR_PADDING) / (title->right - title->left + MC_CALENDAR_PADDING);
2595 /* today label affects whole height */
2596 if (infoPtr->dwStyle & MCS_NOTODAY)
2597 y = (client.bottom + MC_CALENDAR_PADDING) / (days->bottom - title->top + MC_CALENDAR_PADDING);
2598 else
2599 y = (client.bottom - todayrect->bottom + todayrect->top + MC_CALENDAR_PADDING) /
2600 (days->bottom - title->top + MC_CALENDAR_PADDING);
2601
2602 /* TODO: ensure that count is properly adjusted to fit 12 months constraint */
2603 if (x == 0) x = 1;
2604 if (y == 0) y = 1;
2605
2606 if (x*y != MONTHCAL_GetCalCount(infoPtr))
2607 {
2608 infoPtr->dim.cx = x;
2609 infoPtr->dim.cy = y;
2610 infoPtr->calendars = heap_realloc(infoPtr->calendars, MONTHCAL_GetCalCount(infoPtr)*sizeof(CALENDAR_INFO));
2611
2612 infoPtr->monthdayState = heap_realloc(infoPtr->monthdayState,
2614 MONTHCAL_NotifyDayState(infoPtr);
2615
2616 /* update pointers that we'll need */
2617 title = &infoPtr->calendars[0].title;
2618 wdays = &infoPtr->calendars[0].wdays;
2619 days = &infoPtr->calendars[0].days;
2620 }
2621
2622 for (i = 1; i < MONTHCAL_GetCalCount(infoPtr); i++)
2623 {
2624 /* set months */
2625 infoPtr->calendars[i] = infoPtr->calendars[0];
2626 MONTHCAL_GetMonth(&infoPtr->calendars[i].month, i);
2627 }
2628
2629 /* offset all rectangles to center in client area */
2630 c_dx = (client.right - x * title->right - MC_CALENDAR_PADDING * (x-1)) / 2;
2631 c_dy = (client.bottom - y * todayrect->bottom - MC_CALENDAR_PADDING * (y-1)) / 2;
2632
2633 /* if calendar doesn't fit client area show it at left/top bounds */
2634 if (title->left + c_dx < 0) c_dx = 0;
2635 if (title->top + c_dy < 0) c_dy = 0;
2636
2637 for (i = 0; i < y; i++)
2638 {
2639 for (j = 0; j < x; j++)
2640 {
2641 dx = j*(title->right - title->left + MC_CALENDAR_PADDING) + c_dx;
2642 dy = i*(days->bottom - title->top + MC_CALENDAR_PADDING) + c_dy;
2643
2644 OffsetRect(&infoPtr->calendars[i*x+j].title, dx, dy);
2645 OffsetRect(&infoPtr->calendars[i*x+j].titlemonth, dx, dy);
2646 OffsetRect(&infoPtr->calendars[i*x+j].titleyear, dx, dy);
2647 OffsetRect(&infoPtr->calendars[i*x+j].wdays, dx, dy);
2648 OffsetRect(&infoPtr->calendars[i*x+j].weeknums, dx, dy);
2649 OffsetRect(&infoPtr->calendars[i*x+j].days, dx, dy);
2650 }
2651 }
2652
2653 OffsetRect(prev, c_dx, c_dy);
2654 OffsetRect(next, (x-1)*(title->right - title->left + MC_CALENDAR_PADDING) + c_dx, c_dy);
2655
2656 i = infoPtr->dim.cx * infoPtr->dim.cy - infoPtr->dim.cx;
2657 todayrect->left = infoPtr->calendars[i].title.left;
2658 todayrect->right = infoPtr->calendars[i].title.right;
2659 todayrect->top = infoPtr->calendars[i].days.bottom;
2660 todayrect->bottom = infoPtr->calendars[i].days.bottom + infoPtr->height_increment;
2661
2662 TRACE("dx=%d dy=%d client[%s] title[%s] wdays[%s] days[%s] today[%s]\n",
2663 infoPtr->width_increment,infoPtr->height_increment,
2666 wine_dbgstr_rect(wdays),
2667 wine_dbgstr_rect(days),
2668 wine_dbgstr_rect(todayrect));
2670
2671static LRESULT MONTHCAL_Size(MONTHCAL_INFO *infoPtr, int Width, int Height)
2672{
2673 TRACE("(width=%d, height=%d)\n", Width, Height);
2674
2675 MONTHCAL_UpdateSize(infoPtr);
2676 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
2677
2678 return 0;
2680
2681static LRESULT MONTHCAL_GetFont(const MONTHCAL_INFO *infoPtr)
2682{
2683 return (LRESULT)infoPtr->hFont;
2685
2687{
2688 HFONT hOldFont;
2689 LOGFONTW lf;
2690
2691 if (!hFont) return 0;
2692
2693 hOldFont = infoPtr->hFont;
2694 infoPtr->hFont = hFont;
2695
2696 GetObjectW(infoPtr->hFont, sizeof(lf), &lf);
2697 lf.lfWeight = FW_BOLD;
2698 infoPtr->hBoldFont = CreateFontIndirectW(&lf);
2699
2700 MONTHCAL_UpdateSize(infoPtr);
2701
2702 if (redraw)
2703 InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
2704
2705 return (LRESULT)hOldFont;
2706}
2708/* update theme after a WM_THEMECHANGED message */
2709static LRESULT theme_changed (const MONTHCAL_INFO* infoPtr)
2710{
2711 HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
2712 CloseThemeData (theme);
2713 OpenThemeData (infoPtr->hwndSelf, themeClass);
2714 return 0;
2716
2717static INT MONTHCAL_StyleChanged(MONTHCAL_INFO *infoPtr, WPARAM wStyleType,
2718 const STYLESTRUCT *lpss)
2719{
2720 TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n",
2721 wStyleType, lpss->styleOld, lpss->styleNew);
2722
2723 if (wStyleType != GWL_STYLE) return 0;
2724
2725 infoPtr->dwStyle = lpss->styleNew;
2726
2727 /* make room for week numbers */
2728 if ((lpss->styleNew ^ lpss->styleOld) & (MCS_WEEKNUMBERS | MCS_SHORTDAYSOFWEEK))
2729 MONTHCAL_UpdateSize(infoPtr);
2730
2731 return 0;
2733
2734static INT MONTHCAL_StyleChanging(MONTHCAL_INFO *infoPtr, WPARAM wStyleType,
2735 STYLESTRUCT *lpss)
2736{
2737 TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n",
2738 wStyleType, lpss->styleOld, lpss->styleNew);
2739
2740 /* block MCS_MULTISELECT change */
2741 if ((lpss->styleNew ^ lpss->styleOld) & MCS_MULTISELECT)
2742 {
2743 if (lpss->styleOld & MCS_MULTISELECT)
2744 lpss->styleNew |= MCS_MULTISELECT;
2745 else
2746 lpss->styleNew &= ~MCS_MULTISELECT;
2747 }
2748
2749 /* block MCS_DAYSTATE change */
2750 if ((lpss->styleNew ^ lpss->styleOld) & MCS_DAYSTATE)
2751 {
2752 if (lpss->styleOld & MCS_DAYSTATE)
2753 lpss->styleNew |= MCS_DAYSTATE;
2754 else
2755 lpss->styleNew &= ~MCS_DAYSTATE;
2756 }
2757
2758 return 0;
2759}
2760
2761/* FIXME: check whether dateMin/dateMax need to be adjusted. */
2762static LRESULT
2764{
2765 MONTHCAL_INFO *infoPtr;
2766
2767 /* allocate memory for info structure */
2768 infoPtr = heap_alloc_zero(sizeof(*infoPtr));
2769 SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr);
2770
2771 if (infoPtr == NULL) {
2772 ERR("could not allocate info memory!\n");
2773 return 0;
2774 }
2775
2776 infoPtr->hwndSelf = hwnd;
2777 infoPtr->hwndNotify = lpcs->hwndParent;
2778 infoPtr->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
2779 infoPtr->dim.cx = infoPtr->dim.cy = 1;
2780 infoPtr->calendars = heap_alloc_zero(sizeof(CALENDAR_INFO));
2781 if (!infoPtr->calendars) goto fail;
2782 infoPtr->monthdayState = heap_alloc_zero(3 * sizeof(MONTHDAYSTATE));
2783 if (!infoPtr->monthdayState) goto fail;
2784
2785 /* initialize info structure */
2786 /* FIXME: calculate systemtime ->> localtime(subtract timezoneinfo) */
2787
2788 GetLocalTime(&infoPtr->todaysDate);
2789 MONTHCAL_SetFirstDayOfWeek(infoPtr, -1);
2790
2791 infoPtr->maxSelCount = (infoPtr->dwStyle & MCS_MULTISELECT) ? 7 : 1;
2792
2799
2801 infoPtr->brushes[BrushTitle] = CreateSolidBrush(infoPtr->colors[MCSC_TITLEBK]);
2802 infoPtr->brushes[BrushMonth] = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]);
2803
2804 infoPtr->pens[PenRed] = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
2805 infoPtr->pens[PenText] = CreatePen(PS_SOLID, 1, infoPtr->colors[MCSC_TEXT]);
2806
2807 infoPtr->minSel = infoPtr->todaysDate;
2808 infoPtr->maxSel = infoPtr->todaysDate;
2809 infoPtr->calendars[0].month = infoPtr->todaysDate;
2810 infoPtr->isUnicode = TRUE;
2811
2812 /* setup control layout and day state data */
2813 MONTHCAL_UpdateSize(infoPtr);
2814
2815 /* today auto update timer, to be freed only on control destruction */
2817
2818 OpenThemeData (infoPtr->hwndSelf, themeClass);
2819
2820 return 0;
2821
2822fail:
2823 heap_free(infoPtr->monthdayState);
2824 heap_free(infoPtr->calendars);
2825 heap_free(infoPtr);
2826 return 0;
2827}
2829static LRESULT
2831{
2832 INT i;
2833
2834 /* free month calendar info data */
2835 heap_free(infoPtr->monthdayState);
2836 heap_free(infoPtr->calendars);
2837 SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0);
2838
2840
2841 for (i = 0; i < BrushLast; i++) DeleteObject(infoPtr->brushes[i]);
2842 for (i = 0; i < PenLast; i++) DeleteObject(infoPtr->pens[i]);
2843
2844 heap_free(infoPtr);
2845 return 0;
2846}
2847
2848/*
2849 * Handler for WM_NOTIFY messages
2851static LRESULT
2853{
2854 /* notification from year edit updown */
2855 if (hdr->code == UDN_DELTAPOS)
2856 {
2857 NMUPDOWN *nmud = (NMUPDOWN*)hdr;
2858
2859 if (hdr->hwndFrom == infoPtr->hWndYearUpDown && nmud->iDelta)
2860 {
2861 /* year value limits are set up explicitly after updown creation */
2862 MONTHCAL_Scroll(infoPtr, 12 * nmud->iDelta, FALSE);
2863 MONTHCAL_NotifyDayState(infoPtr);
2865 }
2866 }
2867 return 0;
2868}
2870static inline BOOL
2871MONTHCAL_SetUnicodeFormat(MONTHCAL_INFO *infoPtr, BOOL isUnicode)
2872{
2873 BOOL prev = infoPtr->isUnicode;
2874 infoPtr->isUnicode = isUnicode;
2875 return prev;
2876}
2878static inline BOOL
2880{
2881 return infoPtr->isUnicode;
2882}
2884static LRESULT WINAPI
2886{
2888
2889 TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n", hwnd, uMsg, wParam, lParam);
2890
2891 if (!infoPtr && (uMsg != WM_CREATE))
2892 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
2893 switch(uMsg)
2894 {
2895 case MCM_GETCURSEL:
2896 return MONTHCAL_GetCurSel(infoPtr, (LPSYSTEMTIME)lParam);
2897
2898 case MCM_SETCURSEL:
2899 return MONTHCAL_SetCurSel(infoPtr, (LPSYSTEMTIME)lParam);
2900
2901 case MCM_GETMAXSELCOUNT:
2902 return MONTHCAL_GetMaxSelCount(infoPtr);
2903
2904 case MCM_SETMAXSELCOUNT:
2905 return MONTHCAL_SetMaxSelCount(infoPtr, wParam);
2906
2907 case MCM_GETSELRANGE:
2908 return MONTHCAL_GetSelRange(infoPtr, (LPSYSTEMTIME)lParam);
2909
2910 case MCM_SETSELRANGE:
2911 return MONTHCAL_SetSelRange(infoPtr, (LPSYSTEMTIME)lParam);
2912
2913 case MCM_GETMONTHRANGE:
2914 return MONTHCAL_GetMonthRange(infoPtr, wParam, (SYSTEMTIME*)lParam);
2915
2916 case MCM_SETDAYSTATE:
2918
2919 case MCM_GETMINREQRECT:
2920 return MONTHCAL_GetMinReqRect(infoPtr, (LPRECT)lParam);
2921
2922 case MCM_GETCOLOR:
2923 return MONTHCAL_GetColor(infoPtr, wParam);
2924
2925 case MCM_SETCOLOR:
2926 return MONTHCAL_SetColor(infoPtr, wParam, (COLORREF)lParam);
2927
2928 case MCM_GETTODAY:
2929 return MONTHCAL_GetToday(infoPtr, (LPSYSTEMTIME)lParam);
2930
2931 case MCM_SETTODAY:
2932 return MONTHCAL_SetToday(infoPtr, (LPSYSTEMTIME)lParam);
2933
2934 case MCM_HITTEST:
2935 return MONTHCAL_HitTest(infoPtr, (PMCHITTESTINFO)lParam);
2936
2938 return MONTHCAL_GetFirstDayOfWeek(infoPtr);
2939
2941 return MONTHCAL_SetFirstDayOfWeek(infoPtr, (INT)lParam);
2942
2943 case MCM_GETRANGE:
2944 return MONTHCAL_GetRange(infoPtr, (LPSYSTEMTIME)lParam);
2945
2946 case MCM_SETRANGE:
2947 return MONTHCAL_SetRange(infoPtr, (SHORT)wParam, (LPSYSTEMTIME)lParam);
2948
2949 case MCM_GETMONTHDELTA:
2950 return MONTHCAL_GetMonthDelta(infoPtr);
2951
2952 case MCM_SETMONTHDELTA:
2953 return MONTHCAL_SetMonthDelta(infoPtr, wParam);
2954
2956 return MONTHCAL_GetMaxTodayWidth(infoPtr);
2957
2959 return MONTHCAL_SetUnicodeFormat(infoPtr, (BOOL)wParam);
2960
2962 return MONTHCAL_GetUnicodeFormat(infoPtr);
2963
2965 return MONTHCAL_GetCalCount(infoPtr);
2966
2967 case WM_GETDLGCODE:
2969
2970 case WM_RBUTTONUP:
2971 return MONTHCAL_RButtonUp(infoPtr, lParam);
2972
2973 case WM_LBUTTONDOWN:
2974 return MONTHCAL_LButtonDown(infoPtr, lParam);
2975
2976 case WM_MOUSEMOVE:
2977 return MONTHCAL_MouseMove(infoPtr, lParam);
2978
2979 case WM_LBUTTONUP:
2980 return MONTHCAL_LButtonUp(infoPtr, lParam);
2981
2982 case WM_PAINT:
2983 return MONTHCAL_Paint(infoPtr, (HDC)wParam);
2984
2985 case WM_PRINTCLIENT:
2986 return MONTHCAL_PrintClient(infoPtr, (HDC)wParam, (DWORD)lParam);
2987
2988 case WM_ERASEBKGND:
2989 return MONTHCAL_EraseBkgnd(infoPtr, (HDC)wParam);
2990
2991 case WM_SETFOCUS:
2992 return MONTHCAL_SetFocus(infoPtr);
2993
2994 case WM_SIZE:
2995 return MONTHCAL_Size(infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
2996
2997 case WM_NOTIFY:
2998 return MONTHCAL_Notify(infoPtr, (NMHDR*)lParam);
2999
3000 case WM_CREATE:
3002
3003 case WM_SETFONT:
3004 return MONTHCAL_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
3005
3006 case WM_GETFONT:
3007 return MONTHCAL_GetFont(infoPtr);
3008
3009 case WM_TIMER:
3010 return MONTHCAL_Timer(infoPtr, wParam);
3011
3012 case WM_THEMECHANGED:
3013 return theme_changed (infoPtr);
3014
3015 case WM_DESTROY:
3016 return MONTHCAL_Destroy(infoPtr);
3017
3018 case WM_SYSCOLORCHANGE:
3020 return 0;
3021
3022 case WM_STYLECHANGED:
3024
3025 case WM_STYLECHANGING:
3027
3028 default:
3029 if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg))
3030 ERR( "unknown msg %04x wp=%08lx lp=%08lx\n", uMsg, wParam, lParam);
3031 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
3032 }
3033}
3034
3036void
3038{
3039 WNDCLASSW wndClass;
3040
3041 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
3042 wndClass.style = CS_GLOBALCLASS;
3044 wndClass.cbClsExtra = 0;
3045 wndClass.cbWndExtra = sizeof(MONTHCAL_INFO *);
3046 wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
3047 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
3048 wndClass.lpszClassName = MONTHCAL_CLASSW;
3049
3050 RegisterClassW(&wndClass);
3051}
3052
3054void
3056{
3058}
Arabic default style
Definition: afstyles.h:94
static int state
Definition: maze.c:121
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:71
static const char * wine_dbgstr_point(const POINT *ppt)
Definition: atltest.h:138
static const char * wine_dbgstr_rect(const RECT *prc)
Definition: atltest.h:160
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
HFONT hFont
Definition: main.c:53
#define ARRAY_SIZE(A)
Definition: main.h:33
#define FIXME(fmt,...)
Definition: debug.h:114
#define WARN(fmt,...)
Definition: debug.h:115
#define ERR(fmt,...)
Definition: debug.h:113
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
BOOL COMCTL32_IsReflectedMessage(UINT uMsg) DECLSPEC_HIDDEN
Definition: commctrl.c:1748
#define IDM_GOTODAY
Definition: comctl32.h:85
VOID COMCTL32_RefreshSysColors(void) DECLSPEC_HIDDEN
Definition: commctrl.c:1586
#define IDM_TODAY
Definition: comctl32.h:84
COMCTL32_SysColor comctl32_color
Definition: commctrl.c:82
HMODULE COMCTL32_hModule
Definition: commctrl.c:79
int selection
Definition: ctm.c:92
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static int MONTHCAL_GetDayFromPos(const MONTHCAL_INFO *infoPtr, POINT pt, INT calIdx)
Definition: monthcal.c:563
static LRESULT MONTHCAL_LButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam)
Definition: monthcal.c:2152
static LRESULT MONTHCAL_GetSelRange(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *range)
Definition: monthcal.c:1637
static LRESULT MONTHCAL_GetToday(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *today)
Definition: monthcal.c:1720
static LRESULT MONTHCAL_Timer(MONTHCAL_INFO *infoPtr, WPARAM id)
Definition: monthcal.c:2330
static LRESULT MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht)
Definition: monthcal.c:1804
#define MC_SEL_LBUTUP
Definition: monthcal.c:57
#define MC_PREVNEXTMONTHTIMER
Definition: monthcal.c:64
static LRESULT MONTHCAL_SetDayState(const MONTHCAL_INFO *infoPtr, INT months, MONTHDAYSTATE *states)
Definition: monthcal.c:1528
static LRESULT MONTHCAL_SetColor(MONTHCAL_INFO *infoPtr, UINT index, COLORREF color)
Definition: monthcal.c:1305
static LRESULT MONTHCAL_LButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam)
Definition: monthcal.c:2273
static int MONTHCAL_MonthDiff(const SYSTEMTIME *left, const SYSTEMTIME *right)
Definition: monthcal.c:208
static LRESULT theme_changed(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:2707
static LRESULT MONTHCAL_GetMaxTodayWidth(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:1448
void MONTHCAL_Unregister(void)
Definition: monthcal.c:3053
static const SYSTEMTIME max_allowed_date
Definition: monthcal.c:152
static void MONTHCAL_EditYear(MONTHCAL_INFO *infoPtr, INT calIdx)
Definition: monthcal.c:2117
static INT MONTHCAL_StyleChanging(MONTHCAL_INFO *infoPtr, WPARAM wStyleType, STYLESTRUCT *lpss)
Definition: monthcal.c:2732
static void MONTHCAL_CircleDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEMTIME *date)
Definition: monthcal.c:775
static void MONTHCAL_CopyDate(const SYSTEMTIME *from, SYSTEMTIME *to)
Definition: monthcal.c:280
static void MONTHCAL_NotifyDayState(MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:1948
static LRESULT MONTHCAL_PrintClient(MONTHCAL_INFO *infoPtr, HDC hdc, DWORD options)
Definition: monthcal.c:2459
nav_direction
Definition: monthcal.c:157
@ DIRECTION_BACKWARD
Definition: monthcal.c:158
@ DIRECTION_FORWARD
Definition: monthcal.c:159
static LRESULT CALLBACK EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: monthcal.c:2080
static BOOL MONTHCAL_ValidateDate(const SYSTEMTIME *time)
Definition: monthcal.c:249
#define MC_PREVPRESSED
Definition: monthcal.c:59
static BOOL MONTHCAL_ValidateTime(const SYSTEMTIME *time)
Definition: monthcal.c:444
static void MONTHCAL_GetDayPos(const MONTHCAL_INFO *infoPtr, const SYSTEMTIME *date, INT *col, INT *row, INT calIdx)
Definition: monthcal.c:592
#define MC_NEXTPRESSED
Definition: monthcal.c:60
static BOOL MONTHCAL_IsSelRangeValid(const MONTHCAL_INFO *infoPtr, const SYSTEMTIME *range0, const SYSTEMTIME *range1, SYSTEMTIME *adjust)
Definition: monthcal.c:400
static void MONTHCAL_NotifySelectionChange(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:169
#define MC_TODAYUPDATEDELAY
Definition: monthcal.c:62
#define DAYSTO100NSECS(days)
Definition: monthcal.c:70
static UINT fill_hittest_info(const MCHITTESTINFO *src, MCHITTESTINFO *dest)
Definition: monthcal.c:1792
static int get_localized_dayname(const MONTHCAL_INFO *infoPtr, unsigned int day, WCHAR *buff, unsigned int count)
Definition: monthcal.c:1156
#define MC_CALENDAR_PADDING
Definition: monthcal.c:67
static BOOL MONTHCAL_IsDateInValidRange(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date, BOOL fix)
Definition: monthcal.c:349
static void MONTHCAL_PaintTitle(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
Definition: monthcal.c:865
static BOOL MONTHCAL_SetDayFocus(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *st)
Definition: monthcal.c:729
static void MONTHCAL_PaintTodayTitle(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
Definition: monthcal.c:1059
static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
Definition: monthcal.c:1169
static void MONTHCAL_GetNextMonth(SYSTEMTIME *date)
Definition: monthcal.c:497
static LRESULT MONTHCAL_Create(HWND hwnd, LPCREATESTRUCTW lpcs)
Definition: monthcal.c:2761
static LRESULT MONTHCAL_RButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam)
Definition: monthcal.c:2037
static LRESULT MONTHCAL_GetMonthRange(const MONTHCAL_INFO *infoPtr, DWORD flag, SYSTEMTIME *st)
Definition: monthcal.c:672
static void MONTHCAL_GoToMonth(MONTHCAL_INFO *infoPtr, enum nav_direction direction)
Definition: monthcal.c:2007
static LRESULT MONTHCAL_SetSelRange(MONTHCAL_INFO *infoPtr, SYSTEMTIME *range)
Definition: monthcal.c:1656
static LRESULT MONTHCAL_GetMonthDelta(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:1351
#define MC_PREVNEXTMONTHDELAY
Definition: monthcal.c:61
static void MONTHCAL_GetMaxDate(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date)
Definition: monthcal.c:532
#define MCS_NOSELCHANGEONNAV
Definition: monthcal.c:55
#define MC_SEL_LBUTDOWN
Definition: monthcal.c:58
static LRESULT MONTHCAL_Notify(MONTHCAL_INFO *infoPtr, NMHDR *hdr)
Definition: monthcal.c:2850
static LRESULT WINAPI MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: monthcal.c:2883
struct MONTHCAL_INFO * LPMONTHCAL_INFO
static void MONTHCAL_UpdateSize(MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:2486
static LRESULT MONTHCAL_GetFont(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:2679
static void MONTHCAL_PaintLeadTrailMonths(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
Definition: monthcal.c:1117
static LRESULT MONTHCAL_SetFont(MONTHCAL_INFO *infoPtr, HFONT hFont, BOOL redraw)
Definition: monthcal.c:2684
static LRESULT MONTHCAL_SetMonthDelta(MONTHCAL_INFO *infoPtr, INT delta)
Definition: monthcal.c:1363
int MONTHCAL_MonthLength(int month, int year)
Definition: monthcal.c:215
#define MC_TODAYUPDATETIMER
Definition: monthcal.c:65
static void MONTHCAL_PaintButton(MONTHCAL_INFO *infoPtr, HDC hdc, enum nav_direction button)
Definition: monthcal.c:827
static LRESULT MONTHCAL_GetMaxSelCount(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:1616
static COLORREF MONTHCAL_GetColor(const MONTHCAL_INFO *infoPtr, UINT index)
Definition: monthcal.c:1296
static LRESULT MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
Definition: monthcal.c:1553
CachedBrush
Definition: monthcal.c:80
@ BrushTitle
Definition: monthcal.c:81
@ BrushBackground
Definition: monthcal.c:83
@ BrushLast
Definition: monthcal.c:84
@ BrushMonth
Definition: monthcal.c:82
static void MONTHCAL_Refresh(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
Definition: monthcal.c:1227
static LRESULT MONTHCAL_SetRange(MONTHCAL_INFO *infoPtr, SHORT limits, SYSTEMTIME *range)
Definition: monthcal.c:1454
static LRESULT MONTHCAL_GetFirstDayOfWeek(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:1375
static const WCHAR themeClass[]
Definition: monthcal.c:147
static BOOL MONTHCAL_GetDayRect(const MONTHCAL_INFO *infoPtr, const SYSTEMTIME *date, RECT *r, INT calIdx)
Definition: monthcal.c:635
static INT MONTHCAL_GetCalCount(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:163
static LRESULT MONTHCAL_GetCurSel(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
Definition: monthcal.c:1541
static void MONTHCAL_PaintFocusAndCircle(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
Definition: monthcal.c:1093
static BOOL MONTHCAL_UpdateToday(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *today)
Definition: monthcal.c:1737
static const SYSTEMTIME min_allowed_date
Definition: monthcal.c:153
static LRESULT MONTHCAL_GetMinReqRect(const MONTHCAL_INFO *infoPtr, RECT *rect)
Definition: monthcal.c:1275
static void MONTHCAL_GetMinDate(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date)
Definition: monthcal.c:509
static void MONTHCAL_GetDayRectI(const MONTHCAL_INFO *infoPtr, RECT *r, INT col, INT row, INT calIdx)
Definition: monthcal.c:622
static void MONTHCAL_Scroll(MONTHCAL_INFO *infoPtr, INT delta, BOOL keep_selection)
Definition: monthcal.c:1972
void MONTHCAL_Register(void)
Definition: monthcal.c:3035
static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEMTIME *st, int bold, const PAINTSTRUCT *ps)
Definition: monthcal.c:784
int MONTHCAL_CalculateDayOfWeek(SYSTEMTIME *date, BOOL inplace)
Definition: monthcal.c:468
static LRESULT MONTHCAL_EraseBkgnd(const MONTHCAL_INFO *infoPtr, HDC hdc)
Definition: monthcal.c:2447
static LRESULT MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
Definition: monthcal.c:2364
static BOOL MONTHCAL_GetUnicodeFormat(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:2877
static LRESULT MONTHCAL_SetToday(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *today)
Definition: monthcal.c:1759
static LRESULT MONTHCAL_SetFirstDayOfWeek(MONTHCAL_INFO *infoPtr, INT day)
Definition: monthcal.c:1403
static BOOL MONTHCAL_IsDateEqual(const SYSTEMTIME *first, const SYSTEMTIME *second)
Definition: monthcal.c:242
static LRESULT MONTHCAL_SetFocus(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:2476
static LRESULT MONTHCAL_SetMaxSelCount(MONTHCAL_INFO *infoPtr, INT max)
Definition: monthcal.c:1623
static void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to)
Definition: monthcal.c:266
static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
Definition: monthcal.c:948
static void MONTHCAL_GetPrevMonth(SYSTEMTIME *date)
Definition: monthcal.c:503
static BOOL MONTHCAL_SetUnicodeFormat(MONTHCAL_INFO *infoPtr, BOOL isUnicode)
Definition: monthcal.c:2869
LONG MONTHCAL_CompareSystemTime(const SYSTEMTIME *first, const SYSTEMTIME *second)
Definition: monthcal.c:303
static LRESULT MONTHCAL_Destroy(MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:2828
static LRESULT MONTHCAL_Size(MONTHCAL_INFO *infoPtr, int Width, int Height)
Definition: monthcal.c:2669
CachedPen
Definition: monthcal.c:73
@ PenRed
Definition: monthcal.c:74
@ PenText
Definition: monthcal.c:75
@ PenLast
Definition: monthcal.c:76
static void MONTHCAL_GetMonth(SYSTEMTIME *date, INT months)
Definition: monthcal.c:484
static INT MONTHCAL_GetCalendarFromPoint(const MONTHCAL_INFO *infoPtr, const POINT *pt)
Definition: monthcal.c:1773
static LRESULT MONTHCAL_GetRange(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *range)
Definition: monthcal.c:1514
static INT MONTHCAL_StyleChanged(MONTHCAL_INFO *infoPtr, WPARAM wStyleType, const STYLESTRUCT *lpss)
Definition: monthcal.c:2715
static void MONTHCAL_Circle(const MONTHCAL_INFO *infoPtr, HDC hdc, const RECT *r)
Definition: monthcal.c:757
struct _CALENDAR_INFO CALENDAR_INFO
static void MONTHCAL_NotifySelect(const MONTHCAL_INFO *infoPtr)
Definition: monthcal.c:189
static const SYSTEMTIME st_null
Definition: monthcal.c:150
static LRESULT MONTHCAL_Paint(MONTHCAL_INFO *infoPtr, HDC hdc_paint)
Definition: monthcal.c:2428
static LONG MONTHCAL_CompareMonths(const SYSTEMTIME *first, const SYSTEMTIME *second)
Definition: monthcal.c:313
static LONG MONTHCAL_CompareDate(const SYSTEMTIME *first, const SYSTEMTIME *second)
Definition: monthcal.c:325
#define CALLBACK
Definition: compat.h:35
#define lstrlenW
Definition: compat.h:750
static DOUBLE day(DOUBLE time)
Definition: date.c:117
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:158
LONG WINAPI CompareFileTime(IN CONST FILETIME *lpFileTime1, IN CONST FILETIME *lpFileTime2)
Definition: time.c:106
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:286
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: locale.c:1665
HRESULT WINAPI DrawThemeBackground(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect)
Definition: draw.c:128
HTHEME WINAPI OpenThemeData(HWND hwnd, LPCWSTR classlist)
Definition: system.c:835
HTHEME WINAPI GetWindowTheme(HWND hwnd)
Definition: system.c:851
HRESULT WINAPI CloseThemeData(HTHEME hTheme)
Definition: system.c:950
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
static const WCHAR month[12][4]
Definition: session.c:2150
#define pt(x, y)
Definition: drawing.c:79
#define RGB(r, g, b)
Definition: precomp.h:71
#define WM_APP
Definition: eventvwr.h:73
static unsigned char buff[32768]
Definition: fatten.c:17
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
pKey DeleteObject()
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizeiptr size
Definition: glext.h:5919
GLenum src
Definition: glext.h:6340
GLuint color
Definition: glext.h:6243
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLdouble GLdouble right
Definition: glext.h:10859
GLenum GLint * range
Definition: glext.h:7539
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLint left
Definition: glext.h:7726
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
const GLint * first
Definition: glext.h:5794
const GLfloat * m
Definition: glext.h:10848
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static const struct newhuff ht[]
Definition: huffman.h:296
char hdr[14]
Definition: iptest.cpp:33
#define debugstr_w
Definition: kernel32.h:32
INT WINAPI GetDateFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpDateStr, INT cchOut)
Definition: lcformat.c:993
GLint dy
Definition: linetemp.h:97
GLint dx
Definition: linetemp.h:97
__u16 date
Definition: mkdosfs.c:8
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
HDC hdc
Definition: main.c:9
DWORD button
Definition: button.c:166
static HDC
Definition: imagelist.c:92
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
#define cmp(status, error)
Definition: error.c:114
static char * dest
Definition: rtl.c:135
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
WCHAR strW[12]
Definition: clipboard.c:2029
static HTHEME(WINAPI *pOpenThemeDataEx)(HWND
Definition: mk_font.cpp:20
unsigned int UINT
Definition: ndis.h:50
#define LOCALE_USER_DEFAULT
INT WINAPI DrawTextW(HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags)
Definition: defwnd.c:16
#define OBJ_FONT
Definition: objidl.idl:1414
#define LOWORD(l)
Definition: pedump.c:82
#define WS_CHILD
Definition: pedump.c:617
#define ES_READONLY
Definition: pedump.c:675
#define WS_VISIBLE
Definition: pedump.c:620
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
#define WS_DISABLED
Definition: pedump.c:621
static char title[]
Definition: ps.c:92
#define NM_RELEASEDCAPTURE
Definition: commctrl.h:141
DWORD * LPMONTHDAYSTATE
Definition: commctrl.h:4180
#define UPDOWN_CLASSW
Definition: commctrl.h:2119
#define MCN_GETDAYSTATE
Definition: commctrl.h:4301
#define MONTHCAL_CLASSW
Definition: commctrl.h:4175
#define MCSC_MONTHBK
Definition: commctrl.h:4211
#define MCM_GETRANGE
Definition: commctrl.h:4262
#define MCS_NOTRAILINGDATES
Definition: commctrl.h:4312
#define MCHT_TITLE
Definition: commctrl.h:4236
#define GDTR_MAX
Definition: commctrl.h:4457
#define MCM_SETMAXSELCOUNT
Definition: commctrl.h:4190
#define MCM_GETUNICODEFORMAT
Definition: commctrl.h:4278
#define MCHT_CALENDARBK
Definition: commctrl.h:4251
#define MCM_HITTEST
Definition: commctrl.h:4218
#define MCM_SETRANGE
Definition: commctrl.h:4264
#define MCHT_TITLEMONTH
Definition: commctrl.h:4246
#define GDTR_MIN
Definition: commctrl.h:4456
#define MCHT_CALENDARDAY
Definition: commctrl.h:4255
#define MCSC_TITLEBK
Definition: commctrl.h:4209
#define UDS_SETBUDDYINT
Definition: commctrl.h:2132
#define WC_EDITW
Definition: commctrl.h:4687
#define UDM_SETPOS
Definition: commctrl.h:2143
#define MCHT_TITLEBTNPREV
Definition: commctrl.h:4249
#define MCM_SETDAYSTATE
Definition: commctrl.h:4198
#define MCM_GETCALENDARCOUNT
Definition: commctrl.h:4274
#define MCS_NOTODAYCIRCLE
Definition: commctrl.h:4310
#define MCS_MULTISELECT
Definition: commctrl.h:4308
#define MCM_GETMONTHRANGE
Definition: commctrl.h:4196
#define MCM_GETMONTHDELTA
Definition: commctrl.h:4266
#define MCM_GETTODAY
Definition: commctrl.h:4216
#define MCN_SELCHANGE
Definition: commctrl.h:4291
#define MCHT_CALENDARDATENEXT
Definition: commctrl.h:4253
#define MCM_GETCURSEL
Definition: commctrl.h:4184
#define UDS_NOTHOUSANDS
Definition: commctrl.h:2138
#define MCSC_TITLETEXT
Definition: commctrl.h:4210
#define UDM_SETRANGE
Definition: commctrl.h:2141
#define MCS_NOTODAY
Definition: commctrl.h:4311
#define MCM_GETFIRSTDAYOFWEEK
Definition: commctrl.h:4260
#define MCM_SETUNICODEFORMAT
Definition: commctrl.h:4276
#define GMR_VISIBLE
Definition: commctrl.h:4315
#define MCM_GETCOLOR
Definition: commctrl.h:4204
#define MCM_SETFIRSTDAYOFWEEK
Definition: commctrl.h:4258
#define UDS_ARROWKEYS
Definition: commctrl.h:2136
#define MCS_DAYSTATE
Definition: commctrl.h:4307
#define MCHITTESTINFO_V1_SIZE
Definition: commctrl.h:4234
#define MCM_SETCOLOR
Definition: commctrl.h:4202
#define MCHT_TODAYLINK
Definition: commctrl.h:4238
#define MCSC_TEXT
Definition: commctrl.h:4208
DWORD MONTHDAYSTATE
Definition: commctrl.h:4180
#define MCHT_CALENDARDATE
Definition: commctrl.h:4252
#define UDM_SETBUDDY
Definition: commctrl.h:2145
#define MCHT_TITLEBTNNEXT
Definition: commctrl.h:4248
#define MCS_SHORTDAYSOFWEEK
Definition: commctrl.h:4313
#define MCM_GETMAXTODAYWIDTH
Definition: commctrl.h:4270
#define MCM_GETMAXSELCOUNT
Definition: commctrl.h:4188
#define GMR_DAYSTATE
Definition: commctrl.h:4316
#define MCM_GETSELRANGE
Definition: commctrl.h:4192
#define MCM_SETSELRANGE
Definition: commctrl.h:4194
#define MCHT_CALENDARDATEPREV
Definition: commctrl.h:4254
#define MCM_SETCURSEL
Definition: commctrl.h:4186
#define UDN_DELTAPOS
Definition: commctrl.h:2169
#define MCM_SETMONTHDELTA
Definition: commctrl.h:4268
#define MCSC_TRAILINGTEXT
Definition: commctrl.h:4212
#define MCM_GETMINREQRECT
Definition: commctrl.h:4200
#define MCHT_CALENDARWEEKNUM
Definition: commctrl.h:4256
#define MCHT_TITLEYEAR
Definition: commctrl.h:4247
#define MCN_SELECT
Definition: commctrl.h:4305
#define MCS_WEEKNUMBERS
Definition: commctrl.h:4309
#define MCSC_BACKGROUND
Definition: commctrl.h:4207
#define MCM_SETTODAY
Definition: commctrl.h:4214
void redraw(int x, int y, int cx, int cy)
Definition: qtewin.cpp:1248
static unsigned __int64 next
Definition: rand_nt.c:6
#define atoiW(s)
Definition: unicode.h:60
#define strstrW(d, s)
Definition: unicode.h:38
#define strlenW(s)
Definition: unicode.h:34
#define strncmpW(s1, s2, n)
Definition: unicode.h:42
#define WM_PRINTCLIENT
Definition: richedit.h:70
#define WM_NOTIFY
Definition: richedit.h:61
static FILE * client
Definition: client.c:41
RECT text_rect
Definition: sndrec32.cpp:77
#define TRACE(s)
Definition: solgame.cpp:4
CardRegion * from
Definition: spigame.cpp:19
& rect
Definition: startmenu.cpp:1413
COLORREF clrWindow
Definition: comctl32.h:176
COLORREF clrActiveCaption
Definition: comctl32.h:179
COLORREF clrGrayText
Definition: comctl32.h:178
COLORREF clrWindowText
Definition: comctl32.h:177
LONG lfWeight
Definition: dimm.idl:63
SYSTEMTIME st
Definition: commctrl.h:4225
int height_increment
Definition: monthcal.c:112
DWORD dwStyle
Definition: monthcal.c:103
CALENDAR_INFO * calendars
Definition: monthcal.c:143
HPEN pens[PenLast]
Definition: monthcal.c:107
HWND hWndYearEdit
Definition: monthcal.c:139
HBRUSH brushes[BrushLast]
Definition: monthcal.c:106
SYSTEMTIME maxSel
Definition: monthcal.c:129
SYSTEMTIME minSel
Definition: monthcal.c:128
HWND hwndSelf
Definition: monthcal.c:102
BOOL firstDaySet
Definition: monthcal.c:118
SYSTEMTIME focusedSel
Definition: monthcal.c:130
SYSTEMTIME todaysDate
Definition: monthcal.c:123
SYSTEMTIME minDate
Definition: monthcal.c:132
HFONT hFont
Definition: monthcal.c:109
HWND hWndYearUpDown
Definition: monthcal.c:140
DWORD rangeValid
Definition: monthcal.c:131
int width_increment
Definition: monthcal.c:113
RECT titlebtnprev
Definition: monthcal.c:136
HFONT hBoldFont
Definition: monthcal.c:110
INT maxSelCount
Definition: monthcal.c:127
RECT todayrect
Definition: monthcal.c:137
RECT titlebtnnext
Definition: monthcal.c:135
SYSTEMTIME firstSel
Definition: monthcal.c:126
int textHeight
Definition: monthcal.c:111
BOOL todaySet
Definition: monthcal.c:124
HWND hwndNotify
Definition: monthcal.c:138
WNDPROC EditWndProc
Definition: monthcal.c:141
BOOL isUnicode
Definition: monthcal.c:120
MONTHDAYSTATE * monthdayState
Definition: monthcal.c:122
SYSTEMTIME maxDate
Definition: monthcal.c:133
COLORREF colors[MCSC_TRAILINGTEXT+1]
Definition: monthcal.c:105
RECT weeknums
Definition: monthcal.c:95
RECT titlemonth
Definition: monthcal.c:91
RECT titleyear
Definition: monthcal.c:92
SYSTEMTIME month
Definition: monthcal.c:97
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
int iDelta
Definition: commctrl.h:2166
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
WORD wYear
Definition: winbase.h:905
WORD wMonth
Definition: winbase.h:906
WORD wHour
Definition: winbase.h:909
WORD wSecond
Definition: winbase.h:911
WORD wMinute
Definition: winbase.h:910
WORD wDay
Definition: winbase.h:908
WORD wDayOfWeek
Definition: winbase.h:907
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
struct _ULARGE_INTEGER::@4142 u
LPCWSTR lpszClassName
Definition: winuser.h:3185
HBRUSH hbrBackground
Definition: winuser.h:3183
int cbClsExtra
Definition: winuser.h:3178
UINT style
Definition: winuser.h:3176
WNDPROC lpfnWndProc
Definition: winuser.h:3177
int cbWndExtra
Definition: winuser.h:3179
HCURSOR hCursor
Definition: winuser.h:3182
Definition: ps.c:97
LPMONTHDAYSTATE prgDayState
Definition: commctrl.h:4298
SYSTEMTIME stStart
Definition: commctrl.h:4295
UINT_PTR idFrom
Definition: winuser.h:3158
UINT code
Definition: winuser.h:3159
HWND hwndFrom
Definition: winuser.h:3157
SYSTEMTIME stSelStart
Definition: commctrl.h:4287
SYSTEMTIME stSelEnd
Definition: commctrl.h:4288
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
DWORD styleNew
Definition: winuser.h:3693
DWORD styleOld
Definition: winuser.h:3692
Definition: time.h:68
#define max(a, b)
Definition: svc.c:63
#define GWLP_WNDPROC
Definition: treelist.c:66
uint32_t DWORD_PTR
Definition: typedefs.h:65
int32_t INT
Definition: typedefs.h:58
#define MAKELONG(a, b)
Definition: typedefs.h:249
#define HIWORD(l)
Definition: typedefs.h:247
_In_ HFONT _Out_ PUINT _Out_ PUINT Width
Definition: font.h:89
_In_ HFONT _Out_ PUINT Height
Definition: font.h:88
@ ABS_RIGHTNORMAL
Definition: vsstyle.h:1103
@ ABS_RIGHTDISABLED
Definition: vsstyle.h:1106
@ ABS_LEFTDISABLED
Definition: vsstyle.h:1102
@ ABS_RIGHTPRESSED
Definition: vsstyle.h:1105
@ ABS_LEFTNORMAL
Definition: vsstyle.h:1099
@ ABS_LEFTPRESSED
Definition: vsstyle.h:1101
@ SBP_ARROWBTN
Definition: vsstyle.h:1076
#define ZeroMemory
Definition: winbase.h:1712
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
DWORD COLORREF
Definition: windef.h:300
#define WINAPI
Definition: msvc.h:6
BOOL WINAPI GetTextMetricsW(_In_ HDC, _Out_ LPTEXTMETRICW)
Definition: text.c:221
HGDIOBJ WINAPI GetStockObject(_In_ int)
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
int WINAPI GetClipBox(_In_ HDC, _Out_ LPRECT)
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:999
#define FW_BOLD
Definition: wingdi.h:378
HGDIOBJ WINAPI GetCurrentObject(_In_ HDC, _In_ UINT)
Definition: dc.c:428
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
BOOL WINAPI MoveToEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
#define TRANSPARENT
Definition: wingdi.h:950
COLORREF WINAPI GetBkColor(_In_ HDC)
Definition: dc.c:978
#define NULL_BRUSH
Definition: wingdi.h:901
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
BOOL WINAPI Rectangle(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int)
HFONT WINAPI CreateFontIndirectW(_In_ const LOGFONTW *)
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1056
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:918
HBRUSH WINAPI CreateSolidBrush(_In_ COLORREF)
HPEN WINAPI CreatePen(_In_ int, _In_ int, _In_ COLORREF)
BOOL WINAPI LineTo(_In_ HDC, _In_ int, _In_ int)
#define PS_SOLID
Definition: wingdi.h:586
BOOL WINAPI GetTextExtentPoint32W(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpString, _In_ int c, _Out_ LPSIZE psizl)
#define LOCALE_IFIRSTWEEKOFYEAR
Definition: winnls.h:76
#define LOCALE_SMONTHNAME1
Definition: winnls.h:91
#define LOCALE_SABBREVMONTHNAME1
Definition: winnls.h:104
#define LOCALE_SABBREVDAYNAME1
Definition: winnls.h:84
#define LOCALE_IFIRSTDAYOFWEEK
Definition: winnls.h:75
DWORD LCTYPE
Definition: winnls.h:517
#define DATE_SHORTDATE
Definition: winnls.h:196
#define WM_PAINT
Definition: winuser.h:1620
HWND WINAPI SetCapture(_In_ HWND hWnd)
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define WM_ERASEBKGND
Definition: winuser.h:1625
BOOL WINAPI IsWindow(_In_opt_ HWND)
HMENU WINAPI CreatePopupMenu(void)
Definition: menu.c:838
#define WM_CLOSE
Definition: winuser.h:1621
#define DFC_SCROLL
Definition: winuser.h:475
#define GetWindowLongPtrW
Definition: winuser.h:4829
#define COLOR_WINDOW
Definition: winuser.h:918
BOOL WINAPI ReleaseCapture(void)
Definition: message.c:2890
#define DT_CENTER
Definition: winuser.h:527
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI AdjustWindowRect(_Inout_ LPRECT, _In_ DWORD, _In_ BOOL)
#define TPM_RIGHTBUTTON
Definition: winuser.h:2380
#define WM_CREATE
Definition: winuser.h:1608
#define DLGC_WANTCHARS
Definition: winuser.h:2618
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
BOOL WINAPI DrawFrameControl(_In_ HDC, _Inout_ LPRECT, _In_ UINT, _In_ UINT)
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
#define WM_SIZE
Definition: winuser.h:1611
#define PRF_ERASEBKGND
Definition: winuser.h:2526
LONG WINAPI GetWindowLongW(_In_ HWND, _In_ int)
#define DT_SINGLELINE
Definition: winuser.h:540
#define DLGC_WANTALLKEYS
Definition: winuser.h:2612
#define DFCS_INACTIVE
Definition: winuser.h:502
#define MF_STRING
Definition: winuser.h:138
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
#define IDC_ARROW
Definition: winuser.h:687
#define WM_RBUTTONUP
Definition: winuser.h:1780
#define WM_SETFOCUS
Definition: winuser.h:1613
#define WM_MOUSEMOVE
Definition: winuser.h:1775
#define TPM_NONOTIFY
Definition: winuser.h:2386
#define WM_LBUTTONDOWN
Definition: winuser.h:1776
#define WM_SYSCOLORCHANGE
Definition: winuser.h:1626
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2136
#define WM_GETFONT
Definition: winuser.h:1651
BOOL WINAPI ClientToScreen(_In_ HWND, _Inout_ LPPOINT)
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
BOOL WINAPI PtInRect(_In_ LPCRECT, _In_ POINT)
#define DT_LEFT
Definition: winuser.h:534
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define VK_RETURN
Definition: winuser.h:2201
HWND WINAPI SetFocus(_In_opt_ HWND)
#define MF_ENABLED
Definition: winuser.h:128
#define WM_SETFONT
Definition: winuser.h:1650
#define WM_TIMER
Definition: winuser.h:1742
HWND WINAPI CreateWindowExW(_In_ DWORD dwExStyle, _In_opt_ LPCWSTR lpClassName, _In_opt_ LPCWSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
#define TPM_LEFTALIGN
Definition: winuser.h:2377
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define DLGC_WANTARROWS
Definition: winuser.h:2610
BOOL WINAPI IntersectRect(_Out_ LPRECT, _In_ LPCRECT, _In_ LPCRECT)
HDC WINAPI GetDC(_In_opt_ HWND)
#define PRF_CLIENT
Definition: winuser.h:2525
#define WM_LBUTTONUP
Definition: winuser.h:1777
BOOL WINAPI SetRectEmpty(_Out_ LPRECT)
#define DT_VCENTER
Definition: winuser.h:543
HWND WINAPI GetParent(_In_ HWND)
#define CS_GLOBALCLASS
Definition: winuser.h:652
#define GWLP_ID
Definition: winuser.h:860
#define PRF_CHECKVISIBLE
Definition: winuser.h:2523
#define WM_USER
Definition: winuser.h:1895
BOOL WINAPI OffsetRect(_Inout_ LPRECT, _In_ int, _In_ int)
BOOL WINAPI TrackPopupMenu(_In_ HMENU, _In_ UINT, _In_ int, _In_ int, _Reserved_ int, _In_ HWND, _Reserved_ LPCRECT)
#define WM_DESTROY
Definition: winuser.h:1609
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
#define WM_KEYDOWN
Definition: winuser.h:1715
#define DFCS_SCROLLLEFT
Definition: winuser.h:491
BOOL WINAPI DrawFocusRect(_In_ HDC, _In_ LPCRECT)
#define DFCS_SCROLLRIGHT
Definition: winuser.h:492
BOOL WINAPI InvalidateRect(_In_opt_ HWND, _In_opt_ LPCRECT, _In_ BOOL)
LRESULT(CALLBACK * WNDPROC)(HWND, UINT, WPARAM, LPARAM)
Definition: winuser.h:2906
#define TPM_RETURNCMD
Definition: winuser.h:2387
#define DT_CALCRECT
Definition: winuser.h:526
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
BOOL WINAPI UnionRect(_Out_ LPRECT, _In_ LPCRECT, _In_ LPCRECT)
#define SetWindowLongPtrW
Definition: winuser.h:5346
LRESULT WINAPI CallWindowProcW(_In_ WNDPROC, _In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define GWL_STYLE
Definition: winuser.h:852
#define VK_ESCAPE
Definition: winuser.h:2214
BOOL WINAPI IsWindowVisible(_In_ HWND)
#define DFCS_PUSHED
Definition: winuser.h:503
#define WM_KILLFOCUS
Definition: winuser.h:1614
#define WM_GETDLGCODE
Definition: winuser.h:1689
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI AppendMenuW(_In_ HMENU, _In_ UINT, _In_ UINT_PTR, _In_opt_ LPCWSTR)
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184