rebar.c 142 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 18 19
 * 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
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
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 192 193
    BOOL     bUnicode;    /* TRUE if this window is W type */
    BOOL     NtfUnicode;  /* TRUE if parent wants notify in W format */
    BOOL     DoRedraw;    /* TRUE to acutally draw bands */
194
    UINT     fStatus;     /* Status flags (see below)  */
195 196 197 198 199
    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 */
200 201
    POINT    dragStart;   /* x,y of button down */
    POINT    dragNow;     /* x,y of this MouseMove */
Robert Shearman's avatar
Robert Shearman committed
202
    INT      iOldBand;    /* last band that had the mouse cursor over it */
203
    INT      ihitoffset;  /* offset of hotspot from gripper.left */
204
    POINT    origin;      /* left/upper corner of client */
Robert Shearman's avatar
Robert Shearman committed
205 206
    INT      ichevronhotBand; /* last band that had a hot chevron */
    INT      iGrabbedBand;/* band number of band whose gripper was grabbed */
207 208 209

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

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

/* ----   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
226
#define SEP_WIDTH       ((infoPtr->dwStyle & RBS_BANDBORDERS) ? SEP_WIDTH_SIZE : 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
227

228 229 230
/* 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
231

232 233 234 235 236 237 238
/* 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.                 */
239
#define GRIPPER_HEIGHT  16
240 241 242 243 244 245 246

/* 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
247

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

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

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

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

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

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

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

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

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

288

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

291 292 293 294 295 296

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

297
static const char *band_stylename[] = {
298 299 300 301 302 303 304 305 306 307 308
    "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 };

309
static const char *band_maskname[] = {
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
    "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];

327
static const WCHAR themeClass[] = { 'R','e','b','a','r',0 };
328 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

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

362

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

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

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

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

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

458
}
Alexandre Julliard's avatar
Alexandre Julliard committed
459

Robert Shearman's avatar
Robert Shearman committed
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
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 );
}
479 480 481

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

485 486
    parent = infoPtr->hwndNotify;
    if (!parent) {
487 488
        parent = GetParent (infoPtr->hwndSelf);
	owner = GetWindow (infoPtr->hwndSelf, GW_OWNER);
489 490
	if (owner) parent = owner;
    }
491 492 493 494 495 496 497 498 499 500 501 502
    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;
503 504
    nmhdr->code = code;

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

508 509 510 511 512 513
    if (infoPtr->NtfUnicode)
	return SendMessageW (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom,
			     (LPARAM)nmhdr);
    else
	return SendMessageA (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom,
			     (LPARAM)nmhdr);
514 515 516
}

static INT
517
REBAR_Notify_NMREBAR (REBAR_INFO *infoPtr, UINT uBand, UINT code)
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
{
    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;
539
    return REBAR_Notify ((NMHDR *)&notify_rebar, infoPtr, code);
540 541
}

Eric Kohl's avatar
Eric Kohl committed
542
static VOID
543
REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
Eric Kohl's avatar
Eric Kohl committed
544
{
545 546 547
    HFONT hOldFont = 0;
    INT oldBkMode = 0;
    NMCUSTOMDRAW nmcd;
548
    HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
Eric Kohl's avatar
Eric Kohl committed
549

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
    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
571 572 573

    /* draw gripper */
    if (lpBand->fDraw & DRAW_GRIPPER)
574 575 576 577 578 579 580 581 582 583 584 585 586
    {
        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
587 588

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

592
	/* center image */
Eric Kohl's avatar
Eric Kohl committed
593 594 595
	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
596
	ImageList_Draw (infoPtr->himl, lpBand->iImage, hdc,
Eric Kohl's avatar
Eric Kohl committed
597
			pt.x, pt.y,
Eric Kohl's avatar
Eric Kohl committed
598
			ILD_TRANSPARENT);
Eric Kohl's avatar
Eric Kohl committed
599
    }
Eric Kohl's avatar
Eric Kohl committed
600 601 602

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

Robert Shearman's avatar
Robert Shearman committed
621 622
    if (!IsRectEmpty(&lpBand->rcChevron))
    {
623
        if (theme)
Robert Shearman's avatar
Robert Shearman committed
624
        {
625 626 627 628 629 630 631 632
            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
633
        }
634
        else
Robert Shearman's avatar
Robert Shearman committed
635
        {
636 637 638 639 640 641 642 643 644 645 646 647
            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
648 649 650
        }
    }

651 652 653 654 655 656 657 658 659 660 661
    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
662
}
Alexandre Julliard's avatar
Alexandre Julliard committed
663 664 665


static VOID
666
REBAR_Refresh (REBAR_INFO *infoPtr, HDC hdc)
Alexandre Julliard's avatar
Alexandre Julliard committed
667
{
Eric Kohl's avatar
Eric Kohl committed
668
    REBAR_BAND *lpBand;
669
    UINT i;
Eric Kohl's avatar
Eric Kohl committed
670

671 672
    if (!infoPtr->DoRedraw) return;

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

676
	if (HIDDENBAND(lpBand)) continue;
Eric Kohl's avatar
Eric Kohl committed
677

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

    }
}

686

687
static void
688
REBAR_FixVert (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend,
689
		   INT mcy)
690
     /* Function:                                                    */
691 692 693 694 695
     /*   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
696
{
697
    REBAR_BAND *lpBand;
698
    INT i;
699

700
    for (i = (INT)rowstart; i<=(INT)rowend; i++) {
701 702
        lpBand = &infoPtr->bands[i];
	if (HIDDENBAND(lpBand)) continue;
703

704
	/* adjust height of bands in row to "mcy" value */
705
	if (infoPtr->dwStyle & CCS_VERT) {
706
	    if (lpBand->rcBand.right != lpBand->rcBand.left + mcy)
707 708 709
	        lpBand->rcBand.right = lpBand->rcBand.left + mcy;
	}
	else {
710
	    if (lpBand->rcBand.bottom != lpBand->rcBand.top + mcy)
711
	        lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
712

713 714
	}

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


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

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

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

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

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

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

	/* compute new width */
865
	if (extra) {
866 867
	    curwidth += extra;
	    extra = 0;
868
	}
869 870

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

    /* *******************  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;
901 902
}

903

904
static void
905
REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
906 907 908 909 910 911 912
     /* 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;
913
    RECT oldChild, work;
914 915

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

918
    for(i=rstart; i<rend; i++){
919
      lpBand = &infoPtr->bands[i];
920 921 922 923 924 925 926
      if (HIDDENBAND(lpBand)) {
          SetRect (&lpBand->rcChild,
		   lpBand->rcBand.right, lpBand->rcBand.top,
		   lpBand->rcBand.right, lpBand->rcBand.bottom);
	  continue;
      }

927 928 929 930
      oldChild = lpBand->rcChild;

      /* set initial gripper rectangle */
      SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
931
	       lpBand->rcBand.left, lpBand->rcBand.bottom);
932 933

      /* calculate gripper rectangle */
934 935 936 937 938 939 940 941 942 943
      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);
944
      }
945 946 947 948 949
      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;
950
	  SetRect (&lpBand->rcCapImage,
951 952
		   lpBand->rcBand.left+xoff, lpBand->rcBand.top,
		   lpBand->rcBand.left+xoff, lpBand->rcBand.bottom);
953 954 955
      }

      /* image is visible */
956 957 958 959 960 961 962 963 964
      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);
965
	  /* update band height
966 967 968 969 970 971 972 973 974
	  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);
975
      }
Eric Kohl's avatar
Eric Kohl committed
976

977
      /* text is visible */
978
      if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
979
	  lpBand->fDraw |= DRAW_TEXT;
980
	  lpBand->rcCapText.right = max(lpBand->rcCapText.left,
981
					lpBand->rcCapText.right-REBAR_POST_TEXT);
982
      }
Eric Kohl's avatar
Eric Kohl committed
983

984 985
      /* set initial child window rectangle if there is a child */
      if (lpBand->fMask & RBBIM_CHILD) {
986 987 988 989 990
	  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
991 992 993 994 995 996 997
	  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);
	  }
998 999
      }
      else {
1000 1001 1002
          SetRect (&lpBand->rcChild,
		   lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top,
		   lpBand->rcBand.right, lpBand->rcBand.bottom);
1003 1004
      }

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

    }

}

1033 1034

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

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

1048
    for(i=rstart; i<rend; i++){
1049 1050 1051
	lpBand = &infoPtr->bands[i];
	if (HIDDENBAND(lpBand)) continue;
	oldChild = lpBand->rcChild;
1052

1053 1054 1055
	/* set initial gripper rectangle */
	SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
		 lpBand->rcBand.right, lpBand->rcBand.top);
1056

1057 1058 1059 1060
	/* calculate gripper rectangle */
	if (lpBand->fStatus & HAS_GRIPPER) {
	    lpBand->fDraw |= DRAW_GRIPPER;

1061
	    if (infoPtr->dwStyle & RBS_VERTICALGRIPPER) {
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
		/*  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  */
1076 1077
		lpBand->rcGripper.left   += 2;
		lpBand->rcGripper.right  -= 2;
1078 1079 1080 1081 1082 1083 1084 1085 1086
		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);
	    }
1087
	}
1088 1089 1090 1091 1092
	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;
1093
	    /* initialize Caption image rectangle  */
1094
	    SetRect (&lpBand->rcCapImage,
1095 1096
		     lpBand->rcBand.left, lpBand->rcBand.top+xoff,
		     lpBand->rcBand.right, lpBand->rcBand.top+xoff);
1097 1098
	}

1099 1100 1101 1102 1103 1104 1105 1106
	/* 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 */
1107
	    SetRect (&lpBand->rcCapText,
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
		     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 */
1118
	    SetRect (&lpBand->rcCapText,
1119 1120
		     lpBand->rcBand.left, lpBand->rcCapImage.bottom,
		     lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
1121 1122
	}

1123
	/* text is visible */
1124
	if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
1125 1126
	    lpBand->fDraw |= DRAW_TEXT;
	    lpBand->rcCapText.bottom = max(lpBand->rcCapText.top,
1127
					   lpBand->rcCapText.bottom);
1128
	}
1129

1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
	/* 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);
	}
1143

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

1168 1169 1170 1171
    }
}


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

    GetClientRect (infoPtr->hwndSelf, &rc);

1184
    TRACE( " old [%ld x %ld], new [%ld x %ld], client [%ld x %ld]\n",
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
	   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;

1207 1208 1209 1210
    width = 0;
    height = 0;
    x = 0;
    y = 0;
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 1258 1259 1260 1261 1262
    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;
1263 1264
	x = infoPtr->origin.x;
	y = infoPtr->origin.y;
1265 1266
    }

1267
    TRACE("hwnd %p, style=%08lx, setting at (%d,%d) for (%d,%d)\n",
1268 1269 1270 1271
	infoPtr->hwndSelf, infoPtr->dwStyle,
	x, y, width, height);
    SetWindowPos (infoPtr->hwndSelf, 0, x, y, width, height,
		    SWP_NOZORDER);
1272
    infoPtr->fStatus &= ~AUTO_RESIZE;
1273 1274 1275 1276 1277 1278
}


static VOID
REBAR_MoveChildWindows (REBAR_INFO *infoPtr, UINT start, UINT endplus)
{
1279
    static const WCHAR strComboBox[] = { 'C','o','m','b','o','B','o','x',0 };
1280
    REBAR_BAND *lpBand;
1281
    WCHAR szClassName[40];
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
    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) {
1295
	    TRACE("hwndChild = %p\n", lpBand->hwndChild);
1296

1297 1298 1299 1300 1301 1302
	    /* 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;
1303
	    if (infoPtr->dwStyle & CCS_VERT)
1304 1305 1306
		rbcz.rcBand.top += lpBand->cxHeader;
	    else
		rbcz.rcBand.left += lpBand->cxHeader;
1307 1308 1309
	    REBAR_Notify ((NMHDR *)&rbcz, infoPtr, RBN_CHILDSIZE);
	    if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) {
		TRACE("Child rect changed by NOTIFY for band %u\n", i);
1310
		TRACE("    from (%ld,%ld)-(%ld,%ld)  to (%ld,%ld)-(%ld,%ld)\n",
1311 1312 1313 1314
		      lpBand->rcChild.left, lpBand->rcChild.top,
		      lpBand->rcChild.right, lpBand->rcChild.bottom,
		      rbcz.rcChild.left, rbcz.rcChild.top,
		      rbcz.rcChild.right, rbcz.rcChild.bottom);
1315
		lpBand->rcChild = rbcz.rcChild;  /* *** ??? */
1316 1317
	    }

1318 1319 1320 1321 1322 1323 1324 1325
	    /* 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
	     */

