[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    COREL: treeview merge
From:       Alex Priem <alexp () sci ! kun ! nl>
Date:       2000-03-29 19:37:34
[Download RAW message or body]

This is a multipart MIME message.


Merged the changes in corel's cvs to the treeview common control to 
wine-cvs.  Remaining differences between corel-cvs:

1) corel uses TVN_DELETEITEM, we use TVN_DELETEITEM[AW]. Soit.
2) we use TREEVIEW_Refresh (HWND hwnd, HDC hdc), corel sticks to the old
   TREEVIEW_Refresh (HWND hwnd). I believe our way is more correct because
   of the way hdc's are handled in TREEVIEW_Paint.
3) some superfluos infoPtr==NULL checks in corel's cvs. We check that
   already when we enter TREEVIEW_WindowProc.
4) ffs () (find first bit set in a word).
5) WM_MOUSEWHEEL.



["changelog" (text/plain)]

keyword substitution: kv
total revisions: 44;	selected revisions: 44
description:
----------------------------
revision 1.43
date: 2000/03/29 15:19:48;  author: jefft;  state: Exp;  lines: +524 -420
Currently, if item has LPSTR_CALLBACK label, it (label) will be
overwritten by first TVN_GETDISPINFO notification. According to MSDN
TreeView sends GETDISPINFO notification every time it has to access item's
label. The same is valid for any other callback parameters (image, children,
etc.).
    Also there was a possibility of memory leak/corruption.  In
TREEVIEW_SendDispInfoNotify, if user will return its own text pointer, it
will be copied into internal item structure. So, when item is to be
destroyed, treeview will try to release this memory by itself.

   Solution is to use temporary item and stack allocated buffer for label. I
already used this approach for I_CHILDRENCALLBACK in one of my previous
patches. This one will finish the job.

  In DrawItem we can combine several GETDISPINFO notifications in one call
(Windows does).
--
Serge Ivanov
----------------------------
revision 1.42
date: 2000/02/28 16:00:41;  author: jefft;  state: Exp;  lines: +7 -1
The treeview control was not sorting its items.

The cause of this problem was that the treeview control was not
calling the sort function.

The treeview now uses the DPA_QuickSort, and its own compare function.
I modified the TREEVIEW_SortOnName to use the strcasecmp() function
and removed the negation operation.

Jason Mawdsley
Macadamian Technologies Inc.
----------------------------
revision 1.41
date: 2000/02/17 12:45:11;  author: jefft;  state: Exp;  lines: +22 -6
Using the left arrow key in a tree view with a vertical scrollbar will
not cause a crash anymore with this patch.

Sheri Steeves
----------------------------
revision 1.40
date: 2000/02/16 19:24:20;  author: jefft;  state: Exp;  lines: +0 -3
Well, that was my mistake to skip refreshing invisible window.  This cause
problem because WM_SETFOCUS message is recieved before window became
visible, so we don't select item in setfocus handler (see description for my
previous patch).

This is a final fix for Paradox shipstopper #344326 - bdeadmin.exe access
violation.
--
Serge Ivanov
----------------------------
revision 1.39
date: 2000/02/15 17:22:26;  author: jefft;  state: Exp;  lines: +48 -17
This is a fix for Paradox shipstopper #344326 - bdeadmin.exe access
violation

In Windows if TreeView doesn't have selection when it receives
SetFocus, it always select first visible item.  Also we have to reset
selection if selected item was in collapsed tree branch.  One more
correction: TVE_COLLAPSERESET & TVE_EXPANDPARTIAL are command options
not independent commands. So I modified TREEVIEW_Expand to treat them
properly.
--
Serge Ivanov
----------------------------
revision 1.38
date: 2000/02/14 14:09:15;  author: jefft;  state: Exp;  lines: +21 -4
This patch implements the behavior of semding WM_CONTEXTMENU when
receiving a WM_RBUTTONUP. It was not implemented in the listview,
header and treeview. Now the subclass control of this three basic
controls will receive the WM_CONTEXTMENU and not there parent.

Pascal Lessard
----------------------------
revision 1.37
date: 2000/02/11 15:27:08;  author: jefft;  state: Exp;  lines: +145 -122
This is quite unusual behaviour but that is how things working in Windows
(pretty close). Receiving L|RBUTTONDOWN treeview creates internal Peek -
Dispactch loop. When it recieves buttonUp or mousemove message it exits loop
and handle these messages inside buttonDown call. So it doesn't handle
buttonUp and move messages in window procedure.

Also I added time delayed label editing. Now editItem is used to pass item
to edit procedure, and it can't be used to test 'in edit' condition. So in
places where it was previousely used to test 'in edit' state I replaced it
with hwndEdit.

This patch will fix (finally I hope) Paradox Emergency Shipstopper #327366 -
Unable to insert and item in the BDE

PS: I'm sorry for quite an ugly diff, but I don't know which options can
make it nicer. All these interleaved insertions and removals (starting from
TREEVIEW_LButtonDown) are because of several functions were removed and two
were heavily modified.

Serge Ivanov wrote:
----------------------------
revision 1.36
date: 2000/02/09 21:51:41;  author: stephane;  state: Exp;  lines: +47 -10
Pierre Mageau
Fix width calculation of the edit label.
----------------------------
revision 1.35
date: 2000/02/09 21:49:11;  author: stephane;  state: Exp;  lines: +28 -16
Pierre Mageau
Fox for handling correctly the cancelling mode of the Edit label.
----------------------------
revision 1.34
date: 2000/02/09 17:22:40;  author: ulrichc;  state: Exp;  lines: +8 -3
Created by: Serge Ivanov

When we send TVN_GETDISPINFO user can modify item inside this
call. So, reseting cChildren to I_CHILDRENCALLBACK after the call we lose
modifications made by user. The only way to have things working is to create
temporary copy of item and pass it in notification.
----------------------------
revision 1.33
date: 2000/02/07 17:04:00;  author: ulrichc;  state: Exp;  lines: +99 -72
Created by: Serge Ivanov

1. Well, this is quite a mess with using cChildren. Actually, this field
intended to modify item's appearance and behaviour rather than reflect
physical presence of children. In Wine it is used in both ways, which is
wrong.
Also, this patch will preserve cChilred=I_CHILDRENCALLBACK, forcing treeview
to call parent every time it needs to access this field (previously it was
overwritten after first TVN_GETDISPINFO notification).

2. In TVN_BEGINLABELEDIT: "The item member is a TVITEM structure that
contains valid information about the item being edited in the hItem, state,
lParam, and pszText members" (MSDN). So, we must properly set mask field (it
was 0 before), and discard possible modification of TVITEM. (Lines:
@@ -2626,6 +2651,10 and @@ -3004,7 +3028,8)


This patch will probably fix Paradox shipstopper # 327366 - Unable to insert
an item in the BDE
----------------------------
revision 1.32
date: 2000/02/01 22:17:16;  author: ulrichc;  state: Exp;  lines: +11 -6
Created by: Serge Ivanov

This patch will keep TREEVIEW_ITEM.cchTextMax up-to-date.
----------------------------
revision 1.31
date: 2000/02/01 20:18:17;  author: ulrichc;  state: Exp;  lines: +18 -19
Created by; Serge Ivanov

TreeView - minor bugfix and optimization:
   - GetDC call moved down to avoid possible resource leak.
   - Invariant code is moved out of loop.
----------------------------
revision 1.30
date: 2000/01/28 16:31:22;  author: ulrichc;  state: Exp;  lines: +2 -2
Breated by: Serge Ivanov

This is a patch for Paradox shipstopper #343243 - OE fills with Object name
and hangs with Box or Ellipse drawing tools
----------------------------
revision 1.29
date: 2000/01/20 18:26:39;  author: ulrichc;  state: Exp;  lines: +3 -1
Fix bug 335240. Treeview was missing special case for GetNextItemA
----------------------------
revision 1.28
date: 2000/01/17 14:52:48;  author: ulrichc;  state: Exp;  lines: +1 -2
Finish commit of Alexandre's per-process class patch
----------------------------
revision 1.27
date: 2000/01/14 20:54:58;  author: ulrichc;  state: Exp;  lines: +0 -2
This commits the per-process classes fix be Alexandre
----------------------------
revision 1.26
date: 2000/01/11 14:35:43;  author: stephane;  state: Exp;  lines: +1 -1
Noomen Hamza
A fix for the vertical scrollbar after expanding items.
----------------------------
revision 1.25
date: 1999/12/21 23:42:34;  author: stephane;  state: Exp;  lines: +10 -13
Noomen Hamza
Add support for I_CHILDRENCALLBACK notification
----------------------------
revision 1.24
date: 1999/12/15 17:28:42;  author: ulrichc;  state: Exp;  lines: +68 -53
Created by: Serge Ivanov

- Added handling of TVS_SHOWSELALWAYS window style.
- infoPtr->clrText text color is used to draw items labels.
- Use FillRect to show selection, because DrawTextA is limited to text size only.
- Draw properly focus rectangle.

- (line 2321): clrText is reseted to -1 (which is correct) just few lines
below.
----------------------------
revision 1.23
date: 1999/12/15 15:23:30;  author: ulrichc;  state: Exp;  lines: +12 -7
Created by: Serge Ivanov

This patch will adds proper handling TVIS_OVERLAYMASK flag and allows to
display overlay images.

This is a fix for Paradox bug #330572 - Object Explorer- missing blue dot on
object tree to indicate code associated with that object

["treediff" (text/plain)]

--- wine/dlls/comctl32/treeview.c	Sun Mar 26 19:56:11 2000
+++ wine-devel/dlls/comctl32/treeview.c	Wed Mar 29 20:49:55 2000
@@ -80,6 +80,10 @@
 TREEVIEW_SendCustomDrawItemNotify (HWND hwnd, HDC hdc,
             TREEVIEW_ITEM *tvItem, UINT uItemDrawState);
 static LRESULT
+TREEVIEW_RButtonUp (HWND hwnd, LPPOINT pPt);
+static LRESULT
+TREEVIEW_SelectItem (HWND hwnd, WPARAM wParam, LPARAM lParam);
+static LRESULT
 TREEVIEW_DoSelectItem (HWND hwnd, INT action, HTREEITEM newSelect, INT cause);
 static void
 TREEVIEW_Refresh (HWND hwnd, HDC hdc);
@@ -89,7 +93,9 @@
 							LPARAM lParam);
 
 LRESULT WINAPI
