[comctl32]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Sun, 17 Jul 2011 15:16:59 +0000 (15:16 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Sun, 17 Jul 2011 15:16:59 +0000 (15:16 +0000)
- Sync comctl32 with wine. Among it's improvements are reduced flicker in the listview and hot tracking support for themed buttons

svn path=/branches/GSoC_2011/ThemesSupport/; revision=52714

15 files changed:
dll/win32/comctl32/comboex.c
dll/win32/comctl32/comctl32undoc.c
dll/win32/comctl32/datetime.c
dll/win32/comctl32/ipaddress.c
dll/win32/comctl32/listview.c
dll/win32/comctl32/monthcal.c
dll/win32/comctl32/propsheet.c
dll/win32/comctl32/status.c
dll/win32/comctl32/syslink.c
dll/win32/comctl32/tab.c
dll/win32/comctl32/theme_button.c
dll/win32/comctl32/theme_dialog.c
dll/win32/comctl32/theming.c
dll/win32/comctl32/toolbar.c
dll/win32/comctl32/tooltips.c

index 10d8b87..3402a71 100644 (file)
@@ -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);
            }
index ff94051..cc59747 100644 (file)
@@ -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; i<mp->extview.nMaxItems; i++)
+    for(i=0; i<mp->extview.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; i<mp->cursize; 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 {
index 1ac6ba7..abfef58 100644 (file)
@@ -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; 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;
+            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;
-
-        /* 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;
 }
@@ -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);
index 1f41f91..ee8a31d 100644 (file)
@@ -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);
index d6da12d..033472c 100644 (file)
@@ -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.lower<iter2->range.lower && iter1->range.upper>iter2->range.upper) ||
+                (iter1->range.lower>iter2->range.lower && iter1->range.upper<iter2->range.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);
+    iterator_frameditems_absolute(&old_elems, infoPtr, &infoPtr->marqueeRect);
 
-    while (iterator_next(&i))
+    CopyRect(&infoPtr->marqueeRect, &rect);
+
+    CopyRect(&infoPtr->marqueeDrawRect, &rect);
+    OffsetRect(&infoPtr->marqueeDrawRect, offset->x, offset->y);
+
+    iterator_frameditems_absolute(&new_elems, infoPtr, &infoPtr->marqueeRect);
+    iterator_remove_common_items(&old_elems, &new_elems);
+
+    /* Iterate over no longer selected items */
+    while (iterator_next(&old_elems))
     {
-        if (i.nItem > -1)
+        if (old_elems.nItem > -1)
         {
-            if (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED) == 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);
 
-    iterator_destroy(&i);
-
-    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);
 
+    /* Iterate over newly selected items */
     if (GetKeyState(VK_CONTROL) & 0x8000)
         controlDown = TRUE;
 
-    while (iterator_next(&i))
+    while (iterator_next(&new_elems))
     {
-        if (i.nItem > -1)
+        if (new_elems.nItem > -1)
         {
             /* If CTRL is pressed, invert. If not, always select the item. */
-            if ((controlDown) && (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED)))
+            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, i.nItem, &item);
+            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: */
index 2091d88..edc95f4 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright 1999 Chris Morgan <cmorgan@wpi.edu> and
  *               James Abbatiello <abbeyj@wpi.edu>
  * Copyright 2000 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
- * 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.
- * 1<day<31, so everything is OK.
- */
-
+  /* no need to check styles: when selection is not valid, it is set to zero.
+     1 < day < 31, so everything is OK */
   MONTHCAL_CalcPosFromDay(infoPtr, st, &r);
   if(!IntersectRect(&r_temp, &(ps->rcPaint), &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;
+    WARN("Can't load resource\n");
+    strcpyW(buf_todayW, todayW);
+  }
 
-    if(!(infoPtr->dwStyle & MCS_NOTODAYCIRCLE)) {
-      SYSTEMTIME fake_st;
+  col = infoPtr->dwStyle & MCS_NOTODAYCIRCLE ? 0 : 1;
+  if (infoPtr->dwStyle & MCS_WEEKNUMBERS) col--;
+  MONTHCAL_CalcDayRect(infoPtr, &text_rect, col, 6);
+  box_rect = text_rect;
 
-      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);
+  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, &rtoday, DT_CALCRECT | DT_LEFT | DT_VCENTER | DT_SINGLELINE);
-    DrawTextW(hdc, buf, -1, &rtoday, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
+  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);
 
-    SelectObject(hdc, infoPtr->hFont);
+  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;
 }
index 2172a85..bcd904c 100644 (file)
@@ -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);
index eeaf299..427fb76 100644 (file)
@@ -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));
index 9340fc6..c13267e 100644 (file)
@@ -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 );
index fe82d59..ff1b953 100644 (file)
@@ -52,6 +52,7 @@
  *
  */
 
+#include <assert.h>
 #include <stdarg.h>
 #include <string.h>
 
@@ -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))
-    {
-        TAB_ITEM *item = TAB_GetItem(infoPtr, iItem);
-        LPBYTE oldItems = (LPBYTE)infoPtr->items;
+    if (iItem < 0 || iItem >= infoPtr->uNumItem) return FALSE;
 
-       TAB_InvalidateTabArea(infoPtr);
-        Free(item->pszText);
-       infoPtr->uNumItem--;
+    item = TAB_GetItem(infoPtr, iItem);
+    Free(item->pszText);
+    Free(item);
+    infoPtr->uNumItem--;
+    DPA_DeletePtr(infoPtr->items, iItem);
 
-       if (!infoPtr->uNumItem)
+    TAB_InvalidateTabArea(infoPtr);
+
+    if (infoPtr->uNumItem == 0)
+    {
+        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;
+        infoPtr->iSelected = -1;
+    }
+    else
+    {
+        if (iItem <= infoPtr->iHotTracked)
+        {
+            /* When tabs move left/up, the hot track item may change */
+            FIXME("Recalc hot track\n");
+        }
+    }
 
-       /* Reposition and repaint tabs */
-       TAB_SetItemBounds(infoPtr);
+    /* adjust the selected index */
+    if (iItem == infoPtr->iSelected)
+        infoPtr->iSelected = -1;
+    else if (iItem < infoPtr->iSelected)
+        infoPtr->iSelected--;
 
-       bResult = TRUE;
-    }
+    /* reposition and repaint tabs */
+    TAB_SetItemBounds(infoPtr);
 
-    return bResult;
+    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);
index 113e851..51442dd 100644 (file)
@@ -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)
+    if(!paint)
+        return FALSE;
+
+    if(IsWindowEnabled(hwnd))
     {
-        hDC = hParamDC ? hParamDC : BeginPaint(hwnd, &ps);
-        paint(theme, hwnd, hDC, drawState, dtFlags);
-        if (!hParamDC) EndPaint(hwnd, &ps);
-        return TRUE;
+        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;
 
-    return FALSE; /* Delegate drawing to the non-themed code. */
+    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);
index 9285941..d64eb37 100644 (file)
@@ -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 );
index bab87cc..3ff6814 100644 (file)
@@ -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};
index 0b9dec2..2af5cec 100644 (file)
@@ -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
index 49e20cf..87da4fd 100644 (file)
@@ -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);