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