comctl32: rebar[1/4]: rewrite the layouting code

Mikołaj Zalewski mikolaj at zalewski.pl
Sat Feb 17 15:10:51 CST 2007


As this patch is big and will probably have to wait for the moderator I 
will write a comment in the second patch
-------------- next part --------------
From 2b42e9b97b443ced2531a445b531fddc5db2dcad Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Miko=C5=82aj_Zalewski?= <mikolaj at zalewski.pl>
Date: Sat, 17 Feb 2007 19:24:25 +0100
Subject: [PATCH] comctl32: rebar: rewrite the layouting code

---
 dlls/comctl32/rebar.c       | 1735 +++++++++++++------------------------------
 dlls/comctl32/tests/rebar.c |  421 ++++++++++-
 2 files changed, 901 insertions(+), 1255 deletions(-)

diff --git a/dlls/comctl32/rebar.c b/dlls/comctl32/rebar.c
index 9550eb5..9da110c 100644
--- a/dlls/comctl32/rebar.c
+++ b/dlls/comctl32/rebar.c
@@ -127,20 +127,14 @@ typedef struct
     LPARAM    lParam;
     UINT    cxHeader;
 
+    INT     cxEffective;     /* current cx for band */
     UINT    lcx;            /* minimum cx for band */
-    UINT    ccx;            /* current cx for band */
-    UINT    hcx;            /* maximum cx for band */
     UINT    lcy;            /* minimum cy for band */
-    UINT    ccy;            /* current cy for band */
-    UINT    hcy;            /* maximum cy for band */
 
-    SIZE    offChild;       /* x,y offset if child is not FIXEDSIZE */
-    UINT    uMinHeight;
     INT     iRow;           /* zero-based index of the row this band assigned to */
     UINT    fStatus;        /* status flags, reset only by _Validate */
     UINT    fDraw;          /* drawing flags, reset only by _Layout */
     UINT    uCDret;         /* last return from NM_CUSTOMDRAW */
-    RECT    rcoldBand;      /* previous calculated band rectangle */
     RECT    rcBand;         /* calculated band rectangle */
     RECT    rcGripper;      /* calculated gripper rectangle */
     RECT    rcCapImage;     /* calculated caption image rectangle */
@@ -161,12 +155,8 @@ typedef struct
 #define DRAW_GRIPPER    0x00000001
 #define DRAW_IMAGE      0x00000002
 #define DRAW_TEXT       0x00000004
-#define DRAW_RIGHTSEP   0x00000010
-#define DRAW_BOTTOMSEP  0x00000020
 #define DRAW_CHEVRONHOT 0x00000040
 #define DRAW_CHEVRONPUSHED 0x00000080
-#define DRAW_LAST_IN_ROW   0x00000100
-#define DRAW_FIRST_IN_ROW  0x00000200
 #define NTF_INVALIDATE  0x01000000
 
 typedef struct
@@ -250,10 +240,16 @@ typedef struct
 /* Width of the chevron button if present */
 #define CHEVRON_WIDTH  10
 
+/* the gap between the child and the next band */
+#define REBAR_POST_CHILD 4
+
 /* Height of divider for Rebar if not disabled (CCS_NODIVIDER)     */
 /* either top or bottom                                            */
 #define REBAR_DIVIDER  2
 
+/* height of a rebar without a child */
+#define REBAR_NO_CHILD_HEIGHT 4
+
 /* minimium vertical height of a normal bar                        */
 /*   or minimum width of a CCS_VERT bar - from experiment on Win2k */
 #define REBAR_MINSIZE  23
@@ -265,29 +261,11 @@ typedef struct
 
 #define RB_GETBANDINFO_OLD (WM_USER+5) /* obsoleted after IE3, but we have to support it anyway */
 
-/*  The following 6 defines return the proper rcBand element       */
-/*  depending on whether CCS_VERT was set.                         */
-#define rcBlt(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.top : b->rcBand.left)
-#define rcBrb(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.bottom : b->rcBand.right)
-#define rcBw(b)  ((infoPtr->dwStyle & CCS_VERT) ? (b->rcBand.bottom - b->rcBand.top) : \
-		  (b->rcBand.right - b->rcBand.left))
-#define ircBlt(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.left : b->rcBand.top)
-#define ircBrb(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.right : b->rcBand.bottom)
-#define ircBw(b)  ((infoPtr->dwStyle & CCS_VERT) ? (b->rcBand.right - b->rcBand.left) : \
-		  (b->rcBand.bottom - b->rcBand.top))
-
 /*  The following define determines if a given band is hidden      */
 #define HIDDENBAND(a)  (((a)->fStyle & RBBS_HIDDEN) ||   \
                         ((infoPtr->dwStyle & CCS_VERT) &&         \
                          ((a)->fStyle & RBBS_NOVERT)))
 
-/*  The following defines adjust the right or left end of a rectangle */
-#define READJ(b,i) do { if(infoPtr->dwStyle & CCS_VERT) b->rcBand.bottom+=(i); \
-                    else b->rcBand.right += (i); } while(0)
-#define LEADJ(b,i) do { if(infoPtr->dwStyle & CCS_VERT) b->rcBand.top+=(i); \
-                    else b->rcBand.left += (i); } while(0)
-
-
 #define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongPtrW (hwnd, 0))
 
 static LRESULT REBAR_NotifyFormat(REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam);
@@ -429,8 +407,8 @@ REBAR_DumpBand (REBAR_INFO *iP)
 	if (pB->fMask & RBBIM_STYLE)
 	    TRACE("band # %u: style=0x%08x (%s)\n",
 		  i, pB->fStyle, REBAR_FmtStyle(pB->fStyle));
-	TRACE("band # %u: uMinH=%u xHeader=%u",
-	      i, pB->uMinHeight, pB->cxHeader);
+	TRACE("band # %u: xHeader=%u",
+	      i, pB->cxHeader);
 	if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_LPARAM )) {
 	    if (pB->fMask & RBBIM_SIZE)
 		TRACE(" cx=%u", pB->cx);
@@ -446,8 +424,8 @@ REBAR_DumpBand (REBAR_INFO *iP)
 	if (pB->fMask & RBBIM_TEXT)
 	    TRACE("band # %u: text=%s\n",
 		  i, (pB->lpText) ? debugstr_w(pB->lpText) : "(null)");
-	TRACE("band # %u: lcx=%u, ccx=%u, hcx=%u, lcy=%u, ccy=%u, hcy=%u, offChild=%d,%d\n",
-	      i, pB->lcx, pB->ccx, pB->hcx, pB->lcy, pB->ccy, pB->hcy, pB->offChild.cx, pB->offChild.cy);
+	TRACE("band # %u: lcx=%u, cxEffective=%u, lcy=%u\n",
+	      i, pB->lcx, pB->cxEffective, pB->lcy);
 	TRACE("band # %u: fStatus=%08x, fDraw=%08x, Band=(%d,%d)-(%d,%d), Grip=(%d,%d)-(%d,%d)\n",
 	      i, pB->fStatus, pB->fDraw,
 	      pB->rcBand.left, pB->rcBand.top, pB->rcBand.right, pB->rcBand.bottom,
@@ -461,6 +439,43 @@ REBAR_DumpBand (REBAR_INFO *iP)
 
 }
 
+static void translate_rect(REBAR_INFO *infoPtr, RECT *dest, const RECT *src)
+{
+    if (infoPtr->dwStyle & CCS_VERT) {
+        dest->top = src->left;
+        dest->bottom = src->right;
+        dest->left = src->top;
+        dest->right = src->bottom;
+    } else {
+        *dest = *src;
+    }
+}
+
+static int get_rect_cx(REBAR_INFO *infoPtr, RECT *lpRect)
+{
+    if (infoPtr->dwStyle & CCS_VERT)
+        return lpRect->bottom - lpRect->top;
+    return lpRect->right - lpRect->left;
+}
+
+static int get_rect_cy(REBAR_INFO *infoPtr, RECT *lpRect)
+{
+    if (infoPtr->dwStyle & CCS_VERT)
+        return lpRect->right - lpRect->left;
+    return lpRect->bottom - lpRect->top;
+}
+
+static void round_child_height(REBAR_BAND *lpBand, int cyHeight)
+{
+    int cy = 0;
+    if (lpBand->cyIntegral == 0)
+        return;
+    cy = max(cyHeight - (int)lpBand->cyMinChild, 0);
+    cy = lpBand->cyMinChild + (cy/lpBand->cyIntegral) * lpBand->cyIntegral;
+    cy = min(cy, lpBand->cyMaxChild);
+    lpBand->cyChild = cy;
+}
+
 static void
 REBAR_DrawChevron (HDC hdc, INT left, INT top, INT colorRef)
 {
@@ -544,6 +559,9 @@ REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
     INT oldBkMode = 0;
     NMCUSTOMDRAW nmcd;
     HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
+    RECT rcBand;
+
+    translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
 
     if (lpBand->fDraw & DRAW_TEXT) {
 	hOldFont = SelectObject (hdc, infoPtr->hFont);
@@ -553,7 +571,7 @@ REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
     /* should test for CDRF_NOTIFYITEMDRAW here */
     nmcd.dwDrawStage = CDDS_ITEMPREPAINT;
     nmcd.hdc = hdc;
-    nmcd.rc = lpBand->rcBand;
+    nmcd.rc = rcBand;
     nmcd.rc.right = lpBand->rcCapText.right;
     nmcd.rc.bottom = lpBand->rcCapText.bottom;
     nmcd.dwItemSpec = lpBand->wID;
@@ -649,7 +667,7 @@ REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
     if (lpBand->uCDret == (CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYITEMDRAW)) {
 	nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;
 	nmcd.hdc = hdc;
-	nmcd.rc = lpBand->rcBand;
+	nmcd.rc = rcBand;
 	nmcd.rc.right = lpBand->rcCapText.right;
 	nmcd.rc.bottom = lpBand->rcCapText.bottom;
 	nmcd.dwItemSpec = lpBand->wID;
@@ -683,235 +701,14 @@ REBAR_Refresh (REBAR_INFO *infoPtr, HDC hdc)
 
 
 static void
-REBAR_FixVert (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend,
-		   INT mcy)
-     /* Function:                                                    */
-     /*   Cycle through bands in row and fix height of each band.    */
-     /*   Also determine whether each band has changed.              */
-     /* On entry:                                                    */
-     /*   all bands at desired size.                                 */
-     /*   start and end bands are *not* hidden                       */
-{
-    REBAR_BAND *lpBand;
-    INT i;
-
-    for (i = (INT)rowstart; i<=(INT)rowend; i++) {
-        lpBand = &infoPtr->bands[i];
-	if (HIDDENBAND(lpBand)) continue;
-
-	/* adjust height of bands in row to "mcy" value */
-	if (infoPtr->dwStyle & CCS_VERT) {
-	    if (lpBand->rcBand.right != lpBand->rcBand.left + mcy)
-	        lpBand->rcBand.right = lpBand->rcBand.left + mcy;
-	}
-	else {
-	    if (lpBand->rcBand.bottom != lpBand->rcBand.top + mcy)
-	        lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
-
-	}
-
-	/* mark whether we need to invalidate this band and trace */
-	if ((lpBand->rcoldBand.left !=lpBand->rcBand.left) ||
-	    (lpBand->rcoldBand.top !=lpBand->rcBand.top) ||
-	    (lpBand->rcoldBand.right !=lpBand->rcBand.right) ||
-	    (lpBand->rcoldBand.bottom !=lpBand->rcBand.bottom)) {
-	    lpBand->fDraw |= NTF_INVALIDATE;
-            TRACE("band %d row=%d: changed to (%d,%d)-(%d,%d) from (%d,%d)-(%d,%d)\n",
-		  i, lpBand->iRow,
-		  lpBand->rcBand.left, lpBand->rcBand.top,
-		  lpBand->rcBand.right, lpBand->rcBand.bottom,
-		  lpBand->rcoldBand.left, lpBand->rcoldBand.top,
-		  lpBand->rcoldBand.right, lpBand->rcoldBand.bottom);
-	}
-	else
-            TRACE("band %d row=%d: unchanged (%d,%d)-(%d,%d)\n",
-		  i, lpBand->iRow,
-		  lpBand->rcBand.left, lpBand->rcBand.top,
-		  lpBand->rcBand.right, lpBand->rcBand.bottom);
-    }
-}
-
-
-static void
-REBAR_AdjustBands (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend,
-		   INT maxx, INT mcy)
-     /* Function: This routine distributes the extra space in a row. */
-     /*  See algorithm below.                                        */
-     /* On entry:                                                    */
-     /*   all bands @ ->cxHeader size                                */
-     /*   start and end bands are *not* hidden                       */
-{
-    REBAR_BAND *lpBand;
-    UINT xsep, extra, curwidth, fudge;
-    INT x, i, last_adjusted;
-
-    TRACE("start=%u, end=%u, max x=%d, max y=%d\n",
-	  rowstart, rowend, maxx, mcy);
-
-    /* *******************  Phase 1  ************************ */
-    /* Alg:                                                   */
-    /*  For each visible band with valid child                */
-    /*      a. inflate band till either all extra space used  */
-    /*         or band's ->ccx reached.                       */
-    /*  If any band modified, add any space left to last band */
-    /*  adjusted.                                             */
-    /*                                                        */
-    /* ****************************************************** */
-    lpBand = &infoPtr->bands[rowend];
-    extra = maxx - rcBrb(lpBand);
-    x = 0;
-    last_adjusted = -1;
-    for (i=(INT)rowstart; i<=(INT)rowend; i++) {
-	lpBand = &infoPtr->bands[i];
-	if (HIDDENBAND(lpBand)) continue;
-	xsep = (x == 0) ? 0 : SEP_WIDTH;
-	curwidth = rcBw(lpBand);
-
-	/* set new left/top point */
-	if (infoPtr->dwStyle & CCS_VERT)
-	    lpBand->rcBand.top = x + xsep;
-	else
-	    lpBand->rcBand.left = x + xsep;
-
-	/* compute new width */
-	if ((lpBand->hwndChild && extra) && !(lpBand->fStyle & RBBS_FIXEDSIZE)) {
-	    /* set to the "current" band size less the header */
-	    fudge = lpBand->ccx;
-	    last_adjusted = i;
-	    if ((lpBand->fMask & RBBIM_SIZE) && (lpBand->cx > 0) &&
-		(fudge > curwidth)) {
-		TRACE("adjusting band %d by %d, fudge=%d, curwidth=%d, extra=%d\n",
-		      i, fudge-curwidth, fudge, curwidth, extra);
-		if ((fudge - curwidth) > extra)
-		    fudge = curwidth + extra;
-		extra -= (fudge - curwidth);
-		curwidth = fudge;
-	    }
-	    else {
-		TRACE("adjusting band %d by %d, fudge=%d, curwidth=%d\n",
-		      i, extra, fudge, curwidth);
-		curwidth += extra;
-		extra = 0;
-	    }
-	}
-
-	/* set new right/bottom point */
-	if (infoPtr->dwStyle & CCS_VERT)
-	    lpBand->rcBand.bottom = lpBand->rcBand.top + curwidth;
-	else
-	    lpBand->rcBand.right = lpBand->rcBand.left + curwidth;
-	TRACE("Phase 1 band %d, (%d,%d)-(%d,%d), orig x=%d, xsep=%d\n",
-	      i, lpBand->rcBand.left, lpBand->rcBand.top,
-	      lpBand->rcBand.right, lpBand->rcBand.bottom, x, xsep);
-	x = rcBrb(lpBand);
-    }
-    if ((x >= maxx) || (last_adjusted != -1)) {
-	if (x > maxx) {
-	    ERR("Phase 1 failed, x=%d, maxx=%d, start=%u, end=%u\n",
-		x, maxx,  rowstart, rowend);
-	}
-	/* done, so spread extra space */
-	if (x < maxx) {
-	    fudge = maxx - x;
-	    TRACE("Need to spread %d on last adjusted band %d\n",
-		fudge, last_adjusted);
-	    for (i=(INT)last_adjusted; i<=(INT)rowend; i++) {
-		lpBand = &infoPtr->bands[i];
-		if (HIDDENBAND(lpBand)) continue;
-
-		/* set right/bottom point */
-		if (i != last_adjusted) {
-		    if (infoPtr->dwStyle & CCS_VERT)
-			lpBand->rcBand.top += fudge;
-		    else
-			lpBand->rcBand.left += fudge;
-		}
-
-		/* set left/bottom point */
-		if (infoPtr->dwStyle & CCS_VERT)
-		    lpBand->rcBand.bottom += fudge;
-		else
-		    lpBand->rcBand.right += fudge;
-	    }
-	}
-	TRACE("Phase 1 succeeded, used x=%d\n", x);
-	REBAR_FixVert (infoPtr, rowstart, rowend, mcy);
- 	return;
-    }
-
-    /* *******************  Phase 2  ************************ */
-    /* Alg:                                                   */
-    /*  Find first visible band, put all                      */
-    /*    extra space there.                                  */
-    /*                                                        */
-    /* ****************************************************** */
-
-    x = 0;
-    for (i=(INT)rowstart; i<=(INT)rowend; i++) {
-	lpBand = &infoPtr->bands[i];
-	if (HIDDENBAND(lpBand)) continue;
-	xsep = (x == 0) ? 0 : SEP_WIDTH;
-	curwidth = rcBw(lpBand);
-
-	/* set new left/top point */
-	if (infoPtr->dwStyle & CCS_VERT)
-	    lpBand->rcBand.top = x + xsep;
-	else
-	    lpBand->rcBand.left = x + xsep;
-
-	/* compute new width */
-	if (extra) {
-	    curwidth += extra;
-	    extra = 0;
-	}
-
-	/* set new right/bottom point */
-	if (infoPtr->dwStyle & CCS_VERT)
-	    lpBand->rcBand.bottom = lpBand->rcBand.top + curwidth;
-	else
-	    lpBand->rcBand.right = lpBand->rcBand.left + curwidth;
-	TRACE("Phase 2 band %d, (%d,%d)-(%d,%d), orig x=%d, xsep=%d\n",
-	      i, lpBand->rcBand.left, lpBand->rcBand.top,
-	      lpBand->rcBand.right, lpBand->rcBand.bottom, x, xsep);
-	x = rcBrb(lpBand);
-    }
-    if (x >= maxx) {
-	if (x > maxx) {
-	    ERR("Phase 2 failed, x=%d, maxx=%d, start=%u, end=%u\n",
-		x, maxx,  rowstart, rowend);
-	}
-	/* done, so spread extra space */
-	TRACE("Phase 2 succeeded, used x=%d\n", x);
-	REBAR_FixVert (infoPtr, rowstart, rowend, mcy);
-	return;
-    }
-
-    /* *******************  Phase 3  ************************ */
-    /* at this point everything is back to ->cxHeader values  */
-    /* and should not have gotten here.                       */
-    /* ****************************************************** */
-
-    lpBand = &infoPtr->bands[rowstart];
-    ERR("Serious problem adjusting row %d, start band %d, end band %d\n",
-	lpBand->iRow, rowstart, rowend);
-    REBAR_DumpBand (infoPtr);
-    return;
-}
-
-
-static void
-REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
+REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend)
      /* Function: this routine initializes all the rectangles in */
      /*  each band in a row to fit in the adjusted rcBand rect.  */
      /* *** Supports only Horizontal bars. ***                   */
 {
     REBAR_BAND *lpBand;
     UINT i, xoff, yoff;
-    HWND parenthwnd;
-    RECT oldChild, work;
-
-    /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
-    parenthwnd = GetParent (infoPtr->hwndSelf);
+    RECT work;
 
     for(i=rstart; i<rend; i++){
       lpBand = &infoPtr->bands[i];
@@ -922,8 +719,6 @@ REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
 	  continue;
       }
 
-      oldChild = lpBand->rcChild;
-
       /* set initial gripper rectangle */
       SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
 	       lpBand->rcBand.left, lpBand->rcBand.bottom);
@@ -960,11 +755,6 @@ REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
 	  SetRect (&lpBand->rcCapText,
 		   lpBand->rcCapImage.right+REBAR_POST_IMAGE, lpBand->rcBand.top+1,
 		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
-	  /* update band height
-	  if (lpBand->uMinHeight < infoPtr->imageSize.cy + 2) {
-	      lpBand->uMinHeight = infoPtr->imageSize.cy + 2;
-	      lpBand->rcBand.bottom = lpBand->rcBand.top + lpBand->uMinHeight;
-	  }  */
       }
       else {
 	  /* set initial caption text rectangle */
@@ -980,12 +770,12 @@ REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
       }
 
       /* set initial child window rectangle if there is a child */
-      if (lpBand->fMask & RBBIM_CHILD) {
-	  xoff = lpBand->offChild.cx;
-	  yoff = lpBand->offChild.cy;
+      if (lpBand->hwndChild != NULL) {
+          int cyBand = lpBand->rcBand.bottom - lpBand->rcBand.top;
+          yoff = (cyBand - lpBand->cyChild) / 2;
 	  SetRect (&lpBand->rcChild,
-		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top+yoff,
-		   lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
+                   lpBand->rcBand.left + lpBand->cxHeader, lpBand->rcBand.top + yoff,
+                   lpBand->rcBand.right - REBAR_POST_CHILD, lpBand->rcBand.top + yoff + lpBand->cyChild);
 	  if ((lpBand->fStyle & RBBS_USECHEVRON) && (lpBand->rcChild.right - lpBand->rcChild.left < lpBand->cxIdeal))
 	  {
 	      lpBand->rcChild.right -= CHEVRON_WIDTH;
@@ -1001,26 +791,16 @@ REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
       }
 
       /* flag if notify required and invalidate rectangle */
-      if (notify &&
-	  ((oldChild.right-oldChild.left != lpBand->rcChild.right-lpBand->rcChild.left) ||
-	   (oldChild.bottom-oldChild.top != lpBand->rcChild.bottom-lpBand->rcChild.top))) {
-	  TRACE("Child rectangle changed for band %u\n", i);
-          TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
-		oldChild.left, oldChild.top,
-	        oldChild.right, oldChild.bottom,
-		lpBand->rcChild.left, lpBand->rcChild.top,
-	        lpBand->rcChild.right, lpBand->rcChild.bottom);
-      }
       if (lpBand->fDraw & NTF_INVALIDATE) {
           TRACE("invalidating (%d,%d)-(%d,%d)\n",
 		lpBand->rcBand.left,
 		lpBand->rcBand.top,
-		lpBand->rcBand.right + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0),
-		lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0));
+		lpBand->rcBand.right + SEP_WIDTH,
+		lpBand->rcBand.bottom + SEP_WIDTH);
 	  lpBand->fDraw &= ~NTF_INVALIDATE;
 	  work = lpBand->rcBand;
-	  if (lpBand->fDraw & DRAW_RIGHTSEP) work.right += SEP_WIDTH_SIZE;
-	  if (lpBand->fDraw & DRAW_BOTTOMSEP) work.bottom += SEP_WIDTH_SIZE;
+	  work.right += SEP_WIDTH;
+	  work.bottom += SEP_WIDTH;
 	  InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
       }
 
@@ -1030,27 +810,24 @@ REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
 
 
 static VOID
-REBAR_CalcVertBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
+REBAR_CalcVertBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend)
      /* Function: this routine initializes all the rectangles in */
      /*  each band in a row to fit in the adjusted rcBand rect.  */
      /* *** Supports only Vertical bars. ***                     */
 {
     REBAR_BAND *lpBand;
-    UINT i, xoff, yoff;
-    HWND parenthwnd;
-    RECT oldChild, work;
-
-    /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
-    parenthwnd = GetParent (infoPtr->hwndSelf);
+    UINT i, xoff;
+    RECT work;
 
     for(i=rstart; i<rend; i++){
-	lpBand = &infoPtr->bands[i];
+        RECT rcBand;
+        lpBand = &infoPtr->bands[i];
 	if (HIDDENBAND(lpBand)) continue;
-	oldChild = lpBand->rcChild;
 
-	/* set initial gripper rectangle */
-	SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
-		 lpBand->rcBand.right, lpBand->rcBand.top);
+        translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
+
+        /* set initial gripper rectangle */
+	SetRect (&lpBand->rcGripper, rcBand.left, rcBand.top, rcBand.right, rcBand.top);
 
 	/* calculate gripper rectangle */
 	if (lpBand->fStatus & HAS_GRIPPER) {
@@ -1064,9 +841,9 @@ REBAR_CalcVertBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
 		lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_HEIGHT;
 
 		/* initialize Caption image rectangle  */
-		SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
+		SetRect (&lpBand->rcCapImage, rcBand.left,
 			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
-			 lpBand->rcBand.right,
+			 rcBand.right,
 			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
 	    }
 	    else {
@@ -1077,9 +854,9 @@ REBAR_CalcVertBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
 		lpBand->rcGripper.bottom  = lpBand->rcGripper.top + GRIPPER_WIDTH;
 
 		/* initialize Caption image rectangle  */
-		SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
+		SetRect (&lpBand->rcCapImage, rcBand.left,
 			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
-			 lpBand->rcBand.right,
+			 rcBand.right,
 			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
 	    }
 	}
@@ -1090,8 +867,8 @@ REBAR_CalcVertBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
 		xoff = REBAR_ALWAYS_SPACE;
 	    /* initialize Caption image rectangle  */
 	    SetRect (&lpBand->rcCapImage,
-		     lpBand->rcBand.left, lpBand->rcBand.top+xoff,
-		     lpBand->rcBand.right, lpBand->rcBand.top+xoff);
+                      rcBand.left, rcBand.top+xoff,
+                      rcBand.right, rcBand.top+xoff);
 	}
 
 	/* image is visible */
