rebar.c 141 KB
Newer Older
1
/*
2
 * Rebar control
Alexandre Julliard's avatar
Alexandre Julliard committed
3
 *
4
 * Copyright 1998, 1999 Eric Kohl
Alexandre Julliard's avatar
Alexandre Julliard committed
5
 *
6 7 8 9 10 11 12 13 14 15 16 17
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
 *
20
 * NOTES
Alexandre Julliard's avatar
Alexandre Julliard committed
21
 *
22
 * This code was audited for completeness against the documented features
23
 * of Comctl32.dll version 6.0 on Oct. 19, 2004, by Robert Shearman.
24 25 26 27
 * 
 * Unless otherwise noted, we believe this code to be complete, as per
 * the specification mentioned above.
 * If you discover missing features or bugs please note them below.
28
 *
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
 * TODO
 *   Styles:
 *   - RBS_DBLCLKTOGGLE
 *   - RBS_FIXEDORDER
 *   - RBS_REGISTERDROP
 *   - RBS_TOOLTIPS
 *   - CCS_NORESIZE
 *   - CCS_NOMOVEX
 *   - CCS_NOMOVEY
 *   Messages:
 *   - RB_BEGINDRAG
 *   - RB_DRAGMOVE
 *   - RB_ENDDRAG
 *   - RB_GETBANDMARGINS
 *   - RB_GETCOLORSCHEME
 *   - RB_GETDROPTARGET
 *   - RB_GETPALETTE
 *   - RB_SETCOLORSCHEME
 *   - RB_SETPALETTE
 *   - RB_SETTOOLTIPS
 *   - WM_CHARTOITEM
 *   - WM_LBUTTONDBLCLK
 *   - WM_MEASUREITEM
 *   - WM_PALETTECHANGED
 *   - WM_QUERYNEWPALETTE
 *   - WM_RBUTTONDOWN
 *   - WM_RBUTTONUP
 *   - WM_SYSCOLORCHANGE
 *   - WM_VKEYTOITEM
 *   - WM_WININICHANGE
 *   Notifications:
 *   - NM_HCHITTEST
 *   - NM_RELEASEDCAPTURE
 *   - RBN_AUTOBREAK
 *   - RBN_GETOBJECT
 *   - RBN_MINMAX
 *   Band styles:
 *   - RBBS_FIXEDBMP
 *   Native uses (on each draw!!) SM_CYBORDER (or SM_CXBORDER for CCS_VERT)
 *   to set the size of the separator width (the value SEP_WIDTH_SIZE
 *   in here). Should be fixed!!
 */

/*
 * Testing: set to 1 to make background brush *always* green
 */
#define GLATESTING 0

/*
78
 *
79 80 81
 * 2.  At "FIXME:  problem # 2" WinRAR:
 *   if "#if 1" then last band draws in separate row
 *   if "#if 0" then last band draws in previous row *** just like native ***
82
 *
83 84 85 86 87 88 89
 */
#define PROBLEM2 0

/*
 * 3. REBAR_MoveChildWindows should have a loop because more than
 *    one pass is made (together with the RBN_CHILDSIZEs) is made on
 *    at least RB_INSERTBAND
Alexandre Julliard's avatar
Alexandre Julliard committed
90 91
 */

92
#include <stdarg.h>
93
#include <stdlib.h>
94 95
#include <string.h>

96
#include "windef.h"
97
#include "winbase.h"
98
#include "wingdi.h"
99
#include "wine/unicode.h"
100 101
#include "winuser.h"
#include "winnls.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
102
#include "commctrl.h"
103
#include "comctl32.h"
104 105
#include "uxtheme.h"
#include "tmschema.h"
106
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
107

108
WINE_DEFAULT_DEBUG_CHANNEL(rebar);
109 110 111 112

typedef struct
{
    UINT    fStyle;
113
    UINT    fMask;
114 115 116 117
    COLORREF  clrFore;
    COLORREF  clrBack;
    INT     iImage;
    HWND    hwndChild;
118 119 120
    UINT    cxMinChild;     /* valid if _CHILDSIZE */
    UINT    cyMinChild;     /* valid if _CHILDSIZE */
    UINT    cx;             /* valid if _SIZE */
121 122
    HBITMAP hbmBack;
    UINT    wID;
123 124 125
    UINT    cyChild;        /* valid if _CHILDSIZE */
    UINT    cyMaxChild;     /* valid if _CHILDSIZE */
    UINT    cyIntegral;     /* valid if _CHILDSIZE */
126 127 128 129
    UINT    cxIdeal;
    LPARAM    lParam;
    UINT    cxHeader;

130
    UINT    lcx;            /* minimum cx for band */
131
    UINT    ccx;            /* current cx for band */
132 133
    UINT    hcx;            /* maximum cx for band */
    UINT    lcy;            /* minimum cy for band */
134
    UINT    ccy;            /* current cy for band */
135 136
    UINT    hcy;            /* maximum cy for band */

137
    SIZE    offChild;       /* x,y offset if child is not FIXEDSIZE */
138
    UINT    uMinHeight;
139
    INT     iRow;           /* zero-based index of the row this band assigned to */
140 141
    UINT    fStatus;        /* status flags, reset only by _Validate */
    UINT    fDraw;          /* drawing flags, reset only by _Layout */
142
    UINT    uCDret;         /* last return from NM_CUSTOMDRAW */
143
    RECT    rcoldBand;      /* previous calculated band rectangle */
144 145 146 147 148
    RECT    rcBand;         /* calculated band rectangle */
    RECT    rcGripper;      /* calculated gripper rectangle */
    RECT    rcCapImage;     /* calculated caption image rectangle */
    RECT    rcCapText;      /* calculated caption text rectangle */
    RECT    rcChild;        /* calculated child rectangle */
Robert Shearman's avatar
Robert Shearman committed
149
    RECT    rcChevron;      /* calculated chevron rectangle */
150 151 152 153 154

    LPWSTR    lpText;
    HWND    hwndPrevParent;
} REBAR_BAND;

155 156 157 158 159
/* fStatus flags */
#define HAS_GRIPPER    0x00000001
#define HAS_IMAGE      0x00000002
#define HAS_TEXT       0x00000004

160
/* fDraw flags */
161 162 163 164 165
#define DRAW_GRIPPER    0x00000001
#define DRAW_IMAGE      0x00000002
#define DRAW_TEXT       0x00000004
#define DRAW_RIGHTSEP   0x00000010
#define DRAW_BOTTOMSEP  0x00000020
Robert Shearman's avatar
Robert Shearman committed
166 167
#define DRAW_CHEVRONHOT 0x00000040
#define DRAW_CHEVRONPUSHED 0x00000080
168 169
#define DRAW_LAST_IN_ROW   0x00000100
#define DRAW_FIRST_IN_ROW  0x00000200
170
#define NTF_INVALIDATE  0x01000000
171

172 173 174 175
typedef struct
{
    COLORREF   clrBk;       /* background color */
    COLORREF   clrText;     /* text color */
176
    COLORREF   clrBtnText;  /* system color for BTNTEXT */
177
    COLORREF   clrBtnFace;  /* system color for BTNFACE */
178
    HIMAGELIST himl;        /* handle to imagelist */
179
    UINT     uNumBands;   /* # of bands in rebar (first=0, last=uNumBands-1 */
180 181
    UINT     uNumRows;    /* # of rows of bands (first=1, last=uNumRows */
    HWND     hwndSelf;    /* handle of REBAR window itself */
182 183
    HWND     hwndToolTip; /* handle to the tool tip control */
    HWND     hwndNotify;  /* notification window (parent) */
184
    HFONT    hDefaultFont;
185 186
    HFONT    hFont;       /* handle to the rebar's font */
    SIZE     imageSize;   /* image size (image list) */
187
    DWORD    dwStyle;     /* window style */
188
    DWORD    orgStyle;    /* original style (dwStyle may change) */
189
    SIZE     calcSize;    /* calculated rebar size */
190
    SIZE     oldSize;     /* previous calculated rebar size */
191
    BOOL     bUnicode;    /* TRUE if parent wants notify in W format */
192
    BOOL     DoRedraw;    /* TRUE to acutally draw bands */
193
    UINT     fStatus;     /* Status flags (see below)  */
194 195 196 197 198
    HCURSOR  hcurArrow;   /* handle to the arrow cursor */
    HCURSOR  hcurHorz;    /* handle to the EW cursor */
    HCURSOR  hcurVert;    /* handle to the NS cursor */
    HCURSOR  hcurDrag;    /* handle to the drag cursor */
    INT      iVersion;    /* version number */
199 200
    POINT    dragStart;   /* x,y of button down */
    POINT    dragNow;     /* x,y of this MouseMove */
Robert Shearman's avatar
Robert Shearman committed
201
    INT      iOldBand;    /* last band that had the mouse cursor over it */
202
    INT      ihitoffset;  /* offset of hotspot from gripper.left */
203
    POINT    origin;      /* left/upper corner of client */
Robert Shearman's avatar
Robert Shearman committed
204 205
    INT      ichevronhotBand; /* last band that had a hot chevron */
    INT      iGrabbedBand;/* band number of band whose gripper was grabbed */
206 207 208

    REBAR_BAND *bands;      /* pointer to the array of rebar bands */
} REBAR_INFO;
209

210
/* fStatus flags */
211 212 213 214 215
#define BEGIN_DRAG_ISSUED   0x00000001
#define AUTO_RESIZE         0x00000002
#define RESIZE_ANYHOW       0x00000004
#define NTF_HGHTCHG         0x00000008
#define BAND_NEEDS_LAYOUT   0x00000010
216 217
#define BAND_NEEDS_REDRAW   0x00000020
#define CREATE_RUNNING      0x00000040
218 219 220 221 222 223 224

/* ----   REBAR layout constants. Mostly determined by        ---- */
/* ----   experiment on WIN 98.                               ---- */

/* Width (or height) of separators between bands (either horz. or  */
/* vert.). True only if RBS_BANDBORDERS is set                     */
#define SEP_WIDTH_SIZE  2
225
#define SEP_WIDTH       ((infoPtr->dwStyle & RBS_BANDBORDERS) ? SEP_WIDTH_SIZE : 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
226

227 228 229
/* Blank (background color) space between Gripper (if present)     */
/* and next item (image, text, or window). Always present          */
#define REBAR_ALWAYS_SPACE  4
Eric Kohl's avatar
Eric Kohl committed
230

231 232 233 234 235 236 237
/* Blank (background color) space after Image (if present).        */
#define REBAR_POST_IMAGE  2

/* Blank (background color) space after Text (if present).         */
#define REBAR_POST_TEXT  4

/* Height of vertical gripper in a CCS_VERT rebar.                 */
238
#define GRIPPER_HEIGHT  16
239 240 241 242 243 244 245

/* Blank (background color) space before Gripper (if present).     */
#define REBAR_PRE_GRIPPER   2

/* Width (of normal vertical gripper) or height (of horz. gripper) */
/* if present.                                                     */
#define GRIPPER_WIDTH  3
Eric Kohl's avatar
Eric Kohl committed
246

Robert Shearman's avatar
Robert Shearman committed
247 248 249
/* Width of the chevron button if present */
#define CHEVRON_WIDTH  10

250 251 252 253
/* Height of divider for Rebar if not disabled (CCS_NODIVIDER)     */
/* either top or bottom                                            */
#define REBAR_DIVIDER  2

254 255 256 257
/* minimium vertical height of a normal bar                        */
/*   or minimum width of a CCS_VERT bar - from experiment on Win2k */
#define REBAR_MINSIZE  23

258 259
/* This is the increment that is used over the band height         */
#define REBARSPACE(a)     ((a->fStyle & RBBS_CHILDEDGE) ? 2*REBAR_DIVIDER : 0)
260

261 262
/* ----   End of REBAR layout constants.                      ---- */

263
#define RB_GETBANDINFO_OLD (WM_USER+5) /* obsoleted after IE3, but we have to support it anyway */
264

265
/*  The following 6 defines return the proper rcBand element       */
266
/*  depending on whether CCS_VERT was set.                         */
267 268 269
#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) : \
270
		  (b->rcBand.right - b->rcBand.left))
271 272 273
#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) : \
274
		  (b->rcBand.bottom - b->rcBand.top))
275 276 277

/*  The following define determines if a given band is hidden      */
#define HIDDENBAND(a)  (((a)->fStyle & RBBS_HIDDEN) ||   \
278
                        ((infoPtr->dwStyle & CCS_VERT) &&         \
279 280
                         ((a)->fStyle & RBBS_NOVERT)))

281
/*  The following defines adjust the right or left end of a rectangle */
282 283 284 285
#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)
286

287

288
#define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongPtrW (hwnd, 0))
Alexandre Julliard's avatar
Alexandre Julliard committed
289

290 291
static LRESULT REBAR_NotifyFormat(REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam);

292 293 294 295 296 297

/* "constant values" retrieved when DLL was initialized    */
/* FIXME we do this when the classes are registered.       */
static UINT mindragx = 0;
static UINT mindragy = 0;

298
static const char * const band_stylename[] = {
299 300 301 302 303 304 305 306 307 308 309
    "RBBS_BREAK",              /* 0001 */
    "RBBS_FIXEDSIZE",          /* 0002 */
    "RBBS_CHILDEDGE",          /* 0004 */
    "RBBS_HIDDEN",             /* 0008 */
    "RBBS_NOVERT",             /* 0010 */
    "RBBS_FIXEDBMP",           /* 0020 */
    "RBBS_VARIABLEHEIGHT",     /* 0040 */
    "RBBS_GRIPPERALWAYS",      /* 0080 */
    "RBBS_NOGRIPPER",          /* 0100 */
    NULL };

310
static const char * const band_maskname[] = {
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
    "RBBIM_STYLE",         /*    0x00000001 */
    "RBBIM_COLORS",        /*    0x00000002 */
    "RBBIM_TEXT",          /*    0x00000004 */
    "RBBIM_IMAGE",         /*    0x00000008 */
    "RBBIM_CHILD",         /*    0x00000010 */
    "RBBIM_CHILDSIZE",     /*    0x00000020 */
    "RBBIM_SIZE",          /*    0x00000040 */
    "RBBIM_BACKGROUND",    /*    0x00000080 */
    "RBBIM_ID",            /*    0x00000100 */
    "RBBIM_IDEALSIZE",     /*    0x00000200 */
    "RBBIM_LPARAM",        /*    0x00000400 */
    "RBBIM_HEADERSIZE",    /*    0x00000800 */
    NULL };


static CHAR line[200];

328
static const WCHAR themeClass[] = { 'R','e','b','a','r',0 };
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362

static CHAR *
REBAR_FmtStyle( UINT style)
{
    INT i = 0;

    *line = 0;
    while (band_stylename[i]) {
	if (style & (1<<i)) {
	    if (*line != 0) strcat(line, " | ");
	    strcat(line, band_stylename[i]);
	}
	i++;
    }
    return line;
}


static CHAR *
REBAR_FmtMask( UINT mask)
{
    INT i = 0;

    *line = 0;
    while (band_maskname[i]) {
	if (mask & (1<<i)) {
	    if (*line != 0) strcat(line, " | ");
	    strcat(line, band_maskname[i]);
	}
	i++;
    }
    return line;
}

363

364 365 366
static VOID
REBAR_DumpBandInfo( LPREBARBANDINFOA pB)
{
367
    if( !TRACE_ON(rebar) ) return;
368
    TRACE("band info: ");
369
    if (pB->fMask & RBBIM_ID)
370 371 372
        TRACE("ID=%u, ", pB->wID);
    TRACE("size=%u, child=%p", pB->cbSize, pB->hwndChild);
    if (pB->fMask & RBBIM_COLORS)
373
        TRACE(", clrF=0x%06x, clrB=0x%06x", pB->clrFore, pB->clrBack);
374 375
    TRACE("\n");

376 377 378 379 380 381
    TRACE("band info: mask=0x%08x (%s)\n", pB->fMask, REBAR_FmtMask(pB->fMask));
    if (pB->fMask & RBBIM_STYLE)
	TRACE("band info: style=0x%08x (%s)\n", pB->fStyle, REBAR_FmtStyle(pB->fStyle));
    if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_HEADERSIZE | RBBIM_LPARAM )) {
	TRACE("band info:");
	if (pB->fMask & RBBIM_SIZE)
382
	    TRACE(" cx=%u", pB->cx);
383
	if (pB->fMask & RBBIM_IDEALSIZE)
384
	    TRACE(" xIdeal=%u", pB->cxIdeal);
385
	if (pB->fMask & RBBIM_HEADERSIZE)
386
	    TRACE(" xHeader=%u", pB->cxHeader);
387
	if (pB->fMask & RBBIM_LPARAM)
388 389
	    TRACE(" lParam=0x%08lx", pB->lParam);
	TRACE("\n");
390 391 392
    }
    if (pB->fMask & RBBIM_CHILDSIZE)
	TRACE("band info: xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
393
	      pB->cxMinChild,
394
	      pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
395 396 397
}

static VOID
398
REBAR_DumpBand (REBAR_INFO *iP)
399 400 401 402
{
    REBAR_BAND *pB;
    UINT i;

403
    if(! TRACE_ON(rebar) ) return;
404

405
    TRACE("hwnd=%p: color=%08x/%08x, bands=%u, rows=%u, cSize=%d,%d\n",
406 407
	  iP->hwndSelf, iP->clrText, iP->clrBk, iP->uNumBands, iP->uNumRows,
	  iP->calcSize.cx, iP->calcSize.cy);
408
    TRACE("hwnd=%p: flags=%08x, dragStart=%d,%d, dragNow=%d,%d, iGrabbedBand=%d\n",
409 410
	  iP->hwndSelf, iP->fStatus, iP->dragStart.x, iP->dragStart.y,
	  iP->dragNow.x, iP->dragNow.y,
Robert Shearman's avatar
Robert Shearman committed
411
	  iP->iGrabbedBand);
412 413 414
    TRACE("hwnd=%p: style=%08x, notify in Unicode=%s, redraw=%s\n",
          iP->hwndSelf, iP->dwStyle, (iP->bUnicode)?"TRUE":"FALSE",
          (iP->DoRedraw)?"TRUE":"FALSE");
415
    for (i = 0; i < iP->uNumBands; i++) {
416
	pB = &iP->bands[i];
417
	TRACE("band # %u:", i);
418
	if (pB->fMask & RBBIM_ID)
419 420 421 422
	    TRACE(" ID=%u", pB->wID);
	if (pB->fMask & RBBIM_CHILD)
	    TRACE(" child=%p", pB->hwndChild);
	if (pB->fMask & RBBIM_COLORS)
423
            TRACE(" clrF=0x%06x clrB=0x%06x", pB->clrFore, pB->clrBack);
424
	TRACE("\n");
425 426
	TRACE("band # %u: mask=0x%08x (%s)\n", i, pB->fMask, REBAR_FmtMask(pB->fMask));
	if (pB->fMask & RBBIM_STYLE)
427
	    TRACE("band # %u: style=0x%08x (%s)\n",
428
		  i, pB->fStyle, REBAR_FmtStyle(pB->fStyle));
429
	TRACE("band # %u: uMinH=%u xHeader=%u",
430 431 432
	      i, pB->uMinHeight, pB->cxHeader);
	if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_LPARAM )) {
	    if (pB->fMask & RBBIM_SIZE)
433
		TRACE(" cx=%u", pB->cx);
434
	    if (pB->fMask & RBBIM_IDEALSIZE)
435
		TRACE(" xIdeal=%u", pB->cxIdeal);
436
	    if (pB->fMask & RBBIM_LPARAM)
437
		TRACE(" lParam=0x%08lx", pB->lParam);
438
	}
439
	TRACE("\n");
440 441 442
	if (RBBIM_CHILDSIZE)
	    TRACE("band # %u: xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
		  i, pB->cxMinChild, pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
443 444 445
	if (pB->fMask & RBBIM_TEXT)
	    TRACE("band # %u: text=%s\n",
		  i, (pB->lpText) ? debugstr_w(pB->lpText) : "(null)");
446
	TRACE("band # %u: lcx=%u, ccx=%u, hcx=%u, lcy=%u, ccy=%u, hcy=%u, offChild=%d,%d\n",
447
	      i, pB->lcx, pB->ccx, pB->hcx, pB->lcy, pB->ccy, pB->hcy, pB->offChild.cx, pB->offChild.cy);
448
	TRACE("band # %u: fStatus=%08x, fDraw=%08x, Band=(%d,%d)-(%d,%d), Grip=(%d,%d)-(%d,%d)\n",
449 450 451
	      i, pB->fStatus, pB->fDraw,
	      pB->rcBand.left, pB->rcBand.top, pB->rcBand.right, pB->rcBand.bottom,
	      pB->rcGripper.left, pB->rcGripper.top, pB->rcGripper.right, pB->rcGripper.bottom);
452
	TRACE("band # %u: Img=(%d,%d)-(%d,%d), Txt=(%d,%d)-(%d,%d), Child=(%d,%d)-(%d,%d)\n",
453 454 455 456
	      i,
	      pB->rcCapImage.left, pB->rcCapImage.top, pB->rcCapImage.right, pB->rcCapImage.bottom,
	      pB->rcCapText.left, pB->rcCapText.top, pB->rcCapText.right, pB->rcCapText.bottom,
	      pB->rcChild.left, pB->rcChild.top, pB->rcChild.right, pB->rcChild.bottom);
457
    }
458

459
}
Alexandre Julliard's avatar
Alexandre Julliard committed
460

Robert Shearman's avatar
Robert Shearman committed
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
static void
REBAR_DrawChevron (HDC hdc, INT left, INT top, INT colorRef)
{
    INT x, y;
    HPEN hPen, hOldPen;

    if (!(hPen = CreatePen( PS_SOLID, 1, GetSysColor( colorRef )))) return;
    hOldPen = SelectObject ( hdc, hPen );
    x = left + 2;
    y = top;
    MoveToEx (hdc, x, y, NULL);
    LineTo (hdc, x+5, y++); x++;
    MoveToEx (hdc, x, y, NULL);
    LineTo (hdc, x+3, y++); x++;
    MoveToEx (hdc, x, y, NULL);
    LineTo (hdc, x+1, y++);
    SelectObject( hdc, hOldPen );
    DeleteObject( hPen );
}
480 481 482

static HWND
REBAR_GetNotifyParent (REBAR_INFO *infoPtr)
483 484 485
{
    HWND parent, owner;

486 487
    parent = infoPtr->hwndNotify;
    if (!parent) {
488 489
        parent = GetParent (infoPtr->hwndSelf);
	owner = GetWindow (infoPtr->hwndSelf, GW_OWNER);
490 491
	if (owner) parent = owner;
    }
492 493 494 495 496 497 498 499 500 501 502 503
    return parent;
}


static INT
REBAR_Notify (NMHDR *nmhdr, REBAR_INFO *infoPtr, UINT code)
{
    HWND parent;

    parent = REBAR_GetNotifyParent (infoPtr);
    nmhdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf);
    nmhdr->hwndFrom = infoPtr->hwndSelf;
504 505
    nmhdr->code = code;

506
    TRACE("window %p, code=%08x, via %s\n", parent, code, (infoPtr->bUnicode)?"Unicode":"ANSI");
507

508
    return SendMessageW(parent, WM_NOTIFY, (WPARAM)nmhdr->idFrom, (LPARAM)nmhdr);
509 510 511
}

static INT
512
REBAR_Notify_NMREBAR (REBAR_INFO *infoPtr, UINT uBand, UINT code)
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
{
    NMREBAR notify_rebar;
    REBAR_BAND *lpBand;

    notify_rebar.dwMask = 0;
    if (uBand!=-1) {
	lpBand = &infoPtr->bands[uBand];
	if (lpBand->fMask & RBBIM_ID) {
	    notify_rebar.dwMask |= RBNM_ID;
	    notify_rebar.wID = lpBand->wID;
	}
	if (lpBand->fMask & RBBIM_LPARAM) {
	    notify_rebar.dwMask |= RBNM_LPARAM;
	    notify_rebar.lParam = lpBand->lParam;
	}
	if (lpBand->fMask & RBBIM_STYLE) {
	    notify_rebar.dwMask |= RBNM_STYLE;
	    notify_rebar.fStyle = lpBand->fStyle;
	}
    }
    notify_rebar.uBand = uBand;
534
    return REBAR_Notify ((NMHDR *)&notify_rebar, infoPtr, code);
535 536
}

