I don't like this, but add the treeview refresh hack.
[reactos.git] / reactos / dll / win32 / comctl32 / treeview.c
index 0eff5f9..8d2a6f3 100644 (file)
  *
  * Note that TREEVIEW_INFO * and HTREEITEM are the same thing.
  *
- * Note2: All items always! have valid (allocated) pszText field.
- *      If item's text == LPSTR_TEXTCALLBACKA we allocate buffer
+ * Note2: If item's text == LPSTR_TEXTCALLBACKA we allocate buffer
  *      of size TEXT_CALLBACK_SIZE in DoSetItem.
  *      We use callbackMask to keep track of fields to be updated.
  *
  * TODO:
- *   missing notifications: NM_SETCURSOR, TVN_GETINFOTIP, TVN_KEYDOWN,
+ *   missing notifications: TVN_GETINFOTIP, TVN_KEYDOWN,
  *      TVN_SETDISPINFO, TVN_SINGLEEXPAND
  *
  *   missing styles: TVS_FULLROWSELECT, TVS_INFOTIP, TVS_RTLREADING,
@@ -64,6 +63,8 @@
 #include "wine/unicode.h"
 #include "wine/debug.h"
 
+WINE_DEFAULT_DEBUG_CHANNEL(treeview);
+
 /* internal structures */
 
 typedef struct _TREEITEM    /* HTREEITEM is a _TREEINFO *. */
@@ -120,6 +121,7 @@ typedef struct tagTREEVIEW_INFO
   HTREEITEM     selectedItem;   /* handle to selected item or 0 if none */
   HTREEITEM     hotItem;        /* handle currently under cursor, 0 if none */
   HTREEITEM    focusedItem;    /* item that was under the cursor when WM_LBUTTONDOWN was received */
+  HTREEITEM     editItem;       /* item being edited with builtin edit box */
 
   HTREEITEM     firstVisible;   /* handle to first visible item */
   LONG          maxVisibleOrder;
@@ -153,10 +155,10 @@ typedef struct tagTREEVIEW_INFO
   int           stateImageWidth;
   HDPA          items;
 
-  DWORD lastKeyPressTimestamp; /* Added */
-  WPARAM charCode; /* Added */
-  INT nSearchParamLength; /* Added */
-  WCHAR szSearchParam[ MAX_PATH ]; /* Added */
+  DWORD lastKeyPressTimestamp;
+  WPARAM charCode;
+  INT nSearchParamLength;
+  WCHAR szSearchParam[ MAX_PATH ];
 } TREEVIEW_INFO;
 
 
@@ -169,7 +171,7 @@ typedef struct tagTREEVIEW_INFO
 #define TV_VSCROLL     0x02    /* (horizontal/vertical) */
 #define TV_LDRAG               0x04    /* Lbutton pushed to start drag */
 #define TV_LDRAGGING   0x08    /* Lbutton pushed, mouse moved. */
-#define TV_RDRAG               0x10    /* dito Rbutton */
+#define TV_RDRAG               0x10    /* ditto Rbutton */
 #define TV_RDRAGGING   0x20
 
 /* bitflags for infoPtr->timer */
@@ -177,14 +179,6 @@ typedef struct tagTREEVIEW_INFO
 #define TV_EDIT_TIMER    2
 #define TV_EDIT_TIMER_SET 2
 
-
-VOID TREEVIEW_Register (VOID);
-VOID TREEVIEW_Unregister (VOID);
-
-
-WINE_DEFAULT_DEBUG_CHANNEL(treeview);
-
-
 #define TEXT_CALLBACK_SIZE 260
 
 #define TREEVIEW_LEFT_MARGIN 8
@@ -197,6 +191,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(treeview);
 #define OVERLAYIMAGEINDEX(x) (((x) >> 8) & 0x0f)
 #define ISVISIBLE(x)         ((x)->visibleOrder >= 0)
 
+#define GETLINECOLOR(x) ((x) == CLR_DEFAULT ? comctl32_color.clrGrayText   : (x))
+#define GETBKCOLOR(x)   ((x) == CLR_NONE    ? comctl32_color.clrWindow     : (x))
+#define GETTXTCOLOR(x)  ((x) == CLR_NONE    ? comctl32_color.clrWindowText : (x))
+#define GETINSCOLOR(x)  ((x) == CLR_DEFAULT ? comctl32_color.clrBtnText    : (x))
 
 static const WCHAR themeClass[] = { 'T','r','e','e','v','i','e','w',0 };
 
@@ -213,8 +211,6 @@ static LRESULT TREEVIEW_RButtonUp(const TREEVIEW_INFO *, const POINT *);
 static LRESULT TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel);
 static VOID TREEVIEW_UpdateScrollBars(TREEVIEW_INFO *infoPtr);
 static LRESULT TREEVIEW_HScroll(TREEVIEW_INFO *, WPARAM);
-static INT TREEVIEW_NotifyFormat (TREEVIEW_INFO *infoPtr, HWND wParam, UINT lParam);
-
 
 /* Random Utilities *****************************************************/
 
@@ -241,8 +237,6 @@ TREEVIEW_GetInfoPtr(HWND hwnd)
 static inline int
 TREEVIEW_GetItemIndex(const TREEVIEW_INFO *infoPtr, HTREEITEM handle)
 {
-    assert(infoPtr != NULL);
-
     return DPA_GetPtrIndex(infoPtr->items, handle);
 }
 
@@ -407,8 +401,6 @@ TREEVIEW_GetPrevListItem(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *tvIt
 static TREEVIEW_ITEM *
 TREEVIEW_GetNextListItem(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *tvItem)
 {
-    assert(tvItem != NULL);
-
     /*
      * If this item has children and is expanded, return the first child
      */
@@ -518,8 +510,7 @@ TREEVIEW_SendSimpleNotify(const TREEVIEW_INFO *infoPtr, UINT code)
     nmhdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID);
     nmhdr.code = get_notifycode(infoPtr, code);
 
-    return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
-                                 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
+    return (BOOL)TREEVIEW_SendRealNotify(infoPtr, nmhdr.idFrom, (LPARAM)&nmhdr);
 }
 
 static VOID
@@ -582,9 +573,7 @@ TREEVIEW_SendTreeviewNotify(const TREEVIEW_INFO *infoPtr, UINT code, UINT action
     nmhdr.ptDrag.x = 0;
     nmhdr.ptDrag.y = 0;
 
-    ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr,
-                              (WPARAM)nmhdr.hdr.idFrom,
-                             (LPARAM)&nmhdr);
+    ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr, nmhdr.hdr.idFrom, (LPARAM)&nmhdr);
     if (!infoPtr->bNtfUnicode)
     {
        Free(nmhdr.itemOld.pszText);
@@ -614,9 +603,7 @@ TREEVIEW_SendTreeviewDnDNotify(const TREEVIEW_INFO *infoPtr, UINT code,
     nmhdr.ptDrag.x = pt.x;
     nmhdr.ptDrag.y = pt.y;
 
-    return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
-                             (WPARAM)nmhdr.hdr.idFrom,
-                             (LPARAM)&nmhdr);
+    return (BOOL)TREEVIEW_SendRealNotify(infoPtr, nmhdr.hdr.idFrom, (LPARAM)&nmhdr);
 }
 
 
@@ -644,9 +631,7 @@ TREEVIEW_SendCustomDrawNotify(const TREEVIEW_INFO *infoPtr, DWORD dwDrawStage,
     nmcdhdr.clrTextBk = infoPtr->clrBk;
     nmcdhdr.iLevel = 0;
 
-    return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
-                             (WPARAM)nmcd->hdr.idFrom,
-                             (LPARAM)&nmcdhdr);
+    return (BOOL)TREEVIEW_SendRealNotify(infoPtr, nmcd->hdr.idFrom, (LPARAM)&nmcdhdr);
 }
 
 
@@ -691,11 +676,9 @@ TREEVIEW_SendCustomDrawItemNotify(const TREEVIEW_INFO *infoPtr, HDC hdc,
          nmcd->dwDrawStage, nmcd->hdc, nmcd->dwItemSpec,
          nmcd->uItemState, nmcd->lItemlParam);
 
-    retval = TREEVIEW_SendRealNotify(infoPtr,
-                          (WPARAM)nmcd->hdr.idFrom,
-                         (LPARAM)nmcdhdr);
+    retval = TREEVIEW_SendRealNotify(infoPtr, nmcd->hdr.idFrom, (LPARAM)nmcdhdr);
 
-    return (BOOL)retval;
+    return retval;
 }
 
 static BOOL
