Implement dragging on gripper to expand and compress bands. Actual
moving bands to different rows will be later.

diff --git a/dlls/comctl32/rebar.c b/dlls/comctl32/rebar.c
index a6bc743..1a1cb16 100644
--- a/dlls/comctl32/rebar.c
+++ b/dlls/comctl32/rebar.c
@@ -1,5 +1,5 @@
 /*
- * Rebar control    rev 4a
+ * Rebar control    rev 5b
  *
  * Copyright 1998, 1999 Eric Kohl
  *
@@ -18,18 +18,18 @@
  *   - All notifications.
 
  * Changes Guy Albertelli <galberte@neo.lrun.com>
- *  1. Correct use of fStyle for fMask
- *  2. Rewrite to support putting bands in rows, also supports GETROWCOUNT
- *     and GETROWHEIGHT.
- *  3. Make fMask in internal band info indicate what is valid rather than -1.
- *  4. Correct output of GETBANDINFO to match MS for iImage, lpText
- *  5. Handle RBN_CHILDSIZE notification (not really working)
- *  6. Draw separators between bands and fix size of grippers.
- *  7. Draw separators between rows.
- *  8. Support RBBS_BREAK if specified by user.
- *  9. Support background color for band and draw the background.
- * 10. Eliminated duplicate code in SetBandInfo[AW] and InsertBand[AW]. 
- * 11. Support text color and propagate colors from Bar to Band
+ *  rev 2,3,4
+ *   - Implement initial version of row grouping, row separators,
+ *     text and background colors. Support additional messages. 
+ *     Support RBBS_BREAK. Implement ERASEBKGND and improve painting.
+ *  rev 5
+ *  1. Support dragging by the Gripper for only left and right drags 
+ *     within a row. (5a)
+ *  2. Implement WM_LBUTTONDOWN, WM_LBUTTONUP, and WM_MOUSEMOVE.
+ *  3. Support RBS_BANDBORDERS. 
+ *  4. Total rewrite of MouseMove code to handle multiple bands in row. (5b)
+ *  5. Fix drawing bugs.
+ *
  *    Still to do:
  *  1. default row height should be the max height of all visible bands
  *  2. Following still not handled: RBBS_FIXEDBMP, RBBS_CHILDEDGE,
@@ -40,8 +40,10 @@
 
 #include <string.h>
 
+#include "class.h"
 #include "winbase.h"
 #include "wingdi.h"
+#include "win.h"
 #include "wine/unicode.h"
 #include "wine/winestring.h"
 #include "commctrl.h"
@@ -74,6 +76,7 @@
     UINT    lcy;            /* minimum cy for band */
     UINT    hcy;            /* maximum cy for band */
 
+    SIZE    offChild;       /* x,y offset if child is not FIXEDSIZE */
     UINT    uMinHeight;
     INT     iRow;           /* row this band assigned to */
     UINT    fDraw;          /* drawing flags */
@@ -87,6 +90,14 @@
     HWND    hwndPrevParent;
 } REBAR_BAND;
 
+/* fDraw flags */
+#define DRAW_GRIPPER    1
+#define DRAW_IMAGE      2
+#define DRAW_TEXT       4
+#define DRAW_CHILD      8
+#define DRAW_SEP        16
+
+
 typedef struct
 {
     COLORREF   clrBk;       /* background color */
@@ -100,24 +111,25 @@
     SIZE     imageSize;   /* image size (image list) */
 
     SIZE     calcSize;    /* calculated rebar size */
-    BOOL     bAutoResize; /* auto resize deadlock flag */
     BOOL     bUnicode;    /* Unicode flag */
+    UINT     fStatus;     /* Status flags (see below)  */ 
     HCURSOR  hcurArrow;   /* handle to the arrow cursor */
     HCURSOR  hcurHorz;    /* handle to the EW cursor */
     HCURSOR  hcurVert;    /* handle to the NS cursor */
     HCURSOR  hcurDrag;    /* handle to the drag cursor */
     INT      iVersion;    /* version number */
+    POINTS   dragStart;   /* x,y of button down */
+    POINTS   dragNow;     /* x,y of this MouseMove */
+    INT      ihitBand;    /* band number of band whose gripper was grabbed */
+    INT      ihitoffset;  /* offset of hotspot from gripper.left */
 
     REBAR_BAND *bands;      /* pointer to the array of rebar bands */
 } REBAR_INFO;
 
