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