-TREEVIEW_EndEditLabelNow (HWND hwnd, WPARAM wParam, LPARAM lParam);
+TREEVIEW_EndEditLabelNow (HWND hwnd, BOOL bCancel);
+
+HWND TREEVIEW_EditLabelA(HWND hwnd, HTREEITEM hItem);
 
 
 
@@ -98,8 +104,8 @@
    is checked beforehand, and that tree state is valid.  */
 
 /* FIXME: MS documentation says `GetNextVisibleItem' returns NULL 
-   if not successfull. Probably only applies to dereferencing infoPtr
-   (i.e. we are offered a valid treeview structure)
+   if not succesfull'. Probably only applies to dereferencing infoPtr
+   (ie we are offered a valid treeview structure)
    and not whether there is a next `visible' child. 
    FIXME: check other failures.
  */
@@ -121,11 +127,47 @@
 }
 
 /***************************************************************************
+ * This function uses cChildren field to decide whether item has children
+ * or not.
+ * Note: return value doesn't reflect physical presence of children.
+ */
+static INT TREEVIEW_HasChildren(
+    HWND hwnd, 
+    TREEVIEW_ITEM *wineItem)
+{
+   INT cChildren = 0;
+
+   if ( wineItem->mask & TVIF_CHILDREN )
+   {
+      if (wineItem->cChildren == I_CHILDRENCALLBACK)
+      {
+         TREEVIEW_ITEM tempItem;
+
+         tempItem.hItem  = wineItem->hItem;
+         tempItem.state  = wineItem->state;
+         tempItem.lParam = wineItem->lParam;
+
+         TREEVIEW_SendDispInfoNotify(hwnd, &tempItem, TVN_GETDISPINFOA, TVIF_CHILDREN);
+         cChildren = tempItem.cChildren;
+      }
+      else
+         cChildren = wineItem->cChildren;
+   }
+   else if ( wineItem->firstChild )
+      cChildren = 1;
+
+   return cChildren;
+}
+
+
+/***************************************************************************
  * This method returns the last expanded child item of a tree node
  */
 static TREEVIEW_ITEM *TREEVIEW_GetLastListItem(
+  HWND hwnd,
   TREEVIEW_INFO *infoPtr,
   TREEVIEW_ITEM *tvItem)
+
 {
   TREEVIEW_ITEM *wineItem = tvItem;
 
@@ -138,10 +180,14 @@
   /* 
    * If the last sibling has expanded children, restart.
    */
-  if ( ( wineItem->cChildren > 0 ) && ( wineItem->state & TVIS_EXPANDED) )
+	if ((wineItem->state & TVIS_EXPANDED) &&
+       TREEVIEW_HasChildren(hwnd, wineItem))
+  	{
     return TREEVIEW_GetLastListItem(
+			 hwnd,
              infoPtr, 
              &(infoPtr->items[(INT)wineItem->firstChild]));
+	}
 
   return wineItem;
 }
@@ -151,6 +197,7 @@
  * considering the tree hierarchy.
  */
 static TREEVIEW_ITEM *TREEVIEW_GetPrevListItem(
+	HWND hwnd,
   TREEVIEW_INFO *infoPtr, 
   TREEVIEW_ITEM *tvItem)
 {
@@ -162,10 +209,14 @@
      */
     TREEVIEW_ITEM *upItem = &infoPtr->items[(INT)tvItem->upsibling];
     
-    if ( ( upItem->cChildren > 0 ) && ( upItem->state & TVIS_EXPANDED) )
+	if ( (upItem->state & TVIS_EXPANDED) &&
+           TREEVIEW_HasChildren(hwnd, upItem) )
+     {
       return TREEVIEW_GetLastListItem( 
+			   hwnd,
                infoPtr, 
                &infoPtr->items[(INT)upItem->firstChild]);
+	  }
     else
       return upItem;
   }
@@ -187,6 +238,7 @@
  * considering the tree hierarchy.
  */
 static TREEVIEW_ITEM *TREEVIEW_GetNextListItem(
+  HWND hwnd,
   TREEVIEW_INFO *infoPtr, 
   TREEVIEW_ITEM *tvItem)
 {
@@ -195,8 +247,11 @@
   /* 
    * If this item has children and is expanded, return the first child
    */
-  if ((tvItem->firstChild) && (tvItem->state & TVIS_EXPANDED)) 
+  if ( (tvItem->state & TVIS_EXPANDED) &&
+        TREEVIEW_HasChildren(hwnd, tvItem) )
+  {
 		return (& infoPtr->items[(INT)tvItem->firstChild]);
+  }
 
 
   /*
@@ -226,6 +281,7 @@
  *             forward if count is >0.
  */
 static TREEVIEW_ITEM *TREEVIEW_GetListItem(
+  HWND hwnd,
   TREEVIEW_INFO *infoPtr, 
   TREEVIEW_ITEM *tvItem,
   LONG          count)
@@ -241,7 +297,7 @@
     {
       /* Keep a pointer to the previous in case we ask for more than we got */
       previousItem = wineItem; 
-      wineItem     = TREEVIEW_GetNextListItem(infoPtr, wineItem);
+      wineItem     = TREEVIEW_GetNextListItem(hwnd, infoPtr, wineItem);
     } 
 
     if (wineItem == NULL)
@@ -254,7 +310,7 @@
     {
       /* Keep a pointer to the previous in case we ask for more than we got */
       previousItem = wineItem; 
-      wineItem = TREEVIEW_GetPrevListItem(infoPtr, wineItem);
+      wineItem = TREEVIEW_GetPrevListItem(hwnd, infoPtr, wineItem);
     }
 
     if (wineItem == NULL)
@@ -281,6 +337,7 @@
  kill=(INT)parentItem->firstChild;
  while (kill) {
  	tv_set_bit ( kill, infoPtr->freeList);
+	infoPtr->uNumItems--;
  	killItem=& infoPtr->items[kill];
 	if (killItem->pszText!=LPSTR_TEXTCALLBACKA) 
 		COMCTL32_Free (killItem->pszText);
@@ -290,12 +347,7 @@
 	kill=(INT)killItem->sibling;
  }
 
- if (parentItem->cChildren>0) {
- 	infoPtr->uNumItems -= parentItem->cChildren;
- 	parentItem->firstChild = 0;
- 	parentItem->cChildren  = 0;
- }
-
+ parentItem->firstChild = 0;
 }
 
 
@@ -321,20 +373,10 @@
 
  if (wineItem->parent) {
 	parentItem=& infoPtr->items [(INT)wineItem->parent];
-	switch (parentItem->cChildren) {
-		case I_CHILDRENCALLBACK: 
-				FIXME("we don't handle I_CHILDRENCALLBACK yet\n");
-				break;
-		case 1:
-			parentItem->cChildren=0;
-			parentItem->firstChild=0;    
-			return;
-		default:
-			parentItem->cChildren--;
-			if ((INT)parentItem->firstChild==iItem) 
+
+	if ((INT)parentItem->firstChild==iItem) 
 				parentItem->firstChild=wineItem->sibling;
 		}
- }
 
  if (iItem==(INT)infoPtr->TopRootItem) 
 	infoPtr->TopRootItem=(HTREEITEM)wineItem->sibling;
@@ -346,6 +388,13 @@
 	siblingItem=& infoPtr->items [(INT)wineItem->sibling];
 	siblingItem->upsibling=wineItem->upsibling;
  }
+
+ if (iItem==(INT)infoPtr->selectedItem) {
+     if (!wineItem->upsibling)
+            infoPtr->selectedItem = 0;
+     else
+          TREEVIEW_DoSelectItem(hwnd, TVGN_CARET, wineItem->upsibling, TVC_UNKNOWN);
+ }
 }
 
 
@@ -523,6 +572,10 @@
 
   TRACE("\n");
   infoPtr->clrText=(COLORREF) lParam;
+
+  if (infoPtr->clrText != prevColor)
+     InvalidateRect(hwnd, NULL, TRUE);
+
   return (LRESULT) prevColor;
 }
 
@@ -543,6 +596,10 @@
 
   TRACE("\n");
   infoPtr->clrBk=(COLORREF) lParam;
+
+  if (infoPtr->clrBk != prevColor)
+     InvalidateRect(hwnd, NULL, TRUE);
+
   return (LRESULT) prevColor;
 }
 
@@ -572,7 +629,6 @@
   UINT  uTextJustify = DT_LEFT;
   RECT  r;
 
- 
   if (wineItem->state & TVIS_BOLD) 
   	hOldFont = SelectObject (hdc, infoPtr->hBoldFont);
   else 
