Implementation of TVM_SORTCHILDRENCB.
Implementation of TVI_SORT insertion.
Fix display problem when TVIF_IMAGE|TVIF_SELECTEDIMAGE were not set.
Fix problems related to TVIS_EXPANDEDONCE.

diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c
index 3ae8227..2144ea7 100644
--- a/dlls/comctl32/treeview.c
+++ b/dlls/comctl32/treeview.c
@@ -190,6 +190,7 @@
   if ((tvItem->firstChild) && (tvItem->state & TVIS_EXPANDED)) 
 		return (& infoPtr->items[(INT)tvItem->firstChild]);
 
+
   /*
    * try to get the sibling
    */
@@ -493,6 +494,8 @@
 /* cdmode: custom draw mode as received from app. in first NMCUSTOMDRAW 
            notification */
 
+#define TREEVIEW_LEFT_MARGIN 8
+
 static void
 TREEVIEW_DrawItem (HWND hwnd, HDC hdc, TREEVIEW_ITEM *wineItem)
 
@@ -528,9 +531,15 @@
   /* 
    * Set drawing starting points 
    */
-  r      = wineItem->rect;        /* this item rectangle */
-  center = (r.top+r.bottom)/2;    /* this item vertical center */
-  xpos   = r.left + 8;            /* horizontal starting point */
+  r      = wineItem->rect;               /* this item rectangle */
+  center = (r.top+r.bottom)/2;           /* this item vertical center */
+  xpos   = r.left + TREEVIEW_LEFT_MARGIN;/* horizontal starting point */
+
+  TRACE(treeview, "Left %3d, Top %3d, Right %3d, Bottom %3d\n", 
+    r.left, 
+    r.top, 
+    r.right, 
+    r.bottom);
 
   /* 
    * Display the tree hierarchy 
@@ -577,9 +586,7 @@
       else
       {
         points[2].x = points[1].x = 8 + (20*wineItem->iLevel); 
-        points[2].y = ((upNode->cChildren == 0) ? 
-                         upRect.top :
-                         upRect.bottom-3);    
+        points[2].y = ((upNode->cChildren == 0) ? upRect.top : upRect.bottom-1);    
         points[1].y = points[0].y = center;
         points[0].x = points[1].x + 10; 
       }
@@ -623,19 +630,28 @@
   /* 
    * Display the (+/-) signs
    */
-  wineItem->expandBox.left   = 0; /* Initialize the expandBox */
-  wineItem->expandBox.top    = 0;
-  wineItem->expandBox.right  = 0;
-  wineItem->expandBox.bottom = 0;
+  if (wineItem->iLevel != 0)/*  update position only for non root node */
+    xpos+=(5*wineItem->iLevel);
+
   if (( GetWindowLongA( hwnd, GWL_STYLE) & TVS_HASBUTTONS) && 
       ( GetWindowLongA( hwnd, GWL_STYLE) & TVS_HASLINES))
   {
-	  if (wineItem->cChildren)
+	  if ( (wineItem->cChildren) ||
+	       (wineItem->cChildren == I_CHILDRENCALLBACK))
     {
-      if (wineItem->parent)
-        xpos+=5;  /* update position only for nodes that have a parent */
-  
-  		Rectangle (hdc, xpos-4, center-4, xpos+5, center+5);
+      /* Setup expand box coordinate to facilitate the LMBClick handling */
+      wineItem->expandBox.left   = xpos-4;
+      wineItem->expandBox.top    = center-4;
+      wineItem->expandBox.right  = xpos+5;
+      wineItem->expandBox.bottom = center+5;
+
+  		Rectangle (
+        hdc, 
+        wineItem->expandBox.left, 
+        wineItem->expandBox.top , 
+        wineItem->expandBox.right, 
+        wineItem->expandBox.bottom);
+
   		MoveToEx (hdc, xpos-2, center, NULL);
   		LineTo   (hdc, xpos+3, center);
   
@@ -643,26 +659,16 @@
   			MoveToEx (hdc, xpos,   center-2, NULL);
   			LineTo   (hdc, xpos,   center+3);
   	  }
-  
-      /* Setup expand box coordinate to facilitate the LMBClick handling */
-      wineItem->expandBox.left   = xpos-4;
-      wineItem->expandBox.top    = center-4;
-      wineItem->expandBox.right  = xpos+5;
-      wineItem->expandBox.bottom = center+5;
-    }
-    else
-    {
-      xpos+=(5*wineItem->iLevel);
     }
   }
 
   /* 
    * Display the image assiciated with this item
    */
