Vincent Povirk : comctl32: Validate text entered in a datetime by the user.
Alexandre Julliard
julliard at winehq.org
Thu Mar 10 11:30:24 CST 2011
Module: wine
Branch: master
Commit: 08a4c8611b277d1153b9f4bbad600de6af234d29
URL: http://source.winehq.org/git/wine.git/?a=commit;h=08a4c8611b277d1153b9f4bbad600de6af234d29
Author: Vincent Povirk <vincent at codeweavers.com>
Date: Wed Mar 9 15:30:54 2011 -0600
comctl32: Validate text entered in a datetime by the user.
---
dlls/comctl32/datetime.c | 190 ++++++++++++++++++++++++++--------------------
1 files changed, 107 insertions(+), 83 deletions(-)
diff --git a/dlls/comctl32/datetime.c b/dlls/comctl32/datetime.c
index ed625e9..8269758 100644
--- a/dlls/comctl32/datetime.c
+++ b/dlls/comctl32/datetime.c
@@ -73,6 +73,8 @@ typedef struct
BOOL bCalDepressed; /* TRUE = cal button is depressed */
int bDropdownEnabled;
int select;
+ WCHAR charsEntered[4];
+ int nCharsEntered;
HFONT hFont;
int nrFieldsAllocated;
int nrFields;
@@ -697,6 +699,13 @@ DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc)
/* fill if focused */
HBRUSH hbr = CreateSolidBrush (comctl32_color.clrActiveCaption);
+ if (infoPtr->nCharsEntered)
+ {
+ memcpy(txt, infoPtr->charsEntered, infoPtr->nCharsEntered * sizeof(WCHAR));
+ txt[infoPtr->nCharsEntered] = 0;
+ GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size);
+ }
+
selection.left = 0;
selection.top = 0;
selection.right = size.cx;
@@ -756,6 +765,68 @@ static int DATETIME_GetPrevDateField(const DATETIME_INFO *infoPtr, int i)
return -1;
}
+static void
+DATETIME_ApplySelectedField (DATETIME_INFO *infoPtr)
+{
+ int fieldNum = infoPtr->select & DTHT_DATEFIELD;
+ int i, val=0;
+ SYSTEMTIME date = infoPtr->date;
+
+ if (infoPtr->select == -1 || infoPtr->nCharsEntered == 0)
+ return;
+
+ for (i=0; i<infoPtr->nCharsEntered; i++)
+ val = val * 10 + infoPtr->charsEntered[i] - '0';
+
+ infoPtr->nCharsEntered = 0;
+
+ switch (infoPtr->fieldspec[fieldNum]) {
+ case ONEDIGITYEAR:
+ case TWODIGITYEAR:
+ date.wYear = date.wYear - (date.wYear%100) + val;
+ break;
+ case INVALIDFULLYEAR:
+ case FULLYEAR:
+ date.wYear = val;
+ break;
+ case ONEDIGITMONTH:
+ case TWODIGITMONTH:
+ date.wMonth = val;
+ break;
+ case ONEDIGITDAY:
+ case TWODIGITDAY:
+ date.wDay = val;
+ break;
+ case ONEDIGIT12HOUR:
+ case TWODIGIT12HOUR:
+ case ONEDIGIT24HOUR:
+ case TWODIGIT24HOUR:
+ /* FIXME: Preserve AM/PM for 12HOUR? */
+ date.wHour = val;
+ break;
+ case ONEDIGITMINUTE:
+ case TWODIGITMINUTE:
+ date.wMinute = val;
+ break;
+ case ONEDIGITSECOND:
+ case TWODIGITSECOND:
+ date.wSecond = val;
+ break;
+ }
+
+ if (DATETIME_SetSystemTime(infoPtr, GDT_VALID, &date))
+ DATETIME_SendDateTimeChangeNotify (infoPtr);
+}
+
+static void
+DATETIME_SetSelectedField (DATETIME_INFO *infoPtr, int select)
+{
+ DATETIME_ApplySelectedField(infoPtr);
+
+ infoPtr->select = select;
+ infoPtr->nCharsEntered = 0;
+}
+
static LRESULT
DATETIME_LButtonDown (DATETIME_INFO *infoPtr, INT x, INT y)
{
@@ -784,7 +855,8 @@ DATETIME_LButtonDown (DATETIME_INFO *infoPtr, INT x, INT y)
if (infoPtr->fieldspec[new] == FULLDAY) return 0;
}
}
- infoPtr->select = new;
+
+ DATETIME_SetSelectedField(infoPtr, new);
if (infoPtr->select == DTHT_MCPOPUP) {
RECT rcMonthCal;
@@ -962,6 +1034,7 @@ DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode)
{
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
int wrap = 0;
+ int new;
if (!(infoPtr->haveFocus)) return 0;
if ((fieldNum==0) && (infoPtr->select)) return 0;
@@ -973,40 +1046,50 @@ DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode)
switch (vkCode) {
case VK_ADD:
case VK_UP:
+ infoPtr->nCharsEntered = 0;
DATETIME_IncreaseField (infoPtr, fieldNum, 1);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_SUBTRACT:
case VK_DOWN:
+ infoPtr->nCharsEntered = 0;
DATETIME_IncreaseField (infoPtr, fieldNum, -1);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_HOME:
+ infoPtr->nCharsEntered = 0;
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MIN);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_END:
+ infoPtr->nCharsEntered = 0;
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MAX);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_LEFT:
+ new = infoPtr->select;
do {
- if (infoPtr->select == 0) {
- infoPtr->select = infoPtr->nrFields - 1;
+ if (new == 0) {
+ new = new - 1;
wrap++;
} else {
- infoPtr->select--;
+ new--;
}
- } while ((infoPtr->fieldspec[infoPtr->select] & DT_STRING) && (wrap<2));
+ } while ((infoPtr->fieldspec[new] & DT_STRING) && (wrap<2));
+ if (new != infoPtr->select)
+ DATETIME_SetSelectedField(infoPtr, new);
break;
case VK_RIGHT:
+ new = infoPtr->select;
do {
- infoPtr->select++;
- if (infoPtr->select==infoPtr->nrFields) {
- infoPtr->select = 0;
+ new++;
+ if (new==infoPtr->nrFields) {
+ new = 0;
wrap++;
}
- } while ((infoPtr->fieldspec[infoPtr->select] & DT_STRING) && (wrap<2));
+ } while ((infoPtr->fieldspec[new] & DT_STRING) && (wrap<2));
+ if (new != infoPtr->select)
+ DATETIME_SetSelectedField(infoPtr, new);
break;
}
@@ -1022,80 +1105,20 @@ DATETIME_Char (DATETIME_INFO *infoPtr, WPARAM vkCode)
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
if (vkCode >= '0' && vkCode <= '9') {
- int num = vkCode-'0';
- int newDays;
-
- /* this is a somewhat simplified version of what Windows does */
- SYSTEMTIME *date = &infoPtr->date;
- switch (infoPtr->fieldspec[fieldNum]) {
- case ONEDIGITYEAR:
- case TWODIGITYEAR:
- date->wYear = date->wYear - (date->wYear%100) +
- (date->wYear%10)*10 + num;
- MONTHCAL_CalculateDayOfWeek(date, TRUE);
- DATETIME_SendDateTimeChangeNotify (infoPtr);
- break;
- case INVALIDFULLYEAR:
- case FULLYEAR:
- /* reset current year initialy */
- date->wYear = ((date->wYear/1000) ? 0 : 1)*(date->wYear%1000)*10 + num;
- MONTHCAL_CalculateDayOfWeek(date, TRUE);
- DATETIME_SendDateTimeChangeNotify (infoPtr);
- break;
- case ONEDIGITMONTH:
- case TWODIGITMONTH:
- if ((date->wMonth%10) > 1 || num > 2)
- date->wMonth = num;
- else
- date->wMonth = (date->wMonth%10)*10+num;
- MONTHCAL_CalculateDayOfWeek(date, TRUE);
- DATETIME_SendDateTimeChangeNotify (infoPtr);
- break;
- case ONEDIGITDAY:
- case TWODIGITDAY:
- newDays = (date->wDay%10)*10+num;
- if (newDays > MONTHCAL_MonthLength(date->wMonth, date->wYear))
- date->wDay = num;
- else
- date->wDay = newDays;
- MONTHCAL_CalculateDayOfWeek(date, TRUE);
- DATETIME_SendDateTimeChangeNotify (infoPtr);
- break;
- case ONEDIGIT12HOUR:
- case TWODIGIT12HOUR:
- if ((date->wHour%10) > 1 || num > 2)
- date->wHour = num;
- else
- date->wHour = (date->wHour%10)*10+num;
- DATETIME_SendDateTimeChangeNotify (infoPtr);
- break;
- case ONEDIGIT24HOUR:
- case TWODIGIT24HOUR:
- if ((date->wHour%10) > 2)
- date->wHour = num;
- else if ((date->wHour%10) == 2 && num > 3)
- date->wHour = num;
- else
- date->wHour = (date->wHour%10)*10+num;
- DATETIME_SendDateTimeChangeNotify (infoPtr);
- break;
- case ONEDIGITMINUTE:
- case TWODIGITMINUTE:
- if ((date->wMinute%10) > 5)
- date->wMinute = num;
- else
- date->wMinute = (date->wMinute%10)*10+num;
- DATETIME_SendDateTimeChangeNotify (infoPtr);
- break;
- case ONEDIGITSECOND:
- case TWODIGITSECOND:
- if ((date->wSecond%10) > 5)
- date->wSecond = num;
- else
- date->wSecond = (date->wSecond%10)*10+num;
- DATETIME_SendDateTimeChangeNotify (infoPtr);
- break;
- }
+ int maxChars;
+ int fieldSpec;
+
+ infoPtr->charsEntered[infoPtr->nCharsEntered++] = vkCode;
+
+ fieldSpec = infoPtr->fieldspec[fieldNum];
+
+ if (fieldSpec == INVALIDFULLYEAR || fieldSpec == FULLYEAR)
+ maxChars = 4;
+ else
+ maxChars = 2;
+
+ if (maxChars == infoPtr->nCharsEntered)
+ DATETIME_ApplySelectedField(infoPtr);
}
return 0;
}
@@ -1133,6 +1156,7 @@ DATETIME_KillFocus (DATETIME_INFO *infoPtr, HWND lostFocus)
if (infoPtr->haveFocus) {
DATETIME_SendSimpleNotify (infoPtr, NM_KILLFOCUS);
infoPtr->haveFocus = 0;
+ DATETIME_SetSelectedField (infoPtr, -1);
}
InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
More information about the wine-cvs
mailing list