[PATCH 04/10] Use true date comparison on multiselection, not only the day is valuable
Nikolay Sivov
bunglehead at gmail.com
Sun Oct 4 14:17:07 CDT 2009
---
dlls/comctl32/monthcal.c | 133 ++++++++++++++++++++++++++++++++++------------
1 files changed, 98 insertions(+), 35 deletions(-)
diff --git a/dlls/comctl32/monthcal.c b/dlls/comctl32/monthcal.c
index a54cba7..2078efc 100644
--- a/dlls/comctl32/monthcal.c
+++ b/dlls/comctl32/monthcal.c
@@ -71,6 +71,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(monthcal);
#define countof(arr) (sizeof(arr)/sizeof(arr[0]))
+/* convert from days to 100 nanoseconds unit - used as FILETIME unit */
+#define DAYSTO100NSECS(days) (((ULONGLONG)(days))*24*60*60*10000000)
+
typedef struct
{
HWND hwndSelf;
@@ -97,7 +100,7 @@ typedef struct
MONTHDAYSTATE *monthdayState;
SYSTEMTIME todaysDate;
int status; /* See MC_SEL flags */
- int firstSelDay; /* first selected day */
+ SYSTEMTIME firstSel; /* first selected day */
INT maxSelCount;
SYSTEMTIME minSel;
SYSTEMTIME maxSel;
@@ -1108,7 +1111,6 @@ MONTHCAL_GetCurSel(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
}
/* FIXME: if the specified date is not visible, make it visible */
-/* FIXME: redraw? */
static LRESULT
MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
{
@@ -1126,6 +1128,7 @@ MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
infoPtr->curSel = *curSel;
+ /* FIXME: it's possible to reduce rectangle here */
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return TRUE;
@@ -1181,15 +1184,28 @@ MONTHCAL_SetSelRange(MONTHCAL_INFO *infoPtr, SYSTEMTIME *range)
if(infoPtr->dwStyle & MCS_MULTISELECT)
{
+ SYSTEMTIME old_range[2];
+
/* adjust timestamps */
if(!MONTHCAL_ValidateTime(&range[0]))
MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[0]);
if(!MONTHCAL_ValidateTime(&range[1]))
MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[1]);
+ old_range[0] = infoPtr->minSel;
+ old_range[1] = infoPtr->maxSel;
+
infoPtr->minSel = range[0];
infoPtr->maxSel = range[1];
+ /* redraw if bounds changed */
+ /* FIXME: no actual need to redraw everything */
+ if(!MONTHCAL_IsDateEqual(&old_range[0], &range[0]) ||
+ !MONTHCAL_IsDateEqual(&old_range[1], &range[1]))
+ {
+ InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
+ }
+
TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
return TRUE;
}
@@ -1566,7 +1582,7 @@ MONTHCAL_LButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam)
}
case MCHT_TODAYLINK:
{
- infoPtr->firstSelDay = infoPtr->todaysDate.wDay;
+ infoPtr->firstSel = infoPtr->todaysDate;
infoPtr->curSel = infoPtr->todaysDate;
infoPtr->minSel = infoPtr->todaysDate;
infoPtr->maxSel = infoPtr->todaysDate;
@@ -1580,7 +1596,18 @@ MONTHCAL_LButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam)
case MCHT_CALENDARDATEPREV:
case MCHT_CALENDARDATE:
{
- infoPtr->firstSelDay = ht.st.wDay;
+ infoPtr->firstSel = ht.st;
+
+ if(infoPtr->dwStyle & MCS_MULTISELECT)
+ {
+ SYSTEMTIME st[2];
+
+ st[0] = st[1] = ht.st;
+
+ /* clear selection range */
+ MONTHCAL_SetSelRange(infoPtr, st);
+ }
+
infoPtr->status = MC_SEL_LBUTDOWN;
MONTHCAL_SetDayFocus(infoPtr, &ht.st);
return 0;
@@ -1634,12 +1661,17 @@ MONTHCAL_LButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam)
(hit == MCHT_CALENDARDATEPREV) ||
(hit == MCHT_CALENDARDATE))
{
- SYSTEMTIME st[2], sel = infoPtr->curSel;
+ SYSTEMTIME sel = infoPtr->curSel;
- st[0] = st[1] = ht.st;
- MONTHCAL_SetSelRange(infoPtr, st);
- /* will be invalidated here */
- MONTHCAL_SetCurSel(infoPtr, &st[0]);
+ if(!(infoPtr->dwStyle & MCS_MULTISELECT))
+ {
+ SYSTEMTIME st[2];
+
+ st[0] = st[1] = ht.st;
+ MONTHCAL_SetSelRange(infoPtr, st);
+ /* will be invalidated here */
+ MONTHCAL_SetCurSel(infoPtr, &st[0]);
+ }
/* send MCN_SELCHANGE only if new date selected */
if (!MONTHCAL_IsDateEqual(&sel, &ht.st))
@@ -1691,8 +1723,8 @@ static LRESULT
MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
{
MCHITTESTINFO ht;
- SYSTEMTIME old_focused;
- int selday, hit;
+ SYSTEMTIME old_focused, st_ht;
+ INT hit;
RECT r;
if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0;
@@ -1711,47 +1743,78 @@ MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
return 0;
}
- selday = ht.st.wDay;
+ st_ht = ht.st;
old_focused = infoPtr->focusedSel;
MONTHCAL_SetDayFocus(infoPtr, &ht.st);
MONTHCAL_CalcPosFromDay(infoPtr, ht.st.wDay, ht.st.wMonth, &r);
if(infoPtr->dwStyle & MCS_MULTISELECT) {
- SYSTEMTIME selArray[2];
+ SYSTEMTIME st[2];
+ FILETIME ft_ht, ft_first;
+ ULARGE_INTEGER ul_ht, ul_first, ul_diff;
int i;
+ LONG cmp;
+
+ MONTHCAL_GetSelRange(infoPtr, st);
+ i = MONTHCAL_IsDateEqual(&infoPtr->firstSel, &st[0]) ? 1 : 0;
+
+ SystemTimeToFileTime(&st_ht, &ft_ht);
+ SystemTimeToFileTime(&infoPtr->firstSel, &ft_first);
+
+ cmp = CompareFileTime(&ft_ht, &ft_first);
+
+ if(MONTHCAL_IsDateEqual(&infoPtr->firstSel, &st[1])) {
+ /* If we're still at the first selected date and range is empty, return.
+ If range isn't empty we should change range to a singel firstSel */
+ if(MONTHCAL_IsDateEqual(&infoPtr->firstSel, &st_ht) &&
+ MONTHCAL_IsDateEqual(&st[0], &st[1])) goto done;
- MONTHCAL_GetSelRange(infoPtr, selArray);
- i = 0;
- if(infoPtr->firstSelDay==selArray[0].wDay) i=1;
- TRACE("oldRange:%d %d %d %d\n", infoPtr->firstSelDay, selArray[0].wDay, selArray[1].wDay, i);
- if(infoPtr->firstSelDay==selArray[1].wDay) {
- /* 1st time we get here: selArray[0]=selArray[1]) */
- /* if we're still at the first selected date, return */
- if(infoPtr->firstSelDay==selday) goto done;
- if(selday<infoPtr->firstSelDay) i = 0;
+ /* new selected date is earlier */
+ if(cmp == -1) i = 0;
}
- if(abs(infoPtr->firstSelDay - selday) >= infoPtr->maxSelCount) {
- if(selday>infoPtr->firstSelDay)
- selday = infoPtr->firstSelDay + infoPtr->maxSelCount;
+ ul_ht.LowPart = ft_ht.dwLowDateTime;
+ ul_ht.HighPart = ft_ht.dwHighDateTime;
+ ul_first.LowPart = ft_first.dwLowDateTime;
+ ul_first.HighPart = ft_first.dwHighDateTime;
+
+ /* new selected date is later */
+ if(cmp == 1)
+ ul_diff.QuadPart = ul_ht.QuadPart - ul_first.QuadPart;
+ else
+ ul_diff.QuadPart = -ul_ht.QuadPart + ul_first.QuadPart;
+
+ if(ul_diff.QuadPart >= DAYSTO100NSECS(infoPtr->maxSelCount)) {
+ if(cmp == 1)
+ ul_ht.QuadPart = ul_first.QuadPart + DAYSTO100NSECS(infoPtr->maxSelCount - 1);
else
- selday = infoPtr->firstSelDay - infoPtr->maxSelCount;
+ ul_ht.QuadPart = ul_first.QuadPart - DAYSTO100NSECS(infoPtr->maxSelCount - 1);
+
+ ft_ht.dwLowDateTime = ul_ht.LowPart;
+ ft_ht.dwHighDateTime = ul_ht.HighPart;
+ FileTimeToSystemTime(&ft_ht, &st_ht);
}
- if(selArray[i].wDay!=selday) {
- TRACE("newRange:%d %d %d %d\n", infoPtr->firstSelDay, selArray[0].wDay, selArray[1].wDay, i);
+ if(!MONTHCAL_IsDateEqual(&st[i], &st_ht)) {
+ FILETIME ft_range0, ft_range1;
+
+ st[i] = st_ht;
+
+ SystemTimeToFileTime(&st[0], &ft_range0);
+ SystemTimeToFileTime(&st[1], &ft_range1);
- selArray[i].wDay = selday;
+ /* swap bounds if needed */
+ if(CompareFileTime(&ft_range0, &ft_range1) == 1) {
+ SYSTEMTIME swap = st[1];
- if(selArray[0].wDay>selArray[1].wDay) {
- DWORD tempday;
- tempday = selArray[1].wDay;
- selArray[1].wDay = selArray[0].wDay;
- selArray[0].wDay = tempday;
+ st[1] = st[0];
+ st[0] = swap;
}
- MONTHCAL_SetSelRange(infoPtr, selArray);
+ MONTHCAL_CopyTime(&infoPtr->todaysDate, &st[0]);
+ MONTHCAL_CopyTime(&infoPtr->todaysDate, &st[1]);
+ MONTHCAL_SetSelRange(infoPtr, st);
}
}
--
1.5.6.5
--=-44dBov4AunFMhM46cdL1--
More information about the wine-patches
mailing list