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