+  xpos += 13; /* update position */
   if (wineItem->mask & (TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
     INT        imageIndex;
     HIMAGELIST *himlp = NULL;
-    xpos             += 13; /* update position */
 
 	  if (infoPtr->himlNormal) 
       himlp=&infoPtr->himlNormal; /* get the image list */
@@ -712,7 +718,9 @@
     }
   }
 
-
+  /* 
+   * Display the text assiciated with this item
+   */
   r.left=xpos;
   if ((wineItem->mask & TVIF_TEXT) && (wineItem->pszText)) 
   {
@@ -1230,7 +1238,242 @@
  return (LRESULT) infoPtr->uNumItems;
 }
 
+/***************************************************************************
+ * This method does the chaining of the insertion of a treeview item 
+ * before an item.
+ */
+static void TREEVIEW_InsertBefore(
+    TREEVIEW_INFO *infoPtr,
+    TREEVIEW_ITEM *newItem, 
+    TREEVIEW_ITEM *sibling,
+    TREEVIEW_ITEM *parent)
+{
+  HTREEITEM     siblingHandle   = 0;
+  HTREEITEM     upSiblingHandle = 0;
+  TREEVIEW_ITEM *upSibling      = NULL;
 
+  if (newItem == NULL)
+    ERR(treeview, "NULL newItem, impossible condition\n");
+
+  if (parent == NULL)
+    ERR(treeview, "NULL parent, impossible condition\n");
+
+  if (sibling != NULL) /* Insert before this sibling for this parent */
+  { 
+    /* Store the new item sibling up sibling and sibling tem handle */
+    siblingHandle   = sibling->hItem;
+    upSiblingHandle = sibling->upsibling;
+    /* As well as a pointer to the upsibling sibling object */
+    if ( (INT)sibling->upsibling != 0 )
+      upSibling = &infoPtr->items[(INT)sibling->upsibling];
+  
+    /* Adjust the sibling pointer */
+    sibling->upsibling = newItem->hItem;
+    
+    /* Adjust the new item pointers */
+    newItem->upsibling = upSiblingHandle;
+    newItem->sibling   = siblingHandle;
+    
+    /* Adjust the up sibling pointer */
+    if ( upSibling != NULL )        
+      upSibling->sibling = newItem->hItem;
+    else
+      /* this item is the first child of this parent, adjust parent pointers */
+      parent->firstChild = newItem->hItem;
+  }
+  else /* Insert as first child of this parent */
+    parent->firstChild = newItem->hItem;
+}
+
+/***************************************************************************
+ * This method does the chaining of the insertion of a treeview item 
+ * after an item.
+ */
+static void TREEVIEW_InsertAfter(
+    TREEVIEW_INFO *infoPtr,
+    TREEVIEW_ITEM *newItem, 
+    TREEVIEW_ITEM *upSibling,
+    TREEVIEW_ITEM *parent)
+{
+  HTREEITEM     upSiblingHandle = 0;
+  HTREEITEM     siblingHandle   = 0;
+  TREEVIEW_ITEM *sibling        = NULL;
+
+  if (newItem == NULL)
+    ERR(treeview, "NULL newItem, impossible condition\n");
+
+  if (parent == NULL)
+    ERR(treeview, "NULL parent, impossible condition\n");
+
+  if (upSibling != NULL) /* Insert after this upsibling for this parent */
+  { 
+    /* Store the new item up sibling and sibling item handle */
+    upSiblingHandle = upSibling->hItem;
+    siblingHandle   = upSibling->sibling;
+    /* As well as a pointer to the upsibling sibling object */
+    if ( (INT)upSibling->sibling != 0 )
+      sibling = &infoPtr->items[(INT)upSibling->sibling];
+  
+    /* Adjust the up sibling pointer */
+    upSibling->sibling = newItem->hItem;
+    
+    /* Adjust the new item pointers */
+    newItem->upsibling = upSiblingHandle;
+    newItem->sibling   = siblingHandle;
+    
+    /* Adjust the sibling pointer */
+    if ( sibling != NULL )        
+      sibling->upsibling = newItem->hItem; 
+    /*
+    else 
+      newItem is the last of the level, nothing else to do 
+    */
+  }
+  else /* Insert as first child of this parent */
+    parent->firstChild = newItem->hItem;
+}
+
+/***************************************************************************
+ * This method is used to abstract the comparaison of two items during 
+ * the insertion or a request for a sort.
+ */
+static INT TREEVIEW_CompareItems(
+  TREEVIEW_INFO *infoPtr, 
+  TREEVIEW_ITEM *first,   
+  TREEVIEW_ITEM *second)
+{
+
+  if ((first == NULL) || (second == NULL))
+    ERR( treeview, 
+      "Invalid parameters passed infoPtr=%p, first=%p, second=%p.\n",
+      infoPtr,
+      first,
+      second);
+
+  if (infoPtr->pCallBackSort == NULL)
+  {
+    /* Simply sort based on the label comparaison */
+    return strcmp(first->pszText, second->pszText);
+  }
+  else
+  {
+    /* use the callback method setup in tree view struct */
+    if( (first->lParam == 0) || (second->lParam == 0))
+      ERR( treeview, "Invalid lParam, first=%08lx, second=%08lx.\n", 
+        first->lParam, 
+        second->lParam);
+
+    return (infoPtr->pCallBackSort->lpfnCompare)(
+              first->lParam,
+              second->lParam, 
+              infoPtr->pCallBackSort->lParam);
+  }
+}
+
+/***************************************************************************
+ * Forward the DPA local callback to the treeview owner callback
+ */
+static INT TREEVIEW_CallBackCompare( 
+  LPVOID first, 
+  LPVOID second, 
+  LPARAM tvInfoPtr)
+{
+  /* Forward the call to the client define callback */
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr((HWND)tvInfoPtr);
+  return (infoPtr->pCallBackSort->lpfnCompare)(
+    ((TREEVIEW_ITEM*)first)->lParam,
+    ((TREEVIEW_ITEM*)second)->lParam,
+    infoPtr->pCallBackSort->lParam);
+}
+
+/***************************************************************************
+ * Setup the treeview structure with regards of the sort method
+ * and sort the children of the TV item specified in lParam
+ */
+LRESULT WINAPI TREEVIEW_SortChildrenCB(
+  HWND   hwnd, 
+  WPARAM wParam, 
+  LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
+  TREEVIEW_ITEM *sortMe  = NULL; /* Node for which we sort the children */
+
+  /* Obtain the TVSORTBC struct */
+  infoPtr->pCallBackSort = (LPTVSORTCB)lParam;
+
+  /* Obtain the parent node to sort */  
+  sortMe = &infoPtr->items[ (INT)infoPtr->pCallBackSort->hParent ];
+
+  /* Make sure there is something to sort */
+  if ( sortMe->cChildren > 1 ) 
+  {
+    /* pointer organization */
+    HDPA          sortList   = DPA_Create(sortMe->cChildren);
+    HTREEITEM     itemHandle = sortMe->firstChild;
+    TREEVIEW_ITEM *itemPtr   = & infoPtr->items[ (INT)itemHandle ];
+
+    /* TREEVIEW_ITEM rechaining */
+    INT  count     = 0;
+    VOID *item     = 0;
+    VOID *nextItem = 0;
+    VOID *prevItem = 0;
+
+    /* Build the list of item to sort */
+    do 
+    {
+      DPA_InsertPtr(
+        sortList,              /* the list */
+        sortMe->cChildren+1,   /* force the insertion to be an append */
+        itemPtr);              /* the ptr to store */   
+
+      /* Get the next sibling */
+      itemHandle = itemPtr->sibling;
+      itemPtr    = & infoPtr->items[ (INT)itemHandle ];
+    } while ( itemHandle != NULL );
+
+    /* let DPA perform the sort activity */
+    DPA_Sort(
+      sortList,                  /* what  */ 
+      TREEVIEW_CallBackCompare,  /* how   */
+      hwnd);                     /* owner */
+
+    /* 
+     * Reorganized TREEVIEW_ITEM structures. 
+     * Note that we know we have at least two elements.
+     */
+
+    /* Get the first item and get ready to start... */
+    item = DPA_GetPtr(sortList, count++);    
+    while ( (nextItem = DPA_GetPtr(sortList, count++)) != NULL )
+    {
+      /* link the two current item toghether */
+      ((TREEVIEW_ITEM*)item)->sibling       = ((TREEVIEW_ITEM*)nextItem)->hItem;
+      ((TREEVIEW_ITEM*)nextItem)->upsibling = ((TREEVIEW_ITEM*)item)->hItem;
+
+      if (prevItem == NULL) /* this is the first item, update the parent */
+      {
+        sortMe->firstChild                = ((TREEVIEW_ITEM*)item)->hItem;
+        ((TREEVIEW_ITEM*)item)->upsibling = NULL;
+      }
+      else                  /* fix the back chaining */
+      {
+        ((TREEVIEW_ITEM*)item)->upsibling = ((TREEVIEW_ITEM*)prevItem)->hItem;
+      }
+
+      /* get ready for the next one */
+      prevItem = item; 
+      item     = nextItem;
+    }
+
+    /* the last item is pointed to by item and never has a sibling */
+    ((TREEVIEW_ITEM*)item)->sibling = NULL; 
+
+    DPA_Destroy(sortList);
+
+    return TRUE;
+  }
+  return FALSE;
+}
 
 
 /* the method used below isn't the most memory-friendly, but it avoids 
@@ -1247,7 +1490,8 @@
   TVITEMEXA 	*tvItem;
   TREEVIEW_ITEM *wineItem, *parentItem, *prevsib, *sibItem;
   INT		iItem,listItems,i,len;
-  
+ 
+  /* Item to insert */
   ptdi = (LPTVINSERTSTRUCTA) lParam;
 
 	/* check if memory is available */
