Better implementation of GetCalendarInfo{A,W}, not perfect.
[wine] / dlls / comctl32 / toolbar.c
1 /*
2  * Toolbar control
3  *
4  * Copyright 1998,1999 Eric Kohl
5  * Copyright 2000 Eric Kohl for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  *  Differences between MSDN and actual native control operation:
22  *   1. MSDN says: "TBSTYLE_LIST: Creates a flat toolbar with button text
23  *                  to the right of the bitmap. Otherwise, this style is
24  *                  identical to TBSTYLE_FLAT."
25  *      As implemented by both v4.71 and v5.80 of the native COMCTL32.DLL
26  *      you can create a TBSTYLE_LIST without TBSTYLE_FLAT and the result
27  *      is non-flat non-transparent buttons. Therefore TBSTYLE_LIST does
28  *      *not* imply TBSTYLE_FLAT as documented.  (GA 8/2001)
29  *
30  *
31  * TODO:
32  *   - A little bug in TOOLBAR_DrawMasked()
33  *   - Button wrapping (under construction).
34  *   - Messages.
35  *   - Notifications (under construction).
36  *   - Fix TB_SETROWS.
37  *   - Tooltip support (almost complete).
38  *   - Unicode suppport (under construction).
39  *   - Fix TOOLBAR_SetButtonInfo32A/W.
40  *   - TBSTYLE_AUTOSIZE for toolbar and buttons.
41  *   - I_IMAGECALLBACK support.
42  *   - iString of -1 is undocumented
43  *   - Customization dialog:
44  *      - Add flat look.
45  *      - Minor buglet in 'available buttons' list:
46  *        Buttons are not listed in M$-like order. M$ seems to use a single
47  *        internal list to store the button information of both listboxes.
48  *      - Drag list support.
49  *      - Help and Reset button support.
50  *
51  * Testing:
52  *   - Run tests using Waite Group Windows95 API Bible Volume 2.
53  *     The second cdrom contains executables addstr.exe, btncount.exe,
54  *     btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
55  *     enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
56  *     indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
57  *     setparnt.exe, setrows.exe, toolwnd.exe.
58  *   - Microsofts controlspy examples.
59  *   - Charles Petzold's 'Programming Windows': gadgets.exe
60  */
61
62 #include <string.h>
63
64 #include "winbase.h"
65 #include "windef.h"
66 #include "wingdi.h"
67 #include "winuser.h"
68 #include "wine/unicode.h"
69 #include "commctrl.h"
70 #include "imagelist.h"
71 #include "comctl32.h"
72 #include "wine/debug.h"
73
74 WINE_DEFAULT_DEBUG_CHANNEL(toolbar);
75
76 typedef struct
77 {
78     INT iBitmap;
79     INT idCommand;
80     BYTE  fsState;
81     BYTE  fsStyle;
82     DWORD dwData;
83     INT iString;
84
85     BOOL bHot;
86     INT nRow;
87     RECT rect;
88 } TBUTTON_INFO; 
89
90 typedef struct
91 {
92     UINT nButtons;
93     HINSTANCE hInst;
94     UINT nID;
95 } TBITMAP_INFO;
96
97 typedef struct
98 {
99     DWORD      dwStructSize;   /* size of TBBUTTON struct */
100     INT      nHeight;        /* height of the toolbar */
101     INT      nWidth;         /* width of the toolbar */
102     INT      nButtonHeight;
103     INT      nButtonWidth;
104     INT      nBitmapHeight;
105     INT      nBitmapWidth;
106     INT      nIndent;
107     INT      nRows;           /* number of button rows */
108     INT      nMaxTextRows;    /* maximum number of text rows */
109     INT      cxMin;           /* minimum button width */
110     INT      cxMax;           /* maximum button width */
111     INT      nNumButtons;     /* number of buttons */
112     INT      nNumBitmaps;     /* number of bitmaps */
113     INT      nNumStrings;     /* number of strings */
114     INT      nNumBitmapInfos;
115     BOOL     bUnicode;        /* ASCII (FALSE) or Unicode (TRUE)? */
116     BOOL     bCaptured;       /* mouse captured? */
117     INT      nButtonDown;
118     INT      nOldHit;
119     INT      nHotItem;        /* index of the "hot" item */
120     DWORD    dwBaseCustDraw;  /* CDRF_ response (w/o TBCDRF_) from PREPAINT */
121     DWORD    dwItemCustDraw;  /* CDRF_ response (w/o TBCDRF_) from ITEMPREP */
122     DWORD    dwItemCDFlag;    /* TBCDRF_ flags from last ITEMPREPAINT    */
123     SIZE     szPadding;       /* padding values around button */
124     HFONT    hDefaultFont;
125     HFONT    hFont;           /* text font */
126     HIMAGELIST himlInt;         /* image list created internally */
127     HIMAGELIST himlDef;         /* default image list */
128     HIMAGELIST himlHot;         /* hot image list */
129     HIMAGELIST himlDis;         /* disabled image list */
130     HWND     hwndToolTip;     /* handle to tool tip control */
131     HWND     hwndNotify;      /* handle to the window that gets notifications */
132     HWND     hwndSelf;        /* my own handle */
133     BOOL     bTransparent;    /* background transparency flag */
134     BOOL     bBtnTranspnt;    /* button transparency flag */
135     BOOL     bAutoSize;       /* auto size deadlock indicator */
136     BOOL     bAnchor;         /* anchor highlight enabled */
137     BOOL     bNtfUnicode;     /* TRUE if NOTIFYs use {W} */
138     BOOL     bDoRedraw;       /* Redraw status */
139     DWORD      dwExStyle;       /* extended toolbar style */
140     DWORD      dwDTFlags;       /* DrawText flags */
141
142     COLORREF   clrInsertMark;   /* insert mark color */
143     COLORREF   clrBtnHighlight; /* color for Flat Separator */
144     COLORREF   clrBtnShadow;    /* color for Flag Separator */
145     RECT     rcBound;         /* bounding rectangle */
146     INT      iVersion;
147
148     TBUTTON_INFO *buttons;      /* pointer to button array */
149     LPWSTR       *strings;      /* pointer to string array */
150     TBITMAP_INFO *bitmaps;
151 } TOOLBAR_INFO, *PTOOLBAR_INFO;
152
153
154 /* used by customization dialog */
155 typedef struct
156 {
157     PTOOLBAR_INFO tbInfo;
158     HWND          tbHwnd;
159 } CUSTDLG_INFO, *PCUSTDLG_INFO;
160
161 typedef struct
162 {
163     TBBUTTON btn;
164     BOOL     bVirtual;
165     BOOL     bRemovable;
166     CHAR     text[64];
167 } CUSTOMBUTTON, *PCUSTOMBUTTON;
168
169
170 #define SEPARATOR_WIDTH    8
171 #define TOP_BORDER         2
172 #define BOTTOM_BORDER      2
173 #define DDARROW_WIDTH      11 
174
175 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
176 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
177 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
178
179 /* Used to find undocumented extended styles */
180 #define TBSTYLE_EX_ALL (TBSTYLE_EX_DRAWDDARROWS | \
181                         TBSTYLE_EX_UNDOC1 | \
182                         TBSTYLE_EX_MIXEDBUTTONS | \
183                         TBSTYLE_EX_HIDECLIPPEDBUTTONS)
184
185 static LRESULT
186 TOOLBAR_NotifyFormat(TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam);
187
188
189 static LPWSTR
190 TOOLBAR_GetText(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
191 {
192     LPWSTR lpText = NULL;
193
194     /* FIXME: iString == -1 is undocumented */
195     if ((HIWORD(btnPtr->iString) != 0) && (btnPtr->iString != -1))
196         lpText = (LPWSTR)btnPtr->iString;
197     else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
198         lpText = infoPtr->strings[btnPtr->iString];
199     
200     return lpText;
201 }
202
203 static void
204 TOOLBAR_DumpButton(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *bP, INT btn_num, BOOL internal)
205 {
206     if (TRACE_ON(toolbar)){
207         TRACE("button %d id %d, bitmap=%d, state=%02x, style=%02x, data=%08lx, stringid=0x%08x\n",
208               btn_num, bP->idCommand,
209               bP->iBitmap, bP->fsState, bP->fsStyle, bP->dwData, bP->iString);
210         TRACE("string %s\n", debugstr_w(TOOLBAR_GetText(infoPtr,bP)));
211         if (internal)
212             TRACE("button %d id %d, hot=%s, row=%d, rect=(%d,%d)-(%d,%d)\n",
213                   btn_num, bP->idCommand,
214                   (bP->bHot) ? "TRUE":"FALSE", bP->nRow,
215                   bP->rect.left, bP->rect.top, 
216                   bP->rect.right, bP->rect.bottom);
217     }
218 }
219
220
221 static void
222 TOOLBAR_DumpToolbar(TOOLBAR_INFO *iP, INT line)
223 {
224     if (TRACE_ON(toolbar)) {
225         INT i;
226         DWORD dwStyle;
227
228         dwStyle = GetWindowLongA (iP->hwndSelf, GWL_STYLE);
229         TRACE("toolbar %08x at line %d, exStyle=%08lx, buttons=%d, bitmaps=%d, strings=%d, style=%08lx\n",
230               iP->hwndSelf, line,
231               iP->dwExStyle, iP->nNumButtons, iP->nNumBitmaps,
232               iP->nNumStrings, dwStyle);
233         TRACE("toolbar %08x at line %d, himlInt=%p, himlDef=%p, himlHot=%p, himlDis=%p, redrawable=%s\n",
234               iP->hwndSelf, line,
235               iP->himlInt, iP->himlDef, iP->himlHot, iP->himlDis,
236               (iP->bDoRedraw) ? "TRUE" : "FALSE");
237         for(i=0; i<iP->nNumButtons; i++) {
238             TOOLBAR_DumpButton(iP, &iP->buttons[i], i, TRUE);
239         }
240     }
241 }
242
243
244 /***********************************************************************
245 *               TOOLBAR_CheckStyle
246 *
247 * This function validates that the styles set are implemented and
248 * issues FIXME's warning of possible problems. In a perfect world this
249 * function should be null.
250 */
251 static void
252 TOOLBAR_CheckStyle (HWND hwnd, DWORD dwStyle)
253 {
254     if (dwStyle & TBSTYLE_ALTDRAG)
255         FIXME("[%04x] TBSTYLE_ALTDRAG not implemented\n", hwnd);
256     if (dwStyle & TBSTYLE_REGISTERDROP)
257         FIXME("[%04x] TBSTYLE_REGISTERDROP not implemented\n", hwnd);
258 }
259
260
261 static INT
262 TOOLBAR_SendNotify (NMHDR *nmhdr, TOOLBAR_INFO *infoPtr, UINT code)
263 {
264         if(!IsWindow(infoPtr->hwndSelf))
265             return 0;   /* we have just been destroyed */
266         
267     nmhdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf);
268     nmhdr->hwndFrom = infoPtr->hwndSelf;
269     nmhdr->code = code;
270
271     TRACE("to window %04x, code=%08x, %s\n", infoPtr->hwndNotify, code,
272           (infoPtr->bNtfUnicode) ? "via Unicode" : "via ANSI");
273
274     if (infoPtr->bNtfUnicode)
275         return SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, 
276                              (WPARAM) nmhdr->idFrom, (LPARAM)nmhdr);
277     else
278         return SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, 
279                              (WPARAM) nmhdr->idFrom, (LPARAM)nmhdr);
280 }
281
282 /***********************************************************************
283 *               TOOLBAR_GetBitmapIndex
284 *
285 * This function returns the bitmap index associated with a button.
286 * If the button specifies I_IMAGECALLBACK, then the TBN_GETDISPINFO
287 * is issued to retrieve the index.
288 */
289 static INT 
290 TOOLBAR_GetBitmapIndex(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
291 {
292     INT ret = btnPtr->iBitmap;
293
294     if (ret == I_IMAGECALLBACK) {
295         /* issue TBN_GETDISPINFO */
296         NMTBDISPINFOA nmgd;
297
298         nmgd.idCommand = btnPtr->idCommand;
299         nmgd.lParam = btnPtr->dwData;
300         nmgd.dwMask = TBNF_IMAGE;
301         TOOLBAR_SendNotify ((NMHDR *) &nmgd, infoPtr,
302                         (infoPtr->bNtfUnicode) ? TBN_GETDISPINFOW :
303                         TBN_GETDISPINFOA);
304         if (nmgd.dwMask & TBNF_DI_SETITEM) {
305             btnPtr->iBitmap = nmgd.iImage;
306         }
307         ret = nmgd.iImage;
308         TRACE("TBN_GETDISPINFOA returned bitmap id %d, mask=%08lx, nNumBitmaps=%d\n", 
309               ret, nmgd.dwMask, infoPtr->nNumBitmaps);
310     }
311     return ret;
312 }
313
314
315 static BOOL 
316 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
317 {
318     if (((index>=0) && (index <= infoPtr->nNumBitmaps)) ||
319         (index == I_IMAGECALLBACK))
320       return TRUE;
321     else
322       return FALSE;
323 }
324
325
326 /***********************************************************************
327 *               TOOLBAR_DrawImageList
328 *
329 * This function validates the bitmap index (including I_IMAGECALLBACK
330 * functionality). It then draws the image via the ImageList_Draw
331 * function. It returns TRUE if the image was drawn, FALSE otherwise. 
332 */
333 static BOOL
334 TOOLBAR_DrawImageList (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HIMAGELIST himl,
335                         HDC hdc, UINT left, UINT top, UINT draw_flags)
336 {
337     INT index;
338
339     if (!himl) return FALSE;
340
341     if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
342         if (btnPtr->iBitmap == I_IMAGENONE) return FALSE;
343         ERR("index %d is not valid, max %d\n", 
344             btnPtr->iBitmap, infoPtr->nNumBitmaps);
345         return FALSE;
346     }
347
348     if ((index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) {
349         if ((index == I_IMAGECALLBACK) ||
350             (index == I_IMAGENONE)) return FALSE;
351         ERR("TBN_GETDISPINFO returned invalid index %d\n",
352             index);
353         return FALSE;
354     }
355     TRACE("drawing index=%d, himl=%p, left=%d, top=%d, flags=%08x\n",
356           index, himl, left, top, draw_flags);
357
358     ImageList_Draw (himl, index, hdc, left, top, draw_flags);
359     return TRUE;
360 }
361
362
363 /***********************************************************************
364 *               TOOLBAR_TestImageExist
365 *
366 * This function is similar to TOOLBAR_DrawImageList, except it does not
367 * draw the image. The I_IMAGECALLBACK functionality is implemented.
368 */
369 static BOOL
370 TOOLBAR_TestImageExist (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HIMAGELIST himl)
371 {
372     INT index;
373
374     if (!himl) return FALSE;
375
376     if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
377         if (btnPtr->iBitmap == I_IMAGENONE) return FALSE;
378         ERR("index %d is not valid, max %d\n", 
379             btnPtr->iBitmap, infoPtr->nNumBitmaps);
380         return FALSE;
381     }
382
383     if ((index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) {
384         if ((index == I_IMAGECALLBACK) ||
385             (index == I_IMAGENONE)) return FALSE;
386         ERR("TBN_GETDISPINFO returned invalid index %d\n",
387             index);
388         return FALSE;
389     }
390     return TRUE;
391 }
392
393
394 static void
395 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc, TOOLBAR_INFO *infoPtr)
396 {
397     RECT myrect;
398     COLORREF oldcolor, newcolor;
399
400     myrect.left = (lpRect->left + lpRect->right) / 2 - 1;
401     myrect.right = myrect.left + 1;
402     myrect.top = lpRect->top + 2;
403     myrect.bottom = lpRect->bottom - 2;
404
405     newcolor = (infoPtr->clrBtnShadow == CLR_DEFAULT) ? 
406                 comctl32_color.clrBtnShadow : infoPtr->clrBtnShadow;
407     oldcolor = SetBkColor (hdc, newcolor);
408     ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
409
410     myrect.left = myrect.right;
411     myrect.right = myrect.left + 1;
412
413     newcolor = (infoPtr->clrBtnHighlight == CLR_DEFAULT) ? 
414                 comctl32_color.clrBtnHighlight : infoPtr->clrBtnHighlight;
415     SetBkColor (hdc, newcolor);
416     ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
417
418     SetBkColor (hdc, oldcolor);
419 }
420
421
422 /***********************************************************************
423 *               TOOLBAR_DrawDDFlatSeparator
424 *
425 * This function draws the separator that was flaged as TBSTYLE_DROPDOWN.
426 * In this case, the separator is a pixel high line of COLOR_BTNSHADOW,
427 * followed by a pixel high line of COLOR_BTNHIGHLIGHT. These separators
428 * are horizontal as opposed to the vertical separators for not dropdown
429 * type.
430 *
431 * FIXME: It is possible that the height of each line is really SM_CYBORDER.
432 */
433 static void
434 TOOLBAR_DrawDDFlatSeparator (LPRECT lpRect, HDC hdc, TBUTTON_INFO *btnPtr, TOOLBAR_INFO *infoPtr)
435 {
436     RECT myrect;
437     COLORREF oldcolor, newcolor;
438
439     myrect.left = lpRect->left;
440     myrect.right = lpRect->right;
441     myrect.top = lpRect->top + (lpRect->bottom - lpRect->top - 2)/2;
442     myrect.bottom = myrect.top + 1;
443
444     InflateRect (&myrect, -2, 0);
445
446     TRACE("rect=(%d,%d)-(%d,%d)\n",
447           myrect.left, myrect.top, myrect.right, myrect.bottom);
448
449     newcolor = (infoPtr->clrBtnShadow == CLR_DEFAULT) ? 
450                 comctl32_color.clrBtnShadow : infoPtr->clrBtnShadow;
451     oldcolor = SetBkColor (hdc, newcolor);
452     ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
453
454     myrect.top = myrect.bottom;
455     myrect.bottom = myrect.top + 1;
456
457     newcolor = (infoPtr->clrBtnHighlight == CLR_DEFAULT) ? 
458                 comctl32_color.clrBtnHighlight : infoPtr->clrBtnHighlight;
459     SetBkColor (hdc, newcolor);
460     ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
461
462     SetBkColor (hdc, oldcolor);
463 }
464
465
466 static void
467 TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, INT colorRef)
468 {
469     INT x, y;
470     SelectObject ( hdc, GetSysColorPen (colorRef));
471     x = left + 2;
472     y = top + 8;
473     MoveToEx (hdc, x, y, NULL);
474     LineTo (hdc, x+5, y++); x++;
475     MoveToEx (hdc, x, y, NULL);
476     LineTo (hdc, x+3, y++); x++;
477     MoveToEx (hdc, x, y, NULL);
478     LineTo (hdc, x+1, y++);
479 }
480
481 /*
482  * Draw the text string for this button.
483  * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
484  *      is non-zero, so we can simply check himlDef to see if we have
485  *      an image list
486  */
487 static void
488 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
489                     HDC hdc, INT nState, DWORD dwStyle,
490                     RECT *rcText, LPWSTR lpText, NMTBCUSTOMDRAW *tbcd)
491 {
492     HFONT  hOldFont = 0;
493     COLORREF clrOld = 0;
494
495     /* draw text */
496     if (lpText) {
497         TRACE("string rect=(%d,%d)-(%d,%d)\n",
498               rcText->left, rcText->top, rcText->right, rcText->bottom);
499
500         hOldFont = SelectObject (hdc, infoPtr->hFont);
501         if (!(nState & TBSTATE_ENABLED)) {
502             clrOld = SetTextColor (hdc, tbcd->clrBtnHighlight);
503             OffsetRect (rcText, 1, 1);
504             DrawTextW (hdc, lpText, -1, rcText, infoPtr->dwDTFlags);
505             SetTextColor (hdc, comctl32_color.clr3dShadow);
506             OffsetRect (rcText, -1, -1);
507         }
508         else if (nState & TBSTATE_INDETERMINATE) {
509             clrOld = SetTextColor (hdc, comctl32_color.clr3dShadow);
510         }
511         else if (btnPtr->bHot && (infoPtr->dwItemCDFlag & TBCDRF_HILITEHOTTRACK )) {
512             clrOld = SetTextColor (hdc, tbcd->clrTextHighlight);
513         }
514         else {
515             clrOld = SetTextColor (hdc, tbcd->clrText);
516         }
517
518         DrawTextW (hdc, lpText, -1, rcText, infoPtr->dwDTFlags);
519         SetTextColor (hdc, clrOld);
520         SelectObject (hdc, hOldFont);
521     }
522 }
523
524
525 static void
526 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
527 {
528     HBRUSH hbr = SelectObject (hdc, COMCTL32_hPattern55AABrush);
529     INT cx = lpRect->right - lpRect->left;
530     INT cy = lpRect->bottom - lpRect->top;
531     PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
532     SelectObject (hdc, hbr);
533 }
534
535
536 static void
537 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
538                     HDC hdc, INT x, INT y)
539 {
540     /* FIXME: this function is a hack since it uses image list
541               internals directly */
542
543     HIMAGELIST himl = infoPtr->himlDef;
544     HBITMAP hbmMask;
545     HDC hdcImageList;
546     HDC hdcMask;
547
548     if (!himl)
549         return;
550
551     /* create new dc's */
552     hdcImageList = CreateCompatibleDC (0);
553     hdcMask = CreateCompatibleDC (0);
554
555     /* create new bitmap */
556     hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
557     SelectObject (hdcMask, hbmMask);
558
559     /* copy the mask bitmap */
560     SelectObject (hdcImageList, himl->hbmMask);
561     SetBkColor (hdcImageList, RGB(255, 255, 255));
562     SetTextColor (hdcImageList, RGB(0, 0, 0));
563     BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
564               hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
565
566     /* draw the new mask */
567     SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
568     BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
569               hdcMask, 0, 0, 0xB8074A);
570
571     SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
572     BitBlt (hdc, x, y, himl->cx, himl->cy,
573               hdcMask, 0, 0, 0xB8074A);
574
575     DeleteObject (hbmMask);
576     DeleteDC (hdcMask);
577     DeleteDC (hdcImageList);
578 }
579
580
581 static UINT
582 TOOLBAR_TranslateState(TBUTTON_INFO *btnPtr)
583 {
584     UINT retstate = 0;
585
586     retstate |= (btnPtr->fsState & TBSTATE_CHECKED) ? CDIS_CHECKED  : 0;
587     retstate |= (btnPtr->fsState & TBSTATE_PRESSED) ? CDIS_SELECTED : 0;
588     retstate |= (btnPtr->fsState & TBSTATE_ENABLED) ? 0 : CDIS_DISABLED;
589     retstate |= (btnPtr->fsState & TBSTATE_MARKED ) ? CDIS_MARKED   : 0;
590     retstate |= (btnPtr->bHot                     ) ? CDIS_HOT      : 0;
591     retstate |= (btnPtr->fsState & TBSTATE_INDETERMINATE) ? CDIS_INDETERMINATE : 0;
592     /* FIXME: don't set CDIS_GRAYED, CDIS_FOCUS, CDIS_DEFAULT       */
593     /*        don't test TBSTATE_HIDDEN                             */
594     return retstate;
595 }
596
597
598 static void
599 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
600 {
601     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
602     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
603     BOOL hasDropDownArrow = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
604                             (btnPtr->fsStyle & TBSTYLE_DROPDOWN);
605     RECT rc, rcArrow, rcBitmap, rcText, rcFill;
606     LPWSTR lpText = NULL;
607     NMTBCUSTOMDRAW tbcd;
608     DWORD ntfret;
609     INT offset;
610
611     if (btnPtr->fsState & TBSTATE_HIDDEN)
612         return;
613
614     rc = btnPtr->rect;
615     CopyRect (&rcFill, &rc);
616     CopyRect (&rcArrow, &rc);
617     CopyRect(&rcBitmap, &rc);
618     CopyRect(&rcText, &rc);
619
620     /* get a pointer to the text */
621     lpText = TOOLBAR_GetText(infoPtr, btnPtr);
622
623     if (hasDropDownArrow)
624     {
625         if (dwStyle & TBSTYLE_FLAT)
626             rc.right = max(rc.left, rc.right - DDARROW_WIDTH);
627         else
628             rc.right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
629         rcArrow.left = rc.right; 
630     }
631
632     /* Center the bitmap horizontally and vertically */
633     if (dwStyle & TBSTYLE_LIST)
634         rcBitmap.left += 3;
635     else
636         rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;
637
638     if(lpText)
639         rcBitmap.top+=2; /* this looks to be the correct value from vmware comparison - cmm */
640     else
641         rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;
642
643     TRACE("iBitmap: %d, start=(%d,%d) w=%d, h=%d\n", 
644           btnPtr->iBitmap, rcBitmap.left, rcBitmap.top,
645           infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
646     TRACE ("iString: %x\n", btnPtr->iString);
647     TRACE ("Stringtext: %s\n", debugstr_w(lpText));
648
649     /* draw text */
650     if (lpText) {
651
652         InflateRect (&rcText, -3, -3);
653
654         if (infoPtr->himlDef && 
655             TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
656                 /* The following test looked like this before
657                  * I changed it. IE4 "Links" toolbar would not
658                  * draw correctly with the original code.  - GA 8/01
659                  *   ((dwStyle & TBSTYLE_LIST) &&
660                  *    ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
661                  *       (btnPtr->iBitmap != I_IMAGENONE))
662                  */ 
663                 if (dwStyle & TBSTYLE_LIST) {
664                     /* LIST style w/ ICON offset is by matching native. */
665                     /* Matches IE4 "Links" bar.   - GA 8/01             */
666                     rcText.left += (infoPtr->nBitmapWidth + 2);
667                 }
668                 else {
669                     rcText.top += infoPtr->nBitmapHeight + 1;
670                 }
671         }
672         else {
673                 if (dwStyle & TBSTYLE_LIST) {
674                     /* LIST style w/o ICON offset is by matching native. */
675                     /* Matches IE4 "menu" bar.   - GA  8/01              */
676                     rcText.left += 4;
677                 }
678         }
679
680         if (btnPtr->fsState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
681             OffsetRect (&rcText, 1, 1);
682     }
683
684     /* Initialize fields in all cases, because we use these later */
685     ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
686     tbcd.clrText = comctl32_color.clrBtnText;
687     tbcd.clrTextHighlight = comctl32_color.clrHighlightText;
688     tbcd.clrBtnFace = comctl32_color.clrBtnFace;
689     tbcd.clrBtnHighlight = comctl32_color.clrBtnHighlight;
690     tbcd.clrMark = comctl32_color.clrHighlight;
691     tbcd.clrHighlightHotTrack = 0;
692     tbcd.nStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE;
693     tbcd.nHLStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE;
694     /* MSDN says that this is the text rectangle.              */
695     /* But (why always a but) tracing of v5.7 of native shows  */
696     /* that this is really a *relative* rectangle based on the */
697     /* the nmcd.rc. Also the left and top are always 0 ignoring*/
698     /* any bitmap that might be present.                       */
699     tbcd.rcText.left = 0;
700     tbcd.rcText.top = 0;
701     tbcd.rcText.right = rcText.right - rc.left;
702     tbcd.rcText.bottom = rcText.bottom - rc.top;
703
704     /* FIXME: what should these be set to ????? */
705     tbcd.hbrMonoDither = 0;
706     tbcd.hbrLines = 0;
707     tbcd.hpenLines = 0;
708
709     /* Issue Item Prepaint notify */ 
710     infoPtr->dwItemCustDraw = 0;
711     infoPtr->dwItemCDFlag = 0;
712     if (infoPtr->dwBaseCustDraw & CDRF_NOTIFYITEMDRAW)
713     {
714         tbcd.nmcd.dwDrawStage = CDDS_ITEMPREPAINT;
715         tbcd.nmcd.hdc = hdc;
716         tbcd.nmcd.rc = rc;
717         tbcd.nmcd.dwItemSpec = btnPtr->idCommand;
718         tbcd.nmcd.uItemState = TOOLBAR_TranslateState(btnPtr);
719         tbcd.nmcd.lItemlParam = btnPtr->dwData;
720         ntfret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
721         infoPtr->dwItemCustDraw = ntfret & 0xffff;
722         infoPtr->dwItemCDFlag = ntfret & 0xffff0000;
723         if (infoPtr->dwItemCustDraw & CDRF_SKIPDEFAULT) 
724             return;
725         /* save the only part of the rect that the user can change */
726         rcText.right = tbcd.rcText.right + rc.left;
727         rcText.bottom = tbcd.rcText.bottom + rc.top;
728     }
729
730     if (!infoPtr->bBtnTranspnt)
731         FillRect( hdc, &rcFill, GetSysColorBrush(COLOR_BTNFACE));
732
733     /* separator */
734     if (btnPtr->fsStyle & TBSTYLE_SEP) {
735         /* with the FLAT style, iBitmap is the width and has already */
736         /* been taken into consideration in calculating the width    */
737         /* so now we need to draw the vertical separator             */
738         /* empirical tests show that iBitmap can/will be non-zero    */
739         /* when drawing the vertical bar...      */
740         if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */) {
741             if (btnPtr->fsStyle & TBSTYLE_DROPDOWN)
742                 TOOLBAR_DrawDDFlatSeparator (&rc, hdc, btnPtr, infoPtr);
743             else
744                 TOOLBAR_DrawFlatSeparator (&rc, hdc, infoPtr);
745         }
746         else if (btnPtr->fsStyle != TBSTYLE_SEP) {
747             FIXME("Draw some kind of separator: fsStyle=%x\n",
748                   btnPtr->fsStyle);
749         }
750         goto FINALNOTIFY;
751     }
752
753     /* disabled */
754     if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
755         if (!(dwStyle & TBSTYLE_FLAT) && !(infoPtr->dwItemCDFlag & TBCDRF_NOEDGES))
756         {
757             DrawEdge (hdc, &rc, EDGE_RAISED,
758                       BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
759             if (hasDropDownArrow)
760             DrawEdge (hdc, &rcArrow, EDGE_RAISED,
761                       BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
762         }
763         
764         if (hasDropDownArrow)
765         {
766             TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1, COLOR_3DHIGHLIGHT);
767             TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_3DSHADOW);
768         }
769
770         if (!TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDis,
771                                    hdc, rcBitmap.left, rcBitmap.top, 
772                                    ILD_NORMAL))
773             TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
774
775         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle, &rcText, lpText, &tbcd);
776         goto FINALNOTIFY;
777     }
778
779     /* pressed TBSTYLE_BUTTON */
780     if (btnPtr->fsState & TBSTATE_PRESSED) {
781         offset = (infoPtr->dwItemCDFlag & TBCDRF_NOOFFSET) ? 0 : 1;
782         if (!(infoPtr->dwItemCDFlag & TBCDRF_NOEDGES))
783         {
784             if (dwStyle & TBSTYLE_FLAT)
785             {
786                 DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
787                 if (hasDropDownArrow)
788                     DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
789             }
790             else
791             {
792                 DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
793                 if (hasDropDownArrow)
794                     DrawEdge (hdc, &rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
795             }
796         }
797
798         if (hasDropDownArrow)
799             TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
800
801         TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
802                                hdc, rcBitmap.left+offset, rcBitmap.top+offset, 
803                                ILD_NORMAL);
804
805         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle, &rcText, lpText, &tbcd);
806         goto FINALNOTIFY;
807     }
808
809     /* checked TBSTYLE_CHECK */
810     if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
811         (btnPtr->fsState & TBSTATE_CHECKED)) {
812         if (!(infoPtr->dwItemCDFlag & TBCDRF_NOEDGES))
813         {
814             if (dwStyle & TBSTYLE_FLAT)
815                 DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
816                           BF_RECT | BF_ADJUST);
817             else
818                 DrawEdge (hdc, &rc, EDGE_SUNKEN,
819                           BF_RECT | BF_MIDDLE | BF_ADJUST);
820         }
821
822         TOOLBAR_DrawPattern (hdc, &rc);
823         
824         TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
825                                hdc, rcBitmap.left+1, rcBitmap.top+1, 
826                                ILD_NORMAL);
827
828         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle, &rcText, lpText, &tbcd);
829         goto FINALNOTIFY;
830     }
831
832     /* indeterminate */ 
833     if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
834         if (!(infoPtr->dwItemCDFlag & TBCDRF_NOEDGES))
835             DrawEdge (hdc, &rc, EDGE_RAISED,
836                       BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
837
838         TOOLBAR_DrawPattern (hdc, &rc);
839         TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
840         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle, &rcText, lpText, &tbcd);
841         goto FINALNOTIFY;
842     }
843
844     /* normal state */
845     if (dwStyle & TBSTYLE_FLAT)
846     {
847         if (btnPtr->bHot)
848         {
849             if ( infoPtr->dwItemCDFlag & TBCDRF_HILITEHOTTRACK )
850             {
851                 COLORREF oldclr;
852
853                 oldclr = SetBkColor(hdc, tbcd.clrHighlightHotTrack);
854                 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, 0);
855                 if (hasDropDownArrow)
856                     ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rcArrow, NULL, 0, 0);
857                 SetBkColor(hdc, oldclr);
858             }
859             else
860             {
861                 if (!(infoPtr->dwItemCDFlag & TBCDRF_NOEDGES))
862                 {
863                     DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT);
864                     if (hasDropDownArrow)
865                         DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT);
866                 }
867             }
868         }
869 #if 1
870         else /* The following code needs to be removed after
871               * "hot item" support has been implemented for the
872               * case where it is being de-selected.
873               */
874         {
875             FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
876             if (hasDropDownArrow)
877             FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
878         }
879 #endif
880
881         if (hasDropDownArrow)
882             TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
883
884         if (btnPtr->bHot) {
885             /* if hot, attempt to draw with himlHot, if fails, use himlDef */
886             if (!TOOLBAR_DrawImageList (infoPtr, btnPtr, 
887                                         infoPtr->himlHot,
888                                         hdc, rcBitmap.left, 
889                                         rcBitmap.top, ILD_NORMAL))
890                 TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
891                                        hdc, rcBitmap.left, rcBitmap.top,
892                                        ILD_NORMAL);
893         }
894         else
895             TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
896                                    hdc, rcBitmap.left, rcBitmap.top,
897                                    ILD_NORMAL);
898     }
899     else
900     {
901         if (!(infoPtr->dwItemCDFlag & TBCDRF_NOEDGES))
902             DrawEdge (hdc, &rc, EDGE_RAISED,
903                       BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
904
905         if (hasDropDownArrow)
906         {
907             if (!(infoPtr->dwItemCDFlag & TBCDRF_NOEDGES))
908                 DrawEdge (hdc, &rcArrow, EDGE_RAISED,
909                           BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
910             TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
911         }
912
913         TOOLBAR_DrawImageList (infoPtr, btnPtr, infoPtr->himlDef,
914                                hdc, rcBitmap.left, rcBitmap.top,
915                                ILD_NORMAL);}
916     
917
918     TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle, &rcText, lpText, &tbcd);
919
920  FINALNOTIFY:
921     if (infoPtr->dwItemCustDraw & CDRF_NOTIFYPOSTPAINT)
922     {
923         tbcd.nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;
924         tbcd.nmcd.hdc = hdc;
925         tbcd.nmcd.rc = rc;
926         tbcd.nmcd.dwItemSpec = btnPtr->idCommand;
927         tbcd.nmcd.uItemState = TOOLBAR_TranslateState(btnPtr);
928         tbcd.nmcd.lItemlParam = btnPtr->dwData;
929         tbcd.rcText = rcText;
930         tbcd.nStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE;
931         tbcd.nHLStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE;
932         ntfret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
933     }
934
935 }
936
937
938 static void
939 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
940 {
941     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
942     TBUTTON_INFO *btnPtr;
943     INT i, oldBKmode = 0;
944     RECT rcTemp;
945     NMTBCUSTOMDRAW tbcd;
946     DWORD ntfret;
947
948     /* if imagelist belongs to the app, it can be changed
949        by the app after setting it */
950     if (infoPtr->himlDef != infoPtr->himlInt)
951         infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
952
953     TOOLBAR_DumpToolbar (infoPtr, __LINE__);
954
955     /* Send initial notify */
956     ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
957     tbcd.nmcd.dwDrawStage = CDDS_PREPAINT;
958     tbcd.nmcd.hdc = hdc;
959     tbcd.nmcd.rc = ps->rcPaint;
960     ntfret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
961     infoPtr->dwBaseCustDraw = ntfret & 0xffff;
962
963     if (infoPtr->bBtnTranspnt)
964         oldBKmode = SetBkMode (hdc, TRANSPARENT);
965
966     /* redraw necessary buttons */
967     btnPtr = infoPtr->buttons;
968     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
969     {
970         if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
971             TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
972     }
973
974     if (infoPtr->bBtnTranspnt && (oldBKmode != TRANSPARENT))
975         SetBkMode (hdc, oldBKmode);
976
977     if (infoPtr->dwBaseCustDraw & CDRF_NOTIFYPOSTPAINT)
978     {
979         ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
980         tbcd.nmcd.dwDrawStage = CDDS_POSTPAINT;
981         tbcd.nmcd.hdc = hdc;
982         tbcd.nmcd.rc = ps->rcPaint;
983         ntfret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
984     }
985 }
986
987 /***********************************************************************
988 *               TOOLBAR_MeasureString
989 *
990 * This function gets the width and height of a string in pixels. This
991 * is done first by using GetTextExtentPoint to get the basic width
992 * and height. The DrawText is called with DT_CALCRECT to get the exact
993 * width. The reason is because the text may have more than one "&" (or
994 * prefix characters as M$ likes to call them). The prefix character
995 * indicates where the underline goes, except for the string "&&" which
996 * is reduced to a single "&". GetTextExtentPoint does not process these
997 * only DrawText does. Note that the TBSTYLE_NOPREFIX is handled here.
998 */
999 static void
1000 TOOLBAR_MeasureString(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, 
1001                       HDC hdc, LPSIZE lpSize)
1002 {
1003     RECT myrect;
1004
1005     lpSize->cx = 0;
1006     lpSize->cy = 0;
1007
1008     if (!(btnPtr->fsState & TBSTATE_HIDDEN) ) 
1009     {
1010         LPWSTR lpText = TOOLBAR_GetText(infoPtr, btnPtr);
1011
1012         if(lpText != NULL) {
1013             /* first get size of all the text */
1014             GetTextExtentPoint32W (hdc, lpText, strlenW (lpText), lpSize);
1015
1016             /* feed above size into the rectangle for DrawText */
1017             myrect.left = myrect.top = 0;
1018             myrect.right = lpSize->cx;
1019             myrect.bottom = lpSize->cy;
1020
1021             /* Use DrawText to get true size as drawn (less pesky "&") */
1022             DrawTextW (hdc, lpText, -1, &myrect, DT_VCENTER | DT_SINGLELINE |
1023                    DT_CALCRECT | ((btnPtr->fsStyle & TBSTYLE_NOPREFIX) ?
1024                                   DT_NOPREFIX : 0));
1025
1026             /* feed back to caller  */
1027             lpSize->cx = myrect.right;
1028             lpSize->cy = myrect.bottom;
1029         }
1030     }
1031
1032     TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
1033 }
1034
1035 /***********************************************************************
1036 *               TOOLBAR_CalcStrings
1037 *
1038 * This function walks through each string and measures it and returns
1039 * the largest height and width to caller.
1040 */
1041 static void
1042 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
1043 {
1044     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1045     TBUTTON_INFO *btnPtr;
1046     INT i;
1047     SIZE sz;
1048     HDC hdc;
1049     HFONT hOldFont;
1050
1051     lpSize->cx = 0;
1052     lpSize->cy = 0;
1053
1054     hdc = GetDC (hwnd);
1055     hOldFont = SelectObject (hdc, infoPtr->hFont);
1056
1057     btnPtr = infoPtr->buttons;
1058     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
1059         if(TOOLBAR_HasText(infoPtr, btnPtr))
1060         {
1061             TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz);
1062             if (sz.cx > lpSize->cx)
1063                 lpSize->cx = sz.cx;
1064             if (sz.cy > lpSize->cy)
1065                 lpSize->cy = sz.cy;
1066         }
1067     }
1068
1069     SelectObject (hdc, hOldFont);
1070     ReleaseDC (hwnd, hdc);
1071
1072     TRACE("max string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
1073 }
1074
1075 /***********************************************************************
1076 *               TOOLBAR_WrapToolbar
1077 *
1078 * This function walks through the buttons and seperators in the 
1079 * toolbar, and sets the TBSTATE_WRAP flag only on those items where 
1080 * wrapping should occur based on the width of the toolbar window.  
1081 * It does *not* calculate button placement itself.  That task 
1082 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage 
1083 * the toolbar wrapping on its own, it can use the TBSTYLE_WRAPABLE 
1084 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
1085 *
1086 * Note: TBSTYLE_WRAPABLE or TBSTYLE_EX_UNDOC1 can be used also to allow 
1087 * vertical toolbar lists. 
1088 */ 
1089
1090 static void
1091 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
1092 {
1093     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1094     TBUTTON_INFO *btnPtr;
1095     INT x, cx, i, j;
1096     RECT rc;
1097     BOOL bWrap, bButtonWrap;
1098
1099     /*  When the toolbar window style is not TBSTYLE_WRAPABLE,  */ 
1100     /*  no layout is necessary. Applications may use this style */
1101     /*  to perform their own layout on the toolbar.             */
1102     if( !(dwStyle & TBSTYLE_WRAPABLE) && 
1103         !(infoPtr->dwExStyle & TBSTYLE_EX_UNDOC1) )  return;
1104
1105     btnPtr = infoPtr->buttons;
1106     x  = infoPtr->nIndent;
1107
1108     /* this can get the parents width, to know how far we can extend
1109      * this toolbar.  We cannot use its height, as there may be multiple
1110      * toolbars in a rebar control
1111      */
1112     GetClientRect( GetParent(hwnd), &rc );
1113     infoPtr->nWidth = rc.right - rc.left;
1114     bButtonWrap = FALSE;
1115
1116     TRACE("start ButtonWidth=%d, BitmapWidth=%d, nWidth=%d, nIndent=%d\n",
1117           infoPtr->nButtonWidth, infoPtr->nBitmapWidth, infoPtr->nWidth,
1118           infoPtr->nIndent);
1119
1120     for (i = 0; i < infoPtr->nNumButtons; i++ )
1121     {
1122         bWrap = FALSE;
1123         btnPtr[i].fsState &= ~TBSTATE_WRAP;
1124         
1125         if (btnPtr[i].fsState & TBSTATE_HIDDEN)
1126             continue;
1127
1128         /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1129         /* it is the actual width of the separator. This is used for */
1130         /* custom controls in toolbars.                              */
1131         /*                                                           */
1132         /* TBSTYLE_DROPDOWN separators are treated as buttons for    */
1133         /* width.  - GA 8/01                                         */
1134         if ((btnPtr[i].fsStyle & TBSTYLE_SEP) &&
1135             !(btnPtr[i].fsStyle & TBSTYLE_DROPDOWN))
1136             cx = (btnPtr[i].iBitmap > 0) ?  
1137                         btnPtr[i].iBitmap : SEPARATOR_WIDTH;
1138         else
1139             cx = infoPtr->nButtonWidth;
1140
1141         /* Two or more adjacent separators form a separator group.   */ 
1142         /* The first separator in a group should be wrapped to the   */
1143         /* next row if the previous wrapping is on a button.         */
1144         if( bButtonWrap &&
1145                 (btnPtr[i].fsStyle & TBSTYLE_SEP) && 
1146                 (i + 1 < infoPtr->nNumButtons ) &&
1147                 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) ) 
1148         {
1149             TRACE("wrap point 1 btn %d style %02x\n", i, btnPtr[i].fsStyle);
1150             btnPtr[i].fsState |= TBSTATE_WRAP;
1151             x = infoPtr->nIndent;
1152             i++;
1153             bButtonWrap = FALSE;
1154             continue;
1155         }
1156
1157         /* The layout makes sure the bitmap is visible, but not the button. */
1158         /* Test added to also wrap after a button that starts a row but     */
1159         /* is bigger than the area.  - GA  8/01                             */
1160         if (( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2 
1161            > infoPtr->nWidth ) ||
1162             ((x == infoPtr->nIndent) && (cx > infoPtr->nWidth)))
1163         {
1164             BOOL bFound = FALSE;
1165
1166             /*  If the current button is a separator and not hidden,  */ 
1167             /*  go to the next until it reaches a non separator.      */
1168             /*  Wrap the last separator if it is before a button.     */
1169             while( ( ((btnPtr[i].fsStyle & TBSTYLE_SEP) &&
1170                       !(btnPtr[i].fsStyle & TBSTYLE_DROPDOWN)) || 
1171                      (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
1172                         i < infoPtr->nNumButtons )
1173             {
1174                 i++;
1175                 bFound = TRUE;
1176             }
1177     
1178             if( bFound && i < infoPtr->nNumButtons )
1179             {
1180                 i--;
1181                 TRACE("wrap point 2 btn %d style %02x, x=%d, cx=%d\n", 
1182                       i, btnPtr[i].fsStyle, x, cx);
1183                 btnPtr[i].fsState |= TBSTATE_WRAP;
1184                 x = infoPtr->nIndent;
1185                 bButtonWrap = FALSE;
1186                 continue;
1187             }
1188             else if ( i >= infoPtr->nNumButtons)
1189                 break;
1190
1191             /*  If the current button is not a separator, find the last  */ 
1192             /*  separator and wrap it.                                   */
1193             for ( j = i - 1; j >= 0  &&  !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
1194             {
1195                 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
1196                         !(btnPtr[j].fsState & TBSTATE_HIDDEN))
1197                 {
1198                     bFound = TRUE; 
1199                     i = j; 
1200                     TRACE("wrap point 3 btn %d style %02x, x=%d, cx=%d\n", 
1201                           i, btnPtr[i].fsStyle, x, cx);
1202                     x = infoPtr->nIndent;
1203                     btnPtr[j].fsState |= TBSTATE_WRAP;
1204                     bButtonWrap = FALSE; 
1205                     break;
1206                 }
1207             }
1208
1209             /*  If no separator available for wrapping, wrap one of     */
1210             /*  non-hidden previous button.                             */
1211             if (!bFound)
1212             {
1213                 for ( j = i - 1; 
1214                         j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
1215                 {
1216                     if (btnPtr[j].fsState & TBSTATE_HIDDEN) 
1217                         continue;
1218
1219                     bFound = TRUE; 
1220                     i = j; 
1221                     TRACE("wrap point 4 btn %d style %02x, x=%d, cx=%d\n", 
1222                           i, btnPtr[i].fsStyle, x, cx);
1223                     x = infoPtr->nIndent;
1224                     btnPtr[j].fsState |= TBSTATE_WRAP;
1225                     bButtonWrap = TRUE;
1226                     break;
1227                 }
1228             }
1229
1230             /* If all above failed, wrap the current button. */
1231             if (!bFound)  
1232             {
1233                 TRACE("wrap point 5 btn %d style %02x, x=%d, cx=%d\n",
1234                       i, btnPtr[i].fsStyle, x, cx);
1235                 btnPtr[i].fsState |= TBSTATE_WRAP;
1236                 bFound = TRUE;
1237                 x = infoPtr->nIndent;
1238                 if (btnPtr[i].fsStyle & TBSTYLE_SEP )
1239                     bButtonWrap = FALSE;
1240                 else
1241                     bButtonWrap = TRUE;
1242             }               
1243         }
1244         else {
1245             TRACE("wrap point 6 btn %d style %02x, x=%d, cx=%d\n", 
1246                   i, btnPtr[i].fsStyle, x, cx);
1247             x += cx;
1248         }
1249     }
1250 }
1251
1252
1253 /***********************************************************************
1254 *               TOOLBAR_CalcToolbar
1255 *
1256 * This function calculates button and separator placement. It first 
1257 * calculates the button sizes, gets the toolbar window width and then 
1258 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap 
1259 * on. It assigns a new location to each item and sends this location to
1260 * the tooltip window if appropriate. Finally, it updates the rcBound 
1261 * rect and calculates the new required toolbar window height. 
1262 */  
1263
1264 static void
1265 TOOLBAR_CalcToolbar (HWND hwnd)
1266 {
1267     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
1268     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1269     TBUTTON_INFO *btnPtr;
1270     INT i, nRows, nSepRows;
1271     INT x, y, cx, cy;
1272     SIZE  sizeString;
1273     BOOL bWrap;
1274     BOOL usesBitmaps = FALSE;
1275     BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
1276
1277     TOOLBAR_CalcStrings (hwnd, &sizeString);
1278
1279     for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
1280     {
1281         if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
1282             usesBitmaps = TRUE;
1283     }
1284     if (dwStyle & TBSTYLE_LIST)
1285     {
1286         infoPtr->nButtonHeight = max((usesBitmaps) ? infoPtr->nBitmapHeight :
1287                                      0, sizeString.cy) + infoPtr->szPadding.cy;
1288         infoPtr->nButtonWidth = ((usesBitmaps) ? infoPtr->nBitmapWidth :
1289                                  0) + sizeString.cx + 6;
1290         TRACE("LIST style, But w=%d h=%d, useBitmaps=%d, Bit w=%d h=%d\n",
1291               infoPtr->nButtonWidth, infoPtr->nButtonHeight, usesBitmaps,
1292               infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
1293         TOOLBAR_DumpToolbar (infoPtr, __LINE__);
1294     }
1295     else {
1296         if (sizeString.cy > 0)
1297         {
1298             if (usesBitmaps)
1299                 infoPtr->nButtonHeight = sizeString.cy + 
1300                     2 + /* this is the space to separate text from bitmap */
1301                   infoPtr->nBitmapHeight + 6;
1302             else 
1303                 infoPtr->nButtonHeight = sizeString.cy + 6;
1304         }
1305         else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
1306             infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
1307
1308         if (sizeString.cx > infoPtr->nBitmapWidth)
1309             infoPtr->nButtonWidth = sizeString.cx + 6;
1310         else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
1311             infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
1312     }
1313
1314     if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
1315         infoPtr->nButtonWidth = infoPtr->cxMin;
1316     if ( infoPtr->cxMax > 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
1317         infoPtr->nButtonWidth = infoPtr->cxMax;
1318
1319     TOOLBAR_WrapToolbar( hwnd, dwStyle );
1320
1321     x  = infoPtr->nIndent;
1322     y  = 0;
1323
1324    /*
1325     * We will set the height below, and we set the width on entry 
1326     * so we do not reset them here.. 
1327     */
1328 #if 0
1329     GetClientRect( hwnd, &rc );
1330     /* get initial values for toolbar */
1331     infoPtr->nWidth  = rc.right - rc.left;
1332     infoPtr->nHeight = rc.bottom - rc.top;
1333 #endif
1334
1335     /* from above, minimum is a button, and possible text */
1336     cx = infoPtr->nButtonWidth;
1337
1338     /* cannot use just ButtonHeight, we may have no buttons! */
1339     if (infoPtr->nNumButtons > 0)
1340         infoPtr->nHeight = infoPtr->nButtonHeight;
1341
1342     cy = infoPtr->nHeight;
1343
1344     nRows = nSepRows = 0;
1345
1346     infoPtr->rcBound.top = y;
1347     infoPtr->rcBound.left = x;
1348     infoPtr->rcBound.bottom = y + cy;
1349     infoPtr->rcBound.right = x;
1350
1351     btnPtr = infoPtr->buttons;
1352
1353     /* do not base height/width on parent, if the parent is a */
1354     /* rebar control it could have multiple rows of toolbars  */
1355 /*    GetClientRect( GetParent(hwnd), &rc ); */
1356 /*    cx = rc.right - rc.left; */
1357 /*    cy = rc.bottom - rc.top; */
1358
1359     TRACE("cy=%d\n", cy);
1360
1361     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
1362     {
1363         bWrap = FALSE;
1364         if (btnPtr->fsState & TBSTATE_HIDDEN)
1365         {
1366             SetRectEmpty (&btnPtr->rect);
1367             continue;
1368         }
1369
1370         cy = infoPtr->nHeight;
1371
1372         /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1373         /* it is the actual width of the separator. This is used for */
1374         /* custom controls in toolbars.                              */
1375         if (btnPtr->fsStyle & TBSTYLE_SEP) {
1376             if (btnPtr->fsStyle & TBSTYLE_DROPDOWN) {
1377                 cy = (btnPtr->iBitmap > 0) ?
1378                      btnPtr->iBitmap : SEPARATOR_WIDTH;
1379                 cx = infoPtr->nButtonWidth;
1380             }
1381             else
1382                 cx = (btnPtr->iBitmap > 0) ?
1383                      btnPtr->iBitmap : SEPARATOR_WIDTH;
1384         }
1385         else
1386         {
1387             if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE) 
1388             {
1389               SIZE sz;
1390               HDC hdc;
1391               HFONT hOldFont;
1392
1393               hdc = GetDC (hwnd);
1394               hOldFont = SelectObject (hdc, infoPtr->hFont);
1395
1396               TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz);
1397
1398               SelectObject (hdc, hOldFont);
1399               ReleaseDC (hwnd, hdc);
1400
1401               /* Fudge amount measured against IE4 "menu" and "Links" */
1402               /* toolbars with native control (v4.71).  -  GA 8/01    */
1403               cx = sz.cx + 6 + 5 + 5;
1404               if ((dwStyle & TBSTYLE_LIST) && 
1405                   (TOOLBAR_TestImageExist (infoPtr, btnPtr, infoPtr->himlDef)))
1406                   cx += infoPtr->nBitmapWidth;
1407             }
1408             else
1409               cx = infoPtr->nButtonWidth;
1410
1411             if (hasDropDownArrows && (btnPtr->fsStyle & TBSTYLE_DROPDOWN))
1412               cx += DDARROW_WIDTH; 
1413         }
1414         if (btnPtr->fsState & TBSTATE_WRAP )
1415                     bWrap = TRUE;
1416
1417         SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
1418
1419         if (infoPtr->rcBound.left > x)
1420             infoPtr->rcBound.left = x;
1421         if (infoPtr->rcBound.right < x + cx)
1422             infoPtr->rcBound.right = x + cx;
1423         if (infoPtr->rcBound.bottom < y + cy)
1424             infoPtr->rcBound.bottom = y + cy;
1425
1426         /* Set the toolTip only for non-hidden, non-separator button */
1427         if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP )) 
1428         {
1429             TTTOOLINFOA ti;
1430
1431             ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1432             ti.cbSize = sizeof(TTTOOLINFOA);
1433             ti.hwnd = hwnd;
1434             ti.uId = btnPtr->idCommand;
1435             ti.rect = btnPtr->rect;
1436             SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
1437                             0, (LPARAM)&ti);
1438         }
1439
1440         /* btnPtr->nRow is zero based. The space between the rows is    */
1441         /* also considered as a row.                                    */
1442         btnPtr->nRow = nRows + nSepRows;
1443
1444         TRACE("button %d style=%x, bWrap=%d, nRows=%d, nSepRows=%d, btnrow=%d, (%d,%d)-(%d,%d)\n",
1445               i, btnPtr->fsStyle, bWrap, nRows, nSepRows, btnPtr->nRow,
1446               x, y, x+cx, y+cy);
1447
1448         if( bWrap )
1449         {
1450             if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
1451                 y += cy;
1452             else 
1453             {   
1454                 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
1455                 /* it is the actual width of the separator. This is used for */
1456                 /* custom controls in toolbars.                              */
1457                 if ( !(btnPtr->fsStyle & TBSTYLE_DROPDOWN))
1458                     y += cy + ( (btnPtr->iBitmap > 0 ) ?
1459                                 btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3; 
1460                 else
1461                     y += cy;
1462              
1463                 /* nSepRows is used to calculate the extra height follwoing  */
1464                 /* the last row.                                             */
1465                 nSepRows++;
1466             }
1467             x = infoPtr->nIndent;
1468
1469             /* Increment row number unless this is the last button    */
1470             /* and it has Wrap set.                                   */
1471             if (i != infoPtr->nNumButtons-1)
1472                 nRows++;
1473         }
1474         else
1475             x += cx;
1476     }
1477
1478     /* infoPtr->nRows is the number of rows on the toolbar */
1479     infoPtr->nRows = nRows + nSepRows + 1;
1480
1481 #if 0
1482     /********************************************************************
1483      * The following while interesting, does not match the values       *
1484      * created above for the button rectangles, nor the rcBound rect.   *
1485      * We will comment it out and remove it later.                      *
1486      *                                                                  *
1487      * The problem showed up as heights in the pager control that was   *
1488      * wrong.                                                           *
1489      ********************************************************************/
1490
1491     /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following   */
1492     /* the last row.                                                    */
1493     infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight + 
1494                         nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
1495                         nSepRows * (infoPtr->nBitmapHeight + 1) + 
1496                         BOTTOM_BORDER; 
1497 #endif
1498
1499     infoPtr->nHeight = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
1500
1501     TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
1502 }
1503
1504
1505 static INT
1506 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
1507 {
1508     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1509     TBUTTON_INFO *btnPtr;
1510     INT i;
1511     
1512     btnPtr = infoPtr->buttons;
1513     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
1514         if (btnPtr->fsState & TBSTATE_HIDDEN)
1515             continue;
1516
1517         if (btnPtr->fsStyle & TBSTYLE_SEP) {
1518             if (PtInRect (&btnPtr->rect, *lpPt)) {
1519                 TRACE(" ON SEPARATOR %d!\n", i);
1520                 return -i;
1521             }
1522         }
1523         else {
1524             if (PtInRect (&btnPtr->rect, *lpPt)) {
1525                 TRACE(" ON BUTTON %d!\n", i);
1526                 return i;
1527             }
1528         }
1529     }
1530
1531     TRACE(" NOWHERE!\n");
1532     return -1;
1533 }
1534
1535
1536 static INT
1537 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand, BOOL CommandIsIndex)
1538 {
1539     TBUTTON_INFO *btnPtr;
1540     INT i;
1541
1542     if (CommandIsIndex) {
1543         TRACE("command is really index command=%d\n", idCommand);
1544         if (idCommand >= infoPtr->nNumButtons) return -1;
1545         return idCommand;
1546     }
1547     btnPtr = infoPtr->buttons;
1548     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
1549         if (btnPtr->idCommand == idCommand) {
1550             TRACE("command=%d index=%d\n", idCommand, i);
1551             return i;
1552         }
1553     }
1554     TRACE("no index found for command=%d\n", idCommand);
1555     return -1;
1556 }
1557
1558
1559 static INT
1560 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
1561 {
1562     TBUTTON_INFO *btnPtr;
1563     INT nRunIndex;
1564
1565     if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
1566         return -1;
1567
1568     /* check index button */
1569     btnPtr = &infoPtr->buttons[nIndex];
1570     if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1571         if (btnPtr->fsState & TBSTATE_CHECKED)
1572             return nIndex;
1573     }
1574
1575     /* check previous buttons */
1576     nRunIndex = nIndex - 1;
1577     while (nRunIndex >= 0) {
1578         btnPtr = &infoPtr->buttons[nRunIndex];
1579         if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1580             if (btnPtr->fsState & TBSTATE_CHECKED)
1581                 return nRunIndex;
1582         }
1583         else
1584             break;
1585         nRunIndex--;
1586     }
1587
1588     /* check next buttons */
1589     nRunIndex = nIndex + 1;
1590     while (nRunIndex < infoPtr->nNumButtons) {
1591         btnPtr = &infoPtr->buttons[nRunIndex];  
1592         if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1593             if (btnPtr->fsState & TBSTATE_CHECKED)
1594                 return nRunIndex;
1595         }
1596         else
1597             break;
1598         nRunIndex++;
1599     }
1600
1601     return -1;
1602 }
1603
1604
1605 static VOID
1606 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
1607                     WPARAM wParam, LPARAM lParam)
1608 {
1609     MSG msg;
1610
1611     msg.hwnd = hwndMsg;
1612     msg.message = uMsg;
1613     msg.wParam = wParam;
1614     msg.lParam = lParam;
1615     msg.time = GetMessageTime ();
1616     msg.pt.x = LOWORD(GetMessagePos ());
1617     msg.pt.y = HIWORD(GetMessagePos ());
1618
1619     SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
1620 }
1621
1622
1623 /***********************************************************************
1624  * TOOLBAR_CustomizeDialogProc
1625  * This function implements the toolbar customization dialog.
1626  */
1627 static BOOL WINAPI
1628 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1629 {
1630     PCUSTDLG_INFO custInfo = (PCUSTDLG_INFO)GetWindowLongA (hwnd, DWL_USER);
1631     PCUSTOMBUTTON btnInfo;
1632     NMTOOLBARA nmtb;
1633     TOOLBAR_INFO *infoPtr = custInfo ? custInfo->tbInfo : NULL;
1634
1635     switch (uMsg)
1636     {
1637         case WM_INITDIALOG:
1638             custInfo = (PCUSTDLG_INFO)lParam;
1639             SetWindowLongA (hwnd, DWL_USER, (DWORD)custInfo);
1640
1641             if (custInfo)
1642             {
1643                 char Buffer[256];
1644                 int i = 0;
1645                 int index;
1646                 
1647                 infoPtr = custInfo->tbInfo;
1648
1649                 /* send TBN_QUERYINSERT notification */
1650                 nmtb.iItem = custInfo->tbInfo->nNumButtons;
1651
1652                 if (!TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_QUERYINSERT))
1653                     return FALSE;
1654
1655                 /* add items to 'toolbar buttons' list and check if removable */
1656                 for (i = 0; i < custInfo->tbInfo->nNumButtons; i++)
1657                 {
1658                     btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1659                     memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1660                     btnInfo->btn.fsStyle = TBSTYLE_SEP;
1661                     btnInfo->bVirtual = FALSE;
1662                     LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1663
1664                     /* send TBN_QUERYDELETE notification */
1665                     nmtb.iItem = i;
1666                     btnInfo->bRemovable = TOOLBAR_SendNotify ((NMHDR *) &nmtb, 
1667                                                       infoPtr, 
1668                                                       TBN_QUERYDELETE);
1669
1670                     index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, 0);
1671                     SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1672                 }
1673
1674                 /* insert separator button into 'available buttons' list */
1675                 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1676                 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1677                 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1678                 btnInfo->bVirtual = FALSE;
1679                 btnInfo->bRemovable = TRUE;
1680                 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1681                 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1682                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1683
1684                 /* insert all buttons into dsa */
1685                 for (i = 0;; i++)
1686                 {
1687                     /* send TBN_GETBUTTONINFO notification */
1688                     nmtb.iItem = i;
1689                     nmtb.pszText = Buffer;
1690                     nmtb.cchText = 256;
1691
1692                     if (!TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_GETBUTTONINFOA))
1693                         break;
1694
1695                     TRACE("style: %x\n", nmtb.tbButton.fsStyle);                
1696
1697                     /* insert button into the apropriate list */
1698                     index = TOOLBAR_GetButtonIndex (custInfo->tbInfo, nmtb.tbButton.idCommand, FALSE);
1699                     if (index == -1)
1700                     {
1701                         btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1702                         memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1703                         btnInfo->bVirtual = FALSE;
1704                         btnInfo->bRemovable = TRUE;
1705                         if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1706                             strcpy (btnInfo->text, nmtb.pszText);
1707
1708                         index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1709                         SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1710                     }
1711                     else
1712                     {
1713                         btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1714                         memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1715                         if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1716                             strcpy (btnInfo->text, nmtb.pszText);
1717
1718                         SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1719                     }
1720                 }
1721
1722                 /* select first item in the 'available' list */
1723                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, 0, 0);
1724
1725                 /* append 'virtual' separator button to the 'toolbar buttons' list */
1726                 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1727                 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1728                 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1729                 btnInfo->bVirtual = TRUE;
1730                 btnInfo->bRemovable = FALSE;
1731                 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1732                 index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1733                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1734
1735                 /* select last item in the 'toolbar' list */
1736                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index, 0);
1737                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETTOPINDEX, index, 0);
1738
1739                 /* set focus and disable buttons */
1740                 PostMessageA (hwnd, WM_USER, 0, 0);
1741             }
1742             return TRUE;
1743
1744         case WM_USER:
1745             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1746             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1747             EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), FALSE);
1748             SetFocus (GetDlgItem (hwnd, IDC_TOOLBARBTN_LBOX));
1749             return TRUE;
1750
1751         case WM_CLOSE:
1752             EndDialog(hwnd, FALSE);
1753             return TRUE;
1754
1755         case WM_COMMAND:
1756             switch (LOWORD(wParam))
1757             {
1758                 case IDC_TOOLBARBTN_LBOX:
1759                     if (HIWORD(wParam) == LBN_SELCHANGE)
1760                     {
1761                         PCUSTOMBUTTON btnInfo;
1762                         NMTOOLBARA nmtb;
1763                         int count;
1764                         int index;
1765
1766                         count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1767                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1768
1769                         /* send TBN_QUERYINSERT notification */
1770                         nmtb.iItem = index;
1771                         TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, 
1772                                         TBN_QUERYINSERT);
1773
1774                         /* get list box item */
1775                         btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1776
1777                         if (index == (count - 1))
1778                         {
1779                             /* last item (virtual separator) */
1780                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1781                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1782                         }
1783                         else if (index == (count - 2))
1784                         {
1785                             /* second last item (last non-virtual item) */
1786                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1787                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1788                         }
1789                         else if (index == 0)
1790                         {
1791                             /* first item */
1792                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1793                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1794                         }
1795                         else
1796                         {
1797                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1798                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1799                         }
1800
1801                         EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), btnInfo->bRemovable);
1802                     }
1803                     break;
1804
1805                 case IDC_MOVEUP_BTN:
1806                     {
1807                         PCUSTOMBUTTON btnInfo;
1808                         int index;
1809                         int count;
1810
1811                         count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1812                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1813                         TRACE("Move up: index %d\n", index);
1814
1815                         /* send TBN_QUERYINSERT notification */
1816                         nmtb.iItem = index;
1817
1818                         if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1819                                             TBN_QUERYINSERT))
1820                         {
1821                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1822
1823                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1824                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index-1, 0);
1825                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index-1, (LPARAM)btnInfo);
1826                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1827
1828                             if (index <= 1)
1829                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1830                             else if (index >= (count - 3))
1831                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1832
1833                             SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1834                             SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index-1, (LPARAM)&(btnInfo->btn));
1835                         }
1836                     }
1837                     break;
1838
1839                 case IDC_MOVEDN_BTN: /* move down */
1840                     {
1841                         PCUSTOMBUTTON btnInfo;
1842                         int index;
1843                         int count;
1844
1845                         count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1846                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1847                         TRACE("Move up: index %d\n", index);
1848
1849                         /* send TBN_QUERYINSERT notification */
1850                         nmtb.iItem = index;
1851                         if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1852                                             TBN_QUERYINSERT))
1853                         {
1854                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1855
1856                             /* move button down */
1857                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1858                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index+1, 0);
1859                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index+1, (LPARAM)btnInfo);
1860                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index+1 , 0);
1861
1862                             if (index == 0)
1863                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1864                             else if (index >= (count - 3))
1865                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1866
1867                             SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1868                             SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index+1, (LPARAM)&(btnInfo->btn));
1869                         }
1870                     }
1871                     break;
1872
1873                 case IDC_REMOVE_BTN: /* remove button */
1874                     {
1875                         PCUSTOMBUTTON btnInfo;
1876                         int index;
1877
1878                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1879                         TRACE("Remove: index %d\n", index);
1880
1881                         /* send TBN_QUERYDELETE notification */
1882                         nmtb.iItem = index;
1883                         if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1884                                             TBN_QUERYDELETE))
1885                         {
1886                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1887                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1888                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index , 0);
1889
1890                             SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1891
1892                             /* insert into 'available button' list */
1893                             if (!(btnInfo->btn.fsStyle & TBSTYLE_SEP))
1894                             {
1895                                 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1896                                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1897                             }
1898                             else
1899                                 COMCTL32_Free (btnInfo);
1900                         }
1901                     }
1902                     break;
1903
1904                 case IDOK: /* Add button */
1905                     {
1906                         int index;
1907                         int count;
1908
1909                         count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1910                         index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0);
1911                         TRACE("Add: index %d\n", index);
1912
1913                         /* send TBN_QUERYINSERT notification */
1914                         nmtb.iItem = index;
1915                         if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
1916                                             TBN_QUERYINSERT))
1917                         {
1918                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, index, 0);
1919
1920                             if (index != 0)
1921                             {
1922                                 /* remove from 'available buttons' list */
1923                                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_DELETESTRING, index, 0);
1924                                 if (index == count-1)
1925                                     SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1926                                 else
1927                                     SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index , 0);
1928                             }
1929                             else
1930                             {
1931                                 PCUSTOMBUTTON btnNew;
1932
1933                                 /* duplicate 'separator' button */
1934                                 btnNew = (PCUSTOMBUTTON)COMCTL32_Alloc (sizeof(CUSTOMBUTTON));
1935                                 memcpy (btnNew, btnInfo, sizeof(CUSTOMBUTTON));
1936                                 btnInfo = btnNew;
1937                             }
1938
1939                             /* insert into 'toolbar button' list */
1940                             index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1941                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index, 0);
1942                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1943
1944                             SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index, (LPARAM)&(btnInfo->btn));
1945                         }
1946                     }
1947                     break;
1948
1949                 case IDCANCEL:
1950                     EndDialog(hwnd, FALSE);
1951                     break;
1952             }
1953             return TRUE;
1954
1955         case WM_DESTROY:
1956             {
1957                 int count;
1958                 int i;
1959
1960                 /* delete items from 'toolbar buttons' listbox*/
1961                 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1962                 for (i = 0; i < count; i++)
1963                 {
1964                     btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, i, 0);
1965                     COMCTL32_Free(btnInfo);
1966                     SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, 0, 0);
1967                 }
1968                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_RESETCONTENT, 0, 0);
1969
1970
1971                 /* delete items from 'available buttons' listbox*/
1972                 count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1973                 for (i = 0; i < count; i++)
1974                 {
1975                     btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, i, 0);
1976                     COMCTL32_Free(btnInfo);
1977                     SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, i, 0);
1978                 }
1979                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_RESETCONTENT, 0, 0);
1980             }
1981             return TRUE;
1982
1983         case WM_DRAWITEM:
1984             if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1985             {
1986                 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
1987                 RECT rcButton;
1988                 RECT rcText;
1989                 HPEN hOldPen;
1990                 HBRUSH hOldBrush;
1991                 COLORREF oldText = 0;
1992                 COLORREF oldBk = 0;
1993
1994                 /* get item data */
1995                 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, wParam, LB_GETITEMDATA, (WPARAM)lpdis->itemID, 0);
1996                 if (btnInfo == NULL)
1997                 {
1998                     FIXME("btnInfo invalid!\n");
1999                     return TRUE;
2000                 }
2001
2002                 /* set colors and select objects */
2003                 oldBk = SetBkColor (lpdis->hDC, (lpdis->itemState & ODS_FOCUS)?comctl32_color.clrHighlight:comctl32_color.clrWindow);
2004                 if (btnInfo->bVirtual)
2005                    oldText = SetTextColor (lpdis->hDC, comctl32_color.clrGrayText);
2006                 else
2007                    oldText = SetTextColor (lpdis->hDC, (lpdis->itemState & ODS_FOCUS)?comctl32_color.clrHighlightText:comctl32_color.clrWindowText);
2008                 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
2009                 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
2010
2011                 /* fill background rectangle */
2012                 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
2013                            lpdis->rcItem.right, lpdis->rcItem.bottom);
2014
2015                 /* calculate button and text rectangles */
2016                 CopyRect (&rcButton, &lpdis->rcItem);
2017                 InflateRect (&rcButton, -1, -1);
2018                 CopyRect (&rcText, &rcButton);
2019                 rcButton.right = rcButton.left + custInfo->tbInfo->nBitmapWidth + 6;
2020                 rcText.left = rcButton.right + 2;
2021
2022                 /* draw focus rectangle */
2023                 if (lpdis->itemState & ODS_FOCUS)
2024                     DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
2025
2026                 /* draw button */
2027                 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
2028
2029                 /* draw image and text */
2030                 if ((btnInfo->btn.fsStyle & TBSTYLE_SEP) == 0)
2031                     ImageList_Draw (custInfo->tbInfo->himlDef, btnInfo->btn.iBitmap, lpdis->hDC,
2032                                     rcButton.left+3, rcButton.top+3, ILD_NORMAL);
2033                 DrawTextA (lpdis->hDC,  btnInfo->text, -1, &rcText,
2034                                DT_LEFT | DT_VCENTER | DT_SINGLELINE);
2035
2036                 /* delete objects and reset colors */
2037                 SelectObject (lpdis->hDC, hOldBrush);
2038                 SelectObject (lpdis->hDC, hOldPen);
2039                 SetBkColor (lpdis->hDC, oldBk);
2040                 SetTextColor (lpdis->hDC, oldText);
2041
2042                 return TRUE;
2043             }
2044             return FALSE;
2045
2046         case WM_MEASUREITEM:
2047             if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
2048             {
2049                 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
2050
2051                 if (custInfo && custInfo->tbInfo)
2052                     lpmis->itemHeight = custInfo->tbInfo->nBitmapHeight + 8;
2053                 else
2054                     lpmis->itemHeight = 15 + 8; /* default height */
2055
2056                 return TRUE;
2057             }
2058             return FALSE;
2059
2060         default:
2061             return FALSE;
2062     }
2063 }
2064
2065
2066 /***********************************************************************
2067  * TOOLBAR_AddBitmap:  Add the bitmaps to the default image list.
2068  *
2069  */
2070 static LRESULT
2071 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2072 {
2073     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2074     LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
2075     INT nIndex = 0, nButtons, nCount;
2076     HBITMAP hbmLoad;
2077
2078     TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
2079     if (!lpAddBmp)
2080         return -1;
2081
2082     if (lpAddBmp->hInst == HINST_COMMCTRL)
2083     {
2084         if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
2085             nButtons = 15;
2086         else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
2087             nButtons = 13;
2088         else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
2089             nButtons = 5;
2090         else
2091             return -1;
2092
2093         TRACE ("adding %d internal bitmaps!\n", nButtons);
2094
2095         /* Windows resize all the buttons to the size of a newly added standard image */
2096         if (lpAddBmp->nID & 1) 
2097         {
2098             /* large icons */
2099             /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap 
2100              * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this 
2101              */
2102             SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
2103                           MAKELPARAM((WORD)24, (WORD)24));
2104             SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
2105                           MAKELPARAM((WORD)31, (WORD)30));
2106         }       
2107         else 
2108         {
2109             /* small icons */
2110             SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
2111                           MAKELPARAM((WORD)16, (WORD)16));
2112             SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
2113                           MAKELPARAM((WORD)22, (WORD)22));
2114         }
2115         
2116         TOOLBAR_CalcToolbar (hwnd);
2117     }
2118     else
2119     {
2120         nButtons = (INT)wParam;
2121         if (nButtons <= 0)
2122             return -1;
2123         
2124         TRACE ("adding %d bitmaps!\n", nButtons);
2125     }
2126     
2127     if (!(infoPtr->himlDef)) {
2128         /* create new default image list */
2129         TRACE ("creating default image list!\n");
2130
2131         infoPtr->himlDef =
2132             ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
2133                               ILC_COLOR | ILC_MASK, nButtons, 2);
2134         infoPtr->himlInt = infoPtr->himlDef;
2135     }
2136
2137     nCount = ImageList_GetImageCount(infoPtr->himlDef);
2138
2139     /* Add bitmaps to the default image list */
2140     if (lpAddBmp->hInst == (HINSTANCE)0)
2141     {
2142         nIndex = 
2143             ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
2144                                  CLR_DEFAULT);
2145     }
2146     else if (lpAddBmp->hInst == HINST_COMMCTRL)
2147     {
2148         /* Add system bitmaps */
2149         switch (lpAddBmp->nID)
2150     {
2151             case IDB_STD_SMALL_COLOR:
2152                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
2153                                        MAKEINTRESOURCEA(IDB_STD_SMALL));
2154                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
2155                                               hbmLoad, CLR_DEFAULT);
2156                 DeleteObject (hbmLoad);
2157                 break;
2158
2159             case IDB_STD_LARGE_COLOR:
2160                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
2161                                        MAKEINTRESOURCEA(IDB_STD_LARGE));
2162                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
2163                                               hbmLoad, CLR_DEFAULT);
2164                 DeleteObject (hbmLoad);
2165                 break;
2166
2167             case IDB_VIEW_SMALL_COLOR:
2168                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
2169                                        MAKEINTRESOURCEA(IDB_VIEW_SMALL));
2170                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
2171                                               hbmLoad, CLR_DEFAULT);
2172                 DeleteObject (hbmLoad);
2173                 break;
2174
2175             case IDB_VIEW_LARGE_COLOR:
2176                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
2177                                        MAKEINTRESOURCEA(IDB_VIEW_LARGE));
2178                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
2179                                               hbmLoad, CLR_DEFAULT);
2180                 DeleteObject (hbmLoad);
2181                 break;
2182
2183             case IDB_HIST_SMALL_COLOR:
2184                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
2185                                        MAKEINTRESOURCEA(IDB_HIST_SMALL));
2186                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
2187                                               hbmLoad, CLR_DEFAULT);
2188                 DeleteObject (hbmLoad);
2189                 break;
2190
2191             case IDB_HIST_LARGE_COLOR:
2192                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
2193                                        MAKEINTRESOURCEA(IDB_HIST_LARGE));
2194                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
2195                                               hbmLoad, CLR_DEFAULT);
2196                 DeleteObject (hbmLoad);
2197                 break;
2198
2199             default:
2200         nIndex = ImageList_GetImageCount (infoPtr->himlDef);
2201                 ERR ("invalid imagelist!\n");
2202                 break;
2203         }
2204     }
2205     else
2206     {
2207         hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
2208         nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
2209         DeleteObject (hbmLoad);
2210     }
2211
2212     TRACE("Number of bitmap infos: %d\n", infoPtr->nNumBitmapInfos);
2213
2214     if (infoPtr->nNumBitmapInfos == 0)
2215     {
2216         infoPtr->bitmaps = COMCTL32_Alloc(sizeof(TBITMAP_INFO));
2217     }
2218     else
2219     {
2220         TBITMAP_INFO *oldBitmaps = infoPtr->bitmaps;
2221         infoPtr->bitmaps = COMCTL32_Alloc((infoPtr->nNumBitmapInfos + 1) * sizeof(TBITMAP_INFO));
2222         memcpy(&infoPtr->bitmaps[0], &oldBitmaps[0], infoPtr->nNumBitmapInfos);
2223     }
2224
2225     infoPtr->bitmaps[infoPtr->nNumBitmapInfos].nButtons = nButtons;
2226     infoPtr->bitmaps[infoPtr->nNumBitmapInfos].hInst = lpAddBmp->hInst;
2227     infoPtr->bitmaps[infoPtr->nNumBitmapInfos].nID = lpAddBmp->nID;
2228
2229     infoPtr->nNumBitmapInfos++;
2230     TRACE("Number of bitmap infos: %d\n", infoPtr->nNumBitmapInfos);
2231
2232     if (nIndex != -1)
2233     {
2234        INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
2235
2236        if (infoPtr->nNumBitmaps + nButtons != imagecount)
2237        {
2238          WARN("Desired images do not match received images : Previous image number %i Previous images in list %i added %i expecting total %i, Images in list %i\n",
2239               infoPtr->nNumBitmaps, nCount, imagecount - nCount,
2240               infoPtr->nNumBitmaps+nButtons,imagecount);
2241
2242          infoPtr->nNumBitmaps = imagecount;
2243        }
2244        else
2245          infoPtr->nNumBitmaps += nButtons;
2246     }
2247
2248     InvalidateRect(hwnd, NULL, FALSE);
2249
2250     return nIndex;
2251 }
2252
2253
2254 static LRESULT
2255 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2256 {
2257     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2258     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2259     INT nOldButtons, nNewButtons, nAddButtons, nCount;
2260
2261     TRACE("adding %d buttons!\n", wParam);
2262
2263     nAddButtons = (UINT)wParam;
2264     nOldButtons = infoPtr->nNumButtons;
2265     nNewButtons = nOldButtons + nAddButtons;
2266
2267     if (infoPtr->nNumButtons == 0) {
2268         infoPtr->buttons =
2269             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2270     }
2271     else {
2272         TBUTTON_INFO *oldButtons = infoPtr->buttons;
2273         infoPtr->buttons =
2274             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2275         memcpy (&infoPtr->buttons[0], &oldButtons[0],
2276                 nOldButtons * sizeof(TBUTTON_INFO));
2277         COMCTL32_Free (oldButtons);
2278     }
2279
2280     infoPtr->nNumButtons = nNewButtons;
2281
2282     /* insert new button data */
2283     for (nCount = 0; nCount < nAddButtons; nCount++) {
2284         TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
2285         btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
2286         btnPtr->idCommand = lpTbb[nCount].idCommand;
2287         btnPtr->fsState   = lpTbb[nCount].fsState;
2288         btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
2289         btnPtr->dwData    = lpTbb[nCount].dwData;
2290         btnPtr->iString   = lpTbb[nCount].iString;
2291         btnPtr->bHot      = FALSE;
2292
2293         if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
2294             TTTOOLINFOA ti;
2295
2296             ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2297             ti.cbSize   = sizeof (TTTOOLINFOA);
2298             ti.hwnd     = hwnd;
2299             ti.uId      = btnPtr->idCommand;
2300             ti.hinst    = 0;
2301             ti.lpszText = LPSTR_TEXTCALLBACKA;
2302
2303             SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2304                             0, (LPARAM)&ti);
2305         }
2306     }
2307
2308     TOOLBAR_CalcToolbar (hwnd);
2309
2310     TOOLBAR_DumpToolbar (infoPtr, __LINE__);
2311
2312     InvalidateRect(hwnd, NULL, FALSE);
2313
2314     return TRUE;
2315 }
2316
2317
2318 static LRESULT
2319 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2320 {
2321     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2322     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2323     INT nOldButtons, nNewButtons, nAddButtons, nCount;
2324
2325     TRACE("adding %d buttons!\n", wParam);
2326
2327     nAddButtons = (UINT)wParam;
2328     nOldButtons = infoPtr->nNumButtons;
2329     nNewButtons = nOldButtons + nAddButtons;
2330
2331     if (infoPtr->nNumButtons == 0) {
2332         infoPtr->buttons =
2333             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2334     }
2335     else {
2336         TBUTTON_INFO *oldButtons = infoPtr->buttons;
2337         infoPtr->buttons =
2338             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
2339         memcpy (&infoPtr->buttons[0], &oldButtons[0],
2340                 nOldButtons * sizeof(TBUTTON_INFO));
2341         COMCTL32_Free (oldButtons);
2342     }
2343
2344     infoPtr->nNumButtons = nNewButtons;
2345
2346     /* insert new button data */
2347     for (nCount = 0; nCount < nAddButtons; nCount++) {
2348         TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
2349         btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
2350         btnPtr->idCommand = lpTbb[nCount].idCommand;
2351         btnPtr->fsState   = lpTbb[nCount].fsState;
2352         btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
2353         btnPtr->dwData    = lpTbb[nCount].dwData;
2354         btnPtr->iString   = lpTbb[nCount].iString;
2355         btnPtr->bHot      = FALSE;
2356
2357         if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
2358             TTTOOLINFOW ti;
2359
2360             ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2361             ti.cbSize   = sizeof (TTTOOLINFOW);
2362             ti.hwnd     = hwnd;
2363             ti.uId      = btnPtr->idCommand;
2364             ti.hinst    = 0;
2365             ti.lpszText = LPSTR_TEXTCALLBACKW;
2366
2367             SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2368                             0, (LPARAM)&ti);
2369         }
2370     }
2371
2372     TOOLBAR_CalcToolbar (hwnd);
2373
2374     TOOLBAR_DumpToolbar (infoPtr, __LINE__);
2375
2376     InvalidateRect(hwnd, NULL, FALSE);
2377
2378     return TRUE;
2379 }
2380
2381
2382 static LRESULT
2383 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2384 {
2385     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2386     INT nIndex;
2387
2388     if ((wParam) && (HIWORD(lParam) == 0)) {
2389         char szString[256];
2390         INT len;
2391         TRACE("adding string from resource!\n");
2392
2393         len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
2394                              szString, 256);
2395
2396         TRACE("len=%d \"%s\"\n", len, szString);
2397         nIndex = infoPtr->nNumStrings;
2398         if (infoPtr->nNumStrings == 0) {
2399             infoPtr->strings =
2400                 COMCTL32_Alloc (sizeof(LPWSTR));
2401         }
2402         else {
2403             LPWSTR *oldStrings = infoPtr->strings;
2404             infoPtr->strings =
2405                 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2406             memcpy (&infoPtr->strings[0], &oldStrings[0],
2407                     sizeof(LPWSTR) * infoPtr->nNumStrings);
2408             COMCTL32_Free (oldStrings);
2409         }
2410
2411         /*COMCTL32_Alloc zeros out the allocated memory*/
2412         Str_SetPtrAtoW (&infoPtr->strings[infoPtr->nNumStrings], szString );
2413         infoPtr->nNumStrings++;
2414     }
2415     else {
2416         LPSTR p = (LPSTR)lParam;
2417         INT len;
2418
2419         if (p == NULL)
2420             return -1;
2421         TRACE("adding string(s) from array!\n");
2422
2423         nIndex = infoPtr->nNumStrings;
2424         while (*p) {
2425             len = strlen (p);
2426             TRACE("len=%d \"%s\"\n", len, p);
2427
2428             if (infoPtr->nNumStrings == 0) {
2429                 infoPtr->strings =
2430                     COMCTL32_Alloc (sizeof(LPWSTR));
2431             }
2432             else {
2433                 LPWSTR *oldStrings = infoPtr->strings;
2434                 infoPtr->strings =
2435                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2436                 memcpy (&infoPtr->strings[0], &oldStrings[0],
2437                         sizeof(LPWSTR) * infoPtr->nNumStrings);
2438                 COMCTL32_Free (oldStrings);
2439             }
2440
2441             Str_SetPtrAtoW (&infoPtr->strings[infoPtr->nNumStrings], p );
2442             infoPtr->nNumStrings++;
2443
2444             p += (len+1);
2445         }
2446     }
2447
2448     return nIndex;
2449 }
2450
2451
2452 static LRESULT
2453 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2454 {
2455 #define MAX_RESOURCE_STRING_LENGTH 512
2456     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2457     INT nIndex;
2458
2459     if ((wParam) && (HIWORD(lParam) == 0)) {
2460         WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
2461         INT len;
2462         TRACE("adding string from resource!\n");
2463
2464         len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
2465                              szString, MAX_RESOURCE_STRING_LENGTH);
2466
2467         TRACE("len=%d %s\n", len, debugstr_w(szString));
2468         TRACE("First char: 0x%x\n", *szString);
2469         if (szString[0] == L'|')
2470         {
2471             PWSTR p = szString + 1;
2472                 
2473             nIndex = infoPtr->nNumStrings;
2474             while (*p != L'|') {
2475
2476             if (infoPtr->nNumStrings == 0) {
2477                 infoPtr->strings =
2478                     COMCTL32_Alloc (sizeof(LPWSTR));
2479             }
2480             else {
2481                 LPWSTR *oldStrings = infoPtr->strings;
2482                 infoPtr->strings =
2483                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2484                 memcpy (&infoPtr->strings[0], &oldStrings[0],
2485                         sizeof(LPWSTR) * infoPtr->nNumStrings);
2486                 COMCTL32_Free (oldStrings);
2487             }
2488
2489             len = COMCTL32_StrChrW (p, L'|') - p;
2490             TRACE("len=%d %s\n", len, debugstr_w(p));
2491             infoPtr->strings[infoPtr->nNumStrings] =
2492                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
2493             lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len+1);
2494             infoPtr->nNumStrings++;
2495
2496                 p += (len+1);
2497             }
2498         }
2499         else
2500         {
2501             nIndex = infoPtr->nNumStrings;
2502             if (infoPtr->nNumStrings == 0) {
2503                 infoPtr->strings =
2504                     COMCTL32_Alloc (sizeof(LPWSTR));
2505             }
2506             else {
2507                 LPWSTR *oldStrings = infoPtr->strings;
2508                 infoPtr->strings =
2509                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2510                 memcpy (&infoPtr->strings[0], &oldStrings[0],
2511                         sizeof(LPWSTR) * infoPtr->nNumStrings);
2512                 COMCTL32_Free (oldStrings);
2513             }
2514
2515             Str_SetPtrW (&infoPtr->strings[infoPtr->nNumStrings], szString);
2516             infoPtr->nNumStrings++;
2517         }
2518     }
2519     else {
2520         LPWSTR p = (LPWSTR)lParam;
2521         INT len;
2522
2523         if (p == NULL)
2524             return -1;
2525         TRACE("adding string(s) from array!\n");
2526         nIndex = infoPtr->nNumStrings;
2527         while (*p) {
2528             len = strlenW (p);
2529
2530             TRACE("len=%d %s\n", len, debugstr_w(p));
2531             if (infoPtr->nNumStrings == 0) {
2532                 infoPtr->strings =
2533                     COMCTL32_Alloc (sizeof(LPWSTR));
2534             }
2535             else {
2536                 LPWSTR *oldStrings = infoPtr->strings;
2537                 infoPtr->strings =
2538                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
2539                 memcpy (&infoPtr->strings[0], &oldStrings[0],
2540                         sizeof(LPWSTR) * infoPtr->nNumStrings);
2541                 COMCTL32_Free (oldStrings);
2542             }
2543
2544             Str_SetPtrW (&infoPtr->strings[infoPtr->nNumStrings], p);
2545             infoPtr->nNumStrings++;
2546
2547             p += (len+1);
2548         }
2549     }
2550
2551     return nIndex;
2552 }
2553
2554
2555 static LRESULT
2556 TOOLBAR_AutoSize (HWND hwnd)
2557 {
2558     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2559     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2560     RECT parent_rect;
2561     RECT window_rect;
2562     HWND parent;
2563     INT  x, y;
2564     INT  cx, cy;
2565     UINT uPosFlags = SWP_NOZORDER;
2566
2567     TRACE("resize forced, style=%lx!\n", dwStyle);
2568
2569     parent = GetParent (hwnd);
2570     GetClientRect(parent, &parent_rect);
2571
2572     x = parent_rect.left;
2573     y = parent_rect.top;
2574
2575     /* FIXME: we should be able to early out if nothing */
2576     /* has changed with nWidth != parent_rect width */
2577
2578     if (dwStyle & CCS_NORESIZE) {
2579         uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
2580         cx = 0;
2581         cy = 0;
2582         TOOLBAR_CalcToolbar (hwnd);
2583     }
2584     else {
2585         infoPtr->nWidth = parent_rect.right - parent_rect.left;
2586         TOOLBAR_CalcToolbar (hwnd);
2587         InvalidateRect( hwnd, NULL, TRUE );
2588         cy = infoPtr->nHeight;
2589         cx = infoPtr->nWidth;
2590
2591         if (dwStyle & CCS_NOMOVEY) {
2592                 GetWindowRect(hwnd, &window_rect);
2593                 ScreenToClient(parent, (LPPOINT)&window_rect.left);
2594                 y = window_rect.top;
2595         }
2596     }
2597
2598     if (dwStyle & CCS_NOPARENTALIGN)
2599         uPosFlags |= SWP_NOMOVE;
2600
2601     if (!(dwStyle & CCS_NODIVIDER))
2602         cy += GetSystemMetrics(SM_CYEDGE);
2603
2604     if (dwStyle & WS_BORDER)
2605     {
2606         x = y = 1;
2607         cy += GetSystemMetrics(SM_CYEDGE);
2608         cx += GetSystemMetrics(SM_CYEDGE);
2609     }
2610
2611     infoPtr->bAutoSize = TRUE;
2612     SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
2613                         cx, cy, uPosFlags);
2614     /* The following line makes sure that the infoPtr->bAutoSize is turned off after
2615      * the setwindowpos calls */
2616     infoPtr->bAutoSize = FALSE;
2617
2618     return 0;
2619 }
2620
2621
2622 static LRESULT
2623 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
2624 {
2625     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2626
2627     return infoPtr->nNumButtons;
2628 }
2629
2630
2631 static LRESULT
2632 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2633 {
2634     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2635
2636     if (infoPtr == NULL) {
2637         ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
2638         ERR("infoPtr == NULL!\n");
2639         return 0;
2640     }
2641
2642     infoPtr->dwStructSize = (DWORD)wParam;
2643
2644     return 0;
2645 }
2646
2647
2648 static LRESULT
2649 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2650 {
2651     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2652     TBUTTON_INFO *btnPtr;
2653     INT nIndex;
2654
2655     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2656     if (nIndex == -1)
2657         return FALSE;
2658
2659     btnPtr = &infoPtr->buttons[nIndex];
2660     btnPtr->iBitmap = LOWORD(lParam);
2661
2662     /* we HAVE to erase the background, the new bitmap could be */
2663     /* transparent */
2664     InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2665
2666     return TRUE;
2667 }
2668
2669
2670 static LRESULT
2671 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2672 {
2673     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2674     TBUTTON_INFO *btnPtr;
2675     INT nIndex;
2676     INT nOldIndex = -1;
2677     BOOL bChecked = FALSE;
2678
2679     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2680     if (nIndex == -1)
2681         return FALSE;
2682
2683     btnPtr = &infoPtr->buttons[nIndex];
2684
2685     if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
2686         return FALSE;
2687
2688     bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
2689
2690     if (LOWORD(lParam) == FALSE)
2691         btnPtr->fsState &= ~TBSTATE_CHECKED;
2692     else {
2693         if (btnPtr->fsStyle & TBSTYLE_GROUP) {
2694             nOldIndex = 
2695                 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
2696             if (nOldIndex == nIndex)
2697                 return 0;
2698             if (nOldIndex != -1)
2699                 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
2700         }
2701         btnPtr->fsState |= TBSTATE_CHECKED;
2702     }
2703
2704     if( bChecked != LOWORD(lParam) )
2705     {
2706         if (nOldIndex != -1)
2707         {
2708             InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
2709                 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
2710         }
2711         InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2712     }
2713
2714     /* FIXME: Send a WM_NOTIFY?? */
2715
2716     return TRUE;
2717 }
2718
2719
2720 static LRESULT
2721 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
2722 {
2723     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2724
2725     return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2726 }
2727
2728
2729 static LRESULT
2730 TOOLBAR_Customize (HWND hwnd)
2731 {
2732     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2733     CUSTDLG_INFO custInfo;
2734     LRESULT ret;
2735     LPCVOID template;
2736     HRSRC hRes;
2737     NMHDR nmhdr;
2738
2739     custInfo.tbInfo = infoPtr;
2740     custInfo.tbHwnd = hwnd;
2741
2742     /* send TBN_BEGINADJUST notification */
2743     TOOLBAR_SendNotify ((NMHDR *) &nmhdr, infoPtr,
2744                     TBN_BEGINADJUST);
2745
2746     if (!(hRes = FindResourceA (COMCTL32_hModule,
2747                                 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
2748                                 RT_DIALOGA)))
2749         return FALSE;
2750
2751     if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
2752         return FALSE;
2753
2754     ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
2755                                    (LPDLGTEMPLATEA)template,
2756                                    hwnd,
2757                                    (DLGPROC)TOOLBAR_CustomizeDialogProc,
2758                                    (LPARAM)&custInfo);
2759
2760     /* send TBN_ENDADJUST notification */
2761     TOOLBAR_SendNotify ((NMHDR *) &nmhdr, infoPtr,
2762                     TBN_ENDADJUST);
2763
2764     return ret;
2765 }
2766
2767
2768 static LRESULT
2769 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2770 {
2771     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2772     INT nIndex = (INT)wParam;
2773
2774     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2775         return FALSE;
2776
2777     if ((infoPtr->hwndToolTip) && 
2778         !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
2779         TTTOOLINFOA ti;
2780
2781         ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2782         ti.cbSize   = sizeof (TTTOOLINFOA);
2783         ti.hwnd     = hwnd;
2784         ti.uId      = infoPtr->buttons[nIndex].idCommand;
2785
2786         SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
2787     }
2788
2789     if (infoPtr->nNumButtons == 1) {
2790         TRACE(" simple delete!\n");
2791         COMCTL32_Free (infoPtr->buttons);
2792         infoPtr->buttons = NULL;
2793         infoPtr->nNumButtons = 0;
2794     }
2795     else {
2796         TBUTTON_INFO *oldButtons = infoPtr->buttons;
2797         TRACE("complex delete! [nIndex=%d]\n", nIndex);
2798
2799         infoPtr->nNumButtons--;
2800         infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2801         if (nIndex > 0) {
2802             memcpy (&infoPtr->buttons[0], &oldButtons[0],
2803                     nIndex * sizeof(TBUTTON_INFO));
2804         }
2805
2806         if (nIndex < infoPtr->nNumButtons) {
2807             memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
2808                     (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
2809         }
2810
2811         COMCTL32_Free (oldButtons);
2812     }
2813
2814     TOOLBAR_CalcToolbar (hwnd);
2815
2816     InvalidateRect (hwnd, NULL, TRUE);
2817
2818     return TRUE;
2819 }
2820
2821
2822 static LRESULT
2823 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2824 {
2825     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2826     TBUTTON_INFO *btnPtr;
2827     INT nIndex;
2828     DWORD bState;
2829
2830     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2831     if (nIndex == -1)
2832         return FALSE;
2833
2834     btnPtr = &infoPtr->buttons[nIndex];
2835
2836     bState = btnPtr->fsState & TBSTATE_ENABLED;
2837
2838     /* update the toolbar button state */
2839     if(LOWORD(lParam) == FALSE) {
2840         btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
2841     } else {
2842         btnPtr->fsState |= TBSTATE_ENABLED;
2843     }
2844
2845     /* redraw the button only if the state of the button changed */
2846     if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
2847     {
2848         InvalidateRect(hwnd, &btnPtr->rect,
2849             TOOLBAR_HasText(infoPtr, btnPtr));
2850     }
2851
2852     return TRUE;
2853 }
2854
2855
2856 static inline LRESULT
2857 TOOLBAR_GetAnchorHighlight (HWND hwnd)
2858 {
2859     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2860
2861     return infoPtr->bAnchor;
2862 }
2863
2864
2865 static LRESULT
2866 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2867 {
2868     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2869     INT nIndex;
2870
2871     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
2872     if (nIndex == -1)
2873         return -1;
2874
2875     return infoPtr->buttons[nIndex].iBitmap;
2876 }
2877
2878
2879 static inline LRESULT
2880 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2881 {
2882     return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
2883 }
2884
2885
2886 static LRESULT
2887 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2888 {
2889     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2890     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2891     INT nIndex = (INT)wParam;
2892     TBUTTON_INFO *btnPtr;
2893
2894     if (infoPtr == NULL)
2895         return FALSE;
2896
2897     if (lpTbb == NULL)
2898         return FALSE;
2899
2900     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2901         return FALSE;
2902
2903     btnPtr = &infoPtr->buttons[nIndex];
2904     lpTbb->iBitmap   = btnPtr->iBitmap;
2905     lpTbb->idCommand = btnPtr->idCommand;
2906     lpTbb->fsState   = btnPtr->fsState;
2907     lpTbb->fsStyle   = btnPtr->fsStyle;
2908     lpTbb->dwData    = btnPtr->dwData;
2909     lpTbb->iString   = btnPtr->iString;
2910
2911     return TRUE;
2912 }
2913
2914
2915 static LRESULT
2916 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2917 {
2918     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2919     LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
2920     TBUTTON_INFO *btnPtr;
2921     INT nIndex;
2922
2923     if (infoPtr == NULL)
2924         return -1;
2925     if (lpTbInfo == NULL)
2926         return -1;
2927     if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2928         return -1;
2929
2930     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam,
2931                                      lpTbInfo->dwMask & 0x80000000);
2932     if (nIndex == -1)
2933         return -1;
2934
2935     if (!(btnPtr = &infoPtr->buttons[nIndex])) return -1;
2936
2937     if (lpTbInfo->dwMask & TBIF_COMMAND)
2938         lpTbInfo->idCommand = btnPtr->idCommand;
2939     if (lpTbInfo->dwMask & TBIF_IMAGE)
2940         lpTbInfo->iImage = btnPtr->iBitmap;
2941     if (lpTbInfo->dwMask & TBIF_LPARAM)
2942         lpTbInfo->lParam = btnPtr->dwData;
2943     if (lpTbInfo->dwMask & TBIF_SIZE)
2944         lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2945     if (lpTbInfo->dwMask & TBIF_STATE)
2946         lpTbInfo->fsState = btnPtr->fsState;
2947     if (lpTbInfo->dwMask & TBIF_STYLE)
2948         lpTbInfo->fsStyle = btnPtr->fsStyle;
2949      if (lpTbInfo->dwMask & TBIF_TEXT) {
2950          LPWSTR lpText = TOOLBAR_GetText(infoPtr,btnPtr);
2951          Str_GetPtrWtoA (lpText, lpTbInfo->pszText,lpTbInfo->cchText);
2952          }
2953     return nIndex;
2954 }
2955
2956
2957 static LRESULT
2958 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2959 {
2960     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2961     LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
2962     TBUTTON_INFO *btnPtr;
2963     INT nIndex;
2964
2965     if (infoPtr == NULL)
2966         return -1;
2967     if (lpTbInfo == NULL)
2968         return -1;
2969     if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
2970         return -1;
2971
2972     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, 
2973                                      lpTbInfo->dwMask & 0x80000000);
2974     if (nIndex == -1)
2975         return -1;
2976
2977     btnPtr = &infoPtr->buttons[nIndex];
2978
2979     if (lpTbInfo->dwMask & TBIF_COMMAND)
2980         lpTbInfo->idCommand = btnPtr->idCommand;
2981     if (lpTbInfo->dwMask & TBIF_IMAGE)
2982         lpTbInfo->iImage = btnPtr->iBitmap;
2983     if (lpTbInfo->dwMask & TBIF_LPARAM)
2984         lpTbInfo->lParam = btnPtr->dwData;
2985     if (lpTbInfo->dwMask & TBIF_SIZE)
2986         lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2987     if (lpTbInfo->dwMask & TBIF_STATE)
2988         lpTbInfo->fsState = btnPtr->fsState;
2989     if (lpTbInfo->dwMask & TBIF_STYLE)
2990         lpTbInfo->fsStyle = btnPtr->fsStyle;
2991     if (lpTbInfo->dwMask & TBIF_TEXT) {
2992         LPWSTR lpText = TOOLBAR_GetText(infoPtr,btnPtr);
2993         Str_GetPtrW (lpText,lpTbInfo->pszText,lpTbInfo->cchText);
2994     }
2995
2996     return nIndex;
2997 }
2998
2999
3000 static LRESULT
3001 TOOLBAR_GetButtonSize (HWND hwnd)
3002 {
3003     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3004
3005     if (infoPtr->nNumButtons > 0)
3006         return MAKELONG((WORD)infoPtr->nButtonWidth,
3007                         (WORD)infoPtr->nButtonHeight);
3008     else
3009         return MAKELONG(8,7);
3010 }
3011
3012
3013 static LRESULT
3014 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3015 {
3016     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3017     INT nIndex;
3018     LPWSTR lpText;
3019
3020     if (lParam == 0)
3021         return -1;
3022
3023     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3024     if (nIndex == -1)
3025         return -1;
3026
3027     lpText = TOOLBAR_GetText(infoPtr,&infoPtr->buttons[nIndex]);
3028
3029     return WideCharToMultiByte( CP_ACP, 0, lpText, -1,
3030                                 (LPSTR)lParam, 0x7fffffff, NULL, NULL ) - 1;
3031 }
3032
3033
3034 static LRESULT
3035 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3036 {
3037     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3038     INT nIndex;
3039     LPWSTR lpText;
3040
3041     if (lParam == 0)
3042         return -1;
3043
3044     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3045     if (nIndex == -1)
3046         return -1;
3047
3048     lpText = TOOLBAR_GetText(infoPtr,&infoPtr->buttons[nIndex]);
3049
3050     strcpyW ((LPWSTR)lParam, lpText);
3051
3052     return strlenW (lpText);
3053 }
3054
3055
3056 static LRESULT
3057 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3058 {
3059     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3060
3061     return (LRESULT)infoPtr->himlDis;
3062 }
3063
3064
3065 inline static LRESULT
3066 TOOLBAR_GetExtendedStyle (HWND hwnd)
3067 {
3068     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3069
3070     return infoPtr->dwExStyle;
3071 }
3072
3073
3074 static LRESULT
3075 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3076 {
3077     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3078
3079     return (LRESULT)infoPtr->himlHot;
3080 }
3081
3082
3083 static LRESULT
3084 TOOLBAR_GetHotItem (HWND hwnd)
3085 {
3086     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3087
3088     if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
3089         return -1;
3090
3091     if (infoPtr->nHotItem < 0)
3092         return -1;
3093
3094     return (LRESULT)infoPtr->nHotItem;
3095 }
3096
3097
3098 static LRESULT
3099 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3100 {
3101     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3102
3103     return (LRESULT)infoPtr->himlDef;
3104 }
3105
3106
3107 /* << TOOLBAR_GetInsertMark >> */
3108 /* << TOOLBAR_GetInsertMarkColor >> */
3109
3110
3111 static LRESULT
3112 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
3113 {
3114     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3115     TBUTTON_INFO *btnPtr;
3116     LPRECT     lpRect;
3117     INT        nIndex;
3118
3119     if (infoPtr == NULL)
3120         return FALSE;
3121     nIndex = (INT)wParam;
3122     btnPtr = &infoPtr->buttons[nIndex];
3123     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
3124         return FALSE;
3125     lpRect = (LPRECT)lParam;
3126     if (lpRect == NULL)
3127         return FALSE;
3128     if (btnPtr->fsState & TBSTATE_HIDDEN)
3129         return FALSE;
3130     
3131     lpRect->left   = btnPtr->rect.left;
3132     lpRect->right  = btnPtr->rect.right;
3133     lpRect->bottom = btnPtr->rect.bottom;
3134     lpRect->top    = btnPtr->rect.top;
3135
3136     return TRUE;
3137 }
3138
3139
3140 static LRESULT
3141 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3142 {
3143     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3144     LPSIZE lpSize = (LPSIZE)lParam;
3145
3146     if (lpSize == NULL)
3147         return FALSE;
3148
3149     lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
3150     lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
3151
3152     TRACE("maximum size %d x %d\n",
3153            infoPtr->rcBound.right - infoPtr->rcBound.left,
3154            infoPtr->rcBound.bottom - infoPtr->rcBound.top);
3155
3156     return TRUE;
3157 }
3158
3159
3160 /* << TOOLBAR_GetObject >> */
3161
3162
3163 static LRESULT
3164 TOOLBAR_GetPadding (HWND hwnd)
3165 {
3166     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3167     DWORD oldPad;
3168
3169     oldPad = MAKELONG(infoPtr->szPadding.cx, infoPtr->szPadding.cy);
3170     return (LRESULT) oldPad;
3171 }
3172
3173
3174 static LRESULT
3175 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
3176 {
3177     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3178     TBUTTON_INFO *btnPtr;
3179     LPRECT     lpRect;
3180     INT        nIndex;
3181
3182     if (infoPtr == NULL)
3183         return FALSE;
3184     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3185     btnPtr = &infoPtr->buttons[nIndex];
3186     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
3187         return FALSE;
3188     lpRect = (LPRECT)lParam;
3189     if (lpRect == NULL)
3190         return FALSE;
3191     
3192     lpRect->left   = btnPtr->rect.left;
3193     lpRect->right  = btnPtr->rect.right;
3194     lpRect->bottom = btnPtr->rect.bottom;
3195     lpRect->top    = btnPtr->rect.top;
3196
3197     return TRUE;
3198 }
3199
3200
3201 static LRESULT
3202 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3203 {
3204     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3205
3206     if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
3207         return infoPtr->nRows;
3208     else
3209         return 1;
3210 }
3211
3212
3213 static LRESULT
3214 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
3215 {
3216     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3217     INT nIndex;
3218
3219     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3220     if (nIndex == -1)
3221         return -1;
3222
3223     return infoPtr->buttons[nIndex].fsState;
3224 }
3225
3226
3227 static LRESULT
3228 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3229 {
3230     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3231     INT nIndex;
3232
3233     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3234     if (nIndex == -1)
3235         return -1;
3236
3237     return infoPtr->buttons[nIndex].fsStyle;
3238 }
3239
3240
3241 static LRESULT
3242 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3243 {
3244     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3245
3246     if (infoPtr == NULL)
3247         return 0;
3248
3249     return infoPtr->nMaxTextRows;
3250 }
3251
3252
3253 static LRESULT
3254 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3255 {
3256     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3257
3258     if (infoPtr == NULL)
3259         return 0;
3260     return infoPtr->hwndToolTip;
3261 }
3262
3263
3264 static LRESULT
3265 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3266 {
3267     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3268
3269     TRACE("%s hwnd=0x%x stub!\n", 
3270            infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
3271
3272     return infoPtr->bUnicode;
3273 }
3274
3275
3276 inline static LRESULT
3277 TOOLBAR_GetVersion (HWND hwnd)
3278 {
3279     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3280     return infoPtr->iVersion;
3281 }
3282
3283
3284 static LRESULT
3285 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
3286 {
3287     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3288     TBUTTON_INFO *btnPtr;
3289     INT nIndex;
3290
3291     TRACE("\n");
3292
3293     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3294     if (nIndex == -1)
3295         return FALSE;
3296
3297     btnPtr = &infoPtr->buttons[nIndex];
3298     if (LOWORD(lParam) == FALSE)
3299         btnPtr->fsState &= ~TBSTATE_HIDDEN;
3300     else
3301         btnPtr->fsState |= TBSTATE_HIDDEN;
3302
3303     TOOLBAR_CalcToolbar (hwnd);
3304
3305     InvalidateRect (hwnd, NULL, TRUE);
3306
3307     return TRUE;
3308 }
3309
3310
3311 inline static LRESULT
3312 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
3313 {
3314     return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
3315 }
3316
3317
3318 static LRESULT
3319 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3320 {
3321     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3322     TBUTTON_INFO *btnPtr;
3323     INT nIndex;
3324
3325     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3326     if (nIndex == -1)
3327         return FALSE;
3328
3329     btnPtr = &infoPtr->buttons[nIndex];
3330     if (LOWORD(lParam) == FALSE)
3331         btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
3332     else
3333         btnPtr->fsState |= TBSTATE_INDETERMINATE;
3334
3335     InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
3336
3337     return TRUE;
3338 }
3339
3340
3341 static LRESULT
3342 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3343 {
3344     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3345     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
3346     INT nIndex = (INT)wParam;
3347     TBUTTON_INFO *oldButtons;
3348
3349     if (lpTbb == NULL)
3350         return FALSE;
3351
3352     TOOLBAR_DumpButton(infoPtr, (TBUTTON_INFO *)lpTbb, nIndex, FALSE);
3353
3354     if (nIndex == -1) {
3355        /* EPP: this seems to be an undocumented call (from my IE4)
3356         * I assume in that case that:
3357         * - lpTbb->iString is a string pointer (not a string index in strings[] table
3358         * - index of insertion is at the end of existing buttons
3359         * I only see this happen with nIndex == -1, but it could have a special
3360         * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3361         */
3362         nIndex = infoPtr->nNumButtons;
3363
3364     } else if (nIndex < 0)
3365        return FALSE;
3366
3367     /* If the string passed is not an index, assume address of string
3368        and do our own AddString */
3369     if ((HIWORD(lpTbb->iString) != 0) && (lpTbb->iString != -1)) {
3370         LPSTR ptr;
3371         INT len;
3372
3373         TRACE("string %s passed instead of index, adding string\n",
3374               debugstr_a((LPSTR)lpTbb->iString));
3375         len = strlen((LPSTR)lpTbb->iString) + 2;
3376         ptr = COMCTL32_Alloc(len);
3377         strcpy(ptr, (LPSTR)lpTbb->iString);
3378         ptr[len - 1] = 0; /* ended by two '\0' */
3379         lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
3380         COMCTL32_Free(ptr);
3381     }
3382
3383     TRACE("inserting button index=%d\n", nIndex);
3384     if (nIndex > infoPtr->nNumButtons) {
3385         nIndex = infoPtr->nNumButtons;
3386         TRACE("adjust index=%d\n", nIndex);
3387     }
3388
3389     oldButtons = infoPtr->buttons;
3390     infoPtr->nNumButtons++;
3391     infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
3392     /* pre insert copy */
3393     if (nIndex > 0) {
3394         memcpy (&infoPtr->buttons[0], &oldButtons[0],
3395                 nIndex * sizeof(TBUTTON_INFO));
3396     }
3397
3398     /* insert new button */
3399     infoPtr->buttons[nIndex].iBitmap   = lpTbb->iBitmap;
3400     infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
3401     infoPtr->buttons[nIndex].fsState   = lpTbb->fsState;
3402     infoPtr->buttons[nIndex].fsStyle   = lpTbb->fsStyle;
3403     infoPtr->buttons[nIndex].dwData    = lpTbb->dwData;
3404     /* if passed string and not index, then add string */
3405     if(HIWORD(lpTbb->iString) && lpTbb->iString!=-1) {
3406         Str_SetPtrAtoW ((LPWSTR *)&infoPtr->buttons[nIndex].iString, (LPCSTR )lpTbb->iString);
3407     }
3408     else
3409         infoPtr->buttons[nIndex].iString   = lpTbb->iString;
3410
3411     if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
3412         TTTOOLINFOA ti;
3413
3414         ZeroMemory (&ti, sizeof(TTTOOLINFOA));
3415         ti.cbSize   = sizeof (TTTOOLINFOA);
3416         ti.hwnd     = hwnd;
3417         ti.uId      = lpTbb->idCommand;
3418         ti.hinst    = 0;
3419         ti.lpszText = LPSTR_TEXTCALLBACKA;
3420
3421         SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
3422                         0, (LPARAM)&ti);
3423     }
3424
3425     /* post insert copy */
3426     if (nIndex < infoPtr->nNumButtons - 1) {
3427         memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
3428                 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
3429     }
3430
3431     COMCTL32_Free (oldButtons);
3432
3433     TOOLBAR_CalcToolbar (hwnd);
3434
3435     InvalidateRect (hwnd, NULL, TRUE);
3436
3437     return TRUE;
3438 }
3439
3440
3441 static LRESULT
3442 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3443 {
3444     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3445     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
3446     INT nIndex = (INT)wParam;
3447     TBUTTON_INFO *oldButtons;
3448
3449     if (lpTbb == NULL)
3450         return FALSE;
3451
3452     TOOLBAR_DumpButton(infoPtr, (TBUTTON_INFO *)lpTbb, nIndex, FALSE);
3453
3454     if (nIndex == -1) {
3455        /* EPP: this seems to be an undocumented call (from my IE4)
3456         * I assume in that case that:
3457         * - lpTbb->iString is a string pointer (not a string index in strings[] table
3458         * - index of insertion is at the end of existing buttons
3459         * I only see this happen with nIndex == -1, but it could have a special
3460         * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
3461         */
3462         nIndex = infoPtr->nNumButtons;
3463
3464     } else if (nIndex < 0)
3465        return FALSE;
3466
3467     /* If the string passed is not an index, assume address of string 
3468        and do our own AddString */
3469     if ((HIWORD(lpTbb->iString) != 0) && (lpTbb->iString != -1)) {
3470         LPWSTR ptr;
3471         INT len;
3472
3473         TRACE("string %s passed instead of index, adding string\n",
3474               debugstr_w((LPWSTR)lpTbb->iString));
3475         len = strlenW((LPWSTR)lpTbb->iString) + 2;
3476         ptr = COMCTL32_Alloc(len*sizeof(WCHAR));
3477         strcpyW(ptr, (LPWSTR)lpTbb->iString);
3478         ptr[len - 1] = 0; /* ended by two '\0' */
3479         lpTbb->iString = TOOLBAR_AddStringW(hwnd, 0, (LPARAM)ptr);
3480         COMCTL32_Free(ptr);
3481     }
3482
3483     TRACE("inserting button index=%d\n", nIndex);
3484     if (nIndex > infoPtr->nNumButtons) {
3485         nIndex = infoPtr->nNumButtons;
3486         TRACE("adjust index=%d\n", nIndex);
3487     }
3488
3489     oldButtons = infoPtr->buttons;
3490     infoPtr->nNumButtons++;
3491     infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
3492     /* pre insert copy */
3493     if (nIndex > 0) {
3494         memcpy (&infoPtr->buttons[0], &oldButtons[0],
3495                 nIndex * sizeof(TBUTTON_INFO));
3496     }
3497
3498     /* insert new button */
3499     infoPtr->buttons[nIndex].iBitmap   = lpTbb->iBitmap;
3500     infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
3501     infoPtr->buttons[nIndex].fsState   = lpTbb->fsState;
3502     infoPtr->buttons[nIndex].fsStyle   = lpTbb->fsStyle;
3503     infoPtr->buttons[nIndex].dwData    = lpTbb->dwData;
3504     /* if passed string and not index, then add string */
3505     if(HIWORD(lpTbb->iString) && lpTbb->iString!=-1) {
3506         Str_SetPtrW ((LPWSTR *)&infoPtr->buttons[nIndex].iString, (LPWSTR)lpTbb->iString);
3507     }
3508     else
3509         infoPtr->buttons[nIndex].iString   = lpTbb->iString;
3510
3511     if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
3512         TTTOOLINFOW ti;
3513
3514         ZeroMemory (&ti, sizeof(TTTOOLINFOW));
3515         ti.cbSize   = sizeof (TTTOOLINFOW);
3516         ti.hwnd     = hwnd;
3517         ti.uId      = lpTbb->idCommand;
3518         ti.hinst    = 0;
3519         ti.lpszText = LPSTR_TEXTCALLBACKW;
3520
3521         SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
3522                         0, (LPARAM)&ti);
3523     }
3524
3525     /* post insert copy */
3526     if (nIndex < infoPtr->nNumButtons - 1) {
3527         memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
3528                 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
3529     }
3530
3531     COMCTL32_Free (oldButtons);
3532
3533     TOOLBAR_CalcToolbar (hwnd);
3534
3535     InvalidateRect (hwnd, NULL, TRUE);
3536
3537     return TRUE;
3538 }
3539
3540
3541 /* << TOOLBAR_InsertMarkHitTest >> */
3542
3543
3544 static LRESULT
3545 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
3546 {
3547     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3548     INT nIndex;
3549
3550     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3551     if (nIndex == -1)
3552         return FALSE;
3553
3554     return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
3555 }
3556
3557
3558 static LRESULT
3559 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
3560 {
3561     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3562     INT nIndex;
3563
3564     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3565     if (nIndex == -1)
3566         return FALSE;
3567
3568     return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
3569 }
3570
3571
3572 static LRESULT
3573 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
3574 {
3575     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3576     INT nIndex;
3577
3578     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3579     if (nIndex == -1)
3580         return TRUE;
3581
3582     return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
3583 }
3584
3585
3586 static LRESULT
3587 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
3588 {
3589     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3590     INT nIndex;
3591
3592     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3593     if (nIndex == -1)
3594         return FALSE;
3595
3596     return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
3597 }
3598
3599
3600 static LRESULT
3601 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
3602 {
3603     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3604     INT nIndex;
3605
3606     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3607     if (nIndex == -1)
3608         return FALSE;
3609
3610     return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
3611 }
3612
3613
3614 static LRESULT
3615 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
3616 {
3617     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3618     INT nIndex;
3619
3620     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3621     if (nIndex == -1)
3622         return FALSE;
3623
3624     return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
3625 }
3626
3627
3628 /* << TOOLBAR_LoadImages >> */
3629 /* << TOOLBAR_MapAccelerator >> */
3630 /* << TOOLBAR_MarkButton >> */
3631 /* << TOOLBAR_MoveButton >> */
3632
3633
3634 static LRESULT
3635 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
3636 {
3637     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3638     TBUTTON_INFO *btnPtr;
3639     INT nIndex;
3640
3641     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
3642     if (nIndex == -1)
3643         return FALSE;
3644
3645     btnPtr = &infoPtr->buttons[nIndex];
3646     if (LOWORD(lParam) == FALSE)
3647         btnPtr->fsState &= ~TBSTATE_PRESSED;
3648     else
3649         btnPtr->fsState |= TBSTATE_PRESSED;
3650
3651     InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
3652
3653     return TRUE;
3654 }
3655
3656
3657 static LRESULT
3658 TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
3659 {
3660     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3661     LPTBREPLACEBITMAP lpReplace = (LPTBREPLACEBITMAP) lParam;
3662     HBITMAP hBitmap;
3663     int i = 0, nOldButtons = 0, pos = 0;
3664
3665     TRACE("hInstOld %x nIDOld %x hInstNew %x nIDNew %x nButtons %x\n",
3666           lpReplace->hInstOld, lpReplace->nIDOld, lpReplace->hInstNew, lpReplace->nIDNew,
3667           lpReplace->nButtons);
3668
3669     if (lpReplace->hInstOld == -1)
3670     {
3671         FIXME("changing standard bitmaps not implemented\n");
3672         return FALSE;
3673     }
3674     else if (lpReplace->hInstOld != 0)
3675     {
3676         FIXME("resources not in the current module not implemented\n");
3677         return FALSE;
3678     }
3679     else
3680     {
3681         hBitmap = (HBITMAP) lpReplace->nIDNew;
3682     }
3683
3684     TRACE("To be replaced hInstOld %x nIDOld %x\n", lpReplace->hInstOld, lpReplace->nIDOld);
3685     for (i = 0; i < infoPtr->nNumBitmapInfos; i++) {
3686         TBITMAP_INFO *tbi = &infoPtr->bitmaps[i];
3687         TRACE("tbimapinfo %d hInstOld %x nIDOld %x\n", i, tbi->hInst, tbi->nID);
3688         if (tbi->hInst == lpReplace->hInstOld && tbi->nID == lpReplace->nIDOld)
3689         {
3690             TRACE("Found: nButtons %d hInst %x nID %x\n", tbi->nButtons, tbi->hInst, tbi->nID);
3691             nOldButtons = tbi->nButtons;
3692             tbi->nButtons = lpReplace->nButtons;
3693             tbi->hInst = lpReplace->hInstNew;
3694             tbi->nID = lpReplace->nIDNew;
3695             TRACE("tbimapinfo changed %d hInstOld %x nIDOld %x\n", i, tbi->hInst, tbi->nID);
3696             break;
3697         }
3698         pos += tbi->nButtons;
3699     }
3700
3701     if (nOldButtons == 0)
3702     {
3703         WARN("No hinst/bitmap found! hInst %x nID %x\n", lpReplace->hInstOld, lpReplace->nIDOld);
3704         return FALSE;
3705     }
3706
3707     infoPtr->nNumBitmaps = infoPtr->nNumBitmaps - nOldButtons + lpReplace->nButtons;
3708
3709     /* ImageList_Replace(infoPtr->himlDef, pos, hBitmap, NULL); */
3710
3711
3712     for (i = pos + nOldButtons - 1; i >= pos; i--) {
3713         ImageList_Remove(infoPtr->himlDef, i);
3714     }
3715
3716     ImageList_AddMasked(infoPtr->himlDef, hBitmap, CLR_DEFAULT);
3717
3718     InvalidateRect(hwnd, NULL, FALSE);
3719
3720     return TRUE;
3721 }
3722
3723 static LRESULT
3724 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3725 {
3726 #if 0
3727     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3728     LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
3729
3730     if (lpSave == NULL) return 0;
3731
3732     if ((BOOL)wParam) {
3733         /* save toolbar information */
3734         FIXME("save to \"%s\" \"%s\"\n",
3735                lpSave->pszSubKey, lpSave->pszValueName);
3736
3737
3738     }
3739     else {
3740         /* restore toolbar information */
3741
3742         FIXME("restore from \"%s\" \"%s\"\n",
3743                lpSave->pszSubKey, lpSave->pszValueName);
3744
3745
3746     }
3747 #endif
3748
3749     return 0;
3750 }
3751
3752
3753 static LRESULT
3754 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3755 {
3756 #if 0
3757     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3758     LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
3759
3760     if (lpSave == NULL)
3761         return 0;
3762
3763     if ((BOOL)wParam) {
3764         /* save toolbar information */
3765         FIXME("save to \"%s\" \"%s\"\n",
3766                lpSave->pszSubKey, lpSave->pszValueName);
3767
3768
3769     }
3770     else {
3771         /* restore toolbar information */
3772
3773         FIXME("restore from \"%s\" \"%s\"\n",
3774                lpSave->pszSubKey, lpSave->pszValueName);
3775
3776
3777     }
3778 #endif
3779
3780     return 0;
3781 }
3782
3783
3784 static LRESULT
3785 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
3786 {
3787     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3788     BOOL bOldAnchor = infoPtr->bAnchor;
3789
3790     infoPtr->bAnchor = (BOOL)wParam;
3791
3792     return (LRESULT)bOldAnchor;
3793 }
3794
3795
3796 static LRESULT
3797 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3798 {
3799     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3800
3801     if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3802         return FALSE;
3803
3804     if (infoPtr->nNumButtons > 0)
3805         WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
3806              infoPtr->nNumButtons,
3807              infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
3808              LOWORD(lParam), HIWORD(lParam));
3809
3810     infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
3811     infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
3812
3813     /* uses image list internals directly */
3814     if (infoPtr->himlDef) {
3815         infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
3816         infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
3817     }
3818
3819     return TRUE;
3820 }
3821
3822
3823 static LRESULT
3824 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3825 {
3826     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3827     LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
3828     TBUTTON_INFO *btnPtr;
3829     INT nIndex;
3830
3831     if (lptbbi == NULL)
3832         return FALSE;
3833     if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
3834         return FALSE;
3835     
3836     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam,
3837                                      lptbbi->dwMask & 0x80000000);
3838     if (nIndex == -1)
3839         return FALSE;
3840
3841     btnPtr = &infoPtr->buttons[nIndex];
3842     if (lptbbi->dwMask & TBIF_COMMAND)
3843         btnPtr->idCommand = lptbbi->idCommand;
3844     if (lptbbi->dwMask & TBIF_IMAGE)
3845         btnPtr->iBitmap = lptbbi->iImage;
3846     if (lptbbi->dwMask & TBIF_LPARAM)
3847         btnPtr->dwData = lptbbi->lParam;
3848 /*    if (lptbbi->dwMask & TBIF_SIZE) */
3849 /*      btnPtr->cx = lptbbi->cx; */
3850     if (lptbbi->dwMask & TBIF_STATE)
3851         btnPtr->fsState = lptbbi->fsState;
3852     if (lptbbi->dwMask & TBIF_STYLE)
3853         btnPtr->fsStyle = lptbbi->fsStyle;
3854
3855     if ((lptbbi->dwMask & TBIF_TEXT) && ((INT)lptbbi->pszText != -1)) {
3856         if ((HIWORD(btnPtr->iString) == 0) || (btnPtr->iString == -1))
3857             /* iString is index, zero it to make Str_SetPtr succeed */
3858             btnPtr->iString=0;
3859       
3860          Str_SetPtrAtoW ((LPWSTR *)&btnPtr->iString, lptbbi->pszText);
3861     }
3862     return TRUE;
3863 }
3864
3865
3866 static LRESULT
3867 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3868 {
3869     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3870     LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
3871     TBUTTON_INFO *btnPtr;
3872     INT nIndex;
3873
3874     if (lptbbi == NULL)
3875         return FALSE;
3876     if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
3877         return FALSE;
3878
3879     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam,
3880                                      lptbbi->dwMask & 0x80000000);
3881     if (nIndex == -1)
3882         return FALSE;
3883
3884     btnPtr = &infoPtr->buttons[nIndex];
3885     if (lptbbi->dwMask & TBIF_COMMAND)
3886         btnPtr->idCommand = lptbbi->idCommand;
3887     if (lptbbi->dwMask & TBIF_IMAGE)
3888         btnPtr->iBitmap = lptbbi->iImage;
3889     if (lptbbi->dwMask & TBIF_LPARAM)
3890         btnPtr->dwData = lptbbi->lParam;
3891 /*    if (lptbbi->dwMask & TBIF_SIZE) */
3892 /*      btnPtr->cx = lptbbi->cx; */
3893     if (lptbbi->dwMask & TBIF_STATE)
3894         btnPtr->fsState = lptbbi->fsState;
3895     if (lptbbi->dwMask & TBIF_STYLE)
3896         btnPtr->fsStyle = lptbbi->fsStyle;
3897
3898     if ((lptbbi->dwMask & TBIF_TEXT) && ((INT)lptbbi->pszText != -1)) {
3899         if ((HIWORD(btnPtr->iString) == 0) || (btnPtr->iString == -1))
3900             /* iString is index, zero it to make Str_SetPtr succeed */
3901             btnPtr->iString=0;
3902         Str_SetPtrW ((LPWSTR *)&btnPtr->iString, lptbbi->pszText);
3903     }
3904     return TRUE;
3905 }
3906
3907
3908 static LRESULT
3909 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3910 {
3911     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3912     INT cx = LOWORD(lParam), cy = HIWORD(lParam);
3913
3914     if ((cx < 0) || (cy < 0))
3915     {
3916         ERR("invalid parameter 0x%08lx\n", (DWORD)lParam);
3917         return FALSE;
3918     }
3919
3920     /* The documentation claims you can only change the button size before
3921      * any button has been added. But this is wrong. 
3922      * WINZIP32.EXE (ver 8) calls this on one of its buttons after adding 
3923      * it to the toolbar, and it checks that the return value is nonzero - mjm
3924      * Further testing shows that we must actually perform the change too.
3925      */
3926     /*
3927      * The documentation also does not mention that if 0 is supplied for
3928      * either size, the system changes it to the default of 24 wide and
3929      * 22 high. Demonstarted in ControlSpy Toolbar. GLA 3/02 
3930      */
3931     infoPtr->nButtonWidth = (cx) ? cx : 24;
3932     infoPtr->nButtonHeight = (cy) ? cy : 22;
3933     return TRUE;
3934 }
3935
3936
3937 static LRESULT
3938 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
3939 {
3940     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3941
3942     if (infoPtr == NULL) {
3943         TRACE("Toolbar not initialized yet?????\n");
3944         return FALSE;
3945     }
3946
3947     /* if setting to current values, ignore */
3948     if ((infoPtr->cxMin == (INT)LOWORD(lParam)) &&
3949         (infoPtr->cxMax == (INT)HIWORD(lParam))) {
3950         TRACE("matches current width, min=%d, max=%d, no recalc\n",
3951               infoPtr->cxMin, infoPtr->cxMax);
3952         return TRUE; 
3953     }
3954
3955     /* save new values */
3956     infoPtr->cxMin = (INT)LOWORD(lParam);
3957     infoPtr->cxMax = (INT)HIWORD(lParam);
3958
3959     /* if both values are 0 then we are done */
3960     if (lParam == 0) {
3961         TRACE("setting both min and max to 0, norecalc\n"); 
3962         return TRUE;
3963     }
3964
3965     /* otherwise we need to recalc the toolbar and in some cases
3966        recalc the bounding rectangle (does DrawText w/ DT_CALCRECT
3967        which doesn't actually draw - GA). */
3968     TRACE("number of buttons %d, cx=%d, cy=%d, recalcing\n", 
3969         infoPtr->nNumButtons, infoPtr->cxMin, infoPtr->cxMax);
3970
3971     TOOLBAR_CalcToolbar (hwnd);
3972
3973     InvalidateRect (hwnd, NULL, TRUE);
3974
3975     return TRUE;
3976 }
3977
3978
3979 static LRESULT
3980 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
3981 {
3982     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3983     INT nIndex = (INT)wParam;
3984
3985     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
3986         return FALSE;
3987
3988     infoPtr->buttons[nIndex].idCommand = (INT)lParam;
3989
3990     if (infoPtr->hwndToolTip) {
3991
3992         FIXME("change tool tip!\n");
3993
3994     }
3995
3996     return TRUE;
3997 }
3998
3999
4000 static LRESULT
4001 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
4002 {
4003     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4004     HIMAGELIST himlTemp;
4005
4006
4007     if (wParam != 0) {
4008         FIXME("no support for multiple image lists\n");
4009         return 0;
4010     }
4011
4012     himlTemp = infoPtr->himlDis;
4013     infoPtr->himlDis = (HIMAGELIST)lParam;
4014
4015     /* FIXME: redraw ? */
4016
4017     return (LRESULT)himlTemp; 
4018 }
4019
4020
4021 static LRESULT
4022 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
4023 {
4024     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4025     DWORD dwTemp;
4026
4027     dwTemp = infoPtr->dwDTFlags;
4028     infoPtr->dwDTFlags =
4029         (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
4030
4031     return (LRESULT)dwTemp;
4032 }
4033
4034 static LRESULT
4035 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
4036 {
4037     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4038     DWORD dwTemp;
4039
4040     dwTemp = infoPtr->dwExStyle;
4041     infoPtr->dwExStyle = (DWORD)lParam;
4042
4043     if (infoPtr->dwExStyle & (TBSTYLE_EX_MIXEDBUTTONS |
4044                               TBSTYLE_EX_HIDECLIPPEDBUTTONS)) {
4045         FIXME("Extended style not implemented %s %s\n",
4046               (infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) ?
4047               "TBSTYLE_EX_MIXEDBUTTONS" : "",
4048               (infoPtr->dwExStyle & TBSTYLE_EX_HIDECLIPPEDBUTTONS) ?
4049               "TBSTYLE_EX_HIDECLIPPEDBUTTONS" : "");
4050     }
4051
4052     if (infoPtr->dwExStyle & ~TBSTYLE_EX_ALL)
4053         FIXME("Unknown Toolbar Extended Style 0x%08lx. Please report.\n",
4054               (infoPtr->dwExStyle & ~TBSTYLE_EX_ALL));
4055
4056     return (LRESULT)dwTemp; 
4057 }
4058
4059
4060 static LRESULT
4061 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
4062 {
4063     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
4064     HIMAGELIST himlTemp;
4065
4066     if (wParam != 0) {
4067         FIXME("no support for multiple image lists\n");
4068         return 0;
4069     }
4070
4071     himlTemp = infoPtr->himlHot;
4072     infoPtr->himlHot = (HIMAGELIST)lParam;
4073
4074     /* FIXME: redraw ? */
4075
4076     return (LRESULT)himlTemp; 
4077 }
4078
4079
4080 static LRESULT
4081 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
4082 {
4083     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
4084     INT nOldHotItem = infoPtr->nHotItem;
4085     TBUTTON_INFO *btnPtr;
4086
4087     if ((INT) wParam < 0 || (INT)wParam > infoPtr->nNumButtons)
4088         wParam = -2;
4089
4090     if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
4091     {
4092
4093         infoPtr->nHotItem = (INT)wParam;
4094         if ((INT)wParam >=0)
4095         {
4096             btnPtr = &infoPtr->buttons[(INT)wParam];
4097             btnPtr->bHot = TRUE;
4098                 InvalidateRect (hwnd, &btnPtr->rect,
4099                     TOOLBAR_HasText(infoPtr, btnPtr));
4100         }
4101         if (nOldHotItem>=0)
4102         {
4103             btnPtr = &infoPtr->buttons[nOldHotItem];
4104             btnPtr->bHot = FALSE;
4105                 InvalidateRect (hwnd, &btnPtr->rect,
4106                     TOOLBAR_HasText(infoPtr, btnPtr));
4107         }
4108     }
4109
4110     if (nOldHotItem < 0)
4111         return -1;
4112
4113     return (LRESULT)nOldHotItem;
4114 }
4115
4116
4117 static LRESULT
4118 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
4119 {
4120     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4121     HIMAGELIST himlTemp;
4122
4123     if (wParam != 0) {
4124         FIXME("no support for multiple image lists\n");
4125         return 0;
4126     }
4127
4128     himlTemp = infoPtr->himlDef;
4129     infoPtr->himlDef = (HIMAGELIST)lParam;
4130
4131     infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
4132
4133     ImageList_GetIconSize(infoPtr->himlDef, &infoPtr->nBitmapWidth,
4134                           &infoPtr->nBitmapHeight);
4135     TRACE("hwnd %08x, new himl=%08x, count=%d, bitmap w=%d, h=%d\n",
4136           hwnd, (INT)infoPtr->himlDef, infoPtr->nNumBitmaps,
4137           infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
4138
4139     /* FIXME: redraw ? */
4140     InvalidateRect(hwnd, NULL, TRUE);
4141
4142     return (LRESULT)himlTemp; 
4143 }
4144
4145
4146 static LRESULT
4147 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
4148 {
4149     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4150
4151     infoPtr->nIndent = (INT)wParam;
4152
4153     TRACE("\n");
4154
4155     /* process only on indent changing */
4156     if(infoPtr->nIndent != (INT)wParam)
4157     {
4158         infoPtr->nIndent = (INT)wParam;
4159         TOOLBAR_CalcToolbar (hwnd);
4160         InvalidateRect(hwnd, NULL, FALSE);
4161     }
4162
4163     return TRUE;
4164 }
4165
4166
4167 /* << TOOLBAR_SetInsertMark >> */
4168
4169
4170 static LRESULT
4171 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
4172 {
4173     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4174
4175     infoPtr->clrInsertMark = (COLORREF)lParam;
4176
4177     /* FIXME : redraw ??*/
4178
4179     return 0;
4180 }
4181
4182
4183 static LRESULT
4184 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
4185 {
4186     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4187
4188     if (infoPtr == NULL)
4189         return FALSE;
4190
4191     infoPtr->nMaxTextRows = (INT)wParam;
4192
4193     return TRUE;
4194 }
4195
4196
4197 static LRESULT
4198 TOOLBAR_SetPadding (HWND hwnd, WPARAM wParam, LPARAM lParam)
4199 {
4200     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4201     DWORD  oldPad;
4202
4203     oldPad = MAKELONG(infoPtr->szPadding.cx, infoPtr->szPadding.cy);
4204     infoPtr->szPadding.cx = LOWORD((DWORD)lParam);
4205     infoPtr->szPadding.cy = HIWORD((DWORD)lParam);
4206     FIXME("stub - nothing done with values, cx=%ld, cy=%ld\n",
4207           infoPtr->szPadding.cx, infoPtr->szPadding.cy);
4208     return (LRESULT) oldPad;
4209 }
4210
4211
4212 static LRESULT
4213 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
4214 {
4215     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4216     HWND hwndOldNotify;
4217
4218     TRACE("\n");
4219
4220     if (infoPtr == NULL)
4221         return 0;
4222     hwndOldNotify = infoPtr->hwndNotify;
4223     infoPtr->hwndNotify = (HWND)wParam;
4224
4225     return hwndOldNotify;
4226 }
4227
4228
4229 static LRESULT
4230 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
4231 {
4232     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4233     LPRECT lprc = (LPRECT)lParam;
4234
4235     TRACE("\n");
4236
4237     if (LOWORD(wParam) > 1) {
4238         FIXME("multiple rows not supported!\n");
4239     }
4240
4241     if(infoPtr->nRows != LOWORD(wParam))
4242     {
4243         infoPtr->nRows = LOWORD(wParam);
4244
4245         /* recalculate toolbar */
4246         TOOLBAR_CalcToolbar (hwnd);
4247
4248         /* repaint toolbar */
4249         InvalidateRect(hwnd, NULL, FALSE);
4250     }
4251
4252     /* return bounding rectangle */
4253     if (lprc) {
4254         lprc->left   = infoPtr->rcBound.left;
4255         lprc->right  = infoPtr->rcBound.right;
4256         lprc->top    = infoPtr->rcBound.top;
4257         lprc->bottom = infoPtr->rcBound.bottom;
4258     }
4259
4260     return 0;
4261 }
4262
4263
4264 static LRESULT
4265 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
4266 {
4267     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4268     TBUTTON_INFO *btnPtr;
4269     INT nIndex;
4270
4271     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
4272     if (nIndex == -1)
4273         return FALSE;
4274
4275     btnPtr = &infoPtr->buttons[nIndex];
4276
4277     /* if hidden state has changed the invalidate entire window and recalc */
4278     if ((btnPtr->fsState & TBSTATE_HIDDEN) != (LOWORD(lParam) & TBSTATE_HIDDEN)) {
4279         btnPtr->fsState = LOWORD(lParam);
4280         TOOLBAR_CalcToolbar (hwnd);
4281         InvalidateRect(hwnd, 0, TOOLBAR_HasText(infoPtr, btnPtr));
4282         return TRUE;
4283     }
4284
4285     /* process state changing if current state doesn't match new state */
4286     if(btnPtr->fsState != LOWORD(lParam))
4287     {
4288         btnPtr->fsState = LOWORD(lParam);
4289         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
4290             btnPtr));
4291     }
4292
4293     return TRUE;
4294 }
4295
4296
4297 static LRESULT
4298 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
4299 {
4300     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4301     TBUTTON_INFO *btnPtr;
4302     INT nIndex;
4303
4304     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE);
4305     if (nIndex == -1)
4306         return FALSE;
4307
4308     btnPtr = &infoPtr->buttons[nIndex];
4309
4310     /* process style change if current style doesn't match new style */
4311     if(btnPtr->fsStyle != LOWORD(lParam))
4312     {
4313         btnPtr->fsStyle = LOWORD(lParam);
4314         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
4315             btnPtr));
4316
4317         if (infoPtr->hwndToolTip) {
4318             FIXME("change tool tip!\n");
4319         }
4320     }
4321
4322     return TRUE;
4323 }
4324
4325
4326 inline static LRESULT
4327 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
4328 {
4329     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4330
4331     if (infoPtr == NULL)
4332         return 0;
4333     infoPtr->hwndToolTip = (HWND)wParam;
4334     return 0;
4335 }
4336
4337
4338 static LRESULT
4339 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
4340 {
4341     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4342     BOOL bTemp;
4343
4344     TRACE("%s hwnd=0x%04x stub!\n", 
4345            ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
4346
4347     bTemp = infoPtr->bUnicode;
4348     infoPtr->bUnicode = (BOOL)wParam;
4349
4350     return bTemp;
4351 }
4352
4353
4354 static LRESULT
4355 TOOLBAR_GetColorScheme (HWND hwnd, LPCOLORSCHEME lParam)
4356 {
4357     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4358
4359     lParam->clrBtnHighlight = (infoPtr->clrBtnHighlight == CLR_DEFAULT) ? 
4360                                comctl32_color.clrBtnHighlight : 
4361                                infoPtr->clrBtnHighlight;
4362     lParam->clrBtnShadow = (infoPtr->clrBtnShadow == CLR_DEFAULT) ? 
4363                            comctl32_color.clrBtnShadow : infoPtr->clrBtnShadow;
4364     return 1;
4365 }
4366
4367
4368 static LRESULT
4369 TOOLBAR_SetColorScheme (HWND hwnd, LPCOLORSCHEME lParam)
4370 {
4371     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4372
4373     TRACE("new colors Hl=%lx Shd=%lx, old colors Hl=%lx Shd=%lx\n",
4374           lParam->clrBtnHighlight, lParam->clrBtnShadow,
4375           infoPtr->clrBtnHighlight, infoPtr->clrBtnShadow);
4376
4377     infoPtr->clrBtnHighlight = lParam->clrBtnHighlight;
4378     infoPtr->clrBtnShadow = lParam->clrBtnShadow;
4379     InvalidateRect(hwnd, 0, 0);
4380     return 0;
4381 }
4382
4383
4384 static LRESULT
4385 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
4386 {
4387     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4388     INT iOldVersion = infoPtr->iVersion;
4389
4390     infoPtr->iVersion = iVersion;
4391
4392     return iOldVersion;
4393 }
4394
4395
4396 /*********************************************************************/
4397 /*                                                                   */
4398 /* This is undocumented and appears to be a "Super" TB_SETHOTITEM    */
4399 /* without the restriction of TBSTYLE_FLAT. This implementation is   */
4400 /* based on relay traces of the native control and IE 5.5            */
4401 /*                                                                   */
4402 /*********************************************************************/
4403 static LRESULT
4404 TOOLBAR_Unkwn45E (HWND hwnd, WPARAM wParam, LPARAM lParam)
4405 {
4406     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
4407     INT nOldHotItem = infoPtr->nHotItem;
4408     TBUTTON_INFO *btnPtr;
4409     INT no_hi = 0;
4410     NMTBHOTITEM nmhotitem;
4411
4412     if ((INT) wParam < 0 || (INT)wParam > infoPtr->nNumButtons)
4413         wParam = -2;
4414
4415     infoPtr->nHotItem = (INT)wParam;
4416     if (nOldHotItem != infoPtr->nHotItem) {
4417         nmhotitem.dwFlags = (DWORD)lParam;
4418         if ( !(nmhotitem.dwFlags & HICF_ENTERING) )
4419             nmhotitem.idOld = (nOldHotItem >= 0) ?
4420                 infoPtr->buttons[nOldHotItem].idCommand : 0;
4421         if ( !(nmhotitem.dwFlags & HICF_LEAVING) )
4422             nmhotitem.idNew = (infoPtr->nHotItem >= 0) ? 
4423                 infoPtr->buttons[infoPtr->nHotItem].idCommand : 0;
4424         no_hi = TOOLBAR_SendNotify((NMHDR*)&nmhotitem, infoPtr, TBN_HOTITEMCHANGE);
4425     }
4426     if ((INT)wParam >=0) {
4427         btnPtr = &infoPtr->buttons[(INT)wParam];
4428         btnPtr->bHot = (no_hi) ? FALSE : TRUE;
4429         InvalidateRect (hwnd, &btnPtr->rect,
4430                         TOOLBAR_HasText(infoPtr, btnPtr));
4431     }
4432     if (nOldHotItem>=0) {
4433         btnPtr = &infoPtr->buttons[nOldHotItem];
4434         btnPtr->bHot = FALSE;
4435         InvalidateRect (hwnd, &btnPtr->rect,
4436                         TOOLBAR_HasText(infoPtr, btnPtr));
4437     }
4438     GetFocus();
4439     TRACE("old item=%d, new item=%d, flags=%08lx, notify=%d\n",
4440           nOldHotItem, infoPtr->nHotItem, (DWORD)lParam, no_hi);
4441
4442     if (nOldHotItem < 0)
4443         return -1;
4444
4445     return (LRESULT)nOldHotItem;
4446 }
4447
4448
4449 static LRESULT
4450 TOOLBAR_Unkwn463 (HWND hwnd, WPARAM wParam, LPARAM lParam)
4451 {
4452     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4453     LPSIZE lpsize = (LPSIZE)lParam;
4454
4455     if (lpsize == NULL)
4456         return FALSE;
4457
4458     /*
4459      * Testing shows the following:
4460      *   wParam    = 0 adjust cx value
4461      *             = 1 set cy value to max size.
4462      *   lParam    pointer to SIZE structure
4463      *
4464      */
4465     TRACE("[0463] wParam %d, lParam 0x%08lx -> 0x%08lx 0x%08lx\n",
4466           wParam, lParam, lpsize->cx, lpsize->cy);
4467
4468     switch(wParam) {
4469     case 0:
4470         if (lpsize->cx == -1) {
4471             /* **** this is wrong, native measures each button and sets it */
4472             lpsize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
4473         }
4474         else if(HIWORD(lpsize->cx)) {
4475             RECT rc;
4476             HWND hwndParent = GetParent(hwnd);
4477
4478             InvalidateRect(hwnd, 0, 1);
4479             GetWindowRect(hwnd, &rc);
4480             MapWindowPoints(0, hwndParent, (LPPOINT)&rc, 2);
4481             TRACE("mapped to (%d,%d)-(%d,%d)\n",
4482                 rc.left, rc.top, rc.right, rc.bottom);
4483             lpsize->cx = max(rc.right-rc.left,
4484                              infoPtr->rcBound.right - infoPtr->rcBound.left);
4485         }
4486         else {
4487             lpsize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
4488         }
4489         break;
4490     case 1:
4491         lpsize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
4492         /* lpsize->cy = infoPtr->nHeight; */
4493         break;
4494     default:
4495         ERR("Unknown wParam %d for Toolbar message [0463]. Please report\n",
4496             wParam);
4497         return 0;
4498     }
4499     TRACE("[0463] set to -> 0x%08lx 0x%08lx\n",
4500           lpsize->cx, lpsize->cy);
4501     return 1;
4502 }
4503
4504
4505 static LRESULT
4506 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
4507 {
4508     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4509     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4510     LOGFONTA logFont;
4511
4512     /* initialize info structure */
4513     infoPtr->nButtonHeight = 22;
4514     infoPtr->nButtonWidth = 24;
4515     infoPtr->nBitmapHeight = 15;
4516     infoPtr->nBitmapWidth = 16;
4517
4518     infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
4519     infoPtr->nRows = 1;
4520     infoPtr->nMaxTextRows = 1;
4521     infoPtr->cxMin = -1;
4522     infoPtr->cxMax = -1;
4523     infoPtr->nNumBitmaps = 0;
4524     infoPtr->nNumStrings = 0;
4525
4526     infoPtr->bCaptured = FALSE;
4527     infoPtr->bUnicode = IsWindowUnicode (hwnd);
4528     infoPtr->nButtonDown = -1;
4529     infoPtr->nOldHit = -1;
4530     infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
4531     infoPtr->hwndNotify = GetParent (hwnd);
4532     infoPtr->bTransparent = (dwStyle & TBSTYLE_TRANSPARENT);
4533     infoPtr->bBtnTranspnt = (dwStyle & (TBSTYLE_FLAT | TBSTYLE_LIST));
4534     infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
4535     infoPtr->bAnchor = FALSE; /* no anchor highlighting */
4536     infoPtr->iVersion = 0;
4537     infoPtr->hwndSelf = hwnd;
4538     infoPtr->bDoRedraw = TRUE;
4539     infoPtr->clrBtnHighlight = CLR_DEFAULT;
4540     infoPtr->clrBtnShadow = CLR_DEFAULT;
4541     infoPtr->szPadding.cx = 7;
4542     infoPtr->szPadding.cy = 6;
4543     TOOLBAR_NotifyFormat(infoPtr, (WPARAM)hwnd, (LPARAM)NF_REQUERY);
4544
4545     SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
4546     infoPtr->hFont = infoPtr->hDefaultFont = CreateFontIndirectA (&logFont);
4547
4548     if (dwStyle & TBSTYLE_TOOLTIPS) {
4549         /* Create tooltip control */
4550         infoPtr->hwndToolTip =
4551             CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
4552                                CW_USEDEFAULT, CW_USEDEFAULT,
4553                                CW_USEDEFAULT, CW_USEDEFAULT,
4554                                hwnd, 0, 0, 0);
4555
4556         /* Send NM_TOOLTIPSCREATED notification */
4557         if (infoPtr->hwndToolTip) {
4558             NMTOOLTIPSCREATED nmttc;
4559
4560             nmttc.hwndToolTips = infoPtr->hwndToolTip;
4561
4562             TOOLBAR_SendNotify ((NMHDR *) &nmttc, infoPtr,
4563                             NM_TOOLTIPSCREATED);
4564         }
4565     }
4566
4567     TOOLBAR_CheckStyle (hwnd, dwStyle);
4568
4569     TOOLBAR_CalcToolbar(hwnd);
4570
4571     return 0;
4572 }
4573
4574
4575 static LRESULT
4576 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
4577 {
4578     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4579
4580     /* delete tooltip control */
4581     if (infoPtr->hwndToolTip)
4582         DestroyWindow (infoPtr->hwndToolTip);
4583
4584     /* delete button data */
4585     if (infoPtr->buttons)
4586         COMCTL32_Free (infoPtr->buttons);
4587
4588     /* delete strings */
4589     if (infoPtr->strings) {
4590         INT i;
4591         for (i = 0; i < infoPtr->nNumStrings; i++)
4592             if (infoPtr->strings[i])
4593                 COMCTL32_Free (infoPtr->strings[i]);
4594
4595         COMCTL32_Free (infoPtr->strings);
4596     }
4597
4598     /* destroy internal image list */
4599     if (infoPtr->himlInt)
4600         ImageList_Destroy (infoPtr->himlInt);
4601
4602     /* delete default font */
4603     if (infoPtr->hFont)
4604         DeleteObject (infoPtr->hDefaultFont);
4605
4606     /* free toolbar info data */
4607     COMCTL32_Free (infoPtr);
4608     SetWindowLongA (hwnd, 0, 0);
4609
4610     return 0;
4611 }
4612
4613
4614 static LRESULT
4615 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
4616 {
4617     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4618     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4619     NMTBCUSTOMDRAW tbcd;
4620     INT ret = FALSE;
4621     DWORD ntfret;
4622
4623     if (dwStyle & TBSTYLE_CUSTOMERASE) {
4624         ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
4625         tbcd.nmcd.dwDrawStage = CDDS_PREERASE;
4626         tbcd.nmcd.hdc = (HDC)wParam;
4627         ntfret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
4628         infoPtr->dwBaseCustDraw = ntfret & 0xffff;
4629
4630         /* FIXME: in general the return flags *can* be or'ed together */
4631         switch (infoPtr->dwBaseCustDraw) 
4632             {
4633             case CDRF_DODEFAULT:
4634                 break;
4635             case CDRF_SKIPDEFAULT:
4636                 return TRUE;
4637             default:
4638                 FIXME("[%04x] response %ld not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4639                       hwnd, ntfret);
4640             }
4641     }
4642
4643     /* If the toolbar is "transparent" then pass the WM_ERASEBKGND up 
4644      * to my parent for processing.
4645      */
4646     if (infoPtr->bTransparent) {
4647         POINT pt, ptorig;
4648         HDC hdc = (HDC)wParam;
4649         HWND parent;
4650
4651         pt.x = 0;
4652         pt.y = 0;
4653         parent = GetParent(hwnd);
4654         MapWindowPoints(hwnd, parent, &pt, 1);
4655         OffsetWindowOrgEx (hdc, pt.x, pt.y, &ptorig);
4656         ret = SendMessageA (parent, WM_ERASEBKGND, wParam, lParam);
4657         SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0);
4658     }
4659     if (!ret)
4660         ret = DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
4661
4662     if ((dwStyle & TBSTYLE_CUSTOMERASE) && 
4663         (infoPtr->dwBaseCustDraw & CDRF_NOTIFYPOSTERASE)) { 
4664         ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
4665         tbcd.nmcd.dwDrawStage = CDDS_POSTERASE;
4666         tbcd.nmcd.hdc = (HDC)wParam;
4667         ntfret = TOOLBAR_SendNotify ((NMHDR *)&tbcd, infoPtr, NM_CUSTOMDRAW);
4668         infoPtr->dwBaseCustDraw = ntfret & 0xffff;
4669         switch (infoPtr->dwBaseCustDraw) 
4670             {
4671             case CDRF_DODEFAULT:
4672                 break;
4673             case CDRF_SKIPDEFAULT:
4674                 return TRUE;
4675             default:
4676                 FIXME("[%04x] response %ld not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n",
4677                       hwnd, ntfret);
4678             }
4679     }
4680     return ret;
4681 }
4682
4683
4684 static LRESULT
4685 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
4686 {
4687     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4688
4689     return infoPtr->hFont;
4690 }
4691
4692
4693 static LRESULT
4694 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
4695 {
4696     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4697     TBUTTON_INFO *btnPtr;
4698     POINT pt;
4699     INT   nHit;
4700
4701     pt.x = (INT)LOWORD(lParam);
4702     pt.y = (INT)HIWORD(lParam);
4703     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4704
4705     if (nHit >= 0) {
4706         btnPtr = &infoPtr->buttons[nHit];
4707         if (!(btnPtr->fsState & TBSTATE_ENABLED))
4708             return 0;
4709         SetCapture (hwnd);
4710         infoPtr->bCaptured = TRUE;
4711         infoPtr->nButtonDown = nHit;
4712
4713         btnPtr->fsState |= TBSTATE_PRESSED;
4714
4715         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
4716             btnPtr));
4717     }
4718     else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
4719         TOOLBAR_Customize (hwnd);
4720
4721     return 0;
4722 }
4723
4724
4725 static LRESULT
4726 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
4727 {
4728     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4729     TBUTTON_INFO *btnPtr;
4730     POINT pt;
4731     INT   nHit;
4732     NMTOOLBARA nmtb;
4733
4734     if (infoPtr->hwndToolTip)
4735         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
4736                             WM_LBUTTONDOWN, wParam, lParam);
4737
4738     pt.x = (INT)LOWORD(lParam);
4739     pt.y = (INT)HIWORD(lParam);
4740     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4741
4742     if (nHit >= 0) {
4743         RECT arrowRect;
4744         btnPtr = &infoPtr->buttons[nHit];
4745         if (!(btnPtr->fsState & TBSTATE_ENABLED))
4746             return 0;
4747
4748         infoPtr->nOldHit = nHit;
4749
4750         CopyRect(&arrowRect, &btnPtr->rect);
4751         arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
4752
4753         /* for EX_DRAWDDARROWS style,  click must be in the drop-down arrow rect */
4754         if ((btnPtr->fsStyle & TBSTYLE_DROPDOWN) &&
4755              ((TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && PtInRect(&arrowRect, pt)) ||
4756               (!TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle))))
4757         {
4758             LRESULT res;
4759             /*
4760              * this time we must force a Redraw, so the btn is
4761              * painted down before CaptureChanged repaints it up
4762              */
4763             RedrawWindow(hwnd,&btnPtr->rect,0,
4764                         RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
4765
4766             nmtb.iItem = btnPtr->idCommand;
4767             memset(&nmtb.tbButton, 0, sizeof(TBBUTTON));
4768             nmtb.cchText = 0;
4769             nmtb.pszText = 0;
4770             memset(&nmtb.rcButton, 0, sizeof(RECT));
4771             res = TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
4772                                   TBN_DROPDOWN);
4773             if (res != TBDDRET_TREATPRESSED)
4774                 /* ??? guess  (GA)  */
4775                 return 0;
4776             /* otherwise drop through and process as pushed */
4777         }
4778         /* SetCapture (hwnd); */
4779         infoPtr->bCaptured = TRUE;
4780         infoPtr->nButtonDown = nHit;
4781
4782         btnPtr->fsState |= TBSTATE_PRESSED;
4783         btnPtr->bHot = FALSE;
4784
4785         InvalidateRect(hwnd, &btnPtr->rect,
4786                        TOOLBAR_HasText(infoPtr, btnPtr));
4787         UpdateWindow(hwnd);
4788         SetCapture (hwnd);
4789
4790         /* native issues the TBN_BEGINDRAG here */
4791         nmtb.iItem = btnPtr->idCommand;
4792         nmtb.tbButton.iBitmap = btnPtr->iBitmap;
4793         nmtb.tbButton.idCommand = btnPtr->idCommand;
4794         nmtb.tbButton.fsState = btnPtr->fsState;
4795         nmtb.tbButton.fsStyle = btnPtr->fsStyle;
4796         nmtb.tbButton.dwData = btnPtr->dwData;
4797         nmtb.tbButton.iString = btnPtr->iString;
4798         nmtb.cchText = 0;  /* !!! not correct */
4799         nmtb.pszText = 0;  /* !!! not correct */
4800         TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
4801                         TBN_BEGINDRAG);
4802     }
4803
4804     return 0;
4805 }
4806
4807 static LRESULT
4808 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
4809 {
4810     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4811     TBUTTON_INFO *btnPtr;
4812     POINT pt;
4813     INT   nHit;
4814     INT   nOldIndex = -1;
4815     BOOL  bSendMessage = TRUE;
4816     NMHDR hdr;
4817     NMMOUSE nmmouse;
4818     NMTOOLBARA nmtb;
4819
4820     if (infoPtr->hwndToolTip)
4821         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
4822                             WM_LBUTTONUP, wParam, lParam);
4823
4824     pt.x = (INT)LOWORD(lParam);
4825     pt.y = (INT)HIWORD(lParam);
4826     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4827
4828     /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
4829     /* if the cursor is still inside of the toolbar */
4830     if((infoPtr->nHotItem >= 0) && (nHit != -1))
4831         infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
4832
4833         btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4834         btnPtr->fsState &= ~TBSTATE_PRESSED;
4835
4836         if (btnPtr->fsStyle & TBSTYLE_CHECK) {
4837                 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
4838                     nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
4839                         nHit);
4840                     if (nOldIndex == nHit)
4841                         bSendMessage = FALSE;
4842                     if ((nOldIndex != nHit) && 
4843                         (nOldIndex != -1))
4844                         infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
4845                     btnPtr->fsState |= TBSTATE_CHECKED;
4846                 }
4847                 else {
4848                     if (btnPtr->fsState & TBSTATE_CHECKED)
4849                         btnPtr->fsState &= ~TBSTATE_CHECKED;
4850                     else
4851                         btnPtr->fsState |= TBSTATE_CHECKED;
4852                 }
4853         }
4854
4855         if (nOldIndex != -1)
4856         {
4857             InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
4858                 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
4859         }
4860
4861         /*
4862          * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
4863          * that resets bCaptured and btn TBSTATE_PRESSED flags,
4864          * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged) 
4865          */
4866         if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0))
4867             ReleaseCapture ();
4868
4869         /* Issue NM_RELEASEDCAPTURE to parent to let him know it is released */
4870         TOOLBAR_SendNotify ((NMHDR *) &hdr, infoPtr,
4871                         NM_RELEASEDCAPTURE);
4872
4873         /* native issues TBN_ENDDRAG here, if _LBUTTONDOWN issued the 
4874          * TBN_BEGINDRAG
4875          */
4876         nmtb.iItem = btnPtr->idCommand;
4877         nmtb.tbButton.iBitmap = btnPtr->iBitmap;
4878         nmtb.tbButton.idCommand = btnPtr->idCommand;
4879         nmtb.tbButton.fsState = btnPtr->fsState;
4880         nmtb.tbButton.fsStyle = btnPtr->fsStyle;
4881         nmtb.tbButton.dwData = btnPtr->dwData;
4882         nmtb.tbButton.iString = btnPtr->iString;
4883         nmtb.cchText = 0;  /* !!! not correct */
4884         nmtb.pszText = 0;  /* !!! not correct */
4885         TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr,
4886                         TBN_ENDDRAG);
4887
4888         SendMessageA (infoPtr->hwndNotify, WM_COMMAND,
4889           MAKEWPARAM(infoPtr->buttons[nHit].idCommand, 0), (LPARAM)hwnd);
4890
4891         /* !!! Undocumented - toolbar at 4.71 level and above sends
4892          * either NMRCLICK or NM_CLICK with the NMMOUSE structure.
4893          * Only NM_RCLICK is documented.
4894          */
4895         nmmouse.dwItemSpec = btnPtr->idCommand;
4896         nmmouse.dwItemData = btnPtr->dwData;
4897         TOOLBAR_SendNotify ((NMHDR *) &nmmouse, infoPtr,
4898                         NM_CLICK);
4899     return 0;
4900 }
4901
4902 static LRESULT
4903 TOOLBAR_CaptureChanged(HWND hwnd)
4904 {
4905     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4906     TBUTTON_INFO *btnPtr;
4907
4908     infoPtr->bCaptured = FALSE;
4909
4910     if (infoPtr->nButtonDown >= 0)
4911     {
4912         btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4913         btnPtr->fsState &= ~TBSTATE_PRESSED;
4914
4915         infoPtr->nButtonDown = -1;
4916         infoPtr->nOldHit = -1;
4917
4918         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
4919             btnPtr));
4920     }
4921     return 0;
4922 }
4923
4924 static LRESULT
4925 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
4926 {
4927     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4928     TBUTTON_INFO *hotBtnPtr, *btnPtr;
4929     RECT rc1;
4930
4931     if (infoPtr->nOldHit < 0)
4932       return TRUE;
4933
4934     hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
4935
4936     /* Redraw the button if the last button we were over is the hot button and it
4937        is enabled */
4938     if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
4939     {
4940         hotBtnPtr->bHot = FALSE;
4941         rc1 = hotBtnPtr->rect;
4942         InflateRect (&rc1, 1, 1);
4943         InvalidateRect (hwnd, &rc1, TOOLBAR_HasText(infoPtr,
4944             hotBtnPtr));
4945     }
4946
4947     /* If the last button we were over is depressed then make it not */
4948     /* depressed and redraw it */
4949     if(infoPtr->nOldHit == infoPtr->nButtonDown)
4950     {
4951       btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4952
4953       btnPtr->fsState &= ~TBSTATE_PRESSED;
4954
4955       rc1 = hotBtnPtr->rect;
4956       InflateRect (&rc1, 1, 1);
4957       InvalidateRect (hwnd, &rc1, TRUE);
4958     }
4959
4960     infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
4961     infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
4962
4963     return TRUE;
4964 }
4965
4966 static LRESULT
4967 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
4968 {
4969     TBUTTON_INFO *btnPtr = NULL, *oldBtnPtr = NULL;
4970     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4971     POINT pt;
4972     INT   nHit;
4973     TRACKMOUSEEVENT trackinfo;
4974     NMTBHOTITEM nmhotitem;
4975
4976     /* fill in the TRACKMOUSEEVENT struct */
4977     trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
4978     trackinfo.dwFlags = TME_QUERY;
4979     trackinfo.hwndTrack = hwnd;
4980     trackinfo.dwHoverTime = HOVER_DEFAULT;
4981
4982     /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
4983     _TrackMouseEvent(&trackinfo);
4984
4985     /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
4986     if(!(trackinfo.dwFlags & TME_LEAVE)) {
4987         trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
4988  
4989         /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
4990         /* and can properly deactivate the hot toolbar button */
4991         _TrackMouseEvent(&trackinfo);
4992    }
4993
4994     if (infoPtr->hwndToolTip)
4995         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
4996                             WM_MOUSEMOVE, wParam, lParam);
4997
4998     pt.x = (INT)LOWORD(lParam);
4999     pt.y = (INT)HIWORD(lParam);
5000
5001     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
5002
5003     if (infoPtr->nOldHit != nHit)
5004     {
5005         /* Remove the effect of an old hot button if the button was enabled and was
5006            drawn with the hot button effect */
5007         if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem && 
5008                 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
5009         {
5010             oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
5011             oldBtnPtr->bHot = FALSE;
5012         }
5013
5014         /* It's not a separator or in nowhere. It's a hot button. */
5015         if (nHit >= 0)
5016         {
5017             btnPtr = &infoPtr->buttons[nHit];
5018
5019             infoPtr->nHotItem = nHit;
5020
5021             /* only enabled buttons show hot effect */            
5022             if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
5023             {
5024                 btnPtr->bHot = TRUE;
5025             }
5026         }
5027
5028         nmhotitem.dwFlags = HICF_MOUSE;
5029         if (oldBtnPtr)
5030             nmhotitem.idOld = oldBtnPtr->idCommand;
5031         else
5032             nmhotitem.dwFlags |= HICF_ENTERING;
5033         if (btnPtr)
5034             nmhotitem.idNew = btnPtr->idCommand;
5035         else
5036             nmhotitem.dwFlags |= HICF_LEAVING;
5037         TOOLBAR_SendNotify((NMHDR*)&nmhotitem, infoPtr, TBN_HOTITEMCHANGE);
5038
5039         /* now invalidate the old and new buttons so they will be painted */
5040         if (oldBtnPtr)
5041             InvalidateRect (hwnd, &oldBtnPtr->rect,
5042                             TOOLBAR_HasText(infoPtr, oldBtnPtr));
5043         if (btnPtr && (btnPtr->fsState & TBSTATE_ENABLED))
5044             InvalidateRect(hwnd, &btnPtr->rect,
5045                            TOOLBAR_HasText(infoPtr, btnPtr));
5046
5047         if (infoPtr->bCaptured) {
5048             btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
5049             if (infoPtr->nOldHit == infoPtr->nButtonDown) {
5050                 btnPtr->fsState &= ~TBSTATE_PRESSED;
5051                 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
5052             }
5053             else if (nHit == infoPtr->nButtonDown) {
5054                 btnPtr->fsState |= TBSTATE_PRESSED;
5055                 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
5056             }
5057         }
5058         infoPtr->nOldHit = nHit;
5059     }
5060     return 0;
5061 }
5062
5063
5064 inline static LRESULT
5065 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
5066 {
5067 /*    if (wndPtr->dwStyle & CCS_NODIVIDER) */
5068         return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
5069 /*    else */
5070 /*      return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
5071 }
5072
5073
5074 inline static LRESULT
5075 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
5076 {
5077     if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
5078         ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
5079
5080     return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
5081 }
5082
5083
5084 static LRESULT
5085 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
5086 {
5087     TOOLBAR_INFO *infoPtr;
5088     LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
5089     DWORD styleadd = 0;
5090
5091     /* allocate memory for info structure */
5092     infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
5093     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
5094
5095     /* paranoid!! */
5096     infoPtr->dwStructSize = sizeof(TBBUTTON);
5097
5098     /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
5099     if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
5100         HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
5101         SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
5102     }
5103
5104     /* native control does:
5105      *    Get a lot of colors and brushes
5106      *    WM_NOTIFYFORMAT
5107      *    SystemParametersInfoA(0x1f, 0x3c, adr1, 0)
5108      *    CreateFontIndirectA(adr1)
5109      *    CreateBitmap(0x27, 0x24, 1, 1, 0)
5110      *    hdc = GetDC(toolbar)
5111      *    GetSystemMetrics(0x48)
5112      *    fnt2=CreateFontA(0xe, 0, 0, 0, 0x190, 0, 0, 0, 0, 2, 
5113      *                     0, 0, 0, 0, "MARLETT")
5114      *    oldfnt = SelectObject(hdc, fnt2)
5115      *    GetCharWidthA(hdc, 0x36, 0x36, adr2)
5116      *    GetTextMetricsA(hdc, adr3)
5117      *    SelectObject(hdc, oldfnt)
5118      *    DeleteObject(fnt2)
5119      *    ReleaseDC(hdc)
5120      *    InvalidateRect(toolbar, 0, 1)
5121      *    SetWindowLongA(toolbar, 0, addr)
5122      *    SetWindowLongA(toolbar, -16, xxx)  **sometimes**
5123      *                                          WM_STYLECHANGING
5124      *                             CallWinEx   old         new
5125      *                       ie 1  0x56000a4c  0x46000a4c  0x56008a4d
5126      *                       ie 2  0x4600094c  0x4600094c  0x4600894d
5127      *                       ie 3  0x56000b4c  0x46000b4c  0x56008b4d
5128      *                      rebar  0x50008844  0x40008844  0x50008845
5129      *                      pager  0x50000844  0x40000844  0x50008845
5130      *                    IC35mgr  0x5400084e  **nochange**
5131      *           on entry to _NCCREATE         0x5400084e
5132      *                    rowlist  0x5400004e  **nochange**
5133      *           on entry to _NCCREATE         0x5400004e
5134      *
5135      */
5136
5137     /* I think the code below is a bug, but it is the way that the native
5138      * controls seem to work. The effect is that if the user of TBSTYLE_FLAT
5139      * forgets to specify TBSTYLE_TRANSPARENT but does specify either
5140      * CCS_TOP or CCS_BOTTOM (_NOMOVEY and _TOP), then the control
5141      * does *not* set TBSTYLE_TRANSPARENT even though it should!!!!
5142      * Some how, the only cases of this seem to be MFC programs.
5143      *
5144      * Note also that the addition of _TRANSPARENT occurs *only* here. It
5145      * does not occur in the WM_STYLECHANGING routine.
5146      *    (Guy Albertelli   9/2001)
5147      *
5148      */
5149     if ((cs->style & TBSTYLE_FLAT) && !(cs->style & TBSTYLE_TRANSPARENT))
5150         styleadd |= TBSTYLE_TRANSPARENT;
5151     if (!(cs->style & (CCS_TOP | CCS_NOMOVEY))) {
5152         styleadd |= CCS_TOP;   /* default to top */
5153         SetWindowLongA (hwnd, GWL_STYLE, cs->style | styleadd);
5154     }
5155
5156     return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
5157 }
5158
5159
5160 static LRESULT
5161 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
5162 {
5163     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
5164     RECT rcWindow;
5165     HDC hdc;
5166
5167     if (dwStyle & WS_MINIMIZE)
5168         return 0; /* Nothing to do */
5169
5170     DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
5171
5172     if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
5173         return 0;
5174
5175     if (!(dwStyle & CCS_NODIVIDER))
5176     {
5177         GetWindowRect (hwnd, &rcWindow);
5178         OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
5179         if( dwStyle & WS_BORDER )
5180             OffsetRect (&rcWindow, 1, 1);
5181         DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
5182     }
5183
5184     ReleaseDC( hwnd, hdc );
5185
5186     return 0;
5187 }
5188
5189
5190 inline static LRESULT
5191 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
5192 {
5193     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
5194     LPNMHDR lpnmh = (LPNMHDR)lParam;
5195
5196     if (lpnmh->code == PGN_CALCSIZE) {
5197         LPNMPGCALCSIZE lppgc = (LPNMPGCALCSIZE)lParam;
5198
5199         if (lppgc->dwFlag == PGF_CALCWIDTH) {
5200             lppgc->iWidth = infoPtr->rcBound.right - infoPtr->rcBound.left;
5201             TRACE("processed PGN_CALCSIZE, returning horz size = %d\n", 
5202                   lppgc->iWidth);
5203         }
5204         else {
5205             lppgc->iHeight = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
5206             TRACE("processed PGN_CALCSIZE, returning vert size = %d\n", 
5207                   lppgc->iHeight);
5208         }
5209         return 0;
5210     }
5211
5212     if (lpnmh->code == PGN_SCROLL) {
5213         LPNMPGSCROLL lppgs = (LPNMPGSCROLL)lParam;
5214
5215         lppgs->iScroll = (lppgs->iDir & (PGF_SCROLLLEFT | PGF_SCROLLRIGHT)) ?
5216                           infoPtr->nButtonWidth : infoPtr->nButtonHeight;
5217         TRACE("processed PGN_SCROLL, returning scroll=%d, dir=%d\n",
5218               lppgs->iScroll, lppgs->iDir);
5219         return 0;
5220     }
5221
5222
5223     TRACE("passing WM_NOTIFY!\n");
5224
5225     if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
5226         if (infoPtr->bNtfUnicode)
5227             return SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, 
5228                                  wParam, lParam);
5229         else
5230             return SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, 
5231                                  wParam, lParam);
5232
5233 #if 0
5234         if (lpnmh->code == TTN_GETDISPINFOA) {
5235             LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
5236
5237             FIXME("retrieving ASCII string\n");
5238
5239         }
5240         else if (lpnmh->code == TTN_GETDISPINFOW) {
5241             LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
5242
5243             FIXME("retrieving UNICODE string\n");
5244
5245         }
5246 #endif
5247     }
5248
5249     return 0;
5250 }
5251
5252
5253 static LRESULT
5254 TOOLBAR_NotifyFormatFake(HWND hwnd, WPARAM wParam, LPARAM lParam)
5255 {
5256     /* remove this routine when Toolbar is improved to pass infoPtr
5257      * around instead of hwnd.
5258      */
5259     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
5260     return TOOLBAR_NotifyFormat(infoPtr, wParam, lParam);
5261 }
5262
5263
5264 static LRESULT
5265 TOOLBAR_NotifyFormat(TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
5266 {
5267     INT i;
5268
5269     if (lParam == NF_REQUERY) {
5270         i = SendMessageA(GetParent(infoPtr->hwndSelf),
5271                          WM_NOTIFYFORMAT, infoPtr->hwndSelf, NF_QUERY);
5272         if ((i < NFR_ANSI) || (i > NFR_UNICODE)) {
5273             ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n",
5274                 i);
5275             i = NFR_ANSI;
5276         }
5277         infoPtr->bNtfUnicode = (i == NFR_UNICODE) ? 1 : 0;
5278         return (LRESULT)i;
5279     }
5280     return (LRESULT)((infoPtr->bUnicode) ? NFR_UNICODE : NFR_ANSI);
5281 }
5282
5283
5284 static LRESULT
5285 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
5286 {
5287     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
5288     HDC hdc;
5289     PAINTSTRUCT ps;
5290
5291     /* fill ps.rcPaint with a default rect */
5292     memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound)); 
5293
5294     hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
5295
5296     TRACE("psrect=(%d,%d)-(%d,%d)\n",
5297           ps.rcPaint.left, ps.rcPaint.top,
5298           ps.rcPaint.right, ps.rcPaint.bottom);
5299
5300     TOOLBAR_Refresh (hwnd, hdc, &ps);
5301     if (!wParam) EndPaint (hwnd, &ps);
5302
5303     return 0;
5304 }
5305
5306
5307 static LRESULT
5308 TOOLBAR_SetRedraw (HWND hwnd, WPARAM wParam, LPARAM lParam)
5309      /*****************************************************
5310       *
5311       * Function;
5312       *  Handles the WM_SETREDRAW message.
5313       *
5314       * Documentation:
5315       *  According to testing V4.71 of COMCTL32 returns the 
5316       *  *previous* status of the redraw flag (either 0 or 1)
5317       *  instead of the MSDN documented value of 0 if handled.
5318       *  (For laughs see the "consistancy" with same function
5319       *   in rebar.)
5320       *
5321       *****************************************************/
5322 {
5323     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
5324     BOOL oldredraw = infoPtr->bDoRedraw;
5325
5326     TRACE("set to %s\n", 
5327           (wParam) ? "TRUE" : "FALSE");
5328     infoPtr->bDoRedraw = (BOOL) wParam;
5329     if (wParam) {
5330         InvalidateRect (infoPtr->hwndSelf, 0, TRUE);
5331     }
5332     return (oldredraw) ? 1 : 0;
5333 }
5334
5335
5336 static LRESULT
5337 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
5338 {
5339     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
5340     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
5341     RECT parent_rect;
5342     RECT window_rect;
5343     HWND parent;
5344     INT  x, y;
5345     INT  cx, cy;
5346     INT  flags;
5347     UINT uPosFlags = 0;
5348
5349     /* Resize deadlock check */
5350     if (infoPtr->bAutoSize) {
5351         infoPtr->bAutoSize = FALSE;
5352         return 0;
5353     }
5354
5355     /* FIXME: optimize to only update size if the new size doesn't */
5356     /* match the current size */
5357
5358     flags = (INT) wParam;
5359
5360     /* FIXME for flags =
5361      * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
5362      */
5363
5364     TRACE("sizing toolbar!\n");
5365
5366     if (flags == SIZE_RESTORED) {
5367         /* width and height don't apply */
5368         parent = GetParent (hwnd);
5369         GetClientRect(parent, &parent_rect);
5370         x = parent_rect.left;
5371         y = parent_rect.top;
5372
5373         if (dwStyle & CCS_NORESIZE) {
5374             uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
5375
5376             /*
5377              * this sets the working width of the toolbar, and
5378              * Calc Toolbar will not adjust it, only the height
5379              */
5380             infoPtr->nWidth = parent_rect.right - parent_rect.left; 
5381             cy = infoPtr->nHeight;
5382             cx = infoPtr->nWidth;
5383             TOOLBAR_CalcToolbar (hwnd);
5384             infoPtr->nWidth = cx;
5385             infoPtr->nHeight = cy;
5386         }
5387         else {
5388             infoPtr->nWidth = parent_rect.right - parent_rect.left;
5389             TOOLBAR_CalcToolbar (hwnd);
5390             cy = infoPtr->nHeight;
5391             cx = infoPtr->nWidth;
5392
5393             if (dwStyle & CCS_NOMOVEY) {
5394                 GetWindowRect(hwnd, &window_rect);
5395                 ScreenToClient(parent, (LPPOINT)&window_rect.left);
5396                 y = window_rect.top;
5397             }
5398         }
5399
5400         if (dwStyle & CCS_NOPARENTALIGN) {
5401             uPosFlags |= SWP_NOMOVE;
5402             cy = infoPtr->nHeight;
5403             cx = infoPtr->nWidth;
5404         }
5405
5406         if (!(dwStyle & CCS_NODIVIDER))
5407             cy += GetSystemMetrics(SM_CYEDGE);
5408
5409         if (dwStyle & WS_BORDER)
5410         {
5411             x = y = 1;
5412             cy += GetSystemMetrics(SM_CYEDGE);
5413             cx += GetSystemMetrics(SM_CYEDGE);
5414         }
5415
5416         SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
5417                         cx, cy, uPosFlags | SWP_NOZORDER);
5418     }
5419     return 0;
5420 }
5421
5422
5423 static LRESULT
5424 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
5425 {
5426     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
5427
5428     if (nType == GWL_STYLE) {
5429         if (lpStyle->styleNew & TBSTYLE_LIST) {
5430             infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
5431         }
5432         else {
5433             infoPtr->dwDTFlags = DT_CENTER;
5434         }
5435         infoPtr->bTransparent = (lpStyle->styleNew & TBSTYLE_TRANSPARENT);
5436         infoPtr->bBtnTranspnt = (lpStyle->styleNew & 
5437                                  (TBSTYLE_FLAT | TBSTYLE_LIST));
5438         TOOLBAR_CheckStyle (hwnd, lpStyle->styleNew);
5439     }
5440
5441     TOOLBAR_AutoSize (hwnd);
5442
5443     InvalidateRect(hwnd, NULL, FALSE);
5444
5445     return 0;
5446 }
5447
5448
5449 static LRESULT
5450 TOOLBAR_SysColorChange (HWND hwnd)
5451 {
5452     COMCTL32_RefreshSysColors();
5453
5454     return 0;
5455 }
5456
5457
5458
5459 static LRESULT WINAPI
5460 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5461 {
5462     TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", 
5463           hwnd, uMsg, /* SPY_GetMsgName(uMsg), */ wParam, lParam);
5464
5465     if (!TOOLBAR_GetInfoPtr(hwnd) && (uMsg != WM_NCCREATE))
5466         return DefWindowProcA( hwnd, uMsg, wParam, lParam );
5467
5468     switch (uMsg)
5469     {
5470         case TB_ADDBITMAP:
5471             return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
5472
5473         case TB_ADDBUTTONSA:
5474             return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
5475
5476         case TB_ADDBUTTONSW:
5477             return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
5478
5479         case TB_ADDSTRINGA:
5480             return TOOLBAR_AddStringA (hwnd, wParam, lParam);
5481
5482         case TB_ADDSTRINGW:
5483             return TOOLBAR_AddStringW (hwnd, wParam, lParam);
5484
5485         case TB_AUTOSIZE:
5486             return TOOLBAR_AutoSize (hwnd);
5487
5488         case TB_BUTTONCOUNT:
5489             return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
5490
5491         case TB_BUTTONSTRUCTSIZE:
5492             return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
5493
5494         case TB_CHANGEBITMAP:
5495             return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
5496
5497         case TB_CHECKBUTTON:
5498             return TOOLBAR_CheckButton (hwnd, wParam, lParam);
5499
5500         case TB_COMMANDTOINDEX:
5501             return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
5502
5503         case TB_CUSTOMIZE:
5504             return TOOLBAR_Customize (hwnd);
5505
5506         case TB_DELETEBUTTON:
5507             return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
5508
5509         case TB_ENABLEBUTTON:
5510             return TOOLBAR_EnableButton (hwnd, wParam, lParam);
5511
5512         case TB_GETANCHORHIGHLIGHT:
5513             return TOOLBAR_GetAnchorHighlight (hwnd);
5514
5515         case TB_GETBITMAP:
5516             return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
5517
5518         case TB_GETBITMAPFLAGS:
5519             return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
5520
5521         case TB_GETBUTTON:
5522             return TOOLBAR_GetButton (hwnd, wParam, lParam);
5523
5524         case TB_GETBUTTONINFOA:
5525             return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
5526
5527         case TB_GETBUTTONINFOW:
5528             return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
5529
5530         case TB_GETBUTTONSIZE:
5531             return TOOLBAR_GetButtonSize (hwnd);
5532
5533         case TB_GETBUTTONTEXTA:
5534             return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
5535
5536         case TB_GETBUTTONTEXTW:
5537             return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
5538
5539         case TB_GETDISABLEDIMAGELIST:
5540             return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
5541
5542         case TB_GETEXTENDEDSTYLE:
5543             return TOOLBAR_GetExtendedStyle (hwnd);
5544
5545         case TB_GETHOTIMAGELIST:
5546             return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
5547
5548         case TB_GETHOTITEM:
5549             return TOOLBAR_GetHotItem (hwnd);
5550
5551         case TB_GETIMAGELIST:
5552             return TOOLBAR_GetImageList (hwnd, wParam, lParam);
5553
5554 /*      case TB_GETINSERTMARK:                  */ /* 4.71 */
5555 /*      case TB_GETINSERTMARKCOLOR:             */ /* 4.71 */
5556
5557         case TB_GETITEMRECT:
5558             return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
5559
5560         case TB_GETMAXSIZE:
5561             return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
5562
5563 /*      case TB_GETOBJECT:                      */ /* 4.71 */
5564
5565         case TB_GETPADDING:
5566             return TOOLBAR_GetPadding (hwnd);
5567
5568         case TB_GETRECT:
5569             return TOOLBAR_GetRect (hwnd, wParam, lParam);
5570
5571         case TB_GETROWS:
5572             return TOOLBAR_GetRows (hwnd, wParam, lParam);
5573
5574         case TB_GETSTATE:
5575             return TOOLBAR_GetState (hwnd, wParam, lParam);
5576
5577         case TB_GETSTYLE:
5578             return TOOLBAR_GetStyle (hwnd, wParam, lParam);
5579
5580         case TB_GETTEXTROWS:
5581             return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
5582
5583         case TB_GETTOOLTIPS:
5584             return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
5585
5586         case TB_GETUNICODEFORMAT:
5587             return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
5588
5589         case TB_HIDEBUTTON:
5590             return TOOLBAR_HideButton (hwnd, wParam, lParam);
5591
5592         case TB_HITTEST:
5593             return TOOLBAR_HitTest (hwnd, wParam, lParam);
5594
5595         case TB_INDETERMINATE:
5596             return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
5597
5598         case TB_INSERTBUTTONA:
5599             return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
5600
5601         case TB_INSERTBUTTONW:
5602             return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
5603
5604 /*      case TB_INSERTMARKHITTEST:              */ /* 4.71 */
5605
5606         case TB_ISBUTTONCHECKED:
5607             return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
5608
5609         case TB_ISBUTTONENABLED:
5610             return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
5611
5612         case TB_ISBUTTONHIDDEN:
5613             return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
5614
5615         case TB_ISBUTTONHIGHLIGHTED:
5616             return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
5617
5618         case TB_ISBUTTONINDETERMINATE:
5619             return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
5620
5621         case TB_ISBUTTONPRESSED:
5622             return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
5623
5624         case TB_LOADIMAGES:                        /* 4.70 */
5625             FIXME("missing standard imagelists\n");
5626             return 0;
5627
5628 /*      case TB_MAPACCELERATORA:                */ /* 4.71 */
5629 /*      case TB_MAPACCELERATORW:                */ /* 4.71 */
5630 /*      case TB_MARKBUTTON:                     */ /* 4.71 */
5631 /*      case TB_MOVEBUTTON:                     */ /* 4.71 */
5632
5633         case TB_PRESSBUTTON:
5634             return TOOLBAR_PressButton (hwnd, wParam, lParam);
5635
5636         case TB_REPLACEBITMAP:
5637             return TOOLBAR_ReplaceBitmap (hwnd, wParam, lParam);
5638
5639         case TB_SAVERESTOREA:
5640             return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
5641
5642         case TB_SAVERESTOREW:
5643             return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
5644
5645         case TB_SETANCHORHIGHLIGHT:
5646             return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
5647
5648         case TB_SETBITMAPSIZE:
5649             return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
5650
5651         case TB_SETBUTTONINFOA:
5652             return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
5653
5654         case TB_SETBUTTONINFOW:
5655             return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
5656
5657         case TB_SETBUTTONSIZE:
5658             return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
5659
5660         case TB_SETBUTTONWIDTH:
5661             return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
5662
5663         case TB_SETCMDID:
5664             return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
5665
5666         case TB_SETDISABLEDIMAGELIST:
5667             return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
5668
5669         case TB_SETDRAWTEXTFLAGS:
5670             return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
5671
5672         case TB_SETEXTENDEDSTYLE:
5673             return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
5674
5675         case TB_SETHOTIMAGELIST:
5676             return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
5677
5678         case TB_SETHOTITEM:
5679             return TOOLBAR_SetHotItem (hwnd, wParam);
5680
5681         case TB_SETIMAGELIST:
5682             return TOOLBAR_SetImageList (hwnd, wParam, lParam);
5683
5684         case TB_SETINDENT:
5685             return TOOLBAR_SetIndent (hwnd, wParam, lParam);
5686
5687 /*      case TB_SETINSERTMARK:                  */ /* 4.71 */
5688
5689         case TB_SETINSERTMARKCOLOR:
5690             return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
5691
5692         case TB_SETMAXTEXTROWS:
5693             return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
5694
5695         case TB_SETPADDING:
5696             return TOOLBAR_SetPadding (hwnd, wParam, lParam);
5697
5698         case TB_SETPARENT:
5699             return TOOLBAR_SetParent (hwnd, wParam, lParam);
5700
5701         case TB_SETROWS:
5702             return TOOLBAR_SetRows (hwnd, wParam, lParam);
5703
5704         case TB_SETSTATE:
5705             return TOOLBAR_SetState (hwnd, wParam, lParam);
5706
5707         case TB_SETSTYLE:
5708             return TOOLBAR_SetStyle (hwnd, wParam, lParam);
5709
5710         case TB_SETTOOLTIPS:
5711             return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
5712
5713         case TB_SETUNICODEFORMAT:
5714             return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
5715
5716         case TB_UNKWN45E:
5717             return TOOLBAR_Unkwn45E (hwnd, wParam, lParam);
5718
5719         case TB_UNKWN463:
5720             return TOOLBAR_Unkwn463 (hwnd, wParam, lParam);
5721
5722
5723 /* Common Control Messages */
5724
5725 /*      case TB_GETCOLORSCHEME:                 */ /* identical to CCM_ */
5726         case CCM_GETCOLORSCHEME:
5727             return TOOLBAR_GetColorScheme (hwnd, (LPCOLORSCHEME)lParam);
5728
5729 /*      case TB_SETCOLORSCHEME:                 */ /* identical to CCM_ */
5730         case CCM_SETCOLORSCHEME:
5731             return TOOLBAR_SetColorScheme (hwnd, (LPCOLORSCHEME)lParam);
5732
5733         case CCM_GETVERSION:
5734             return TOOLBAR_GetVersion (hwnd);
5735
5736         case CCM_SETVERSION:
5737             return TOOLBAR_SetVersion (hwnd, (INT)wParam);
5738
5739
5740 /*      case WM_CHAR: */
5741
5742         case WM_CREATE:
5743             return TOOLBAR_Create (hwnd, wParam, lParam);
5744
5745         case WM_DESTROY:
5746           return TOOLBAR_Destroy (hwnd, wParam, lParam);
5747
5748         case WM_ERASEBKGND:
5749             return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
5750
5751         case WM_GETFONT:
5752                 return TOOLBAR_GetFont (hwnd, wParam, lParam);
5753
5754 /*      case WM_KEYDOWN: */
5755 /*      case WM_KILLFOCUS: */
5756
5757         case WM_LBUTTONDBLCLK:
5758             return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
5759
5760         case WM_LBUTTONDOWN:
5761             return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
5762
5763         case WM_LBUTTONUP:
5764             return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
5765
5766         case WM_MOUSEMOVE:
5767             return TOOLBAR_MouseMove (hwnd, wParam, lParam);
5768
5769         case WM_MOUSELEAVE:
5770             return TOOLBAR_MouseLeave (hwnd, wParam, lParam);   
5771
5772         case WM_CAPTURECHANGED:
5773             return TOOLBAR_CaptureChanged(hwnd);        
5774
5775         case WM_NCACTIVATE:
5776             return TOOLBAR_NCActivate (hwnd, wParam, lParam);
5777
5778         case WM_NCCALCSIZE:
5779             return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
5780
5781         case WM_NCCREATE:
5782             return TOOLBAR_NCCreate (hwnd, wParam, lParam);
5783
5784         case WM_NCPAINT:
5785             return TOOLBAR_NCPaint (hwnd, wParam, lParam);
5786
5787         case WM_NOTIFY:
5788             return TOOLBAR_Notify (hwnd, wParam, lParam);
5789
5790         case WM_NOTIFYFORMAT:
5791             TOOLBAR_NotifyFormatFake (hwnd, wParam, lParam);
5792
5793         case WM_PAINT:
5794             return TOOLBAR_Paint (hwnd, wParam);
5795
5796         case WM_SETREDRAW:
5797             return TOOLBAR_SetRedraw (hwnd, wParam, lParam);
5798
5799         case WM_SIZE:
5800             return TOOLBAR_Size (hwnd, wParam, lParam);
5801
5802         case WM_STYLECHANGED:
5803             return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
5804
5805         case WM_SYSCOLORCHANGE:
5806             return TOOLBAR_SysColorChange (hwnd);
5807
5808 /*      case WM_WININICHANGE: */
5809
5810         case WM_CHARTOITEM:
5811         case WM_COMMAND:
5812         case WM_DRAWITEM:
5813         case WM_MEASUREITEM:
5814         case WM_VKEYTOITEM:
5815             {
5816                 TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
5817                 if(infoPtr != NULL)
5818                     return SendMessageA (infoPtr->hwndNotify, uMsg, wParam, lParam);
5819                 else
5820                     return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
5821             }
5822
5823         /* We see this in Outlook Express 5.x and just does DefWindowProc */
5824         case PGM_FORWARDMOUSE:
5825             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
5826
5827         default:
5828             if (uMsg >= WM_USER)
5829                 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
5830                      uMsg, wParam, lParam);
5831             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
5832     }
5833     return 0;
5834 }
5835
5836
5837 VOID
5838 TOOLBAR_Register (void)
5839 {
5840     WNDCLASSA wndClass;
5841
5842     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
5843     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
5844     wndClass.lpfnWndProc   = (WNDPROC)ToolbarWindowProc;
5845     wndClass.cbClsExtra    = 0;
5846     wndClass.cbWndExtra    = sizeof(TOOLBAR_INFO *);
5847     wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
5848     wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
5849     wndClass.lpszClassName = TOOLBARCLASSNAMEA;
5850  
5851     RegisterClassA (&wndClass);
5852 }
5853
5854
5855 VOID
5856 TOOLBAR_Unregister (void)
5857 {
5858     UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);
5859 }