Implemented most functionality.  TODO lists whats left.

diff --git a/dlls/comctl32/pager.c b/dlls/comctl32/pager.c
index 94d4086..8f8bf3c 100644
--- a/dlls/comctl32/pager.c
+++ b/dlls/comctl32/pager.c
@@ -4,13 +4,14 @@
  * Copyright 1998, 1999 Eric Kohl
  *
  * NOTES
- *   This is just a dummy control. An author is needed! Any volunteers?
- *   I will only improve this control once in a while.
- *     Eric <ekohl@abo.rhein-zeitung.de>
+ *    Tested primarily with the controlspy Pager application.
+ *       Susan Farley (susan@codeweavers.com)
  *
  * TODO:
- *   - All messages.
- *   - All notifications.
+ *    Implement repetitive button press.
+ *    Adjust arrow size relative to size of button.
+ *    Allow border size changes.
+ *    Implement drag and drop style.
  */
 
 #include "winbase.h"
@@ -21,199 +22,618 @@
 
 typedef struct
 {
-    HWND   hwndChild;
-    COLORREF clrBk;
-    INT    nBorder;
-    INT    nButtonSize;
-    INT    nPos;
-    BOOL   bForward;
-
-    INT    nChildSize;
+    HWND   hwndChild;  /* handle of the contained wnd */
+    BOOL   bHorizontal;/* orientation of the control */
+    COLORREF clrBk;    /* background color */
+    INT    nBorder;    /* border size for the control */
+    INT    nButtonSize;/* size of the pager btns */
+    INT    nPos;       /* scroll position */
+    INT    nDelta;     /* scroll delta */
+    INT    nWidth;     /* from child wnd's response to PGN_CALCSIZE */
+    INT    nHeight;    /* from child wnd's response to PGN_CALCSIZE */ 
+    BOOL   bForward;   /* forward WM_MOUSEMOVE msgs to the contained wnd */
+    INT    TLbtnState; /* state of top or left btn */
+    INT    BRbtnState; /* state of bottom or right btn */
 
 } PAGER_INFO;
 
 #define PAGER_GetInfoPtr(hwnd) ((PAGER_INFO *)GetWindowLongA(hwnd, 0))
 
+#define MIN_ARROW_WIDTH  8
+#define MIN_ARROW_HEIGHT 5
+
+/* the horizontal arrows are: 
+ *
+ * 01234    01234
+ * 1  *      *
+ * 2 **      **
+ * 3***      ***
+ * 4***      ***
+ * 5 **      **
+ * 6  *      *
+ * 7  
+ *
+ */
+static void
+PAGER_DrawHorzArrow (HDC hdc, RECT r, INT colorRef, BOOL left)
+{
+    INT x, y, w, h;
+    HPEN hOldPen;
+    
+    w = r.right - r.left + 1;
+    h = r.bottom - r.top + 1;
+    if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
+        return;  /* refuse to draw partial arrow */
+
+    hOldPen = SelectObject ( hdc, GetSysColorPen (colorRef));
+    if (left)
+    {
+        x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 3;
+        y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x--, y+5); y++;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x--, y+3); y++;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x, y+1);
+    }
+    else
+    {
+        x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
+        y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x++, y+5); y++;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x++, y+3); y++;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x, y+1);
+    }
+
+    SelectObject( hdc, hOldPen );
+}
+
+/* the vertical arrows are: 
+ *
+ * 01234567    01234567
+ * 1******        **  
+ * 2 ****        ****
+ * 3  **        ******
+ * 4
+ *
+ */
+static void
+PAGER_DrawVertArrow (HDC hdc, RECT r, INT colorRef, BOOL up)
+{
+    INT x, y, w, h;
+    HPEN hOldPen;
+    
+    w = r.right - r.left + 1;
+    h = r.bottom - r.top + 1;
+    if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
+        return;  /* refuse to draw partial arrow */
+
+    hOldPen = SelectObject ( hdc, GetSysColorPen (colorRef));
+    if (up)
+    {
+        x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
+        y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 3;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x+5, y--); x++;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x+3, y--); x++;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x+1, y);
+    }
+    else
+    {
+        x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
+        y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x+5, y++); x++;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x+3, y++); x++;
+        MoveToEx (hdc, x, y, NULL);
+        LineTo (hdc, x+1, y);
+    }
+
+    SelectObject( hdc, hOldPen );
+}
+
+static void
+PAGER_DrawButton(HDC hdc, COLORREF clrBk, RECT arrowRect,
+                 BOOL horz, BOOL topLeft, INT btnState)
+{
+    HBRUSH   hBrush, hOldBrush;
+    RECT     rc = arrowRect;
+
+    if (!btnState) /* PGF_INVISIBLE */
+        return;
+
+    if ((rc.right - rc.left <= 0) || (rc.bottom - rc.top <= 0))
+        return;  
+
+    hBrush = CreateSolidBrush(clrBk);
+    hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
+
+    FillRect(hdc, &rc, hBrush);
+
+    if (btnState == PGF_HOT) 
+    {
+       rc.left++, rc.top++; rc.right++, rc.bottom++;
+       DrawEdge( hdc, &rc, EDGE_RAISED, BF_RECT);
+       if (horz)
+           PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
+       else
+           PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
+       rc.left--, rc.top--; rc.right--, rc.bottom--;
+    }
+    else if (btnState == PGF_NORMAL) 
+    {
+       DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
+       if (horz)
+           PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
+       else
+           PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
+    }
+    else if (btnState == PGF_DEPRESSED) 
+    {
+       rc.left++, rc.top++;
+       DrawEdge( hdc, &rc, BDR_SUNKENOUTER, BF_RECT);
+       if (horz)
+           PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
+       else
+           PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
+       rc.left--, rc.top--;
+    }
+    else if (btnState == PGF_GRAYED) 
+    {
+       DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
+       if (horz)
+       {
+           PAGER_DrawHorzArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft);
+           rc.left++, rc.top++; rc.right++, rc.bottom++;
+           PAGER_DrawHorzArrow(hdc, rc, COLOR_3DSHADOW, topLeft);
+       }
+       else
+       {
+           PAGER_DrawVertArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft);
+           rc.left++, rc.top++; rc.right++, rc.bottom++;
+           PAGER_DrawVertArrow(hdc, rc, COLOR_3DSHADOW, topLeft);
+       }
+       rc.left--, rc.top--; rc.right--, rc.bottom--;
+    }
+
+    SelectObject( hdc, hOldBrush );
+    DeleteObject(hBrush);
+}
+
+/* << PAGER_GetDropTarget >> */
 
 static inline LRESULT
 PAGER_ForwardMouse (HWND hwnd, WPARAM wParam)
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    TRACE("[%04x]\n", hwnd);
 
     infoPtr->bForward = (BOOL)wParam;
 
     return 0;
 }
 