@@ -612,10 +668,11 @@
     if ( dwStyle & TVS_LINESATROOT) 
     {
       TREEVIEW_ITEM *upNode    = NULL;
-     	BOOL  hasParentOrSibling = TRUE;
+      BOOL  hasParentOrSibling = TRUE;
       RECT  upRect             = {0,0,0,0};
       HPEN  hOldPen, hNewPen;
-    	POINT points[3];
+   	  POINT points[3];
+	  INT cChildren = 0;
       /* 
        * determine the target location of the line at root, either be linked
        * to the up sibling or to the parent node.
@@ -627,20 +684,23 @@
       else
         hasParentOrSibling = FALSE;
 
-      if (upNode)
+      if (upNode) 
+	  {
         upRect = upNode->rect;
+		cChildren = TREEVIEW_HasChildren(hwnd, upNode);
+	  }
 
       if ( wineItem->iLevel == 0 )
       {
         points[2].x = points[1].x = upRect.left+8;
         points[0].x = points[2].x + 10;
-        points[2].y = upRect.bottom-3;      
+        points[2].y = upRect.bottom- (cChildren ? 3 : 8);
         points[1].y = points[0].y = center;
       }
       else
       {
         points[2].x = points[1].x = 8 + (20*wineItem->iLevel); 
-        points[2].y = ( upNode->cChildren == 0) ? 
+        points[2].y = (cChildren == 0) ?
                         upRect.top :        /* is linked to the "L" above */
                         ( wineItem->upsibling != NULL) ? 
                           upRect.bottom-3:  /* is linked to an icon       */
@@ -673,8 +733,7 @@
 
   if (( dwStyle & TVS_HASBUTTONS) && ( dwStyle & TVS_HASLINES))
   {
-	  if ( (wineItem->cChildren) ||
-	       (wineItem->cChildren == I_CHILDRENCALLBACK))
+	if (TREEVIEW_HasChildren(hwnd, wineItem))
     {
       /* Setup expand box coordinate to facilitate the LMBClick handling */
       wineItem->expandBox.left   = xpos-4;
@@ -714,7 +773,6 @@
    	if (infoPtr->himlState) 
         himlp=&infoPtr->himlState;
 	imageIndex=wineItem->state>>12;
-	imageIndex++;          /* yeah, right */
 	TRACE ("imindex:%d\n",imageIndex);
     if ((himlp) && (imageIndex))
     { 
@@ -740,7 +798,7 @@
   	if ( (wineItem->state & TVIS_SELECTED) && 
          (wineItem->iSelectedImage)) { 
         
-      /* The item is curently selected */
+      /* The item is currently selected */
 		  if (wineItem->iSelectedImage == I_IMAGECALLBACK) 
   			TREEVIEW_SendDispInfoNotify 
 					(hwnd, wineItem, TVN_GETDISPINFOA, TVIF_SELECTEDIMAGE);
@@ -757,7 +815,12 @@
  
     if (himlp)         
     { 
-      ImageList_Draw ( *himlp, imageIndex, hdc, xpos-2, r.top+1, ILD_NORMAL);
+      int ovlIdx = 0;
+
+      if (wineItem->stateMask & TVIS_OVERLAYMASK)
+           ovlIdx = wineItem->state & TVIS_OVERLAYMASK;
+
+      ImageList_Draw ( *himlp, imageIndex, hdc, xpos-2, r.top+1, ILD_NORMAL|ovlIdx);
    	  ImageList_GetIconSize (*himlp, &cx, &cy);
 	  wineItem->bitmap.left=xpos-2;
 	  wineItem->bitmap.right=xpos-2+cx;
@@ -771,12 +834,17 @@
   /* 
    * Display the text associated with this item
    */
+
+  /* Don't paint item's text if it's being edited */
+  if (!infoPtr->hwndEdit || (infoPtr->editItem != wineItem->hItem))
+  {
   r.left=xpos;
   if ((wineItem->mask & TVIF_TEXT) && (wineItem->pszText)) 
   {
-    COLORREF oldBkColor = 0;
     COLORREF oldTextColor = 0;
     INT      oldBkMode;
+      HBRUSH   hbrBk = 0;
+      BOOL     inFocus = GetFocus() == hwnd;
 
     r.left += 3;
     r.right -= 3;
@@ -786,81 +854,106 @@
     wineItem->text.top   = r.top;
     wineItem->text.bottom= r.bottom;
 
-    if (wineItem->pszText== LPSTR_TEXTCALLBACKA) {
-      TRACE("LPSTR_TEXTCALLBACK\n");
-      TREEVIEW_SendDispInfoNotify (hwnd, wineItem, TVN_GETDISPINFOA, TVIF_TEXT);
-    }
-
-/* Yep, there are some things that need to be straightened out here. 
-   Removing the comments around the setTextColor does not give the right
-   results. Dito FillRect.
-*/
+      oldBkMode = SetBkMode(hdc, TRANSPARENT);
 
+      /* - If item is drop target or it is selected and window is in focus -
+       * use blue background (COLOR_HIGHLIGHT).
+       * - If item is selected, window is not in focus, but it has style
+       * TVS_SHOWSELALWAYS - use grey background (COLOR_BTNFACE)
+       * - Otherwise - don't fill background
+       */
+       if ((wineItem->state & TVIS_DROPHILITED) ||
+	   ((wineItem->state & TVIS_SELECTED) &&
+	    (inFocus || (GetWindowLongA( hwnd, GWL_STYLE) & TVS_SHOWSELALWAYS))))
+       {
+	   if ((wineItem->state & TVIS_DROPHILITED) || inFocus)
+	   {
+	       hbrBk = CreateSolidBrush(GetSysColor( COLOR_HIGHLIGHT));
+	       oldTextColor = SetTextColor(hdc, GetSysColor( COLOR_HIGHLIGHTTEXT));
+	   }
+	   else
+	   {
+	       hbrBk = CreateSolidBrush(GetSysColor( COLOR_BTNFACE));
+
+	       if (infoPtr->clrText == -1)
+		   oldTextColor = SetTextColor(hdc, GetSysColor( COLOR_WINDOWTEXT));
+	       else
+		   oldTextColor = SetTextColor(hdc, infoPtr->clrText);
+	   }
+      } 
+      else 
+      {
+	  if (infoPtr->clrText == -1)
+	      oldTextColor = SetTextColor(hdc, GetSysColor( COLOR_WINDOWTEXT));
+	  else
+	      oldTextColor = SetTextColor(hdc, infoPtr->clrText);
+      }
         
-/*    GetTextExtentPoint32A (hdc, wineItem->pszText, 
-					strlen (wineItem->pszText), &size); */
+      if (wineItem->pszText== LPSTR_TEXTCALLBACKA) {
+        TRACE("LPSTR_TEXTCALLBACK\n");
+        TREEVIEW_SendDispInfoNotify (hwnd, wineItem, TVN_GETDISPINFOA, TVIF_TEXT);
+      }
 	
-/*    FillRect ( hdc, &wineItem->text, GetSysColorBrush (infoPtr->clrBk));
- */
+      /* Obtain the text coordinate */
+     DrawTextA (
+	    hdc,
+	    wineItem->pszText,
+	    lstrlenA(wineItem->pszText),
+	    &wineItem->text,
+	    uTextJustify | DT_VCENTER | DT_SINGLELINE | DT_CALCRECT | DT_NOPREFIX);
     
+      /* We need to reset it to items height */
+      wineItem->text.top = r.top;
+      wineItem->text.bottom = r.bottom;
+      wineItem->text.right += 4; /* This is extra for focus rectangle */
 
-    if (!(cditem & CDRF_NOTIFYPOSTPAINT) && 
-        (wineItem->state & (TVIS_SELECTED | TVIS_DROPHILITED)) ) {
-    	oldBkMode    = SetBkMode  (hdc, OPAQUE);
-    	oldBkColor   = SetBkColor  (hdc, GetSysColor( COLOR_HIGHLIGHT));
-    	oldTextColor = SetTextColor(hdc, GetSysColor( COLOR_HIGHLIGHTTEXT));
-	} else {
-    	oldBkMode    = SetBkMode  (hdc, TRANSPARENT);
-	  	oldBkColor   = SetBkColor (hdc, infoPtr->clrBk);
- /*	    oldTextColor = SetTextColor(hdc, infoPtr->clrText);  */
+      if (hbrBk)
+      {
+          FillRect(hdc, &wineItem->text, hbrBk);
+	  DeleteObject(hbrBk);
 	}
 
-
+      wineItem->text.left += 2;
 
     /* Draw it */
     DrawTextA ( hdc, 
       wineItem->pszText, 
       lstrlenA(wineItem->pszText), 
       &wineItem->text, 
-      uTextJustify | DT_VCENTER | DT_SINGLELINE ); 
+        uTextJustify | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); 
 
-    /* Obtain the text coordinate */
-    DrawTextA (
-      hdc, 
-      wineItem->pszText, 
-      lstrlenA(wineItem->pszText), 
-      &wineItem->text, 
-      uTextJustify | DT_VCENTER | DT_SINGLELINE | DT_CALCRECT); 
+       wineItem->text.left -=2;
 
     /* Restore the hdc state */
     SetTextColor( hdc, oldTextColor);
 
-    if (oldBkMode != TRANSPARENT)
-      SetBkMode(hdc, oldBkMode);
-    if (wineItem->state & (TVIS_SELECTED | TVIS_DROPHILITED))
-      SetBkColor (hdc, oldBkColor);
-
     /* Draw the box arround the selected item */
-    if (wineItem->state & TVIS_SELECTED ) 
+      if ((wineItem->state & TVIS_SELECTED) && inFocus) 
     {
       HPEN  hNewPen     = CreatePen(PS_DOT, 0, GetSysColor(COLOR_WINDOWTEXT) );
       HPEN  hOldPen     = SelectObject( hdc, hNewPen );
-      POINT points[4];
+	INT   rop	  = SetROP2(hdc, R2_XORPEN);
+        POINT points[5];
       
-      points[0].x = wineItem->text.left-1;
-      points[0].y = wineItem->text.top+1; 
-      points[1].x = wineItem->text.right;
-      points[1].y = wineItem->text.top+1; 
-      points[2].x = wineItem->text.right;
-      points[2].y = wineItem->text.bottom; 
-      points[3].x = wineItem->text.left-1;
-      points[3].y = wineItem->text.bottom;
+        points[4].x = points[0].x = wineItem->text.left;
+        points[4].y = points[0].y = wineItem->text.top; 
+        points[1].x = wineItem->text.right-1 ;
+        points[1].y = wineItem->text.top; 
+        points[2].x = wineItem->text.right-1;
+        points[2].y = wineItem->text.bottom-1; 
+        points[3].x = wineItem->text.left;
+        points[3].y = wineItem->text.bottom-1;
 
-      Polyline (hdc,points,4); 
+        Polyline (hdc,points,5); 
 
+	SetROP2(hdc, rop);
       DeleteObject(hNewPen);
       SelectObject(hdc, hOldPen);
     }
+
+      if (oldBkMode != TRANSPARENT)
+	  SetBkMode(hdc, oldBkMode);
+    }
   }
 
   /* Draw insertion mark if necessary */
@@ -899,7 +992,7 @@
                        (hwnd, hdc, wineItem, CDDS_ITEMPOSTPAINT);
 		TRACE("postpaint:cditem-app returns 0x%x\n",cditem);
 	}
-
+  
   SelectObject (hdc, hOldFont);
 }
 
@@ -1013,9 +1106,11 @@
 
   if (tvItem->mask & TVIF_TEXT) {
 		if (tvItem->pszText!=LPSTR_TEXTCALLBACKA) {
-        len=lstrlenA (tvItem->pszText);
-        if (len>wineItem->cchTextMax) 
-			wineItem->pszText= COMCTL32_ReAlloc (wineItem->pszText, len+1);
+        len=lstrlenA (tvItem->pszText)+1;
+        if (len>wineItem->cchTextMax) {
+			wineItem->pszText= COMCTL32_ReAlloc (wineItem->pszText, len);
+			wineItem->cchTextMax=len;
+		}
         lstrcpynA (wineItem->pszText, tvItem->pszText,len);
 		} else {
 			if (wineItem->cchTextMax) {
@@ -1048,25 +1143,25 @@
 
 
 
+
 static void
 TREEVIEW_Refresh (HWND hwnd, HDC hdc)
+
 {
     TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
 	TEXTMETRICA tm;
 	HBRUSH hbrBk;
     RECT rect;
-    INT iItem, indent, x, y, cx, height, itemHeight;
+    INT iItem, indent, x, y, height, itemHeight;
     INT viewtop,viewbottom,viewleft,viewright;
-    TREEVIEW_ITEM *wineItem, *prevItem;
+    TREEVIEW_ITEM *wineItem;
 
     TRACE("\n");
 
-
     if (infoPtr->Timer & TV_REFRESH_TIMER_SET) {
 		KillTimer (hwnd, TV_REFRESH_TIMER);
 		infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
     }
-
     
     GetClientRect (hwnd, &rect);
     if ((rect.left-rect.right ==0) || (rect.top-rect.bottom==0)) return;
@@ -1084,25 +1179,16 @@
     viewleft=infoPtr->cx;
     viewright=infoPtr->cx + rect.right-rect.left;
 
+    TRACE("[%d %d %d %d]\n",viewtop,viewbottom,viewleft,viewright);
+
     /* draw background */
     
     hbrBk = CreateSolidBrush (infoPtr->clrBk);
     FillRect(hdc, &rect, hbrBk);
     DeleteObject(hbrBk);
 
-    iItem=(INT)infoPtr->TopRootItem;
-    infoPtr->firstVisible=0;
-    wineItem=NULL;
-    indent=0;
-    x=y=0;
-    TRACE("[%d %d %d %d]\n",viewtop,viewbottom,viewleft,viewright);
 
-    while (iItem) {
-		prevItem=wineItem;
-        wineItem= & infoPtr->items[iItem];
-		wineItem->iLevel=indent;
-
-        ImageList_GetIconSize (infoPtr->himlNormal, &cx, &itemHeight);
+    ImageList_GetIconSize (infoPtr->himlNormal, &x, &itemHeight);
         if (infoPtr->uItemHeight>itemHeight)
 		    itemHeight=infoPtr->uItemHeight;
 
@@ -1112,6 +1198,16 @@
 
         infoPtr->uRealItemHeight=itemHeight;	
 
+    iItem=(INT)infoPtr->TopRootItem;
+    infoPtr->firstVisible=0;
+    wineItem=NULL;
+    indent=0;
+    x=y=0;
+
+    while (iItem) {
+		wineItem= & infoPtr->items[iItem];
+		wineItem->iLevel=indent;
+
 
 /* FIXME: remove this in later stage  */
 /*
@@ -1161,7 +1257,6 @@
 			while ((!iItem) && (indent>0)) {
 				indent--;
 				x-=infoPtr->uIndent;
-				prevItem=wineItem;
 				wineItem=&infoPtr->items[(INT)wineItem->parent];
 				iItem=(INT)wineItem->sibling;
 			}
@@ -1212,6 +1307,8 @@
 	case TV_EDIT_TIMER:
 		KillTimer (hwnd, TV_EDIT_TIMER);
 		infoPtr->Timer &= ~TV_EDIT_TIMER_SET;
+		if (infoPtr->editItem)
+          TREEVIEW_EditLabelA(hwnd, infoPtr->editItem);
 		return 0;
 	default:
 		ERR("got unknown timer\n");
@@ -1253,9 +1350,7 @@
   if (!wineItem) return FALSE;
 
    if (tvItem->mask & TVIF_CHILDREN) {
-		if (TVIF_CHILDREN==I_CHILDRENCALLBACK) 
-			FIXME("I_CHILDRENCALLBACK not supported\n");
-        tvItem->cChildren=wineItem->cChildren;
+        tvItem->cChildren=TREEVIEW_HasChildren(hwnd, wineItem);
    }
 
    if (tvItem->mask & TVIF_HANDLE) {
@@ -1316,6 +1411,8 @@
   iItem = (INT) lParam;
   retval=0;
   switch (flag) {
+	case TVGN_CHILD:  /* Special case: child of 0 is root */
+					if (iItem) break;
 	case TVGN_ROOT: retval=(INT)infoPtr->TopRootItem;
 					break;
 	case TVGN_CARET:retval=(INT)infoPtr->selectedItem;
@@ -1352,13 +1449,13 @@
 					retval=(INT)wineItem->firstChild;
 					break;
 	case TVGN_LASTVISIBLE:  
-					returnItem=TREEVIEW_GetLastListItem (infoPtr,wineItem);
+					returnItem=TREEVIEW_GetLastListItem (hwnd,infoPtr,wineItem);
 					break;
 	case TVGN_NEXTVISIBLE:  
-					returnItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
+					returnItem=TREEVIEW_GetNextListItem (hwnd,infoPtr,wineItem);
 					break;
 	case TVGN_PREVIOUSVISIBLE: 
-					returnItem=TREEVIEW_GetPrevListItem (infoPtr, wineItem);
+					returnItem=TREEVIEW_GetPrevListItem (hwnd,infoPtr,wineItem);
 					break;
 	default:		FIXME("Unknown msg %x,item %x\n", flag,iItem);
 					break;
@@ -1522,7 +1619,12 @@
 	}
   txt2=item->pszText;
 
-  return -strcmp (txt1,txt2);
+  /*
+   * Why are we negating? And, why are we being
+   * case sensitive.
+   */
+  /* return -strcmp (txt1,txt2); */
+  return strcasecmp( txt1, txt2 );
 }
 
 /***************************************************************************
@@ -1545,6 +1647,8 @@
 {
   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
   TREEVIEW_ITEM *sortMe  = NULL; /* Node for which we sort the children */
+  INT            cChildren;
+  HTREEITEM      hti;
 
   /* Obtain the TVSORTBC struct */
   infoPtr->pCallBackSort = pSort;
@@ -1564,11 +1668,15 @@
   /* Obtain the parent node to sort */  
   sortMe = &infoPtr->items[ (INT)parent ];
 
+  cChildren = 0;
+  for(hti = sortMe->firstChild; hti; hti = infoPtr->items[(INT)hti].sibling)
+      cChildren++;
+
   /* Make sure there is something to sort */
-  if ( sortMe->cChildren > 1 ) 
+  if ( cChildren > 1 ) 
   {
     /* pointer organization */
-    HDPA          sortList   = DPA_Create(sortMe->cChildren);
+    HDPA          sortList   = DPA_Create(cChildren);
     HTREEITEM     itemHandle = sortMe->firstChild;
     TREEVIEW_ITEM *itemPtr   = & infoPtr->items[ (INT)itemHandle ];
 
@@ -1583,7 +1691,7 @@
     {
       DPA_InsertPtr(
         sortList,              /* the list */
-        sortMe->cChildren+1,   /* force the insertion to be an append */
+        cChildren+1,           /* force the insertion to be an append */
         itemPtr);              /* the ptr to store */   
 
       /* Get the next sibling */
@@ -1684,7 +1792,7 @@
   TVINSERTSTRUCTA  *ptdi;
   TVITEMEXA 	*tvItem;
   TREEVIEW_ITEM *wineItem, *parentItem, *prevsib, *sibItem;
-  INT		iItem,listItems,i,len;
+  INT		iItem,i,len;
  
   /* Item to insert */
   ptdi = (LPTVINSERTSTRUCTA) lParam;
@@ -1754,7 +1862,6 @@
     parentItem       = NULL;
     wineItem->parent = 0; 
     sibItem          = &infoPtr->items [(INT)infoPtr->TopRootItem];
-    listItems        = infoPtr->uNumItems;
   }
   else  {
   	parentItem = &infoPtr->items[(INT)ptdi->hParent];
@@ -1765,8 +1872,6 @@
   
   	wineItem->parent = ptdi->hParent;
   	sibItem          = &infoPtr->items [(INT)parentItem->firstChild];
-  	parentItem->cChildren++;
-  	listItems        = parentItem->cChildren;
   }
 
   
@@ -1785,7 +1890,7 @@
     {
       TRACE("(%p,%s)\n", &tvItem->pszText, tvItem->pszText); 
       len = lstrlenA (tvItem->pszText)+1;
-      wineItem->pszText= COMCTL32_Alloc (len+1);
+      wineItem->pszText= COMCTL32_Alloc (len);
       lstrcpyA (wineItem->pszText, tvItem->pszText);
       wineItem->cchTextMax=len;
     }
@@ -1806,12 +1911,11 @@
   wineItem->firstChild=0;
   wineItem->hItem=(HTREEITEM)iItem;
 
-  if (listItems>1) {
+  if (sibItem!=wineItem) {
      prevsib=NULL;
 
      switch ((DWORD) ptdi->hInsertAfter) {
 		case (DWORD) TVI_FIRST: 
-			if (sibItem==wineItem) break;
 			if (wineItem->parent) {
 				wineItem->sibling=parentItem->firstChild;
 				parentItem->firstChild=(HTREEITEM)iItem;
@@ -1823,14 +1927,7 @@
 			break;
 
 		case (DWORD) TVI_SORT:  
-  	  if (sibItem==wineItem) 
-        /* 
-         * This item is the first child of the level and it 
-         * has already been inserted 
-         */                
-        break; 
-      else
-      {
+      	{
         TREEVIEW_ITEM *aChild;
 		  
   
@@ -1898,7 +1995,7 @@
 
 
 		case (DWORD) TVI_LAST:  
-			if (sibItem==wineItem) break;
+		        TVI_LAST_CASE:
 			while (sibItem->sibling) {
 				prevsib=sibItem;
 				sibItem=&infoPtr->items [(INT)sibItem->sibling];
@@ -1913,9 +2010,7 @@
                 sibItem=&infoPtr->items [(INT)sibItem->sibling];
               }
 			if (sibItem->hItem!=ptdi->hInsertAfter) {
-			 ERR("tried to insert item after nonexisting handle %d.\n",
-                      (INT) ptdi->hInsertAfter);
-			 break;
+				goto TVI_LAST_CASE;
 			}
 			prevsib=sibItem;
 			if (sibItem->sibling) {
@@ -1935,14 +2030,11 @@
    TRACE("new item %d; parent %d, mask %x\n", iItem, 
 			(INT)wineItem->parent,tvItem->mask);
 
-   wineItem->mask=tvItem->mask;
-   wineItem->iIntegral=1; 
+  wineItem->mask=tvItem->mask;
+  wineItem->iIntegral=1; 
 
-   if (tvItem->mask & TVIF_CHILDREN) {
+  if (tvItem->mask & TVIF_CHILDREN) 
 	 wineItem->cChildren=tvItem->cChildren;
-	 if (tvItem->cChildren==I_CHILDRENCALLBACK) 
-			FIXME(" I_CHILDRENCALLBACK not supported\n");
-	}
 
   wineItem->expandBox.left   = 0; /* Initialize the expandBox */
   wineItem->expandBox.top    = 0;
@@ -1968,6 +2060,7 @@
 	wineItem->stateMask=tvItem->stateMask;
    }
 
+
    TREEVIEW_QueueRefresh (hwnd);
 
    return (LRESULT) iItem;
@@ -2117,33 +2210,55 @@
 TREEVIEW_Edit_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, 
 							LPARAM lParam)
 {
+  BOOL bCancel = FALSE;
+  static BOOL bIgnoreKillFocus = FALSE;
+
   switch (uMsg) 
   {
-    case WM_ERASEBKGND: 
+    case WM_PAINT:
     {
-      RECT rc;
-      HDC  hdc = (HDC) wParam;
-      GetClientRect (hwnd, &rc);
-      Rectangle (hdc, rc.left, rc.top, rc.right, rc.bottom);
-      return -1;
+          LRESULT rc;
+	  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd));
+	  TRACE("WM_PAINT start\n");
+	  rc = CallWindowProcA( infoPtr->wpEditOrig, hwnd, uMsg, wParam, lParam);
+	  TRACE("WM_PAINT done\n");
+	  return rc;
     }
 
-    case WM_GETDLGCODE:
+    case WM_KILLFOCUS:
+        if(bIgnoreKillFocus)
     {
+            return TRUE;
+        }
+	break;
+
+    case WM_GETDLGCODE:
       return DLGC_WANTARROWS | DLGC_WANTALLKEYS;
+
+    case WM_KEYDOWN:
+        if (VK_ESCAPE == (INT)wParam)
+        {
+	    bCancel = TRUE;
+            break;
+        }
+        else if (VK_RETURN == (INT)wParam)
+        {
+	    break;
     }
 
     default:
     {
       TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd));
-	  if (infoPtr!=NULL)
        return CallWindowProcA (infoPtr->wpEditOrig, hwnd, uMsg, wParam, lParam);
-	  else 
-		break;
-		
     }
   }
 
+  /* Processing LVN_ENDLABELEDIT message could kill the focus       */
+  /* eg. Using a messagebox                                         */
+  bIgnoreKillFocus = TRUE;
+  TREEVIEW_EndEditLabelNow(GetParent(hwnd), bCancel);
+  bIgnoreKillFocus = FALSE;
+
   return 0;
 }
 
@@ -2163,34 +2278,48 @@
       /* 
        * Adjust the edit window size 
        */
+      char buffer[1024];
       TREEVIEW_INFO *infoPtr  = TREEVIEW_GetInfoPtr(hwnd);
       TREEVIEW_ITEM *editItem = TREEVIEW_ValidItem(infoPtr, infoPtr->editItem);
-      INT           iLength   = GetWindowTextLengthA(infoPtr->hwndEdit);
       HDC           hdc       = GetDC(infoPtr->hwndEdit);
-      TEXTMETRICA   tm;
+      SIZE 	    sz;
+      int	    len;
+      HFONT         hFont, hOldFont=0;
+
+      len = GetWindowTextA(infoPtr->hwndEdit, buffer, 1024);
+
+      /* Select font to get the right dimension of the string */
+      hFont = SendMessageA(infoPtr->hwndEdit, WM_GETFONT, 0, 0);
+      if(hFont != 0)
+      {
+          hOldFont = SelectObject(hdc, hFont);
+      }
 
-      if ( GetTextMetricsA(hdc, &tm) )
+      if (GetTextExtentPoint32A(hdc, buffer, strlen(buffer), &sz))
       {
-        LONG newWidth = (iLength * tm.tmAveCharWidth) + 15;
+          TEXTMETRICA textMetric;
+          /* Add Extra spacing for the next character */
+          GetTextMetricsA(hdc, &textMetric);
+          sz.cx += (textMetric.tmMaxCharWidth * 2);
             
     		SetWindowPos ( 
           infoPtr->hwndEdit,
           HWND_TOP, 
-          editItem->text.left - 2, 
-          editItem->text.top  - 1,
-          newWidth,
+            0, 
+            0,
+            sz.cx,
           editItem->text.bottom - editItem->text.top  + 3,
-          SWP_DRAWFRAME );
+            SWP_NOMOVE|SWP_DRAWFRAME);
       }
-      ReleaseDC(hwnd, hdc);
 
-      break;
+      if(hFont != 0)
+      {
+          SelectObject(hdc, hOldFont);
     }
 
-    case EN_KILLFOCUS:
-/*      TREEVIEW_EndEditLabelNow(hwnd, (WPARAM)FALSE, 0); 
-*/
+      ReleaseDC(hwnd, hdc);
       break;
+    }
 
     default:
       return SendMessageA (GetParent (hwnd), WM_COMMAND, wParam, lParam);
@@ -2329,22 +2458,6 @@
         SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA, 0, (LPARAM)&ti);
     }
 
- 	infoPtr->hwndEdit = CreateWindowExA ( 
-                          WS_EX_LEFT, 
-                          "EDIT",
-                          0,
-                          WS_CHILD | WS_BORDER | ES_AUTOHSCROLL | 
-                          ES_WANTRETURN | ES_LEFT,
-                          0, 0, 0, 0,
-                          hwnd, 
-                          0,0,0); /* FIXME: (HMENU)IDTVEDIT,pcs->hInstance,0);*/
-
-  SendMessageA ( infoPtr->hwndEdit, WM_SETFONT, infoPtr->hFont, FALSE);
-	infoPtr->wpEditOrig = (WNDPROC)SetWindowLongA (
-                                    infoPtr->hwndEdit,
-                                    GWL_WNDPROC, 
-                           					(LONG) TREEVIEW_Edit_SubclassProc);
-
   if (dwStyle & TVS_CHECKBOXES) {	
 		HBITMAP hbmLoad;
 		int nIndex;
@@ -2371,13 +2484,16 @@
      
   TRACE("\n");
   TREEVIEW_RemoveTree (hwnd);
-  SetWindowLongA (hwnd, 0, (DWORD)NULL);
-
   if (infoPtr->Timer & TV_REFRESH_TIMER_SET) 
         KillTimer (hwnd, TV_REFRESH_TIMER);
   if (infoPtr->hwndToolTip) 
 		DestroyWindow (infoPtr->hwndToolTip);
 
+   /* Restore original windproc so that we can free infoPtr */
+   if (infoPtr->hwndEdit)
+   SetWindowLongA (infoPtr->hwndEdit, GWL_WNDPROC, (DWORD)infoPtr->wpEditOrig);
+
+   DeleteObject(infoPtr->hBoldFont);
   COMCTL32_Free (infoPtr);
   return 0;
 }
@@ -2402,6 +2518,20 @@
 static LRESULT
 TREEVIEW_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
+   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
+
+   if(!infoPtr->selectedItem)
+   {
+      if(!infoPtr->firstVisible) {
+		 HDC hdc = GetDC (hwnd);
+         TREEVIEW_Refresh (hwnd,hdc);
+		 ReleaseDC (hwnd,hdc);
+	  }
+
+      TREEVIEW_DoSelectItem(hwnd, TVGN_CARET, infoPtr->firstVisible, TVC_UNKNOWN);
+   }
+
+
    TREEVIEW_SendSimpleNotify (hwnd, NM_SETFOCUS);
    InvalidateRect(hwnd, NULL, FALSE);
    return 0;
@@ -2467,6 +2597,9 @@
 
   TRACE("code:%x action:%x olditem:%x newitem:%x\n",
 		  code,action,(INT)oldItem,(INT)newItem);
+
+  ZeroMemory(&nmhdr, sizeof(NMTREEVIEWA));
+
   nmhdr.hdr.hwndFrom = hwnd;
   nmhdr.hdr.idFrom =  GetWindowLongA( hwnd, GWL_ID);
   nmhdr.hdr.code = code;
@@ -2569,6 +2702,10 @@
                   (WPARAM)tvdi.hdr.idFrom, 
                   (LPARAM)&tvdi);
 
+  /* Ignore posible changes */
+  if (code == TVN_BEGINLABELEDITA)
+      return retval;
+
   if (what & TVIF_TEXT) {
 		wineItem->pszText        = tvdi.item.pszText;
 		if (buf==tvdi.item.pszText) {
@@ -2697,7 +2834,7 @@
 
   if (!wineItem) 
     return 0;
-  if (!wineItem->cChildren) 
+  if (!TREEVIEW_HasChildren(hwnd, wineItem))
     return 0;
 
 	if (wineItem->pszText==LPSTR_TEXTCALLBACKA) 
@@ -2707,11 +2844,6 @@
   		TRACE("For (%s) item:%d, flags %x, state:%d\n", 
                 wineItem->pszText, flag, expand, wineItem->state);
 
-  if (wineItem->cChildren==I_CHILDRENCALLBACK) {
-    FIXME("we don't handle I_CHILDRENCALLBACK yet\n");
-    return 0;
-  }
-
   if (flag == TVE_TOGGLE) {    /* FIXME: check exact behaviour here */
    flag &= ~TVE_TOGGLE;    /* ie: bitwise ops or 'case' ops */
    if (wineItem->state & TVIS_EXPANDED) 
@@ -2720,23 +2852,21 @@
      flag |= TVE_EXPAND;
   }
 
-  switch (flag) 
+  switch (flag & TVE_TOGGLE) 
   {
-    case TVE_COLLAPSERESET: 
-      TRACE("  case TVE_COLLAPSERESET\n");
-      if (!wineItem->state & TVIS_EXPANDED) 
-        return 0;
-
-       wineItem->state &= ~(TVIS_EXPANDEDONCE | TVIS_EXPANDED);
-       TREEVIEW_RemoveAllChildren (hwnd, wineItem);
-       break;
-
     case TVE_COLLAPSE: 
       TRACE("  case TVE_COLLAPSE\n");
       if (!wineItem->state & TVIS_EXPANDED) 
         return 0;
 
       wineItem->state &= ~TVIS_EXPANDED;
+
+      if (flag & TVE_COLLAPSERESET)
+      {
+         TRACE("  TVE_COLLAPSERESET\n");
+         wineItem->state &= ~TVIS_EXPANDEDONCE;
+         TREEVIEW_RemoveAllChildren (hwnd, wineItem);
+      }
       break;
 
     case TVE_EXPAND: 
@@ -2798,14 +2928,37 @@
         /* this item has already been expanded */
         wineItem->state |= TVIS_EXPANDED;
       }
-      break;
 
-    case TVE_EXPANDPARTIAL:
-      TRACE("  case TVE_EXPANDPARTIAL\n");
+      if(flag & TVE_EXPANDPARTIAL)
+      {
       FIXME("TVE_EXPANDPARTIAL not implemented\n");
-      wineItem->state ^=TVIS_EXPANDED;
-      wineItem->state |=TVIS_EXPANDEDONCE;
+      }
       break;
+
+    default:
+      return 0;
+  }
+
+  /* If item was collapsed we probably need to change selection */
+  if (flag & TVE_COLLAPSE)
+  {
+     HTREEITEM hItem = infoPtr->selectedItem;
+
+     if (!TREEVIEW_ValidItem (infoPtr, hItem))
+        hItem = wineItem->hItem;
+     else
+     {
+        while ( hItem )
+        {
+           hItem = infoPtr->items[(INT)hItem].parent;
+
+           if (hItem == wineItem->hItem)
+      break;
+  }
+     }
+
+     if (hItem)
+        TREEVIEW_DoSelectItem(hwnd, TVGN_CARET, hItem, TVC_UNKNOWN);
   }
 
   TRACE("Exiting, Item %d state is now %d...\n", 
@@ -2832,7 +2985,7 @@
  wineItem=&infoPtr->items [(INT)infoPtr->firstVisible];
 
  while ((wineItem!=NULL) && (pt.y > wineItem->rect.bottom))
-       wineItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
+       wineItem=TREEVIEW_GetNextListItem (hwnd, infoPtr, wineItem);
 	
  if (!wineItem) 
 	return NULL;
@@ -2851,6 +3004,7 @@
   RECT rect;
   UINT status,x,y;
 
+  lpht->hItem = 0;
   GetClientRect (hwnd, &rect);
   status=0;
   x=lpht->pt.x;
@@ -2904,77 +3058,219 @@
   return (LRESULT) wineItem->hItem;
 }
 
-LRESULT WINAPI
-TREEVIEW_EndEditLabelNow (HWND hwnd, WPARAM wParam, LPARAM lParam)
+
+HWND TREEVIEW_EditLabelA(HWND hwnd, HTREEITEM hItem)
 {
+  SIZE sz;
   TREEVIEW_INFO *infoPtr    = TREEVIEW_GetInfoPtr(hwnd);
-  TREEVIEW_ITEM *editedItem = TREEVIEW_ValidItem (infoPtr, infoPtr->editItem);
-  BOOL          bRevert     = (BOOL)wParam;
-  BOOL          bReturn     = ! bRevert;
+  TREEVIEW_ITEM *editItem = TREEVIEW_ValidItem(infoPtr, (HTREEITEM)hItem);
+  HINSTANCE hinst = GetWindowLongA(hwnd, GWL_HINSTANCE);
 
-  if ( ! (BOOL)wParam ) /* wParam is set to true to cancel the edition */
+  HDC hdc;
+  HFONT hOldFont=0;
+  TEXTMETRICA textMetric;
+
+  TRACE("%d %d\n",(INT)hwnd, (INT)hItem);
+   if (!editItem)
+       return FALSE;
+
+  if(infoPtr->hwndEdit)
+    return infoPtr->hwndEdit;
+
+   /* Make shure that edit item is selected */
+  TREEVIEW_DoSelectItem ( hwnd, TVGN_CARET, hItem, TVC_UNKNOWN);
+  hdc = GetDC (hwnd);
+  TREEVIEW_Refresh(hwnd, hdc);
+
+  if (editItem->pszText== LPSTR_TEXTCALLBACKA)
+       TREEVIEW_SendDispInfoNotify (hwnd, editItem, TVN_GETDISPINFOA, TVIF_TEXT);
+
+    /* Select the font to get appropriate metric dimensions */
+  if(infoPtr->hFont != 0)
   {
-		if ( TREEVIEW_SendDispInfoNotify(  /* return true to cancel edition */
-           hwnd, 
-           editedItem,
-           TVN_ENDLABELEDITA, 
-           0))
-    {
-      bRevert = TRUE;
-      bReturn = FALSE; 
-    }
+	      hOldFont = SelectObject(hdc, infoPtr->hFont);
   }
 
-  if (bRevert == FALSE) /* Apply the changes */
+  /*Get String Lenght in pixels */
+  GetTextExtentPoint32A(hdc, editItem->pszText, strlen(editItem->pszText), &sz);
+
+  /*Add Extra spacing for the next character */
+  GetTextMetricsA(hdc, &textMetric);
+  sz.cx += (textMetric.tmMaxCharWidth * 2);
+
+  if(infoPtr->hFont != 0)
   {
-    char tmpText[1024];
-    int  iLength = GetWindowTextA(infoPtr->hwndEdit, tmpText, 1023);
-    bReturn      = FALSE;
+      SelectObject(hdc, hOldFont);
+  }
+
+  ReleaseDC(hwnd, hdc);
+  infoPtr->hwndEdit = CreateWindowExA (
+                         WS_EX_LEFT,
+                         "EDIT",
+                     	 0,
+                         WS_CHILD | WS_BORDER | ES_AUTOHSCROLL | WS_CLIPSIBLINGS |
+						  ES_WANTRETURN | ES_LEFT,
+                         editItem->text.left - 2, editItem->text.top  - 1,
+            sz.cx+3, editItem->text.bottom - editItem->text.top  + 3,
+						 hwnd,
+                         0,hinst,0); /* FIXME: (HMENU)IDTVEDIT,pcs->hInstance,0);*/
+
+  SendMessageA ( infoPtr->hwndEdit, WM_SETFONT, infoPtr->hFont, FALSE);
+  infoPtr->wpEditOrig = (WNDPROC)SetWindowLongA (
+                                   infoPtr->hwndEdit,
+                                   GWL_WNDPROC,
+                  (DWORD) TREEVIEW_Edit_SubclassProc);
+
+  if (TREEVIEW_SendDispInfoNotify (hwnd, editItem, TVN_BEGINLABELEDITA,
+           editItem->mask & (TVIF_HANDLE|TVIF_TEXT|TVIF_STATE|TVIF_PARAM)))
+
 
-    if (iLength == 0) 
     {
-      ERR("Problem retreiving new item label.");
+	     DestroyWindow(infoPtr->hwndEdit);
+     infoPtr->hwndEdit = 0;
+     return (HWND)0;
     }
-    else if (iLength >= 1023)
+
+  infoPtr->editItem = hItem;
+  SetWindowTextA(infoPtr->hwndEdit, editItem->pszText);
+  SetFocus(infoPtr->hwndEdit);
+  SendMessageA(infoPtr->hwndEdit, EM_SETSEL, 0, -1);
+  ShowWindow(infoPtr->hwndEdit, SW_SHOW);
+
+  return infoPtr->hwndEdit;
+}
+
+
+LRESULT WINAPI
+TREEVIEW_EndEditLabelNow (HWND hwnd, BOOL bCancel)
+{
+  TREEVIEW_INFO *infoPtr    = TREEVIEW_GetInfoPtr(hwnd);
+  TREEVIEW_ITEM *editedItem = TREEVIEW_ValidItem (infoPtr, infoPtr->editItem);
+  NMTVDISPINFOA tvdi;
+  BOOL bCommit;
+  char tmpText[1024] = { '\0' };
+  int  iLength = 0;
+
+  if (!infoPtr->hwndEdit)
+     return FALSE;
+
+  tvdi.hdr.hwndFrom    = hwnd;
+  tvdi.hdr.idFrom  = GetWindowLongA(hwnd, GWL_ID);
+  tvdi.hdr.code        = TVN_ENDLABELEDITA;
+  tvdi.item.mask   = 0;
+  tvdi.item.hItem  = editedItem->hItem;
+  tvdi.item.state  = editedItem->state;
+  tvdi.item.lParam = editedItem->lParam;
+
+  if (!bCancel)
+	{
+	 iLength = GetWindowTextA(infoPtr->hwndEdit, tmpText, 1023);
+
+     if (iLength >= 1023)
     {
-      ERR(
-        "Insuficient space to retrieve new item label, new label ignored.");
+      ERR("Insuficient space to retrieve new item label.");
+    }
+
+	 tvdi.item.pszText = tmpText;
+     tvdi.item.cchTextMax  = iLength + 1;
     }
     else
     {
-      if (strcmp( tmpText, editedItem->pszText ) == 0)
-        /* Do nothing if the label has not changed */
-        bReturn = TRUE;
-      else
+  	  tvdi.item.pszText = NULL;
+      tvdi.item.cchTextMax  = 0;
+    }
+
+	  bCommit=(BOOL)SendMessageA (
+                  GetParent(hwnd),
+                 WM_NOTIFY,
+                  (WPARAM)tvdi.hdr.idFrom,
+                  (LPARAM)&tvdi);
+
+  if (!bCancel && bCommit) /* Apply the changes */
+  {
+      if (strcmp( tmpText, editedItem->pszText ) != 0)
       {
-        LPSTR tmpLabel = COMCTL32_Alloc( iLength+1 );
-  
-        if ( tmpLabel == NULL )
-          ERR(
-            "OutOfMemory, cannot allocate space for label");
+        if(NULL == COMCTL32_ReAlloc(editedItem->pszText, iLength+1 ))
+   {
+          ERR("OutOfMemory, cannot allocate space for label");
+          DestroyWindow(infoPtr->hwndEdit);
+          infoPtr->hwndEdit = 0;
+     return FALSE;
+   }
         else
         {
-          COMCTL32_Free(editedItem->pszText);
-          editedItem->pszText = tmpLabel;
+		  editedItem->cchTextMax = iLength + 1;
           lstrcpyA( editedItem->pszText, tmpText);
-          bReturn = TRUE;
         }
       }
     }
 
-		ShowWindow(infoPtr->hwndEdit, SW_HIDE);
-		EnableWindow(infoPtr->hwndEdit, FALSE);
+	ShowWindow(infoPtr->hwndEdit, SW_HIDE);
+	DestroyWindow(infoPtr->hwndEdit);
+	infoPtr->hwndEdit = 0;
     infoPtr->editItem = 0;
-  }
-
-  return bReturn;
+	return TRUE;
 }
 
 
+/***************************************************************************
+ * This is quite unusual piece of code, but that's how it's implemented in
+ * Windows.
+ */
+static LRESULT TREEVIEW_TrackMouse(HWND hwnd, POINT pt)
+{
+   INT cxDrag = GetSystemMetrics(SM_CXDRAG);
+   INT cyDrag = GetSystemMetrics(SM_CYDRAG);
+   RECT r;
+   MSG msg;
+
+   r.top    = pt.y - cyDrag;
+   r.left   = pt.x - cxDrag;
+   r.bottom = pt.y + cyDrag;
+   r.right  = pt.x + cxDrag;
+
+   SetCapture(hwnd);
+
+   while(1)
+   {
+      if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE|PM_NOYIELD))
+      {
+         if (msg.message == WM_MOUSEMOVE)
+         {
+            pt.x = (INT)LOWORD(msg.lParam);
+            pt.y = (INT)HIWORD(msg.lParam);
+            if (PtInRect(&r, pt))
+               continue;
+            else
+            {
+               ReleaseCapture();
+               return 1;
+            }
+         }
+         else if (msg.message >= WM_LBUTTONDOWN &&
+                  msg.message <= WM_RBUTTONDBLCLK)
+         {
+        if(msg.message == WM_RBUTTONUP)
+        TREEVIEW_RButtonUp (hwnd, &pt);
+        break;
+   }
+
+        DispatchMessageA( &msg );
+ }
+
+      if (GetCapture() != hwnd)
+         return 0;
+   }
+
+   ReleaseCapture();
+   return 0;
+}
+
 
 static LRESULT
 TREEVIEW_LButtonDoubleClick (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
   TREEVIEW_ITEM *wineItem;
   POINT pt;
 
@@ -2983,6 +3279,13 @@
   pt.y = (INT)HIWORD(lParam);
   SetFocus (hwnd);
 
+  if (infoPtr->Timer & TV_EDIT_TIMER_SET)
+  {
+     /* If there is pending 'edit label' event - kill it now */
+     infoPtr->editItem = 0;
+     KillTimer (hwnd, TV_EDIT_TIMER);
+  }
+
   wineItem=TREEVIEW_HitTestPoint (hwnd, pt);
   if (!wineItem) return 0;
   TRACE("item %d \n",(INT)wineItem->hItem);
@@ -2998,106 +3301,81 @@
 TREEVIEW_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
-  INT iItem;
   TVHITTESTINFO ht;
+  BOOL bTrack;
+  DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
 
-  ht.pt.x = (INT)LOWORD(lParam);
-  ht.pt.y = (INT)HIWORD(lParam);
-
-  SetFocus (hwnd);
-  iItem=TREEVIEW_HitTest (hwnd, (LPARAM) &ht);
-  TRACE("item %d \n",iItem);
 
-  if (ht.flags & TVHT_ONITEMBUTTON) {
-    TREEVIEW_Expand (hwnd, (WPARAM) TVE_TOGGLE, (LPARAM) iItem);
-  }
-  else
+  /* If Edit control is active - kill it and return.
+   * The best way to do it is to set focus to itself.
+   * Edit control subclassed procedure will automatically call
+   * EndEditLabelNow.
+   */
+  if (infoPtr->hwndEdit)
   {
-    infoPtr->uInternalStatus|=TV_LDRAG;
-  }
-  
+     SetFocus (hwnd);
   return 0;
 }
 
-static LRESULT
-TREEVIEW_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
-  INT           iItem;
-  TREEVIEW_ITEM *wineItem;
-  TVHITTESTINFO ht;
- 
   ht.pt.x = (INT)LOWORD(lParam);
   ht.pt.y = (INT)HIWORD(lParam);
  
-  TRACE("\n");
+  TREEVIEW_HitTest (hwnd, (LPARAM) &ht);
+  TRACE("item %d \n", (INT)ht.hItem);
+ 
+  bTrack = (ht.flags & TVHT_ONITEM) && !(dwStyle & TVS_DISABLEDRAGDROP);
 
-  /* Return true to cancel default behaviour */
+  /* Send NM_CLICK right away */
+  if (!bTrack)
   if ( TREEVIEW_SendSimpleNotify (hwnd, NM_CLICK) )
-    return 0;
+        goto setfocus;
 
-  /* Get the item */
-  iItem = TREEVIEW_HitTest (hwnd, (LPARAM) &ht);
-  TRACE ("%d\n",iItem);
-  if (!iItem) 
+  if (ht.flags & TVHT_ONITEMBUTTON)
+  {
+     TREEVIEW_Expand (hwnd, (WPARAM) TVE_TOGGLE, (LPARAM) ht.hItem);
+     goto setfocus;
+  }
+  else if (bTrack)
+  {
+     if (TREEVIEW_TrackMouse(hwnd, ht.pt))
+     {
+        TREEVIEW_SendTreeviewDnDNotify (hwnd, TVN_BEGINDRAGA, ht.hItem, ht.pt);
+        infoPtr->dropItem = ht.hItem;
     return 0;
+     }
+  }
 
-  wineItem = TREEVIEW_ValidItem(infoPtr, (HTREEITEM)iItem);
- 
-  infoPtr->uInternalStatus &= ~(TV_LDRAG | TV_LDRAGGING);
+  if(TREEVIEW_SendSimpleNotify (hwnd, NM_CLICK))
+     goto setfocus;
 
   /* 
    * If the style allow editing and the node is already selected 
    * and the click occured on the item label...
    */
-  if ( ( GetWindowLongA( hwnd, GWL_STYLE) & TVS_EDITLABELS ) && 
-       ( wineItem->state & TVIS_SELECTED ) &&
-       ( ht.flags & TVHT_ONITEMLABEL ))
-  {
-    if ( infoPtr->editItem == 0 ) /* If we are not curently editing */
-    {
-  		if ( TREEVIEW_SendDispInfoNotify(  /* Return true to cancel edition */
-              hwnd, 
-              wineItem, 
-              TVN_BEGINLABELEDITA, 
-              0))
+  if ( ( dwStyle & TVS_EDITLABELS ) &&
+       ( ht.flags & TVHT_ONITEMLABEL ) &&
+       ( infoPtr->selectedItem == ht.hItem ) )
       {
-        return 0; 
-      }
+       if (infoPtr->Timer & TV_EDIT_TIMER_SET)
+          KillTimer (hwnd, TV_EDIT_TIMER);
   
-  		TRACE("Edit started for %s.\n", wineItem->pszText);
-  		infoPtr->editItem = wineItem->hItem;
-  
-  		SetWindowPos ( 
-        infoPtr->hwndEdit, 
-        HWND_TOP, 
-        wineItem->text.left - 2, 
-        wineItem->text.top  - 1,
-        wineItem->text.right  - wineItem->text.left + 20 ,
-        wineItem->text.bottom - wineItem->text.top  + 3,
-        SWP_DRAWFRAME );
-  
-  		SetWindowTextA( infoPtr->hwndEdit, wineItem->pszText );
-      SendMessageA  ( infoPtr->hwndEdit, EM_SETSEL, 0, -1 );
-  		SetFocus      ( infoPtr->hwndEdit); 
-      ShowWindow    ( infoPtr->hwndEdit, SW_SHOW); 
-    }
-  }
-  else if ( infoPtr->editItem != 0 ) /* If we are curently editing */
-  {
-    TREEVIEW_EndEditLabelNow(hwnd, (WPARAM)FALSE, 0);
+       infoPtr->editItem = ht.hItem;
+       SetTimer (hwnd, TV_EDIT_TIMER, GetDoubleClickTime(), 0);
+       infoPtr->Timer|=TV_EDIT_TIMER_SET;
   }
   else if ( ht.flags & (TVHT_ONITEMLABEL | TVHT_ONITEMICON))
   {
-    TREEVIEW_DoSelectItem ( hwnd, TVGN_CARET, (HTREEITEM)iItem, TVC_BYMOUSE);
+     TREEVIEW_DoSelectItem ( hwnd, TVGN_CARET, ht.hItem, TVC_BYMOUSE);
   }
+  else if (ht.flags & TVHT_ONITEMSTATEICON)
+  {
+     if (dwStyle & TVS_CHECKBOXES)  /* TVS_CHECKBOXES requires _us_ */
+     {                              /* to toggle the current state  */
+        int state;
+        TREEVIEW_ITEM *wineItem;
 
-  if (ht.flags & TVHT_ONITEMSTATEICON) {
-	DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
-
+        wineItem = TREEVIEW_ValidItem(infoPtr, ht.hItem);
 	
-	if (dwStyle & TVS_CHECKBOXES) {      /* TVS_CHECKBOXES requires _us_ */
-			int state;					 /* to toggle the current state */
 			state=1-(wineItem->state>>12);
 			TRACE ("state:%x\n", state);
 			wineItem->state&= ~TVIS_STATEIMAGEMASK;
@@ -3106,6 +3384,9 @@
 			TREEVIEW_QueueRefresh (hwnd);
 		}
   }
+  
+setfocus:
+  SetFocus (hwnd);
   return 0;
 }
 
@@ -3114,57 +3395,51 @@
 TREEVIEW_RButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
+ TVHITTESTINFO ht;
 
- TRACE("\n");
- infoPtr->uInternalStatus|=TV_RDRAG;
- return 0;
-}
+ if (infoPtr->hwndEdit)
+ {
+   SetFocus(hwnd);
+      return 0;
+   }
 
-static LRESULT
-TREEVIEW_RButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
- TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
+   ht.pt.x = (INT)LOWORD(lParam);
+   ht.pt.y = (INT)HIWORD(lParam);
+
+   TREEVIEW_HitTest (hwnd, (LPARAM) &ht);
+
+   if (TREEVIEW_TrackMouse(hwnd, ht.pt))
+	{
+      if (ht.hItem)
+       {
+          TREEVIEW_SendTreeviewDnDNotify (hwnd, TVN_BEGINRDRAGA, ht.hItem, ht.pt);
+         infoPtr->dropItem = ht.hItem;
+      }
+   }
+   else
+   {
+      SetFocus(hwnd);
+      TREEVIEW_SendSimpleNotify (hwnd, NM_RCLICK);
+   }
 
- TRACE("\n");
- if (TREEVIEW_SendSimpleNotify (hwnd, NM_RCLICK)) return 0;
- infoPtr->uInternalStatus&= ~(TV_RDRAG | TV_RDRAGGING);
  return 0;
 }
 
-
 static LRESULT
-TREEVIEW_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
+TREEVIEW_RButtonUp (HWND hwnd, LPPOINT pPt)
 {
- TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
- TREEVIEW_ITEM *hotItem;
  POINT pt;
 
- pt.x=(INT) LOWORD (lParam);
- pt.y=(INT) HIWORD (lParam);
- hotItem=TREEVIEW_HitTestPoint (hwnd, pt);
- if (!hotItem) return 0;
- infoPtr->focusItem=hotItem->hItem;
-
- if ( GetWindowLongA( hwnd, GWL_STYLE) & TVS_DISABLEDRAGDROP) return 0;
-
- if (infoPtr->uInternalStatus & TV_LDRAG) {
-	TREEVIEW_SendTreeviewDnDNotify (hwnd, TVN_BEGINDRAGA, hotItem->hItem, pt);
-	infoPtr->uInternalStatus &= ~TV_LDRAG;
-	infoPtr->uInternalStatus |= TV_LDRAGGING;
-	infoPtr->dropItem=hotItem->hItem;
-	return 0;
- }
+ pt.x = pPt->x;
+ pt.y = pPt->y;
 
- if (infoPtr->uInternalStatus & TV_RDRAG) {
-	TREEVIEW_SendTreeviewDnDNotify (hwnd, TVN_BEGINRDRAGA, hotItem->hItem, pt);
-	infoPtr->uInternalStatus &= ~TV_RDRAG;
-	infoPtr->uInternalStatus |= TV_RDRAGGING;
-	infoPtr->dropItem=hotItem->hItem;
-	return 0;
+    /* Change to screen coordinate for WM_CONTEXTMENU */
+    ClientToScreen(hwnd, &pt);
+
+    /* Send the WM_CONTEXTMENU on a right click */
+  SendMessageA( hwnd, WM_CONTEXTMENU, (WPARAM) hwnd, MAKELPARAM(pt.x, pt.y));
+  return 0;
  }
- 
- return 0;
-}
 
 
 static LRESULT
@@ -3245,7 +3520,7 @@
 	(INT)newSelect, 
 	action, 
 	cause,
-	wineItem->state);
+	wineItem ? wineItem->state : 0);
 
   if ( (wineItem) && (wineItem->parent))
   {
@@ -3313,14 +3588,13 @@
  
  TREEVIEW_QueueRefresh (hwnd);
 
- TRACE("Leaving state %d\n", wineItem->state);
+ TRACE("Leaving state %d\n", wineItem ? wineItem->state : 0);
  return TRUE;
 }
 
 /* FIXME: handle NM_KILLFocus etc */
 static LRESULT
 TREEVIEW_SelectItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