@@ -1103,19 +880,14 @@ REBAR_CalcVertBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
 
 	    /* set initial caption text rectangle */
 	    SetRect (&lpBand->rcCapText,
-		     lpBand->rcBand.left, lpBand->rcCapImage.bottom+REBAR_POST_IMAGE,
-		     lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
-	    /* update band height *
-	       if (lpBand->uMinHeight < infoPtr->imageSize.cx + 2) {
-	       lpBand->uMinHeight = infoPtr->imageSize.cx + 2;
-	       lpBand->rcBand.right = lpBand->rcBand.left + lpBand->uMinHeight;
-	       } */
+		     rcBand.left, lpBand->rcCapImage.bottom+REBAR_POST_IMAGE,
+		     rcBand.right, rcBand.top+lpBand->cxHeader);
 	}
 	else {
 	    /* set initial caption text rectangle */
 	    SetRect (&lpBand->rcCapText,
-		     lpBand->rcBand.left, lpBand->rcCapImage.bottom,
-		     lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
+		     rcBand.left, lpBand->rcCapImage.bottom,
+		     rcBand.right, rcBand.top+lpBand->cxHeader);
 	}
 
 	/* text is visible */
@@ -1126,40 +898,29 @@ REBAR_CalcVertBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
 	}
 
 	/* set initial child window rectangle if there is a child */
-	if (lpBand->fMask & RBBIM_CHILD) {
-	    yoff = lpBand->offChild.cx;
-	    xoff = lpBand->offChild.cy;
+	if (lpBand->hwndChild != NULL) {
+            int cxBand = rcBand.right - rcBand.left;
+            xoff = (cxBand - lpBand->cyChild) / 2;
 	    SetRect (&lpBand->rcChild,
-		     lpBand->rcBand.left+xoff, lpBand->rcBand.top+lpBand->cxHeader,
-		     lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
+		     rcBand.left + xoff,                   rcBand.top + lpBand->cxHeader,
+                     rcBand.left + xoff + lpBand->cyChild, rcBand.bottom - REBAR_POST_CHILD);
 	}
 	else {
 	    SetRect (&lpBand->rcChild,
-		     lpBand->rcBand.left, lpBand->rcBand.top+lpBand->cxHeader,
-		     lpBand->rcBand.right, lpBand->rcBand.bottom);
+		     rcBand.left, rcBand.top+lpBand->cxHeader,
+		     rcBand.right, rcBand.bottom);
 	}
 
-	/* flag if notify required and invalidate rectangle */
-	if (notify &&
-	    ((oldChild.right-oldChild.left != lpBand->rcChild.right-lpBand->rcChild.left) ||
-	     (oldChild.bottom-oldChild.top != lpBand->rcChild.bottom-lpBand->rcChild.top))) {
-	    TRACE("Child rectangle changed for band %u\n", i);
-            TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
-		  oldChild.left, oldChild.top,
-		  oldChild.right, oldChild.bottom,
-		  lpBand->rcChild.left, lpBand->rcChild.top,
-		  lpBand->rcChild.right, lpBand->rcChild.bottom);
-	}
 	if (lpBand->fDraw & NTF_INVALIDATE) {
             TRACE("invalidating (%d,%d)-(%d,%d)\n",
-		  lpBand->rcBand.left,
-		  lpBand->rcBand.top,
-		  lpBand->rcBand.right + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0),
-		  lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0));
+                  rcBand.left,
+                  rcBand.top,
+                  rcBand.right + SEP_WIDTH,
+                  rcBand.bottom + SEP_WIDTH);
 	    lpBand->fDraw &= ~NTF_INVALIDATE;
-	    work = lpBand->rcBand;
-	    if (lpBand->fDraw & DRAW_RIGHTSEP) work.bottom += SEP_WIDTH_SIZE;
-	    if (lpBand->fDraw & DRAW_BOTTOMSEP) work.right += SEP_WIDTH_SIZE;
+	    work = rcBand;
+	    work.bottom += SEP_WIDTH;
+	    work.right += SEP_WIDTH;
 	    InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
 	}
 
@@ -1184,6 +945,9 @@ REBAR_ForceResize (REBAR_INFO *infoPtr)
 	   infoPtr->calcSize.cx, infoPtr->calcSize.cy,
 	   rc.right, rc.bottom);
 
+    if (infoPtr->dwStyle & CCS_NORESIZE)
+        return;
+
     /* If we need to shrink client, then skip size test */
     if ((infoPtr->calcSize.cy >= rc.bottom) &&
 	(infoPtr->calcSize.cx >= rc.right)) {
@@ -1236,12 +1000,12 @@ REBAR_ForceResize (REBAR_INFO *infoPtr)
 	    break;
 	case CCS_LEFT:
 	    /* _LEFT sets height to parents height */
-	    width += infoPtr->calcSize.cx;
+            width += infoPtr->calcSize.cx;
 	    height += (rcPcl.bottom - rcPcl.top);
 	    x += ((infoPtr->dwStyle & WS_BORDER) ? -xedge : 0);
 	    x += ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
 	    y += ((infoPtr->dwStyle & WS_BORDER) ? -yedge : 0);
-	    break;
+            break;
 	case CCS_RIGHT:
 	    /* FIXME: wrong wrong wrong */
 	    /* _RIGHT sets height to parents height */
@@ -1297,7 +1061,7 @@ REBAR_MoveChildWindows (REBAR_INFO *infoPtr, UINT start, UINT endplus)
 	    rbcz.uBand = i;
 	    rbcz.wID = lpBand->wID;
 	    rbcz.rcChild = lpBand->rcChild;
-	    rbcz.rcBand = lpBand->rcBand;
+            translate_rect(infoPtr, &rbcz.rcBand, &lpBand->rcBand);
 	    if (infoPtr->dwStyle & CCS_VERT)
 		rbcz.rcBand.top += lpBand->cxHeader;
 	    else
@@ -1311,7 +1075,7 @@ REBAR_MoveChildWindows (REBAR_INFO *infoPtr, UINT start, UINT endplus)
 		      rbcz.rcChild.left, rbcz.rcChild.top,
 		      rbcz.rcChild.right, rbcz.rcChild.bottom);
 		lpBand->rcChild = rbcz.rcChild;  /* *** ??? */