1326 1327 1328
	    GetClassNameW (lpBand->hwndChild, szClassName, sizeof(szClassName)/sizeof(szClassName[0]));
	    if (!lstrcmpW (szClassName, strComboBox) ||
		!lstrcmpW (szClassName, WC_COMBOBOXEXW)) {
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340
		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 */
1341
		TRACE("moving child (Combo(Ex)) %p to (%ld,%d) for (%ld,%d)\n",
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
		      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 {
1356
		TRACE("moving child (Other) %p to (%ld,%ld) for (%ld,%ld)\n",
1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373
		      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");
1374

1375 1376
    if (infoPtr->DoRedraw)
	UpdateWindow (infoPtr->hwndSelf);
1377

1378 1379
    if (infoPtr->fStatus & NTF_HGHTCHG) {
        infoPtr->fStatus &= ~NTF_HGHTCHG;
1380 1381 1382 1383 1384 1385
        /*
         * 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);
1386
        REBAR_Notify (&heightchange, infoPtr, RBN_HEIGHTCHANGE);
1387
    }
1388 1389 1390 1391 1392 1393 1394 1395 1396

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

1397 1398 1399 1400 1401
}


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

1413 1414 1415 1416 1417 1418
    if (!(infoPtr->fStatus & BAND_NEEDS_LAYOUT)) {
	TRACE("no layout done. No band changed.\n");
	REBAR_DumpBand (infoPtr);
	return;
    }
    infoPtr->fStatus &= ~BAND_NEEDS_LAYOUT;
1419
    if (!infoPtr->DoRedraw) infoPtr->fStatus |= BAND_NEEDS_REDRAW;
1420 1421

    GetClientRect (infoPtr->hwndSelf, &rcClient);
1422
    TRACE("Client is (%ld,%ld)-(%ld,%ld)\n",
1423
	  rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
Eric Kohl's avatar
Eric Kohl committed
1424

1425 1426
    if (lpRect) {
	rcAdj = *lpRect;
1427
	TRACE("adjustment rect is (%ld,%ld)-(%ld,%ld)\n",
1428
	      rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom);
1429 1430
    }
    else {
1431
        CopyRect (&rcAdj, &rcClient);
1432
    }
Eric Kohl's avatar
Eric Kohl committed
1433

1434 1435 1436 1437 1438
    clientcx = rcClient.right - rcClient.left;
    clientcy = rcClient.bottom - rcClient.top;
    adjcx = rcAdj.right - rcAdj.left;
    adjcy = rcAdj.bottom - rcAdj.top;
    if (resetclient) {
1439 1440 1441
        TRACE("window client rect will be set to adj rect\n");
        clientcx = adjcx;
        clientcy = adjcy;
1442
    }
1443

1444 1445 1446 1447 1448 1449
    if (!infoPtr->DoRedraw && (clientcx == 0) && (clientcy == 0)) {
	ERR("no redraw and client is zero, skip layout\n");
	infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
	return;
    }

1450
    /* save height of original control */
1451
    if (infoPtr->dwStyle & CCS_VERT)
1452 1453 1454
        origheight = infoPtr->calcSize.cx;
    else
        origheight = infoPtr->calcSize.cy;
1455
    origrows = infoPtr->uNumRows;
1456

1457 1458 1459
    initx = 0;
    inity = 0;

1460 1461
    /* ******* Start Phase 1 - all bands on row at minimum size ******* */

1462 1463 1464 1465
    TRACE("band loop constants, clientcx=%d, clientcy=%d, adjcx=%d, adjcy=%d\n",
	  clientcx, clientcy, adjcx, adjcy);
    x = initx;
    y = inity;
1466
    row = 0;
1467 1468
    cx = 0;
    mcy = 0;
1469
    rowstart = 0;
1470
    prevBand = NULL;
1471
    cntonrow = 0;
1472

Eric Kohl's avatar
Eric Kohl committed
1473 1474
    for (i = 0; i < infoPtr->uNumBands; i++) {
	lpBand = &infoPtr->bands[i];
1475 1476
	lpBand->fDraw = 0;
	lpBand->iRow = row;
Eric Kohl's avatar
Eric Kohl committed
1477

Robert Shearman's avatar
Robert Shearman committed
1478 1479
	SetRectEmpty(&lpBand->rcChevron);

1480
	if (HIDDENBAND(lpBand)) continue;
Eric Kohl's avatar
Eric Kohl committed
1481

1482
	lpBand->rcoldBand = lpBand->rcBand;
1483

1484 1485 1486
	/* Set the offset of the child window */
	if ((lpBand->fMask & RBBIM_CHILD) &&
	    !(lpBand->fStyle & RBBS_FIXEDSIZE)) {
1487
	    lpBand->offChild.cx = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 4 : 0);
1488 1489 1490
	}
	lpBand->offChild.cy = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 2 : 0);

1491
	/* separator from previous band */
1492
	cxsep = (cntonrow == 0) ? 0 : SEP_WIDTH;
1493
	cx = lpBand->lcx;
1494

1495
        /* In native, 0 as one of the coordinates means no limit */
1496
	if (infoPtr->dwStyle & CCS_VERT)
1497
	    dobreak = (adjcy && (y + cx + cxsep > adjcy));
1498
        else
1499
	    dobreak = (adjcx && (x + cx + cxsep > adjcx));
1500

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

	    for (j = rowstart; j < i; j++) {
		REBAR_BAND *lpB;
		lpB = &infoPtr->bands[j];
1508
		if (infoPtr->dwStyle & CCS_VERT) {
1509 1510 1511 1512 1513 1514 1515
		    lpB->rcBand.right  = lpB->rcBand.left + mcy;
		}
		else {
		    lpB->rcBand.bottom = lpB->rcBand.top + mcy;
		}
	    }

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

1526 1527 1528 1529 1530
	    mcy = 0;
	    cxsep = 0;
	    row++;
	    lpBand->iRow = row;
	    prevBand = NULL;
1531
	    rowstart = i;
1532
	    cntonrow = 0;
1533
	}
1534

1535
	if (mcy < lpBand->lcy + REBARSPACE(lpBand))
1536
	    mcy = lpBand->lcy + REBARSPACE(lpBand);
1537 1538 1539

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

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

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

1592
    if (infoPtr->dwStyle & CCS_VERT)
1593 1594 1595 1596
        x += mcy;
    else
        y += mcy;

1597 1598
    for (j = rowstart; j < infoPtr->uNumBands; j++) {
	lpBand = &infoPtr->bands[j];
1599
	if (infoPtr->dwStyle & CCS_VERT) {
1600 1601 1602 1603 1604 1605 1606
	    lpBand->rcBand.right  = lpBand->rcBand.left + mcy;
	}
	else {
	    lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
	}
    }

1607
    if (infoPtr->uNumBands)
1608
        infoPtr->uNumRows = row + 1;
1609 1610 1611 1612

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


1613 1614 1615
    /* ******* Start Phase 1a - Adjust heights for RBS_VARHEIGHT off ******* */

    mmcy = 0;
1616
    if (!(infoPtr->dwStyle & RBS_VARHEIGHT)) {
1617 1618 1619 1620 1621 1622
	INT xy;

	/* get the max height of all bands */
	for (i=0; i<infoPtr->uNumBands; i++) {
	    lpBand = &infoPtr->bands[i];
	    if (HIDDENBAND(lpBand)) continue;
1623
	    if (infoPtr->dwStyle & CCS_VERT)
1624 1625 1626 1627 1628 1629 1630
		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;
1631
	row = 0;
1632 1633 1634 1635 1636
	for (i=0; i<infoPtr->uNumBands; i++) {
	    lpBand = &infoPtr->bands[i];
	    if (HIDDENBAND(lpBand)) continue;
	    if (lpBand->iRow != row)
		xy += (mmcy + SEP_WIDTH);
1637
	    if (infoPtr->dwStyle & CCS_VERT) {
1638 1639 1640 1641 1642 1643 1644 1645 1646 1647
		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 */
1648
	if (infoPtr->dwStyle & CCS_VERT)
1649 1650 1651 1652 1653 1654 1655 1656
	    x = xy + mmcy;
	else
	    y = xy + mmcy;
    }

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


1657
    /* ******* Start Phase 2 - split rows till adjustment height full ******* */
1658

1659
    /* assumes that the following variables contain:                 */
1660 1661 1662
    /*   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)) {
1663
        INT i, prev_rh, new_rh, adj_rh, prev_idx, current_idx;
1664
	REBAR_BAND *prev, *current, *walk;
1665
	UINT j;
1666

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

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

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


1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782
    /* ******* 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 ******* */
1783 1784 1785


    /* ******* Start Phase 2b - adjust all bands for height full ******* */
1786 1787 1788 1789 1790 1791
    /* 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) {
1792
	INT diff, i;
1793
	UINT j;
1794 1795

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

        /* iterate backwards thru the rows */
1798
        for (i = infoPtr->uNumBands-1; i>=0; i--) {
1799
	    lpBand = &infoPtr->bands[i];
1800
	    if(HIDDENBAND(lpBand)) continue;
1801 1802

	    /* if row has more than 1 band, ignore it */
1803
            if( !(lpBand->fDraw&DRAW_FIRST_IN_ROW) )
1804
                continue;
1805
            if( !(lpBand->fDraw&DRAW_LAST_IN_ROW) )
1806 1807
                continue;

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

1843
    /* ******* End Phase 2b - adjust all bands for height full ******* */
1844 1845


1846 1847
    /* ******* Start Phase 3 - adjust all bands for width full ******* */

1848
    if (infoPtr->uNumBands) {
1849
        int startband;
1850

1851
	/* If RBS_BANDBORDERS set then indicate to draw bottom separator */
1852
	/* on all bands in all rows but last row.                        */
1853 1854
	/* Also indicate to draw the right separator for each band in    */
	/* each row but the rightmost band.                              */
1855
	if (infoPtr->dwStyle & RBS_BANDBORDERS) {
1856

1857 1858 1859 1860 1861 1862
            for (i=0; i<infoPtr->uNumBands; i++) {
	        lpBand = &infoPtr->bands[i];
		if (HIDDENBAND(lpBand))
                    continue;

                /* not righthand bands */
1863
                if( !(lpBand->fDraw & DRAW_LAST_IN_ROW) )
1864 1865 1866
		    lpBand->fDraw |= DRAW_RIGHTSEP;

                /* not the last row */
1867
                if( lpBand->iRow != infoPtr->uNumRows )
1868
		    lpBand->fDraw |= DRAW_BOTTOMSEP;
1869 1870
	    }
	}
1871

1872 1873
	/* Distribute the extra space on the horizontal and adjust  */
	/* all bands in row to same height.                         */
1874
	mcy = 0;
1875
        startband = -1;
1876 1877 1878
        for (i=0; i<infoPtr->uNumBands; i++) {

            lpBand = &infoPtr->bands[i];
1879 1880 1881 1882 1883 1884 1885 1886

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

            if ( (mcy < ircBw(lpBand)) && !HIDDENBAND(lpBand) )
1887 1888
                mcy = ircBw(lpBand);

1889
            if( lpBand->fDraw & DRAW_LAST_IN_ROW )
1890 1891
            {
	        TRACE("P3 processing row %d, starting band %d, ending band %d\n",
1892 1893 1894
		      lpBand->iRow, startband, i);
                if( startband < 0 )
                    ERR("Last band %d with no first, row %d\n", i, lpBand->iRow);
1895 1896

	        REBAR_AdjustBands (infoPtr, startband, i,
1897
			       (infoPtr->dwStyle & CCS_VERT) ?
1898
			       clientcy : clientcx, mcy);
1899
            }
1900 1901 1902
	}

	/* Calculate the other rectangles in each band */
1903
	if (infoPtr->dwStyle & CCS_VERT) {
1904
	    REBAR_CalcVertBand (infoPtr, 0, infoPtr->uNumBands,
1905
				notify);
1906 1907
	}
	else {
1908
	    REBAR_CalcHorzBand (infoPtr, 0, infoPtr->uNumBands,
1909
				notify);
1910
	}
1911 1912
    }

1913 1914
    /* ******* End Phase 3 - adjust all bands for width full ******* */

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

1941
    REBAR_DumpBand (infoPtr);
1942

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

1945
    REBAR_ForceResize (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
1946 1947 1948 1949
}


static VOID
1950
REBAR_ValidateBand (REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
1951 1952 1953 1954 1955
     /* 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;
1956
    UINT textheight=0;
1957
    UINT i, nonfixed;
1958
    REBAR_BAND *tBand;
1959

1960
    lpBand->fStatus = 0;
1961 1962
    lpBand->lcx = 0;
    lpBand->lcy = 0;
1963 1964
    lpBand->ccx = 0;
    lpBand->ccy = 0;
1965 1966 1967
    lpBand->hcx = 0;
    lpBand->hcy = 0;

1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986
    /* Data comming in from users into the cx... and cy... fields  */
    /* 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     */
    /* address. Here I will use the algorithim that if the value   */
    /* is greater than 65535 then it is bad and replace it with    */
    /* a zero. Feel free to improve the algorithim.  -  GA 12/2000 */
    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;

1987 1988 1989 1990 1991
    /* 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;

1992
    /* Header is where the image, text and gripper exist  */
1993
    /* in the band and precede the child window.          */
1994

1995 1996 1997 1998 1999 2000 2001 2002
    /* 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++;
    }

2003
    /* calculate gripper rectangle */
2004
    if (  (!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
2005
	  ( (lpBand->fStyle & RBBS_GRIPPERALWAYS) ||
2006
	    ( !(lpBand->fStyle & RBBS_FIXEDSIZE) && (nonfixed > 1)))
2007 2008
       ) {
	lpBand->fStatus |= HAS_GRIPPER;
2009 2010
        if (infoPtr->dwStyle & CCS_VERT)
	    if (infoPtr->dwStyle & RBS_VERTICALGRIPPER)
2011 2012 2013 2014 2015 2016 2017
                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;
2018 2019 2020 2021
    }

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

    /* text is visible */
2034 2035
    if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText) &&
        !(lpBand->fStyle & RBBS_HIDETITLE)) {
2036 2037 2038 2039
	HDC hdc = GetDC (0);
	HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
	SIZE size;

2040
	lpBand->fStatus |= HAS_TEXT;
2041 2042
	GetTextExtentPoint32W (hdc, lpBand->lpText,
			       lstrlenW (lpBand->lpText), &size);
2043 2044
	header += ((infoPtr->dwStyle & CCS_VERT) ? (size.cy + REBAR_POST_TEXT) : (size.cx + REBAR_POST_TEXT));
	textheight = (infoPtr->dwStyle & CCS_VERT) ? 0 : size.cy;
2045 2046 2047 2048 2049

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

2050 2051 2052 2053 2054 2055
    /* 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;
    }

2056 2057 2058 2059 2060 2061
    /* check if user overrode the header value */
    if (!(lpBand->fMask & RBBIM_HEADERSIZE))
        lpBand->cxHeader = header;


    /* Now compute minimum size of child window */
2062 2063
    lpBand->offChild.cx = 0;
    lpBand->offChild.cy = 0;
2064
    lpBand->lcy = textheight;
2065
    lpBand->ccy = lpBand->lcy;
2066 2067
    if (lpBand->fMask & RBBIM_CHILDSIZE) {
        lpBand->lcx = lpBand->cxMinChild;
2068 2069

	/* Set the .cy values for CHILDSIZE case */
2070
        lpBand->lcy = max(lpBand->lcy, lpBand->cyMinChild);
2071
	lpBand->ccy = lpBand->lcy;
2072
        lpBand->hcy = lpBand->lcy;
2073
        if (lpBand->cyMaxChild != 0xffffffff) {
2074 2075
	    lpBand->hcy = lpBand->cyMaxChild;
        }
2076 2077 2078
	if (lpBand->cyChild != 0xffffffff)
	    lpBand->ccy = max (lpBand->cyChild, lpBand->lcy);

2079 2080 2081
        TRACE("_CHILDSIZE\n");
    }
    if (lpBand->fMask & RBBIM_SIZE) {
2082
        lpBand->hcx = max (lpBand->cx-lpBand->cxHeader, lpBand->lcx);
2083 2084 2085 2086
        TRACE("_SIZE\n");
    }
    else
        lpBand->hcx = lpBand->lcx;
2087 2088 2089 2090 2091 2092
    lpBand->ccx = lpBand->hcx;

    /* make ->.cx include header size for _Layout */
    lpBand->lcx += lpBand->cxHeader;
    lpBand->ccx += lpBand->cxHeader;
    lpBand->hcx += lpBand->cxHeader;
2093 2094 2095

}

2096
static BOOL
2097 2098 2099
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.      */
2100
     /*  It returns true if something changed and false if not.   */
2101
{
2102 2103
    BOOL bChanged = FALSE;

2104 2105
    lpBand->fMask |= lprbbi->fMask;

2106 2107 2108
    if( (lprbbi->fMask & RBBIM_STYLE) &&
        (lpBand->fStyle != lprbbi->fStyle ) )
    {
2109
	lpBand->fStyle = lprbbi->fStyle;
2110 2111
        bChanged = TRUE;
    }
2112

2113 2114 2115 2116
    if( (lprbbi->fMask & RBBIM_COLORS) &&
       ( ( lpBand->clrFore != lprbbi->clrFore ) ||
         ( lpBand->clrBack != lprbbi->clrBack ) ) )
    {
2117 2118
	lpBand->clrFore = lprbbi->clrFore;
	lpBand->clrBack = lprbbi->clrBack;
2119
        bChanged = TRUE;
2120 2121
    }

2122 2123 2124
    if( (lprbbi->fMask & RBBIM_IMAGE) &&
       ( lpBand->iImage != lprbbi->iImage ) )
    {
2125
	lpBand->iImage = lprbbi->iImage;
2126 2127
        bChanged = TRUE;
    }
2128

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

2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160
    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 ) ) ) ) )
    {
2161 2162
	lpBand->cxMinChild = lprbbi->cxMinChild;
	lpBand->cyMinChild = lprbbi->cyMinChild;
2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173
	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;
	}
2174
        bChanged = TRUE;
2175 2176
    }

2177 2178 2179
    if( (lprbbi->fMask & RBBIM_SIZE) &&
        (lpBand->cx != lprbbi->cx ) )
    {
2180
	lpBand->cx = lprbbi->cx;
2181 2182
        bChanged = TRUE;
    }
2183

2184 2185 2186
    if( (lprbbi->fMask & RBBIM_BACKGROUND) &&
       ( lpBand->hbmBack != lprbbi->hbmBack ) )
    {
2187
	lpBand->hbmBack = lprbbi->hbmBack;
2188 2189
        bChanged = TRUE;
    }
2190

2191 2192 2193
    if( (lprbbi->fMask & RBBIM_ID) &&
        (lpBand->wID != lprbbi->wID ) )
    {
2194
	lpBand->wID = lprbbi->wID;
2195 2196
        bChanged = TRUE;
    }
2197 2198 2199

    /* check for additional data */
    if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
2200 2201 2202
	if( (lprbbi->fMask & RBBIM_IDEALSIZE) &&
            ( lpBand->cxIdeal != lprbbi->cxIdeal ) )
        {
2203
	    lpBand->cxIdeal = lprbbi->cxIdeal;
2204 2205
            bChanged = TRUE;
        }
2206

2207 2208 2209
	if( (lprbbi->fMask & RBBIM_LPARAM) &&
            (lpBand->lParam != lprbbi->lParam ) )
        {
2210
	    lpBand->lParam = lprbbi->lParam;
2211 2212
            bChanged = TRUE;
        }
2213

2214 2215 2216
	if( (lprbbi->fMask & RBBIM_HEADERSIZE) &&
            (lpBand->cxHeader != lprbbi->cxHeader ) )
        {
2217
	    lpBand->cxHeader = lprbbi->cxHeader;
2218 2219
            bChanged = TRUE;
        }
2220
    }
2221 2222

    return bChanged;
2223 2224
}