Eric Kohl's avatar
Eric Kohl committed
537
static VOID
538
REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
Eric Kohl's avatar
Eric Kohl committed
539
{
540 541 542
    HFONT hOldFont = 0;
    INT oldBkMode = 0;
    NMCUSTOMDRAW nmcd;
543
    HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
Eric Kohl's avatar
Eric Kohl committed
544

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
    if (lpBand->fDraw & DRAW_TEXT) {
	hOldFont = SelectObject (hdc, infoPtr->hFont);
	oldBkMode = SetBkMode (hdc, TRANSPARENT);
    }

    /* should test for CDRF_NOTIFYITEMDRAW here */
    nmcd.dwDrawStage = CDDS_ITEMPREPAINT;
    nmcd.hdc = hdc;
    nmcd.rc = lpBand->rcBand;
    nmcd.rc.right = lpBand->rcCapText.right;
    nmcd.rc.bottom = lpBand->rcCapText.bottom;
    nmcd.dwItemSpec = lpBand->wID;
    nmcd.uItemState = 0;
    nmcd.lItemlParam = lpBand->lParam;
    lpBand->uCDret = REBAR_Notify ((NMHDR *)&nmcd, infoPtr, NM_CUSTOMDRAW);
    if (lpBand->uCDret == CDRF_SKIPDEFAULT) {
	if (oldBkMode != TRANSPARENT)
	    SetBkMode (hdc, oldBkMode);
	SelectObject (hdc, hOldFont);
	return;
    }
Eric Kohl's avatar
Eric Kohl committed
566 567 568

    /* draw gripper */
    if (lpBand->fDraw & DRAW_GRIPPER)
569 570 571 572 573 574 575 576 577 578 579 580 581
    {
        if (theme)
        {
            RECT rcGripper = lpBand->rcGripper;
            int partId = (infoPtr->dwStyle & CCS_VERT) ? RP_GRIPPERVERT : RP_GRIPPER;
            GetThemeBackgroundExtent (theme, hdc, partId, 0, &rcGripper, &rcGripper);
            OffsetRect (&rcGripper, lpBand->rcGripper.left - rcGripper.left,
                lpBand->rcGripper.top - rcGripper.top);
            DrawThemeBackground (theme, hdc, partId, 0, &rcGripper, NULL);
        }
        else
            DrawEdge (hdc, &lpBand->rcGripper, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
    }
Eric Kohl's avatar
Eric Kohl committed
582 583

    /* draw caption image */
Eric Kohl's avatar
Eric Kohl committed
584
    if (lpBand->fDraw & DRAW_IMAGE) {
585
	POINT pt;
Eric Kohl's avatar
Eric Kohl committed
586

587
	/* center image */
Eric Kohl's avatar
Eric Kohl committed
588 589 590
	pt.y = (lpBand->rcCapImage.bottom + lpBand->rcCapImage.top - infoPtr->imageSize.cy)/2;
	pt.x = (lpBand->rcCapImage.right + lpBand->rcCapImage.left - infoPtr->imageSize.cx)/2;

Eric Kohl's avatar
Eric Kohl committed
591
	ImageList_Draw (infoPtr->himl, lpBand->iImage, hdc,
Eric Kohl's avatar
Eric Kohl committed
592
			pt.x, pt.y,
Eric Kohl's avatar
Eric Kohl committed
593
			ILD_TRANSPARENT);
Eric Kohl's avatar
Eric Kohl committed
594
    }
Eric Kohl's avatar
Eric Kohl committed
595 596 597

    /* draw caption text */
    if (lpBand->fDraw & DRAW_TEXT) {
598
	/* need to handle CDRF_NEWFONT here */
599
	INT oldBkMode = SetBkMode (hdc, TRANSPARENT);
600
	COLORREF oldcolor = CLR_NONE;
Guy Albertelli's avatar
Guy Albertelli committed
601 602 603 604 605 606
	COLORREF new;
	if (lpBand->clrFore != CLR_NONE) {
	    new = (lpBand->clrFore == CLR_DEFAULT) ? infoPtr->clrBtnText :
		    lpBand->clrFore;
	    oldcolor = SetTextColor (hdc, new);
	}
607
	DrawTextW (hdc, lpBand->lpText, -1, &lpBand->rcCapText,
608
		   DT_CENTER | DT_VCENTER | DT_SINGLELINE);
Eric Kohl's avatar
Eric Kohl committed
609
	if (oldBkMode != TRANSPARENT)
610
	    SetBkMode (hdc, oldBkMode);
611
	if (lpBand->clrFore != CLR_NONE)
Guy Albertelli's avatar
Guy Albertelli committed
612
	    SetTextColor (hdc, oldcolor);
613
	SelectObject (hdc, hOldFont);
Eric Kohl's avatar
Eric Kohl committed
614
    }
615

Robert Shearman's avatar
Robert Shearman committed
616 617
    if (!IsRectEmpty(&lpBand->rcChevron))
    {
618
        if (theme)
Robert Shearman's avatar
Robert Shearman committed
619
        {
620 621 622 623 624 625 626 627
            int stateId; 
            if (lpBand->fDraw & DRAW_CHEVRONPUSHED)
                stateId = CHEVS_PRESSED;
            else if (lpBand->fDraw & DRAW_CHEVRONHOT)
                stateId = CHEVS_HOT;
            else
                stateId = CHEVS_NORMAL;
            DrawThemeBackground (theme, hdc, RP_CHEVRON, stateId, &lpBand->rcChevron, NULL);
Robert Shearman's avatar
Robert Shearman committed
628
        }
629
        else
Robert Shearman's avatar
Robert Shearman committed
630
        {
631 632 633 634 635 636 637 638 639 640 641 642
            if (lpBand->fDraw & DRAW_CHEVRONPUSHED)
            {
                DrawEdge(hdc, &lpBand->rcChevron, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE);
                REBAR_DrawChevron(hdc, lpBand->rcChevron.left+1, lpBand->rcChevron.top + 11, COLOR_WINDOWFRAME);
            }
            else if (lpBand->fDraw & DRAW_CHEVRONHOT)
            {
                DrawEdge(hdc, &lpBand->rcChevron, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
                REBAR_DrawChevron(hdc, lpBand->rcChevron.left, lpBand->rcChevron.top + 10, COLOR_WINDOWFRAME);
            }
            else
                REBAR_DrawChevron(hdc, lpBand->rcChevron.left, lpBand->rcChevron.top + 10, COLOR_WINDOWFRAME);
Robert Shearman's avatar
Robert Shearman committed
643 644 645
        }
    }

646 647 648 649 650 651 652 653 654 655 656
    if (lpBand->uCDret == (CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYITEMDRAW)) {
	nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;
	nmcd.hdc = hdc;
	nmcd.rc = lpBand->rcBand;
	nmcd.rc.right = lpBand->rcCapText.right;
	nmcd.rc.bottom = lpBand->rcCapText.bottom;
	nmcd.dwItemSpec = lpBand->wID;
	nmcd.uItemState = 0;
	nmcd.lItemlParam = lpBand->lParam;
	lpBand->uCDret = REBAR_Notify ((NMHDR *)&nmcd, infoPtr, NM_CUSTOMDRAW);
    }
Eric Kohl's avatar
Eric Kohl committed
657
}
Alexandre Julliard's avatar
Alexandre Julliard committed
658 659 660


static VOID
661
REBAR_Refresh (REBAR_INFO *infoPtr, HDC hdc)
Alexandre Julliard's avatar
Alexandre Julliard committed
662
{
Eric Kohl's avatar
Eric Kohl committed
663
    REBAR_BAND *lpBand;
664
    UINT i;
Eric Kohl's avatar
Eric Kohl committed
665

666 667
    if (!infoPtr->DoRedraw) return;

Eric Kohl's avatar
Eric Kohl committed
668 669 670
    for (i = 0; i < infoPtr->uNumBands; i++) {
	lpBand = &infoPtr->bands[i];

671
	if (HIDDENBAND(lpBand)) continue;
Eric Kohl's avatar
Eric Kohl committed
672

673
	/* now draw the band */
674
	TRACE("[%p] drawing band %i, flags=%08x\n",
675
	      infoPtr->hwndSelf, i, lpBand->fDraw);
676
	REBAR_DrawBand (hdc, infoPtr, lpBand);
Eric Kohl's avatar
Eric Kohl committed
677 678 679 680

    }
}

681

682
static void
683
REBAR_FixVert (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend,
684
		   INT mcy)
685
     /* Function:                                                    */
686 687 688 689 690
     /*   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                       */
Eric Kohl's avatar
Eric Kohl committed
691
{
692
    REBAR_BAND *lpBand;
693
    INT i;
694

695
    for (i = (INT)rowstart; i<=(INT)rowend; i++) {
696 697
        lpBand = &infoPtr->bands[i];
	if (HIDDENBAND(lpBand)) continue;
698

699
	/* adjust height of bands in row to "mcy" value */
700
	if (infoPtr->dwStyle & CCS_VERT) {
701
	    if (lpBand->rcBand.right != lpBand->rcBand.left + mcy)
702 703 704
	        lpBand->rcBand.right = lpBand->rcBand.left + mcy;
	}
	else {
705
	    if (lpBand->rcBand.bottom != lpBand->rcBand.top + mcy)
706
	        lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
707

708 709
	}

710 711 712 713 714 715
	/* 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;
716
            TRACE("band %d row=%d: changed to (%d,%d)-(%d,%d) from (%d,%d)-(%d,%d)\n",
717 718
		  i, lpBand->iRow,
		  lpBand->rcBand.left, lpBand->rcBand.top,
719 720 721
		  lpBand->rcBand.right, lpBand->rcBand.bottom,
		  lpBand->rcoldBand.left, lpBand->rcoldBand.top,
		  lpBand->rcoldBand.right, lpBand->rcoldBand.bottom);
722
	}
723
	else
724
            TRACE("band %d row=%d: unchanged (%d,%d)-(%d,%d)\n",
725 726 727
		  i, lpBand->iRow,
		  lpBand->rcBand.left, lpBand->rcBand.top,
		  lpBand->rcBand.right, lpBand->rcBand.bottom);
728 729 730 731 732 733
    }
}


static void
REBAR_AdjustBands (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend,
734
		   INT maxx, INT mcy)
735 736 737 738 739 740 741
     /* 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;
742 743
    UINT xsep, extra, curwidth, fudge;
    INT x, i, last_adjusted;
744 745 746 747 748 749

    TRACE("start=%u, end=%u, max x=%d, max y=%d\n",
	  rowstart, rowend, maxx, mcy);

    /* *******************  Phase 1  ************************ */
    /* Alg:                                                   */
750
    /*  For each visible band with valid child                */
751 752 753
    /*      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 */
754
    /*  adjusted.                                             */
755 756 757 758 759
    /*                                                        */
    /* ****************************************************** */
    lpBand = &infoPtr->bands[rowend];
    extra = maxx - rcBrb(lpBand);
    x = 0;
760
    last_adjusted = -1;
761 762 763 764 765 766 767
    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 */
768
	if (infoPtr->dwStyle & CCS_VERT)
769 770 771 772 773
	    lpBand->rcBand.top = x + xsep;
	else
	    lpBand->rcBand.left = x + xsep;

	/* compute new width */
774
	if ((lpBand->hwndChild && extra) && !(lpBand->fStyle & RBBS_FIXEDSIZE)) {
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
	    /* 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 */
796
	if (infoPtr->dwStyle & CCS_VERT)
797 798 799
	    lpBand->rcBand.bottom = lpBand->rcBand.top + curwidth;
	else
	    lpBand->rcBand.right = lpBand->rcBand.left + curwidth;
800
	TRACE("Phase 1 band %d, (%d,%d)-(%d,%d), orig x=%d, xsep=%d\n",
801 802 803 804
	      i, lpBand->rcBand.left, lpBand->rcBand.top,
	      lpBand->rcBand.right, lpBand->rcBand.bottom, x, xsep);
	x = rcBrb(lpBand);
    }
805
    if ((x >= maxx) || (last_adjusted != -1)) {
806
	if (x > maxx) {
807
	    ERR("Phase 1 failed, x=%d, maxx=%d, start=%u, end=%u\n",
808
		x, maxx,  rowstart, rowend);
809 810 811 812 813 814 815 816 817 818 819 820
	}
	/* 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) {
821
		    if (infoPtr->dwStyle & CCS_VERT)
822 823 824 825 826 827
			lpBand->rcBand.top += fudge;
		    else
			lpBand->rcBand.left += fudge;
		}

		/* set left/bottom point */
828
		if (infoPtr->dwStyle & CCS_VERT)
829 830 831 832
		    lpBand->rcBand.bottom += fudge;
		else
		    lpBand->rcBand.right += fudge;
	    }
833
	}
834
	TRACE("Phase 1 succeeded, used x=%d\n", x);
835
	REBAR_FixVert (infoPtr, rowstart, rowend, mcy);
836
 	return;
837 838
    }

839 840
    /* *******************  Phase 2  ************************ */
    /* Alg:                                                   */
841
    /*  Find first visible band, put all                      */
842 843 844 845 846 847 848 849 850 851 852 853
    /*    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 */
854
	if (infoPtr->dwStyle & CCS_VERT)
855 856 857 858 859
	    lpBand->rcBand.top = x + xsep;
	else
	    lpBand->rcBand.left = x + xsep;

	/* compute new width */
860
	if (extra) {
861 862
	    curwidth += extra;
	    extra = 0;
863
	}
864 865

	/* set new right/bottom point */
866
	if (infoPtr->dwStyle & CCS_VERT)
867 868 869
	    lpBand->rcBand.bottom = lpBand->rcBand.top + curwidth;
	else
	    lpBand->rcBand.right = lpBand->rcBand.left + curwidth;
870
	TRACE("Phase 2 band %d, (%d,%d)-(%d,%d), orig x=%d, xsep=%d\n",
871 872 873 874 875 876
	      i, lpBand->rcBand.left, lpBand->rcBand.top,
	      lpBand->rcBand.right, lpBand->rcBand.bottom, x, xsep);
	x = rcBrb(lpBand);
    }
    if (x >= maxx) {
	if (x > maxx) {
877
	    ERR("Phase 2 failed, x=%d, maxx=%d, start=%u, end=%u\n",
878
		x, maxx,  rowstart, rowend);
879 880 881
	}
	/* done, so spread extra space */
	TRACE("Phase 2 succeeded, used x=%d\n", x);
882
	REBAR_FixVert (infoPtr, rowstart, rowend, mcy);
883
	return;
884
    }
885 886 887 888 889 890 891 892 893 894 895

    /* *******************  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;
896 897
}

898

899
static void
900
REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
901 902 903 904 905 906 907
     /* 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;
908
    RECT oldChild, work;
909 910

    /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
911
    parenthwnd = GetParent (infoPtr->hwndSelf);
912

913
    for(i=rstart; i<rend; i++){
914
      lpBand = &infoPtr->bands[i];
915 916 917 918 919 920 921
      if (HIDDENBAND(lpBand)) {
          SetRect (&lpBand->rcChild,
		   lpBand->rcBand.right, lpBand->rcBand.top,
		   lpBand->rcBand.right, lpBand->rcBand.bottom);
	  continue;
      }

922 923 924 925
      oldChild = lpBand->rcChild;

      /* set initial gripper rectangle */
      SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
926
	       lpBand->rcBand.left, lpBand->rcBand.bottom);
927 928

      /* calculate gripper rectangle */
929 930 931 932 933 934 935 936 937 938
      if ( lpBand->fStatus & HAS_GRIPPER) {
	  lpBand->fDraw |= DRAW_GRIPPER;
	  lpBand->rcGripper.left   += REBAR_PRE_GRIPPER;
	  lpBand->rcGripper.right  = lpBand->rcGripper.left + GRIPPER_WIDTH;
	  lpBand->rcGripper.top    += 2;
	  lpBand->rcGripper.bottom -= 2;

	  SetRect (&lpBand->rcCapImage,
		   lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.top,
		   lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.bottom);
939
      }
940 941 942 943 944
      else {  /* no gripper will be drawn */
	  xoff = 0;
	  if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
	      /* if no gripper but either image or text, then leave space */
	      xoff = REBAR_ALWAYS_SPACE;
945
	  SetRect (&lpBand->rcCapImage,
946 947
		   lpBand->rcBand.left+xoff, lpBand->rcBand.top,
		   lpBand->rcBand.left+xoff, lpBand->rcBand.bottom);
948 949 950
      }

      /* image is visible */
951 952 953 954 955 956 957 958 959
      if (lpBand->fStatus & HAS_IMAGE) {
	  lpBand->fDraw |= DRAW_IMAGE;
	  lpBand->rcCapImage.right  += infoPtr->imageSize.cx;
	  lpBand->rcCapImage.bottom = lpBand->rcCapImage.top + infoPtr->imageSize.cy;

	  /* set initial caption text rectangle */
	  SetRect (&lpBand->rcCapText,
		   lpBand->rcCapImage.right+REBAR_POST_IMAGE, lpBand->rcBand.top+1,
		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
960
	  /* update band height
961 962 963 964 965 966 967 968 969
	  if (lpBand->uMinHeight < infoPtr->imageSize.cy + 2) {
	      lpBand->uMinHeight = infoPtr->imageSize.cy + 2;
	      lpBand->rcBand.bottom = lpBand->rcBand.top + lpBand->uMinHeight;
	  }  */
      }
      else {
	  /* set initial caption text rectangle */
	  SetRect (&lpBand->rcCapText, lpBand->rcCapImage.right, lpBand->rcBand.top+1,
		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
970
      }
Eric Kohl's avatar
Eric Kohl committed
971

972
      /* text is visible */
973
      if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
974
	  lpBand->fDraw |= DRAW_TEXT;
975
	  lpBand->rcCapText.right = max(lpBand->rcCapText.left,
976
					lpBand->rcCapText.right-REBAR_POST_TEXT);
977
      }
Eric Kohl's avatar
Eric Kohl committed
978

979 980
      /* set initial child window rectangle if there is a child */
      if (lpBand->fMask & RBBIM_CHILD) {
981 982 983 984 985
	  xoff = lpBand->offChild.cx;
	  yoff = lpBand->offChild.cy;
	  SetRect (&lpBand->rcChild,
		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top+yoff,
		   lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
Robert Shearman's avatar
Robert Shearman committed
986 987 988 989 990 991 992
	  if ((lpBand->fStyle & RBBS_USECHEVRON) && (lpBand->rcChild.right - lpBand->rcChild.left < lpBand->cxIdeal))
	  {
	      lpBand->rcChild.right -= CHEVRON_WIDTH;
	      SetRect(&lpBand->rcChevron, lpBand->rcChild.right,
	              lpBand->rcChild.top, lpBand->rcChild.right + CHEVRON_WIDTH,
	              lpBand->rcChild.bottom);
	  }
993 994
      }
      else {
995 996 997
          SetRect (&lpBand->rcChild,
		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top,
		   lpBand->rcBand.right, lpBand->rcBand.bottom);
998 999
      }

1000
      /* flag if notify required and invalidate rectangle */
1001
      if (notify &&
1002 1003 1004
	  ((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);
1005
          TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
1006 1007 1008 1009
		oldChild.left, oldChild.top,
	        oldChild.right, oldChild.bottom,
		lpBand->rcChild.left, lpBand->rcChild.top,
	        lpBand->rcChild.right, lpBand->rcChild.bottom);
1010 1011
      }
      if (lpBand->fDraw & NTF_INVALIDATE) {
1012
          TRACE("invalidating (%d,%d)-(%d,%d)\n",
1013
		lpBand->rcBand.left,
1014
		lpBand->rcBand.top,
1015
		lpBand->rcBand.right + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0),
1016 1017 1018 1019 1020
		lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0));
	  lpBand->fDraw &= ~NTF_INVALIDATE;
	  work = lpBand->rcBand;
	  if (lpBand->fDraw & DRAW_RIGHTSEP) work.right += SEP_WIDTH_SIZE;
	  if (lpBand->fDraw & DRAW_BOTTOMSEP) work.bottom += SEP_WIDTH_SIZE;
1021
	  InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
1022
      }
Eric Kohl's avatar
Eric Kohl committed
1023 1024 1025 1026 1027

    }

}

1028 1029

static VOID
1030
REBAR_CalcVertBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
1031 1032 1033
     /* Function: this routine initializes all the rectangles in */
     /*  each band in a row to fit in the adjusted rcBand rect.  */
     /* *** Supports only Vertical bars. ***                     */
1034
{
1035 1036 1037
    REBAR_BAND *lpBand;
    UINT i, xoff, yoff;
    HWND parenthwnd;
1038
    RECT oldChild, work;
1039 1040

    /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
1041
    parenthwnd = GetParent (infoPtr->hwndSelf);
1042

1043
    for(i=rstart; i<rend; i++){
1044 1045 1046
	lpBand = &infoPtr->bands[i];
	if (HIDDENBAND(lpBand)) continue;
	oldChild = lpBand->rcChild;
1047

1048 1049 1050
	/* set initial gripper rectangle */
	SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
		 lpBand->rcBand.right, lpBand->rcBand.top);
1051

1052 1053 1054 1055
	/* calculate gripper rectangle */
	if (lpBand->fStatus & HAS_GRIPPER) {
	    lpBand->fDraw |= DRAW_GRIPPER;

1056
	    if (infoPtr->dwStyle & RBS_VERTICALGRIPPER) {
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
		/*  vertical gripper  */
		lpBand->rcGripper.left   += 3;
		lpBand->rcGripper.right  = lpBand->rcGripper.left + GRIPPER_WIDTH;
		lpBand->rcGripper.top    += REBAR_PRE_GRIPPER;
		lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_HEIGHT;

		/* initialize Caption image rectangle  */
		SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
			 lpBand->rcBand.right,
			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
	    }
	    else {
		/*  horizontal gripper  */
1071 1072
		lpBand->rcGripper.left   += 2;
		lpBand->rcGripper.right  -= 2;
1073 1074 1075 1076 1077 1078 1079 1080 1081
		lpBand->rcGripper.top    += REBAR_PRE_GRIPPER;
		lpBand->rcGripper.bottom  = lpBand->rcGripper.top + GRIPPER_WIDTH;

		/* initialize Caption image rectangle  */
		SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
			 lpBand->rcBand.right,
			 lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
	    }
1082
	}
1083 1084 1085 1086 1087
	else {  /* no gripper will be drawn */
	    xoff = 0;
	    if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
		/* if no gripper but either image or text, then leave space */
		xoff = REBAR_ALWAYS_SPACE;
1088
	    /* initialize Caption image rectangle  */
1089
	    SetRect (&lpBand->rcCapImage,
1090 1091
		     lpBand->rcBand.left, lpBand->rcBand.top+xoff,
		     lpBand->rcBand.right, lpBand->rcBand.top+xoff);
1092 1093
	}

1094 1095 1096 1097 1098 1099 1100 1101
	/* image is visible */
	if (lpBand->fStatus & HAS_IMAGE) {
	    lpBand->fDraw |= DRAW_IMAGE;

	    lpBand->rcCapImage.right  = lpBand->rcCapImage.left + infoPtr->imageSize.cx;
	    lpBand->rcCapImage.bottom += infoPtr->imageSize.cy;

	    /* set initial caption text rectangle */
1102
	    SetRect (&lpBand->rcCapText,
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
		     lpBand->rcBand.left, lpBand->rcCapImage.bottom+REBAR_POST_IMAGE,
		     lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
	    /* update band height *
	       if (lpBand->uMinHeight < infoPtr->imageSize.cx + 2) {
	       lpBand->uMinHeight = infoPtr->imageSize.cx + 2;
	       lpBand->rcBand.right = lpBand->rcBand.left + lpBand->uMinHeight;
	       } */
	}
	else {
	    /* set initial caption text rectangle */
1113
	    SetRect (&lpBand->rcCapText,
1114 1115
		     lpBand->rcBand.left, lpBand->rcCapImage.bottom,
		     lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
1116 1117
	}

1118
	/* text is visible */
1119
	if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
1120 1121
	    lpBand->fDraw |= DRAW_TEXT;
	    lpBand->rcCapText.bottom = max(lpBand->rcCapText.top,
1122
					   lpBand->rcCapText.bottom);
1123
	}
1124

1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
	/* set initial child window rectangle if there is a child */
	if (lpBand->fMask & RBBIM_CHILD) {
	    yoff = lpBand->offChild.cx;
	    xoff = lpBand->offChild.cy;
	    SetRect (&lpBand->rcChild,
		     lpBand->rcBand.left+xoff, lpBand->rcBand.top+lpBand->cxHeader,
		     lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
	}
	else {
	    SetRect (&lpBand->rcChild,
		     lpBand->rcBand.left, lpBand->rcBand.top+lpBand->cxHeader,
		     lpBand->rcBand.right, lpBand->rcBand.bottom);
	}
1138

1139
	/* flag if notify required and invalidate rectangle */
1140
	if (notify &&
1141 1142 1143
	    ((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);
1144
            TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
1145 1146 1147 1148 1149 1150
		  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) {
1151
            TRACE("invalidating (%d,%d)-(%d,%d)\n",
1152
		  lpBand->rcBand.left,
1153
		  lpBand->rcBand.top,
1154
		  lpBand->rcBand.right + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0),
1155 1156 1157 1158 1159
		  lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0));
	    lpBand->fDraw &= ~NTF_INVALIDATE;
	    work = lpBand->rcBand;
	    if (lpBand->fDraw & DRAW_RIGHTSEP) work.bottom += SEP_WIDTH_SIZE;
	    if (lpBand->fDraw & DRAW_BOTTOMSEP) work.right += SEP_WIDTH_SIZE;
1160
	    InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
Eric Kohl's avatar
Eric Kohl committed
1161
	}
1162

1163 1164 1165 1166
    }
}


Eric Kohl's avatar
Eric Kohl committed
1167
static VOID
1168 1169 1170 1171 1172
REBAR_ForceResize (REBAR_INFO *infoPtr)
     /* Function: This changes the size of the REBAR window to that */
     /*  calculated by REBAR_Layout.                                */
{
    RECT rc;
1173 1174 1175
    INT x, y, width, height;
    INT xedge = GetSystemMetrics(SM_CXEDGE);
    INT yedge = GetSystemMetrics(SM_CYEDGE);
1176 1177 1178

    GetClientRect (infoPtr->hwndSelf, &rc);

1179
    TRACE( " old [%d x %d], new [%d x %d], client [%d x %d]\n",
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201
	   infoPtr->oldSize.cx, infoPtr->oldSize.cy,
	   infoPtr->calcSize.cx, infoPtr->calcSize.cy,
	   rc.right, rc.bottom);

    /* If we need to shrink client, then skip size test */
    if ((infoPtr->calcSize.cy >= rc.bottom) &&
	(infoPtr->calcSize.cx >= rc.right)) {

	/* if size did not change then skip process */
	if ((infoPtr->oldSize.cx == infoPtr->calcSize.cx) &&
	    (infoPtr->oldSize.cy == infoPtr->calcSize.cy) &&
	    !(infoPtr->fStatus & RESIZE_ANYHOW))
	    {
		TRACE("skipping reset\n");
		return;
	    }
    }

    infoPtr->fStatus &= ~RESIZE_ANYHOW;
    /* Set flag to ignore next WM_SIZE message */
    infoPtr->fStatus |= AUTO_RESIZE;

1202 1203 1204 1205
    width = 0;
    height = 0;
    x = 0;
    y = 0;
1206

1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
    if (infoPtr->dwStyle & WS_BORDER) {
	width = 2 * xedge;
	height = 2 * yedge;
    }

    if (!(infoPtr->dwStyle & CCS_NOPARENTALIGN)) {
	INT mode = infoPtr->dwStyle & (CCS_VERT | CCS_TOP | CCS_BOTTOM);
	RECT rcPcl;

	GetClientRect(GetParent(infoPtr->hwndSelf), &rcPcl);
	switch (mode) {
	case CCS_TOP:
	    /* _TOP sets width to parents width */
	    width += (rcPcl.right - rcPcl.left);
	    height += infoPtr->calcSize.cy;
	    x += ((infoPtr->dwStyle & WS_BORDER) ? -xedge : 0);
	    y += ((infoPtr->dwStyle & WS_BORDER) ? -yedge : 0);
	    y += ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
	    break;
	case CCS_BOTTOM:
	    /* FIXME: wrong wrong wrong */
	    /* _BOTTOM sets width to parents width */
	    width += (rcPcl.right - rcPcl.left);
	    height += infoPtr->calcSize.cy;
      	    x += -xedge;
	    y = rcPcl.bottom - height + 1;
	    break;
	case CCS_LEFT:
	    /* _LEFT sets height to parents height */
	    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;
	case CCS_RIGHT:
	    /* FIXME: wrong wrong wrong */
	    /* _RIGHT sets height to parents height */
	    width += infoPtr->calcSize.cx;
	    height += (rcPcl.bottom - rcPcl.top);
	    x = rcPcl.right - width + 1;
      	    y = -yedge;
	    break;
	default:
	    width += infoPtr->calcSize.cx;
	    height += infoPtr->calcSize.cy;
	}
    }
    else {
	width += infoPtr->calcSize.cx;
	height += infoPtr->calcSize.cy;
1258 1259
	x = infoPtr->origin.x;
	y = infoPtr->origin.y;
1260 1261
    }

1262
    TRACE("hwnd %p, style=%08x, setting at (%d,%d) for (%d,%d)\n",
1263 1264 1265 1266
	infoPtr->hwndSelf, infoPtr->dwStyle,
	x, y, width, height);
    SetWindowPos (infoPtr->hwndSelf, 0, x, y, width, height,
		    SWP_NOZORDER);
1267
    infoPtr->fStatus &= ~AUTO_RESIZE;
1268 1269 1270 1271 1272 1273
}


static VOID
REBAR_MoveChildWindows (REBAR_INFO *infoPtr, UINT start, UINT endplus)
{
1274
    static const WCHAR strComboBox[] = { 'C','o','m','b','o','B','o','x',0 };
1275
    REBAR_BAND *lpBand;
1276
    WCHAR szClassName[40];
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
    UINT i;
    NMREBARCHILDSIZE  rbcz;
    NMHDR heightchange;
    HDWP deferpos;

    if (!(deferpos = BeginDeferWindowPos(infoPtr->uNumBands)))
        ERR("BeginDeferWindowPos returned NULL\n");

    for (i = start; i < endplus; i++) {
	lpBand = &infoPtr->bands[i];

	if (HIDDENBAND(lpBand)) continue;
	if (lpBand->hwndChild) {
1290
	    TRACE("hwndChild = %p\n", lpBand->hwndChild);
1291

1292 1293 1294 1295 1296 1297
	    /* Always geterate the RBN_CHILDSIZE even it child
		   did not change */
	    rbcz.uBand = i;
	    rbcz.wID = lpBand->wID;
	    rbcz.rcChild = lpBand->rcChild;
	    rbcz.rcBand = lpBand->rcBand;
1298
	    if (infoPtr->dwStyle & CCS_VERT)
1299 1300 1301
		rbcz.rcBand.top += lpBand->cxHeader;
	    else
		rbcz.rcBand.left += lpBand->cxHeader;
1302 1303 1304
	    REBAR_Notify ((NMHDR *)&rbcz, infoPtr, RBN_CHILDSIZE);
	    if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) {
		TRACE("Child rect changed by NOTIFY for band %u\n", i);
1305
		TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
1306 1307 1308 1309
		      lpBand->rcChild.left, lpBand->rcChild.top,
		      lpBand->rcChild.right, lpBand->rcChild.bottom,
		      rbcz.rcChild.left, rbcz.rcChild.top,
		      rbcz.rcChild.right, rbcz.rcChild.bottom);
1310
		lpBand->rcChild = rbcz.rcChild;  /* *** ??? */
1311 1312
	    }

1313 1314 1315 1316 1317 1318 1319 1320
	    /* native (IE4 in "Favorites" frame **1) does:
	     *   SetRect (&rc, -1, -1, -1, -1)
	     *   EqualRect (&rc,band->rc???)
	     *   if ret==0
	     *     CopyRect (band->rc????, &rc)
	     *     set flag outside of loop
	     */

1321 1322 1323
	    GetClassNameW (lpBand->hwndChild, szClassName, sizeof(szClassName)/sizeof(szClassName[0]));
	    if (!lstrcmpW (szClassName, strComboBox) ||
		!lstrcmpW (szClassName, WC_COMBOBOXEXW)) {
1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
		INT nEditHeight, yPos;
		RECT rc;

		/* special placement code for combo or comboex box */


		/* get size of edit line */
		GetWindowRect (lpBand->hwndChild, &rc);
		nEditHeight = rc.bottom - rc.top;
		yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;

		/* center combo box inside child area */
1336
		TRACE("moving child (Combo(Ex)) %p to (%d,%d) for (%d,%d)\n",
1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
		      lpBand->hwndChild,
		      lpBand->rcChild.left, yPos,
		      lpBand->rcChild.right - lpBand->rcChild.left,
		      nEditHeight);
		deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
					   lpBand->rcChild.left,
					   /*lpBand->rcChild.top*/ yPos,
					   lpBand->rcChild.right - lpBand->rcChild.left,
					   nEditHeight,
					   SWP_NOZORDER);
		if (!deferpos)
		    ERR("DeferWindowPos returned NULL\n");
	    }
	    else {
1351
		TRACE("moving child (Other) %p to (%d,%d) for (%d,%d)\n",
1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368
		      lpBand->hwndChild,
		      lpBand->rcChild.left, lpBand->rcChild.top,
		      lpBand->rcChild.right - lpBand->rcChild.left,
		      lpBand->rcChild.bottom - lpBand->rcChild.top);
		deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
					   lpBand->rcChild.left,
					   lpBand->rcChild.top,
					   lpBand->rcChild.right - lpBand->rcChild.left,
					   lpBand->rcChild.bottom - lpBand->rcChild.top,
					   SWP_NOZORDER);
		if (!deferpos)
		    ERR("DeferWindowPos returned NULL\n");
	    }
	}
    }
    if (!EndDeferWindowPos(deferpos))
        ERR("EndDeferWindowPos returned NULL\n");
1369

1370 1371
    if (infoPtr->DoRedraw)
	UpdateWindow (infoPtr->hwndSelf);
1372

1373 1374
    if (infoPtr->fStatus & NTF_HGHTCHG) {
        infoPtr->fStatus &= ~NTF_HGHTCHG;
1375 1376 1377 1378 1379 1380
        /*
         * We need to force a resize here, because some applications
         * try to get the rebar size during processing of the 
         * RBN_HEIGHTCHANGE notification.
         */
        REBAR_ForceResize (infoPtr);
1381
        REBAR_Notify (&heightchange, infoPtr, RBN_HEIGHTCHANGE);
1382
    }
1383 1384 1385 1386 1387 1388 1389 1390 1391

    /* native (from **1 above) does:
     *      UpdateWindow(rebar)
     *      REBAR_ForceResize
     *      RBN_HEIGHTCHANGE if necessary
     *      if ret from any EqualRect was 0
     *         Goto "BeginDeferWindowPos"
     */

1392 1393 1394 1395 1396
}


static VOID
REBAR_Layout (REBAR_INFO *infoPtr, LPRECT lpRect, BOOL notify, BOOL resetclient)
1397 1398 1399
     /* 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.                    */
Eric Kohl's avatar
Eric Kohl committed
1400
{
1401
    REBAR_BAND *lpBand, *prevBand;
1402
    RECT rcClient, rcAdj;
1403
    INT initx, inity, x, y, cx, cxsep, mmcy, mcy, clientcx, clientcy;
1404
    INT adjcx, adjcy, row, rightx, bottomy, origheight;
1405
    UINT i, j, rowstart, origrows, cntonrow;
1406
    BOOL dobreak;
Eric Kohl's avatar
Eric Kohl committed
1407

1408 1409 1410 1411 1412 1413
    if (!(infoPtr->fStatus & BAND_NEEDS_LAYOUT)) {
	TRACE("no layout done. No band changed.\n");
	REBAR_DumpBand (infoPtr);
	return;
    }
    infoPtr->fStatus &= ~BAND_NEEDS_LAYOUT;
1414
    if (!infoPtr->DoRedraw) infoPtr->fStatus |= BAND_NEEDS_REDRAW;
1415 1416

    GetClientRect (infoPtr->hwndSelf, &rcClient);
1417
    TRACE("Client is (%d,%d)-(%d,%d)\n",
1418
	  rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
Eric Kohl's avatar
Eric Kohl committed
1419

1420 1421
    if (lpRect) {
	rcAdj = *lpRect;
1422
	TRACE("adjustment rect is (%d,%d)-(%d,%d)\n",
1423
	      rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom);
1424 1425
    }
    else {
1426
        CopyRect (&rcAdj, &rcClient);
1427
    }
Eric Kohl's avatar
Eric Kohl committed
1428

1429 1430 1431 1432 1433
    clientcx = rcClient.right - rcClient.left;
    clientcy = rcClient.bottom - rcClient.top;
    adjcx = rcAdj.right - rcAdj.left;
    adjcy = rcAdj.bottom - rcAdj.top;
    if (resetclient) {
1434 1435 1436
        TRACE("window client rect will be set to adj rect\n");
        clientcx = adjcx;
        clientcy = adjcy;
1437
    }
1438

1439 1440 1441 1442 1443 1444
    if (!infoPtr->DoRedraw && (clientcx == 0) && (clientcy == 0)) {
	ERR("no redraw and client is zero, skip layout\n");
	infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
	return;
    }

1445
    /* save height of original control */
1446
    if (infoPtr->dwStyle & CCS_VERT)
1447 1448 1449
        origheight = infoPtr->calcSize.cx;
    else
        origheight = infoPtr->calcSize.cy;
1450
    origrows = infoPtr->uNumRows;
1451

1452 1453 1454
    initx = 0;
    inity = 0;

1455 1456
    /* ******* Start Phase 1 - all bands on row at minimum size ******* */

1457 1458 1459 1460
    TRACE("band loop constants, clientcx=%d, clientcy=%d, adjcx=%d, adjcy=%d\n",
	  clientcx, clientcy, adjcx, adjcy);
    x = initx;
    y = inity;
1461
    row = 0;
1462 1463
    cx = 0;
    mcy = 0;
1464
    rowstart = 0;
1465
    prevBand = NULL;
1466
    cntonrow = 0;
1467

Eric Kohl's avatar
Eric Kohl committed
1468 1469
    for (i = 0; i < infoPtr->uNumBands; i++) {
	lpBand = &infoPtr->bands[i];
1470 1471
	lpBand->fDraw = 0;
	lpBand->iRow = row;
Eric Kohl's avatar
Eric Kohl committed
1472

Robert Shearman's avatar
Robert Shearman committed
1473 1474
	SetRectEmpty(&lpBand->rcChevron);

1475
	if (HIDDENBAND(lpBand)) continue;
Eric Kohl's avatar
Eric Kohl committed
1476

1477
	lpBand->rcoldBand = lpBand->rcBand;
1478

1479 1480 1481
	/* Set the offset of the child window */
	if ((lpBand->fMask & RBBIM_CHILD) &&
	    !(lpBand->fStyle & RBBS_FIXEDSIZE)) {
1482
	    lpBand->offChild.cx = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 4 : 0);
1483 1484 1485
	}
	lpBand->offChild.cy = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 2 : 0);

1486
	/* separator from previous band */
1487
	cxsep = (cntonrow == 0) ? 0 : SEP_WIDTH;
1488
	cx = lpBand->lcx;
1489

1490
        /* In native, 0 as one of the coordinates means no limit */
1491
	if (infoPtr->dwStyle & CCS_VERT)
1492
	    dobreak = (adjcy && (y + cx + cxsep > adjcy));
1493
        else
1494
	    dobreak = (adjcx && (x + cx + cxsep > adjcx));
1495

1496
	/* This is the check for whether we need to start a new row */
1497
	if ( ( (lpBand->fStyle & RBBS_BREAK) && (i != 0) ) ||
1498
	     ( ((infoPtr->dwStyle & CCS_VERT) ? (y != 0) : (x != 0)) && dobreak)) {
1499 1500 1501 1502

	    for (j = rowstart; j < i; j++) {
		REBAR_BAND *lpB;
		lpB = &infoPtr->bands[j];
1503
		if (infoPtr->dwStyle & CCS_VERT) {
1504 1505 1506 1507 1508 1509 1510
		    lpB->rcBand.right  = lpB->rcBand.left + mcy;
		}
		else {
		    lpB->rcBand.bottom = lpB->rcBand.top + mcy;
		}
	    }

1511
	    TRACE("P1 Spliting to new row %d on band %u\n", row+1, i);
1512
	    if (infoPtr->dwStyle & CCS_VERT) {
1513
		y = inity;
1514 1515 1516
		x += (mcy + SEP_WIDTH);
	    }
	    else {
1517
		x = initx;
1518 1519
		y += (mcy + SEP_WIDTH);
	    }
1520

1521 1522 1523 1524 1525
	    mcy = 0;
	    cxsep = 0;
	    row++;
	    lpBand->iRow = row;
	    prevBand = NULL;
1526
	    rowstart = i;
1527
	    cntonrow = 0;
1528
	}
1529

1530
	if (mcy < lpBand->lcy + REBARSPACE(lpBand))
1531
	    mcy = lpBand->lcy + REBARSPACE(lpBand);
1532 1533 1534

	/* if boundary rect specified then limit mcy */
	if (lpRect) {
1535
	    if (infoPtr->dwStyle & CCS_VERT) {
1536
	        if (adjcx && (x+mcy > adjcx)) {
1537
		    mcy = adjcx - x;
1538
		    TRACE("P1 row %u limiting mcy=%d, adjcx=%d, x=%d\n",
1539 1540
			  i, mcy, adjcx, x);
		}
1541
	    }
1542
	    else {
1543
	        if (adjcy && (y+mcy > adjcy)) {
1544
		    mcy = adjcy - y;
1545
		    TRACE("P1 row %u limiting mcy=%d, adjcy=%d, y=%d\n",
1546 1547
			  i, mcy, adjcy, y);
		}
1548
	    }
1549
	}
Eric Kohl's avatar
Eric Kohl committed
1550

1551
	TRACE("P1 band %u, row %d, x=%d, y=%d, cxsep=%d, cx=%d\n",
1552 1553
	      i, row,
	      x, y, cxsep, cx);
1554
	if (infoPtr->dwStyle & CCS_VERT) {
1555 1556 1557 1558
	    /* 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;
1559
	    lpBand->rcBand.right  = x + min(mcy,
1560
					    lpBand->lcy+REBARSPACE(lpBand));
1561 1562 1563 1564
	    lpBand->rcBand.top    = min(bottomy, y + cxsep);
	    lpBand->rcBand.bottom = bottomy;
	    lpBand->uMinHeight = lpBand->lcy;
	    y = bottomy;
1565 1566
	}
	else {
1567 1568 1569 1570 1571 1572
	    /* 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;
1573
	    lpBand->rcBand.bottom = y + min(mcy,
1574
					    lpBand->lcy+REBARSPACE(lpBand));
1575 1576
	    lpBand->uMinHeight = lpBand->lcy;
	    x = rightx;
1577
	}
1578
	TRACE("P1 band %u, row %d, (%d,%d)-(%d,%d)\n",
1579 1580 1581
	      i, row,
	      lpBand->rcBand.left, lpBand->rcBand.top,
	      lpBand->rcBand.right, lpBand->rcBand.bottom);
1582
	prevBand = lpBand;
1583
	cntonrow++;
1584 1585 1586

    } /* for (i = 0; i < infoPtr->uNumBands... */

1587
    if (infoPtr->dwStyle & CCS_VERT)
1588 1589 1590 1591
        x += mcy;
    else
        y += mcy;

1592 1593
    for (j = rowstart; j < infoPtr->uNumBands; j++) {
	lpBand = &infoPtr->bands[j];
1594
	if (infoPtr->dwStyle & CCS_VERT) {
1595 1596 1597 1598 1599 1600 1601
	    lpBand->rcBand.right  = lpBand->rcBand.left + mcy;
	}
	else {
	    lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
	}
    }

1602
    if (infoPtr->uNumBands)
1603
        infoPtr->uNumRows = row + 1;
1604 1605 1606 1607

    /* ******* End Phase 1 - all bands on row at minimum size ******* */


1608 1609 1610
    /* ******* Start Phase 1a - Adjust heights for RBS_VARHEIGHT off ******* */

    mmcy = 0;
1611
    if (!(infoPtr->dwStyle & RBS_VARHEIGHT)) {
1612 1613 1614 1615 1616 1617
	INT xy;

	/* get the max height of all bands */
	for (i=0; i<infoPtr->uNumBands; i++) {
	    lpBand = &infoPtr->bands[i];
	    if (HIDDENBAND(lpBand)) continue;
1618
	    if (infoPtr->dwStyle & CCS_VERT)
1619 1620 1621 1622 1623 1624 1625
		mmcy = max(mmcy, lpBand->rcBand.right - lpBand->rcBand.left);
	    else
		mmcy = max(mmcy, lpBand->rcBand.bottom - lpBand->rcBand.top);
	}

	/* now adjust all rectangles by using the height found above */
	xy = 0;
1626
	row = 0;
1627 1628 1629 1630 1631
	for (i=0; i<infoPtr->uNumBands; i++) {
	    lpBand = &infoPtr->bands[i];
	    if (HIDDENBAND(lpBand)) continue;
	    if (lpBand->iRow != row)
		xy += (mmcy + SEP_WIDTH);
1632
	    if (infoPtr->dwStyle & CCS_VERT) {
1633 1634 1635 1636 1637 1638 1639 1640 1641 1642
		lpBand->rcBand.left = xy;
		lpBand->rcBand.right = xy + mmcy;
	    }
	    else {
		lpBand->rcBand.top = xy;
		lpBand->rcBand.bottom = xy + mmcy;
	    }
	}

	/* set the x/y values to the correct maximum */
1643
	if (infoPtr->dwStyle & CCS_VERT)
1644 1645 1646 1647 1648 1649 1650 1651
	    x = xy + mmcy;
	else
	    y = xy + mmcy;
    }

    /* ******* End Phase 1a - Adjust heights for RBS_VARHEIGHT off ******* */


1652
    /* ******* Start Phase 2 - split rows till adjustment height full ******* */
1653

1654
    /* assumes that the following variables contain:                 */
1655 1656 1657
    /*   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)) {
1658
        INT i, prev_rh, new_rh, adj_rh, prev_idx, current_idx;
1659
	REBAR_BAND *prev, *current, *walk;
1660
	UINT j;
1661

1662
/* FIXME:  problem # 2 */
1663
	if (((infoPtr->dwStyle & CCS_VERT) ?
1664 1665 1666
#if PROBLEM2
	     (x < adjcx) : (y < adjcy)
#else
1667
	     (adjcx - x > 5) : (adjcy - y > 4)
1668 1669
#endif
	     ) &&
1670
	    (infoPtr->uNumBands > 1)) {
1671
	    for (i=(INT)infoPtr->uNumBands-2; i>=0; i--) {
1672
		TRACE("P2 adjcx=%d, adjcy=%d, x=%d, y=%d\n",
1673
		      adjcx, adjcy, x, y);
1674 1675

		/* find the current band (starts at i+1) */
1676
		current = &infoPtr->bands[i+1];
1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697
		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);
1698
		if (prev->iRow == current->iRow) {
1699
		    new_rh = (infoPtr->dwStyle & RBS_VARHEIGHT) ?
1700
			current->lcy + REBARSPACE(current) :
1701 1702
			mmcy;
		    adj_rh = new_rh + SEP_WIDTH;
1703 1704 1705
		    infoPtr->uNumRows++;
		    current->fDraw |= NTF_INVALIDATE;
		    current->iRow++;
1706
		    if (infoPtr->dwStyle & CCS_VERT) {
1707
		        current->rcBand.top = inity;
1708 1709 1710 1711 1712 1713
			current->rcBand.bottom = clientcy;
			current->rcBand.left += (prev_rh + SEP_WIDTH);
			current->rcBand.right = current->rcBand.left + new_rh;
			x += adj_rh;
		    }
		    else {
1714
		        current->rcBand.left = initx;
1715 1716 1717 1718 1719
			current->rcBand.right = clientcx;
			current->rcBand.top += (prev_rh + SEP_WIDTH);
			current->rcBand.bottom = current->rcBand.top + new_rh;
			y += adj_rh;
		    }
1720
                    TRACE("P2 moving band %d to own row at (%d,%d)-(%d,%d)\n",
1721
			  current_idx,
1722 1723
			  current->rcBand.left, current->rcBand.top,
			  current->rcBand.right, current->rcBand.bottom);
1724
                    TRACE("P2 prev band %d at (%d,%d)-(%d,%d)\n",
1725
			  prev_idx,
1726 1727
			  prev->rcBand.left, prev->rcBand.top,
			  prev->rcBand.right, prev->rcBand.bottom);
1728
		    TRACE("P2 values: prev_rh=%d, new_rh=%d, adj_rh=%d\n",
1729
			  prev_rh, new_rh, adj_rh);
1730
		    /* for bands below current adjust row # and top/bottom */
1731
		    for (j = current_idx+1; j<infoPtr->uNumBands; j++) {
1732
		        walk = &infoPtr->bands[j];
1733
			if (HIDDENBAND(walk)) continue;
1734 1735
			walk->fDraw |= NTF_INVALIDATE;
			walk->iRow++;
1736
			if (infoPtr->dwStyle & CCS_VERT) {
1737 1738 1739 1740 1741 1742 1743 1744
			    walk->rcBand.left += adj_rh;
			    walk->rcBand.right += adj_rh;
			}
			else {
			    walk->rcBand.top += adj_rh;
			    walk->rcBand.bottom += adj_rh;
			}
		    }
1745
		    if ((infoPtr->dwStyle & CCS_VERT) ? (x >= adjcx) : (y >= adjcy))
1746 1747 1748 1749
		        break; /* all done */
		}
	    }
	}
Eric Kohl's avatar
Eric Kohl committed
1750
    }
1751 1752 1753 1754

    /* ******* End Phase 2 - split rows till adjustment height full ******* */


1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
    /* ******* Start Phase 2a - mark first and last band in each ******* */

    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;
        }
        else if( prevBand->iRow == lpBand->iRow )
            prevBand = lpBand;
        else {
            prevBand->fDraw |= DRAW_LAST_IN_ROW;
            lpBand->fDraw |= DRAW_FIRST_IN_ROW;
            prevBand = lpBand;
        }
    }
    if( prevBand )
        prevBand->fDraw |= DRAW_LAST_IN_ROW;

    /* ******* End Phase 2a - mark first and last band in each ******* */
1778 1779 1780


    /* ******* Start Phase 2b - adjust all bands for height full ******* */
1781 1782 1783 1784 1785 1786
    /* assumes that the following variables contain:                 */
    /*   y/x     current height/width of all rows                    */
    /*   clientcy/clientcx     height/width of client area           */

    if (((infoPtr->dwStyle & CCS_VERT) ? clientcx > x : clientcy > y) &&
	infoPtr->uNumBands) {
1787
	INT diff, i;
1788
	UINT j;
1789 1790

	diff = (infoPtr->dwStyle & CCS_VERT) ? clientcx - x : clientcy - y;
1791 1792

        /* iterate backwards thru the rows */
1793
        for (i = infoPtr->uNumBands-1; i>=0; i--) {
1794
	    lpBand = &infoPtr->bands[i];
1795
	    if(HIDDENBAND(lpBand)) continue;
1796 1797

	    /* if row has more than 1 band, ignore it */
1798
            if( !(lpBand->fDraw&DRAW_FIRST_IN_ROW) )
1799
                continue;
1800
            if( !(lpBand->fDraw&DRAW_LAST_IN_ROW) )
1801 1802
                continue;

1803
            /* FIXME: this next line is wrong, but fixing it to be inverted causes IE's sidebars to be the wrong size */
1804
	    if (lpBand->fMask & RBBS_VARIABLEHEIGHT) continue;
1805
	    if (((INT)lpBand->cyMaxChild < 1) ||
1806 1807
		((INT)lpBand->cyIntegral < 1)) {
		if (lpBand->cyMaxChild + lpBand->cyIntegral == 0) continue;
1808
		ERR("P2b band %u RBBS_VARIABLEHEIGHT set but cyMax=%d, cyInt=%d\n",
1809
		    i, lpBand->cyMaxChild, lpBand->cyIntegral);
1810 1811 1812
		continue;
	    }
	    /* j is now the maximum height/width in the client area */
1813
	    j = ((diff / lpBand->cyIntegral) * lpBand->cyIntegral) +
1814
		ircBw(lpBand);
1815
	    if (j > lpBand->cyMaxChild + REBARSPACE(lpBand))
1816
		j = lpBand->cyMaxChild + REBARSPACE(lpBand);
1817 1818 1819 1820 1821
	    diff -= (j - ircBw(lpBand));
	    if (infoPtr->dwStyle & CCS_VERT)
		lpBand->rcBand.right = lpBand->rcBand.left + j;
	    else
		lpBand->rcBand.bottom = lpBand->rcBand.top + j;
1822
            TRACE("P2b band %d, row %d changed to (%d,%d)-(%d,%d)\n",
1823
		  i, lpBand->iRow,
1824 1825 1826 1827 1828
		  lpBand->rcBand.left, lpBand->rcBand.top,
		  lpBand->rcBand.right, lpBand->rcBand.bottom);
	    if (diff <= 0) break;
	}
	if (diff < 0) {
1829
	    ERR("P2b allocated more than available, diff=%d\n", diff);
1830 1831 1832 1833 1834 1835 1836 1837
	    diff = 0;
	}
	if (infoPtr->dwStyle & CCS_VERT)
	    x = clientcx - diff;
	else
	    y = clientcy - diff;
    }