-
 static inline LRESULT
-PAGER_GetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
+PAGER_GetButtonState (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); 
+    LRESULT btnState = PGF_INVISIBLE;
+    INT btn = (INT)lParam;
+    TRACE("[%04x]\n", hwnd);
 
-    return (LRESULT)infoPtr->clrBk;
+    if (btn == PGB_TOPORLEFT)
+        btnState = infoPtr->TLbtnState;
+    else if (btn == PGB_BOTTOMORRIGHT)
+        btnState = infoPtr->BRbtnState;
+
+    return btnState;
 }
 
 
 static inline LRESULT
-PAGER_GetBorder (HWND hwnd, WPARAM wParam, LPARAM lParam)
+PAGER_GetPos(HWND hwnd)
 {
-    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
-
-    return (LRESULT)infoPtr->nBorder;
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); 
+    TRACE("[%04x] returns %d\n", hwnd, infoPtr->nPos);
+    return (LRESULT)infoPtr->nPos;
 }
 
-
 static inline LRESULT
-PAGER_GetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
+PAGER_GetButtonSize(HWND hwnd)
 {
-    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
-
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); 
+    TRACE("[%04x] returns %d\n", hwnd, infoPtr->nButtonSize);
     return (LRESULT)infoPtr->nButtonSize;
 }
 
-
-static LRESULT
-PAGER_GetButtonState (HWND hwnd, WPARAM wParam, LPARAM lParam)
+static inline LRESULT
+PAGER_GetBorder(HWND hwnd)
 {
-    /* PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); */
-
-    FIXME("empty stub!\n");
-
-    return PGF_INVISIBLE;
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); 
+    TRACE("[%04x] returns %d\n", hwnd, infoPtr->nBorder);
+    return (LRESULT)infoPtr->nBorder;
 }
 
-
-/* << PAGER_GetDropTarget >> */
-
-
 static inline LRESULT
-PAGER_GetPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
+PAGER_GetBkColor(HWND hwnd)
 {
-    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); 
+    TRACE("[%04x] returns %06lx\n", hwnd, infoPtr->clrBk);
+    return (LRESULT)infoPtr->clrBk;
+}
 
-    return infoPtr->nPos;
+static void 
+PAGER_CalcSize (HWND hwnd, INT* size, BOOL getWidth) 
+{
+    NMPGCALCSIZE nmpgcs;
+    ZeroMemory (&nmpgcs, sizeof (NMPGCALCSIZE));
+    nmpgcs.hdr.hwndFrom = hwnd;
+    nmpgcs.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
+    nmpgcs.hdr.code = PGN_CALCSIZE;
+    nmpgcs.dwFlag = getWidth ? PGF_CALCWIDTH : PGF_CALCHEIGHT;
+    nmpgcs.iWidth = getWidth ? *size : 0;
+    nmpgcs.iHeight = getWidth ? 0 : *size;
+    SendMessageA (hwnd, WM_NOTIFY,
+                  (WPARAM)nmpgcs.hdr.idFrom, (LPARAM)&nmpgcs);
+
+    *size = getWidth ? nmpgcs.iWidth : nmpgcs.iHeight;
+
+    TRACE("[%04x] PGN_CALCSIZE returns %s=%d\n", hwnd,
+                  getWidth ? "width" : "height", *size);
+}
+
+static void
+PAGER_PositionChildWnd(HWND hwnd, PAGER_INFO* infoPtr)
+{
+    if (infoPtr->hwndChild)
+    {
+        int nPos = infoPtr->nPos;
+
+        /* compensate for a grayed btn, which will soon become invisible */
+        if (infoPtr->TLbtnState == PGF_GRAYED)
+            nPos += infoPtr->nButtonSize;
+
+        if (infoPtr->bHorizontal)
+        {
+            TRACE("[%04x] SWP %dx%d at (%d,%d)\n", hwnd,
+                         infoPtr->nWidth, infoPtr->nHeight,
+                         -nPos, 0);
+            SetWindowPos(infoPtr->hwndChild, 0,
+                         -nPos, 0,
+                         infoPtr->nWidth, infoPtr->nHeight,
+    	     SWP_NOZORDER);
+        }
+        else
+        {
+            TRACE("[%04x] SWP %dx%d at (%d,%d)\n", hwnd, 
+	         infoPtr->nWidth, infoPtr->nHeight,
+                         0, -nPos);
+            SetWindowPos(infoPtr->hwndChild, 0,
+                         0, -nPos,
+                         infoPtr->nWidth, infoPtr->nHeight,
+                         SWP_NOZORDER);
+        }
+
+        InvalidateRect(infoPtr->hwndChild, NULL, FALSE);
+    }
+}
+
+static INT
+PAGER_GetScrollRange(HWND hwnd, PAGER_INFO* infoPtr)
+{
+    INT scrollRange = 0;
+
+    if (infoPtr->hwndChild)
+    {
+        INT wndSize, childSize;
+        RECT wndRect;
+        GetWindowRect(hwnd, &wndRect);
+
+        if (infoPtr->bHorizontal)
+        {
+            wndSize = wndRect.right - wndRect.left;
+            PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
+            childSize = infoPtr->nWidth;
+        }
+        else
+        {
+            wndSize = wndRect.bottom - wndRect.top;
+            PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
+            childSize = infoPtr->nHeight;
+        }
+
+        if (childSize > wndSize)
+            scrollRange = childSize - wndSize + infoPtr->nButtonSize;
+    }
+
+    TRACE("[%04x] returns %d\n", hwnd, scrollRange);
+    return scrollRange;
+}
+
+static void 
+PAGER_GrayAndRestoreBtns(PAGER_INFO* infoPtr, INT scrollRange,
+                         BOOL* needsResize, BOOL* needsRepaint)
+{
+    if (infoPtr->nPos > 0)
+    {
+        *needsResize |= !infoPtr->TLbtnState; /* PGF_INVISIBLE */
+        if (infoPtr->TLbtnState != PGF_DEPRESSED)
+            infoPtr->TLbtnState = PGF_NORMAL;
+    }
+    else
+    {
+        *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
+        infoPtr->TLbtnState = PGF_GRAYED;
+    }
+
+    if (scrollRange <= 0)
+    {
+        *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
+        infoPtr->TLbtnState = PGF_GRAYED;
+        *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
+        infoPtr->BRbtnState = PGF_GRAYED;
+    }
+    else if (infoPtr->nPos < scrollRange)
+    {
+        *needsResize |= !infoPtr->BRbtnState; /* PGF_INVISIBLE */
+        if (infoPtr->BRbtnState != PGF_DEPRESSED)
+            infoPtr->BRbtnState = PGF_NORMAL;
+    }
+    else
+    {
+        *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
+        infoPtr->BRbtnState = PGF_GRAYED;
+    }
 }
 
 
-static LRESULT
-PAGER_RecalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
+static void 
+PAGER_NormalizeBtns(PAGER_INFO* infoPtr, BOOL* needsRepaint)
+{
+    if (infoPtr->TLbtnState & (PGF_HOT | PGF_DEPRESSED))
+    {
+        infoPtr->TLbtnState = PGF_NORMAL;
+        *needsRepaint = TRUE;
+    }
+
+    if (infoPtr->BRbtnState & (PGF_HOT | PGF_DEPRESSED))
+    {
+        infoPtr->BRbtnState = PGF_NORMAL;
+        *needsRepaint = TRUE;
+    }
+}
+
+static void 
+PAGER_HideGrayBtns(PAGER_INFO* infoPtr, BOOL* needsResize)
+{
+    if (infoPtr->TLbtnState == PGF_GRAYED)
+    {
+        infoPtr->TLbtnState = PGF_INVISIBLE;
+        *needsResize = TRUE;
+    }
+
+    if (infoPtr->BRbtnState == PGF_GRAYED)
+    {
+        infoPtr->BRbtnState = PGF_INVISIBLE;
+        *needsResize = TRUE;
+    }
+}
+
+static void
+PAGER_UpdateBtns(HWND hwnd, PAGER_INFO *infoPtr,
+                 INT scrollRange, BOOL hideGrayBtns)
+{
+    BOOL resizeClient = FALSE;
+    BOOL repaintBtns = FALSE;
+
+    if (scrollRange < 0)
+        PAGER_NormalizeBtns(infoPtr, &repaintBtns);
+    else
+        PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
+
+    if (hideGrayBtns)
+        PAGER_HideGrayBtns(infoPtr, &resizeClient);
+
+    if (resizeClient) /* initiate NCCalcSize to resize client wnd */
+        SetWindowPos(hwnd, 0,0,0,0,0, 
+                     SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
+                     SWP_NOZORDER | SWP_NOACTIVATE);
+
+    if (repaintBtns)
+        SendMessageA(hwnd, WM_NCPAINT, 0, 0); 
+}
+
+static LRESULT  
+PAGER_SetPos(HWND hwnd, INT newPos, BOOL fromBtnPress)
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
-    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
-    NMPGCALCSIZE nmpgcs;
+    INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
 