2225
static LRESULT
2226
REBAR_InternalEraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, RECT *clip)
2227 2228 2229 2230
     /* 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.    */
2231 2232
{
    REBAR_BAND *lpBand;
2233 2234
    UINT i;
    INT oldrow;
2235
    HDC hdc = (HDC)wParam;
2236
    RECT rect, cr;
Guy Albertelli's avatar
Guy Albertelli committed
2237
    COLORREF old = CLR_NONE, new;
2238 2239 2240
    HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);

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

2242
    oldrow = -1;
2243 2244
    for(i=0; i<infoPtr->uNumBands; i++) {
        lpBand = &infoPtr->bands[i];
2245
	if (HIDDENBAND(lpBand)) continue;
2246 2247 2248 2249 2250 2251 2252

	/* draw band separator between rows */
	if (lpBand->iRow != oldrow) {
	    oldrow = lpBand->iRow;
	    if (lpBand->fDraw & DRAW_BOTTOMSEP) {
		RECT rcRowSep;
		rcRowSep = lpBand->rcBand;
2253
		if (infoPtr->dwStyle & CCS_VERT) {
2254 2255
		    rcRowSep.right += SEP_WIDTH_SIZE;
		    rcRowSep.bottom = infoPtr->calcSize.cy;
2256 2257 2258 2259
                    if (theme)
                        DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcRowSep, EDGE_ETCHED, BF_RIGHT, NULL);
                    else
		        DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_RIGHT);
2260 2261 2262 2263
		}
		else {
		    rcRowSep.bottom += SEP_WIDTH_SIZE;
		    rcRowSep.right = infoPtr->calcSize.cx;
2264 2265 2266 2267
                    if (theme)
                        DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcRowSep, EDGE_ETCHED, BF_BOTTOM, NULL);
                    else
		        DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_BOTTOM);
2268
		}
2269
		TRACE ("drawing band separator bottom (%ld,%ld)-(%ld,%ld)\n",
2270 2271 2272 2273 2274 2275 2276 2277 2278
		       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;
2279
	    if (infoPtr->dwStyle & CCS_VERT) {
2280
		rcSep.bottom += SEP_WIDTH_SIZE;
2281 2282 2283 2284
                if (theme)
                    DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_BOTTOM, NULL);
                else
		    DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOM);
2285 2286 2287
	    }
	    else {
		rcSep.right += SEP_WIDTH_SIZE;
2288 2289 2290 2291
                if (theme)
                    DrawThemeEdge (theme, hdc, RP_BAND, 0, &rcSep, EDGE_ETCHED, BF_RIGHT, NULL);
                else
		    DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_RIGHT);
2292
	    }
2293
	    TRACE("drawing band separator right (%ld,%ld)-(%ld,%ld)\n",
2294
		  rcSep.left, rcSep.top, rcSep.right, rcSep.bottom);
2295
	}
2296 2297

	/* draw the actual background */
Guy Albertelli's avatar
Guy Albertelli committed
2298 2299 2300
	if (lpBand->clrBack != CLR_NONE) {
	    new = (lpBand->clrBack == CLR_DEFAULT) ? infoPtr->clrBtnFace :
		    lpBand->clrBack;
2301
#if GLATESTING
Guy Albertelli's avatar
Guy Albertelli committed
2302 2303
	    /* testing only - make background green to see it */
	    new = RGB(0,128,0);
2304
#endif
Guy Albertelli's avatar
Guy Albertelli committed
2305
	}
2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316
	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
2317 2318

	rect = lpBand->rcBand;
2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340

        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);
            TRACE("%s background color=0x%06lx, band (%ld,%ld)-(%ld,%ld), clip (%ld,%ld)-(%ld,%ld)\n",
                  (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);
        }
2341 2342 2343 2344
    }
    return TRUE;
}

Eric Kohl's avatar
Eric Kohl committed
2345
static void
Robert Shearman's avatar
Robert Shearman committed
2346
REBAR_InternalHitTest (REBAR_INFO *infoPtr, const LPPOINT lpPt, UINT *pFlags, INT *pBand)
Eric Kohl's avatar
Eric Kohl committed
2347 2348
{
    REBAR_BAND *lpBand;
2349
    RECT rect;
2350
    UINT  iCount;
Alexandre Julliard's avatar
Alexandre Julliard committed
2351

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

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

Eric Kohl's avatar
Eric Kohl committed
2405 2406 2407 2408
	    *pFlags = RBHT_NOWHERE;
	    if (pBand)
		*pBand = -1;

2409
	    TRACE("NOWHERE\n");
Eric Kohl's avatar
Eric Kohl committed
2410 2411 2412 2413 2414 2415 2416
	    return;
	}
    }
    else {
	*pFlags = RBHT_NOWHERE;
	if (pBand)
	    *pBand = -1;
2417
	TRACE("NOWHERE\n");
Eric Kohl's avatar
Eric Kohl committed
2418 2419 2420
	return;
    }
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2421

2422 2423

static INT
2424
REBAR_Shrink (REBAR_INFO *infoPtr, REBAR_BAND *band, INT movement, INT i)
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436
     /* 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.                      */

2437
    avail = rcBw(band) - band->lcx;
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 2471 2472 2473 2474 2475

    /* 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 */
2476
    if (rcBlt(band) + Leadjust < 0) {
2477 2478 2479 2480 2481 2482 2483
        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);

2484
    TRACE("band %d:  left=%d, right=%d, move=%d, rtn=%d, rcBand=(%ld,%ld)-(%ld,%ld)\n",
2485 2486 2487 2488 2489 2490 2491 2492
	  i, Leadjust, Readjust, movement, ret,
	  band->rcBand.left, band->rcBand.top,
	  band->rcBand.right, band->rcBand.bottom);
    return ret;
}


static void
2493
REBAR_HandleLRDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
2494 2495 2496 2497 2498 2499 2500
     /* 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.                        ****  */
{
2501
    REBAR_BAND *hitBand, *band, *mindBand, *maxdBand;
2502
    RECT newrect;
2503
    INT imindBand = -1, imaxdBand, ihitBand, i, movement;
2504 2505 2506 2507 2508 2509
    INT RHeaderSum = 0, LHeaderSum = 0;
    INT compress;

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

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

Robert Shearman's avatar
Robert Shearman committed
2522
    ihitBand = infoPtr->iGrabbedBand;
2523 2524 2525 2526 2527 2528
    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];
2529
	if (HIDDENBAND(band)) continue;
2530 2531 2532 2533 2534
	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 */
2535
	    /* one to separate each band.                                  */
2536
	    if (i < ihitBand)
2537
	        LHeaderSum += (band->lcx + SEP_WIDTH);
2538
	    else
2539
	        RHeaderSum += (band->lcx + SEP_WIDTH);
2540 2541 2542

	}
    }
2543
    if (RHeaderSum) RHeaderSum -= SEP_WIDTH; /* no separator after last band */
2544 2545 2546 2547

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

2548 2549
    if (imindBand == imaxdBand) return; /* nothing to drag against */
    if (imindBand == ihitBand) return; /* first band in row, can't drag */
2550 2551

    /* limit movement to inside adjustable bands - Left */
2552 2553 2554 2555
    if ( (ptsmove->x < mindBand->rcBand.left) ||
	 (ptsmove->x > maxdBand->rcBand.right) ||
	 (ptsmove->y < mindBand->rcBand.top) ||
	 (ptsmove->y > maxdBand->rcBand.bottom))
2556 2557
        return; /* should swap bands */

2558
    if (infoPtr->dwStyle & CCS_VERT)
2559 2560 2561 2562 2563
        movement = ptsmove->y - ((hitBand->rcBand.top+REBAR_PRE_GRIPPER) -
			     infoPtr->ihitoffset);
    else
        movement = ptsmove->x - ((hitBand->rcBand.left+REBAR_PRE_GRIPPER) -
			     infoPtr->ihitoffset);