1838
    /* ******* End Phase 2b - adjust all bands for height full ******* */
1839 1840


1841 1842
    /* ******* Start Phase 3 - adjust all bands for width full ******* */

1843
    if (infoPtr->uNumBands) {
1844
        int startband;
1845

1846
	/* If RBS_BANDBORDERS set then indicate to draw bottom separator */
1847
	/* on all bands in all rows but last row.                        */
1848 1849
	/* Also indicate to draw the right separator for each band in    */
	/* each row but the rightmost band.                              */
1850
	if (infoPtr->dwStyle & RBS_BANDBORDERS) {
1851

1852 1853 1854 1855 1856 1857
            for (i=0; i<infoPtr->uNumBands; i++) {
	        lpBand = &infoPtr->bands[i];
		if (HIDDENBAND(lpBand))
                    continue;

                /* not righthand bands */
1858
                if( !(lpBand->fDraw & DRAW_LAST_IN_ROW) )
1859 1860 1861
		    lpBand->fDraw |= DRAW_RIGHTSEP;

                /* not the last row */
1862
                if( lpBand->iRow != infoPtr->uNumRows )
1863
		    lpBand->fDraw |= DRAW_BOTTOMSEP;
1864 1865
	    }
	}
1866

1867 1868
	/* Distribute the extra space on the horizontal and adjust  */
	/* all bands in row to same height.                         */
1869
	mcy = 0;
1870
        startband = -1;
1871 1872 1873
        for (i=0; i<infoPtr->uNumBands; i++) {

            lpBand = &infoPtr->bands[i];
1874 1875 1876 1877 1878 1879 1880 1881

            if( lpBand->fDraw & DRAW_FIRST_IN_ROW )
            {
                startband = i;
                mcy = 0;
            }

            if ( (mcy < ircBw(lpBand)) && !HIDDENBAND(lpBand) )
1882 1883
                mcy = ircBw(lpBand);

1884
            if( lpBand->fDraw & DRAW_LAST_IN_ROW )
1885 1886
            {
	        TRACE("P3 processing row %d, starting band %d, ending band %d\n",
1887 1888 1889
		      lpBand->iRow, startband, i);
                if( startband < 0 )
                    ERR("Last band %d with no first, row %d\n", i, lpBand->iRow);
1890 1891

	        REBAR_AdjustBands (infoPtr, startband, i,
1892
			       (infoPtr->dwStyle & CCS_VERT) ?
1893
			       clientcy : clientcx, mcy);
1894
            }
1895 1896 1897
	}

	/* Calculate the other rectangles in each band */
1898
	if (infoPtr->dwStyle & CCS_VERT) {
1899
	    REBAR_CalcVertBand (infoPtr, 0, infoPtr->uNumBands,
1900
				notify);
1901 1902
	}
	else {
1903
	    REBAR_CalcHorzBand (infoPtr, 0, infoPtr->uNumBands,
1904
				notify);
1905
	}
1906 1907
    }

1908 1909
    /* ******* End Phase 3 - adjust all bands for width full ******* */

1910
    /* now compute size of Rebar itself */
1911
    infoPtr->oldSize = infoPtr->calcSize;
1912 1913 1914 1915 1916
    if (infoPtr->uNumBands == 0) {
	/* we have no bands, so make size the size of client */
	x = clientcx;
	y = clientcy;
    }
1917
    if (infoPtr->dwStyle & CCS_VERT) {
1918
        if( infoPtr->uNumBands != 0 && x < REBAR_MINSIZE )
1919
            x = REBAR_MINSIZE;
1920
	infoPtr->calcSize.cx = x;
1921
	infoPtr->calcSize.cy = clientcy;
1922 1923 1924
	TRACE("vert, notify=%d, x=%d, origheight=%d\n",
	      notify, x, origheight);
	if (notify && (x != origheight)) infoPtr->fStatus |= NTF_HGHTCHG;
1925 1926
    }
    else {
1927
        if( infoPtr->uNumBands != 0 && y < REBAR_MINSIZE )
1928
            y = REBAR_MINSIZE;
1929
	infoPtr->calcSize.cx = clientcx;
1930
	infoPtr->calcSize.cy = y;
1931 1932
	TRACE("horz, notify=%d, y=%d, origheight=%d\n",
	      notify, y, origheight);
1933
	if (notify && (y != origheight)) infoPtr->fStatus |= NTF_HGHTCHG;
1934
    }
Eric Kohl's avatar
Eric Kohl committed
1935

1936
    REBAR_DumpBand (infoPtr);
1937

1938
    REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands);
Eric Kohl's avatar
Eric Kohl committed
1939

1940
    REBAR_ForceResize (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
1941 1942 1943 1944
}


static VOID
1945
REBAR_ValidateBand (REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
1946 1947 1948 1949 1950
     /* Function:  This routine evaluates the band specs supplied */
     /*  by the user and updates the following 5 fields in        */
     /*  the internal band structure: cxHeader, lcx, lcy, hcx, hcy*/
{
    UINT header=0;
1951
    UINT textheight=0;
1952
    UINT i, nonfixed;
1953
    REBAR_BAND *tBand;
1954

1955
    lpBand->fStatus = 0;
1956 1957
    lpBand->lcx = 0;
    lpBand->lcy = 0;
1958 1959
    lpBand->ccx = 0;
    lpBand->ccy = 0;
1960 1961 1962
    lpBand->hcx = 0;
    lpBand->hcy = 0;

1963
    /* Data coming in from users into the cx... and cy... fields   */
1964 1965 1966 1967 1968 1969
    /* may be bad, just garbage, because the user never clears     */
    /* the fields. RB_{SET|INSERT}BAND{A|W} just passes the data   */
    /* along if the fields exist in the input area. Here we must   */
    /* determine if the data is valid. I have no idea how MS does  */
    /* the validation, but it does because the RB_GETBANDINFO      */
    /* returns a 0 when I know the sample program passed in an     */
1970
    /* address. Here I will use the algorithm that if the value    */
1971
    /* is greater than 65535 then it is bad and replace it with    */
1972
    /* a zero. Feel free to improve the algorithm.  -  GA 12/2000  */
1973 1974 1975 1976 1977 1978 1979 1980 1981
    if (lpBand->cxMinChild > 65535) lpBand->cxMinChild = 0;
    if (lpBand->cyMinChild > 65535) lpBand->cyMinChild = 0;
    if (lpBand->cx         > 65535) lpBand->cx         = 0;
    if (lpBand->cyChild    > 65535) lpBand->cyChild    = 0;
    if (lpBand->cyMaxChild > 65535) lpBand->cyMaxChild = 0;
    if (lpBand->cyIntegral > 65535) lpBand->cyIntegral = 0;
    if (lpBand->cxIdeal    > 65535) lpBand->cxIdeal    = 0;
    if (lpBand->cxHeader   > 65535) lpBand->cxHeader   = 0;

1982 1983 1984 1985 1986
    /* FIXME: probably should only set NEEDS_LAYOUT flag when */
    /*        values change. Till then always set it.         */
    TRACE("setting NEEDS_LAYOUT\n");
    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;

1987
    /* Header is where the image, text and gripper exist  */
1988
    /* in the band and precede the child window.          */
1989

1990 1991 1992 1993 1994 1995 1996 1997
    /* count number of non-FIXEDSIZE and non-Hidden bands */
    nonfixed = 0;
    for (i=0; i<infoPtr->uNumBands; i++){
	tBand = &infoPtr->bands[i];
	if (!HIDDENBAND(tBand) && !(tBand->fStyle & RBBS_FIXEDSIZE))
	    nonfixed++;
    }

1998
    /* calculate gripper rectangle */
1999
    if (  (!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
2000
	  ( (lpBand->fStyle & RBBS_GRIPPERALWAYS) ||
2001
	    ( !(lpBand->fStyle & RBBS_FIXEDSIZE) && (nonfixed > 1)))
2002 2003
       ) {
	lpBand->fStatus |= HAS_GRIPPER;
2004 2005
        if (infoPtr->dwStyle & CCS_VERT)
	    if (infoPtr->dwStyle & RBS_VERTICALGRIPPER)
2006 2007 2008 2009 2010 2011 2012
                header += (GRIPPER_HEIGHT + REBAR_PRE_GRIPPER);
            else
	        header += (GRIPPER_WIDTH + REBAR_PRE_GRIPPER);
        else
            header += (REBAR_PRE_GRIPPER + GRIPPER_WIDTH);
        /* Always have 4 pixels before anything else */
        header += REBAR_ALWAYS_SPACE;
2013 2014 2015 2016
    }

    /* image is visible */
    if ((lpBand->fMask & RBBIM_IMAGE) && (infoPtr->himl)) {
2017
	lpBand->fStatus |= HAS_IMAGE;
2018
        if (infoPtr->dwStyle & CCS_VERT) {
2019
	   header += (infoPtr->imageSize.cy + REBAR_POST_IMAGE);
2020 2021 2022
	   lpBand->lcy = infoPtr->imageSize.cx + 2;
	}
	else {
2023
	   header += (infoPtr->imageSize.cx + REBAR_POST_IMAGE);
2024 2025 2026 2027 2028
	   lpBand->lcy = infoPtr->imageSize.cy + 2;
	}
    }

    /* text is visible */
2029 2030
    if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText) &&
        !(lpBand->fStyle & RBBS_HIDETITLE)) {
2031 2032 2033 2034
	HDC hdc = GetDC (0);
	HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
	SIZE size;

2035
	lpBand->fStatus |= HAS_TEXT;
2036 2037
	GetTextExtentPoint32W (hdc, lpBand->lpText,
			       lstrlenW (lpBand->lpText), &size);
2038 2039
	header += ((infoPtr->dwStyle & CCS_VERT) ? (size.cy + REBAR_POST_TEXT) : (size.cx + REBAR_POST_TEXT));
	textheight = (infoPtr->dwStyle & CCS_VERT) ? 0 : size.cy;
2040 2041 2042 2043 2044

	SelectObject (hdc, hOldFont);
	ReleaseDC (0, hdc);
    }

2045 2046 2047 2048 2049 2050
    /* if no gripper but either image or text, then leave space */
    if ((lpBand->fStatus & (HAS_IMAGE | HAS_TEXT)) &&
	!(lpBand->fStatus & HAS_GRIPPER)) {
	header += REBAR_ALWAYS_SPACE;
    }

2051 2052 2053 2054 2055 2056
    /* check if user overrode the header value */
    if (!(lpBand->fMask & RBBIM_HEADERSIZE))
        lpBand->cxHeader = header;


    /* Now compute minimum size of child window */
2057 2058
    lpBand->offChild.cx = 0;
    lpBand->offChild.cy = 0;
2059
    lpBand->lcy = textheight;
2060
    lpBand->ccy = lpBand->lcy;
2061 2062
    if (lpBand->fMask & RBBIM_CHILDSIZE) {
        lpBand->lcx = lpBand->cxMinChild;
2063 2064

	/* Set the .cy values for CHILDSIZE case */
2065
        lpBand->lcy = max(lpBand->lcy, lpBand->cyMinChild);
2066
	lpBand->ccy = lpBand->lcy;
2067
        lpBand->hcy = lpBand->lcy;
2068
        if (lpBand->cyMaxChild != 0xffffffff) {
2069 2070
	    lpBand->hcy = lpBand->cyMaxChild;
        }
2071 2072 2073
	if (lpBand->cyChild != 0xffffffff)
	    lpBand->ccy = max (lpBand->cyChild, lpBand->lcy);

2074 2075 2076
        TRACE("_CHILDSIZE\n");
    }
    if (lpBand->fMask & RBBIM_SIZE) {
2077
        lpBand->hcx = max (lpBand->cx-lpBand->cxHeader, lpBand->lcx);
2078 2079 2080 2081
        TRACE("_SIZE\n");
    }
    else
        lpBand->hcx = lpBand->lcx;
2082 2083 2084 2085 2086 2087
    lpBand->ccx = lpBand->hcx;

    /* make ->.cx include header size for _Layout */
    lpBand->lcx += lpBand->cxHeader;
    lpBand->ccx += lpBand->cxHeader;
    lpBand->hcx += lpBand->cxHeader;
2088 2089 2090

}

2091
static BOOL
2092 2093 2094
REBAR_CommonSetupBand (HWND hwnd, LPREBARBANDINFOA lprbbi, REBAR_BAND *lpBand)
     /* Function:  This routine copies the supplied values from   */
     /*  user input (lprbbi) to the internal band structure.      */
2095
     /*  It returns true if something changed and false if not.   */
2096
{
2097 2098
    BOOL bChanged = FALSE;

2099 2100
    lpBand->fMask |= lprbbi->fMask;

2101 2102 2103
    if( (lprbbi->fMask & RBBIM_STYLE) &&
        (lpBand->fStyle != lprbbi->fStyle ) )
    {
2104
	lpBand->fStyle = lprbbi->fStyle;
2105 2106
        bChanged = TRUE;
    }
2107

2108 2109 2110 2111
    if( (lprbbi->fMask & RBBIM_COLORS) &&
       ( ( lpBand->clrFore != lprbbi->clrFore ) ||
         ( lpBand->clrBack != lprbbi->clrBack ) ) )
    {
2112 2113
	lpBand->clrFore = lprbbi->clrFore;
	lpBand->clrBack = lprbbi->clrBack;
2114
        bChanged = TRUE;
2115 2116
    }

2117 2118 2119
    if( (lprbbi->fMask & RBBIM_IMAGE) &&
       ( lpBand->iImage != lprbbi->iImage ) )
    {
2120
	lpBand->iImage = lprbbi->iImage;
2121 2122
        bChanged = TRUE;
    }
2123

2124 2125 2126
    if( (lprbbi->fMask & RBBIM_CHILD) &&
       (lprbbi->hwndChild != lpBand->hwndChild ) )
    {
2127 2128 2129 2130
	if (lprbbi->hwndChild) {
	    lpBand->hwndChild = lprbbi->hwndChild;
	    lpBand->hwndPrevParent =
		SetParent (lpBand->hwndChild, hwnd);
2131
	    /* below in trace from WinRAR */
2132
	    ShowWindow(lpBand->hwndChild, SW_SHOWNOACTIVATE | SW_SHOWNORMAL);
2133
	    /* above in trace from WinRAR */
2134 2135
	}
	else {
2136
	    TRACE("child: %p  prev parent: %p\n",
2137 2138 2139 2140
		   lpBand->hwndChild, lpBand->hwndPrevParent);
	    lpBand->hwndChild = 0;
	    lpBand->hwndPrevParent = 0;
	}
2141
        bChanged = TRUE;
2142 2143
    }

2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155
    if( (lprbbi->fMask & RBBIM_CHILDSIZE) &&
        ( (lpBand->cxMinChild != lprbbi->cxMinChild) ||
          (lpBand->cyMinChild != lprbbi->cyMinChild ) ||
          ( (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) &&
            ( (lpBand->cyChild    != lprbbi->cyChild ) ||
              (lpBand->cyMaxChild != lprbbi->cyMaxChild ) ||
              (lpBand->cyIntegral != lprbbi->cyIntegral ) ) ) ||
          ( (lprbbi->cbSize < sizeof (REBARBANDINFOA)) &&
            ( (lpBand->cyChild || 
               lpBand->cyMaxChild || 
               lpBand->cyIntegral ) ) ) ) )
    {
2156 2157
	lpBand->cxMinChild = lprbbi->cxMinChild;
	lpBand->cyMinChild = lprbbi->cyMinChild;
2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168
	if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
	    lpBand->cyChild    = lprbbi->cyChild;
	    lpBand->cyMaxChild = lprbbi->cyMaxChild;
	    lpBand->cyIntegral = lprbbi->cyIntegral;
	}
	else { /* special case - these should be zeroed out since   */
	       /* RBBIM_CHILDSIZE added these in WIN32_IE >= 0x0400 */
	    lpBand->cyChild    = 0;
	    lpBand->cyMaxChild = 0;
	    lpBand->cyIntegral = 0;
	}
2169
        bChanged = TRUE;
2170 2171
    }

2172 2173 2174
    if( (lprbbi->fMask & RBBIM_SIZE) &&
        (lpBand->cx != lprbbi->cx ) )
    {
2175
	lpBand->cx = lprbbi->cx;
2176 2177
        bChanged = TRUE;
    }
2178

2179 2180 2181
    if( (lprbbi->fMask & RBBIM_BACKGROUND) &&
       ( lpBand->hbmBack != lprbbi->hbmBack ) )
    {
2182
	lpBand->hbmBack = lprbbi->hbmBack;
2183 2184
        bChanged = TRUE;
    }
2185

2186 2187 2188
    if( (lprbbi->fMask & RBBIM_ID) &&
        (lpBand->wID != lprbbi->wID ) )
    {
2189
	lpBand->wID = lprbbi->wID;
2190 2191
        bChanged = TRUE;
    }
2192 2193 2194

    /* check for additional data */
    if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
2195 2196 2197
	if( (lprbbi->fMask & RBBIM_IDEALSIZE) &&
            ( lpBand->cxIdeal != lprbbi->cxIdeal ) )
        {
2198
	    lpBand->cxIdeal = lprbbi->cxIdeal;
2199 2200
            bChanged = TRUE;
        }
2201

2202 2203 2204
	if( (lprbbi->fMask & RBBIM_LPARAM) &&
            (lpBand->lParam != lprbbi->lParam ) )
        {
2205
	    lpBand->lParam = lprbbi->lParam;
2206 2207
            bChanged = TRUE;
        }
2208

2209 2210 2211
	if( (lprbbi->fMask & RBBIM_HEADERSIZE) &&
            (lpBand->cxHeader != lprbbi->cxHeader ) )
        {
2212
	    lpBand->cxHeader = lprbbi->cxHeader;
2213 2214
            bChanged = TRUE;
        }
2215
    }
2216 2217

    return bChanged;
2218 2219
}

2220
static LRESULT
2221
REBAR_InternalEraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, RECT *clip)
2222 2223 2224 2225
     /* Function:  This erases the background rectangle by drawing  */
     /*  each band with its background color (or the default) and   */
     /*  draws each bands right separator if necessary. The row     */
     /*  separators are drawn on the first band of the next row.    */
2226 2227
{
    REBAR_BAND *lpBand;
2228 2229
    UINT i;
    INT oldrow;
2230
    HDC hdc = (HDC)wParam;
2231
    RECT rect, cr;
Guy Albertelli's avatar
Guy Albertelli committed
2232
    COLORREF old = CLR_NONE, new;
2233 2234 2235
    HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);

    GetClientRect (infoPtr->hwndSelf, &cr);
2236

2237
    oldrow = -1;
2238 2239
    for(i=0; i<infoPtr->uNumBands; i++) {
        lpBand = &infoPtr->bands[i];
2240
	if (HIDDENBAND(lpBand)) continue;
2241 2242 2243 2244 2245 2246 2247

	/* draw band separator between rows */
	if (lpBand->iRow != oldrow) {
	    oldrow = lpBand->iRow;
	    if (lpBand->fDraw & DRAW_BOTTOMSEP) {
		RECT rcRowSep;
		rcRowSep = lpBand->rcBand;
2248
		if (infoPtr->dwStyle & CCS_VERT) {
2249 2250
		    rcRowSep.right += SEP_WIDTH_SIZE;
		    rcRowSep.bottom = infoPtr->calcSize.cy;
2251 2252 2253 2254
                    if (theme)
                        DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcRowSep, EDGE_ETCHED, BF_RIGHT, NULL);
                    else
		        DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_RIGHT);
2255 2256 2257 2258
		}
		else {
		    rcRowSep.bottom += SEP_WIDTH_SIZE;
		    rcRowSep.right = infoPtr->calcSize.cx;
2259 2260 2261 2262
                    if (theme)
                        DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcRowSep, EDGE_ETCHED, BF_BOTTOM, NULL);
                    else
		        DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_BOTTOM);
2263
		}
2264
		TRACE ("drawing band separator bottom (%d,%d)-(%d,%d)\n",
2265 2266 2267 2268 2269 2270 2271 2272 2273
		       rcRowSep.left, rcRowSep.top,
		       rcRowSep.right, rcRowSep.bottom);
	    }
	}

	/* draw band separator between bands in a row */
	if (lpBand->fDraw & DRAW_RIGHTSEP) {
	    RECT rcSep;
	    rcSep = lpBand->rcBand;
2274
	    if (infoPtr->dwStyle & CCS_VERT) {
2275
		rcSep.bottom += SEP_WIDTH_SIZE;
2276 2277 2278 2279
                if (theme)
                    DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_BOTTOM, NULL);
                else
		    DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOM);
2280 2281 2282
	    }
	    else {
		rcSep.right += SEP_WIDTH_SIZE;
2283 2284 2285 2286
                if (theme)
                    DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_RIGHT, NULL);
                else
		    DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_RIGHT);
2287
	    }
2288
            TRACE("drawing band separator right (%d,%d)-(%d,%d)\n",
2289
		  rcSep.left, rcSep.top, rcSep.right, rcSep.bottom);
2290
	}
2291 2292

	/* draw the actual background */
Guy Albertelli's avatar
Guy Albertelli committed
2293 2294 2295
	if (lpBand->clrBack != CLR_NONE) {
	    new = (lpBand->clrBack == CLR_DEFAULT) ? infoPtr->clrBtnFace :
		    lpBand->clrBack;
2296
#if GLATESTING
Guy Albertelli's avatar
Guy Albertelli committed
2297 2298
	    /* testing only - make background green to see it */
	    new = RGB(0,128,0);
2299
#endif
Guy Albertelli's avatar
Guy Albertelli committed
2300
	}
2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311
	else {
	    /* In the absence of documentation for Rebar vs. CLR_NONE,
	     * we will use the default BtnFace color. Note documentation
	     * exists for Listview and Imagelist.
	     */
	    new = infoPtr->clrBtnFace;
#if GLATESTING
	    /* testing only - make background green to see it */
	    new = RGB(0,128,0);
#endif
	}
Guy Albertelli's avatar
Guy Albertelli committed
2312 2313

	rect = lpBand->rcBand;
2314 2315 2316 2317 2318 2319 2320 2321 2322 2323

        if (theme)
        {
            /* When themed, the background color is ignored (but not a 
             * background bitmap */
            DrawThemeBackground (theme, hdc, 0, 0, &cr, &rect);
        }
        else
        {
            old = SetBkColor (hdc, new);
2324
            TRACE("%s background color=0x%06x, band (%d,%d)-(%d,%d), clip (%d,%d)-(%d,%d)\n",
2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335
                  (lpBand->clrBack == CLR_NONE) ? "none" :
                    ((lpBand->clrBack == CLR_DEFAULT) ? "dft" : ""),
                  GetBkColor(hdc),
                  lpBand->rcBand.left,lpBand->rcBand.top,
                  lpBand->rcBand.right,lpBand->rcBand.bottom,
                  clip->left, clip->top,
                  clip->right, clip->bottom);
            ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, 0);
            if (lpBand->clrBack != CLR_NONE)
                SetBkColor (hdc, old);
        }
2336 2337 2338 2339
    }
    return TRUE;
}