+/* fStatus flags */
+#define BEGIN_DRAG_ISSUED   1
+#define AUTO_RESIZE         2
 
-/* fDraw flags */
-#define DRAW_GRIPPER    1
-#define DRAW_IMAGE      2
-#define DRAW_TEXT       4
-#define DRAW_CHILD      8
-#define DRAW_SEP        16
 
 #define GRIPPER_WIDTH   8
 #define GRIPPER_HEIGHT  16
@@ -129,6 +141,13 @@
 
 #define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongA (hwnd, 0))
 
+
+/* "constant values" retrieved when DLL was initialized    */
+/* FIXME we do this when the classes are registered.       */
+static UINT mindragx = 0;
+static UINT mindragy = 0;
+
+
 static VOID
 REBAR_DumpBandInfo( LPREBARBANDINFOA pB)
 {
@@ -153,6 +172,10 @@
       TRACE("hwnd=%04x: color=%08lx/%08lx, bands=%u, rows=%u, cSize=%ld,%ld\n", 
         hwnd, iP->clrText, iP->clrBk, iP->uNumBands, iP->uNumRows,
         iP->calcSize.cx, iP->calcSize.cy);
+      TRACE("hwnd=%04x: flags=%08x, dragStart=%d,%d, dragNow=%d,%d, ihitBand=%d\n",
+	    hwnd, iP->fStatus, iP->dragStart.x, iP->dragStart.y,
+	    iP->dragNow.x, iP->dragNow.y,
+	    iP->ihitBand);
       for (i = 0; i < iP->uNumBands; i++) {
 	pB = &iP->bands[i];
 	TRACE("band # %u: ID=%u, mask=0x%08x, style=0x%08x, child=%04x, row=%u\n",
@@ -160,8 +183,8 @@
 	TRACE("band # %u: xMin=%u, yMin=%u, cx=%u, yChild=%u, yMax=%u, yIntgl=%u, uMinH=%u,\n",
 	  i, pB->cxMinChild, pB->cyMinChild, pB->cx,
           pB->cyChild, pB->cyMaxChild, pB->cyIntegral, pB->uMinHeight);
-	TRACE("band # %u: header=%u, lcx=%u, hcx=%u, lcy=%u, hcy=%u\n",
-	  i, pB->cxHeader, pB->lcx, pB->hcx, pB->lcy, pB->hcy);
+	TRACE("band # %u: header=%u, lcx=%u, hcx=%u, lcy=%u, hcy=%u, offChild=%ld,%ld\n",
+	  i, pB->cxHeader, pB->lcx, pB->hcx, pB->lcy, pB->hcy, pB->offChild.cx, pB->offChild.cy);
 	TRACE("band # %u: fDraw=%08x, Band=(%d,%d)-(%d,%d), Grip=(%d,%d)-(%d,%d)\n",
 	  i, pB->fDraw,
 	  pB->rcBand.left, pB->rcBand.top, pB->rcBand.right, pB->rcBand.bottom,
@@ -176,6 +199,22 @@
     }
 }
 
+static void
+REBAR_Notify (HWND hwnd, NMHDR *nmhdr, UINT code)
+{
+    HWND parent, owner;
+
+    parent = GetParent (hwnd);
+    owner = GetWindow (hwnd, GW_OWNER);
+    if (owner) parent = owner;
+    nmhdr->idFrom = GetDlgCtrlID (hwnd);
+    nmhdr->hwndFrom = hwnd;
+    nmhdr->code = code;
+
+    SendMessageA (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom,
+		      (LPARAM)nmhdr);
+}
+
 static VOID
 REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand, DWORD dwStyle)
 {
@@ -194,17 +233,6 @@
 	DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_LEFT | BF_TOP | BF_MIDDLE);
     }
 