-    if (infoPtr->hwndChild) {
-	ZeroMemory (&nmpgcs, sizeof (NMPGCALCSIZE));
-	nmpgcs.hdr.hwndFrom = hwnd;
-	nmpgcs.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
-	nmpgcs.hdr.code = PGN_CALCSIZE;
-	nmpgcs.dwFlag = (dwStyle & PGS_HORZ) ? PGF_CALCWIDTH : PGF_CALCHEIGHT;
-	SendMessageA (GetParent (hwnd), WM_NOTIFY,
-			(WPARAM)nmpgcs.hdr.idFrom, (LPARAM)&nmpgcs);
+    if (scrollRange <= 0)
+        newPos = 0;
+    else if (newPos < 0)
+        newPos = 0;
+    else if (newPos > scrollRange)
+        newPos = scrollRange;
 
-	infoPtr->nChildSize = (dwStyle & PGS_HORZ) ? nmpgcs.iWidth : nmpgcs.iHeight;
+    if (newPos != infoPtr->nPos)
+    {
+        infoPtr->nPos = newPos;
+        TRACE("[%04x] pos=%d\n", hwnd, infoPtr->nPos);
 
+        /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
+        PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, !fromBtnPress);
 
-        FIXME("Child size %d\n", infoPtr->nChildSize);
+        PAGER_PositionChildWnd(hwnd, infoPtr);
+    }
 
+    return 0;
+}
 
+static LRESULT
+PAGER_RecalcSize(HWND hwnd)
+{
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    INT scrollRange;
+
+    TRACE("[%04x]\n", hwnd);
+    scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
+
+    if (scrollRange <= 0)
+    PAGER_SetPos(hwnd, 0, FALSE);
+    else 
+    {
+        PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, TRUE);
+        PAGER_PositionChildWnd(hwnd, infoPtr);
     }
 
     return 0;
 }
 
 
-static inline LRESULT
+static LRESULT
 PAGER_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
     COLORREF clrTemp = infoPtr->clrBk;
 
     infoPtr->clrBk = (COLORREF)lParam;
+    TRACE("[%04x] %06lx\n", hwnd, infoPtr->clrBk);
 
-    /* FIXME: redraw */
+    PAGER_RecalcSize(hwnd);
 
     return (LRESULT)clrTemp;
 }
 
 
-static inline LRESULT
+static LRESULT
 PAGER_SetBorder (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
     INT nTemp = infoPtr->nBorder;
 
     infoPtr->nBorder = (INT)lParam;
+    TRACE("[%04x] %d\n", hwnd, infoPtr->nBorder);
 
-    /* FIXME: redraw */
+    PAGER_RecalcSize(hwnd);
 
     return (LRESULT)nTemp;
 }
 
 
-static inline LRESULT
+static LRESULT
 PAGER_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
     INT nTemp = infoPtr->nButtonSize;
 
     infoPtr->nButtonSize = (INT)lParam;
+    TRACE("[%04x] %d\n", hwnd, infoPtr->nButtonSize);
 
-    FIXME("size=%d\n", infoPtr->nButtonSize);
-
-    /* FIXME: redraw */
+    PAGER_RecalcSize(hwnd);
 
     return (LRESULT)nTemp;
 }
 
 
-static inline LRESULT
+
+static LRESULT
 PAGER_SetChild (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
 
     infoPtr->hwndChild = IsWindow ((HWND)lParam) ? (HWND)lParam : 0;
 
-    FIXME("hwnd=%x\n", infoPtr->hwndChild);
+    if (infoPtr->hwndChild)
+    {
+        RECT wndRect;
+        INT wndSizeScrollable;
 
-    /* FIXME: redraw */
-    if (infoPtr->hwndChild) {
-	RECT rect;
+        TRACE("[%04x] hwndChild=%04x\n", hwnd, infoPtr->hwndChild);
 
-	GetClientRect (hwnd, &rect);
-	SetParent (infoPtr->hwndChild, hwnd);
-	SetWindowPos (infoPtr->hwndChild, HWND_TOP,
-			0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE);
+        GetWindowRect(hwnd, &wndRect);
+        wndSizeScrollable = infoPtr->bHorizontal ?
+                            wndRect.right - wndRect.left :
+                            wndRect.bottom - wndRect.top;
 
-	MoveWindow (infoPtr->hwndChild, 0, 0, rect.right, rect.bottom, TRUE);
+        infoPtr->nPos = 0;
+        infoPtr->nDelta = wndSizeScrollable;
+
+        PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
+        PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
+
+        /* adjust non-scrollable dimension to fit the child */
+        SetWindowPos(hwnd, 0,
+                     0,0,
+                     infoPtr->bHorizontal ? wndSizeScrollable : infoPtr->nWidth,
+                     infoPtr->bHorizontal ? infoPtr->nHeight : wndSizeScrollable, 
+                     SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER);
+
+        /* position child within the page scroller */
+        SetWindowPos(infoPtr->hwndChild, HWND_TOP,
+                     0,0,0,0,
+                     SWP_SHOWWINDOW | SWP_NOSIZE);
+
+        PAGER_SetPos(hwnd, 0, FALSE);
     }
 
     return 0;
 }
 
-
-static inline LRESULT
-PAGER_SetPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
+static void
+PAGER_Scroll(HWND hwnd, INT dir)
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    NMPGSCROLL nmpgScroll;
 
-    infoPtr->nPos = (INT)lParam;
+    if (infoPtr->hwndChild)
+    {
+        ZeroMemory (&nmpgScroll, sizeof (NMPGSCROLL));
+        nmpgScroll.hdr.hwndFrom = hwnd;
+        nmpgScroll.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
+        nmpgScroll.hdr.code = PGN_SCROLL;
 
-    FIXME("pos=%d\n", infoPtr->nPos);
+        GetClientRect(hwnd, &nmpgScroll.rcParent);  
+        nmpgScroll.iXpos = nmpgScroll.iYpos = 0;
+        nmpgScroll.iDir = dir;
+        nmpgScroll.iScroll = infoPtr->nDelta;
 
-    /* FIXME: redraw */
-    SetWindowPos (infoPtr->hwndChild, HWND_TOP,
-		    0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE);
+        if (infoPtr->bHorizontal)
+            nmpgScroll.iXpos = infoPtr->nPos;
+        else
+            nmpgScroll.iYpos = infoPtr->nPos;
 
-    return 0;
+        TRACE("[%04x] sending PGN_SCROLL\n", hwnd);
+        SendMessageA (hwnd, WM_NOTIFY,
+                    (WPARAM)nmpgScroll.hdr.idFrom, (LPARAM)&nmpgScroll);
+
+        if (infoPtr->nDelta != nmpgScroll.iScroll)
+        {
+            TRACE("delta changing from %d to %d\n",
+            infoPtr->nDelta, nmpgScroll.iScroll);
+            infoPtr->nDelta = nmpgScroll.iScroll;
+        }
+
+        if (dir == PGF_SCROLLLEFT || dir == PGF_SCROLLUP)
+            PAGER_SetPos(hwnd, infoPtr->nPos - infoPtr->nDelta, TRUE);
+        else
+            PAGER_SetPos(hwnd, infoPtr->nPos + infoPtr->nDelta, TRUE);
+    }
 }
 