@@ -724,7 +707,7 @@ static void
 TREEVIEW_UpdateDispInfo(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
                        UINT mask)
 {
-    NMTVDISPINFOW callback;
+    NMTVDISPINFOEXW callback;
     HWND hwnd = infoPtr->hwnd;
 
     TRACE("mask %x callbackMask %x\n", mask, wineItem->callbackMask);
@@ -750,8 +733,7 @@ TREEVIEW_UpdateDispInfo(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
     if (mask & TVIF_TEXT)
        wineItem->textWidth = 0;
 
-    TREEVIEW_SendRealNotify(infoPtr,
-                            (WPARAM)callback.hdr.idFrom, (LPARAM)&callback);
+    TREEVIEW_SendRealNotify(infoPtr, callback.hdr.idFrom, (LPARAM)&callback);
 
     /* It may have changed due to a call to SetItem. */
     mask &= wineItem->callbackMask;
@@ -766,7 +748,7 @@ TREEVIEW_UpdateDispInfo(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
                                           (LPSTR)callback.item.pszText, -1,
                                            NULL, 0);
            buflen = max((len)*sizeof(WCHAR), TEXT_CALLBACK_SIZE);
-           newText = (LPWSTR)ReAlloc(wineItem->pszText, buflen);
+            newText = ReAlloc(wineItem->pszText, buflen);
 
            TRACE("returned str %s, len=%d, buflen=%d\n",
                  debugstr_a((LPSTR)callback.item.pszText), len, buflen);
@@ -808,7 +790,7 @@ TREEVIEW_UpdateDispInfo(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
                                          (LPSTR)callback.item.pszText, -1,
                                            NULL, 0);
            buflen = max((len)*sizeof(WCHAR), TEXT_CALLBACK_SIZE);
-           newText = (LPWSTR)Alloc(buflen);
+            newText = Alloc(buflen);
 
            TRACE("same buffer str %s, len=%d, buflen=%d\n",
                  debugstr_a((LPSTR)callback.item.pszText), len, buflen);
@@ -856,6 +838,23 @@ TREEVIEW_HasChildren(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem)
     return wineItem->cChildren > 0;
 }
 
+static INT TREEVIEW_NotifyFormat (TREEVIEW_INFO *infoPtr, HWND hwndFrom, UINT nCommand)
+{
+    INT format;
+
+    TRACE("(hwndFrom=%p, nCommand=%d)\n", hwndFrom, nCommand);
+
+    if (nCommand != NF_REQUERY) return 0;
+
+    format = SendMessageW(hwndFrom, WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwnd, NF_QUERY);
+    TRACE("format=%d\n", format);
+
+    if (format != NFR_ANSI && format != NFR_UNICODE) return 0;
+
+    infoPtr->bNtfUnicode = (format == NFR_UNICODE);
+
+    return format;
+}
 
 /* Item Position ********************************************************/
 
@@ -873,7 +872,7 @@ TREEVIEW_ComputeItemInternalMetrics(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM
                > TVS_LINESATROOT);
 #endif
 
-    item->linesOffset = infoPtr->uIndent * (item->iLevel + lar - 1)
+    item->linesOffset = infoPtr->uIndent * (lar ? item->iLevel : item->iLevel - 1)
        - infoPtr->scrollX;
     item->stateOffset = item->linesOffset + infoPtr->uIndent;
     item->imageOffset = item->stateOffset
@@ -1033,7 +1032,6 @@ static void
 TREEVIEW_FreeItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
 {
     DPA_DeletePtr(infoPtr->items, DPA_GetPtrIndex(infoPtr->items, item));
-    Free(item);
     if (infoPtr->selectedItem == item)
         infoPtr->selectedItem = NULL;
     if (infoPtr->hotItem == item)
@@ -1046,6 +1044,7 @@ TREEVIEW_FreeItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
         infoPtr->dropItem = NULL;
     if (infoPtr->insertMarkItem == item)
         infoPtr->insertMarkItem = NULL;
+    Free(item);
 }
 
 
@@ -1059,7 +1058,6 @@ static void
 TREEVIEW_InsertBefore(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling,
                      TREEVIEW_ITEM *parent)
 {
-    assert(newItem != NULL);
     assert(parent != NULL);
 
     if (sibling != NULL)
@@ -1092,7 +1090,6 @@ static void
 TREEVIEW_InsertAfter(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling,
                     TREEVIEW_ITEM *parent)
 {
-    assert(newItem != NULL);
     assert(parent != NULL);
 
     if (sibling != NULL)
@@ -1129,7 +1126,7 @@ TREEVIEW_DoSetItemT(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
     if (tvItem->mask & TVIF_TEXT)
     {
         wineItem->textWidth = 0; /* force width recalculation */
-       if (tvItem->pszText != LPSTR_TEXTCALLBACKW) /* covers != TEXTCALLBACKA too */
+       if (tvItem->pszText != LPSTR_TEXTCALLBACKW && tvItem->pszText != NULL) /* covers != TEXTCALLBACKA too, and undocumented: pszText of NULL also means TEXTCALLBACK */
        {
             int len;
             LPWSTR newText;
@@ -1237,7 +1234,7 @@ TREEVIEW_InsertItemT(TREEVIEW_INFO *infoPtr, const TVINSERTSTRUCTW *ptdi, BOOL i
        if (!TREEVIEW_ValidItem(infoPtr, parentItem))
        {
            WARN("invalid parent %p\n", parentItem);
-           return (LRESULT)(HTREEITEM)NULL;
+            return 0;
        }
     }
 
@@ -1268,13 +1265,14 @@ TREEVIEW_InsertItemT(TREEVIEW_INFO *infoPtr, const TVINSERTSTRUCTW *ptdi, BOOL i
 
     newItem = TREEVIEW_AllocateItem(infoPtr);
     if (newItem == NULL)
-       return (LRESULT)(HTREEITEM)NULL;
+        return 0;
 
     newItem->parent = parentItem;
     newItem->iIntegral = 1;
+    newItem->visibleOrder = -1;
 
     if (!TREEVIEW_DoSetItemT(infoPtr, newItem, tvItem, isW))
-       return (LRESULT)(HTREEITEM)NULL;
+        return 0;
 
     /* After this point, nothing can fail. (Except for TVI_SORT.) */
 
@@ -1384,6 +1382,8 @@ TREEVIEW_InsertItemT(TREEVIEW_INFO *infoPtr, const TVINSERTSTRUCTW *ptdi, BOOL i
 
     TREEVIEW_VerifyTree(infoPtr);
 
+    if (!infoPtr->bRedraw) return (LRESULT)newItem;
+
     if (parentItem == infoPtr->root ||
         (ISVISIBLE(parentItem) && parentItem->state & TVIS_EXPANDED))
     {
@@ -1409,8 +1409,6 @@ TREEVIEW_InsertItemT(TREEVIEW_INFO *infoPtr, const TVINSERTSTRUCTW *ptdi, BOOL i
     }
     else
     {
-       newItem->visibleOrder = -1;
-
        /* refresh treeview if newItem is the first item inserted under parentItem */
        if (ISVISIBLE(parentItem) && newItem->prevSibling == newItem->nextSibling)
        {
@@ -1581,6 +1579,7 @@ TREEVIEW_DeleteItem(TREEVIEW_INFO *infoPtr, HTREEITEM wineItem)
 
     TREEVIEW_VerifyTree(infoPtr);
 
+    if (!infoPtr->bRedraw) return TRUE;
 
     if (visible)
     {
@@ -1601,14 +1600,18 @@ TREEVIEW_DeleteItem(TREEVIEW_INFO *infoPtr, HTREEITEM wineItem)
 
 /* Get/Set Messages *********************************************************/
 static LRESULT
-TREEVIEW_SetRedraw(TREEVIEW_INFO* infoPtr, WPARAM wParam, LPARAM lParam)
+TREEVIEW_SetRedraw(TREEVIEW_INFO* infoPtr, WPARAM wParam)
 {
-  if(wParam)
-    infoPtr->bRedraw = TRUE;
-  else
-    infoPtr->bRedraw = FALSE;
+    infoPtr->bRedraw = wParam ? TRUE : FALSE;
 
-  return 0;
+    if (infoPtr->bRedraw)
+    {
+        TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root);
+        TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL);
+        TREEVIEW_UpdateScrollBars(infoPtr);
+        TREEVIEW_Invalidate(infoPtr, NULL);
+    }
+    return 0;
 }
 
 static LRESULT
@@ -1695,10 +1698,10 @@ TREEVIEW_GetImageList(const TREEVIEW_INFO *infoPtr, WPARAM wParam)
 
     switch (wParam)
     {
-    case (WPARAM)TVSIL_NORMAL:
+    case TVSIL_NORMAL:
        return (LRESULT)infoPtr->himlNormal;
 
-    case (WPARAM)TVSIL_STATE:
+    case TVSIL_STATE:
        return (LRESULT)infoPtr->himlState;
 
     default:
@@ -1752,7 +1755,7 @@ TREEVIEW_SetImageList(TREEVIEW_INFO *infoPtr, WPARAM wParam, HIMAGELIST himlNew)
 
     switch (wParam)
     {
-    case (WPARAM)TVSIL_NORMAL:
+    case TVSIL_NORMAL:
        himlOld = infoPtr->himlNormal;
        infoPtr->himlNormal = himlNew;
 
@@ -1767,7 +1770,7 @@ TREEVIEW_SetImageList(TREEVIEW_INFO *infoPtr, WPARAM wParam, HIMAGELIST himlNew)
 
        break;
 
-    case (WPARAM)TVSIL_STATE:
+    case TVSIL_STATE:
        himlOld = infoPtr->himlState;
        infoPtr->himlState = himlNew;
 
@@ -1881,6 +1884,7 @@ TREEVIEW_SetFont(TREEVIEW_INFO *infoPtr, HFONT hFont, BOOL bRedraw)
     infoPtr->hFont = hFont ? hFont : infoPtr->hDefaultFont;
 
     DeleteObject(infoPtr->hBoldFont);
+    DeleteObject(infoPtr->hUnderlineFont);
     infoPtr->hBoldFont = TREEVIEW_CreateBoldFont(infoPtr->hFont);
     infoPtr->hUnderlineFont = TREEVIEW_CreateUnderlineFont(infoPtr->hFont);
 
@@ -2043,8 +2047,7 @@ TREEVIEW_GetItemRect(const TREEVIEW_INFO *infoPtr, BOOL fTextRect, LPRECT lpRect
        *lpRect = wineItem->rect;
     }
 
-    TRACE("%s [L:%d R:%d T:%d B:%d]\n", fTextRect ? "text" : "item",
-         lpRect->left, lpRect->right, lpRect->top, lpRect->bottom);
+    TRACE("%s [%s]\n", fTextRect ? "text" : "item", wine_dbgstr_rect(lpRect));
 
     return TRUE;
 }
@@ -2052,7 +2055,7 @@ TREEVIEW_GetItemRect(const TREEVIEW_INFO *infoPtr, BOOL fTextRect, LPRECT lpRect
 static inline LRESULT
 TREEVIEW_GetVisibleCount(const TREEVIEW_INFO *infoPtr)
 {
-    /* Suprise! This does not take integral height into account. */
+    /* Surprise! This does not take integral height into account. */
     return infoPtr->clientHeight / infoPtr->uItemHeight;
 }
 
@@ -2100,7 +2103,12 @@ TREEVIEW_GetItemT(const TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem, BOOL isW)
 
     if (tvItem->mask & TVIF_TEXT)
     {
-        if (isW)
+        if (wineItem->pszText == NULL)
+        {
+            if (tvItem->cchTextMax > 0)
+                tvItem->pszText[0] = '\0';
+        }
+        else if (isW)
         {
             if (wineItem->pszText == LPSTR_TEXTCALLBACKW)
             {
@@ -2148,7 +2156,7 @@ TREEVIEW_SetItemT(TREEVIEW_INFO *infoPtr, const TVITEMEXW *tvItem, BOOL isW)
     if (!TREEVIEW_ValidItem(infoPtr, wineItem))
        return FALSE;
 
-    /* store the orignal item values */
+    /* store the original item values */
     originalItem = *wineItem;
 
     if (!TREEVIEW_DoSetItemT(infoPtr, wineItem, tvItem, isW))
@@ -2319,11 +2327,12 @@ TREEVIEW_DrawItemLines(const TREEVIEW_INFO *infoPtr, HDC hdc, const TREEVIEW_ITE
                 & (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS))
                > TVS_LINESATROOT);
     HBRUSH hbr, hbrOld;
+    COLORREF clrBk = GETBKCOLOR(infoPtr->clrBk);
 
     if (!lar && item->iLevel == 0)
        return;
 
-    hbr    = CreateSolidBrush(infoPtr->clrBk);
+    hbr    = CreateSolidBrush(clrBk);
     hbrOld = SelectObject(hdc, hbr);
 
     centerx = (item->linesOffset + item->stateOffset) / 2;
@@ -2337,7 +2346,7 @@ TREEVIEW_DrawItemLines(const TREEVIEW_INFO *infoPtr, HDC hdc, const TREEVIEW_ITE
 
        /* Get a dotted grey pen */
         lb.lbStyle = BS_SOLID;
-        lb.lbColor = infoPtr->clrLine;
+        lb.lbColor = GETLINECOLOR(infoPtr->clrLine);
         hNewPen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL);
        hOldPen = SelectObject(hdc, hNewPen);
 
@@ -2407,20 +2416,24 @@ TREEVIEW_DrawItemLines(const TREEVIEW_INFO *infoPtr, HDC hdc, const TREEVIEW_ITE
                 /* plussize = ceil(rectsize * 3/4) */
                 LONG plussize = (rectsize + 1) * 3 / 4;
 
-                HPEN hNewPen  = CreatePen(PS_SOLID, 0, infoPtr->clrLine);
-                HPEN hOldPen  = SelectObject(hdc, hNewPen);
+                HPEN new_pen  = CreatePen(PS_SOLID, 0, GETLINECOLOR(infoPtr->clrLine));
+                HPEN old_pen  = SelectObject(hdc, new_pen);
 
                 Rectangle(hdc, centerx - rectsize - 1, centery - rectsize - 1,
                           centerx + rectsize + 2, centery + rectsize + 2);
 
-                SelectObject(hdc, hOldPen);
-                DeleteObject(hNewPen);
+                SelectObject(hdc, old_pen);
+                DeleteObject(new_pen);
+
+                /* draw +/- signs with current text color */
+                new_pen = CreatePen(PS_SOLID, 0, GETTXTCOLOR(infoPtr->clrText));
+                old_pen = SelectObject(hdc, new_pen);
 
                 if (height < 18 || width < 18)
                 {
                     MoveToEx(hdc, centerx - plussize + 1, centery, NULL);
                     LineTo(hdc, centerx + plussize, centery);
-
+    
                     if (!(item->state & TVIS_EXPANDED))
                     {
                         MoveToEx(hdc, centerx, centery - plussize + 1, NULL);
@@ -2431,15 +2444,18 @@ TREEVIEW_DrawItemLines(const TREEVIEW_INFO *infoPtr, HDC hdc, const TREEVIEW_ITE
                 {
                     Rectangle(hdc, centerx - plussize + 1, centery - 1,
                     centerx + plussize, centery + 2);
-
+    
                     if (!(item->state & TVIS_EXPANDED))
                     {
                         Rectangle(hdc, centerx - 1, centery - plussize + 1,
                         centerx + 2, centery + plussize);
-                        SetPixel(hdc, centerx - 1, centery, infoPtr->clrBk);
-                        SetPixel(hdc, centerx + 1, centery, infoPtr->clrBk);
+                        SetPixel(hdc, centerx - 1, centery, clrBk);
+                        SetPixel(hdc, centerx + 1, centery, clrBk);
                     }
                 }
+
+                SelectObject(hdc, old_pen);
+                DeleteObject(new_pen);
             }
        }
     }
@@ -2471,27 +2487,22 @@ TREEVIEW_DrawItem(const TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem
     {
        if ((wineItem->state & TVIS_DROPHILITED) || inFocus)
        {
-           nmcdhdr.clrTextBk = GetSysColor(COLOR_HIGHLIGHT);
-           nmcdhdr.clrText   = GetSysColor(COLOR_HIGHLIGHTTEXT);
+           nmcdhdr.clrTextBk = comctl32_color.clrHighlight;
+           nmcdhdr.clrText   = comctl32_color.clrHighlightText;
        }
        else
        {
-           nmcdhdr.clrTextBk = GetSysColor(COLOR_BTNFACE);
-           if (infoPtr->clrText == -1)
-               nmcdhdr.clrText = GetSysColor(COLOR_WINDOWTEXT);
-           else
-               nmcdhdr.clrText = infoPtr->clrText;
+           nmcdhdr.clrTextBk = comctl32_color.clrBtnFace;
+           nmcdhdr.clrText   = GETTXTCOLOR(infoPtr->clrText);
        }
     }
     else
     {
-       nmcdhdr.clrTextBk = infoPtr->clrBk;
+       nmcdhdr.clrTextBk = GETBKCOLOR(infoPtr->clrBk);
        if ((infoPtr->dwStyle & TVS_TRACKSELECT) && (wineItem == infoPtr->hotItem))
            nmcdhdr.clrText = comctl32_color.clrHighlight;
-       else if (infoPtr->clrText == -1)
-           nmcdhdr.clrText = GetSysColor(COLOR_WINDOWTEXT);
        else
-           nmcdhdr.clrText = infoPtr->clrText;
+           nmcdhdr.clrText = GETTXTCOLOR(infoPtr->clrText);
     }
 
     hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, wineItem));
@@ -2590,9 +2601,8 @@ TREEVIEW_DrawItem(const TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem
            rcText.left = wineItem->textOffset;
            rcText.right = rcText.left + wineItem->textWidth + 4;
 
-            TRACE("drawing text %s at (%d,%d)-(%d,%d)\n",
-                 debugstr_w(wineItem->pszText),
-                 rcText.left, rcText.top, rcText.right, rcText.bottom);
+            TRACE("drawing text %s at (%s)\n",
+                  debugstr_w(wineItem->pszText), wine_dbgstr_rect(&rcText));
 
            /* Draw it */
            ExtTextOutW(hdc, rcText.left + 2, rcText.top + 1,
@@ -2601,7 +2611,7 @@ TREEVIEW_DrawItem(const TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem
                        wineItem->pszText,
                        lstrlenW(wineItem->pszText),
                        NULL);
-
+                       
            /* Draw the box around the selected item */
            if ((wineItem == infoPtr->selectedItem) && inFocus)
            {
@@ -2624,7 +2634,7 @@ TREEVIEW_DrawItem(const TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem
        int offset;
        int left, right;
 
-       hNewPen = CreatePen(PS_SOLID, 2, infoPtr->clrInsertMark);
+       hNewPen = CreatePen(PS_SOLID, 2, GETINSCOLOR(infoPtr->clrInsertMark));
        hOldPen = SelectObject(hdc, hNewPen);
 
        if (infoPtr->insertBeforeorAfter)
@@ -2792,16 +2802,27 @@ TREEVIEW_UpdateScrollBars(TREEVIEW_INFO *infoPtr)
        infoPtr->uInternalStatus &= ~TV_HSCROLL;
 }
 
+static void
+TREEVIEW_FillBkgnd(const TREEVIEW_INFO *infoPtr, HDC hdc, const RECT *rc)
+{
+    HBRUSH hBrush;
+    COLORREF clrBk = GETBKCOLOR(infoPtr->clrBk);
+
+    hBrush =  CreateSolidBrush(clrBk);
+    FillRect(hdc, rc, hBrush);
+    DeleteObject(hBrush);
+}
+
 /* CtrlSpy doesn't mention this, but CorelDRAW's object manager needs it. */
 static LRESULT
-TREEVIEW_EraseBackground(const TREEVIEW_INFO *infoPtr, HDC hDC)
+TREEVIEW_EraseBackground(const TREEVIEW_INFO *infoPtr, HDC hdc)
 {
-    HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
     RECT rect;
 
+    TRACE("%p\n", infoPtr);
+
     GetClientRect(infoPtr->hwnd, &rect);
-    FillRect(hDC, &rect, hBrush);
-    DeleteObject(hBrush);
+    TREEVIEW_FillBkgnd(infoPtr, hdc, &rect);
 
     return 1;
 }
@@ -2844,22 +2865,35 @@ TREEVIEW_Refresh(TREEVIEW_INFO *infoPtr, HDC hdc, const RECT *rc)
        }
     }
 
+    //
+    // This is correct, but is causes and infinite loop of WM_PAINT messages, resulting
+    // in continuous painting of the scroll bar in reactos. Comment out until the real
+    // bug is found
+    // 
+    //TREEVIEW_UpdateScrollBars(infoPtr);
+
     if (infoPtr->cdmode & CDRF_NOTIFYPOSTPAINT)
        infoPtr->cdmode =
            TREEVIEW_SendCustomDrawNotify(infoPtr, CDDS_POSTPAINT, hdc, rect);
 }
 
+static inline void
+TREEVIEW_InvalidateItem(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *item)
+{
+    if (item) InvalidateRect(infoPtr->hwnd, &item->rect, TRUE);
+}
+
 static void
 TREEVIEW_Invalidate(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *item)
 {
-    if (item != NULL)
+    if (item)
        InvalidateRect(infoPtr->hwnd, &item->rect, TRUE);
     else
         InvalidateRect(infoPtr->hwnd, NULL, TRUE);
 }
 
 static LRESULT
-TREEVIEW_Paint(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+TREEVIEW_Paint(TREEVIEW_INFO *infoPtr, HDC hdc_ref)
 {
     HDC hdc;
     PAINTSTRUCT ps;
@@ -2867,27 +2901,48 @@ TREEVIEW_Paint(TREEVIEW_INFO *infoPtr, WPARAM wParam)
 
     TRACE("\n");
 
-    if (wParam)
+    if (hdc_ref)
     {
-        hdc = (HDC)wParam;
+        hdc = hdc_ref;
         GetClientRect(infoPtr->hwnd, &rc);
-        TREEVIEW_EraseBackground(infoPtr, hdc);
     }
     else
     {
         hdc = BeginPaint(infoPtr->hwnd, &ps);
-        rc = ps.rcPaint;
+        rc  = ps.rcPaint;
+        if(ps.fErase)
+            TREEVIEW_FillBkgnd(infoPtr, hdc, &rc);
     }
 
     if(infoPtr->bRedraw) /* WM_SETREDRAW sets bRedraw */
         TREEVIEW_Refresh(infoPtr, hdc, &rc);
 
-    if (!wParam)
+    if (!hdc_ref)
        EndPaint(infoPtr->hwnd, &ps);
 
     return 0;
 }
 
+static LRESULT
+TREEVIEW_PrintClient(TREEVIEW_INFO *infoPtr, HDC hdc, DWORD options)
+{
+    FIXME("Partial Stub: (hdc=%p options=0x%08x)\n", hdc, options);
+
+    if ((options & PRF_CHECKVISIBLE) && !IsWindowVisible(infoPtr->hwnd))
+        return 0;
+
+    if (options & PRF_ERASEBKGND)
+        TREEVIEW_EraseBackground(infoPtr, hdc);
+
+    if (options & PRF_CLIENT)
+    {
+        RECT rc;
+        GetClientRect(infoPtr->hwnd, &rc);
+        TREEVIEW_Refresh(infoPtr, hdc, &rc);
+    }
+
+    return 0;
+}
 
 /* Sorting **************************************************************/
 
@@ -2926,7 +2981,7 @@ TREEVIEW_SortOnName(TREEVIEW_ITEM *first, TREEVIEW_ITEM *second,
 
 /* Returns the number of physical children belonging to item. */
 static INT
-TREEVIEW_CountChildren(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *item)
+TREEVIEW_CountChildren(const TREEVIEW_ITEM *item)
 {
     INT cChildren = 0;
     HTREEITEM hti;
@@ -2940,7 +2995,7 @@ TREEVIEW_CountChildren(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *item)
 /* Returns a DPA containing a pointer to each physical child of item in
  * sibling order. If item has no children, an empty DPA is returned. */
 static HDPA
-TREEVIEW_BuildChildDPA(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *item)
+TREEVIEW_BuildChildDPA(const TREEVIEW_ITEM *item)
 {
     HTREEITEM child = item->firstChild;
 
@@ -2971,7 +3026,7 @@ TREEVIEW_BuildChildDPA(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *item)
  */
 
 static LRESULT
-TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, BOOL fRecurse, HTREEITEM parent,
+TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, HTREEITEM parent,
              LPTVSORTCB pSort)
 {
     INT cChildren;
@@ -3000,7 +3055,7 @@ TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, BOOL fRecurse, HTREEITEM parent,
        lpCompare = (LPARAM)infoPtr;
     }
 
-    cChildren = TREEVIEW_CountChildren(infoPtr, parent);
+    cChildren = TREEVIEW_CountChildren(parent);
 
     /* Make sure there is something to sort */
     if (cChildren > 1)
@@ -3011,7 +3066,7 @@ TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, BOOL fRecurse, HTREEITEM parent,
        HTREEITEM nextItem = 0;
        HTREEITEM prevItem = 0;
 
-       HDPA sortList = TREEVIEW_BuildChildDPA(infoPtr, parent);
+       HDPA sortList = TREEVIEW_BuildChildDPA(parent);
 
        if (sortList == NULL)
            return FALSE;
@@ -3022,10 +3077,10 @@ TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, BOOL fRecurse, HTREEITEM parent,
        /* The order of DPA entries has been changed, so fixup the
         * nextSibling and prevSibling pointers. */
 
-       item = (HTREEITEM)DPA_GetPtr(sortList, count++);
-       while ((nextItem = (HTREEITEM)DPA_GetPtr(sortList, count++)) != NULL)
+        item = DPA_GetPtr(sortList, count++);
+        while ((nextItem = DPA_GetPtr(sortList, count++)) != NULL)
        {
-           /* link the two current item toghether */
+           /* link the two current item together */
            item->nextSibling = nextItem;
            nextItem->prevSibling = item;
 
@@ -3092,9 +3147,9 @@ TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, BOOL fRecurse, HTREEITEM parent,
  * and sort the children of the TV item specified in lParam
  */
 static LRESULT
-TREEVIEW_SortChildrenCB(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPTVSORTCB pSort)
+TREEVIEW_SortChildrenCB(TREEVIEW_INFO *infoPtr, LPTVSORTCB pSort)
 {
-    return TREEVIEW_Sort(infoPtr, wParam, pSort->hParent, pSort);
+    return TREEVIEW_Sort(infoPtr, pSort->hParent, pSort);
 }
 
 
@@ -3102,9 +3157,9 @@ TREEVIEW_SortChildrenCB(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPTVSORTCB pSort)
  * Sort the children of the TV item specified in lParam.
  */
 static LRESULT
-TREEVIEW_SortChildren(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+TREEVIEW_SortChildren(TREEVIEW_INFO *infoPtr, LPARAM lParam)
 {
-    return TREEVIEW_Sort(infoPtr, (BOOL)wParam, (HTREEITEM)lParam, NULL);
+    return TREEVIEW_Sort(infoPtr, (HTREEITEM)lParam, NULL);
 }
 
 
@@ -3225,7 +3280,7 @@ TREEVIEW_Collapse(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
     {
         scrollRect.top = nextItem->rect.top;
 
-        ScrollWindowEx (infoPtr->hwnd, 0, scrollDist, &scrollRect, NULL,
+        ScrollWindowEx (infoPtr->hwnd, 0, scrollDist, &scrollRect, &scrollRect,
                        NULL, NULL, SW_ERASE | SW_INVALIDATE);
         TREEVIEW_Invalidate(infoPtr, wineItem);
     } else {
@@ -3298,56 +3353,59 @@ TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
     if (bExpandPartial)
        FIXME("TVE_EXPANDPARTIAL not implemented\n");
 
-    TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem);
-    TREEVIEW_UpdateSubTree(infoPtr, wineItem);
-    TREEVIEW_UpdateScrollBars(infoPtr);
-
-    scrollRect.left = 0;
-    scrollRect.bottom = infoPtr->treeHeight;
-    scrollRect.right = infoPtr->clientWidth;
-    if (nextItem)
+    if (ISVISIBLE(wineItem))
     {
-        scrollDist = nextItem->rect.top - orgNextTop;
-        scrollRect.top = orgNextTop;
+        TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem);
+        TREEVIEW_UpdateSubTree(infoPtr, wineItem);
+        TREEVIEW_UpdateScrollBars(infoPtr);
 
-        ScrollWindowEx (infoPtr->hwnd, 0, scrollDist, &scrollRect, NULL,
-                       NULL, NULL, SW_ERASE | SW_INVALIDATE);
-        TREEVIEW_Invalidate (infoPtr, wineItem);
-    } else {
-        scrollRect.top = wineItem->rect.top;
-        InvalidateRect(infoPtr->hwnd, &scrollRect, FALSE);
-    }
+        scrollRect.left = 0;
+        scrollRect.bottom = infoPtr->treeHeight;
+        scrollRect.right = infoPtr->clientWidth;
+        if (nextItem)
+        {
+            scrollDist = nextItem->rect.top - orgNextTop;
+            scrollRect.top = orgNextTop;
+
+            ScrollWindowEx (infoPtr->hwnd, 0, scrollDist, &scrollRect, NULL,
+                        NULL, NULL, SW_ERASE | SW_INVALIDATE);
+            TREEVIEW_Invalidate (infoPtr, wineItem);
+        } else {
+            scrollRect.top = wineItem->rect.top;
+            InvalidateRect(infoPtr->hwnd, &scrollRect, FALSE);
+        }
 
-    /* Scroll up so that as many children as possible are visible.
-     * This fails when expanding causes an HScroll bar to appear, but we
-     * don't know that yet, so the last item is obscured. */
-    if (wineItem->firstChild != NULL)
-    {
-       int nChildren = wineItem->lastChild->visibleOrder
-           - wineItem->firstChild->visibleOrder + 1;
+        /* Scroll up so that as many children as possible are visible.
+        * This fails when expanding causes an HScroll bar to appear, but we
+        * don't know that yet, so the last item is obscured. */
+        if (wineItem->firstChild != NULL)
+        {
+            int nChildren = wineItem->lastChild->visibleOrder
+                - wineItem->firstChild->visibleOrder + 1;
 
-       int visible_pos = wineItem->visibleOrder
-           - infoPtr->firstVisible->visibleOrder;
+            int visible_pos = wineItem->visibleOrder
+                - infoPtr->firstVisible->visibleOrder;
 
-       int rows_below = TREEVIEW_GetVisibleCount(infoPtr) - visible_pos - 1;
+            int rows_below = TREEVIEW_GetVisibleCount(infoPtr) - visible_pos - 1;
 
-       if (visible_pos > 0 && nChildren > rows_below)
-       {
-           int scroll = nChildren - rows_below;
+            if (visible_pos > 0 && nChildren > rows_below)
+            {
+                int scroll = nChildren - rows_below;
 
-           if (scroll > visible_pos)
-               scroll = visible_pos;
+                if (scroll > visible_pos)
+                    scroll = visible_pos;
 
-           if (scroll > 0)
-           {
-               TREEVIEW_ITEM *newFirstVisible
-                   = TREEVIEW_GetListItem(infoPtr, infoPtr->firstVisible,
-                                          scroll);
+                if (scroll > 0)
+                {
+                    TREEVIEW_ITEM *newFirstVisible
+                        = TREEVIEW_GetListItem(infoPtr, infoPtr->firstVisible,
+                                            scroll);
 
 
-               TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE);
-           }
-       }
+                    TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE);
+                }
+            }
+        }
     }
 
     return TRUE;
@@ -3473,14 +3531,14 @@ TREEVIEW_HitTest(const TREEVIEW_INFO *infoPtr, LPTVHITTESTINFO lpht)
     if (status)
     {
        lpht->flags = status;
-       return (LRESULT)(HTREEITEM)NULL;
+        return 0;
     }
 
     wineItem = TREEVIEW_HitTestPoint(infoPtr, lpht->pt);
     if (!wineItem)
     {
        lpht->flags = TVHT_NOWHERE;
-       return (LRESULT)(HTREEITEM)NULL;
+        return 0;
     }
 
     if (x >= wineItem->textOffset + wineItem->textWidth)
@@ -3543,16 +3601,24 @@ TREEVIEW_Edit_SubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
            return TRUE;
        break;
 
+    case WM_DESTROY:
+    {
+       WNDPROC editProc = infoPtr->wpEditOrig;
+       infoPtr->wpEditOrig = 0;
+       SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (DWORD_PTR)editProc);
+       return CallWindowProcW(editProc, hwnd, uMsg, wParam, lParam);
+    }
+
     case WM_GETDLGCODE:
        return DLGC_WANTARROWS | DLGC_WANTALLKEYS;
 
     case WM_KEYDOWN:
-       if (wParam == (WPARAM)VK_ESCAPE)
+       if (wParam == VK_ESCAPE)
        {
            bCancel = TRUE;
            break;
        }
-       else if (wParam == (WPARAM)VK_RETURN)
+       else if (wParam == VK_RETURN)
        {
            break;
        }
@@ -3578,7 +3644,7 @@ TREEVIEW_Edit_SubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 static LRESULT
 TREEVIEW_Command(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 {
-    TRACE("%lx %ld\n", wParam, lParam);
+    TRACE("code=%x, id=%x, handle=%lx\n", HIWORD(wParam), LOWORD(wParam), lParam);
 
     switch (HIWORD(wParam))
     {
@@ -3588,15 +3654,18 @@ TREEVIEW_Command(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
             * Adjust the edit window size
             */
            WCHAR buffer[1024];
-           TREEVIEW_ITEM *editItem = infoPtr->selectedItem;
+           TREEVIEW_ITEM *editItem = infoPtr->editItem;
            HDC hdc = GetDC(infoPtr->hwndEdit);
            SIZE sz;
-           int len;
            HFONT hFont, hOldFont = 0;
 
+           TRACE("edit=%p\n", infoPtr->hwndEdit);
+
+           if (!IsWindow(infoPtr->hwndEdit) || !hdc) return FALSE;
+
            infoPtr->bLabelChanged = TRUE;
 
-           len = GetWindowTextW(infoPtr->hwndEdit, buffer, sizeof(buffer));
+           GetWindowTextW(infoPtr->hwndEdit, buffer, sizeof(buffer)/sizeof(buffer[0]));
 
            /* Select font to get the right dimension of the string */
            hFont = (HFONT)SendMessageW(infoPtr->hwndEdit, WM_GETFONT, 0, 0);
@@ -3635,6 +3704,12 @@ TREEVIEW_Command(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
            ReleaseDC(infoPtr->hwnd, hdc);
            break;
        }
+    case EN_KILLFOCUS:
+       /* apparently we should respect passed handle value */
+       if (infoPtr->hwndEdit != (HWND)lParam) return FALSE;
+
+       TREEVIEW_EndEditLabelNow(infoPtr, FALSE);
+       break;
 
     default:
        return SendMessageW(infoPtr->hwndNotify, WM_COMMAND, wParam, lParam);
@@ -3649,15 +3724,13 @@ TREEVIEW_EditLabel(TREEVIEW_INFO *infoPtr, HTREEITEM hItem)
     HWND hwnd = infoPtr->hwnd;
     HWND hwndEdit;
     SIZE sz;
-    TREEVIEW_ITEM *editItem = hItem;
     HINSTANCE hinst = (HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE);
     HDC hdc;
     HFONT hOldFont=0;
     TEXTMETRICW textMetric;
-    static const WCHAR EditW[] = {'E','d','i','t',0};
 
     TRACE("%p %p\n", hwnd, hItem);
-    if (!TREEVIEW_ValidItem(infoPtr, editItem))
+    if (!TREEVIEW_ValidItem(infoPtr, hItem))
        return NULL;
 
     if (infoPtr->hwndEdit)
@@ -3665,11 +3738,10 @@ TREEVIEW_EditLabel(TREEVIEW_INFO *infoPtr, HTREEITEM hItem)
 
     infoPtr->bLabelChanged = FALSE;
 
-    /* Make sure that edit item is selected */
-    TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, hItem, TVC_UNKNOWN);
+    /* make edit item visible */
     TREEVIEW_EnsureVisible(infoPtr, hItem, TRUE);
 
-    TREEVIEW_UpdateDispInfo(infoPtr, editItem, TVIF_TEXT);
+    TREEVIEW_UpdateDispInfo(infoPtr, hItem, TVIF_TEXT);
 
     hdc = GetDC(hwnd);
     /* Select the font to get appropriate metric dimensions */
@@ -3679,15 +3751,18 @@ TREEVIEW_EditLabel(TREEVIEW_INFO *infoPtr, HTREEITEM hItem)
     }
 
     /* Get string length in pixels */
-    GetTextExtentPoint32W(hdc, editItem->pszText, strlenW(editItem->pszText),
-                         &sz);
+    if (hItem->pszText)
+        GetTextExtentPoint32W(hdc, hItem->pszText, strlenW(hItem->pszText),
+                        &sz);
+    else
+        GetTextExtentPoint32A(hdc, "", 0, &sz);
 
     /* Add Extra spacing for the next character */
     GetTextMetricsW(hdc, &textMetric);
     sz.cx += (textMetric.tmMaxCharWidth * 2);
 
     sz.cx = max(sz.cx, textMetric.tmMaxCharWidth * 3);
-    sz.cx = min(sz.cx, infoPtr->clientWidth - editItem->textOffset + 2);
+    sz.cx = min(sz.cx, infoPtr->clientWidth - hItem->textOffset + 2);
 
     if (infoPtr->hFont != 0)
     {
@@ -3695,15 +3770,18 @@ TREEVIEW_EditLabel(TREEVIEW_INFO *infoPtr, HTREEITEM hItem)
     }
 
     ReleaseDC(hwnd, hdc);
+
+    infoPtr->editItem = hItem;
+
     hwndEdit = CreateWindowExW(WS_EX_LEFT,
-                              EditW,
+                              WC_EDITW,
                               0,
                               WS_CHILD | WS_BORDER | ES_AUTOHSCROLL |
                               WS_CLIPSIBLINGS | ES_WANTRETURN |
-                              ES_LEFT, editItem->textOffset - 2,
-                              editItem->rect.top - 1, sz.cx + 3,
-                              editItem->rect.bottom -
-                              editItem->rect.top + 3, hwnd, 0, hinst, 0);
+                              ES_LEFT, hItem->textOffset - 2,
+                              hItem->rect.top - 1, sz.cx + 3,
+                              hItem->rect.bottom -
+                              hItem->rect.top + 3, hwnd, 0, hinst, 0);
 /* FIXME: (HMENU)IDTVEDIT,pcs->hInstance,0); */
 
     infoPtr->hwndEdit = hwndEdit;
@@ -3715,21 +3793,23 @@ TREEVIEW_EditLabel(TREEVIEW_INFO *infoPtr, HTREEITEM hItem)
                   GetWindowLongW(hwndEdit, GWL_STYLE) | WS_BORDER);
 
     SendMessageW(hwndEdit, WM_SETFONT,
-                (WPARAM)TREEVIEW_FontForItem(infoPtr, editItem), FALSE);
+                (WPARAM)TREEVIEW_FontForItem(infoPtr, hItem), FALSE);
 
     infoPtr->wpEditOrig = (WNDPROC)SetWindowLongPtrW(hwndEdit, GWLP_WNDPROC,
                                                  (DWORD_PTR)
                                                  TREEVIEW_Edit_SubclassProc);
 
-    if (TREEVIEW_BeginLabelEditNotify(infoPtr, editItem))
+    if (TREEVIEW_BeginLabelEditNotify(infoPtr, hItem))
     {
        DestroyWindow(hwndEdit);
        infoPtr->hwndEdit = 0;
+       infoPtr->editItem = NULL;
        return NULL;
     }
 
-    infoPtr->selectedItem = hItem;
-    SetWindowTextW(hwndEdit, editItem->pszText);
+    if (hItem->pszText)
+        SetWindowTextW(hwndEdit, hItem->pszText);
+
     SetFocus(hwndEdit);
     SendMessageW(hwndEdit, EM_SETSEL, 0, -1);
     ShowWindow(hwndEdit, SW_SHOW);
@@ -3742,15 +3822,14 @@ static LRESULT
 TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel)
 {
     HWND hwnd = infoPtr->hwnd;
-    TREEVIEW_ITEM *editedItem = infoPtr->selectedItem;
+    TREEVIEW_ITEM *editedItem = infoPtr->editItem;
     NMTVDISPINFOW tvdi;
     BOOL bCommit;
     WCHAR tmpText[1024] = { '\0' };
     WCHAR *newText = tmpText;
     int iLength = 0;
 
-    if (!infoPtr->hwndEdit)
-       return FALSE;
+    if (!IsWindow(infoPtr->hwndEdit)) return FALSE;
 
     tvdi.hdr.hwndFrom = hwnd;
     tvdi.hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID);
@@ -3782,8 +3861,7 @@ TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel)
        tvdi.item.cchTextMax = 0;
     }
 
-    bCommit = (BOOL)TREEVIEW_SendRealNotify(infoPtr,
-                                (WPARAM)tvdi.hdr.idFrom, (LPARAM)&tvdi);
+    bCommit = (BOOL)TREEVIEW_SendRealNotify(infoPtr, tvdi.hdr.idFrom, (LPARAM)&tvdi);
 
     if (!bCancel && bCommit)   /* Apply the changes */
     {
@@ -3804,6 +3882,7 @@ TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel)
                 if(newText != tmpText) Free(newText);
                 DestroyWindow(infoPtr->hwndEdit);
                 infoPtr->hwndEdit = 0;
+                infoPtr->editItem = NULL;
                 return FALSE;
             }
             else
@@ -3820,6 +3899,7 @@ TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel)
     ShowWindow(infoPtr->hwndEdit, SW_HIDE);
     DestroyWindow(infoPtr->hwndEdit);
     infoPtr->hwndEdit = 0;
+    infoPtr->editItem = NULL;
     return TRUE;
 }
 
@@ -3971,7 +4051,6 @@ TREEVIEW_LButtonDown(TREEVIEW_INFO *infoPtr, LPARAM lParam)
     HWND hwnd = infoPtr->hwnd;
     TVHITTESTINFO ht;
     BOOL bTrack, bDoLabelEdit;
-    HTREEITEM tempItem;
 
     /* If Edit control is active - kill it and return.
      * The best way to do it is to set focus to itself.
@@ -3994,10 +4073,8 @@ TREEVIEW_LButtonDown(TREEVIEW_INFO *infoPtr, LPARAM lParam)
     if(ht.hItem && (ht.flags & TVHT_ONITEM))
     {
         infoPtr->focusedItem = ht.hItem;
-        InvalidateRect(hwnd, &(((HTREEITEM)(ht.hItem))->rect), TRUE);
-
-        if(infoPtr->selectedItem)
-            InvalidateRect(hwnd, &(infoPtr->selectedItem->rect), TRUE);
+        TREEVIEW_InvalidateItem(infoPtr, infoPtr->focusedItem);
+        TREEVIEW_InvalidateItem(infoPtr, infoPtr->selectedItem);
     }
 
     bTrack = (ht.flags & TVHT_ONITEM)
@@ -4031,12 +4108,11 @@ TREEVIEW_LButtonDown(TREEVIEW_INFO *infoPtr, LPARAM lParam)
             if(infoPtr->focusedItem)
             {
                 /* refresh the item that was focused */
-                tempItem = infoPtr->focusedItem;
-                infoPtr->focusedItem = 0;
-                InvalidateRect(infoPtr->hwnd, &tempItem->rect, TRUE);
+                TREEVIEW_InvalidateItem(infoPtr, infoPtr->focusedItem);
+                infoPtr->focusedItem = NULL;
 
                 /* refresh the selected item to return the filled background */
-                InvalidateRect(infoPtr->hwnd, &(infoPtr->selectedItem->rect), TRUE);
+                TREEVIEW_InvalidateItem(infoPtr, infoPtr->selectedItem);
             }
 
            return 0;
@@ -4173,13 +4249,12 @@ TREEVIEW_RButtonUp(const TREEVIEW_INFO *infoPtr, const POINT *pPt)
         SendMessageW(infoPtr->hwnd, WM_CONTEXTMENU,
             (WPARAM)infoPtr->hwnd, MAKELPARAM(ht.pt.x, ht.pt.y));
     }
-
     return 0;
 }
 
 
 static LRESULT
-TREEVIEW_CreateDragImage(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+TREEVIEW_CreateDragImage(TREEVIEW_INFO *infoPtr, LPARAM lParam)
 {
     TREEVIEW_ITEM *dragItem = (HTREEITEM)lParam;
     INT cx, cy;
@@ -4205,10 +4280,14 @@ TREEVIEW_CreateDragImage(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
     hdc = CreateCompatibleDC(htopdc);
 
     hOldFont = SelectObject(hdc, infoPtr->hFont);
-    GetTextExtentPoint32W(hdc, dragItem->pszText, strlenW(dragItem->pszText),
+
+    if (dragItem->pszText)
+        GetTextExtentPoint32W(hdc, dragItem->pszText, strlenW(dragItem->pszText),
                          &size);
-    TRACE("%d %d %s %d\n", size.cx, size.cy, debugstr_w(dragItem->pszText),
-         strlenW(dragItem->pszText));
+    else
+        GetTextExtentPoint32A(hdc, "", 0, &size);
+
+    TRACE("%d %d %s\n", size.cx, size.cy, debugstr_w(dragItem->pszText));
     hbmp = CreateCompatibleBitmap(htopdc, size.cx, size.cy);
     hOldbmp = SelectObject(hdc, hbmp);
 
@@ -4229,8 +4308,11 @@ TREEVIEW_CreateDragImage(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 /* draw item text */
 
     SetRect(&rc, cx, 0, size.cx, size.cy);
-    DrawTextW(hdc, dragItem->pszText, strlenW(dragItem->pszText), &rc,
-             DT_LEFT);
+
+    if (dragItem->pszText)
+        DrawTextW(hdc, dragItem->pszText, strlenW(dragItem->pszText), &rc,
+                  DT_LEFT);
+
     SelectObject(hdc, hOldFont);
     SelectObject(hdc, hOldbmp);
 
@@ -4250,7 +4332,6 @@ TREEVIEW_DoSelectItem(TREEVIEW_INFO *infoPtr, INT action, HTREEITEM newSelect,
                      INT cause)
 {
     TREEVIEW_ITEM *prevSelect;
-    RECT rcFocused;
 
     assert(newSelect == NULL || TREEVIEW_ValidItem(infoPtr, newSelect));
 
@@ -4260,12 +4341,8 @@ TREEVIEW_DoSelectItem(TREEVIEW_INFO *infoPtr, INT action, HTREEITEM newSelect,
 
     /* reset and redraw focusedItem if focusedItem was set so we don't */
     /* have to worry about the previously focused item when we set a new one */
-    if(infoPtr->focusedItem)
-    {
-        rcFocused = (infoPtr->focusedItem)->rect;
-        infoPtr->focusedItem = 0;
-        InvalidateRect(infoPtr->hwnd, &rcFocused, TRUE);
-    }
+    TREEVIEW_InvalidateItem(infoPtr, infoPtr->focusedItem);
+    infoPtr->focusedItem = NULL;
 
     switch (action)
     {
@@ -4294,10 +4371,8 @@ TREEVIEW_DoSelectItem(TREEVIEW_INFO *infoPtr, INT action, HTREEITEM newSelect,
 
        TREEVIEW_EnsureVisible(infoPtr, infoPtr->selectedItem, FALSE);
 
-       if (prevSelect)
-           TREEVIEW_Invalidate(infoPtr, prevSelect);
-       if (newSelect)
-           TREEVIEW_Invalidate(infoPtr, newSelect);
+        TREEVIEW_InvalidateItem(infoPtr, prevSelect);
+        TREEVIEW_InvalidateItem(infoPtr, newSelect);
 
        TREEVIEW_SendTreeviewNotify(infoPtr,
                                    TVN_SELCHANGEDW,
@@ -4377,7 +4452,7 @@ TREEVIEW_SelectItem(TREEVIEW_INFO *infoPtr, INT wParam, HTREEITEM item)
  * BUGS
  *
  *  - The current implementation has a list of characters it will
- *    accept and it ignores averything else. In particular it will
+ *    accept and it ignores everything else. In particular it will
  *    ignore accentuated characters which seems to match what
  *    Windows does. But I'm not sure it makes sense to follow
  *    Windows there.
@@ -4390,13 +4465,8 @@ TREEVIEW_SelectItem(TREEVIEW_INFO *infoPtr, INT wParam, HTREEITEM item)
  *
  *  TREEVIEW_ProcessLetterKeys
  */
-static INT TREEVIEW_ProcessLetterKeys(
-    HWND hwnd, /* handle to the window */
-    WPARAM charCode, /* the character code, the actual character */
-    LPARAM keyData /* key data */
-    )
+static INT TREEVIEW_ProcessLetterKeys(TREEVIEW_INFO *infoPtr, WPARAM charCode, LPARAM keyData)
 {
-    TREEVIEW_INFO *infoPtr;
     HTREEITEM nItem;
     HTREEITEM endidx,idx;
     TVITEMEXW item;
@@ -4404,12 +4474,7 @@ static INT TREEVIEW_ProcessLetterKeys(
     DWORD timestamp,elapsed;
 
     /* simple parameter checking */
-    if (!hwnd || !charCode || !keyData)
-        return 0;
-
-    infoPtr=(TREEVIEW_INFO*)GetWindowLongPtrW(hwnd, 0);
-    if (!infoPtr)
-        return 0;
+    if (!charCode || !keyData) return 0;
 
     /* only allow the valid WM_CHARs through */
     if (!isalnum(charCode) &&
@@ -4527,7 +4592,7 @@ TREEVIEW_EnsureVisible(TREEVIEW_INFO *infoPtr, HTREEITEM item, BOOL bHScroll)
        /* Expand parents as necessary. */
        HTREEITEM parent;
 
-        /* see if we are trying to ensure that root is vislble */
+        /* see if we are trying to ensure that root is visible */
         if((item != infoPtr->root) && TREEVIEW_ValidItem(infoPtr, item))
           parent = item->parent;
         else
@@ -4818,11 +4883,14 @@ scroll:
 }
 
 static LRESULT
-TREEVIEW_MouseWheel(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+TREEVIEW_MouseWheel(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 {
     short gcWheelDelta;
     UINT pulScrollLines = 3;
 
+    if (wParam & (MK_SHIFT | MK_CONTROL))
+        return DefWindowProcW(infoPtr->hwnd, WM_MOUSEWHEEL, wParam, lParam);
+
     if (infoPtr->firstVisible == NULL)
        return TRUE;
 
@@ -4878,7 +4946,7 @@ initialize_checkboxes(TREEVIEW_INFO *infoPtr)
 
     SelectObject(hdc, hbmOld);
     nIndex = ImageList_AddMasked(infoPtr->himlState, hbm,
-                                 GetSysColor(COLOR_WINDOW));
+                                 comctl32_color.clrWindow);
     TRACE("checkbox index %d\n", nIndex);
 
     DeleteObject(hbm);
@@ -4898,7 +4966,7 @@ TREEVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs)
 
     TRACE("wnd %p, style %x\n", hwnd, GetWindowLongW(hwnd, GWL_STYLE));
 
-    infoPtr = (TREEVIEW_INFO *)Alloc(sizeof(TREEVIEW_INFO));
+    infoPtr = Alloc(sizeof(TREEVIEW_INFO));
 
     if (infoPtr == NULL)
     {
@@ -4927,26 +4995,27 @@ TREEVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs)
     infoPtr->treeHeight = 0;
 
     infoPtr->uIndent = MINIMUM_INDENT;
-    infoPtr->selectedItem = 0;
-    infoPtr->focusedItem = 0;
-    infoPtr->hotItem = 0;
-    infoPtr->firstVisible = 0;
+    infoPtr->selectedItem = NULL;
+    infoPtr->focusedItem = NULL;
+    infoPtr->hotItem = NULL;
+    infoPtr->editItem = NULL;
+    infoPtr->firstVisible = NULL;
     infoPtr->maxVisibleOrder = 0;
-    infoPtr->dropItem = 0;
-    infoPtr->insertMarkItem = 0;
+    infoPtr->dropItem = NULL;
+    infoPtr->insertMarkItem = NULL;
     infoPtr->insertBeforeorAfter = 0;
     /* dragList */
 
     infoPtr->scrollX = 0;
 
-    infoPtr->clrBk = GetSysColor(COLOR_WINDOW);
-    infoPtr->clrText = -1;     /* use system color */
-    infoPtr->clrLine = RGB(128, 128, 128);
-    infoPtr->clrInsertMark = GetSysColor(COLOR_BTNTEXT);
+    infoPtr->clrBk   = CLR_NONE; /* use system color */
+    infoPtr->clrText = CLR_NONE; /* use system color */
+    infoPtr->clrLine = CLR_DEFAULT;
+    infoPtr->clrInsertMark = CLR_DEFAULT;
 
     /* hwndToolTip */
 
-    infoPtr->hwndEdit = 0;
+    infoPtr->hwndEdit = NULL;
     infoPtr->wpEditOrig = NULL;
     infoPtr->bIgnoreEditKillFocus = FALSE;
     infoPtr->bLabelChanged = FALSE;
@@ -4997,7 +5066,7 @@ TREEVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs)
     /* Make sure actual scrollbar state is consistent with uInternalStatus */
     ShowScrollBar(hwnd, SB_VERT, FALSE);
     ShowScrollBar(hwnd, SB_HORZ, FALSE);
-
+    
     OpenThemeData (hwnd, themeClass);
 
     return 0;
@@ -5009,7 +5078,11 @@ TREEVIEW_Destroy(TREEVIEW_INFO *infoPtr)
 {
     TRACE("\n");
 
+    /* free item data */
     TREEVIEW_RemoveTree(infoPtr);
+    /* root isn't freed with other items */
+    TREEVIEW_FreeItem(infoPtr, infoPtr->root);
+    DPA_Destroy(infoPtr->items);
 
     /* tool tip is automatically destroyed: we are its owner */
 
@@ -5021,7 +5094,7 @@ TREEVIEW_Destroy(TREEVIEW_INFO *infoPtr)
     CloseThemeData (GetWindowTheme (infoPtr->hwnd));
 
     /* Deassociate treeview from the window before doing anything drastic. */
-    SetWindowLongPtrW(infoPtr->hwnd, 0, (DWORD_PTR)NULL);
+    SetWindowLongPtrW(infoPtr->hwnd, 0, 0);
 
 
     DeleteObject(infoPtr->hDefaultFont);
@@ -5197,27 +5270,26 @@ TREEVIEW_KeyDown(TREEVIEW_INFO *infoPtr, WPARAM wParam)
 static LRESULT
 TREEVIEW_MouseLeave (TREEVIEW_INFO * infoPtr)
 {
-    if (infoPtr->hotItem)
-    {
-        /* remove hot effect from item */
-        InvalidateRect(infoPtr->hwnd, &infoPtr->hotItem->rect, TRUE);
-        infoPtr->hotItem = NULL;
-    }
+    /* remove hot effect from item */
+    TREEVIEW_InvalidateItem(infoPtr, infoPtr->hotItem);
+    infoPtr->hotItem = NULL;
+
     return 0;
 }
 
 static LRESULT
-TREEVIEW_MouseMove (TREEVIEW_INFO * infoPtr, WPARAM wParam, LPARAM lParam)
+TREEVIEW_MouseMove (TREEVIEW_INFO * infoPtr, LPARAM lParam)
 {
     POINT pt;
     TRACKMOUSEEVENT trackinfo;
     TREEVIEW_ITEM * item;
 
+    if (!(infoPtr->dwStyle & TVS_TRACKSELECT)) return 0;
+
     /* fill in the TRACKMOUSEEVENT struct */
     trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
     trackinfo.dwFlags = TME_QUERY;
     trackinfo.hwndTrack = infoPtr->hwnd;
-    trackinfo.dwHoverTime = HOVER_DEFAULT;
 
     /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
     _TrackMouseEvent(&trackinfo);
@@ -5226,6 +5298,9 @@ TREEVIEW_MouseMove (TREEVIEW_INFO * infoPtr, WPARAM wParam, LPARAM lParam)
     if(!(trackinfo.dwFlags & TME_LEAVE))
     {
         trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
+        trackinfo.hwndTrack = infoPtr->hwnd;
+        /* do it as fast as possible, minimal systimer latency will be used */
+        trackinfo.dwHoverTime = 1;
 
         /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
         /* and can properly deactivate the hot item */
@@ -5240,19 +5315,17 @@ TREEVIEW_MouseMove (TREEVIEW_INFO * infoPtr, WPARAM wParam, LPARAM lParam)
     if (item != infoPtr->hotItem)
     {
         /* redraw old hot item */
-        if (infoPtr->hotItem)
-            InvalidateRect(infoPtr->hwnd, &infoPtr->hotItem->rect, TRUE);
+        TREEVIEW_InvalidateItem(infoPtr, infoPtr->hotItem);
         infoPtr->hotItem = item;
         /* redraw new hot item */
-        if (infoPtr->hotItem)
-            InvalidateRect(infoPtr->hwnd, &infoPtr->hotItem->rect, TRUE);
+        TREEVIEW_InvalidateItem(infoPtr, infoPtr->hotItem);
     }
 
     return 0;
 }
 
 /* Draw themed border */
-static BOOL nc_paint (const TREEVIEW_INFO *infoPtr, HRGN region)
+static BOOL TREEVIEW_NCPaint (const TREEVIEW_INFO *infoPtr, HRGN region, LPARAM lParam)
 {
     HTHEME theme = GetWindowTheme (infoPtr->hwnd);
     HDC dc;
@@ -5261,7 +5334,8 @@ static BOOL nc_paint (const TREEVIEW_INFO *infoPtr, HRGN region)
     int cxEdge = GetSystemMetrics (SM_CXEDGE),
         cyEdge = GetSystemMetrics (SM_CYEDGE);
 
-    if (!theme) return FALSE;
+    if (!theme)
+        return DefWindowProcW (infoPtr->hwnd, WM_NCPAINT, (WPARAM)region, lParam);
 
     GetWindowRect(infoPtr->hwnd, &r);
 
@@ -5308,24 +5382,6 @@ TREEVIEW_Notify(const TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
     return DefWindowProcW(infoPtr->hwnd, WM_NOTIFY, wParam, lParam);
 }
 
-static INT TREEVIEW_NotifyFormat (TREEVIEW_INFO *infoPtr, HWND hwndFrom, UINT nCommand)
-{
-    INT format;
-
-    TRACE("(hwndFrom=%p, nCommand=%d)\n", hwndFrom, nCommand);
-
-    if (nCommand != NF_REQUERY) return 0;
-
-    format = SendMessageW(hwndFrom, WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwnd, NF_QUERY);
-    TRACE("format=%d\n", format);
-
-    if (format != NFR_ANSI && format != NFR_UNICODE) return 0;
-
-    infoPtr->bNtfUnicode = (format == NFR_UNICODE);
-
-    return format;
-}
-
 static LRESULT
 TREEVIEW_Size(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 {
@@ -5399,13 +5455,27 @@ TREEVIEW_SetCursor(const TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 {
     POINT pt;
     TREEVIEW_ITEM * item;
+    NMMOUSE nmmouse;
 
     GetCursorPos(&pt);
     ScreenToClient(infoPtr->hwnd, &pt);
 
     item = TREEVIEW_HitTestPoint(infoPtr, pt);
 
-    /* FIXME: send NM_SETCURSOR */
+    memset(&nmmouse, 0, sizeof(nmmouse));
+    nmmouse.hdr.hwndFrom = infoPtr->hwnd;
+    nmmouse.hdr.idFrom = GetWindowLongPtrW(infoPtr->hwnd, GWLP_ID);
+    nmmouse.hdr.code = NM_SETCURSOR;
+    if (item)
+    {
+        nmmouse.dwItemSpec = (DWORD_PTR)item;
+        nmmouse.dwItemData = item->lParam;
+    }
+    nmmouse.pt.x = 0;
+    nmmouse.pt.y = 0;
+    nmmouse.dwHitInfo = lParam;
+    if (TREEVIEW_SendRealNotify(infoPtr, nmmouse.hdr.idFrom, (LPARAM)&nmmouse))
+        return 0;
 
     if (item && (infoPtr->dwStyle & TVS_TRACKSELECT))
     {
@@ -5444,7 +5514,7 @@ TREEVIEW_KillFocus(const TREEVIEW_INFO *infoPtr)
 }
 
 /* update theme after a WM_THEMECHANGED message */
-static LRESULT theme_changed(const TREEVIEW_INFO *infoPtr)
+static LRESULT TREEVIEW_ThemeChanged(const TREEVIEW_INFO *infoPtr)
 {
     HTHEME theme = GetWindowTheme (infoPtr->hwnd);
     CloseThemeData (theme);
@@ -5472,14 +5542,12 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     switch (uMsg)
     {
     case TVM_CREATEDRAGIMAGE:
-       return TREEVIEW_CreateDragImage(infoPtr, wParam, lParam);
+       return TREEVIEW_CreateDragImage(infoPtr, lParam);
 
     case TVM_DELETEITEM:
        return TREEVIEW_DeleteItem(infoPtr, (HTREEITEM)lParam);
 
     case TVM_EDITLABELA:
-       return (LRESULT)TREEVIEW_EditLabel(infoPtr, (HTREEITEM)lParam);
-
     case TVM_EDITLABELW:
        return (LRESULT)TREEVIEW_EditLabel(infoPtr, (HTREEITEM)lParam);
 
@@ -5519,11 +5587,9 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        return 0;
 
     case TVM_GETITEMA:
-       return TREEVIEW_GetItemT(infoPtr, (LPTVITEMEXW)lParam, FALSE);
-
     case TVM_GETITEMW:
-       return TREEVIEW_GetItemT(infoPtr, (LPTVITEMEXW)lParam, TRUE);
-
+       return TREEVIEW_GetItemT(infoPtr, (LPTVITEMEXW)lParam,
+                                uMsg == TVM_GETITEMW);
     case TVM_GETITEMHEIGHT:
        return TREEVIEW_GetItemHeight(infoPtr);
 
@@ -5558,11 +5624,9 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        return TREEVIEW_HitTest(infoPtr, (LPTVHITTESTINFO)lParam);
 
     case TVM_INSERTITEMA:
-       return TREEVIEW_InsertItemT(infoPtr, (LPTVINSERTSTRUCTW)lParam, FALSE);
-
     case TVM_INSERTITEMW:
-       return TREEVIEW_InsertItemT(infoPtr, (LPTVINSERTSTRUCTW)lParam, TRUE);
-
+       return TREEVIEW_InsertItemT(infoPtr, (LPTVINSERTSTRUCTW)lParam,
+                                   uMsg == TVM_INSERTITEMW);
     case TVM_SELECTITEM:
        return TREEVIEW_SelectItem(infoPtr, (INT)wParam, (HTREEITEM)lParam);
 
@@ -5582,11 +5646,9 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        return TREEVIEW_SetInsertMarkColor(infoPtr, (COLORREF)lParam);
 
     case TVM_SETITEMA:
-       return TREEVIEW_SetItemT(infoPtr, (LPTVITEMEXW)lParam, FALSE);
-
     case TVM_SETITEMW:
-        return TREEVIEW_SetItemT(infoPtr, (LPTVITEMEXW)lParam, TRUE);
-
+        return TREEVIEW_SetItemT(infoPtr, (LPTVITEMEXW)lParam,
+                                uMsg == TVM_SETITEMW);
     case TVM_SETLINECOLOR:
        return TREEVIEW_SetLineColor(infoPtr, (COLORREF)lParam);
 
@@ -5606,13 +5668,13 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         return TREEVIEW_SetUnicodeFormat(infoPtr, (BOOL)wParam);
 
     case TVM_SORTCHILDREN:
-       return TREEVIEW_SortChildren(infoPtr, wParam, lParam);
+       return TREEVIEW_SortChildren(infoPtr, lParam);
 
     case TVM_SORTCHILDRENCB:
-       return TREEVIEW_SortChildrenCB(infoPtr, wParam, (LPTVSORTCB)lParam);
+       return TREEVIEW_SortChildrenCB(infoPtr, (LPTVSORTCB)lParam);
 
     case WM_CHAR:
-        return TREEVIEW_ProcessLetterKeys( hwnd, wParam, lParam );
+        return TREEVIEW_ProcessLetterKeys(infoPtr, wParam, lParam);
 
     case WM_COMMAND:
        return TREEVIEW_Command(infoPtr, wParam, lParam);
@@ -5652,10 +5714,7 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        return TREEVIEW_MouseLeave(infoPtr);
 
     case WM_MOUSEMOVE:
-        if (infoPtr->dwStyle & TVS_TRACKSELECT)
-            return TREEVIEW_MouseMove(infoPtr, wParam, lParam);
-        else
-            return 0;
+       return TREEVIEW_MouseMove(infoPtr, lParam);
 
     case WM_NCLBUTTONDOWN:
         if (infoPtr->hwndEdit)
@@ -5663,9 +5722,7 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         goto def;
 
     case WM_NCPAINT:
-        if (nc_paint (infoPtr, (HRGN)wParam))
-            return 0;
-        goto def;
+        return TREEVIEW_NCPaint (infoPtr, (HRGN)wParam, lParam);
 
     case WM_NOTIFY:
        return TREEVIEW_Notify(infoPtr, wParam, lParam);
@@ -5674,8 +5731,10 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        return TREEVIEW_NotifyFormat(infoPtr, (HWND)wParam, (UINT)lParam);
 
     case WM_PRINTCLIENT:
+        return TREEVIEW_PrintClient(infoPtr, (HDC)wParam, lParam);
+
     case WM_PAINT:
-       return TREEVIEW_Paint(infoPtr, wParam);
+       return TREEVIEW_Paint(infoPtr, (HDC)wParam);
 
     case WM_RBUTTONDOWN:
        return TREEVIEW_RButtonDown(infoPtr, lParam);
@@ -5690,7 +5749,7 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        return TREEVIEW_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
 
     case WM_SETREDRAW:
-        return TREEVIEW_SetRedraw(infoPtr, wParam, lParam);
+        return TREEVIEW_SetRedraw(infoPtr, wParam);
 
     case WM_SIZE:
        return TREEVIEW_Size(infoPtr, wParam, lParam);
@@ -5698,7 +5757,9 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     case WM_STYLECHANGED:
        return TREEVIEW_StyleChanged(infoPtr, wParam, lParam);
 
-       /* WM_SYSCOLORCHANGE */
+    case WM_SYSCOLORCHANGE:
+        COMCTL32_RefreshSysColors();
+        return 0;
 
        /* WM_SYSKEYDOWN */
 
@@ -5706,7 +5767,7 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        return TREEVIEW_HandleTimer(infoPtr, wParam);
 
     case WM_THEMECHANGED:
-        return theme_changed (infoPtr);
+        return TREEVIEW_ThemeChanged (infoPtr);
 
     case WM_VSCROLL:
        return TREEVIEW_VScroll(infoPtr, wParam);
@@ -5714,9 +5775,7 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
        /* WM_WININICHANGE */
 
     case WM_MOUSEWHEEL:
-       if (wParam & (MK_SHIFT | MK_CONTROL))
-           goto def;
-       return TREEVIEW_MouseWheel(infoPtr, wParam);
+       return TREEVIEW_MouseWheel(infoPtr, wParam, lParam);
 
     case WM_DRAWITEM:
        TRACE("drawItem\n");
@@ -5724,7 +5783,7 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
     default:
        /* This mostly catches MFC and Delphi messages. :( */
-       if ((uMsg >= WM_USER) && (uMsg < WM_APP))
+       if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg))
            TRACE("Unknown msg %04x wp=%08lx lp=%08lx\n", uMsg, wParam, lParam);
 def:
        return DefWindowProcW(hwnd, uMsg, wParam, lParam);