Index: trunk/src/comctl32/comctl32.def
===================================================================
--- trunk/src/comctl32/comctl32.def	(revision 10097)
+++ trunk/src/comctl32/comctl32.def	(revision 10098)
@@ -1,3 +1,3 @@
-; $Id: comctl32.def,v 1.28 2003-04-09 11:58:39 sandervl Exp $
+; $Id: comctl32.def,v 1.29 2003-05-15 14:26:27 sandervl Exp $
 LIBRARY COMCTL32 INITINSTANCE
 DESCRIPTION 'Odin32 System DLL - ComCtl32 - Common Controls Library'
@@ -103,5 +103,4 @@
 
   CreateMRUListA      = _CreateMRUListA@4          @151
-; ordinals????
   FreeMRUList         = _FreeMRUList@4             @152
   AddMRUStringA       = _AddMRUStringA@8           @153
@@ -160,5 +159,5 @@
   StrCmpNIW           = _COMCTL32_StrCmpNIW@12     @361
   StrStrW             = _COMCTL32_StrStrW@8        @362
-;StrStrIW @363
+  StrStrIW            = _COMCTL32_StrStrIW@8       @363
   StrSpnW             = _COMCTL32_StrSpnW@8        @364
   StrToIntW           = _COMCTL32_StrToIntW@4      @365
@@ -191,8 +190,9 @@
   CreateMRUListLazyW  = _CreateMRUListLazyW@16     @404
 
-                        _COMCTL32_410@16           @410 NONAME
-                        _COMCTL32_411@12           @411 NONAME
-                        _COMCTL32_412@12           @412 NONAME
-                        _COMCTL32_413@16           @413 NONAME
+; These are only available in comctrl 6
+  DefSubclassProc      = _DefSubclassProc@16       @410
+  GetWindowSubclass    = _GetWindowSubclass@16     @411
+  RemoveWindowSubclass = _RemoveWindowSubclass@12  @412
+  SetWindowSubclass    = _SetWindowSubclass@16     @413
                         _COMCTL32_415@20           @415 NONAME
 
@@ -201,8 +201,2 @@
 
 
-; These are only available in comctrl 6
-  DefSubclassProc      = _DefSubclassProc@16        @500
-  GetWindowSubclass    = _GetWindowSubclass@16      @501
-  RemoveWindowSubclass = _RemoveWindowSubclass@12   @502
-  SetWindowSubclass    = _SetWindowSubclass@16      @503
-
Index: trunk/src/comctl32/comctl32dbg.def
===================================================================
--- trunk/src/comctl32/comctl32dbg.def	(revision 10097)
+++ trunk/src/comctl32/comctl32dbg.def	(revision 10098)
@@ -1,3 +1,3 @@
-; $Id: comctl32dbg.def,v 1.4 2003-04-09 11:58:40 sandervl Exp $
+; $Id: comctl32dbg.def,v 1.5 2003-05-15 14:26:27 sandervl Exp $
 LIBRARY COMCTL32 INITINSTANCE
 DESCRIPTION 'Odin32 System DLL - ComCtl32 - Common Controls Library'
@@ -103,5 +103,4 @@
 
   CreateMRUListA      = _DbgCreateMRUListA@4          @151
-; ordinals????
   FreeMRUList         = _DbgFreeMRUList@4             @152
   AddMRUStringA       = _DbgAddMRUStringA@8           @153
@@ -157,5 +156,5 @@
   StrCmpNIW           = _DbgCOMCTL32_StrCmpNIW@12     @361
   StrStrW             = _DbgCOMCTL32_StrStrW@8        @362
-;StrStrIW @363
+  StrStrIW            = _DbgCOMCTL32_StrStrIW@8       @363
   StrSpnW             = _DbgCOMCTL32_StrSpnW@8        @364
   StrToIntW           = _DbgCOMCTL32_StrToIntW@4      @365
@@ -188,8 +187,9 @@
   CreateMRUListLazyW  = _DbgCreateMRUListLazyW@16     @404
 
-                        _COMCTL32_410@16           @410 NONAME
-                        _COMCTL32_411@12           @411 NONAME
-                        _COMCTL32_412@12           @412 NONAME
-                        _COMCTL32_413@16           @413 NONAME
+; These are only available in comctrl 6
+  DefSubclassProc      = _DefSubclassProc@16       @410
+  GetWindowSubclass    = _GetWindowSubclass@16     @411
+  RemoveWindowSubclass = _RemoveWindowSubclass@12  @412
+  SetWindowSubclass    = _SetWindowSubclass@16     @413
                         _COMCTL32_415@20           @415 NONAME
 
@@ -197,7 +197,2 @@
                         _COMCTL32_419@16           @419 NONAME
 
-; These are only available in comctrl 6
-  DefSubclassProc      = _DefSubclassProc@16        @500
-  GetWindowSubclass    = _GetWindowSubclass@16      @501
-  RemoveWindowSubclass = _RemoveWindowSubclass@12   @502
-  SetWindowSubclass    = _SetWindowSubclass@16      @503
Index: trunk/src/comctl32/initcomctl32.cpp
===================================================================
--- trunk/src/comctl32/initcomctl32.cpp	(revision 10097)
+++ trunk/src/comctl32/initcomctl32.cpp	(revision 10098)
@@ -1,3 +1,3 @@
-/* $Id: initcomctl32.cpp,v 1.5 2003-05-15 14:25:13 sandervl Exp $ */
+/* $Id: initcomctl32.cpp,v 1.6 2003-05-15 14:26:27 sandervl Exp $ */
 /*
  * COMCTL32 DLL entry point
Index: trunk/src/comctl32/makefile
===================================================================
--- trunk/src/comctl32/makefile	(revision 10097)
+++ trunk/src/comctl32/makefile	(revision 10098)
@@ -1,3 +1,3 @@
-# $Id: makefile,v 1.39 2003-05-15 14:25:14 sandervl Exp $
+# $Id: makefile,v 1.40 2003-05-15 14:26:27 sandervl Exp $
 
 #
Index: trunk/src/comctl32/monthcal.c
===================================================================
--- trunk/src/comctl32/monthcal.c	(revision 10097)
+++ trunk/src/comctl32/monthcal.c	(revision 10098)
@@ -8,4 +8,18 @@
  * Copyright 2000 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
  *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
  * TODO:
  *   - Notifications.
@@ -13,13 +27,7 @@
  *
  *  FIXME: handle resources better (doesn't work now); also take care
-           of internationalization. 
+           of internationalization.
  *  FIXME: keyboard handling.
  */
-
-#ifdef __WIN32OS2__
-#include <odin.h>
-#include <string.h>
-#define inline
-#endif
 
 #include <math.h>
@@ -35,11 +43,7 @@
 #include "commctrl.h"
 #include "comctl32.h"
-#include "debugtools.h"
-
-#ifdef __WIN32OS2__
-#include "ccbase.h"
-#endif
-
-DEFAULT_DEBUG_CHANNEL(monthcal);
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(monthcal);
 
 #define MC_SEL_LBUTUP	    1	/* Left button released */
@@ -51,11 +55,8 @@
 										/* to the next month */
 #define MC_NEXTMONTHTIMER   1			/* Timer ID's */
-#define MC_PREVMONTHTIMER   2			
+#define MC_PREVMONTHTIMER   2
 
 typedef struct
 {
-#ifdef __WIN32OS2__
-    COMCTL32_HEADER header;
-#endif
     COLORREF	bk;
     COLORREF	txt;
@@ -91,10 +92,10 @@
     SYSTEMTIME	minDate;
     SYSTEMTIME	maxDate;
-		
+
     RECT rcClient;	/* rect for whole client area */
     RECT rcDraw;	/* rect for drawable portion of client area */
     RECT title;		/* rect for the header above the calendar */
     RECT titlebtnnext;	/* the `next month' button in the header */
-    RECT titlebtnprev;  /* the `prev month' button in the header */	
+    RECT titlebtnprev;  /* the `prev month' button in the header */
     RECT titlemonth;	/* the `month name' txt in the header */
     RECT titleyear;	/* the `year number' txt in the header */
@@ -121,5 +122,5 @@
 {
 const int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
-  /*Wrap around, this eases handleing*/
+  /*Wrap around, this eases handling*/
   if(month == 0)
     month = 12;
@@ -141,5 +142,5 @@
 
 /* make sure that time is valid */
-static int MONTHCAL_ValidateTime(SYSTEMTIME time) 
+static int MONTHCAL_ValidateTime(SYSTEMTIME time)
 {
   if(time.wMonth > 12) return FALSE;
@@ -156,5 +157,5 @@
 
 
-void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to) 
+void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to)
 {
   to->wYear = from->wYear;
@@ -169,5 +170,5 @@
 
 
-/* Note:Depending on DST, this may be offset by a day. 
+/* Note:Depending on DST, this may be offset by a day.
    Need to find out if we're on a DST place & adjust the clock accordingly.
    Above function assumes we have a valid data.
@@ -182,5 +183,5 @@
   year-=(month < 3);
 
-  return((year + year/4 - year/100 + year/400 + 
+  return((year + year/4 - year/100 + year/400 +
          DayOfWeekTable[month-1] + day - 1 ) % 7);
 }
@@ -189,6 +190,6 @@
    and day in the calendar. day== 0 mean the last day of tha last month
 */
-static int MONTHCAL_CalcDayFromPos(MONTHCAL_INFO *infoPtr, int x, int y, 
-				   int *daypos,int *weekpos) 
+static int MONTHCAL_CalcDayFromPos(MONTHCAL_INFO *infoPtr, int x, int y,
+				   int *daypos,int *weekpos)
 {
   int retval, firstDay;
@@ -202,5 +203,5 @@
   *daypos = (x - infoPtr->days.left ) / infoPtr->width_increment;
   *weekpos = (y - infoPtr->days.top ) / infoPtr->height_increment;
-    
+
   firstDay = (MONTHCAL_CalculateDayOfWeek(1, infoPtr->currentMonth, infoPtr->currentYear)+6 - infoPtr->firstDay)%7;
   retval = *daypos + (7 * *weekpos) - firstDay;
@@ -211,5 +212,5 @@
 /* sets x and y to be the position of the day */
 /* x == day, y == week where(0,0) == firstDay, 1st week */
-static void MONTHCAL_CalcDayXY(MONTHCAL_INFO *infoPtr, int day, int month, 
+static void MONTHCAL_CalcDayXY(MONTHCAL_INFO *infoPtr, int day, int month,
                                  int *x, int *y)
 {
@@ -227,5 +228,5 @@
     if(prevMonth==0)
        prevMonth = 12;
-   
+
     *x = (MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear) - firstDay) % 7;
     *y = 0;
@@ -240,5 +241,5 @@
 
 /* x: column(day), y: row(week) */
-static void MONTHCAL_CalcDayRect(MONTHCAL_INFO *infoPtr, RECT *r, int x, int y) 
+static void MONTHCAL_CalcDayRect(MONTHCAL_INFO *infoPtr, RECT *r, int x, int y)
 {
   r->left = infoPtr->days.left + x * infoPtr->width_increment;
@@ -252,5 +253,5 @@
 /* day is the day value of the month(1 == 1st), month is the month */
 /* value(january == 1, december == 12) */
-static inline void MONTHCAL_CalcPosFromDay(MONTHCAL_INFO *infoPtr, 
+static inline void MONTHCAL_CalcPosFromDay(MONTHCAL_INFO *infoPtr,
                                             int day, int month, RECT *r)
 {
@@ -278,5 +279,5 @@
   x = day_rect.left;
   y = day_rect.top;
-	
+
   points[0].x = x;
   points[0].y = y - 1;
@@ -287,5 +288,5 @@
   points[3].x = x + infoPtr->width_increment;
   points[3].y = y + 0.5 * infoPtr->height_increment;
-	
+
   points[4].x = x + infoPtr->width_increment;
   points[4].y = y + 0.9 * infoPtr->height_increment;
@@ -295,5 +296,5 @@
   points[6].y = y + 0.9 * infoPtr->height_increment; /* bring the bottom up just
 				a hair to fit inside the day rectangle */
-	
+
   points[7].x = x + 0.2 * infoPtr->width_increment;
   points[7].y = y + 0.8 * infoPtr->height_increment;
@@ -309,5 +310,5 @@
   points[12].x = x + 0.4 * infoPtr->width_increment;
   points[12].y = y + 0.2 * infoPtr->height_increment;
-  
+
   PolyBezier(hdc, points, 13);
   DeleteObject(hRedPen);
@@ -329,5 +330,5 @@
   sprintf(buf, "%d", day);
 
-/* No need to check styles: when selection is not valid, it is set to zero. 
+/* No need to check styles: when selection is not valid, it is set to zero.
  * 1<day<31, so evertyhing's OK.
  */
@@ -341,5 +342,5 @@
 
     TRACE("%d %d %d\n",day, infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
-    TRACE("%d %d %d %d\n", r.left, r.top, r.right, r.bottom);
+    TRACE("%ld %ld %ld %ld\n", r.left, r.top, r.right, r.bottom);
     oldCol = SetTextColor(hdc, infoPtr->monthbk);
     oldBk = SetBkColor(hdc, infoPtr->trailingtxt);
@@ -390,5 +391,5 @@
 
 /* CHECKME: For `todays date', do we need to check the locale?*/
-static void MONTHCAL_Refresh(HWND hwnd, HDC hdc, PAINTSTRUCT* ps) 
+static void MONTHCAL_Refresh(HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
 {
   MONTHCAL_INFO *infoPtr=MONTHCAL_GetInfoPtr(hwnd);
@@ -425,5 +426,5 @@
   hbr = CreateSolidBrush (infoPtr->bk);
   FillRect(hdc, rcClient, hbr);
-  DeleteObject(hbr);       
+  DeleteObject(hbr);
 
   /* draw header */
@@ -434,8 +435,8 @@
     DeleteObject(hbr);
   }
-	
+
   /* if the previous button is pressed draw it depressed */
   if(IntersectRect(&rcTemp, &(ps->rcPaint), prev))
-  {  
+  {
     if((infoPtr->status & MC_PREVPRESSED))
         DrawFrameControl(hdc, prev, DFC_SCROLL,
@@ -447,5 +448,5 @@
   }
 
-  /* if next button is depressed draw it depressed */	
+  /* if next button is depressed draw it depressed */
   if(IntersectRect(&rcTemp, &(ps->rcPaint), next))
   {
@@ -466,12 +467,12 @@
   titlemonth->left   = title->left;
   titlemonth->right  = title->right;
- 
+
   GetLocaleInfoA( LOCALE_USER_DEFAULT,LOCALE_SMONTHNAME1+infoPtr->currentMonth -1,
 		  buf1,sizeof(buf1));
   sprintf(buf, "%s %ld", buf1, infoPtr->currentYear);
- 
+
   if(IntersectRect(&rcTemp, &(ps->rcPaint), titlemonth))
   {
-    DrawTextA(hdc, buf, strlen(buf), titlemonth, 
+    DrawTextA(hdc, buf, strlen(buf), titlemonth,
                         DT_CENTER | DT_VCENTER | DT_SINGLELINE);
   }
@@ -481,5 +482,5 @@
 /* titlemonth left/right contained rect for whole titletxt('June  1999')
   * MCM_HitTestInfo wants month & year rects, so prepare these now.
-  *(no, we can't draw them separately; the whole text is centered) 
+  *(no, we can't draw them separately; the whole text is centered)
   */
   GetTextExtentPoint32A(hdc, buf, strlen(buf), &size);
@@ -489,5 +490,5 @@
   titlemonth->right = titlemonth->left + size.cx;
   titleyear->left = titlemonth->right;
- 
+
   /* draw month area */
   rcTemp.top=infoPtr->wdays.top;
@@ -501,11 +502,11 @@
     DeleteObject(hbr);
   }
-	
+
 /* draw line under day abbreviatons */
 
   MoveToEx(hdc, infoPtr->days.left + 3, title->bottom + textHeight + 1, NULL);
-     
+
   LineTo(hdc, rcDraw->right - 3, title->bottom + textHeight + 1);
-  
+
   prevMonth = infoPtr->currentMonth - 1;
   if(prevMonth == 0) /* if currentMonth is january(1) prevMonth is */
@@ -537,8 +538,8 @@
 
 /* draw day numbers; first, the previous month */
-  
+
   firstDay = MONTHCAL_CalculateDayOfWeek(1, infoPtr->currentMonth, infoPtr->currentYear);
-  
-  day = MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear)  + 
+
+  day = MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear)  +
     (infoPtr->firstDay + 7  - firstDay)%7 + 1;
   if (day > MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear))
@@ -553,5 +554,5 @@
     if(IntersectRect(&rcTemp, &(ps->rcPaint), &rcDay))
     {
-      MONTHCAL_DrawDay(hdc, infoPtr, day, prevMonth, i, 0, 
+      MONTHCAL_DrawDay(hdc, infoPtr, day, prevMonth, i, 0,
           infoPtr->monthdayState[m] & mask);
     }
@@ -577,5 +578,5 @@
     {
 
-      MONTHCAL_DrawDay(hdc, infoPtr, day, infoPtr->currentMonth, i, 0, 
+      MONTHCAL_DrawDay(hdc, infoPtr, day, infoPtr->currentMonth, i, 0,
 	infoPtr->monthdayState[m] & mask);
 
@@ -595,5 +596,5 @@
   j = 1; /* move to the 2nd week of the current month */
   i = 0; /* move back to sunday */
-  while(day <= MONTHCAL_MonthLength(infoPtr->currentMonth, infoPtr->currentYear)) {	
+  while(day <= MONTHCAL_MonthLength(infoPtr->currentMonth, infoPtr->currentYear)) {
     MONTHCAL_CalcDayRect(infoPtr, &rcDay, i, j);
     if(IntersectRect(&rcTemp, &(ps->rcPaint), &rcDay))
@@ -604,6 +605,6 @@
       if((infoPtr->currentMonth==infoPtr->todaysDate.wMonth) &&
           (day==infoPtr->todaysDate.wDay) &&
-          (infoPtr->currentYear == infoPtr->todaysDate.wYear)) 
-        if(!(dwStyle & MCS_NOTODAYCIRCLE))  
+          (infoPtr->currentYear == infoPtr->todaysDate.wYear))
+        if(!(dwStyle & MCS_NOTODAYCIRCLE))
 	  MONTHCAL_CircleDay(hdc, infoPtr, day, infoPtr->currentMonth);
     }
@@ -627,5 +628,5 @@
     MONTHCAL_CalcDayRect(infoPtr, &rcDay, i, j);
     if(IntersectRect(&rcTemp, &(ps->rcPaint), &rcDay))
-    {   
+    {
       MONTHCAL_DrawDay(hdc, infoPtr, day, infoPtr->currentMonth + 1, i, j,
 		infoPtr->monthdayState[m] & mask);
@@ -634,5 +635,5 @@
     mask<<=1;
     day++;
-    i++;	
+    i++;
     if(i==7) { /* past saturday, go to next week's sunday */
       i = 0;
@@ -650,6 +651,6 @@
     if(!(dwStyle & MCS_NOTODAYCIRCLE))  {
       /*day is the number of days from nextmonth we put on the calendar */
-      MONTHCAL_CircleDay(hdc, infoPtr, 
-			 day+MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear), 
+      MONTHCAL_CircleDay(hdc, infoPtr,
+			 day+MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear),
 			 infoPtr->currentMonth);
       offset+=textWidth;
@@ -674,5 +675,5 @@
   }
 
-/*eventually draw week numbers*/   
+/*eventually draw week numbers*/
   if(dwStyle & MCS_WEEKNUMBERS)  {
     /* display weeknumbers*/
@@ -682,5 +683,5 @@
        LOCALE_IFIRSTWEEKOFYEAR == 0 (e.g US?):
        The week containing Jan 1 is the first week of year
-       LOCALE_IFIRSTWEEKOFYEAR == 2 (e.g. Germany): 
+       LOCALE_IFIRSTWEEKOFYEAR == 2 (e.g. Germany):
        First week of year must contain 4 days of the new year
        LOCALE_IFIRSTWEEKOFYEAR == 1  (what contries?)
@@ -704,10 +705,10 @@
 	/* calculate all those exceptions for january */
 	weeknum1=MONTHCAL_CalculateDayOfWeek(1,1,infoPtr->currentYear);
-	if ((infoPtr->firstDay +7 - weeknum1)%7 > mindays) 
+	if ((infoPtr->firstDay +7 - weeknum1)%7 > mindays)
 	    weeknum =1;
 	else
 	  {
 	    weeknum = 0;
-	    for(i=0; i<11; i++) 
+	    for(i=0; i<11; i++)
 	      weeknum+=MONTHCAL_MonthLength(i+1, infoPtr->currentYear-1);
 	    weeknum +=startofprescal+ 7;
@@ -721,5 +722,5 @@
       {
 	weeknum = 0;
-	for(i=0; i<prevMonth-1; i++) 
+	for(i=0; i<prevMonth-1; i++)
 	  weeknum+=MONTHCAL_MonthLength(i+1, infoPtr->currentYear);
 	weeknum +=startofprescal+ 7;
@@ -749,18 +750,18 @@
       days->bottom+=infoPtr->height_increment;
     }
-			
+
     MoveToEx(hdc, infoPtr->weeknums.right, infoPtr->weeknums.top + 3 , NULL);
     LineTo(hdc,   infoPtr->weeknums.right, infoPtr->weeknums.bottom );
-		
+
   }
   /* currentFont was font at entering Refresh */
 
   SetBkColor(hdc, oldBkColor);
-  SelectObject(hdc, currentFont);     
+  SelectObject(hdc, currentFont);
   SetTextColor(hdc, oldTextColor);
 }
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_GetMinReqRect(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -768,5 +769,5 @@
   LPRECT lpRect = (LPRECT) lParam;
   TRACE("%x %lx\n", wParam, lParam);
-	
+
   /* validate parameters */
 
@@ -781,5 +782,5 @@
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_GetColor(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -807,5 +808,5 @@
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_SetColor(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -847,5 +848,5 @@
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_GetMonthDelta(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -853,5 +854,5 @@
 
   TRACE("%x %lx\n", wParam, lParam);
-  
+
   if(infoPtr->delta)
     return infoPtr->delta;
@@ -861,5 +862,5 @@
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_SetMonthDelta(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -868,5 +869,5 @@
 
   TRACE("%x %lx\n", wParam, lParam);
-	
+
   infoPtr->delta = (int)wParam;
   return prev;
@@ -874,9 +875,9 @@
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_GetFirstDayOfWeek(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
   MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
-	
+
   return infoPtr->firstDay;
 }
@@ -887,5 +888,5 @@
 /* FIXME: this needs to be implemented properly in MONTHCAL_Refresh() */
 /* FIXME: we need more error checking here */
-static LRESULT 
+static LRESULT
 MONTHCAL_SetFirstDayOfWeek(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -916,5 +917,5 @@
 /* FIXME: fill this in */
 static LRESULT
-MONTHCAL_GetMonthRange(HWND hwnd, WPARAM wParam, LPARAM lParam) 
+MONTHCAL_GetMonthRange(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
   MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd);
@@ -937,5 +938,5 @@
 
 /* FIXME: are validated times taken from current date/time or simply
- * copied? 
+ * copied?
  * FIXME:    check whether MCM_GETMONTHRANGE shows correct result after
  *            adjusting range with MCM_SETRANGE
@@ -950,5 +951,5 @@
 
   TRACE("%x %lx\n", wParam, lParam);
-  
+
   if(wParam & GDTR_MAX) {
     if(MONTHCAL_ValidateTime(lprgSysTimeArray[1])){
@@ -973,7 +974,7 @@
   infoPtr->monthRange = infoPtr->maxDate.wMonth - infoPtr->minDate.wMonth;
 
-  if(infoPtr->monthRange!=prev) { 
-	COMCTL32_ReAlloc(infoPtr->monthdayState, 
-		infoPtr->monthRange * sizeof(MONTHDAYSTATE));
+  if(infoPtr->monthRange!=prev) {
+	infoPtr->monthdayState = COMCTL32_ReAlloc(infoPtr->monthdayState,
+                                                  infoPtr->monthRange * sizeof(MONTHDAYSTATE));
   }
 
@@ -983,5 +984,5 @@
 
 /* CHECKME: At the moment, we copy ranges anyway,regardless of
- * infoPtr->rangeValid; a invalid range is simply filled with zeros in 
+ * infoPtr->rangeValid; a invalid range is simply filled with zeros in
  * SetRange.  Is this the right behavior?
 */
@@ -1015,10 +1016,10 @@
   if(iMonths!=infoPtr->monthRange) return 0;
 
-  for(i=0; i<iMonths; i++) 
+  for(i=0; i<iMonths; i++)
     infoPtr->monthdayState[i] = dayStates[i];
   return 1;
 }
 
-static LRESULT 
+static LRESULT
 MONTHCAL_GetCurSel(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1036,5 +1037,5 @@
 /* FIXME: if the specified date is not visible, make it visible */
 /* FIXME: redraw? */
-static LRESULT 
+static LRESULT
 MONTHCAL_SetCurSel(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1057,5 +1058,5 @@
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_GetMaxSelCount(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1067,5 +1068,5 @@
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_SetMaxSelCount(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1081,5 +1082,5 @@
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_GetSelRange(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1100,10 +1101,10 @@
     return TRUE;
   }
- 
+
   return FALSE;
 }
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_SetSelRange(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1124,10 +1125,10 @@
     return TRUE;
   }
- 
+
   return FALSE;
 }
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_GetToday(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1145,5 +1146,5 @@
 
 
-static LRESULT 
+static LRESULT
 MONTHCAL_SetToday(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1170,13 +1171,13 @@
   DWORD retval;
   int day,wday,wnum;
-  
-  
+
+
   x = lpht->pt.x;
   y = lpht->pt.y;
   retval = MCHT_NOWHERE;
-  
-
-  /* Comment in for debugging... 
-  TRACE("%d %d wd[%d %d %d %d] d[%d %d %d %d] t[%d %d %d %d] wn[%d %d %d %d]\n", x, y, 
+
+
+  /* Comment in for debugging...
+  TRACE("%d %d wd[%d %d %d %d] d[%d %d %d %d] t[%d %d %d %d] wn[%d %d %d %d]\n", x, y,
 	infoPtr->wdays.left, infoPtr->wdays.right,
 	infoPtr->wdays.top, infoPtr->wdays.bottom,
@@ -1190,5 +1191,5 @@
 
   /* are we in the header? */
-  
+
   if(PtInRect(&infoPtr->title, lpht->pt)) {
     if(PtInRect(&infoPtr->titlebtnprev, lpht->pt)) {
@@ -1208,9 +1209,9 @@
       goto done;
     }
-    
+
     retval = MCHT_TITLE;
     goto done;
   }
-  
+
   day = MONTHCAL_CalcDayFromPos(infoPtr,x,y,&wday,&wnum);
   if(PtInRect(&infoPtr->wdays, lpht->pt)) {
@@ -1218,24 +1219,24 @@
     lpht->st.wYear  = infoPtr->currentYear;
     lpht->st.wMonth = (day < 1)? infoPtr->currentMonth -1 : infoPtr->currentMonth;
-    lpht->st.wDay   = (day < 1)? 
+    lpht->st.wDay   = (day < 1)?
       MONTHCAL_MonthLength(infoPtr->currentMonth-1,infoPtr->currentYear) -day : day;
     goto done;
   }
-  if(PtInRect(&infoPtr->weeknums, lpht->pt)) {  
-    retval = MCHT_CALENDARWEEKNUM; 
+  if(PtInRect(&infoPtr->weeknums, lpht->pt)) {
+    retval = MCHT_CALENDARWEEKNUM;
     lpht->st.wYear  = infoPtr->currentYear;
-    lpht->st.wMonth = (day < 1) ? infoPtr->currentMonth -1 : 
-      (day > MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear)) ? 
+    lpht->st.wMonth = (day < 1) ? infoPtr->currentMonth -1 :
+      (day > MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear)) ?
       infoPtr->currentMonth +1 :infoPtr->currentMonth;
-    lpht->st.wDay   = (day < 1 ) ? 
-      MONTHCAL_MonthLength(infoPtr->currentMonth-1,infoPtr->currentYear) -day : 
-      (day > MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear)) ? 
+    lpht->st.wDay   = (day < 1 ) ?
+      MONTHCAL_MonthLength(infoPtr->currentMonth-1,infoPtr->currentYear) -day :
+      (day > MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear)) ?
       day - MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear) : day;
-    goto done;				    
-  }
-  if(PtInRect(&infoPtr->days, lpht->pt)) 
+    goto done;
+  }
+  if(PtInRect(&infoPtr->days, lpht->pt))
     {
       lpht->st.wYear  = infoPtr->currentYear;
-      if ( day < 1) 
+      if ( day < 1)
 	{
 	  retval = MCHT_CALENDARDATEPREV;
@@ -1267,13 +1268,13 @@
     }
   if(PtInRect(&infoPtr->todayrect, lpht->pt)) {
-    retval = MCHT_TODAYLINK; 
+    retval = MCHT_TODAYLINK;
     goto done;
   }
-  
-  
+
+
   /* Hit nothing special? What's left must be background :-) */
-  
-  retval = MCHT_CALENDARBK;       
- done: 
+
+  retval = MCHT_CALENDARBK;
+ done:
   lpht->uHit = retval;
   return retval;
@@ -1331,5 +1332,5 @@
     nmds.nmhdr.code     = MCN_GETDAYSTATE;
     nmds.cDayState	= infoPtr->monthRange;
-    nmds.prgDayState	= COMCTL32_Alloc 
+    nmds.prgDayState	= COMCTL32_Alloc
                         (infoPtr->monthRange * sizeof(MONTHDAYSTATE));
 
@@ -1348,5 +1349,5 @@
   POINT menupoint;
   char buf[32];
-  
+
   hMenu = CreatePopupMenu();
   if (!LoadStringA(COMCTL32_hModule,IDM_GOTODAY,buf,sizeof(buf)))
@@ -1365,5 +1366,5 @@
       infoPtr->currentYear=infoPtr->todaysDate.wYear;
       InvalidateRect(hwnd, NULL, FALSE);
-    }	
+    }
   return 0;
 }
@@ -1381,5 +1382,5 @@
   POINT menupoint;
   TRACE("%x %lx\n", wParam, lParam);
-	
+
   if (infoPtr->hWndYearUpDown)
     {
@@ -1399,5 +1400,5 @@
       InvalidateRect(hwnd, NULL, FALSE);
     }
-  
+
   ht.pt.x = (INT)LOWORD(lParam);
   ht.pt.y = (INT)HIWORD(lParam);
@@ -1414,5 +1415,5 @@
     return TRUE;
   }
-  if(hit == MCHT_TITLEBTNPREV){ 
+  if(hit == MCHT_TITLEBTNPREV){
     MONTHCAL_GoToPrevMonth(hwnd, infoPtr);
     infoPtr->status = MC_PREVPRESSED;
@@ -1424,5 +1425,5 @@
   if(hit == MCHT_TITLEMONTH) {
     hMenu = CreatePopupMenu();
-    
+
     for (i=0; i<12;i++)
       {
@@ -1451,6 +1452,6 @@
 			 infoPtr->textHeight,
 			 hwnd,
-			 (HMENU)NULL, 
-			 (HINSTANCE)NULL, 
+			 NULL,
+			 NULL,
 			 NULL);
     infoPtr->hWndYearUpDown=CreateWindowExA(0,
@@ -1462,6 +1463,6 @@
 			 infoPtr->textHeight,
 			 hwnd,
-			 (HMENU)NULL, 
-			 (HINSTANCE)NULL, 
+			 NULL,
+			 NULL,
 			 NULL);
     SendMessageA( infoPtr->hWndYearUpDown, UDM_SETRANGE, (WPARAM) 0, MAKELONG (9999, 1753));
@@ -1469,5 +1470,5 @@
     SendMessageA( infoPtr->hWndYearUpDown, UDM_SETPOS,   (WPARAM) 0,(LPARAM)infoPtr->currentYear );
     return TRUE;
-	 
+
   }
   if(hit == MCHT_TODAYLINK) {
@@ -1487,5 +1488,5 @@
     MONTHCAL_CopyTime(&nmsc.stSelStart, &infoPtr->minSel);
     MONTHCAL_CopyTime(&nmsc.stSelEnd, &infoPtr->maxSel);
-	
+
     SendMessageA(GetParent(hwnd), WM_NOTIFY,
            (WPARAM)nmsc.nmhdr.idFrom,(LPARAM)&nmsc);
@@ -1493,5 +1494,5 @@
     MONTHCAL_CopyTime(&ht.st, &selArray[0]);
     MONTHCAL_CopyTime(&ht.st, &selArray[1]);
-    MONTHCAL_SetSelRange(hwnd,0,(LPARAM) &selArray); 
+    MONTHCAL_SetSelRange(hwnd,0,(LPARAM) &selArray);
 
     /* redraw both old and new days if the selected day changed */
@@ -1546,5 +1547,5 @@
     return TRUE;
   }
-  if(hit == MCHT_CALENDARDATEPREV){ 
+  if(hit == MCHT_CALENDARDATEPREV){
     MONTHCAL_GoToPrevMonth(hwnd, infoPtr);
     InvalidateRect(hwnd, NULL, FALSE);
@@ -1554,5 +1555,5 @@
   nmhdr.idFrom   = GetWindowLongA( hwnd, GWL_ID);
   nmhdr.code     = NM_RELEASEDCAPTURE;
-  TRACE("Sent notification from %x to %x\n", hwnd, GetParent(hwnd));
+  TRACE("Sent notification from %p to %p\n", hwnd, GetParent(hwnd));
 
   SendMessageA(GetParent(hwnd), WM_NOTIFY,
@@ -1564,12 +1565,12 @@
   MONTHCAL_CopyTime(&nmsc.stSelStart, &infoPtr->minSel);
   MONTHCAL_CopyTime(&nmsc.stSelEnd, &infoPtr->maxSel);
-	
+
   SendMessageA(GetParent(hwnd), WM_NOTIFY,
            (WPARAM)nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
-  
+
   /* redraw if necessary */
   if(redraw)
     InvalidateRect(hwnd, NULL, FALSE);
-	
+
   return 0;
 }
@@ -1586,5 +1587,5 @@
 
   switch(wParam) {
-  case MC_NEXTMONTHTIMER: 
+  case MC_NEXTMONTHTIMER:
     redraw = TRUE;
     MONTHCAL_GoToNextMonth(hwnd, infoPtr);
@@ -1618,7 +1619,7 @@
   ht.pt.x = LOWORD(lParam);
   ht.pt.y = HIWORD(lParam);
-	
+
   hit = MONTHCAL_HitTest(hwnd, (LPARAM)&ht);
-  
+
   /* not on the calendar date numbers? bail out */
   TRACE("hit:%x\n",hit);
@@ -1638,5 +1639,5 @@
     if(infoPtr->firstSelDay==selArray[0].wDay) i=1;
     TRACE("oldRange:%d %d %d %d\n", infoPtr->firstSelDay, selArray[0].wDay, selArray[1].wDay, i);
-    if(infoPtr->firstSelDay==selArray[1].wDay) {  
+    if(infoPtr->firstSelDay==selArray[1].wDay) {
       /* 1st time we get here: selArray[0]=selArray[1])  */
       /* if we're still at the first selected date, return */
@@ -1644,5 +1645,5 @@
       if(selday<infoPtr->firstSelDay) i = 0;
     }
-			
+
     if(abs(infoPtr->firstSelDay - selday) >= infoPtr->maxSelCount) {
       if(selday>infoPtr->firstSelDay)
@@ -1651,8 +1652,8 @@
         selday = infoPtr->firstSelDay - infoPtr->maxSelCount;
     }
-		
+
     if(selArray[i].wDay!=selday) {
       TRACE("newRange:%d %d %d %d\n", infoPtr->firstSelDay, selArray[0].wDay, selArray[1].wDay, i);
-			
+
       selArray[i].wDay = selday;
 
@@ -1712,5 +1713,5 @@
 {
   TRACE("\n");
-  
+
   InvalidateRect(hwnd, NULL, FALSE);
 
@@ -1769,6 +1770,6 @@
 
   /* recalculate the height and width increments and offsets */
-  /* FIXME: We use up all available width. This will inhibit having multiple 
-     calendars in a row, like win doesn 
+  /* FIXME: We use up all available width. This will inhibit having multiple
+     calendars in a row, like win doesn
   */
   if(dwStyle & MCS_WEEKNUMBERS)
@@ -1776,6 +1777,6 @@
   else
     xdiv=7.0;
-  infoPtr->width_increment = (infoPtr->rcDraw.right - infoPtr->rcDraw.left) / xdiv; 
-  infoPtr->height_increment = (infoPtr->rcDraw.bottom - infoPtr->rcDraw.top) / 10.0; 
+  infoPtr->width_increment = (infoPtr->rcDraw.right - infoPtr->rcDraw.left) / xdiv;
+  infoPtr->height_increment = (infoPtr->rcDraw.bottom - infoPtr->rcDraw.top) / 10.0;
   infoPtr->left_offset = (infoPtr->rcDraw.right - infoPtr->rcDraw.left) - (infoPtr->width_increment * xdiv);
   infoPtr->top_offset = (infoPtr->rcDraw.bottom - infoPtr->rcDraw.top) - (infoPtr->height_increment * 10.0);
@@ -1790,5 +1791,5 @@
     rcDraw->bottom = rcDraw->top + 9 * infoPtr->textHeight + 5;
     }*/
-   
+
   /* calculate title area */
   title->top    = rcClient->top;
@@ -1805,5 +1806,5 @@
   next->right  = title->right - 6;
   next->left   = next->right - (title->bottom - title->top);
-  
+
   /* titlemonth->left and right change based upon the current month */
   /* and are recalculated in refresh as the current month may change */
@@ -1811,9 +1812,9 @@
   titlemonth->top    = titleyear->top    = title->top    + (infoPtr->height_increment)/2;
   titlemonth->bottom = titleyear->bottom = title->bottom - (infoPtr->height_increment)/2;
-  
+
   /* setup the dimensions of the rectangle we draw the names of the */
   /* days of the week in */
   weeknumrect->left =infoPtr->left_offset;
-  if(dwStyle & MCS_WEEKNUMBERS)  
+  if(dwStyle & MCS_WEEKNUMBERS)
     weeknumrect->right=prev->right;
   else
@@ -1823,8 +1824,8 @@
   wdays->top    = title->bottom ;
   wdays->bottom = wdays->top + infoPtr->height_increment;
-  
+
   days->top    = weeknumrect->top = wdays->bottom ;
   days->bottom = weeknumrect->bottom = days->top     + 6 * infoPtr->height_increment;
-  
+
   todayrect->left   = rcClient->left;
   todayrect->right  = rcClient->right;
@@ -1832,5 +1833,5 @@
   todayrect->bottom = days->bottom + infoPtr->height_increment;
 
-  /* uncomment for excessive debugging 
+  /* uncomment for excessive debugging
   TRACE("dx=%d dy=%d rcC[%d %d %d %d] t[%d %d %d %d] wd[%d %d %d %d] w[%d %d %d %d] t[%d %d %d %d]\n",
 	infoPtr->width_increment,infoPtr->height_increment,
@@ -1841,7 +1842,7 @@
 	todayrect->left,todayrect->right,todayrect->top,todayrect->bottom);
   */
-  
+
   /* restore the originally selected font */
-  SelectObject(hdc, currentFont);     
+  SelectObject(hdc, currentFont);
 
   ReleaseDC(hwnd, hdc);
@@ -1850,5 +1851,5 @@
 static LRESULT MONTHCAL_Size(HWND hwnd, int Width, int Height)
 {
-  TRACE("(hwnd=%x, width=%d, height=%d)\n", hwnd, Width, Height);
+  TRACE("(hwnd=%p, width=%d, height=%d)\n", hwnd, Width, Height);
 
   MONTHCAL_UpdateSize(hwnd);
@@ -1868,9 +1869,5 @@
 
   /* allocate memory for info structure */
-#ifdef __WIN32OS2__
-  infoPtr =(MONTHCAL_INFO*)initControl(hwnd,sizeof(MONTHCAL_INFO));
-#else
   infoPtr =(MONTHCAL_INFO*)COMCTL32_Alloc(sizeof(MONTHCAL_INFO));
-#endif
   SetWindowLongA(hwnd, 0, (DWORD)infoPtr);
 
@@ -1900,5 +1897,5 @@
   infoPtr->maxSelCount  = 7;
   infoPtr->monthRange = 3;
-  infoPtr->monthdayState = COMCTL32_Alloc 
+  infoPtr->monthdayState = COMCTL32_Alloc
                          (infoPtr->monthRange * sizeof(MONTHDAYSTATE));
   infoPtr->titlebk     = GetSysColor(COLOR_ACTIVECAPTION);
@@ -1923,4 +1920,6 @@
 
   /* free month calendar info data */
+  if(infoPtr->monthdayState)
+      COMCTL32_Free(infoPtr->monthdayState);
   COMCTL32_Free(infoPtr);
   SetWindowLongA(hwnd, 0, 0);
@@ -1932,5 +1931,5 @@
 MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-  TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam);
+  TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam);
   if (!MONTHCAL_GetInfoPtr(hwnd) && (uMsg != WM_CREATE))
     return DefWindowProcA(hwnd, uMsg, wParam, lParam);
@@ -2037,11 +2036,7 @@
 
   default:
-    if(uMsg >= WM_USER)
+    if ((uMsg >= WM_USER) && (uMsg < WM_APP))
       ERR( "unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam);
-#ifdef __WIN32OS2__
-    return defComCtl32ProcA(hwnd, uMsg, wParam, lParam);
-#else
     return DefWindowProcA(hwnd, uMsg, wParam, lParam);
-#endif
   }
   return 0;
@@ -2062,5 +2057,5 @@
   wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
   wndClass.lpszClassName = MONTHCAL_CLASSA;
- 
+
   RegisterClassA(&wndClass);
 }
@@ -2070,4 +2065,4 @@
 MONTHCAL_Unregister(void)
 {
-    UnregisterClassA(MONTHCAL_CLASSA, (HINSTANCE)NULL);
-}
+    UnregisterClassA(MONTHCAL_CLASSA, NULL);
+}
Index: trunk/src/comctl32/nativefont.c
===================================================================
--- trunk/src/comctl32/nativefont.c	(revision 10097)
+++ trunk/src/comctl32/nativefont.c	(revision 10098)
@@ -124,5 +124,5 @@
     wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
     wndClass.lpszClassName = WC_NATIVEFONTCTLA;
- 
+
     RegisterClassA (&wndClass);
 }
@@ -132,5 +132,4 @@
 NATIVEFONT_Unregister (void)
 {
-    UnregisterClassA (WC_NATIVEFONTCTLA, (HINSTANCE)NULL);
+    UnregisterClassA (WC_NATIVEFONTCTLA, NULL);
 }
-
Index: trunk/src/comctl32/pager.c
===================================================================
--- trunk/src/comctl32/pager.c	(revision 10097)
+++ trunk/src/comctl32/pager.c	(revision 10098)
@@ -837,5 +837,5 @@
 
     /* set default settings */
-    infoPtr->hwndChild = (HWND)NULL;
+    infoPtr->hwndChild = NULL;
     infoPtr->bNoResize = dwStyle & CCS_NORESIZE;
     infoPtr->clrBk = GetSysColor(COLOR_BTNFACE);
@@ -898,5 +898,5 @@
     DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
 
-    TRACE("orig rect=(%d,%d)-(%d,%d)\n",
+    TRACE("orig rect=(%ld,%ld)-(%ld,%ld)\n",
 	  lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
 
@@ -913,5 +913,5 @@
 	scrollRange = infoPtr->nWidth - (rcmyw.right - rcmyw.left);
 
-	TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%d,%d)-(%d,%d), cursor=(%ld,%ld)\n",
+	TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%ld,%ld)-(%ld,%ld), cursor=(%ld,%ld)\n",
 	      infoPtr->nPos, scrollRange, infoPtr->nHeight,
 	      rcmyw.left, rcmyw.top,
@@ -927,5 +927,5 @@
 	    rbrc = wnrc;
 	    rbrc.left = rbrc.right - infoPtr->nButtonSize;
-	    TRACE("horz lt rect=(%d,%d)-(%d,%d), rb rect=(%d,%d)-(%d,%d)\n",
+	    TRACE("horz lt rect=(%ld,%ld)-(%ld,%ld), rb rect=(%ld,%ld)-(%ld,%ld)\n",
 		  ltrc.left, ltrc.top, ltrc.right, ltrc.bottom,
 		  rbrc.left, rbrc.top, rbrc.right, rbrc.bottom);
@@ -962,5 +962,5 @@
 	scrollRange = infoPtr->nHeight - (rcmyw.bottom - rcmyw.top);
 
-	TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%d,%d)-(%d,%d), cursor=(%ld,%ld)\n",
+	TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%ld,%ld)-(%ld,%ld), cursor=(%ld,%ld)\n",
 	      infoPtr->nPos, scrollRange, infoPtr->nHeight,
 	      rcmyw.left, rcmyw.top,
@@ -987,5 +987,5 @@
 	    rbrc = wnrc;
 	    rbrc.left = rbrc.right - infoPtr->nButtonSize;
-	    TRACE("vert lt rect=(%d,%d)-(%d,%d), rb rect=(%d,%d)-(%d,%d)\n",
+	    TRACE("vert lt rect=(%ld,%ld)-(%ld,%ld), rb rect=(%ld,%ld)-(%ld,%ld)\n",
 		  ltrc.left, ltrc.top, ltrc.right, ltrc.bottom,
 		  rbrc.left, rbrc.top, rbrc.right, rbrc.bottom);
@@ -999,10 +999,7 @@
 	if (infoPtr->BRbtnState && (lpRect->bottom - infoPtr->nButtonSize > lpRect->top))
 	    lpRect->bottom -= infoPtr->nButtonSize;
-	/* ???? */
-	if ((lpRect->bottom < 0) || (lpRect->bottom > infoPtr->nHeight))
-	    lpRect->bottom = infoPtr->nHeight;
-    }
-
-    TRACE("[%p] client rect set to %dx%d at (%d,%d) BtnState[%d,%d]\n",
+    }
+
+    TRACE("[%p] client rect set to %ldx%ld at (%ld,%ld) BtnState[%d,%d]\n",
 	  hwnd, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top,
 	  lpRect->left, lpRect->top,
@@ -1233,5 +1230,5 @@
 	/* If in one of the buttons the capture and draw buttons */
 	if (btnrect) {
-	    TRACE("[%p] draw btn (%d,%d)-(%d,%d), Capture %s, style %08lx\n",
+	    TRACE("[%p] draw btn (%ld,%ld)-(%ld,%ld), Capture %s, style %08lx\n",
 		  hwnd, btnrect->left, btnrect->top,
 		  btnrect->right, btnrect->bottom,
@@ -1604,4 +1601,4 @@
 PAGER_Unregister (void)
 {
-    UnregisterClassA (WC_PAGESCROLLERA, (HINSTANCE)NULL);
-}
+    UnregisterClassA (WC_PAGESCROLLERA, NULL);
+}
Index: trunk/src/comctl32/progress.c
===================================================================
--- trunk/src/comctl32/progress.c	(revision 10097)
+++ trunk/src/comctl32/progress.c	(revision 10098)
@@ -258,4 +258,5 @@
     infoPtr->MaxVal = high;
     PROGRESS_CoercePos(infoPtr);
+    InvalidateRect(infoPtr->Self, NULL, TRUE);
     return res;
 }
@@ -335,5 +336,5 @@
     case PBM_SETPOS:
     {
-	INT oldVal;
+        UINT oldVal;
         oldVal = infoPtr->CurVal;
         if(oldVal != wParam) {
@@ -431,4 +432,4 @@
 VOID PROGRESS_Unregister (void)
 {
-    UnregisterClassW (PROGRESS_CLASSW, (HINSTANCE)NULL);
-}
+    UnregisterClassW (PROGRESS_CLASSW, NULL);
+}
Index: trunk/src/comctl32/propsheet.c
===================================================================
--- trunk/src/comctl32/propsheet.c	(revision 10097)
+++ trunk/src/comctl32/propsheet.c	(revision 10098)
@@ -26,4 +26,6 @@
 #include <string.h>
 
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
 #include "winbase.h"
 #include "commctrl.h"
@@ -31,5 +33,4 @@
 #include "winnls.h"
 #include "comctl32.h"
-#include "heap.h"
 
 #include "wine/debug.h"
@@ -113,6 +114,4 @@
 #define MAX_BUTTONTEXT_LENGTH 64
 
-#define PSH_WIZARD97_OLD   0x00002000
-#define PSH_WIZARD97_NEW   0x01000000
 #define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)
 
@@ -120,5 +119,5 @@
  * Prototypes
  */
-static BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo);
+static int PROPSHEET_CreateDialog(PropSheetInfo* psInfo);
 static BOOL PROPSHEET_SizeMismatch(HWND hwndDlg, PropSheetInfo* psInfo);
 static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo);
@@ -290,5 +289,5 @@
   psInfo->hasHelp = dwFlags & PSH_HASHELP;
   psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
-  psInfo->useCallback = dwFlags & PSH_USECALLBACK;
+  psInfo->useCallback = (dwFlags & PSH_USECALLBACK )&& (lppsh->pfnCallback);
   psInfo->isModeless = dwFlags & PSH_MODELESS;
 
@@ -341,5 +340,5 @@
   psInfo->hasHelp = dwFlags & PSH_HASHELP;
   psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
-  psInfo->useCallback = dwFlags & PSH_USECALLBACK;
+  psInfo->useCallback = (dwFlags & PSH_USECALLBACK) && (lppsh->pfnCallback);
   psInfo->isModeless = dwFlags & PSH_MODELESS;
 
@@ -554,5 +553,5 @@
  * Creates the actual property sheet.
  */
-BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo)
+int PROPSHEET_CreateDialog(PropSheetInfo* psInfo)
 {
   LRESULT ret;
@@ -570,8 +569,8 @@
                             MAKEINTRESOURCEW(resID),
                             RT_DIALOGW)))
-    return FALSE;
+    return -1;
 
   if(!(template = (LPVOID)LoadResource(COMCTL32_hModule, hRes)))
-    return FALSE;
+    return -1;
 
   /*
@@ -583,5 +582,5 @@
 
   if (!temp)
-    return FALSE;
+    return -1;
 
   memcpy(temp, template, resSize);
@@ -597,9 +596,12 @@
                                     (LPARAM)psInfo);
   else
-      ret = CreateDialogIndirectParamW(psInfo->ppshheader.hInstance,
-                                       (LPDLGTEMPLATEW) temp,
-                                       psInfo->ppshheader.hwndParent,
-                                       PROPSHEET_DialogProc,
-                                       (LPARAM)psInfo) ? TRUE : FALSE;
+  {
+      ret = (int)CreateDialogIndirectParamW(psInfo->ppshheader.hInstance,
+                                            (LPDLGTEMPLATEW) temp,
+                                            psInfo->ppshheader.hwndParent,
+                                            PROPSHEET_DialogProc,
+                                            (LPARAM)psInfo);
+      if ( !ret ) ret = -1;
+  }
 
   COMCTL32_Free(temp);
@@ -623,5 +625,5 @@
    */
   GetClientRect(hwndTabCtrl, &rcOrigTab);
-  TRACE("orig tab %d %d %d %d\n", rcOrigTab.left, rcOrigTab.top,
+  TRACE("orig tab %ld %ld %ld %ld\n", rcOrigTab.left, rcOrigTab.top,
         rcOrigTab.right, rcOrigTab.bottom);
 
@@ -635,5 +637,5 @@
 
   MapDialogRect(hwndDlg, &rcPage);
-  TRACE("biggest page %d %d %d %d\n", rcPage.left, rcPage.top,
+  TRACE("biggest page %ld %ld %ld %ld\n", rcPage.left, rcPage.top,
         rcPage.right, rcPage.bottom);
 
@@ -677,5 +679,5 @@
 
   MapDialogRect(hwndDlg, &rcPage);
-  TRACE("biggest page %d %d %d %d\n", rcPage.left, rcPage.top,
+  TRACE("biggest page %ld %ld %ld %ld\n", rcPage.left, rcPage.top,
         rcPage.right, rcPage.bottom);
 
@@ -748,5 +750,5 @@
   rc.right -= rc.left;
   rc.bottom -= rc.top;
-  TRACE("setting tab %08lx, rc (0,0)-(%d,%d)\n",
+  TRACE("setting tab %08lx, rc (0,0)-(%ld,%ld)\n",
         (DWORD)hwndTabCtrl, rc.right, rc.bottom);
   SetWindowPos(hwndTabCtrl, 0, 0, 0, rc.right, rc.bottom,
@@ -755,5 +757,5 @@
   GetClientRect(hwndTabCtrl, &rc);
 
-  TRACE("tab client rc %d %d %d %d\n",
+  TRACE("tab client rc %ld %ld %ld %ld\n",
         rc.left, rc.top, rc.right, rc.bottom);
 
@@ -764,5 +766,5 @@
    * Resize the property sheet.
    */
-  TRACE("setting dialog %08lx, rc (0,0)-(%d,%d)\n",
+  TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
         (DWORD)hwndDlg, rc.right, rc.bottom);
   SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
@@ -822,5 +824,5 @@
   }
 
-  TRACE("Biggest page %d %d %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
+  TRACE("Biggest page %ld %ld %ld %ld\n", rc.left, rc.top, rc.right, rc.bottom);
   TRACE("   constants padx=%d, pady=%d, butH=%d, lH=%d\n",
 	padding.x, padding.y, buttonHeight, lineHeight);
@@ -833,5 +835,5 @@
    * Resize the property sheet.
    */
-  TRACE("setting dialog %08lx, rc (0,0)-(%d,%d)\n",
+  TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
         (DWORD)hwndDlg, rc.right, rc.bottom);
   SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
@@ -1425,5 +1427,5 @@
 
       padding = PROPSHEET_GetPaddingInfoWizard(hwndParent, psInfo);
-      TRACE("setting page %08lx, rc (%d,%d)-(%d,%d) w=%d, h=%d, padx=%d, pady=%d\n",
+      TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d, padx=%d, pady=%d\n",
 	    (DWORD)hwndPage, rc.left, rc.top, rc.right, rc.bottom,
 	    pageWidth, pageHeight, padding.x, padding.y);
@@ -1441,5 +1443,5 @@
       pageWidth = rc.right - rc.left;
       pageHeight = rc.bottom - rc.top;
-      TRACE("setting page %08lx, rc (%d,%d)-(%d,%d) w=%d, h=%d\n",
+      TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d\n",
 	    (DWORD)hwndPage, rc.left, rc.top, rc.right, rc.bottom,
 	    pageWidth, pageHeight);
@@ -1617,5 +1619,4 @@
   HWND hwndPage;
   PSHNOTIFY psn;
-  LRESULT msgResult;
   PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg,
                                                     PropSheetInfoStr);
@@ -1651,7 +1652,12 @@
     if (hwndPage)
     {
-       msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
-       if (msgResult == PSNRET_INVALID_NOCHANGEPAGE)
-          return FALSE;
+       switch (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn))
+       {
+       case PSNRET_INVALID:
+           PROPSHEET_ShowPage(hwndDlg, i, psInfo);
+           /* fall through */
+       case PSNRET_INVALID_NOCHANGEPAGE:
+           return FALSE;
+       }
     }
   }
@@ -2385,5 +2391,5 @@
   PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR,
                                                        sizeof(PropSheetInfo));
-  int i, n;
+  UINT i, n;
   BYTE* pByte;
 
@@ -2429,5 +2435,5 @@
   PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR,
                                                        sizeof(PropSheetInfo));
-  int i, n;
+  UINT i, n;
   BYTE* pByte;
 
Index: trunk/src/comctl32/rebar.c
===================================================================
--- trunk/src/comctl32/rebar.c	(revision 10097)
+++ trunk/src/comctl32/rebar.c	(revision 10098)
@@ -1228,6 +1228,12 @@
 	infoPtr->hwndSelf, infoPtr->dwStyle,
 	x, y, width, height);
-    SetWindowPos (infoPtr->hwndSelf, 0, x, y, width, height,
-		    SWP_NOZORDER);
+
+//testestest
+#ifdef __WIN32OS2__
+//NOTE: this one is causing problems!!!!
+#endif
+//    SetWindowPos (infoPtr->hwndSelf, 0, x, y, width, height,
+//		    SWP_NOZORDER);
+//testestest
 }
 
Index: trunk/src/comctl32/smoothscroll.c
===================================================================
--- trunk/src/comctl32/smoothscroll.c	(revision 10097)
+++ trunk/src/comctl32/smoothscroll.c	(revision 10098)
@@ -3,4 +3,18 @@
  *
  * Copyright 2000 Marcus Meissner <marcus@jet.franken.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * TODO
@@ -12,7 +26,7 @@
 #include "winerror.h"
 #include "commctrl.h"
-#include "debugtools.h"
+#include "wine/debug.h"
 
-DEFAULT_DEBUG_CHANNEL(commctrl);
+WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
 
 static DWORD	smoothscroll = 2;
@@ -98,5 +112,5 @@
    }
 
-   FIXME("(hwnd=%x,flags=%lx,x2=%lx): should smooth scroll here.\n",
+   FIXME("(hwnd=%p,flags=%lx,x2=%lx): should smooth scroll here.\n",
 	   smooth->hwnd,flags,smooth->x2
    );
Index: trunk/src/comctl32/tab.c
===================================================================
--- trunk/src/comctl32/tab.c	(revision 10097)
+++ trunk/src/comctl32/tab.c	(revision 10098)
@@ -59,4 +59,6 @@
   INT        tabHeight;       /* height of the tab row */
   INT        tabWidth;        /* width of tabs */
+  USHORT     uHItemPadding;   /* amount of horizontal padding, in pixels */
+  USHORT     uVItemPadding;   /* amount of vertical padding, in pixels */
   HFONT      hFont;           /* handle to the current font */
   HCURSOR    hcurArrow;       /* handle to the current cursor */
@@ -81,6 +83,4 @@
  */
 #define SELECTED_TAB_OFFSET     2
-#define HORIZONTAL_ITEM_PADDING 6
-#define VERTICAL_ITEM_PADDING   3
 #define ROUND_CORNER_SIZE       2
 #define DISPLAY_AREA_PADDINGX   2
@@ -173,5 +173,5 @@
 	      iItem, ti->mask, ti->dwState, debugstr_w(ti->pszText),
 	      ti->iImage);
-	TRACE("tab %d, lParam=0x%08lx, rect.left=%d, rect.top(row)=%d\n",
+	TRACE("tab %d, lParam=0x%08lx, rect.left=%ld, rect.top(row)=%ld\n",
 	      iItem, ti->lParam, ti->rect.left, ti->rect.top);
     }
@@ -259,4 +259,15 @@
 }
 
+static LRESULT
+TAB_SetPadding (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+    
+    if (infoPtr == NULL) return 0;
+    infoPtr->uHItemPadding=LOWORD(lParam);
+    infoPtr->uVItemPadding=HIWORD(lParam);
+    return 0;
+}
+
 /******************************************************************************
  * TAB_InternalGetItemRect
@@ -367,5 +378,5 @@
 	     0);
   }
-  TRACE("item %d tab h=%d, rect=(%d,%d)-(%d,%d)\n",
+  TRACE("item %d tab h=%d, rect=(%ld,%ld)-(%ld,%ld)\n",
 	itemIndex, infoPtr->tabHeight,
 	itemRect->left, itemRect->top, itemRect->right, itemRect->bottom);
@@ -488,5 +499,5 @@
   if (isVisible)
   {
-      TRACE("invalidate (%d,%d)-(%d,%d)\n",
+      TRACE("invalidate (%ld,%ld)-(%ld,%ld)\n",
 	    selectedRect.left,selectedRect.top,
 	    selectedRect.right,selectedRect.bottom);
@@ -987,6 +998,6 @@
 					  controlPos.bottom - controlPos.top,
 					  hwnd,
-					  (HMENU)NULL,
-					  (HINSTANCE)NULL,
+					  NULL,
+					  NULL,
 					  NULL);
     }
@@ -994,5 +1005,5 @@
     {
       SetWindowPos(infoPtr->hwndUpDown,
-		   (HWND)NULL,
+		   NULL,
 		   controlPos.left, controlPos.top,
 		   controlPos.right - controlPos.left,
@@ -1100,5 +1111,5 @@
     /* Take the highest between font or icon */
     if (fontMetrics.tmHeight > icon_height)
-      item_height = fontMetrics.tmHeight;
+      item_height = fontMetrics.tmHeight + 2;
     else
       item_height = icon_height;
@@ -1108,18 +1119,13 @@
      * selected item + extra space for the selected item.
      */
-#ifdef __WIN32OS2__
-    //Code below doesn't always work
-    infoPtr->tabHeight = item_height + 2 * VERTICAL_ITEM_PADDING +
-        SELECTED_TAB_OFFSET;
-#else
     infoPtr->tabHeight = item_height + SELECTED_TAB_OFFSET +
 	                 ((lStyle & TCS_BUTTONS) ? 2 : 1) *
-                          VERTICAL_ITEM_PADDING;
-#endif
+                          infoPtr->uVItemPadding;
+
     TRACE("tabH=%d, tmH=%ld, iconh=%d\n",
 	  infoPtr->tabHeight, fontMetrics.tmHeight, icon_height);
   }
 
-  TRACE("client right=%d\n", clientRect.right);
+  TRACE("client right=%ld\n", clientRect.right);
 
   for (curItem = 0; curItem < infoPtr->uNumItem; curItem++)
@@ -1132,5 +1138,5 @@
       infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left +
                                            infoPtr->tabWidth +
-                                           2 * HORIZONTAL_ITEM_PADDING;
+                                           2 * infoPtr->uHItemPadding;
     }
     else
@@ -1157,6 +1163,6 @@
       infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left +
                                            size.cx + icon_width +
-                                           num * HORIZONTAL_ITEM_PADDING;
-      TRACE("for <%s>, l,r=%d,%d, num=%d\n",
+                                           num * infoPtr->uHItemPadding;
+      TRACE("for <%s>, l,r=%ld,%ld, num=%d\n",
 	  debugstr_w(infoPtr->items[curItem].pszText),
 	  infoPtr->items[curItem].rect.left,
@@ -1182,5 +1188,5 @@
 	infoPtr->items[curItem].rect.left = 0;
         curItemRowCount++;
-	TRACE("wrapping <%s>, l,r=%d,%d\n",
+	TRACE("wrapping <%s>, l,r=%ld,%ld\n",
 	    debugstr_w(infoPtr->items[curItem].pszText),
 	    infoPtr->items[curItem].rect.left,
@@ -1192,5 +1198,5 @@
 
     TRACE("TextSize: %li\n", size.cx);
-    TRACE("Rect: T %i, L %i, B %i, R %i\n",
+    TRACE("Rect: T %li, L %li, B %li, R %li\n",
 	  infoPtr->items[curItem].rect.top,
 	  infoPtr->items[curItem].rect.left,
@@ -1256,5 +1262,5 @@
           infoPtr->items[iItm].rect.left = 0;
 
-	  TRACE("r=%d, cl=%d, cl.r=%d, iCount=%d, iRow=%d, uNumRows=%d, remTab=%d, tabPerRow=%d\n",
+	  TRACE("r=%ld, cl=%d, cl.r=%ld, iCount=%d, iRow=%d, uNumRows=%d, remTab=%d, tabPerRow=%d\n",
 	      infoPtr->items[iItm].rect.right,
 	      curItemLeftPos, clientRect.right,
@@ -1305,5 +1311,5 @@
             curItemLeftPos = infoPtr->items[iItm].rect.right;
 
-	  TRACE("arranging <%s>, l,r=%d,%d, row=%d\n",
+	  TRACE("arranging <%s>, l,r=%ld,%ld, row=%ld\n",
 	      debugstr_w(infoPtr->items[iItm].pszText),
 	      infoPtr->items[iItm].rect.left,
@@ -1353,5 +1359,5 @@
               infoPtr->items[iIndex].rect.right += (iCount + 1) * widthDiff;
 
-	      TRACE("adjusting 1 <%s>, l,r=%d,%d\n",
+	      TRACE("adjusting 1 <%s>, l,r=%ld,%ld\n",
 		  debugstr_w(infoPtr->items[iIndex].pszText),
 		  infoPtr->items[iIndex].rect.left,
@@ -1366,5 +1372,5 @@
           infoPtr->items[iIndexStart].rect.right = clientRect.right - 4;
 
-	  TRACE("adjusting 2 <%s>, l,r=%d,%d\n",
+	  TRACE("adjusting 2 <%s>, l,r=%ld,%ld\n",
 	      debugstr_w(infoPtr->items[iIndexStart].pszText),
 	      infoPtr->items[iIndexStart].rect.left,
@@ -1483,12 +1489,4 @@
                      comctl32_color.clrHighlight : comctl32_color.clrBtnText);
 
-  /*
-   * Deflate the rectangle to acount for the padding
-   */
-  if(lStyle & TCS_VERTICAL)
-    InflateRect(drawRect, -VERTICAL_ITEM_PADDING, -HORIZONTAL_ITEM_PADDING);
-  else
-    InflateRect(drawRect, -HORIZONTAL_ITEM_PADDING, -VERTICAL_ITEM_PADDING);
-
 
   /*
@@ -1512,11 +1510,12 @@
     dis.itemID     = iItem;
     dis.itemAction = ODA_DRAWENTIRE;
+    dis.itemState = 0;
     if ( iItem == infoPtr->iSelected )
-      dis.itemState = ODS_SELECTED;
-    else
-      dis.itemState = 0;
+      dis.itemState |= ODS_SELECTED;
+    if (infoPtr->uFocus == iItem) 
+      dis.itemState |= ODS_FOCUS;
     dis.hwndItem = hwnd;		/* */
     dis.hDC      = hdc;
-    dis.rcItem   = *drawRect;		/* */
+    CopyRect(&dis.rcItem,drawRect);
     dis.itemData = infoPtr->items[iItem].lParam;
 
@@ -1544,4 +1543,12 @@
     RECT rcText;
     INT center_offset;
+
+    /*
+     * Deflate the rectangle to acount for the padding
+     */
+    if(lStyle & TCS_VERTICAL)
+      InflateRect(drawRect, -infoPtr->uVItemPadding, -infoPtr->uHItemPadding);
+    else
+      InflateRect(drawRect, -infoPtr->uHItemPadding, -infoPtr->uVItemPadding);
 
     /* set rcImage to drawRect, we will use top & left in our ImageList_Draw call */
@@ -1573,9 +1580,9 @@
 
       if(lStyle & TCS_VERTICAL)
-        center_offset = ((drawRect->bottom - drawRect->top) - (cy + HORIZONTAL_ITEM_PADDING + (rcText.right - rcText.left))) / 2;
+        center_offset = ((drawRect->bottom - drawRect->top) - (cy + infoPtr->uHItemPadding + (rcText.right - rcText.left))) / 2;
       else
-        center_offset = ((drawRect->right - drawRect->left) - (cx + HORIZONTAL_ITEM_PADDING + (rcText.right - rcText.left))) / 2;
-
-      TRACE("for <%s>, c_o=%d, draw=(%d,%d)-(%d,%d), textlen=%d\n",
+        center_offset = ((drawRect->right - drawRect->left) - (cx + infoPtr->uHItemPadding + (rcText.right - rcText.left))) / 2;
+
+      TRACE("for <%s>, c_o=%d, draw=(%ld,%ld)-(%ld,%ld), textlen=%ld\n",
 	  debugstr_w(infoPtr->items[iItem].pszText), center_offset,
 	  drawRect->left, drawRect->top, drawRect->right, drawRect->bottom,
@@ -1588,5 +1595,5 @@
                                              /* right side of the tab, but the image still uses the left as its x position */
                                              /* this keeps the image always drawn off of the same side of the tab */
-        drawRect->top = rcImage.top + (cx + HORIZONTAL_ITEM_PADDING);
+        drawRect->top = rcImage.top + (cx + infoPtr->uHItemPadding);
       }
       else if(lStyle & TCS_VERTICAL)
@@ -1594,14 +1601,14 @@
         rcImage.top = drawRect->bottom - cy - center_offset;
 	rcImage.left--;
-        drawRect->bottom = rcImage.top - HORIZONTAL_ITEM_PADDING;
+        drawRect->bottom = rcImage.top - infoPtr->uHItemPadding;
       }
       else /* normal style, whether TCS_BOTTOM or not */
       {
         rcImage.left = drawRect->left + center_offset + 3;
-        drawRect->left = rcImage.left + cx + HORIZONTAL_ITEM_PADDING;
+        drawRect->left = rcImage.left + cx + infoPtr->uHItemPadding;
 	rcImage.top -= (lStyle & TCS_BOTTOM) ? 2 : 1;
       }
 
-      TRACE("drawing image=%d, left=%d, top=%d\n",
+      TRACE("drawing image=%d, left=%ld, top=%ld\n",
 	    infoPtr->items[iItem].iImage, rcImage.left, rcImage.top-1);
       ImageList_Draw
@@ -1861,5 +1868,5 @@
 	  r.left += (1-ZZ);
 
-	  TRACE("<left> item=%d, fill=(%d,%d)-(%d,%d), edge=(%d,%d)-(%d,%d)\n",
+	  TRACE("<left> item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n",
 		iItem,
 		fillRect.left,fillRect.top,fillRect.right,fillRect.bottom,
@@ -1905,5 +1912,5 @@
 	  fillRect.right += (1-ZZ);
 
-	  TRACE("<left> item=%d, fill=(%d,%d)-(%d,%d), edge=(%d,%d)-(%d,%d)\n",
+	  TRACE("<left> item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n",
 		iItem,
 		fillRect.left,fillRect.top,fillRect.right,fillRect.bottom,
@@ -1962,5 +1969,5 @@
 	  r.top -= ZZ;
 
-	  TRACE("<bottom> item=%d, fill=(%d,%d)-(%d,%d), edge=(%d,%d)-(%d,%d)\n",
+	  TRACE("<bottom> item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n",
 		iItem,
 		fillRect.left,fillRect.top,fillRect.right,fillRect.bottom,
@@ -2007,5 +2014,5 @@
 	  fillRect.bottom += (1-ZZ);
 
-	  TRACE("<top> item=%d, fill=(%d,%d)-(%d,%d), edge=(%d,%d)-(%d,%d)\n",
+	  TRACE("<top> item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n",
 		iItem,
 		fillRect.left,fillRect.top,fillRect.right,fillRect.bottom,
@@ -2102,5 +2109,5 @@
   }
 
-  TRACE("border=(%d,%d)-(%d,%d)\n",
+  TRACE("border=(%ld,%ld)-(%ld,%ld)\n",
 	rect.left, rect.top, rect.right, rect.bottom);
 
@@ -2319,5 +2326,5 @@
   TAB_INFO* infoPtr)
 {
-  RECT clientRect;
+  RECT clientRect, r;
   DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   INT lastRow = infoPtr->uNumRows - 1;
@@ -2353,8 +2360,15 @@
                       ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) + 2;
   }
-
-  TRACE("invalidate (%d,%d)-(%d,%d)\n",
+  
+  /* Punch out the updown control */
+  if (infoPtr->needsScrolling && (clientRect.right > 0)) {
+    GetClientRect(infoPtr->hwndUpDown, &r);
+    clientRect.right = clientRect.right - (r.right - r.left);
+  }
+  
+  TRACE("invalidate (%ld,%ld)-(%ld,%ld)\n",
 	clientRect.left,clientRect.top,
 	clientRect.right,clientRect.bottom);
+ 
   InvalidateRect(hwnd, &clientRect, TRUE);
 }
@@ -2368,5 +2382,5 @@
   hdc = wParam== 0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
 
-  TRACE("erase %d, rect=(%d,%d)-(%d,%d)\n",
+  TRACE("erase %d, rect=(%ld,%ld)-(%ld,%ld)\n",
 	ps.fErase,
 	ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right,ps.rcPaint.bottom);
@@ -2392,5 +2406,5 @@
 
   GetClientRect (hwnd, &rect);
-  TRACE("Rect: %p T %i, L %i, B %i, R %i\n", hwnd,
+  TRACE("Rect: %p T %li, L %li, B %li, R %li\n", hwnd,
         rect.top, rect.left, rect.bottom, rect.right);
 
@@ -2467,5 +2481,5 @@
 
   GetClientRect (hwnd, &rect);
-  TRACE("Rect: %p T %i, L %i, B %i, R %i\n", hwnd,
+  TRACE("Rect: %p T %li, L %li, B %li, R %li\n", hwnd,
         rect.top, rect.left, rect.bottom, rect.right);
 
@@ -2543,6 +2557,7 @@
   {
     lResult = MAKELONG(infoPtr->tabWidth, infoPtr->tabHeight);
-    infoPtr->tabWidth = (INT)LOWORD(lParam);
-    infoPtr->tabHeight = (INT)HIWORD(lParam);
+    /* UNDOCUMENTED: If requested Width or Height is 0 this means that program wants to use default. */    
+    if (LOWORD(lParam)) infoPtr->tabWidth = (INT)LOWORD(lParam);
+    if (HIWORD(lParam)) infoPtr->tabHeight = (INT)HIWORD(lParam);
     TRACE("was h=%d,w=%d, now h=%d,w=%d\n",
 	  HIWORD(lResult), LOWORD(lResult),
@@ -2899,4 +2914,6 @@
   infoPtr->uNumItem        = 0;
   infoPtr->uNumRows        = 0;
+  infoPtr->uHItemPadding   = 6;
+  infoPtr->uVItemPadding   = 3;
   infoPtr->hFont           = 0;
   infoPtr->items           = 0;
@@ -2959,5 +2976,5 @@
   infoPtr->tabHeight = fontMetrics.tmHeight + SELECTED_TAB_OFFSET +
 	               ((dwStyle & TCS_BUTTONS) ? 2 : 1) *
-                        VERTICAL_ITEM_PADDING;
+                        infoPtr->uVItemPadding;
 
   /* Initialize the width of a tab. */
@@ -3073,6 +3090,5 @@
 
     case TCM_SETPADDING:
-      FIXME("Unimplemented msg TCM_SETPADDING\n");
-      return 0;
+      return TAB_SetPadding (hwnd, wParam, lParam);
 
     case TCM_GETROWCOUNT:
@@ -3202,5 +3218,5 @@
   wndClass.cbWndExtra    = sizeof(TAB_INFO *);
   wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
-  wndClass.hbrBackground = (HBRUSH)NULL;
+  wndClass.hbrBackground = NULL;
   wndClass.lpszClassName = WC_TABCONTROLA;
 
@@ -3212,4 +3228,4 @@
 TAB_Unregister (void)
 {
-    UnregisterClassA (WC_TABCONTROLA, (HINSTANCE)NULL);
-}
+    UnregisterClassA (WC_TABCONTROLA, NULL);
+}
Index: trunk/src/comctl32/toolbar.c
===================================================================
--- trunk/src/comctl32/toolbar.c	(revision 10097)
+++ trunk/src/comctl32/toolbar.c	(revision 10098)
@@ -30,5 +30,4 @@
  *
  * TODO:
- *   - A little bug in TOOLBAR_DrawMasked()
  *   - Button wrapping (under construction).
  *   - Messages.
@@ -97,4 +96,10 @@
 typedef struct
 {
+    HIMAGELIST himl;
+    INT id;
+} IMLENTRY, *PIMLENTRY;
+
+typedef struct
+{
     DWORD      dwStructSize;   /* size of TBBUTTON struct */
     INT      nHeight;        /* height of the toolbar */
@@ -125,7 +130,10 @@
     HFONT    hFont;           /* text font */
     HIMAGELIST himlInt;         /* image list created internally */
-    HIMAGELIST himlDef;         /* default image list */
-    HIMAGELIST himlHot;         /* hot image list */
-    HIMAGELIST himlDis;         /* disabled image list */
+    PIMLENTRY *himlDef;       /* default image list array */
+    INT       cimlDef;        /* default image list array count */
+    PIMLENTRY *himlHot;       /* hot image list array */
+    INT       cimlHot;        /* hot image list array count */
+    PIMLENTRY *himlDis;       /* disabled image list array */
+    INT       cimlDis;        /* disabled image list array count */
     HWND     hwndToolTip;     /* handle to tool tip control */
     HWND     hwndNotify;      /* handle to the window that gets notifications */
@@ -164,5 +172,5 @@
     BOOL     bVirtual;
     BOOL     bRemovable;
-    CHAR     text[64];
+    WCHAR    text[64];
 } CUSTOMBUTTON, *PCUSTOMBUTTON;
 
@@ -183,4 +191,17 @@
                         TBSTYLE_EX_HIDECLIPPEDBUTTONS)
 
+#define GETIBITMAP(infoPtr, i) (infoPtr->iVersion >= 5 ? LOWORD(i) : i)
+#define GETHIMLID(infoPtr, i) (infoPtr->iVersion >= 5 ? HIWORD(i) : 0)
+#define GETDEFIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDef, infoPtr->cimlDef, id)
+#define GETHOTIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlHot, infoPtr->cimlHot, id)
+#define GETDISIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDis, infoPtr->cimlDis, id)
+
+static BOOL TOOLBAR_GetButtonInfo(TOOLBAR_INFO *infoPtr, NMTOOLBARW *nmtb);
+static BOOL TOOLBAR_IsButtonRemovable(TOOLBAR_INFO *infoPtr, int iItem, PCUSTOMBUTTON btnInfo);
+static HIMAGELIST TOOLBAR_GetImageList(PIMLENTRY *pies, INT cies, INT id);
+static PIMLENTRY TOOLBAR_GetImageListEntry(PIMLENTRY *pies, INT cies, INT id);
+static VOID TOOLBAR_DeleteImageList(PIMLENTRY **pies, INT *cies);
+static HIMAGELIST TOOLBAR_InsertImageList(PIMLENTRY **pies, INT *cies, HIMAGELIST himl, INT id);
+
 static LRESULT
 TOOLBAR_NotifyFormat(TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam);
@@ -206,9 +227,9 @@
     if (TRACE_ON(toolbar)){
 	TRACE("button %d id %d, bitmap=%d, state=%02x, style=%02x, data=%08lx, stringid=0x%08x\n",
-	      btn_num, bP->idCommand,
-	      bP->iBitmap, bP->fsState, bP->fsStyle, bP->dwData, bP->iString);
+              btn_num, bP->idCommand, GETIBITMAP(infoPtr, bP->iBitmap), 
+              bP->fsState, bP->fsStyle, bP->dwData, bP->iString);
 	TRACE("string %s\n", debugstr_w(TOOLBAR_GetText(infoPtr,bP)));
 	if (internal)
-	    TRACE("button %d id %d, hot=%s, row=%d, rect=(%d,%d)-(%d,%d)\n",
+	    TRACE("button %d id %d, hot=%s, row=%d, rect=(%ld,%ld)-(%ld,%ld)\n",
 		  btn_num, bP->idCommand,
 		  (bP->bHot) ? "TRUE":"FALSE", bP->nRow,
@@ -309,4 +330,8 @@
 	      ret, nmgd.dwMask, infoPtr->nNumBitmaps);
     }
+
+    if (ret != I_IMAGENONE)
+        ret = GETIBITMAP(infoPtr, ret);
+
     return ret;
 }
@@ -316,6 +341,11 @@
 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
 {
-    if (((index>=0) && (index <= infoPtr->nNumBitmaps)) ||
-	(index == I_IMAGECALLBACK))
+    HIMAGELIST himl;
+    INT id = GETHIMLID(infoPtr, index);
+    INT iBitmap = GETIBITMAP(infoPtr, index);
+
+    if (((himl = GETDEFIMAGELIST(infoPtr, id)) &&
+        iBitmap >= 0 && iBitmap < ImageList_GetImageCount(himl)) ||
+        (index == I_IMAGECALLBACK))
       return TRUE;
     else
@@ -444,5 +474,5 @@
     InflateRect (&myrect, -2, 0);
 
-    TRACE("rect=(%d,%d)-(%d,%d)\n",
+    TRACE("rect=(%ld,%ld)-(%ld,%ld)\n",
 	  myrect.left, myrect.top, myrect.right, myrect.bottom);
 
@@ -500,5 +530,5 @@
     /* draw text */
     if (lpText) {
-	TRACE("string rect=(%d,%d)-(%d,%d)\n",
+	TRACE("string rect=(%ld,%ld)-(%ld,%ld)\n",
 	      rcText->left, rcText->top, rcText->right, rcText->bottom);
 
@@ -543,10 +573,7 @@
 		    HDC hdc, INT x, INT y)
 {
-    /* FIXME: this function is a hack since it uses image list
-	      internals directly */
-
-    HIMAGELIST himl = infoPtr->himlDef;
+    HIMAGELIST himl = GETDEFIMAGELIST(infoPtr, 0);
+    INT cx, cy;
     HBITMAP hbmMask;
-    HDC hdcImageList;
     HDC hdcMask;
 
@@ -554,31 +581,25 @@
 	return;
 
+    ImageList_GetIconSize(himl, &cx, &cy);
+
     /* create new dc's */
-    hdcImageList = CreateCompatibleDC (0);
     hdcMask = CreateCompatibleDC (0);
 
     /* create new bitmap */
-    hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
+    hbmMask = CreateBitmap (cx, cy, 1, 1, NULL);
     SelectObject (hdcMask, hbmMask);
 
     /* copy the mask bitmap */
-    SelectObject (hdcImageList, himl->hbmMask);
-    SetBkColor (hdcImageList, RGB(255, 255, 255));
-    SetTextColor (hdcImageList, RGB(0, 0, 0));
-    BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
-	      hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
+    ImageList_DrawEx(himl, btnPtr->iBitmap, hdcMask, 0, 0, 0, 0, RGB(255, 255, 255), RGB(0, 0, 0), ILD_MASK);
 
     /* draw the new mask */
     SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
-    BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
-	      hdcMask, 0, 0, 0xB8074A);
+    BitBlt (hdc, x+1, y+1, cx, cy, hdcMask, 0, 0, 0xB8074A);
 
     SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
-    BitBlt (hdc, x, y, himl->cx, himl->cy,
-	      hdcMask, 0, 0, 0xB8074A);
+    BitBlt (hdc, x, y, cx, cy, hdcMask, 0, 0, 0xB8074A);
 
     DeleteObject (hbmMask);
     DeleteDC (hdcMask);
-    DeleteDC (hdcImageList);
 }
 
@@ -613,4 +634,5 @@
     DWORD ntfret;
     INT offset;
+    HIMAGELIST himlDef;
 
     if (btnPtr->fsState & TBSTATE_HIDDEN)
@@ -646,5 +668,5 @@
         rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;
 
-    TRACE("iBitmap: %d, start=(%d,%d) w=%d, h=%d\n",
+    TRACE("iBitmap: %d, start=(%ld,%ld) w=%d, h=%d\n",
 	  btnPtr->iBitmap, rcBitmap.left, rcBitmap.top,
 	  infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
@@ -657,5 +679,5 @@
 	InflateRect (&rcText, -3, -3);
 
-	if (infoPtr->himlDef &&
+	if (GETDEFIMAGELIST(infoPtr, 0) &&
             TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
 	        /* The following test looked like this before
@@ -756,6 +778,10 @@
     }
 
+    /* Determine index of image list */
+    himlDef = GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr, btnPtr->iBitmap));
+
     /* disabled */
     if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
+	HIMAGELIST himlDis = GETDISIMAGELIST(infoPtr, GETHIMLID(infoPtr, btnPtr->iBitmap));
 	if (!(dwStyle & TBSTYLE_FLAT) && !(infoPtr->dwItemCDFlag & TBCDRF_NOEDGES))
 	{
@@ -773,5 +799,5 @@
 	}
 
-	if (!TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDis,
+	if (!TOOLBAR_DrawImageList (infoPtr, btnPtr, himlDis,
 				   hdc, rcBitmap.left, rcBitmap.top,
 				   ILD_NORMAL))
@@ -804,5 +830,5 @@
 	    TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
 
-	TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
+	TOOLBAR_DrawImageList (infoPtr, btnPtr, himlDef,
 			       hdc, rcBitmap.left+offset, rcBitmap.top+offset,
 			       ILD_NORMAL);
@@ -827,5 +853,5 @@
 	TOOLBAR_DrawPattern (hdc, &rc);
 
-	TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
+	TOOLBAR_DrawImageList (infoPtr, btnPtr, himlDef,
 			       hdc, rcBitmap.left+1, rcBitmap.top+1,
 			       ILD_NORMAL);
@@ -888,15 +914,17 @@
 
 	if (btnPtr->bHot) {
+            HIMAGELIST himlHot = GETHOTIMAGELIST(infoPtr, 
+                GETHIMLID(infoPtr, btnPtr->iBitmap));
 	    /* if hot, attempt to draw with himlHot, if fails, use himlDef */
 	    if (!TOOLBAR_DrawImageList (infoPtr, btnPtr,
-					infoPtr->himlHot,
+					himlHot,
 					hdc, rcBitmap.left,
 					rcBitmap.top, ILD_NORMAL))
-		TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
+		TOOLBAR_DrawImageList (infoPtr, btnPtr, himlDef,
 				       hdc, rcBitmap.left, rcBitmap.top,
 				       ILD_NORMAL);
 	}
 	else
-	    TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
+	    TOOLBAR_DrawImageList (infoPtr, btnPtr, himlDef,
 				   hdc, rcBitmap.left, rcBitmap.top,
 				   ILD_NORMAL);
@@ -916,5 +944,5 @@
 	}
 
-	TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
+	TOOLBAR_DrawImageList (infoPtr, btnPtr, himlDef,
 			       hdc, rcBitmap.left, rcBitmap.top,
 			       ILD_NORMAL);}
@@ -953,6 +981,10 @@
     /* if imagelist belongs to the app, it can be changed
        by the app after setting it */
-    if (infoPtr->himlDef != infoPtr->himlInt)
-        infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
+    if (GETDEFIMAGELIST(infoPtr, 0) != infoPtr->himlInt)
+    {
+        infoPtr->nNumBitmaps = 0;
+        for (i = 0; i < infoPtr->cimlDef; i++)
+            infoPtr->nNumBitmaps += ImageList_GetImageCount(infoPtr->himlDef[i]->himl);
+    }
 
     TOOLBAR_DumpToolbar (infoPtr, __LINE__);
@@ -1408,5 +1440,5 @@
               cx = sz.cx + 6 + 5 + 5;
 	      if ((dwStyle & TBSTYLE_LIST) &&
-		  (TOOLBAR_TestImageExist (infoPtr, btnPtr, infoPtr->himlDef)))
+		  (TOOLBAR_TestImageExist (infoPtr, btnPtr, GETDEFIMAGELIST(infoPtr,0))))
 		  cx += infoPtr->nBitmapWidth;
             }
@@ -1646,5 +1678,5 @@
 	    if (custInfo)
 	    {
-		char Buffer[256];
+		WCHAR Buffer[256];
 		int i = 0;
 		int index;
@@ -1658,18 +1690,22 @@
 		    return FALSE;
 
+		/* Send TBN_INITCUSTOMIZE notification */
+		if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_INITCUSTOMIZE) ==
+                    TBNRF_HIDEHELP)
+                {
+                    FIXME("TBNRF_HIDEHELP not supported\n");
+                }
+
 		/* add items to 'toolbar buttons' list and check if removable */
 		for (i = 0; i < custInfo->tbInfo->nNumButtons; i++)
-		{
+                {
 		    btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
-		    memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
-		    btnInfo->btn.fsStyle = TBSTYLE_SEP;
-		    btnInfo->bVirtual = FALSE;
-		    LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
+                    memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
+                    btnInfo->btn.fsStyle = TBSTYLE_SEP;
+                    btnInfo->bVirtual = FALSE;
+		    LoadStringW (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
 
 		    /* send TBN_QUERYDELETE notification */
-		    nmtb.iItem = i;
-		    btnInfo->bRemovable = TOOLBAR_SendNotify ((NMHDR *) &nmtb,
-						      infoPtr,
-						      TBN_QUERYDELETE);
+                    btnInfo->bRemovable = TOOLBAR_IsButtonRemovable(infoPtr, i, btnInfo);
 
 		    index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, 0);
@@ -1683,5 +1719,5 @@
 		btnInfo->bVirtual = FALSE;
 		btnInfo->bRemovable = TRUE;
-		LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
+		LoadStringW (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
 		index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
 		SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
@@ -1691,12 +1727,21 @@
 		{
 		    /* send TBN_GETBUTTONINFO notification */
+                    NMTOOLBARW nmtb;
 		    nmtb.iItem = i;
 		    nmtb.pszText = Buffer;
 		    nmtb.cchText = 256;
 
-		    if (!TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_GETBUTTONINFOA))
+                    /* Clear previous button's text */
+                    ZeroMemory(nmtb.pszText, nmtb.cchText * sizeof(WCHAR));
+
+                    if (!TOOLBAR_GetButtonInfo(infoPtr, &nmtb))
 			break;
 
-		    TRACE("style: %x\n", nmtb.tbButton.fsStyle);
+		    TRACE("WM_INITDIALOG style: %x iItem(%d) idCommand(%d) iString(%d) %s\n", 
+                        nmtb.tbButton.fsStyle, i, 
+                        nmtb.tbButton.idCommand,
+                        nmtb.tbButton.iString,
+                        nmtb.tbButton.iString >= 0 ? debugstr_w(infoPtr->strings[nmtb.tbButton.iString])
+                        : "");
 
 		    /* insert button into the apropriate list */
@@ -1705,21 +1750,28 @@
 		    {
 			btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
-			memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
 			btnInfo->bVirtual = FALSE;
 			btnInfo->bRemovable = TRUE;
-			if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
-			    strcpy (btnInfo->text, nmtb.pszText);
 
 			index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
-			SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
+			SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, 
+				LB_SETITEMDATA, index, (LPARAM)btnInfo);
 		    }
 		    else
 		    {
-			btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
-			memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
-			if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
-			    strcpy (btnInfo->text, nmtb.pszText);
-
-			SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
+                        btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, 
+                            IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
+                    }
+
+                    memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
+                    if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
+                    {
+                        if (lstrlenW(nmtb.pszText))
+                            lstrcpyW(btnInfo->text, nmtb.pszText);
+                        else if (nmtb.tbButton.iString >= 0 && 
+                            nmtb.tbButton.iString < infoPtr->nNumStrings)
+                        {
+                            lstrcpyW(btnInfo->text, 
+                                infoPtr->strings[nmtb.tbButton.iString]);
+                        }
 		    }
 		}
@@ -1734,5 +1786,5 @@
 		btnInfo->bVirtual = TRUE;
 		btnInfo->bRemovable = FALSE;
-		LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
+		LoadStringW (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
 		index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
 		SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
@@ -1882,10 +1934,15 @@
 
 			index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
+
+			if (LB_ERR == index)
+				break;
+
 			TRACE("Remove: index %d\n", index);
 
+			btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, 
+				LB_GETITEMDATA, index, 0);
+
 			/* send TBN_QUERYDELETE notification */
-			nmtb.iItem = index;
-		        if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
-					    TBN_QUERYDELETE))
+			if (TOOLBAR_IsButtonRemovable(infoPtr, index, btnInfo))
 			{
 			    btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
@@ -1990,4 +2047,5 @@
 	    {
 		LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
+    	DWORD dwStyle = GetWindowLongA (infoPtr->hwndSelf, GWL_STYLE);
 		RECT rcButton;
 		RECT rcText;
@@ -2032,11 +2090,15 @@
 
 		/* draw button */
+		if (!(dwStyle & TBSTYLE_FLAT))
 		DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
 
 		/* draw image and text */
-		if ((btnInfo->btn.fsStyle & TBSTYLE_SEP) == 0)
-		    ImageList_Draw (custInfo->tbInfo->himlDef, btnInfo->btn.iBitmap, lpdis->hDC,
-				    rcButton.left+3, rcButton.top+3, ILD_NORMAL);
-		DrawTextA (lpdis->hDC,  btnInfo->text, -1, &rcText,
+		if ((btnInfo->btn.fsStyle & TBSTYLE_SEP) == 0) {
+			HIMAGELIST himl = GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr, 
+				btnInfo->btn.iBitmap));
+		    ImageList_Draw (himl, GETIBITMAP(infoPtr, btnInfo->btn.iBitmap), 
+				lpdis->hDC, rcButton.left+3, rcButton.top+3, ILD_NORMAL);
+		}
+		DrawTextW (lpdis->hDC,  btnInfo->text, -1, &rcText,
 			       DT_LEFT | DT_VCENTER | DT_SINGLELINE);
 
@@ -2082,4 +2144,5 @@
     INT nIndex = 0, nButtons, nCount;
     HBITMAP hbmLoad;
+    HIMAGELIST himlDef;
 
     TRACE("hwnd=%p wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
@@ -2132,22 +2195,55 @@
     }
 
-    if (!(infoPtr->himlDef)) {
+    if (!infoPtr->cimlDef) {
 	/* create new default image list */
 	TRACE ("creating default image list!\n");
 
-	infoPtr->himlDef =
-	    ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
-			      ILC_COLOR | ILC_MASK, nButtons, 2);
-	infoPtr->himlInt = infoPtr->himlDef;
-    }
-
-    nCount = ImageList_GetImageCount(infoPtr->himlDef);
+    himlDef = ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight, 
+		ILC_COLOR | ILC_MASK, nButtons, 2);
+	TOOLBAR_InsertImageList(&infoPtr->himlDef, &infoPtr->cimlDef, himlDef, 0);
+    infoPtr->himlInt = himlDef;
+    }
+    else {
+        himlDef = GETDEFIMAGELIST(infoPtr, 0);
+    }
+
+    if (!himlDef) {
+        WARN("No default image list available\n");
+        return -1;
+    }
+
+    nCount = ImageList_GetImageCount(himlDef);
 
     /* Add bitmaps to the default image list */
-    if (lpAddBmp->hInst == (HINSTANCE)0)
+    if (lpAddBmp->hInst == NULL)
     {
-	nIndex =
-	    ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
-				 CLR_DEFAULT);
+       BITMAP  bmp;
+       HBITMAP hOldBitmapBitmap, hOldBitmapLoad;
+       HDC     hdcImage, hdcBitmap;
+
+       /* copy the bitmap before adding it so that the user's bitmap
+        * doesn't get modified.
+        */
+       GetObjectA ((HBITMAP)lpAddBmp->nID, sizeof(BITMAP), (LPVOID)&bmp);
+
+       hdcImage  = CreateCompatibleDC(0);
+       hdcBitmap = CreateCompatibleDC(0);
+
+       /* create new bitmap */
+       hbmLoad = CreateBitmap (bmp.bmWidth, bmp.bmHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
+       hOldBitmapBitmap = SelectObject(hdcBitmap, (HBITMAP)lpAddBmp->nID);
+       hOldBitmapLoad = SelectObject(hdcImage, hbmLoad);
+
+       /* Copy the user's image */
+       BitBlt (hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight,
+               hdcBitmap, 0, 0, SRCCOPY);
+
+       SelectObject (hdcImage, hOldBitmapLoad);
+       SelectObject (hdcBitmap, hOldBitmapBitmap);
+       DeleteDC (hdcImage);
+       DeleteDC (hdcBitmap);
+
+       nIndex = ImageList_AddMasked (himlDef, hbmLoad, CLR_DEFAULT);
+       DeleteObject (hbmLoad);
     }
     else if (lpAddBmp->hInst == HINST_COMMCTRL)
@@ -2159,5 +2255,5 @@
 		hbmLoad = LoadBitmapA (COMCTL32_hModule,
 				       MAKEINTRESOURCEA(IDB_STD_SMALL));
-		nIndex = ImageList_AddMasked (infoPtr->himlDef,
+		nIndex = ImageList_AddMasked (himlDef,
 					      hbmLoad, CLR_DEFAULT);
 		DeleteObject (hbmLoad);
@@ -2167,5 +2263,5 @@
 		hbmLoad = LoadBitmapA (COMCTL32_hModule,
 				       MAKEINTRESOURCEA(IDB_STD_LARGE));
-		nIndex = ImageList_AddMasked (infoPtr->himlDef,
+		nIndex = ImageList_AddMasked (himlDef,
 					      hbmLoad, CLR_DEFAULT);
 		DeleteObject (hbmLoad);
@@ -2175,5 +2271,5 @@
 		hbmLoad = LoadBitmapA (COMCTL32_hModule,
 				       MAKEINTRESOURCEA(IDB_VIEW_SMALL));
-		nIndex = ImageList_AddMasked (infoPtr->himlDef,
+		nIndex = ImageList_AddMasked (himlDef,
 					      hbmLoad, CLR_DEFAULT);
 		DeleteObject (hbmLoad);
@@ -2183,5 +2279,5 @@
 		hbmLoad = LoadBitmapA (COMCTL32_hModule,
 				       MAKEINTRESOURCEA(IDB_VIEW_LARGE));
-		nIndex = ImageList_AddMasked (infoPtr->himlDef,
+		nIndex = ImageList_AddMasked (himlDef,
 					      hbmLoad, CLR_DEFAULT);
 		DeleteObject (hbmLoad);
@@ -2191,5 +2287,5 @@
 		hbmLoad = LoadBitmapA (COMCTL32_hModule,
 				       MAKEINTRESOURCEA(IDB_HIST_SMALL));
-		nIndex = ImageList_AddMasked (infoPtr->himlDef,
+		nIndex = ImageList_AddMasked (himlDef,
 					      hbmLoad, CLR_DEFAULT);
 		DeleteObject (hbmLoad);
@@ -2199,5 +2295,5 @@
 		hbmLoad = LoadBitmapA (COMCTL32_hModule,
 				       MAKEINTRESOURCEA(IDB_HIST_LARGE));
-		nIndex = ImageList_AddMasked (infoPtr->himlDef,
+		nIndex = ImageList_AddMasked (himlDef,
 					      hbmLoad, CLR_DEFAULT);
 		DeleteObject (hbmLoad);
@@ -2205,5 +2301,5 @@
 
 	    default:
-	nIndex = ImageList_GetImageCount (infoPtr->himlDef);
+	nIndex = ImageList_GetImageCount (himlDef);
 		ERR ("invalid imagelist!\n");
 		break;
@@ -2213,5 +2309,5 @@
     {
 	hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
-	nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
+	nIndex = ImageList_AddMasked (himlDef, hbmLoad, CLR_DEFAULT);
 	DeleteObject (hbmLoad);
     }
@@ -2239,5 +2335,5 @@
     if (nIndex != -1)
     {
-       INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
+       INT imagecount = ImageList_GetImageCount(himlDef);
 
        if (infoPtr->nNumBitmaps + nButtons != imagecount)
@@ -2921,4 +3017,6 @@
     lpTbb->fsState   = btnPtr->fsState;
     lpTbb->fsStyle   = btnPtr->fsStyle;
+    lpTbb->bReserved[0] = 0;
+    lpTbb->bReserved[1] = 0;
     lpTbb->dwData    = btnPtr->dwData;
     lpTbb->iString   = btnPtr->iString;
@@ -3075,7 +3173,5 @@
 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
-
-    return (LRESULT)infoPtr->himlDis;
+    return (LRESULT)GETDISIMAGELIST(TOOLBAR_GetInfoPtr (hwnd), 0);
 }
 
@@ -3093,7 +3189,5 @@
 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
-
-    return (LRESULT)infoPtr->himlHot;
+    return (LRESULT)GETHOTIMAGELIST(TOOLBAR_GetInfoPtr (hwnd), 0);
 }
 
@@ -3115,9 +3209,7 @@
 
 static LRESULT
-TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
-
-    return (LRESULT)infoPtr->himlDef;
+TOOLBAR_GetDefImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    return (LRESULT) GETDEFIMAGELIST(TOOLBAR_GetInfoPtr(hwnd), 0);
 }
 
@@ -3168,5 +3260,5 @@
     lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
 
-    TRACE("maximum size %d x %d\n",
+    TRACE("maximum size %ld x %ld\n",
 	   infoPtr->rcBound.right - infoPtr->rcBound.left,
 	   infoPtr->rcBound.bottom - infoPtr->rcBound.top);
@@ -3680,4 +3772,5 @@
     HBITMAP hBitmap;
     int i = 0, nOldButtons = 0, pos = 0;
+    HIMAGELIST himlDef = 0;
 
     TRACE("hInstOld %p nIDOld %x hInstNew %p nIDNew %x nButtons %x\n",
@@ -3725,12 +3818,42 @@
     infoPtr->nNumBitmaps = infoPtr->nNumBitmaps - nOldButtons + lpReplace->nButtons;
 
-    /* ImageList_Replace(infoPtr->himlDef, pos, hBitmap, NULL); */
-
-
+    /* ImageList_Replace(GETDEFIMAGELIST(), pos, hBitmap, NULL); */
+
+
+    himlDef = GETDEFIMAGELIST(infoPtr, 0);
     for (i = pos + nOldButtons - 1; i >= pos; i--) {
-        ImageList_Remove(infoPtr->himlDef, i);
-    }
-
-    ImageList_AddMasked(infoPtr->himlDef, hBitmap, CLR_DEFAULT);
+        ImageList_Remove(himlDef, i);
+    }
+
+    {
+       BITMAP  bmp;
+       HBITMAP hOldBitmapBitmap, hOldBitmapLoad, hbmLoad;
+       HDC     hdcImage, hdcBitmap;
+
+       /* copy the bitmap before adding it so that the user's bitmap
+        * doesn't get modified.
+        */
+       GetObjectA (hBitmap, sizeof(BITMAP), (LPVOID)&bmp);
+
+       hdcImage  = CreateCompatibleDC(0);
+       hdcBitmap = CreateCompatibleDC(0);
+
+       /* create new bitmap */
+       hbmLoad = CreateBitmap (bmp.bmWidth, bmp.bmHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
+       hOldBitmapBitmap = SelectObject(hdcBitmap, hBitmap);
+       hOldBitmapLoad = SelectObject(hdcImage, hbmLoad);
+
+       /* Copy the user's image */
+       BitBlt (hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight,
+               hdcBitmap, 0, 0, SRCCOPY);
+
+       SelectObject (hdcImage, hOldBitmapLoad);
+       SelectObject (hdcBitmap, hOldBitmapBitmap);
+       DeleteDC (hdcImage);
+       DeleteDC (hdcBitmap);
+
+       ImageList_AddMasked (himlDef, hbmLoad, CLR_DEFAULT);
+       DeleteObject (hbmLoad);
+    }
 
     InvalidateRect(hwnd, NULL, FALSE);
@@ -3816,4 +3939,5 @@
 {
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
+    HIMAGELIST himlDef = GETDEFIMAGELIST(infoPtr, 0);
 
     if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
@@ -3829,8 +3953,9 @@
     infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
 
+
     /* uses image list internals directly */
-    if (infoPtr->himlDef) {
-        infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
-        infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
+    if (himlDef) {
+        himlDef->cx = infoPtr->nBitmapWidth;
+        himlDef->cy = infoPtr->nBitmapHeight;
     }
 
@@ -4020,14 +4145,13 @@
 {
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
+    HIMAGELIST himl = (HIMAGELIST)lParam;
     HIMAGELIST himlTemp;
-
-
-    if (wParam != 0) {
-	FIXME("no support for multiple image lists\n");
-	return 0;
-    }
-
-    himlTemp = infoPtr->himlDis;
-    infoPtr->himlDis = (HIMAGELIST)lParam;
+    INT id = 0;
+
+    if (infoPtr->iVersion >= 5)
+        id = wParam;
+
+    himlTemp = TOOLBAR_InsertImageList(&infoPtr->himlDis, 
+        &infoPtr->cimlDis, himl, id);
 
     /* FIXME: redraw ? */
@@ -4081,12 +4205,12 @@
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
     HIMAGELIST himlTemp;
-
-    if (wParam != 0) {
-	FIXME("no support for multiple image lists\n");
-	return 0;
-    }
-
-    himlTemp = infoPtr->himlHot;
-    infoPtr->himlHot = (HIMAGELIST)lParam;
+    HIMAGELIST himl = (HIMAGELIST)lParam;
+    INT id = 0;
+
+    if (infoPtr->iVersion >= 5)
+        id = wParam;
+
+    himlTemp = TOOLBAR_InsertImageList(&infoPtr->himlHot, 
+        &infoPtr->cimlHot, himl, id);
 
     /* FIXME: redraw ? */
@@ -4138,16 +4262,18 @@
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
     HIMAGELIST himlTemp;
-
-    if (wParam != 0) {
-	FIXME("no support for multiple image lists\n");
-	return 0;
-    }
-
-    himlTemp = infoPtr->himlDef;
-    infoPtr->himlDef = (HIMAGELIST)lParam;
-
-    infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
-
-    ImageList_GetIconSize(infoPtr->himlDef, &infoPtr->nBitmapWidth,
+    HIMAGELIST himl = (HIMAGELIST)lParam;
+    INT i, id = 0;
+
+    if (infoPtr->iVersion >= 5)
+        id = wParam;
+
+    himlTemp = TOOLBAR_InsertImageList(&infoPtr->himlDef, 
+        &infoPtr->cimlDef, himl, id);
+
+    infoPtr->nNumBitmaps = 0;
+    for (i = 0; i < infoPtr->cimlDef; i++)
+        infoPtr->nNumBitmaps += ImageList_GetImageCount(infoPtr->himlDef[i]->himl);
+
+    ImageList_GetIconSize(himl, &infoPtr->nBitmapWidth,
 			  &infoPtr->nBitmapHeight);
     TRACE("hwnd %p, new himl=%08x, count=%d, bitmap w=%d, h=%d\n",
@@ -4407,4 +4533,7 @@
 
     infoPtr->iVersion = iVersion;
+
+    if (infoPtr->iVersion >= 5)
+        TOOLBAR_SetUnicodeFormat(hwnd, (WPARAM)TRUE, (LPARAM)0);
 
     return iOldVersion;
@@ -4497,5 +4626,5 @@
 	    GetWindowRect(hwnd, &rc);
 	    MapWindowPoints(0, hwndParent, (LPPOINT)&rc, 2);
-	    TRACE("mapped to (%d,%d)-(%d,%d)\n",
+	    TRACE("mapped to (%ld,%ld)-(%ld,%ld)\n",
 		rc.left, rc.top, rc.right, rc.bottom);
 	    lpsize->cx = max(rc.right-rc.left,
@@ -4617,4 +4746,8 @@
     if (infoPtr->himlInt)
 	ImageList_Destroy (infoPtr->himlInt);
+
+	TOOLBAR_DeleteImageList(&infoPtr->himlDef, &infoPtr->cimlDef);
+	TOOLBAR_DeleteImageList(&infoPtr->himlDis, &infoPtr->cimlDis);
+	TOOLBAR_DeleteImageList(&infoPtr->himlHot, &infoPtr->cimlHot);
 
     /* delete default font */
@@ -5312,5 +5445,5 @@
     hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
 
-    TRACE("psrect=(%d,%d)-(%d,%d)\n",
+    TRACE("psrect=(%ld,%ld)-(%ld,%ld)\n",
 	  ps.rcPaint.left, ps.rcPaint.top,
 	  ps.rcPaint.right, ps.rcPaint.bottom);
@@ -5568,5 +5701,5 @@
 
 	case TB_GETIMAGELIST:
-	    return TOOLBAR_GetImageList (hwnd, wParam, lParam);
+	    return TOOLBAR_GetDefImageList (hwnd, wParam, lParam);
 
 /*	case TB_GETINSERTMARK:			*/ /* 4.71 */
@@ -5874,4 +6007,126 @@
 TOOLBAR_Unregister (void)
 {
-    UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);
-}
+    UnregisterClassA (TOOLBARCLASSNAMEA, NULL);
+}
+
+static HIMAGELIST TOOLBAR_InsertImageList(PIMLENTRY **pies, INT *cies, HIMAGELIST himl, INT id)
+{
+    HIMAGELIST himlold;
+    PIMLENTRY c = NULL;
+
+    /* Check if the entry already exists */
+    c = TOOLBAR_GetImageListEntry(*pies, *cies, id);
+
+    /* If this is a new entry we must create it and insert into the array */
+    if (!c)
+    {
+        PIMLENTRY *pnies;
+
+	c = (PIMLENTRY) COMCTL32_Alloc(sizeof(IMLENTRY));
+	c->id = id;
+
+	pnies = COMCTL32_Alloc((*cies + 1) * sizeof(PIMLENTRY));
+	memcpy(pnies, *pies, ((*cies) * sizeof(PIMLENTRY)));
+	pnies[*cies] = c;
+	(*cies)++;
+
+	COMCTL32_Free(*pies);
+	*pies = pnies;
+    }
+
+    himlold = c->himl;
+    c->himl = himl;
+
+    return himlold;
+}
+
+
+static VOID TOOLBAR_DeleteImageList(PIMLENTRY **pies, INT *cies)
+{
+    int i;
+
+    for (i = 0; i < *cies; i++)
+	COMCTL32_Free((*pies)[i]);
+
+    COMCTL32_Free(*pies);
+
+    *cies = 0;
+    *pies = NULL;
+}
+
+
+static PIMLENTRY TOOLBAR_GetImageListEntry(PIMLENTRY *pies, INT cies, INT id)
+{
+    PIMLENTRY c = NULL;
+
+    if (pies != NULL)
+    {
+	int i;
+
+        for (i = 0; i < cies; i++)
+        {
+            if (pies[i]->id == id)
+            {
+                c = pies[i];
+                break;
+            }
+        }
+    }
+
+    return c;
+}
+
+
+static HIMAGELIST TOOLBAR_GetImageList(PIMLENTRY *pies, INT cies, INT id)
+{
+    HIMAGELIST himlDef = 0;
+    PIMLENTRY pie = TOOLBAR_GetImageListEntry(pies, cies, id);
+
+    if (pie)
+        himlDef = pie->himl;
+
+    return himlDef;
+}
+
+
+static BOOL TOOLBAR_GetButtonInfo(TOOLBAR_INFO *infoPtr, NMTOOLBARW *nmtb)
+{
+    if (infoPtr->bUnicode)
+        return TOOLBAR_SendNotify ((NMHDR *) nmtb, infoPtr, TBN_GETBUTTONINFOW);
+    else
+    {
+        CHAR Buffer[256];
+        NMTOOLBARA nmtba;
+        BOOL bRet = FALSE;
+
+        nmtba.iItem = nmtb->iItem;
+        nmtba.pszText = Buffer;
+        nmtba.cchText = 256;
+        ZeroMemory(nmtba.pszText, nmtba.cchText);
+
+        if (TOOLBAR_SendNotify ((NMHDR *) &nmtba, infoPtr, TBN_GETBUTTONINFOA))
+        {
+            int ccht = strlen(nmtba.pszText);
+            if (ccht)
+               MultiByteToWideChar(CP_ACP, 0, (LPCSTR)nmtba.pszText, -1, 
+                  nmtb->pszText, nmtb->cchText);
+
+            memcpy(&nmtb->tbButton, &nmtba.tbButton, sizeof(TBBUTTON));
+            bRet = TRUE;
+        }
+
+        return bRet;
+    }
+}
+
+
+static BOOL TOOLBAR_IsButtonRemovable(TOOLBAR_INFO *infoPtr,
+	int iItem, PCUSTOMBUTTON btnInfo)
+{
+    NMTOOLBARA nmtb;
+
+    nmtb.iItem = iItem;
+    memcpy(&nmtb.tbButton, &btnInfo->btn, sizeof(TBBUTTON));
+
+    return TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_QUERYDELETE);
+}
Index: trunk/src/comctl32/tooltips.c
===================================================================
--- trunk/src/comctl32/tooltips.c	(revision 10097)
+++ trunk/src/comctl32/tooltips.c	(revision 10098)
@@ -2102,7 +2102,5 @@
         return 0;
 
-#ifdef __WIN32OS2__
     if(infoPtr->hFont) DeleteObject (infoPtr->hFont);
-#endif
 
     infoPtr->hFont = CreateFontIndirectW(&lf);
Index: trunk/src/comctl32/trackbar.c
===================================================================
--- trunk/src/comctl32/trackbar.c	(revision 10098)
+++ trunk/src/comctl32/trackbar.c	(revision 10098)
@@ -0,0 +1,1745 @@
+/*
+ * Trackbar control
+ *
+ * Copyright 1998, 1999 Eric Kohl
+ * Copyright 1998, 1999 Alex Priem
+ * Copyright 2002 Dimitrie O. Paun
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * NOTE
+ * 
+ * This code was audited for completeness against the documented features
+ * of Comctl32.dll version 6.0 on Sep. 12, 2002, by Dimitrie O. Paun.
+ * 
+ * Unless otherwise noted, we believe this code to be complete, as per
+ * the specification mentioned above.
+ * If you discover missing features, or bugs, please note them below.
+ * 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "winbase.h"
+#include "commctrl.h"
+#include "wine/debug.h"
+
+#include "comctl32.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(trackbar);
+
+typedef struct
+{
+    HWND hwndSelf;
+    LONG lRangeMin;
+    LONG lRangeMax;
+    LONG lLineSize;
+    LONG lPageSize;
+    LONG lSelMin;
+    LONG lSelMax;
+    LONG lPos;
+    UINT uThumbLen;
+    UINT uNumTics;
+    UINT uTicFreq;
+    HWND hwndNotify;
+    HWND hwndToolTip;
+    HWND hwndBuddyLA;
+    HWND hwndBuddyRB;
+    INT  fLocation;
+    INT  flags;
+    BOOL bUnicode;
+    RECT rcChannel;
+    RECT rcSelection;
+    RECT rcThumb;
+    LPLONG tics;
+} TRACKBAR_INFO;
+
+#define TB_REFRESH_TIMER	1
+#define TB_REFRESH_DELAY	500
+
+#define TOOLTIP_OFFSET		2     /* distance from ctrl edge to tooltip */
+
+/* Used by TRACKBAR_Refresh to find out which parts of the control
+   need to be recalculated */
+
+#define TB_THUMBPOSCHANGED      1
+#define TB_THUMBSIZECHANGED     2
+#define TB_THUMBCHANGED 	(TB_THUMBPOSCHANGED | TB_THUMBSIZECHANGED)
+#define TB_SELECTIONCHANGED     4
+#define TB_DRAG_MODE            8     /* we're dragging the slider */
+#define TB_AUTO_PAGE_LEFT	16
+#define TB_AUTO_PAGE_RIGHT	32
+#define TB_AUTO_PAGE		(TB_AUTO_PAGE_LEFT | TB_AUTO_PAGE_RIGHT)
+
+/* helper defines for TRACKBAR_DrawTic */
+#define TIC_EDGE                0x20
+#define TIC_SELECTIONMARKMAX    0x80
+#define TIC_SELECTIONMARKMIN    0x100
+#define TIC_SELECTIONMARK       (TIC_SELECTIONMARKMAX | TIC_SELECTIONMARKMIN)
+
+static BOOL TRACKBAR_SendNotify (TRACKBAR_INFO *infoPtr, UINT code);
+
+static inline int 
+notify_customdraw(NMCUSTOMDRAW *pnmcd, int stage)
+{
+    pnmcd->dwDrawStage = stage;
+    return SendMessageW (GetParent(pnmcd->hdr.hwndFrom), WM_NOTIFY, 
+		         pnmcd->hdr.idFrom, (LPARAM)pnmcd);
+}
+
+static void TRACKBAR_RecalculateTics (TRACKBAR_INFO *infoPtr)
+{
+    int i, tic, nrTics;
+
+    if (infoPtr->uTicFreq && infoPtr->lRangeMax >= infoPtr->lRangeMin)
+    	nrTics=(infoPtr->lRangeMax - infoPtr->lRangeMin)/infoPtr->uTicFreq;
+    else {
+        nrTics = 0;
+        COMCTL32_Free (infoPtr->tics);
+        infoPtr->tics = NULL;
+        infoPtr->uNumTics = 0;
+        return;
+    }
+
+    if (nrTics != infoPtr->uNumTics) {
+    	infoPtr->tics=COMCTL32_ReAlloc (infoPtr->tics,
+                                        (nrTics+1)*sizeof (DWORD));
+	if (!infoPtr->tics) {
+	    infoPtr->uNumTics = 0;
+	    TRACKBAR_SendNotify(infoPtr, NM_OUTOFMEMORY);
+	    return;
+	}
+    	infoPtr->uNumTics = nrTics;
+    }
+
+    tic = infoPtr->lRangeMin + infoPtr->uTicFreq;
+    for (i = 0; i < nrTics; i++, tic += infoPtr->uTicFreq)
+        infoPtr->tics[i] = tic;
+}
+
+/* converts from physical (mouse) position to logical position
+   (in range of trackbar) */
+
+static inline LONG
+TRACKBAR_ConvertPlaceToPosition (TRACKBAR_INFO *infoPtr, int place,
+                                 int vertical)
+{
+    double range, width, pos;
+
+    range = infoPtr->lRangeMax - infoPtr->lRangeMin;
+    if (vertical) {
+    	width = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top;
+        pos = (range*(place - infoPtr->rcChannel.top)) / width;
+    } else {
+    	width = infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+        pos = (range*(place - infoPtr->rcChannel.left)) / width;
+    }
+    pos += infoPtr->lRangeMin;
+    if (pos > infoPtr->lRangeMax)
+        pos = infoPtr->lRangeMax;
+    else if (pos < infoPtr->lRangeMin)
+        pos = infoPtr->lRangeMin;
+
+    TRACE("%.2f\n", pos);
+    return (LONG)(pos + 0.5);
+}
+
+
+/* return: 0> prev, 0 none, >0 next */
+static LONG
+TRACKBAR_GetAutoPageDirection (TRACKBAR_INFO *infoPtr, POINT clickPoint)
+{
+    DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
+    RECT pageRect;
+
+    if (dwStyle & TBS_VERT) {
+	pageRect.top = infoPtr->rcChannel.top;
+	pageRect.bottom = infoPtr->rcChannel.bottom;
+	pageRect.left = infoPtr->rcThumb.left;
+	pageRect.right = infoPtr->rcThumb.right;
+    } else {
+	pageRect.top = infoPtr->rcThumb.top;
+	pageRect.bottom = infoPtr->rcThumb.bottom;
+	pageRect.left = infoPtr->rcChannel.left;
+	pageRect.right = infoPtr->rcChannel.right;
+    }
+
+
+    if (PtInRect(&pageRect, clickPoint))
+    {
+	int clickPlace = (dwStyle & TBS_VERT) ? clickPoint.y : clickPoint.x;
+
+        LONG clickPos = TRACKBAR_ConvertPlaceToPosition(infoPtr, clickPlace,
+                                                        dwStyle & TBS_VERT);
+	return clickPos - infoPtr->lPos;
+    }
+
+    return 0;
+}
+
+static void inline
+TRACKBAR_PageUp (TRACKBAR_INFO *infoPtr)
+{
+    if (infoPtr->lPos == infoPtr->lRangeMax) return;
+
+    infoPtr->lPos += infoPtr->lPageSize;
+    if (infoPtr->lPos > infoPtr->lRangeMax)
+	infoPtr->lPos = infoPtr->lRangeMax;
+    TRACKBAR_SendNotify (infoPtr, TB_PAGEUP);
+}
+
+
+static void inline
+TRACKBAR_PageDown (TRACKBAR_INFO *infoPtr)
+{
+    if (infoPtr->lPos == infoPtr->lRangeMin) return;
+
+    infoPtr->lPos -= infoPtr->lPageSize;
+    if (infoPtr->lPos < infoPtr->lRangeMin)
+        infoPtr->lPos = infoPtr->lRangeMin;
+    TRACKBAR_SendNotify (infoPtr, TB_PAGEDOWN);
+}
+
+static void
+TRACKBAR_CalcChannel (TRACKBAR_INFO *infoPtr)
+{
+    DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
+    INT cyChannel, offsetthumb, offsetedge;
+    RECT lpRect, *channel = & infoPtr->rcChannel;
+
+    GetClientRect (infoPtr->hwndSelf, &lpRect);
+
+    offsetthumb = (int)(infoPtr->uThumbLen/4.5);
+    offsetedge  = offsetthumb + 3;
+    cyChannel   = (dwStyle & TBS_ENABLESELRANGE) ? (offsetthumb+1)*3 : 4;
+
+    if (dwStyle & TBS_VERT) {
+        channel->top    = lpRect.top + offsetedge;
+        channel->bottom = lpRect.bottom - offsetedge;
+        channel->left = lpRect.left + offsetthumb;
+        if (dwStyle & (TBS_BOTH | TBS_LEFT))
+            channel->left += (lpRect.right-lpRect.left-offsetthumb-cyChannel)/2;
+        channel->right = channel->left + cyChannel;
+    } else {
+        channel->left = lpRect.left + offsetedge;
+        channel->right = lpRect.right - offsetedge;
+        channel->top = lpRect.top + offsetthumb;
+        if (dwStyle & (TBS_BOTH | TBS_TOP))
+            channel->top += (lpRect.bottom-lpRect.top-offsetedge-cyChannel)/2;
+        channel->bottom   = channel->top + cyChannel;
+    }
+}
+
+static void
+TRACKBAR_CalcThumb (TRACKBAR_INFO *infoPtr, LONG lPos, RECT *thumb)
+{
+    int range, width, thumbdepth;
+    DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
+    RECT lpRect;
+
+    range=infoPtr->lRangeMax - infoPtr->lRangeMin;
+    thumbdepth = ((int)(infoPtr->uThumbLen / 4.5) * 2) + 2;
+
+    if (!range) range = 1;
+
+    GetClientRect(infoPtr->hwndSelf, &lpRect);
+
+    if (dwStyle & TBS_VERT)
+    {
+    	width=infoPtr->rcChannel.bottom - infoPtr->rcChannel.top;
+
+        if (dwStyle & (TBS_BOTH | TBS_LEFT))
+            thumb->left = (lpRect.right - lpRect.bottom - infoPtr->uThumbLen)/2;
+        else
+            thumb->left = 2;
+        thumb->right = thumb -> left + infoPtr->uThumbLen;
+        thumb->top = infoPtr->rcChannel.top +
+                     (width*(lPos - infoPtr->lRangeMin))/range -
+                     thumbdepth/2;
+        thumb->bottom = thumb->top + thumbdepth;
+    }
+    else
+    {
+    	width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+
+        thumb->left = infoPtr->rcChannel.left +
+                      (width*(lPos - infoPtr->lRangeMin))/range -
+                      thumbdepth/2;
+        thumb->right = thumb->left + thumbdepth;
+        if (dwStyle & (TBS_BOTH | TBS_TOP))
+            thumb->top = (lpRect.bottom - lpRect.top - infoPtr->uThumbLen)/2;
+        else
+            thumb->top = 2;
+        thumb->bottom = thumb->top + infoPtr->uThumbLen;
+    }
+}
+
+inline static void
+TRACKBAR_UpdateThumb (TRACKBAR_INFO *infoPtr)
+{
+    TRACKBAR_CalcThumb(infoPtr, infoPtr->lPos, &infoPtr->rcThumb);
+}
+
+static inline void
+TRACKBAR_InvalidateAll(TRACKBAR_INFO * infoPtr)
+{
+    InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
+}
+
+static void
+TRACKBAR_InvalidateThumb (TRACKBAR_INFO *infoPtr, LONG thumbPos)
+{
+    RECT rcThumb;
+
+    TRACKBAR_CalcThumb(infoPtr, thumbPos, &rcThumb);
+    InflateRect(&rcThumb, 1, 1);
+    InvalidateRect(infoPtr->hwndSelf, &rcThumb, FALSE);
+}
+
+static inline void
+TRACKBAR_InvalidateThumbMove (TRACKBAR_INFO *infoPtr, LONG oldPos, LONG newPos)
+{
+    TRACKBAR_InvalidateThumb (infoPtr, oldPos);
+    if (newPos != oldPos)
+        TRACKBAR_InvalidateThumb (infoPtr, newPos);
+}
+
+static BOOL inline
+TRACKBAR_HasSelection (TRACKBAR_INFO *infoPtr)
+{
+    return infoPtr->lSelMin != infoPtr->lSelMax;
+}
+
+static void
+TRACKBAR_CalcSelection (TRACKBAR_INFO *infoPtr)
+{
+    RECT *selection = &infoPtr->rcSelection;
+    int range = infoPtr->lRangeMax - infoPtr->lRangeMin;
+
+    if (range <= 0) {
+        SetRectEmpty (selection);
+    } else {
+        if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_VERT) {
+            int height = infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+            selection->top    = infoPtr->rcChannel.top +
+                (height*infoPtr->lSelMin)/range;
+            selection->bottom = infoPtr->rcChannel.top +
+                (height*infoPtr->lSelMax)/range;
+            selection->left   = infoPtr->rcChannel.left + 3;
+            selection->right  = infoPtr->rcChannel.right - 3;
+        } else {
+            int width = infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+            selection->left   = infoPtr->rcChannel.left +
+                (width*infoPtr->lSelMin)/range;
+            selection->right  = infoPtr->rcChannel.left +
+                (width*infoPtr->lSelMax)/range;
+            selection->top    = infoPtr->rcChannel.top + 3;
+            selection->bottom = infoPtr->rcChannel.bottom - 3;
+        }
+    }
+
+    TRACE("selection[left=%ld, top=%ld, right=%ld, bottom=%ld]\n",
+	   selection->left, selection->top, selection->right, selection->bottom);
+}
+
+static BOOL
+TRACKBAR_AutoPage (TRACKBAR_INFO *infoPtr, POINT clickPoint)
+{
+    LONG dir = TRACKBAR_GetAutoPageDirection(infoPtr, clickPoint);
+    LONG prevPos = infoPtr->lPos;
+
+    TRACE("x=%ld, y=%ld, dir=%ld\n", clickPoint.x, clickPoint.y, dir);
+
+    if (dir > 0 && (infoPtr->flags & TB_AUTO_PAGE_RIGHT))
+	TRACKBAR_PageUp(infoPtr);
+    else if (dir < 0 && (infoPtr->flags & TB_AUTO_PAGE_LEFT))
+	TRACKBAR_PageDown(infoPtr);
+    else return FALSE;
+
+    infoPtr->flags |= TB_THUMBPOSCHANGED;
+    TRACKBAR_InvalidateThumbMove (infoPtr, prevPos, infoPtr->lPos);
+
+    return TRUE;
+}
+
+/* Trackbar drawing code. I like my spaghetti done milanese.  */
+
+static void
+TRACKBAR_DrawChannel (TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle)
+{
+    RECT rcChannel = infoPtr->rcChannel;
+
+    DrawEdge (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
+    if (dwStyle & TBS_ENABLESELRANGE) {		 /* fill the channel */
+        FillRect (hdc, &rcChannel, GetStockObject(WHITE_BRUSH));
+	if (TRACKBAR_HasSelection(infoPtr))
+	    FillRect (hdc, &infoPtr->rcSelection, GetSysColorBrush(COLOR_HIGHLIGHT));
+    }
+}
+
+static void
+TRACKBAR_DrawOneTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
+{
+    int x, y, ox, oy, range, side, offset = 5, indent = 0, len = 3;
+    RECT rcTics;
+
+    TRACE("\n");
+
+    GetClientRect(infoPtr->hwndSelf, &rcTics);
+    if (flags & TBS_VERT) {
+	rcTics.top    = infoPtr->rcChannel.top;
+	rcTics.bottom = infoPtr->rcChannel.bottom;
+    } else {
+	rcTics.left   = infoPtr->rcChannel.left;
+	rcTics.right  = infoPtr->rcChannel.right;
+    }
+
+    if (flags & (TBS_TOP | TBS_LEFT)) {
+	x = rcTics.left;
+	y = rcTics.top;
+	side = -1;
+    } else {
+  	x = rcTics.right;
+  	y = rcTics.bottom;
+	side = 1;
+    }
+
+    range = infoPtr->lRangeMax - infoPtr->lRangeMin;
+    if (range == 0)
+      range = 1; /* to avoid division by zero */
+
+    if (flags & TIC_SELECTIONMARK) {
+  	indent = (flags & TIC_SELECTIONMARKMIN) ? -1 : 1;
+    } else if (flags & TIC_EDGE) {
+	len++;
+    }
+
+    if (flags & TBS_VERT) {
+	int height = rcTics.bottom = rcTics.top;
+	y = rcTics.top + (height*(ticPos - infoPtr->lRangeMin))/range;
+	x -= (offset + 2) * side;
+	y += indent;
+    } else {
+        int width = rcTics.right - rcTics.left;
+        x = rcTics.left + (width*(ticPos - infoPtr->lRangeMin))/range;
+	x += indent;
+	y -= (offset + 2) * side;
+    }
+
+    ox = x;
+    oy = y;
+    MoveToEx(hdc, x, y, 0);
+    if (flags & TBS_VERT) x += len * side;
+    else y += len * side;
+    LineTo(hdc, x, y);
+	    
+    if (flags & TIC_SELECTIONMARK) {
+	if (flags & TBS_VERT) {
+	    x -= side;
+	} else {
+	    y -= side;
+	}
+	MoveToEx(hdc, x, y, 0);
+	if (flags & TBS_VERT) {
+	    y += 2 * indent;
+	} else {
+	    x += 2 * indent;
+	}
+	
+	LineTo(hdc, x, y);
+	LineTo(hdc, ox, oy);
+    }
+}
+
+
+static inline void
+TRACKBAR_DrawTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
+{
+    if ((flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH))
+        TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags | TBS_LEFT);
+
+    if (!(flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH))
+        TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags);
+}
+
+static void
+TRACKBAR_DrawTics (TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle)
+{
+    int i, ticFlags = dwStyle & 0x0f;
+    LOGPEN ticPen = { PS_SOLID, {1, 0}, GetSysColor (COLOR_3DDKSHADOW) };
+    HPEN hOldPen, hTicPen;
+    
+    /* create the pen to draw the tics with */   
+    hTicPen = CreatePenIndirect(&ticPen);
+    hOldPen = hTicPen ? SelectObject(hdc, hTicPen) : 0;
+
+    /* actually draw the tics */
+    for (i=0; i<infoPtr->uNumTics; i++)
+        TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->tics[i], ticFlags);
+
+    TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lRangeMin, ticFlags | TIC_EDGE);
+    TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lRangeMax, ticFlags | TIC_EDGE);
+
+    if ((dwStyle & TBS_ENABLESELRANGE) && TRACKBAR_HasSelection(infoPtr)) {
+        TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lSelMin,
+                          ticFlags | TIC_SELECTIONMARKMIN);
+        TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lSelMax,
+                          ticFlags | TIC_SELECTIONMARKMAX);
+    }
+    
+    /* clean up the pen, if we created one */
+    if (hTicPen) {
+	SelectObject(hdc, hOldPen);
+	DeleteObject(hTicPen);
+    }
+}
+
+static void
+TRACKBAR_DrawThumb(TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle)
+{
+    HBRUSH oldbr;
+    HPEN  oldpen;
+    RECT thumb = infoPtr->rcThumb;
+    int BlackUntil = 3;
+    int PointCount = 6;
+    POINT points[6];
+    int fillClr;
+
+    static INT PointDepth = 4;
+
+    fillClr = infoPtr->flags & TB_DRAG_MODE ? COLOR_BTNHILIGHT : COLOR_BTNFACE;
+    oldbr = SelectObject (hdc, GetSysColorBrush(fillClr));
+    SetPolyFillMode (hdc, WINDING);
+
+    if (dwStyle & TBS_BOTH)
+    {
+       points[0].x=thumb.right;
+       points[0].y=thumb.top;
+       points[1].x=thumb.right;
+       points[1].y=thumb.bottom;
+       points[2].x=thumb.left;
+       points[2].y=thumb.bottom;
+       points[3].x=thumb.left;
+       points[3].y=thumb.top;
+       points[4].x=points[0].x;
+       points[4].y=points[0].y;
+       PointCount = 5;
+       BlackUntil = 3;
+    }
+    else
+    {
+        if (dwStyle & TBS_VERT)
+        {
+          if (dwStyle & TBS_LEFT)
+          {
+            points[0].x=thumb.right;
+            points[0].y=thumb.top;
+            points[1].x=thumb.right;
+            points[1].y=thumb.bottom;
+            points[2].x=thumb.left + PointDepth;
+            points[2].y=thumb.bottom;
+            points[3].x=thumb.left;
+            points[3].y=(thumb.bottom - thumb.top) / 2 + thumb.top;
+            points[4].x=thumb.left + PointDepth;
+            points[4].y=thumb.top;
+            points[5].x=points[0].x;
+            points[5].y=points[0].y;
+            BlackUntil = 4;
+          }
+          else
+          {
+            points[0].x=thumb.right;
+            points[0].y=(thumb.bottom - thumb.top) / 2 + thumb.top;
+            points[1].x=thumb.right - PointDepth;
+            points[1].y=thumb.bottom;
+            points[2].x=thumb.left;
+            points[2].y=thumb.bottom;
+            points[3].x=thumb.left;
+            points[3].y=thumb.top;
+            points[4].x=thumb.right - PointDepth;
+            points[4].y=thumb.top;
+            points[5].x=points[0].x;
+            points[5].y=points[0].y;
+          }
+        }
+        else
+        {
+          if (dwStyle & TBS_TOP)
+          {
+            points[0].x=(thumb.right - thumb.left) / 2 + thumb.left ;
+            points[0].y=thumb.top;
+            points[1].x=thumb.right;
+            points[1].y=thumb.top + PointDepth;
+            points[2].x=thumb.right;
+            points[2].y=thumb.bottom;
+            points[3].x=thumb.left;
+            points[3].y=thumb.bottom;
+            points[4].x=thumb.left;
+            points[4].y=thumb.top + PointDepth;
+            points[5].x=points[0].x;
+            points[5].y=points[0].y;
+            BlackUntil = 4;
+          }
+          else
+          {
+            points[0].x=thumb.right;
+            points[0].y=thumb.top;
+            points[1].x=thumb.right;
+            points[1].y=thumb.bottom - PointDepth;
+            points[2].x=(thumb.right - thumb.left) / 2 + thumb.left ;
+            points[2].y=thumb.bottom;
+            points[3].x=thumb.left;
+            points[3].y=thumb.bottom - PointDepth;
+            points[4].x=thumb.left;
+            points[4].y=thumb.top;
+            points[5].x=points[0].x;
+            points[5].y=points[0].y;
+          }
+        }
+
+    }
+
+    /* Draw the thumb now */
+    Polygon (hdc, points, PointCount);
+    oldpen = SelectObject(hdc, GetStockObject(BLACK_PEN));
+    Polyline(hdc,points, BlackUntil);
+    SelectObject(hdc, GetStockObject(WHITE_PEN));
+    Polyline(hdc, &points[BlackUntil-1], PointCount+1-BlackUntil);
+    SelectObject(hdc, oldpen);
+    SelectObject(hdc, oldbr);
+}
+
+
+static void inline
+TRACKBAR_ActivateToolTip (TRACKBAR_INFO *infoPtr, BOOL fShow)
+{
+    TTTOOLINFOW ti;
+
+    if (!infoPtr->hwndToolTip) return;
+
+    ZeroMemory(&ti, sizeof(ti));
+    ti.cbSize = sizeof(ti);
+    ti.hwnd   = infoPtr->hwndSelf;
+
+    SendMessageW (infoPtr->hwndToolTip, TTM_TRACKACTIVATE, fShow, (LPARAM)&ti);
+}
+
+
+static void
+TRACKBAR_UpdateToolTip (TRACKBAR_INFO *infoPtr)
+{
+    DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
+    WCHAR buf[80], fmt[] = { '%', 'l', 'd', 0 };
+    TTTOOLINFOW ti;
+    POINT pt;
+    RECT rcClient;
+    LRESULT size;
+
+    if (!infoPtr->hwndToolTip) return;
+
+    ZeroMemory(&ti, sizeof(ti));
+    ti.cbSize = sizeof(ti);
+    ti.hwnd   = infoPtr->hwndSelf;
+    ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
+
+    wsprintfW (buf, fmt, infoPtr->lPos);
+    ti.lpszText = buf;
+    SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW, 0, (LPARAM)&ti);
+
+    GetClientRect (infoPtr->hwndSelf, &rcClient);
+    size = SendMessageW (infoPtr->hwndToolTip, TTM_GETBUBBLESIZE, 0, (LPARAM)&ti);
+    if (dwStyle & TBS_VERT) {
+	if (infoPtr->fLocation == TBTS_LEFT)
+	    pt.x = 0 - LOWORD(size) - TOOLTIP_OFFSET;
+	else
+	    pt.x = rcClient.right + TOOLTIP_OFFSET;
+    	pt.y = (infoPtr->rcThumb.top + infoPtr->rcThumb.bottom - HIWORD(size))/2;
+    } else {
+	if (infoPtr->fLocation == TBTS_TOP)
+	    pt.y = 0 - HIWORD(size) - TOOLTIP_OFFSET;
+	else
+            pt.y = rcClient.bottom + TOOLTIP_OFFSET;
+        pt.x = (infoPtr->rcThumb.left + infoPtr->rcThumb.right - LOWORD(size))/2;
+    }
+    ClientToScreen(infoPtr->hwndSelf, &pt);
+
+    SendMessageW (infoPtr->hwndToolTip, TTM_TRACKPOSITION,
+                  0, (LPARAM)MAKELPARAM(pt.x, pt.y));
+}
+
+
+static void
+TRACKBAR_Refresh (TRACKBAR_INFO *infoPtr, HDC hdcDst)
+{
+    DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
+    RECT rcClient;
+    HDC hdc;
+    HBITMAP hOldBmp = 0, hOffScreenBmp = 0;
+    NMCUSTOMDRAW nmcd;
+    int gcdrf, icdrf;
+
+    if (infoPtr->flags & TB_THUMBCHANGED) {
+        TRACKBAR_UpdateThumb (infoPtr);
+        if (infoPtr->flags & TB_THUMBSIZECHANGED)
+            TRACKBAR_CalcChannel (infoPtr);
+    }
+    if (infoPtr->flags & TB_SELECTIONCHANGED)
+        TRACKBAR_CalcSelection (infoPtr);
+
+    if (infoPtr->flags & TB_DRAG_MODE)
+        TRACKBAR_UpdateToolTip (infoPtr);
+
+    infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED);
+
+    GetClientRect (infoPtr->hwndSelf, &rcClient);
+    
+    /* try to render offscreen, if we fail, carrry onscreen */
+    hdc = CreateCompatibleDC(hdcDst);
+    if (hdc) {
+        hOffScreenBmp = CreateCompatibleBitmap(hdcDst, rcClient.right, rcClient.bottom);
+        if (hOffScreenBmp) {
+	    hOldBmp = SelectObject(hdc, hOffScreenBmp);
+	} else {
+	    DeleteObject(hdc);
+	    hdc = hdcDst;
+	}
+    } else {
+	hdc = hdcDst;
+    }
+
+    ZeroMemory(&nmcd, sizeof(nmcd));
+    nmcd.hdr.hwndFrom = infoPtr->hwndSelf;
+    nmcd.hdr.idFrom = GetWindowLongW (infoPtr->hwndSelf, GWL_ID);
+    nmcd.hdr.code = NM_CUSTOMDRAW;
+    nmcd.hdc = hdc;
+
+    /* start the paint cycle */
+    nmcd.rc = rcClient;
+    gcdrf = notify_customdraw(&nmcd, CDDS_PREPAINT);
+    if (gcdrf & CDRF_SKIPDEFAULT) goto cleanup;
+    
+    /* Erase backbround */
+    if (gcdrf == CDRF_DODEFAULT ||
+        notify_customdraw(&nmcd, CDDS_PREERASE) != CDRF_SKIPDEFAULT) {
+	FillRect (hdc, &rcClient, GetSysColorBrush(COLOR_BTNFACE));
+        if (gcdrf != CDRF_DODEFAULT)
+	    notify_customdraw(&nmcd, CDDS_POSTERASE);
+    }
+    
+    /* draw channel */
+    if (gcdrf & CDRF_NOTIFYITEMDRAW) {
+        nmcd.dwItemSpec = TBCD_CHANNEL;
+	nmcd.uItemState = CDIS_DEFAULT;
+	nmcd.rc = infoPtr->rcChannel;
+	icdrf = notify_customdraw(&nmcd, CDDS_ITEMPREPAINT);
+    } else icdrf = CDRF_DODEFAULT;
+    if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
+	TRACKBAR_DrawChannel (infoPtr, hdc, dwStyle);
+	if (icdrf & CDRF_NOTIFYPOSTPAINT)
+	    notify_customdraw(&nmcd, CDDS_ITEMPOSTPAINT);
+    }
+
+
+    /* draw tics */
+    if (!(dwStyle & TBS_NOTICKS)) {
+    	if (gcdrf & CDRF_NOTIFYITEMDRAW) {
+            nmcd.dwItemSpec = TBCD_TICS;
+	    nmcd.uItemState = CDIS_DEFAULT;
+	    nmcd.rc = rcClient;
+	    icdrf = notify_customdraw(&nmcd, CDDS_ITEMPREPAINT);
+        } else icdrf = CDRF_DODEFAULT;
+	if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
+	    TRACKBAR_DrawTics (infoPtr, hdc, dwStyle);
+	    if (icdrf & CDRF_NOTIFYPOSTPAINT)
+		notify_customdraw(&nmcd, CDDS_ITEMPOSTPAINT);
+	}
+    }
+    
+    /* draw thumb */
+    if (!(dwStyle & TBS_NOTHUMB)) {
+	if (gcdrf & CDRF_NOTIFYITEMDRAW) {
+	    nmcd.dwItemSpec = TBCD_THUMB;
+	    nmcd.uItemState = infoPtr->flags & TB_DRAG_MODE ? CDIS_HOT : CDIS_DEFAULT;
+	    nmcd.rc = infoPtr->rcThumb;
+	    icdrf = notify_customdraw(&nmcd, CDDS_ITEMPREPAINT);
+	} else icdrf = CDRF_DODEFAULT;
+	if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
+            TRACKBAR_DrawThumb(infoPtr, hdc, dwStyle);
+	    if (icdrf & CDRF_NOTIFYPOSTPAINT)
+		notify_customdraw(&nmcd, CDDS_ITEMPOSTPAINT);
+	}
+    }
+
+    /* finish up the painting */
+    if (gcdrf & CDRF_NOTIFYPOSTPAINT)
+	notify_customdraw(&nmcd, CDDS_POSTPAINT);
+    
+cleanup:
+    /* cleanup, if we rendered offscreen */
+    if (hdc != hdcDst) {
+	BitBlt(hdcDst, 0, 0, rcClient.right, rcClient.bottom, hdc, 0, 0, SRCCOPY);
+	SelectObject(hdc, hOldBmp);
+	DeleteObject(hOffScreenBmp);
+	DeleteObject(hdc);
+    }
+}
+
+
+static void
+TRACKBAR_AlignBuddies (TRACKBAR_INFO *infoPtr)
+{
+    DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
+    HWND hwndParent = GetParent (infoPtr->hwndSelf);
+    RECT rcSelf, rcBuddy;
+    INT x, y;
+
+    GetWindowRect (infoPtr->hwndSelf, &rcSelf);
+    MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcSelf, 2);
+
+    /* align buddy left or above */
+    if (infoPtr->hwndBuddyLA) {
+	GetWindowRect (infoPtr->hwndBuddyLA, &rcBuddy);
+	MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
+
+	if (dwStyle & TBS_VERT) {
+	    x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
+		(rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
+	    y = rcSelf.top - (rcBuddy.bottom - rcBuddy.top);
+	}
+	else {
+	    x = rcSelf.left - (rcBuddy.right - rcBuddy.left);
+	    y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 -
+		(rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top;
+	}
+
+	SetWindowPos (infoPtr->hwndBuddyLA, 0, x, y, 0, 0,
+                      SWP_NOZORDER | SWP_NOSIZE);
+    }
+
+
+    /* align buddy right or below */
+    if (infoPtr->hwndBuddyRB) {
+	GetWindowRect (infoPtr->hwndBuddyRB, &rcBuddy);
+	MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
+
+	if (dwStyle & TBS_VERT) {
+	    x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
+		(rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
+	    y = rcSelf.bottom;
+	}
+	else {
+	    x = rcSelf.right;
+	    y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 -
+		(rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top;
+	}
+	SetWindowPos (infoPtr->hwndBuddyRB, 0, x, y, 0, 0,
+                      SWP_NOZORDER | SWP_NOSIZE);
+    }
+}
+
+
+static LRESULT
+TRACKBAR_ClearSel (TRACKBAR_INFO *infoPtr, BOOL fRedraw)
+{
+    infoPtr->lSelMin = 0;
+    infoPtr->lSelMax = 0;
+    infoPtr->flags |= TB_SELECTIONCHANGED;
+
+    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT
+TRACKBAR_ClearTics (TRACKBAR_INFO *infoPtr, BOOL fRedraw)
+{
+    if (infoPtr->tics) {
+        COMCTL32_Free (infoPtr->tics);
+        infoPtr->tics = NULL;
+        infoPtr->uNumTics = 0;
+    }
+
+    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT inline
+TRACKBAR_GetChannelRect (TRACKBAR_INFO *infoPtr, LPRECT lprc)
+{
+    if (lprc == NULL) return 0;
+
+    lprc->left   = infoPtr->rcChannel.left;
+    lprc->right  = infoPtr->rcChannel.right;
+    lprc->bottom = infoPtr->rcChannel.bottom;
+    lprc->top    = infoPtr->rcChannel.top;
+
+    return 0;
+}
+
+
+static LONG inline
+TRACKBAR_GetNumTics (TRACKBAR_INFO *infoPtr)
+{
+    if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_NOTICKS)
+        return 0;
+
+    return infoPtr->uNumTics + 2;
+}
+
+
+static int comp_tics(const void *ap, const void *bp)
+{
+    DWORD a = *((DWORD *)ap);
+    DWORD b = *((DWORD *)bp);
+
+    TRACE("(a=%ld, b=%ld)\n", a, b);
+    if (a < b) return -1;
+    if (a > b) return 1;
+    return 0;
+}
+
+
+static LONG inline
+TRACKBAR_GetTic (TRACKBAR_INFO *infoPtr, INT iTic)
+{
+    if ((iTic < 0) || (iTic >= infoPtr->uNumTics) || !infoPtr->tics)
+	return -1;
+
+    qsort(infoPtr->tics, infoPtr->uNumTics, sizeof(DWORD), comp_tics);
+    return infoPtr->tics[iTic];
+}
+
+
+static LONG inline
+TRACKBAR_GetTicPos (TRACKBAR_INFO *infoPtr, INT iTic)
+{
+    LONG range, width, pos, tic;
+
+    if ((iTic < 0) || (iTic >= infoPtr->uNumTics) || !infoPtr->tics)
+	return -1;
+
+    tic   = TRACKBAR_GetTic (infoPtr, iTic);
+    range = infoPtr->lRangeMax - infoPtr->lRangeMin;
+    width = infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+    pos   = infoPtr->rcChannel.left + (width * tic) / range;
+
+    return pos;
+}
+
+
+static HWND
+TRACKBAR_SetBuddy (TRACKBAR_INFO *infoPtr, BOOL fLocation, HWND hwndBuddy)
+{
+    HWND hwndTemp;
+
+    if (fLocation) {
+	/* buddy is left or above */
+	hwndTemp = infoPtr->hwndBuddyLA;
+	infoPtr->hwndBuddyLA = hwndBuddy;
+    }
+    else {
+        /* buddy is right or below */
+        hwndTemp = infoPtr->hwndBuddyRB;
+        infoPtr->hwndBuddyRB = hwndBuddy;
+    }
+
+    TRACKBAR_AlignBuddies (infoPtr);
+
+    return hwndTemp;
+}
+
+
+static LONG inline
+TRACKBAR_SetLineSize (TRACKBAR_INFO *infoPtr, LONG lLineSize)
+{
+    LONG lTemp = infoPtr->lLineSize;
+
+    infoPtr->lLineSize = lLineSize;
+
+    return lTemp;
+}
+
+
+static LONG inline
+TRACKBAR_SetPageSize (TRACKBAR_INFO *infoPtr, LONG lPageSize)
+{
+    LONG lTemp = infoPtr->lPageSize;
+
+    infoPtr->lPageSize = lPageSize;
+
+    return lTemp;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetPos (TRACKBAR_INFO *infoPtr, BOOL fPosition, LONG lPosition)
+{
+    LONG oldPos = infoPtr->lPos;
+    infoPtr->lPos = lPosition;
+
+    if (infoPtr->lPos < infoPtr->lRangeMin)
+	infoPtr->lPos = infoPtr->lRangeMin;
+
+    if (infoPtr->lPos > infoPtr->lRangeMax)
+	infoPtr->lPos = infoPtr->lRangeMax;
+    infoPtr->flags |= TB_THUMBPOSCHANGED;
+
+    if (fPosition) TRACKBAR_InvalidateThumbMove(infoPtr, oldPos, lPosition);
+
+    return 0;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetRange (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lRange)
+{
+    infoPtr->lRangeMin = (SHORT)LOWORD(lRange);
+    infoPtr->lRangeMax = (SHORT)HIWORD(lRange);
+
+    if (infoPtr->lPos < infoPtr->lRangeMin) {
+        infoPtr->lPos = infoPtr->lRangeMin;
+        infoPtr->flags |= TB_THUMBPOSCHANGED;
+    }
+
+    if (infoPtr->lPos > infoPtr->lRangeMax) {
+        infoPtr->lPos = infoPtr->lRangeMax;
+        infoPtr->flags |= TB_THUMBPOSCHANGED;
+    }
+
+    infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5;
+    if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1;
+
+    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetRangeMax (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lMax)
+{
+    infoPtr->lRangeMax = lMax;
+    if (infoPtr->lPos > infoPtr->lRangeMax) {
+        infoPtr->lPos = infoPtr->lRangeMax;
+        infoPtr->flags |= TB_THUMBPOSCHANGED;
+    }
+
+    infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5;
+    if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1;
+
+    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetRangeMin (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lMin)
+{
+    infoPtr->lRangeMin = lMin;
+    if (infoPtr->lPos < infoPtr->lRangeMin) {
+        infoPtr->lPos = infoPtr->lRangeMin;
+        infoPtr->flags |= TB_THUMBPOSCHANGED;
+    }
+
+    infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5;
+    if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1;
+
+    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetSel (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lSel)
+{
+    if (!GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_ENABLESELRANGE)
+        return 0;
+
+    infoPtr->lSelMin = (SHORT)LOWORD(lSel);
+    infoPtr->lSelMax = (SHORT)HIWORD(lSel);
+    infoPtr->flags |= TB_SELECTIONCHANGED;
+
+    if (infoPtr->lSelMin < infoPtr->lRangeMin)
+        infoPtr->lSelMin = infoPtr->lRangeMin;
+    if (infoPtr->lSelMax > infoPtr->lRangeMax)
+        infoPtr->lSelMax = infoPtr->lRangeMax;
+
+    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetSelEnd (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lEnd)
+{
+    if (!GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_ENABLESELRANGE)
+	return 0;
+
+    infoPtr->lSelMax = lEnd;
+    infoPtr->flags |= TB_SELECTIONCHANGED;
+
+    if (infoPtr->lSelMax > infoPtr->lRangeMax)
+        infoPtr->lSelMax = infoPtr->lRangeMax;
+
+    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetSelStart (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lStart)
+{
+    if (!GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_ENABLESELRANGE)
+	return 0;
+
+    infoPtr->lSelMin = lStart;
+    infoPtr->flags  |=TB_SELECTIONCHANGED;
+
+    if (infoPtr->lSelMin < infoPtr->lRangeMin)
+        infoPtr->lSelMin = infoPtr->lRangeMin;
+
+    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetThumbLength (TRACKBAR_INFO *infoPtr, UINT iLength)
+{
+    if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_FIXEDLENGTH)
+        infoPtr->uThumbLen = iLength;
+
+    infoPtr->flags |= TB_THUMBSIZECHANGED;
+
+    InvalidateRect (infoPtr->hwndSelf, &infoPtr->rcThumb, FALSE);
+
+    return 0;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetTic (TRACKBAR_INFO *infoPtr, LONG lPos)
+{
+    if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_AUTOTICKS)
+	return FALSE;
+
+    if ((lPos < infoPtr->lRangeMin) || (lPos> infoPtr->lRangeMax))
+        return FALSE;
+
+    TRACE("lPos=%ld\n", lPos);
+
+    infoPtr->uNumTics++;
+    infoPtr->tics=COMCTL32_ReAlloc( infoPtr->tics,
+                                    (infoPtr->uNumTics)*sizeof (DWORD));
+    if (!infoPtr->tics) {
+	infoPtr->uNumTics = 0;
+	TRACKBAR_SendNotify(infoPtr, NM_OUTOFMEMORY);
+	return FALSE;
+    }
+    infoPtr->tics[infoPtr->uNumTics-1] = lPos;
+
+    TRACKBAR_InvalidateAll(infoPtr);
+
+    return TRUE;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetTicFreq (TRACKBAR_INFO *infoPtr, WORD wFreq)
+{
+    if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_AUTOTICKS) {
+        infoPtr->uTicFreq = wFreq;
+	TRACKBAR_RecalculateTics (infoPtr);
+	TRACKBAR_InvalidateAll(infoPtr);
+    }
+
+    return 0;
+}
+
+
+static INT inline
+TRACKBAR_SetTipSide (TRACKBAR_INFO *infoPtr, INT fLocation)
+{
+    INT fTemp = infoPtr->fLocation;
+
+    infoPtr->fLocation = fLocation;
+
+    return fTemp;
+}
+
+
+static LRESULT inline
+TRACKBAR_SetToolTips (TRACKBAR_INFO *infoPtr, HWND hwndTT)
+{
+    infoPtr->hwndToolTip = hwndTT;
+
+    return 0;
+}
+
+
+static BOOL inline
+TRACKBAR_SetUnicodeFormat (TRACKBAR_INFO *infoPtr, BOOL fUnicode)
+{
+    BOOL bTemp = infoPtr->bUnicode;
+
+    infoPtr->bUnicode = fUnicode;
+
+    return bTemp;
+}
+
+
+static LRESULT
+TRACKBAR_InitializeThumb (TRACKBAR_INFO *infoPtr)
+{
+    /* initial thumb length */
+    RECT rect;
+    GetClientRect(infoPtr->hwndSelf,&rect);
+    infoPtr->uThumbLen = (rect.bottom - rect.top - 6);
+
+    TRACKBAR_CalcChannel (infoPtr);
+    TRACKBAR_UpdateThumb (infoPtr);
+    infoPtr->flags &= ~TB_SELECTIONCHANGED;
+
+    return 0;
+}
+
+
+static LRESULT
+TRACKBAR_Create (HWND hwnd, LPCREATESTRUCTW lpcs)
+{
+    TRACKBAR_INFO *infoPtr;
+    DWORD oldStyle, newStyle;
+
+    infoPtr = (TRACKBAR_INFO *)COMCTL32_Alloc (sizeof(TRACKBAR_INFO));
+    if (!infoPtr) return -1;
+    SetWindowLongW (hwnd, 0, (DWORD)infoPtr);
+
+    /* set default values */
+    infoPtr->hwndSelf  = hwnd;
+    infoPtr->lRangeMin = 0;
+    infoPtr->lRangeMax = 100;
+    infoPtr->lLineSize = 1;
+    infoPtr->lPageSize = 20;
+    infoPtr->lSelMin   = 0;
+    infoPtr->lSelMax   = 0;
+    infoPtr->lPos      = 0;
+    infoPtr->fLocation = -1;
+    infoPtr->uNumTics  = 0;    /* start and end tic are not included in count*/
+    infoPtr->uTicFreq  = 1;
+    infoPtr->tics      = NULL;
+    infoPtr->hwndNotify= GetParent (hwnd);
+
+    TRACKBAR_InitializeThumb (infoPtr);
+
+    oldStyle = newStyle = GetWindowLongW (hwnd, GWL_STYLE);
+    if (oldStyle & TBS_VERT) {
+	if (! (oldStyle & (TBS_LEFT | TBS_RIGHT | TBS_BOTH)) )
+	    newStyle |= TBS_RIGHT;
+    } else {
+	if (! (oldStyle & (TBS_TOP | TBS_BOTTOM | TBS_BOTH)) )
+	    newStyle |= TBS_BOTTOM;
+    }
+    if (newStyle != oldStyle)
+	SetWindowLongW (hwnd, GWL_STYLE, newStyle);
+
+    /* Create tooltip control */
+    if (newStyle & TBS_TOOLTIPS) {
+
+    	infoPtr->hwndToolTip =
+            CreateWindowExW (0, TOOLTIPS_CLASSW, NULL, 0,
+                             CW_USEDEFAULT, CW_USEDEFAULT,
+                             CW_USEDEFAULT, CW_USEDEFAULT,
+                             hwnd, 0, 0, 0);
+
+    	if (infoPtr->hwndToolTip) {
+            TTTOOLINFOW ti;	    
+            ZeroMemory (&ti, sizeof(ti));
+            ti.cbSize   = sizeof(ti);
+     	    ti.uFlags   = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
+	    ti.hwnd     = hwnd;
+
+            SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW, 0, (LPARAM)&ti);
+	 }
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TRACKBAR_Destroy (TRACKBAR_INFO *infoPtr)
+{
+    /* delete tooltip control */
+    if (infoPtr->hwndToolTip)
+    	DestroyWindow (infoPtr->hwndToolTip);
+
+    COMCTL32_Free (infoPtr);
+    SetWindowLongW (infoPtr->hwndSelf, 0, 0);
+    return 0;
+}
+
+
+static LRESULT
+TRACKBAR_KillFocus (TRACKBAR_INFO *infoPtr, HWND hwndGetFocus)
+{
+    TRACE("\n");
+
+    TRACKBAR_InvalidateAll(infoPtr);
+
+    return 0;
+}
+
+static LRESULT
+TRACKBAR_LButtonDown (TRACKBAR_INFO *infoPtr, DWORD fwKeys, POINTS pts)
+{
+    POINT clickPoint = { pts.x, pts.y };
+
+    SetFocus(infoPtr->hwndSelf);
+
+    if (PtInRect(&infoPtr->rcThumb, clickPoint)) {
+        infoPtr->flags |= TB_DRAG_MODE;
+        SetCapture (infoPtr->hwndSelf);
+	TRACKBAR_UpdateToolTip (infoPtr);
+	TRACKBAR_ActivateToolTip (infoPtr, TRUE);
+	TRACKBAR_InvalidateThumb(infoPtr, infoPtr->lPos);
+    } else {
+	LONG dir = TRACKBAR_GetAutoPageDirection(infoPtr, clickPoint);
+	if (dir == 0) return 0;
+	infoPtr->flags |= (dir < 0) ? TB_AUTO_PAGE_LEFT : TB_AUTO_PAGE_RIGHT;
+	TRACKBAR_AutoPage (infoPtr, clickPoint);
+        SetCapture (infoPtr->hwndSelf);
+        SetTimer(infoPtr->hwndSelf, TB_REFRESH_TIMER, TB_REFRESH_DELAY, 0);
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TRACKBAR_LButtonUp (TRACKBAR_INFO *infoPtr, DWORD fwKeys, POINTS pts)
+{
+    if (infoPtr->flags & TB_DRAG_MODE) {
+        TRACKBAR_SendNotify (infoPtr, TB_ENDTRACK);
+        infoPtr->flags &= ~TB_DRAG_MODE;
+        ReleaseCapture ();
+	TRACKBAR_SendNotify(infoPtr, NM_RELEASEDCAPTURE);
+        TRACKBAR_ActivateToolTip(infoPtr, FALSE);
+	TRACKBAR_InvalidateThumb(infoPtr, infoPtr->lPos);
+    }
+    if (infoPtr->flags & TB_AUTO_PAGE) {
+	KillTimer (infoPtr->hwndSelf, TB_REFRESH_TIMER);
+        infoPtr->flags &= ~TB_AUTO_PAGE;
+        ReleaseCapture ();
+	TRACKBAR_SendNotify(infoPtr, NM_RELEASEDCAPTURE);
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TRACKBAR_CaptureChanged (TRACKBAR_INFO *infoPtr)
+{
+    TRACKBAR_SendNotify (infoPtr, TB_ENDTRACK);
+    return 0;
+}
+
+
+static LRESULT
+TRACKBAR_Paint (TRACKBAR_INFO *infoPtr, HDC hdc)
+{
+    if (hdc) {
+	TRACKBAR_Refresh(infoPtr, hdc);
+    } else {
+	PAINTSTRUCT ps;
+    	hdc = BeginPaint (infoPtr->hwndSelf, &ps);
+    	TRACKBAR_Refresh (infoPtr, hdc);
+    	EndPaint (infoPtr->hwndSelf, &ps);
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TRACKBAR_SetFocus (TRACKBAR_INFO *infoPtr, HWND hwndLoseFocus)
+{
+    TRACE("\n");
+
+    TRACKBAR_InvalidateAll(infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT
+TRACKBAR_Size (TRACKBAR_INFO *infoPtr, DWORD fwSizeType, INT nWidth, INT nHeight)
+{
+    TRACKBAR_CalcChannel (infoPtr);
+    TRACKBAR_AlignBuddies (infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT
+TRACKBAR_Timer (TRACKBAR_INFO *infoPtr, INT wTimerID, TIMERPROC *tmrpc)
+{
+    if (infoPtr->flags & TB_AUTO_PAGE) {
+	POINT pt;
+	if (GetCursorPos(&pt))
+	    if (ScreenToClient(infoPtr->hwndSelf, &pt))
+		TRACKBAR_AutoPage(infoPtr, pt);
+    }
+    return 0;
+}
+
+
+static BOOL
+TRACKBAR_SendNotify (TRACKBAR_INFO *infoPtr, UINT code)
+{
+    BOOL bVert = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_VERT;
+
+    TRACE("%x\n", code);
+
+    return (BOOL) SendMessageW (GetParent (infoPtr->hwndSelf),
+                                bVert ? WM_VSCROLL : WM_HSCROLL,
+				(WPARAM)code, (LPARAM)infoPtr->hwndSelf);
+}
+
+
+static LRESULT
+TRACKBAR_MouseMove (TRACKBAR_INFO *infoPtr, DWORD fwKeys, POINTS pts)
+{
+    DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE);
+    INT clickPlace = (dwStyle & TBS_VERT) ? pts.y : pts.x;
+    DOUBLE dragPos, oldPos = infoPtr->lPos;
+
+    TRACE("(x=%d. y=%d)\n", pts.x, pts.y);
+
+    if (infoPtr->flags & TB_AUTO_PAGE) {
+	POINT pt;
+	POINTSTOPOINT(pt, pts);
+	TRACKBAR_AutoPage (infoPtr, pt);
+	return TRUE;
+    }
+
+    if (!(infoPtr->flags & TB_DRAG_MODE)) return TRUE;
+
+    dragPos = TRACKBAR_ConvertPlaceToPosition (infoPtr, clickPlace,
+                                               dwStyle & TBS_VERT);
+    if (dragPos > ((INT)dragPos) + 0.5) dragPos++;
+
+    if (dragPos == oldPos) return TRUE;
+
+    infoPtr->lPos = dragPos;
+
+    infoPtr->flags |= TB_THUMBPOSCHANGED;
+    TRACKBAR_SendNotify (infoPtr, TB_THUMBTRACK | (infoPtr->lPos<<16));
+
+
+    TRACKBAR_InvalidateThumbMove(infoPtr, oldPos, dragPos);
+    UpdateWindow (infoPtr->hwndSelf);
+
+    return TRUE;
+}
+
+
+static BOOL
+TRACKBAR_KeyDown (TRACKBAR_INFO *infoPtr, INT nVirtKey, DWORD lKeyData)
+{
+    BOOL downIsLeft = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_DOWNISLEFT;
+    LONG pos = infoPtr->lPos;
+
+    TRACE("%x\n", nVirtKey);
+
+    switch (nVirtKey) {
+    case VK_UP:
+	if (downIsLeft) goto step_right;
+    case VK_LEFT:
+    step_left:
+        if (infoPtr->lPos == infoPtr->lRangeMin) return FALSE;
+        infoPtr->lPos -= infoPtr->lLineSize;
+        if (infoPtr->lPos < infoPtr->lRangeMin)
+            infoPtr->lPos = infoPtr->lRangeMin;
+        TRACKBAR_SendNotify (infoPtr, TB_LINEUP);
+        break;
+    case VK_DOWN:
+	if (downIsLeft) goto step_left;
+    case VK_RIGHT:
+    step_right:
+        if (infoPtr->lPos == infoPtr->lRangeMax) return FALSE;
+        infoPtr->lPos += infoPtr->lLineSize;
+        if (infoPtr->lPos > infoPtr->lRangeMax)
+            infoPtr->lPos = infoPtr->lRangeMax;
+        TRACKBAR_SendNotify (infoPtr, TB_LINEDOWN);
+        break;
+    case VK_NEXT:
+	if (downIsLeft) goto page_left;
+    page_right:
+	TRACKBAR_PageUp(infoPtr);
+        break;
+    case VK_PRIOR:
+	if (downIsLeft) goto page_right;
+    page_left:
+	TRACKBAR_PageDown(infoPtr);
+        break;
+    case VK_HOME:
+        if (infoPtr->lPos == infoPtr->lRangeMin) return FALSE;
+        infoPtr->lPos = infoPtr->lRangeMin;
+        TRACKBAR_SendNotify (infoPtr, TB_TOP);
+        break;
+    case VK_END:
+        if (infoPtr->lPos == infoPtr->lRangeMax) return FALSE;
+        infoPtr->lPos = infoPtr->lRangeMax;
+        TRACKBAR_SendNotify (infoPtr, TB_BOTTOM);
+        break;
+    }
+
+    if (pos != infoPtr->lPos) {
+	infoPtr->flags |=TB_THUMBPOSCHANGED;
+	TRACKBAR_InvalidateThumbMove (infoPtr, pos, infoPtr->lPos);
+    }
+
+    return TRUE;
+}
+
+
+static BOOL inline
+TRACKBAR_KeyUp (TRACKBAR_INFO *infoPtr, INT nVirtKey, DWORD lKeyData)
+{
+    switch (nVirtKey) {
+    case VK_LEFT:
+    case VK_UP:
+    case VK_RIGHT:
+    case VK_DOWN:
+    case VK_NEXT:
+    case VK_PRIOR:
+    case VK_HOME:
+    case VK_END:
+        TRACKBAR_SendNotify (infoPtr, TB_ENDTRACK);
+    }
+    return TRUE;
+}
+
+
+static LRESULT WINAPI
+TRACKBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    TRACKBAR_INFO *infoPtr = (TRACKBAR_INFO *)GetWindowLongW (hwnd, 0);
+
+    TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam);
+
+    if (!infoPtr && (uMsg != WM_CREATE))
+        return DefWindowProcW (hwnd, uMsg, wParam, lParam);
+
+    switch (uMsg)
+    {
+    case TBM_CLEARSEL:
+        return TRACKBAR_ClearSel (infoPtr, (BOOL)wParam);
+
+    case TBM_CLEARTICS:
+        return TRACKBAR_ClearTics (infoPtr, (BOOL)wParam);
+
+    case TBM_GETBUDDY:
+        return (LRESULT)(wParam ? infoPtr->hwndBuddyLA : infoPtr->hwndBuddyRB);
+
+    case TBM_GETCHANNELRECT:
+        return TRACKBAR_GetChannelRect (infoPtr, (LPRECT)lParam);
+
+    case TBM_GETLINESIZE:
+        return infoPtr->lLineSize;
+
+    case TBM_GETNUMTICS:
+        return TRACKBAR_GetNumTics (infoPtr);
+
+    case TBM_GETPAGESIZE:
+        return infoPtr->lPageSize;
+
+    case TBM_GETPOS:
+        return infoPtr->lPos;
+
+    case TBM_GETPTICS:
+        return (LRESULT)infoPtr->tics;
+
+    case TBM_GETRANGEMAX:
+        return infoPtr->lRangeMax;
+
+    case TBM_GETRANGEMIN:
+        return infoPtr->lRangeMin;
+
+    case TBM_GETSELEND:
+        return infoPtr->lSelMax;
+
+    case TBM_GETSELSTART:
+        return infoPtr->lSelMin;
+
+    case TBM_GETTHUMBLENGTH:
+        return infoPtr->uThumbLen;
+
+    case TBM_GETTHUMBRECT:
+	return CopyRect((LPRECT)lParam, &infoPtr->rcThumb);
+
+    case TBM_GETTIC:
+        return TRACKBAR_GetTic (infoPtr, (INT)wParam);
+
+    case TBM_GETTICPOS:
+        return TRACKBAR_GetTicPos (infoPtr, (INT)wParam);
+
+    case TBM_GETTOOLTIPS:
+        return (LRESULT)infoPtr->hwndToolTip;
+
+    case TBM_GETUNICODEFORMAT:
+        return infoPtr->bUnicode;
+
+    case TBM_SETBUDDY:
+        return (LRESULT) TRACKBAR_SetBuddy(infoPtr, (BOOL)wParam, (HWND)lParam);
+
+    case TBM_SETLINESIZE:
+        return TRACKBAR_SetLineSize (infoPtr, (LONG)lParam);
+
+    case TBM_SETPAGESIZE:
+        return TRACKBAR_SetPageSize (infoPtr, (LONG)lParam);
+
+    case TBM_SETPOS:
+        return TRACKBAR_SetPos (infoPtr, (BOOL)wParam, (LONG)lParam);
+
+    case TBM_SETRANGE:
+        return TRACKBAR_SetRange (infoPtr, (BOOL)wParam, (LONG)lParam);
+
+    case TBM_SETRANGEMAX:
+        return TRACKBAR_SetRangeMax (infoPtr, (BOOL)wParam, (LONG)lParam);
+
+    case TBM_SETRANGEMIN:
+        return TRACKBAR_SetRangeMin (infoPtr, (BOOL)wParam, (LONG)lParam);
+
+    case TBM_SETSEL:
+        return TRACKBAR_SetSel (infoPtr, (BOOL)wParam, (LONG)lParam);
+
+    case TBM_SETSELEND:
+        return TRACKBAR_SetSelEnd (infoPtr, (BOOL)wParam, (LONG)lParam);
+
+    case TBM_SETSELSTART:
+        return TRACKBAR_SetSelStart (infoPtr, (BOOL)wParam, (LONG)lParam);
+
+    case TBM_SETTHUMBLENGTH:
+        return TRACKBAR_SetThumbLength (infoPtr, (UINT)wParam);
+
+    case TBM_SETTIC:
+        return TRACKBAR_SetTic (infoPtr, (LONG)lParam);
+
+    case TBM_SETTICFREQ:
+        return TRACKBAR_SetTicFreq (infoPtr, (WORD)wParam);
+
+    case TBM_SETTIPSIDE:
+        return TRACKBAR_SetTipSide (infoPtr, (INT)wParam);
+
+    case TBM_SETTOOLTIPS:
+        return TRACKBAR_SetToolTips (infoPtr, (HWND)wParam);
+
+    case TBM_SETUNICODEFORMAT:
+	return TRACKBAR_SetUnicodeFormat (infoPtr, (BOOL)wParam);
+
+
+    case WM_CAPTURECHANGED:
+        return TRACKBAR_CaptureChanged (infoPtr);
+
+    case WM_CREATE:
+        return TRACKBAR_Create (hwnd, (LPCREATESTRUCTW)lParam);
+
+    case WM_DESTROY:
+        return TRACKBAR_Destroy (infoPtr);
+
+/*	case WM_ENABLE: */
+
+    case WM_ERASEBKGND:
+	return 0;
+
+    case WM_GETDLGCODE:
+        return DLGC_WANTARROWS;
+
+    case WM_KEYDOWN:
+        return TRACKBAR_KeyDown (infoPtr, (INT)wParam, (DWORD)lParam);
+
+    case WM_KEYUP:
+        return TRACKBAR_KeyUp (infoPtr, (INT)wParam, (DWORD)lParam);
+
+    case WM_KILLFOCUS:
+        return TRACKBAR_KillFocus (infoPtr, (HWND)wParam);
+
+    case WM_LBUTTONDOWN:
+        return TRACKBAR_LButtonDown (infoPtr, wParam, MAKEPOINTS(lParam));
+
+    case WM_LBUTTONUP:
+        return TRACKBAR_LButtonUp (infoPtr, wParam, MAKEPOINTS(lParam));
+
+    case WM_MOUSEMOVE:
+        return TRACKBAR_MouseMove (infoPtr, wParam, MAKEPOINTS(lParam));
+
+    case WM_PAINT:
+        return TRACKBAR_Paint (infoPtr, (HDC)wParam);
+
+    case WM_SETFOCUS:
+        return TRACKBAR_SetFocus (infoPtr, (HWND)wParam);
+
+    case WM_SIZE:
+        return TRACKBAR_Size (infoPtr, wParam, LOWORD(lParam), HIWORD(lParam));
+
+    case WM_TIMER:
+	return TRACKBAR_Timer (infoPtr, (INT)wParam, (TIMERPROC *)lParam);
+
+    case WM_WININICHANGE:
+        return TRACKBAR_InitializeThumb (infoPtr);
+
+    default:
+        if ((uMsg >= WM_USER) && (uMsg < WM_APP))
+            ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam);
+        return DefWindowProcW (hwnd, uMsg, wParam, lParam);
+    }
+    return 0;
+}
+
+
+void TRACKBAR_Register (void)
+{
+    WNDCLASSW wndClass;
+
+    ZeroMemory (&wndClass, sizeof(WNDCLASSW));
+    wndClass.style         = CS_GLOBALCLASS;
+    wndClass.lpfnWndProc   = (WNDPROC)TRACKBAR_WindowProc;
+    wndClass.cbClsExtra    = 0;
+    wndClass.cbWndExtra    = sizeof(TRACKBAR_INFO *);
+    wndClass.hCursor       = LoadCursorW (0, IDC_ARROWW);
+    wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
+    wndClass.lpszClassName = TRACKBAR_CLASSW;
+
+    RegisterClassW (&wndClass);
+}
+
+
+void TRACKBAR_Unregister (void)
+{
+    UnregisterClassW (TRACKBAR_CLASSW, NULL);
+}
Index: trunk/src/comctl32/trackbar.cpp
===================================================================
--- trunk/src/comctl32/trackbar.cpp	(revision 10097)
+++ 	(revision )
@@ -1,2428 +1,0 @@
-/* $Id: trackbar.cpp,v 1.9 2002-10-29 13:47:30 sandervl Exp $ */
-/*
- * Trackbar control
- *
- * Copyright 1998, 1999 Eric Kohl <ekohl@abo.rhein-zeitung.de>
- * Copyright 1998,1999 Alex Priem <alexp@sci.kun.nl>
- * Copyright 1999 Achim Hasenmueller
- * Copyright 1999 Christoph Bratschi <cbratschi@datacomm.ch>
- *
- *
- * Status: complete
- * Version: 5.80
- *
- * Note: TBM_SETTHUMBLENGTH implemented, COMCTL32 5.00 ignores it
- *       Microsoft(TM) should fix this bug :)
- */
-
-#include "winbase.h"
-#include "commctrl.h"
-#include "ccbase.h"
-#include "trackbar.h"
-#include "comctl32.h"
-#include <stdio.h>
-
-#define TRACKBAR_GetInfoPtr(hwnd) ((TRACKBAR_INFO*)getInfoPtr(hwnd))
-
-
-/* Used by TRACKBAR_Draw to find out which parts of the control
-   need to be recalculated */
-
-#define TB_THUMBPOSCHANGED      1
-#define TB_THUMBSIZECHANGED     2
-#define TB_THUMBCHANGED         (TB_THUMBPOSCHANGED | TB_THUMBPOSCHANGED)
-#define TB_SELECTIONCHANGED     4
-#define TB_DRAG_MODE            16     /* we're dragging the slider */
-#define TB_DRAGPOSVALID         32     /* current Position is in dragPos */
-#define TB_SCROLL_MODE          64     /* WM_TIMER scroll mode */
-#define TB_SHOW_TOOLTIP         128    /* tooltip-style enabled and tooltip on */
-
-/* helper defines for TRACKBAR_DrawTic */
-#define TIC_LEFTEDGE            0x20
-#define TIC_RIGHTEDGE           0x40
-#define TIC_EDGE                (TIC_LEFTEDGE | TIC_RIGHTEDGE)
-#define TIC_SELECTIONMARKMAX    0x80
-#define TIC_SELECTIONMARKMIN    0x100
-#define TIC_SELECTIONMARK       (TIC_SELECTIONMARKMAX | TIC_SELECTIONMARKMIN)
-
-/* size calculation */
-
-#define BORDER_SIZE 2
-
-#define SCALE_SIZE  4
-#define SCALE_SPACE 1
-
-#define THUMB_LEN_SEL 23
-#define THUMB_LEN     21
-#define THUMB_MINLEN   4
-
-#define CHANNEL_NOSEL_HEIGHT 4 //min no sel height
-#define CHANNEL_MIN_HEIGHT   6 //min sel height
-#define CHANNEL_THUMB_DIFF   8 //sel thumb, channel difference
-#define CHANNEL_SPACE        8
-#define CHANNEL_SCALE_SPACE  SCALE_SIZE+SCALE_SPACE+BORDER_SIZE
-#define CHANNEL_THUMB_SPACE  BORDER_SIZE
-
-#define TOOLTIP_SPACE 5
-
-/* scroll mode */
-
-#define SCROLL_TIME     500 //ms
-#define SCROLL_TIMER_ID 1
-
-/* Tooltips */
-
-#define TOOLTIP_XSPACE 5
-#define TOOLTIP_YSPACE 5
-
-static const WORD pattern[8] =
-     {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
-
-static BOOL TRACKBAR_SendNotify(TRACKBAR_INFO *infoPtr,UINT code);
-
-static void TRACKBAR_RecalculateTics(TRACKBAR_INFO *infoPtr,BOOL restoreOld)
-{
-    INT i,tic,nrTics;
-
-    if (infoPtr->dwStyle & TBS_NOTICKS) //no ticks
-    {
-      COMCTL32_Free(infoPtr->tics);
-      infoPtr->tics = NULL;
-
-      infoPtr->uNumTics = 0;
-      return;
-    }
-
-    if (restoreOld && !(infoPtr->dwStyle & TBS_AUTOTICKS) && infoPtr->tics)
-    { //check old ticks
-      LPLONG oldTics = (LONG*)COMCTL32_Alloc(infoPtr->uNumTics*sizeof(DWORD));
-      INT count = 0;
-
-      for (i = 0;i < infoPtr->uNumTics;i++)
-      {
-        if ((infoPtr->tics[i] >= infoPtr->nRangeMin) && (infoPtr->tics[i] <= infoPtr->nRangeMax))
-        {
-          oldTics[count] = infoPtr->tics[i];
-          count++;
-        }
-      }
-
-      COMCTL32_Free(infoPtr->tics);
-      infoPtr->tics = (LONG*)COMCTL32_ReAlloc(oldTics,count*sizeof(DWORD));
-      infoPtr->uNumTics = count;
-
-      return;
-    }
-
-    if (infoPtr->uTicFreq && (infoPtr->nRangeMax > infoPtr->nRangeMin) && (infoPtr->dwStyle & TBS_AUTOTICKS))
-    {
-      //Tics without start and end tic
-      nrTics = (infoPtr->nRangeMax-infoPtr->nRangeMin)/infoPtr->uTicFreq-1;
-      if (nrTics <= 0)
-      {
-        COMCTL32_Free(infoPtr->tics);
-        infoPtr->tics = NULL;
-        infoPtr->uNumTics = 0;
-        return;
-      }
-    } else
-    {
-      COMCTL32_Free(infoPtr->tics);
-      infoPtr->tics = NULL;
-      infoPtr->uNumTics = 0;
-      return;
-    }
-
-    if (nrTics != infoPtr->uNumTics)
-    {
-      COMCTL32_Free(infoPtr->tics);
-      infoPtr->tics = (LONG*)COMCTL32_Alloc(nrTics*sizeof(DWORD));
-      infoPtr->uNumTics = nrTics;
-    }
-
-    tic = infoPtr->nRangeMin+infoPtr->uTicFreq; //start not included
-    for (i = 0;i < nrTics;i++)
-    {
-      infoPtr->tics[i] = tic;
-      tic += infoPtr->uTicFreq;
-    }
-}
-
-
-/* converts from physical (mouse) position to logical position
-   (in range of trackbar) */
-
-static DOUBLE
-TRACKBAR_ConvertPlaceToPosition(TRACKBAR_INFO *infoPtr,int place,int vertical)
-{
-    double range,width,pos;
-
-    range = infoPtr->nRangeMax-infoPtr->nRangeMin;
-    if (vertical)
-    {
-      width = infoPtr->rcChannel.bottom-infoPtr->rcChannel.top;
-      pos = infoPtr->nRangeMin+(range*(place-infoPtr->rcChannel.top))/width;
-    } else
-    {
-      width = infoPtr->rcChannel.right-infoPtr->rcChannel.left;
-      pos = infoPtr->nRangeMin+(range*(place-infoPtr->rcChannel.left))/width;
-    }
-
-    if (pos > infoPtr->nRangeMax) pos = infoPtr->nRangeMax;
-    else if (pos < infoPtr->nRangeMin) pos = infoPtr->nRangeMin;
-
-    return pos;
-}
-
-
-static VOID
-TRACKBAR_CalcChannel(TRACKBAR_INFO *infoPtr)
-{
-    INT channelSize;
-    RECT lpRect,*channel = &infoPtr->rcChannel;
-    INT thumbDiff;
-
-    GetClientRect(infoPtr->hwnd,&lpRect);
-
-    if (infoPtr->dwStyle & TBS_ENABLESELRANGE) channelSize = MAX(infoPtr->uThumbLen-CHANNEL_THUMB_DIFF,CHANNEL_MIN_HEIGHT);
-    else channelSize = CHANNEL_NOSEL_HEIGHT;
-
-    thumbDiff = (infoPtr->uThumbLen-channelSize)/2;
-
-    if (infoPtr->dwStyle & TBS_VERT)
-    {
-      channel->top    = lpRect.top+CHANNEL_SPACE;
-      channel->bottom = lpRect.bottom-CHANNEL_SPACE;
-
-      if ((infoPtr->dwStyle & TBS_BOTH) || (infoPtr->dwStyle & TBS_NOTICKS))
-      { //center
-        channel->left  = (lpRect.right-channelSize)/2;
-        channel->right = (lpRect.right+channelSize)/2;
-      } else if (infoPtr->dwStyle & TBS_LEFT)
-      {
-        channel->left  = lpRect.left+thumbDiff+CHANNEL_SCALE_SPACE;
-        channel->right = channel->left+channelSize;
-      } else
-      { //Right, align left
-        channel->left = lpRect.left+thumbDiff+CHANNEL_THUMB_SPACE;
-        channel->right = channel->left+channelSize;
-      }
-    } else
-    {
-      channel->left = lpRect.left+CHANNEL_SPACE;
-      channel->right = lpRect.right-CHANNEL_SPACE;
-      if ((infoPtr->dwStyle & TBS_BOTH) || (infoPtr->dwStyle & TBS_NOTICKS))
-      { //center
-        channel->top    = (lpRect.bottom-channelSize)/2;
-        channel->bottom = (lpRect.bottom+channelSize)/2;
-      } else if (infoPtr->dwStyle & TBS_TOP)
-      {
-        channel->top    = lpRect.top+thumbDiff+CHANNEL_SCALE_SPACE;
-        channel->bottom = channel->top+channelSize;
-      } else
-      { //Bottom, align top
-        channel->top    = lpRect.top+thumbDiff+CHANNEL_THUMB_SPACE;
-        channel->bottom = channel->top+channelSize;
-      }
-    }
-}
-
-static VOID
-TRACKBAR_CalcThumb(TRACKBAR_INFO *infoPtr)
-{
-    RECT *thumb;
-    RECT *fullThumb;
-    int range, width;
-    int x,y;
-    int thumbFactor = 2;
-
-    thumb = &infoPtr->rcThumb;
-    fullThumb = &infoPtr->rcFullThumb;
-    range = infoPtr->nRangeMax-infoPtr->nRangeMin;
-    if (infoPtr->dwStyle & TBS_VERT)
-    {
-      width = infoPtr->rcChannel.bottom-infoPtr->rcChannel.top;
-      y = infoPtr->uThumbLen/thumbFactor; //thumb height
-      if (y%2 == 1) y++; //for real arrow
-      thumb->top    = infoPtr->rcChannel.top+(width*(infoPtr->nPos-infoPtr->nRangeMin))/range-y/2; //centered
-      thumb->bottom = thumb->top+y;
-      //centered, no arrows
-      thumb->left  = infoPtr->rcChannel.left-(infoPtr->uThumbLen-(infoPtr->rcChannel.right-infoPtr->rcChannel.left))/2;
-      thumb->right = thumb->left+infoPtr->uThumbLen;
-      CopyRect(fullThumb,thumb);
-      if (infoPtr->dwStyle & TBS_BOTH) return;
-      x = y/2; //arrow width
-      if (infoPtr->dwStyle & TBS_LEFT) thumb->left += x; else thumb->right -= x;
-    } else
-    {
-      width = infoPtr->rcChannel.right-infoPtr->rcChannel.left;
-      x = infoPtr->uThumbLen/thumbFactor; //thumb width
-      if (x%2 == 1) x++; //for real arrow
-      thumb->left   = infoPtr->rcChannel.left+(width*(infoPtr->nPos-infoPtr->nRangeMin))/range-x/2; //centered
-      thumb->right  = thumb->left+x;
-      //centered, no arrows
-      thumb->top  = infoPtr->rcChannel.top-(infoPtr->uThumbLen-(infoPtr->rcChannel.bottom-infoPtr->rcChannel.top))/2;
-      thumb->bottom = thumb->top+infoPtr->uThumbLen;
-      CopyRect(fullThumb,thumb);
-      if (infoPtr->dwStyle & TBS_BOTH) return;
-      y = x/2; //arrow height
-      if (infoPtr->dwStyle & TBS_TOP) thumb->top += y; else thumb->bottom -= y;
-    }
-}
-
-static VOID
-TRACKBAR_CalcSelection(TRACKBAR_INFO *infoPtr)
-{
-    RECT *selection;
-    int range,width,height;
-    int selMin = infoPtr->nSelMin-infoPtr->nRangeMin; //relative to nRangeMin
-    int selMax = infoPtr->nSelMax-infoPtr->nRangeMin; //dito
-
-    selection = &infoPtr->rcSelection;
-    range = infoPtr->nRangeMax-infoPtr->nRangeMin;
-
-    if ((range <= 0) || (selMin == selMax)) SetRectEmpty(selection);
-    else
-        if (!(infoPtr->dwStyle & TBS_VERT))
-        {   //Horizontal
-            width = infoPtr->rcChannel.right-infoPtr->rcChannel.left;
-            selection->left = infoPtr->rcChannel.left+(width*selMin)/range;
-            selection->right  = infoPtr->rcChannel.left+(width*selMax)/range;
-            selection->top    = infoPtr->rcChannel.top+2;
-            selection->bottom = infoPtr->rcChannel.bottom-2;
-        } else
-        {   //Vertical
-            height = infoPtr->rcChannel.bottom-infoPtr->rcChannel.top;
-            selection->top    = infoPtr->rcChannel.top+(height*selMin)/range;
-            selection->bottom = infoPtr->rcChannel.top+(height*selMax)/range;
-            selection->left   = infoPtr->rcChannel.left+2;
-            selection->right  = infoPtr->rcChannel.right-2;
-        }
-}
-
-/* Trackbar drawing code */
-
-/* ticPos is in tic-units, not in pixels */
-
-static VOID
-TRACKBAR_DrawHorizTic(TRACKBAR_INFO *infoPtr,HDC hdc,LONG ticPos,int flags,COLORREF clrTic)
-{
-    RECT rcChannel = infoPtr->rcChannel;
-    int x,y,width,range,side;
-
-    range = infoPtr->nRangeMax-infoPtr->nRangeMin;
-    width = rcChannel.right-rcChannel.left;
-
-    if (flags & TBS_TOP)
-    {
-      y = infoPtr->rcFullThumb.top-SCALE_SPACE-1;
-      side = -1;
-    } else
-    {
-      y = infoPtr->rcFullThumb.bottom+SCALE_SPACE+1;
-      side = 1;
-    }
-    if (flags & TIC_SELECTIONMARK)
-    {
-      ticPos -= infoPtr->nRangeMin; //relative to nRangeMin
-      if (flags & TIC_SELECTIONMARKMIN) x = rcChannel.left+(width*ticPos)/range - 1;
-      else x = rcChannel.left+(width*ticPos)/range+1;
-
-      //first line
-      SetPixel(hdc,x,y+1*side,clrTic);
-      SetPixel(hdc,x,y+2*side,clrTic);
-      //point
-      if (flags & TIC_SELECTIONMARKMIN) x--; else x++;
-      SetPixel(hdc,x,y+2*side,clrTic);
-
-      return;
-    }
-
-    if ((ticPos > infoPtr->nRangeMin) && (ticPos < infoPtr->nRangeMax))
-    {
-      ticPos -= infoPtr->nRangeMin; //relative to nRangeMin
-      x = rcChannel.left+(width*ticPos)/range;
-      SetPixel(hdc,x,y,clrTic); //base
-      SetPixel(hdc,x,y+1*side,clrTic);
-      SetPixel(hdc,x,y+2*side,clrTic);
-    }
-
-    if (flags & TIC_EDGE)
-    {
-      if (flags & TIC_LEFTEDGE) x = rcChannel.left;
-      else x = rcChannel.right;
-
-      SetPixel(hdc,x,y,clrTic); //base
-      SetPixel(hdc,x,y+1*side,clrTic);
-      SetPixel(hdc,x,y+2*side,clrTic);
-      SetPixel(hdc,x,y+3*side,clrTic);
-    }
-}
-
-static VOID TRACKBAR_FillHorzTics(TRACKBAR_INFO *infoPtr,HDC hdc,int flags,COLORREF clrTic)
-{
-  RECT rect;
-  INT range = infoPtr->nRangeMax-infoPtr->nRangeMin;
-  INT width = infoPtr->rcChannel.right-infoPtr->rcChannel.left;
-  HBRUSH hbr = CreateSolidBrush(clrTic);
-
-  if (flags & TBS_TOP)
-  {
-    rect.bottom = infoPtr->rcFullThumb.top-SCALE_SPACE-1+1;
-    rect.top = rect.bottom-3;
-  } else
-  {
-    rect.top = infoPtr->rcFullThumb.bottom+SCALE_SPACE+1;
-    rect.bottom = rect.top+3;
-  }
-  rect.left = infoPtr->rcChannel.left+(width*(infoPtr->tics[0]-infoPtr->nRangeMin))/range;
-  rect.right = infoPtr->rcChannel.left+(width*(infoPtr->tics[infoPtr->uNumTics-1]-infoPtr->nRangeMin))/range+1;
-
-  FillRect(hdc,&rect,hbr);
-  DeleteObject(hbr);
-}
-
-static VOID
-TRACKBAR_DrawVertTic(TRACKBAR_INFO *infoPtr,HDC hdc,LONG ticPos,int flags,COLORREF clrTic)
-{
-    RECT rcChannel = infoPtr->rcChannel;
-    int x,y,width,range,side;
-
-    range = infoPtr->nRangeMax-infoPtr->nRangeMin;
-    width = rcChannel.bottom-rcChannel.top;
-
-    if (flags & TBS_LEFT)
-    {
-      x = infoPtr->rcFullThumb.left-SCALE_SPACE-1;
-      side = -1;
-    } else
-    {
-      x = infoPtr->rcFullThumb.right+SCALE_SPACE+1;
-      side = 1;
-    }
-
-
-    if (flags & TIC_SELECTIONMARK)
-    {
-      ticPos -= infoPtr->nRangeMin;
-      if (flags & TIC_SELECTIONMARKMIN) y = rcChannel.top+(width*ticPos)/range-1;
-      else y = rcChannel.top+(width*ticPos)/range+1;
-
-      //first line
-      SetPixel(hdc,x+1*side,y,clrTic);
-      SetPixel(hdc,x+2*side,y,clrTic);
-      //point
-      if (flags & TIC_SELECTIONMARKMIN) y--; else y++;
-      SetPixel(hdc,x+2*side,y,clrTic);
-
-      return;
-    }
-
-    if ((ticPos>infoPtr->nRangeMin) && (ticPos<infoPtr->nRangeMax))
-    {
-      ticPos -= infoPtr->nRangeMin;
-      y = rcChannel.top+(width*ticPos)/range;
-      SetPixel (hdc,x, y,clrTic); //base
-      SetPixel (hdc,x+1*side,y,clrTic);
-      SetPixel (hdc,x+2*side,y,clrTic);
-    }
-
-    if (flags & TIC_EDGE)
-    {
-      if (flags & TIC_LEFTEDGE) y = rcChannel.top;
-      else y = rcChannel.bottom;
-
-      SetPixel (hdc,x,y,clrTic); //base
-      SetPixel (hdc,x+1*side,y,clrTic);
-      SetPixel (hdc,x+2*side,y,clrTic);
-      SetPixel (hdc,x+3*side,y,clrTic);
-    }
-}
-
-static VOID TRACKBAR_FillVertTics(TRACKBAR_INFO *infoPtr,HDC hdc,int flags,COLORREF clrTic)
-{
-  RECT rect;
-  INT range = infoPtr->nRangeMax-infoPtr->nRangeMin;
-  INT width = infoPtr->rcChannel.bottom-infoPtr->rcChannel.top;
-  HBRUSH hbr = CreateSolidBrush(clrTic);
-
-  if (flags & TBS_TOP)
-  {
-    rect.right = infoPtr->rcFullThumb.left-SCALE_SPACE-1+1;
-    rect.left = rect.right-3;
-  } else
-  {
-    rect.left = infoPtr->rcFullThumb.right+SCALE_SPACE+1;
-    rect.right = rect.left+3;
-  }
-  rect.top = infoPtr->rcChannel.top+(width*(infoPtr->tics[0]-infoPtr->nRangeMin))/range;
-  rect.bottom = infoPtr->rcChannel.top+(width*(infoPtr->tics[infoPtr->uNumTics-1]-infoPtr->nRangeMin))/range+1;
-
-  FillRect(hdc,&rect,hbr);
-  DeleteObject(hbr);
-}
-
-static VOID
-TRACKBAR_DrawTics(TRACKBAR_INFO *infoPtr,HDC hdc,LONG ticPos,int flags,COLORREF clrTic)
-{
-    if (flags & TBS_VERT)
-    {
-        if ((flags & TBS_LEFT) || (flags & TBS_BOTH))
-            TRACKBAR_DrawVertTic (infoPtr,hdc,ticPos,flags | TBS_LEFT ,clrTic);
-        //TBS_RIGHT == default
-        if (!(flags & TBS_LEFT) || (flags & TBS_BOTH))
-            TRACKBAR_DrawVertTic(infoPtr,hdc,ticPos,flags & ~TBS_LEFT,clrTic);
-    } else
-    {
-      if ((flags & TBS_TOP) || (flags & TBS_BOTH))
-        TRACKBAR_DrawHorizTic(infoPtr,hdc,ticPos,flags | TBS_TOP,clrTic);
-      //TBS_BOTTOM == default
-      if (!(flags & TBS_TOP) || (flags & TBS_BOTH))
-        TRACKBAR_DrawHorizTic(infoPtr,hdc,ticPos,flags & ~TBS_TOP,clrTic);
-    }
-}
-
-//draw thumb, call only from draw!
-
-static VOID TRACKBAR_DrawThumb(TRACKBAR_INFO *infoPtr,HDC hdc)
-{
-    if (!(infoPtr->dwStyle & TBS_NOTHUMB))
-    {
-      HBRUSH hbr,hbrOld;
-      RECT thumb = infoPtr->rcThumb;
-
-      if ((infoPtr->flags & TB_DRAG_MODE) || !IsWindowEnabled(infoPtr->hwnd)) hbr = CreateSolidBrush(infoPtr->clrHighlightedThumb);
-      else hbr = infoPtr->hbrThumb;
-      hbrOld = SelectObject(hdc,hbr);
-
-      if (infoPtr->dwStyle & TBS_BOTH)
-      {
-        DrawEdge(hdc,&thumb,EDGE_RAISED,BF_RECT | BF_ADJUST);
-        FillRect(hdc,&thumb,hbr);
-      } else
-      {
-        POINT points[6];
-        RECT triangle;  /* for correct shadows of thumb */
-
-        if (infoPtr->dwStyle & TBS_VERT)
-        { //Vertical
-
-          if (infoPtr->dwStyle & TBS_LEFT)
-          {
-            HPEN oldPen,pen;
-
-            //Outline
-
-            SetPolyFillMode(hdc,WINDING);
-            points[0].x = thumb.left;
-            points[0].y = thumb.top;
-            points[1].x = thumb.left-(thumb.bottom-thumb.top)/2;
-            points[1].y = thumb.top+(thumb.bottom-thumb.top)/2;
-            points[2].x = thumb.left;
-            points[2].y = thumb.bottom;
-            points[3].x = thumb.right;
-            points[3].y = thumb.bottom;
-            points[4].x = thumb.right;
-            points[4].y = thumb.top;
-            points[5].x = points[0].x;
-            points[5].y = points[0].y;
-            Polygon(hdc,points,6);
-
-            //Edge
-
-            thumb.bottom++;
-            thumb.right++;
-            DrawEdge(hdc,&thumb,EDGE_RAISED,BF_BOTTOM | BF_TOP | BF_RIGHT);
-
-            //Draw notch
-
-            triangle.right = points[0].x;
-            triangle.top = points[0].y;
-            triangle.left = points[1].x;
-            triangle.bottom = points[1].y;
-            DrawEdge(hdc,&triangle,EDGE_RAISED,BF_DIAGONAL | BF_DIAGONAL_ENDTOPRIGHT);
-
-            //draw this line direct, DrawEdge not useful
-            pen = GetSysColorPen(COLOR_3DDKSHADOW);
-            oldPen = SelectObject(hdc,pen);
-            MoveToEx(hdc,points[1].x,points[1].y,NULL);
-            LineTo(hdc,points[2].x-1,points[2].y-1);
-            pen = GetSysColorPen(COLOR_BTNSHADOW);
-            SelectObject(hdc,pen);
-            MoveToEx(hdc,points[1].x+1,points[1].y,NULL);
-            LineTo(hdc,points[2].x,points[2].y-1);
-            SelectObject(hdc,oldPen);
-
-          } else //Right
-          {
-            HPEN oldPen,pen;
-
-            //Outline
-
-            SetPolyFillMode(hdc,WINDING);
-            points[0].x = thumb.left;
-            points[0].y = thumb.top;
-            points[1].x = thumb.left;
-            points[1].y = thumb.bottom;
-            points[2].x = thumb.right;
-            points[2].y = thumb.bottom;
-            points[3].x = thumb.right+(thumb.bottom-thumb.top)/2;
-            points[3].y = thumb.bottom-(thumb.bottom-thumb.top)/2;
-            points[4].x = thumb.right;
-            points[4].y = thumb.top;
-            points[5].x = points[0].x;
-            points[5].y = points[0].y;
-            Polygon(hdc,points,6);
-
-            //Edge
-
-            thumb.bottom++;
-            DrawEdge(hdc,&thumb,EDGE_RAISED,BF_BOTTOM | BF_TOP | BF_LEFT);
-
-            //Draw notch
-
-            //draw this line direct, DrawEdge not useful
-            pen = GetSysColorPen(COLOR_3DLIGHT);
-            oldPen = SelectObject(hdc,pen);
-            MoveToEx(hdc,points[4].x,points[4].y,NULL);
-            LineTo(hdc,points[3].x,points[3].y);
-            pen = GetSysColorPen(COLOR_BTNHIGHLIGHT);
-            SelectObject(hdc,pen);
-            MoveToEx(hdc,points[4].x,points[4].y+1,NULL);
-            LineTo(hdc,points[3].x-1,points[3].y);
-            SelectObject(hdc,oldPen);
-
-            triangle.right = points[3].x;
-            triangle.top = points[3].y;
-            triangle.left = points[2].x;
-            triangle.bottom = points[2].y;
-            DrawEdge(hdc,&triangle,EDGE_RAISED,BF_DIAGONAL | BF_DIAGONAL_ENDBOTTOMLEFT);
-          }
-        } else
-        { //Horizontal
-
-          if (infoPtr->dwStyle & TBS_TOP)
-          {
-            //Outline
-
-            SetPolyFillMode(hdc,WINDING);
-            points[0].x = thumb.left;
-            points[0].y = thumb.top;
-            points[1].x = thumb.left+(thumb.right-thumb.left)/2;
-            points[1].y = thumb.top-(thumb.right-thumb.left)/2;
-            points[2].x = thumb.right;
-            points[2].y = thumb.top;
-            points[3].x = thumb.right;
-            points[3].y = thumb.bottom;
-            points[4].x = thumb.left;
-            points[4].y = thumb.bottom;
-            points[5].x = points[0].x;
-            points[5].y = points[0].y;
-            Polygon(hdc,points,6);
-
-            //Edge
-
-            thumb.right++;
-            thumb.bottom++;
-            DrawEdge(hdc,&thumb,EDGE_RAISED,BF_BOTTOM | BF_LEFT | BF_RIGHT);
-
-            //Draw notch
-
-            triangle.left = points[0].x;
-            triangle.bottom = points[0].y;
-            triangle.right = points[1].x;
-            triangle.top = points[1].y;
-            DrawEdge(hdc,&triangle,EDGE_RAISED,BF_DIAGONAL | BF_DIAGONAL_ENDTOPRIGHT);
-
-
-            triangle.left = points[1].x;
-            triangle.top = points[1].y;
-            triangle.right = points[2].x;
-            triangle.bottom = points[2].y;
-            DrawEdge(hdc,&triangle,EDGE_RAISED,BF_DIAGONAL | BF_DIAGONAL_ENDBOTTOMRIGHT);
-
-          } else //Bottom
-          {
-
-            //Outline
-
-            SetPolyFillMode(hdc,WINDING);
-            points[0].x = thumb.left;
-            points[0].y = thumb.top;
-            points[1].x = thumb.right;
-            points[1].y = thumb.top;
-            points[2].x = thumb.right;
-            points[2].y = thumb.bottom;
-            points[3].x = thumb.right-(thumb.right-thumb.left)/2;
-            points[3].y = thumb.bottom+(thumb.right-thumb.left)/2;
-            points[4].x = thumb.left;
-            points[4].y = thumb.bottom;
-            points[5].x = points[0].x;
-            points[5].y = points[0].y;
-            Polygon(hdc,points,6);
-
-            //Edge
-
-            thumb.right++;
-            thumb.bottom++;
-            DrawEdge(hdc,&thumb,EDGE_RAISED,BF_TOP | BF_LEFT | BF_RIGHT);
-
-            //Draw notch
-
-            triangle.right = points[2].x;
-            triangle.top = points[2].y;
-            triangle.left = points[3].x;
-            triangle.bottom = points[3].y;
-            DrawEdge(hdc,&triangle,EDGE_RAISED,BF_DIAGONAL | BF_DIAGONAL_ENDBOTTOMLEFT);
-            triangle.right = points[3].x;
-            triangle.bottom = points[3].y;
-            triangle.left = points[4].x;
-            triangle.top = points[4].y;
-            DrawEdge(hdc,&triangle,EDGE_RAISED,BF_DIAGONAL | BF_DIAGONAL_ENDTOPLEFT);
-
-          }
-        }
-      }
-      SelectObject(hdc,hbrOld);
-      if (hbr != infoPtr->hbrThumb) DeleteObject(hbr);
-    }
-}
-
-//draw the trackbar
-
-static VOID TRACKBAR_Draw(TRACKBAR_INFO *infoPtr,HDC hdc)
-{
-    RECT rcClient,rcChannel,rcSelection;
-    HBRUSH hBrush;
-    int i;
-    NMCUSTOMDRAW cdraw;
-    LRESULT cdctlres,cdres;
-
-    GetClientRect(infoPtr->hwnd,&rcClient);
-
-    //Custom draw
-    cdraw.dwDrawStage  = CDDS_PREPAINT;
-    cdraw.hdc          = hdc;
-    cdraw.dwItemSpec   = 0;
-    cdraw.uItemState   = infoPtr->bFocus ? CDIS_FOCUS:CDIS_DEFAULT;
-    cdraw.rc           = rcClient;
-    cdraw.lItemlParam  = 0;
-
-    cdctlres = sendNotify(infoPtr->hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
-
-    if (cdctlres & CDRF_SKIPDEFAULT) return;
-
-    //Background
-    hBrush = CreateSolidBrush(infoPtr->clrBk);
-    FillRect(hdc,&rcClient,hBrush);
-    DeleteObject(hBrush);
-
-    if (infoPtr->flags & TB_DRAGPOSVALID)
-    {
-      infoPtr->nPos = infoPtr->dragPos;
-      infoPtr->flags |= TB_THUMBPOSCHANGED;
-    }
-
-    if (infoPtr->flags & TB_THUMBCHANGED)
-    {
-      if (infoPtr->flags & TB_THUMBSIZECHANGED)
-      {
-        TRACKBAR_CalcChannel(infoPtr);
-        TRACKBAR_CalcSelection(infoPtr);
-      }
-      TRACKBAR_CalcThumb(infoPtr);
-    }
-    if (infoPtr->flags & TB_SELECTIONCHANGED) TRACKBAR_CalcSelection(infoPtr);
-    infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED | TB_DRAGPOSVALID);
-
-    /* draw channel */
-
-    if (cdctlres & CDRF_NOTIFYITEMDRAW)
-    {
-      cdraw.dwDrawStage    = CDDS_ITEMPREPAINT;
-      cdraw.dwItemSpec     = TBCD_CHANNEL;
-      cdraw.rc             = infoPtr->rcChannel;
-
-      cdres = sendNotify(infoPtr->hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
-    } else cdres = 0;
-
-    if (!(cdres & CDRF_SKIPDEFAULT))
-    {
-      rcChannel = infoPtr->rcChannel;
-      rcSelection = infoPtr->rcSelection;
-      DrawEdge(hdc,&rcChannel,EDGE_SUNKEN,BF_RECT | BF_ADJUST);
-
-      if (infoPtr->dwStyle & TBS_ENABLESELRANGE)           /* fill the channel */
-      {
-        HBRUSH hbr = CreateSolidBrush(RGB(255,255,255));
-        FillRect(hdc,&rcChannel,hbr);
-        DeleteObject(hbr);
-        if (((infoPtr->dwStyle & TBS_VERT) && (rcSelection.top != rcSelection.bottom)) ||
-           ((!(infoPtr->dwStyle & TBS_VERT)) && (rcSelection.left != rcSelection.right)))
-           {
-             hbr = CreateSolidBrush (COLOR_HIGHLIGHT);
-             FillRect (hdc,&rcSelection,hbr);
-             DeleteObject(hbr);
-           }
-      }
-
-      if (cdctlres & CDRF_NOTIFYITEMDRAW)
-      {
-        cdraw.dwDrawStage    = CDDS_ITEMPOSTPAINT;
-
-        sendNotify(infoPtr->hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
-      }
-    }
-
-    /* draw tics */
-
-    if (cdctlres & CDRF_NOTIFYITEMDRAW)
-    {
-      cdraw.dwDrawStage    = CDDS_ITEMPREPAINT;
-      cdraw.dwItemSpec     = TBCD_TICS;
-      SetRectEmpty(&cdraw.rc);
-
-      cdres = sendNotify(infoPtr->hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
-    } else cdres = 0;
-
-    if (!(cdres & CDRF_SKIPDEFAULT))
-    {
-      if (!(infoPtr->dwStyle & TBS_NOTICKS))
-      {
-        int ticFlags = infoPtr->dwStyle & 0x0f;
-        COLORREF clrTic = GetSysColor(COLOR_3DDKSHADOW);
-        INT range = infoPtr->nRangeMax-infoPtr->nRangeMin;
-        INT width = (infoPtr->dwStyle & TBS_VERT) ? rcChannel.bottom-rcChannel.top:rcChannel.right-rcChannel.left;
-
-        //check if maximum of visible marks is reached
-        if ((infoPtr->dwStyle & TBS_AUTOTICKS) && (infoPtr->uNumTics > 1) && ((INT)(width*infoPtr->tics[0]/range) == (INT)(width*infoPtr->tics[1]/range)))
-        {
-          //draw all pixels at once -> much faster
-          if (infoPtr->dwStyle & TBS_VERT)
-          {
-            if ((ticFlags & TBS_LEFT) || (ticFlags & TBS_BOTH))
-              TRACKBAR_FillVertTics(infoPtr,hdc,ticFlags | TBS_LEFT,clrTic);
-            if (!(ticFlags & TBS_LEFT) || (ticFlags & TBS_BOTH))
-              TRACKBAR_FillVertTics(infoPtr,hdc,ticFlags & ~TBS_LEFT,clrTic);
-          } else
-          {
-            if ((ticFlags & TBS_TOP) || (ticFlags & TBS_BOTH))
-              TRACKBAR_FillHorzTics(infoPtr,hdc,ticFlags | TBS_TOP,clrTic);
-            if (!(ticFlags & TBS_TOP) || (ticFlags & TBS_BOTH))
-              TRACKBAR_FillHorzTics(infoPtr,hdc,ticFlags & ~TBS_TOP,clrTic);
-          }
-        } else
-        {
-          for (i = 0;i < infoPtr->uNumTics;i++)
-              TRACKBAR_DrawTics(infoPtr,hdc,infoPtr->tics[i],ticFlags,clrTic);
-        }
-
-        TRACKBAR_DrawTics(infoPtr,hdc,0,ticFlags | TIC_LEFTEDGE,clrTic);
-        TRACKBAR_DrawTics(infoPtr,hdc,0,ticFlags | TIC_RIGHTEDGE,clrTic);
-
-        if ((infoPtr->dwStyle & TBS_ENABLESELRANGE) &&
-              ((infoPtr->dwStyle & TBS_VERT && rcSelection.bottom != rcSelection.top) ||
-              (!(infoPtr->dwStyle & TBS_VERT) && rcSelection.left != rcSelection.right)))
-              {
-                TRACKBAR_DrawTics(infoPtr,hdc,infoPtr->nSelMin,ticFlags | TIC_SELECTIONMARKMIN,clrTic);
-                TRACKBAR_DrawTics(infoPtr,hdc,infoPtr->nSelMax,ticFlags | TIC_SELECTIONMARKMAX,clrTic);
-              }
-      }
-
-      if (cdctlres & CDRF_NOTIFYITEMDRAW)
-      {
-        cdraw.dwDrawStage    = CDDS_ITEMPOSTPAINT;
-
-        sendNotify(infoPtr->hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
-      }
-    }
-
-    /* draw thumb */
-
-    if (cdctlres & CDRF_NOTIFYITEMDRAW)
-    {
-      cdraw.dwDrawStage    = CDDS_ITEMPREPAINT;
-      cdraw.dwItemSpec     = TBCD_THUMB;
-      cdraw.rc             = infoPtr->rcFullThumb;
-
-      cdres = sendNotify(infoPtr->hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
-    } else cdres = 0;
-
-    if (!(cdres & CDRF_SKIPDEFAULT))
-    {
-      TRACKBAR_DrawThumb(infoPtr,hdc);
-
-      if (cdctlres & CDRF_NOTIFYITEMDRAW)
-      {
-        cdraw.dwDrawStage    = CDDS_ITEMPOSTPAINT;
-
-        sendNotify(infoPtr->hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
-      }
-
-    }
-
-    if (infoPtr->bFocus && IsWindowEnabled(infoPtr->hwnd)) DrawFocusRect(hdc,&rcClient);
-
-    if (cdctlres & CDRF_NOTIFYPOSTPAINT)
-    {
-      cdraw.dwDrawStage    = CDDS_POSTPAINT;
-      cdraw.dwItemSpec     = 0;
-      GetClientRect(infoPtr->hwnd,&cdraw.rc);
-
-      sendNotify(infoPtr->hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
-    }
-
-}
-
-//update thumb position
-
-static VOID TRACKBAR_UpdateThumbPosition(TRACKBAR_INFO *infoPtr,INT lastPos,BOOL mustRedraw)
-{
-   HDC hdc;
-   RECT lastRect,newRect,updateRect;
-   HDC hdcCompatible;
-   HBITMAP bitmap,oldbmp;
-
-   //last
-   lastRect = infoPtr->rcFullThumb;
-
-   //new
-   if (infoPtr->flags & TB_DRAGPOSVALID)
-   {
-     infoPtr->nPos = infoPtr->dragPos;
-     infoPtr->flags &= ~TB_DRAGPOSVALID;
-   }
-   if (!mustRedraw && (infoPtr->nPos == lastPos)) return;
-
-   if (infoPtr->dwStyle & TBS_NOTHUMB) return;
-
-   TRACKBAR_CalcThumb(infoPtr);
-   infoPtr->flags &= ~TB_THUMBCHANGED;
-   newRect = infoPtr->rcFullThumb;
-
-   //same rect?
-   if (!mustRedraw && EqualRect(&lastRect,&newRect)) return;
-
-   //3D frame adjustation
-   lastRect.right++;
-   lastRect.bottom++;
-   newRect.right++;
-   newRect.bottom++;
-
-   //BitBlt from memory -> no flickering
-   updateRect.left = MIN(lastRect.left,newRect.left);
-   updateRect.right = MAX(lastRect.right,newRect.right);
-   updateRect.top = MIN(lastRect.top,newRect.top);
-   updateRect.bottom = MAX(lastRect.bottom,newRect.bottom);
-   hdc = GetDC(infoPtr->hwnd);
-   hdcCompatible = CreateCompatibleDC(hdc);
-   bitmap = CreateCompatibleBitmap(hdc,updateRect.right,updateRect.bottom);
-   oldbmp = SelectObject(hdcCompatible,bitmap);
-   TRACKBAR_Draw(infoPtr,hdcCompatible);
-   if (infoPtr->dwStyle & TBS_VERT)
-   {
-     if ((lastRect.top > newRect.top) && (lastRect.top < newRect.bottom))
-       BitBlt(hdc,newRect.left,newRect.top,newRect.right-newRect.left,lastRect.bottom-newRect.top,hdcCompatible,newRect.left,newRect.top,SRCCOPY);
-     else if ((lastRect.bottom < newRect.bottom) && (lastRect.bottom > newRect.top))
-       BitBlt(hdc,lastRect.left,lastRect.top,lastRect.right-lastRect.left,newRect.bottom-lastRect.top,hdcCompatible,lastRect.left,lastRect.top,SRCCOPY);
-     else
-     {
-       BitBlt(hdc,lastRect.left,lastRect.top,lastRect.right-lastRect.left,lastRect.bottom-lastRect.top,hdcCompatible,lastRect.left,lastRect.top,SRCCOPY);
-       BitBlt(hdc,newRect.left,newRect.top,newRect.right-newRect.left,newRect.bottom-newRect.top,hdcCompatible,newRect.left,newRect.top,SRCCOPY);
-     }
-   } else
-   {
-     if ((lastRect.right > newRect.left) && (lastRect.right < newRect.right))
-       BitBlt(hdc,lastRect.left,lastRect.top,newRect.right-lastRect.left,lastRect.bottom-lastRect.top,hdcCompatible,lastRect.left,lastRect.top,SRCCOPY);
-     else if ((lastRect.left < newRect.right) && (lastRect.left > newRect.left))
-       BitBlt(hdc,newRect.left,newRect.top,lastRect.right-newRect.left,newRect.bottom-newRect.top,hdcCompatible,newRect.left,newRect.top,SRCCOPY);
-     else
-     {
-       BitBlt(hdc,lastRect.left,lastRect.top,lastRect.right-lastRect.left,lastRect.bottom-lastRect.top,hdcCompatible,lastRect.left,lastRect.top,SRCCOPY);
-       BitBlt(hdc,newRect.left,newRect.top,newRect.right-newRect.left,newRect.bottom-newRect.top,hdcCompatible,newRect.left,newRect.top,SRCCOPY);
-     }
-   }
-   SelectObject(hdcCompatible,oldbmp);
-   DeleteObject(bitmap);
-   DeleteDC(hdcCompatible);
-   ReleaseDC(infoPtr->hwnd,hdc);
-}
-
-//redraw everything
-
-static VOID TRACKBAR_Refresh(TRACKBAR_INFO *infoPtr)
-{
-   HDC hdc;
-
-   hdc = GetDC(infoPtr->hwnd);
-   TRACKBAR_Draw(infoPtr,hdc);
-   ReleaseDC(infoPtr->hwnd,hdc);
-}
-
-static VOID
-TRACKBAR_AlignBuddies(TRACKBAR_INFO *infoPtr)
-{
-    HWND hwndParent = GetParent(infoPtr->hwnd);
-    RECT rcSelf,rcBuddy;
-    INT x, y;
-
-    GetWindowRect(infoPtr->hwnd,&rcSelf);
-    MapWindowPoints(HWND_DESKTOP,hwndParent,(LPPOINT)&rcSelf,2);
-
-    /* align buddy left or above */
-    if (infoPtr->hwndBuddyLA)
-    {
-      GetWindowRect(infoPtr->hwndBuddyLA,&rcBuddy);
-
-      if (infoPtr->dwStyle & TBS_VERT)
-      { //above
-        x = (infoPtr->rcChannel.right+infoPtr->rcChannel.left)/2-(rcBuddy.right-rcBuddy.left)/2+rcSelf.left;
-        y = rcSelf.top-(rcBuddy.bottom-rcBuddy.top);
-      } else
-      { //left
-        x = rcSelf.left-(rcBuddy.right-rcBuddy.left);
-        y = (infoPtr->rcChannel.bottom+infoPtr->rcChannel.top)/2-(rcBuddy.bottom-rcBuddy.top)/2+rcSelf.top;
-      }
-
-      SetWindowPos(infoPtr->hwndBuddyLA,0,x,y,0,0,SWP_NOZORDER | SWP_NOSIZE);
-    }
-
-
-    /* align buddy right or below */
-    if (infoPtr->hwndBuddyRB)
-    {
-      GetWindowRect(infoPtr->hwndBuddyRB,&rcBuddy);
-
-      if (infoPtr->dwStyle & TBS_VERT)
-      { //below
-        x = (infoPtr->rcChannel.right+infoPtr->rcChannel.left)/2-(rcBuddy.right-rcBuddy.left)/2+rcSelf.left;
-        y = rcSelf.bottom;
-      } else
-      { //right
-        x = rcSelf.right;
-        y = (infoPtr->rcChannel.bottom+infoPtr->rcChannel.top)/2-(rcBuddy.bottom-rcBuddy.top)/2+rcSelf.top;
-      }
-
-      SetWindowPos(infoPtr->hwndBuddyRB,0,x,y,0,0,SWP_NOZORDER | SWP_NOSIZE);
-    }
-}
-
-static LRESULT
-TRACKBAR_ClearSel(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    if (infoPtr->nSelMin != infoPtr->nSelMax)
-    {
-      infoPtr->nSelMin = 0;
-      infoPtr->nSelMax = 0;
-      infoPtr->flags |= TB_SELECTIONCHANGED;
-
-      if ((BOOL)wParam) TRACKBAR_Refresh(infoPtr);
-    }
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_ClearTics(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    if (!(infoPtr->dwStyle & (TBS_AUTOTICKS | TBS_NOTICKS))) return 0;
-
-    if (infoPtr->tics)
-    {
-      COMCTL32_Free(infoPtr->tics);
-      infoPtr->tics = NULL;
-      infoPtr->uNumTics = 0;
-
-      if (wParam) TRACKBAR_Refresh(infoPtr);
-    }
-
-    return 0;
-}
-
-
-static LRESULT
-TRACKBAR_GetBuddy(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    if (wParam)
-      return (LRESULT)infoPtr->hwndBuddyLA; //left or above
-    else
-      return (LRESULT)infoPtr->hwndBuddyRB; //right or below
-}
-
-static LRESULT
-TRACKBAR_GetChannelRect(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    LPRECT lprc = (LPRECT)lParam;
-
-    if (lprc == NULL) return 0;
-
-    CopyRect(lprc,&infoPtr->rcChannel);
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_GetLineSize(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    return infoPtr->nLineSize;
-}
-
-
-static LRESULT
-TRACKBAR_GetNumTics(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    if (infoPtr->dwStyle & TBS_NOTICKS) return 0;
-
-    return infoPtr->uNumTics+2; //includes last and first tick
-}
-
-static LRESULT
-TRACKBAR_GetPageSize(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    return infoPtr->nPageSize;
-}
-
-
-static LRESULT
-TRACKBAR_GetPos(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    return infoPtr->nPos;
-}
-
-
-static LRESULT
-TRACKBAR_GetRangeMax(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    return infoPtr->nRangeMax;
-}
-
-
-static LRESULT
-TRACKBAR_GetRangeMin(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    return infoPtr->nRangeMin;
-}
-
-
-static LRESULT
-TRACKBAR_GetSelEnd(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    return infoPtr->nSelMax;
-}
-
-
-static LRESULT
-TRACKBAR_GetSelStart(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    return infoPtr->nSelMin;
-}
-
-
-static LRESULT
-TRACKBAR_GetThumbLength(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    return infoPtr->uThumbLen;
-}
-
-static LRESULT
-TRACKBAR_GetPTics(TRACKBAR_INFO *infoPtr)
-{
-    return (LRESULT)infoPtr->tics;
-}
-
-static LRESULT
-TRACKBAR_GetThumbRect(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    LPRECT lprc = (LPRECT)lParam;
-
-    if (lprc == NULL) return 0;
-
-    CopyRect(lprc,&infoPtr->rcFullThumb);
-
-    return 0;
-}
-
-
-static LRESULT
-TRACKBAR_GetTic(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT iTic;
-
-    iTic = (INT)wParam;
-    if ((iTic < 0) || (iTic > infoPtr->uNumTics)) return -1;
-
-    return (LRESULT)infoPtr->tics[iTic];
-
-}
-
-
-static LRESULT
-TRACKBAR_GetTicPos(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT iTic, range, width, pos;
-
-
-    iTic = (INT)wParam;
-    if ((iTic < 0) || (iTic > infoPtr->uNumTics)) return -1;
-
-    range = infoPtr->nRangeMax-infoPtr->nRangeMin;
-    width = infoPtr->rcChannel.right-infoPtr->rcChannel.left;
-    pos = infoPtr->rcChannel.left+(width*(infoPtr->tics[iTic]-infoPtr->nRangeMin))/range;
-
-    return (LRESULT) pos;
-}
-
-
-static LRESULT
-TRACKBAR_GetToolTips(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    if (infoPtr->dwStyle & TBS_TOOLTIPS)
-        return (LRESULT)infoPtr->hwndToolTip;
-    return 0;
-}
-
-
-static LRESULT
-TRACKBAR_SetBuddy(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    HWND hwndTemp;
-
-    if (!(GetParent(lParam) == GetParent(infoPtr->hwnd))) return wParam ? infoPtr->hwndBuddyLA:infoPtr->hwndBuddyRB;
-
-    if (wParam)
-    {
-      /* buddy is left or above */
-      hwndTemp = infoPtr->hwndBuddyLA;
-      infoPtr->hwndBuddyLA = (HWND)lParam;
-    } else
-    {
-      /* buddy is right or below */
-      hwndTemp = infoPtr->hwndBuddyRB;
-      infoPtr->hwndBuddyRB = (HWND)lParam;
-    }
-
-    TRACKBAR_AlignBuddies(infoPtr);
-
-    return (LRESULT)hwndTemp;
-}
-
-
-static LRESULT
-TRACKBAR_SetLineSize(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT nTemp = infoPtr->nLineSize;
-
-    infoPtr->nLineSize = (INT)lParam;
-
-    return nTemp;
-}
-
-
-static LRESULT
-TRACKBAR_SetPageSize(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT nTemp = infoPtr->nPageSize;
-
-    infoPtr->nPageSize = (INT)lParam;
-
-    return nTemp;
-}
-
-
-static LRESULT
-TRACKBAR_SetPos(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT lastPos = infoPtr->nPos;
-
-    infoPtr->nPos = (INT)LOWORD(lParam);
-
-    if (infoPtr->nPos < infoPtr->nRangeMin)
-        infoPtr->nPos = infoPtr->nRangeMin;
-
-    if (infoPtr->nPos > infoPtr->nRangeMax)
-        infoPtr->nPos = infoPtr->nRangeMax;
-    infoPtr->flags |= TB_THUMBPOSCHANGED;
-
-    if (wParam) TRACKBAR_UpdateThumbPosition(infoPtr,lastPos,FALSE);
-
-    return 0;
-}
-
-
-static LRESULT
-TRACKBAR_SetRange(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    int newMin,newMax;
-
-    newMin = (INT)LOWORD(lParam);
-    newMax = (INT)HIWORD(lParam);
-
-    if (newMin == newMax) return 0;
-    if (newMin > newMax)
-    { //exchange
-      int x;
-
-      x = newMin;
-      newMin = newMax;
-      newMax = x;
-    }
-    if ((newMin == infoPtr->nRangeMin) && (newMax == infoPtr->nRangeMax)) return 0;
-
-    infoPtr->nRangeMin = newMin;
-    infoPtr->nRangeMax = newMax;
-
-    if (infoPtr->nPos < infoPtr->nRangeMin)
-    {
-      infoPtr->nPos = infoPtr->nRangeMin;
-      infoPtr->flags |= TB_THUMBPOSCHANGED;
-    }
-    if (infoPtr->nPos > infoPtr->nRangeMax)
-    {
-      infoPtr->nPos = infoPtr->nRangeMax;
-      infoPtr->flags |= TB_THUMBPOSCHANGED;
-    }
-
-    if (infoPtr->nSelMin < infoPtr->nRangeMin)
-    {
-      infoPtr->nSelMin = infoPtr->nRangeMin;
-      infoPtr->flags |= TB_SELECTIONCHANGED;
-    }
-    if (infoPtr->nSelMin > infoPtr->nRangeMax)
-    {
-      infoPtr->nSelMin = infoPtr->nRangeMax;
-      infoPtr->flags |= TB_SELECTIONCHANGED;
-    }
-    if (infoPtr->nSelMax < infoPtr->nRangeMin)
-    {
-      infoPtr->nSelMax = infoPtr->nRangeMin;
-      infoPtr->flags |= TB_SELECTIONCHANGED;
-    }
-    if (infoPtr->nSelMax > infoPtr->nRangeMax)
-    {
-      infoPtr->nSelMax = infoPtr->nRangeMax;
-      infoPtr->flags |= TB_SELECTIONCHANGED;
-    }
-
-    infoPtr->nPageSize = (infoPtr->nRangeMax-infoPtr->nRangeMin)/5;
-    if (infoPtr->nPageSize == 0) infoPtr->nPageSize = 1;
-    TRACKBAR_RecalculateTics(infoPtr,TRUE);
-
-    if (wParam) TRACKBAR_Refresh(infoPtr);
-
-    return 0;
-}
-
-
-static LRESULT
-TRACKBAR_SetRangeMax(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    if ((INT)lParam <= infoPtr->nRangeMin) return 0;
-    if (infoPtr->nRangeMax == (INT)lParam) return 0;
-
-    infoPtr->nRangeMax = (INT)lParam;
-    if (infoPtr->nPos > infoPtr->nRangeMax)
-    {
-      infoPtr->nPos = infoPtr->nRangeMax;
-      infoPtr->flags |=TB_THUMBPOSCHANGED;
-    }
-
-    infoPtr->nPageSize = (infoPtr->nRangeMax-infoPtr->nRangeMin)/5;
-    if (infoPtr->nPageSize == 0) infoPtr->nPageSize = 1;
-    TRACKBAR_RecalculateTics(infoPtr,TRUE);
-
-    if (wParam) TRACKBAR_Refresh(infoPtr);
-
-    return 0;
-}
-
-
-static LRESULT
-TRACKBAR_SetRangeMin(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    if ((INT)lParam >= infoPtr->nRangeMax) return 0;
-    if (infoPtr->nRangeMin == (INT)lParam) return 0;
-
-    infoPtr->nRangeMin = (INT)lParam;
-    if (infoPtr->nPos < infoPtr->nRangeMin)
-    {
-      infoPtr->nPos = infoPtr->nRangeMin;
-      infoPtr->flags |=TB_THUMBPOSCHANGED;
-    }
-
-    infoPtr->nPageSize = (infoPtr->nRangeMax-infoPtr->nRangeMin)/5;
-    if (infoPtr->nPageSize == 0) infoPtr->nPageSize = 1;
-    TRACKBAR_RecalculateTics(infoPtr,TRUE);
-
-    if (wParam) TRACKBAR_Refresh(infoPtr);
-
-    return 0;
-}
-
-
-static LRESULT
-TRACKBAR_SetTicFreq(TRACKBAR_INFO *infoPtr,WPARAM wParam)
-{
-    if (infoPtr->uTicFreq == (UINT)wParam) return 0;
-
-    if (!(infoPtr->dwStyle & TBS_AUTOTICKS)) return 0;
-
-    infoPtr->uTicFreq = (UINT)wParam;
-
-    TRACKBAR_RecalculateTics(infoPtr,FALSE);
-
-    TRACKBAR_Refresh(infoPtr);
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_SetSel(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT newMin,newMax,oldMin,oldMax;
-
-    oldMin = infoPtr->nSelMin;
-    oldMax = infoPtr->nSelMax;
-    newMin = (INT)LOWORD(lParam);
-    newMax = (INT)HIWORD(lParam);
-
-    if ((infoPtr->nSelMin == newMin) && (infoPtr->nSelMax == newMax)) return 0;
-    infoPtr->nSelMin = newMin;
-    infoPtr->nSelMax = newMax;
-
-    if (infoPtr->nSelMin < infoPtr->nRangeMin) infoPtr->nSelMin = infoPtr->nRangeMin;
-    if (infoPtr->nSelMin > infoPtr->nRangeMax) infoPtr->nSelMin = infoPtr->nRangeMax;
-    if (infoPtr->nSelMax > infoPtr->nRangeMax) infoPtr->nSelMax = infoPtr->nRangeMax;
-    if (infoPtr->nSelMax < infoPtr->nRangeMin) infoPtr->nSelMax = infoPtr->nRangeMin;
-
-    if (infoPtr->nSelMin > infoPtr->nSelMax) infoPtr->nSelMin = infoPtr->nSelMax;
-
-    if (!(infoPtr->dwStyle & TBS_ENABLESELRANGE)) return 0;
-
-    if ((oldMin != newMin) || (oldMax != newMax))
-    {
-      infoPtr->flags |= TB_SELECTIONCHANGED;
-      if (wParam) TRACKBAR_Refresh(infoPtr);
-    }
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_SetSelEnd(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT oldMax;
-
-    if (infoPtr->nSelMax == (INT)lParam) return 0;
-
-    oldMax = infoPtr->nSelMax;
-    infoPtr->nSelMax = (INT)lParam;
-
-    if (infoPtr->nSelMax > infoPtr->nRangeMax) infoPtr->nSelMax = infoPtr->nRangeMax;
-    if (infoPtr->nSelMax < infoPtr->nRangeMin) infoPtr->nSelMax = infoPtr->nRangeMin;
-
-    if (infoPtr->nSelMin > infoPtr->nSelMax) infoPtr->nSelMin = infoPtr->nSelMax;
-
-    if (!(infoPtr->dwStyle & TBS_ENABLESELRANGE)) return 0;
-
-    if (oldMax != infoPtr->nSelMax)
-    {
-      infoPtr->flags |= TB_SELECTIONCHANGED;
-      if (wParam) TRACKBAR_Refresh(infoPtr);
-    }
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_SetSelStart(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT oldMin;
-
-    if (infoPtr->nSelMin == (INT)lParam) return 0;
-
-    oldMin = infoPtr->nSelMin;
-    infoPtr->nSelMin = (INT)lParam;
-
-    if (infoPtr->nSelMin < infoPtr->nRangeMin) infoPtr->nSelMin = infoPtr->nRangeMin;
-    if (infoPtr->nSelMin > infoPtr->nRangeMax) infoPtr->nSelMin = infoPtr->nRangeMax;
-
-    if (infoPtr->nSelMin > infoPtr->nSelMax) infoPtr->nSelMin = infoPtr->nSelMax;
-
-    if (!(infoPtr->dwStyle & TBS_ENABLESELRANGE)) return 0;
-
-    if (oldMin != infoPtr->nSelMin)
-    {
-      infoPtr->flags |= TB_SELECTIONCHANGED;
-      if (wParam) TRACKBAR_Refresh(infoPtr);
-    }
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_SetThumbLength(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    if (infoPtr->uThumbLen == (UINT)wParam) return 0;
-
-    if (infoPtr->dwStyle & TBS_FIXEDLENGTH) return 0;
-
-    infoPtr->uThumbLen = MAX((UINT)wParam,THUMB_MINLEN);
-    infoPtr->flags |= TB_THUMBSIZECHANGED | TB_THUMBCHANGED;
-
-    TRACKBAR_Refresh(infoPtr);
-
-    return 0;
-}
-
-static void TRACKBAR_QuickSort(LPLONG list,INT lo,INT hi)
-{
-  INT i,j,x,y;
-
-  i = lo;
-  j = hi;
-  x = list[(lo+hi)/2];
-  do
-  {
-    while (list[i] < x) i++;
-    while (x < list[j]) j--;
-    if (i <= j)
-    {
-      y = list[i];
-      list[i] = list[j];
-      list[j] = y;
-      i++;
-      j--;
-    }
-  } while (i <= j);
-  if (lo < j) TRACKBAR_QuickSort(list,lo,j);
-  if (i < hi) TRACKBAR_QuickSort(list,i,hi);
-}
-
-static LRESULT
-TRACKBAR_SetTic(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT nPos = (INT)lParam;
-    INT x;
-
-    if (!(infoPtr->dwStyle & (TBS_AUTOTICKS | TBS_NOTICKS))) return 0;
-
-    if ((nPos < infoPtr->nRangeMin) || (nPos > infoPtr->nRangeMax)) return FALSE;
-
-    //Check if tick exists
-    for (x = 0;x < infoPtr->uNumTics;x++)
-    {
-      if (infoPtr->tics[x] == nPos) return TRUE; //value is ok
-    }
-
-    infoPtr->uNumTics++;
-    infoPtr->tics = (LONG*)COMCTL32_ReAlloc(infoPtr->tics,infoPtr->uNumTics*sizeof(DWORD));
-    infoPtr->tics[infoPtr->uNumTics-1] = nPos;
-
-    //Quicksort the list
-    TRACKBAR_QuickSort(infoPtr->tics,0,infoPtr->uNumTics-1);
-
-    TRACKBAR_Refresh(infoPtr);
-
-    return TRUE;
-}
-
-static LRESULT
-TRACKBAR_SetTipSide(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT fTemp = infoPtr->fLocation;
-
-    if (infoPtr->dwStyle & TBS_VERT)
-    {
-      if ((wParam == TBTS_LEFT) || (wParam == TBTS_RIGHT)) infoPtr->fLocation = (INT)wParam;
-    } else
-    {
-      if ((wParam == TBTS_TOP) || (wParam == TBTS_BOTTOM)) infoPtr->fLocation = (INT)wParam;
-    }
-
-    return fTemp;
-}
-
-static LRESULT
-TRACKBAR_SetToolTips(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    infoPtr->hwndToolTip = (HWND)wParam;
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_InitializeThumb(TRACKBAR_INFO *infoPtr)
-{
-    RECT clientRect;
-    INT scaleSize;
-
-    GetClientRect(infoPtr->hwnd,&clientRect);
-    infoPtr->uThumbLen = (infoPtr->dwStyle & TBS_ENABLESELRANGE) ? THUMB_LEN_SEL:THUMB_LEN;   /* initial thumb length */
-
-    scaleSize = 2*BORDER_SIZE;
-    if (infoPtr->dwStyle & TBS_NOTICKS) scaleSize += 0;
-    else if (infoPtr->dwStyle & TBS_BOTH) scaleSize += 2*(SCALE_SIZE+SCALE_SPACE);
-    else scaleSize += SCALE_SIZE+SCALE_SPACE;
-
-    if (infoPtr->dwStyle & TBS_VERT)
-    {
-      INT width = clientRect.right-clientRect.left;
-
-      if (infoPtr->uThumbLen+scaleSize > width) infoPtr->uThumbLen = MAX(width-scaleSize,THUMB_MINLEN);
-    } else
-    {
-      INT height = clientRect.bottom-clientRect.top;
-
-      if (infoPtr->uThumbLen+scaleSize > height) infoPtr->uThumbLen = MAX(height-scaleSize,THUMB_MINLEN);
-    }
-
-    TRACKBAR_CalcChannel(infoPtr);
-    TRACKBAR_CalcThumb(infoPtr);
-
-    infoPtr->flags &= ~TB_SELECTIONCHANGED;
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_InitColors(TRACKBAR_INFO *infoPtr,BOOL redraw)
-{
-  infoPtr->clrBk = GetSysColor(COLOR_3DFACE);
-  infoPtr->clrHighlightedThumb = GetSysColor(COLOR_3DHILIGHT);
-
-  if (redraw) TRACKBAR_Refresh(infoPtr);
-
-  return 0;
-}
-
-static LRESULT
-TRACKBAR_Create(HWND hwnd,WPARAM wParam,LPARAM lParam)
-{
-    TRACKBAR_INFO *infoPtr;
-    LOGBRUSH lb;
-
-    infoPtr = (TRACKBAR_INFO*)initControl(hwnd,sizeof(TRACKBAR_INFO));
-
-    /* set default values */
-    infoPtr->hwnd    = hwnd;
-    infoPtr->dwStyle = GetWindowLongA(hwnd,GWL_STYLE);;
-
-    infoPtr->nRangeMin  = 0;
-    infoPtr->nRangeMax  = 100;
-    infoPtr->nLineSize  = 1;
-    infoPtr->nPageSize  = 20;
-    infoPtr->nSelMin    = 0;
-    infoPtr->nSelMax    = 0;
-    infoPtr->nPos       = 0;
-
-    infoPtr->uNumTics   = 0;    /* start and end tic are not included in count*/
-    infoPtr->uTicFreq   = 1;
-    infoPtr->tics       = NULL;
-
-    /* Create dotted brush */
-    lb.lbStyle = BS_PATTERN;
-    lb.lbHatch = (INT)CreateBitmap(8, 8, 1, 1, pattern);
-    infoPtr->hbrThumb = CreateBrushIndirect(&lb);
-    DeleteObject((HGDIOBJ)lb.lbHatch);
-
-    TRACKBAR_InitColors(infoPtr,FALSE);
-
-    infoPtr->hwndBuddyLA = 0;
-    infoPtr->hwndBuddyRB = 0;
-    infoPtr->flags       = 0;
-    infoPtr->bFocus      = FALSE;
-
-    if (infoPtr->dwStyle & TBS_VERT)
-    {
-      infoPtr->fLocation = (infoPtr->dwStyle & TBS_LEFT) ? TBTS_RIGHT : TBTS_LEFT;
-    } else
-    {
-      infoPtr->fLocation = (infoPtr->dwStyle & TBS_TOP) ? TBTS_BOTTOM : TBTS_TOP;
-    }
-
-    TRACKBAR_InitializeThumb(infoPtr);
-
-    /* Create tooltip control */
-    if (infoPtr->dwStyle & TBS_TOOLTIPS)
-    {
-      UINT uFlags = TTF_TRACK | TTF_ABSOLUTE;
-
-      if (infoPtr->dwStyle & TBS_VERT)
-        if (infoPtr->fLocation == TBTS_RIGHT)
-          uFlags |= TTF_ALIGNRIGHT | TTF_VCENTER;
-        else
-          uFlags |= TTF_ALIGNLEFT | TTF_VCENTER;
-      else
-        if (infoPtr->fLocation == TBTS_TOP)
-          uFlags |= TTF_ALIGNTOP | TTF_HCENTER;
-        else
-          uFlags |= TTF_ALIGNBOTTOM | TTF_HCENTER;
-
-      infoPtr->hwndToolTip = createToolTip(hwnd,uFlags,TRUE);
-    }
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_Destroy(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    if (infoPtr->hbrThumb)
-      DeleteObject((HGDIOBJ)infoPtr->hbrThumb);
-
-    /* delete tooltip control */
-    destroyToolTip(infoPtr->hwndToolTip);
-
-    COMCTL32_Free(infoPtr->tics);
-    doneControl(infoPtr->hwnd);
-
-    return 0;
-}
-
-static VOID TRACKBAR_CalcToolTipPos(TRACKBAR_INFO *infoPtr,POINT *pt)
-{
-  if (infoPtr->dwStyle & TBS_VERT)
-  {
-    if (infoPtr->fLocation == TBTS_RIGHT)
-    {
-      pt->x = infoPtr->rcFullThumb.right+TOOLTIP_SPACE;
-      pt->y = infoPtr->rcFullThumb.top+(infoPtr->rcFullThumb.bottom-infoPtr->rcFullThumb.top)/2;
-    } else
-    {
-      pt->x = infoPtr->rcFullThumb.left-TOOLTIP_SPACE;
-      pt->y = infoPtr->rcFullThumb.top+(infoPtr->rcFullThumb.bottom-infoPtr->rcFullThumb.top)/2;
-    }
-
-  } else
-  {
-    if (infoPtr->fLocation == TBTS_TOP)
-    {
-      pt->x = infoPtr->rcFullThumb.left+(infoPtr->rcFullThumb.right-infoPtr->rcFullThumb.left)/2;
-      pt->y = infoPtr->rcFullThumb.top-TOOLTIP_SPACE;
-    } else
-    {
-      pt->x = infoPtr->rcFullThumb.left+(infoPtr->rcFullThumb.right-infoPtr->rcFullThumb.left)/2;
-      pt->y = infoPtr->rcFullThumb.bottom+TOOLTIP_SPACE;
-    }
-  }
-  ClientToScreen(infoPtr->hwnd,pt);
-}
-
-static LRESULT
-TRACKBAR_LButtonDown(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    int clickPlace,prevPos,vertical;
-    DOUBLE clickPos;
-    RECT thumb,fullThumb;
-    POINT clickPoint;
-
-    SetFocus(infoPtr->hwnd);
-
-    vertical = infoPtr->dwStyle & TBS_VERT;
-    clickPoint.x = (INT)LOWORD(lParam);
-    clickPoint.y = (INT)HIWORD(lParam);
-
-
-    if (vertical) clickPlace = clickPoint.y;
-    else clickPlace = clickPoint.x;
-
-    //Button down on thumb?
-    thumb = infoPtr->rcThumb;
-    fullThumb = infoPtr->rcFullThumb;
-    if ((vertical &&
-         (clickPoint.y >= thumb.top) &&
-         (clickPoint.y <= thumb.bottom) &&
-         (((infoPtr->dwStyle & TBS_BOTH) &&
-           (clickPoint.x >= thumb.left) &&
-           (clickPoint.x <= thumb.right)
-          ) ||
-          ((infoPtr->dwStyle & TBS_LEFT) &&
-           (clickPoint.x <= thumb.right) &&
-           ((clickPoint.x >= thumb.left) ||
-            ((clickPoint.x >= fullThumb.left) &&
-             ((thumb.left-clickPoint.x <= clickPoint.y-thumb.top) &&
-              (thumb.left-clickPoint.x <= thumb.bottom-clickPoint.y)
-             )
-            )
-           )
-          ) ||
-          (!(infoPtr->dwStyle & (TBS_BOTH | TBS_LEFT)) &&
-           (clickPoint.x >= thumb.left) &&
-           ((clickPoint.x <= thumb.right) ||
-            ((clickPoint.x <= fullThumb.right) &&
-             ((clickPoint.x-thumb.right <= clickPoint.y-thumb.top) &&
-              (clickPoint.x-thumb.right <= thumb.bottom-clickPoint.y)
-             )
-            )
-           )
-         ))
-        ) ||
-        (!vertical &&
-         (clickPoint.x >= thumb.left) &&
-         (clickPoint.x <= thumb.right) &&
-         (((infoPtr->dwStyle & TBS_BOTH) &&
-           (clickPoint.y >= thumb.top) &&
-           (clickPoint.y <= thumb.bottom)
-          ) ||
-          ((infoPtr->dwStyle & TBS_TOP) &&
-           (clickPoint.y <= thumb.bottom) &&
-           ((clickPoint.y >= thumb.top) ||
-            ((clickPoint.y >= fullThumb.top) &&
-             ((thumb.top-clickPoint.y <= clickPoint.x-thumb.left) &&
-              (thumb.top-clickPoint.y <= thumb.right-clickPoint.x)
-             )
-            )
-           )
-          ) ||
-          (!(infoPtr->dwStyle & (TBS_BOTH | TBS_TOP)) &&
-           (clickPoint.y >= thumb.top) &&
-           ((clickPoint.y <= thumb.bottom) ||
-            ((clickPoint.y <= fullThumb.bottom) &&
-             ((clickPoint.y-thumb.bottom <= clickPoint.x-thumb.left) &&
-              (clickPoint.y-thumb.bottom <= thumb.right-clickPoint.x)
-             )
-            )
-           )
-         ))
-       ))
-       {
-         infoPtr->flags |= TB_DRAG_MODE;
-         if (infoPtr->dwStyle & TBS_TOOLTIPS)
-         {  /* enable tooltip */
-           TTTOOLINFOA ti;
-           POINT pt;
-           char buf[80];
-
-           ti.cbSize   = sizeof(TTTOOLINFOA);
-           ti.uId      = 0;
-           ti.hwnd     = (UINT)infoPtr->hwnd;
-           ti.hinst    = 0;
-           sprintf (buf,"%ld",infoPtr->nPos);
-           ti.lpszText = (LPSTR)buf;
-
-           infoPtr->flags |= TB_SHOW_TOOLTIP;
-           SetCapture(infoPtr->hwnd);
-
-           SendMessageA(infoPtr->hwndToolTip,TTM_UPDATETIPTEXTA,0,(LPARAM)&ti);
-           TRACKBAR_CalcToolTipPos(infoPtr,&pt);
-           SendMessageA(infoPtr->hwndToolTip,TTM_TRACKPOSITION,0,(LPARAM)MAKELPARAM(pt.x,pt.y));
-
-           SendMessageA(infoPtr->hwndToolTip,TTM_TRACKACTIVATE,(WPARAM)TRUE,(LPARAM)&ti);
-         }
-
-         SetCapture(infoPtr->hwnd);
-         TRACKBAR_UpdateThumbPosition(infoPtr,infoPtr->nPos,TRUE); //change arrow color
-         return 0;
-       }
-    else if ((vertical &&
-              (clickPoint.y >= thumb.top) &&
-              (clickPoint.y <= thumb.bottom))   ||
-             (!vertical &&
-              (clickPoint.x >= thumb.left) &&
-              (clickPoint.x <= thumb.right)))
-            {
-              //ScrollMode
-              infoPtr->flags |= TB_SCROLL_MODE;
-              SetCapture(infoPtr->hwnd);
-              SetTimer(infoPtr->hwnd,SCROLL_TIMER_ID,SCROLL_TIME,NULL);
-
-              return 0;
-            }
-
-    clickPos = TRACKBAR_ConvertPlaceToPosition(infoPtr,clickPlace,vertical);
-    prevPos = infoPtr->nPos;
-
-    if (clickPos > prevPos)
-    {  /* similar to VK_NEXT */
-      infoPtr->nPos += infoPtr->nPageSize;
-      if (infoPtr->nPos > infoPtr->nRangeMax) infoPtr->nPos = infoPtr->nRangeMax;
-      if (prevPos != infoPtr->nPos) TRACKBAR_SendNotify(infoPtr,TB_PAGEUP);
-    } else
-    {  /* similar to VK_PRIOR */
-      infoPtr->nPos -= infoPtr->nPageSize;
-      if (infoPtr->nPos < infoPtr->nRangeMin) infoPtr->nPos = infoPtr->nRangeMin;
-      if (prevPos != infoPtr->nPos) TRACKBAR_SendNotify(infoPtr,TB_PAGEDOWN);
-    }
-
-    if (prevPos != infoPtr->nPos)
-    {
-      infoPtr->flags |= TB_THUMBPOSCHANGED;
-      TRACKBAR_UpdateThumbPosition(infoPtr,prevPos,TRUE);
-    }
-
-    //ScrollMode
-    infoPtr->flags |= TB_SCROLL_MODE;
-    SetCapture(infoPtr->hwnd);
-    SetTimer(infoPtr->hwnd,SCROLL_TIMER_ID,SCROLL_TIME,NULL);
-
-    return 0;
-}
-
-
-static LRESULT
-TRACKBAR_LButtonUp(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    if (infoPtr->flags & TB_DRAG_MODE)
-    {
-      TRACKBAR_SendNotify(infoPtr,TB_ENDTRACK);
-
-      infoPtr->flags &= ~TB_DRAG_MODE;
-
-      if (GetCapture() == infoPtr->hwnd)
-      {
-        sendNotify(infoPtr->hwnd,NM_RELEASEDCAPTURE);
-
-        ReleaseCapture();
-      }
-
-      TRACKBAR_UpdateThumbPosition(infoPtr,infoPtr->nPos,TRUE); //change arrow color
-    }
-
-    if (infoPtr->flags & TB_SCROLL_MODE)
-    {
-      infoPtr->flags &= ~TB_SCROLL_MODE;
-
-      if (GetCapture() == infoPtr->hwnd)
-      {
-        sendNotify(infoPtr->hwnd,NM_RELEASEDCAPTURE);
-
-        ReleaseCapture();
-      }
-
-      KillTimer(infoPtr->hwnd,SCROLL_TIMER_ID);
-    }
-
-    if (infoPtr->dwStyle & TBS_TOOLTIPS)
-    { /* disable tooltip */
-      TTTOOLINFOA ti;
-
-      ti.cbSize   = sizeof(TTTOOLINFOA);
-      ti.uId      = 0;
-      ti.hwnd     = (UINT)infoPtr->hwnd;
-
-      infoPtr->flags &= ~TB_SHOW_TOOLTIP;
-      SendMessageA(infoPtr->hwndToolTip,TTM_TRACKACTIVATE,(WPARAM)FALSE,(LPARAM)&ti);
-    }
-
-    return 0;
-}
-
-static LRESULT TRACKBAR_Timer(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  POINT mousePoint;
-  INT mousePlace,prevPos,newPos,vertical;
-  DOUBLE mousePos;
-
-  GetCursorPos(&mousePoint);
-  ScreenToClient(infoPtr->hwnd,&mousePoint);
-
-  vertical = infoPtr->dwStyle & TBS_VERT;
-  if (vertical) mousePlace = mousePoint.y;
-  else mousePlace = mousePoint.x;
-
-  mousePos = TRACKBAR_ConvertPlaceToPosition(infoPtr,mousePlace,vertical);
-  prevPos = infoPtr->nPos;
-
-  if (mousePos > (INT)mousePos+0.5) newPos = mousePos+1;
-  else newPos = mousePos;
-  if (newPos == prevPos) return 0;
-
-  if (newPos > prevPos)
-  {  /* similar to VK_NEXT */
-      infoPtr->nPos += infoPtr->nPageSize;
-      if (infoPtr->nPos > infoPtr->nRangeMax) infoPtr->nPos = infoPtr->nRangeMax;
-      if (prevPos != infoPtr->nPos) TRACKBAR_SendNotify(infoPtr,TB_PAGEUP);
-    } else
-    {  /* similar to VK_PRIOR */
-      infoPtr->nPos -= infoPtr->nPageSize;
-      if (infoPtr->nPos < infoPtr->nRangeMin) infoPtr->nPos = infoPtr->nRangeMin;
-      if (prevPos != infoPtr->nPos) TRACKBAR_SendNotify(infoPtr,TB_PAGEDOWN);
-    }
-
-    if (prevPos != infoPtr->nPos)
-    {
-      infoPtr->flags |= TB_THUMBPOSCHANGED;
-      TRACKBAR_UpdateThumbPosition(infoPtr,prevPos,FALSE);
-    }
-
-  return 0;
-}
-
-static LRESULT
-TRACKBAR_CaptureChanged(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    sendNotify(infoPtr->hwnd,NM_RELEASEDCAPTURE);
-
-    if (infoPtr->flags & TB_DRAGPOSVALID)
-    {
-      int lastPos = infoPtr->nPos;
-      infoPtr->nPos = infoPtr->dragPos;
-      if (lastPos != infoPtr->nPos) TRACKBAR_UpdateThumbPosition(infoPtr,lastPos,TRUE);
-    }
-
-    infoPtr->flags &= ~TB_DRAGPOSVALID;
-
-    if (infoPtr->flags & TB_SCROLL_MODE)
-    {
-      infoPtr->flags &= ~TB_SCROLL_MODE;
-      KillTimer(infoPtr->hwnd,SCROLL_TIMER_ID);
-    }
-
-    if (infoPtr->flags & TB_DRAG_MODE)
-    {
-      TRACKBAR_SendNotify(infoPtr,TB_ENDTRACK);
-
-      infoPtr->flags &= ~TB_DRAG_MODE;
-    }
-
-    return 0;
-}
-
-
-static LRESULT
-TRACKBAR_Paint(TRACKBAR_INFO *infoPtr,WPARAM wParam)
-{
-    HDC hdc;
-    PAINTSTRUCT ps;
-
-    hdc = wParam == 0 ? BeginPaint(infoPtr->hwnd,&ps):(HDC)wParam;
-    TRACKBAR_Draw(infoPtr,hdc);
-    if (!wParam) EndPaint(infoPtr->hwnd,&ps);
-    return 0;
-}
-
-
-static LRESULT
-TRACKBAR_SetFocus(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    HDC hdc;
-    RECT rcClient;
-
-    if (!infoPtr->bFocus && IsWindowEnabled(infoPtr->hwnd))
-    {
-      infoPtr->bFocus = TRUE;
-
-      GetClientRect(infoPtr->hwnd,&rcClient);
-      hdc = GetDC (infoPtr->hwnd);
-      DrawFocusRect(hdc,&rcClient);
-      ReleaseDC(infoPtr->hwnd,hdc);
-    }
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_KillFocus(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    HDC hdc;
-    RECT rcClient;
-
-
-    infoPtr->flags &= ~TB_DRAG_MODE;
-    if (infoPtr->bFocus && IsWindowEnabled(infoPtr->hwnd))
-    {
-      infoPtr->bFocus = FALSE;
-
-      GetClientRect(infoPtr->hwnd,&rcClient);
-      hdc = GetDC(infoPtr->hwnd);
-      DrawFocusRect(hdc,&rcClient); //XOR removes
-      ReleaseDC(infoPtr->hwnd,hdc);
-    }
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_Size(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  if (!(infoPtr->dwStyle & TBS_FIXEDLENGTH))
-  {
-    /* If trackbar doesn't have TBS_FIXEDLENGTH style
-     * it sets thumb length according to new width / height.
-     */
-    LONG h;
-    LONG hmin = (infoPtr->dwStyle & TBS_ENABLESELRANGE) ? THUMB_LEN_SEL:THUMB_LEN;
-
-    if (infoPtr->dwStyle & TBS_VERT)
-      h = (LONG)(INT16)LOWORD(lParam);  /* width */
-    else
-      h = (LONG)(INT16)HIWORD(lParam);  /* height */
-
-    if (h < hmin)
-    {
-      /* focus rect + tic size + thumb offset */
-
-       h -= (BORDER_SIZE+SCALE_SPACE)*2;
-    }
-
-    h = MAX(h,THUMB_MINLEN);
-    h = MIN(h,hmin);
-
-    infoPtr->uThumbLen = h;
-  }
-
-  TRACKBAR_CalcChannel(infoPtr);
-  TRACKBAR_AlignBuddies(infoPtr);
-
-  return 0;
-}
-
-static BOOL TRACKBAR_SendNotify(TRACKBAR_INFO *infoPtr,UINT code)
-{
-  if (infoPtr->dwStyle & TBS_VERT)
-    return sendVScroll(infoPtr->hwnd,code);
-  else
-    return sendHScroll(infoPtr->hwnd,code);
-}
-
-static LRESULT
-TRACKBAR_MouseMove(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    SHORT clickPlace;
-    DOUBLE dragPos;
-
-    if (!(infoPtr->flags & TB_DRAG_MODE)) return TRUE;
-
-    if (infoPtr->dwStyle & TBS_VERT) clickPlace = (SHORT)HIWORD(lParam);
-    else clickPlace = (SHORT)LOWORD(lParam);
-
-    dragPos = TRACKBAR_ConvertPlaceToPosition(infoPtr,clickPlace,infoPtr->dwStyle & TBS_VERT);
-    if (dragPos > ((INT)dragPos)+0.5) infoPtr->dragPos = dragPos + 1;
-    else infoPtr->dragPos = dragPos;
-
-    if (infoPtr->nPos == infoPtr->dragPos) return TRUE; //nothing changed
-
-    infoPtr->flags |= TB_DRAGPOSVALID;
-
-    TRACKBAR_UpdateThumbPosition(infoPtr,infoPtr->nPos,FALSE); //infoPtr->nPos now set
-
-    TRACKBAR_SendNotify(infoPtr,TB_THUMBTRACK | (infoPtr->nPos << 16));
-
-    if (infoPtr->flags & TB_SHOW_TOOLTIP)
-    {
-      POINT pt;
-      TTTOOLINFOA ti;
-      char buf[80];
-
-      ti.cbSize = sizeof(TTTOOLINFOA);
-      ti.hwnd = infoPtr->hwnd;
-      ti.uId = 0;
-      ti.hinst = 0;
-      sprintf(buf,"%d",infoPtr->nPos);
-      ti.lpszText = (LPSTR)buf;
-
-      SendMessageA(infoPtr->hwndToolTip,TTM_UPDATETIPTEXTA,0,(LPARAM)&ti);
-      TRACKBAR_CalcToolTipPos(infoPtr,&pt);
-      SendMessageA(infoPtr->hwndToolTip,TTM_TRACKPOSITION,0,(LPARAM)MAKELPARAM(pt.x,pt.y));
-    }
-
-    return 0;
-}
-
-static LRESULT
-TRACKBAR_Enable(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  BOOL oldFocus = infoPtr->bFocus;
-
-  if (wParam) infoPtr->bFocus = (GetFocus() == infoPtr->hwnd);
-  else infoPtr->bFocus = FALSE;
-
-  if (oldFocus != infoPtr->bFocus) TRACKBAR_Refresh(infoPtr);
-  else TRACKBAR_UpdateThumbPosition(infoPtr,infoPtr->nPos,TRUE);
-
-  return 0;
-}
-
-static LRESULT
-TRACKBAR_KeyDown(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-    INT pos;
-
-    if (infoPtr->flags & TB_DRAG_MODE) return TRUE;
-
-    pos = infoPtr->nPos;
-    switch (wParam) {
-    case VK_LEFT:
-    case VK_UP:
-        if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
-        infoPtr->nPos -= infoPtr->nLineSize;
-        if (infoPtr->nPos < infoPtr->nRangeMin)
-            infoPtr->nPos = infoPtr->nRangeMin;
-        TRACKBAR_SendNotify(infoPtr,TB_LINEUP);
-        break;
-    case VK_RIGHT:
-    case VK_DOWN:
-        if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
-        infoPtr->nPos += infoPtr->nLineSize;
-        if (infoPtr->nPos > infoPtr->nRangeMax)
-            infoPtr->nPos = infoPtr->nRangeMax;
-        TRACKBAR_SendNotify(infoPtr,TB_LINEDOWN);
-        break;
-    case VK_NEXT:
-        if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
-        infoPtr->nPos += infoPtr->nPageSize;
-        if (infoPtr->nPos > infoPtr->nRangeMax)
-            infoPtr->nPos = infoPtr->nRangeMax;
-        TRACKBAR_SendNotify(infoPtr,TB_PAGEUP);
-        break;
-    case VK_PRIOR:
-        if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
-        infoPtr->nPos -= infoPtr->nPageSize;
-        if (infoPtr->nPos < infoPtr->nRangeMin)
-            infoPtr->nPos = infoPtr->nRangeMin;
-        TRACKBAR_SendNotify(infoPtr,TB_PAGEDOWN);
-        break;
-    case VK_HOME:
-        if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
-        infoPtr->nPos = infoPtr->nRangeMin;
-        TRACKBAR_SendNotify(infoPtr,TB_TOP);
-        break;
-    case VK_END:
-        if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
-        infoPtr->nPos = infoPtr->nRangeMax;
-        TRACKBAR_SendNotify(infoPtr,TB_BOTTOM);
-        break;
-
-      default:
-        return FALSE;
-    }
-
-    if (pos != infoPtr->nPos)
-    {
-      infoPtr->flags |= TB_THUMBPOSCHANGED;
-      TRACKBAR_UpdateThumbPosition(infoPtr,pos,FALSE);
-    }
-
-    return TRUE;
-}
-
-
-static LRESULT
-TRACKBAR_KeyUp(TRACKBAR_INFO *infoPtr,WPARAM wParam)
-{
-    if (infoPtr->flags & TB_DRAG_MODE) return TRUE;
-
-    switch (wParam) {
-    case VK_LEFT:
-    case VK_UP:
-    case VK_RIGHT:
-    case VK_DOWN:
-    case VK_NEXT:
-    case VK_PRIOR:
-    case VK_HOME:
-    case VK_END:
-        TRACKBAR_SendNotify(infoPtr,TB_ENDTRACK);
-    }
-    return TRUE;
-}
-
-static LRESULT
-TRACKBAR_StyleChanged(TRACKBAR_INFO *infoPtr,WPARAM wParam,LPSTYLESTRUCT lParam)
-{
-  TRACKBAR_CalcChannel(infoPtr);
-
-  return 0;
-}
-
-static LRESULT WINAPI
-TRACKBAR_WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
-{
-  TRACKBAR_INFO *infoPtr;
-
-  if (uMsg == WM_CREATE)
-    return TRACKBAR_Create(hwnd,wParam,lParam);
-
-  infoPtr = TRACKBAR_GetInfoPtr(hwnd);
-
-  if (!infoPtr)
-    goto defproc;
-
-  switch (uMsg)
-  {
-    case TBM_CLEARSEL:
-        return TRACKBAR_ClearSel(infoPtr,wParam,lParam);
-
-    case TBM_CLEARTICS:
-        return TRACKBAR_ClearTics(infoPtr,wParam,lParam);
-
-    case TBM_GETBUDDY:
-        return TRACKBAR_GetBuddy(infoPtr,wParam,lParam);
-
-    case TBM_GETCHANNELRECT:
-        return TRACKBAR_GetChannelRect(infoPtr,wParam,lParam);
-
-    case TBM_GETLINESIZE:
-        return TRACKBAR_GetLineSize(infoPtr,wParam,lParam);
-
-    case TBM_GETNUMTICS:
-        return TRACKBAR_GetNumTics(infoPtr,wParam,lParam);
-
-    case TBM_GETPAGESIZE:
-        return TRACKBAR_GetPageSize(infoPtr,wParam,lParam);
-
-    case TBM_GETPOS:
-        return TRACKBAR_GetPos(infoPtr,wParam,lParam);
-
-    case TBM_GETPTICS:
-        return TRACKBAR_GetPTics(infoPtr);
-
-    case TBM_GETRANGEMAX:
-        return TRACKBAR_GetRangeMax(infoPtr,wParam,lParam);
-
-    case TBM_GETRANGEMIN:
-        return TRACKBAR_GetRangeMin(infoPtr,wParam,lParam);
-
-    case TBM_GETSELEND:
-        return TRACKBAR_GetSelEnd(infoPtr,wParam,lParam);
-
-    case TBM_GETSELSTART:
-        return TRACKBAR_GetSelStart(infoPtr,wParam,lParam);
-
-    case TBM_GETTHUMBLENGTH:
-        return TRACKBAR_GetThumbLength(infoPtr,wParam,lParam);
-
-    case TBM_GETTHUMBRECT:
-        return TRACKBAR_GetThumbRect(infoPtr,wParam,lParam);
-
-    case TBM_GETTIC:
-        return TRACKBAR_GetTic(infoPtr,wParam,lParam);
-
-    case TBM_GETTICPOS:
-        return TRACKBAR_GetTicPos(infoPtr,wParam,lParam);
-
-    case TBM_GETTOOLTIPS:
-        return TRACKBAR_GetToolTips(infoPtr,wParam,lParam);
-
-    case TBM_SETBUDDY:
-        return TRACKBAR_SetBuddy(infoPtr,wParam,lParam);
-
-    case TBM_SETLINESIZE:
-        return TRACKBAR_SetLineSize(infoPtr,wParam,lParam);
-
-    case TBM_SETPAGESIZE:
-        return TRACKBAR_SetPageSize(infoPtr,wParam,lParam);
-
-    case TBM_SETPOS:
-        return TRACKBAR_SetPos(infoPtr,wParam,lParam);
-
-    case TBM_SETRANGE:
-        return TRACKBAR_SetRange(infoPtr,wParam,lParam);
-
-    case TBM_SETRANGEMAX:
-        return TRACKBAR_SetRangeMax(infoPtr,wParam,lParam);
-
-    case TBM_SETRANGEMIN:
-        return TRACKBAR_SetRangeMin(infoPtr,wParam,lParam);
-
-    case TBM_SETSEL:
-        return TRACKBAR_SetSel(infoPtr,wParam,lParam);
-
-    case TBM_SETSELEND:
-        return TRACKBAR_SetSelEnd(infoPtr,wParam,lParam);
-
-    case TBM_SETSELSTART:
-        return TRACKBAR_SetSelStart(infoPtr,wParam,lParam);
-
-    case TBM_SETTHUMBLENGTH:
-        return TRACKBAR_SetThumbLength(infoPtr,wParam,lParam);
-
-    case TBM_SETTIC:
-        return TRACKBAR_SetTic(infoPtr,wParam,lParam);
-
-    case TBM_SETTICFREQ:
-        return TRACKBAR_SetTicFreq(infoPtr,wParam);
-
-    case TBM_SETTIPSIDE:
-        return TRACKBAR_SetTipSide(infoPtr,wParam,lParam);
-
-    case TBM_SETTOOLTIPS:
-        return TRACKBAR_SetToolTips(infoPtr,wParam,lParam);
-
-    case WM_CAPTURECHANGED:
-        return TRACKBAR_CaptureChanged(infoPtr,wParam,lParam);
-
-    case WM_DESTROY:
-        return TRACKBAR_Destroy(infoPtr,wParam,lParam);
-
-    case WM_ENABLE:
-        return TRACKBAR_Enable(infoPtr,wParam,lParam);
-
-    case WM_ERASEBKGND:
-        return 1;
-
-    case WM_GETDLGCODE:
-        return DLGC_WANTARROWS;
-
-    case WM_KEYDOWN:
-        return TRACKBAR_KeyDown(infoPtr,wParam,lParam);
-
-    case WM_KEYUP:
-        return TRACKBAR_KeyUp(infoPtr,wParam);
-
-    case WM_LBUTTONDOWN:
-        return TRACKBAR_LButtonDown(infoPtr,wParam,lParam);
-
-    case WM_LBUTTONUP:
-        return TRACKBAR_LButtonUp(infoPtr,wParam,lParam);
-
-    case WM_TIMER:
-        return TRACKBAR_Timer(infoPtr,wParam,lParam);
-
-    case WM_MOUSEMOVE:
-        return TRACKBAR_MouseMove(infoPtr,wParam,lParam);
-
-    case WM_PAINT:
-        return TRACKBAR_Paint(infoPtr,wParam);
-
-    case WM_SETFOCUS:
-        return TRACKBAR_SetFocus(infoPtr,wParam,lParam);
-
-    case WM_KILLFOCUS:
-        return TRACKBAR_KillFocus(infoPtr,wParam,lParam);
-
-    case WM_STYLECHANGED:
-        return TRACKBAR_StyleChanged(infoPtr,wParam,(LPSTYLESTRUCT)lParam);
-
-    case WM_SIZE:
-        return TRACKBAR_Size(infoPtr,wParam,lParam);
-
-    case WM_WININICHANGE:
-        return TRACKBAR_InitializeThumb(infoPtr);
-
-    case WM_SYSCOLORCHANGE:
-        return TRACKBAR_InitColors(infoPtr,TRUE);
-
-    default:
-        //if (uMsg >= WM_USER)
-        //    ERR (trackbar, "unknown msg %04x wp=%08x lp=%08lx\n",
-        //         uMsg, wParam, lParam);
- defproc:
-        return defComCtl32ProcA(hwnd,uMsg,wParam,lParam);
-    }
-    return 0;
-}
-
-
-VOID
-TRACKBAR_Register (VOID)
-{
-  WNDCLASSA wndClass;
-
-  ZeroMemory (&wndClass, sizeof(WNDCLASSA));
-  wndClass.style         = CS_GLOBALCLASS;
-  wndClass.lpfnWndProc   = (WNDPROC)TRACKBAR_WindowProc;
-  wndClass.cbClsExtra    = 0;
-  wndClass.cbWndExtra    = sizeof(TRACKBAR_INFO *);
-  wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
-  wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
-  wndClass.lpszClassName = TRACKBAR_CLASSA;
-
-  RegisterClassA(&wndClass);
-}
-
-
-VOID
-TRACKBAR_Unregister (VOID)
-{
-  UnregisterClassA (TRACKBAR_CLASSA, (HINSTANCE)NULL);
-}
-
Index: trunk/src/comctl32/trackbar.h
===================================================================
--- trunk/src/comctl32/trackbar.h	(revision 10097)
+++ 	(revision )
@@ -1,53 +1,0 @@
-/* $Id: trackbar.h,v 1.1 2002-10-29 13:47:32 sandervl Exp $ */
-
-/*
- * Trackbar class extra info
- *
- * Copyright 1998 Eric Kohl
- * Copyright 1999 Christoph Bratschi
- */
-
-#ifndef __WINE_TRACKBAR_H
-#define __WINE_TRACKBAR_H
-
-typedef struct tagTRACKBAR_INFO
-{
-    COMCTL32_HEADER header;
-
-    HWND  hwnd;
-    DWORD dwStyle;
-
-    INT  nRangeMin;
-    INT  nRangeMax;
-    INT  nLineSize;
-    INT  nPageSize;
-    INT  nSelMin;
-    INT  nSelMax;
-    INT  nPos;
-    UINT uThumbLen;
-    UINT uNumTics;
-    UINT  uTicFreq;
-    HWND hwndToolTip;
-    HWND hwndBuddyLA;
-    HWND hwndBuddyRB;
-    INT  fLocation;
-    COLORREF clrBk;
-    COLORREF clrHighlightedThumb;
-    HBRUSH   hbrThumb;
-
-
-    INT  flags;
-    BOOL bFocus;
-    RECT rcChannel;
-    RECT rcSelection;
-    RECT rcFullThumb;
-    RECT rcThumb;
-    INT  dragPos;
-    LPLONG tics;
-} TRACKBAR_INFO;
-
-#define TB_REFRESH_TIMER       1
-#define TB_REFRESH_DELAY       1
-
-
-#endif  /* __WINE_TRACKBAR_H */
Index: trunk/src/comctl32/treeview.c
===================================================================
--- trunk/src/comctl32/treeview.c	(revision 10098)
+++ trunk/src/comctl32/treeview.c	(revision 10098)
@@ -0,0 +1,5544 @@
+/* Treeview control
+ *
+ * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
+ * Copyright 1998,1999 Alex Priem <alexp@sci.kun.nl>
+ * Copyright 1999 Sylvain St-Germain
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * 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
+ *      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,
+ *      TVN_SETDISPINFO, TVN_SINGLEEXPAND
+ *
+ *   missing styles: TVS_FULLROWSELECT, TVS_INFOTIP, TVS_NOSCROLL,
+ *      TVS_RTLREADING, TVS_TRACKSELECT
+ *
+ *   missing item styles: TVIS_CUT, TVIS_EXPANDPARTIAL
+ *
+ *   Make the insertion mark look right.
+ *   Scroll (instead of repaint) as much as possible.
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "winbase.h"
+#include "wingdi.h"
+#include "commctrl.h"
+#include "comctl32.h"
+#include "wine/debug.h"
+
+/* internal structures */
+
+typedef struct _TREEITEM    /* HTREEITEM is a _TREEINFO *. */
+{
+  UINT      callbackMask;
+  UINT      state;
+  UINT      stateMask;
+  LPSTR     pszText;
+  int       cchTextMax;
+  int       iImage;
+  int       iSelectedImage;
+  int       cChildren;
+  LPARAM    lParam;
+  int       iIntegral;      /* item height multiplier (1 is normal) */
+  int       iLevel;         /* indentation level:0=root level */
+  HTREEITEM parent;         /* handle to parent or 0 if at root */
+  HTREEITEM firstChild;     /* handle to first child or 0 if no child */
+  HTREEITEM lastChild;
+  HTREEITEM prevSibling;    /* handle to prev item in list, 0 if first */
+  HTREEITEM nextSibling;    /* handle to next item in list, 0 if last */
+  RECT      rect;
+  LONG      linesOffset;
+  LONG      stateOffset;
+  LONG      imageOffset;
+  LONG      textOffset;
+  LONG      textWidth;      /* horizontal text extent for pszText */
+  LONG      visibleOrder;   /* visible ordering, 0 is first visible item */
+} TREEVIEW_ITEM;
+
+
+typedef struct tagTREEVIEW_INFO
+{
+  HWND          hwnd;
+  HWND          hwndNotify;     /* Owner window to send notifications to */
+  DWORD         dwStyle;
+  HTREEITEM     root;
+  UINT          uInternalStatus;
+  INT           Timer;
+  UINT          uNumItems;      /* number of valid TREEVIEW_ITEMs */
+  INT           cdmode;         /* last custom draw setting */
+  UINT          uScrollTime;	/* max. time for scrolling in milliseconds */
+  BOOL		bRedraw;	/* if FALSE we validate but don't redraw in TREEVIEW_Paint() */
+
+  UINT          uItemHeight;    /* item height */
+  BOOL          bHeightSet;
+
+  LONG          clientWidth;    /* width of control window */
+  LONG          clientHeight;   /* height of control window */
+
+  LONG          treeWidth;      /* width of visible tree items */
+  LONG          treeHeight;     /* height of visible tree items */
+
+  UINT          uIndent;        /* indentation in pixels */
+  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     firstVisible;   /* handle to first visible item */
+  LONG          maxVisibleOrder;
+  HTREEITEM     dropItem;       /* handle to item selected by drag cursor */
+  HTREEITEM     insertMarkItem; /* item after which insertion mark is placed */
+  BOOL          insertBeforeorAfter; /* flag used by TVM_SETINSERTMARK */
+  HIMAGELIST    dragList;       /* Bitmap of dragged item */
+  LONG          scrollX;
+  COLORREF      clrBk;
+  COLORREF      clrText;
+  COLORREF      clrLine;
+  COLORREF      clrInsertMark;
+  HFONT         hFont;
+  HFONT         hBoldFont;
+  HWND          hwndToolTip;
+
+  HWND          hwndEdit;
+  WNDPROC       wpEditOrig;     /* orig window proc for subclassing edit */
+  BOOL          bIgnoreEditKillFocus;
+  BOOL          bLabelChanged;
+
+  BOOL          bNtfUnicode;    /* TRUE if should send NOTIFY with W */
+  BOOL          bUnicode;       /* set by CCM_SETUNICODEFORMAT       */
+  HIMAGELIST    himlNormal;
+  int           normalImageHeight;
+  int           normalImageWidth;
+  HIMAGELIST    himlState;
+  int           stateImageHeight;
+  int           stateImageWidth;
+  HDPA          items;
+
+  DWORD lastKeyPressTimestamp; /* Added */
+  WPARAM charCode; /* Added */
+  INT nSearchParamLength; /* Added */
+  CHAR szSearchParam[ MAX_PATH ]; /* Added */
+} TREEVIEW_INFO;
+
+
+/******** Defines that TREEVIEW_ProcessLetterKeys uses ****************/
+#define KEY_DELAY       450
+
+/* bitflags for infoPtr->uInternalStatus */
+
+#define TV_HSCROLL 	0x01    /* treeview too large to fit in window */
+#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_RDRAGGING	0x20
+
+/* bitflags for infoPtr->timer */
+
+#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
+
+#define MINIMUM_INDENT 19
+
+#define CALLBACK_MASK_ALL (TVIF_TEXT|TVIF_CHILDREN|TVIF_IMAGE|TVIF_SELECTEDIMAGE)
+
+#define STATEIMAGEINDEX(x) (((x) >> 12) & 0x0f)
+#define OVERLAYIMAGEINDEX(x) (((x) >> 8) & 0x0f)
+#define ISVISIBLE(x)         ((x)->visibleOrder >= 0)
+
+
+typedef VOID (*TREEVIEW_ItemEnumFunc)(TREEVIEW_INFO *, TREEVIEW_ITEM *,LPVOID);
+
+
+static VOID TREEVIEW_Invalidate(TREEVIEW_INFO *, TREEVIEW_ITEM *);
+
+static LRESULT TREEVIEW_DoSelectItem(TREEVIEW_INFO *, INT, HTREEITEM, INT);
+static VOID TREEVIEW_SetFirstVisible(TREEVIEW_INFO *, TREEVIEW_ITEM *, BOOL);
+static LRESULT TREEVIEW_EnsureVisible(TREEVIEW_INFO *, HTREEITEM, BOOL);
+static LRESULT TREEVIEW_RButtonUp(TREEVIEW_INFO *, LPPOINT);
+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 *****************************************************/
+
+#ifndef NDEBUG
+static inline void
+TREEVIEW_VerifyTree(TREEVIEW_INFO *infoPtr)
+{
+    (void)infoPtr;
+}
+#else
+/* The definition is at the end of the file. */
+static void TREEVIEW_VerifyTree(TREEVIEW_INFO *infoPtr);
+#endif
+
+/* Returns the treeview private data if hwnd is a treeview.
+ * Otherwise returns an undefined value. */
+static TREEVIEW_INFO *
+TREEVIEW_GetInfoPtr(HWND hwnd)
+{
+    return (TREEVIEW_INFO *)GetWindowLongA(hwnd, 0);
+}
+
+/* Don't call this. Nothing wants an item index. */
+static inline int
+TREEVIEW_GetItemIndex(TREEVIEW_INFO *infoPtr, HTREEITEM handle)
+{
+    assert(infoPtr != NULL);
+
+    return DPA_GetPtrIndex(infoPtr->items, handle);
+}
+
+/***************************************************************************
+ * This method checks that handle is an item for this tree.
+ */
+static BOOL
+TREEVIEW_ValidItem(TREEVIEW_INFO *infoPtr, HTREEITEM handle)
+{
+    if (TREEVIEW_GetItemIndex(infoPtr, handle) == -1)
+    {
+	TRACE("invalid item %p\n", handle);
+	return FALSE;
+    }
+    else
+	return TRUE;
+}
+
+static HFONT
+TREEVIEW_CreateBoldFont(HFONT hOrigFont)
+{
+    LOGFONTA font;
+
+    GetObjectA(hOrigFont, sizeof(font), &font);
+    font.lfWeight = FW_BOLD;
+    return CreateFontIndirectA(&font);
+}
+
+static inline HFONT
+TREEVIEW_FontForItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
+{
+    return (item->state & TVIS_BOLD) ? infoPtr->hBoldFont : infoPtr->hFont;
+}
+
+/* for trace/debugging purposes only */
+static const char *
+TREEVIEW_ItemName(TREEVIEW_ITEM *item)
+{
+    if (item == NULL) return "<null item>";
+    if (item->pszText == LPSTR_TEXTCALLBACKA) return "<callback>";
+    if (item->pszText == NULL) return "<null>";
+    return item->pszText;
+}
+
+/* An item is not a child of itself. */
+static BOOL
+TREEVIEW_IsChildOf(TREEVIEW_ITEM *parent, TREEVIEW_ITEM *child)
+{
+    do
+    {
+	child = child->parent;
+	if (child == parent) return TRUE;
+    } while (child != NULL);
+
+    return FALSE;
+}
+
+
+/* Tree Traversal *******************************************************/
+
+/***************************************************************************
+ * This method returns the last expanded sibling or child child item
+ * of a tree node
+ */
+static TREEVIEW_ITEM *
+TREEVIEW_GetLastListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem)
+{
+    if (!wineItem)
+       return NULL;
+
+    while (wineItem->lastChild)
+    {
+       if (wineItem->state & TVIS_EXPANDED)
+          wineItem = wineItem->lastChild;
+       else
+          break;
+    }
+
+    if (wineItem == infoPtr->root)
+        return NULL;
+
+    return wineItem;
+}
+
+/***************************************************************************
+ * This method returns the previous non-hidden item in the list not
+ * considering the tree hierarchy.
+ */
+static TREEVIEW_ITEM *
+TREEVIEW_GetPrevListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *tvItem)
+{
+    if (tvItem->prevSibling)
+    {
+	/* This item has a prevSibling, get the last item in the sibling's tree. */
+	TREEVIEW_ITEM *upItem = tvItem->prevSibling;
+
+	if ((upItem->state & TVIS_EXPANDED) && upItem->lastChild != NULL)
+	    return TREEVIEW_GetLastListItem(infoPtr, upItem->lastChild);
+	else
+	    return upItem;
+    }
+    else
+    {
+	/* this item does not have a prevSibling, get the parent */
+	return (tvItem->parent != infoPtr->root) ? tvItem->parent : NULL;
+    }
+}
+
+
+/***************************************************************************
+ * This method returns the next physical item in the treeview not
+ * considering the tree hierarchy.
+ */
+static TREEVIEW_ITEM *
+TREEVIEW_GetNextListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *tvItem)
+{
+    assert(tvItem != NULL);
+
+    /*
+     * If this item has children and is expanded, return the first child
+     */
+    if ((tvItem->state & TVIS_EXPANDED) && tvItem->firstChild != NULL)
+    {
+	return tvItem->firstChild;
+    }
+
+
+    /*
+     * try to get the sibling
+     */
+    if (tvItem->nextSibling)
+	return tvItem->nextSibling;
+
+    /*
+     * Otherwise, get the parent's sibling.
+     */
+    while (tvItem->parent)
+    {
+	tvItem = tvItem->parent;
+
+	if (tvItem->nextSibling)
+	    return tvItem->nextSibling;
+    }
+
+    return NULL;
+}
+
+/***************************************************************************
+ * This method returns the nth item starting at the given item.  It returns
+ * the last item (or first) we we run out of items.
+ *
+ * Will scroll backward if count is <0.
+ *             forward if count is >0.
+ */
+static TREEVIEW_ITEM *
+TREEVIEW_GetListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
+		     LONG count)
+{
+    TREEVIEW_ITEM *(*next_item)(TREEVIEW_INFO *, TREEVIEW_ITEM *);
+    TREEVIEW_ITEM *previousItem;
+
+    assert(wineItem != NULL);
+
+    if (count > 0)
+    {
+	next_item = TREEVIEW_GetNextListItem;
+    }
+    else if (count < 0)
+    {
+	count = -count;
+	next_item = TREEVIEW_GetPrevListItem;
+    }
+    else
+	return wineItem;
+
+    do
+    {
+	previousItem = wineItem;
+	wineItem = next_item(infoPtr, wineItem);
+
+    } while (--count && wineItem != NULL);
+
+
+    return wineItem ? wineItem : previousItem;
+}
+
+/* Notifications ************************************************************/
+
+static INT get_notifycode(TREEVIEW_INFO *infoPtr, INT code)
+{
+    if (!infoPtr->bNtfUnicode) {
+	switch (code) {
+	case TVN_SELCHANGINGW:	  return TVN_SELCHANGINGA;
+	case TVN_SELCHANGEDW:	  return TVN_SELCHANGEDA;
+	case TVN_GETDISPINFOW:	  return TVN_GETDISPINFOA;
+	case TVN_SETDISPINFOW:	  return TVN_SETDISPINFOA;
+	case TVN_ITEMEXPANDINGW:  return TVN_ITEMEXPANDINGA;
+	case TVN_ITEMEXPANDEDW:	  return TVN_ITEMEXPANDEDA;
+	case TVN_BEGINDRAGW:	  return TVN_BEGINDRAGA;
+	case TVN_BEGINRDRAGW:	  return TVN_BEGINRDRAGA;
+	case TVN_DELETEITEMW:	  return TVN_DELETEITEMA;
+	case TVN_BEGINLABELEDITW: return TVN_BEGINLABELEDITA;
+	case TVN_ENDLABELEDITW:	  return TVN_ENDLABELEDITA;
+	case TVN_GETINFOTIPW:	  return TVN_GETINFOTIPA;
+	}
+    }
+    return code;
+}
+
+static LRESULT
+TREEVIEW_SendRealNotify(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+{
+    TRACE("wParam=%d, lParam=%ld\n", wParam, lParam);
+    return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam);
+}
+
+static BOOL
+TREEVIEW_SendSimpleNotify(TREEVIEW_INFO *infoPtr, UINT code)
+{
+    NMHDR nmhdr;
+    HWND hwnd = infoPtr->hwnd;
+
+    TRACE("%d\n", code);
+    nmhdr.hwndFrom = hwnd;
+    nmhdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
+    nmhdr.code = get_notifycode(infoPtr, code);
+
+    return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
+				  (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
+}
+
+static VOID
+TREEVIEW_TVItemFromItem(TREEVIEW_INFO *infoPtr, UINT mask, TVITEMA *tvItem, TREEVIEW_ITEM *item)
+{
+    tvItem->mask = mask;
+    tvItem->hItem = item;
+    tvItem->state = item->state;
+    tvItem->stateMask = 0;
+    tvItem->iImage = item->iImage;
+    tvItem->cchTextMax = item->cchTextMax;
+    tvItem->iImage = item->iImage;
+    tvItem->iSelectedImage = item->iSelectedImage;
+    tvItem->cChildren = item->cChildren;
+    tvItem->lParam = item->lParam;
+
+    /* **** **** **** **** WARNING **** **** **** **** */
+    /* This control stores all the data in A format    */
+    /* we will convert it to W if the notify format    */
+    /* is Unicode.                                     */
+    /* **** **** **** **** WARNING **** **** **** **** */
+    if (infoPtr->bNtfUnicode) {
+        INT len = MultiByteToWideChar( CP_ACP, 0, item->pszText, -1, NULL, 0 );
+        if (len > 1) {
+            tvItem->pszText = (LPSTR)COMCTL32_Alloc (len*sizeof(WCHAR));
+            MultiByteToWideChar( CP_ACP, 0, item->pszText, -1, (LPWSTR)tvItem->pszText, len*sizeof(WCHAR) );
+	}
+    }
+    else
+	tvItem->pszText = item->pszText;
+}
+
+static BOOL
+TREEVIEW_SendTreeviewNotify(TREEVIEW_INFO *infoPtr, UINT code, UINT action,
+			    UINT mask, HTREEITEM oldItem, HTREEITEM newItem)
+{
+    HWND hwnd = infoPtr->hwnd;
+    NMTREEVIEWA nmhdr;
+    BOOL ret;
+
+    TRACE("code:%d action:%x olditem:%p newitem:%p\n",
+	  code, action, oldItem, newItem);
+
+    ZeroMemory(&nmhdr, sizeof(NMTREEVIEWA));
+
+    nmhdr.hdr.hwndFrom = hwnd;
+    nmhdr.hdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
+    nmhdr.hdr.code = get_notifycode(infoPtr, code);
+    nmhdr.action = action;
+
+    if (oldItem)
+	TREEVIEW_TVItemFromItem(infoPtr, mask, &nmhdr.itemOld, oldItem);
+
+    if (newItem)
+	TREEVIEW_TVItemFromItem(infoPtr, mask, &nmhdr.itemNew, newItem);
+
+    nmhdr.ptDrag.x = 0;
+    nmhdr.ptDrag.y = 0;
+
+    ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr,
+			      (WPARAM)GetWindowLongA(hwnd, GWL_ID),
+			      (LPARAM)&nmhdr);
+    if (infoPtr->bNtfUnicode) {
+	COMCTL32_Free(nmhdr.itemOld.pszText);
+	COMCTL32_Free(nmhdr.itemNew.pszText);
+    }
+    return ret;
+}
+
+static BOOL
+TREEVIEW_SendTreeviewDnDNotify(TREEVIEW_INFO *infoPtr, UINT code,
+			       HTREEITEM dragItem, POINT pt)
+{
+    HWND hwnd = infoPtr->hwnd;
+    NMTREEVIEWA nmhdr;
+
+    TRACE("code:%d dragitem:%p\n", code, dragItem);
+
+    nmhdr.hdr.hwndFrom = hwnd;
+    nmhdr.hdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
+    nmhdr.hdr.code = get_notifycode(infoPtr, code);
+    nmhdr.action = 0;
+    nmhdr.itemNew.mask = TVIF_STATE | TVIF_PARAM | TVIF_HANDLE;
+    nmhdr.itemNew.hItem = dragItem;
+    nmhdr.itemNew.state = dragItem->state;
+    nmhdr.itemNew.lParam = dragItem->lParam;
+
+    nmhdr.ptDrag.x = pt.x;
+    nmhdr.ptDrag.y = pt.y;
+
+    return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
+			      (WPARAM)GetWindowLongA(hwnd, GWL_ID),
+			      (LPARAM)&nmhdr);
+}
+
+
+static BOOL
+TREEVIEW_SendCustomDrawNotify(TREEVIEW_INFO *infoPtr, DWORD dwDrawStage,
+			      HDC hdc, RECT rc)
+{
+    HWND hwnd = infoPtr->hwnd;
+    NMTVCUSTOMDRAW nmcdhdr;
+    LPNMCUSTOMDRAW nmcd;
+
+    TRACE("drawstage:%lx hdc:%p\n", dwDrawStage, hdc);
+
+    nmcd = &nmcdhdr.nmcd;
+    nmcd->hdr.hwndFrom = hwnd;
+    nmcd->hdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
+    nmcd->hdr.code = NM_CUSTOMDRAW;
+    nmcd->dwDrawStage = dwDrawStage;
+    nmcd->hdc = hdc;
+    nmcd->rc = rc;
+    nmcd->dwItemSpec = 0;
+    nmcd->uItemState = 0;
+    nmcd->lItemlParam = 0;
+    nmcdhdr.clrText = infoPtr->clrText;
+    nmcdhdr.clrTextBk = infoPtr->clrBk;
+    nmcdhdr.iLevel = 0;
+
+    return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
+			      (WPARAM)GetWindowLongA(hwnd, GWL_ID),
+			      (LPARAM)&nmcdhdr);
+}
+
+
+
+/* FIXME: need to find out when the flags in uItemState need to be set */
+
+static BOOL
+TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc,
+				  TREEVIEW_ITEM *wineItem, UINT uItemDrawState)
+{
+    HWND hwnd = infoPtr->hwnd;
+    NMTVCUSTOMDRAW nmcdhdr;
+    LPNMCUSTOMDRAW nmcd;
+    DWORD dwDrawStage, dwItemSpec;
+    UINT uItemState;
+    INT retval;
+
+    dwDrawStage = CDDS_ITEM | uItemDrawState;
+    dwItemSpec = (DWORD)wineItem;
+    uItemState = 0;
+    if (wineItem->state & TVIS_SELECTED)
+	uItemState |= CDIS_SELECTED;
+    if (wineItem == infoPtr->selectedItem)
+	uItemState |= CDIS_FOCUS;
+    if (wineItem == infoPtr->hotItem)
+	uItemState |= CDIS_HOT;
+
+    nmcd = &nmcdhdr.nmcd;
+    nmcd->hdr.hwndFrom = hwnd;
+    nmcd->hdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
+    nmcd->hdr.code = NM_CUSTOMDRAW;
+    nmcd->dwDrawStage = dwDrawStage;
+    nmcd->hdc = hdc;
+    nmcd->rc = wineItem->rect;
+    nmcd->dwItemSpec = dwItemSpec;
+    nmcd->uItemState = uItemState;
+    nmcd->lItemlParam = wineItem->lParam;
+    nmcdhdr.clrText = infoPtr->clrText;
+    nmcdhdr.clrTextBk = infoPtr->clrBk;
+    nmcdhdr.iLevel = wineItem->iLevel;
+
+    TRACE("drawstage:%lx hdc:%p item:%lx, itemstate:%x, lItemlParam:%lx\n",
+	  nmcd->dwDrawStage, nmcd->hdc, nmcd->dwItemSpec,
+	  nmcd->uItemState, nmcd->lItemlParam);
+
+    retval = TREEVIEW_SendRealNotify(infoPtr,
+			  (WPARAM)GetWindowLongA(hwnd, GWL_ID),
+			  (LPARAM)&nmcdhdr);
+
+    infoPtr->clrText = nmcdhdr.clrText;
+    infoPtr->clrBk = nmcdhdr.clrTextBk;
+    return (BOOL)retval;
+}
+
+static BOOL
+TREEVIEW_BeginLabelEditNotify(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *editItem)
+{
+    HWND hwnd = infoPtr->hwnd;
+    LPSTR allocated = NULL;
+    NMTVDISPINFOA tvdi;
+    BOOL ret;
+
+    tvdi.hdr.hwndFrom = hwnd;
+    tvdi.hdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
+    tvdi.hdr.code = get_notifycode(infoPtr, TVN_BEGINLABELEDITW);
+
+    tvdi.item.mask = TVIF_HANDLE | TVIF_STATE | TVIF_PARAM | TVIF_TEXT;
+    tvdi.item.hItem = editItem;
+    tvdi.item.state = editItem->state;
+    tvdi.item.lParam = editItem->lParam;
+    if (infoPtr->bNtfUnicode) {
+        INT len = MultiByteToWideChar( CP_ACP, 0, editItem->pszText, -1, NULL, 0 );
+        if (len > 1) {
+            tvdi.item.pszText = allocated = (LPSTR)COMCTL32_Alloc (len*sizeof(WCHAR));
+            MultiByteToWideChar( CP_ACP, 0, editItem->pszText, -1, (LPWSTR)tvdi.item.pszText, len*sizeof(WCHAR) );
+	    tvdi.item.cchTextMax = len*sizeof(WCHAR);
+	}
+	else {
+	    tvdi.item.pszText = editItem->pszText;  /* ??? */
+	    tvdi.item.cchTextMax = editItem->cchTextMax;  /* ??? */
+	}
+    }
+    else {
+	tvdi.item.pszText = editItem->pszText;
+	tvdi.item.cchTextMax = editItem->cchTextMax;
+    }
+
+    ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr,
+					 tvdi.hdr.idFrom,
+					(LPARAM)&tvdi);
+    if (allocated)
+	COMCTL32_Free(allocated);
+    return ret;
+}
+
+static void
+TREEVIEW_UpdateDispInfo(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
+			UINT mask)
+{
+    NMTVDISPINFOA callback;
+    HWND hwnd = infoPtr->hwnd;
+
+    mask &= wineItem->callbackMask;
+
+    if (mask == 0) return;
+
+    callback.hdr.hwndFrom         = hwnd;
+    callback.hdr.idFrom           = GetWindowLongA(hwnd, GWL_ID);
+    callback.hdr.code             = get_notifycode(infoPtr, TVN_GETDISPINFOW);
+
+    /* 'state' always contains valid value, as well as 'lParam'.
+     * All other parameters are uninitialized.
+     */
+    callback.item.pszText         = wineItem->pszText;
+    callback.item.cchTextMax      = wineItem->cchTextMax;
+    callback.item.mask            = mask;
+    callback.item.hItem           = wineItem;
+    callback.item.state           = wineItem->state;
+    callback.item.lParam          = wineItem->lParam;
+
+    /* If text is changed we need to recalculate textWidth */
+    if (mask & TVIF_TEXT)
+       wineItem->textWidth = 0;
+
+    TREEVIEW_SendRealNotify(infoPtr,
+                            (WPARAM)callback.hdr.idFrom, (LPARAM)&callback);
+
+    /* It may have changed due to a call to SetItem. */
+    mask &= wineItem->callbackMask;
+
+    if ((mask & TVIF_TEXT) && callback.item.pszText != wineItem->pszText)
+    {
+	/* Instead of copying text into our buffer user specified its own */
+	if (infoPtr->bNtfUnicode) {
+	    LPWSTR newText;
+	    int buflen;
+            int len = WideCharToMultiByte( CP_ACP, 0,
+					   (LPWSTR)callback.item.pszText, -1,
+                                           NULL, 0, NULL, NULL );
+	    buflen = max((len+1)*sizeof(WCHAR), TEXT_CALLBACK_SIZE);
+	    newText = (LPWSTR)COMCTL32_ReAlloc(wineItem->pszText, buflen);
+
+	    TRACE("returned wstr %s, len=%d, buflen=%d\n",
+		  debugstr_w((LPWSTR)callback.item.pszText), len, buflen);
+
+	    if (newText)
+	    {
+		wineItem->pszText = (LPSTR)newText;
+		WideCharToMultiByte( CP_ACP, 0,
+				     (LPWSTR)callback.item.pszText, -1,
+				     wineItem->pszText, buflen,
+				     NULL, NULL );
+		wineItem->cchTextMax = buflen;
+	    }
+	    /* If ReAlloc fails we have nothing to do, but keep original text */
+	}
+	else {
+	    int len = max(lstrlenA(callback.item.pszText) + 1,
+			  TEXT_CALLBACK_SIZE);
+	    LPSTR newText = COMCTL32_ReAlloc(wineItem->pszText, len);
+
+	    TRACE("returned str %s, len=%d\n",
+		  debugstr_a(callback.item.pszText), len);
+
+	    if (newText)
+	    {
+		wineItem->pszText = newText;
+		strcpy(wineItem->pszText, callback.item.pszText);
+		wineItem->cchTextMax = len;
+	    }
+	    /* If ReAlloc fails we have nothing to do, but keep original text */
+	}
+    }
+    else if (mask & TVIF_TEXT) {
+	/* User put text into our buffer, that is ok unless W string */
+	if (infoPtr->bNtfUnicode) {
+	    LPWSTR newText;
+	    LPSTR oldText = NULL;
+	    int buflen;
+            int len = WideCharToMultiByte( CP_ACP, 0,
+					   (LPWSTR)callback.item.pszText, -1,
+                                           NULL, 0, NULL, NULL );
+	    buflen = max((len+1)*sizeof(WCHAR), TEXT_CALLBACK_SIZE);
+	    newText = (LPWSTR)COMCTL32_Alloc(buflen);
+
+	    TRACE("same buffer wstr %s, len=%d, buflen=%d\n",
+		  debugstr_w((LPWSTR)callback.item.pszText), len, buflen);
+
+	    if (newText)
+	    {
+		oldText = wineItem->pszText;
+		wineItem->pszText = (LPSTR)newText;
+		WideCharToMultiByte( CP_ACP, 0,
+				     (LPWSTR)callback.item.pszText, -1,
+				     wineItem->pszText, buflen, NULL, NULL );
+		wineItem->cchTextMax = buflen;
+		if (oldText)
+		    COMCTL32_Free(oldText);
+	    }
+	}
+    }
+
+    if (mask & TVIF_IMAGE)
+	wineItem->iImage = callback.item.iImage;
+
+    if (mask & TVIF_SELECTEDIMAGE)
+	wineItem->iSelectedImage = callback.item.iSelectedImage;
+
+    if (mask & TVIF_CHILDREN)
+	wineItem->cChildren = callback.item.cChildren;
+
+    /* These members are now permanently set. */
+    if (callback.item.mask & TVIF_DI_SETITEM)
+	wineItem->callbackMask &= ~callback.item.mask;
+}
+
+/***************************************************************************
+ * This function uses cChildren field to decide whether the item has
+ * children or not.
+ * Note: if this returns TRUE, the child items may not actually exist,
+ * they could be virtual.
+ *
+ * Just use wineItem->firstChild to check for physical children.
+ */
+static BOOL
+TREEVIEW_HasChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem)
+{
+    TREEVIEW_UpdateDispInfo(infoPtr, wineItem, TVIF_CHILDREN);
+
+    return wineItem->cChildren > 0;
+}
+
+
+/* Item Position ********************************************************/
+
+/* Compute linesOffset, stateOffset, imageOffset, textOffset of an item. */
+static VOID
+TREEVIEW_ComputeItemInternalMetrics(TREEVIEW_INFO *infoPtr,
+				    TREEVIEW_ITEM *item)
+{
+    /* Same effect, different optimisation. */
+#if 0
+    BOOL lar = ((infoPtr->dwStyle & TVS_LINESATROOT)
+		&& (infoPtr->dwStyle & (TVS_HASLINES|TVS_HASBUTTONS)));
+#else
+    BOOL lar = ((infoPtr->dwStyle
+		 & (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS))
+		> TVS_LINESATROOT);
+#endif
+
+    item->linesOffset = infoPtr->uIndent * (item->iLevel + lar - 1)
+	- infoPtr->scrollX;
+    item->stateOffset = item->linesOffset + infoPtr->uIndent;
+    item->imageOffset = item->stateOffset
+	+ (STATEIMAGEINDEX(item->state) ? infoPtr->stateImageWidth : 0);
+    item->textOffset  = item->imageOffset + infoPtr->normalImageWidth;
+}
+
+static VOID
+TREEVIEW_ComputeTextWidth(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item, HDC hDC)
+{
+    HDC hdc;
+    HFONT hOldFont=0;
+    SIZE sz;
+
+    /* DRAW's OM docker creates items like this */
+    if (item->pszText == NULL)
+    {
+	item->textWidth = 0;
+	return;
+    }
+
+    if (item->textWidth != 0 && !(item->callbackMask & TVIF_TEXT))
+       return;
+
+    if (hDC != 0)
+    {
+	hdc = hDC;
+    }
+    else
+    {
+	hdc = GetDC(infoPtr->hwnd);
+	hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, item));
+    }
+
+    GetTextExtentPoint32A(hdc, item->pszText, strlen(item->pszText), &sz);
+    item->textWidth = sz.cx;
+
+    if (hDC == 0)
+    {
+	SelectObject(hdc, hOldFont);
+	ReleaseDC(0, hdc);
+    }
+}
+
+static VOID
+TREEVIEW_ComputeItemRect(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
+{
+    item->rect.top = infoPtr->uItemHeight *
+	(item->visibleOrder - infoPtr->firstVisible->visibleOrder);
+
+    item->rect.bottom = item->rect.top
+	+ infoPtr->uItemHeight * item->iIntegral - 1;
+
+    item->rect.left = 0;
+    item->rect.right = infoPtr->clientWidth;
+}
+
+/* We know that only items after start need their order updated. */
+static void
+TREEVIEW_RecalculateVisibleOrder(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *start)
+{
+    TREEVIEW_ITEM *item;
+    int order;
+
+    if (!start)
+    {
+	start = infoPtr->root->firstChild;
+	order = 0;
+    }
+    else
+	order = start->visibleOrder;
+
+    for (item = start; item != NULL;
+         item = TREEVIEW_GetNextListItem(infoPtr, item))
+    {
+	item->visibleOrder = order;
+	order += item->iIntegral;
+    }
+
+    infoPtr->maxVisibleOrder = order;
+
+    for (item = start; item != NULL;
+	 item = TREEVIEW_GetNextListItem(infoPtr, item))
+    {
+	TREEVIEW_ComputeItemRect(infoPtr, item);
+    }
+}
+
+
+/* Update metrics of all items in selected subtree.
+ * root must be expanded
+ */
+static VOID
+TREEVIEW_UpdateSubTree(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *root)
+{
+   TREEVIEW_ITEM *sibling;
+   HDC hdc;
+   HFONT hOldFont;
+
+   if (!root->firstChild || !(root->state & TVIS_EXPANDED))
+      return;
+
+   root->state &= ~TVIS_EXPANDED;
+   sibling = TREEVIEW_GetNextListItem(infoPtr, root);
+   root->state |= TVIS_EXPANDED;
+
+   hdc = GetDC(infoPtr->hwnd);
+   hOldFont = SelectObject(hdc, infoPtr->hFont);
+
+   for (; root != sibling;
+        root = TREEVIEW_GetNextListItem(infoPtr, root))
+   {
+      TREEVIEW_ComputeItemInternalMetrics(infoPtr, root);
+
+      if (root->callbackMask & TVIF_TEXT)
+         TREEVIEW_UpdateDispInfo(infoPtr, root, TVIF_TEXT);
+
+      if (root->textWidth == 0)
+      {
+         SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, root));
+         TREEVIEW_ComputeTextWidth(infoPtr, root, hdc);
+      }
+   }
+
+   SelectObject(hdc, hOldFont);
+   ReleaseDC(infoPtr->hwnd, hdc);
+}
+
+/* Item Allocation **********************************************************/
+
+static TREEVIEW_ITEM *
+TREEVIEW_AllocateItem(TREEVIEW_INFO *infoPtr)
+{
+    TREEVIEW_ITEM *newItem = COMCTL32_Alloc(sizeof(TREEVIEW_ITEM));
+
+    if (!newItem)
+	return NULL;
+
+    if (DPA_InsertPtr(infoPtr->items, INT_MAX, newItem) == -1)
+    {
+	COMCTL32_Free(newItem);
+	return NULL;
+    }
+
+    return newItem;
+}
+
+/* Exact opposite of TREEVIEW_AllocateItem. In particular, it does not
+ * free item->pszText. */
+static void
+TREEVIEW_FreeItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
+{
+    DPA_DeletePtr(infoPtr->items, DPA_GetPtrIndex(infoPtr->items, item));
+    COMCTL32_Free(item);
+    if (infoPtr->selectedItem == item)
+        infoPtr->selectedItem = NULL;
+    if (infoPtr->hotItem == item)
+        infoPtr->hotItem = NULL;
+    if (infoPtr->focusedItem == item)
+        infoPtr->focusedItem = NULL;
+    if (infoPtr->firstVisible == item)
+        infoPtr->firstVisible = NULL;
+    if (infoPtr->dropItem == item)
+        infoPtr->dropItem = NULL;
+    if (infoPtr->insertMarkItem == item)
+        infoPtr->insertMarkItem = NULL;
+}
+
+
+/* Item Insertion *******************************************************/
+
+/***************************************************************************
+ * This method inserts newItem before sibling as a child of parent.
+ * sibling can be NULL, but only if parent has no children.
+ */
+static void
+TREEVIEW_InsertBefore(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling,
+		      TREEVIEW_ITEM *parent)
+{
+    assert(newItem != NULL);
+    assert(parent != NULL);
+
+    if (sibling != NULL)
+    {
+	assert(sibling->parent == parent);
+
+	if (sibling->prevSibling != NULL)
+	    sibling->prevSibling->nextSibling = newItem;
+
+	newItem->prevSibling = sibling->prevSibling;
+	sibling->prevSibling = newItem;
+    }
+    else
+       newItem->prevSibling = NULL;
+
+    newItem->nextSibling = sibling;
+
+    if (parent->firstChild == sibling)
+	parent->firstChild = newItem;
+
+    if (parent->lastChild == NULL)
+	parent->lastChild = newItem;
+}
+
+/***************************************************************************
+ * This method inserts newItem after sibling as a child of parent.
+ * sibling can be NULL, but only if parent has no children.
+ */
+static void
+TREEVIEW_InsertAfter(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling,
+		     TREEVIEW_ITEM *parent)
+{
+    assert(newItem != NULL);
+    assert(parent != NULL);
+
+    if (sibling != NULL)
+    {
+	assert(sibling->parent == parent);
+
+	if (sibling->nextSibling != NULL)
+	    sibling->nextSibling->prevSibling = newItem;
+
+	newItem->nextSibling = sibling->nextSibling;
+	sibling->nextSibling = newItem;
+    }
+    else
+       newItem->nextSibling = NULL;
+
+    newItem->prevSibling = sibling;
+
+    if (parent->lastChild == sibling)
+	parent->lastChild = newItem;
+
+    if (parent->firstChild == NULL)
+	parent->firstChild = newItem;
+}
+
+static BOOL
+TREEVIEW_DoSetItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
+		   const TVITEMEXA *tvItem)
+{
+    UINT callbackClear = 0;
+    UINT callbackSet = 0;
+
+    /* Do this first in case it fails. */
+    if (tvItem->mask & TVIF_TEXT)
+    {
+        wineItem->textWidth = 0; /* force width recalculation */
+	if (tvItem->pszText != LPSTR_TEXTCALLBACKA)
+	{
+	    int len = lstrlenA(tvItem->pszText) + 1;
+	    LPSTR newText = COMCTL32_ReAlloc(wineItem->pszText, len);
+
+	    if (newText == NULL) return FALSE;
+
+	    callbackClear |= TVIF_TEXT;
+
+	    wineItem->pszText = newText;
+	    wineItem->cchTextMax = len;
+	    lstrcpynA(wineItem->pszText, tvItem->pszText, len);
+	    TRACE("setting text %s, item %p\n",
+		  debugstr_a(wineItem->pszText), wineItem);
+	}
+	else
+	{
+	    callbackSet |= TVIF_TEXT;
+
+	    wineItem->pszText = COMCTL32_ReAlloc(wineItem->pszText,
+						 TEXT_CALLBACK_SIZE);
+	    wineItem->cchTextMax = TEXT_CALLBACK_SIZE;
+	    TRACE("setting callback, item %p\n",
+		  wineItem);
+	}
+    }
+
+    if (tvItem->mask & TVIF_CHILDREN)
+    {
+	wineItem->cChildren = tvItem->cChildren;
+
+	if (wineItem->cChildren == I_CHILDRENCALLBACK)
+	    callbackSet |= TVIF_CHILDREN;
+	else
+	    callbackClear |= TVIF_CHILDREN;
+    }
+
+    if (tvItem->mask & TVIF_IMAGE)
+    {
+	wineItem->iImage = tvItem->iImage;
+
+	if (wineItem->iImage == I_IMAGECALLBACK)
+	    callbackSet |= TVIF_IMAGE;
+	else
+	    callbackClear |= TVIF_IMAGE;
+    }
+
+    if (tvItem->mask & TVIF_SELECTEDIMAGE)
+    {
+	wineItem->iSelectedImage = tvItem->iSelectedImage;
+
+	if (wineItem->iSelectedImage == I_IMAGECALLBACK)
+	    callbackSet |= TVIF_SELECTEDIMAGE;
+	else
+	    callbackClear |= TVIF_SELECTEDIMAGE;
+    }
+
+    if (tvItem->mask & TVIF_PARAM)
+	wineItem->lParam = tvItem->lParam;
+
+    /* If the application sets TVIF_INTEGRAL without
+     * supplying a TVITEMEX structure, it's toast. */
+    if (tvItem->mask & TVIF_INTEGRAL)
+	wineItem->iIntegral = tvItem->iIntegral;
+
+    if (tvItem->mask & TVIF_STATE)
+    {
+	TRACE("prevstate,state,mask:%x,%x,%x\n", wineItem->state, tvItem->state,
+	      tvItem->stateMask);
+	wineItem->state &= ~tvItem->stateMask;
+	wineItem->state |= (tvItem->state & tvItem->stateMask);
+    }
+
+    wineItem->callbackMask |= callbackSet;
+    wineItem->callbackMask &= ~callbackClear;
+
+    return TRUE;
+}
+
+/* Note that the new item is pre-zeroed. */
+static LRESULT
+TREEVIEW_InsertItemA(TREEVIEW_INFO *infoPtr, LPARAM lParam)
+{
+    const TVINSERTSTRUCTA *ptdi = (LPTVINSERTSTRUCTA) lParam;
+    const TVITEMEXA *tvItem = &ptdi->DUMMYUNIONNAME.itemex;
+    HTREEITEM insertAfter;
+    TREEVIEW_ITEM *newItem, *parentItem;
+    BOOL bTextUpdated = FALSE;
+
+    if (ptdi->hParent == TVI_ROOT || ptdi->hParent == 0)
+    {
+	parentItem = infoPtr->root;
+    }
+    else
+    {
+	parentItem = ptdi->hParent;
+
+	if (!TREEVIEW_ValidItem(infoPtr, parentItem))
+	{
+	    WARN("invalid parent %p\n", parentItem);
+	    return (LRESULT)(HTREEITEM)NULL;
+	}
+    }
+
+    insertAfter = ptdi->hInsertAfter;
+
+    /* Validate this now for convenience. */
+    switch ((DWORD)insertAfter)
+    {
+    case (DWORD)TVI_FIRST:
+    case (DWORD)TVI_LAST:
+    case (DWORD)TVI_SORT:
+	break;
+
+    default:
+	if (!TREEVIEW_ValidItem(infoPtr, insertAfter) ||
+            insertAfter->parent != parentItem)
+	{
+	    WARN("invalid insert after %p\n", insertAfter);
+	    insertAfter = TVI_LAST;
+	}
+    }
+
+    TRACE("parent %p position %p: '%s'\n", parentItem, insertAfter,
+	  (tvItem->mask & TVIF_TEXT)
+	  ? ((tvItem->pszText == LPSTR_TEXTCALLBACKA) ? "<callback>"
+	     : tvItem->pszText)
+	  : "<no label>");
+
+    newItem = TREEVIEW_AllocateItem(infoPtr);
+    if (newItem == NULL)
+	return (LRESULT)(HTREEITEM)NULL;
+
+    newItem->parent = parentItem;
+    newItem->iIntegral = 1;
+
+    if (!TREEVIEW_DoSetItem(infoPtr, newItem, tvItem))
+	return (LRESULT)(HTREEITEM)NULL;
+
+    /* After this point, nothing can fail. (Except for TVI_SORT.) */
+
+    infoPtr->uNumItems++;
+
+    switch ((DWORD)insertAfter)
+    {
+    case (DWORD)TVI_FIRST:
+        {
+           TREEVIEW_ITEM *originalFirst = parentItem->firstChild;
+           TREEVIEW_InsertBefore(newItem, parentItem->firstChild, parentItem);
+           if (infoPtr->firstVisible == originalFirst)
+              TREEVIEW_SetFirstVisible(infoPtr, newItem, TRUE);
+        }
+	break;
+
+    case (DWORD)TVI_LAST:
+	TREEVIEW_InsertAfter(newItem, parentItem->lastChild, parentItem);
+	break;
+
+	/* hInsertAfter names a specific item we want to insert after */
+    default:
+	TREEVIEW_InsertAfter(newItem, insertAfter, insertAfter->parent);
+	break;
+
+    case (DWORD)TVI_SORT:
+	{
+	    TREEVIEW_ITEM *aChild;
+	    TREEVIEW_ITEM *previousChild = NULL;
+	    BOOL bItemInserted = FALSE;
+
+	    aChild = parentItem->firstChild;
+
+	    bTextUpdated = TRUE;
+	    TREEVIEW_UpdateDispInfo(infoPtr, newItem, TVIF_TEXT);
+
+	    /* Iterate the parent children to see where we fit in */
+	    while (aChild != NULL)
+	    {
+		INT comp;
+
+		TREEVIEW_UpdateDispInfo(infoPtr, aChild, TVIF_TEXT);
+		comp = lstrcmpA(newItem->pszText, aChild->pszText);
+
+		if (comp < 0)	/* we are smaller than the current one */
+		{
+		    TREEVIEW_InsertBefore(newItem, aChild, parentItem);
+		    bItemInserted = TRUE;
+		    break;
+		}
+		else if (comp > 0)	/* we are bigger than the current one */
+		{
+		    previousChild = aChild;
+
+		    /* This will help us to exit if there is no more sibling */
+		    aChild = (aChild->nextSibling == 0)
+			? NULL
+			: aChild->nextSibling;
+
+		    /* 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(newItem, aChild, parentItem);
+		    bItemInserted = TRUE;
+		    break;
+		}
+	    }
+
+	    /*
+	     * we reach the end of the child list and the item has not
+	     * yet been inserted, therefore, insert it after the last child.
+	     */
+	    if ((!bItemInserted) && (aChild == NULL))
+		TREEVIEW_InsertAfter(newItem, previousChild, parentItem);
+
+	    break;
+	}
+    }
+
+
+    TRACE("new item %p; parent %p, mask %x\n", newItem,
+	  newItem->parent, tvItem->mask);
+
+    newItem->iLevel = newItem->parent->iLevel + 1;
+
+    if (newItem->parent->cChildren == 0)
+	newItem->parent->cChildren = 1;
+
+    if (infoPtr->dwStyle & TVS_CHECKBOXES)
+    {
+	if (STATEIMAGEINDEX(newItem->state) == 0)
+	    newItem->state |= INDEXTOSTATEIMAGEMASK(1);
+    }
+
+    if (infoPtr->firstVisible == NULL)
+	infoPtr->firstVisible = newItem;
+
+    TREEVIEW_VerifyTree(infoPtr);
+
+    if (parentItem == infoPtr->root ||
+        (ISVISIBLE(parentItem) && parentItem->state & TVIS_EXPANDED))
+    {
+       TREEVIEW_ITEM *item;
+       TREEVIEW_ITEM *prev = TREEVIEW_GetPrevListItem(infoPtr, newItem);
+
+       TREEVIEW_RecalculateVisibleOrder(infoPtr, prev);
+       TREEVIEW_ComputeItemInternalMetrics(infoPtr, newItem);
+
+       if (!bTextUpdated)
+          TREEVIEW_UpdateDispInfo(infoPtr, newItem, TVIF_TEXT);
+
+       TREEVIEW_ComputeTextWidth(infoPtr, newItem, 0);
+       TREEVIEW_UpdateScrollBars(infoPtr);
+    /*
+     * if the item was inserted in a visible part of the tree,
+     * invalidate it, as well as those after it
+     */
+       for (item = newItem;
+            item != NULL;
+	    item = TREEVIEW_GetNextListItem(infoPtr, item))
+          TREEVIEW_Invalidate(infoPtr, item);
+    }
+    else
+    {
+       newItem->visibleOrder = -1;
+
+       /* refresh treeview if newItem is the first item inserted under parentItem */
+       if (ISVISIBLE(parentItem) && newItem->prevSibling == newItem->nextSibling)
+       {
+          /* parent got '+' - update it */
+          TREEVIEW_Invalidate(infoPtr, parentItem);
+       }
+    }
+
+    return (LRESULT)newItem;
+}
+
+
+static LRESULT
+TREEVIEW_InsertItemW(TREEVIEW_INFO *infoPtr, LPARAM lParam)
+{
+    TVINSERTSTRUCTW *tvisW;
+    TVINSERTSTRUCTA tvisA;
+    LRESULT lRes;
+
+    tvisW = (LPTVINSERTSTRUCTW) lParam;
+
+    tvisA.hParent = tvisW->hParent;
+    tvisA.hInsertAfter = tvisW->hInsertAfter;
+
+    tvisA.DUMMYUNIONNAME.item.mask = tvisW->DUMMYUNIONNAME.item.mask;
+    tvisA.DUMMYUNIONNAME.item.hItem = tvisW->DUMMYUNIONNAME.item.hItem;
+    tvisA.DUMMYUNIONNAME.item.state = tvisW->DUMMYUNIONNAME.item.state;
+    tvisA.DUMMYUNIONNAME.item.stateMask = tvisW->DUMMYUNIONNAME.item.stateMask;
+    tvisA.DUMMYUNIONNAME.item.cchTextMax =
+	tvisW->DUMMYUNIONNAME.item.cchTextMax;
+
+    if (tvisW->DUMMYUNIONNAME.item.pszText)
+    {
+	if (tvisW->DUMMYUNIONNAME.item.pszText != LPSTR_TEXTCALLBACKW)
+	{
+            int len = WideCharToMultiByte( CP_ACP, 0, tvisW->DUMMYUNIONNAME.item.pszText, -1,
+                                           NULL, 0, NULL, NULL );
+	    tvisA.DUMMYUNIONNAME.item.pszText = COMCTL32_Alloc(len);
+            WideCharToMultiByte( CP_ACP, 0, tvisW->DUMMYUNIONNAME.item.pszText, -1,
+                                 tvisA.DUMMYUNIONNAME.item.pszText, len, NULL, NULL );
+	}
+	else
+	{
+	    tvisA.DUMMYUNIONNAME.item.pszText = LPSTR_TEXTCALLBACKA;
+	    tvisA.DUMMYUNIONNAME.item.cchTextMax = 0;
+	}
+    }
+
+    tvisA.DUMMYUNIONNAME.item.iImage = tvisW->DUMMYUNIONNAME.item.iImage;
+    tvisA.DUMMYUNIONNAME.item.iSelectedImage =
+	tvisW->DUMMYUNIONNAME.item.iSelectedImage;
+    tvisA.DUMMYUNIONNAME.item.cChildren = tvisW->DUMMYUNIONNAME.item.cChildren;
+    tvisA.DUMMYUNIONNAME.item.lParam = tvisW->DUMMYUNIONNAME.item.lParam;
+
+    lRes = TREEVIEW_InsertItemA(infoPtr, (LPARAM)&tvisA);
+
+    if (tvisA.DUMMYUNIONNAME.item.pszText != LPSTR_TEXTCALLBACKA)
+    {
+	COMCTL32_Free(tvisA.DUMMYUNIONNAME.item.pszText);
+    }
+
+    return lRes;
+
+}
+
+
+/* Item Deletion ************************************************************/
+static void
+TREEVIEW_RemoveItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem);
+
+static void
+TREEVIEW_RemoveAllChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *parentItem)
+{
+    TREEVIEW_ITEM *kill = parentItem->firstChild;
+
+    while (kill != NULL)
+    {
+	TREEVIEW_ITEM *next = kill->nextSibling;
+
+	TREEVIEW_RemoveItem(infoPtr, kill);
+
+	kill = next;
+    }
+
+    assert(parentItem->cChildren <= 0); /* I_CHILDRENCALLBACK or 0 */
+    assert(parentItem->firstChild == NULL);
+    assert(parentItem->lastChild == NULL);
+}
+
+static void
+TREEVIEW_UnlinkItem(TREEVIEW_ITEM *item)
+{
+    TREEVIEW_ITEM *parentItem = item->parent;
+
+    assert(item != NULL);
+    assert(item->parent != NULL); /* i.e. it must not be the root */
+
+    if (parentItem->firstChild == item)
+	parentItem->firstChild = item->nextSibling;
+
+    if (parentItem->lastChild == item)
+	parentItem->lastChild = item->prevSibling;
+
+    if (parentItem->firstChild == NULL && parentItem->lastChild == NULL
+	&& parentItem->cChildren > 0)
+	parentItem->cChildren = 0;
+
+    if (item->prevSibling)
+	item->prevSibling->nextSibling = item->nextSibling;
+
+    if (item->nextSibling)
+	item->nextSibling->prevSibling = item->prevSibling;
+}
+
+static void
+TREEVIEW_RemoveItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem)
+{
+    TRACE("%p, (%s)\n", wineItem, TREEVIEW_ItemName(wineItem));
+
+    TREEVIEW_SendTreeviewNotify(infoPtr, TVN_DELETEITEMW, TVC_UNKNOWN,
+				TVIF_HANDLE | TVIF_PARAM, wineItem, 0);
+
+    if (wineItem->firstChild)
+	TREEVIEW_RemoveAllChildren(infoPtr, wineItem);
+
+    TREEVIEW_UnlinkItem(wineItem);
+
+    infoPtr->uNumItems--;
+
+    if (wineItem->pszText != LPSTR_TEXTCALLBACKA)
+	COMCTL32_Free(wineItem->pszText);
+
+    TREEVIEW_FreeItem(infoPtr, wineItem);
+}
+
+
+/* Empty out the tree. */
+static void
+TREEVIEW_RemoveTree(TREEVIEW_INFO *infoPtr)
+{
+    TREEVIEW_RemoveAllChildren(infoPtr, infoPtr->root);
+
+    assert(infoPtr->uNumItems == 0);	/* root isn't counted in uNumItems */
+}
+
+static LRESULT
+TREEVIEW_DeleteItem(TREEVIEW_INFO *infoPtr, HTREEITEM wineItem)
+{
+    TREEVIEW_ITEM *oldSelection = infoPtr->selectedItem;
+    TREEVIEW_ITEM *newSelection = oldSelection;
+    TREEVIEW_ITEM *newFirstVisible = NULL;
+    TREEVIEW_ITEM *parent, *prev = NULL;
+    BOOL visible = FALSE;
+
+    if (wineItem == TVI_ROOT)
+    {
+	TRACE("TVI_ROOT\n");
+	parent = infoPtr->root;
+	newSelection = NULL;
+	visible = TRUE;
+	TREEVIEW_RemoveTree(infoPtr);
+    }
+    else
+    {
+	if (!TREEVIEW_ValidItem(infoPtr, wineItem))
+	    return FALSE;
+
+	TRACE("%p (%s)\n", wineItem, TREEVIEW_ItemName(wineItem));
+	parent = wineItem->parent;
+
+        if (ISVISIBLE(wineItem))
+        {
+            prev = TREEVIEW_GetPrevListItem(infoPtr, wineItem);
+            visible = TRUE;
+        }
+
+	if (infoPtr->selectedItem != NULL
+	    && (wineItem == infoPtr->selectedItem
+		|| TREEVIEW_IsChildOf(wineItem, infoPtr->selectedItem)))
+	{
+	    if (wineItem->nextSibling)
+		newSelection = wineItem->nextSibling;
+	    else if (wineItem->parent != infoPtr->root)
+		newSelection = wineItem->parent;
+	}
+
+	if (infoPtr->firstVisible == wineItem)
+	{
+	    if (wineItem->nextSibling)
+	       newFirstVisible = wineItem->nextSibling;
+	    else if (wineItem->prevSibling)
+	       newFirstVisible = wineItem->prevSibling;
+	    else if (wineItem->parent != infoPtr->root)
+	       newFirstVisible = wineItem->parent;
+	       TREEVIEW_SetFirstVisible(infoPtr, NULL, TRUE);
+	}
+	else
+	    newFirstVisible = infoPtr->firstVisible;
+
+	TREEVIEW_RemoveItem(infoPtr, wineItem);
+    }
+
+    /* Don't change if somebody else already has. */
+    if (oldSelection == infoPtr->selectedItem)
+    {
+	if (TREEVIEW_ValidItem(infoPtr, newSelection))
+	    TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, newSelection, TVC_UNKNOWN);
+	else
+	    infoPtr->selectedItem = 0;
+    }
+
+    /* Validate insertMark dropItem.
+     * hotItem ??? - used for comparison only.
+     */
+    if (!TREEVIEW_ValidItem(infoPtr, infoPtr->insertMarkItem))
+	infoPtr->insertMarkItem = 0;
+
+    if (!TREEVIEW_ValidItem(infoPtr, infoPtr->dropItem))
+	infoPtr->dropItem = 0;
+
+    if (!TREEVIEW_ValidItem(infoPtr, newFirstVisible))
+        newFirstVisible = infoPtr->root->firstChild;
+
+    TREEVIEW_VerifyTree(infoPtr);
+
+
+    if (visible)
+    {
+       TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE);
+       TREEVIEW_RecalculateVisibleOrder(infoPtr, prev);
+       TREEVIEW_UpdateScrollBars(infoPtr);
+       TREEVIEW_Invalidate(infoPtr, NULL);
+    }
+    else if (ISVISIBLE(parent) && !TREEVIEW_HasChildren(infoPtr, parent))
+    {
+       /* parent lost '+/-' - update it */
+       TREEVIEW_Invalidate(infoPtr, parent);
+    }
+
+    return TRUE;
+}
+
+
+/* Get/Set Messages *********************************************************/
+static LRESULT
+TREEVIEW_SetRedraw(TREEVIEW_INFO* infoPtr, WPARAM wParam, LPARAM lParam)
+{
+  if(wParam)
+    infoPtr->bRedraw = TRUE;
+  else
+    infoPtr->bRedraw = FALSE;
+
+  return 0;
+}
+
+static LRESULT
+TREEVIEW_GetIndent(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("\n");
+    return infoPtr->uIndent;
+}
+
+static LRESULT
+TREEVIEW_SetIndent(TREEVIEW_INFO *infoPtr, UINT newIndent)
+{
+    TRACE("\n");
+
+    if (newIndent < MINIMUM_INDENT)
+	newIndent = MINIMUM_INDENT;
+
+    if (infoPtr->uIndent != newIndent)
+    {
+	infoPtr->uIndent = newIndent;
+	TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root);
+	TREEVIEW_UpdateScrollBars(infoPtr);
+	TREEVIEW_Invalidate(infoPtr, NULL);
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TREEVIEW_GetToolTips(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("\n");
+    return (LRESULT)infoPtr->hwndToolTip;
+}
+
+static LRESULT
+TREEVIEW_SetToolTips(TREEVIEW_INFO *infoPtr, HWND hwndTT)
+{
+    HWND prevToolTip;
+
+    TRACE("\n");
+    prevToolTip = infoPtr->hwndToolTip;
+    infoPtr->hwndToolTip = hwndTT;
+
+    return (LRESULT)prevToolTip;
+}
+
+
+static LRESULT
+TREEVIEW_GetScrollTime(TREEVIEW_INFO *infoPtr)
+{
+    return infoPtr->uScrollTime;
+}
+
+static LRESULT
+TREEVIEW_SetScrollTime(TREEVIEW_INFO *infoPtr, UINT uScrollTime)
+{
+    UINT uOldScrollTime = infoPtr->uScrollTime;
+
+    infoPtr->uScrollTime = min(uScrollTime, 100);
+
+    return uOldScrollTime;
+}
+
+
+static LRESULT
+TREEVIEW_GetImageList(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+{
+    TRACE("\n");
+
+    switch (wParam)
+    {
+    case (WPARAM)TVSIL_NORMAL:
+	return (LRESULT)infoPtr->himlNormal;
+
+    case (WPARAM)TVSIL_STATE:
+	return (LRESULT)infoPtr->himlState;
+
+    default:
+	return 0;
+    }
+}
+
+static LRESULT
+TREEVIEW_SetImageList(TREEVIEW_INFO *infoPtr, WPARAM wParam, HIMAGELIST himlNew)
+{
+    HIMAGELIST himlOld = 0;
+    int oldWidth  = infoPtr->normalImageWidth;
+    int oldHeight = infoPtr->normalImageHeight;
+
+
+    TRACE("%x,%p\n", wParam, himlNew);
+
+    switch (wParam)
+    {
+    case (WPARAM)TVSIL_NORMAL:
+	himlOld = infoPtr->himlNormal;
+	infoPtr->himlNormal = himlNew;
+
+	if (himlNew != NULL)
+	    ImageList_GetIconSize(himlNew, &infoPtr->normalImageWidth,
+				  &infoPtr->normalImageHeight);
+	else
+	{
+	    infoPtr->normalImageWidth = 0;
+	    infoPtr->normalImageHeight = 0;
+	}
+
+	break;
+
+    case (WPARAM)TVSIL_STATE:
+	himlOld = infoPtr->himlState;
+	infoPtr->himlState = himlNew;
+
+	if (himlNew != NULL)
+	    ImageList_GetIconSize(himlNew, &infoPtr->stateImageWidth,
+				  &infoPtr->stateImageHeight);
+	else
+	{
+	    infoPtr->stateImageWidth = 0;
+	    infoPtr->stateImageHeight = 0;
+	}
+
+	break;
+    }
+
+    if (oldWidth != infoPtr->normalImageWidth ||
+        oldHeight != infoPtr->normalImageHeight)
+    {
+       TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root);
+       TREEVIEW_UpdateScrollBars(infoPtr);
+    }
+
+    TREEVIEW_Invalidate(infoPtr, NULL);
+
+    return (LRESULT)himlOld;
+}
+
+/* Compute the natural height (based on the font size) for items. */
+static UINT
+TREEVIEW_NaturalHeight(TREEVIEW_INFO *infoPtr)
+{
+    TEXTMETRICA tm;
+    HDC hdc = GetDC(0);
+    HFONT hOldFont = SelectObject(hdc, infoPtr->hFont);
+
+    GetTextMetricsA(hdc, &tm);
+
+    SelectObject(hdc, hOldFont);
+    ReleaseDC(0, hdc);
+
+    /* The 16 is a hack because our fonts are tiny. */
+    /* add 2 for the focus border and 1 more for margin some apps assume */
+    return max(16, tm.tmHeight + tm.tmExternalLeading + 3);
+}
+
+static LRESULT
+TREEVIEW_SetItemHeight(TREEVIEW_INFO *infoPtr, INT newHeight)
+{
+    INT prevHeight = infoPtr->uItemHeight;
+
+    TRACE("%d \n", newHeight);
+    if (newHeight == -1)
+    {
+	infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr);
+	infoPtr->bHeightSet = FALSE;
+    }
+    else
+    {
+	infoPtr->uItemHeight = newHeight;
+	infoPtr->bHeightSet = TRUE;
+    }
+
+    /* Round down, unless we support odd ("non even") heights. */
+    if (!(infoPtr->dwStyle) & TVS_NONEVENHEIGHT)
+	infoPtr->uItemHeight &= ~1;
+
+    if (infoPtr->uItemHeight != prevHeight)
+    {
+	TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL);
+	TREEVIEW_UpdateScrollBars(infoPtr);
+	TREEVIEW_Invalidate(infoPtr, NULL);
+    }
+
+    return prevHeight;
+}
+
+static LRESULT
+TREEVIEW_GetItemHeight(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("\n");
+    return infoPtr->uItemHeight;
+}
+
+
+static LRESULT
+TREEVIEW_GetFont(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("%p\n", infoPtr->hFont);
+    return (LRESULT)infoPtr->hFont;
+}
+
+
+static INT CALLBACK
+TREEVIEW_ResetTextWidth(LPVOID pItem, DWORD unused)
+{
+    (void)unused;
+
+    ((TREEVIEW_ITEM *)pItem)->textWidth = 0;
+
+    return 1;
+}
+
+static LRESULT
+TREEVIEW_SetFont(TREEVIEW_INFO *infoPtr, HFONT hFont, BOOL bRedraw)
+{
+    UINT uHeight = infoPtr->uItemHeight;
+
+    TRACE("%p %i\n", hFont, bRedraw);
+
+    infoPtr->hFont = hFont ? hFont : GetStockObject(SYSTEM_FONT);
+
+    DeleteObject(infoPtr->hBoldFont);
+    infoPtr->hBoldFont = TREEVIEW_CreateBoldFont(infoPtr->hFont);
+
+    if (!infoPtr->bHeightSet)
+	infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr);
+
+    if (uHeight != infoPtr->uItemHeight)
+       TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL);
+
+    DPA_EnumCallback(infoPtr->items, TREEVIEW_ResetTextWidth, 0);
+
+    TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root);
+    TREEVIEW_UpdateScrollBars(infoPtr);
+
+    if (bRedraw)
+	TREEVIEW_Invalidate(infoPtr, NULL);
+
+    return 0;
+}
+
+
+static LRESULT
+TREEVIEW_GetLineColor(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("\n");
+    return (LRESULT)infoPtr->clrLine;
+}
+
+static LRESULT
+TREEVIEW_SetLineColor(TREEVIEW_INFO *infoPtr, COLORREF color)
+{
+    COLORREF prevColor = infoPtr->clrLine;
+
+    TRACE("\n");
+    infoPtr->clrLine = color;
+    return (LRESULT)prevColor;
+}
+
+
+static LRESULT
+TREEVIEW_GetTextColor(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("\n");
+    return (LRESULT)infoPtr->clrText;
+}
+
+static LRESULT
+TREEVIEW_SetTextColor(TREEVIEW_INFO *infoPtr, COLORREF color)
+{
+    COLORREF prevColor = infoPtr->clrText;
+
+    TRACE("\n");
+    infoPtr->clrText = color;
+
+    if (infoPtr->clrText != prevColor)
+	TREEVIEW_Invalidate(infoPtr, NULL);
+
+    return (LRESULT)prevColor;
+}
+
+
+static LRESULT
+TREEVIEW_GetBkColor(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("\n");
+    return (LRESULT)infoPtr->clrBk;
+}
+
+static LRESULT
+TREEVIEW_SetBkColor(TREEVIEW_INFO *infoPtr, COLORREF newColor)
+{
+    COLORREF prevColor = infoPtr->clrBk;
+
+    TRACE("\n");
+    infoPtr->clrBk = newColor;
+
+    if (newColor != prevColor)
+	TREEVIEW_Invalidate(infoPtr, NULL);
+
+    return (LRESULT)prevColor;
+}
+
+
+static LRESULT
+TREEVIEW_GetInsertMarkColor(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("\n");
+    return (LRESULT)infoPtr->clrInsertMark;
+}
+
+static LRESULT
+TREEVIEW_SetInsertMarkColor(TREEVIEW_INFO *infoPtr, COLORREF color)
+{
+    COLORREF prevColor = infoPtr->clrInsertMark;
+
+    TRACE("%lx\n", color);
+    infoPtr->clrInsertMark = color;
+
+    return (LRESULT)prevColor;
+}
+
+
+static LRESULT
+TREEVIEW_SetInsertMark(TREEVIEW_INFO *infoPtr, BOOL wParam, HTREEITEM item)
+{
+    TRACE("%d %p\n", wParam, item);
+
+    if (!TREEVIEW_ValidItem(infoPtr, item))
+	return 0;
+
+    infoPtr->insertBeforeorAfter = wParam;
+    infoPtr->insertMarkItem = item;
+
+    TREEVIEW_Invalidate(infoPtr, NULL);
+
+    return 1;
+}
+
+
+/************************************************************************
+ * Some serious braindamage here. lParam is a pointer to both the
+ * input HTREEITEM and the output RECT.
+ */
+static LRESULT
+TREEVIEW_GetItemRect(TREEVIEW_INFO *infoPtr, BOOL fTextRect, LPRECT lpRect)
+{
+    TREEVIEW_ITEM *wineItem;
+    const HTREEITEM *pItem = (HTREEITEM *)lpRect;
+
+    TRACE("\n");
+    /*
+     * validate parameters
+     */
+    if (pItem == NULL)
+	return FALSE;
+
+    wineItem = *pItem;
+    if (!TREEVIEW_ValidItem(infoPtr, wineItem) || !ISVISIBLE(wineItem))
+	return FALSE;
+
+    /*
+     * If wParam is TRUE return the text size otherwise return
+     * the whole item size
+     */
+    if (fTextRect)
+    {
+	/* Windows does not send TVN_GETDISPINFO here. */
+
+	lpRect->top = wineItem->rect.top;
+	lpRect->bottom = wineItem->rect.bottom;
+
+	lpRect->left = wineItem->textOffset;
+	lpRect->right = wineItem->textOffset + wineItem->textWidth;
+    }
+    else
+    {
+	*lpRect = wineItem->rect;
+    }
+
+    TRACE("%s [L:%ld R:%ld T:%ld B:%ld]\n", fTextRect ? "text" : "item",
+	  lpRect->left, lpRect->right, lpRect->top, lpRect->bottom);
+
+    return TRUE;
+}
+
+static inline LRESULT
+TREEVIEW_GetVisibleCount(TREEVIEW_INFO *infoPtr)
+{
+    /* Suprise! This does not take integral height into account. */
+    return infoPtr->clientHeight / infoPtr->uItemHeight;
+}
+
+
+static LRESULT
+TREEVIEW_GetItemA(TREEVIEW_INFO *infoPtr, LPTVITEMEXA tvItem)
+{
+    TREEVIEW_ITEM *wineItem;
+
+    wineItem = tvItem->hItem;
+    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
+	return FALSE;
+
+    TREEVIEW_UpdateDispInfo(infoPtr, wineItem, tvItem->mask);
+
+    if (tvItem->mask & TVIF_CHILDREN)
+	tvItem->cChildren = wineItem->cChildren;
+
+    if (tvItem->mask & TVIF_HANDLE)
+	tvItem->hItem = wineItem;
+
+    if (tvItem->mask & TVIF_IMAGE)
+	tvItem->iImage = wineItem->iImage;
+
+    if (tvItem->mask & TVIF_INTEGRAL)
+	tvItem->iIntegral = wineItem->iIntegral;
+
+    /* undocumented: windows ignores TVIF_PARAM and
+     * * always sets lParam
+     */
+    tvItem->lParam = wineItem->lParam;
+
+    if (tvItem->mask & TVIF_SELECTEDIMAGE)
+	tvItem->iSelectedImage = wineItem->iSelectedImage;
+
+    if (tvItem->mask & TVIF_STATE) {
+        /* Careful here - Windows ignores the stateMask when you get the state
+ 	    That contradicts the documentation, but makes more common sense, masking
+	    retrieval in this way seems overkill */
+        tvItem->state = wineItem->state;
+    }
+
+    if (tvItem->mask & TVIF_TEXT)
+	lstrcpynA(tvItem->pszText, wineItem->pszText, tvItem->cchTextMax);
+
+    TRACE("item <%p>, txt %p, img %p, mask %x\n",
+	  wineItem, tvItem->pszText, &tvItem->iImage, tvItem->mask);
+
+    return TRUE;
+}
+
+/* Beware MSDN Library Visual Studio 6.0. It says -1 on failure, 0 on success,
+ * which is wrong. */
+static LRESULT
+TREEVIEW_SetItemA(TREEVIEW_INFO *infoPtr, LPTVITEMEXA tvItem)
+{
+    TREEVIEW_ITEM *wineItem;
+    TREEVIEW_ITEM originalItem;
+
+    wineItem = tvItem->hItem;
+
+    TRACE("item %d,mask %x\n", TREEVIEW_GetItemIndex(infoPtr, wineItem),
+	  tvItem->mask);
+
+    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
+	return FALSE;
+    
+    /* store the orignal item values */
+    originalItem = *wineItem;
+
+    if (!TREEVIEW_DoSetItem(infoPtr, wineItem, tvItem))
+	return FALSE;
+
+    /* If the text or TVIS_BOLD was changed, and it is visible, recalculate. */
+    if ((tvItem->mask & TVIF_TEXT
+	 || (tvItem->mask & TVIF_STATE && tvItem->stateMask & TVIS_BOLD))
+	&& ISVISIBLE(wineItem))
+    {
+	TREEVIEW_UpdateDispInfo(infoPtr, wineItem, TVIF_TEXT);
+	TREEVIEW_ComputeTextWidth(infoPtr, wineItem, 0);
+    }
+
+    if (tvItem->mask != 0 && ISVISIBLE(wineItem))
+    {
+	/* The refresh updates everything, but we can't wait until then. */
+	TREEVIEW_ComputeItemInternalMetrics(infoPtr, wineItem);
+
+        /* if any of the items values changed, redraw the item */
+        if(memcmp(&originalItem, wineItem, sizeof(TREEVIEW_ITEM)))
+        {
+            if (tvItem->mask & TVIF_INTEGRAL)
+	    {
+	        TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem);
+	        TREEVIEW_UpdateScrollBars(infoPtr);
+
+	        TREEVIEW_Invalidate(infoPtr, NULL);
+	    }
+	    else
+	    {
+	        TREEVIEW_UpdateScrollBars(infoPtr);
+	        TREEVIEW_Invalidate(infoPtr, wineItem);
+	    }
+        }
+    }
+
+    return TRUE;
+}
+
+static LRESULT
+TREEVIEW_GetItemW(TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem)
+{
+    TREEVIEW_ITEM *wineItem;
+    INT         iItem;
+    iItem = (INT)tvItem->hItem;
+
+    wineItem = tvItem->hItem;
+    if(!TREEVIEW_ValidItem (infoPtr, wineItem))
+        return FALSE;
+
+    TREEVIEW_UpdateDispInfo(infoPtr, wineItem, tvItem->mask);
+
+    if (tvItem->mask & TVIF_CHILDREN) {
+        if (TVIF_CHILDREN==I_CHILDRENCALLBACK)
+            FIXME("I_CHILDRENCALLBACK not supported\n");
+        tvItem->cChildren = wineItem->cChildren;
+    }
+
+    if (tvItem->mask & TVIF_HANDLE) {
+        tvItem->hItem = wineItem;
+    }
+    if (tvItem->mask & TVIF_IMAGE) {
+        tvItem->iImage = wineItem->iImage;
+    }
+    if (tvItem->mask & TVIF_INTEGRAL) {
+        tvItem->iIntegral = wineItem->iIntegral;
+    }
+    /* undocumented: windows ignores TVIF_PARAM and
+     * always sets lParam           */
+    tvItem->lParam = wineItem->lParam;
+    if (tvItem->mask & TVIF_SELECTEDIMAGE) {
+        tvItem->iSelectedImage = wineItem->iSelectedImage;
+    }
+    if (tvItem->mask & TVIF_STATE) {
+        tvItem->state = wineItem->state & tvItem->stateMask;
+    }
+
+    if (tvItem->mask & TVIF_TEXT) {
+        if (wineItem->pszText == LPSTR_TEXTCALLBACKA) {
+            tvItem->pszText = LPSTR_TEXTCALLBACKW;
+            FIXME(" GetItem called with LPSTR_TEXTCALLBACK\n");
+        }
+        else if (wineItem->pszText) {
+	    TRACE("orig str %s at %p\n",
+		  debugstr_a(wineItem->pszText), wineItem->pszText);
+            MultiByteToWideChar(CP_ACP, 0, wineItem->pszText,
+                                -1 , tvItem->pszText, tvItem->cchTextMax);
+        }
+    }
+
+    TRACE("item %d<%p>, txt %p<%s>, img %p, action %x\n",
+	  iItem, tvItem, tvItem->pszText, debugstr_w(tvItem->pszText),
+	  &tvItem->iImage, tvItem->mask);
+    return TRUE;
+}
+
+static LRESULT
+TREEVIEW_SetItemW(TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem)
+{
+    TVITEMEXA tvItemA;
+    INT len;
+    LRESULT rc;
+
+    tvItemA.mask = tvItem->mask;
+    tvItemA.hItem = tvItem->hItem;
+    tvItemA.state = tvItem->state;
+    tvItemA.stateMask = tvItem->stateMask;
+    if (tvItem->mask & TVIF_TEXT) {
+	len = WideCharToMultiByte(CP_ACP, 0, tvItem->pszText, -1,
+				  NULL ,0 , NULL,NULL);
+	if (len) {
+	    len ++;
+	    tvItemA.pszText = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
+	    len = WideCharToMultiByte(CP_ACP, 0, tvItem->pszText, -1,
+				      tvItemA.pszText ,len*sizeof(WCHAR),
+				      NULL,NULL);
+	}
+	else
+	    tvItemA.pszText = NULL;
+    }
+    tvItemA.cchTextMax = tvItem->cchTextMax;
+    tvItemA.iImage = tvItem->iImage;
+    tvItemA.iSelectedImage = tvItem->iSelectedImage;
+    tvItemA.cChildren = tvItem->cChildren;
+    tvItemA.lParam = tvItem->lParam;
+    tvItemA.iIntegral = tvItem->iIntegral;
+
+    rc = TREEVIEW_SetItemA(infoPtr,&tvItemA);
+    HeapFree(GetProcessHeap(),0,tvItemA.pszText);
+    return rc;
+}
+
+static LRESULT
+TREEVIEW_GetItemState(TREEVIEW_INFO *infoPtr, HTREEITEM wineItem, UINT mask)
+{
+    TRACE("\n");
+
+    if (!wineItem || !TREEVIEW_ValidItem(infoPtr, wineItem))
+	return 0;
+
+    return (wineItem->state & mask);
+}
+
+static LRESULT
+TREEVIEW_GetNextItem(TREEVIEW_INFO *infoPtr, UINT which, HTREEITEM wineItem)
+{
+    TREEVIEW_ITEM *retval;
+
+    retval = 0;
+
+    /* handle all the global data here */
+    switch (which)
+    {
+    case TVGN_CHILD:		/* Special case: child of 0 is root */
+	if (wineItem)
+	    break;
+	/* fall through */
+    case TVGN_ROOT:
+	retval = infoPtr->root->firstChild;
+	break;
+
+    case TVGN_CARET:
+	retval = infoPtr->selectedItem;
+	break;
+
+    case TVGN_FIRSTVISIBLE:
+	retval = infoPtr->firstVisible;
+	break;
+
+    case TVGN_DROPHILITE:
+	retval = infoPtr->dropItem;
+	break;
+
+    case TVGN_LASTVISIBLE:
+	retval = TREEVIEW_GetLastListItem(infoPtr, infoPtr->root);
+	break;
+    }
+
+    if (retval)
+    {
+	TRACE("flags:%x, returns %p\n", which, retval);
+	return (LRESULT)retval;
+    }
+
+    if (wineItem == TVI_ROOT) wineItem = infoPtr->root;
+
+    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
+	return FALSE;
+
+    switch (which)
+    {
+    case TVGN_NEXT:
+	retval = wineItem->nextSibling;
+	break;
+    case TVGN_PREVIOUS:
+	retval = wineItem->prevSibling;
+	break;
+    case TVGN_PARENT:
+	retval = (wineItem->parent != infoPtr->root) ? wineItem->parent : NULL;
+	break;
+    case TVGN_CHILD:
+	retval = wineItem->firstChild;
+	break;
+    case TVGN_NEXTVISIBLE:
+	retval = TREEVIEW_GetNextListItem(infoPtr, wineItem);
+	break;
+    case TVGN_PREVIOUSVISIBLE:
+	retval = TREEVIEW_GetPrevListItem(infoPtr, wineItem);
+	break;
+    default:
+	TRACE("Unknown msg %x,item %p\n", which, wineItem);
+	break;
+    }
+
+    TRACE("flags:%x, item %p;returns %p\n", which, wineItem, retval);
+    return (LRESULT)retval;
+}
+
+
+static LRESULT
+TREEVIEW_GetCount(TREEVIEW_INFO *infoPtr)
+{
+    TRACE(" %d\n", infoPtr->uNumItems);
+    return (LRESULT)infoPtr->uNumItems;
+}
+
+static VOID
+TREEVIEW_ToggleItemState(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
+{
+    if (infoPtr->dwStyle & TVS_CHECKBOXES)
+    {
+	static const unsigned int state_table[] = { 0, 2, 1 };
+
+	unsigned int state;
+
+	state = STATEIMAGEINDEX(item->state);
+	TRACE("state:%x\n", state);
+	item->state &= ~TVIS_STATEIMAGEMASK;
+
+	if (state < 3)
+	    state = state_table[state];
+
+	item->state |= INDEXTOSTATEIMAGEMASK(state);
+
+	TRACE("state:%x\n", state);
+	TREEVIEW_Invalidate(infoPtr, item);
+    }
+}
+
+
+/* Painting *************************************************************/
+
+/* Draw the lines and expand button for an item. Also draws one section
+ * of the line from item's parent to item's parent's next sibling. */
+static void
+TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item)
+{
+    LONG centerx, centery;
+    BOOL lar = ((infoPtr->dwStyle
+		 & (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS))
+		> TVS_LINESATROOT);
+
+    if (!lar && item->iLevel == 0)
+	return;
+
+    centerx = (item->linesOffset + item->stateOffset) / 2;
+    centery = (item->rect.top + item->rect.bottom) / 2;
+
+    if (infoPtr->dwStyle & TVS_HASLINES)
+    {
+	HPEN hOldPen, hNewPen;
+	HTREEITEM parent;
+
+	/*
+	 * Get a dotted grey pen
+	 */
+	hNewPen = CreatePen(PS_ALTERNATE, 0, infoPtr->clrLine);
+	hOldPen = SelectObject(hdc, hNewPen);
+
+	MoveToEx(hdc, item->stateOffset, centery, NULL);
+	LineTo(hdc, centerx - 1, centery);
+
+	if (item->prevSibling || item->parent != infoPtr->root)
+	{
+	    MoveToEx(hdc, centerx, item->rect.top, NULL);
+	    LineTo(hdc, centerx, centery);
+	}
+
+	if (item->nextSibling)
+	{
+	    MoveToEx(hdc, centerx, centery, NULL);
+	    LineTo(hdc, centerx, item->rect.bottom + 1);
+	}
+
+	/* Draw the line from our parent to its next sibling. */
+	parent = item->parent;
+	while (parent != infoPtr->root)
+	{
+	    int pcenterx = (parent->linesOffset + parent->stateOffset) / 2;
+
+	    if (parent->nextSibling
+		/* skip top-levels unless TVS_LINESATROOT */
+		&& parent->stateOffset > parent->linesOffset)
+	    {
+		MoveToEx(hdc, pcenterx, item->rect.top, NULL);
+		LineTo(hdc, pcenterx, item->rect.bottom + 1);
+	    }
+
+	    parent = parent->parent;
+	}
+
+	SelectObject(hdc, hOldPen);
+	DeleteObject(hNewPen);
+    }
+
+    /*
+     * Display the (+/-) signs
+     */
+
+    if (infoPtr->dwStyle & TVS_HASBUTTONS)
+    {
+	if (item->cChildren)
+	{
+	    LONG height = item->rect.bottom - item->rect.top;
+	    LONG width  = item->stateOffset - item->linesOffset;
+	    LONG rectsize = min(height, width) / 4;
+	    /* plussize = ceil(rectsize * 3/4) */
+	    LONG plussize = (rectsize + 1) * 3 / 4;
+
+	    HPEN hNewPen  = CreatePen(PS_SOLID, 0, infoPtr->clrLine);
+	    HPEN hOldPen  = SelectObject(hdc, hNewPen);
+	    HBRUSH hbr    = CreateSolidBrush(infoPtr->clrBk);
+	    HBRUSH hbrOld = SelectObject(hdc, hbr);
+
+	    Rectangle(hdc, centerx - rectsize, centery - rectsize,
+		      centerx + rectsize + 1, centery + rectsize + 1);
+
+	    SelectObject(hdc, hbrOld);
+	    DeleteObject(hbr);
+
+	    SelectObject(hdc, hOldPen);
+	    DeleteObject(hNewPen);
+
+	    MoveToEx(hdc, centerx - plussize + 1, centery, NULL);
+	    LineTo(hdc, centerx + plussize, centery);
+
+	    if (!(item->state & TVIS_EXPANDED))
+	    {
+		MoveToEx(hdc, centerx, centery - plussize + 1, NULL);
+		LineTo(hdc, centerx, centery + plussize);
+	    }
+	}
+    }
+}
+
+static void
+TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
+{
+    INT cditem;
+    HFONT hOldFont;
+    int centery;
+
+    hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, wineItem));
+
+    TREEVIEW_UpdateDispInfo(infoPtr, wineItem, CALLBACK_MASK_ALL);
+
+    /* The custom draw handler can query the text rectangle,
+     * so get ready. */
+    TREEVIEW_ComputeTextWidth(infoPtr, wineItem, hdc);
+
+    cditem = 0;
+
+    if (infoPtr->cdmode & CDRF_NOTIFYITEMDRAW)
+    {
+	cditem = TREEVIEW_SendCustomDrawItemNotify
+	    (infoPtr, hdc, wineItem, CDDS_ITEMPREPAINT);
+	TRACE("prepaint:cditem-app returns 0x%x\n", cditem);
+
+	if (cditem & CDRF_SKIPDEFAULT)
+	{
+	    SelectObject(hdc, hOldFont);
+	    return;
+	}
+    }
+
+    if (cditem & CDRF_NEWFONT)
+	TREEVIEW_ComputeTextWidth(infoPtr, wineItem, hdc);
+
+    TREEVIEW_DrawItemLines(infoPtr, hdc, wineItem);
+
+    centery = (wineItem->rect.top + wineItem->rect.bottom) / 2;
+
+    /*
+     * Display the images associated with this item
+     */
+    {
+	INT imageIndex;
+
+	/* State images are displayed to the left of the Normal image
+	 * image number is in state; zero should be `display no image'.
+	 */
+	imageIndex = STATEIMAGEINDEX(wineItem->state);
+
+	if (infoPtr->himlState && imageIndex)
+	{
+	    ImageList_Draw(infoPtr->himlState, imageIndex, hdc,
+			   wineItem->stateOffset,
+			   centery - infoPtr->stateImageHeight / 2,
+			   ILD_NORMAL);
+	}
+
+	/* Now, draw the normal image; can be either selected or
+	 * non-selected image.
+	 */
+
+	if ((wineItem->state & TVIS_SELECTED) && (wineItem->iSelectedImage))
+	{
+	    /* The item is currently selected */
+	    imageIndex = wineItem->iSelectedImage;
+	}
+	else
+	{
+	    /* The item is not selected */
+	    imageIndex = wineItem->iImage;
+	}
+
+	if (infoPtr->himlNormal)
+	{
+	    int ovlIdx = wineItem->state & TVIS_OVERLAYMASK;
+
+	    ImageList_Draw(infoPtr->himlNormal, imageIndex, hdc,
+			   wineItem->imageOffset,
+			   centery - infoPtr->normalImageHeight / 2,
+			   ILD_NORMAL | ovlIdx);
+	}
+    }
+
+
+    /*
+     * Display the text associated with this item
+     */
+
+    /* Don't paint item's text if it's being edited */
+    if (!infoPtr->hwndEdit || (infoPtr->selectedItem != wineItem))
+    {
+	if (wineItem->pszText)
+	{
+	    COLORREF oldTextColor = 0;
+	    INT oldBkMode;
+	    HBRUSH hbrBk = 0;
+	    BOOL inFocus = (GetFocus() == infoPtr->hwnd);
+	    RECT rcText;
+
+	    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 == infoPtr->focusedItem) && !(wineItem->state & TVIS_SELECTED)) ||
+		((wineItem->state & TVIS_SELECTED) && (!infoPtr->focusedItem) &&
+		 (inFocus || (infoPtr->dwStyle & 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);
+	    }
+
+	    rcText.top = wineItem->rect.top;
+	    rcText.bottom = wineItem->rect.bottom;
+	    rcText.left = wineItem->textOffset;
+	    rcText.right = rcText.left + wineItem->textWidth + 4;
+
+	    if (hbrBk)
+	    {
+		FillRect(hdc, &rcText, hbrBk);
+		DeleteObject(hbrBk);
+	    }
+
+	    /* Draw the box around the selected item */
+	    if ((wineItem == infoPtr->selectedItem) && inFocus)
+	    {
+		DrawFocusRect(hdc,&rcText);
+	    }
+
+	    InflateRect(&rcText, -2, -1); /* allow for the focus rect */
+
+	    TRACE("drawing text %s at (%ld,%ld)-(%ld,%ld)\n",
+		  debugstr_a(wineItem->pszText),
+		  rcText.left, rcText.top, rcText.right, rcText.bottom);
+
+	    /* Draw it */
+	    DrawTextA(hdc,
+		      wineItem->pszText,
+		      lstrlenA(wineItem->pszText),
+		      &rcText,
+		      DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
+
+	    /* Restore the hdc state */
+	    SetTextColor(hdc, oldTextColor);
+
+	    if (oldBkMode != TRANSPARENT)
+		SetBkMode(hdc, oldBkMode);
+	}
+    }
+
+    /* Draw insertion mark if necessary */
+
+    if (infoPtr->insertMarkItem)
+	TRACE("item:%d,mark:%d\n",
+	      TREEVIEW_GetItemIndex(infoPtr, wineItem),
+	      (int)infoPtr->insertMarkItem);
+
+    if (wineItem == infoPtr->insertMarkItem)
+    {
+	HPEN hNewPen, hOldPen;
+	int offset;
+	int left, right;
+
+	hNewPen = CreatePen(PS_SOLID, 2, infoPtr->clrInsertMark);
+	hOldPen = SelectObject(hdc, hNewPen);
+
+	if (infoPtr->insertBeforeorAfter)
+	    offset = wineItem->rect.bottom - 1;
+	else
+	    offset = wineItem->rect.top + 1;
+
+	left = wineItem->textOffset - 2;
+	right = wineItem->textOffset + wineItem->textWidth + 2;
+
+	MoveToEx(hdc, left, offset - 3, NULL);
+	LineTo(hdc, left, offset + 4);
+
+	MoveToEx(hdc, left, offset, NULL);
+	LineTo(hdc, right + 1, offset);
+
+	MoveToEx(hdc, right, offset + 3, NULL);
+	LineTo(hdc, right, offset - 4);
+
+	SelectObject(hdc, hOldPen);
+	DeleteObject(hNewPen);
+    }
+
+    if (cditem & CDRF_NOTIFYPOSTPAINT)
+    {
+	cditem = TREEVIEW_SendCustomDrawItemNotify
+	    (infoPtr, hdc, wineItem, CDDS_ITEMPOSTPAINT);
+	TRACE("postpaint:cditem-app returns 0x%x\n", cditem);
+    }
+
+    SelectObject(hdc, hOldFont);
+}
+
+/* Computes treeHeight and treeWidth and updates the scroll bars.
+ */
+static void
+TREEVIEW_UpdateScrollBars(TREEVIEW_INFO *infoPtr)
+{
+    TREEVIEW_ITEM *wineItem;
+    HWND hwnd = infoPtr->hwnd;
+    BOOL vert = FALSE;
+    BOOL horz = FALSE;
+    SCROLLINFO si;
+    LONG scrollX = infoPtr->scrollX;
+
+    infoPtr->treeWidth = 0;
+    infoPtr->treeHeight = 0;
+
+    /* We iterate through all visible items in order to get the tree height
+     * and width */
+    wineItem = infoPtr->root->firstChild;
+
+    while (wineItem != NULL)
+    {
+	if (ISVISIBLE(wineItem))
+	{
+            /* actually we draw text at textOffset + 2 */
+	    if (2+wineItem->textOffset+wineItem->textWidth > infoPtr->treeWidth)
+		infoPtr->treeWidth = wineItem->textOffset+wineItem->textWidth+2;
+
+	    /* This is scroll-adjusted, but we fix this below. */
+	    infoPtr->treeHeight = wineItem->rect.bottom;
+	}
+
+	wineItem = TREEVIEW_GetNextListItem(infoPtr, wineItem);
+    }
+
+    /* Fix the scroll adjusted treeHeight and treeWidth. */
+    if (infoPtr->root->firstChild)
+	infoPtr->treeHeight -= infoPtr->root->firstChild->rect.top;
+
+    infoPtr->treeWidth += infoPtr->scrollX;
+
+    if (infoPtr->dwStyle & TVS_NOSCROLL) return;
+
+    /* Adding one scroll bar may take up enough space that it forces us
+     * to add the other as well. */
+    if (infoPtr->treeHeight > infoPtr->clientHeight)
+    {
+	vert = TRUE;
+
+	if (infoPtr->treeWidth
+	    > infoPtr->clientWidth - GetSystemMetrics(SM_CXVSCROLL))
+	    horz = TRUE;
+    }
+    else if (infoPtr->treeWidth > infoPtr->clientWidth)
+	horz = TRUE;
+
+    if (!vert && horz && infoPtr->treeHeight
+	> infoPtr->clientHeight - GetSystemMetrics(SM_CYVSCROLL))
+	vert = TRUE;
+
+    if (horz && (infoPtr->dwStyle & TVS_NOHSCROLL)) horz = FALSE;
+
+    si.cbSize = sizeof(SCROLLINFO);
+    si.fMask  = SIF_POS|SIF_RANGE|SIF_PAGE;
+    si.nMin   = 0;
+
+    if (vert)
+    {
+	si.nPage = TREEVIEW_GetVisibleCount(infoPtr);
+       if ( si.nPage )
+       {
+           si.nPos  = infoPtr->firstVisible->visibleOrder;
+           si.nMax  = infoPtr->maxVisibleOrder - 1;
+
+           SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+
+           if (!(infoPtr->uInternalStatus & TV_VSCROLL))
+               ShowScrollBar(hwnd, SB_VERT, TRUE);
+           infoPtr->uInternalStatus |= TV_VSCROLL;
+       }
+       else
+       {
+           if (infoPtr->uInternalStatus & TV_VSCROLL)
+               ShowScrollBar(hwnd, SB_VERT, FALSE);
+           infoPtr->uInternalStatus &= ~TV_VSCROLL;
+       }
+    }
+    else
+    {
+	if (infoPtr->uInternalStatus & TV_VSCROLL)
+	    ShowScrollBar(hwnd, SB_VERT, FALSE);
+	infoPtr->uInternalStatus &= ~TV_VSCROLL;
+    }
+
+    if (horz)
+    {
+	si.nPage = infoPtr->clientWidth;
+	si.nPos  = infoPtr->scrollX;
+	si.nMax  = infoPtr->treeWidth - 1;
+
+	if (si.nPos > si.nMax - max( si.nPage-1, 0 ))
+        {
+           si.nPos = si.nMax - max( si.nPage-1, 0 );
+           scrollX = si.nPos;
+        }
+
+	if (!(infoPtr->uInternalStatus & TV_HSCROLL))
+	    ShowScrollBar(hwnd, SB_HORZ, TRUE);
+	infoPtr->uInternalStatus |= TV_HSCROLL;
+
+	SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
+    }
+    else
+    {
+	if (infoPtr->uInternalStatus & TV_HSCROLL)
+	    ShowScrollBar(hwnd, SB_HORZ, FALSE);
+	infoPtr->uInternalStatus &= ~TV_HSCROLL;
+
+	scrollX = 0;
+    }
+
+    if (infoPtr->scrollX != scrollX)
+    {
+	TREEVIEW_HScroll(infoPtr,
+	                 MAKEWPARAM(SB_THUMBPOSITION, scrollX));
+    }
+
+    if (!horz)
+	infoPtr->uInternalStatus &= ~TV_HSCROLL;
+}
+
+/* CtrlSpy doesn't mention this, but CorelDRAW's object manager needs it. */
+static LRESULT
+TREEVIEW_EraseBackground(TREEVIEW_INFO *infoPtr, HDC hDC)
+{
+    HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
+    RECT rect;
+
+    GetClientRect(infoPtr->hwnd, &rect);
+    FillRect(hDC, &rect, hBrush);
+    DeleteObject(hBrush);
+
+    return 1;
+}
+
+static void
+TREEVIEW_Refresh(TREEVIEW_INFO *infoPtr, HDC hdc, RECT *rc)
+{
+    HWND hwnd = infoPtr->hwnd;
+    RECT rect = *rc;
+    TREEVIEW_ITEM *wineItem;
+
+    if (infoPtr->clientHeight == 0 || infoPtr->clientWidth == 0)
+    {
+	TRACE("empty window\n");
+	return;
+    }
+
+    infoPtr->cdmode = TREEVIEW_SendCustomDrawNotify(infoPtr, CDDS_PREPAINT,
+						    hdc, rect);
+
+    if (infoPtr->cdmode == CDRF_SKIPDEFAULT)
+    {
+	ReleaseDC(hwnd, hdc);
+	return;
+    }
+
+    for (wineItem = infoPtr->root->firstChild;
+         wineItem != NULL;
+         wineItem = TREEVIEW_GetNextListItem(infoPtr, wineItem))
+    {
+	if (ISVISIBLE(wineItem))
+	{
+            /* Avoid unneeded calculations */
+            if (wineItem->rect.top > rect.bottom)
+                break;
+            if (wineItem->rect.bottom < rect.top)
+                continue;
+
+	    TREEVIEW_DrawItem(infoPtr, hdc, wineItem);
+	}
+    }
+
+    TREEVIEW_UpdateScrollBars(infoPtr);
+
+    if (infoPtr->cdmode & CDRF_NOTIFYPOSTPAINT)
+	infoPtr->cdmode =
+	    TREEVIEW_SendCustomDrawNotify(infoPtr, CDDS_POSTPAINT, hdc, rect);
+}
+
+static void
+TREEVIEW_Invalidate(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
+{
+    if (item != NULL)
+	InvalidateRect(infoPtr->hwnd, &item->rect, TRUE);
+    else
+        InvalidateRect(infoPtr->hwnd, NULL, TRUE);
+}
+
+static LRESULT
+TREEVIEW_Paint(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+{
+    HDC hdc;
+    PAINTSTRUCT ps;
+    RECT rc;
+
+    TRACE("\n");
+
+    if (wParam)
+    {
+        hdc = (HDC)wParam;
+        if (!GetUpdateRect(infoPtr->hwnd, &rc, TRUE))
+        {
+            HBITMAP hbitmap;
+            BITMAP bitmap;
+            hbitmap = GetCurrentObject(hdc, OBJ_BITMAP);
+            if (!hbitmap) return 0;
+            GetObjectA(hbitmap, sizeof(BITMAP), &bitmap);
+            rc.left = 0; rc.top = 0;
+            rc.right = bitmap.bmWidth;
+            rc.bottom = bitmap.bmHeight;
+            TREEVIEW_EraseBackground(infoPtr, (HDC)wParam);
+        }
+    }
+    else
+    {
+        hdc = BeginPaint(infoPtr->hwnd, &ps);
+        rc = ps.rcPaint;
+    }
+
+    if(infoPtr->bRedraw) /* WM_SETREDRAW sets bRedraw */
+        TREEVIEW_Refresh(infoPtr, hdc, &rc);
+
+    if (!wParam)
+	EndPaint(infoPtr->hwnd, &ps);
+
+    return 0;
+}
+
+
+/* Sorting **************************************************************/
+
+/***************************************************************************
+ * Forward the DPA local callback to the treeview owner callback
+ */
+static INT WINAPI
+TREEVIEW_CallBackCompare(TREEVIEW_ITEM *first, TREEVIEW_ITEM *second, LPTVSORTCB pCallBackSort)
+{
+    /* Forward the call to the client-defined callback */
+    return pCallBackSort->lpfnCompare(first->lParam,
+				      second->lParam,
+				      pCallBackSort->lParam);
+}
+
+/***************************************************************************
+ * Treeview native sort routine: sort on item text.
+ */
+static INT WINAPI
+TREEVIEW_SortOnName(TREEVIEW_ITEM *first, TREEVIEW_ITEM *second,
+                     TREEVIEW_INFO *infoPtr)
+{
+    TREEVIEW_UpdateDispInfo(infoPtr, first, TVIF_TEXT);
+    TREEVIEW_UpdateDispInfo(infoPtr, second, TVIF_TEXT);
+
+    return strcasecmp(first->pszText, second->pszText);
+}
+
+/* Returns the number of physical children belonging to item. */
+static INT
+TREEVIEW_CountChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
+{
+    INT cChildren = 0;
+    HTREEITEM hti;
+
+    for (hti = item->firstChild; hti != NULL; hti = hti->nextSibling)
+	cChildren++;
+
+    return cChildren;
+}
+
+/* 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(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
+{
+    HTREEITEM child = item->firstChild;
+
+    HDPA list = DPA_Create(8);
+    if (list == 0) return NULL;
+
+    for (child = item->firstChild; child != NULL; child = child->nextSibling)
+    {
+	if (DPA_InsertPtr(list, INT_MAX, child) == -1)
+	{
+	    DPA_Destroy(list);
+	    return NULL;
+	}
+    }
+
+    return list;
+}
+
+/***************************************************************************
+ * Setup the treeview structure with regards of the sort method
+ * and sort the children of the TV item specified in lParam
+ * fRecurse: currently unused. Should be zero.
+ * parent: if pSort!=NULL, should equal pSort->hParent.
+ *         otherwise, item which child items are to be sorted.
+ * pSort:  sort method info. if NULL, sort on item text.
+ *         if non-NULL, sort on item's lParam content, and let the
+ *         application decide what that means. See also TVM_SORTCHILDRENCB.
+ */
+
+static LRESULT
+TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, BOOL fRecurse, HTREEITEM parent,
+	      LPTVSORTCB pSort)
+{
+    INT cChildren;
+    PFNDPACOMPARE pfnCompare;
+    LPARAM lpCompare;
+
+    /* undocumented feature: TVI_ROOT or NULL means `sort the whole tree' */
+    if (parent == TVI_ROOT || parent == NULL)
+	parent = infoPtr->root;
+
+    /* Check for a valid handle to the parent item */
+    if (!TREEVIEW_ValidItem(infoPtr, parent))
+    {
+	ERR("invalid item hParent=%x\n", (INT)parent);
+	return FALSE;
+    }
+
+    if (pSort)
+    {
+	pfnCompare = (PFNDPACOMPARE)TREEVIEW_CallBackCompare;
+	lpCompare = (LPARAM)pSort;
+    }
+    else
+    {
+	pfnCompare = (PFNDPACOMPARE)TREEVIEW_SortOnName;
+	lpCompare = (LPARAM)infoPtr;
+    }
+
+    cChildren = TREEVIEW_CountChildren(infoPtr, parent);
+
+    /* Make sure there is something to sort */
+    if (cChildren > 1)
+    {
+	/* TREEVIEW_ITEM rechaining */
+	INT count = 0;
+	HTREEITEM item = 0;
+	HTREEITEM nextItem = 0;
+	HTREEITEM prevItem = 0;
+
+	HDPA sortList = TREEVIEW_BuildChildDPA(infoPtr, parent);
+
+	if (sortList == NULL)
+	    return FALSE;
+
+	/* let DPA sort the list */
+	DPA_Sort(sortList, pfnCompare, lpCompare);
+
+	/* 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)
+	{
+	    /* link the two current item toghether */
+	    item->nextSibling = nextItem;
+	    nextItem->prevSibling = item;
+
+	    if (prevItem == NULL)
+	    {
+		/* this is the first item, update the parent */
+		parent->firstChild = item;
+		item->prevSibling = NULL;
+	    }
+	    else
+	    {
+		/* fix the back chaining */
+		item->prevSibling = prevItem;
+	    }
+
+	    /* get ready for the next one */
+	    prevItem = item;
+	    item = nextItem;
+	}
+
+	/* the last item is pointed to by item and never has a sibling */
+	item->nextSibling = NULL;
+	parent->lastChild = item;
+
+	DPA_Destroy(sortList);
+
+	TREEVIEW_VerifyTree(infoPtr);
+
+	if (parent->state & TVIS_EXPANDED)
+	{
+	    int visOrder = infoPtr->firstVisible->visibleOrder;
+
+        if (parent == infoPtr->root)
+            TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL);
+        else
+            TREEVIEW_RecalculateVisibleOrder(infoPtr, parent);
+
+	    if (TREEVIEW_IsChildOf(parent, infoPtr->firstVisible))
+	    {
+	        TREEVIEW_ITEM *item;
+
+	        for (item = infoPtr->root->firstChild; item != NULL;
+	             item = TREEVIEW_GetNextListItem(infoPtr, item))
+	        {
+	            if (item->visibleOrder == visOrder)
+	                break;
+	        }
+
+                TREEVIEW_SetFirstVisible(infoPtr, item, FALSE);
+	    }
+
+	    TREEVIEW_Invalidate(infoPtr, NULL);
+	}
+
+	return TRUE;
+    }
+    return FALSE;
+}
+
+
+/***************************************************************************
+ * Setup the treeview structure with regards of the sort method
+ * and sort the children of the TV item specified in lParam
+ */
+static LRESULT
+TREEVIEW_SortChildrenCB(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPTVSORTCB pSort)
+{
+    return TREEVIEW_Sort(infoPtr, wParam, pSort->hParent, pSort);
+}
+
+
+/***************************************************************************
+ * Sort the children of the TV item specified in lParam.
+ */
+static LRESULT
+TREEVIEW_SortChildren(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+{
+    return TREEVIEW_Sort(infoPtr, (BOOL)wParam, (HTREEITEM)lParam, NULL);
+}
+
+
+/* Expansion/Collapse ***************************************************/
+
+static BOOL
+TREEVIEW_SendExpanding(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
+		       UINT action)
+{
+    return !TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDINGW, action,
+					TVIF_HANDLE | TVIF_STATE | TVIF_PARAM
+					| TVIF_IMAGE | TVIF_SELECTEDIMAGE,
+					0, wineItem);
+}
+
+static VOID
+TREEVIEW_SendExpanded(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
+		      UINT action)
+{
+    TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDEDW, action,
+				TVIF_HANDLE | TVIF_STATE | TVIF_PARAM
+				| TVIF_IMAGE | TVIF_SELECTEDIMAGE,
+				0, wineItem);
+}
+
+
+/* This corresponds to TVM_EXPAND with TVE_COLLAPSE.
+ * bRemoveChildren corresponds to TVE_COLLAPSERESET. */
+static BOOL
+TREEVIEW_Collapse(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
+		  BOOL bRemoveChildren, BOOL bUser)
+{
+    UINT action = TVE_COLLAPSE | (bRemoveChildren ? TVE_COLLAPSERESET : 0);
+    BOOL bSetSelection, bSetFirstVisible;
+
+    TRACE("TVE_COLLAPSE %p %s\n", wineItem, TREEVIEW_ItemName(wineItem));
+
+    if (!(wineItem->state & TVIS_EXPANDED) || wineItem->firstChild == NULL)
+	return FALSE;
+
+    if (bUser)
+	TREEVIEW_SendExpanding(infoPtr, wineItem, action);
+
+    wineItem->state &= ~TVIS_EXPANDED;
+
+    if (bUser)
+	TREEVIEW_SendExpanded(infoPtr, wineItem, action);
+
+    bSetSelection = (infoPtr->selectedItem != NULL
+		     && TREEVIEW_IsChildOf(wineItem, infoPtr->selectedItem));
+
+    bSetFirstVisible = (infoPtr->firstVisible != NULL
+                        && TREEVIEW_IsChildOf(wineItem, infoPtr->firstVisible));
+
+    if (bRemoveChildren)
+    {
+	TRACE("TVE_COLLAPSERESET\n");
+	wineItem->state &= ~TVIS_EXPANDEDONCE;
+	TREEVIEW_RemoveAllChildren(infoPtr, wineItem);
+    }
+
+    if (wineItem->firstChild)
+    {
+        TREEVIEW_ITEM *item, *sibling;
+
+	sibling = TREEVIEW_GetNextListItem(infoPtr, wineItem);
+
+	for (item = wineItem->firstChild; item != sibling;
+	     item = TREEVIEW_GetNextListItem(infoPtr, item))
+	{
+	    item->visibleOrder = -1;
+	}
+    }
+
+    TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem);
+
+    TREEVIEW_SetFirstVisible(infoPtr, bSetFirstVisible ? wineItem
+			     : infoPtr->firstVisible, TRUE);
+
+    if (bSetSelection)
+    {
+	/* Don't call DoSelectItem, it sends notifications. */
+	if (TREEVIEW_ValidItem(infoPtr, infoPtr->selectedItem))
+	    infoPtr->selectedItem->state &= ~TVIS_SELECTED;
+	wineItem->state |= TVIS_SELECTED;
+	infoPtr->selectedItem = wineItem;
+
+	TREEVIEW_EnsureVisible(infoPtr, wineItem, FALSE);
+    }
+
+    TREEVIEW_UpdateScrollBars(infoPtr);
+    TREEVIEW_Invalidate(infoPtr, NULL);
+
+    return TRUE;
+}
+
+static BOOL
+TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
+		BOOL bExpandPartial, BOOL bUser)
+{
+    TRACE("\n");
+
+    if (!TREEVIEW_HasChildren(infoPtr, wineItem)
+	|| wineItem->state & TVIS_EXPANDED)
+	return FALSE;
+
+    TRACE("TVE_EXPAND %p %s\n", wineItem, TREEVIEW_ItemName(wineItem));
+
+    if (bUser || !(wineItem->state & TVIS_EXPANDEDONCE))
+    {
+	if (!TREEVIEW_SendExpanding(infoPtr, wineItem, TVE_EXPAND))
+	{
+	    TRACE("  TVN_ITEMEXPANDING returned TRUE, exiting...\n");
+	    return FALSE;
+	}
+
+	wineItem->state |= TVIS_EXPANDED;
+	TREEVIEW_SendExpanded(infoPtr, wineItem, TVE_EXPAND);
+	wineItem->state |= TVIS_EXPANDEDONCE;
+    }
+    else
+    {
+	/* this item has already been expanded */
+	wineItem->state |= TVIS_EXPANDED;
+    }
+
+    if (bExpandPartial)
+	FIXME("TVE_EXPANDPARTIAL not implemented\n");
+
+    TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem);
+    TREEVIEW_UpdateSubTree(infoPtr, wineItem);
+    TREEVIEW_UpdateScrollBars(infoPtr);
+
+    /* Scroll up so that as many children as possible are visible.
+     * This looses 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 rows_below = TREEVIEW_GetVisibleCount(infoPtr) - visible_pos - 1;
+
+	if (visible_pos > 0 && nChildren > rows_below)
+	{
+	    int scroll = nChildren - rows_below;
+
+	    if (scroll > visible_pos)
+		scroll = visible_pos;
+
+	    if (scroll > 0)
+	    {
+		TREEVIEW_ITEM *newFirstVisible
+		    = TREEVIEW_GetListItem(infoPtr, infoPtr->firstVisible,
+					   scroll);
+
+
+		TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE);
+	    }
+	}
+    }
+
+    TREEVIEW_Invalidate(infoPtr, NULL);
+
+    return TRUE;
+}
+
+static BOOL
+TREEVIEW_Toggle(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, BOOL bUser)
+{
+    TRACE("\n");
+
+    if (wineItem->state & TVIS_EXPANDED)
+	return TREEVIEW_Collapse(infoPtr, wineItem, FALSE, bUser);
+    else
+	return TREEVIEW_Expand(infoPtr, wineItem, FALSE, bUser);
+}
+
+static VOID
+TREEVIEW_ExpandAll(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
+{
+    TREEVIEW_Expand(infoPtr, item, FALSE, TRUE);
+
+    for (item = item->firstChild; item != NULL; item = item->nextSibling)
+    {
+	if (TREEVIEW_HasChildren(infoPtr, item))
+	    TREEVIEW_ExpandAll(infoPtr, item);
+    }
+}
+
+/* Note:If the specified item is the child of a collapsed parent item,
+   the parent's list of child items is (recursively) expanded to reveal the
+   specified item. This is mentioned for TREEVIEW_SelectItem; don't
+   know if it also applies here.
+*/
+
+static LRESULT
+TREEVIEW_ExpandMsg(TREEVIEW_INFO *infoPtr, UINT flag, HTREEITEM wineItem)
+{
+    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
+	return 0;
+
+    TRACE("For (%s) item:%d, flags %x, state:%d\n",
+	      TREEVIEW_ItemName(wineItem), flag,
+	      TREEVIEW_GetItemIndex(infoPtr, wineItem), wineItem->state);
+
+    switch (flag & TVE_TOGGLE)
+    {
+    case TVE_COLLAPSE:
+	return TREEVIEW_Collapse(infoPtr, wineItem, flag & TVE_COLLAPSERESET,
+				 FALSE);
+
+    case TVE_EXPAND:
+	return TREEVIEW_Expand(infoPtr, wineItem, flag & TVE_EXPANDPARTIAL,
+			       FALSE);
+
+    case TVE_TOGGLE:
+	return TREEVIEW_Toggle(infoPtr, wineItem, TRUE);
+
+    default:
+	return 0;
+    }
+
+#if 0
+    TRACE("Exiting, Item %p state is now %d...\n", wineItem, wineItem->state);
+#endif
+}
+
+/* Hit-Testing **********************************************************/
+
+static TREEVIEW_ITEM *
+TREEVIEW_HitTestPoint(TREEVIEW_INFO *infoPtr, POINT pt)
+{
+    TREEVIEW_ITEM *wineItem;
+    LONG row;
+
+    if (!infoPtr->firstVisible)
+	return NULL;
+
+    row = pt.y / infoPtr->uItemHeight + infoPtr->firstVisible->visibleOrder;
+
+    for (wineItem = infoPtr->firstVisible; wineItem != NULL;
+	 wineItem = TREEVIEW_GetNextListItem(infoPtr, wineItem))
+    {
+	if (row >= wineItem->visibleOrder
+	    && row < wineItem->visibleOrder + wineItem->iIntegral)
+	    break;
+    }
+
+    return wineItem;
+}
+
+static LRESULT
+TREEVIEW_HitTest(TREEVIEW_INFO *infoPtr, LPTVHITTESTINFO lpht)
+{
+    TREEVIEW_ITEM *wineItem;
+    RECT rect;
+    UINT status;
+    LONG x, y;
+
+    lpht->hItem = 0;
+    GetClientRect(infoPtr->hwnd, &rect);
+    status = 0;
+    x = lpht->pt.x;
+    y = lpht->pt.y;
+
+    if (x < rect.left)
+    {
+	status |= TVHT_TOLEFT;
+    }
+    else if (x > rect.right)
+    {
+	status |= TVHT_TORIGHT;
+    }
+
+    if (y < rect.top)
+    {
+	status |= TVHT_ABOVE;
+    }
+    else if (y > rect.bottom)
+    {
+	status |= TVHT_BELOW;
+    }
+
+    if (status)
+    {
+	lpht->flags = status;
+	return (LRESULT)(HTREEITEM)NULL;
+    }
+
+    wineItem = TREEVIEW_HitTestPoint(infoPtr, lpht->pt);
+    if (!wineItem)
+    {
+	lpht->flags = TVHT_NOWHERE;
+	return (LRESULT)(HTREEITEM)NULL;
+    }
+
+    if (x >= wineItem->textOffset + wineItem->textWidth)
+    {
+	lpht->flags = TVHT_ONITEMRIGHT;
+    }
+    else if (x >= wineItem->textOffset)
+    {
+	lpht->flags = TVHT_ONITEMLABEL;
+    }
+    else if (x >= wineItem->imageOffset)
+    {
+	lpht->flags = TVHT_ONITEMICON;
+    }
+    else if (x >= wineItem->stateOffset)
+    {
+	lpht->flags = TVHT_ONITEMSTATEICON;
+    }
+    else if (x >= wineItem->linesOffset && infoPtr->dwStyle & TVS_HASBUTTONS)
+    {
+	lpht->flags = TVHT_ONITEMBUTTON;
+    }
+    else
+    {
+	lpht->flags = TVHT_ONITEMINDENT;
+    }
+
+    lpht->hItem = wineItem;
+    TRACE("(%ld,%ld):result %x\n", lpht->pt.x, lpht->pt.y, lpht->flags);
+
+    return (LRESULT)wineItem;
+}
+
+/* Item Label Editing ***************************************************/
+
+static LRESULT
+TREEVIEW_GetEditControl(TREEVIEW_INFO *infoPtr)
+{
+    return (LRESULT)infoPtr->hwndEdit;
+}
+
+static LRESULT CALLBACK
+TREEVIEW_Edit_SubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    TREEVIEW_INFO *infoPtr;
+    BOOL bCancel = FALSE;
+
+    switch (uMsg)
+    {
+    case WM_PAINT:
+	{
+	    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_KILLFOCUS:
+    {
+	TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd));
+	if (infoPtr->bIgnoreEditKillFocus)
+	    return TRUE;
+
+	break;
+    }
+
+    case WM_GETDLGCODE:
+	return DLGC_WANTARROWS | DLGC_WANTALLKEYS;
+
+    case WM_KEYDOWN:
+	if (wParam == (WPARAM)VK_ESCAPE)
+	{
+	    bCancel = TRUE;
+	    break;
+	}
+	else if (wParam == (WPARAM)VK_RETURN)
+	{
+	    break;
+	}
+
+	/* fall through */
+    default:
+	{
+	    TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd));
+
+	    return CallWindowProcA(infoPtr->wpEditOrig, hwnd, uMsg, wParam,
+				   lParam);
+	}
+    }
+
+    /* Processing TVN_ENDLABELEDIT message could kill the focus       */
+    /* eg. Using a messagebox                                         */
+
+    infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd));
+    infoPtr->bIgnoreEditKillFocus = TRUE;
+    TREEVIEW_EndEditLabelNow(infoPtr, bCancel || !infoPtr->bLabelChanged);
+    infoPtr->bIgnoreEditKillFocus = FALSE;
+
+    return 0;
+}
+
+
+/* should handle edit control messages here */
+
+static LRESULT
+TREEVIEW_Command(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+{
+    TRACE("%x %ld\n", wParam, lParam);
+
+    switch (HIWORD(wParam))
+    {
+    case EN_UPDATE:
+	{
+	    /*
+	     * Adjust the edit window size
+	     */
+	    char buffer[1024];
+	    TREEVIEW_ITEM *editItem = infoPtr->selectedItem;
+	    HDC hdc = GetDC(infoPtr->hwndEdit);
+	    SIZE sz;
+	    int len;
+	    HFONT hFont, hOldFont = 0;
+
+	    infoPtr->bLabelChanged = TRUE;
+
+	    len = GetWindowTextA(infoPtr->hwndEdit, buffer, sizeof(buffer));
+
+	    /* Select font to get the right dimension of the string */
+	    hFont = (HFONT)SendMessageA(infoPtr->hwndEdit, WM_GETFONT, 0, 0);
+	    if (hFont != 0)
+	    {
+		hOldFont = SelectObject(hdc, hFont);
+	    }
+
+	    if (GetTextExtentPoint32A(hdc, buffer, strlen(buffer), &sz))
+	    {
+		TEXTMETRICA textMetric;
+
+		/* Add Extra spacing for the next character */
+		GetTextMetricsA(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);
+
+		SetWindowPos(infoPtr->hwndEdit,
+			     HWND_TOP,
+			     0,
+			     0,
+			     sz.cx,
+			     editItem->rect.bottom - editItem->rect.top + 3,
+			     SWP_NOMOVE | SWP_DRAWFRAME);
+	    }
+
+	    if (hFont != 0)
+	    {
+		SelectObject(hdc, hOldFont);
+	    }
+
+	    ReleaseDC(infoPtr->hwnd, hdc);
+	    break;
+	}
+
+    default:
+	return SendMessageA(GetParent(infoPtr->hwnd), WM_COMMAND, wParam, lParam);
+    }
+
+    return 0;
+}
+
+static HWND
+TREEVIEW_EditLabelA(TREEVIEW_INFO *infoPtr, HTREEITEM hItem)
+{
+    HWND hwnd = infoPtr->hwnd;
+    HWND hwndEdit;
+    SIZE sz;
+    TREEVIEW_ITEM *editItem = hItem;
+    HINSTANCE hinst = (HINSTANCE)GetWindowLongA(hwnd, GWL_HINSTANCE);
+    HDC hdc;
+    HFONT hOldFont=0;
+    TEXTMETRICA textMetric;
+
+    TRACE("%x %p\n", (unsigned)hwnd, hItem);
+    if (!TREEVIEW_ValidItem(infoPtr, editItem))
+	return NULL;
+
+    if (infoPtr->hwndEdit)
+	return infoPtr->hwndEdit;
+
+    infoPtr->bLabelChanged = FALSE;
+
+    /* Make sure that edit item is selected */
+    TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, hItem, TVC_UNKNOWN);
+    TREEVIEW_EnsureVisible(infoPtr, hItem, TRUE);
+
+    TREEVIEW_UpdateDispInfo(infoPtr, editItem, TVIF_TEXT);
+
+    hdc = GetDC(hwnd);
+    /* Select the font to get appropriate metric dimensions */
+    if (infoPtr->hFont != 0)
+    {
+	hOldFont = SelectObject(hdc, infoPtr->hFont);
+    }
+
+    /* Get string length 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);
+
+    sz.cx = max(sz.cx, textMetric.tmMaxCharWidth * 3);
+    sz.cx = min(sz.cx, infoPtr->clientWidth - editItem->textOffset + 2);
+
+    if (infoPtr->hFont != 0)
+    {
+	SelectObject(hdc, hOldFont);
+    }
+
+    ReleaseDC(hwnd, hdc);
+    hwndEdit = CreateWindowExA(WS_EX_LEFT,
+			       "EDIT",
+			       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);
+/* FIXME: (HMENU)IDTVEDIT,pcs->hInstance,0); */
+
+    infoPtr->hwndEdit = hwndEdit;
+
+    /* Get a 2D border. */
+    SetWindowLongA(hwndEdit, GWL_EXSTYLE,
+		   GetWindowLongA(hwndEdit, GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE);
+    SetWindowLongA(hwndEdit, GWL_STYLE,
+		   GetWindowLongA(hwndEdit, GWL_STYLE) | WS_BORDER);
+
+    SendMessageA(hwndEdit, WM_SETFONT,
+		 (WPARAM)TREEVIEW_FontForItem(infoPtr, editItem), FALSE);
+
+    infoPtr->wpEditOrig = (WNDPROC)SetWindowLongA(hwndEdit, GWL_WNDPROC,
+						  (DWORD)
+						  TREEVIEW_Edit_SubclassProc);
+
+    if (TREEVIEW_BeginLabelEditNotify(infoPtr, editItem))
+    {
+	DestroyWindow(hwndEdit);
+	infoPtr->hwndEdit = 0;
+	return NULL;
+    }
+
+    infoPtr->selectedItem = hItem;
+    SetWindowTextA(hwndEdit, editItem->pszText);
+    SetFocus(hwndEdit);
+    SendMessageA(hwndEdit, EM_SETSEL, 0, -1);
+    ShowWindow(hwndEdit, SW_SHOW);
+
+    return hwndEdit;
+}
+
+
+static LRESULT
+TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel)
+{
+    HWND hwnd = infoPtr->hwnd;
+    TREEVIEW_ITEM *editedItem = infoPtr->selectedItem;
+    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 = get_notifycode(infoPtr, TVN_ENDLABELEDITW);
+    tvdi.item.mask = 0;
+    tvdi.item.hItem = editedItem;
+    tvdi.item.state = editedItem->state;
+    tvdi.item.lParam = editedItem->lParam;
+
+    if (!bCancel)
+    {
+	iLength = GetWindowTextA(infoPtr->hwndEdit, tmpText, 1023);
+
+	if (iLength >= 1023)
+	{
+	    ERR("Insufficient space to retrieve new item label\n");
+	}
+
+	tvdi.item.pszText = tmpText;
+	tvdi.item.cchTextMax = iLength + 1;
+    }
+    else
+    {
+	tvdi.item.pszText = NULL;
+	tvdi.item.cchTextMax = 0;
+    }
+
+    bCommit = (BOOL)TREEVIEW_SendRealNotify(infoPtr,
+				 (WPARAM)tvdi.hdr.idFrom, (LPARAM)&tvdi);
+
+    if (!bCancel && bCommit)	/* Apply the changes */
+    {
+	if (strcmp(tmpText, editedItem->pszText) != 0)
+	{
+	    if (NULL == COMCTL32_ReAlloc(editedItem->pszText, iLength + 1))
+	    {
+		ERR("OutOfMemory, cannot allocate space for label\n");
+		DestroyWindow(infoPtr->hwndEdit);
+		infoPtr->hwndEdit = 0;
+		return FALSE;
+	    }
+	    else
+	    {
+		editedItem->cchTextMax = iLength + 1;
+		lstrcpyA(editedItem->pszText, tmpText);
+	    }
+	}
+    }
+
+    ShowWindow(infoPtr->hwndEdit, SW_HIDE);
+    DestroyWindow(infoPtr->hwndEdit);
+    infoPtr->hwndEdit = 0;
+    return TRUE;
+}
+
+static LRESULT
+TREEVIEW_HandleTimer(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+{
+    if (wParam != TV_EDIT_TIMER)
+    {
+	ERR("got unknown timer\n");
+	return 1;
+    }
+
+    KillTimer(infoPtr->hwnd, TV_EDIT_TIMER);
+    infoPtr->Timer &= ~TV_EDIT_TIMER_SET;
+
+    TREEVIEW_EditLabelA(infoPtr, infoPtr->selectedItem);
+
+    return 0;
+}
+
+
+/* Mouse Tracking/Drag **************************************************/
+
+/***************************************************************************
+ * This is quite unusual piece of code, but that's how it's implemented in
+ * Windows.
+ */
+static LRESULT
+TREEVIEW_TrackMouse(TREEVIEW_INFO *infoPtr, 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(infoPtr->hwnd);
+
+    while (1)
+    {
+	if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD))
+	{
+	    if (msg.message == WM_MOUSEMOVE)
+	    {
+		pt.x = SLOWORD(msg.lParam);
+		pt.y = SHIWORD(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(infoPtr, &pt);
+		break;
+	    }
+
+	    DispatchMessageA(&msg);
+	}
+
+	if (GetCapture() != infoPtr->hwnd)
+	    return 0;
+    }
+
+    ReleaseCapture();
+    return 0;
+}
+
+
+static LRESULT
+TREEVIEW_LButtonDoubleClick(TREEVIEW_INFO *infoPtr, LPARAM lParam)
+{
+    TREEVIEW_ITEM *wineItem;
+    TVHITTESTINFO hit;
+
+    TRACE("\n");
+    SetFocus(infoPtr->hwnd);
+
+    if (infoPtr->Timer & TV_EDIT_TIMER_SET)
+    {
+	/* If there is pending 'edit label' event - kill it now */
+	KillTimer(infoPtr->hwnd, TV_EDIT_TIMER);
+    }
+
+    hit.pt.x = SLOWORD(lParam);
+    hit.pt.y = SHIWORD(lParam);
+
+    wineItem = (TREEVIEW_ITEM *)TREEVIEW_HitTest(infoPtr, &hit);
+    if (!wineItem)
+	return 0;
+    TRACE("item %d\n", TREEVIEW_GetItemIndex(infoPtr, wineItem));
+
+    if (TREEVIEW_SendSimpleNotify(infoPtr, NM_DBLCLK) == FALSE)
+    {				/* FIXME! */
+	switch (hit.flags)
+	{
+	case TVHT_ONITEMRIGHT:
+	    /* FIXME: we should not have sent NM_DBLCLK in this case. */
+	    break;
+
+	case TVHT_ONITEMINDENT:
+	    if (!(infoPtr->dwStyle & TVS_HASLINES))
+	    {
+		break;
+	    }
+	    else
+	    {
+		int level = hit.pt.x / infoPtr->uIndent;
+		if (!(infoPtr->dwStyle & TVS_LINESATROOT)) level++;
+
+		while (wineItem->iLevel > level)
+		{
+		    wineItem = wineItem->parent;
+		}
+
+		/* fall through */
+	    }
+
+	case TVHT_ONITEMLABEL:
+	case TVHT_ONITEMICON:
+	case TVHT_ONITEMBUTTON:
+	    TREEVIEW_Toggle(infoPtr, wineItem, TRUE);
+	    break;
+
+	case TVHT_ONITEMSTATEICON:
+	   if (infoPtr->dwStyle & TVS_CHECKBOXES)
+	       TREEVIEW_ToggleItemState(infoPtr, wineItem);
+	   else
+	       TREEVIEW_Toggle(infoPtr, wineItem, TRUE);
+	   break;
+	}
+    }
+    return TRUE;
+}
+
+
+static LRESULT
+TREEVIEW_LButtonDown(TREEVIEW_INFO *infoPtr, LPARAM lParam)
+{
+    HWND hwnd = infoPtr->hwnd;
+    TVHITTESTINFO ht;
+    BOOL bTrack;
+    HTREEITEM tempItem;
+
+    /* 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)
+    {
+	SetFocus(hwnd);
+	return 0;
+    }
+
+    ht.pt.x = SLOWORD(lParam);
+    ht.pt.y = SHIWORD(lParam);
+
+    TREEVIEW_HitTest(infoPtr, &ht);
+    TRACE("item %d\n", TREEVIEW_GetItemIndex(infoPtr, ht.hItem));
+
+    /* update focusedItem and redraw both items */
+    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);
+    }
+
+    bTrack = (ht.flags & TVHT_ONITEM)
+	&& !(infoPtr->dwStyle & TVS_DISABLEDRAGDROP);
+
+    /* Send NM_CLICK right away */
+    if (!bTrack)
+	if (TREEVIEW_SendSimpleNotify(infoPtr, NM_CLICK))
+	    goto setfocus;
+
+    if (ht.flags & TVHT_ONITEMBUTTON)
+    {
+	TREEVIEW_Toggle(infoPtr, ht.hItem, TRUE);
+	goto setfocus;
+    }
+    else if (bTrack)
+    {   /* if TREEVIEW_TrackMouse == 1 dragging occurred and the cursor left the dragged item's rectangle */
+	if (TREEVIEW_TrackMouse(infoPtr, ht.pt))
+	{
+	    TREEVIEW_SendTreeviewDnDNotify(infoPtr, TVN_BEGINDRAGW, ht.hItem, ht.pt);
+	    infoPtr->dropItem = ht.hItem;
+
+            /* clean up focusedItem as we dragged and won't select this item */
+            if(infoPtr->focusedItem)
+            {
+                /* refresh the item that was focused */
+                tempItem = infoPtr->focusedItem;
+                infoPtr->focusedItem = 0;
+                InvalidateRect(infoPtr->hwnd, &tempItem->rect, TRUE);
+
+                /* refresh the selected item to return the filled background */
+                InvalidateRect(infoPtr->hwnd, &(infoPtr->selectedItem->rect), TRUE);
+            }
+
+	    return 0;
+        }
+    }
+
+    if (bTrack && TREEVIEW_SendSimpleNotify(infoPtr, NM_CLICK))
+        goto setfocus;
+
+    /*
+     * If the style allows editing and the node is already selected
+     * and the click occurred on the item label...
+     */
+    if ((infoPtr->dwStyle & TVS_EDITLABELS) &&
+	        (ht.flags & TVHT_ONITEMLABEL) && (infoPtr->selectedItem == ht.hItem))
+    {
+	if (infoPtr->Timer & TV_EDIT_TIMER_SET)
+	    KillTimer(hwnd, TV_EDIT_TIMER);
+
+	SetTimer(hwnd, TV_EDIT_TIMER, GetDoubleClickTime(), 0);
+	infoPtr->Timer |= TV_EDIT_TIMER_SET;
+    }
+    else if (ht.flags & TVHT_ONITEM) /* select the item if the hit was inside of the icon or text */
+    {
+        /*
+         * if we are TVS_SINGLEEXPAND then we want this single click to
+         * do a bunch of things.
+         */
+        if((infoPtr->dwStyle & TVS_SINGLEEXPAND) &&
+          (infoPtr->hwndEdit == 0))
+        {
+            TREEVIEW_ITEM *SelItem;
+
+            /*
+             * Send the notification
+             */
+            TREEVIEW_SendTreeviewNotify(infoPtr, TVN_SINGLEEXPAND, TVC_UNKNOWN, TVIF_HANDLE | TVIF_PARAM, ht.hItem, 0);
+
+            /*
+             * Close the previous selection all the way to the root
+             * as long as the new selection is not a child
+             */
+            if((infoPtr->selectedItem)
+                && (infoPtr->selectedItem != ht.hItem))
+            {
+                BOOL closeit = TRUE;
+                SelItem = ht.hItem;
+
+                /* determine if the hitItem is a child of the currently selected item */
+                while(closeit && SelItem && TREEVIEW_ValidItem(infoPtr, SelItem) && (SelItem != infoPtr->root))
+                {
+                    closeit = (SelItem != infoPtr->selectedItem);
+                    SelItem = SelItem->parent;
+                }
+
+                if(closeit)
+                {
+                    if(TREEVIEW_ValidItem(infoPtr, infoPtr->selectedItem))
+                        SelItem = infoPtr->selectedItem;
+
+                    while(SelItem && (SelItem != ht.hItem) && TREEVIEW_ValidItem(infoPtr, SelItem) && (SelItem != infoPtr->root))
+                    {
+                        TREEVIEW_Collapse(infoPtr, SelItem, FALSE, FALSE);
+                        SelItem = SelItem->parent;
+                    }
+                }
+            }
+
+            /*
+             * Expand the current item
+             */
+            TREEVIEW_Expand(infoPtr, ht.hItem, TVE_TOGGLE, FALSE);
+        }
+
+        /* Select the current item */
+        TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, ht.hItem, TVC_BYMOUSE);
+    }
+    else if (ht.flags & TVHT_ONITEMSTATEICON)
+    {
+	/* TVS_CHECKBOXES requires us to toggle the current state */
+	if (infoPtr->dwStyle & TVS_CHECKBOXES)
+	    TREEVIEW_ToggleItemState(infoPtr, ht.hItem);
+    }
+
+  setfocus:
+    SetFocus(hwnd);
+    return 0;
+}
+
+
+static LRESULT
+TREEVIEW_RButtonDown(TREEVIEW_INFO *infoPtr, LPARAM lParam)
+{
+    TVHITTESTINFO ht;
+
+    if (infoPtr->hwndEdit)
+    {
+	SetFocus(infoPtr->hwnd);
+	return 0;
+    }
+
+    ht.pt.x = SLOWORD(lParam);
+    ht.pt.y = SHIWORD(lParam);
+
+    TREEVIEW_HitTest(infoPtr, &ht);
+
+    if (TREEVIEW_TrackMouse(infoPtr, ht.pt))
+    {
+	if (ht.hItem)
+	{
+	    TREEVIEW_SendTreeviewDnDNotify(infoPtr, TVN_BEGINRDRAGW, ht.hItem, ht.pt);
+	    infoPtr->dropItem = ht.hItem;
+	}
+    }
+    else
+    {
+	SetFocus(infoPtr->hwnd);
+	TREEVIEW_SendSimpleNotify(infoPtr, NM_RCLICK);
+    }
+
+    return 0;
+}
+
+static LRESULT
+TREEVIEW_RButtonUp(TREEVIEW_INFO *infoPtr, LPPOINT pPt)
+{
+    return 0;
+}
+
+
+static LRESULT
+TREEVIEW_CreateDragImage(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+{
+    TREEVIEW_ITEM *dragItem = (HTREEITEM)lParam;
+    INT cx, cy;
+    HDC hdc, htopdc;
+    HWND hwtop;
+    HBITMAP hbmp, hOldbmp;
+    SIZE size;
+    RECT rc;
+    HFONT hOldFont;
+
+    TRACE("\n");
+
+    if (!(infoPtr->himlNormal))
+	return 0;
+
+    if (!dragItem || !TREEVIEW_ValidItem(infoPtr, dragItem))
+	return 0;
+
+    TREEVIEW_UpdateDispInfo(infoPtr, dragItem, TVIF_TEXT);
+
+    hwtop = GetDesktopWindow();
+    htopdc = GetDC(hwtop);
+    hdc = CreateCompatibleDC(htopdc);
+
+    hOldFont = SelectObject(hdc, infoPtr->hFont);
+    GetTextExtentPoint32A(hdc, dragItem->pszText, lstrlenA(dragItem->pszText),
+			  &size);
+    TRACE("%ld %ld %s %d\n", size.cx, size.cy, dragItem->pszText,
+	  lstrlenA(dragItem->pszText));
+    hbmp = CreateCompatibleBitmap(htopdc, size.cx, size.cy);
+    hOldbmp = SelectObject(hdc, hbmp);
+
+    ImageList_GetIconSize(infoPtr->himlNormal, &cx, &cy);
+    size.cx += cx;
+    if (cy > size.cy)
+	size.cy = cy;
+
+    infoPtr->dragList = ImageList_Create(size.cx, size.cy, ILC_COLOR, 10, 10);
+    ImageList_Draw(infoPtr->himlNormal, dragItem->iImage, hdc, 0, 0,
+		   ILD_NORMAL);
+
+/*
+ ImageList_GetImageInfo (infoPtr->himlNormal, dragItem->hItem, &iminfo);
+ ImageList_AddMasked (infoPtr->dragList, iminfo.hbmImage, CLR_DEFAULT);
+*/
+
+/* draw item text */
+
+    SetRect(&rc, cx, 0, size.cx, size.cy);
+    DrawTextA(hdc, dragItem->pszText, lstrlenA(dragItem->pszText), &rc,
+	      DT_LEFT);
+    SelectObject(hdc, hOldFont);
+    SelectObject(hdc, hOldbmp);
+
+    ImageList_Add(infoPtr->dragList, hbmp, 0);
+
+    DeleteDC(hdc);
+    DeleteObject(hbmp);
+    ReleaseDC(hwtop, htopdc);
+
+    return (LRESULT)infoPtr->dragList;
+}
+
+/* Selection ************************************************************/
+
+static LRESULT
+TREEVIEW_DoSelectItem(TREEVIEW_INFO *infoPtr, INT action, HTREEITEM newSelect,
+		      INT cause)
+{
+    TREEVIEW_ITEM *prevSelect;
+    RECT rcFocused;
+
+    assert(newSelect == NULL || TREEVIEW_ValidItem(infoPtr, newSelect));
+
+    TRACE("Entering item %p (%s), flag %x, cause %x, state %d\n",
+	  newSelect, TREEVIEW_ItemName(newSelect), action, cause,
+	  newSelect ? newSelect->state : 0);
+
+    /* 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);
+    }
+
+    switch (action)
+    {
+    case TVGN_CARET:
+	prevSelect = infoPtr->selectedItem;
+
+	if (prevSelect == newSelect)
+	    return FALSE;
+
+	if (TREEVIEW_SendTreeviewNotify(infoPtr,
+					TVN_SELCHANGINGW,
+					cause,
+					TVIF_HANDLE | TVIF_STATE | TVIF_PARAM,
+					prevSelect,
+					newSelect))
+	    return FALSE;
+
+	if (prevSelect)
+	    prevSelect->state &= ~TVIS_SELECTED;
+	if (newSelect)
+	    newSelect->state |= TVIS_SELECTED;
+
+	infoPtr->selectedItem = newSelect;
+
+	TREEVIEW_EnsureVisible(infoPtr, infoPtr->selectedItem, FALSE);
+
+	TREEVIEW_SendTreeviewNotify(infoPtr,
+				    TVN_SELCHANGEDW,
+				    cause,
+				    TVIF_HANDLE | TVIF_STATE | TVIF_PARAM,
+				    prevSelect,
+				    newSelect);
+	TREEVIEW_Invalidate(infoPtr, prevSelect);
+	TREEVIEW_Invalidate(infoPtr, newSelect);
+	break;
+
+    case TVGN_DROPHILITE:
+	prevSelect = infoPtr->dropItem;
+
+	if (prevSelect)
+	    prevSelect->state &= ~TVIS_DROPHILITED;
+
+	infoPtr->dropItem = newSelect;
+
+	if (newSelect)
+	    newSelect->state |= TVIS_DROPHILITED;
+
+	TREEVIEW_Invalidate(infoPtr, prevSelect);
+	TREEVIEW_Invalidate(infoPtr, newSelect);
+	break;
+
+    case TVGN_FIRSTVISIBLE:
+	TREEVIEW_EnsureVisible(infoPtr, newSelect, FALSE);
+	TREEVIEW_SetFirstVisible(infoPtr, newSelect, TRUE);
+	TREEVIEW_Invalidate(infoPtr, NULL);
+	break;
+    }
+
+    TRACE("Leaving state %d\n", newSelect ? newSelect->state : 0);
+    return TRUE;
+}
+
+/* FIXME: handle NM_KILLFOCUS etc */
+static LRESULT
+TREEVIEW_SelectItem(TREEVIEW_INFO *infoPtr, INT wParam, HTREEITEM item)
+{
+    if (item != NULL && !TREEVIEW_ValidItem(infoPtr, item))
+	return FALSE;
+
+    TRACE("%p (%s) %d\n", item, TREEVIEW_ItemName(item), wParam);
+
+    if (!TREEVIEW_DoSelectItem(infoPtr, wParam, item, TVC_UNKNOWN))
+	return FALSE;
+
+    return TRUE;
+}
+
+/*************************************************************************
+ *		TREEVIEW_ProcessLetterKeys
+ *
+ *  Processes keyboard messages generated by pressing the letter keys
+ *  on the keyboard.
+ *  What this does is perform a case insensitive search from the
+ *  current position with the following quirks:
+ *  - If two chars or more are pressed in quick succession we search
+ *    for the corresponding string (e.g. 'abc').
+ *  - If there is a delay we wipe away the current search string and
+ *    restart with just that char.
+ *  - If the user keeps pressing the same character, whether slowly or
+ *    fast, so that the search string is entirely composed of this
+ *    character ('aaaaa' for instance), then we search for first item
+ *    that starting with that character.
+ *  - If the user types the above character in quick succession, then
+ *    we must also search for the corresponding string ('aaaaa'), and
+ *    go to that string if there is a match.
+ *
+ * RETURNS
+ *
+ *  Zero.
+ *
+ * BUGS
+ *
+ *  - The current implementation has a list of characters it will
+ *    accept and it ignores averything 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.
+ *  - We don't sound a beep when the search fails.
+ *  - The search should start from the focused item, not from the selected
+ *    item. One reason for this is to allow for multiple selections in trees.
+ *    But currently infoPtr->focusedItem does not seem very usable.
+ *
+ * SEE ALSO
+ *
+ *  TREEVIEW_ProcessLetterKeys
+ */
+static INT TREEVIEW_ProcessLetterKeys(
+    HWND hwnd, /* handle to the window */
+    WPARAM charCode, /* the character code, the actual character */
+    LPARAM keyData /* key data */
+    )
+{
+    TREEVIEW_INFO *infoPtr;
+    HTREEITEM nItem;
+    HTREEITEM endidx,idx;
+    TVITEMEXA item;
+    CHAR buffer[MAX_PATH];
+    DWORD timestamp,elapsed;
+
+    /* simple parameter checking */
+    if (!hwnd || !charCode || !keyData)
+        return 0;
+
+    infoPtr=(TREEVIEW_INFO*)GetWindowLongA(hwnd, 0);
+    if (!infoPtr)
+        return 0;
+
+    /* only allow the valid WM_CHARs through */
+    if (!isalnum(charCode) &&
+        charCode != '.' && charCode != '`' && charCode != '!' &&
+        charCode != '@' && charCode != '#' && charCode != '$' &&
+        charCode != '%' && charCode != '^' && charCode != '&' &&
+        charCode != '*' && charCode != '(' && charCode != ')' &&
+        charCode != '-' && charCode != '_' && charCode != '+' &&
+        charCode != '=' && charCode != '\\'&& charCode != ']' &&
+        charCode != '}' && charCode != '[' && charCode != '{' &&
+        charCode != '/' && charCode != '?' && charCode != '>' &&
+        charCode != '<' && charCode != ',' && charCode != '~')
+        return 0;
+
+    /* compute how much time elapsed since last keypress */
+    timestamp = GetTickCount();
+    if (timestamp > infoPtr->lastKeyPressTimestamp) {
+        elapsed=timestamp-infoPtr->lastKeyPressTimestamp;
+    } else {
+        elapsed=infoPtr->lastKeyPressTimestamp-timestamp;
+    }
+
+    /* update the search parameters */
+    infoPtr->lastKeyPressTimestamp=timestamp;
+    if (elapsed < KEY_DELAY) {
+        if (infoPtr->nSearchParamLength < sizeof(infoPtr->szSearchParam)) {
+            infoPtr->szSearchParam[infoPtr->nSearchParamLength++]=charCode;
+        }
+        if (infoPtr->charCode != charCode) {
+            infoPtr->charCode=charCode=0;
+        }
+    } else {
+        infoPtr->charCode=charCode;
+        infoPtr->szSearchParam[0]=charCode;
+        infoPtr->nSearchParamLength=1;
+        /* Redundant with the 1 char string */
+        charCode=0;
+    }
+
+    /* and search from the current position */
+    nItem=NULL;
+    if (infoPtr->selectedItem != NULL) {
+        endidx=infoPtr->selectedItem;
+        /* if looking for single character match,
+         * then we must always move forward
+         */
+        if (infoPtr->nSearchParamLength == 1)
+            idx=TREEVIEW_GetNextListItem(infoPtr,endidx);
+        else
+            idx=endidx;
+    } else {
+        endidx=NULL;
+        idx=infoPtr->root->firstChild;
+    }
+    do {
+        if (idx == NULL) {
+            if (endidx == NULL)
+                break;
+            idx=infoPtr->root->firstChild;
+        }
+
+        /* get item */
+        ZeroMemory(&item, sizeof(item));
+        item.mask = TVIF_TEXT;
+        item.hItem = idx;
+        item.pszText = buffer;
+        item.cchTextMax = sizeof(buffer);
+        TREEVIEW_GetItemA( infoPtr, &item );
+
+        /* check for a match */
+        if (strncasecmp(item.pszText,infoPtr->szSearchParam,infoPtr->nSearchParamLength) == 0) {
+            nItem=idx;
+            break;
+        } else if ( (charCode != 0) && (nItem == NULL) &&
+                    (nItem != infoPtr->selectedItem) &&
+                    (strncasecmp(item.pszText,infoPtr->szSearchParam,1) == 0) ) {
+            /* This would work but we must keep looking for a longer match */
+            nItem=idx;
+        }
+        idx=TREEVIEW_GetNextListItem(infoPtr,idx);
+    } while (idx != endidx);
+
+    if (nItem != NULL) {
+        if (TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, nItem, TVC_BYKEYBOARD)) {
+            TREEVIEW_EnsureVisible(infoPtr, nItem, FALSE);
+        }
+    }
+
+    return 0;
+}
+
+/* Scrolling ************************************************************/
+
+static LRESULT
+TREEVIEW_EnsureVisible(TREEVIEW_INFO *infoPtr, HTREEITEM item, BOOL bHScroll)
+{
+    HTREEITEM newFirstVisible = NULL;
+    int visible_pos;
+
+    if (!TREEVIEW_ValidItem(infoPtr, item))
+	return FALSE;
+
+    if (!ISVISIBLE(item))
+    {
+	/* Expand parents as necessary. */
+	HTREEITEM parent;
+
+        /* see if we are trying to ensure that root is vislble */
+        if((item != infoPtr->root) && TREEVIEW_ValidItem(infoPtr, item))
+          parent = item->parent;
+        else
+          parent = item; /* this item is the topmost item */
+
+	while (parent != infoPtr->root)
+	{
+	    if (!(parent->state & TVIS_EXPANDED))
+		TREEVIEW_Expand(infoPtr, parent, FALSE, FALSE);
+
+	    parent = parent->parent;
+	}
+    }
+
+    TRACE("%p (%s) %ld - %ld\n", item, TREEVIEW_ItemName(item), item->visibleOrder,
+	  infoPtr->firstVisible->visibleOrder);
+
+    visible_pos = item->visibleOrder - infoPtr->firstVisible->visibleOrder;
+
+    if (visible_pos < 0)
+    {
+	/* item is before the start of the list: put it at the top. */
+	newFirstVisible = item;
+    }
+    else if (visible_pos >= TREEVIEW_GetVisibleCount(infoPtr)
+	     /* Sometimes, before we are displayed, GVC is 0, causing us to
+	      * spuriously scroll up. */
+	     && visible_pos > 0)
+    {
+	/* item is past the end of the list. */
+	int scroll = visible_pos - TREEVIEW_GetVisibleCount(infoPtr);
+
+	newFirstVisible = TREEVIEW_GetListItem(infoPtr, infoPtr->firstVisible,
+					       scroll + 1);
+    }
+
+    if (bHScroll)
+    {
+        /* Scroll window so item's text is visible as much as possible */
+        /* Calculation of amount of extra space is taken from EditLabel code */
+        INT pos, x;
+        TEXTMETRICA textMetric;
+        HDC hdc = GetWindowDC(infoPtr->hwnd);
+
+        x = item->textWidth;
+
+        GetTextMetricsA(hdc, &textMetric);
+        ReleaseDC(infoPtr->hwnd, hdc);
+
+        x += (textMetric.tmMaxCharWidth * 2);
+        x = max(x, textMetric.tmMaxCharWidth * 3);
+
+	if (item->textOffset < 0)
+	   pos = item->textOffset;
+	else if (item->textOffset + x > infoPtr->clientWidth)
+        {
+           if (x > infoPtr->clientWidth)
+              pos = item->textOffset;
+           else
+              pos = item->textOffset + x - infoPtr->clientWidth;
+        }
+        else
+           pos = 0;
+
+	TREEVIEW_HScroll(infoPtr, MAKEWPARAM(SB_THUMBPOSITION, infoPtr->scrollX + pos));
+    }
+
+    if (newFirstVisible != NULL && newFirstVisible != infoPtr->firstVisible)
+    {
+	TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE);
+
+	return TRUE;
+    }
+
+    return FALSE;
+}
+
+static VOID
+TREEVIEW_SetFirstVisible(TREEVIEW_INFO *infoPtr,
+                         TREEVIEW_ITEM *newFirstVisible,
+                         BOOL bUpdateScrollPos)
+{
+    int gap_size;
+
+    TRACE("%p: %s\n", newFirstVisible, TREEVIEW_ItemName(newFirstVisible));
+
+    if (newFirstVisible != NULL)
+    {
+	/* Prevent an empty gap from appearing at the bottom... */
+	gap_size = TREEVIEW_GetVisibleCount(infoPtr)
+	    - infoPtr->maxVisibleOrder + newFirstVisible->visibleOrder;
+
+	if (gap_size > 0)
+	{
+	    newFirstVisible = TREEVIEW_GetListItem(infoPtr, newFirstVisible,
+						   -gap_size);
+
+	    /* ... unless we just don't have enough items. */
+	    if (newFirstVisible == NULL)
+		newFirstVisible = infoPtr->root->firstChild;
+	}
+    }
+
+    if (infoPtr->firstVisible != newFirstVisible)
+    {
+	if (infoPtr->firstVisible == NULL || newFirstVisible == NULL)
+	{
+	    infoPtr->firstVisible = newFirstVisible;
+	    TREEVIEW_Invalidate(infoPtr, NULL);
+	}
+	else
+	{
+	    TREEVIEW_ITEM *item;
+	    int scroll = infoPtr->uItemHeight *
+	                 (infoPtr->firstVisible->visibleOrder
+	                  - newFirstVisible->visibleOrder);
+
+	    infoPtr->firstVisible = newFirstVisible;
+
+	    for (item = infoPtr->root->firstChild; item != NULL;
+	         item = TREEVIEW_GetNextListItem(infoPtr, item))
+	    {
+	       item->rect.top += scroll;
+	       item->rect.bottom += scroll;
+	    }
+
+	    if (bUpdateScrollPos)
+		SetScrollPos(infoPtr->hwnd, SB_VERT,
+		              newFirstVisible->visibleOrder, TRUE);
+
+	    ScrollWindow(infoPtr->hwnd, 0, scroll, NULL, NULL);
+	    UpdateWindow(infoPtr->hwnd);
+	}
+    }
+}
+
+/************************************************************************
+ * VScroll is always in units of visible items. i.e. we always have a
+ * visible item aligned to the top of the control. (Unless we have no
+ * items at all.)
+ */
+static LRESULT
+TREEVIEW_VScroll(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+{
+    TREEVIEW_ITEM *oldFirstVisible = infoPtr->firstVisible;
+    TREEVIEW_ITEM *newFirstVisible = NULL;
+
+    int nScrollCode = LOWORD(wParam);
+
+    TRACE("wp %x\n", wParam);
+
+    if (!(infoPtr->uInternalStatus & TV_VSCROLL))
+	return 0;
+
+    if (infoPtr->hwndEdit)
+	SetFocus(infoPtr->hwnd);
+
+    if (!oldFirstVisible)
+    {
+	assert(infoPtr->root->firstChild == NULL);
+	return 0;
+    }
+
+    switch (nScrollCode)
+    {
+    case SB_TOP:
+	newFirstVisible = infoPtr->root->firstChild;
+	break;
+
+    case SB_BOTTOM:
+	newFirstVisible = TREEVIEW_GetLastListItem(infoPtr, infoPtr->root);
+	break;
+
+    case SB_LINEUP:
+	newFirstVisible = TREEVIEW_GetPrevListItem(infoPtr, oldFirstVisible);
+	break;
+
+    case SB_LINEDOWN:
+	newFirstVisible = TREEVIEW_GetNextListItem(infoPtr, oldFirstVisible);
+	break;
+
+    case SB_PAGEUP:
+	newFirstVisible = TREEVIEW_GetListItem(infoPtr, oldFirstVisible,
+					       -max(1, TREEVIEW_GetVisibleCount(infoPtr)));
+	break;
+
+    case SB_PAGEDOWN:
+	newFirstVisible = TREEVIEW_GetListItem(infoPtr, oldFirstVisible,
+					       max(1, TREEVIEW_GetVisibleCount(infoPtr)));
+	break;
+
+    case SB_THUMBTRACK:
+    case SB_THUMBPOSITION:
+	newFirstVisible = TREEVIEW_GetListItem(infoPtr,
+					       infoPtr->root->firstChild,
+					       (LONG)(SHORT)HIWORD(wParam));
+	break;
+
+    case SB_ENDSCROLL:
+	return 0;
+    }
+
+    if (newFirstVisible != NULL)
+    {
+	if (newFirstVisible != oldFirstVisible)
+	    TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible,
+	                          nScrollCode != SB_THUMBTRACK);
+	else if (nScrollCode == SB_THUMBPOSITION)
+	    SetScrollPos(infoPtr->hwnd, SB_VERT,
+	                 newFirstVisible->visibleOrder, TRUE);
+    }
+
+    return 0;
+}
+
+static LRESULT
+TREEVIEW_HScroll(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+{
+    int maxWidth;
+    int scrollX = infoPtr->scrollX;
+    int nScrollCode = LOWORD(wParam);
+
+    TRACE("wp %x\n", wParam);
+
+    if (!(infoPtr->uInternalStatus & TV_HSCROLL))
+	return FALSE;
+
+    if (infoPtr->hwndEdit)
+	SetFocus(infoPtr->hwnd);
+
+    maxWidth = infoPtr->treeWidth - infoPtr->clientWidth;
+    /* shall never occur */
+    if (maxWidth <= 0)
+    {
+       scrollX = 0;
+       goto scroll;
+    }
+
+    switch (nScrollCode)
+    {
+    case SB_LINELEFT:
+	scrollX -= infoPtr->uItemHeight;
+	break;
+    case SB_LINERIGHT:
+	scrollX += infoPtr->uItemHeight;
+	break;
+    case SB_PAGELEFT:
+	scrollX -= infoPtr->clientWidth;
+	break;
+    case SB_PAGERIGHT:
+	scrollX += infoPtr->clientWidth;
+	break;
+
+    case SB_THUMBTRACK:
+    case SB_THUMBPOSITION:
+	scrollX = (int)(SHORT)HIWORD(wParam);
+	break;
+
+    case SB_ENDSCROLL:
+       return 0;
+    }
+
+    if (scrollX > maxWidth)
+        scrollX = maxWidth;
+    else if (scrollX < 0)
+        scrollX = 0;
+
+scroll:
+    if (scrollX != infoPtr->scrollX)
+    {
+        TREEVIEW_ITEM *item;
+        LONG scroll_pixels = infoPtr->scrollX - scrollX;
+
+        for (item = infoPtr->root->firstChild; item != NULL;
+             item = TREEVIEW_GetNextListItem(infoPtr, item))
+        {
+           item->linesOffset += scroll_pixels;
+           item->stateOffset += scroll_pixels;
+           item->imageOffset += scroll_pixels;
+           item->textOffset  += scroll_pixels;
+        }
+
+	ScrollWindow(infoPtr->hwnd, scroll_pixels, 0, NULL, NULL);
+	infoPtr->scrollX = scrollX;
+	UpdateWindow(infoPtr->hwnd);
+    }
+
+    if (nScrollCode != SB_THUMBTRACK)
+       SetScrollPos(infoPtr->hwnd, SB_HORZ, scrollX, TRUE);
+
+    return 0;
+}
+
+static LRESULT
+TREEVIEW_MouseWheel(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+{
+    short gcWheelDelta;
+    UINT pulScrollLines = 3;
+
+    if (infoPtr->firstVisible == NULL)
+	return TRUE;
+
+    SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &pulScrollLines, 0);
+
+    gcWheelDelta = -(short)HIWORD(wParam);
+    pulScrollLines *= (gcWheelDelta / WHEEL_DELTA);
+
+    if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
+    {
+	int newDy = infoPtr->firstVisible->visibleOrder + pulScrollLines;
+	int maxDy = infoPtr->maxVisibleOrder;
+
+	if (newDy > maxDy)
+	    newDy = maxDy;
+
+	if (newDy < 0)
+	    newDy = 0;
+
+	TREEVIEW_VScroll(infoPtr, MAKEWPARAM(SB_THUMBPOSITION, newDy));
+    }
+    return TRUE;
+}
+
+/* Create/Destroy *******************************************************/
+
+static LRESULT
+TREEVIEW_Create(HWND hwnd)
+{
+    RECT rcClient;
+    TREEVIEW_INFO *infoPtr;
+
+    TRACE("wnd %p, style %lx\n", hwnd, GetWindowLongA(hwnd, GWL_STYLE));
+
+    infoPtr = (TREEVIEW_INFO *)COMCTL32_Alloc(sizeof(TREEVIEW_INFO));
+
+    if (infoPtr == NULL)
+    {
+	ERR("could not allocate info memory!\n");
+	return 0;
+    }
+
+    SetWindowLongA(hwnd, 0, (DWORD)infoPtr);
+
+    infoPtr->hwnd = hwnd;
+    infoPtr->dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
+    infoPtr->uInternalStatus = 0;
+    infoPtr->Timer = 0;
+    infoPtr->uNumItems = 0;
+    infoPtr->cdmode = 0;
+    infoPtr->uScrollTime = 300;	/* milliseconds */
+    infoPtr->bRedraw = TRUE;
+
+    GetClientRect(hwnd, &rcClient);
+
+    /* No scroll bars yet. */
+    infoPtr->clientWidth = rcClient.right;
+    infoPtr->clientHeight = rcClient.bottom;
+
+    infoPtr->treeWidth = 0;
+    infoPtr->treeHeight = 0;
+
+    infoPtr->uIndent = 19;
+    infoPtr->selectedItem = 0;
+    infoPtr->focusedItem = 0;
+    /* hotItem? */
+    infoPtr->firstVisible = 0;
+    infoPtr->maxVisibleOrder = 0;
+    infoPtr->dropItem = 0;
+    infoPtr->insertMarkItem = 0;
+    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);
+
+    /* hwndToolTip */
+
+    infoPtr->hwndEdit = 0;
+    infoPtr->wpEditOrig = NULL;
+    infoPtr->bIgnoreEditKillFocus = FALSE;
+    infoPtr->bLabelChanged = FALSE;
+
+    infoPtr->himlNormal = NULL;
+    infoPtr->himlState = NULL;
+    infoPtr->normalImageWidth = 0;
+    infoPtr->normalImageHeight = 0;
+    infoPtr->stateImageWidth = 0;
+    infoPtr->stateImageHeight = 0;
+
+    infoPtr->items = DPA_Create(16);
+
+    infoPtr->hFont = GetStockObject(DEFAULT_GUI_FONT);
+    infoPtr->hBoldFont = TREEVIEW_CreateBoldFont(infoPtr->hFont);
+
+    infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr);
+
+    infoPtr->root = TREEVIEW_AllocateItem(infoPtr);
+    infoPtr->root->state = TVIS_EXPANDED;
+    infoPtr->root->iLevel = -1;
+    infoPtr->root->visibleOrder = -1;
+
+    infoPtr->hwndNotify = GetParent(hwnd);
+#if 0
+    infoPtr->bTransparent = ( GetWindowLongA( hwnd, GWL_STYLE) & TBSTYLE_FLAT);
+#endif
+
+    infoPtr->hwndToolTip = 0;
+
+    infoPtr->bUnicode = IsWindowUnicode (hwnd);
+
+    /* Determine what type of notify should be issued */
+    /* sets infoPtr->bNtfUnicode */
+    TREEVIEW_NotifyFormat(infoPtr, infoPtr->hwndNotify, NF_REQUERY);
+
+    if (!(infoPtr->dwStyle & TVS_NOTOOLTIPS))
+	infoPtr->hwndToolTip = COMCTL32_CreateToolTip(hwnd);
+
+    if (infoPtr->dwStyle & TVS_CHECKBOXES)
+    {
+	RECT rc;
+	HBITMAP hbm, hbmOld;
+	HDC hdc;
+	int nIndex;
+
+	infoPtr->himlState =
+	    ImageList_Create(16, 16, ILC_COLOR | ILC_MASK, 3, 0);
+
+	hdc = CreateCompatibleDC(0);
+	hbm = CreateCompatibleBitmap(hdc, 48, 16);
+	hbmOld = SelectObject(hdc, hbm);
+
+	rc.left  = 0;   rc.top    = 0;
+	rc.right = 48;  rc.bottom = 16;
+	FillRect(hdc, &rc, (HBRUSH)(COLOR_WINDOW+1));
+
+	rc.left  = 18;   rc.top    = 2;
+	rc.right = 30;   rc.bottom = 14;
+	DrawFrameControl(hdc, &rc, DFC_BUTTON,
+	                  DFCS_BUTTONCHECK|DFCS_FLAT);
+
+	rc.left  = 34;   rc.right  = 46;
+	DrawFrameControl(hdc, &rc, DFC_BUTTON,
+	                  DFCS_BUTTONCHECK|DFCS_FLAT|DFCS_CHECKED);
+
+	nIndex = ImageList_AddMasked(infoPtr->himlState, hbm,
+	                              GetSysColor(COLOR_WINDOW));
+	TRACE("chckbox index %d\n", nIndex);
+	SelectObject(hdc, hbmOld);
+	DeleteObject(hbm);
+	DeleteDC(hdc);
+
+	infoPtr->stateImageWidth = 16;
+	infoPtr->stateImageHeight = 16;
+    }
+    return 0;
+}
+
+
+static LRESULT
+TREEVIEW_Destroy(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("\n");
+
+    TREEVIEW_RemoveTree(infoPtr);
+
+    /* tool tip is automatically destroyed: we are its owner */
+
+    /* Restore original wndproc */
+    if (infoPtr->hwndEdit)
+	SetWindowLongA(infoPtr->hwndEdit, GWL_WNDPROC,
+		       (LONG)infoPtr->wpEditOrig);
+
+    /* Deassociate treeview from the window before doing anything drastic. */
+    SetWindowLongA(infoPtr->hwnd, 0, (LONG)NULL);
+
+    DeleteObject(infoPtr->hBoldFont);
+    COMCTL32_Free(infoPtr);
+
+    return 0;
+}
+
+/* Miscellaneous Messages ***********************************************/
+
+static LRESULT
+TREEVIEW_ScrollKeyDown(TREEVIEW_INFO *infoPtr, WPARAM key)
+{
+    static const struct
+    {
+	unsigned char code;
+    }
+    scroll[] =
+    {
+#define SCROLL_ENTRY(dir, code) { ((dir) << 7) | (code) }
+	SCROLL_ENTRY(SB_VERT, SB_PAGEUP),	/* VK_PRIOR */
+	SCROLL_ENTRY(SB_VERT, SB_PAGEDOWN),	/* VK_NEXT */
+	SCROLL_ENTRY(SB_VERT, SB_BOTTOM),	/* VK_END */
+	SCROLL_ENTRY(SB_VERT, SB_TOP),		/* VK_HOME */
+	SCROLL_ENTRY(SB_HORZ, SB_LINEUP),	/* VK_LEFT */
+	SCROLL_ENTRY(SB_VERT, SB_LINEUP),	/* VK_UP */
+	SCROLL_ENTRY(SB_HORZ, SB_LINEDOWN),	/* VK_RIGHT */
+	SCROLL_ENTRY(SB_VERT, SB_LINEDOWN)	/* VK_DOWN */
+#undef SCROLL_ENTRY
+    };
+
+    if (key >= VK_PRIOR && key <= VK_DOWN)
+    {
+	unsigned char code = scroll[key - VK_PRIOR].code;
+
+	(((code & (1 << 7)) == (SB_HORZ << 7))
+	 ? TREEVIEW_HScroll
+	 : TREEVIEW_VScroll)(infoPtr, code & 0x7F);
+    }
+
+    return 0;
+}
+
+/************************************************************************
+ *        TREEVIEW_KeyDown
+ *
+ * VK_UP       Move selection to the previous non-hidden item.
+ * VK_DOWN     Move selection to the next non-hidden item.
+ * VK_HOME     Move selection to the first item.
+ * VK_END      Move selection to the last item.
+ * VK_LEFT     If expanded then collapse, otherwise move to parent.
+ * VK_RIGHT    If collapsed then expand, otherwise move to first child.
+ * VK_ADD      Expand.
+ * VK_SUBTRACT Collapse.
+ * VK_MULTIPLY Expand all.
+ * VK_PRIOR    Move up GetVisibleCount items.
+ * VK_NEXT     Move down GetVisibleCount items.
+ * VK_BACK     Move to parent.
+ * CTRL-Left,Right,Up,Down,PgUp,PgDown,Home,End: Scroll without changing selection
+ */
+static LRESULT
+TREEVIEW_KeyDown(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+{
+    /* If it is non-NULL and different, it will be selected and visible. */
+    TREEVIEW_ITEM *newSelection = NULL;
+
+    TREEVIEW_ITEM *prevItem = infoPtr->selectedItem;
+
+    TRACE("%x\n", wParam);
+
+    if (prevItem == NULL)
+	return FALSE;
+
+    if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+	return TREEVIEW_ScrollKeyDown(infoPtr, wParam);
+
+    switch (wParam)
+    {
+    case VK_UP:
+	newSelection = TREEVIEW_GetPrevListItem(infoPtr, prevItem);
+	if (!newSelection)
+	    newSelection = infoPtr->root->firstChild;
+	break;
+
+    case VK_DOWN:
+	newSelection = TREEVIEW_GetNextListItem(infoPtr, prevItem);
+	break;
+
+    case VK_HOME:
+	newSelection = infoPtr->root->firstChild;
+	break;
+
+    case VK_END:
+	newSelection = TREEVIEW_GetLastListItem(infoPtr, infoPtr->root);
+	break;
+
+    case VK_LEFT:
+	if (prevItem->state & TVIS_EXPANDED)
+	{
+	    TREEVIEW_Collapse(infoPtr, prevItem, FALSE, TRUE);
+	}
+	else if (prevItem->parent != infoPtr->root)
+	{
+	    newSelection = prevItem->parent;
+	}
+	break;
+
+    case VK_RIGHT:
+	if (TREEVIEW_HasChildren(infoPtr, prevItem))
+	{
+	    if (!(prevItem->state & TVIS_EXPANDED))
+		TREEVIEW_Expand(infoPtr, prevItem, FALSE, TRUE);
+	    else
+	    {
+		newSelection = prevItem->firstChild;
+	    }
+	}
+
+	break;
+
+    case VK_MULTIPLY:
+	TREEVIEW_ExpandAll(infoPtr, prevItem);
+	break;
+
+    case VK_ADD:
+	if (!(prevItem->state & TVIS_EXPANDED))
+	    TREEVIEW_Expand(infoPtr, prevItem, FALSE, TRUE);
+	break;
+
+    case VK_SUBTRACT:
+	if (prevItem->state & TVIS_EXPANDED)
+	    TREEVIEW_Collapse(infoPtr, prevItem, FALSE, TRUE);
+	break;
+
+    case VK_PRIOR:
+	newSelection
+	    = TREEVIEW_GetListItem(infoPtr, prevItem,
+				   -TREEVIEW_GetVisibleCount(infoPtr));
+	break;
+
+    case VK_NEXT:
+	newSelection
+	    = TREEVIEW_GetListItem(infoPtr, prevItem,
+				   TREEVIEW_GetVisibleCount(infoPtr));
+	break;
+
+    case VK_BACK:
+	newSelection = prevItem->parent;
+	if (newSelection == infoPtr->root)
+	    newSelection = NULL;
+	break;
+
+    case VK_SPACE:
+	if (infoPtr->dwStyle & TVS_CHECKBOXES)
+	    TREEVIEW_ToggleItemState(infoPtr, prevItem);
+	break;
+    }
+
+    if (newSelection && newSelection != prevItem)
+    {
+	if (TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, newSelection,
+				  TVC_BYKEYBOARD))
+	{
+	    TREEVIEW_EnsureVisible(infoPtr, newSelection, FALSE);
+	}
+    }
+
+    return FALSE;
+}
+
+static LRESULT
+TREEVIEW_Notify(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+{
+    LPNMHDR lpnmh = (LPNMHDR)lParam;
+
+    if (lpnmh->code == PGN_CALCSIZE) {
+	LPNMPGCALCSIZE lppgc = (LPNMPGCALCSIZE)lParam;
+
+	if (lppgc->dwFlag == PGF_CALCWIDTH) {
+	    lppgc->iWidth = infoPtr->treeWidth;
+	    TRACE("got PGN_CALCSIZE, returning horz size = %ld, client=%ld\n",
+		  infoPtr->treeWidth, infoPtr->clientWidth);
+	}
+	else {
+	    lppgc->iHeight = infoPtr->treeHeight;
+	    TRACE("got PGN_CALCSIZE, returning vert size = %ld, client=%ld\n",
+		  infoPtr->treeHeight, infoPtr->clientHeight);
+	}
+	return 0;
+    }
+    return DefWindowProcA(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)
+{
+    if (wParam == SIZE_RESTORED)
+    {
+	infoPtr->clientWidth  = SLOWORD(lParam);
+	infoPtr->clientHeight = SHIWORD(lParam);
+
+	TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL);
+	TREEVIEW_SetFirstVisible(infoPtr, infoPtr->firstVisible, TRUE);
+	TREEVIEW_UpdateScrollBars(infoPtr);
+    }
+    else
+    {
+	FIXME("WM_SIZE flag %x %lx not handled\n", wParam, lParam);
+    }
+
+    TREEVIEW_Invalidate(infoPtr, NULL);
+    return 0;
+}
+
+static LRESULT
+TREEVIEW_StyleChanged(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+{
+    TRACE("(%x %lx)\n", wParam, lParam);
+
+    if (wParam == GWL_STYLE)
+    {
+       DWORD dwNewStyle = ((LPSTYLESTRUCT)lParam)->styleNew;
+
+       /* we have to take special care about tooltips */
+       if ((infoPtr->dwStyle ^ dwNewStyle) & TVS_NOTOOLTIPS)
+       {
+          if (infoPtr->dwStyle & TVS_NOTOOLTIPS)
+          {
+              infoPtr->hwndToolTip = COMCTL32_CreateToolTip(infoPtr->hwnd);
+              TRACE("\n");
+          }
+          else
+          {
+             DestroyWindow(infoPtr->hwndToolTip);
+             infoPtr->hwndToolTip = 0;
+          }
+       }
+
+       infoPtr->dwStyle = dwNewStyle;
+    }
+
+    TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root);
+    TREEVIEW_UpdateScrollBars(infoPtr);
+    TREEVIEW_Invalidate(infoPtr, NULL);
+
+    return 0;
+}
+
+static LRESULT
+TREEVIEW_SetFocus(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("\n");
+
+    if (!infoPtr->selectedItem)
+    {
+	TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, infoPtr->firstVisible,
+			      TVC_UNKNOWN);
+    }
+
+    TREEVIEW_SendSimpleNotify(infoPtr, NM_SETFOCUS);
+    TREEVIEW_Invalidate(infoPtr, infoPtr->selectedItem);
+    return 0;
+}
+
+static LRESULT
+TREEVIEW_KillFocus(TREEVIEW_INFO *infoPtr)
+{
+    TRACE("\n");
+
+    TREEVIEW_SendSimpleNotify(infoPtr, NM_KILLFOCUS);
+    TREEVIEW_Invalidate(infoPtr, infoPtr->selectedItem);
+    return 0;
+}
+
+
+static LRESULT WINAPI
+TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
+    if (infoPtr) TREEVIEW_VerifyTree(infoPtr);
+    else
+    {
+	if (uMsg == WM_CREATE)
+	    TREEVIEW_Create(hwnd);
+	else
+	    goto def;
+    }
+
+    switch (uMsg)
+    {
+    case TVM_CREATEDRAGIMAGE:
+	return TREEVIEW_CreateDragImage(infoPtr, wParam, lParam);
+
+    case TVM_DELETEITEM:
+	return TREEVIEW_DeleteItem(infoPtr, (HTREEITEM)lParam);
+
+    case TVM_EDITLABELA:
+	return (LRESULT)TREEVIEW_EditLabelA(infoPtr, (HTREEITEM)lParam);
+
+    case TVM_EDITLABELW:
+	FIXME("Unimplemented msg TVM_EDITLABELW\n");
+	return 0;
+
+    case TVM_ENDEDITLABELNOW:
+	return TREEVIEW_EndEditLabelNow(infoPtr, (BOOL)wParam);
+
+    case TVM_ENSUREVISIBLE:
+	return TREEVIEW_EnsureVisible(infoPtr, (HTREEITEM)lParam, TRUE);
+
+    case TVM_EXPAND:
+	return TREEVIEW_ExpandMsg(infoPtr, (UINT)wParam, (HTREEITEM)lParam);
+
+    case TVM_GETBKCOLOR:
+	return TREEVIEW_GetBkColor(infoPtr);
+
+    case TVM_GETCOUNT:
+	return TREEVIEW_GetCount(infoPtr);
+
+    case TVM_GETEDITCONTROL:
+	return TREEVIEW_GetEditControl(infoPtr);
+
+    case TVM_GETIMAGELIST:
+	return TREEVIEW_GetImageList(infoPtr, wParam);
+
+    case TVM_GETINDENT:
+	return TREEVIEW_GetIndent(infoPtr);
+
+    case TVM_GETINSERTMARKCOLOR:
+	return TREEVIEW_GetInsertMarkColor(infoPtr);
+
+    case TVM_GETISEARCHSTRINGA:
+	FIXME("Unimplemented msg TVM_GETISEARCHSTRINGA\n");
+	return 0;
+
+    case TVM_GETISEARCHSTRINGW:
+	FIXME("Unimplemented msg TVM_GETISEARCHSTRINGW\n");
+	return 0;
+
+    case TVM_GETITEMA:
+	return TREEVIEW_GetItemA(infoPtr, (LPTVITEMEXA)lParam);
+
+    case TVM_GETITEMW:
+	return TREEVIEW_GetItemW(infoPtr, (LPTVITEMEXW)lParam);
+
+    case TVM_GETITEMHEIGHT:
+	return TREEVIEW_GetItemHeight(infoPtr);
+
+    case TVM_GETITEMRECT:
+	return TREEVIEW_GetItemRect(infoPtr, (BOOL)wParam, (LPRECT)lParam);
+
+    case TVM_GETITEMSTATE:
+	return TREEVIEW_GetItemState(infoPtr, (HTREEITEM)wParam, (UINT)lParam);
+
+    case TVM_GETLINECOLOR:
+	return TREEVIEW_GetLineColor(infoPtr);
+
+    case TVM_GETNEXTITEM:
+	return TREEVIEW_GetNextItem(infoPtr, (UINT)wParam, (HTREEITEM)lParam);
+
+    case TVM_GETSCROLLTIME:
+	return TREEVIEW_GetScrollTime(infoPtr);
+
+    case TVM_GETTEXTCOLOR:
+	return TREEVIEW_GetTextColor(infoPtr);
+
+    case TVM_GETTOOLTIPS:
+	return TREEVIEW_GetToolTips(infoPtr);
+
+    case TVM_GETUNICODEFORMAT:
+	FIXME("Unimplemented msg TVM_GETUNICODEFORMAT\n");
+	return 0;
+
+    case TVM_GETVISIBLECOUNT:
+	return TREEVIEW_GetVisibleCount(infoPtr);
+
+    case TVM_HITTEST:
+	return TREEVIEW_HitTest(infoPtr, (LPTVHITTESTINFO)lParam);
+
+    case TVM_INSERTITEMA:
+	return TREEVIEW_InsertItemA(infoPtr, lParam);
+
+    case TVM_INSERTITEMW:
+	return TREEVIEW_InsertItemW(infoPtr, lParam);
+
+    case TVM_SELECTITEM:
+	return TREEVIEW_SelectItem(infoPtr, (INT)wParam, (HTREEITEM)lParam);
+
+    case TVM_SETBKCOLOR:
+	return TREEVIEW_SetBkColor(infoPtr, (COLORREF)lParam);
+
+    case TVM_SETIMAGELIST:
+	return TREEVIEW_SetImageList(infoPtr, wParam, (HIMAGELIST)lParam);
+
+    case TVM_SETINDENT:
+	return TREEVIEW_SetIndent(infoPtr, (UINT)wParam);
+
+    case TVM_SETINSERTMARK:
+	return TREEVIEW_SetInsertMark(infoPtr, (BOOL)wParam, (HTREEITEM)lParam);
+
+    case TVM_SETINSERTMARKCOLOR:
+	return TREEVIEW_SetInsertMarkColor(infoPtr, (COLORREF)lParam);
+
+    case TVM_SETITEMA:
+	return TREEVIEW_SetItemA(infoPtr, (LPTVITEMEXA)lParam);
+
+    case TVM_SETITEMW:
+    return TREEVIEW_SetItemW(infoPtr, (LPTVITEMEXW)lParam);
+	return 0;
+
+    case TVM_SETLINECOLOR:
+	return TREEVIEW_SetLineColor(infoPtr, (COLORREF)lParam);
+
+    case TVM_SETITEMHEIGHT:
+	return TREEVIEW_SetItemHeight(infoPtr, (INT)(SHORT)wParam);
+
+    case TVM_SETSCROLLTIME:
+	return TREEVIEW_SetScrollTime(infoPtr, (UINT)wParam);
+
+    case TVM_SETTEXTCOLOR:
+	return TREEVIEW_SetTextColor(infoPtr, (COLORREF)lParam);
+
+    case TVM_SETTOOLTIPS:
+	return TREEVIEW_SetToolTips(infoPtr, (HWND)wParam);
+
+    case TVM_SETUNICODEFORMAT:
+	FIXME("Unimplemented msg TVM_SETUNICODEFORMAT\n");
+	return 0;
+
+    case TVM_SORTCHILDREN:
+	return TREEVIEW_SortChildren(infoPtr, wParam, lParam);
+
+    case TVM_SORTCHILDRENCB:
+	return TREEVIEW_SortChildrenCB(infoPtr, wParam, (LPTVSORTCB)lParam);
+
+    case WM_CHAR:
+        return TREEVIEW_ProcessLetterKeys( hwnd, wParam, lParam );
+
+    case WM_COMMAND:
+	return TREEVIEW_Command(infoPtr, wParam, lParam);
+
+    case WM_DESTROY:
+	return TREEVIEW_Destroy(infoPtr);
+
+	/* WM_ENABLE */
+
+    case WM_ERASEBKGND:
+	return TREEVIEW_EraseBackground(infoPtr, (HDC)wParam);
+
+    case WM_GETDLGCODE:
+	return DLGC_WANTARROWS | DLGC_WANTCHARS;
+
+    case WM_GETFONT:
+	return TREEVIEW_GetFont(infoPtr);
+
+    case WM_HSCROLL:
+	return TREEVIEW_HScroll(infoPtr, wParam);
+
+    case WM_KEYDOWN:
+	return TREEVIEW_KeyDown(infoPtr, wParam);
+
+    case WM_KILLFOCUS:
+	return TREEVIEW_KillFocus(infoPtr);
+
+    case WM_LBUTTONDBLCLK:
+	return TREEVIEW_LButtonDoubleClick(infoPtr, lParam);
+
+    case WM_LBUTTONDOWN:
+	return TREEVIEW_LButtonDown(infoPtr, lParam);
+
+	/* WM_MBUTTONDOWN */
+
+	/* WM_MOUSEMOVE */
+
+    case WM_NOTIFY:
+	return TREEVIEW_Notify(infoPtr, wParam, lParam);
+
+    case WM_NOTIFYFORMAT:
+	return TREEVIEW_NotifyFormat(infoPtr, (HWND)wParam, (UINT)lParam);
+
+    case WM_PAINT:
+	return TREEVIEW_Paint(infoPtr, wParam);
+
+	/* WM_PRINTCLIENT */
+
+    case WM_RBUTTONDOWN:
+	return TREEVIEW_RButtonDown(infoPtr, lParam);
+
+    case WM_SETFOCUS:
+	return TREEVIEW_SetFocus(infoPtr);
+
+    case WM_SETFONT:
+	return TREEVIEW_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
+
+    case WM_SETREDRAW:
+        return TREEVIEW_SetRedraw(infoPtr, wParam, lParam);
+
+    case WM_SIZE:
+	return TREEVIEW_Size(infoPtr, wParam, lParam);
+
+    case WM_STYLECHANGED:
+	return TREEVIEW_StyleChanged(infoPtr, wParam, lParam);
+
+	/* WM_SYSCOLORCHANGE */
+
+	/* WM_SYSKEYDOWN */
+
+    case WM_TIMER:
+	return TREEVIEW_HandleTimer(infoPtr, wParam);
+
+    case WM_VSCROLL:
+	return TREEVIEW_VScroll(infoPtr, wParam);
+
+	/* WM_WININICHANGE */
+
+    case WM_MOUSEWHEEL:
+	if (wParam & (MK_SHIFT | MK_CONTROL))
+	    goto def;
+	return TREEVIEW_MouseWheel(infoPtr, wParam);
+
+    case WM_DRAWITEM:
+	TRACE("drawItem\n");
+	goto def;
+
+    default:
+	/* This mostly catches MFC and Delphi messages. :( */
+	if ((uMsg >= WM_USER) && (uMsg < WM_APP))
+	    TRACE("Unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam);
+def:
+	return DefWindowProcA(hwnd, uMsg, wParam, lParam);
+    }
+    return 0;
+}
+
+
+/* Class Registration ***************************************************/
+
+VOID
+TREEVIEW_Register(void)
+{
+    WNDCLASSA wndClass;
+
+    TRACE("\n");
+
+    ZeroMemory(&wndClass, sizeof(WNDCLASSA));
+    wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
+    wndClass.lpfnWndProc = (WNDPROC)TREEVIEW_WindowProc;
+    wndClass.cbClsExtra = 0;
+    wndClass.cbWndExtra = sizeof(TREEVIEW_INFO *);
+
+    wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
+    wndClass.hbrBackground = 0;
+    wndClass.lpszClassName = WC_TREEVIEWA;
+
+    RegisterClassA(&wndClass);
+}
+
+
+VOID
+TREEVIEW_Unregister(void)
+{
+    UnregisterClassA(WC_TREEVIEWA, NULL);
+}
+
+
+/* Tree Verification ****************************************************/
+
+#ifdef NDEBUG
+static inline void
+TREEVIEW_VerifyChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item);
+
+static inline void TREEVIEW_VerifyItemCommon(TREEVIEW_INFO *infoPtr,
+					     TREEVIEW_ITEM *item)
+{
+    assert(infoPtr != NULL);
+    assert(item != NULL);
+
+    /* both NULL, or both non-null */
+    assert((item->firstChild == NULL) == (item->lastChild == NULL));
+
+    assert(item->firstChild != item);
+    assert(item->lastChild != item);
+
+    if (item->firstChild)
+    {
+	assert(item->firstChild->parent == item);
+	assert(item->firstChild->prevSibling == NULL);
+    }
+
+    if (item->lastChild)
+    {
+	assert(item->lastChild->parent == item);
+	assert(item->lastChild->nextSibling == NULL);
+    }
+
+    assert(item->nextSibling != item);
+    if (item->nextSibling)
+    {
+	assert(item->nextSibling->parent == item->parent);
+	assert(item->nextSibling->prevSibling == item);
+    }
+
+    assert(item->prevSibling != item);
+    if (item->prevSibling)
+    {
+	assert(item->prevSibling->parent == item->parent);
+	assert(item->prevSibling->nextSibling == item);
+    }
+}
+
+static inline void
+TREEVIEW_VerifyItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
+{
+    assert(item != NULL);
+
+    assert(item->parent != NULL);
+    assert(item->parent != item);
+    assert(item->iLevel == item->parent->iLevel + 1);
+
+    assert(DPA_GetPtrIndex(infoPtr->items, item) != -1);
+
+    TREEVIEW_VerifyItemCommon(infoPtr, item);
+
+    TREEVIEW_VerifyChildren(infoPtr, item);
+}
+
+static inline void
+TREEVIEW_VerifyChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
+{
+    TREEVIEW_ITEM *child;
+    assert(item != NULL);
+
+    for (child = item->firstChild; child != NULL; child = child->nextSibling)
+	TREEVIEW_VerifyItem(infoPtr, child);
+}
+
+static inline void
+TREEVIEW_VerifyRoot(TREEVIEW_INFO *infoPtr)
+{
+    TREEVIEW_ITEM *root = infoPtr->root;
+
+    assert(root != NULL);
+    assert(root->iLevel == -1);
+    assert(root->parent == NULL);
+    assert(root->prevSibling == NULL);
+
+    TREEVIEW_VerifyItemCommon(infoPtr, root);
+
+    TREEVIEW_VerifyChildren(infoPtr, root);
+}
+
+static void
+TREEVIEW_VerifyTree(TREEVIEW_INFO *infoPtr)
+{
+    assert(infoPtr != NULL);
+
+    TREEVIEW_VerifyRoot(infoPtr);
+}
+#endif
Index: trunk/src/comctl32/treeview.cpp
===================================================================
--- trunk/src/comctl32/treeview.cpp	(revision 10097)
+++ 	(revision )
@@ -1,5247 +1,0 @@
-/* $Id: treeview.cpp,v 1.21 2002-10-29 13:47:34 sandervl Exp $ */
-/* Treeview control
- *
- * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
- * Copyright 1998,1999 Alex Priem <alexp@sci.kun.nl>
- * Copyright 1999 Sylvain St-Germain
- * Copyright 1999 Achim Hasenmueller
- * Copyright 1999-2000 Christoph Bratschi (cbratschi@datacomm.ch)
- *
- * 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/W we allocate buffer
- *      of size TEXT_CALLBACK_SIZE in DoSetItem.
- *      We use callbackMask to keep track of fields to be updated.
- *
- *
- * Status: complete (many things untested)
- * Version: 5.80
- */
-
-/*
- Most identical with:
- - Corel 20000807 level
- - (WINE 991212 level)
-*/
-
-/* CB: todo/bugs
- - startup: missing WM_SIZE messages -> i.e. wrong info tip calculation
- - bug in SetScrollInfo/ShowScrollBar: WM_SIZE and WM_NCPAINT problems (i.e. RegEdit)
- - VK_LEFT in WinHlp32 displays expanded icon
- - expand not finished
- - WM_ENABLE: draw disabled control
- - AMD cpuid: text not drawn (> treeview.cpp,v 1.13 2000/05/10 19:50:33)
-  t1: GDI32: SetBkColor to FFFFFF
-  t1: GDI32: GetTextMetricsA returned 1
-  t1: GDI32: SetTextAlign
--->
-  t1: GDI32: RestoreDC
-  t1: SendInternalMessageA WM_NOTIFY for 68000003 65 1312e4
-  t1: USER32:  GetDlgCtrlID
-
-  missing lines at -->:
-  t1: GDI32: GetTextExtentPoint32A 10001a1 Processor Speed Test 20 returned 1 (93,14)
-  t1: GDI32: ExtTextOutA 10001a1 Processor Speed Test
-  t1: GDI32: GetTextAlign
-  t1: GDI32: GetTextExtentPoint32A 10001a1 454 Mhz 7 returned 1 (37,14)
-  t1: GDI32: ExtTextOutA 10001a1 454 Mhz
-  t1: GDI32: GetTextAlign
-
-  don't know why it fails
-*/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <limits.h>
-#include "winbase.h"
-#include "wingdi.h"
-#include "winnls.h"
-#include "commctrl.h"
-#include "comctl32.h"
-#include "ccbase.h"
-#include "treeview.h"
-
-/* ffs should be in <string.h>. */
-
-//#define NDEBUG
-#define NDEBUG_TEXT
-
-#define TEXT_CALLBACK_SIZE 260
-
-#define TREEVIEW_LEFT_MARGIN 8
-
-#define MINIMUM_INDENT 19
-
-#define CALLBACK_MASK_ALL (TVIF_TEXT|TVIF_CHILDREN|TVIF_IMAGE|TVIF_SELECTEDIMAGE)
-
-#define STATEIMAGEINDEX(x)   (((x) >> 12) & 0x0f)
-#define OVERLAYIMAGEINDEX(x) (((x) >> 8) & 0x0f)
-#define ISVISIBLE(x)         ((x)->displayed)
-#define INCLIENT(x)          ((x)->inclient)
-
-typedef VOID (*TREEVIEW_ItemEnumFunc)(TREEVIEW_INFO *, TREEVIEW_ITEM *,LPVOID);
-
-static BOOL    TREEVIEW_UnqueueRefresh(TREEVIEW_INFO *,BOOL calc,BOOL refresh);
-static void    TREEVIEW_QueueRefresh(TREEVIEW_INFO *);
-static void    TREEVIEW_Refresh(TREEVIEW_INFO *infoPtr);
-static void    TREEVIEW_RefreshItem(TREEVIEW_INFO *infoPtr,TREEVIEW_ITEM *item,DWORD changed);
-
-static VOID    TREEVIEW_HideInfoTip(TREEVIEW_INFO *infoPtr);
-static LRESULT TREEVIEW_DoSelectItem(TREEVIEW_INFO *, INT, HTREEITEM, INT);
-static LRESULT TREEVIEW_EnsureVisible(TREEVIEW_INFO *,HTREEITEM,BOOL);
-static LRESULT TREEVIEW_RButtonUp(TREEVIEW_INFO *, LPPOINT);
-static LRESULT TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel);
-static VOID    TREEVIEW_CheckInfoTip(TREEVIEW_INFO *infoPtr);
-static VOID    TREEVIEW_ISearch(TREEVIEW_INFO *infoPtr,CHAR ch);
-
-/* Random Utilities *****************************************************/
-
-#ifdef NDEBUG
-static inline void
-TREEVIEW_VerifyTree(TREEVIEW_INFO *infoPtr)
-{
-    (void)infoPtr;
-}
-
-#else
-/* The definition is at the end of the file. */
-static void TREEVIEW_VerifyTree(TREEVIEW_INFO *infoPtr);
-#ifndef NDEBUG_TEXT
-static void TREEVIEW_WriteVerify(CHAR *text)
-{
-  dprintf((text));
-}
-#else
-static inline void TREEVIEW_WriteVerify(CHAR * text) {}
-#endif
-#endif
-
-/* Returns the treeview private data if hwnd is a treeview.
- * Otherwise returns an undefined value. */
-#define TREEVIEW_GetInfoPtr(hwnd) ((TREEVIEW_INFO *)getInfoPtr(hwnd))
-
-/* Don't call this. Nothing wants an item index. */
-static inline int
-TREEVIEW_GetItemIndex(TREEVIEW_INFO *infoPtr, HTREEITEM handle)
-{
-    assert(infoPtr != NULL);
-
-    return DPA_GetPtrIndex(infoPtr->items,handle);
-}
-
-/***************************************************************************
- * This method checks that handle is an item for this tree.
- */
-static BOOL
-TREEVIEW_ValidItem(TREEVIEW_INFO *infoPtr,HTREEITEM handle)
-{
-    if (TREEVIEW_GetItemIndex(infoPtr, handle) == -1)
-    {
-        //TRACE("invalid item %p\n", handle);
-        return FALSE;
-    }
-    else
-        return TRUE;
-}
-
-static HFONT
-TREEVIEW_CreateBoldFont(HFONT hOrigFont)
-{
-    LOGFONTA font;
-
-    GetObjectA(hOrigFont, sizeof(font), &font);
-    font.lfWeight = FW_BOLD;
-
-    return CreateFontIndirectA(&font);
-}
-
-static inline HFONT
-TREEVIEW_FontForItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
-{
-    return (item->state & TVIS_BOLD) ? infoPtr->hBoldFont : infoPtr->hFont;
-}
-
-/* for trace/debugging purposes only */
-static const WCHAR *
-TREEVIEW_ItemName(TREEVIEW_ITEM *item)
-{
-    if (item == NULL) return (WCHAR*)L"<null item>";
-    if (item->pszText == LPSTR_TEXTCALLBACKW) return (WCHAR*)L"<callback>";
-    if (item->pszText == NULL) return (WCHAR*)L"<null>";
-
-    return item->pszText;
-}
-
-/* An item is not a child of itself. */
-static BOOL
-TREEVIEW_IsChildOf(TREEVIEW_ITEM *parent, TREEVIEW_ITEM *child)
-{
-    do
-    {
-        child = child->parent;
-        if (child == parent) return TRUE;
-    } while (child != NULL);
-
-    return FALSE;
-}
-
-/* Tree Traversal *******************************************************/
-
-/***************************************************************************
- * This method returns the last expanded sibling or child child item
- * of a tree node
- */
-static TREEVIEW_ITEM *
-TREEVIEW_GetLastListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem)
-{
-    if (!wineItem)
-       return NULL;
-
-    while (wineItem->lastChild)
-    {
-       if (wineItem->state & TVIS_EXPANDED)
-          wineItem = wineItem->lastChild;
-       else
-          break;
-    }
-
-    if (wineItem == infoPtr->root)
-        return NULL;
-
-    return wineItem;
-}
-
-/***************************************************************************
- * This method returns the previous non-hidden item in the list not
- * considering the tree hierarchy.
- */
-static TREEVIEW_ITEM *
-TREEVIEW_GetPrevListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *tvItem)
-{
-    if (tvItem->prevSibling)
-    {
-        /* This item has a prevSibling, get the last item in the sibling's tree. */
-        TREEVIEW_ITEM *upItem = tvItem->prevSibling;
-
-        if ((upItem->state & TVIS_EXPANDED) && upItem->lastChild != NULL)
-            return TREEVIEW_GetLastListItem(infoPtr, upItem->lastChild);
-        else
-            return upItem;
-    }
-    else
-    {
-        /* this item does not have a prevSibling, get the parent */
-        return (tvItem->parent != infoPtr->root) ? tvItem->parent : NULL;
-    }
-}
-
-
-/***************************************************************************
- * This method returns the next physical item in the treeview not
- * considering the tree hierarchy.
- */
-static TREEVIEW_ITEM *
-TREEVIEW_GetNextListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *tvItem)
-{
-    assert(tvItem != NULL);
-
-    /*
-     * If this item has children and is expanded, return the first child
-     */
-    if ((tvItem->state & TVIS_EXPANDED) && tvItem->firstChild != NULL)
-    {
-        return tvItem->firstChild;
-    }
-
-
-    /*
-     * try to get the sibling
-     */
-    if (tvItem->nextSibling)
-        return tvItem->nextSibling;
-
-    /*
-     * Otherwise, get the parent's sibling.
-     */
-    while (tvItem->parent)
-    {
-        tvItem = tvItem->parent;
-
-        if (tvItem->nextSibling)
-            return tvItem->nextSibling;
-    }
-
-    return NULL;
-}
-
-/***************************************************************************
- * This method returns the nth item starting at the given item.  It returns
- * the last item (or first) we we run out of items.
- *
- * Will scroll backward if count is <0.
- *             forward if count is >0.
- */
-static TREEVIEW_ITEM *
-TREEVIEW_GetListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
-                     LONG count)
-{
-    TREEVIEW_ITEM *(*next_item)(TREEVIEW_INFO *, TREEVIEW_ITEM *);
-    TREEVIEW_ITEM *previousItem;
-
-    assert(wineItem != NULL);
-
-    if (count > 0)
-    {
-        next_item = TREEVIEW_GetNextListItem;
-    }
-    else if (count < 0)
-    {
-        count = -count;
-        next_item = TREEVIEW_GetPrevListItem;
-    }
-    else
-        return wineItem;
-
-    do
-    {
-        previousItem = wineItem;
-        wineItem = next_item(infoPtr, wineItem);
-
-    } while (--count && wineItem != NULL);
-
-
-    return wineItem ? wineItem : previousItem;
-}
-
-static VOID
-TREEVIEW_ForEachDisplayed(TREEVIEW_INFO *infoPtr,TREEVIEW_ItemEnumFunc func,LPVOID data)
-{
-    TREEVIEW_ITEM *item;
-
-    for (item = infoPtr->root->firstChild; item != NULL;
-         item = TREEVIEW_GetNextListItem(infoPtr, item))
-    {
-        func(infoPtr, item, data);
-    }
-}
-
-/* Notifications */
-
-static VOID
-TREEVIEW_TVItemFromItem(UINT mask,TVITEMW *tvItem,TREEVIEW_ITEM *item)
-{
-    tvItem->mask = mask;
-    tvItem->hItem = item;
-    tvItem->state = item->state;
-    tvItem->stateMask = 0;
-    tvItem->iImage = item->iImage;
-    tvItem->pszText = item->pszText;
-    tvItem->cchTextMax = item->cchTextMax;
-    tvItem->iImage = item->iImage;
-    tvItem->iSelectedImage = item->iSelectedImage;
-    tvItem->cChildren = item->cChildren;
-    tvItem->lParam = item->lParam;
-}
-
-static BOOL TREEVIEW_SendTreeviewNotify(TREEVIEW_INFO *infoPtr,UINT code,UINT action,UINT mask,HTREEITEM oldItem,HTREEITEM newItem)
-{
-  NMTREEVIEWW nmhdr;
-  CHAR *oldText = NULL,*newText = NULL;
-  BOOL rc;
-
-  ZeroMemory(&nmhdr,sizeof(NMTREEVIEWW));
-
-  nmhdr.action = action;
-  if (oldItem)
-  {
-    TREEVIEW_TVItemFromItem(mask, &nmhdr.itemOld, oldItem);
-    if (!isUnicodeNotify(&infoPtr->header))
-    {
-      if (!oldItem->pszText || (oldItem->pszText == LPSTR_TEXTCALLBACKW)) nmhdr.itemOld.pszText = NULL; else
-      {
-        INT len = lstrlenW(oldItem->pszText)+1;
-
-        oldText = (CHAR*)COMCTL32_Alloc(len);
-        lstrcpyWtoA(oldText,oldItem->pszText);
-        nmhdr.itemOld.pszText = (WCHAR*)oldText;
-        nmhdr.itemOld.cchTextMax = len;
-      }
-    }
-  }
-
-  if (newItem)
-  {
-    TREEVIEW_TVItemFromItem(mask, &nmhdr.itemNew, newItem);
-    if (!isUnicodeNotify(&infoPtr->header))
-    {
-      if (!newItem->pszText || (newItem->pszText == LPSTR_TEXTCALLBACKW)) nmhdr.itemNew.pszText = NULL; else
-      {
-        INT len = lstrlenW(newItem->pszText)+1;
-
-        newText = (CHAR*)COMCTL32_Alloc(len);
-        lstrcpyWtoA(newText,newItem->pszText);
-        nmhdr.itemNew.pszText = (WCHAR*)newText;
-        nmhdr.itemNew.cchTextMax = len;
-      }
-    }
-  }
-
-  nmhdr.ptDrag.x = 0;
-  nmhdr.ptDrag.y = 0;
-
-  rc = (BOOL)sendNotify(infoPtr->hwnd,code,&nmhdr.hdr);
-
-  if (oldText) COMCTL32_Free(oldText);
-  if (newText) COMCTL32_Free(newText);
-
-  return rc;
-}
-
-static BOOL
-TREEVIEW_SendTreeviewDnDNotify (TREEVIEW_INFO *infoPtr,UINT code,HTREEITEM dragItem,POINT pt)
-{
-  NMTREEVIEWA nmhdr;
-
-  nmhdr.action = 0;
-  nmhdr.itemNew.mask = TVIF_STATE | TVIF_PARAM | TVIF_HANDLE;
-  nmhdr.itemNew.hItem = dragItem;
-  nmhdr.itemNew.state = dragItem->state;
-  nmhdr.itemNew.lParam = dragItem->lParam;
-
-  nmhdr.ptDrag.x = pt.x;
-  nmhdr.ptDrag.y = pt.y;
-
-  return (BOOL)sendNotify(infoPtr->hwnd,code,&nmhdr.hdr);
-}
-
-static BOOL
-TREEVIEW_SendCustomDrawNotify(TREEVIEW_INFO *infoPtr,DWORD dwDrawStage,HDC hdc,RECT rc)
-{
-  NMTVCUSTOMDRAW nmcdhdr;
-  LPNMCUSTOMDRAW nmcd;
-
-  nmcd = &nmcdhdr.nmcd;
-  nmcd->dwDrawStage = dwDrawStage;
-  nmcd->hdc         = hdc;
-  nmcd->rc          = rc;
-  nmcd->dwItemSpec  = 0;
-  nmcd->uItemState  = 0;
-  nmcd->lItemlParam = 0;
-  nmcdhdr.clrText   = infoPtr->clrText;
-  nmcdhdr.clrTextBk = infoPtr->clrBk;
-  nmcdhdr.iLevel    = 0;
-
-  return (BOOL)sendNotify(infoPtr->hwnd,NM_CUSTOMDRAW,&nmcdhdr.nmcd.hdr);
-}
-
-/* FIXME: need to find out when the flags in uItemState need to be set */
-
-static BOOL
-TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr,HDC hdc,TREEVIEW_ITEM *wineItem,UINT uItemDrawState)
-{
-  NMTVCUSTOMDRAW nmcdhdr;
-  LPNMCUSTOMDRAW nmcd;
-  DWORD dwDrawStage,dwItemSpec;
-  UINT uItemState;
-  INT retval;
-
-  dwDrawStage = CDDS_ITEM | uItemDrawState;
-  dwItemSpec = (DWORD)wineItem;
-  uItemState = 0;
-  if (wineItem->state & TVIS_SELECTED)
-  {
-    uItemState |= CDIS_SELECTED;
-    if (GetFocus() == infoPtr->hwnd) uItemState |= CDIS_FOCUS;
-  }
-  if (wineItem == infoPtr->selectedItem)
-    uItemState |= CDIS_FOCUS;
-  if (wineItem == infoPtr->hotItem)
-    uItemState |= CDIS_HOT;
-
-  nmcd = &nmcdhdr.nmcd;
-  nmcd->dwDrawStage = dwDrawStage;
-  nmcd->hdc         = hdc;
-  nmcd->rc          = wineItem->rect;
-  nmcd->dwItemSpec  = dwItemSpec;
-  nmcd->uItemState  = uItemState;
-  nmcd->lItemlParam = wineItem->lParam;
-  nmcdhdr.clrText   = infoPtr->clrText;
-  nmcdhdr.clrTextBk = infoPtr->clrBk;
-  nmcdhdr.iLevel    = wineItem->iLevel;
-
-  retval = sendNotify(infoPtr->hwnd,NM_CUSTOMDRAW,&nmcdhdr.nmcd.hdr);
-
-  infoPtr->clrText = nmcdhdr.clrText;
-  infoPtr->clrBk   = nmcdhdr.clrTextBk;
-
-  return (BOOL)retval;
-}
-
-static void
-TREEVIEW_UpdateDispInfo(TREEVIEW_INFO *infoPtr,TREEVIEW_ITEM *wineItem,UINT mask)
-{
-  NMTVDISPINFOW callback;
-
-  mask &= wineItem->callbackMask;
-
-  if (mask == 0) return;
-
-  /* 'state' always contains valid value, as well as 'lParam'.
-   * All other parameters are uninitialized.
-   */
-
-  callback.item.pszText         = wineItem->pszText;
-  callback.item.cchTextMax      = wineItem->cchTextMax;
-  callback.item.mask            = mask;
-  callback.item.hItem           = wineItem;
-  callback.item.state           = wineItem->state;
-  callback.item.lParam = wineItem->lParam;
-
-  /*
-  callback.item.stateMask       = 0;
-  callback.item.iImage          = wineItem->iImage;
-  callback.item.iSelectedImage  = wineItem->iSelectedImage;
-  callback.item.cChildren       = wineItem->cChildren;
-  */
-
-  sendNotify(infoPtr->hwnd,isUnicodeNotify(&infoPtr->header) ? TVN_GETDISPINFOW:TVN_GETDISPINFOA,&callback.hdr);
-
-  /* It may have changed due to a call to SetItem. */
-  mask &= wineItem->callbackMask;
-
-  if (mask & TVIF_TEXT)
-  {
-    if (callback.item.pszText != wineItem->pszText)
-    {
-      INT len = MAX((isUnicodeNotify(&infoPtr->header) ? lstrlenW(callback.item.pszText):lstrlenA((CHAR*)callback.item.pszText))+1,TEXT_CALLBACK_SIZE);
-
-      wineItem->pszText = (WCHAR*)COMCTL32_ReAlloc(wineItem->pszText,len*sizeof(WCHAR));
-      if (isUnicodeNotify(&infoPtr->header))
-        lstrcpyW(wineItem->pszText,callback.item.pszText);
-      else
-        lstrcpyAtoW(wineItem->pszText,(CHAR*)callback.item.pszText);
-      wineItem->cchTextMax = len;
-    } else if (!isUnicodeNotify(&infoPtr->header))
-    {
-      WCHAR *newText;
-      INT len = MAX(lstrlenA((CHAR*)callback.item.pszText)+1,TEXT_CALLBACK_SIZE);
-
-      newText = (WCHAR*)COMCTL32_Alloc(len*sizeof(WCHAR));
-      lstrcpyAtoW(newText,(LPSTR)callback.item.pszText);
-      if (wineItem->pszText) COMCTL32_Free(wineItem->pszText);
-      wineItem->pszText = newText;
-      wineItem->cchTextMax = len;
-    }
-  }
-
-  if (mask & TVIF_IMAGE)
-    wineItem->iImage = callback.item.iImage;
-
-  if (mask & TVIF_SELECTEDIMAGE)
-    wineItem->iSelectedImage = callback.item.iSelectedImage;
-
-  if (mask & TVIF_CHILDREN)
-    wineItem->cChildren = callback.item.cChildren;
-
-  /* These members are now permanently set. */
-  if (callback.item.mask & TVIF_DI_SETITEM)
-    wineItem->callbackMask &= ~callback.item.mask;
-}
-
-static VOID TREEVIEW_SendKeyDownNotify(TREEVIEW_INFO *infoPtr,UINT code,WORD wVKey)
-{
-  NMTVKEYDOWN nmkdhdr;
-
-  nmkdhdr.wVKey = wVKey;
-  nmkdhdr.flags = 0;
-
-  sendNotify(infoPtr->hwnd,code,&nmkdhdr.hdr);
-}
-
-/***************************************************************************
- * This function uses cChildren field to decide whether the item has
- * children or not.
- * Note: if this returns TRUE, the child items may not actually exist,
- * they could be virtual.
- *
- * Just use wineItem->firstChild to check for physical children.
- */
-static INT
-TREEVIEW_HasChildren(TREEVIEW_INFO *infoPtr,TREEVIEW_ITEM *wineItem)
-{
-  TREEVIEW_UpdateDispInfo(infoPtr, wineItem, TVIF_CHILDREN);
-
-  return wineItem->cChildren > 0;
-}
-
-/* Item Position ********************************************************/
-
-static VOID
-TREEVIEW_ComputeTextWidth(TREEVIEW_INFO *infoPtr,TREEVIEW_ITEM *item,HDC hDC,BOOL useFont)
-{
-    HDC hdc;
-    HFONT hOldFont = 0;
-    RECT rect;
-
-    /* DRAW's OM docker creates items like this */
-    if (item->pszText == NULL)
-    {
-        item->textWidth = 0;
-        return;
-    }
-
-    hdc = hDC ? hDC:GetDC(infoPtr->hwnd);
-    if (!hDC || !useFont) hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, item));
-
-    SetRectEmpty(&rect);
-    DrawTextW (hdc,item->pszText,lstrlenW(item->pszText),&rect,DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_CALCRECT | DT_NOPREFIX);
-    item->textWidth = rect.right-rect.left;
-    item->textHeight = rect.bottom-rect.top;
-    item->rect.right = item->textOffset+item->textWidth+4;
-
-    if (!hDC || !useFont) SelectObject(hdc, hOldFont);
-    if (!hDC) ReleaseDC(infoPtr->hwnd,hdc);
-}
-
-static INT CALLBACK
-TREEVIEW_ResetItemOrderVisible(LPVOID pItem, DWORD unused)
-{
-    TREEVIEW_ITEM *item = (TREEVIEW_ITEM *)pItem;
-    (void)unused;
-
-    item->displayOrder = -1;
-    item->displayed = FALSE;
-    item->inclient = FALSE;
-
-    return 1;
-}
-
-static VOID TREEVIEW_CalcItem(TREEVIEW_INFO *infoPtr,TREEVIEW_ITEM *item,HDC hdc)
-{
-  TREEVIEW_UpdateDispInfo(infoPtr,item,TVIF_TEXT);
-  TREEVIEW_ComputeTextWidth(infoPtr,item,hdc,FALSE);
-  item->calculated = TRUE;
-}
-
-static BOOL TREEVIEW_CalcItems(TREEVIEW_INFO *infoPtr)
-{
-  TREEVIEW_ITEM *item;
-  int order = 0;
-  BOOL lar = ((infoPtr->dwStyle & (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS)) > TVS_LINESATROOT);
-  HDC hdc = 0;
-  INT maxXScroll,maxYScroll;
-  INT xDiff,yDiff;
-  BOOL changedLeftTop = FALSE;
-  RECT rc;
-
-  TREEVIEW_HideInfoTip(infoPtr);
-
-  // 1) reset
-  infoPtr->treeWidth = 0;
-  infoPtr->treeHeight = 0;
-  GetClientRect(infoPtr->hwnd,&rc);
-  infoPtr->clientWidth = rc.right;
-  infoPtr->clientHeight = rc.bottom;
-  DPA_EnumCallback(infoPtr->items,TREEVIEW_ResetItemOrderVisible,(LPARAM)NULL);
-
-  // 2) get order and tree height
-  infoPtr->firstVisible = NULL;
-  for (item = infoPtr->root->firstChild;item != NULL;item = TREEVIEW_GetNextListItem(infoPtr, item))
-  {
-    INT itemW;
-
-    item->displayOrder = order;
-
-    if ((infoPtr->uInternalStatus & TV_CALCALL) || !item->calculated)
-    {
-      if (!hdc) hdc = GetDC(infoPtr->hwnd);
-      TREEVIEW_CalcItem(infoPtr,item,hdc);
-    }
-
-    //set internal metrics
-    item->linesOffset = infoPtr->uIndent * (item->iLevel + lar - 1) - infoPtr->lefttop.x;
-    item->stateOffset = item->linesOffset + infoPtr->uIndent;
-    item->imageOffset = item->stateOffset + (STATEIMAGEINDEX(item->state) ? infoPtr->stateImageWidth : 0);
-    item->textOffset  = item->imageOffset + infoPtr->normalImageWidth;
-
-    //set item rect
-    item->rect.top = infoPtr->uItemHeight*item->displayOrder-infoPtr->lefttop.y;
-    item->rect.bottom = item->rect.top+infoPtr->uItemHeight*item->iIntegral;
-    item->rect.left = item->stateOffset;
-    item->rect.right = item->textOffset+item->textWidth+4;
-    item->displayed = TRUE;
-    item->inclient = (((item->rect.top >= 0) || (item->rect.bottom >= 0)) && (item->rect.top < infoPtr->clientHeight));
-    if (!infoPtr->firstVisible && item->inclient) infoPtr->firstVisible = item;
-
-    itemW = item->textOffset+item->textWidth+4+infoPtr->lefttop.x;
-    if (itemW > infoPtr->treeWidth)
-      infoPtr->treeWidth = itemW;
-
-    infoPtr->treeHeight += item->rect.bottom-item->rect.top;
-
-    order += item->iIntegral;
-  }
-  infoPtr->maxDisplayOrder = order;
-
-  if (hdc) ReleaseDC(infoPtr->hwnd,hdc);
-  infoPtr->uInternalStatus &= ~TV_CALCALL;
-
-  // 3) check lefttop
-  yDiff = xDiff = 0;
-
-  maxYScroll = infoPtr->treeHeight-infoPtr->clientHeight;
-  if (maxYScroll < 0) maxYScroll = 0;
-  if (infoPtr->lefttop.y > maxYScroll)
-  {
-    INT mod = maxYScroll % infoPtr->uItemHeight;
-
-    if (mod > 0) maxYScroll += infoPtr->uItemHeight-mod;
-    yDiff = infoPtr->lefttop.y-maxYScroll;
-    infoPtr->lefttop.y = maxYScroll;
-  }
-
-  maxXScroll = infoPtr->treeWidth-infoPtr->clientWidth;
-  if (maxXScroll < 0) maxXScroll = 0;
-  if (infoPtr->lefttop.x > maxXScroll)
-  {
-    xDiff = infoPtr->lefttop.x-maxXScroll;
-    infoPtr->lefttop.x = maxXScroll;
-  }
-
-  changedLeftTop = xDiff || yDiff;
-  if (changedLeftTop)
-  {
-    //update visible flag and position
-    infoPtr->firstVisible = NULL;
-    for (item = infoPtr->root->firstChild;item != NULL;item = TREEVIEW_GetNextListItem(infoPtr, item))
-    {
-      item->rect.top += yDiff;
-      item->rect.bottom += yDiff;
-      item->rect.left += xDiff;
-      item->rect.right += xDiff;
-      item->inclient = (((item->rect.top >= 0) || (item->rect.bottom >= 0)) && (item->rect.top < infoPtr->clientHeight));
-      if (!infoPtr->firstVisible && item->inclient) infoPtr->firstVisible = item;
-      item->linesOffset += xDiff;
-      item->stateOffset += xDiff;
-      item->imageOffset += xDiff;
-      item->textOffset  += xDiff;
-    }
-  }
-
-  // 4) set scrollbars
-  if (!(infoPtr->dwStyle & TVS_NOSCROLL) && (infoPtr->clientHeight > 0) && (infoPtr->clientWidth > 0))
-  {
-    if (infoPtr->treeHeight > infoPtr->clientHeight)
-    {
-      SCROLLINFO info;
-      INT visH = ((INT)(infoPtr->clientHeight/infoPtr->uItemHeight))*infoPtr->uItemHeight;
-
-      info.cbSize = sizeof(info);
-      info.nMin   = 0;
-      info.nMax   = infoPtr->treeHeight-1;
-      info.nPos   = infoPtr->lefttop.y;
-      info.nPage  = visH;
-      info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
-      infoPtr->uInternalStatus |= TV_VSCROLL;
-      SetScrollInfo(infoPtr->hwnd,SB_VERT,&info,TRUE);
-    } else
-    {
-      if (infoPtr->uInternalStatus & TV_VSCROLL)
-        ShowScrollBar(infoPtr->hwnd,SB_VERT,FALSE);
-      infoPtr->uInternalStatus &= ~TV_VSCROLL;
-    }
-    if (!(infoPtr->dwStyle & TVS_NOHSCROLL) && (infoPtr->treeWidth > infoPtr->clientWidth))
-    {
-      SCROLLINFO info;
-
-      info.cbSize = sizeof(info);
-      info.nMin   = 0;
-      info.nMax   = infoPtr->treeWidth-1;
-      info.nPos   = infoPtr->lefttop.x;
-      info.nPage  = MAX(infoPtr->clientWidth,1);
-      info.fMask  = SIF_RANGE | SIF_POS | SIF_PAGE;
-      infoPtr->uInternalStatus |= TV_HSCROLL;
-      SetScrollInfo(infoPtr->hwnd,SB_HORZ,&info,TRUE);
-    } else
-    {
-      if (infoPtr->uInternalStatus & TV_HSCROLL)
-        ShowScrollBar(infoPtr->hwnd,SB_HORZ,FALSE);
-      infoPtr->uInternalStatus &= ~TV_HSCROLL;
-    }
-  } else
-  {
-    if (infoPtr->uInternalStatus & (TV_VSCROLL | TV_HSCROLL))
-      ShowScrollBar(infoPtr->hwnd,SB_BOTH,FALSE);
-    infoPtr->uInternalStatus &= ~(TV_VSCROLL | TV_HSCROLL);
-  }
-
-  infoPtr->dwStyle = GetWindowLongA(infoPtr->hwnd,GWL_STYLE);
-
-  return changedLeftTop;
-}
-
-static VOID TREEVIEW_MoveItems(TREEVIEW_INFO *infoPtr,INT xScroll,INT yScroll)
-{
-  TREEVIEW_ITEM *item;
-
-  infoPtr->firstVisible = NULL;
-  for (item = infoPtr->root->firstChild;item;item = TREEVIEW_GetNextListItem(infoPtr,item))
-  {
-    item->rect.top += yScroll;
-    item->rect.bottom += yScroll;
-    item->rect.left += xScroll;
-    item->rect.right += xScroll;
-    item->inclient = (((item->rect.top >= 0) || (item->rect.bottom >= 0)) && (item->rect.top < infoPtr->clientHeight));
-    if (!infoPtr->firstVisible && item->inclient) infoPtr->firstVisible = item;
-
-    //set internal metrics
-    item->linesOffset += xScroll;
-    item->stateOffset += xScroll;
-    item->imageOffset += xScroll;
-    item->textOffset  += xScroll;
-  }
-}
-
-/* Item Allocation **********************************************************/
-
-static TREEVIEW_ITEM *
-TREEVIEW_AllocateItem(TREEVIEW_INFO *infoPtr)
-{
-    TREEVIEW_ITEM *newItem = (TREEVIEW_ITEM*)COMCTL32_Alloc(sizeof(TREEVIEW_ITEM));
-
-    if (!newItem)
-        return NULL;
-
-    ZeroMemory(newItem,sizeof(TREEVIEW_ITEM));
-    if (DPA_InsertPtr(infoPtr->items, INT_MAX, newItem) == -1)
-    {
-        COMCTL32_Free(newItem);
-        return NULL;
-    }
-
-    return newItem;
-}
-
-/* Exact opposite of TREEVIEW_AllocateItem. In particular, it does not
- * free item->pszText. */
-static void
-TREEVIEW_FreeItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
-{
-    DPA_DeletePtr(infoPtr->items, DPA_GetPtrIndex(infoPtr->items, item));
-    COMCTL32_Free(item);
-}
-
-
-/* Item Insertion *******************************************************/
-
-/***************************************************************************
- * This method inserts newItem before sibling as a child of parent.
- * sibling can be NULL, but only if parent has no children.
- */
-static void
-TREEVIEW_InsertBefore(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling,
-                      TREEVIEW_ITEM *parent)
-{
-    assert(newItem != NULL);
-    assert(parent != NULL);
-
-    if (sibling != NULL)
-    {
-        assert(sibling->parent == parent);
-
-        if (sibling->prevSibling != NULL)
-            sibling->prevSibling->nextSibling = newItem;
-
-        newItem->prevSibling = sibling->prevSibling;
-        sibling->prevSibling = newItem;
-    } else newItem->prevSibling = NULL;
-
-    newItem->nextSibling = sibling;
-
-    if (parent->firstChild == sibling)
-        parent->firstChild = newItem;
-
-    if (parent->lastChild == NULL)
-        parent->lastChild = newItem;
-}
-
-/***************************************************************************
- * This method inserts newItem after sibling as a child of parent.
- * sibling can be NULL, but only if parent has no children.
- */
-static void
-TREEVIEW_InsertAfter(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling,
-                     TREEVIEW_ITEM *parent)
-{
-    assert(newItem != NULL);
-    assert(parent != NULL);
-
-    if (sibling != NULL)
-    {
-        assert(sibling->parent == parent);
-
-        if (sibling->nextSibling != NULL)
-            sibling->nextSibling->prevSibling = newItem;
-
-        newItem->nextSibling = sibling->nextSibling;
-        sibling->nextSibling = newItem;
-    } else newItem->nextSibling = NULL;
-
-    newItem->prevSibling = sibling;
-
-    if (parent->lastChild == sibling)
-        parent->lastChild = newItem;
-
-    if (parent->firstChild == NULL)
-        parent->firstChild = newItem;
-}
-
-static BOOL
-TREEVIEW_DoSetItem(TREEVIEW_INFO *infoPtr,TREEVIEW_ITEM *wineItem,const TVITEMEXW *tvItem,BOOL unicode,DWORD *changed = NULL)
-{
-  UINT callbackClear = 0;
-  UINT callbackSet = 0;
-
-  if (changed) *changed = 0;
-
-  /* Do this first in case it fails. */
-
-  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 (unicode)
-    {
-      if (tvItem->pszText != LPSTR_TEXTCALLBACKW)
-      {
-        INT len = lstrlenW(tvItem->pszText)+1;
-
-        callbackClear |= TVIF_TEXT;
-
-        if (changed && ((wineItem->callbackMask & LVIF_TEXT) || (lstrcmpW(wineItem->pszText,tvItem->pszText) != 0))) *changed |= TVIF_TEXT;
-        if (len > wineItem->cchTextMax)
-        {
-          LPWSTR newText = (WCHAR*)COMCTL32_ReAlloc(wineItem->pszText,len*sizeof(WCHAR));
-          if (newText == NULL) return FALSE;
-
-          wineItem->pszText = newText;
-          wineItem->cchTextMax = len;
-        }
-        lstrcpyW (wineItem->pszText,tvItem->pszText);
-      } else
-      {
-        callbackSet |= TVIF_TEXT;
-
-        wineItem->pszText = (WCHAR*)COMCTL32_ReAlloc(wineItem->pszText,TEXT_CALLBACK_SIZE*sizeof(WCHAR));
-        wineItem->cchTextMax = TEXT_CALLBACK_SIZE;
-        if (changed) *changed |= TVIF_TEXT;
-      }
-    } else
-    {
-      if ((LPSTR)tvItem->pszText != LPSTR_TEXTCALLBACKA)
-      {
-        INT len = lstrlenA((LPSTR)tvItem->pszText)+1;
-
-        callbackClear |= TVIF_TEXT;
-
-        if (changed && ((wineItem->callbackMask & LVIF_TEXT) || (lstrcmpAtoW((CHAR*)tvItem->pszText,wineItem->pszText) != 0))) *changed |= TVIF_TEXT;
-        if (len > wineItem->cchTextMax)
-        {
-          LPWSTR newText = (WCHAR*)COMCTL32_ReAlloc(wineItem->pszText,len*sizeof(WCHAR));
-          if (newText == NULL) return FALSE;
-
-          wineItem->pszText = newText;
-          wineItem->cchTextMax = len;
-        }
-        lstrcpyAtoW (wineItem->pszText,(LPSTR)tvItem->pszText);
-      } else
-      {
-        callbackSet |= TVIF_TEXT;
-
-        wineItem->pszText = (WCHAR*)COMCTL32_ReAlloc(wineItem->pszText,TEXT_CALLBACK_SIZE*sizeof(WCHAR));
-        wineItem->cchTextMax = TEXT_CALLBACK_SIZE;
-        if (changed) *changed |= TVIF_TEXT;
-      }
-    }
-  }
-
-  if (tvItem->mask & TVIF_CHILDREN)
-  {
-    if (changed && (wineItem->cChildren != tvItem->cChildren)) *changed |= TVIF_CHILDREN;
-    wineItem->cChildren = tvItem->cChildren;
-
-    if (wineItem->cChildren == I_CHILDRENCALLBACK)
-      callbackSet |= TVIF_CHILDREN;
-    else
-      callbackClear |= TVIF_CHILDREN;
-  }
-
-  if (tvItem->mask & TVIF_IMAGE)
-  {
-    if (changed && (wineItem->iImage != tvItem->iImage)) *changed |= TVIF_IMAGE;
-    wineItem->iImage = tvItem->iImage;
-
-    if (wineItem->iImage == I_IMAGECALLBACK)
-      callbackSet |= TVIF_IMAGE;
-    else
-      callbackClear |= TVIF_IMAGE;
-  }
-
-  if (tvItem->mask & TVIF_SELECTEDIMAGE)
-  {
-    if (changed && (wineItem->iSelectedImage != tvItem->iSelectedImage)) *changed |= TVIF_SELECTEDIMAGE;
-    wineItem->iSelectedImage = tvItem->iSelectedImage;
-
-    if (wineItem->iSelectedImage == I_IMAGECALLBACK)
-      callbackSet |= TVIF_SELECTEDIMAGE;
-    else
-      callbackClear |= TVIF_SELECTEDIMAGE;
-  }
-
-  if (tvItem->mask & TVIF_PARAM)
-  {
-    if (changed && (wineItem->lParam != tvItem->lParam)) *changed |= TVIF_PARAM;
-    wineItem->lParam = tvItem->lParam;
-  }
-
-  /* If the application sets TVIF_INTEGRAL without
-   * supplying a TVITEMEX structure, it's toast. */
-  if (tvItem->mask & TVIF_INTEGRAL)
-  {
-    if (changed && (wineItem->iIntegral != tvItem->iIntegral)) *changed |= TVIF_INTEGRAL;
-    wineItem->iIntegral = tvItem->iIntegral;
-  }
-
-  if (tvItem->mask & TVIF_STATE)
-  {
-    DWORD oldState = wineItem->state;
-
-    wineItem->state &= ~tvItem->stateMask;
-    wineItem->state |= (tvItem->state & tvItem->stateMask);
-    if (changed && (wineItem->state != oldState)) *changed |= TVIF_STATE;
-  }
-
-  wineItem->callbackMask |= callbackSet;
-  wineItem->callbackMask &= ~callbackClear;
-
-  return TRUE;
-}
-
-/* Note that the new item is pre-zeroed. */
-static LRESULT
-TREEVIEW_InsertItem(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam,BOOL unicode)
-{
-  TVINSERTSTRUCTW *ptdi = (LPTVINSERTSTRUCTW)lParam;
-  TVITEMEXW *tvItem;
-  HTREEITEM insertAfter;
-  INT x;
-  TREEVIEW_ITEM *newItem, *parentItem;
-  BOOL bTextUpdated = FALSE;
-
-  if (!ptdi) return NULL;
-  tvItem = &ptdi->itemex;
-
-  if (infoPtr->hwndEdit) SetFocus(infoPtr->hwnd);
-
-  if ((ptdi->hParent == TVI_ROOT) || (ptdi->hParent == 0))
-  {
-    parentItem = infoPtr->root;
-  } else
-  {
-    parentItem = ptdi->hParent;
-
-    if (!TREEVIEW_ValidItem(infoPtr,parentItem))
-    {
-      //dprintf(("invalid parent %p\n",parentItem));
-
-      return (LRESULT)(HTREEITEM)NULL;
-    }
-  }
-
-  insertAfter = ptdi->hInsertAfter;
-
-  /* Validate this now for convenience. */
-  if ((insertAfter != TVI_FIRST) && (insertAfter != TVI_LAST) && (insertAfter != TVI_SORT))
-  {
-    if (!TREEVIEW_ValidItem(infoPtr,insertAfter))
-    {
-      //dprintf(("invalid insert after %p\n",insertAfter));
-      insertAfter = TVI_LAST;
-    } else if (parentItem != insertAfter->parent)
-    {
-      //dprintf(("invalid insert after parent %p %p %p",insertAfter,insertAfter->parent,parentItem));
-      //CB: Verified with AMD cpuid 2.04 (there are other strange things...)
-      insertAfter = parentItem->lastChild;
-    }
-  }
-
-  //TRACE("parent %p position %p: %s\n", parentItem, insertAfter,
-  //      (tvItem->mask & TVIF_TEXT)
-  //      ? ((tvItem->pszText == LPSTR_TEXTCALLBACKA) ? "<callback>"
-  //      : tvItem->pszText)
-  //      : "<no label>");
-
-  newItem = TREEVIEW_AllocateItem(infoPtr);
-  if (newItem == NULL)
-    return (LRESULT)(HTREEITEM)NULL;
-
-  newItem->parent = parentItem;
-  newItem->iIntegral = 1;
-
-  if (!TREEVIEW_DoSetItem(infoPtr,newItem,tvItem,unicode))
-    return (LRESULT)(HTREEITEM)NULL;
-
-  /* After this point, nothing can fail. (Except for TVI_SORT.) */
-
-  infoPtr->uNumItems++;
-
-  if (insertAfter == TVI_FIRST)
-  {
-    TREEVIEW_InsertBefore(newItem, parentItem->firstChild, parentItem);
-  } else if (insertAfter == TVI_LAST)
-  {
-    TREEVIEW_InsertAfter(newItem, parentItem->lastChild, parentItem);
-  } else if (insertAfter == TVI_SORT)
-  {
-    TREEVIEW_ITEM *aChild;
-    TREEVIEW_ITEM *previousChild = NULL;
-    BOOL bItemInserted = FALSE;
-
-    aChild = parentItem->firstChild;
-
-    bTextUpdated = TRUE;
-    TREEVIEW_UpdateDispInfo(infoPtr, newItem, TVIF_TEXT);
-
-    /* Iterate the parent children to see where we fit in */
-    while (aChild)
-    {
-      INT comp;
-
-      TREEVIEW_UpdateDispInfo(infoPtr,aChild,TVIF_TEXT);
-      comp = lstrcmpW(newItem->pszText,aChild->pszText);
-
-      if (comp < 0)     /* we are smaller than the current one */
-      {
-        TREEVIEW_InsertBefore(newItem, aChild, parentItem);
-        bItemInserted = TRUE;
-        break;
-      }
-      else if (comp > 0)        /* we are bigger than the current one */
-      {
-        previousChild = aChild;
-
-         /* This will help us to exit if there is no more sibling */
-        aChild = (aChild->nextSibling == 0)
-                  ? NULL
-                  : aChild->nextSibling;
-
-        /* 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(newItem, 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(newItem, previousChild, parentItem);
-  } else
-  {
-    /* hInsertAfter names a specific item we want to insert after */
-    TREEVIEW_InsertAfter(newItem,insertAfter,parentItem);
-  }
-
-  //TRACE("new item %p; parent %p, mask %x\n", newItem,
-  // newItem->parent, tvItem->mask);
-
-  newItem->iLevel = newItem->parent->iLevel + 1;
-
-  if (newItem->parent->cChildren == 0)
-    newItem->parent->cChildren = 1;
-
-  if (infoPtr->dwStyle & TVS_CHECKBOXES)
-  {
-    if (STATEIMAGEINDEX(newItem->state) == 0)
-      newItem->state |= INDEXTOSTATEIMAGEMASK(1);
-  }
-
-  TREEVIEW_VerifyTree(infoPtr);
-
-  newItem->calculated = FALSE;
-  TREEVIEW_QueueRefresh(infoPtr);
-
-  return (LRESULT)newItem;
-}
-
-/* Item Deletion ************************************************************/
-static void
-TREEVIEW_RemoveItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem);
-
-static void
-TREEVIEW_RemoveAllChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *parentItem)
-{
-    TREEVIEW_ITEM *kill = parentItem->firstChild;
-
-    while (kill != NULL)
-    {
-        TREEVIEW_ITEM *next = kill->nextSibling;
-
-        TREEVIEW_RemoveItem(infoPtr, kill);
-
-        kill = next;
-    }
-
-    assert(parentItem->cChildren <= 0); /* I_CHILDRENCALLBACK or 0 */
-    assert(parentItem->firstChild == NULL);
-    assert(parentItem->lastChild == NULL);
-}
-
-static void
-TREEVIEW_UnlinkItem(TREEVIEW_ITEM *item)
-{
-    TREEVIEW_ITEM *parentItem = item->parent;
-
-    assert(item != NULL);
-    assert(item->parent != NULL); /* i.e. it must not be the root */
-
-    if (parentItem->firstChild == item)
-        parentItem->firstChild = item->nextSibling;
-
-    if (parentItem->lastChild == item)
-        parentItem->lastChild = item->prevSibling;
-
-    if (parentItem->firstChild == NULL && parentItem->lastChild == NULL
-        && parentItem->cChildren > 0)
-        parentItem->cChildren = 0;
-
-    if (item->prevSibling)
-        item->prevSibling->nextSibling = item->nextSibling;
-
-    if (item->nextSibling)
-        item->nextSibling->prevSibling = item->prevSibling;
-}
-
-static void
-TREEVIEW_RemoveItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem)
-{
-    //TRACE("%p, (%s)\n", wineItem, TREEVIEW_ItemName(wineItem));
-
-    TREEVIEW_SendTreeviewNotify(infoPtr,isUnicodeNotify(&infoPtr->header) ? TVN_DELETEITEMW:TVN_DELETEITEMA,TVIF_HANDLE | TVIF_PARAM,0,wineItem,0);
-
-    if (wineItem->firstChild)
-        TREEVIEW_RemoveAllChildren(infoPtr, wineItem);
-
-    /* Selection is handled in TREEVIEW_DeleteItem. */
-
-    if (infoPtr->insertMarkItem == wineItem)
-        infoPtr->insertMarkItem = NULL;
-
-    /* XXX focusItem, hotItem, dropItem */
-
-    TREEVIEW_UnlinkItem(wineItem);
-
-    infoPtr->uNumItems--;
-
-    if (wineItem->pszText != LPSTR_TEXTCALLBACKW)
-        COMCTL32_Free(wineItem->pszText);
-
-    TREEVIEW_FreeItem(infoPtr, wineItem);
-}
-
-
-/* Empty out the tree. */
-static void
-TREEVIEW_RemoveTree(TREEVIEW_INFO *infoPtr)
-{
-    TREEVIEW_RemoveAllChildren(infoPtr, infoPtr->root);
-
-    assert(infoPtr->uNumItems == 0);    /* root isn't counted in uNumItems */
-}
-
-static LRESULT
-TREEVIEW_DeleteItem(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    TREEVIEW_ITEM *oldSelection = infoPtr->selectedItem;
-    TREEVIEW_ITEM *newSelection = NULL;
-    TREEVIEW_ITEM *newFirstVisible = NULL;
-    TREEVIEW_ITEM *parent, *prev = NULL;
-    BOOL visible = FALSE;
-
-    if (lParam == (LPARAM)TVI_ROOT)
-    {
-        parent = infoPtr->root;
-        newSelection = NULL;
-        visible = TRUE;
-        TREEVIEW_RemoveTree(infoPtr);
-    }
-    else
-    {
-        TREEVIEW_ITEM *wineItem = (TREEVIEW_ITEM *)lParam;
-
-        if (!TREEVIEW_ValidItem(infoPtr, wineItem))
-            return FALSE;
-
-        //TRACE("%p (%s)\n", wineItem, TREEVIEW_ItemName(wineItem));
-        parent = wineItem->parent;
-
-        if (ISVISIBLE(wineItem))
-        {
-            prev = TREEVIEW_GetPrevListItem(infoPtr, wineItem);
-            visible = TRUE;
-        }
-
-        if (infoPtr->selectedItem != NULL
-            && (wineItem == infoPtr->selectedItem
-                || TREEVIEW_IsChildOf(wineItem, infoPtr->selectedItem)))
-        {
-            if (wineItem->nextSibling)
-                newSelection = wineItem->nextSibling;
-            else if (wineItem->parent != infoPtr->root)
-                newSelection = wineItem->parent;
-        }
-
-        if (infoPtr->firstVisible == wineItem)
-        {
-            if (wineItem->nextSibling)
-               newFirstVisible = wineItem->nextSibling;
-            else if (wineItem->prevSibling)
-               newFirstVisible = wineItem->prevSibling;
-            else if (wineItem->parent != infoPtr->root)
-               newFirstVisible = wineItem->parent;
-        }
-        else
-            newFirstVisible = infoPtr->firstVisible;
-
-        TREEVIEW_RemoveItem(infoPtr, wineItem);
-    }
-
-    /* Don't change if somebody else already has. */
-    if (oldSelection == infoPtr->selectedItem)
-    {
-#ifdef __WIN32OS2__
-      //Crash in UltraEdit when opening file, because the old selected
-      //item is already freed
-      if (oldSelection == (TREEVIEW_ITEM *)lParam) {
-          infoPtr->selectedItem = 0;
-      }
-#endif
-      if (TREEVIEW_ValidItem(infoPtr, newSelection))
-        TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, newSelection, TVC_UNKNOWN);
-      else
-        infoPtr->selectedItem = 0;
-    }
-
-    /* Validate insertMark dropItem.
-     * hotItem ??? - used for comparision only.
-     */
-    if (!TREEVIEW_ValidItem(infoPtr, infoPtr->insertMarkItem))
-        infoPtr->insertMarkItem = 0;
-
-    if (!TREEVIEW_ValidItem(infoPtr, infoPtr->dropItem))
-        infoPtr->dropItem = 0;
-
-    if (!TREEVIEW_ValidItem(infoPtr, newFirstVisible))
-        newFirstVisible = infoPtr->root->firstChild;
-
-    TREEVIEW_VerifyTree(infoPtr);
-
-    if (visible)
-      TREEVIEW_QueueRefresh(infoPtr);
-    else if (INCLIENT(parent) && !TREEVIEW_HasChildren(infoPtr,parent))
-      TREEVIEW_RefreshItem(infoPtr,parent,TVIF_CHILDREN);
-
-    return TRUE;
-}
-
-/* Get/Set Messages *********************************************************/
-
-static LRESULT
-TREEVIEW_GetIndent(TREEVIEW_INFO *infoPtr)
-{
-  return infoPtr->uIndent;
-}
-
-static LRESULT
-TREEVIEW_SetIndent(TREEVIEW_INFO *infoPtr, WPARAM wParam)
-{
-  INT newIndent;
-
-  newIndent = (INT)wParam;
-  if (newIndent < MINIMUM_INDENT)
-    newIndent = MINIMUM_INDENT;
-
-  if (infoPtr->uIndent != newIndent)
-  {
-    infoPtr->uIndent = newIndent;
-
-    infoPtr->uInternalStatus |= TV_CALCALL;
-    TREEVIEW_QueueRefresh(infoPtr);
-  }
-
-  return 0;
-}
-
-static LRESULT
-TREEVIEW_GetToolTips(TREEVIEW_INFO *infoPtr)
-{
-    return infoPtr->hwndToolTip;
-}
-
-static LRESULT
-TREEVIEW_SetToolTips(TREEVIEW_INFO *infoPtr, WPARAM wParam)
-{
-    HWND prevToolTip;
-
-    prevToolTip = infoPtr->hwndToolTip;
-    infoPtr->hwndToolTip = (HWND)wParam;
-
-    return prevToolTip;
-}
-
-static LRESULT
-TREEVIEW_GetScrollTime(TREEVIEW_INFO *infoPtr)
-{
-    return infoPtr->uScrollTime;
-}
-
-static LRESULT
-TREEVIEW_SetScrollTime(TREEVIEW_INFO *infoPtr, UINT uScrollTime)
-{
-    UINT uOldScrollTime = infoPtr->uScrollTime;
-
-    infoPtr->uScrollTime = min(uScrollTime, 100);
-
-    return uOldScrollTime;
-}
-
-
-static LRESULT
-TREEVIEW_GetImageList(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    switch (wParam)
-    {
-    case (WPARAM)TVSIL_NORMAL:
-        return (LRESULT)infoPtr->himlNormal;
-
-    case (WPARAM)TVSIL_STATE:
-        return (LRESULT)infoPtr->himlState;
-
-    default:
-        return 0;
-    }
-}
-
-static LRESULT
-TREEVIEW_SetImageList(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    HIMAGELIST himlNew = (HIMAGELIST)lParam;
-    HIMAGELIST himlOld = 0;
-    int oldWidth  = infoPtr->normalImageWidth;
-    int oldHeight = infoPtr->normalImageHeight;
-
-    switch (wParam)
-    {
-      case (WPARAM)TVSIL_NORMAL:
-        himlOld = infoPtr->himlNormal;
-        infoPtr->himlNormal = himlNew;
-
-        if (himlNew != NULL)
-            ImageList_GetIconSize(himlNew, &infoPtr->normalImageWidth,
-                                  &infoPtr->normalImageHeight);
-        else
-        {
-            infoPtr->normalImageWidth = 0;
-            infoPtr->normalImageHeight = 0;
-        }
-
-        break;
-
-      case (WPARAM)TVSIL_STATE:
-        himlOld = infoPtr->himlState;
-        infoPtr->himlState = himlNew;
-
-        if (himlNew != NULL)
-            ImageList_GetIconSize(himlNew, &infoPtr->stateImageWidth,
-                                  &infoPtr->stateImageHeight);
-        else
-        {
-            infoPtr->stateImageWidth = 0;
-            infoPtr->stateImageHeight = 0;
-        }
-
-        break;
-    }
-
-    if ((oldWidth != infoPtr->normalImageWidth) || (oldHeight != infoPtr->normalImageHeight))
-      infoPtr->uInternalStatus |= TV_CALCALL;
-    TREEVIEW_QueueRefresh(infoPtr);
-
-    return (LRESULT)himlOld;
-}
-
-/* Compute the natural height (based on the font size) for items. */
-static UINT
-TREEVIEW_NaturalHeight(TREEVIEW_INFO *infoPtr)
-{
-  TEXTMETRICA tm;
-  HDC hdc = GetDC(infoPtr->hwnd);
-  HFONT hOldFont = SelectObject(hdc, infoPtr->hFont);
-  INT height;
-
-  GetTextMetricsA(hdc, &tm);
-
-  SelectObject(hdc, hOldFont);
-  ReleaseDC(infoPtr->hwnd, hdc);
-
-  /* The 16 is a hack because our fonts are tiny. */
-  height = MAX(16, tm.tmHeight + tm.tmExternalLeading);
-  if (!(infoPtr->dwStyle & TVS_NONEVENHEIGHT))
-    if (height & 0x1) height++; //important for PS_DOT pen!
-
-  return height;
-}
-
-static LRESULT
-TREEVIEW_SetItemHeight(TREEVIEW_INFO *infoPtr, WPARAM wParam)
-{
-    INT prevHeight = infoPtr->uItemHeight;
-
-    if (wParam == (WPARAM)(SHORT)-1)
-    {
-        infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr);
-        infoPtr->bHeightSet = FALSE;
-    }
-    else
-    {
-        infoPtr->uItemHeight = wParam;
-        infoPtr->bHeightSet = TRUE;
-    }
-
-    if (!(infoPtr->dwStyle & TVS_NONEVENHEIGHT))
-      if (infoPtr->uItemHeight & 0x1) infoPtr->uItemHeight++;
-
-    if (infoPtr->uItemHeight != prevHeight)
-    {
-        infoPtr->uInternalStatus |= TV_CALCALL;
-        TREEVIEW_QueueRefresh(infoPtr);
-    }
-
-    return prevHeight;
-}
-
-static LRESULT
-TREEVIEW_GetItemHeight(TREEVIEW_INFO *infoPtr)
-{
-    return infoPtr->uItemHeight;
-}
-
-
-static LRESULT
-TREEVIEW_GetFont(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    return infoPtr->hFont;
-}
-
-static LRESULT
-TREEVIEW_SetFont(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-  UINT uHeight = infoPtr->uItemHeight;
-
-  infoPtr->hFont = wParam ? (HFONT)wParam : GetStockObject(SYSTEM_FONT);
-
-  DeleteObject(infoPtr->hBoldFont);
-  infoPtr->hBoldFont = TREEVIEW_CreateBoldFont(infoPtr->hFont);
-
-  if (!infoPtr->bHeightSet)
-    infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr);
-
-  SendMessageA(infoPtr->hwndToolTip,WM_SETFONT,infoPtr->hFont,1);
-
-  if (uHeight != infoPtr->uItemHeight)
-  {
-    infoPtr->uInternalStatus |= TV_CALCALL;
-    TREEVIEW_CalcItems(infoPtr);
-  }
-
-  if (lParam)
-  {
-    TREEVIEW_UnqueueRefresh(infoPtr,FALSE,FALSE);
-    TREEVIEW_Refresh(infoPtr);
-  }
-
-  return 0;
-}
-
-
-static LRESULT
-TREEVIEW_GetLineColor(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    return (LRESULT)infoPtr->clrLine;
-}
-
-static LRESULT
-TREEVIEW_SetLineColor(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    COLORREF prevColor = infoPtr->clrLine;
-
-    infoPtr->clrLine = (COLORREF)lParam;
-
-    return (LRESULT)prevColor;
-}
-
-
-static LRESULT
-TREEVIEW_GetTextColor(TREEVIEW_INFO *infoPtr)
-{
-    return (LRESULT)infoPtr->clrText;
-}
-
-static LRESULT
-TREEVIEW_SetTextColor(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    COLORREF prevColor = infoPtr->clrText;
-
-    infoPtr->clrText = (COLORREF)lParam;
-
-    if (infoPtr->clrText != prevColor)
-        TREEVIEW_QueueRefresh(infoPtr);
-
-    return (LRESULT)prevColor;
-}
-
-
-static LRESULT
-TREEVIEW_GetBkColor(TREEVIEW_INFO *infoPtr)
-{
-    return (LRESULT)infoPtr->clrBk;
-}
-
-static LRESULT
-TREEVIEW_SetBkColor(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    COLORREF prevColor = infoPtr->clrBk;
-
-    infoPtr->clrBk = (COLORREF)lParam;
-
-    if (infoPtr->clrBk != prevColor)
-        TREEVIEW_QueueRefresh(infoPtr);
-
-    return (LRESULT)prevColor;
-}
-
-
-static LRESULT
-TREEVIEW_GetInsertMarkColor(TREEVIEW_INFO *infoPtr, WPARAM wParam,
-                            LPARAM lParam)
-{
-    return (LRESULT)infoPtr->clrInsertMark;
-}
-
-static LRESULT
-TREEVIEW_SetInsertMarkColor(TREEVIEW_INFO *infoPtr, WPARAM wParam,
-                            LPARAM lParam)
-{
-    COLORREF prevColor = infoPtr->clrInsertMark;
-
-    infoPtr->clrInsertMark = (COLORREF)lParam;
-
-    return (LRESULT)prevColor;
-}
-
-
-static LRESULT
-TREEVIEW_SetInsertMark(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    if (!TREEVIEW_ValidItem(infoPtr, (HTREEITEM)lParam))
-        return 0;
-
-    infoPtr->insertBeforeorAfter = (BOOL)wParam;
-    infoPtr->insertMarkItem = (HTREEITEM)lParam;
-
-    TREEVIEW_QueueRefresh(infoPtr);
-
-    return 1;
-}
-
-/************************************************************************
- * Some serious braindamage here. lParam is a pointer to both the
- * input HTREEITEM and the output RECT.
- */
-static LRESULT
-TREEVIEW_GetItemRect(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    TREEVIEW_ITEM *wineItem;
-    const HTREEITEM *pItem = (HTREEITEM*)lParam;
-    LPRECT lpRect = (LPRECT)lParam;
-
-    /*
-     * validate parameters
-     */
-    if (pItem == NULL)
-        return FALSE;
-
-    TREEVIEW_UnqueueRefresh(infoPtr,TRUE,TRUE);
-
-    wineItem = *pItem;
-    if (!TREEVIEW_ValidItem(infoPtr, *pItem) || !wineItem->displayed)
-        return FALSE;
-
-    if (!wineItem->calculated)
-      TREEVIEW_CalcItem(infoPtr,wineItem,(HDC)0);
-
-    /*
-     * If wParam is TRUE return the text size otherwise return
-     * the whole item size
-     */
-    if (wParam)
-    {
-        /* Windows does not send TVN_GETDISPINFO here. */
-
-        lpRect->top = wineItem->rect.top;
-        lpRect->bottom = wineItem->rect.bottom;
-
-        lpRect->left = wineItem->textOffset;
-        lpRect->right = wineItem->textOffset+wineItem->textWidth+4;
-    }
-    else
-    {
-        *lpRect = wineItem->rect;
-    }
-
-    return TRUE;
-}
-
-static inline LRESULT
-TREEVIEW_GetVisibleCount(TREEVIEW_INFO *infoPtr)
-{
-    /* Suprise! This does not take integral height into account. */
-    return infoPtr->clientHeight / infoPtr->uItemHeight;
-}
-
-static LRESULT
-TREEVIEW_GetItem(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam,BOOL unicode)
-{
-    LPTVITEMEXW tvItem;
-    TREEVIEW_ITEM *wineItem;
-
-    tvItem = (LPTVITEMEXW)lParam;
-
-    wineItem = tvItem->hItem;
-
-    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
-        return FALSE;
-
-    TREEVIEW_UpdateDispInfo(infoPtr, wineItem, tvItem->mask);
-
-    if (tvItem->mask & TVIF_CHILDREN)
-        tvItem->cChildren = wineItem->cChildren;
-
-    if (tvItem->mask & TVIF_HANDLE)
-        tvItem->hItem = wineItem;
-
-    if (tvItem->mask & TVIF_IMAGE)
-        tvItem->iImage = wineItem->iImage;
-
-    if (tvItem->mask & TVIF_INTEGRAL)
-        tvItem->iIntegral = wineItem->iIntegral;
-
-    /* undocumented: windows ignores TVIF_PARAM and
-     * * always sets lParam
-     */
-    tvItem->lParam = wineItem->lParam;
-
-    if (tvItem->mask & TVIF_SELECTEDIMAGE)
-        tvItem->iSelectedImage = wineItem->iSelectedImage;
-
-    if (tvItem->mask & TVIF_STATE)
-        tvItem->state = wineItem->state & tvItem->stateMask;
-
-    if (tvItem->mask & TVIF_TEXT)
-    {
-      if (unicode)
-        lstrcpynW(tvItem->pszText,wineItem->pszText,tvItem->cchTextMax);
-      else
-        lstrcpynWtoA((CHAR*)tvItem->pszText,wineItem->pszText,tvItem->cchTextMax);
-    }
-
-    return TRUE;
-}
-
-/* Beware MSDN Library Visual Studio 6.0. It says -1 on failure, 0 on success,
- * which is wrong. */
-static LRESULT
-TREEVIEW_SetItem(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam,BOOL unicode)
-{
-    TREEVIEW_ITEM *wineItem;
-    TVITEMEXW *tvItem;
-    DWORD changed = 0;
-
-    if (infoPtr->hwndEdit) SetFocus(infoPtr->hwnd);
-
-    tvItem = (LPTVITEMEXW)lParam;
-    wineItem = tvItem->hItem;
-
-    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
-        return FALSE;
-
-    if (!TREEVIEW_DoSetItem(infoPtr,wineItem,tvItem,unicode,&changed))
-        return FALSE;
-
-    /* If the text or TVIS_BOLD was changed, and it is displayed, recalculate. */
-    if (((changed & TVIF_TEXT) || ((tvItem->mask & TVIF_STATE) && (tvItem->stateMask & TVIS_BOLD))) && wineItem->displayed)
-    {
-      TREEVIEW_ComputeTextWidth(infoPtr,wineItem,0,FALSE);
-    }
-
-    if (changed & (TVIF_INTEGRAL | TVIF_CHILDREN))
-      TREEVIEW_QueueRefresh(infoPtr);
-    else if (changed)
-      TREEVIEW_RefreshItem(infoPtr,wineItem,changed);
-
-    return TRUE;
-}
-
-static LRESULT
-TREEVIEW_GetItemState(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    TREEVIEW_ITEM *wineItem = (HTREEITEM)wParam;
-
-    if (!wineItem || !TREEVIEW_ValidItem(infoPtr, wineItem))
-        return 0;
-
-    return (wineItem->state & lParam);
-}
-
-static LRESULT
-TREEVIEW_GetNextItem(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    TREEVIEW_ITEM *wineItem;
-    TREEVIEW_ITEM *retval;
-    WPARAM which;
-
-    which = (INT)wParam;
-    wineItem = (TREEVIEW_ITEM *)lParam;
-    retval = 0;
-
-    /* handle all the global data here */
-    switch (which)
-    {
-      case TVGN_CHILD:            /* Special case: child of 0 is root */
-        if (wineItem)
-            break;
-        /* fall through */
-      case TVGN_ROOT:
-        retval = infoPtr->root->firstChild;
-        break;
-
-      case TVGN_CARET:
-        retval = infoPtr->selectedItem;
-        break;
-
-      case TVGN_FIRSTVISIBLE:
-        TREEVIEW_UnqueueRefresh(infoPtr,TRUE,TRUE);
-        retval = infoPtr->firstVisible;
-        break;
-
-      case TVGN_DROPHILITE:
-        retval = infoPtr->dropItem;
-        break;
-
-      case TVGN_LASTVISIBLE:
-        retval = TREEVIEW_GetLastListItem(infoPtr,infoPtr->root);
-        break;
-    }
-
-    if (retval)
-    {
-        //TRACE("flags:%x, returns %p\n", which, retval);
-        return (LRESULT)retval;
-    }
-
-    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
-        return FALSE;
-
-    switch (which)
-    {
-      case TVGN_NEXT:
-        retval = wineItem->nextSibling;
-        break;
-
-      case TVGN_PREVIOUS:
-        retval = wineItem->prevSibling;
-        break;
-
-      case TVGN_PARENT:
-        retval = (wineItem->parent != infoPtr->root) ? wineItem->parent : NULL;
-        break;
-
-      case TVGN_CHILD:
-        retval = wineItem->firstChild;
-        break;
-
-      case TVGN_NEXTVISIBLE:
-        retval = TREEVIEW_GetNextListItem(infoPtr, wineItem);
-        break;
-
-      case TVGN_PREVIOUSVISIBLE:
-        retval = TREEVIEW_GetPrevListItem(infoPtr, wineItem);
-        break;
-
-      default:
-        //TRACE("Unknown msg %x,item %p\n", which, wineItem);
-        break;
-    }
-
-    //TRACE("flags:%x, item %p;returns %p\n", which, wineItem, retval);
-    return (LRESULT)retval;
-}
-
-
-static LRESULT
-TREEVIEW_GetCount(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    return (LRESULT)infoPtr->uNumItems;
-}
-
-static VOID
-TREEVIEW_ToggleItemState(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
-{
-    if (infoPtr->dwStyle & TVS_CHECKBOXES)
-    {
-        static const unsigned int state_table[] = { 0, 2, 1 };
-
-        unsigned int state;
-
-        state = STATEIMAGEINDEX(item->state);
-        //TRACE("state:%x\n", state);
-        item->state &= ~TVIS_STATEIMAGEMASK;
-
-        if (state < 3)
-            state = state_table[state];
-
-        item->state |= INDEXTOSTATEIMAGEMASK(state);
-
-        //TRACE("state:%x\n", state);
-        TREEVIEW_RefreshItem(infoPtr,item,TVIF_IMAGE);
-    }
-}
-
-
-/* Painting *************************************************************/
-
-/* Draw the lines and expand button for an item. Also draws one section
- * of the line from item's parent to item's parent's next sibling. */
-static void
-TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item)
-{
-    LONG centerx, centery;
-    BOOL lar = ((infoPtr->dwStyle
-                 & (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS))
-                > TVS_LINESATROOT);
-
-    if (!lar && item->iLevel == 0)
-        return;
-
-    centerx = (item->linesOffset + item->stateOffset) / 2;
-    centery = (item->rect.top + item->rect.bottom) / 2;
-
-    if (infoPtr->dwStyle & TVS_HASLINES)
-    {
-        HPEN hOldPen, hNewPen;
-        HTREEITEM parent;
-
-        /*
-         * Get a dotted grey pen
-         */
-        hNewPen = CreatePen(PS_DOT, 0, infoPtr->clrLine);
-        hOldPen = SelectObject(hdc, hNewPen);
-
-        MoveToEx(hdc, item->stateOffset, centery, NULL);
-        LineTo(hdc, centerx - 1, centery);
-
-        if (item->prevSibling || item->parent != infoPtr->root)
-        {
-            MoveToEx(hdc, centerx, item->rect.top, NULL);
-            LineTo(hdc, centerx, centery);
-        }
-
-        if (item->nextSibling)
-        {
-            MoveToEx(hdc, centerx, centery, NULL);
-            LineTo(hdc, centerx, item->rect.bottom + 1);
-        }
-
-        /* Draw the line from our parent to its next sibling. */
-        parent = item->parent;
-        while (parent != infoPtr->root)
-        {
-            int pcenterx = (parent->linesOffset + parent->stateOffset) / 2;
-
-            if (parent->nextSibling
-                /* skip top-levels unless TVS_LINESATROOT */
-                && parent->stateOffset > parent->linesOffset)
-            {
-                MoveToEx(hdc, pcenterx, item->rect.top, NULL);
-                LineTo(hdc, pcenterx, item->rect.bottom + 1);
-            }
-
-            parent = parent->parent;
-        }
-
-        SelectObject(hdc, hOldPen);
-        DeleteObject(hNewPen);
-    }
-
-    /*
-     * Display the (+/-) signs
-     */
-
-    if (infoPtr->dwStyle & TVS_HASBUTTONS)
-    {
-        if (item->cChildren)
-        {
-            LONG height = item->rect.bottom - item->rect.top;
-            LONG width  = item->stateOffset - item->linesOffset;
-            LONG rectsize = MIN(height, width) / 4;
-            /* plussize = ceil(rectsize * 3/4) */
-            LONG plussize = (rectsize + 1) * 3 / 4;
-
-            HPEN hNewPen  = CreatePen(PS_SOLID, 0, infoPtr->clrLine);
-            HPEN hOldPen  = SelectObject(hdc, hNewPen);
-            HBRUSH hbr    = CreateSolidBrush(infoPtr->clrBk);
-            HBRUSH hbrOld = SelectObject(hdc, hbr);
-
-            Rectangle(hdc, centerx - rectsize, centery - rectsize,
-                      centerx + rectsize + 1, centery + rectsize + 1);
-
-            SelectObject(hdc, hbrOld);
-            DeleteObject(hbr);
-
-            SelectObject(hdc, hOldPen);
-            DeleteObject(hNewPen);
-
-            MoveToEx(hdc, centerx - plussize + 1, centery, NULL);
-            LineTo(hdc, centerx + plussize, centery);
-
-            if (!(item->state & TVIS_EXPANDED))
-            {
-                MoveToEx(hdc, centerx, centery - plussize + 1, NULL);
-                LineTo(hdc, centerx, centery + plussize);
-            }
-        }
-    }
-}
-
-static VOID TREEVIEW_DrawHottrackLine(HDC hdc,TREEVIEW_ITEM *item)
-{
-  HPEN hPen,hOldPen;
-  INT rop;
-
-  if (!item->inclient) return;
-
-  rop = SetROP2(hdc,R2_XORPEN);
-  hPen = CreatePen(PS_SOLID,2,RGB(0,0,0));
-  hOldPen = SelectObject(hdc,hPen);
-
-  MoveToEx(hdc,item->textOffset,item->rect.bottom-1,NULL);
-  LineTo(hdc,item->textOffset+item->textWidth,item->rect.bottom-1);
-
-  DeleteObject(hPen);
-  SelectObject(hdc,hOldPen);
-  SetROP2(hdc,rop);
-}
-
-static void
-TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
-{
-    INT cditem;
-    HFONT hOldFont;
-    int centery;
-
-    if (!wineItem->calculated) TREEVIEW_CalcItem(infoPtr,wineItem,hdc);
-
-    hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, wineItem));
-
-    TREEVIEW_UpdateDispInfo(infoPtr, wineItem, CALLBACK_MASK_ALL);
-
-    /* The custom draw handler can query the text rectangle,
-     * so get ready. */
-    TREEVIEW_ComputeTextWidth(infoPtr,wineItem,hdc,TRUE);
-
-    cditem = 0;
-
-    if (infoPtr->cdmode & CDRF_NOTIFYITEMDRAW)
-    {
-        cditem = TREEVIEW_SendCustomDrawItemNotify(infoPtr, hdc, wineItem, CDDS_ITEMPREPAINT);
-
-        if (cditem & CDRF_SKIPDEFAULT)
-        {
-            SelectObject(hdc, hOldFont);
-            return;
-        }
-    }
-
-    if (cditem & CDRF_NEWFONT)
-        TREEVIEW_ComputeTextWidth(infoPtr,wineItem,hdc,TRUE);
-
-    TREEVIEW_DrawItemLines(infoPtr, hdc, wineItem);
-
-    centery = (wineItem->rect.top + wineItem->rect.bottom) / 2;
-
-    /*
-     * Display the images associated with this item
-     */
-    {
-        INT imageIndex;
-
-        /* State images are displayed to the left of the Normal image
-         * image number is in state; zero should be `display no image'.
-         */
-        imageIndex = STATEIMAGEINDEX(wineItem->state);
-
-        if (infoPtr->himlState && imageIndex)
-        {
-            ImageList_Draw(infoPtr->himlState, imageIndex, hdc,
-                           wineItem->stateOffset,
-                           centery - infoPtr->stateImageHeight / 2,
-                           ILD_NORMAL);
-        }
-
-        /* Now, draw the normal image; can be either selected or
-         * non-selected image.
-         */
-
-        if ((wineItem->state & TVIS_SELECTED) && wineItem->iSelectedImage)
-        {
-            /* The item is curently selected */
-            imageIndex = wineItem->iSelectedImage;
-        }
-        else
-        {
-            /* The item is not selected */
-            imageIndex = wineItem->iImage;
-        }
-
-        if (infoPtr->himlNormal && (imageIndex != I_IMAGENONE))
-        {
-            int ovlIdx = wineItem->state & TVIS_OVERLAYMASK;
-
-            ImageList_Draw(infoPtr->himlNormal, imageIndex, hdc,
-                           wineItem->imageOffset,
-                           centery - infoPtr->normalImageHeight / 2,
-                           ILD_NORMAL | ovlIdx);
-        }
-    }
-
-
-    /*
-     * Display the text associated with this item
-     */
-
-    /* Don't paint item's text if it's being edited */
-    if (!infoPtr->hwndEdit)
-    {
-        if (wineItem->pszText && (wineItem->pszText[0] != 0))
-        {
-            COLORREF oldTextColor = 0;
-            INT oldBkMode;
-            HBRUSH hbrBk = 0;
-            BOOL inFocus = (GetFocus() == infoPtr->hwnd);
-            RECT rcText;
-
-            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 || (infoPtr->dwStyle & 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);
-            }
-
-            rcText.top = wineItem->rect.top;
-            rcText.bottom = wineItem->rect.bottom;
-            rcText.left = wineItem->textOffset;
-            rcText.right = rcText.left + wineItem->textWidth + 4;
-
-            if (hbrBk)
-            {
-                FillRect(hdc, &rcText, hbrBk);
-                DeleteObject(hbrBk);
-            }
-
-            /* Draw the box arround the selected item */
-            if ((wineItem == infoPtr->selectedItem) && inFocus)
-            {
-                HPEN hNewPen = CreatePen(PS_DOT, 0,
-                                         GetSysColor(COLOR_WINDOWTEXT));
-                HPEN hOldPen = SelectObject(hdc, hNewPen);
-                INT rop = SetROP2(hdc, R2_XORPEN);
-                POINT points[5];
-
-                points[4].x = points[0].x = rcText.left;
-                points[4].y = points[0].y = rcText.top;
-                points[1].x = rcText.right - 1;
-                points[1].y = rcText.top;
-                points[2].x = rcText.right - 1;
-                points[2].y = rcText.bottom - 1;
-                points[3].x = rcText.left;
-                points[3].y = rcText.bottom - 1;
-
-                Polyline(hdc, points, 5);
-
-                SetROP2(hdc, rop);
-                SelectObject(hdc, hOldPen);
-                DeleteObject(hNewPen);
-            }
-
-            rcText.left += 2;
-            rcText.right -= 2;
-
-            /* Draw it */
-            DrawTextW(hdc,
-                      wineItem->pszText,
-                      lstrlenW(wineItem->pszText),
-                      &rcText,
-                      DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
-
-            /* Restore the hdc state */
-            SetTextColor(hdc, oldTextColor);
-
-            if (oldBkMode != TRANSPARENT)
-                SetBkMode(hdc, oldBkMode);
-        }
-    }
-
-    /* Draw insertion mark if necessary */
-
-    if (wineItem == infoPtr->insertMarkItem)
-    {
-        HPEN hNewPen, hOldPen;
-        int offset;
-        int left, right;
-
-        hNewPen = CreatePen(PS_SOLID, 2, infoPtr->clrInsertMark);
-        hOldPen = SelectObject(hdc, hNewPen);
-
-        if (infoPtr->insertBeforeorAfter)
-            offset = wineItem->rect.bottom - 1;
-        else
-            offset = wineItem->rect.top + 1;
-
-        left = wineItem->textOffset - 2;
-        right = wineItem->textOffset + wineItem->textWidth + 2;
-
-        MoveToEx(hdc, left, offset - 3, NULL);
-        LineTo(hdc, left, offset + 4);
-
-        MoveToEx(hdc, left, offset, NULL);
-        LineTo(hdc, right + 1, offset);
-
-        MoveToEx(hdc, right, offset + 3, NULL);
-        LineTo(hdc, right, offset - 4);
-
-        SelectObject(hdc, hOldPen);
-        DeleteObject(hNewPen);
-    }
-
-    //draw hot item if necessary
-    if (wineItem == infoPtr->hotItem)
-      TREEVIEW_DrawHottrackLine(hdc,wineItem);
-
-    if (cditem & CDRF_NOTIFYPOSTPAINT)
-    {
-        cditem = TREEVIEW_SendCustomDrawItemNotify(infoPtr, hdc, wineItem, CDDS_ITEMPOSTPAINT);
-    }
-
-    SelectObject(hdc, hOldFont);
-}
-
-static void TREEVIEW_QueueRefresh(TREEVIEW_INFO *infoPtr)
-{
-  if (infoPtr->Timer & TV_REFRESH_TIMER_SET)
-    KillTimer(infoPtr->hwnd,TV_REFRESH_TIMER);
-
-  if (infoPtr->uInternalStatus & TV_NOREDRAW)
-  {
-    infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
-
-    return;
-  }
-
-  SetTimer(infoPtr->hwnd,TV_REFRESH_TIMER,TV_REFRESH_DELAY,0);
-  infoPtr->Timer |= TV_REFRESH_TIMER_SET;
-}
-
-static BOOL TREEVIEW_UnqueueRefresh(TREEVIEW_INFO *infoPtr,BOOL calc,BOOL refresh)
-{
-  if (infoPtr->Timer & TV_REFRESH_TIMER_SET)
-  {
-    KillTimer(infoPtr->hwnd,TV_REFRESH_TIMER);
-    infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
-
-    if (calc) TREEVIEW_CalcItems(infoPtr);
-    if (refresh)
-    {
-      TREEVIEW_Refresh(infoPtr);
-      UpdateWindow(infoPtr->hwnd);
-    }
-
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-static void
-TREEVIEW_Draw(TREEVIEW_INFO *infoPtr,HDC hdc,RECT *updateRect)
-{
-    RECT rect;
-    TREEVIEW_ITEM *item;
-    INT iItem;
-
-    TREEVIEW_UnqueueRefresh(infoPtr,TRUE,FALSE);
-
-    GetClientRect(infoPtr->hwnd,&rect);
-    if ((rect.left == rect.right) || (rect.top == rect.bottom)) return;
-
-    infoPtr->cdmode = TREEVIEW_SendCustomDrawNotify(infoPtr,CDDS_PREPAINT,hdc,rect);
-
-    if (infoPtr->cdmode == CDRF_SKIPDEFAULT) return;
-
-    /* We iterate through all visible items in order */
-    item = infoPtr->firstVisible;
-
-    while ((item != NULL) && item->inclient)
-    {
-      RECT itemRect = item->rect;
-
-      if (!item->calculated) TREEVIEW_CalcItem(infoPtr,item,hdc);
-      if (updateRect && IntersectRect(NULL,&itemRect,updateRect))
-        TREEVIEW_DrawItem(infoPtr,hdc,item);
-      else
-      {
-        if (updateRect && (item->rect.top >= updateRect->bottom)) break;
-        itemRect.left = 0;
-        if (updateRect && IntersectRect(NULL,&itemRect,updateRect))
-          TREEVIEW_DrawItemLines(infoPtr,hdc,item);
-      }
-      item = TREEVIEW_GetNextListItem(infoPtr,item);
-    }
-
-    if (infoPtr->cdmode & CDRF_NOTIFYPOSTPAINT)
-        infoPtr->cdmode = TREEVIEW_SendCustomDrawNotify(infoPtr, CDDS_POSTPAINT, hdc, rect);
-}
-
-static void TREEVIEW_Refresh(TREEVIEW_INFO *infoPtr)
-{
-  TREEVIEW_UnqueueRefresh(infoPtr,TRUE,FALSE);
-
-  InvalidateRect(infoPtr->hwnd,NULL,TRUE);
-}
-
-static void TREEVIEW_RefreshItem(TREEVIEW_INFO *infoPtr,TREEVIEW_ITEM *item,DWORD changed)
-{
-  if (item && item->inclient)
-  {
-    RECT rect = item->rect;
-
-    //left
-    if (changed & TVIF_STATE) rect.left = item->stateOffset;
-    else if (changed & (TVIF_IMAGE | TVIF_SELECTEDIMAGE)) rect.left = item->imageOffset;
-    else if (changed & TVIF_TEXT) rect.left = item->textOffset;
-
-    //right
-    if (changed & TVIF_TEXT);
-    else if (changed & (TVIF_IMAGE | TVIF_SELECTEDIMAGE)) rect.right = item->imageOffset-infoPtr->normalImageWidth;
-    else if (changed & TVIF_STATE) rect.right = item->stateOffset-infoPtr->stateImageWidth;
-
-    InvalidateRect(infoPtr->hwnd,&rect,TRUE);
-  }
-}
-
-static LRESULT
-TREEVIEW_Paint(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  HDC hdc = (HDC)wParam;
-
-  if (!hdc)
-  {
-    PAINTSTRUCT ps;
-
-    hdc = BeginPaint(infoPtr->hwnd,&ps);
-    TREEVIEW_Draw(infoPtr,hdc,&ps.rcPaint);
-    EndPaint(infoPtr->hwnd,&ps);
-  } else
-      TREEVIEW_Draw(infoPtr,hdc,NULL);
-
-  return 0;
-}
-
-/* Sorting **************************************************************/
-
-/***************************************************************************
- * Forward the DPA local callback to the treeview owner callback
- */
-static INT WINAPI
-TREEVIEW_CallBackCompare(LPVOID pvFirst, LPVOID pvSecond, LPARAM callback)
-{
-    LPTVSORTCB pCallBackSort = (LPTVSORTCB)callback;
-
-    TREEVIEW_ITEM *first = (TREEVIEW_ITEM *)pvFirst;
-    TREEVIEW_ITEM *second = (TREEVIEW_ITEM *)pvSecond;
-
-    /* Forward the call to the client-defined callback */
-    return pCallBackSort->lpfnCompare(first->lParam,
-                                      second->lParam,
-                                      pCallBackSort->lParam);
-}
-
-/***************************************************************************
- * Treeview native sort routine: sort on item text.
- */
-static INT WINAPI
-TREEVIEW_SortOnName(LPVOID pvFirst, LPVOID pvSecond, LPARAM tvInfoPtr)
-{
-    TREEVIEW_INFO *infoPtr = (TREEVIEW_INFO *)tvInfoPtr;
-
-    TREEVIEW_ITEM *first = (TREEVIEW_ITEM *)pvFirst;
-    TREEVIEW_ITEM *second = (TREEVIEW_ITEM *)pvSecond;
-
-    TREEVIEW_UpdateDispInfo(infoPtr, first, TVIF_TEXT);
-    TREEVIEW_UpdateDispInfo(infoPtr, second, TVIF_TEXT);
-
-    return lstrcmpiW(first->pszText, second->pszText);
-}
-
-/* Returns the number of physical children belonging to item. */
-static INT
-TREEVIEW_CountChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
-{
-    INT cChildren = 0;
-    HTREEITEM hti;
-
-    for (hti = item->firstChild; hti != NULL; hti = hti->nextSibling)
-        cChildren++;
-
-    return cChildren;
-}
-
-/* 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(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
-{
-    HTREEITEM child = item->firstChild;
-
-    HDPA list = DPA_Create(8);
-    if (list == 0) return NULL;
-
-    for (child = item->firstChild; child != NULL; child = child->nextSibling)
-    {
-        if (DPA_InsertPtr(list, INT_MAX, child) == -1)
-        {
-            DPA_Destroy(list);
-            return NULL;
-        }
-    }
-
-    return list;
-}
-
-/***************************************************************************
- * Setup the treeview structure with regards of the sort method
- * and sort the children of the TV item specified in lParam
- * fRecurse: currently unused. Should be zero.
- * parent: if pSort!=NULL, should equal pSort->hParent.
- *         otherwise, item which child items are to be sorted.
- * pSort:  sort method info. if NULL, sort on item text.
- *         if non-NULL, sort on item's lParam content, and let the
- *         application decide what that means. See also TVM_SORTCHILDRENCB.
- */
-
-static LRESULT
-TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, BOOL fRecurse, HTREEITEM parent,
-              LPTVSORTCB pSort)
-{
-    INT cChildren;
-    PFNDPACOMPARE pfnCompare;
-    LPARAM lpCompare;
-    BOOL root = FALSE;
-
-    /* undocumented feature: TVI_ROOT means `sort the whole tree' */
-    if ((parent == TVI_ROOT) || (parent == 0))
-    {
-      root = TRUE;
-      parent = infoPtr->root;
-    }
-
-    /* Check for a valid handle to the parent item */
-    if (!TREEVIEW_ValidItem(infoPtr, parent))
-    {
-        //ERR("invalid item hParent=%x\n", (INT)parent);
-        return FALSE;
-    }
-
-    if (pSort)
-    {
-        pfnCompare = (PFNDPACOMPARE)TREEVIEW_CallBackCompare;
-        lpCompare = (LPARAM)pSort;
-    }
-    else
-    {
-        pfnCompare = (PFNDPACOMPARE)TREEVIEW_SortOnName;
-        lpCompare = (LPARAM)infoPtr;
-    }
-
-    cChildren = TREEVIEW_CountChildren(infoPtr,parent);
-
-    /* Make sure there is something to sort */
-    if (cChildren > 1)
-    {
-        /* TREEVIEW_ITEM rechaining */
-        INT count = 0;
-        HTREEITEM item = 0;
-        HTREEITEM nextItem = 0;
-        HTREEITEM prevItem = 0;
-
-        HDPA sortList = TREEVIEW_BuildChildDPA(infoPtr, parent);
-
-        if (sortList == NULL)
-            return FALSE;
-
-        /* let DPA sort the list */
-        DPA_Sort(sortList, pfnCompare, lpCompare);
-
-        /* 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)
-        {
-            /* link the two current item toghether */
-            item->nextSibling = nextItem;
-            nextItem->prevSibling = item;
-
-            if (prevItem == NULL)
-            {
-                /* this is the first item, update the parent */
-                parent->firstChild = item;
-                item->prevSibling = NULL;
-            }
-            else
-            {
-                /* fix the back chaining */
-                item->prevSibling = prevItem;
-            }
-
-            /* get ready for the next one */
-            prevItem = item;
-            item = nextItem;
-        }
-
-        /* the last item is pointed to by item and never has a sibling */
-        item->nextSibling = NULL;
-        parent->lastChild = item;
-
-        DPA_Destroy(sortList);
-
-        TREEVIEW_VerifyTree(infoPtr);
-
-        TREEVIEW_QueueRefresh(infoPtr);
-
-        return TRUE;
-    }
-    return FALSE;
-}
-
-/***************************************************************************
- * Setup the treeview structure with regards of the sort method
- * and sort the children of the TV item specified in lParam
- */
-static LRESULT
-TREEVIEW_SortChildrenCB(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    LPTVSORTCB pSort = (LPTVSORTCB)lParam;
-
-    return TREEVIEW_Sort(infoPtr, wParam, pSort->hParent, pSort);
-}
-
-
-/***************************************************************************
- * Sort the children of the TV item specified in lParam.
- */
-static LRESULT
-TREEVIEW_SortChildren(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    return TREEVIEW_Sort(infoPtr, (BOOL)wParam, (HTREEITEM)lParam, NULL);
-}
-
-
-/* Expansion/Collapse ***************************************************/
-
-static BOOL
-TREEVIEW_SendExpanding(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
-                       UINT action)
-{
-    return !TREEVIEW_SendTreeviewNotify(infoPtr,isUnicodeNotify(&infoPtr->header) ? TVN_ITEMEXPANDINGW:TVN_ITEMEXPANDINGA, action,
-                                        TVIF_HANDLE | TVIF_STATE | TVIF_PARAM
-                                        | TVIF_IMAGE | TVIF_SELECTEDIMAGE,
-                                        0, wineItem);
-}
-
-static VOID
-TREEVIEW_SendExpanded(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
-                      UINT action)
-{
-    TREEVIEW_SendTreeviewNotify(infoPtr,isUnicodeNotify(&infoPtr->header) ? TVN_ITEMEXPANDEDW:TVN_ITEMEXPANDEDA, action,
-                                TVIF_HANDLE | TVIF_STATE | TVIF_PARAM
-                                | TVIF_IMAGE | TVIF_SELECTEDIMAGE,
-                                0, wineItem);
-}
-
-
-/* This corresponds to TVM_EXPAND with TVE_COLLAPSE.
- * bRemoveChildren corresponds to TVE_COLLAPSERESET. */
-static BOOL
-TREEVIEW_Collapse(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
-                  BOOL bRemoveChildren, BOOL bUser)
-{
-    UINT action = TVE_COLLAPSE | (bRemoveChildren ? TVE_COLLAPSERESET : 0);
-    BOOL bSetSelection, bSetFirstVisible;
-
-    //TRACE("TVE_COLLAPSE %p %s\n", wineItem, TREEVIEW_ItemName(wineItem));
-
-    if (!(wineItem->state & TVIS_EXPANDED) || wineItem->firstChild == NULL)
-        return FALSE;
-
-    if (bUser)
-        TREEVIEW_SendExpanding(infoPtr, wineItem, action);
-
-    wineItem->state &= ~TVIS_EXPANDED;
-
-    if (bUser)
-        TREEVIEW_SendExpanded(infoPtr, wineItem, action);
-
-    bSetSelection = (infoPtr->selectedItem != NULL
-                     && TREEVIEW_IsChildOf(wineItem, infoPtr->selectedItem));
-
-    if (TREEVIEW_IsChildOf(wineItem,infoPtr->firstVisible))
-    {
-      infoPtr->lefttop.y += wineItem->rect.top;
-    }
-
-    if (bRemoveChildren)
-    {
-        //TRACE("TVE_COLLAPSERESET\n");
-        wineItem->state &= ~TVIS_EXPANDEDONCE;
-        TREEVIEW_RemoveAllChildren(infoPtr, wineItem);
-    }
-
-    //update window
-    //CB: todo: optimize!
-    TREEVIEW_UnqueueRefresh(infoPtr,FALSE,FALSE);
-    //CB: todo: precalc expanded items here
-    TREEVIEW_CalcItems(infoPtr);
-    TREEVIEW_Refresh(infoPtr);
-
-    if (bSetSelection)
-    {
-        /* Don't call DoSelectItem, it sends notifications. */
-        if (infoPtr->selectedItem)
-            infoPtr->selectedItem->state &= ~TVIS_SELECTED;
-        wineItem->state |= TVIS_SELECTED;
-        infoPtr->selectedItem = wineItem;
-
-        TREEVIEW_EnsureVisible(infoPtr,wineItem,TRUE);
-    }
-
-    return TRUE;
-}
-
-static BOOL
-TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
-                BOOL bExpandPartial, BOOL bUser)
-{
-    //TRACE("TVE_EXPAND\n");
-
-    if (!TREEVIEW_HasChildren(infoPtr, wineItem)
-        || (wineItem->state & TVIS_EXPANDED))
-        return FALSE;
-
-    //TRACE("  is not expanded...\n");
-
-    if (bUser || !(wineItem->state & TVIS_EXPANDEDONCE))
-    {
-        //TRACE("  and has never been expanded...\n");
-
-        if (bExpandPartial)
-        {
-return FALSE; //CB: how does this work??? (only display one level? nonsense in MSDN docu)
-          wineItem->state ^=TVIS_EXPANDED;
-          wineItem->state |=TVIS_EXPANDEDONCE;
-        }
-
-        wineItem->state |= TVIS_EXPANDED;
-        //TRACE("  TVN_ITEMEXPANDING sent...\n");
-
-        if (!TREEVIEW_SendExpanding(infoPtr, wineItem, TVE_EXPAND))
-        {
-            //TRACE("  TVN_ITEMEXPANDING returned TRUE, exiting...\n");
-            return FALSE;
-        }
-
-        TREEVIEW_SendExpanded(infoPtr, wineItem, TVE_EXPAND);
-
-        wineItem->state |= TVIS_EXPANDEDONCE;
-    }
-    else
-    {
-        /* this item has already been expanded */
-        wineItem->state |= TVIS_EXPANDED;
-    }
-
-    //if (bExpandPartial)
-    //  FIXME("TVE_EXPANDPARTIAL not implemented\n");
-
-    //update window
-    //CB: todo: optimize!
-    TREEVIEW_UnqueueRefresh(infoPtr,TRUE,FALSE);
-
-    /* Scroll up so that as many children as possible are visible.
-     * This looses when expanding causes an HScroll bar to appear, but we
-     * don't know that yet, so the last item is obscured. */
-    if (wineItem->firstChild && wineItem->inclient && (infoPtr->firstVisible != wineItem) && (wineItem->lastChild->rect.bottom > infoPtr->clientHeight))
-    {
-      INT childrenH = wineItem->lastChild->rect.bottom-wineItem->firstChild->rect.top;
-      INT itemH = wineItem->rect.bottom-wineItem->rect.top;
-      INT clientH = ((INT)(infoPtr->clientHeight/infoPtr->uItemHeight))*infoPtr->uItemHeight;
-
-      if (itemH+childrenH > clientH)
-      {
-        infoPtr->lefttop.y += wineItem->rect.top;
-      } else
-      {
-        INT diff = wineItem->lastChild->rect.bottom-clientH;
-
-        infoPtr->lefttop.y += diff;
-      }
-    }
-
-    TREEVIEW_CalcItems(infoPtr);
-    TREEVIEW_Refresh(infoPtr);
-    //CB: todo: check cx and cy to fit ranges!
-
-    return TRUE;
-}
-
-static BOOL
-TREEVIEW_Toggle(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, BOOL bUser)
-{
-    if (wineItem->state & TVIS_EXPANDED)
-        return TREEVIEW_Collapse(infoPtr, wineItem, FALSE, bUser);
-    else
-        return TREEVIEW_Expand(infoPtr, wineItem, FALSE, bUser);
-}
-
-static VOID
-TREEVIEW_ExpandAll(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
-{
-    TREEVIEW_Expand(infoPtr, item, FALSE, TRUE);
-
-    for (item = item->firstChild; item != NULL; item = item->nextSibling)
-    {
-        if (TREEVIEW_HasChildren(infoPtr, item))
-            TREEVIEW_ExpandAll(infoPtr, item);
-    }
-}
-
-/* Note:If the specified item is the child of a collapsed parent item,
-   the parent's list of child items is (recursively) expanded to reveal the
-   specified item. This is mentioned for TREEVIEW_SelectItem; don't
-   know if it also applies here.
-*/
-
-static LRESULT
-TREEVIEW_ExpandMsg(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    TREEVIEW_ITEM *wineItem = (HTREEITEM)lParam;
-    UINT flag = wParam;
-
-    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
-        return 0;
-
-    switch (flag & TVE_TOGGLE)
-    {
-    case TVE_COLLAPSE:
-        return TREEVIEW_Collapse(infoPtr, wineItem, flag & TVE_COLLAPSERESET,
-                                 FALSE);
-
-    case TVE_EXPAND:
-        return TREEVIEW_Expand(infoPtr, wineItem, flag & TVE_EXPANDPARTIAL,
-                               FALSE);
-
-    case TVE_TOGGLE:
-        return TREEVIEW_Toggle(infoPtr, wineItem, TRUE);
-
-    default:
-        return 0;
-    }
-
-}
-
-/* Hit-Testing **********************************************************/
-
-static TREEVIEW_ITEM *
-TREEVIEW_HitTestPoint(TREEVIEW_INFO *infoPtr,POINT pt)
-{
-  TREEVIEW_ITEM *wineItem;
-
-  if (!infoPtr->firstVisible)
-    return NULL;
-
-  wineItem = infoPtr->firstVisible;
-
-  while (wineItem && (pt.y > wineItem->rect.bottom))
-    wineItem = TREEVIEW_GetNextListItem(infoPtr,wineItem);
-
-  return wineItem;
-}
-
-static LRESULT
-TREEVIEW_HitTest(TREEVIEW_INFO *infoPtr,LPTVHITTESTINFO lpht,BOOL ignoreClientRect)
-{
-    TREEVIEW_ITEM *wineItem;
-    RECT rect;
-    UINT status;
-    LONG x, y;
-
-    if (!lpht) return 0;
-
-    status = 0;
-    x = lpht->pt.x;
-    y = lpht->pt.y;
-    lpht->hItem = 0;
-
-    if (!ignoreClientRect)
-    {
-      GetClientRect(infoPtr->hwnd,&rect);
-
-      if (x < rect.left) status |= TVHT_TOLEFT;
-      else if (x > rect.right) status |= TVHT_TORIGHT;
-      if (y < rect.top) status |= TVHT_ABOVE;
-      else if (y > rect.bottom) status |= TVHT_BELOW;
-
-      if (status)
-      {
-        lpht->flags = status;
-        return (LRESULT)(HTREEITEM)NULL;
-      }
-    }
-
-    wineItem = TREEVIEW_HitTestPoint(infoPtr,lpht->pt);
-    if (!wineItem)
-    {
-        lpht->flags = TVHT_NOWHERE;
-        return (LRESULT)(HTREEITEM)NULL;
-    }
-
-    if (!wineItem->calculated)
-      TREEVIEW_CalcItem(infoPtr,wineItem,0);
-
-    if (x >= wineItem->textOffset + wineItem->textWidth)
-    {
-        lpht->flags = TVHT_ONITEMRIGHT;
-    }
-    else if (x >= wineItem->textOffset)
-    {
-        lpht->flags = TVHT_ONITEMLABEL;
-    }
-    else if (x >= wineItem->imageOffset)
-    {
-        lpht->flags = TVHT_ONITEMICON;
-    }
-    else if (x >= wineItem->stateOffset)
-    {
-        lpht->flags = TVHT_ONITEMSTATEICON;
-    }
-    else if ((x >= wineItem->linesOffset) && (infoPtr->dwStyle & TVS_HASBUTTONS))
-    {
-        lpht->flags = TVHT_ONITEMBUTTON;
-    }
-    else
-    {
-        lpht->flags = TVHT_ONITEMINDENT;
-    }
-
-    lpht->hItem = wineItem;
-    //TRACE("(%ld,%ld):result %x\n", lpht->pt.x, lpht->pt.y, lpht->flags);
-
-    return (LRESULT)wineItem;
-}
-
-/* Item Label Editing ***************************************************/
-
-static LRESULT
-TREEVIEW_GetEditControl(TREEVIEW_INFO *infoPtr)
-{
-    return infoPtr->hwndEdit;
-}
-
-static LRESULT CALLBACK
-TREEVIEW_Edit_SubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-    TREEVIEW_INFO *infoPtr;
-    BOOL bCancel = FALSE;
-
-    switch (uMsg)
-    {
-    case WM_PAINT:
-        {
-            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_KILLFOCUS:
-    {
-        TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd));
-        if (infoPtr->bIgnoreEditKillFocus)
-            return TRUE;
-
-        break;
-    }
-
-    case WM_GETDLGCODE:
-        return DLGC_WANTARROWS | DLGC_WANTALLKEYS;
-
-    case WM_KEYDOWN:
-        if (wParam == (WPARAM)VK_ESCAPE)
-        {
-            bCancel = TRUE;
-            break;
-        }
-        else if (wParam == (WPARAM)VK_RETURN)
-        {
-            break;
-        }
-
-        /* fall through */
-    default:
-        {
-            TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd));
-
-            //@@@PH 1999/11/05 method called with freed infoPtr memory object
-            if (infoPtr != NULL)
-              return CallWindowProcA(infoPtr->wpEditOrig, hwnd, uMsg, wParam, lParam);
-            else
-              break;
-        }
-    }
-
-    /* Processing TVN_ENDLABELEDIT message could kill the focus       */
-    /* eg. Using a messagebox                                         */
-
-    infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd));
-    infoPtr->bIgnoreEditKillFocus = TRUE;
-    TREEVIEW_EndEditLabelNow(infoPtr, bCancel || !infoPtr->bLabelChanged);
-    infoPtr->bIgnoreEditKillFocus = FALSE;
-
-    return 0;
-}
-
-
-/* should handle edit control messages here */
-
-static LRESULT
-TREEVIEW_Command(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    //TRACE("%x %ld\n", wParam, lParam);
-
-    switch (HIWORD(wParam))
-    {
-    case EN_UPDATE:
-        {
-            /*
-             * Adjust the edit window size
-             */
-            char buffer[1024];
-            TREEVIEW_ITEM *editItem = infoPtr->selectedItem;
-            HDC hdc = GetDC(infoPtr->hwndEdit);
-            SIZE sz;
-            int len;
-            HFONT hFont, hOldFont = 0;
-
-            infoPtr->bLabelChanged = TRUE;
-
-            len = GetWindowTextA(infoPtr->hwndEdit, buffer, sizeof(buffer));
-
-            /* 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 (GetTextExtentPoint32A(hdc, buffer, strlen(buffer), &sz))
-            {
-                TEXTMETRICA textMetric;
-
-                /* Add Extra spacing for the next character */
-                GetTextMetricsA(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);
-
-                SetWindowPos(infoPtr->hwndEdit,
-                             HWND_TOP,
-                             0,
-                             0,
-                             sz.cx,
-                             editItem->rect.bottom - editItem->rect.top + 3,
-                             SWP_NOMOVE | SWP_DRAWFRAME);
-            }
-
-            if (hFont != 0)
-            {
-                SelectObject(hdc, hOldFont);
-            }
-
-            ReleaseDC(infoPtr->hwnd, hdc);
-            break;
-        }
-
-    default:
-        return SendMessageA(GetParent(infoPtr->hwnd), WM_COMMAND, wParam, lParam);
-    }
-
-    return 0;
-}
-
-HWND TREEVIEW_EditLabel(TREEVIEW_INFO *infoPtr,HTREEITEM hItem,BOOL unicode)
-{
-  SIZE sz;
-  TREEVIEW_ITEM *editItem = hItem;
-  HINSTANCE hinst = GetWindowLongA(infoPtr->hwnd,GWL_HINSTANCE);
-  HDC hdc;
-  HFONT hOldFont = 0;
-  TEXTMETRICA textMetric;
-  CHAR* textA = NULL;
-  NMTVDISPINFOW tvdi;
-
-  if (!TREEVIEW_ValidItem(infoPtr, editItem))
-    return (HWND)NULL;
-
-  if(infoPtr->hwndEdit)
-    return infoPtr->hwndEdit;
-
-  infoPtr->bLabelChanged = FALSE;
-
-  /* Make shure that edit item is selected */
-
-  TREEVIEW_DoSelectItem(infoPtr,TVGN_CARET,hItem,TVC_UNKNOWN);
-  TREEVIEW_EnsureVisible(infoPtr,hItem,TRUE);
-
-  TREEVIEW_UpdateDispInfo(infoPtr, editItem, TVIF_TEXT);
-
-  hdc = GetDC(infoPtr->hwnd);
-  /* Select the font to get appropriate metric dimensions */
-  if(infoPtr->hFont != 0)
-  {
-      hOldFont = SelectObject(hdc, infoPtr->hFont);
-  }
-
-  /*Get String Lenght in pixels */
-  GetTextExtentPoint32W(hdc,editItem->pszText,lstrlenW(editItem->pszText),&sz);
-
-  /*Add Extra spacing for the next character */
-  GetTextMetricsA(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);
-
-  if(infoPtr->hFont != 0)
-  {
-      SelectObject(hdc, hOldFont);
-  }
-
-  ReleaseDC(infoPtr->hwnd, hdc);
-  infoPtr->hwndEdit = CreateWindowExA (
-                         WS_EX_LEFT,
-                         "EDIT",
-                          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,
-                         infoPtr->hwnd,
-                         0,hinst,0); /* FIXME: (HMENU)IDTVEDIT,pcs->hInstance,0);*/
-
-    /* Get a 2D border. */
-  SetWindowLongA(infoPtr->hwndEdit, GWL_EXSTYLE,GetWindowLongA(infoPtr->hwndEdit, GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE);
-  SetWindowLongA(infoPtr->hwndEdit, GWL_STYLE,GetWindowLongA(infoPtr->hwndEdit, GWL_STYLE) | WS_BORDER);
-
-  SendMessageA(infoPtr->hwndEdit, WM_SETFONT, TREEVIEW_FontForItem(infoPtr, editItem),FALSE);
-
-  infoPtr->wpEditOrig = (WNDPROC)SetWindowLongA (infoPtr->hwndEdit,GWL_WNDPROC,(DWORD)TREEVIEW_Edit_SubclassProc);
-
-  tvdi.item.mask        = TVIF_HANDLE | TVIF_TEXT | TVIF_STATE | TVIF_PARAM;
-  tvdi.item.hItem       = editItem;
-  tvdi.item.state       = editItem->state;
-  tvdi.item.lParam      = editItem->lParam;
-  if (isUnicodeNotify(&infoPtr->header))
-  {
-    tvdi.item.pszText     = editItem->pszText;
-  } else
-  {
-    textA = HEAP_strdupWtoA(GetProcessHeap(),0,editItem->pszText);
-    tvdi.item.pszText = (LPWSTR)textA;
-  }
-
-  if (sendNotify(infoPtr->hwnd,isUnicodeNotify(&infoPtr->header) ? TVN_BEGINLABELEDITW:TVN_BEGINLABELEDITA,&tvdi.hdr))
-  {
-     DestroyWindow(infoPtr->hwndEdit);
-     infoPtr->hwndEdit = 0;
-     if (textA) HeapFree(GetProcessHeap(),0,textA);
-
-     return (HWND)0;
-  }
-  if (textA) HeapFree(GetProcessHeap(),0,textA);
-
-  infoPtr->selectedItem = hItem;
-  SetWindowTextW(infoPtr->hwndEdit,editItem->pszText);
-  SetFocus(infoPtr->hwndEdit);
-  SendMessageA(infoPtr->hwndEdit, EM_SETSEL, 0, -1);
-  ShowWindow(infoPtr->hwndEdit, SW_SHOW);
-
-  return infoPtr->hwndEdit;
-}
-
-
-static LRESULT
-TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr,BOOL bCancel)
-{
-  TREEVIEW_ITEM *editedItem = infoPtr->selectedItem;
-  NMTVDISPINFOW tvdi;
-  DWORD dwStyle = GetWindowLongA(infoPtr->hwnd,GWL_STYLE);
-  BOOL bCommit;
-  WCHAR *textW = NULL;
-  CHAR *textA = NULL;
-  int  iLength = 0;
-
-  if (!infoPtr->hwndEdit)
-     return FALSE;
-
-  tvdi.item.mask        = 0;
-  tvdi.item.hItem       = editedItem;
-  tvdi.item.state       = editedItem->state;
-  tvdi.item.lParam      = editedItem->lParam;
-
-  if (!bCancel)
-  {
-    textW = (WCHAR*)COMCTL32_Alloc(1024*sizeof(WCHAR));
-    iLength = GetWindowTextW(infoPtr->hwndEdit,textW,1023);
-
-    if (isUnicodeNotify(&infoPtr->header)) tvdi.item.pszText = textW; else
-    {
-      INT len = iLength+1;
-
-      textA = (CHAR*)COMCTL32_Alloc(1024*sizeof(CHAR));
-      lstrcpynWtoA(textA,textW,len);
-      tvdi.item.pszText = (WCHAR*)textA;
-    }
-    tvdi.item.cchTextMax  = iLength + 1;
-  } else
-  {
-    tvdi.item.pszText = NULL;
-    tvdi.item.cchTextMax  = 0;
-  }
-
-  bCommit = (BOOL)sendNotify(infoPtr->hwnd,isUnicodeNotify(&infoPtr->header) ? TVN_ENDLABELEDITW:TVN_ENDLABELEDITA,&tvdi.hdr);
-
-  if (!bCancel && bCommit) /* Apply the changes */
-  {
-    BOOL mustFree = FALSE;
-
-    if (!isUnicodeNotify(&infoPtr->header))
-      lstrcpynAtoW(textW,textA,iLength+1);
-
-    if (lstrcmpW(textW,editedItem->pszText) != 0)
-    {
-      if (editedItem->callbackMask & TVIF_TEXT)
-      {
-        NMTVDISPINFOW tvdi;
-        BOOL retval;
-
-        tvdi.item.mask        = TVIF_TEXT;
-        tvdi.item.hItem       = editedItem;
-        tvdi.item.state       = editedItem->state;
-        tvdi.item.lParam      = editedItem->lParam;
-        if (isUnicodeNotify(&infoPtr->header))
-        {
-          tvdi.item.pszText     = textW;
-          tvdi.item.cchTextMax  = lstrlenW(textW)+1;
-        } else
-        {
-          tvdi.item.pszText     = (LPWSTR)textA;
-          tvdi.item.cchTextMax  = lstrlenA(textA)+1;
-        }
-
-        retval = (BOOL)sendNotify(infoPtr->hwnd,isUnicodeNotify(&infoPtr->header) ? TVN_SETDISPINFOW:TVN_SETDISPINFOA,&tvdi.hdr);
-      } else
-      {
-        if (!COMCTL32_ReAlloc(editedItem->pszText,(iLength+1)*sizeof(WCHAR)))
-        {
-          //ERR("OutOfMemory, cannot allocate space for label");
-          DestroyWindow(infoPtr->hwndEdit);
-          infoPtr->hwndEdit = 0;
-          if (textA) COMCTL32_Free(textA);
-          if (textW) COMCTL32_Free(textW);
-
-          return FALSE;
-        } else
-        {
-          editedItem->cchTextMax = iLength + 1;
-          lstrcpyW(editedItem->pszText,textW);
-        }
-      }
-    }
-  }
-
-  ShowWindow(infoPtr->hwndEdit, SW_HIDE);
-  DestroyWindow(infoPtr->hwndEdit);
-  infoPtr->hwndEdit = 0;
-  if (textA) COMCTL32_Free(textA);
-  if (textW) COMCTL32_Free(textW);
-
-  editedItem->calculated = FALSE;
-  TREEVIEW_RefreshItem(infoPtr,editedItem,0);
-
-  return TRUE;
-}
-
-static LRESULT
-TREEVIEW_HandleTimer (TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-  switch (wParam)
-  {
-    case TV_REFRESH_TIMER:
-      KillTimer(infoPtr->hwnd,TV_REFRESH_TIMER);
-      infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
-      TREEVIEW_CalcItems(infoPtr);
-      TREEVIEW_Refresh(infoPtr);
-      return 0;
-
-    case TV_EDIT_TIMER:
-      KillTimer(infoPtr->hwnd,TV_EDIT_TIMER);
-      infoPtr->Timer &= ~TV_EDIT_TIMER_SET;
-      TREEVIEW_EditLabel(infoPtr,infoPtr->selectedItem,TRUE);
-      return 0;
-
-    case TV_INFOTIP_TIMER:
-      TREEVIEW_CheckInfoTip(infoPtr);
-      return 0;
- }
-
- return 1;
-}
-
-/* Mouse Tracking/Drag **************************************************/
-
-/***************************************************************************
- * This is quite unusual piece of code, but that's how it's implemented in
- * Windows.
- */
-static LRESULT
-TREEVIEW_TrackMouse(TREEVIEW_INFO *infoPtr, 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(infoPtr->hwnd);
-
-    while (1)
-    {
-        if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD))
-        {
-            if (msg.message == WM_MOUSEMOVE)
-            {
-                pt.x = (LONG)(INT16)LOWORD(msg.lParam);
-                pt.y = (LONG)(INT16)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(infoPtr, &pt);
-                break;
-            }
-
-            DispatchMessageA(&msg);
-        }
-
-        if (GetCapture() != infoPtr->hwnd)
-            return 0;
-    }
-
-    ReleaseCapture();
-    return 0;
-}
-
-static LRESULT
-TREEVIEW_LButtonDoubleClick(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-  TREEVIEW_ITEM *wineItem;
-  TV_HITTESTINFO hit;
-
-  hit.pt.x = (LONG)(INT16)LOWORD(lParam);
-  hit.pt.y = (LONG)(INT16)HIWORD(lParam);
-
-  SetFocus (infoPtr->hwnd);
-
-  if (infoPtr->Timer & TV_EDIT_TIMER_SET)
-  {
-     /* If there is pending 'edit label' event - kill it now */
-     KillTimer(infoPtr->hwnd,TV_EDIT_TIMER);
-  }
-
-  wineItem = (TREEVIEW_ITEM *)TREEVIEW_HitTest(infoPtr,&hit,FALSE);
-  if (!wineItem)
-    return 0;
-
-  //MSDN documentation says: stop on non zero. but this isn't true in this case
-  if (!sendNotify(infoPtr->hwnd,NM_DBLCLK))
-  {                             /* FIXME! */
-    switch (hit.flags)
-    {
-      case TVHT_ONITEMRIGHT:
-        /* FIXME: we should not have send NM_DBLCLK in this case. */
-        break;
-
-      case TVHT_ONITEMINDENT:
-        if (!(infoPtr->dwStyle & TVS_HASLINES))
-        {
-          break;
-        } else
-        {
-          int level = hit.pt.x / infoPtr->uIndent;
-
-          if (!(infoPtr->dwStyle & TVS_LINESATROOT)) level++;
-
-          while (wineItem->iLevel > level)
-          {
-            wineItem = wineItem->parent;
-          }
-
-          /* fall through */
-        }
-
-      case TVHT_ONITEMLABEL:
-      case TVHT_ONITEMICON:
-      case TVHT_ONITEMBUTTON:
-        TREEVIEW_Toggle(infoPtr, wineItem, TRUE);
-        break;
-
-      case TVHT_ONITEMSTATEICON:
-        if (infoPtr->dwStyle & TVS_CHECKBOXES)
-          TREEVIEW_ToggleItemState(infoPtr, wineItem);
-        else
-          TREEVIEW_Toggle(infoPtr, wineItem, TRUE);
-        break;
-    }
- }
-
- return TRUE;
-}
-
-static LRESULT
-TREEVIEW_LButtonDown(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-  TVHITTESTINFO ht;
-  BOOL bTrack;
-
-  /* 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)
-  {
-     SetFocus(infoPtr->hwnd);
-     return 0;
-  }
-
-  ht.pt.x = (LONG)(INT16)LOWORD(lParam);
-  ht.pt.y = (LONG)(INT16)HIWORD(lParam);
-
-  TREEVIEW_HitTest(infoPtr,&ht,FALSE);
-
-  bTrack = (ht.flags & TVHT_ONITEM) && !(infoPtr->dwStyle & TVS_DISABLEDRAGDROP);
-
-  /* Send NM_CLICK right away */
-  if (!bTrack)
-     if (sendNotify(infoPtr->hwnd,NM_CLICK))
-        goto setfocus;
-
-  if (ht.flags & TVHT_ONITEMBUTTON)
-  {
-    TREEVIEW_Toggle(infoPtr,ht.hItem,TRUE);
-    goto setfocus;
-  } else if (bTrack)
-  {
-    if (TREEVIEW_TrackMouse(infoPtr,ht.pt))
-    {
-      TREEVIEW_SendTreeviewDnDNotify(infoPtr,isUnicodeNotify(&infoPtr->header) ? TVN_BEGINDRAGW:TVN_BEGINDRAGA, ht.hItem, ht.pt);
-      infoPtr->dropItem = ht.hItem;
-      return 0;
-    }
-  }
-
-  if (sendNotify(infoPtr->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 ((infoPtr->dwStyle & TVS_EDITLABELS) && (ht.flags & TVHT_ONITEMLABEL) && (infoPtr->selectedItem == ht.hItem))
-  {
-    if (infoPtr->Timer & TV_EDIT_TIMER_SET)
-      KillTimer(infoPtr->hwnd,TV_EDIT_TIMER);
-
-    SetTimer(infoPtr->hwnd,TV_EDIT_TIMER,GetDoubleClickTime(),0);
-    infoPtr->Timer |= TV_EDIT_TIMER_SET;
-  } else if (ht.flags & (TVHT_ONITEMLABEL | TVHT_ONITEMICON))
-  {
-    TREEVIEW_DoSelectItem(infoPtr,TVGN_CARET,ht.hItem,TVC_BYMOUSE);
-  } else if (ht.flags & TVHT_ONITEMSTATEICON)
-  {
-    if (infoPtr->dwStyle & TVS_CHECKBOXES)
-    {
-      /* TVS_CHECKBOXES requires us to toggle the current state */
-      if (infoPtr->dwStyle & TVS_CHECKBOXES)
-        TREEVIEW_ToggleItemState(infoPtr,ht.hItem);
-    }
-  }
-
-setfocus:
-  SetFocus(infoPtr->hwnd);
-
-  return 0;
-}
-
-static LRESULT
-TREEVIEW_RButtonDown(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-   TVHITTESTINFO ht;
-
-   if (infoPtr->hwndEdit)
-   {
-      SetFocus(infoPtr->hwnd);
-      return 0;
-   }
-
-   ht.pt.x = (LONG)(INT16)LOWORD(lParam);
-   ht.pt.y = (LONG)(INT16)HIWORD(lParam);
-
-   TREEVIEW_HitTest(infoPtr,&ht,FALSE);
-
-   if (TREEVIEW_TrackMouse(infoPtr,ht.pt))
-   {
-      if (ht.hItem)
-      {
-         TREEVIEW_SendTreeviewDnDNotify(infoPtr,isUnicodeNotify(&infoPtr->header) ? TVN_BEGINRDRAGW:TVN_BEGINDRAGA, ht.hItem, ht.pt);
-         infoPtr->dropItem = ht.hItem;
-      }
-   }
-   else
-   {
-      SetFocus(infoPtr->hwnd);
-      sendNotify(infoPtr->hwnd,NM_RCLICK);
-   }
-
-   return 0;
-}
-
-static LRESULT
-TREEVIEW_RButtonUp(TREEVIEW_INFO *infoPtr, LPPOINT pPt)
-{
-    POINT pt = *pPt;
-
-    /* Change to screen coordinate for WM_CONTEXTMENU */
-    ClientToScreen(infoPtr->hwnd, &pt);
-
-    /* Send the WM_CONTEXTMENU on a right click */
-    SendMessageA( infoPtr->hwnd, WM_CONTEXTMENU, (WPARAM)infoPtr->hwnd, MAKELPARAM(pt.x, pt.y));
-    return 0;
-}
-
-static LRESULT TREEVIEW_CreateDragImage (TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-  TREEVIEW_ITEM *dragItem;
-  INT cx,cy;
-  HDC    hdc,htopdc;
-  HWND hwtop;
-  HBITMAP hbmp,hOldbmp;
-  SIZE  size;
-  RECT  rc;
-  HFONT hOldFont;
-
-  if (!(infoPtr->himlNormal)) return 0;
-  if (!dragItem || !TREEVIEW_ValidItem(infoPtr, dragItem))
-    return 0;
-
-  TREEVIEW_UpdateDispInfo(infoPtr, dragItem, TVIF_TEXT);
-
-  hwtop = GetDesktopWindow();
-  htopdc = GetDC(hwtop);
-  hdc = CreateCompatibleDC(htopdc);
-
-  hOldFont = SelectObject (hdc, infoPtr->hFont);
-  GetTextExtentPoint32W (hdc, dragItem->pszText, lstrlenW (dragItem->pszText), &size);
-
-  hbmp = CreateCompatibleBitmap (htopdc, size.cx, size.cy);
-  hOldbmp = SelectObject (hdc, hbmp);
-
-  ImageList_GetIconSize (infoPtr->himlNormal, &cx, &cy);
-  size.cx += cx;
-  if (cy > size.cy) size.cy = cy;
-
-  infoPtr->dragList = ImageList_Create (size.cx, size.cy, ILC_COLOR, 10, 10);
-  ImageList_Draw (infoPtr->himlNormal, dragItem->iImage, hdc, 0, 0, ILD_NORMAL);
-
-/*
- ImageList_GetImageInfo (infoPtr->himlNormal, dragItem->hItem, &iminfo);
- ImageList_AddMasked (infoPtr->dragList, iminfo.hbmImage, CLR_DEFAULT);
-*/
-
-  /* draw item text */
-
-  SetRect (&rc, cx, 0, size.cx,size.cy);
-  DrawTextW (hdc, dragItem->pszText, lstrlenW(dragItem->pszText), &rc, DT_LEFT);
-  SelectObject (hdc, hOldFont);
-  SelectObject (hdc, hOldbmp);
-
-  ImageList_Add (infoPtr->dragList, hbmp, 0);
-
-  DeleteDC (hdc);
-  DeleteObject (hbmp);
-  ReleaseDC (hwtop, htopdc);
-
-  return (LRESULT)infoPtr->dragList;
-}
-
-/* Selection ************************************************************/
-
-static LRESULT
-TREEVIEW_DoSelectItem(TREEVIEW_INFO *infoPtr, INT action, HTREEITEM newSelect,
-                      INT cause)
-{
-  TREEVIEW_ITEM *prevSelect;
-  BOOL refreshPrev = FALSE,refreshNew = FALSE;
-
-  assert(newSelect == NULL || TREEVIEW_ValidItem(infoPtr, newSelect));
-
-  //TRACE("Entering item %p (%s), flag %x, cause %x, state %d\n",
-  //    newSelect, TREEVIEW_ItemName(newSelect), action, cause,
-  //    newSelect ? newSelect->state : 0);
-
-  if (newSelect && newSelect->parent)
-  {
-    TREEVIEW_ITEM *parent = newSelect->parent;
-
-    /*
-     * If the item has a collapse parent expand the parent so he
-     * can expose the item
-     */
-    while (parent && !(parent->state & TVIS_EXPANDED))
-    {
-      TREEVIEW_Expand(infoPtr,parent,FALSE,FALSE);
-      parent = parent->parent;
-    }
-  }
-
-
-  switch (action)
-  {
-    case TVGN_CARET:
-      prevSelect = infoPtr->selectedItem;
-
-      if (prevSelect == newSelect)
-          return FALSE;
-
-      if (TREEVIEW_SendTreeviewNotify(infoPtr,
-                                      isUnicodeNotify(&infoPtr->header) ? TVN_SELCHANGINGW:TVN_SELCHANGINGA,
-                                      cause,
-                                      TVIF_HANDLE | TVIF_STATE | TVIF_PARAM,
-                                      prevSelect,
-                                      newSelect))
-        return FALSE;
-
-      if (prevSelect)
-      {
-        refreshPrev = prevSelect->state & TVIS_SELECTED;
-        prevSelect->state &= ~TVIS_SELECTED;
-      }
-
-      if (newSelect)
-      {
-        refreshNew = !(newSelect->state & TVIS_SELECTED);
-        newSelect->state |= TVIS_SELECTED;
-      }
-
-      infoPtr->selectedItem = newSelect;
-
-      if ((cause == TVC_BYMOUSE) && (infoPtr->dwStyle & TVS_SINGLEEXPAND))
-      {
-        BOOL control = GetKeyState(VK_CONTROL) & 0x8000;
-        UINT rc = TREEVIEW_SendTreeviewNotify(infoPtr,TVN_SINGLEEXPAND,0,TVIF_HANDLE | TVIF_STATE | TVIF_PARAM,prevSelect,newSelect);
-
-        if (!(rc & TVNRET_SKIPOLD) && !control && (prevSelect->state & TVIS_EXPANDED))
-          TREEVIEW_Collapse(infoPtr,prevSelect,FALSE,FALSE);
-        if (!(rc & TVNRET_SKIPNEW) && TREEVIEW_HasChildren(infoPtr,newSelect))
-          TREEVIEW_Toggle(infoPtr,newSelect,FALSE);
-      }
-
-      TREEVIEW_UnqueueRefresh(infoPtr,TRUE,TRUE);
-      TREEVIEW_EnsureVisible(infoPtr,infoPtr->selectedItem,FALSE);
-      if (infoPtr->dwStyle & TVS_FULLROWSELECT)
-      {
-        TREEVIEW_ITEM *item;
-
-        //deselect last selected row
-        if (prevSelect)
-        {
-          if (refreshPrev) TREEVIEW_RefreshItem(infoPtr,prevSelect,TVIF_IMAGE | TVIF_TEXT);
-          if (prevSelect->prevSibling)
-          {
-            item = prevSelect->prevSibling;
-            while (item)
-            {
-              if (item->state & TVIS_SELECTED)
-              {
-                item->state &= ~TVIS_SELECTED;
-                TREEVIEW_RefreshItem(infoPtr,item,TVIF_IMAGE | TVIF_TEXT);
-              }
-              item = item->prevSibling;
-            }
-          }
-          if (prevSelect->nextSibling)
-          {
-            item = prevSelect->nextSibling;
-            while (item)
-            {
-              if (item->state & TVIS_SELECTED)
-              {
-                item->state &= ~TVIS_SELECTED;
-                TREEVIEW_RefreshItem(infoPtr,item,TVIF_IMAGE | TVIF_TEXT);
-              }
-              item = item->nextSibling;
-            }
-          }
-        }
-
-        //select new row
-        if (newSelect)
-        {
-          if (refreshNew) TREEVIEW_RefreshItem(infoPtr,newSelect,TVIF_IMAGE | TVIF_TEXT);
-          if (newSelect->prevSibling)
-          {
-            item = newSelect->prevSibling;
-            while (item)
-            {
-              if (!(item->state & TVIS_SELECTED))
-              {
-                item->state |= TVIS_SELECTED;
-                TREEVIEW_RefreshItem(infoPtr,item,TVIF_IMAGE | TVIF_TEXT);
-              }
-              item = item->prevSibling;
-            }
-          }
-          if (newSelect->nextSibling)
-          {
-            item =  newSelect->nextSibling;
-            while (item)
-            {
-              if (!(item->state & TVIS_SELECTED))
-              {
-                item->state |= TVIS_SELECTED;
-                TREEVIEW_RefreshItem(infoPtr,item,TVIF_IMAGE | TVIF_TEXT);
-              }
-              item = item->nextSibling;
-            }
-          }
-        }
-      } else
-      {
-        if (refreshPrev) TREEVIEW_RefreshItem(infoPtr,prevSelect,TVIF_IMAGE | TVIF_TEXT);
-        if (refreshNew) TREEVIEW_RefreshItem(infoPtr,newSelect,TVIF_IMAGE | TVIF_TEXT);
-      }
-
-      TREEVIEW_SendTreeviewNotify(infoPtr,
-                                  isUnicodeNotify(&infoPtr->header) ? TVN_SELCHANGEDW:TVN_SELCHANGEDA,
-                                  cause,
-                                  TVIF_HANDLE | TVIF_STATE | TVIF_PARAM,
-                                  prevSelect,
-                                  newSelect);
-      break;
-
-    case TVGN_DROPHILITE:
-      prevSelect = infoPtr->dropItem;
-
-      if (prevSelect)
-      {
-        refreshPrev = prevSelect->state & TVIS_DROPHILITED;
-        prevSelect->state &= ~TVIS_DROPHILITED;
-      }
-
-      infoPtr->dropItem = newSelect;
-
-      if (newSelect)
-      {
-        refreshNew = !(newSelect->state & TVIS_DROPHILITED);
-        newSelect->state |= TVIS_DROPHILITED;
-      }
-
-      TREEVIEW_UnqueueRefresh(infoPtr,TRUE,TRUE);
-      if (refreshPrev) TREEVIEW_RefreshItem(infoPtr,prevSelect,TVIF_IMAGE | TVIF_TEXT);
-      if (refreshNew) TREEVIEW_RefreshItem(infoPtr,newSelect,TVIF_IMAGE | TVIF_TEXT);
-
-      break;
-
-    case TVGN_FIRSTVISIBLE:
-    {
-      TREEVIEW_ITEM *firstVis;
-      INT scrollY;
-
-      if (!infoPtr->firstVisible) return FALSE;
-
-      firstVis = infoPtr->firstVisible;
-
-      if (newSelect->rect.top < 0)
-        scrollY = newSelect->rect.top;
-      else
-      {
-        scrollY = MIN(newSelect->rect.top,(infoPtr->treeHeight-infoPtr->clientHeight)-infoPtr->lefttop.y);
-        scrollY -= scrollY % infoPtr->uItemHeight;
-      }
-
-      if (scrollY != 0)
-      {
-        infoPtr->lefttop.y += scrollY;
-        if (!TREEVIEW_UnqueueRefresh(infoPtr,TRUE,TRUE))
-          TREEVIEW_CalcItems(infoPtr);
-
-        ScrollWindowEx(infoPtr->hwnd,0,-scrollY,NULL,NULL,0,NULL,SW_INVALIDATE | SW_SCROLLCHILDREN | (infoPtr->uScrollTime << 16));
-      }
-
-      break;
-    }
-  }
-
-  //TRACE("Leaving state %d\n", newSelect ? newSelect->state : 0);
-  return TRUE;
-}
-
-/* FIXME: handle NM_KILLFOCUS etc */
-static LRESULT
-TREEVIEW_SelectItem(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    HTREEITEM item = (HTREEITEM)lParam;
-
-    if (item != NULL && !TREEVIEW_ValidItem(infoPtr, item))
-        return FALSE;
-
-    //TRACE("%p (%s) %d\n", item, TREEVIEW_ItemName(item), (int)wParam);
-
-    if (!TREEVIEW_DoSelectItem(infoPtr, wParam, item, TVC_UNKNOWN))
-        return FALSE;
-
-    return TRUE;
-}
-
-/* Scrolling ************************************************************/
-
-static LRESULT TREEVIEW_EnsureVisible(TREEVIEW_INFO *infoPtr,HTREEITEM item,BOOL bHScroll)
-{
-  RECT rect;
-  INT scrollY = 0,scrollX = 0;
-
-  if (!item) return FALSE;
-
-  if (!TREEVIEW_ValidItem(infoPtr,item))
-    return FALSE;
-
-  if (item && item->parent)
-  {
-    TREEVIEW_ITEM *parent = item->parent;
-
-    while (parent && !(parent->state & TVIS_EXPANDED))
-    {
-      TREEVIEW_Expand(infoPtr,parent,FALSE,FALSE);
-      parent = parent->parent;
-    }
-  }
-
-  TREEVIEW_UnqueueRefresh(infoPtr,TRUE,TRUE);
-  GetClientRect(infoPtr->hwnd,&rect);
-  if (item->rect.top < 0)
-    scrollY = item->rect.top;
-  else if (item->rect.bottom > rect.bottom)
-  {
-    INT mod;
-
-    scrollY = item->rect.bottom-rect.bottom;
-    mod = scrollY % infoPtr->uItemHeight;
-    if (mod) scrollY += infoPtr->uItemHeight-mod;
-  }
-
-  if (bHScroll)
-  {
-    if (!item->calculated) TREEVIEW_CalcItem(infoPtr,item,0);
-
-    if (item->textOffset < rect.left)
-      scrollX = item->textOffset-rect.left;
-    else if (item->textOffset+item->textWidth > rect.right)
-    {
-      scrollX = item->textOffset+item->textWidth-rect.right;
-      if (scrollX > item->textOffset-rect.left) scrollX = item->textOffset-rect.left;
-    }
-  }
-
-  if ((scrollY != 0) || (scrollX != 0))
-  {
-    infoPtr->lefttop.y += scrollY;
-    infoPtr->lefttop.x += scrollX;
-    TREEVIEW_CalcItems(infoPtr);
-    ScrollWindowEx(infoPtr->hwnd,-scrollX,-scrollY,NULL,NULL,0,NULL,SW_INVALIDATE | SW_SCROLLCHILDREN | (infoPtr->uScrollTime << 16));
-
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-static LRESULT
-TREEVIEW_VScroll(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  INT newY,mod;
-  INT maxY = infoPtr->treeHeight-infoPtr->clientHeight;
-
-  if (!(infoPtr->uInternalStatus & TV_VSCROLL)) return FALSE;
-
-  mod = maxY % infoPtr->uItemHeight;
-  if (mod > 0) maxY += infoPtr->uItemHeight-mod;
-
-  switch (LOWORD (wParam))
-  {
-    case SB_LINEUP:
-      newY = infoPtr->lefttop.y-infoPtr->uItemHeight;
-      if (newY < 0) newY = 0;
-      break;
-
-    case SB_LINEDOWN:
-      newY = infoPtr->lefttop.y+infoPtr->uItemHeight;
-      if (newY > maxY) newY = maxY;
-      break;
-
-    case SB_PAGEUP:
-      newY = infoPtr->lefttop.y-MAX(((INT)(infoPtr->clientHeight/infoPtr->uItemHeight))*infoPtr->uItemHeight,infoPtr->uItemHeight);
-      if (newY < 0) newY = 0;
-      break;
-
-    case SB_PAGEDOWN:
-      newY = infoPtr->lefttop.y+MAX(((INT)(infoPtr->clientHeight/infoPtr->uItemHeight))*infoPtr->uItemHeight,infoPtr->uItemHeight);
-      if (newY > maxY) newY = maxY;
-      break;
-
-    case SB_THUMBTRACK:
-      newY = HIWORD(wParam);
-      mod = newY % infoPtr->uItemHeight;
-      if (mod > 0) newY -= mod;
-      break;
-
-    default:
-      return FALSE;
-  }
-
-  if (newY != infoPtr->lefttop.y)
-  {
-    INT scrollY = infoPtr->lefttop.y-newY;
-    SCROLLINFO info;
-
-    TREEVIEW_HideInfoTip(infoPtr);
-    infoPtr->lefttop.y = newY;
-    if (!TREEVIEW_UnqueueRefresh(infoPtr,TRUE,TRUE))
-      TREEVIEW_MoveItems(infoPtr,0,scrollY);
-
-    info.cbSize = sizeof(info);
-    info.nPos   = infoPtr->lefttop.y;
-    info.fMask  = SIF_POS;
-    SetScrollInfo(infoPtr->hwnd,SB_VERT,&info,TRUE);
-
-    ScrollWindowEx(infoPtr->hwnd,0,scrollY,NULL,NULL,0,NULL,SW_INVALIDATE | SW_SCROLLCHILDREN | (infoPtr->uScrollTime << 16));
-
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-static LRESULT
-TREEVIEW_HScroll(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  int maxWidth;
-  int lastPos = infoPtr->lefttop.x;
-  SCROLLINFO info;
-
-  if (!(infoPtr->uInternalStatus & TV_HSCROLL)) return FALSE;
-
-  switch (LOWORD (wParam))
-  {
-    case SB_LINEUP:
-      if (!infoPtr->lefttop.x) return FALSE;
-      infoPtr->lefttop.x -= infoPtr->uItemHeight;
-      if (infoPtr->lefttop.x < 0) infoPtr->lefttop.x = 0;
-      break;
-
-    case SB_LINEDOWN:
-      maxWidth = infoPtr->treeWidth-infoPtr->clientWidth;
-      if (maxWidth <= 0) return FALSE;
-      if (infoPtr->lefttop.x == maxWidth) return FALSE;
-      infoPtr->lefttop.x += infoPtr->uItemHeight; /*FIXME */
-      if (infoPtr->lefttop.x > maxWidth)
-        infoPtr->lefttop.x = maxWidth;
-      break;
-
-    case SB_PAGEUP:
-      if (!infoPtr->lefttop.x) return FALSE;
-      infoPtr->lefttop.x -= infoPtr->clientWidth;
-      if (infoPtr->lefttop.x < 0) infoPtr->lefttop.x = 0;
-      break;
-
-    case SB_PAGEDOWN:
-      maxWidth = infoPtr->treeWidth-infoPtr->clientWidth;
-      if (maxWidth <= 0) return FALSE;
-      if (infoPtr->lefttop.x == maxWidth) return FALSE;
-      infoPtr->lefttop.x += infoPtr->clientWidth;
-      if (infoPtr->lefttop.x > maxWidth)
-        infoPtr->lefttop.x = maxWidth;
-      break;
-
-    case SB_THUMBTRACK:
-      maxWidth = infoPtr->treeWidth-infoPtr->clientWidth;
-      if (maxWidth <= 0) return FALSE;
-      infoPtr->lefttop.x = HIWORD(wParam);
-      if (infoPtr->lefttop.x < 0) infoPtr->lefttop.x = 0;
-      if (infoPtr->lefttop.x > maxWidth) infoPtr->lefttop.x = maxWidth;
-      break;
-
-    default:
-      return FALSE;
-  }
-
-  if (lastPos != infoPtr->lefttop.x)
-  {
-    TREEVIEW_HideInfoTip(infoPtr);
-    if (!TREEVIEW_UnqueueRefresh(infoPtr,TRUE,TRUE))
-      TREEVIEW_MoveItems(infoPtr,lastPos-infoPtr->lefttop.x,0);
-
-    info.cbSize = sizeof(info);
-    info.nPos   = infoPtr->lefttop.x;
-    info.fMask  = SIF_POS;
-    SetScrollInfo(infoPtr->hwnd,SB_HORZ,&info,TRUE);
-
-    ScrollWindowEx(infoPtr->hwnd,lastPos-infoPtr->lefttop.x,0,NULL,NULL,0,NULL,SW_INVALIDATE | SW_SCROLLCHILDREN | (infoPtr->uScrollTime << 16));
-
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-static LRESULT
-TREEVIEW_MouseWheel(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    short gcWheelDelta;
-    UINT pulScrollLines = 3;
-
-    if (infoPtr->firstVisible == NULL)
-        return TRUE;
-
-    SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &pulScrollLines, 0);
-
-    gcWheelDelta = -(short)HIWORD(wParam);
-    pulScrollLines *= (gcWheelDelta / WHEEL_DELTA);
-
-    if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
-    {
-        int wheelDy = pulScrollLines * infoPtr->uItemHeight;
-        int newDy = infoPtr->lefttop.y + wheelDy;
-        int maxDy = infoPtr->treeHeight-infoPtr->clientHeight;
-
-        if (newDy > maxDy) newDy = maxDy;
-
-        if (newDy < 0) newDy = 0;
-
-        TREEVIEW_VScroll(infoPtr, MAKEWPARAM(SB_THUMBTRACK, newDy), 0);
-    }
-    return TRUE;
-}
-
-/* Create/Destroy *******************************************************/
-
-static LRESULT
-TREEVIEW_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  LPCREATESTRUCTA lpcs = (LPCREATESTRUCTA)lParam;
-  TREEVIEW_INFO *infoPtr;
-  RECT rcClient;
-
-  /* allocate memory for info structure */
-  infoPtr = (TREEVIEW_INFO*)initControl(hwnd,sizeof(TREEVIEW_INFO));
-
-  if (!infoPtr) return 0;
-
-  /* set default settings */
-  infoPtr->hwnd = hwnd;
-  infoPtr->dwStyle = lpcs->style;
-  infoPtr->uInternalStatus = TV_CALCALL;
-  infoPtr->Timer = 0;
-  infoPtr->uNumItems = 0;
-  infoPtr->cdmode = 0;
-  infoPtr->uScrollTime = 300;   /* milliseconds */
-
-  GetClientRect(hwnd,&rcClient);
-
-  /* No scroll bars yet. */
-  infoPtr->clientWidth = rcClient.right;
-  infoPtr->clientHeight = rcClient.bottom;
-
-  infoPtr->treeWidth = 0;
-  infoPtr->treeHeight = 0;
-
-  infoPtr->uIndent = 19;
-  infoPtr->selectedItem = 0;
-  infoPtr->firstVisible = 0;
-  infoPtr->maxDisplayOrder = 0;
-  infoPtr->dropItem = 0;
-  infoPtr->insertMarkItem = 0;
-  infoPtr->insertBeforeorAfter = 0;
-
-  infoPtr->clrBk = GetSysColor(COLOR_WINDOW);
-  infoPtr->clrText = -1;        /* use system color */
-  infoPtr->clrLine = RGB(128, 128, 128);
-  infoPtr->clrInsertMark = GetSysColor(COLOR_BTNTEXT);
-
-  infoPtr->lefttop.y = 0;
-  infoPtr->lefttop.x = 0;
-
-  infoPtr->hwndEdit = 0;
-  infoPtr->wpEditOrig = NULL;
-  infoPtr->bIgnoreEditKillFocus = FALSE;
-  infoPtr->bLabelChanged = FALSE;
-
-  infoPtr->himlNormal = NULL;
-  infoPtr->himlState = NULL;
-  infoPtr->normalImageWidth = 0;
-  infoPtr->normalImageHeight = 0;
-  infoPtr->stateImageWidth = 0;
-  infoPtr->stateImageHeight = 0;
-
-  infoPtr->items = DPA_Create(16);
-
-  infoPtr->hFont = GetStockObject(DEFAULT_GUI_FONT);
-  infoPtr->hBoldFont = TREEVIEW_CreateBoldFont(infoPtr->hFont);
-
-  infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr);
-
-  infoPtr->root = TREEVIEW_AllocateItem(infoPtr);
-  infoPtr->root->state = TVIS_EXPANDED;
-  infoPtr->root->iLevel = -1;
-  infoPtr->root->displayOrder = -1;
-
-  infoPtr->pszISearch = NULL;
-  infoPtr->uISearchLen = 0;
-
-  infoPtr->tipItem = 0;
-  infoPtr->hwndToolTip = 0;
-  if (!(infoPtr->dwStyle & TVS_NOTOOLTIPS))
-  {
-    infoPtr->hwndToolTip = createToolTip(hwnd,TTF_TRACK | TTF_ABSOLUTE | TTF_TRANSPARENT,TRUE);
-    SendMessageA(infoPtr->hwndToolTip,WM_SETFONT,infoPtr->hFont,0);
-  }
-
-  if (infoPtr->dwStyle & TVS_CHECKBOXES)
-  {
-    RECT rc;
-    HBITMAP hbm, hbmOld;
-    HDC hdc;
-    int nIndex;
-
-    infoPtr->himlState = ImageList_Create(16,16,ILC_COLOR | ILC_MASK,3,0);
-
-    hdc = CreateCompatibleDC(0);
-    hbm = CreateCompatibleBitmap(hdc, 48, 16);
-    hbmOld = SelectObject(hdc, hbm);
-
-    rc.left  = 0;   rc.top    = 0;
-    rc.right = 48;  rc.bottom = 16;
-    FillRect(hdc, &rc, (HBRUSH)(COLOR_WINDOW+1));
-
-    rc.left  = 18;   rc.top    = 2;
-    rc.right = 30;   rc.bottom = 14;
-    DrawFrameControl(hdc, &rc, DFC_BUTTON,
-                     DFCS_BUTTONCHECK|DFCS_FLAT);
-
-    rc.left  = 34;   rc.right  = 46;
-    DrawFrameControl(hdc, &rc, DFC_BUTTON,
-                     DFCS_BUTTONCHECK|DFCS_FLAT|DFCS_CHECKED);
-
-    nIndex = ImageList_AddMasked(infoPtr->himlState, hbm,
-                                 GetSysColor(COLOR_WINDOW));
-    //TRACE("chckbox index %d\n", nIndex);
-    SelectObject(hdc, hbmOld);
-    DeleteObject(hbm);
-    DeleteDC(hdc);
-
-    infoPtr->stateImageWidth = 16;
-    infoPtr->stateImageHeight = 16;
-  }
-
-  return 0;
-}
-
-static LRESULT
-TREEVIEW_Destroy(TREEVIEW_INFO *infoPtr)
-{
-   TREEVIEW_RemoveTree(infoPtr);
-
-   /* tool tip is automatically destroyed: we are its owner */
-
-   /* Restore original windproc. */
-   if (infoPtr->hwndEdit)
-     SetWindowLongA(infoPtr->hwndEdit, GWL_WNDPROC,(LONG)infoPtr->wpEditOrig);
-
-   if (infoPtr->Timer & TV_REFRESH_TIMER_SET)
-     KillTimer(infoPtr->hwnd, TV_REFRESH_TIMER);
-
-   DeleteObject(infoPtr->hBoldFont);
-   COMCTL32_Free(infoPtr->pszISearch);
-   doneControl(infoPtr->hwnd);
-
-   return 0;
-}
-
-/* Miscellaneous Messages ***********************************************/
-
-static LRESULT
-TREEVIEW_ScrollKeyDown(TREEVIEW_INFO *infoPtr, WPARAM key)
-{
-    static const struct
-    {
-        unsigned char code;
-    }
-    scroll[] =
-    {
-#define SCROLL_ENTRY(dir, code) { ((dir) << 7) | (code) }
-        SCROLL_ENTRY(SB_VERT, SB_PAGEUP),       /* VK_PRIOR */
-        SCROLL_ENTRY(SB_VERT, SB_PAGEDOWN),     /* VK_NEXT */
-        SCROLL_ENTRY(SB_VERT, SB_BOTTOM),       /* VK_END */
-        SCROLL_ENTRY(SB_VERT, SB_TOP),          /* VK_HOME */
-        SCROLL_ENTRY(SB_HORZ, SB_LINEUP),       /* VK_LEFT */
-        SCROLL_ENTRY(SB_VERT, SB_LINEUP),       /* VK_UP */
-        SCROLL_ENTRY(SB_HORZ, SB_LINEDOWN),     /* VK_RIGHT */
-        SCROLL_ENTRY(SB_VERT, SB_LINEDOWN)      /* VK_DOWN */
-#undef SCROLL_ENTRY
-    };
-
-    if (key >= VK_PRIOR && key <= VK_DOWN)
-    {
-        unsigned char code = scroll[key - VK_PRIOR].code;
-
-        (((code & (1 << 7)) == (SB_HORZ << 7))
-         ? TREEVIEW_HScroll
-         : TREEVIEW_VScroll)(infoPtr, code & 0x7F, 0);
-    }
-
-    return 0;
-}
-
-/************************************************************************
- *        TREEVIEW_KeyDown
- *
- * VK_UP       Move selection to the previous non-hidden item.
- * VK_DOWN     Move selection to the next non-hidden item.
- * VK_HOME     Move selection to the first item.
- * VK_END      Move selection to the last item.
- * VK_LEFT     If expanded then collapse, otherwise move to parent.
- * VK_RIGHT    If collapsed then expand, otherwise move to first child.
- * VK_ADD      Expand.
- * VK_SUBTRACT Collapse.
- * VK_MULTIPLY Expand all.
- * VK_PRIOR    Move up GetVisibleCount items.
- * VK_NEXT     Move down GetVisibleCount items.
- * VK_BACK     Move to parent.
- * CTRL-Left,Right,Up,Down,PgUp,PgDown,Home,End: Scroll without changing selection
- */
-static LRESULT
-TREEVIEW_KeyDown(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-  /* If it is non-NULL and different, it will be selected and visible. */
-  TREEVIEW_ITEM *newSelection = NULL;
-  TREEVIEW_ITEM *prevItem = infoPtr->selectedItem;
-
-  TREEVIEW_SendKeyDownNotify(infoPtr,TVN_KEYDOWN,wParam);
-
-  //TRACE("%x %lx\n", wParam, lParam);
-
-  if (prevItem == NULL)
-      return FALSE;
-
-  if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
-      return TREEVIEW_ScrollKeyDown(infoPtr, wParam);
-
-  switch (wParam)
-  {
-    case VK_UP:
-        newSelection = TREEVIEW_GetPrevListItem(infoPtr, prevItem);
-        if (!newSelection)
-            newSelection = infoPtr->root->firstChild;
-        break;
-
-    case VK_DOWN:
-        newSelection = TREEVIEW_GetNextListItem(infoPtr, prevItem);
-        break;
-
-    case VK_HOME:
-        newSelection = infoPtr->root->firstChild;
-        break;
-
-    case VK_END:
-        newSelection = TREEVIEW_GetLastListItem(infoPtr,infoPtr->root);
-        break;
-
-    case VK_LEFT:
-        if (prevItem->state & TVIS_EXPANDED)
-        {
-            TREEVIEW_Collapse(infoPtr, prevItem, FALSE, TRUE);
-        }
-        else if (prevItem->parent != infoPtr->root)
-        {
-            newSelection = prevItem->parent;
-        }
-        break;
-
-    case VK_RIGHT:
-        if (TREEVIEW_HasChildren(infoPtr, prevItem))
-        {
-            if (!(prevItem->state & TVIS_EXPANDED))
-                TREEVIEW_Expand(infoPtr, prevItem, FALSE, TRUE);
-            else
-            {
-                newSelection = prevItem->firstChild;
-            }
-        }
-
-        break;
-
-    case VK_MULTIPLY:
-        TREEVIEW_ExpandAll(infoPtr, prevItem);
-        break;
-
-    case VK_ADD:
-        if (!(prevItem->state & TVIS_EXPANDED))
-            TREEVIEW_Expand(infoPtr, prevItem, FALSE, TRUE);
-        break;
-
-    case VK_SUBTRACT:
-        if (prevItem->state & TVIS_EXPANDED)
-            TREEVIEW_Collapse(infoPtr, prevItem, FALSE, TRUE);
-        break;
-
-    case VK_PRIOR:
-        newSelection
-            = TREEVIEW_GetListItem(infoPtr, prevItem,
-                                   -TREEVIEW_GetVisibleCount(infoPtr));
-        break;
-
-    case VK_NEXT:
-        newSelection
-            = TREEVIEW_GetListItem(infoPtr, prevItem,
-                                   TREEVIEW_GetVisibleCount(infoPtr));
-        break;
-
-    case VK_RETURN:
-      sendNotify(infoPtr->hwnd,NM_RETURN);
-      break;
-
-    case VK_BACK:
-        newSelection = prevItem->parent;
-        if (newSelection == infoPtr->root)
-            newSelection = NULL;
-        break;
-
-    case VK_SPACE:
-        if (infoPtr->dwStyle & TVS_CHECKBOXES)
-            TREEVIEW_ToggleItemState(infoPtr, prevItem);
-        break;
-  }
-
-  if (newSelection && newSelection != prevItem)
-  {
-    if (TREEVIEW_DoSelectItem(infoPtr,TVGN_CARET,newSelection,TVC_BYKEYBOARD))
-    {
-      TREEVIEW_EnsureVisible(infoPtr,newSelection,FALSE);
-    }
-  }
-
-  return FALSE;
-}
-
-static LRESULT
-TREEVIEW_Size(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-  if (wParam == SIZE_RESTORED)
-  {
-    infoPtr->clientWidth = LOWORD(lParam);
-    infoPtr->clientHeight = HIWORD(lParam);
-    if (TREEVIEW_CalcItems(infoPtr))
-      TREEVIEW_Refresh(infoPtr);
-  }
-
-  return 0;
-}
-
-static LRESULT
-TREEVIEW_StyleChanged(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  if (wParam == GWL_STYLE)
-  {
-    DWORD dwNewStyle = ((LPSTYLESTRUCT)lParam)->styleNew;
-
-    /* we have to take special care about tooltips */
-    if ((infoPtr->dwStyle ^ dwNewStyle) & TVS_NOTOOLTIPS)
-    {
-      if (infoPtr->dwStyle & TVS_NOTOOLTIPS)
-      {
-        infoPtr->hwndToolTip = createToolTip(infoPtr->hwnd,TTF_TRACK | TTF_ABSOLUTE | TTF_TRANSPARENT,TRUE);
-        SendMessageA(infoPtr->hwndToolTip,WM_SETFONT,infoPtr->hFont,0);
-      } else
-      {
-        DestroyWindow(infoPtr->hwndToolTip);
-        infoPtr->hwndToolTip = 0;
-      }
-    }
-
-    infoPtr->dwStyle = dwNewStyle;
-  }
-
-  if (infoPtr->hwndEdit) SetFocus(infoPtr->hwnd);
-
-  infoPtr->uInternalStatus |= TV_CALCALL;
-  TREEVIEW_QueueRefresh(infoPtr);
-
-  return 0;
-}
-
-static LRESULT
-TREEVIEW_SetFocus(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-  sendNotify(infoPtr->hwnd,NM_SETFOCUS);
-
-  if (!(infoPtr->dwStyle & TVS_SHOWSELALWAYS))
-  {
-    if (infoPtr->selectedItem)
-      TREEVIEW_RefreshItem(infoPtr,infoPtr->selectedItem,TVIF_IMAGE | TVIF_TEXT);
-    else if (infoPtr->firstVisible)
-      TREEVIEW_DoSelectItem(infoPtr,TVGN_CARET,infoPtr->firstVisible,TVC_UNKNOWN);
-  }
-
-  return 0;
-}
-
-static LRESULT
-TREEVIEW_KillFocus(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-  sendNotify(infoPtr->hwnd,NM_KILLFOCUS);
-
-  if (!(infoPtr->dwStyle & TVS_SHOWSELALWAYS) && infoPtr->selectedItem)
-    TREEVIEW_RefreshItem(infoPtr,infoPtr->selectedItem,TVIF_IMAGE | TVIF_TEXT);
-
-  return 0;
-}
-
-static LRESULT TREEVIEW_RButtonDoubleClick(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  sendNotify(infoPtr->hwnd,NM_RDBLCLK);
-
-  return DefWindowProcA(infoPtr->hwnd,WM_RBUTTONDBLCLK,wParam,lParam);
-}
-
-
-HTREEITEM TREEVIEW_GetInfoTipItem(TREEVIEW_INFO *infoPtr,POINT pt)
-{
-  TVHITTESTINFO ht;
-
-  ht.pt = pt;
-  TREEVIEW_HitTest(infoPtr,&ht,FALSE);
-
-  if (ht.hItem && (ht.flags & TVHT_ONITEM))
-  {
-    TREEVIEW_ITEM *item = ht.hItem;
-
-    if (item->inclient && ((item->textOffset < 0) || (item->textOffset+item->textWidth > infoPtr->clientWidth)))
-      return ht.hItem;
-  }
-
-  //check tool rect -> no flickering on tip frame
-  if (infoPtr->tipItem)
-  {
-    POINT pt2 = pt;
-    RECT rect;
-
-    GetWindowRect(infoPtr->hwndToolTip,&rect);
-    ClientToScreen(infoPtr->hwnd,&pt2);
-    return PtInRect(&rect,pt2) ? infoPtr->tipItem:0;
-  }
-
-  return 0;
-}
-
-VOID TREEVIEW_ShowInfoTip(TREEVIEW_INFO *infoPtr,TREEVIEW_ITEM *item)
-{
-  LPWSTR text;
-  BOOL mustFree = FALSE;
-  TTTOOLINFOW ti;
-  POINT pt;
-
-  if (infoPtr->dwStyle & TVS_INFOTIP)
-  {
-    NMTVGETINFOTIPW tvgit;
-    WCHAR* buf = (WCHAR*)COMCTL32_Alloc(isUnicodeNotify(&infoPtr->header) ? INFOTIPSIZE*sizeof(WCHAR):INFOTIPSIZE*sizeof(CHAR));
-
-    tvgit.pszText    = buf;
-    tvgit.cchTextMax = INFOTIPSIZE;
-    tvgit.hItem      = item;
-    tvgit.lParam     = item->lParam;
-
-    sendNotify(infoPtr->hwnd,isUnicodeNotify(&infoPtr->header) ? TVN_GETINFOTIPW:TVN_GETINFOTIPA,&tvgit.hdr);
-    if (isUnicodeNotify(&infoPtr->header))
-    {
-      if (buf != tvgit.pszText) COMCTL32_Free(buf); else mustFree = TRUE;
-      text = tvgit.pszText;
-    } else
-    {
-      text = (WCHAR*)COMCTL32_Alloc(tvgit.cchTextMax*sizeof(WCHAR));
-      mustFree = TRUE;
-      lstrcpyAtoW(text,(LPSTR)tvgit.pszText);
-      COMCTL32_Free(buf);
-    }
-  } else
-  {
-    TREEVIEW_UpdateDispInfo(infoPtr,item,TVIF_TEXT);
-    text = item->pszText;
-  }
-
-  infoPtr->tipItem = item;
-  SetTimer(infoPtr->hwnd,TV_INFOTIP_TIMER,TV_INFOTIP_DELAY,0);
-  infoPtr->Timer |= TV_INFOTIP_TIMER_SET;
-
-  ti.cbSize   = sizeof(ti);
-  ti.uId      = 0;
-  ti.hwnd     = infoPtr->hwnd;
-  ti.hinst    = 0;
-  ti.lpszText = text;
-  SendMessageA(infoPtr->hwndToolTip,TTM_TRACKACTIVATE,(WPARAM)FALSE,(LPARAM)&ti);
-  pt.x = item->textOffset;
-  pt.y = item->rect.top;
-  ClientToScreen(infoPtr->hwnd,&pt);
-  SendMessageA(infoPtr->hwndToolTip,TTM_TRACKPOSITION,0,(LPARAM)MAKELPARAM(pt.x,pt.y));
-  SendMessageA(infoPtr->hwndToolTip,TTM_UPDATETIPTEXTW,0,(LPARAM)&ti);
-  SendMessageA(infoPtr->hwndToolTip,TTM_TRACKACTIVATE,(WPARAM)TRUE,(LPARAM)&ti);
-
-  if (mustFree) COMCTL32_Free(text);
-}
-
-VOID TREEVIEW_HideInfoTip(TREEVIEW_INFO *infoPtr)
-{
-  if (infoPtr->tipItem)
-  {
-    TTTOOLINFOA ti;
-
-    infoPtr->tipItem = 0;
-    KillTimer(infoPtr->hwnd,TV_INFOTIP_TIMER);
-    infoPtr->Timer &= ~TV_INFOTIP_TIMER_SET;
-
-    ti.cbSize   = sizeof(TTTOOLINFOA);
-    ti.uId      = 0;
-    ti.hwnd     = (UINT)infoPtr->hwnd;
-
-    SendMessageA(infoPtr->hwndToolTip,TTM_TRACKACTIVATE,(WPARAM)FALSE,(LPARAM)&ti);
-  }
-}
-
-static VOID TREEVIEW_CheckInfoTip(TREEVIEW_INFO *infoPtr)
-{
-  HTREEITEM hItem;
-  POINT pt;
-
-  GetCursorPos(&pt);
-  ScreenToClient(infoPtr->hwnd,&pt);
-  hItem = TREEVIEW_GetInfoTipItem(infoPtr,pt);
-
-  if (hItem != infoPtr->tipItem)
-    TREEVIEW_HideInfoTip(infoPtr);
-}
-
-HTREEITEM TREEVIEW_GetHottrackItem(TREEVIEW_INFO *infoPtr,POINT pt)
-{
-  TVHITTESTINFO ht;
-
-  ht.pt = pt;
-  TREEVIEW_HitTest(infoPtr,&ht,FALSE);
-
-  return (ht.hItem && (ht.flags & TVHT_ONITEM)) ? ht.hItem:0;
-}
-
-static LRESULT TREEVIEW_MouseMove(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  POINT pt;
-
-  pt.x = (INT)LOWORD(lParam);
-  pt.y = (INT)HIWORD(lParam);
-
-  if (infoPtr->hwndToolTip)
-  {
-    HTREEITEM hItem = TREEVIEW_GetInfoTipItem(infoPtr,pt);
-
-    if (infoPtr->tipItem != hItem)
-    {
-      if (hItem)
-      {
-        TREEVIEW_ITEM *item = hItem;
-
-        TREEVIEW_ShowInfoTip(infoPtr,item);
-      } else TREEVIEW_HideInfoTip(infoPtr);
-    }
-  }
-
-  if (infoPtr->dwStyle & TVS_TRACKSELECT)
-  {
-    HTREEITEM hItem = TREEVIEW_GetHottrackItem(infoPtr,pt);
-
-    if (infoPtr->hotItem != hItem)
-    {
-      TREEVIEW_ITEM *item;
-      HDC hdc = 0;
-
-      item = infoPtr->hotItem;
-      if (TREEVIEW_ValidItem(infoPtr,infoPtr->hotItem))
-      {
-        if (!hdc) hdc = GetDC(infoPtr->hwnd);
-        TREEVIEW_DrawHottrackLine(hdc,item);
-      }
-      if (hItem)
-      {
-        item = hItem;
-        if (item)
-        {
-          if (!hdc) hdc = GetDC(infoPtr->hwnd);
-          TREEVIEW_DrawHottrackLine(hdc,item);
-        }
-      }
-      if (hdc) ReleaseDC(infoPtr->hwnd,hdc);
-    }
-  }
-
-  return 0;
-}
-
-static LRESULT TREEVIEW_SetRedraw(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  if (wParam)
-  {
-    if (!(infoPtr->uInternalStatus & TV_NOREDRAW)) return 0;
-    infoPtr->uInternalStatus &= ~TV_NOREDRAW;
-    TREEVIEW_CalcItems(infoPtr);
-    TREEVIEW_Refresh(infoPtr);
-  } else
-  {
-    infoPtr->uInternalStatus |= TV_NOREDRAW;
-  }
-
-  return 0;
-}
-
-static LRESULT
-TREEVIEW_SysColorChange(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  TREEVIEW_Refresh(infoPtr);
-
-  return DefWindowProcA(infoPtr->hwnd,WM_SYSCOLORCHANGE,wParam,lParam);
-}
-
-static LRESULT TREEVIEW_Enable(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  TREEVIEW_Refresh(infoPtr);
-
-  return DefWindowProcA(infoPtr->hwnd,WM_ENABLE,wParam,lParam);
-}
-
-static LRESULT
-TREEVIEW_EraseBackground(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
-{
-    HBRUSH hBrush = CreateSolidBrush (infoPtr->clrBk);
-    RECT rect;
-
-    GetClientRect (infoPtr->hwnd, &rect);
-    FillRect ((HDC)wParam, &rect, hBrush);
-    DeleteObject (hBrush);
-
-    return TRUE;
-}
-
-static LRESULT TREEVIEW_GetDlgCode(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  return DLGC_WANTARROWS | DLGC_WANTCHARS;
-}
-
-
-static LRESULT TREEVIEW_Char(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  CHAR ch = (CHAR)wParam;
-
-  TREEVIEW_ISearch(infoPtr,ch);
-
-  return 0;
-}
-
-static BOOL TREEVIEW_Compare(TREEVIEW_INFO *infoPtr,TREEVIEW_ITEM *item,LPWSTR text,INT textlen,BOOL *matchLast)
-{
-  BOOL res;
-  INT itemlen;
-
-  TREEVIEW_UpdateDispInfo(infoPtr,item,TVIF_TEXT);
-
-  itemlen = lstrlenW(item->pszText);
-  if (itemlen < textlen)
-  {
-    res = FALSE;
-  } else
-  {
-    res = (lstrcmpniW(item->pszText,text,textlen) == 0);
-  }
-  if (!res && matchLast)
-  {
-    textlen--;
-    if ((textlen > 0) && (itemlen >= textlen))
-      *matchLast = (lstrcmpniW(item->pszText,text,textlen) == 0);
-    else
-      *matchLast = FALSE;
-  }
-
-  return res;
-}
-
-static TREEVIEW_ITEM* TREEVIEW_Search(TREEVIEW_INFO *infoPtr,TREEVIEW_ITEM *item,LPWSTR text,INT textlen,TREEVIEW_ITEM **nearest)
-{
-  TREEVIEW_ITEM *start;
-  BOOL bMatchLast;
-
-  start = item;
-  if (nearest) *nearest = NULL;
-
-  //search start to end
-  while (item)
-  {
-    if (nearest)
-    {
-      if (TREEVIEW_Compare(infoPtr,item,text,textlen,(!*nearest) ? &bMatchLast:NULL))
-        return item;
-      else if (!*nearest && bMatchLast)
-        *nearest = item;
-    } else
-    {
-      if (TREEVIEW_Compare(infoPtr,item,text,textlen,NULL))
-        return item;
-    }
-    item = TREEVIEW_GetNextListItem(infoPtr,item);
-  }
-
-  item = infoPtr->root;
-
-  //search first to start
-  while (item != start)
-  {
-    if (nearest)
-    {
-      if (TREEVIEW_Compare(infoPtr,item,text,textlen,(!*nearest) ? &bMatchLast:NULL))
-        return item;
-      else if (!*nearest && bMatchLast)
-        *nearest = item;
-    } else
-    {
-      if (TREEVIEW_Compare(infoPtr,item,text,textlen,NULL))
-        return item;
-    }
-    item = TREEVIEW_GetNextListItem(infoPtr,item);
-  }
-
-  return NULL;
-}
-
-//NOTE: sister function in listview control -> sync changes
-
-static VOID TREEVIEW_ISearch(TREEVIEW_INFO *infoPtr,CHAR ch)
-{
-  LPWSTR newString;
-  INT len;
-  CHAR ch2[2];
-  TREEVIEW_ITEM *item,*nearest = NULL;
-  DWORD dwISearchTime;
-  BOOL checkNearest = TRUE;
-
-  //check timer
-  dwISearchTime = GetTickCount();
-  if ((infoPtr->uISearchLen > 0) && (TICKDIFF(infoPtr->dwISearchTime,dwISearchTime) > TV_ISEARCH_DELAY))
-  {
-    COMCTL32_Free(infoPtr->pszISearch);
-    infoPtr->pszISearch = NULL;
-    infoPtr->uISearchLen = 0;
-  }
-
-  //prepare new search string
-  len = infoPtr->uISearchLen+1;
-  newString = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
-
-  if (infoPtr->uISearchLen > 0) lstrcpyW(newString,infoPtr->pszISearch);
-
-  ch2[0] = ch;
-  ch2[1] = 0;
-  lstrcpyAtoW((LPWSTR)&newString[len-1],(LPSTR)&ch2);
-  for (INT x = 1;x < len;x++)
-  {
-    if (newString[0] != newString[x])
-    {
-      checkNearest = FALSE;
-      break;
-    }
-  }
-
-  //search
-
-  //start with selected item or root
-  if (infoPtr->selectedItem)
-  {
-    item = infoPtr->selectedItem;
-
-    //check if new string is valid for old selection
-    if (TREEVIEW_Compare(infoPtr,item,newString,len,NULL))
-      goto ISearchDone;
-
-    //no match, continue with next item
-    item = TREEVIEW_GetNextListItem(infoPtr,item);
-    if (!item) item = infoPtr->root;
-  } else item = infoPtr->root;
-
-  //scan
-  item = TREEVIEW_Search(infoPtr,item,newString,len,checkNearest ? &nearest:NULL);
-
-  if (!item && nearest)
-  {
-    TREEVIEW_SelectItem(infoPtr,(WPARAM)TVGN_CARET,(LPARAM)nearest);
-    TREEVIEW_EnsureVisible(infoPtr,nearest,FALSE);
-    infoPtr->dwISearchTime = GetTickCount();
-
-    COMCTL32_Free(newString);
-    return;
-  }
-
-ISearchDone:
-  //done
-  if (item)
-  {
-    COMCTL32_Free(infoPtr->pszISearch);
-    infoPtr->pszISearch = newString;
-    infoPtr->uISearchLen = len;
-    TREEVIEW_SelectItem(infoPtr,(WPARAM)TVGN_CARET,(LPARAM)item);
-    TREEVIEW_EnsureVisible(infoPtr,item,FALSE);
-    infoPtr->dwISearchTime = GetTickCount();
-  } else
-  {
-    COMCTL32_Free(newString);
-    MessageBeep(0xFFFFFFFF);
-  }
-}
-
-static LRESULT TREEVIEW_GetISearchString(TREEVIEW_INFO *infoPtr,LPWSTR lpsz,BOOL unicode)
-{
-  if (infoPtr->uISearchLen == 0) return 0;
-
-  if (unicode)
-    lstrcpyW(lpsz,infoPtr->pszISearch);
-  else
-    lstrcpyWtoA((LPSTR)lpsz,infoPtr->pszISearch);
-
-  return infoPtr->uISearchLen;
-}
-
-static LRESULT TREEVIEW_SetCursor(TREEVIEW_INFO *infoPtr,WPARAM wParam,LPARAM lParam)
-{
-  sendNotify(infoPtr->hwnd,NM_SETCURSOR); //CB: todo: result
-
-  return DefWindowProcA(infoPtr->hwnd,WM_SETCURSOR,wParam,lParam);
-}
-
-static LRESULT TREEVIEW_NCCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
-{
-  DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE),oldStyle = dwStyle;
-
-  dwStyle &= ~(WS_HSCROLL | WS_VSCROLL);
-  if (dwStyle != oldStyle) SetWindowLongA(hwnd,GWL_STYLE,dwStyle);
-
-  return DefWindowProcA(hwnd,WM_NCCREATE,wParam,lParam);
-}
-
-static LRESULT WINAPI
-TREEVIEW_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-    TREEVIEW_INFO *infoPtr;
-
-    if (uMsg == WM_NCCREATE)
-    {
-      return TREEVIEW_NCCreate(hwnd,wParam,lParam);
-    } else if (uMsg == WM_CREATE)
-    {
-      return TREEVIEW_Create(hwnd, wParam, lParam);
-    }
-
-    infoPtr = TREEVIEW_GetInfoPtr(hwnd);
-    if (infoPtr) TREEVIEW_VerifyTree(infoPtr); else goto def;
-
-    switch (uMsg)
-    {
-        case TVM_INSERTITEMA:
-          return TREEVIEW_InsertItem(infoPtr,wParam,lParam,FALSE);
-
-        case TVM_INSERTITEMW:
-          return TREEVIEW_InsertItem(infoPtr,wParam,lParam,TRUE);
-
-        case TVM_DELETEITEM:
-          return TREEVIEW_DeleteItem(infoPtr,wParam,lParam);
-
-        case TVM_EXPAND:
-          return TREEVIEW_ExpandMsg(infoPtr,wParam,lParam);
-
-        case TVM_GETITEMRECT:
-          return TREEVIEW_GetItemRect(infoPtr,wParam,lParam);
-
-        case TVM_GETCOUNT:
-          return TREEVIEW_GetCount(infoPtr,wParam,lParam);
-
-        case TVM_GETINDENT:
-          return TREEVIEW_GetIndent(infoPtr);
-
-        case TVM_SETINDENT:
-          return TREEVIEW_SetIndent(infoPtr,wParam);
-
-        case TVM_GETIMAGELIST:
-          return TREEVIEW_GetImageList(infoPtr,wParam,lParam);
-
-        case TVM_SETIMAGELIST:
-          return TREEVIEW_SetImageList (infoPtr, wParam, lParam);
-
-        case TVM_GETNEXTITEM:
-          return TREEVIEW_GetNextItem (infoPtr, wParam, lParam);
-
-        case TVM_SELECTITEM:
-          return TREEVIEW_SelectItem (infoPtr, wParam, lParam);
-
-        case TVM_GETITEMA:
-          return TREEVIEW_GetItem(infoPtr,wParam,lParam,FALSE);
-
-        case TVM_GETITEMW:
-          return TREEVIEW_GetItem(infoPtr,wParam,lParam,TRUE);
-
-        case TVM_SETITEMA:
-          return TREEVIEW_SetItem(infoPtr,wParam,lParam,FALSE);
-
-        case TVM_SETITEMW:
-          return TREEVIEW_SetItem(infoPtr,wParam,lParam,TRUE);
-
-        case TVM_EDITLABELA:
-          return TREEVIEW_EditLabel(infoPtr,(HTREEITEM)lParam,FALSE);
-
-        case TVM_EDITLABELW:
-          return TREEVIEW_EditLabel(infoPtr,(HTREEITEM)lParam,TRUE);
-
-        case TVM_GETEDITCONTROL:
-          return TREEVIEW_GetEditControl (infoPtr);
-
-        case TVM_GETVISIBLECOUNT:
-          return TREEVIEW_GetVisibleCount (infoPtr);
-
-        case TVM_HITTEST:
-          return TREEVIEW_HitTest(infoPtr,(LPTVHITTESTINFO)lParam,FALSE);
-
-        case TVM_CREATEDRAGIMAGE:
-          return TREEVIEW_CreateDragImage (infoPtr, wParam, lParam);
-
-        case TVM_SORTCHILDREN:
-          return TREEVIEW_SortChildren(infoPtr, wParam, lParam);
-
-        case TVM_ENSUREVISIBLE:
-          return TREEVIEW_EnsureVisible(infoPtr,(HTREEITEM)lParam,TRUE);
-
-        case TVM_SORTCHILDRENCB:
-          return TREEVIEW_SortChildrenCB(infoPtr, wParam, lParam);
-
-        case TVM_ENDEDITLABELNOW:
-          return TREEVIEW_EndEditLabelNow (infoPtr,(BOOL)wParam);
-
-        case TVM_GETISEARCHSTRINGA:
-          return TREEVIEW_GetISearchString(infoPtr,(LPWSTR)lParam,FALSE);
-
-        case TVM_GETISEARCHSTRINGW:
-          return TREEVIEW_GetISearchString(infoPtr,(LPWSTR)lParam,TRUE);
-
-        case TVM_GETTOOLTIPS:
-          return TREEVIEW_GetToolTips (infoPtr);
-
-        case TVM_SETTOOLTIPS:
-          return TREEVIEW_SetToolTips (infoPtr, wParam);
-
-        case TVM_SETINSERTMARK:
-          return TREEVIEW_SetInsertMark (infoPtr,wParam, lParam);
-
-        case TVM_SETITEMHEIGHT:
-          return TREEVIEW_SetItemHeight (infoPtr, wParam);
-
-        case TVM_GETITEMHEIGHT:
-          return TREEVIEW_GetItemHeight (infoPtr);
-
-        case TVM_SETBKCOLOR:
-          return TREEVIEW_SetBkColor (infoPtr, wParam, lParam);
-
-        case TVM_SETTEXTCOLOR:
-          return TREEVIEW_SetTextColor (infoPtr, wParam, lParam);
-
-        case TVM_GETBKCOLOR:
-          return TREEVIEW_GetBkColor (infoPtr);
-
-        case TVM_GETTEXTCOLOR:
-          return TREEVIEW_GetTextColor (infoPtr);
-
-        case TVM_SETSCROLLTIME:
-          return TREEVIEW_SetScrollTime (infoPtr, (UINT)wParam);
-
-        case TVM_GETSCROLLTIME:
-          return TREEVIEW_GetScrollTime (infoPtr);
-
-        case TVM_GETITEMSTATE:
-          return TREEVIEW_GetItemState (infoPtr,wParam, lParam);
-
-        case TVM_GETLINECOLOR:
-          return TREEVIEW_GetLineColor (infoPtr,wParam, lParam);
-
-        case TVM_SETLINECOLOR:
-          return TREEVIEW_SetLineColor (infoPtr,wParam, lParam);
-
-        case TVM_SETINSERTMARKCOLOR:
-          return TREEVIEW_SetInsertMarkColor (infoPtr,wParam, lParam);
-
-        case TVM_GETINSERTMARKCOLOR:
-          return TREEVIEW_GetInsertMarkColor (infoPtr,wParam, lParam);
-
-        case WM_COMMAND:
-          return TREEVIEW_Command (infoPtr, wParam, lParam);
-
-        case WM_DESTROY:
-          return TREEVIEW_Destroy (infoPtr);
-
-        case WM_ENABLE:
-          return TREEVIEW_Enable(infoPtr,wParam,lParam);
-
-        case WM_ERASEBKGND:
-          return TREEVIEW_EraseBackground (infoPtr, wParam, lParam);
-
-        case WM_GETDLGCODE:
-          return TREEVIEW_GetDlgCode(infoPtr,wParam,lParam);
-
-        case WM_PAINT:
-          return TREEVIEW_Paint (infoPtr, wParam, lParam);
-
-        case WM_GETFONT:
-          return TREEVIEW_GetFont (infoPtr, wParam, lParam);
-
-        case WM_SETFONT:
-          return TREEVIEW_SetFont (infoPtr, wParam, lParam);
-
-        case WM_KEYDOWN:
-          return TREEVIEW_KeyDown (infoPtr, wParam, lParam);
-
-        case WM_CHAR:
-          return TREEVIEW_Char(infoPtr,wParam,lParam);
-
-        case WM_SETFOCUS:
-          return TREEVIEW_SetFocus (infoPtr, wParam, lParam);
-
-        case WM_KILLFOCUS:
-          return TREEVIEW_KillFocus (infoPtr, wParam, lParam);
-
-        case WM_MOUSEMOVE:
-          return TREEVIEW_MouseMove(infoPtr,wParam,lParam);
-
-        case WM_LBUTTONDOWN:
-          return TREEVIEW_LButtonDown (infoPtr, wParam, lParam);
-
-        case WM_LBUTTONDBLCLK:
-          return TREEVIEW_LButtonDoubleClick (infoPtr, wParam, lParam);
-
-        case WM_RBUTTONDOWN:
-          return TREEVIEW_RButtonDown (infoPtr, wParam, lParam);
-
-        case WM_RBUTTONDBLCLK:
-          return TREEVIEW_RButtonDoubleClick(infoPtr,wParam,lParam);
-
-        case WM_STYLECHANGED:
-          return TREEVIEW_StyleChanged (infoPtr, wParam, lParam);
-
-        case WM_SYSCOLORCHANGE:
-          return TREEVIEW_SysColorChange(infoPtr,wParam,lParam);
-
-        case WM_SETCURSOR:
-          return TREEVIEW_SetCursor(infoPtr,wParam,lParam);
-
-        case WM_SETREDRAW:
-          return TREEVIEW_SetRedraw(infoPtr,wParam,lParam);
-
-        case WM_TIMER:
-          return TREEVIEW_HandleTimer (infoPtr, wParam, lParam);
-
-        case WM_SIZE:
-          return TREEVIEW_Size (infoPtr, wParam,lParam);
-
-        case WM_HSCROLL:
-          return TREEVIEW_HScroll (infoPtr, wParam, lParam);
-
-        case WM_VSCROLL:
-          return TREEVIEW_VScroll (infoPtr, wParam, lParam);
-
-        case WM_MOUSEWHEEL:
-          return TREEVIEW_MouseWheel (infoPtr, wParam, lParam);
-
-        case WM_DRAWITEM:
-          //printf ("drawItem\n");
-           return DefWindowProcA (hwnd, uMsg, wParam, lParam);
-
-        default:
-def:
-          return defComCtl32ProcA(hwnd,uMsg,wParam,lParam);
-      }
-    return 0;
-}
-
-/* Tree Verification ****************************************************/
-
-#ifndef NDEBUG
-static inline void
-TREEVIEW_VerifyChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item);
-
-static inline void TREEVIEW_VerifyItemCommon(TREEVIEW_INFO *infoPtr,
-                                             TREEVIEW_ITEM *item)
-{
-    TREEVIEW_WriteVerify("TV: checking infoPtr");
-    assert(infoPtr != NULL);
-    TREEVIEW_WriteVerify("TV: checking item");
-    assert(item != NULL);
-
-    /* both NULL, or both non-null */
-    TREEVIEW_WriteVerify("TV: checking firstChild,lastChild");
-    assert((item->firstChild == NULL) == (item->lastChild == NULL));
-
-    TREEVIEW_WriteVerify("TV: checking firstChild,lastChild != item");
-    assert(item->firstChild != item);
-    assert(item->lastChild != item);
-
-    TREEVIEW_WriteVerify("TV: checking firstChild");
-    if (item->firstChild)
-    {
-        assert(item->firstChild->parent == item);
-        assert(item->firstChild->prevSibling == NULL);
-    }
-
-    TREEVIEW_WriteVerify("TV: checking lastChild");
-    if (item->lastChild)
-    {
-        TREEVIEW_WriteVerify("TV: checking lastChild->parent");
-        assert(item->lastChild->parent == item);
-        TREEVIEW_WriteVerify("TV: checking lastChild->nextSibling");
-        assert(item->lastChild->nextSibling == NULL);
-    }
-
-    TREEVIEW_WriteVerify("TV: checking nextSibling");
-    assert(item->nextSibling != item);
-    if (item->nextSibling)
-    {
-        assert(item->nextSibling->parent == item->parent);
-        assert(item->nextSibling->prevSibling == item);
-    }
-
-    TREEVIEW_WriteVerify("TV: checking prevSibling");
-    assert(item->prevSibling != item);
-    if (item->prevSibling)
-    {
-        assert(item->prevSibling->parent == item->parent);
-        assert(item->prevSibling->nextSibling == item);
-    }
-}
-
-static inline void
-TREEVIEW_VerifyItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
-{
-    TREEVIEW_WriteVerify("TV: checking item");
-    assert(item != NULL);
-
-    TREEVIEW_WriteVerify("TV: checking parent, iLevel");
-    assert(item->parent != NULL);
-    assert(item->parent != item);
-    assert(item->iLevel == item->parent->iLevel + 1);
-
-    TREEVIEW_WriteVerify("TV: checking PtrIndex");
-    assert(DPA_GetPtrIndex(infoPtr->items, item) != -1);
-
-    TREEVIEW_VerifyItemCommon(infoPtr, item);
-
-    TREEVIEW_VerifyChildren(infoPtr, item);
-}
-
-static inline void
-TREEVIEW_VerifyChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
-{
-    TREEVIEW_ITEM *child;
-    assert(item != NULL);
-
-    for (child = item->firstChild; child != NULL; child = child->nextSibling)
-        TREEVIEW_VerifyItem(infoPtr, child);
-}
-
-static inline void
-TREEVIEW_VerifyRoot(TREEVIEW_INFO *infoPtr)
-{
-    TREEVIEW_ITEM *root = infoPtr->root;
-
-    TREEVIEW_WriteVerify("TV: checking root");
-    assert(root != NULL);
-    TREEVIEW_WriteVerify("TV: checking iLevel");
-    assert(root->iLevel == -1);
-    TREEVIEW_WriteVerify("TV: checking parent");
-    assert(root->parent == NULL);
-    TREEVIEW_WriteVerify("TV: checking prevSibling");
-    assert(root->prevSibling == NULL);
-
-    TREEVIEW_VerifyItemCommon(infoPtr, root);
-
-    TREEVIEW_VerifyChildren(infoPtr, root);
-}
-
-static void
-TREEVIEW_VerifyTree(TREEVIEW_INFO *infoPtr)
-{
-  TREEVIEW_WriteVerify("TV: checking infoPtr");
-  assert(infoPtr != NULL);
-
-  TREEVIEW_VerifyRoot(infoPtr);
-}
-#endif
-
-/* Class Registration ***************************************************/
-
-VOID TREEVIEW_Register (VOID)
-{
-    WNDCLASSA wndClass;
-
-    ZeroMemory (&wndClass, sizeof(WNDCLASSA));
-    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
-    wndClass.lpfnWndProc   = (WNDPROC)TREEVIEW_WindowProc;
-    wndClass.cbClsExtra    = 0;
-    wndClass.cbWndExtra    = sizeof(TREEVIEW_INFO *);
-    wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
-    wndClass.hbrBackground = 0;
-    wndClass.lpszClassName = WC_TREEVIEWA;
-
-    RegisterClassA (&wndClass);
-}
-
-
-VOID TREEVIEW_Unregister (VOID)
-{
-    UnregisterClassA (WC_TREEVIEWA, (HINSTANCE)NULL);
-}
Index: trunk/src/comctl32/treeview.h
===================================================================
--- trunk/src/comctl32/treeview.h	(revision 10097)
+++ 	(revision )
@@ -1,137 +1,0 @@
-/* $Id: treeview.h,v 1.1 2002-10-29 13:47:35 sandervl Exp $ */
-/*
- * Treeview class extra info
- *
- * Copyright 1998 Eric Kohl
- * Copyright 1998 Alex Priem
- * Copyright 2000 Christoph Bratschi
- */
-
-#ifndef __WINE_TREEVIEW_H
-#define __WINE_TREEVIEW_H
-
-#define ITEM_VSPACE            2
-#define TV_REFRESH_DELAY     100     /* 100 ms delay between two refreshes */
-#define TV_DEFAULTITEMHEIGHT  16
-#define TVITEM_ALLOC          32      /* default nr of items to allocate at first try */
-#define TV_ISEARCH_DELAY     1000 //documented in ListView_Message_Processing.htm
-#define TV_INFOTIP_DELAY     500
-
-
-/* internal structures */
-
-typedef struct _TREEITEM    /* HTREEITEM is a _TREEINFO *. */
-{
-  UINT      callbackMask;
-  UINT      state;
-  UINT      stateMask;
-  LPWSTR    pszText;
-  int       cchTextMax;
-  int       iImage;
-  int       iSelectedImage;
-  int       cChildren;
-  LPARAM    lParam;
-  int       iIntegral;      /* item height multiplier (1 is normal) */
-  int       iLevel;         /* indentation level:0=root level */
-  HTREEITEM parent;         /* handle to parent or 0 if at root*/
-  HTREEITEM firstChild;     /* handle to first child or 0 if no child*/
-  HTREEITEM lastChild;
-  HTREEITEM prevSibling;    /* handle to prev item in list, 0 if first */
-  HTREEITEM nextSibling;    /* handle to next item in list, 0 if last */
-  RECT      rect;
-  LONG      linesOffset;
-  LONG      stateOffset;
-  LONG      imageOffset;
-  LONG      textOffset;
-  LONG      textWidth;      /* horizontal text extent for pszText */
-  LONG      textHeight;
-  BOOL      inclient;       // displayed in client rect
-  BOOL      displayed;      // item is displayed
-  int       displayOrder;   /* display ordering, 0 is first display item */
-
-  BOOL      calculated;     //rect is valid
-} TREEVIEW_ITEM, *LPTREEVIEW_ITEM;
-
-typedef struct tagTREEVIEW_INFO
-{
-  COMCTL32_HEADER header;
-
-  HWND          hwnd;
-  DWORD         dwStyle;
-  HTREEITEM     root;
-  UINT          uInternalStatus;
-  INT           Timer;
-  UINT          uNumItems;      /* number of valid TREEVIEW_ITEMs */
-  INT           cdmode;         /* last custom draw setting */
-  UINT          uScrollTime;    /* max. time for scrolling in milliseconds*/
-
-  UINT          uItemHeight;    /* item height */
-  BOOL          bHeightSet;
-
-  LONG          clientWidth;    /* width of control window */
-  LONG          clientHeight;   /* height of control window */
-
-  LONG          treeWidth;      /* width of displayed tree items */
-  LONG          treeHeight;     /* height of displayed tree items */
-
-  UINT          uIndent;        /* indentation in pixels */
-  HTREEITEM     selectedItem;   /* handle to selected item or 0 if none */
-  HTREEITEM     focusItem;      /* handle to item that has focus, 0 if none */
-  HTREEITEM     hotItem;        /* handle currently under cursor, 0 if none */
-  HTREEITEM     firstVisible;   /* handle to first visible item */
-  int           maxDisplayOrder;
-  HTREEITEM     dropItem;       /* handle to item selected by drag cursor */
-  HTREEITEM     insertMarkItem; /* item after which insertion mark is placed */
-  BOOL          insertBeforeorAfter; /* flag used by TVM_SETINSERTMARK */
-  HIMAGELIST    dragList;       /* Bitmap of dragged item */
-  COLORREF      clrBk;
-  COLORREF      clrText;
-  COLORREF      clrLine;
-  COLORREF      clrInsertMark;
-  HFONT         hFont;
-  HFONT         hBoldFont;
-  HWND          hwndToolTip;
-
-  HWND          hwndEdit;
-  WNDPROC       wpEditOrig;     /* orig window proc for subclassing edit */
-  BOOL          bIgnoreEditKillFocus;
-  BOOL          bLabelChanged;
-
-  HIMAGELIST    himlNormal;
-  int           normalImageHeight;
-  int           normalImageWidth;
-  HIMAGELIST    himlState;
-  int           stateImageHeight;
-  int           stateImageWidth;
-  HDPA          items;
-
-  HTREEITEM       tipItem;        // item with tooltip
-  POINT           lefttop;        //in pixels
-
-  LPWSTR          pszISearch;
-  UINT            uISearchLen;
-  DWORD           dwISearchTime;
-} TREEVIEW_INFO, *LPTREEVIEW_INFO;
-
-/* bitflags for infoPtr->uInternalStatus */
-
-#define TV_HSCROLL      0x001    /* treeview too large to fit in window */
-#define TV_VSCROLL      0x002    /* (horizontal/vertical) */
-#define TV_LDRAG        0x004    /* Lbutton pushed to start drag */
-#define TV_LDRAGGING    0x008    /* Lbutton pushed, mouse moved.  */
-#define TV_RDRAG        0x010    /* dito Rbutton */
-#define TV_RDRAGGING    0x020
-#define TV_NOREDRAW     0x040
-#define TV_CALCALL      0x080
-
-/* bitflags for infoPtr->timer */
-
-#define TV_REFRESH_TIMER 1
-#define TV_EDIT_TIMER    2
-#define TV_INFOTIP_TIMER 3
-
-#define TV_REFRESH_TIMER_SET 1
-#define TV_EDIT_TIMER_SET    2
-#define TV_INFOTIP_TIMER_SET 4
-
-#endif  /* __WINE_TREEVIEW_H */