-
 static LRESULT
 PAGER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     PAGER_INFO *infoPtr;
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+    SetWindowLongA(hwnd, GWL_STYLE, dwStyle & WS_CLIPCHILDREN);
 
     /* allocate memory for info structure */
     infoPtr = (PAGER_INFO *)COMCTL32_Alloc (sizeof(PAGER_INFO));
@@ -221,11 +641,33 @@
 
     /* set default settings */
     infoPtr->hwndChild = (HWND)NULL;
-    infoPtr->clrBk = GetSysColor (COLOR_BTNFACE);
+    infoPtr->clrBk = GetSysColor(COLOR_BTNFACE);
     infoPtr->nBorder = 0;
-    infoPtr->nButtonSize = 0;
+    infoPtr->nButtonSize = 12;
     infoPtr->nPos = 0;
+    infoPtr->nWidth = 0;
+    infoPtr->nHeight = 0;
+    infoPtr->bForward = FALSE;
+    infoPtr->TLbtnState = PGF_INVISIBLE;
+    infoPtr->BRbtnState = PGF_INVISIBLE;
 
+    if (dwStyle & PGS_AUTOSCROLL)
+        FIXME("[%04x] Autoscroll style is not implemented yet.\n", hwnd);
+    if (dwStyle & PGS_DRAGNDROP)
+        FIXME("[%04x] Drag and Drop style is not implemented yet.\n", hwnd);
+    if ((dwStyle & PGS_HORZ) && (dwStyle & PGS_VERT))
+    {
+        ERR("[%04x] Cannot have both horizontal and vertical styles.\n", hwnd);
+        ERR("[%04x] Defaulting to vertical.\n", hwnd);
+        dwStyle &= ~PGS_HORZ;
+    }
+    else if (!(dwStyle & PGS_HORZ) && !(dwStyle & PGS_VERT))
+        dwStyle |= PGS_VERT; /* the default according to MSDN */
+
+    infoPtr->bHorizontal = dwStyle & PGS_HORZ;
+
+    TRACE("[%04x] orientation = %s\n", hwnd,
+                  infoPtr->bHorizontal ? "PGS_HORZ" : "PGS_VERT");
 
     return 0;
 }
@@ -235,143 +677,436 @@
 PAGER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
-
-
-
-
     /* free pager info data */
     COMCTL32_Free (infoPtr);
     SetWindowLongA (hwnd, 0, 0);
     return 0;
 }
 
