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