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