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