-	    }
+            }
 
 	    /* native (IE4 in "Favorites" frame **1) does:
 	     *   SetRect (&rc, -1, -1, -1, -1)
@@ -1394,552 +1158,308 @@ REBAR_MoveChildWindows (REBAR_INFO *infoPtr, UINT start, UINT endplus)
 
 }
 
-
-static VOID
-REBAR_Layout (REBAR_INFO *infoPtr, LPRECT lpRect, BOOL notify, BOOL resetclient)
-     /* Function: This routine is resposible for laying out all */
-     /*  the bands in a rebar. It assigns each band to a row and*/
-     /*  determines when to start a new row.                    */
+static void swap_size_if_vert(REBAR_INFO *infoPtr, SIZE *size)
 {
-    REBAR_BAND *lpBand, *prevBand;
-    RECT rcClient, rcAdj;
-    INT initx, inity, x, y, cx, cxsep, mmcy, mcy, clientcx, clientcy;
-    INT adjcx, adjcy, row, rightx, bottomy, origheight;
-    UINT i, j, rowstart, origrows, cntonrow;
-    BOOL dobreak;
-
-    if (!(infoPtr->fStatus & BAND_NEEDS_LAYOUT)) {
-	TRACE("no layout done. No band changed.\n");
-	REBAR_DumpBand (infoPtr);
-	return;
-    }
-    infoPtr->fStatus &= ~BAND_NEEDS_LAYOUT;
-    if (!infoPtr->DoRedraw) infoPtr->fStatus |= BAND_NEEDS_REDRAW;
-
-    GetClientRect (infoPtr->hwndSelf, &rcClient);
-    TRACE("Client is (%d,%d)-(%d,%d)\n",
-	  rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
-
-    if (lpRect) {
-	rcAdj = *lpRect;
-	TRACE("adjustment rect is (%d,%d)-(%d,%d)\n",
-	      rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom);
-    }
-    else {
-        CopyRect (&rcAdj, &rcClient);
-    }
-
-    clientcx = rcClient.right - rcClient.left;
-    clientcy = rcClient.bottom - rcClient.top;
-    adjcx = rcAdj.right - rcAdj.left;
-    adjcy = rcAdj.bottom - rcAdj.top;
-    if (resetclient) {
-        TRACE("window client rect will be set to adj rect\n");
-        clientcx = adjcx;
-        clientcy = adjcy;
-    }
-
-    if (!infoPtr->DoRedraw && (clientcx == 0) && (clientcy == 0)) {
-	ERR("no redraw and client is zero, skip layout\n");
-	infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
-	return;
-    }
-
-    /* save height of original control */
     if (infoPtr->dwStyle & CCS_VERT)
-        origheight = infoPtr->calcSize.cx;
-    else
-        origheight = infoPtr->calcSize.cy;
-    origrows = infoPtr->uNumRows;
-
-    initx = 0;
-    inity = 0;
-
-    /* ******* Start Phase 1 - all bands on row at minimum size ******* */
-
-    TRACE("band loop constants, clientcx=%d, clientcy=%d, adjcx=%d, adjcy=%d\n",
-	  clientcx, clientcy, adjcx, adjcy);
-    x = initx;
-    y = inity;
-    row = 0;
-    cx = 0;
-    mcy = 0;
-    rowstart = 0;
-    prevBand = NULL;
-    cntonrow = 0;
-
-    for (i = 0; i < infoPtr->uNumBands; i++) {
-	lpBand = &infoPtr->bands[i];
-	lpBand->fDraw = 0;
-	lpBand->iRow = row;
-
-	SetRectEmpty(&lpBand->rcChevron);
-
-	if (HIDDENBAND(lpBand)) continue;
-
-	lpBand->rcoldBand = lpBand->rcBand;
+    {
+        LONG tmp = size->cx;
+        size->cx = size->cy;
+        size->cy = tmp;
+    }
+}
 
-	/* Set the offset of the child window */
-	if ((lpBand->fMask & RBBIM_CHILD) &&
-	    !(lpBand->fStyle & RBBS_FIXEDSIZE)) {
-	    lpBand->offChild.cx = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 4 : 0);
-	}
-	lpBand->offChild.cy = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 2 : 0);
+static int next_band(REBAR_INFO *infoPtr, int i)
+{
+    int n;
+    for (n = i + 1; n < infoPtr->uNumBands; n++)
+        if (!HIDDENBAND(&infoPtr->bands[n]))
+            break;
+    return n;
+}
 
-	/* separator from previous band */
-	cxsep = (cntonrow == 0) ? 0 : SEP_WIDTH;
-	cx = lpBand->lcx;
+static int prev_band(REBAR_INFO *infoPtr, int i)
+{
+    int n;
+    for (n = i - 1; n >= 0; n--)
+        if (!HIDDENBAND(&infoPtr->bands[n]))
+            break;
+    return n;
+}
 
-        /* In native, 0 as one of the coordinates means no limit */
-	if (infoPtr->dwStyle & CCS_VERT)
-	    dobreak = (adjcy && (y + cx + cxsep > adjcy));
+static int get_row_begin_for_band(REBAR_INFO *infoPtr, INT iBand)
+{
+    int iLastBand = iBand;
+    int iRow = infoPtr->bands[iBand].iRow;
+    while ((iBand = prev_band(infoPtr, iBand)) >= 0) {
+        if (infoPtr->bands[iBand].iRow != iRow)
+            break;
         else
-	    dobreak = (adjcx && (x + cx + cxsep > adjcx));
-
-	/* This is the check for whether we need to start a new row */
-	if ( ( (lpBand->fStyle & RBBS_BREAK) && (i != 0) ) ||
-	     ( ((infoPtr->dwStyle & CCS_VERT) ? (y != 0) : (x != 0)) && dobreak)) {
-
-	    for (j = rowstart; j < i; j++) {
-		REBAR_BAND *lpB;
-		lpB = &infoPtr->bands[j];
-		if (infoPtr->dwStyle & CCS_VERT) {
-		    lpB->rcBand.right  = lpB->rcBand.left + mcy;
-		}
-		else {
-		    lpB->rcBand.bottom = lpB->rcBand.top + mcy;
-		}
-	    }
-
-	    TRACE("P1 Spliting to new row %d on band %u\n", row+1, i);
-	    if (infoPtr->dwStyle & CCS_VERT) {
-		y = inity;
-		x += (mcy + SEP_WIDTH);
-	    }
-	    else {
-		x = initx;
-		y += (mcy + SEP_WIDTH);
-	    }
-
-	    mcy = 0;
-	    cxsep = 0;
-	    row++;
-	    lpBand->iRow = row;
-	    prevBand = NULL;
-	    rowstart = i;
-	    cntonrow = 0;
-	}
-
-	if (mcy < lpBand->lcy + REBARSPACE(lpBand))
-	    mcy = lpBand->lcy + REBARSPACE(lpBand);
-
-	/* if boundary rect specified then limit mcy */
-	if (lpRect) {
-	    if (infoPtr->dwStyle & CCS_VERT) {
-	        if (adjcx && (x+mcy > adjcx)) {
-		    mcy = adjcx - x;
-		    TRACE("P1 row %u limiting mcy=%d, adjcx=%d, x=%d\n",
-			  i, mcy, adjcx, x);
-		}
-	    }
-	    else {
-	        if (adjcy && (y+mcy > adjcy)) {
-		    mcy = adjcy - y;
-		    TRACE("P1 row %u limiting mcy=%d, adjcy=%d, y=%d\n",
-			  i, mcy, adjcy, y);
-		}
-	    }
-	}
-
-	TRACE("P1 band %u, row %d, x=%d, y=%d, cxsep=%d, cx=%d\n",
-	      i, row,
-	      x, y, cxsep, cx);
-	if (infoPtr->dwStyle & CCS_VERT) {
-	    /* bound the bottom side if we have a bounding rectangle */
-	    rightx = clientcx;
-	    bottomy = (lpRect) ? min(clientcy, y+cxsep+cx) : y+cxsep+cx;
-	    lpBand->rcBand.left   = x;
-	    lpBand->rcBand.right  = x + min(mcy,
-					    lpBand->lcy+REBARSPACE(lpBand));
-	    lpBand->rcBand.top    = min(bottomy, y + cxsep);
-	    lpBand->rcBand.bottom = bottomy;
-	    lpBand->uMinHeight = lpBand->lcy;
-	    y = bottomy;
-	}
-	else {
-	    /* bound the right side if we have a bounding rectangle */
-	    rightx = (lpRect) ? min(clientcx, x+cxsep+cx) : x+cxsep+cx;
-	    bottomy = clientcy;
-	    lpBand->rcBand.left   = min(rightx, x + cxsep);
-	    lpBand->rcBand.right  = rightx;
-	    lpBand->rcBand.top    = y;
-	    lpBand->rcBand.bottom = y + min(mcy,
-					    lpBand->lcy+REBARSPACE(lpBand));
-	    lpBand->uMinHeight = lpBand->lcy;
-	    x = rightx;
-	}
-	TRACE("P1 band %u, row %d, (%d,%d)-(%d,%d)\n",
-	      i, row,
-	      lpBand->rcBand.left, lpBand->rcBand.top,
-	      lpBand->rcBand.right, lpBand->rcBand.bottom);
-	prevBand = lpBand;
-	cntonrow++;
+            iLastBand = iBand;
+    }
+    return iLastBand;
+}
 
-    } /* for (i = 0; i < infoPtr->uNumBands... */
+static int get_row_end_for_band(REBAR_INFO *infoPtr, INT iBand)
+{
+    int iRow = infoPtr->bands[iBand].iRow;
+    while ((iBand = next_band(infoPtr, iBand)) < infoPtr->uNumBands)
+        if (infoPtr->bands[iBand].iRow != iRow)
+            break;
+    return iBand;
+}
 
