diff --git a/dll/win32/comctl32/comboex.c b/dll/win32/comctl32/comboex.c index 10d8b8727b8..3402a7126ef 100644 --- a/dll/win32/comctl32/comboex.c +++ b/dll/win32/comctl32/comboex.c @@ -1120,10 +1120,10 @@ static LRESULT COMBOEX_Command (COMBOEX_INFO *infoPtr, WPARAM wParam) switch (command) { case CBN_DROPDOWN: - SetFocus (infoPtr->hwndCombo); - ShowWindow (infoPtr->hwndEdit, SW_HIDE); - return SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf); - + SetFocus (infoPtr->hwndCombo); + ShowWindow (infoPtr->hwndEdit, SW_HIDE); + infoPtr->flags |= WCBE_ACTEDIT; + return SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf); case CBN_CLOSEUP: SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf); /* @@ -1741,7 +1741,7 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, return DefSubclassProc(hwnd, uMsg, wParam, lParam); case WM_KEYDOWN: { - INT_PTR oldItem, selected, step = 1; + INT_PTR oldItem, selected; CBE_ITEMDATA *item; switch ((INT)wParam) @@ -1851,13 +1851,15 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, break; case VK_UP: - step = -1; case VK_DOWN: - /* by default, step is 1 */ + { + INT step = wParam == VK_DOWN ? 1 : -1; + oldItem = SendMessageW (infoPtr->hwndSelf, CB_GETCURSEL, 0, 0); if (oldItem >= 0 && oldItem + step >= 0) SendMessageW (infoPtr->hwndSelf, CB_SETCURSEL, oldItem + step, 0); return 0; + } default: return DefSubclassProc(hwnd, uMsg, wParam, lParam); } diff --git a/dll/win32/comctl32/comctl32undoc.c b/dll/win32/comctl32/comctl32undoc.c index ff94051bcc0..cc5974787d6 100644 --- a/dll/win32/comctl32/comctl32undoc.c +++ b/dll/win32/comctl32/comctl32undoc.c @@ -168,23 +168,23 @@ DWORD WINAPI GetSize (LPVOID lpMem) *|typedef INT (CALLBACK *MRUStringCmpFn)(LPCTSTR lhs, LPCTSTR rhs); *|typedef INT (CALLBACK *MRUBinaryCmpFn)(LPCVOID lhs, LPCVOID rhs, DWORD length); *| - *|typedef struct tagCREATEMRULIST + *|typedef struct tagMRUINFO *|{ *| DWORD cbSize; - *| DWORD nMaxItems; - *| DWORD dwFlags; + *| UINT uMax; + *| UINT fFlags; *| HKEY hKey; *| LPTSTR lpszSubKey; *| PROC lpfnCompare; - *|} CREATEMRULIST, *LPCREATEMRULIST; + *|} MRUINFO, *LPMRUINFO; * * MEMBERS - * cbSize [I] The size of the CREATEMRULIST structure. This must be set - * to sizeof(CREATEMRULIST) by the caller. - * nMaxItems [I] The maximum number of items allowed in the list. Because + * cbSize [I] The size of the MRUINFO structure. This must be set + * to sizeof(MRUINFO) by the caller. + * uMax [I] The maximum number of items allowed in the list. Because * of the limited number of identifiers, this should be set to * a value from 1 to 30 by the caller. - * dwFlags [I] If bit 0 is set, the list will be used to store binary + * fFlags [I] If bit 0 is set, the list will be used to store binary * data, otherwise it is assumed to store strings. If bit 1 * is set, every change made to the list will be reflected in * the registry immediately, otherwise changes will only be @@ -210,11 +210,11 @@ typedef INT (CALLBACK *MRUStringCmpFnA)(LPCSTR lhs, LPCSTR rhs); typedef INT (CALLBACK *MRUStringCmpFnW)(LPCWSTR lhs, LPCWSTR rhs); typedef INT (CALLBACK *MRUBinaryCmpFn)(LPCVOID lhs, LPCVOID rhs, DWORD length); -typedef struct tagCREATEMRULISTA +typedef struct tagMRUINFOA { DWORD cbSize; - DWORD nMaxItems; - DWORD dwFlags; + UINT uMax; + UINT fFlags; HKEY hKey; LPSTR lpszSubKey; union @@ -222,13 +222,13 @@ typedef struct tagCREATEMRULISTA MRUStringCmpFnA string_cmpfn; MRUBinaryCmpFn binary_cmpfn; } u; -} CREATEMRULISTA, *LPCREATEMRULISTA; +} MRUINFOA, *LPMRUINFOA; -typedef struct tagCREATEMRULISTW +typedef struct tagMRUINFOW { DWORD cbSize; - DWORD nMaxItems; - DWORD dwFlags; + UINT uMax; + UINT fFlags; HKEY hKey; LPWSTR lpszSubKey; union @@ -236,12 +236,12 @@ typedef struct tagCREATEMRULISTW MRUStringCmpFnW string_cmpfn; MRUBinaryCmpFn binary_cmpfn; } u; -} CREATEMRULISTW, *LPCREATEMRULISTW; +} MRUINFOW, *LPMRUINFOW; -/* dwFlags */ -#define MRUF_STRING_LIST 0 /* list will contain strings */ -#define MRUF_BINARY_LIST 1 /* list will contain binary data */ -#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */ +/* MRUINFO.fFlags */ +#define MRU_STRING 0 /* list will contain strings */ +#define MRU_BINARY 1 /* list will contain binary data */ +#define MRU_CACHEWRITE 2 /* only save list order to reg. is FreeMRUList */ /* If list is a string list lpfnCompare has the following prototype * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2) @@ -263,7 +263,7 @@ typedef struct tagWINEMRUITEM typedef struct tagWINEMRULIST { - CREATEMRULISTW extview; /* original create information */ + MRUINFOW extview; /* original create information */ BOOL isUnicode; /* is compare fn Unicode */ DWORD wineFlags; /* internal flags */ DWORD cursize; /* current size of realMRU */ @@ -325,7 +325,7 @@ static void MRU_SaveChanged ( LPWINEMRULIST mp ) witem->itemFlag &= ~WMRUIF_CHANGED; realname[0] = 'a' + i; err = RegSetValueExW(newkey, realname, 0, - (mp->extview.dwFlags & MRUF_BINARY_LIST) ? + (mp->extview.fFlags & MRU_BINARY) ? REG_BINARY : REG_SZ, &witem->datastart, witem->size); if (err) { @@ -363,7 +363,7 @@ void WINAPI FreeMRUList (HANDLE hMRUList) MRU_SaveChanged( mp ); } - for(i=0; iextview.nMaxItems; i++) + for(i=0; iextview.uMax; i++) Free(mp->array[i]); Free(mp->realMRU); @@ -400,7 +400,7 @@ INT WINAPI FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, if (!mp || !mp->extview.u.string_cmpfn) return -1; - if(!(mp->extview.dwFlags & MRUF_BINARY_LIST) && !mp->isUnicode) { + if(!(mp->extview.fFlags & MRU_BINARY) && !mp->isUnicode) { DWORD len = WideCharToMultiByte(CP_ACP, 0, lpData, -1, NULL, 0, NULL, NULL); dataA = Alloc(len); @@ -408,7 +408,7 @@ INT WINAPI FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, } for(i=0; icursize; i++) { - if (mp->extview.dwFlags & MRUF_BINARY_LIST) { + if (mp->extview.fFlags & MRU_BINARY) { if (!mp->extview.u.binary_cmpfn(lpData, &mp->array[i]->datastart, cbData)) break; } @@ -480,7 +480,7 @@ INT WINAPI AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData) } else { /* either add a new entry or replace oldest */ - if (mp->cursize < mp->extview.nMaxItems) { + if (mp->cursize < mp->extview.uMax) { /* Add in a new item */ replace = mp->cursize; mp->cursize++; @@ -509,7 +509,7 @@ INT WINAPI AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData) TRACE("(%p, %p, %d) adding data, /%c/ now most current\n", hList, lpData, cbData, replace+'a'); - if (!(mp->extview.dwFlags & MRUF_DELAYED_SAVE)) { + if (!(mp->extview.fFlags & MRU_CACHEWRITE)) { /* save changed stuff right now */ MRU_SaveChanged( mp ); } @@ -649,9 +649,9 @@ INT WINAPI FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum) } /************************************************************************* - * CreateMRUListLazy_common (internal) + * create_mru_list (internal) */ -static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) +static HANDLE create_mru_list(LPWINEMRULIST mp) { UINT i, err; HKEY newkey; @@ -663,12 +663,12 @@ static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) /* get space to save indices that will turn into names * but in order of most to least recently used */ - mp->realMRU = Alloc((mp->extview.nMaxItems + 2) * sizeof(WCHAR)); + mp->realMRU = Alloc((mp->extview.uMax + 2) * sizeof(WCHAR)); /* get space to save pointers to actual data in order of * 'a' to 'z' (0 to n). */ - mp->array = Alloc(mp->extview.nMaxItems * sizeof(LPVOID)); + mp->array = Alloc(mp->extview.uMax * sizeof(LPVOID)); /* open the sub key */ if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey, @@ -681,7 +681,7 @@ static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) &dwdisp))) { /* error - what to do ??? */ ERR("(%u %u %x %p %s %p): Could not open key, error=%d\n", - mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags, + mp->extview.cbSize, mp->extview.uMax, mp->extview.fFlags, mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey), mp->extview.u.string_cmpfn, err); return 0; @@ -689,7 +689,7 @@ static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) /* get values from key 'MRUList' */ if (newkey) { - datasize = (mp->extview.nMaxItems + 1) * sizeof(WCHAR); + datasize = (mp->extview.uMax + 1) * sizeof(WCHAR); if((err=RegQueryValueExW( newkey, strMRUList, 0, &type, (LPBYTE)mp->realMRU, &datasize))) { /* not present - set size to 1 (will become 0 later) */ @@ -726,7 +726,7 @@ static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) mp->cursize = 0; TRACE("(%u %u %x %p %s %p): Current Size = %d\n", - mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags, + mp->extview.cbSize, mp->extview.uMax, mp->extview.fFlags, mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey), mp->extview.u.string_cmpfn, mp->cursize); return mp; @@ -737,24 +737,22 @@ static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) * * See CreateMRUListLazyA. */ -HANDLE WINAPI CreateMRUListLazyW (const CREATEMRULISTW *lpcml, DWORD dwParam2, +HANDLE WINAPI CreateMRUListLazyW (const MRUINFOW *infoW, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4) { LPWINEMRULIST mp; /* Native does not check for a NULL lpcml */ - - if (lpcml->cbSize != sizeof(CREATEMRULISTW) || !lpcml->hKey || - IsBadStringPtrW(lpcml->lpszSubKey, -1)) + if (!infoW->hKey || IsBadStringPtrW(infoW->lpszSubKey, -1)) return NULL; mp = Alloc(sizeof(WINEMRULIST)); - memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW)); - mp->extview.lpszSubKey = Alloc((strlenW(lpcml->lpszSubKey) + 1) * sizeof(WCHAR)); - strcpyW(mp->extview.lpszSubKey, lpcml->lpszSubKey); + memcpy(&mp->extview, infoW, sizeof(MRUINFOW)); + mp->extview.lpszSubKey = Alloc((strlenW(infoW->lpszSubKey) + 1) * sizeof(WCHAR)); + strcpyW(mp->extview.lpszSubKey, infoW->lpszSubKey); mp->isUnicode = TRUE; - return CreateMRUListLazy_common(mp); + return create_mru_list(mp); } /************************************************************************** @@ -771,7 +769,7 @@ HANDLE WINAPI CreateMRUListLazyW (const CREATEMRULISTW *lpcml, DWORD dwParam2, * RETURNS * Handle to MRU list. */ -HANDLE WINAPI CreateMRUListLazyA (const CREATEMRULISTA *lpcml, DWORD dwParam2, +HANDLE WINAPI CreateMRUListLazyA (const MRUINFOA *lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4) { LPWINEMRULIST mp; @@ -779,18 +777,18 @@ HANDLE WINAPI CreateMRUListLazyA (const CREATEMRULISTA *lpcml, DWORD dwParam2, /* Native does not check for a NULL lpcml */ - if (lpcml->cbSize != sizeof(CREATEMRULISTA) || !lpcml->hKey || + if (lpcml->cbSize != sizeof(MRUINFOA) || !lpcml->hKey || IsBadStringPtrA(lpcml->lpszSubKey, -1)) return 0; mp = Alloc(sizeof(WINEMRULIST)); - memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW)); + memcpy(&mp->extview, lpcml, sizeof(MRUINFOA)); len = MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1, NULL, 0); mp->extview.lpszSubKey = Alloc(len * sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1, mp->extview.lpszSubKey, len); mp->isUnicode = FALSE; - return CreateMRUListLazy_common(mp); + return create_mru_list(mp); } /************************************************************************** @@ -798,9 +796,9 @@ HANDLE WINAPI CreateMRUListLazyA (const CREATEMRULISTA *lpcml, DWORD dwParam2, * * See CreateMRUListA. */ -HANDLE WINAPI CreateMRUListW (const CREATEMRULISTW *lpcml) +HANDLE WINAPI CreateMRUListW (const MRUINFOW *infoW) { - return CreateMRUListLazyW(lpcml, 0, 0, 0); + return CreateMRUListLazyW(infoW, 0, 0, 0); } /************************************************************************** @@ -814,7 +812,7 @@ HANDLE WINAPI CreateMRUListW (const CREATEMRULISTW *lpcml) * RETURNS * Handle to MRU list. */ -HANDLE WINAPI CreateMRUListA (const CREATEMRULISTA *lpcml) +HANDLE WINAPI CreateMRUListA (const MRUINFOA *lpcml) { return CreateMRUListLazyA (lpcml, 0, 0, 0); } @@ -879,7 +877,7 @@ INT WINAPI EnumMRUListA (HANDLE hList, INT nItemPos, LPVOID lpBuffer, desired -= 'a'; TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired); witem = mp->array[desired]; - if(mp->extview.dwFlags & MRUF_BINARY_LIST) { + if(mp->extview.fFlags & MRU_BINARY) { datasize = min( witem->size, nBufferSize ); memcpy( lpBuffer, &witem->datastart, datasize); } else { diff --git a/dll/win32/comctl32/datetime.c b/dll/win32/comctl32/datetime.c index 1ac6ba7ad36..abfef586605 100644 --- a/dll/win32/comctl32/datetime.c +++ b/dll/win32/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; @@ -165,7 +167,8 @@ DATETIME_SetSystemTime (DATETIME_INFO *infoPtr, DWORD flag, const SYSTEMTIME *sy if (flag == GDT_VALID) { if (systime->wYear < 1601 || systime->wYear > 30827 || systime->wMonth < 1 || systime->wMonth > 12 || - systime->wDay < 1 || systime->wDay > 31 || + systime->wDay < 1 || + systime->wDay > MONTHCAL_MonthLength(systime->wMonth, systime->wYear) || systime->wHour > 23 || systime->wMinute > 59 || systime->wSecond > 59 || @@ -277,10 +280,11 @@ DATETIME_UseFormat (DATETIME_INFO *infoPtr, LPCWSTR formattxt) static BOOL -DATETIME_SetFormatW (DATETIME_INFO *infoPtr, LPCWSTR lpszFormat) +DATETIME_SetFormatW (DATETIME_INFO *infoPtr, LPCWSTR format) { - if (!lpszFormat) { - WCHAR format_buf[80]; + WCHAR format_buf[80]; + + if (!format) { DWORD format_item; if (infoPtr->dwStyle & DTS_LONGDATEFORMAT) @@ -290,13 +294,13 @@ DATETIME_SetFormatW (DATETIME_INFO *infoPtr, LPCWSTR lpszFormat) else /* DTS_SHORTDATEFORMAT */ format_item = LOCALE_SSHORTDATE; GetLocaleInfoW(LOCALE_USER_DEFAULT, format_item, format_buf, sizeof(format_buf)/sizeof(format_buf[0])); - lpszFormat = format_buf; + format = format_buf; } - DATETIME_UseFormat (infoPtr, lpszFormat); + DATETIME_UseFormat (infoPtr, format); InvalidateRect (infoPtr->hwndSelf, NULL, TRUE); - return 1; + return TRUE; } @@ -470,6 +474,9 @@ DATETIME_IncreaseField (DATETIME_INFO *infoPtr, int number, int delta) case TWODIGITYEAR: case FULLYEAR: date->wYear = wrap(date->wYear, delta, 1752, 9999); + if (date->wDay > MONTHCAL_MonthLength(date->wMonth, date->wYear)) + /* This can happen when moving away from a leap year. */ + date->wDay = MONTHCAL_MonthLength(date->wMonth, date->wYear); MONTHCAL_CalculateDayOfWeek(date, TRUE); break; case ONEDIGITMONTH: @@ -696,6 +703,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; @@ -755,6 +769,74 @@ 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, clamp_day=0; + SYSTEMTIME date = infoPtr->date; + + if (infoPtr->select == -1 || infoPtr->nCharsEntered == 0) + return; + + for (i=0; inCharsEntered; 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; + clamp_day = 1; + break; + case INVALIDFULLYEAR: + case FULLYEAR: + date.wYear = val; + clamp_day = 1; + break; + case ONEDIGITMONTH: + case TWODIGITMONTH: + date.wMonth = val; + clamp_day = 1; + 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 (clamp_day && date.wDay > MONTHCAL_MonthLength(date.wMonth, date.wYear)) + date.wDay = MONTHCAL_MonthLength(date.wMonth, date.wYear); + + 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) { @@ -783,7 +865,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; @@ -961,6 +1044,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; @@ -972,40 +1056,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; } @@ -1021,80 +1115,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; + int maxChars; + int fieldSpec; - /* 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; - } + 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; } @@ -1132,6 +1166,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); diff --git a/dll/win32/comctl32/ipaddress.c b/dll/win32/comctl32/ipaddress.c index 1f41f91eac1..ee8a31d2d28 100644 --- a/dll/win32/comctl32/ipaddress.c +++ b/dll/win32/comctl32/ipaddress.c @@ -384,15 +384,16 @@ static void IPADDRESS_SetFocusToField (const IPADDRESS_INFO *infoPtr, INT index) static BOOL IPADDRESS_ConstrainField (const IPADDRESS_INFO *infoPtr, int currentfield) { - const IPPART_INFO *part = &infoPtr->Part[currentfield]; - WCHAR field[10]; static const WCHAR fmt[] = { '%', 'd', 0 }; + const IPPART_INFO *part; int curValue, newValue; + WCHAR field[10]; TRACE("(currentfield=%d)\n", currentfield); if (currentfield < 0 || currentfield > 3) return FALSE; + part = &infoPtr->Part[currentfield]; if (!GetWindowTextW (part->EditHwnd, field, 4)) return FALSE; curValue = atoiW(field); diff --git a/dll/win32/comctl32/listview.c b/dll/win32/comctl32/listview.c index d6da12d5a0a..033472cc8da 100644 --- a/dll/win32/comctl32/listview.c +++ b/dll/win32/comctl32/listview.c @@ -315,7 +315,6 @@ typedef struct tagLISTVIEW_INFO COLORREF clrBk; COLORREF clrText; COLORREF clrTextBk; - BOOL bDefaultBkColor; /* font */ HFONT hDefaultFont; @@ -1498,6 +1497,70 @@ static BOOL iterator_visibleitems(ITERATOR *i, const LISTVIEW_INFO *infoPtr, HDC return TRUE; } +/* Remove common elements from two iterators */ +/* Passed iterators have to point on the first elements */ +static BOOL iterator_remove_common_items(ITERATOR *iter1, ITERATOR *iter2) +{ + if(!iter1->ranges || !iter2->ranges) { + int lower, upper; + + if(iter1->ranges || iter2->ranges || + (iter1->range.lowerrange.lower && iter1->range.upper>iter2->range.upper) || + (iter1->range.lower>iter2->range.lower && iter1->range.upperrange.upper)) { + ERR("result is not a one range iterator\n"); + return FALSE; + } + + if(iter1->range.lower==-1 || iter2->range.lower==-1) + return TRUE; + + lower = iter1->range.lower; + upper = iter1->range.upper; + + if(lower < iter2->range.lower) + iter1->range.upper = iter2->range.lower; + else if(upper > iter2->range.upper) + iter1->range.lower = iter2->range.upper; + else + iter1->range.lower = iter1->range.upper = -1; + + if(iter2->range.lower < lower) + iter2->range.upper = lower; + else if(iter2->range.upper > upper) + iter2->range.lower = upper; + else + iter2->range.lower = iter2->range.upper = -1; + + return TRUE; + } + + iterator_next(iter1); + iterator_next(iter2); + + while(1) { + if(iter1->nItem==-1 || iter2->nItem==-1) + break; + + if(iter1->nItem == iter2->nItem) { + int delete = iter1->nItem; + + iterator_prev(iter1); + iterator_prev(iter2); + ranges_delitem(iter1->ranges, delete); + ranges_delitem(iter2->ranges, delete); + iterator_next(iter1); + iterator_next(iter2); + } else if(iter1->nItem > iter2->nItem) + iterator_next(iter2); + else + iterator_next(iter1); + } + + iter1->nItem = iter1->range.lower = iter1->range.upper = -1; + iter2->nItem = iter2->range.lower = iter2->range.upper = -1; + return TRUE; +} + /******** Misc helper functions ************************************/ static inline LRESULT CallWindowProcT(WNDPROC proc, HWND hwnd, UINT uMsg, @@ -1636,19 +1699,8 @@ static inline BOOL LISTVIEW_GetItemW(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpL /* used to handle collapse main item column case */ static inline BOOL LISTVIEW_DrawFocusRect(const LISTVIEW_INFO *infoPtr, HDC hdc) { - BOOL Ret = FALSE; - - if (infoPtr->rcFocus.left < infoPtr->rcFocus.right) - { - DWORD dwOldBkColor, dwOldTextColor; - - dwOldBkColor = SetBkColor(hdc, RGB(255, 255, 255)); - dwOldTextColor = SetBkColor(hdc, RGB(0, 0, 0)); - Ret = DrawFocusRect(hdc, &infoPtr->rcFocus); - SetBkColor(hdc, dwOldBkColor); - SetBkColor(hdc, dwOldTextColor); - } - return Ret; + return (infoPtr->rcFocus.left < infoPtr->rcFocus.right) ? + DrawFocusRect(hdc, &infoPtr->rcFocus) : FALSE; } /* Listview invalidation functions: use _only_ these functions to invalidate */ @@ -3745,7 +3797,7 @@ static void LISTVIEW_MarqueeHighlight(LISTVIEW_INFO *infoPtr, const POINT *coord { BOOL controlDown = FALSE; LVITEMW item; - ITERATOR i; + ITERATOR old_elems, new_elems; RECT rect; if (coords_offs->x > infoPtr->marqueeOrigin.x) @@ -3788,54 +3840,55 @@ static void LISTVIEW_MarqueeHighlight(LISTVIEW_INFO *infoPtr, const POINT *coord if ((scroll & SCROLL_DOWN) && (coords_orig->y >= infoPtr->rcList.bottom)) LISTVIEW_Scroll(infoPtr, 0, (coords_orig->y - infoPtr->rcList.bottom)); - /* Invert the items in the old marquee rectangle */ - iterator_frameditems_absolute(&i, infoPtr, &infoPtr->marqueeRect); - - while (iterator_next(&i)) - { - if (i.nItem > -1) - { - if (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED) == LVIS_SELECTED) - item.state = 0; - else - item.state = LVIS_SELECTED; - - item.stateMask = LVIS_SELECTED; - - LISTVIEW_SetItemState(infoPtr, i.nItem, &item); - } - } - - iterator_destroy(&i); + iterator_frameditems_absolute(&old_elems, infoPtr, &infoPtr->marqueeRect); CopyRect(&infoPtr->marqueeRect, &rect); CopyRect(&infoPtr->marqueeDrawRect, &rect); OffsetRect(&infoPtr->marqueeDrawRect, offset->x, offset->y); - /* Iterate over the items within our marquee rectangle */ - iterator_frameditems_absolute(&i, infoPtr, &infoPtr->marqueeRect); + iterator_frameditems_absolute(&new_elems, infoPtr, &infoPtr->marqueeRect); + iterator_remove_common_items(&old_elems, &new_elems); - if (GetKeyState(VK_CONTROL) & 0x8000) - controlDown = TRUE; - - while (iterator_next(&i)) + /* Iterate over no longer selected items */ + while (iterator_next(&old_elems)) { - if (i.nItem > -1) + if (old_elems.nItem > -1) { - /* If CTRL is pressed, invert. If not, always select the item. */ - if ((controlDown) && (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED))) + if (LISTVIEW_GetItemState(infoPtr, old_elems.nItem, LVIS_SELECTED) == LVIS_SELECTED) item.state = 0; else item.state = LVIS_SELECTED; item.stateMask = LVIS_SELECTED; - LISTVIEW_SetItemState(infoPtr, i.nItem, &item); + LISTVIEW_SetItemState(infoPtr, old_elems.nItem, &item); } } + iterator_destroy(&old_elems); + + + /* Iterate over newly selected items */ + if (GetKeyState(VK_CONTROL) & 0x8000) + controlDown = TRUE; + + while (iterator_next(&new_elems)) + { + if (new_elems.nItem > -1) + { + /* If CTRL is pressed, invert. If not, always select the item. */ + if ((controlDown) && (LISTVIEW_GetItemState(infoPtr, new_elems.nItem, LVIS_SELECTED))) + item.state = 0; + else + item.state = LVIS_SELECTED; + + item.stateMask = LVIS_SELECTED; + + LISTVIEW_SetItemState(infoPtr, new_elems.nItem, &item); + } + } + iterator_destroy(&new_elems); - iterator_destroy(&i); LISTVIEW_InvalidateRect(infoPtr, &rect); } @@ -4284,9 +4337,9 @@ static BOOL set_sub_item(const LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, particularly useful. We currently do not actually do anything with the flag on subitems. */ - if (lpLVItem->mask & ~(LVIF_TEXT | LVIF_IMAGE | LVIF_STATE)) return FALSE; + if (lpLVItem->mask & ~(LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_DI_SETITEM)) return FALSE; if (!(lpLVItem->mask & (LVIF_TEXT | LVIF_IMAGE | LVIF_STATE))) return TRUE; - + /* get the subitem structure, and create it if not there */ hdpaSubItems = DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); assert (hdpaSubItems); @@ -4354,6 +4407,9 @@ static BOOL LISTVIEW_SetItemT(LISTVIEW_INFO *infoPtr, LVITEMW *lpLVItem, BOOL is if (!lpLVItem || lpLVItem->iItem < 0 || lpLVItem->iItem >= infoPtr->nItemCount) return FALSE; + /* Invalidate old item area */ + LISTVIEW_InvalidateItem(infoPtr, lpLVItem->iItem); + /* For efficiency, we transform the lpLVItem->pszText to Unicode here */ if ((lpLVItem->mask & LVIF_TEXT) && is_text(lpLVItem->pszText)) { @@ -4973,6 +5029,9 @@ static void LISTVIEW_Refresh(LISTVIEW_INFO *infoPtr, HDC hdc, const RECT *prcEra SelectObject(hdc, hbmp); SelectObject(hdc, infoPtr->hFont); + + if(GetClipBox(hdcOrig, &rcClient)) + IntersectClipRect(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); } else { /* Save dc values we're gonna trash while drawing * FIXME: Should be done in LISTVIEW_DrawItem() */ @@ -5054,11 +5113,7 @@ enddraw: /* Draw marquee rectangle if appropriate */ if (infoPtr->bMarqueeSelect) - { - SetBkColor(hdc, RGB(255, 255, 255)); - SetTextColor(hdc, RGB(0, 0, 0)); DrawFocusRect(hdc, &infoPtr->marqueeDrawRect); - } if (cdmode & CDRF_NOTIFYPOSTPAINT) notify_postpaint(infoPtr, &nmlvcd); @@ -5678,7 +5733,7 @@ static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, BOOL storeText, BOOL WCHAR szDispText[DISP_TEXT_SIZE] = { 0 }; NMLVDISPINFOW dispInfo; INT editedItem = infoPtr->nEditLabelItem; - BOOL bSame; + BOOL same; WCHAR *pszText = NULL; BOOL res; @@ -5698,9 +5753,6 @@ static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, BOOL storeText, BOOL TRACE("(pszText=%s, isW=%d)\n", debugtext_t(pszText, isW), isW); - infoPtr->nEditLabelItem = -1; - infoPtr->hwndEdit = 0; - ZeroMemory(&dispInfo, sizeof(dispInfo)); dispInfo.item.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT; dispInfo.item.iItem = editedItem; @@ -5715,32 +5767,34 @@ static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, BOOL storeText, BOOL } if (isW) - bSame = (lstrcmpW(dispInfo.item.pszText, pszText) == 0); + same = (lstrcmpW(dispInfo.item.pszText, pszText) == 0); else { LPWSTR tmp = textdupTtoW(pszText, FALSE); - bSame = (lstrcmpW(dispInfo.item.pszText, tmp) == 0); + same = (lstrcmpW(dispInfo.item.pszText, tmp) == 0); textfreeT(tmp, FALSE); } /* add the text from the edit in */ dispInfo.item.mask |= LVIF_TEXT; - dispInfo.item.pszText = bSame ? NULL : pszText; - dispInfo.item.cchTextMax = bSame ? 0 : textlenT(pszText, isW); + dispInfo.item.pszText = same ? NULL : pszText; + dispInfo.item.cchTextMax = textlenT(dispInfo.item.pszText, isW); /* Do we need to update the Item Text */ - if (!notify_dispinfoT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW)) - { - res = FALSE; - goto cleanup; - } + res = notify_dispinfoT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW); + + infoPtr->nEditLabelItem = -1; + infoPtr->hwndEdit = 0; + + if (!res) goto cleanup; + if (!IsWindow(hwndSelf)) { res = FALSE; goto cleanup; } if (!pszText) return TRUE; - if (bSame) + if (same) { res = TRUE; goto cleanup; @@ -7823,10 +7877,8 @@ static BOOL LISTVIEW_RedrawItems(const LISTVIEW_INFO *infoPtr, INT nFirst, INT n * is passed, then the scroll will be 0. (per MSDN 7/2002) * * For: (per experimentation with native control and CSpy ListView) - * LV_VIEW_ICON dy=1 = 1 pixel (vertical only) - * dx ignored - * LV_VIEW_SMALLICON dy=1 = 1 pixel (vertical only) - * dx ignored + * LV_VIEW_ICON scrolling in any direction is allowed + * LV_VIEW_SMALLICON scrolling in any direction is allowed * LV_VIEW_LIST dx=1 = 1 column (horizontal only) * but will only scroll 1 column per message * no matter what the value. @@ -7846,7 +7898,6 @@ static BOOL LISTVIEW_Scroll(LISTVIEW_INFO *infoPtr, INT dx, INT dy) if (dy != 0) return FALSE; break; default: /* icon */ - dx = 0; break; } @@ -7872,7 +7923,6 @@ static BOOL LISTVIEW_SetBkColor(LISTVIEW_INFO *infoPtr, COLORREF clrBk) { TRACE("(clrBk=%x)\n", clrBk); - infoPtr->bDefaultBkColor = FALSE; if(infoPtr->clrBk != clrBk) { if (infoPtr->clrBk != CLR_NONE) DeleteObject(infoPtr->hBkBrush); infoPtr->clrBk = clrBk; @@ -8803,8 +8853,8 @@ static BOOL LISTVIEW_SetItemTextT(LISTVIEW_INFO *infoPtr, INT nItem, const LVITE { LVITEMW lvItem; - if (nItem < 0 && nItem >= infoPtr->nItemCount) return FALSE; - + if (!lpLVItem || nItem < 0 || nItem >= infoPtr->nItemCount) return FALSE; + lvItem.iItem = nItem; lvItem.iSubItem = lpLVItem->iSubItem; lvItem.mask = LVIF_TEXT; @@ -9116,9 +9166,7 @@ static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare, /* I believe nHotItem should be left alone, see LISTVIEW_ShiftIndices */ /* refresh the display */ - if (infoPtr->uView != LV_VIEW_ICON && infoPtr->uView != LV_VIEW_SMALLICON) - LISTVIEW_InvalidateList(infoPtr); - + LISTVIEW_InvalidateList(infoPtr); return TRUE; } @@ -9265,7 +9313,6 @@ static LRESULT LISTVIEW_NCCreate(HWND hwnd, const CREATESTRUCTW *lpcs) infoPtr->clrText = CLR_DEFAULT; infoPtr->clrTextBk = CLR_DEFAULT; LISTVIEW_SetBkColor(infoPtr, comctl32_color.clrWindow); - infoPtr->bDefaultBkColor = TRUE; /* set default values */ infoPtr->nFocusedItem = -1; @@ -9595,6 +9642,7 @@ static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *infoPtr, INT nScrollCode, { INT nOldScrollPos, nNewScrollPos; SCROLLINFO scrollInfo; + BOOL is_an_icon; TRACE("(nScrollCode=%d(%s), nScrollDiff=%d)\n", nScrollCode, debugscrollcode(nScrollCode), nScrollDiff); @@ -9604,6 +9652,8 @@ static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *infoPtr, INT nScrollCode, scrollInfo.cbSize = sizeof(SCROLLINFO); scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; + is_an_icon = ((infoPtr->uView == LV_VIEW_ICON) || (infoPtr->uView == LV_VIEW_SMALLICON)); + if (!GetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &scrollInfo)) return 1; nOldScrollPos = scrollInfo.nPos; @@ -9614,11 +9664,11 @@ static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *infoPtr, INT nScrollCode, break; case SB_LINELEFT: - nScrollDiff = -1; + nScrollDiff = (is_an_icon) ? -LISTVIEW_SCROLL_ICON_LINE_SIZE : -1; break; case SB_LINERIGHT: - nScrollDiff = 1; + nScrollDiff = (is_an_icon) ? LISTVIEW_SCROLL_ICON_LINE_SIZE : 1; break; case SB_PAGELEFT: @@ -10160,7 +10210,6 @@ static LRESULT LISTVIEW_NCDestroy(LISTVIEW_INFO *infoPtr) */ static LRESULT LISTVIEW_Notify(LISTVIEW_INFO *infoPtr, const NMHDR *lpnmhdr) { - HWND hwndSelf = infoPtr->hwndSelf; const NMHEADERW *lpnmh; TRACE("(lpnmhdr=%p)\n", lpnmhdr); @@ -10213,10 +10262,6 @@ static LRESULT LISTVIEW_Notify(LISTVIEW_INFO *infoPtr, const NMHDR *lpnmhdr) LISTVIEW_InvalidateList(infoPtr); notify_forward_header(infoPtr, lpnmh); return FALSE; - - case HDN_ITEMCHANGINGW: - case HDN_ITEMCHANGINGA: - return notify_forward_header(infoPtr, lpnmh); case HDN_ITEMCHANGEDW: case HDN_ITEMCHANGEDA: @@ -10224,10 +10269,6 @@ static LRESULT LISTVIEW_Notify(LISTVIEW_INFO *infoPtr, const NMHDR *lpnmhdr) COLUMN_INFO *lpColumnInfo; HDITEMW hdi; INT dx, cxy; - - notify_forward_header(infoPtr, lpnmh); - if (!IsWindow(hwndSelf)) - break; if (!lpnmh->pitem || !(lpnmh->pitem->mask & HDI_WIDTH)) { @@ -11528,11 +11569,6 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_SYSCOLORCHANGE: COMCTL32_RefreshSysColors(); - if (infoPtr->bDefaultBkColor) - { - LISTVIEW_SetBkColor(infoPtr, comctl32_color.clrWindow); - infoPtr->bDefaultBkColor = TRUE; - } return 0; /* case WM_TIMER: */ diff --git a/dll/win32/comctl32/monthcal.c b/dll/win32/comctl32/monthcal.c index 2091d8875fb..edc95f4c568 100644 --- a/dll/win32/comctl32/monthcal.c +++ b/dll/win32/comctl32/monthcal.c @@ -6,7 +6,7 @@ * Copyright 1999 Chris Morgan and * James Abbatiello * Copyright 2000 Uwe Bonnes - * Copyright 2009, 2010 Nikolay Sivov + * Copyright 2009-2011 Nikolay Sivov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,7 +33,6 @@ * * TODO: * -- MCM_[GS]ETUNICODEFORMAT - * -- MONTHCAL_GetMonthRange * -- handle resources better (doesn't work now); * -- take care of internationalization. * -- keyboard handling. @@ -77,6 +76,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(monthcal); /* convert from days to 100 nanoseconds unit - used as FILETIME unit */ #define DAYSTO100NSECS(days) (((ULONGLONG)(days))*24*60*60*10000000) +enum CachedPen +{ + PenRed = 0, + PenText, + PenLast +}; + +enum CachedBrush +{ + BrushTitle = 0, + BrushMonth, + BrushBackground, + BrushLast +}; + /* single calendar data */ typedef struct _CALENDAR_INFO { @@ -96,6 +110,8 @@ typedef struct DWORD dwStyle; /* cached GWL_STYLE */ COLORREF colors[MCSC_TRAILINGTEXT+1]; + HBRUSH brushes[BrushLast]; + HPEN pens[PenLast]; HFONT hFont; HFONT hBoldFont; @@ -143,8 +159,8 @@ static const WCHAR themeClass[] = { 'S','c','r','o','l','l','b','a','r',0 }; /* empty SYSTEMTIME const */ static const SYSTEMTIME st_null; /* valid date limits */ -static const SYSTEMTIME max_allowed_date = { 9999, 12, 0, 31, 0, 0, 0, 0 }; -static const SYSTEMTIME min_allowed_date = { 1752, 9, 0, 14, 0, 0, 0, 0 }; +static const SYSTEMTIME max_allowed_date = { .wYear = 9999, .wMonth = 12, .wDay = 31 }; +static const SYSTEMTIME min_allowed_date = { .wYear = 1752, .wMonth = 9, .wDay = 14 }; /* Prev/Next buttons */ enum nav_direction @@ -449,7 +465,7 @@ int MONTHCAL_CalculateDayOfWeek(SYSTEMTIME *date, BOOL inplace) return st.wDayOfWeek; } -/* add/substract 'months' from date */ +/* add/subtract 'months' from date */ static inline void MONTHCAL_GetMonth(SYSTEMTIME *date, INT months) { INT length, m = date->wMonth + months; @@ -636,28 +652,31 @@ static BOOL MONTHCAL_SetDayFocus(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *st) return TRUE; } +/* draw today boundary box for specified rectangle */ +static void MONTHCAL_Circle(const MONTHCAL_INFO *infoPtr, HDC hdc, const RECT *r) +{ + HPEN old_pen = SelectObject(hdc, infoPtr->pens[PenRed]); + HBRUSH old_brush; + + old_brush = SelectObject(hdc, GetStockObject(NULL_BRUSH)); + Rectangle(hdc, r->left, r->top, r->right, r->bottom); + + SelectObject(hdc, old_brush); + SelectObject(hdc, old_pen); +} + /* Draw today day mark rectangle * - * [I] hdc : context to draw in - * [I] day : day to mark with rectangle + * [I] hdc : context to draw in + * [I] date : day to mark with rectangle * */ static void MONTHCAL_CircleDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEMTIME *date) { - HPEN hRedPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); - HPEN hOldPen2 = SelectObject(hdc, hRedPen); - HBRUSH hOldBrush; RECT day_rect; - MONTHCAL_CalcPosFromDay(infoPtr, date, &day_rect); - - hOldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH)); - Rectangle(hdc, day_rect.left, day_rect.top, day_rect.right, day_rect.bottom); - - SelectObject(hdc, hOldBrush); - DeleteObject(hRedPen); - SelectObject(hdc, hOldPen2); + MONTHCAL_Circle(infoPtr, hdc, &day_rect); } static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEMTIME *st, @@ -666,46 +685,39 @@ static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEM static const WCHAR fmtW[] = { '%','d',0 }; WCHAR buf[10]; RECT r, r_temp; - static BOOL bold_selected; - BOOL selected_day = FALSE; - HBRUSH hbr; COLORREF oldCol = 0; COLORREF oldBk = 0; + INT old_bkmode, selection; -/* No need to check styles: when selection is not valid, it is set to zero. - * 1rcPaint), &r)) return; if ((MONTHCAL_CompareDate(st, &infoPtr->minSel) >= 0) && - (MONTHCAL_CompareDate(st, &infoPtr->maxSel) <= 0)) { + (MONTHCAL_CompareDate(st, &infoPtr->maxSel) <= 0)) + { TRACE("%d %d %d\n", st->wDay, infoPtr->minSel.wDay, infoPtr->maxSel.wDay); TRACE("%s\n", wine_dbgstr_rect(&r)); oldCol = SetTextColor(hdc, infoPtr->colors[MCSC_MONTHBK]); oldBk = SetBkColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]); - hbr = GetSysColorBrush(COLOR_HIGHLIGHT); - FillRect(hdc, &r, hbr); + FillRect(hdc, &r, infoPtr->brushes[BrushTitle]); - selected_day = TRUE; + selection = 1; } + else + selection = 0; - if(bold && !bold_selected) { - SelectObject(hdc, infoPtr->hBoldFont); - bold_selected = TRUE; - } - if(!bold && bold_selected) { - SelectObject(hdc, infoPtr->hFont); - bold_selected = FALSE; - } + SelectObject(hdc, bold ? infoPtr->hBoldFont : infoPtr->hFont); - SetBkMode(hdc,TRANSPARENT); + old_bkmode = SetBkMode(hdc, TRANSPARENT); wsprintfW(buf, fmtW, st->wDay); DrawTextW(hdc, buf, -1, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE ); + SetBkMode(hdc, old_bkmode); - if(selected_day) { + if (selection) + { SetTextColor(hdc, oldCol); SetBkColor(hdc, oldBk); } @@ -755,13 +767,10 @@ static void MONTHCAL_PaintTitle(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRU RECT *title = &infoPtr->calendars[calIdx].title; const SYSTEMTIME *st = &infoPtr->calendars[calIdx].month; WCHAR buf_month[80], buf_fmt[80]; - HBRUSH hbr; SIZE sz; /* fill header box */ - hbr = CreateSolidBrush(infoPtr->colors[MCSC_TITLEBK]); - FillRect(hdc, title, hbr); - DeleteObject(hbr); + FillRect(hdc, title, infoPtr->brushes[BrushTitle]); /* month/year string */ SetBkColor(hdc, infoPtr->colors[MCSC_TITLEBK]); @@ -793,7 +802,7 @@ static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, con INT i, prev_month; SYSTEMTIME st; WCHAR buf[80]; - HBRUSH hbr; + HPEN old_pen; RECT r; if (!(infoPtr->dwStyle & MCS_WEEKNUMBERS)) return; @@ -865,9 +874,8 @@ static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, con r = infoPtr->calendars[calIdx].weeknums; /* erase whole week numbers area */ - hbr = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]); - FillRect(hdc, &r, hbr); - DeleteObject(hbr); + FillRect(hdc, &r, infoPtr->brushes[BrushTitle]); + SetTextColor(hdc, infoPtr->colors[MCSC_TITLEBK]); /* reduce rectangle to one week number */ r.bottom = r.top + infoPtr->height_increment; @@ -890,43 +898,50 @@ static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, con } /* line separator for week numbers column */ + old_pen = SelectObject(hdc, infoPtr->pens[PenText]); MoveToEx(hdc, infoPtr->calendars[calIdx].weeknums.right, infoPtr->calendars[calIdx].weeknums.top + 3 , NULL); LineTo(hdc, infoPtr->calendars[calIdx].weeknums.right, infoPtr->calendars[calIdx].weeknums.bottom); + SelectObject(hdc, old_pen); } /* bottom today date */ static void MONTHCAL_PaintTodayTitle(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps) { - if(!(infoPtr->dwStyle & MCS_NOTODAY)) { + static const WCHAR fmt_todayW[] = { '%','s',' ','%','s',0 }; + WCHAR buf_todayW[30], buf_dateW[20], buf[80]; + RECT text_rect, box_rect; + HFONT old_font; + INT col; + + if(infoPtr->dwStyle & MCS_NOTODAY) return; + + if (!LoadStringW(COMCTL32_hModule, IDM_TODAY, buf_todayW, countof(buf_todayW))) + { static const WCHAR todayW[] = { 'T','o','d','a','y',':',0 }; - static const WCHAR fmt_todayW[] = { '%','s',' ','%','s',0 }; - WCHAR buf_todayW[30], buf_dateW[20], buf[80]; - RECT rtoday; - - if(!(infoPtr->dwStyle & MCS_NOTODAYCIRCLE)) { - SYSTEMTIME fake_st; - - MONTHCAL_GetMaxDate(infoPtr, &fake_st); - /* this is always safe cause next month will never fully fit calendar */ - fake_st.wDay += 1; - MONTHCAL_CircleDay(infoPtr, hdc, &fake_st); - } - if (!LoadStringW(COMCTL32_hModule, IDM_TODAY, buf_todayW, countof(buf_todayW))) - { - WARN("Can't load resource\n"); - strcpyW(buf_todayW, todayW); - } - MONTHCAL_CalcDayRect(infoPtr, &rtoday, 1, 6); - GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &infoPtr->todaysDate, NULL, - buf_dateW, countof(buf_dateW)); - SelectObject(hdc, infoPtr->hBoldFont); - - wsprintfW(buf, fmt_todayW, buf_todayW, buf_dateW); - DrawTextW(hdc, buf, -1, &rtoday, DT_CALCRECT | DT_LEFT | DT_VCENTER | DT_SINGLELINE); - DrawTextW(hdc, buf, -1, &rtoday, DT_LEFT | DT_VCENTER | DT_SINGLELINE); - - SelectObject(hdc, infoPtr->hFont); + WARN("Can't load resource\n"); + strcpyW(buf_todayW, todayW); } + + col = infoPtr->dwStyle & MCS_NOTODAYCIRCLE ? 0 : 1; + if (infoPtr->dwStyle & MCS_WEEKNUMBERS) col--; + MONTHCAL_CalcDayRect(infoPtr, &text_rect, col, 6); + box_rect = text_rect; + + GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &infoPtr->todaysDate, NULL, + buf_dateW, countof(buf_dateW)); + old_font = SelectObject(hdc, infoPtr->hBoldFont); + SetTextColor(hdc, infoPtr->colors[MCSC_TEXT]); + + wsprintfW(buf, fmt_todayW, buf_todayW, buf_dateW); + DrawTextW(hdc, buf, -1, &text_rect, DT_CALCRECT | DT_LEFT | DT_VCENTER | DT_SINGLELINE); + DrawTextW(hdc, buf, -1, &text_rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE); + + if(!(infoPtr->dwStyle & MCS_NOTODAYCIRCLE)) { + OffsetRect(&box_rect, -infoPtr->width_increment, 0); + MONTHCAL_Circle(infoPtr, hdc, &box_rect); + } + + SelectObject(hdc, old_font); } /* today mark + focus */ @@ -947,15 +962,53 @@ static void MONTHCAL_PaintFocusAndCircle(const MONTHCAL_INFO *infoPtr, HDC hdc, } } +/* months before first calendar month and after last calendar month */ +static void MONTHCAL_PaintLeadTrailMonths(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps) +{ + INT mask, length; + SYSTEMTIME st_max, st; + + if (infoPtr->dwStyle & MCS_NOTRAILINGDATES) return; + + SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]); + + /* draw prev month */ + MONTHCAL_GetMinDate(infoPtr, &st); + mask = 1 << (st.wDay-1); + /* December and January both 31 days long, so no worries if wrapped */ + length = MONTHCAL_MonthLength(infoPtr->calendars[0].month.wMonth - 1, + infoPtr->calendars[0].month.wYear); + while(st.wDay <= length) + { + MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[0] & mask, ps); + mask <<= 1; + st.wDay++; + } + + /* draw next month */ + st = infoPtr->calendars[infoPtr->cal_num-1].month; + st.wDay = 1; + MONTHCAL_GetNextMonth(&st); + MONTHCAL_GetMaxDate(infoPtr, &st_max); + mask = 1; + + while(st.wDay <= st_max.wDay) + { + MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[2] & mask, ps); + mask <<= 1; + st.wDay++; + } +} + /* paint a calendar area */ static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx) { const SYSTEMTIME *date = &infoPtr->calendars[calIdx].month; - INT prev_month, i, j, length; + INT i, j, length; RECT r, fill_bk_rect; SYSTEMTIME st; WCHAR buf[80]; - HBRUSH hbr; + HPEN old_pen; int mask; /* fill whole days area - from week days area to today note rectangle */ @@ -963,26 +1016,23 @@ static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const fill_bk_rect.bottom = infoPtr->calendars[calIdx].days.bottom + (infoPtr->todayrect.bottom - infoPtr->todayrect.top); - hbr = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]); - FillRect(hdc, &fill_bk_rect, hbr); - DeleteObject(hbr); + FillRect(hdc, &fill_bk_rect, infoPtr->brushes[BrushMonth]); /* draw line under day abbreviations */ + old_pen = SelectObject(hdc, infoPtr->pens[PenText]); MoveToEx(hdc, infoPtr->calendars[calIdx].days.left + 3, infoPtr->calendars[calIdx].title.bottom + infoPtr->textHeight + 1, NULL); LineTo(hdc, infoPtr->calendars[calIdx].days.right - 3, infoPtr->calendars[calIdx].title.bottom + infoPtr->textHeight + 1); - - prev_month = date->wMonth - 1; - if (prev_month == 0) prev_month = 12; + SelectObject(hdc, old_pen); infoPtr->calendars[calIdx].wdays.left = infoPtr->calendars[calIdx].days.left = infoPtr->calendars[calIdx].weeknums.right; - /* 1. draw day abbreviations */ + /* draw day abbreviations */ SelectObject(hdc, infoPtr->hFont); SetBkColor(hdc, infoPtr->colors[MCSC_MONTHBK]); - SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]); + SetTextColor(hdc, infoPtr->colors[MCSC_TITLEBK]); /* rectangle to draw a single day abbreviation within */ r = infoPtr->calendars[calIdx].wdays; r.right = r.left + infoPtr->width_increment; @@ -994,47 +1044,7 @@ static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const OffsetRect(&r, infoPtr->width_increment, 0); } - /* 2. previous and next months */ - if (!(infoPtr->dwStyle & MCS_NOTRAILINGDATES) && (calIdx == 0 || calIdx == infoPtr->cal_num - 1)) - { - SYSTEMTIME st_max; - - SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]); - - /* draw prev month */ - if (calIdx == 0) - { - MONTHCAL_GetMinDate(infoPtr, &st); - mask = 1 << (st.wDay-1); - length = MONTHCAL_MonthLength(prev_month, date->wYear); - - while(st.wDay <= length) - { - MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[0] & mask, ps); - mask <<= 1; - st.wDay++; - } - } - - /* draw next month */ - if (calIdx == infoPtr->cal_num - 1) - { - st = *date; - st.wDay = 1; - MONTHCAL_GetNextMonth(&st); - MONTHCAL_GetMaxDate(infoPtr, &st_max); - mask = 1; - - while(st.wDay <= st_max.wDay) - { - MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[2] & mask, ps); - mask <<= 1; - st.wDay++; - } - } - } - - /* 3. current month */ + /* draw current month */ SetTextColor(hdc, infoPtr->colors[MCSC_TEXT]); st = *date; st.wDay = 1; @@ -1076,6 +1086,9 @@ static void MONTHCAL_Refresh(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT MONTHCAL_PaintWeeknumbers(infoPtr, hdc, ps, i); } + /* partially visible months */ + MONTHCAL_PaintLeadTrailMonths(infoPtr, hdc, ps); + /* focus and today rectangle */ MONTHCAL_PaintFocusAndCircle(infoPtr, hdc, ps); @@ -1125,6 +1138,7 @@ MONTHCAL_GetColor(const MONTHCAL_INFO *infoPtr, UINT index) static LRESULT MONTHCAL_SetColor(MONTHCAL_INFO *infoPtr, UINT index, COLORREF color) { + enum CachedBrush type; COLORREF prev; TRACE("%p, %d: color %08x\n", infoPtr, index, color); @@ -1134,6 +1148,35 @@ MONTHCAL_SetColor(MONTHCAL_INFO *infoPtr, UINT index, COLORREF color) prev = infoPtr->colors[index]; infoPtr->colors[index] = color; + /* update cached brush */ + switch (index) + { + case MCSC_BACKGROUND: + type = BrushBackground; + break; + case MCSC_TITLEBK: + type = BrushTitle; + break; + case MCSC_MONTHBK: + type = BrushMonth; + break; + default: + type = BrushLast; + } + + if (type != BrushLast) + { + DeleteObject(infoPtr->brushes[type]); + infoPtr->brushes[type] = CreateSolidBrush(color); + } + + /* update cached pen */ + if (index == MCSC_TEXT) + { + DeleteObject(infoPtr->pens[PenText]); + infoPtr->pens[PenText] = CreatePen(PS_SOLID, 1, infoPtr->colors[index]); + } + InvalidateRect(infoPtr->hwndSelf, NULL, index == MCSC_BACKGROUND ? TRUE : FALSE); return prev; } @@ -1265,8 +1308,6 @@ MONTHCAL_GetMonthRange(const MONTHCAL_INFO *infoPtr, DWORD flag, SYSTEMTIME *st) } case GMR_DAYSTATE: { - /*FIXME: currently multicalendar feature isn't implemented, - min date from previous month and max date from next one returned */ MONTHCAL_GetMinDate(infoPtr, &st[0]); MONTHCAL_GetMaxDate(infoPtr, &st[1]); break; @@ -1727,7 +1768,7 @@ MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht) { htinfo.uHit = MCHT_CALENDARDATEPREV; MONTHCAL_GetPrevMonth(&htinfo.st); - htinfo.st.wDay = MONTHCAL_MonthLength(lpht->st.wMonth, lpht->st.wYear) + day; + htinfo.st.wDay = MONTHCAL_MonthLength(htinfo.st.wMonth, htinfo.st.wYear) + day; } else if (day > MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear)) { @@ -2237,15 +2278,11 @@ MONTHCAL_Paint(MONTHCAL_INFO *infoPtr, HDC hdc_paint) static LRESULT MONTHCAL_EraseBkgnd(const MONTHCAL_INFO *infoPtr, HDC hdc) { - HBRUSH hbr; RECT rc; if (!GetClipBox(hdc, &rc)) return FALSE; - /* fill background */ - hbr = CreateSolidBrush (infoPtr->colors[MCSC_BACKGROUND]); - FillRect(hdc, &rc, hbr); - DeleteObject(hbr); + FillRect(hdc, &rc, infoPtr->brushes[BrushBackground]); return TRUE; } @@ -2520,7 +2557,7 @@ MONTHCAL_Create(HWND hwnd, LPCREATESTRUCTW lpcs) MONTHCAL_SetFont(infoPtr, GetStockObject(DEFAULT_GUI_FONT), FALSE); /* initialize info structure */ - /* FIXME: calculate systemtime ->> localtime(substract timezoneinfo) */ + /* FIXME: calculate systemtime ->> localtime(subtract timezoneinfo) */ GetLocalTime(&infoPtr->todaysDate); MONTHCAL_SetFirstDayOfWeek(infoPtr, -1); @@ -2538,6 +2575,13 @@ MONTHCAL_Create(HWND hwnd, LPCREATESTRUCTW lpcs) infoPtr->colors[MCSC_MONTHBK] = comctl32_color.clrWindow; infoPtr->colors[MCSC_TRAILINGTEXT] = comctl32_color.clrGrayText; + infoPtr->brushes[BrushBackground] = CreateSolidBrush(infoPtr->colors[MCSC_BACKGROUND]); + infoPtr->brushes[BrushTitle] = CreateSolidBrush(infoPtr->colors[MCSC_TITLEBK]); + infoPtr->brushes[BrushMonth] = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]); + + infoPtr->pens[PenRed] = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); + infoPtr->pens[PenText] = CreatePen(PS_SOLID, 1, infoPtr->colors[MCSC_TEXT]); + infoPtr->minSel = infoPtr->todaysDate; infoPtr->maxSel = infoPtr->todaysDate; infoPtr->calendars[0].month = infoPtr->todaysDate; @@ -2564,13 +2608,18 @@ fail: static LRESULT MONTHCAL_Destroy(MONTHCAL_INFO *infoPtr) { + INT i; + /* free month calendar info data */ Free(infoPtr->monthdayState); Free(infoPtr->calendars); SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0); CloseThemeData (GetWindowTheme (infoPtr->hwndSelf)); - + + for (i = 0; i < BrushLast; i++) DeleteObject(infoPtr->brushes[i]); + for (i = 0; i < PenLast; i++) DeleteObject(infoPtr->pens[i]); + Free(infoPtr); return 0; } diff --git a/dll/win32/comctl32/propsheet.c b/dll/win32/comctl32/propsheet.c index 2172a8507ad..bcd904c13d8 100644 --- a/dll/win32/comctl32/propsheet.c +++ b/dll/win32/comctl32/propsheet.c @@ -2490,7 +2490,7 @@ static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags) { SendMessageW(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0); SetFocus(hwndFinish); - } +} else if (dwFlags & PSWIZB_NEXT) { SendMessageW(hwndDlg, DM_SETDEFID, IDC_NEXT_BUTTON, 0); diff --git a/dll/win32/comctl32/status.c b/dll/win32/comctl32/status.c index eeaf299f6b3..427fb76f629 100644 --- a/dll/win32/comctl32/status.c +++ b/dll/win32/comctl32/status.c @@ -661,10 +661,12 @@ static BOOL STATUSBAR_SetParts (STATUS_INFO *infoPtr, INT count, LPINT parts) { STATUSWINDOWPART *tmp; - UINT i, oldNumParts; + INT i, oldNumParts; TRACE("(%d,%p)\n", count, parts); + if(!count) return FALSE; + oldNumParts = infoPtr->numParts; infoPtr->numParts = count; if (oldNumParts > infoPtr->numParts) { @@ -693,7 +695,7 @@ STATUSBAR_SetParts (STATUS_INFO *infoPtr, INT count, LPINT parts) infoPtr->parts[i].x = parts[i]; if (infoPtr->hwndToolTip) { - UINT nTipCount; + INT nTipCount; TTTOOLINFOW ti; ZeroMemory (&ti, sizeof(TTTOOLINFOW)); diff --git a/dll/win32/comctl32/syslink.c b/dll/win32/comctl32/syslink.c index 9340fc613b1..c13267e995c 100644 --- a/dll/win32/comctl32/syslink.c +++ b/dll/win32/comctl32/syslink.c @@ -529,7 +529,7 @@ static PDOC_ITEM SYSLINK_GetFocusLink (const SYSLINK_INFO *infoPtr, int *LinkId) while(Current != NULL) { - if((Current->Type == slLink)) + if(Current->Type == slLink) { if(Current->u.Link.state & LIS_FOCUSED) { @@ -1564,7 +1564,7 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message, infoPtr = (SYSLINK_INFO *)GetWindowLongPtrW(hwnd, 0); if (!infoPtr && message != WM_CREATE) - goto HandleDefaultMessage; + return DefWindowProcW(hwnd, message, wParam, lParam); switch(message) { case WM_PRINTCLIENT: @@ -1588,8 +1588,8 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message, SetCursor(LoadCursorW(0, (LPCWSTR)IDC_HAND)); return TRUE; } - /* let the default window proc handle this message */ - goto HandleDefaultMessage; + + return DefWindowProcW(hwnd, message, wParam, lParam); } case WM_SIZE: @@ -1615,7 +1615,7 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message, case WM_SETTEXT: SYSLINK_SetText(infoPtr, (LPWSTR)lParam); - goto HandleDefaultMessage; + return DefWindowProcW(hwnd, message, wParam, lParam); case WM_LBUTTONDOWN: { @@ -1645,8 +1645,9 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message, SYSKEY_SelectNextPrevLink(infoPtr, shift); return 0; } + default: + return DefWindowProcW(hwnd, message, wParam, lParam); } - goto HandleDefaultMessage; } case WM_GETDLGCODE: @@ -1777,7 +1778,6 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message, return 0; default: -HandleDefaultMessage: if ((message >= WM_USER) && (message < WM_APP) && !COMCTL32_IsReflectedMessage(message)) { ERR("unknown msg %04x wp=%04lx lp=%08lx\n", message, wParam, lParam ); diff --git a/dll/win32/comctl32/tab.c b/dll/win32/comctl32/tab.c index fe82d59e90f..ff1b953e4f7 100644 --- a/dll/win32/comctl32/tab.c +++ b/dll/win32/comctl32/tab.c @@ -52,6 +52,7 @@ * */ +#include #include #include @@ -110,7 +111,6 @@ typedef struct INT iSelected; /* the currently selected item */ INT iHotTracked; /* the highlighted item under the mouse */ INT uFocus; /* item which has the focus */ - TAB_ITEM* items; /* pointer to an array of TAB_ITEM's */ BOOL DoRedraw; /* flag for redrawing when tab contents is changed*/ BOOL needsScrolling; /* TRUE if the size of the tabs is greater than * the size of the control */ @@ -122,6 +122,8 @@ typedef struct DWORD exStyle; /* Extended style used, currently: TCS_EX_FLATSEPARATORS, TCS_EX_REGISTERDROP */ DWORD dwStyle; /* the cached window GWL_STYLE */ + + HDPA items; /* dynamic array of TAB_ITEM* pointers */ } TAB_INFO; /****************************************************************************** @@ -141,9 +143,6 @@ typedef struct #define EXTRA_ICON_PADDING 3 #define TAB_GetInfoPtr(hwnd) ((TAB_INFO *)GetWindowLongPtrW(hwnd,0)) -/* Since items are variable sized, cannot directly access them */ -#define TAB_GetItem(info,i) \ - ((TAB_ITEM*)((LPBYTE)info->items + (i) * TAB_ITEM_SIZE(info))) #define GET_DEFAULT_MIN_TAB_WIDTH(infoPtr) (DEFAULT_MIN_TAB_WIDTH - (DEFAULT_PADDING_X - (infoPtr)->uHItemPadding) * 2) @@ -155,6 +154,12 @@ typedef struct static const WCHAR themeClass[] = { 'T','a','b',0 }; +static inline TAB_ITEM* TAB_GetItem(const TAB_INFO *infoPtr, INT i) +{ + assert(i >= 0 && i < infoPtr->uNumItem); + return DPA_GetPtr(infoPtr->items, i); +} + /****************************************************************************** * Prototypes */ @@ -209,9 +214,8 @@ static void TAB_DumpItemInternal(const TAB_INFO *infoPtr, UINT iItem) { if (TRACE_ON(tab)) { - TAB_ITEM *ti; + TAB_ITEM *ti = TAB_GetItem(infoPtr, iItem); - ti = TAB_GetItem(infoPtr, iItem); TRACE("tab %d, dwState=0x%08x, pszText=%s, iImage=%d\n", iItem, ti->dwState, debugstr_w(ti->pszText), ti->iImage); TRACE("tab %d, rect.left=%d, rect.top(row)=%d\n", @@ -702,11 +706,10 @@ TAB_LButtonUp (const TAB_INFO *infoPtr) return 0; } -static inline LRESULT -TAB_RButtonDown (const TAB_INFO *infoPtr) +static inline void +TAB_RButtonUp (const TAB_INFO *infoPtr) { TAB_SendSimpleNotify(infoPtr, NM_RCLICK); - return 0; } /****************************************************************************** @@ -1766,6 +1769,7 @@ TAB_DrawItemInterior(const TAB_INFO *infoPtr, HDC hdc, INT iItem, RECT *drawRect { /* this could be considered broken on 64 bit, but that's how it works - only first 4 bytes are copied */ + dis.itemData = 0; memcpy(&dis.itemData, (ULONG_PTR*)TAB_GetItem(infoPtr, iItem)->extra, 4); } @@ -2113,9 +2117,10 @@ static void TAB_DrawItem(const TAB_INFO *infoPtr, HDC hdc, INT iItem) partIndex += 4; /* The part also differs on the position of a tab on a line. * "Visually" determining the position works well enough. */ + GetClientRect(infoPtr->hwnd, &r1); if(selectedRect.left == 0) partIndex += 1; - if(selectedRect.right == clRight) + if(selectedRect.right == r1.right) partIndex += 2; if (iItem == infoPtr->iSelected) @@ -2436,6 +2441,9 @@ static void TAB_EnsureSelectionVisible( INT iSelected = infoPtr->iSelected; INT iOrigLeftmostVisible = infoPtr->leftmostVisible; + if (iSelected < 0) + return; + /* set the items row to the bottommost row or topmost row depending on * style */ if ((infoPtr->uNumRows > 1) && !(infoPtr->dwStyle & TCS_BUTTONS)) @@ -2640,42 +2648,21 @@ TAB_InsertItemT (TAB_INFO *infoPtr, INT iItem, const TCITEMW *pti, BOOL bUnicode TAB_DumpItemExternalT(pti, iItem, bUnicode); - - if (infoPtr->uNumItem == 0) { - infoPtr->items = Alloc (TAB_ITEM_SIZE(infoPtr)); - infoPtr->uNumItem++; - infoPtr->iSelected = 0; + if (!(item = Alloc(TAB_ITEM_SIZE(infoPtr)))) return FALSE; + if (DPA_InsertPtr(infoPtr->items, iItem, item) == -1) + { + Free(item); + return FALSE; } - else { - LPBYTE oldItems = (LPBYTE)infoPtr->items; - infoPtr->uNumItem++; - infoPtr->items = Alloc (TAB_ITEM_SIZE(infoPtr) * infoPtr->uNumItem); - - /* pre insert copy */ - if (iItem > 0) { - memcpy (infoPtr->items, oldItems, - iItem * TAB_ITEM_SIZE(infoPtr)); - } - - /* post insert copy */ - if (iItem < infoPtr->uNumItem - 1) { - memcpy (TAB_GetItem(infoPtr, iItem + 1), - oldItems + iItem * TAB_ITEM_SIZE(infoPtr), - (infoPtr->uNumItem - iItem - 1) * TAB_ITEM_SIZE(infoPtr)); - - } - - if (iItem <= infoPtr->iSelected) + if (infoPtr->uNumItem == 0) + infoPtr->iSelected = 0; + else if (iItem <= infoPtr->iSelected) infoPtr->iSelected++; - Free (oldItems); - } - - item = TAB_GetItem(infoPtr, iItem); + infoPtr->uNumItem++; item->pszText = NULL; - if (pti->mask & TCIF_TEXT) { if (bUnicode) @@ -2885,64 +2872,49 @@ TAB_GetItemT (TAB_INFO *infoPtr, INT iItem, LPTCITEMW tabItem, BOOL bUnicode) static LRESULT TAB_DeleteItem (TAB_INFO *infoPtr, INT iItem) { - BOOL bResult = FALSE; + TAB_ITEM *item; TRACE("(%p, %d)\n", infoPtr, iItem); - if ((iItem >= 0) && (iItem < infoPtr->uNumItem)) + if (iItem < 0 || iItem >= infoPtr->uNumItem) return FALSE; + + item = TAB_GetItem(infoPtr, iItem); + Free(item->pszText); + Free(item); + infoPtr->uNumItem--; + DPA_DeletePtr(infoPtr->items, iItem); + + TAB_InvalidateTabArea(infoPtr); + + if (infoPtr->uNumItem == 0) { - TAB_ITEM *item = TAB_GetItem(infoPtr, iItem); - LPBYTE oldItems = (LPBYTE)infoPtr->items; - - TAB_InvalidateTabArea(infoPtr); - Free(item->pszText); - infoPtr->uNumItem--; - - if (!infoPtr->uNumItem) + if (infoPtr->iHotTracked >= 0) { - infoPtr->items = NULL; - if (infoPtr->iHotTracked >= 0) - { - KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER); - infoPtr->iHotTracked = -1; - } + KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER); + infoPtr->iHotTracked = -1; } - else - { - infoPtr->items = Alloc(TAB_ITEM_SIZE(infoPtr) * infoPtr->uNumItem); - if (iItem > 0) - memcpy(infoPtr->items, oldItems, iItem * TAB_ITEM_SIZE(infoPtr)); - - if (iItem < infoPtr->uNumItem) - memcpy(TAB_GetItem(infoPtr, iItem), - oldItems + (iItem + 1) * TAB_ITEM_SIZE(infoPtr), - (infoPtr->uNumItem - iItem) * TAB_ITEM_SIZE(infoPtr)); - - if (iItem <= infoPtr->iHotTracked) - { - /* When tabs move left/up, the hot track item may change */ - FIXME("Recalc hot track\n"); - } - } - Free(oldItems); - - /* Readjust the selected index */ - if (iItem == infoPtr->iSelected) - infoPtr->iSelected = -1; - else if (iItem < infoPtr->iSelected) - infoPtr->iSelected--; - - if (infoPtr->uNumItem == 0) - infoPtr->iSelected = -1; - - /* Reposition and repaint tabs */ - TAB_SetItemBounds(infoPtr); - - bResult = TRUE; + infoPtr->iSelected = -1; + } + else + { + if (iItem <= infoPtr->iHotTracked) + { + /* When tabs move left/up, the hot track item may change */ + FIXME("Recalc hot track\n"); + } } - return bResult; + /* adjust the selected index */ + if (iItem == infoPtr->iSelected) + infoPtr->iSelected = -1; + else if (iItem < infoPtr->iSelected) + infoPtr->iSelected--; + + /* reposition and repaint tabs */ + TAB_SetItemBounds(infoPtr); + + return TRUE; } static inline LRESULT TAB_DeleteAllItems (TAB_INFO *infoPtr) @@ -3063,7 +3035,7 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam) infoPtr->uHItemPadding_s = 6; infoPtr->uVItemPadding_s = 3; infoPtr->hFont = 0; - infoPtr->items = 0; + infoPtr->items = DPA_Create(8); infoPtr->hcurArrow = LoadCursorW (0, (LPWSTR)IDC_ARROW); infoPtr->iSelected = -1; infoPtr->iHotTracked = -1; @@ -3147,16 +3119,22 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam) static LRESULT TAB_Destroy (TAB_INFO *infoPtr) { - UINT iItem; + INT iItem; SetWindowLongPtrW(infoPtr->hwnd, 0, 0); - if (infoPtr->items) { - for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) { - Free (TAB_GetItem(infoPtr, iItem)->pszText); - } - Free (infoPtr->items); + for (iItem = infoPtr->uNumItem - 1; iItem >= 0; iItem--) + { + TAB_ITEM *tab = TAB_GetItem(infoPtr, iItem); + + DPA_DeletePtr(infoPtr->items, iItem); + infoPtr->uNumItem--; + + Free(tab->pszText); + Free(tab); } + DPA_Destroy(infoPtr->items); + infoPtr->items = NULL; if (infoPtr->hwndToolTip) DestroyWindow (infoPtr->hwndToolTip); @@ -3450,8 +3428,9 @@ TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_NOTIFY: return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam); - case WM_RBUTTONDOWN: - return TAB_RButtonDown (infoPtr); + case WM_RBUTTONUP: + TAB_RButtonUp (infoPtr); + return DefWindowProcW (hwnd, uMsg, wParam, lParam); case WM_MOUSEMOVE: return TAB_MouseMove (infoPtr, wParam, lParam); diff --git a/dll/win32/comctl32/theme_button.c b/dll/win32/comctl32/theme_button.c index 113e851b14f..51442dd4aca 100644 --- a/dll/win32/comctl32/theme_button.c +++ b/dll/win32/comctl32/theme_button.c @@ -246,18 +246,26 @@ static BOOL BUTTON_Paint(HTHEME theme, HWND hwnd, HDC hParamDC) DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE); DWORD dwStyleEx = GetWindowLongW(hwnd, GWL_EXSTYLE); UINT dtFlags = get_drawtext_flags(dwStyle, dwStyleEx); - ButtonState drawState = IsWindowEnabled(hwnd) ? STATE_NORMAL : STATE_DISABLED; + int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0); + ButtonState drawState; pfThemedPaint paint = btnThemedPaintFunc[ dwStyle & BUTTON_TYPE ]; - if (paint) - { - hDC = hParamDC ? hParamDC : BeginPaint(hwnd, &ps); - paint(theme, hwnd, hDC, drawState, dtFlags); - if (!hParamDC) EndPaint(hwnd, &ps); - return TRUE; - } + if(!paint) + return FALSE; - return FALSE; /* Delegate drawing to the non-themed code. */ + if(IsWindowEnabled(hwnd)) + { + if(state & BST_PUSHED) drawState = STATE_PRESSED; + else if(state & BST_HOT) drawState = STATE_HOT; + else if(state & BST_FOCUS) drawState = STATE_DEFAULTED; + else drawState = STATE_NORMAL; + } + else drawState = STATE_DISABLED; + + hDC = hParamDC ? hParamDC : BeginPaint(hwnd, &ps); + paint(theme, hwnd, hDC, drawState, dtFlags); + if (!hParamDC) EndPaint(hwnd, &ps); + return TRUE; } /********************************************************************** @@ -309,6 +317,37 @@ LRESULT CALLBACK THEMING_ButtonSubclassProc(HWND hwnd, UINT msg, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); + case WM_MOUSEMOVE: + { + TRACKMOUSEEVENT mouse_event; + mouse_event.cbSize = sizeof(TRACKMOUSEEVENT); + mouse_event.dwFlags = TME_QUERY; + if(!TrackMouseEvent(&mouse_event) || !(mouse_event.dwFlags&(TME_HOVER|TME_LEAVE))) + { + mouse_event.dwFlags = TME_HOVER|TME_LEAVE; + mouse_event.hwndTrack = hwnd; + mouse_event.dwHoverTime = 1; + TrackMouseEvent(&mouse_event); + } + break; + } + + case WM_MOUSEHOVER: + { + int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0); + SetWindowLongW(hwnd, 0, state|BST_HOT); + InvalidateRect(hwnd, NULL, FALSE); + break; + } + + case WM_MOUSELEAVE: + { + int state = (int)SendMessageW(hwnd, BM_GETSTATE, 0, 0); + SetWindowLongW(hwnd, 0, state&(~BST_HOT)); + InvalidateRect(hwnd, NULL, FALSE); + break; + } + default: /* Call old proc */ return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam); diff --git a/dll/win32/comctl32/theme_dialog.c b/dll/win32/comctl32/theme_dialog.c index 92859418e76..d64eb37cd7a 100644 --- a/dll/win32/comctl32/theme_dialog.c +++ b/dll/win32/comctl32/theme_dialog.c @@ -54,7 +54,9 @@ LRESULT CALLBACK THEMING_DialogSubclassProc (HWND hWnd, UINT msg, case WM_DESTROY: CloseThemeData ( theme ); - return THEMING_CallOriginalClass (hWnd, msg, wParam, lParam); + SetWindowTheme( hWnd, NULL, NULL ); + OpenThemeData( hWnd, NULL ); + return THEMING_CallOriginalClass (hWnd, msg, wParam, lParam); case WM_THEMECHANGED: CloseThemeData ( theme ); diff --git a/dll/win32/comctl32/theming.c b/dll/win32/comctl32/theming.c index bab87ccabf7..3ff6814c15b 100644 --- a/dll/win32/comctl32/theming.c +++ b/dll/win32/comctl32/theming.c @@ -35,15 +35,15 @@ typedef LRESULT (CALLBACK* THEMING_SUBCLASSPROC)(HWND, UINT, WPARAM, LPARAM, ULONG_PTR); extern LRESULT CALLBACK THEMING_ButtonSubclassProc (HWND, UINT, WPARAM, LPARAM, - ULONG_PTR); + ULONG_PTR) DECLSPEC_HIDDEN; extern LRESULT CALLBACK THEMING_ComboSubclassProc (HWND, UINT, WPARAM, LPARAM, - ULONG_PTR); + ULONG_PTR) DECLSPEC_HIDDEN; extern LRESULT CALLBACK THEMING_DialogSubclassProc (HWND, UINT, WPARAM, LPARAM, - ULONG_PTR); + ULONG_PTR) DECLSPEC_HIDDEN; extern LRESULT CALLBACK THEMING_EditSubclassProc (HWND, UINT, WPARAM, LPARAM, - ULONG_PTR); + ULONG_PTR) DECLSPEC_HIDDEN; extern LRESULT CALLBACK THEMING_ListBoxSubclassProc (HWND, UINT, WPARAM, LPARAM, - ULONG_PTR); + ULONG_PTR) DECLSPEC_HIDDEN; static const WCHAR dialogClass[] = {'#','3','2','7','7','0',0}; static const WCHAR comboLboxClass[] = {'C','o','m','b','o','L','b','o','x',0}; diff --git a/dll/win32/comctl32/toolbar.c b/dll/win32/comctl32/toolbar.c index 0b9dec24ee0..2af5cecc51c 100644 --- a/dll/win32/comctl32/toolbar.c +++ b/dll/win32/comctl32/toolbar.c @@ -574,7 +574,7 @@ TOOLBAR_DrawString (const TOOLBAR_INFO *infoPtr, RECT *rcText, LPCWSTR lpText, UINT state = tbcd->nmcd.uItemState; /* draw text */ - if (lpText) { + if (lpText && infoPtr->nMaxTextRows > 0) { TRACE("string=%s rect=(%s)\n", debugstr_w(lpText), wine_dbgstr_rect(rcText)); @@ -2305,7 +2305,7 @@ static LRESULT TOOLBAR_Cust_AvailDragListNotification(const CUSTDLG_INFO *custIn return 0; } -extern UINT uDragListMessage; +extern UINT uDragListMessage DECLSPEC_HIDDEN; /*********************************************************************** * TOOLBAR_CustomizeDialogProc diff --git a/dll/win32/comctl32/tooltips.c b/dll/win32/comctl32/tooltips.c index 49e20cf3515..87da4fd9ed8 100644 --- a/dll/win32/comctl32/tooltips.c +++ b/dll/win32/comctl32/tooltips.c @@ -1979,37 +1979,13 @@ TOOLTIPS_NCHitTest (const TOOLTIPS_INFO *infoPtr, WPARAM wParam, LPARAM lParam) static LRESULT TOOLTIPS_NotifyFormat (TOOLTIPS_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { - TTTOOL_INFO *toolPtr = infoPtr->tools; - LRESULT nResult; - - TRACE("infoPtr=%p wParam=%lx lParam=%p\n", infoPtr, wParam, (PVOID)lParam); - - if (lParam == NF_QUERY) { - if (toolPtr->bNotifyUnicode) { - return NFR_UNICODE; - } else { - return NFR_ANSI; - } - } - else if (lParam == NF_REQUERY) { - nResult = SendMessageW (toolPtr->hwnd, WM_NOTIFYFORMAT, - (WPARAM)infoPtr->hwndSelf, (LPARAM)NF_QUERY); - if (nResult == NFR_ANSI) { - toolPtr->bNotifyUnicode = FALSE; - TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n"); - } else if (nResult == NFR_UNICODE) { - toolPtr->bNotifyUnicode = TRUE; - TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n"); - } else { - TRACE (" -- WM_NOTIFYFORMAT returns: error!\n"); - } - return nResult; - } + FIXME ("hwnd=%p wParam=%lx lParam=%lx\n", infoPtr->hwndSelf, wParam, lParam); return 0; } + static LRESULT TOOLTIPS_Paint (const TOOLTIPS_INFO *infoPtr, HDC hDC) { @@ -2076,7 +2052,7 @@ TOOLTIPS_OnWMGetText (const TOOLTIPS_INFO *infoPtr, WPARAM size, LPWSTR pszText) { LRESULT res; - if(!infoPtr->szTipText || !size) + if(!size) return 0; res = min(strlenW(infoPtr->szTipText)+1, size);