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