-    if (infoPtr->dwStyle & CCS_VERT)
-        x += mcy;
-    else
-        y += mcy;
+static void REBAR_SetRowRectsX(REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand)
+{
+    int xPos = 0, i;
+    for (i = iBeginBand; i < iEndBand; i = next_band(infoPtr, i))
+    {
+        REBAR_BAND *lpBand = &infoPtr->bands[i];
 
-    for (j = rowstart; j < infoPtr->uNumBands; j++) {
-	lpBand = &infoPtr->bands[j];
-	if (infoPtr->dwStyle & CCS_VERT) {
-	    lpBand->rcBand.right  = lpBand->rcBand.left + mcy;
-	}
-	else {
-	    lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
-	}
+        lpBand = &infoPtr->bands[i];
+        if (lpBand->rcBand.left != xPos || lpBand->rcBand.right != xPos + lpBand->cxEffective) {
+            lpBand->fDraw |= NTF_INVALIDATE;
+            TRACE("Setting rect %d to %d,%d\n", i, xPos, xPos + lpBand->cxEffective);
+            lpBand->rcBand.left = xPos;
+            lpBand->rcBand.right = xPos + lpBand->cxEffective;
+        }
+        xPos += lpBand->cxEffective + SEP_WIDTH;
     }
+}
 
-    if (infoPtr->uNumBands)
-        infoPtr->uNumRows = row + 1;
+/* The rationale of this function is probably as follows: if we have some space
+ * to distribute we want to add it to a band on the right. However we don't want
+ * to unminimize a minimized band so we search for a band that is big enough.
+ * For some reason "big enough" is defined as bigger than the minimum size of the
+ * first band in the row
+ */
+static REBAR_BAND *REBAR_FindBandToGrow(REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand)
+{
+    INT iLcx = 0, i;
 
-    /* ******* End Phase 1 - all bands on row at minimum size ******* */
+    iLcx = infoPtr->bands[iBeginBand].lcx;
 
+    for (i = prev_band(infoPtr, iEndBand); i >= iBeginBand; i = prev_band(infoPtr, i))
+        if (infoPtr->bands[i].cxEffective > iLcx && !(infoPtr->bands[i].fStyle&RBBS_FIXEDSIZE))
+            break;
 
-    /* ******* Start Phase 1a - Adjust heights for RBS_VARHEIGHT off ******* */
+    if (i < iBeginBand)
+        for (i = prev_band(infoPtr, iEndBand); i >= iBeginBand; i = prev_band(infoPtr, i))
+            if (infoPtr->bands[i].lcx == iLcx)
+                break;
 
-    mmcy = 0;
-    if (!(infoPtr->dwStyle & RBS_VARHEIGHT)) {
-	INT xy;
+    TRACE("Extra space for row [%d..%d) should be added to band %d\n", iBeginBand, iEndBand, i);
+    return &infoPtr->bands[i];
+}
 
-	/* get the max height of all bands */
-	for (i=0; i<infoPtr->uNumBands; i++) {
-	    lpBand = &infoPtr->bands[i];
-	    if (HIDDENBAND(lpBand)) continue;
-	    if (infoPtr->dwStyle & CCS_VERT)
-		mmcy = max(mmcy, lpBand->rcBand.right - lpBand->rcBand.left);
-	    else
-		mmcy = max(mmcy, lpBand->rcBand.bottom - lpBand->rcBand.top);
-	}
+static int REBAR_ShrinkBandsRTL(REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT cxShrink, BOOL bEnforce)
+{
+    REBAR_BAND *lpBand;
+    INT width, i;
 
-	/* now adjust all rectangles by using the height found above */
-	xy = 0;
-	row = 0;
-	for (i=0; i<infoPtr->uNumBands; i++) {
-	    lpBand = &infoPtr->bands[i];
-	    if (HIDDENBAND(lpBand)) continue;
-	    if (lpBand->iRow != row)
-		xy += (mmcy + SEP_WIDTH);
-	    if (infoPtr->dwStyle & CCS_VERT) {
-		lpBand->rcBand.left = xy;
-		lpBand->rcBand.right = xy + mmcy;
-	    }
-	    else {
-		lpBand->rcBand.top = xy;
-		lpBand->rcBand.bottom = xy + mmcy;
-	    }
-	}
+    TRACE("Shrinking bands [%d..%d) by %d, right-to-left\n", iBeginBand, iEndBand, cxShrink);
+    for (i = prev_band(infoPtr, iEndBand); i >= iBeginBand; i = prev_band(infoPtr, i))
+    {
+        lpBand = &infoPtr->bands[i];
 
-	/* set the x/y values to the correct maximum */
-	if (infoPtr->dwStyle & CCS_VERT)
-	    x = xy + mmcy;
-	else
-	    y = xy + mmcy;
+        width = max(lpBand->cxEffective - cxShrink, (int)lpBand->lcx);
+        cxShrink -= lpBand->cxEffective - width;
+        lpBand->cxEffective = width;
+        if (bEnforce && lpBand->cx > lpBand->cxEffective)
+            lpBand->cx = lpBand->cxEffective;
+        if (cxShrink == 0)
+            break;
     }
-
-    /* ******* End Phase 1a - Adjust heights for RBS_VARHEIGHT off ******* */
+    return cxShrink;
+}
 
 
-    /* ******* Start Phase 2 - split rows till adjustment height full ******* */
+static int REBAR_ShrinkBandsLTR(REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT cxShrink, BOOL bEnforce)
+{
+    REBAR_BAND *lpBand;
+    INT width, i;
 
-    /* assumes that the following variables contain:                 */
-    /*   y/x       current height/width of all rows                  */
-    /* adjcy/adjcx adjustment height/width or 0 (as small as possible) */
-    if (lpRect && ((infoPtr->dwStyle & CCS_VERT) ? adjcx : adjcy)) {
-        INT i, prev_rh, new_rh, adj_rh, prev_idx, current_idx;
-	REBAR_BAND *prev, *current, *walk;
-	UINT j;
+    TRACE("Shrinking bands [%d..%d) by %d, left-to-right\n", iBeginBand, iEndBand, cxShrink);
+    for (i = iBeginBand; i < iEndBand; i = next_band(infoPtr, i))
+    {
+        lpBand = &infoPtr->bands[i];
 
-/* FIXME:  problem # 2 */
-	if (((infoPtr->dwStyle & CCS_VERT) ?
-#if PROBLEM2
-	     (x < adjcx) : (y < adjcy)
-#else
-	     (adjcx - x > 5) : (adjcy - y > 4)
-#endif
-	     ) &&
-	    (infoPtr->uNumBands > 1)) {
-	    for (i=(INT)infoPtr->uNumBands-2; i>=0; i--) {
-		TRACE("P2 adjcx=%d, adjcy=%d, x=%d, y=%d\n",
-		      adjcx, adjcy, x, y);
-
-		/* find the current band (starts at i+1) */
-		current = &infoPtr->bands[i+1];
-		current_idx = i+1;
-		while (HIDDENBAND(current)) {
-		    i--;
-		    if (i < 0) break; /* out of bands */
-		    current = &infoPtr->bands[i+1];
-		    current_idx = i+1;
-		}
-		if (i < 0) break; /* out of bands */
-
-		/* now find the prev band (starts at i) */
-	        prev = &infoPtr->bands[i];
-		prev_idx = i;
-		while (HIDDENBAND(prev)) {
-		    i--;
-		    if (i < 0) break; /* out of bands */
-		    prev = &infoPtr->bands[i];
-		    prev_idx = i;
-		}
-		if (i < 0) break; /* out of bands */
-
-		prev_rh = ircBw(prev);
-		if (prev->iRow == current->iRow) {
-		    new_rh = (infoPtr->dwStyle & RBS_VARHEIGHT) ?
-			current->lcy + REBARSPACE(current) :
-			mmcy;
-		    adj_rh = new_rh + SEP_WIDTH;
-		    infoPtr->uNumRows++;
-		    current->fDraw |= NTF_INVALIDATE;
-		    current->iRow++;
-		    if (infoPtr->dwStyle & CCS_VERT) {
-		        current->rcBand.top = inity;
-			current->rcBand.bottom = clientcy;
-			current->rcBand.left += (prev_rh + SEP_WIDTH);
-			current->rcBand.right = current->rcBand.left + new_rh;
-			x += adj_rh;
-		    }
-		    else {
-		        current->rcBand.left = initx;
-			current->rcBand.right = clientcx;
-			current->rcBand.top += (prev_rh + SEP_WIDTH);
-			current->rcBand.bottom = current->rcBand.top + new_rh;
-			y += adj_rh;
-		    }
-                    TRACE("P2 moving band %d to own row at (%d,%d)-(%d,%d)\n",
-			  current_idx,
-			  current->rcBand.left, current->rcBand.top,
-			  current->rcBand.right, current->rcBand.bottom);
-                    TRACE("P2 prev band %d at (%d,%d)-(%d,%d)\n",
-			  prev_idx,
-			  prev->rcBand.left, prev->rcBand.top,
-			  prev->rcBand.right, prev->rcBand.bottom);
-		    TRACE("P2 values: prev_rh=%d, new_rh=%d, adj_rh=%d\n",
-			  prev_rh, new_rh, adj_rh);
-		    /* for bands below current adjust row # and top/bottom */
-		    for (j = current_idx+1; j<infoPtr->uNumBands; j++) {
-		        walk = &infoPtr->bands[j];
-			if (HIDDENBAND(walk)) continue;
-			walk->fDraw |= NTF_INVALIDATE;
-			walk->iRow++;
-			if (infoPtr->dwStyle & CCS_VERT) {
-			    walk->rcBand.left += adj_rh;
-			    walk->rcBand.right += adj_rh;
-			}
-			else {
-			    walk->rcBand.top += adj_rh;
-			    walk->rcBand.bottom += adj_rh;
-			}
-		    }
-		    if ((infoPtr->dwStyle & CCS_VERT) ? (x >= adjcx) : (y >= adjcy))
-		        break; /* all done */
-		}
-	    }
-	}
+        width = max(lpBand->cxEffective - cxShrink, (int)lpBand->lcx);
+        cxShrink -= lpBand->cxEffective - width;
+        lpBand->cxEffective = width;
+        if (bEnforce)
+            lpBand->cx = lpBand->cxEffective;
+        if (cxShrink == 0)
+            break;
     }
+    return cxShrink;
+}
 
-    /* ******* End Phase 2 - split rows till adjustment height full ******* */
-
-
-    /* ******* Start Phase 2a - mark first and last band in each ******* */
+static int REBAR_SetBandsHeight(REBAR_INFO *infoPtr, INT iBeginBand, INT iEndBand, INT yStart)
+{
+    REBAR_BAND *lpBand;
+    int yMaxHeight = 0;
+    int yPos = yStart;
+    int row = infoPtr->bands[iBeginBand].iRow;
+    int i;
+    for (i = iBeginBand; i < iEndBand; i = next_band(infoPtr, i))
+    {
+        lpBand = &infoPtr->bands[i];
+        yMaxHeight = max(yMaxHeight, lpBand->lcy);
+    }
+    TRACE("Bands [%d; %d) height: %d\n", iBeginBand, iEndBand, yMaxHeight);
 
-    prevBand = NULL;
-    for (i = 0; i < infoPtr->uNumBands; i++) { 	 
-        lpBand = &infoPtr->bands[i]; 	 
-        if (HIDDENBAND(lpBand))
-            continue;
-        if( !prevBand ) {
-            lpBand->fDraw |= DRAW_FIRST_IN_ROW;
-            prevBand = lpBand;
+    for (i = iBeginBand; i < iEndBand; i = next_band(infoPtr, i))
+    {
+        lpBand = &infoPtr->bands[i];
+        /* we may be called for multiple rows if RBS_VARHEIGHT not set */
+        if (lpBand->iRow != row) {
+            yPos += yMaxHeight + SEP_WIDTH;
+            row = lpBand->iRow;
         }
-        else if( prevBand->iRow == lpBand->iRow )
-            prevBand = lpBand;
-        else {
-            prevBand->fDraw |= DRAW_LAST_IN_ROW;
-            lpBand->fDraw |= DRAW_FIRST_IN_ROW;
-            prevBand = lpBand;
+
+        if (lpBand->rcBand.top != yPos || lpBand->rcBand.bottom != yPos + yMaxHeight) {
+            lpBand->fDraw |= NTF_INVALIDATE;
+            lpBand->rcBand.top = yPos;
+            lpBand->rcBand.bottom = yPos + yMaxHeight;
+            TRACE("Band %d: %s\n", i, wine_dbgstr_rect(&lpBand->rcBand));
         }
     }
-    if( prevBand )
-        prevBand->fDraw |= DRAW_LAST_IN_ROW;
-
-    /* ******* End Phase 2a - mark first and last band in each ******* */
-
-
-    /* ******* Start Phase 2b - adjust all bands for height full ******* */
-    /* assumes that the following variables contain:                 */
-    /*   y/x     current height/width of all rows                    */
-    /*   clientcy/clientcx     height/width of client area           */
+    return yPos + yMaxHeight;
+}
 
-    if (((infoPtr->dwStyle & CCS_VERT) ? clientcx > x : clientcy > y) &&
-	infoPtr->uNumBands) {
-	INT diff, i;
-	UINT j;
+static void REBAR_LayoutRow(REBAR_INFO *infoPtr, int iBeginBand, int iEndBand, int cx, int *piRow, int *pyPos)
+{
+    REBAR_BAND *lpBand;
+    int i, extra;
+    int width = 0;
 
-	diff = (infoPtr->dwStyle & CCS_VERT) ? clientcx - x : clientcy - y;
+    TRACE("Adjusting row [%d;%d). Width: %d\n", iBeginBand, iEndBand, cx);
+    for (i = iBeginBand; i < iEndBand; i++)
+        infoPtr->bands[i].iRow = *piRow;
 
-        /* iterate backwards thru the rows */
-        for (i = infoPtr->uNumBands-1; i>=0; i--) {
-	    lpBand = &infoPtr->bands[i];
-	    if(HIDDENBAND(lpBand)) continue;
-
-	    /* if row has more than 1 band, ignore it */
-            if( !(lpBand->fDraw&DRAW_FIRST_IN_ROW) )
-                continue;
-            if( !(lpBand->fDraw&DRAW_LAST_IN_ROW) )
-                continue;
-
-            /* FIXME: this next line is wrong, but fixing it to be inverted causes IE's sidebars to be the wrong size */
-	    if (lpBand->fMask & RBBS_VARIABLEHEIGHT) continue;
-	    if (((INT)lpBand->cyMaxChild < 1) ||
-		((INT)lpBand->cyIntegral < 1)) {
-		if (lpBand->cyMaxChild + lpBand->cyIntegral == 0) continue;
-		ERR("P2b band %u RBBS_VARIABLEHEIGHT set but cyMax=%d, cyInt=%d\n",
-		    i, lpBand->cyMaxChild, lpBand->cyIntegral);
-		continue;
-	    }
-	    /* j is now the maximum height/width in the client area */
-	    j = ((diff / lpBand->cyIntegral) * lpBand->cyIntegral) +
-		ircBw(lpBand);
-	    if (j > lpBand->cyMaxChild + REBARSPACE(lpBand))
-		j = lpBand->cyMaxChild + REBARSPACE(lpBand);
-	    diff -= (j - ircBw(lpBand));
-	    if (infoPtr->dwStyle & CCS_VERT)
-		lpBand->rcBand.right = lpBand->rcBand.left + j;
-	    else
-		lpBand->rcBand.bottom = lpBand->rcBand.top + j;
-            TRACE("P2b band %d, row %d changed to (%d,%d)-(%d,%d)\n",
-		  i, lpBand->iRow,
-		  lpBand->rcBand.left, lpBand->rcBand.top,
-		  lpBand->rcBand.right, lpBand->rcBand.bottom);
-	    if (diff <= 0) break;
-	}
-	if (diff < 0) {
-	    ERR("P2b allocated more than available, diff=%d\n", diff);
-	    diff = 0;
-	}
-	if (infoPtr->dwStyle & CCS_VERT)
-	    x = clientcx - diff;
-	else
-	    y = clientcy - diff;
+    /* compute the extra space */
+    for (i = iBeginBand; i < iEndBand; i = next_band(infoPtr, i))
+    {
+        lpBand = &infoPtr->bands[i];
+        if (i > iBeginBand)
+            width += SEP_WIDTH;
+        lpBand->cxEffective = max(lpBand->lcx, lpBand->cx);
+        width += lpBand->cxEffective;
+    }
+
+    extra = cx - width;
+    TRACE("Extra space: %d\n", extra);
+    if (extra < 0) {
+        int ret = REBAR_ShrinkBandsRTL(infoPtr, iBeginBand, iEndBand, -extra, FALSE);
+        if (ret > 0 && next_band(infoPtr, iBeginBand) != iEndBand)  /* one band may be longer than expected... */
+            ERR("Error layouting row %d - couldn't shrink for %d pixels (%d total shrink)\n", *piRow, ret, -extra);
+    } else
+    if (extra > 0) {
+        lpBand = REBAR_FindBandToGrow(infoPtr, iBeginBand, iEndBand);
+        lpBand->cxEffective += extra;
+    }
+
+    REBAR_SetRowRectsX(infoPtr, iBeginBand, iEndBand);
+    if (infoPtr->dwStyle & RBS_VARHEIGHT)
+    {
+        if (*piRow > 0)
+            *pyPos += SEP_WIDTH;
+        *pyPos = REBAR_SetBandsHeight(infoPtr, iBeginBand, iEndBand, *pyPos);
     }
+    (*piRow)++;
+}
 
-    /* ******* End Phase 2b - adjust all bands for height full ******* */
-
-
-    /* ******* Start Phase 3 - adjust all bands for width full ******* */
-
-    if (infoPtr->uNumBands) {
-        int startband;
-
-	/* If RBS_BANDBORDERS set then indicate to draw bottom separator */
-	/* on all bands in all rows but last row.                        */
-	/* Also indicate to draw the right separator for each band in    */
-	/* each row but the rightmost band.                              */
-	if (infoPtr->dwStyle & RBS_BANDBORDERS) {
-
-            for (i=0; i<infoPtr->uNumBands; i++) {
-	        lpBand = &infoPtr->bands[i];
-		if (HIDDENBAND(lpBand))
-                    continue;
-
-                /* not righthand bands */
-                if( !(lpBand->fDraw & DRAW_LAST_IN_ROW) )
-		    lpBand->fDraw |= DRAW_RIGHTSEP;
+static VOID
+REBAR_Layout(REBAR_INFO *infoPtr, LPRECT lpRect, BOOL notify)
+{
+    REBAR_BAND *lpBand;
+    RECT rcAdj;
+    INT adjcx, adjcy, i;
+    INT rowstart = 0;
+    INT row = 0;
+    INT xMin, yPos;
+    INT cyTarget;
+    const INT yInit = 0;
 
-                /* not the last row */
-                if( lpBand->iRow != infoPtr->uNumRows )
-		    lpBand->fDraw |= DRAW_BOTTOMSEP;
-	    }
-	}
+    if (!(infoPtr->fStatus & BAND_NEEDS_LAYOUT)) {
+	TRACE("no layout done. No band changed.\n");
+	REBAR_DumpBand (infoPtr);
+	return;
+    }
 
-	/* Distribute the extra space on the horizontal and adjust  */
-	/* all bands in row to same height.                         */
-	mcy = 0;
-        startband = -1;
-        for (i=0; i<infoPtr->uNumBands; i++) {
+    infoPtr->fStatus &= ~BAND_NEEDS_LAYOUT;
+    if (!infoPtr->DoRedraw) infoPtr->fStatus |= BAND_NEEDS_REDRAW;
 
-            lpBand = &infoPtr->bands[i];
+    cyTarget = 0;
+    if (lpRect) {
+        rcAdj = *lpRect;
+        cyTarget = get_rect_cy(infoPtr, lpRect);
+    } else if (infoPtr->dwStyle & CCS_NORESIZE || GetParent(infoPtr->hwndSelf) == NULL)
+        GetClientRect(infoPtr->hwndSelf, &rcAdj);
+    else
+        GetClientRect(GetParent(infoPtr->hwndSelf), &rcAdj);
+    TRACE("adjustment rect is (%d,%d)-(%d,%d)\n", rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom);
 
-            if( lpBand->fDraw & DRAW_FIRST_IN_ROW )
-            {
-                startband = i;
-                mcy = 0;
-            }
+    adjcx = get_rect_cx(infoPtr, &rcAdj);
+    adjcy = get_rect_cy(infoPtr, &rcAdj);
 
-            if ( (mcy < ircBw(lpBand)) && !HIDDENBAND(lpBand) )
-                mcy = ircBw(lpBand);
+    if (infoPtr->uNumBands == 0) {
+        TRACE("No bands - setting size to (0,%d), vert: %lx\n", adjcx, infoPtr->dwStyle & CCS_VERT);
+        infoPtr->oldSize = infoPtr->calcSize;
+        infoPtr->calcSize.cx = adjcx;
+        infoPtr->calcSize.cy = 0;
+        swap_size_if_vert(infoPtr, &infoPtr->calcSize);
+        infoPtr->uNumRows = 0;
+        REBAR_ForceResize(infoPtr);
+        return;
+    }
+
+    yPos = yInit;
+    xMin = 0;
+    /* divide rows */
+    i = 0;
+    for (i = 0; i < infoPtr->uNumBands; i++)
+    {
+        lpBand = &infoPtr->bands[i];
+        if (HIDDENBAND(lpBand)) continue;
 
-            if( lpBand->fDraw & DRAW_LAST_IN_ROW )
-            {
-	        TRACE("P3 processing row %d, starting band %d, ending band %d\n",
-		      lpBand->iRow, startband, i);
-                if( startband < 0 )
-                    ERR("Last band %d with no first, row %d\n", i, lpBand->iRow);
-
-	        REBAR_AdjustBands (infoPtr, startband, i,
-			       (infoPtr->dwStyle & CCS_VERT) ?
-			       clientcy : clientcx, mcy);
-            }
-	}
+        if (i > rowstart && (lpBand->fStyle & RBBS_BREAK || xMin + lpBand->lcx > adjcx)) {
+            TRACE("%s break on band %d\n", (lpBand->fStyle & RBBS_BREAK ? "Hard" : "Soft"), i - 1);
+            REBAR_LayoutRow(infoPtr, rowstart, i, adjcx, &row, &yPos);
+            rowstart = i;
+            xMin = 0;
+        }
+        else
+            xMin += SEP_WIDTH;
 
-	/* Calculate the other rectangles in each band */
-	if (infoPtr->dwStyle & CCS_VERT) {
-	    REBAR_CalcVertBand (infoPtr, 0, infoPtr->uNumBands,
-				notify);
-	}
-	else {
-	    REBAR_CalcHorzBand (infoPtr, 0, infoPtr->uNumBands,
-				notify);
-	}
+        xMin += lpBand->lcx;
     }
+    REBAR_LayoutRow(infoPtr, rowstart, infoPtr->uNumBands, adjcx, &row, &yPos);
+
+    if (!(infoPtr->dwStyle & RBS_VARHEIGHT))
+        yPos = REBAR_SetBandsHeight(infoPtr, 0, infoPtr->uNumBands, yInit);
 
-    /* ******* End Phase 3 - adjust all bands for width full ******* */
+    infoPtr->uNumRows = row;
 
+    if (infoPtr->dwStyle & CCS_VERT)
+        REBAR_CalcVertBand(infoPtr, 0, infoPtr->uNumBands);
+    else
+        REBAR_CalcHorzBand(infoPtr, 0, infoPtr->uNumBands);
     /* now compute size of Rebar itself */
     infoPtr->oldSize = infoPtr->calcSize;
-    if (infoPtr->uNumBands == 0) {
-	/* we have no bands, so make size the size of client */
-	x = clientcx;
-	y = clientcy;
-    }
-    if (infoPtr->dwStyle & CCS_VERT) {
-        if( infoPtr->uNumBands != 0 && x < REBAR_MINSIZE )
-            x = REBAR_MINSIZE;
-	infoPtr->calcSize.cx = x;
-	infoPtr->calcSize.cy = clientcy;
-	TRACE("vert, notify=%d, x=%d, origheight=%d\n",
-	      notify, x, origheight);
-	if (notify && (x != origheight)) infoPtr->fStatus |= NTF_HGHTCHG;
-    }
-    else {
-        if( infoPtr->uNumBands != 0 && y < REBAR_MINSIZE )
-            y = REBAR_MINSIZE;
-	infoPtr->calcSize.cx = clientcx;
-	infoPtr->calcSize.cy = y;
-	TRACE("horz, notify=%d, y=%d, origheight=%d\n",
-	      notify, y, origheight);
-	if (notify && (y != origheight)) infoPtr->fStatus |= NTF_HGHTCHG;
-    }
 
-    REBAR_DumpBand (infoPtr);
+    infoPtr->calcSize.cx = adjcx;
+    infoPtr->calcSize.cy = yPos;
+    swap_size_if_vert(infoPtr, &infoPtr->calcSize);
+    if (infoPtr->calcSize.cx != infoPtr->oldSize.cx || infoPtr->calcSize.cy != infoPtr->oldSize.cy)
+        if (notify && (yPos != infoPtr->calcSize.cy)) infoPtr->fStatus |= NTF_HGHTCHG;
 
-    REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands);
+    TRACE("calcsize notify=%d, size=(%d, %d), origheight=(%d,%d)\n", notify,
+            infoPtr->calcSize.cx, infoPtr->calcSize.cy,
+	    infoPtr->oldSize.cx, infoPtr->oldSize.cy);
 
+    REBAR_DumpBand (infoPtr);
+    REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands);
     REBAR_ForceResize (infoPtr);
 }
 
@@ -1958,10 +1478,6 @@ REBAR_ValidateBand (REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
     lpBand->fStatus = 0;
     lpBand->lcx = 0;
     lpBand->lcy = 0;
-    lpBand->ccx = 0;
-    lpBand->ccy = 0;
-    lpBand->hcx = 0;
-    lpBand->hcy = 0;
 
     /* Data coming in from users into the cx... and cy... fields   */
     /* may be bad, just garbage, because the user never clears     */
@@ -1977,7 +1493,6 @@ REBAR_ValidateBand (REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
     if (lpBand->cyMinChild > 65535) lpBand->cyMinChild = 0;
     if (lpBand->cx         > 65535) lpBand->cx         = 0;
     if (lpBand->cyChild    > 65535) lpBand->cyChild    = 0;
-    if (lpBand->cyMaxChild > 65535) lpBand->cyMaxChild = 0;
     if (lpBand->cyIntegral > 65535) lpBand->cyIntegral = 0;
     if (lpBand->cxIdeal    > 65535) lpBand->cxIdeal    = 0;
     if (lpBand->cxHeader   > 65535) lpBand->cxHeader   = 0;
@@ -2057,38 +1572,18 @@ REBAR_ValidateBand (REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
 
 
     /* Now compute minimum size of child window */
-    lpBand->offChild.cx = 0;
-    lpBand->offChild.cy = 0;
     lpBand->lcy = textheight;
-    lpBand->ccy = lpBand->lcy;
-    if (lpBand->fMask & RBBIM_CHILDSIZE) {
-        lpBand->lcx = lpBand->cxMinChild;
-
+    if (lpBand->hwndChild != NULL) {
 	/* Set the .cy values for CHILDSIZE case */
-        lpBand->lcy = max(lpBand->lcy, lpBand->cyMinChild);
-	lpBand->ccy = lpBand->lcy;
-        lpBand->hcy = lpBand->lcy;
-        if (lpBand->cyMaxChild != 0xffffffff) {
-	    lpBand->hcy = lpBand->cyMaxChild;
-        }
-	if (lpBand->cyChild != 0xffffffff)
-	    lpBand->ccy = max (lpBand->cyChild, lpBand->lcy);
-
+        lpBand->lcy = max(lpBand->lcy, lpBand->cyChild + REBARSPACE(lpBand));
         TRACE("_CHILDSIZE\n");
     }
-    if (lpBand->fMask & RBBIM_SIZE) {
-        lpBand->hcx = max (lpBand->cx-lpBand->cxHeader, lpBand->lcx);
-        TRACE("_SIZE\n");
-    }
     else
-        lpBand->hcx = lpBand->lcx;
-    lpBand->ccx = lpBand->hcx;
-
-    /* make ->.cx include header size for _Layout */
-    lpBand->lcx += lpBand->cxHeader;
-    lpBand->ccx += lpBand->cxHeader;
-    lpBand->hcx += lpBand->cxHeader;
+        lpBand->lcy = max(lpBand->lcy, REBAR_NO_CHILD_HEIGHT);
 
+    lpBand->lcx = lpBand->cxMinChild + lpBand->cxHeader + REBAR_POST_CHILD;
+    if (lpBand->fStyle & RBBS_USECHEVRON && lpBand->cxMinChild < lpBand->cxIdeal)
+        lpBand->lcx += CHEVRON_WIDTH;
 }
 
 static BOOL
@@ -2158,15 +1653,17 @@ REBAR_CommonSetupBand(HWND hwnd, LPREBARBANDINFOW lprbbi, REBAR_BAND *lpBand)
     {
 	lpBand->cxMinChild = lprbbi->cxMinChild;
 	lpBand->cyMinChild = lprbbi->cyMinChild;
-	if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
-	    lpBand->cyChild    = lprbbi->cyChild;
+        /* These fields where added in WIN32_IE == 0x400 and are set only for RBBS_VARIABLEHEIGHT bands */
+        if (lprbbi->cbSize >= sizeof (REBARBANDINFOA) && (lprbbi->fStyle & RBBS_VARIABLEHEIGHT)) {
 	    lpBand->cyMaxChild = lprbbi->cyMaxChild;
-	    lpBand->cyIntegral = lprbbi->cyIntegral;
-	}
-	else { /* special case - these should be zeroed out since   */
-	       /* RBBIM_CHILDSIZE added these in WIN32_IE >= 0x0400 */
-	    lpBand->cyChild    = 0;
-	    lpBand->cyMaxChild = 0;
+            lpBand->cyIntegral = lprbbi->cyIntegral;
+
+            lpBand->cyChild = lpBand->cyMinChild;
+            round_child_height(lpBand, lprbbi->cyChild);  /* try to increase cyChild */
+        }
+	else {
+	    lpBand->cyChild    = lpBand->cyMinChild;
+	    lpBand->cyMaxChild = 0x7fffffff;
 	    lpBand->cyIntegral = 0;
 	}
         bChanged = TRUE;
@@ -2232,7 +1729,7 @@ REBAR_InternalEraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, REC
     UINT i;
     INT oldrow;
     HDC hdc = (HDC)wParam;
-    RECT rect, cr;
+    RECT cr;
     COLORREF old = CLR_NONE, new;
     HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
 
@@ -2240,15 +1737,17 @@ REBAR_InternalEraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, REC
 
     oldrow = -1;
     for(i=0; i<infoPtr->uNumBands; i++) {
+        RECT rcBand;
         lpBand = &infoPtr->bands[i];
 	if (HIDDENBAND(lpBand)) continue;
+        translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
 
 	/* draw band separator between rows */
 	if (lpBand->iRow != oldrow) {
 	    oldrow = lpBand->iRow;
-	    if (lpBand->fDraw & DRAW_BOTTOMSEP) {
+	    if (infoPtr->dwStyle & RBS_BANDBORDERS) {
 		RECT rcRowSep;
-		rcRowSep = lpBand->rcBand;
+		rcRowSep = rcBand;
 		if (infoPtr->dwStyle & CCS_VERT) {
 		    rcRowSep.right += SEP_WIDTH_SIZE;
 		    rcRowSep.bottom = infoPtr->calcSize.cy;
@@ -2272,18 +1771,20 @@ REBAR_InternalEraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, REC
 	}
 
 	/* draw band separator between bands in a row */
-	if (lpBand->fDraw & DRAW_RIGHTSEP) {
+        if (infoPtr->dwStyle & RBS_BANDBORDERS && lpBand->rcBand.left > 0) {
 	    RECT rcSep;
-	    rcSep = lpBand->rcBand;
+	    rcSep = rcBand;
 	    if (infoPtr->dwStyle & CCS_VERT) {
-		rcSep.bottom += SEP_WIDTH_SIZE;
+                rcSep.bottom = rcSep.top;
+		rcSep.top -= SEP_WIDTH_SIZE;
                 if (theme)
                     DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_BOTTOM, NULL);
                 else
 		    DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOM);
 	    }
 	    else {
-		rcSep.right += SEP_WIDTH_SIZE;
+                rcSep.right = rcSep.left;
+		rcSep.left -= SEP_WIDTH_SIZE;
                 if (theme)
                     DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_RIGHT, NULL);
                 else
@@ -2314,13 +1815,11 @@ REBAR_InternalEraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, REC
 #endif
 	}
 
-	rect = lpBand->rcBand;
-
         if (theme)
         {
             /* When themed, the background color is ignored (but not a 
              * background bitmap */
-            DrawThemeBackground (theme, hdc, 0, 0, &cr, &rect);
+            DrawThemeBackground (theme, hdc, 0, 0, &cr, &rcBand);
         }
         else
         {
@@ -2329,11 +1828,11 @@ REBAR_InternalEraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, REC
                   (lpBand->clrBack == CLR_NONE) ? "none" :
                     ((lpBand->clrBack == CLR_DEFAULT) ? "dft" : ""),
                   GetBkColor(hdc),
-                  lpBand->rcBand.left,lpBand->rcBand.top,
-                  lpBand->rcBand.right,lpBand->rcBand.bottom,
+                  rcBand.left,rcBand.top,
+                  rcBand.right,rcBand.bottom,
                   clip->left, clip->top,
                   clip->right, clip->bottom);
-            ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, 0);
+            ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &rcBand, NULL, 0, 0);
             if (lpBand->clrBack != CLR_NONE)
                 SetBkColor (hdc, old);
         }
@@ -2363,9 +1862,11 @@ REBAR_InternalHitTest (REBAR_INFO *infoPtr, const LPPOINT lpPt, UINT *pFlags, IN
 	else {
 	    /* somewhere inside */
 	    for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
+                RECT rcBand;
 		lpBand = &infoPtr->bands[iCount];
-		if (HIDDENBAND(lpBand)) continue;
-		if (PtInRect (&lpBand->rcBand, *lpPt)) {
+                translate_rect(infoPtr, &rcBand, &lpBand->rcBand);
+                if (HIDDENBAND(lpBand)) continue;
+		if (PtInRect (&rcBand, *lpPt)) {
 		    if (pBand)
 			*pBand = iCount;
 		    if (PtInRect (&lpBand->rcGripper, *lpPt)) {
@@ -2418,76 +1919,6 @@ REBAR_InternalHitTest (REBAR_INFO *infoPtr, const LPPOINT lpPt, UINT *pFlags, IN
     }
 }
 
-
-static INT
-REBAR_Shrink (REBAR_INFO *infoPtr, 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 = rcBw(band) - band->lcx;
-
-    /* now compute the Left End adjustment factor and Right End */
-    /* adjustment factor. They may be different if shrinking.   */
-    if (avail <= 0) {
-        /* if this band is not shrinkable, then just move it */
-        Leadjust = Readjust = movement;
-	ret = movement;
-    }
-    else {
-        if (movement < 0) {
-	    /* Drag to left */
-	    if (avail <= abs(movement)) {
-	        Readjust = movement;
-		Leadjust = movement + avail;
-		ret = Leadjust;
-	    }
-	    else {
-	        Readjust = movement;
-		Leadjust = 0;
-		ret = 0;
-	    }
-	}
-	else {
-	    /* Drag to right */
-	    if (avail <= abs(movement)) {
-	        Leadjust = movement;
-		Readjust = movement - avail;
-		ret = Readjust;
-	    }
-	    else {
-	        Leadjust = movement;
-		Readjust = 0;
-		ret = 0;
-	    }
-	}
-    }
-
-    /* Reasonability Check */
-    if (rcBlt(band) + Leadjust < 0) {
-        ERR("adjustment will fail, band %d: left=%d, right=%d, move=%d, rtn=%d\n",
-	    i, Leadjust, Readjust, movement, ret);
-    }
-
-    LEADJ(band, Leadjust);
-    READJ(band, Readjust);
-
-    TRACE("band %d:  left=%d, right=%d, move=%d, rtn=%d, rcBand=(%d,%d)-(%d,%d)\n",
-	  i, Leadjust, Readjust, movement, ret,
-	  band->rcBand.left, band->rcBand.top,
-	  band->rcBand.right, band->rcBand.bottom);
-    return ret;
-}
-
-
 static void
 REBAR_HandleLRDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
      /* Function:  This will implement the functionality of a     */
@@ -2497,14 +1928,11 @@ REBAR_HandleLRDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
      /*  **** FIXME Switching order of bands in a row not   ****  */
      /*  ****       yet implemented.                        ****  */
 {
-    REBAR_BAND *hitBand, *band, *mindBand, *maxdBand;
-    RECT newrect;
-    INT imindBand = -1, imaxdBand, ihitBand, i, movement;
-    INT RHeaderSum = 0, LHeaderSum = 0;
-    INT compress;
+    REBAR_BAND *hitBand;
+    INT iHitBand, iRowBegin, iRowEnd;
+    INT movement, xBand;
 
     /* on first significant mouse movement, issue notify */
-
     if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
 	if (REBAR_Notify_NMREBAR (infoPtr, -1, RBN_BEGINDRAG)) {
 	    /* Notify returned TRUE - abort drag */
@@ -2518,126 +1946,32 @@ REBAR_HandleLRDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
 	infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
     }
 
-    ihitBand = infoPtr->iGrabbedBand;
-    hitBand = &infoPtr->bands[ihitBand];
-    imaxdBand = ihitBand; /* to suppress warning message */
+    iHitBand = infoPtr->iGrabbedBand;
+    iRowBegin = get_row_begin_for_band(infoPtr, iHitBand);
+    iRowEnd = get_row_end_for_band(infoPtr, iHitBand);
+    hitBand = &infoPtr->bands[iHitBand];
 
-    /* find all the bands in the row of the one whose Gripper was seized */
-    for (i=0; i<infoPtr->uNumBands; i++) {
-        band = &infoPtr->bands[i];
-	if (HIDDENBAND(band)) continue;
-	if (band->iRow == hitBand->iRow) {
-	    imaxdBand = i;
-	    if (imindBand == -1) imindBand = i;
-	    /* minimum size of each band is size of header plus            */
-	    /* size of minimum child plus offset of child from header plus */
-	    /* one to separate each band.                                  */
-	    if (i < ihitBand)
-	        LHeaderSum += (band->lcx + SEP_WIDTH);
-	    else
-	        RHeaderSum += (band->lcx + SEP_WIDTH);
+    xBand = hitBand->rcBand.left;
+    movement = (infoPtr->dwStyle&CCS_VERT ? ptsmove->y : ptsmove->x)
+                    - (xBand + REBAR_PRE_GRIPPER - infoPtr->ihitoffset);
 
-	}
+    if (movement < 0) {
+        int cxLeft = REBAR_ShrinkBandsRTL(infoPtr, iRowBegin, iHitBand, -movement, TRUE);
+        hitBand->cxEffective += -movement - cxLeft;
+        hitBand->cx = hitBand->cxEffective;
+    } else if (movement > 0) {
+        int cxLeft = REBAR_ShrinkBandsLTR(infoPtr, iHitBand, iRowEnd, movement, TRUE);
+        REBAR_BAND *lpPrev = &infoPtr->bands[prev_band(infoPtr, iHitBand)];
+        lpPrev->cxEffective += movement - cxLeft;
+        lpPrev->cx = lpPrev->cxEffective;
     }
-    if (RHeaderSum) RHeaderSum -= SEP_WIDTH; /* no separator after last band */
-
-    mindBand = &infoPtr->bands[imindBand];
-    maxdBand = &infoPtr->bands[imaxdBand];
-
-    if (imindBand == imaxdBand) return; /* nothing to drag against */
-    if (imindBand == ihitBand) return; /* first band in row, can't drag */
-
-    /* limit movement to inside adjustable bands - Left */
-    if ( (ptsmove->x < mindBand->rcBand.left) ||
-	 (ptsmove->x > maxdBand->rcBand.right) ||
-	 (ptsmove->y < mindBand->rcBand.top) ||
-	 (ptsmove->y > maxdBand->rcBand.bottom))
-        return; /* should swap bands */
 
+    REBAR_SetRowRectsX(infoPtr, iRowBegin, iRowEnd);
     if (infoPtr->dwStyle & CCS_VERT)
-        movement = ptsmove->y - ((hitBand->rcBand.top+REBAR_PRE_GRIPPER) -
-			     infoPtr->ihitoffset);
+        REBAR_CalcVertBand(infoPtr, 0, infoPtr->uNumBands);
     else
-        movement = ptsmove->x - ((hitBand->rcBand.left+REBAR_PRE_GRIPPER) -
-			     infoPtr->ihitoffset);
-    infoPtr->dragNow = *ptsmove;
-
-    TRACE("before: movement=%d (%d,%d), imindBand=%d, ihitBand=%d, imaxdBand=%d, LSum=%d, RSum=%d\n",
-	  movement, ptsmove->x, ptsmove->y, imindBand, ihitBand,
-	  imaxdBand, LHeaderSum, RHeaderSum);
-    REBAR_DumpBand (infoPtr);
-
-    if (movement < 0) {
-
-        /* ***  Drag left/up *** */
-        compress = rcBlt(hitBand) - rcBlt(mindBand) -
-	           LHeaderSum;
-	if (compress < abs(movement)) {
-	    TRACE("limiting left drag, was %d changed to %d\n",
-		  movement, -compress);
-	    movement = -compress;
-	}
-
-        for (i=ihitBand; i>=imindBand; i--) {
-	    band = &infoPtr->bands[i];
-	    if (HIDDENBAND(band)) continue;
-	    if (i == ihitBand) {
-		LEADJ(band, movement);
-	    }
-	    else
-	        movement = REBAR_Shrink (infoPtr, band, movement, i);
-	    band->ccx = rcBw(band);
-	}
-    }
-    else {
-	BOOL first = TRUE;
-
-        /* ***  Drag right/down *** */
-        compress = rcBrb(maxdBand) - rcBlt(hitBand) -
-	           RHeaderSum;
-	if (compress < abs(movement)) {
-	    TRACE("limiting right drag, was %d changed to %d\n",
-		  movement, compress);
-	    movement = compress;
-	}
-        for (i=ihitBand-1; i<=imaxdBand; i++) {
-	    band = &infoPtr->bands[i];
-	    if (HIDDENBAND(band)) continue;
-	    if (first) {
-		first = FALSE;
-		READJ(band, movement);
-	    }
-	    else
-	        movement = REBAR_Shrink (infoPtr, band, movement, i);
-	    band->ccx = rcBw(band);
-	}
-    }
-
-    /* recompute all rectangles */
-    if (infoPtr->dwStyle & CCS_VERT) {
-	REBAR_CalcVertBand (infoPtr, imindBand, imaxdBand+1,
-			    FALSE);
-    }
-    else {
-	REBAR_CalcHorzBand (infoPtr, imindBand, imaxdBand+1,
-			    FALSE);
-    }
-
-    TRACE("bands after adjustment, see band # %d, %d\n",
-	  imindBand, imaxdBand);
-    REBAR_DumpBand (infoPtr);
-
-    SetRect (&newrect,
-	     mindBand->rcBand.left,
-	     mindBand->rcBand.top,
-	     maxdBand->rcBand.right,
-	     maxdBand->rcBand.bottom);
-
-    REBAR_MoveChildWindows (infoPtr, imindBand, imaxdBand+1);
-
-    InvalidateRect (infoPtr->hwndSelf, &newrect, TRUE);
-    UpdateWindow (infoPtr->hwndSelf);
-
+        REBAR_CalcHorzBand(infoPtr, 0, infoPtr->uNumBands);
+    REBAR_MoveChildWindows(infoPtr, iRowBegin, iRowEnd);
 }
 
 
@@ -2677,7 +2011,7 @@ REBAR_DeleteBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
     TRACE("setting NEEDS_LAYOUT\n");
     infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
     infoPtr->fStatus |= RESIZE_ANYHOW;
-    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
+    REBAR_Layout(infoPtr, NULL, TRUE);
 
     return TRUE;
 }
@@ -2779,7 +2113,9 @@ REBAR_GetBandInfoT(REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, BOOL bUnic
     if (lprbbi->fMask & RBBIM_CHILDSIZE) {
 	lprbbi->cxMinChild = lpBand->cxMinChild;
 	lprbbi->cyMinChild = lpBand->cyMinChild;
-	if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
+        /* to make tests pass we follow Windows behaviour and allow to read these fields only
+         * for RBBS_VARIABLEHEIGHTS bands */
+        if (lprbbi->cbSize >= sizeof (REBARBANDINFOA) && (lpBand->fStyle & RBBS_VARIABLEHEIGHT)) {
 	    lprbbi->cyChild    = lpBand->cyChild;
 	    lprbbi->cyMaxChild = lpBand->cyMaxChild;
 	    lprbbi->cyIntegral = lpBand->cyIntegral;
@@ -2882,12 +2218,13 @@ REBAR_GetRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
     LPRECT lprc = (LPRECT)lParam;
     REBAR_BAND *lpBand;
 
-    if ((iBand < 0) && ((UINT)iBand >= infoPtr->uNumBands))
+    if ((iBand < 0) || ((UINT)iBand >= infoPtr->uNumBands))
 	return FALSE;
     if (!lprc)
 	return FALSE;
 
     lpBand = &infoPtr->bands[iBand];
+    /* For CCS_VERT the coordintes will be swapped - like on Windows */
     CopyRect (lprc, &lpBand->rcBand);
 
     TRACE("band %d, (%d,%d)-(%d,%d)\n", iBand,
@@ -2918,10 +2255,7 @@ REBAR_GetRowHeight (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 	lpBand = &infoPtr->bands[i];
 	if (HIDDENBAND(lpBand)) continue;
 	if (lpBand->iRow != iRow) continue;
-	if (infoPtr->dwStyle & CCS_VERT)
-	    j = lpBand->rcBand.right - lpBand->rcBand.left;
-	else
-	    j = lpBand->rcBand.bottom - lpBand->rcBand.top;
+        j = lpBand->rcBand.bottom - lpBand->rcBand.top;
 	if (j > ret) ret = j;
     }
 
@@ -3051,7 +2385,7 @@ REBAR_InsertBandT(REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, BOOL bUnico
 
     REBAR_DumpBand (infoPtr);
 
-    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
+    REBAR_Layout(infoPtr, NULL, TRUE);
     InvalidateRect(infoPtr->hwndSelf, 0, TRUE);
 
     return TRUE;
@@ -3063,6 +2397,9 @@ REBAR_MaximizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 {
     REBAR_BAND *lpBand;
     UINT uBand = (UINT) wParam;
+    int iRowBegin, iRowEnd;
+    int cxDesired, extra, extraOrig;
+    int cxIdealBand;
 
     /* Validate */
     if ((infoPtr->uNumBands == 0) ||
@@ -3075,21 +2412,29 @@ REBAR_MaximizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 
     lpBand = &infoPtr->bands[uBand];
 
-    if (lParam && (lpBand->fMask & RBBIM_IDEALSIZE)) {
-	/* handle setting ideal size */
-	lpBand->ccx = lpBand->cxIdeal;
-    }
-    else {
-	/* handle setting to max */
-	FIXME("(uBand = %u fIdeal = %s) case not coded\n",
-	      (UINT)wParam, lParam ? "TRUE" : "FALSE");
-	return FALSE;
-    }
-
-    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
-    REBAR_Layout (infoPtr, 0, TRUE, TRUE);
-    InvalidateRect (infoPtr->hwndSelf, 0, TRUE);
+    cxIdealBand = lpBand->cxIdeal + lpBand->cxHeader + REBAR_POST_CHILD;
+    if (lParam && (lpBand->cxEffective < cxIdealBand))
+        cxDesired = cxIdealBand;
+    else
+        cxDesired = (infoPtr->dwStyle&CCS_VERT ? infoPtr->calcSize.cy : infoPtr->calcSize.cx);
+
+    iRowBegin = get_row_begin_for_band(infoPtr, uBand);
+    iRowEnd   = get_row_end_for_band(infoPtr, uBand);
+    extraOrig = extra = cxDesired - lpBand->cxEffective;
+    if (extra > 0)
+        extra = REBAR_ShrinkBandsRTL(infoPtr, iRowBegin, uBand, extra, TRUE);
+    if (extra > 0)
+        extra = REBAR_ShrinkBandsLTR(infoPtr, next_band(infoPtr, uBand), iRowEnd, extra, TRUE);
+    lpBand->cxEffective += extraOrig - extra;
+    lpBand->cx = lpBand->cxEffective;
+    TRACE("(%d, %ld): Wanted size %d, obtained %d (shrink %d, %d)\n", wParam, lParam, cxDesired, lpBand->cx, extraOrig, extra);
+    REBAR_SetRowRectsX(infoPtr, iRowBegin, iRowEnd);
 
+    if (infoPtr->dwStyle & CCS_VERT)
+        REBAR_CalcVertBand(infoPtr, iRowBegin, iRowEnd);
+    else
+        REBAR_CalcHorzBand(infoPtr, iRowBegin, iRowEnd);
+    REBAR_MoveChildWindows(infoPtr, iRowBegin, iRowEnd);
     return TRUE;
 
 }
@@ -3098,11 +2443,9 @@ REBAR_MaximizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 static LRESULT
 REBAR_MinimizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 {
-    REBAR_BAND *band, *lpBand;
+    REBAR_BAND *lpBand;
     UINT uBand = (UINT) wParam;
-    RECT newrect;
-    INT imindBand, imaxdBand, iprevBand, startBand, endBand;
-    INT movement, i;
+    int iPrev, iRowBegin, iRowEnd;
 
     /* A "minimize" band is equivalent to "dragging" the gripper
      * of than band to the right till the band is only the size
@@ -3120,110 +2463,32 @@ REBAR_MinimizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 
     /* compute amount of movement and validate */
     lpBand = &infoPtr->bands[uBand];
-
-    if (infoPtr->dwStyle & CCS_VERT)
-	movement = lpBand->rcBand.bottom - lpBand->rcBand.top -
-	    lpBand->cxHeader;
-    else
-	movement = lpBand->rcBand.right - lpBand->rcBand.left -
-	    lpBand->cxHeader;
-    if (movement < 0) {
-	ERR("something is wrong, band=(%d,%d)-(%d,%d), cxheader=%d\n",
-	    lpBand->rcBand.left, lpBand->rcBand.top,
-	    lpBand->rcBand.right, lpBand->rcBand.bottom,
-	    lpBand->cxHeader);
-	return FALSE;
-    }
-
-    imindBand = -1;
-    imaxdBand = -1;
-    iprevBand = -1; /* to suppress warning message */
-
-    /* find the first band in row of the one whose is being minimized */
-    for (i=0; i<infoPtr->uNumBands; i++) {
-        band = &infoPtr->bands[i];
-	if (HIDDENBAND(band)) continue;
-	if (band->iRow == lpBand->iRow) {
-	    imaxdBand = i;
-	    if (imindBand == -1) imindBand = i;
-	}
-    }
-
-    /* if the selected band is first in row then need to expand */
-    /* next visible band                                        */
-    if (imindBand == uBand) {
-	band = NULL;
-	movement = -movement;
-	/* find the first visible band to the right of the selected band */
-	for (i=uBand+1; i<=imaxdBand; i++) {
-	    band = &infoPtr->bands[i];
-	    if (!HIDDENBAND(band)) {
-		iprevBand = i;
-		LEADJ(band, movement);
-		band->ccx = rcBw(band);
-		break;
-	    }
-	}
-	/* what case is this */
-	if (iprevBand == -1) {
-	    ERR("no previous visible band\n");
-	    return FALSE;
-	}
-	startBand = uBand;
-	endBand = iprevBand;
-	SetRect (&newrect,
-		 lpBand->rcBand.left,
-		 lpBand->rcBand.top,
-		 band->rcBand.right,
-		 band->rcBand.bottom);
-    }
-    /* otherwise expand previous visible band                   */
-    else {
-	band = NULL;
-	/* find the first visible band to the left of the selected band */
-	for (i=uBand-1; i>=imindBand; i--) {
-	    band = &infoPtr->bands[i];
-	    if (!HIDDENBAND(band)) {
-		iprevBand = i;
-		READJ(band, movement);
-		band->ccx = rcBw(band);
-		break;
-	    }
-	}
-	/* what case is this */
-	if (iprevBand == -1) {
-	    ERR("no previous visible band\n");
-	    return FALSE;
-	}
-	startBand = iprevBand;
-	endBand = uBand;
-	SetRect (&newrect,
-		 band->rcBand.left,
-		 band->rcBand.top,
-		 lpBand->rcBand.right,
-		 lpBand->rcBand.bottom);
-    }
-
-    REBAR_Shrink (infoPtr, lpBand, movement, uBand);
-
-    /* recompute all rectangles */
-    if (infoPtr->dwStyle & CCS_VERT) {
-	REBAR_CalcVertBand (infoPtr, startBand, endBand+1,
-			    FALSE);
-    }
-    else {
-	REBAR_CalcHorzBand (infoPtr, startBand, endBand+1,
-			    FALSE);
+    iPrev = prev_band(infoPtr, uBand);
+    /* if first band in row */
+    if (iPrev < 0 || infoPtr->bands[iPrev].iRow != lpBand->iRow) {
+        int iNext = next_band(infoPtr, uBand);
+        if (iNext < infoPtr->uNumBands && infoPtr->bands[iNext].iRow == lpBand->iRow) {
+            TRACE("(%d): Minimizing the first band in row is by maximizing the second\n", wParam);
+            REBAR_MaximizeBand(infoPtr, iNext, FALSE);
+        }
+        else
+            TRACE("(%d): Only one band in row - nothing to do\n", wParam);
+        return TRUE;
     }
 
-    TRACE("bands after minimize, see band # %d, %d\n",
-	  startBand, endBand);
-    REBAR_DumpBand (infoPtr);
+    infoPtr->bands[iPrev].cxEffective += lpBand->cxEffective - lpBand->lcx;
+    infoPtr->bands[iPrev].cx = infoPtr->bands[iPrev].cxEffective;
+    lpBand->cx = lpBand->cxEffective = lpBand->lcx;
 
-    REBAR_MoveChildWindows (infoPtr, startBand, endBand+1);
+    iRowBegin = get_row_begin_for_band(infoPtr, uBand);
+    iRowEnd = get_row_end_for_band(infoPtr, uBand);
+    REBAR_SetRowRectsX(infoPtr, iRowBegin, iRowEnd);
 
-    InvalidateRect (infoPtr->hwndSelf, &newrect, TRUE);
-    UpdateWindow (infoPtr->hwndSelf);
+    if (infoPtr->dwStyle & CCS_VERT)
+        REBAR_CalcVertBand(infoPtr, iRowBegin, iRowEnd);
+    else
+        REBAR_CalcHorzBand(infoPtr, iRowBegin, iRowEnd);
+    REBAR_MoveChildWindows(infoPtr, iRowBegin, iRowEnd);
     return FALSE;
 }
 
@@ -3341,8 +2606,8 @@ REBAR_SetBandInfoT(REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, BOOL bUnic
 
     REBAR_DumpBand (infoPtr);
 
-    if (bChanged && (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE))) {
-	  REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
+    if (bChanged && (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE))) {
+	  REBAR_Layout(infoPtr, NULL, TRUE);
 	  InvalidateRect(infoPtr->hwndSelf, 0, 1);
     }
 
@@ -3492,7 +2757,7 @@ REBAR_ShowBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
     }
 
     infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
-    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
+    REBAR_Layout(infoPtr, NULL, TRUE);
     InvalidateRect(infoPtr->hwndSelf, 0, 1);
 
     return TRUE;
@@ -3522,7 +2787,7 @@ REBAR_SizeToRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
     /* force full _Layout processing */
     TRACE("setting NEEDS_LAYOUT\n");
     infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
-    REBAR_Layout (infoPtr, lpRect, TRUE, FALSE);
+    REBAR_Layout(infoPtr, lpRect, TRUE);
     InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
     return TRUE;
 }
@@ -3678,9 +2943,9 @@ REBAR_LButtonDown (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
         infoPtr->dragStart.y = (short)HIWORD(lParam);
         infoPtr->dragNow = infoPtr->dragStart;
         if (infoPtr->dwStyle & CCS_VERT)
-            infoPtr->ihitoffset = infoPtr->dragStart.y - (lpBand->rcBand.top+REBAR_PRE_GRIPPER);
+            infoPtr->ihitoffset = infoPtr->dragStart.y - (lpBand->rcBand.left + REBAR_PRE_GRIPPER);
         else
-            infoPtr->ihitoffset = infoPtr->dragStart.x - (lpBand->rcBand.left+REBAR_PRE_GRIPPER);
+            infoPtr->ihitoffset = infoPtr->dragStart.x - (lpBand->rcBand.left + REBAR_PRE_GRIPPER);
     }
     return 0;
 }
@@ -3745,6 +3010,7 @@ REBAR_MouseMove (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
     if (infoPtr->iGrabbedBand >= 0)
     {
         REBAR_BAND *band1, *band2;
+        int yPtMove = (infoPtr->dwStyle & CCS_VERT ? ptMove.x : ptMove.y);
     
         if (GetCapture() != infoPtr->hwndSelf)
             ERR("We are dragging but haven't got capture?!?\n");
@@ -3757,25 +3023,13 @@ REBAR_MouseMove (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
             (abs(ptMove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
 
         /* Test for valid drag case - must not be first band in row */
-        if (infoPtr->dwStyle & CCS_VERT) {
-            if ((ptMove.x < band2->rcBand.left) ||
-	      (ptMove.x > band2->rcBand.right) ||
+        if ((yPtMove < band2->rcBand.top) ||
+	      (yPtMove > band2->rcBand.bottom) ||
               ((infoPtr->iGrabbedBand > 0) && (band1->iRow != band2->iRow))) {
-                FIXME("Cannot drag to other rows yet!!\n");
-            }
-            else {
-                REBAR_HandleLRDrag (infoPtr, &ptMove);
-            }
+            FIXME("Cannot drag to other rows yet!!\n");
         }
         else {
-            if ((ptMove.y < band2->rcBand.top) ||
-              (ptMove.y > band2->rcBand.bottom) ||
-              ((infoPtr->iGrabbedBand > 0) && (band1->iRow != band2->iRow))) {
-                FIXME("Cannot drag to other rows yet!!\n");
-            }
-            else {
-                REBAR_HandleLRDrag (infoPtr, &ptMove);
-            }
+            REBAR_HandleLRDrag (infoPtr, &ptMove);
         }
     }
     else
@@ -4114,7 +3368,7 @@ REBAR_SetFont (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 
     if (LOWORD(lParam)) {
         GetClientRect (infoPtr->hwndSelf, &rcClient);
-        REBAR_Layout (infoPtr, &rcClient, FALSE, TRUE);
+        REBAR_Layout(infoPtr, &rcClient, FALSE);
     }
 
     return 0;
@@ -4203,6 +3457,9 @@ REBAR_Size (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 		  LOWORD(lParam), HIWORD(lParam),
 		  rcClient.right, rcClient.bottom);
 	}
+        infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
+        REBAR_Layout(infoPtr, &rcClient, TRUE);
+        return 0;
     }
     else {
 	if ((INT)wParam != SIZE_RESTORED) {
@@ -4245,11 +3502,11 @@ REBAR_Size (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 	      autosize.rcTarget.right, autosize.rcTarget.bottom, lParam);
     }
 
-    if ((infoPtr->calcSize.cx != rcClient.right) ||
-	(infoPtr->calcSize.cy != rcClient.bottom))
-	infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
-
-    REBAR_Layout (infoPtr, &rcClient, TRUE, TRUE);
+    if (((infoPtr->calcSize.cx != rcClient.right) || (infoPtr->calcSize.cy != rcClient.bottom)))
+    {
+        infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
+        REBAR_Layout(infoPtr, &rcClient, TRUE);
+    }
 
     return 0;
 }
@@ -4259,12 +3516,18 @@ static LRESULT
 REBAR_StyleChanged (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 {
     STYLESTRUCT *ss = (STYLESTRUCT *)lParam;
-
+    
     TRACE("current style=%08x, styleOld=%08x, style being set to=%08x\n",
 	  infoPtr->dwStyle, ss->styleOld, ss->styleNew);
     infoPtr->orgStyle = infoPtr->dwStyle = ss->styleNew;
     if (GetWindowTheme (infoPtr->hwndSelf))
         infoPtr->dwStyle &= ~WS_BORDER;
+    /* maybe it should be COMMON_STYLES like in toolbar */
+    if ((ss->styleNew ^ ss->styleOld) & CCS_VERT)
+    {
+        infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
+        REBAR_Layout(infoPtr, NULL, TRUE);
+    }
 
     return FALSE;
 }
diff --git a/dlls/comctl32/tests/rebar.c b/dlls/comctl32/tests/rebar.c
index 23497ef..2633dcb 100644
--- a/dlls/comctl32/tests/rebar.c
+++ b/dlls/comctl32/tests/rebar.c
@@ -29,6 +29,13 @@
 static HWND hMainWnd;
 static HWND hRebar;
 
+
+#define check_rect(name, val, exp) ok(val.top == exp.top && val.bottom == exp.bottom && \
+    val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d)\n", \
+    val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom);
+ 
+#define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
+
 #define expect_eq(expr, value, type, format) { type ret = expr; ok((value) == ret, #expr " expected " format "  got " format "\n", (value), (ret)); }
 
 static void rebuild_rebar(HWND *hRebar)
@@ -41,15 +48,390 @@ static void rebuild_rebar(HWND *hRebar)
     SendMessageA(*hRebar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
 }
 
+static HWND build_toolbar(int nr, HWND hParent)
+{
+    TBBUTTON btns[8];
+    HWND hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_NORESIZE, 0, 0, 0, 0,
+        hParent, (HMENU)5, GetModuleHandle(NULL), NULL);
+    int iBitmapId = 0;
+    int i;
+
+    ok(hToolbar != NULL, "Toolbar creation problem\n");
+    ok(SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
+    ok(SendMessage(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
+    ok(SendMessage(hToolbar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0)==1, "WM_SETFONT\n");
+
+    for (i=0; i<5+nr; i++)
+    {
+        btns[i].iBitmap = i;
+        btns[i].idCommand = i;
+        btns[i].fsStyle = BTNS_BUTTON;
+        btns[i].fsState = TBSTATE_ENABLED;
+    }
+
+    switch (nr)
+    {
+        case 0: iBitmapId = IDB_HIST_SMALL_COLOR; break;
+        case 1: iBitmapId = IDB_VIEW_SMALL_COLOR; break;
+        case 2: iBitmapId = IDB_STD_SMALL_COLOR; break;
+    }
+    ok(SendMessage(hToolbar, TB_LOADIMAGES, iBitmapId, (LPARAM)HINST_COMMCTRL) == 0, "TB_LOADIMAGE failed\n");
+    ok(SendMessage(hToolbar, TB_ADDBUTTONS, 5+nr, (LPARAM)btns), "TB_ADDBUTTONS failed\n");
+    return hToolbar;
+}
+
 static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
     return DefWindowProcA(hWnd, msg, wParam, lParam);
 }
 
+#if 0  /* use this to generate more tests*/
+
+static void dump_sizes(HWND hRebar)
+{
+    SIZE sz;
+    RECT r;
+    int count;
+    int i, h;
+
+    GetClientRect(hRebar, &r);
+    count = SendMessageA(hRebar, RB_GETROWCOUNT, 0, 0);
+    printf("  { {%d, %d, %d, %d}, %d, %d, {", r.left, r.top, r.right, r.bottom,
+        SendMessageA(hRebar, RB_GETBARHEIGHT, 0, 0), count);
+    if (count == 0)
+        printf("0, ");
+    for (i = 0; i < count; i++)  /* rows */
+        printf("%d, ", SendMessageA(hRebar, RB_GETROWHEIGHT, i, 0));
+    printf("}, ");
+
+    count = SendMessageA(hRebar, RB_GETBANDCOUNT, 0, 0);
+    printf("%d, {", count);
+    if (count == 0)
+        printf("{{0, 0, 0, 0}, 0, 0},");
+    for (i=0; i<count; i++)
+    {
+        REBARBANDINFO rbi;
+        rbi.cbSize = sizeof(REBARBANDINFO);
+        rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE;
+        ok(SendMessageA(hRebar, RB_GETBANDINFOA, i, (LPARAM)&rbi), "RB_GETBANDINFO failed\n");
+        ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&r), "RB_GETRECT failed\n");
+        printf("%s{ {%3d, %3d, %3d, %3d}, 0x%02x, %d}, ", (i%2==0 ? "\n    " : ""), r.left, r.top, r.right, r.bottom,
+            rbi.fStyle, rbi.cx);
+    }
+    printf("\n  }, }, \n");
+}
+
+#define check_sizes() dump_sizes(hRebar);
+#define check_sizes_todo(todomask) dump_sizes(hRebar);
+
+#else
+
+typedef struct {
+    RECT rc;
+    DWORD fStyle;
+    INT cx;
+} rbband_result_t;
+
+typedef struct {
+    RECT rcClient;
+    int cyBarHeight;
+    int nRows;
+    int cyRowHeights[50];
+    int nBands;
+    rbband_result_t bands[50];
+} rbsize_result_t;
+
+rbsize_result_t rbsize_results[] = {
+  { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
+  }, },
+  { {0, 0, 672, 4}, 4, 1, {4, }, 1, {
+    { {  0,   0, 672,   4}, 0x00, 200},
+  }, },
+  { {0, 0, 672, 4}, 4, 1, {4, }, 2, {
+    { {  0,   0, 200,   4}, 0x00, 200}, { {200,   0, 672,   4}, 0x04, 200},
+  }, },
+  { {0, 0, 672, 30}, 30, 1, {30, }, 3, {
+    { {  0,   0, 200,  30}, 0x00, 200}, { {200,   0, 400,  30}, 0x04, 200},
+    { {400,   0, 672,  30}, 0x00, 200},
+  }, },
+  { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
+    { {  0,   0, 200,  34}, 0x00, 200}, { {200,   0, 400,  34}, 0x04, 200},
+    { {400,   0, 604,  34}, 0x00, 200}, { {604,   0, 672,  34}, 0x04, 68},
+  }, },
+  { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
+    { {  0,   0, 200,  34}, 0x00, 200}, { {200,   0, 400,  34}, 0x04, 200},
+    { {400,   0, 604,  34}, 0x00, 200}, { {604,   0, 672,  34}, 0x04, 68},
+  }, },
+  { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
+    { {  0,   0, 200,  34}, 0x00, 200}, { {202,   0, 402,  34}, 0x04, 200},
+    { {404,   0, 604,  34}, 0x00, 200}, { {606,   0, 672,  34}, 0x04, 66},
+  }, },
+  { {0, 0, 672, 70}, 70, 2, {34, 34, }, 5, {
+    { {  0,   0, 142,  34}, 0x00, 200}, { {144,   0, 557,  34}, 0x00, 200},
+    { {559,   0, 672,  34}, 0x04, 200}, { {  0,  36, 200,  70}, 0x00, 200},
+    { {202,  36, 672,  70}, 0x04, 66},
+  }, },
+  { {0, 0, 672, 34}, 34, 1, {34, }, 5, {
+    { {  0,   0, 167,  34}, 0x00, 200}, { {169,   0, 582,  34}, 0x00, 200},
+    { {559,   0, 759,  34}, 0x08, 200}, { {584,   0, 627,  34}, 0x00, 200},
+    { {629,   0, 672,  34}, 0x04, 66},
+  }, },
+  { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
+    { {  0,   0, 167,  34}, 0x00, 200}, { {169,   0, 582,  34}, 0x00, 200},
+    { {584,   0, 627,  34}, 0x00, 200}, { {629,   0, 672,  34}, 0x04, 66},
+  }, },
+  { {0, 0, 672, 34}, 34, 1, {34, }, 3, {
+    { {  0,   0, 413,  34}, 0x00, 200}, { {415,   0, 615,  34}, 0x00, 200},
+    { {617,   0, 672,  34}, 0x04, 66},
+  }, },
+  { {0, 0, 672, 34}, 34, 1, {34, }, 2, {
+    { {  0,   0, 604,  34}, 0x00, 200}, { {606,   0, 672,  34}, 0x04, 66},
+  }, },
+  { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+    { {  0,   0, 114,  20}, 0x00, 40}, { {114,   0, 184,  20}, 0x00, 70},
+    { {184,   0, 424,  20}, 0x00, 240}, { {424,   0, 672,  20}, 0x00, 60},
+    { {  0,  20, 672,  40}, 0x00, 200},
+  }, },
+  { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+    { {  0,   0, 114,  20}, 0x00, 40}, { {114,   0, 227,  20}, 0x00, 113},
+    { {227,   0, 424,  20}, 0x00, 197}, { {424,   0, 672,  20}, 0x00, 60},
+    { {  0,  20, 672,  40}, 0x00, 200},
+  }, },
+  { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+    { {  0,   0, 114,  20}, 0x00, 40}, { {114,   0, 328,  20}, 0x00, 214},
+    { {328,   0, 511,  20}, 0x00, 183}, { {511,   0, 672,  20}, 0x00, 161},
+    { {  0,  20, 672,  40}, 0x00, 200},
+  }, },
+  { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+    { {  0,   0, 114,  20}, 0x00, 40}, { {114,   0, 167,  20}, 0x00, 53},
+    { {167,   0, 511,  20}, 0x00, 344}, { {511,   0, 672,  20}, 0x00, 161},
+    { {  0,  20, 672,  40}, 0x00, 200},
+  }, },
+  { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+    { {  0,   0, 114,  20}, 0x00, 40}, { {114,   0, 328,  20}, 0x00, 214},
+    { {328,   0, 511,  20}, 0x00, 183}, { {511,   0, 672,  20}, 0x00, 161},
+    { {  0,  20, 672,  40}, 0x00, 200},
+  }, },
+  { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+    { {  0,   0, 114,  20}, 0x00, 40}, { {114,   0, 328,  20}, 0x00, 214},
+    { {328,   0, 511,  20}, 0x00, 183}, { {511,   0, 672,  20}, 0x00, 161},
+    { {  0,  20, 672,  40}, 0x00, 200},
+  }, },
+  { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
+  }, },
+  { {0, 0, 672, 65}, 65, 1, {65, }, 3, {
+    { {  0,   0,  90,  65}, 0x40, 90}, { { 90,   0, 180,  65}, 0x40, 90},
+    { {180,   0, 672,  65}, 0x40, 90},
+  }, },
+  { {0, 0, 0, 226}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
+  }, },
+  { {0, 0, 65, 226}, 65, 1, {65, }, 1, {
+    { {  0,   0, 226,  65}, 0x40, 90},
+  }, },
+  { {0, 0, 65, 226}, 65, 1, {65, }, 2, {
+    { {  0,   0,  90,  65}, 0x40, 90}, { { 90,   0, 226,  65}, 0x40, 90},
+  }, },
+  { {0, 0, 65, 226}, 65, 1, {65, }, 3, {
+    { {  0,   0,  90,  65}, 0x40, 90}, { { 90,   0, 163,  65}, 0x40, 90},
+    { {163,   0, 226,  65}, 0x40, 90},
+  }, },
+};
+
+static int rbsize_numtests = 0;
+
+#define check_sizes_todo(todomask) { \
+        RECT rc; \
+        REBARBANDINFO rbi; \
+        int count, i/*, mask=(todomask)*/; \
+        rbsize_result_t *res = &rbsize_results[rbsize_numtests]; \
+        assert(rbsize_numtests < sizeof(rbsize_results)/sizeof(rbsize_results[0])); \
+        GetClientRect(hRebar, &rc); \
+        check_rect("client", rc, res->rcClient); \
+        count = SendMessage(hRebar, RB_GETROWCOUNT, 0, 0); \
+        compare(count, res->nRows, "%d"); \
+        for (i=0; i<min(count, res->nRows); i++) { \
+            int height = SendMessageA(hRebar, RB_GETROWHEIGHT, 0, 0);\
+            ok(height == res->cyRowHeights[i], "Height mismatch for row %d - %d vs %d\n", i, res->cyRowHeights[i], height); \
+        } \
+        count = SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0); \
+        compare(count, res->nBands, "%d"); \
+        for (i=0; i<min(count, res->nBands); i++) { \
+            ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_ITEMRECT\n"); \
+            if (!(res->bands[i].fStyle & RBBS_HIDDEN)) \
+                check_rect("band", rc, res->bands[i].rc); \
+            rbi.cbSize = sizeof(REBARBANDINFO); \
+            rbi.fMask = RBBIM_STYLE | RBBIM_SIZE; \
+            ok(SendMessageA(hRebar, RB_GETBANDINFO,  i, (LPARAM)&rbi) == 1, "RB_GETBANDINFO\n"); \
+            compare(rbi.fStyle, res->bands[i].fStyle, "%x"); \
+            compare(rbi.cx, res->bands[i].cx, "%d"); \
+        } \
+        rbsize_numtests++; \
+    }
+
+#define check_sizes() check_sizes_todo(0)
+
+#endif
+
+static void add_band_w(HWND hRebar, LPCSTR lpszText, int cxMinChild, int cx, int cxIdeal)
+{
+    CHAR buffer[MAX_PATH];
+    REBARBANDINFO rbi;
+
+    if (lpszText != NULL)
+        strcpy(buffer, lpszText);
+    rbi.cbSize = sizeof(rbi);
+    rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_TEXT;
+    rbi.cx = cx;
+    rbi.cxMinChild = cxMinChild;
+    rbi.cxIdeal = cxIdeal;
+    rbi.cyMinChild = 20;
+    rbi.hwndChild = build_toolbar(1, hRebar);
+    rbi.lpText = (lpszText ? buffer : NULL);
+    SendMessage(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+}
+
+static void layout_test()
+{
+    HWND hRebar = NULL;
+    REBARBANDINFO rbi;
+
+    rebuild_rebar(&hRebar);
+    check_sizes();
+    rbi.cbSize = sizeof(rbi);
+    rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
+    rbi.cx = 200;
+    rbi.cxMinChild = 100;
+    rbi.cyMinChild = 30;
+    rbi.hwndChild = NULL;
+    SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+    check_sizes();
+
+    rbi.fMask |= RBBIM_STYLE;
+    rbi.fStyle = RBBS_CHILDEDGE;
+    SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+    check_sizes();
+
+    rbi.fStyle = 0;
+    rbi.cx = 200;
+    rbi.cxMinChild = 30;
+    rbi.cyMinChild = 30;
+    rbi.hwndChild = build_toolbar(0, hRebar);
+    SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+    check_sizes();
+
+    rbi.fStyle = RBBS_CHILDEDGE;
+    rbi.cx = 68;
+    rbi.hwndChild = build_toolbar(0, hRebar);
+    SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+    check_sizes();
+
+    SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_BANDBORDERS);
+    check_sizes();      /* a style change won't start a relayout */
+    rbi.fMask = RBBIM_SIZE;
+    rbi.cx = 66;
+    SendMessageA(hRebar, RB_SETBANDINFO, 3, (LPARAM)&rbi);
+    check_sizes();      /* here it will be relayouted */
+
+    /* this will force a new row */
+    rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
+    rbi.cx = 200;
+    rbi.cxMinChild = 400;
+    rbi.cyMinChild = 30;
+    rbi.hwndChild = build_toolbar(0, hRebar);
+    SendMessageA(hRebar, RB_INSERTBAND, 1, (LPARAM)&rbi);
+    check_sizes();
+
+    rbi.fMask = RBBIM_STYLE;
+    rbi.fStyle = RBBS_HIDDEN;
+    SendMessageA(hRebar, RB_SETBANDINFO, 2, (LPARAM)&rbi);
+    check_sizes();
+
+    SendMessageA(hRebar, RB_DELETEBAND, 2, 0);
+    check_sizes();
+    SendMessageA(hRebar, RB_DELETEBAND, 0, 0);
+    check_sizes();
+    SendMessageA(hRebar, RB_DELETEBAND, 1, 0);
+    check_sizes();
+
+    rebuild_rebar(&hRebar);
+    add_band_w(hRebar, "ABC",     70,  40, 100);
+    add_band_w(hRebar, NULL,      40,  70, 100);
+    add_band_w(hRebar, NULL,     170, 240, 100);
+    add_band_w(hRebar, "MMMMMMM", 60,  60, 100);
+    add_band_w(hRebar, NULL,     200, 200, 100);
+    check_sizes();
+    SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
+    check_sizes();
+    SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
+    check_sizes();
+    SendMessageA(hRebar, RB_MAXIMIZEBAND, 2, FALSE);
+    check_sizes();
+    SendMessageA(hRebar, RB_MINIMIZEBAND, 2, 0);
+    check_sizes();
+    SendMessageA(hRebar, RB_MINIMIZEBAND, 0, 0);
+    check_sizes();
+
+    /* VARHEIGHT resizing test on a horizontal rebar */
+    rebuild_rebar(&hRebar);
+    SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_AUTOSIZE);
+    check_sizes();
+    rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
+    rbi.fStyle = RBBS_VARIABLEHEIGHT;
+    rbi.cxMinChild = 50;
+    rbi.cyMinChild = 10;
+    rbi.cyIntegral = 11;
+    rbi.cyChild = 70;
+    rbi.cyMaxChild = 200;
+    rbi.cx = 90;
+    rbi.hwndChild = build_toolbar(0, hRebar);
+    SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+
+    rbi.cyChild = 50;
+    rbi.hwndChild = build_toolbar(0, hRebar);
+    SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+
+    rbi.cyMinChild = 40;
+    rbi.cyChild = 50;
+    rbi.cyIntegral = 5;
+    rbi.hwndChild = build_toolbar(0, hRebar);
+    SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+    check_sizes();
+
+    /* VARHEIGHT resizing on a vertical rebar */
+    rebuild_rebar(&hRebar);
+    SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | CCS_VERT | RBS_AUTOSIZE);
+    check_sizes();
+    rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
+    rbi.fStyle = RBBS_VARIABLEHEIGHT;
+    rbi.cxMinChild = 50;
+    rbi.cyMinChild = 10;
+    rbi.cyIntegral = 11;
+    rbi.cyChild = 70;
+    rbi.cyMaxChild = 90;
+    rbi.cx = 90;
+    rbi.hwndChild = build_toolbar(0, hRebar);
+    SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+    check_sizes();
+
+    rbi.cyChild = 50;
+    rbi.hwndChild = build_toolbar(0, hRebar);
+    SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+    check_sizes();
+
+    rbi.cyMinChild = 40;
+    rbi.cyChild = 50;
+    rbi.cyIntegral = 5;
+    rbi.hwndChild = build_toolbar(0, hRebar);
+    SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+    check_sizes();
+
+    DestroyWindow(hRebar);
+}
+
 static void expect_band_content(UINT uBand, UINT fStyle, COLORREF clrFore,
     COLORREF clrBack, LPCSTR lpText, int iImage, HWND hwndChild,
     UINT cxMinChild, UINT cyMinChild, UINT cx, HBITMAP hbmBack, UINT wID,
-    /*UINT cyChild, UINT cyMaxChild, UINT cyIntegral,*/ UINT cxIdeal, LPARAM lParam,
+    UINT cyChild, UINT cyMaxChild, UINT cyIntegral, UINT cxIdeal, LPARAM lParam,
     UINT cxHeader)
 {
     CHAR buf[MAX_PATH] = "abc";
@@ -74,12 +456,12 @@ static void expect_band_content(UINT uBand, UINT fStyle, COLORREF clrFore,
     expect_eq(rb.cx, cx, int, "%d");
     expect_eq(rb.hbmBack, hbmBack, HBITMAP, "%p");
     expect_eq(rb.wID, wID, int, "%d");
-    /* in Windows the values of cyChild, cyMaxChild and cyIntegral can't be read */
-    todo_wine expect_eq(rb.cyChild, 0xdddddddd, int, "%x");
-    todo_wine expect_eq(rb.cyMaxChild, 0xdddddddd, int, "%x");
-    todo_wine expect_eq(rb.cyIntegral, 0xdddddddd, int, "%x");
+    /* the values of cyChild, cyMaxChild and cyIntegral can't be read unless the band is RBBS_VARIABLEHEIGHT */
+    expect_eq(rb.cyChild, cyChild, int, "%x");
+    expect_eq(rb.cyMaxChild, cyMaxChild, int, "%x");
+    expect_eq(rb.cyIntegral, cyIntegral, int, "%x");
     expect_eq(rb.cxIdeal, cxIdeal, int, "%d");
-    expect_eq(rb.lParam, lParam, LPARAM, "%lx");
+    expect_eq(rb.lParam, lParam, LPARAM, "%ld");
     expect_eq(rb.cxHeader, cxHeader, int, "%d");
 }
 
@@ -93,7 +475,7 @@ static void bandinfo_test()
     rb.cbSize = sizeof(REBARBANDINFO);
     rb.fMask = 0;
     ok(SendMessageA(hRebar, RB_INSERTBANDA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
-    expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0, 0, 0);
+    expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0);
 
     rb.fMask = RBBIM_CHILDSIZE;
     rb.cxMinChild = 15;
@@ -102,37 +484,37 @@ static void bandinfo_test()
     rb.cyMaxChild = 20;
     rb.cyIntegral = 10;
     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
-    expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0, 0, 0);
+    expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0);
 
     rb.fMask = RBBIM_TEXT;
     rb.lpText = szABC;
     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
-    expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0, 0, 35);
+    expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 35);
 
     rb.cbSize = sizeof(REBARBANDINFO);
     rb.fMask = 0;
     ok(SendMessageA(hRebar, RB_INSERTBANDA, 1, (LPARAM)&rb), "RB_INSERTBAND failed\n");
-    expect_band_content(1, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0, 0, 9);
-    expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0, 0, 40);
+    expect_band_content(1, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 9);
+    expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 40);
 
     rb.fMask = RBBIM_HEADERSIZE;
     rb.cxHeader = 50;
     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
-    expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0, 0, 50);
+    expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 50);
 
     rb.cxHeader = 5;
     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