-    /* draw background */
-    if (lpBand->clrBack != CLR_NONE) {
-        HBRUSH brh = CreateSolidBrush (lpBand->clrBack);
-	TRACE("backround color=0x%06lx, rect (%d,%d)-(%d,%d)\n",
-	      lpBand->clrBack,
-	      lpBand->rcBand.left,lpBand->rcBand.top,
-	      lpBand->rcBand.right,lpBand->rcBand.bottom);
-        FillRect (hdc, &lpBand->rcBand, brh);
-	DeleteObject (brh);
-    }
-
     /* draw gripper */
     if (lpBand->fDraw & DRAW_GRIPPER)
         DrawEdge (hdc, &lpBand->rcGripper, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
@@ -260,18 +288,21 @@
 
 	/* if a new row then draw a separator */
 	if (oldrow != lpBand->iRow) {
-	  if (dwStyle & CCS_VERT) {
-	    SetRect (&rcRowSep, lpBand->rcBand.left-2, 0,
-		     lpBand->rcBand.left-1, infoPtr->calcSize.cy);
-	  }
-	  else {
-	    SetRect (&rcRowSep, 0, lpBand->rcBand.top-2,
-		     infoPtr->calcSize.cx, lpBand->rcBand.top-1);
-	  } 
-	  TRACE ("drawing row sep (%d,%d)-(%d,%d)\n",
-		 rcRowSep.left, rcRowSep.top, rcRowSep.right, rcRowSep.bottom);
-	  DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_TOP|BF_LEFT);
-	  oldrow = lpBand->iRow;
+	    if (dwStyle & RBS_BANDBORDERS) {
+	        if (dwStyle & CCS_VERT) {
+	            SetRect (&rcRowSep, lpBand->rcBand.left-2, 0,
+			     lpBand->rcBand.left-1, infoPtr->calcSize.cy);
+		}
+		else {
+		    SetRect (&rcRowSep, 0, lpBand->rcBand.top-2,
+			     infoPtr->calcSize.cx, lpBand->rcBand.top-1);
+		}
+		TRACE ("drawing row sep (%d,%d)-(%d,%d)\n",
+		       rcRowSep.left, rcRowSep.top,
+		       rcRowSep.right, rcRowSep.bottom);
+		DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_TOP|BF_LEFT);
+		oldrow = lpBand->iRow;
+	    }
 	}
 
 	/* now draw the band */