+static LRESULT
+PAGER_NCCalcSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);                                                                         
+    /*
+     * lParam points to a RECT struct.  On entry, the struct
+     * contains the proposed wnd rectangle for the window. 
+     * On exit, the struct should contain the screen
+     * coordinates of the corresponding window's client area.
+     */
+    LPRECT lpRect = (LPRECT)lParam;
+
+    if (infoPtr->bHorizontal)
+    {
+        if (infoPtr->TLbtnState) /* != PGF_INVISIBLE */
+            lpRect->left += infoPtr->nButtonSize;
+        if (infoPtr->BRbtnState) 
+            lpRect->right -= infoPtr->nButtonSize;
+    }
+    else
+    {
+        if (infoPtr->TLbtnState)
+            lpRect->top += infoPtr->nButtonSize;
+        if (infoPtr->BRbtnState)
+            lpRect->bottom -= infoPtr->nButtonSize;
+    }
+
+    TRACE("[%04x] client rect set to %dx%d at (%d,%d)\n", hwnd,
+                lpRect->right-lpRect->left,
+                lpRect->bottom-lpRect->top,
+                lpRect->left, lpRect->top);
+
+    return 0;
+}
+
+static LRESULT
+PAGER_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    PAGER_INFO* infoPtr = PAGER_GetInfoPtr(hwnd);
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+    RECT rcWindow, rcBottomRight, rcTopLeft;
+    HDC hdc;
+
+    if (dwStyle & WS_MINIMIZE)
+        return 0;
+
+    DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
+
+    if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
+        return 0;
+
+    GetWindowRect (hwnd, &rcWindow);
+    OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
+
+    rcTopLeft = rcBottomRight = rcWindow;
+    if (infoPtr->bHorizontal)
+    {
+        rcTopLeft.right = rcTopLeft.left + infoPtr->nButtonSize;
+        rcBottomRight.left = rcBottomRight.right - infoPtr->nButtonSize;
+    }
+    else
+    {
+        rcTopLeft.bottom = rcTopLeft.top + infoPtr->nButtonSize;
+        rcBottomRight.top = rcBottomRight.bottom - infoPtr->nButtonSize;
+    }
+
+    PAGER_DrawButton(hdc, infoPtr->clrBk, rcTopLeft,
+                    infoPtr->bHorizontal, TRUE, infoPtr->TLbtnState);
+    PAGER_DrawButton(hdc, infoPtr->clrBk, rcBottomRight,
+                    infoPtr->bHorizontal, FALSE, infoPtr->BRbtnState); 
+
+    ReleaseDC( hwnd, hdc );
+    return 0;
+}
+
+static INT 
+PAGER_HitTest (HWND hwnd, LPPOINT pt)
+{
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    RECT clientRect;
+
+    GetClientRect (hwnd, &clientRect);
+
+    if (PtInRect(&clientRect, *pt))
+    {
+       /* TRACE("HTCLIENT\n"); */
+        return HTCLIENT;
+    }
+
+    if (infoPtr->TLbtnState && infoPtr->TLbtnState != PGF_GRAYED)
+    {
+        if (infoPtr->bHorizontal)
+        {
+            if (pt->x < clientRect.left)
+            {
+                /* TRACE("HTLEFT\n"); */
+                return HTLEFT;
+            }
+        }
+        else
+        {
+            if (pt->y < clientRect.top)
+            {
+                /* TRACE("HTTOP\n"); */
+                return HTTOP;
+            }
+        }
+    }
+
+    if (infoPtr->BRbtnState && infoPtr->BRbtnState != PGF_GRAYED)
+    {
+        if (infoPtr->bHorizontal)
+        {
+            if (pt->x > clientRect.right)
+            {
+                /* TRACE("HTRIGHT\n"); */
+                return HTRIGHT;
+            }
+        }
+        else
+        {
+            if (pt->y > clientRect.bottom)
+            {
+               /* TRACE("HTBOTTOM\n"); */
+                return HTBOTTOM;
+            }
+        }
+    }
+
+    /* TRACE("HTNOWHERE\n"); */
+    return HTNOWHERE;
+}
+
+static LRESULT
+PAGER_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    POINT pt = { SLOWORD(lParam), SHIWORD(lParam) };
+    ScreenToClient (hwnd, &pt);
+    return PAGER_HitTest(hwnd, &pt);
+}
+
+static LRESULT
+PAGER_SetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
+{
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    BOOL notCaptured = FALSE;
+
+    switch(LOWORD(lParam))
+    {
+        case HTLEFT:
+        case HTTOP:
+            if ((notCaptured = infoPtr->TLbtnState != PGF_HOT))
+                infoPtr->TLbtnState = PGF_HOT;
+            break;
+        case HTRIGHT:
+        case HTBOTTOM:
+            if ((notCaptured = infoPtr->BRbtnState != PGF_HOT))
+               infoPtr->BRbtnState = PGF_HOT;
+            break;
+        default:
+            return FALSE;
+    }
+
+    if (notCaptured)
+    {
+        TRACKMOUSEEVENT trackinfo;
+
+        TRACE("[%04x] SetCapture\n", hwnd);
+        SetCapture(hwnd);
+
+        trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
+        trackinfo.dwFlags = TME_QUERY;
+        trackinfo.hwndTrack = hwnd;
+        trackinfo.dwHoverTime = HOVER_DEFAULT;
+
+        /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
+        _TrackMouseEvent(&trackinfo);
+
+        /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
+        if(!(trackinfo.dwFlags & TME_LEAVE)) {
+            trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
+ 
+           /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
+           /* and can properly deactivate the hot button */
+           _TrackMouseEvent(&trackinfo);
+        }
+
+        SendMessageA(hwnd, WM_NCPAINT, 0, 0); 
+    }
+
+    return TRUE;
+}
+
+static LRESULT
+PAGER_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+
+    TRACE("[%04x] ReleaseCapture\n", hwnd);
+    ReleaseCapture();
+
+    /* Notify parent of released mouse capture */
+    if (infoPtr->hwndChild)
+    {
+        NMHDR nmhdr;
+        ZeroMemory (&nmhdr, sizeof (NMHDR));
+        nmhdr.hwndFrom = hwnd;
+        nmhdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
+        nmhdr.code = NM_RELEASEDCAPTURE;
+        SendMessageA (GetParent (infoPtr->hwndChild), WM_NOTIFY,
+                        (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
+    }
+
+    /* make HOT btns NORMAL and hide gray btns */
+    PAGER_UpdateBtns(hwnd, infoPtr, -1, TRUE);
+
+    return TRUE;
+}
+
+static LRESULT
+PAGER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    BOOL repaintBtns = FALSE;
+    POINT pt = { SLOWORD(lParam), SHIWORD(lParam) };
+    INT hit;
+
+    TRACE("[%04x]\n", hwnd);
+	
+    if (infoPtr->nDelta <= 0)
+        return FALSE;
+
+    hit = PAGER_HitTest(hwnd, &pt);
+
+    /* put btn in DEPRESSED state */
+    if (hit == HTLEFT || hit == HTTOP)
+    {
+        repaintBtns = infoPtr->TLbtnState != PGF_DEPRESSED;
+        infoPtr->TLbtnState = PGF_DEPRESSED;
+    }
+    else if (hit == HTRIGHT || hit == HTBOTTOM)
+    {
+        repaintBtns = infoPtr->BRbtnState != PGF_DEPRESSED;
+        infoPtr->BRbtnState = PGF_DEPRESSED;
+    }
+
+    if (repaintBtns)
+        SendMessageA(hwnd, WM_NCPAINT, 0, 0); 
+
+    switch(hit)
+    {
+    case HTLEFT:
+        TRACE("[%04x] PGF_SCROLLLEFT\n", hwnd);
+        PAGER_Scroll(hwnd, PGF_SCROLLLEFT);
+        break;
+    case HTTOP:
+        TRACE("[%04x] PGF_SCROLLUP\n", hwnd);
+        PAGER_Scroll(hwnd, PGF_SCROLLUP);
+        break;
+    case HTRIGHT:
+        TRACE("[%04x] PGF_SCROLLRIGHT\n", hwnd);
+        PAGER_Scroll(hwnd, PGF_SCROLLRIGHT);
+        break;
+    case HTBOTTOM:
+        TRACE("[%04x] PGF_SCROLLDOWN\n", hwnd);
+        PAGER_Scroll(hwnd, PGF_SCROLLDOWN);
+        break;
+    default:
+        break;
+    }
+
+    return TRUE;
+}
+
+static LRESULT
+PAGER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    TRACE("[%04x]\n", hwnd);
+
+    /* make PRESSED btns NORMAL but don't hide gray btns */
+    PAGER_UpdateBtns(hwnd, infoPtr, -1, FALSE);
+
+    return 0;
+}
 
 static LRESULT
 PAGER_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