@@ -1259,6 +1503,9 @@
 	infoPtr->TopRootItem=(HTREEITEM)1;
    }
 
+  /* 
+   * Reallocate contiguous space for items 
+   */
   if (infoPtr->uNumItems == (infoPtr->uNumPtrsAlloced-1) ) {
    	TREEVIEW_ITEM *oldItems = infoPtr->items;
 	INT *oldfreeList = infoPtr->freeList;
@@ -1276,47 +1523,90 @@
     COMCTL32_Free (oldfreeList);  
    }
 
+  /* 
+   * Reset infoPtr structure with new stat according to current TV picture
+   */
   iItem=0;
   infoPtr->uNumItems++;
-
   if ((INT)infoPtr->uMaxHandle==(infoPtr->uNumItems-1))  { 
   	iItem=infoPtr->uNumItems;
   	infoPtr->uMaxHandle = (HTREEITEM)((INT)infoPtr->uMaxHandle + 1);
   } else {					 /* check freelist */
-	for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) {
-		if (infoPtr->freeList[i]) {
-			iItem=ffs (infoPtr->freeList[i])-1;
-			tv_clear_bit(iItem,&infoPtr->freeList[i]);
- 			iItem+=i<<5;
-			break;
-		}
-  	 } 
+  	for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) {
+  		if (infoPtr->freeList[i]) {
+  			iItem=ffs (infoPtr->freeList[i])-1;
+  			tv_clear_bit(iItem,&infoPtr->freeList[i]);
+   			iItem+=i<<5;
+  			break;
+  		}
+    } 
   }
