Include stdio.h for MinGW.
[wine] / dlls / comctl32 / rebar.c
1 /*
2  * Testing: set to 1 to make background brush *always* green
3  */
4 #define GLATESTING 0
5
6 /*
7  *
8  * 2.  At "FIXME:  problem # 2" WinRAR:
9  *   if "#if 1" then last band draws in separate row
10  *   if "#if 0" then last band draws in previous row *** just like native ***
11  *
12  */
13 #define PROBLEM2 0
14
15 /*
16  * 3. REBAR_MoveChildWindows should have a loop because more than
17  *    one pass is made (together with the RBN_CHILDSIZEs) is made on
18  *    at least RB_INSERTBAND
19  */
20
21
22 /*
23  * Rebar control    rev 8e
24  *
25  * Copyright 1998, 1999 Eric Kohl
26  *
27  * This library is free software; you can redistribute it and/or
28  * modify it under the terms of the GNU Lesser General Public
29  * License as published by the Free Software Foundation; either
30  * version 2.1 of the License, or (at your option) any later version.
31  *
32  * This library is distributed in the hope that it will be useful,
33  * but WITHOUT ANY WARRANTY; without even the implied warranty of
34  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
35  * Lesser General Public License for more details.
36  *
37  * You should have received a copy of the GNU Lesser General Public
38  * License along with this library; if not, write to the Free Software
39  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
40  *
41  * NOTES
42  *   An author is needed! Any volunteers?
43  *   I will only improve this control once in a while.
44  *     Eric <ekohl@abo.rhein-zeitung.de>
45  *
46  * TODO:
47  *   - vertical placement
48  *   - ComboBox and ComboBoxEx placement
49  *   - center image
50  *   - Layout code.
51  *   - Display code.
52  *   - Some messages.
53  *   - All notifications.
54
55  * Changes Guy Albertelli <galberte@neo.lrun.com>
56  *  rev 2,3,4
57  *   - Implement initial version of row grouping, row separators,
58  *     text and background colors. Support additional messages.
59  *     Support RBBS_BREAK. Implement ERASEBKGND and improve painting.
60  *  rev 5
61  *   - implement support for dragging Gripper left or right in a row. Supports
62  *     WM_LBUTTONDOWN, WM_LBUTTONUP, and WM_MOUSEMOVE. Also support
63  *     RBS_BANDBORDERS.
64  *  rev 6
65  *   - Fix or implement notifications for RBN_HEIGHTCHANGE, RBN_CHILDSIZE.
66  *   - Correct styles RBBS_NOGRIPPER, RBBS_GRIPPERALWAYS, and RBBS_FIXEDSIZE.
67  *   - Fix algorithm for Layout and AdjustBand.
68  *
69  * rev 7
70  *   - Fix algorithm for _Layout and _AdjustBand.
71  *   - Fix or implement RBN_ENDDRAG, RB_MOVEBAND, WM_SETREDRAW,
72  *     WM_STYLECHANGED, RB_MINIMIZEBAND, RBBS_VARIABLEHEIGHT, RBS_VARHEIGHT,
73  *     RBBS_HIDDEN, WM_NOTIFYFORMAT, NM_NCHITTEST, WM_SETREDRAW, RBS_AUTOSIZE,
74  *     WM_SETFONT, RBS_BORDERS
75  *   - Create structures in WM_NCCREATE
76  *   - Additional performance enhancements.
77  *
78  * rev 8
79  *  1. Create array of start and end band indexes by row and use.
80  *  2. Fix problem with REBAR_Layout Phase 2b to process only if only
81  *     band in row.
82  *  3. Set the Caption Font (Regular) as default font for text.
83  *  4. Delete font handle on control distruction.
84  *  5. Add UpdateWindow call in _MoveChildWindows to match repainting done
85  *     by native control
86  *  6. Improve some traces.
87  *  7. Invalidate window rectangles after SetBandInfo, InsertBand, ShowBand
88  *     so that repainting is correct.
89  *  8. Implement RB_MAXIMIZEBAND for the "ideal=TRUE" case.
90  *  9. Implement item custom draw notifications partially. Only done for
91  *     ITEMPREPAINT and ITEMPOSTPAINT. (Used by IE4 for "Favorites" frame
92  *     to draw the word "Favorites").
93  * rev 8a
94  * 10. Handle CCS_NODIVIDER and fix WS_BORDER code.
95  * 11. Fix logic error in _AdjustBands where flag was set to valid band
96  *     number (0) to indicate *no* band.
97  * 12. Fix CCS_VERT errors in _ForceResize, _NCCalcSize, and _NCPaint.
98  * 13. Support some special cases of CCS_TOP (and therefore CCS_LEFT),
99  *     CCS_BOTTOM (and therefore CCS_RIGHT) and CCS_NOPARENTALIGN. Not
100  *     at all sure whether this is all cases.
101  * 14. Handle returned value for the RBN_CHILDSIZE notify.
102  * 15. Implement RBBS_CHILDEDGE, and set each bands "offChild" at _Layout
103  *     time.
104  * 16. Fix REBARSPACE. It should depend on CCS_NODIVIDER.
105  * rev 8b
106  * 17. Fix determination of whether Gripper is needed in _ValidateBand.
107  * 18. Fix _AdjustBand processing of RBBS_FIXEDSIZE.
108  * rev 8c
109  * 19. Fix problem in _Layout when all lengths are 0.
110  * 20. If CLR_NONE specified, we will use default BtnFace color when drawing.
111  * 21. Fix test in REBAR_Layout.
112  * rev 8d
113  * 22. Add support for WM_WINDOWPOSCHANGED to save new origin of window.
114  * 23. Correct RBN_CHILDSIZE rect value for CCS_VERT rebar.
115  * 24. Do UpdateWindow only if doing redraws.
116  * rev 8e
117  * 25. Adjust setting of offChild.cx based on RBBS_CHILDEDGE.
118  *
119  *
120  *    Still to do:
121  *  2. Following still not handled: RBBS_FIXEDBMP,
122  *            CCS_NORESIZE,
123  *            CCS_NOMOVEX, CCS_NOMOVEY
124  *  3. Following are only partially handled:
125  *            RBS_AUTOSIZE, RBBS_VARIABLEHEIGHT
126  *  5. Native uses (on each draw!!) SM_CYBORDER (or SM_CXBORDER for CCS_VERT)
127  *     to set the size of the separator width (the value SEP_WIDTH_SIZE
128  *     in here). Should be fixed!!
129  *  6. The following messages are not implemented:
130  *        RB_BEGINDRAG, RB_DRAGMOVE, RB_ENDDRAG, RB_GETCOLORSCHEME,
131  *        RB_GETDROPTARGET, RB_MAXIMIZEBAND,
132  *        RB_SETCOLORSCHEME, RB_SETPALETTE, RB_SETTOOLTIPS
133  *        WM_CHARTOITEM, WM_LBUTTONDBLCLK, WM_MEASUREITEM,
134  *        WM_PALETTECHANGED, WM_PRINTCLIENT, WM_QUERYNEWPALETTE,
135  *        WM_RBUTTONDOWN, WM_RBUTTONUP,
136  *        WM_SYSCOLORCHANGE, WM_VKEYTOITEM, WM_WININICHANGE
137  *  7. The following notifications are not implemented:
138  *        NM_CUSTOMDRAW, NM_RELEASEDCAPTURE
139  *        RBN_MINMAX
140  */
141
142 #include <stdarg.h>
143 #include <stdlib.h>
144 #include <string.h>
145
146 #include "windef.h"
147 #include "winbase.h"
148 #include "wingdi.h"
149 #include "wine/unicode.h"
150 #include "winuser.h"
151 #include "winnls.h"
152 #include "commctrl.h"
153 #include "comctl32.h"
154 #include "wine/debug.h"
155
156 WINE_DEFAULT_DEBUG_CHANNEL(rebar);
157
158 typedef struct
159 {
160     UINT    fStyle;
161     UINT    fMask;
162     COLORREF  clrFore;
163     COLORREF  clrBack;
164     INT     iImage;
165     HWND    hwndChild;
166     UINT    cxMinChild;     /* valid if _CHILDSIZE */
167     UINT    cyMinChild;     /* valid if _CHILDSIZE */
168     UINT    cx;             /* valid if _SIZE */
169     HBITMAP hbmBack;
170     UINT    wID;
171     UINT    cyChild;        /* valid if _CHILDSIZE */
172     UINT    cyMaxChild;     /* valid if _CHILDSIZE */
173     UINT    cyIntegral;     /* valid if _CHILDSIZE */
174     UINT    cxIdeal;
175     LPARAM    lParam;
176     UINT    cxHeader;
177
178     UINT    lcx;            /* minimum cx for band */
179     UINT    ccx;            /* current cx for band */
180     UINT    hcx;            /* maximum cx for band */
181     UINT    lcy;            /* minimum cy for band */
182     UINT    ccy;            /* current cy for band */
183     UINT    hcy;            /* maximum cy for band */
184
185     SIZE    offChild;       /* x,y offset if child is not FIXEDSIZE */
186     UINT    uMinHeight;
187     INT     iRow;           /* row this band assigned to */
188     UINT    fStatus;        /* status flags, reset only by _Validate */
189     UINT    fDraw;          /* drawing flags, reset only by _Layout */
190     UINT    uCDret;         /* last return from NM_CUSTOMDRAW */
191     RECT    rcoldBand;      /* previous calculated band rectangle */
192     RECT    rcBand;         /* calculated band rectangle */
193     RECT    rcGripper;      /* calculated gripper rectangle */
194     RECT    rcCapImage;     /* calculated caption image rectangle */
195     RECT    rcCapText;      /* calculated caption text rectangle */
196     RECT    rcChild;        /* calculated child rectangle */
197     RECT    rcChevron;      /* calculated chevron rectangle */
198
199     LPWSTR    lpText;
200     HWND    hwndPrevParent;
201 } REBAR_BAND;
202
203 /* fStatus flags */
204 #define HAS_GRIPPER    0x00000001
205 #define HAS_IMAGE      0x00000002
206 #define HAS_TEXT       0x00000004
207
208 /* fDraw flags */
209 #define DRAW_GRIPPER    0x00000001
210 #define DRAW_IMAGE      0x00000002
211 #define DRAW_TEXT       0x00000004
212 #define DRAW_RIGHTSEP   0x00000010
213 #define DRAW_BOTTOMSEP  0x00000020
214 #define DRAW_CHEVRONHOT 0x00000040
215 #define DRAW_CHEVRONPUSHED 0x00000080
216 #define DRAW_LAST_IN_ROW   0x00000100
217 #define DRAW_FIRST_IN_ROW  0x00000200
218 #define NTF_INVALIDATE  0x01000000
219
220 typedef struct
221 {
222     COLORREF   clrBk;       /* background color */
223     COLORREF   clrText;     /* text color */
224     COLORREF   clrBtnText;  /* system color for BTNTEXT */
225     COLORREF   clrBtnFace;  /* system color for BTNFACE */
226     HIMAGELIST himl;        /* handle to imagelist */
227     UINT     uNumBands;   /* # of bands in rebar (first=0, last=uNumBands-1 */
228     UINT     uNumRows;    /* # of rows of bands (first=1, last=uNumRows */
229     HWND     hwndSelf;    /* handle of REBAR window itself */
230     HWND     hwndToolTip; /* handle to the tool tip control */
231     HWND     hwndNotify;  /* notification window (parent) */
232     HFONT    hDefaultFont;
233     HFONT    hFont;       /* handle to the rebar's font */
234     SIZE     imageSize;   /* image size (image list) */
235     DWORD    dwStyle;     /* window style */
236     SIZE     calcSize;    /* calculated rebar size */
237     SIZE     oldSize;     /* previous calculated rebar size */
238     BOOL     bUnicode;    /* TRUE if this window is W type */
239     BOOL     NtfUnicode;  /* TRUE if parent wants notify in W format */
240     BOOL     DoRedraw;    /* TRUE to acutally draw bands */
241     UINT     fStatus;     /* Status flags (see below)  */
242     HCURSOR  hcurArrow;   /* handle to the arrow cursor */
243     HCURSOR  hcurHorz;    /* handle to the EW cursor */
244     HCURSOR  hcurVert;    /* handle to the NS cursor */
245     HCURSOR  hcurDrag;    /* handle to the drag cursor */
246     INT      iVersion;    /* version number */
247     POINTS   dragStart;   /* x,y of button down */
248     POINTS   dragNow;     /* x,y of this MouseMove */
249     INT      iOldBand;    /* last band that had the mouse cursor over it */
250     INT      ihitoffset;  /* offset of hotspot from gripper.left */
251     POINT    origin;      /* left/upper corner of client */
252     INT      ichevronhotBand; /* last band that had a hot chevron */
253     INT      iGrabbedBand;/* band number of band whose gripper was grabbed */
254
255     REBAR_BAND *bands;      /* pointer to the array of rebar bands */
256 } REBAR_INFO;
257
258 /* fStatus flags */
259 #define BEGIN_DRAG_ISSUED   0x00000001
260 #define AUTO_RESIZE         0x00000002
261 #define RESIZE_ANYHOW       0x00000004
262 #define NTF_HGHTCHG         0x00000008
263 #define BAND_NEEDS_LAYOUT   0x00000010
264 #define BAND_NEEDS_REDRAW   0x00000020
265 #define CREATE_RUNNING      0x00000040
266
267 /* ----   REBAR layout constants. Mostly determined by        ---- */
268 /* ----   experiment on WIN 98.                               ---- */
269
270 /* Width (or height) of separators between bands (either horz. or  */
271 /* vert.). True only if RBS_BANDBORDERS is set                     */
272 #define SEP_WIDTH_SIZE  2
273 #define SEP_WIDTH       ((infoPtr->dwStyle & RBS_BANDBORDERS) ? SEP_WIDTH_SIZE : 0)
274
275 /* Blank (background color) space between Gripper (if present)     */
276 /* and next item (image, text, or window). Always present          */
277 #define REBAR_ALWAYS_SPACE  4
278
279 /* Blank (background color) space after Image (if present).        */
280 #define REBAR_POST_IMAGE  2
281
282 /* Blank (background color) space after Text (if present).         */
283 #define REBAR_POST_TEXT  4
284
285 /* Height of vertical gripper in a CCS_VERT rebar.                 */
286 #define GRIPPER_HEIGHT  16
287
288 /* Blank (background color) space before Gripper (if present).     */
289 #define REBAR_PRE_GRIPPER   2
290
291 /* Width (of normal vertical gripper) or height (of horz. gripper) */
292 /* if present.                                                     */
293 #define GRIPPER_WIDTH  3
294
295 /* Width of the chevron button if present */
296 #define CHEVRON_WIDTH  10
297
298 /* Height of divider for Rebar if not disabled (CCS_NODIVIDER)     */
299 /* either top or bottom                                            */
300 #define REBAR_DIVIDER  2
301
302 /* minimium vertical height of a normal bar                        */
303 /*   or minimum width of a CCS_VERT bar - from experiment on Win2k */
304 #define REBAR_MINSIZE  23
305
306 /* This is the increment that is used over the band height         */
307 #define REBARSPACE(a)     ((a->fStyle & RBBS_CHILDEDGE) ? 2*REBAR_DIVIDER : 0)
308
309 /* ----   End of REBAR layout constants.                      ---- */
310
311 #define RB_GETBANDINFO_OLD (WM_USER+5) /* obsoleted after IE3, but we have to support it anyway */
312
313 /*  The following 6 defines return the proper rcBand element       */
314 /*  depending on whether CCS_VERT was set.                         */
315 #define rcBlt(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.top : b->rcBand.left)
316 #define rcBrb(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.bottom : b->rcBand.right)
317 #define rcBw(b)  ((infoPtr->dwStyle & CCS_VERT) ? (b->rcBand.bottom - b->rcBand.top) : \
318                   (b->rcBand.right - b->rcBand.left))
319 #define ircBlt(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.left : b->rcBand.top)
320 #define ircBrb(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.right : b->rcBand.bottom)
321 #define ircBw(b)  ((infoPtr->dwStyle & CCS_VERT) ? (b->rcBand.right - b->rcBand.left) : \
322                   (b->rcBand.bottom - b->rcBand.top))
323
324 /*  The following define determines if a given band is hidden      */
325 #define HIDDENBAND(a)  (((a)->fStyle & RBBS_HIDDEN) ||   \
326                         ((infoPtr->dwStyle & CCS_VERT) &&         \
327                          ((a)->fStyle & RBBS_NOVERT)))
328
329 /*  The following defines adjust the right or left end of a rectangle */
330 #define READJ(b,i) do { if(infoPtr->dwStyle & CCS_VERT) b->rcBand.bottom+=(i); \
331                     else b->rcBand.right += (i); } while(0)
332 #define LEADJ(b,i) do { if(infoPtr->dwStyle & CCS_VERT) b->rcBand.top+=(i); \
333                     else b->rcBand.left += (i); } while(0)
334
335
336 #define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongPtrW (hwnd, 0))
337
338
339 /* "constant values" retrieved when DLL was initialized    */
340 /* FIXME we do this when the classes are registered.       */
341 static UINT mindragx = 0;
342 static UINT mindragy = 0;
343
344 static const char *band_stylename[] = {
345     "RBBS_BREAK",              /* 0001 */
346     "RBBS_FIXEDSIZE",          /* 0002 */
347     "RBBS_CHILDEDGE",          /* 0004 */
348     "RBBS_HIDDEN",             /* 0008 */
349     "RBBS_NOVERT",             /* 0010 */
350     "RBBS_FIXEDBMP",           /* 0020 */
351     "RBBS_VARIABLEHEIGHT",     /* 0040 */
352     "RBBS_GRIPPERALWAYS",      /* 0080 */
353     "RBBS_NOGRIPPER",          /* 0100 */
354     NULL };
355
356 static const char *band_maskname[] = {
357     "RBBIM_STYLE",         /*    0x00000001 */
358     "RBBIM_COLORS",        /*    0x00000002 */
359     "RBBIM_TEXT",          /*    0x00000004 */
360     "RBBIM_IMAGE",         /*    0x00000008 */
361     "RBBIM_CHILD",         /*    0x00000010 */
362     "RBBIM_CHILDSIZE",     /*    0x00000020 */
363     "RBBIM_SIZE",          /*    0x00000040 */
364     "RBBIM_BACKGROUND",    /*    0x00000080 */
365     "RBBIM_ID",            /*    0x00000100 */
366     "RBBIM_IDEALSIZE",     /*    0x00000200 */
367     "RBBIM_LPARAM",        /*    0x00000400 */
368     "RBBIM_HEADERSIZE",    /*    0x00000800 */
369     NULL };
370
371
372 static CHAR line[200];
373
374
375 static CHAR *
376 REBAR_FmtStyle( UINT style)
377 {
378     INT i = 0;
379
380     *line = 0;
381     while (band_stylename[i]) {
382         if (style & (1<<i)) {
383             if (*line != 0) strcat(line, " | ");
384             strcat(line, band_stylename[i]);
385         }
386         i++;
387     }
388     return line;
389 }
390
391
392 static CHAR *
393 REBAR_FmtMask( UINT mask)
394 {
395     INT i = 0;
396
397     *line = 0;
398     while (band_maskname[i]) {
399         if (mask & (1<<i)) {
400             if (*line != 0) strcat(line, " | ");
401             strcat(line, band_maskname[i]);
402         }
403         i++;
404     }
405     return line;
406 }
407
408
409 static VOID
410 REBAR_DumpBandInfo( LPREBARBANDINFOA pB)
411 {
412     if( !TRACE_ON(rebar) ) return;
413     TRACE("band info: ID=%u, size=%u, child=%p, clrF=0x%06lx, clrB=0x%06lx\n",
414           pB->wID, pB->cbSize, pB->hwndChild, pB->clrFore, pB->clrBack);
415     TRACE("band info: mask=0x%08x (%s)\n", pB->fMask, REBAR_FmtMask(pB->fMask));
416     if (pB->fMask & RBBIM_STYLE)
417         TRACE("band info: style=0x%08x (%s)\n", pB->fStyle, REBAR_FmtStyle(pB->fStyle));
418     if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_HEADERSIZE | RBBIM_LPARAM )) {
419         TRACE("band info:");
420         if (pB->fMask & RBBIM_SIZE)
421             TRACE(" cx=%u", pB->cx);
422         if (pB->fMask & RBBIM_IDEALSIZE)
423             TRACE(" xIdeal=%u", pB->cxIdeal);
424         if (pB->fMask & RBBIM_HEADERSIZE)
425             TRACE(" xHeader=%u", pB->cxHeader);
426         if (pB->fMask & RBBIM_LPARAM)
427             TRACE(" lParam=0x%08lx", pB->lParam);
428         TRACE("\n");
429     }
430     if (pB->fMask & RBBIM_CHILDSIZE)
431         TRACE("band info: xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
432               pB->cxMinChild,
433               pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
434 }
435
436 static VOID
437 REBAR_DumpBand (REBAR_INFO *iP)
438 {
439     REBAR_BAND *pB;
440     UINT i;
441
442     if(! TRACE_ON(rebar) ) return;
443
444     TRACE("hwnd=%p: color=%08lx/%08lx, bands=%u, rows=%u, cSize=%ld,%ld\n",
445           iP->hwndSelf, iP->clrText, iP->clrBk, iP->uNumBands, iP->uNumRows,
446           iP->calcSize.cx, iP->calcSize.cy);
447     TRACE("hwnd=%p: flags=%08x, dragStart=%d,%d, dragNow=%d,%d, iGrabbedBand=%d\n",
448           iP->hwndSelf, iP->fStatus, iP->dragStart.x, iP->dragStart.y,
449           iP->dragNow.x, iP->dragNow.y,
450           iP->iGrabbedBand);
451     TRACE("hwnd=%p: style=%08lx, I'm Unicode=%s, notify in Unicode=%s, redraw=%s\n",
452           iP->hwndSelf, iP->dwStyle, (iP->bUnicode)?"TRUE":"FALSE",
453           (iP->NtfUnicode)?"TRUE":"FALSE", (iP->DoRedraw)?"TRUE":"FALSE");
454     for (i = 0; i < iP->uNumBands; i++) {
455         pB = &iP->bands[i];
456         TRACE("band # %u: ID=%u, child=%p, row=%u, clrF=0x%06lx, clrB=0x%06lx\n",
457               i, pB->wID, pB->hwndChild, pB->iRow, pB->clrFore, pB->clrBack);
458         TRACE("band # %u: mask=0x%08x (%s)\n", i, pB->fMask, REBAR_FmtMask(pB->fMask));
459         if (pB->fMask & RBBIM_STYLE)
460             TRACE("band # %u: style=0x%08x (%s)\n",
461                   i, pB->fStyle, REBAR_FmtStyle(pB->fStyle));
462         TRACE("band # %u: uMinH=%u xHeader=%u",
463               i, pB->uMinHeight, pB->cxHeader);
464         if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_LPARAM )) {
465             if (pB->fMask & RBBIM_SIZE)
466                 TRACE(" cx=%u", pB->cx);
467             if (pB->fMask & RBBIM_IDEALSIZE)
468                 TRACE(" xIdeal=%u", pB->cxIdeal);
469             if (pB->fMask & RBBIM_LPARAM)
470                 TRACE(" lParam=0x%08lx", pB->lParam);
471         }
472         TRACE("\n");
473         if (RBBIM_CHILDSIZE)
474             TRACE("band # %u: xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
475                   i, pB->cxMinChild, pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
476         if (pB->fMask & RBBIM_TEXT)
477             TRACE("band # %u: text=%s\n",
478                   i, (pB->lpText) ? debugstr_w(pB->lpText) : "(null)");
479         TRACE("band # %u: lcx=%u, ccx=%u, hcx=%u, lcy=%u, ccy=%u, hcy=%u, offChild=%ld,%ld\n",
480               i, pB->lcx, pB->ccx, pB->hcx, pB->lcy, pB->ccy, pB->hcy, pB->offChild.cx, pB->offChild.cy);
481         TRACE("band # %u: fStatus=%08x, fDraw=%08x, Band=(%ld,%ld)-(%ld,%ld), Grip=(%ld,%ld)-(%ld,%ld)\n",
482               i, pB->fStatus, pB->fDraw,
483               pB->rcBand.left, pB->rcBand.top, pB->rcBand.right, pB->rcBand.bottom,
484               pB->rcGripper.left, pB->rcGripper.top, pB->rcGripper.right, pB->rcGripper.bottom);
485         TRACE("band # %u: Img=(%ld,%ld)-(%ld,%ld), Txt=(%ld,%ld)-(%ld,%ld), Child=(%ld,%ld)-(%ld,%ld)\n",
486               i,
487               pB->rcCapImage.left, pB->rcCapImage.top, pB->rcCapImage.right, pB->rcCapImage.bottom,
488               pB->rcCapText.left, pB->rcCapText.top, pB->rcCapText.right, pB->rcCapText.bottom,
489               pB->rcChild.left, pB->rcChild.top, pB->rcChild.right, pB->rcChild.bottom);
490     }
491
492 }
493
494 static void
495 REBAR_DrawChevron (HDC hdc, INT left, INT top, INT colorRef)
496 {
497     INT x, y;
498     HPEN hPen, hOldPen;
499
500     if (!(hPen = CreatePen( PS_SOLID, 1, GetSysColor( colorRef )))) return;
501     hOldPen = SelectObject ( hdc, hPen );
502     x = left + 2;
503     y = top;
504     MoveToEx (hdc, x, y, NULL);
505     LineTo (hdc, x+5, y++); x++;
506     MoveToEx (hdc, x, y, NULL);
507     LineTo (hdc, x+3, y++); x++;
508     MoveToEx (hdc, x, y, NULL);
509     LineTo (hdc, x+1, y++);
510     SelectObject( hdc, hOldPen );
511     DeleteObject( hPen );
512 }
513
514 static HWND
515 REBAR_GetNotifyParent (REBAR_INFO *infoPtr)
516 {
517     HWND parent, owner;
518
519     parent = infoPtr->hwndNotify;
520     if (!parent) {
521         parent = GetParent (infoPtr->hwndSelf);
522         owner = GetWindow (infoPtr->hwndSelf, GW_OWNER);
523         if (owner) parent = owner;
524     }
525     return parent;
526 }
527
528
529 static INT
530 REBAR_Notify (NMHDR *nmhdr, REBAR_INFO *infoPtr, UINT code)
531 {
532     HWND parent;
533
534     parent = REBAR_GetNotifyParent (infoPtr);
535     nmhdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf);
536     nmhdr->hwndFrom = infoPtr->hwndSelf;
537     nmhdr->code = code;
538
539     TRACE("window %p, code=%08x, %s\n", parent, code,
540           (infoPtr->NtfUnicode) ? "via Unicode" : "via ANSI");
541
542     if (infoPtr->NtfUnicode)
543         return SendMessageW (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom,
544                              (LPARAM)nmhdr);
545     else
546         return SendMessageA (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom,
547                              (LPARAM)nmhdr);
548 }
549
550 static INT
551 REBAR_Notify_NMREBAR (REBAR_INFO *infoPtr, UINT uBand, UINT code)
552 {
553     NMREBAR notify_rebar;
554     REBAR_BAND *lpBand;
555
556     notify_rebar.dwMask = 0;
557     if (uBand!=-1) {
558         lpBand = &infoPtr->bands[uBand];
559         if (lpBand->fMask & RBBIM_ID) {
560             notify_rebar.dwMask |= RBNM_ID;
561             notify_rebar.wID = lpBand->wID;
562         }
563         if (lpBand->fMask & RBBIM_LPARAM) {
564             notify_rebar.dwMask |= RBNM_LPARAM;
565             notify_rebar.lParam = lpBand->lParam;
566         }
567         if (lpBand->fMask & RBBIM_STYLE) {
568             notify_rebar.dwMask |= RBNM_STYLE;
569             notify_rebar.fStyle = lpBand->fStyle;
570         }
571     }
572     notify_rebar.uBand = uBand;
573     return REBAR_Notify ((NMHDR *)&notify_rebar, infoPtr, code);
574 }
575
576 static VOID
577 REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
578 {
579     HFONT hOldFont = 0;
580     INT oldBkMode = 0;
581     NMCUSTOMDRAW nmcd;
582
583     if (lpBand->fDraw & DRAW_TEXT) {
584         hOldFont = SelectObject (hdc, infoPtr->hFont);
585         oldBkMode = SetBkMode (hdc, TRANSPARENT);
586     }
587
588     /* should test for CDRF_NOTIFYITEMDRAW here */
589     nmcd.dwDrawStage = CDDS_ITEMPREPAINT;
590     nmcd.hdc = hdc;
591     nmcd.rc = lpBand->rcBand;
592     nmcd.rc.right = lpBand->rcCapText.right;
593     nmcd.rc.bottom = lpBand->rcCapText.bottom;
594     nmcd.dwItemSpec = lpBand->wID;
595     nmcd.uItemState = 0;
596     nmcd.lItemlParam = lpBand->lParam;
597     lpBand->uCDret = REBAR_Notify ((NMHDR *)&nmcd, infoPtr, NM_CUSTOMDRAW);
598     if (lpBand->uCDret == CDRF_SKIPDEFAULT) {
599         if (oldBkMode != TRANSPARENT)
600             SetBkMode (hdc, oldBkMode);
601         SelectObject (hdc, hOldFont);
602         return;
603     }
604
605     /* draw gripper */
606     if (lpBand->fDraw & DRAW_GRIPPER)
607         DrawEdge (hdc, &lpBand->rcGripper, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
608
609     /* draw caption image */
610     if (lpBand->fDraw & DRAW_IMAGE) {
611         POINT pt;
612
613         /* center image */
614         pt.y = (lpBand->rcCapImage.bottom + lpBand->rcCapImage.top - infoPtr->imageSize.cy)/2;
615         pt.x = (lpBand->rcCapImage.right + lpBand->rcCapImage.left - infoPtr->imageSize.cx)/2;
616
617         ImageList_Draw (infoPtr->himl, lpBand->iImage, hdc,
618                         pt.x, pt.y,
619                         ILD_TRANSPARENT);
620     }
621
622     /* draw caption text */
623     if (lpBand->fDraw & DRAW_TEXT) {
624         /* need to handle CDRF_NEWFONT here */
625         INT oldBkMode = SetBkMode (hdc, TRANSPARENT);
626         COLORREF oldcolor = CLR_NONE;
627         COLORREF new;
628         if (lpBand->clrFore != CLR_NONE) {
629             new = (lpBand->clrFore == CLR_DEFAULT) ? infoPtr->clrBtnText :
630                     lpBand->clrFore;
631             oldcolor = SetTextColor (hdc, new);
632         }
633         DrawTextW (hdc, lpBand->lpText, -1, &lpBand->rcCapText,
634                    DT_CENTER | DT_VCENTER | DT_SINGLELINE);
635         if (oldBkMode != TRANSPARENT)
636             SetBkMode (hdc, oldBkMode);
637         if (lpBand->clrFore != CLR_NONE)
638             SetTextColor (hdc, oldcolor);
639         SelectObject (hdc, hOldFont);
640     }
641
642     if (!IsRectEmpty(&lpBand->rcChevron))
643     {
644         if (lpBand->fDraw & DRAW_CHEVRONPUSHED)
645         {
646             DrawEdge(hdc, &lpBand->rcChevron, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE);
647             REBAR_DrawChevron(hdc, lpBand->rcChevron.left+1, lpBand->rcChevron.top + 11, COLOR_WINDOWFRAME);
648         }
649         else if (lpBand->fDraw & DRAW_CHEVRONHOT)
650         {
651             DrawEdge(hdc, &lpBand->rcChevron, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
652             REBAR_DrawChevron(hdc, lpBand->rcChevron.left, lpBand->rcChevron.top + 10, COLOR_WINDOWFRAME);
653         }
654         else
655             REBAR_DrawChevron(hdc, lpBand->rcChevron.left, lpBand->rcChevron.top + 10, COLOR_WINDOWFRAME);
656     }
657
658     if (lpBand->uCDret == (CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYITEMDRAW)) {
659         nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;
660         nmcd.hdc = hdc;
661         nmcd.rc = lpBand->rcBand;
662         nmcd.rc.right = lpBand->rcCapText.right;
663         nmcd.rc.bottom = lpBand->rcCapText.bottom;
664         nmcd.dwItemSpec = lpBand->wID;
665         nmcd.uItemState = 0;
666         nmcd.lItemlParam = lpBand->lParam;
667         lpBand->uCDret = REBAR_Notify ((NMHDR *)&nmcd, infoPtr, NM_CUSTOMDRAW);
668     }
669 }
670
671
672 static VOID
673 REBAR_Refresh (REBAR_INFO *infoPtr, HDC hdc)
674 {
675     REBAR_BAND *lpBand;
676     UINT i;
677
678     if (!infoPtr->DoRedraw) return;
679
680     for (i = 0; i < infoPtr->uNumBands; i++) {
681         lpBand = &infoPtr->bands[i];
682
683         if (HIDDENBAND(lpBand)) continue;
684
685         /* now draw the band */
686         TRACE("[%p] drawing band %i, flags=%08x\n",
687               infoPtr->hwndSelf, i, lpBand->fDraw);
688         REBAR_DrawBand (hdc, infoPtr, lpBand);
689
690     }
691 }
692
693
694 static void
695 REBAR_FixVert (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend,
696                    INT mcy)
697      /* Function:                                                    */
698      /*   Cycle through bands in row and fix height of each band.    */
699      /*   Also determine whether each band has changed.              */
700      /* On entry:                                                    */
701      /*   all bands at desired size.                                 */
702      /*   start and end bands are *not* hidden                       */
703 {
704     REBAR_BAND *lpBand;
705     INT i;
706
707     for (i = (INT)rowstart; i<=(INT)rowend; i++) {
708         lpBand = &infoPtr->bands[i];
709         if (HIDDENBAND(lpBand)) continue;
710
711         /* adjust height of bands in row to "mcy" value */
712         if (infoPtr->dwStyle & CCS_VERT) {
713             if (lpBand->rcBand.right != lpBand->rcBand.left + mcy)
714                 lpBand->rcBand.right = lpBand->rcBand.left + mcy;
715         }
716         else {
717             if (lpBand->rcBand.bottom != lpBand->rcBand.top + mcy)
718                 lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
719
720         }
721
722         /* mark whether we need to invalidate this band and trace */
723         if ((lpBand->rcoldBand.left !=lpBand->rcBand.left) ||
724             (lpBand->rcoldBand.top !=lpBand->rcBand.top) ||
725             (lpBand->rcoldBand.right !=lpBand->rcBand.right) ||
726             (lpBand->rcoldBand.bottom !=lpBand->rcBand.bottom)) {
727             lpBand->fDraw |= NTF_INVALIDATE;
728             TRACE("band %d row=%d: changed to (%ld,%ld)-(%ld,%ld) from (%ld,%ld)-(%ld,%ld)\n",
729                   i, lpBand->iRow,
730                   lpBand->rcBand.left, lpBand->rcBand.top,
731                   lpBand->rcBand.right, lpBand->rcBand.bottom,
732                   lpBand->rcoldBand.left, lpBand->rcoldBand.top,
733                   lpBand->rcoldBand.right, lpBand->rcoldBand.bottom);
734         }
735         else
736             TRACE("band %d row=%d: unchanged (%ld,%ld)-(%ld,%ld)\n",
737                   i, lpBand->iRow,
738                   lpBand->rcBand.left, lpBand->rcBand.top,
739                   lpBand->rcBand.right, lpBand->rcBand.bottom);
740     }
741 }
742
743
744 static void
745 REBAR_AdjustBands (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend,
746                    INT maxx, INT mcy)
747      /* Function: This routine distributes the extra space in a row. */
748      /*  See algorithm below.                                        */
749      /* On entry:                                                    */
750      /*   all bands @ ->cxHeader size                                */
751      /*   start and end bands are *not* hidden                       */
752 {
753     REBAR_BAND *lpBand;
754     UINT xsep, extra, curwidth, fudge;
755     INT x, i, last_adjusted;
756
757     TRACE("start=%u, end=%u, max x=%d, max y=%d\n",
758           rowstart, rowend, maxx, mcy);
759
760     /* *******************  Phase 1  ************************ */
761     /* Alg:                                                   */
762     /*  For each visible band with valid child                */
763     /*      a. inflate band till either all extra space used  */
764     /*         or band's ->ccx reached.                       */
765     /*  If any band modified, add any space left to last band */
766     /*  adjusted.                                             */
767     /*                                                        */
768     /* ****************************************************** */
769     lpBand = &infoPtr->bands[rowend];
770     extra = maxx - rcBrb(lpBand);
771     x = 0;
772     last_adjusted = -1;
773     for (i=(INT)rowstart; i<=(INT)rowend; i++) {
774         lpBand = &infoPtr->bands[i];
775         if (HIDDENBAND(lpBand)) continue;
776         xsep = (x == 0) ? 0 : SEP_WIDTH;
777         curwidth = rcBw(lpBand);
778
779         /* set new left/top point */
780         if (infoPtr->dwStyle & CCS_VERT)
781             lpBand->rcBand.top = x + xsep;
782         else
783             lpBand->rcBand.left = x + xsep;
784
785         /* compute new width */
786         if ((lpBand->hwndChild && extra) && !(lpBand->fStyle & RBBS_FIXEDSIZE)) {
787             /* set to the "current" band size less the header */
788             fudge = lpBand->ccx;
789             last_adjusted = i;
790             if ((lpBand->fMask & RBBIM_SIZE) && (lpBand->cx > 0) &&
791                 (fudge > curwidth)) {
792                 TRACE("adjusting band %d by %d, fudge=%d, curwidth=%d, extra=%d\n",
793                       i, fudge-curwidth, fudge, curwidth, extra);
794                 if ((fudge - curwidth) > extra)
795                     fudge = curwidth + extra;
796                 extra -= (fudge - curwidth);
797                 curwidth = fudge;
798             }
799             else {
800                 TRACE("adjusting band %d by %d, fudge=%d, curwidth=%d\n",
801                       i, extra, fudge, curwidth);
802                 curwidth += extra;
803                 extra = 0;
804             }
805         }
806
807         /* set new right/bottom point */
808         if (infoPtr->dwStyle & CCS_VERT)
809             lpBand->rcBand.bottom = lpBand->rcBand.top + curwidth;
810         else
811             lpBand->rcBand.right = lpBand->rcBand.left + curwidth;
812         TRACE("Phase 1 band %d, (%ld,%ld)-(%ld,%ld), orig x=%d, xsep=%d\n",
813               i, lpBand->rcBand.left, lpBand->rcBand.top,
814               lpBand->rcBand.right, lpBand->rcBand.bottom, x, xsep);
815         x = rcBrb(lpBand);
816     }
817     if ((x >= maxx) || (last_adjusted != -1)) {
818         if (x > maxx) {
819             ERR("Phase 1 failed, x=%d, maxx=%d, start=%u, end=%u\n",
820                 x, maxx,  rowstart, rowend);
821         }
822         /* done, so spread extra space */
823         if (x < maxx) {
824             fudge = maxx - x;
825             TRACE("Need to spread %d on last adjusted band %d\n",
826                 fudge, last_adjusted);
827             for (i=(INT)last_adjusted; i<=(INT)rowend; i++) {
828                 lpBand = &infoPtr->bands[i];
829                 if (HIDDENBAND(lpBand)) continue;
830
831                 /* set right/bottom point */
832                 if (i != last_adjusted) {
833                     if (infoPtr->dwStyle & CCS_VERT)
834                         lpBand->rcBand.top += fudge;
835                     else
836                         lpBand->rcBand.left += fudge;
837                 }
838
839                 /* set left/bottom point */
840                 if (infoPtr->dwStyle & CCS_VERT)
841                     lpBand->rcBand.bottom += fudge;
842                 else
843                     lpBand->rcBand.right += fudge;
844             }
845         }
846         TRACE("Phase 1 succeeded, used x=%d\n", x);
847         REBAR_FixVert (infoPtr, rowstart, rowend, mcy);
848         return;
849     }
850
851     /* *******************  Phase 2  ************************ */
852     /* Alg:                                                   */
853     /*  Find first visible band, put all                      */
854     /*    extra space there.                                  */
855     /*                                                        */
856     /* ****************************************************** */
857
858     x = 0;
859     for (i=(INT)rowstart; i<=(INT)rowend; i++) {
860         lpBand = &infoPtr->bands[i];
861         if (HIDDENBAND(lpBand)) continue;
862         xsep = (x == 0) ? 0 : SEP_WIDTH;
863         curwidth = rcBw(lpBand);
864
865         /* set new left/top point */
866         if (infoPtr->dwStyle & CCS_VERT)
867             lpBand->rcBand.top = x + xsep;
868         else
869             lpBand->rcBand.left = x + xsep;
870
871         /* compute new width */
872         if (extra) {
873             curwidth += extra;
874             extra = 0;
875         }
876
877         /* set new right/bottom point */
878         if (infoPtr->dwStyle & CCS_VERT)
879             lpBand->rcBand.bottom = lpBand->rcBand.top + curwidth;
880         else
881             lpBand->rcBand.right = lpBand->rcBand.left + curwidth;
882         TRACE("Phase 2 band %d, (%ld,%ld)-(%ld,%ld), orig x=%d, xsep=%d\n",
883               i, lpBand->rcBand.left, lpBand->rcBand.top,
884               lpBand->rcBand.right, lpBand->rcBand.bottom, x, xsep);
885         x = rcBrb(lpBand);
886     }
887     if (x >= maxx) {
888         if (x > maxx) {
889             ERR("Phase 2 failed, x=%d, maxx=%d, start=%u, end=%u\n",
890                 x, maxx,  rowstart, rowend);
891         }
892         /* done, so spread extra space */
893         TRACE("Phase 2 succeeded, used x=%d\n", x);
894         REBAR_FixVert (infoPtr, rowstart, rowend, mcy);
895         return;
896     }
897
898     /* *******************  Phase 3  ************************ */
899     /* at this point everything is back to ->cxHeader values  */
900     /* and should not have gotten here.                       */
901     /* ****************************************************** */
902
903     lpBand = &infoPtr->bands[rowstart];
904     ERR("Serious problem adjusting row %d, start band %d, end band %d\n",
905         lpBand->iRow, rowstart, rowend);
906     REBAR_DumpBand (infoPtr);
907     return;
908 }
909
910
911 static void
912 REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
913      /* Function: this routine initializes all the rectangles in */
914      /*  each band in a row to fit in the adjusted rcBand rect.  */
915      /* *** Supports only Horizontal bars. ***                   */
916 {
917     REBAR_BAND *lpBand;
918     UINT i, xoff, yoff;
919     HWND parenthwnd;
920     RECT oldChild, work;
921
922     /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
923     parenthwnd = GetParent (infoPtr->hwndSelf);
924
925     for(i=rstart; i<rend; i++){
926       lpBand = &infoPtr->bands[i];
927       if (HIDDENBAND(lpBand)) {
928           SetRect (&lpBand->rcChild,
929                    lpBand->rcBand.right, lpBand->rcBand.top,
930                    lpBand->rcBand.right, lpBand->rcBand.bottom);
931           continue;
932       }
933
934       oldChild = lpBand->rcChild;
935
936       /* set initial gripper rectangle */
937       SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
938                lpBand->rcBand.left, lpBand->rcBand.bottom);
939
940       /* calculate gripper rectangle */
941       if ( lpBand->fStatus & HAS_GRIPPER) {
942           lpBand->fDraw |= DRAW_GRIPPER;
943           lpBand->rcGripper.left   += REBAR_PRE_GRIPPER;
944           lpBand->rcGripper.right  = lpBand->rcGripper.left + GRIPPER_WIDTH;
945           lpBand->rcGripper.top    += 2;
946           lpBand->rcGripper.bottom -= 2;
947
948           SetRect (&lpBand->rcCapImage,
949                    lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.top,
950                    lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.bottom);
951       }
952       else {  /* no gripper will be drawn */
953           xoff = 0;
954           if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
955               /* if no gripper but either image or text, then leave space */
956               xoff = REBAR_ALWAYS_SPACE;
957           SetRect (&lpBand->rcCapImage,
958                    lpBand->rcBand.left+xoff, lpBand->rcBand.top,
959                    lpBand->rcBand.left+xoff, lpBand->rcBand.bottom);
960       }
961
962       /* image is visible */
963       if (lpBand->fStatus & HAS_IMAGE) {
964           lpBand->fDraw |= DRAW_IMAGE;
965           lpBand->rcCapImage.right  += infoPtr->imageSize.cx;
966           lpBand->rcCapImage.bottom = lpBand->rcCapImage.top + infoPtr->imageSize.cy;
967
968           /* set initial caption text rectangle */
969           SetRect (&lpBand->rcCapText,
970                    lpBand->rcCapImage.right+REBAR_POST_IMAGE, lpBand->rcBand.top+1,
971                    lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
972           /* update band height
973           if (lpBand->uMinHeight < infoPtr->imageSize.cy + 2) {
974               lpBand->uMinHeight = infoPtr->imageSize.cy + 2;
975               lpBand->rcBand.bottom = lpBand->rcBand.top + lpBand->uMinHeight;
976           }  */
977       }
978       else {
979           /* set initial caption text rectangle */
980           SetRect (&lpBand->rcCapText, lpBand->rcCapImage.right, lpBand->rcBand.top+1,
981                    lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1);
982       }
983
984       /* text is visible */
985       if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
986           lpBand->fDraw |= DRAW_TEXT;
987           lpBand->rcCapText.right = max(lpBand->rcCapText.left,
988                                         lpBand->rcCapText.right-REBAR_POST_TEXT);
989       }
990
991       /* set initial child window rectangle if there is a child */
992       if (lpBand->fMask & RBBIM_CHILD) {
993           xoff = lpBand->offChild.cx;
994           yoff = lpBand->offChild.cy;
995           SetRect (&lpBand->rcChild,
996                    lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top+yoff,
997                    lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
998           if ((lpBand->fStyle & RBBS_USECHEVRON) && (lpBand->rcChild.right - lpBand->rcChild.left < lpBand->cxIdeal))
999           {
1000               lpBand->rcChild.right -= CHEVRON_WIDTH;
1001               SetRect(&lpBand->rcChevron, lpBand->rcChild.right,
1002                       lpBand->rcChild.top, lpBand->rcChild.right + CHEVRON_WIDTH,
1003                       lpBand->rcChild.bottom);
1004           }
1005       }
1006       else {
1007           SetRect (&lpBand->rcChild,
1008                    lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top,
1009                    lpBand->rcBand.right, lpBand->rcBand.bottom);
1010       }
1011
1012       /* flag if notify required and invalidate rectangle */
1013       if (notify &&
1014           ((oldChild.right-oldChild.left != lpBand->rcChild.right-lpBand->rcChild.left) ||
1015            (oldChild.bottom-oldChild.top != lpBand->rcChild.bottom-lpBand->rcChild.top))) {
1016           TRACE("Child rectangle changed for band %u\n", i);
1017           TRACE("    from (%ld,%ld)-(%ld,%ld)  to (%ld,%ld)-(%ld,%ld)\n",
1018                 oldChild.left, oldChild.top,
1019                 oldChild.right, oldChild.bottom,
1020                 lpBand->rcChild.left, lpBand->rcChild.top,
1021                 lpBand->rcChild.right, lpBand->rcChild.bottom);
1022       }
1023       if (lpBand->fDraw & NTF_INVALIDATE) {
1024           TRACE("invalidating (%ld,%ld)-(%ld,%ld)\n",
1025                 lpBand->rcBand.left,
1026                 lpBand->rcBand.top,
1027                 lpBand->rcBand.right + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0),
1028                 lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0));
1029           lpBand->fDraw &= ~NTF_INVALIDATE;
1030           work = lpBand->rcBand;
1031           if (lpBand->fDraw & DRAW_RIGHTSEP) work.right += SEP_WIDTH_SIZE;
1032           if (lpBand->fDraw & DRAW_BOTTOMSEP) work.bottom += SEP_WIDTH_SIZE;
1033           InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
1034       }
1035
1036     }
1037
1038 }
1039
1040
1041 static VOID
1042 REBAR_CalcVertBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify)
1043      /* Function: this routine initializes all the rectangles in */
1044      /*  each band in a row to fit in the adjusted rcBand rect.  */
1045      /* *** Supports only Vertical bars. ***                     */
1046 {
1047     REBAR_BAND *lpBand;
1048     UINT i, xoff, yoff;
1049     HWND parenthwnd;
1050     RECT oldChild, work;
1051
1052     /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
1053     parenthwnd = GetParent (infoPtr->hwndSelf);
1054
1055     for(i=rstart; i<rend; i++){
1056         lpBand = &infoPtr->bands[i];
1057         if (HIDDENBAND(lpBand)) continue;
1058         oldChild = lpBand->rcChild;
1059
1060         /* set initial gripper rectangle */
1061         SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
1062                  lpBand->rcBand.right, lpBand->rcBand.top);
1063
1064         /* calculate gripper rectangle */
1065         if (lpBand->fStatus & HAS_GRIPPER) {
1066             lpBand->fDraw |= DRAW_GRIPPER;
1067
1068             if (infoPtr->dwStyle & RBS_VERTICALGRIPPER) {
1069                 /*  vertical gripper  */
1070                 lpBand->rcGripper.left   += 3;
1071                 lpBand->rcGripper.right  = lpBand->rcGripper.left + GRIPPER_WIDTH;
1072                 lpBand->rcGripper.top    += REBAR_PRE_GRIPPER;
1073                 lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_HEIGHT;
1074
1075                 /* initialize Caption image rectangle  */
1076                 SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
1077                          lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
1078                          lpBand->rcBand.right,
1079                          lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
1080             }
1081             else {
1082                 /*  horizontal gripper  */
1083                 lpBand->rcGripper.left   += 2;
1084                 lpBand->rcGripper.right  -= 2;
1085                 lpBand->rcGripper.top    += REBAR_PRE_GRIPPER;
1086                 lpBand->rcGripper.bottom  = lpBand->rcGripper.top + GRIPPER_WIDTH;
1087
1088                 /* initialize Caption image rectangle  */
1089                 SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
1090                          lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE,
1091                          lpBand->rcBand.right,
1092                          lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE);
1093             }
1094         }
1095         else {  /* no gripper will be drawn */
1096             xoff = 0;
1097             if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT))
1098                 /* if no gripper but either image or text, then leave space */
1099                 xoff = REBAR_ALWAYS_SPACE;
1100             /* initialize Caption image rectangle  */
1101             SetRect (&lpBand->rcCapImage,
1102                      lpBand->rcBand.left, lpBand->rcBand.top+xoff,
1103                      lpBand->rcBand.right, lpBand->rcBand.top+xoff);
1104         }
1105
1106         /* image is visible */
1107         if (lpBand->fStatus & HAS_IMAGE) {
1108             lpBand->fDraw |= DRAW_IMAGE;
1109
1110             lpBand->rcCapImage.right  = lpBand->rcCapImage.left + infoPtr->imageSize.cx;
1111             lpBand->rcCapImage.bottom += infoPtr->imageSize.cy;
1112
1113             /* set initial caption text rectangle */
1114             SetRect (&lpBand->rcCapText,
1115                      lpBand->rcBand.left, lpBand->rcCapImage.bottom+REBAR_POST_IMAGE,
1116                      lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
1117             /* update band height *
1118                if (lpBand->uMinHeight < infoPtr->imageSize.cx + 2) {
1119                lpBand->uMinHeight = infoPtr->imageSize.cx + 2;
1120                lpBand->rcBand.right = lpBand->rcBand.left + lpBand->uMinHeight;
1121                } */
1122         }
1123         else {
1124             /* set initial caption text rectangle */
1125             SetRect (&lpBand->rcCapText,
1126                      lpBand->rcBand.left, lpBand->rcCapImage.bottom,
1127                      lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader);
1128         }
1129
1130         /* text is visible */
1131         if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) {
1132             lpBand->fDraw |= DRAW_TEXT;
1133             lpBand->rcCapText.bottom = max(lpBand->rcCapText.top,
1134                                            lpBand->rcCapText.bottom);
1135         }
1136
1137         /* set initial child window rectangle if there is a child */
1138         if (lpBand->fMask & RBBIM_CHILD) {
1139             yoff = lpBand->offChild.cx;
1140             xoff = lpBand->offChild.cy;
1141             SetRect (&lpBand->rcChild,
1142                      lpBand->rcBand.left+xoff, lpBand->rcBand.top+lpBand->cxHeader,
1143                      lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
1144         }
1145         else {
1146             SetRect (&lpBand->rcChild,
1147                      lpBand->rcBand.left, lpBand->rcBand.top+lpBand->cxHeader,
1148                      lpBand->rcBand.right, lpBand->rcBand.bottom);
1149         }
1150
1151         /* flag if notify required and invalidate rectangle */
1152         if (notify &&
1153             ((oldChild.right-oldChild.left != lpBand->rcChild.right-lpBand->rcChild.left) ||
1154              (oldChild.bottom-oldChild.top != lpBand->rcChild.bottom-lpBand->rcChild.top))) {
1155             TRACE("Child rectangle changed for band %u\n", i);
1156             TRACE("    from (%ld,%ld)-(%ld,%ld)  to (%ld,%ld)-(%ld,%ld)\n",
1157                   oldChild.left, oldChild.top,
1158                   oldChild.right, oldChild.bottom,
1159                   lpBand->rcChild.left, lpBand->rcChild.top,
1160                   lpBand->rcChild.right, lpBand->rcChild.bottom);
1161         }
1162         if (lpBand->fDraw & NTF_INVALIDATE) {
1163             TRACE("invalidating (%ld,%ld)-(%ld,%ld)\n",
1164                   lpBand->rcBand.left,
1165                   lpBand->rcBand.top,
1166                   lpBand->rcBand.right + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0),
1167                   lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0));
1168             lpBand->fDraw &= ~NTF_INVALIDATE;
1169             work = lpBand->rcBand;
1170             if (lpBand->fDraw & DRAW_RIGHTSEP) work.bottom += SEP_WIDTH_SIZE;
1171             if (lpBand->fDraw & DRAW_BOTTOMSEP) work.right += SEP_WIDTH_SIZE;
1172             InvalidateRect(infoPtr->hwndSelf, &work, TRUE);
1173         }
1174
1175     }
1176 }
1177
1178
1179 static VOID
1180 REBAR_ForceResize (REBAR_INFO *infoPtr)
1181      /* Function: This changes the size of the REBAR window to that */
1182      /*  calculated by REBAR_Layout.                                */
1183 {
1184     RECT rc;
1185     INT x, y, width, height;
1186     INT xedge = GetSystemMetrics(SM_CXEDGE);
1187     INT yedge = GetSystemMetrics(SM_CYEDGE);
1188
1189     GetClientRect (infoPtr->hwndSelf, &rc);
1190
1191     TRACE( " old [%ld x %ld], new [%ld x %ld], client [%ld x %ld]\n",
1192            infoPtr->oldSize.cx, infoPtr->oldSize.cy,
1193            infoPtr->calcSize.cx, infoPtr->calcSize.cy,
1194            rc.right, rc.bottom);
1195
1196     /* If we need to shrink client, then skip size test */
1197     if ((infoPtr->calcSize.cy >= rc.bottom) &&
1198         (infoPtr->calcSize.cx >= rc.right)) {
1199
1200         /* if size did not change then skip process */
1201         if ((infoPtr->oldSize.cx == infoPtr->calcSize.cx) &&
1202             (infoPtr->oldSize.cy == infoPtr->calcSize.cy) &&
1203             !(infoPtr->fStatus & RESIZE_ANYHOW))
1204             {
1205                 TRACE("skipping reset\n");
1206                 return;
1207             }
1208     }
1209
1210     infoPtr->fStatus &= ~RESIZE_ANYHOW;
1211     /* Set flag to ignore next WM_SIZE message */
1212     infoPtr->fStatus |= AUTO_RESIZE;
1213
1214     width = 0;
1215     height = 0;
1216     x = 0;
1217     y = 0;
1218
1219     if (infoPtr->dwStyle & WS_BORDER) {
1220         width = 2 * xedge;
1221         height = 2 * yedge;
1222     }
1223
1224     if (!(infoPtr->dwStyle & CCS_NOPARENTALIGN)) {
1225         INT mode = infoPtr->dwStyle & (CCS_VERT | CCS_TOP | CCS_BOTTOM);
1226         RECT rcPcl;
1227
1228         GetClientRect(GetParent(infoPtr->hwndSelf), &rcPcl);
1229         switch (mode) {
1230         case CCS_TOP:
1231             /* _TOP sets width to parents width */
1232             width += (rcPcl.right - rcPcl.left);
1233             height += infoPtr->calcSize.cy;
1234             x += ((infoPtr->dwStyle & WS_BORDER) ? -xedge : 0);
1235             y += ((infoPtr->dwStyle & WS_BORDER) ? -yedge : 0);
1236             y += ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
1237             break;
1238         case CCS_BOTTOM:
1239             /* FIXME: wrong wrong wrong */
1240             /* _BOTTOM sets width to parents width */
1241             width += (rcPcl.right - rcPcl.left);
1242             height += infoPtr->calcSize.cy;
1243             x += -xedge;
1244             y = rcPcl.bottom - height + 1;
1245             break;
1246         case CCS_LEFT:
1247             /* _LEFT sets height to parents height */
1248             width += infoPtr->calcSize.cx;
1249             height += (rcPcl.bottom - rcPcl.top);
1250             x += ((infoPtr->dwStyle & WS_BORDER) ? -xedge : 0);
1251             x += ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER);
1252             y += ((infoPtr->dwStyle & WS_BORDER) ? -yedge : 0);
1253             break;
1254         case CCS_RIGHT:
1255             /* FIXME: wrong wrong wrong */
1256             /* _RIGHT sets height to parents height */
1257             width += infoPtr->calcSize.cx;
1258             height += (rcPcl.bottom - rcPcl.top);
1259             x = rcPcl.right - width + 1;
1260             y = -yedge;
1261             break;
1262         default:
1263             width += infoPtr->calcSize.cx;
1264             height += infoPtr->calcSize.cy;
1265         }
1266     }
1267     else {
1268         width += infoPtr->calcSize.cx;
1269         height += infoPtr->calcSize.cy;
1270         x = infoPtr->origin.x;
1271         y = infoPtr->origin.y;
1272     }
1273
1274     TRACE("hwnd %p, style=%08lx, setting at (%d,%d) for (%d,%d)\n",
1275         infoPtr->hwndSelf, infoPtr->dwStyle,
1276         x, y, width, height);
1277     SetWindowPos (infoPtr->hwndSelf, 0, x, y, width, height,
1278                     SWP_NOZORDER);
1279     infoPtr->fStatus &= ~AUTO_RESIZE;
1280 }
1281
1282
1283 static VOID
1284 REBAR_MoveChildWindows (REBAR_INFO *infoPtr, UINT start, UINT endplus)
1285 {
1286     REBAR_BAND *lpBand;
1287     CHAR szClassName[40];
1288     UINT i;
1289     NMREBARCHILDSIZE  rbcz;
1290     NMHDR heightchange;
1291     HDWP deferpos;
1292
1293     if (!(deferpos = BeginDeferWindowPos(infoPtr->uNumBands)))
1294         ERR("BeginDeferWindowPos returned NULL\n");
1295
1296     for (i = start; i < endplus; i++) {
1297         lpBand = &infoPtr->bands[i];
1298
1299         if (HIDDENBAND(lpBand)) continue;
1300         if (lpBand->hwndChild) {
1301             TRACE("hwndChild = %p\n", lpBand->hwndChild);
1302
1303             /* Always geterate the RBN_CHILDSIZE even it child
1304                    did not change */
1305             rbcz.uBand = i;
1306             rbcz.wID = lpBand->wID;
1307             rbcz.rcChild = lpBand->rcChild;
1308             rbcz.rcBand = lpBand->rcBand;
1309             if (infoPtr->dwStyle & CCS_VERT)
1310                 rbcz.rcBand.top += lpBand->cxHeader;
1311             else
1312                 rbcz.rcBand.left += lpBand->cxHeader;
1313             REBAR_Notify ((NMHDR *)&rbcz, infoPtr, RBN_CHILDSIZE);
1314             if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) {
1315                 TRACE("Child rect changed by NOTIFY for band %u\n", i);
1316                 TRACE("    from (%ld,%ld)-(%ld,%ld)  to (%ld,%ld)-(%ld,%ld)\n",
1317                       lpBand->rcChild.left, lpBand->rcChild.top,
1318                       lpBand->rcChild.right, lpBand->rcChild.bottom,
1319                       rbcz.rcChild.left, rbcz.rcChild.top,
1320                       rbcz.rcChild.right, rbcz.rcChild.bottom);
1321                 lpBand->rcChild = rbcz.rcChild;  /* *** ??? */
1322             }
1323
1324             /* native (IE4 in "Favorites" frame **1) does:
1325              *   SetRect (&rc, -1, -1, -1, -1)
1326              *   EqualRect (&rc,band->rc???)
1327              *   if ret==0
1328              *     CopyRect (band->rc????, &rc)
1329              *     set flag outside of loop
1330              */
1331
1332             GetClassNameA (lpBand->hwndChild, szClassName, 40);
1333             if (!lstrcmpA (szClassName, "ComboBox") ||
1334                 !lstrcmpA (szClassName, WC_COMBOBOXEXA)) {
1335                 INT nEditHeight, yPos;
1336                 RECT rc;
1337
1338                 /* special placement code for combo or comboex box */
1339
1340
1341                 /* get size of edit line */
1342                 GetWindowRect (lpBand->hwndChild, &rc);
1343                 nEditHeight = rc.bottom - rc.top;
1344                 yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;
1345
1346                 /* center combo box inside child area */
1347                 TRACE("moving child (Combo(Ex)) %p to (%ld,%d) for (%ld,%d)\n",
1348                       lpBand->hwndChild,
1349                       lpBand->rcChild.left, yPos,
1350                       lpBand->rcChild.right - lpBand->rcChild.left,
1351                       nEditHeight);
1352                 deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
1353                                            lpBand->rcChild.left,
1354                                            /*lpBand->rcChild.top*/ yPos,
1355                                            lpBand->rcChild.right - lpBand->rcChild.left,
1356                                            nEditHeight,
1357                                            SWP_NOZORDER);
1358                 if (!deferpos)
1359                     ERR("DeferWindowPos returned NULL\n");
1360             }
1361             else {
1362                 TRACE("moving child (Other) %p to (%ld,%ld) for (%ld,%ld)\n",
1363                       lpBand->hwndChild,
1364                       lpBand->rcChild.left, lpBand->rcChild.top,
1365                       lpBand->rcChild.right - lpBand->rcChild.left,
1366                       lpBand->rcChild.bottom - lpBand->rcChild.top);
1367                 deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP,
1368                                            lpBand->rcChild.left,
1369                                            lpBand->rcChild.top,
1370                                            lpBand->rcChild.right - lpBand->rcChild.left,
1371                                            lpBand->rcChild.bottom - lpBand->rcChild.top,
1372                                            SWP_NOZORDER);
1373                 if (!deferpos)
1374                     ERR("DeferWindowPos returned NULL\n");
1375             }
1376         }
1377     }
1378     if (!EndDeferWindowPos(deferpos))
1379         ERR("EndDeferWindowPos returned NULL\n");
1380
1381     if (infoPtr->DoRedraw)
1382         UpdateWindow (infoPtr->hwndSelf);
1383
1384     if (infoPtr->fStatus & NTF_HGHTCHG) {
1385         infoPtr->fStatus &= ~NTF_HGHTCHG;
1386         /*
1387          * We need to force a resize here, because some applications
1388          * try to get the rebar size during processing of the 
1389          * RBN_HEIGHTCHANGE notification.
1390          */
1391         REBAR_ForceResize (infoPtr);
1392         REBAR_Notify (&heightchange, infoPtr, RBN_HEIGHTCHANGE);
1393     }
1394
1395     /* native (from **1 above) does:
1396      *      UpdateWindow(rebar)
1397      *      REBAR_ForceResize
1398      *      RBN_HEIGHTCHANGE if necessary
1399      *      if ret from any EqualRect was 0
1400      *         Goto "BeginDeferWindowPos"
1401      */
1402
1403 }
1404
1405
1406 static VOID
1407 REBAR_Layout (REBAR_INFO *infoPtr, LPRECT lpRect, BOOL notify, BOOL resetclient)
1408      /* Function: This routine is resposible for laying out all */
1409      /*  the bands in a rebar. It assigns each band to a row and*/
1410      /*  determines when to start a new row.                    */
1411 {
1412     REBAR_BAND *lpBand, *prevBand;
1413     RECT rcClient, rcAdj;
1414     INT initx, inity, x, y, cx, cxsep, mmcy, mcy, clientcx, clientcy;
1415     INT adjcx, adjcy, row, rightx, bottomy, origheight;
1416     UINT i, j, rowstart, origrows, cntonrow;
1417     BOOL dobreak;
1418
1419     if (!(infoPtr->fStatus & BAND_NEEDS_LAYOUT)) {
1420         TRACE("no layout done. No band changed.\n");
1421         REBAR_DumpBand (infoPtr);
1422         return;
1423     }
1424     infoPtr->fStatus &= ~BAND_NEEDS_LAYOUT;
1425     if (!infoPtr->DoRedraw) infoPtr->fStatus |= BAND_NEEDS_REDRAW;
1426
1427     GetClientRect (infoPtr->hwndSelf, &rcClient);
1428     TRACE("Client is (%ld,%ld)-(%ld,%ld)\n",
1429           rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
1430
1431     if (lpRect) {
1432         rcAdj = *lpRect;
1433         TRACE("adjustment rect is (%ld,%ld)-(%ld,%ld)\n",
1434               rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom);
1435     }
1436     else {
1437         CopyRect (&rcAdj, &rcClient);
1438     }
1439
1440     clientcx = rcClient.right - rcClient.left;
1441     clientcy = rcClient.bottom - rcClient.top;
1442     adjcx = rcAdj.right - rcAdj.left;
1443     adjcy = rcAdj.bottom - rcAdj.top;
1444     if (resetclient) {
1445         TRACE("window client rect will be set to adj rect\n");
1446         clientcx = adjcx;
1447         clientcy = adjcy;
1448     }
1449
1450     if (!infoPtr->DoRedraw && (clientcx == 0) && (clientcy == 0)) {
1451         ERR("no redraw and client is zero, skip layout\n");
1452         infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
1453         return;
1454     }
1455
1456     /* save height of original control */
1457     if (infoPtr->dwStyle & CCS_VERT)
1458         origheight = infoPtr->calcSize.cx;
1459     else
1460         origheight = infoPtr->calcSize.cy;
1461     origrows = infoPtr->uNumRows;
1462
1463     initx = 0;
1464     inity = 0;
1465
1466     /* ******* Start Phase 1 - all bands on row at minimum size ******* */
1467
1468     TRACE("band loop constants, clientcx=%d, clientcy=%d, adjcx=%d, adjcy=%d\n",
1469           clientcx, clientcy, adjcx, adjcy);
1470     x = initx;
1471     y = inity;
1472     row = 1;
1473     cx = 0;
1474     mcy = 0;
1475     rowstart = 0;
1476     prevBand = NULL;
1477     cntonrow = 0;
1478
1479     for (i = 0; i < infoPtr->uNumBands; i++) {
1480         lpBand = &infoPtr->bands[i];
1481         lpBand->fDraw = 0;
1482         lpBand->iRow = row;
1483
1484         SetRectEmpty(&lpBand->rcChevron);
1485
1486         if (HIDDENBAND(lpBand)) continue;
1487
1488         lpBand->rcoldBand = lpBand->rcBand;
1489
1490         /* Set the offset of the child window */
1491         if ((lpBand->fMask & RBBIM_CHILD) &&
1492             !(lpBand->fStyle & RBBS_FIXEDSIZE)) {
1493             lpBand->offChild.cx = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 4 : 0);
1494         }
1495         lpBand->offChild.cy = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 2 : 0);
1496
1497         /* separator from previous band */
1498         cxsep = (cntonrow == 0) ? 0 : SEP_WIDTH;
1499         cx = lpBand->lcx;
1500
1501         if (infoPtr->dwStyle & CCS_VERT)
1502             dobreak = (y + cx + cxsep > adjcy);
1503         else
1504             dobreak = (x + cx + cxsep > adjcx);
1505
1506         /* This is the check for whether we need to start a new row */
1507         if ( ( (lpBand->fStyle & RBBS_BREAK) && (i != 0) ) ||
1508              ( ((infoPtr->dwStyle & CCS_VERT) ? (y != 0) : (x != 0)) && dobreak)) {
1509
1510             for (j = rowstart; j < i; j++) {
1511                 REBAR_BAND *lpB;
1512                 lpB = &infoPtr->bands[j];
1513                 if (infoPtr->dwStyle & CCS_VERT) {
1514                     lpB->rcBand.right  = lpB->rcBand.left + mcy;
1515                 }
1516                 else {
1517                     lpB->rcBand.bottom = lpB->rcBand.top + mcy;
1518                 }
1519             }
1520
1521             TRACE("P1 Spliting to new row %d on band %u\n", row+1, i);
1522             if (infoPtr->dwStyle & CCS_VERT) {
1523                 y = inity;
1524                 x += (mcy + SEP_WIDTH);
1525             }
1526             else {
1527                 x = initx;
1528                 y += (mcy + SEP_WIDTH);
1529             }
1530
1531             mcy = 0;
1532             cxsep = 0;
1533             row++;
1534             lpBand->iRow = row;
1535             prevBand = NULL;
1536             rowstart = i;
1537             cntonrow = 0;
1538         }
1539
1540         if (mcy < lpBand->lcy + REBARSPACE(lpBand))
1541             mcy = lpBand->lcy + REBARSPACE(lpBand);
1542
1543         /* if boundary rect specified then limit mcy */
1544         if (lpRect) {
1545             if (infoPtr->dwStyle & CCS_VERT) {
1546                 if (x+mcy > adjcx) {
1547                     mcy = adjcx - x;
1548                     TRACE("P1 row %u limiting mcy=%d, adjcx=%d, x=%d\n",
1549                           i, mcy, adjcx, x);
1550                 }
1551             }
1552             else {
1553                 if (y+mcy > adjcy) {
1554                     mcy = adjcy - y;
1555                     TRACE("P1 row %u limiting mcy=%d, adjcy=%d, y=%d\n",
1556                           i, mcy, adjcy, y);
1557                 }
1558             }
1559         }
1560
1561         TRACE("P1 band %u, row %d, x=%d, y=%d, cxsep=%d, cx=%d\n",
1562               i, row,
1563               x, y, cxsep, cx);
1564         if (infoPtr->dwStyle & CCS_VERT) {
1565             /* bound the bottom side if we have a bounding rectangle */
1566             rightx = clientcx;
1567             bottomy = (lpRect) ? min(clientcy, y+cxsep+cx) : y+cxsep+cx;
1568             lpBand->rcBand.left   = x;
1569             lpBand->rcBand.right  = x + min(mcy,
1570                                             lpBand->lcy+REBARSPACE(lpBand));
1571             lpBand->rcBand.top    = min(bottomy, y + cxsep);
1572             lpBand->rcBand.bottom = bottomy;
1573             lpBand->uMinHeight = lpBand->lcy;
1574             y = bottomy;
1575         }
1576         else {
1577             /* bound the right side if we have a bounding rectangle */
1578             rightx = (lpRect) ? min(clientcx, x+cxsep+cx) : x+cxsep+cx;
1579             bottomy = clientcy;
1580             lpBand->rcBand.left   = min(rightx, x + cxsep);
1581             lpBand->rcBand.right  = rightx;
1582             lpBand->rcBand.top    = y;
1583             lpBand->rcBand.bottom = y + min(mcy,
1584                                             lpBand->lcy+REBARSPACE(lpBand));
1585             lpBand->uMinHeight = lpBand->lcy;
1586             x = rightx;
1587         }
1588         TRACE("P1 band %u, row %d, (%ld,%ld)-(%ld,%ld)\n",
1589               i, row,
1590               lpBand->rcBand.left, lpBand->rcBand.top,
1591               lpBand->rcBand.right, lpBand->rcBand.bottom);
1592         prevBand = lpBand;
1593         cntonrow++;
1594
1595     } /* for (i = 0; i < infoPtr->uNumBands... */
1596
1597     if (infoPtr->dwStyle & CCS_VERT)
1598         x += mcy;
1599     else
1600         y += mcy;
1601
1602     for (j = rowstart; j < infoPtr->uNumBands; j++) {
1603         lpBand = &infoPtr->bands[j];
1604         if (infoPtr->dwStyle & CCS_VERT) {
1605             lpBand->rcBand.right  = lpBand->rcBand.left + mcy;
1606         }
1607         else {
1608             lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
1609         }
1610     }
1611
1612     if (infoPtr->uNumBands)
1613         infoPtr->uNumRows = row;
1614
1615     /* ******* End Phase 1 - all bands on row at minimum size ******* */
1616
1617
1618     /* ******* Start Phase 1a - Adjust heights for RBS_VARHEIGHT off ******* */
1619
1620     mmcy = 0;
1621     if (!(infoPtr->dwStyle & RBS_VARHEIGHT)) {
1622         INT xy;
1623
1624         /* get the max height of all bands */
1625         for (i=0; i<infoPtr->uNumBands; i++) {
1626             lpBand = &infoPtr->bands[i];
1627             if (HIDDENBAND(lpBand)) continue;
1628             if (infoPtr->dwStyle & CCS_VERT)
1629                 mmcy = max(mmcy, lpBand->rcBand.right - lpBand->rcBand.left);
1630             else
1631                 mmcy = max(mmcy, lpBand->rcBand.bottom - lpBand->rcBand.top);
1632         }
1633
1634         /* now adjust all rectangles by using the height found above */
1635         xy = 0;
1636         row = 1;
1637         for (i=0; i<infoPtr->uNumBands; i++) {
1638             lpBand = &infoPtr->bands[i];
1639             if (HIDDENBAND(lpBand)) continue;
1640             if (lpBand->iRow != row)
1641                 xy += (mmcy + SEP_WIDTH);
1642             if (infoPtr->dwStyle & CCS_VERT) {
1643                 lpBand->rcBand.left = xy;
1644                 lpBand->rcBand.right = xy + mmcy;
1645             }
1646             else {
1647                 lpBand->rcBand.top = xy;
1648                 lpBand->rcBand.bottom = xy + mmcy;
1649             }
1650         }
1651
1652         /* set the x/y values to the correct maximum */
1653         if (infoPtr->dwStyle & CCS_VERT)
1654             x = xy + mmcy;
1655         else
1656             y = xy + mmcy;
1657     }
1658
1659     /* ******* End Phase 1a - Adjust heights for RBS_VARHEIGHT off ******* */
1660
1661
1662     /* ******* Start Phase 2 - split rows till adjustment height full ******* */
1663
1664     /* assumes that the following variables contain:                 */
1665     /*   y/x     current height/width of all rows                    */
1666     if (lpRect) {
1667         INT i, prev_rh, new_rh, adj_rh, prev_idx, current_idx;
1668         REBAR_BAND *prev, *current, *walk;
1669         UINT j;
1670
1671 /* FIXME:  problem # 2 */
1672         if (((infoPtr->dwStyle & CCS_VERT) ?
1673 #if PROBLEM2
1674              (x < adjcx) : (y < adjcy)
1675 #else
1676              (adjcx - x > 5) : (adjcy - y > 4)
1677 #endif
1678              ) &&
1679             (infoPtr->uNumBands > 1)) {
1680             for (i=(INT)infoPtr->uNumBands-2; i>=0; i--) {
1681                 TRACE("P2 adjcx=%d, adjcy=%d, x=%d, y=%d\n",
1682                       adjcx, adjcy, x, y);
1683
1684                 /* find the current band (starts at i+1) */
1685                 current = &infoPtr->bands[i+1];
1686                 current_idx = i+1;
1687                 while (HIDDENBAND(current)) {
1688                     i--;
1689                     if (i < 0) break; /* out of bands */
1690                     current = &infoPtr->bands[i+1];
1691                     current_idx = i+1;
1692                 }
1693                 if (i < 0) break; /* out of bands */
1694
1695                 /* now find the prev band (starts at i) */
1696                 prev = &infoPtr->bands[i];
1697                 prev_idx = i;
1698                 while (HIDDENBAND(prev)) {
1699                     i--;
1700                     if (i < 0) break; /* out of bands */
1701                     prev = &infoPtr->bands[i];
1702                     prev_idx = i;
1703                 }
1704                 if (i < 0) break; /* out of bands */
1705
1706                 prev_rh = ircBw(prev);
1707                 if (prev->iRow == current->iRow) {
1708                     new_rh = (infoPtr->dwStyle & RBS_VARHEIGHT) ?
1709                         current->lcy + REBARSPACE(current) :
1710                         mmcy;
1711                     adj_rh = new_rh + SEP_WIDTH;
1712                     infoPtr->uNumRows++;
1713                     current->fDraw |= NTF_INVALIDATE;
1714                     current->iRow++;
1715                     if (infoPtr->dwStyle & CCS_VERT) {
1716                         current->rcBand.top = inity;
1717                         current->rcBand.bottom = clientcy;
1718                         current->rcBand.left += (prev_rh + SEP_WIDTH);
1719                         current->rcBand.right = current->rcBand.left + new_rh;
1720                         x += adj_rh;
1721                     }
1722                     else {
1723                         current->rcBand.left = initx;
1724                         current->rcBand.right = clientcx;
1725                         current->rcBand.top += (prev_rh + SEP_WIDTH);
1726                         current->rcBand.bottom = current->rcBand.top + new_rh;
1727                         y += adj_rh;
1728                     }
1729                     TRACE("P2 moving band %d to own row at (%ld,%ld)-(%ld,%ld)\n",
1730                           current_idx,
1731                           current->rcBand.left, current->rcBand.top,
1732                           current->rcBand.right, current->rcBand.bottom);
1733                     TRACE("P2 prev band %d at (%ld,%ld)-(%ld,%ld)\n",
1734                           prev_idx,
1735                           prev->rcBand.left, prev->rcBand.top,
1736                           prev->rcBand.right, prev->rcBand.bottom);
1737                     TRACE("P2 values: prev_rh=%d, new_rh=%d, adj_rh=%d\n",
1738                           prev_rh, new_rh, adj_rh);
1739                     /* for bands below current adjust row # and top/bottom */
1740                     for (j = current_idx+1; j<infoPtr->uNumBands; j++) {
1741                         walk = &infoPtr->bands[j];
1742                         if (HIDDENBAND(walk)) continue;
1743                         walk->fDraw |= NTF_INVALIDATE;
1744                         walk->iRow++;
1745                         if (infoPtr->dwStyle & CCS_VERT) {
1746                             walk->rcBand.left += adj_rh;
1747                             walk->rcBand.right += adj_rh;
1748                         }
1749                         else {
1750                             walk->rcBand.top += adj_rh;
1751                             walk->rcBand.bottom += adj_rh;
1752                         }
1753                     }
1754                     if ((infoPtr->dwStyle & CCS_VERT) ? (x >= adjcx) : (y >= adjcy))
1755                         break; /* all done */
1756                 }
1757             }
1758         }
1759     }
1760
1761     /* ******* End Phase 2 - split rows till adjustment height full ******* */
1762
1763
1764     /* ******* Start Phase 2a - mark first and last band in each ******* */
1765
1766     prevBand = NULL;
1767     for (i = 0; i < infoPtr->uNumBands; i++) {   
1768         lpBand = &infoPtr->bands[i];     
1769         if (HIDDENBAND(lpBand))
1770             continue;
1771         if( !prevBand ) {
1772             lpBand->fDraw |= DRAW_FIRST_IN_ROW;
1773             prevBand = lpBand;
1774         }
1775         else if( prevBand->iRow == lpBand->iRow )
1776             prevBand = lpBand;
1777         else {
1778             prevBand->fDraw |= DRAW_LAST_IN_ROW;
1779             lpBand->fDraw |= DRAW_FIRST_IN_ROW;
1780             prevBand = lpBand;
1781         }
1782     }
1783     if( prevBand )
1784         prevBand->fDraw |= DRAW_LAST_IN_ROW;
1785
1786     /* ******* End Phase 2a - mark first and last band in each ******* */
1787
1788
1789     /* ******* Start Phase 2b - adjust all bands for height full ******* */
1790     /* assumes that the following variables contain:                 */
1791     /*   y/x     current height/width of all rows                    */
1792     /*   clientcy/clientcx     height/width of client area           */
1793
1794     if (((infoPtr->dwStyle & CCS_VERT) ? clientcx > x : clientcy > y) &&
1795         infoPtr->uNumBands) {
1796         INT diff, i;
1797         UINT j;
1798
1799         diff = (infoPtr->dwStyle & CCS_VERT) ? clientcx - x : clientcy - y;
1800
1801         /* iterate backwards thru the rows */
1802         for (i = infoPtr->uNumBands-1; i>=0; i--) {
1803             lpBand = &infoPtr->bands[i];
1804             if(HIDDENBAND(lpBand)) continue;
1805
1806             /* if row has more than 1 band, ignore it */
1807             if( !(lpBand->fDraw&DRAW_FIRST_IN_ROW) )
1808                 continue;
1809             if( !(lpBand->fDraw&DRAW_LAST_IN_ROW) )
1810                 continue;
1811
1812             if (lpBand->fMask & RBBS_VARIABLEHEIGHT) continue;
1813             if (((INT)lpBand->cyMaxChild < 1) ||
1814                 ((INT)lpBand->cyIntegral < 1)) {
1815                 if (lpBand->cyMaxChild + lpBand->cyIntegral == 0) continue;
1816                 ERR("P2b band %u RBBS_VARIABLEHEIGHT set but cyMax=%d, cyInt=%d\n",
1817                     i, lpBand->cyMaxChild, lpBand->cyIntegral);
1818                 continue;
1819             }
1820             /* j is now the maximum height/width in the client area */
1821             j = ((diff / lpBand->cyIntegral) * lpBand->cyIntegral) +
1822                 ircBw(lpBand);
1823             if (j > lpBand->cyMaxChild + REBARSPACE(lpBand))
1824                 j = lpBand->cyMaxChild + REBARSPACE(lpBand);
1825             diff -= (j - ircBw(lpBand));
1826             if (infoPtr->dwStyle & CCS_VERT)
1827                 lpBand->rcBand.right = lpBand->rcBand.left + j;
1828             else
1829                 lpBand->rcBand.bottom = lpBand->rcBand.top + j;
1830             TRACE("P2b band %d, row %d changed to (%ld,%ld)-(%ld,%ld)\n",
1831                   i, lpBand->iRow,
1832                   lpBand->rcBand.left, lpBand->rcBand.top,
1833                   lpBand->rcBand.right, lpBand->rcBand.bottom);
1834             if (diff <= 0) break;
1835         }
1836         if (diff < 0) {
1837             ERR("P2b allocated more than available, diff=%d\n", diff);
1838             diff = 0;
1839         }
1840         if (infoPtr->dwStyle & CCS_VERT)
1841             x = clientcx - diff;
1842         else
1843             y = clientcy - diff;
1844     }
1845
1846     /* ******* End Phase 2b - adjust all bands for height full ******* */
1847
1848
1849     /* ******* Start Phase 3 - adjust all bands for width full ******* */
1850
1851     if (infoPtr->uNumBands) {
1852         int startband;
1853
1854         /* If RBS_BANDBORDERS set then indicate to draw bottom separator */
1855         /* on all bands in all rows but last row.                        */
1856         /* Also indicate to draw the right separator for each band in    */
1857         /* each row but the rightmost band.                              */
1858         if (infoPtr->dwStyle & RBS_BANDBORDERS) {
1859
1860             for (i=0; i<infoPtr->uNumBands; i++) {
1861                 lpBand = &infoPtr->bands[i];
1862                 if (HIDDENBAND(lpBand))
1863                     continue;
1864
1865                 /* not righthand bands */
1866                 if( !(lpBand->fDraw & DRAW_LAST_IN_ROW) )
1867                     lpBand->fDraw |= DRAW_RIGHTSEP;
1868
1869                 /* not the last row */
1870                 if( lpBand->iRow != infoPtr->uNumRows )
1871                     lpBand->fDraw |= DRAW_BOTTOMSEP;
1872             }
1873         }
1874
1875         /* Distribute the extra space on the horizontal and adjust  */
1876         /* all bands in row to same height.                         */
1877         mcy = 0;
1878         startband = -1;
1879         for (i=0; i<infoPtr->uNumBands; i++) {
1880
1881             lpBand = &infoPtr->bands[i];
1882
1883             if( lpBand->fDraw & DRAW_FIRST_IN_ROW )
1884             {
1885                 startband = i;
1886                 mcy = 0;
1887             }
1888
1889             if ( (mcy < ircBw(lpBand)) && !HIDDENBAND(lpBand) )
1890                 mcy = ircBw(lpBand);
1891
1892             if( lpBand->fDraw & DRAW_LAST_IN_ROW )
1893             {
1894                 TRACE("P3 processing row %d, starting band %d, ending band %d\n",
1895                       lpBand->iRow, startband, i);
1896                 if( startband < 0 )
1897                     ERR("Last band %d with no first, row %d\n", i, lpBand->iRow);
1898
1899                 REBAR_AdjustBands (infoPtr, startband, i,
1900                                (infoPtr->dwStyle & CCS_VERT) ?
1901                                clientcy : clientcx, mcy);
1902             }
1903         }
1904
1905         /* Calculate the other rectangles in each band */
1906         if (infoPtr->dwStyle & CCS_VERT) {
1907             REBAR_CalcVertBand (infoPtr, 0, infoPtr->uNumBands,
1908                                 notify);
1909         }
1910         else {
1911             REBAR_CalcHorzBand (infoPtr, 0, infoPtr->uNumBands,
1912                                 notify);
1913         }
1914     }
1915
1916     /* ******* End Phase 3 - adjust all bands for width full ******* */
1917
1918     /* now compute size of Rebar itself */
1919     infoPtr->oldSize = infoPtr->calcSize;
1920     if (infoPtr->uNumBands == 0) {
1921         /* we have no bands, so make size the size of client */
1922         x = clientcx;
1923         y = clientcy;
1924     }
1925     if (infoPtr->dwStyle & CCS_VERT) {
1926         if( x < REBAR_MINSIZE )
1927             x = REBAR_MINSIZE;
1928         infoPtr->calcSize.cx = x;
1929         infoPtr->calcSize.cy = clientcy;
1930         TRACE("vert, notify=%d, x=%d, origheight=%d\n",
1931               notify, x, origheight);
1932         if (notify && (x != origheight)) infoPtr->fStatus |= NTF_HGHTCHG;
1933     }
1934     else {
1935         if( y < REBAR_MINSIZE )
1936             y = REBAR_MINSIZE;
1937         infoPtr->calcSize.cx = clientcx;
1938         infoPtr->calcSize.cy = y;
1939         TRACE("horz, notify=%d, y=%d, origheight=%d\n",
1940               notify, y, origheight);
1941         if (notify && (y != origheight)) infoPtr->fStatus |= NTF_HGHTCHG;
1942     }
1943
1944     REBAR_DumpBand (infoPtr);
1945
1946     REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands);
1947
1948     REBAR_ForceResize (infoPtr);
1949 }
1950
1951
1952 static VOID
1953 REBAR_ValidateBand (REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
1954      /* Function:  This routine evaluates the band specs supplied */
1955      /*  by the user and updates the following 5 fields in        */
1956      /*  the internal band structure: cxHeader, lcx, lcy, hcx, hcy*/
1957 {
1958     UINT header=0;
1959     UINT textheight=0;
1960     UINT i, nonfixed;
1961     REBAR_BAND *tBand;
1962
1963     lpBand->fStatus = 0;
1964     lpBand->lcx = 0;
1965     lpBand->lcy = 0;
1966     lpBand->ccx = 0;
1967     lpBand->ccy = 0;
1968     lpBand->hcx = 0;
1969     lpBand->hcy = 0;
1970
1971     /* Data comming in from users into the cx... and cy... fields  */
1972     /* may be bad, just garbage, because the user never clears     */
1973     /* the fields. RB_{SET|INSERT}BAND{A|W} just passes the data   */
1974     /* along if the fields exist in the input area. Here we must   */
1975     /* determine if the data is valid. I have no idea how MS does  */
1976     /* the validation, but it does because the RB_GETBANDINFO      */
1977     /* returns a 0 when I know the sample program passed in an     */
1978     /* address. Here I will use the algorithim that if the value   */
1979     /* is greater than 65535 then it is bad and replace it with    */
1980     /* a zero. Feel free to improve the algorithim.  -  GA 12/2000 */
1981     if (lpBand->cxMinChild > 65535) lpBand->cxMinChild = 0;
1982     if (lpBand->cyMinChild > 65535) lpBand->cyMinChild = 0;
1983     if (lpBand->cx         > 65535) lpBand->cx         = 0;
1984     if (lpBand->cyChild    > 65535) lpBand->cyChild    = 0;
1985     if (lpBand->cyMaxChild > 65535) lpBand->cyMaxChild = 0;
1986     if (lpBand->cyIntegral > 65535) lpBand->cyIntegral = 0;
1987     if (lpBand->cxIdeal    > 65535) lpBand->cxIdeal    = 0;
1988     if (lpBand->cxHeader   > 65535) lpBand->cxHeader   = 0;
1989
1990     /* FIXME: probably should only set NEEDS_LAYOUT flag when */
1991     /*        values change. Till then always set it.         */
1992     TRACE("setting NEEDS_LAYOUT\n");
1993     infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
1994
1995     /* Header is where the image, text and gripper exist  */
1996     /* in the band and preceed the child window.          */
1997
1998     /* count number of non-FIXEDSIZE and non-Hidden bands */
1999     nonfixed = 0;
2000     for (i=0; i<infoPtr->uNumBands; i++){
2001         tBand = &infoPtr->bands[i];
2002         if (!HIDDENBAND(tBand) && !(tBand->fStyle & RBBS_FIXEDSIZE))
2003             nonfixed++;
2004     }
2005
2006     /* calculate gripper rectangle */
2007     if (  (!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
2008           ( (lpBand->fStyle & RBBS_GRIPPERALWAYS) ||
2009             ( !(lpBand->fStyle & RBBS_FIXEDSIZE) && (nonfixed > 1)))
2010        ) {
2011         lpBand->fStatus |= HAS_GRIPPER;
2012         if (infoPtr->dwStyle & CCS_VERT)
2013             if (infoPtr->dwStyle & RBS_VERTICALGRIPPER)
2014                 header += (GRIPPER_HEIGHT + REBAR_PRE_GRIPPER);
2015             else
2016                 header += (GRIPPER_WIDTH + REBAR_PRE_GRIPPER);
2017         else
2018             header += (REBAR_PRE_GRIPPER + GRIPPER_WIDTH);
2019         /* Always have 4 pixels before anything else */
2020         header += REBAR_ALWAYS_SPACE;
2021     }
2022
2023     /* image is visible */
2024     if ((lpBand->fMask & RBBIM_IMAGE) && (infoPtr->himl)) {
2025         lpBand->fStatus |= HAS_IMAGE;
2026         if (infoPtr->dwStyle & CCS_VERT) {
2027            header += (infoPtr->imageSize.cy + REBAR_POST_IMAGE);
2028            lpBand->lcy = infoPtr->imageSize.cx + 2;
2029         }
2030         else {
2031            header += (infoPtr->imageSize.cx + REBAR_POST_IMAGE);
2032            lpBand->lcy = infoPtr->imageSize.cy + 2;
2033         }
2034     }
2035
2036     /* text is visible */
2037     if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText) &&
2038         !(lpBand->fStyle & RBBS_HIDETITLE)) {
2039         HDC hdc = GetDC (0);
2040         HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
2041         SIZE size;
2042
2043         lpBand->fStatus |= HAS_TEXT;
2044         GetTextExtentPoint32W (hdc, lpBand->lpText,
2045                                lstrlenW (lpBand->lpText), &size);
2046         header += ((infoPtr->dwStyle & CCS_VERT) ? (size.cy + REBAR_POST_TEXT) : (size.cx + REBAR_POST_TEXT));
2047         textheight = (infoPtr->dwStyle & CCS_VERT) ? 0 : size.cy;
2048
2049         SelectObject (hdc, hOldFont);
2050         ReleaseDC (0, hdc);
2051     }
2052
2053     /* if no gripper but either image or text, then leave space */
2054     if ((lpBand->fStatus & (HAS_IMAGE | HAS_TEXT)) &&
2055         !(lpBand->fStatus & HAS_GRIPPER)) {
2056         header += REBAR_ALWAYS_SPACE;
2057     }
2058
2059     /* check if user overrode the header value */
2060     if (!(lpBand->fMask & RBBIM_HEADERSIZE))
2061         lpBand->cxHeader = header;
2062
2063
2064     /* Now compute minimum size of child window */
2065     lpBand->offChild.cx = 0;
2066     lpBand->offChild.cy = 0;
2067     lpBand->lcy = textheight;
2068     lpBand->ccy = lpBand->lcy;
2069     if (lpBand->fMask & RBBIM_CHILDSIZE) {
2070         lpBand->lcx = lpBand->cxMinChild;
2071
2072         /* Set the .cy values for CHILDSIZE case */
2073         lpBand->lcy = max(lpBand->lcy, lpBand->cyMinChild);
2074         lpBand->ccy = lpBand->lcy;
2075         lpBand->hcy = lpBand->lcy;
2076         if (lpBand->cyMaxChild != 0xffffffff) {
2077             lpBand->hcy = lpBand->cyMaxChild;
2078         }
2079         if (lpBand->cyChild != 0xffffffff)
2080             lpBand->ccy = max (lpBand->cyChild, lpBand->lcy);
2081
2082         TRACE("_CHILDSIZE\n");
2083     }
2084     if (lpBand->fMask & RBBIM_SIZE) {
2085         lpBand->hcx = max (lpBand->cx-lpBand->cxHeader, lpBand->lcx);
2086         TRACE("_SIZE\n");
2087     }
2088     else
2089         lpBand->hcx = lpBand->lcx;
2090     lpBand->ccx = lpBand->hcx;
2091
2092     /* make ->.cx include header size for _Layout */
2093     lpBand->lcx += lpBand->cxHeader;
2094     lpBand->ccx += lpBand->cxHeader;
2095     lpBand->hcx += lpBand->cxHeader;
2096
2097 }
2098
2099 static BOOL
2100 REBAR_CommonSetupBand (HWND hwnd, LPREBARBANDINFOA lprbbi, REBAR_BAND *lpBand)
2101      /* Function:  This routine copies the supplied values from   */
2102      /*  user input (lprbbi) to the internal band structure.      */
2103      /*  It returns true if something changed and false if not.   */
2104 {
2105     BOOL bChanged = FALSE;
2106
2107     lpBand->fMask |= lprbbi->fMask;
2108
2109     if( (lprbbi->fMask & RBBIM_STYLE) &&
2110         (lpBand->fStyle != lprbbi->fStyle ) )
2111     {
2112         lpBand->fStyle = lprbbi->fStyle;
2113         bChanged = TRUE;
2114     }
2115
2116     if( (lprbbi->fMask & RBBIM_COLORS) &&
2117        ( ( lpBand->clrFore != lprbbi->clrFore ) ||
2118          ( lpBand->clrBack != lprbbi->clrBack ) ) )
2119     {
2120         lpBand->clrFore = lprbbi->clrFore;
2121         lpBand->clrBack = lprbbi->clrBack;
2122         bChanged = TRUE;
2123     }
2124
2125     if( (lprbbi->fMask & RBBIM_IMAGE) &&
2126        ( lpBand->iImage != lprbbi->iImage ) )
2127     {
2128         lpBand->iImage = lprbbi->iImage;
2129         bChanged = TRUE;
2130     }
2131
2132     if( (lprbbi->fMask & RBBIM_CHILD) &&
2133        (lprbbi->hwndChild != lpBand->hwndChild ) )
2134     {
2135         if (lprbbi->hwndChild) {
2136             lpBand->hwndChild = lprbbi->hwndChild;
2137             lpBand->hwndPrevParent =
2138                 SetParent (lpBand->hwndChild, hwnd);
2139             /* below in trace fro WinRAR */
2140             ShowWindow(lpBand->hwndChild, SW_SHOWNOACTIVATE | SW_SHOWNORMAL);
2141             /* above in trace fro WinRAR */
2142         }
2143         else {
2144             TRACE("child: %p  prev parent: %p\n",
2145                    lpBand->hwndChild, lpBand->hwndPrevParent);
2146             lpBand->hwndChild = 0;
2147             lpBand->hwndPrevParent = 0;
2148         }
2149         bChanged = TRUE;
2150     }
2151
2152     if( (lprbbi->fMask & RBBIM_CHILDSIZE) &&
2153         ( (lpBand->cxMinChild != lprbbi->cxMinChild) ||
2154           (lpBand->cyMinChild != lprbbi->cyMinChild ) ||
2155           ( (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) &&
2156             ( (lpBand->cyChild    != lprbbi->cyChild ) ||
2157               (lpBand->cyMaxChild != lprbbi->cyMaxChild ) ||
2158               (lpBand->cyIntegral != lprbbi->cyIntegral ) ) ) ||
2159           ( (lprbbi->cbSize < sizeof (REBARBANDINFOA)) &&
2160             ( (lpBand->cyChild || 
2161                lpBand->cyMaxChild || 
2162                lpBand->cyIntegral ) ) ) ) )
2163     {
2164         lpBand->cxMinChild = lprbbi->cxMinChild;
2165         lpBand->cyMinChild = lprbbi->cyMinChild;
2166         if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
2167             lpBand->cyChild    = lprbbi->cyChild;
2168             lpBand->cyMaxChild = lprbbi->cyMaxChild;
2169             lpBand->cyIntegral = lprbbi->cyIntegral;
2170         }
2171         else { /* special case - these should be zeroed out since   */
2172                /* RBBIM_CHILDSIZE added these in WIN32_IE >= 0x0400 */
2173             lpBand->cyChild    = 0;
2174             lpBand->cyMaxChild = 0;
2175             lpBand->cyIntegral = 0;
2176         }
2177         bChanged = TRUE;
2178     }
2179
2180     if( (lprbbi->fMask & RBBIM_SIZE) &&
2181         (lpBand->cx != lprbbi->cx ) )
2182     {
2183         lpBand->cx = lprbbi->cx;
2184         bChanged = TRUE;
2185     }
2186
2187     if( (lprbbi->fMask & RBBIM_BACKGROUND) &&
2188        ( lpBand->hbmBack != lprbbi->hbmBack ) )
2189     {
2190         lpBand->hbmBack = lprbbi->hbmBack;
2191         bChanged = TRUE;
2192     }
2193
2194     if( (lprbbi->fMask & RBBIM_ID) &&
2195         (lpBand->wID != lprbbi->wID ) )
2196     {
2197         lpBand->wID = lprbbi->wID;
2198         bChanged = TRUE;
2199     }
2200
2201     /* check for additional data */
2202     if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
2203         if( (lprbbi->fMask & RBBIM_IDEALSIZE) &&
2204             ( lpBand->cxIdeal != lprbbi->cxIdeal ) )
2205         {
2206             lpBand->cxIdeal = lprbbi->cxIdeal;
2207             bChanged = TRUE;
2208         }
2209
2210         if( (lprbbi->fMask & RBBIM_LPARAM) &&
2211             (lpBand->lParam != lprbbi->lParam ) )
2212         {
2213             lpBand->lParam = lprbbi->lParam;
2214             bChanged = TRUE;
2215         }
2216
2217         if( (lprbbi->fMask & RBBIM_HEADERSIZE) &&
2218             (lpBand->cxHeader != lprbbi->cxHeader ) )
2219         {
2220             lpBand->cxHeader = lprbbi->cxHeader;
2221             bChanged = TRUE;
2222         }
2223     }
2224
2225     return bChanged;
2226 }
2227
2228 static LRESULT
2229 REBAR_InternalEraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, RECT *clip)
2230      /* Function:  This erases the background rectangle by drawing  */
2231      /*  each band with its background color (or the default) and   */
2232      /*  draws each bands right separator if necessary. The row     */
2233      /*  separators are drawn on the first band of the next row.    */
2234 {
2235     REBAR_BAND *lpBand;
2236     UINT i;
2237     INT oldrow;
2238     HDC hdc = (HDC)wParam;
2239     RECT rect;
2240     COLORREF old = CLR_NONE, new;
2241
2242     oldrow = -1;
2243     for(i=0; i<infoPtr->uNumBands; i++) {
2244         lpBand = &infoPtr->bands[i];
2245         if (HIDDENBAND(lpBand)) continue;
2246
2247         /* draw band separator between rows */
2248         if (lpBand->iRow != oldrow) {
2249             oldrow = lpBand->iRow;
2250             if (lpBand->fDraw & DRAW_BOTTOMSEP) {
2251                 RECT rcRowSep;
2252                 rcRowSep = lpBand->rcBand;
2253                 if (infoPtr->dwStyle & CCS_VERT) {
2254                     rcRowSep.right += SEP_WIDTH_SIZE;
2255                     rcRowSep.bottom = infoPtr->calcSize.cy;
2256                     DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_RIGHT);
2257                 }
2258                 else {
2259                     rcRowSep.bottom += SEP_WIDTH_SIZE;
2260                     rcRowSep.right = infoPtr->calcSize.cx;
2261                     DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_BOTTOM);
2262                 }
2263                 TRACE ("drawing band separator bottom (%ld,%ld)-(%ld,%ld)\n",
2264                        rcRowSep.left, rcRowSep.top,
2265                        rcRowSep.right, rcRowSep.bottom);
2266             }
2267         }
2268
2269         /* draw band separator between bands in a row */
2270         if (lpBand->fDraw & DRAW_RIGHTSEP) {
2271             RECT rcSep;
2272             rcSep = lpBand->rcBand;
2273             if (infoPtr->dwStyle & CCS_VERT) {
2274                 rcSep.bottom += SEP_WIDTH_SIZE;
2275                 DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOM);
2276             }
2277             else {
2278                 rcSep.right += SEP_WIDTH_SIZE;
2279                 DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_RIGHT);
2280             }
2281             TRACE("drawing band separator right (%ld,%ld)-(%ld,%ld)\n",
2282                   rcSep.left, rcSep.top, rcSep.right, rcSep.bottom);
2283         }
2284
2285         /* draw the actual background */
2286         if (lpBand->clrBack != CLR_NONE) {
2287             new = (lpBand->clrBack == CLR_DEFAULT) ? infoPtr->clrBtnFace :
2288                     lpBand->clrBack;
2289 #if GLATESTING
2290             /* testing only - make background green to see it */
2291             new = RGB(0,128,0);
2292 #endif
2293         }
2294         else {
2295             /* In the absence of documentation for Rebar vs. CLR_NONE,
2296              * we will use the default BtnFace color. Note documentation
2297              * exists for Listview and Imagelist.
2298              */
2299             new = infoPtr->clrBtnFace;
2300 #if GLATESTING
2301             /* testing only - make background green to see it */
2302             new = RGB(0,128,0);
2303 #endif
2304         }
2305         old = SetBkColor (hdc, new);
2306
2307         rect = lpBand->rcBand;
2308         TRACE("%s background color=0x%06lx, band (%ld,%ld)-(%ld,%ld), clip (%ld,%ld)-(%ld,%ld)\n",
2309               (lpBand->clrBack == CLR_NONE) ? "none" :
2310                 ((lpBand->clrBack == CLR_DEFAULT) ? "dft" : ""),
2311               GetBkColor(hdc),
2312               lpBand->rcBand.left,lpBand->rcBand.top,
2313               lpBand->rcBand.right,lpBand->rcBand.bottom,
2314               clip->left, clip->top,
2315               clip->right, clip->bottom);
2316         ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, 0);
2317         if (lpBand->clrBack != CLR_NONE)
2318             SetBkColor (hdc, old);
2319     }
2320     return TRUE;
2321 }
2322
2323 static void
2324 REBAR_InternalHitTest (REBAR_INFO *infoPtr, const LPPOINT lpPt, UINT *pFlags, INT *pBand)
2325 {
2326     REBAR_BAND *lpBand;
2327     RECT rect;
2328     UINT  iCount;
2329
2330     GetClientRect (infoPtr->hwndSelf, &rect);
2331
2332     *pFlags = RBHT_NOWHERE;
2333     if (PtInRect (&rect, *lpPt))
2334     {
2335         if (infoPtr->uNumBands == 0) {
2336             *pFlags = RBHT_NOWHERE;
2337             if (pBand)
2338                 *pBand = -1;
2339             TRACE("NOWHERE\n");
2340             return;
2341         }
2342         else {
2343             /* somewhere inside */
2344             for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
2345                 lpBand = &infoPtr->bands[iCount];
2346                 if (HIDDENBAND(lpBand)) continue;
2347                 if (PtInRect (&lpBand->rcBand, *lpPt)) {
2348                     if (pBand)
2349                         *pBand = iCount;
2350                     if (PtInRect (&lpBand->rcGripper, *lpPt)) {
2351                         *pFlags = RBHT_GRABBER;
2352                         TRACE("ON GRABBER %d\n", iCount);
2353                         return;
2354                     }
2355                     else if (PtInRect (&lpBand->rcCapImage, *lpPt)) {
2356                         *pFlags = RBHT_CAPTION;
2357                         TRACE("ON CAPTION %d\n", iCount);
2358                         return;
2359                     }
2360                     else if (PtInRect (&lpBand->rcCapText, *lpPt)) {
2361                         *pFlags = RBHT_CAPTION;
2362                         TRACE("ON CAPTION %d\n", iCount);
2363                         return;
2364                     }
2365                     else if (PtInRect (&lpBand->rcChild, *lpPt)) {
2366                         *pFlags = RBHT_CLIENT;
2367                         TRACE("ON CLIENT %d\n", iCount);
2368                         return;
2369                     }
2370                     else if (PtInRect (&lpBand->rcChevron, *lpPt)) {
2371                         *pFlags = RBHT_CHEVRON;
2372                         TRACE("ON CHEVRON %d\n", iCount);
2373                         return;
2374                     }
2375                     else {
2376                         *pFlags = RBHT_NOWHERE;
2377                         TRACE("NOWHERE %d\n", iCount);
2378                         return;
2379                     }
2380                 }
2381             }
2382
2383             *pFlags = RBHT_NOWHERE;
2384             if (pBand)
2385                 *pBand = -1;
2386
2387             TRACE("NOWHERE\n");
2388             return;
2389         }
2390     }
2391     else {
2392         *pFlags = RBHT_NOWHERE;
2393         if (pBand)
2394             *pBand = -1;
2395         TRACE("NOWHERE\n");
2396         return;
2397     }
2398 }
2399
2400
2401 static INT
2402 REBAR_Shrink (REBAR_INFO *infoPtr, REBAR_BAND *band, INT movement, INT i)
2403      /* Function:  This attempts to shrink the given band by the  */
2404      /*  the amount in "movement". A shrink to the left is indi-  */
2405      /*  cated by "movement" being negative. "i" is merely the    */
2406      /*  band index for trace messages.                           */
2407 {
2408     INT Leadjust, Readjust, avail, ret;
2409
2410     /* Note: a left drag is indicated by "movement" being negative.  */
2411     /*       Similarly, a right drag is indicated by "movement"      */
2412     /*       being positive. "movement" should never be 0, but if    */
2413     /*       it is then the band does not move.                      */
2414
2415     avail = rcBw(band) - band->lcx;
2416
2417     /* now compute the Left End adjustment factor and Right End */
2418     /* adjustment factor. They may be different if shrinking.   */
2419     if (avail <= 0) {
2420         /* if this band is not shrinkable, then just move it */
2421         Leadjust = Readjust = movement;
2422         ret = movement;
2423     }
2424     else {
2425         if (movement < 0) {
2426             /* Drag to left */
2427             if (avail <= abs(movement)) {
2428                 Readjust = movement;
2429                 Leadjust = movement + avail;
2430                 ret = Leadjust;
2431             }
2432             else {
2433                 Readjust = movement;
2434                 Leadjust = 0;
2435                 ret = 0;
2436             }
2437         }
2438         else {
2439             /* Drag to right */
2440             if (avail <= abs(movement)) {
2441                 Leadjust = movement;
2442                 Readjust = movement - avail;
2443                 ret = Readjust;
2444             }
2445             else {
2446                 Leadjust = movement;
2447                 Readjust = 0;
2448                 ret = 0;
2449             }
2450         }
2451     }
2452
2453     /* Reasonability Check */
2454     if (rcBlt(band) + Leadjust < 0) {
2455         ERR("adjustment will fail, band %d: left=%d, right=%d, move=%d, rtn=%d\n",
2456             i, Leadjust, Readjust, movement, ret);
2457     }
2458
2459     LEADJ(band, Leadjust);
2460     READJ(band, Readjust);
2461
2462     TRACE("band %d:  left=%d, right=%d, move=%d, rtn=%d, rcBand=(%ld,%ld)-(%ld,%ld)\n",
2463           i, Leadjust, Readjust, movement, ret,
2464           band->rcBand.left, band->rcBand.top,
2465           band->rcBand.right, band->rcBand.bottom);
2466     return ret;
2467 }
2468
2469
2470 static void
2471 REBAR_HandleLRDrag (REBAR_INFO *infoPtr, POINTS *ptsmove)
2472      /* Function:  This will implement the functionality of a     */
2473      /*  Gripper drag within a row. It will not implement "out-   */
2474      /*  of-row" drags. (They are detected and handled in         */
2475      /*  REBAR_MouseMove.)                                        */
2476      /*  **** FIXME Switching order of bands in a row not   ****  */
2477      /*  ****       yet implemented.                        ****  */
2478 {
2479     REBAR_BAND *hitBand, *band, *mindBand, *maxdBand;
2480     RECT newrect;
2481     INT imindBand = -1, imaxdBand, ihitBand, i, movement;
2482     INT RHeaderSum = 0, LHeaderSum = 0;
2483     INT compress;
2484
2485     /* on first significant mouse movement, issue notify */
2486
2487     if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
2488         if (REBAR_Notify_NMREBAR (infoPtr, -1, RBN_BEGINDRAG)) {
2489             /* Notify returned TRUE - abort drag */
2490             infoPtr->dragStart.x = 0;
2491             infoPtr->dragStart.y = 0;
2492             infoPtr->dragNow = infoPtr->dragStart;
2493             infoPtr->iGrabbedBand = -1;
2494             ReleaseCapture ();
2495             return ;
2496         }
2497         infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
2498     }
2499
2500     ihitBand = infoPtr->iGrabbedBand;
2501     hitBand = &infoPtr->bands[ihitBand];
2502     imaxdBand = ihitBand; /* to suppress warning message */
2503
2504     /* find all the bands in the row of the one whose Gripper was seized */
2505     for (i=0; i<infoPtr->uNumBands; i++) {
2506         band = &infoPtr->bands[i];
2507         if (HIDDENBAND(band)) continue;
2508         if (band->iRow == hitBand->iRow) {
2509             imaxdBand = i;
2510             if (imindBand == -1) imindBand = i;
2511             /* minimum size of each band is size of header plus            */
2512             /* size of minimum child plus offset of child from header plus */
2513             /* a one to separate each band.                                */
2514             if (i < ihitBand)
2515                 LHeaderSum += (band->lcx + SEP_WIDTH);
2516             else
2517                 RHeaderSum += (band->lcx + SEP_WIDTH);
2518
2519         }
2520     }
2521     if (RHeaderSum) RHeaderSum -= SEP_WIDTH; /* no separator after last band */
2522
2523     mindBand = &infoPtr->bands[imindBand];
2524     maxdBand = &infoPtr->bands[imaxdBand];
2525
2526     if (imindBand == imaxdBand) return; /* nothing to drag against */
2527     if (imindBand == ihitBand) return; /* first band in row, can't drag */
2528
2529     /* limit movement to inside adjustable bands - Left */
2530     if ( (ptsmove->x < mindBand->rcBand.left) ||
2531          (ptsmove->x > maxdBand->rcBand.right) ||
2532          (ptsmove->y < mindBand->rcBand.top) ||
2533          (ptsmove->y > maxdBand->rcBand.bottom))
2534         return; /* should swap bands */
2535
2536     if (infoPtr->dwStyle & CCS_VERT)
2537         movement = ptsmove->y - ((hitBand->rcBand.top+REBAR_PRE_GRIPPER) -
2538                              infoPtr->ihitoffset);
2539     else
2540         movement = ptsmove->x - ((hitBand->rcBand.left+REBAR_PRE_GRIPPER) -
2541                              infoPtr->ihitoffset);
2542     infoPtr->dragNow = *ptsmove;
2543
2544     TRACE("before: movement=%d (%d,%d), imindBand=%d, ihitBand=%d, imaxdBand=%d, LSum=%d, RSum=%d\n",
2545           movement, ptsmove->x, ptsmove->y, imindBand, ihitBand,
2546           imaxdBand, LHeaderSum, RHeaderSum);
2547     REBAR_DumpBand (infoPtr);
2548
2549     if (movement < 0) {
2550
2551         /* ***  Drag left/up *** */
2552         compress = rcBlt(hitBand) - rcBlt(mindBand) -
2553                    LHeaderSum;
2554         if (compress < abs(movement)) {
2555             TRACE("limiting left drag, was %d changed to %d\n",
2556                   movement, -compress);
2557             movement = -compress;
2558         }
2559
2560         for (i=ihitBand; i>=imindBand; i--) {
2561             band = &infoPtr->bands[i];
2562             if (HIDDENBAND(band)) continue;
2563             if (i == ihitBand) {
2564                 LEADJ(band, movement);
2565             }
2566             else
2567                 movement = REBAR_Shrink (infoPtr, band, movement, i);
2568             band->ccx = rcBw(band);
2569         }
2570     }
2571     else {
2572         BOOL first = TRUE;
2573
2574         /* ***  Drag right/down *** */
2575         compress = rcBrb(maxdBand) - rcBlt(hitBand) -
2576                    RHeaderSum;
2577         if (compress < abs(movement)) {
2578             TRACE("limiting right drag, was %d changed to %d\n",
2579                   movement, compress);
2580             movement = compress;
2581         }
2582         for (i=ihitBand-1; i<=imaxdBand; i++) {
2583             band = &infoPtr->bands[i];
2584             if (HIDDENBAND(band)) continue;
2585             if (first) {
2586                 first = FALSE;
2587                 READJ(band, movement);
2588             }
2589             else
2590                 movement = REBAR_Shrink (infoPtr, band, movement, i);
2591             band->ccx = rcBw(band);
2592         }
2593     }
2594
2595     /* recompute all rectangles */
2596     if (infoPtr->dwStyle & CCS_VERT) {
2597         REBAR_CalcVertBand (infoPtr, imindBand, imaxdBand+1,
2598                             FALSE);
2599     }
2600     else {
2601         REBAR_CalcHorzBand (infoPtr, imindBand, imaxdBand+1,
2602                             FALSE);
2603     }
2604
2605     TRACE("bands after adjustment, see band # %d, %d\n",
2606           imindBand, imaxdBand);
2607     REBAR_DumpBand (infoPtr);
2608
2609     SetRect (&newrect,
2610              mindBand->rcBand.left,
2611              mindBand->rcBand.top,
2612              maxdBand->rcBand.right,
2613              maxdBand->rcBand.bottom);
2614
2615     REBAR_MoveChildWindows (infoPtr, imindBand, imaxdBand+1);
2616
2617     InvalidateRect (infoPtr->hwndSelf, &newrect, TRUE);
2618     UpdateWindow (infoPtr->hwndSelf);
2619
2620 }
2621
2622
2623
2624 /* << REBAR_BeginDrag >> */
2625
2626
2627 static LRESULT
2628 REBAR_DeleteBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
2629 {
2630     UINT uBand = (UINT)wParam;
2631     HWND childhwnd = 0;
2632     REBAR_BAND *lpBand;
2633
2634     if (uBand >= infoPtr->uNumBands)
2635         return FALSE;
2636
2637     TRACE("deleting band %u!\n", uBand);
2638     lpBand = &infoPtr->bands[uBand];
2639     REBAR_Notify_NMREBAR (infoPtr, uBand, RBN_DELETINGBAND);
2640
2641     if (infoPtr->uNumBands == 1) {
2642         TRACE(" simple delete!\n");
2643         if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild)
2644             childhwnd = lpBand->hwndChild;
2645         Free (infoPtr->bands);
2646         infoPtr->bands = NULL;
2647         infoPtr->uNumBands = 0;
2648     }
2649     else {
2650         REBAR_BAND *oldBands = infoPtr->bands;
2651         TRACE("complex delete! [uBand=%u]\n", uBand);
2652
2653         if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild)
2654             childhwnd = lpBand->hwndChild;
2655
2656         infoPtr->uNumBands--;
2657         infoPtr->bands = Alloc (sizeof (REBAR_BAND) * infoPtr->uNumBands);
2658         if (uBand > 0) {
2659             memcpy (&infoPtr->bands[0], &oldBands[0],
2660                     uBand * sizeof(REBAR_BAND));
2661         }
2662
2663         if (uBand < infoPtr->uNumBands) {
2664             memcpy (&infoPtr->bands[uBand], &oldBands[uBand+1],
2665                     (infoPtr->uNumBands - uBand) * sizeof(REBAR_BAND));
2666         }
2667
2668         Free (oldBands);
2669     }
2670
2671     if (childhwnd)
2672         ShowWindow (childhwnd, SW_HIDE);
2673
2674     REBAR_Notify_NMREBAR (infoPtr, -1, RBN_DELETEDBAND);
2675
2676     /* if only 1 band left the re-validate to possible eliminate gripper */
2677     if (infoPtr->uNumBands == 1)
2678       REBAR_ValidateBand (infoPtr, &infoPtr->bands[0]);
2679
2680     TRACE("setting NEEDS_LAYOUT\n");
2681     infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
2682     infoPtr->fStatus |= RESIZE_ANYHOW;
2683     REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
2684
2685     return TRUE;
2686 }
2687
2688
2689 /* << REBAR_DragMove >> */
2690 /* << REBAR_EndDrag >> */
2691
2692
2693 static LRESULT
2694 REBAR_GetBandBorders (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
2695 {
2696     LPRECT lpRect = (LPRECT)lParam;
2697     REBAR_BAND *lpBand;
2698
2699     if (!lParam)
2700         return 0;
2701     if ((UINT)wParam >= infoPtr->uNumBands)
2702         return 0;
2703
2704     lpBand = &infoPtr->bands[(UINT)wParam];
2705
2706     /* FIXME - the following values were determined by experimentation */
2707     /* with the REBAR Control Spy. I have guesses as to what the 4 and */
2708     /* 1 are, but I am not sure. There doesn't seem to be any actual   */
2709     /* difference in size of the control area with and without the     */
2710     /* style.  -  GA                                                   */
2711     if (infoPtr->dwStyle & RBS_BANDBORDERS) {
2712         if (infoPtr->dwStyle & CCS_VERT) {
2713             lpRect->left = 1;
2714             lpRect->top = lpBand->cxHeader + 4;
2715             lpRect->right = 1;
2716             lpRect->bottom = 0;
2717         }
2718         else {
2719             lpRect->left = lpBand->cxHeader + 4;
2720             lpRect->top = 1;
2721             lpRect->right = 0;
2722             lpRect->bottom = 1;
2723         }
2724     }
2725     else {
2726         lpRect->left = lpBand->cxHeader;
2727     }
2728     return 0;
2729 }
2730
2731
2732 inline static LRESULT
2733 REBAR_GetBandCount (REBAR_INFO *infoPtr)
2734 {
2735     TRACE("band count %u!\n", infoPtr->uNumBands);
2736
2737     return infoPtr->uNumBands;
2738 }
2739
2740
2741 static LRESULT
2742 REBAR_GetBandInfoA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
2743 {
2744     LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
2745     REBAR_BAND *lpBand;
2746
2747     if (lprbbi == NULL)
2748         return FALSE;
2749     if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
2750         return FALSE;
2751     if ((UINT)wParam >= infoPtr->uNumBands)
2752         return FALSE;
2753
2754     TRACE("index %u\n", (UINT)wParam);
2755
2756     /* copy band information */
2757     lpBand = &infoPtr->bands[(UINT)wParam];
2758
2759     if (lprbbi->fMask & RBBIM_STYLE)
2760         lprbbi->fStyle = lpBand->fStyle;
2761
2762     if (lprbbi->fMask & RBBIM_COLORS) {
2763         lprbbi->clrFore = lpBand->clrFore;
2764         lprbbi->clrBack = lpBand->clrBack;
2765         if (lprbbi->clrBack == CLR_DEFAULT)
2766             lprbbi->clrBack = infoPtr->clrBtnFace;
2767     }
2768
2769     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
2770       if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
2771       {
2772           if (!WideCharToMultiByte( CP_ACP, 0, lpBand->lpText, -1,
2773                                     lprbbi->lpText, lprbbi->cch, NULL, NULL ))
2774               lprbbi->lpText[lprbbi->cch-1] = 0;
2775       }
2776       else
2777         *lprbbi->lpText = 0;
2778     }
2779
2780     if (lprbbi->fMask & RBBIM_IMAGE) {
2781       if (lpBand->fMask & RBBIM_IMAGE)
2782         lprbbi->iImage = lpBand->iImage;
2783       else
2784         lprbbi->iImage = -1;
2785     }
2786
2787     if (lprbbi->fMask & RBBIM_CHILD)
2788         lprbbi->hwndChild = lpBand->hwndChild;
2789
2790     if (lprbbi->fMask & RBBIM_CHILDSIZE) {
2791         lprbbi->cxMinChild = lpBand->cxMinChild;
2792         lprbbi->cyMinChild = lpBand->cyMinChild;
2793         if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
2794             lprbbi->cyChild    = lpBand->cyChild;
2795             lprbbi->cyMaxChild = lpBand->cyMaxChild;
2796             lprbbi->cyIntegral = lpBand->cyIntegral;
2797         }
2798     }
2799
2800     if (lprbbi->fMask & RBBIM_SIZE)
2801         lprbbi->cx = lpBand->cx;
2802
2803     if (lprbbi->fMask & RBBIM_BACKGROUND)
2804         lprbbi->hbmBack = lpBand->hbmBack;
2805
2806     if (lprbbi->fMask & RBBIM_ID)
2807         lprbbi->wID = lpBand->wID;
2808
2809     /* check for additional data */
2810     if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
2811         if (lprbbi->fMask & RBBIM_IDEALSIZE)
2812             lprbbi->cxIdeal = lpBand->cxIdeal;
2813
2814         if (lprbbi->fMask & RBBIM_LPARAM)
2815             lprbbi->lParam = lpBand->lParam;
2816
2817         if (lprbbi->fMask & RBBIM_HEADERSIZE)
2818             lprbbi->cxHeader = lpBand->cxHeader;
2819     }
2820
2821     REBAR_DumpBandInfo (lprbbi);
2822
2823     return TRUE;
2824 }
2825
2826
2827 static LRESULT
2828 REBAR_GetBandInfoW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
2829 {
2830     LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
2831     REBAR_BAND *lpBand;
2832
2833     if (lprbbi == NULL)
2834         return FALSE;
2835     if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE)
2836         return FALSE;
2837     if ((UINT)wParam >= infoPtr->uNumBands)
2838         return FALSE;
2839
2840     TRACE("index %u\n", (UINT)wParam);
2841
2842     /* copy band information */
2843     lpBand = &infoPtr->bands[(UINT)wParam];
2844
2845     if (lprbbi->fMask & RBBIM_STYLE)
2846         lprbbi->fStyle = lpBand->fStyle;
2847
2848     if (lprbbi->fMask & RBBIM_COLORS) {
2849         lprbbi->clrFore = lpBand->clrFore;
2850         lprbbi->clrBack = lpBand->clrBack;
2851         if (lprbbi->clrBack == CLR_DEFAULT)
2852             lprbbi->clrBack = infoPtr->clrBtnFace;
2853     }
2854
2855     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
2856       if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
2857         lstrcpynW (lprbbi->lpText, lpBand->lpText, lprbbi->cch);
2858       else
2859         *lprbbi->lpText = 0;
2860     }
2861
2862     if (lprbbi->fMask & RBBIM_IMAGE) {
2863       if (lpBand->fMask & RBBIM_IMAGE)
2864         lprbbi->iImage = lpBand->iImage;
2865       else
2866         lprbbi->iImage = -1;
2867     }
2868
2869     if (lprbbi->fMask & RBBIM_CHILD)
2870         lprbbi->hwndChild = lpBand->hwndChild;
2871
2872     if (lprbbi->fMask & RBBIM_CHILDSIZE) {
2873         lprbbi->cxMinChild = lpBand->cxMinChild;
2874         lprbbi->cyMinChild = lpBand->cyMinChild;
2875         if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
2876             lprbbi->cyChild    = lpBand->cyChild;
2877             lprbbi->cyMaxChild = lpBand->cyMaxChild;
2878             lprbbi->cyIntegral = lpBand->cyIntegral;
2879         }
2880     }
2881
2882     if (lprbbi->fMask & RBBIM_SIZE)
2883         lprbbi->cx = lpBand->cx;
2884
2885     if (lprbbi->fMask & RBBIM_BACKGROUND)
2886         lprbbi->hbmBack = lpBand->hbmBack;
2887
2888     if (lprbbi->fMask & RBBIM_ID)
2889         lprbbi->wID = lpBand->wID;
2890
2891     /* check for additional data */
2892     if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) {
2893         if (lprbbi->fMask & RBBIM_IDEALSIZE)
2894             lprbbi->cxIdeal = lpBand->cxIdeal;
2895
2896         if (lprbbi->fMask & RBBIM_LPARAM)
2897             lprbbi->lParam = lpBand->lParam;
2898
2899         if (lprbbi->fMask & RBBIM_HEADERSIZE)
2900             lprbbi->cxHeader = lpBand->cxHeader;
2901     }
2902
2903     REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
2904
2905     return TRUE;
2906 }
2907
2908
2909 static LRESULT
2910 REBAR_GetBarHeight (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
2911 {
2912     INT nHeight;
2913
2914     nHeight = (infoPtr->dwStyle & CCS_VERT) ? infoPtr->calcSize.cx : infoPtr->calcSize.cy;
2915
2916     TRACE("height = %d\n", nHeight);
2917
2918     return nHeight;
2919 }
2920
2921
2922 static LRESULT
2923 REBAR_GetBarInfo (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
2924 {
2925     LPREBARINFO lpInfo = (LPREBARINFO)lParam;
2926
2927     if (lpInfo == NULL)
2928         return FALSE;
2929
2930     if (lpInfo->cbSize < sizeof (REBARINFO))
2931         return FALSE;
2932
2933     TRACE("getting bar info!\n");
2934
2935     if (infoPtr->himl) {
2936         lpInfo->himl = infoPtr->himl;
2937         lpInfo->fMask |= RBIM_IMAGELIST;
2938     }
2939
2940     return TRUE;
2941 }
2942
2943
2944 inline static LRESULT
2945 REBAR_GetBkColor (REBAR_INFO *infoPtr)
2946 {
2947     COLORREF clr = infoPtr->clrBk;
2948
2949     if (clr == CLR_DEFAULT)
2950       clr = infoPtr->clrBtnFace;
2951
2952     TRACE("background color 0x%06lx!\n", clr);
2953
2954     return clr;
2955 }
2956
2957
2958 /* << REBAR_GetColorScheme >> */
2959 /* << REBAR_GetDropTarget >> */
2960
2961
2962 static LRESULT
2963 REBAR_GetPalette (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
2964 {
2965     FIXME("empty stub!\n");
2966
2967     return 0;
2968 }
2969
2970
2971 static LRESULT
2972 REBAR_GetRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
2973 {
2974     INT iBand = (INT)wParam;
2975     LPRECT lprc = (LPRECT)lParam;
2976     REBAR_BAND *lpBand;
2977
2978     if ((iBand < 0) && ((UINT)iBand >= infoPtr->uNumBands))
2979         return FALSE;
2980     if (!lprc)
2981         return FALSE;
2982
2983     lpBand = &infoPtr->bands[iBand];
2984     CopyRect (lprc, &lpBand->rcBand);
2985
2986     TRACE("band %d, (%ld,%ld)-(%ld,%ld)\n", iBand,
2987           lprc->left, lprc->top, lprc->right, lprc->bottom);
2988
2989     return TRUE;
2990 }
2991
2992
2993 inline static LRESULT
2994 REBAR_GetRowCount (REBAR_INFO *infoPtr)
2995 {
2996     TRACE("%u\n", infoPtr->uNumRows);
2997
2998     return infoPtr->uNumRows;
2999 }
3000
3001
3002 static LRESULT
3003 REBAR_GetRowHeight (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3004 {
3005     INT iRow = (INT)wParam;
3006     int j = 0, ret = 0;
3007     UINT i;
3008     REBAR_BAND *lpBand;
3009
3010     for (i=0; i<infoPtr->uNumBands; i++) {
3011         lpBand = &infoPtr->bands[i];
3012         if (HIDDENBAND(lpBand)) continue;
3013         if (lpBand->iRow != iRow) continue;
3014         if (infoPtr->dwStyle & CCS_VERT)
3015             j = lpBand->rcBand.right - lpBand->rcBand.left;
3016         else
3017             j = lpBand->rcBand.bottom - lpBand->rcBand.top;
3018         if (j > ret) ret = j;
3019     }
3020
3021     TRACE("row %d, height %d\n", iRow, ret);
3022
3023     return ret;
3024 }
3025
3026
3027 inline static LRESULT
3028 REBAR_GetTextColor (REBAR_INFO *infoPtr)
3029 {
3030     TRACE("text color 0x%06lx!\n", infoPtr->clrText);
3031
3032     return infoPtr->clrText;
3033 }
3034
3035
3036 inline static LRESULT
3037 REBAR_GetToolTips (REBAR_INFO *infoPtr)
3038 {
3039     return (LRESULT)infoPtr->hwndToolTip;
3040 }
3041
3042
3043 inline static LRESULT
3044 REBAR_GetUnicodeFormat (REBAR_INFO *infoPtr)
3045 {
3046     TRACE("%s hwnd=%p\n",
3047           infoPtr->bUnicode ? "TRUE" : "FALSE", infoPtr->hwndSelf);
3048
3049     return infoPtr->bUnicode;
3050 }
3051
3052
3053 inline static LRESULT
3054 REBAR_GetVersion (REBAR_INFO *infoPtr)
3055 {
3056     TRACE("version %d\n", infoPtr->iVersion);
3057     return infoPtr->iVersion;
3058 }
3059
3060
3061 static LRESULT
3062 REBAR_HitTest (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3063 {
3064     LPRBHITTESTINFO lprbht = (LPRBHITTESTINFO)lParam;
3065
3066     if (!lprbht)
3067         return -1;
3068
3069     REBAR_InternalHitTest (infoPtr, &lprbht->pt, &lprbht->flags, &lprbht->iBand);
3070
3071     return lprbht->iBand;
3072 }
3073
3074
3075 static LRESULT
3076 REBAR_IdToIndex (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3077 {
3078     UINT i;
3079
3080     if (infoPtr == NULL)
3081         return -1;
3082
3083     if (infoPtr->uNumBands < 1)
3084         return -1;
3085
3086     for (i = 0; i < infoPtr->uNumBands; i++) {
3087         if (infoPtr->bands[i].wID == (UINT)wParam) {
3088             TRACE("id %u is band %u found!\n", (UINT)wParam, i);
3089             return i;
3090         }
3091     }
3092
3093     TRACE("id %u is not found\n", (UINT)wParam);
3094     return -1;
3095 }
3096
3097
3098 static LRESULT
3099 REBAR_InsertBandA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3100 {
3101     LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
3102     UINT uIndex = (UINT)wParam;
3103     REBAR_BAND *lpBand;
3104
3105     if (infoPtr == NULL)
3106         return FALSE;
3107     if (lprbbi == NULL)
3108         return FALSE;
3109     if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
3110         return FALSE;
3111
3112     /* trace the index as signed to see the -1 */
3113     TRACE("insert band at %d!\n", (INT)uIndex);
3114     REBAR_DumpBandInfo (lprbbi);
3115
3116     if (infoPtr->uNumBands == 0) {
3117         infoPtr->bands = (REBAR_BAND *)Alloc (sizeof (REBAR_BAND));
3118         uIndex = 0;
3119     }
3120     else {
3121         REBAR_BAND *oldBands = infoPtr->bands;
3122         infoPtr->bands =
3123             (REBAR_BAND *)Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
3124         if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
3125             uIndex = infoPtr->uNumBands;
3126
3127         /* pre insert copy */
3128         if (uIndex > 0) {
3129             memcpy (&infoPtr->bands[0], &oldBands[0],
3130                     uIndex * sizeof(REBAR_BAND));
3131         }
3132
3133         /* post copy */
3134         if (uIndex < infoPtr->uNumBands) {
3135             memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
3136                     (infoPtr->uNumBands - uIndex) * sizeof(REBAR_BAND));
3137         }
3138
3139         Free (oldBands);
3140     }
3141
3142     infoPtr->uNumBands++;
3143
3144     TRACE("index %u!\n", uIndex);
3145
3146     /* initialize band (infoPtr->bands[uIndex])*/
3147     lpBand = &infoPtr->bands[uIndex];
3148     lpBand->fMask = 0;
3149     lpBand->fStatus = 0;
3150     lpBand->clrFore = infoPtr->clrText;
3151     lpBand->clrBack = infoPtr->clrBk;
3152     lpBand->hwndChild = 0;
3153     lpBand->hwndPrevParent = 0;
3154
3155     REBAR_CommonSetupBand (infoPtr->hwndSelf, lprbbi, lpBand);
3156     lpBand->lpText = NULL;
3157     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
3158         INT len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
3159         if (len > 1) {
3160             lpBand->lpText = (LPWSTR)Alloc (len*sizeof(WCHAR));
3161             MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, lpBand->lpText, len );
3162         }
3163     }
3164
3165     REBAR_ValidateBand (infoPtr, lpBand);
3166     /* On insert of second band, revalidate band 1 to possible add gripper */
3167     if (infoPtr->uNumBands == 2)
3168         REBAR_ValidateBand (infoPtr, &infoPtr->bands[0]);
3169
3170     REBAR_DumpBand (infoPtr);
3171
3172     REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3173     InvalidateRect(infoPtr->hwndSelf, 0, 1);
3174
3175     return TRUE;
3176 }
3177
3178
3179 static LRESULT
3180 REBAR_InsertBandW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3181 {
3182     LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
3183     UINT uIndex = (UINT)wParam;
3184     REBAR_BAND *lpBand;
3185
3186     if (infoPtr == NULL)
3187         return FALSE;
3188     if (lprbbi == NULL)
3189         return FALSE;
3190     if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE)
3191         return FALSE;
3192
3193     /* trace the index as signed to see the -1 */
3194     TRACE("insert band at %d!\n", (INT)uIndex);
3195     REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
3196
3197     if (infoPtr->uNumBands == 0) {
3198         infoPtr->bands = (REBAR_BAND *)Alloc (sizeof (REBAR_BAND));
3199         uIndex = 0;
3200     }
3201     else {
3202         REBAR_BAND *oldBands = infoPtr->bands;
3203         infoPtr->bands =
3204             (REBAR_BAND *)Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
3205         if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
3206             uIndex = infoPtr->uNumBands;
3207
3208         /* pre insert copy */
3209         if (uIndex > 0) {
3210             memcpy (&infoPtr->bands[0], &oldBands[0],
3211                     uIndex * sizeof(REBAR_BAND));
3212         }
3213
3214         /* post copy */
3215         if (uIndex <= infoPtr->uNumBands - 1) {
3216             memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
3217                     (infoPtr->uNumBands - uIndex) * sizeof(REBAR_BAND));
3218         }
3219
3220         Free (oldBands);
3221     }
3222
3223     infoPtr->uNumBands++;
3224
3225     TRACE("index %u!\n", uIndex);
3226
3227     /* initialize band (infoPtr->bands[uIndex])*/
3228     lpBand = &infoPtr->bands[uIndex];
3229     lpBand->fMask = 0;
3230     lpBand->fStatus = 0;
3231     lpBand->clrFore = infoPtr->clrText;
3232     lpBand->clrBack = infoPtr->clrBk;
3233     lpBand->hwndChild = 0;
3234     lpBand->hwndPrevParent = 0;
3235
3236     REBAR_CommonSetupBand (infoPtr->hwndSelf, (LPREBARBANDINFOA)lprbbi, lpBand);
3237     lpBand->lpText = NULL;
3238     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
3239         INT len = lstrlenW (lprbbi->lpText);
3240         if (len > 0) {
3241             lpBand->lpText = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR));
3242             strcpyW (lpBand->lpText, lprbbi->lpText);
3243         }
3244     }
3245
3246     REBAR_ValidateBand (infoPtr, lpBand);
3247     /* On insert of second band, revalidate band 1 to possible add gripper */
3248     if (infoPtr->uNumBands == 2)
3249         REBAR_ValidateBand (infoPtr, &infoPtr->bands[uIndex ? 0 : 1]);
3250
3251     REBAR_DumpBand (infoPtr);
3252
3253     REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3254     InvalidateRect(infoPtr->hwndSelf, 0, 1);
3255
3256     return TRUE;
3257 }
3258
3259
3260 static LRESULT
3261 REBAR_MaximizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3262 {
3263     REBAR_BAND *lpBand;
3264     UINT uBand = (UINT) wParam;
3265
3266     /* Validate */
3267     if ((infoPtr->uNumBands == 0) ||
3268         ((INT)uBand < 0) || (uBand >= infoPtr->uNumBands)) {
3269         /* error !!! */
3270         ERR("Illegal MaximizeBand, requested=%d, current band count=%d\n",
3271               (INT)uBand, infoPtr->uNumBands);
3272         return FALSE;
3273     }
3274
3275     lpBand = &infoPtr->bands[uBand];
3276
3277     if (lParam && (lpBand->fMask & RBBIM_IDEALSIZE)) {
3278         /* handle setting ideal size */
3279         lpBand->ccx = lpBand->cxIdeal;
3280     }
3281     else {
3282         /* handle setting to max */
3283         FIXME("(uBand = %u fIdeal = %s) case not coded\n",
3284               (UINT)wParam, lParam ? "TRUE" : "FALSE");
3285         return FALSE;
3286     }
3287
3288     infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
3289     REBAR_Layout (infoPtr, 0, TRUE, TRUE);
3290     InvalidateRect (infoPtr->hwndSelf, 0, TRUE);
3291
3292     return TRUE;
3293
3294 }
3295
3296
3297 static LRESULT
3298 REBAR_MinimizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3299 {
3300     REBAR_BAND *band, *lpBand;
3301     UINT uBand = (UINT) wParam;
3302     RECT newrect;
3303     INT imindBand, imaxdBand, iprevBand, startBand, endBand;
3304     INT movement, i;
3305
3306     /* A "minimize" band is equivalent to "dragging" the gripper
3307      * of than band to the right till the band is only the size
3308      * of the cxHeader.
3309      */
3310
3311     /* Validate */
3312     if ((infoPtr->uNumBands == 0) ||
3313         ((INT)uBand < 0) || (uBand >= infoPtr->uNumBands)) {
3314         /* error !!! */
3315         ERR("Illegal MinimizeBand, requested=%d, current band count=%d\n",
3316               (INT)uBand, infoPtr->uNumBands);
3317         return FALSE;
3318     }
3319
3320     /* compute amount of movement and validate */
3321     lpBand = &infoPtr->bands[uBand];
3322
3323     if (infoPtr->dwStyle & CCS_VERT)
3324         movement = lpBand->rcBand.bottom - lpBand->rcBand.top -
3325             lpBand->cxHeader;
3326     else
3327         movement = lpBand->rcBand.right - lpBand->rcBand.left -
3328             lpBand->cxHeader;
3329     if (movement < 0) {
3330         ERR("something is wrong, band=(%ld,%ld)-(%ld,%ld), cxheader=%d\n",
3331             lpBand->rcBand.left, lpBand->rcBand.top,
3332             lpBand->rcBand.right, lpBand->rcBand.bottom,
3333             lpBand->cxHeader);
3334         return FALSE;
3335     }
3336
3337     imindBand = -1;
3338     imaxdBand = -1;
3339     iprevBand = -1; /* to suppress warning message */
3340
3341     /* find the first band in row of the one whose is being minimized */
3342     for (i=0; i<infoPtr->uNumBands; i++) {
3343         band = &infoPtr->bands[i];
3344         if (HIDDENBAND(band)) continue;
3345         if (band->iRow == lpBand->iRow) {
3346             imaxdBand = i;
3347             if (imindBand == -1) imindBand = i;
3348         }
3349     }
3350
3351     /* if the selected band is first in row then need to expand */
3352     /* next visible band                                        */
3353     if (imindBand == uBand) {
3354         band = NULL;
3355         movement = -movement;
3356         /* find the first visible band to the right of the selected band */
3357         for (i=uBand+1; i<=imaxdBand; i++) {
3358             band = &infoPtr->bands[i];
3359             if (!HIDDENBAND(band)) {
3360                 iprevBand = i;
3361                 LEADJ(band, movement);
3362                 band->ccx = rcBw(band);
3363                 break;
3364             }
3365         }
3366         /* what case is this */
3367         if (iprevBand == -1) {
3368             ERR("no previous visible band\n");
3369             return FALSE;
3370         }
3371         startBand = uBand;
3372         endBand = iprevBand;
3373         SetRect (&newrect,
3374                  lpBand->rcBand.left,
3375                  lpBand->rcBand.top,
3376                  band->rcBand.right,
3377                  band->rcBand.bottom);
3378     }
3379     /* otherwise expand previous visible band                   */
3380     else {
3381         band = NULL;
3382         /* find the first visible band to the left of the selected band */
3383         for (i=uBand-1; i>=imindBand; i--) {
3384             band = &infoPtr->bands[i];
3385             if (!HIDDENBAND(band)) {
3386                 iprevBand = i;
3387                 READJ(band, movement);
3388                 band->ccx = rcBw(band);
3389                 break;
3390             }
3391         }
3392         /* what case is this */
3393         if (iprevBand == -1) {
3394             ERR("no previous visible band\n");
3395             return FALSE;
3396         }
3397         startBand = iprevBand;
3398         endBand = uBand;
3399         SetRect (&newrect,
3400                  band->rcBand.left,
3401                  band->rcBand.top,
3402                  lpBand->rcBand.right,
3403                  lpBand->rcBand.bottom);
3404     }
3405
3406     REBAR_Shrink (infoPtr, lpBand, movement, uBand);
3407
3408     /* recompute all rectangles */
3409     if (infoPtr->dwStyle & CCS_VERT) {
3410         REBAR_CalcVertBand (infoPtr, startBand, endBand+1,
3411                             FALSE);
3412     }
3413     else {
3414         REBAR_CalcHorzBand (infoPtr, startBand, endBand+1,
3415                             FALSE);
3416     }
3417
3418     TRACE("bands after minimize, see band # %d, %d\n",
3419           startBand, endBand);
3420     REBAR_DumpBand (infoPtr);
3421
3422     REBAR_MoveChildWindows (infoPtr, startBand, endBand+1);
3423
3424     InvalidateRect (infoPtr->hwndSelf, &newrect, TRUE);
3425     UpdateWindow (infoPtr->hwndSelf);
3426     return FALSE;
3427 }
3428
3429
3430 static LRESULT
3431 REBAR_MoveBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3432 {
3433     REBAR_BAND *oldBands = infoPtr->bands;
3434     REBAR_BAND holder;
3435     UINT uFrom = (UINT)wParam;
3436     UINT uTo = (UINT)lParam;
3437
3438     /* Validate */
3439     if ((infoPtr->uNumBands == 0) ||
3440         ((INT)uFrom < 0) || (uFrom >= infoPtr->uNumBands) ||
3441         ((INT)uTo < 0)   || (uTo >= infoPtr->uNumBands)) {
3442         /* error !!! */
3443         ERR("Illegal MoveBand, from=%d, to=%d, current band count=%d\n",
3444               (INT)uFrom, (INT)uTo, infoPtr->uNumBands);
3445         return FALSE;
3446     }
3447
3448     /* save one to be moved */
3449     memcpy (&holder, &oldBands[uFrom], sizeof(REBAR_BAND));
3450
3451     /* close up rest of bands (pseudo delete) */
3452     if (uFrom < infoPtr->uNumBands - 1) {
3453         memcpy (&oldBands[uFrom], &oldBands[uFrom+1],
3454                 (infoPtr->uNumBands - uFrom - 1) * sizeof(REBAR_BAND));
3455     }
3456
3457     /* allocate new space and copy rest of bands into it */
3458     infoPtr->bands =
3459         (REBAR_BAND *)Alloc ((infoPtr->uNumBands)*sizeof(REBAR_BAND));
3460
3461     /* pre insert copy */
3462     if (uTo > 0) {
3463         memcpy (&infoPtr->bands[0], &oldBands[0],
3464                 uTo * sizeof(REBAR_BAND));
3465     }
3466
3467     /* set moved band */
3468     memcpy (&infoPtr->bands[uTo], &holder, sizeof(REBAR_BAND));
3469
3470     /* post copy */
3471     if (uTo < infoPtr->uNumBands - 1) {
3472         memcpy (&infoPtr->bands[uTo+1], &oldBands[uTo],
3473                 (infoPtr->uNumBands - uTo - 1) * sizeof(REBAR_BAND));
3474     }
3475
3476     Free (oldBands);
3477
3478     TRACE("moved band %d to index %d\n", uFrom, uTo);
3479     REBAR_DumpBand (infoPtr);
3480
3481     infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
3482     /* **************************************************** */
3483     /*                                                      */
3484     /* We do not do a REBAR_Layout here because the native  */
3485     /* control does not do that. The actual layout and      */
3486     /* repaint is done by the *next* real action, ex.:      */
3487     /* RB_INSERTBAND, RB_DELETEBAND, RB_SIZETORECT, etc.    */
3488     /*                                                      */
3489     /* **************************************************** */
3490
3491     return TRUE;
3492 }
3493
3494
3495 /* return TRUE if two strings are different */
3496 static BOOL
3497 REBAR_strdifW( LPCWSTR a, LPCWSTR b )
3498 {
3499     return ( (a && !b) || (b && !a) || (a && b && lstrcmpW(a, b) ) );
3500 }
3501
3502 static LRESULT
3503 REBAR_SetBandInfoA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3504 {
3505     LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
3506     REBAR_BAND *lpBand;
3507     BOOL bChanged;
3508
3509     if (lprbbi == NULL)
3510         return FALSE;
3511     if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE)
3512         return FALSE;
3513     if ((UINT)wParam >= infoPtr->uNumBands)
3514         return FALSE;
3515
3516     TRACE("index %u\n", (UINT)wParam);
3517     REBAR_DumpBandInfo (lprbbi);
3518
3519     /* set band information */
3520     lpBand = &infoPtr->bands[(UINT)wParam];
3521
3522     bChanged = REBAR_CommonSetupBand (infoPtr->hwndSelf, lprbbi, lpBand);
3523     if (lprbbi->fMask & RBBIM_TEXT) {
3524         LPWSTR wstr = NULL;
3525
3526         if (lprbbi->lpText)
3527         {
3528             INT len;
3529             len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
3530             if (len > 1)
3531                 wstr = (LPWSTR)Alloc (len*sizeof(WCHAR));
3532             if (wstr)
3533                 MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, wstr, len );
3534         }
3535         if (REBAR_strdifW(lpBand->lpText, wstr)) {
3536             if (lpBand->lpText) {
3537                 Free (lpBand->lpText);
3538                 lpBand->lpText = NULL;
3539             }
3540             if (wstr) {
3541                 lpBand->lpText = wstr;
3542                 wstr = NULL;
3543             }
3544             bChanged = TRUE;
3545         }
3546         if (wstr)
3547             Free (wstr);
3548     }
3549
3550     REBAR_ValidateBand (infoPtr, lpBand);
3551
3552     REBAR_DumpBand (infoPtr);
3553
3554     if (bChanged && (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE))) {
3555           REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3556           InvalidateRect(infoPtr->hwndSelf, 0, 1);
3557     }
3558
3559     return TRUE;
3560 }
3561
3562 static LRESULT
3563 REBAR_SetBandInfoW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3564 {
3565     LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
3566     REBAR_BAND *lpBand;
3567     BOOL bChanged;
3568
3569     if (lprbbi == NULL)
3570         return FALSE;
3571     if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE)
3572         return FALSE;
3573     if ((UINT)wParam >= infoPtr->uNumBands)
3574         return FALSE;
3575
3576     TRACE("index %u\n", (UINT)wParam);
3577     REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
3578
3579     /* set band information */
3580     lpBand = &infoPtr->bands[(UINT)wParam];
3581
3582     bChanged = REBAR_CommonSetupBand (infoPtr->hwndSelf, (LPREBARBANDINFOA)lprbbi, lpBand);
3583     if( (lprbbi->fMask & RBBIM_TEXT) && 
3584         REBAR_strdifW( lpBand->lpText, lprbbi->lpText ) ) {
3585         if (lpBand->lpText) {
3586             Free (lpBand->lpText);
3587             lpBand->lpText = NULL;
3588         }
3589         if (lprbbi->lpText) {
3590             INT len = lstrlenW (lprbbi->lpText);
3591             if (len > 0)
3592             {
3593                 lpBand->lpText = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR));
3594                 strcpyW (lpBand->lpText, lprbbi->lpText);
3595             }
3596         }
3597         bChanged = TRUE;
3598     }
3599
3600     REBAR_ValidateBand (infoPtr, lpBand);
3601
3602     REBAR_DumpBand (infoPtr);
3603
3604     if ( bChanged && (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) ) {
3605       REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3606       InvalidateRect(infoPtr->hwndSelf, 0, 1);
3607     }
3608
3609     return TRUE;
3610 }
3611
3612
3613 static LRESULT
3614 REBAR_SetBarInfo (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3615 {
3616     LPREBARINFO lpInfo = (LPREBARINFO)lParam;
3617     REBAR_BAND *lpBand;
3618     UINT i;
3619
3620     if (lpInfo == NULL)
3621         return FALSE;
3622
3623     if (lpInfo->cbSize < sizeof (REBARINFO))
3624         return FALSE;
3625
3626     TRACE("setting bar info!\n");
3627
3628     if (lpInfo->fMask & RBIM_IMAGELIST) {
3629         infoPtr->himl = lpInfo->himl;
3630         if (infoPtr->himl) {
3631             INT cx, cy;
3632             ImageList_GetIconSize (infoPtr->himl, &cx, &cy);
3633             infoPtr->imageSize.cx = cx;
3634             infoPtr->imageSize.cy = cy;
3635         }
3636         else {
3637             infoPtr->imageSize.cx = 0;
3638             infoPtr->imageSize.cy = 0;
3639         }
3640         TRACE("new image cx=%ld, cy=%ld\n", infoPtr->imageSize.cx,
3641               infoPtr->imageSize.cy);
3642     }
3643
3644     /* revalidate all bands to reset flags for images in headers of bands */
3645     for (i=0; i<infoPtr->uNumBands; i++) {
3646         lpBand = &infoPtr->bands[i];
3647         REBAR_ValidateBand (infoPtr, lpBand);
3648     }
3649
3650     return TRUE;
3651 }
3652
3653
3654 static LRESULT
3655 REBAR_SetBkColor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3656 {
3657     COLORREF clrTemp;
3658
3659     clrTemp = infoPtr->clrBk;
3660     infoPtr->clrBk = (COLORREF)lParam;
3661
3662     TRACE("background color 0x%06lx!\n", infoPtr->clrBk);
3663
3664     return clrTemp;
3665 }
3666
3667
3668 /* << REBAR_SetColorScheme >> */
3669 /* << REBAR_SetPalette >> */
3670
3671
3672 static LRESULT
3673 REBAR_SetParent (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3674 {
3675     HWND hwndTemp = infoPtr->hwndNotify;
3676
3677     infoPtr->hwndNotify = (HWND)wParam;
3678
3679     return (LRESULT)hwndTemp;
3680 }
3681
3682
3683 static LRESULT
3684 REBAR_SetTextColor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3685 {
3686     COLORREF clrTemp;
3687
3688     clrTemp = infoPtr->clrText;
3689     infoPtr->clrText = (COLORREF)lParam;
3690
3691     TRACE("text color 0x%06lx!\n", infoPtr->clrText);
3692
3693     return clrTemp;
3694 }
3695
3696
3697 /* << REBAR_SetTooltips >> */
3698
3699
3700 inline static LRESULT
3701 REBAR_SetUnicodeFormat (REBAR_INFO *infoPtr, WPARAM wParam)
3702 {
3703     BOOL bTemp = infoPtr->bUnicode;
3704
3705     TRACE("to %s hwnd=%p, was %s\n",
3706           ((BOOL)wParam) ? "TRUE" : "FALSE", infoPtr->hwndSelf,
3707           (bTemp) ? "TRUE" : "FALSE");
3708
3709     infoPtr->bUnicode = (BOOL)wParam;
3710
3711    return bTemp;
3712 }
3713
3714
3715 static LRESULT
3716 REBAR_SetVersion (REBAR_INFO *infoPtr, INT iVersion)
3717 {
3718     INT iOldVersion = infoPtr->iVersion;
3719
3720     if (iVersion > COMCTL32_VERSION)
3721         return -1;
3722
3723     infoPtr->iVersion = iVersion;
3724
3725     TRACE("new version %d\n", iVersion);
3726
3727     return iOldVersion;
3728 }
3729
3730
3731 static LRESULT
3732 REBAR_ShowBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3733 {
3734     REBAR_BAND *lpBand;
3735
3736     if (((INT)wParam < 0) || ((INT)wParam > infoPtr->uNumBands))
3737         return FALSE;
3738
3739     lpBand = &infoPtr->bands[(INT)wParam];
3740
3741     if ((BOOL)lParam) {
3742         TRACE("show band %d\n", (INT)wParam);
3743         lpBand->fStyle = lpBand->fStyle & ~RBBS_HIDDEN;
3744         if (IsWindow (lpBand->hwndChild))
3745             ShowWindow (lpBand->hwndChild, SW_SHOW);
3746     }
3747     else {
3748         TRACE("hide band %d\n", (INT)wParam);
3749         lpBand->fStyle = lpBand->fStyle | RBBS_HIDDEN;
3750         if (IsWindow (lpBand->hwndChild))
3751             ShowWindow (lpBand->hwndChild, SW_HIDE);
3752     }
3753
3754     infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
3755     REBAR_Layout (infoPtr, NULL, TRUE, FALSE);
3756     InvalidateRect(infoPtr->hwndSelf, 0, 1);
3757
3758     return TRUE;
3759 }
3760
3761
3762 static LRESULT
3763 REBAR_SizeToRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3764 {
3765     LPRECT lpRect = (LPRECT)lParam;
3766     RECT t1;
3767
3768     if (lpRect == NULL)
3769        return FALSE;
3770
3771     TRACE("[%ld %ld %ld %ld]\n",
3772           lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
3773
3774     /*  what is going on???? */
3775     GetWindowRect(infoPtr->hwndSelf, &t1);
3776     TRACE("window rect [%ld %ld %ld %ld]\n",
3777           t1.left, t1.top, t1.right, t1.bottom);
3778     GetClientRect(infoPtr->hwndSelf, &t1);
3779     TRACE("client rect [%ld %ld %ld %ld]\n",
3780           t1.left, t1.top, t1.right, t1.bottom);
3781
3782     /* force full _Layout processing */
3783     TRACE("setting NEEDS_LAYOUT\n");
3784     infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
3785     REBAR_Layout (infoPtr, lpRect, TRUE, FALSE);
3786     InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
3787     return TRUE;
3788 }
3789
3790
3791
3792 static LRESULT
3793 REBAR_Create (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3794 {
3795     LPCREATESTRUCTA cs = (LPCREATESTRUCTA) lParam;
3796     RECT wnrc1, clrc1;
3797
3798     if (TRACE_ON(rebar)) {
3799         GetWindowRect(infoPtr->hwndSelf, &wnrc1);
3800         GetClientRect(infoPtr->hwndSelf, &clrc1);
3801         TRACE("window=(%ld,%ld)-(%ld,%ld) client=(%ld,%ld)-(%ld,%ld) cs=(%d,%d %dx%d)\n",
3802               wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom,
3803               clrc1.left, clrc1.top, clrc1.right, clrc1.bottom,
3804               cs->x, cs->y, cs->cx, cs->cy);
3805     }
3806
3807     TRACE("created!\n");
3808     return 0;
3809 }
3810
3811
3812 static LRESULT
3813 REBAR_Destroy (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3814 {
3815     REBAR_BAND *lpBand;
3816     UINT i;
3817
3818
3819     /* free rebar bands */
3820     if ((infoPtr->uNumBands > 0) && infoPtr->bands) {
3821         /* clean up each band */
3822         for (i = 0; i < infoPtr->uNumBands; i++) {
3823             lpBand = &infoPtr->bands[i];
3824
3825             /* delete text strings */
3826             if (lpBand->lpText) {
3827                 Free (lpBand->lpText);
3828                 lpBand->lpText = NULL;
3829             }
3830             /* destroy child window */
3831             DestroyWindow (lpBand->hwndChild);
3832         }
3833
3834         /* free band array */
3835         Free (infoPtr->bands);
3836         infoPtr->bands = NULL;
3837     }
3838
3839     DeleteObject (infoPtr->hcurArrow);
3840     DeleteObject (infoPtr->hcurHorz);
3841     DeleteObject (infoPtr->hcurVert);
3842     DeleteObject (infoPtr->hcurDrag);
3843     if(infoPtr->hDefaultFont) DeleteObject (infoPtr->hDefaultFont);
3844     SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0);
3845
3846     /* free rebar info data */
3847     Free (infoPtr);
3848     TRACE("destroyed!\n");
3849     return 0;
3850 }
3851
3852
3853 static LRESULT
3854 REBAR_EraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3855 {
3856     RECT cliprect;
3857
3858     if (GetClipBox ( (HDC)wParam, &cliprect))
3859         return REBAR_InternalEraseBkGnd (infoPtr, wParam, lParam, &cliprect);
3860     return 0;
3861 }
3862
3863
3864 static LRESULT
3865 REBAR_GetFont (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3866 {
3867     return (LRESULT)infoPtr->hFont;
3868 }
3869
3870 static LRESULT
3871 REBAR_PushChevron(REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3872 {
3873     if (wParam >= 0 && (UINT)wParam < infoPtr->uNumBands)
3874     {
3875         NMREBARCHEVRON nmrbc;
3876         REBAR_BAND *lpBand = &infoPtr->bands[wParam];
3877
3878         TRACE("Pressed chevron on band %d\n", wParam);
3879
3880         /* redraw chevron in pushed state */
3881         lpBand->fDraw |= DRAW_CHEVRONPUSHED;
3882         RedrawWindow(infoPtr->hwndSelf, &lpBand->rcChevron,0,
3883           RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3884
3885         /* notify app so it can display a popup menu or whatever */
3886         nmrbc.uBand = wParam;
3887         nmrbc.wID = lpBand->wID;
3888         nmrbc.lParam = lpBand->lParam;
3889         nmrbc.rc = lpBand->rcChevron;
3890         nmrbc.lParamNM = lParam;
3891         REBAR_Notify((NMHDR*)&nmrbc, infoPtr, RBN_CHEVRONPUSHED);
3892
3893         /* redraw chevron in previous state */
3894         lpBand->fDraw &= ~DRAW_CHEVRONPUSHED;
3895         InvalidateRect(infoPtr->hwndSelf, &lpBand->rcChevron, TRUE);
3896
3897         return TRUE;
3898     }
3899     return FALSE;
3900 }
3901
3902 static LRESULT
3903 REBAR_LButtonDown (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3904 {
3905     REBAR_BAND *lpBand;
3906     UINT htFlags;
3907     UINT iHitBand;
3908     POINT ptMouseDown;
3909     ptMouseDown.x = (INT)LOWORD(lParam);
3910     ptMouseDown.y = (INT)HIWORD(lParam);
3911
3912     REBAR_InternalHitTest(infoPtr, &ptMouseDown, &htFlags, &iHitBand);
3913     lpBand = &infoPtr->bands[iHitBand];
3914
3915     if (htFlags == RBHT_CHEVRON)
3916     {
3917         REBAR_PushChevron(infoPtr, iHitBand, 0);
3918     }
3919     else if (htFlags == RBHT_GRABBER || htFlags == RBHT_CAPTION)
3920     {
3921         TRACE("Starting drag\n");
3922
3923         SetCapture (infoPtr->hwndSelf);
3924         infoPtr->iGrabbedBand = iHitBand;
3925
3926         /* save off the LOWORD and HIWORD of lParam as initial x,y */
3927         infoPtr->dragStart = MAKEPOINTS(lParam);
3928         infoPtr->dragNow = infoPtr->dragStart;
3929         if (infoPtr->dwStyle & CCS_VERT)
3930             infoPtr->ihitoffset = infoPtr->dragStart.y - (lpBand->rcBand.top+REBAR_PRE_GRIPPER);
3931         else
3932             infoPtr->ihitoffset = infoPtr->dragStart.x - (lpBand->rcBand.left+REBAR_PRE_GRIPPER);
3933     }
3934     return 0;
3935 }
3936
3937 static LRESULT
3938 REBAR_LButtonUp (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3939 {
3940     if (infoPtr->iGrabbedBand >= 0)
3941     {
3942         NMHDR layout;
3943         RECT rect;
3944
3945         infoPtr->dragStart.x = 0;
3946         infoPtr->dragStart.y = 0;
3947         infoPtr->dragNow = infoPtr->dragStart;
3948
3949         ReleaseCapture ();
3950
3951         if (infoPtr->fStatus & BEGIN_DRAG_ISSUED) {
3952             REBAR_Notify(&layout, infoPtr, RBN_LAYOUTCHANGED);
3953             REBAR_Notify_NMREBAR (infoPtr, infoPtr->iGrabbedBand, RBN_ENDDRAG);
3954             infoPtr->fStatus &= ~BEGIN_DRAG_ISSUED;
3955         }
3956
3957         infoPtr->iGrabbedBand = -1;
3958
3959         GetClientRect(infoPtr->hwndSelf, &rect);
3960         InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
3961     }
3962
3963     return 0;
3964 }
3965
3966 static LRESULT
3967 REBAR_MouseLeave (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3968 {
3969     if (infoPtr->ichevronhotBand >= 0)
3970     {
3971         REBAR_BAND *lpChevronBand = &infoPtr->bands[infoPtr->ichevronhotBand];
3972         if (lpChevronBand->fDraw & DRAW_CHEVRONHOT)
3973         {
3974             lpChevronBand->fDraw &= ~DRAW_CHEVRONHOT;
3975             InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
3976         }
3977     }
3978     infoPtr->iOldBand = -1;
3979     infoPtr->ichevronhotBand = -2;
3980
3981     return TRUE;
3982 }
3983
3984 static LRESULT
3985 REBAR_MouseMove (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
3986 {
3987     REBAR_BAND *lpChevronBand;
3988     POINTS ptsmove;
3989
3990     ptsmove = MAKEPOINTS(lParam);
3991
3992     /* if we are currently dragging a band */
3993     if (infoPtr->iGrabbedBand >= 0)
3994     {
3995         REBAR_BAND *band1, *band2;
3996     
3997         if (GetCapture() != infoPtr->hwndSelf)
3998             ERR("We are dragging but haven't got capture?!?\n");
3999
4000         band1 = &infoPtr->bands[infoPtr->iGrabbedBand-1];
4001         band2 = &infoPtr->bands[infoPtr->iGrabbedBand];
4002
4003         /* if mouse did not move much, exit */
4004         if ((abs(ptsmove.x - infoPtr->dragNow.x) <= mindragx) &&
4005             (abs(ptsmove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
4006
4007         /* Test for valid drag case - must not be first band in row */
4008         if (infoPtr->dwStyle & CCS_VERT) {
4009             if ((ptsmove.x < band2->rcBand.left) ||
4010               (ptsmove.x > band2->rcBand.right) ||
4011               ((infoPtr->iGrabbedBand > 0) && (band1->iRow != band2->iRow))) {
4012                 FIXME("Cannot drag to other rows yet!!\n");
4013             }
4014             else {
4015                 REBAR_HandleLRDrag (infoPtr, &ptsmove);
4016             }
4017         }
4018         else {
4019             if ((ptsmove.y < band2->rcBand.top) ||
4020               (ptsmove.y > band2->rcBand.bottom) ||
4021               ((infoPtr->iGrabbedBand > 0) && (band1->iRow != band2->iRow))) {
4022                 FIXME("Cannot drag to other rows yet!!\n");
4023             }
4024             else {
4025                 REBAR_HandleLRDrag (infoPtr, &ptsmove);
4026             }
4027         }
4028     }
4029     else
4030     {
4031         POINT ptMove;
4032         INT iHitBand;
4033         UINT htFlags;
4034         TRACKMOUSEEVENT trackinfo;
4035
4036         ptMove.x = (INT)ptsmove.x;
4037         ptMove.y = (INT)ptsmove.y;
4038         REBAR_InternalHitTest(infoPtr, &ptMove, &htFlags, &iHitBand);
4039
4040         if (infoPtr->iOldBand >= 0 && infoPtr->iOldBand == infoPtr->ichevronhotBand)
4041         {
4042             lpChevronBand = &infoPtr->bands[infoPtr->ichevronhotBand];
4043             if (lpChevronBand->fDraw & DRAW_CHEVRONHOT)
4044             {
4045                 lpChevronBand->fDraw &= ~DRAW_CHEVRONHOT;
4046                 InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
4047             }
4048             infoPtr->ichevronhotBand = -2;
4049         }
4050
4051         if (htFlags == RBHT_CHEVRON)
4052         {
4053             /* fill in the TRACKMOUSEEVENT struct */
4054             trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
4055             trackinfo.dwFlags = TME_QUERY;
4056             trackinfo.hwndTrack = infoPtr->hwndSelf;
4057             trackinfo.dwHoverTime = 0;
4058
4059             /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
4060             _TrackMouseEvent(&trackinfo);
4061
4062             /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
4063             if(!(trackinfo.dwFlags & TME_LEAVE))
4064             {
4065                 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
4066
4067                 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
4068                 /* and can properly deactivate the hot chevron */
4069                 _TrackMouseEvent(&trackinfo);
4070             }
4071
4072             lpChevronBand = &infoPtr->bands[iHitBand];
4073             if (!(lpChevronBand->fDraw & DRAW_CHEVRONHOT))
4074             {
4075                 lpChevronBand->fDraw |= DRAW_CHEVRONHOT;
4076                 InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE);
4077                 infoPtr->ichevronhotBand = iHitBand;
4078             }
4079         }
4080         infoPtr->iOldBand = iHitBand;
4081     }
4082
4083     return 0;
4084 }
4085
4086
4087 inline static LRESULT
4088 REBAR_NCCalcSize (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4089 {
4090     if (infoPtr->dwStyle & WS_BORDER) {
4091         InflateRect((LPRECT)lParam, -GetSystemMetrics(SM_CXEDGE),
4092                     -GetSystemMetrics(SM_CYEDGE));
4093     }
4094     TRACE("new client=(%ld,%ld)-(%ld,%ld)\n",
4095           ((LPRECT)lParam)->left, ((LPRECT)lParam)->top,
4096           ((LPRECT)lParam)->right, ((LPRECT)lParam)->bottom);
4097     return 0;
4098 }
4099
4100
4101 static LRESULT
4102 REBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4103 {
4104     LPCREATESTRUCTA cs = (LPCREATESTRUCTA) lParam;
4105     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
4106     RECT wnrc1, clrc1;
4107     NONCLIENTMETRICSA ncm;
4108     HFONT tfont;
4109     INT i;
4110
4111     if (infoPtr != NULL) {
4112         ERR("Strange info structure pointer *not* NULL\n");
4113         return FALSE;
4114     }
4115
4116     if (TRACE_ON(rebar)) {
4117         GetWindowRect(hwnd, &wnrc1);
4118         GetClientRect(hwnd, &clrc1);
4119         TRACE("window=(%ld,%ld)-(%ld,%ld) client=(%ld,%ld)-(%ld,%ld) cs=(%d,%d %dx%d)\n",
4120               wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom,
4121               clrc1.left, clrc1.top, clrc1.right, clrc1.bottom,
4122               cs->x, cs->y, cs->cx, cs->cy);
4123     }
4124
4125     /* allocate memory for info structure */
4126     infoPtr = (REBAR_INFO *)Alloc (sizeof(REBAR_INFO));
4127     SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
4128
4129     /* initialize info structure - initial values are 0 */
4130     infoPtr->clrBk = CLR_NONE;
4131     infoPtr->clrText = CLR_NONE;
4132     infoPtr->clrBtnText = GetSysColor (COLOR_BTNTEXT);
4133     infoPtr->clrBtnFace = GetSysColor (COLOR_BTNFACE);
4134     infoPtr->iOldBand = -1;
4135     infoPtr->ichevronhotBand = -2;
4136     infoPtr->iGrabbedBand = -1;
4137     infoPtr->hwndSelf = hwnd;
4138     infoPtr->DoRedraw = TRUE;
4139     infoPtr->hcurArrow = LoadCursorA (0, (LPSTR)IDC_ARROW);
4140     infoPtr->hcurHorz  = LoadCursorA (0, (LPSTR)IDC_SIZEWE);
4141     infoPtr->hcurVert  = LoadCursorA (0, (LPSTR)IDC_SIZENS);
4142     infoPtr->hcurDrag  = LoadCursorA (0, (LPSTR)IDC_SIZE);
4143     infoPtr->bUnicode = IsWindowUnicode (hwnd);
4144     infoPtr->fStatus = CREATE_RUNNING;
4145     infoPtr->hFont = GetStockObject (SYSTEM_FONT);
4146
4147     /* issue WM_NOTIFYFORMAT to get unicode status of parent */
4148     i = SendMessageA(REBAR_GetNotifyParent (infoPtr),
4149                      WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY);
4150     if ((i < NFR_ANSI) || (i > NFR_UNICODE)) {
4151         ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n",
4152             i);
4153         i = NFR_ANSI;
4154     }
4155     infoPtr->NtfUnicode = (i == NFR_UNICODE) ? 1 : 0;
4156
4157     /* add necessary styles to the requested styles */
4158     infoPtr->dwStyle = cs->style | WS_VISIBLE | CCS_TOP;
4159     SetWindowLongA (hwnd, GWL_STYLE, infoPtr->dwStyle);
4160
4161     /* get font handle for Caption Font */
4162     ncm.cbSize = sizeof(NONCLIENTMETRICSA);
4163     SystemParametersInfoA (SPI_GETNONCLIENTMETRICS,
4164                           ncm.cbSize, &ncm, 0);
4165     /* if the font is bold, set to normal */
4166     if (ncm.lfCaptionFont.lfWeight > FW_NORMAL) {
4167         ncm.lfCaptionFont.lfWeight = FW_NORMAL;
4168     }
4169     tfont = CreateFontIndirectA (&ncm.lfCaptionFont);
4170     if (tfont) {
4171         infoPtr->hFont = infoPtr->hDefaultFont = tfont;
4172     }
4173
4174 /* native does:
4175             GetSysColor (numerous);
4176             GetSysColorBrush (numerous) (see WM_SYSCOLORCHANGE);
4177            *GetStockObject (SYSTEM_FONT);
4178            *SetWindowLong (hwnd, 0, info ptr);
4179            *WM_NOTIFYFORMAT;
4180            *SetWindowLong (hwnd, GWL_STYLE, style+0x10000001);
4181                                     WS_VISIBLE = 0x10000000;
4182                                     CCS_TOP    = 0x00000001;
4183            *SystemParametersInfo (SPI_GETNONCLIENTMETRICS...);
4184            *CreateFontIndirect (lfCaptionFont from above);
4185             GetDC ();
4186             SelectObject (hdc, fontabove);
4187             GetTextMetrics (hdc, );    guessing is tmHeight
4188             SelectObject (hdc, oldfont);
4189             ReleaseDC ();
4190             GetWindowRect ();
4191             MapWindowPoints (0, parent, rectabove, 2);
4192             GetWindowRect ();
4193             GetClientRect ();
4194             ClientToScreen (clientrect);
4195             SetWindowPos (hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER);
4196  */
4197     return TRUE;
4198 }
4199
4200
4201 static LRESULT
4202 REBAR_NCHitTest (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4203 {
4204     NMMOUSE nmmouse;
4205     POINTS shortpt;
4206     POINT clpt, pt;
4207     INT i;
4208     UINT scrap;
4209     LRESULT ret = HTCLIENT;
4210
4211     /*
4212      * Differences from doc at MSDN (as observed with version 4.71 of
4213      *      comctl32.dll
4214      * 1. doc says nmmouse.pt is in screen coord, trace shows client coord.
4215      * 2. if band is not identified .dwItemSpec is 0xffffffff.
4216      * 3. native always seems to return HTCLIENT if notify return is 0.
4217      */
4218
4219     shortpt = MAKEPOINTS (lParam);
4220     POINTSTOPOINT(pt, shortpt);
4221     clpt = pt;
4222     ScreenToClient (infoPtr->hwndSelf, &clpt);
4223     REBAR_InternalHitTest (infoPtr, &clpt, &scrap,
4224                            (INT *)&nmmouse.dwItemSpec);
4225     nmmouse.dwItemData = 0;
4226     nmmouse.pt = clpt;
4227     nmmouse.dwHitInfo = 0;
4228     if ((i = REBAR_Notify((NMHDR *) &nmmouse, infoPtr, NM_NCHITTEST))) {
4229         TRACE("notify changed return value from %ld to %d\n",
4230               ret, i);
4231         ret = (LRESULT) i;
4232     }
4233     TRACE("returning %ld, client point (%ld,%ld)\n", ret, clpt.x, clpt.y);
4234     return ret;
4235 }
4236
4237
4238 static LRESULT
4239 REBAR_NCPaint (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4240 {
4241     RECT rcWindow;
4242     HDC hdc;
4243
4244     if (infoPtr->dwStyle & WS_MINIMIZE)
4245         return 0; /* Nothing to do */
4246
4247     if (infoPtr->dwStyle & WS_BORDER) {
4248
4249         /* adjust rectangle and draw the necessary edge */
4250         if (!(hdc = GetDCEx( infoPtr->hwndSelf, 0, DCX_USESTYLE | DCX_WINDOW )))
4251             return 0;
4252         GetWindowRect (infoPtr->hwndSelf, &rcWindow);
4253         OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
4254         TRACE("rect (%ld,%ld)-(%ld,%ld)\n",
4255               rcWindow.left, rcWindow.top,
4256               rcWindow.right, rcWindow.bottom);
4257         DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT);
4258         ReleaseDC( infoPtr->hwndSelf, hdc );
4259     }
4260
4261     return 0;
4262 }
4263
4264
4265 static LRESULT
4266 REBAR_NotifyFormat (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4267 {
4268     INT i;
4269
4270     if (lParam == NF_REQUERY) {
4271         i = SendMessageA(REBAR_GetNotifyParent (infoPtr),
4272                          WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY);
4273         if ((i < NFR_ANSI) || (i > NFR_UNICODE)) {
4274             ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n",
4275                 i);
4276             i = NFR_ANSI;
4277         }
4278         infoPtr->NtfUnicode = (i == NFR_UNICODE) ? 1 : 0;
4279         return (LRESULT)i;
4280     }
4281     return (LRESULT)((infoPtr->bUnicode) ? NFR_UNICODE : NFR_ANSI);
4282 }
4283
4284
4285 static LRESULT
4286 REBAR_Paint (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4287 {
4288     HDC hdc;
4289     PAINTSTRUCT ps;
4290     RECT rc;
4291
4292     GetClientRect(infoPtr->hwndSelf, &rc);
4293     hdc = wParam==0 ? BeginPaint (infoPtr->hwndSelf, &ps) : (HDC)wParam;
4294
4295     TRACE("painting (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n",
4296           ps.rcPaint.left, ps.rcPaint.top,
4297           ps.rcPaint.right, ps.rcPaint.bottom,
4298           rc.left, rc.top, rc.right, rc.bottom);
4299
4300     if (ps.fErase) {
4301         /* Erase area of paint if requested */
4302         REBAR_InternalEraseBkGnd (infoPtr, wParam, lParam, &ps.rcPaint);
4303     }
4304
4305     REBAR_Refresh (infoPtr, hdc);
4306     if (!wParam)
4307         EndPaint (infoPtr->hwndSelf, &ps);
4308     return 0;
4309 }
4310
4311
4312 static LRESULT
4313 REBAR_SetCursor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4314 {
4315     POINT pt;
4316     UINT  flags;
4317
4318     TRACE("code=0x%X  id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
4319
4320     GetCursorPos (&pt);
4321     ScreenToClient (infoPtr->hwndSelf, &pt);
4322
4323     REBAR_InternalHitTest (infoPtr, &pt, &flags, NULL);
4324
4325     if (flags == RBHT_GRABBER) {
4326         if ((infoPtr->dwStyle & CCS_VERT) &&
4327             !(infoPtr->dwStyle & RBS_VERTICALGRIPPER))
4328             SetCursor (infoPtr->hcurVert);
4329         else
4330             SetCursor (infoPtr->hcurHorz);
4331     }
4332     else if (flags != RBHT_CLIENT)
4333         SetCursor (infoPtr->hcurArrow);
4334
4335     return 0;
4336 }
4337
4338
4339 static LRESULT
4340 REBAR_SetFont (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4341 {
4342     RECT rcClient;
4343     REBAR_BAND *lpBand;
4344     UINT i;
4345
4346     infoPtr->hFont = (HFONT)wParam;
4347
4348     /* revalidate all bands to change sizes of text in headers of bands */
4349     for (i=0; i<infoPtr->uNumBands; i++) {
4350         lpBand = &infoPtr->bands[i];
4351         REBAR_ValidateBand (infoPtr, lpBand);
4352     }
4353
4354
4355     if (LOWORD(lParam)) {
4356         GetClientRect (infoPtr->hwndSelf, &rcClient);
4357         REBAR_Layout (infoPtr, &rcClient, FALSE, TRUE);
4358     }
4359
4360     return 0;
4361 }
4362
4363
4364 inline static LRESULT
4365 REBAR_SetRedraw (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4366      /*****************************************************
4367       *
4368       * Function;
4369       *  Handles the WM_SETREDRAW message.
4370       *
4371       * Documentation:
4372       *  According to testing V4.71 of COMCTL32 returns the
4373       *  *previous* status of the redraw flag (either 0 or -1)
4374       *  instead of the MSDN documented value of 0 if handled
4375       *
4376       *****************************************************/
4377 {
4378     BOOL oldredraw = infoPtr->DoRedraw;
4379
4380     TRACE("set to %s, fStatus=%08x\n",
4381           (wParam) ? "TRUE" : "FALSE", infoPtr->fStatus);
4382     infoPtr->DoRedraw = (BOOL) wParam;
4383     if (wParam) {
4384         if (infoPtr->fStatus & BAND_NEEDS_REDRAW) {
4385             REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands);
4386             REBAR_ForceResize (infoPtr);
4387             InvalidateRect (infoPtr->hwndSelf, 0, TRUE);
4388         }
4389         infoPtr->fStatus &= ~BAND_NEEDS_REDRAW;
4390     }
4391     return (oldredraw) ? -1 : 0;
4392 }
4393
4394
4395 static LRESULT
4396 REBAR_Size (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4397 {
4398     RECT rcClient;
4399
4400     /* auto resize deadlock check */
4401     if (infoPtr->fStatus & AUTO_RESIZE) {
4402         infoPtr->fStatus &= ~AUTO_RESIZE;
4403         TRACE("AUTO_RESIZE was set, reset, fStatus=%08x lparam=%08lx\n",
4404               infoPtr->fStatus, lParam);
4405         return 0;
4406     }
4407
4408     if (infoPtr->fStatus & CREATE_RUNNING) {
4409         /* still in CreateWindow */
4410         RECT rcWin;
4411
4412         if ((INT)wParam != SIZE_RESTORED) {
4413             ERR("WM_SIZE in create and flags=%08x, lParam=%08lx\n",
4414                 wParam, lParam);
4415         }
4416
4417         TRACE("still in CreateWindow\n");
4418         infoPtr->fStatus &= ~CREATE_RUNNING;
4419         GetWindowRect ( infoPtr->hwndSelf, &rcWin);
4420         TRACE("win rect (%ld,%ld)-(%ld,%ld)\n",
4421               rcWin.left, rcWin.top, rcWin.right, rcWin.bottom);
4422
4423         if ((lParam == 0) && (rcWin.right-rcWin.left == 0) &&
4424             (rcWin.bottom-rcWin.top == 0)) {
4425             /* native control seems to do this */
4426             GetClientRect (GetParent(infoPtr->hwndSelf), &rcClient);
4427             TRACE("sizing rebar, message and client zero, parent client (%ld,%ld)\n",
4428                   rcClient.right, rcClient.bottom);
4429         }
4430         else {
4431             INT cx, cy;
4432
4433             cx = rcWin.right - rcWin.left;
4434             cy = rcWin.bottom - rcWin.top;
4435             if ((cx == LOWORD(lParam)) && (cy == HIWORD(lParam))) {
4436                 return 0;
4437             }
4438
4439             /* do the actual WM_SIZE request */
4440             GetClientRect (infoPtr->hwndSelf, &rcClient);
4441             TRACE("sizing rebar from (%ld,%ld) to (%d,%d), client (%ld,%ld)\n",
4442                   infoPtr->calcSize.cx, infoPtr->calcSize.cy,
4443                   LOWORD(lParam), HIWORD(lParam),
4444                   rcClient.right, rcClient.bottom);
4445         }
4446     }
4447     else {
4448         if ((INT)wParam != SIZE_RESTORED) {
4449             ERR("WM_SIZE out of create and flags=%08x, lParam=%08lx\n",
4450                 wParam, lParam);
4451         }
4452
4453         /* Handle cases when outside of the CreateWindow process */
4454
4455         GetClientRect (infoPtr->hwndSelf, &rcClient);
4456         if ((lParam == 0) && (rcClient.right + rcClient.bottom != 0) &&
4457             (infoPtr->dwStyle & RBS_AUTOSIZE)) {
4458             /* on a WM_SIZE to zero and current client not zero and AUTOSIZE */
4459             /* native seems to use the current client rect for the size      */
4460             infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
4461             TRACE("sizing rebar to client (%ld,%ld) size is zero but AUTOSIZE set\n",
4462                   rcClient.right, rcClient.bottom);
4463         }
4464         else {
4465             TRACE("sizing rebar from (%ld,%ld) to (%d,%d), client (%ld,%ld)\n",
4466                   infoPtr->calcSize.cx, infoPtr->calcSize.cy,
4467                   LOWORD(lParam), HIWORD(lParam),
4468                   rcClient.right, rcClient.bottom);
4469         }
4470     }
4471
4472     if (infoPtr->dwStyle & RBS_AUTOSIZE) {
4473         NMRBAUTOSIZE autosize;
4474
4475         GetClientRect(infoPtr->hwndSelf, &autosize.rcTarget);
4476         autosize.fChanged = 0;  /* ??? */
4477         autosize.rcActual = autosize.rcTarget;  /* ??? */
4478         REBAR_Notify((NMHDR *) &autosize, infoPtr, RBN_AUTOSIZE);
4479         TRACE("RBN_AUTOSIZE client=(%ld,%ld), lp=%08lx\n",
4480               autosize.rcTarget.right, autosize.rcTarget.bottom, lParam);
4481     }
4482
4483     if ((infoPtr->calcSize.cx != rcClient.right) ||
4484         (infoPtr->calcSize.cy != rcClient.bottom))
4485         infoPtr->fStatus |= BAND_NEEDS_LAYOUT;
4486
4487     REBAR_Layout (infoPtr, &rcClient, TRUE, TRUE);
4488
4489     return 0;
4490 }
4491
4492
4493 static LRESULT
4494 REBAR_StyleChanged (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4495 {
4496     STYLESTRUCT *ss = (STYLESTRUCT *)lParam;
4497
4498     TRACE("current style=%08lx, styleOld=%08lx, style being set to=%08lx\n",
4499           infoPtr->dwStyle, ss->styleOld, ss->styleNew);
4500     infoPtr->dwStyle = ss->styleNew;
4501
4502     return FALSE;
4503 }
4504
4505
4506 static LRESULT
4507 REBAR_WindowPosChanged (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
4508 {
4509     WINDOWPOS *lpwp = (WINDOWPOS *)lParam;
4510     LRESULT ret;
4511     RECT rc;
4512
4513     /* Save the new origin of this window - used by _ForceResize */
4514     infoPtr->origin.x = lpwp->x;
4515     infoPtr->origin.y = lpwp->y;
4516     ret = DefWindowProcA(infoPtr->hwndSelf, WM_WINDOWPOSCHANGED,
4517                          wParam, lParam);
4518     GetWindowRect(infoPtr->hwndSelf, &rc);
4519     TRACE("hwnd %p new pos (%ld,%ld)-(%ld,%ld)\n",
4520           infoPtr->hwndSelf, rc.left, rc.top, rc.right, rc.bottom);
4521     return ret;
4522 }
4523
4524
4525 static LRESULT WINAPI
4526 REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4527 {
4528     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
4529
4530     TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n",
4531           hwnd, uMsg, wParam, lParam);
4532     if (!infoPtr && (uMsg != WM_NCCREATE))
4533             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4534     switch (uMsg)
4535     {
4536 /*      case RB_BEGINDRAG: */
4537
4538         case RB_DELETEBAND:
4539             return REBAR_DeleteBand (infoPtr, wParam, lParam);
4540
4541 /*      case RB_DRAGMOVE: */
4542 /*      case RB_ENDDRAG: */
4543
4544         case RB_GETBANDBORDERS:
4545             return REBAR_GetBandBorders (infoPtr, wParam, lParam);
4546
4547         case RB_GETBANDCOUNT:
4548             return REBAR_GetBandCount (infoPtr);
4549
4550         case RB_GETBANDINFO_OLD:
4551         case RB_GETBANDINFOA:
4552             return REBAR_GetBandInfoA (infoPtr, wParam, lParam);
4553
4554         case RB_GETBANDINFOW:
4555             return REBAR_GetBandInfoW (infoPtr, wParam, lParam);
4556
4557         case RB_GETBARHEIGHT:
4558             return REBAR_GetBarHeight (infoPtr, wParam, lParam);
4559
4560         case RB_GETBARINFO:
4561             return REBAR_GetBarInfo (infoPtr, wParam, lParam);
4562
4563         case RB_GETBKCOLOR:
4564             return REBAR_GetBkColor (infoPtr);
4565
4566 /*      case RB_GETCOLORSCHEME: */
4567 /*      case RB_GETDROPTARGET: */
4568
4569         case RB_GETPALETTE:
4570             return REBAR_GetPalette (infoPtr, wParam, lParam);
4571
4572         case RB_GETRECT:
4573             return REBAR_GetRect (infoPtr, wParam, lParam);
4574
4575         case RB_GETROWCOUNT:
4576             return REBAR_GetRowCount (infoPtr);
4577
4578         case RB_GETROWHEIGHT:
4579             return REBAR_GetRowHeight (infoPtr, wParam, lParam);
4580
4581         case RB_GETTEXTCOLOR:
4582             return REBAR_GetTextColor (infoPtr);
4583
4584         case RB_GETTOOLTIPS:
4585             return REBAR_GetToolTips (infoPtr);
4586
4587         case RB_GETUNICODEFORMAT:
4588             return REBAR_GetUnicodeFormat (infoPtr);
4589
4590         case CCM_GETVERSION:
4591             return REBAR_GetVersion (infoPtr);
4592
4593         case RB_HITTEST:
4594             return REBAR_HitTest (infoPtr, wParam, lParam);
4595
4596         case RB_IDTOINDEX:
4597             return REBAR_IdToIndex (infoPtr, wParam, lParam);
4598
4599         case RB_INSERTBANDA:
4600             return REBAR_InsertBandA (infoPtr, wParam, lParam);
4601
4602         case RB_INSERTBANDW:
4603             return REBAR_InsertBandW (infoPtr, wParam, lParam);
4604
4605         case RB_MAXIMIZEBAND:
4606             return REBAR_MaximizeBand (infoPtr, wParam, lParam);
4607
4608         case RB_MINIMIZEBAND:
4609             return REBAR_MinimizeBand (infoPtr, wParam, lParam);
4610
4611         case RB_MOVEBAND:
4612             return REBAR_MoveBand (infoPtr, wParam, lParam);
4613
4614         case RB_PUSHCHEVRON:
4615             return REBAR_PushChevron (infoPtr, wParam, lParam);
4616
4617         case RB_SETBANDINFOA:
4618             return REBAR_SetBandInfoA (infoPtr, wParam, lParam);
4619
4620         case RB_SETBANDINFOW:
4621             return REBAR_SetBandInfoW (infoPtr, wParam, lParam);
4622
4623         case RB_SETBARINFO:
4624             return REBAR_SetBarInfo (infoPtr, wParam, lParam);
4625
4626         case RB_SETBKCOLOR:
4627             return REBAR_SetBkColor (infoPtr, wParam, lParam);
4628
4629 /*      case RB_SETCOLORSCHEME: */
4630 /*      case RB_SETPALETTE: */
4631 /*          return REBAR_GetPalette (infoPtr, wParam, lParam); */
4632
4633         case RB_SETPARENT:
4634             return REBAR_SetParent (infoPtr, wParam, lParam);
4635
4636         case RB_SETTEXTCOLOR:
4637             return REBAR_SetTextColor (infoPtr, wParam, lParam);
4638
4639 /*      case RB_SETTOOLTIPS: */
4640
4641         case RB_SETUNICODEFORMAT:
4642             return REBAR_SetUnicodeFormat (infoPtr, wParam);
4643
4644         case CCM_SETVERSION:
4645             return REBAR_SetVersion (infoPtr, (INT)wParam);
4646
4647         case RB_SHOWBAND:
4648             return REBAR_ShowBand (infoPtr, wParam, lParam);
4649
4650         case RB_SIZETORECT:
4651             return REBAR_SizeToRect (infoPtr, wParam, lParam);
4652
4653
4654 /*    Messages passed to parent */
4655         case WM_COMMAND:
4656         case WM_DRAWITEM:
4657         case WM_NOTIFY:
4658             if (infoPtr->NtfUnicode)
4659                 return SendMessageW (REBAR_GetNotifyParent (infoPtr),
4660                                      uMsg, wParam, lParam);
4661             else
4662                 return SendMessageA (REBAR_GetNotifyParent (infoPtr),
4663                                      uMsg, wParam, lParam);
4664
4665
4666 /*      case WM_CHARTOITEM:     supported according to ControlSpy */
4667
4668         case WM_CREATE:
4669             return REBAR_Create (infoPtr, wParam, lParam);
4670
4671         case WM_DESTROY:
4672             return REBAR_Destroy (infoPtr, wParam, lParam);
4673
4674         case WM_ERASEBKGND:
4675             return REBAR_EraseBkGnd (infoPtr, wParam, lParam);
4676
4677         case WM_GETFONT:
4678             return REBAR_GetFont (infoPtr, wParam, lParam);
4679
4680 /*      case WM_LBUTTONDBLCLK:  supported according to ControlSpy */
4681
4682         case WM_LBUTTONDOWN:
4683             return REBAR_LButtonDown (infoPtr, wParam, lParam);
4684
4685         case WM_LBUTTONUP:
4686             return REBAR_LButtonUp (infoPtr, wParam, lParam);
4687
4688 /*      case WM_MEASUREITEM:    supported according to ControlSpy */
4689
4690         case WM_MOUSEMOVE:
4691             return REBAR_MouseMove (infoPtr, wParam, lParam);
4692
4693         case WM_MOUSELEAVE:
4694             return REBAR_MouseLeave (infoPtr, wParam, lParam);
4695
4696         case WM_NCCALCSIZE:
4697             return REBAR_NCCalcSize (infoPtr, wParam, lParam);
4698
4699         case WM_NCCREATE:
4700             return REBAR_NCCreate (hwnd, wParam, lParam);
4701
4702         case WM_NCHITTEST:
4703             return REBAR_NCHitTest (infoPtr, wParam, lParam);
4704
4705         case WM_NCPAINT:
4706             return REBAR_NCPaint (infoPtr, wParam, lParam);
4707
4708         case WM_NOTIFYFORMAT:
4709             return REBAR_NotifyFormat (infoPtr, wParam, lParam);
4710
4711         case WM_PAINT:
4712             return REBAR_Paint (infoPtr, wParam, lParam);
4713
4714 /*      case WM_PALETTECHANGED: supported according to ControlSpy */
4715 /*      case WM_PRINTCLIENT:    supported according to ControlSpy */
4716 /*      case WM_QUERYNEWPALETTE:supported according to ControlSpy */
4717 /*      case WM_RBUTTONDOWN:    supported according to ControlSpy */
4718 /*      case WM_RBUTTONUP:      supported according to ControlSpy */
4719
4720         case WM_SETCURSOR:
4721             return REBAR_SetCursor (infoPtr, wParam, lParam);
4722
4723         case WM_SETFONT:
4724             return REBAR_SetFont (infoPtr, wParam, lParam);
4725
4726         case WM_SETREDRAW:
4727             return REBAR_SetRedraw (infoPtr, wParam, lParam);
4728
4729         case WM_SIZE:
4730             return REBAR_Size (infoPtr, wParam, lParam);
4731
4732         case WM_STYLECHANGED:
4733             return REBAR_StyleChanged (infoPtr, wParam, lParam);
4734
4735 /*      case WM_SYSCOLORCHANGE: supported according to ControlSpy */
4736 /*      "Applications that have brushes using the existing system colors
4737          should delete those brushes and recreate them using the new
4738          system colors."  per MSDN                                */
4739
4740 /*      case WM_VKEYTOITEM:     supported according to ControlSpy */
4741 /*      case WM_WININICHANGE: */
4742
4743         case WM_WINDOWPOSCHANGED:
4744             return REBAR_WindowPosChanged (infoPtr, wParam, lParam);
4745
4746         default:
4747             if ((uMsg >= WM_USER) && (uMsg < WM_APP))
4748                 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
4749                      uMsg, wParam, lParam);
4750             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4751     }
4752     return 0;
4753 }
4754
4755
4756 VOID
4757 REBAR_Register (void)
4758 {
4759     WNDCLASSA wndClass;
4760
4761     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4762     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
4763     wndClass.lpfnWndProc   = (WNDPROC)REBAR_WindowProc;
4764     wndClass.cbClsExtra    = 0;
4765     wndClass.cbWndExtra    = sizeof(REBAR_INFO *);
4766     wndClass.hCursor       = 0;
4767     wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
4768 #if GLATESTING
4769     wndClass.hbrBackground = CreateSolidBrush(RGB(0,128,0));
4770 #endif
4771     wndClass.lpszClassName = REBARCLASSNAMEA;
4772
4773     RegisterClassA (&wndClass);
4774
4775     mindragx = GetSystemMetrics (SM_CXDRAG);
4776     mindragy = GetSystemMetrics (SM_CYDRAG);
4777
4778 }
4779
4780
4781 VOID
4782 REBAR_Unregister (void)
4783 {
4784     UnregisterClassA (REBARCLASSNAMEA, NULL);
4785 }