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