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