Eric Kohl's avatar
Eric Kohl committed
2340
static void
Robert Shearman's avatar
Robert Shearman committed
2341
REBAR_InternalHitTest (REBAR_INFO *infoPtr, const LPPOINT lpPt, UINT *pFlags, INT *pBand)
Eric Kohl's avatar
Eric Kohl committed
2342 2343
{
    REBAR_BAND *lpBand;
2344
    RECT rect;
2345
    UINT  iCount;
Alexandre Julliard's avatar
Alexandre Julliard committed
2346

2347
    GetClientRect (infoPtr->hwndSelf, &rect);
Alexandre Julliard's avatar
Alexandre Julliard committed
2348

Eric Kohl's avatar
Eric Kohl committed
2349
    *pFlags = RBHT_NOWHERE;
2350
    if (PtInRect (&rect, *lpPt))
Eric Kohl's avatar
Eric Kohl committed
2351 2352 2353 2354 2355
    {
	if (infoPtr->uNumBands == 0) {
	    *pFlags = RBHT_NOWHERE;
	    if (pBand)
		*pBand = -1;
2356
	    TRACE("NOWHERE\n");
Eric Kohl's avatar
Eric Kohl committed
2357 2358 2359 2360 2361 2362
	    return;
	}
	else {
	    /* somewhere inside */
	    for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
		lpBand = &infoPtr->bands[iCount];
2363
		if (HIDDENBAND(lpBand)) continue;
2364
		if (PtInRect (&lpBand->rcBand, *lpPt)) {
Eric Kohl's avatar
Eric Kohl committed
2365 2366
		    if (pBand)
			*pBand = iCount;
2367
		    if (PtInRect (&lpBand->rcGripper, *lpPt)) {
Eric Kohl's avatar
Eric Kohl committed
2368
			*pFlags = RBHT_GRABBER;
2369
			TRACE("ON GRABBER %d\n", iCount);
Eric Kohl's avatar
Eric Kohl committed
2370 2371
			return;
		    }
2372
		    else if (PtInRect (&lpBand->rcCapImage, *lpPt)) {
Eric Kohl's avatar
Eric Kohl committed
2373
			*pFlags = RBHT_CAPTION;
2374
			TRACE("ON CAPTION %d\n", iCount);
Eric Kohl's avatar
Eric Kohl committed
2375 2376
			return;
		    }
2377
		    else if (PtInRect (&lpBand->rcCapText, *lpPt)) {
Eric Kohl's avatar
Eric Kohl committed
2378
			*pFlags = RBHT_CAPTION;
2379
			TRACE("ON CAPTION %d\n", iCount);
Eric Kohl's avatar
Eric Kohl committed
2380 2381
			return;
		    }
2382
		    else if (PtInRect (&lpBand->rcChild, *lpPt)) {
Eric Kohl's avatar
Eric Kohl committed
2383
			*pFlags = RBHT_CLIENT;
2384
			TRACE("ON CLIENT %d\n", iCount);
Eric Kohl's avatar
Eric Kohl committed
2385 2386
			return;
		    }
Robert Shearman's avatar
Robert Shearman committed
2387 2388 2389 2390 2391
		    else if (PtInRect (&lpBand->rcChevron, *lpPt)) {
			*pFlags = RBHT_CHEVRON;
			TRACE("ON CHEVRON %d\n", iCount);
			return;
		    }
Eric Kohl's avatar
Eric Kohl committed
2392 2393
		    else {
			*pFlags = RBHT_NOWHERE;
2394
			TRACE("NOWHERE %d\n", iCount);
Eric Kohl's avatar
Eric Kohl committed
2395 2396 2397 2398
			return;
		    }
		}
	    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2399

Eric Kohl's avatar
Eric Kohl committed
2400 2401 2402 2403
	    *pFlags = RBHT_NOWHERE;
	    if (pBand)
		*pBand = -1;

2404
	    TRACE("NOWHERE\n");
Eric Kohl's avatar
Eric Kohl committed
2405 2406 2407 2408 2409 2410 2411
	    return;
	}
    }
    else {
	*pFlags = RBHT_NOWHERE;
	if (pBand)
	    *pBand = -1;
2412
	TRACE("NOWHERE\n");
Eric Kohl's avatar
Eric Kohl committed
2413 2414 2415
	return;
    }
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2416

2417 2418

static INT
2419
REBAR_Shrink (REBAR_INFO *infoPtr, REBAR_BAND *band, INT movement, INT i)
2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431
     /* 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.                      */

2432
    avail = rcBw(band) - band->lcx;
2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470

    /* 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 */
2471
    if (rcBlt(band) + Leadjust < 0) {
2472 2473 2474 2475 2476 2477 2478
        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);

2479
    TRACE("band %d:  left=%d, right=%d, move=%d, rtn=%d, rcBand=(%d,%d)-(%d,%d)\n",
2480 2481 2482 2483 2484 2485 2486 2487
	  i, Leadjust, Readjust, movement, ret,
	  band->rcBand.left, band->rcBand.top,
	  band->rcBand.right, band->rcBand.bottom);
    return ret;
}


static void
2488
REBAR_HandleLRDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
2489 2490 2491 2492 2493 2494 2495
     /* Function:  This will implement the functionality of a     */
     /*  Gripper drag within a row. It will not implement "out-   */
     /*  of-row" drags. (They are detected and handled in         */
     /*  REBAR_MouseMove.)                                        */
     /*  **** FIXME Switching order of bands in a row not   ****  */
     /*  ****       yet implemented.                        ****  */
{
2496
    REBAR_BAND *hitBand, *band, *mindBand, *maxdBand;
2497
    RECT newrect;
2498
    INT imindBand = -1, imaxdBand, ihitBand, i, movement;
2499 2500 2501 2502 2503 2504
    INT RHeaderSum = 0, LHeaderSum = 0;
    INT compress;

    /* on first significant mouse movement, issue notify */

    if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
2505
	if (REBAR_Notify_NMREBAR (infoPtr, -1, RBN_BEGINDRAG)) {
2506 2507 2508 2509
	    /* Notify returned TRUE - abort drag */
	    infoPtr->dragStart.x = 0;
	    infoPtr->dragStart.y = 0;
	    infoPtr->dragNow = infoPtr->dragStart;
Robert Shearman's avatar
Robert Shearman committed
2510
	    infoPtr->iGrabbedBand = -1;
2511 2512 2513
	    ReleaseCapture ();
	    return ;
	}
2514 2515 2516
	infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
    }

Robert Shearman's avatar
Robert Shearman committed
2517
    ihitBand = infoPtr->iGrabbedBand;
2518 2519 2520 2521 2522 2523
    hitBand = &infoPtr->bands[ihitBand];
    imaxdBand = ihitBand; /* to suppress warning message */

    /* find all the bands in the row of the one whose Gripper was seized */
    for (i=0; i<infoPtr->uNumBands; i++) {
        band = &infoPtr->bands[i];
2524
	if (HIDDENBAND(band)) continue;
2525 2526 2527 2528 2529
	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 */
2530
	    /* one to separate each band.                                  */
2531
	    if (i < ihitBand)
2532
	        LHeaderSum += (band->lcx + SEP_WIDTH);
2533
	    else
2534
	        RHeaderSum += (band->lcx + SEP_WIDTH);
2535 2536 2537

	}
    }
2538
    if (RHeaderSum) RHeaderSum -= SEP_WIDTH; /* no separator after last band */
2539 2540 2541 2542

    mindBand = &infoPtr->bands[imindBand];
    maxdBand = &infoPtr->bands[imaxdBand];

2543 2544
    if (imindBand == imaxdBand) return; /* nothing to drag against */
    if (imindBand == ihitBand) return; /* first band in row, can't drag */
2545 2546

    /* limit movement to inside adjustable bands - Left */
2547 2548 2549 2550
    if ( (ptsmove->x < mindBand->rcBand.left) ||
	 (ptsmove->x > maxdBand->rcBand.right) ||
	 (ptsmove->y < mindBand->rcBand.top) ||
	 (ptsmove->y > maxdBand->rcBand.bottom))
2551 2552
        return; /* should swap bands */

2553
    if (infoPtr->dwStyle & CCS_VERT)
2554 2555 2556 2557 2558
        movement = ptsmove->y - ((hitBand->rcBand.top+REBAR_PRE_GRIPPER) -
			     infoPtr->ihitoffset);
    else
        movement = ptsmove->x - ((hitBand->rcBand.left+REBAR_PRE_GRIPPER) -
			     infoPtr->ihitoffset);
2559 2560
    infoPtr->dragNow = *ptsmove;

2561
    TRACE("before: movement=%d (%d,%d), imindBand=%d, ihitBand=%d, imaxdBand=%d, LSum=%d, RSum=%d\n",
2562 2563
	  movement, ptsmove->x, ptsmove->y, imindBand, ihitBand,
	  imaxdBand, LHeaderSum, RHeaderSum);
2564
    REBAR_DumpBand (infoPtr);
2565

2566
    if (movement < 0) {
2567

2568 2569
        /* ***  Drag left/up *** */
        compress = rcBlt(hitBand) - rcBlt(mindBand) -
2570 2571 2572 2573 2574 2575
	           LHeaderSum;
	if (compress < abs(movement)) {
	    TRACE("limiting left drag, was %d changed to %d\n",
		  movement, -compress);
	    movement = -compress;
	}
2576

2577 2578
        for (i=ihitBand; i>=imindBand; i--) {
	    band = &infoPtr->bands[i];
2579
	    if (HIDDENBAND(band)) continue;
2580
	    if (i == ihitBand) {
2581
		LEADJ(band, movement);
2582
	    }
2583
	    else
2584
	        movement = REBAR_Shrink (infoPtr, band, movement, i);
2585
	    band->ccx = rcBw(band);
2586 2587 2588
	}
    }
    else {
2589
	BOOL first = TRUE;
2590

2591 2592
        /* ***  Drag right/down *** */
        compress = rcBrb(maxdBand) - rcBlt(hitBand) -
2593 2594 2595 2596 2597 2598 2599 2600
	           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];
2601
	    if (HIDDENBAND(band)) continue;
2602 2603
	    if (first) {
		first = FALSE;
2604
		READJ(band, movement);
2605
	    }
2606
	    else
2607
	        movement = REBAR_Shrink (infoPtr, band, movement, i);
2608
	    band->ccx = rcBw(band);
2609 2610 2611
	}
    }

2612
    /* recompute all rectangles */
2613
    if (infoPtr->dwStyle & CCS_VERT) {
2614
	REBAR_CalcVertBand (infoPtr, imindBand, imaxdBand+1,
2615
			    FALSE);
2616 2617
    }
    else {
2618
	REBAR_CalcHorzBand (infoPtr, imindBand, imaxdBand+1,
2619
			    FALSE);
2620 2621
    }

2622 2623
    TRACE("bands after adjustment, see band # %d, %d\n",
	  imindBand, imaxdBand);
2624
    REBAR_DumpBand (infoPtr);
2625

2626
    SetRect (&newrect,
2627
	     mindBand->rcBand.left,
2628
	     mindBand->rcBand.top,
2629
	     maxdBand->rcBand.right,
2630
	     maxdBand->rcBand.bottom);
2631

2632
    REBAR_MoveChildWindows (infoPtr, imindBand, imaxdBand+1);
2633

2634 2635
    InvalidateRect (infoPtr->hwndSelf, &newrect, TRUE);
    UpdateWindow (infoPtr->hwndSelf);
2636 2637 2638

}

Alexandre Julliard's avatar
Alexandre Julliard committed
2639 2640


2641
/* << REBAR_BeginDrag >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
2642 2643 2644


static LRESULT
2645
REBAR_DeleteBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2646
{
2647
    UINT uBand = (UINT)wParam;
2648 2649
    HWND childhwnd = 0;
    REBAR_BAND *lpBand;
Alexandre Julliard's avatar
Alexandre Julliard committed
2650 2651 2652 2653

    if (uBand >= infoPtr->uNumBands)
	return FALSE;

2654
    TRACE("deleting band %u!\n", uBand);
2655
    lpBand = &infoPtr->bands[uBand];
2656
    REBAR_Notify_NMREBAR (infoPtr, uBand, RBN_DELETINGBAND);
Alexandre Julliard's avatar
Alexandre Julliard committed
2657

Eric Kohl's avatar
Eric Kohl committed
2658
    if (infoPtr->uNumBands == 1) {
2659
	TRACE(" simple delete!\n");
2660 2661
	if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild)
	    childhwnd = lpBand->hwndChild;
2662
	Free (infoPtr->bands);
Eric Kohl's avatar
Eric Kohl committed
2663 2664 2665 2666 2667
	infoPtr->bands = NULL;
	infoPtr->uNumBands = 0;
    }
    else {
	REBAR_BAND *oldBands = infoPtr->bands;
2668
        TRACE("complex delete! [uBand=%u]\n", uBand);
Eric Kohl's avatar
Eric Kohl committed
2669

2670 2671 2672
	if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild)
	    childhwnd = lpBand->hwndChild;

Eric Kohl's avatar
Eric Kohl committed
2673
	infoPtr->uNumBands--;
2674
	infoPtr->bands = Alloc (sizeof (REBAR_BAND) * infoPtr->uNumBands);
Eric Kohl's avatar
Eric Kohl committed
2675 2676 2677 2678 2679 2680 2681 2682 2683 2684
        if (uBand > 0) {
            memcpy (&infoPtr->bands[0], &oldBands[0],
                    uBand * sizeof(REBAR_BAND));
        }

        if (uBand < infoPtr->uNumBands) {
            memcpy (&infoPtr->bands[uBand], &oldBands[uBand+1],
                    (infoPtr->uNumBands - uBand) * sizeof(REBAR_BAND));
        }

2685
	Free (oldBands);
Eric Kohl's avatar
Eric Kohl committed
2686 2687
    }

2688 2689 2690
    if (childhwnd)
        ShowWindow (childhwnd, SW_HIDE);

2691
    REBAR_Notify_NMREBAR (infoPtr, -1, RBN_DELETEDBAND);
2692 2693 2694

    /* if only 1 band left the re-validate to possible eliminate gripper */
    if (infoPtr->uNumBands == 1)
2695
      REBAR_ValidateBand (infoPtr, &infoPtr->bands[0]);
2696

2697 2698
    TRACE("setting NEEDS_LAYOUT\n");
    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
2699
    infoPtr->fStatus |= RESIZE_ANYHOW;
2700
    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
Eric Kohl's avatar
Eric Kohl committed
2701

Alexandre Julliard's avatar
Alexandre Julliard committed
2702 2703
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2704 2705


2706 2707
/* << REBAR_DragMove >> */
/* << REBAR_EndDrag >> */
Eric Kohl's avatar
Eric Kohl committed
2708 2709 2710


static LRESULT
2711
REBAR_GetBandBorders (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
2712
{
2713
    LPRECT lpRect = (LPRECT)lParam;
2714 2715 2716 2717
    REBAR_BAND *lpBand;

    if (!lParam)
	return 0;
2718
    if ((UINT)wParam >= infoPtr->uNumBands)
2719 2720
	return 0;

2721
    lpBand = &infoPtr->bands[(UINT)wParam];
2722 2723 2724 2725 2726 2727

    /* FIXME - the following values were determined by experimentation */
    /* with the REBAR Control Spy. I have guesses as to what the 4 and */
    /* 1 are, but I am not sure. There doesn't seem to be any actual   */
    /* difference in size of the control area with and without the     */
    /* style.  -  GA                                                   */
2728 2729
    if (infoPtr->dwStyle & RBS_BANDBORDERS) {
	if (infoPtr->dwStyle & CCS_VERT) {
2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740
	    lpRect->left = 1;
	    lpRect->top = lpBand->cxHeader + 4;
	    lpRect->right = 1;
	    lpRect->bottom = 0;
	}
	else {
	    lpRect->left = lpBand->cxHeader + 4;
	    lpRect->top = 1;
	    lpRect->right = 0;
	    lpRect->bottom = 1;
	}
2741 2742
    }
    else {
2743
	lpRect->left = lpBand->cxHeader;
2744
    }
Eric Kohl's avatar
Eric Kohl committed
2745 2746
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2747 2748


Patrik Stridvall's avatar
Patrik Stridvall committed
2749
inline static LRESULT
2750
REBAR_GetBandCount (REBAR_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
2751
{
2752
    TRACE("band count %u!\n", infoPtr->uNumBands);
Alexandre Julliard's avatar
Alexandre Julliard committed
2753 2754 2755 2756 2757 2758

    return infoPtr->uNumBands;
}


static LRESULT
2759
REBAR_GetBandInfoA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2760
{
2761
    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2762 2763 2764 2765
    REBAR_BAND *lpBand;

    if (lprbbi == NULL)
	return FALSE;
2766
    if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
2767
	return FALSE;
2768
    if ((UINT)wParam >= infoPtr->uNumBands)
Alexandre Julliard's avatar
Alexandre Julliard committed
2769 2770
	return FALSE;

2771
    TRACE("index %u\n", (UINT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2772 2773

    /* copy band information */
2774
    lpBand = &infoPtr->bands[(UINT)wParam];
Alexandre Julliard's avatar
Alexandre Julliard committed
2775 2776 2777 2778 2779 2780 2781

    if (lprbbi->fMask & RBBIM_STYLE)
	lprbbi->fStyle = lpBand->fStyle;

    if (lprbbi->fMask & RBBIM_COLORS) {
	lprbbi->clrFore = lpBand->clrFore;
	lprbbi->clrBack = lpBand->clrBack;
Guy Albertelli's avatar
Guy Albertelli committed
2782
	if (lprbbi->clrBack == CLR_DEFAULT)
2783
	    lprbbi->clrBack = infoPtr->clrBtnFace;
Alexandre Julliard's avatar
Alexandre Julliard committed
2784 2785
    }

2786 2787
    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
      if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
2788 2789 2790 2791 2792
      {
          if (!WideCharToMultiByte( CP_ACP, 0, lpBand->lpText, -1,
                                    lprbbi->lpText, lprbbi->cch, NULL, NULL ))
              lprbbi->lpText[lprbbi->cch-1] = 0;
      }
2793
      else
2794
	*lprbbi->lpText = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
2795 2796
    }

2797 2798
    if (lprbbi->fMask & RBBIM_IMAGE) {
      if (lpBand->fMask & RBBIM_IMAGE)
Alexandre Julliard's avatar
Alexandre Julliard committed
2799
	lprbbi->iImage = lpBand->iImage;
2800 2801 2802
      else
	lprbbi->iImage = -1;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2803 2804 2805 2806 2807 2808 2809

    if (lprbbi->fMask & RBBIM_CHILD)
	lprbbi->hwndChild = lpBand->hwndChild;

    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
	lprbbi->cxMinChild = lpBand->cxMinChild;
	lprbbi->cyMinChild = lpBand->cyMinChild;
2810 2811 2812 2813 2814
	if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
	    lprbbi->cyChild    = lpBand->cyChild;
	    lprbbi->cyMaxChild = lpBand->cyMaxChild;
	    lprbbi->cyIntegral = lpBand->cyIntegral;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825
    }

    if (lprbbi->fMask & RBBIM_SIZE)
	lprbbi->cx = lpBand->cx;

    if (lprbbi->fMask & RBBIM_BACKGROUND)
	lprbbi->hbmBack = lpBand->hbmBack;

    if (lprbbi->fMask & RBBIM_ID)
	lprbbi->wID = lpBand->wID;

Alexandre Julliard's avatar
Alexandre Julliard committed
2826
    /* check for additional data */
2827
    if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
Alexandre Julliard's avatar
Alexandre Julliard committed
2828 2829
	if (lprbbi->fMask & RBBIM_IDEALSIZE)
	    lprbbi->cxIdeal = lpBand->cxIdeal;
Alexandre Julliard's avatar
Alexandre Julliard committed
2830

Alexandre Julliard's avatar
Alexandre Julliard committed
2831 2832
	if (lprbbi->fMask & RBBIM_LPARAM)
	    lprbbi->lParam = lpBand->lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2833

Alexandre Julliard's avatar
Alexandre Julliard committed
2834 2835 2836
	if (lprbbi->fMask & RBBIM_HEADERSIZE)
	    lprbbi->cxHeader = lpBand->cxHeader;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2837

2838 2839
    REBAR_DumpBandInfo (lprbbi);

Alexandre Julliard's avatar
Alexandre Julliard committed
2840 2841 2842 2843
    return TRUE;
}


Eric Kohl's avatar
Eric Kohl committed
2844
static LRESULT
2845
REBAR_GetBandInfoW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
2846
{
2847
    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
Eric Kohl's avatar
Eric Kohl committed
2848 2849 2850 2851
    REBAR_BAND *lpBand;

    if (lprbbi == NULL)
	return FALSE;
2852
    if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE)
Eric Kohl's avatar
Eric Kohl committed
2853
	return FALSE;
2854
    if ((UINT)wParam >= infoPtr->uNumBands)
Eric Kohl's avatar
Eric Kohl committed
2855 2856
	return FALSE;

2857
    TRACE("index %u\n", (UINT)wParam);
Eric Kohl's avatar
Eric Kohl committed
2858 2859

    /* copy band information */
2860
    lpBand = &infoPtr->bands[(UINT)wParam];
Eric Kohl's avatar
Eric Kohl committed
2861 2862 2863 2864 2865 2866 2867

    if (lprbbi->fMask & RBBIM_STYLE)
	lprbbi->fStyle = lpBand->fStyle;

    if (lprbbi->fMask & RBBIM_COLORS) {
	lprbbi->clrFore = lpBand->clrFore;
	lprbbi->clrBack = lpBand->clrBack;
Guy Albertelli's avatar
Guy Albertelli committed
2868
	if (lprbbi->clrBack == CLR_DEFAULT)
2869
	    lprbbi->clrBack = infoPtr->clrBtnFace;
Eric Kohl's avatar
Eric Kohl committed
2870 2871
    }

2872 2873 2874
    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
      if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
	lstrcpynW (lprbbi->lpText, lpBand->lpText, lprbbi->cch);
2875
      else
2876
	*lprbbi->lpText = 0;
Eric Kohl's avatar
Eric Kohl committed
2877 2878
    }

2879 2880
    if (lprbbi->fMask & RBBIM_IMAGE) {
      if (lpBand->fMask & RBBIM_IMAGE)
Eric Kohl's avatar
Eric Kohl committed
2881
	lprbbi->iImage = lpBand->iImage;
2882 2883 2884
      else
	lprbbi->iImage = -1;
    }
Eric Kohl's avatar
Eric Kohl committed
2885 2886 2887 2888 2889 2890 2891

    if (lprbbi->fMask & RBBIM_CHILD)
	lprbbi->hwndChild = lpBand->hwndChild;

    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
	lprbbi->cxMinChild = lpBand->cxMinChild;
	lprbbi->cyMinChild = lpBand->cyMinChild;
2892 2893 2894 2895 2896
	if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
	    lprbbi->cyChild    = lpBand->cyChild;
	    lprbbi->cyMaxChild = lpBand->cyMaxChild;
	    lprbbi->cyIntegral = lpBand->cyIntegral;
	}
Eric Kohl's avatar
Eric Kohl committed
2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908
    }

    if (lprbbi->fMask & RBBIM_SIZE)
	lprbbi->cx = lpBand->cx;

    if (lprbbi->fMask & RBBIM_BACKGROUND)
	lprbbi->hbmBack = lpBand->hbmBack;

    if (lprbbi->fMask & RBBIM_ID)
	lprbbi->wID = lpBand->wID;

    /* check for additional data */
2909
    if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
Eric Kohl's avatar
Eric Kohl committed
2910 2911 2912 2913 2914 2915 2916 2917 2918 2919
	if (lprbbi->fMask & RBBIM_IDEALSIZE)
	    lprbbi->cxIdeal = lpBand->cxIdeal;

	if (lprbbi->fMask & RBBIM_LPARAM)
	    lprbbi->lParam = lpBand->lParam;

	if (lprbbi->fMask & RBBIM_HEADERSIZE)
	    lprbbi->cxHeader = lpBand->cxHeader;
    }

2920 2921
    REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);

Eric Kohl's avatar
Eric Kohl committed
2922 2923
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2924

Alexandre Julliard's avatar
Alexandre Julliard committed
2925 2926