-    HBRUSH hBrush = CreateSolidBrush (infoPtr->clrBk);
+    HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
     RECT rect;
-
     GetClientRect (hwnd, &rect);
+
     FillRect ((HDC)wParam, &rect, hBrush);
     DeleteObject (hBrush);
-
-/*    return TRUE; */
-    return FALSE;
-}
-
-
-static LRESULT
-PAGER_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    /* PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); */
-
-    TRACE("stub!\n");
-
-    return 0;
-}
-
-
-/* << PAGER_Paint >> */
-
-
-static LRESULT
-PAGER_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
-    RECT rect;
-
-    GetClientRect (hwnd, &rect);
-    if (infoPtr->hwndChild) {
-	SetWindowPos (infoPtr->hwndChild, HWND_TOP, rect.left, rect.top,
-			rect.right - rect.left, rect.bottom - rect.top,
-			SWP_SHOWWINDOW);
-/*	MoveWindow (infoPtr->hwndChild, 1, 1, rect.right - 2, rect.bottom-2, TRUE); */
-/*	UpdateWindow (infoPtr->hwndChild); */
-
-    }
-/*    FillRect ((HDC)wParam, &rect, hBrush); */
-/*    DeleteObject (hBrush); */
     return TRUE;
 }
 
 
+static LRESULT
+PAGER_Size (HWND hwnd)
+{
+    /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
+
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+    RECT wndRect;
+    GetWindowRect(hwnd, &wndRect);
+
+    infoPtr->nDelta = infoPtr->bHorizontal ?
+                      wndRect.right - wndRect.left :
+                      wndRect.bottom - wndRect.top;
+    infoPtr->nDelta -= 2*infoPtr->nButtonSize;
+	
+    TRACE("[%04x] nDelta=%d\n", hwnd, infoPtr->nDelta);
+
+    PAGER_PositionChildWnd(hwnd, infoPtr);
+	
+    return TRUE;
+}
+
 
 static LRESULT WINAPI
 PAGER_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-    TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam);
