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