static LRESULT
2927
REBAR_GetBarHeight (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2928
{
2929
    INT nHeight;
Alexandre Julliard's avatar
Alexandre Julliard committed
2930

2931
    nHeight = (infoPtr->dwStyle & CCS_VERT) ? infoPtr->calcSize.cx : infoPtr->calcSize.cy;
2932

2933
    TRACE("height = %d\n", nHeight);
Alexandre Julliard's avatar
Alexandre Julliard committed
2934

2935
    return nHeight;
Alexandre Julliard's avatar
Alexandre Julliard committed
2936
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2937 2938 2939


static LRESULT
2940
REBAR_GetBarInfo (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2941 2942 2943 2944 2945 2946 2947 2948 2949
{
    LPREBARINFO lpInfo = (LPREBARINFO)lParam;

    if (lpInfo == NULL)
	return FALSE;

    if (lpInfo->cbSize < sizeof (REBARINFO))
	return FALSE;

2950
    TRACE("getting bar info!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
2951 2952 2953 2954 2955 2956 2957 2958 2959 2960

    if (infoPtr->himl) {
	lpInfo->himl = infoPtr->himl;
	lpInfo->fMask |= RBIM_IMAGELIST;
    }

    return TRUE;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
2961
inline static LRESULT
2962
REBAR_GetBkColor (REBAR_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
2963
{
2964
    COLORREF clr = infoPtr->clrBk;
Alexandre Julliard's avatar
Alexandre Julliard committed
2965

Guy Albertelli's avatar
Guy Albertelli committed
2966
    if (clr == CLR_DEFAULT)
2967
      clr = infoPtr->clrBtnFace;
2968

2969
    TRACE("background color 0x%06x!\n", clr);
Alexandre Julliard's avatar
Alexandre Julliard committed
2970

2971
    return clr;
Alexandre Julliard's avatar
Alexandre Julliard committed
2972 2973 2974
}


2975 2976
/* << REBAR_GetColorScheme >> */
/* << REBAR_GetDropTarget >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
2977

Eric Kohl's avatar
Eric Kohl committed
2978 2979

static LRESULT
2980
REBAR_GetPalette (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
2981
{
2982
    FIXME("empty stub!\n");
Eric Kohl's avatar
Eric Kohl committed
2983 2984 2985 2986 2987 2988

    return 0;
}


static LRESULT
2989
REBAR_GetRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
2990
{
2991 2992
    INT iBand = (INT)wParam;
    LPRECT lprc = (LPRECT)lParam;
Eric Kohl's avatar
Eric Kohl committed
2993 2994
    REBAR_BAND *lpBand;

2995
    if ((iBand < 0) && ((UINT)iBand >= infoPtr->uNumBands))
Eric Kohl's avatar
Eric Kohl committed
2996 2997 2998 2999 3000
	return FALSE;
    if (!lprc)
	return FALSE;

    lpBand = &infoPtr->bands[iBand];
3001
    CopyRect (lprc, &lpBand->rcBand);
3002

3003
    TRACE("band %d, (%d,%d)-(%d,%d)\n", iBand,
3004
	  lprc->left, lprc->top, lprc->right, lprc->bottom);
Eric Kohl's avatar
Eric Kohl committed
3005 3006 3007 3008 3009

    return TRUE;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
3010
inline static LRESULT
3011
REBAR_GetRowCount (REBAR_INFO *infoPtr)
Eric Kohl's avatar
Eric Kohl committed
3012
{
3013
    TRACE("%u\n", infoPtr->uNumRows);
Eric Kohl's avatar
Eric Kohl committed
3014

3015
    return infoPtr->uNumRows;
Eric Kohl's avatar
Eric Kohl committed
3016 3017 3018 3019
}


static LRESULT
3020
REBAR_GetRowHeight (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3021
{
3022
    INT iRow = (INT)wParam;
3023 3024
    int j = 0, ret = 0;
    UINT i;
3025
    REBAR_BAND *lpBand;
Eric Kohl's avatar
Eric Kohl committed
3026

3027
    for (i=0; i<infoPtr->uNumBands; i++) {
3028 3029 3030
	lpBand = &infoPtr->bands[i];
	if (HIDDENBAND(lpBand)) continue;
	if (lpBand->iRow != iRow) continue;
3031
	if (infoPtr->dwStyle & CCS_VERT)
3032 3033 3034 3035
	    j = lpBand->rcBand.right - lpBand->rcBand.left;
	else
	    j = lpBand->rcBand.bottom - lpBand->rcBand.top;
	if (j > ret) ret = j;
3036 3037 3038
    }

    TRACE("row %d, height %d\n", iRow, ret);
Eric Kohl's avatar
Eric Kohl committed
3039

3040
    return ret;
Eric Kohl's avatar
Eric Kohl committed
3041
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3042 3043


Patrik Stridvall's avatar
Patrik Stridvall committed
3044
inline static LRESULT
3045
REBAR_GetTextColor (REBAR_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
3046
{
3047
    TRACE("text color 0x%06x!\n", infoPtr->clrText);
Alexandre Julliard's avatar
Alexandre Julliard committed
3048 3049 3050 3051 3052

    return infoPtr->clrText;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
3053
inline static LRESULT
3054
REBAR_GetToolTips (REBAR_INFO *infoPtr)
Eric Kohl's avatar
Eric Kohl committed
3055
{
3056
    return (LRESULT)infoPtr->hwndToolTip;
Eric Kohl's avatar
Eric Kohl committed
3057 3058 3059
}


Patrik Stridvall's avatar
Patrik Stridvall committed
3060
inline static LRESULT
3061
REBAR_GetUnicodeFormat (REBAR_INFO *infoPtr)
Eric Kohl's avatar
Eric Kohl committed
3062
{
3063
    TRACE("%s hwnd=%p\n",
3064 3065
	  infoPtr->bUnicode ? "TRUE" : "FALSE", infoPtr->hwndSelf);

Eric Kohl's avatar
Eric Kohl committed
3066 3067
    return infoPtr->bUnicode;
}
Eric Kohl's avatar
Eric Kohl committed
3068 3069


Eric Kohl's avatar
Eric Kohl committed
3070
inline static LRESULT
3071
REBAR_GetVersion (REBAR_INFO *infoPtr)
Eric Kohl's avatar
Eric Kohl committed
3072
{
3073
    TRACE("version %d\n", infoPtr->iVersion);
Eric Kohl's avatar
Eric Kohl committed
3074 3075 3076 3077
    return infoPtr->iVersion;
}


Eric Kohl's avatar
Eric Kohl committed
3078
static LRESULT
3079
REBAR_HitTest (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3080
{
3081
    LPRBHITTESTINFO lprbht = (LPRBHITTESTINFO)lParam;
Eric Kohl's avatar
Eric Kohl committed
3082 3083 3084 3085

    if (!lprbht)
	return -1;

3086
    REBAR_InternalHitTest (infoPtr, &lprbht->pt, &lprbht->flags, &lprbht->iBand);
Eric Kohl's avatar
Eric Kohl committed
3087 3088 3089

    return lprbht->iBand;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3090 3091 3092


static LRESULT
3093
REBAR_IdToIndex (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3094
{
3095
    UINT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
3096 3097 3098 3099 3100 3101 3102 3103

    if (infoPtr == NULL)
	return -1;

    if (infoPtr->uNumBands < 1)
	return -1;

    for (i = 0; i < infoPtr->uNumBands; i++) {
3104
	if (infoPtr->bands[i].wID == (UINT)wParam) {
3105
	    TRACE("id %u is band %u found!\n", (UINT)wParam, i);
Alexandre Julliard's avatar
Alexandre Julliard committed
3106
	    return i;
Alexandre Julliard's avatar
Alexandre Julliard committed
3107
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
3108 3109
    }

3110
    TRACE("id %u is not found\n", (UINT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3111 3112 3113 3114 3115
    return -1;
}


static LRESULT
3116
REBAR_InsertBandA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3117
{
3118 3119
    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
    UINT uIndex = (UINT)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3120 3121 3122 3123 3124 3125
    REBAR_BAND *lpBand;

    if (infoPtr == NULL)
	return FALSE;
    if (lprbbi == NULL)
	return FALSE;
3126
    if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
3127 3128
	return FALSE;

3129 3130 3131
    /* trace the index as signed to see the -1 */
    TRACE("insert band at %d!\n", (INT)uIndex);
    REBAR_DumpBandInfo (lprbbi);
Alexandre Julliard's avatar
Alexandre Julliard committed
3132

Alexandre Julliard's avatar
Alexandre Julliard committed
3133
    if (infoPtr->uNumBands == 0) {
3134
	infoPtr->bands = (REBAR_BAND *)Alloc (sizeof (REBAR_BAND));
Alexandre Julliard's avatar
Alexandre Julliard committed
3135 3136 3137 3138 3139
	uIndex = 0;
    }
    else {
	REBAR_BAND *oldBands = infoPtr->bands;
	infoPtr->bands =
3140
	    (REBAR_BAND *)Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
3141
	if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
Alexandre Julliard's avatar
Alexandre Julliard committed
3142 3143
	    uIndex = infoPtr->uNumBands;

Alexandre Julliard's avatar
Alexandre Julliard committed
3144 3145 3146 3147 3148
	/* pre insert copy */
	if (uIndex > 0) {
	    memcpy (&infoPtr->bands[0], &oldBands[0],
		    uIndex * sizeof(REBAR_BAND));
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
3149 3150

	/* post copy */
3151
	if (uIndex < infoPtr->uNumBands) {
Alexandre Julliard's avatar
Alexandre Julliard committed
3152
	    memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
3153
		    (infoPtr->uNumBands - uIndex) * sizeof(REBAR_BAND));
Alexandre Julliard's avatar
Alexandre Julliard committed
3154
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
3155

3156
	Free (oldBands);
Alexandre Julliard's avatar
Alexandre Julliard committed
3157 3158 3159 3160
    }

    infoPtr->uNumBands++;

3161
    TRACE("index %u!\n", uIndex);
Alexandre Julliard's avatar
Alexandre Julliard committed
3162 3163 3164

    /* initialize band (infoPtr->bands[uIndex])*/
    lpBand = &infoPtr->bands[uIndex];
3165
    lpBand->fMask = 0;
3166
    lpBand->fStatus = 0;
3167 3168 3169 3170 3171
    lpBand->clrFore = infoPtr->clrText;
    lpBand->clrBack = infoPtr->clrBk;
    lpBand->hwndChild = 0;
    lpBand->hwndPrevParent = 0;

3172
    REBAR_CommonSetupBand (infoPtr->hwndSelf, lprbbi, lpBand);
3173
    lpBand->lpText = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
3174
    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
3175 3176
        INT len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
        if (len > 1) {
3177
            lpBand->lpText = (LPWSTR)Alloc (len*sizeof(WCHAR));
3178
            MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, lpBand->lpText, len );
Alexandre Julliard's avatar
Alexandre Julliard committed
3179 3180 3181
	}
    }

3182
    REBAR_ValidateBand (infoPtr, lpBand);
3183 3184
    /* On insert of second band, revalidate band 1 to possible add gripper */
    if (infoPtr->uNumBands == 2)
3185
	REBAR_ValidateBand (infoPtr, &infoPtr->bands[0]);
Alexandre Julliard's avatar
Alexandre Julliard committed
3186

3187
    REBAR_DumpBand (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
3188

3189
    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3190
    InvalidateRect(infoPtr->hwndSelf, 0, 1);
Eric Kohl's avatar
Eric Kohl committed
3191

Alexandre Julliard's avatar
Alexandre Julliard committed
3192 3193 3194 3195
    return TRUE;
}


Eric Kohl's avatar
Eric Kohl committed
3196
static LRESULT
3197
REBAR_InsertBandW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3198
{
3199 3200
    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
    UINT uIndex = (UINT)wParam;
Eric Kohl's avatar
Eric Kohl committed
3201 3202 3203 3204 3205 3206
    REBAR_BAND *lpBand;

    if (infoPtr == NULL)
	return FALSE;
    if (lprbbi == NULL)
	return FALSE;
3207
    if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE)
Eric Kohl's avatar
Eric Kohl committed
3208 3209
	return FALSE;

3210 3211 3212
    /* trace the index as signed to see the -1 */
    TRACE("insert band at %d!\n", (INT)uIndex);
    REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
Eric Kohl's avatar
Eric Kohl committed
3213 3214

    if (infoPtr->uNumBands == 0) {
3215
	infoPtr->bands = (REBAR_BAND *)Alloc (sizeof (REBAR_BAND));
Eric Kohl's avatar
Eric Kohl committed
3216 3217 3218 3219 3220
	uIndex = 0;
    }
    else {
	REBAR_BAND *oldBands = infoPtr->bands;
	infoPtr->bands =
3221
	    (REBAR_BAND *)Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
3222
	if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
Eric Kohl's avatar
Eric Kohl committed
3223 3224 3225 3226 3227 3228 3229 3230 3231
	    uIndex = infoPtr->uNumBands;

	/* pre insert copy */
	if (uIndex > 0) {
	    memcpy (&infoPtr->bands[0], &oldBands[0],
		    uIndex * sizeof(REBAR_BAND));
	}

	/* post copy */
3232
	if (uIndex <= infoPtr->uNumBands - 1) {
Eric Kohl's avatar
Eric Kohl committed
3233
	    memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
3234
		    (infoPtr->uNumBands - uIndex) * sizeof(REBAR_BAND));
Eric Kohl's avatar
Eric Kohl committed
3235 3236
	}

3237
	Free (oldBands);
Eric Kohl's avatar
Eric Kohl committed
3238 3239 3240 3241
    }

    infoPtr->uNumBands++;

3242
    TRACE("index %u!\n", uIndex);
Eric Kohl's avatar
Eric Kohl committed
3243 3244 3245

    /* initialize band (infoPtr->bands[uIndex])*/
    lpBand = &infoPtr->bands[uIndex];
3246
    lpBand->fMask = 0;
3247
    lpBand->fStatus = 0;
3248 3249 3250 3251 3252
    lpBand->clrFore = infoPtr->clrText;
    lpBand->clrBack = infoPtr->clrBk;
    lpBand->hwndChild = 0;
    lpBand->hwndPrevParent = 0;

3253
    REBAR_CommonSetupBand (infoPtr->hwndSelf, (LPREBARBANDINFOA)lprbbi, lpBand);
3254
    lpBand->lpText = NULL;
Eric Kohl's avatar
Eric Kohl committed
3255
    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
3256
	INT len = lstrlenW (lprbbi->lpText);
Eric Kohl's avatar
Eric Kohl committed
3257
	if (len > 0) {
3258
	    lpBand->lpText = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR));
3259
	    strcpyW (lpBand->lpText, lprbbi->lpText);
Eric Kohl's avatar
Eric Kohl committed
3260 3261 3262
	}
    }

3263
    REBAR_ValidateBand (infoPtr, lpBand);
3264 3265
    /* On insert of second band, revalidate band 1 to possible add gripper */
    if (infoPtr->uNumBands == 2)
3266
	REBAR_ValidateBand (infoPtr, &infoPtr->bands[uIndex ? 0 : 1]);
Eric Kohl's avatar
Eric Kohl committed
3267

3268
    REBAR_DumpBand (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
3269

3270
    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3271
    InvalidateRect(infoPtr->hwndSelf, 0, 1);
Eric Kohl's avatar
Eric Kohl committed
3272 3273 3274 3275 3276

    return TRUE;
}


3277
static LRESULT
3278
REBAR_MaximizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3279
{
3280 3281
    REBAR_BAND *lpBand;
    UINT uBand = (UINT) wParam;
3282

3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309
    /* Validate */
    if ((infoPtr->uNumBands == 0) ||
	((INT)uBand < 0) || (uBand >= infoPtr->uNumBands)) {
	/* error !!! */
	ERR("Illegal MaximizeBand, requested=%d, current band count=%d\n",
	      (INT)uBand, infoPtr->uNumBands);
      	return FALSE;
    }

    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);

    return TRUE;
3310

3311 3312 3313 3314
}


static LRESULT
3315
REBAR_MinimizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3316
{
3317 3318 3319 3320 3321
    REBAR_BAND *band, *lpBand;
    UINT uBand = (UINT) wParam;
    RECT newrect;
    INT imindBand, imaxdBand, iprevBand, startBand, endBand;
    INT movement, i;
3322

3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346
    /* A "minimize" band is equivalent to "dragging" the gripper
     * of than band to the right till the band is only the size
     * of the cxHeader.
     */

    /* Validate */
    if ((infoPtr->uNumBands == 0) ||
	((INT)uBand < 0) || (uBand >= infoPtr->uNumBands)) {
	/* error !!! */
	ERR("Illegal MinimizeBand, requested=%d, current band count=%d\n",
	      (INT)uBand, infoPtr->uNumBands);
      	return FALSE;
    }

    /* 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) {
3347
	ERR("something is wrong, band=(%d,%d)-(%d,%d), cxheader=%d\n",
3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389
	    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;
3390
	SetRect (&newrect,
3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415
		 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;
3416
	SetRect (&newrect,
3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430
		 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 {
3431
	REBAR_CalcHorzBand (infoPtr, startBand, endBand+1,
3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443
			    FALSE);
    }

    TRACE("bands after minimize, see band # %d, %d\n",
	  startBand, endBand);
    REBAR_DumpBand (infoPtr);

    REBAR_MoveChildWindows (infoPtr, startBand, endBand+1);

    InvalidateRect (infoPtr->hwndSelf, &newrect, TRUE);
    UpdateWindow (infoPtr->hwndSelf);
    return FALSE;
3444 3445 3446 3447
}


static LRESULT
3448
REBAR_MoveBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3449
{
3450 3451 3452 3453
    REBAR_BAND *oldBands = infoPtr->bands;
    REBAR_BAND holder;
    UINT uFrom = (UINT)wParam;
    UINT uTo = (UINT)lParam;
3454

3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467
    /* Validate */
    if ((infoPtr->uNumBands == 0) ||
	((INT)uFrom < 0) || (uFrom >= infoPtr->uNumBands) ||
	((INT)uTo < 0)   || (uTo >= infoPtr->uNumBands)) {
	/* error !!! */
	ERR("Illegal MoveBand, from=%d, to=%d, current band count=%d\n",
	      (INT)uFrom, (INT)uTo, infoPtr->uNumBands);
      	return FALSE;
    }

    /* save one to be moved */
    memcpy (&holder, &oldBands[uFrom], sizeof(REBAR_BAND));

3468
    /* close up rest of bands (pseudo delete) */
3469 3470 3471 3472 3473 3474 3475
    if (uFrom < infoPtr->uNumBands - 1) {
	memcpy (&oldBands[uFrom], &oldBands[uFrom+1],
		(infoPtr->uNumBands - uFrom - 1) * sizeof(REBAR_BAND));
    }

    /* allocate new space and copy rest of bands into it */
    infoPtr->bands =
3476
	(REBAR_BAND *)Alloc ((infoPtr->uNumBands)*sizeof(REBAR_BAND));
3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492

    /* pre insert copy */
    if (uTo > 0) {
	memcpy (&infoPtr->bands[0], &oldBands[0],
		uTo * sizeof(REBAR_BAND));
    }

    /* set moved band */
    memcpy (&infoPtr->bands[uTo], &holder, sizeof(REBAR_BAND));

    /* post copy */
    if (uTo < infoPtr->uNumBands - 1) {
	memcpy (&infoPtr->bands[uTo+1], &oldBands[uTo],
		(infoPtr->uNumBands - uTo - 1) * sizeof(REBAR_BAND));
    }

3493
    Free (oldBands);
3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508

    TRACE("moved band %d to index %d\n", uFrom, uTo);
    REBAR_DumpBand (infoPtr);

    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
    /* **************************************************** */
    /*                                                      */
    /* We do not do a REBAR_Layout here because the native  */
    /* control does not do that. The actual layout and      */
    /* repaint is done by the *next* real action, ex.:      */
    /* RB_INSERTBAND, RB_DELETEBAND, RB_SIZETORECT, etc.    */
    /*                                                      */
    /* **************************************************** */

    return TRUE;
3509
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3510 3511


3512 3513 3514 3515 3516 3517 3518
/* return TRUE if two strings are different */
static BOOL
REBAR_strdifW( LPCWSTR a, LPCWSTR b )
{
    return ( (a && !b) || (b && !a) || (a && b && lstrcmpW(a, b) ) );
}

Alexandre Julliard's avatar
Alexandre Julliard committed
3519
static LRESULT
3520
REBAR_SetBandInfoA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3521
{
3522
    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3523
    REBAR_BAND *lpBand;
3524
    BOOL bChanged;
Alexandre Julliard's avatar
Alexandre Julliard committed
3525 3526 3527

    if (lprbbi == NULL)
	return FALSE;
3528
    if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
3529
	return FALSE;
3530
    if ((UINT)wParam >= infoPtr->uNumBands)
Alexandre Julliard's avatar
Alexandre Julliard committed
3531 3532
	return FALSE;

3533
    TRACE("index %u\n", (UINT)wParam);
3534
    REBAR_DumpBandInfo (lprbbi);
Alexandre Julliard's avatar
Alexandre Julliard committed
3535 3536

    /* set band information */
3537
    lpBand = &infoPtr->bands[(UINT)wParam];
Alexandre Julliard's avatar
Alexandre Julliard committed
3538

3539
    bChanged = REBAR_CommonSetupBand (infoPtr->hwndSelf, lprbbi, lpBand);
Eric Kohl's avatar
Eric Kohl committed
3540
    if (lprbbi->fMask & RBBIM_TEXT) {
3541 3542 3543 3544 3545 3546
        LPWSTR wstr = NULL;

        if (lprbbi->lpText)
        {
            INT len;
            len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
3547
            if (len > 1)
3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564
                wstr = (LPWSTR)Alloc (len*sizeof(WCHAR));
            if (wstr)
                MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, wstr, len );
        }
        if (REBAR_strdifW(lpBand->lpText, wstr)) {
	    if (lpBand->lpText) {
	        Free (lpBand->lpText);
	        lpBand->lpText = NULL;
	    }
	    if (wstr) {
                lpBand->lpText = wstr;
                wstr = NULL;
	    }
            bChanged = TRUE;
        }
        if (wstr)
	    Free (wstr);
Alexandre Julliard's avatar
Alexandre Julliard committed
3565 3566
    }

3567
    REBAR_ValidateBand (infoPtr, lpBand);
Alexandre Julliard's avatar
Alexandre Julliard committed
3568

3569
    REBAR_DumpBand (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
3570

3571
    if (bChanged && (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE))) {
3572
	  REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3573 3574
	  InvalidateRect(infoPtr->hwndSelf, 0, 1);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
3575 3576 3577 3578

    return TRUE;
}

Eric Kohl's avatar
Eric Kohl committed
3579
static LRESULT
3580
REBAR_SetBandInfoW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3581
{
3582
    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
Eric Kohl's avatar
Eric Kohl committed
3583
    REBAR_BAND *lpBand;
3584
    BOOL bChanged;
Eric Kohl's avatar
Eric Kohl committed
3585 3586 3587

    if (lprbbi == NULL)
	return FALSE;
3588
    if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE)
Eric Kohl's avatar
Eric Kohl committed
3589
	return FALSE;
3590
    if ((UINT)wParam >= infoPtr->uNumBands)
Eric Kohl's avatar
Eric Kohl committed
3591 3592
	return FALSE;

3593
    TRACE("index %u\n", (UINT)wParam);
3594
    REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
Eric Kohl's avatar
Eric Kohl committed
3595 3596

    /* set band information */
3597
    lpBand = &infoPtr->bands[(UINT)wParam];
Eric Kohl's avatar
Eric Kohl committed
3598

3599 3600 3601
    bChanged = REBAR_CommonSetupBand (infoPtr->hwndSelf, (LPREBARBANDINFOA)lprbbi, lpBand);
    if( (lprbbi->fMask & RBBIM_TEXT) && 
        REBAR_strdifW( lpBand->lpText, lprbbi->lpText ) ) {
Eric Kohl's avatar
Eric Kohl committed
3602
	if (lpBand->lpText) {
3603
	    Free (lpBand->lpText);
Eric Kohl's avatar
Eric Kohl committed
3604 3605 3606
	    lpBand->lpText = NULL;
	}
	if (lprbbi->lpText) {
3607
	    INT len = lstrlenW (lprbbi->lpText);
3608 3609 3610 3611 3612
	    if (len > 0)
	    {
	        lpBand->lpText = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR));
	        strcpyW (lpBand->lpText, lprbbi->lpText);
	    }
Eric Kohl's avatar
Eric Kohl committed
3613
	}
3614
        bChanged = TRUE;
Eric Kohl's avatar
Eric Kohl committed
3615 3616
    }

3617
    REBAR_ValidateBand (infoPtr, lpBand);
Eric Kohl's avatar
Eric Kohl committed
3618

