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