Removed some unnecessary includes.
[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  * TODO:
8  *   - A little bug in TOOLBAR_DrawMasked()
9  *   - Button wrapping (under construction).
10  *   - Messages.
11  *   - Notifications (under construction).
12  *   - Fix TB_SETROWS.
13  *   - Tooltip support (almost complete).
14  *   - Unicode suppport (under construction).
15  *   - Fix TOOLBAR_SetButtonInfo32A/W.
16  *   - TBSTYLE_AUTOSIZE for toolbar and buttons.
17  *   - I_IMAGECALLBACK support.
18  *   - iString of -1 is undocumented
19  *   - Customization dialog:
20  *      - Add flat look.
21  *      - Minor buglet in 'available buttons' list:
22  *        Buttons are not listed in M$-like order. M$ seems to use a single
23  *        internal list to store the button information of both listboxes.
24  *      - Drag list support.
25  *      - Help and Reset button support.
26  *
27  * Testing:
28  *   - Run tests using Waite Group Windows95 API Bible Volume 2.
29  *     The second cdrom contains executables addstr.exe, btncount.exe,
30  *     btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
31  *     enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
32  *     indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
33  *     setparnt.exe, setrows.exe, toolwnd.exe.
34  *   - Microsofts controlspy examples.
35  *   - Charles Petzold's 'Programming Windows': gadgets.exe
36  */
37
38 #include <string.h>
39
40 #include "winbase.h"
41 #include "windef.h"
42 #include "wingdi.h"
43 #include "winuser.h"
44 #include "wine/unicode.h"
45 #include "commctrl.h"
46 #include "imagelist.h"
47 #include "comctl32.h"
48 #include "debugtools.h"
49
50 DEFAULT_DEBUG_CHANNEL(toolbar);
51
52 typedef struct
53 {
54     INT iBitmap;
55     INT idCommand;
56     BYTE  fsState;
57     BYTE  fsStyle;
58     DWORD dwData;
59     INT iString;
60
61     BOOL bHot;
62     INT nRow;
63     RECT rect;
64 } TBUTTON_INFO; 
65
66 typedef struct
67 {
68     DWORD      dwStructSize;   /* size of TBBUTTON struct */
69     INT      nHeight;        /* height of the toolbar */
70     INT      nWidth;         /* width of the toolbar */
71     INT      nButtonHeight;
72     INT      nButtonWidth;
73     INT      nBitmapHeight;
74     INT      nBitmapWidth;
75     INT      nIndent;
76     INT      nRows;           /* number of button rows */
77     INT      nMaxTextRows;    /* maximum number of text rows */
78     INT      cxMin;           /* minimum button width */
79     INT      cxMax;           /* maximum button width */
80     INT      nNumButtons;     /* number of buttons */
81     INT      nNumBitmaps;     /* number of bitmaps */
82     INT      nNumStrings;     /* number of strings */
83     BOOL     bUnicode;        /* ASCII (FALSE) or Unicode (TRUE)? */
84     BOOL     bCaptured;       /* mouse captured? */
85     INT      nButtonDown;
86     INT      nOldHit;
87     INT      nHotItem;        /* index of the "hot" item */
88     HFONT    hFont;           /* text font */
89     HIMAGELIST himlInt;         /* image list created internally */
90     HIMAGELIST himlDef;         /* default image list */
91     HIMAGELIST himlHot;         /* hot image list */
92     HIMAGELIST himlDis;         /* disabled image list */
93     HWND     hwndToolTip;     /* handle to tool tip control */
94     HWND     hwndNotify;      /* handle to the window that gets notifications */
95     BOOL     bTransparent;    /* background transparency flag */
96     BOOL     bAutoSize;       /* auto size deadlock indicator */
97     BOOL     bAnchor;         /* anchor highlight enabled */
98     DWORD      dwExStyle;       /* extended toolbar style */
99     DWORD      dwDTFlags;       /* DrawText flags */
100
101     COLORREF   clrInsertMark;   /* insert mark color */
102     RECT     rcBound;         /* bounding rectangle */
103     INT      iVersion;
104
105     TBUTTON_INFO *buttons;      /* pointer to button array */
106     LPWSTR       *strings;      /* pointer to string array */
107 } TOOLBAR_INFO, *PTOOLBAR_INFO;
108
109
110 /* used by customization dialog */
111 typedef struct
112 {
113     PTOOLBAR_INFO tbInfo;
114     HWND          tbHwnd;
115 } CUSTDLG_INFO, *PCUSTDLG_INFO;
116
117 typedef struct
118 {
119     TBBUTTON btn;
120     BOOL     bVirtual;
121     BOOL     bRemovable;
122     CHAR     text[64];
123 } CUSTOMBUTTON, *PCUSTOMBUTTON;
124
125
126 #define SEPARATOR_WIDTH    8
127 #define TOP_BORDER         2
128 #define BOTTOM_BORDER      2
129 #define DDARROW_WIDTH      11 
130
131 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
132 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
133 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
134
135 static LPWSTR
136 TOOLBAR_GetText(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
137 {
138     LPWSTR lpText = NULL;
139
140     /* FIXME: iString == -1 is undocumented */
141     if ((HIWORD(btnPtr->iString) != 0) && (btnPtr->iString != -1))
142         lpText = (LPWSTR)btnPtr->iString;
143     else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
144         lpText = infoPtr->strings[btnPtr->iString];
145     
146     return lpText;
147 }
148
149 static BOOL 
150 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
151 {
152     if ((index>=0) && (index < infoPtr->nNumBitmaps))
153       return TRUE;
154     else
155       return FALSE;
156 }
157
158
159 static void
160 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
161 {
162     INT x = (lpRect->left + lpRect->right) / 2 - 1;
163     INT yBottom = lpRect->bottom - 3;
164     INT yTop = lpRect->top + 1;
165
166     SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
167     MoveToEx (hdc, x, yBottom, NULL);
168     LineTo (hdc, x, yTop);
169     x++;
170     SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
171     MoveToEx (hdc, x, yBottom, NULL);
172     LineTo (hdc, x, yTop);
173 }
174
175 static void
176 TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, INT colorRef)
177 {
178     INT x, y;
179     SelectObject ( hdc, GetSysColorPen (colorRef));
180     x = left + 2;
181     y = top + 8;
182     MoveToEx (hdc, x, y, NULL);
183     LineTo (hdc, x+5, y++); x++;
184     MoveToEx (hdc, x, y, NULL);
185     LineTo (hdc, x+3, y++); x++;
186     MoveToEx (hdc, x, y, NULL);
187     LineTo (hdc, x+1, y++);
188 }
189
190 /*
191  * Draw the text string for this button.
192  * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
193  *      is non-zero, so we can simply check himlDef to see if we have
194  *      an image list
195  */
196 static void
197 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
198                     HDC hdc, INT nState, DWORD dwStyle)
199 {
200     RECT   rcText = btnPtr->rect;
201     HFONT  hOldFont;
202     INT    nOldBkMode;
203     COLORREF clrOld;
204     LPWSTR lpText = NULL;
205     HIMAGELIST himl = infoPtr->himlDef;
206
207     TRACE ("iString: %x\n", btnPtr->iString);
208
209     /* get a pointer to the text */
210     lpText = TOOLBAR_GetText(infoPtr, btnPtr);
211
212     TRACE ("lpText: %s\n", debugstr_w(lpText));
213
214     /* draw text */
215     if (lpText) {
216
217         InflateRect (&rcText, -3, -3);
218
219         if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
220                 if ((dwStyle & TBSTYLE_LIST) &&
221                     ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
222                     (btnPtr->iBitmap != I_IMAGENONE)) {
223                     rcText.left += infoPtr->nBitmapWidth;
224                 }
225                 else {
226                     rcText.top += infoPtr->nBitmapHeight;
227                 }
228         }
229
230         if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
231             OffsetRect (&rcText, 1, 1);
232
233         hOldFont = SelectObject (hdc, infoPtr->hFont);
234         nOldBkMode = SetBkMode (hdc, TRANSPARENT);
235         if (!(nState & TBSTATE_ENABLED)) {
236             clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
237             OffsetRect (&rcText, 1, 1);
238             DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
239             SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
240             OffsetRect (&rcText, -1, -1);
241             DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
242         }
243         else if (nState & TBSTATE_INDETERMINATE) {
244             clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
245             DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
246         }
247         else {
248             clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
249             DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
250         }
251
252         SetTextColor (hdc, clrOld);
253         SelectObject (hdc, hOldFont);
254         if (nOldBkMode != TRANSPARENT)
255             SetBkMode (hdc, nOldBkMode);
256     }
257 }
258
259
260 static void
261 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
262 {
263     HBRUSH hbr = SelectObject (hdc, COMCTL32_hPattern55AABrush);
264     INT cx = lpRect->right - lpRect->left;
265     INT cy = lpRect->bottom - lpRect->top;
266     PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
267     SelectObject (hdc, hbr);
268 }
269
270
271 static void
272 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
273                     HDC hdc, INT x, INT y)
274 {
275     /* FIXME: this function is a hack since it uses image list
276               internals directly */
277
278     HIMAGELIST himl = infoPtr->himlDef;
279     HBITMAP hbmMask;
280     HDC hdcImageList;
281     HDC hdcMask;
282
283     if (!himl)
284         return;
285
286     /* create new dc's */
287     hdcImageList = CreateCompatibleDC (0);
288     hdcMask = CreateCompatibleDC (0);
289
290     /* create new bitmap */
291     hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
292     SelectObject (hdcMask, hbmMask);
293
294     /* copy the mask bitmap */
295     SelectObject (hdcImageList, himl->hbmMask);
296     SetBkColor (hdcImageList, RGB(255, 255, 255));
297     SetTextColor (hdcImageList, RGB(0, 0, 0));
298     BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
299               hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
300
301     /* draw the new mask */
302     SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
303     BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
304               hdcMask, 0, 0, 0xB8074A);
305
306     SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
307     BitBlt (hdc, x, y, himl->cx, himl->cy,
308               hdcMask, 0, 0, 0xB8074A);
309
310     DeleteObject (hbmMask);
311     DeleteDC (hdcMask);
312     DeleteDC (hdcImageList);
313 }
314
315
316 static void
317 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
318 {
319     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
320     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
321     BOOL hasDropDownArrow = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
322                             (btnPtr->fsStyle & TBSTYLE_DROPDOWN);
323     RECT rc, rcArrow, rcBitmap;
324
325     if (btnPtr->fsState & TBSTATE_HIDDEN)
326         return;
327
328     rc = btnPtr->rect;
329     CopyRect (&rcArrow, &rc);
330     CopyRect(&rcBitmap, &rc);
331
332     FillRect( hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
333
334     if (hasDropDownArrow)
335     {
336         if (dwStyle & TBSTYLE_FLAT)
337             rc.right = max(rc.left, rc.right - DDARROW_WIDTH);
338         else
339             rc.right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
340         rcArrow.left = rc.right; 
341     }
342
343     /* Center the bitmap horizontally and vertically */
344     rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;
345
346     if(TOOLBAR_HasText(infoPtr, btnPtr))
347         rcBitmap.top+=2; /* this looks to be the correct value from vmware comparison - cmm */
348     else
349         rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;
350
351     TRACE("iBitmap: %d\n", btnPtr->iBitmap);
352
353     /* separator */
354     if (btnPtr->fsStyle & TBSTYLE_SEP) {
355         /* with the FLAT style, iBitmap is the width and has already */
356         /* been taken into consideration in calculating the width    */
357         /* so now we need to draw the vertical separator             */
358         /* empirical tests show that iBitmap can/will be non-zero    */
359         /* when drawing the vertical bar...      */
360         if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */)
361             TOOLBAR_DrawFlatSeparator (&rc, hdc);
362         return;
363     }
364
365     /* disabled */
366     if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
367         if (!(dwStyle & TBSTYLE_FLAT))
368         {
369             DrawEdge (hdc, &rc, EDGE_RAISED,
370                       BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
371             if (hasDropDownArrow)
372             DrawEdge (hdc, &rcArrow, EDGE_RAISED,
373                       BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
374         }
375         
376         if (hasDropDownArrow)
377         {
378             TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1, COLOR_3DHIGHLIGHT);
379             TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_3DSHADOW);
380         }
381
382         if (infoPtr->himlDis && 
383             TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
384             ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
385                         rcBitmap.left, rcBitmap.top, ILD_NORMAL);
386         else
387             TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
388
389         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
390         return;
391     }
392
393     /* pressed TBSTYLE_BUTTON */
394     if (btnPtr->fsState & TBSTATE_PRESSED) {
395         if (dwStyle & TBSTYLE_FLAT)
396         {
397             DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
398             if (hasDropDownArrow)
399             DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
400         }
401         else
402         {
403             DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
404             if (hasDropDownArrow)
405             DrawEdge (hdc, &rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
406         }
407
408         if (hasDropDownArrow)
409             TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
410
411         if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
412             ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
413                         rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
414
415         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
416         return;
417     }
418
419     /* checked TBSTYLE_CHECK */
420     if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
421         (btnPtr->fsState & TBSTATE_CHECKED)) {
422         if (dwStyle & TBSTYLE_FLAT)
423             DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
424                         BF_RECT | BF_MIDDLE | BF_ADJUST);
425         else
426             DrawEdge (hdc, &rc, EDGE_SUNKEN,
427                         BF_RECT | BF_MIDDLE | BF_ADJUST);
428
429         TOOLBAR_DrawPattern (hdc, &rc);
430         
431         if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
432             ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
433                         rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
434         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
435         return;
436     }
437
438     /* indeterminate */ 
439     if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
440         DrawEdge (hdc, &rc, EDGE_RAISED,
441                     BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
442
443         TOOLBAR_DrawPattern (hdc, &rc);
444         TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
445         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
446         return;
447     }
448
449     /* normal state */
450     if (dwStyle & TBSTYLE_FLAT)
451     {
452         if (btnPtr->bHot)
453         {
454             DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
455             if (hasDropDownArrow)
456             DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
457         }
458         else
459         {
460             FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
461             if (hasDropDownArrow)
462             FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
463         }
464
465         if (hasDropDownArrow)
466             TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
467
468         if (btnPtr->bHot && infoPtr->himlHot &&
469             TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
470             ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
471                         rcBitmap.left, rcBitmap.top, ILD_NORMAL);
472         else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
473             ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
474                         rcBitmap.left, rcBitmap.top, ILD_NORMAL);
475     }
476     else
477     {
478         DrawEdge (hdc, &rc, EDGE_RAISED,
479                 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
480
481         if (hasDropDownArrow)
482         {
483             DrawEdge (hdc, &rcArrow, EDGE_RAISED,
484                     BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
485             TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
486         }
487
488         if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
489             ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
490                         rcBitmap.left, rcBitmap.top, ILD_NORMAL);
491     }
492
493     TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
494 }
495
496
497 static void
498 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
499 {
500     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
501     TBUTTON_INFO *btnPtr;
502     INT i;
503     RECT rcTemp;
504
505     /* if imagelist belongs to the app, it can be changed
506        by the app after setting it */
507     if (infoPtr->himlDef != infoPtr->himlInt)
508         infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
509     /* redraw necessary buttons */
510     btnPtr = infoPtr->buttons;
511     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
512     {
513         if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
514             TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
515     }
516 }
517
518 static void
519 TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
520 {
521     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
522     TBUTTON_INFO *btnPtr;
523     HDC hdc;
524     HFONT hOldFont;
525
526     lpSize->cx = 0;
527     lpSize->cy = 0;
528     hdc = GetDC (0);
529     hOldFont = SelectObject (hdc, infoPtr->hFont);
530
531     btnPtr = &infoPtr->buttons[index];
532
533     if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
534          (btnPtr->iString > -1) &&
535          (btnPtr->iString < infoPtr->nNumStrings)) 
536     {
537         LPWSTR lpText = infoPtr->strings[btnPtr->iString];
538         GetTextExtentPoint32W (hdc, lpText, strlenW (lpText), lpSize);
539     }
540
541     SelectObject (hdc, hOldFont);
542     ReleaseDC (0, hdc);
543
544     TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
545 }
546
547 static void
548 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
549 {
550     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
551     TBUTTON_INFO *btnPtr;
552     INT i;
553     SIZE sz;
554
555
556     lpSize->cx = 0;
557     lpSize->cy = 0;
558
559     btnPtr = infoPtr->buttons;
560     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
561         if(TOOLBAR_HasText(infoPtr, btnPtr))
562         {
563             TOOLBAR_MeasureString(hwnd,i,&sz);
564             if (sz.cx > lpSize->cx)
565                 lpSize->cx = sz.cx;
566             if (sz.cy > lpSize->cy)
567                 lpSize->cy = sz.cy;
568         }
569     }
570
571     TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
572 }
573
574 /***********************************************************************
575 *               TOOLBAR_WrapToolbar
576 *
577 * This function walks through the buttons and seperators in the 
578 * toolbar, and sets the TBSTATE_WRAP flag only on those items where 
579 * wrapping should occur based on the width of the toolbar window.  
580 * It does *not* calculate button placement itself.  That task 
581 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage 
582 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE 
583 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
584 */ 
585
586 static void
587 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
588 {
589     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
590     TBUTTON_INFO *btnPtr;
591     INT x, cx, i, j;
592     RECT rc;
593     BOOL bWrap, bButtonWrap;
594
595     /*  When the toolbar window style is not TBSTYLE_WRAPABLE,  */ 
596     /*  no layout is necessary. Applications may use this style */
597     /*  to perform their own layout on the toolbar.             */
598     if( !(dwStyle & TBSTYLE_WRAPABLE) )
599         return;
600
601     btnPtr = infoPtr->buttons;
602     x  = infoPtr->nIndent;
603
604     /* this can get the parents width, to know how far we can extend
605      * this toolbar.  We cannot use its height, as there may be multiple
606      * toolbars in a rebar control
607      */
608     GetClientRect( GetParent(hwnd), &rc );
609     infoPtr->nWidth = rc.right - rc.left;
610     bButtonWrap = FALSE;
611
612     for (i = 0; i < infoPtr->nNumButtons; i++ )
613     {
614         bWrap = FALSE;
615         btnPtr[i].fsState &= ~TBSTATE_WRAP;
616         
617         if (btnPtr[i].fsState & TBSTATE_HIDDEN)
618             continue;
619
620         /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
621         /* it is the actual width of the separator. This is used for */
622         /* custom controls in toolbars.                              */
623         if (btnPtr[i].fsStyle & TBSTYLE_SEP)
624             cx = (btnPtr[i].iBitmap > 0) ?  
625                         btnPtr[i].iBitmap : SEPARATOR_WIDTH;
626         else
627             cx = infoPtr->nButtonWidth;
628
629         /* Two or more adjacent separators form a separator group.   */ 
630         /* The first separator in a group should be wrapped to the   */
631         /* next row if the previous wrapping is on a button.         */
632         if( bButtonWrap &&
633                 (btnPtr[i].fsStyle & TBSTYLE_SEP) && 
634                 (i + 1 < infoPtr->nNumButtons ) &&
635                 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) ) 
636         {
637             btnPtr[i].fsState |= TBSTATE_WRAP;
638             x = infoPtr->nIndent;
639             i++;
640             bButtonWrap = FALSE;
641             continue;
642         }
643
644         /* The layout makes sure the bitmap is visible, but not the button. */
645         if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2 
646                  > infoPtr->nWidth ) 
647         {
648             BOOL bFound = FALSE;
649
650             /*  If the current button is a separator and not hidden,  */ 
651             /*  go to the next until it reaches a non separator.      */
652             /*  Wrap the last separator if it is before a button.     */
653             while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) || 
654                         (btnPtr[i].fsState & TBSTATE_HIDDEN) ) && 
655                         i < infoPtr->nNumButtons )
656             {
657                 i++;
658                 bFound = TRUE;
659             }
660     
661             if( bFound && i < infoPtr->nNumButtons )
662             {
663                 i--;
664                 btnPtr[i].fsState |= TBSTATE_WRAP;
665                 x = infoPtr->nIndent;
666                 bButtonWrap = FALSE;
667                 continue;
668             }
669             else if ( i >= infoPtr->nNumButtons)
670                 break;
671
672             /*  If the current button is not a separator, find the last  */ 
673             /*  separator and wrap it.                                   */
674             for ( j = i - 1; j >= 0  &&  !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
675             {
676                 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
677                         !(btnPtr[j].fsState & TBSTATE_HIDDEN))
678                 {
679                     bFound = TRUE; 
680                     i = j; 
681                     x = infoPtr->nIndent;
682                     btnPtr[j].fsState |= TBSTATE_WRAP;
683                     bButtonWrap = FALSE; 
684                     break;
685                 }
686             }
687
688             /*  If no separator available for wrapping, wrap one of     */
689             /*  non-hidden previous button.                             */
690             if (!bFound)
691             {
692                 for ( j = i - 1; 
693                         j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
694                 {
695                     if (btnPtr[j].fsState & TBSTATE_HIDDEN) 
696                         continue;
697
698                     bFound = TRUE; 
699                     i = j; 
700                     x = infoPtr->nIndent;
701                     btnPtr[j].fsState |= TBSTATE_WRAP;
702                     bButtonWrap = TRUE;
703                     break;
704                 }
705             }
706
707             /* If all above failed, wrap the current button. */
708             if (!bFound)  
709             {
710                 btnPtr[i].fsState |= TBSTATE_WRAP;
711                 bFound = TRUE;
712                 x = infoPtr->nIndent;
713                 if (btnPtr[i].fsState & TBSTYLE_SEP )
714                     bButtonWrap = FALSE;
715                 else
716                     bButtonWrap = TRUE;
717             }               
718         }
719         else
720             x += cx;
721     }
722 }
723
724
725 /***********************************************************************
726 *               TOOLBAR_CalcToolbar
727 *
728 * This function calculates button and separator placement. It first 
729 * calculates the button sizes, gets the toolbar window width and then 
730 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap 
731 * on. It assigns a new location to each item and sends this location to
732 * the tooltip window if appropriate. Finally, it updates the rcBound 
733 * rect and calculates the new required toolbar window height. 
734 */  
735
736 static void
737 TOOLBAR_CalcToolbar (HWND hwnd)
738 {
739     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
740     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
741     TBUTTON_INFO *btnPtr;
742     INT i, nRows, nSepRows;
743     INT x, y, cx, cy;
744     SIZE  sizeString;
745     BOOL bWrap;
746     BOOL usesBitmaps = FALSE;
747     BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
748
749     TOOLBAR_CalcStrings (hwnd, &sizeString);
750
751     if (dwStyle & TBSTYLE_LIST)
752     {
753         infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
754         infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
755     }
756     else {
757         for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
758         {
759             if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
760                 usesBitmaps = TRUE;
761         }
762
763         if (sizeString.cy > 0)
764         {
765             if (usesBitmaps)
766               infoPtr->nButtonHeight = sizeString.cy +
767                   infoPtr->nBitmapHeight + 6;
768             else 
769                 infoPtr->nButtonHeight = sizeString.cy + 6;
770         }
771         else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
772             infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
773
774         if (sizeString.cx > infoPtr->nBitmapWidth)
775             infoPtr->nButtonWidth = sizeString.cx + 6;
776         else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
777             infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
778     }
779
780     if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
781         infoPtr->nButtonWidth = infoPtr->cxMin;
782     if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
783         infoPtr->nButtonWidth = infoPtr->cxMax;
784
785     TOOLBAR_WrapToolbar( hwnd, dwStyle );
786
787     x  = infoPtr->nIndent;
788     y  = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
789
790    /*
791     * We will set the height below, and we set the width on entry 
792     * so we do not reset them here.. 
793     */
794 #if 0
795     GetClientRect( hwnd, &rc );
796     /* get initial values for toolbar */
797     infoPtr->nWidth  = rc.right - rc.left;
798     infoPtr->nHeight = rc.bottom - rc.top;
799 #endif
800
801     /* from above, minimum is a button, and possible text */
802     cx = infoPtr->nButtonWidth;
803
804     /* cannot use just ButtonHeight, we may have no buttons! */
805     if (infoPtr->nNumButtons > 0)
806         infoPtr->nHeight = infoPtr->nButtonHeight;
807
808     cy = infoPtr->nHeight;
809
810     nRows = nSepRows = 0;
811
812     infoPtr->rcBound.top = y;
813     infoPtr->rcBound.left = x;
814     infoPtr->rcBound.bottom = y + cy;
815     infoPtr->rcBound.right = x;
816
817     btnPtr = infoPtr->buttons;
818
819     /* do not base height/width on parent, if the parent is a */
820     /* rebar control it could have multiple rows of toolbars  */
821 /*    GetClientRect( GetParent(hwnd), &rc ); */
822 /*    cx = rc.right - rc.left; */
823 /*    cy = rc.bottom - rc.top; */
824
825     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
826     {
827         bWrap = FALSE;
828         if (btnPtr->fsState & TBSTATE_HIDDEN)
829         {
830             SetRectEmpty (&btnPtr->rect);
831             continue;
832         }
833
834             /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
835             /* it is the actual width of the separator. This is used for */
836             /* custom controls in toolbars.                              */
837         if (btnPtr->fsStyle & TBSTYLE_SEP)
838                 cx = (btnPtr->iBitmap > 0) ?
839                      btnPtr->iBitmap : SEPARATOR_WIDTH;
840         else
841         {
842             if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE) 
843             {
844               SIZE sz;
845               TOOLBAR_MeasureString(hwnd,i,&sz);
846               cx = sz.cx + 6;
847             }
848             else
849               cx = infoPtr->nButtonWidth;
850
851             if (hasDropDownArrows && (btnPtr->fsStyle & TBSTYLE_DROPDOWN))
852               cx += DDARROW_WIDTH; 
853         }
854         cy = infoPtr->nHeight;
855
856         if (btnPtr->fsState & TBSTATE_WRAP )
857                     bWrap = TRUE;
858
859         SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
860
861         if (infoPtr->rcBound.left > x)
862             infoPtr->rcBound.left = x;
863         if (infoPtr->rcBound.right < x + cx)
864             infoPtr->rcBound.right = x + cx;
865         if (infoPtr->rcBound.bottom < y + cy)
866             infoPtr->rcBound.bottom = y + cy;
867
868         /* Set the toolTip only for non-hidden, non-separator button */
869         if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP )) 
870         {
871             TTTOOLINFOA ti;
872
873             ZeroMemory (&ti, sizeof(TTTOOLINFOA));
874             ti.cbSize = sizeof(TTTOOLINFOA);
875             ti.hwnd = hwnd;
876             ti.uId = btnPtr->idCommand;
877             ti.rect = btnPtr->rect;
878             SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
879                             0, (LPARAM)&ti);
880         }
881
882         /* btnPtr->nRow is zero based. The space between the rows is    */
883         /* also considered as a row.                                    */
884         btnPtr->nRow = nRows + nSepRows;
885         if( bWrap )
886         {
887             if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
888                 y += cy;
889             else 
890             {   
891                 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
892                 /* it is the actual width of the separator. This is used for */
893                 /* custom controls in toolbars.                              */
894                 y += cy + ( (btnPtr->iBitmap > 0 ) ? 
895                         btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3; 
896              
897                 /* nSepRows is used to calculate the extra height follwoing  */          
898                 /* the last row.                                             */
899                 nSepRows++;
900             }
901             x = infoPtr->nIndent;
902                 nRows++;
903         }
904         else
905             x += cx;
906     }
907
908     /* infoPtr->nRows is the number of rows on the toolbar */
909     infoPtr->nRows = nRows + nSepRows + 1;
910
911     /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following   */
912     /* the last row.                                                    */
913     infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight + 
914                         nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
915                         nSepRows * (infoPtr->nBitmapHeight + 1) + 
916                         BOTTOM_BORDER; 
917     TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
918 }
919
920
921 static INT
922 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
923 {
924     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
925     TBUTTON_INFO *btnPtr;
926     INT i;
927     
928     btnPtr = infoPtr->buttons;
929     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
930         if (btnPtr->fsState & TBSTATE_HIDDEN)
931             continue;
932
933         if (btnPtr->fsStyle & TBSTYLE_SEP) {
934             if (PtInRect (&btnPtr->rect, *lpPt)) {
935                 TRACE(" ON SEPARATOR %d!\n", i);
936                 return -i;
937             }
938         }
939         else {
940             if (PtInRect (&btnPtr->rect, *lpPt)) {
941                 TRACE(" ON BUTTON %d!\n", i);
942                 return i;
943             }
944         }
945     }
946
947     TRACE(" NOWHERE!\n");
948     return -1;
949 }
950
951
952 static INT
953 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
954 {
955     TBUTTON_INFO *btnPtr;
956     INT i;
957
958     btnPtr = infoPtr->buttons;
959     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
960         if (btnPtr->idCommand == idCommand) {
961             TRACE("command=%d index=%d\n", idCommand, i);
962             return i;
963         }
964     }
965     TRACE("no index found for command=%d\n", idCommand);
966     return -1;
967 }
968
969
970 static INT
971 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
972 {
973     TBUTTON_INFO *btnPtr;
974     INT nRunIndex;
975
976     if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
977         return -1;
978
979     /* check index button */
980     btnPtr = &infoPtr->buttons[nIndex];
981     if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
982         if (btnPtr->fsState & TBSTATE_CHECKED)
983             return nIndex;
984     }
985
986     /* check previous buttons */
987     nRunIndex = nIndex - 1;
988     while (nRunIndex >= 0) {
989         btnPtr = &infoPtr->buttons[nRunIndex];
990         if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
991             if (btnPtr->fsState & TBSTATE_CHECKED)
992                 return nRunIndex;
993         }
994         else
995             break;
996         nRunIndex--;
997     }
998
999     /* check next buttons */
1000     nRunIndex = nIndex + 1;
1001     while (nRunIndex < infoPtr->nNumButtons) {
1002         btnPtr = &infoPtr->buttons[nRunIndex];  
1003         if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1004             if (btnPtr->fsState & TBSTATE_CHECKED)
1005                 return nRunIndex;
1006         }
1007         else
1008             break;
1009         nRunIndex++;
1010     }
1011
1012     return -1;
1013 }
1014
1015
1016 static VOID
1017 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
1018                     WPARAM wParam, LPARAM lParam)
1019 {
1020     MSG msg;
1021
1022     msg.hwnd = hwndMsg;
1023     msg.message = uMsg;
1024     msg.wParam = wParam;
1025     msg.lParam = lParam;
1026     msg.time = GetMessageTime ();
1027     msg.pt.x = LOWORD(GetMessagePos ());
1028     msg.pt.y = HIWORD(GetMessagePos ());
1029
1030     SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
1031 }
1032
1033
1034 /***********************************************************************
1035  * TOOLBAR_CustomizeDialogProc
1036  * This function implements the toolbar customization dialog.
1037  */
1038 static BOOL WINAPI
1039 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1040 {
1041     PCUSTDLG_INFO custInfo = (PCUSTDLG_INFO)GetWindowLongA (hwnd, DWL_USER);
1042     PCUSTOMBUTTON btnInfo;
1043     NMTOOLBARA nmtb;
1044
1045     switch (uMsg)
1046     {
1047         case WM_INITDIALOG:
1048             custInfo = (PCUSTDLG_INFO)lParam;
1049             SetWindowLongA (hwnd, DWL_USER, (DWORD)custInfo);
1050
1051             if (custInfo)
1052             {
1053                 char Buffer[256];
1054                 int i = 0;
1055                 int index;
1056
1057                 /* send TBN_QUERYINSERT notification */
1058                 nmtb.hdr.hwndFrom = hwnd;
1059                 nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1060                 nmtb.hdr.code     = TBN_QUERYINSERT;
1061                 nmtb.iItem = custInfo->tbInfo->nNumButtons;
1062
1063                 if (!SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1064                                    (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1065                     return FALSE;
1066
1067                 /* add items to 'toolbar buttons' list and check if removable */
1068                 for (i = 0; i < custInfo->tbInfo->nNumButtons; i++)
1069                 {
1070                     btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1071                     memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1072                     btnInfo->btn.fsStyle = TBSTYLE_SEP;
1073                     btnInfo->bVirtual = FALSE;
1074                     LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1075
1076                     /* send TBN_QUERYDELETE notification */
1077                     nmtb.hdr.hwndFrom = hwnd;
1078                     nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1079                     nmtb.hdr.code     = TBN_QUERYDELETE;
1080                     nmtb.iItem = i;
1081
1082                     btnInfo->bRemovable = SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1083                                                         (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
1084
1085                     index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, 0);
1086                     SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1087                 }
1088
1089                 /* insert separator button into 'available buttons' list */
1090                 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1091                 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1092                 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1093                 btnInfo->bVirtual = FALSE;
1094                 btnInfo->bRemovable = TRUE;
1095                 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1096                 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1097                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1098
1099                 /* insert all buttons into dsa */
1100                 for (i = 0;; i++)
1101                 {
1102                     /* send TBN_GETBUTTONINFO notification */
1103                     nmtb.hdr.hwndFrom = hwnd;
1104                     nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1105                     nmtb.hdr.code     = TBN_GETBUTTONINFOA;
1106                     nmtb.iItem = i;
1107                     nmtb.pszText = Buffer;
1108                     nmtb.cchText = 256;
1109
1110                     if (!SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1111                                        (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1112                         break;
1113
1114                     TRACE("style: %x\n", nmtb.tbButton.fsStyle);                
1115
1116                     /* insert button into the apropriate list */
1117                     index = TOOLBAR_GetButtonIndex (custInfo->tbInfo, nmtb.tbButton.idCommand);
1118                     if (index == -1)
1119                     {
1120                         btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1121                         memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1122                         btnInfo->bVirtual = FALSE;
1123                         btnInfo->bRemovable = TRUE;
1124                         if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1125                             strcpy (btnInfo->text, nmtb.pszText);
1126
1127                         index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1128                         SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1129                     }
1130                     else
1131                     {
1132                         btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1133                         memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1134                         if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1135                             strcpy (btnInfo->text, nmtb.pszText);
1136
1137                         SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1138                     }
1139                 }
1140
1141                 /* select first item in the 'available' list */
1142                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, 0, 0);
1143
1144                 /* append 'virtual' separator button to the 'toolbar buttons' list */
1145                 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1146                 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1147                 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1148                 btnInfo->bVirtual = TRUE;
1149                 btnInfo->bRemovable = FALSE;
1150                 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1151                 index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1152                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1153
1154                 /* select last item in the 'toolbar' list */
1155                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index, 0);
1156                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETTOPINDEX, index, 0);
1157
1158                 /* set focus and disable buttons */
1159                 PostMessageA (hwnd, WM_USER, 0, 0);
1160             }
1161             return TRUE;
1162
1163         case WM_USER:
1164             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1165             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1166             EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), FALSE);
1167             SetFocus (GetDlgItem (hwnd, IDC_TOOLBARBTN_LBOX));
1168             return TRUE;
1169
1170         case WM_CLOSE:
1171             EndDialog(hwnd, FALSE);
1172             return TRUE;
1173
1174         case WM_COMMAND:
1175             switch (LOWORD(wParam))
1176             {
1177                 case IDC_TOOLBARBTN_LBOX:
1178                     if (HIWORD(wParam) == LBN_SELCHANGE)
1179                     {
1180                         PCUSTOMBUTTON btnInfo;
1181                         NMTOOLBARA nmtb;
1182                         int count;
1183                         int index;
1184
1185                         count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1186                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1187
1188                         /* send TBN_QUERYINSERT notification */
1189                         nmtb.hdr.hwndFrom = hwnd;
1190                         nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1191                         nmtb.hdr.code     = TBN_QUERYINSERT;
1192                         nmtb.iItem = index;
1193
1194                         SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1195                                       (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
1196
1197                         /* get list box item */
1198                         btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1199
1200                         if (index == (count - 1))
1201                         {
1202                             /* last item (virtual separator) */
1203                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1204                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1205                         }
1206                         else if (index == (count - 2))
1207                         {
1208                             /* second last item (last non-virtual item) */
1209                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1210                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1211                         }
1212                         else if (index == 0)
1213                         {
1214                             /* first item */
1215                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1216                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1217                         }
1218                         else
1219                         {
1220                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1221                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1222                         }
1223
1224                         EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), btnInfo->bRemovable);
1225                     }
1226                     break;
1227
1228                 case IDC_MOVEUP_BTN:
1229                     {
1230                         PCUSTOMBUTTON btnInfo;
1231                         int index;
1232                         int count;
1233
1234                         count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1235                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1236                         TRACE("Move up: index %d\n", index);
1237
1238                         /* send TBN_QUERYINSERT notification */
1239                         nmtb.hdr.hwndFrom = hwnd;
1240                         nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1241                         nmtb.hdr.code     = TBN_QUERYINSERT;
1242                         nmtb.iItem = index;
1243
1244                         if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1245                                           (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1246                         {
1247                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1248
1249                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1250                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index-1, 0);
1251                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index-1, (LPARAM)btnInfo);
1252                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1253
1254                             if (index <= 1)
1255                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1256                             else if (index >= (count - 3))
1257                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1258
1259                             SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1260                             SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index-1, (LPARAM)&(btnInfo->btn));
1261                         }
1262                     }
1263                     break;
1264
1265                 case IDC_MOVEDN_BTN: /* move down */
1266                     {
1267                         PCUSTOMBUTTON btnInfo;
1268                         int index;
1269                         int count;
1270
1271                         count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1272                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1273                         TRACE("Move up: index %d\n", index);
1274
1275                         /* send TBN_QUERYINSERT notification */
1276                         nmtb.hdr.hwndFrom = hwnd;
1277                         nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1278                         nmtb.hdr.code     = TBN_QUERYINSERT;
1279                         nmtb.iItem = index;
1280
1281                         if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1282                                           (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1283                         {
1284                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1285
1286                             /* move button down */
1287                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1288                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index+1, 0);
1289                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index+1, (LPARAM)btnInfo);
1290                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index+1 , 0);
1291
1292                             if (index == 0)
1293                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1294                             else if (index >= (count - 3))
1295                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1296
1297                             SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1298                             SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index+1, (LPARAM)&(btnInfo->btn));
1299                         }
1300                     }
1301                     break;
1302
1303                 case IDC_REMOVE_BTN: /* remove button */
1304                     {
1305                         PCUSTOMBUTTON btnInfo;
1306                         int index;
1307
1308                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1309                         TRACE("Remove: index %d\n", index);
1310
1311                         /* send TBN_QUERYDELETE notification */
1312                         nmtb.hdr.hwndFrom = hwnd;
1313                         nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1314                         nmtb.hdr.code     = TBN_QUERYDELETE;
1315                         nmtb.iItem = index;
1316
1317                         if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1318                                           (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1319                         {
1320                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1321                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1322                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index , 0);
1323
1324                             SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1325
1326                             /* insert into 'available button' list */
1327                             if (!(btnInfo->btn.fsStyle & TBSTYLE_SEP))
1328                             {
1329                                 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1330                                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1331                             }
1332                             else
1333                                 COMCTL32_Free (btnInfo);
1334                         }
1335                     }
1336                     break;
1337
1338                 case IDOK: /* Add button */
1339                     {
1340                         int index;
1341                         int count;
1342
1343                         count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1344                         index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0);
1345                         TRACE("Add: index %d\n", index);
1346
1347                         /* send TBN_QUERYINSERT notification */
1348                         nmtb.hdr.hwndFrom = hwnd;
1349                         nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1350                         nmtb.hdr.code     = TBN_QUERYINSERT;
1351                         nmtb.iItem = index;
1352
1353                         if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1354                                           (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1355                         {
1356                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, index, 0);
1357
1358                             if (index != 0)
1359                             {
1360                                 /* remove from 'available buttons' list */
1361                                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_DELETESTRING, index, 0);
1362                                 if (index == count-1)
1363                                     SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1364                                 else
1365                                     SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index , 0);
1366                             }
1367                             else
1368                             {
1369                                 PCUSTOMBUTTON btnNew;
1370
1371                                 /* duplicate 'separator' button */
1372                                 btnNew = (PCUSTOMBUTTON)COMCTL32_Alloc (sizeof(CUSTOMBUTTON));
1373                                 memcpy (btnNew, btnInfo, sizeof(CUSTOMBUTTON));
1374                                 btnInfo = btnNew;
1375                             }
1376
1377                             /* insert into 'toolbar button' list */
1378                             index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1379                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index, 0);
1380                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1381
1382                             SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index, (LPARAM)&(btnInfo->btn));
1383                         }
1384                     }
1385                     break;
1386
1387                 case IDCANCEL:
1388                     EndDialog(hwnd, FALSE);
1389                     break;
1390             }
1391             return TRUE;
1392
1393         case WM_DESTROY:
1394             {
1395                 int count;
1396                 int i;
1397
1398                 /* delete items from 'toolbar buttons' listbox*/
1399                 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1400                 for (i = 0; i < count; i++)
1401                 {
1402                     btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, i, 0);
1403                     COMCTL32_Free(btnInfo);
1404                     SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, 0, 0);
1405                 }
1406                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_RESETCONTENT, 0, 0);
1407
1408
1409                 /* delete items from 'available buttons' listbox*/
1410                 count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1411                 for (i = 0; i < count; i++)
1412                 {
1413                     btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, i, 0);
1414                     COMCTL32_Free(btnInfo);
1415                     SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, i, 0);
1416                 }
1417                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_RESETCONTENT, 0, 0);
1418             }
1419             return TRUE;
1420
1421         case WM_DRAWITEM:
1422             if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1423             {
1424                 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
1425                 RECT rcButton;
1426                 RECT rcText;
1427                 HPEN hOldPen;
1428                 HBRUSH hOldBrush;
1429                 COLORREF oldText = 0;
1430                 COLORREF oldBk = 0;
1431
1432                 /* get item data */
1433                 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, wParam, LB_GETITEMDATA, (WPARAM)lpdis->itemID, 0);
1434                 if (btnInfo == NULL)
1435                 {
1436                     FIXME("btnInfo invalid!\n");
1437                     return TRUE;
1438                 }
1439
1440                 /* set colors and select objects */
1441                 oldBk = SetBkColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1442                 if (btnInfo->bVirtual)
1443                    oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
1444                 else
1445                    oldText = SetTextColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHTTEXT:COLOR_WINDOWTEXT));
1446                 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1447                 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1448
1449                 /* fill background rectangle */
1450                 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
1451                            lpdis->rcItem.right, lpdis->rcItem.bottom);
1452
1453                 /* calculate button and text rectangles */
1454                 CopyRect (&rcButton, &lpdis->rcItem);
1455                 InflateRect (&rcButton, -1, -1);
1456                 CopyRect (&rcText, &rcButton);
1457                 rcButton.right = rcButton.left + custInfo->tbInfo->nBitmapWidth + 6;
1458                 rcText.left = rcButton.right + 2;
1459
1460                 /* draw focus rectangle */
1461                 if (lpdis->itemState & ODS_FOCUS)
1462                     DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
1463
1464                 /* draw button */
1465                 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
1466
1467                 /* draw image and text */
1468                 if ((btnInfo->btn.fsStyle & TBSTYLE_SEP) == 0)
1469                     ImageList_Draw (custInfo->tbInfo->himlDef, btnInfo->btn.iBitmap, lpdis->hDC,
1470                                     rcButton.left+3, rcButton.top+3, ILD_NORMAL);
1471                 DrawTextA (lpdis->hDC,  btnInfo->text, -1, &rcText,
1472                                DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1473
1474                 /* delete objects and reset colors */
1475                 SelectObject (lpdis->hDC, hOldBrush);
1476                 SelectObject (lpdis->hDC, hOldPen);
1477                 SetBkColor (lpdis->hDC, oldBk);
1478                 SetTextColor (lpdis->hDC, oldText);
1479
1480                 return TRUE;
1481             }
1482             return FALSE;
1483
1484         case WM_MEASUREITEM:
1485             if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1486             {
1487                 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
1488
1489                 if (custInfo && custInfo->tbInfo)
1490                     lpmis->itemHeight = custInfo->tbInfo->nBitmapHeight + 8;
1491                 else
1492                     lpmis->itemHeight = 15 + 8; /* default height */
1493
1494                 return TRUE;
1495             }
1496             return FALSE;
1497
1498         default:
1499             return FALSE;
1500     }
1501 }
1502
1503
1504 /***********************************************************************
1505  * TOOLBAR_AddBitmap:  Add the bitmaps to the default image list.
1506  *
1507  */
1508 static LRESULT
1509 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1510 {
1511     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1512     LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1513     INT nIndex = 0, nButtons, nCount;
1514     HBITMAP hbmLoad;
1515
1516     TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1517     if (!lpAddBmp)
1518         return -1;
1519
1520     if (lpAddBmp->hInst == HINST_COMMCTRL)
1521     {
1522         if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1523             nButtons = 15;
1524         else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1525             nButtons = 13;
1526         else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1527             nButtons = 5;
1528         else
1529             return -1;
1530
1531         TRACE ("adding %d internal bitmaps!\n", nButtons);
1532
1533         /* Windows resize all the buttons to the size of a newly added standard image */
1534         if (lpAddBmp->nID & 1) 
1535         {
1536             /* large icons */
1537             /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap 
1538              * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this 
1539              */
1540             SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1541                           MAKELPARAM((WORD)24, (WORD)24));
1542             SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1543                           MAKELPARAM((WORD)31, (WORD)30));
1544         }       
1545         else 
1546         {
1547             /* small icons */
1548             SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1549                           MAKELPARAM((WORD)16, (WORD)16));
1550             SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1551                           MAKELPARAM((WORD)22, (WORD)22));
1552         }
1553         
1554         TOOLBAR_CalcToolbar (hwnd);
1555     }
1556     else
1557     {
1558         nButtons = (INT)wParam;
1559         if (nButtons <= 0)
1560             return -1;
1561         
1562         TRACE ("adding %d bitmaps!\n", nButtons);
1563     }
1564     
1565     if (!(infoPtr->himlDef)) {
1566         /* create new default image list */
1567         TRACE ("creating default image list!\n");
1568
1569         infoPtr->himlDef =
1570             ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1571                               ILC_COLOR | ILC_MASK, nButtons, 2);
1572         infoPtr->himlInt = infoPtr->himlDef;
1573     }
1574
1575     nCount = ImageList_GetImageCount(infoPtr->himlDef);
1576
1577     /* Add bitmaps to the default image list */
1578     if (lpAddBmp->hInst == (HINSTANCE)0)
1579     {
1580         nIndex = 
1581             ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1582                                  CLR_DEFAULT);
1583     }
1584     else if (lpAddBmp->hInst == HINST_COMMCTRL)
1585     {
1586         /* Add system bitmaps */
1587         switch (lpAddBmp->nID)
1588     {
1589             case IDB_STD_SMALL_COLOR:
1590                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1591                                        MAKEINTRESOURCEA(IDB_STD_SMALL));
1592                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1593                                               hbmLoad, CLR_DEFAULT);
1594                 DeleteObject (hbmLoad);
1595                 break;
1596
1597             case IDB_STD_LARGE_COLOR:
1598                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1599                                        MAKEINTRESOURCEA(IDB_STD_LARGE));
1600                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1601                                               hbmLoad, CLR_DEFAULT);
1602                 DeleteObject (hbmLoad);
1603                 break;
1604
1605             case IDB_VIEW_SMALL_COLOR:
1606                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1607                                        MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1608                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1609                                               hbmLoad, CLR_DEFAULT);
1610                 DeleteObject (hbmLoad);
1611                 break;
1612
1613             case IDB_VIEW_LARGE_COLOR:
1614                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1615                                        MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1616                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1617                                               hbmLoad, CLR_DEFAULT);
1618                 DeleteObject (hbmLoad);
1619                 break;
1620
1621             case IDB_HIST_SMALL_COLOR:
1622                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1623                                        MAKEINTRESOURCEA(IDB_HIST_SMALL));
1624                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1625                                               hbmLoad, CLR_DEFAULT);
1626                 DeleteObject (hbmLoad);
1627                 break;
1628
1629             case IDB_HIST_LARGE_COLOR:
1630                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1631                                        MAKEINTRESOURCEA(IDB_HIST_LARGE));
1632                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1633                                               hbmLoad, CLR_DEFAULT);
1634                 DeleteObject (hbmLoad);
1635                 break;
1636
1637             default:
1638         nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1639                 ERR ("invalid imagelist!\n");
1640                 break;
1641         }
1642     }
1643     else
1644     {
1645         hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1646         nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1647         DeleteObject (hbmLoad);
1648     }
1649
1650     if (nIndex != -1)
1651     {
1652        INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1653
1654        if (infoPtr->nNumBitmaps + nButtons != imagecount)
1655        {
1656          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",
1657               infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1658               infoPtr->nNumBitmaps+nButtons,imagecount);
1659
1660          infoPtr->nNumBitmaps = imagecount;
1661        }
1662        else
1663          infoPtr->nNumBitmaps += nButtons;
1664     }
1665
1666     InvalidateRect(hwnd, NULL, FALSE);
1667
1668     return nIndex;
1669 }
1670
1671
1672 static LRESULT
1673 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1674 {
1675     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1676     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1677     INT nOldButtons, nNewButtons, nAddButtons, nCount;
1678
1679     TRACE("adding %d buttons!\n", wParam);
1680
1681     nAddButtons = (UINT)wParam;
1682     nOldButtons = infoPtr->nNumButtons;
1683     nNewButtons = nOldButtons + nAddButtons;
1684
1685     if (infoPtr->nNumButtons == 0) {
1686         infoPtr->buttons =
1687             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1688     }
1689     else {
1690         TBUTTON_INFO *oldButtons = infoPtr->buttons;
1691         infoPtr->buttons =
1692             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1693         memcpy (&infoPtr->buttons[0], &oldButtons[0],
1694                 nOldButtons * sizeof(TBUTTON_INFO));
1695         COMCTL32_Free (oldButtons);
1696     }
1697
1698     infoPtr->nNumButtons = nNewButtons;
1699
1700     /* insert new button data */
1701     for (nCount = 0; nCount < nAddButtons; nCount++) {
1702         TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1703         btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
1704         btnPtr->idCommand = lpTbb[nCount].idCommand;
1705         btnPtr->fsState   = lpTbb[nCount].fsState;
1706         btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
1707         btnPtr->dwData    = lpTbb[nCount].dwData;
1708         btnPtr->iString   = lpTbb[nCount].iString;
1709         btnPtr->bHot      = FALSE;
1710
1711         if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1712             TTTOOLINFOA ti;
1713
1714             ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1715             ti.cbSize   = sizeof (TTTOOLINFOA);
1716             ti.hwnd     = hwnd;
1717             ti.uId      = btnPtr->idCommand;
1718             ti.hinst    = 0;
1719             ti.lpszText = LPSTR_TEXTCALLBACKA;
1720
1721             SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1722                             0, (LPARAM)&ti);
1723         }
1724     }
1725
1726     TOOLBAR_CalcToolbar (hwnd);
1727
1728     InvalidateRect(hwnd, NULL, FALSE);
1729
1730     return TRUE;
1731 }
1732
1733
1734 static LRESULT
1735 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1736 {
1737     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1738     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1739     INT nOldButtons, nNewButtons, nAddButtons, nCount;
1740
1741     TRACE("adding %d buttons!\n", wParam);
1742
1743     nAddButtons = (UINT)wParam;
1744     nOldButtons = infoPtr->nNumButtons;
1745     nNewButtons = nOldButtons + nAddButtons;
1746
1747     if (infoPtr->nNumButtons == 0) {
1748         infoPtr->buttons =
1749             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1750     }
1751     else {
1752         TBUTTON_INFO *oldButtons = infoPtr->buttons;
1753         infoPtr->buttons =
1754             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1755         memcpy (&infoPtr->buttons[0], &oldButtons[0],
1756                 nOldButtons * sizeof(TBUTTON_INFO));
1757         COMCTL32_Free (oldButtons);
1758     }
1759
1760     infoPtr->nNumButtons = nNewButtons;
1761
1762     /* insert new button data */
1763     for (nCount = 0; nCount < nAddButtons; nCount++) {
1764         TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1765         btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
1766         btnPtr->idCommand = lpTbb[nCount].idCommand;
1767         btnPtr->fsState   = lpTbb[nCount].fsState;
1768         btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
1769         btnPtr->dwData    = lpTbb[nCount].dwData;
1770         btnPtr->iString   = lpTbb[nCount].iString;
1771         btnPtr->bHot      = FALSE;
1772
1773         if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1774             TTTOOLINFOW ti;
1775
1776             ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1777             ti.cbSize   = sizeof (TTTOOLINFOW);
1778             ti.hwnd     = hwnd;
1779             ti.uId      = btnPtr->idCommand;
1780             ti.hinst    = 0;
1781             ti.lpszText = LPSTR_TEXTCALLBACKW;
1782
1783             SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1784                             0, (LPARAM)&ti);
1785         }
1786     }
1787
1788     TOOLBAR_CalcToolbar (hwnd);
1789
1790     InvalidateRect(hwnd, NULL, FALSE);
1791
1792     return TRUE;
1793 }
1794
1795
1796 static LRESULT
1797 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1798 {
1799     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1800     INT nIndex;
1801
1802     if ((wParam) && (HIWORD(lParam) == 0)) {
1803         char szString[256];
1804         INT len, lenW;
1805         TRACE("adding string from resource!\n");
1806
1807         len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1808                              szString, 256);
1809
1810         TRACE("len=%d \"%s\"\n", len, szString);
1811         nIndex = infoPtr->nNumStrings;
1812         if (infoPtr->nNumStrings == 0) {
1813             infoPtr->strings =
1814                 COMCTL32_Alloc (sizeof(LPWSTR));
1815         }
1816         else {
1817             LPWSTR *oldStrings = infoPtr->strings;
1818             infoPtr->strings =
1819                 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1820             memcpy (&infoPtr->strings[0], &oldStrings[0],
1821                     sizeof(LPWSTR) * infoPtr->nNumStrings);
1822             COMCTL32_Free (oldStrings);
1823         }
1824
1825         lenW = MultiByteToWideChar( CP_ACP, 0, szString, -1, NULL, 0 );
1826         infoPtr->strings[infoPtr->nNumStrings] = COMCTL32_Alloc (sizeof(WCHAR)*lenW);
1827         MultiByteToWideChar( CP_ACP, 0, szString, -1,
1828                              infoPtr->strings[infoPtr->nNumStrings], lenW );
1829         infoPtr->nNumStrings++;
1830     }
1831     else {
1832         LPSTR p = (LPSTR)lParam;
1833         INT len, lenW;
1834
1835         if (p == NULL)
1836             return -1;
1837         TRACE("adding string(s) from array!\n");
1838
1839         nIndex = infoPtr->nNumStrings;
1840         while (*p) {
1841             len = strlen (p);
1842             TRACE("len=%d \"%s\"\n", len, p);
1843
1844             if (infoPtr->nNumStrings == 0) {
1845                 infoPtr->strings =
1846                     COMCTL32_Alloc (sizeof(LPWSTR));
1847             }
1848             else {
1849                 LPWSTR *oldStrings = infoPtr->strings;
1850                 infoPtr->strings =
1851                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1852                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1853                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1854                 COMCTL32_Free (oldStrings);
1855             }
1856
1857             lenW = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
1858             infoPtr->strings[infoPtr->nNumStrings] = COMCTL32_Alloc (sizeof(WCHAR)*lenW);
1859             MultiByteToWideChar( CP_ACP, 0, p, -1,
1860                                  infoPtr->strings[infoPtr->nNumStrings], lenW );
1861             infoPtr->nNumStrings++;
1862
1863             p += (len+1);
1864         }
1865     }
1866
1867     return nIndex;
1868 }
1869
1870
1871 static LRESULT
1872 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1873 {
1874 #define MAX_RESOURCE_STRING_LENGTH 512
1875     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1876     INT nIndex;
1877
1878     if ((wParam) && (HIWORD(lParam) == 0)) {
1879         WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1880         INT len;
1881         TRACE("adding string from resource!\n");
1882
1883         len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1884                              szString, MAX_RESOURCE_STRING_LENGTH);
1885
1886         TRACE("len=%d %s\n", len, debugstr_w(szString));
1887         TRACE("First char: 0x%x\n", *szString);
1888         if (szString[0] == L'|')
1889         {
1890             PWSTR p = szString + 1;
1891                 
1892             nIndex = infoPtr->nNumStrings;
1893             while (*p != L'|') {
1894
1895             if (infoPtr->nNumStrings == 0) {
1896                 infoPtr->strings =
1897                     COMCTL32_Alloc (sizeof(LPWSTR));
1898             }
1899             else {
1900                 LPWSTR *oldStrings = infoPtr->strings;
1901                 infoPtr->strings =
1902                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1903                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1904                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1905                 COMCTL32_Free (oldStrings);
1906             }
1907
1908             len = COMCTL32_StrChrW (p, L'|') - p;
1909             TRACE("len=%d %s\n", len, debugstr_w(p));
1910             infoPtr->strings[infoPtr->nNumStrings] =
1911                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1912             lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1913             infoPtr->nNumStrings++;
1914
1915                 p += (len+1);
1916             }
1917         }
1918         else
1919         {
1920             nIndex = infoPtr->nNumStrings;
1921             if (infoPtr->nNumStrings == 0) {
1922                 infoPtr->strings =
1923                     COMCTL32_Alloc (sizeof(LPWSTR));
1924             }
1925             else {
1926                 LPWSTR *oldStrings = infoPtr->strings;
1927                 infoPtr->strings =
1928                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1929                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1930                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1931                 COMCTL32_Free (oldStrings);
1932             }
1933
1934             infoPtr->strings[infoPtr->nNumStrings] =
1935                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1936             strcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1937             infoPtr->nNumStrings++;
1938         }
1939     }
1940     else {
1941         LPWSTR p = (LPWSTR)lParam;
1942         INT len;
1943
1944         if (p == NULL)
1945             return -1;
1946         TRACE("adding string(s) from array!\n");
1947         nIndex = infoPtr->nNumStrings;
1948         while (*p) {
1949             len = strlenW (p);
1950
1951             TRACE("len=%d %s\n", len, debugstr_w(p));
1952             if (infoPtr->nNumStrings == 0) {
1953                 infoPtr->strings =
1954                     COMCTL32_Alloc (sizeof(LPWSTR));
1955             }
1956             else {
1957                 LPWSTR *oldStrings = infoPtr->strings;
1958                 infoPtr->strings =
1959                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1960                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1961                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1962                 COMCTL32_Free (oldStrings);
1963             }
1964
1965             infoPtr->strings[infoPtr->nNumStrings] =
1966                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1967             strcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1968             infoPtr->nNumStrings++;
1969
1970             p += (len+1);
1971         }
1972     }
1973
1974     return nIndex;
1975 }
1976
1977
1978 static LRESULT
1979 TOOLBAR_AutoSize (HWND hwnd)
1980 {
1981     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1982     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1983     RECT parent_rect;
1984     RECT window_rect;
1985     HWND parent;
1986     INT  x, y;
1987     INT  cx, cy;
1988     UINT uPosFlags = SWP_NOZORDER;
1989
1990     TRACE("resize forced, style=%lx!\n", dwStyle);
1991
1992     parent = GetParent (hwnd);
1993     GetClientRect(parent, &parent_rect);
1994
1995     x = parent_rect.left;
1996     y = parent_rect.top;
1997
1998     /* FIXME: we should be able to early out if nothing */
1999     /* has changed with nWidth != parent_rect width */
2000
2001     if (dwStyle & CCS_NORESIZE) {
2002         uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
2003         cx = 0;
2004         cy = 0;
2005     }
2006     else {
2007         infoPtr->nWidth = parent_rect.right - parent_rect.left;
2008         TOOLBAR_CalcToolbar (hwnd);
2009         InvalidateRect( hwnd, NULL, TRUE );
2010         cy = infoPtr->nHeight;
2011         cx = infoPtr->nWidth;
2012
2013         if (dwStyle & CCS_NOMOVEY) {
2014                 GetWindowRect(hwnd, &window_rect);
2015                 ScreenToClient(parent, (LPPOINT)&window_rect.left);
2016                 y = window_rect.top;
2017         }
2018     }
2019
2020     if (dwStyle & CCS_NOPARENTALIGN)
2021         uPosFlags |= SWP_NOMOVE;
2022
2023     if (!(dwStyle & CCS_NODIVIDER))
2024         cy += GetSystemMetrics(SM_CYEDGE);
2025
2026     if (dwStyle & WS_BORDER)
2027     {
2028         x = y = 1;
2029         cy += GetSystemMetrics(SM_CYEDGE);
2030         cx += GetSystemMetrics(SM_CYEDGE);
2031     }
2032
2033     infoPtr->bAutoSize = TRUE;
2034     SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
2035                         cx, cy, uPosFlags);
2036     /* The following line makes sure that the infoPtr->bAutoSize is turned off after
2037      * the setwindowpos calls */
2038     infoPtr->bAutoSize = FALSE;
2039
2040     return 0;
2041 }
2042
2043
2044 static LRESULT
2045 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
2046 {
2047     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2048
2049     return infoPtr->nNumButtons;
2050 }
2051
2052
2053 static LRESULT
2054 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2055 {
2056     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2057
2058     if (infoPtr == NULL) {
2059         ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
2060         ERR("infoPtr == NULL!\n");
2061         return 0;
2062     }
2063
2064     infoPtr->dwStructSize = (DWORD)wParam;
2065
2066     return 0;
2067 }
2068
2069
2070 static LRESULT
2071 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2072 {
2073     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2074     TBUTTON_INFO *btnPtr;
2075     INT nIndex;
2076
2077     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2078     if (nIndex == -1)
2079         return FALSE;
2080
2081     btnPtr = &infoPtr->buttons[nIndex];
2082     btnPtr->iBitmap = LOWORD(lParam);
2083
2084     /* we HAVE to erase the background, the new bitmap could be */
2085     /* transparent */
2086     InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2087
2088     return TRUE;
2089 }
2090
2091
2092 static LRESULT
2093 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2094 {
2095     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2096     TBUTTON_INFO *btnPtr;
2097     INT nIndex;
2098     INT nOldIndex = -1;
2099     BOOL bChecked = FALSE;
2100
2101     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2102     if (nIndex == -1)
2103         return FALSE;
2104
2105     btnPtr = &infoPtr->buttons[nIndex];
2106
2107     if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
2108         return FALSE;
2109
2110     bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
2111
2112     if (LOWORD(lParam) == FALSE)
2113         btnPtr->fsState &= ~TBSTATE_CHECKED;
2114     else {
2115         if (btnPtr->fsStyle & TBSTYLE_GROUP) {
2116             nOldIndex = 
2117                 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
2118             if (nOldIndex == nIndex)
2119                 return 0;
2120             if (nOldIndex != -1)
2121                 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
2122         }
2123         btnPtr->fsState |= TBSTATE_CHECKED;
2124     }
2125
2126     if( bChecked != LOWORD(lParam) )
2127     {
2128         if (nOldIndex != -1)
2129         {
2130             InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
2131                 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
2132         }
2133         InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2134     }
2135
2136     /* FIXME: Send a WM_NOTIFY?? */
2137
2138     return TRUE;
2139 }
2140
2141
2142 static LRESULT
2143 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
2144 {
2145     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2146
2147     return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2148 }
2149
2150
2151 static LRESULT
2152 TOOLBAR_Customize (HWND hwnd)
2153 {
2154     CUSTDLG_INFO custInfo;
2155     LRESULT ret;
2156     LPCVOID template;
2157     HRSRC hRes;
2158     NMHDR nmhdr;
2159
2160     custInfo.tbInfo = TOOLBAR_GetInfoPtr (hwnd);
2161     custInfo.tbHwnd = hwnd;
2162
2163     /* send TBN_BEGINADJUST notification */
2164     nmhdr.hwndFrom = hwnd;
2165     nmhdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
2166     nmhdr.code     = TBN_BEGINADJUST;
2167
2168     SendMessageA (custInfo.tbInfo->hwndNotify, WM_NOTIFY,
2169                   (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
2170
2171     if (!(hRes = FindResourceA (COMCTL32_hModule,
2172                                 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
2173                                 RT_DIALOGA)))
2174         return FALSE;
2175
2176     if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
2177         return FALSE;
2178
2179     ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
2180                                    (LPDLGTEMPLATEA)template,
2181                                    hwnd,
2182                                    (DLGPROC)TOOLBAR_CustomizeDialogProc,
2183                                    (LPARAM)&custInfo);
2184
2185     /* send TBN_ENDADJUST notification */
2186     nmhdr.code = TBN_ENDADJUST;
2187     SendMessageA (custInfo.tbInfo->hwndNotify, WM_NOTIFY,
2188                   (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
2189
2190     return ret;
2191 }
2192
2193
2194 static LRESULT
2195 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2196 {
2197     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2198     INT nIndex = (INT)wParam;
2199
2200     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2201         return FALSE;
2202
2203     if ((infoPtr->hwndToolTip) && 
2204         !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
2205         TTTOOLINFOA ti;
2206
2207         ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2208         ti.cbSize   = sizeof (TTTOOLINFOA);
2209         ti.hwnd     = hwnd;
2210         ti.uId      = infoPtr->buttons[nIndex].idCommand;
2211
2212         SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
2213     }
2214
2215     if (infoPtr->nNumButtons == 1) {
2216         TRACE(" simple delete!\n");
2217         COMCTL32_Free (infoPtr->buttons);
2218         infoPtr->buttons = NULL;
2219         infoPtr->nNumButtons = 0;
2220     }
2221     else {
2222         TBUTTON_INFO *oldButtons = infoPtr->buttons;
2223         TRACE("complex delete! [nIndex=%d]\n", nIndex);
2224
2225         infoPtr->nNumButtons--;
2226         infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2227         if (nIndex > 0) {
2228             memcpy (&infoPtr->buttons[0], &oldButtons[0],
2229                     nIndex * sizeof(TBUTTON_INFO));
2230         }
2231
2232         if (nIndex < infoPtr->nNumButtons) {
2233             memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
2234                     (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
2235         }
2236
2237         COMCTL32_Free (oldButtons);
2238     }
2239
2240     TOOLBAR_CalcToolbar (hwnd);
2241
2242     InvalidateRect (hwnd, NULL, TRUE);
2243
2244     return TRUE;
2245 }
2246
2247
2248 static LRESULT
2249 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2250 {
2251     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2252     TBUTTON_INFO *btnPtr;
2253     INT nIndex;
2254     DWORD bState;
2255
2256     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2257     if (nIndex == -1)
2258         return FALSE;
2259
2260     btnPtr = &infoPtr->buttons[nIndex];
2261
2262     bState = btnPtr->fsState & TBSTATE_ENABLED;
2263
2264     /* update the toolbar button state */
2265     if(LOWORD(lParam) == FALSE) {
2266         btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
2267     } else {
2268         btnPtr->fsState |= TBSTATE_ENABLED;
2269     }
2270
2271     /* redraw the button only if the state of the button changed */
2272     if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
2273     {
2274         InvalidateRect(hwnd, &btnPtr->rect,
2275             TOOLBAR_HasText(infoPtr, btnPtr));
2276     }
2277
2278     return TRUE;
2279 }
2280
2281
2282 static inline LRESULT
2283 TOOLBAR_GetAnchorHighlight (HWND hwnd)
2284 {
2285     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2286
2287     return infoPtr->bAnchor;
2288 }
2289
2290
2291 static LRESULT
2292 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2293 {
2294     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2295     INT nIndex;
2296
2297     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2298     if (nIndex == -1)
2299         return -1;
2300
2301     return infoPtr->buttons[nIndex].iBitmap;
2302 }
2303
2304
2305 static inline LRESULT
2306 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2307 {
2308     return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
2309 }
2310
2311
2312 static LRESULT
2313 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2314 {
2315     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2316     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2317     INT nIndex = (INT)wParam;
2318     TBUTTON_INFO *btnPtr;
2319
2320     if (infoPtr == NULL)
2321         return FALSE;
2322
2323     if (lpTbb == NULL)
2324         return FALSE;
2325
2326     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2327         return FALSE;
2328
2329     btnPtr = &infoPtr->buttons[nIndex];
2330     lpTbb->iBitmap   = btnPtr->iBitmap;
2331     lpTbb->idCommand = btnPtr->idCommand;
2332     lpTbb->fsState   = btnPtr->fsState;
2333     lpTbb->fsStyle   = btnPtr->fsStyle;
2334     lpTbb->dwData    = btnPtr->dwData;
2335     lpTbb->iString   = btnPtr->iString;
2336
2337     return TRUE;
2338 }
2339
2340
2341 static LRESULT
2342 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2343 {
2344     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2345     LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
2346     TBUTTON_INFO *btnPtr;
2347     INT nIndex;
2348
2349     if (infoPtr == NULL)
2350         return -1;
2351     if (lpTbInfo == NULL)
2352         return -1;
2353     if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2354         return -1;
2355
2356     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2357     if (nIndex == -1)
2358         return -1;
2359
2360     btnPtr = &infoPtr->buttons[nIndex];
2361
2362     if (lpTbInfo->dwMask & TBIF_COMMAND)
2363         lpTbInfo->idCommand = btnPtr->idCommand;
2364     if (lpTbInfo->dwMask & TBIF_IMAGE)
2365         lpTbInfo->iImage = btnPtr->iBitmap;
2366     if (lpTbInfo->dwMask & TBIF_LPARAM)
2367         lpTbInfo->lParam = btnPtr->dwData;
2368     if (lpTbInfo->dwMask & TBIF_SIZE)
2369         lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2370     if (lpTbInfo->dwMask & TBIF_STATE)
2371         lpTbInfo->fsState = btnPtr->fsState;
2372     if (lpTbInfo->dwMask & TBIF_STYLE)
2373         lpTbInfo->fsStyle = btnPtr->fsStyle;
2374      if (lpTbInfo->dwMask & TBIF_TEXT) {
2375          if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
2376          {      
2377              if (!WideCharToMultiByte( CP_ACP, 0, (LPWSTR)infoPtr->strings[btnPtr->iString], -1,
2378                                        lpTbInfo->pszText, lpTbInfo->cchText, NULL, NULL ))
2379                  lpTbInfo->pszText[lpTbInfo->cchText-1] = 0;
2380          }
2381          else lpTbInfo->pszText[0]=0;
2382     }
2383     return nIndex;
2384 }
2385
2386
2387 static LRESULT
2388 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2389 {
2390     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2391     LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
2392     TBUTTON_INFO *btnPtr;
2393     INT nIndex;
2394
2395     if (infoPtr == NULL)
2396         return -1;
2397     if (lpTbInfo == NULL)
2398         return -1;
2399     if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
2400         return -1;
2401
2402     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2403     if (nIndex == -1)
2404         return -1;
2405
2406     btnPtr = &infoPtr->buttons[nIndex];
2407
2408     if (lpTbInfo->dwMask & TBIF_COMMAND)
2409         lpTbInfo->idCommand = btnPtr->idCommand;
2410     if (lpTbInfo->dwMask & TBIF_IMAGE)
2411         lpTbInfo->iImage = btnPtr->iBitmap;
2412     if (lpTbInfo->dwMask & TBIF_LPARAM)
2413         lpTbInfo->lParam = btnPtr->dwData;
2414     if (lpTbInfo->dwMask & TBIF_SIZE)
2415         lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2416     if (lpTbInfo->dwMask & TBIF_STATE)
2417         lpTbInfo->fsState = btnPtr->fsState;
2418     if (lpTbInfo->dwMask & TBIF_STYLE)
2419         lpTbInfo->fsStyle = btnPtr->fsStyle;
2420     if (lpTbInfo->dwMask & TBIF_TEXT) {
2421         if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
2422             lstrcpynW (lpTbInfo->pszText,
2423                        (LPWSTR)infoPtr->strings[btnPtr->iString],
2424                        lpTbInfo->cchText);
2425     }
2426
2427     return nIndex;
2428 }
2429
2430
2431 static LRESULT
2432 TOOLBAR_GetButtonSize (HWND hwnd)
2433 {
2434     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2435
2436     return MAKELONG((WORD)infoPtr->nButtonWidth,
2437                     (WORD)infoPtr->nButtonHeight);
2438 }
2439
2440
2441 static LRESULT
2442 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2443 {
2444     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2445     INT nIndex, nStringIndex;
2446
2447     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2448     if (nIndex == -1)
2449         return -1;
2450
2451     nStringIndex = infoPtr->buttons[nIndex].iString;
2452
2453     TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2454
2455     if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2456         return -1;
2457
2458     if (lParam == 0)
2459         return -1;
2460
2461     return WideCharToMultiByte( CP_ACP, 0, (LPWSTR)infoPtr->strings[nStringIndex], -1,
2462                                 (LPSTR)lParam, 0x7fffffff, NULL, NULL ) - 1;
2463 }
2464
2465
2466 static LRESULT
2467 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2468 {
2469     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2470     INT nIndex, nStringIndex;
2471
2472     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2473     if (nIndex == -1)
2474         return -1;
2475
2476     nStringIndex = infoPtr->buttons[nIndex].iString;
2477
2478     TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2479
2480     if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2481         return -1;
2482
2483     if (lParam == 0)
2484         return -1;
2485
2486     strcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2487
2488     return strlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
2489 }
2490
2491
2492 /* << TOOLBAR_GetColorScheme >> */
2493
2494
2495 static LRESULT
2496 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2497 {
2498     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2499
2500     return (LRESULT)infoPtr->himlDis;
2501 }
2502
2503
2504 inline static LRESULT
2505 TOOLBAR_GetExtendedStyle (HWND hwnd)
2506 {
2507     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2508
2509     return infoPtr->dwExStyle;
2510 }
2511
2512
2513 static LRESULT
2514 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2515 {
2516     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2517
2518     return (LRESULT)infoPtr->himlHot;
2519 }
2520
2521
2522 static LRESULT
2523 TOOLBAR_GetHotItem (HWND hwnd)
2524 {
2525     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2526
2527     if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2528         return -1;
2529
2530     if (infoPtr->nHotItem < 0)
2531         return -1;
2532
2533     return (LRESULT)infoPtr->nHotItem;
2534 }
2535
2536
2537 static LRESULT
2538 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2539 {
2540     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2541
2542     return (LRESULT)infoPtr->himlDef;
2543 }
2544
2545
2546 /* << TOOLBAR_GetInsertMark >> */
2547 /* << TOOLBAR_GetInsertMarkColor >> */
2548
2549
2550 static LRESULT
2551 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2552 {
2553     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2554     TBUTTON_INFO *btnPtr;
2555     LPRECT     lpRect;
2556     INT        nIndex;
2557
2558     if (infoPtr == NULL)
2559         return FALSE;
2560     nIndex = (INT)wParam;
2561     btnPtr = &infoPtr->buttons[nIndex];
2562     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2563         return FALSE;
2564     lpRect = (LPRECT)lParam;
2565     if (lpRect == NULL)
2566         return FALSE;
2567     if (btnPtr->fsState & TBSTATE_HIDDEN)
2568         return FALSE;
2569     
2570     lpRect->left   = btnPtr->rect.left;
2571     lpRect->right  = btnPtr->rect.right;
2572     lpRect->bottom = btnPtr->rect.bottom;
2573     lpRect->top    = btnPtr->rect.top;
2574
2575     return TRUE;
2576 }
2577
2578
2579 static LRESULT
2580 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2581 {
2582     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2583     LPSIZE lpSize = (LPSIZE)lParam;
2584
2585     if (lpSize == NULL)
2586         return FALSE;
2587
2588     lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2589     lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2590
2591     TRACE("maximum size %d x %d\n",
2592            infoPtr->rcBound.right - infoPtr->rcBound.left,
2593            infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2594
2595     return TRUE;
2596 }
2597
2598
2599 /* << TOOLBAR_GetObject >> */
2600 /* << TOOLBAR_GetPadding >> */
2601
2602
2603 static LRESULT
2604 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2605 {
2606     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2607     TBUTTON_INFO *btnPtr;
2608     LPRECT     lpRect;
2609     INT        nIndex;
2610
2611     if (infoPtr == NULL)
2612         return FALSE;
2613     nIndex = (INT)wParam;
2614     btnPtr = &infoPtr->buttons[nIndex];
2615     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2616         return FALSE;
2617     lpRect = (LPRECT)lParam;
2618     if (lpRect == NULL)
2619         return FALSE;
2620     
2621     lpRect->left   = btnPtr->rect.left;
2622     lpRect->right  = btnPtr->rect.right;
2623     lpRect->bottom = btnPtr->rect.bottom;
2624     lpRect->top    = btnPtr->rect.top;
2625
2626     return TRUE;
2627 }
2628
2629
2630 static LRESULT
2631 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2632 {
2633     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2634
2635     if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2636         return infoPtr->nRows;
2637     else
2638         return 1;
2639 }
2640
2641
2642 static LRESULT
2643 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2644 {
2645     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2646     INT nIndex;
2647
2648     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2649     if (nIndex == -1)
2650         return -1;
2651
2652     return infoPtr->buttons[nIndex].fsState;
2653 }
2654
2655
2656 static LRESULT
2657 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2658 {
2659     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2660     INT nIndex;
2661
2662     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2663     if (nIndex == -1)
2664         return -1;
2665
2666     return infoPtr->buttons[nIndex].fsStyle;
2667 }
2668
2669
2670 static LRESULT
2671 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2672 {
2673     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2674
2675     if (infoPtr == NULL)
2676         return 0;
2677
2678     return infoPtr->nMaxTextRows;
2679 }
2680
2681
2682 static LRESULT
2683 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2684 {
2685     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2686
2687     if (infoPtr == NULL)
2688         return 0;
2689     return infoPtr->hwndToolTip;
2690 }
2691
2692
2693 static LRESULT
2694 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2695 {
2696     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2697
2698     TRACE("%s hwnd=0x%x stub!\n", 
2699            infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2700
2701     return infoPtr->bUnicode;
2702 }
2703
2704
2705 inline static LRESULT
2706 TOOLBAR_GetVersion (HWND hwnd)
2707 {
2708     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2709     return infoPtr->iVersion;
2710 }
2711
2712
2713 static LRESULT
2714 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2715 {
2716     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2717     TBUTTON_INFO *btnPtr;
2718     INT nIndex;
2719
2720     TRACE("\n");
2721
2722     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2723     if (nIndex == -1)
2724         return FALSE;
2725
2726     btnPtr = &infoPtr->buttons[nIndex];
2727     if (LOWORD(lParam) == FALSE)
2728         btnPtr->fsState &= ~TBSTATE_HIDDEN;
2729     else
2730         btnPtr->fsState |= TBSTATE_HIDDEN;
2731
2732     TOOLBAR_CalcToolbar (hwnd);
2733
2734     InvalidateRect (hwnd, NULL, TRUE);
2735
2736     return TRUE;
2737 }
2738
2739
2740 inline static LRESULT
2741 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2742 {
2743     return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2744 }
2745
2746
2747 static LRESULT
2748 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2749 {
2750     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2751     TBUTTON_INFO *btnPtr;
2752     INT nIndex;
2753
2754     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2755     if (nIndex == -1)
2756         return FALSE;
2757
2758     btnPtr = &infoPtr->buttons[nIndex];
2759     if (LOWORD(lParam) == FALSE)
2760         btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2761     else
2762         btnPtr->fsState |= TBSTATE_INDETERMINATE;
2763
2764     InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
2765
2766     return TRUE;
2767 }
2768
2769
2770 static LRESULT
2771 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2772 {
2773     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2774     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2775     INT nIndex = (INT)wParam;
2776     TBUTTON_INFO *oldButtons;
2777
2778     if (lpTbb == NULL)
2779         return FALSE;
2780
2781     if (nIndex == -1) {
2782        /* EPP: this seems to be an undocumented call (from my IE4)
2783         * I assume in that case that:
2784         * - lpTbb->iString is a string pointer (not a string index in strings[] table
2785         * - index of insertion is at the end of existing buttons
2786         * I only see this happen with nIndex == -1, but it could have a special
2787         * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2788         */
2789        int      len;
2790        LPSTR    ptr;
2791
2792        /* FIXME: iString == -1 is undocumented */
2793        if(lpTbb->iString && lpTbb->iString!=-1) {
2794            len = strlen((char*)lpTbb->iString) + 2;
2795            ptr = COMCTL32_Alloc(len);
2796            nIndex = infoPtr->nNumButtons;
2797            strcpy(ptr, (char*)lpTbb->iString);
2798            ptr[len - 1] = 0; /* ended by two '\0' */
2799            lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2800            COMCTL32_Free(ptr);
2801        }
2802        else {
2803            ERR("lpTbb->iString is NULL\n");
2804            return FALSE;
2805        }
2806
2807     } else if (nIndex < 0)
2808        return FALSE;
2809
2810     TRACE("inserting button index=%d\n", nIndex);
2811     if (nIndex > infoPtr->nNumButtons) {
2812         nIndex = infoPtr->nNumButtons;
2813         TRACE("adjust index=%d\n", nIndex);
2814     }
2815
2816     oldButtons = infoPtr->buttons;
2817     infoPtr->nNumButtons++;
2818     infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2819     /* pre insert copy */
2820     if (nIndex > 0) {
2821         memcpy (&infoPtr->buttons[0], &oldButtons[0],
2822                 nIndex * sizeof(TBUTTON_INFO));
2823     }
2824
2825     /* insert new button */
2826     infoPtr->buttons[nIndex].iBitmap   = lpTbb->iBitmap;
2827     infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2828     infoPtr->buttons[nIndex].fsState   = lpTbb->fsState;
2829     infoPtr->buttons[nIndex].fsStyle   = lpTbb->fsStyle;
2830     infoPtr->buttons[nIndex].dwData    = lpTbb->dwData;
2831     infoPtr->buttons[nIndex].iString   = lpTbb->iString;
2832
2833     if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2834         TTTOOLINFOA ti;
2835
2836         ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2837         ti.cbSize   = sizeof (TTTOOLINFOA);
2838         ti.hwnd     = hwnd;
2839         ti.uId      = lpTbb->idCommand;
2840         ti.hinst    = 0;
2841         ti.lpszText = LPSTR_TEXTCALLBACKA;
2842
2843         SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2844                         0, (LPARAM)&ti);
2845     }
2846
2847     /* post insert copy */
2848     if (nIndex < infoPtr->nNumButtons - 1) {
2849         memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2850                 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2851     }
2852
2853     COMCTL32_Free (oldButtons);
2854
2855     TOOLBAR_CalcToolbar (hwnd);
2856
2857     InvalidateRect (hwnd, NULL, FALSE);
2858
2859     return TRUE;
2860 }
2861
2862
2863 static LRESULT
2864 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2865 {
2866     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2867     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2868     INT nIndex = (INT)wParam;
2869     TBUTTON_INFO *oldButtons;
2870
2871     if (lpTbb == NULL)
2872         return FALSE;
2873     if (nIndex < 0)
2874         return FALSE;
2875
2876     TRACE("inserting button index=%d\n", nIndex);
2877     if (nIndex > infoPtr->nNumButtons) {
2878         nIndex = infoPtr->nNumButtons;
2879         TRACE("adjust index=%d\n", nIndex);
2880     }
2881
2882     oldButtons = infoPtr->buttons;
2883     infoPtr->nNumButtons++;
2884     infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2885     /* pre insert copy */
2886     if (nIndex > 0) {
2887         memcpy (&infoPtr->buttons[0], &oldButtons[0],
2888                 nIndex * sizeof(TBUTTON_INFO));
2889     }
2890
2891     /* insert new button */
2892     infoPtr->buttons[nIndex].iBitmap   = lpTbb->iBitmap;
2893     infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2894     infoPtr->buttons[nIndex].fsState   = lpTbb->fsState;
2895     infoPtr->buttons[nIndex].fsStyle   = lpTbb->fsStyle;
2896     infoPtr->buttons[nIndex].dwData    = lpTbb->dwData;
2897     infoPtr->buttons[nIndex].iString   = lpTbb->iString;
2898
2899     if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2900         TTTOOLINFOW ti;
2901
2902         ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2903         ti.cbSize   = sizeof (TTTOOLINFOW);
2904         ti.hwnd     = hwnd;
2905         ti.uId      = lpTbb->idCommand;
2906         ti.hinst    = 0;
2907         ti.lpszText = LPSTR_TEXTCALLBACKW;
2908
2909         SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2910                         0, (LPARAM)&ti);
2911     }
2912
2913     /* post insert copy */
2914     if (nIndex < infoPtr->nNumButtons - 1) {
2915         memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2916                 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2917     }
2918
2919     COMCTL32_Free (oldButtons);
2920
2921     InvalidateRect (hwnd, NULL, FALSE);
2922
2923     return TRUE;
2924 }
2925
2926
2927 /* << TOOLBAR_InsertMarkHitTest >> */
2928
2929
2930 static LRESULT
2931 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2932 {
2933     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2934     INT nIndex;
2935
2936     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2937     if (nIndex == -1)
2938         return FALSE;
2939
2940     return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2941 }
2942
2943
2944 static LRESULT
2945 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2946 {
2947     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2948     INT nIndex;
2949
2950     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2951     if (nIndex == -1)
2952         return FALSE;
2953
2954     return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2955 }
2956
2957
2958 static LRESULT
2959 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2960 {
2961     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2962     INT nIndex;
2963
2964     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2965     if (nIndex == -1)
2966         return TRUE;
2967
2968     return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2969 }
2970
2971
2972 static LRESULT
2973 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2974 {
2975     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2976     INT nIndex;
2977
2978     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2979     if (nIndex == -1)
2980         return FALSE;
2981
2982     return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2983 }
2984
2985
2986 static LRESULT
2987 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2988 {
2989     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2990     INT nIndex;
2991
2992     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2993     if (nIndex == -1)
2994         return FALSE;
2995
2996     return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2997 }
2998
2999
3000 static LRESULT
3001 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
3002 {
3003     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3004     INT nIndex;
3005
3006     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3007     if (nIndex == -1)
3008         return FALSE;
3009
3010     return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
3011 }
3012
3013
3014 /* << TOOLBAR_LoadImages >> */
3015 /* << TOOLBAR_MapAccelerator >> */
3016 /* << TOOLBAR_MarkButton >> */
3017 /* << TOOLBAR_MoveButton >> */
3018
3019
3020 static LRESULT
3021 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
3022 {
3023     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3024     TBUTTON_INFO *btnPtr;
3025     INT nIndex;
3026
3027     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3028     if (nIndex == -1)
3029         return FALSE;
3030
3031     btnPtr = &infoPtr->buttons[nIndex];
3032     if (LOWORD(lParam) == FALSE)
3033         btnPtr->fsState &= ~TBSTATE_PRESSED;
3034     else
3035         btnPtr->fsState |= TBSTATE_PRESSED;
3036
3037     InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
3038
3039     return TRUE;
3040 }
3041
3042
3043 /* << TOOLBAR_ReplaceBitmap >> */
3044
3045
3046 static LRESULT
3047 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3048 {
3049 #if 0
3050     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3051     LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
3052
3053     if (lpSave == NULL) return 0;
3054
3055     if ((BOOL)wParam) {
3056         /* save toolbar information */
3057         FIXME("save to \"%s\" \"%s\"\n",
3058                lpSave->pszSubKey, lpSave->pszValueName);
3059
3060
3061     }
3062     else {
3063         /* restore toolbar information */
3064
3065         FIXME("restore from \"%s\" \"%s\"\n",
3066                lpSave->pszSubKey, lpSave->pszValueName);
3067
3068
3069     }
3070 #endif
3071
3072     return 0;
3073 }
3074
3075
3076 static LRESULT
3077 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3078 {
3079 #if 0
3080     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3081     LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
3082
3083     if (lpSave == NULL)
3084         return 0;
3085
3086     if ((BOOL)wParam) {
3087         /* save toolbar information */
3088         FIXME("save to \"%s\" \"%s\"\n",
3089                lpSave->pszSubKey, lpSave->pszValueName);
3090
3091
3092     }
3093     else {
3094         /* restore toolbar information */
3095
3096         FIXME("restore from \"%s\" \"%s\"\n",
3097                lpSave->pszSubKey, lpSave->pszValueName);
3098
3099
3100     }
3101 #endif
3102
3103     return 0;
3104 }
3105
3106
3107 static LRESULT
3108 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
3109 {
3110     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3111     BOOL bOldAnchor = infoPtr->bAnchor;
3112
3113     infoPtr->bAnchor = (BOOL)wParam;
3114
3115     return (LRESULT)bOldAnchor;
3116 }
3117
3118
3119 static LRESULT
3120 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3121 {
3122     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3123
3124     if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3125         return FALSE;
3126
3127     if (infoPtr->nNumButtons > 0)
3128         WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
3129              infoPtr->nNumButtons,
3130              infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
3131              LOWORD(lParam), HIWORD(lParam));
3132
3133     infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
3134     infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
3135
3136     /* uses image list internals directly */
3137     if (infoPtr->himlDef) {
3138         infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
3139         infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
3140     }
3141
3142     return TRUE;
3143 }
3144
3145
3146 static LRESULT
3147 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3148 {
3149     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3150     LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
3151     TBUTTON_INFO *btnPtr;
3152     INT nIndex;
3153
3154     if (lptbbi == NULL)
3155         return FALSE;
3156     if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
3157         return FALSE;
3158     
3159     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3160     if (nIndex == -1)
3161         return FALSE;
3162
3163     btnPtr = &infoPtr->buttons[nIndex];
3164     if (lptbbi->dwMask & TBIF_COMMAND)
3165         btnPtr->idCommand = lptbbi->idCommand;
3166     if (lptbbi->dwMask & TBIF_IMAGE)
3167         btnPtr->iBitmap = lptbbi->iImage;
3168     if (lptbbi->dwMask & TBIF_LPARAM)
3169         btnPtr->dwData = lptbbi->lParam;
3170 /*    if (lptbbi->dwMask & TBIF_SIZE) */
3171 /*      btnPtr->cx = lptbbi->cx; */
3172     if (lptbbi->dwMask & TBIF_STATE)
3173         btnPtr->fsState = lptbbi->fsState;
3174     if (lptbbi->dwMask & TBIF_STYLE)
3175         btnPtr->fsStyle = lptbbi->fsStyle;
3176
3177     if (lptbbi->dwMask & TBIF_TEXT) {
3178         if ((btnPtr->iString >= 0) || 
3179             (btnPtr->iString < infoPtr->nNumStrings)) {
3180            TRACE("Ooooooch\n");
3181 #if 0
3182             WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
3183             INT len = lstrlenA (lptbbi->pszText);
3184             *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
3185 #endif
3186
3187             /* this is the ultimate sollution */
3188 /*          Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
3189         }
3190     }
3191
3192     return TRUE;
3193 }
3194
3195
3196 static LRESULT
3197 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3198 {
3199     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3200     LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
3201     TBUTTON_INFO *btnPtr;
3202     INT nIndex;
3203
3204     if (lptbbi == NULL)
3205         return FALSE;
3206     if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
3207         return FALSE;
3208
3209     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3210     if (nIndex == -1)
3211         return FALSE;
3212
3213     btnPtr = &infoPtr->buttons[nIndex];
3214     if (lptbbi->dwMask & TBIF_COMMAND)
3215         btnPtr->idCommand = lptbbi->idCommand;
3216     if (lptbbi->dwMask & TBIF_IMAGE)
3217         btnPtr->iBitmap = lptbbi->iImage;
3218     if (lptbbi->dwMask & TBIF_LPARAM)
3219         btnPtr->dwData = lptbbi->lParam;
3220 /*    if (lptbbi->dwMask & TBIF_SIZE) */
3221 /*      btnPtr->cx = lptbbi->cx; */
3222     if (lptbbi->dwMask & TBIF_STATE)
3223         btnPtr->fsState = lptbbi->fsState;
3224     if (lptbbi->dwMask & TBIF_STYLE)
3225         btnPtr->fsStyle = lptbbi->fsStyle;
3226
3227     if (lptbbi->dwMask & TBIF_TEXT) {
3228         if ((btnPtr->iString >= 0) ||
3229             (btnPtr->iString < infoPtr->nNumStrings)) {
3230 #if 0
3231             WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
3232             INT len = lstrlenW (lptbbi->pszText);
3233             *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
3234 #endif
3235
3236             /* this is the ultimate solution */
3237 /*          Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
3238         }
3239     }
3240
3241     return TRUE;
3242 }
3243
3244
3245 static LRESULT
3246 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3247 {
3248     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3249
3250     if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3251     {
3252         ERR("invalid parameter\n");
3253         return FALSE;
3254     }
3255
3256     /* The documentation claims you can only change the button size before
3257      * any button has been added. But this is wrong. 
3258      * WINZIP32.EXE (ver 8) calls this on one of its buttons after adding 
3259      * it to the toolbar, and it checks that the return value is nonzero - mjm
3260      * Further testing shows that we must actually perform the change too.
3261      */
3262     infoPtr->nButtonWidth = (INT)LOWORD(lParam);
3263     infoPtr->nButtonHeight = (INT)HIWORD(lParam);
3264     return TRUE;
3265 }
3266
3267
3268 static LRESULT
3269 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
3270 {
3271     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3272
3273     if (infoPtr == NULL) {
3274         TRACE("Toolbar not initialized yet?????\n");
3275         return FALSE;
3276     }
3277
3278     /* if setting to current values, ignore */
3279     if ((infoPtr->cxMin == (INT)LOWORD(lParam)) &&
3280         (infoPtr->cxMax == (INT)HIWORD(lParam))) {
3281         TRACE("matches current width, min=%d, max=%d, no recalc\n",
3282               infoPtr->cxMin, infoPtr->cxMax);
3283         return TRUE; 
3284     }
3285
3286     /* save new values */
3287     infoPtr->cxMin = (INT)LOWORD(lParam);
3288     infoPtr->cxMax = (INT)HIWORD(lParam);
3289
3290     /* if both values are 0 then we are done */
3291     if (lParam == 0) {
3292         TRACE("setting both min and max to 0, norecalc\n"); 
3293         return TRUE;
3294     }
3295
3296     /* otherwise we need to recalc the toolbar and in some cases
3297        recalc the bounding rectangle (does DrawText w/ DT_CALCRECT
3298        which doesn't actually draw - GA). */
3299     TRACE("number of buttons %d, cx=%d, cy=%d, recalcing\n", 
3300         infoPtr->nNumButtons, infoPtr->cxMin, infoPtr->cxMax);
3301
3302     TOOLBAR_CalcToolbar (hwnd);
3303
3304     InvalidateRect (hwnd, NULL, TRUE);
3305
3306     return TRUE;
3307 }
3308
3309
3310 static LRESULT
3311 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
3312 {
3313     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3314     INT nIndex = (INT)wParam;
3315
3316     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
3317         return FALSE;
3318
3319     infoPtr->buttons[nIndex].idCommand = (INT)lParam;
3320
3321     if (infoPtr->hwndToolTip) {
3322
3323         FIXME("change tool tip!\n");
3324
3325     }
3326
3327     return TRUE;
3328 }
3329
3330
3331 /* << TOOLBAR_SetColorScheme >> */
3332
3333
3334 static LRESULT
3335 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3336 {
3337     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3338     HIMAGELIST himlTemp;
3339
3340
3341     himlTemp = infoPtr->himlDis;
3342     infoPtr->himlDis = (HIMAGELIST)lParam;
3343
3344     /* FIXME: redraw ? */
3345
3346     return (LRESULT)himlTemp; 
3347 }
3348
3349
3350 static LRESULT
3351 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
3352 {
3353     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3354     DWORD dwTemp;
3355
3356     dwTemp = infoPtr->dwDTFlags;
3357     infoPtr->dwDTFlags =
3358         (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
3359
3360     return (LRESULT)dwTemp;
3361 }
3362
3363
3364 static LRESULT
3365 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3366 {
3367     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3368     DWORD dwTemp;
3369
3370     dwTemp = infoPtr->dwExStyle;
3371     infoPtr->dwExStyle = (DWORD)lParam;
3372
3373     return (LRESULT)dwTemp; 
3374 }
3375
3376
3377 static LRESULT
3378 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3379 {
3380     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3381     HIMAGELIST himlTemp;
3382
3383     himlTemp = infoPtr->himlHot;
3384     infoPtr->himlHot = (HIMAGELIST)lParam;
3385
3386     /* FIXME: redraw ? */
3387
3388     return (LRESULT)himlTemp; 
3389 }
3390
3391
3392 static LRESULT
3393 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
3394 {
3395     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3396     INT nOldHotItem = infoPtr->nHotItem;
3397     TBUTTON_INFO *btnPtr;
3398
3399     if ((INT) wParam < 0 || (INT)wParam > infoPtr->nNumButtons)
3400         wParam = -2;
3401
3402     if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
3403     {
3404
3405         infoPtr->nHotItem = (INT)wParam;
3406         if ((INT)wParam >=0)
3407         {
3408             btnPtr = &infoPtr->buttons[(INT)wParam];
3409             btnPtr->bHot = TRUE;
3410                 InvalidateRect (hwnd, &btnPtr->rect,
3411                     TOOLBAR_HasText(infoPtr, btnPtr));
3412         }
3413         if (nOldHotItem>=0)
3414         {
3415             btnPtr = &infoPtr->buttons[nOldHotItem];
3416             btnPtr->bHot = FALSE;
3417                 InvalidateRect (hwnd, &btnPtr->rect,
3418                     TOOLBAR_HasText(infoPtr, btnPtr));
3419         }
3420     }
3421
3422     if (nOldHotItem < 0)
3423         return -1;
3424
3425     return (LRESULT)nOldHotItem;
3426 }
3427
3428
3429 static LRESULT
3430 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3431 {
3432     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3433     HIMAGELIST himlTemp;
3434
3435     himlTemp = infoPtr->himlDef;
3436     infoPtr->himlDef = (HIMAGELIST)lParam;
3437
3438      infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
3439     /* FIXME: redraw ? */
3440
3441     return (LRESULT)himlTemp; 
3442 }
3443
3444
3445 static LRESULT
3446 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3447 {
3448     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3449
3450     infoPtr->nIndent = (INT)wParam;
3451
3452     TRACE("\n");
3453
3454     /* process only on indent changing */
3455     if(infoPtr->nIndent != (INT)wParam)
3456     {
3457         infoPtr->nIndent = (INT)wParam;
3458         TOOLBAR_CalcToolbar (hwnd);
3459         InvalidateRect(hwnd, NULL, FALSE);
3460     }
3461
3462     return TRUE;
3463 }
3464
3465
3466 /* << TOOLBAR_SetInsertMark >> */
3467
3468
3469 static LRESULT
3470 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
3471 {
3472     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3473
3474     infoPtr->clrInsertMark = (COLORREF)lParam;
3475
3476     /* FIXME : redraw ??*/
3477
3478     return 0;
3479 }
3480
3481
3482 static LRESULT
3483 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3484 {
3485     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3486
3487     if (infoPtr == NULL)
3488         return FALSE;
3489
3490     infoPtr->nMaxTextRows = (INT)wParam;
3491
3492     return TRUE;
3493 }
3494
3495
3496 /* << TOOLBAR_SetPadding >> */
3497
3498
3499 static LRESULT
3500 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3501 {
3502     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3503     HWND hwndOldNotify;
3504
3505     TRACE("\n");
3506
3507     if (infoPtr == NULL)
3508         return 0;
3509     hwndOldNotify = infoPtr->hwndNotify;
3510     infoPtr->hwndNotify = (HWND)wParam;
3511
3512     return hwndOldNotify;
3513 }
3514
3515
3516 static LRESULT
3517 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3518 {
3519     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3520     LPRECT lprc = (LPRECT)lParam;
3521
3522     TRACE("\n");
3523
3524     if (LOWORD(wParam) > 1) {
3525         FIXME("multiple rows not supported!\n");
3526     }
3527
3528     if(infoPtr->nRows != LOWORD(wParam))
3529     {
3530         infoPtr->nRows = LOWORD(wParam);
3531
3532         /* recalculate toolbar */
3533         TOOLBAR_CalcToolbar (hwnd);
3534
3535         /* repaint toolbar */
3536         InvalidateRect(hwnd, NULL, FALSE);
3537     }
3538
3539     /* return bounding rectangle */
3540     if (lprc) {
3541         lprc->left   = infoPtr->rcBound.left;
3542         lprc->right  = infoPtr->rcBound.right;
3543         lprc->top    = infoPtr->rcBound.top;
3544         lprc->bottom = infoPtr->rcBound.bottom;
3545     }
3546
3547     return 0;
3548 }
3549
3550
3551 static LRESULT
3552 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
3553 {
3554     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3555     TBUTTON_INFO *btnPtr;
3556     INT nIndex;
3557
3558     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3559     if (nIndex == -1)
3560         return FALSE;
3561
3562     btnPtr = &infoPtr->buttons[nIndex];
3563
3564     /* process state changing if current state doesn't match new state */
3565     if(btnPtr->fsState != LOWORD(lParam))
3566     {
3567         btnPtr->fsState = LOWORD(lParam);
3568         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3569             btnPtr));
3570     }
3571
3572     return TRUE;
3573 }
3574
3575
3576 static LRESULT
3577 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3578 {
3579     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3580     TBUTTON_INFO *btnPtr;
3581     INT nIndex;
3582
3583     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3584     if (nIndex == -1)
3585         return FALSE;
3586
3587     btnPtr = &infoPtr->buttons[nIndex];
3588
3589     /* process style change if current style doesn't match new style */
3590     if(btnPtr->fsStyle != LOWORD(lParam))
3591     {
3592         btnPtr->fsStyle = LOWORD(lParam);
3593         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3594             btnPtr));
3595
3596         if (infoPtr->hwndToolTip) {
3597             FIXME("change tool tip!\n");
3598         }
3599     }
3600
3601     return TRUE;
3602 }
3603
3604
3605 inline static LRESULT
3606 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3607 {
3608     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3609
3610     if (infoPtr == NULL)
3611         return 0;
3612     infoPtr->hwndToolTip = (HWND)wParam;
3613     return 0;
3614 }
3615
3616
3617 static LRESULT
3618 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3619 {
3620     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3621     BOOL bTemp;
3622
3623     TRACE("%s hwnd=0x%04x stub!\n", 
3624            ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3625
3626     bTemp = infoPtr->bUnicode;
3627     infoPtr->bUnicode = (BOOL)wParam;
3628
3629     return bTemp;
3630 }
3631
3632
3633 static LRESULT
3634 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3635 {
3636     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3637     INT iOldVersion = infoPtr->iVersion;
3638
3639     infoPtr->iVersion = iVersion;
3640
3641     return iOldVersion;
3642 }
3643
3644
3645 static LRESULT
3646 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3647 {
3648     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3649     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3650     LOGFONTA logFont;
3651
3652     /* initialize info structure */
3653     infoPtr->nButtonHeight = 22;
3654     infoPtr->nButtonWidth = 24;
3655     infoPtr->nBitmapHeight = 15;
3656     infoPtr->nBitmapWidth = 16;
3657
3658     infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3659     infoPtr->nRows = 1;
3660     infoPtr->nMaxTextRows = 1;
3661     infoPtr->cxMin = -1;
3662     infoPtr->cxMax = -1;
3663     infoPtr->nNumBitmaps = 0;
3664     infoPtr->nNumStrings = 0;
3665
3666     infoPtr->bCaptured = FALSE;
3667     infoPtr->bUnicode = IsWindowUnicode (hwnd);
3668     infoPtr->nButtonDown = -1;
3669     infoPtr->nOldHit = -1;
3670     infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3671     infoPtr->hwndNotify = GetParent (hwnd);
3672     infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3673     infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3674     infoPtr->bAnchor = FALSE; /* no anchor highlighting */
3675     infoPtr->iVersion = 0;
3676
3677     SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
3678     infoPtr->hFont = CreateFontIndirectA (&logFont);
3679
3680     if (dwStyle & TBSTYLE_TOOLTIPS) {
3681         /* Create tooltip control */
3682         infoPtr->hwndToolTip =
3683             CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
3684                                CW_USEDEFAULT, CW_USEDEFAULT,
3685                                CW_USEDEFAULT, CW_USEDEFAULT,
3686                                hwnd, 0, 0, 0);
3687
3688         /* Send NM_TOOLTIPSCREATED notification */
3689         if (infoPtr->hwndToolTip) {
3690             NMTOOLTIPSCREATED nmttc;
3691
3692             nmttc.hdr.hwndFrom = hwnd;
3693             nmttc.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
3694             nmttc.hdr.code = NM_TOOLTIPSCREATED;
3695             nmttc.hwndToolTips = infoPtr->hwndToolTip;
3696
3697             SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3698                           (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
3699         }
3700     }
3701
3702     TOOLBAR_CalcToolbar(hwnd);
3703
3704     return 0;
3705 }
3706
3707
3708 static LRESULT
3709 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3710 {
3711     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3712
3713     /* delete tooltip control */
3714     if (infoPtr->hwndToolTip)
3715         DestroyWindow (infoPtr->hwndToolTip);
3716
3717     /* delete button data */
3718     if (infoPtr->buttons)
3719         COMCTL32_Free (infoPtr->buttons);
3720
3721     /* delete strings */
3722     if (infoPtr->strings) {
3723         INT i;
3724         for (i = 0; i < infoPtr->nNumStrings; i++)
3725             if (infoPtr->strings[i])
3726                 COMCTL32_Free (infoPtr->strings[i]);
3727
3728         COMCTL32_Free (infoPtr->strings);
3729     }
3730
3731     /* destroy internal image list */
3732     if (infoPtr->himlInt)
3733         ImageList_Destroy (infoPtr->himlInt);
3734
3735     /* delete default font */
3736     if (infoPtr->hFont)
3737         DeleteObject (infoPtr->hFont);
3738
3739     /* free toolbar info data */
3740     COMCTL32_Free (infoPtr);
3741     SetWindowLongA (hwnd, 0, 0);
3742
3743     return 0;
3744 }
3745
3746
3747 static LRESULT
3748 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3749 {
3750     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3751
3752     if (infoPtr->bTransparent)
3753         return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3754
3755     return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3756 }
3757
3758
3759 static LRESULT
3760 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3761 {
3762     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3763
3764     return infoPtr->hFont;
3765 }
3766
3767
3768 static LRESULT
3769 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3770 {
3771     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3772     TBUTTON_INFO *btnPtr;
3773     POINT pt;
3774     INT   nHit;
3775
3776     pt.x = (INT)LOWORD(lParam);
3777     pt.y = (INT)HIWORD(lParam);
3778     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3779
3780     if (nHit >= 0) {
3781         btnPtr = &infoPtr->buttons[nHit];
3782         if (!(btnPtr->fsState & TBSTATE_ENABLED))
3783             return 0;
3784         SetCapture (hwnd);
3785         infoPtr->bCaptured = TRUE;
3786         infoPtr->nButtonDown = nHit;
3787
3788         btnPtr->fsState |= TBSTATE_PRESSED;
3789
3790         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3791             btnPtr));
3792     }
3793     else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3794         TOOLBAR_Customize (hwnd);
3795
3796     return 0;
3797 }
3798
3799
3800 static LRESULT
3801 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3802 {
3803     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3804     TBUTTON_INFO *btnPtr;
3805     POINT pt;
3806     INT   nHit;
3807
3808     if (infoPtr->hwndToolTip)
3809         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3810                             WM_LBUTTONDOWN, wParam, lParam);
3811
3812     pt.x = (INT)LOWORD(lParam);
3813     pt.y = (INT)HIWORD(lParam);
3814     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3815
3816     if (nHit >= 0) {
3817         RECT arrowRect;
3818         btnPtr = &infoPtr->buttons[nHit];
3819         if (!(btnPtr->fsState & TBSTATE_ENABLED))
3820             return 0;
3821
3822         infoPtr->nOldHit = nHit;
3823
3824         CopyRect(&arrowRect, &btnPtr->rect);
3825         arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
3826
3827         /* for EX_DRAWDDARROWS style,  click must be in the drop-down arrow rect */
3828         if ((btnPtr->fsStyle & TBSTYLE_DROPDOWN) &&
3829              ((TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && PtInRect(&arrowRect, pt)) ||
3830               (!TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle))))
3831         {
3832             NMTOOLBARA nmtb;
3833             /*
3834              * this time we must force a Redraw, so the btn is
3835              * painted down before CaptureChanged repaints it up
3836              */
3837             RedrawWindow(hwnd,&btnPtr->rect,0,
3838                         RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3839
3840             nmtb.hdr.hwndFrom = hwnd;
3841             nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3842             nmtb.hdr.code = TBN_DROPDOWN;
3843             nmtb.iItem = btnPtr->idCommand;
3844
3845             SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3846                           (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3847         }
3848         else
3849         {
3850             SetCapture (hwnd);
3851             infoPtr->bCaptured = TRUE;
3852             infoPtr->nButtonDown = nHit;
3853
3854             btnPtr->fsState |= TBSTATE_PRESSED;
3855             btnPtr->bHot = FALSE;
3856
3857             InvalidateRect(hwnd, &btnPtr->rect,
3858                            TOOLBAR_HasText(infoPtr, btnPtr));
3859         }
3860     }
3861
3862     return 0;
3863 }
3864
3865 static LRESULT
3866 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3867 {
3868     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3869     TBUTTON_INFO *btnPtr;
3870     POINT pt;
3871     INT   nHit;
3872     INT   nOldIndex = -1;
3873     BOOL  bSendMessage = TRUE;
3874
3875     if (infoPtr->hwndToolTip)
3876         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3877                             WM_LBUTTONUP, wParam, lParam);
3878
3879     pt.x = (INT)LOWORD(lParam);
3880     pt.y = (INT)HIWORD(lParam);
3881     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3882
3883     /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3884     /* if the cursor is still inside of the toolbar */
3885     if((infoPtr->nHotItem >= 0) && (nHit != -1))
3886         infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
3887
3888     if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3889         btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3890         btnPtr->fsState &= ~TBSTATE_PRESSED;
3891
3892         if (nHit == infoPtr->nButtonDown) {
3893             if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3894                 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3895                     nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3896                         infoPtr->nButtonDown);
3897                     if (nOldIndex == infoPtr->nButtonDown)
3898                         bSendMessage = FALSE;
3899                     if ((nOldIndex != infoPtr->nButtonDown) && 
3900                         (nOldIndex != -1))
3901                         infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3902                     btnPtr->fsState |= TBSTATE_CHECKED;
3903                 }
3904                 else {
3905                     if (btnPtr->fsState & TBSTATE_CHECKED)
3906                         btnPtr->fsState &= ~TBSTATE_CHECKED;
3907                     else
3908                         btnPtr->fsState |= TBSTATE_CHECKED;
3909                 }
3910             }
3911         }
3912         else
3913             bSendMessage = FALSE;
3914
3915         if (nOldIndex != -1)
3916         {
3917             InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
3918                 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
3919         }
3920
3921         /*
3922          * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
3923          * that resets bCaptured and btn TBSTATE_PRESSED flags,
3924          * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged) 
3925          */
3926         ReleaseCapture ();
3927
3928         if (bSendMessage)
3929             SendMessageA (GetParent(hwnd), WM_COMMAND,
3930                           MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3931     }
3932
3933     return 0;
3934 }
3935
3936 static LRESULT
3937 TOOLBAR_CaptureChanged(HWND hwnd)
3938 {
3939     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3940     TBUTTON_INFO *btnPtr;
3941
3942     infoPtr->bCaptured = FALSE;
3943
3944     if (infoPtr->nButtonDown >= 0)
3945     {
3946         btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3947         btnPtr->fsState &= ~TBSTATE_PRESSED;
3948
3949         infoPtr->nButtonDown = -1;
3950         infoPtr->nOldHit = -1;
3951
3952         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3953             btnPtr));
3954     }
3955     return 0;
3956 }
3957
3958 static LRESULT
3959 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3960 {
3961     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3962     TBUTTON_INFO *hotBtnPtr, *btnPtr;
3963
3964     if (infoPtr->nOldHit < 0)
3965       return TRUE;
3966
3967     hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3968
3969     /* Redraw the button if the last button we were over is the hot button and it
3970        is enabled */
3971     if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3972     {
3973         hotBtnPtr->bHot = FALSE;
3974
3975         InvalidateRect (hwnd, &hotBtnPtr->rect, TOOLBAR_HasText(infoPtr,
3976             hotBtnPtr));
3977     }
3978
3979     /* If the last button we were over is depressed then make it not */
3980     /* depressed and redraw it */
3981     if(infoPtr->nOldHit == infoPtr->nButtonDown)
3982     {
3983       btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3984
3985       btnPtr->fsState &= ~TBSTATE_PRESSED;
3986
3987       InvalidateRect (hwnd, &(btnPtr->rect), TRUE);
3988     }
3989
3990     infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3991     infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3992
3993     return TRUE;
3994 }
3995
3996 static LRESULT
3997 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3998 {
3999     TBUTTON_INFO *btnPtr, *oldBtnPtr;
4000     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4001     POINT pt;
4002     INT   nHit;
4003     TRACKMOUSEEVENT trackinfo;
4004
4005     /* fill in the TRACKMOUSEEVENT struct */
4006     trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
4007     trackinfo.dwFlags = TME_QUERY;
4008     trackinfo.hwndTrack = hwnd;
4009     trackinfo.dwHoverTime = HOVER_DEFAULT;
4010
4011     /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
4012     _TrackMouseEvent(&trackinfo);
4013
4014     /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
4015     if(!(trackinfo.dwFlags & TME_LEAVE)) {
4016         trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
4017  
4018         /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
4019         /* and can properly deactivate the hot toolbar button */
4020         _TrackMouseEvent(&trackinfo);
4021    }
4022
4023     if (infoPtr->hwndToolTip)
4024         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
4025                             WM_MOUSEMOVE, wParam, lParam);
4026
4027     pt.x = (INT)LOWORD(lParam);
4028     pt.y = (INT)HIWORD(lParam);
4029
4030     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
4031
4032     if (infoPtr->nOldHit != nHit)
4033     {
4034         /* Remove the effect of an old hot button if the button was enabled and was
4035            drawn with the hot button effect */
4036         if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem && 
4037                 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
4038         {
4039             oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
4040             oldBtnPtr->bHot = FALSE;
4041                     
4042             InvalidateRect (hwnd, &oldBtnPtr->rect,
4043                 TOOLBAR_HasText(infoPtr, oldBtnPtr));
4044         }
4045
4046         /* It's not a separator or in nowhere. It's a hot button. */
4047         if (nHit >= 0)
4048         {
4049             btnPtr = &infoPtr->buttons[nHit];
4050             btnPtr->bHot = TRUE;
4051
4052             infoPtr->nHotItem = nHit;
4053
4054             /* only enabled buttons show hot effect */            
4055             if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
4056             {
4057                 InvalidateRect(hwnd, &btnPtr->rect,
4058                     TOOLBAR_HasText(infoPtr, btnPtr));
4059             }
4060
4061         }
4062
4063     if (infoPtr->bCaptured) {
4064             btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
4065             if (infoPtr->nOldHit == infoPtr->nButtonDown) {
4066                 btnPtr->fsState &= ~TBSTATE_PRESSED;
4067                 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
4068             }
4069             else if (nHit == infoPtr->nButtonDown) {
4070                 btnPtr->fsState |= TBSTATE_PRESSED;
4071                 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
4072             }
4073         }
4074         infoPtr->nOldHit = nHit;
4075     }
4076     return 0;
4077 }
4078
4079
4080 inline static LRESULT
4081 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4082 {
4083 /*    if (wndPtr->dwStyle & CCS_NODIVIDER) */
4084         return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
4085 /*    else */
4086 /*      return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
4087 }
4088
4089
4090 inline static LRESULT
4091 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
4092 {
4093     if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
4094         ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
4095
4096     return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
4097 }
4098
4099
4100 static LRESULT
4101 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4102 {
4103     TOOLBAR_INFO *infoPtr;
4104
4105     /* allocate memory for info structure */
4106     infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
4107     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
4108
4109     /* paranoid!! */
4110     infoPtr->dwStructSize = sizeof(TBBUTTON);
4111
4112     /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
4113     if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
4114         HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
4115         SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
4116     }
4117
4118     return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
4119 }
4120
4121
4122 static LRESULT
4123 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
4124 {
4125     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4126     RECT rcWindow;
4127     HDC hdc;
4128
4129     if (dwStyle & WS_MINIMIZE)
4130         return 0; /* Nothing to do */
4131
4132     DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
4133
4134     if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
4135         return 0;
4136
4137     if (!(dwStyle & CCS_NODIVIDER))
4138     {
4139         GetWindowRect (hwnd, &rcWindow);
4140         OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
4141         if( dwStyle & WS_BORDER )
4142             OffsetRect (&rcWindow, 1, 1);
4143         DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
4144     }
4145
4146     ReleaseDC( hwnd, hdc );
4147
4148     return 0;
4149 }
4150
4151
4152 inline static LRESULT
4153 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
4154 {
4155     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4156     LPNMHDR lpnmh = (LPNMHDR)lParam;
4157
4158     TRACE("passing WM_NOTIFY!\n");
4159
4160     if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
4161         SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,   wParam, lParam);
4162
4163 #if 0
4164         if (lpnmh->code == TTN_GETDISPINFOA) {
4165             LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
4166
4167             FIXME("retrieving ASCII string\n");
4168
4169         }
4170         else if (lpnmh->code == TTN_GETDISPINFOW) {
4171             LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
4172
4173             FIXME("retrieving UNICODE string\n");
4174
4175         }
4176 #endif
4177     }
4178
4179     return 0;
4180 }
4181
4182
4183 static LRESULT
4184 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
4185 {
4186     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
4187     HDC hdc;
4188     PAINTSTRUCT ps;
4189
4190     /* fill ps.rcPaint with a default rect */
4191     memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound)); 
4192
4193     hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
4194
4195     TRACE("psrect=(%d,%d)-(%d,%d)\n",
4196           ps.rcPaint.left, ps.rcPaint.top,
4197           ps.rcPaint.right, ps.rcPaint.bottom);
4198
4199     TOOLBAR_Refresh (hwnd, hdc, &ps);
4200     if (!wParam) EndPaint (hwnd, &ps);
4201
4202     return 0;
4203 }
4204
4205
4206 static LRESULT
4207 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
4208 {
4209     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4210     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4211     RECT parent_rect;
4212     RECT window_rect;
4213     HWND parent;
4214     INT  x, y;
4215     INT  cx, cy;
4216     INT  flags;
4217     UINT uPosFlags = 0;
4218
4219     /* Resize deadlock check */
4220     if (infoPtr->bAutoSize) {
4221         infoPtr->bAutoSize = FALSE;
4222         return 0;
4223     }
4224
4225     /* FIXME: optimize to only update size if the new size doesn't */
4226     /* match the current size */
4227
4228     flags = (INT) wParam;
4229
4230     /* FIXME for flags =
4231      * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
4232      */
4233
4234     TRACE("sizing toolbar!\n");
4235
4236     if (flags == SIZE_RESTORED) {
4237         /* width and height don't apply */
4238         parent = GetParent (hwnd);
4239         GetClientRect(parent, &parent_rect);
4240         x = parent_rect.left;
4241         y = parent_rect.top;
4242
4243         if (dwStyle & CCS_NORESIZE) {
4244             uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
4245
4246             /*
4247              * this sets the working width of the toolbar, and
4248              * Calc Toolbar will not adjust it, only the height
4249              */
4250             infoPtr->nWidth = parent_rect.right - parent_rect.left; 
4251             cy = infoPtr->nHeight;
4252             cx = infoPtr->nWidth;
4253             TOOLBAR_CalcToolbar (hwnd);
4254             infoPtr->nWidth = cx;
4255             infoPtr->nHeight = cy;
4256         }
4257         else {
4258             infoPtr->nWidth = parent_rect.right - parent_rect.left;
4259             TOOLBAR_CalcToolbar (hwnd);
4260             cy = infoPtr->nHeight;
4261             cx = infoPtr->nWidth;
4262
4263             if (dwStyle & CCS_NOMOVEY) {
4264                 GetWindowRect(hwnd, &window_rect);
4265                 ScreenToClient(parent, (LPPOINT)&window_rect.left);
4266                 y = window_rect.top;
4267             }
4268         }
4269
4270         if (dwStyle & CCS_NOPARENTALIGN) {
4271             uPosFlags |= SWP_NOMOVE;
4272             cy = infoPtr->nHeight;
4273             cx = infoPtr->nWidth;
4274         }
4275
4276         if (!(dwStyle & CCS_NODIVIDER))
4277             cy += GetSystemMetrics(SM_CYEDGE);
4278
4279         if (dwStyle & WS_BORDER)
4280         {
4281             x = y = 1;
4282             cy += GetSystemMetrics(SM_CYEDGE);
4283             cx += GetSystemMetrics(SM_CYEDGE);
4284         }
4285
4286         SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
4287                         cx, cy, uPosFlags | SWP_NOZORDER);
4288     }
4289     return 0;
4290 }
4291
4292
4293 static LRESULT
4294 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
4295 {
4296     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4297
4298     if (nType == GWL_STYLE) {
4299         if (lpStyle->styleNew & TBSTYLE_LIST) {
4300             infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
4301         }
4302         else {
4303             infoPtr->dwDTFlags = DT_CENTER;
4304         }
4305     }
4306
4307     TOOLBAR_AutoSize (hwnd);
4308
4309     InvalidateRect(hwnd, NULL, FALSE);
4310
4311     return 0;
4312 }
4313
4314
4315
4316 static LRESULT WINAPI
4317 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4318 {
4319     if (!TOOLBAR_GetInfoPtr(hwnd) && (uMsg != WM_NCCREATE))
4320         return DefWindowProcA( hwnd, uMsg, wParam, lParam );
4321
4322     switch (uMsg)
4323     {
4324         case TB_ADDBITMAP:
4325             return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
4326
4327         case TB_ADDBUTTONSA:
4328             return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
4329
4330         case TB_ADDBUTTONSW:
4331             return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
4332
4333         case TB_ADDSTRINGA:
4334             return TOOLBAR_AddStringA (hwnd, wParam, lParam);
4335
4336         case TB_ADDSTRINGW:
4337             return TOOLBAR_AddStringW (hwnd, wParam, lParam);
4338
4339         case TB_AUTOSIZE:
4340             return TOOLBAR_AutoSize (hwnd);
4341
4342         case TB_BUTTONCOUNT:
4343             return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
4344
4345         case TB_BUTTONSTRUCTSIZE:
4346             return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
4347
4348         case TB_CHANGEBITMAP:
4349             return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
4350
4351         case TB_CHECKBUTTON:
4352             return TOOLBAR_CheckButton (hwnd, wParam, lParam);
4353
4354         case TB_COMMANDTOINDEX:
4355             return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
4356
4357         case TB_CUSTOMIZE:
4358             return TOOLBAR_Customize (hwnd);
4359
4360         case TB_DELETEBUTTON:
4361             return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
4362
4363         case TB_ENABLEBUTTON:
4364             return TOOLBAR_EnableButton (hwnd, wParam, lParam);
4365
4366         case TB_GETANCHORHIGHLIGHT:
4367             return TOOLBAR_GetAnchorHighlight (hwnd);
4368
4369         case TB_GETBITMAP:
4370             return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
4371
4372         case TB_GETBITMAPFLAGS:
4373             return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
4374
4375         case TB_GETBUTTON:
4376             return TOOLBAR_GetButton (hwnd, wParam, lParam);
4377
4378         case TB_GETBUTTONINFOA:
4379             return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
4380
4381         case TB_GETBUTTONINFOW:
4382             return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
4383
4384         case TB_GETBUTTONSIZE:
4385             return TOOLBAR_GetButtonSize (hwnd);
4386
4387         case TB_GETBUTTONTEXTA:
4388             return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
4389
4390         case TB_GETBUTTONTEXTW:
4391             return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
4392
4393 /*      case TB_GETCOLORSCHEME:                 */ /* 4.71 */
4394
4395         case TB_GETDISABLEDIMAGELIST:
4396             return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
4397
4398         case TB_GETEXTENDEDSTYLE:
4399             return TOOLBAR_GetExtendedStyle (hwnd);
4400
4401         case TB_GETHOTIMAGELIST:
4402             return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
4403
4404         case TB_GETHOTITEM:
4405             return TOOLBAR_GetHotItem (hwnd);
4406
4407         case TB_GETIMAGELIST:
4408             return TOOLBAR_GetImageList (hwnd, wParam, lParam);
4409
4410 /*      case TB_GETINSERTMARK:                  */ /* 4.71 */
4411 /*      case TB_GETINSERTMARKCOLOR:             */ /* 4.71 */
4412
4413         case TB_GETITEMRECT:
4414             return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
4415
4416         case TB_GETMAXSIZE:
4417             return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
4418
4419 /*      case TB_GETOBJECT:                      */ /* 4.71 */
4420 /*      case TB_GETPADDING:                     */ /* 4.71 */
4421
4422         case TB_GETRECT:
4423             return TOOLBAR_GetRect (hwnd, wParam, lParam);
4424
4425         case TB_GETROWS:
4426             return TOOLBAR_GetRows (hwnd, wParam, lParam);
4427
4428         case TB_GETSTATE:
4429             return TOOLBAR_GetState (hwnd, wParam, lParam);
4430
4431         case TB_GETSTYLE:
4432             return TOOLBAR_GetStyle (hwnd, wParam, lParam);
4433
4434         case TB_GETTEXTROWS:
4435             return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
4436
4437         case TB_GETTOOLTIPS:
4438             return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
4439
4440         case TB_GETUNICODEFORMAT:
4441             return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
4442
4443         case CCM_GETVERSION:
4444             return TOOLBAR_GetVersion (hwnd);
4445
4446         case TB_HIDEBUTTON:
4447             return TOOLBAR_HideButton (hwnd, wParam, lParam);
4448
4449         case TB_HITTEST:
4450             return TOOLBAR_HitTest (hwnd, wParam, lParam);
4451
4452         case TB_INDETERMINATE:
4453             return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
4454
4455         case TB_INSERTBUTTONA:
4456             return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
4457
4458         case TB_INSERTBUTTONW:
4459             return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
4460
4461 /*      case TB_INSERTMARKHITTEST:              */ /* 4.71 */
4462
4463         case TB_ISBUTTONCHECKED:
4464             return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
4465
4466         case TB_ISBUTTONENABLED:
4467             return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
4468
4469         case TB_ISBUTTONHIDDEN:
4470             return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
4471
4472         case TB_ISBUTTONHIGHLIGHTED:
4473             return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
4474
4475         case TB_ISBUTTONINDETERMINATE:
4476             return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
4477
4478         case TB_ISBUTTONPRESSED:
4479             return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
4480
4481         case TB_LOADIMAGES:                        /* 4.70 */
4482             FIXME("missing standard imagelists\n");
4483             return 0;
4484
4485 /*      case TB_MAPACCELERATORA:                */ /* 4.71 */
4486 /*      case TB_MAPACCELERATORW:                */ /* 4.71 */
4487 /*      case TB_MARKBUTTON:                     */ /* 4.71 */
4488 /*      case TB_MOVEBUTTON:                     */ /* 4.71 */
4489
4490         case TB_PRESSBUTTON:
4491             return TOOLBAR_PressButton (hwnd, wParam, lParam);
4492
4493 /*      case TB_REPLACEBITMAP: */
4494
4495         case TB_SAVERESTOREA:
4496             return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
4497
4498         case TB_SAVERESTOREW:
4499             return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
4500
4501         case TB_SETANCHORHIGHLIGHT:
4502             return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
4503
4504         case TB_SETBITMAPSIZE:
4505             return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
4506
4507         case TB_SETBUTTONINFOA:
4508             return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
4509
4510         case TB_SETBUTTONINFOW:
4511             return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
4512
4513         case TB_SETBUTTONSIZE:
4514             return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
4515
4516         case TB_SETBUTTONWIDTH:
4517             return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
4518
4519         case TB_SETCMDID:
4520             return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
4521
4522 /*      case TB_SETCOLORSCHEME:                 */ /* 4.71 */
4523
4524         case TB_SETDISABLEDIMAGELIST:
4525             return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
4526
4527         case TB_SETDRAWTEXTFLAGS:
4528             return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
4529
4530         case TB_SETEXTENDEDSTYLE:
4531             return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
4532
4533         case TB_SETHOTIMAGELIST:
4534             return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
4535
4536         case TB_SETHOTITEM:
4537             return TOOLBAR_SetHotItem (hwnd, wParam);
4538
4539         case TB_SETIMAGELIST:
4540             return TOOLBAR_SetImageList (hwnd, wParam, lParam);
4541
4542         case TB_SETINDENT:
4543             return TOOLBAR_SetIndent (hwnd, wParam, lParam);
4544
4545 /*      case TB_SETINSERTMARK:                  */ /* 4.71 */
4546
4547         case TB_SETINSERTMARKCOLOR:
4548             return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
4549
4550         case TB_SETMAXTEXTROWS:
4551             return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
4552
4553 /*      case TB_SETPADDING:                     */ /* 4.71 */
4554
4555         case TB_SETPARENT:
4556             return TOOLBAR_SetParent (hwnd, wParam, lParam);
4557
4558         case TB_SETROWS:
4559             return TOOLBAR_SetRows (hwnd, wParam, lParam);
4560
4561         case TB_SETSTATE:
4562             return TOOLBAR_SetState (hwnd, wParam, lParam);
4563
4564         case TB_SETSTYLE:
4565             return TOOLBAR_SetStyle (hwnd, wParam, lParam);
4566
4567         case TB_SETTOOLTIPS:
4568             return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
4569
4570         case TB_SETUNICODEFORMAT:
4571             return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
4572
4573         case CCM_SETVERSION:
4574             return TOOLBAR_SetVersion (hwnd, (INT)wParam);
4575
4576
4577 /*      case WM_CHAR: */
4578
4579         case WM_CREATE:
4580             return TOOLBAR_Create (hwnd, wParam, lParam);
4581
4582         case WM_DESTROY:
4583           return TOOLBAR_Destroy (hwnd, wParam, lParam);
4584
4585         case WM_ERASEBKGND:
4586             return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
4587
4588         case WM_GETFONT:
4589                 return TOOLBAR_GetFont (hwnd, wParam, lParam);
4590
4591 /*      case WM_KEYDOWN: */
4592 /*      case WM_KILLFOCUS: */
4593
4594         case WM_LBUTTONDBLCLK:
4595             return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
4596
4597         case WM_LBUTTONDOWN:
4598             return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
4599
4600         case WM_LBUTTONUP:
4601             return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
4602
4603         case WM_MOUSEMOVE:
4604             return TOOLBAR_MouseMove (hwnd, wParam, lParam);
4605
4606         case WM_MOUSELEAVE:
4607             return TOOLBAR_MouseLeave (hwnd, wParam, lParam);   
4608
4609         case WM_CAPTURECHANGED:
4610             return TOOLBAR_CaptureChanged(hwnd);        
4611
4612         case WM_NCACTIVATE:
4613             return TOOLBAR_NCActivate (hwnd, wParam, lParam);
4614
4615         case WM_NCCALCSIZE:
4616             return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
4617
4618         case WM_NCCREATE:
4619             return TOOLBAR_NCCreate (hwnd, wParam, lParam);
4620
4621         case WM_NCPAINT:
4622             return TOOLBAR_NCPaint (hwnd, wParam, lParam);
4623
4624         case WM_NOTIFY:
4625             return TOOLBAR_Notify (hwnd, wParam, lParam);
4626
4627 /*      case WM_NOTIFYFORMAT: */
4628
4629         case WM_PAINT:
4630             return TOOLBAR_Paint (hwnd, wParam);
4631
4632         case WM_SIZE:
4633             return TOOLBAR_Size (hwnd, wParam, lParam);
4634
4635         case WM_STYLECHANGED:
4636             return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
4637
4638 /*      case WM_SYSCOLORCHANGE: */
4639
4640 /*      case WM_WININICHANGE: */
4641
4642         case WM_CHARTOITEM:
4643         case WM_COMMAND:
4644         case WM_DRAWITEM:
4645         case WM_MEASUREITEM:
4646         case WM_VKEYTOITEM:
4647             return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
4648
4649         default:
4650             if (uMsg >= WM_USER)
4651                 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
4652                      uMsg, wParam, lParam);
4653             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4654     }
4655     return 0;
4656 }
4657
4658
4659 VOID
4660 TOOLBAR_Register (void)
4661 {
4662     WNDCLASSA wndClass;
4663
4664     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4665     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
4666     wndClass.lpfnWndProc   = (WNDPROC)ToolbarWindowProc;
4667     wndClass.cbClsExtra    = 0;
4668     wndClass.cbWndExtra    = sizeof(TOOLBAR_INFO *);
4669     wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
4670     wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
4671     wndClass.lpszClassName = TOOLBARCLASSNAMEA;
4672  
4673     RegisterClassA (&wndClass);
4674 }
4675
4676
4677 VOID
4678 TOOLBAR_Unregister (void)
4679 {
4680     UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);
4681 }
4682