-
 {
  return TREEVIEW_DoSelectItem (hwnd, wParam, (HTREEITEM) lParam, TVC_UNKNOWN);
 }
@@ -3357,6 +3631,8 @@
 
  GetObjectA (infoPtr->hFont, sizeof (LOGFONTA), &logFont);
  logFont.lfWeight=FW_BOLD;
+
+ DeleteObject(infoPtr->hBoldFont);
  infoPtr->hBoldFont = CreateFontIndirectA (&logFont);
 
  hdc = GetDC (0);
@@ -3386,6 +3662,9 @@
   TRACE("wp %x, lp %lx\n", wParam, lParam);
   if (!infoPtr->uInternalStatus & TV_VSCROLL) return FALSE;
 
+  if(infoPtr->hwndEdit)
+     SetFocus(hwnd);
+
   switch (LOWORD (wParam)) {
 	case SB_LINEUP: 
 			if (!infoPtr->cy) return FALSE;
@@ -3431,6 +3710,9 @@
 	
   if (!infoPtr->uInternalStatus & TV_HSCROLL) return FALSE;
 
+  if(infoPtr->hwndEdit)
+     SetFocus(hwnd);
+
   switch (LOWORD (wParam)) {
 	case SB_LINEUP: 
 			if (!infoPtr->cx) return FALSE;
@@ -3475,6 +3757,8 @@
  INT           scrollNeeds     = -1;
  INT           cyChangeNeeds   = -1;
  INT           prevSelect      = (INT)infoPtr->selectedItem;
+ INT           nNumItemsToScroll = -1;
+ INT           i; 
 
  TREEVIEW_ITEM *prevItem       = 
     (prevSelect != 0 ) ? 
@@ -3490,8 +3774,7 @@
 
  switch (wParam) {
 	case VK_UP: 
-		newItem=TREEVIEW_GetPrevListItem (infoPtr, prevItem);
-
+		newItem=TREEVIEW_GetPrevListItem (hwnd, infoPtr, prevItem);
 		if (!newItem) 
 			newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
 
@@ -3502,7 +3785,7 @@
 		break;
 
 	case VK_DOWN: 
-		newItem=TREEVIEW_GetNextListItem (infoPtr, prevItem);
+		newItem=TREEVIEW_GetNextListItem (hwnd, infoPtr, prevItem);
 
 		if (!newItem) 
       newItem=prevItem;
@@ -3522,7 +3805,7 @@
 
 	case VK_END:
 		newItem       = &infoPtr->items[(INT)infoPtr->TopRootItem];
-		newItem       = TREEVIEW_GetLastListItem (infoPtr, newItem);
+		newItem       = TREEVIEW_GetLastListItem (hwnd, infoPtr, newItem);
     hNewSelection = newItem->hItem;
 
     if (! newItem->visible)
@@ -3531,7 +3814,8 @@
 		break;
 
 	case VK_LEFT:
-    if ( (prevItem->cChildren > 0) && (prevItem->state & TVIS_EXPANDED) )
+	if ( (prevItem->state & TVIS_EXPANDED) &&
+         TREEVIEW_HasChildren(hwnd, prevItem))
     {
       TREEVIEW_Expand(hwnd, TVE_COLLAPSE, prevSelect );
     }
@@ -3539,17 +3823,30 @@
     {
       newItem = (& infoPtr->items[(INT)prevItem->parent]);
       if (! newItem->visible) 
+      {
         /* FIXME find a way to make this item the first visible... */
-        newItem = NULL; 
+	  /* newItem = NULL; */
 
+          /* Start of horrible hack, a quick and dirty get it 
+           * working quickly fix.  It is not elegant, but it works.
+           * Basically, since the tree items are sequentially
+           * numbered, just scroll up the number of lines equal
+           * to (current tree item index - parent index).
+           * I added 2(plus one more scroll call at bottom of 
+           * the function) like in VK_PRIOR/VK_NEXT so we don't lose 
+           * the selected item  from the display area. 
+           */
+          nNumItemsToScroll = prevSelect - (INT)prevItem->parent;
+          scrollNeeds = SB_LINEUP;
+          for (i=0; i < nNumItemsToScroll +2; i++)
+            TREEVIEW_VScroll(hwnd, scrollNeeds, 0);
+      }
       hNewSelection = newItem->hItem;
     }
-
     break;
 
 	case VK_RIGHT:
-    if ( ( prevItem->cChildren > 0)  || 
-         ( prevItem->cChildren == I_CHILDRENCALLBACK))
+	if ( TREEVIEW_HasChildren(hwnd, prevItem) )
     {
       if (! (prevItem->state & TVIS_EXPANDED))
         TREEVIEW_Expand(hwnd, TVE_EXPAND, prevSelect );
@@ -3575,6 +3872,7 @@
   case VK_PRIOR:
     
 		newItem=TREEVIEW_GetListItem(
+			  hwnd,
               infoPtr, 
               prevItem,
               -1*(TREEVIEW_GetVisibleCount(hwnd,0,0)-3));
@@ -3590,6 +3888,7 @@
 
   case VK_NEXT:
 		newItem=TREEVIEW_GetListItem(
+			  hwnd,
               infoPtr, 
               prevItem,
               TREEVIEW_GetVisibleCount(hwnd,0,0)-3);
@@ -3669,7 +3968,6 @@
   return uOldScrollTime;
 }
 
-
 static LRESULT WINAPI
 TREEVIEW_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
@@ -3732,7 +4030,7 @@
       		return 0;
 
     	case TVM_EDITLABELA:
-      		FIXME("Unimplemented msg TVM_EDITLABELA \n");
+			return TREEVIEW_EditLabelA(hwnd, (HTREEITEM)lParam);
       		return 0;
 
     	case TVM_EDITLABELW:
@@ -3762,7 +4060,7 @@
       		return TREEVIEW_SortChildrenCB(hwnd, wParam, lParam);
   
     	case TVM_ENDEDITLABELNOW:
-      		return TREEVIEW_EndEditLabelNow (hwnd, wParam, lParam);
+      		return TREEVIEW_EndEditLabelNow (hwnd, (BOOL) wParam);
   
     	case TVM_GETISEARCHSTRINGA:
       		FIXME("Unimplemented msg TVM_GETISEARCHSTRINGA\n");
@@ -3863,21 +4161,12 @@
 		case WM_LBUTTONDOWN:
 			return TREEVIEW_LButtonDown (hwnd, wParam, lParam);
 
-		case WM_LBUTTONUP:
-			return TREEVIEW_LButtonUp (hwnd, wParam, lParam);
-  
 		case WM_LBUTTONDBLCLK:
 			return TREEVIEW_LButtonDoubleClick (hwnd, wParam, lParam);
   
 		case WM_RBUTTONDOWN:
 			return TREEVIEW_RButtonDown (hwnd, wParam, lParam);
 
-		case WM_RBUTTONUP:
-			return TREEVIEW_RButtonUp (hwnd, wParam, lParam);
-
-		case WM_MOUSEMOVE:
-			return TREEVIEW_MouseMove (hwnd, wParam, lParam);
-  
 		case WM_STYLECHANGED: 
 			return TREEVIEW_StyleChanged (hwnd, wParam, lParam);
 
@@ -3934,6 +4223,3 @@
 {
     UnregisterClassA (WC_TREEVIEWA, (HINSTANCE)NULL);
 }
-
-
-


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic