Removed some unnecessary includes.
[wine] / dlls / comctl32 / rebar.c
1 /*
2  * Rebar control    rev 5b
3  *
4  * Copyright 1998, 1999 Eric Kohl
5  *
6  * NOTES
7  *   An author is needed! Any volunteers?
8  *   I will only improve this control once in a while.
9  *     Eric <ekohl@abo.rhein-zeitung.de>
10  *
11  * TODO:
12  *   - vertical placement
13  *   - ComboBox and ComboBoxEx placement
14  *   - center image 
15  *   - Layout code.
16  *   - Display code.
17  *   - Some messages.
18  *   - All notifications.
19
20  * Changes Guy Albertelli <galberte@neo.lrun.com>
21  *  rev 2,3,4
22  *   - Implement initial version of row grouping, row separators,
23  *     text and background colors. Support additional messages. 
24  *     Support RBBS_BREAK. Implement ERASEBKGND and improve painting.
25  *  rev 5
26  *  1. Support dragging by the Gripper for only left and right drags 
27  *     within a row. (5a)
28  *  2. Implement WM_LBUTTONDOWN, WM_LBUTTONUP, and WM_MOUSEMOVE.
29  *  3. Support RBS_BANDBORDERS. 
30  *  4. Total rewrite of MouseMove code to handle multiple bands in row. (5b)
31  *  5. Fix drawing bugs.
32  *
33  *    Still to do:
34  *  1. default row height should be the max height of all visible bands
35  *  2. Following still not handled: RBBS_FIXEDBMP, RBBS_CHILDEDGE,
36  *            RBBS_VARIABLEHEIGHT, RBBS_USECHEVRON
37  *  3. GETBANDINFO seems to return correct colors in native but not here.
38
39  */
40
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include "winbase.h"
45 #include "wingdi.h"
46 #include "wine/unicode.h"
47 #include "commctrl.h"
48 #include "debugtools.h"
49
50 DEFAULT_DEBUG_CHANNEL(rebar);
51
52 typedef struct
53 {
54     UINT    fStyle;
55     UINT    fMask;
56     COLORREF  clrFore;
57     COLORREF  clrBack;
58     INT     iImage;
59     HWND    hwndChild;
60     UINT    cxMinChild;
61     UINT    cyMinChild;
62     UINT    cx;
63     HBITMAP hbmBack;
64     UINT    wID;
65     UINT    cyChild;
66     UINT    cyMaxChild;
67     UINT    cyIntegral;
68     UINT    cxIdeal;
69     LPARAM    lParam;
70     UINT    cxHeader;
71
72     UINT    lcx;            /* minimum cx for band */
73     UINT    hcx;            /* maximum cx for band */
74     UINT    lcy;            /* minimum cy for band */
75     UINT    hcy;            /* maximum cy for band */
76
77     SIZE    offChild;       /* x,y offset if child is not FIXEDSIZE */
78     UINT    uMinHeight;
79     INT     iRow;           /* row this band assigned to */
80     UINT    fDraw;          /* drawing flags */
81     RECT    rcBand;         /* calculated band rectangle */
82     RECT    rcGripper;      /* calculated gripper rectangle */
83     RECT    rcCapImage;     /* calculated caption image rectangle */
84     RECT    rcCapText;      /* calculated caption text rectangle */
85     RECT    rcChild;        /* calculated child rectangle */
86
87     LPWSTR    lpText;
88     HWND    hwndPrevParent;
89 } REBAR_BAND;
90
91 /* fDraw flags */
92 #define DRAW_GRIPPER    1
93 #define DRAW_IMAGE      2
94 #define DRAW_TEXT       4
95 #define DRAW_CHILD      8
96 #define DRAW_SEP        16
97
98
99 typedef struct
100 {
101     COLORREF   clrBk;       /* background color */
102     COLORREF   clrText;     /* text color */
103     HIMAGELIST himl;        /* handle to imagelist */
104     UINT     uNumBands;   /* number of bands in the rebar */
105     UINT     uNumRows;    /* number of rows of bands */
106     HWND     hwndToolTip; /* handle to the tool tip control */
107     HWND     hwndNotify;  /* notification window (parent) */
108     HFONT    hFont;       /* handle to the rebar's font */
109     SIZE     imageSize;   /* image size (image list) */
110
111     SIZE     calcSize;    /* calculated rebar size */
112     BOOL     bUnicode;    /* Unicode flag */
113     UINT     fStatus;     /* Status flags (see below)  */ 
114     HCURSOR  hcurArrow;   /* handle to the arrow cursor */
115     HCURSOR  hcurHorz;    /* handle to the EW cursor */
116     HCURSOR  hcurVert;    /* handle to the NS cursor */
117     HCURSOR  hcurDrag;    /* handle to the drag cursor */
118     INT      iVersion;    /* version number */
119     POINTS   dragStart;   /* x,y of button down */
120     POINTS   dragNow;     /* x,y of this MouseMove */
121     INT      ihitBand;    /* band number of band whose gripper was grabbed */
122     INT      ihitoffset;  /* offset of hotspot from gripper.left */
123
124     REBAR_BAND *bands;      /* pointer to the array of rebar bands */
125 } REBAR_INFO;
126
127 /* fStatus flags */
128 #define BEGIN_DRAG_ISSUED   1
129 #define AUTO_RESIZE         2
130
131
132 #define GRIPPER_WIDTH   8
133 #define GRIPPER_HEIGHT  16
134 #define SEP_WIDTH       3
135
136 /* This is the increment that is used over the band height */
137 /* Determined by experiment.                               */ 
138 #define REBARSPACE      4
139
140 #define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongA (hwnd, 0))
141
142
143 /* "constant values" retrieved when DLL was initialized    */
144 /* FIXME we do this when the classes are registered.       */
145 static UINT mindragx = 0;
146 static UINT mindragy = 0;
147
148
149 static VOID
150 REBAR_DumpBandInfo( LPREBARBANDINFOA pB)
151 {
152         TRACE("band info: ID=%u, size=%u, style=0x%08x, mask=0x%08x, child=%04x\n",
153           pB->wID, pB->cbSize, pB->fStyle, pB->fMask, pB->hwndChild); 
154         TRACE("band info: cx=%u, xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n",
155           pB->cx, pB->cxMinChild, 
156           pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral);
157         TRACE("band info: xIdeal=%u, xHeader=%u, lParam=0x%08lx, clrF=0x%06lx, clrB=0x%06lx\n",
158           pB->cxIdeal, pB->cxHeader, pB->lParam, pB->clrFore, pB->clrBack);
159 }
160
161 static VOID
162 REBAR_DumpBand (HWND hwnd)
163 {
164     REBAR_INFO *iP = REBAR_GetInfoPtr (hwnd);
165     REBAR_BAND *pB;
166     UINT i;
167
168     if( TRACE_ON(rebar) ) {
169
170       TRACE("hwnd=%04x: color=%08lx/%08lx, bands=%u, rows=%u, cSize=%ld,%ld\n", 
171         hwnd, iP->clrText, iP->clrBk, iP->uNumBands, iP->uNumRows,
172         iP->calcSize.cx, iP->calcSize.cy);
173       TRACE("hwnd=%04x: flags=%08x, dragStart=%d,%d, dragNow=%d,%d, ihitBand=%d\n",
174             hwnd, iP->fStatus, iP->dragStart.x, iP->dragStart.y,
175             iP->dragNow.x, iP->dragNow.y,
176             iP->ihitBand);
177       for (i = 0; i < iP->uNumBands; i++) {
178         pB = &iP->bands[i];
179         TRACE("band # %u: ID=%u, mask=0x%08x, style=0x%08x, child=%04x, row=%u\n",
180           i, pB->wID, pB->fMask, pB->fStyle, pB->hwndChild, pB->iRow);
181         TRACE("band # %u: xMin=%u, yMin=%u, cx=%u, yChild=%u, yMax=%u, yIntgl=%u, uMinH=%u,\n",
182           i, pB->cxMinChild, pB->cyMinChild, pB->cx,
183           pB->cyChild, pB->cyMaxChild, pB->cyIntegral, pB->uMinHeight);
184         TRACE("band # %u: header=%u, lcx=%u, hcx=%u, lcy=%u, hcy=%u, offChild=%ld,%ld\n",
185           i, pB->cxHeader, pB->lcx, pB->hcx, pB->lcy, pB->hcy, pB->offChild.cx, pB->offChild.cy);
186         TRACE("band # %u: fDraw=%08x, Band=(%d,%d)-(%d,%d), Grip=(%d,%d)-(%d,%d)\n",
187           i, pB->fDraw,
188           pB->rcBand.left, pB->rcBand.top, pB->rcBand.right, pB->rcBand.bottom,
189           pB->rcGripper.left, pB->rcGripper.top, pB->rcGripper.right, pB->rcGripper.bottom);
190         TRACE("band # %u: Img=(%d,%d)-(%d,%d), Txt=(%d,%d)-(%d,%d), Child=(%d,%d)-(%d,%d)\n",
191           i,
192           pB->rcCapImage.left, pB->rcCapImage.top, pB->rcCapImage.right, pB->rcCapImage.bottom,
193           pB->rcCapText.left, pB->rcCapText.top, pB->rcCapText.right, pB->rcCapText.bottom,
194           pB->rcChild.left, pB->rcChild.top, pB->rcChild.right, pB->rcChild.bottom);
195       }
196
197     }
198 }
199
200 static void
201 REBAR_Notify (HWND hwnd, NMHDR *nmhdr, UINT code)
202 {
203     HWND parent, owner;
204
205     parent = GetParent (hwnd);
206     owner = GetWindow (hwnd, GW_OWNER);
207     if (owner) parent = owner;
208     nmhdr->idFrom = GetDlgCtrlID (hwnd);
209     nmhdr->hwndFrom = hwnd;
210     nmhdr->code = code;
211
212     SendMessageA (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom,
213                       (LPARAM)nmhdr);
214 }
215
216 static VOID
217 REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand, DWORD dwStyle)
218 {
219
220     /* draw separator */
221     if (lpBand->fDraw & DRAW_SEP) {
222         RECT rcSep;
223         if (dwStyle & CCS_VERT)
224           SetRect (&rcSep, lpBand->rcBand.left-2, lpBand->rcBand.top-SEP_WIDTH,
225                    lpBand->rcBand.right+2, lpBand->rcBand.top-1);
226         else
227           SetRect (&rcSep, lpBand->rcBand.left-SEP_WIDTH, lpBand->rcBand.top-2,
228                    lpBand->rcBand.left-1, lpBand->rcBand.bottom+2);
229         TRACE("drawing band separator (%d,%d)-(%d,%d)\n",
230               rcSep.left, rcSep.top, rcSep.right, rcSep.bottom);
231         DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_LEFT | BF_TOP | BF_MIDDLE);
232     }
233
234     /* draw gripper */
235     if (lpBand->fDraw & DRAW_GRIPPER)
236         DrawEdge (hdc, &lpBand->rcGripper, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
237
238     /* draw caption image */
239     if (lpBand->fDraw & DRAW_IMAGE) {
240         POINT pt;
241
242         /* center image */
243         pt.y = (lpBand->rcCapImage.bottom + lpBand->rcCapImage.top - infoPtr->imageSize.cy)/2;
244         pt.x = (lpBand->rcCapImage.right + lpBand->rcCapImage.left - infoPtr->imageSize.cx)/2;
245
246         ImageList_Draw (infoPtr->himl, lpBand->iImage, hdc,
247                         pt.x, pt.y,
248                         ILD_TRANSPARENT);
249     }
250
251     /* draw caption text */
252     if (lpBand->fDraw & DRAW_TEXT) {
253         HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
254         INT oldBkMode = SetBkMode (hdc, TRANSPARENT);
255         COLORREF oldcolor = CLR_NONE;
256         if (lpBand->clrFore != CLR_NONE)
257             oldcolor = SetTextColor (hdc, lpBand->clrFore);
258         DrawTextW (hdc, lpBand->lpText, -1, &lpBand->rcCapText,
259                      DT_CENTER | DT_VCENTER | DT_SINGLELINE);
260         if (oldBkMode != TRANSPARENT)
261             SetBkMode (hdc, oldBkMode);
262         if (lpBand->clrFore != CLR_NONE)
263             SetTextColor (hdc, oldcolor);
264         SelectObject (hdc, hOldFont);
265     }
266 }
267
268
269 static VOID
270 REBAR_Refresh (HWND hwnd, HDC hdc)
271 {
272     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
273     REBAR_BAND *lpBand;
274     UINT i, oldrow;
275     RECT rcRowSep;
276     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
277
278     oldrow = infoPtr->bands[0].iRow;
279     for (i = 0; i < infoPtr->uNumBands; i++) {
280         lpBand = &infoPtr->bands[i];
281
282         if ((lpBand->fStyle & RBBS_HIDDEN) || 
283             ((dwStyle & CCS_VERT) &&
284              (lpBand->fStyle & RBBS_NOVERT)))
285             continue;
286
287         /* if a new row then draw a separator */
288         if (oldrow != lpBand->iRow) {
289             if (dwStyle & RBS_BANDBORDERS) {
290                 if (dwStyle & CCS_VERT) {
291                     SetRect (&rcRowSep, lpBand->rcBand.left-2, 0,
292                              lpBand->rcBand.left-1, infoPtr->calcSize.cy);
293                 }
294                 else {
295                     SetRect (&rcRowSep, 0, lpBand->rcBand.top-2,
296                              infoPtr->calcSize.cx, lpBand->rcBand.top-1);
297                 }
298                 TRACE ("drawing row sep (%d,%d)-(%d,%d)\n",
299                        rcRowSep.left, rcRowSep.top,
300                        rcRowSep.right, rcRowSep.bottom);
301                 DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_TOP|BF_LEFT);
302                 oldrow = lpBand->iRow;
303             }
304         }
305
306         /* now draw the band */
307         REBAR_DrawBand (hdc, infoPtr, lpBand, dwStyle);
308
309     }
310 }
311
312 static void
313 REBAR_AdjustBands (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend,
314                    INT maxx, INT usedx, INT mcy, DWORD dwStyle)
315      /* Function: This routine distributes the extra space in a row */
316      /*  evenly over the adjustable bands in the row. It also makes */
317      /*  sure that all bands in the row are the same height.        */
318 {
319     REBAR_BAND *lpBand;
320     UINT i, j;
321     INT incr, lastx=0;
322
323     TRACE("start=%u, end=%u, max x=%d, used x=%d, max y=%d\n",
324           rowstart, rowend-1, maxx, usedx, mcy);
325
326     j = 0;
327     for (i = rowstart; i<rowend; i++) {
328       lpBand = &infoPtr->bands[i];
329       if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild &&
330           !(lpBand->fStyle & RBBS_FIXEDSIZE)) 
331          j++;
332     }
333     if (j)
334       incr = (maxx-usedx) / j;
335     else
336       incr = 0;
337
338     TRACE("adjusting %u of %u bands in row, incr=%d\n", 
339           j, rowend-rowstart, incr);
340
341     for (i = rowstart; i<rowend; i++) {
342       lpBand = &infoPtr->bands[i];
343       if (dwStyle & CCS_VERT) {
344         lpBand->rcBand.bottom = lastx + 
345                                 lpBand->rcBand.bottom - lpBand->rcBand.top;
346         if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild &&
347             !(lpBand->fStyle & RBBS_FIXEDSIZE)) {
348            /* if a child window exists and not fixed then widen it */
349            lpBand->rcBand.bottom += incr;
350         }
351         lpBand->rcBand.top = lastx;
352         lastx = lpBand->rcBand.bottom + 1;
353         lpBand->rcBand.right = lpBand->rcBand.left + mcy;
354       }
355       else {
356         lpBand->rcBand.right = lastx + 
357                                lpBand->rcBand.right - lpBand->rcBand.left;
358         if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild &&
359             !(lpBand->fStyle & RBBS_FIXEDSIZE)) {
360            /* if a child window exists and not fixed then widen it */
361            lpBand->rcBand.right += incr;
362         }
363         lpBand->rcBand.left = lastx;
364         lastx = lpBand->rcBand.right + 1;
365         lpBand->rcBand.bottom = lpBand->rcBand.top + mcy;
366       }
367     }
368
369 }
370
371 static void
372 REBAR_CalcHorzBand (HWND hwnd, REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify, DWORD dwStyle)
373      /* Function: this routine initializes all the rectangles in */
374      /*  each band in a row to fit in the adjusted rcBand rect.  */
375      /* *** Supports only Horizontal bars. ***                   */
376 {
377     REBAR_BAND *lpBand;
378     UINT i, xoff, yoff;
379     NMREBARCHILDSIZE  rbcz;
380     HWND parenthwnd;
381     RECT oldChild;
382
383     rbcz.hdr.hwndFrom = hwnd;
384     rbcz.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
385     /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
386     parenthwnd = GetParent (hwnd);
387
388     for(i=rstart; i<rend; i++){
389       lpBand = &infoPtr->bands[i];
390       oldChild = lpBand->rcChild;
391
392       /* set initial gripper rectangle */
393       SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
394              lpBand->rcBand.left, lpBand->rcBand.bottom);
395
396       /* calculate gripper rectangle */
397       if ((!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
398           (!(lpBand->fStyle & RBBS_FIXEDSIZE)) &&
399           ((lpBand->fStyle & RBBS_GRIPPERALWAYS) || 
400            (infoPtr->uNumBands > 1))) {
401         lpBand->fDraw |= DRAW_GRIPPER;
402         lpBand->rcGripper.left   += 1;
403         lpBand->rcGripper.right  = lpBand->rcGripper.left + 3;
404         lpBand->rcGripper.top    += 3;
405         lpBand->rcGripper.bottom -= 3;
406
407         SetRect (&lpBand->rcCapImage, lpBand->rcGripper.left + GRIPPER_WIDTH,
408                  lpBand->rcBand.top, lpBand->rcGripper.left + GRIPPER_WIDTH,
409                  lpBand->rcBand.bottom);
410       }
411       else {
412         SetRect (&lpBand->rcCapImage, lpBand->rcBand.left, lpBand->rcBand.top,
413                  lpBand->rcBand.left, lpBand->rcBand.bottom);
414       }
415
416       /* image is visible */
417       if ((lpBand->fMask & RBBIM_IMAGE) && (infoPtr->himl)) {
418         lpBand->fDraw |= DRAW_IMAGE;
419
420         lpBand->rcCapImage.right  += infoPtr->imageSize.cx;
421         lpBand->rcCapImage.bottom = lpBand->rcCapImage.top + infoPtr->imageSize.cy;
422
423         /* update band height */
424         if (lpBand->uMinHeight < infoPtr->imageSize.cy + 2) {
425             lpBand->uMinHeight = infoPtr->imageSize.cy + 2;
426             lpBand->rcBand.bottom = lpBand->rcBand.top + lpBand->uMinHeight;
427         }
428       }
429
430       /* set initial caption text rectangle */
431       SetRect (&lpBand->rcCapText, lpBand->rcCapImage.right, lpBand->rcBand.top+1,
432                lpBand->rcCapImage.right, lpBand->rcBand.bottom-1);
433
434       /* text is visible */
435       if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText)) {
436         HDC hdc = GetDC (0);
437         HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
438         SIZE size;
439
440         lpBand->fDraw |= DRAW_TEXT;
441         GetTextExtentPoint32W (hdc, lpBand->lpText,
442                                lstrlenW (lpBand->lpText), &size);
443         lpBand->rcCapText.right += (size.cx + 2);
444
445         SelectObject (hdc, hOldFont);
446         ReleaseDC (0, hdc);
447       }
448
449       /* set initial child window rectangle if there is a child */
450       if (lpBand->fMask & RBBIM_CHILD) {
451         xoff = lpBand->offChild.cx;
452         yoff = lpBand->offChild.cy;
453         SetRect (&lpBand->rcChild,
454                  lpBand->rcBand.left+lpBand->cxHeader+xoff, lpBand->rcBand.top+yoff,
455                  lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
456       }
457       else {
458         SetRect (&lpBand->rcChild,
459                  lpBand->rcCapText.right, lpBand->rcBand.top,
460                  lpBand->rcBand.right, lpBand->rcBand.bottom);
461       }
462
463 #if 1
464       /* do notify is child rectangle changed */
465       if (notify && !EqualRect (&oldChild, &lpBand->rcChild)) {
466         TRACE("Child rectangle changed for band %u\n", i);
467         TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
468                 oldChild.left, oldChild.top,
469                 oldChild.right, oldChild.bottom,
470                 lpBand->rcChild.left, lpBand->rcChild.top,
471                 lpBand->rcChild.right, lpBand->rcChild.bottom);
472         rbcz.hdr.code = RBN_CHILDSIZE;
473         rbcz.uBand = i;
474         rbcz.wID = lpBand->wID;
475         rbcz.rcChild = lpBand->rcChild;
476         rbcz.rcBand = lpBand->rcBand;
477         SendMessageA (parenthwnd, WM_NOTIFY, (WPARAM) rbcz.hdr.idFrom, 
478                       (LPARAM)&rbcz);
479         if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) {
480           TRACE("Child rect changed by NOTIFY for band %u\n", i);
481           TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
482                 lpBand->rcChild.left, lpBand->rcChild.top,
483                 lpBand->rcChild.right, lpBand->rcChild.bottom,
484                 rbcz.rcChild.left, rbcz.rcChild.top,
485                 rbcz.rcChild.right, rbcz.rcChild.bottom);
486         }
487       }
488 #endif
489
490     }
491
492 }
493
494
495 static VOID
496 REBAR_CalcVertBand (HWND hwnd, REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify, DWORD dwStyle)
497      /* Function: this routine initializes all the rectangles in */
498      /*  each band in a row to fit in the adjusted rcBand rect.  */
499      /* *** Supports only Vertical bars. ***                     */
500 {
501     REBAR_BAND *lpBand;
502     UINT i, xoff, yoff;
503     NMREBARCHILDSIZE  rbcz;
504     HWND parenthwnd;
505     RECT oldChild;
506
507     rbcz.hdr.hwndFrom = hwnd;
508     rbcz.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
509     /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */
510     parenthwnd = GetParent (hwnd);
511
512     for(i=rstart; i<rend; i++){
513       lpBand = &infoPtr->bands[i];
514       oldChild = lpBand->rcChild;
515
516       /* set initial gripper rectangle */
517       SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top,
518              lpBand->rcBand.right, lpBand->rcBand.top);
519
520       /* calculate gripper rectangle */
521       if ((!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
522           (!(lpBand->fStyle & RBBS_FIXEDSIZE)) &&
523           ((lpBand->fStyle & RBBS_GRIPPERALWAYS) || 
524            (infoPtr->uNumBands > 1))) {
525         lpBand->fDraw |= DRAW_GRIPPER;
526
527         if (dwStyle & RBS_VERTICALGRIPPER) {
528             /*  vertical gripper  */
529             lpBand->rcGripper.left   += 3;
530             lpBand->rcGripper.right  = lpBand->rcGripper.left + 3;
531             lpBand->rcGripper.top    += 3;
532             lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_HEIGHT;
533
534             /* initialize Caption image rectangle  */
535             SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
536                      lpBand->rcGripper.top + GRIPPER_HEIGHT,
537                      lpBand->rcBand.right,
538                      lpBand->rcGripper.top + GRIPPER_HEIGHT);
539         }
540         else {
541             /*  horizontal gripper  */
542             lpBand->rcGripper.left   += 3;
543             lpBand->rcGripper.right  -= 3;
544             lpBand->rcGripper.top    += 3;
545             lpBand->rcGripper.bottom  = lpBand->rcGripper.top + 3;
546
547             /* initialize Caption image rectangle  */
548             SetRect (&lpBand->rcCapImage, lpBand->rcBand.left,
549                      lpBand->rcGripper.top + GRIPPER_WIDTH,
550                      lpBand->rcBand.right,
551                      lpBand->rcGripper.top + GRIPPER_WIDTH);
552         }
553       }
554       else {
555         /* initialize Caption image rectangle  */
556         SetRect (&lpBand->rcCapImage, lpBand->rcBand.left, lpBand->rcBand.top,
557                  lpBand->rcBand.right, lpBand->rcBand.top);
558       }
559
560       /* image is visible */
561       if ((lpBand->fMask & RBBIM_IMAGE) && (infoPtr->himl)) {
562         lpBand->fDraw |= DRAW_IMAGE;
563
564         lpBand->rcCapImage.right  += infoPtr->imageSize.cx;
565         lpBand->rcCapImage.bottom += infoPtr->imageSize.cy;
566
567         /* update band height */
568         if (lpBand->uMinHeight < infoPtr->imageSize.cx + 2) {
569             lpBand->uMinHeight = infoPtr->imageSize.cx + 2;
570             lpBand->rcBand.right = lpBand->rcBand.left + lpBand->uMinHeight;
571         }
572       }
573
574       /* set initial caption text rectangle */
575       lpBand->rcCapText.left   = lpBand->rcBand.left + 1;
576       lpBand->rcCapText.top    = lpBand->rcCapImage.bottom;
577       lpBand->rcCapText.right  = lpBand->rcBand.right - 1;
578       lpBand->rcCapText.bottom = lpBand->rcCapText.top;
579
580       /* text is visible */
581       if (lpBand->lpText) {
582         HDC hdc = GetDC (0);
583         HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
584         SIZE size;
585
586         lpBand->fDraw |= DRAW_TEXT;
587         GetTextExtentPoint32W (hdc, lpBand->lpText,
588                                lstrlenW (lpBand->lpText), &size);
589         lpBand->rcCapText.bottom += (size.cy + 2);
590
591         SelectObject (hdc, hOldFont);
592         ReleaseDC (0, hdc);
593       }
594
595       /* set initial child window rectangle if there is a child */
596       if (lpBand->fMask & RBBIM_CHILD) {
597         yoff = lpBand->offChild.cx;
598         xoff = lpBand->offChild.cy;
599         SetRect (&lpBand->rcChild,
600                  lpBand->rcBand.left+xoff, 
601                  lpBand->rcBand.top+lpBand->cxHeader+yoff,
602                  lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff);
603       }
604       else {
605         SetRect (&lpBand->rcChild,
606                  lpBand->rcBand.left, lpBand->rcCapText.bottom,
607                  lpBand->rcBand.right, lpBand->rcBand.top);
608       }
609
610 #if 1
611       /* do notify is child rectangle changed */
612       if (notify && !EqualRect (&oldChild, &lpBand->rcChild)) {
613         TRACE("Child rectangle changed for band %u\n", i);
614         TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
615               oldChild.left, oldChild.top,
616               oldChild.right, oldChild.bottom,
617               lpBand->rcChild.left, lpBand->rcChild.top,
618               lpBand->rcChild.right, lpBand->rcChild.bottom);
619         rbcz.hdr.code = RBN_CHILDSIZE;
620         rbcz.uBand = i;
621         rbcz.wID = lpBand->wID;
622         rbcz.rcChild = lpBand->rcChild;
623         rbcz.rcBand = lpBand->rcBand;
624         SendMessageA (parenthwnd, WM_NOTIFY, (WPARAM) rbcz.hdr.idFrom, 
625                       (LPARAM)&rbcz);
626         if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) {
627           TRACE("Child rect changed by NOTIFY for band %u\n", i);
628           TRACE("    from (%d,%d)-(%d,%d)  to (%d,%d)-(%d,%d)\n",
629                 lpBand->rcChild.left, lpBand->rcChild.top,
630                 lpBand->rcChild.right, lpBand->rcChild.bottom,
631                 rbcz.rcChild.left, rbcz.rcChild.top,
632                 rbcz.rcChild.right, rbcz.rcChild.bottom);
633         }
634       }
635 #endif
636
637     }
638 }
639
640
641 static VOID
642 REBAR_Layout (HWND hwnd, LPRECT lpRect, BOOL notify, BOOL resetclient)
643      /* Function: This routine is resposible for laying out all */
644      /*  the bands in a rebar. It assigns each band to a row and*/
645      /*  determines when to start a new row.                    */
646 {
647     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
648     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
649     REBAR_BAND *lpBand;
650     RECT rcClient, rcAdj;
651     INT x, y, cx, cxsep, mcy, clientcx, clientcy, adjcx, adjcy, row, rightx, bottomy;
652     UINT i, rowstartband;
653     BOOL dobreak;
654
655     GetClientRect (hwnd, &rcClient);
656     TRACE("Client is (%d,%d)-(%d,%d)\n",
657           rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
658
659     if (lpRect) {
660         rcAdj = *lpRect;
661         TRACE("adjustment rect is (%d,%d)-(%d,%d)\n",
662               rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom);
663     }
664     else {
665       CopyRect (&rcAdj, &rcClient);
666     }
667
668     clientcx = rcClient.right - rcClient.left;
669     clientcy = rcClient.bottom - rcClient.top;
670     adjcx = rcAdj.right - rcAdj.left;
671     adjcy = rcAdj.bottom - rcAdj.top;
672     if (resetclient) {
673       TRACE("window client rect will be set to adj rect\n");
674       clientcx = adjcx;
675       clientcy = adjcy;
676     }
677     x = 0;
678     y = 0;
679     rowstartband = 0;
680     row = 1;
681     cx = 0;
682     mcy = 0;
683
684     for (i = 0; i < infoPtr->uNumBands; i++) {
685         lpBand = &infoPtr->bands[i];
686         lpBand->fDraw = 0;
687         lpBand->iRow = row;
688
689         if ((lpBand->fStyle & RBBS_HIDDEN) || 
690             ((dwStyle & CCS_VERT) && (lpBand->fStyle & RBBS_NOVERT)))
691             continue;
692
693         cxsep = (x==0) ? 0 : SEP_WIDTH;  /* separator from previous band */
694         cx = lpBand->cxHeader +   /* Header: includes gripper, text, image */
695              lpBand->hcx;         /* coumpted size of child */
696         if (dwStyle & CCS_VERT)
697           dobreak = (y + cx + cxsep > adjcy);
698         else
699           dobreak = (x + cx + cxsep > adjcx);
700         /* This is the check for whether we need to start a new row */
701         if ( ( (lpBand->fStyle & RBBS_BREAK) && (i != 0) ) ||
702              ( ((dwStyle & CCS_VERT) ? (y != 0) : (x != 0)) && dobreak)) {
703           INT borders;
704
705           TRACE("Spliting to new row %d on band %u\n", row+1, i);
706           borders = (dwStyle & RBS_BANDBORDERS) ? 2 : 0;
707           if (dwStyle & CCS_VERT) {
708             /* first adjust all bands in previous current row to */
709             /* redistribute extra x pixels                       */
710             REBAR_AdjustBands (infoPtr, rowstartband, i,
711                                clientcy, y, mcy, dwStyle);
712             /* calculate band subrectangles and break to new row */
713             REBAR_CalcVertBand (hwnd, infoPtr, rowstartband, i,
714                                 notify, dwStyle);
715             y = 0;
716             x += (mcy + borders);
717           }
718           else {
719             /* first adjust all bands in previous current row to */
720             /* redistribute extra x pixels                       */
721             REBAR_AdjustBands (infoPtr, rowstartband, i,
722                                clientcx, x, mcy, dwStyle);
723             /* calculate band subrectangles and break to new row */
724             REBAR_CalcHorzBand (hwnd, infoPtr, rowstartband, i,
725                                 notify, dwStyle);
726             x = 0;
727             y += (mcy + borders);
728           }
729
730           /* FIXME: if not RBS_VARHEIGHT then find max */
731           mcy = 0;
732           cxsep = 0;
733           row++;
734           rowstartband = i;
735           lpBand->iRow = row;
736         }
737
738         if (mcy < lpBand->lcy + REBARSPACE) mcy = lpBand->lcy + REBARSPACE;
739
740         /* if boundary rect specified then limit mcy */
741         if (lpRect) {
742           if (dwStyle & CCS_VERT) {
743             if (x+mcy > adjcx) {
744               mcy = adjcx - x;
745               TRACE("row %u limiting mcy=%d, adjcx=%d, x=%d\n",
746                     i, mcy, adjcx, x);
747             }
748           }
749           else {
750             if (y+mcy > adjcy) {
751               mcy = adjcy - y;
752               TRACE("row %u limiting mcy=%d, adjcy=%d, y=%d\n",
753                     i, mcy, adjcy, y);
754             }
755           }
756         }
757
758         if (dwStyle & CCS_VERT) {
759           /* bound the bottom side if we have a bounding rectangle */
760           lpBand->fDraw |= (y==0) ? 0 : DRAW_SEP;
761           rightx = clientcx;
762           bottomy = (lpRect) ? min(clientcy, y+cxsep+cx) : y+cxsep+cx;
763           lpBand->rcBand.left   = x;
764           lpBand->rcBand.right  = y + min(mcy, lpBand->lcy+REBARSPACE);
765           lpBand->rcBand.top    = min(bottomy, y + cxsep);
766           lpBand->rcBand.bottom = bottomy;
767           lpBand->uMinHeight = lpBand->lcy;
768           y = bottomy;
769         }
770         else {
771           /* bound the right side if we have a bounding rectangle */
772           lpBand->fDraw |= (x==0) ? 0 : DRAW_SEP;
773           rightx = (lpRect) ? min(clientcx, x+cxsep+cx) : x+cxsep+cx;
774           bottomy = clientcy;
775           lpBand->rcBand.left   = min(rightx, x + cxsep);
776           lpBand->rcBand.right  = rightx;
777           lpBand->rcBand.top    = y;
778           lpBand->rcBand.bottom = y + min(mcy, lpBand->lcy+REBARSPACE);
779           lpBand->uMinHeight = lpBand->lcy;
780           x = rightx;
781         }
782         TRACE("band %u, row %d, (%d,%d)-(%d,%d)\n",
783               i, row,
784               lpBand->rcBand.left, lpBand->rcBand.top,
785               lpBand->rcBand.right, lpBand->rcBand.bottom);
786
787     }
788     if (infoPtr->uNumBands) {
789       infoPtr->uNumRows = row;
790
791       if (dwStyle & CCS_VERT) {
792         REBAR_AdjustBands (infoPtr, rowstartband, infoPtr->uNumBands,
793                            clientcy, y, mcy, dwStyle);
794         REBAR_CalcVertBand (hwnd, infoPtr, rowstartband, infoPtr->uNumBands,
795                             notify, dwStyle);
796         x += mcy;
797       }
798       else {
799         REBAR_AdjustBands (infoPtr, rowstartband, infoPtr->uNumBands,
800                            clientcx, x, mcy, dwStyle);
801         REBAR_CalcHorzBand (hwnd, infoPtr, rowstartband, infoPtr->uNumBands, 
802                             notify, dwStyle);
803         y += mcy;
804       }
805     }
806
807     /* FIXME: if not RBS_VARHEIGHT then find max mcy and adj rect*/
808
809     if (dwStyle & CCS_VERT) {
810         infoPtr->calcSize.cx = x;
811         infoPtr->calcSize.cy = clientcy;
812     }
813     else {
814         infoPtr->calcSize.cx = clientcx;
815         infoPtr->calcSize.cy = y;
816     }
817     REBAR_DumpBand (hwnd);
818 }
819
820
821 static VOID
822 REBAR_ForceResize (HWND hwnd)
823      /* Function: This changes the size of the REBAR window to that */
824      /*  calculated by REBAR_Layout.                                */
825 {
826     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
827     RECT rc;
828
829     TRACE( " to [%ld x %ld]!\n",
830            infoPtr->calcSize.cx, infoPtr->calcSize.cy);
831
832     infoPtr->fStatus |= AUTO_RESIZE;
833
834     rc.left = 0;
835     rc.top = 0;
836     rc.right  = infoPtr->calcSize.cx;
837     rc.bottom = infoPtr->calcSize.cy;
838
839     if (GetWindowLongA (hwnd, GWL_STYLE) & WS_BORDER) {
840         InflateRect (&rc, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
841     }
842
843     SetWindowPos (hwnd, 0, 0, 0,
844                     rc.right - rc.left, rc.bottom - rc.top,
845                     SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
846 }
847
848
849 static VOID
850 REBAR_MoveChildWindows (HWND hwnd)
851 {
852     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
853     REBAR_BAND *lpBand;
854     CHAR szClassName[40];
855     UINT i;
856
857     for (i = 0; i < infoPtr->uNumBands; i++) {
858         lpBand = &infoPtr->bands[i];
859
860         if (lpBand->fStyle & RBBS_HIDDEN)
861             continue;
862         if (lpBand->hwndChild) {
863             TRACE("hwndChild = %x\n", lpBand->hwndChild);
864
865             GetClassNameA (lpBand->hwndChild, szClassName, 40);
866             if (!lstrcmpA (szClassName, "ComboBox")) {
867                 INT nEditHeight, yPos;
868                 RECT rc;
869
870                 /* special placement code for combo box */
871
872
873                 /* get size of edit line */
874                 GetWindowRect (lpBand->hwndChild, &rc);
875                 nEditHeight = rc.bottom - rc.top;
876                 yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;
877
878                 /* center combo box inside child area */
879                 TRACE("moving child %04x to (%d,%d)-(%d,%d)\n",
880                       lpBand->hwndChild,
881                       lpBand->rcChild.left, yPos,
882                       lpBand->rcChild.right - lpBand->rcChild.left,
883                       nEditHeight);
884                 SetWindowPos (lpBand->hwndChild, HWND_TOP,
885                             lpBand->rcChild.left, /*lpBand->rcChild.top*/ yPos,
886                             lpBand->rcChild.right - lpBand->rcChild.left,
887                             nEditHeight,
888                             SWP_SHOWWINDOW);
889             }
890 #if 0
891             else if (!lstrcmpA (szClassName, WC_COMBOBOXEXA)) {
892                 INT nEditHeight, yPos;
893                 RECT rc;
894                 HWND hwndEdit;
895
896                 /* special placement code for extended combo box */
897
898                 /* get size of edit line */
899                 hwndEdit = SendMessageA (lpBand->hwndChild, CBEM_GETEDITCONTROL, 0, 0);
900                 GetWindowRect (hwndEdit, &rc);
901                 nEditHeight = rc.bottom - rc.top;
902                 yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2;
903
904                 /* center combo box inside child area */
905                 TRACE("moving child %04x to (%d,%d)-(%d,%d)\n",
906                       lpBand->hwndChild,
907                       lpBand->rcChild.left, yPos,
908                       lpBand->rcChild.right - lpBand->rcChild.left,
909                       nEditHeight);
910                 SetWindowPos (lpBand->hwndChild, HWND_TOP,
911                             lpBand->rcChild.left, /*lpBand->rcChild.top*/ yPos,
912                             lpBand->rcChild.right - lpBand->rcChild.left,
913                             nEditHeight,
914                             SWP_SHOWWINDOW);
915
916             }
917 #endif
918             else {
919                 TRACE("moving child %04x to (%d,%d)-(%d,%d)\n",
920                       lpBand->hwndChild,
921                       lpBand->rcChild.left, lpBand->rcChild.top,
922                       lpBand->rcChild.right - lpBand->rcChild.left,
923                       lpBand->rcChild.bottom - lpBand->rcChild.top);
924                 SetWindowPos (lpBand->hwndChild, HWND_TOP,
925                             lpBand->rcChild.left, lpBand->rcChild.top,
926                             lpBand->rcChild.right - lpBand->rcChild.left,
927                             lpBand->rcChild.bottom - lpBand->rcChild.top,
928                             SWP_SHOWWINDOW);
929             }
930         }
931     }
932 }
933
934
935 static VOID
936 REBAR_ValidateBand (HWND hwnd, REBAR_INFO *infoPtr, REBAR_BAND *lpBand)
937      /* Function:  This routine evaluates the band specs supplied */
938      /*  by the user and updates the following 5 fields in        */
939      /*  the internal band structure: cxHeader, lcx, lcy, hcx, hcy*/
940 {
941     UINT header=0;
942     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
943
944     lpBand->lcx = 0;
945     lpBand->lcy = 0;
946     lpBand->hcx = 0;
947     lpBand->hcy = 0;
948
949     /* Header is where the image, text and gripper exist  */
950     /* in the band and preceed the child window.          */
951
952     /* calculate gripper rectangle */
953     if ((!(lpBand->fStyle & RBBS_NOGRIPPER)) &&
954         (!(lpBand->fStyle & RBBS_FIXEDSIZE)) &&
955         ((lpBand->fStyle & RBBS_GRIPPERALWAYS) || 
956          (infoPtr->uNumBands > 1))) {
957        if (dwStyle & CCS_VERT)
958           if (dwStyle & RBS_VERTICALGRIPPER)
959              header += (GRIPPER_HEIGHT + 3);
960           else
961              header += (GRIPPER_WIDTH + 3);
962        else
963           header += (GRIPPER_WIDTH + 1);
964     }
965
966     /* image is visible */
967     if ((lpBand->fMask & RBBIM_IMAGE) && (infoPtr->himl)) {
968         if (dwStyle & CCS_VERT) {
969            header += infoPtr->imageSize.cy;
970            lpBand->lcy = infoPtr->imageSize.cx + 2;
971         }
972         else {
973            header += infoPtr->imageSize.cx;
974            lpBand->lcy = infoPtr->imageSize.cy + 2;
975         }
976     }
977
978     /* text is visible */
979     if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText)) {
980         HDC hdc = GetDC (0);
981         HFONT hOldFont = SelectObject (hdc, infoPtr->hFont);
982         SIZE size;
983
984         GetTextExtentPoint32W (hdc, lpBand->lpText,
985                                lstrlenW (lpBand->lpText), &size);
986         header += ((dwStyle & CCS_VERT) ? (size.cy + 2) : (size.cx + 2));
987
988         SelectObject (hdc, hOldFont);
989         ReleaseDC (0, hdc);
990     }
991
992     /* check if user overrode the header value */
993     if (!(lpBand->fMask & RBBIM_HEADERSIZE))
994         lpBand->cxHeader = header;
995
996
997     /* Now compute minimum size of child window */
998     lpBand->offChild.cx = 0;
999     lpBand->offChild.cy = 0;
1000     if (lpBand->fMask & RBBIM_CHILDSIZE) {
1001         if (!(lpBand->fStyle & RBBS_FIXEDSIZE)) {
1002             lpBand->offChild.cx = 4;
1003             lpBand->offChild.cy = 2;
1004         }
1005         lpBand->lcx = lpBand->cxMinChild;
1006         lpBand->lcy = lpBand->cyMinChild;
1007         lpBand->hcy = lpBand->lcy;
1008         if (lpBand->fStyle & RBBS_VARIABLEHEIGHT) {
1009             if (lpBand->cyChild != 0xffffffff)
1010                 lpBand->lcy = max (lpBand->cyChild, lpBand->lcy);
1011             lpBand->hcy = lpBand->cyMaxChild;
1012         }
1013         TRACE("_CHILDSIZE\n");
1014     }
1015     if (lpBand->fMask & RBBIM_SIZE) {
1016         lpBand->hcx = max (lpBand->cx, lpBand->lcx);
1017         TRACE("_SIZE\n");
1018     }
1019     else
1020         lpBand->hcx = lpBand->lcx;
1021
1022 }
1023
1024 static void
1025 REBAR_CommonSetupBand (HWND hwnd, LPREBARBANDINFOA lprbbi, REBAR_BAND *lpBand)
1026      /* Function:  This routine copies the supplied values from   */
1027      /*  user input (lprbbi) to the internal band structure.      */
1028 {
1029     lpBand->fMask |= lprbbi->fMask;
1030
1031     if (lprbbi->fMask & RBBIM_STYLE)
1032         lpBand->fStyle = lprbbi->fStyle;
1033
1034     if (lprbbi->fMask & RBBIM_COLORS) {
1035         lpBand->clrFore = lprbbi->clrFore;
1036         lpBand->clrBack = lprbbi->clrBack;
1037     }
1038
1039     if (lprbbi->fMask & RBBIM_IMAGE)
1040         lpBand->iImage = lprbbi->iImage;
1041
1042     if (lprbbi->fMask & RBBIM_CHILD) {
1043         if (lprbbi->hwndChild) {
1044             lpBand->hwndChild = lprbbi->hwndChild;
1045             lpBand->hwndPrevParent =
1046                 SetParent (lpBand->hwndChild, hwnd);
1047         }
1048         else {
1049             TRACE("child: 0x%x  prev parent: 0x%x\n",
1050                    lpBand->hwndChild, lpBand->hwndPrevParent);
1051             lpBand->hwndChild = 0;
1052             lpBand->hwndPrevParent = 0;
1053         }
1054     }
1055
1056     if (lprbbi->fMask & RBBIM_CHILDSIZE) {
1057         lpBand->cxMinChild = lprbbi->cxMinChild;
1058         lpBand->cyMinChild = lprbbi->cyMinChild;
1059         lpBand->cyMaxChild = lprbbi->cyMaxChild;
1060         lpBand->cyChild    = lprbbi->cyChild;
1061         lpBand->cyIntegral = lprbbi->cyIntegral;
1062     }
1063
1064     if (lprbbi->fMask & RBBIM_SIZE)
1065         lpBand->cx = lprbbi->cx;
1066
1067     if (lprbbi->fMask & RBBIM_BACKGROUND)
1068         lpBand->hbmBack = lprbbi->hbmBack;
1069
1070     if (lprbbi->fMask & RBBIM_ID)
1071         lpBand->wID = lprbbi->wID;
1072
1073     /* check for additional data */
1074     if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
1075         if (lprbbi->fMask & RBBIM_IDEALSIZE)
1076             lpBand->cxIdeal = lprbbi->cxIdeal;
1077
1078         if (lprbbi->fMask & RBBIM_LPARAM)
1079             lpBand->lParam = lprbbi->lParam;
1080
1081         if (lprbbi->fMask & RBBIM_HEADERSIZE)
1082             lpBand->cxHeader = lprbbi->cxHeader;
1083     }
1084 }
1085
1086 static LRESULT
1087 REBAR_InternalEraseBkGnd (HWND hwnd, WPARAM wParam, LPARAM lParam, RECT *clip)
1088      /* Function:  This erases the background rectangle with the  */
1089      /*  default brush, then with any band that has a different   */
1090      /*  background color.                                        */
1091 {
1092     HBRUSH hbrBackground = GetClassWord(hwnd, GCW_HBRBACKGROUND);
1093     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1094     RECT eraserect;
1095     REBAR_BAND *lpBand;
1096     INT i;
1097
1098     if (hbrBackground)
1099         FillRect( (HDC) wParam, clip, hbrBackground);
1100
1101     for(i=0; i<infoPtr->uNumBands; i++) {
1102         lpBand = &infoPtr->bands[i];
1103         if (lpBand->clrBack != CLR_NONE) {
1104           if (IntersectRect (&eraserect, clip, &lpBand->rcBand)) {
1105             /* draw background */
1106             HBRUSH brh = CreateSolidBrush (lpBand->clrBack);
1107             TRACE("backround color=0x%06lx, rect (%d,%d)-(%d,%d)\n",
1108                   lpBand->clrBack,
1109                   lpBand->rcBand.left,lpBand->rcBand.top,
1110                   lpBand->rcBand.right,lpBand->rcBand.bottom);
1111             FillRect ( (HDC)wParam, &eraserect, brh);
1112             DeleteObject (brh);
1113           }
1114         }
1115     }
1116     return TRUE;
1117 }
1118
1119 static void
1120 REBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pBand)
1121 {
1122     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1123     REBAR_BAND *lpBand;
1124     RECT rect;
1125     INT  iCount;
1126
1127     GetClientRect (hwnd, &rect);
1128
1129     *pFlags = RBHT_NOWHERE;
1130     if (PtInRect (&rect, *lpPt))
1131     {
1132         if (infoPtr->uNumBands == 0) {
1133             *pFlags = RBHT_NOWHERE;
1134             if (pBand)
1135                 *pBand = -1;
1136             TRACE("NOWHERE\n");
1137             return;
1138         }
1139         else {
1140             /* somewhere inside */
1141             infoPtr->ihitBand = -1;
1142             for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) {
1143                 lpBand = &infoPtr->bands[iCount];
1144                 if (PtInRect (&lpBand->rcBand, *lpPt)) {
1145                     if (pBand)
1146                         *pBand = iCount;
1147                     if (PtInRect (&lpBand->rcGripper, *lpPt)) {
1148                         *pFlags = RBHT_GRABBER;
1149                         infoPtr->ihitBand = iCount;
1150                         TRACE("ON GRABBER %d\n", iCount);
1151                         return;
1152                     }
1153                     else if (PtInRect (&lpBand->rcCapImage, *lpPt)) {
1154                         *pFlags = RBHT_CAPTION;
1155                         TRACE("ON CAPTION %d\n", iCount);
1156                         return;
1157                     }
1158                     else if (PtInRect (&lpBand->rcCapText, *lpPt)) {
1159                         *pFlags = RBHT_CAPTION;
1160                         TRACE("ON CAPTION %d\n", iCount);
1161                         return;
1162                     }
1163                     else if (PtInRect (&lpBand->rcChild, *lpPt)) {
1164                         *pFlags = RBHT_CLIENT;
1165                         TRACE("ON CLIENT %d\n", iCount);
1166                         return;
1167                     }
1168                     else {
1169                         *pFlags = RBHT_NOWHERE;
1170                         TRACE("NOWHERE %d\n", iCount);
1171                         return;
1172                     }
1173                 }
1174             }
1175
1176             *pFlags = RBHT_NOWHERE;
1177             if (pBand)
1178                 *pBand = -1;
1179
1180             TRACE("NOWHERE\n");
1181             return;
1182         }
1183     }
1184     else {
1185         *pFlags = RBHT_NOWHERE;
1186         if (pBand)
1187             *pBand = -1;
1188         TRACE("NOWHERE\n");
1189         return;
1190     }
1191
1192     TRACE("flags=0x%X\n", *pFlags);
1193     return;
1194 }
1195
1196 #define READJ(b,i) {b->rcChild.right += (i);b->rcBand.right += (i);}
1197 #define LEADJ(b,i) {b->rcBand.left += (i); \
1198                     b->rcGripper.left += (i); \
1199                     b->rcGripper.right += (i); \
1200                     b->rcCapImage.left += (i); \
1201                     b->rcCapImage.right += (i); \
1202                     b->rcCapText.left += (i); \
1203                     b->rcCapText.right += (i); \
1204                     b->rcChild.left += (i);}
1205
1206
1207 static INT
1208 REBAR_Shrink (REBAR_BAND *band, INT movement, INT i)
1209      /* Function:  This attempts to shrink the given band by the  */
1210      /*  the amount in "movement". A shrink to the left is indi-  */
1211      /*  cated by "movement" being negative. "i" is merely the    */
1212      /*  band index for trace messages.                           */
1213 {
1214     INT Leadjust, Readjust, avail, ret;
1215
1216     /* Note: a left drag is indicated by "movement" being negative.  */
1217     /*       Similarly, a right drag is indicated by "movement"      */
1218     /*       being positive. "movement" should never be 0, but if    */
1219     /*       it is then the band does not move.                      */
1220
1221     avail = band->rcBand.right - band->rcBand.left -
1222             band->cxHeader - band->offChild.cx;
1223
1224     /* now compute the Left End adjustment factor and Right End */
1225     /* adjustment factor. They may be different if shrinking.   */
1226     if (avail <= 0) {
1227         /* if this band is not shrinkable, then just move it */
1228         Leadjust = Readjust = movement;
1229         ret = movement;
1230     }
1231     else {
1232         if (movement < 0) {
1233             /* Drag to left */
1234             if (avail <= abs(movement)) {
1235                 Readjust = movement;
1236                 Leadjust = movement + avail;
1237                 ret = Leadjust;
1238             }
1239             else {
1240                 Readjust = movement;
1241                 Leadjust = 0;
1242                 ret = 0;
1243             }
1244         }
1245         else {
1246             /* Drag to right */
1247             if (avail <= abs(movement)) {
1248                 Leadjust = movement;
1249                 Readjust = movement - avail;
1250                 ret = Readjust;
1251             }
1252             else {
1253                 Leadjust = movement;
1254                 Readjust = 0;
1255                 ret = 0;
1256             }
1257         }
1258     }
1259
1260     /* Reasonability Check */
1261     if (band->rcBand.left+Leadjust < 0) {
1262         ERR("adjustment will fail, band %d: left=%d, right=%d, move=%d, rtn=%d\n",
1263             i, Leadjust, Readjust, movement, ret);
1264     }
1265
1266     LEADJ(band, Leadjust);
1267     READJ(band, Readjust);
1268
1269     TRACE("band %d:  left=%d, right=%d, move=%d, rtn=%d, rcBand=(%d,%d)-(%d,%d)\n",
1270           i, Leadjust, Readjust, movement, ret,
1271           band->rcBand.left, band->rcBand.top,
1272           band->rcBand.right, band->rcBand.bottom);
1273     return ret;
1274 }
1275
1276
1277 static void
1278 REBAR_HandleLRDrag (HWND hwnd, REBAR_INFO *infoPtr, POINTS *ptsmove)
1279      /* Function:  This will implement the functionality of a     */
1280      /*  Gripper drag within a row. It will not implement "out-   */
1281      /*  of-row" drags. (They are detected and handled in         */
1282      /*  REBAR_MouseMove.)                                        */
1283      /*  **** FIXME Vertical rebars not implemented.        ****  */
1284      /*  **** FIXME Switching order of bands in a row not   ****  */
1285      /*  ****       yet implemented.                        ****  */
1286 {
1287     REBAR_BAND *hitBand, *band, *prevband, *mindBand, *maxdBand;
1288     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1289     HDWP deferpos;
1290     NMREBARCHILDSIZE cs;
1291     NMREBAR startdrag;
1292     RECT newrect;
1293     INT imindBand = -1, imaxdBand, ihitBand, i, movement, tempx;
1294     INT RHeaderSum = 0, LHeaderSum = 0;
1295     INT compress;
1296
1297     /* *** FIXME drag does not work for vertical           *** */
1298     if (dwStyle & CCS_VERT) {
1299         FIXME("Drag not yet implemented for vertical rebars\n");
1300         return;
1301     }
1302
1303     /* on first significant mouse movement, issue notify */
1304
1305     if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) {
1306         startdrag.dwMask = 0;
1307         startdrag.uBand = -1;
1308         REBAR_Notify(hwnd, (NMHDR *) &startdrag, RBN_BEGINDRAG);
1309         infoPtr->fStatus |= BEGIN_DRAG_ISSUED;
1310     }
1311
1312     ihitBand = infoPtr->ihitBand;
1313     hitBand = &infoPtr->bands[ihitBand];
1314     imaxdBand = ihitBand; /* to suppress warning message */
1315
1316     /* find all the bands in the row of the one whose Gripper was seized */
1317     for (i=0; i<infoPtr->uNumBands; i++) {
1318         band = &infoPtr->bands[i];
1319         if (band->iRow == hitBand->iRow) {
1320             imaxdBand = i;
1321             if (imindBand == -1) imindBand = i;
1322             /* minimum size of each band is size of header plus            */
1323             /* size of minimum child plus offset of child from header plus */
1324             /* a one to separate each band.                                */
1325             if (i < ihitBand)
1326                 LHeaderSum += (band->cxHeader + band->offChild.cx +
1327                                band->lcx + 1);
1328             else 
1329                 RHeaderSum += (band->cxHeader + band->offChild.cx +
1330                                band->lcx + 1);
1331
1332         }
1333     }
1334     if (RHeaderSum) RHeaderSum--; /* no separator afterlast band */
1335
1336     mindBand = &infoPtr->bands[imindBand];
1337     maxdBand = &infoPtr->bands[imaxdBand];
1338
1339     if (imindBand == imaxdBand) return; /* nothing to drag agains */
1340     if (imindBand == ihitBand) return; /* first band in row, cant drag */
1341
1342     /* limit movement to inside adjustable bands - Left */
1343     if (ptsmove->x < mindBand->rcBand.left)
1344         return; /* should swap bands */
1345     /* limit movement to inside adjustable bands - Right */
1346     if (ptsmove->x > maxdBand->rcBand.right)
1347         return; /* should swap bands */
1348
1349     movement = ptsmove->x - (hitBand->rcGripper.left - infoPtr->ihitoffset);
1350     infoPtr->dragNow = *ptsmove;
1351
1352     TRACE("before: movement=%d (%d,%d), imindBand=%d, ihitBand=%d, imaxdBand=%d, LSum=%d, RSum=%d\n",
1353           movement, ptsmove->x, ptsmove->y, imindBand, ihitBand,
1354           imaxdBand, LHeaderSum, RHeaderSum);
1355     REBAR_DumpBand (hwnd);
1356
1357     if (movement < 0) {  
1358
1359         /* ***  Drag left *** */
1360         compress = hitBand->rcBand.left-1 - mindBand->rcBand.left -
1361                    LHeaderSum;
1362         if (compress < abs(movement)) {
1363             TRACE("limiting left drag, was %d changed to %d\n",
1364                   movement, -compress);
1365             movement = -compress;
1366         }
1367         for (i=ihitBand; i>=imindBand; i--) {
1368             band = &infoPtr->bands[i];
1369             if (i == ihitBand) {
1370                 prevband = &infoPtr->bands[i-1];
1371                 if (band->rcBand.left - movement <= prevband->rcBand.right) {
1372                     tempx = movement - (prevband->rcBand.right-band->rcBand.left+1);
1373                     ERR("movement bad. BUG!! was %d, left=%d, right=%d, setting to %d\n",
1374                         movement, band->rcBand.left, prevband->rcBand.right, tempx);
1375                     movement = tempx;
1376                 }
1377                 LEADJ(band, movement)
1378             }
1379             else 
1380                 movement = REBAR_Shrink (band, movement, i);
1381         }
1382     }
1383     else {
1384
1385         /* ***  Drag right *** */
1386         compress = maxdBand->rcBand.right - hitBand->rcBand.left -
1387                    RHeaderSum;
1388         if (compress < abs(movement)) {
1389             TRACE("limiting right drag, was %d changed to %d\n",
1390                   movement, compress);
1391             movement = compress;
1392         }
1393         for (i=ihitBand-1; i<=imaxdBand; i++) {
1394             band = &infoPtr->bands[i];
1395             if (i == ihitBand-1) {
1396                 READJ(band, movement)
1397             }
1398             else 
1399                 movement = REBAR_Shrink (band, movement, i);
1400         }
1401     }
1402
1403     TRACE("bands after adjustment, see band # %d, %d\n",
1404           imindBand, imaxdBand);
1405     REBAR_DumpBand (hwnd);
1406
1407     SetRect (&newrect, 
1408              mindBand->rcBand.left,
1409              min(mindBand->rcBand.top, maxdBand->rcBand.top),
1410              maxdBand->rcBand.right,
1411              max(mindBand->rcBand.bottom, maxdBand->rcBand.bottom));
1412
1413     if (!(deferpos = BeginDeferWindowPos (4))) {
1414         ERR("BeginDeferWindowPos returned NULL\n");
1415     }
1416
1417     for (i=imindBand; i<=imaxdBand; i++) {
1418         band = &infoPtr->bands[i];
1419         if ((band->fMask & RBBIM_CHILD) && band->hwndChild) {
1420             cs.uBand = i;
1421             cs.wID = band->wID;
1422             cs.rcChild = band->rcChild;
1423             cs.rcBand = band->rcBand;
1424             REBAR_Notify (hwnd, (NMHDR *) &cs, RBN_CHILDSIZE);
1425             deferpos = DeferWindowPos (deferpos, band->hwndChild, HWND_TOP,
1426                                        cs.rcChild.left, cs.rcChild.top,
1427                                        cs.rcChild.right - cs.rcChild.left,
1428                                        cs.rcChild.bottom - cs.rcChild.top,
1429                                        SWP_NOZORDER);
1430             if (!deferpos) {
1431                 ERR("DeferWindowPos returned NULL\n");
1432             }
1433         }
1434     }
1435
1436     if (!EndDeferWindowPos (deferpos)) {
1437         ERR("EndDeferWindowPos failed\n");
1438     }
1439
1440     InvalidateRect (hwnd, &newrect, TRUE);
1441     UpdateWindow (hwnd);
1442
1443 }
1444 #undef READJ
1445 #undef LEADJ
1446
1447
1448
1449 /* << REBAR_BeginDrag >> */
1450
1451
1452 static LRESULT
1453 REBAR_DeleteBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
1454 {
1455     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1456     UINT uBand = (UINT)wParam;
1457
1458     if (uBand >= infoPtr->uNumBands)
1459         return FALSE;
1460
1461     TRACE("deleting band %u!\n", uBand);
1462
1463     if (infoPtr->uNumBands == 1) {
1464         TRACE(" simple delete!\n");
1465         COMCTL32_Free (infoPtr->bands);
1466         infoPtr->bands = NULL;
1467         infoPtr->uNumBands = 0;
1468     }
1469     else {
1470         REBAR_BAND *oldBands = infoPtr->bands;
1471         TRACE("complex delete! [uBand=%u]\n", uBand);
1472
1473         infoPtr->uNumBands--;
1474         infoPtr->bands = COMCTL32_Alloc (sizeof (REBAR_BAND) * infoPtr->uNumBands);
1475         if (uBand > 0) {
1476             memcpy (&infoPtr->bands[0], &oldBands[0],
1477                     uBand * sizeof(REBAR_BAND));
1478         }
1479
1480         if (uBand < infoPtr->uNumBands) {
1481             memcpy (&infoPtr->bands[uBand], &oldBands[uBand+1],
1482                     (infoPtr->uNumBands - uBand) * sizeof(REBAR_BAND));
1483         }
1484
1485         COMCTL32_Free (oldBands);
1486     }
1487
1488     REBAR_Layout (hwnd, NULL, FALSE, FALSE);
1489     REBAR_ForceResize (hwnd);
1490     REBAR_MoveChildWindows (hwnd);
1491
1492     return TRUE;
1493 }
1494
1495
1496 /* << REBAR_DragMove >> */
1497 /* << REBAR_EndDrag >> */
1498
1499
1500 static LRESULT
1501 REBAR_GetBandBorders (HWND hwnd, WPARAM wParam, LPARAM lParam)
1502 {
1503     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1504     /* LPRECT32 lpRect = (LPRECT32)lParam; */
1505     REBAR_BAND *lpBand;
1506
1507     if (!lParam)
1508         return 0;
1509     if ((UINT)wParam >= infoPtr->uNumBands)
1510         return 0;
1511
1512     lpBand = &infoPtr->bands[(UINT)wParam];
1513     if (GetWindowLongA (hwnd, GWL_STYLE) & RBS_BANDBORDERS) {
1514       /*lpRect.left   = ??? */
1515       /*lpRect.top    = ??? */
1516       /*lpRect.right  = ??? */
1517       /*lpRect.bottom = ??? */
1518     }
1519     else {
1520       /*lpRect.left   = ??? */
1521     }
1522     FIXME("stub\n");
1523     return 0;
1524 }
1525
1526
1527 inline static LRESULT
1528 REBAR_GetBandCount (HWND hwnd)
1529 {
1530     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1531
1532     TRACE("band count %u!\n", infoPtr->uNumBands);
1533
1534     return infoPtr->uNumBands;
1535 }
1536
1537
1538 static LRESULT
1539 REBAR_GetBandInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1540 {
1541     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1542     LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
1543     REBAR_BAND *lpBand;
1544
1545     if (lprbbi == NULL)
1546         return FALSE;
1547     if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
1548         return FALSE;
1549     if ((UINT)wParam >= infoPtr->uNumBands)
1550         return FALSE;
1551
1552     TRACE("index %u\n", (UINT)wParam);
1553
1554     /* copy band information */
1555     lpBand = &infoPtr->bands[(UINT)wParam];
1556
1557     if (lprbbi->fMask & RBBIM_STYLE)
1558         lprbbi->fStyle = lpBand->fStyle;
1559
1560     if (lprbbi->fMask & RBBIM_COLORS) {
1561         lprbbi->clrFore = lpBand->clrFore;
1562         lprbbi->clrBack = lpBand->clrBack;
1563         if (lprbbi->clrBack == CLR_NONE)
1564             lprbbi->clrBack = GetSysColor (COLOR_BTNFACE);
1565     }
1566
1567     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
1568       if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
1569       {
1570           if (!WideCharToMultiByte( CP_ACP, 0, lpBand->lpText, -1,
1571                                     lprbbi->lpText, lprbbi->cch, NULL, NULL ))
1572               lprbbi->lpText[lprbbi->cch-1] = 0;
1573       }
1574       else 
1575         *lprbbi->lpText = 0;
1576     }
1577
1578     if (lprbbi->fMask & RBBIM_IMAGE) {
1579       if (lpBand->fMask & RBBIM_IMAGE)
1580         lprbbi->iImage = lpBand->iImage;
1581       else
1582         lprbbi->iImage = -1;
1583     }
1584
1585     if (lprbbi->fMask & RBBIM_CHILD)
1586         lprbbi->hwndChild = lpBand->hwndChild;
1587
1588     if (lprbbi->fMask & RBBIM_CHILDSIZE) {
1589         lprbbi->cxMinChild = lpBand->cxMinChild;
1590         lprbbi->cyMinChild = lpBand->cyMinChild;
1591         lprbbi->cyMaxChild = lpBand->cyMaxChild;
1592         lprbbi->cyChild    = lpBand->cyChild;
1593         lprbbi->cyIntegral = lpBand->cyIntegral;
1594     }
1595
1596     if (lprbbi->fMask & RBBIM_SIZE)
1597         lprbbi->cx = lpBand->cx;
1598
1599     if (lprbbi->fMask & RBBIM_BACKGROUND)
1600         lprbbi->hbmBack = lpBand->hbmBack;
1601
1602     if (lprbbi->fMask & RBBIM_ID)
1603         lprbbi->wID = lpBand->wID;
1604
1605     /* check for additional data */
1606     if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
1607         if (lprbbi->fMask & RBBIM_IDEALSIZE)
1608             lprbbi->cxIdeal = lpBand->cxIdeal;
1609
1610         if (lprbbi->fMask & RBBIM_LPARAM)
1611             lprbbi->lParam = lpBand->lParam;
1612
1613         if (lprbbi->fMask & RBBIM_HEADERSIZE)
1614             lprbbi->cxHeader = lpBand->cxHeader;
1615     }
1616
1617     REBAR_DumpBandInfo (lprbbi);
1618
1619     return TRUE;
1620 }
1621
1622
1623 static LRESULT
1624 REBAR_GetBandInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1625 {
1626     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1627     LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
1628     REBAR_BAND *lpBand;
1629
1630     if (lprbbi == NULL)
1631         return FALSE;
1632     if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
1633         return FALSE;
1634     if ((UINT)wParam >= infoPtr->uNumBands)
1635         return FALSE;
1636
1637     TRACE("index %u\n", (UINT)wParam);
1638
1639     /* copy band information */
1640     lpBand = &infoPtr->bands[(UINT)wParam];
1641
1642     if (lprbbi->fMask & RBBIM_STYLE)
1643         lprbbi->fStyle = lpBand->fStyle;
1644
1645     if (lprbbi->fMask & RBBIM_COLORS) {
1646         lprbbi->clrFore = lpBand->clrFore;
1647         lprbbi->clrBack = lpBand->clrBack;
1648         if (lprbbi->clrBack == CLR_NONE)
1649             lprbbi->clrBack = GetSysColor (COLOR_BTNFACE);
1650     }
1651
1652     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
1653       if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT))
1654         lstrcpynW (lprbbi->lpText, lpBand->lpText, lprbbi->cch);
1655       else 
1656         *lprbbi->lpText = 0;
1657     }
1658
1659     if (lprbbi->fMask & RBBIM_IMAGE) {
1660       if (lpBand->fMask & RBBIM_IMAGE)
1661         lprbbi->iImage = lpBand->iImage;
1662       else
1663         lprbbi->iImage = -1;
1664     }
1665
1666     if (lprbbi->fMask & RBBIM_CHILD)
1667         lprbbi->hwndChild = lpBand->hwndChild;
1668
1669     if (lprbbi->fMask & RBBIM_CHILDSIZE) {
1670         lprbbi->cxMinChild = lpBand->cxMinChild;
1671         lprbbi->cyMinChild = lpBand->cyMinChild;
1672         lprbbi->cyMaxChild = lpBand->cyMaxChild;
1673         lprbbi->cyChild    = lpBand->cyChild;
1674         lprbbi->cyIntegral = lpBand->cyIntegral;
1675     }
1676
1677     if (lprbbi->fMask & RBBIM_SIZE)
1678         lprbbi->cx = lpBand->cx;
1679
1680     if (lprbbi->fMask & RBBIM_BACKGROUND)
1681         lprbbi->hbmBack = lpBand->hbmBack;
1682
1683     if (lprbbi->fMask & RBBIM_ID)
1684         lprbbi->wID = lpBand->wID;
1685
1686     /* check for additional data */
1687     if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) {
1688         if (lprbbi->fMask & RBBIM_IDEALSIZE)
1689             lprbbi->cxIdeal = lpBand->cxIdeal;
1690
1691         if (lprbbi->fMask & RBBIM_LPARAM)
1692             lprbbi->lParam = lpBand->lParam;
1693
1694         if (lprbbi->fMask & RBBIM_HEADERSIZE)
1695             lprbbi->cxHeader = lpBand->cxHeader;
1696     }
1697
1698     REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
1699
1700     return TRUE;
1701 }
1702
1703
1704 static LRESULT
1705 REBAR_GetBarHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
1706 {
1707     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1708     INT nHeight;
1709
1710     nHeight = infoPtr->calcSize.cy;
1711
1712     TRACE("height = %d\n", nHeight);
1713
1714     return nHeight;
1715 }
1716
1717
1718 static LRESULT
1719 REBAR_GetBarInfo (HWND hwnd, WPARAM wParam, LPARAM lParam)
1720 {
1721     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1722     LPREBARINFO lpInfo = (LPREBARINFO)lParam;
1723
1724     if (lpInfo == NULL)
1725         return FALSE;
1726
1727     if (lpInfo->cbSize < sizeof (REBARINFO))
1728         return FALSE;
1729
1730     TRACE("getting bar info!\n");
1731
1732     if (infoPtr->himl) {
1733         lpInfo->himl = infoPtr->himl;
1734         lpInfo->fMask |= RBIM_IMAGELIST;
1735     }
1736
1737     return TRUE;
1738 }
1739
1740
1741 inline static LRESULT
1742 REBAR_GetBkColor (HWND hwnd)
1743 {
1744     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1745     COLORREF clr = infoPtr->clrBk;
1746
1747     if (clr == CLR_NONE)
1748       clr = GetSysColor (COLOR_BTNFACE);
1749
1750     TRACE("background color 0x%06lx!\n", clr);
1751
1752     return clr;
1753 }
1754
1755
1756 /* << REBAR_GetColorScheme >> */
1757 /* << REBAR_GetDropTarget >> */
1758
1759
1760 static LRESULT
1761 REBAR_GetPalette (HWND hwnd, WPARAM wParam, LPARAM lParam)
1762 {
1763     FIXME("empty stub!\n");
1764
1765     return 0;
1766 }
1767
1768
1769 static LRESULT
1770 REBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1771 {
1772     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1773     INT iBand = (INT)wParam;
1774     LPRECT lprc = (LPRECT)lParam;
1775     REBAR_BAND *lpBand;
1776
1777     if ((iBand < 0) && ((UINT)iBand >= infoPtr->uNumBands))
1778         return FALSE;
1779     if (!lprc)
1780         return FALSE;
1781
1782     lpBand = &infoPtr->bands[iBand];
1783     CopyRect (lprc, &lpBand->rcBand);
1784
1785     TRACE("band %d, (%d,%d)-(%d,%d)\n", iBand,
1786           lprc->left, lprc->top, lprc->right, lprc->bottom);
1787
1788     return TRUE;
1789 }
1790
1791
1792 inline static LRESULT
1793 REBAR_GetRowCount (HWND hwnd)
1794 {
1795     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1796
1797     TRACE("%u\n", infoPtr->uNumRows);
1798
1799     return infoPtr->uNumRows;
1800 }
1801
1802
1803 static LRESULT
1804 REBAR_GetRowHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
1805 {
1806     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1807     INT iRow = (INT)wParam;
1808     int ret = 0;
1809     int i, j = 0;
1810     REBAR_BAND *lpBand;
1811     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1812
1813     for (i=0; i<infoPtr->uNumBands; i++) {
1814       lpBand = &infoPtr->bands[i];
1815       if (lpBand->iRow != iRow) continue;
1816       if (dwStyle & CCS_VERT)
1817         j = lpBand->rcBand.right - lpBand->rcBand.left;
1818       else
1819         j = lpBand->rcBand.bottom - lpBand->rcBand.top;
1820       if (j > ret) ret = j;
1821     }
1822
1823     TRACE("row %d, height %d\n", iRow, ret);
1824
1825     return ret;
1826 }
1827
1828
1829 inline static LRESULT
1830 REBAR_GetTextColor (HWND hwnd)
1831 {
1832     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1833
1834     TRACE("text color 0x%06lx!\n", infoPtr->clrText);
1835
1836     return infoPtr->clrText;
1837 }
1838
1839
1840 inline static LRESULT
1841 REBAR_GetToolTips (HWND hwnd)
1842 {
1843     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1844     return infoPtr->hwndToolTip;
1845 }
1846
1847
1848 inline static LRESULT
1849 REBAR_GetUnicodeFormat (HWND hwnd)
1850 {
1851     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1852     return infoPtr->bUnicode;
1853 }
1854
1855
1856 inline static LRESULT
1857 REBAR_GetVersion (HWND hwnd)
1858 {
1859     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1860     TRACE("version %d\n", infoPtr->iVersion);
1861     return infoPtr->iVersion;
1862 }
1863
1864
1865 static LRESULT
1866 REBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1867 {
1868     /* REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
1869     LPRBHITTESTINFO lprbht = (LPRBHITTESTINFO)lParam; 
1870
1871     if (!lprbht)
1872         return -1;
1873
1874     REBAR_InternalHitTest (hwnd, &lprbht->pt, &lprbht->flags, &lprbht->iBand);
1875
1876     return lprbht->iBand;
1877 }
1878
1879
1880 static LRESULT
1881 REBAR_IdToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1882 {
1883     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1884     UINT i;
1885
1886     if (infoPtr == NULL)
1887         return -1;
1888
1889     if (infoPtr->uNumBands < 1)
1890         return -1;
1891
1892     for (i = 0; i < infoPtr->uNumBands; i++) {
1893         if (infoPtr->bands[i].wID == (UINT)wParam) {
1894             TRACE("id %u is band %u found!\n", (UINT)wParam, i);
1895             return i;
1896         }
1897     }
1898
1899     TRACE("id %u is not found\n", (UINT)wParam);
1900     return -1;
1901 }
1902
1903
1904 static LRESULT
1905 REBAR_InsertBandA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1906 {
1907     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1908     LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
1909     UINT uIndex = (UINT)wParam;
1910     REBAR_BAND *lpBand;
1911
1912     if (infoPtr == NULL)
1913         return FALSE;
1914     if (lprbbi == NULL)
1915         return FALSE;
1916     if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
1917         return FALSE;
1918
1919     /* trace the index as signed to see the -1 */
1920     TRACE("insert band at %d!\n", (INT)uIndex);
1921     REBAR_DumpBandInfo (lprbbi);
1922
1923     if (infoPtr->uNumBands == 0) {
1924         infoPtr->bands = (REBAR_BAND *)COMCTL32_Alloc (sizeof (REBAR_BAND));
1925         uIndex = 0;
1926     }
1927     else {
1928         REBAR_BAND *oldBands = infoPtr->bands;
1929         infoPtr->bands =
1930             (REBAR_BAND *)COMCTL32_Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
1931         if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
1932             uIndex = infoPtr->uNumBands;
1933
1934         /* pre insert copy */
1935         if (uIndex > 0) {
1936             memcpy (&infoPtr->bands[0], &oldBands[0],
1937                     uIndex * sizeof(REBAR_BAND));
1938         }
1939
1940         /* post copy */
1941         if (uIndex < infoPtr->uNumBands - 1) {
1942             memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
1943                     (infoPtr->uNumBands - uIndex - 1) * sizeof(REBAR_BAND));
1944         }
1945
1946         COMCTL32_Free (oldBands);
1947     }
1948
1949     infoPtr->uNumBands++;
1950
1951     TRACE("index %u!\n", uIndex);
1952
1953     /* initialize band (infoPtr->bands[uIndex])*/
1954     lpBand = &infoPtr->bands[uIndex];
1955     lpBand->fMask = 0;
1956     lpBand->clrFore = infoPtr->clrText;
1957     lpBand->clrBack = infoPtr->clrBk;
1958     lpBand->hwndChild = 0;
1959     lpBand->hwndPrevParent = 0;
1960
1961     REBAR_CommonSetupBand (hwnd, lprbbi, lpBand);
1962     lpBand->lpText = NULL;
1963     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
1964         INT len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
1965         if (len > 1) {
1966             lpBand->lpText = (LPWSTR)COMCTL32_Alloc (len*sizeof(WCHAR));
1967             MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, lpBand->lpText, len );
1968         }
1969     }
1970
1971     REBAR_ValidateBand (hwnd, infoPtr, lpBand);
1972
1973     REBAR_DumpBand (hwnd);
1974
1975     REBAR_Layout (hwnd, NULL, FALSE, FALSE);
1976     REBAR_ForceResize (hwnd);
1977     REBAR_MoveChildWindows (hwnd);
1978
1979     return TRUE;
1980 }
1981
1982
1983 static LRESULT
1984 REBAR_InsertBandW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1985 {
1986     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
1987     LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
1988     UINT uIndex = (UINT)wParam;
1989     REBAR_BAND *lpBand;
1990
1991     if (infoPtr == NULL)
1992         return FALSE;
1993     if (lprbbi == NULL)
1994         return FALSE;
1995     if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
1996         return FALSE;
1997
1998     /* trace the index as signed to see the -1 */
1999     TRACE("insert band at %d!\n", (INT)uIndex);
2000     REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
2001
2002     if (infoPtr->uNumBands == 0) {
2003         infoPtr->bands = (REBAR_BAND *)COMCTL32_Alloc (sizeof (REBAR_BAND));
2004         uIndex = 0;
2005     }
2006     else {
2007         REBAR_BAND *oldBands = infoPtr->bands;
2008         infoPtr->bands =
2009             (REBAR_BAND *)COMCTL32_Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
2010         if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands))
2011             uIndex = infoPtr->uNumBands;
2012
2013         /* pre insert copy */
2014         if (uIndex > 0) {
2015             memcpy (&infoPtr->bands[0], &oldBands[0],
2016                     uIndex * sizeof(REBAR_BAND));
2017         }
2018
2019         /* post copy */
2020         if (uIndex < infoPtr->uNumBands - 1) {
2021             memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex],
2022                     (infoPtr->uNumBands - uIndex - 1) * sizeof(REBAR_BAND));
2023         }
2024
2025         COMCTL32_Free (oldBands);
2026     }
2027
2028     infoPtr->uNumBands++;
2029
2030     TRACE("index %u!\n", uIndex);
2031
2032     /* initialize band (infoPtr->bands[uIndex])*/
2033     lpBand = &infoPtr->bands[uIndex];
2034     lpBand->fMask = 0;
2035     lpBand->clrFore = infoPtr->clrText;
2036     lpBand->clrBack = infoPtr->clrBk;
2037     lpBand->hwndChild = 0;
2038     lpBand->hwndPrevParent = 0;
2039
2040     REBAR_CommonSetupBand (hwnd, (LPREBARBANDINFOA)lprbbi, lpBand);
2041     lpBand->lpText = NULL;
2042     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
2043         INT len = lstrlenW (lprbbi->lpText);
2044         if (len > 0) {
2045             lpBand->lpText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
2046             strcpyW (lpBand->lpText, lprbbi->lpText);
2047         }
2048     }
2049
2050     REBAR_ValidateBand (hwnd, infoPtr, lpBand);
2051
2052     REBAR_DumpBand (hwnd);
2053
2054     REBAR_Layout (hwnd, NULL, FALSE, FALSE);
2055     REBAR_ForceResize (hwnd);
2056     REBAR_MoveChildWindows (hwnd);
2057
2058     return TRUE;
2059 }
2060
2061
2062 static LRESULT
2063 REBAR_MaximizeBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
2064 {
2065 /*    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
2066
2067     FIXME("(uBand = %u fIdeal = %s)\n",
2068            (UINT)wParam, lParam ? "TRUE" : "FALSE");
2069
2070  
2071     return 0;
2072 }
2073
2074
2075 static LRESULT
2076 REBAR_MinimizeBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
2077 {
2078 /*    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
2079
2080     FIXME("(uBand = %u)\n", (UINT)wParam);
2081
2082  
2083     return 0;
2084 }
2085
2086
2087 static LRESULT
2088 REBAR_MoveBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
2089 {
2090 /*    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); */
2091
2092     FIXME("(iFrom = %u iTof = %u)\n",
2093            (UINT)wParam, (UINT)lParam);
2094
2095  
2096     return FALSE;
2097 }
2098
2099
2100 static LRESULT
2101 REBAR_SetBandInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2102 {
2103     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2104     LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam;
2105     REBAR_BAND *lpBand;
2106
2107     if (lprbbi == NULL)
2108         return FALSE;
2109     if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEA)
2110         return FALSE;
2111     if ((UINT)wParam >= infoPtr->uNumBands)
2112         return FALSE;
2113
2114     TRACE("index %u\n", (UINT)wParam);
2115     REBAR_DumpBandInfo (lprbbi);
2116
2117     /* set band information */
2118     lpBand = &infoPtr->bands[(UINT)wParam];
2119
2120     REBAR_CommonSetupBand (hwnd, lprbbi, lpBand);
2121     if (lprbbi->fMask & RBBIM_TEXT) {
2122         if (lpBand->lpText) {
2123             COMCTL32_Free (lpBand->lpText);
2124             lpBand->lpText = NULL;
2125         }
2126         if (lprbbi->lpText) {
2127             INT len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 );
2128             lpBand->lpText = (LPWSTR)COMCTL32_Alloc (len*sizeof(WCHAR));
2129             MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, lpBand->lpText, len );
2130         }
2131     }
2132
2133     REBAR_ValidateBand (hwnd, infoPtr, lpBand);
2134
2135     REBAR_DumpBand (hwnd);
2136
2137     if (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) {
2138       REBAR_Layout (hwnd, NULL, TRUE, FALSE);
2139       REBAR_ForceResize (hwnd);
2140       REBAR_MoveChildWindows (hwnd);
2141     }
2142
2143     return TRUE;
2144 }
2145
2146
2147 static LRESULT
2148 REBAR_SetBandInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2149 {
2150     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2151     LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam;
2152     REBAR_BAND *lpBand;
2153
2154     if (lprbbi == NULL)
2155         return FALSE;
2156     if (lprbbi->cbSize < REBARBANDINFO_V3_SIZEW)
2157         return FALSE;
2158     if ((UINT)wParam >= infoPtr->uNumBands)
2159         return FALSE;
2160
2161     TRACE("index %u\n", (UINT)wParam);
2162     REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi);
2163
2164     /* set band information */
2165     lpBand = &infoPtr->bands[(UINT)wParam];
2166
2167     REBAR_CommonSetupBand (hwnd, (LPREBARBANDINFOA)lprbbi, lpBand);
2168     if (lprbbi->fMask & RBBIM_TEXT) {
2169         if (lpBand->lpText) {
2170             COMCTL32_Free (lpBand->lpText);
2171             lpBand->lpText = NULL;
2172         }
2173         if (lprbbi->lpText) {
2174             INT len = lstrlenW (lprbbi->lpText);
2175             lpBand->lpText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
2176             strcpyW (lpBand->lpText, lprbbi->lpText);
2177         }
2178     }
2179
2180     REBAR_ValidateBand (hwnd, infoPtr, lpBand);
2181
2182     REBAR_DumpBand (hwnd);
2183
2184     if (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) {
2185       REBAR_Layout (hwnd, NULL, TRUE, FALSE);
2186       REBAR_ForceResize (hwnd);
2187       REBAR_MoveChildWindows (hwnd);
2188     }
2189
2190     return TRUE;
2191 }
2192
2193
2194 static LRESULT
2195 REBAR_SetBarInfo (HWND hwnd, WPARAM wParam, LPARAM lParam)
2196 {
2197     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2198     LPREBARINFO lpInfo = (LPREBARINFO)lParam;
2199
2200     if (lpInfo == NULL)
2201         return FALSE;
2202
2203     if (lpInfo->cbSize < sizeof (REBARINFO))
2204         return FALSE;
2205
2206     TRACE("setting bar info!\n");
2207
2208     if (lpInfo->fMask & RBIM_IMAGELIST) {
2209         infoPtr->himl = lpInfo->himl;
2210         if (infoPtr->himl) {
2211             INT cx, cy;
2212             ImageList_GetIconSize (infoPtr->himl, &cx, &cy);
2213             infoPtr->imageSize.cx = cx;
2214             infoPtr->imageSize.cy = cy;
2215         }
2216         else {
2217             infoPtr->imageSize.cx = 0;
2218             infoPtr->imageSize.cy = 0;
2219         }
2220         TRACE("new image cx=%ld, cy=%ld\n", infoPtr->imageSize.cx,
2221               infoPtr->imageSize.cy);
2222     }
2223
2224     return TRUE;
2225 }
2226
2227
2228 static LRESULT
2229 REBAR_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2230 {
2231     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2232     COLORREF clrTemp;
2233
2234     clrTemp = infoPtr->clrBk;
2235     infoPtr->clrBk = (COLORREF)lParam;
2236
2237     TRACE("background color 0x%06lx!\n", infoPtr->clrBk);
2238
2239     return clrTemp;
2240 }
2241
2242
2243 /* << REBAR_SetColorScheme >> */
2244 /* << REBAR_SetPalette >> */
2245
2246
2247 static LRESULT
2248 REBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2249 {
2250     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2251     HWND hwndTemp = infoPtr->hwndNotify;
2252
2253     infoPtr->hwndNotify = (HWND)wParam;
2254
2255     return (LRESULT)hwndTemp;
2256 }
2257
2258
2259 static LRESULT
2260 REBAR_SetTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2261 {
2262     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2263     COLORREF clrTemp;
2264
2265     clrTemp = infoPtr->clrText;
2266     infoPtr->clrText = (COLORREF)lParam;
2267
2268     TRACE("text color 0x%06lx!\n", infoPtr->clrText);
2269
2270     return clrTemp;
2271 }
2272
2273
2274 /* << REBAR_SetTooltips >> */
2275
2276
2277 inline static LRESULT
2278 REBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam)
2279 {
2280     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2281     BOOL bTemp = infoPtr->bUnicode;
2282     infoPtr->bUnicode = (BOOL)wParam;
2283     return bTemp;
2284 }
2285
2286
2287 static LRESULT
2288 REBAR_SetVersion (HWND hwnd, INT iVersion)
2289 {
2290     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2291     INT iOldVersion = infoPtr->iVersion;
2292
2293     if (iVersion > COMCTL32_VERSION)
2294         return -1;
2295
2296     infoPtr->iVersion = iVersion;
2297
2298     TRACE("new version %d\n", iVersion);
2299
2300     return iOldVersion;
2301 }
2302
2303
2304 static LRESULT
2305 REBAR_ShowBand (HWND hwnd, WPARAM wParam, LPARAM lParam)
2306 {
2307     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2308     REBAR_BAND *lpBand;
2309
2310     if (((INT)wParam < 0) || ((INT)wParam > infoPtr->uNumBands))
2311         return FALSE;
2312
2313     lpBand = &infoPtr->bands[(INT)wParam];
2314
2315     if ((BOOL)lParam) {
2316         TRACE("show band %d\n", (INT)wParam);
2317         lpBand->fStyle = lpBand->fStyle & ~RBBS_HIDDEN;
2318         if (IsWindow (lpBand->hwndChild))
2319             ShowWindow (lpBand->hwndChild, SW_SHOW);
2320     }
2321     else {
2322         TRACE("hide band %d\n", (INT)wParam);
2323         lpBand->fStyle = lpBand->fStyle | RBBS_HIDDEN;
2324         if (IsWindow (lpBand->hwndChild))
2325             ShowWindow (lpBand->hwndChild, SW_SHOW);
2326     }
2327
2328     REBAR_Layout (hwnd, NULL, TRUE, FALSE);
2329     REBAR_ForceResize (hwnd);
2330     REBAR_MoveChildWindows (hwnd);
2331
2332     return TRUE;
2333 }
2334
2335
2336 static LRESULT
2337 REBAR_SizeToRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2338 {
2339     LPRECT lpRect = (LPRECT)lParam;
2340     RECT t1;
2341
2342     if (lpRect == NULL)
2343        return FALSE;
2344
2345     TRACE("[%d %d %d %d]\n",
2346           lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
2347
2348     /*  what is going on???? */
2349     GetWindowRect(hwnd, &t1);
2350     TRACE("window rect [%d %d %d %d]\n",
2351           t1.left, t1.top, t1.right, t1.bottom);
2352     GetClientRect(hwnd, &t1);
2353     TRACE("client rect [%d %d %d %d]\n",
2354           t1.left, t1.top, t1.right, t1.bottom);
2355
2356     REBAR_Layout (hwnd, lpRect, TRUE, FALSE);
2357     REBAR_ForceResize (hwnd);
2358     REBAR_MoveChildWindows (hwnd);
2359     return TRUE;
2360 }
2361
2362
2363
2364 static LRESULT
2365 REBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
2366 {
2367     REBAR_INFO *infoPtr;
2368
2369     /* allocate memory for info structure */
2370     infoPtr = (REBAR_INFO *)COMCTL32_Alloc (sizeof(REBAR_INFO));
2371     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
2372
2373     /* initialize info structure */
2374     infoPtr->iVersion = 0;
2375     infoPtr->clrBk = CLR_NONE;
2376     infoPtr->clrText = GetSysColor (COLOR_BTNTEXT);
2377     infoPtr->ihitBand = -1;
2378     infoPtr->fStatus = 0;
2379
2380     infoPtr->hcurArrow = LoadCursorA (0, IDC_ARROWA);
2381     infoPtr->hcurHorz  = LoadCursorA (0, IDC_SIZEWEA);
2382     infoPtr->hcurVert  = LoadCursorA (0, IDC_SIZENSA);
2383     infoPtr->hcurDrag  = LoadCursorA (0, IDC_SIZEA);
2384
2385     infoPtr->bUnicode = IsWindowUnicode (hwnd);
2386
2387     if (GetWindowLongA (hwnd, GWL_STYLE) & RBS_AUTOSIZE)
2388         FIXME("style RBS_AUTOSIZE set!\n");
2389
2390 #if 0
2391     SendMessageA (hwnd, WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY);
2392 #endif
2393
2394     TRACE("created!\n");
2395     return 0;
2396 }
2397
2398
2399 static LRESULT
2400 REBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
2401 {
2402     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2403     REBAR_BAND *lpBand;
2404     INT i;
2405
2406
2407     /* free rebar bands */
2408     if ((infoPtr->uNumBands > 0) && infoPtr->bands) {
2409         /* clean up each band */
2410         for (i = 0; i < infoPtr->uNumBands; i++) {
2411             lpBand = &infoPtr->bands[i];
2412
2413             /* delete text strings */
2414             if (lpBand->lpText) {
2415                 COMCTL32_Free (lpBand->lpText);
2416                 lpBand->lpText = NULL;
2417             }
2418             /* destroy child window */
2419             DestroyWindow (lpBand->hwndChild);
2420         }
2421
2422         /* free band array */
2423         COMCTL32_Free (infoPtr->bands);
2424         infoPtr->bands = NULL;
2425     }
2426
2427     DeleteObject (infoPtr->hcurArrow);
2428     DeleteObject (infoPtr->hcurHorz);
2429     DeleteObject (infoPtr->hcurVert);
2430     DeleteObject (infoPtr->hcurDrag);
2431
2432     /* free rebar info data */
2433     COMCTL32_Free (infoPtr);
2434     SetWindowLongA (hwnd, 0, 0);
2435     TRACE("destroyed!\n");
2436     return 0;
2437 }
2438
2439
2440 static LRESULT
2441 REBAR_EraseBkGnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
2442 {
2443     RECT cliprect;
2444
2445     if (GetClipBox ( (HDC)wParam, &cliprect))
2446         return REBAR_InternalEraseBkGnd (hwnd, wParam, lParam, &cliprect);
2447     return 0;
2448 }
2449
2450
2451 static LRESULT
2452 REBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2453 {
2454     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2455
2456     return (LRESULT)infoPtr->hFont;
2457 }
2458
2459
2460 static LRESULT
2461 REBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
2462 {
2463     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2464     REBAR_BAND *lpBand;
2465
2466     /* If InternalHitTest did not find a hit on the Gripper, */
2467     /* then ignore the button click.                         */
2468     if (infoPtr->ihitBand == -1) return 0;
2469
2470     SetCapture (hwnd);
2471
2472     /* save off the LOWORD and HIWORD of lParam as initial x,y */
2473     lpBand = &infoPtr->bands[infoPtr->ihitBand];
2474     infoPtr->dragStart = MAKEPOINTS(lParam);
2475     infoPtr->dragNow = infoPtr->dragStart;
2476     infoPtr->ihitoffset = infoPtr->dragStart.x - lpBand->rcGripper.left;
2477
2478     return 0;
2479 }
2480
2481
2482 static LRESULT
2483 REBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
2484 {
2485     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2486     NMHDR layout;
2487     NMREBAR enddrag;
2488     RECT rect;
2489
2490     /* If InternalHitTest did not find a hit on the Gripper, */
2491     /* then ignore the button click.                         */
2492     if (infoPtr->ihitBand == -1) return 0;
2493
2494     infoPtr->dragStart.x = 0;
2495     infoPtr->dragStart.y = 0;
2496     infoPtr->dragNow = infoPtr->dragStart;
2497     infoPtr->ihitBand = -1;
2498
2499     ReleaseCapture ();
2500
2501     if (infoPtr->fStatus & BEGIN_DRAG_ISSUED) {
2502         REBAR_Notify(hwnd, (NMHDR *) &layout, RBN_LAYOUTCHANGED);
2503
2504         enddrag.dwMask = 0;
2505         enddrag.uBand = -1;
2506         REBAR_Notify(hwnd, (NMHDR *) &enddrag, RBN_ENDDRAG);
2507         infoPtr->fStatus &= ~BEGIN_DRAG_ISSUED;
2508     }
2509
2510     GetClientRect(hwnd, &rect);
2511     InvalidateRect(hwnd, NULL, TRUE);
2512
2513     return 0;
2514 }
2515
2516
2517 static LRESULT
2518 REBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
2519 {
2520     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2521     REBAR_BAND *band1, *band2;
2522     POINTS ptsmove;
2523
2524     /* Validate entry as hit on Gripper has occured */
2525     if (GetCapture() != hwnd) return 0;
2526     if (infoPtr->ihitBand == -1) return 0;
2527
2528     ptsmove = MAKEPOINTS(lParam);
2529
2530     /* if mouse did not move much, exit */
2531     if ((abs(ptsmove.x - infoPtr->dragNow.x) <= mindragx) &&
2532         (abs(ptsmove.y - infoPtr->dragNow.y) <= mindragy)) return 0;
2533
2534     band1 = &infoPtr->bands[infoPtr->ihitBand-1];
2535     band2 = &infoPtr->bands[infoPtr->ihitBand];
2536
2537     /* Test for valid drag case - must not be first band in row */
2538     if ((ptsmove.y < band2->rcBand.top) ||
2539         (ptsmove.y > band2->rcBand.bottom) ||
2540         ((infoPtr->ihitBand > 0) && (band1->iRow != band2->iRow))) {
2541         FIXME("Cannot drag to other rows yet!!\n");
2542     }
2543     else {
2544         REBAR_HandleLRDrag (hwnd, infoPtr, &ptsmove);
2545     }
2546     return 0;
2547 }
2548
2549
2550 inline static LRESULT
2551 REBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2552 {
2553     if (GetWindowLongA (hwnd, GWL_STYLE) & WS_BORDER) {
2554         ((LPRECT)lParam)->left   += GetSystemMetrics(SM_CXEDGE);
2555         ((LPRECT)lParam)->top    += GetSystemMetrics(SM_CYEDGE);
2556         ((LPRECT)lParam)->right  -= GetSystemMetrics(SM_CXEDGE);
2557         ((LPRECT)lParam)->bottom -= GetSystemMetrics(SM_CYEDGE);
2558     }
2559
2560     return 0;
2561 }
2562
2563
2564 static LRESULT
2565 REBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
2566 {
2567     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2568     RECT rcWindow;
2569     HDC hdc;
2570
2571     if (dwStyle & WS_MINIMIZE)
2572         return 0; /* Nothing to do */
2573
2574     DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
2575
2576     if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW )))
2577         return 0;
2578
2579     if (dwStyle & WS_BORDER) {
2580         GetWindowRect (hwnd, &rcWindow);
2581         OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
2582         DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT);
2583     }
2584
2585     ReleaseDC( hwnd, hdc );
2586
2587     return 0;
2588 }
2589
2590
2591 static LRESULT
2592 REBAR_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
2593 {
2594     HDC hdc;
2595     PAINTSTRUCT ps;
2596
2597     hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
2598
2599     if (ps.fErase) {
2600         /* Erase area of paint if requested */
2601         REBAR_InternalEraseBkGnd (hwnd, wParam, lParam, &ps.rcPaint);
2602     }
2603
2604     REBAR_Refresh (hwnd, hdc);
2605     if (!wParam)
2606         EndPaint (hwnd, &ps);
2607     return 0;
2608 }
2609
2610
2611 static LRESULT
2612 REBAR_SetCursor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2613 {
2614     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2615     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2616     POINT pt;
2617     UINT  flags;
2618
2619     TRACE("code=0x%X  id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
2620
2621     GetCursorPos (&pt);
2622     ScreenToClient (hwnd, &pt);
2623
2624     REBAR_InternalHitTest (hwnd, &pt, &flags, NULL);
2625
2626     if (flags == RBHT_GRABBER) {
2627         if ((dwStyle & CCS_VERT) &&
2628             !(dwStyle & RBS_VERTICALGRIPPER))
2629             SetCursor (infoPtr->hcurVert);
2630         else
2631             SetCursor (infoPtr->hcurHorz);
2632     }
2633     else if (flags != RBHT_CLIENT)
2634         SetCursor (infoPtr->hcurArrow);
2635
2636     return 0;
2637 }
2638
2639
2640 static LRESULT
2641 REBAR_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2642 {
2643     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2644     
2645     /* TEXTMETRIC32A tm; */
2646     HFONT hFont /*, hOldFont */;
2647     /* HDC32 hdc; */
2648
2649     infoPtr->hFont = (HFONT)wParam;
2650
2651     hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
2652 /*
2653     hdc = GetDC32 (0);
2654     hOldFont = SelectObject32 (hdc, hFont);
2655     GetTextMetrics32A (hdc, &tm);
2656     infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
2657     SelectObject32 (hdc, hOldFont);
2658     ReleaseDC32 (0, hdc);
2659 */
2660     if (lParam) {
2661 /*
2662         REBAR_Layout (hwnd);
2663         hdc = GetDC32 (hwnd);
2664         REBAR_Refresh (hwnd, hdc);
2665         ReleaseDC32 (hwnd, hdc);
2666 */
2667     }
2668
2669     return 0;
2670 }
2671
2672 static LRESULT
2673 REBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
2674 {
2675     REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd);
2676     RECT rcClient;
2677
2678     /* auto resize deadlock check */
2679     if (infoPtr->fStatus & AUTO_RESIZE) {
2680         infoPtr->fStatus &= ~AUTO_RESIZE;
2681         return 0;
2682     }
2683
2684     GetClientRect (hwnd, &rcClient);
2685     if ((lParam == 0) && (rcClient.right == 0) && (rcClient.bottom == 0)) {
2686       /* native control seems to do this */
2687       GetClientRect (GetParent(hwnd), &rcClient);
2688       TRACE("sizing rebar, message and client zero, parent client (%d,%d)\n", 
2689             rcClient.right, rcClient.bottom);
2690     }
2691     else {
2692       TRACE("sizing rebar to (%d,%d), client (%d,%d)\n", 
2693             LOWORD(lParam), HIWORD(lParam), rcClient.right, rcClient.bottom);
2694     }
2695
2696     REBAR_Layout (hwnd, &rcClient, FALSE, TRUE);
2697     REBAR_ForceResize (hwnd);
2698     REBAR_MoveChildWindows (hwnd);
2699
2700     return 0;
2701 }
2702
2703
2704 static LRESULT WINAPI
2705 REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2706 {
2707     TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam);
2708     if (!REBAR_GetInfoPtr (hwnd) && (uMsg != WM_CREATE))
2709             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2710     switch (uMsg)
2711     {
2712 /*      case RB_BEGINDRAG: */
2713
2714         case RB_DELETEBAND:
2715             return REBAR_DeleteBand (hwnd, wParam, lParam);
2716
2717 /*      case RB_DRAGMOVE: */
2718 /*      case RB_ENDDRAG: */
2719
2720         case RB_GETBANDBORDERS:
2721             return REBAR_GetBandBorders (hwnd, wParam, lParam);
2722
2723         case RB_GETBANDCOUNT:
2724             return REBAR_GetBandCount (hwnd);
2725
2726         case RB_GETBANDINFO:    /* obsoleted after IE3, but we have to
2727                                    support it anyway. */
2728         case RB_GETBANDINFOA:
2729             return REBAR_GetBandInfoA (hwnd, wParam, lParam);
2730
2731         case RB_GETBANDINFOW:
2732             return REBAR_GetBandInfoW (hwnd, wParam, lParam);
2733
2734         case RB_GETBARHEIGHT:
2735             return REBAR_GetBarHeight (hwnd, wParam, lParam);
2736
2737         case RB_GETBARINFO:
2738             return REBAR_GetBarInfo (hwnd, wParam, lParam);
2739
2740         case RB_GETBKCOLOR:
2741             return REBAR_GetBkColor (hwnd);
2742
2743 /*      case RB_GETCOLORSCHEME: */
2744 /*      case RB_GETDROPTARGET: */
2745
2746         case RB_GETPALETTE:
2747             return REBAR_GetPalette (hwnd, wParam, lParam);
2748
2749         case RB_GETRECT:
2750             return REBAR_GetRect (hwnd, wParam, lParam);
2751
2752         case RB_GETROWCOUNT:
2753             return REBAR_GetRowCount (hwnd);
2754
2755         case RB_GETROWHEIGHT:
2756             return REBAR_GetRowHeight (hwnd, wParam, lParam);
2757
2758         case RB_GETTEXTCOLOR:
2759             return REBAR_GetTextColor (hwnd);
2760
2761         case RB_GETTOOLTIPS:
2762             return REBAR_GetToolTips (hwnd);
2763
2764         case RB_GETUNICODEFORMAT:
2765             return REBAR_GetUnicodeFormat (hwnd);
2766
2767         case CCM_GETVERSION:
2768             return REBAR_GetVersion (hwnd);
2769
2770         case RB_HITTEST:
2771             return REBAR_HitTest (hwnd, wParam, lParam);
2772
2773         case RB_IDTOINDEX:
2774             return REBAR_IdToIndex (hwnd, wParam, lParam);
2775
2776         case RB_INSERTBANDA:
2777             return REBAR_InsertBandA (hwnd, wParam, lParam);
2778
2779         case RB_INSERTBANDW:
2780             return REBAR_InsertBandW (hwnd, wParam, lParam);
2781
2782         case RB_MAXIMIZEBAND:
2783             return REBAR_MaximizeBand (hwnd, wParam, lParam);
2784
2785         case RB_MINIMIZEBAND:
2786             return REBAR_MinimizeBand (hwnd, wParam, lParam);
2787
2788         case RB_MOVEBAND:
2789             return REBAR_MoveBand (hwnd, wParam, lParam);
2790
2791         case RB_SETBANDINFOA:
2792             return REBAR_SetBandInfoA (hwnd, wParam, lParam);
2793
2794         case RB_SETBANDINFOW:
2795             return REBAR_SetBandInfoW (hwnd, wParam, lParam);
2796
2797         case RB_SETBARINFO:
2798             return REBAR_SetBarInfo (hwnd, wParam, lParam);
2799
2800         case RB_SETBKCOLOR:
2801             return REBAR_SetBkColor (hwnd, wParam, lParam);
2802
2803 /*      case RB_SETCOLORSCHEME: */
2804 /*      case RB_SETPALETTE: */
2805 /*          return REBAR_GetPalette (hwnd, wParam, lParam); */
2806
2807         case RB_SETPARENT:
2808             return REBAR_SetParent (hwnd, wParam, lParam);
2809
2810         case RB_SETTEXTCOLOR:
2811             return REBAR_SetTextColor (hwnd, wParam, lParam);
2812
2813 /*      case RB_SETTOOLTIPS: */
2814
2815         case RB_SETUNICODEFORMAT:
2816             return REBAR_SetUnicodeFormat (hwnd, wParam);
2817
2818         case CCM_SETVERSION:
2819             return REBAR_SetVersion (hwnd, (INT)wParam);
2820
2821         case RB_SHOWBAND:
2822             return REBAR_ShowBand (hwnd, wParam, lParam);
2823
2824         case RB_SIZETORECT:
2825             return REBAR_SizeToRect (hwnd, wParam, lParam);
2826
2827
2828         case WM_COMMAND:
2829             return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
2830
2831         case WM_CREATE:
2832             return REBAR_Create (hwnd, wParam, lParam);
2833
2834         case WM_DESTROY:
2835             return REBAR_Destroy (hwnd, wParam, lParam);
2836
2837         case WM_GETFONT:
2838             return REBAR_GetFont (hwnd, wParam, lParam);
2839
2840         case WM_LBUTTONDOWN:
2841             return REBAR_LButtonDown (hwnd, wParam, lParam);
2842
2843         case WM_LBUTTONUP:
2844             return REBAR_LButtonUp (hwnd, wParam, lParam);
2845
2846         case WM_MOUSEMOVE:
2847             return REBAR_MouseMove (hwnd, wParam, lParam);
2848
2849         case WM_NCCALCSIZE:
2850             return REBAR_NCCalcSize (hwnd, wParam, lParam);
2851
2852         case WM_NCPAINT:
2853             return REBAR_NCPaint (hwnd, wParam, lParam);
2854
2855         case WM_NOTIFY:
2856             return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
2857
2858         case WM_PAINT:
2859             return REBAR_Paint (hwnd, wParam, lParam);
2860
2861         case WM_SETCURSOR:
2862             return REBAR_SetCursor (hwnd, wParam, lParam);
2863
2864         case WM_SETFONT:
2865             return REBAR_SetFont (hwnd, wParam, lParam);
2866
2867         case WM_SIZE:
2868             return REBAR_Size (hwnd, wParam, lParam);
2869         case WM_DRAWITEM:
2870             return SendMessageA(GetParent(hwnd),uMsg,wParam,lParam);
2871
2872 /*      case WM_TIMER: */
2873
2874 /*      case WM_WININICHANGE: */
2875
2876         case WM_ERASEBKGND:
2877           return REBAR_EraseBkGnd (hwnd, wParam, lParam);
2878
2879         default:
2880             if (uMsg >= WM_USER)
2881                 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2882                      uMsg, wParam, lParam);
2883             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2884     }
2885     return 0;
2886 }
2887
2888
2889 VOID
2890 REBAR_Register (void)
2891 {
2892     WNDCLASSA wndClass;
2893
2894     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2895     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
2896     wndClass.lpfnWndProc   = (WNDPROC)REBAR_WindowProc;
2897     wndClass.cbClsExtra    = 0;
2898     wndClass.cbWndExtra    = sizeof(REBAR_INFO *);
2899     wndClass.hCursor       = 0;
2900     wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2901     wndClass.lpszClassName = REBARCLASSNAMEA;
2902  
2903     RegisterClassA (&wndClass);
2904
2905     mindragx = GetSystemMetrics (SM_CXDRAG);
2906     mindragy = GetSystemMetrics (SM_CYDRAG);
2907
2908 }
2909
2910
2911 VOID
2912 REBAR_Unregister (void)
2913 {
2914     UnregisterClassA (REBARCLASSNAMEA, (HINSTANCE)NULL);
2915 }
2916