Index: trunk/src/comctl32/animate.c
===================================================================
--- trunk/src/comctl32/animate.c	(revision 5627)
+++ trunk/src/comctl32/animate.c	(revision 5630)
@@ -4,5 +4,5 @@
  *
  * Copyright 1998, 1999 Eric Kohl
- *         1999 Eric Pouech
+ * 		   1999 Eric Pouech
  *
  * NOTES
@@ -15,10 +15,9 @@
  */
 
-
+#include <string.h>
 #include "winbase.h"
 #include "commctrl.h"
 #include "vfw.h"
 #include "mmsystem.h"
-#include "services.h"
 #include "debugtools.h"
 #ifdef __WIN32OS2__
@@ -31,79 +30,43 @@
 {
 #ifdef __WIN32OS2__
-    COMCTL32_HEADER header;
-#endif
-
-   /* pointer to msvideo functions. it's easier to put them here.
-    * to be correct, they should be defined on a per process basis, but
-    * this would required a per process storage. We're using a per object
-    * storage instead, which is not efficient on memory usage, but
-    * will lead to less bugs in the future
-    */
-#ifdef __WIN32OS2__
-   HIC      (* WINAPI fnICOpen)(DWORD, DWORD, UINT);
-   LRESULT  (* WINAPI fnICClose)(HIC);
-   LRESULT  (* WINAPI fnICSendMessage)(HIC, UINT, DWORD, DWORD);
-   DWORD    (* WINAPIV fnICDecompress)(HIC,DWORD,LPBITMAPINFOHEADER,LPVOID,LPBITMAPINFOHEADER,LPVOID);
-
-    HMMIO (* WINAPI fnmmioOpenA)(LPSTR,MMIOINFO*,DWORD);
-    HMMIO (* WINAPI fnmmioOpenW)(LPSTR,MMIOINFO*,DWORD);
-    MMRESULT (* WINAPI fnmmioClose)(HMMIO,UINT);
-    UINT  (* WINAPI fnmmioAscend)(HMMIO,MMCKINFO*,UINT);
-    UINT  (* WINAPI fnmmioDescend)(HMMIO,MMCKINFO*,const MMCKINFO*,UINT);
-    LONG  (* WINAPI fnmmioSeek)(HMMIO,LONG,INT);
-    LONG  (* WINAPI fnmmioRead)(HMMIO,HPSTR,LONG);
-#else
-   HIC      WINAPI  (*fnICOpen)(DWORD, DWORD, UINT);
-   LRESULT  WINAPI  (*fnICClose)(HIC);
-   LRESULT  WINAPI  (*fnICSendMessage)(HIC, UINT, DWORD, DWORD);
-   DWORD    WINAPIV (*fnICDecompress)(HIC,DWORD,LPBITMAPINFOHEADER,LPVOID,LPBITMAPINFOHEADER,LPVOID);
-
-    HMMIO WINAPI (*fnmmioOpenA)(LPSTR,MMIOINFO*,DWORD);
-    MMRESULT WINAPI (*fnmmioClose)(HMMIO,UINT);
-    UINT  WINAPI (*fnmmioAscend)(HMMIO,MMCKINFO*,UINT);
-    UINT  WINAPI (*fnmmioDescend)(HMMIO,MMCKINFO*,const MMCKINFO*,UINT);
-    LONG  WINAPI (*fnmmioSeek)(HMMIO,LONG,INT);
-    LONG  WINAPI (*fnmmioRead)(HMMIO,HPSTR,LONG);
-#endif
-
+   COMCTL32_HEADER      header;
+#endif
    /* reference to input stream (file or resource) */
-   HGLOBAL      hRes;
-   HMMIO            hMMio;  /* handle to mmio stream */
-   HWND         hWnd;
+   HGLOBAL 		hRes;
+   HMMIO		hMMio;	/* handle to mmio stream */
+   HWND			hWnd;
    /* information on the loaded AVI file */
-   MainAVIHeader    mah;
-   AVIStreamHeader  ash;
-   LPBITMAPINFOHEADER   inbih;
-   LPDWORD      lpIndex;
+   MainAVIHeader	mah;
+   AVIStreamHeader	ash;
+   LPBITMAPINFOHEADER	inbih;
+   LPDWORD		lpIndex;
    /* data for the decompressor */
-   HIC          hic;
-   LPBITMAPINFOHEADER   outbih;
-   LPVOID       indata;
-   LPVOID       outdata;
+   HIC			hic;
+   LPBITMAPINFOHEADER	outbih;
+   LPVOID		indata;
+   LPVOID		outdata;
    /* data for the background mechanism */
-   CRITICAL_SECTION cs;
-   HANDLE       hThread;
-   UINT         uTimer;
+   CRITICAL_SECTION	cs;
+   HANDLE		hThread;
+   UINT			uTimer;
    /* data for playing the file */
-   int          nFromFrame;
-   int          nToFrame;
-   int          nLoop;
-   int          currFrame;
+   int			nFromFrame;
+   int			nToFrame;
+   int			nLoop;
+   int			currFrame;
    /* tranparency info*/
-   COLORREF             transparentColor;
-   HBRUSH               hbrushBG;
-   HBITMAP              hbmPrevFrame;
+   COLORREF         	transparentColor;   
+   HBRUSH           	hbrushBG;
+   HBITMAP  	    	hbmPrevFrame;
 } ANIMATE_INFO;
 
 #define ANIMATE_GetInfoPtr(hWnd) ((ANIMATE_INFO *)GetWindowLongA(hWnd, 0))
-#define ANIMATE_COLOR_NONE      0xffffffff
-
-HMODULE hModWinmm;
+#define ANIMATE_COLOR_NONE  	0xffffffff
 
 static void ANIMATE_Notify(ANIMATE_INFO* infoPtr, UINT notif)
 {
-    SendMessageA(GetParent(infoPtr->hWnd), WM_COMMAND,
-         MAKEWPARAM(GetDlgCtrlID(infoPtr->hWnd), notif),
-         (LPARAM)infoPtr->hWnd);
+    SendMessageA(GetParent(infoPtr->hWnd), WM_COMMAND, 
+		 MAKEWPARAM(GetDlgCtrlID(infoPtr->hWnd), notif), 
+		 (LPARAM)infoPtr->hWnd);
 }
 
@@ -114,8 +77,8 @@
 #endif
 {
-    HRSRC   hrsrc;
-    MMIOINFO    mminfo;
-    LPVOID  lpAvi;
-
+    HRSRC 	hrsrc;
+    MMIOINFO	mminfo;
+    LPVOID	lpAvi;
+    
 #ifdef __WIN32OS2__
     if (unicode)
@@ -127,23 +90,22 @@
 #endif
     if (!hrsrc)
-    return FALSE;
-
+	return FALSE;
+    
     infoPtr->hRes = LoadResource(hInst, hrsrc);
     if (!infoPtr->hRes)
-    return FALSE;
-
+ 	return FALSE;
+    
     lpAvi = LockResource(infoPtr->hRes);
     if (!lpAvi)
-    return FALSE;
-
+	return FALSE;
+    
     memset(&mminfo, 0, sizeof(mminfo));
     mminfo.fccIOProc = FOURCC_MEM;
     mminfo.pchBuffer = (LPSTR)lpAvi;
     mminfo.cchBuffer = SizeofResource(hInst, hrsrc);
-    infoPtr->hMMio = infoPtr->fnmmioOpenA(NULL, &mminfo, MMIO_READ);
-
+    infoPtr->hMMio = mmioOpenA(NULL, &mminfo, MMIO_READ);
     if (!infoPtr->hMMio) {
-    GlobalFree((HGLOBAL)lpAvi);
-    return FALSE;
+	GlobalFree((HGLOBAL)lpAvi);
+	return FALSE;
     }
 
@@ -160,15 +122,14 @@
 #ifdef __WIN32OS2__
     if (unicode)
-      infoPtr->hMMio = infoPtr->fnmmioOpenW(lpName,NULL,MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
+      infoPtr->hMMio = mmioOpenW(lpName,NULL,MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
     else
-      infoPtr->hMMio = infoPtr->fnmmioOpenA((LPSTR)lpName,NULL,MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
+      infoPtr->hMMio = mmioOpenA((LPSTR)lpName,NULL,MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
 #else
-    infoPtr->hMMio = infoPtr->fnmmioOpenA((LPSTR)lpName, NULL,
-                   MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
-#endif
-
+    infoPtr->hMMio = mmioOpenA((LPSTR)lpName, NULL,
+			       MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
+#endif
     if (!infoPtr->hMMio)
-    return FALSE;
-
+	return FALSE;
+    
     return TRUE;
 }
@@ -180,13 +141,13 @@
 
     /* should stop playing */
-    if (infoPtr->hThread)
+    if (infoPtr->hThread) 
     {
         if (!TerminateThread(infoPtr->hThread,0))
             WARN("could not destroy animation thread!\n");
-        infoPtr->hThread = 0;
+	    infoPtr->hThread = 0;
     }
     if (infoPtr->uTimer) {
-    KillTimer(infoPtr->hWnd, infoPtr->uTimer);
-    infoPtr->uTimer = 0;
+	KillTimer(infoPtr->hWnd, infoPtr->uTimer);
+	infoPtr->uTimer = 0;
     }
 
@@ -202,74 +163,74 @@
 {
     if (infoPtr->hMMio) {
-    ANIMATE_DoStop(infoPtr);
-    infoPtr->fnmmioClose(infoPtr->hMMio, 0);
-    if (infoPtr->hRes) {
-        FreeResource(infoPtr->hRes);
-        infoPtr->hRes = 0;
-    }
-    if (infoPtr->lpIndex) {
-        HeapFree(GetProcessHeap(), 0, infoPtr->lpIndex);
-        infoPtr->lpIndex = NULL;
-    }
-    if (infoPtr->hic) {
-        (infoPtr->fnICClose)(infoPtr->hic);
-        infoPtr->hic = 0;
-    }
-    if (infoPtr->inbih) {
-        HeapFree(GetProcessHeap(), 0, infoPtr->inbih);
-        infoPtr->inbih = NULL;
-    }
-    if (infoPtr->outbih) {
-        HeapFree(GetProcessHeap(), 0, infoPtr->outbih);
-        infoPtr->outbih = NULL;
-    }
+	ANIMATE_DoStop(infoPtr);
+	mmioClose(infoPtr->hMMio, 0);
+	if (infoPtr->hRes) {
+ 	    FreeResource(infoPtr->hRes);
+	    infoPtr->hRes = 0;
+	}
+	if (infoPtr->lpIndex) {
+	    HeapFree(GetProcessHeap(), 0, infoPtr->lpIndex);
+	    infoPtr->lpIndex = NULL;
+	}
+	if (infoPtr->hic) {
+	    ICClose(infoPtr->hic);
+	    infoPtr->hic = 0;
+	}
+	if (infoPtr->inbih) {
+	    HeapFree(GetProcessHeap(), 0, infoPtr->inbih);
+	    infoPtr->inbih = NULL;
+	}
+	if (infoPtr->outbih) {
+	    HeapFree(GetProcessHeap(), 0, infoPtr->outbih);
+	    infoPtr->outbih = NULL;
+	}
         if( infoPtr->indata )
         {
-    HeapFree(GetProcessHeap(), 0, infoPtr->indata);
+	HeapFree(GetProcessHeap(), 0, infoPtr->indata);
             infoPtr->indata = NULL;
         }
-        if( infoPtr->outdata )
+    	if( infoPtr->outdata )
         {
-    HeapFree(GetProcessHeap(), 0, infoPtr->outdata);
+	HeapFree(GetProcessHeap(), 0, infoPtr->outdata);
             infoPtr->outdata = NULL;
         }
-        if( infoPtr->hbmPrevFrame )
+    	if( infoPtr->hbmPrevFrame )
         {
-        DeleteObject(infoPtr->hbmPrevFrame);
+	    DeleteObject(infoPtr->hbmPrevFrame);
             infoPtr->hbmPrevFrame = 0;
         }
-    infoPtr->indata = infoPtr->outdata = NULL;
-    infoPtr->hWnd = 0;
-    infoPtr->hMMio = 0;
-
-    memset(&infoPtr->mah, 0, sizeof(infoPtr->mah));
-    memset(&infoPtr->ash, 0, sizeof(infoPtr->ash));
-    infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0;
-    }
-    infoPtr->transparentColor = ANIMATE_COLOR_NONE;
+	infoPtr->indata = infoPtr->outdata = NULL;
+	infoPtr->hWnd = 0;
+	infoPtr->hMMio = 0;
+	
+	memset(&infoPtr->mah, 0, sizeof(infoPtr->mah));
+	memset(&infoPtr->ash, 0, sizeof(infoPtr->ash));
+	infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0;
+    }
+    infoPtr->transparentColor = ANIMATE_COLOR_NONE;    
 }
 
 static void ANIMATE_TransparentBlt(ANIMATE_INFO* infoPtr, HDC hdcDest, HDC hdcSource)
-{
+{       
     HDC hdcMask;
     HBITMAP hbmMask;
-    HBITMAP hbmOld;
-
+    HBITMAP hbmOld;            
+    
     /* create a transparency mask */
     hdcMask = CreateCompatibleDC(hdcDest);
-    hbmMask = CreateBitmap(infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 1,1,NULL);
-    hbmOld = SelectObject(hdcMask, hbmMask);
+    hbmMask = CreateBitmap(infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 1,1,NULL);   
+    hbmOld = SelectObject(hdcMask, hbmMask);             
 
     SetBkColor(hdcSource,infoPtr->transparentColor);
     BitBlt(hdcMask,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCCOPY);
-
+            
     /* mask the source bitmap */
-    SetBkColor(hdcSource, RGB(0,0,0));
-    SetTextColor(hdcSource, RGB(255,255,255));
+    SetBkColor(hdcSource, RGB(0,0,0));          
+    SetTextColor(hdcSource, RGB(255,255,255)); 
     BitBlt(hdcSource, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND);
 
     /* mask the destination bitmap */
-    SetBkColor(hdcDest, RGB(255,255,255));
-    SetTextColor(hdcDest, RGB(0,0,0));
+    SetBkColor(hdcDest, RGB(255,255,255));   
+    SetTextColor(hdcDest, RGB(0,0,0));         
     BitBlt(hdcDest, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND);
 
@@ -297,5 +258,5 @@
 
     if (!hDC || !infoPtr->inbih)
-    return TRUE;
+	return TRUE;
 
     if (infoPtr->hic )
@@ -305,13 +266,13 @@
 
         nWidth = infoPtr->outbih->biWidth;
-        nHeight = infoPtr->outbih->biHeight;
+        nHeight = infoPtr->outbih->biHeight;  
     } else
-    {
+    {  
         pBitmapData = infoPtr->indata;
         pBitmapInfo = (LPBITMAPINFO)infoPtr->inbih;
 
         nWidth = infoPtr->inbih->biWidth;
-        nHeight = infoPtr->inbih->biHeight;
-    }
+        nHeight = infoPtr->inbih->biHeight;  
+    }  
 
     if(!infoPtr->hbmPrevFrame)
@@ -320,31 +281,31 @@
     }
 
-    SetDIBits(hDC, infoPtr->hbmPrevFrame, 0, nHeight, pBitmapData, (LPBITMAPINFO)pBitmapInfo, DIB_RGB_COLORS);
-
+    SetDIBits(hDC, infoPtr->hbmPrevFrame, 0, nHeight, pBitmapData, (LPBITMAPINFO)pBitmapInfo, DIB_RGB_COLORS); 
+    
     hdcMem = CreateCompatibleDC(hDC);
     hbmOld = SelectObject(hdcMem, infoPtr->hbmPrevFrame);
 
-    /*
-     * we need to get the transparent color even without ACS_TRANSPARENT,
+    /* 
+     * we need to get the transparent color even without ACS_TRANSPARENT, 
      * because the style can be changed later on and the color should always
-     * be obtained in the first frame
+     * be obtained in the first frame 
      */
     if(infoPtr->transparentColor == ANIMATE_COLOR_NONE)
     {
         infoPtr->transparentColor = GetPixel(hdcMem,0,0);
-    }
-
-    if(GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT)
-    {
+    } 
+
+    if(GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT) 
+    { 
         HDC hdcFinal = CreateCompatibleDC(hDC);
         HBITMAP hbmFinal = CreateCompatibleBitmap(hDC,nWidth, nHeight);
         HBITMAP hbmOld2 = SelectObject(hdcFinal, hbmFinal);
         RECT rect;
-
+	
         rect.left = 0;
         rect.top = 0;
         rect.right = nWidth;
         rect.bottom = nHeight;
-
+        
         if(!infoPtr->hbrushBG)
             infoPtr->hbrushBG = GetCurrentObject(hDC, OBJ_BRUSH);
@@ -359,14 +320,14 @@
         infoPtr->hbmPrevFrame = hbmFinal;
          }
-
-    if (GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_CENTER)
+    
+    if (GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_CENTER) 
     {
-       RECT rect;
+       RECT rect;   
 
        GetWindowRect(infoPtr->hWnd, &rect);
-       nOffsetX = ((rect.right - rect.left) - nWidth)/2;
-       nOffsetY = ((rect.bottom - rect.top) - nHeight)/2;
-    }
-    BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY);
+       nOffsetX = ((rect.right - rect.left) - nWidth)/2; 
+       nOffsetY = ((rect.bottom - rect.top) - nHeight)/2;  
+    }
+    BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY);    
 
     SelectObject(hdcMem, hbmOld);
@@ -377,5 +338,5 @@
 static LRESULT ANIMATE_DrawFrame(ANIMATE_INFO* infoPtr)
 {
-    HDC     hDC;
+    HDC		hDC;
 
     TRACE("Drawing frame %d (loop %d)\n", infoPtr->currFrame, infoPtr->nLoop);
@@ -383,29 +344,29 @@
     EnterCriticalSection(&infoPtr->cs);
 
-    infoPtr->fnmmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET);
-    infoPtr->fnmmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize);
-
+    mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET);
+    mmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize);
+    
     if (infoPtr->hic &&
-    (infoPtr->fnICDecompress)(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata,
-                  infoPtr->outbih, infoPtr->outdata) != ICERR_OK) {
+	ICDecompress(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata, 
+		     infoPtr->outbih, infoPtr->outdata) != ICERR_OK) {
+	LeaveCriticalSection(&infoPtr->cs);
+	WARN("Decompression error\n");
+	return FALSE;
+    }
+
+    if ((hDC = GetDC(infoPtr->hWnd)) != 0) {
+	ANIMATE_PaintFrame(infoPtr, hDC);
+	ReleaseDC(infoPtr->hWnd, hDC);
+    }
+
+    if (infoPtr->currFrame++ >= infoPtr->nToFrame) {
+	infoPtr->currFrame = infoPtr->nFromFrame;
+	if (infoPtr->nLoop != -1) {
+	    if (--infoPtr->nLoop == 0) {
+		ANIMATE_DoStop(infoPtr);
+	    }
+	}
+    }
     LeaveCriticalSection(&infoPtr->cs);
-    WARN("Decompression error\n");
-    return FALSE;
-    }
-
-    if ((hDC = GetDC(infoPtr->hWnd)) != 0) {
-    ANIMATE_PaintFrame(infoPtr, hDC);
-    ReleaseDC(infoPtr->hWnd, hDC);
-    }
-
-    if (infoPtr->currFrame++ >= infoPtr->nToFrame) {
-    infoPtr->currFrame = infoPtr->nFromFrame;
-    if (infoPtr->nLoop != -1) {
-        if (--infoPtr->nLoop == 0) {
-        ANIMATE_DoStop(infoPtr);
-        }
-    }
-    }
-    LeaveCriticalSection(&infoPtr->cs);
 
     return TRUE;
@@ -414,7 +375,7 @@
 static DWORD CALLBACK ANIMATE_AnimationThread(LPVOID ptr_)
 {
-    ANIMATE_INFO*   infoPtr = (ANIMATE_INFO*)ptr_;
+    ANIMATE_INFO*	infoPtr = (ANIMATE_INFO*)ptr_;
     HDC hDC;
-
+    
     if(!infoPtr)
     {
@@ -424,19 +385,21 @@
 
     while(1)
-    {
-        if(GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT)
+    {    
+        if(GetWindowLongA(infoPtr->hWnd, GWL_STYLE) & ACS_TRANSPARENT) 
         {
             hDC = GetDC(infoPtr->hWnd);
+	    /* sometimes the animation window will be destroyed in between
+	     * by the main program, so a ReleaseDC() error msg is possible */
             infoPtr->hbrushBG = SendMessageA(GetParent(infoPtr->hWnd),WM_CTLCOLORSTATIC,hDC, infoPtr->hWnd);
             ReleaseDC(infoPtr->hWnd,hDC);
         }
-
-    EnterCriticalSection(&infoPtr->cs);
-    ANIMATE_DrawFrame(infoPtr);
-    LeaveCriticalSection(&infoPtr->cs);
-
+        
+        EnterCriticalSection(&infoPtr->cs);
+        ANIMATE_DrawFrame(infoPtr);
+        LeaveCriticalSection(&infoPtr->cs);
+    
         /* time is in microseconds, we should convert it to milliseconds */
         Sleep((infoPtr->mah.dwMicroSecPerFrame+500)/1000);
-}
+    }
     return TRUE;
 }
@@ -448,9 +411,9 @@
     /* nothing opened */
     if (!infoPtr->hMMio)
-    return FALSE;
+	return FALSE;
 
     if (infoPtr->hThread || infoPtr->uTimer) {
-    FIXME("Already playing ? what should I do ??\n");
-    ANIMATE_DoStop(infoPtr);
+	FIXME("Already playing ? what should I do ??\n");
+	ANIMATE_DoStop(infoPtr);
     }
 
@@ -460,23 +423,23 @@
 
     if (infoPtr->nToFrame == 0xFFFF)
-    infoPtr->nToFrame = infoPtr->mah.dwTotalFrames - 1;
-
-    TRACE("(repeat=%d from=%d to=%d);\n",
-      infoPtr->nLoop, infoPtr->nFromFrame, infoPtr->nToFrame);
+	infoPtr->nToFrame = infoPtr->mah.dwTotalFrames - 1;
+
+    TRACE("(repeat=%d from=%d to=%d);\n", 
+	  infoPtr->nLoop, infoPtr->nFromFrame, infoPtr->nToFrame);
 
     if (infoPtr->nFromFrame >= infoPtr->nToFrame ||
-    infoPtr->nToFrame >= infoPtr->mah.dwTotalFrames)
-    return FALSE;
+	infoPtr->nToFrame >= infoPtr->mah.dwTotalFrames)
+	return FALSE;
 
     infoPtr->currFrame = infoPtr->nFromFrame;
 
     if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TIMER) {
-    TRACE("Using a timer\n");
-    /* create a timer to display AVI */
-    infoPtr->uTimer = SetTimer(hWnd, 1, infoPtr->mah.dwMicroSecPerFrame / 1000, NULL);
+	TRACE("Using a timer\n");
+	/* create a timer to display AVI */
+	infoPtr->uTimer = SetTimer(hWnd, 1, infoPtr->mah.dwMicroSecPerFrame / 1000, NULL);
     } else {
         DWORD threadID;
 
-    TRACE("Using an animation thread\n");
+	TRACE("Using an animation thread\n");
         infoPtr->hThread = CreateThread(0,0,ANIMATE_AnimationThread,(LPVOID)infoPtr,0,0 &threadID);
         if(!infoPtr->hThread)
@@ -485,7 +448,7 @@
            return FALSE;
     }
-
-    }
-
+	
+    }
+	
     ANIMATE_Notify(infoPtr, ACN_START);
 
@@ -496,163 +459,169 @@
 static BOOL ANIMATE_GetAviInfo(ANIMATE_INFO *infoPtr)
 {
-    MMCKINFO        ckMainRIFF;
-    MMCKINFO        mmckHead;
-    MMCKINFO        mmckList;
-    MMCKINFO        mmckInfo;
-    DWORD       numFrame;
-    DWORD       insize;
-
-    if (infoPtr->fnmmioDescend(infoPtr->hMMio, &ckMainRIFF, NULL, 0) != 0) {
-    WARN("Can't find 'RIFF' chunk\n");
-    return FALSE;
+    MMCKINFO		ckMainRIFF;
+    MMCKINFO		mmckHead;
+    MMCKINFO		mmckList;
+    MMCKINFO		mmckInfo;
+    DWORD		numFrame;
+    DWORD		insize;
+
+    if (mmioDescend(infoPtr->hMMio, &ckMainRIFF, NULL, 0) != 0) {
+	WARN("Can't find 'RIFF' chunk\n");
+	return FALSE;
     }
 
     if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
-    (ckMainRIFF.fccType != mmioFOURCC('A', 'V', 'I', ' '))) {
-    WARN("Can't find 'AVI ' chunk\n");
-    return FALSE;
+	(ckMainRIFF.fccType != mmioFOURCC('A', 'V', 'I', ' '))) {
+	WARN("Can't find 'AVI ' chunk\n");
+	return FALSE;
     }
 
     mmckHead.fccType = mmioFOURCC('h', 'd', 'r', 'l');
-    if (infoPtr->fnmmioDescend(infoPtr->hMMio, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
-    WARN("Can't find 'hdrl' list\n");
-    return FALSE;
+    if (mmioDescend(infoPtr->hMMio, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
+	WARN("Can't find 'hdrl' list\n");
+	return FALSE;
     }
 
     mmckInfo.ckid = mmioFOURCC('a', 'v', 'i', 'h');
-    if (infoPtr->fnmmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
-    WARN("Can't find 'avih' chunk\n");
-    return FALSE;
-    }
-
-    infoPtr->fnmmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah));
-    TRACE("mah.dwMicroSecPerFrame=%ld\n",   infoPtr->mah.dwMicroSecPerFrame);
-    TRACE("mah.dwMaxBytesPerSec=%ld\n",     infoPtr->mah.dwMaxBytesPerSec);
-    TRACE("mah.dwPaddingGranularity=%ld\n",     infoPtr->mah.dwPaddingGranularity);
-    TRACE("mah.dwFlags=%ld\n",          infoPtr->mah.dwFlags);
-    TRACE("mah.dwTotalFrames=%ld\n",        infoPtr->mah.dwTotalFrames);
-    TRACE("mah.dwInitialFrames=%ld\n",      infoPtr->mah.dwInitialFrames);
-    TRACE("mah.dwStreams=%ld\n",        infoPtr->mah.dwStreams);
-    TRACE("mah.dwSuggestedBufferSize=%ld\n",    infoPtr->mah.dwSuggestedBufferSize);
-    TRACE("mah.dwWidth=%ld\n",          infoPtr->mah.dwWidth);
-    TRACE("mah.dwHeight=%ld\n",         infoPtr->mah.dwHeight);
-    infoPtr->fnmmioAscend(infoPtr->hMMio, &mmckInfo, 0);
+    if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
+	WARN("Can't find 'avih' chunk\n");
+	return FALSE;
+    }
+
+    mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah));
+
+    TRACE("mah.dwMicroSecPerFrame=%ld\n", 	infoPtr->mah.dwMicroSecPerFrame);
+    TRACE("mah.dwMaxBytesPerSec=%ld\n", 	infoPtr->mah.dwMaxBytesPerSec);
+    TRACE("mah.dwPaddingGranularity=%ld\n", 	infoPtr->mah.dwPaddingGranularity);
+    TRACE("mah.dwFlags=%ld\n", 			infoPtr->mah.dwFlags);
+    TRACE("mah.dwTotalFrames=%ld\n", 		infoPtr->mah.dwTotalFrames);
+    TRACE("mah.dwInitialFrames=%ld\n", 		infoPtr->mah.dwInitialFrames);
+    TRACE("mah.dwStreams=%ld\n", 		infoPtr->mah.dwStreams);
+    TRACE("mah.dwSuggestedBufferSize=%ld\n",	infoPtr->mah.dwSuggestedBufferSize);
+    TRACE("mah.dwWidth=%ld\n", 			infoPtr->mah.dwWidth);
+    TRACE("mah.dwHeight=%ld\n", 		infoPtr->mah.dwHeight);
+
+    mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
 
     mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
-    if (infoPtr->fnmmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
-    WARN("Can't find 'strl' list\n");
-    return FALSE;
+    if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
+	WARN("Can't find 'strl' list\n");
+	return FALSE;
     }
 
     mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'h');
-    if (infoPtr->fnmmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
-    WARN("Can't find 'strh' chunk\n");
-    return FALSE;
-    }
-
-    infoPtr->fnmmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash));
-    TRACE("ash.fccType='%c%c%c%c'\n",       LOBYTE(LOWORD(infoPtr->ash.fccType)),
-                                            HIBYTE(LOWORD(infoPtr->ash.fccType)),
-                                            LOBYTE(HIWORD(infoPtr->ash.fccType)),
-                                            HIBYTE(HIWORD(infoPtr->ash.fccType)));
-    TRACE("ash.fccHandler='%c%c%c%c'\n",    LOBYTE(LOWORD(infoPtr->ash.fccHandler)),
-                                            HIBYTE(LOWORD(infoPtr->ash.fccHandler)),
-                                            LOBYTE(HIWORD(infoPtr->ash.fccHandler)),
-                                            HIBYTE(HIWORD(infoPtr->ash.fccHandler)));
-    TRACE("ash.dwFlags=%ld\n",          infoPtr->ash.dwFlags);
-    TRACE("ash.wPriority=%d\n",         infoPtr->ash.wPriority);
-    TRACE("ash.wLanguage=%d\n",         infoPtr->ash.wLanguage);
-    TRACE("ash.dwInitialFrames=%ld\n",      infoPtr->ash.dwInitialFrames);
-    TRACE("ash.dwScale=%ld\n",          infoPtr->ash.dwScale);
-    TRACE("ash.dwRate=%ld\n",           infoPtr->ash.dwRate);
-    TRACE("ash.dwStart=%ld\n",          infoPtr->ash.dwStart);
-    TRACE("ash.dwLength=%ld\n",         infoPtr->ash.dwLength);
-    TRACE("ash.dwSuggestedBufferSize=%ld\n",    infoPtr->ash.dwSuggestedBufferSize);
-    TRACE("ash.dwQuality=%ld\n",        infoPtr->ash.dwQuality);
-    TRACE("ash.dwSampleSize=%ld\n",         infoPtr->ash.dwSampleSize);
-    TRACE("ash.rcFrame=(%d,%d,%d,%d)\n",    infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left,
-      infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right);
-    infoPtr->fnmmioAscend(infoPtr->hMMio, &mmckInfo, 0);
+    if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
+	WARN("Can't find 'strh' chunk\n");
+	return FALSE;
+    }
+
+    mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash));
+
+    TRACE("ash.fccType='%c%c%c%c'\n", 		LOBYTE(LOWORD(infoPtr->ash.fccType)), 
+	                                        HIBYTE(LOWORD(infoPtr->ash.fccType)), 
+	                                        LOBYTE(HIWORD(infoPtr->ash.fccType)), 
+	                                        HIBYTE(HIWORD(infoPtr->ash.fccType)));
+    TRACE("ash.fccHandler='%c%c%c%c'\n",	LOBYTE(LOWORD(infoPtr->ash.fccHandler)), 
+	                                        HIBYTE(LOWORD(infoPtr->ash.fccHandler)), 
+	                                        LOBYTE(HIWORD(infoPtr->ash.fccHandler)), 
+	                                        HIBYTE(HIWORD(infoPtr->ash.fccHandler)));
+    TRACE("ash.dwFlags=%ld\n", 			infoPtr->ash.dwFlags);
+    TRACE("ash.wPriority=%d\n", 		infoPtr->ash.wPriority);
+    TRACE("ash.wLanguage=%d\n", 		infoPtr->ash.wLanguage);
+    TRACE("ash.dwInitialFrames=%ld\n", 		infoPtr->ash.dwInitialFrames);
+    TRACE("ash.dwScale=%ld\n", 			infoPtr->ash.dwScale);
+    TRACE("ash.dwRate=%ld\n", 			infoPtr->ash.dwRate);
+    TRACE("ash.dwStart=%ld\n", 			infoPtr->ash.dwStart);
+    TRACE("ash.dwLength=%ld\n", 		infoPtr->ash.dwLength);
+    TRACE("ash.dwSuggestedBufferSize=%ld\n", 	infoPtr->ash.dwSuggestedBufferSize);
+    TRACE("ash.dwQuality=%ld\n", 		infoPtr->ash.dwQuality);
+    TRACE("ash.dwSampleSize=%ld\n", 		infoPtr->ash.dwSampleSize);
+    TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", 	infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left, 
+	  infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right);
+
+    mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
 
     mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'f');
-    if (infoPtr->fnmmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
-    WARN("Can't find 'strh' chunk\n");
-    return FALSE;
+    if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) {
+	WARN("Can't find 'strh' chunk\n");
+	return FALSE;
     }
 
     infoPtr->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
     if (!infoPtr->inbih) {
-    WARN("Can't alloc input BIH\n");
-    return FALSE;
-    }
-
-    infoPtr->fnmmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize);
-    TRACE("bih.biSize=%ld\n",       infoPtr->inbih->biSize);
-    TRACE("bih.biWidth=%ld\n",      infoPtr->inbih->biWidth);
-    TRACE("bih.biHeight=%ld\n",     infoPtr->inbih->biHeight);
-    TRACE("bih.biPlanes=%d\n",      infoPtr->inbih->biPlanes);
-    TRACE("bih.biBitCount=%d\n",    infoPtr->inbih->biBitCount);
-    TRACE("bih.biCompression=%ld\n",    infoPtr->inbih->biCompression);
-    TRACE("bih.biSizeImage=%ld\n",  infoPtr->inbih->biSizeImage);
-    TRACE("bih.biXPelsPerMeter=%ld\n",  infoPtr->inbih->biXPelsPerMeter);
-    TRACE("bih.biYPelsPerMeter=%ld\n",  infoPtr->inbih->biYPelsPerMeter);
-    TRACE("bih.biClrUsed=%ld\n",    infoPtr->inbih->biClrUsed);
-    TRACE("bih.biClrImportant=%ld\n",   infoPtr->inbih->biClrImportant);
-    infoPtr->fnmmioAscend(infoPtr->hMMio, &mmckInfo, 0);
-
-    infoPtr->fnmmioAscend(infoPtr->hMMio, &mmckList, 0);
-
+	WARN("Can't alloc input BIH\n");
+	return FALSE;
+    }
+
+    mmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize);
+
+    TRACE("bih.biSize=%ld\n", 		infoPtr->inbih->biSize);
+    TRACE("bih.biWidth=%ld\n", 		infoPtr->inbih->biWidth);
+    TRACE("bih.biHeight=%ld\n", 	infoPtr->inbih->biHeight);
+    TRACE("bih.biPlanes=%d\n", 		infoPtr->inbih->biPlanes);
+    TRACE("bih.biBitCount=%d\n", 	infoPtr->inbih->biBitCount);
+    TRACE("bih.biCompression=%ld\n", 	infoPtr->inbih->biCompression);
+    TRACE("bih.biSizeImage=%ld\n", 	infoPtr->inbih->biSizeImage);
+    TRACE("bih.biXPelsPerMeter=%ld\n", 	infoPtr->inbih->biXPelsPerMeter);
+    TRACE("bih.biYPelsPerMeter=%ld\n", 	infoPtr->inbih->biYPelsPerMeter);
+    TRACE("bih.biClrUsed=%ld\n", 	infoPtr->inbih->biClrUsed);
+    TRACE("bih.biClrImportant=%ld\n", 	infoPtr->inbih->biClrImportant);
+
+    mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
+
+    mmioAscend(infoPtr->hMMio, &mmckList, 0);
+    
 #if 0
     /* an AVI has 0 or 1 video stream, and to be animated should not contain
-     * an audio stream, so only one strl is allowed
+     * an audio stream, so only one strl is allowed 
      */
     mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l');
-    if (infoPtr->fnmmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
-    WARN("There should be a single 'strl' list\n");
-    return FALSE;
-    }
-#endif
-
-    infoPtr->fnmmioAscend(infoPtr->hMMio, &mmckHead, 0);
+    if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
+	WARN("There should be a single 'strl' list\n");
+	return FALSE;
+    }
+#endif
+
+    mmioAscend(infoPtr->hMMio, &mmckHead, 0);
 
     /* no need to read optional JUNK chunk */
 
     mmckList.fccType = mmioFOURCC('m', 'o', 'v', 'i');
-    if (infoPtr->fnmmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
-    WARN("Can't find 'movi' list\n");
-    return FALSE;
+    if (mmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
+	WARN("Can't find 'movi' list\n");
+	return FALSE;
     }
 
     /* FIXME: should handle the 'rec ' LIST when present */
 
-    infoPtr->lpIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-                 infoPtr->mah.dwTotalFrames * sizeof(DWORD));
+    infoPtr->lpIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+				 infoPtr->mah.dwTotalFrames * sizeof(DWORD));
     if (!infoPtr->lpIndex) {
-    WARN("Can't alloc index array\n");
-    return FALSE;
+	WARN("Can't alloc index array\n");
+	return FALSE;
     }
 
     numFrame = insize = 0;
-    while (infoPtr->fnmmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 &&
-       numFrame < infoPtr->mah.dwTotalFrames) {
-    infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset;
-    if (insize < mmckInfo.cksize)
-        insize = mmckInfo.cksize;
-    numFrame++;
-    infoPtr->fnmmioAscend(infoPtr->hMMio, &mmckInfo, 0);
+    while (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 && 
+	   numFrame < infoPtr->mah.dwTotalFrames) {
+	infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset;
+	if (insize < mmckInfo.cksize)
+	    insize = mmckInfo.cksize;
+	numFrame++;
+	mmioAscend(infoPtr->hMMio, &mmckInfo, 0);
     }
     if (numFrame != infoPtr->mah.dwTotalFrames) {
-    WARN("Found %ld frames (/%ld)\n", numFrame, infoPtr->mah.dwTotalFrames);
-    return FALSE;
+	WARN("Found %ld frames (/%ld)\n", numFrame, infoPtr->mah.dwTotalFrames);
+	return FALSE;
     }
     if (insize > infoPtr->ash.dwSuggestedBufferSize) {
-    WARN("insize=%ld suggestedSize=%ld\n", insize, infoPtr->ash.dwSuggestedBufferSize);
-    infoPtr->ash.dwSuggestedBufferSize = insize;
+	WARN("insize=%ld suggestedSize=%ld\n", insize, infoPtr->ash.dwSuggestedBufferSize);
+	infoPtr->ash.dwSuggestedBufferSize = insize;
     }
 
     infoPtr->indata = HeapAlloc(GetProcessHeap(), 0, infoPtr->ash.dwSuggestedBufferSize);
     if (!infoPtr->indata) {
-    WARN("Can't alloc input buffer\n");
-    return FALSE;
+	WARN("Can't alloc input buffer\n");
+	return FALSE;
     }
 
@@ -663,5 +632,5 @@
 static BOOL    ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr)
 {
-    DWORD   outSize;
+    DWORD	outSize;
 
     /* check uncompressed AVI */
@@ -669,44 +638,40 @@
        (infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' ')))
     {
-        infoPtr->hic = 0;
-    return TRUE;
+        infoPtr->hic = 0;             
+	return TRUE;
     }
 
     /* try to get a decompressor for that type */
-    infoPtr->hic = (infoPtr->fnICOpen)(ICTYPE_VIDEO,
-                       infoPtr->ash.fccHandler,
-                       ICMODE_DECOMPRESS);
+    infoPtr->hic = ICOpen(ICTYPE_VIDEO, infoPtr->ash.fccHandler, ICMODE_DECOMPRESS);
     if (!infoPtr->hic) {
-    WARN("Can't load codec for the file\n");
-    return FALSE;
-    }
-
-    outSize = (infoPtr->fnICSendMessage)(infoPtr->hic,
-                     ICM_DECOMPRESS_GET_FORMAT,
-                     (DWORD)infoPtr->inbih, 0L);
+	WARN("Can't load codec for the file\n");
+	return FALSE;
+    }
+    
+    outSize = ICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT, 
+			    (DWORD)infoPtr->inbih, 0L);
+
     infoPtr->outbih = HeapAlloc(GetProcessHeap(), 0, outSize);
     if (!infoPtr->outbih) {
-    WARN("Can't alloc output BIH\n");
-    return FALSE;
-    }
-
-    if ((infoPtr->fnICSendMessage)(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
-                   (DWORD)infoPtr->inbih,
-                   (DWORD)infoPtr->outbih) != ICERR_OK) {
-    WARN("Can't get output BIH\n");
-    return FALSE;
+	WARN("Can't alloc output BIH\n");
+	return FALSE;
+    }
+
+    if (ICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT, 
+		      (DWORD)infoPtr->inbih, (DWORD)infoPtr->outbih) != ICERR_OK) {
+	WARN("Can't get output BIH\n");
+	return FALSE;
     }
 
     infoPtr->outdata = HeapAlloc(GetProcessHeap(), 0, infoPtr->outbih->biSizeImage);
     if (!infoPtr->outdata) {
-    WARN("Can't alloc output buffer\n");
-    return FALSE;
-    }
-
-    if ((infoPtr->fnICSendMessage)(infoPtr->hic, ICM_DECOMPRESS_BEGIN,
-                   (DWORD)infoPtr->inbih,
-                   (DWORD)infoPtr->outbih) != ICERR_OK) {
-    WARN("Can't begin decompression\n");
-    return FALSE;
+	WARN("Can't alloc output buffer\n");
+	return FALSE;
+    }
+
+    if (ICSendMessage(infoPtr->hic, ICM_DECOMPRESS_BEGIN, 
+		      (DWORD)infoPtr->inbih, (DWORD)infoPtr->outbih) != ICERR_OK) {
+	WARN("Can't begin decompression\n");
+	return FALSE;
     }
 
@@ -726,8 +691,8 @@
 
     if (!lParam) {
-    TRACE("Closing avi!\n");
-    return TRUE;
-    }
-
+	TRACE("Closing avi!\n");
+	return TRUE;
+    }
+    
     if (!hInstance)
        hInstance = GetWindowLongA(hWnd, GWL_HINSTANCE);
@@ -738,7 +703,7 @@
 
         if (!ANIMATE_LoadRes(infoPtr, hInstance, (LPWSTR)lParam,unicode)) {
-            //TRACE("No AVI resource found!\n");
+            TRACE("No AVI resource found!\n");
             if (!ANIMATE_LoadFile(infoPtr, (LPWSTR)lParam,unicode)) {
-                //WARN("No AVI file found!\n");
+                WARN("No AVI file found!\n");
                 return FALSE;
             }
@@ -748,5 +713,5 @@
 
         if (!ANIMATE_LoadRes(infoPtr,hInstance,unicode ? MAKEINTRESOURCEW((INT)lParam):(LPWSTR)MAKEINTRESOURCEA((INT)lParam),unicode)) {
-            //WARN("No AVI resource found!\n");
+            WARN("No AVI resource found!\n");
             return FALSE;
         }
@@ -773,24 +738,23 @@
     }
 #endif
-
     if (!ANIMATE_GetAviInfo(infoPtr)) {
-    WARN("Can't get AVI information\n");
-    ANIMATE_Free(infoPtr);
-    return FALSE;
+	WARN("Can't get AVI information\n");
+	ANIMATE_Free(infoPtr);
+	return FALSE;
     }
 
     if (!ANIMATE_GetAviCodec(infoPtr)) {
-    WARN("Can't get AVI Codec\n");
-    ANIMATE_Free(infoPtr);
-    return FALSE;
+	WARN("Can't get AVI Codec\n");
+	ANIMATE_Free(infoPtr);
+	return FALSE;
     }
 
     if (!GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) {
-    SetWindowPos(hWnd, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight,
-             SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
+	SetWindowPos(hWnd, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight,
+		     SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
     }
 
     if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_AUTOPLAY) {
-    return ANIMATE_Play(hWnd, -1, (LPARAM)MAKELONG(0, infoPtr->mah.dwTotalFrames-1));
+	return ANIMATE_Play(hWnd, -1, (LPARAM)MAKELONG(0, infoPtr->mah.dwTotalFrames-1));
     }
 
@@ -807,5 +771,5 @@
     /* nothing opened */
     if (!infoPtr->hMMio)
-    return FALSE;
+	return FALSE;
 
     ANIMATE_DoStop(infoPtr);
@@ -816,9 +780,5 @@
 static LRESULT ANIMATE_Create(HWND hWnd, WPARAM wParam, LPARAM lParam)
 {
-    ANIMATE_INFO*   infoPtr;
-    HMODULE     hModule = LoadLibraryA("msvfw32.dll");
-
-    if (!hModule)
-        return FALSE;
+    ANIMATE_INFO*	infoPtr;
 
     /* allocate memory for info structure */
@@ -829,13 +789,7 @@
 #endif
     if (!infoPtr) {
-        ERR("could not allocate info memory!\n");
-        return 0;
-    }
-
-    /* Temporary hack until we get dllglue up and running */
-    infoPtr->fnICOpen        = (void*)GetProcAddress(hModule, "ICOpen");
-    infoPtr->fnICClose       = (void*)GetProcAddress(hModule, "ICClose");
-    infoPtr->fnICSendMessage = (void*)GetProcAddress(hModule, "ICSendMessage");
-    infoPtr->fnICDecompress  = (void*)GetProcAddress(hModule, "ICDecompress");
+	ERR("could not allocate info memory!\n");
+	return 0;
+    }
 
     TRACE("Animate style=0x%08lx, parent=%08lx\n", GetWindowLongA(hWnd, GWL_STYLE), (DWORD)GetParent(hWnd));
@@ -846,18 +800,7 @@
     infoPtr->transparentColor = ANIMATE_COLOR_NONE;
     infoPtr->hbmPrevFrame = 0;
-    hModWinmm = LoadLibraryA("WINMM");
-
-    infoPtr->fnmmioOpenA = (void*)GetProcAddress(hModWinmm, "mmioOpenA");
-#ifdef __WIN32OS2__
-    infoPtr->fnmmioOpenW = (void*)GetProcAddress(hModWinmm, "mmioOpenW");
-#endif
-    infoPtr->fnmmioClose = (void*)GetProcAddress(hModWinmm, "mmioClose");
-    infoPtr->fnmmioAscend = (void*)GetProcAddress(hModWinmm, "mmioAscend");
-    infoPtr->fnmmioDescend = (void*)GetProcAddress(hModWinmm, "mmioDescend");
-    infoPtr->fnmmioSeek = (void*)GetProcAddress(hModWinmm, "mmioSeek");
-    infoPtr->fnmmioRead = (void*)GetProcAddress(hModWinmm, "mmioRead");
 
     InitializeCriticalSection(&infoPtr->cs);
-
+    
     return 0;
 }
@@ -876,5 +819,4 @@
     SetWindowLongA(hWnd, 0, 0);
 
-    FreeLibrary(hModWinmm);
     return 0;
 }
@@ -884,9 +826,9 @@
 {
     RECT rect;
-    HBRUSH hBrush = 0;
-
-    if(GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT)
+    HBRUSH hBrush = 0;       
+
+    if(GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) 
     {
-        hBrush = SendMessageA(GetParent(hWnd),WM_CTLCOLORSTATIC,(HDC)wParam, hWnd);
+        hBrush = SendMessageA(GetParent(hWnd),WM_CTLCOLORSTATIC,(HDC)wParam, hWnd);    
     }
 
@@ -900,5 +842,5 @@
 {
     if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) {
-    InvalidateRect(hWnd, NULL, TRUE);
+	InvalidateRect(hWnd, NULL, TRUE);
     }
     return TRUE;
@@ -909,69 +851,69 @@
     TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hWnd, uMsg, wParam, lParam);
     if (!ANIMATE_GetInfoPtr(hWnd) && (uMsg != WM_NCCREATE))
-    return DefWindowProcA(hWnd, uMsg, wParam, lParam);
+	return DefWindowProcA(hWnd, uMsg, wParam, lParam);
     switch (uMsg)
     {
 #ifdef __WIN32OS2__
-        case ACM_OPENA:
-          return ANIMATE_Open(hWnd,wParam,lParam,FALSE);
-
-        case ACM_OPENW:
-          return ANIMATE_Open(hWnd,wParam,lParam,TRUE);
+    case ACM_OPENA:
+        return ANIMATE_Open(hWnd,wParam,lParam,FALSE);
+
+    case ACM_OPENW:
+        return ANIMATE_Open(hWnd,wParam,lParam,TRUE);
 #else
     case ACM_OPENA:
-    return ANIMATE_OpenA(hWnd, wParam, lParam);
-
-    /*  case ACM_OPEN32W: FIXME!! */
-    /*      return ANIMATE_Open32W(hWnd, wParam, lParam); */
-#endif
-
+	return ANIMATE_OpenA(hWnd, wParam, lParam);
+	
+	/*	case ACM_OPEN32W: FIXME!! */
+	/*	    return ANIMATE_Open32W(hWnd, wParam, lParam); */
+#endif
+	
     case ACM_PLAY:
-    return ANIMATE_Play(hWnd, wParam, lParam);
-
+	return ANIMATE_Play(hWnd, wParam, lParam);
+	
     case ACM_STOP:
-    return ANIMATE_Stop(hWnd, wParam, lParam);
-
+	return ANIMATE_Stop(hWnd, wParam, lParam);
+	
     case WM_NCCREATE:
-    ANIMATE_Create(hWnd, wParam, lParam);
-    return DefWindowProcA(hWnd, uMsg, wParam, lParam);
-
+	ANIMATE_Create(hWnd, wParam, lParam);
+	return DefWindowProcA(hWnd, uMsg, wParam, lParam);
+	
     case WM_NCHITTEST:
-    return HTTRANSPARENT;
+	return HTTRANSPARENT;
 
     case WM_DESTROY:
-    ANIMATE_Destroy(hWnd, wParam, lParam);
-    return DefWindowProcA(hWnd, uMsg, wParam, lParam);
-
+	ANIMATE_Destroy(hWnd, wParam, lParam);
+	return DefWindowProcA(hWnd, uMsg, wParam, lParam);
+	
     case WM_ERASEBKGND:
-    ANIMATE_EraseBackground(hWnd, wParam, lParam);
-    break;
-
-    /*  case WM_STYLECHANGED: FIXME shall we do something ?? */
+	ANIMATE_EraseBackground(hWnd, wParam, lParam);
+	break;
+
+    /*	case WM_STYLECHANGED: FIXME shall we do something ?? */
 
     case WM_TIMER:
-        if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT)
+    	if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT)
         {
             ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd);
             infoPtr->hbrushBG = SendMessageA(GetParent(hWnd),WM_CTLCOLORSTATIC,(HDC)wParam, hWnd);
         }
-    return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd));
-
+	return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd));
+	
     case WM_CLOSE:
-    ANIMATE_Free(ANIMATE_GetInfoPtr(hWnd));
-    return TRUE;
+	ANIMATE_Free(ANIMATE_GetInfoPtr(hWnd));
+	return TRUE;
 
     case WM_PAINT:
         {
             ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd);
-
+	        
             /* the animation isn't playing, don't paint */
-        if(!infoPtr->uTimer && !infoPtr->hThread)
-        /* default paint handling */
-            return DefWindowProcA(hWnd, uMsg, wParam, lParam);
-
+	    if(!infoPtr->uTimer && !infoPtr->hThread)
+		/* default paint handling */
+	    	return DefWindowProcA(hWnd, uMsg, wParam, lParam);
+	    
             if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT)
                 infoPtr->hbrushBG = SendMessageA(GetParent(hWnd), WM_CTLCOLORSTATIC,
-                                         (HDC)wParam, hWnd);
-
+		                                 (HDC)wParam, hWnd);
+    
             if (wParam)
             {
@@ -982,28 +924,28 @@
             else
             {
-            PAINTSTRUCT ps;
-            HDC hDC = BeginPaint(hWnd, &ps);
+	        PAINTSTRUCT ps;
+ 	        HDC hDC = BeginPaint(hWnd, &ps);
 
                 EnterCriticalSection(&infoPtr->cs);
                 ANIMATE_PaintFrame(infoPtr, hDC);
                 LeaveCriticalSection(&infoPtr->cs);
-
-            EndPaint(hWnd, &ps);
+    
+	        EndPaint(hWnd, &ps);
+	    }
         }
-        }
-    break;
+	break;
 
     case WM_SIZE:
-    ANIMATE_Size(hWnd, wParam, lParam);
-    return DefWindowProcA(hWnd, uMsg, wParam, lParam);
+	ANIMATE_Size(hWnd, wParam, lParam);
+	return DefWindowProcA(hWnd, uMsg, wParam, lParam);
 
     default:
-    if (uMsg >= WM_USER)
-        ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam);
-
-#ifdef __WIN32OS2__
-            return defComCtl32ProcA (hWnd, uMsg, wParam, lParam);
+	if (uMsg >= WM_USER)
+	    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);
+	return DefWindowProcA(hWnd, uMsg, wParam, lParam);
 #endif
     }
@@ -1024,5 +966,5 @@
     wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
     wndClass.lpszClassName = ANIMATE_CLASSA;
-
+ 
     RegisterClassA(&wndClass);
 }
Index: trunk/src/comctl32/cctl_De.orc
===================================================================
--- trunk/src/comctl32/cctl_De.orc	(revision 5627)
+++ trunk/src/comctl32/cctl_De.orc	(revision 5630)
@@ -1,48 +1,64 @@
 LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT
 
-IDD_PROPSHEET DIALOG DISCARDABLE 0,0,223,140
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE 
-CAPTION "Eigenschaften für:"
+STRINGTABLE DISCARDABLE
+{
+     IDS_CLOSE    "Schließen"
+}
+ 
+STRINGTABLE DISCARDABLE 
+{
+     IDM_TODAY    "Heute:"
+     IDM_GOTODAY  "Gehe zu Heute"
+}
+
+STRINGTABLE DISCARDABLE
+{
+    IDS_SEPARATOR "Trennzeichen"
+}
+
+IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
+CAPTION "Eigenschaften für "
 FONT 8, "MS Sans Serif"
 BEGIN
-	DEFPUSHBUTTON "Ok",IDOK,4,122,50,14
-	PUSHBUTTON "Abbrechen",IDCANCEL,58,122,50,14
-	PUSHBUTTON "Ubernehmen",IDC_APPLY_BUTTON,112,122,50,14
-	PUSHBUTTON "Hilfe",IDHELP,166,122,50,14, WS_TABSTOP | WS_GROUP 
-	CONTROL "Tabstopp",IDC_TABCONTROL,"SysTabControl32", WS_CLIPSIBLINGS | WS_TABSTOP ,4,4,215,114
+  DEFPUSHBUTTON "&OK",        IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP
+  PUSHBUTTON    "A&bbrechen", IDCANCEL,58,122,50,14
+  PUSHBUTTON    "&Anwenden",  IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED
+  PUSHBUTTON    "&Hilfe",     IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP
+  CONTROL       "Tab",        IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP,4,4,212,114
 END
 
 
-IDD_WIZARD DIALOG DISCARDABLE 20,20,292,46
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE 
-CAPTION "Assistent"
+IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
+CAPTION "Wizard"
 FONT 8, "MS Sans Serif"
 BEGIN
-	DEFPUSHBUTTON "Fertig",IDC_FINISH_BUTTON,119,26,50,14
-	DEFPUSHBUTTON "&Weiter >",IDC_NEXT_BUTTON,62,26,50,14
-	PUSHBUTTON "< &Zurück",IDC_BACK_BUTTON,12,26,50,14
-	PUSHBUTTON "Abbrechen",IDCANCEL,176,26,50,14
-	PUSHBUTTON "Hilfe",IDHELP,233,26,50,14, WS_GROUP 
-	LTEXT "",IDC_SUNKEN_LINE,7,17,276,1, SS_SUNKEN 
-	CONTROL "Tabstopp",IDC_TABCONTROL,"SysTabControl32", WS_CLIPSIBLINGS | WS_DISABLED ,7,7,276,3
+  DEFPUSHBUTTON "&Beenden",   IDC_FINISH_BUTTON,121,138,50,14
+  DEFPUSHBUTTON "&Weiter >", IDC_NEXT_BUTTON,121,138,50,14
+  PUSHBUTTON    "< &Zurück", IDC_BACK_BUTTON,71,138,50,14
+  PUSHBUTTON    "Abbrechen", IDCANCEL,178,138,50,14
+  PUSHBUTTON    "&Hilfe",     IDHELP,235,138,50,14,WS_GROUP
+  LTEXT         "",          IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN
+  CONTROL       "Tab",       IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5
 END
 
 
-IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10,20,362,125
-STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU 
-CAPTION "Symbolleiste anpassen"
+IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Toolbar einrichten"
 FONT 8, "MS Sans Serif"
 BEGIN
-	DEFPUSHBUTTON "S&chließen",IDCANCEL,309,6,49,14
-	PUSHBUTTON "Zurücksetzen",IDC_RESET_BTN,309,23,49,14
-	PUSHBUTTON "&Hilfe",IDC_HELP_BTN,309,40,49,14
-	PUSHBUTTON "Nach &oben",IDC_MOVEUP_BTN,309,74,49,14
-	PUSHBUTTON "&Nach unten",IDC_MOVEDN_BTN,309,91,49,14
-	LTEXT "&Verfügbare Schaltflächen:",-1,4,5,84,10
-	LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP 
-	PUSHBUTTON "Hinz&ufügen ->",IDOK,129,42,49,14
-	PUSHBUTTON "<- &Entfernen",IDC_REMOVE_BTN,129,62,49,14
-	LTEXT "&Schaltflächen auf Symbolleiste:",-1,183,5,101,10
-	LISTBOX IDC_TOOLBARBTN_LBOX,183,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP 
+  DEFPUSHBUTTON "&Schließen",               IDCANCEL,308,6,44,14
+  PUSHBUTTON    "&Zurücksetzen",            IDC_RESET_BTN,308,23,44,14
+  PUSHBUTTON    "&Hilfe",                   IDC_HELP_BTN,308,40,44,14
+  PUSHBUTTON    "Nach &Oben verschieben",   IDC_MOVEUP_BTN,308,74,44,14
+  PUSHBUTTON    "Nach &Unten verschieben",  IDC_MOVEDN_BTN,308,91,44,14
+  LTEXT         "&Vorhandene Knöpfe:", -1,4,5,84,10
+  LISTBOX       IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
+  PUSHBUTTON    "H&inzufügen ->",           IDOK, 131, 42, 44, 14
+  PUSHBUTTON    "<- &Löschen",              IDC_REMOVE_BTN,131,62,44,14
+  LTEXT         "&Toolbarknöpfe:", -1,182,5,78,10
+  LISTBOX       IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
 END
 
@@ -66,7 +82,3 @@
 }
 
-STRINGTABLE DISCARDABLE 
-{
-	IDS_CLOSE	"Schließen"
-}
 
Index: trunk/src/comctl32/comboex.c
===================================================================
--- trunk/src/comctl32/comboex.c	(revision 5627)
+++ trunk/src/comctl32/comboex.c	(revision 5630)
@@ -19,5 +19,5 @@
 
 /*
- * ComboBoxEx control v2 (mod4)
+ * ComboBoxEx control v2 (mod5)
  *
  * Copyright 1998, 1999 Eric Kohl
@@ -59,6 +59,16 @@
  *   5. The LBN_SELCHANGE is just for documentation purposes.
  *
+ *  mod 5
+ *   1. Add support for CB_GETITEMDATA to a Comboex. Returns the LPARAM
+ *      passed during insert of item.
+ *   2. Remember selected item and don't issue CB_SETCURSEL unless needed.
+ *   3. Add initial support for WM_NCCREATE to remove unwanted window styles
+ *      (Currently just WS_VSCROLL and WS_HSCROLL, but probably should be
+ *       more.)
+ *   4. Improve some traces.
+ *   5. Add support for CB_SETITEMDATA sets LPARAM value from item.
+ *
  * Test vehicals were the ControlSpy modules (rebar.exe and comboboxex.exe),
- *  and IE 4.0.
+ *  WinRAR, and IE 4.0.
  *
  */
@@ -69,5 +79,4 @@
 #include "debugtools.h"
 #include "wine/unicode.h"
-
 #ifdef __WIN32OS2__
 #include "ccbase.h"
@@ -109,4 +118,5 @@
     WNDPROC      prevComboWndProc;   /* previous Combo WNDPROC value */
     DWORD        dwExtStyle;
+    INT          selected;         /* index of selected item */
     DWORD        flags;            /* WINE internal flags */
     HFONT        font;
@@ -882,4 +892,31 @@
 
 static LRESULT
+COMBOEX_GetItemData (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    INT index = wParam;
+    COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
+    CBE_ITEMDATA *item1, *item2;
+    LRESULT lret = 0;
+
+    item1 = (CBE_ITEMDATA *)COMBOEX_Forward (hwnd, CB_GETITEMDATA, 
+					     wParam, lParam);
+    if ((item1 != NULL) && ((LRESULT)item1 != CB_ERR)) {
+	item2 = COMBOEX_FindItem (infoPtr, index);
+	if (item2 != item1) {
+	    ERR("data structures damaged!\n");
+	    return CB_ERR;
+	}
+	if (item1->mask & CBEIF_LPARAM)
+	    lret = (LRESULT) item1->lParam;
+	TRACE("returning 0x%08lx\n", lret);
+	return lret;
+    }
+    lret = (LRESULT)item1;
+    TRACE("non-valid result from combo, returning 0x%08lx\n", lret);
+    return lret;
+}
+
+
+static LRESULT
 COMBOEX_SetCursel (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -896,8 +933,34 @@
     TRACE("selecting item %d text=%s\n", index, (item->pszText) ?
 	  debugstr_w(item->pszText) : "<null>");
+    infoPtr->selected = index;
 
     lret = SendMessageW (infoPtr->hwndCombo, CB_SETCURSEL, wParam, lParam);
     COMBOEX_SetEditText (infoPtr, item);
     return lret;
+}
+
+
+static LRESULT
+COMBOEX_SetItemData (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    INT index = wParam;
+    COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
+    CBE_ITEMDATA *item1, *item2;
+
+    item1 = (CBE_ITEMDATA *)COMBOEX_Forward (hwnd, CB_GETITEMDATA, 
+					     wParam, lParam);
+    if ((item1 != NULL) && ((LRESULT)item1 != CB_ERR)) {
+	item2 = COMBOEX_FindItem (infoPtr, index);
+	if (item2 != item1) {
+	    ERR("data structures damaged!\n");
+	    return CB_ERR;
+	}
+	item1->mask |= CBEIF_LPARAM;
+	item1->lParam = lParam;
+	TRACE("setting lparam to 0x%08lx\n", lParam);
+	return 0;
+    }
+    TRACE("non-valid result from combo 0x%08lx\n", (DWORD)item1);
+    return (LRESULT)item1;
 }
 
@@ -968,4 +1031,5 @@
     infoPtr->nb_items = 0;
     infoPtr->hwndSelf = hwnd;
+    infoPtr->selected = -1;
 
     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
@@ -975,5 +1039,10 @@
 			(CBS_SIMPLE|CBS_DROPDOWN|CBS_DROPDOWNLIST|WS_CHILD);
 
-    TRACE("combo style=%08lx, additional style=%08lx\n", dwComboStyle,
+    GetWindowRect(hwnd, &wnrc1);
+    GetClientRect(hwnd, &clrc1);
+    TRACE("EX window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d)\n",
+	  wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom,
+	  clrc1.left, clrc1.top, clrc1.right, clrc1.bottom);
+    TRACE("combo style=%08lx, adding style=%08lx\n", dwComboStyle,
           WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VSCROLL |
           CBS_NOINTEGRALHEIGHT | CBS_DROPDOWNLIST |
@@ -1077,5 +1146,5 @@
     GetClientRect(hwnd, &clrc1);
     GetWindowRect(infoPtr->hwndCombo, &cmbwrc);
-    TRACE("Ex wnd=(%d,%d)-(%d,%d) Ex clt=(%d,%d)-(%d,%d) Cb wnd=(%d,%d)-(%d,%d)\n",
+    TRACE("EX window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d) CB wnd=(%d,%d)-(%d,%d)\n",
 	  wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom,
 	  clrc1.left, clrc1.top, clrc1.right, clrc1.bottom,
@@ -1086,5 +1155,5 @@
 
     GetWindowRect(infoPtr->hwndCombo, &cmbwrc);
-    TRACE("Ex wnd=(%d,%d)-(%d,%d)\n",
+    TRACE("CB window=(%d,%d)-(%d,%d)\n",
 	  cmbwrc.left, cmbwrc.top, cmbwrc.right, cmbwrc.bottom);
     SetWindowPos(hwnd, HWND_TOP, 
@@ -1118,4 +1187,5 @@
     INT cursel, n, oldItem;
     NMCBEENDEDITA cbeend;
+    DWORD oldflags;
 
     TRACE("for command %d\n", command);
@@ -1171,14 +1241,18 @@
 	    }
 	}
-	if (infoPtr->flags & WCBE_ACTEDIT) {
+
+	/* Save flags for testing and reset them */
+	oldflags = infoPtr->flags;
+	infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
+
+	if (oldflags & WCBE_ACTEDIT) {
 	    WideCharToMultiByte (CP_ACP, 0, item->pszText, -1,
 				 cbeend.szText, sizeof(cbeend.szText),
 				 NULL, NULL);
-	    cbeend.fChanged = (infoPtr->flags & WCBE_EDITCHG);
+	    cbeend.fChanged = (oldflags & WCBE_EDITCHG);
 	    cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo,
 						 CB_GETCURSEL, 0, 0);
 	    cbeend.iWhy = CBENF_DROPDOWN;
 
-	    infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
 	    if (COMBOEX_Notify (infoPtr, CBEN_ENDEDITA, 
 				(NMHDR *)&cbeend, FALSE)) {
@@ -1188,6 +1262,12 @@
 	    }
 	}
-	SendMessageW (hwnd, CB_SETCURSEL, cursel, 0);
-	SetFocus(infoPtr->hwndCombo);
+
+	/* if selection has changed the set the new current selection */
+	cursel = SendMessageW (infoPtr->hwndCombo, CB_GETCURSEL, 0, 0);
+	if ((oldflags & WCBE_EDITCHG) || (cursel != infoPtr->selected)) {
+	    infoPtr->selected = cursel;
+	    SendMessageW (hwnd, CB_SETCURSEL, cursel, 0);
+	    SetFocus(infoPtr->hwndCombo);
+	}
 	return 0;
 
@@ -1210,5 +1290,6 @@
 	    ERR("item %d not found. Problem!\n", oldItem);
 	    break;
-	}  
+	}
+	infoPtr->selected = oldItem;
 	COMBOEX_SetEditText (infoPtr, item);
 	return SendMessageW (GetParent (hwnd), WM_COMMAND, wParam, 
@@ -1619,4 +1700,21 @@
 
 static LRESULT
+COMBOEX_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    /* WARNING: The COMBOEX_INFO structure is not yet created */
+    DWORD oldstyle, newstyle;
+
+    oldstyle = (DWORD)GetWindowLongA (hwnd, GWL_STYLE);
+    newstyle = oldstyle & ~(WS_VSCROLL | WS_HSCROLL);
+    if (newstyle != oldstyle) {
+	TRACE("req style %08lx, reseting style %08lx\n",
+	      oldstyle, newstyle);
+	SetWindowLongA (hwnd, GWL_STYLE, newstyle);
+    }
+    return 1;
+}
+
+
+static LRESULT
 COMBOEX_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1656,4 +1754,6 @@
             - (cbx_crect.right-cbx_crect.left); 
 
+    TRACE("winpos=(%d,%d %dx%d) flags=0x%08x\n",
+	  wp->x, wp->y, wp->cx, wp->cy, wp->flags);
     TRACE("EX window=(%d,%d)-(%d,%d), client=(%d,%d)-(%d,%d)\n",
 	  cbx_wrect.left, cbx_wrect.top, cbx_wrect.right, cbx_wrect.bottom,
@@ -1771,5 +1871,5 @@
 		    break;
 		}
-		  
+		infoPtr->selected = oldItem;		  
 		COMBOEX_SetEditText (infoPtr, item);
 		RedrawWindow (infoPtr->hwndCombo, 0, 0, RDW_ERASE | 
@@ -2110,6 +2210,12 @@
 {
     TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx\n", hwnd, uMsg, wParam, lParam);
-    if (!COMBOEX_GetInfoPtr (hwnd) && (uMsg != WM_CREATE))
+
+    if (!COMBOEX_GetInfoPtr (hwnd)) {
+	if (uMsg == WM_CREATE)
+	    return COMBOEX_Create (hwnd, wParam, lParam);
+	if (uMsg == WM_NCCREATE)
+	    COMBOEX_NCCreate (hwnd, wParam, lParam);
         return DefWindowProcA (hwnd, uMsg, wParam, lParam);
+    }
 
     switch (uMsg)
@@ -2167,5 +2273,4 @@
 /*   Combo messages we are not sure if we need to process or just forward */
 	case CB_GETDROPPEDCONTROLRECT:
-	case CB_GETITEMDATA:
 	case CB_GETITEMHEIGHT:
 	case CB_GETLBTEXT:
@@ -2175,8 +2280,7 @@
 	case CB_RESETCONTENT:
 	case CB_SELECTSTRING:
-	case CB_SETITEMDATA:
 	case WM_SETTEXT:
 	case WM_GETTEXT:
-	    FIXME("(0x%x 0x%x 0x%lx): possible missing fucntion\n", 
+	    FIXME("(0x%x 0x%x 0x%lx): possibly missing function\n",
 		  uMsg, wParam, lParam);
 	    return COMBOEX_Forward (hwnd, uMsg, wParam, lParam);
@@ -2196,6 +2300,12 @@
 					    wParam, lParam);
 
+	case CB_GETITEMDATA:
+	    return COMBOEX_GetItemData (hwnd, wParam, lParam);
+
 	case CB_SETCURSEL:
 	    return COMBOEX_SetCursel (hwnd, wParam, lParam);
+
+	case CB_SETITEMDATA:
+	    return COMBOEX_SetItemData (hwnd, wParam, lParam);
 
 	case CB_SETITEMHEIGHT:
@@ -2213,7 +2323,4 @@
 
 /*   Window messages we need to process */
-	case WM_CREATE:
-	    return COMBOEX_Create (hwnd, wParam, lParam);
-
         case WM_DELETEITEM:
 	    return COMBOEX_WM_DeleteItem (hwnd, wParam, lParam);
@@ -2241,5 +2348,5 @@
             return defComCtl32ProcA (hwnd, uMsg, wParam, lParam);
 #else
-            return DefWindowProcA (hwnd, uMsg, wParam, lParam);
+	    return DefWindowProcA (hwnd, uMsg, wParam, lParam);
 #endif
     }
Index: trunk/src/comctl32/comctl32.def
===================================================================
--- trunk/src/comctl32/comctl32.def	(revision 5627)
+++ trunk/src/comctl32/comctl32.def	(revision 5630)
@@ -1,3 +1,3 @@
-; $Id: comctl32.def,v 1.21 2001-03-31 13:25:26 sandervl Exp $
+; $Id: comctl32.def,v 1.22 2001-04-29 10:30:56 sandervl Exp $
 LIBRARY COMCTL32 INITINSTANCE
 DESCRIPTION 'Odin32 System DLL - ComCtl32 - Common Controls Library'
@@ -103,7 +103,12 @@
 ; ordinals????
   FreeMRUListA        = _FreeMRUListA@4            @152
-  AddMRUData          = _AddMRUData@12             @153
-  FindMRUData         = _FindMRUData@16            @154
-  CreateMRUListLazyA  = _CreateMRUListLazyA@16     @155
+  AddMRUStringA       = _AddMRUStringA@8           @153
+  EnumMRUListA        = _EnumMRUListA@16           @154
+  FindMRUStringA      = _FindMRUStringA@12         @155
+  DelMRUString        = _DelMRUString@8            @156
+  CreateMRUListLazyA  = _CreateMRUListLazyA@16     @157
+
+  AddMRUData          = _AddMRUData@12             @167
+  FindMRUData         = _FindMRUData@16            @169
 
   Str_GetPtrA         = _Str_GetPtrA@12            @233
@@ -164,6 +169,7 @@
   StrSpnW             = _COMCTL32_StrSpnW@8        @364
 
-  comctl32_410        = _comctl32_410@16           @410
-  comctl32_411        = _comctl32_411@12           @411
-  comctl32_412        = _comctl32_412@12           @412
-  comctl32_413        = _comctl32_413@16           @413
+                        _comctl32_410@16           @410 NONAME
+                        _comctl32_411@12           @411 NONAME
+                        _comctl32_412@12           @412 NONAME
+                        _comctl32_413@16           @413 NONAME
+                        _COMCTL32_415@20           @415 NONAME
Index: trunk/src/comctl32/comctl32.h
===================================================================
--- trunk/src/comctl32/comctl32.h	(revision 5627)
+++ trunk/src/comctl32/comctl32.h	(revision 5630)
@@ -1,3 +1,3 @@
-/* $Id: comctl32.h,v 1.19 2001-03-31 13:25:26 sandervl Exp $ */
+/* $Id: comctl32.h,v 1.20 2001-04-29 10:30:56 sandervl Exp $ */
 /*
  * Win32 common controls implementation
@@ -208,4 +208,8 @@
 void UPDOWN_Unregister(void);
 
+
+INT  Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen);
+BOOL Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc);
+
 #ifdef __cplusplus
 }
Index: trunk/src/comctl32/comctl32undoc.cpp
===================================================================
--- trunk/src/comctl32/comctl32undoc.cpp	(revision 5627)
+++ trunk/src/comctl32/comctl32undoc.cpp	(revision 5630)
@@ -1,3 +1,3 @@
-/* $Id: comctl32undoc.cpp,v 1.8 2001-03-31 13:25:26 sandervl Exp $ */
+/* $Id: comctl32undoc.cpp,v 1.9 2001-04-29 10:30:56 sandervl Exp $ */
 /*
  * Undocumented functions from COMCTL32.DLL
@@ -2545,3 +2545,101 @@
 }
 
-
+/**************************************************************************
+ * COMCTL32_415 [COMCTL32.415]
+ *
+ * FIXME: What's this supposed to do?
+ *        Parameter 1 is an HWND, you're on your own for the rest.
+ */
+
+BOOL WINAPI COMCTL32_415( HWND hwnd, DWORD b, DWORD c, DWORD d, DWORD e)
+{
+
+   FIXME("(%x, %lx, %lx, %lx, %lx): stub!\n", hwnd, b, c, d, e);
+
+   return TRUE;
+}
+
+/**************************************************************************
+ * Str_GetPtrWtoA [internal]
+ *
+ * Converts a unicode string into a multi byte string
+ *
+ * PARAMS
+ *     lpSrc   [I] Pointer to the unicode source string
+ *     lpDest  [O] Pointer to caller supplied storage for the multi byte string
+ *     nMaxLen [I] Size, in bytes, of the destination buffer
+ *
+ * RETURNS
+ *     Length, in bytes, of the converted string.
+ */
+
+INT
+Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen)
+{
+    INT len;
+
+    TRACE("(%s %p %d)\n", debugstr_w(lpSrc), lpDest, nMaxLen);
+
+    if (!lpDest && lpSrc)
+	return WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
+
+    if (nMaxLen == 0)
+	return 0;
+
+    if (lpSrc == NULL) {
+	lpDest[0] = '\0';
+	return 0;
+    }
+
+    len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
+    if (len >= nMaxLen)
+	len = nMaxLen - 1;
+
+    WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL);
+    lpDest[len] = '\0';
+
+    return len;
+}
+
+
+/**************************************************************************
+ * Str_SetPtrAtoW [internal]
+ *
+ * Converts a multi byte string to a unicode string.
+ * If the pointer to the destination buffer is NULL a buffer is allocated.
+ * If the destination buffer is too small to keep the converted multi byte
+ * string the destination buffer is reallocated. If the source pointer is
+ * NULL, the destination buffer is freed.
+ *
+ * PARAMS
+ *     lppDest [I/O] pointer to a pointer to the destination buffer
+ *     lpSrc   [I] pointer to a multi byte string
+ *
+ * RETURNS
+ *     TRUE: conversion successful
+ *     FALSE: error
+ */
+
+BOOL
+Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc)
+{
+    TRACE("(%p %s)\n", lppDest, lpSrc);
+
+    if (lpSrc) {
+	INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0);
+	LPWSTR ptr = (LPWSTR)COMCTL32_ReAlloc (*lppDest, len*sizeof(WCHAR));
+
+	if (!ptr)
+	    return FALSE;
+	MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len);
+	*lppDest = ptr;
+    }
+    else {
+	if (*lppDest) {
+	    COMCTL32_Free (*lppDest);
+	    *lppDest = NULL;
+	}
+    }
+
+    return TRUE;
+}
Index: trunk/src/comctl32/makefile
===================================================================
--- trunk/src/comctl32/makefile	(revision 5627)
+++ trunk/src/comctl32/makefile	(revision 5630)
@@ -1,3 +1,3 @@
-# $Id: makefile,v 1.31 2000-12-02 23:37:13 bird Exp $
+# $Id: makefile,v 1.32 2001-04-29 10:30:56 sandervl Exp $
 
 #
@@ -57,4 +57,5 @@
 $(ODIN32_LIB)/user32.lib \
 $(ODIN32_LIB)/msvfw32.lib \
+$(ODIN32_LIB)/winmm.lib \
 $(ODIN32_LIB)/$(ODINCRT).lib \
 os2386.lib \
Index: trunk/src/comctl32/rebar.c
===================================================================
--- trunk/src/comctl32/rebar.c	(revision 5630)
+++ trunk/src/comctl32/rebar.c	(revision 5630)
@@ -0,0 +1,3423 @@
+/*
+ * Rebar control    rev 6e
+ *
+ * Copyright 1998, 1999 Eric Kohl
+ *
+ * NOTES
+ *   An author is needed! Any volunteers?
+ *   I will only improve this control once in a while.
+ *     Eric <ekohl@abo.rhein-zeitung.de>
+ *
+ * TODO:
+ *   - vertical placement
+ *   - ComboBox and ComboBoxEx placement
+ *   - center image 
+ *   - Layout code.
+ *   - Display code.
+ *   - Some messages.
+ *   - All notifications.
+
+ * Changes Guy Albertelli <galberte@neo.lrun.com>
+ *  rev 2,3,4
+ *   - Implement initial version of row grouping, row separators,
+ *     text and background colors. Support additional messages. 
+ *     Support RBBS_BREAK. Implement ERASEBKGND and improve painting.
+ *  rev 5
+ *   - implement support for dragging Gripper left or right in a row. Supports
+ *     WM_LBUTTONDOWN, WM_LBUTTONUP, and WM_MOUSEMOVE. Also support 
+ *     RBS_BANDBORDERS.
+ *  rev 6
+ *  1. Make drawing of rebar attempt to match pixel by pixel with MS. (6a)
+ *  2. Fix interlock between REBAR_ForceResize and REBAR_Size (AUTO_RESIZE flag) (6a)
+ *  3. Fix up some of the notifications (RBN_HEIGHTCHANGE). (6a)
+ *  4. Fix up DeleteBand by hiding child window. (6a)
+ *  5. Change how band borders are drawn and rects are invalidated. (6b)
+ *  6. Fix height of bar with only caption text. (6b)
+ *  7. RBBS_NOGRIPPER trumps RBBS_GRIPPERALWAYS (gripper hidden), but 
+ *     RBBS_GRIPPERALWAYS trumps RBBS_FIXEDSIZE (gripper displays). (6b)
+ *  8. New algorithim for AdjustBand:
+ *      For all bands in a row: bands left to right are sized to their "cx"
+ *      size (if space available). Also use max of (cxHeader+cxMinChild) and
+ *      cx. (6c)
+ *  9. New alogrithim for Layout:
+ *      Insert band in row if cxHeader space is available. If adjustment
+ *      rect exists, then back out bands in row from last to second into
+ *      separate rows till "y" adjustment rect equalled or exceeded. (6c)
+ * 10. Implement vertical drag. (6c)
+ * 11. Use DeferWindowPos to set child window position. (6c)
+ * 12. Fixup RBN_CHILDSIZE notify. The rcBand rectangle should start
+ *     after the header. (6d)
+ * 13. Flags for DeferWindowPos seem to always be SWP_NOZORDER in the 
+ *     traces. (6d)
+ * 14. Make handling of ComboBox and ComboBoxEx the same in 
+ *     _MoveChildWindow. (6d)
+ * 15. Changes in phase 2 of _Layout for WinRAR example. (6e)
+ * 16. Do notify change size of children for WM_SIZE message. (6e)
+ * 17. Re-validate first band when second is added (for gripper add). (6e)
+ *
+ *
+ *
+ *    Still to do:
+ *  1. default row height should be the max height of all visible bands
+ *  2. Following still not handled: RBBS_FIXEDBMP, RBBS_CHILDEDGE,
+ *            RBBS_USECHEVRON
+ *  3. RBS_VARHEIGHT is assumed to always be on.
+ *  4. RBBS_HIDDEN (and the CCS_VERT + RBBS_NOVERT case) is not really 
+ *     supported by the following functions:
+ *      _Layout (phase 2), _InternalEraseBkgnd, _InternalHitTest,
+ *      _HandleLRDrag
+ *  5. _HandleLRDrag does not properly position ComboBox or ComboBoxEx 
+ *     children. (See code in _MoveChildWindow.)
+
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "winbase.h"
+#include "wingdi.h"
+#include "wine/unicode.h"
+#include "commctrl.h"
+#include "debugtools.h"
+#ifdef __WIN32OS2__
+#include "ccbase.h"
+#endif
+
+DEFAULT_DEBUG_CHANNEL(rebar);
+
+typedef struct
+{
+    UINT    fStyle;
+    UINT    fMask;
+    COLORREF  clrFore;
+    COLORREF  clrBack;
+    INT     iImage;
+    HWND    hwndChild;
+    UINT    cxMinChild;
+    UINT    cyMinChild;
+    UINT    cx;
+    HBITMAP hbmBack;
+    UINT    wID;
+    UINT    cyChild;
+    UINT    cyMaxChild;
+    UINT    cyIntegral;
+    UINT    cxIdeal;
+    LPARAM    lParam;
+    UINT    cxHeader;
+
+    UINT    lcx;            /* minimum cx for band */
+    UINT    hcx;            /* maximum cx for band */
+    UINT    lcy;            /* minimum cy for band */
+    UINT    hcy;            /* maximum cy for band */
+
+    SIZE    offChild;       /* x,y offset if child is not FIXEDSIZE */
+    UINT    uMinHeight;
+    INT     iRow;           /* row this band assigned to */
+    UINT    fStatus;        /* status flags, reset only by _Validate */
+    UINT    fDraw;          /* drawing flags, reset only by _Layout */
+    RECT    rcBand;         /* calculated band rectangle */
+    RECT    rcGripper;      /* calculated gripper rectangle */
+    RECT    rcCapImage;     /* calculated caption image rectangle */
+    RECT    rcCapText;      /* calculated caption text rectangle */
+    RECT    rcChild;        /* calculated child rectangle */
+
+    LPWSTR    lpText;
+    HWND    hwndPrevParent;
+} REBAR_BAND;
+
+/* fStatus flags */
+#define HAS_GRIPPER    0x00000001
+#define HAS_IMAGE      0x00000002
+#define HAS_TEXT       0x00000004
+
+/* fDraw flags */
+#define DRAW_GRIPPER    0x00000001
+#define DRAW_IMAGE      0x00000002
+#define DRAW_TEXT       0x00000004
+#define DRAW_RIGHTSEP   0x00000010
+#define DRAW_BOTTOMSEP  0x00000020
+#define DRAW_SEPBOTH    (DRAW_RIGHTSEP | DRAW_BOTTOMSEP)
+#define NTF_INVALIDATE  0x01000000
+#define NTF_CHILDSIZE   0x02000000
+
+
+typedef struct
+{
+#ifdef __WIN32OS2__
+    COMCTL32_HEADER header;
+#endif
+    COLORREF   clrBk;       /* background color */
+    COLORREF   clrText;     /* text color */
+    HIMAGELIST himl;        /* handle to imagelist */
+    UINT     uNumBands;   /* number of bands in the rebar */
+    UINT     uNumRows;    /* number of rows of bands */
+    HWND     hwndToolTip; /* handle to the tool tip control */
+    HWND     hwndNotify;  /* notification window (parent) */
+    HFONT    hFont;       /* handle to the rebar's font */
+    SIZE     imageSize;   /* image size (image list) */
+
+    SIZE     calcSize;    /* calculated rebar size */
+    SIZE     oldSize;     /* previous calculated rebar size */
+    BOOL     bUnicode;    /* Unicode flag */
+    UINT     fStatus;     /* Status flags (see below)  */ 
+    HCURSOR  hcurArrow;   /* handle to the arrow cursor */
+    HCURSOR  hcurHorz;    /* handle to the EW cursor */
+    HCURSOR  hcurVert;    /* handle to the NS cursor */
+    HCURSOR  hcurDrag;    /* handle to the drag cursor */
+    INT      iVersion;    /* version number */
+    POINTS   dragStart;   /* x,y of button down */
+    POINTS   dragNow;     /* x,y of this MouseMove */
+    INT      ihitBand;    /* band number of band whose gripper was grabbed */
+    INT      ihitoffset;  /* offset of hotspot from gripper.left */
+
+    REBAR_BAND *bands;      /* pointer to the array of rebar bands */
+} REBAR_INFO;
+
+/* fStatus flags */
+#define BEGIN_DRAG_ISSUED   1
+#define AUTO_RESIZE         2
+#define RESIZE_ANYHOW       4
+#define NTF_HGHTCHG         8
+
+/* ----   REBAR layout constants. Mostly determined by        ---- */
+/* ----   experiment on WIN 98.                               ---- */
+
+/* Width (or height) of separators between bands (either horz. or  */
+/* vert.). True only if RBS_BANDBORDERS is set                     */
+#define SEP_WIDTH_SIZE  2
+#define SEP_WIDTH       ((dwStyle & RBS_BANDBORDERS) ? SEP_WIDTH_SIZE : 0)
+
+/* Blank (background color) space between Gripper (if present)     */
+/* and next item (image, text, or window). Always present          */
+#define REBAR_ALWAYS_SPACE  4
+
+/* Blank (background color) space after Image (if present).        */
+#define REBAR_POST_IMAGE  2
+
+/* Blank (background color) space after Text (if present).         */
+#define REBAR_POST_TEXT  4
+
+/* Height of vertical gripper in a CCS_VERT rebar.                 */
+#define GRIPPER_HEIGHT  16
+
+/* Blank (background color) space before Gripper (if present).     */
+#define REBAR_PRE_GRIPPER   2
+
+/* Width (of normal vertical gripper) or height (of horz. gripper) */
+/* if present.                                                     */
+#define GRIPPER_WIDTH  3
+
+/* This is the increment that is used over the band height */
+/* Determined by experiment.                               */ 
+#define REBARSPACE      4
+
+/* ----   End of REBAR layout constants.                      ---- */
+
+
+/*  The following 4 defines return the proper rcBand element       */
+/*  depending on whether CCS_VERT was set.                         */
+#define rcBlt(b) ((dwStyle & CCS_VERT) ? b->rcBand.top : b->rcBand.left)
+#define rcBrb(b) ((dwStyle & CCS_VERT) ? b->rcBand.bottom : b->rcBand.right)
+#define ircBlt(b) ((dwStyle & CCS_VERT) ? b->rcBand.left : b->rcBand.top)
+#define ircBrb(b) ((dwStyle & CCS_VERT) ? b->rcBand.right : b->rcBand.bottom)
+
+/*  The following define determines if a given band is hidden      */
+#define HIDDENBAND(a)  (((a)->fStyle & RBBS_HIDDEN) ||   \
+                        ((dwStyle & CCS_VERT) &&         \
+                         ((a)->fStyle & RBBS_NOVERT)))
+
+
+#define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongA (hwnd, 0))
+
+
+/* "constant values" retrieved when DLL was initialized    */
+/* FIXME we do this when the classes are registered.       */
+static UINT mindragx = 0;
+static UINT mindragy = 0;
+
+
+static VOID
+REBAR_DumpBandInfo( LPREBARBANDINFOA pB)
+{
+	TRACE("band info: ID=%u, size=%u, style=0x%08x, mask=0x%08x, child=%04x\n",
+	  pB->wID, pB->cbSize, pB->fStyle, pB->fMask, pB->hwndChild); 
+	TRACE("band info: cx=%u, xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
+          pB->cx, pB->cxMinChild, 
+          pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
+	TRACE("band info: xIdeal=%u, xHeader=%u, lParam=0x%08lx, clrF=0x%06lx, clrB=0x%06lx\n",
+	  pB->cxIdeal, pB->cxHeader, pB->lParam, pB->clrFore, pB->clrBack);
+}
+
+static VOID
+REBAR_DumpBand (HWND hwnd)
+{
+    REBAR_INFO *iP = REBAR_GetInfoPtr (hwnd);
+    REBAR_BAND *pB;
+    UINT i;
+
+    if( TRACE_ON(rebar) ) {
+
+      TRACE("hwnd=%04x: color=%08lx/%08lx, bands=%u, rows=%u, cSize=%ld,%ld\n", 
+        hwnd, iP->clrText, iP->clrBk, iP->uNumBands, iP->uNumRows,
+        iP->calcSize.cx, iP->calcSize.cy);
+      TRACE("hwnd=%04x: flags=%08x, dragStart=%d,%d, dragNow=%d,%d, ihitBand=%d\n",
+	    hwnd, iP->fStatus, iP->dragStart.x, iP->dragStart.y,
+	    iP->dragNow.x, iP->dragNow.y,
+	    iP->ihitBand);
+      for (i = 0; i < iP->uNumBands; i++) {
+	pB = &iP->bands[i];
+	TRACE("band # %u: ID=%u, mask=0x%08x, style=0x%08x, child=%04x, row=%u\n",
+	  i, pB->wID, pB->fMask, pB->fStyle, pB->hwndChild, pB->iRow);
+	TRACE("band # %u: xMin=%u, yMin=%u, cx=%u, yChild=%u, yMax=%u, yIntgl=%u, uMinH=%u,\n",
+	  i, pB->cxMinChild, pB->cyMinChild, pB->cx,
+          pB->cyChild, pB->cyMaxChild, pB->cyIntegral, pB->uMinHeight);
+	TRACE("band # %u: header=%u, lcx=%u, hcx=%u, lcy=%u, hcy=%u, offChild=%ld,%ld\n",
+	  i, pB->cxHeader, pB->lcx, pB->hcx, pB->lcy, pB->hcy, pB->offChild.cx, pB->offChild.cy);
+	TRACE("band # %u: fStatus=%08x, fDraw=%08x, Band=(%d,%d)-(%d,%d), Grip=(%d,%d)-(%d,%d)\n",
+	  i, pB->fStatus, pB->fDraw,
+	  pB->rcBand.left, pB->rcBand.top, pB->rcBand.right, pB->rcBand.bottom,
+	  pB->rcGripper.left, pB->rcGripper.top, pB->rcGripper.right, pB->rcGripper.bottom);
+	TRACE("band # %u: Img=(%d,%d)-(%d,%d), Txt=(%d,%d)-(%d,%d), Child=(%d,%d)-(%d,%d)\n",
+	  i,
+	  pB->rcCapImage.left, pB->rcCapImage.top, pB->rcCapImage.right, pB->rcCapImage.bottom,
+	  pB->rcCapText.left, pB->rcCapText.top, pB->rcCapText.right, pB->rcCapText.bottom,
+	  pB->rcChild.left, pB->rcChild.top, pB->rcChild.right, pB->rcChild.bottom);
+      }
+
+    }
+}
+
+static INT
+REBAR_Notify (HWND hwnd, NMHDR *nmhdr, REBAR_INFO *infoPtr, UINT code)
+{
+    HWND parent, owner;
+
+    parent = infoPtr->hwndNotify;
+    if (!parent) {
+        parent = GetParent (hwnd);
+	owner = GetWindow (hwnd, GW_OWNER);
+	if (owner) parent = owner;
+    }
+    nmhdr->idFrom = GetDlgCtrlID (hwnd);
+    nmhdr->hwndFrom = hwnd;
+    nmhdr->code = code;
+
+    return SendMessageA (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom,
+			 (LPARAM)nmhdr);
+}
+
+static INT
+REBAR_Notify_NMREBAR (HWND hwnd, REBAR_INFO *infoPtr, UINT uBand, UINT code)
+{
+    NMREBAR notify_rebar;
+    REBAR_BAND *lpBand;
+
+    notify_rebar.dwMask = 0;
+    if (uBand!=-1) {
+	lpBand = &infoPtr->bands[uBand];
+	if (lpBand->fMask & RBBIM_ID) {
+	    notify_rebar.dwMask |= RBNM_ID;
+	    notify_rebar.wID = lpBand->wID;
+	}
+	if (lpBand->fMask & RBBIM_LPARAM) {
+	    notify_rebar.dwMask |= RBNM_LPARAM;
+	    notify_rebar.lParam = lpBand->lParam;
+	}
+	if (lpBand->fMask & RBBIM_STYLE) {
+	    notify_rebar.dwMask |= RBNM_STYLE;
+	    notify_rebar.fStyle = lpBand->fStyle;
+	}
+    }
+    notify_rebar.uBand = uBand;
+    return REBAR_Notify (hwnd, (NMHDR *)&notify_rebar, infoPtr, code);
+}
+
+static VOID
+REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand, DWORD dwStyle)
+{
+
+    /* draw separators on both the bottom and right */
+    if ((lpBand->fDraw & DRAW_SEPBOTH) == DRAW_SEPBOTH) {
+        RECT rcSep;
+	SetRect (&rcSep,
+		 lpBand->rcBand.left,
+		 lpBand->rcBand.top,
+		 lpBand->rcBand.right + SEP_WIDTH_SIZE,
+		 lpBand->rcBand.bottom + SEP_WIDTH_SIZE);
+	DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOMRIGHT);
+	TRACE("drawing band separator both (%d,%d)-(%d,%d)\n",
+	      rcSep.left, rcSep.top, rcSep.right, rcSep.bottom);
+    }
+
+    /* draw band separator between bands in a row */
+    if ((lpBand->fDraw & DRAW_SEPBOTH) == DRAW_RIGHTSEP) {
+        RECT rcSep;
+	if (dwStyle & CCS_VERT) {
+	    SetRect (&rcSep, 
+		     lpBand->rcBand.left,
+		     lpBand->rcBand.bottom,
+		     lpBand->rcBand.right,
+		     lpBand->rcBand.bottom + SEP_WIDTH_SIZE);
+	    DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOM);
+	}
+	else {
+	    SetRect (&rcSep, 
+		     lpBand->rcBand.right,
+		     lpBand->rcBand.top,
+		     lpBand->rcBand.right + SEP_WIDTH_SIZE,
+		     lpBand->rcBand.bottom);
+	    DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_RIGHT);
+	}
+	TRACE("drawing band separator right (%d,%d)-(%d,%d)\n",
+	      rcSep.left, rcSep.top, rcSep.right, rcSep.bottom);
+    }
+
+    /* draw band separator between rows */
+    if ((lpBand->fDraw & DRAW_SEPBOTH) == DRAW_BOTTOMSEP) {
+        RECT rcRowSep;
+        if (dwStyle & CCS_VERT) {
+	    SetRect (&rcRowSep,
+		     lpBand->rcBand.right,
+		     lpBand->rcBand.top,
+		     lpBand->rcBand.right + SEP_WIDTH_SIZE,
+		     lpBand->rcBand.bottom);
+	    DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_RIGHT);
+	}
+	else {
+	    SetRect (&rcRowSep, 
+		     lpBand->rcBand.left,
+		     lpBand->rcBand.bottom,
+		     lpBand->rcBand.right,
+		     lpBand->rcBand.bottom + SEP_WIDTH_SIZE);
+	    DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_BOTTOM);
+	}
+	TRACE ("drawing band separator bottom (%d,%d)-(%d,%d)\n",
+	       rcRowSep.left, rcRowSep.top,
+	       rcRowSep.right, rcRowSep.bottom);
+    }
+
+    /* draw gripper */
+    if (lpBand->fDraw & DRAW_GRIPPER)
+        DrawEdge (hdc, &lpBand->rcGripper, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
+
+    /* draw caption image */
+    if (lpBand->fDraw & DRAW_IMAGE) {
+	POINT pt;
+
+	/* center image */
+	pt.y = (lpBand->rcCapImage.bottom + lpBand->rcCapImage.top - infoPtr->imageSize.cy)/2;
+	pt.x = (lpBand->rcCapImage.right + lpBand->rcCapImage.left - infoPtr->imageSize.cx)/2;
+
+	ImageList_Draw (infoPtr->himl, lpBand->iImage, hdc,
+			pt.x, pt.y,
+			ILD_TRANSPARENT);
+    }
+
+    /* draw caption text */
+    if (lpBand->fDraw & DRAW_TEXT) {
+	HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
+	INT oldBkMode = SetBkMode (hdc, TRANSPARENT);
+	COLORREF oldcolor = CLR_NONE;
+	if (lpBand->clrFore != CLR_NONE)
+	    oldcolor = SetTextColor (hdc, lpBand->clrFore);
+	DrawTextW (hdc, lpBand->lpText, -1, &lpBand->rcCapText,
+		   DT_CENTER | DT_VCENTER | DT_SINGLELINE);
+	if (oldBkMode != TRANSPARENT)
+	    SetBkMode (hdc, oldBkMode);
+	if (lpBand->clrFore != CLR_NONE)
+	    SetTextColor (hdc, oldcolor);
+	SelectObject (hdc, hOldFont);
+    }
+}
+
+
+static VOID
+REBAR_Refresh (HWND hwnd, HDC hdc)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    REBAR_BAND *lpBand;
+    UINT i, oldrow;
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+
+    oldrow = infoPtr->bands[0].iRow;
+    for (i = 0; i < infoPtr->uNumBands; i++) {
+	lpBand = &infoPtr->bands[i];
+
+	if ((lpBand->fStyle & RBBS_HIDDEN) || 
+	    ((dwStyle & CCS_VERT) &&
+	     (lpBand->fStyle & RBBS_NOVERT)))
+	    continue;
+
+	/* now draw the band */
+	REBAR_DrawBand (hdc, infoPtr, lpBand, dwStyle);
+
+    }
+}
+
+static void
+REBAR_AdjustBands (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend,
+		   INT maxx, INT usedx, INT mcy, DWORD dwStyle)
+     /* Function: This routine distributes the extra space in a row */
+     /*  by increasing bands from left to right to their "cx" width.*/
+     /*  Uses "cxHeader"+"cxMinChild" if it is bigger than "cx".    */
+{
+    REBAR_BAND *lpBand;
+    UINT i;
+    INT j, k;
+    INT incr, current_width, lastx=0;
+    RECT oldband;
+
+    TRACE("start=%u, end=%u, max x=%d, used x=%d, max y=%d\n",
+	  rowstart, rowend-1, maxx, usedx, mcy);
+
+    incr = maxx - usedx;
+
+    for (i = rowstart; i<rowend; i++) {
+        lpBand = &infoPtr->bands[i];
+	if (HIDDENBAND(lpBand)) continue;
+	j = 0;
+	k = 0;
+	oldband = lpBand->rcBand;
+
+	/* get the current width of the band */
+	if (dwStyle & CCS_VERT)
+	    current_width = lpBand->rcBand.bottom - lpBand->rcBand.top;
+	else
+	    current_width = lpBand->rcBand.right - lpBand->rcBand.left;
+
+	/* compute (in "j") the adjustment for this band */
+	/* FIXME ??? should this not use "cx" and "cxHeader" and "cxMinChild" */
+	if (!(lpBand->fStyle & RBBS_FIXEDSIZE)) {
+	    if ((lpBand->fMask & RBBIM_SIZE) && (lpBand->cx > 0))
+	        j = min(lpBand->cx - current_width, incr);
+	    if ((lpBand->fMask & RBBIM_CHILDSIZE) &&
+		(lpBand->cxMinChild > 0) &&
+		(lpBand->fMask & RBBIM_CHILD) &&
+		(lpBand->hwndChild)) {
+	        k = lpBand->cxHeader + lpBand->cxMinChild - current_width;
+		if (k > 0) {
+		    j = max(k, j);
+		    j = min(j, incr);
+		}
+	    }
+	}
+
+	incr -= j;
+
+	/* validate values */
+	if (incr < 0) {
+	    ERR("failed, incr=%d, current_width=%d, j=%d, k=%d\n",
+		incr, current_width, j, k);
+	    j -= incr;
+	    incr = 0;
+	}
+	if (lastx + j + current_width > maxx) {
+	    ERR("exceeded maximum, lastx=%d, j=%d, current_width=%d\n",
+		lastx, j, current_width);
+	    j = maxx - lastx - current_width;
+	    incr = 0;
+	}
+
+	/* adjust the band rectangle for adding width  */
+	/* and setting height of all bands in row.     */
+	if (dwStyle & CCS_VERT) {
+	    lpBand->rcBand.top = lastx;
+	    lpBand->rcBand.bottom = lastx + j + current_width;
+	    if ((lpBand->rcBand.top != oldband.top) ||
+		(lpBand->rcBand.bottom != oldband.bottom))
+	        lpBand->fDraw |= NTF_INVALIDATE;
+	    if (lpBand->rcBand.right != lpBand->rcBand.left + mcy) {
+	        lpBand->rcBand.right = lpBand->rcBand.left + mcy;
+		lpBand->fDraw |= NTF_INVALIDATE;
+	    }
+	}
+	else {
+	    lpBand->rcBand.left = lastx;
+	    lpBand->rcBand.right = lastx + j + current_width;
+	    if ((lpBand->rcBand.left != oldband.left) ||
+		(lpBand->rcBand.right != oldband.right))
+	        lpBand->fDraw |= NTF_INVALIDATE;
+	    if (lpBand->rcBand.bottom != lpBand->rcBand.top + mcy) {
+	        lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
+		lpBand->fDraw |= NTF_INVALIDATE;
+	    }
+	}
+
+	/* update to the next band start */
+	lastx += (j + current_width + SEP_WIDTH);
+	if (j) {
+	    TRACE("band %d row=%d: changed to (%d,%d)-(%d,%d)\n",
+		  i, lpBand->iRow,
+		  lpBand->rcBand.left, lpBand->rcBand.top,
+		  lpBand->rcBand.right, lpBand->rcBand.bottom);
+	}
+	else {
+	    TRACE("band %d row=%d: unchanged (%d,%d)-(%d,%d)\n",
+		  i, lpBand->iRow,
+		  lpBand->rcBand.left, lpBand->rcBand.top,
+		  lpBand->rcBand.right, lpBand->rcBand.bottom);
+	}
+    }
+
+    /* if any remaining space then add to the rowstart band */
+    if (incr > 0) {
+        lpBand = &infoPtr->bands[rowstart];
+	lpBand->rcBand.right += incr;
+	TRACE("band %d row=%d: extended to (%d,%d)-(%d,%d)\n",
+	      rowstart, lpBand->iRow,
+	      lpBand->rcBand.left, lpBand->rcBand.top,
+	      lpBand->rcBand.right, lpBand->rcBand.bottom);
+	for (i=rowstart+1; i<rowend; i++) {
+	    lpBand = &infoPtr->bands[i];
+	    if (HIDDENBAND(lpBand)) continue;
+	    lpBand->rcBand.left += incr;
+	    lpBand->rcBand.right += incr;
+	    lpBand->fDraw |= NTF_INVALIDATE;
+	}
+    }
+}
+
+static void
+REBAR_CalcHorzBand (HWND hwnd, REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify, DWORD dwStyle)
+     /* Function: this routine initializes all the rectangles in */
+     /*  each band in a row to fit in the adjusted rcBand rect.  */
+     /* *** Supports only Horizontal bars. ***                   */
+{
+    REBAR_BAND *lpBand;
+    UINT i, xoff, yoff;
+    HWND parenthwnd;
+    RECT oldChild, work;
+
+    /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
+    parenthwnd = GetParent (hwnd);
+
+    for(i=rstart; i<rend; i++){
+      lpBand = &infoPtr->bands[i];
+      if (HIDDENBAND(lpBand)) {
+          SetRect (&lpBand->rcChild,
+		   lpBand->rcBand.right, lpBand->rcBand.top,
+		   lpBand->rcBand.right, lpBand->rcBand.bottom);
+	  continue;
+      }
+
+      oldChild = lpBand->rcChild;
+
+      /* set initial gripper rectangle */
+      SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
+	       lpBand->rcBand.left, lpBand->rcBand.bottom);
+
+      /* calculate gripper rectangle */
+      if ( lpBand->fStatus & HAS_GRIPPER) {
+	  lpBand->fDraw |= DRAW_GRIPPER;
+	  lpBand->rcGripper.left   += REBAR_PRE_GRIPPER;
+	  lpBand->rcGripper.right  = lpBand->rcGripper.left + GRIPPER_WIDTH;
+	  lpBand->rcGripper.top    += 2;
+	  lpBand->rcGripper.bottom -= 2;
+
+	  SetRect (&lpBand->rcCapImage,
+		   lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.top,
+		   lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.bottom);
+      }
+      else {  /* no gripper will be drawn */
+	  xoff = 0;
+	  if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
+	      /* if no gripper but either image or text, then leave space */
+	      xoff = REBAR_ALWAYS_SPACE;
+	  SetRect (&lpBand->rcCapImage, 
+		   lpBand->rcBand.left+xoff, lpBand->rcBand.top,
+		   lpBand->rcBand.left+xoff, lpBand->rcBand.bottom);
+      }
+
+      /* image is visible */
+      if (lpBand->fStatus & HAS_IMAGE) {
+	  lpBand->fDraw |= DRAW_IMAGE;
+	  lpBand->rcCapImage.right  += infoPtr->imageSize.cx;
+	  lpBand->rcCapImage.bottom = lpBand->rcCapImage.top + infoPtr->imageSize.cy;
+
+	  /* set initial caption text rectangle */
+	  SetRect (&lpBand->rcCapText,
+		   lpBand->rcCapImage.right+REBAR_POST_IMAGE, lpBand->rcBand.top+1,
+		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
+	  /* update band height 
+	  if (lpBand->uMinHeight < infoPtr->imageSize.cy + 2) {
+	      lpBand->uMinHeight = infoPtr->imageSize.cy + 2;
+	      lpBand->rcBand.bottom = lpBand->rcBand.top + lpBand->uMinHeight;
+	  }  */
+      }
+      else {
+	  /* set initial caption text rectangle */
+	  SetRect (&lpBand->rcCapText, lpBand->rcCapImage.right, lpBand->rcBand.top+1,
+		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
+      }
+
+      /* text is visible */
+      if (lpBand->fStatus & HAS_TEXT) {
+	  lpBand->fDraw |= DRAW_TEXT;
+	  lpBand->rcCapText.right = max(lpBand->rcCapText.left, 
+					lpBand->rcCapText.right-REBAR_POST_TEXT);
+      }
+
+      /* set initial child window rectangle if there is a child */
+      if (lpBand->fMask & RBBIM_CHILD) {
+	  xoff = lpBand->offChild.cx;
+	  yoff = lpBand->offChild.cy;
+	  SetRect (&lpBand->rcChild,
+		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top+yoff,
+		   lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
+      }
+      else {
+          SetRect (&lpBand->rcChild,
+		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top,
+		   lpBand->rcBand.right, lpBand->rcBand.bottom);
+      }
+
+      /* flag if notify required and invalidate rectangle */
+      if (notify && 
+	  ((oldChild.right-oldChild.left != lpBand->rcChild.right-lpBand->rcChild.left) ||
+	   (oldChild.bottom-oldChild.top != lpBand->rcChild.bottom-lpBand->rcChild.top))) {
+	  TRACE("Child rectangle changed for band %u\n", i);
+	  TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
+		oldChild.left, oldChild.top,
+	        oldChild.right, oldChild.bottom,
+		lpBand->rcChild.left, lpBand->rcChild.top,
+	        lpBand->rcChild.right, lpBand->rcChild.bottom);
+	  lpBand->fDraw |= NTF_CHILDSIZE;
+      }
+      if (lpBand->fDraw & NTF_INVALIDATE) {
+	  TRACE("invalidating (%d,%d)-(%d,%d)\n",
+		lpBand->rcBand.left, 
+		lpBand->rcBand.top,
+		lpBand->rcBand.right + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0), 
+		lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0));
+	  lpBand->fDraw &= ~NTF_INVALIDATE;
+	  work = lpBand->rcBand;
+	  if (lpBand->fDraw & DRAW_RIGHTSEP) work.right += SEP_WIDTH_SIZE;
+	  if (lpBand->fDraw & DRAW_BOTTOMSEP) work.bottom += SEP_WIDTH_SIZE;
+	  InvalidateRect(hwnd, &work, TRUE);
+      }
+
+    }
+
+}
+
+
+static VOID
+REBAR_CalcVertBand (HWND hwnd, REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify, DWORD dwStyle)
+     /* Function: this routine initializes all the rectangles in */
+     /*  each band in a row to fit in the adjusted rcBand rect.  */
+     /* *** Supports only Vertical bars. ***                     */
+{
+    REBAR_BAND *lpBand;
+    UINT i, xoff, yoff;
+    NMREBARCHILDSIZE  rbcz;
+    HWND parenthwnd;
+    RECT oldChild, work;
+
+    rbcz.hdr.hwndFrom = hwnd;
+    rbcz.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
+    /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
+    parenthwnd = GetParent (hwnd);
+
+    for(i=rstart; i<rend; i++){
+	lpBand = &infoPtr->bands[i];
+	if (HIDDENBAND(lpBand)) continue;
+	oldChild = lpBand->rcChild;
+
+	/* set initial gripper rectangle */
+	SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
+		 lpBand->rcBand.right, lpBand->rcBand.top);
+
+	/* calculate gripper rectangle */
+	if (lpBand->fStatus & HAS_GRIPPER) {
+	    lpBand->fDraw |= DRAW_GRIPPER;
+
+	    if (dwStyle & RBS_VERTICALGRIPPER) {
+		/*  vertical gripper  */
+		lpBand->rcGripper.left   += 3;
+		lpBand->rcGripper.right  = lpBand->rcGripper.left + GRIPPER_WIDTH;
+		lpBand->rcGripper.top    += REBAR_PRE_GRIPPER;
+		lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_HEIGHT;
+
+		/* initialize Caption image rectangle  */
+		SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
+			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
+			 lpBand->rcBand.right,
+			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
+	    }
+	    else {
+		/*  horizontal gripper  */
+		lpBand->rcGripper.left   += 3;
+		lpBand->rcGripper.right  -= 3;
+		lpBand->rcGripper.top    += REBAR_PRE_GRIPPER;
+		lpBand->rcGripper.bottom  = lpBand->rcGripper.top + GRIPPER_WIDTH;
+
+		/* initialize Caption image rectangle  */
+		SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
+			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
+			 lpBand->rcBand.right,
+			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
+	    }
+	}
+	else {  /* no gripper will be drawn */
+	    xoff = 0;
+	    if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
+		/* if no gripper but either image or text, then leave space */
+		xoff = REBAR_ALWAYS_SPACE;
+	    /* initialize Caption image rectangle  */
+	    SetRect (&lpBand->rcCapImage, 
+		     lpBand->rcBand.left, lpBand->rcBand.top+xoff,
+		     lpBand->rcBand.right, lpBand->rcBand.top+xoff);
+	}
+
+	/* image is visible */
+	if (lpBand->fStatus & HAS_IMAGE) {
+	    lpBand->fDraw |= DRAW_IMAGE;
+
+	    lpBand->rcCapImage.right  = lpBand->rcCapImage.left + infoPtr->imageSize.cx;
+	    lpBand->rcCapImage.bottom += infoPtr->imageSize.cy;
+
+	    /* set initial caption text rectangle */
+	    SetRect (&lpBand->rcCapText, 
+		     lpBand->rcBand.left, lpBand->rcCapImage.bottom+REBAR_POST_IMAGE,
+		     lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
+	    /* update band height *
+	       if (lpBand->uMinHeight < infoPtr->imageSize.cx + 2) {
+	       lpBand->uMinHeight = infoPtr->imageSize.cx + 2;
+	       lpBand->rcBand.right = lpBand->rcBand.left + lpBand->uMinHeight;
+	       } */
+	}
+	else {
+	    /* set initial caption text rectangle */
+	    SetRect (&lpBand->rcCapText, 
+		     lpBand->rcBand.left, lpBand->rcCapImage.bottom,
+		     lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
+	}
+
+	/* text is visible */
+	if (lpBand->fStatus & HAS_TEXT) {
+	    lpBand->fDraw |= DRAW_TEXT;
+	    lpBand->rcCapText.bottom = max(lpBand->rcCapText.top,
+					   lpBand->rcCapText.bottom-REBAR_POST_TEXT);
+	}
+
+	/* set initial child window rectangle if there is a child */
+	if (lpBand->fMask & RBBIM_CHILD) {
+	    yoff = lpBand->offChild.cx;
+	    xoff = lpBand->offChild.cy;
+	    SetRect (&lpBand->rcChild,
+		     lpBand->rcBand.left+xoff, lpBand->rcBand.top+lpBand->cxHeader,
+		     lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
+	}
+	else {
+	    SetRect (&lpBand->rcChild,
+		     lpBand->rcBand.left, lpBand->rcBand.top+lpBand->cxHeader,
+		     lpBand->rcBand.right, lpBand->rcBand.bottom);
+	}
+
+	/* flag if notify required and invalidate rectangle */
+	if (notify && 
+	    ((oldChild.right-oldChild.left != lpBand->rcChild.right-lpBand->rcChild.left) ||
+	     (oldChild.bottom-oldChild.top != lpBand->rcChild.bottom-lpBand->rcChild.top))) {
+	    TRACE("Child rectangle changed for band %u\n", i);
+	    TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
+		  oldChild.left, oldChild.top,
+		  oldChild.right, oldChild.bottom,
+		  lpBand->rcChild.left, lpBand->rcChild.top,
+		  lpBand->rcChild.right, lpBand->rcChild.bottom);
+	    lpBand->fDraw |= NTF_CHILDSIZE;
+	}
+	if (lpBand->fDraw & NTF_INVALIDATE) {
+	    TRACE("invalidating (%d,%d)-(%d,%d)\n",
+		  lpBand->rcBand.left, 
+		  lpBand->rcBand.top,
+		  lpBand->rcBand.right + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0), 
+		  lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0));
+	    lpBand->fDraw &= ~NTF_INVALIDATE;
+	    work = lpBand->rcBand;
+	    if (lpBand->fDraw & DRAW_RIGHTSEP) work.bottom += SEP_WIDTH_SIZE;
+	    if (lpBand->fDraw & DRAW_BOTTOMSEP) work.right += SEP_WIDTH_SIZE;
+	    InvalidateRect(hwnd, &work, TRUE);
+	}
+
+    }
+}
+
+
+static VOID
+REBAR_Layout (HWND hwnd, LPRECT lpRect, BOOL notify, BOOL resetclient)
+     /* Function: This routine is resposible for laying out all */
+     /*  the bands in a rebar. It assigns each band to a row and*/
+     /*  determines when to start a new row.                    */
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+    REBAR_BAND *lpBand, *prevBand;
+    RECT rcClient, rcAdj, rcoldBand;
+    INT x, y, cx, cxsep, mcy, clientcx, clientcy;
+    INT adjcx, adjcy, row, rightx, bottomy, origheight;
+    UINT i, rowstartband;
+    BOOL dobreak;
+
+    GetClientRect (hwnd, &rcClient);
+    TRACE("Client is (%d,%d)-(%d,%d)\n",
+	  rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+
+    if (lpRect) {
+	rcAdj = *lpRect;
+	TRACE("adjustment rect is (%d,%d)-(%d,%d)\n",
+	      rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom);
+    }
+    else {
+        CopyRect (&rcAdj, &rcClient);
+    }
+
+    clientcx = rcClient.right - rcClient.left;
+    clientcy = rcClient.bottom - rcClient.top;
+    adjcx = rcAdj.right - rcAdj.left;
+    adjcy = rcAdj.bottom - rcAdj.top;
+    if (resetclient) {
+        TRACE("window client rect will be set to adj rect\n");
+        clientcx = adjcx;
+        clientcy = adjcy;
+    }
+
+    /* save height of original control */
+    if (dwStyle & CCS_VERT) 
+        origheight = infoPtr->calcSize.cx;
+    else
+        origheight = infoPtr->calcSize.cy;
+
+
+    /* ******* Start Phase 1 - all bands on row at minimum size ******* */
+
+    x = 0;
+    y = 0;
+    row = 1;
+    cx = 0;
+    mcy = 0;
+    prevBand = NULL;
+
+    for (i = 0; i < infoPtr->uNumBands; i++) {
+	lpBand = &infoPtr->bands[i];
+	lpBand->fDraw = 0;
+	lpBand->iRow = row;
+
+	if ((lpBand->fStyle & RBBS_HIDDEN) || 
+	    ((dwStyle & CCS_VERT) && (lpBand->fStyle & RBBS_NOVERT)))
+	    continue;
+
+	rcoldBand = lpBand->rcBand;
+
+	/* separator from previous band */
+	cxsep = ( ((dwStyle & CCS_VERT) ? y : x)==0) ? 0 : SEP_WIDTH;  
+
+	/* Header: includes gripper, text, image */
+	cx = lpBand->cxHeader;   
+	if (lpBand->fStyle & RBBS_FIXEDSIZE) cx += lpBand->lcx;
+
+	if (dwStyle & CCS_VERT)
+	    dobreak = (y + cx + cxsep > adjcy);
+        else
+	    dobreak = (x + cx + cxsep > adjcx);
+
+	/* This is the check for whether we need to start a new row */
+	if ( ( (lpBand->fStyle & RBBS_BREAK) && (i != 0) ) ||
+	     ( ((dwStyle & CCS_VERT) ? (y != 0) : (x != 0)) && dobreak)) {
+	    TRACE("Spliting to new row %d on band %u\n", row+1, i);
+	    if (dwStyle & CCS_VERT) {
+		y = 0;
+		x += (mcy + SEP_WIDTH);
+	    }
+	    else {
+		x = 0;
+		y += (mcy + SEP_WIDTH);
+	    }
+
+	    /* FIXME: if not RBS_VARHEIGHT then find max */
+	    mcy = 0;
+	    cxsep = 0;
+	    row++;
+	    lpBand->iRow = row;
+	    prevBand = NULL;
+	}
+
+	if (mcy < lpBand->lcy + REBARSPACE) mcy = lpBand->lcy + REBARSPACE;
+
+	/* if boundary rect specified then limit mcy */
+	if (lpRect) {
+	    if (dwStyle & CCS_VERT) {
+	        if (x+mcy > adjcx) {
+		    mcy = adjcx - x;
+		    TRACE("row %u limiting mcy=%d, adjcx=%d, x=%d\n",
+			  i, mcy, adjcx, x);
+		}
+	    }
+	    else {
+	        if (y+mcy > adjcy) {
+		    mcy = adjcy - y;
+		    TRACE("row %u limiting mcy=%d, adjcy=%d, y=%d\n",
+			  i, mcy, adjcy, y);
+		}
+	    }
+	}
+
+	if (dwStyle & CCS_VERT) {
+	    /* bound the bottom side if we have a bounding rectangle */
+	    if ((x>0) && (dwStyle & RBS_BANDBORDERS) && prevBand)
+	        prevBand->fDraw |= DRAW_RIGHTSEP;
+	    rightx = clientcx;
+	    bottomy = (lpRect) ? min(clientcy, y+cxsep+cx) : y+cxsep+cx;
+	    lpBand->rcBand.left   = x;
+	    lpBand->rcBand.right  = x + min(mcy, lpBand->lcy+REBARSPACE);
+	    lpBand->rcBand.top    = min(bottomy, y + cxsep);
+	    lpBand->rcBand.bottom = bottomy;
+	    lpBand->uMinHeight = lpBand->lcy;
+	    if (!EqualRect(&rcoldBand, &lpBand->rcBand))
+	        lpBand->fDraw |= NTF_INVALIDATE;
+	    y = bottomy;
+	}
+	else {
+	    /* bound the right side if we have a bounding rectangle */
+	    if ((x>0) && (dwStyle & RBS_BANDBORDERS) && prevBand)
+	        prevBand->fDraw |= DRAW_RIGHTSEP;
+	    rightx = (lpRect) ? min(clientcx, x+cxsep+cx) : x+cxsep+cx;
+	    bottomy = clientcy;
+	    lpBand->rcBand.left   = min(rightx, x + cxsep);
+	    lpBand->rcBand.right  = rightx;
+	    lpBand->rcBand.top    = y;
+	    lpBand->rcBand.bottom = y + min(mcy, lpBand->lcy+REBARSPACE);
+	    lpBand->uMinHeight = lpBand->lcy;
+	    if (!EqualRect(&rcoldBand, &lpBand->rcBand))
+	        lpBand->fDraw |= NTF_INVALIDATE;
+	    x = rightx;
+	}
+	TRACE("band %u, row %d, (%d,%d)-(%d,%d)\n",
+	      i, row,
+	      lpBand->rcBand.left, lpBand->rcBand.top,
+	      lpBand->rcBand.right, lpBand->rcBand.bottom);
+	prevBand = lpBand;
+
+    } /* for (i = 0; i < infoPtr->uNumBands... */
+
+    if (dwStyle & CCS_VERT)
+        x += mcy;
+    else
+        y += mcy;
+
+    if (infoPtr->uNumBands)
+        infoPtr->uNumRows = row;
+
+    /* ******* End Phase 1 - all bands on row at minimum size ******* */
+
+
+    /* ******* Start Phase 2 - split rows till adjustment height full ******* */
+
+    /* assumes that the following variables contain:                 */
+    /*   y/x     current height/width of all rows                    */
+    if (lpRect) {
+        INT i, j, prev_rh, current_rh, new_rh, adj_rh;
+	REBAR_BAND *prev, *current, *walk;
+
+/*	if (((dwStyle & CCS_VERT) ? (x < adjcx) : (y < adjcy)) && */
+
+	if (((dwStyle & CCS_VERT) ? (adjcx - x > 4) : (adjcy - y > 4)) && 
+	    (infoPtr->uNumBands > 1)) {
+	    for (i=infoPtr->uNumBands-2; i>=0; i--) {
+		TRACE("adjcx=%d, adjcy=%d, x=%d, y=%d\n",
+		      adjcx, adjcy, x, y);
+	        prev = &infoPtr->bands[i];
+		prev_rh = ircBrb(prev) - ircBlt(prev);
+		current = &infoPtr->bands[i+1];
+		current_rh = ircBrb(current) - ircBlt(current);
+		if (prev->iRow == current->iRow) {
+		    new_rh = current->lcy + REBARSPACE;
+		    adj_rh = prev_rh + new_rh + SEP_WIDTH - current_rh;
+		    infoPtr->uNumRows++;
+		    current->fDraw |= NTF_INVALIDATE;
+		    current->iRow++;
+		    if (dwStyle & CCS_VERT) {
+		        current->rcBand.top = 0;
+			current->rcBand.bottom = clientcy;
+			current->rcBand.left += (prev_rh + SEP_WIDTH);
+			current->rcBand.right = current->rcBand.left + new_rh;
+			x += adj_rh;
+		    }
+		    else {
+		        current->rcBand.left = 0;
+			current->rcBand.right = clientcx;
+			current->rcBand.top += (prev_rh + SEP_WIDTH);
+			current->rcBand.bottom = current->rcBand.top + new_rh;
+			y += adj_rh;
+		    }
+		    TRACE("moving band %d to own row at (%d,%d)-(%d,%d)\n",
+			  i+1,
+			  current->rcBand.left, current->rcBand.top,
+			  current->rcBand.right, current->rcBand.bottom);
+		    TRACE("prev band %d at (%d,%d)-(%d,%d)\n",
+			  i,
+			  prev->rcBand.left, prev->rcBand.top,
+			  prev->rcBand.right, prev->rcBand.bottom);
+		    TRACE("values: prev_rh=%d, current_rh=%d, new_rh=%d, adj_rh=%d\n",
+			  prev_rh, current_rh, new_rh, adj_rh);
+		    /* for bands below current adjust row # and top/bottom */
+		    for (j = i+2; j<infoPtr->uNumBands; j++) {
+		        walk = &infoPtr->bands[j];
+			walk->fDraw |= NTF_INVALIDATE;
+			walk->iRow++;
+			if (dwStyle & CCS_VERT) {
+			    walk->rcBand.left += adj_rh;
+			    walk->rcBand.right += adj_rh;
+			}
+			else {
+			    walk->rcBand.top += adj_rh;
+			    walk->rcBand.bottom += adj_rh;
+			}
+		    }
+		    if ((dwStyle & CCS_VERT) ? (x >= adjcx) : (y >= adjcy)) 
+		        break; /* all done */
+		}
+	    }
+	}
+    }
+
+    /* ******* End Phase 2 - split rows till adjustment height full ******* */
+
+
+
+    /* ******* Start Phase 3 - adjust all bands for width full ******* */
+
+    if (infoPtr->uNumBands) {
+	REBAR_BAND *prev, *current;
+	/* If RBS_BANDBORDERS set then indicate to draw bottom separator */
+	if (dwStyle & RBS_BANDBORDERS) {
+	    for (i = 0; i < infoPtr->uNumBands; i++) {
+	        lpBand = &infoPtr->bands[i];
+		if (HIDDENBAND(lpBand)) continue;
+		if (lpBand->iRow < infoPtr->uNumRows) 
+		    lpBand->fDraw |= DRAW_BOTTOMSEP;
+	    }
+	}
+
+	/* Adjust the horizontal and vertical of each band */
+	prev = &infoPtr->bands[0];
+	current = prev;
+	mcy = prev->lcy + REBARSPACE;
+	rowstartband = 0;
+	for (i=1; i<infoPtr->uNumBands; i++) {
+	    prev = &infoPtr->bands[i-1];
+	    current = &infoPtr->bands[i];
+	    if (prev->iRow != current->iRow) {
+	        REBAR_AdjustBands (infoPtr, rowstartband, i,
+				   (dwStyle & CCS_VERT) ? clientcy : clientcx,
+				   rcBrb(prev),
+				   mcy, dwStyle);
+		mcy = 0;
+		rowstartband = i;
+	    }
+	    if (mcy < current->lcy + REBARSPACE)
+	        mcy = current->lcy + REBARSPACE;
+	}
+	REBAR_AdjustBands (infoPtr, rowstartband, infoPtr->uNumBands,
+			   (dwStyle & CCS_VERT) ? clientcy : clientcx,
+			   rcBrb(current),
+			   mcy, dwStyle);
+
+	/* Calculate the other rectangles in each band */
+	if (dwStyle & CCS_VERT) {
+	    REBAR_CalcVertBand (hwnd, infoPtr, 0, infoPtr->uNumBands,
+				notify, dwStyle);
+	}
+	else {
+	    REBAR_CalcHorzBand (hwnd, infoPtr, 0, infoPtr->uNumBands, 
+				notify, dwStyle);
+	}
+    }
+
+    /* ******* End Phase 3 - adjust all bands for width full ******* */
+
+
+    /* FIXME: if not RBS_VARHEIGHT then find max mcy and adj rect*/
+
+    infoPtr->oldSize = infoPtr->calcSize;
+    if (dwStyle & CCS_VERT) {
+	infoPtr->calcSize.cx = x;
+	infoPtr->calcSize.cy = clientcy;
+	TRACE("vert, notify=%d, x=%d, origheight=%d\n",
+	      notify, x, origheight);
+	if (notify && (x != origheight)) infoPtr->fStatus |= NTF_HGHTCHG;
+    }
+    else {
+	infoPtr->calcSize.cx = clientcx;
+	infoPtr->calcSize.cy = y;
+	TRACE("horz, notify=%d, y=%d, origheight=%d\n",
+	      notify, y, origheight);
+	if (notify && (y != origheight)) infoPtr->fStatus |= NTF_HGHTCHG; 
+    }
+    REBAR_DumpBand (hwnd);
+}
+
+
+static VOID
+REBAR_ForceResize (HWND hwnd)
+     /* Function: This changes the size of the REBAR window to that */
+     /*  calculated by REBAR_Layout.                                */
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    RECT rc;
+
+    TRACE( " from [%ld x %ld] to [%ld x %ld]!\n",
+	   infoPtr->oldSize.cx, infoPtr->oldSize.cy,
+	   infoPtr->calcSize.cx, infoPtr->calcSize.cy);
+
+    /* if size did not change then skip process */
+    if ((infoPtr->oldSize.cx == infoPtr->calcSize.cx) &&
+	(infoPtr->oldSize.cy == infoPtr->calcSize.cy) &&
+	!(infoPtr->fStatus & RESIZE_ANYHOW))
+        return;
+
+    infoPtr->fStatus &= ~RESIZE_ANYHOW;
+    /* Set flag to ignore next WM_SIZE message */
+    infoPtr->fStatus |= AUTO_RESIZE;
+
+    rc.left = 0;
+    rc.top = 0;
+    rc.right  = infoPtr->calcSize.cx;
+    rc.bottom = infoPtr->calcSize.cy;
+
+    if (GetWindowLongA (hwnd, GWL_STYLE) & WS_BORDER) {
+	InflateRect (&rc, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
+    }
+
+    SetWindowPos (hwnd, 0, 0, 0,
+		    rc.right - rc.left, rc.bottom - rc.top,
+		    SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
+}
+
+
+static VOID
+REBAR_MoveChildWindows (HWND hwnd)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    REBAR_BAND *lpBand;
+    CHAR szClassName[40];
+    UINT i;
+    NMREBARCHILDSIZE  rbcz;
+    NMHDR heightchange;
+    HDWP deferpos;
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+
+    if (!(deferpos = BeginDeferWindowPos(8)))
+        ERR("BeginDeferWindowPso returned NULL\n");
+
+    for (i = 0; i < infoPtr->uNumBands; i++) {
+	lpBand = &infoPtr->bands[i];
+
+	if (HIDDENBAND(lpBand)) continue;
+	if (lpBand->hwndChild) {
+	    TRACE("hwndChild = %x\n", lpBand->hwndChild);
+
+	    if (lpBand->fDraw & NTF_CHILDSIZE) {
+	        lpBand->fDraw &= ~NTF_CHILDSIZE;
+		rbcz.uBand = i;
+		rbcz.wID = lpBand->wID;
+		rbcz.rcChild = lpBand->rcChild;
+		rbcz.rcBand = lpBand->rcBand;
+		rbcz.rcBand.left += lpBand->cxHeader;
+		REBAR_Notify (hwnd, (NMHDR *)&rbcz, infoPtr, RBN_CHILDSIZE);
+		if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) {
+		    TRACE("Child rect changed by NOTIFY for band %u\n", i);
+		    TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
+			  lpBand->rcChild.left, lpBand->rcChild.top,
+			  lpBand->rcChild.right, lpBand->rcChild.bottom,
+			  rbcz.rcChild.left, rbcz.rcChild.top,
+			  rbcz.rcChild.right, rbcz.rcChild.bottom);
+		}
+	    }
+
+	    GetClassNameA (lpBand->hwndChild, szClassName, 40);
+	    if (!lstrcmpA (szClassName, "ComboBox") ||
+		!lstrcmpA (szClassName, WC_COMBOBOXEXA)) {
+		INT nEditHeight, yPos;
+		RECT rc;
+
+		/* special placement code for combo or comboex box */
+
+
+		/* get size of edit line */
+		GetWindowRect (lpBand->hwndChild, &rc);
+		nEditHeight = rc.bottom - rc.top;
+		yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;
+
+		/* center combo box inside child area */
+		TRACE("moving child (Combo(Ex)) %04x to (%d,%d)-(%d,%d)\n",
+		      lpBand->hwndChild,
+		      lpBand->rcChild.left, yPos,
+		      lpBand->rcChild.right - lpBand->rcChild.left,
+		      nEditHeight);
+		deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
+					   lpBand->rcChild.left,
+					   /*lpBand->rcChild.top*/ yPos,
+					   lpBand->rcChild.right - lpBand->rcChild.left,
+					   nEditHeight,
+					   SWP_NOZORDER);
+		if (!deferpos)
+		    ERR("DeferWindowPos returned NULL\n");
+	    }
+	    else {
+		TRACE("moving child (Other) %04x to (%d,%d)-(%d,%d)\n",
+		      lpBand->hwndChild,
+		      lpBand->rcChild.left, lpBand->rcChild.top,
+		      lpBand->rcChild.right - lpBand->rcChild.left,
+		      lpBand->rcChild.bottom - lpBand->rcChild.top);
+		deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
+					   lpBand->rcChild.left,
+					   lpBand->rcChild.top,
+					   lpBand->rcChild.right - lpBand->rcChild.left,
+					   lpBand->rcChild.bottom - lpBand->rcChild.top,
+					   SWP_NOZORDER);
+		if (!deferpos)
+		    ERR("DeferWindowPos returned NULL\n");
+	    }
+	}
+    }
+    if (!EndDeferWindowPos(deferpos))
+        ERR("EndDeferWindowPos returned NULL\n");
+    if (infoPtr->fStatus & NTF_HGHTCHG) {
+        infoPtr->fStatus &= ~NTF_HGHTCHG;
+        REBAR_Notify (hwnd, &heightchange, infoPtr, RBN_HEIGHTCHANGE);
+    }
+}
+
+
+static VOID
+REBAR_ValidateBand (HWND hwnd, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
+     /* Function:  This routine evaluates the band specs supplied */
+     /*  by the user and updates the following 5 fields in        */
+     /*  the internal band structure: cxHeader, lcx, lcy, hcx, hcy*/
+{
+    UINT header=0;
+    UINT textheight=0;
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+
+    lpBand->fStatus = 0;
+    lpBand->lcx = 0;
+    lpBand->lcy = 0;
+    lpBand->hcx = 0;
+    lpBand->hcy = 0;
+
+    /* Data comming in from users into the cx... and cy... fields  */
+    /* may be bad, just garbage, because the user never clears     */
+    /* the fields. RB_{SET|INSERT}BAND{A|W} just passes the data   */
+    /* along if the fields exist in the input area. Here we must   */
+    /* determine if the data is valid. I have no idea how MS does  */
+    /* the validation, but it does because the RB_GETBANDINFO      */
+    /* returns a 0 when I know the sample program passed in an     */
+    /* address. Here I will use the algorithim that if the value   */
+    /* is greater than 65535 then it is bad and replace it with    */
+    /* a zero. Feel free to improve the algorithim.  -  GA 12/2000 */
+    if (lpBand->cxMinChild > 65535) lpBand->cxMinChild = 0;
+    if (lpBand->cyMinChild > 65535) lpBand->cyMinChild = 0;
+    if (lpBand->cx         > 65535) lpBand->cx         = 0;
+    if (lpBand->cyChild    > 65535) lpBand->cyChild    = 0;
+    if (lpBand->cyMaxChild > 65535) lpBand->cyMaxChild = 0;
+    if (lpBand->cyIntegral > 65535) lpBand->cyIntegral = 0;
+    if (lpBand->cxIdeal    > 65535) lpBand->cxIdeal    = 0;
+    if (lpBand->cxHeader   > 65535) lpBand->cxHeader   = 0;
+
+    /* Header is where the image, text and gripper exist  */
+    /* in the band and preceed the child window.          */
+
+    /* calculate gripper rectangle */
+    if (  (!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
+	  ( (lpBand->fStyle & RBBS_GRIPPERALWAYS) || 
+	    ( !(lpBand->fStyle & RBBS_FIXEDSIZE) && (infoPtr->uNumBands > 1)))
+       ) {
+	lpBand->fStatus |= HAS_GRIPPER;
+        if (dwStyle & CCS_VERT)
+	    if (dwStyle & RBS_VERTICALGRIPPER)
+                header += (GRIPPER_HEIGHT + REBAR_PRE_GRIPPER);
+            else
+	        header += (GRIPPER_WIDTH + REBAR_PRE_GRIPPER);
+        else
+            header += (REBAR_PRE_GRIPPER + GRIPPER_WIDTH);
+        /* Always have 4 pixels before anything else */
+        header += REBAR_ALWAYS_SPACE;
+    }
+
+    /* image is visible */
+    if ((lpBand->fMask & RBBIM_IMAGE) && (infoPtr->himl)) {
+	lpBand->fStatus |= HAS_IMAGE;
+        if (dwStyle & CCS_VERT) {
+	   header += (infoPtr->imageSize.cy + REBAR_POST_IMAGE);
+	   lpBand->lcy = infoPtr->imageSize.cx + 2;
+	}
+	else {
+	   header += (infoPtr->imageSize.cx + REBAR_POST_IMAGE);
+	   lpBand->lcy = infoPtr->imageSize.cy + 2;
+	}
+    }
+
+    /* text is visible */
+    if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText)) {
+	HDC hdc = GetDC (0);
+	HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
+	SIZE size;
+
+	lpBand->fStatus |= HAS_TEXT;
+	GetTextExtentPoint32W (hdc, lpBand->lpText,
+			       lstrlenW (lpBand->lpText), &size);
+	header += ((dwStyle & CCS_VERT) ? (size.cy + REBAR_POST_TEXT) : (size.cx + REBAR_POST_TEXT));
+	textheight = (dwStyle & CCS_VERT) ? 0 : size.cy;
+
+	SelectObject (hdc, hOldFont);
+	ReleaseDC (0, hdc);
+    }
+
+    /* if no gripper but either image or text, then leave space */
+    if ((lpBand->fStatus & (HAS_IMAGE | HAS_TEXT)) &&
+	!(lpBand->fStatus & HAS_GRIPPER)) {
+	header += REBAR_ALWAYS_SPACE;
+    }
+
+    /* check if user overrode the header value */
+    if (!(lpBand->fMask & RBBIM_HEADERSIZE))
+        lpBand->cxHeader = header;
+
+
+    /* Now compute minimum size of child window */
+    lpBand->offChild.cx = 0;
+    lpBand->offChild.cy = 0;
+    lpBand->lcy = textheight;
+    if (lpBand->fMask & RBBIM_CHILDSIZE) {
+	if (!(lpBand->fStyle & RBBS_FIXEDSIZE)) {
+	    lpBand->offChild.cx = 4;
+	    lpBand->offChild.cy = 2;
+        }
+        lpBand->lcx = lpBand->cxMinChild;
+        lpBand->lcy = max(lpBand->lcy, lpBand->cyMinChild);
+        lpBand->hcy = lpBand->lcy;
+        if (lpBand->fStyle & RBBS_VARIABLEHEIGHT) {
+	    if (lpBand->cyChild != 0xffffffff)
+	        lpBand->lcy = max (lpBand->cyChild, lpBand->lcy);
+	    lpBand->hcy = lpBand->cyMaxChild;
+        }
+        TRACE("_CHILDSIZE\n");
+    }
+    if (lpBand->fMask & RBBIM_SIZE) {
+        lpBand->hcx = max (lpBand->cx, lpBand->lcx);
+        TRACE("_SIZE\n");
+    }
+    else
+        lpBand->hcx = lpBand->lcx;
+
+}
+
+static void
+REBAR_CommonSetupBand (HWND hwnd, LPREBARBANDINFOA lprbbi, REBAR_BAND *lpBand)
+     /* Function:  This routine copies the supplied values from   */
+     /*  user input (lprbbi) to the internal band structure.      */
+{
+    lpBand->fMask |= lprbbi->fMask;
+
+    if (lprbbi->fMask & RBBIM_STYLE)
+	lpBand->fStyle = lprbbi->fStyle;
+
+    if (lprbbi->fMask & RBBIM_COLORS) {
+	lpBand->clrFore = lprbbi->clrFore;
+	lpBand->clrBack = lprbbi->clrBack;
+    }
+
+    if (lprbbi->fMask & RBBIM_IMAGE)
+	lpBand->iImage = lprbbi->iImage;
+
+    if (lprbbi->fMask & RBBIM_CHILD) {
+	if (lprbbi->hwndChild) {
+	    lpBand->hwndChild = lprbbi->hwndChild;
+	    lpBand->hwndPrevParent =
+		SetParent (lpBand->hwndChild, hwnd);
+	}
+	else {
+	    TRACE("child: 0x%x  prev parent: 0x%x\n",
+		   lpBand->hwndChild, lpBand->hwndPrevParent);
+	    lpBand->hwndChild = 0;
+	    lpBand->hwndPrevParent = 0;
+	}
+    }
+
+    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
+	lpBand->cxMinChild = lprbbi->cxMinChild;
+	lpBand->cyMinChild = lprbbi->cyMinChild;
+	if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
+	    lpBand->cyChild    = lprbbi->cyChild;
+	    lpBand->cyMaxChild = lprbbi->cyMaxChild;
+	    lpBand->cyIntegral = lprbbi->cyIntegral;
+	}
+	else { /* special case - these should be zeroed out since   */
+	       /* RBBIM_CHILDSIZE added these in WIN32_IE >= 0x0400 */
+	    lpBand->cyChild    = 0;
+	    lpBand->cyMaxChild = 0;
+	    lpBand->cyIntegral = 0;
+	}
+    }
+
+    if (lprbbi->fMask & RBBIM_SIZE)
+	lpBand->cx = lprbbi->cx;
+
+    if (lprbbi->fMask & RBBIM_BACKGROUND)
+	lpBand->hbmBack = lprbbi->hbmBack;
+
+    if (lprbbi->fMask & RBBIM_ID)
+	lpBand->wID = lprbbi->wID;
+
+    /* check for additional data */
+    if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
+	if (lprbbi->fMask & RBBIM_IDEALSIZE)
+	    lpBand->cxIdeal = lprbbi->cxIdeal;
+
+	if (lprbbi->fMask & RBBIM_LPARAM)
+	    lpBand->lParam = lprbbi->lParam;
+
+	if (lprbbi->fMask & RBBIM_HEADERSIZE)
+	    lpBand->cxHeader = lprbbi->cxHeader;
+    }
+}
+
+static LRESULT
+REBAR_InternalEraseBkGnd (HWND hwnd, WPARAM wParam, LPARAM lParam, RECT *clip)
+     /* Function:  This erases the background rectangle with the  */
+     /*  default brush, then with any band that has a different   */
+     /*  background color.                                        */
+{
+    HBRUSH hbrBackground = GetClassWord(hwnd, GCW_HBRBACKGROUND);
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    RECT eraserect;
+    REBAR_BAND *lpBand;
+    INT i;
+
+    if (hbrBackground)
+        FillRect( (HDC) wParam, clip, hbrBackground);
+
+    for(i=0; i<infoPtr->uNumBands; i++) {
+        lpBand = &infoPtr->bands[i];
+	if (lpBand->clrBack != CLR_NONE) {
+	  if (IntersectRect (&eraserect, clip, &lpBand->rcBand)) {
+	    /* draw background */
+	    HBRUSH brh = CreateSolidBrush (lpBand->clrBack);
+	    TRACE("backround color=0x%06lx, band (%d,%d)-(%d,%d), clip (%d,%d)-(%d,%d)\n",
+		  lpBand->clrBack,
+		  lpBand->rcBand.left,lpBand->rcBand.top,
+		  lpBand->rcBand.right,lpBand->rcBand.bottom,
+		  clip->left, clip->top,
+		  clip->right, clip->bottom);
+	    FillRect ( (HDC)wParam, &eraserect, brh);
+	    DeleteObject (brh);
+	  }
+	}
+    }
+    return TRUE;
+}
+
+static void
+REBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pBand)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    REBAR_BAND *lpBand;
+    RECT rect;
+    INT  iCount;
+
+    GetClientRect (hwnd, &rect);
+
+    *pFlags = RBHT_NOWHERE;
+    if (PtInRect (&rect, *lpPt))
+    {
+	if (infoPtr->uNumBands == 0) {
+	    *pFlags = RBHT_NOWHERE;
+	    if (pBand)
+		*pBand = -1;
+	    TRACE("NOWHERE\n");
+	    return;
+	}
+	else {
+	    /* somewhere inside */
+	    infoPtr->ihitBand = -1;
+	    for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
+		lpBand = &infoPtr->bands[iCount];
+		if (PtInRect (&lpBand->rcBand, *lpPt)) {
+		    if (pBand)
+			*pBand = iCount;
+		    if (PtInRect (&lpBand->rcGripper, *lpPt)) {
+			*pFlags = RBHT_GRABBER;
+			infoPtr->ihitBand = iCount;
+			TRACE("ON GRABBER %d\n", iCount);
+			return;
+		    }
+		    else if (PtInRect (&lpBand->rcCapImage, *lpPt)) {
+			*pFlags = RBHT_CAPTION;
+			TRACE("ON CAPTION %d\n", iCount);
+			return;
+		    }
+		    else if (PtInRect (&lpBand->rcCapText, *lpPt)) {
+			*pFlags = RBHT_CAPTION;
+			TRACE("ON CAPTION %d\n", iCount);
+			return;
+		    }
+		    else if (PtInRect (&lpBand->rcChild, *lpPt)) {
+			*pFlags = RBHT_CLIENT;
+			TRACE("ON CLIENT %d\n", iCount);
+			return;
+		    }
+		    else {
+			*pFlags = RBHT_NOWHERE;
+			TRACE("NOWHERE %d\n", iCount);
+			return;
+		    }
+		}
+	    }
+
+	    *pFlags = RBHT_NOWHERE;
+	    if (pBand)
+		*pBand = -1;
+
+	    TRACE("NOWHERE\n");
+	    return;
+	}
+    }
+    else {
+	*pFlags = RBHT_NOWHERE;
+	if (pBand)
+	    *pBand = -1;
+	TRACE("NOWHERE\n");
+	return;
+    }
+
+    TRACE("flags=0x%X\n", *pFlags);
+    return;
+}
+
+#define READJ(b,i) {if(dwStyle & CCS_VERT) b->rcBand.bottom+=(i); \
+                    else b->rcBand.right += (i);}
+#define LEADJ(b,i) {if(dwStyle & CCS_VERT) b->rcBand.top+=(i); \
+                    else b->rcBand.left += (i);}
+
+
+static INT
+REBAR_Shrink (REBAR_BAND *band, INT movement, INT i, DWORD dwStyle)
+     /* Function:  This attempts to shrink the given band by the  */
+     /*  the amount in "movement". A shrink to the left is indi-  */
+     /*  cated by "movement" being negative. "i" is merely the    */
+     /*  band index for trace messages.                           */
+{
+    INT Leadjust, Readjust, avail, ret;
+
+    /* Note: a left drag is indicated by "movement" being negative.  */
+    /*       Similarly, a right drag is indicated by "movement"      */
+    /*       being positive. "movement" should never be 0, but if    */
+    /*       it is then the band does not move.                      */
+
+    avail = rcBrb(band) - rcBlt(band) - band->cxHeader - band->lcx;
+
+    /* now compute the Left End adjustment factor and Right End */
+    /* adjustment factor. They may be different if shrinking.   */
+    if (avail <= 0) {
+        /* if this band is not shrinkable, then just move it */
+        Leadjust = Readjust = movement;
+	ret = movement;
+    }
+    else {
+        if (movement < 0) {
+	    /* Drag to left */
+	    if (avail <= abs(movement)) {
+	        Readjust = movement;
+		Leadjust = movement + avail;
+		ret = Leadjust;
+	    }
+	    else {
+	        Readjust = movement;
+		Leadjust = 0;
+		ret = 0;
+	    }
+	}
+	else {
+	    /* Drag to right */
+	    if (avail <= abs(movement)) {
+	        Leadjust = movement;
+		Readjust = movement - avail;
+		ret = Readjust;
+	    }
+	    else {
+	        Leadjust = movement;
+		Readjust = 0;
+		ret = 0;
+	    }
+	}
+    }
+
+    /* Reasonability Check */
+    if (rcBlt(band) + Leadjust < 0) {
+        ERR("adjustment will fail, band %d: left=%d, right=%d, move=%d, rtn=%d\n",
+	    i, Leadjust, Readjust, movement, ret);
+    }
+
+    LEADJ(band, Leadjust);
+    READJ(band, Readjust);
+
+    TRACE("band %d:  left=%d, right=%d, move=%d, rtn=%d, rcBand=(%d,%d)-(%d,%d)\n",
+	  i, Leadjust, Readjust, movement, ret,
+	  band->rcBand.left, band->rcBand.top,
+	  band->rcBand.right, band->rcBand.bottom);
+    return ret;
+}
+
+
+static void
+REBAR_HandleLRDrag (HWND hwnd, REBAR_INFO *infoPtr, POINTS *ptsmove, DWORD dwStyle)
+     /* Function:  This will implement the functionality of a     */
+     /*  Gripper drag within a row. It will not implement "out-   */
+     /*  of-row" drags. (They are detected and handled in         */
+     /*  REBAR_MouseMove.)                                        */
+     /*  **** FIXME Switching order of bands in a row not   ****  */
+     /*  ****       yet implemented.                        ****  */
+{
+    REBAR_BAND *hitBand, *band, *prevband, *mindBand, *maxdBand;
+    HDWP deferpos;
+    NMREBARCHILDSIZE cs;
+    RECT newrect;
+    INT imindBand = -1, imaxdBand, ihitBand, i, movement, tempx;
+    INT RHeaderSum = 0, LHeaderSum = 0;
+    INT compress;
+
+    /* on first significant mouse movement, issue notify */
+
+    if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
+	if (REBAR_Notify_NMREBAR (hwnd, infoPtr, -1, RBN_BEGINDRAG)) {
+	    /* Notify returned TRUE - abort drag */
+	    infoPtr->dragStart.x = 0;
+	    infoPtr->dragStart.y = 0;
+	    infoPtr->dragNow = infoPtr->dragStart;
+	    infoPtr->ihitBand = -1;
+	    ReleaseCapture ();
+	    return ;
+	}
+	infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
+    }
+
+    ihitBand = infoPtr->ihitBand;
+    hitBand = &infoPtr->bands[ihitBand];
+    imaxdBand = ihitBand; /* to suppress warning message */
+
+    /* find all the bands in the row of the one whose Gripper was seized */
+    for (i=0; i<infoPtr->uNumBands; i++) {
+        band = &infoPtr->bands[i];
+	if (HIDDENBAND(band)) continue;
+	if (band->iRow == hitBand->iRow) {
+	    imaxdBand = i;
+	    if (imindBand == -1) imindBand = i;
+	    /* minimum size of each band is size of header plus            */
+	    /* size of minimum child plus offset of child from header plus */
+	    /* a one to separate each band.                                */
+	    if (i < ihitBand)
+	        LHeaderSum += (band->cxHeader + band->lcx + SEP_WIDTH);
+	    else 
+	        RHeaderSum += (band->cxHeader + band->lcx + SEP_WIDTH);
+
+	}
+    }
+    if (RHeaderSum) RHeaderSum -= SEP_WIDTH; /* no separator afterlast band */
+
+    mindBand = &infoPtr->bands[imindBand];
+    maxdBand = &infoPtr->bands[imaxdBand];
+
+    if (imindBand == imaxdBand) return; /* nothing to drag agains */
+    if (imindBand == ihitBand) return; /* first band in row, cant drag */
+
+    /* limit movement to inside adjustable bands - Left */
+    if ( (ptsmove->x < mindBand->rcBand.left) ||
+	 (ptsmove->x > maxdBand->rcBand.right) ||
+	 (ptsmove->y < mindBand->rcBand.top) ||
+	 (ptsmove->y > maxdBand->rcBand.bottom))
+        return; /* should swap bands */
+
+    if (dwStyle & CCS_VERT)
+        movement = ptsmove->y - ((hitBand->rcBand.top+REBAR_PRE_GRIPPER) -
+			     infoPtr->ihitoffset);
+    else
+        movement = ptsmove->x - ((hitBand->rcBand.left+REBAR_PRE_GRIPPER) -
+			     infoPtr->ihitoffset);
+    infoPtr->dragNow = *ptsmove;
+
+    TRACE("before: movement=%d (%d,%d), imindBand=%d, ihitBand=%d, imaxdBand=%d, LSum=%d, RSum=%d\n",
+	  movement, ptsmove->x, ptsmove->y, imindBand, ihitBand,
+	  imaxdBand, LHeaderSum, RHeaderSum);
+    REBAR_DumpBand (hwnd);
+
+    if (movement < 0) {  
+
+        /* ***  Drag left/up *** */
+        compress = rcBlt(hitBand) - rcBlt(mindBand) -
+	           LHeaderSum;
+	if (compress < abs(movement)) {
+	    TRACE("limiting left drag, was %d changed to %d\n",
+		  movement, -compress);
+	    movement = -compress;
+	}
+        for (i=ihitBand; i>=imindBand; i--) {
+	    band = &infoPtr->bands[i];
+	    if (i == ihitBand) {
+		prevband = &infoPtr->bands[i-1];
+		if (rcBlt(band) - movement <= rcBlt(prevband)) {
+		    tempx = movement - (rcBrb(prevband)-rcBlt(band)+1);
+		    ERR("movement bad. BUG!! was %d, left=%d, right=%d, setting to %d\n",
+			movement, rcBlt(band), rcBlt(prevband), tempx);
+		    movement = tempx;
+		}
+		LEADJ(band, movement)
+	    }
+	    else 
+	        movement = REBAR_Shrink (band, movement, i, dwStyle);
+	}
+    }
+    else {
+
+        /* ***  Drag right/down *** */
+        compress = rcBrb(maxdBand) - rcBlt(hitBand) -
+	           RHeaderSum;
+	if (compress < abs(movement)) {
+	    TRACE("limiting right drag, was %d changed to %d\n",
+		  movement, compress);
+	    movement = compress;
+	}
+        for (i=ihitBand-1; i<=imaxdBand; i++) {
+	    band = &infoPtr->bands[i];
+	    if (HIDDENBAND(band)) continue;
+	    if (i == ihitBand-1) {
+		READJ(band, movement)
+	    }
+	    else 
+	        movement = REBAR_Shrink (band, movement, i, dwStyle);
+	}
+    }
+
+    /* recompute all rectangles */
+    if (dwStyle & CCS_VERT) {
+	REBAR_CalcVertBand (hwnd, infoPtr, imindBand, imaxdBand+1,
+			    FALSE, dwStyle);
+    }
+    else {
+	REBAR_CalcHorzBand (hwnd, infoPtr, imindBand, imaxdBand+1, 
+			    FALSE, dwStyle);
+    }
+
+    TRACE("bands after adjustment, see band # %d, %d\n",
+	  imindBand, imaxdBand);
+    REBAR_DumpBand (hwnd);
+
+    SetRect (&newrect, 
+	     mindBand->rcBand.left,
+	     mindBand->rcBand.top,
+	     maxdBand->rcBand.right,
+	     maxdBand->rcBand.bottom);
+
+    if (!(deferpos = BeginDeferWindowPos (4))) {
+        ERR("BeginDeferWindowPos returned NULL\n");
+    }
+
+    for (i=imindBand; i<=imaxdBand; i++) {
+        band = &infoPtr->bands[i];
+	if ((band->fMask & RBBIM_CHILD) && band->hwndChild) {
+	    cs.uBand = i;
+	    cs.wID = band->wID;
+	    cs.rcChild = band->rcChild;
+	    cs.rcBand = band->rcBand;
+	    cs.rcBand.left += band->cxHeader;
+	    REBAR_Notify (hwnd, (NMHDR *) &cs, infoPtr, RBN_CHILDSIZE);
+	    deferpos = DeferWindowPos (deferpos, band->hwndChild, HWND_TOP,
+				       cs.rcChild.left, cs.rcChild.top,
+				       cs.rcChild.right - cs.rcChild.left,
+				       cs.rcChild.bottom - cs.rcChild.top,
+				       SWP_NOZORDER);
+	    if (!deferpos) {
+	        ERR("DeferWindowPos returned NULL\n");
+	    }
+	}
+    }
+
+    if (!EndDeferWindowPos (deferpos)) {
+        ERR("EndDeferWindowPos failed\n");
+    }
+
+    InvalidateRect (hwnd, &newrect, TRUE);
+    UpdateWindow (hwnd);
+
+}
+#undef READJ
+#undef LEADJ
+
+
+
+/* << REBAR_BeginDrag >> */
+
+
+static LRESULT
+REBAR_DeleteBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    UINT uBand = (UINT)wParam;
+    HWND childhwnd = 0;
+    REBAR_BAND *lpBand;
+
+    if (uBand >= infoPtr->uNumBands)
+	return FALSE;
+
+    TRACE("deleting band %u!\n", uBand);
+    lpBand = &infoPtr->bands[uBand];
+    REBAR_Notify_NMREBAR (hwnd, infoPtr, uBand, RBN_DELETINGBAND);
+
+    if (infoPtr->uNumBands == 1) {
+	TRACE(" simple delete!\n");
+	if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild)
+	    childhwnd = lpBand->hwndChild;
+	COMCTL32_Free (infoPtr->bands);
+	infoPtr->bands = NULL;
+	infoPtr->uNumBands = 0;
+    }
+    else {
+	REBAR_BAND *oldBands = infoPtr->bands;
+        TRACE("complex delete! [uBand=%u]\n", uBand);
+
+	if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild)
+	    childhwnd = lpBand->hwndChild;
+
+	infoPtr->uNumBands--;
+	infoPtr->bands = COMCTL32_Alloc (sizeof (REBAR_BAND) * infoPtr->uNumBands);
+        if (uBand > 0) {
+            memcpy (&infoPtr->bands[0], &oldBands[0],
+                    uBand * sizeof(REBAR_BAND));
+        }
+
+        if (uBand < infoPtr->uNumBands) {
+            memcpy (&infoPtr->bands[uBand], &oldBands[uBand+1],
+                    (infoPtr->uNumBands - uBand) * sizeof(REBAR_BAND));
+        }
+
+	COMCTL32_Free (oldBands);
+    }
+
+    if (childhwnd)
+        ShowWindow (childhwnd, SW_HIDE);
+
+    REBAR_Notify_NMREBAR (hwnd, infoPtr, -1, RBN_DELETEDBAND);
+
+    /* if only 1 band left the re-validate to possible eliminate gripper */
+    if (infoPtr->uNumBands == 1)
+      REBAR_ValidateBand (hwnd, infoPtr, &infoPtr->bands[0]);
+
+    REBAR_Layout (hwnd, NULL, TRUE, FALSE);
+    infoPtr->fStatus |= RESIZE_ANYHOW;
+    REBAR_ForceResize (hwnd);
+    REBAR_MoveChildWindows (hwnd);
+
+    return TRUE;
+}
+
+
+/* << REBAR_DragMove >> */
+/* << REBAR_EndDrag >> */
+
+
+static LRESULT
+REBAR_GetBandBorders (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    LPRECT lpRect = (LPRECT)lParam;
+    REBAR_BAND *lpBand;
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+
+    if (!lParam)
+	return 0;
+    if ((UINT)wParam >= infoPtr->uNumBands)
+	return 0;
+
+    lpBand = &infoPtr->bands[(UINT)wParam];
+
+    /* FIXME - the following values were determined by experimentation */
+    /* with the REBAR Control Spy. I have guesses as to what the 4 and */
+    /* 1 are, but I am not sure. There doesn't seem to be any actual   */
+    /* difference in size of the control area with and without the     */
+    /* style.  -  GA                                                   */
+    if (GetWindowLongA (hwnd, GWL_STYLE) & RBS_BANDBORDERS) {
+	if (dwStyle & CCS_VERT) {
+	    lpRect->left = 1;
+	    lpRect->top = lpBand->cxHeader + 4;
+	    lpRect->right = 1;
+	    lpRect->bottom = 0;
+	}
+	else {
+	    lpRect->left = lpBand->cxHeader + 4;
+	    lpRect->top = 1;
+	    lpRect->right = 0;
+	    lpRect->bottom = 1;
+	}
+    }
+    else {
+	lpRect->left = lpBand->cxHeader;
+    }
+    FIXME("stub\n");
+    return 0;
+}
+
+
+inline static LRESULT
+REBAR_GetBandCount (HWND hwnd)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+
+    TRACE("band count %u!\n", infoPtr->uNumBands);
+
+    return infoPtr->uNumBands;
+}
+
+
+static LRESULT
+REBAR_GetBandInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
+    REBAR_BAND *lpBand;
+
+    if (lprbbi == NULL)
+	return FALSE;
+    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
+	return FALSE;
+    if ((UINT)wParam >= infoPtr->uNumBands)
+	return FALSE;
+
+    TRACE("index %u\n", (UINT)wParam);
+
+    /* copy band information */
+    lpBand = &infoPtr->bands[(UINT)wParam];
+
+    if (lprbbi->fMask & RBBIM_STYLE)
+	lprbbi->fStyle = lpBand->fStyle;
+
+    if (lprbbi->fMask & RBBIM_COLORS) {
+	lprbbi->clrFore = lpBand->clrFore;
+	lprbbi->clrBack = lpBand->clrBack;
+	if (lprbbi->clrBack == CLR_NONE)
+	    lprbbi->clrBack = GetSysColor (COLOR_BTNFACE);
+    }
+
+    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
+      if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
+      {
+          if (!WideCharToMultiByte( CP_ACP, 0, lpBand->lpText, -1,
+                                    lprbbi->lpText, lprbbi->cch, NULL, NULL ))
+              lprbbi->lpText[lprbbi->cch-1] = 0;
+      }
+      else 
+	*lprbbi->lpText = 0;
+    }
+
+    if (lprbbi->fMask & RBBIM_IMAGE) {
+      if (lpBand->fMask & RBBIM_IMAGE)
+	lprbbi->iImage = lpBand->iImage;
+      else
+	lprbbi->iImage = -1;
+    }
+
+    if (lprbbi->fMask & RBBIM_CHILD)
+	lprbbi->hwndChild = lpBand->hwndChild;
+
+    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
+	lprbbi->cxMinChild = lpBand->cxMinChild;
+	lprbbi->cyMinChild = lpBand->cyMinChild;
+	if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
+	    lprbbi->cyChild    = lpBand->cyChild;
+	    lprbbi->cyMaxChild = lpBand->cyMaxChild;
+	    lprbbi->cyIntegral = lpBand->cyIntegral;
+	}
+    }
+
+    if (lprbbi->fMask & RBBIM_SIZE)
+	lprbbi->cx = lpBand->cx;
+
+    if (lprbbi->fMask & RBBIM_BACKGROUND)
+	lprbbi->hbmBack = lpBand->hbmBack;
+
+    if (lprbbi->fMask & RBBIM_ID)
+	lprbbi->wID = lpBand->wID;
+
+    /* check for additional data */
+    if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
+	if (lprbbi->fMask & RBBIM_IDEALSIZE)
+	    lprbbi->cxIdeal = lpBand->cxIdeal;
+
+	if (lprbbi->fMask & RBBIM_LPARAM)
+	    lprbbi->lParam = lpBand->lParam;
+
+	if (lprbbi->fMask & RBBIM_HEADERSIZE)
+	    lprbbi->cxHeader = lpBand->cxHeader;
+    }
+
+    REBAR_DumpBandInfo (lprbbi);
+
+    return TRUE;
+}
+
+
+static LRESULT
+REBAR_GetBandInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
+    REBAR_BAND *lpBand;
+
+    if (lprbbi == NULL)
+	return FALSE;
+    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
+	return FALSE;
+    if ((UINT)wParam >= infoPtr->uNumBands)
+	return FALSE;
+
+    TRACE("index %u\n", (UINT)wParam);
+
+    /* copy band information */
+    lpBand = &infoPtr->bands[(UINT)wParam];
+
+    if (lprbbi->fMask & RBBIM_STYLE)
+	lprbbi->fStyle = lpBand->fStyle;
+
+    if (lprbbi->fMask & RBBIM_COLORS) {
+	lprbbi->clrFore = lpBand->clrFore;
+	lprbbi->clrBack = lpBand->clrBack;
+	if (lprbbi->clrBack == CLR_NONE)
+	    lprbbi->clrBack = GetSysColor (COLOR_BTNFACE);
+    }
+
+    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
+      if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
+	lstrcpynW (lprbbi->lpText, lpBand->lpText, lprbbi->cch);
+      else 
+	*lprbbi->lpText = 0;
+    }
+
+    if (lprbbi->fMask & RBBIM_IMAGE) {
+      if (lpBand->fMask & RBBIM_IMAGE)
+	lprbbi->iImage = lpBand->iImage;
+      else
+	lprbbi->iImage = -1;
+    }
+
+    if (lprbbi->fMask & RBBIM_CHILD)
+	lprbbi->hwndChild = lpBand->hwndChild;
+
+    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
+	lprbbi->cxMinChild = lpBand->cxMinChild;
+	lprbbi->cyMinChild = lpBand->cyMinChild;
+	if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
+	    lprbbi->cyChild    = lpBand->cyChild;
+	    lprbbi->cyMaxChild = lpBand->cyMaxChild;
+	    lprbbi->cyIntegral = lpBand->cyIntegral;
+	}
+    }
+
+    if (lprbbi->fMask & RBBIM_SIZE)
+	lprbbi->cx = lpBand->cx;
+
+    if (lprbbi->fMask & RBBIM_BACKGROUND)
+	lprbbi->hbmBack = lpBand->hbmBack;
+
+    if (lprbbi->fMask & RBBIM_ID)
+	lprbbi->wID = lpBand->wID;
+
+    /* check for additional data */
+    if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
+	if (lprbbi->fMask & RBBIM_IDEALSIZE)
+	    lprbbi->cxIdeal = lpBand->cxIdeal;
+
+	if (lprbbi->fMask & RBBIM_LPARAM)
+	    lprbbi->lParam = lpBand->lParam;
+
+	if (lprbbi->fMask & RBBIM_HEADERSIZE)
+	    lprbbi->cxHeader = lpBand->cxHeader;
+    }
+
+    REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
+
+    return TRUE;
+}
+
+
+static LRESULT
+REBAR_GetBarHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    INT nHeight;
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+
+    nHeight = (dwStyle & CCS_VERT) ? infoPtr->calcSize.cx : infoPtr->calcSize.cy;
+
+    TRACE("height = %d\n", nHeight);
+
+    return nHeight;
+}
+
+
+static LRESULT
+REBAR_GetBarInfo (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    LPREBARINFO lpInfo = (LPREBARINFO)lParam;
+
+    if (lpInfo == NULL)
+	return FALSE;
+
+    if (lpInfo->cbSize < sizeof (REBARINFO))
+	return FALSE;
+
+    TRACE("getting bar info!\n");
+
+    if (infoPtr->himl) {
+	lpInfo->himl = infoPtr->himl;
+	lpInfo->fMask |= RBIM_IMAGELIST;
+    }
+
+    return TRUE;
+}
+
+
+inline static LRESULT
+REBAR_GetBkColor (HWND hwnd)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    COLORREF clr = infoPtr->clrBk;
+
+    if (clr == CLR_NONE)
+      clr = GetSysColor (COLOR_BTNFACE);
+
+    TRACE("background color 0x%06lx!\n", clr);
+
+    return clr;
+}
+
+
+/* << REBAR_GetColorScheme >> */
+/* << REBAR_GetDropTarget >> */
+
+
+static LRESULT
+REBAR_GetPalette (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    FIXME("empty stub!\n");
+
+    return 0;
+}
+
+
+static LRESULT
+REBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    INT iBand = (INT)wParam;
+    LPRECT lprc = (LPRECT)lParam;
+    REBAR_BAND *lpBand;
+
+    if ((iBand < 0) && ((UINT)iBand >= infoPtr->uNumBands))
+	return FALSE;
+    if (!lprc)
+	return FALSE;
+
+    lpBand = &infoPtr->bands[iBand];
+    CopyRect (lprc, &lpBand->rcBand);
+
+    TRACE("band %d, (%d,%d)-(%d,%d)\n", iBand,
+	  lprc->left, lprc->top, lprc->right, lprc->bottom);
+
+    return TRUE;
+}
+
+
+inline static LRESULT
+REBAR_GetRowCount (HWND hwnd)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+
+    TRACE("%u\n", infoPtr->uNumRows);
+
+    return infoPtr->uNumRows;
+}
+
+
+static LRESULT
+REBAR_GetRowHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    INT iRow = (INT)wParam;
+    int ret = 0;
+    int i, j = 0;
+    REBAR_BAND *lpBand;
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+
+    for (i=0; i<infoPtr->uNumBands; i++) {
+      lpBand = &infoPtr->bands[i];
+      if (HIDDENBAND(lpBand)) continue;
+      if (lpBand->iRow != iRow) continue;
+      if (dwStyle & CCS_VERT)
+	j = lpBand->rcBand.right - lpBand->rcBand.left;
+      else
+	j = lpBand->rcBand.bottom - lpBand->rcBand.top;
+      if (j > ret) ret = j;
+    }
+
+    TRACE("row %d, height %d\n", iRow, ret);
+
+    return ret;
+}
+
+
+inline static LRESULT
+REBAR_GetTextColor (HWND hwnd)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+
+    TRACE("text color 0x%06lx!\n", infoPtr->clrText);
+
+    return infoPtr->clrText;
+}
+
+
+inline static LRESULT
+REBAR_GetToolTips (HWND hwnd)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    return infoPtr->hwndToolTip;
+}
+
+
+inline static LRESULT
+REBAR_GetUnicodeFormat (HWND hwnd)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    return infoPtr->bUnicode;
+}
+
+
+inline static LRESULT
+REBAR_GetVersion (HWND hwnd)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    TRACE("version %d\n", infoPtr->iVersion);
+    return infoPtr->iVersion;
+}
+
+
+static LRESULT
+REBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    /* REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
+    LPRBHITTESTINFO lprbht = (LPRBHITTESTINFO)lParam; 
+
+    if (!lprbht)
+	return -1;
+
+    REBAR_InternalHitTest (hwnd, &lprbht->pt, &lprbht->flags, &lprbht->iBand);
+
+    return lprbht->iBand;
+}
+
+
+static LRESULT
+REBAR_IdToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    UINT i;
+
+    if (infoPtr == NULL)
+	return -1;
+
+    if (infoPtr->uNumBands < 1)
+	return -1;
+
+    for (i = 0; i < infoPtr->uNumBands; i++) {
+	if (infoPtr->bands[i].wID == (UINT)wParam) {
+	    TRACE("id %u is band %u found!\n", (UINT)wParam, i);
+	    return i;
+	}
+    }
+
+    TRACE("id %u is not found\n", (UINT)wParam);
+    return -1;
+}
+
+
+static LRESULT
+REBAR_InsertBandA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
+    UINT uIndex = (UINT)wParam;
+    REBAR_BAND *lpBand;
+
+    if (infoPtr == NULL)
+	return FALSE;
+    if (lprbbi == NULL)
+	return FALSE;
+    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
+	return FALSE;
+
+    /* trace the index as signed to see the -1 */
+    TRACE("insert band at %d!\n", (INT)uIndex);
+    REBAR_DumpBandInfo (lprbbi);
+
+    if (infoPtr->uNumBands == 0) {
+	infoPtr->bands = (REBAR_BAND *)COMCTL32_Alloc (sizeof (REBAR_BAND));
+	uIndex = 0;
+    }
+    else {
+	REBAR_BAND *oldBands = infoPtr->bands;
+	infoPtr->bands =
+	    (REBAR_BAND *)COMCTL32_Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
+	if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
+	    uIndex = infoPtr->uNumBands;
+
+	/* pre insert copy */
+	if (uIndex > 0) {
+	    memcpy (&infoPtr->bands[0], &oldBands[0],
+		    uIndex * sizeof(REBAR_BAND));
+	}
+
+	/* post copy */
+	if (uIndex < infoPtr->uNumBands - 1) {
+	    memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
+		    (infoPtr->uNumBands - uIndex - 1) * sizeof(REBAR_BAND));
+	}
+
+	COMCTL32_Free (oldBands);
+    }
+
+    infoPtr->uNumBands++;
+
+    TRACE("index %u!\n", uIndex);
+
+    /* initialize band (infoPtr->bands[uIndex])*/
+    lpBand = &infoPtr->bands[uIndex];
+    lpBand->fMask = 0;
+    lpBand->fStatus = 0;
+    lpBand->clrFore = infoPtr->clrText;
+    lpBand->clrBack = infoPtr->clrBk;
+    lpBand->hwndChild = 0;
+    lpBand->hwndPrevParent = 0;
+
+    REBAR_CommonSetupBand (hwnd, lprbbi, lpBand);
+    lpBand->lpText = NULL;
+    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
+        INT len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
+        if (len > 1) {
+            lpBand->lpText = (LPWSTR)COMCTL32_Alloc (len*sizeof(WCHAR));
+            MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, lpBand->lpText, len );
+	}
+    }
+
+    REBAR_ValidateBand (hwnd, infoPtr, lpBand);
+    /* On insert of second band, revalidate band 1 to possible add gripper */
+    if (infoPtr->uNumBands == 2)
+	REBAR_ValidateBand (hwnd, infoPtr, &infoPtr->bands[0]);
+
+    REBAR_DumpBand (hwnd);
+
+    REBAR_Layout (hwnd, NULL, TRUE, FALSE);
+    REBAR_ForceResize (hwnd);
+    REBAR_MoveChildWindows (hwnd);
+
+    return TRUE;
+}
+
+
+static LRESULT
+REBAR_InsertBandW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
+    UINT uIndex = (UINT)wParam;
+    REBAR_BAND *lpBand;
+
+    if (infoPtr == NULL)
+	return FALSE;
+    if (lprbbi == NULL)
+	return FALSE;
+    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
+	return FALSE;
+
+    /* trace the index as signed to see the -1 */
+    TRACE("insert band at %d!\n", (INT)uIndex);
+    REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
+
+    if (infoPtr->uNumBands == 0) {
+	infoPtr->bands = (REBAR_BAND *)COMCTL32_Alloc (sizeof (REBAR_BAND));
+	uIndex = 0;
+    }
+    else {
+	REBAR_BAND *oldBands = infoPtr->bands;
+	infoPtr->bands =
+	    (REBAR_BAND *)COMCTL32_Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
+	if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
+	    uIndex = infoPtr->uNumBands;
+
+	/* pre insert copy */
+	if (uIndex > 0) {
+	    memcpy (&infoPtr->bands[0], &oldBands[0],
+		    uIndex * sizeof(REBAR_BAND));
+	}
+
+	/* post copy */
+	if (uIndex < infoPtr->uNumBands - 1) {
+	    memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
+		    (infoPtr->uNumBands - uIndex - 1) * sizeof(REBAR_BAND));
+	}
+
+	COMCTL32_Free (oldBands);
+    }
+
+    infoPtr->uNumBands++;
+
+    TRACE("index %u!\n", uIndex);
+
+    /* initialize band (infoPtr->bands[uIndex])*/
+    lpBand = &infoPtr->bands[uIndex];
+    lpBand->fMask = 0;
+    lpBand->fStatus = 0;
+    lpBand->clrFore = infoPtr->clrText;
+    lpBand->clrBack = infoPtr->clrBk;
+    lpBand->hwndChild = 0;
+    lpBand->hwndPrevParent = 0;
+
+    REBAR_CommonSetupBand (hwnd, (LPREBARBANDINFOA)lprbbi, lpBand);
+    lpBand->lpText = NULL;
+    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
+	INT len = lstrlenW (lprbbi->lpText);
+	if (len > 0) {
+	    lpBand->lpText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
+	    strcpyW (lpBand->lpText, lprbbi->lpText);
+	}
+    }
+
+    REBAR_ValidateBand (hwnd, infoPtr, lpBand);
+    /* On insert of second band, revalidate band 1 to possible add gripper */
+    if (infoPtr->uNumBands == 2)
+	REBAR_ValidateBand (hwnd, infoPtr, &infoPtr->bands[0]);
+
+    REBAR_DumpBand (hwnd);
+
+    REBAR_Layout (hwnd, NULL, TRUE, FALSE);
+    REBAR_ForceResize (hwnd);
+    REBAR_MoveChildWindows (hwnd);
+
+    return TRUE;
+}
+
+
+static LRESULT
+REBAR_MaximizeBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+/*    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
+
+    FIXME("(uBand = %u fIdeal = %s) stub\n",
+	   (UINT)wParam, lParam ? "TRUE" : "FALSE");
+
+ 
+    return 0;
+}
+
+
+static LRESULT
+REBAR_MinimizeBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+/*    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
+
+    FIXME("(uBand = %u) stub\n", (UINT)wParam);
+
+ 
+    return 0;
+}
+
+
+static LRESULT
+REBAR_MoveBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+/*    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
+
+    FIXME("(iFrom = %u iTof = %u) stub\n",
+	   (UINT)wParam, (UINT)lParam);
+
+ 
+    return FALSE;
+}
+
+
+static LRESULT
+REBAR_SetBandInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
+    REBAR_BAND *lpBand;
+
+    if (lprbbi == NULL)
+	return FALSE;
+    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
+	return FALSE;
+    if ((UINT)wParam >= infoPtr->uNumBands)
+	return FALSE;
+
+    TRACE("index %u\n", (UINT)wParam);
+    REBAR_DumpBandInfo (lprbbi);
+
+    /* set band information */
+    lpBand = &infoPtr->bands[(UINT)wParam];
+
+    REBAR_CommonSetupBand (hwnd, lprbbi, lpBand);
+    if (lprbbi->fMask & RBBIM_TEXT) {
+	if (lpBand->lpText) {
+	    COMCTL32_Free (lpBand->lpText);
+	    lpBand->lpText = NULL;
+	}
+	if (lprbbi->lpText) {
+            INT len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
+            lpBand->lpText = (LPWSTR)COMCTL32_Alloc (len*sizeof(WCHAR));
+            MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, lpBand->lpText, len );
+	}
+    }
+
+    REBAR_ValidateBand (hwnd, infoPtr, lpBand);
+
+    REBAR_DumpBand (hwnd);
+
+    if (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) {
+      REBAR_Layout (hwnd, NULL, TRUE, FALSE);
+      REBAR_ForceResize (hwnd);
+      REBAR_MoveChildWindows (hwnd);
+    }
+
+    return TRUE;
+}
+
+
+static LRESULT
+REBAR_SetBandInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
+    REBAR_BAND *lpBand;
+
+    if (lprbbi == NULL)
+	return FALSE;
+    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
+	return FALSE;
+    if ((UINT)wParam >= infoPtr->uNumBands)
+	return FALSE;
+
+    TRACE("index %u\n", (UINT)wParam);
+    REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
+
+    /* set band information */
+    lpBand = &infoPtr->bands[(UINT)wParam];
+
+    REBAR_CommonSetupBand (hwnd, (LPREBARBANDINFOA)lprbbi, lpBand);
+    if (lprbbi->fMask & RBBIM_TEXT) {
+	if (lpBand->lpText) {
+	    COMCTL32_Free (lpBand->lpText);
+	    lpBand->lpText = NULL;
+	}
+	if (lprbbi->lpText) {
+	    INT len = lstrlenW (lprbbi->lpText);
+	    lpBand->lpText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
+	    strcpyW (lpBand->lpText, lprbbi->lpText);
+	}
+    }
+
+    REBAR_ValidateBand (hwnd, infoPtr, lpBand);
+
+    REBAR_DumpBand (hwnd);
+
+    if (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) {
+      REBAR_Layout (hwnd, NULL, TRUE, FALSE);
+      REBAR_ForceResize (hwnd);
+      REBAR_MoveChildWindows (hwnd);
+    }
+
+    return TRUE;
+}
+
+
+static LRESULT
+REBAR_SetBarInfo (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    LPREBARINFO lpInfo = (LPREBARINFO)lParam;
+    REBAR_BAND *lpBand;
+    UINT i;
+
+    if (lpInfo == NULL)
+	return FALSE;
+
+    if (lpInfo->cbSize < sizeof (REBARINFO))
+	return FALSE;
+
+    TRACE("setting bar info!\n");
+
+    if (lpInfo->fMask & RBIM_IMAGELIST) {
+	infoPtr->himl = lpInfo->himl;
+	if (infoPtr->himl) {
+            INT cx, cy;
+	    ImageList_GetIconSize (infoPtr->himl, &cx, &cy);
+	    infoPtr->imageSize.cx = cx;
+	    infoPtr->imageSize.cy = cy;
+	}
+	else {
+	    infoPtr->imageSize.cx = 0;
+	    infoPtr->imageSize.cy = 0;
+	}
+	TRACE("new image cx=%ld, cy=%ld\n", infoPtr->imageSize.cx,
+	      infoPtr->imageSize.cy);
+    }
+
+    /* revalidate all bands to reset flags for images in headers of bands */
+    for (i=0; i<infoPtr->uNumBands; i++) {
+        lpBand = &infoPtr->bands[i];
+	REBAR_ValidateBand (hwnd, infoPtr, lpBand);
+    }
+
+    return TRUE;
+}
+
+
+static LRESULT
+REBAR_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    COLORREF clrTemp;
+
+    clrTemp = infoPtr->clrBk;
+    infoPtr->clrBk = (COLORREF)lParam;
+
+    TRACE("background color 0x%06lx!\n", infoPtr->clrBk);
+
+    return clrTemp;
+}
+
+
+/* << REBAR_SetColorScheme >> */
+/* << REBAR_SetPalette >> */
+
+
+static LRESULT
+REBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    HWND hwndTemp = infoPtr->hwndNotify;
+
+    infoPtr->hwndNotify = (HWND)wParam;
+
+    return (LRESULT)hwndTemp;
+}
+
+
+static LRESULT
+REBAR_SetTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    COLORREF clrTemp;
+
+    clrTemp = infoPtr->clrText;
+    infoPtr->clrText = (COLORREF)lParam;
+
+    TRACE("text color 0x%06lx!\n", infoPtr->clrText);
+
+    return clrTemp;
+}
+
+
+/* << REBAR_SetTooltips >> */
+
+
+inline static LRESULT
+REBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    BOOL bTemp = infoPtr->bUnicode;
+    infoPtr->bUnicode = (BOOL)wParam;
+    return bTemp;
+}
+
+
+static LRESULT
+REBAR_SetVersion (HWND hwnd, INT iVersion)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    INT iOldVersion = infoPtr->iVersion;
+
+    if (iVersion > COMCTL32_VERSION)
+	return -1;
+
+    infoPtr->iVersion = iVersion;
+
+    TRACE("new version %d\n", iVersion);
+
+    return iOldVersion;
+}
+
+
+static LRESULT
+REBAR_ShowBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    REBAR_BAND *lpBand;
+
+    if (((INT)wParam < 0) || ((INT)wParam > infoPtr->uNumBands))
+	return FALSE;
+
+    lpBand = &infoPtr->bands[(INT)wParam];
+
+    if ((BOOL)lParam) {
+	TRACE("show band %d\n", (INT)wParam);
+	lpBand->fStyle = lpBand->fStyle & ~RBBS_HIDDEN;
+	if (IsWindow (lpBand->hwndChild))
+	    ShowWindow (lpBand->hwndChild, SW_SHOW);
+    }
+    else {
+	TRACE("hide band %d\n", (INT)wParam);
+	lpBand->fStyle = lpBand->fStyle | RBBS_HIDDEN;
+	if (IsWindow (lpBand->hwndChild))
+	    ShowWindow (lpBand->hwndChild, SW_HIDE);
+    }
+
+    REBAR_Layout (hwnd, NULL, TRUE, FALSE);
+    REBAR_ForceResize (hwnd);
+    REBAR_MoveChildWindows (hwnd);
+
+    return TRUE;
+}
+
+
+static LRESULT
+REBAR_SizeToRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    LPRECT lpRect = (LPRECT)lParam;
+    RECT t1;
+
+    if (lpRect == NULL)
+       return FALSE;
+
+    TRACE("[%d %d %d %d]\n",
+	  lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
+
+    /*  what is going on???? */
+    GetWindowRect(hwnd, &t1);
+    TRACE("window rect [%d %d %d %d]\n",
+	  t1.left, t1.top, t1.right, t1.bottom);
+    GetClientRect(hwnd, &t1);
+    TRACE("client rect [%d %d %d %d]\n",
+	  t1.left, t1.top, t1.right, t1.bottom);
+
+    REBAR_Layout (hwnd, lpRect, TRUE, FALSE);
+    REBAR_ForceResize (hwnd);
+    REBAR_MoveChildWindows (hwnd);
+    return TRUE;
+}
+
+
+
+static LRESULT
+REBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr;
+
+    /* allocate memory for info structure */
+#ifdef __WIN32OS2__
+    infoPtr = (REBAR_INFO*)initControl(hwnd,sizeof(REBAR_INFO));
+#else
+    infoPtr = (REBAR_INFO *)COMCTL32_Alloc (sizeof(REBAR_INFO));
+#endif
+    SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
+
+    /* initialize info structure - initial values are 0 */
+    infoPtr->clrBk = CLR_NONE;
+    infoPtr->clrText = GetSysColor (COLOR_BTNTEXT);
+    infoPtr->ihitBand = -1;
+
+    infoPtr->hcurArrow = LoadCursorA (0, IDC_ARROWA);
+    infoPtr->hcurHorz  = LoadCursorA (0, IDC_SIZEWEA);
+    infoPtr->hcurVert  = LoadCursorA (0, IDC_SIZENSA);
+    infoPtr->hcurDrag  = LoadCursorA (0, IDC_SIZEA);
+
+    infoPtr->bUnicode = IsWindowUnicode (hwnd);
+
+    if (GetWindowLongA (hwnd, GWL_STYLE) & RBS_AUTOSIZE)
+	FIXME("style RBS_AUTOSIZE set!\n");
+
+#if 0
+    SendMessageA (hwnd, WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY);
+#endif
+
+    TRACE("created!\n");
+    return 0;
+}
+
+
+static LRESULT
+REBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    REBAR_BAND *lpBand;
+    INT i;
+
+
+    /* free rebar bands */
+    if ((infoPtr->uNumBands > 0) && infoPtr->bands) {
+	/* clean up each band */
+	for (i = 0; i < infoPtr->uNumBands; i++) {
+	    lpBand = &infoPtr->bands[i];
+
+	    /* delete text strings */
+	    if (lpBand->lpText) {
+		COMCTL32_Free (lpBand->lpText);
+		lpBand->lpText = NULL;
+	    }
+	    /* destroy child window */
+	    DestroyWindow (lpBand->hwndChild);
+	}
+
+	/* free band array */
+	COMCTL32_Free (infoPtr->bands);
+	infoPtr->bands = NULL;
+    }
+
+    DeleteObject (infoPtr->hcurArrow);
+    DeleteObject (infoPtr->hcurHorz);
+    DeleteObject (infoPtr->hcurVert);
+    DeleteObject (infoPtr->hcurDrag);
+
+    /* free rebar info data */
+    COMCTL32_Free (infoPtr);
+    SetWindowLongA (hwnd, 0, 0);
+    TRACE("destroyed!\n");
+    return 0;
+}
+
+
+static LRESULT
+REBAR_EraseBkGnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    RECT cliprect;
+
+    if (GetClipBox ( (HDC)wParam, &cliprect))
+        return REBAR_InternalEraseBkGnd (hwnd, wParam, lParam, &cliprect);
+    return 0;
+}
+
+
+static LRESULT
+REBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+
+    return (LRESULT)infoPtr->hFont;
+}
+
+
+static LRESULT
+REBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    REBAR_BAND *lpBand;
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+
+    /* If InternalHitTest did not find a hit on the Gripper, */
+    /* then ignore the button click.                         */
+    if (infoPtr->ihitBand == -1) return 0;
+
+    SetCapture (hwnd);
+
+    /* save off the LOWORD and HIWORD of lParam as initial x,y */
+    lpBand = &infoPtr->bands[infoPtr->ihitBand];
+    infoPtr->dragStart = MAKEPOINTS(lParam);
+    infoPtr->dragNow = infoPtr->dragStart;
+    if (dwStyle & CCS_VERT)
+        infoPtr->ihitoffset = infoPtr->dragStart.y - (lpBand->rcBand.top+REBAR_PRE_GRIPPER);
+    else
+        infoPtr->ihitoffset = infoPtr->dragStart.x - (lpBand->rcBand.left+REBAR_PRE_GRIPPER);
+
+    return 0;
+}
+
+
+static LRESULT
+REBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    NMHDR layout;
+    RECT rect;
+
+    /* If InternalHitTest did not find a hit on the Gripper, */
+    /* then ignore the button click.                         */
+    if (infoPtr->ihitBand == -1) return 0;
+
+    infoPtr->dragStart.x = 0;
+    infoPtr->dragStart.y = 0;
+    infoPtr->dragNow = infoPtr->dragStart;
+    infoPtr->ihitBand = -1;
+
+    ReleaseCapture ();
+
+    if (infoPtr->fStatus & BEGIN_DRAG_ISSUED) {
+        REBAR_Notify(hwnd, (NMHDR *) &layout, infoPtr, RBN_LAYOUTCHANGED);
+	REBAR_Notify_NMREBAR (hwnd, infoPtr, -1, RBN_ENDDRAG);
+	infoPtr->fStatus &= ~BEGIN_DRAG_ISSUED;
+    }
+
+    GetClientRect(hwnd, &rect);
+    InvalidateRect(hwnd, NULL, TRUE);
+
+    return 0;
+}
+
+
+static LRESULT
+REBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    REBAR_BAND *band1, *band2;
+    POINTS ptsmove;
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+
+    /* Validate entry as hit on Gripper has occured */
+    if (GetCapture() != hwnd) return 0;
+    if (infoPtr->ihitBand == -1) return 0;
+
+    ptsmove = MAKEPOINTS(lParam);
+
+    /* if mouse did not move much, exit */
+    if ((abs(ptsmove.x - infoPtr->dragNow.x) <= mindragx) &&
+	(abs(ptsmove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
+
+    band1 = &infoPtr->bands[infoPtr->ihitBand-1];
+    band2 = &infoPtr->bands[infoPtr->ihitBand];
+
+    /* Test for valid drag case - must not be first band in row */
+    if (dwStyle & CCS_VERT) {
+	if ((ptsmove.x < band2->rcBand.left) ||
+	    (ptsmove.x > band2->rcBand.right) ||
+	    ((infoPtr->ihitBand > 0) && (band1->iRow != band2->iRow))) {
+	    FIXME("Cannot drag to other rows yet!!\n");
+	}
+	else {
+	    REBAR_HandleLRDrag (hwnd, infoPtr, &ptsmove, dwStyle);
+	}
+    }
+    else {
+	if ((ptsmove.y < band2->rcBand.top) ||
+	    (ptsmove.y > band2->rcBand.bottom) ||
+	    ((infoPtr->ihitBand > 0) && (band1->iRow != band2->iRow))) {
+	    FIXME("Cannot drag to other rows yet!!\n");
+	}
+	else {
+	    REBAR_HandleLRDrag (hwnd, infoPtr, &ptsmove, dwStyle);
+	}
+    }
+    return 0;
+}
+
+
+inline static LRESULT
+REBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    if (GetWindowLongA (hwnd, GWL_STYLE) & WS_BORDER) {
+	((LPRECT)lParam)->left   += GetSystemMetrics(SM_CXEDGE);
+	((LPRECT)lParam)->top    += GetSystemMetrics(SM_CYEDGE);
+	((LPRECT)lParam)->right  -= GetSystemMetrics(SM_CXEDGE);
+	((LPRECT)lParam)->bottom -= GetSystemMetrics(SM_CYEDGE);
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+REBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+    RECT rcWindow;
+    HDC hdc;
+
+    if (dwStyle & WS_MINIMIZE)
+	return 0; /* Nothing to do */
+
+    DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
+
+    if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW )))
+	return 0;
+
+    if (dwStyle & WS_BORDER) {
+	GetWindowRect (hwnd, &rcWindow);
+	OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
+	DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT);
+    }
+
+    ReleaseDC( hwnd, hdc );
+
+    return 0;
+}
+
+
+static LRESULT
+REBAR_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    HDC hdc;
+    PAINTSTRUCT ps;
+
+    hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
+
+    TRACE("painting (%d,%d)-(%d,%d)\n",
+	  ps.rcPaint.left, ps.rcPaint.top,
+	  ps.rcPaint.right, ps.rcPaint.bottom);
+
+    if (ps.fErase) {
+	/* Erase area of paint if requested */
+        REBAR_InternalEraseBkGnd (hwnd, wParam, lParam, &ps.rcPaint);
+    }
+
+    REBAR_Refresh (hwnd, hdc);
+    if (!wParam)
+	EndPaint (hwnd, &ps);
+    return 0;
+}
+
+
+static LRESULT
+REBAR_SetCursor (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+    POINT pt;
+    UINT  flags;
+
+    TRACE("code=0x%X  id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
+
+    GetCursorPos (&pt);
+    ScreenToClient (hwnd, &pt);
+
+    REBAR_InternalHitTest (hwnd, &pt, &flags, NULL);
+
+    if (flags == RBHT_GRABBER) {
+	if ((dwStyle & CCS_VERT) &&
+	    !(dwStyle & RBS_VERTICALGRIPPER))
+	    SetCursor (infoPtr->hcurVert);
+	else
+	    SetCursor (infoPtr->hcurHorz);
+    }
+    else if (flags != RBHT_CLIENT)
+	SetCursor (infoPtr->hcurArrow);
+
+    return 0;
+}
+
+
+static LRESULT
+REBAR_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    RECT rcClient;
+    REBAR_BAND *lpBand;
+    UINT i;
+
+    infoPtr->hFont = (HFONT)wParam;
+
+    /* revalidate all bands to change sizes of text in headers of bands */
+    for (i=0; i<infoPtr->uNumBands; i++) {
+        lpBand = &infoPtr->bands[i];
+	REBAR_ValidateBand (hwnd, infoPtr, lpBand);
+    }
+
+
+    if (lParam) {
+        GetClientRect (hwnd, &rcClient);
+        REBAR_Layout (hwnd, &rcClient, FALSE, TRUE);
+	REBAR_ForceResize (hwnd);
+	REBAR_MoveChildWindows (hwnd);
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+REBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    RECT rcClient;
+
+    /* auto resize deadlock check */
+    if (infoPtr->fStatus & AUTO_RESIZE) {
+	infoPtr->fStatus &= ~AUTO_RESIZE;
+	TRACE("AUTO_RESIZE was set, reset, fStatus=%08x\n",
+	      infoPtr->fStatus);
+	return 0;
+    }
+
+    GetClientRect (hwnd, &rcClient);
+    if ((lParam == 0) && (rcClient.right == 0) && (rcClient.bottom == 0)) {
+      /* native control seems to do this */
+      GetClientRect (GetParent(hwnd), &rcClient);
+      TRACE("sizing rebar, message and client zero, parent client (%d,%d)\n", 
+	    rcClient.right, rcClient.bottom);
+    }
+    else {
+      TRACE("sizing rebar from (%ld,%ld) to (%d,%d), client (%d,%d)\n", 
+	    infoPtr->calcSize.cx, infoPtr->calcSize.cy,
+	    LOWORD(lParam), HIWORD(lParam),
+	    rcClient.right, rcClient.bottom);
+    }
+
+    REBAR_Layout (hwnd, &rcClient, TRUE, TRUE);
+    REBAR_ForceResize (hwnd);
+    infoPtr->fStatus &= ~AUTO_RESIZE;
+    REBAR_MoveChildWindows (hwnd);
+
+    return 0;
+}
+
+
+static LRESULT WINAPI
+REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam);
+    if (!REBAR_GetInfoPtr (hwnd) && (uMsg != WM_CREATE))
+	    return DefWindowProcA (hwnd, uMsg, wParam, lParam);
+    switch (uMsg)
+    {
+/*	case RB_BEGINDRAG: */
+
+	case RB_DELETEBAND:
+	    return REBAR_DeleteBand (hwnd, wParam, lParam);
+
+/*	case RB_DRAGMOVE: */
+/*	case RB_ENDDRAG: */
+
+	case RB_GETBANDBORDERS:
+	    return REBAR_GetBandBorders (hwnd, wParam, lParam);
+
+	case RB_GETBANDCOUNT:
+	    return REBAR_GetBandCount (hwnd);
+
+	case RB_GETBANDINFO:	/* obsoleted after IE3, but we have to
+				   support it anyway. */
+	case RB_GETBANDINFOA:
+	    return REBAR_GetBandInfoA (hwnd, wParam, lParam);
+
+	case RB_GETBANDINFOW:
+	    return REBAR_GetBandInfoW (hwnd, wParam, lParam);
+
+	case RB_GETBARHEIGHT:
+	    return REBAR_GetBarHeight (hwnd, wParam, lParam);
+
+	case RB_GETBARINFO:
+	    return REBAR_GetBarInfo (hwnd, wParam, lParam);
+
+	case RB_GETBKCOLOR:
+	    return REBAR_GetBkColor (hwnd);
+
+/*	case RB_GETCOLORSCHEME: */
+/*	case RB_GETDROPTARGET: */
+
+	case RB_GETPALETTE:
+	    return REBAR_GetPalette (hwnd, wParam, lParam);
+
+	case RB_GETRECT:
+	    return REBAR_GetRect (hwnd, wParam, lParam);
+
+	case RB_GETROWCOUNT:
+	    return REBAR_GetRowCount (hwnd);
+
+	case RB_GETROWHEIGHT:
+	    return REBAR_GetRowHeight (hwnd, wParam, lParam);
+
+	case RB_GETTEXTCOLOR:
+	    return REBAR_GetTextColor (hwnd);
+
+	case RB_GETTOOLTIPS:
+	    return REBAR_GetToolTips (hwnd);
+
+	case RB_GETUNICODEFORMAT:
+	    return REBAR_GetUnicodeFormat (hwnd);
+
+	case CCM_GETVERSION:
+	    return REBAR_GetVersion (hwnd);
+
+	case RB_HITTEST:
+	    return REBAR_HitTest (hwnd, wParam, lParam);
+
+	case RB_IDTOINDEX:
+	    return REBAR_IdToIndex (hwnd, wParam, lParam);
+
+	case RB_INSERTBANDA:
+	    return REBAR_InsertBandA (hwnd, wParam, lParam);
+
+	case RB_INSERTBANDW:
+	    return REBAR_InsertBandW (hwnd, wParam, lParam);
+
+	case RB_MAXIMIZEBAND:
+	    return REBAR_MaximizeBand (hwnd, wParam, lParam);
+
+	case RB_MINIMIZEBAND:
+	    return REBAR_MinimizeBand (hwnd, wParam, lParam);
+
+	case RB_MOVEBAND:
+	    return REBAR_MoveBand (hwnd, wParam, lParam);
+
+	case RB_SETBANDINFOA:
+	    return REBAR_SetBandInfoA (hwnd, wParam, lParam);
+
+	case RB_SETBANDINFOW:
+	    return REBAR_SetBandInfoW (hwnd, wParam, lParam);
+
+	case RB_SETBARINFO:
+	    return REBAR_SetBarInfo (hwnd, wParam, lParam);
+
+	case RB_SETBKCOLOR:
+	    return REBAR_SetBkColor (hwnd, wParam, lParam);
+
+/*	case RB_SETCOLORSCHEME: */
+/*	case RB_SETPALETTE: */
+/*	    return REBAR_GetPalette (hwnd, wParam, lParam); */
+
+	case RB_SETPARENT:
+	    return REBAR_SetParent (hwnd, wParam, lParam);
+
+	case RB_SETTEXTCOLOR:
+	    return REBAR_SetTextColor (hwnd, wParam, lParam);
+
+/*	case RB_SETTOOLTIPS: */
+
+	case RB_SETUNICODEFORMAT:
+	    return REBAR_SetUnicodeFormat (hwnd, wParam);
+
+	case CCM_SETVERSION:
+	    return REBAR_SetVersion (hwnd, (INT)wParam);
+
+	case RB_SHOWBAND:
+	    return REBAR_ShowBand (hwnd, wParam, lParam);
+
+	case RB_SIZETORECT:
+	    return REBAR_SizeToRect (hwnd, wParam, lParam);
+
+
+/*    Messages passed to parent */
+	case WM_COMMAND:
+	case WM_DRAWITEM:
+	case WM_NOTIFY:
+	    return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
+
+
+/*      case WM_CHARTOITEM:     supported according to ControlSpy */
+
+	case WM_CREATE:
+	    return REBAR_Create (hwnd, wParam, lParam);
+
+	case WM_DESTROY:
+	    return REBAR_Destroy (hwnd, wParam, lParam);
+
+        case WM_ERASEBKGND:
+	    return REBAR_EraseBkGnd (hwnd, wParam, lParam);
+
+	case WM_GETFONT:
+	    return REBAR_GetFont (hwnd, wParam, lParam);
+
+/*      case WM_LBUTTONDBLCLK:  supported according to ControlSpy */
+
+	case WM_LBUTTONDOWN:
+	    return REBAR_LButtonDown (hwnd, wParam, lParam);
+
+	case WM_LBUTTONUP:
+	    return REBAR_LButtonUp (hwnd, wParam, lParam);
+
+/*      case WM_MEASUREITEM:    supported according to ControlSpy */
+
+	case WM_MOUSEMOVE:
+	    return REBAR_MouseMove (hwnd, wParam, lParam);
+
+	case WM_NCCALCSIZE:
+	    return REBAR_NCCalcSize (hwnd, wParam, lParam);
+
+/*      case WM_NCCREATE:       supported according to ControlSpy */
+/*      case WM_NCHITTEST:      supported according to ControlSpy */
+
+	case WM_NCPAINT:
+	    return REBAR_NCPaint (hwnd, wParam, lParam);
+
+/*      case WM_NOTIFYFORMAT:   supported according to ControlSpy */
+
+	case WM_PAINT:
+	    return REBAR_Paint (hwnd, wParam, lParam);
+
+/*      case WM_PALETTECHANGED: supported according to ControlSpy */
+/*      case WM_PRINTCLIENT:    supported according to ControlSpy */
+/*      case WM_QUERYNEWPALETTE:supported according to ControlSpy */
+/*      case WM_RBUTTONDOWN:    supported according to ControlSpy */
+/*      case WM_RBUTTONUP:      supported according to ControlSpy */
+
+	case WM_SETCURSOR:
+	    return REBAR_SetCursor (hwnd, wParam, lParam);
+
+	case WM_SETFONT:
+	    return REBAR_SetFont (hwnd, wParam, lParam);
+
+/*      case WM_SETREDRAW:      supported according to ControlSpy */
+
+	case WM_SIZE:
+	    return REBAR_Size (hwnd, wParam, lParam);
+
+/*      case WM_STYLECHANGED:   supported according to ControlSpy */
+/*      case WM_SYSCOLORCHANGE: supported according to ControlSpy */
+/*      case WM_VKEYTOITEM:     supported according to ControlSpy */
+/*	case WM_WININICHANGE: */
+
+	default:
+	    if (uMsg >= WM_USER)
+		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;
+}
+
+
+VOID
+REBAR_Register (void)
+{
+    WNDCLASSA wndClass;
+
+    ZeroMemory (&wndClass, sizeof(WNDCLASSA));
+    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
+    wndClass.lpfnWndProc   = (WNDPROC)REBAR_WindowProc;
+    wndClass.cbClsExtra    = 0;
+    wndClass.cbWndExtra    = sizeof(REBAR_INFO *);
+    wndClass.hCursor       = 0;
+    wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+    wndClass.lpszClassName = REBARCLASSNAMEA;
+ 
+    RegisterClassA (&wndClass);
+
+    mindragx = GetSystemMetrics (SM_CXDRAG);
+    mindragy = GetSystemMetrics (SM_CYDRAG);
+
+}
+
+
+VOID
+REBAR_Unregister (void)
+{
+    UnregisterClassA (REBARCLASSNAMEA, (HINSTANCE)NULL);
+}
+
Index: trunk/src/comctl32/rebar.cpp
===================================================================
--- trunk/src/comctl32/rebar.cpp	(revision 5627)
+++ 	(revision )
@@ -1,2024 +1,0 @@
-/* $Id: rebar.cpp,v 1.2 2000-03-18 16:17:27 cbratschi Exp $ */
-/*
- * Rebar control
- *
- * Copyright 1998, 1999 Eric Kohl
- * Copyright 1999 Achim Hasenmueller
- * Copyright 1999 Christoph Bratschi
- *
- * NOTES
- *   An author is needed! Any volunteers?
- *   I will only improve this control once in a while.
- *     Eric <ekohl@abo.rhein-zeitung.de>
- *
- * TODO:
- *   - vertical placement
- *   - ComboBox and ComboBoxEx placement
- *   - center image
- *   - Layout code.
- *   - Display code.
- *   - Some messages.
- *   - All notifications.
- */
-
-/* WINE 991212 */
-
-#include <string.h>
-
-#include "winbase.h"
-#include "wingdi.h"
-#include "commctrl.h"
-#include "ccbase.h"
-#include "rebar.h"
-#include "comctl32.h"
-
-
-/* fDraw flags */
-#define DRAW_GRIPPER    1
-#define DRAW_IMAGE      2
-#define DRAW_TEXT       4
-#define DRAW_CHILD      8
-
-#define GRIPPER_WIDTH   13
-
-
-#define REBAR_GetInfoPtr(hwnd) ((REBAR_INFO*)getInfoPtr(hwnd))
-
-
-static VOID
-REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
-{
-
-    DrawEdge (hdc, &lpBand->rcBand, BDR_RAISEDINNER, BF_MIDDLE);
-
-    /* draw background */
-
-    /* draw gripper */
-    if (lpBand->fDraw & DRAW_GRIPPER)
-        DrawEdge (hdc, &lpBand->rcGripper, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
-
-    /* draw caption image */
-    if (lpBand->fDraw & DRAW_IMAGE) {
-        /* FIXME: center image */
-        POINT pt;
-
-        pt.y = (lpBand->rcCapImage.bottom + lpBand->rcCapImage.top - infoPtr->imageSize.cy)/2;
-        pt.x = (lpBand->rcCapImage.right + lpBand->rcCapImage.left - infoPtr->imageSize.cx)/2;
-
-        ImageList_Draw (infoPtr->himl, lpBand->iImage, hdc,
-/*                      lpBand->rcCapImage.left, lpBand->rcCapImage.top, */
-                        pt.x, pt.y,
-                        ILD_TRANSPARENT);
-    }
-
-    /* draw caption text */
-    if (lpBand->fDraw & DRAW_TEXT) {
-        HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
-        INT oldBkMode = SetBkMode (hdc, TRANSPARENT);
-        DrawTextW (hdc, lpBand->lpText, -1, &lpBand->rcCapText,
-                     DT_CENTER | DT_VCENTER | DT_SINGLELINE);
-        if (oldBkMode != TRANSPARENT)
-            SetBkMode (hdc, oldBkMode);
-        SelectObject (hdc, hOldFont);
-    }
-}
-
-
-static VOID
-REBAR_Refresh (HWND hwnd, HDC hdc)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    REBAR_BAND *lpBand;
-    UINT i;
-
-    for (i = 0; i < infoPtr->uNumBands; i++) {
-        lpBand = &infoPtr->bands[i];
-
-        if ((lpBand->fStyle & RBBS_HIDDEN) ||
-            ((GetWindowLongA (hwnd, GWL_STYLE) & CCS_VERT) &&
-             (lpBand->fStyle & RBBS_NOVERT)))
-            continue;
-
-        REBAR_DrawBand (hdc, infoPtr, lpBand);
-
-    }
-}
-
-
-static VOID
-REBAR_CalcHorzBand (REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
-{
-    lpBand->fDraw = 0;
-
-    /* set initial caption image rectangle */
-    SetRect (&lpBand->rcCapImage, 0, 0, 0, 0);
-
-    /* image is visible */
-    if ((lpBand->iImage > -1) && (infoPtr->himl)) {
-        lpBand->fDraw |= DRAW_IMAGE;
-
-        lpBand->rcCapImage.right  = lpBand->rcCapImage.left + infoPtr->imageSize.cx;
-        lpBand->rcCapImage.bottom = lpBand->rcCapImage.top + infoPtr->imageSize.cy;
-
-        /* update band height */
-        if (lpBand->uMinHeight < infoPtr->imageSize.cy + 2) {
-            lpBand->uMinHeight = infoPtr->imageSize.cy + 2;
-            lpBand->rcBand.bottom = lpBand->rcBand.top + lpBand->uMinHeight;
-        }
-    }
-
-    /* set initial caption text rectangle */
-    lpBand->rcCapText.left   = lpBand->rcCapImage.right;
-    lpBand->rcCapText.top    = lpBand->rcBand.top + 1;
-    lpBand->rcCapText.right  = lpBand->rcCapText.left;
-    lpBand->rcCapText.bottom = lpBand->rcBand.bottom - 1;
-
-    /* text is visible */
-    if (lpBand->lpText) {
-        HDC hdc = GetDC (0);
-        HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
-        SIZE size;
-
-        lpBand->fDraw |= DRAW_TEXT;
-        GetTextExtentPoint32W (hdc, lpBand->lpText,
-                               lstrlenW (lpBand->lpText), &size);
-        lpBand->rcCapText.right += size.cx;
-
-        SelectObject (hdc, hOldFont);
-        ReleaseDC (0, hdc);
-    }
-
-    /* set initial child window rectangle */
-    if (lpBand->fStyle & RBBS_FIXEDSIZE) {
-        lpBand->rcChild.left   = lpBand->rcCapText.right;
-        lpBand->rcChild.top    = lpBand->rcBand.top;
-        lpBand->rcChild.right  = lpBand->rcBand.right;
-        lpBand->rcChild.bottom = lpBand->rcBand.bottom;
-    }
-    else {
-        lpBand->rcChild.left   = lpBand->rcCapText.right + 4;
-        lpBand->rcChild.top    = lpBand->rcBand.top + 2;
-        lpBand->rcChild.right  = lpBand->rcBand.right - 4;
-        lpBand->rcChild.bottom = lpBand->rcBand.bottom - 2;
-    }
-
-    /* calculate gripper rectangle */
-    if ((!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
-        (!(lpBand->fStyle & RBBS_FIXEDSIZE)) &&
-        ((lpBand->fStyle & RBBS_GRIPPERALWAYS) ||
-         (infoPtr->uNumBands > 1))) {
-        lpBand->fDraw |= DRAW_GRIPPER;
-        lpBand->rcGripper.left   = lpBand->rcBand.left + 3;
-        lpBand->rcGripper.right  = lpBand->rcGripper.left + 3;
-        lpBand->rcGripper.top    = lpBand->rcBand.top + 3;
-        lpBand->rcGripper.bottom = lpBand->rcBand.bottom - 3;
-
-        /* move caption rectangles */
-        OffsetRect (&lpBand->rcCapImage, GRIPPER_WIDTH, 0);
-        OffsetRect (&lpBand->rcCapText, GRIPPER_WIDTH, 0);
-
-        /* adjust child rectangle */
-        lpBand->rcChild.left += GRIPPER_WIDTH;
-    }
-
-
-}
-
-
-static VOID
-REBAR_CalcVertBand (HWND hwnd, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
-{
-    lpBand->fDraw = 0;
-
-    /* set initial caption image rectangle */
-    SetRect (&lpBand->rcCapImage, 0, 0, 0, 0);
-
-    /* image is visible */
-    if ((lpBand->iImage > -1) && (infoPtr->himl)) {
-        lpBand->fDraw |= DRAW_IMAGE;
-
-        lpBand->rcCapImage.right  = lpBand->rcCapImage.left + infoPtr->imageSize.cx;
-        lpBand->rcCapImage.bottom = lpBand->rcCapImage.top + infoPtr->imageSize.cy;
-
-        /* update band width */
-        if (lpBand->uMinHeight < infoPtr->imageSize.cx + 2) {
-            lpBand->uMinHeight = infoPtr->imageSize.cx + 2;
-            lpBand->rcBand.right = lpBand->rcBand.left + lpBand->uMinHeight;
-        }
-    }
-
-    /* set initial caption text rectangle */
-    lpBand->rcCapText.left   = lpBand->rcBand.left + 1;
-    lpBand->rcCapText.top    = lpBand->rcCapImage.bottom;
-    lpBand->rcCapText.right  = lpBand->rcBand.right - 1;
-    lpBand->rcCapText.bottom = lpBand->rcCapText.top;
-
-    /* text is visible */
-    if (lpBand->lpText) {
-        HDC hdc = GetDC (0);
-        HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
-        SIZE size;
-
-        lpBand->fDraw |= DRAW_TEXT;
-        GetTextExtentPoint32W (hdc, lpBand->lpText,
-                               lstrlenW (lpBand->lpText), &size);
-/*      lpBand->rcCapText.right += size.cx; */
-        lpBand->rcCapText.bottom += size.cy;
-
-        SelectObject (hdc, hOldFont);
-        ReleaseDC (0, hdc);
-    }
-
-    /* set initial child window rectangle */
-    if (lpBand->fStyle & RBBS_FIXEDSIZE) {
-        lpBand->rcChild.left   = lpBand->rcBand.left;
-        lpBand->rcChild.top    = lpBand->rcCapText.bottom;
-        lpBand->rcChild.right  = lpBand->rcBand.right;
-        lpBand->rcChild.bottom = lpBand->rcBand.bottom;
-    }
-    else {
-        lpBand->rcChild.left   = lpBand->rcBand.left + 2;
-        lpBand->rcChild.top    = lpBand->rcCapText.bottom + 4;
-        lpBand->rcChild.right  = lpBand->rcBand.right - 2;
-        lpBand->rcChild.bottom = lpBand->rcBand.bottom - 4;
-    }
-
-    /* calculate gripper rectangle */
-    if ((!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
-        (!(lpBand->fStyle & RBBS_FIXEDSIZE)) &&
-        ((lpBand->fStyle & RBBS_GRIPPERALWAYS) ||
-         (infoPtr->uNumBands > 1))) {
-        lpBand->fDraw |= DRAW_GRIPPER;
-
-        if (GetWindowLongA (hwnd, GWL_STYLE) & RBS_VERTICALGRIPPER) {
-            /* adjust band width */
-            lpBand->rcBand.right += GRIPPER_WIDTH;
-            lpBand->uMinHeight += GRIPPER_WIDTH;
-
-            lpBand->rcGripper.left   = lpBand->rcBand.left + 3;
-            lpBand->rcGripper.right  = lpBand->rcGripper.left + 3;
-            lpBand->rcGripper.top    = lpBand->rcBand.top + 3;
-            lpBand->rcGripper.bottom = lpBand->rcBand.bottom - 3;
-
-            /* move caption rectangles */
-            OffsetRect (&lpBand->rcCapImage, GRIPPER_WIDTH, 0);
-            OffsetRect (&lpBand->rcCapText, GRIPPER_WIDTH, 0);
-
-            /* adjust child rectangle */
-            lpBand->rcChild.left += GRIPPER_WIDTH;
-        }
-        else {
-            lpBand->rcGripper.left   = lpBand->rcBand.left + 3;
-            lpBand->rcGripper.right  = lpBand->rcBand.right - 3;
-            lpBand->rcGripper.top    = lpBand->rcBand.top + 3;
-            lpBand->rcGripper.bottom = lpBand->rcGripper.top + 3;
-
-            /* move caption rectangles */
-            OffsetRect (&lpBand->rcCapImage, 0, GRIPPER_WIDTH);
-            OffsetRect (&lpBand->rcCapText, 0, GRIPPER_WIDTH);
-
-            /* adjust child rectangle */
-            lpBand->rcChild.top += GRIPPER_WIDTH;
-        }
-    }
-}
-
-
-static VOID
-REBAR_Layout (HWND hwnd, LPRECT lpRect)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
-    REBAR_BAND *lpBand;
-    RECT rcClient;
-    INT x, y, cx, cy;
-    UINT i;
-
-    if (lpRect)
-        rcClient = *lpRect;
-    else
-        GetClientRect (hwnd, &rcClient);
-
-    x = 0;
-    y = 0;
-
-    if (dwStyle & CCS_VERT) {
-        cx = 20;    /* FIXME: fixed height */
-        cy = rcClient.bottom - rcClient.top;
-    }
-    else {
-        cx = rcClient.right - rcClient.left;
-        cy = 20;    /* FIXME: fixed height */
-    }
-
-    for (i = 0; i < infoPtr->uNumBands; i++) {
-        lpBand = &infoPtr->bands[i];
-
-        if ((lpBand->fStyle & RBBS_HIDDEN) ||
-            ((dwStyle & CCS_VERT) && (lpBand->fStyle & RBBS_NOVERT)))
-            continue;
-
-
-        if (dwStyle & CCS_VERT) {
-            if (lpBand->fStyle & RBBS_VARIABLEHEIGHT)
-                cx = lpBand->cyMaxChild;
-            else if (lpBand->fStyle & RBBIM_CHILDSIZE)
-                cx = lpBand->cyMinChild;
-            else
-                cx = 20; /* FIXME */
-
-            lpBand->rcBand.left   = x;
-            lpBand->rcBand.right  = x + cx;
-            lpBand->rcBand.top    = y;
-            lpBand->rcBand.bottom = y + cy;
-            lpBand->uMinHeight = cx;
-        }
-        else {
-            if (lpBand->fStyle & RBBS_VARIABLEHEIGHT)
-                cy = lpBand->cyMaxChild;
-            else if (lpBand->fStyle & RBBIM_CHILDSIZE)
-                cy = lpBand->cyMinChild;
-            else {
-//                cy = 20; /* FIXME */
-                cy = 36; //SvL: Better size of AbiWord (FIXME)
-            }
-
-            lpBand->rcBand.left   = x;
-            lpBand->rcBand.right  = x + cx;
-            lpBand->rcBand.top    = y;
-            lpBand->rcBand.bottom = y + cy;
-            lpBand->uMinHeight = cy;
-        }
-
-        if (dwStyle & CCS_VERT) {
-            REBAR_CalcVertBand (hwnd, infoPtr, lpBand);
-            x += lpBand->uMinHeight;
-        }
-        else {
-            REBAR_CalcHorzBand (infoPtr, lpBand);
-            y += lpBand->uMinHeight;
-        }
-    }
-
-    if (dwStyle & CCS_VERT) {
-        infoPtr->calcSize.cx = x;
-        infoPtr->calcSize.cy = rcClient.bottom - rcClient.top;
-    }
-    else {
-        infoPtr->calcSize.cx = rcClient.right - rcClient.left;
-        infoPtr->calcSize.cy = y;
-    }
-}
-
-
-static VOID
-REBAR_ForceResize (HWND hwnd)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    RECT rc;
-
-//    TRACE (rebar, " to [%d x %d]!\n",
-//         infoPtr->calcSize.cx, infoPtr->calcSize.cy);
-
-    infoPtr->bAutoResize = TRUE;
-
-    rc.left = 0;
-    rc.top = 0;
-    rc.right  = infoPtr->calcSize.cx;
-    rc.bottom = infoPtr->calcSize.cy;
-
-    if (GetWindowLongA (hwnd, GWL_STYLE) & WS_BORDER) {
-        InflateRect (&rc, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
-    }
-
-    SetWindowPos (hwnd, 0, 0, 0,
-                    rc.right - rc.left, rc.bottom - rc.top,
-                    SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
-}
-
-
-static VOID
-REBAR_MoveChildWindows (HWND hwnd)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    REBAR_BAND *lpBand;
-    CHAR szClassName[40];
-    UINT i;
-
-    for (i = 0; i < infoPtr->uNumBands; i++) {
-        lpBand = &infoPtr->bands[i];
-
-        if (lpBand->fStyle & RBBS_HIDDEN)
-            continue;
-        if (lpBand->hwndChild) {
-//          TRACE (rebar, "hwndChild = %x\n", lpBand->hwndChild);
-
-            GetClassNameA (lpBand->hwndChild, szClassName, 40);
-            if (!lstrcmpA (szClassName, "ComboBox")) {
-                INT nEditHeight, yPos;
-                RECT rc;
-
-                /* special placement code for combo box */
-
-
-                /* get size of edit line */
-                GetWindowRect (lpBand->hwndChild, &rc);
-                nEditHeight = rc.bottom - rc.top;
-                yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;
-
-                /* center combo box inside child area */
-                SetWindowPos (lpBand->hwndChild, HWND_TOP,
-                            lpBand->rcChild.left, /*lpBand->rcChild.top*/ yPos,
-                            lpBand->rcChild.right - lpBand->rcChild.left,
-                            nEditHeight,
-                            SWP_SHOWWINDOW);
-            }
-#if 0
-            else if (!lstrcmpA (szClassName, WC_COMBOBOXEXA)) {
-                INT nEditHeight, yPos;
-                RECT rc;
-                HWND hwndEdit;
-
-                /* special placement code for extended combo box */
-
-                /* get size of edit line */
-                hwndEdit = SendMessageA (lpBand->hwndChild, CBEM_GETEDITCONTROL, 0, 0);
-                GetWindowRect (hwndEdit, &rc);
-                nEditHeight = rc.bottom - rc.top;
-                yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;
-
-                /* center combo box inside child area */
-                SetWindowPos (lpBand->hwndChild, HWND_TOP,
-                            lpBand->rcChild.left, /*lpBand->rcChild.top*/ yPos,
-                            lpBand->rcChild.right - lpBand->rcChild.left,
-                            nEditHeight,
-                            SWP_SHOWWINDOW);
-
-            }
-#endif
-            else {
-                SetWindowPos (lpBand->hwndChild, HWND_TOP,
-                            lpBand->rcChild.left, lpBand->rcChild.top,
-                            lpBand->rcChild.right - lpBand->rcChild.left,
-                            lpBand->rcChild.bottom - lpBand->rcChild.top,
-                            SWP_SHOWWINDOW);
-            }
-        }
-    }
-}
-
-
-static void
-REBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pBand)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    REBAR_BAND *lpBand;
-    RECT rect;
-    INT  iCount;
-
-    GetClientRect (hwnd, &rect);
-
-    *pFlags = RBHT_NOWHERE;
-    if (PtInRect (&rect, *lpPt))
-    {
-        if (infoPtr->uNumBands == 0) {
-            *pFlags = RBHT_NOWHERE;
-            if (pBand)
-                *pBand = -1;
-//          TRACE (rebar, "NOWHERE\n");
-            return;
-        }
-        else {
-            /* somewhere inside */
-            for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
-                lpBand = &infoPtr->bands[iCount];
-                if (PtInRect (&lpBand->rcBand, *lpPt)) {
-                    if (pBand)
-                        *pBand = iCount;
-                    if (PtInRect (&lpBand->rcGripper, *lpPt)) {
-                        *pFlags = RBHT_GRABBER;
-//                      TRACE (rebar, "ON GRABBER %d\n", iCount);
-                        return;
-                    }
-                    else if (PtInRect (&lpBand->rcCapImage, *lpPt)) {
-                        *pFlags = RBHT_CAPTION;
-//                      TRACE (rebar, "ON CAPTION %d\n", iCount);
-                        return;
-                    }
-                    else if (PtInRect (&lpBand->rcCapText, *lpPt)) {
-                        *pFlags = RBHT_CAPTION;
-//                      TRACE (rebar, "ON CAPTION %d\n", iCount);
-                        return;
-                    }
-                    else if (PtInRect (&lpBand->rcChild, *lpPt)) {
-                        *pFlags = RBHT_CLIENT;
-//                      TRACE (rebar, "ON CLIENT %d\n", iCount);
-                        return;
-                    }
-                    else {
-                        *pFlags = RBHT_NOWHERE;
-//                      TRACE (rebar, "NOWHERE %d\n", iCount);
-                        return;
-                    }
-                }
-            }
-
-            *pFlags = RBHT_NOWHERE;
-            if (pBand)
-                *pBand = -1;
-
-//          TRACE (rebar, "NOWHERE\n");
-            return;
-        }
-    }
-    else {
-        *pFlags = RBHT_NOWHERE;
-        if (pBand)
-            *pBand = -1;
-//      TRACE (rebar, "NOWHERE\n");
-        return;
-    }
-
-//    TRACE (rebar, "flags=0x%X\n", *pFlags);
-    return;
-}
-
-
-
-/* << REBAR_BeginDrag >> */
-
-
-static LRESULT
-REBAR_DeleteBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    UINT uBand = (UINT)wParam;
-
-    if (uBand >= infoPtr->uNumBands)
-        return FALSE;
-
-//    TRACE (rebar, "deleting band %u!\n", uBand);
-
-    if (infoPtr->uNumBands == 1) {
-//      TRACE (rebar, " simple delete!\n");
-        COMCTL32_Free (infoPtr->bands);
-        infoPtr->bands = NULL;
-        infoPtr->uNumBands = 0;
-    }
-    else {
-        REBAR_BAND *oldBands = infoPtr->bands;
-//        TRACE(rebar, "complex delete! [uBand=%u]\n", uBand);
-
-        infoPtr->uNumBands--;
-        infoPtr->bands = (REBAR_BAND*)COMCTL32_Alloc (sizeof (REBAR_BAND) * infoPtr->uNumBands);
-        if (uBand > 0) {
-            memcpy (&infoPtr->bands[0], &oldBands[0],
-                    uBand * sizeof(REBAR_BAND));
-        }
-
-        if (uBand < infoPtr->uNumBands) {
-            memcpy (&infoPtr->bands[uBand], &oldBands[uBand+1],
-                    (infoPtr->uNumBands - uBand) * sizeof(REBAR_BAND));
-        }
-
-        COMCTL32_Free (oldBands);
-    }
-
-    REBAR_Layout (hwnd, NULL);
-    REBAR_ForceResize (hwnd);
-    REBAR_MoveChildWindows (hwnd);
-
-    return TRUE;
-}
-
-
-/* << REBAR_DragMove >> */
-/* << REBAR_EndDrag >> */
-
-
-static LRESULT
-REBAR_GetBandBorders (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    /* LPRECT32 lpRect = (LPRECT32)lParam; */
-    REBAR_BAND *lpBand;
-
-    if (!lParam)
-        return 0;
-    if ((UINT)wParam >= infoPtr->uNumBands)
-        return 0;
-
-    lpBand = &infoPtr->bands[(UINT)wParam];
-    if (GetWindowLongA (hwnd, GWL_STYLE) & RBS_BANDBORDERS) {
-
-    }
-    else {
-
-    }
-
-    return 0;
-}
-
-
-static LRESULT
-REBAR_GetBandCount (HWND hwnd)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-
-//    TRACE (rebar, "band count %u!\n", infoPtr->uNumBands);
-
-    return infoPtr->uNumBands;
-}
-
-
-static LRESULT
-REBAR_GetBandInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
-    REBAR_BAND *lpBand;
-
-    if (lprbbi == NULL)
-        return FALSE;
-    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
-        return FALSE;
-    if ((UINT)wParam >= infoPtr->uNumBands)
-        return FALSE;
-
-//    TRACE (rebar, "index %u\n", (UINT)wParam);
-
-    /* copy band information */
-    lpBand = &infoPtr->bands[(UINT)wParam];
-
-    if (lprbbi->fMask & RBBIM_STYLE)
-        lprbbi->fStyle = lpBand->fStyle;
-
-    if (lprbbi->fMask & RBBIM_COLORS) {
-        lprbbi->clrFore = lpBand->clrFore;
-        lprbbi->clrBack = lpBand->clrBack;
-    }
-
-    if ((lprbbi->fMask & RBBIM_TEXT) &&
-        (lprbbi->lpText) && (lpBand->lpText)) {
-            lstrcpynWtoA (lprbbi->lpText, lpBand->lpText,lprbbi->cch);
-    }
-
-    if (lprbbi->fMask & RBBIM_IMAGE)
-        lprbbi->iImage = lpBand->iImage;
-
-    if (lprbbi->fMask & RBBIM_CHILD)
-        lprbbi->hwndChild = lpBand->hwndChild;
-
-    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
-        lprbbi->cxMinChild = lpBand->cxMinChild;
-        lprbbi->cyMinChild = lpBand->cyMinChild;
-        lprbbi->cyMaxChild = lpBand->cyMaxChild;
-        lprbbi->cyChild    = lpBand->cyChild;
-        lprbbi->cyIntegral = lpBand->cyIntegral;
-    }
-
-    if (lprbbi->fMask & RBBIM_SIZE)
-        lprbbi->cx = lpBand->cx;
-
-    if (lprbbi->fMask & RBBIM_BACKGROUND)
-        lprbbi->hbmBack = lpBand->hbmBack;
-
-    if (lprbbi->fMask & RBBIM_ID)
-        lprbbi->wID = lpBand->wID;
-
-    /* check for additional data */
-    if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
-        if (lprbbi->fMask & RBBIM_IDEALSIZE)
-            lprbbi->cxIdeal = lpBand->cxIdeal;
-
-        if (lprbbi->fMask & RBBIM_LPARAM)
-            lprbbi->lParam = lpBand->lParam;
-
-        if (lprbbi->fMask & RBBIM_HEADERSIZE)
-            lprbbi->cxHeader = lpBand->cxHeader;
-    }
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_GetBandInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
-    REBAR_BAND *lpBand;
-
-    if (lprbbi == NULL)
-        return FALSE;
-    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
-        return FALSE;
-    if ((UINT)wParam >= infoPtr->uNumBands)
-        return FALSE;
-
-//    TRACE (rebar, "index %u\n", (UINT)wParam);
-
-    /* copy band information */
-    lpBand = &infoPtr->bands[(UINT)wParam];
-
-    if (lprbbi->fMask & RBBIM_STYLE)
-        lprbbi->fStyle = lpBand->fStyle;
-
-    if (lprbbi->fMask & RBBIM_COLORS) {
-        lprbbi->clrFore = lpBand->clrFore;
-        lprbbi->clrBack = lpBand->clrBack;
-    }
-
-    if ((lprbbi->fMask & RBBIM_TEXT) &&
-        (lprbbi->lpText) && (lpBand->lpText)) {
-            lstrcpynW (lprbbi->lpText, lpBand->lpText, lprbbi->cch);
-    }
-
-    if (lprbbi->fMask & RBBIM_IMAGE)
-        lprbbi->iImage = lpBand->iImage;
-
-    if (lprbbi->fMask & RBBIM_CHILD)
-        lprbbi->hwndChild = lpBand->hwndChild;
-
-    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
-        lprbbi->cxMinChild = lpBand->cxMinChild;
-        lprbbi->cyMinChild = lpBand->cyMinChild;
-        lprbbi->cyMaxChild = lpBand->cyMaxChild;
-        lprbbi->cyChild    = lpBand->cyChild;
-        lprbbi->cyIntegral = lpBand->cyIntegral;
-    }
-
-    if (lprbbi->fMask & RBBIM_SIZE)
-        lprbbi->cx = lpBand->cx;
-
-    if (lprbbi->fMask & RBBIM_BACKGROUND)
-        lprbbi->hbmBack = lpBand->hbmBack;
-
-    if (lprbbi->fMask & RBBIM_ID)
-        lprbbi->wID = lpBand->wID;
-
-    /* check for additional data */
-    if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
-        if (lprbbi->fMask & RBBIM_IDEALSIZE)
-            lprbbi->cxIdeal = lpBand->cxIdeal;
-
-        if (lprbbi->fMask & RBBIM_LPARAM)
-            lprbbi->lParam = lpBand->lParam;
-
-        if (lprbbi->fMask & RBBIM_HEADERSIZE)
-            lprbbi->cxHeader = lpBand->cxHeader;
-    }
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_GetBarHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    INT nHeight;
-
-    REBAR_Layout (hwnd, NULL);
-    nHeight = infoPtr->calcSize.cy;
-
-    if (GetWindowLongA (hwnd, GWL_STYLE) & WS_BORDER)
-        nHeight += (2 * GetSystemMetrics(SM_CYEDGE));
-
-
-//    FIXME (rebar, "height = %d\n", nHeight);
-
-    return nHeight;
-}
-
-
-static LRESULT
-REBAR_GetBarInfo (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    LPREBARINFO lpInfo = (LPREBARINFO)lParam;
-
-    if (lpInfo == NULL)
-        return FALSE;
-
-    if (lpInfo->cbSize < sizeof (REBARINFO))
-        return FALSE;
-
-//    TRACE (rebar, "getting bar info!\n");
-
-    if (infoPtr->himl) {
-        lpInfo->himl = infoPtr->himl;
-        lpInfo->fMask |= RBIM_IMAGELIST;
-    }
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_GetBkColor (HWND hwnd)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-
-//    TRACE (rebar, "background color 0x%06lx!\n", infoPtr->clrBk);
-
-    return infoPtr->clrBk;
-}
-
-
-/* << REBAR_GetColorScheme >> */
-/* << REBAR_GetDropTarget >> */
-
-
-static LRESULT
-REBAR_GetPalette (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-//    FIXME (rebar, "empty stub!\n");
-
-    return 0;
-}
-
-
-static LRESULT
-REBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    INT iBand = (INT)wParam;
-    LPRECT lprc = (LPRECT)lParam;
-    REBAR_BAND *lpBand;
-
-    if ((iBand < 0) && ((UINT)iBand >= infoPtr->uNumBands))
-        return FALSE;
-    if (!lprc)
-        return FALSE;
-
-//    TRACE (rebar, "band %d\n", iBand);
-
-    lpBand = &infoPtr->bands[iBand];
-    CopyRect (lprc, &lpBand->rcBand);
-/*
-    lprc->left   = lpBand->rcBand.left;
-    lprc->top    = lpBand->rcBand.top;
-    lprc->right  = lpBand->rcBand.right;
-    lprc->bottom = lpBand->rcBand.bottom;
-*/
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_GetRowCount (HWND hwnd)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-
-//    FIXME (rebar, "%u : semi stub!\n", infoPtr->uNumBands);
-
-    return infoPtr->uNumBands;
-}
-
-
-static LRESULT
-REBAR_GetRowHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-/*    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
-
-//    FIXME (rebar, "-- height = 20: semi stub!\n");
-
-    return 20;
-}
-
-
-static LRESULT
-REBAR_GetTextColor (HWND hwnd)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-
-//    TRACE (rebar, "text color 0x%06lx!\n", infoPtr->clrText);
-
-    return infoPtr->clrText;
-}
-
-
-static LRESULT
-REBAR_GetToolTips (HWND hwnd)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    return infoPtr->hwndToolTip;
-}
-
-
-static LRESULT
-REBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    /* REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
-    LPRBHITTESTINFO lprbht = (LPRBHITTESTINFO)lParam;
-
-    if (!lprbht)
-        return -1;
-
-    REBAR_InternalHitTest (hwnd, &lprbht->pt, &lprbht->flags, &lprbht->iBand);
-
-    return lprbht->iBand;
-}
-
-
-static LRESULT
-REBAR_IdToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    UINT i;
-
-    if (infoPtr == NULL)
-        return -1;
-
-    if (infoPtr->uNumBands < 1)
-        return -1;
-
-//    TRACE (rebar, "id %u\n", (UINT)wParam);
-
-    for (i = 0; i < infoPtr->uNumBands; i++) {
-        if (infoPtr->bands[i].wID == (UINT)wParam) {
-//          TRACE (rebar, "band %u found!\n", i);
-            return i;
-        }
-    }
-
-//    TRACE (rebar, "no band found!\n");
-    return -1;
-}
-
-
-static LRESULT
-REBAR_InsertBandA (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
-    UINT uIndex = (UINT)wParam;
-    REBAR_BAND *lpBand;
-
-    if (infoPtr == NULL)
-        return FALSE;
-    if (lprbbi == NULL)
-        return FALSE;
-    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
-        return FALSE;
-
-//    TRACE (rebar, "insert band at %u!\n", uIndex);
-
-    if (infoPtr->uNumBands == 0) {
-        infoPtr->bands = (REBAR_BAND *)COMCTL32_Alloc (sizeof (REBAR_BAND));
-        uIndex = 0;
-    }
-    else {
-        REBAR_BAND *oldBands = infoPtr->bands;
-        infoPtr->bands =
-            (REBAR_BAND *)COMCTL32_Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
-        if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
-            uIndex = infoPtr->uNumBands;
-
-        /* pre insert copy */
-        if (uIndex > 0) {
-            memcpy (&infoPtr->bands[0], &oldBands[0],
-                    uIndex * sizeof(REBAR_BAND));
-        }
-
-        /* post copy */
-        if (uIndex < infoPtr->uNumBands - 1) {
-            memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
-                    (infoPtr->uNumBands - uIndex - 1) * sizeof(REBAR_BAND));
-        }
-
-        COMCTL32_Free (oldBands);
-    }
-
-    infoPtr->uNumBands++;
-
-//    TRACE (rebar, "index %u!\n", uIndex);
-
-    /* initialize band (infoPtr->bands[uIndex])*/
-    lpBand = &infoPtr->bands[uIndex];
-
-    if (lprbbi->fMask & RBBIM_STYLE)
-        lpBand->fStyle = lprbbi->fStyle;
-
-    if (lprbbi->fMask & RBBIM_COLORS) {
-        lpBand->clrFore = lprbbi->clrFore;
-        lpBand->clrBack = lprbbi->clrBack;
-    }
-    else {
-        lpBand->clrFore = CLR_NONE;
-        lpBand->clrBack = CLR_NONE;
-    }
-
-    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
-        INT len = lstrlenA (lprbbi->lpText);
-        if (len > 0) {
-            lpBand->lpText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
-            lstrcpyAtoW (lpBand->lpText, lprbbi->lpText);
-        }
-    }
-
-    if (lprbbi->fMask & RBBIM_IMAGE)
-        lpBand->iImage = lprbbi->iImage;
-    else
-        lpBand->iImage = -1;
-
-    if (lprbbi->fMask & RBBIM_CHILD) {
-//      TRACE (rebar, "hwndChild = %x\n", lprbbi->hwndChild);
-        lpBand->hwndChild = lprbbi->hwndChild;
-        lpBand->hwndPrevParent =
-            SetParent (lpBand->hwndChild, hwnd);
-    }
-
-    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
-        lpBand->cxMinChild = lprbbi->cxMinChild;
-        lpBand->cyMinChild = lprbbi->cyMinChild;
-        lpBand->cyMaxChild = lprbbi->cyMaxChild;
-        lpBand->cyChild    = lprbbi->cyChild;
-        lpBand->cyIntegral = lprbbi->cyIntegral;
-    }
-    else {
-        lpBand->cxMinChild = -1;
-        lpBand->cyMinChild = -1;
-        lpBand->cyMaxChild = -1;
-        lpBand->cyChild    = -1;
-        lpBand->cyIntegral = -1;
-    }
-
-    if (lprbbi->fMask & RBBIM_SIZE)
-        lpBand->cx = lprbbi->cx;
-    else
-        lpBand->cx = -1;
-
-    if (lprbbi->fMask & RBBIM_BACKGROUND)
-        lpBand->hbmBack = lprbbi->hbmBack;
-
-    if (lprbbi->fMask & RBBIM_ID)
-        lpBand->wID = lprbbi->wID;
-
-    /* check for additional data */
-    if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
-        if (lprbbi->fMask & RBBIM_IDEALSIZE)
-            lpBand->cxIdeal = lprbbi->cxIdeal;
-
-        if (lprbbi->fMask & RBBIM_LPARAM)
-            lpBand->lParam = lprbbi->lParam;
-
-        if (lprbbi->fMask & RBBIM_HEADERSIZE)
-            lpBand->cxHeader = lprbbi->cxHeader;
-    }
-
-
-    REBAR_Layout (hwnd, NULL);
-    REBAR_ForceResize (hwnd);
-    REBAR_MoveChildWindows (hwnd);
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_InsertBandW (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
-    UINT uIndex = (UINT)wParam;
-    REBAR_BAND *lpBand;
-
-    if (infoPtr == NULL)
-        return FALSE;
-    if (lprbbi == NULL)
-        return FALSE;
-    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
-        return FALSE;
-
-//    TRACE (rebar, "insert band at %u!\n", uIndex);
-
-    if (infoPtr->uNumBands == 0) {
-        infoPtr->bands = (REBAR_BAND *)COMCTL32_Alloc (sizeof (REBAR_BAND));
-        uIndex = 0;
-    }
-    else {
-        REBAR_BAND *oldBands = infoPtr->bands;
-        infoPtr->bands =
-            (REBAR_BAND *)COMCTL32_Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
-        if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
-            uIndex = infoPtr->uNumBands;
-
-        /* pre insert copy */
-        if (uIndex > 0) {
-            memcpy (&infoPtr->bands[0], &oldBands[0],
-                    uIndex * sizeof(REBAR_BAND));
-        }
-
-        /* post copy */
-        if (uIndex < infoPtr->uNumBands - 1) {
-            memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
-                    (infoPtr->uNumBands - uIndex - 1) * sizeof(REBAR_BAND));
-        }
-
-        COMCTL32_Free (oldBands);
-    }
-
-    infoPtr->uNumBands++;
-
-//    TRACE (rebar, "index %u!\n", uIndex);
-
-    /* initialize band (infoPtr->bands[uIndex])*/
-    lpBand = &infoPtr->bands[uIndex];
-
-    if (lprbbi->fMask & RBBIM_STYLE)
-        lpBand->fStyle = lprbbi->fStyle;
-
-    if (lprbbi->fMask & RBBIM_COLORS) {
-        lpBand->clrFore = lprbbi->clrFore;
-        lpBand->clrBack = lprbbi->clrBack;
-    }
-    else {
-        lpBand->clrFore = CLR_NONE;
-        lpBand->clrBack = CLR_NONE;
-    }
-
-    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
-        INT len = lstrlenW (lprbbi->lpText);
-        if (len > 0) {
-            lpBand->lpText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
-            lstrcpyW (lpBand->lpText, lprbbi->lpText);
-        }
-    }
-
-    if (lprbbi->fMask & RBBIM_IMAGE)
-        lpBand->iImage = lprbbi->iImage;
-    else
-        lpBand->iImage = -1;
-
-    if (lprbbi->fMask & RBBIM_CHILD) {
-//      TRACE (rebar, "hwndChild = %x\n", lprbbi->hwndChild);
-        lpBand->hwndChild = lprbbi->hwndChild;
-        lpBand->hwndPrevParent =
-            SetParent (lpBand->hwndChild, hwnd);
-    }
-
-    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
-        lpBand->cxMinChild = lprbbi->cxMinChild;
-        lpBand->cyMinChild = lprbbi->cyMinChild;
-        lpBand->cyMaxChild = lprbbi->cyMaxChild;
-        lpBand->cyChild    = lprbbi->cyChild;
-        lpBand->cyIntegral = lprbbi->cyIntegral;
-    }
-    else {
-        lpBand->cxMinChild = -1;
-        lpBand->cyMinChild = -1;
-        lpBand->cyMaxChild = -1;
-        lpBand->cyChild    = -1;
-        lpBand->cyIntegral = -1;
-    }
-
-    if (lprbbi->fMask & RBBIM_SIZE)
-        lpBand->cx = lprbbi->cx;
-    else
-        lpBand->cx = -1;
-
-    if (lprbbi->fMask & RBBIM_BACKGROUND)
-        lpBand->hbmBack = lprbbi->hbmBack;
-
-    if (lprbbi->fMask & RBBIM_ID)
-        lpBand->wID = lprbbi->wID;
-
-    /* check for additional data */
-    if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
-        if (lprbbi->fMask & RBBIM_IDEALSIZE)
-            lpBand->cxIdeal = lprbbi->cxIdeal;
-
-        if (lprbbi->fMask & RBBIM_LPARAM)
-            lpBand->lParam = lprbbi->lParam;
-
-        if (lprbbi->fMask & RBBIM_HEADERSIZE)
-            lpBand->cxHeader = lprbbi->cxHeader;
-    }
-
-
-    REBAR_Layout (hwnd, NULL);
-    REBAR_ForceResize (hwnd);
-    REBAR_MoveChildWindows (hwnd);
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_MaximizeBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-/*    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
-
-//    FIXME (rebar, "(uBand = %u fIdeal = %s)\n",
-//         (UINT)wParam, lParam ? "TRUE" : "FALSE");
-
-
-    return 0;
-}
-
-
-static LRESULT
-REBAR_MinimizeBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-/*    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
-
-//    FIXME (rebar, "(uBand = %u)\n", (UINT)wParam);
-
-
-    return 0;
-}
-
-
-static LRESULT
-REBAR_MoveBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-/*    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
-
-//    FIXME (rebar, "(iFrom = %u iTof = %u)\n",
-//         (UINT)wParam, (UINT)lParam);
-
-
-    return FALSE;
-}
-
-
-static LRESULT
-REBAR_SetBandInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
-    REBAR_BAND *lpBand;
-
-    if (lprbbi == NULL)
-        return FALSE;
-    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
-        return FALSE;
-    if ((UINT)wParam >= infoPtr->uNumBands)
-        return FALSE;
-
-//    TRACE (rebar, "index %u\n", (UINT)wParam);
-
-    /* set band information */
-    lpBand = &infoPtr->bands[(UINT)wParam];
-
-    if (lprbbi->fMask & RBBIM_STYLE)
-        lpBand->fStyle = lprbbi->fStyle;
-
-    if (lprbbi->fMask & RBBIM_COLORS) {
-        lpBand->clrFore = lprbbi->clrFore;
-        lpBand->clrBack = lprbbi->clrBack;
-    }
-
-    if (lprbbi->fMask & RBBIM_TEXT) {
-        if (lpBand->lpText) {
-            COMCTL32_Free (lpBand->lpText);
-            lpBand->lpText = NULL;
-        }
-        if (lprbbi->lpText) {
-            INT len = lstrlenA (lprbbi->lpText);
-            lpBand->lpText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
-            lstrcpyAtoW (lpBand->lpText, lprbbi->lpText);
-        }
-    }
-
-    if (lprbbi->fMask & RBBIM_IMAGE)
-        lpBand->iImage = lprbbi->iImage;
-
-    if (lprbbi->fMask & RBBIM_CHILD) {
-        if (lprbbi->hwndChild) {
-            lpBand->hwndChild = lprbbi->hwndChild;
-            lpBand->hwndPrevParent =
-                SetParent (lpBand->hwndChild, hwnd);
-        }
-        else {
-//          TRACE (rebar, "child: 0x%x  prev parent: 0x%x\n",
-//                 lpBand->hwndChild, lpBand->hwndPrevParent);
-            lpBand->hwndChild = 0;
-            lpBand->hwndPrevParent = 0;
-        }
-    }
-
-    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
-        lpBand->cxMinChild = lprbbi->cxMinChild;
-        lpBand->cyMinChild = lprbbi->cyMinChild;
-        lpBand->cyMaxChild = lprbbi->cyMaxChild;
-        lpBand->cyChild    = lprbbi->cyChild;
-        lpBand->cyIntegral = lprbbi->cyIntegral;
-    }
-
-    if (lprbbi->fMask & RBBIM_SIZE)
-        lpBand->cx = lprbbi->cx;
-
-    if (lprbbi->fMask & RBBIM_BACKGROUND)
-        lpBand->hbmBack = lprbbi->hbmBack;
-
-    if (lprbbi->fMask & RBBIM_ID)
-        lpBand->wID = lprbbi->wID;
-
-    /* check for additional data */
-    if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
-        if (lprbbi->fMask & RBBIM_IDEALSIZE)
-            lpBand->cxIdeal = lprbbi->cxIdeal;
-
-        if (lprbbi->fMask & RBBIM_LPARAM)
-            lpBand->lParam = lprbbi->lParam;
-
-        if (lprbbi->fMask & RBBIM_HEADERSIZE)
-            lpBand->cxHeader = lprbbi->cxHeader;
-    }
-
-    REBAR_Layout (hwnd, NULL);
-    REBAR_ForceResize (hwnd);
-    REBAR_MoveChildWindows (hwnd);
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_SetBandInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
-    REBAR_BAND *lpBand;
-
-    if (lprbbi == NULL)
-        return FALSE;
-    if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
-        return FALSE;
-    if ((UINT)wParam >= infoPtr->uNumBands)
-        return FALSE;
-
-//    TRACE (rebar, "index %u\n", (UINT)wParam);
-
-    /* set band information */
-    lpBand = &infoPtr->bands[(UINT)wParam];
-
-    if (lprbbi->fMask & RBBIM_STYLE)
-        lpBand->fStyle = lprbbi->fStyle;
-
-    if (lprbbi->fMask & RBBIM_COLORS) {
-        lpBand->clrFore = lprbbi->clrFore;
-        lpBand->clrBack = lprbbi->clrBack;
-    }
-
-    if (lprbbi->fMask & RBBIM_TEXT) {
-        if (lpBand->lpText) {
-            COMCTL32_Free (lpBand->lpText);
-            lpBand->lpText = NULL;
-        }
-        if (lprbbi->lpText) {
-            INT len = lstrlenW (lprbbi->lpText);
-            lpBand->lpText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
-            lstrcpyW (lpBand->lpText, lprbbi->lpText);
-        }
-    }
-
-    if (lprbbi->fMask & RBBIM_IMAGE)
-        lpBand->iImage = lprbbi->iImage;
-
-    if (lprbbi->fMask & RBBIM_CHILD) {
-        if (lprbbi->hwndChild) {
-            lpBand->hwndChild = lprbbi->hwndChild;
-            lpBand->hwndPrevParent =
-                SetParent (lpBand->hwndChild, hwnd);
-        }
-        else {
-//          TRACE (rebar, "child: 0x%x  prev parent: 0x%x\n",
-//                 lpBand->hwndChild, lpBand->hwndPrevParent);
-            lpBand->hwndChild = 0;
-            lpBand->hwndPrevParent = 0;
-        }
-    }
-
-    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
-        lpBand->cxMinChild = lprbbi->cxMinChild;
-        lpBand->cyMinChild = lprbbi->cyMinChild;
-        lpBand->cyMaxChild = lprbbi->cyMaxChild;
-        lpBand->cyChild    = lprbbi->cyChild;
-        lpBand->cyIntegral = lprbbi->cyIntegral;
-    }
-
-    if (lprbbi->fMask & RBBIM_SIZE)
-        lpBand->cx = lprbbi->cx;
-
-    if (lprbbi->fMask & RBBIM_BACKGROUND)
-        lpBand->hbmBack = lprbbi->hbmBack;
-
-    if (lprbbi->fMask & RBBIM_ID)
-        lpBand->wID = lprbbi->wID;
-
-    /* check for additional data */
-    if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
-        if (lprbbi->fMask & RBBIM_IDEALSIZE)
-            lpBand->cxIdeal = lprbbi->cxIdeal;
-
-        if (lprbbi->fMask & RBBIM_LPARAM)
-            lpBand->lParam = lprbbi->lParam;
-
-        if (lprbbi->fMask & RBBIM_HEADERSIZE)
-            lpBand->cxHeader = lprbbi->cxHeader;
-    }
-
-    REBAR_Layout (hwnd, NULL);
-    REBAR_ForceResize (hwnd);
-    REBAR_MoveChildWindows (hwnd);
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_SetBarInfo (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    LPREBARINFO lpInfo = (LPREBARINFO)lParam;
-
-    if (lpInfo == NULL)
-        return FALSE;
-
-    if (lpInfo->cbSize < sizeof (REBARINFO))
-        return FALSE;
-
-//    TRACE (rebar, "setting bar info!\n");
-
-    if (lpInfo->fMask & RBIM_IMAGELIST) {
-        infoPtr->himl = lpInfo->himl;
-        if (infoPtr->himl) {
-            ImageList_GetIconSize (infoPtr->himl, &infoPtr->imageSize.cx,
-                                   &infoPtr->imageSize.cy);
-        }
-        else {
-            infoPtr->imageSize.cx = 0;
-            infoPtr->imageSize.cy = 0;
-        }
-    }
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    COLORREF clrTemp;
-
-    clrTemp = infoPtr->clrBk;
-    infoPtr->clrBk = (COLORREF)lParam;
-
-//    TRACE (rebar, "background color 0x%06lx!\n", infoPtr->clrBk);
-
-    return clrTemp;
-}
-
-
-/* << REBAR_SetColorScheme >> */
-/* << REBAR_SetPalette >> */
-
-
-static LRESULT
-REBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    HWND hwndTemp = infoPtr->header.hwndNotify;
-
-    infoPtr->header.hwndNotify = (HWND)wParam;
-
-    return (LRESULT)hwndTemp;
-}
-
-
-static LRESULT
-REBAR_SetTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    COLORREF clrTemp;
-
-    clrTemp = infoPtr->clrText;
-    infoPtr->clrText = (COLORREF)lParam;
-
-//    TRACE (rebar, "text color 0x%06lx!\n", infoPtr->clrText);
-
-    return clrTemp;
-}
-
-
-/* << REBAR_SetTooltips >> */
-
-
-static LRESULT
-REBAR_ShowBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    REBAR_BAND *lpBand;
-
-    if (((INT)wParam < 0) || ((INT)wParam > infoPtr->uNumBands))
-        return FALSE;
-
-    lpBand = &infoPtr->bands[(INT)wParam];
-
-    if ((BOOL)lParam) {
-//      TRACE (rebar, "show band %d\n", (INT)wParam);
-        lpBand->fStyle = lpBand->fStyle & ~RBBS_HIDDEN;
-        if (IsWindow (lpBand->hwndChild))
-            ShowWindow (lpBand->hwndChild, SW_SHOW);
-    }
-    else {
-//      TRACE (rebar, "hide band %d\n", (INT)wParam);
-        lpBand->fStyle = lpBand->fStyle | RBBS_HIDDEN;
-        if (IsWindow (lpBand->hwndChild))
-            ShowWindow (lpBand->hwndChild, SW_SHOW);
-    }
-
-    REBAR_Layout (hwnd, NULL);
-    REBAR_ForceResize (hwnd);
-    REBAR_MoveChildWindows (hwnd);
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_SizeToRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    LPRECT lpRect = (LPRECT)lParam;
-
-    if (lpRect == NULL)
-        return FALSE;
-
-//    FIXME (rebar, "layout change not implemented!\n");
-//    FIXME (rebar, "[%d %d %d %d]\n",
-//         lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
-
-#if 0
-    SetWindowPos (hwnd, 0, lpRect->left, lpRect->top,
-                    lpRect->right - lpRect->left, lpRect->bottom - lpRect->top,
-                    SWP_NOZORDER);
-#endif
-
-    infoPtr->calcSize.cx = lpRect->right - lpRect->left;
-    infoPtr->calcSize.cy = lpRect->bottom - lpRect->top;
-
-    REBAR_ForceResize (hwnd);
-    return TRUE;
-}
-
-
-
-static LRESULT
-REBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr;
-
-    /* allocate memory for info structure */
-    infoPtr = (REBAR_INFO*)initControl(hwnd,sizeof(REBAR_INFO));
-
-    /* initialize info structure */
-    infoPtr->clrBk = CLR_NONE;
-    infoPtr->clrText = RGB(0, 0, 0);
-
-    infoPtr->bAutoResize = FALSE;
-    infoPtr->hcurArrow = LoadCursorA (0, IDC_ARROWA);
-    infoPtr->hcurHorz  = LoadCursorA (0, IDC_SIZEWEA);
-    infoPtr->hcurVert  = LoadCursorA (0, IDC_SIZENSA);
-    infoPtr->hcurDrag  = LoadCursorA (0, IDC_SIZEA);
-
-//    if (GetWindowLongA (hwnd, GWL_STYLE) & RBS_AUTOSIZE)
-//      FIXME (rebar, "style RBS_AUTOSIZE set!\n");
-
-    return 0;
-}
-
-
-static LRESULT
-REBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    REBAR_BAND *lpBand;
-    INT i;
-
-
-    /* free rebar bands */
-    if ((infoPtr->uNumBands > 0) && infoPtr->bands) {
-        /* clean up each band */
-        for (i = 0; i < infoPtr->uNumBands; i++) {
-            lpBand = &infoPtr->bands[i];
-
-            /* delete text strings */
-            if (lpBand->lpText) {
-                COMCTL32_Free (lpBand->lpText);
-                lpBand->lpText = NULL;
-            }
-            /* destroy child window */
-            DestroyWindow (lpBand->hwndChild);
-        }
-
-        /* free band array */
-        COMCTL32_Free (infoPtr->bands);
-        infoPtr->bands = NULL;
-    }
-
-
-
-
-    DeleteObject (infoPtr->hcurArrow);
-    DeleteObject (infoPtr->hcurHorz);
-    DeleteObject (infoPtr->hcurVert);
-    DeleteObject (infoPtr->hcurDrag);
-
-
-
-
-    /* free rebar info data */
-    doneControl(hwnd);
-
-    return 0;
-}
-
-
-static LRESULT
-REBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-
-    return (LRESULT)infoPtr->hFont;
-}
-
-
-#if 0
-static LRESULT
-REBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-
-    return 0;
-}
-#endif
-
-
-static LRESULT
-REBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    if (GetWindowLongA (hwnd, GWL_STYLE) & WS_BORDER) {
-        ((LPRECT)lParam)->left   += GetSystemMetrics(SM_CXEDGE);
-        ((LPRECT)lParam)->top    += GetSystemMetrics(SM_CYEDGE);
-        ((LPRECT)lParam)->right  -= GetSystemMetrics(SM_CXEDGE);
-        ((LPRECT)lParam)->bottom -= GetSystemMetrics(SM_CYEDGE);
-    }
-
-    return 0;
-}
-
-
-static LRESULT
-REBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
-    RECT rcWindow;
-    HDC hdc;
-
-    if (dwStyle & WS_MINIMIZE)
-        return 0; /* Nothing to do */
-
-    DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
-
-    if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW )))
-        return 0;
-
-    if (dwStyle & WS_BORDER) {
-        GetWindowRect (hwnd, &rcWindow);
-        OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
-        DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT);
-    }
-
-    ReleaseDC( hwnd, hdc );
-
-    return 0;
-}
-
-
-static LRESULT
-REBAR_Paint (HWND hwnd, WPARAM wParam)
-{
-    HDC hdc;
-    PAINTSTRUCT ps;
-
-    hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
-    REBAR_Refresh (hwnd, hdc);
-    if (!wParam)
-        EndPaint (hwnd, &ps);
-    return 0;
-}
-
-
-static LRESULT
-REBAR_SetCursor (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
-    POINT pt;
-    UINT  flags;
-
-//    TRACE (rebar, "code=0x%X  id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
-
-    GetCursorPos (&pt);
-    ScreenToClient (hwnd, &pt);
-
-    REBAR_InternalHitTest (hwnd, &pt, &flags, NULL);
-
-    if (flags == RBHT_GRABBER) {
-        if ((dwStyle & CCS_VERT) &&
-            !(dwStyle & RBS_VERTICALGRIPPER))
-            SetCursor (infoPtr->hcurVert);
-        else
-            SetCursor (infoPtr->hcurHorz);
-    }
-    else if (flags != RBHT_CLIENT)
-        SetCursor (infoPtr->hcurArrow);
-    //CB: else not handled -> cursor not changed
-
-    return TRUE;
-}
-
-
-static LRESULT
-REBAR_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-
-    /* TEXTMETRIC32A tm; */
-    HFONT hFont /*, hOldFont */;
-    /* HDC32 hdc; */
-
-    infoPtr->hFont = (HFONT)wParam;
-
-    hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
-/*
-    hdc = GetDC32 (0);
-    hOldFont = SelectObject32 (hdc, hFont);
-    GetTextMetrics32A (hdc, &tm);
-    infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
-    SelectObject32 (hdc, hOldFont);
-    ReleaseDC32 (0, hdc);
-*/
-    if (lParam) {
-/*
-        REBAR_Layout (hwnd);
-        hdc = GetDC32 (hwnd);
-        REBAR_Refresh (hwnd, hdc);
-        ReleaseDC32 (hwnd, hdc);
-*/
-    }
-
-    return 0;
-}
-
-static LRESULT
-REBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
-    /* DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); */
-    RECT rcParent;
-    /* INT32 x, y, cx, cy; */
-
-    /* auto resize deadlock check */
-    if (infoPtr->bAutoResize) {
-        infoPtr->bAutoResize = FALSE;
-        return 0;
-    }
-
-//    TRACE (rebar, "sizing rebar!\n");
-
-    /* get parent rectangle */
-    GetClientRect (GetParent (hwnd), &rcParent);
-/*
-    REBAR_Layout (hwnd, &rcParent);
-
-    if (dwStyle & CCS_VERT) {
-        if (dwStyle & CCS_LEFT == CCS_LEFT) {
-            x = rcParent.left;
-            y = rcParent.top;
-            cx = infoPtr->calcSize.cx;
-            cy = infoPtr->calcSize.cy;
-        }
-        else {
-            x = rcParent.right - infoPtr->calcSize.cx;
-            y = rcParent.top;
-            cx = infoPtr->calcSize.cx;
-            cy = infoPtr->calcSize.cy;
-        }
-    }
-    else {
-        if (dwStyle & CCS_TOP) {
-            x = rcParent.left;
-            y = rcParent.top;
-            cx = infoPtr->calcSize.cx;
-            cy = infoPtr->calcSize.cy;
-        }
-        else {
-            x = rcParent.left;
-            y = rcParent.bottom - infoPtr->calcSize.cy;
-            cx = infoPtr->calcSize.cx;
-            cy = infoPtr->calcSize.cy;
-        }
-    }
-
-    SetWindowPos32 (hwnd, 0, x, y, cx, cy,
-                    SWP_NOZORDER | SWP_SHOWWINDOW);
-*/
-    REBAR_Layout (hwnd, NULL);
-    REBAR_ForceResize (hwnd);
-    REBAR_MoveChildWindows (hwnd);
-
-    return 0;
-}
-
-
-static LRESULT WINAPI
-REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-    switch (uMsg)
-    {
-/*      case RB_BEGINDRAG: */
-
-        case RB_DELETEBAND:
-            return REBAR_DeleteBand (hwnd, wParam, lParam);
-
-/*      case RB_DRAGMOVE: */
-/*      case RB_ENDDRAG: */
-
-        case RB_GETBANDBORDERS:
-            return REBAR_GetBandBorders (hwnd, wParam, lParam);
-
-        case RB_GETBANDCOUNT:
-            return REBAR_GetBandCount (hwnd);
-
-/*      case RB_GETBANDINFO32:  */ /* outdated, just for compatibility */
-
-        case RB_GETBANDINFOA:
-            return REBAR_GetBandInfoA (hwnd, wParam, lParam);
-
-        case RB_GETBANDINFOW:
-            return REBAR_GetBandInfoW (hwnd, wParam, lParam);
-
-        case RB_GETBARHEIGHT:
-            return REBAR_GetBarHeight (hwnd, wParam, lParam);
-
-        case RB_GETBARINFO:
-            return REBAR_GetBarInfo (hwnd, wParam, lParam);
-
-        case RB_GETBKCOLOR:
-            return REBAR_GetBkColor (hwnd);
-
-/*      case RB_GETCOLORSCHEME: */
-/*      case RB_GETDROPTARGET: */
-
-        case RB_GETPALETTE:
-            return REBAR_GetPalette (hwnd, wParam, lParam);
-
-        case RB_GETRECT:
-            return REBAR_GetRect (hwnd, wParam, lParam);
-
-        case RB_GETROWCOUNT:
-            return REBAR_GetRowCount (hwnd);
-
-        case RB_GETROWHEIGHT:
-            return REBAR_GetRowHeight (hwnd, wParam, lParam);
-
-        case RB_GETTEXTCOLOR:
-            return REBAR_GetTextColor (hwnd);
-
-        case RB_GETTOOLTIPS:
-            return REBAR_GetToolTips (hwnd);
-
-        case RB_HITTEST:
-            return REBAR_HitTest (hwnd, wParam, lParam);
-
-        case RB_IDTOINDEX:
-            return REBAR_IdToIndex (hwnd, wParam, lParam);
-
-        case RB_INSERTBANDA:
-            return REBAR_InsertBandA (hwnd, wParam, lParam);
-
-        case RB_INSERTBANDW:
-            return REBAR_InsertBandW (hwnd, wParam, lParam);
-
-        case RB_MAXIMIZEBAND:
-            return REBAR_MaximizeBand (hwnd, wParam, lParam);
-
-        case RB_MINIMIZEBAND:
-            return REBAR_MinimizeBand (hwnd, wParam, lParam);
-
-        case RB_MOVEBAND:
-            return REBAR_MoveBand (hwnd, wParam, lParam);
-
-        case RB_SETBANDINFOA:
-            return REBAR_SetBandInfoA (hwnd, wParam, lParam);
-
-        case RB_SETBANDINFOW:
-            return REBAR_SetBandInfoW (hwnd, wParam, lParam);
-
-        case RB_SETBARINFO:
-            return REBAR_SetBarInfo (hwnd, wParam, lParam);
-
-        case RB_SETBKCOLOR:
-            return REBAR_SetBkColor (hwnd, wParam, lParam);
-
-/*      case RB_SETCOLORSCHEME: */
-/*      case RB_SETPALETTE: */
-/*          return REBAR_GetPalette (hwnd, wParam, lParam); */
-
-        case RB_SETPARENT:
-            return REBAR_SetParent (hwnd, wParam, lParam);
-
-        case RB_SETTEXTCOLOR:
-            return REBAR_SetTextColor (hwnd, wParam, lParam);
-
-/*      case RB_SETTOOLTIPS: */
-
-        case RB_SHOWBAND:
-            return REBAR_ShowBand (hwnd, wParam, lParam);
-
-        case RB_SIZETORECT:
-            return REBAR_SizeToRect (hwnd, wParam, lParam);
-
-
-        case WM_COMMAND:
-            return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
-
-        case WM_CREATE:
-            return REBAR_Create (hwnd, wParam, lParam);
-
-        case WM_DESTROY:
-            return REBAR_Destroy (hwnd, wParam, lParam);
-
-        case WM_GETFONT:
-            return REBAR_GetFont (hwnd, wParam, lParam);
-
-/*      case WM_MOUSEMOVE: */
-/*          return REBAR_MouseMove (hwnd, wParam, lParam); */
-
-        case WM_NCCALCSIZE:
-            return REBAR_NCCalcSize (hwnd, wParam, lParam);
-
-        case WM_NCPAINT:
-            return REBAR_NCPaint (hwnd, wParam, lParam);
-
-        case WM_NOTIFY:
-            return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
-
-        case WM_PAINT:
-            return REBAR_Paint (hwnd, wParam);
-
-        case WM_SETCURSOR:
-            return REBAR_SetCursor (hwnd, wParam, lParam);
-
-        case WM_SETFONT:
-            return REBAR_SetFont (hwnd, wParam, lParam);
-
-        case WM_SIZE:
-            return REBAR_Size (hwnd, wParam, lParam);
-
-/*      case WM_TIMER: */
-
-/*      case WM_WININICHANGE: */
-
-        default:
-//          if (uMsg >= WM_USER)
-//              ERR (rebar, "unknown msg %04x wp=%08x lp=%08lx\n",
-//                   uMsg, wParam, lParam);
-            return defComCtl32ProcA (hwnd, uMsg, wParam, lParam);
-    }
-    return 0;
-}
-
-
-VOID
-REBAR_Register (VOID)
-{
-    WNDCLASSA wndClass;
-
-    ZeroMemory (&wndClass, sizeof(WNDCLASSA));
-    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
-    wndClass.lpfnWndProc   = (WNDPROC)REBAR_WindowProc;
-    wndClass.cbClsExtra    = 0;
-    wndClass.cbWndExtra    = sizeof(REBAR_INFO *);
-    wndClass.hCursor       = 0;
-    wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
-    wndClass.lpszClassName = REBARCLASSNAMEA;
-
-    RegisterClassA (&wndClass);
-}
-
-
-VOID
-REBAR_Unregister (VOID)
-{
-     UnregisterClassA (REBARCLASSNAMEA, (HINSTANCE)NULL);
-}
-
Index: trunk/src/comctl32/status.c
===================================================================
--- trunk/src/comctl32/status.c	(revision 5630)
+++ trunk/src/comctl32/status.c	(revision 5630)
@@ -0,0 +1,1409 @@
+/*
+ * Interface code to StatusWindow widget/control
+ *
+ * Copyright 1996 Bruce Milner
+ * Copyright 1998, 1999 Eric Kohl
+ */
+/*
+ * FIXME/TODO
+ * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
+ * 2) Tooltip support (almost done).
+ * 3) where else should we use infoPtr->hwndParent instead of GetParent() ?
+ * 4) send WM_QUERYFORMAT
+ */
+
+#include <string.h>
+#include "winbase.h"
+#include "wine/unicode.h"
+#include "commctrl.h"
+#include "debugtools.h"
+#ifdef __WIN32OS2__
+#include "ccbase.h"
+#endif
+
+DEFAULT_DEBUG_CHANNEL(statusbar);
+
+typedef struct
+{
+    INT	x;
+    INT	style;
+    RECT	bound;
+    LPWSTR	text;
+    HICON     hIcon;
+} STATUSWINDOWPART;
+
+typedef struct
+{
+#ifdef __WIN32OS2__
+    COMCTL32_HEADER   header;
+#endif
+    HWND              hwndParent;
+    WORD              numParts;
+    WORD              textHeight;
+    UINT              height;
+    BOOL              simple;
+    HWND              hwndToolTip;
+    HFONT             hFont;
+    HFONT             hDefaultFont;
+    COLORREF            clrBk;     /* background color */
+    BOOL              bUnicode;  /* unicode flag */
+    STATUSWINDOWPART	part0;	   /* simple window */
+    STATUSWINDOWPART   *parts;
+} STATUSWINDOWINFO;
+
+/*
+ * Run tests using Waite Group Windows95 API Bible Vol. 1&2
+ * The second cdrom contains executables drawstat.exe, gettext.exe,
+ * simple.exe, getparts.exe, setparts.exe, statwnd.exe
+ */
+
+
+#define _MAX(a,b) (((a)>(b))?(a):(b))
+#define _MIN(a,b) (((a)>(b))?(b):(a))
+
+#define HORZ_BORDER 0
+#define VERT_BORDER 2
+#define HORZ_GAP    2
+
+#define STATUSBAR_GetInfoPtr(hwnd) ((STATUSWINDOWINFO *)GetWindowLongA (hwnd, 0))
+
+/* prototype */
+static void
+STATUSBAR_SetPartBounds (STATUSWINDOWINFO *infoPtr, HWND hwnd);
+
+static void
+STATUSBAR_DrawSizeGrip (HDC hdc, LPRECT lpRect)
+{
+    HPEN hOldPen;
+    POINT pt;
+    INT i;
+
+    TRACE("draw size grip %d,%d - %d,%d\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
+    pt.x = lpRect->right - 1;
+    pt.y = lpRect->bottom - 1;
+
+    hOldPen = SelectObject (hdc, GetSysColorPen (COLOR_3DFACE));
+    MoveToEx (hdc, pt.x - 12, pt.y, NULL);
+    LineTo (hdc, pt.x, pt.y);
+    LineTo (hdc, pt.x, pt.y - 12);
+
+    pt.x--;
+    pt.y--;
+
+    SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
+    for (i = 1; i < 11; i += 4) {
+	MoveToEx (hdc, pt.x - i, pt.y, NULL);
+	LineTo (hdc, pt.x, pt.y - i);
+
+	MoveToEx (hdc, pt.x - i-1, pt.y, NULL);
+	LineTo (hdc, pt.x, pt.y - i-1);
+    }
+
+    SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
+    for (i = 3; i < 13; i += 4) {
+	MoveToEx (hdc, pt.x - i, pt.y, NULL);
+	LineTo (hdc, pt.x, pt.y - i);
+    }
+
+    SelectObject (hdc, hOldPen);
+}
+
+
+static void 
+STATUSBAR_DrawPart (HDC hdc, STATUSWINDOWPART *part)
+{
+    RECT r = part->bound;
+    UINT border = BDR_SUNKENOUTER;
+
+    TRACE("part bound %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom);
+    if (part->style & SBT_POPOUT)
+      border = BDR_RAISEDOUTER;
+    else if (part->style & SBT_NOBORDERS)
+      border = 0;
+
+    DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST);
+
+    /* draw the icon */
+    if (part->hIcon) {
+	INT cy = r.bottom - r.top;
+
+	r.left += 2;
+	DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
+	r.left += cy;
+    }
+
+    /* now draw text */
+    if (part->text) {
+      int oldbkmode = SetBkMode(hdc, TRANSPARENT);
+      LPWSTR p = (LPWSTR)part->text;
+      UINT align = DT_LEFT;
+      if (*p == L'\t') {
+	p++;
+	align = DT_CENTER;
+
+	if (*p == L'\t') {
+	  p++;
+	  align = DT_RIGHT;
+	}
+      }
+      r.left += 3;
+      TRACE("%s at %d,%d - %d,%d\n", debugstr_w(p), r.left, r.top, r.right, r.bottom);
+      DrawTextW (hdc, p, -1, &r, align|DT_VCENTER|DT_SINGLELINE);
+      if (oldbkmode != TRANSPARENT)
+	SetBkMode(hdc, oldbkmode);
+    }
+}
+
+
+static VOID
+STATUSBAR_RefreshPart (STATUSWINDOWINFO *infoPtr, HWND hwnd, STATUSWINDOWPART *part, HDC hdc, int itemID)
+{
+    HBRUSH hbrBk;
+    HFONT  hOldFont;
+
+    TRACE("item %d\n", itemID);
+    if (!IsWindowVisible (hwnd))
+        return;
+
+    if (part->bound.right < part->bound.left) return;
+
+    if (infoPtr->clrBk != CLR_DEFAULT)
+	hbrBk = CreateSolidBrush (infoPtr->clrBk);
+    else
+	hbrBk = GetSysColorBrush (COLOR_3DFACE);
+    FillRect(hdc, &part->bound, hbrBk);
+
+    hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
+
+    if (part->style & SBT_OWNERDRAW) {
+	DRAWITEMSTRUCT dis;
+
+	dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
+	dis.itemID = itemID;
+	dis.hwndItem = hwnd;
+	dis.hDC = hdc;
+	dis.rcItem = part->bound;
+	dis.itemData = (INT)part->text;
+	SendMessageA (GetParent (hwnd), WM_DRAWITEM,
+		(WPARAM)dis.CtlID, (LPARAM)&dis);
+    } else
+	STATUSBAR_DrawPart (hdc, part);
+
+    SelectObject (hdc, hOldFont);
+
+    if (infoPtr->clrBk != CLR_DEFAULT)
+	DeleteObject (hbrBk);
+
+    if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
+	RECT rect;
+
+	GetClientRect (hwnd, &rect);
+	STATUSBAR_DrawSizeGrip (hdc, &rect);
+    }
+}
+
+
+static BOOL
+STATUSBAR_Refresh (STATUSWINDOWINFO *infoPtr, HWND hwnd, HDC hdc)
+{
+    int      i;
+    RECT   rect;
+    HBRUSH hbrBk;
+    HFONT  hOldFont;
+
+    TRACE("\n");
+    if (!IsWindowVisible(hwnd))
+        return (TRUE);
+
+    STATUSBAR_SetPartBounds(infoPtr, hwnd);
+
+    GetClientRect (hwnd, &rect);
+
+    if (infoPtr->clrBk != CLR_DEFAULT)
+	hbrBk = CreateSolidBrush (infoPtr->clrBk);
+    else
+	hbrBk = GetSysColorBrush (COLOR_3DFACE);
+    FillRect(hdc, &rect, hbrBk);
+
+    hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
+
+    if (infoPtr->simple) {
+	STATUSBAR_RefreshPart (infoPtr, hwnd, &infoPtr->part0, hdc, 0);
+    } else {
+	for (i = 0; i < infoPtr->numParts; i++) {
+	    if (infoPtr->parts[i].style & SBT_OWNERDRAW) {
+		DRAWITEMSTRUCT dis;
+
+		dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
+		dis.itemID = i;
+		dis.hwndItem = hwnd;
+		dis.hDC = hdc;
+		dis.rcItem = infoPtr->parts[i].bound;
+		dis.itemData = (INT)infoPtr->parts[i].text;
+		SendMessageA (GetParent (hwnd), WM_DRAWITEM,
+			(WPARAM)dis.CtlID, (LPARAM)&dis);
+	    } else
+		STATUSBAR_RefreshPart (infoPtr, hwnd, &infoPtr->parts[i], hdc, i);
+	}
+    }
+
+    SelectObject (hdc, hOldFont);
+
+    if (infoPtr->clrBk != CLR_DEFAULT)
+	DeleteObject (hbrBk);
+
+    if (GetWindowLongA(hwnd, GWL_STYLE) & SBARS_SIZEGRIP)
+	STATUSBAR_DrawSizeGrip (hdc, &rect);
+
+    return TRUE;
+}
+
+
+static void
+STATUSBAR_SetPartBounds (STATUSWINDOWINFO *infoPtr, HWND hwnd)
+{
+    STATUSWINDOWPART *part;
+    RECT rect, *r;
+    int	i;
+
+    /* get our window size */
+    GetClientRect (hwnd, &rect);
+    TRACE("client wnd size is %d,%d - %d,%d\n", rect.left, rect.top, rect.right, rect.bottom);
+
+    rect.top += VERT_BORDER;
+
+    /* set bounds for simple rectangle */
+    infoPtr->part0.bound = rect;
+
+    /* set bounds for non-simple rectangles */
+    for (i = 0; i < infoPtr->numParts; i++) {
+	part = &infoPtr->parts[i];
+	r = &infoPtr->parts[i].bound;
+	r->top = rect.top;
+	r->bottom = rect.bottom;
+	if (i == 0)
+	    r->left = 0;
+	else
+	    r->left = infoPtr->parts[i-1].bound.right + HORZ_GAP;
+	if (part->x == -1)
+	    r->right = rect.right;
+	else
+	    r->right = part->x;
+
+	if (infoPtr->hwndToolTip) {
+	    TTTOOLINFOA ti;
+
+	    ti.cbSize = sizeof(TTTOOLINFOA);
+	    ti.hwnd = hwnd;
+	    ti.uId = i;
+	    ti.rect = *r;
+	    SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
+			    0, (LPARAM)&ti);
+	}
+    }
+}
+
+
+static VOID
+STATUSBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
+		      WPARAM wParam, LPARAM lParam)
+{
+    MSG msg;
+
+    msg.hwnd = hwndMsg;
+    msg.message = uMsg;
+    msg.wParam = wParam;
+    msg.lParam = lParam;
+    msg.time = GetMessageTime ();
+    msg.pt.x = LOWORD(GetMessagePos ());
+    msg.pt.y = HIWORD(GetMessagePos ());
+
+    SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
+}
+
+
+inline static LRESULT
+STATUSBAR_GetBorders (LPARAM lParam)
+{
+    LPINT out = (LPINT) lParam;
+
+    TRACE("\n");
+    out[0] = HORZ_BORDER; /* horizontal border width */
+    out[1] = VERT_BORDER; /* vertical border width */
+    out[2] = HORZ_GAP; /* width of border between rectangles */
+
+    return TRUE;
+}
+
+
+static LRESULT
+STATUSBAR_GetIcon (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
+{
+    INT nPart;
+
+    nPart = (INT)wParam & 0x00ff;
+    TRACE("%d\n", nPart);
+    if ((nPart < -1) || (nPart >= infoPtr->numParts))
+	return 0;
+
+    if (nPart == -1)
+        return (infoPtr->part0.hIcon);
+    else
+        return (infoPtr->parts[nPart].hIcon);
+}
+
+
+static LRESULT
+STATUSBAR_GetParts (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    LPINT parts;
+    INT   num_parts;
+    INT   i;
+
+    num_parts = (INT) wParam;
+    TRACE("(%d)\n", num_parts);
+    parts = (LPINT) lParam;
+    if (parts) {
+	for (i = 0; i < num_parts; i++) {
+	    parts[i] = infoPtr->parts[i].x;
+	}
+    }
+    return (infoPtr->numParts);
+}
+
+
+static LRESULT
+STATUSBAR_GetRect (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    int	nPart;
+    LPRECT  rect;
+
+    nPart = ((INT) wParam) & 0x00ff;
+    TRACE("part %d\n", nPart);
+    rect = (LPRECT) lParam;
+    if (infoPtr->simple)
+	*rect = infoPtr->part0.bound;
+    else
+	*rect = infoPtr->parts[nPart].bound;
+    return TRUE;
+}
+
+
+static LRESULT
+STATUSBAR_GetTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    STATUSWINDOWPART *part;
+    INT   nPart;
+    LRESULT result;
+
+    nPart = ((INT) wParam) & 0x00ff;
+    TRACE("part %d\n", nPart);
+    if (infoPtr->simple)
+	part = &infoPtr->part0;
+    else
+	part = &infoPtr->parts[nPart];
+
+    if (part->style & SBT_OWNERDRAW)
+	result = (LRESULT)part->text;
+    else {
+        DWORD len = part->text ? WideCharToMultiByte( CP_ACP, 0, part->text, -1,
+                                                      NULL, 0, NULL, NULL ) - 1 : 0;
+        result = MAKELONG( len, part->style );
+        if (lParam && len)
+            WideCharToMultiByte( CP_ACP, 0, part->text, -1, (LPSTR)lParam, len+1, NULL, NULL );
+    }
+    return result;
+}
+
+
+static LRESULT
+STATUSBAR_GetTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    STATUSWINDOWPART *part;
+    INT   nPart;
+    LRESULT result;
+
+    nPart = ((INT)wParam) & 0x00ff;
+    TRACE("part %d\n", nPart);
+    if (infoPtr->simple)
+	part = &infoPtr->part0;
+    else
+	part = &infoPtr->parts[nPart];
+
+    if (part->style & SBT_OWNERDRAW)
+	result = (LRESULT)part->text;
+    else {
+	result = part->text ? strlenW (part->text) : 0;
+	result |= (part->style << 16);
+	if (part->text && lParam)
+	    strcpyW ((LPWSTR)lParam, part->text);
+    }
+    return result;
+}
+
+
+static LRESULT
+STATUSBAR_GetTextLength (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
+{
+    STATUSWINDOWPART *part;
+    INT nPart;
+    DWORD result;
+
+    nPart = ((INT) wParam) & 0x00ff;
+
+    TRACE("part %d\n", nPart);
+    if (infoPtr->simple)
+	part = &infoPtr->part0;
+    else
+	part = &infoPtr->parts[nPart];
+
+    if (part->text)
+	result = strlenW(part->text);
+    else
+	result = 0;
+
+    result |= (part->style << 16);
+    return result;
+}
+
+
+static LRESULT
+STATUSBAR_GetTipTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    LPSTR tip = (LPSTR)lParam;
+
+    if (tip) {
+        CHAR buf[INFOTIPSIZE];
+        buf[0]='\0';
+
+        if (infoPtr->hwndToolTip) {
+            TTTOOLINFOA ti;
+            ti.cbSize = sizeof(TTTOOLINFOA);
+            ti.hwnd = hwnd;
+            ti.uId = LOWORD(wParam);
+            ti.lpszText = buf;
+            SendMessageA(infoPtr->hwndToolTip, TTM_GETTEXTA, 0, (LPARAM)&ti);
+        }
+        lstrcpynA(tip, buf, HIWORD(wParam));
+    }
+    return 0;
+}
+
+
+static LRESULT
+STATUSBAR_GetTipTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    LPWSTR tip = (LPWSTR)lParam;
+
+    TRACE("\n");
+    if (tip) {
+        WCHAR buf[INFOTIPSIZE];
+        buf[0]=0;
+
+	if (infoPtr->hwndToolTip) {
+	    TTTOOLINFOW ti;
+	    ti.cbSize = sizeof(TTTOOLINFOW);
+	    ti.hwnd = hwnd;
+	    ti.uId = LOWORD(wParam);
+            ti.lpszText = buf;
+	    SendMessageW(infoPtr->hwndToolTip, TTM_GETTEXTW, 0, (LPARAM)&ti);
+	}
+	lstrcpynW(tip, buf, HIWORD(wParam));
+    }
+
+    return 0;
+}
+
+
+inline static LRESULT
+STATUSBAR_GetUnicodeFormat (STATUSWINDOWINFO *infoPtr, HWND hwnd)
+{
+    return infoPtr->bUnicode;
+}
+
+
+inline static LRESULT
+STATUSBAR_IsSimple (STATUSWINDOWINFO *infoPtr, HWND hwnd)
+{
+    return infoPtr->simple;
+}
+
+
+static LRESULT
+STATUSBAR_SetBkColor (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    COLORREF oldBkColor;
+
+    oldBkColor = infoPtr->clrBk;
+    infoPtr->clrBk = (COLORREF)lParam;
+    InvalidateRect(hwnd, NULL, FALSE);
+
+    TRACE("CREF: %08lx -> %08lx\n", oldBkColor, infoPtr->clrBk);
+    return oldBkColor;
+}
+
+
+static LRESULT
+STATUSBAR_SetIcon (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    INT nPart = (INT)wParam & 0x00ff;
+
+    if ((nPart < -1) || (nPart >= infoPtr->numParts))
+	return FALSE;
+
+    TRACE("setting part %d, icon %lx\n",nPart,lParam);
+
+    if (nPart == -1) {
+	if (infoPtr->part0.hIcon == (HICON)lParam) /* same as - no redraw */
+	    return TRUE;
+	infoPtr->part0.hIcon = (HICON)lParam;
+	if (infoPtr->simple)
+            InvalidateRect(hwnd, &infoPtr->part0.bound, FALSE);
+    } else {
+	if (infoPtr->parts[nPart].hIcon == (HICON)lParam) /* same as - no redraw */
+	    return TRUE;
+
+	infoPtr->parts[nPart].hIcon = (HICON)lParam;
+	if (!(infoPtr->simple))
+            InvalidateRect(hwnd, &infoPtr->parts[nPart].bound, FALSE);
+    }
+    return TRUE;
+}
+
+
+static LRESULT
+STATUSBAR_SetMinHeight (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+
+    TRACE("\n");
+    if (IsWindowVisible (hwnd)) {
+	HWND parent = GetParent (hwnd);
+	INT  width, x, y;
+	RECT parent_rect;
+
+	GetClientRect (parent, &parent_rect);
+	infoPtr->height = (INT)wParam + VERT_BORDER;
+	width = parent_rect.right - parent_rect.left;
+	x = parent_rect.left;
+	y = parent_rect.bottom - infoPtr->height;
+	MoveWindow (hwnd, parent_rect.left,
+		      parent_rect.bottom - infoPtr->height,
+		      width, infoPtr->height, TRUE);
+	STATUSBAR_SetPartBounds (infoPtr, hwnd);
+    }
+
+    return TRUE;
+}
+
+
+static LRESULT
+STATUSBAR_SetParts (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    STATUSWINDOWPART *tmp;
+    LPINT parts;
+    int	i;
+    int	oldNumParts;
+
+    TRACE("(%d,%p)\n",wParam,(LPVOID)lParam);
+
+    /* FIXME: should return FALSE sometimes (maybe when wParam == 0 ?) */
+    if (infoPtr->simple)
+	infoPtr->simple = FALSE;
+
+    oldNumParts = infoPtr->numParts;
+    infoPtr->numParts = (INT) wParam;
+    parts = (LPINT) lParam;
+    if (oldNumParts > infoPtr->numParts) {
+	for (i = infoPtr->numParts ; i < oldNumParts; i++) {
+	    if (infoPtr->parts[i].text && !(infoPtr->parts[i].style & SBT_OWNERDRAW))
+		COMCTL32_Free (infoPtr->parts[i].text);
+	}
+    }
+    if (oldNumParts < infoPtr->numParts) {
+	tmp = COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * infoPtr->numParts);
+	for (i = 0; i < oldNumParts; i++) {
+	    tmp[i] = infoPtr->parts[i];
+	}
+	if (infoPtr->parts)
+	    COMCTL32_Free (infoPtr->parts);
+	infoPtr->parts = tmp;
+    }
+    if (oldNumParts == infoPtr->numParts) {
+	for (i=0;i<oldNumParts;i++)
+	    if (infoPtr->parts[i].x != parts[i])
+		break;
+	if (i==oldNumParts) /* Unchanged? no need to redraw! */
+	    return TRUE;
+    }
+    
+    for (i = 0; i < infoPtr->numParts; i++)
+	infoPtr->parts[i].x = parts[i];
+
+    if (infoPtr->hwndToolTip) {
+	INT nTipCount =
+	    SendMessageA (infoPtr->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0);
+
+	if (nTipCount < infoPtr->numParts) {
+	    /* add tools */
+	    TTTOOLINFOA ti;
+	    INT i;
+
+	    ZeroMemory (&ti, sizeof(TTTOOLINFOA));
+	    ti.cbSize = sizeof(TTTOOLINFOA);
+	    ti.hwnd = hwnd;
+	    for (i = nTipCount; i < infoPtr->numParts; i++) {
+		TRACE("add tool %d\n", i);
+		ti.uId = i;
+		SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
+				0, (LPARAM)&ti);
+	    }
+	}
+	else if (nTipCount > infoPtr->numParts) {
+	    /* delete tools */
+	    INT i;
+
+	    for (i = nTipCount - 1; i >= infoPtr->numParts; i--) {
+		FIXME("delete tool %d\n", i);
+	    }
+	}
+    }
+    STATUSBAR_SetPartBounds (infoPtr, hwnd);
+    InvalidateRect(hwnd, NULL, FALSE);
+    return TRUE;
+}
+
+
+static LRESULT
+STATUSBAR_SetTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    STATUSWINDOWPART *part=NULL;
+    int	nPart;
+    int	style;
+    LPSTR text;
+    BOOL	changed = FALSE;
+
+    text = (LPSTR) lParam;
+    nPart = ((INT) wParam) & 0x00ff;
+    style = ((INT) wParam) & 0xff00;
+
+    TRACE("part %d, text %s\n",nPart,debugstr_a(text));
+
+    if (nPart==255)
+	part = &infoPtr->part0;
+    else if (!infoPtr->simple && infoPtr->parts!=NULL)
+	part = &infoPtr->parts[nPart];
+    if (!part) return FALSE;
+
+    if (part->style != style)
+	changed = TRUE;
+
+    part->style = style;
+    if (style & SBT_OWNERDRAW) {
+	if (part->text == (LPWSTR)text)
+	    return TRUE;
+	part->text = (LPWSTR)text;
+    } else {
+	LPWSTR ntext;
+
+	/* check if text is unchanged -> no need to redraw */
+	if (text) {
+            DWORD len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 );
+	    LPWSTR tmptext = COMCTL32_Alloc(len*sizeof(WCHAR));
+            MultiByteToWideChar( CP_ACP, 0, text, -1, tmptext, len );
+
+	    if (!changed && part->text && !lstrcmpW(tmptext,part->text)) {
+		COMCTL32_Free(tmptext);
+		return TRUE;
+	    }
+	    ntext = tmptext;
+	} else {
+	    if (!changed && !part->text) 
+		return TRUE;
+	    ntext = 0;
+	}
+
+	if (part->text)
+	    COMCTL32_Free (part->text);
+	part->text = ntext;
+    }
+    InvalidateRect(hwnd, &part->bound, FALSE);
+
+    return TRUE;
+}
+
+
+static LRESULT
+STATUSBAR_SetTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    STATUSWINDOWPART *part;
+    INT  nPart, style, len;
+    LPWSTR text;
+    BOOL bRedraw = FALSE;
+
+    text = (LPWSTR) lParam;
+    nPart = ((INT) wParam) & 0x00ff;
+    style = ((INT) wParam) & 0xff00;
+
+    TRACE("part %d -> '%s' with style %04x\n", nPart, debugstr_w(text), style);
+    if ((infoPtr->simple) || (infoPtr->parts==NULL) || (nPart==255))
+	part = &infoPtr->part0;
+    else
+	part = &infoPtr->parts[nPart];
+    if (!part) return FALSE;
+
+    if(part->style != style)
+        bRedraw = TRUE;
+
+    part->style = style;
+
+    /* FIXME: not sure how/if we can check for change in string with ownerdraw(remove this if we can't)... */
+    if (style & SBT_OWNERDRAW)
+    {
+	part->text = text;
+        bRedraw = TRUE;
+    } else if(!text)
+    {
+        if(part->text)
+        {
+            COMCTL32_Free(part->text);
+            bRedraw = TRUE;
+        }
+        part->text = 0;
+    } else if(!part->text || strcmpW(part->text, text)) /* see if the new string differs from the existing string */
+    {
+	if(part->text) COMCTL32_Free(part->text);
+
+        len = strlenW(text);
+        part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
+	strcpyW(part->text, text);
+        bRedraw = TRUE;
+    }
+
+    if(bRedraw)
+        InvalidateRect(hwnd, &part->bound, FALSE);
+
+    return TRUE;
+}
+
+
+static LRESULT
+STATUSBAR_SetTipTextA (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TRACE("part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
+    if (infoPtr->hwndToolTip) {
+	TTTOOLINFOA ti;
+	ti.cbSize = sizeof(TTTOOLINFOA);
+	ti.hwnd = hwnd;
+	ti.uId = (INT)wParam;
+	ti.hinst = 0;
+	ti.lpszText = (LPSTR)lParam;
+	SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA,
+			0, (LPARAM)&ti);
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+STATUSBAR_SetTipTextW (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TRACE("part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
+    if (infoPtr->hwndToolTip) {
+	TTTOOLINFOW ti;
+	ti.cbSize = sizeof(TTTOOLINFOW);
+	ti.hwnd = hwnd;
+	ti.uId = (INT)wParam;
+	ti.hinst = 0;
+	ti.lpszText = (LPWSTR)lParam;
+	SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW,
+			0, (LPARAM)&ti);
+    }
+
+    return 0;
+}
+
+
+inline static LRESULT
+STATUSBAR_SetUnicodeFormat (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
+{
+    BOOL bOld = infoPtr->bUnicode;
+
+    TRACE("(0x%x)\n", (BOOL)wParam);
+    infoPtr->bUnicode = (BOOL)wParam;
+
+    return bOld;
+}
+
+
+static LRESULT
+STATUSBAR_Simple (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    NMHDR  nmhdr;
+
+    TRACE("(is simple: %d)\n", wParam);
+    if (infoPtr->simple == wParam) /* no need to change */
+	return TRUE;
+
+    infoPtr->simple = (BOOL)wParam;
+
+    /* send notification */
+    nmhdr.hwndFrom = hwnd;
+    nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
+    nmhdr.code = SBN_SIMPLEMODECHANGE;
+    SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
+    InvalidateRect(hwnd, NULL, FALSE);
+    return TRUE;
+}
+
+
+static LRESULT
+STATUSBAR_WMCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    LPCREATESTRUCTA lpCreate = (LPCREATESTRUCTA)lParam;
+    NONCLIENTMETRICSA nclm;
+    DWORD dwStyle;
+    RECT	rect;
+    int	        width, len;
+    HDC	hdc;
+    STATUSWINDOWINFO *infoPtr;
+
+    TRACE("\n");
+#ifdef __WIN32OS2__
+    infoPtr = (STATUSWINDOWINFO*)initControl(hwnd,sizeof(STATUSWINDOWINFO));
+#else
+    infoPtr = (STATUSWINDOWINFO*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO));
+#endif
+    SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
+
+    infoPtr->hwndParent = lpCreate->hwndParent;
+    infoPtr->numParts = 1;
+    infoPtr->parts = 0;
+    infoPtr->simple = FALSE;
+    infoPtr->clrBk = CLR_DEFAULT;
+    infoPtr->hFont = 0;
+
+    /* TODO: send unicode parent notification query (WM_QUERYFORMAT) here */
+
+    GetClientRect (hwnd, &rect);
+    InvalidateRect (hwnd, &rect, 0);
+    UpdateWindow(hwnd);
+
+    nclm.cbSize = sizeof(NONCLIENTMETRICSA);
+    SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, nclm.cbSize, &nclm, 0);
+    infoPtr->hDefaultFont = CreateFontIndirectA (&nclm.lfStatusFont);
+
+    /* initialize simple case */
+    infoPtr->part0.bound = rect;
+    infoPtr->part0.text = 0;
+    infoPtr->part0.x = 0;
+    infoPtr->part0.style = 0;
+    infoPtr->part0.hIcon = 0;
+
+    /* initialize first part */
+    infoPtr->parts = COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
+    infoPtr->parts[0].bound = rect;
+    infoPtr->parts[0].text = 0;
+    infoPtr->parts[0].x = -1;
+    infoPtr->parts[0].style = 0;
+    infoPtr->parts[0].hIcon = 0;
+
+    if (IsWindowUnicode (hwnd)) {
+	infoPtr->bUnicode = TRUE;
+	if (lpCreate->lpszName &&
+	    (len = strlenW ((LPCWSTR)lpCreate->lpszName))) {
+	    infoPtr->parts[0].text = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
+	    strcpyW (infoPtr->parts[0].text, (LPCWSTR)lpCreate->lpszName);
+	}
+    }
+    else {
+	if (lpCreate->lpszName &&
+	    (len = strlen((LPCSTR)lpCreate->lpszName))) {
+            DWORD lenW = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lpCreate->lpszName, -1, NULL, 0 );
+	    infoPtr->parts[0].text = COMCTL32_Alloc (lenW*sizeof(WCHAR));
+            MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lpCreate->lpszName, -1,
+                                 infoPtr->parts[0].text, lenW );
+	}
+    }
+
+    dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
+
+#ifndef __WIN32OS2__
+    /* statusbars on managed windows should not have SIZEGRIP style */
+    if ((dwStyle & SBARS_SIZEGRIP) && lpCreate->hwndParent)
+        if (GetWindowLongA(lpCreate->hwndParent, GWL_EXSTYLE) & WS_EX_MANAGED)
+            SetWindowLongA (hwnd, GWL_STYLE, dwStyle & ~SBARS_SIZEGRIP);
+#endif
+    if ((hdc = GetDC (0))) {
+	TEXTMETRICA tm;
+	HFONT hOldFont;
+
+	hOldFont = SelectObject (hdc,infoPtr->hDefaultFont);
+	GetTextMetricsA(hdc, &tm);
+	infoPtr->textHeight = tm.tmHeight;
+	SelectObject (hdc, hOldFont);
+	ReleaseDC(0, hdc);
+    }
+
+    if (dwStyle & SBT_TOOLTIPS) {
+	infoPtr->hwndToolTip =
+	    CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
+			       CW_USEDEFAULT, CW_USEDEFAULT,
+			       CW_USEDEFAULT, CW_USEDEFAULT,
+			     hwnd, 0,
+			     GetWindowLongA (hwnd, GWL_HINSTANCE), NULL);
+
+	if (infoPtr->hwndToolTip) {
+	    NMTOOLTIPSCREATED nmttc;
+
+	    nmttc.hdr.hwndFrom = hwnd;
+	    nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
+	    nmttc.hdr.code = NM_TOOLTIPSCREATED;
+	    nmttc.hwndToolTips = infoPtr->hwndToolTip;
+
+	    SendMessageA (lpCreate->hwndParent, WM_NOTIFY,
+			    (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
+	}
+    }
+
+    if (!dwStyle & CCS_NORESIZE) /* don't resize wnd if it doesn't want it ! */
+    {
+        GetClientRect (GetParent (hwnd), &rect);
+        width = rect.right - rect.left;
+        infoPtr->height = infoPtr->textHeight + 4 + VERT_BORDER;
+        SetWindowPos(hwnd, 0, lpCreate->x, lpCreate->y - 1,
+			width, infoPtr->height, SWP_NOZORDER);
+        STATUSBAR_SetPartBounds (infoPtr, hwnd);
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+STATUSBAR_WMDestroy (STATUSWINDOWINFO *infoPtr, HWND hwnd)
+{
+    int	i;
+
+    TRACE("\n");
+    for (i = 0; i < infoPtr->numParts; i++) {
+	if (infoPtr->parts[i].text && !(infoPtr->parts[i].style & SBT_OWNERDRAW))
+	    COMCTL32_Free (infoPtr->parts[i].text);
+    }
+    if (infoPtr->part0.text && !(infoPtr->part0.style & SBT_OWNERDRAW))
+	COMCTL32_Free (infoPtr->part0.text);
+    COMCTL32_Free (infoPtr->parts);
+
+    /* delete default font */
+    if (infoPtr->hDefaultFont)
+	DeleteObject (infoPtr->hDefaultFont);
+
+    /* delete tool tip control */
+    if (infoPtr->hwndToolTip)
+	DestroyWindow (infoPtr->hwndToolTip);
+
+    COMCTL32_Free (infoPtr);
+    SetWindowLongA(hwnd, 0, 0);
+    return 0;
+}
+
+
+static inline LRESULT
+STATUSBAR_WMGetFont (STATUSWINDOWINFO *infoPtr, HWND hwnd)
+{
+    TRACE("\n");
+    return infoPtr->hFont? infoPtr->hFont : infoPtr->hDefaultFont;
+}
+
+
+/* in contrast to SB_GETTEXT*, WM_GETTEXT handles the text
+ * of the first part only (usual behaviour) */
+static LRESULT
+STATUSBAR_WMGetText (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    INT len;
+
+    TRACE("\n");
+    if (!(infoPtr->parts[0].text))
+        return 0;
+    if (infoPtr->bUnicode)
+        len = strlenW (infoPtr->parts[0].text);
+    else
+        len = WideCharToMultiByte( CP_ACP, 0, infoPtr->parts[0].text, -1, NULL, 0, NULL, NULL )-1;
+
+    if (wParam > len) {
+	if (infoPtr->bUnicode)
+	    strcpyW ((LPWSTR)lParam, infoPtr->parts[0].text);
+	else
+            WideCharToMultiByte( CP_ACP, 0, infoPtr->parts[0].text, -1,
+                                 (LPSTR)lParam, len+1, NULL, NULL );
+	return len;
+    }
+
+    return -1;
+}
+
+
+inline static LRESULT
+STATUSBAR_WMMouseMove (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    if (infoPtr->hwndToolTip)
+	STATUSBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
+			      WM_MOUSEMOVE, wParam, lParam);
+    return 0;
+}
+
+
+static LRESULT
+STATUSBAR_WMNCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
+	RECT  rect;
+	POINT pt;
+
+	GetClientRect (hwnd, &rect);
+
+	pt.x = (INT)LOWORD(lParam);
+	pt.y = (INT)HIWORD(lParam);
+	ScreenToClient (hwnd, &pt);
+
+	rect.left = rect.right - 13;
+	rect.top += 2;
+
+	if (PtInRect (&rect, pt))
+	    return HTBOTTOMRIGHT;
+    }
+
+    /* FIXME: instead check result in StatusWindowProc and call if needed ? */
+    return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
+}
+
+
+static inline LRESULT
+STATUSBAR_WMNCLButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TRACE("\n");
+    PostMessageA (GetParent (hwnd), WM_NCLBUTTONDOWN, wParam, lParam);
+    return 0;
+}
+
+
+static inline LRESULT
+STATUSBAR_WMNCLButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TRACE("\n");
+    PostMessageA (GetParent (hwnd), WM_NCLBUTTONUP, wParam, lParam);
+    return 0;
+}
+
+
+static LRESULT
+STATUSBAR_WMPaint (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam)
+{
+    HDC hdc;
+    PAINTSTRUCT ps;
+
+    TRACE("\n");
+    hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
+    STATUSBAR_Refresh (infoPtr, hwnd, hdc);
+    if (!wParam)
+	EndPaint (hwnd, &ps);
+
+    return 0;
+}
+
+
+static LRESULT
+STATUSBAR_WMSetFont (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    infoPtr->hFont = (HFONT)wParam;
+    TRACE("%04x\n", infoPtr->hFont);
+#ifdef __WIN32OS2__
+    if (LOWORD(lParam) == TRUE)
+    {
+      HDC hdc = GetDC (hwnd);
+      TEXTMETRICA tm;
+      HFONT hOldFont;
+
+      hOldFont = SelectObject(hdc,infoPtr->hFont);
+      GetTextMetricsA(hdc,&tm);
+      infoPtr->textHeight = tm.tmHeight+tm.tmExternalLeading;
+      SelectObject(hdc,hOldFont);
+
+      //CB: todo: move window
+
+      STATUSBAR_Refresh (infoPtr, hwnd, hdc);
+      ReleaseDC (hwnd, hdc);
+    }
+#else
+    if (LOWORD(lParam) == TRUE)
+        InvalidateRect(hwnd, NULL, FALSE);
+#endif
+
+    return 0;
+}
+
+
+static LRESULT
+STATUSBAR_WMSetText (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    STATUSWINDOWPART *part;
+    int len;
+
+    TRACE("\n");
+    if (infoPtr->numParts == 0)
+	return FALSE;
+
+    part = &infoPtr->parts[0];
+    /* duplicate string */
+    if (part->text)
+        COMCTL32_Free (part->text);
+    part->text = 0;
+    if (infoPtr->bUnicode) {
+	if (lParam && (len = strlenW((LPCWSTR)lParam))) {
+	    part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
+	    strcpyW (part->text, (LPCWSTR)lParam);
+	}
+    }
+    else {
+	if (lParam && (len = lstrlenA((LPCSTR)lParam))) {
+            DWORD lenW = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lParam, -1, NULL, 0 );
+            part->text = COMCTL32_Alloc (lenW*sizeof(WCHAR));
+            MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lParam, -1, part->text, lenW );
+	}
+    }
+
+    InvalidateRect(hwnd, &part->bound, FALSE);
+
+    return TRUE;
+}
+
+
+static LRESULT
+STATUSBAR_WMSize (STATUSWINDOWINFO *infoPtr, HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    INT  width, x, y, flags;
+    RECT parent_rect;
+    DWORD dwStyle;
+
+    /* Need to resize width to match parent */
+    flags = (INT) wParam;
+
+    TRACE("flags %04x\n", flags);
+    /* FIXME for flags =
+     * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
+     */
+
+    dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
+    if (!dwStyle & CCS_NORESIZE) /* don't resize wnd if it doesn't want it ! */
+    {
+        if (flags == SIZE_RESTORED) {
+	    /* width and height don't apply */
+	    GetClientRect (infoPtr->hwndParent, &parent_rect);
+	    width = parent_rect.right - parent_rect.left;
+	    x = parent_rect.left;
+	    y = parent_rect.bottom - infoPtr->height;
+	    MoveWindow (hwnd, parent_rect.left, 
+		      parent_rect.bottom - infoPtr->height,
+		      width, infoPtr->height, TRUE);
+	    STATUSBAR_SetPartBounds (infoPtr, hwnd);
+        }
+	return 0; /* FIXME: ok to return here ? */
+    }
+
+    /* FIXME: instead check result in StatusWindowProc and call if needed ? */
+    return DefWindowProcA (hwnd, WM_SIZE, wParam, lParam);
+}
+
+
+static LRESULT
+STATUSBAR_SendNotify (HWND hwnd, UINT code)
+{
+    NMHDR  nmhdr;
+
+    TRACE("code %04x\n", code);
+    nmhdr.hwndFrom = hwnd;
+    nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
+    nmhdr.code = code;
+    SendMessageA (GetParent (hwnd), WM_NOTIFY, 0, (LPARAM)&nmhdr);
+    return 0;
+}
+
+
+
+static LRESULT WINAPI
+StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr(hwnd);
+
+    TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, msg, wParam, lParam);
+    if (!(infoPtr) && (msg != WM_CREATE))
+        return DefWindowProcA (hwnd, msg, wParam, lParam);
+
+    switch (msg) {
+	case SB_GETBORDERS:
+	    return STATUSBAR_GetBorders (lParam);
+
+	case SB_GETICON:
+	    return STATUSBAR_GetIcon (infoPtr, hwnd, wParam);
+
+	case SB_GETPARTS:
+	    return STATUSBAR_GetParts (infoPtr, hwnd, wParam, lParam);
+
+	case SB_GETRECT:
+	    return STATUSBAR_GetRect (infoPtr, hwnd, wParam, lParam);
+
+	case SB_GETTEXTA:
+	    return STATUSBAR_GetTextA (infoPtr, hwnd, wParam, lParam);
+
+	case SB_GETTEXTW:
+	    return STATUSBAR_GetTextW (infoPtr, hwnd, wParam, lParam);
+
+	case SB_GETTEXTLENGTHA:
+	case SB_GETTEXTLENGTHW:
+	    return STATUSBAR_GetTextLength (infoPtr, hwnd, wParam);
+
+	case SB_GETTIPTEXTA:
+	    return STATUSBAR_GetTipTextA (infoPtr, hwnd, wParam, lParam);
+
+	case SB_GETTIPTEXTW:
+	    return STATUSBAR_GetTipTextW (infoPtr, hwnd, wParam, lParam);
+
+	case SB_GETUNICODEFORMAT:
+	    return STATUSBAR_GetUnicodeFormat (infoPtr, hwnd);
+
+	case SB_ISSIMPLE:
+	    return STATUSBAR_IsSimple (infoPtr, hwnd);
+
+	case SB_SETBKCOLOR:
+	    return STATUSBAR_SetBkColor (infoPtr, hwnd, wParam, lParam);
+
+	case SB_SETICON:
+	    return STATUSBAR_SetIcon (infoPtr, hwnd, wParam, lParam);
+
+	case SB_SETMINHEIGHT:
+	    return STATUSBAR_SetMinHeight (infoPtr, hwnd, wParam, lParam);
+
+	case SB_SETPARTS:	
+	    return STATUSBAR_SetParts (infoPtr, hwnd, wParam, lParam);
+
+	case SB_SETTEXTA:
+	    return STATUSBAR_SetTextA (infoPtr, hwnd, wParam, lParam);
+
+	case SB_SETTEXTW:
+	    return STATUSBAR_SetTextW (infoPtr, hwnd, wParam, lParam);
+
+	case SB_SETTIPTEXTA:
+	    return STATUSBAR_SetTipTextA (infoPtr, hwnd, wParam, lParam);
+
+	case SB_SETTIPTEXTW:
+	    return STATUSBAR_SetTipTextW (infoPtr, hwnd, wParam, lParam);
+
+	case SB_SETUNICODEFORMAT:
+	    return STATUSBAR_SetUnicodeFormat (infoPtr, hwnd, wParam);
+
+	case SB_SIMPLE:
+	    return STATUSBAR_Simple (infoPtr, hwnd, wParam, lParam);
+
+
+	case WM_CREATE:
+	    return STATUSBAR_WMCreate (hwnd, wParam, lParam);
+
+	case WM_DESTROY:
+	    return STATUSBAR_WMDestroy (infoPtr, hwnd);
+
+	case WM_GETFONT:
+            return STATUSBAR_WMGetFont (infoPtr, hwnd);
+
+	case WM_GETTEXT:
+            return STATUSBAR_WMGetText (infoPtr, hwnd, wParam, lParam);
+
+	case WM_GETTEXTLENGTH:
+	    return STATUSBAR_GetTextLength (infoPtr, hwnd, 0);
+
+	case WM_LBUTTONDBLCLK:
+            return STATUSBAR_SendNotify (hwnd, NM_DBLCLK);
+
+	case WM_LBUTTONUP:
+	    return STATUSBAR_SendNotify (hwnd, NM_CLICK);
+
+	case WM_MOUSEMOVE:
+            return STATUSBAR_WMMouseMove (infoPtr, hwnd, wParam, lParam);
+
+	case WM_NCHITTEST:
+            return STATUSBAR_WMNCHitTest (hwnd, wParam, lParam);
+
+	case WM_NCLBUTTONDOWN:
+	    return STATUSBAR_WMNCLButtonDown (hwnd, wParam, lParam);
+
+	case WM_NCLBUTTONUP:
+	    return STATUSBAR_WMNCLButtonUp (hwnd, wParam, lParam);
+
+	case WM_PAINT:
+	    return STATUSBAR_WMPaint (infoPtr, hwnd, wParam);
+
+	case WM_RBUTTONDBLCLK:
+	    return STATUSBAR_SendNotify (hwnd, NM_RDBLCLK);
+
+	case WM_RBUTTONUP:
+	    return STATUSBAR_SendNotify (hwnd, NM_RCLICK);
+
+	case WM_SETFONT:
+	    return STATUSBAR_WMSetFont (infoPtr, hwnd, wParam, lParam);
+
+	case WM_SETTEXT:
+	    return STATUSBAR_WMSetText (infoPtr, hwnd, wParam, lParam);
+
+	case WM_SIZE:
+	    return STATUSBAR_WMSize (infoPtr, hwnd, wParam, lParam);
+
+	default:
+	    if (msg >= WM_USER)
+		ERR("unknown msg %04x wp=%04x lp=%08lx\n",
+		     msg, wParam, lParam);
+#ifdef __WIN32OS2__
+            return defComCtl32ProcA (hwnd, msg, wParam, lParam);
+#else
+	    return DefWindowProcA (hwnd, msg, wParam, lParam);
+#endif
+    }
+    return 0;
+}
+
+
+/***********************************************************************
+ * STATUS_Register [Internal]
+ *
+ * Registers the status window class.
+ */
+
+VOID
+STATUS_Register (void)
+{
+    WNDCLASSA wndClass;
+
+    ZeroMemory (&wndClass, sizeof(WNDCLASSA));
+    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW;
+    wndClass.lpfnWndProc   = (WNDPROC)StatusWindowProc;
+    wndClass.cbClsExtra    = 0;
+    wndClass.cbWndExtra    = sizeof(STATUSWINDOWINFO *);
+    wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
+    wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
+    wndClass.lpszClassName = STATUSCLASSNAMEA;
+ 
+    RegisterClassA (&wndClass);
+}
+
+
+/***********************************************************************
+ * STATUS_Unregister [Internal]
+ *
+ * Unregisters the status window class.
+ */
+
+VOID
+STATUS_Unregister (void)
+{
+    UnregisterClassA (STATUSCLASSNAMEA, (HINSTANCE)NULL);
+}
+
Index: trunk/src/comctl32/status.cpp
===================================================================
--- trunk/src/comctl32/status.cpp	(revision 5627)
+++ 	(revision )
@@ -1,1273 +1,0 @@
-/* $Id: status.cpp,v 1.3 2000-05-22 17:25:11 cbratschi Exp $ */
-/*
- * Interface code to StatusWindow widget/control
- *
- * Copyright 1996 Bruce Milner
- * Copyright 1998, 1999 Eric Kohl
- * Copyright 1999 Achim Hasenmueller
- * Copyright 1999 Christoph Bratschi
- */
-
-/* Corel WINE 20000513 level */
-
-#include "winbase.h"
-#include "commctrl.h"
-#include "comctl32.h"
-#include "ccbase.h"
-#include "status.h"
-#include <string.h>
-
-/*
- * Run tests using Waite Group Windows95 API Bible Vol. 1&2
- * The second cdrom contains executables drawstat.exe,gettext.exe,
- * simple.exe, getparts.exe, setparts.exe, statwnd.exe
- */
-
-/*
- * Fixme/Todo
- * 1) Don't hard code bar to bottom of window, allow CCS_TOP also.
- * 2) Tooltip support (almost done).
- */
-
-/* CB: Odin problems
- - DrawText: DT_VCENTER doesn't work (DT_SINGLELINE bug?)
-*/
-
-#define _MAX(a,b) (((a)>(b))?(a):(b))
-#define _MIN(a,b) (((a)>(b))?(b):(a))
-
-#define HORZ_BORDER 0
-#define VERT_BORDER 2
-#define VERT_SPACE  2 //space between border and text
-#define HORZ_GAP    2
-#define TOP_MARGIN  2
-#define ICON_SPACE  2
-#define TEXT_SPACE  3
-
-#define STATUSBAR_GetInfoPtr(hwnd) ((STATUSWINDOWINFO*)getInfoPtr(hwnd))
-
-
-static RECT STATUSBAR_GetSizeBox(HWND hwnd)
-{
-  RECT rect;
-
-  GetClientRect(hwnd,&rect);
-  rect.left = rect.right-GetSystemMetrics(SM_CXVSCROLL);
-  rect.top  = rect.bottom-GetSystemMetrics(SM_CYHSCROLL);
-
-  return rect;
-}
-
-static void
-STATUSBAR_DrawSizeGrip (HDC hdc, LPRECT lpRect)
-{
-    HPEN hOldPen;
-    POINT pt;
-    INT i;
-
-    pt.x = lpRect->right - 1;
-    pt.y = lpRect->bottom - 1;
-
-    hOldPen = SelectObject (hdc, GetSysColorPen (COLOR_3DFACE));
-    MoveToEx (hdc, pt.x - 12, pt.y, NULL);
-    LineTo (hdc, pt.x, pt.y);
-    LineTo (hdc, pt.x, pt.y - 12);
-
-    pt.x--;
-    pt.y--;
-
-    SelectObject (hdc, GetSysColorPen (COLOR_3DSHADOW));
-    for (i = 1; i < 11; i += 4) {
-        MoveToEx (hdc, pt.x - i, pt.y, NULL);
-        LineTo (hdc, pt.x, pt.y - i);
-
-        MoveToEx (hdc, pt.x - i-1, pt.y, NULL);
-        LineTo (hdc, pt.x, pt.y - i-1);
-    }
-
-    SelectObject (hdc, GetSysColorPen (COLOR_3DHIGHLIGHT));
-    for (i = 3; i < 13; i += 4) {
-        MoveToEx (hdc, pt.x - i, pt.y, NULL);
-        LineTo (hdc, pt.x, pt.y - i);
-    }
-
-    SelectObject (hdc, hOldPen);
-}
-
-
-static void
-STATUSBAR_DrawPart (HDC hdc, STATUSWINDOWPART *part)
-{
-    RECT r = part->bound;
-    UINT border = BDR_SUNKENOUTER;
-
-    if (part->style & SBT_POPOUT)
-      border = BDR_RAISEDOUTER;
-    else if (part->style & SBT_NOBORDERS)
-      border = 0;
-
-    DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST);
-
-    r.bottom -= VERT_SPACE;
-    r.top += VERT_SPACE;
-
-    /* draw the icon */
-    if (part->hIcon) {
-        INT cy = r.bottom - r.top;
-
-        r.left += ICON_SPACE;
-        DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
-        r.left += cy;
-    }
-
-    /* now draw text */
-    if (part->text) {
-      int oldbkmode = SetBkMode(hdc, TRANSPARENT);
-      LPWSTR p = (LPWSTR)part->text;
-      UINT align = DT_LEFT;
-      if (*p == L'\t') {
-        p++;
-        align = DT_CENTER;
-
-        if (*p == L'\t') {
-          p++;
-          align = DT_RIGHT;
-        }
-      }
-      r.left += TEXT_SPACE;
-      DrawTextW (hdc, p, lstrlenW (p), &r, align|DT_VCENTER|DT_SINGLELINE);
-      if (oldbkmode != TRANSPARENT)
-        SetBkMode(hdc, oldbkmode);
-    }
-}
-
-
-static VOID
-STATUSBAR_RefreshPart (HWND hwnd, STATUSWINDOWPART *part, HDC hdc)
-{
-    STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-    HBRUSH hbrBk;
-    HFONT  hOldFont;
-
-    if (!IsWindowVisible (hwnd))
-        return;
-
-    if (self->clrBk != CLR_DEFAULT)
-        hbrBk = CreateSolidBrush (self->clrBk);
-    else
-        hbrBk = GetSysColorBrush (COLOR_3DFACE);
-    FillRect(hdc, &part->bound, hbrBk);
-
-    hOldFont = SelectObject (hdc, self->hFont ? self->hFont : self->hDefaultFont);
-
-    if (part->style & SBT_OWNERDRAW) {
-        DRAWITEMSTRUCT dis;
-
-        dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
-        dis.itemID = -1;
-        dis.hwndItem = hwnd;
-        dis.hDC = hdc;
-        dis.rcItem = part->bound;
-        dis.itemData = (INT)part->text;
-        SendMessageA (GetParent (hwnd), WM_DRAWITEM,
-                (WPARAM)dis.CtlID, (LPARAM)&dis);
-    }
-    else
-        STATUSBAR_DrawPart (hdc, part);
-
-    SelectObject (hdc, hOldFont);
-
-    if (self->clrBk != CLR_DEFAULT)
-        DeleteObject (hbrBk);
-
-    if (GetWindowLongA (hwnd, GWL_STYLE) & SBARS_SIZEGRIP) {
-        RECT rect;
-
-        GetClientRect (hwnd, &rect);
-        STATUSBAR_DrawSizeGrip (hdc, &rect);
-    }
-}
-
-
-static BOOL
-STATUSBAR_Refresh (HWND hwnd, HDC hdc)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    int      i;
-    RECT   rect;
-    HBRUSH hbrBk;
-    HFONT  hOldFont;
-
-    if (!IsWindowVisible(hwnd))
-        return (TRUE);
-
-    GetClientRect (hwnd, &rect);
-
-    if (infoPtr->clrBk != CLR_DEFAULT)
-        hbrBk = CreateSolidBrush (infoPtr->clrBk);
-    else
-        hbrBk = GetSysColorBrush (COLOR_3DFACE);
-    FillRect(hdc, &rect, hbrBk);
-
-    hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);
-
-    if (infoPtr->simple) {
-        STATUSBAR_DrawPart (hdc, &infoPtr->part0);
-    }
-    else {
-        for (i = 0; i < infoPtr->numParts; i++) {
-            if (infoPtr->parts[i].style & SBT_OWNERDRAW) {
-                DRAWITEMSTRUCT dis;
-
-                dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
-                dis.itemID = -1;
-                dis.hwndItem = hwnd;
-                dis.hDC = hdc;
-                dis.rcItem = infoPtr->parts[i].bound;
-                dis.itemData = (INT)infoPtr->parts[i].text;
-                SendMessageA (GetParent (hwnd), WM_DRAWITEM,
-                        (WPARAM)dis.CtlID, (LPARAM)&dis);
-            }
-            else
-                STATUSBAR_DrawPart (hdc, &infoPtr->parts[i]);
-        }
-    }
-
-    SelectObject (hdc, hOldFont);
-
-    if (infoPtr->clrBk != CLR_DEFAULT)
-        DeleteObject (hbrBk);
-
-    if (GetWindowLongA(hwnd, GWL_STYLE) & SBARS_SIZEGRIP)
-        STATUSBAR_DrawSizeGrip (hdc, &rect);
-
-    return TRUE;
-}
-
-
-static void
-STATUSBAR_SetPartBounds (HWND hwnd)
-{
-    STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-    STATUSWINDOWPART *part;
-    RECT rect, *r;
-    int i;
-
-    /* get our window size */
-    GetClientRect (hwnd, &rect);
-
-    rect.top += TOP_MARGIN;
-
-    /* set bounds for simple rectangle */
-    self->part0.bound = rect;
-
-    /* set bounds for non-simple rectangles */
-    for (i = 0; i < self->numParts; i++) {
-        part = &self->parts[i];
-        r = &self->parts[i].bound;
-        r->top = rect.top;
-        r->bottom = rect.bottom;
-        if (i == 0)
-            r->left = 0;
-        else
-            r->left = self->parts[i-1].bound.right + HORZ_GAP;
-        if (part->x == -1)
-            r->right = rect.right;
-        else
-            r->right = part->x;
-
-        if (self->hwndToolTip) {
-            TTTOOLINFOA ti;
-
-            ti.cbSize = sizeof(TTTOOLINFOA);
-            ti.hwnd = hwnd;
-            ti.uId = i;
-            ti.rect = *r;
-            SendMessageA (self->hwndToolTip, TTM_NEWTOOLRECTA,
-                            0, (LPARAM)&ti);
-        }
-    }
-}
-
-
-static VOID
-STATUSBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
-                      WPARAM wParam, LPARAM lParam)
-{
-    MSG msg;
-
-    msg.hwnd = hwndMsg;
-    msg.message = uMsg;
-    msg.wParam = wParam;
-    msg.lParam = lParam;
-    msg.time = GetMessageTime ();
-    msg.pt.x = LOWORD(GetMessagePos ());
-    msg.pt.y = HIWORD(GetMessagePos ());
-
-    SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
-}
-
-
-static LRESULT
-STATUSBAR_GetBorders (LPARAM lParam)
-{
-    LPINT out = (LPINT) lParam;
-
-    out[0] = HORZ_BORDER; /* horizontal border width */
-    out[1] = VERT_BORDER; /* vertical border width */
-    out[2] = HORZ_GAP; /* width of border between rectangles */
-
-    return TRUE;
-}
-
-
-static LRESULT
-STATUSBAR_GetIcon (HWND hwnd, WPARAM wParam)
-{
-    STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-    INT nPart;
-
-    nPart = (INT)wParam & 0x00ff;
-    if ((nPart < -1) || (nPart >= self->numParts))
-        return 0;
-
-    if (nPart == -1)
-        return (self->part0.hIcon);
-    else
-        return (self->parts[nPart].hIcon);
-}
-
-
-static LRESULT
-STATUSBAR_GetParts (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    LPINT parts;
-    INT   num_parts;
-    INT   i;
-
-    num_parts = (INT) wParam;
-    parts = (LPINT) lParam;
-    if (parts) {
-        return (infoPtr->numParts);
-        for (i = 0; i < num_parts; i++) {
-            parts[i] = infoPtr->parts[i].x;
-        }
-    }
-    return (infoPtr->numParts);
-}
-
-
-static LRESULT
-STATUSBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    int part_num;
-    LPRECT  rect;
-
-    part_num = ((INT) wParam) & 0x00ff;
-    rect = (LPRECT) lParam;
-    if (infoPtr->simple)
-        *rect = infoPtr->part0.bound;
-    else
-        *rect = infoPtr->parts[part_num].bound;
-    return TRUE;
-}
-
-
-static LRESULT
-STATUSBAR_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-    STATUSWINDOWPART *part;
-    INT   nPart;
-    LRESULT result;
-
-    nPart = ((INT) wParam) & 0x00ff;
-    if (self->simple)
-        part = &self->part0;
-    else
-        part = &self->parts[nPart];
-
-    if (part->style & SBT_OWNERDRAW)
-        result = (LRESULT)part->text;
-    else {
-        result = part->text ? lstrlenW (part->text) : 0;
-        result |= (part->style << 16);
-        if (lParam && LOWORD(result))
-            lstrcpyWtoA((LPSTR)lParam, part->text);
-    }
-    return result;
-}
-
-
-static LRESULT
-STATUSBAR_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    STATUSWINDOWPART *part;
-    INT   nPart;
-    LRESULT result;
-
-    nPart = ((INT)wParam) & 0x00ff;
-    if (infoPtr->simple)
-        part = &infoPtr->part0;
-    else
-        part = &infoPtr->parts[nPart];
-
-    if (part->style & SBT_OWNERDRAW)
-        result = (LRESULT)part->text;
-    else {
-        result = part->text ? lstrlenW (part->text) : 0;
-        result |= (part->style << 16);
-        if (lParam)
-            lstrcpyW ((LPWSTR)lParam, part->text);
-    }
-    return result;
-}
-
-
-static LRESULT
-STATUSBAR_GetTextLength (HWND hwnd, WPARAM wParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    STATUSWINDOWPART *part;
-    INT part_num;
-    DWORD result;
-
-    part_num = ((INT) wParam) & 0x00ff;
-
-    if (infoPtr->simple)
-        part = &infoPtr->part0;
-    else
-        part = &infoPtr->parts[part_num];
-
-    if (part->text)
-        result = lstrlenW(part->text);
-    else
-        result = 0;
-
-    result |= (part->style << 16);
-    return result;
-}
-
-
-static LRESULT
-STATUSBAR_GetTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-
-    if (infoPtr->hwndToolTip) {
-        TTTOOLINFOA ti;
-        ti.cbSize = sizeof(TTTOOLINFOA);
-        ti.hwnd = hwnd;
-        ti.uId = LOWORD(wParam);
-        SendMessageA (infoPtr->hwndToolTip, TTM_GETTEXTA, 0, (LPARAM)&ti);
-
-        if (ti.lpszText)
-            lstrcpynA ((LPSTR)lParam, ti.lpszText, HIWORD(wParam));
-    }
-
-    return 0;
-}
-
-
-static LRESULT
-STATUSBAR_GetTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-
-    if (infoPtr->hwndToolTip) {
-        TTTOOLINFOW ti;
-        ti.cbSize = sizeof(TTTOOLINFOW);
-        ti.hwnd = hwnd;
-        ti.uId = LOWORD(wParam);
-        SendMessageW (infoPtr->hwndToolTip, TTM_GETTEXTW, 0, (LPARAM)&ti);
-
-        if (ti.lpszText)
-            lstrcpynW ((LPWSTR)lParam, ti.lpszText, HIWORD(wParam));
-    }
-
-    return 0;
-}
-
-static LRESULT
-STATUSBAR_IsSimple (HWND hwnd)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    return infoPtr->simple;
-}
-
-
-static LRESULT
-STATUSBAR_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-    COLORREF oldBkColor;
-    HDC    hdc;
-
-    oldBkColor = self->clrBk;
-    self->clrBk = (COLORREF)lParam;
-    hdc = GetDC (hwnd);
-    STATUSBAR_Refresh (hwnd, hdc);
-    ReleaseDC (hwnd, hdc);
-
-    return oldBkColor;
-}
-
-
-static LRESULT
-STATUSBAR_SetIcon (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-    INT nPart = (INT)wParam & 0x00ff;
-    HDC hdc;
-
-    if ((nPart < -1) || (nPart >= self->numParts))
-        return FALSE;
-
-    hdc = GetDC (hwnd);
-    if (nPart == -1) {
-        self->part0.hIcon = (HICON)lParam;
-        if (self->simple)
-            STATUSBAR_RefreshPart (hwnd, &self->part0, hdc);
-    }
-    else {
-        self->parts[nPart].hIcon = (HICON)lParam;
-        if (!(self->simple))
-            STATUSBAR_RefreshPart (hwnd, &self->parts[nPart], hdc);
-    }
-    ReleaseDC (hwnd, hdc);
-
-    return TRUE;
-}
-
-
-static LRESULT
-STATUSBAR_SetMinHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-
-    if (IsWindowVisible (hwnd)) {
-        HWND parent = GetParent (hwnd);
-        INT  width, x, y;
-        RECT parent_rect;
-
-        GetClientRect (parent, &parent_rect);
-        self->height = (INT)wParam + VERT_BORDER;
-        width = parent_rect.right - parent_rect.left;
-        x = parent_rect.left;
-        y = parent_rect.bottom - self->height;
-        MoveWindow (hwnd, parent_rect.left,
-                      parent_rect.bottom - self->height,
-                      width, self->height, TRUE);
-        STATUSBAR_SetPartBounds (hwnd);
-    }
-
-    return TRUE;
-}
-
-
-static LRESULT
-STATUSBAR_SetParts (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-    STATUSWINDOWPART *tmp;
-    HDC hdc;
-    LPINT parts;
-    int i;
-    int oldNumParts;
-
-    if (self->simple)
-        self->simple = FALSE;
-
-    oldNumParts = self->numParts;
-    self->numParts = (INT) wParam;
-    parts = (LPINT) lParam;
-    if (oldNumParts > self->numParts) {
-        for (i = self->numParts ; i < oldNumParts; i++) {
-            if (self->parts[i].text && !(self->parts[i].style & SBT_OWNERDRAW))
-                COMCTL32_Free (self->parts[i].text);
-        }
-    }
-    else if (oldNumParts < self->numParts) {
-        tmp = (STATUSWINDOWPART*)COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * self->numParts);
-        for (i = 0; i < oldNumParts; i++) {
-            tmp[i] = self->parts[i];
-        }
-        if (self->parts)
-            COMCTL32_Free (self->parts);
-        self->parts = tmp;
-    }
-
-    for (i = 0; i < self->numParts; i++) {
-        self->parts[i].x = parts[i];
-    }
-
-    if (self->hwndToolTip) {
-        INT nTipCount =
-            SendMessageA (self->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0);
-
-        if (nTipCount < self->numParts) {
-            /* add tools */
-            TTTOOLINFOA ti;
-            INT i;
-
-            ZeroMemory (&ti, sizeof(TTTOOLINFOA));
-            ti.cbSize = sizeof(TTTOOLINFOA);
-            ti.hwnd = hwnd;
-            for (i = nTipCount; i < self->numParts; i++) {
-//              TRACE (statusbar, "add tool %d\n", i);
-                ti.uId = i;
-                SendMessageA (self->hwndToolTip, TTM_ADDTOOLA,
-                                0, (LPARAM)&ti);
-            }
-        }
-        else if (nTipCount > self->numParts) {
-            /* delete tools */
-            INT i;
-
-            for (i = nTipCount - 1; i >= self->numParts; i--) {
-
-//              FIXME (statusbar, "delete tool %d\n", i);
-
-            }
-        }
-    }
-
-    STATUSBAR_SetPartBounds (hwnd);
-
-    hdc = GetDC (hwnd);
-    STATUSBAR_Refresh (hwnd, hdc);
-    ReleaseDC (hwnd, hdc);
-
-    return TRUE;
-}
-
-
-static LRESULT
-STATUSBAR_SetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-    STATUSWINDOWPART *part;
-    int part_num;
-    int style;
-    LPSTR text;
-    LPWSTR newText;
-    int len;
-    HDC hdc;
-
-    text = (LPSTR) lParam;
-    part_num = ((INT) wParam) & 0x00ff;
-    style = ((INT) wParam) & 0xff00;
-
-    if ((self->simple) || (self->parts==NULL) || (part_num==255))
-        part = &self->part0;
-    else
-        part = &self->parts[part_num];
-    if (!part) return FALSE;
-
-    if (style & SBT_OWNERDRAW)
-    {
-      if (!(part->style & SBT_OWNERDRAW) && part->text) COMCTL32_Free(part->text);
-      part->text = (LPWSTR)text;
-    } else
-    {
-      //compare
-      if (text && (len = lstrlenA(text)))
-      {
-        newText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
-        lstrcpyAtoW (newText,text);
-      } else newText = NULL;
-      if (lstrcmpW(part->text,newText) == 0)
-      {
-        COMCTL32_Free(newText);
-        if (part->style != style)
-        {
-          hdc = GetDC(hwnd);
-          STATUSBAR_RefreshPart(hwnd,part,hdc);
-          ReleaseDC(hwnd, hdc);
-        }
-        return TRUE;
-      }
-
-      COMCTL32_Free(part->text);
-      part->text = newText;
-    }
-    part->style = style;
-
-    hdc = GetDC (hwnd);
-    STATUSBAR_RefreshPart (hwnd, part, hdc);
-    ReleaseDC (hwnd, hdc);
-
-    return TRUE;
-}
-
-
-static LRESULT
-STATUSBAR_SetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-    STATUSWINDOWPART *part;
-    INT  part_num, style, len;
-    LPWSTR text;
-    HDC  hdc;
-
-    text = (LPWSTR) lParam;
-    part_num = ((INT) wParam) & 0x00ff;
-    style = ((INT) wParam) & 0xff00;
-
-    if ((self->simple) || (self->parts==NULL) || (part_num==255))
-        part = &self->part0;
-    else
-        part = &self->parts[part_num];
-    if (!part) return FALSE;
-
-    if (style & SBT_OWNERDRAW)
-    {
-      if (!(part->style & SBT_OWNERDRAW) && part->text) COMCTL32_Free(part->text);
-      part->text = text;
-    } else
-    {
-      //compare
-      if (lstrcmpW(part->text,text) == 0)
-      {
-        if (part->style != style)
-        {
-          hdc = GetDC(hwnd);
-          STATUSBAR_RefreshPart(hwnd,part,hdc);
-          ReleaseDC(hwnd, hdc);
-        }
-        return TRUE;
-      }
-
-      /* duplicate string */
-      COMCTL32_Free(part->text);
-      if (text && (len = lstrlenW(text)))
-      {
-        part->text = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
-        lstrcpyW(part->text,text);
-      }
-    }
-    part->style = style;
-
-    hdc = GetDC (hwnd);
-    STATUSBAR_RefreshPart (hwnd, part, hdc);
-    ReleaseDC (hwnd, hdc);
-
-    return TRUE;
-}
-
-
-static LRESULT
-STATUSBAR_SetTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-
-//    TRACE (statusbar, "part %d: \"%s\"\n", (INT)wParam, (LPSTR)lParam);
-    if (infoPtr->hwndToolTip) {
-        TTTOOLINFOA ti;
-        ti.cbSize = sizeof(TTTOOLINFOA);
-        ti.hwnd = hwnd;
-        ti.uId = (INT)wParam;
-        ti.hinst = 0;
-        ti.lpszText = (LPSTR)lParam;
-        SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA,
-                        0, (LPARAM)&ti);
-    }
-
-    return 0;
-}
-
-
-static LRESULT
-STATUSBAR_SetTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-
-    if (infoPtr->hwndToolTip) {
-        TTTOOLINFOW ti;
-        ti.cbSize = sizeof(TTTOOLINFOW);
-        ti.hwnd = hwnd;
-        ti.uId = (INT)wParam;
-        ti.hinst = 0;
-        ti.lpszText = (LPWSTR)lParam;
-        SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW,
-                        0, (LPARAM)&ti);
-    }
-
-    return 0;
-}
-
-static LRESULT
-STATUSBAR_Simple (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    HDC  hdc;
-
-    infoPtr->simple = (BOOL)wParam;
-
-    /* send notification */
-    sendNotify(hwnd,SBN_SIMPLEMODECHANGE);
-
-    hdc = GetDC (hwnd);
-    STATUSBAR_Refresh (hwnd, hdc);
-    ReleaseDC (hwnd, hdc);
-
-    return TRUE;
-}
-
-
-static LRESULT
-STATUSBAR_WMCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    LPCREATESTRUCTA lpCreate = (LPCREATESTRUCTA)lParam;
-    NONCLIENTMETRICSA nclm;
-    RECT        rect;
-    int         width, len;
-    HDC hdc;
-    STATUSWINDOWINFO *infoPtr;
-
-    infoPtr = (STATUSWINDOWINFO*)initControl(hwnd,sizeof(STATUSWINDOWINFO));
-
-    infoPtr->numParts = 1;
-    infoPtr->parts = 0;
-    infoPtr->simple = FALSE;
-    infoPtr->clrBk = CLR_DEFAULT;
-    infoPtr->hFont = 0;
-    GetClientRect (hwnd, &rect);
-
-    nclm.cbSize = sizeof(NONCLIENTMETRICSA);
-    SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
-    infoPtr->hDefaultFont = CreateFontIndirectA (&nclm.lfStatusFont);
-
-    /* initialize simple case */
-    infoPtr->part0.bound = rect;
-    infoPtr->part0.text = 0;
-    infoPtr->part0.x = 0;
-    infoPtr->part0.style = 0;
-    infoPtr->part0.hIcon = 0;
-
-    /* initialize first part */
-    infoPtr->parts = (STATUSWINDOWPART*)COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
-    infoPtr->parts[0].bound = rect;
-    infoPtr->parts[0].text = 0;
-    infoPtr->parts[0].x = -1;
-    infoPtr->parts[0].style = 0;
-    infoPtr->parts[0].hIcon = 0;
-
-    if (infoPtr->header.fUnicode)
-    {
-      if (lpCreate->lpszName && (len = lstrlenW ((LPCWSTR)lpCreate->lpszName)))
-      {
-        infoPtr->parts[0].text = (WCHAR*)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
-        lstrcpyW (infoPtr->parts[0].text, (LPCWSTR)lpCreate->lpszName);
-      }
-    } else
-    {
-      if (lpCreate->lpszName && (len = lstrlenA ((LPCSTR)lpCreate->lpszName)))
-      {
-        infoPtr->parts[0].text = (WCHAR*)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
-        lstrcpyAtoW (infoPtr->parts[0].text, (char*)lpCreate->lpszName);
-      }
-    }
-
-    hdc = GetDC(hwnd);
-    if (hdc) {
-        TEXTMETRICA tm;
-        HFONT hOldFont;
-
-        hOldFont = SelectObject (hdc,infoPtr->hDefaultFont);
-        GetTextMetricsA(hdc, &tm);
-        infoPtr->textHeight = tm.tmHeight+tm.tmExternalLeading;
-        SelectObject (hdc, hOldFont);
-        ReleaseDC(hwnd, hdc);
-    }
-
-    if (GetWindowLongA(hwnd,GWL_STYLE) & SBT_TOOLTIPS)
-      infoPtr->hwndToolTip = createToolTip(hwnd,0,FALSE);
-
-    GetClientRect (GetParent (hwnd), &rect);
-    width = rect.right - rect.left;
-    infoPtr->height = infoPtr->textHeight + 4 + VERT_BORDER;
-//CB: todo: find bug in font handling!
-infoPtr->height += 4;
-    MoveWindow(hwnd,lpCreate->x,lpCreate->y-1,width,infoPtr->height,FALSE);
-    STATUSBAR_SetPartBounds (hwnd);
-
-    return 0;
-}
-
-
-static LRESULT
-STATUSBAR_WMDestroy (HWND hwnd)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    int i;
-
-    for (i = 0; i < infoPtr->numParts; i++) {
-        if (infoPtr->parts[i].text && !(infoPtr->parts[i].style & SBT_OWNERDRAW))
-            COMCTL32_Free (infoPtr->parts[i].text);
-    }
-    if (infoPtr->part0.text && !(infoPtr->part0.style & SBT_OWNERDRAW))
-        COMCTL32_Free (infoPtr->part0.text);
-    COMCTL32_Free (infoPtr->parts);
-
-    /* delete default font */
-    if (infoPtr->hDefaultFont)
-        DeleteObject (infoPtr->hDefaultFont);
-
-    doneControl(hwnd);
-
-    return 0;
-}
-
-
-static LRESULT
-STATUSBAR_WMGetFont (HWND hwnd)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    return infoPtr->hFont;
-}
-
-
-static LRESULT
-STATUSBAR_WMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    INT len;
-
-    if (!(infoPtr->parts[0].text))
-        return 0;
-    len = lstrlenW (infoPtr->parts[0].text);
-    if (wParam > len)
-    {
-      if (infoPtr->header.fUnicode)
-        lstrcpyW ((LPWSTR)lParam, infoPtr->parts[0].text);
-      else
-        lstrcpyWtoA ((LPSTR)lParam, infoPtr->parts[0].text);
-      return len;
-    }
-
-    return -1;
-}
-
-static LRESULT
-STATUSBAR_WMMouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr(hwnd);
-
-    if (infoPtr->hwndToolTip)
-        STATUSBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
-                              WM_MOUSEMOVE, wParam, lParam);
-    return 0;
-}
-
-
-static LRESULT
-STATUSBAR_WMNCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  if (GetWindowLongA (hwnd,GWL_STYLE) & SBARS_SIZEGRIP)
-  {
-    RECT rect = STATUSBAR_GetSizeBox(hwnd);
-    POINT pt;
-
-    pt.x = (SHORT)LOWORD(lParam);
-    pt.y = (SHORT)HIWORD(lParam);
-    ScreenToClient(hwnd,&pt);
-
-    if (PtInRect(&rect,pt))
-      return HTBOTTOMRIGHT;
-  }
-
-  return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
-}
-
-
-static LRESULT
-STATUSBAR_WMNCLButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  PostMessageA (GetParent (hwnd), WM_NCLBUTTONDOWN, wParam, lParam);
-  return 0;
-}
-
-
-static LRESULT
-STATUSBAR_WMNCLButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    PostMessageA (GetParent (hwnd), WM_NCLBUTTONUP, wParam, lParam);
-    return 0;
-}
-
-
-static LRESULT
-STATUSBAR_WMPaint (HWND hwnd, WPARAM wParam)
-{
-    HDC hdc;
-    PAINTSTRUCT ps;
-
-    hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
-    STATUSBAR_Refresh (hwnd, hdc);
-    if (!wParam)
-        EndPaint (hwnd, &ps);
-
-    return 0;
-}
-
-
-static LRESULT
-STATUSBAR_WMSetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-
-    infoPtr->hFont = (HFONT)wParam;
-    if (LOWORD(lParam) == TRUE)
-    {
-      HDC hdc = GetDC (hwnd);
-      TEXTMETRICA tm;
-      HFONT hOldFont;
-
-      hOldFont = SelectObject(hdc,infoPtr->hFont);
-      GetTextMetricsA(hdc,&tm);
-      infoPtr->textHeight = tm.tmHeight+tm.tmExternalLeading;
-      SelectObject(hdc,hOldFont);
-
-      //CB: todo: move window
-
-      STATUSBAR_Refresh (hwnd, hdc);
-      ReleaseDC (hwnd, hdc);
-    }
-
-    return 0;
-}
-
-
-static LRESULT
-STATUSBAR_WMSetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    STATUSWINDOWPART *part;
-    int len;
-    HDC hdc;
-
-    if (!infoPtr) return DefWindowProcA(hwnd,WM_SETTEXT,wParam,lParam);
-
-    if (infoPtr->numParts == 0)
-        return FALSE;
-
-    part = &infoPtr->parts[0];
-    /* duplicate string */
-    if (part->text)
-        COMCTL32_Free (part->text);
-    part->text = 0;
-    if (infoPtr->header.fUnicode) {
-        if (lParam && (len = lstrlenW((LPCWSTR)lParam))) {
-            part->text = (WCHAR*)COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
-            lstrcpyW (part->text, (LPCWSTR)lParam);
-        }
-    }
-    else {
-        if (lParam && (len = lstrlenA((LPCSTR)lParam))) {
-            part->text = (WCHAR*)COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
-            lstrcpyAtoW (part->text, (char*)lParam);
-        }
-    }
-
-    hdc = GetDC (hwnd);
-    STATUSBAR_RefreshPart (hwnd, part, hdc);
-    ReleaseDC (hwnd, hdc);
-
-    return TRUE;
-}
-
-
-static LRESULT
-STATUSBAR_WMSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    STATUSWINDOWINFO *infoPtr = STATUSBAR_GetInfoPtr (hwnd);
-    INT  width, x, y, flags;
-    RECT parent_rect;
-    HWND parent;
-
-    /* Need to resize width to match parent */
-    flags = (INT) wParam;
-
-    /* FIXME for flags =
-     * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED, SIZE_RESTORED
-     */
-
-    if (flags == SIZE_RESTORED) {
-        /* width and height don't apply */
-        parent = GetParent (hwnd);
-        GetClientRect (parent, &parent_rect);
-        width = parent_rect.right - parent_rect.left;
-        x = parent_rect.left;
-        y = parent_rect.bottom - infoPtr->height;
-        MoveWindow (hwnd, parent_rect.left,
-                      parent_rect.bottom - infoPtr->height,
-                      width, infoPtr->height, TRUE);
-        STATUSBAR_SetPartBounds (hwnd);
-    }
-    return 0;
-}
-
-static LRESULT WINAPI
-StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-    switch (msg) {
-        case SB_GETBORDERS:
-            return STATUSBAR_GetBorders (lParam);
-
-        case SB_GETICON:
-            return STATUSBAR_GetIcon (hwnd, wParam);
-
-        case SB_GETPARTS:
-            return STATUSBAR_GetParts (hwnd, wParam, lParam);
-
-        case SB_GETRECT:
-            return STATUSBAR_GetRect (hwnd, wParam, lParam);
-
-        case SB_GETTEXTA:
-            return STATUSBAR_GetTextA (hwnd, wParam, lParam);
-
-        case SB_GETTEXTW:
-            return STATUSBAR_GetTextW (hwnd, wParam, lParam);
-
-        case SB_GETTEXTLENGTHA:
-        case SB_GETTEXTLENGTHW:
-            return STATUSBAR_GetTextLength (hwnd, wParam);
-
-        case SB_GETTIPTEXTA:
-            return STATUSBAR_GetTipTextA (hwnd, wParam, lParam);
-
-        case SB_GETTIPTEXTW:
-            return STATUSBAR_GetTipTextW (hwnd, wParam, lParam);
-
-        case SB_ISSIMPLE:
-            return STATUSBAR_IsSimple (hwnd);
-
-        case SB_SETBKCOLOR:
-            return STATUSBAR_SetBkColor (hwnd, wParam, lParam);
-
-        case SB_SETICON:
-            return STATUSBAR_SetIcon (hwnd, wParam, lParam);
-
-        case SB_SETMINHEIGHT:
-            return STATUSBAR_SetMinHeight (hwnd, wParam, lParam);
-
-        case SB_SETPARTS:
-            return STATUSBAR_SetParts (hwnd, wParam, lParam);
-
-        case SB_SETTEXTA:
-            return STATUSBAR_SetTextA (hwnd, wParam, lParam);
-
-        case SB_SETTEXTW:
-            return STATUSBAR_SetTextW (hwnd, wParam, lParam);
-
-        case SB_SETTIPTEXTA:
-            return STATUSBAR_SetTipTextA (hwnd, wParam, lParam);
-
-        case SB_SETTIPTEXTW:
-            return STATUSBAR_SetTipTextW (hwnd, wParam, lParam);
-
-        case SB_SIMPLE:
-            return STATUSBAR_Simple (hwnd, wParam, lParam);
-
-
-        case WM_CREATE:
-            return STATUSBAR_WMCreate (hwnd, wParam, lParam);
-
-        case WM_DESTROY:
-            return STATUSBAR_WMDestroy (hwnd);
-
-        case WM_GETFONT:
-            return STATUSBAR_WMGetFont (hwnd);
-
-        case WM_GETTEXT:
-            return STATUSBAR_WMGetText (hwnd, wParam, lParam);
-
-        case WM_GETTEXTLENGTH:
-            return STATUSBAR_GetTextLength (hwnd, 0);
-
-        case WM_LBUTTONDBLCLK:
-            return sendNotify(hwnd,NM_DBLCLK);
-
-        case WM_LBUTTONUP:
-            return sendNotify(hwnd,NM_CLICK);
-
-        case WM_MOUSEMOVE:
-            return STATUSBAR_WMMouseMove (hwnd, wParam, lParam);
-
-        case WM_NCHITTEST:
-            return STATUSBAR_WMNCHitTest (hwnd, wParam, lParam);
-
-        case WM_NCLBUTTONDOWN:
-            return STATUSBAR_WMNCLButtonDown (hwnd, wParam, lParam);
-
-        case WM_NCLBUTTONUP:
-            return STATUSBAR_WMNCLButtonUp (hwnd, wParam, lParam);
-
-        case WM_PAINT:
-            return STATUSBAR_WMPaint (hwnd, wParam);
-
-        case WM_RBUTTONDBLCLK:
-            return sendNotify(hwnd,NM_RDBLCLK);
-
-        case WM_RBUTTONUP:
-            return sendNotify(hwnd,NM_RCLICK);
-
-        case WM_SETFONT:
-            return STATUSBAR_WMSetFont (hwnd, wParam, lParam);
-
-        case WM_SETTEXT:
-            return STATUSBAR_WMSetText (hwnd, wParam, lParam);
-
-        case WM_SIZE:
-            return STATUSBAR_WMSize (hwnd, wParam, lParam);
-
-        default:
-//            if (msg >= WM_USER)
-//              ERR (statusbar, "unknown msg %04x wp=%04x lp=%08lx\n",
-//                   msg, wParam, lParam);
-            return defComCtl32ProcA (hwnd, msg, wParam, lParam);
-    }
-    return 0;
-}
-
-
-/***********************************************************************
- * STATUS_Register [Internal]
- *
- * Registers the status window class.
- */
-
-VOID
-STATUS_Register (VOID)
-{
-    WNDCLASSA wndClass;
-
-    ZeroMemory (&wndClass, sizeof(WNDCLASSA));
-    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW;
-    wndClass.lpfnWndProc   = (WNDPROC)StatusWindowProc;
-    wndClass.cbClsExtra    = 0;
-    wndClass.cbWndExtra    = sizeof(STATUSWINDOWINFO *);
-    wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
-    wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
-    wndClass.lpszClassName = STATUSCLASSNAMEA;
-
-    RegisterClassA (&wndClass);
-}
-
-
-/***********************************************************************
- * STATUS_Unregister [Internal]
- *
- * Unregisters the status window class.
- */
-
-VOID
-STATUS_Unregister (VOID)
-{
-    UnregisterClassA (STATUSCLASSNAMEA, (HINSTANCE)NULL);
-}
-
Index: trunk/src/comctl32/tab.c
===================================================================
--- trunk/src/comctl32/tab.c	(revision 5630)
+++ trunk/src/comctl32/tab.c	(revision 5630)
@@ -0,0 +1,3024 @@
+/*
+ * Tab control
+ *
+ * Copyright 1998 Anders Carlsson
+ * Copyright 1999 Alex Priem <alexp@sci.kun.nl>
+ * Copyright 1999 Francis Beaudet
+ *
+ * TODO:
+ *  Image list support
+ *  Unicode support (under construction)
+ *
+ * FIXME:
+ *  UpDown control not displayed until after a tab is clicked on
+ */
+
+#include <string.h>
+
+#include "winbase.h"
+#include "commctrl.h"
+#include "comctl32.h"
+#include "debugtools.h"
+#include <math.h>
+#ifdef __WIN32OS2__
+#include "ccbase.h"
+#define COMCTL32_hPattern55AABrush GetPattern55AABitmap()
+#endif
+
+DEFAULT_DEBUG_CHANNEL(tab);
+
+typedef struct
+{
+  UINT   mask;
+  DWORD  dwState;
+  LPWSTR pszText;
+  INT    iImage;
+  LPARAM lParam;
+  RECT   rect;    /* bounding rectangle of the item relative to the
+		   * leftmost item (the leftmost item, 0, would have a 
+		   * "left" member of 0 in this rectangle) 
+                   *  
+                   * additionally the top member hold the row number
+                   * and bottom is unused and should be 0 */
+} TAB_ITEM;
+
+typedef struct
+{
+#ifdef __WIN32OS2__
+  COMCTL32_HEADER header;
+#endif
+  UINT       uNumItem;        /* number of tab items */
+  UINT       uNumRows;	      /* number of tab rows */
+  INT        tabHeight;       /* height of the tab row */
+  INT        tabWidth;        /* width of tabs */
+  HFONT      hFont;           /* handle to the current font */
+  HCURSOR    hcurArrow;       /* handle to the current cursor */
+  HIMAGELIST himl;            /* handle to a image list (may be 0) */
+  HWND       hwndToolTip;     /* handle to tab's tooltip */
+  INT        leftmostVisible; /* Used for scrolling, this member contains
+			       * the index of the first visible item */
+  INT        iSelected;       /* the currently selected item */
+  INT        iHotTracked;     /* the highlighted item under the mouse */
+  INT        uFocus;          /* item which has the focus */
+  TAB_ITEM*  items;           /* pointer to an array of TAB_ITEM's */
+  BOOL       DoRedraw;        /* flag for redrawing when tab contents is changed*/
+  BOOL       needsScrolling;  /* TRUE if the size of the tabs is greater than 
+			       * the size of the control */
+  BOOL	     fSizeSet;	      /* was the size of the tabs explicitly set? */
+  BOOL       bUnicode;        /* Unicode control? */
+  HWND       hwndUpDown;      /* Updown control used for scrolling */
+} TAB_INFO;
+
+/******************************************************************************
+ * Positioning constants
+ */
+#define SELECTED_TAB_OFFSET     2
+#define HORIZONTAL_ITEM_PADDING 5
+#define VERTICAL_ITEM_PADDING   3
+#define ROUND_CORNER_SIZE       2
+#define DISPLAY_AREA_PADDINGX   2
+#define DISPLAY_AREA_PADDINGY   2
+#define CONTROL_BORDER_SIZEX    2
+#define CONTROL_BORDER_SIZEY    2
+#define BUTTON_SPACINGX         4 
+#define BUTTON_SPACINGY         4
+#define FLAT_BTN_SPACINGX       8
+#define DEFAULT_TAB_WIDTH       96
+
+#define TAB_GetInfoPtr(hwnd) ((TAB_INFO *)GetWindowLongA(hwnd,0))
+
+/******************************************************************************
+ * Hot-tracking timer constants
+ */
+#define TAB_HOTTRACK_TIMER            1
+#define TAB_HOTTRACK_TIMER_INTERVAL   100   /* milliseconds */
+
+/******************************************************************************
+ * Prototypes
+ */
+static void TAB_Refresh (HWND hwnd, HDC hdc);
+static void TAB_InvalidateTabArea(HWND hwnd, TAB_INFO* infoPtr);
+static void TAB_EnsureSelectionVisible(HWND hwnd, TAB_INFO* infoPtr);
+static void TAB_DrawItem(HWND hwnd, HDC hdc, INT iItem);
+static void TAB_DrawItemInterior(HWND hwnd, HDC hdc, INT iItem, RECT* drawRect);
+
+static BOOL
+TAB_SendSimpleNotify (HWND hwnd, UINT code)
+{
+    NMHDR nmhdr;
+
+    nmhdr.hwndFrom = hwnd;
+    nmhdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
+    nmhdr.code = code;
+
+    return (BOOL) SendMessageA (GetParent (hwnd), WM_NOTIFY,
+            (WPARAM) nmhdr.idFrom, (LPARAM) &nmhdr);
+}
+
+static VOID
+TAB_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
+            WPARAM wParam, LPARAM lParam)
+{
+    MSG msg;
+
+    msg.hwnd = hwndMsg;
+    msg.message = uMsg;
+    msg.wParam = wParam;
+    msg.lParam = lParam;
+    msg.time = GetMessageTime ();
+    msg.pt.x = LOWORD(GetMessagePos ());
+    msg.pt.y = HIWORD(GetMessagePos ());
+
+    SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
+}
+
+static LRESULT
+TAB_GetCurSel (HWND hwnd)
+{
+    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+ 
+    return infoPtr->iSelected;
+}
+
+static LRESULT
+TAB_GetCurFocus (HWND hwnd)
+{
+    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+ 
+    return infoPtr->uFocus;
+}
+
+static LRESULT
+TAB_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+
+    if (infoPtr == NULL) return 0;
+    return infoPtr->hwndToolTip;
+}
+
+static LRESULT
+TAB_SetCurSel (HWND hwnd,WPARAM wParam)
+{
+    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  INT iItem = (INT)wParam;
+  INT prevItem;
+ 
+  prevItem = -1;
+  if ((iItem >= 0) && (iItem < infoPtr->uNumItem)) {
+    prevItem=infoPtr->iSelected;
+      infoPtr->iSelected=iItem;
+      TAB_EnsureSelectionVisible(hwnd, infoPtr);
+      TAB_InvalidateTabArea(hwnd, infoPtr);
+  }
+  return prevItem;
+}
+
+static LRESULT
+TAB_SetCurFocus (HWND hwnd,WPARAM wParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  INT iItem=(INT) wParam;
+ 
+  if ((iItem < 0) || (iItem >= infoPtr->uNumItem)) return 0;
+
+  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS) {
+    FIXME("Should set input focus\n");
+  } else { 
+    int oldFocus = infoPtr->uFocus;
+    if (infoPtr->iSelected != iItem || infoPtr->uFocus == -1 ) {
+      infoPtr->uFocus = iItem;
+      if (oldFocus != -1) {
+        if (TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)!=TRUE)  {
+          infoPtr->iSelected = iItem;
+          TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE);
+        }
+        else
+          infoPtr->iSelected = iItem;
+        TAB_EnsureSelectionVisible(hwnd, infoPtr);
+        TAB_InvalidateTabArea(hwnd, infoPtr);
+      }
+    }
+  }
+  return 0;
+}
+
+static LRESULT
+TAB_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+
+    if (infoPtr == NULL) return 0;
+    infoPtr->hwndToolTip = (HWND)wParam;
+    return 0;
+}
+
+/******************************************************************************
+ * TAB_InternalGetItemRect
+ *
+ * This method will calculate the rectangle representing a given tab item in
+ * client coordinates. This method takes scrolling into account.
+ *
+ * This method returns TRUE if the item is visible in the window and FALSE
+ * if it is completely outside the client area.
+ */
+static BOOL TAB_InternalGetItemRect(
+  HWND        hwnd,
+  TAB_INFO*   infoPtr,
+  INT         itemIndex,
+  RECT*       itemRect,
+  RECT*       selectedRect)
+{
+  RECT tmpItemRect,clientRect;
+  LONG        lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
+  
+  /* Perform a sanity check and a trivial visibility check. */
+  if ( (infoPtr->uNumItem <= 0) ||
+       (itemIndex >= infoPtr->uNumItem) ||
+       (!((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) && (itemIndex < infoPtr->leftmostVisible)) )
+    return FALSE;
+
+  /*
+   * Avoid special cases in this procedure by assigning the "out"
+   * parameters if the caller didn't supply them
+   */
+  if (itemRect == NULL)
+    itemRect = &tmpItemRect;
+  
+  /* Retrieve the unmodified item rect. */
+  *itemRect = infoPtr->items[itemIndex].rect;
+
+  /* calculate the times bottom and top based on the row */
+  GetClientRect(hwnd, &clientRect);
+
+  if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL))
+  {
+    itemRect->bottom = clientRect.bottom -
+                   SELECTED_TAB_OFFSET -
+                   itemRect->top * (infoPtr->tabHeight - 2) -
+                   ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : 0);
+
+    itemRect->top = clientRect.bottom -
+                   infoPtr->tabHeight -
+                   itemRect->top * (infoPtr->tabHeight - 2) -
+                   ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : 0);
+  }
+  else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL))
+  {
+    itemRect->right = clientRect.right - SELECTED_TAB_OFFSET - itemRect->left * (infoPtr->tabHeight - 2) -
+                      ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGY : 0);
+    itemRect->left = clientRect.right - infoPtr->tabHeight - itemRect->left * (infoPtr->tabHeight - 2) -
+                      ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGY : 0);
+  }
+  else if((lStyle & TCS_VERTICAL) && !(lStyle & TCS_BOTTOM))
+  {
+    itemRect->right = clientRect.left + infoPtr->tabHeight + itemRect->left * (infoPtr->tabHeight - 2) +
+                      ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGY : 0);
+    itemRect->left = clientRect.left + SELECTED_TAB_OFFSET + itemRect->left * (infoPtr->tabHeight - 2) +
+                      ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGY : 0);
+  }
+  else if(!(lStyle & TCS_VERTICAL) && !(lStyle & TCS_BOTTOM)) /* not TCS_BOTTOM and not TCS_VERTICAL */
+  {
+    itemRect->bottom = clientRect.top + 
+                      infoPtr->tabHeight +
+                      itemRect->top * (infoPtr->tabHeight - 2) +
+                      ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : 0);
+    itemRect->top = clientRect.top + 
+                   SELECTED_TAB_OFFSET +
+                   itemRect->top * (infoPtr->tabHeight - 2) +
+                   ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : 0);
+ }
+
+  /*
+   * "scroll" it to make sure the item at the very left of the 
+   * tab control is the leftmost visible tab.
+   */
+  if(lStyle & TCS_VERTICAL)
+  {
+    OffsetRect(itemRect,
+	     0,
+	     -(clientRect.bottom - infoPtr->items[infoPtr->leftmostVisible].rect.bottom));
+
+    /*
+     * Move the rectangle so the first item is slightly offset from
+     * the bottom of the tab control.
+     */
+    OffsetRect(itemRect,
+	     0,
+	     -SELECTED_TAB_OFFSET);
+
+  } else
+  {
+    OffsetRect(itemRect,
+	     -infoPtr->items[infoPtr->leftmostVisible].rect.left, 
+	     0);
+
+    /*
+     * Move the rectangle so the first item is slightly offset from
+     * the left of the tab control.
+     */
+    OffsetRect(itemRect,
+	     SELECTED_TAB_OFFSET,
+	     0);
+  }
+
+  /* Now, calculate the position of the item as if it were selected. */
+  if (selectedRect!=NULL)
+  {
+    CopyRect(selectedRect, itemRect);
+
+    /* The rectangle of a selected item is a bit wider. */
+    if(lStyle & TCS_VERTICAL)
+      InflateRect(selectedRect, 0, SELECTED_TAB_OFFSET);
+    else
+      InflateRect(selectedRect, SELECTED_TAB_OFFSET, 0);
+
+    /* If it also a bit higher. */
+    if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL))
+    {      
+      selectedRect->top -= 2; /* the border is thicker on the bottom */
+      selectedRect->bottom += SELECTED_TAB_OFFSET;
+    }
+    else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL))
+    {
+      selectedRect->left -= 2; /* the border is thicker on the right */
+      selectedRect->right += SELECTED_TAB_OFFSET;
+    }
+    else if(lStyle & TCS_VERTICAL)
+    {
+      selectedRect->left -= SELECTED_TAB_OFFSET;
+      selectedRect->right += 1;
+    }
+    else
+    {
+      selectedRect->top -= SELECTED_TAB_OFFSET;
+      selectedRect->bottom += 1;
+    }
+  }
+
+  return TRUE;
+}
+
+static BOOL TAB_GetItemRect(HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  return TAB_InternalGetItemRect(hwnd, TAB_GetInfoPtr(hwnd), (INT)wParam, 
+                                 (LPRECT)lParam, (LPRECT)NULL);
+}
+
+/******************************************************************************
+ * TAB_KeyUp
+ *
+ * This method is called to handle keyboard input
+ */
+static LRESULT TAB_KeyUp(
+  HWND   hwnd, 
+  WPARAM keyCode)
+{
+  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
+  int       newItem = -1;
+
+  switch (keyCode)
+  {
+    case VK_LEFT:
+      newItem = infoPtr->uFocus - 1;
+      break;
+    case VK_RIGHT:
+      newItem = infoPtr->uFocus + 1;
+      break;
+  }
+  
+  /*
+   * If we changed to a valid item, change the selection
+   */
+  if ((newItem >= 0) &&
+       (newItem < infoPtr->uNumItem) &&
+       (infoPtr->uFocus != newItem))
+  {
+    if (!TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING))
+    {
+      infoPtr->iSelected = newItem;
+      infoPtr->uFocus    = newItem;
+      TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE);
+
+      TAB_EnsureSelectionVisible(hwnd, infoPtr);
+      TAB_InvalidateTabArea(hwnd, infoPtr);
+    }
+  }
+
+  return 0;
+}
+
+/******************************************************************************
+ * TAB_FocusChanging
+ *
+ * This method is called whenever the focus goes in or out of this control
+ * it is used to update the visual state of the control.
+ */
+static LRESULT TAB_FocusChanging(
+  HWND   hwnd, 
+  UINT   uMsg, 
+  WPARAM wParam, 
+  LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  RECT      selectedRect;
+  BOOL      isVisible;
+
+  /*
+   * Get the rectangle for the item.
+   */
+  isVisible = TAB_InternalGetItemRect(hwnd,
+				      infoPtr,
+				      infoPtr->uFocus,
+				      NULL,
+				      &selectedRect);
+  
+  /*
+   * If the rectangle is not completely invisible, invalidate that
+   * portion of the window.
+   */
+  if (isVisible)
+  {
+    InvalidateRect(hwnd, &selectedRect, TRUE);
+  }
+
+  /*
+   * Don't otherwise disturb normal behavior.
+   */
+  return DefWindowProcA (hwnd, uMsg, wParam, lParam);
+}
+
+static HWND TAB_InternalHitTest (
+  HWND      hwnd,
+  TAB_INFO* infoPtr, 
+  POINT     pt, 
+  UINT*     flags)
+
+{
+  RECT rect;
+  int iCount; 
+  
+  for (iCount = 0; iCount < infoPtr->uNumItem; iCount++)
+  {
+    TAB_InternalGetItemRect(hwnd, infoPtr, iCount, &rect, NULL);
+
+    if (PtInRect(&rect, pt))
+    {
+      *flags = TCHT_ONITEM;
+      return iCount;
+    }
+  }
+
+  *flags = TCHT_NOWHERE;
+  return -1;
+}
+
+static LRESULT
+TAB_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  LPTCHITTESTINFO lptest = (LPTCHITTESTINFO) lParam;
+  
+  return TAB_InternalHitTest (hwnd, infoPtr, lptest->pt, &lptest->flags);
+}
+
+/******************************************************************************
+ * TAB_NCHitTest
+ *
+ * Napster v2b5 has a tab control for its main navigation which has a client
+ * area that covers the whole area of the dialog pages.
+ * That's why it receives all msgs for that area and the underlying dialog ctrls
+ * are dead.
+ * So I decided that we should handle WM_NCHITTEST here and return
+ * HTTRANSPARENT if we don't hit the tab control buttons.
+ * FIXME: WM_NCHITTEST handling correct ? Fix it if you know that Windows
+ * doesn't do it that way. Maybe depends on tab control styles ?
+ */
+static LRESULT
+TAB_NCHitTest (HWND hwnd, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  POINT pt;
+  UINT dummyflag;
+
+  pt.x = LOWORD(lParam);
+  pt.y = HIWORD(lParam);
+  ScreenToClient(hwnd, &pt);
+
+  if (TAB_InternalHitTest(hwnd, infoPtr, pt, &dummyflag) == -1)
+    return HTTRANSPARENT;
+  else
+    return HTCLIENT;
+}
+
+static LRESULT
+TAB_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  POINT pt;
+  INT newItem, dummy;
+
+  if (infoPtr->hwndToolTip)
+    TAB_RelayEvent (infoPtr->hwndToolTip, hwnd,
+		    WM_LBUTTONDOWN, wParam, lParam);
+
+  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_FOCUSONBUTTONDOWN ) {
+    SetFocus (hwnd);
+  }
+
+  if (infoPtr->hwndToolTip)
+    TAB_RelayEvent (infoPtr->hwndToolTip, hwnd,
+		    WM_LBUTTONDOWN, wParam, lParam);
+  
+  pt.x = (INT)LOWORD(lParam);
+  pt.y = (INT)HIWORD(lParam);
+  
+  newItem = TAB_InternalHitTest (hwnd, infoPtr, pt, &dummy);
+  
+  TRACE("On Tab, item %d\n", newItem);
+
+  if ((newItem != -1) && (infoPtr->iSelected != newItem))
+  {
+    if (TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING) != TRUE)
+    {
+      infoPtr->iSelected = newItem;
+      infoPtr->uFocus    = newItem;
+      TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE);
+
+      TAB_EnsureSelectionVisible(hwnd, infoPtr);
+
+      TAB_InvalidateTabArea(hwnd, infoPtr);
+    }
+  }
+  return 0;
+}
+
+static LRESULT
+TAB_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_SendSimpleNotify(hwnd, NM_CLICK);
+
+  return 0;
+}
+
+static LRESULT
+TAB_RButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_SendSimpleNotify(hwnd, NM_RCLICK);
+  return 0;
+}
+
+/******************************************************************************
+ * TAB_DrawLoneItemInterior
+ *
+ * This calls TAB_DrawItemInterior.  However, TAB_DrawItemInterior is normally
+ * called by TAB_DrawItem which is normally called by TAB_Refresh which sets
+ * up the device context and font.  This routine does the same setup but
+ * only calls TAB_DrawItemInterior for the single specified item.
+ */
+static void
+TAB_DrawLoneItemInterior(HWND hwnd, TAB_INFO* infoPtr, int iItem)
+{
+  HDC hdc = GetDC(hwnd);
+  HFONT hOldFont = SelectObject(hdc, infoPtr->hFont);
+  TAB_DrawItemInterior(hwnd, hdc, iItem, NULL);
+  SelectObject(hdc, hOldFont);
+  ReleaseDC(hwnd, hdc);
+}
+
+/******************************************************************************
+ * TAB_HotTrackTimerProc
+ *
+ * When a mouse-move event causes a tab to be highlighted (hot-tracking), a
+ * timer is setup so we can check if the mouse is moved out of our window.
+ * (We don't get an event when the mouse leaves, the mouse-move events just
+ * stop being delivered to our window and just start being delivered to
+ * another window.)  This function is called when the timer triggers so
+ * we can check if the mouse has left our window.  If so, we un-highlight
+ * the hot-tracked tab.
+ */
+static VOID CALLBACK
+TAB_HotTrackTimerProc
+  (
+  HWND hwnd,    /* handle of window for timer messages */
+  UINT uMsg,    /* WM_TIMER message */
+  UINT idEvent, /* timer identifier */
+  DWORD dwTime  /* current system time */
+  )
+{
+  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
+
+  if (infoPtr != NULL && infoPtr->iHotTracked >= 0)
+  {
+    POINT pt;
+
+    /*
+    ** If we can't get the cursor position, or if the cursor is outside our
+    ** window, we un-highlight the hot-tracked tab.  Note that the cursor is
+    ** "outside" even if it is within our bounding rect if another window
+    ** overlaps.  Note also that the case where the cursor stayed within our
+    ** window but has moved off the hot-tracked tab will be handled by the
+    ** WM_MOUSEMOVE event. 
+    */
+    if (!GetCursorPos(&pt) || WindowFromPoint(pt) != hwnd)
+    {
+      /* Redraw iHotTracked to look normal */
+      INT iRedraw = infoPtr->iHotTracked;
+      infoPtr->iHotTracked = -1;
+      TAB_DrawLoneItemInterior(hwnd, infoPtr, iRedraw);
+
+      /* Kill this timer */
+      KillTimer(hwnd, TAB_HOTTRACK_TIMER);
+    }
+  }
+}
+
+/******************************************************************************
+ * TAB_RecalcHotTrack
+ *
+ * If a tab control has the TCS_HOTTRACK style, then the tab under the mouse
+ * should be highlighted.  This function determines which tab in a tab control,
+ * if any, is under the mouse and records that information.  The caller may
+ * supply output parameters to receive the item number of the tab item which
+ * was highlighted but isn't any longer and of the tab item which is now
+ * highlighted but wasn't previously.  The caller can use this information to
+ * selectively redraw those tab items.
+ *
+ * If the caller has a mouse position, it can supply it through the pos
+ * parameter.  For example, TAB_MouseMove does this.  Otherwise, the caller
+ * supplies NULL and this function determines the current mouse position
+ * itself.
+ */
+static void
+TAB_RecalcHotTrack
+  (
+  HWND            hwnd,
+  const LPARAM*   pos,
+  int*            out_redrawLeave,
+  int*            out_redrawEnter
+  )
+{
+  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
+
+  int item = -1;
+
+
+  if (out_redrawLeave != NULL)
+    *out_redrawLeave = -1;
+  if (out_redrawEnter != NULL)
+    *out_redrawEnter = -1;
+
+  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_HOTTRACK)
+  {
+    POINT pt;
+    UINT  flags;
+
+    if (pos == NULL)
+    {
+      GetCursorPos(&pt);
+      ScreenToClient(hwnd, &pt);
+    }
+    else
+    {
+      pt.x = LOWORD(*pos);
+      pt.y = HIWORD(*pos);
+    }
+
+    item = TAB_InternalHitTest(hwnd, infoPtr, pt, &flags);
+  }
+
+  if (item != infoPtr->iHotTracked)
+  {
+    if (infoPtr->iHotTracked >= 0)
+    {
+      /* Mark currently hot-tracked to be redrawn to look normal */
+      if (out_redrawLeave != NULL)
+        *out_redrawLeave = infoPtr->iHotTracked;
+
+      if (item < 0)
+      {
+        /* Kill timer which forces recheck of mouse pos */
+        KillTimer(hwnd, TAB_HOTTRACK_TIMER);
+      }
+    }
+    else
+    {
+      /* Start timer so we recheck mouse pos */
+      UINT timerID = SetTimer
+        (
+        hwnd,
+        TAB_HOTTRACK_TIMER,
+        TAB_HOTTRACK_TIMER_INTERVAL,
+        TAB_HotTrackTimerProc
+        );
+
+      if (timerID == 0)
+        return; /* Hot tracking not available */
+    }
+
+    infoPtr->iHotTracked = item;
+
+    if (item >= 0)
+    {
+	/* Mark new hot-tracked to be redrawn to look highlighted */
+      if (out_redrawEnter != NULL)
+        *out_redrawEnter = item;
+    }
+  }
+}
+
+/******************************************************************************
+ * TAB_MouseMove
+ *
+ * Handles the mouse-move event.  Updates tooltips.  Updates hot-tracking.
+ */
+static LRESULT
+TAB_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  int redrawLeave;
+  int redrawEnter;
+
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+
+  if (infoPtr->hwndToolTip)
+    TAB_RelayEvent (infoPtr->hwndToolTip, hwnd,
+		    WM_LBUTTONDOWN, wParam, lParam);
+
+  /* Determine which tab to highlight.  Redraw tabs which change highlight
+  ** status. */
+  TAB_RecalcHotTrack(hwnd, &lParam, &redrawLeave, &redrawEnter);
+
+  if (redrawLeave != -1)
+    TAB_DrawLoneItemInterior(hwnd, infoPtr, redrawLeave);
+  if (redrawEnter != -1)
+    TAB_DrawLoneItemInterior(hwnd, infoPtr, redrawEnter);
+
+  return 0;
+}
+
+/******************************************************************************
+ * TAB_AdjustRect
+ *
+ * Calculates the tab control's display area given the window rectangle or
+ * the window rectangle given the requested display rectangle.
+ */
+static LRESULT TAB_AdjustRect(
+  HWND   hwnd, 
+  WPARAM fLarger, 
+  LPRECT prc)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+
+  if(lStyle & TCS_VERTICAL)
+  {
+    if (fLarger) /* Go from display rectangle */
+    {
+      /* Add the height of the tabs. */
+      if (lStyle & TCS_BOTTOM)
+        prc->right += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+      else
+        prc->left -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+
+      /* FIXME: not sure if these InflateRect's need to have different values for TCS_VERTICAL */
+      /* Inflate the rectangle for the padding */
+      InflateRect(prc, DISPLAY_AREA_PADDINGX, DISPLAY_AREA_PADDINGY);
+
+      /* Inflate for the border */
+      InflateRect(prc, CONTROL_BORDER_SIZEX, CONTROL_BORDER_SIZEX);
+    }
+    else /* Go from window rectangle. */
+    {
+      /* FIXME: not sure if these InflateRect's need to have different values for TCS_VERTICAL */
+      /* Deflate the rectangle for the border */
+      InflateRect(prc, -CONTROL_BORDER_SIZEX, -CONTROL_BORDER_SIZEX);
+
+      /* Deflate the rectangle for the padding */
+      InflateRect(prc, -DISPLAY_AREA_PADDINGX, -DISPLAY_AREA_PADDINGY);
+
+      /* Remove the height of the tabs. */
+      if (lStyle & TCS_BOTTOM)
+        prc->right -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+      else
+        prc->left += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+    }
+  }
+  else {
+    if (fLarger) /* Go from display rectangle */
+    {
+      /* Add the height of the tabs. */
+      if (lStyle & TCS_BOTTOM)
+        prc->bottom += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+      else
+        prc->top -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+
+      /* Inflate the rectangle for the padding */
+      InflateRect(prc, DISPLAY_AREA_PADDINGX, DISPLAY_AREA_PADDINGY);
+
+      /* Inflate for the border */
+      InflateRect(prc, CONTROL_BORDER_SIZEX, CONTROL_BORDER_SIZEX);
+    }
+    else /* Go from window rectangle. */
+    {
+      /* Deflate the rectangle for the border */
+      InflateRect(prc, -CONTROL_BORDER_SIZEX, -CONTROL_BORDER_SIZEX);
+
+      /* Deflate the rectangle for the padding */
+      InflateRect(prc, -DISPLAY_AREA_PADDINGX, -DISPLAY_AREA_PADDINGY);
+
+      /* Remove the height of the tabs. */
+      if (lStyle & TCS_BOTTOM)
+        prc->bottom -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+      else
+        prc->top += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+    }
+  }
+
+  return 0;
+}
+
+/******************************************************************************
+ * TAB_OnHScroll
+ *
+ * This method will handle the notification from the scroll control and
+ * perform the scrolling operation on the tab control.
+ */
+static LRESULT TAB_OnHScroll(
+  HWND    hwnd, 
+  int     nScrollCode,
+  int     nPos,
+  HWND    hwndScroll)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+
+  if(nScrollCode == SB_THUMBPOSITION && nPos != infoPtr->leftmostVisible)
+  {
+     if(nPos < infoPtr->leftmostVisible)
+        infoPtr->leftmostVisible--;
+     else
+        infoPtr->leftmostVisible++;
+
+     TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
+     TAB_InvalidateTabArea(hwnd, infoPtr);
+     SendMessageA(infoPtr->hwndUpDown, UDM_SETPOS, 0,
+                   MAKELONG(infoPtr->leftmostVisible, 0));
+   }
+
+   return 0;
+}
+
+/******************************************************************************
+ * TAB_SetupScrolling
+ *
+ * This method will check the current scrolling state and make sure the 
+ * scrolling control is displayed (or not).
+ */
+static void TAB_SetupScrolling(
+  HWND        hwnd,
+  TAB_INFO*   infoPtr,
+  const RECT* clientRect)
+{
+  INT maxRange = 0;
+  DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+
+  if (infoPtr->needsScrolling)
+  {
+    RECT controlPos;
+    INT vsize, tabwidth;
+
+    /*
+     * Calculate the position of the scroll control.
+     */
+    if(lStyle & TCS_VERTICAL)
+    {
+      controlPos.right = clientRect->right;
+      controlPos.left  = controlPos.right - 2 * GetSystemMetrics(SM_CXHSCROLL);
+
+      if (lStyle & TCS_BOTTOM)
+      {
+        controlPos.top    = clientRect->bottom - infoPtr->tabHeight;
+        controlPos.bottom = controlPos.top + GetSystemMetrics(SM_CYHSCROLL);
+      }
+      else
+      {
+        controlPos.bottom = clientRect->top + infoPtr->tabHeight;
+        controlPos.top    = controlPos.bottom - GetSystemMetrics(SM_CYHSCROLL);
+      }
+    }
+    else
+    {
+      controlPos.right = clientRect->right;
+      controlPos.left  = controlPos.right - 2 * GetSystemMetrics(SM_CXHSCROLL);
+
+      if (lStyle & TCS_BOTTOM)
+      {
+        controlPos.top    = clientRect->bottom - infoPtr->tabHeight;
+        controlPos.bottom = controlPos.top + GetSystemMetrics(SM_CYHSCROLL);
+      }
+      else
+      {
+        controlPos.bottom = clientRect->top + infoPtr->tabHeight;
+        controlPos.top    = controlPos.bottom - GetSystemMetrics(SM_CYHSCROLL);
+      }
+    }
+
+    /*
+     * If we don't have a scroll control yet, we want to create one.
+     * If we have one, we want to make sure it's positioned properly.
+     */
+    if (infoPtr->hwndUpDown==0)
+    {
+      infoPtr->hwndUpDown = CreateWindowA("msctls_updown32",
+					  "",
+					  WS_VISIBLE | WS_CHILD | UDS_HORZ,
+					  controlPos.left, controlPos.top,
+					  controlPos.right - controlPos.left,
+					  controlPos.bottom - controlPos.top,
+					  hwnd,
+					  (HMENU)NULL, 
+					  (HINSTANCE)NULL, 
+					  NULL);	
+    }
+    else
+    {
+      SetWindowPos(infoPtr->hwndUpDown, 
+		   (HWND)NULL,
+		   controlPos.left, controlPos.top,
+		   controlPos.right - controlPos.left,
+		   controlPos.bottom - controlPos.top,
+		   SWP_SHOWWINDOW | SWP_NOZORDER);		   
+    }
+
+    /* Now calculate upper limit of the updown control range.
+     * We do this by calculating how many tabs will be offscreen when the
+     * last tab is visible.
+     */
+    if(infoPtr->uNumItem)
+    {
+       vsize = clientRect->right - (controlPos.right - controlPos.left + 1);
+       maxRange = infoPtr->uNumItem;
+       tabwidth = infoPtr->items[maxRange - 1].rect.right;
+
+       for(; maxRange > 0; maxRange--)
+       {
+          if(tabwidth - infoPtr->items[maxRange - 1].rect.left > vsize)
+             break;
+       }
+
+       if(maxRange == infoPtr->uNumItem)
+          maxRange--;
+    }
+  }
+  else
+  {
+    /* If we once had a scroll control... hide it */
+    if (infoPtr->hwndUpDown!=0)
+      ShowWindow(infoPtr->hwndUpDown, SW_HIDE);
+  }
+  if (infoPtr->hwndUpDown)
+     SendMessageA(infoPtr->hwndUpDown, UDM_SETRANGE32, 0, maxRange);
+}
+
+/******************************************************************************
+ * TAB_SetItemBounds
+ *
+ * This method will calculate the position rectangles of all the items in the
+ * control. The rectangle calculated starts at 0 for the first item in the
+ * list and ignores scrolling and selection.
+ * It also uses the current font to determine the height of the tab row and
+ * it checks if all the tabs fit in the client area of the window. If they
+ * dont, a scrolling control is added.
+ */
+static void TAB_SetItemBounds (HWND hwnd)
+{
+  TAB_INFO*   infoPtr = TAB_GetInfoPtr(hwnd);
+  LONG        lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
+  TEXTMETRICA fontMetrics;
+  INT         curItem;
+  INT         curItemLeftPos;
+  INT         curItemRowCount;
+  HFONT       hFont, hOldFont;
+  HDC         hdc;
+  RECT        clientRect;
+  SIZE        size;
+  INT         iTemp;
+  RECT*       rcItem;
+  INT         iIndex;
+
+  /*
+   * We need to get text information so we need a DC and we need to select
+   * a font.
+   */
+  hdc = GetDC(hwnd); 
+    
+  hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
+  hOldFont = SelectObject (hdc, hFont);
+
+  /*
+   * We will base the rectangle calculations on the client rectangle
+   * of the control.
+   */
+  GetClientRect(hwnd, &clientRect);
+
+  /* if TCS_VERTICAL then swap the height and width so this code places the
+     tabs along the top of the rectangle and we can just rotate them after 
+     rather than duplicate all of the below code */
+  if(lStyle & TCS_VERTICAL)
+  {
+     iTemp = clientRect.bottom;
+     clientRect.bottom = clientRect.right;
+     clientRect.right = iTemp;
+  }
+
+  /* The leftmost item will be "0" aligned */
+  curItemLeftPos = 0;
+  curItemRowCount = infoPtr->uNumItem ? 1 : 0;
+
+  if (!(lStyle & TCS_FIXEDWIDTH) && !((lStyle & TCS_OWNERDRAWFIXED) && infoPtr->fSizeSet) )
+  {
+    int item_height;
+    int icon_height = 0;
+
+    /* Use the current font to determine the height of a tab. */
+    GetTextMetricsA(hdc, &fontMetrics);
+
+    /* Get the icon height */
+    if (infoPtr->himl)
+      ImageList_GetIconSize(infoPtr->himl, 0, &icon_height);
+
+    /* Take the highest between font or icon */
+    if (fontMetrics.tmHeight > icon_height)
+      item_height = fontMetrics.tmHeight;
+    else
+      item_height = icon_height;
+
+    /*
+     * Make sure there is enough space for the letters + icon + growing the 
+     * selected item + extra space for the selected item.   
+     */
+    infoPtr->tabHeight = item_height + 2 * VERTICAL_ITEM_PADDING +
+        SELECTED_TAB_OFFSET;
+
+  }
+
+  for (curItem = 0; curItem < infoPtr->uNumItem; curItem++)
+  {
+    /* Set the leftmost position of the tab. */
+    infoPtr->items[curItem].rect.left = curItemLeftPos;
+
+    if ( (lStyle & TCS_FIXEDWIDTH) || ((lStyle & TCS_OWNERDRAWFIXED) && infoPtr->fSizeSet))
+    {
+      infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left +
+                                           infoPtr->tabWidth +
+                                           2 * HORIZONTAL_ITEM_PADDING;
+    }
+    else
+    {
+      int icon_width  = 0;
+      int num = 2;
+
+      /* Calculate how wide the tab is depending on the text it contains */
+      GetTextExtentPoint32W(hdc, infoPtr->items[curItem].pszText,
+                            lstrlenW(infoPtr->items[curItem].pszText), &size);
+
+      /* under Windows, there seems to be a minimum width of 2x the height
+       * for button style tabs */
+      if (lStyle & TCS_BUTTONS)
+	      size.cx = max(size.cx, 2 * (infoPtr->tabHeight - 2));
+
+      /* Add the icon width */
+      if (infoPtr->himl)
+      {
+        ImageList_GetIconSize(infoPtr->himl, &icon_width, 0);
+        num++;
+      }
+
+      infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left +
+                                           size.cx + icon_width + 
+                                           num * HORIZONTAL_ITEM_PADDING;
+    }
+
+    /*
+     * Check if this is a multiline tab control and if so
+     * check to see if we should wrap the tabs
+     *
+     * Because we are going to arange all these tabs evenly
+     * really we are basically just counting rows at this point
+     *
+     */
+
+    if (((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) &&
+        (infoPtr->items[curItem].rect.right > clientRect.right))
+    {
+        infoPtr->items[curItem].rect.right -=
+                                      infoPtr->items[curItem].rect.left;
+
+	infoPtr->items[curItem].rect.left = 0;
+        curItemRowCount++;
+    }
+
+    infoPtr->items[curItem].rect.bottom = 0;
+    infoPtr->items[curItem].rect.top = curItemRowCount - 1;
+
+    TRACE("TextSize: %li\n", size.cx);
+    TRACE("Rect: T %i, L %i, B %i, R %i\n", 
+	  infoPtr->items[curItem].rect.top,
+	  infoPtr->items[curItem].rect.left,
+	  infoPtr->items[curItem].rect.bottom,
+	  infoPtr->items[curItem].rect.right);  
+
+    /*
+     * The leftmost position of the next item is the rightmost position
+     * of this one.
+     */
+    if (lStyle & TCS_BUTTONS)
+    {
+      curItemLeftPos = infoPtr->items[curItem].rect.right + 1;
+      if (lStyle & TCS_FLATBUTTONS)
+        curItemLeftPos += FLAT_BTN_SPACINGX;
+    }
+    else
+      curItemLeftPos = infoPtr->items[curItem].rect.right;
+  }
+
+  if (!((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)))
+  {
+    /*
+     * Check if we need a scrolling control.
+     */
+    infoPtr->needsScrolling = (curItemLeftPos + (2 * SELECTED_TAB_OFFSET) >
+                               clientRect.right);
+
+    /* Don't need scrolling, then update infoPtr->leftmostVisible */
+    if(!infoPtr->needsScrolling)
+      infoPtr->leftmostVisible = 0; 
+
+    TAB_SetupScrolling(hwnd, infoPtr, &clientRect);
+  }
+
+  /* Set the number of rows */
+  infoPtr->uNumRows = curItemRowCount;
+
+   if (((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) && (infoPtr->uNumItem > 0))
+   {
+      INT widthDiff, remainder;
+      INT tabPerRow,remTab;
+      INT iRow,iItm;
+      INT iIndexStart=0,iIndexEnd=0, iCount=0;
+
+      /*
+       * Ok Microsoft trys to even out the rows. place the same
+       * number of tabs in each row. So lets give that a shot
+       *
+       */
+
+      tabPerRow = infoPtr->uNumItem / (infoPtr->uNumRows);
+      remTab = infoPtr->uNumItem % (infoPtr->uNumRows);
+
+      for (iItm=0,iRow=0,iCount=0,curItemLeftPos=0;
+           iItm<infoPtr->uNumItem;
+           iItm++,iCount++)
+      {
+          /* if we have reached the maximum number of tabs on this row */
+          /* move to the next row, reset our current item left position and */
+          /* the count of items on this row */
+          if (iCount >= ((iRow<remTab)?tabPerRow + 1:tabPerRow))
+          {
+              iRow++;
+              curItemLeftPos = 0;
+              iCount = 0;
+          }
+
+          /* normalize the current rect */
+
+          /* shift the item to the left side of the clientRect */
+          infoPtr->items[iItm].rect.right -= 
+            infoPtr->items[iItm].rect.left;
+          infoPtr->items[iItm].rect.left = 0;
+
+          /* shift the item to the right to place it as the next item in this row */
+          infoPtr->items[iItm].rect.left += curItemLeftPos;
+          infoPtr->items[iItm].rect.right += curItemLeftPos;
+          infoPtr->items[iItm].rect.top = iRow;
+          if (lStyle & TCS_BUTTONS)
+	  {
+            curItemLeftPos = infoPtr->items[iItm].rect.right + 1;
+            if (lStyle & TCS_FLATBUTTONS)
+	      curItemLeftPos += FLAT_BTN_SPACINGX;
+	  }
+          else
+            curItemLeftPos = infoPtr->items[iItm].rect.right;
+      }
+          
+      /*
+       * Justify the rows
+       */
+      {
+         while(iIndexStart < infoPtr->uNumItem)
+        {
+        /* 
+         * find the indexs of the row
+         */
+        /* find the first item on the next row */
+        for (iIndexEnd=iIndexStart;
+             (iIndexEnd < infoPtr->uNumItem) && 
+ 	       (infoPtr->items[iIndexEnd].rect.top ==
+                infoPtr->items[iIndexStart].rect.top) ;
+            iIndexEnd++)
+        /* intentionaly blank */;
+
+        /* 
+         * we need to justify these tabs so they fill the whole given
+         * client area
+         *
+         */
+        /* find the amount of space remaining on this row */
+        widthDiff = clientRect.right - (2 * SELECTED_TAB_OFFSET) -
+                            infoPtr->items[iIndexEnd - 1].rect.right;
+
+        /* iCount is the number of tab items on this row */
+        iCount = iIndexEnd - iIndexStart;
+
+
+        if (iCount > 1)
+        {
+           remainder = widthDiff % iCount;
+           widthDiff = widthDiff / iCount;
+           /* add widthDiff/iCount, or extra space/items on row, to each item on this row */
+           for (iIndex=iIndexStart,iCount=0; iIndex < iIndexEnd; 
+                iIndex++,iCount++)
+           {
+              infoPtr->items[iIndex].rect.left += iCount * widthDiff;
+              infoPtr->items[iIndex].rect.right += (iCount + 1) * widthDiff;
+           }
+           infoPtr->items[iIndex - 1].rect.right += remainder;
+        }
+        else /* we have only one item on this row, make it take up the entire row */
+        {
+          infoPtr->items[iIndexStart].rect.left = clientRect.left;
+          infoPtr->items[iIndexStart].rect.right = clientRect.right - 4;
+        }
+
+
+        iIndexStart = iIndexEnd;
+        }
+      }
+  }
+
+  /* if TCS_VERTICAL rotate the tabs so they are along the side of the clientRect */
+  if(lStyle & TCS_VERTICAL)
+  {
+    RECT rcOriginal;
+    for(iIndex = 0; iIndex < infoPtr->uNumItem; iIndex++)
+    {
+      rcItem = &(infoPtr->items[iIndex].rect);
+
+      rcOriginal = *rcItem;
+
+      /* this is rotating the items by 90 degrees around the center of the control */
+      rcItem->top = (clientRect.right - (rcOriginal.left - clientRect.left)) - (rcOriginal.right - rcOriginal.left);
+      rcItem->bottom = rcItem->top + (rcOriginal.right - rcOriginal.left);
+      rcItem->left = rcOriginal.top;
+      rcItem->right = rcOriginal.bottom;
+    }
+  }
+
+  TAB_EnsureSelectionVisible(hwnd,infoPtr);
+  TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
+
+  /* Cleanup */
+  SelectObject (hdc, hOldFont);
+  ReleaseDC (hwnd, hdc);
+}
+
+/******************************************************************************
+ * TAB_DrawItemInterior
+ *
+ * This method is used to draw the interior (text and icon) of a single tab
+ * into the tab control.
+ */         
+static void
+TAB_DrawItemInterior
+  (
+  HWND        hwnd,
+  HDC         hdc,
+  INT         iItem,
+  RECT*       drawRect
+  )
+{
+  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
+  LONG      lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
+
+  RECT localRect;
+
+  HPEN   htextPen   = GetSysColorPen (COLOR_BTNTEXT);
+  HPEN   holdPen;
+  INT    oldBkMode;
+
+  if (drawRect == NULL)
+  {
+    BOOL isVisible;
+    RECT itemRect;
+    RECT selectedRect;
+
+    /*
+     * Get the rectangle for the item.
+     */
+    isVisible = TAB_InternalGetItemRect(hwnd, infoPtr, iItem, &itemRect, &selectedRect);
+    if (!isVisible)
+      return;
+
+    /*
+     * Make sure drawRect points to something valid; simplifies code.
+     */
+    drawRect = &localRect;
+
+    /*
+     * This logic copied from the part of TAB_DrawItem which draws
+     * the tab background.  It's important to keep it in sync.  I
+     * would have liked to avoid code duplication, but couldn't figure
+     * out how without making spaghetti of TAB_DrawItem.
+     */
+    if (lStyle & TCS_BUTTONS)
+    {
+      *drawRect = itemRect;
+      if (iItem == infoPtr->iSelected)
+      {
+        drawRect->right--;
+        drawRect->bottom--;
+      }
+    }
+    else
+    {
+      if (iItem == infoPtr->iSelected)
+        *drawRect = selectedRect;
+      else
+        *drawRect = itemRect;
+      drawRect->right--;
+      drawRect->bottom--;
+    }
+  }
+
+  /*
+   * Text pen
+   */
+  holdPen = SelectObject(hdc, htextPen);
+
+  oldBkMode = SetBkMode(hdc, TRANSPARENT);
+  SetTextColor(hdc, GetSysColor((iItem == infoPtr->iHotTracked) ? COLOR_HIGHLIGHT : COLOR_BTNTEXT));
+
+  /*
+   * 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);
+
+
+  /*
+   * if owner draw, tell the owner to draw
+   */
+  if ((lStyle & TCS_OWNERDRAWFIXED) && GetParent(hwnd))
+  {
+    DRAWITEMSTRUCT dis;
+    UINT id;
+
+    /*
+     * get the control id
+     */
+    id = GetWindowLongA( hwnd, GWL_ID );
+
+    /* 
+     * put together the DRAWITEMSTRUCT
+     */
+    dis.CtlType    = ODT_TAB;	
+    dis.CtlID      = id;		
+    dis.itemID     = iItem;		
+    dis.itemAction = ODA_DRAWENTIRE;	
+    if ( iItem == infoPtr->iSelected )
+      dis.itemState = ODS_SELECTED;	
+    else				
+      dis.itemState = 0;		
+    dis.hwndItem = hwnd;		/* */
+    dis.hDC      = hdc;		
+    dis.rcItem   = *drawRect;		/* */
+    dis.itemData = infoPtr->items[iItem].lParam;
+
+    /*
+     * send the draw message
+     */
+    SendMessageA( GetParent(hwnd), WM_DRAWITEM, (WPARAM)id, (LPARAM)&dis );
+  }
+  else
+  {
+    INT cx;
+    INT cy;
+    UINT uHorizAlign;
+    RECT rcTemp;
+    RECT rcImage;
+    LOGFONTA logfont;
+    HFONT hFont = 0;
+    HFONT hOldFont = 0; /* stop uninitialized warning */
+
+    INT nEscapement = 0; /* stop uninitialized warning */
+    INT nOrientation = 0; /* stop uninitialized warning */
+    INT iPointSize;
+
+    /* used to center the icon and text in the tab */
+    RECT rcText;
+    INT center_offset;
+
+    /* set rcImage to drawRect, we will use top & left in our ImageList_Draw call */
+    rcImage = *drawRect;
+
+    rcTemp = *drawRect;
+
+    /*
+     * Setup for text output
+     */
+    oldBkMode = SetBkMode(hdc, TRANSPARENT);
+    SetTextColor(hdc, GetSysColor((iItem == infoPtr->iHotTracked) ? COLOR_HIGHLIGHT : COLOR_BTNTEXT));
+
+    /* get the rectangle that the text fits in */
+    DrawTextW(hdc, infoPtr->items[iItem].pszText, -1,
+              &rcText, DT_CALCRECT);
+    rcText.right += 4;
+    /*
+     * If not owner draw, then do the drawing ourselves.
+     *
+     * Draw the icon.
+     */
+    if (infoPtr->himl && (infoPtr->items[iItem].mask & TCIF_IMAGE))
+    {
+      ImageList_GetIconSize(infoPtr->himl, &cx, &cy);
+
+      if(lStyle & TCS_VERTICAL)
+        center_offset = ((drawRect->bottom - drawRect->top) - (cy + VERTICAL_ITEM_PADDING + (rcText.right - rcText.left))) / 2;
+      else
+        center_offset = ((drawRect->right - drawRect->left) - (cx + HORIZONTAL_ITEM_PADDING + (rcText.right - rcText.left))) / 2;
+
+      if((lStyle & TCS_VERTICAL) && (lStyle & TCS_BOTTOM))
+      {
+        /* rcImage.left = drawRect->left; */ /* explicit from above rcImage = *drawRect */
+        rcImage.top = drawRect->top + center_offset;
+        rcImage.left = drawRect->right - cx; /* if tab is TCS_VERTICAL and TCS_BOTTOM, the text is drawn from the */
+                                             /* 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 + VERTICAL_ITEM_PADDING);
+      }
+      else if(lStyle & TCS_VERTICAL)
+      {
+        /* rcImage.left = drawRect->left; */ /* explicit from above rcImage = *drawRect */
+        rcImage.top = drawRect->bottom - cy - center_offset;
+
+        drawRect->bottom = rcImage.top - VERTICAL_ITEM_PADDING;
+      }
+      else /* normal style, whether TCS_BOTTOM or not */
+      {
+        rcImage.left = drawRect->left + center_offset;
+        /* rcImage.top = drawRect->top; */ /* explicit from above rcImage = *drawRect */
+
+        drawRect->left = rcImage.left + cx + HORIZONTAL_ITEM_PADDING;
+      }
+
+      ImageList_Draw
+        (
+        infoPtr->himl,
+        infoPtr->items[iItem].iImage,
+        hdc,
+        rcImage.left,
+        rcImage.top + 1,
+        ILD_NORMAL
+        );
+    } else /* no image, so just shift the drawRect borders around */
+    {
+      if(lStyle & TCS_VERTICAL)
+      {
+        center_offset = 0;
+        /*
+        currently the rcText rect is flawed because the rotated font does not
+        often match the horizontal font. So leave this as 0
+        ((drawRect->bottom - drawRect->top) - (rcText.right - rcText.left)) / 2;
+        */
+        if(lStyle & TCS_BOTTOM)
+          drawRect->top+=center_offset;
+        else
+          drawRect->bottom-=center_offset;
+      }
+      else
+      {
+        center_offset = ((drawRect->right - drawRect->left) - (rcText.right - rcText.left)) / 2;
+        drawRect->left+=center_offset;
+      }
+    }
+
+    /* Draw the text */
+    if (lStyle & TCS_RIGHTJUSTIFY)
+      uHorizAlign = DT_CENTER;
+    else
+      uHorizAlign = DT_LEFT;
+
+    if(lStyle & TCS_VERTICAL) /* if we are vertical rotate the text and each character */
+    {
+      if(lStyle & TCS_BOTTOM)
+      {
+        nEscapement = -900;
+        nOrientation = -900;
+      }
+      else
+      {
+        nEscapement = 900;
+        nOrientation = 900;
+      }
+    }
+
+    /* to get a font with the escapement and orientation we are looking for, we need to */
+    /* call CreateFontIndirectA, which requires us to set the values of the logfont we pass in */
+    if(lStyle & TCS_VERTICAL)
+    {
+      if (!GetObjectA((infoPtr->hFont) ? 
+                infoPtr->hFont : GetStockObject(SYSTEM_FONT),
+                sizeof(LOGFONTA),&logfont))
+      {
+        iPointSize = 9;
+
+        lstrcpyA(logfont.lfFaceName, "Arial");
+        logfont.lfHeight = -MulDiv(iPointSize, GetDeviceCaps(hdc, LOGPIXELSY), 
+                                    72);
+        logfont.lfWeight = FW_NORMAL;
+        logfont.lfItalic = 0;
+        logfont.lfUnderline = 0;
+        logfont.lfStrikeOut = 0;
+      }
+
+      logfont.lfEscapement = nEscapement;
+      logfont.lfOrientation = nOrientation;
+      hFont = CreateFontIndirectA(&logfont);
+      hOldFont = SelectObject(hdc, hFont);
+    }
+
+    if (lStyle & TCS_VERTICAL)
+    {
+      ExtTextOutW(hdc,
+      (lStyle & TCS_BOTTOM) ? drawRect->right : drawRect->left,
+      (!(lStyle & TCS_BOTTOM)) ? drawRect->bottom : drawRect->top,
+      ETO_CLIPPED,
+      drawRect,
+      infoPtr->items[iItem].pszText,
+      lstrlenW(infoPtr->items[iItem].pszText),
+      0);
+    }
+    else
+    {
+      DrawTextW
+      (
+        hdc,
+        infoPtr->items[iItem].pszText,
+        lstrlenW(infoPtr->items[iItem].pszText),
+        drawRect,
+        uHorizAlign | DT_SINGLELINE
+        );
+    }
+
+    /* clean things up */
+    *drawRect = rcTemp; /* restore drawRect */
+
+    if(lStyle & TCS_VERTICAL)
+    {
+      SelectObject(hdc, hOldFont); /* restore the original font */
+      if (hFont)
+        DeleteObject(hFont);
+    }
+  }
+
+  /*
+  * Cleanup
+  */
+  SetBkMode(hdc, oldBkMode);
+  SelectObject(hdc, holdPen);
+}
+
+/******************************************************************************
+ * TAB_DrawItem
+ *
+ * This method is used to draw a single tab into the tab control.
+ */         
+static void TAB_DrawItem(
+  HWND hwnd, 
+  HDC  hdc, 
+  INT  iItem)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  LONG      lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
+  RECT      itemRect;
+  RECT      selectedRect;
+  BOOL      isVisible;
+  RECT      r;
+
+  /*
+   * Get the rectangle for the item.
+   */
+  isVisible = TAB_InternalGetItemRect(hwnd,
+				      infoPtr,
+				      iItem,
+				      &itemRect,
+				      &selectedRect);
+
+  if (isVisible)
+  {
+    HBRUSH hbr       = CreateSolidBrush (GetSysColor(COLOR_BTNFACE));    
+    HPEN   hwPen     = GetSysColorPen (COLOR_3DHILIGHT);
+    HPEN hbPen  = GetSysColorPen (COLOR_3DDKSHADOW);
+    HPEN hShade = GetSysColorPen (COLOR_BTNSHADOW);
+
+    HPEN   holdPen;
+    BOOL   deleteBrush = TRUE;
+
+    if (lStyle & TCS_BUTTONS)
+    {
+      /* Get item rectangle */
+      r = itemRect;
+
+      holdPen = SelectObject (hdc, hwPen);
+
+      /* Separators between flat buttons */
+      /* FIXME: test and correct this if necessary for TCS_FLATBUTTONS style */
+      if (lStyle & TCS_FLATBUTTONS) 
+      {
+        int x = r.right + FLAT_BTN_SPACINGX - 2;
+
+        /* highlight */
+        MoveToEx (hdc, x, r.bottom - 1, NULL);
+        LineTo   (hdc, x, r.top - 1);
+        x--;
+
+        /* shadow */
+        SelectObject(hdc, hbPen);
+        MoveToEx (hdc, x, r.bottom - 1, NULL);
+        LineTo   (hdc, x, r.top - 1);
+
+        /* shade */
+        SelectObject (hdc, hShade );
+        MoveToEx (hdc, x - 1, r.bottom - 1, NULL);
+        LineTo   (hdc, x - 1, r.top - 1);
+      }
+
+      if (iItem == infoPtr->iSelected)
+      {
+        /* Background color */
+        if (!((lStyle & TCS_OWNERDRAWFIXED) && infoPtr->fSizeSet))
+	{
+              COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
+              DeleteObject(hbr);
+              hbr = GetSysColorBrush(COLOR_SCROLLBAR);
+
+              SetTextColor(hdc, GetSysColor(COLOR_3DFACE));
+              SetBkColor(hdc, bk);
+
+              /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
+               * we better use 0x55aa bitmap brush to make scrollbar's background
+               * look different from the window background.
+               */
+               if (bk == GetSysColor(COLOR_WINDOW))
+                  hbr = COMCTL32_hPattern55AABrush;
+
+              deleteBrush = FALSE;
+	}
+
+        /* Erase the background */
+        FillRect(hdc, &r, hbr);
+
+        /*
+         * Draw the tab now.
+         * The rectangles calculated exclude the right and bottom
+         * borders of the rectangle. To simplify the following code, those
+         * borders are shaved-off beforehand.
+         */
+        r.right--;
+        r.bottom--;
+
+        /* highlight */
+        SelectObject(hdc, hwPen);
+        MoveToEx (hdc, r.left, r.bottom, NULL);
+        LineTo   (hdc, r.right, r.bottom);
+        LineTo   (hdc, r.right, r.top + 1);
+        
+        /* shadow */
+        SelectObject(hdc, hbPen);
+        LineTo  (hdc, r.left + 1, r.top + 1);
+        LineTo  (hdc, r.left + 1, r.bottom);
+
+        /* shade */
+        SelectObject (hdc, hShade );
+        MoveToEx (hdc, r.right, r.top, NULL);
+        LineTo   (hdc, r.left, r.top);
+        LineTo   (hdc, r.left, r.bottom);
+      }
+      else
+      {
+        /* Erase the background */
+        FillRect(hdc, &r, hbr);
+
+	if (!(lStyle & TCS_FLATBUTTONS))
+	{
+          /* highlight */
+          MoveToEx (hdc, r.left, r.bottom, NULL);
+          LineTo   (hdc, r.left, r.top);
+          LineTo   (hdc, r.right, r.top);
+         
+          /* shadow */
+          SelectObject(hdc, hbPen);
+          LineTo  (hdc, r.right, r.bottom);
+          LineTo  (hdc, r.left, r.bottom);
+
+          /* shade */
+          SelectObject (hdc, hShade );
+          MoveToEx (hdc, r.right - 1, r.top, NULL);
+          LineTo   (hdc, r.right - 1, r.bottom - 1);
+          LineTo   (hdc, r.left + 1, r.bottom - 1);
+	}
+      }
+    }
+    else /* !TCS_BUTTONS */
+    {
+      /* Background color */
+      DeleteObject(hbr);
+      hbr = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));    
+
+      /* We draw a rectangle of different sizes depending on the selection
+       * state. */
+      if (iItem == infoPtr->iSelected)
+        r = selectedRect;
+      else
+        r = itemRect;
+
+      /*
+       * Erase the background.
+       * This is necessary when drawing the selected item since it is larger 
+       * than the others, it might overlap with stuff already drawn by the 
+       * other tabs
+       */     
+      FillRect(hdc, &r, hbr);
+
+      /*
+       * Draw the tab now.
+       * The rectangles calculated exclude the right and bottom
+       * borders of the rectangle. To simplify the following code, those
+       * borders are shaved-off beforehand.
+       */
+      r.right--;
+      r.bottom--;
+      
+      holdPen = SelectObject (hdc, hwPen);
+      if(lStyle & TCS_VERTICAL)
+      {
+        if (lStyle & TCS_BOTTOM)
+        {
+          /* highlight */
+          MoveToEx (hdc, r.left, r.top, NULL);
+          LineTo   (hdc, r.right - ROUND_CORNER_SIZE, r.top);
+          LineTo   (hdc, r.right, r.top + ROUND_CORNER_SIZE);
+
+          /* shadow */
+          SelectObject(hdc, hbPen);
+          LineTo  (hdc, r.right, r.bottom - ROUND_CORNER_SIZE);
+          LineTo  (hdc, r.right - ROUND_CORNER_SIZE, r.bottom);
+          LineTo  (hdc, r.left - 1, r.bottom);
+
+          /* shade */
+          SelectObject (hdc, hShade );
+          MoveToEx (hdc, r.right - 1, r.top, NULL);
+          LineTo   (hdc, r.right - 1, r.bottom - 1);
+          LineTo   (hdc, r.left - 1,    r.bottom - 1);
+        }
+        else
+        {
+          /* highlight */
+          MoveToEx (hdc, r.right, r.top, NULL);
+          LineTo   (hdc, r.left + ROUND_CORNER_SIZE, r.top);
+          LineTo   (hdc, r.left, r.top + ROUND_CORNER_SIZE);
+          LineTo   (hdc, r.left, r.bottom - ROUND_CORNER_SIZE);
+
+          /* shadow */
+          SelectObject(hdc, hbPen);
+          LineTo (hdc, r.left + ROUND_CORNER_SIZE,  r.bottom);
+          LineTo (hdc, r.right + 1, r.bottom);
+
+          /* shade */
+          SelectObject (hdc, hShade );
+          MoveToEx (hdc, r.left + ROUND_CORNER_SIZE - 1, r.bottom - 1, NULL);
+          LineTo   (hdc, r.right + 1, r.bottom - 1);
+        }
+      }
+      else
+      {
+        if (lStyle & TCS_BOTTOM)
+        {
+          /* highlight */
+          MoveToEx (hdc, r.left, r.top, NULL);
+          LineTo   (hdc, r.left, r.bottom - ROUND_CORNER_SIZE);
+          LineTo   (hdc, r.left + ROUND_CORNER_SIZE, r.bottom);
+
+          /* shadow */
+          SelectObject(hdc, hbPen);
+          LineTo  (hdc, r.right - ROUND_CORNER_SIZE, r.bottom);
+          LineTo  (hdc, r.right, r.bottom - ROUND_CORNER_SIZE);
+          LineTo  (hdc, r.right, r.top - 1);
+
+          /* shade */
+          SelectObject (hdc, hShade );
+          MoveToEx   (hdc, r.left, r.bottom - 1, NULL);
+          LineTo   (hdc, r.right - ROUND_CORNER_SIZE - 1, r.bottom - 1);
+          LineTo   (hdc, r.right - 1, r.bottom - ROUND_CORNER_SIZE - 1);
+          LineTo  (hdc, r.right - 1, r.top - 1);
+        }
+        else
+        {
+          /* highlight */
+          if(infoPtr->items[iItem].rect.left == 0) /* if leftmost draw the line longer */
+            MoveToEx (hdc, r.left, r.bottom, NULL);
+          else
+            MoveToEx (hdc, r.left, r.bottom - 1, NULL);
+
+          LineTo   (hdc, r.left, r.top + ROUND_CORNER_SIZE);
+          LineTo   (hdc, r.left + ROUND_CORNER_SIZE, r.top);
+          LineTo   (hdc, r.right - ROUND_CORNER_SIZE, r.top);
+
+          /* shadow */
+          SelectObject(hdc, hbPen);
+          LineTo (hdc, r.right,  r.top + ROUND_CORNER_SIZE);
+          LineTo (hdc, r.right,  r.bottom + 1);
+
+
+          /* shade */
+          SelectObject (hdc, hShade );
+          MoveToEx (hdc, r.right - 1, r.top + ROUND_CORNER_SIZE, NULL);
+          LineTo   (hdc, r.right - 1, r.bottom + 1);
+        }
+      }
+    }
+  
+    /* This modifies r to be the text rectangle. */
+{
+    HFONT hOldFont = SelectObject(hdc, infoPtr->hFont);
+    TAB_DrawItemInterior(hwnd, hdc, iItem, &r);
+    SelectObject(hdc,hOldFont);
+}
+    /* Draw the focus rectangle */
+    if (((lStyle & TCS_FOCUSNEVER) == 0) &&
+	 (GetFocus() == hwnd) &&
+	 (iItem == infoPtr->uFocus) )
+    {
+      r = itemRect;
+      InflateRect(&r, -1, -1);
+
+      DrawFocusRect(hdc, &r);
+    }
+
+    /* Cleanup */
+    SelectObject(hdc, holdPen);
+    if (deleteBrush) DeleteObject(hbr);
+  }
+}
+
+/******************************************************************************
+ * TAB_DrawBorder
+ *
+ * This method is used to draw the raised border around the tab control
+ * "content" area.
+ */         
+static void TAB_DrawBorder (HWND hwnd, HDC hdc)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  HPEN htmPen;
+  HPEN hwPen  = GetSysColorPen (COLOR_3DHILIGHT);
+  HPEN hbPen  = GetSysColorPen (COLOR_3DDKSHADOW);
+  HPEN hShade = GetSysColorPen (COLOR_BTNSHADOW);
+  RECT rect;
+  DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+
+  GetClientRect (hwnd, &rect);
+
+  /*
+   * Adjust for the style
+   */
+
+  if (infoPtr->uNumItem)
+  {
+    if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL))
+    {
+      rect.bottom -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+    }
+    else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL))
+    {
+      rect.right -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+    }
+    else if(lStyle & TCS_VERTICAL)
+    {
+      rect.left += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2;
+    }
+    else /* not TCS_VERTICAL and not TCS_BOTTOM */
+    {
+      rect.top += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 1;
+    }
+  }
+
+  /*
+   * Shave-off the right and bottom margins (exluded in the
+   * rect)
+   */
+  rect.right--;
+  rect.bottom--;
+
+  /* highlight */
+  htmPen = SelectObject (hdc, hwPen);
+
+  MoveToEx (hdc, rect.left, rect.bottom, NULL);
+  LineTo (hdc, rect.left, rect.top);
+  LineTo (hdc, rect.right, rect.top);
+
+  /* Dark Shadow */
+  SelectObject (hdc, hbPen);
+  LineTo (hdc, rect.right, rect.bottom );
+  LineTo (hdc, rect.left, rect.bottom);
+
+  /* shade */
+  SelectObject (hdc, hShade );
+  MoveToEx (hdc, rect.right - 1, rect.top, NULL);
+  LineTo   (hdc, rect.right - 1, rect.bottom - 1);
+  LineTo   (hdc, rect.left,    rect.bottom - 1);
+
+  SelectObject(hdc, htmPen);
+}
+
+/******************************************************************************
+ * TAB_Refresh
+ *
+ * This method repaints the tab control..
+ */             
+static void TAB_Refresh (HWND hwnd, HDC hdc)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  HFONT hOldFont;
+  INT i;
+
+  if (!infoPtr->DoRedraw)
+    return;
+
+  hOldFont = SelectObject (hdc, infoPtr->hFont);
+
+  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS)
+  {
+    for (i = 0; i < infoPtr->uNumItem; i++) 
+      TAB_DrawItem (hwnd, hdc, i);
+  }
+  else
+  {
+    /* Draw all the non selected item first */
+    for (i = 0; i < infoPtr->uNumItem; i++) 
+    {
+      if (i != infoPtr->iSelected)
+	TAB_DrawItem (hwnd, hdc, i);
+    }
+
+    /* Now, draw the border, draw it before the selected item
+     * since the selected item overwrites part of the border. */
+    TAB_DrawBorder (hwnd, hdc);
+
+    /* Then, draw the selected item */
+    TAB_DrawItem (hwnd, hdc, infoPtr->iSelected);
+
+    /* If we haven't set the current focus yet, set it now.
+     * Only happens when we first paint the tab controls */
+    if (infoPtr->uFocus == -1)
+      TAB_SetCurFocus(hwnd, infoPtr->iSelected);
+  }
+
+  SelectObject (hdc, hOldFont);
+}
+
+static DWORD
+TAB_GetRowCount (HWND hwnd )
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+
+  return infoPtr->uNumRows;
+}
+
+static LRESULT
+TAB_SetRedraw (HWND hwnd, WPARAM wParam)
+{
+    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  
+  infoPtr->DoRedraw=(BOOL) wParam;
+  return 0;
+}
+
+static LRESULT TAB_EraseBackground(
+  HWND hwnd, 
+  HDC  givenDC)
+{
+  HDC  hdc;
+  RECT clientRect;
+
+  HBRUSH brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+
+  hdc = givenDC ? givenDC : GetDC(hwnd);
+
+  GetClientRect(hwnd, &clientRect);
+
+  FillRect(hdc, &clientRect, brush);
+
+  if (givenDC==0)
+    ReleaseDC(hwnd, hdc);
+
+  DeleteObject(brush);
+
+  return 0;
+}
+
+/******************************************************************************
+ * TAB_EnsureSelectionVisible
+ *
+ * This method will make sure that the current selection is completely
+ * visible by scrolling until it is.
+ */
+static void TAB_EnsureSelectionVisible(
+  HWND      hwnd,
+  TAB_INFO* infoPtr)
+{
+  INT iSelected = infoPtr->iSelected;
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  INT iOrigLeftmostVisible = infoPtr->leftmostVisible;
+
+  /* set the items row to the bottommost row or topmost row depending on
+   * style */
+  if ((infoPtr->uNumRows > 1) && !(lStyle & TCS_BUTTONS))
+  {
+      INT newselected;
+      INT iTargetRow;
+
+      if(lStyle & TCS_VERTICAL)
+        newselected = infoPtr->items[iSelected].rect.left;
+      else
+        newselected = infoPtr->items[iSelected].rect.top;
+
+      /* the target row is always (number of rows - 1)
+         as row 0 is furthest from the clientRect */
+      iTargetRow = infoPtr->uNumRows - 1;
+
+      if (newselected != iTargetRow)
+      {
+         INT i;
+         if(lStyle & TCS_VERTICAL)
+         {
+           for (i=0; i < infoPtr->uNumItem; i++)
+           {
+             /* move everything in the row of the selected item to the iTargetRow */
+             if (infoPtr->items[i].rect.left == newselected )
+                 infoPtr->items[i].rect.left = iTargetRow;
+             else
+             {
+               if (infoPtr->items[i].rect.left > newselected)
+                 infoPtr->items[i].rect.left-=1;
+             }
+           }
+         }
+         else
+         {
+           for (i=0; i < infoPtr->uNumItem; i++)
+           {
+             if (infoPtr->items[i].rect.top == newselected )
+                 infoPtr->items[i].rect.top = iTargetRow;
+             else
+             {
+               if (infoPtr->items[i].rect.top > newselected)
+                 infoPtr->items[i].rect.top-=1;
+             }
+          }
+        }
+        TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
+      }
+  }
+
+  /*
+   * Do the trivial cases first.
+   */
+  if ( (!infoPtr->needsScrolling) ||
+       (infoPtr->hwndUpDown==0) || (lStyle & TCS_VERTICAL))
+    return;
+
+  if (infoPtr->leftmostVisible >= iSelected)
+  {
+    infoPtr->leftmostVisible = iSelected;
+  }
+  else
+  {
+     RECT r;
+     INT  width, i;
+
+     /* Calculate the part of the client area that is visible */
+     GetClientRect(hwnd, &r);
+     width = r.right;
+
+     GetClientRect(infoPtr->hwndUpDown, &r);
+     width -= r.right;
+
+     if ((infoPtr->items[iSelected].rect.right -
+          infoPtr->items[iSelected].rect.left) >= width )
+     {
+        /* Special case: width of selected item is greater than visible
+         * part of control.
+         */
+        infoPtr->leftmostVisible = iSelected;
+     }
+     else
+     {
+        for (i = infoPtr->leftmostVisible; i < infoPtr->uNumItem; i++)
+        {
+           if ((infoPtr->items[iSelected].rect.right -
+                infoPtr->items[i].rect.left) < width)
+              break;
+        }
+        infoPtr->leftmostVisible = i;
+     }
+  }
+
+  if (infoPtr->leftmostVisible != iOrigLeftmostVisible)
+    TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
+
+  SendMessageA(infoPtr->hwndUpDown, UDM_SETPOS, 0,
+               MAKELONG(infoPtr->leftmostVisible, 0));
+}
+
+/******************************************************************************
+ * TAB_InvalidateTabArea
+ *
+ * This method will invalidate the portion of the control that contains the
+ * tabs. It is called when the state of the control changes and needs
+ * to be redisplayed
+ */
+static void TAB_InvalidateTabArea(
+  HWND      hwnd,
+  TAB_INFO* infoPtr)
+{
+  RECT clientRect;
+  DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  INT lastRow = infoPtr->uNumRows - 1;
+
+  if (lastRow < 0) return;
+
+  GetClientRect(hwnd, &clientRect);
+
+  if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL))
+  {
+    clientRect.top = clientRect.bottom -
+                   infoPtr->tabHeight -
+                   lastRow * (infoPtr->tabHeight - 2) -
+                   ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) - 2;
+  }
+  else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL))
+  {
+    clientRect.left = clientRect.right - infoPtr->tabHeight -
+                      lastRow * (infoPtr->tabHeight - 2) -
+                      ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) - 2;
+  }
+  else if(lStyle & TCS_VERTICAL)
+  {
+    clientRect.right = clientRect.left + infoPtr->tabHeight +
+                       lastRow * (infoPtr->tabHeight - 2) -
+                      ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) + 1;
+
+  }
+  else
+  {
+    clientRect.bottom = clientRect.top + infoPtr->tabHeight +
+                      lastRow * (infoPtr->tabHeight - 2) +
+                      ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) + 1;
+  }
+
+  InvalidateRect(hwnd, &clientRect, TRUE);
+}
+
+static LRESULT
+TAB_Paint (HWND hwnd, WPARAM wParam)
+{
+  HDC hdc;
+  PAINTSTRUCT ps;
+    
+  hdc = wParam== 0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
+  TAB_Refresh (hwnd, hdc);
+    
+  if(!wParam)
+    EndPaint (hwnd, &ps);
+
+  return 0;
+}
+
+static LRESULT
+TAB_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{    
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  TCITEMA *pti;
+  INT iItem;
+  RECT rect;
+  
+  GetClientRect (hwnd, &rect);
+  TRACE("Rect: %x T %i, L %i, B %i, R %i\n", hwnd,
+        rect.top, rect.left, rect.bottom, rect.right);  
+  
+  pti = (TCITEMA *)lParam;
+  iItem = (INT)wParam;
+  
+  if (iItem < 0) return -1;
+  if (iItem > infoPtr->uNumItem)
+    iItem = infoPtr->uNumItem;
+  
+  if (infoPtr->uNumItem == 0) {
+    infoPtr->items = COMCTL32_Alloc (sizeof (TAB_ITEM));
+    infoPtr->uNumItem++;
+    infoPtr->iSelected = 0;
+  }
+  else {
+    TAB_ITEM *oldItems = infoPtr->items;
+    
+    infoPtr->uNumItem++;
+    infoPtr->items = COMCTL32_Alloc (sizeof (TAB_ITEM) * infoPtr->uNumItem);
+    
+    /* pre insert copy */
+    if (iItem > 0) {
+      memcpy (&infoPtr->items[0], &oldItems[0],
+	      iItem * sizeof(TAB_ITEM));
+    }
+    
+    /* post insert copy */
+    if (iItem < infoPtr->uNumItem - 1) {
+      memcpy (&infoPtr->items[iItem+1], &oldItems[iItem],
+	      (infoPtr->uNumItem - iItem - 1) * sizeof(TAB_ITEM));
+      
+    }
+
+    if (iItem <= infoPtr->iSelected)
+      infoPtr->iSelected++;
+
+    COMCTL32_Free (oldItems);
+  }
+  
+  infoPtr->items[iItem].mask = pti->mask;
+  if (pti->mask & TCIF_TEXT)
+    Str_SetPtrAtoW (&infoPtr->items[iItem].pszText, pti->pszText);
+
+  if (pti->mask & TCIF_IMAGE)
+    infoPtr->items[iItem].iImage = pti->iImage;
+  
+  if (pti->mask & TCIF_PARAM)
+    infoPtr->items[iItem].lParam = pti->lParam;
+  
+  TAB_SetItemBounds(hwnd);
+  TAB_InvalidateTabArea(hwnd, infoPtr);
+  
+  TRACE("[%04x]: added item %d '%s'\n",
+	hwnd, iItem, debugstr_w(infoPtr->items[iItem].pszText));
+
+  return iItem;
+}
+
+
+static LRESULT
+TAB_InsertItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  TCITEMW *pti;
+  INT iItem;
+  RECT rect;
+
+  GetClientRect (hwnd, &rect);
+  TRACE("Rect: %x T %i, L %i, B %i, R %i\n", hwnd,
+        rect.top, rect.left, rect.bottom, rect.right);
+
+  pti = (TCITEMW *)lParam;
+  iItem = (INT)wParam;
+
+  if (iItem < 0) return -1;
+  if (iItem > infoPtr->uNumItem)
+    iItem = infoPtr->uNumItem;
+
+  if (infoPtr->uNumItem == 0) {
+    infoPtr->items = COMCTL32_Alloc (sizeof (TAB_ITEM));
+    infoPtr->uNumItem++;
+    infoPtr->iSelected = 0;
+  }
+  else {
+    TAB_ITEM *oldItems = infoPtr->items;
+
+    infoPtr->uNumItem++;
+    infoPtr->items = COMCTL32_Alloc (sizeof (TAB_ITEM) * infoPtr->uNumItem);
+
+    /* pre insert copy */
+    if (iItem > 0) {
+      memcpy (&infoPtr->items[0], &oldItems[0],
+	      iItem * sizeof(TAB_ITEM));
+    }
+
+    /* post insert copy */
+    if (iItem < infoPtr->uNumItem - 1) {
+      memcpy (&infoPtr->items[iItem+1], &oldItems[iItem],
+	      (infoPtr->uNumItem - iItem - 1) * sizeof(TAB_ITEM));
+
+  }
+  
+    if (iItem <= infoPtr->iSelected)
+      infoPtr->iSelected++;
+
+    COMCTL32_Free (oldItems);
+  }
+
+  infoPtr->items[iItem].mask = pti->mask;
+  if (pti->mask & TCIF_TEXT)
+    Str_SetPtrW (&infoPtr->items[iItem].pszText, pti->pszText);
+
+  if (pti->mask & TCIF_IMAGE)
+    infoPtr->items[iItem].iImage = pti->iImage;
+  
+  if (pti->mask & TCIF_PARAM)
+    infoPtr->items[iItem].lParam = pti->lParam;
+  
+  TAB_SetItemBounds(hwnd);
+  TAB_InvalidateTabArea(hwnd, infoPtr);
+  
+  TRACE("[%04x]: added item %d '%s'\n",
+	hwnd, iItem, debugstr_w(infoPtr->items[iItem].pszText));
+
+  return iItem;
+}
+
+
+static LRESULT 
+TAB_SetItemSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  LONG lResult = 0;
+
+  if ((lStyle & TCS_FIXEDWIDTH) || (lStyle & TCS_OWNERDRAWFIXED))
+  {
+    lResult = MAKELONG(infoPtr->tabWidth, infoPtr->tabHeight);
+    infoPtr->tabWidth = (INT)LOWORD(lParam);
+    infoPtr->tabHeight = (INT)HIWORD(lParam);
+  }
+  infoPtr->fSizeSet = TRUE;
+
+  return lResult;
+}
+
+static LRESULT 
+TAB_SetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  TCITEMA *tabItem; 
+  TAB_ITEM *wineItem;
+  INT    iItem;
+
+  iItem = (INT)wParam;
+  tabItem = (LPTCITEMA)lParam;
+
+  TRACE("%d %p\n", iItem, tabItem);
+  if ((iItem<0) || (iItem>=infoPtr->uNumItem)) return FALSE;
+
+  wineItem = &infoPtr->items[iItem];
+
+  if (tabItem->mask & TCIF_IMAGE)
+    wineItem->iImage = tabItem->iImage;
+
+  if (tabItem->mask & TCIF_PARAM)
+    wineItem->lParam = tabItem->lParam;
+
+  if (tabItem->mask & TCIF_RTLREADING) 
+    FIXME("TCIF_RTLREADING\n");
+
+  if (tabItem->mask & TCIF_STATE) 
+    wineItem->dwState = tabItem->dwState;
+
+  if (tabItem->mask & TCIF_TEXT)
+   Str_SetPtrAtoW(&wineItem->pszText, tabItem->pszText);
+
+  /* Update and repaint tabs */
+  TAB_SetItemBounds(hwnd);
+  TAB_InvalidateTabArea(hwnd,infoPtr);
+
+  return TRUE;
+  }
+
+
+static LRESULT
+TAB_SetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  TCITEMW *tabItem;
+  TAB_ITEM *wineItem;
+  INT    iItem;
+
+  iItem = (INT)wParam;
+  tabItem = (LPTCITEMW)lParam;
+
+  TRACE("%d %p\n", iItem, tabItem);
+  if ((iItem<0) || (iItem>=infoPtr->uNumItem)) return FALSE;
+
+  wineItem = &infoPtr->items[iItem];
+
+  if (tabItem->mask & TCIF_IMAGE)
+    wineItem->iImage = tabItem->iImage;
+
+  if (tabItem->mask & TCIF_PARAM)
+    wineItem->lParam = tabItem->lParam;
+
+  if (tabItem->mask & TCIF_RTLREADING)
+    FIXME("TCIF_RTLREADING\n");
+
+  if (tabItem->mask & TCIF_STATE)
+    wineItem->dwState = tabItem->dwState;
+
+  if (tabItem->mask & TCIF_TEXT)
+   Str_SetPtrW(&wineItem->pszText, tabItem->pszText);
+
+  /* Update and repaint tabs */
+  TAB_SetItemBounds(hwnd);
+  TAB_InvalidateTabArea(hwnd,infoPtr);
+
+  return TRUE;
+}
+
+
+static LRESULT 
+TAB_GetItemCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+   TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+
+   return infoPtr->uNumItem;
+}
+
+
+static LRESULT 
+TAB_GetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+   TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+   TCITEMA *tabItem;
+   TAB_ITEM *wineItem;
+   INT    iItem;
+
+  iItem = (INT)wParam;
+  tabItem = (LPTCITEMA)lParam;
+  TRACE("\n");
+  if ((iItem<0) || (iItem>=infoPtr->uNumItem))
+    return FALSE;
+
+  wineItem = &infoPtr->items[iItem];
+
+  if (tabItem->mask & TCIF_IMAGE) 
+    tabItem->iImage = wineItem->iImage;
+
+  if (tabItem->mask & TCIF_PARAM) 
+    tabItem->lParam = wineItem->lParam;
+
+  if (tabItem->mask & TCIF_RTLREADING) 
+    FIXME("TCIF_RTLREADING\n");
+
+  if (tabItem->mask & TCIF_STATE) 
+    tabItem->dwState = wineItem->dwState;
+
+  if (tabItem->mask & TCIF_TEXT) 
+   Str_GetPtrWtoA (wineItem->pszText, tabItem->pszText, tabItem->cchTextMax);
+
+  return TRUE;
+}
+
+
+static LRESULT 
+TAB_GetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  TCITEMW *tabItem;
+  TAB_ITEM *wineItem;
+  INT    iItem;
+
+  iItem = (INT)wParam;
+  tabItem = (LPTCITEMW)lParam;
+  TRACE("\n");
+  if ((iItem<0) || (iItem>=infoPtr->uNumItem))
+    return FALSE;
+
+  wineItem=& infoPtr->items[iItem];
+
+  if (tabItem->mask & TCIF_IMAGE)
+    tabItem->iImage = wineItem->iImage;
+
+  if (tabItem->mask & TCIF_PARAM)
+    tabItem->lParam = wineItem->lParam;
+
+  if (tabItem->mask & TCIF_RTLREADING)
+    FIXME("TCIF_RTLREADING\n");
+
+  if (tabItem->mask & TCIF_STATE)
+    tabItem->dwState = wineItem->dwState;
+
+  if (tabItem->mask & TCIF_TEXT)
+   Str_GetPtrW (wineItem->pszText, tabItem->pszText, tabItem->cchTextMax);
+
+  return TRUE;
+}
+
+
+static LRESULT 
+TAB_DeleteItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  INT iItem = (INT) wParam;
+  BOOL bResult = FALSE;
+
+  if ((iItem >= 0) && (iItem < infoPtr->uNumItem))
+  {
+    TAB_ITEM *oldItems = infoPtr->items;
+    
+    infoPtr->uNumItem--;
+    infoPtr->items = COMCTL32_Alloc(sizeof (TAB_ITEM) * infoPtr->uNumItem);
+    
+    if (iItem > 0) 
+      memcpy(&infoPtr->items[0], &oldItems[0], iItem * sizeof(TAB_ITEM));
+    
+    if (iItem < infoPtr->uNumItem) 
+      memcpy(&infoPtr->items[iItem], &oldItems[iItem + 1],
+              (infoPtr->uNumItem - iItem) * sizeof(TAB_ITEM));
+    
+    COMCTL32_Free(oldItems);
+
+    /* Readjust the selected index */
+    if ((iItem == infoPtr->iSelected) && (iItem > 0))
+      infoPtr->iSelected--;
+      
+    if (iItem < infoPtr->iSelected)
+      infoPtr->iSelected--;
+
+    if (infoPtr->uNumItem == 0)
+      infoPtr->iSelected = -1;
+
+    /* Reposition and repaint tabs */
+    TAB_SetItemBounds(hwnd);
+    TAB_InvalidateTabArea(hwnd,infoPtr);
+
+    bResult = TRUE;
+  }
+
+  return bResult;
+}
+
+static LRESULT 
+TAB_DeleteAllItems (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+   TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+
+  COMCTL32_Free (infoPtr->items);
+  infoPtr->uNumItem = 0;
+  infoPtr->iSelected = -1;
+  if (infoPtr->iHotTracked >= 0)
+    KillTimer(hwnd, TAB_HOTTRACK_TIMER);
+  infoPtr->iHotTracked = -1;
+ 
+  TAB_SetItemBounds(hwnd);
+  TAB_InvalidateTabArea(hwnd,infoPtr);
+  return TRUE;
+}
+
+
+static LRESULT
+TAB_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+
+  TRACE("\n");
+  return (LRESULT)infoPtr->hFont;
+}
+
+static LRESULT
+TAB_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
+
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  
+  TRACE("%x %lx\n",wParam, lParam);
+  
+  infoPtr->hFont = (HFONT)wParam;
+  
+  TAB_SetItemBounds(hwnd);
+
+  TAB_InvalidateTabArea(hwnd, infoPtr);
+
+  return 0;
+}
+
+
+static LRESULT
+TAB_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+
+  TRACE("\n");
+  return (LRESULT)infoPtr->himl;
+}
+
+static LRESULT
+TAB_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+    HIMAGELIST himlPrev;
+
+    TRACE("\n");
+    himlPrev = infoPtr->himl;
+    infoPtr->himl= (HIMAGELIST)lParam;
+    return (LRESULT)himlPrev;
+}
+
+static LRESULT
+TAB_GetUnicodeFormat (HWND hwnd)
+{
+    TAB_INFO *infoPtr = TAB_GetInfoPtr (hwnd);
+    return infoPtr->bUnicode;
+}
+
+static LRESULT
+TAB_SetUnicodeFormat (HWND hwnd, WPARAM wParam)
+{
+    TAB_INFO *infoPtr = TAB_GetInfoPtr (hwnd);
+    BOOL bTemp = infoPtr->bUnicode;
+
+    infoPtr->bUnicode = (BOOL)wParam;
+
+    return bTemp;
+}
+
+static LRESULT
+TAB_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
+
+{
+/* I'm not really sure what the following code was meant to do.
+   This is what it is doing:
+   When WM_SIZE is sent with SIZE_RESTORED, the control
+   gets positioned in the top left corner.
+
+  RECT parent_rect;
+  HWND parent;
+  UINT uPosFlags,cx,cy;
+
+  uPosFlags=0;
+  if (!wParam) {
+    parent = GetParent (hwnd);
+    GetClientRect(parent, &parent_rect);
+    cx=LOWORD (lParam);
+    cy=HIWORD (lParam);
+    if (GetWindowLongA(hwnd, GWL_STYLE) & CCS_NORESIZE) 
+        uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
+
+    SetWindowPos (hwnd, 0, parent_rect.left, parent_rect.top,
+            cx, cy, uPosFlags | SWP_NOZORDER);
+  } else {
+    FIXME("WM_SIZE flag %x %lx not handled\n", wParam, lParam);
+  } */
+
+  /* Recompute the size/position of the tabs. */
+  TAB_SetItemBounds (hwnd);
+
+  /* Force a repaint of the control. */
+  InvalidateRect(hwnd, NULL, TRUE);
+
+  return 0;
+}
+
+
+static LRESULT 
+TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr;
+  TEXTMETRICA fontMetrics;
+  HDC hdc;
+  HFONT hOldFont;
+  DWORD dwStyle;
+
+#ifdef __WIN32OS2__
+  infoPtr = (TAB_INFO*)initControl(hwnd,sizeof(TAB_INFO));
+#else
+  infoPtr = (TAB_INFO *)COMCTL32_Alloc (sizeof(TAB_INFO));
+#endif
+
+  SetWindowLongA(hwnd, 0, (DWORD)infoPtr);
+   
+  infoPtr->uNumItem        = 0;
+  infoPtr->uNumRows        = 0;
+  infoPtr->hFont           = 0;
+  infoPtr->items           = 0;
+  infoPtr->hcurArrow       = LoadCursorA (0, IDC_ARROWA);
+  infoPtr->iSelected       = -1;
+  infoPtr->iHotTracked     = -1;
+  infoPtr->uFocus          = -1;  
+  infoPtr->hwndToolTip     = 0;
+  infoPtr->DoRedraw        = TRUE;
+  infoPtr->needsScrolling  = FALSE;
+  infoPtr->hwndUpDown      = 0;
+  infoPtr->leftmostVisible = 0;
+  infoPtr->fSizeSet	   = FALSE;
+  infoPtr->bUnicode	   = IsWindowUnicode (hwnd);
+  
+  TRACE("Created tab control, hwnd [%04x]\n", hwnd); 
+
+  /* The tab control always has the WS_CLIPSIBLINGS style. Even 
+     if you don't specify it in CreateWindow. This is necessary in 
+     order for paint to work correctly. This follows windows behaviour. */
+  dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  SetWindowLongA(hwnd, GWL_STYLE, dwStyle|WS_CLIPSIBLINGS);
+
+  if (dwStyle & TCS_TOOLTIPS) {
+    /* Create tooltip control */
+    infoPtr->hwndToolTip =
+      CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
+		       CW_USEDEFAULT, CW_USEDEFAULT,
+		       CW_USEDEFAULT, CW_USEDEFAULT,
+		       hwnd, 0, 0, 0);
+    
+    /* Send NM_TOOLTIPSCREATED notification */
+    if (infoPtr->hwndToolTip) {
+      NMTOOLTIPSCREATED nmttc;
+      
+      nmttc.hdr.hwndFrom = hwnd;
+      nmttc.hdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
+      nmttc.hdr.code = NM_TOOLTIPSCREATED;
+      nmttc.hwndToolTips = infoPtr->hwndToolTip;
+      
+      SendMessageA (GetParent (hwnd), WM_NOTIFY,
+		    (WPARAM)GetWindowLongA(hwnd, GWL_ID), (LPARAM)&nmttc);
+    }
+  }  
+    
+  /*
+   * We need to get text information so we need a DC and we need to select
+   * a font.
+   */
+  hdc = GetDC(hwnd); 
+  hOldFont = SelectObject (hdc, GetStockObject (SYSTEM_FONT));
+
+  /* Use the system font to determine the initial height of a tab. */
+  GetTextMetricsA(hdc, &fontMetrics);
+
+  /*
+   * Make sure there is enough space for the letters + growing the 
+   * selected item + extra space for the selected item.   
+   */
+  infoPtr->tabHeight = fontMetrics.tmHeight + 2 * VERTICAL_ITEM_PADDING +
+                       SELECTED_TAB_OFFSET;
+
+  /* Initialize the width of a tab. */
+  infoPtr->tabWidth = DEFAULT_TAB_WIDTH;
+
+  SelectObject (hdc, hOldFont);
+  ReleaseDC(hwnd, hdc);
+
+  return 0;
+}
+
+static LRESULT
+TAB_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
+  INT iItem;
+
+  if (!infoPtr)
+      return 0;
+
+  if (infoPtr->items) {
+    for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) {
+      if (infoPtr->items[iItem].pszText)
+	COMCTL32_Free (infoPtr->items[iItem].pszText);
+    }
+    COMCTL32_Free (infoPtr->items);
+  }
+  
+  if (infoPtr->hwndToolTip) 
+    DestroyWindow (infoPtr->hwndToolTip);
+ 
+  if (infoPtr->hwndUpDown)
+    DestroyWindow(infoPtr->hwndUpDown);
+
+  if (infoPtr->iHotTracked >= 0)
+    KillTimer(hwnd, TAB_HOTTRACK_TIMER);
+
+  COMCTL32_Free (infoPtr);
+  SetWindowLongA(hwnd, 0, 0);
+  return 0;
+}
+
+static LRESULT WINAPI
+TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+
+    TRACE("hwnd=%x msg=%x wParam=%x lParam=%lx\n", hwnd, uMsg, wParam, lParam);
+    if (!TAB_GetInfoPtr(hwnd) && (uMsg != WM_CREATE))
+      return DefWindowProcA (hwnd, uMsg, wParam, lParam);
+
+    switch (uMsg)
+    {
+    case TCM_GETIMAGELIST:
+      return TAB_GetImageList (hwnd, wParam, lParam);
+      
+    case TCM_SETIMAGELIST:
+      return TAB_SetImageList (hwnd, wParam, lParam);
+      
+    case TCM_GETITEMCOUNT:
+      return TAB_GetItemCount (hwnd, wParam, lParam);
+      
+    case TCM_GETITEMA:
+      return TAB_GetItemA (hwnd, wParam, lParam);
+      
+    case TCM_GETITEMW:
+      return TAB_GetItemW (hwnd, wParam, lParam);
+      
+    case TCM_SETITEMA:
+      return TAB_SetItemA (hwnd, wParam, lParam);
+      
+    case TCM_SETITEMW:
+      return TAB_SetItemW (hwnd, wParam, lParam);
+      
+    case TCM_DELETEITEM:
+      return TAB_DeleteItem (hwnd, wParam, lParam);
+      
+    case TCM_DELETEALLITEMS:
+     return TAB_DeleteAllItems (hwnd, wParam, lParam);
+     
+    case TCM_GETITEMRECT:
+     return TAB_GetItemRect (hwnd, wParam, lParam);
+      
+    case TCM_GETCURSEL:
+      return TAB_GetCurSel (hwnd);
+      
+    case TCM_HITTEST:
+      return TAB_HitTest (hwnd, wParam, lParam);
+      
+    case TCM_SETCURSEL:
+      return TAB_SetCurSel (hwnd, wParam);
+      
+    case TCM_INSERTITEMA:
+      return TAB_InsertItemA (hwnd, wParam, lParam);
+      
+    case TCM_INSERTITEMW:
+      return TAB_InsertItemW (hwnd, wParam, lParam);
+      
+    case TCM_SETITEMEXTRA:
+      FIXME("Unimplemented msg TCM_SETITEMEXTRA\n");
+      return 0;
+      
+    case TCM_ADJUSTRECT:
+      return TAB_AdjustRect (hwnd, (BOOL)wParam, (LPRECT)lParam);
+      
+    case TCM_SETITEMSIZE:
+      return TAB_SetItemSize (hwnd, wParam, lParam);
+      
+    case TCM_REMOVEIMAGE:
+      FIXME("Unimplemented msg TCM_REMOVEIMAGE\n");
+      return 0;
+      
+    case TCM_SETPADDING:
+      FIXME("Unimplemented msg TCM_SETPADDING\n");
+      return 0;
+      
+    case TCM_GETROWCOUNT:
+      return TAB_GetRowCount(hwnd);
+
+    case TCM_GETUNICODEFORMAT:
+      return TAB_GetUnicodeFormat (hwnd);
+
+    case TCM_SETUNICODEFORMAT:
+      return TAB_SetUnicodeFormat (hwnd, wParam);
+
+    case TCM_HIGHLIGHTITEM:
+      FIXME("Unimplemented msg TCM_HIGHLIGHTITEM\n");
+      return 0;
+      
+    case TCM_GETTOOLTIPS:
+      return TAB_GetToolTips (hwnd, wParam, lParam);
+      
+    case TCM_SETTOOLTIPS:
+      return TAB_SetToolTips (hwnd, wParam, lParam);
+      
+    case TCM_GETCURFOCUS:
+      return TAB_GetCurFocus (hwnd);
+      
+    case TCM_SETCURFOCUS:
+      return TAB_SetCurFocus (hwnd, wParam);
+      
+    case TCM_SETMINTABWIDTH:
+      FIXME("Unimplemented msg TCM_SETMINTABWIDTH\n");
+      return 0;
+      
+    case TCM_DESELECTALL:
+      FIXME("Unimplemented msg TCM_DESELECTALL\n");
+      return 0;
+      
+    case TCM_GETEXTENDEDSTYLE:
+      FIXME("Unimplemented msg TCM_GETEXTENDEDSTYLE\n");
+      return 0;
+
+    case TCM_SETEXTENDEDSTYLE:
+      FIXME("Unimplemented msg TCM_SETEXTENDEDSTYLE\n");
+      return 0;
+
+    case WM_GETFONT:
+      return TAB_GetFont (hwnd, wParam, lParam);
+      
+    case WM_SETFONT:
+      return TAB_SetFont (hwnd, wParam, lParam);
+      
+    case WM_CREATE:
+      return TAB_Create (hwnd, wParam, lParam);
+      
+    case WM_NCDESTROY:
+      return TAB_Destroy (hwnd, wParam, lParam);
+      
+    case WM_GETDLGCODE:
+      return DLGC_WANTARROWS | DLGC_WANTCHARS;
+      
+    case WM_LBUTTONDOWN:
+      return TAB_LButtonDown (hwnd, wParam, lParam);
+      
+    case WM_LBUTTONUP:
+      return TAB_LButtonUp (hwnd, wParam, lParam);
+      
+    case WM_RBUTTONDOWN:
+      return TAB_RButtonDown (hwnd, wParam, lParam);
+      
+    case WM_MOUSEMOVE:
+      return TAB_MouseMove (hwnd, wParam, lParam);
+      
+    case WM_ERASEBKGND:
+      return TAB_EraseBackground (hwnd, (HDC)wParam);
+
+    case WM_PAINT:
+      return TAB_Paint (hwnd, wParam);
+
+    case WM_SIZE:
+      return TAB_Size (hwnd, wParam, lParam);
+      
+    case WM_SETREDRAW:
+      return TAB_SetRedraw (hwnd, wParam);
+
+    case WM_HSCROLL:
+      return TAB_OnHScroll(hwnd, (int)LOWORD(wParam), (int)HIWORD(wParam), (HWND)lParam);
+
+    case WM_STYLECHANGED:
+      TAB_SetItemBounds (hwnd);
+      InvalidateRect(hwnd, NULL, TRUE);
+      return 0;
+      
+    case WM_KILLFOCUS:
+    case WM_SETFOCUS:
+      return TAB_FocusChanging(hwnd, uMsg, wParam, lParam);
+
+    case WM_KEYUP:
+      return TAB_KeyUp(hwnd, wParam);
+    case WM_NCHITTEST:
+      return TAB_NCHitTest(hwnd, lParam);
+
+    default:
+      if (uMsg >= WM_USER)
+	WARN("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;
+}
+
+
+VOID
+TAB_Register (void)
+{
+  WNDCLASSA wndClass;
+
+  ZeroMemory (&wndClass, sizeof(WNDCLASSA));
+  wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
+  wndClass.lpfnWndProc   = (WNDPROC)TAB_WindowProc;
+  wndClass.cbClsExtra    = 0;
+  wndClass.cbWndExtra    = sizeof(TAB_INFO *);
+  wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
+  wndClass.hbrBackground = (HBRUSH)NULL;
+  wndClass.lpszClassName = WC_TABCONTROLA;
+  
+  RegisterClassA (&wndClass);
+}
+
+
+VOID
+TAB_Unregister (void)
+{
+    UnregisterClassA (WC_TABCONTROLA, (HINSTANCE)NULL);
+}
Index: trunk/src/comctl32/tab.cpp
===================================================================
--- trunk/src/comctl32/tab.cpp	(revision 5627)
+++ 	(revision )
@@ -1,2549 +1,0 @@
-/* $Id: tab.cpp,v 1.4 2000-05-22 17:25:11 cbratschi Exp $ */
-/*
- * Tab control
- *
- * Copyright 1998 Anders Carlsson
- * Copyright 1999 Alex Priem <alexp@sci.kun.nl>
- * Copyright 1999 Francis Beaudet
- * Copyright 1999 Achim Hasenmueller
- * Copyright 1999 Christoph Bratschi
- *
- * TODO:
- *  Image list support
- *  Multiline support
- */
-
-/* inconsistent: report! */
-/*
- - Corel WINE 20000513 level
- - (WINE 991212 level)
-*/
-
-#include <string.h>
-
-#include "winbase.h"
-#include "commctrl.h"
-#include "ccbase.h"
-#include "tab.h"
-#include "comctl32.h"
-
-
-/******************************************************************************
- * Positioning constants
- */
-#define SELECTED_TAB_OFFSET     2
-#define HORIZONTAL_ITEM_PADDING 5
-#define VERTICAL_ITEM_PADDING   3
-#define ROUND_CORNER_SIZE       2
-#define FOCUS_RECT_HOFFSET      2
-#define FOCUS_RECT_VOFFSET      1
-#define DISPLAY_AREA_PADDINGX   5
-#define DISPLAY_AREA_PADDINGY   5
-#define CONTROL_BORDER_SIZEX    2
-#define CONTROL_BORDER_SIZEY    2
-#define BUTTON_SPACINGX         10
-#define DEFAULT_TAB_WIDTH       96
-
-#define TAB_GetInfoPtr(hwnd) ((TAB_INFO*)getInfoPtr(hwnd))
-
-/******************************************************************************
- * Hot-tracking timer constants
- */
-#define TAB_HOTTRACK_TIMER            1
-#define TAB_HOTTRACK_TIMER_INTERVAL   100   /* milliseconds */
-
-/******************************************************************************
- * Prototypes
- */
-static void TAB_Refresh (HWND hwnd, HDC hdc);
-static void TAB_InvalidateTabArea(HWND      hwnd, TAB_INFO* infoPtr);
-static void TAB_EnsureSelectionVisible(HWND hwnd, TAB_INFO* infoPtr);
-static void TAB_DrawItem(HWND hwnd, HDC hdc, INT iItem);
-static void TAB_DrawItemInterior(HWND hwnd, HDC hdc, INT iItem, RECT* drawRect);
-
-static VOID
-TAB_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
-            WPARAM wParam, LPARAM lParam)
-{
-    MSG msg;
-
-    msg.hwnd = hwndMsg;
-    msg.message = uMsg;
-    msg.wParam = wParam;
-    msg.lParam = lParam;
-    msg.time = GetMessageTime ();
-    msg.pt.x = LOWORD(GetMessagePos ());
-    msg.pt.y = HIWORD(GetMessagePos ());
-
-    SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
-}
-
-static LRESULT
-TAB_GetCurSel (HWND hwnd)
-{
-    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-    return infoPtr->iSelected;
-}
-
-static LRESULT
-TAB_GetCurFocus (HWND hwnd)
-{
-    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-    return infoPtr->uFocus;
-}
-
-static LRESULT
-TAB_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-    if (infoPtr == NULL) return 0;
-    return infoPtr->hwndToolTip;
-}
-
-
-static LRESULT
-TAB_SetCurSel (HWND hwnd,WPARAM wParam)
-{
-    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  INT iItem=(INT) wParam;
-  INT prevItem;
-
-  prevItem=-1;
-  if ((iItem >= 0) && (iItem < infoPtr->uNumItem)) {
-    prevItem=infoPtr->iSelected;
-      infoPtr->iSelected=iItem;
-      TAB_EnsureSelectionVisible(hwnd, infoPtr);
-      TAB_InvalidateTabArea(hwnd, infoPtr);
-  }
-  return prevItem;
-}
-
-static LRESULT
-TAB_SetCurFocus (HWND hwnd,WPARAM wParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  INT iItem=(INT) wParam;
-
-  if ((iItem < 0) || (iItem >= infoPtr->uNumItem)) return 0;
-
-  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS)
-  {
-    //FIXME (tab,"Should set input focus\n");
-  } else
-  {
-    if (infoPtr->iSelected != iItem || infoPtr->uFocus == -1)
-    {
-      infoPtr->uFocus = iItem;
-      if (sendNotify(hwnd,TCN_SELCHANGING) != TRUE)
-      {
-        infoPtr->iSelected = iItem;
-        sendNotify(hwnd,TCN_SELCHANGE);
-
-        TAB_EnsureSelectionVisible(hwnd, infoPtr);
-        TAB_InvalidateTabArea(hwnd, infoPtr);
-      }
-    }
-  }
-  return 0;
-}
-
-static LRESULT
-TAB_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-    if (infoPtr == NULL) return 0;
-    infoPtr->hwndToolTip = (HWND)wParam;
-    return 0;
-}
-
-/******************************************************************************
- * TAB_InternalGetItemRect
- *
- * This method will calculate the rectangle representing a given tab item in
- * client coordinates. This method takes scrolling into account.
- *
- * This method returns TRUE if the item is visible in the window and FALSE
- * if it is completely outside the client area.
- */
-static BOOL TAB_InternalGetItemRect(
-  HWND        hwnd,
-  TAB_INFO*   infoPtr,
-  INT         itemIndex,
-  RECT*       itemRect,
-  RECT*       selectedRect)
-{
-  RECT tmpItemRect,clientRect;
-  LONG        lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
-
-  /*
-   * Perform a sanity check and a trivial visibility check.
-   */
-  if ( (infoPtr->uNumItem <= 0) ||
-       (itemIndex >= infoPtr->uNumItem) ||
-       (!(lStyle &TCS_MULTILINE) && (itemIndex < infoPtr->leftmostVisible)) )
-    return FALSE;
-
-  /*
-   * Avoid special cases in this procedure by assigning the "out"
-   * parameters if the caller didn't supply them
-   */
-  if (itemRect==NULL)
-    itemRect = &tmpItemRect;
-
-  /*
-   * Retrieve the unmodified item rect.
-   */
-  *itemRect = infoPtr->items[itemIndex].rect;
-
-  /*
-   * calculate the times bottom and top based on the row
-   */
-  GetClientRect(hwnd, &clientRect);
-
-  if (lStyle & TCS_BOTTOM)
-  {
-    itemRect->bottom = clientRect.bottom -
-                      SELECTED_TAB_OFFSET -
-                      itemRect->top * (infoPtr->tabHeight - 2);
-
-    itemRect->top = clientRect.bottom -
-                   infoPtr->tabHeight -
-                   itemRect->top * ( infoPtr->tabHeight - 2);
-  }
-  else
-  {
-    itemRect->bottom = clientRect.top +
-                      infoPtr->tabHeight +
-                      itemRect->top * (infoPtr->tabHeight - 2);
-    itemRect->top = clientRect.top +
-                   SELECTED_TAB_OFFSET+
-                   itemRect->top * (infoPtr->tabHeight - 2);
- }
-
-  /*
-   * "scroll" it to make sure the item at the very left of the
-   * tab control is the leftmost visible tab.
-   */
-  OffsetRect(itemRect,
-             -infoPtr->items[infoPtr->leftmostVisible].rect.left,
-             0);
-
-  /*
-   * Move the rectangle so the first item is slightly offset from
-   * the left of the tab control.
-   */
-  OffsetRect(itemRect,
-             SELECTED_TAB_OFFSET,
-             0);
-
-
-  /*
-   * Now, calculate the position of the item as if it were selected.
-   */
-  if (selectedRect!=NULL)
-  {
-    CopyRect(selectedRect, itemRect);
-
-    /*
-     * The rectangle of a selected item is a bit wider.
-     */
-    InflateRect(selectedRect, SELECTED_TAB_OFFSET, 0);
-
-    /*
-     * If it also a bit higher.
-     */
-    if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM)
-    {
-      selectedRect->top    -=2; /* the border is thicker on the bottom */
-      selectedRect->bottom +=SELECTED_TAB_OFFSET;
-    }
-    else
-    {
-      selectedRect->top   -=SELECTED_TAB_OFFSET;
-      selectedRect->bottom+=1;
-    }
-  }
-
-  return TRUE;
-}
-
-static BOOL TAB_GetItemRect(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  return TAB_InternalGetItemRect(hwnd, TAB_GetInfoPtr(hwnd), (INT)wParam,
-                                 (LPRECT)lParam, (LPRECT)NULL);
-}
-
-/******************************************************************************
- * TAB_KeyUp
- *
- * This method is called to handle keyboard input
- */
-static LRESULT TAB_KeyUp(
-  HWND   hwnd,
-  WPARAM keyCode)
-{
-  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
-  int       newItem = -1;
-
-  switch (keyCode)
-  {
-    case VK_LEFT:
-      newItem = infoPtr->uFocus-1;
-      break;
-    case VK_RIGHT:
-      newItem = infoPtr->uFocus+1;
-      break;
-  }
-
-  /*
-   * If we changed to a valid item, change the selection
-   */
-  if ( (newItem >= 0) &&
-       (newItem < infoPtr->uNumItem) &&
-       (infoPtr->uFocus != newItem) )
-  {
-    if (!sendNotify(hwnd,TCN_SELCHANGING))
-    {
-      infoPtr->iSelected = newItem;
-      infoPtr->uFocus    = newItem;
-      sendNotify(hwnd,TCN_SELCHANGE);
-
-      TAB_EnsureSelectionVisible(hwnd, infoPtr);
-      TAB_InvalidateTabArea(hwnd, infoPtr);
-    }
-  }
-
-  return 0;
-}
-
-/******************************************************************************
- * TAB_FocusChanging
- *
- * This method is called whenever the focus goes in or out of this control
- * it is used to update the visual state of the control.
- */
-static LRESULT TAB_FocusChanging(
-  HWND   hwnd,
-  UINT   uMsg,
-  WPARAM wParam,
-  LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  RECT      selectedRect;
-  BOOL      isVisible;
-
-  /*
-   * Get the rectangle for the item.
-   */
-  isVisible = TAB_InternalGetItemRect(hwnd,
-                                      infoPtr,
-                                      infoPtr->uFocus,
-                                      NULL,
-                                      &selectedRect);
-
-  /*
-   * If the rectangle is not completely invisible, invalidate that
-   * portion of the window.
-   */
-  if (isVisible)
-  {
-    InvalidateRect(hwnd, &selectedRect, TRUE);
-  }
-
-  /*
-   * Don't otherwise disturb normal behavior.
-   */
-  return DefWindowProcA (hwnd, uMsg, wParam, lParam);
-}
-
-static HWND TAB_InternalHitTest (
-  HWND      hwnd,
-  TAB_INFO* infoPtr,
-  POINT     pt,
-  UINT*     flags)
-
-{
-  RECT rect;
-  int iCount;
-
-  for (iCount = 0; iCount < infoPtr->uNumItem; iCount++)
-  {
-    TAB_InternalGetItemRect(hwnd,
-                            infoPtr,
-                            iCount,
-                            &rect,
-                            NULL);
-
-    if (PtInRect (&rect, pt))
-    {
-      *flags = TCHT_ONITEM;
-      return iCount;
-    }
-  }
-
-  *flags=TCHT_NOWHERE;
-  return -1;
-}
-
-static LRESULT
-TAB_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  LPTCHITTESTINFO lptest=(LPTCHITTESTINFO) lParam;
-
-  return TAB_InternalHitTest (hwnd, infoPtr,lptest->pt,&lptest->flags);
-}
-
-
-static LRESULT
-TAB_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  POINT pt;
-  INT newItem,dummy;
-
-  if (infoPtr->hwndToolTip)
-    TAB_RelayEvent (infoPtr->hwndToolTip, hwnd,
-                    WM_LBUTTONDOWN, wParam, lParam);
-
-  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_FOCUSONBUTTONDOWN ) {
-    SetFocus (hwnd);
-  }
-
-  if (infoPtr->hwndToolTip)
-    TAB_RelayEvent (infoPtr->hwndToolTip, hwnd,
-                    WM_LBUTTONDOWN, wParam, lParam);
-
-  pt.x = (INT)LOWORD(lParam);
-  pt.y = (INT)HIWORD(lParam);
-
-  newItem = TAB_InternalHitTest (hwnd, infoPtr, pt, (unsigned int*)&dummy);
-
-//  TRACE("On Tab, item %d\n", newItem);
-
-  if ( (newItem!=-1) &&
-       (infoPtr->iSelected != newItem) )
-  {
-    if (sendNotify(hwnd,TCN_SELCHANGING) != TRUE)
-    {
-      infoPtr->iSelected = newItem;
-      infoPtr->uFocus    = newItem;
-      sendNotify(hwnd, TCN_SELCHANGE);
-
-      TAB_EnsureSelectionVisible(hwnd, infoPtr);
-
-      TAB_InvalidateTabArea(hwnd, infoPtr);
-    }
-  }
-  return 0;
-}
-
-static LRESULT
-TAB_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  sendNotify(hwnd,NM_CLICK);
-
-  return 0;
-}
-
-static LRESULT
-TAB_RButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  sendNotify(hwnd,NM_RCLICK);
-
-  return 0;
-}
-
-/******************************************************************************
- * TAB_DrawLoneItemInterior
- *
- * This calls TAB_DrawItemInterior.  However, TAB_DrawItemInterior is normally
- * called by TAB_DrawItem which is normally called by TAB_Refresh which sets
- * up the device context and font.  This routine does the same setup but
- * only calls TAB_DrawItemInterior for the single specified item.
- */
-static void
-TAB_DrawLoneItemInterior(HWND hwnd, TAB_INFO* infoPtr, int iItem)
-{
-  HDC hdc = GetDC(hwnd);
-  HFONT hOldFont = SelectObject(hdc, infoPtr->hFont);
-  TAB_DrawItemInterior(hwnd, hdc, iItem, NULL);
-  SelectObject(hdc, hOldFont);
-  ReleaseDC(hwnd, hdc);
-}
-
-/******************************************************************************
- * TAB_HotTrackTimerProc
- *
- * When a mouse-move event causes a tab to be highlighted (hot-tracking), a
- * timer is setup so we can check if the mouse is moved out of our window.
- * (We don't get an event when the mouse leaves, the mouse-move events just
- * stop being delivered to our window and just start being delivered to
- * another window.)  This function is called when the timer triggers so
- * we can check if the mouse has left our window.  If so, we un-highlight
- * the hot-tracked tab.
- */
-static VOID CALLBACK
-TAB_HotTrackTimerProc
-  (
-  HWND hwnd,    // handle of window for timer messages
-  UINT uMsg,    // WM_TIMER message
-  UINT idEvent, // timer identifier
-  DWORD dwTime  // current system time
-  )
-{
-  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
-
-  if (infoPtr != NULL && infoPtr->iHotTracked >= 0)
-  {
-    POINT pt;
-
-    /*
-    ** If we can't get the cursor position, or if the cursor is outside our
-    ** window, we un-highlight the hot-tracked tab.  Note that the cursor is
-    ** "outside" even if it is within our bounding rect if another window
-    ** overlaps.  Note also that the case where the cursor stayed within our
-    ** window but has moved off the hot-tracked tab will be handled by the
-    ** WM_MOUSEMOVE event.
-    */
-    if (!GetCursorPos(&pt) || WindowFromPoint(pt) != hwnd)
-    {
-      // Redraw iHotTracked to look normal
-      INT iRedraw = infoPtr->iHotTracked;
-      infoPtr->iHotTracked = -1;
-      TAB_DrawLoneItemInterior(hwnd, infoPtr, iRedraw);
-
-      // Kill this timer
-      KillTimer(hwnd, TAB_HOTTRACK_TIMER);
-    }
-  }
-}
-
-/******************************************************************************
- * TAB_RecalcHotTrack
- *
- * If a tab control has the TCS_HOTTRACK style, then the tab under the mouse
- * should be highlighted.  This function determines which tab in a tab control,
- * if any, is under the mouse and records that information.  The caller may
- * supply output parameters to receive the item number of the tab item which
- * was highlighted but isn't any longer and of the tab item which is now
- * highlighted but wasn't previously.  The caller can use this information to
- * selectively redraw those tab items.
- *
- * If the caller has a mouse position, it can supply it through the pos
- * parameter.  For example, TAB_MouseMove does this.  Otherwise, the caller
- * supplies NULL and this function determines the current mouse position
- * itself.
- */
-static void
-TAB_RecalcHotTrack
-  (
-  HWND            hwnd,
-  const LPARAM*   pos,
-  int*            out_redrawLeave,
-  int*            out_redrawEnter
-  )
-{
-  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
-
-  int item = -1;
-
-
-  if (out_redrawLeave != NULL)
-    *out_redrawLeave = -1;
-  if (out_redrawEnter != NULL)
-    *out_redrawEnter = -1;
-
-  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_HOTTRACK)
-  {
-    POINT pt;
-    UINT  flags;
-
-    if (pos == NULL)
-    {
-      GetCursorPos(&pt);
-      ScreenToClient(hwnd, &pt);
-    }
-    else
-    {
-      pt.x = LOWORD(*pos);
-      pt.y = HIWORD(*pos);
-    }
-
-    item = TAB_InternalHitTest(hwnd, infoPtr, pt, &flags);
-  }
-
-  if (item != infoPtr->iHotTracked)
-  {
-    if (infoPtr->iHotTracked >= 0)
-    {
-      // Mark currently hot-tracked to be redrawn to look normal
-      if (out_redrawLeave != NULL)
-        *out_redrawLeave = infoPtr->iHotTracked;
-
-      if (item < 0)
-      {
-        // Kill timer which forces recheck of mouse pos
-        KillTimer(hwnd, TAB_HOTTRACK_TIMER);
-      }
-    }
-    else
-    {
-      // Start timer so we recheck mouse pos
-      UINT timerID = SetTimer
-        (
-        hwnd,
-        TAB_HOTTRACK_TIMER,
-        TAB_HOTTRACK_TIMER_INTERVAL,
-        TAB_HotTrackTimerProc
-        );
-
-      if (timerID == 0)
-        return; /* Hot tracking not available */
-    }
-
-    infoPtr->iHotTracked = item;
-
-    if (item >= 0)
-    {
-      // Mark new hot-tracked to be redrawn to look highlighted
-      if (out_redrawEnter != NULL)
-        *out_redrawEnter = item;
-    }
-  }
-}
-
-/******************************************************************************
- * TAB_MouseMove
- *
- * Handles the mouse-move event.  Updates tooltips.  Updates hot-tracking.
- */
-static LRESULT
-TAB_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  int redrawLeave;
-  int redrawEnter;
-
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-  if (infoPtr->hwndToolTip)
-    TAB_RelayEvent (infoPtr->hwndToolTip, hwnd,
-                    WM_LBUTTONDOWN, wParam, lParam);
-
-  /* Determine which tab to highlight.  Redraw tabs which change highlight
-  ** status. */
-  TAB_RecalcHotTrack(hwnd, &lParam, &redrawLeave, &redrawEnter);
-
-  if (redrawLeave != -1)
-    TAB_DrawLoneItemInterior(hwnd, infoPtr, redrawLeave);
-  if (redrawEnter != -1)
-    TAB_DrawLoneItemInterior(hwnd, infoPtr, redrawEnter);
-
-  return 0;
-}
-
-/******************************************************************************
- * TAB_AdjustRect
- *
- * Calculates the tab control's display area given the windows rectangle or
- * the window rectangle given the requested display rectangle.
- */
-static LRESULT TAB_AdjustRect(
-  HWND   hwnd,
-  WPARAM fLarger,
-  LPRECT prc)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-  if (fLarger)
-  {
-    /*
-     * Go from display rectangle
-     */
-
-    /*
-     * Add the height of the tabs.
-     */
-    if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM)
-      prc->bottom += (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
-    else
-      prc->top -= (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
-
-    /*
-     * Inflate the rectangle for the padding
-     */
-    InflateRect(prc, DISPLAY_AREA_PADDINGX, DISPLAY_AREA_PADDINGY);
-
-    /*
-     * Inflate for the border
-     */
-    InflateRect(prc, CONTROL_BORDER_SIZEX, CONTROL_BORDER_SIZEX);
-  }
-  else
-  {
-    /*
-     * Go from window rectangle.
-     */
-
-    /*
-     * Deflate the rectangle for the border
-     */
-    InflateRect(prc, -CONTROL_BORDER_SIZEX, -CONTROL_BORDER_SIZEX);
-
-    /*
-     * Deflate the rectangle for the padding
-     */
-    InflateRect(prc, -DISPLAY_AREA_PADDINGX, -DISPLAY_AREA_PADDINGY);
-
-    /*
-     * Remove the height of the tabs.
-     */
-    if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM)
-      prc->bottom -= (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
-    else
-      prc->top += (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
-
-  }
-
-  return 0;
-}
-
-/******************************************************************************
- * TAB_OnHScroll
- *
- * This method will handle the notification from the scroll control and
- * perform the scrolling operation on the tab control.
- */
-static LRESULT TAB_OnHScroll(
-  HWND    hwnd,
-  int     nScrollCode,
-  int     nPos,
-  HWND    hwndScroll)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-  if(nScrollCode == SB_THUMBPOSITION && nPos != infoPtr->leftmostVisible)
-  {
-     if(nPos < infoPtr->leftmostVisible)
-        infoPtr->leftmostVisible--;
-     else
-        infoPtr->leftmostVisible++;
-
-     TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
-     TAB_InvalidateTabArea(hwnd, infoPtr);
-     SendMessageA(infoPtr->hwndUpDown, UDM_SETPOS, 0,
-                   MAKELONG(infoPtr->leftmostVisible, 0));
-   }
-
-   return 0;
-}
-
-/******************************************************************************
- * TAB_SetupScrolling
- *
- * This method will check the current scrolling state and make sure the
- * scrolling control is displayed (or not).
- */
-static void TAB_SetupScrolling(
-  HWND        hwnd,
-  TAB_INFO*   infoPtr,
-  const RECT* clientRect)
-{
-  INT maxRange = 0;
-
-  if (infoPtr->needsScrolling)
-  {
-    RECT controlPos;
-    INT vsize, tabwidth;
-
-    /*
-     * Calculate the position of the scroll control.
-     */
-    controlPos.right = clientRect->right;
-    controlPos.left  = controlPos.right - 2*GetSystemMetrics(SM_CXHSCROLL);
-
-    if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM)
-    {
-      controlPos.top    = clientRect->bottom - infoPtr->tabHeight;
-      controlPos.bottom = controlPos.top + GetSystemMetrics(SM_CYHSCROLL);
-    }
-    else
-    {
-      controlPos.bottom = clientRect->top + infoPtr->tabHeight;
-      controlPos.top    = controlPos.bottom - GetSystemMetrics(SM_CYHSCROLL);
-    }
-
-    /*
-     * If we don't have a scroll control yet, we want to create one.
-     * If we have one, we want to make sure it's positioned right.
-     */
-    if (infoPtr->hwndUpDown==0)
-    {
-      /*
-       * I use a scrollbar since it seems to be more stable than the Updown
-       * control.
-       */
-      infoPtr->hwndUpDown = CreateWindowA("msctls_updown32",
-					  "",
-					  WS_VISIBLE | WS_CHILD | UDS_HORZ,
-                                          controlPos.left, controlPos.top,
-                                          controlPos.right - controlPos.left,
-                                          controlPos.bottom - controlPos.top,
-                                          hwnd,
-                                          (HMENU)NULL,
-                                          (HINSTANCE)NULL,
-                                          NULL);
-    }
-    else
-    {
-      SetWindowPos(infoPtr->hwndUpDown,
-                   (HWND)NULL,
-                   controlPos.left, controlPos.top,
-                   controlPos.right - controlPos.left,
-                   controlPos.bottom - controlPos.top,
-                   SWP_SHOWWINDOW | SWP_NOZORDER);
-    }
-
-    /* Now calculate upper limit of the updown control range.
-     * We do this by calculating how many tabs will be offscreen when the
-     * last tab is visible.
-     */
-    if(infoPtr->uNumItem)
-    {
-       vsize = clientRect->right - (controlPos.right - controlPos.left + 1);
-       maxRange = infoPtr->uNumItem;
-       tabwidth = infoPtr->items[maxRange-1].rect.right;
-
-       for(; maxRange > 0; maxRange--)
-       {
-          if(tabwidth - infoPtr->items[maxRange - 1].rect.left > vsize)
-             break;
-       }
-
-       if(maxRange == infoPtr->uNumItem)
-          maxRange--;
-    }
-  }
-  else
-  {
-    /*
-     * If we once had a scroll control... hide it.
-     */
-    if (infoPtr->hwndUpDown!=0)
-    {
-      ShowWindow(infoPtr->hwndUpDown, SW_HIDE);
-    }
-  }
-
-  if (infoPtr->hwndUpDown)
-     SendMessageA(infoPtr->hwndUpDown, UDM_SETRANGE32, 0, maxRange);
-}
-
-/******************************************************************************
- * TAB_SetItemBounds
- *
- * This method will calculate the position rectangles of all the items in the
- * control. The rectangle calculated starts at 0 for the first item in the
- * list and ignores scrolling and selection.
- * It also uses the current font to determine the height of the tab row and
- * it checks if all the tabs fit in the client area of the window. If they
- * dont, a scrolling control is added.
- */
-static void TAB_SetItemBounds (HWND hwnd)
-{
-  TAB_INFO*   infoPtr = TAB_GetInfoPtr(hwnd);
-  LONG        lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
-  TEXTMETRICA fontMetrics;
-  INT         curItem;
-  INT         curItemLeftPos;
-  INT         curItemRowCount;
-  HFONT       hFont, hOldFont;
-  HDC         hdc;
-  RECT        clientRect;
-  SIZE        size;
-
-  /*
-   * We need to get text information so we need a DC and we need to select
-   * a font.
-   */
-  hdc = GetDC(hwnd);
-
-  hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
-  hOldFont = SelectObject (hdc, hFont);
-
-  /*
-   * We will base the rectangle calculations on the client rectangle
-   * of the control.
-   */
-  GetClientRect(hwnd, &clientRect);
-
-  /*
-   * The leftmost item will be "0" aligned
-   */
-  curItemLeftPos = 0;
-  curItemRowCount = 0;
-
-  if (!(lStyle & TCS_FIXEDWIDTH) && !((lStyle & TCS_OWNERDRAWFIXED) && infoPtr->fSizeSet))
-  {
-    int item_height;
-    int icon_height = 0;
-
-    /*
-     * Use the current font to determine the height of a tab.
-     */
-    GetTextMetricsA(hdc, &fontMetrics);
-
-    /*
-     * Get the icon height
-     */
-    if (infoPtr->himl)
-      ImageList_GetIconSize(infoPtr->himl, 0, &icon_height);
-
-    /*
-     * Take the highest between font or icon
-     */
-    if (fontMetrics.tmHeight > icon_height)
-      item_height = fontMetrics.tmHeight;
-    else
-      item_height = icon_height;
-
-    /*
-     * Make sure there is enough space for the letters + icon + growing the
-     * selected item + extra space for the selected item.
-     */
-    infoPtr->tabHeight = item_height + 2*VERTICAL_ITEM_PADDING +
-      SELECTED_TAB_OFFSET;
-  }
-
-  for (curItem = 0; curItem < infoPtr->uNumItem; curItem++)
-  {
-    /*
-     * Set the leftmost position of the tab.
-     */
-    infoPtr->items[curItem].rect.left = curItemLeftPos;
-
-    if ((lStyle & TCS_FIXEDWIDTH) || ((lStyle & TCS_OWNERDRAWFIXED) && infoPtr->fSizeSet))
-    {
-      infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left +
-                                           infoPtr->tabWidth +
-                                           2*HORIZONTAL_ITEM_PADDING;
-    }
-    else
-    {
-      int icon_width  = 0;
-      int num = 2;
-
-      /*
-       * Calculate how wide the tab is depending on the text it contains
-       */
-      GetTextExtentPoint32W(hdc, infoPtr->items[curItem].pszText,
-                            lstrlenW(infoPtr->items[curItem].pszText), &size);
-
-      /*
-       * Add the icon width
-       */
-      if (infoPtr->himl)
-      {
-        ImageList_GetIconSize(infoPtr->himl, &icon_width, 0);
-        num++;
-      }
-
-      infoPtr->items[curItem].rect.right = infoPtr->items[curItem].rect.left +
-                                           size.cx + icon_width +
-                                           num*HORIZONTAL_ITEM_PADDING;
-    }
-
-    /*
-     * Check if this is a multiline tab control and if so
-     * check to see if we should wrap the tabs
-     *
-     * Because we are going to arange all these tabs evenly
-     * really we are basically just counting rows at this point
-     *
-     */
-
-    if ((lStyle & TCS_MULTILINE)&&
-        (infoPtr->items[curItem].rect.right > clientRect.right))
-    {
-        infoPtr->items[curItem].rect.right -=
-                                      infoPtr->items[curItem].rect.left;
-	infoPtr->items[curItem].rect.left = 0;
-        curItemRowCount ++;
-    }
-
-    infoPtr->items[curItem].rect.bottom = 0;
-    infoPtr->items[curItem].rect.top = curItemRowCount;
-
-//    TRACE("TextSize: %i\n ", size.cx);
-//    TRACE("Rect: T %i, L %i, B %i, R %i\n",
-//        infoPtr->items[curItem].rect.top,
-//        infoPtr->items[curItem].rect.left,
-//        infoPtr->items[curItem].rect.bottom,
-//        infoPtr->items[curItem].rect.right);
-
-    /*
-     * The leftmost position of the next item is the rightmost position
-     * of this one.
-     */
-    if (lStyle & TCS_BUTTONS)
-      curItemLeftPos = infoPtr->items[curItem].rect.right + BUTTON_SPACINGX;
-    else
-      curItemLeftPos = infoPtr->items[curItem].rect.right;
-  }
-
-  if (!(lStyle & TCS_MULTILINE))
-  {
-    /*
-     * Check if we need a scrolling control.
-     */
-    infoPtr->needsScrolling = (curItemLeftPos + (2*SELECTED_TAB_OFFSET) >
-                               clientRect.right);
-
-    /* Don't need scrolling, then update infoPtr->leftmostVisible */
-    if(!infoPtr->needsScrolling)
-      infoPtr->leftmostVisible = 0;
-
-    TAB_SetupScrolling(hwnd, infoPtr, &clientRect);
-  }
-
-  /*
-   * Set the number of rows
-   */
-
-  infoPtr->uNumRows = curItemRowCount;
-
-   if ((lStyle & TCS_MULTILINE)&&(infoPtr->uNumItem > 0))
-   {
-      INT widthDiff,remainder;
-      INT tabPerRow,remTab;
-      INT iRow,iItm;
-      INT iIndexStart=0,iIndexEnd=0, iCount=0;
-
-      /*
-       * Ok Microsoft trys to even out the rows. place the same
-       * number of tabs in each row. So lets give that a shot
-       *
-       */
-
-      tabPerRow = infoPtr->uNumItem / (infoPtr->uNumRows + 1);
-      remTab = infoPtr->uNumItem % (infoPtr->uNumRows + 1);
-
-      for (iItm=0,iRow=0,iCount=0,curItemLeftPos=0;
-           iItm<infoPtr->uNumItem;
-           iItm++,iCount++)
-      {
-          if (iCount >= ((iRow<remTab)?tabPerRow+1:tabPerRow))
-          {
-              iRow++;
-              curItemLeftPos = 0;
-              iCount = 0;
-          }
-          /*
-           * normalize the current rect
-           */
-          infoPtr->items[iItm].rect.right -=
-            infoPtr->items[iItm].rect.left;
-          infoPtr->items[iItm].rect.left = 0;
-
-          infoPtr->items[iItm].rect.top = iRow;
-          infoPtr->items[iItm].rect.left +=curItemLeftPos;
-          infoPtr->items[iItm].rect.right +=curItemLeftPos;
-          if (lStyle & TCS_BUTTONS)
-            curItemLeftPos = infoPtr->items[iItm].rect.right +
-                             BUTTON_SPACINGX;
-          else
-            curItemLeftPos = infoPtr->items[iItm].rect.right;
-      }
-
-      /*
-       * Justify the rows
-       *
-       */
-      {
-         while(iIndexStart < infoPtr->uNumItem)
-        {
-        /*
-         * find the indexs of the row
-         */
-        for (iIndexEnd=iIndexStart;
-             (iIndexEnd < infoPtr->uNumItem) &&
- 	       (infoPtr->items[iIndexEnd].rect.top ==
-                infoPtr->items[iIndexStart].rect.top) ;
-            iIndexEnd++)
-        /* intentionaly blank */;
-
-        /*
-         * we need to justify these tabs so they fill the whole given
-         * client area
-         *
-         */
-        widthDiff = clientRect.right - (2*SELECTED_TAB_OFFSET) -
-                            infoPtr->items[iIndexEnd-1].rect.right;
-
-        iCount = iIndexEnd-iIndexStart;
-
-        if (iCount)
-        {
-           INT iIndex;
-           remainder = widthDiff % iCount;
-           widthDiff = widthDiff / iCount;
-           for (iIndex=iIndexStart,iCount=0; iIndex < iIndexEnd;
-                iIndex++,iCount++)
-           {
-              infoPtr->items[iIndex].rect.left +=iCount*widthDiff;
-              infoPtr->items[iIndex].rect.right +=(iCount+1)*widthDiff;
-           }
-           infoPtr->items[iIndex-1].rect.right += remainder;
-        }
-
-        iIndexStart=iIndexEnd;
-        }
-      }
-  }
-
-  TAB_EnsureSelectionVisible(hwnd,infoPtr);
-  TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
-
-  /*
-   * Cleanup
-   */
-  SelectObject (hdc, hOldFont);
-  ReleaseDC (hwnd, hdc);
-}
-
-/******************************************************************************
- * TAB_DrawItemInterior
- *
- * This method is used to draw the interior (text and icon) of a single tab
- * into the tab control.
- */
-static void
-TAB_DrawItemInterior
-  (
-  HWND        hwnd,
-  HDC         hdc,
-  INT         iItem,
-  RECT*       drawRect
-  )
-{
-  TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd);
-  LONG      lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
-
-  RECT localRect;
-
-  HPEN   htextPen   = GetSysColorPen (COLOR_BTNTEXT);
-  HPEN   holdPen;
-  INT    oldBkMode;
-
-  if (drawRect == NULL)
-  {
-    BOOL isVisible;
-    RECT itemRect;
-    RECT selectedRect;
-
-    /*
-     * Get the rectangle for the item.
-     */
-    isVisible = TAB_InternalGetItemRect
-      (
-      hwnd,
-      infoPtr,
-      iItem,
-      &itemRect,
-      &selectedRect
-      );
-    if (!isVisible)
-      return;
-
-    /*
-     * Make sure drawRect points to something valid; simplifies code.
-     */
-    drawRect = &localRect;
-
-    /*
-     * This logic copied from the part of TAB_DrawItem which draws
-     * the tab background.  It's important to keep it in sync.  I
-     * would have liked to avoid code duplication, but couldn't figure
-     * out how without making spaghetti of TAB_DrawItem.
-     */
-    if (lStyle & TCS_BUTTONS)
-    {
-      *drawRect = itemRect;
-      if (iItem == infoPtr->iSelected)
-      {
-        drawRect->right--;
-        drawRect->bottom--;
-      }
-    }
-    else
-    {
-      if (iItem == infoPtr->iSelected)
-        *drawRect = selectedRect;
-      else
-        *drawRect = itemRect;
-      drawRect->right--;
-      drawRect->bottom--;
-    }
-  }
-
-  /*
-   * Text pen
-   */
-  holdPen = SelectObject(hdc, htextPen);
-
-  oldBkMode = SetBkMode(hdc, TRANSPARENT);
-  SetTextColor
-    (
-    hdc,
-    GetSysColor
-      (
-      (iItem == infoPtr->iHotTracked) ? COLOR_HIGHLIGHT : COLOR_BTNTEXT
-      )
-    );
-
-  /*
-   * Deflate the rectangle to acount for the padding
-   */
-  InflateRect(drawRect, -HORIZONTAL_ITEM_PADDING, -VERTICAL_ITEM_PADDING);
-
-  /*
-   * if owner draw, tell the owner to draw
-   */
-  if ( (lStyle & TCS_OWNERDRAWFIXED) && GetParent(hwnd) )
-  {
-    DRAWITEMSTRUCT dis;
-    UINT id;
-
-    /*
-     * get the control id
-     */
-    id = GetWindowLongA(hwnd,GWL_ID);
-
-    /*
-     * put together the DRAWITEMSTRUCT
-     */
-    dis.CtlType    = ODT_TAB;	
-    dis.CtlID      = id;		
-    dis.itemID     = iItem;		
-    dis.itemAction = ODA_DRAWENTIRE;	
-    if ( iItem == infoPtr->iSelected )
-      dis.itemState = ODS_SELECTED;	
-    else				
-      dis.itemState = 0;		
-    dis.hwndItem = hwnd;		/* */
-    dis.hDC      = hdc;		
-    dis.rcItem   = *drawRect;		/* */
-    dis.itemData = infoPtr->items[iItem].lParam;
-
-    /*
-     * send the draw message
-     */
-    SendMessageA( GetParent(hwnd), WM_DRAWITEM, (WPARAM)id, (LPARAM)&dis );
-  }
-  else
-  {
-    UINT uHorizAlign;
-
-    /*
-     * If not owner draw, then do the drawing ourselves.
-     *
-     * Draw the icon.
-     */
-    if (infoPtr->himl && (infoPtr->items[iItem].mask & TCIF_IMAGE))
-    {
-      INT cx;
-      INT cy;
-
-      ImageList_Draw
-        (
-        infoPtr->himl,
-        infoPtr->items[iItem].iImage,
-        hdc,
-        drawRect->left,
-        drawRect->top + 1,
-        ILD_NORMAL
-        );
-      ImageList_GetIconSize(infoPtr->himl, &cx, &cy);
-      drawRect->left += (cx + HORIZONTAL_ITEM_PADDING);
-    }
-
-    /*
-     * Draw the text;
-     */
-    if (lStyle & TCS_RIGHTJUSTIFY)
-      uHorizAlign = DT_CENTER;
-    else
-      uHorizAlign = DT_LEFT;
-
-    DrawTextW
-      (
-      hdc,
-      infoPtr->items[iItem].pszText,
-      lstrlenW(infoPtr->items[iItem].pszText),
-      drawRect,
-      uHorizAlign | DT_SINGLELINE | DT_VCENTER
-      );
-  }
-
-  /*
-  * Cleanup
-  */
-  SetBkMode(hdc, oldBkMode);
-  SelectObject(hdc, holdPen);
-}
-
-/******************************************************************************
- * TAB_DrawItem
- *
- * This method is used to draw a single tab into the tab control.
- */
-static void TAB_DrawItem(
-  HWND hwnd,
-  HDC  hdc,
-  INT  iItem)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  LONG      lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
-  RECT      itemRect;
-  RECT      selectedRect;
-  BOOL      isVisible;
-  RECT      r;
-
-  /*
-   * Get the rectangle for the item.
-   */
-  isVisible = TAB_InternalGetItemRect(hwnd,
-                                      infoPtr,
-                                      iItem,
-                                      &itemRect,
-                                      &selectedRect);
-
-  if (isVisible)
-  {
-    HBRUSH hbr       = CreateSolidBrush (GetSysColor(COLOR_BTNFACE));
-    HPEN   hwPen     = GetSysColorPen (COLOR_3DHILIGHT);
-    HPEN   hbPen     = GetSysColorPen (COLOR_BTNSHADOW);
-    HPEN   hfocusPen = CreatePen(PS_DOT, 1, GetSysColor(COLOR_BTNTEXT));
-    HPEN   holdPen;
-    INT    oldBkMode;
-    BOOL deleteBrush = TRUE;
-
-    if (lStyle & TCS_BUTTONS)
-    {
-      /*
-       * Get item rectangle.
-       */
-      r = itemRect;
-
-      holdPen = SelectObject (hdc, hwPen);
-
-      if (iItem == infoPtr->iSelected)
-      {
-        /*
-         * Background color.
-         */
-        if (!((lStyle & TCS_OWNERDRAWFIXED) && infoPtr->fSizeSet))
-        {
-          COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
-          DeleteObject(hbr);
-          hbr = GetSysColorBrush(COLOR_SCROLLBAR);
-          SetTextColor(hdc, GetSysColor(COLOR_3DFACE));
-          SetBkColor(hdc, bk);
-
-          /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
-           * we better use 0x55aa bitmap brush to make scrollbar's background
-           * look different from the window background.
-           */
-          if (bk == GetSysColor(COLOR_WINDOW))
-              hbr = GetPattern55AABrush();
-
-          deleteBrush = FALSE;
-        }
-
-        /*
-         * Erase the background.
-         */
-        FillRect(hdc, &r, hbr);
-
-        /*
-         * Draw the tab now.
-         * The rectangles calculated exclude the right and bottom
-         * borders of the rectangle. To simply the following code, those
-         * borders are shaved-off beforehand.
-         */
-        r.right--;
-        r.bottom--;
-
-        /* highlight */
-        MoveToEx (hdc, r.left, r.bottom, NULL);
-        LineTo   (hdc, r.right, r.bottom);
-        LineTo   (hdc, r.right, r.top);
-
-        /* shadow */
-        SelectObject(hdc, hbPen);
-        LineTo  (hdc, r.left, r.top);
-        LineTo  (hdc, r.left, r.bottom);
-      }
-      else
-      {
-        /*
-         * Erase the background.
-         */
-        FillRect(hdc, &r, hbr);
-
-        /* highlight */
-        MoveToEx (hdc, r.left, r.bottom, NULL);
-        LineTo   (hdc, r.left, r.top);
-        LineTo   (hdc, r.right, r.top);
-
-        /* shadow */
-        SelectObject(hdc, hbPen);
-        LineTo  (hdc, r.right, r.bottom);
-        LineTo  (hdc, r.left, r.bottom);
-      }
-    }
-    else
-    {
-      /*
-       * Background color.
-       */
-      DeleteObject(hbr);
-      hbr = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
-
-      /*
-       * We draw a rectangle of different sizes depending on the selection
-       * state.
-       */
-      if (iItem == infoPtr->iSelected)
-        r = selectedRect;
-      else
-        r = itemRect;
-
-      /*
-       * Erase the background.
-       * This is necessary when drawing the selected item since it is larger
-       * than the others, it might overlap with stuff already drawn by the
-       * other tabs
-       */
-      FillRect(hdc, &r, hbr);
-
-      /*
-       * Draw the tab now.
-       * The rectangles calculated exclude the right and bottom
-       * borders of the rectangle. To simply the following code, those
-       * borders are shaved-off beforehand.
-       */
-      r.right--;
-      r.bottom--;
-
-      holdPen = SelectObject (hdc, hwPen);
-
-      if (lStyle & TCS_BOTTOM)
-      {
-        /* highlight */
-        MoveToEx (hdc, r.left, r.top, NULL);
-        LineTo   (hdc, r.left, r.bottom - ROUND_CORNER_SIZE);
-        LineTo   (hdc, r.left + ROUND_CORNER_SIZE, r.bottom);
-
-        /* shadow */
-        SelectObject(hdc, hbPen);
-        LineTo  (hdc, r.right - ROUND_CORNER_SIZE, r.bottom);
-        LineTo  (hdc, r.right, r.bottom - ROUND_CORNER_SIZE);
-        LineTo  (hdc, r.right, r.top);
-      }
-      else
-      {
-        /* highlight */
-        MoveToEx (hdc, r.left, r.bottom, NULL);
-        LineTo   (hdc, r.left, r.top + ROUND_CORNER_SIZE);
-        LineTo   (hdc, r.left + ROUND_CORNER_SIZE, r.top);
-        LineTo   (hdc, r.right - ROUND_CORNER_SIZE, r.top);
-
-        /* shadow */
-        SelectObject(hdc, hbPen);
-        LineTo (hdc, r.right,  r.top + ROUND_CORNER_SIZE);
-        LineTo (hdc, r.right,  r.bottom);
-      }
-    }
-
-    oldBkMode = SetBkMode(hdc, TRANSPARENT);
-
-    /* This modifies r to be the text rectangle. */
-    TAB_DrawItemInterior(hwnd, hdc, iItem, &r);
-
-    /*
-     * Draw the focus rectangle
-     */
-    if (((lStyle & TCS_FOCUSNEVER) == 0) &&
-         (GetFocus() == hwnd) &&
-         (iItem == infoPtr->uFocus) )
-    {
-      InflateRect(&r, FOCUS_RECT_HOFFSET, FOCUS_RECT_VOFFSET);
-
-      SelectObject(hdc, hfocusPen);
-
-      MoveToEx (hdc, r.left,    r.top, NULL);
-      LineTo   (hdc, r.right-1, r.top);
-      LineTo   (hdc, r.right-1, r.bottom -1);
-      LineTo   (hdc, r.left,    r.bottom -1);
-      LineTo   (hdc, r.left,    r.top);
-    }
-
-    /*
-     * Cleanup
-     */
-    SetBkMode(hdc, oldBkMode);
-    SelectObject(hdc, holdPen);
-    DeleteObject(hfocusPen);
-    if (deleteBrush) DeleteObject(hbr);
-  }
-}
-
-/******************************************************************************
- * TAB_DrawBorder
- *
- * This method is used to draw the raised border around the tab control
- * "content" area.
- */
-static void TAB_DrawBorder (HWND hwnd, HDC hdc)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  HPEN htmPen;
-  HPEN hwPen  = GetSysColorPen (COLOR_3DHILIGHT);
-  HPEN hbPen  = GetSysColorPen (COLOR_3DDKSHADOW);
-  HPEN hShade = GetSysColorPen (COLOR_BTNSHADOW);
-  RECT rect;
-
-  GetClientRect (hwnd, &rect);
-
-  /*
-   * Adjust for the style
-   */
-  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM)
-  {
-    rect.bottom -= (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
-  }
-  else
-  {
-    rect.top += (infoPtr->tabHeight - 2) * (infoPtr->uNumRows + 1) + 2;
-  }
-
-  /*
-   * Shave-off the right and bottom margins (exluded in the
-   * rect)
-   */
-  rect.right--;
-  rect.bottom--;
-
-  /* highlight */
-  htmPen = SelectObject (hdc, hwPen);
-
-  MoveToEx (hdc, rect.left, rect.bottom, NULL);
-  LineTo (hdc, rect.left, rect.top);
-  LineTo (hdc, rect.right, rect.top);
-
-  /* Dark Shadow */
-  SelectObject (hdc, hbPen);
-  LineTo (hdc, rect.right, rect.bottom );
-  LineTo (hdc, rect.left, rect.bottom);
-
-  /* shade */
-  SelectObject (hdc, hShade );
-  MoveToEx (hdc, rect.right-1, rect.top, NULL);
-  LineTo   (hdc, rect.right-1, rect.bottom-1);
-  LineTo   (hdc, rect.left,    rect.bottom-1);
-
-  SelectObject(hdc, htmPen);
-}
-
-/******************************************************************************
- * TAB_Refresh
- *
- * This method repaints the tab control..
- */
-static void TAB_Refresh (HWND hwnd, HDC hdc)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  HFONT hOldFont;
-  INT i;
-
-  if (!infoPtr->DoRedraw)
-    return;
-
-  hOldFont = SelectObject (hdc, infoPtr->hFont);
-
-  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS)
-  {
-    for (i = 0; i < infoPtr->uNumItem; i++)
-    {
-        TAB_DrawItem (hwnd, hdc, i);
-    }
-  }
-  else
-  {
-    /*
-     * Draw all the non selected item first.
-     */
-    for (i = 0; i < infoPtr->uNumItem; i++)
-    {
-      if (i != infoPtr->iSelected)
-        TAB_DrawItem (hwnd, hdc, i);
-    }
-
-    /*
-     * Now, draw the border, draw it before the selected item
-     * since the selected item overwrites part of the border.
-     */
-    TAB_DrawBorder (hwnd, hdc);
-
-    /*
-     * Then, draw the selected item
-     */
-    TAB_DrawItem (hwnd, hdc, infoPtr->iSelected);
-
-    /*
-     * If we haven't set the current focus yet, set it now.
-     * Only happens when we first paint the tab controls.
-     */
-     if (infoPtr->uFocus == -1)
-       TAB_SetCurFocus(hwnd, infoPtr->iSelected);
-  }
-
-  SelectObject (hdc, hOldFont);
-}
-
-static LRESULT
-TAB_SetRedraw (HWND hwnd, WPARAM wParam)
-{
-    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-  infoPtr->DoRedraw=(BOOL) wParam;
-  return 0;
-}
-
-static LRESULT TAB_EraseBackground(
-  HWND hwnd,
-  HDC  givenDC)
-{
-  HDC  hdc;
-  RECT clientRect;
-
-  HBRUSH brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
-
-  hdc = givenDC ? givenDC : GetDC(hwnd);
-
-  GetClientRect(hwnd, &clientRect);
-
-  FillRect(hdc, &clientRect, brush);
-
-  if (givenDC==0)
-    ReleaseDC(hwnd, hdc);
-
-  DeleteObject(brush);
-
-  return 0;
-}
-
-/******************************************************************************
- * TAB_EnsureSelectionVisible
- *
- * This method will make sure that the current selection is completely
- * visible by scrolling until it is.
- */
-static void TAB_EnsureSelectionVisible(
-  HWND      hwnd,
-  TAB_INFO* infoPtr)
-{
-  INT iSelected = infoPtr->iSelected;
-
-  INT iOrigLeftmostVisible = infoPtr->leftmostVisible;
-
-  /*
-   * set the items row to the bottommost row or topmost row depending on
-   * style
-   */
-
-  if (infoPtr->uNumRows > 0)
-  {
-      INT newselected=infoPtr->items[iSelected].rect.top;
-      INT iTargetRow;
-      LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-
-      if (lStyle & TCS_BOTTOM)
-          iTargetRow = 0;
-      else
-          iTargetRow = infoPtr->uNumRows;
-
-      if (newselected != iTargetRow)
-      {
-         INT i;
-         for (i=0; i < infoPtr->uNumItem; i++)
-             if (infoPtr->items[i].rect.top == newselected )
-                 infoPtr->items[i].rect.top = iTargetRow;
-             else if (lStyle&TCS_BOTTOM)
-                 {
-                  if (infoPtr->items[i].rect.top < newselected)
-                     infoPtr->items[i].rect.top+=1;
-                 }
-                 else
-                 {
-                   if (infoPtr->items[i].rect.top > newselected)
-                     infoPtr->items[i].rect.top-=1;
-                 }
-
-        TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
-      }
-  }
-
-  /*
-   * Do the trivial cases first.
-   */
-  if ( (!infoPtr->needsScrolling) ||
-       (infoPtr->hwndUpDown==0) )
-    return;
-
-  if (infoPtr->leftmostVisible >= iSelected)
-  {
-    infoPtr->leftmostVisible = iSelected;
-  }
-  else
-  {
-     RECT r;
-     INT  width, i;
-     /*
-      * Calculate the part of the client area that is visible.
-      */
-     GetClientRect(hwnd, &r);
-     width = r.right;
-
-     GetClientRect(infoPtr->hwndUpDown, &r);
-     width -= r.right;
-
-     if ((infoPtr->items[iSelected].rect.right -
-          infoPtr->items[iSelected].rect.left) >= width )
-     {
-        /* Special case: width of selected item is greater than visible
-         * part of control.
-         */
-        infoPtr->leftmostVisible = iSelected;
-     }
-     else
-     {
-        for (i = infoPtr->leftmostVisible; i < infoPtr->uNumItem; i++)
-        {
-           if ((infoPtr->items[iSelected].rect.right -
-                infoPtr->items[i].rect.left) < width)
-              break;
-        }
-        infoPtr->leftmostVisible = i;
-     }
-  }
-
-  if (infoPtr->leftmostVisible != iOrigLeftmostVisible)
-    TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL);
-
-  SendMessageA(infoPtr->hwndUpDown, UDM_SETPOS, 0,
-               MAKELONG(infoPtr->leftmostVisible, 0));
-}
-
-/******************************************************************************
- * TAB_InvalidateTabArea
- *
- * This method will invalidate the portion of the control that contains the
- * tabs. It is called when the state of the control changes and needs
- * to be redisplayed
- */
-static void TAB_InvalidateTabArea(
-  HWND      hwnd,
-  TAB_INFO* infoPtr)
-{
-  RECT clientRect;
-
-  GetClientRect(hwnd, &clientRect);
-
-  if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BOTTOM)
-  {
-    clientRect.top = clientRect.bottom - (infoPtr->tabHeight *
-                                           (infoPtr->uNumRows + 1) + 3);
-  }
-  else
-  {
-    clientRect.bottom = clientRect.top + (infoPtr->tabHeight *
-                                           (infoPtr->uNumRows + 1) + 1);
-  }
-
-  InvalidateRect(hwnd, &clientRect, TRUE);
-}
-
-static LRESULT
-TAB_Paint (HWND hwnd, WPARAM wParam)
-{
-  HDC hdc;
-  PAINTSTRUCT ps;
-
-  hdc = wParam== 0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
-  TAB_Refresh (hwnd, hdc);
-
-  if(!wParam)
-    EndPaint (hwnd, &ps);
-
-  return 0;
-}
-
-static LRESULT TAB_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  TCITEMA *pti;
-  INT iItem, len;
-  RECT rect;
-
-  GetClientRect (hwnd, &rect);
-//  TRACE(tab, "Rect: %x T %i, L %i, B %i, R %i\n", hwnd,
-//        rect.top, rect.left, rect.bottom, rect.right);
-
-  pti = (TCITEMA *)lParam;
-  iItem = (INT)wParam;
-
-  if (iItem < 0) return -1;
-  if (iItem > infoPtr->uNumItem)
-    iItem = infoPtr->uNumItem;
-
-  if (infoPtr->uNumItem == 0) {
-    infoPtr->items = (TAB_ITEM*)COMCTL32_Alloc (sizeof (TAB_ITEM));
-    infoPtr->uNumItem++;
-    infoPtr->iSelected = 0;
-  }
-  else {
-    TAB_ITEM *oldItems = infoPtr->items;
-
-    infoPtr->uNumItem++;
-    infoPtr->items = (TAB_ITEM*)COMCTL32_Alloc (sizeof (TAB_ITEM) * infoPtr->uNumItem);
-
-    /* pre insert copy */
-    if (iItem > 0) {
-      memcpy (&infoPtr->items[0], &oldItems[0],
-              iItem * sizeof(TAB_ITEM));
-    }
-
-    /* post insert copy */
-    if (iItem < infoPtr->uNumItem - 1) {
-      memcpy (&infoPtr->items[iItem+1], &oldItems[iItem],
-              (infoPtr->uNumItem - iItem - 1) * sizeof(TAB_ITEM));
-
-    }
-
-    if (iItem <= infoPtr->iSelected)
-      infoPtr->iSelected++;
-
-    COMCTL32_Free (oldItems);
-  }
-
-  infoPtr->items[iItem].mask = pti->mask;
-  if (pti->mask & TCIF_TEXT) {
-    len = lstrlenA (pti->pszText);
-    infoPtr->items[iItem].pszText = (WCHAR*)COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
-    lstrcpyAtoW (infoPtr->items[iItem].pszText, pti->pszText);
-    infoPtr->items[iItem].cchTextMax = pti->cchTextMax;
-  }
-
-  if (pti->mask & TCIF_IMAGE)
-    infoPtr->items[iItem].iImage = pti->iImage;
-
-  if (pti->mask & TCIF_PARAM)
-    infoPtr->items[iItem].lParam = pti->lParam;
-
-  TAB_SetItemBounds(hwnd);
-  TAB_InvalidateTabArea(hwnd, infoPtr);
-
-//  TRACE(tab, "[%04x]: added item %d '%s'\n",
-//      hwnd, iItem, infoPtr->items[iItem].pszText);
-
-  return iItem;
-}
-
-static LRESULT TAB_InsertItemW(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  TCITEMW *pti;
-  INT iItem, len;
-  RECT rect;
-
-  GetClientRect (hwnd, &rect);
-//  TRACE(tab, "Rect: %x T %i, L %i, B %i, R %i\n", hwnd,
-//        rect.top, rect.left, rect.bottom, rect.right);
-
-  pti = (TCITEMW*)lParam;
-  iItem = (INT)wParam;
-
-  if (iItem < 0) return -1;
-  if (iItem > infoPtr->uNumItem)
-    iItem = infoPtr->uNumItem;
-
-  if (infoPtr->uNumItem == 0) {
-    infoPtr->items = (TAB_ITEM*)COMCTL32_Alloc (sizeof (TAB_ITEM));
-    infoPtr->uNumItem++;
-  }
-  else {
-    TAB_ITEM *oldItems = infoPtr->items;
-
-    infoPtr->uNumItem++;
-    infoPtr->items = (TAB_ITEM*)COMCTL32_Alloc (sizeof (TAB_ITEM) * infoPtr->uNumItem);
-
-    /* pre insert copy */
-    if (iItem > 0) {
-      memcpy (&infoPtr->items[0], &oldItems[0],
-              iItem * sizeof(TAB_ITEM));
-    }
-
-    /* post insert copy */
-    if (iItem < infoPtr->uNumItem - 1) {
-      memcpy (&infoPtr->items[iItem+1], &oldItems[iItem],
-              (infoPtr->uNumItem - iItem - 1) * sizeof(TAB_ITEM));
-
-    }
-
-    COMCTL32_Free (oldItems);
-  }
-
-  infoPtr->items[iItem].mask = pti->mask;
-  if (pti->mask & TCIF_TEXT) {
-    len = lstrlenW (pti->pszText);
-    infoPtr->items[iItem].pszText = (WCHAR*)COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
-    lstrcpyW (infoPtr->items[iItem].pszText, pti->pszText);
-    infoPtr->items[iItem].cchTextMax = pti->cchTextMax;
-  }
-
-  if (pti->mask & TCIF_IMAGE)
-    infoPtr->items[iItem].iImage = pti->iImage;
-
-  if (pti->mask & TCIF_PARAM)
-    infoPtr->items[iItem].lParam = pti->lParam;
-
-  TAB_SetItemBounds(hwnd);
-  TAB_InvalidateTabArea(hwnd, infoPtr);
-
-//  TRACE(tab, "[%04x]: added item %d '%s'\n",
-//      hwnd, iItem, infoPtr->items[iItem].pszText);
-
-  return iItem;
-}
-
-static LRESULT
-TAB_SetItemSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  LONG lResult = 0;
-
-  if ((lStyle & TCS_FIXEDWIDTH) || (lStyle & TCS_OWNERDRAWFIXED))
-  {
-    lResult = MAKELONG(infoPtr->tabWidth, infoPtr->tabHeight);
-    infoPtr->tabWidth = (INT)LOWORD(lParam);
-    infoPtr->tabHeight = (INT)HIWORD(lParam);
-  }
-
-  infoPtr->fSizeSet = TRUE;
-
-  return lResult;
-}
-
-static LRESULT
-TAB_SetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  TCITEMA *tabItem;
-  TAB_ITEM *wineItem;
-  INT    iItem,len;
-
-  iItem=(INT) wParam;
-  tabItem=(LPTCITEMA ) lParam;
-//  TRACE("%d %p\n",iItem, tabItem);
-  if ((iItem<0) || (iItem>infoPtr->uNumItem)) return FALSE;
-
-  wineItem=& infoPtr->items[iItem];
-
-  if (tabItem->mask & TCIF_IMAGE)
-    wineItem->iImage=tabItem->iImage;
-
-  if (tabItem->mask & TCIF_PARAM)
-    wineItem->lParam=tabItem->lParam;
-
-//  if (tabItem->mask & TCIF_RTLREADING)
-//    FIXME("TCIF_RTLREADING\n");
-
-  if (tabItem->mask & TCIF_STATE)
-    wineItem->dwState=tabItem->dwState;
-
-  if (tabItem->mask & TCIF_TEXT) {
-   len=lstrlenA (tabItem->pszText);
-   if (len > wineItem->cchTextMax)
-     wineItem->pszText = (WCHAR*)COMCTL32_ReAlloc(wineItem->pszText,(len+1)*sizeof(WCHAR));
-   lstrcpyAtoW(wineItem->pszText,tabItem->pszText);
-  }
-
-  /*
-   * Update and repaint tabs.
-   */
-  TAB_SetItemBounds(hwnd);
-  TAB_InvalidateTabArea(hwnd,infoPtr);
-
-  return TRUE;
-}
-
-static LRESULT TAB_SetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  TCITEMW *tabItem;
-  TAB_ITEM *wineItem;
-  INT    iItem,len;
-
-  iItem=(INT) wParam;
-  tabItem=(LPTCITEMW) lParam;
-//  TRACE (tab,"%d %p\n",iItem, tabItem);
-  if ((iItem<0) || (iItem>infoPtr->uNumItem)) return FALSE;
-
-  wineItem=& infoPtr->items[iItem];
-
-  if (tabItem->mask & TCIF_IMAGE)
-    wineItem->iImage=tabItem->iImage;
-
-  if (tabItem->mask & TCIF_PARAM)
-    wineItem->lParam=tabItem->lParam;
-
-//  if (tabItem->mask & TCIF_RTLREADING)
-//    FIXME (tab,"TCIF_RTLREADING\n");
-
-  if (tabItem->mask & TCIF_STATE)
-    wineItem->dwState=tabItem->dwState;
-
-  if (tabItem->mask & TCIF_TEXT) {
-   len = lstrlenW (tabItem->pszText);
-   if (len>wineItem->cchTextMax)
-     wineItem->pszText = (WCHAR*)COMCTL32_ReAlloc (wineItem->pszText, (len+1)*sizeof(WCHAR));
-   lstrcpyW (wineItem->pszText, tabItem->pszText);
-  }
-
-  return TRUE;
-}
-
-static LRESULT
-TAB_GetItemCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-   TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-   return infoPtr->uNumItem;
-}
-
-
-static LRESULT
-TAB_GetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-   TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-   TCITEMA *tabItem;
-   TAB_ITEM *wineItem;
-   INT    iItem;
-
-  iItem=(INT) wParam;
-  tabItem=(LPTCITEMA) lParam;
-//  TRACE (tab,"\n");
-  if ((iItem<0) || (iItem>=infoPtr->uNumItem)) return FALSE;
-
-  wineItem=& infoPtr->items[iItem];
-
-  if (tabItem->mask & TCIF_IMAGE)
-    tabItem->iImage=wineItem->iImage;
-
-  if (tabItem->mask & TCIF_PARAM)
-    tabItem->lParam=wineItem->lParam;
-
-//  if (tabItem->mask & TCIF_RTLREADING)
-//    FIXME (tab, "TCIF_RTLREADING\n");
-
-  if (tabItem->mask & TCIF_STATE)
-    tabItem->dwState=wineItem->dwState;
-
-  if (tabItem->mask & TCIF_TEXT)
-   lstrcpynWtoA (tabItem->pszText, wineItem->pszText, tabItem->cchTextMax);
-
-  return TRUE;
-}
-
-static LRESULT TAB_GetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-   TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-   TCITEMW *tabItem;
-   TAB_ITEM *wineItem;
-   INT    iItem;
-
-  iItem=(INT) wParam;
-  tabItem=(LPTCITEMW) lParam;
-//  TRACE (tab,"\n");
-  if ((iItem<0) || (iItem>infoPtr->uNumItem)) return FALSE;
-
-  wineItem=& infoPtr->items[iItem];
-
-  if (tabItem->mask & TCIF_IMAGE)
-    tabItem->iImage=wineItem->iImage;
-
-  if (tabItem->mask & TCIF_PARAM)
-    tabItem->lParam=wineItem->lParam;
-
-//  if (tabItem->mask & TCIF_RTLREADING)
-//    FIXME (tab, "TCIF_RTLREADING\n");
-
-  if (tabItem->mask & TCIF_STATE)
-    tabItem->dwState=wineItem->dwState;
-
-  if (tabItem->mask & TCIF_TEXT)
-   lstrcpynW (tabItem->pszText, wineItem->pszText, tabItem->cchTextMax);
-
-  return TRUE;
-}
-
-static LRESULT
-TAB_DeleteItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  INT iItem = (INT) wParam;
-  BOOL bResult = FALSE;
-
-  if ((iItem >= 0) && (iItem < infoPtr->uNumItem))
-  {
-    TAB_ITEM *oldItems = infoPtr->items;
-
-    infoPtr->uNumItem--;
-    infoPtr->items = (TAB_ITEM*)COMCTL32_Alloc(sizeof (TAB_ITEM) * infoPtr->uNumItem);
-
-    if (iItem > 0)
-      memcpy(&infoPtr->items[0], &oldItems[0], iItem * sizeof(TAB_ITEM));
-
-    if (iItem < infoPtr->uNumItem)
-      memcpy(&infoPtr->items[iItem], &oldItems[iItem + 1],
-              (infoPtr->uNumItem - iItem) * sizeof(TAB_ITEM));
-
-    COMCTL32_Free (oldItems);
-
-    /*
-     * Readjust the selected index.
-     */
-    if ((iItem == infoPtr->iSelected) && (iItem > 0))
-      infoPtr->iSelected--;
-
-    if (iItem < infoPtr->iSelected)
-      infoPtr->iSelected--;
-
-    if (infoPtr->uNumItem == 0)
-      infoPtr->iSelected = -1;
-
-    /*
-     * Reposition and repaint tabs.
-     */
-    TAB_SetItemBounds(hwnd);
-    TAB_InvalidateTabArea(hwnd,infoPtr);
-
-    bResult = TRUE;
-  }
-
-  return bResult;
-}
-
-static LRESULT
-TAB_DeleteAllItems (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-   TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-  COMCTL32_Free (infoPtr->items);
-  infoPtr->uNumItem = 0;
-  infoPtr->iSelected = -1;
-  if (infoPtr->iHotTracked >= 0)
-    KillTimer(hwnd, TAB_HOTTRACK_TIMER);
-  infoPtr->iHotTracked = -1;
-
-  TAB_SetItemBounds(hwnd);
-  TAB_InvalidateTabArea(hwnd,infoPtr);
-
-  return TRUE;
-}
-
-
-static LRESULT
-TAB_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-//  TRACE (tab,"\n");
-  return (LRESULT)infoPtr->hFont;
-}
-
-static LRESULT
-TAB_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
-
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-//  TRACE (tab,"%x %lx\n",wParam, lParam);
-
-  infoPtr->hFont = (HFONT)wParam;
-
-  TAB_SetItemBounds(hwnd);
-
-  TAB_InvalidateTabArea(hwnd, infoPtr);
-
-  return 0;
-}
-
-
-static LRESULT
-TAB_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-
-//  TRACE (tab,"\n");
-  return (LRESULT)infoPtr->himl;
-}
-
-static LRESULT
-TAB_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-    HIMAGELIST himlPrev;
-
-//    TRACE (tab,"\n");
-    himlPrev = infoPtr->himl;
-    infoPtr->himl= (HIMAGELIST)lParam;
-    return (LRESULT)himlPrev;
-}
-
-
-static LRESULT
-TAB_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
-
-{
-/* I'm not really sure what the following code was meant to do.
-   This is what it is doing:
-   When WM_SIZE is sent with SIZE_RESTORED, the control
-   gets positioned in the top left corner.
-
-  RECT parent_rect;
-  HWND parent;
-  UINT uPosFlags,cx,cy;
-
-  uPosFlags=0;
-  if (!wParam) {
-    parent = GetParent (hwnd);
-    GetClientRect(parent, &parent_rect);
-    cx=LOWORD (lParam);
-    cy=HIWORD (lParam);
-    if (GetWindowLongA(hwnd, GWL_STYLE) & CCS_NORESIZE)
-        uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
-
-    SetWindowPos (hwnd, 0, parent_rect.left, parent_rect.top,
-            cx, cy, uPosFlags | SWP_NOZORDER);
-  } else {
-//    FIXME (tab,"WM_SIZE flag %x %lx not handled\n", wParam, lParam);
-  } */
-
-  /*
-   * Recompute the size/position of the tabs.
-   */
-  TAB_SetItemBounds (hwnd);
-
-  /*
-   * Force a repaint of the control.
-   */
-  InvalidateRect(hwnd, NULL, TRUE);
-
-  return 0;
-}
-
-
-static LRESULT
-TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr;
-  TEXTMETRICA fontMetrics;
-  HDC hdc;
-  HFONT hOldFont;
-  DWORD dwStyle;
-
-  infoPtr = (TAB_INFO*)initControl(hwnd,sizeof(TAB_INFO));
-
-  infoPtr->uNumItem        = 0;
-  infoPtr->uNumRows        = 0;
-  infoPtr->hFont           = 0;
-  infoPtr->items           = 0;
-  infoPtr->hcurArrow       = LoadCursorA (0, IDC_ARROWA);
-  infoPtr->iSelected       = -1;
-  infoPtr->iHotTracked     = -1;
-  infoPtr->uFocus          = -1;
-  infoPtr->hwndToolTip     = 0;
-  infoPtr->DoRedraw        = TRUE;
-  infoPtr->needsScrolling  = FALSE;
-  infoPtr->hwndUpDown      = 0;
-  infoPtr->leftmostVisible = 0;
-  infoPtr->fSizeSet	   = FALSE;
-
-  /* The tab control always has the WS_CLIPSIBLINGS style. Even
-     if you don't specify in CreateWindow. This is necesary in
-     order for paint to work correctly. This follows windows behaviour. */
-  dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  SetWindowLongA(hwnd, GWL_STYLE, dwStyle|WS_CLIPSIBLINGS);
-
-
-  /* Create tooltip control */
-  if (dwStyle & TCS_TOOLTIPS)
-    infoPtr->hwndToolTip = createToolTip(hwnd,0,FALSE);
-
-  /*
-   * We need to get text information so we need a DC and we need to select
-   * a font.
-   */
-  hdc = GetDC(hwnd);
-  hOldFont = SelectObject (hdc, GetStockObject (SYSTEM_FONT));
-
-  /*
-   * Use the system font to determine the initial height of a tab.
-   */
-  GetTextMetricsA(hdc, &fontMetrics);
-
-  /*
-   * Make sure there is enough space for the letters + growing the
-   * selected item + extra space for the selected item.
-   */
-  infoPtr->tabHeight = fontMetrics.tmHeight + 2*VERTICAL_ITEM_PADDING +
-                       SELECTED_TAB_OFFSET;
-
-  /*
-   * Initialize the width of a tab.
-   */
-  infoPtr->tabWidth = DEFAULT_TAB_WIDTH;
-
-  SelectObject (hdc, hOldFont);
-  ReleaseDC(hwnd, hdc);
-
-  return 0;
-}
-
-static LRESULT
-TAB_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-  TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd);
-  INT iItem;
-
-  if (infoPtr->items) {
-    for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) {
-      if (infoPtr->items[iItem].pszText)
-        COMCTL32_Free (infoPtr->items[iItem].pszText);
-    }
-    COMCTL32_Free (infoPtr->items);
-  }
-
-  if (infoPtr->iHotTracked >= 0)
-    KillTimer(hwnd, TAB_HOTTRACK_TIMER);
-
-  doneControl(hwnd);
-
-  return 0;
-}
-
-static LRESULT TAB_StyleChanged(HWND hwnd,WPARAM wParam,LPARAM lParam)
-{
-  TAB_SetItemBounds (hwnd);
-  InvalidateRect(hwnd, NULL, TRUE);
-
-  return 0;
-}
-
-static LRESULT WINAPI
-TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-  switch (uMsg)
-  {
-    case TCM_GETIMAGELIST:
-      return TAB_GetImageList (hwnd, wParam, lParam);
-
-    case TCM_SETIMAGELIST:
-      return TAB_SetImageList (hwnd, wParam, lParam);
-
-    case TCM_GETITEMCOUNT:
-      return TAB_GetItemCount (hwnd, wParam, lParam);
-
-    case TCM_GETITEMA:
-      return TAB_GetItemA (hwnd, wParam, lParam);
-
-    case TCM_GETITEMW:
-      return TAB_GetItemW(hwnd,wParam,lParam);
-
-    case TCM_SETITEMA:
-      return TAB_SetItemA (hwnd, wParam, lParam);
-
-    case TCM_SETITEMW:
-      return TAB_SetItemW(hwnd,wParam,lParam);
-
-    case TCM_DELETEITEM:
-      return TAB_DeleteItem (hwnd, wParam, lParam);
-
-    case TCM_DELETEALLITEMS:
-     return TAB_DeleteAllItems (hwnd, wParam, lParam);
-
-    case TCM_GETITEMRECT:
-     return TAB_GetItemRect (hwnd, wParam, lParam);
-
-    case TCM_GETCURSEL:
-      return TAB_GetCurSel (hwnd);
-
-    case TCM_HITTEST:
-      return TAB_HitTest (hwnd, wParam, lParam);
-
-    case TCM_SETCURSEL:
-      return TAB_SetCurSel (hwnd, wParam);
-
-    case TCM_INSERTITEMA:
-      return TAB_InsertItemA(hwnd,wParam,lParam);
-
-    case TCM_INSERTITEMW:
-      return TAB_InsertItemW(hwnd,wParam,lParam);
-
-    case TCM_SETITEMEXTRA:
-//      FIXME (tab, "Unimplemented msg TCM_SETITEMEXTRA\n");
-      return 0;
-
-    case TCM_ADJUSTRECT:
-      return TAB_AdjustRect (hwnd, (BOOL)wParam, (LPRECT)lParam);
-
-    case TCM_SETITEMSIZE:
-      return TAB_SetItemSize (hwnd, wParam, lParam);
-
-    case TCM_REMOVEIMAGE:
-//      FIXME (tab, "Unimplemented msg TCM_REMOVEIMAGE\n");
-      return 0;
-
-    case TCM_SETPADDING:
-//      FIXME (tab, "Unimplemented msg TCM_SETPADDING\n");
-      return 0;
-
-    case TCM_GETROWCOUNT:
-//      FIXME (tab, "Unimplemented msg TCM_GETROWCOUNT\n");
-      return 0;
-
-    case TCM_HIGHLIGHTITEM:
-//      FIXME (tab, "Unimplemented msg TCM_HIGHLIGHTITEM\n");
-      return 0;
-
-    case TCM_GETTOOLTIPS:
-      return TAB_GetToolTips (hwnd, wParam, lParam);
-
-    case TCM_SETTOOLTIPS:
-      return TAB_SetToolTips (hwnd, wParam, lParam);
-
-    case TCM_GETCURFOCUS:
-      return TAB_GetCurFocus (hwnd);
-
-    case TCM_SETCURFOCUS:
-      return TAB_SetCurFocus (hwnd, wParam);
-
-    case TCM_SETMINTTABWIDTH:
-//      FIXME (tab, "Unimplemented msg TCM_SETMINTTABWIDTH\n");
-      return 0;
-
-    case TCM_DESELECTALL:
-//      FIXME (tab, "Unimplemented msg TCM_DESELECTALL\n");
-      return 0;
-
-    case TCM_GETEXTENDEDSTYLE:
-//      FIXME (tab, "Unimplemented msg TCM_GETEXTENDEDSTYLE\n");
-      return 0;
-
-    case TCM_SETEXTENDEDSTYLE:
-//      FIXME (tab, "Unimplemented msg TCM_SETEXTENDEDSTYLE\n");
-      return 0;
-
-    case WM_GETFONT:
-      return TAB_GetFont (hwnd, wParam, lParam);
-
-    case WM_SETFONT:
-      return TAB_SetFont (hwnd, wParam, lParam);
-
-    case WM_CREATE:
-      return TAB_Create (hwnd, wParam, lParam);
-
-    case WM_NCDESTROY:
-      return TAB_Destroy (hwnd, wParam, lParam);
-
-    case WM_GETDLGCODE:
-      return DLGC_WANTARROWS | DLGC_WANTCHARS;
-
-    case WM_LBUTTONDOWN:
-      return TAB_LButtonDown (hwnd, wParam, lParam);
-
-    case WM_LBUTTONUP:
-      return TAB_LButtonUp (hwnd, wParam, lParam);
-
-    case WM_RBUTTONDOWN:
-      return TAB_RButtonDown (hwnd, wParam, lParam);
-
-    case WM_MOUSEMOVE:
-      return TAB_MouseMove (hwnd, wParam, lParam);
-
-    case WM_ERASEBKGND:
-      return TAB_EraseBackground (hwnd, (HDC)wParam);
-
-    case WM_PAINT:
-      return TAB_Paint (hwnd, wParam);
-
-    case WM_SIZE:
-      return TAB_Size (hwnd, wParam, lParam);
-
-    case WM_SETREDRAW:
-      return TAB_SetRedraw (hwnd, wParam);
-
-    case WM_HSCROLL:
-      return TAB_OnHScroll(hwnd, (int)LOWORD(wParam), (int)HIWORD(wParam), (HWND)lParam);
-
-    case WM_STYLECHANGED:
-      return TAB_StyleChanged(hwnd,wParam,lParam);
-
-    case WM_KILLFOCUS:
-    case WM_SETFOCUS:
-      return TAB_FocusChanging(hwnd, uMsg, wParam, lParam);
-
-    case WM_KEYUP:
-      return TAB_KeyUp(hwnd, wParam);
-
-    default:
-//      if (uMsg >= WM_USER)
-//      ERR (tab, "unknown msg %04x wp=%08x lp=%08lx\n",
-//           uMsg, wParam, lParam);
-      return defComCtl32ProcA (hwnd, uMsg, wParam, lParam);
-  }
-
-  return 0;
-}
-
-
-VOID TAB_Register(VOID)
-{
-  WNDCLASSA wndClass;
-
-  ZeroMemory (&wndClass, sizeof(WNDCLASSA));
-  wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
-  wndClass.lpfnWndProc   = (WNDPROC)TAB_WindowProc;
-  wndClass.cbClsExtra    = 0;
-  wndClass.cbWndExtra    = sizeof(TAB_INFO *);
-  wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
-  wndClass.hbrBackground = (HBRUSH)NULL;
-  wndClass.lpszClassName = WC_TABCONTROLA;
-
-  RegisterClassA (&wndClass);
-}
-
-
-VOID TAB_Unregister(VOID)
-{
-  UnregisterClassA (WC_TABCONTROLA, (HINSTANCE)NULL);
-}
-