- 
- for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) 
-	TRACE (treeview,"%8x\n",infoPtr->freeList[i]);
+
+  /* little performace enhancement... */  
+  if (TRACE_ON(treeview)) { 
+    for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) 
+	    TRACE (treeview,"%8x\n",infoPtr->freeList[i]);
+  }
 
   if (!iItem) ERR (treeview, "Argh -- can't find free item.\n");
-  
+
+  /* 
+   * Find the parent item of the new item 
+   */  
   tvItem= & ptdi->DUMMYUNIONNAME.itemex;
   wineItem=& infoPtr->items[iItem];
 
   if ((ptdi->hParent==TVI_ROOT) || (ptdi->hParent==0)) {
-	parentItem=NULL;
-	wineItem->parent=0; 
-	sibItem=&infoPtr->items [(INT)infoPtr->TopRootItem];
-	listItems=infoPtr->uNumItems;
+    parentItem       = NULL;
+    wineItem->parent = 0; 
+    sibItem          = &infoPtr->items [(INT)infoPtr->TopRootItem];
+    listItems        = infoPtr->uNumItems;
   }
   else  {
-	parentItem= &infoPtr->items[(INT)ptdi->hParent];
-	if (!parentItem->firstChild) 
-		parentItem->firstChild=(HTREEITEM)iItem;
-	wineItem->parent=ptdi->hParent;
-	sibItem=&infoPtr->items [(INT)parentItem->firstChild];
-	parentItem->cChildren++;
-	listItems=parentItem->cChildren;
+  	parentItem = &infoPtr->items[(INT)ptdi->hParent];
+  
+    /* Do the insertion here it if it's the only item of this parent */
+  	if (!parentItem->firstChild) 
+  		parentItem->firstChild=(HTREEITEM)iItem;
+  
+  	wineItem->parent = ptdi->hParent;
+  	sibItem          = &infoPtr->items [(INT)parentItem->firstChild];
+  	parentItem->cChildren++;
+  	listItems        = parentItem->cChildren;
   }
 
