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