@@ -419,21 +450,15 @@
 
       /* set initial child window rectangle if there is a child */
       if (lpBand->fMask & RBBIM_CHILD) {
-	if (lpBand->fStyle & RBBS_FIXEDSIZE) {
-	  xoff = 0;
-	  yoff = 0;
-        }
-        else {
-	  xoff = 4;
-	  yoff = 2;
-        }
+	xoff = lpBand->offChild.cx;
+	yoff = lpBand->offChild.cy;
         SetRect (&lpBand->rcChild,
 	         lpBand->rcBand.left+lpBand->cxHeader+xoff, lpBand->rcBand.top+yoff,
 	         lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
       }
       else {
         SetRect (&lpBand->rcChild,
-	         lpBand->rcBand.right, lpBand->rcBand.top,
+	         lpBand->rcCapText.right, lpBand->rcBand.top,
 	         lpBand->rcBand.right, lpBand->rcBand.bottom);
       }
 
@@ -571,14 +596,8 @@
 
       /* set initial child window rectangle if there is a child */
       if (lpBand->fMask & RBBIM_CHILD) {
-	if (lpBand->fStyle & RBBS_FIXEDSIZE) {
-	  xoff = 0;
-	  yoff = 0;
-        }
-        else {
-	  xoff = 2;
-	  yoff = 4;
-        }
+	yoff = lpBand->offChild.cx;
+	xoff = lpBand->offChild.cy;
         SetRect (&lpBand->rcChild,
 	         lpBand->rcBand.left+xoff, 
 		 lpBand->rcBand.top+lpBand->cxHeader+yoff,
@@ -586,7 +605,7 @@
       }
       else {
         SetRect (&lpBand->rcChild,
-	         lpBand->rcBand.right, lpBand->rcBand.top,
+	         lpBand->rcBand.left, lpBand->rcCapText.bottom,
 	         lpBand->rcBand.right, lpBand->rcBand.top);
       }
 
@@ -676,7 +695,6 @@
 	cxsep = (x==0) ? 0 : SEP_WIDTH;  /* separator from previous band */
 	cx = lpBand->cxHeader +   /* Header: includes gripper, text, image */
              lpBand->hcx;         /* coumpted size of child */
-
 	if (dwStyle & CCS_VERT)
 	  dobreak = (y + cx + cxsep > adjcy);
         else
@@ -684,8 +702,10 @@
 	/* This is the check for whether we need to start a new row */
 	if ( ( (lpBand->fStyle & RBBS_BREAK) && (i != 0) ) ||
 	     ( ((dwStyle & CCS_VERT) ? (y != 0) : (x != 0)) && dobreak)) {
-	  TRACE("Spliting to new row %d on band %u\n", row+1, i);
+	  INT borders;
 
+	  TRACE("Spliting to new row %d on band %u\n", row+1, i);
+	  borders = (dwStyle & RBS_BANDBORDERS) ? 2 : 0;
 	  if (dwStyle & CCS_VERT) {
 	    /* first adjust all bands in previous current row to */
 	    /* redistribute extra x pixels                       */
@@ -695,7 +715,7 @@
 	    REBAR_CalcVertBand (hwnd, infoPtr, rowstartband, i,
 				notify, dwStyle);
 	    y = 0;
-	    x += (mcy + 2);
+	    x += (mcy + borders);
 	  }
 	  else {
 	    /* first adjust all bands in previous current row to */
@@ -706,7 +726,7 @@
 	    REBAR_CalcHorzBand (hwnd, infoPtr, rowstartband, i,
 				notify, dwStyle);
 	    x = 0;
-	    y += (mcy + 2);
+	    y += (mcy + borders);
 	  }
 
 	  /* FIXME: if not RBS_VARHEIGHT then find max */
@@ -802,6 +822,8 @@
 
 static VOID
 REBAR_ForceResize (HWND hwnd)
+     /* Function: This changes the size of the REBAR window to that */
+     /*  calculated by REBAR_Layout.                                */
 {
     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
     RECT rc;
@@ -809,7 +831,7 @@
     TRACE( " to [%ld x %ld]!\n",
 	   infoPtr->calcSize.cx, infoPtr->calcSize.cy);
 
-    infoPtr->bAutoResize = TRUE;
+    infoPtr->fStatus |= AUTO_RESIZE;
 
     rc.left = 0;
     rc.top = 0;
@@ -975,7 +997,13 @@
 
 
     /* Now compute minimum size of child window */
+    lpBand->offChild.cx = 0;
+    lpBand->offChild.cy = 0;
     if (lpBand->fMask & RBBIM_CHILDSIZE) {
+	if (!(lpBand->fStyle & RBBS_FIXEDSIZE)) {
+	    lpBand->offChild.cx = 4;
+	    lpBand->offChild.cy = 2;
+        }
         lpBand->lcx = lpBand->cxMinChild;
         lpBand->lcy = lpBand->cyMinChild;
         lpBand->hcy = lpBand->lcy;
@@ -1057,6 +1085,40 @@
     }
 }
 
+static LRESULT
+REBAR_InternalEraseBkGnd (HWND hwnd, WPARAM wParam, LPARAM lParam, RECT *clip)
+     /* Function:  This erases the background rectangle with the  */
+     /*  default brush, then with any band that has a different   */
+     /*  background color.                                        */
+{
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    RECT eraserect;
+    REBAR_BAND *lpBand;
+    INT i;
+
+    if (wndPtr->class->hbrBackground)
+        FillRect( (HDC) wParam, clip, wndPtr->class->hbrBackground);
+    WIN_ReleaseWndPtr(wndPtr);
+
+    for(i=0; i<infoPtr->uNumBands; i++) {
+        lpBand = &infoPtr->bands[i];
+	if (lpBand->clrBack != CLR_NONE) {
+	  if (IntersectRect (&eraserect, clip, &lpBand->rcBand)) {
+	    /* draw background */
+	    HBRUSH brh = CreateSolidBrush (lpBand->clrBack);
+	    TRACE("backround color=0x%06lx, rect (%d,%d)-(%d,%d)\n",
+		  lpBand->clrBack,
+		  lpBand->rcBand.left,lpBand->rcBand.top,
+		  lpBand->rcBand.right,lpBand->rcBand.bottom);
+	    FillRect ( (HDC)wParam, &eraserect, brh);
+	    DeleteObject (brh);
+	  }
+	}
+    }
+    return TRUE;
+}
+
 static void
 REBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pBand)
 {
@@ -1079,6 +1141,7 @@
 	}
 	else {
 	    /* somewhere inside */
+	    infoPtr->ihitBand = -1;
 	    for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
 		lpBand = &infoPtr->bands[iCount];
 		if (PtInRect (&lpBand->rcBand, *lpPt)) {
@@ -1086,6 +1149,7 @@
 			*pBand = iCount;
 		    if (PtInRect (&lpBand->rcGripper, *lpPt)) {
 			*pFlags = RBHT_GRABBER;
+			infoPtr->ihitBand = iCount;
 			TRACE("ON GRABBER %d\n", iCount);
 			return;
 		    }
@@ -1132,6 +1196,257 @@
     return;
 }
 
+#define READJ(b,i) {b->rcChild.right += (i);b->rcBand.right += (i);}
+#define LEADJ(b,i) {b->rcBand.left += (i); \
+                    b->rcGripper.left += (i); \
+                    b->rcGripper.right += (i); \
+                    b->rcCapImage.left += (i); \
+                    b->rcCapImage.right += (i); \
+                    b->rcCapText.left += (i); \
+                    b->rcCapText.right += (i); \
+                    b->rcChild.left += (i);}
+
+
+static INT
+REBAR_Shrink (REBAR_BAND *band, INT movement, INT i)
+     /* Function:  This attempts to shrink the given band by the  */
+     /*  the amount in "movement". A shrink to the left is indi-  */
+     /*  cated by "movement" being negative. "i" is merely the    */
+     /*  band index for trace messages.                           */
+{
+    INT Leadjust, Readjust, avail, ret;
+
+    /* Note: a left drag is indicated by "movement" being negative.  */
+    /*       Similarly, a right drag is indicated by "movement"      */
+    /*       being positive. "movement" should never be 0, but if    */
+    /*       it is then the band does not move.                      */
+
+    avail = band->rcBand.right - band->rcBand.left -
+            band->cxHeader - band->offChild.cx;
+
+    /* now compute the Left End adjustment factor and Right End */
+    /* adjustment factor. They may be different if shrinking.   */
+    if (avail <= 0) {
+        /* if this band is not shrinkable, then just move it */
+        Leadjust = Readjust = movement;
+	ret = movement;
+    }
+    else {
+        if (movement < 0) {
+	    /* Drag to left */
+	    if (avail <= abs(movement)) {
+	        Readjust = movement;
+		Leadjust = movement + avail;
+		ret = Leadjust;
+	    }
+	    else {
+	        Readjust = movement;
+		Leadjust = 0;
+		ret = 0;
+	    }
+	}
+	else {
+	    /* Drag to right */
+	    if (avail <= abs(movement)) {
+	        Leadjust = movement;
+		Readjust = movement - avail;
+		ret = Readjust;
+	    }
+	    else {
+	        Leadjust = movement;
+		Readjust = 0;
+		ret = 0;
+	    }
+	}
+    }
+
+    /* Reasonability Check */
+    if (band->rcBand.left+Leadjust < 0) {
+        ERR("adjustment will fail, band %d: left=%d, right=%d, move=%d, rtn=%d\n",
+	    i, Leadjust, Readjust, movement, ret);
+    }
+
+    LEADJ(band, Leadjust);
+    READJ(band, Readjust);
+
+    TRACE("band %d:  left=%d, right=%d, move=%d, rtn=%d, rcBand=(%d,%d)-(%d,%d)\n",
+	  i, Leadjust, Readjust, movement, ret,
+	  band->rcBand.left, band->rcBand.top,
+	  band->rcBand.right, band->rcBand.bottom);
+    return ret;
+}
+
+
+static void
+REBAR_HandleLRDrag (HWND hwnd, REBAR_INFO *infoPtr, POINTS *ptsmove)
+     /* Function:  This will implement the functionality of a     */
+     /*  Gripper drag within a row. It will not implement "out-   */
+     /*  of-row" drags. (They are detected and handled in         */
+     /*  REBAR_MouseMove.)                                        */
+     /*  **** FIXME Vertical rebars not implemented.        ****  */
+     /*  **** FIXME Switching order of bands in a row not   ****  */
+     /*  ****       yet implemented.                        ****  */
+{
+    REBAR_BAND *hitBand, *band, *prevband, *mindBand, *maxdBand;
+    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
+    HDWP deferpos;
+    NMREBARCHILDSIZE cs;
+    NMREBAR startdrag;
+    RECT newrect;
+    INT imindBand = -1, imaxdBand, ihitBand, i, movement, tempx;
+    INT RHeaderSum = 0, LHeaderSum = 0;
+    INT compress;
+
+    /* *** FIXME drag does not work for vertical           *** */
+    if (dwStyle & CCS_VERT) {
+        FIXME("Drag not yet implemented for vertical rebars\n");
+	return;
+    }
+
+    /* on first significant mouse movement, issue notify */
+
+    if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
+        startdrag.dwMask = 0;
+	startdrag.uBand = -1;
+	REBAR_Notify(hwnd, (NMHDR *) &startdrag, RBN_BEGINDRAG);
+	infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
+    }
+
+    ihitBand = infoPtr->ihitBand;
+    hitBand = &infoPtr->bands[ihitBand];
+    imaxdBand = ihitBand; /* to suppress warning message */
+
+    /* find all the bands in the row of the one whose Gripper was seized */
+    for (i=0; i<infoPtr->uNumBands; i++) {
+        band = &infoPtr->bands[i];
+	if (band->iRow == hitBand->iRow) {
+	    imaxdBand = i;
+	    if (imindBand == -1) imindBand = i;
+	    /* minimum size of each band is size of header plus            */
+	    /* size of minimum child plus offset of child from header plus */
+	    /* a one to separate each band.                                */
+	    if (i < ihitBand)
+	        LHeaderSum += (band->cxHeader + band->offChild.cx +
+			       band->lcx + 1);
+	    else 
+	        RHeaderSum += (band->cxHeader + band->offChild.cx +
+			       band->lcx + 1);
+
+	}
+    }
+    if (RHeaderSum) RHeaderSum--; /* no separator afterlast band */
+
+    mindBand = &infoPtr->bands[imindBand];
+    maxdBand = &infoPtr->bands[imaxdBand];
+
+    if (imindBand == imaxdBand) return; /* nothing to drag agains */
+    if (imindBand == ihitBand) return; /* first band in row, cant drag */
+
+    /* limit movement to inside adjustable bands - Left */
+    if (ptsmove->x < mindBand->rcBand.left)
+        return; /* should swap bands */
+    /* limit movement to inside adjustable bands - Right */
+    if (ptsmove->x > maxdBand->rcBand.right)
+        return; /* should swap bands */
+
+    movement = ptsmove->x - (hitBand->rcGripper.left - infoPtr->ihitoffset);
+    infoPtr->dragNow = *ptsmove;
+
+    TRACE("before: movement=%d (%d,%d), imindBand=%d, ihitBand=%d, imaxdBand=%d, LSum=%d, RSum=%d\n",
+	  movement, ptsmove->x, ptsmove->y, imindBand, ihitBand,
+	  imaxdBand, LHeaderSum, RHeaderSum);
+    REBAR_DumpBand (hwnd);
+
+    if (movement < 0) {  
+
+        /* ***  Drag left *** */
+        compress = hitBand->rcBand.left-1 - mindBand->rcBand.left -
+	           LHeaderSum;
+	if (compress < abs(movement)) {
+	    TRACE("limiting left drag, was %d changed to %d\n",
+		  movement, -compress);
+	    movement = -compress;
+	}
+        for (i=ihitBand; i>=imindBand; i--) {
+	    band = &infoPtr->bands[i];
+	    if (i == ihitBand) {
+		prevband = &infoPtr->bands[i-1];
+		if (band->rcBand.left - movement <= prevband->rcBand.right) {
+		    tempx = movement - (prevband->rcBand.right-band->rcBand.left+1);
+		    ERR("movement bad. BUG!! was %d, left=%d, right=%d, setting to %d\n",
+			movement, band->rcBand.left, prevband->rcBand.right, tempx);
+		    movement = tempx;
+		}
+		LEADJ(band, movement)
+	    }
+	    else 
+	        movement = REBAR_Shrink (band, movement, i);
+	}
+    }
+    else {
+
+        /* ***  Drag right *** */
+        compress = maxdBand->rcBand.right - hitBand->rcBand.left -
+	           RHeaderSum;
+	if (compress < abs(movement)) {
+	    TRACE("limiting right drag, was %d changed to %d\n",
+		  movement, compress);
+	    movement = compress;
+	}
+        for (i=ihitBand-1; i<=imaxdBand; i++) {
+	    band = &infoPtr->bands[i];
+	    if (i == ihitBand-1) {
+		READJ(band, movement)
+	    }
+	    else 
+	        movement = REBAR_Shrink (band, movement, i);
+	}
+    }
+
+    TRACE("bands after adjustment, see band # %d, %d\n",
+	  imindBand, imaxdBand);
+    REBAR_DumpBand (hwnd);
+
+    SetRect (&newrect, 
+	     mindBand->rcBand.left,
+	     min(mindBand->rcBand.top, maxdBand->rcBand.top),
+	     maxdBand->rcBand.right,
+	     max(mindBand->rcBand.bottom, maxdBand->rcBand.bottom));
+
+    if (!(deferpos = BeginDeferWindowPos (4))) {
+        ERR("BeginDeferWindowPos returned NULL\n");
+    }
+
+    for (i=imindBand; i<=imaxdBand; i++) {
+        band = &infoPtr->bands[i];
+	if ((band->fMask & RBBIM_CHILD) && band->hwndChild) {
+	    cs.uBand = i;
+	    cs.wID = band->wID;
+	    cs.rcChild = band->rcChild;
+	    cs.rcBand = band->rcBand;
+	    REBAR_Notify (hwnd, (NMHDR *) &cs, RBN_CHILDSIZE);
+	    deferpos = DeferWindowPos (deferpos, band->hwndChild, HWND_TOP,
+				       cs.rcChild.left, cs.rcChild.top,
+				       cs.rcChild.right - cs.rcChild.left,
+				       cs.rcChild.bottom - cs.rcChild.top,
+				       SWP_NOZORDER);
+	    if (!deferpos) {
+	        ERR("DeferWindowPos returned NULL\n");
+	    }
+	}
+    }
+
+    if (!EndDeferWindowPos (deferpos)) {
+        ERR("EndDeferWindowPos failed\n");
+    }
+
+    InvalidateRect (hwnd, &newrect, TRUE);
+    UpdateWindow (hwnd);
+
+}
+#undef READJ
+#undef LEADJ
+
 
 
 /* << REBAR_BeginDrag >> */
@@ -2058,8 +2373,9 @@
     infoPtr->iVersion = 0;
     infoPtr->clrBk = CLR_NONE;
     infoPtr->clrText = GetSysColor (COLOR_BTNTEXT);
+    infoPtr->ihitBand = -1;
+    infoPtr->fStatus = 0;
 
-    infoPtr->bAutoResize = FALSE;
     infoPtr->hcurArrow = LoadCursorA (0, IDC_ARROWA);
     infoPtr->hcurHorz  = LoadCursorA (0, IDC_SIZEWEA);
     infoPtr->hcurVert  = LoadCursorA (0, IDC_SIZENSA);
@@ -2107,17 +2423,11 @@
 	infoPtr->bands = NULL;
     }
 