-    if (!PAGER_GetInfoPtr (hwnd) && (uMsg != WM_CREATE))
-	    return DefWindowProcA (hwnd, uMsg, wParam, lParam);
+    PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
+
+    if (!infoPtr && (uMsg != WM_CREATE))
+    return DefWindowProcA (hwnd, uMsg, wParam, lParam);
+
     switch (uMsg)
     {
-	case PGM_FORWARDMOUSE:
-	    return PAGER_ForwardMouse (hwnd, wParam);
+        case PGM_FORWARDMOUSE:
+            return PAGER_ForwardMouse (hwnd, wParam);
 
-	case PGM_GETBKCOLOR:
-	    return PAGER_GetBkColor (hwnd, wParam, lParam);
+        case PGM_GETBKCOLOR:
+            return PAGER_GetBkColor(hwnd);
 
-	case PGM_GETBORDER:
-	    return PAGER_GetBorder (hwnd, wParam, lParam);
+        case PGM_GETBORDER:
+            return PAGER_GetBorder(hwnd);
 
-	case PGM_GETBUTTONSIZE:
-	    return PAGER_GetButtonSize (hwnd, wParam, lParam);
+        case PGM_GETBUTTONSIZE:
+            return PAGER_GetButtonSize(hwnd);
 
-	case PGM_GETBUTTONSTATE:
-	    return PAGER_GetButtonState (hwnd, wParam, lParam);
+        case PGM_GETPOS:
+            return PAGER_GetPos(hwnd);
 
-/*	case PGM_GETDROPTARGET: */
+        case PGM_GETBUTTONSTATE:
+            return PAGER_GetButtonState (hwnd, wParam, lParam);
 
-	case PGM_GETPOS:
-	    return PAGER_SetPos (hwnd, wParam, lParam);
+/*      case PGM_GETDROPTARGET: */
 
-	case PGM_RECALCSIZE:
-	    return PAGER_RecalcSize (hwnd, wParam, lParam);
+        case PGM_RECALCSIZE:
+            return PAGER_RecalcSize(hwnd);
+    
+        case PGM_SETBKCOLOR:
+            return PAGER_SetBkColor (hwnd, wParam, lParam);
 
-	case PGM_SETBKCOLOR:
-	    return PAGER_SetBkColor (hwnd, wParam, lParam);
+        case PGM_SETBORDER:
+            return PAGER_SetBorder (hwnd, wParam, lParam);
 
-	case PGM_SETBORDER:
-	    return PAGER_SetBorder (hwnd, wParam, lParam);
+        case PGM_SETBUTTONSIZE:
+            return PAGER_SetButtonSize (hwnd, wParam, lParam);
 
-	case PGM_SETBUTTONSIZE:
-	    return PAGER_SetButtonSize (hwnd, wParam, lParam);
+        case PGM_SETCHILD:
+            return PAGER_SetChild (hwnd, wParam, lParam);
 
-	case PGM_SETCHILD:
-	    return PAGER_SetChild (hwnd, wParam, lParam);
+        case PGM_SETPOS:
+            return PAGER_SetPos(hwnd, (INT)lParam, FALSE);
 
-	case PGM_SETPOS:
-	    return PAGER_SetPos (hwnd, wParam, lParam);
+        case WM_CREATE:
+            return PAGER_Create (hwnd, wParam, lParam);
 
-	case WM_CREATE:
-	    return PAGER_Create (hwnd, wParam, lParam);
+        case WM_DESTROY:
+            return PAGER_Destroy (hwnd, wParam, lParam);
 
-	case WM_DESTROY:
-	    return PAGER_Destroy (hwnd, wParam, lParam);
+        case WM_SIZE:
+            return PAGER_Size (hwnd);
 
-	case WM_ERASEBKGND:
-	    return PAGER_EraseBackground (hwnd, wParam, lParam);
+        case WM_NCPAINT:
+            return PAGER_NCPaint (hwnd, wParam, lParam);
 
-	case WM_MOUSEMOVE:
-	    return PAGER_MouseMove (hwnd, wParam, lParam);
+        case WM_NCCALCSIZE:
+            return PAGER_NCCalcSize (hwnd, wParam, lParam);
 
-	case WM_NOTIFY:
-	case WM_COMMAND:
-	    return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
+        case WM_NCHITTEST:
+            return PAGER_NCHitTest (hwnd, wParam, lParam);
 
-/*	case WM_PAINT: */
-/*	    return PAGER_Paint (hwnd, wParam); */
+        case WM_SETCURSOR:
+        {
+            if (hwnd == (HWND)wParam)
+                return PAGER_SetCursor(hwnd, wParam, lParam);
+            else /* its for the child */
+                return 0;
+        }
 
-	case WM_SIZE:
-	    return PAGER_Size (hwnd, wParam, lParam);
+        case WM_MOUSEMOVE:
+            if (infoPtr->bForward && infoPtr->hwndChild)
+                PostMessageA(infoPtr->hwndChild, WM_MOUSEMOVE, wParam, lParam);
+            return TRUE;			
 
-	default:
-	    if (uMsg >= WM_USER)
-		ERR("unknown msg %04x wp=%08x lp=%08lx\n",
-		     uMsg, wParam, lParam);
-	    return DefWindowProcA (hwnd, uMsg, wParam, lParam);
+        case WM_MOUSELEAVE:
+            return PAGER_MouseLeave (hwnd, wParam, lParam);	
+
+        case WM_LBUTTONDOWN:
+            return PAGER_LButtonDown (hwnd, wParam, lParam);
+
+        case WM_LBUTTONUP:
+            return PAGER_LButtonUp (hwnd, wParam, lParam);
+
+        case WM_ERASEBKGND:
+            return PAGER_EraseBackground (hwnd, wParam, lParam);
+/*
+        case WM_PAINT:
+            return PAGER_Paint (hwnd, wParam); 
+*/
+        case WM_NOTIFY:
+        case WM_COMMAND:
+            return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
+
+        default:
+            return DefWindowProcA (hwnd, uMsg, wParam, lParam);
     }
+
     return 0;
 }