-    expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0, 0, 5);
+    expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5);
 
     rb.fMask = RBBIM_TEXT;
     rb.lpText = szABCD;
     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
-    expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABCD", -1, NULL, 15, 20, 0, NULL, 0, 0, 0, 5);
+    expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABCD", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5);
     rb.fMask = RBBIM_STYLE | RBBIM_TEXT;
-    rb.fStyle = 0;
+    rb.fStyle = RBBS_VARIABLEHEIGHT;
     rb.lpText = szABC;
     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
-    expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0, 0, 40);
+    expect_band_content(0, RBBS_VARIABLEHEIGHT, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 20, 0x7fffffff, 0, 0, 0, 40);
 
     DestroyWindow(hRebar);
 }
@@ -159,13 +541,14 @@ START_TEST(rebar)
     wc.lpszClassName = "MyTestWnd";
     wc.lpfnWndProc = MyWndProc;
     RegisterClassA(&wc);
-
-    hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
-      CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0);
+    hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW, 
+      CW_USEDEFAULT, CW_USEDEFAULT, 680, 226+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYSIZEFRAME),
+      NULL, NULL, GetModuleHandleA(NULL), 0);
     GetClientRect(hMainWnd, &rc);
     ShowWindow(hMainWnd, SW_SHOW);
 
     bandinfo_test();
+    layout_test();
     PostQuitMessage(0);
     while(GetMessageA(&msg,0,0,0)) {
         TranslateMessage(&msg);
-- 
1.4.4.2


More information about the wine-patches mailing list