2564 2565
    infoPtr->dragNow = *ptsmove;

2566
    TRACE("before: movement=%d (%ld,%ld), imindBand=%d, ihitBand=%d, imaxdBand=%d, LSum=%d, RSum=%d\n",
2567 2568
	  movement, ptsmove->x, ptsmove->y, imindBand, ihitBand,
	  imaxdBand, LHeaderSum, RHeaderSum);
2569
    REBAR_DumpBand (infoPtr);
2570

2571
    if (movement < 0) {
2572

2573 2574
        /* ***  Drag left/up *** */
        compress = rcBlt(hitBand) - rcBlt(mindBand) -
2575 2576 2577 2578 2579 2580
	           LHeaderSum;
	if (compress < abs(movement)) {
	    TRACE("limiting left drag, was %d changed to %d\n",
		  movement, -compress);
	    movement = -compress;
	}
2581

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

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

2617
    /* recompute all rectangles */
2618
    if (infoPtr->dwStyle & CCS_VERT) {
2619
	REBAR_CalcVertBand (infoPtr, imindBand, imaxdBand+1,
2620
			    FALSE);
2621 2622
    }
    else {
2623
	REBAR_CalcHorzBand (infoPtr, imindBand, imaxdBand+1,
2624
			    FALSE);
2625 2626
    }

2627 2628
    TRACE("bands after adjustment, see band # %d, %d\n",
	  imindBand, imaxdBand);
2629
    REBAR_DumpBand (infoPtr);
2630

2631
    SetRect (&newrect,
2632
	     mindBand->rcBand.left,
2633
	     mindBand->rcBand.top,
2634
	     maxdBand->rcBand.right,
2635
	     maxdBand->rcBand.bottom);
2636

2637
    REBAR_MoveChildWindows (infoPtr, imindBand, imaxdBand+1);
2638

2639 2640
    InvalidateRect (infoPtr->hwndSelf, &newrect, TRUE);
    UpdateWindow (infoPtr->hwndSelf);
2641 2642 2643

}

Alexandre Julliard's avatar
Alexandre Julliard committed
2644 2645


2646
/* << REBAR_BeginDrag >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
2647 2648 2649


static LRESULT
2650
REBAR_DeleteBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2651
{
2652
    UINT uBand = (UINT)wParam;
2653 2654
    HWND childhwnd = 0;
    REBAR_BAND *lpBand;
Alexandre Julliard's avatar
Alexandre Julliard committed
2655 2656 2657 2658

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

2659
    TRACE("deleting band %u!\n", uBand);
2660
    lpBand = &infoPtr->bands[uBand];
2661
    REBAR_Notify_NMREBAR (infoPtr, uBand, RBN_DELETINGBAND);
Alexandre Julliard's avatar
Alexandre Julliard committed
2662

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

2675 2676 2677
	if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild)
	    childhwnd = lpBand->hwndChild;

Eric Kohl's avatar
Eric Kohl committed
2678
	infoPtr->uNumBands--;
2679
	infoPtr->bands = Alloc (sizeof (REBAR_BAND) * infoPtr->uNumBands);
Eric Kohl's avatar
Eric Kohl committed
2680 2681 2682 2683 2684 2685 2686 2687 2688 2689
        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));
        }

2690
	Free (oldBands);
Eric Kohl's avatar
Eric Kohl committed
2691 2692
    }

2693 2694 2695
    if (childhwnd)
        ShowWindow (childhwnd, SW_HIDE);

2696
    REBAR_Notify_NMREBAR (infoPtr, -1, RBN_DELETEDBAND);
2697 2698 2699

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

2702 2703
    TRACE("setting NEEDS_LAYOUT\n");
    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
2704
    infoPtr->fStatus |= RESIZE_ANYHOW;
2705
    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
Eric Kohl's avatar
Eric Kohl committed
2706

Alexandre Julliard's avatar
Alexandre Julliard committed
2707 2708
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2709 2710


2711 2712
/* << REBAR_DragMove >> */
/* << REBAR_EndDrag >> */
Eric Kohl's avatar
Eric Kohl committed
2713 2714 2715


static LRESULT
2716
REBAR_GetBandBorders (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
2717
{
2718
    LPRECT lpRect = (LPRECT)lParam;
2719 2720 2721 2722
    REBAR_BAND *lpBand;

    if (!lParam)
	return 0;
2723
    if ((UINT)wParam >= infoPtr->uNumBands)
2724 2725
	return 0;

2726
    lpBand = &infoPtr->bands[(UINT)wParam];
2727 2728 2729 2730 2731 2732

    /* 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                                                   */
2733 2734
    if (infoPtr->dwStyle & RBS_BANDBORDERS) {
	if (infoPtr->dwStyle & CCS_VERT) {
2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745
	    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;
	}
2746 2747
    }
    else {
2748
	lpRect->left = lpBand->cxHeader;
2749
    }
Eric Kohl's avatar
Eric Kohl committed
2750 2751
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2752 2753


Patrik Stridvall's avatar
Patrik Stridvall committed
2754
inline static LRESULT
2755
REBAR_GetBandCount (REBAR_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
2756
{
2757
    TRACE("band count %u!\n", infoPtr->uNumBands);
Alexandre Julliard's avatar
Alexandre Julliard committed
2758 2759 2760 2761 2762 2763

    return infoPtr->uNumBands;
}


static LRESULT
2764
REBAR_GetBandInfoA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2765
{
2766
    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2767 2768 2769 2770
    REBAR_BAND *lpBand;

    if (lprbbi == NULL)
	return FALSE;
2771
    if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
2772
	return FALSE;
2773
    if ((UINT)wParam >= infoPtr->uNumBands)
Alexandre Julliard's avatar
Alexandre Julliard committed
2774 2775
	return FALSE;

2776
    TRACE("index %u\n", (UINT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2777 2778

    /* copy band information */
2779
    lpBand = &infoPtr->bands[(UINT)wParam];
Alexandre Julliard's avatar
Alexandre Julliard committed
2780 2781 2782 2783 2784 2785 2786

    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
2787
	if (lprbbi->clrBack == CLR_DEFAULT)
2788
	    lprbbi->clrBack = infoPtr->clrBtnFace;
Alexandre Julliard's avatar
Alexandre Julliard committed
2789 2790
    }

2791 2792
    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
      if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
2793 2794 2795 2796 2797
      {
          if (!WideCharToMultiByte( CP_ACP, 0, lpBand->lpText, -1,
                                    lprbbi->lpText, lprbbi->cch, NULL, NULL ))
              lprbbi->lpText[lprbbi->cch-1] = 0;
      }
2798
      else
2799
	*lprbbi->lpText = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
2800 2801
    }

2802 2803
    if (lprbbi->fMask & RBBIM_IMAGE) {
      if (lpBand->fMask & RBBIM_IMAGE)
Alexandre Julliard's avatar
Alexandre Julliard committed
2804
	lprbbi->iImage = lpBand->iImage;
2805 2806 2807
      else
	lprbbi->iImage = -1;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2808 2809 2810 2811 2812 2813 2814

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

    if (lprbbi->fMask & RBBIM_CHILDSIZE) {
	lprbbi->cxMinChild = lpBand->cxMinChild;
	lprbbi->cyMinChild = lpBand->cyMinChild;
2815 2816 2817 2818 2819
	if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
	    lprbbi->cyChild    = lpBand->cyChild;
	    lprbbi->cyMaxChild = lpBand->cyMaxChild;
	    lprbbi->cyIntegral = lpBand->cyIntegral;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830
    }

    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
2831
    /* check for additional data */
2832
    if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
Alexandre Julliard's avatar
Alexandre Julliard committed
2833 2834
	if (lprbbi->fMask & RBBIM_IDEALSIZE)
	    lprbbi->cxIdeal = lpBand->cxIdeal;
Alexandre Julliard's avatar
Alexandre Julliard committed
2835

Alexandre Julliard's avatar
Alexandre Julliard committed
2836 2837
	if (lprbbi->fMask & RBBIM_LPARAM)
	    lprbbi->lParam = lpBand->lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2838

Alexandre Julliard's avatar
Alexandre Julliard committed
2839 2840 2841
	if (lprbbi->fMask & RBBIM_HEADERSIZE)
	    lprbbi->cxHeader = lpBand->cxHeader;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2842

2843 2844
    REBAR_DumpBandInfo (lprbbi);

Alexandre Julliard's avatar
Alexandre Julliard committed
2845 2846 2847 2848
    return TRUE;
}


Eric Kohl's avatar
Eric Kohl committed
2849
static LRESULT
2850
REBAR_GetBandInfoW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
2851
{
2852
    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
Eric Kohl's avatar
Eric Kohl committed
2853 2854 2855 2856
    REBAR_BAND *lpBand;

    if (lprbbi == NULL)
	return FALSE;
2857
    if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE)
Eric Kohl's avatar
Eric Kohl committed
2858
	return FALSE;
2859
    if ((UINT)wParam >= infoPtr->uNumBands)
Eric Kohl's avatar
Eric Kohl committed
2860 2861
	return FALSE;

2862
    TRACE("index %u\n", (UINT)wParam);
Eric Kohl's avatar
Eric Kohl committed
2863 2864

    /* copy band information */
2865
    lpBand = &infoPtr->bands[(UINT)wParam];
Eric Kohl's avatar
Eric Kohl committed
2866 2867 2868 2869 2870 2871 2872

    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
2873
	if (lprbbi->clrBack == CLR_DEFAULT)
2874
	    lprbbi->clrBack = infoPtr->clrBtnFace;
Eric Kohl's avatar
Eric Kohl committed
2875 2876
    }

2877 2878 2879
    if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
      if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
	lstrcpynW (lprbbi->lpText, lpBand->lpText, lprbbi->cch);
2880
      else
2881
	*lprbbi->lpText = 0;
Eric Kohl's avatar
Eric Kohl committed
2882 2883
    }

2884 2885
    if (lprbbi->fMask & RBBIM_IMAGE) {
      if (lpBand->fMask & RBBIM_IMAGE)
Eric Kohl's avatar
Eric Kohl committed
2886
	lprbbi->iImage = lpBand->iImage;
2887 2888 2889
      else
	lprbbi->iImage = -1;
    }
Eric Kohl's avatar
Eric Kohl committed
2890 2891 2892 2893 2894 2895 2896

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

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

    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 */
2914
    if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
Eric Kohl's avatar
Eric Kohl committed
2915 2916 2917 2918 2919 2920 2921 2922 2923 2924
	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;
    }

2925 2926
    REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);

Eric Kohl's avatar
Eric Kohl committed
2927 2928
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2929

Alexandre Julliard's avatar
Alexandre Julliard committed
2930 2931