-
-
-
     DeleteObject (infoPtr->hcurArrow);
     DeleteObject (infoPtr->hcurHorz);
     DeleteObject (infoPtr->hcurVert);
     DeleteObject (infoPtr->hcurDrag);
 
-
-
-
     /* free rebar info data */
     COMCTL32_Free (infoPtr);
     SetWindowLongA (hwnd, 0, 0);
@@ -2127,6 +2437,17 @@
 
 
 static LRESULT
+REBAR_EraseBkGnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    RECT cliprect;
+
+    if (GetClipBox ( (HDC)wParam, &cliprect))
+        return REBAR_InternalEraseBkGnd (hwnd, wParam, lParam, &cliprect);
+    return 0;
+}
+
+
+static LRESULT
 REBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
@@ -2135,15 +2456,94 @@
 }
 
 
-#if 0
+static LRESULT
+REBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    REBAR_BAND *lpBand;
+
+    /* If InternalHitTest did not find a hit on the Gripper, */
+    /* then ignore the button click.                         */
+    if (infoPtr->ihitBand == -1) return 0;
+
+    SetCapture (hwnd);
+
+    /* save off the LOWORD and HIWORD of lParam as initial x,y */
+    lpBand = &infoPtr->bands[infoPtr->ihitBand];
+    infoPtr->dragStart = MAKEPOINTS(lParam);
+    infoPtr->dragNow = infoPtr->dragStart;
+    infoPtr->ihitoffset = infoPtr->dragStart.x - lpBand->rcGripper.left;
+
+    return 0;
+}
+
+
+static LRESULT
+REBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    NMHDR layout;
+    NMREBAR enddrag;
+    RECT rect;
+
+    /* If InternalHitTest did not find a hit on the Gripper, */
+    /* then ignore the button click.                         */
+    if (infoPtr->ihitBand == -1) return 0;
+
+    infoPtr->dragStart.x = 0;
+    infoPtr->dragStart.y = 0;
+    infoPtr->dragNow = infoPtr->dragStart;
+    infoPtr->ihitBand = -1;
+
+    ReleaseCapture ();
+
+    if (infoPtr->fStatus & BEGIN_DRAG_ISSUED) {
+        REBAR_Notify(hwnd, (NMHDR *) &layout, RBN_LAYOUTCHANGED);
+
+	enddrag.dwMask = 0;
+	enddrag.uBand = -1;
+	REBAR_Notify(hwnd, (NMHDR *) &enddrag, RBN_ENDDRAG);
+	infoPtr->fStatus &= ~BEGIN_DRAG_ISSUED;
+    }
+
+    GetClientRect(hwnd, &rect);
+    InvalidateRect(hwnd, NULL, TRUE);
+
+    return 0;
+}
+
+
 static LRESULT
 REBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