+  
+  /* NOTE: I am moving some setup of the wineItem object that was initialy 
+   *       done at the end of the function since some of the values are 
+   *       required by the Callback sorting 
+   */
+
+  if (tvItem->mask & TVIF_TEXT) 
+  {
+    /*
+     * Setup the item text stuff here since it's required by the Sort method
+     * when the insertion are ordered
+     */
+    if (tvItem->pszText!=LPSTR_TEXTCALLBACKA) 
+    {
+      TRACE (treeview,"(%p,%s)\n", &tvItem->pszText, tvItem->pszText); 
+      len = lstrlenA (tvItem->pszText)+1;
+      wineItem->pszText= COMCTL32_Alloc (len+1);
+      lstrcpyA (wineItem->pszText, tvItem->pszText);
+      wineItem->cchTextMax=len;
+    }
+    else 
+    {
+      TRACE (treeview,"LPSTR_TEXTCALLBACK\n");
+      wineItem->pszText = LPSTR_TEXTCALLBACKA;
+      wineItem->cchTextMax = 0;
+    }
+  }
+
+  if (tvItem->mask & TVIF_PARAM) 
+    wineItem->lParam=tvItem->lParam;
+
+
   wineItem->upsibling=0;  /* needed in case we're the first item in a list */ 
   wineItem->sibling=0;     
   wineItem->firstChild=0;
