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