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