Nikolay Sivov : comctl32/monthcal: Fix timestamp storing on MCM_SETRANGE/ MCM_SETSELRANGE.
Alexandre Julliard
julliard at winehq.org
Mon Sep 28 11:54:38 CDT 2009
Module: wine
Branch: master
Commit: 1224cc461dc95608dfce31479cc06b503d3f32d2
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1224cc461dc95608dfce31479cc06b503d3f32d2
Author: Nikolay Sivov <bunglehead at gmail.com>
Date: Sat Sep 26 20:06:48 2009 +0400
comctl32/monthcal: Fix timestamp storing on MCM_SETRANGE/MCM_SETSELRANGE.
---
dlls/comctl32/monthcal.c | 49 ++++++++++++++++++++++++++++++++-------
dlls/comctl32/tests/monthcal.c | 30 +++++++++++++++++++++++-
2 files changed, 69 insertions(+), 10 deletions(-)
diff --git a/dlls/comctl32/monthcal.c b/dlls/comctl32/monthcal.c
index 3aa0693..1389622 100644
--- a/dlls/comctl32/monthcal.c
+++ b/dlls/comctl32/monthcal.c
@@ -160,17 +160,35 @@ static inline BOOL MONTHCAL_IsDateEqual(const SYSTEMTIME *first, const SYSTEMTIM
(first->wDay == second->wDay);
}
-/* make sure that time is valid */
-static BOOL MONTHCAL_ValidateTime(SYSTEMTIME time)
+/* make sure that date fields are valid */
+static BOOL MONTHCAL_ValidateDate(const SYSTEMTIME *time)
{
- if(time.wMonth < 1 || time.wMonth > 12 ) return FALSE;
- if(time.wDayOfWeek > 6) return FALSE;
- if(time.wDay > MONTHCAL_MonthLength(time.wMonth, time.wYear))
+ if(time->wMonth < 1 || time->wMonth > 12 ) return FALSE;
+ if(time->wDayOfWeek > 6) return FALSE;
+ if(time->wDay > MONTHCAL_MonthLength(time->wMonth, time->wYear))
return FALSE;
return TRUE;
}
+/* Used in MCM_SETRANGE/MCM_SETSELRANGE to determine resulting time part.
+ Milliseconds are intentionaly not validated. */
+static BOOL MONTHCAL_ValidateTime(const SYSTEMTIME *time)
+{
+ if((time->wHour > 24) || (time->wMinute > 59) || (time->wSecond > 59))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/* Copies timestamp part only. Milliseconds are intentionaly not copied
+ cause it matches required behaviour for current use of this helper */
+static void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to)
+{
+ to->wHour = from->wHour;
+ to->wMinute = from->wMinute;
+ to->wSecond = from->wSecond;
+}
/* Note:Depending on DST, this may be offset by a day.
Need to find out if we're on a DST place & adjust the clock accordingly.
@@ -908,17 +926,23 @@ MONTHCAL_SetRange(MONTHCAL_INFO *infoPtr, SHORT limits, SYSTEMTIME *range)
TRACE("%x %p\n", limits, range);
- if ((limits & GDTR_MIN && !MONTHCAL_ValidateTime(range[0])) ||
- (limits & GDTR_MAX && !MONTHCAL_ValidateTime(range[1])))
+ if ((limits & GDTR_MIN && !MONTHCAL_ValidateDate(&range[0])) ||
+ (limits & GDTR_MAX && !MONTHCAL_ValidateDate(&range[1])))
return FALSE;
if (limits & GDTR_MIN)
{
+ if (!MONTHCAL_ValidateTime(&range[0]))
+ MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[0]);
+
infoPtr->minDate = range[0];
infoPtr->rangeValid |= GDTR_MIN;
}
if (limits & GDTR_MAX)
{
+ if (!MONTHCAL_ValidateTime(&range[1]))
+ MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[1]);
+
infoPtr->maxDate = range[1];
infoPtr->rangeValid |= GDTR_MAX;
}
@@ -1003,7 +1027,7 @@ MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
if(!curSel) return FALSE;
if(infoPtr->dwStyle & MCS_MULTISELECT) return FALSE;
- if(!MONTHCAL_ValidateTime(*curSel)) return FALSE;
+ if(!MONTHCAL_ValidateDate(curSel)) return FALSE;
infoPtr->minSel = *curSel;
infoPtr->maxSel = *curSel;
@@ -1067,8 +1091,15 @@ MONTHCAL_SetSelRange(MONTHCAL_INFO *infoPtr, SYSTEMTIME *range)
if(infoPtr->dwStyle & MCS_MULTISELECT)
{
- infoPtr->maxSel = range[1];
+ /* adjust timestamps */
+ if(!MONTHCAL_ValidateTime(&range[0]))
+ MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[0]);
+ if(!MONTHCAL_ValidateTime(&range[1]))
+ MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[1]);
+
infoPtr->minSel = range[0];
+ infoPtr->maxSel = range[1];
+
TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
return TRUE;
}
diff --git a/dlls/comctl32/tests/monthcal.c b/dlls/comctl32/tests/monthcal.c
index e5282ff..109d8a8 100644
--- a/dlls/comctl32/tests/monthcal.c
+++ b/dlls/comctl32/tests/monthcal.c
@@ -322,7 +322,7 @@ static const struct message destroy_parent_seq[] = {
static void test_monthcal(void)
{
HWND hwnd;
- SYSTEMTIME st[2], st1[2];
+ SYSTEMTIME st[2], st1[2], today;
int res, month_range;
hwnd = CreateWindowA(MONTHCAL_CLASSA, "MonthCal", WS_POPUP | WS_VISIBLE, CW_USEDEFAULT,
@@ -354,13 +354,41 @@ static void test_monthcal(void)
GetSystemTime(&st[0]);
st[1] = st[0];
+ SendMessage(hwnd, MCM_GETTODAY, 0, (LPARAM)&today);
+
/* Invalid date/time */
st[0].wYear = 2000;
/* Time should not matter */
st[1].wHour = st[1].wMinute = st[1].wSecond = 70;
+ st[1].wMilliseconds = 1200;
ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set MAX limit\n");
+ /* invalid timestamp is written back with today data and msecs untouched */
+ expect(today.wHour, st[1].wHour);
+ expect(today.wMinute, st[1].wMinute);
+ expect(today.wSecond, st[1].wSecond);
+ expect(1200, st[1].wMilliseconds);
+
ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "No limits should be set\n");
ok(st1[0].wYear != 2000, "Lover limit changed\n");
+ /* invalid timestamp should be replaced with today data, except msecs */
+ expect(today.wHour, st1[1].wHour);
+ expect(today.wMinute, st1[1].wMinute);
+ expect(today.wSecond, st1[1].wSecond);
+ expect(1200, st1[1].wMilliseconds);
+
+ /* Invalid date/time with invalid milliseconds only */
+ GetSystemTime(&st[0]);
+ st[1] = st[0];
+ /* Time should not matter */
+ st[1].wMilliseconds = 1200;
+ ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set MAX limit\n");
+ /* invalid milliseconds field doesn't lead to invalid timestamp */
+ expect(st[0].wHour, st[1].wHour);
+ expect(st[0].wMinute, st[1].wMinute);
+ expect(st[0].wSecond, st[1].wSecond);
+ expect(1200, st[1].wMilliseconds);
+
+ GetSystemTime(&st[0]);
st[1].wMonth = 0;
ok(!SendMessage(hwnd, MCM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st), "Should have failed to set limits\n");
More information about the wine-cvs
mailing list