Commit 1224cc46 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

comctl32/monthcal: Fix timestamp storing on MCM_SETRANGE/MCM_SETSELRANGE.

parent 211a55b8
......@@ -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;
}
......
......@@ -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");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment