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