3619
    REBAR_DumpBand (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
3620

3621
    if ( bChanged && (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) ) {
3622
      REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3623 3624
      InvalidateRect(infoPtr->hwndSelf, 0, 1);
    }
Eric Kohl's avatar
Eric Kohl committed
3625 3626 3627

    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3628 3629 3630


static LRESULT
3631
REBAR_SetBarInfo (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3632 3633
{
    LPREBARINFO lpInfo = (LPREBARINFO)lParam;
3634 3635
    REBAR_BAND *lpBand;
    UINT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
3636 3637 3638 3639 3640 3641 3642

    if (lpInfo == NULL)
	return FALSE;

    if (lpInfo->cbSize < sizeof (REBARINFO))
	return FALSE;

3643
    TRACE("setting bar info!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
3644

Eric Kohl's avatar
Eric Kohl committed
3645
    if (lpInfo->fMask & RBIM_IMAGELIST) {
Alexandre Julliard's avatar
Alexandre Julliard committed
3646
	infoPtr->himl = lpInfo->himl;
Eric Kohl's avatar
Eric Kohl committed
3647
	if (infoPtr->himl) {
3648 3649 3650 3651
            INT cx, cy;
	    ImageList_GetIconSize (infoPtr->himl, &cx, &cy);
	    infoPtr->imageSize.cx = cx;
	    infoPtr->imageSize.cy = cy;
Eric Kohl's avatar
Eric Kohl committed
3652 3653 3654 3655 3656
	}
	else {
	    infoPtr->imageSize.cx = 0;
	    infoPtr->imageSize.cy = 0;
	}
3657
	TRACE("new image cx=%d, cy=%d\n", infoPtr->imageSize.cx,
3658
	      infoPtr->imageSize.cy);
Eric Kohl's avatar
Eric Kohl committed
3659
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
3660

3661 3662 3663
    /* revalidate all bands to reset flags for images in headers of bands */
    for (i=0; i<infoPtr->uNumBands; i++) {
        lpBand = &infoPtr->bands[i];
3664
	REBAR_ValidateBand (infoPtr, lpBand);
3665 3666
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
3667 3668 3669 3670 3671
    return TRUE;
}


static LRESULT
3672
REBAR_SetBkColor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3673 3674 3675 3676 3677 3678
{
    COLORREF clrTemp;

    clrTemp = infoPtr->clrBk;
    infoPtr->clrBk = (COLORREF)lParam;

3679
    TRACE("background color 0x%06x!\n", infoPtr->clrBk);
Alexandre Julliard's avatar
Alexandre Julliard committed
3680 3681 3682 3683 3684

    return clrTemp;
}


3685 3686
/* << REBAR_SetColorScheme >> */
/* << REBAR_SetPalette >> */
Eric Kohl's avatar
Eric Kohl committed
3687 3688 3689


static LRESULT
3690
REBAR_SetParent (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3691
{
3692
    HWND hwndTemp = infoPtr->hwndNotify;
Eric Kohl's avatar
Eric Kohl committed
3693

3694
    infoPtr->hwndNotify = (HWND)wParam;
Eric Kohl's avatar
Eric Kohl committed
3695 3696 3697

    return (LRESULT)hwndTemp;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3698 3699 3700


static LRESULT
3701
REBAR_SetTextColor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3702 3703 3704 3705 3706 3707
{
    COLORREF clrTemp;

    clrTemp = infoPtr->clrText;
    infoPtr->clrText = (COLORREF)lParam;

3708
    TRACE("text color 0x%06x!\n", infoPtr->clrText);
Alexandre Julliard's avatar
Alexandre Julliard committed
3709 3710 3711 3712 3713

    return clrTemp;
}


3714
/* << REBAR_SetTooltips >> */
Eric Kohl's avatar
Eric Kohl committed
3715 3716


Patrik Stridvall's avatar
Patrik Stridvall committed
3717
inline static LRESULT
3718
REBAR_SetUnicodeFormat (REBAR_INFO *infoPtr, WPARAM wParam)
Eric Kohl's avatar
Eric Kohl committed
3719
{
3720
    BOOL bTemp = infoPtr->bUnicode;
3721

3722
    TRACE("to %s hwnd=%p, was %s\n",
3723 3724 3725
	  ((BOOL)wParam) ? "TRUE" : "FALSE", infoPtr->hwndSelf,
	  (bTemp) ? "TRUE" : "FALSE");

3726
    infoPtr->bUnicode = (BOOL)wParam;
3727

3728
   return bTemp;
Eric Kohl's avatar
Eric Kohl committed
3729
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3730 3731


Eric Kohl's avatar
Eric Kohl committed
3732
static LRESULT
3733
REBAR_SetVersion (REBAR_INFO *infoPtr, INT iVersion)
Eric Kohl's avatar
Eric Kohl committed
3734 3735 3736 3737 3738 3739 3740 3741
{
    INT iOldVersion = infoPtr->iVersion;

    if (iVersion > COMCTL32_VERSION)
	return -1;

    infoPtr->iVersion = iVersion;

3742 3743
    TRACE("new version %d\n", iVersion);

Eric Kohl's avatar
Eric Kohl committed
3744 3745 3746 3747
    return iOldVersion;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
3748
static LRESULT
3749
REBAR_ShowBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3750
{
Eric Kohl's avatar
Eric Kohl committed
3751
    REBAR_BAND *lpBand;
Alexandre Julliard's avatar
Alexandre Julliard committed
3752

3753
    if (((INT)wParam < 0) || ((INT)wParam > infoPtr->uNumBands))
Alexandre Julliard's avatar
Alexandre Julliard committed
3754 3755
	return FALSE;

3756
    lpBand = &infoPtr->bands[(INT)wParam];
Eric Kohl's avatar
Eric Kohl committed
3757

3758
    if ((BOOL)lParam) {
3759
	TRACE("show band %d\n", (INT)wParam);
Eric Kohl's avatar
Eric Kohl committed
3760
	lpBand->fStyle = lpBand->fStyle & ~RBBS_HIDDEN;
3761 3762
	if (IsWindow (lpBand->hwndChild))
	    ShowWindow (lpBand->hwndChild, SW_SHOW);
Eric Kohl's avatar
Eric Kohl committed
3763 3764
    }
    else {
3765
	TRACE("hide band %d\n", (INT)wParam);
Eric Kohl's avatar
Eric Kohl committed
3766
	lpBand->fStyle = lpBand->fStyle | RBBS_HIDDEN;
3767
	if (IsWindow (lpBand->hwndChild))
3768
	    ShowWindow (lpBand->hwndChild, SW_HIDE);
Eric Kohl's avatar
Eric Kohl committed
3769 3770
    }

3771
    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
3772
    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3773
    InvalidateRect(infoPtr->hwndSelf, 0, 1);
Alexandre Julliard's avatar
Alexandre Julliard committed
3774 3775 3776 3777 3778 3779

    return TRUE;
}


static LRESULT
3780
REBAR_SizeToRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3781
{
3782
    LPRECT lpRect = (LPRECT)lParam;
3783
    RECT t1;
Alexandre Julliard's avatar
Alexandre Julliard committed
3784 3785

    if (lpRect == NULL)
3786
       return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
3787

3788
    TRACE("[%d %d %d %d]\n",
3789
	  lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
Eric Kohl's avatar
Eric Kohl committed
3790

3791
    /*  what is going on???? */
3792
    GetWindowRect(infoPtr->hwndSelf, &t1);
3793
    TRACE("window rect [%d %d %d %d]\n",
3794
	  t1.left, t1.top, t1.right, t1.bottom);
3795
    GetClientRect(infoPtr->hwndSelf, &t1);
3796
    TRACE("client rect [%d %d %d %d]\n",
3797
	  t1.left, t1.top, t1.right, t1.bottom);
Eric Kohl's avatar
Eric Kohl committed
3798

3799 3800 3801 3802
    /* force full _Layout processing */
    TRACE("setting NEEDS_LAYOUT\n");
    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
    REBAR_Layout (infoPtr, lpRect, TRUE, FALSE);
3803
    InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
3804 3805
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3806 3807 3808 3809



static LRESULT
3810
REBAR_Create (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3811
{
3812
    LPCREATESTRUCTW cs = (LPCREATESTRUCTW) lParam;
3813
    RECT wnrc1, clrc1;
3814
    HTHEME theme;
3815 3816

    if (TRACE_ON(rebar)) {
3817 3818
	GetWindowRect(infoPtr->hwndSelf, &wnrc1);
	GetClientRect(infoPtr->hwndSelf, &clrc1);
3819
	TRACE("window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d) cs=(%d,%d %dx%d)\n",
3820 3821 3822 3823
	      wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom,
	      clrc1.left, clrc1.top, clrc1.right, clrc1.bottom,
	      cs->x, cs->y, cs->cx, cs->cy);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
3824

3825
    TRACE("created!\n");
3826 3827 3828 3829 3830 3831 3832
    
    if ((theme = OpenThemeData (infoPtr->hwndSelf, themeClass)))
    {
        /* native seems to clear WS_BORDER when themed */
        infoPtr->dwStyle &= ~WS_BORDER;
    }
    
Alexandre Julliard's avatar
Alexandre Julliard committed
3833 3834 3835 3836 3837
    return 0;
}


static LRESULT
3838
REBAR_Destroy (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3839 3840
{
    REBAR_BAND *lpBand;
3841
    UINT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
3842 3843 3844 3845 3846 3847 3848 3849 3850 3851


    /* free rebar bands */
    if ((infoPtr->uNumBands > 0) && infoPtr->bands) {
	/* clean up each band */
	for (i = 0; i < infoPtr->uNumBands; i++) {
	    lpBand = &infoPtr->bands[i];

	    /* delete text strings */
	    if (lpBand->lpText) {
3852
		Free (lpBand->lpText);
Alexandre Julliard's avatar
Alexandre Julliard committed
3853 3854
		lpBand->lpText = NULL;
	    }
3855
	    /* destroy child window */
3856
	    DestroyWindow (lpBand->hwndChild);
Alexandre Julliard's avatar
Alexandre Julliard committed
3857 3858 3859
	}

	/* free band array */
3860
	Free (infoPtr->bands);
Alexandre Julliard's avatar
Alexandre Julliard committed
3861 3862 3863
	infoPtr->bands = NULL;
    }

3864 3865 3866 3867
    DestroyCursor (infoPtr->hcurArrow);
    DestroyCursor (infoPtr->hcurHorz);
    DestroyCursor (infoPtr->hcurVert);
    DestroyCursor (infoPtr->hcurDrag);
3868
    if(infoPtr->hDefaultFont) DeleteObject (infoPtr->hDefaultFont);
3869
    SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0);
3870 3871
    
    CloseThemeData (GetWindowTheme (infoPtr->hwndSelf));
Eric Kohl's avatar
Eric Kohl committed
3872

Alexandre Julliard's avatar
Alexandre Julliard committed
3873
    /* free rebar info data */
3874
    Free (infoPtr);
3875
    TRACE("destroyed!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
3876 3877 3878 3879
    return 0;
}


3880
static LRESULT
3881
REBAR_EraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3882 3883 3884 3885
{
    RECT cliprect;

    if (GetClipBox ( (HDC)wParam, &cliprect))
3886
        return REBAR_InternalEraseBkGnd (infoPtr, wParam, lParam, &cliprect);
3887 3888 3889 3890
    return 0;
}


Eric Kohl's avatar
Eric Kohl committed
3891
static LRESULT
3892
REBAR_GetFont (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3893 3894 3895 3896
{
    return (LRESULT)infoPtr->hFont;
}

Robert Shearman's avatar
Robert Shearman committed
3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927
static LRESULT
REBAR_PushChevron(REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
    if (wParam >= 0 && (UINT)wParam < infoPtr->uNumBands)
    {
        NMREBARCHEVRON nmrbc;
        REBAR_BAND *lpBand = &infoPtr->bands[wParam];

        TRACE("Pressed chevron on band %d\n", wParam);

        /* redraw chevron in pushed state */
        lpBand->fDraw |= DRAW_CHEVRONPUSHED;
        RedrawWindow(infoPtr->hwndSelf, &lpBand->rcChevron,0,
          RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);

        /* notify app so it can display a popup menu or whatever */
        nmrbc.uBand = wParam;
        nmrbc.wID = lpBand->wID;
        nmrbc.lParam = lpBand->lParam;
        nmrbc.rc = lpBand->rcChevron;
        nmrbc.lParamNM = lParam;
        REBAR_Notify((NMHDR*)&nmrbc, infoPtr, RBN_CHEVRONPUSHED);

        /* redraw chevron in previous state */
        lpBand->fDraw &= ~DRAW_CHEVRONPUSHED;
        InvalidateRect(infoPtr->hwndSelf, &lpBand->rcChevron, TRUE);

        return TRUE;
    }
    return FALSE;
}
Eric Kohl's avatar
Eric Kohl committed
3928

3929
static LRESULT
3930
REBAR_LButtonDown (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3931 3932
{
    REBAR_BAND *lpBand;
Robert Shearman's avatar
Robert Shearman committed
3933
    UINT htFlags;
Mike McCormack's avatar
Mike McCormack committed
3934
    INT iHitBand;
Robert Shearman's avatar
Robert Shearman committed
3935
    POINT ptMouseDown;
3936 3937
    ptMouseDown.x = (short)LOWORD(lParam);
    ptMouseDown.y = (short)HIWORD(lParam);
3938

Robert Shearman's avatar
Robert Shearman committed
3939 3940
    REBAR_InternalHitTest(infoPtr, &ptMouseDown, &htFlags, &iHitBand);
    lpBand = &infoPtr->bands[iHitBand];
3941

Robert Shearman's avatar
Robert Shearman committed
3942 3943 3944 3945 3946 3947 3948
    if (htFlags == RBHT_CHEVRON)
    {
        REBAR_PushChevron(infoPtr, iHitBand, 0);
    }
    else if (htFlags == RBHT_GRABBER || htFlags == RBHT_CAPTION)
    {
        TRACE("Starting drag\n");
3949

Robert Shearman's avatar
Robert Shearman committed
3950 3951
        SetCapture (infoPtr->hwndSelf);
        infoPtr->iGrabbedBand = iHitBand;
3952

Robert Shearman's avatar
Robert Shearman committed
3953
        /* save off the LOWORD and HIWORD of lParam as initial x,y */
3954 3955
        infoPtr->dragStart.x = (short)LOWORD(lParam);
        infoPtr->dragStart.y = (short)HIWORD(lParam);
Robert Shearman's avatar
Robert Shearman committed
3956 3957 3958 3959 3960 3961
        infoPtr->dragNow = infoPtr->dragStart;
        if (infoPtr->dwStyle & CCS_VERT)
            infoPtr->ihitoffset = infoPtr->dragStart.y - (lpBand->rcBand.top+REBAR_PRE_GRIPPER);
        else
            infoPtr->ihitoffset = infoPtr->dragStart.x - (lpBand->rcBand.left+REBAR_PRE_GRIPPER);
    }
3962 3963 3964 3965
    return 0;
}

static LRESULT
3966
REBAR_LButtonUp (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3967
{
Robert Shearman's avatar
Robert Shearman committed
3968 3969 3970 3971 3972 3973 3974 3975
    if (infoPtr->iGrabbedBand >= 0)
    {
        NMHDR layout;
        RECT rect;

        infoPtr->dragStart.x = 0;
        infoPtr->dragStart.y = 0;
        infoPtr->dragNow = infoPtr->dragStart;
3976

Robert Shearman's avatar
Robert Shearman committed
3977
        ReleaseCapture ();
3978

Robert Shearman's avatar
Robert Shearman committed
3979 3980 3981 3982 3983
        if (infoPtr->fStatus & BEGIN_DRAG_ISSUED) {
            REBAR_Notify(&layout, infoPtr, RBN_LAYOUTCHANGED);
            REBAR_Notify_NMREBAR (infoPtr, infoPtr->iGrabbedBand, RBN_ENDDRAG);
            infoPtr->fStatus &= ~BEGIN_DRAG_ISSUED;
        }
3984

Robert Shearman's avatar
Robert Shearman committed
3985
        infoPtr->iGrabbedBand = -1;
3986

Robert Shearman's avatar
Robert Shearman committed
3987 3988
        GetClientRect(infoPtr->hwndSelf, &rect);
        InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
3989 3990 3991 3992 3993
    }

    return 0;
}

Robert Shearman's avatar
Robert Shearman committed
3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010
static LRESULT
REBAR_MouseLeave (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
    if (infoPtr->ichevronhotBand >= 0)
    {
        REBAR_BAND *lpChevronBand = &infoPtr->bands[infoPtr->ichevronhotBand];
        if (lpChevronBand->fDraw & DRAW_CHEVRONHOT)
        {
            lpChevronBand->fDraw &= ~DRAW_CHEVRONHOT;
            InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
        }
    }
    infoPtr->iOldBand = -1;
    infoPtr->ichevronhotBand = -2;

    return TRUE;
}
4011

Eric Kohl's avatar
Eric Kohl committed
4012
static LRESULT
4013
REBAR_MouseMove (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4014
{
Robert Shearman's avatar
Robert Shearman committed
4015
    REBAR_BAND *lpChevronBand;
4016
    POINT ptMove;
Eric Kohl's avatar
Eric Kohl committed
4017

4018 4019
    ptMove.x = (short)LOWORD(lParam);
    ptMove.y = (short)HIWORD(lParam);
4020

Robert Shearman's avatar
Robert Shearman committed
4021 4022 4023 4024 4025 4026 4027
    /* if we are currently dragging a band */
    if (infoPtr->iGrabbedBand >= 0)
    {
        REBAR_BAND *band1, *band2;
    
        if (GetCapture() != infoPtr->hwndSelf)
            ERR("We are dragging but haven't got capture?!?\n");
4028

Robert Shearman's avatar
Robert Shearman committed
4029 4030
        band1 = &infoPtr->bands[infoPtr->iGrabbedBand-1];
        band2 = &infoPtr->bands[infoPtr->iGrabbedBand];
4031

Robert Shearman's avatar
Robert Shearman committed
4032
        /* if mouse did not move much, exit */
4033 4034
        if ((abs(ptMove.x - infoPtr->dragNow.x) <= mindragx) &&
            (abs(ptMove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
Robert Shearman's avatar
Robert Shearman committed
4035 4036 4037

        /* Test for valid drag case - must not be first band in row */
        if (infoPtr->dwStyle & CCS_VERT) {
4038 4039
            if ((ptMove.x < band2->rcBand.left) ||
	      (ptMove.x > band2->rcBand.right) ||
Robert Shearman's avatar
Robert Shearman committed
4040 4041 4042 4043
              ((infoPtr->iGrabbedBand > 0) && (band1->iRow != band2->iRow))) {
                FIXME("Cannot drag to other rows yet!!\n");
            }
            else {
4044
                REBAR_HandleLRDrag (infoPtr, &ptMove);
Robert Shearman's avatar
Robert Shearman committed
4045 4046 4047
            }
        }
        else {
4048 4049
            if ((ptMove.y < band2->rcBand.top) ||
              (ptMove.y > band2->rcBand.bottom) ||
Robert Shearman's avatar
Robert Shearman committed
4050 4051 4052 4053
              ((infoPtr->iGrabbedBand > 0) && (band1->iRow != band2->iRow))) {
                FIXME("Cannot drag to other rows yet!!\n");
            }
            else {
4054
                REBAR_HandleLRDrag (infoPtr, &ptMove);
Robert Shearman's avatar
Robert Shearman committed
4055 4056
            }
        }
4057
    }
Robert Shearman's avatar
Robert Shearman committed
4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106
    else
    {
        INT iHitBand;
        UINT htFlags;
        TRACKMOUSEEVENT trackinfo;

        REBAR_InternalHitTest(infoPtr, &ptMove, &htFlags, &iHitBand);

        if (infoPtr->iOldBand >= 0 && infoPtr->iOldBand == infoPtr->ichevronhotBand)
        {
            lpChevronBand = &infoPtr->bands[infoPtr->ichevronhotBand];
            if (lpChevronBand->fDraw & DRAW_CHEVRONHOT)
            {
                lpChevronBand->fDraw &= ~DRAW_CHEVRONHOT;
                InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
            }
            infoPtr->ichevronhotBand = -2;
        }

        if (htFlags == RBHT_CHEVRON)
        {
            /* fill in the TRACKMOUSEEVENT struct */
            trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
            trackinfo.dwFlags = TME_QUERY;
            trackinfo.hwndTrack = infoPtr->hwndSelf;
            trackinfo.dwHoverTime = 0;

            /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
            _TrackMouseEvent(&trackinfo);

            /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
            if(!(trackinfo.dwFlags & TME_LEAVE))
            {
                trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */

                /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
                /* and can properly deactivate the hot chevron */
                _TrackMouseEvent(&trackinfo);
            }

            lpChevronBand = &infoPtr->bands[iHitBand];
            if (!(lpChevronBand->fDraw & DRAW_CHEVRONHOT))
            {
                lpChevronBand->fDraw |= DRAW_CHEVRONHOT;
                InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
                infoPtr->ichevronhotBand = iHitBand;
            }
        }
        infoPtr->iOldBand = iHitBand;
4107
    }
Robert Shearman's avatar
Robert Shearman committed
4108

Eric Kohl's avatar
Eric Kohl committed
4109 4110 4111 4112
    return 0;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
4113
inline static LRESULT
4114
REBAR_NCCalcSize (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4115
{
4116
    HTHEME theme;
4117 4118
    RECT *rect = (RECT *)lParam;

4119
    if (infoPtr->dwStyle & WS_BORDER) {
4120 4121
        rect->left   = min(rect->left + GetSystemMetrics(SM_CXEDGE), rect->right);
        rect->right  = max(rect->right - GetSystemMetrics(SM_CXEDGE), rect->left);
4122 4123
        rect->top    = min(rect->top + GetSystemMetrics(SM_CYEDGE), rect->bottom);
        rect->bottom = max(rect->bottom - GetSystemMetrics(SM_CYEDGE), rect->top);
Eric Kohl's avatar
Eric Kohl committed
4124
    }
4125 4126
    else if ((theme = GetWindowTheme (infoPtr->hwndSelf)))
    {
4127
        /* FIXME: should use GetThemeInt */
4128
        rect->top = min(rect->top + 1, rect->bottom);
4129
    }
4130
    TRACE("new client=(%d,%d)-(%d,%d)\n", rect->left, rect->top, rect->right, rect->bottom);
4131
    return 0;
Eric Kohl's avatar
Eric Kohl committed
4132 4133 4134
}


4135 4136 4137
static LRESULT
REBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
4138
    LPCREATESTRUCTW cs = (LPCREATESTRUCTW) lParam;
4139 4140
    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
    RECT wnrc1, clrc1;
4141
    NONCLIENTMETRICSW ncm;
4142
    HFONT tfont;
4143 4144 4145 4146 4147 4148 4149 4150 4151

    if (infoPtr != NULL) {
	ERR("Strange info structure pointer *not* NULL\n");
	return FALSE;
    }

    if (TRACE_ON(rebar)) {
	GetWindowRect(hwnd, &wnrc1);
	GetClientRect(hwnd, &clrc1);
4152
	TRACE("window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d) cs=(%d,%d %dx%d)\n",
4153 4154 4155 4156 4157 4158
	      wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom,
	      clrc1.left, clrc1.top, clrc1.right, clrc1.bottom,
	      cs->x, cs->y, cs->cx, cs->cy);
    }

    /* allocate memory for info structure */
4159
    infoPtr = (REBAR_INFO *)Alloc (sizeof(REBAR_INFO));
4160
    SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
4161 4162 4163

    /* initialize info structure - initial values are 0 */
    infoPtr->clrBk = CLR_NONE;
4164 4165
    infoPtr->clrText = CLR_NONE;
    infoPtr->clrBtnText = GetSysColor (COLOR_BTNTEXT);
4166
    infoPtr->clrBtnFace = GetSysColor (COLOR_BTNFACE);
Robert Shearman's avatar
Robert Shearman committed
4167 4168 4169
    infoPtr->iOldBand = -1;
    infoPtr->ichevronhotBand = -2;
    infoPtr->iGrabbedBand = -1;
4170 4171
    infoPtr->hwndSelf = hwnd;
    infoPtr->DoRedraw = TRUE;
4172 4173 4174 4175
    infoPtr->hcurArrow = LoadCursorW (0, (LPWSTR)IDC_ARROW);
    infoPtr->hcurHorz  = LoadCursorW (0, (LPWSTR)IDC_SIZEWE);
    infoPtr->hcurVert  = LoadCursorW (0, (LPWSTR)IDC_SIZENS);
    infoPtr->hcurDrag  = LoadCursorW (0, (LPWSTR)IDC_SIZE);
4176
    infoPtr->fStatus = CREATE_RUNNING;
4177
    infoPtr->hFont = GetStockObject (SYSTEM_FONT);
4178 4179

    /* issue WM_NOTIFYFORMAT to get unicode status of parent */
4180
    REBAR_NotifyFormat(infoPtr, 0, NF_REQUERY);
4181

4182 4183
    /* Stow away the original style */
    infoPtr->orgStyle = cs->style;
4184 4185
    /* add necessary styles to the requested styles */
    infoPtr->dwStyle = cs->style | WS_VISIBLE | CCS_TOP;
4186
    SetWindowLongW (hwnd, GWL_STYLE, infoPtr->dwStyle);
4187

4188
    /* get font handle for Caption Font */
4189
    ncm.cbSize = sizeof(ncm);
4190
    SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
4191 4192 4193 4194
    /* if the font is bold, set to normal */
    if (ncm.lfCaptionFont.lfWeight > FW_NORMAL) {
	ncm.lfCaptionFont.lfWeight = FW_NORMAL;
    }
4195
    tfont = CreateFontIndirectW (&ncm.lfCaptionFont);
4196
    if (tfont) {
4197
        infoPtr->hFont = infoPtr->hDefaultFont = tfont;
4198 4199
    }

4200 4201 4202
/* native does:
	    GetSysColor (numerous);
	    GetSysColorBrush (numerous) (see WM_SYSCOLORCHANGE);
4203
	   *GetStockObject (SYSTEM_FONT);
4204 4205 4206 4207 4208
	   *SetWindowLong (hwnd, 0, info ptr);
	   *WM_NOTIFYFORMAT;
	   *SetWindowLong (hwnd, GWL_STYLE, style+0x10000001);
                                    WS_VISIBLE = 0x10000000;
                                    CCS_TOP    = 0x00000001;
4209 4210
	   *SystemParametersInfo (SPI_GETNONCLIENTMETRICS...);
	   *CreateFontIndirect (lfCaptionFont from above);
4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230
	    GetDC ();
	    SelectObject (hdc, fontabove);
	    GetTextMetrics (hdc, );    guessing is tmHeight
	    SelectObject (hdc, oldfont);
	    ReleaseDC ();
	    GetWindowRect ();
	    MapWindowPoints (0, parent, rectabove, 2);
	    GetWindowRect ();
	    GetClientRect ();
	    ClientToScreen (clientrect);
	    SetWindowPos (hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER);
 */
    return TRUE;
}


static LRESULT
REBAR_NCHitTest (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
    NMMOUSE nmmouse;
4231
    POINT clpt;
4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243
    INT i;
    UINT scrap;
    LRESULT ret = HTCLIENT;

    /*
     * Differences from doc at MSDN (as observed with version 4.71 of
     *      comctl32.dll
     * 1. doc says nmmouse.pt is in screen coord, trace shows client coord.
     * 2. if band is not identified .dwItemSpec is 0xffffffff.
     * 3. native always seems to return HTCLIENT if notify return is 0.
     */

4244 4245
    clpt.x = (short)LOWORD(lParam);
    clpt.y = (short)HIWORD(lParam);
4246
    ScreenToClient (infoPtr->hwndSelf, &clpt);
4247
    REBAR_InternalHitTest (infoPtr, &clpt, &scrap,
4248 4249 4250 4251 4252 4253
			   (INT *)&nmmouse.dwItemSpec);
    nmmouse.dwItemData = 0;
    nmmouse.pt = clpt;
    nmmouse.dwHitInfo = 0;
    if ((i = REBAR_Notify((NMHDR *) &nmmouse, infoPtr, NM_NCHITTEST))) {
	TRACE("notify changed return value from %ld to %d\n",
4254
	      ret, i);
4255 4256
	ret = (LRESULT) i;
    }
4257
    TRACE("returning %ld, client point (%d,%d)\n", ret, clpt.x, clpt.y);
4258 4259 4260 4261
    return ret;
}


Eric Kohl's avatar
Eric Kohl committed
4262
static LRESULT
4263
REBAR_NCPaint (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4264
{
4265
    RECT rcWindow;
4266
    HDC hdc;
4267
    HTHEME theme;
Eric Kohl's avatar
Eric Kohl committed
4268

4269
    if (infoPtr->dwStyle & WS_MINIMIZE)
4270
	return 0; /* Nothing to do */
Eric Kohl's avatar
Eric Kohl committed
4271

4272
    if (infoPtr->dwStyle & WS_BORDER) {
4273 4274 4275 4276

	/* adjust rectangle and draw the necessary edge */
	if (!(hdc = GetDCEx( infoPtr->hwndSelf, 0, DCX_USESTYLE | DCX_WINDOW )))
	    return 0;
4277
	GetWindowRect (infoPtr->hwndSelf, &rcWindow);
4278
	OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
4279
	TRACE("rect (%d,%d)-(%d,%d)\n",
4280 4281
	      rcWindow.left, rcWindow.top,
	      rcWindow.right, rcWindow.bottom);
4282 4283
	DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT);
	ReleaseDC( infoPtr->hwndSelf, hdc );
4284
    }
4285 4286 4287 4288 4289 4290 4291
    else if ((theme = GetWindowTheme (infoPtr->hwndSelf)))
    {
        /* adjust rectangle and draw the necessary edge */
        if (!(hdc = GetDCEx( infoPtr->hwndSelf, 0, DCX_USESTYLE | DCX_WINDOW )))
            return 0;
        GetWindowRect (infoPtr->hwndSelf, &rcWindow);
        OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
4292
        TRACE("rect (%d,%d)-(%d,%d)\n",
4293 4294 4295 4296 4297
              rcWindow.left, rcWindow.top,
              rcWindow.right, rcWindow.bottom);
        DrawThemeEdge (theme, hdc, 0, 0, &rcWindow, BDR_RAISEDINNER, BF_TOP, NULL);
        ReleaseDC( infoPtr->hwndSelf, hdc );
    }
Eric Kohl's avatar
Eric Kohl committed
4298 4299 4300 4301

    return 0;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
4302

4303 4304 4305 4306 4307 4308
static LRESULT
REBAR_NotifyFormat (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
    INT i;

    if (lParam == NF_REQUERY) {
4309
	i = SendMessageW(REBAR_GetNotifyParent (infoPtr),
4310
			 WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY);
4311
        if ((i != NFR_ANSI) && (i != NFR_UNICODE)) {
4312
	    ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n", i);
4313 4314
	    i = NFR_ANSI;
	}
4315
        infoPtr->bUnicode = (i == NFR_UNICODE) ? 1 : 0;
4316 4317 4318 4319 4320 4321
	return (LRESULT)i;
    }
    return (LRESULT)((infoPtr->bUnicode) ? NFR_UNICODE : NFR_ANSI);
}


Alexandre Julliard's avatar
Alexandre Julliard committed
4322
static LRESULT
4323
REBAR_Paint (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4324
{
4325 4326
    HDC hdc;
    PAINTSTRUCT ps;
4327
    RECT rc;
Alexandre Julliard's avatar
Alexandre Julliard committed
4328

4329 4330
    GetClientRect(infoPtr->hwndSelf, &rc);
    hdc = wParam==0 ? BeginPaint (infoPtr->hwndSelf, &ps) : (HDC)wParam;
4331

4332
    TRACE("painting (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n",
4333
	  ps.rcPaint.left, ps.rcPaint.top,
4334 4335
	  ps.rcPaint.right, ps.rcPaint.bottom,
	  rc.left, rc.top, rc.right, rc.bottom);
4336

4337 4338
    if (ps.fErase) {
	/* Erase area of paint if requested */
4339
        REBAR_InternalEraseBkGnd (infoPtr, wParam, lParam, &ps.rcPaint);
4340 4341
    }

4342
    REBAR_Refresh (infoPtr, hdc);
Alexandre Julliard's avatar
Alexandre Julliard committed
4343
    if (!wParam)
4344
	EndPaint (infoPtr->hwndSelf, &ps);
Alexandre Julliard's avatar
Alexandre Julliard committed
4345 4346 4347 4348
    return 0;
}


Eric Kohl's avatar
Eric Kohl committed
4349
static LRESULT
4350
REBAR_SetCursor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4351
{
4352 4353
    POINT pt;
    UINT  flags;
Eric Kohl's avatar
Eric Kohl committed
4354

4355
    TRACE("code=0x%X  id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
Eric Kohl's avatar
Eric Kohl committed
4356

4357
    GetCursorPos (&pt);
4358
    ScreenToClient (infoPtr->hwndSelf, &pt);
Eric Kohl's avatar
Eric Kohl committed
4359

4360
    REBAR_InternalHitTest (infoPtr, &pt, &flags, NULL);
Eric Kohl's avatar
Eric Kohl committed
4361 4362

    if (flags == RBHT_GRABBER) {
4363 4364
	if ((infoPtr->dwStyle & CCS_VERT) &&
	    !(infoPtr->dwStyle & RBS_VERTICALGRIPPER))
4365
	    SetCursor (infoPtr->hcurVert);
Eric Kohl's avatar
Eric Kohl committed
4366
	else
4367
	    SetCursor (infoPtr->hcurHorz);
Eric Kohl's avatar
Eric Kohl committed
4368 4369
    }
    else if (flags != RBHT_CLIENT)
4370
	SetCursor (infoPtr->hcurArrow);
Eric Kohl's avatar
Eric Kohl committed
4371 4372 4373 4374 4375 4376

    return 0;
}


static LRESULT
4377
REBAR_SetFont (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4378
{
4379 4380 4381
    RECT rcClient;
    REBAR_BAND *lpBand;
    UINT i;
Eric Kohl's avatar
Eric Kohl committed
4382

4383
    infoPtr->hFont = (HFONT)wParam;
Eric Kohl's avatar
Eric Kohl committed
4384

4385 4386 4387
    /* revalidate all bands to change sizes of text in headers of bands */
    for (i=0; i<infoPtr->uNumBands; i++) {
        lpBand = &infoPtr->bands[i];
4388
	REBAR_ValidateBand (infoPtr, lpBand);
4389 4390 4391
    }


4392
    if (LOWORD(lParam)) {
4393 4394
        GetClientRect (infoPtr->hwndSelf, &rcClient);
        REBAR_Layout (infoPtr, &rcClient, FALSE, TRUE);
Eric Kohl's avatar
Eric Kohl committed
4395 4396 4397 4398 4399
    }

    return 0;
}

4400

4401 4402
inline static LRESULT
REBAR_SetRedraw (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4403 4404 4405 4406 4407 4408
     /*****************************************************
      *
      * Function;
      *  Handles the WM_SETREDRAW message.
      *
      * Documentation:
4409
      *  According to testing V4.71 of COMCTL32 returns the
4410 4411 4412 4413 4414 4415 4416
      *  *previous* status of the redraw flag (either 0 or -1)
      *  instead of the MSDN documented value of 0 if handled
      *
      *****************************************************/
{
    BOOL oldredraw = infoPtr->DoRedraw;

4417
    TRACE("set to %s, fStatus=%08x\n",
4418
	  (wParam) ? "TRUE" : "FALSE", infoPtr->fStatus);
4419
    infoPtr->DoRedraw = (BOOL) wParam;
4420 4421 4422 4423 4424 4425 4426 4427 4428
    if (wParam) {
	if (infoPtr->fStatus & BAND_NEEDS_REDRAW) {
	    REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands);
	    REBAR_ForceResize (infoPtr);
	    InvalidateRect (infoPtr->hwndSelf, 0, TRUE);
	}
	infoPtr->fStatus &= ~BAND_NEEDS_REDRAW;
    }
    return (oldredraw) ? -1 : 0;
4429 4430
}

4431

Eric Kohl's avatar
Eric Kohl committed
4432
static LRESULT
4433
REBAR_Size (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4434
{
4435
    RECT rcClient;
Eric Kohl's avatar
Eric Kohl committed
4436 4437

    /* auto resize deadlock check */
4438 4439
    if (infoPtr->fStatus & AUTO_RESIZE) {
	infoPtr->fStatus &= ~AUTO_RESIZE;
4440 4441
	TRACE("AUTO_RESIZE was set, reset, fStatus=%08x lparam=%08lx\n",
	      infoPtr->fStatus, lParam);
Eric Kohl's avatar
Eric Kohl committed
4442 4443 4444
	return 0;
    }

4445 4446 4447 4448
    if (infoPtr->fStatus & CREATE_RUNNING) {
	/* still in CreateWindow */
	RECT rcWin;

4449 4450 4451 4452 4453
	if ((INT)wParam != SIZE_RESTORED) {
	    ERR("WM_SIZE in create and flags=%08x, lParam=%08lx\n",
		wParam, lParam);
	}

4454 4455 4456
	TRACE("still in CreateWindow\n");
	infoPtr->fStatus &= ~CREATE_RUNNING;
	GetWindowRect ( infoPtr->hwndSelf, &rcWin);
4457
	TRACE("win rect (%d,%d)-(%d,%d)\n",
4458 4459
	      rcWin.left, rcWin.top, rcWin.right, rcWin.bottom);

4460
	if ((lParam == 0) && (rcWin.right-rcWin.left == 0) &&
4461 4462 4463
	    (rcWin.bottom-rcWin.top == 0)) {
	    /* native control seems to do this */
	    GetClientRect (GetParent(infoPtr->hwndSelf), &rcClient);
4464
            TRACE("sizing rebar, message and client zero, parent client (%d,%d)\n",
4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477
		  rcClient.right, rcClient.bottom);
	}
	else {
	    INT cx, cy;

	    cx = rcWin.right - rcWin.left;
	    cy = rcWin.bottom - rcWin.top;
	    if ((cx == LOWORD(lParam)) && (cy == HIWORD(lParam))) {
		return 0;
	    }

	    /* do the actual WM_SIZE request */
	    GetClientRect (infoPtr->hwndSelf, &rcClient);
4478
            TRACE("sizing rebar from (%d,%d) to (%d,%d), client (%d,%d)\n",
4479 4480 4481 4482
		  infoPtr->calcSize.cx, infoPtr->calcSize.cy,
		  LOWORD(lParam), HIWORD(lParam),
		  rcClient.right, rcClient.bottom);
	}
Eric Kohl's avatar
Eric Kohl committed
4483 4484
    }
    else {
4485 4486 4487 4488 4489
	if ((INT)wParam != SIZE_RESTORED) {
	    ERR("WM_SIZE out of create and flags=%08x, lParam=%08lx\n",
		wParam, lParam);
	}

4490 4491 4492 4493 4494 4495
	/* Handle cases when outside of the CreateWindow process */

	GetClientRect (infoPtr->hwndSelf, &rcClient);
	if ((lParam == 0) && (rcClient.right + rcClient.bottom != 0) &&
	    (infoPtr->dwStyle & RBS_AUTOSIZE)) {
	    /* on a WM_SIZE to zero and current client not zero and AUTOSIZE */
4496
	    /* native seems to use the current parent width for the size     */
4497
	    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
4498 4499 4500 4501 4502
	    GetClientRect (GetParent(infoPtr->hwndSelf), &rcClient);
            if (infoPtr->dwStyle & CCS_VERT)
                rcClient.right = 0;
            else
                rcClient.bottom = 0;
4503
            TRACE("sizing rebar to parent (%d,%d) size is zero but AUTOSIZE set\n",
4504 4505 4506
		  rcClient.right, rcClient.bottom);
	}
	else {
4507
            TRACE("sizing rebar from (%d,%d) to (%d,%d), client (%d,%d)\n",
4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520
		  infoPtr->calcSize.cx, infoPtr->calcSize.cy,
		  LOWORD(lParam), HIWORD(lParam),
		  rcClient.right, rcClient.bottom);
	}
    }

    if (infoPtr->dwStyle & RBS_AUTOSIZE) {
	NMRBAUTOSIZE autosize;

	GetClientRect(infoPtr->hwndSelf, &autosize.rcTarget);
	autosize.fChanged = 0;  /* ??? */
	autosize.rcActual = autosize.rcTarget;  /* ??? */
	REBAR_Notify((NMHDR *) &autosize, infoPtr, RBN_AUTOSIZE);
4521
	TRACE("RBN_AUTOSIZE client=(%d,%d), lp=%08lx\n",
4522
	      autosize.rcTarget.right, autosize.rcTarget.bottom, lParam);
Eric Kohl's avatar
Eric Kohl committed
4523 4524
    }

4525 4526 4527 4528 4529
    if ((infoPtr->calcSize.cx != rcClient.right) ||
	(infoPtr->calcSize.cy != rcClient.bottom))
	infoPtr->fStatus |= BAND_NEEDS_LAYOUT;

    REBAR_Layout (infoPtr, &rcClient, TRUE, TRUE);
Eric Kohl's avatar
Eric Kohl committed
4530 4531 4532 4533

    return 0;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
4534

4535 4536 4537 4538 4539
static LRESULT
REBAR_StyleChanged (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
    STYLESTRUCT *ss = (STYLESTRUCT *)lParam;

4540
    TRACE("current style=%08x, styleOld=%08x, style being set to=%08x\n",
4541
	  infoPtr->dwStyle, ss->styleOld, ss->styleNew);
4542 4543 4544
    infoPtr->orgStyle = infoPtr->dwStyle = ss->styleNew;
    if (GetWindowTheme (infoPtr->hwndSelf))
        infoPtr->dwStyle &= ~WS_BORDER;
4545

4546 4547 4548
    return FALSE;
}

4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560
/* update theme after a WM_THEMECHANGED message */
static LRESULT theme_changed (REBAR_INFO* infoPtr)
{
    HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
    CloseThemeData (theme);
    theme = OpenThemeData (infoPtr->hwndSelf, themeClass);
    /* WS_BORDER disappears when theming is enabled and reappears when
     * disabled... */
    infoPtr->dwStyle &= ~WS_BORDER;
    infoPtr->dwStyle |= theme ? 0 : (infoPtr->orgStyle & WS_BORDER);
    return 0;
}
4561

4562 4563 4564 4565 4566 4567 4568 4569 4570 4571
static LRESULT
REBAR_WindowPosChanged (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
    WINDOWPOS *lpwp = (WINDOWPOS *)lParam;
    LRESULT ret;
    RECT rc;

    /* Save the new origin of this window - used by _ForceResize */
    infoPtr->origin.x = lpwp->x;
    infoPtr->origin.y = lpwp->y;
4572
    ret = DefWindowProcW(infoPtr->hwndSelf, WM_WINDOWPOSCHANGED,
4573 4574
			 wParam, lParam);
    GetWindowRect(infoPtr->hwndSelf, &rc);
4575
    TRACE("hwnd %p new pos (%d,%d)-(%d,%d)\n",
4576 4577 4578 4579 4580
	  infoPtr->hwndSelf, rc.left, rc.top, rc.right, rc.bottom);
    return ret;
}


4581
static LRESULT WINAPI
4582
REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4583
{
4584 4585
    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);

4586
    TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n",
4587
	  hwnd, uMsg, wParam, lParam);
4588
    if (!infoPtr && (uMsg != WM_NCCREATE))
4589
        return DefWindowProcW (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4590 4591
    switch (uMsg)
    {
4592
/*	case RB_BEGINDRAG: */
Alexandre Julliard's avatar
Alexandre Julliard committed
4593 4594

	case RB_DELETEBAND:
4595
	    return REBAR_DeleteBand (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4596

4597 4598
/*	case RB_DRAGMOVE: */
/*	case RB_ENDDRAG: */
4599 4600

	case RB_GETBANDBORDERS:
4601
	    return REBAR_GetBandBorders (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4602 4603

	case RB_GETBANDCOUNT:
4604
	    return REBAR_GetBandCount (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
4605

4606
	case RB_GETBANDINFO_OLD:
4607
	case RB_GETBANDINFOA:
4608
	    return REBAR_GetBandInfoA (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4609

4610
	case RB_GETBANDINFOW:
4611
	    return REBAR_GetBandInfoW (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4612 4613

	case RB_GETBARHEIGHT:
4614
	    return REBAR_GetBarHeight (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4615 4616

	case RB_GETBARINFO:
4617
	    return REBAR_GetBarInfo (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4618 4619

	case RB_GETBKCOLOR:
4620
	    return REBAR_GetBkColor (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
4621

4622 4623
/*	case RB_GETCOLORSCHEME: */
/*	case RB_GETDROPTARGET: */
Eric Kohl's avatar
Eric Kohl committed
4624 4625

	case RB_GETPALETTE:
4626
	    return REBAR_GetPalette (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4627 4628

	case RB_GETRECT:
4629
	    return REBAR_GetRect (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4630 4631

	case RB_GETROWCOUNT:
4632
	    return REBAR_GetRowCount (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
4633 4634

	case RB_GETROWHEIGHT:
4635
	    return REBAR_GetRowHeight (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4636 4637

	case RB_GETTEXTCOLOR:
4638
	    return REBAR_GetTextColor (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
4639

Eric Kohl's avatar
Eric Kohl committed
4640
	case RB_GETTOOLTIPS:
4641
	    return REBAR_GetToolTips (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
4642

Eric Kohl's avatar
Eric Kohl committed
4643
	case RB_GETUNICODEFORMAT:
4644
	    return REBAR_GetUnicodeFormat (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
4645

Eric Kohl's avatar
Eric Kohl committed
4646
	case CCM_GETVERSION:
4647
	    return REBAR_GetVersion (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
4648

Eric Kohl's avatar
Eric Kohl committed
4649
	case RB_HITTEST:
4650
	    return REBAR_HitTest (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4651 4652

	case RB_IDTOINDEX:
4653
	    return REBAR_IdToIndex (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4654

4655
	case RB_INSERTBANDA:
4656
	    return REBAR_InsertBandA (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4657

4658
	case RB_INSERTBANDW:
4659
	    return REBAR_InsertBandW (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4660

4661
	case RB_MAXIMIZEBAND:
4662
	    return REBAR_MaximizeBand (infoPtr, wParam, lParam);
4663 4664

	case RB_MINIMIZEBAND:
4665
	    return REBAR_MinimizeBand (infoPtr, wParam, lParam);
4666 4667

	case RB_MOVEBAND:
4668
	    return REBAR_MoveBand (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4669

Robert Shearman's avatar
Robert Shearman committed
4670 4671 4672
	case RB_PUSHCHEVRON:
	    return REBAR_PushChevron (infoPtr, wParam, lParam);

4673
	case RB_SETBANDINFOA:
4674
	    return REBAR_SetBandInfoA (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4675

4676
	case RB_SETBANDINFOW:
4677
	    return REBAR_SetBandInfoW (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4678 4679

	case RB_SETBARINFO:
4680
	    return REBAR_SetBarInfo (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4681 4682

	case RB_SETBKCOLOR:
4683
	    return REBAR_SetBkColor (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4684

4685 4686
/*	case RB_SETCOLORSCHEME: */
/*	case RB_SETPALETTE: */
4687
/*	    return REBAR_GetPalette (infoPtr, wParam, lParam); */
Eric Kohl's avatar
Eric Kohl committed
4688 4689

	case RB_SETPARENT:
4690
	    return REBAR_SetParent (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4691 4692

	case RB_SETTEXTCOLOR:
4693
	    return REBAR_SetTextColor (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4694

4695
/*	case RB_SETTOOLTIPS: */
Eric Kohl's avatar
Eric Kohl committed
4696 4697

	case RB_SETUNICODEFORMAT:
4698
	    return REBAR_SetUnicodeFormat (infoPtr, wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4699

Eric Kohl's avatar
Eric Kohl committed
4700
	case CCM_SETVERSION:
4701
	    return REBAR_SetVersion (infoPtr, (INT)wParam);
Eric Kohl's avatar
Eric Kohl committed
4702

Alexandre Julliard's avatar
Alexandre Julliard committed
4703
	case RB_SHOWBAND:
4704
	    return REBAR_ShowBand (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4705 4706

	case RB_SIZETORECT:
4707
	    return REBAR_SizeToRect (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4708 4709


4710
/*    Messages passed to parent */
4711
	case WM_COMMAND:
4712 4713
	case WM_DRAWITEM:
	case WM_NOTIFY:
4714
            return SendMessageW(REBAR_GetNotifyParent (infoPtr), uMsg, wParam, lParam);
4715

4716 4717 4718

/*      case WM_CHARTOITEM:     supported according to ControlSpy */

Alexandre Julliard's avatar
Alexandre Julliard committed
4719
	case WM_CREATE:
4720
	    return REBAR_Create (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4721

Alexandre Julliard's avatar
Alexandre Julliard committed
4722
	case WM_DESTROY:
4723
	    return REBAR_Destroy (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4724

4725
        case WM_ERASEBKGND:
4726
	    return REBAR_EraseBkGnd (infoPtr, wParam, lParam);
4727

Eric Kohl's avatar
Eric Kohl committed
4728
	case WM_GETFONT:
4729
	    return REBAR_GetFont (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4730

4731 4732
/*      case WM_LBUTTONDBLCLK:  supported according to ControlSpy */

4733
	case WM_LBUTTONDOWN:
4734
	    return REBAR_LButtonDown (infoPtr, wParam, lParam);
4735 4736

	case WM_LBUTTONUP:
4737
	    return REBAR_LButtonUp (infoPtr, wParam, lParam);
4738

4739 4740
/*      case WM_MEASUREITEM:    supported according to ControlSpy */

4741
	case WM_MOUSEMOVE:
4742
	    return REBAR_MouseMove (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4743

Robert Shearman's avatar
Robert Shearman committed
4744 4745 4746
	case WM_MOUSELEAVE:
	    return REBAR_MouseLeave (infoPtr, wParam, lParam);

Eric Kohl's avatar
Eric Kohl committed
4747
	case WM_NCCALCSIZE:
4748
	    return REBAR_NCCalcSize (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4749

4750 4751 4752 4753 4754
        case WM_NCCREATE:
	    return REBAR_NCCreate (hwnd, wParam, lParam);

        case WM_NCHITTEST:
	    return REBAR_NCHitTest (infoPtr, wParam, lParam);
4755

Eric Kohl's avatar
Eric Kohl committed
4756
	case WM_NCPAINT:
4757
	    return REBAR_NCPaint (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4758

4759 4760
        case WM_NOTIFYFORMAT:
	    return REBAR_NotifyFormat (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4761

4762
	case WM_PRINTCLIENT:
Alexandre Julliard's avatar
Alexandre Julliard committed
4763
	case WM_PAINT:
4764
	    return REBAR_Paint (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4765

4766 4767 4768 4769 4770
/*      case WM_PALETTECHANGED: supported according to ControlSpy */
/*      case WM_QUERYNEWPALETTE:supported according to ControlSpy */
/*      case WM_RBUTTONDOWN:    supported according to ControlSpy */
/*      case WM_RBUTTONUP:      supported according to ControlSpy */

Eric Kohl's avatar
Eric Kohl committed
4771
	case WM_SETCURSOR:
4772
	    return REBAR_SetCursor (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4773 4774

	case WM_SETFONT:
4775
	    return REBAR_SetFont (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4776

4777 4778
        case WM_SETREDRAW:
	    return REBAR_SetRedraw (infoPtr, wParam, lParam);
4779

Eric Kohl's avatar
Eric Kohl committed
4780
	case WM_SIZE:
4781
	    return REBAR_Size (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4782

4783 4784 4785
        case WM_STYLECHANGED:
	    return REBAR_StyleChanged (infoPtr, wParam, lParam);

4786 4787 4788
        case WM_THEMECHANGED:
            return theme_changed (infoPtr);

4789
/*      case WM_SYSCOLORCHANGE: supported according to ControlSpy */
4790
/*      "Applications that have brushes using the existing system colors
4791
         should delete those brushes and recreate them using the new
4792 4793
         system colors."  per MSDN                                */

4794
/*      case WM_VKEYTOITEM:     supported according to ControlSpy */
4795
/*	case WM_WININICHANGE: */
Alexandre Julliard's avatar
Alexandre Julliard committed
4796

4797 4798 4799
        case WM_WINDOWPOSCHANGED:
	    return REBAR_WindowPosChanged (infoPtr, wParam, lParam);

Alexandre Julliard's avatar
Alexandre Julliard committed
4800
	default:
4801
	    if ((uMsg >= WM_USER) && (uMsg < WM_APP))
4802
		ERR("unknown msg %04x wp=%08x lp=%08lx\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
4803
		     uMsg, wParam, lParam);
4804
	    return DefWindowProcW (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4805 4806 4807 4808
    }
}


Eric Kohl's avatar
Eric Kohl committed
4809
VOID
4810
REBAR_Register (void)
Alexandre Julliard's avatar
Alexandre Julliard committed
4811
{
4812
    WNDCLASSW wndClass;
Alexandre Julliard's avatar
Alexandre Julliard committed
4813

4814
    ZeroMemory (&wndClass, sizeof(WNDCLASSW));
Alexandre Julliard's avatar
Alexandre Julliard committed
4815
    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
4816
    wndClass.lpfnWndProc   = REBAR_WindowProc;
Alexandre Julliard's avatar
Alexandre Julliard committed
4817 4818
    wndClass.cbClsExtra    = 0;
    wndClass.cbWndExtra    = sizeof(REBAR_INFO *);
Alexandre Julliard's avatar
Alexandre Julliard committed
4819
    wndClass.hCursor       = 0;
4820
    wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
4821 4822 4823
#if GLATESTING
    wndClass.hbrBackground = CreateSolidBrush(RGB(0,128,0));
#endif
4824
    wndClass.lpszClassName = REBARCLASSNAMEW;
4825

4826
    RegisterClassW (&wndClass);
4827 4828 4829 4830

    mindragx = GetSystemMetrics (SM_CXDRAG);
    mindragy = GetSystemMetrics (SM_CYDRAG);

Alexandre Julliard's avatar
Alexandre Julliard committed
4831 4832
}

Eric Kohl's avatar
Eric Kohl committed
4833 4834

VOID
4835
REBAR_Unregister (void)
Eric Kohl's avatar
Eric Kohl committed
4836
{
4837
    UnregisterClassW (REBARCLASSNAMEW, NULL);
Eric Kohl's avatar
Eric Kohl committed
4838
}