static LRESULT
2932
REBAR_GetBarHeight (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2933
{
2934
    INT nHeight;
Alexandre Julliard's avatar
Alexandre Julliard committed
2935

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

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

2940
    return nHeight;
Alexandre Julliard's avatar
Alexandre Julliard committed
2941
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2942 2943 2944


static LRESULT
2945
REBAR_GetBarInfo (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2946 2947 2948 2949 2950 2951 2952 2953 2954
{
    LPREBARINFO lpInfo = (LPREBARINFO)lParam;

    if (lpInfo == NULL)
	return FALSE;

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

2955
    TRACE("getting bar info!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
2956 2957 2958 2959 2960 2961 2962 2963 2964 2965

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

    return TRUE;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
2966
inline static LRESULT
2967
REBAR_GetBkColor (REBAR_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
2968
{
2969
    COLORREF clr = infoPtr->clrBk;
Alexandre Julliard's avatar
Alexandre Julliard committed
2970

Guy Albertelli's avatar
Guy Albertelli committed
2971
    if (clr == CLR_DEFAULT)
2972
      clr = infoPtr->clrBtnFace;
2973 2974

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

2976
    return clr;
Alexandre Julliard's avatar
Alexandre Julliard committed
2977 2978 2979
}


2980 2981
/* << REBAR_GetColorScheme >> */
/* << REBAR_GetDropTarget >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
2982

Eric Kohl's avatar
Eric Kohl committed
2983 2984

static LRESULT
2985
REBAR_GetPalette (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
2986
{
2987
    FIXME("empty stub!\n");
Eric Kohl's avatar
Eric Kohl committed
2988 2989 2990 2991 2992 2993

    return 0;
}


static LRESULT
2994
REBAR_GetRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
2995
{
2996 2997
    INT iBand = (INT)wParam;
    LPRECT lprc = (LPRECT)lParam;
Eric Kohl's avatar
Eric Kohl committed
2998 2999
    REBAR_BAND *lpBand;

3000
    if ((iBand < 0) && ((UINT)iBand >= infoPtr->uNumBands))
Eric Kohl's avatar
Eric Kohl committed
3001 3002 3003 3004 3005
	return FALSE;
    if (!lprc)
	return FALSE;

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

3008
    TRACE("band %d, (%ld,%ld)-(%ld,%ld)\n", iBand,
3009
	  lprc->left, lprc->top, lprc->right, lprc->bottom);
Eric Kohl's avatar
Eric Kohl committed
3010 3011 3012 3013 3014

    return TRUE;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
3015
inline static LRESULT
3016
REBAR_GetRowCount (REBAR_INFO *infoPtr)
Eric Kohl's avatar
Eric Kohl committed
3017
{
3018
    TRACE("%u\n", infoPtr->uNumRows);
Eric Kohl's avatar
Eric Kohl committed
3019

3020
    return infoPtr->uNumRows;
Eric Kohl's avatar
Eric Kohl committed
3021 3022 3023 3024
}


static LRESULT
3025
REBAR_GetRowHeight (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3026
{
3027
    INT iRow = (INT)wParam;
3028 3029
    int j = 0, ret = 0;
    UINT i;
3030
    REBAR_BAND *lpBand;
Eric Kohl's avatar
Eric Kohl committed
3031

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

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

3045
    return ret;
Eric Kohl's avatar
Eric Kohl committed
3046
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3047 3048


Patrik Stridvall's avatar
Patrik Stridvall committed
3049
inline static LRESULT
3050
REBAR_GetTextColor (REBAR_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
3051
{
3052
    TRACE("text color 0x%06lx!\n", infoPtr->clrText);
Alexandre Julliard's avatar
Alexandre Julliard committed
3053 3054 3055 3056 3057

    return infoPtr->clrText;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
3058
inline static LRESULT
3059
REBAR_GetToolTips (REBAR_INFO *infoPtr)
Eric Kohl's avatar
Eric Kohl committed
3060
{
3061
    return (LRESULT)infoPtr->hwndToolTip;
Eric Kohl's avatar
Eric Kohl committed
3062 3063 3064
}


Patrik Stridvall's avatar
Patrik Stridvall committed
3065
inline static LRESULT
3066
REBAR_GetUnicodeFormat (REBAR_INFO *infoPtr)
Eric Kohl's avatar
Eric Kohl committed
3067
{
3068
    TRACE("%s hwnd=%p\n",
3069 3070
	  infoPtr->bUnicode ? "TRUE" : "FALSE", infoPtr->hwndSelf);

Eric Kohl's avatar
Eric Kohl committed
3071 3072
    return infoPtr->bUnicode;
}
Eric Kohl's avatar
Eric Kohl committed
3073 3074


Eric Kohl's avatar
Eric Kohl committed
3075
inline static LRESULT
3076
REBAR_GetVersion (REBAR_INFO *infoPtr)
Eric Kohl's avatar
Eric Kohl committed
3077
{
3078
    TRACE("version %d\n", infoPtr->iVersion);
Eric Kohl's avatar
Eric Kohl committed
3079 3080 3081 3082
    return infoPtr->iVersion;
}


Eric Kohl's avatar
Eric Kohl committed
3083
static LRESULT
3084
REBAR_HitTest (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3085
{
3086
    LPRBHITTESTINFO lprbht = (LPRBHITTESTINFO)lParam;
Eric Kohl's avatar
Eric Kohl committed
3087 3088 3089 3090

    if (!lprbht)
	return -1;

3091
    REBAR_InternalHitTest (infoPtr, &lprbht->pt, &lprbht->flags, &lprbht->iBand);
Eric Kohl's avatar
Eric Kohl committed
3092 3093 3094

    return lprbht->iBand;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3095 3096 3097


static LRESULT
3098
REBAR_IdToIndex (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3099
{
3100
    UINT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
3101 3102 3103 3104 3105 3106 3107 3108

    if (infoPtr == NULL)
	return -1;

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

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

3115
    TRACE("id %u is not found\n", (UINT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3116 3117 3118 3119 3120
    return -1;
}


static LRESULT
3121
REBAR_InsertBandA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3122
{
3123 3124
    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
    UINT uIndex = (UINT)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3125 3126 3127 3128 3129 3130
    REBAR_BAND *lpBand;

    if (infoPtr == NULL)
	return FALSE;
    if (lprbbi == NULL)
	return FALSE;
3131
    if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
3132 3133
	return FALSE;

3134 3135 3136
    /* 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
3137

Alexandre Julliard's avatar
Alexandre Julliard committed
3138
    if (infoPtr->uNumBands == 0) {
3139
	infoPtr->bands = (REBAR_BAND *)Alloc (sizeof (REBAR_BAND));
Alexandre Julliard's avatar
Alexandre Julliard committed
3140 3141 3142 3143 3144
	uIndex = 0;
    }
    else {
	REBAR_BAND *oldBands = infoPtr->bands;
	infoPtr->bands =
3145
	    (REBAR_BAND *)Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
3146
	if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
Alexandre Julliard's avatar
Alexandre Julliard committed
3147 3148
	    uIndex = infoPtr->uNumBands;

Alexandre Julliard's avatar
Alexandre Julliard committed
3149 3150 3151 3152 3153
	/* pre insert copy */
	if (uIndex > 0) {
	    memcpy (&infoPtr->bands[0], &oldBands[0],
		    uIndex * sizeof(REBAR_BAND));
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
3154 3155

	/* post copy */
3156
	if (uIndex < infoPtr->uNumBands) {
Alexandre Julliard's avatar
Alexandre Julliard committed
3157
	    memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
3158
		    (infoPtr->uNumBands - uIndex) * sizeof(REBAR_BAND));
Alexandre Julliard's avatar
Alexandre Julliard committed
3159
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
3160

3161
	Free (oldBands);
Alexandre Julliard's avatar
Alexandre Julliard committed
3162 3163 3164 3165
    }

    infoPtr->uNumBands++;

3166
    TRACE("index %u!\n", uIndex);
Alexandre Julliard's avatar
Alexandre Julliard committed
3167 3168 3169

    /* initialize band (infoPtr->bands[uIndex])*/
    lpBand = &infoPtr->bands[uIndex];
3170
    lpBand->fMask = 0;
3171
    lpBand->fStatus = 0;
3172 3173 3174 3175 3176
    lpBand->clrFore = infoPtr->clrText;
    lpBand->clrBack = infoPtr->clrBk;
    lpBand->hwndChild = 0;
    lpBand->hwndPrevParent = 0;

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

3187
    REBAR_ValidateBand (infoPtr, lpBand);
3188 3189
    /* On insert of second band, revalidate band 1 to possible add gripper */
    if (infoPtr->uNumBands == 2)
3190
	REBAR_ValidateBand (infoPtr, &infoPtr->bands[0]);
Alexandre Julliard's avatar
Alexandre Julliard committed
3191

3192
    REBAR_DumpBand (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
3193

3194
    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3195
    InvalidateRect(infoPtr->hwndSelf, 0, 1);
Eric Kohl's avatar
Eric Kohl committed
3196

Alexandre Julliard's avatar
Alexandre Julliard committed
3197 3198 3199 3200
    return TRUE;
}


Eric Kohl's avatar
Eric Kohl committed
3201
static LRESULT
3202
REBAR_InsertBandW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3203
{
3204 3205
    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
    UINT uIndex = (UINT)wParam;
Eric Kohl's avatar
Eric Kohl committed
3206 3207 3208 3209 3210 3211
    REBAR_BAND *lpBand;

    if (infoPtr == NULL)
	return FALSE;
    if (lprbbi == NULL)
	return FALSE;
3212
    if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE)
Eric Kohl's avatar
Eric Kohl committed
3213 3214
	return FALSE;

3215 3216 3217
    /* 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
3218 3219

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

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

	/* post copy */
3237
	if (uIndex <= infoPtr->uNumBands - 1) {
Eric Kohl's avatar
Eric Kohl committed
3238
	    memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
3239
		    (infoPtr->uNumBands - uIndex) * sizeof(REBAR_BAND));
Eric Kohl's avatar
Eric Kohl committed
3240 3241
	}

3242
	Free (oldBands);
Eric Kohl's avatar
Eric Kohl committed
3243 3244 3245 3246
    }

    infoPtr->uNumBands++;

3247
    TRACE("index %u!\n", uIndex);
Eric Kohl's avatar
Eric Kohl committed
3248 3249 3250

    /* initialize band (infoPtr->bands[uIndex])*/
    lpBand = &infoPtr->bands[uIndex];
3251
    lpBand->fMask = 0;
3252
    lpBand->fStatus = 0;
3253 3254 3255 3256 3257
    lpBand->clrFore = infoPtr->clrText;
    lpBand->clrBack = infoPtr->clrBk;
    lpBand->hwndChild = 0;
    lpBand->hwndPrevParent = 0;

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

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

3273
    REBAR_DumpBand (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
3274

3275
    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3276
    InvalidateRect(infoPtr->hwndSelf, 0, 1);
Eric Kohl's avatar
Eric Kohl committed
3277 3278 3279 3280 3281

    return TRUE;
}


3282
static LRESULT
3283
REBAR_MaximizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3284
{
3285 3286
    REBAR_BAND *lpBand;
    UINT uBand = (UINT) wParam;
3287

3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314
    /* 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;
3315

3316 3317 3318 3319
}


static LRESULT
3320
REBAR_MinimizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3321
{
3322 3323 3324 3325 3326
    REBAR_BAND *band, *lpBand;
    UINT uBand = (UINT) wParam;
    RECT newrect;
    INT imindBand, imaxdBand, iprevBand, startBand, endBand;
    INT movement, i;
3327

3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351
    /* 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) {
3352
	ERR("something is wrong, band=(%ld,%ld)-(%ld,%ld), cxheader=%d\n",
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 3390 3391 3392 3393 3394
	    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;
3395
	SetRect (&newrect,
3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420
		 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;
3421
	SetRect (&newrect,
3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435
		 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 {
3436
	REBAR_CalcHorzBand (infoPtr, startBand, endBand+1,
3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448
			    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;
3449 3450 3451 3452
}


static LRESULT
3453
REBAR_MoveBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3454
{
3455 3456 3457 3458
    REBAR_BAND *oldBands = infoPtr->bands;
    REBAR_BAND holder;
    UINT uFrom = (UINT)wParam;
    UINT uTo = (UINT)lParam;
3459

3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472
    /* 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));

3473
    /* close up rest of bands (pseudo delete) */
3474 3475 3476 3477 3478 3479 3480
    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 =
3481
	(REBAR_BAND *)Alloc ((infoPtr->uNumBands)*sizeof(REBAR_BAND));
3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497

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

3498
    Free (oldBands);
3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513

    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;
3514
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3515 3516


3517 3518 3519 3520 3521 3522 3523
/* 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
3524
static LRESULT
3525
REBAR_SetBandInfoA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3526
{
3527
    LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3528
    REBAR_BAND *lpBand;
3529
    BOOL bChanged;
Alexandre Julliard's avatar
Alexandre Julliard committed
3530 3531 3532

    if (lprbbi == NULL)
	return FALSE;
3533
    if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
3534
	return FALSE;
3535
    if ((UINT)wParam >= infoPtr->uNumBands)
Alexandre Julliard's avatar
Alexandre Julliard committed
3536 3537
	return FALSE;

3538
    TRACE("index %u\n", (UINT)wParam);
3539
    REBAR_DumpBandInfo (lprbbi);
Alexandre Julliard's avatar
Alexandre Julliard committed
3540 3541

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

3544
    bChanged = REBAR_CommonSetupBand (infoPtr->hwndSelf, lprbbi, lpBand);
Eric Kohl's avatar
Eric Kohl committed
3545
    if (lprbbi->fMask & RBBIM_TEXT) {
3546 3547 3548 3549 3550 3551
        LPWSTR wstr = NULL;

        if (lprbbi->lpText)
        {
            INT len;
            len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
3552
            if (len > 1)
3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569
                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
3570 3571
    }

3572
    REBAR_ValidateBand (infoPtr, lpBand);
Alexandre Julliard's avatar
Alexandre Julliard committed
3573

3574
    REBAR_DumpBand (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
3575

3576
    if (bChanged && (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE))) {
3577
	  REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3578 3579
	  InvalidateRect(infoPtr->hwndSelf, 0, 1);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
3580 3581 3582 3583

    return TRUE;
}

Eric Kohl's avatar
Eric Kohl committed
3584
static LRESULT
3585
REBAR_SetBandInfoW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3586
{
3587
    LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
Eric Kohl's avatar
Eric Kohl committed
3588
    REBAR_BAND *lpBand;
3589
    BOOL bChanged;
Eric Kohl's avatar
Eric Kohl committed
3590 3591 3592

    if (lprbbi == NULL)
	return FALSE;
3593
    if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE)
Eric Kohl's avatar
Eric Kohl committed
3594
	return FALSE;
3595
    if ((UINT)wParam >= infoPtr->uNumBands)
Eric Kohl's avatar
Eric Kohl committed
3596 3597
	return FALSE;

3598
    TRACE("index %u\n", (UINT)wParam);
3599
    REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
Eric Kohl's avatar
Eric Kohl committed
3600 3601

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

3604 3605 3606
    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
3607
	if (lpBand->lpText) {
3608
	    Free (lpBand->lpText);
Eric Kohl's avatar
Eric Kohl committed
3609 3610 3611
	    lpBand->lpText = NULL;
	}
	if (lprbbi->lpText) {
3612
	    INT len = lstrlenW (lprbbi->lpText);
3613 3614 3615 3616 3617
	    if (len > 0)
	    {
	        lpBand->lpText = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR));
	        strcpyW (lpBand->lpText, lprbbi->lpText);
	    }
Eric Kohl's avatar
Eric Kohl committed
3618
	}
3619
        bChanged = TRUE;
Eric Kohl's avatar
Eric Kohl committed
3620 3621
    }

3622
    REBAR_ValidateBand (infoPtr, lpBand);
Eric Kohl's avatar
Eric Kohl committed
3623

3624
    REBAR_DumpBand (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
3625

3626
    if ( bChanged && (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) ) {
3627
      REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3628 3629
      InvalidateRect(infoPtr->hwndSelf, 0, 1);
    }
Eric Kohl's avatar
Eric Kohl committed
3630 3631 3632

    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3633 3634 3635


static LRESULT
3636
REBAR_SetBarInfo (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3637 3638
{
    LPREBARINFO lpInfo = (LPREBARINFO)lParam;
3639 3640
    REBAR_BAND *lpBand;
    UINT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
3641 3642 3643 3644 3645 3646 3647

    if (lpInfo == NULL)
	return FALSE;

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

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

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

3666 3667 3668
    /* revalidate all bands to reset flags for images in headers of bands */
    for (i=0; i<infoPtr->uNumBands; i++) {
        lpBand = &infoPtr->bands[i];
3669
	REBAR_ValidateBand (infoPtr, lpBand);
3670 3671
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
3672 3673 3674 3675 3676
    return TRUE;
}


static LRESULT
3677
REBAR_SetBkColor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3678 3679 3680 3681 3682 3683
{
    COLORREF clrTemp;

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

3684
    TRACE("background color 0x%06lx!\n", infoPtr->clrBk);
Alexandre Julliard's avatar
Alexandre Julliard committed
3685 3686 3687 3688 3689

    return clrTemp;
}


3690 3691
/* << REBAR_SetColorScheme >> */
/* << REBAR_SetPalette >> */
Eric Kohl's avatar
Eric Kohl committed
3692 3693 3694


static LRESULT
3695
REBAR_SetParent (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3696
{
3697
    HWND hwndTemp = infoPtr->hwndNotify;
Eric Kohl's avatar
Eric Kohl committed
3698

3699
    infoPtr->hwndNotify = (HWND)wParam;
Eric Kohl's avatar
Eric Kohl committed
3700 3701 3702

    return (LRESULT)hwndTemp;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3703 3704 3705


static LRESULT
3706
REBAR_SetTextColor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3707 3708 3709 3710 3711 3712
{
    COLORREF clrTemp;

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

3713
    TRACE("text color 0x%06lx!\n", infoPtr->clrText);
Alexandre Julliard's avatar
Alexandre Julliard committed
3714 3715 3716 3717 3718

    return clrTemp;
}


3719
/* << REBAR_SetTooltips >> */
Eric Kohl's avatar
Eric Kohl committed
3720 3721


Patrik Stridvall's avatar
Patrik Stridvall committed
3722
inline static LRESULT
3723
REBAR_SetUnicodeFormat (REBAR_INFO *infoPtr, WPARAM wParam)
Eric Kohl's avatar
Eric Kohl committed
3724
{
3725
    BOOL bTemp = infoPtr->bUnicode;
3726

3727
    TRACE("to %s hwnd=%p, was %s\n",
3728 3729 3730
	  ((BOOL)wParam) ? "TRUE" : "FALSE", infoPtr->hwndSelf,
	  (bTemp) ? "TRUE" : "FALSE");

3731
    infoPtr->bUnicode = (BOOL)wParam;
3732

3733
   return bTemp;
Eric Kohl's avatar
Eric Kohl committed
3734
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3735 3736


Eric Kohl's avatar
Eric Kohl committed
3737
static LRESULT
3738
REBAR_SetVersion (REBAR_INFO *infoPtr, INT iVersion)
Eric Kohl's avatar
Eric Kohl committed
3739 3740 3741 3742 3743 3744 3745 3746
{
    INT iOldVersion = infoPtr->iVersion;

    if (iVersion > COMCTL32_VERSION)
	return -1;

    infoPtr->iVersion = iVersion;

3747 3748
    TRACE("new version %d\n", iVersion);

Eric Kohl's avatar
Eric Kohl committed
3749 3750 3751 3752
    return iOldVersion;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
3753
static LRESULT
3754
REBAR_ShowBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3755
{
Eric Kohl's avatar
Eric Kohl committed
3756
    REBAR_BAND *lpBand;
Alexandre Julliard's avatar
Alexandre Julliard committed
3757

3758
    if (((INT)wParam < 0) || ((INT)wParam > infoPtr->uNumBands))
Alexandre Julliard's avatar
Alexandre Julliard committed
3759 3760
	return FALSE;

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

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

3776
    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
3777
    REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3778
    InvalidateRect(infoPtr->hwndSelf, 0, 1);
Alexandre Julliard's avatar
Alexandre Julliard committed
3779 3780 3781 3782 3783 3784

    return TRUE;
}


static LRESULT
3785
REBAR_SizeToRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3786
{
3787
    LPRECT lpRect = (LPRECT)lParam;
3788
    RECT t1;
Alexandre Julliard's avatar
Alexandre Julliard committed
3789 3790

    if (lpRect == NULL)
3791
       return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
3792

3793
    TRACE("[%ld %ld %ld %ld]\n",
3794
	  lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
Eric Kohl's avatar
Eric Kohl committed
3795

3796
    /*  what is going on???? */
3797
    GetWindowRect(infoPtr->hwndSelf, &t1);
3798
    TRACE("window rect [%ld %ld %ld %ld]\n",
3799
	  t1.left, t1.top, t1.right, t1.bottom);
3800
    GetClientRect(infoPtr->hwndSelf, &t1);
3801
    TRACE("client rect [%ld %ld %ld %ld]\n",
3802
	  t1.left, t1.top, t1.right, t1.bottom);
Eric Kohl's avatar
Eric Kohl committed
3803

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



static LRESULT
3815
REBAR_Create (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3816
{
3817
    LPCREATESTRUCTW cs = (LPCREATESTRUCTW) lParam;
3818
    RECT wnrc1, clrc1;
3819
    HTHEME theme;
3820 3821

    if (TRACE_ON(rebar)) {
3822 3823
	GetWindowRect(infoPtr->hwndSelf, &wnrc1);
	GetClientRect(infoPtr->hwndSelf, &clrc1);
3824
	TRACE("window=(%ld,%ld)-(%ld,%ld) client=(%ld,%ld)-(%ld,%ld) cs=(%d,%d %dx%d)\n",
3825 3826 3827 3828
	      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
3829

3830
    TRACE("created!\n");
3831 3832 3833 3834 3835 3836 3837
    
    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
3838 3839 3840 3841 3842
    return 0;
}


static LRESULT
3843
REBAR_Destroy (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3844 3845
{
    REBAR_BAND *lpBand;
3846
    UINT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
3847 3848 3849 3850 3851 3852 3853 3854 3855 3856


    /* 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) {
3857
		Free (lpBand->lpText);
Alexandre Julliard's avatar
Alexandre Julliard committed
3858 3859
		lpBand->lpText = NULL;
	    }
3860
	    /* destroy child window */
3861
	    DestroyWindow (lpBand->hwndChild);
Alexandre Julliard's avatar
Alexandre Julliard committed
3862 3863 3864
	}

	/* free band array */
3865
	Free (infoPtr->bands);
Alexandre Julliard's avatar
Alexandre Julliard committed
3866 3867 3868
	infoPtr->bands = NULL;
    }

3869 3870 3871 3872
    DestroyCursor (infoPtr->hcurArrow);
    DestroyCursor (infoPtr->hcurHorz);
    DestroyCursor (infoPtr->hcurVert);
    DestroyCursor (infoPtr->hcurDrag);
3873
    if(infoPtr->hDefaultFont) DeleteObject (infoPtr->hDefaultFont);
3874
    SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0);
3875 3876
    
    CloseThemeData (GetWindowTheme (infoPtr->hwndSelf));
Eric Kohl's avatar
Eric Kohl committed
3877

Alexandre Julliard's avatar
Alexandre Julliard committed
3878
    /* free rebar info data */
3879
    Free (infoPtr);
3880
    TRACE("destroyed!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
3881 3882 3883 3884
    return 0;
}


3885
static LRESULT
3886
REBAR_EraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3887 3888 3889 3890
{
    RECT cliprect;

    if (GetClipBox ( (HDC)wParam, &cliprect))
3891
        return REBAR_InternalEraseBkGnd (infoPtr, wParam, lParam, &cliprect);
3892 3893 3894 3895
    return 0;
}


Eric Kohl's avatar
Eric Kohl committed
3896
static LRESULT
3897
REBAR_GetFont (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
3898 3899 3900 3901
{
    return (LRESULT)infoPtr->hFont;
}

Robert Shearman's avatar
Robert Shearman committed
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 3928 3929 3930 3931 3932
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
3933

3934
static LRESULT
3935
REBAR_LButtonDown (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3936 3937
{
    REBAR_BAND *lpBand;
Robert Shearman's avatar
Robert Shearman committed
3938
    UINT htFlags;
Mike McCormack's avatar
Mike McCormack committed
3939
    INT iHitBand;
Robert Shearman's avatar
Robert Shearman committed
3940 3941 3942
    POINT ptMouseDown;
    ptMouseDown.x = (INT)LOWORD(lParam);
    ptMouseDown.y = (INT)HIWORD(lParam);
3943

Robert Shearman's avatar
Robert Shearman committed
3944 3945
    REBAR_InternalHitTest(infoPtr, &ptMouseDown, &htFlags, &iHitBand);
    lpBand = &infoPtr->bands[iHitBand];
3946

Robert Shearman's avatar
Robert Shearman committed
3947 3948 3949 3950 3951 3952 3953
    if (htFlags == RBHT_CHEVRON)
    {
        REBAR_PushChevron(infoPtr, iHitBand, 0);
    }
    else if (htFlags == RBHT_GRABBER || htFlags == RBHT_CAPTION)
    {
        TRACE("Starting drag\n");
3954

Robert Shearman's avatar
Robert Shearman committed
3955 3956
        SetCapture (infoPtr->hwndSelf);
        infoPtr->iGrabbedBand = iHitBand;
3957

Robert Shearman's avatar
Robert Shearman committed
3958
        /* save off the LOWORD and HIWORD of lParam as initial x,y */
3959 3960
        infoPtr->dragStart.x = (short)LOWORD(lParam);
        infoPtr->dragStart.y = (short)HIWORD(lParam);
Robert Shearman's avatar
Robert Shearman committed
3961 3962 3963 3964 3965 3966
        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);
    }
3967 3968 3969 3970
    return 0;
}

static LRESULT
3971
REBAR_LButtonUp (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3972
{
Robert Shearman's avatar
Robert Shearman committed
3973 3974 3975 3976 3977 3978 3979 3980
    if (infoPtr->iGrabbedBand >= 0)
    {
        NMHDR layout;
        RECT rect;

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

Robert Shearman's avatar
Robert Shearman committed
3982
        ReleaseCapture ();
3983

Robert Shearman's avatar
Robert Shearman committed
3984 3985 3986 3987 3988
        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;
        }
3989

Robert Shearman's avatar
Robert Shearman committed
3990
        infoPtr->iGrabbedBand = -1;
3991

Robert Shearman's avatar
Robert Shearman committed
3992 3993
        GetClientRect(infoPtr->hwndSelf, &rect);
        InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
3994 3995 3996 3997 3998
    }

    return 0;
}

Robert Shearman's avatar
Robert Shearman committed
3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015
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;
}
4016

Eric Kohl's avatar
Eric Kohl committed
4017
static LRESULT
4018
REBAR_MouseMove (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4019
{
Robert Shearman's avatar
Robert Shearman committed
4020
    REBAR_BAND *lpChevronBand;
4021
    POINT ptMove;
Eric Kohl's avatar
Eric Kohl committed
4022

4023 4024
    ptMove.x = (short)LOWORD(lParam);
    ptMove.y = (short)HIWORD(lParam);
4025

Robert Shearman's avatar
Robert Shearman committed
4026 4027 4028 4029 4030 4031 4032
    /* 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");
4033

Robert Shearman's avatar
Robert Shearman committed
4034 4035
        band1 = &infoPtr->bands[infoPtr->iGrabbedBand-1];
        band2 = &infoPtr->bands[infoPtr->iGrabbedBand];
4036

Robert Shearman's avatar
Robert Shearman committed
4037
        /* if mouse did not move much, exit */
4038 4039
        if ((abs(ptMove.x - infoPtr->dragNow.x) <= mindragx) &&
            (abs(ptMove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
Robert Shearman's avatar
Robert Shearman committed
4040 4041 4042

        /* Test for valid drag case - must not be first band in row */
        if (infoPtr->dwStyle & CCS_VERT) {
4043 4044
            if ((ptMove.x < band2->rcBand.left) ||
	      (ptMove.x > band2->rcBand.right) ||
Robert Shearman's avatar
Robert Shearman committed
4045 4046 4047 4048
              ((infoPtr->iGrabbedBand > 0) && (band1->iRow != band2->iRow))) {
                FIXME("Cannot drag to other rows yet!!\n");
            }
            else {
4049
                REBAR_HandleLRDrag (infoPtr, &ptMove);
Robert Shearman's avatar
Robert Shearman committed
4050 4051 4052
            }
        }
        else {
4053 4054
            if ((ptMove.y < band2->rcBand.top) ||
              (ptMove.y > band2->rcBand.bottom) ||
Robert Shearman's avatar
Robert Shearman committed
4055 4056 4057 4058
              ((infoPtr->iGrabbedBand > 0) && (band1->iRow != band2->iRow))) {
                FIXME("Cannot drag to other rows yet!!\n");
            }
            else {
4059
                REBAR_HandleLRDrag (infoPtr, &ptMove);
Robert Shearman's avatar
Robert Shearman committed
4060 4061
            }
        }
4062
    }
Robert Shearman's avatar
Robert Shearman committed
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 4107 4108 4109 4110 4111
    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;
4112
    }
Robert Shearman's avatar
Robert Shearman committed
4113

Eric Kohl's avatar
Eric Kohl committed
4114 4115 4116 4117
    return 0;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
4118
inline static LRESULT
4119
REBAR_NCCalcSize (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4120
{
4121
    HTHEME theme;
4122 4123 4124
    if (infoPtr->dwStyle & WS_BORDER) {
	InflateRect((LPRECT)lParam, -GetSystemMetrics(SM_CXEDGE),
		    -GetSystemMetrics(SM_CYEDGE));
Eric Kohl's avatar
Eric Kohl committed
4125
    }
4126 4127 4128 4129
    else if ((theme = GetWindowTheme (infoPtr->hwndSelf)))
    {
        ((LPRECT)lParam)->top++;
    }
4130
    TRACE("new client=(%ld,%ld)-(%ld,%ld)\n",
4131 4132
	  ((LPRECT)lParam)->left, ((LPRECT)lParam)->top,
	  ((LPRECT)lParam)->right, ((LPRECT)lParam)->bottom);
4133
    return 0;
Eric Kohl's avatar
Eric Kohl committed
4134 4135 4136
}


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

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

    if (TRACE_ON(rebar)) {
	GetWindowRect(hwnd, &wnrc1);
	GetClientRect(hwnd, &clrc1);
4155
	TRACE("window=(%ld,%ld)-(%ld,%ld) client=(%ld,%ld)-(%ld,%ld) cs=(%d,%d %dx%d)\n",
4156 4157 4158 4159 4160 4161
	      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 */
4162
    infoPtr = (REBAR_INFO *)Alloc (sizeof(REBAR_INFO));
4163
    SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
4164 4165 4166

    /* initialize info structure - initial values are 0 */
    infoPtr->clrBk = CLR_NONE;
4167 4168
    infoPtr->clrText = CLR_NONE;
    infoPtr->clrBtnText = GetSysColor (COLOR_BTNTEXT);
4169
    infoPtr->clrBtnFace = GetSysColor (COLOR_BTNFACE);
Robert Shearman's avatar
Robert Shearman committed
4170 4171 4172
    infoPtr->iOldBand = -1;
    infoPtr->ichevronhotBand = -2;
    infoPtr->iGrabbedBand = -1;
4173 4174
    infoPtr->hwndSelf = hwnd;
    infoPtr->DoRedraw = TRUE;
4175 4176 4177 4178
    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);
4179
    infoPtr->bUnicode = IsWindowUnicode (hwnd);
4180
    infoPtr->fStatus = CREATE_RUNNING;
4181
    infoPtr->hFont = GetStockObject (SYSTEM_FONT);
4182 4183

    /* issue WM_NOTIFYFORMAT to get unicode status of parent */
4184
    i = SendMessageW(REBAR_GetNotifyParent (infoPtr),
4185
		     WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY);
4186
    if ((i < NFR_ANSI) || (i > NFR_UNICODE)) {
4187
	ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n", i);
4188 4189 4190 4191
	i = NFR_ANSI;
    }
    infoPtr->NtfUnicode = (i == NFR_UNICODE) ? 1 : 0;

4192 4193
    /* Stow away the original style */
    infoPtr->orgStyle = cs->style;
4194 4195
    /* add necessary styles to the requested styles */
    infoPtr->dwStyle = cs->style | WS_VISIBLE | CCS_TOP;
4196
    SetWindowLongW (hwnd, GWL_STYLE, infoPtr->dwStyle);
4197

4198
    /* get font handle for Caption Font */
4199
    ncm.cbSize = sizeof(ncm);
4200
    SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
4201 4202 4203 4204
    /* if the font is bold, set to normal */
    if (ncm.lfCaptionFont.lfWeight > FW_NORMAL) {
	ncm.lfCaptionFont.lfWeight = FW_NORMAL;
    }
4205
    tfont = CreateFontIndirectW (&ncm.lfCaptionFont);
4206
    if (tfont) {
4207
        infoPtr->hFont = infoPtr->hDefaultFont = tfont;
4208 4209
    }

4210 4211 4212
/* native does:
	    GetSysColor (numerous);
	    GetSysColorBrush (numerous) (see WM_SYSCOLORCHANGE);
4213
	   *GetStockObject (SYSTEM_FONT);
4214 4215 4216 4217 4218
	   *SetWindowLong (hwnd, 0, info ptr);
	   *WM_NOTIFYFORMAT;
	   *SetWindowLong (hwnd, GWL_STYLE, style+0x10000001);
                                    WS_VISIBLE = 0x10000000;
                                    CCS_TOP    = 0x00000001;
4219 4220
	   *SystemParametersInfo (SPI_GETNONCLIENTMETRICS...);
	   *CreateFontIndirect (lfCaptionFont from above);
4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240
	    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;
4241
    POINT clpt;
4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253
    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.
     */

4254 4255
    clpt.x = (short)LOWORD(lParam);
    clpt.y = (short)HIWORD(lParam);
4256
    ScreenToClient (infoPtr->hwndSelf, &clpt);
4257
    REBAR_InternalHitTest (infoPtr, &clpt, &scrap,
4258 4259 4260 4261 4262 4263
			   (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",
4264
	      ret, i);
4265 4266 4267 4268 4269 4270 4271
	ret = (LRESULT) i;
    }
    TRACE("returning %ld, client point (%ld,%ld)\n", ret, clpt.x, clpt.y);
    return ret;
}


Eric Kohl's avatar
Eric Kohl committed
4272
static LRESULT
4273
REBAR_NCPaint (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4274
{
4275
    RECT rcWindow;
4276
    HDC hdc;
4277
    HTHEME theme;
Eric Kohl's avatar
Eric Kohl committed
4278

4279
    if (infoPtr->dwStyle & WS_MINIMIZE)
4280
	return 0; /* Nothing to do */
Eric Kohl's avatar
Eric Kohl committed
4281

4282
    if (infoPtr->dwStyle & WS_BORDER) {
4283 4284 4285 4286

	/* adjust rectangle and draw the necessary edge */
	if (!(hdc = GetDCEx( infoPtr->hwndSelf, 0, DCX_USESTYLE | DCX_WINDOW )))
	    return 0;
4287
	GetWindowRect (infoPtr->hwndSelf, &rcWindow);
4288
	OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
4289
	TRACE("rect (%ld,%ld)-(%ld,%ld)\n",
4290 4291
	      rcWindow.left, rcWindow.top,
	      rcWindow.right, rcWindow.bottom);
4292 4293
	DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT);
	ReleaseDC( infoPtr->hwndSelf, hdc );
4294
    }
4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307
    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);
        TRACE("rect (%ld,%ld)-(%ld,%ld)\n",
              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
4308 4309 4310 4311

    return 0;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
4312

4313 4314 4315 4316 4317 4318
static LRESULT
REBAR_NotifyFormat (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
    INT i;

    if (lParam == NF_REQUERY) {
4319
	i = SendMessageW(REBAR_GetNotifyParent (infoPtr),
4320
			 WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY);
4321
	if ((i < NFR_ANSI) || (i > NFR_UNICODE)) {
4322
	    ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n", i);
4323 4324 4325 4326 4327 4328 4329 4330 4331
	    i = NFR_ANSI;
	}
	infoPtr->NtfUnicode = (i == NFR_UNICODE) ? 1 : 0;
	return (LRESULT)i;
    }
    return (LRESULT)((infoPtr->bUnicode) ? NFR_UNICODE : NFR_ANSI);
}


Alexandre Julliard's avatar
Alexandre Julliard committed
4332
static LRESULT
4333
REBAR_Paint (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4334
{
4335 4336
    HDC hdc;
    PAINTSTRUCT ps;
4337
    RECT rc;
Alexandre Julliard's avatar
Alexandre Julliard committed
4338

4339 4340
    GetClientRect(infoPtr->hwndSelf, &rc);
    hdc = wParam==0 ? BeginPaint (infoPtr->hwndSelf, &ps) : (HDC)wParam;
4341

4342
    TRACE("painting (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n",
4343
	  ps.rcPaint.left, ps.rcPaint.top,
4344 4345
	  ps.rcPaint.right, ps.rcPaint.bottom,
	  rc.left, rc.top, rc.right, rc.bottom);
4346

4347 4348
    if (ps.fErase) {
	/* Erase area of paint if requested */
4349
        REBAR_InternalEraseBkGnd (infoPtr, wParam, lParam, &ps.rcPaint);
4350 4351
    }

4352
    REBAR_Refresh (infoPtr, hdc);
Alexandre Julliard's avatar
Alexandre Julliard committed
4353
    if (!wParam)
4354
	EndPaint (infoPtr->hwndSelf, &ps);
Alexandre Julliard's avatar
Alexandre Julliard committed
4355 4356 4357 4358
    return 0;
}


Eric Kohl's avatar
Eric Kohl committed
4359
static LRESULT
4360
REBAR_SetCursor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4361
{
4362 4363
    POINT pt;
    UINT  flags;
Eric Kohl's avatar
Eric Kohl committed
4364

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

4367
    GetCursorPos (&pt);
4368
    ScreenToClient (infoPtr->hwndSelf, &pt);
Eric Kohl's avatar
Eric Kohl committed
4369

4370
    REBAR_InternalHitTest (infoPtr, &pt, &flags, NULL);
Eric Kohl's avatar
Eric Kohl committed
4371 4372

    if (flags == RBHT_GRABBER) {
4373 4374
	if ((infoPtr->dwStyle & CCS_VERT) &&
	    !(infoPtr->dwStyle & RBS_VERTICALGRIPPER))
4375
	    SetCursor (infoPtr->hcurVert);
Eric Kohl's avatar
Eric Kohl committed
4376
	else
4377
	    SetCursor (infoPtr->hcurHorz);
Eric Kohl's avatar
Eric Kohl committed
4378 4379
    }
    else if (flags != RBHT_CLIENT)
4380
	SetCursor (infoPtr->hcurArrow);
Eric Kohl's avatar
Eric Kohl committed
4381 4382 4383 4384 4385 4386

    return 0;
}


static LRESULT
4387
REBAR_SetFont (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4388
{
4389 4390 4391
    RECT rcClient;
    REBAR_BAND *lpBand;
    UINT i;
Eric Kohl's avatar
Eric Kohl committed
4392

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

4395 4396 4397
    /* revalidate all bands to change sizes of text in headers of bands */
    for (i=0; i<infoPtr->uNumBands; i++) {
        lpBand = &infoPtr->bands[i];
4398
	REBAR_ValidateBand (infoPtr, lpBand);
4399 4400 4401
    }


4402
    if (LOWORD(lParam)) {
4403 4404
        GetClientRect (infoPtr->hwndSelf, &rcClient);
        REBAR_Layout (infoPtr, &rcClient, FALSE, TRUE);
Eric Kohl's avatar
Eric Kohl committed
4405 4406 4407 4408 4409
    }

    return 0;
}

4410

4411 4412
inline static LRESULT
REBAR_SetRedraw (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4413 4414 4415 4416 4417 4418
     /*****************************************************
      *
      * Function;
      *  Handles the WM_SETREDRAW message.
      *
      * Documentation:
4419
      *  According to testing V4.71 of COMCTL32 returns the
4420 4421 4422 4423 4424 4425 4426
      *  *previous* status of the redraw flag (either 0 or -1)
      *  instead of the MSDN documented value of 0 if handled
      *
      *****************************************************/
{
    BOOL oldredraw = infoPtr->DoRedraw;

4427
    TRACE("set to %s, fStatus=%08x\n",
4428
	  (wParam) ? "TRUE" : "FALSE", infoPtr->fStatus);
4429
    infoPtr->DoRedraw = (BOOL) wParam;
4430 4431 4432 4433 4434 4435 4436 4437 4438
    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;
4439 4440
}

4441

Eric Kohl's avatar
Eric Kohl committed
4442
static LRESULT
4443
REBAR_Size (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Eric Kohl's avatar
Eric Kohl committed
4444
{
4445
    RECT rcClient;
Eric Kohl's avatar
Eric Kohl committed
4446 4447

    /* auto resize deadlock check */
4448 4449
    if (infoPtr->fStatus & AUTO_RESIZE) {
	infoPtr->fStatus &= ~AUTO_RESIZE;
4450 4451
	TRACE("AUTO_RESIZE was set, reset, fStatus=%08x lparam=%08lx\n",
	      infoPtr->fStatus, lParam);
Eric Kohl's avatar
Eric Kohl committed
4452 4453 4454
	return 0;
    }

4455 4456 4457 4458
    if (infoPtr->fStatus & CREATE_RUNNING) {
	/* still in CreateWindow */
	RECT rcWin;

4459 4460 4461 4462 4463
	if ((INT)wParam != SIZE_RESTORED) {
	    ERR("WM_SIZE in create and flags=%08x, lParam=%08lx\n",
		wParam, lParam);
	}

4464 4465 4466
	TRACE("still in CreateWindow\n");
	infoPtr->fStatus &= ~CREATE_RUNNING;
	GetWindowRect ( infoPtr->hwndSelf, &rcWin);
4467
	TRACE("win rect (%ld,%ld)-(%ld,%ld)\n",
4468 4469
	      rcWin.left, rcWin.top, rcWin.right, rcWin.bottom);

4470
	if ((lParam == 0) && (rcWin.right-rcWin.left == 0) &&
4471 4472 4473
	    (rcWin.bottom-rcWin.top == 0)) {
	    /* native control seems to do this */
	    GetClientRect (GetParent(infoPtr->hwndSelf), &rcClient);
4474
	    TRACE("sizing rebar, message and client zero, parent client (%ld,%ld)\n",
4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487
		  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);
4488
	    TRACE("sizing rebar from (%ld,%ld) to (%d,%d), client (%ld,%ld)\n",
4489 4490 4491 4492
		  infoPtr->calcSize.cx, infoPtr->calcSize.cy,
		  LOWORD(lParam), HIWORD(lParam),
		  rcClient.right, rcClient.bottom);
	}
Eric Kohl's avatar
Eric Kohl committed
4493 4494
    }
    else {
4495 4496 4497 4498 4499
	if ((INT)wParam != SIZE_RESTORED) {
	    ERR("WM_SIZE out of create and flags=%08x, lParam=%08lx\n",
		wParam, lParam);
	}

4500 4501 4502 4503 4504 4505
	/* 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 */
4506
	    /* native seems to use the current parent width for the size     */
4507
	    infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
4508 4509 4510 4511 4512 4513
	    GetClientRect (GetParent(infoPtr->hwndSelf), &rcClient);
            if (infoPtr->dwStyle & CCS_VERT)
                rcClient.right = 0;
            else
                rcClient.bottom = 0;
	    TRACE("sizing rebar to parent (%ld,%ld) size is zero but AUTOSIZE set\n",
4514 4515 4516
		  rcClient.right, rcClient.bottom);
	}
	else {
4517
	    TRACE("sizing rebar from (%ld,%ld) to (%d,%d), client (%ld,%ld)\n",
4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530
		  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);
4531
	TRACE("RBN_AUTOSIZE client=(%ld,%ld), lp=%08lx\n",
4532
	      autosize.rcTarget.right, autosize.rcTarget.bottom, lParam);
Eric Kohl's avatar
Eric Kohl committed
4533 4534
    }

4535 4536 4537 4538 4539
    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
4540 4541 4542 4543

    return 0;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
4544

4545 4546 4547 4548 4549 4550 4551
static LRESULT
REBAR_StyleChanged (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
    STYLESTRUCT *ss = (STYLESTRUCT *)lParam;

    TRACE("current style=%08lx, styleOld=%08lx, style being set to=%08lx\n",
	  infoPtr->dwStyle, ss->styleOld, ss->styleNew);
4552 4553 4554
    infoPtr->orgStyle = infoPtr->dwStyle = ss->styleNew;
    if (GetWindowTheme (infoPtr->hwndSelf))
        infoPtr->dwStyle &= ~WS_BORDER;
4555

4556 4557 4558
    return FALSE;
}

4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570
/* 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;
}
4571

4572 4573 4574 4575 4576 4577 4578 4579 4580 4581
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;
4582
    ret = DefWindowProcW(infoPtr->hwndSelf, WM_WINDOWPOSCHANGED,
4583 4584
			 wParam, lParam);
    GetWindowRect(infoPtr->hwndSelf, &rc);
4585
    TRACE("hwnd %p new pos (%ld,%ld)-(%ld,%ld)\n",
4586 4587 4588 4589 4590
	  infoPtr->hwndSelf, rc.left, rc.top, rc.right, rc.bottom);
    return ret;
}


4591
static LRESULT WINAPI
4592
REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4593
{
4594 4595
    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);

4596
    TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n",
4597
	  hwnd, uMsg, wParam, lParam);
4598
    if (!infoPtr && (uMsg != WM_NCCREATE))
4599
        return DefWindowProcW (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4600 4601
    switch (uMsg)
    {
4602
/*	case RB_BEGINDRAG: */
Alexandre Julliard's avatar
Alexandre Julliard committed
4603 4604

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

4607 4608
/*	case RB_DRAGMOVE: */
/*	case RB_ENDDRAG: */
4609 4610

	case RB_GETBANDBORDERS:
4611
	    return REBAR_GetBandBorders (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4612 4613

	case RB_GETBANDCOUNT:
4614
	    return REBAR_GetBandCount (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
4615

4616
	case RB_GETBANDINFO_OLD:
4617
	case RB_GETBANDINFOA:
4618
	    return REBAR_GetBandInfoA (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4619

4620
	case RB_GETBANDINFOW:
4621
	    return REBAR_GetBandInfoW (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4622 4623

	case RB_GETBARHEIGHT:
4624
	    return REBAR_GetBarHeight (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4625 4626

	case RB_GETBARINFO:
4627
	    return REBAR_GetBarInfo (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4628 4629

	case RB_GETBKCOLOR:
4630
	    return REBAR_GetBkColor (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
4631

4632 4633
/*	case RB_GETCOLORSCHEME: */
/*	case RB_GETDROPTARGET: */
Eric Kohl's avatar
Eric Kohl committed
4634 4635

	case RB_GETPALETTE:
4636
	    return REBAR_GetPalette (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4637 4638

	case RB_GETRECT:
4639
	    return REBAR_GetRect (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4640 4641

	case RB_GETROWCOUNT:
4642
	    return REBAR_GetRowCount (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
4643 4644

	case RB_GETROWHEIGHT:
4645
	    return REBAR_GetRowHeight (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4646 4647

	case RB_GETTEXTCOLOR:
4648
	    return REBAR_GetTextColor (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
4649

Eric Kohl's avatar
Eric Kohl committed
4650
	case RB_GETTOOLTIPS:
4651
	    return REBAR_GetToolTips (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
4652

Eric Kohl's avatar
Eric Kohl committed
4653
	case RB_GETUNICODEFORMAT:
4654
	    return REBAR_GetUnicodeFormat (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
4655

Eric Kohl's avatar
Eric Kohl committed
4656
	case CCM_GETVERSION:
4657
	    return REBAR_GetVersion (infoPtr);
Eric Kohl's avatar
Eric Kohl committed
4658

Eric Kohl's avatar
Eric Kohl committed
4659
	case RB_HITTEST:
4660
	    return REBAR_HitTest (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4661 4662

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

4665
	case RB_INSERTBANDA:
4666
	    return REBAR_InsertBandA (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4667

4668
	case RB_INSERTBANDW:
4669
	    return REBAR_InsertBandW (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4670

4671
	case RB_MAXIMIZEBAND:
4672
	    return REBAR_MaximizeBand (infoPtr, wParam, lParam);
4673 4674

	case RB_MINIMIZEBAND:
4675
	    return REBAR_MinimizeBand (infoPtr, wParam, lParam);
4676 4677

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

Robert Shearman's avatar
Robert Shearman committed
4680 4681 4682
	case RB_PUSHCHEVRON:
	    return REBAR_PushChevron (infoPtr, wParam, lParam);

4683
	case RB_SETBANDINFOA:
4684
	    return REBAR_SetBandInfoA (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4685

4686
	case RB_SETBANDINFOW:
4687
	    return REBAR_SetBandInfoW (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4688 4689

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

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

4695 4696
/*	case RB_SETCOLORSCHEME: */
/*	case RB_SETPALETTE: */
4697
/*	    return REBAR_GetPalette (infoPtr, wParam, lParam); */
Eric Kohl's avatar
Eric Kohl committed
4698 4699

	case RB_SETPARENT:
4700
	    return REBAR_SetParent (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4701 4702

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

4705
/*	case RB_SETTOOLTIPS: */
Eric Kohl's avatar
Eric Kohl committed
4706 4707

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

Eric Kohl's avatar
Eric Kohl committed
4710
	case CCM_SETVERSION:
4711
	    return REBAR_SetVersion (infoPtr, (INT)wParam);
Eric Kohl's avatar
Eric Kohl committed
4712

Alexandre Julliard's avatar
Alexandre Julliard committed
4713
	case RB_SHOWBAND:
4714
	    return REBAR_ShowBand (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4715 4716

	case RB_SIZETORECT:
4717
	    return REBAR_SizeToRect (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4718 4719


4720
/*    Messages passed to parent */
4721
	case WM_COMMAND:
4722 4723
	case WM_DRAWITEM:
	case WM_NOTIFY:
4724 4725 4726 4727 4728 4729
	    if (infoPtr->NtfUnicode)
		return SendMessageW (REBAR_GetNotifyParent (infoPtr),
				     uMsg, wParam, lParam);
	    else
		return SendMessageA (REBAR_GetNotifyParent (infoPtr),
				     uMsg, wParam, lParam);
4730

4731 4732 4733

/*      case WM_CHARTOITEM:     supported according to ControlSpy */

Alexandre Julliard's avatar
Alexandre Julliard committed
4734
	case WM_CREATE:
4735
	    return REBAR_Create (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4736

Alexandre Julliard's avatar
Alexandre Julliard committed
4737
	case WM_DESTROY:
4738
	    return REBAR_Destroy (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4739

4740
        case WM_ERASEBKGND:
4741
	    return REBAR_EraseBkGnd (infoPtr, wParam, lParam);
4742

Eric Kohl's avatar
Eric Kohl committed
4743
	case WM_GETFONT:
4744
	    return REBAR_GetFont (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4745

4746 4747
/*      case WM_LBUTTONDBLCLK:  supported according to ControlSpy */

4748
	case WM_LBUTTONDOWN:
4749
	    return REBAR_LButtonDown (infoPtr, wParam, lParam);
4750 4751

	case WM_LBUTTONUP:
4752
	    return REBAR_LButtonUp (infoPtr, wParam, lParam);
4753

4754 4755
/*      case WM_MEASUREITEM:    supported according to ControlSpy */

4756
	case WM_MOUSEMOVE:
4757
	    return REBAR_MouseMove (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4758

Robert Shearman's avatar
Robert Shearman committed
4759 4760 4761
	case WM_MOUSELEAVE:
	    return REBAR_MouseLeave (infoPtr, wParam, lParam);

Eric Kohl's avatar
Eric Kohl committed
4762
	case WM_NCCALCSIZE:
4763
	    return REBAR_NCCalcSize (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4764

4765 4766 4767 4768 4769
        case WM_NCCREATE:
	    return REBAR_NCCreate (hwnd, wParam, lParam);

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

Eric Kohl's avatar
Eric Kohl committed
4771
	case WM_NCPAINT:
4772
	    return REBAR_NCPaint (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4773

4774 4775
        case WM_NOTIFYFORMAT:
	    return REBAR_NotifyFormat (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4776

4777
	case WM_PRINTCLIENT:
Alexandre Julliard's avatar
Alexandre Julliard committed
4778
	case WM_PAINT:
4779
	    return REBAR_Paint (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4780

4781 4782 4783 4784 4785
/*      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
4786
	case WM_SETCURSOR:
4787
	    return REBAR_SetCursor (infoPtr, wParam, lParam);
Eric Kohl's avatar
Eric Kohl committed
4788 4789

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

4792 4793
        case WM_SETREDRAW:
	    return REBAR_SetRedraw (infoPtr, wParam, lParam);
4794

Eric Kohl's avatar
Eric Kohl committed
4795
	case WM_SIZE:
4796
	    return REBAR_Size (infoPtr, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4797

4798 4799 4800
        case WM_STYLECHANGED:
	    return REBAR_StyleChanged (infoPtr, wParam, lParam);

4801 4802 4803
        case WM_THEMECHANGED:
            return theme_changed (infoPtr);

4804
/*      case WM_SYSCOLORCHANGE: supported according to ControlSpy */
4805
/*      "Applications that have brushes using the existing system colors
4806
         should delete those brushes and recreate them using the new
4807 4808
         system colors."  per MSDN                                */

4809
/*      case WM_VKEYTOITEM:     supported according to ControlSpy */
4810
/*	case WM_WININICHANGE: */
Alexandre Julliard's avatar
Alexandre Julliard committed
4811

4812 4813 4814
        case WM_WINDOWPOSCHANGED:
	    return REBAR_WindowPosChanged (infoPtr, wParam, lParam);

Alexandre Julliard's avatar
Alexandre Julliard committed
4815
	default:
4816
	    if ((uMsg >= WM_USER) && (uMsg < WM_APP))
4817
		ERR("unknown msg %04x wp=%08x lp=%08lx\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
4818
		     uMsg, wParam, lParam);
4819
	    return DefWindowProcW (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4820 4821 4822 4823
    }
}


Eric Kohl's avatar
Eric Kohl committed
4824
VOID
4825
REBAR_Register (void)
Alexandre Julliard's avatar
Alexandre Julliard committed
4826
{
4827
    WNDCLASSW wndClass;
Alexandre Julliard's avatar
Alexandre Julliard committed
4828

4829
    ZeroMemory (&wndClass, sizeof(WNDCLASSW));
Alexandre Julliard's avatar
Alexandre Julliard committed
4830
    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
4831
    wndClass.lpfnWndProc   = REBAR_WindowProc;
Alexandre Julliard's avatar
Alexandre Julliard committed
4832 4833
    wndClass.cbClsExtra    = 0;
    wndClass.cbWndExtra    = sizeof(REBAR_INFO *);
Alexandre Julliard's avatar
Alexandre Julliard committed
4834
    wndClass.hCursor       = 0;
4835
    wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
4836 4837 4838
#if GLATESTING
    wndClass.hbrBackground = CreateSolidBrush(RGB(0,128,0));
#endif
4839
    wndClass.lpszClassName = REBARCLASSNAMEW;
4840

4841
    RegisterClassW (&wndClass);
4842 4843 4844 4845

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

Alexandre Julliard's avatar
Alexandre Julliard committed
4846 4847
}

Eric Kohl's avatar
Eric Kohl committed
4848 4849

VOID
4850
REBAR_Unregister (void)
Eric Kohl's avatar
Eric Kohl committed
4851
{
4852
    UnregisterClassW (REBARCLASSNAMEW, NULL);
Eric Kohl's avatar
Eric Kohl committed
4853
}