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