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