@@ -1324,6 +1614,7 @@
 
   if (listItems>1) {
      prevsib=NULL;
+
      switch ((INT)ptdi->hInsertAfter) {
 		case TVI_FIRST: 
 			if (wineItem->parent) {
@@ -1335,6 +1626,65 @@
 			}
 			sibItem->upsibling=(HTREEITEM)iItem;
 			break;
+
+		case 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        = 
+          &infoPtr->items[(INT)parentItem->firstChild];
+  
+        TREEVIEW_ITEM *previousChild = NULL;
+        BOOL bItemInserted           = FALSE;
+  
+        /* Iterate the parent children to see where we fit in */
+        while ( aChild != NULL )
+        {
+          INT comp = strcmp(wineItem->pszText, aChild->pszText);
+          if ( comp < 0 )  /* we are smaller than the current one */
+          {
+            TREEVIEW_InsertBefore(infoPtr, wineItem, aChild, parentItem);
+            bItemInserted = TRUE;
+            break;
+          }
+          else if ( comp > 0 )  /* we are bigger than the current one */
+          {
+            previousChild = aChild;
+            aChild = (aChild->sibling == 0)  /* This will help us to exit   */
+                        ? NULL               /* if there is no more sibling */
+                        : &infoPtr->items[(INT)aChild->sibling];
+  
+            /* Look at the next item */
+            continue;
+          }
+          else if ( comp == 0 )
+          {
+            /* 
+             * An item with this name is already existing, therefore,  
+             * we add after the one we found 
+             */
+            TREEVIEW_InsertAfter(infoPtr, wineItem, aChild, parentItem);
+            bItemInserted = TRUE;
+            break;
+          }
+        }
+      
+        /* 
+         * we reach the end of the child list and the item as not
+         * yet been inserted, therefore, insert it after the last child.
+         */
+        if ( (! bItemInserted ) && (aChild == NULL) )
+          TREEVIEW_InsertAfter(infoPtr, wineItem, previousChild, parentItem);
+  
+        break;
+      }
+
+
 		case TVI_LAST:  
 			if (sibItem==wineItem) break;
 			while (sibItem->sibling) {
@@ -1344,9 +1694,6 @@
 			sibItem->sibling=(HTREEITEM)iItem;
 			wineItem->upsibling=sibItem->hItem;
 			break;
-		case TVI_SORT:  
-			FIXME (treeview, "Sorted insert not implemented yet\n");
-			break;
 		default:
 			while ((sibItem->sibling) && (sibItem->hItem!=ptdi->hInsertAfter))
 				{
@@ -1384,6 +1731,10 @@
 			FIXME (treeview," I_CHILDRENCALLBACK not supported\n");
 	}
 
+  wineItem->expandBox.left   = 0; /* Initialize the expandBox */
+  wineItem->expandBox.top    = 0;
+  wineItem->expandBox.right  = 0;
+  wineItem->expandBox.bottom = 0;
 
    if (tvItem->mask & TVIF_IMAGE) 
 	wineItem->iImage=tvItem->iImage;
@@ -1394,9 +1745,6 @@
    if (tvItem->mask & TVIF_INTEGRAL) 
    		wineItem->iIntegral=tvItem->iIntegral;   
 
-   if (tvItem->mask & TVIF_PARAM) 
-	wineItem->lParam=tvItem->lParam;
-
    if (tvItem->mask & TVIF_SELECTEDIMAGE) 
 	wineItem->iSelectedImage=tvItem->iSelectedImage;
 
@@ -1405,20 +1753,6 @@
 	wineItem->stateMask=tvItem->stateMask;
    }
 
-   if (tvItem->mask & TVIF_TEXT) {
-	if (tvItem->pszText!=LPSTR_TEXTCALLBACKA) {
-   		TRACE (treeview,"(%p,%s)\n", &tvItem->pszText, tvItem->pszText); 
-		len = lstrlenA (tvItem->pszText)+1;
-		wineItem->pszText= COMCTL32_Alloc (len+1);
-		lstrcpyA (wineItem->pszText, tvItem->pszText);
-		wineItem->cchTextMax=len;
-	}
-	else {
-		TRACE (treeview,"LPSTR_TEXTCALLBACK\n");
-	    wineItem->pszText = LPSTR_TEXTCALLBACKA;
-	    wineItem->cchTextMax = 0;
-	}
-   }
 
    TREEVIEW_QueueRefresh (hwnd);
 
@@ -1649,6 +1983,7 @@
     infoPtr->selectedItem=0;
     infoPtr->clrText=-1;	/* use system color */
     infoPtr->dropItem=0;
+    infoPtr->pCallBackSort=NULL;
 
 /*
     infoPtr->hwndNotify = GetParent32 (hwnd);
@@ -2055,19 +2390,21 @@
       if (!wineItem->state & TVIS_EXPANDED) 
         return 0;
 
-      wineItem->state &= ~(TVIS_EXPANDEDONCE | TVIS_EXPANDED);
+      wineItem->state &= ~TVIS_EXPANDED;
       break;
 
     case TVE_EXPAND: 
       if (wineItem->state & TVIS_EXPANDED) 
         return 0;
 
-      if (!(wineItem->state & TVIS_EXPANDEDONCE)) 
-      {
+     
+      if (!(wineItem->state & TVIS_EXPANDEDONCE))  
+      { 
+        /* this item has never been expanded */
         if (TREEVIEW_SendTreeviewNotify (
               hwnd, 
               TVN_ITEMEXPANDING, 
-              0, 
+              TVE_EXPAND, 
               0, 
               (HTREEITEM)expand))
             return FALSE;   /* FIXME: OK? */
@@ -2076,11 +2413,15 @@
         TREEVIEW_SendTreeviewNotify (
           hwnd, 
           TVN_ITEMEXPANDED, 
-          0, 
+          TVE_EXPAND, 
           0, 
           (HTREEITEM)expand);
       }
-      wineItem->state |= TVIS_EXPANDED;
+      else
+      {
+        /* this item has already been expanded */
+        wineItem->state |= TVIS_EXPANDED;
+      }
       break;
 
     case TVE_EXPANDPARTIAL:
@@ -2197,8 +2538,7 @@
   TRACE (treeview,"item %d \n",(INT)wineItem->hItem);
  
   if (TREEVIEW_SendSimpleNotify (hwnd, NM_DBLCLK)!=TRUE) {     /* FIXME!*/
-	wineItem->state &= ~TVIS_EXPANDEDONCE;
-	TREEVIEW_Expand (hwnd, (WPARAM) TVE_TOGGLE, (LPARAM) wineItem->hItem);
+  	TREEVIEW_Expand (hwnd, (WPARAM) TVE_TOGGLE, (LPARAM) wineItem->hItem);
  }
  return TRUE;
 }
@@ -2738,7 +3078,6 @@
 
 
 
-
 LRESULT WINAPI
 TREEVIEW_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
@@ -2823,8 +3162,7 @@
       		return 0;
   
     	case TVM_SORTCHILDRENCB:
-      		FIXME (treeview, "Unimplemented msg TVM_SORTCHILDRENCB\n");
-      		return 0;
+      		return TREEVIEW_SortChildrenCB(hwnd, wParam, lParam);
   
     	case TVM_ENDEDITLABELNOW:
       		FIXME (treeview, "Unimplemented msg TVM_ENDEDITLABELNOW\n");