+    REBAR_BAND *band1, *band2;
+    POINTS ptsmove;
 
+    /* Validate entry as hit on Gripper has occured */
+    if (GetCapture() != hwnd) return 0;
+    if (infoPtr->ihitBand == -1) return 0;
+
+    ptsmove = MAKEPOINTS(lParam);
+
+    /* if mouse did not move much, exit */
+    if ((abs(ptsmove.x - infoPtr->dragNow.x) <= mindragx) &&
+	(abs(ptsmove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
+
+    band1 = &infoPtr->bands[infoPtr->ihitBand-1];
+    band2 = &infoPtr->bands[infoPtr->ihitBand];
+
+    /* Test for valid drag case - must not be first band in row */
+    if ((ptsmove.y < band2->rcBand.top) ||
+	(ptsmove.y > band2->rcBand.bottom) ||
+        ((infoPtr->ihitBand > 0) && (band1->iRow != band2->iRow))) {
+        FIXME("Cannot drag to other rows yet!!\n");
+    }
+    else {
+        REBAR_HandleLRDrag (hwnd, infoPtr, &ptsmove);
+    }
     return 0;
 }
-#endif
 
 
 inline static LRESULT
@@ -2188,12 +2588,18 @@
 
 
 static LRESULT
-REBAR_Paint (HWND hwnd, WPARAM wParam)
+REBAR_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
     HDC hdc;
     PAINTSTRUCT ps;
 
     hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
+
+    if (ps.fErase) {
+	/* Erase area of paint if requested */
+        REBAR_InternalEraseBkGnd (hwnd, wParam, lParam, &ps.rcPaint);
+    }
+
     REBAR_Refresh (hwnd, hdc);
     if (!wParam)
 	EndPaint (hwnd, &ps);
@@ -2269,8 +2675,8 @@
     RECT rcClient;
 
     /* auto resize deadlock check */
-    if (infoPtr->bAutoResize) {
-	infoPtr->bAutoResize = FALSE;
+    if (infoPtr->fStatus & AUTO_RESIZE) {
+	infoPtr->fStatus &= ~AUTO_RESIZE;
 	return 0;
     }
 
@@ -2430,8 +2836,14 @@
 	case WM_GETFONT:
 	    return REBAR_GetFont (hwnd, wParam, lParam);
 
-/*	case WM_MOUSEMOVE: */
-/*	    return REBAR_MouseMove (hwnd, wParam, lParam); */
+	case WM_LBUTTONDOWN:
+	    return REBAR_LButtonDown (hwnd, wParam, lParam);
+
+	case WM_LBUTTONUP:
+	    return REBAR_LButtonUp (hwnd, wParam, lParam);
+
+	case WM_MOUSEMOVE:
+	    return REBAR_MouseMove (hwnd, wParam, lParam);
 
 	case WM_NCCALCSIZE:
 	    return REBAR_NCCalcSize (hwnd, wParam, lParam);
@@ -2443,7 +2855,7 @@
 	    return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
 
 	case WM_PAINT:
-	    return REBAR_Paint (hwnd, wParam);
+	    return REBAR_Paint (hwnd, wParam, lParam);
 
 	case WM_SETCURSOR:
 	    return REBAR_SetCursor (hwnd, wParam, lParam);
@@ -2460,6 +2872,9 @@
 
 /*	case WM_WININICHANGE: */
 
+        case WM_ERASEBKGND:
+	  return REBAR_EraseBkGnd (hwnd, wParam, lParam);
+
 	default:
 	    if (uMsg >= WM_USER)
 		ERR("unknown msg %04x wp=%08x lp=%08lx\n",
@@ -2485,6 +2900,10 @@
     wndClass.lpszClassName = REBARCLASSNAMEA;
  
     RegisterClassA (&wndClass);
+
+    mindragx = GetSystemMetrics (SM_CXDRAG);
+    mindragy = GetSystemMetrics (SM_CYDRAG);
+
 }