Index: trunk/src/comctl32/comctl32undoc.c
===================================================================
--- trunk/src/comctl32/comctl32undoc.c	(revision 44)
+++ trunk/src/comctl32/comctl32undoc.c	(revision 45)
@@ -1241,2 +1241,3 @@
     return hdpa;
 }
+
Index: trunk/src/comctl32/rebar.c
===================================================================
--- trunk/src/comctl32/rebar.c	(revision 45)
+++ trunk/src/comctl32/rebar.c	(revision 45)
@@ -0,0 +1,2037 @@
+/*
+ * Rebar control
+ *
+ * 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.
+ */
+
+#include <string.h>
+
+#include "winbase.h"
+#include "wingdi.h"
+#include "commctrl.h"
+#include "rebar.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(wndPtr) ((REBAR_INFO *)GetWindowLongA (hwnd, 0))
+
+
+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 */
+
+	    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)) {
+		/* special placement code for extended combo box */
+
+
+	    }
+#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 = 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);
+	    strncpy(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_GetUnicodeFormat (HWND hwnd)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    return infoPtr->bUnicode;
+}
+
+
+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);
+	    strcpy(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);
+	    strcpy(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->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 (rebar, "text color 0x%06lx!\n", infoPtr->clrText);
+
+    return clrTemp;
+}
+
+
+/* << REBAR_SetTooltips >> */
+
+
+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_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 *)COMCTL32_Alloc (sizeof(REBAR_INFO));
+    SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
+
+    /* 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);
+
+    infoPtr->bUnicode = IsWindowUnicode (hwnd);
+
+//    if (GetWindowLongA (hwnd, GWL_STYLE) & RBS_AUTOSIZE)
+//	FIXME (rebar, "style RBS_AUTOSIZE set!\n");
+
+#if 0
+    SendMessageA (hwnd, WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY);
+#endif
+
+//    TRACE (rebar, "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);
+
+//    TRACE (rebar, "destroyed!\n");
+    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);
+
+    return 0;
+}
+
+
+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;
+}
+
+
+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_GETUNICODEFORMAT:
+	    return REBAR_GetUnicodeFormat (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 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 DefWindowProcA (hwnd, uMsg, wParam, lParam);
+    }
+    return 0;
+}
+
+
+VOID
+REBAR_Register (VOID)
+{
+    WNDCLASSA wndClass;
+
+    if (GlobalFindAtomA (REBARCLASSNAMEA)) return;
+
+    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)
+{
+    if (GlobalFindAtomA (REBARCLASSNAMEA))
+	UnregisterClassA (REBARCLASSNAMEA, (HINSTANCE)NULL);
+}
+
Index: trunk/src/comctl32/tooltips.c
===================================================================
--- trunk/src/comctl32/tooltips.c	(revision 45)
+++ trunk/src/comctl32/tooltips.c	(revision 45)
@@ -0,0 +1,2384 @@
+/*
+ * Tool tip control
+ *
+ * Copyright 1998 Eric Kohl
+ *
+ * TODO:
+ *   - Unicode support.
+ *   - Custom draw support.
+ *
+ * Testing:
+ *   - Run tests using Waite Group Windows95 API Bible Volume 2.
+ *     The second cdrom (chapter 3) contains executables activate.exe,
+ *     curtool.exe, deltool.exe, enumtools.exe, getinfo.exe, getiptxt.exe,
+ *     hittest.exe, needtext.exe, newrect.exe, updtext.exe and winfrpt.exe.
+ */
+
+#include <string.h>
+
+#include "winbase.h"
+#include "commctrl.h"
+#include "tooltips.h"
+
+
+#define ID_TIMERSHOW   1    /* show delay timer */
+#define ID_TIMERPOP    2    /* auto pop timer */
+#define ID_TIMERLEAVE  3    /* tool leave timer */
+
+
+extern LPSTR COMCTL32_aSubclass; /* global subclassing atom */
+
+/* property name of tooltip window handle */
+/*#define TT_SUBCLASS_PROP "CC32SubclassInfo" */
+
+#define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongA (hWindow, 0))
+
+
+LRESULT CALLBACK
+TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+
+static VOID
+TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(hwnd);
+    RECT rc;
+    INT oldBkMode;
+    HFONT hOldFont;
+    HBRUSH hBrush;
+    UINT uFlags = DT_EXTERNALLEADING;
+
+    if (infoPtr->nMaxTipWidth > -1)
+	uFlags |= DT_WORDBREAK;
+    if (GetWindowLongA (hwnd, GWL_STYLE) & TTS_NOPREFIX)
+	uFlags |= DT_NOPREFIX;
+    GetClientRect (hwnd, &rc);
+
+    /* fill the background */
+    hBrush = CreateSolidBrush (infoPtr->clrBk);
+    FillRect (hdc, &rc, hBrush);
+    DeleteObject (hBrush);
+
+    /* calculate text rectangle */
+    rc.left   += (2 + infoPtr->rcMargin.left);
+    rc.top    += (2 + infoPtr->rcMargin.top);
+    rc.right  -= (2 + infoPtr->rcMargin.right);
+    rc.bottom -= (2 + infoPtr->rcMargin.bottom);
+
+    /* draw text */
+    oldBkMode = SetBkMode (hdc, TRANSPARENT);
+    SetTextColor (hdc, infoPtr->clrText);
+    hOldFont = SelectObject (hdc, infoPtr->hFont);
+    DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
+    SelectObject (hdc, hOldFont);
+    if (oldBkMode != TRANSPARENT)
+	SetBkMode (hdc, oldBkMode);
+}
+
+
+static VOID
+TOOLTIPS_GetTipText (HWND hwnd, TOOLTIPS_INFO *infoPtr, INT nTool)
+{
+    TTTOOL_INFO *toolPtr = &infoPtr->tools[nTool];
+
+    if ((toolPtr->hinst) && (HIWORD((UINT)toolPtr->lpszText) == 0)) {
+	/* load a resource */
+//	TRACE (tooltips, "load res string %x %x\n",
+//	       toolPtr->hinst, (int)toolPtr->lpszText);
+	LoadStringW (toolPtr->hinst, (UINT)toolPtr->lpszText,
+		       infoPtr->szTipText, INFOTIPSIZE);
+    }
+    else if (toolPtr->lpszText) {
+	if (toolPtr->lpszText == LPSTR_TEXTCALLBACKW) {
+	    NMTTDISPINFOA ttnmdi;
+
+	    /* fill NMHDR struct */
+	    ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFOA));
+	    ttnmdi.hdr.hwndFrom = hwnd;
+	    ttnmdi.hdr.idFrom = toolPtr->uId;
+	    ttnmdi.hdr.code = TTN_GETDISPINFOA;
+	    ttnmdi.lpszText = (LPSTR)&ttnmdi.szText;
+	    ttnmdi.uFlags = toolPtr->uFlags;
+	    ttnmdi.lParam = toolPtr->lParam;
+
+//	    TRACE (tooltips, "hdr.idFrom = %x\n", ttnmdi.hdr.idFrom);
+	    SendMessageA (toolPtr->hwnd, WM_NOTIFY,
+			    (WPARAM)toolPtr->uId, (LPARAM)&ttnmdi);
+
+	    if ((ttnmdi.hinst) && (HIWORD((UINT)ttnmdi.szText) == 0)) {
+		LoadStringW (ttnmdi.hinst, (UINT)ttnmdi.szText,
+			       infoPtr->szTipText, INFOTIPSIZE);
+		if (ttnmdi.uFlags & TTF_DI_SETITEM) {
+		    toolPtr->hinst = ttnmdi.hinst;
+		    toolPtr->lpszText = (LPWSTR)ttnmdi.szText;
+		}
+	    }
+	    else if (ttnmdi.szText[0]) {
+//		lstrcpynAtoW (infoPtr->szTipText, ttnmdi.szText, 80);
+		strncpy(infoPtr->szTipText, ttnmdi.szText, 80);
+		if (ttnmdi.uFlags & TTF_DI_SETITEM) {
+		    INT len = lstrlenA (ttnmdi.szText);
+		    toolPtr->hinst = 0;
+		    toolPtr->lpszText =	COMCTL32_Alloc ((len+1)* sizeof(WCHAR));
+//		    lstrcpyAtoW (toolPtr->lpszText, ttnmdi.szText);
+		    strcpy(toolPtr->lpszText, ttnmdi.szText);
+		}
+	    }
+	    else if (ttnmdi.lpszText == 0) {
+		/* no text available */
+		infoPtr->szTipText[0] = L'\0';
+	    }
+	    else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKA) {
+//		lstrcpynAtoW (infoPtr->szTipText, ttnmdi.lpszText, INFOTIPSIZE);
+		strncpy(infoPtr->szTipText, ttnmdi.lpszText, INFOTIPSIZE);
+		if (ttnmdi.uFlags & TTF_DI_SETITEM) {
+		    INT len = lstrlenA (ttnmdi.lpszText);
+		    toolPtr->hinst = 0;
+		    toolPtr->lpszText =	COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
+//		    lstrcpyAtoW (toolPtr->lpszText, ttnmdi.lpszText);
+		    strcpy(toolPtr->lpszText, ttnmdi.lpszText);
+		}
+	    }
+	    else {
+//		ERR (tooltips, "recursive text callback!\n");
+		infoPtr->szTipText[0] = '\0';
+	    }
+	}
+	else {
+	    /* the item is a usual (unicode) text */
+//	    lstrcpynW (infoPtr->szTipText, toolPtr->lpszText, INFOTIPSIZE);
+	    strncpy(infoPtr->szTipText, toolPtr->lpszText, INFOTIPSIZE);
+	}
+    }
+    else {
+	/* no text available */
+	infoPtr->szTipText[0] = L'\0';
+    }
+
+//    TRACE (tooltips, "\"%s\"\n", debugstr_w(infoPtr->szTipText));
+}
+
+
+static VOID
+TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIPS_INFO *infoPtr, LPSIZE lpSize)
+{
+    HDC hdc;
+    HFONT hOldFont;
+    UINT uFlags = DT_EXTERNALLEADING | DT_CALCRECT;
+    RECT rc = {0, 0, 0, 0};
+
+    if (infoPtr->nMaxTipWidth > -1) {
+	rc.right = infoPtr->nMaxTipWidth;
+	uFlags |= DT_WORDBREAK;
+    }
+    if (GetWindowLongA (hwnd, GWL_STYLE) & TTS_NOPREFIX)
+	uFlags |= DT_NOPREFIX;
+//    TRACE (tooltips, "\"%s\"\n", debugstr_w(infoPtr->szTipText));
+
+    hdc = GetDC (hwnd);
+    hOldFont = SelectObject (hdc, infoPtr->hFont);
+    DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
+    SelectObject (hdc, hOldFont);
+    ReleaseDC (hwnd, hdc);
+
+    lpSize->cx = rc.right - rc.left + 4 + 
+		 infoPtr->rcMargin.left + infoPtr->rcMargin.right;
+    lpSize->cy = rc.bottom - rc.top + 4 +
+		 infoPtr->rcMargin.bottom + infoPtr->rcMargin.top;
+}
+
+
+static VOID
+TOOLTIPS_Show (HWND hwnd, TOOLTIPS_INFO *infoPtr)
+{
+    TTTOOL_INFO *toolPtr;
+    RECT rect;
+    SIZE size;
+    HDC  hdc;
+    NMHDR  hdr;
+
+    if (infoPtr->nTool == -1) {
+//	TRACE (tooltips, "invalid tool (-1)!\n");
+	return;
+    }
+
+    infoPtr->nCurrentTool = infoPtr->nTool;
+
+//    TRACE (tooltips, "Show tooltip pre %d!\n", infoPtr->nTool);
+
+    TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nCurrentTool);
+
+    if (infoPtr->szTipText[0] == L'\0') {
+	infoPtr->nCurrentTool = -1;
+	return;
+    }
+
+//    TRACE (tooltips, "Show tooltip %d!\n", infoPtr->nCurrentTool);
+    toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
+
+    hdr.hwndFrom = hwnd;
+    hdr.idFrom = toolPtr->uId;
+    hdr.code = TTN_SHOW;
+    SendMessageA (toolPtr->hwnd, WM_NOTIFY,
+		    (WPARAM)toolPtr->uId, (LPARAM)&hdr);
+
+//    TRACE (tooltips, "\"%s\"\n", debugstr_w(infoPtr->szTipText));
+
+    TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
+//    TRACE (tooltips, "size %d - %d\n", size.cx, size.cy);
+
+    if (toolPtr->uFlags & TTF_CENTERTIP) {
+	RECT rc;
+
+	if (toolPtr->uFlags & TTF_IDISHWND)
+	    GetWindowRect ((HWND)toolPtr->uId, &rc);
+	else {
+	    rc = toolPtr->rect;
+	    MapWindowPoints (toolPtr->hwnd, (HWND)0, (LPPOINT)&rc, 2);
+	}
+	rect.left = (rc.left + rc.right - size.cx) / 2;
+	rect.top  = rc.bottom + 2;
+    }
+    else {
+	GetCursorPos ((LPPOINT)&rect);
+	rect.top += 20;
+    }
+
+    /* FIXME: check position */
+
+//    TRACE (tooltips, "pos %d - %d\n", rect.left, rect.top);
+
+    rect.right = rect.left + size.cx;
+    rect.bottom = rect.top + size.cy;
+
+    AdjustWindowRectEx (&rect, GetWindowLongA (hwnd, GWL_STYLE),
+			FALSE, GetWindowLongA (hwnd, GWL_EXSTYLE));
+
+    SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
+		    rect.right - rect.left, rect.bottom - rect.top,
+		    SWP_SHOWWINDOW | SWP_NOACTIVATE);
+
+    /* repaint the tooltip */
+    hdc = GetDC (hwnd);
+    TOOLTIPS_Refresh (hwnd, hdc);
+    ReleaseDC (hwnd, hdc);
+
+    SetTimer (hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0);
+}
+
+
+static VOID
+TOOLTIPS_Hide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
+{
+    TTTOOL_INFO *toolPtr;
+    NMHDR hdr;
+
+    if (infoPtr->nCurrentTool == -1)
+	return;
+
+    toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
+//    TRACE (tooltips, "Hide tooltip %d!\n", infoPtr->nCurrentTool);
+    KillTimer (hwnd, ID_TIMERPOP);
+
+    hdr.hwndFrom = hwnd;
+    hdr.idFrom = toolPtr->uId;
+    hdr.code = TTN_POP;
+    SendMessageA (toolPtr->hwnd, WM_NOTIFY,
+		    (WPARAM)toolPtr->uId, (LPARAM)&hdr);
+
+    infoPtr->nCurrentTool = -1;
+
+    SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
+		    SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
+}
+
+
+static VOID
+TOOLTIPS_TrackShow (HWND hwnd, TOOLTIPS_INFO *infoPtr)
+{
+    TTTOOL_INFO *toolPtr;
+    RECT rect;
+    SIZE size;
+    HDC  hdc;
+    NMHDR hdr;
+
+    if (infoPtr->nTrackTool == -1) {
+//	TRACE (tooltips, "invalid tracking tool (-1)!\n");
+	return;
+    }
+
+//    TRACE (tooltips, "show tracking tooltip pre %d!\n", infoPtr->nTrackTool);
+
+    TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nTrackTool);
+
+    if (infoPtr->szTipText[0] == L'\0') {
+	infoPtr->nTrackTool = -1;
+	return;
+    }
+
+//    TRACE (tooltips, "show tracking tooltip %d!\n", infoPtr->nTrackTool);
+    toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
+
+    hdr.hwndFrom = hwnd;
+    hdr.idFrom = toolPtr->uId;
+    hdr.code = TTN_SHOW;
+    SendMessageA (toolPtr->hwnd, WM_NOTIFY,
+		    (WPARAM)toolPtr->uId, (LPARAM)&hdr);
+
+//    TRACE (tooltips, "\"%s\"\n", debugstr_w(infoPtr->szTipText));
+
+    TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
+//    TRACE (tooltips, "size %d - %d\n", size.cx, size.cy);
+
+    if (toolPtr->uFlags & TTF_ABSOLUTE) {
+	rect.left = infoPtr->xTrackPos;
+	rect.top  = infoPtr->yTrackPos;
+
+	if (toolPtr->uFlags & TTF_CENTERTIP) {
+	    rect.left -= (size.cx / 2);
+	    rect.top  -= (size.cy / 2);
+	}
+    }
+    else {
+	RECT rcTool;
+
+	if (toolPtr->uFlags & TTF_IDISHWND)
+	    GetWindowRect ((HWND)toolPtr->uId, &rcTool);
+	else {
+	    rcTool = toolPtr->rect;
+	    MapWindowPoints (toolPtr->hwnd, (HWND)0, (LPPOINT)&rcTool, 2);
+	}
+
+	GetCursorPos ((LPPOINT)&rect);
+	rect.top += 20;
+
+	if (toolPtr->uFlags & TTF_CENTERTIP) {
+	    rect.left -= (size.cx / 2);
+	    rect.top  -= (size.cy / 2);
+	}
+
+	/* smart placement */
+	if ((rect.left + size.cx > rcTool.left) && (rect.left < rcTool.right) &&
+	    (rect.top + size.cy > rcTool.top) && (rect.top < rcTool.bottom))
+	    rect.left = rcTool.right;
+    }
+
+//    TRACE (tooltips, "pos %d - %d\n", rect.left, rect.top);
+
+    rect.right = rect.left + size.cx;
+    rect.bottom = rect.top + size.cy;
+
+    AdjustWindowRectEx (&rect, GetWindowLongA (hwnd, GWL_STYLE),
+			FALSE, GetWindowLongA (hwnd, GWL_EXSTYLE));
+
+    SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
+		    rect.right - rect.left, rect.bottom - rect.top,
+		    SWP_SHOWWINDOW | SWP_NOACTIVATE );
+
+    hdc = GetDC (hwnd);
+    TOOLTIPS_Refresh (hwnd, hdc);
+    ReleaseDC (hwnd, hdc);
+}
+
+
+static VOID
+TOOLTIPS_TrackHide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
+{
+    TTTOOL_INFO *toolPtr;
+    NMHDR hdr;
+
+    if (infoPtr->nTrackTool == -1)
+	return;
+
+    toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
+//    TRACE (tooltips, "hide tracking tooltip %d!\n", infoPtr->nTrackTool);
+
+    hdr.hwndFrom = hwnd;
+    hdr.idFrom = toolPtr->uId;
+    hdr.code = TTN_POP;
+    SendMessageA (toolPtr->hwnd, WM_NOTIFY,
+		    (WPARAM)toolPtr->uId, (LPARAM)&hdr);
+
+    SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
+		    SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
+}
+
+
+static INT
+TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOA lpToolInfo)
+{
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
+	toolPtr = &infoPtr->tools[nTool];
+
+	if (!(toolPtr->uFlags & TTF_IDISHWND) && 
+	    (lpToolInfo->hwnd == toolPtr->hwnd) &&
+	    (lpToolInfo->uId == toolPtr->uId))
+	    return nTool;
+    }
+
+    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
+	toolPtr = &infoPtr->tools[nTool];
+
+	if ((toolPtr->uFlags & TTF_IDISHWND) &&
+	    (lpToolInfo->uId == toolPtr->uId))
+	    return nTool;
+    }
+
+    return -1;
+}
+
+
+static INT
+TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOW lpToolInfo)
+{
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
+	toolPtr = &infoPtr->tools[nTool];
+
+	if (!(toolPtr->uFlags & TTF_IDISHWND) && 
+	    (lpToolInfo->hwnd == toolPtr->hwnd) &&
+	    (lpToolInfo->uId == toolPtr->uId))
+	    return nTool;
+    }
+
+    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
+	toolPtr = &infoPtr->tools[nTool];
+
+	if ((toolPtr->uFlags & TTF_IDISHWND) &&
+	    (lpToolInfo->uId == toolPtr->uId))
+	    return nTool;
+    }
+
+    return -1;
+}
+
+
+static INT
+TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO *infoPtr, HWND hwnd, LPPOINT lpPt)
+{
+    TTTOOL_INFO *toolPtr;
+    INT  nTool;
+
+    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
+	toolPtr = &infoPtr->tools[nTool];
+
+	if (!(toolPtr->uFlags & TTF_IDISHWND)) {
+	    if (hwnd != toolPtr->hwnd)
+		continue;
+	    if (!PtInRect (&toolPtr->rect, *lpPt))
+		continue;
+	    return nTool;
+	}
+    }
+
+    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
+	toolPtr = &infoPtr->tools[nTool];
+
+	if (toolPtr->uFlags & TTF_IDISHWND) {
+	    if ((HWND)toolPtr->uId == hwnd)
+		return nTool;
+	}
+    }
+
+    return -1;
+}
+
+
+static INT
+TOOLTIPS_GetToolFromMessage (TOOLTIPS_INFO *infoPtr, HWND hwndTool)
+{
+    DWORD   dwPos;
+    POINT pt;
+
+    dwPos = GetMessagePos ();
+    pt.x = (INT)LOWORD(dwPos);
+    pt.y = (INT)HIWORD(dwPos);
+    ScreenToClient (hwndTool, &pt);
+
+    return TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
+}
+
+
+static BOOL
+TOOLTIPS_IsWindowActive (HWND hwnd)
+{
+    HWND hwndActive = GetActiveWindow ();
+    if (!hwndActive)
+	return FALSE;
+    if (hwndActive == hwnd)
+	return TRUE;
+    return IsChild (hwndActive, hwnd);
+}
+
+
+static INT
+TOOLTIPS_CheckTool (HWND hwnd, BOOL bShowTest)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    POINT pt;
+    HWND hwndTool;
+    INT nTool;
+
+    GetCursorPos (&pt);
+    hwndTool = SendMessageA (hwnd, TTM_WINDOWFROMPOINT, 0, (LPARAM)&pt);
+    if (hwndTool == 0)
+	return -1;
+
+    ScreenToClient (hwndTool, &pt);
+    nTool = TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
+    if (nTool == -1)
+	return -1;
+
+    if (!(GetWindowLongA (hwnd, GWL_STYLE) & TTS_ALWAYSTIP) && bShowTest) {
+	if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd, GW_OWNER)))
+	    return -1;
+    }
+
+//    TRACE (tooltips, "tool %d\n", nTool);
+
+    return nTool;
+}
+
+
+static LRESULT
+TOOLTIPS_Activate (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    infoPtr->bActive = (BOOL)wParam;
+
+//    if (infoPtr->bActive)
+//	TRACE (tooltips, "activate!\n");
+
+    if (!(infoPtr->bActive) && (infoPtr->nCurrentTool != -1)) 
+	TOOLTIPS_Hide (hwnd, infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_AddToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
+    TTTOOL_INFO *toolPtr;
+
+    if (lpToolInfo == NULL)
+	return FALSE;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
+	return FALSE;
+
+//    TRACE (tooltips, "add tool (%x) %x %d%s!\n",
+//	   hwnd, lpToolInfo->hwnd, lpToolInfo->uId,
+//	   (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
+
+    if (infoPtr->uNumTools == 0) {
+	infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
+	toolPtr = infoPtr->tools;
+    }
+    else {
+	TTTOOL_INFO *oldTools = infoPtr->tools;
+	infoPtr->tools =
+	    COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
+	memcpy (infoPtr->tools, oldTools,
+		infoPtr->uNumTools * sizeof(TTTOOL_INFO));
+	COMCTL32_Free (oldTools);
+	toolPtr = &infoPtr->tools[infoPtr->uNumTools];
+    }
+
+    infoPtr->uNumTools++;
+
+    /* copy tool data */
+    toolPtr->uFlags = lpToolInfo->uFlags;
+    toolPtr->hwnd   = lpToolInfo->hwnd;
+    toolPtr->uId    = lpToolInfo->uId;
+    toolPtr->rect   = lpToolInfo->rect;
+    toolPtr->hinst  = lpToolInfo->hinst;
+
+    if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
+//	TRACE (tooltips, "add string id %x!\n", (int)lpToolInfo->lpszText);
+	toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
+    }
+    else if (lpToolInfo->lpszText) {
+	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA) {
+//	    TRACE (tooltips, "add CALLBACK!\n");
+	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
+	}
+	else {
+	    INT len = lstrlenA (lpToolInfo->lpszText);
+//	    TRACE (tooltips, "add text \"%s\"!\n", lpToolInfo->lpszText);
+	    toolPtr->lpszText =	COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
+//	    lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
+	    strcpy(toolPtr->lpszText, lpToolInfo->lpszText);
+	}
+    }
+
+    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
+	toolPtr->lParam = lpToolInfo->lParam;
+
+    /* install subclassing hook */
+    if (toolPtr->uFlags & TTF_SUBCLASS) {
+	if (toolPtr->uFlags & TTF_IDISHWND) {
+	    LPTT_SUBCLASS_INFO lpttsi =
+		(LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
+	    if (lpttsi == NULL) {
+		lpttsi =
+		    (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
+		lpttsi->wpOrigProc = 
+		    (WNDPROC)SetWindowLongA ((HWND)toolPtr->uId,
+		    GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
+		lpttsi->hwndToolTip = hwnd;
+		lpttsi->uRefCount++;
+		SetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass,
+			    (HANDLE)lpttsi);
+	    }
+//	    else
+//		WARN (tooltips, "A window tool must only be listed once!\n");
+	}
+	else {
+	    LPTT_SUBCLASS_INFO lpttsi =
+		(LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
+	    if (lpttsi == NULL) {
+		lpttsi =
+		    (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
+		lpttsi->wpOrigProc = 
+		    (WNDPROC)SetWindowLongA (toolPtr->hwnd,
+		    GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
+		lpttsi->hwndToolTip = hwnd;
+		lpttsi->uRefCount++;
+		SetPropA (toolPtr->hwnd, COMCTL32_aSubclass, (HANDLE)lpttsi);
+	    }
+	    else
+		lpttsi->uRefCount++;
+	}
+//	TRACE (tooltips, "subclassing installed!\n");
+    }
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLTIPS_AddToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
+    TTTOOL_INFO *toolPtr;
+
+    if (lpToolInfo == NULL)
+	return FALSE;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
+	return FALSE;
+
+//    TRACE (tooltips, "add tool (%x) %x %d%s!\n",
+//	   hwnd, lpToolInfo->hwnd, lpToolInfo->uId,
+//	   (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
+
+    if (infoPtr->uNumTools == 0) {
+	infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
+	toolPtr = infoPtr->tools;
+    }
+    else {
+	TTTOOL_INFO *oldTools = infoPtr->tools;
+	infoPtr->tools =
+	    COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
+	memcpy (infoPtr->tools, oldTools,
+		infoPtr->uNumTools * sizeof(TTTOOL_INFO));
+	COMCTL32_Free (oldTools);
+	toolPtr = &infoPtr->tools[infoPtr->uNumTools];
+    }
+
+    infoPtr->uNumTools++;
+
+    /* copy tool data */
+    toolPtr->uFlags = lpToolInfo->uFlags;
+    toolPtr->hwnd   = lpToolInfo->hwnd;
+    toolPtr->uId    = lpToolInfo->uId;
+    toolPtr->rect   = lpToolInfo->rect;
+    toolPtr->hinst  = lpToolInfo->hinst;
+
+    if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
+//	TRACE (tooltips, "add string id %x!\n", (int)lpToolInfo->lpszText);
+	toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
+    }
+    else if (lpToolInfo->lpszText) {
+	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW) {
+//	    TRACE (tooltips, "add CALLBACK!\n");
+	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
+	}
+	else {
+	    INT len = lstrlenW (lpToolInfo->lpszText);
+//	    TRACE (tooltips, "add text \"%s\"!\n",
+//		   debugstr_w(lpToolInfo->lpszText));
+	    toolPtr->lpszText =	COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
+	    lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
+	}
+    }
+
+    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
+	toolPtr->lParam = lpToolInfo->lParam;
+
+    /* install subclassing hook */
+    if (toolPtr->uFlags & TTF_SUBCLASS) {
+	if (toolPtr->uFlags & TTF_IDISHWND) {
+	    LPTT_SUBCLASS_INFO lpttsi =
+		(LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
+	    if (lpttsi == NULL) {
+		lpttsi =
+		    (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
+		lpttsi->wpOrigProc = 
+		    (WNDPROC)SetWindowLongA ((HWND)toolPtr->uId,
+		    GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
+		lpttsi->hwndToolTip = hwnd;
+		lpttsi->uRefCount++;
+		SetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass,
+			    (HANDLE)lpttsi);
+	    }
+//	    else
+//		WARN (tooltips, "A window tool must only be listed once!\n");
+	}
+	else {
+	    LPTT_SUBCLASS_INFO lpttsi =
+		(LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
+	    if (lpttsi == NULL) {
+		lpttsi =
+		    (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
+		lpttsi->wpOrigProc = 
+		    (WNDPROC)SetWindowLongA (toolPtr->hwnd,
+		    GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
+		lpttsi->hwndToolTip = hwnd;
+		lpttsi->uRefCount++;
+		SetPropA (toolPtr->hwnd, COMCTL32_aSubclass, (HANDLE)lpttsi);
+	    }
+	    else
+		lpttsi->uRefCount++;
+	}
+//	TRACE (tooltips, "subclassing installed!\n");
+    }
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLTIPS_DelToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    if (lpToolInfo == NULL)
+	return 0;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
+	return 0;
+    if (infoPtr->uNumTools == 0)
+	return 0;
+
+    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
+    if (nTool == -1) return 0;
+
+//    TRACE (tooltips, "tool %d\n", nTool);
+
+    /* delete text string */
+    toolPtr = &infoPtr->tools[nTool]; 
+    if ((toolPtr->hinst) && (toolPtr->lpszText)) {
+	if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
+	    COMCTL32_Free (toolPtr->lpszText);
+    }
+
+    /* remove subclassing */
+    if (toolPtr->uFlags & TTF_SUBCLASS) {
+	if (toolPtr->uFlags & TTF_IDISHWND) {
+	    LPTT_SUBCLASS_INFO lpttsi =
+		(LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
+	    if (lpttsi) {
+		SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
+				  (LONG)lpttsi->wpOrigProc);
+		RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
+		COMCTL32_Free (&lpttsi);
+	    }
+//	    else
+//		ERR (tooltips, "Invalid data handle!\n");
+	}
+	else {
+	    LPTT_SUBCLASS_INFO lpttsi =
+		(LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
+	    if (lpttsi) {
+		if (lpttsi->uRefCount == 1) {
+		    SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
+				      (LONG)lpttsi->wpOrigProc);
+		    RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
+		    COMCTL32_Free (&lpttsi);
+		}
+		else
+		    lpttsi->uRefCount--;
+	    }
+//	    else
+//		ERR (tooltips, "Invalid data handle!\n");
+	}
+    }
+
+    /* delete tool from tool list */
+    if (infoPtr->uNumTools == 1) {
+	COMCTL32_Free (infoPtr->tools);
+	infoPtr->tools = NULL;
+    }
+    else {
+	TTTOOL_INFO *oldTools = infoPtr->tools;
+	infoPtr->tools =
+	    COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
+
+	if (nTool > 0)
+	    memcpy (&infoPtr->tools[0], &oldTools[0],
+		    nTool * sizeof(TTTOOL_INFO));
+
+	if (nTool < infoPtr->uNumTools - 1)
+	    memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
+		    (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
+
+	COMCTL32_Free (oldTools);
+    }
+
+    infoPtr->uNumTools--;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_DelToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    if (lpToolInfo == NULL)
+	return 0;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
+	return 0;
+    if (infoPtr->uNumTools == 0)
+	return 0;
+
+    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
+    if (nTool == -1) return 0;
+
+//    TRACE (tooltips, "tool %d\n", nTool);
+
+    /* delete text string */
+    toolPtr = &infoPtr->tools[nTool]; 
+    if ((toolPtr->hinst) && (toolPtr->lpszText)) {
+	if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
+	    COMCTL32_Free (toolPtr->lpszText);
+    }
+
+    /* remove subclassing */
+    if (toolPtr->uFlags & TTF_SUBCLASS) {
+	if (toolPtr->uFlags & TTF_IDISHWND) {
+	    LPTT_SUBCLASS_INFO lpttsi =
+		(LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
+	    if (lpttsi) {
+		SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
+				  (LONG)lpttsi->wpOrigProc);
+		RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
+		COMCTL32_Free (&lpttsi);
+	    }
+//	    else
+//		ERR (tooltips, "Invalid data handle!\n");
+	}
+	else {
+	    LPTT_SUBCLASS_INFO lpttsi =
+		(LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
+	    if (lpttsi) {
+		if (lpttsi->uRefCount == 1) {
+		    SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
+				      (LONG)lpttsi->wpOrigProc);
+		    RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
+		    COMCTL32_Free (&lpttsi);
+		}
+		else
+		    lpttsi->uRefCount--;
+	    }
+//	    else
+//		ERR (tooltips, "Invalid data handle!\n");
+	}
+    }
+
+    /* delete tool from tool list */
+    if (infoPtr->uNumTools == 1) {
+	COMCTL32_Free (infoPtr->tools);
+	infoPtr->tools = NULL;
+    }
+    else {
+	TTTOOL_INFO *oldTools = infoPtr->tools;
+	infoPtr->tools =
+	    COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
+
+	if (nTool > 0)
+	    memcpy (&infoPtr->tools[0], &oldTools[0],
+		    nTool * sizeof(TTTOOL_INFO));
+
+	if (nTool < infoPtr->uNumTools - 1)
+	    memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
+		    (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
+
+	COMCTL32_Free (oldTools);
+    }
+
+    infoPtr->uNumTools--;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_EnumToolsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    UINT uIndex = (UINT)wParam;
+    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
+    TTTOOL_INFO *toolPtr;
+
+    if (lpToolInfo == NULL)
+	return FALSE;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
+	return FALSE;
+    if (uIndex >= infoPtr->uNumTools)
+	return FALSE;
+
+//    TRACE (tooltips, "index=%u\n", uIndex);
+
+    toolPtr = &infoPtr->tools[uIndex];
+
+    /* copy tool data */
+    lpToolInfo->uFlags   = toolPtr->uFlags;
+    lpToolInfo->hwnd     = toolPtr->hwnd;
+    lpToolInfo->uId      = toolPtr->uId;
+    lpToolInfo->rect     = toolPtr->rect;
+    lpToolInfo->hinst    = toolPtr->hinst;
+/*    lpToolInfo->lpszText = toolPtr->lpszText; */
+    lpToolInfo->lpszText = NULL;  /* FIXME */
+
+    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
+	lpToolInfo->lParam = toolPtr->lParam;
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLTIPS_EnumToolsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    UINT uIndex = (UINT)wParam;
+    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
+    TTTOOL_INFO *toolPtr;
+
+    if (lpToolInfo == NULL)
+	return FALSE;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
+	return FALSE;
+    if (uIndex >= infoPtr->uNumTools)
+	return FALSE;
+
+//    TRACE (tooltips, "index=%u\n", uIndex);
+
+    toolPtr = &infoPtr->tools[uIndex];
+
+    /* copy tool data */
+    lpToolInfo->uFlags   = toolPtr->uFlags;
+    lpToolInfo->hwnd     = toolPtr->hwnd;
+    lpToolInfo->uId      = toolPtr->uId;
+    lpToolInfo->rect     = toolPtr->rect;
+    lpToolInfo->hinst    = toolPtr->hinst;
+/*    lpToolInfo->lpszText = toolPtr->lpszText; */
+    lpToolInfo->lpszText = NULL;  /* FIXME */
+
+    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
+	lpToolInfo->lParam = toolPtr->lParam;
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLTIPS_GetCurrentToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
+    TTTOOL_INFO *toolPtr;
+
+    if (lpToolInfo == NULL)
+	return FALSE;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
+	return FALSE;
+
+    if (lpToolInfo) {
+	if (infoPtr->nCurrentTool > -1) {
+	    toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
+
+	    /* copy tool data */
+	    lpToolInfo->uFlags   = toolPtr->uFlags;
+	    lpToolInfo->rect     = toolPtr->rect;
+	    lpToolInfo->hinst    = toolPtr->hinst;
+/*	    lpToolInfo->lpszText = toolPtr->lpszText; */
+	    lpToolInfo->lpszText = NULL;  /* FIXME */
+
+	    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
+		lpToolInfo->lParam = toolPtr->lParam;
+
+	    return TRUE;
+	}
+	else
+	    return FALSE;
+    }
+    else
+	return (infoPtr->nCurrentTool != -1);
+
+    return FALSE;
+}
+
+
+static LRESULT
+TOOLTIPS_GetCurrentToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
+    TTTOOL_INFO *toolPtr;
+
+    if (lpToolInfo == NULL)
+	return FALSE;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
+	return FALSE;
+
+    if (lpToolInfo) {
+	if (infoPtr->nCurrentTool > -1) {
+	    toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
+
+	    /* copy tool data */
+	    lpToolInfo->uFlags   = toolPtr->uFlags;
+	    lpToolInfo->rect     = toolPtr->rect;
+	    lpToolInfo->hinst    = toolPtr->hinst;
+/*	    lpToolInfo->lpszText = toolPtr->lpszText; */
+	    lpToolInfo->lpszText = NULL;  /* FIXME */
+
+	    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
+		lpToolInfo->lParam = toolPtr->lParam;
+
+	    return TRUE;
+	}
+	else
+	    return FALSE;
+    }
+    else
+	return (infoPtr->nCurrentTool != -1);
+
+    return FALSE;
+}
+
+
+static LRESULT
+TOOLTIPS_GetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    switch (wParam) {
+	case TTDT_AUTOMATIC:
+	    return infoPtr->nAutomaticTime;
+
+	case TTDT_RESHOW:
+	    return infoPtr->nReshowTime;
+
+	case TTDT_AUTOPOP:
+	    return infoPtr->nAutoPopTime;
+
+	case TTDT_INITIAL:
+	    return infoPtr->nInitialTime;
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_GetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPRECT lpRect = (LPRECT)lParam;
+
+    lpRect->left   = infoPtr->rcMargin.left;
+    lpRect->right  = infoPtr->rcMargin.right;
+    lpRect->bottom = infoPtr->rcMargin.bottom;
+    lpRect->top    = infoPtr->rcMargin.top;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_GetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    return infoPtr->nMaxTipWidth;
+}
+
+
+static LRESULT
+TOOLTIPS_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
+    INT nTool;
+
+    if (lpToolInfo == NULL)
+	return 0;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
+	return 0;
+
+    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
+    if (nTool == -1) return 0;
+
+//    lstrcpyWtoA (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
+    strcpy(lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
+    INT nTool;
+
+    if (lpToolInfo == NULL)
+	return 0;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
+	return 0;
+
+    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
+    if (nTool == -1) return 0;
+
+    lstrcpyW (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_GetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    return infoPtr->clrBk;
+}
+
+
+static LRESULT
+TOOLTIPS_GetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    return infoPtr->clrText;
+}
+
+
+static LRESULT
+TOOLTIPS_GetToolCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    return infoPtr->uNumTools;
+}
+
+
+static LRESULT
+TOOLTIPS_GetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    if (lpToolInfo == NULL)
+	return FALSE;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
+	return FALSE;
+    if (infoPtr->uNumTools == 0)
+	return FALSE;
+
+    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
+    if (nTool == -1)
+	return FALSE;
+
+//    TRACE (tooltips, "tool %d\n", nTool);
+
+    toolPtr = &infoPtr->tools[nTool];
+
+    /* copy tool data */
+    lpToolInfo->uFlags   = toolPtr->uFlags;
+    lpToolInfo->rect     = toolPtr->rect;
+    lpToolInfo->hinst    = toolPtr->hinst;
+/*    lpToolInfo->lpszText = toolPtr->lpszText; */
+    lpToolInfo->lpszText = NULL;  /* FIXME */
+
+    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
+	lpToolInfo->lParam = toolPtr->lParam;
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLTIPS_GetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    if (lpToolInfo == NULL)
+	return FALSE;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
+	return FALSE;
+    if (infoPtr->uNumTools == 0)
+	return FALSE;
+
+    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
+    if (nTool == -1)
+	return FALSE;
+
+//    TRACE (tooltips, "tool %d\n", nTool);
+
+    toolPtr = &infoPtr->tools[nTool];
+
+    /* copy tool data */
+    lpToolInfo->uFlags   = toolPtr->uFlags;
+    lpToolInfo->rect     = toolPtr->rect;
+    lpToolInfo->hinst    = toolPtr->hinst;
+/*    lpToolInfo->lpszText = toolPtr->lpszText; */
+    lpToolInfo->lpszText = NULL;  /* FIXME */
+
+    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
+	lpToolInfo->lParam = toolPtr->lParam;
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLTIPS_HitTestA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTHITTESTINFOA lptthit = (LPTTHITTESTINFOA)lParam;
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    if (lptthit == 0)
+	return FALSE;
+
+    nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
+    if (nTool == -1)
+	return FALSE;
+
+//    TRACE (tooltips, "tool %d!\n", nTool);
+
+    /* copy tool data */
+    if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOA)) {
+	toolPtr = &infoPtr->tools[nTool];
+
+	lptthit->ti.uFlags   = toolPtr->uFlags;
+	lptthit->ti.hwnd     = toolPtr->hwnd;
+	lptthit->ti.uId      = toolPtr->uId;
+	lptthit->ti.rect     = toolPtr->rect;
+	lptthit->ti.hinst    = toolPtr->hinst;
+/*	lptthit->ti.lpszText = toolPtr->lpszText; */
+	lptthit->ti.lpszText = NULL;  /* FIXME */
+	lptthit->ti.lParam   = toolPtr->lParam;
+    }
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLTIPS_HitTestW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTHITTESTINFOW lptthit = (LPTTHITTESTINFOW)lParam;
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    if (lptthit == 0)
+	return FALSE;
+
+    nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
+    if (nTool == -1)
+	return FALSE;
+
+//    TRACE (tooltips, "tool %d!\n", nTool);
+
+    /* copy tool data */
+    if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOW)) {
+	toolPtr = &infoPtr->tools[nTool];
+
+	lptthit->ti.uFlags   = toolPtr->uFlags;
+	lptthit->ti.hwnd     = toolPtr->hwnd;
+	lptthit->ti.uId      = toolPtr->uId;
+	lptthit->ti.rect     = toolPtr->rect;
+	lptthit->ti.hinst    = toolPtr->hinst;
+/*	lptthit->ti.lpszText = toolPtr->lpszText; */
+	lptthit->ti.lpszText = NULL;  /* FIXME */
+	lptthit->ti.lParam   = toolPtr->lParam;
+    }
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLTIPS_NewToolRectA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOA lpti = (LPTTTOOLINFOA)lParam;
+    INT nTool;
+
+    if (lpti == NULL)
+	return 0;
+    if (lpti->cbSize < TTTOOLINFO_V1_SIZEA)
+	return FALSE;
+
+    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpti);
+    if (nTool == -1) return 0;
+
+    infoPtr->tools[nTool].rect = lpti->rect;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_NewToolRectW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOW lpti = (LPTTTOOLINFOW)lParam;
+    INT nTool;
+
+    if (lpti == NULL)
+	return 0;
+    if (lpti->cbSize < TTTOOLINFO_V1_SIZEW)
+	return FALSE;
+
+    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpti);
+    if (nTool == -1) return 0;
+
+    infoPtr->tools[nTool].rect = lpti->rect;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_Pop (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    TOOLTIPS_Hide (hwnd, infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_RelayEvent (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPMSG lpMsg = (LPMSG)lParam;
+    POINT pt;
+
+    if (lParam == 0) {
+//	ERR (tooltips, "lpMsg == NULL!\n");
+	return 0;
+    }
+
+    switch (lpMsg->message) {
+	case WM_LBUTTONDOWN:
+	case WM_LBUTTONUP:
+	case WM_MBUTTONDOWN:
+	case WM_MBUTTONUP:
+	case WM_RBUTTONDOWN:
+	case WM_RBUTTONUP:
+	    pt = lpMsg->pt;
+	    ScreenToClient (lpMsg->hwnd, &pt);
+	    infoPtr->nOldTool = infoPtr->nTool;
+	    infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
+//	    TRACE (tooltips, "tool (%x) %d %d\n",
+//		   hwnd, infoPtr->nOldTool, infoPtr->nTool);
+	    TOOLTIPS_Hide (hwnd, infoPtr);
+	    break;
+
+	case WM_MOUSEMOVE:
+	    pt = lpMsg->pt;
+	    ScreenToClient (lpMsg->hwnd, &pt);
+	    infoPtr->nOldTool = infoPtr->nTool;
+	    infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
+//	    TRACE (tooltips, "tool (%x) %d %d\n",
+//		   hwnd, infoPtr->nOldTool, infoPtr->nTool);
+//	    TRACE (tooltips, "WM_MOUSEMOVE (%04x %ld %ld)\n",
+//		   hwnd, pt.x, pt.y);
+	    if ((infoPtr->bActive) && (infoPtr->nTool != infoPtr->nOldTool)) {
+		if (infoPtr->nOldTool == -1) {
+		    SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0);
+//		    TRACE (tooltips, "timer 1 started!\n");
+		}
+		else {
+		    TOOLTIPS_Hide (hwnd, infoPtr);
+		    SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
+//		    TRACE (tooltips, "timer 2 started!\n");
+		}
+	    }
+	    if (infoPtr->nCurrentTool != -1) {
+		SetTimer (hwnd, ID_TIMERLEAVE, 100, 0);
+//		TRACE (tooltips, "timer 3 started!\n");
+	    }
+	    break;
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_SetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    INT nTime = (INT)LOWORD(lParam);
+
+    switch (wParam) {
+	case TTDT_AUTOMATIC:
+	    if (nTime == 0) {
+		infoPtr->nAutomaticTime = 500;
+		infoPtr->nReshowTime    = 100;
+		infoPtr->nAutoPopTime   = 5000;
+		infoPtr->nInitialTime   = 500;
+	    }
+	    else {
+		infoPtr->nAutomaticTime = nTime;
+		infoPtr->nReshowTime    = nTime / 5;
+		infoPtr->nAutoPopTime   = nTime * 10;
+		infoPtr->nInitialTime   = nTime;
+	    }
+	    break;
+
+	case TTDT_RESHOW:
+	    infoPtr->nReshowTime = nTime;
+	    break;
+
+	case TTDT_AUTOPOP:
+	    infoPtr->nAutoPopTime = nTime;
+	    break;
+
+	case TTDT_INITIAL:
+	    infoPtr->nInitialTime = nTime;
+	    break;
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_SetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPRECT lpRect = (LPRECT)lParam;
+
+    infoPtr->rcMargin.left   = lpRect->left;
+    infoPtr->rcMargin.right  = lpRect->right;
+    infoPtr->rcMargin.bottom = lpRect->bottom;
+    infoPtr->rcMargin.top    = lpRect->top;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_SetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    INT nTemp = infoPtr->nMaxTipWidth;
+
+    infoPtr->nMaxTipWidth = (INT)lParam;
+
+    return nTemp;
+}
+
+
+static LRESULT
+TOOLTIPS_SetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    infoPtr->clrBk = (COLORREF)wParam;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    infoPtr->clrText = (COLORREF)wParam;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    if (lpToolInfo == NULL)
+	return 0;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
+	return 0;
+
+    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
+    if (nTool == -1) return 0;
+
+//    TRACE (tooltips, "tool %d\n", nTool);
+
+    toolPtr = &infoPtr->tools[nTool];
+
+    /* copy tool data */
+    toolPtr->uFlags = lpToolInfo->uFlags;
+    toolPtr->hwnd   = lpToolInfo->hwnd;
+    toolPtr->uId    = lpToolInfo->uId;
+    toolPtr->rect   = lpToolInfo->rect;
+    toolPtr->hinst  = lpToolInfo->hinst;
+
+    if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
+//	TRACE (tooltips, "set string id %x!\n", (INT)lpToolInfo->lpszText);
+	toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
+    }
+    else if (lpToolInfo->lpszText) {
+	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
+	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
+	else {
+	    if (toolPtr->lpszText) {
+		COMCTL32_Free (toolPtr->lpszText);
+		toolPtr->lpszText = NULL;
+	    }
+	    if (lpToolInfo->lpszText) {
+		INT len = lstrlenA (lpToolInfo->lpszText);
+		toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
+//		lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
+		strcpy(toolPtr->lpszText, lpToolInfo->lpszText);
+	    }
+	}
+    }
+
+    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
+	toolPtr->lParam = lpToolInfo->lParam;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_SetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    if (lpToolInfo == NULL)
+	return 0;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
+	return 0;
+
+    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
+    if (nTool == -1) return 0;
+
+//    TRACE (tooltips, "tool %d\n", nTool);
+
+    toolPtr = &infoPtr->tools[nTool];
+
+    /* copy tool data */
+    toolPtr->uFlags = lpToolInfo->uFlags;
+    toolPtr->hwnd   = lpToolInfo->hwnd;
+    toolPtr->uId    = lpToolInfo->uId;
+    toolPtr->rect   = lpToolInfo->rect;
+    toolPtr->hinst  = lpToolInfo->hinst;
+
+    if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
+//	TRACE (tooltips, "set string id %x!\n", (INT)lpToolInfo->lpszText);
+	toolPtr->lpszText = lpToolInfo->lpszText;
+    }
+    else if (lpToolInfo->lpszText) {
+	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
+	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
+	else {
+	    if (toolPtr->lpszText) {
+		COMCTL32_Free (toolPtr->lpszText);
+		toolPtr->lpszText = NULL;
+	    }
+	    if (lpToolInfo->lpszText) {
+		INT len = lstrlenW (lpToolInfo->lpszText);
+		toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
+		lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
+	    }
+	}
+    }
+
+    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
+	toolPtr->lParam = lpToolInfo->lParam;
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_TrackActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
+
+    if (lpToolInfo == NULL)
+	return 0;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
+	return FALSE;
+
+    if ((BOOL)wParam) {
+	/* activate */
+	infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
+	if (infoPtr->nTrackTool != -1) {
+//	    TRACE (tooltips, "activated!\n");
+	    infoPtr->bTrackActive = TRUE;
+	    TOOLTIPS_TrackShow (hwnd, infoPtr);
+	}
+    }
+    else {
+	/* deactivate */
+	TOOLTIPS_TrackHide (hwnd, infoPtr);
+
+	infoPtr->bTrackActive = FALSE;
+	infoPtr->nTrackTool = -1;
+
+//	TRACE (tooltips, "deactivated!\n");
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_TrackPosition (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    infoPtr->xTrackPos = (INT)LOWORD(lParam);
+    infoPtr->yTrackPos = (INT)HIWORD(lParam);
+
+    if (infoPtr->bTrackActive) {
+//	TRACE (tooltips, "[%d %d]\n",
+//	       infoPtr->xTrackPos, infoPtr->yTrackPos);
+
+	TOOLTIPS_TrackShow (hwnd, infoPtr);
+    }
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_Update (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    if (infoPtr->nCurrentTool != -1)
+	UpdateWindow (hwnd);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_UpdateTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    if (lpToolInfo == NULL)
+	return 0;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
+	return FALSE;
+
+    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
+    if (nTool == -1) return 0;
+
+//    TRACE (tooltips, "tool %d\n", nTool);
+
+    toolPtr = &infoPtr->tools[nTool];
+
+    /* copy tool text */
+    toolPtr->hinst  = lpToolInfo->hinst;
+
+    if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
+	toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
+    }
+    else if (lpToolInfo->lpszText) {
+	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
+	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
+	else {
+	    if (toolPtr->lpszText) {
+		COMCTL32_Free (toolPtr->lpszText);
+		toolPtr->lpszText = NULL;
+	    }
+	    if (lpToolInfo->lpszText) {
+		INT len = lstrlenA (lpToolInfo->lpszText);
+		toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
+//		lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
+		strcpy(toolPtr->lpszText, lpToolInfo->lpszText);
+	    }
+	}
+    }
+
+    /* force repaint */
+    if (infoPtr->bActive)
+	TOOLTIPS_Show (hwnd, infoPtr);
+    else if (infoPtr->bTrackActive)
+	TOOLTIPS_TrackShow (hwnd, infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_UpdateTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
+    TTTOOL_INFO *toolPtr;
+    INT nTool;
+
+    if (lpToolInfo == NULL)
+	return 0;
+    if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
+	return FALSE;
+
+    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
+    if (nTool == -1)
+	return 0;
+
+//    TRACE (tooltips, "tool %d\n", nTool);
+
+    toolPtr = &infoPtr->tools[nTool];
+
+    /* copy tool text */
+    toolPtr->hinst  = lpToolInfo->hinst;
+
+    if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
+	toolPtr->lpszText = lpToolInfo->lpszText;
+    }
+    else if (lpToolInfo->lpszText) {
+	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
+	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
+	else {
+	    if (toolPtr->lpszText) {
+		COMCTL32_Free (toolPtr->lpszText);
+		toolPtr->lpszText = NULL;
+	    }
+	    if (lpToolInfo->lpszText) {
+		INT len = lstrlenW (lpToolInfo->lpszText);
+		toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
+		lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
+	    }
+	}
+    }
+
+    /* force repaint */
+    if (infoPtr->bActive)
+	TOOLTIPS_Show (hwnd, infoPtr);
+    else if (infoPtr->bTrackActive)
+	TOOLTIPS_TrackShow (hwnd, infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_WindowFromPoint (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    return WindowFromPoint (*((LPPOINT)lParam));
+}
+
+
+
+static LRESULT
+TOOLTIPS_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr;
+    NONCLIENTMETRICSA nclm;
+    INT nResult;
+
+    /* allocate memory for info structure */
+    infoPtr = (TOOLTIPS_INFO *)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO));
+    SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
+
+    /* initialize info structure */
+    infoPtr->bActive = TRUE;
+    infoPtr->bTrackActive = FALSE;
+    infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
+    infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
+
+    nclm.cbSize = sizeof(NONCLIENTMETRICSA);
+    SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
+    infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
+
+    infoPtr->nMaxTipWidth = -1;
+    infoPtr->nTool = -1;
+    infoPtr->nOldTool = -1;
+    infoPtr->nCurrentTool = -1;
+    infoPtr->nTrackTool = -1;
+
+    infoPtr->nAutomaticTime = 500;
+    infoPtr->nReshowTime    = 100;
+    infoPtr->nAutoPopTime   = 5000;
+    infoPtr->nInitialTime   = 500;
+
+    nResult = (INT) SendMessageA (GetParent (hwnd), WM_NOTIFYFORMAT,
+				  (WPARAM)hwnd, (LPARAM)NF_QUERY);
+//    if (nResult == NFR_ANSI)
+//	TRACE (tooltips, " -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
+//    else if (nResult == NFR_UNICODE)
+//	FIXME (tooltips, " -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
+//    else
+//	FIXME (tooltips, " -- WM_NOTIFYFORMAT returns: error!\n");
+
+    SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    TTTOOL_INFO *toolPtr;
+    INT i;
+
+    /* free tools */
+    if (infoPtr->tools) {
+	for (i = 0; i < infoPtr->uNumTools; i++) {
+	    toolPtr = &infoPtr->tools[i];
+	    if ((toolPtr->hinst) && (toolPtr->lpszText)) {
+		if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
+		    COMCTL32_Free (toolPtr->lpszText);
+	    }
+
+	    /* remove subclassing */
+	    if (toolPtr->uFlags & TTF_SUBCLASS) {
+		LPTT_SUBCLASS_INFO lpttsi;
+
+		if (toolPtr->uFlags & TTF_IDISHWND)
+		    lpttsi = (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
+		else
+		    lpttsi = (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
+
+		if (lpttsi) {
+		    SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
+				      (LONG)lpttsi->wpOrigProc);
+		    RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
+		    COMCTL32_Free (&lpttsi);
+		}
+	    }
+	}
+	COMCTL32_Free (infoPtr->tools);
+    }
+
+    /* delete font */
+    DeleteObject (infoPtr->hFont);
+
+    /* free tool tips info data */
+    COMCTL32_Free (infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    RECT rect;
+    HBRUSH hBrush;
+
+    hBrush = CreateSolidBrush (infoPtr->clrBk);
+    GetClientRect (hwnd, &rect);
+    FillRect ((HDC)wParam, &rect, hBrush);
+    DeleteObject (hBrush);
+
+    return FALSE;
+}
+
+
+static LRESULT
+TOOLTIPS_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    return infoPtr->hFont;
+}
+
+
+static LRESULT
+TOOLTIPS_MouseMessage (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    TOOLTIPS_Hide (hwnd, infoPtr);
+
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+
+    dwStyle &= 0x0000FFFF;
+    dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
+    SetWindowLongA (hwnd, GWL_STYLE, dwStyle);
+
+    return TRUE;
+}
+
+
+static LRESULT
+TOOLTIPS_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool;
+
+//    TRACE (tooltips, " nTool=%d\n", nTool);
+
+    if ((nTool > -1) && (nTool < infoPtr->uNumTools)) {
+	if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) {
+//	    TRACE (tooltips, "-- in transparent mode!\n");
+	    return HTTRANSPARENT;
+	}
+    }
+
+    return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
+}
+
+
+static LRESULT
+TOOLTIPS_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    HDC hdc;
+    PAINTSTRUCT ps;
+
+    hdc = (wParam == 0) ? BeginPaint (hwnd, &ps) : (HDC)wParam;
+    TOOLTIPS_Refresh (hwnd, hdc);
+    if (!wParam)
+	EndPaint (hwnd, &ps);
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+    infoPtr->hFont = (HFONT)wParam;
+
+    if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
+//	FIXME (tooltips, "full redraw needed!\n");
+    }
+
+    return 0;
+}
+/******************************************************************
+ * TOOLTIPS_OnWMGetTextLength
+ *
+ * This function is called when the tooltip receive a
+ * WM_GETTEXTLENGTH message.
+ * wParam : not used
+ * lParam : not used
+ *
+ * returns the length, in characters, of the tip text
+ ******************************************************************/
+static LRESULT
+TOOLTIPS_OnWMGetTextLength(HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    return lstrlenW(infoPtr->szTipText);
+}
+/******************************************************************
+ * TOOLTIPS_OnWMGetText
+ *
+ * This function is called when the tooltip receive a
+ * WM_GETTEXT message.
+ * wParam : specifies the maximum number of characters to be copied
+ * lParam : is the pointer to the buffer that will receive
+ *          the tip text
+ *
+ * returns the number of characters copied
+ ******************************************************************/
+static LRESULT
+TOOLTIPS_OnWMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    INT length;
+
+    if(!infoPtr || !(infoPtr->szTipText))
+        return 0;
+
+    length = lstrlenW(infoPtr->szTipText);
+    /* When wParam is smaller than the lenght of the tip text
+       copy wParam characters of the tip text and return wParam */
+    if(wParam < length)
+    {
+//        lstrcpynWtoA((LPSTR)lParam, infoPtr->szTipText,(UINT)wParam);
+        strncpy((LPSTR)lParam, infoPtr->szTipText,(UINT)wParam);
+        return wParam;
+    }
+//    lstrcpyWtoA((LPSTR)lParam, infoPtr->szTipText);
+    strcpy((LPSTR)lParam, infoPtr->szTipText);
+    return length;
+
+}
+
+static LRESULT
+TOOLTIPS_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+
+//    TRACE (tooltips, "timer %d (%x) expired!\n", wParam, hwnd);
+
+    switch (wParam)
+    {
+	case ID_TIMERSHOW:
+	    KillTimer (hwnd, ID_TIMERSHOW);
+	    if (TOOLTIPS_CheckTool (hwnd, TRUE) == infoPtr->nTool)
+		TOOLTIPS_Show (hwnd, infoPtr);
+	    break;
+
+	case ID_TIMERPOP:
+	    TOOLTIPS_Hide (hwnd, infoPtr);
+	    break;
+
+	case ID_TIMERLEAVE:
+	    KillTimer (hwnd, ID_TIMERLEAVE);
+	    if (TOOLTIPS_CheckTool (hwnd, FALSE) == -1) {
+		infoPtr->nTool = -1;
+		infoPtr->nOldTool = -1;
+		TOOLTIPS_Hide (hwnd, infoPtr);
+	    }
+	    break;
+    }
+    return 0;
+}
+
+
+static LRESULT
+TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
+    NONCLIENTMETRICSA nclm;
+
+    infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
+    infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
+
+    DeleteObject (infoPtr->hFont);
+    nclm.cbSize = sizeof(NONCLIENTMETRICSA);
+    SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
+    infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
+
+    return 0;
+}
+
+
+LRESULT CALLBACK
+TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    LPTT_SUBCLASS_INFO lpttsi =
+	(LPTT_SUBCLASS_INFO)GetPropA (hwnd, COMCTL32_aSubclass);
+    TOOLTIPS_INFO *infoPtr;
+    UINT nTool;
+
+    switch (uMsg) {
+	case WM_LBUTTONDOWN:
+	case WM_LBUTTONUP:
+	case WM_MBUTTONDOWN:
+	case WM_MBUTTONUP:
+	case WM_RBUTTONDOWN:
+	case WM_RBUTTONUP:
+	    infoPtr = TOOLTIPS_GetInfoPtr(lpttsi->hwndToolTip);
+		nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
+
+//		TRACE (tooltips, "subclassed mouse message %04x\n", uMsg);
+		infoPtr->nOldTool = infoPtr->nTool;
+		infoPtr->nTool = nTool;
+	    TOOLTIPS_Hide (lpttsi->hwndToolTip, infoPtr);
+	    break;
+
+	case WM_MOUSEMOVE:
+	    infoPtr = TOOLTIPS_GetInfoPtr (lpttsi->hwndToolTip);
+		nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
+
+//		TRACE (tooltips, "subclassed WM_MOUSEMOVE\n");
+		infoPtr->nOldTool = infoPtr->nTool;
+		infoPtr->nTool = nTool;
+
+		if ((infoPtr->bActive) &&
+		    (infoPtr->nTool != infoPtr->nOldTool)) {
+		    if (infoPtr->nOldTool == -1) {
+		    SetTimer (hwnd, ID_TIMERSHOW,
+				    infoPtr->nInitialTime, 0);
+//			TRACE (tooltips, "timer 1 started!\n");
+		    }
+		    else {
+		    TOOLTIPS_Hide (lpttsi->hwndToolTip, infoPtr);
+		    SetTimer (hwnd, ID_TIMERSHOW,
+				infoPtr->nReshowTime, 0);
+//			TRACE (tooltips, "timer 2 started!\n");
+		    }
+		}
+		if (infoPtr->nCurrentTool != -1) {
+		SetTimer (hwnd, ID_TIMERLEAVE, 100, 0);
+//		    TRACE (tooltips, "timer 3 started!\n");
+		}
+	    break;
+    }
+
+    return CallWindowProcA (lpttsi->wpOrigProc, hwnd, uMsg, wParam, lParam);
+}
+
+
+LRESULT CALLBACK
+TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    switch (uMsg)
+    {
+	case TTM_ACTIVATE:
+	    return TOOLTIPS_Activate (hwnd, wParam, lParam);
+
+	case TTM_ADDTOOLA:
+	    return TOOLTIPS_AddToolA (hwnd, wParam, lParam);
+
+	case TTM_ADDTOOLW:
+	    return TOOLTIPS_AddToolW (hwnd, wParam, lParam);
+
+	case TTM_DELTOOLA:
+	    return TOOLTIPS_DelToolA (hwnd, wParam, lParam);
+
+	case TTM_DELTOOLW:
+	    return TOOLTIPS_DelToolW (hwnd, wParam, lParam);
+
+	case TTM_ENUMTOOLSA:
+	    return TOOLTIPS_EnumToolsA (hwnd, wParam, lParam);
+
+	case TTM_ENUMTOOLSW:
+	    return TOOLTIPS_EnumToolsW (hwnd, wParam, lParam);
+
+	case TTM_GETCURRENTTOOLA:
+	    return TOOLTIPS_GetCurrentToolA (hwnd, wParam, lParam);
+
+	case TTM_GETCURRENTTOOLW:
+	    return TOOLTIPS_GetCurrentToolW (hwnd, wParam, lParam);
+
+	case TTM_GETDELAYTIME:
+	    return TOOLTIPS_GetDelayTime (hwnd, wParam, lParam);
+
+	case TTM_GETMARGIN:
+	    return TOOLTIPS_GetMargin (hwnd, wParam, lParam);
+
+	case TTM_GETMAXTIPWIDTH:
+	    return TOOLTIPS_GetMaxTipWidth (hwnd, wParam, lParam);
+
+	case TTM_GETTEXTA:
+	    return TOOLTIPS_GetTextA (hwnd, wParam, lParam);
+
+	case TTM_GETTEXTW:
+	    return TOOLTIPS_GetTextW (hwnd, wParam, lParam);
+
+	case TTM_GETTIPBKCOLOR:
+	    return TOOLTIPS_GetTipBkColor (hwnd, wParam, lParam);
+
+	case TTM_GETTIPTEXTCOLOR:
+	    return TOOLTIPS_GetTipTextColor (hwnd, wParam, lParam);
+
+	case TTM_GETTOOLCOUNT:
+	    return TOOLTIPS_GetToolCount (hwnd, wParam, lParam);
+
+	case TTM_GETTOOLINFOA:
+	    return TOOLTIPS_GetToolInfoA (hwnd, wParam, lParam);
+
+	case TTM_GETTOOLINFOW:
+	    return TOOLTIPS_GetToolInfoW (hwnd, wParam, lParam);
+
+	case TTM_HITTESTA:
+	    return TOOLTIPS_HitTestA (hwnd, wParam, lParam);
+
+	case TTM_HITTESTW:
+	    return TOOLTIPS_HitTestW (hwnd, wParam, lParam);
+
+	case TTM_NEWTOOLRECTA:
+	    return TOOLTIPS_NewToolRectA (hwnd, wParam, lParam);
+
+	case TTM_NEWTOOLRECTW:
+	    return TOOLTIPS_NewToolRectW (hwnd, wParam, lParam);
+
+	case TTM_POP:
+	    return TOOLTIPS_Pop (hwnd, wParam, lParam);
+
+	case TTM_RELAYEVENT:
+	    return TOOLTIPS_RelayEvent (hwnd, wParam, lParam);
+
+	case TTM_SETDELAYTIME:
+	    return TOOLTIPS_SetDelayTime (hwnd, wParam, lParam);
+
+	case TTM_SETMARGIN:
+	    return TOOLTIPS_SetMargin (hwnd, wParam, lParam);
+
+	case TTM_SETMAXTIPWIDTH:
+	    return TOOLTIPS_SetMaxTipWidth (hwnd, wParam, lParam);
+
+	case TTM_SETTIPBKCOLOR:
+	    return TOOLTIPS_SetTipBkColor (hwnd, wParam, lParam);
+
+	case TTM_SETTIPTEXTCOLOR:
+	    return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam);
+
+	case TTM_SETTOOLINFOA:
+	    return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
+
+	case TTM_SETTOOLINFOW:
+	    return TOOLTIPS_SetToolInfoW (hwnd, wParam, lParam);
+
+	case TTM_TRACKACTIVATE:
+	    return TOOLTIPS_TrackActivate (hwnd, wParam, lParam);
+
+	case TTM_TRACKPOSITION:
+	    return TOOLTIPS_TrackPosition (hwnd, wParam, lParam);
+
+	case TTM_UPDATE:
+	    return TOOLTIPS_Update (hwnd, wParam, lParam);
+
+	case TTM_UPDATETIPTEXTA:
+	    return TOOLTIPS_UpdateTipTextA (hwnd, wParam, lParam);
+
+	case TTM_UPDATETIPTEXTW:
+	    return TOOLTIPS_UpdateTipTextW (hwnd, wParam, lParam);
+
+	case TTM_WINDOWFROMPOINT:
+	    return TOOLTIPS_WindowFromPoint (hwnd, wParam, lParam);
+
+
+	case WM_CREATE:
+	    return TOOLTIPS_Create (hwnd, wParam, lParam);
+
+	case WM_DESTROY:
+	    return TOOLTIPS_Destroy (hwnd, wParam, lParam);
+
+	case WM_ERASEBKGND:
+	    return TOOLTIPS_EraseBackground (hwnd, wParam, lParam);
+
+	case WM_GETFONT:
+	    return TOOLTIPS_GetFont (hwnd, wParam, lParam);
+
+        case WM_GETTEXT:
+            return TOOLTIPS_OnWMGetText (hwnd, wParam, lParam);
+        
+        case WM_GETTEXTLENGTH:
+            return TOOLTIPS_OnWMGetTextLength (hwnd, wParam, lParam);
+ 
+
+	case WM_LBUTTONDOWN:
+	case WM_LBUTTONUP:
+	case WM_MBUTTONDOWN:
+	case WM_MBUTTONUP:
+	case WM_RBUTTONDOWN:
+	case WM_RBUTTONUP:
+	case WM_MOUSEMOVE:
+	    return TOOLTIPS_MouseMessage (hwnd, uMsg, wParam, lParam);
+
+	case WM_NCCREATE:
+	    return TOOLTIPS_NCCreate (hwnd, wParam, lParam);
+
+	case WM_NCHITTEST:
+	    return TOOLTIPS_NCHitTest (hwnd, wParam, lParam);
+
+/*	case WM_NOTIFYFORMAT: */
+/*	    return TOOLTIPS_NotifyFormat (hwnd, wParam, lParam); */
+
+	case WM_PAINT:
+	    return TOOLTIPS_Paint (hwnd, wParam, lParam);
+
+	case WM_SETFONT:
+	    return TOOLTIPS_SetFont (hwnd, wParam, lParam);
+
+	case WM_TIMER:
+	    return TOOLTIPS_Timer (hwnd, wParam, lParam);
+
+	case WM_WININICHANGE:
+	    return TOOLTIPS_WinIniChange (hwnd, wParam, lParam);
+
+	default:
+	    if (uMsg >= WM_USER)
+//		ERR (tooltips, "unknown msg %04x wp=%08x lp=%08lx\n",
+//		     uMsg, wParam, lParam);
+	    return DefWindowProcA (hwnd, uMsg, wParam, lParam);
+    }
+    return 0;
+}
+
+
+VOID
+TOOLTIPS_Register (VOID)
+{
+    WNDCLASSA wndClass;
+
+    if (GlobalFindAtomA (TOOLTIPS_CLASSA)) return;
+
+    ZeroMemory (&wndClass, sizeof(WNDCLASSA));
+    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
+    wndClass.lpfnWndProc   = (WNDPROC)TOOLTIPS_WindowProc;
+    wndClass.cbClsExtra    = 0;
+    wndClass.cbWndExtra    = sizeof(TOOLTIPS_INFO *);
+    wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
+    wndClass.hbrBackground = 0;
+    wndClass.lpszClassName = TOOLTIPS_CLASSA;
+ 
+    RegisterClassA (&wndClass);
+}
+
+
+VOID
+TOOLTIPS_Unregister (VOID)
+{
+    if (GlobalFindAtomA (TOOLTIPS_CLASSA))
+	UnregisterClassA (TOOLTIPS_CLASSA, (HINSTANCE)NULL);
+}
+
