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