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