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