Added sanity checks in the cleanup code.
[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.
11  *   - Fix TB_SETROWS.
12  *   - Tooltip support (almost complete).
13  *   - Unicode suppport.
14  *   - Fix TOOLBAR_SetButtonInfo32A.
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                 RECT rcButton;
789                 RECT rcText;
790                 HPEN hOldPen;
791                 HBRUSH hOldBrush;
792                 COLORREF oldText = 0;
793                 COLORREF oldBk = 0;
794
795                 FIXME("action: %x itemState: %x\n",
796                       lpdis->itemAction, lpdis->itemState);             
797
798                 if (lpdis->itemState & ODS_FOCUS)
799                 {
800                     oldBk = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
801                     oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
802                 }
803
804                 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
805                 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
806
807                 /* fill background rectangle */
808                 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
809                            lpdis->rcItem.right, lpdis->rcItem.bottom);
810
811                 /* calculate button and text rectangles */
812                 CopyRect (&rcButton, &lpdis->rcItem);
813                 InflateRect (&rcButton, -1, -1);
814                 CopyRect (&rcText, &rcButton);
815                 rcButton.right = rcButton.left + infoPtr->nBitmapWidth + 6;
816                 rcText.left = rcButton.right + 2;
817
818                 /* draw focus rectangle */
819                 if (lpdis->itemState & ODS_FOCUS)
820                     DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
821
822                 /* draw button */
823                 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
824
825                 /* FIXME: draw bitmap */
826 /*
827                 ImageList_Draw (infoPtr->himlStd, btnPtr->iBitmap, hdc,
828                                 rcButton.left+1, rcButton.top+1, ILD_NORMAL);
829 */
830                 /* draw text */
831                 if (wParam == IDC_AVAILBTN_LBOX && lpdis->itemID == 0)
832                 {
833                     /* virtual separator in the 'available' list */
834                     DrawTextA (lpdis->hDC, "Separator", -1, &rcText,
835                                DT_LEFT | DT_VCENTER | DT_SINGLELINE);
836                 }
837                 else
838                 {
839                     /* real button */
840                 }
841
842                 if (lpdis->itemState & ODS_FOCUS)
843                 {
844                     SetBkColor (lpdis->hDC, oldBk);
845                     SetTextColor (lpdis->hDC, oldText);
846                 }
847
848                 SelectObject (lpdis->hDC, hOldBrush);
849                 SelectObject (lpdis->hDC, hOldPen);
850
851                 return TRUE;
852             }
853             return FALSE;
854
855         case WM_MEASUREITEM:
856             if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
857             {
858                 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
859
860                 if (infoPtr)
861                     lpmis->itemHeight = infoPtr->nBitmapHeight + 8;
862                 else
863                     lpmis->itemHeight = 16 + 8; /* default height */
864
865                 return TRUE;
866             }
867             return FALSE;
868
869         default:
870             return FALSE;
871     }
872 }
873
874
875 /***********************************************************************
876  * TOOLBAR_AddBitmap:  Add the bitmaps to the default image list.
877  *
878  */
879 static LRESULT
880 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
881 {
882     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
883     LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
884     INT nIndex = 0, nButtons;
885     HBITMAP hbmLoad;
886
887     if (!lpAddBmp)
888         return -1;
889
890     if (lpAddBmp->hInst == HINST_COMMCTRL)
891     {
892         if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
893             nButtons = 15;
894         else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
895             nButtons = 13;
896         else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
897             nButtons = 5;
898         else
899             return -1;
900
901         TRACE ("adding %d internal bitmaps!\n", nButtons);
902
903         /* Windows resize all the buttons to the size of a newly added standard image */
904         if (lpAddBmp->nID & 1) 
905         {
906             /* large icons */
907             SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
908                           MAKELPARAM((WORD)26, (WORD)26));
909             SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
910                           MAKELPARAM((WORD)33, (WORD)33));
911         }       
912         else 
913         {
914             /* small icons */
915             SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
916                           MAKELPARAM((WORD)16, (WORD)16));
917             SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
918                           MAKELPARAM((WORD)22, (WORD)22));
919         }
920         
921         TOOLBAR_CalcToolbar (hwnd);
922     }
923     else
924     {
925         nButtons = (INT)wParam;
926         if (nButtons <= 0)
927             return -1;
928         
929         TRACE ("adding %d bitmaps!\n", nButtons);
930     }
931     
932     if (!(infoPtr->himlDef)) {
933         /* create new default image list */
934         TRACE ("creating default image list!\n");
935
936         infoPtr->himlDef =
937             ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
938                               ILC_COLOR | ILC_MASK, nButtons, 2);
939         infoPtr->himlInt = infoPtr->himlDef;
940     }
941
942     /* Add bitmaps to the default image list */
943     if (lpAddBmp->hInst == (HINSTANCE)0)
944     {
945         nIndex = 
946             ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
947                                  CLR_DEFAULT);
948     }
949     else if (lpAddBmp->hInst == HINST_COMMCTRL)
950     {
951         /* Add system bitmaps */
952         switch (lpAddBmp->nID)
953     {
954             case IDB_STD_SMALL_COLOR:
955                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
956                                        MAKEINTRESOURCEA(IDB_STD_SMALL));
957                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
958                                               hbmLoad, CLR_DEFAULT);
959                 DeleteObject (hbmLoad);
960                 break;
961
962             case IDB_STD_LARGE_COLOR:
963                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
964                                        MAKEINTRESOURCEA(IDB_STD_LARGE));
965                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
966                                               hbmLoad, CLR_DEFAULT);
967                 DeleteObject (hbmLoad);
968                 break;
969
970             case IDB_VIEW_SMALL_COLOR:
971                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
972                                        MAKEINTRESOURCEA(IDB_VIEW_SMALL));
973                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
974                                               hbmLoad, CLR_DEFAULT);
975                 DeleteObject (hbmLoad);
976                 break;
977
978             case IDB_VIEW_LARGE_COLOR:
979                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
980                                        MAKEINTRESOURCEA(IDB_VIEW_LARGE));
981                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
982                                               hbmLoad, CLR_DEFAULT);
983                 DeleteObject (hbmLoad);
984                 break;
985
986             case IDB_HIST_SMALL_COLOR:
987                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
988                                        MAKEINTRESOURCEA(IDB_HIST_SMALL));
989                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
990                                               hbmLoad, CLR_DEFAULT);
991                 DeleteObject (hbmLoad);
992                 break;
993
994             case IDB_HIST_LARGE_COLOR:
995                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
996                                        MAKEINTRESOURCEA(IDB_HIST_LARGE));
997                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
998                                               hbmLoad, CLR_DEFAULT);
999                 DeleteObject (hbmLoad);
1000                 break;
1001
1002             default:
1003         nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1004                 ERR ("invalid imagelist!\n");
1005                 break;
1006         }
1007     }
1008     else
1009     {
1010         hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1011         nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1012         DeleteObject (hbmLoad);
1013     }
1014
1015     infoPtr->nNumBitmaps += nButtons;
1016
1017     return nIndex;
1018 }
1019
1020
1021 static LRESULT
1022 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1023 {
1024     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1025     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1026     INT nOldButtons, nNewButtons, nAddButtons, nCount;
1027
1028     TRACE("adding %d buttons!\n", wParam);
1029
1030     nAddButtons = (UINT)wParam;
1031     nOldButtons = infoPtr->nNumButtons;
1032     nNewButtons = nOldButtons + nAddButtons;
1033
1034     if (infoPtr->nNumButtons == 0) {
1035         infoPtr->buttons =
1036             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1037     }
1038     else {
1039         TBUTTON_INFO *oldButtons = infoPtr->buttons;
1040         infoPtr->buttons =
1041             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1042         memcpy (&infoPtr->buttons[0], &oldButtons[0],
1043                 nOldButtons * sizeof(TBUTTON_INFO));
1044         COMCTL32_Free (oldButtons);
1045     }
1046
1047     infoPtr->nNumButtons = nNewButtons;
1048
1049     /* insert new button data */
1050     for (nCount = 0; nCount < nAddButtons; nCount++) {
1051         TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1052         btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
1053         btnPtr->idCommand = lpTbb[nCount].idCommand;
1054         btnPtr->fsState   = lpTbb[nCount].fsState;
1055         btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
1056         btnPtr->dwData    = lpTbb[nCount].dwData;
1057         btnPtr->iString   = lpTbb[nCount].iString;
1058         btnPtr->bHot      = FALSE;
1059
1060         if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1061             TTTOOLINFOA ti;
1062
1063             ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1064             ti.cbSize   = sizeof (TTTOOLINFOA);
1065             ti.hwnd     = hwnd;
1066             ti.uId      = btnPtr->idCommand;
1067             ti.hinst    = 0;
1068             ti.lpszText = LPSTR_TEXTCALLBACKA;
1069
1070             SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1071                             0, (LPARAM)&ti);
1072         }
1073     }
1074
1075     TOOLBAR_CalcToolbar (hwnd);
1076
1077     InvalidateRect(hwnd, NULL, FALSE);
1078
1079     return TRUE;
1080 }
1081
1082
1083 /* << TOOLBAR_AddButtons32W >> */
1084
1085
1086 static LRESULT
1087 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1088 {
1089     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1090     INT nIndex;
1091
1092     if ((wParam) && (HIWORD(lParam) == 0)) {
1093         char szString[256];
1094         INT len;
1095         TRACE("adding string from resource!\n");
1096
1097         len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1098                              szString, 256);
1099
1100         TRACE("len=%d \"%s\"\n", len, szString);
1101         nIndex = infoPtr->nNumStrings;
1102         if (infoPtr->nNumStrings == 0) {
1103             infoPtr->strings =
1104                 COMCTL32_Alloc (sizeof(LPWSTR));
1105         }
1106         else {
1107             LPWSTR *oldStrings = infoPtr->strings;
1108             infoPtr->strings =
1109                 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1110             memcpy (&infoPtr->strings[0], &oldStrings[0],
1111                     sizeof(LPWSTR) * infoPtr->nNumStrings);
1112             COMCTL32_Free (oldStrings);
1113         }
1114
1115         infoPtr->strings[infoPtr->nNumStrings] =
1116             COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1117         lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1118         infoPtr->nNumStrings++;
1119     }
1120     else {
1121         LPSTR p = (LPSTR)lParam;
1122         INT len;
1123
1124         if (p == NULL)
1125             return -1;
1126         TRACE("adding string(s) from array!\n");
1127         nIndex = infoPtr->nNumStrings;
1128         while (*p) {
1129             len = lstrlenA (p);
1130             TRACE("len=%d \"%s\"\n", len, p);
1131
1132             if (infoPtr->nNumStrings == 0) {
1133                 infoPtr->strings =
1134                     COMCTL32_Alloc (sizeof(LPWSTR));
1135             }
1136             else {
1137                 LPWSTR *oldStrings = infoPtr->strings;
1138                 infoPtr->strings =
1139                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1140                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1141                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1142                 COMCTL32_Free (oldStrings);
1143             }
1144
1145             infoPtr->strings[infoPtr->nNumStrings] =
1146                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1147             lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1148             infoPtr->nNumStrings++;
1149
1150             p += (len+1);
1151         }
1152     }
1153
1154     return nIndex;
1155 }
1156
1157
1158 static LRESULT
1159 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1160 {
1161     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1162     INT nIndex;
1163
1164     if ((wParam) && (HIWORD(lParam) == 0)) {
1165         WCHAR szString[256];
1166         INT len;
1167         TRACE("adding string from resource!\n");
1168
1169         len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1170                              szString, 256);
1171
1172         TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1173         nIndex = infoPtr->nNumStrings;
1174         if (infoPtr->nNumStrings == 0) {
1175             infoPtr->strings =
1176                 COMCTL32_Alloc (sizeof(LPWSTR));
1177         }
1178         else {
1179             LPWSTR *oldStrings = infoPtr->strings;
1180             infoPtr->strings =
1181                 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1182             memcpy (&infoPtr->strings[0], &oldStrings[0],
1183                     sizeof(LPWSTR) * infoPtr->nNumStrings);
1184             COMCTL32_Free (oldStrings);
1185         }
1186
1187         infoPtr->strings[infoPtr->nNumStrings] =
1188             COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1189         lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1190         infoPtr->nNumStrings++;
1191     }
1192     else {
1193         LPWSTR p = (LPWSTR)lParam;
1194         INT len;
1195
1196         if (p == NULL)
1197             return -1;
1198         TRACE("adding string(s) from array!\n");
1199         nIndex = infoPtr->nNumStrings;
1200         while (*p) {
1201             len = lstrlenW (p);
1202             TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1203
1204             if (infoPtr->nNumStrings == 0) {
1205                 infoPtr->strings =
1206                     COMCTL32_Alloc (sizeof(LPWSTR));
1207             }
1208             else {
1209                 LPWSTR *oldStrings = infoPtr->strings;
1210                 infoPtr->strings =
1211                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1212                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1213                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1214                 COMCTL32_Free (oldStrings);
1215             }
1216
1217             infoPtr->strings[infoPtr->nNumStrings] =
1218                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1219             lstrcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1220             infoPtr->nNumStrings++;
1221
1222             p += (len+1);
1223         }
1224     }
1225
1226     return nIndex;
1227 }
1228
1229
1230 static LRESULT
1231 TOOLBAR_AutoSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1232 {
1233     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1234     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1235     RECT parent_rect;
1236     HWND parent;
1237     /* INT32  x, y; */
1238     INT  cx, cy;
1239     UINT uPosFlags = 0;
1240
1241     TRACE("resize forced!\n");
1242
1243     parent = GetParent (hwnd);
1244     GetClientRect(parent, &parent_rect);
1245
1246     if (dwStyle & CCS_NORESIZE) {
1247         uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1248         cx = 0;
1249         cy = 0;
1250     }
1251     else {
1252         infoPtr->nWidth = parent_rect.right - parent_rect.left;
1253         TOOLBAR_CalcToolbar (hwnd);
1254         InvalidateRect( hwnd, NULL, TRUE );
1255         cy = infoPtr->nHeight;
1256         cx = infoPtr->nWidth;
1257     }
1258
1259     if (dwStyle & CCS_NOPARENTALIGN)
1260         uPosFlags |= SWP_NOMOVE;
1261
1262     if (!(dwStyle & CCS_NODIVIDER))
1263         cy += GetSystemMetrics(SM_CYEDGE);
1264
1265     infoPtr->bAutoSize = TRUE;
1266     SetWindowPos (hwnd, HWND_TOP, parent_rect.left, parent_rect.top,
1267                     cx, cy, uPosFlags);
1268
1269     return 0;
1270 }
1271
1272
1273 static LRESULT
1274 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1275 {
1276     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1277
1278     return infoPtr->nNumButtons;
1279 }
1280
1281
1282 static LRESULT
1283 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1284 {
1285     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1286
1287     if (infoPtr == NULL) {
1288         ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
1289         ERR("infoPtr == NULL!\n");
1290         return 0;
1291     }
1292
1293     infoPtr->dwStructSize = (DWORD)wParam;
1294
1295     return 0;
1296 }
1297
1298
1299 static LRESULT
1300 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1301 {
1302     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1303     TBUTTON_INFO *btnPtr;
1304     HDC hdc;
1305     INT nIndex;
1306
1307     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1308     if (nIndex == -1)
1309         return FALSE;
1310
1311     btnPtr = &infoPtr->buttons[nIndex];
1312     btnPtr->iBitmap = LOWORD(lParam);
1313
1314     hdc = GetDC (hwnd);
1315     TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
1316     ReleaseDC (hwnd, hdc);
1317
1318     return TRUE;
1319 }
1320
1321
1322 static LRESULT
1323 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1324 {
1325     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1326     TBUTTON_INFO *btnPtr;
1327     HDC hdc;
1328     INT nIndex;
1329     INT nOldIndex = -1;
1330
1331     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1332     if (nIndex == -1)
1333         return FALSE;
1334
1335     btnPtr = &infoPtr->buttons[nIndex];
1336
1337     if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
1338         return FALSE;
1339
1340     if (LOWORD(lParam) == FALSE)
1341         btnPtr->fsState &= ~TBSTATE_CHECKED;
1342     else {
1343         if (btnPtr->fsStyle & TBSTYLE_GROUP) {
1344             nOldIndex = 
1345                 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
1346             if (nOldIndex == nIndex)
1347                 return 0;
1348             if (nOldIndex != -1)
1349                 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
1350         }
1351         btnPtr->fsState |= TBSTATE_CHECKED;
1352     }
1353
1354     hdc = GetDC (hwnd);
1355     if (nOldIndex != -1)
1356         TOOLBAR_DrawButton (hwnd, &infoPtr->buttons[nOldIndex], hdc);
1357     TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
1358     ReleaseDC (hwnd, hdc);
1359
1360     /* FIXME: Send a WM_NOTIFY?? */
1361
1362     return TRUE;
1363 }
1364
1365
1366 static LRESULT
1367 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
1368 {
1369     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1370
1371     return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1372 }
1373
1374
1375 static LRESULT
1376 TOOLBAR_Customize (HWND hwnd)
1377 {
1378     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1379     LRESULT ret;
1380     LPCVOID template;
1381     HRSRC hRes;
1382     NMHDR nmhdr;
1383
1384     /* send TBN_BEGINADJUST notification */
1385     nmhdr.hwndFrom = hwnd;
1386     nmhdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1387     nmhdr.code     = TBN_BEGINADJUST;
1388
1389     SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1390                   (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1391
1392     if (!(hRes = FindResourceA (COMCTL32_hModule,
1393                                 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
1394                                 RT_DIALOGA)))
1395         return FALSE;
1396
1397     if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
1398         return FALSE;
1399
1400     ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
1401                                    (LPDLGTEMPLATEA)template,
1402                                    hwnd,
1403                                    (DLGPROC)TOOLBAR_CustomizeDialogProc,
1404                                    (LPARAM)infoPtr);
1405
1406     /* send TBN_ENDADJUST notification */
1407     nmhdr.code = TBN_ENDADJUST;
1408
1409     SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
1410                   (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1411
1412     return ret;
1413 }
1414
1415
1416 static LRESULT
1417 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1418 {
1419     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1420     INT nIndex = (INT)wParam;
1421
1422     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1423         return FALSE;
1424
1425     if ((infoPtr->hwndToolTip) && 
1426         !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
1427         TTTOOLINFOA ti;
1428
1429         ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1430         ti.cbSize   = sizeof (TTTOOLINFOA);
1431         ti.hwnd     = hwnd;
1432         ti.uId      = infoPtr->buttons[nIndex].idCommand;
1433
1434         SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
1435     }
1436
1437     if (infoPtr->nNumButtons == 1) {
1438         TRACE(" simple delete!\n");
1439         COMCTL32_Free (infoPtr->buttons);
1440         infoPtr->buttons = NULL;
1441         infoPtr->nNumButtons = 0;
1442     }
1443     else {
1444         TBUTTON_INFO *oldButtons = infoPtr->buttons;
1445         TRACE("complex delete! [nIndex=%d]\n", nIndex);
1446
1447         infoPtr->nNumButtons--;
1448         infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1449         if (nIndex > 0) {
1450             memcpy (&infoPtr->buttons[0], &oldButtons[0],
1451                     nIndex * sizeof(TBUTTON_INFO));
1452         }
1453
1454         if (nIndex < infoPtr->nNumButtons) {
1455             memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
1456                     (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
1457         }
1458
1459         COMCTL32_Free (oldButtons);
1460     }
1461
1462     TOOLBAR_CalcToolbar (hwnd);
1463
1464     InvalidateRect (hwnd, NULL, TRUE);
1465
1466     return TRUE;
1467 }
1468
1469
1470 static LRESULT
1471 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1472 {
1473     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1474     TBUTTON_INFO *btnPtr;
1475     HDC hdc;
1476     INT nIndex;
1477
1478     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1479     if (nIndex == -1)
1480         return FALSE;
1481
1482     btnPtr = &infoPtr->buttons[nIndex];
1483     if (LOWORD(lParam) == FALSE)
1484         btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
1485     else
1486         btnPtr->fsState |= TBSTATE_ENABLED;
1487
1488     hdc = GetDC (hwnd);
1489     TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
1490     ReleaseDC (hwnd, hdc);
1491
1492     return TRUE;
1493 }
1494
1495
1496 /* << TOOLBAR_GetAnchorHighlight >> */
1497
1498
1499 static LRESULT
1500 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1501 {
1502     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1503     INT nIndex;
1504
1505     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1506     if (nIndex == -1)
1507         return -1;
1508
1509     return infoPtr->buttons[nIndex].iBitmap;
1510 }
1511
1512
1513 static inline LRESULT
1514 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
1515 {
1516     return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
1517 }
1518
1519
1520 static LRESULT
1521 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1522 {
1523     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1524     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1525     INT nIndex = (INT)wParam;
1526     TBUTTON_INFO *btnPtr;
1527
1528     if (infoPtr == NULL)
1529         return FALSE;
1530
1531     if (lpTbb == NULL)
1532         return FALSE;
1533
1534     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1535         return FALSE;
1536
1537     btnPtr = &infoPtr->buttons[nIndex];
1538     lpTbb->iBitmap   = btnPtr->iBitmap;
1539     lpTbb->idCommand = btnPtr->idCommand;
1540     lpTbb->fsState   = btnPtr->fsState;
1541     lpTbb->fsStyle   = btnPtr->fsStyle;
1542     lpTbb->dwData    = btnPtr->dwData;
1543     lpTbb->iString   = btnPtr->iString;
1544
1545     return TRUE;
1546 }
1547
1548
1549 static LRESULT
1550 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1551 {
1552     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1553     LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
1554     TBUTTON_INFO *btnPtr;
1555     INT nIndex;
1556
1557     if (infoPtr == NULL)
1558         return -1;
1559     if (lpTbInfo == NULL)
1560         return -1;
1561     if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
1562         return -1;
1563
1564     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1565     if (nIndex == -1)
1566         return -1;
1567
1568     btnPtr = &infoPtr->buttons[nIndex];
1569
1570     if (lpTbInfo->dwMask & TBIF_COMMAND)
1571         lpTbInfo->idCommand = btnPtr->idCommand;
1572     if (lpTbInfo->dwMask & TBIF_IMAGE)
1573         lpTbInfo->iImage = btnPtr->iBitmap;
1574     if (lpTbInfo->dwMask & TBIF_LPARAM)
1575         lpTbInfo->lParam = btnPtr->dwData;
1576     if (lpTbInfo->dwMask & TBIF_SIZE)
1577         lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
1578     if (lpTbInfo->dwMask & TBIF_STATE)
1579         lpTbInfo->fsState = btnPtr->fsState;
1580     if (lpTbInfo->dwMask & TBIF_STYLE)
1581         lpTbInfo->fsStyle = btnPtr->fsStyle;
1582     if (lpTbInfo->dwMask & TBIF_TEXT) {
1583         if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
1584             lstrcpynA (lpTbInfo->pszText, 
1585                          (LPSTR)infoPtr->strings[btnPtr->iString],
1586                          lpTbInfo->cchText);
1587     }
1588
1589     return nIndex;
1590 }
1591
1592
1593 /* << TOOLBAR_GetButtonInfo32W >> */
1594
1595
1596 static LRESULT
1597 TOOLBAR_GetButtonSize (HWND hwnd)
1598 {
1599     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1600
1601     return MAKELONG((WORD)infoPtr->nButtonWidth,
1602                     (WORD)infoPtr->nButtonHeight);
1603 }
1604
1605
1606 static LRESULT
1607 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1608 {
1609     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1610     INT nIndex, nStringIndex;
1611
1612     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1613     if (nIndex == -1)
1614         return -1;
1615
1616     nStringIndex = infoPtr->buttons[nIndex].iString;
1617
1618     TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
1619
1620     if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
1621         return -1;
1622
1623     if (lParam == 0) return -1;
1624
1625     lstrcpyA ((LPSTR)lParam, (LPSTR)infoPtr->strings[nStringIndex]);
1626
1627     return lstrlenA ((LPSTR)infoPtr->strings[nStringIndex]);
1628 }
1629
1630
1631 /* << TOOLBAR_GetButtonText32W >> */
1632 /* << TOOLBAR_GetColorScheme >> */
1633
1634
1635 static LRESULT
1636 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1637 {
1638     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1639
1640     return (LRESULT)infoPtr->himlDis;
1641 }
1642
1643
1644 inline static LRESULT
1645 TOOLBAR_GetExtendedStyle (HWND hwnd)
1646 {
1647     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1648
1649     return infoPtr->dwExStyle;
1650 }
1651
1652
1653 static LRESULT
1654 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1655 {
1656     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1657
1658     return (LRESULT)infoPtr->himlHot;
1659 }
1660
1661
1662 /* << TOOLBAR_GetHotItem >> */
1663
1664
1665 static LRESULT
1666 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1667 {
1668     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1669
1670     return (LRESULT)infoPtr->himlDef;
1671 }
1672
1673
1674 /* << TOOLBAR_GetInsertMark >> */
1675 /* << TOOLBAR_GetInsertMarkColor >> */
1676
1677
1678 static LRESULT
1679 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1680 {
1681     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1682     TBUTTON_INFO *btnPtr;
1683     LPRECT     lpRect;
1684     INT        nIndex;
1685
1686     if (infoPtr == NULL)
1687         return FALSE;
1688     nIndex = (INT)wParam;
1689     btnPtr = &infoPtr->buttons[nIndex];
1690     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1691         return FALSE;
1692     lpRect = (LPRECT)lParam;
1693     if (lpRect == NULL)
1694         return FALSE;
1695     if (btnPtr->fsState & TBSTATE_HIDDEN)
1696         return FALSE;
1697     
1698     TOOLBAR_CalcToolbar( hwnd );
1699     
1700     lpRect->left   = btnPtr->rect.left;
1701     lpRect->right  = btnPtr->rect.right;
1702     lpRect->bottom = btnPtr->rect.bottom;
1703     lpRect->top    = btnPtr->rect.top;
1704
1705     return TRUE;
1706 }
1707
1708
1709 static LRESULT
1710 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
1711 {
1712     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1713     LPSIZE lpSize = (LPSIZE)lParam;
1714
1715     if (lpSize == NULL)
1716         return FALSE;
1717
1718     lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
1719     lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
1720
1721     TRACE("maximum size %d x %d\n",
1722            infoPtr->rcBound.right - infoPtr->rcBound.left,
1723            infoPtr->rcBound.bottom - infoPtr->rcBound.top);
1724
1725     return TRUE;
1726 }
1727
1728
1729 /* << TOOLBAR_GetObject >> */
1730 /* << TOOLBAR_GetPadding >> */
1731
1732
1733 static LRESULT
1734 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1735 {
1736     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1737     TBUTTON_INFO *btnPtr;
1738     LPRECT     lpRect;
1739     INT        nIndex;
1740
1741     if (infoPtr == NULL)
1742         return FALSE;
1743     nIndex = (INT)wParam;
1744     btnPtr = &infoPtr->buttons[nIndex];
1745     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
1746         return FALSE;
1747     lpRect = (LPRECT)lParam;
1748     if (lpRect == NULL)
1749         return FALSE;
1750     
1751     lpRect->left   = btnPtr->rect.left;
1752     lpRect->right  = btnPtr->rect.right;
1753     lpRect->bottom = btnPtr->rect.bottom;
1754     lpRect->top    = btnPtr->rect.top;
1755
1756     return TRUE;
1757 }
1758
1759
1760 static LRESULT
1761 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
1762 {
1763     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1764
1765     if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
1766         return infoPtr->nRows;
1767     else
1768         return 1;
1769 }
1770
1771
1772 static LRESULT
1773 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
1774 {
1775     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1776     INT nIndex;
1777
1778     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1779     if (nIndex == -1)
1780         return -1;
1781
1782     return infoPtr->buttons[nIndex].fsState;
1783 }
1784
1785
1786 static LRESULT
1787 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
1788 {
1789     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1790     INT nIndex;
1791
1792     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1793     if (nIndex == -1)
1794         return -1;
1795
1796     return infoPtr->buttons[nIndex].fsStyle;
1797 }
1798
1799
1800 static LRESULT
1801 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
1802 {
1803     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1804
1805     if (infoPtr == NULL)
1806         return 0;
1807
1808     return infoPtr->nMaxTextRows;
1809 }
1810
1811
1812 static LRESULT
1813 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
1814 {
1815     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1816
1817     if (infoPtr == NULL)
1818         return 0;
1819     return infoPtr->hwndToolTip;
1820 }
1821
1822
1823 static LRESULT
1824 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
1825 {
1826     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1827
1828     TRACE("%s hwnd=0x%x stub!\n", 
1829            infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
1830
1831     return infoPtr->bUnicode;
1832 }
1833
1834
1835 static LRESULT
1836 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
1837 {
1838     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1839     TBUTTON_INFO *btnPtr;
1840     INT nIndex;
1841
1842     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1843     if (nIndex == -1)
1844         return FALSE;
1845
1846     btnPtr = &infoPtr->buttons[nIndex];
1847     if (LOWORD(lParam) == FALSE)
1848         btnPtr->fsState &= ~TBSTATE_HIDDEN;
1849     else
1850         btnPtr->fsState |= TBSTATE_HIDDEN;
1851
1852     TOOLBAR_CalcToolbar (hwnd);
1853
1854     InvalidateRect (hwnd, NULL, TRUE);
1855
1856     return TRUE;
1857 }
1858
1859
1860 inline static LRESULT
1861 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1862 {
1863     return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
1864 }
1865
1866
1867 static LRESULT
1868 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1869 {
1870     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1871     TBUTTON_INFO *btnPtr;
1872     HDC hdc;
1873     INT nIndex;
1874
1875     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1876     if (nIndex == -1)
1877         return FALSE;
1878
1879     btnPtr = &infoPtr->buttons[nIndex];
1880     if (LOWORD(lParam) == FALSE)
1881         btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
1882     else
1883         btnPtr->fsState |= TBSTATE_INDETERMINATE;
1884
1885     hdc = GetDC (hwnd);
1886     TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
1887     ReleaseDC (hwnd, hdc);
1888
1889     return TRUE;
1890 }
1891
1892
1893 static LRESULT
1894 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1895 {
1896     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1897     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1898     INT nIndex = (INT)wParam;
1899     TBUTTON_INFO *oldButtons;
1900
1901     if (lpTbb == NULL)
1902         return FALSE;
1903     if (nIndex < 0)
1904         return FALSE;
1905
1906     TRACE("inserting button index=%d\n", nIndex);
1907     if (nIndex > infoPtr->nNumButtons) {
1908         nIndex = infoPtr->nNumButtons;
1909         TRACE("adjust index=%d\n", nIndex);
1910     }
1911
1912     oldButtons = infoPtr->buttons;
1913     infoPtr->nNumButtons++;
1914     infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
1915     /* pre insert copy */
1916     if (nIndex > 0) {
1917         memcpy (&infoPtr->buttons[0], &oldButtons[0],
1918                 nIndex * sizeof(TBUTTON_INFO));
1919     }
1920
1921     /* insert new button */
1922     infoPtr->buttons[nIndex].iBitmap   = lpTbb->iBitmap;
1923     infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
1924     infoPtr->buttons[nIndex].fsState   = lpTbb->fsState;
1925     infoPtr->buttons[nIndex].fsStyle   = lpTbb->fsStyle;
1926     infoPtr->buttons[nIndex].dwData    = lpTbb->dwData;
1927     infoPtr->buttons[nIndex].iString   = lpTbb->iString;
1928
1929     if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
1930         TTTOOLINFOA ti;
1931
1932         ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1933         ti.cbSize   = sizeof (TTTOOLINFOA);
1934         ti.hwnd     = hwnd;
1935         ti.uId      = lpTbb->idCommand;
1936         ti.hinst    = 0;
1937         ti.lpszText = LPSTR_TEXTCALLBACKA;
1938
1939         SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1940                         0, (LPARAM)&ti);
1941     }
1942
1943     /* post insert copy */
1944     if (nIndex < infoPtr->nNumButtons - 1) {
1945         memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
1946                 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
1947     }
1948
1949     COMCTL32_Free (oldButtons);
1950
1951     TOOLBAR_CalcToolbar (hwnd);
1952
1953     InvalidateRect (hwnd, NULL, FALSE);
1954
1955     return TRUE;
1956 }
1957
1958
1959 /* << TOOLBAR_InsertButton32W >> */
1960 /* << TOOLBAR_InsertMarkHitTest >> */
1961
1962
1963 static LRESULT
1964 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
1965 {
1966     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1967     INT nIndex;
1968
1969     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1970     if (nIndex == -1)
1971         return FALSE;
1972
1973     return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
1974 }
1975
1976
1977 static LRESULT
1978 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
1979 {
1980     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1981     INT nIndex;
1982
1983     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1984     if (nIndex == -1)
1985         return FALSE;
1986
1987     return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
1988 }
1989
1990
1991 static LRESULT
1992 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
1993 {
1994     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1995     INT nIndex;
1996
1997     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
1998     if (nIndex == -1)
1999         return FALSE;
2000
2001     return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2002 }
2003
2004
2005 static LRESULT
2006 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2007 {
2008     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2009     INT nIndex;
2010
2011     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2012     if (nIndex == -1)
2013         return FALSE;
2014
2015     return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2016 }
2017
2018
2019 static LRESULT
2020 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2021 {
2022     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2023     INT nIndex;
2024
2025     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2026     if (nIndex == -1)
2027         return FALSE;
2028
2029     return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2030 }
2031
2032
2033 static LRESULT
2034 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2035 {
2036     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2037     INT nIndex;
2038
2039     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2040     if (nIndex == -1)
2041         return FALSE;
2042
2043     return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2044 }
2045
2046
2047 /* << TOOLBAR_LoadImages >> */
2048 /* << TOOLBAR_MapAccelerator >> */
2049 /* << TOOLBAR_MarkButton >> */
2050 /* << TOOLBAR_MoveButton >> */
2051
2052
2053 static LRESULT
2054 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2055 {
2056     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2057     TBUTTON_INFO *btnPtr;
2058     HDC hdc;
2059     INT nIndex;
2060
2061     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2062     if (nIndex == -1)
2063         return FALSE;
2064
2065     btnPtr = &infoPtr->buttons[nIndex];
2066     if (LOWORD(lParam) == FALSE)
2067         btnPtr->fsState &= ~TBSTATE_PRESSED;
2068     else
2069         btnPtr->fsState |= TBSTATE_PRESSED;
2070
2071     hdc = GetDC (hwnd);
2072     TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2073     ReleaseDC (hwnd, hdc);
2074
2075     return TRUE;
2076 }
2077
2078
2079 /* << TOOLBAR_ReplaceBitmap >> */
2080
2081
2082 static LRESULT
2083 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2084 {
2085 #if 0
2086     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2087     LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
2088
2089     if (lpSave == NULL) return 0;
2090
2091     if ((BOOL)wParam) {
2092         /* save toolbar information */
2093         FIXME("save to \"%s\" \"%s\"\n",
2094                lpSave->pszSubKey, lpSave->pszValueName);
2095
2096
2097     }
2098     else {
2099         /* restore toolbar information */
2100
2101         FIXME("restore from \"%s\" \"%s\"\n",
2102                lpSave->pszSubKey, lpSave->pszValueName);
2103
2104
2105     }
2106 #endif
2107
2108     return 0;
2109 }
2110
2111
2112 /* << TOOLBAR_SaveRestore32W >> */
2113 /* << TOOLBAR_SetAnchorHighlight >> */
2114
2115
2116 static LRESULT
2117 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2118 {
2119     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2120
2121     if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2122         return FALSE;
2123
2124     infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
2125     infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
2126
2127     return TRUE;
2128 }
2129
2130
2131 static LRESULT
2132 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2133 {
2134     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2135     LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
2136     TBUTTON_INFO *btnPtr;
2137     INT nIndex;
2138
2139     if (lptbbi == NULL)
2140         return FALSE;
2141     if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
2142         return FALSE;
2143     
2144     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2145     if (nIndex == -1)
2146         return FALSE;
2147
2148     btnPtr = &infoPtr->buttons[nIndex];
2149     if (lptbbi->dwMask & TBIF_COMMAND)
2150         btnPtr->idCommand = lptbbi->idCommand;
2151     if (lptbbi->dwMask & TBIF_IMAGE)
2152         btnPtr->iBitmap = lptbbi->iImage;
2153     if (lptbbi->dwMask & TBIF_LPARAM)
2154         btnPtr->dwData = lptbbi->lParam;
2155 /*    if (lptbbi->dwMask & TBIF_SIZE) */
2156 /*      btnPtr->cx = lptbbi->cx; */
2157     if (lptbbi->dwMask & TBIF_STATE)
2158         btnPtr->fsState = lptbbi->fsState;
2159     if (lptbbi->dwMask & TBIF_STYLE)
2160         btnPtr->fsStyle = lptbbi->fsStyle;
2161
2162     if (lptbbi->dwMask & TBIF_TEXT) {
2163         if ((btnPtr->iString >= 0) || 
2164             (btnPtr->iString < infoPtr->nNumStrings)) {
2165 #if 0
2166             CHAR **lpString = &infoPtr->strings[btnPtr->iString];
2167             INT len = lstrlenA (lptbbi->pszText);
2168             *lpString = COMCTL32_ReAlloc (lpString, sizeof(char)*(len+1));
2169 #endif
2170
2171             /* this is the ultimate sollution */
2172 /*          Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
2173         }
2174     }
2175
2176     return TRUE;
2177 }
2178
2179
2180 /* << TOOLBAR_SetButtonInfo32W >> */
2181
2182
2183 static LRESULT
2184 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2185 {
2186     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2187
2188     if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
2189         return FALSE;
2190
2191     infoPtr->nButtonWidth = (INT)LOWORD(lParam);
2192     infoPtr->nButtonHeight = (INT)HIWORD(lParam);
2193
2194     return TRUE;
2195 }
2196
2197
2198 static LRESULT
2199 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
2200 {
2201     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2202
2203     if (infoPtr == NULL)
2204         return FALSE;
2205
2206     infoPtr->cxMin = (INT)LOWORD(lParam);
2207     infoPtr->cxMax = (INT)HIWORD(lParam);
2208
2209     return TRUE;
2210 }
2211
2212
2213 static LRESULT
2214 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
2215 {
2216     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2217     INT nIndex = (INT)wParam;
2218
2219     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2220         return FALSE;
2221
2222     infoPtr->buttons[nIndex].idCommand = (INT)lParam;
2223
2224     if (infoPtr->hwndToolTip) {
2225
2226         FIXME("change tool tip!\n");
2227
2228     }
2229
2230     return TRUE;
2231 }
2232
2233
2234 /* << TOOLBAR_SetColorScheme >> */
2235
2236
2237 static LRESULT
2238 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2239 {
2240     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2241     HIMAGELIST himlTemp;
2242
2243     himlTemp = infoPtr->himlDis;
2244     infoPtr->himlDis = (HIMAGELIST)lParam;
2245
2246     /* FIXME: redraw ? */
2247
2248     return (LRESULT)himlTemp; 
2249 }
2250
2251
2252 static LRESULT
2253 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2254 {
2255     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2256     DWORD dwTemp;
2257
2258     dwTemp = infoPtr->dwDTFlags;
2259     infoPtr->dwDTFlags =
2260         (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
2261
2262     return (LRESULT)dwTemp;
2263 }
2264
2265
2266 static LRESULT
2267 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2268 {
2269     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2270     DWORD dwTemp;
2271
2272     dwTemp = infoPtr->dwExStyle;
2273     infoPtr->dwExStyle = (DWORD)lParam;
2274
2275     return (LRESULT)dwTemp; 
2276 }
2277
2278
2279 static LRESULT
2280 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2281 {
2282     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
2283     HIMAGELIST himlTemp;
2284
2285     himlTemp = infoPtr->himlHot;
2286     infoPtr->himlHot = (HIMAGELIST)lParam;
2287
2288     /* FIXME: redraw ? */
2289
2290     return (LRESULT)himlTemp; 
2291 }
2292
2293
2294 /* << TOOLBAR_SetHotItem >> */
2295
2296
2297 static LRESULT
2298 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2299 {
2300     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2301     HIMAGELIST himlTemp;
2302
2303     himlTemp = infoPtr->himlDef;
2304     infoPtr->himlDef = (HIMAGELIST)lParam;
2305
2306     /* FIXME: redraw ? */
2307
2308     return (LRESULT)himlTemp; 
2309 }
2310
2311
2312 static LRESULT
2313 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2314 {
2315     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2316
2317     infoPtr->nIndent = (INT)wParam;
2318
2319     TOOLBAR_CalcToolbar (hwnd);
2320
2321     InvalidateRect(hwnd, NULL, FALSE);
2322
2323     return TRUE;
2324 }
2325
2326
2327 /* << TOOLBAR_SetInsertMark >> */
2328
2329
2330 static LRESULT
2331 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2332 {
2333     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2334
2335     infoPtr->clrInsertMark = (COLORREF)lParam;
2336
2337     /* FIXME : redraw ??*/
2338
2339     return 0;
2340 }
2341
2342
2343 static LRESULT
2344 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2345 {
2346     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2347
2348     if (infoPtr == NULL)
2349         return FALSE;
2350
2351     infoPtr->nMaxTextRows = (INT)wParam;
2352
2353     return TRUE;
2354 }
2355
2356
2357 /* << TOOLBAR_SetPadding >> */
2358
2359
2360 static LRESULT
2361 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
2362 {
2363     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2364     HWND hwndOldNotify;
2365
2366     if (infoPtr == NULL)
2367         return 0;
2368     hwndOldNotify = infoPtr->hwndNotify;
2369     infoPtr->hwndNotify = (HWND)wParam;
2370
2371     return hwndOldNotify;
2372 }
2373
2374
2375 static LRESULT
2376 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2377 {
2378     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2379     LPRECT lprc = (LPRECT)lParam;
2380
2381     if (LOWORD(wParam) > 1) {
2382
2383         FIXME("multiple rows not supported!\n");
2384
2385     }
2386
2387     /* recalculate toolbar */
2388     TOOLBAR_CalcToolbar (hwnd);
2389
2390     /* return bounding rectangle */
2391     if (lprc) {
2392         lprc->left   = infoPtr->rcBound.left;
2393         lprc->right  = infoPtr->rcBound.right;
2394         lprc->top    = infoPtr->rcBound.top;
2395         lprc->bottom = infoPtr->rcBound.bottom;
2396     }
2397
2398     /* repaint toolbar */
2399     InvalidateRect(hwnd, NULL, FALSE);
2400
2401     return 0;
2402 }
2403
2404
2405 static LRESULT
2406 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2407 {
2408     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2409     TBUTTON_INFO *btnPtr;
2410     HDC hdc;
2411     INT nIndex;
2412
2413     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2414     if (nIndex == -1)
2415         return FALSE;
2416
2417     btnPtr = &infoPtr->buttons[nIndex];
2418     btnPtr->fsState = LOWORD(lParam);
2419
2420     hdc = GetDC (hwnd);
2421     TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2422     ReleaseDC (hwnd, hdc);
2423
2424     return TRUE;
2425 }
2426
2427
2428 static LRESULT
2429 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2430 {
2431     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2432     TBUTTON_INFO *btnPtr;
2433     HDC hdc;
2434     INT nIndex;
2435
2436     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2437     if (nIndex == -1)
2438         return FALSE;
2439
2440     btnPtr = &infoPtr->buttons[nIndex];
2441     btnPtr->fsStyle = LOWORD(lParam);
2442
2443     hdc = GetDC (hwnd);
2444     TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2445     ReleaseDC (hwnd, hdc);
2446
2447     if (infoPtr->hwndToolTip) {
2448
2449         FIXME("change tool tip!\n");
2450
2451     }
2452
2453     return TRUE;
2454 }
2455
2456
2457 inline static LRESULT
2458 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2459 {
2460     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2461
2462     if (infoPtr == NULL)
2463         return 0;
2464     infoPtr->hwndToolTip = (HWND)wParam;
2465     return 0;
2466 }
2467
2468
2469 static LRESULT
2470 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2471 {
2472     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2473     BOOL bTemp;
2474
2475     TRACE("%s hwnd=0x%04x stub!\n", 
2476            ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
2477
2478     bTemp = infoPtr->bUnicode;
2479     infoPtr->bUnicode = (BOOL)wParam;
2480
2481     return bTemp;
2482 }
2483
2484
2485 static LRESULT
2486 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
2487 {
2488     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2489     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2490     LOGFONTA logFont;
2491
2492     /* initialize info structure */
2493     infoPtr->nButtonHeight = 22;
2494     infoPtr->nButtonWidth = 23;
2495     infoPtr->nBitmapHeight = 15;
2496     infoPtr->nBitmapWidth = 16;
2497
2498     infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
2499     infoPtr->nRows = 1;
2500     infoPtr->nMaxTextRows = 1;
2501     infoPtr->cxMin = -1;
2502     infoPtr->cxMax = -1;
2503
2504     infoPtr->bCaptured = FALSE;
2505     infoPtr->bUnicode = IsWindowUnicode (hwnd);
2506     infoPtr->nButtonDown = -1;
2507     infoPtr->nOldHit = -1;
2508     infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
2509     infoPtr->hwndNotify = GetParent (hwnd);
2510     infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
2511     infoPtr->dwDTFlags = DT_CENTER;
2512
2513     SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
2514     infoPtr->hFont = CreateFontIndirectA (&logFont);
2515
2516     if (dwStyle & TBSTYLE_TOOLTIPS) {
2517         /* Create tooltip control */
2518         infoPtr->hwndToolTip =
2519             CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
2520                                CW_USEDEFAULT, CW_USEDEFAULT,
2521                                CW_USEDEFAULT, CW_USEDEFAULT,
2522                                hwnd, 0, 0, 0);
2523
2524         /* Send NM_TOOLTIPSCREATED notification */
2525         if (infoPtr->hwndToolTip) {
2526             NMTOOLTIPSCREATED nmttc;
2527
2528             nmttc.hdr.hwndFrom = hwnd;
2529             nmttc.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
2530             nmttc.hdr.code = NM_TOOLTIPSCREATED;
2531             nmttc.hwndToolTips = infoPtr->hwndToolTip;
2532
2533             SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
2534                           (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
2535         }
2536     }
2537
2538     return 0;
2539 }
2540
2541
2542 static LRESULT
2543 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
2544 {
2545     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2546
2547     /* delete tooltip control */
2548     if (infoPtr->hwndToolTip)
2549         DestroyWindow (infoPtr->hwndToolTip);
2550
2551     /* delete button data */
2552     if (infoPtr->buttons)
2553         COMCTL32_Free (infoPtr->buttons);
2554
2555     /* delete strings */
2556     if (infoPtr->strings) {
2557         INT i;
2558         for (i = 0; i < infoPtr->nNumStrings; i++)
2559             if (infoPtr->strings[i])
2560                 COMCTL32_Free (infoPtr->strings[i]);
2561
2562         COMCTL32_Free (infoPtr->strings);
2563     }
2564
2565     /* destroy internal image list */
2566     if (infoPtr->himlInt)
2567         ImageList_Destroy (infoPtr->himlInt);
2568
2569     /* delete default font */
2570     if (infoPtr->hFont)
2571         DeleteObject (infoPtr->hFont);
2572
2573     /* free toolbar info data */
2574     COMCTL32_Free (infoPtr);
2575
2576     return 0;
2577 }
2578
2579
2580 static LRESULT
2581 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
2582 {
2583     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2584
2585     if (infoPtr->bTransparent)
2586         return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
2587
2588     return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
2589 }
2590
2591
2592 static LRESULT
2593 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
2594 {
2595     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2596     TBUTTON_INFO *btnPtr;
2597     POINT pt;
2598     INT   nHit;
2599     HDC   hdc;
2600
2601     pt.x = (INT)LOWORD(lParam);
2602     pt.y = (INT)HIWORD(lParam);
2603     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
2604
2605     if (nHit >= 0) {
2606         btnPtr = &infoPtr->buttons[nHit];
2607         if (!(btnPtr->fsState & TBSTATE_ENABLED))
2608             return 0;
2609         SetCapture (hwnd);
2610         infoPtr->bCaptured = TRUE;
2611         infoPtr->nButtonDown = nHit;
2612
2613         btnPtr->fsState |= TBSTATE_PRESSED;
2614
2615         hdc = GetDC (hwnd);
2616         TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2617         ReleaseDC (hwnd, hdc);
2618     }
2619     else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
2620         TOOLBAR_Customize (hwnd);
2621
2622     return 0;
2623 }
2624
2625
2626 static LRESULT
2627 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
2628 {
2629     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2630     TBUTTON_INFO *btnPtr;
2631     POINT pt;
2632     INT   nHit;
2633     HDC   hdc;
2634
2635     if (infoPtr->hwndToolTip)
2636         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
2637                             WM_LBUTTONDOWN, wParam, lParam);
2638
2639     pt.x = (INT)LOWORD(lParam);
2640     pt.y = (INT)HIWORD(lParam);
2641     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
2642
2643     if (nHit >= 0) {
2644         btnPtr = &infoPtr->buttons[nHit];
2645         if (!(btnPtr->fsState & TBSTATE_ENABLED))
2646             return 0;
2647
2648         SetCapture (hwnd);
2649         infoPtr->bCaptured = TRUE;
2650         infoPtr->nButtonDown = nHit;
2651         infoPtr->nOldHit = nHit;
2652
2653         btnPtr->fsState |= TBSTATE_PRESSED;
2654
2655         hdc = GetDC (hwnd);
2656         TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2657         ReleaseDC (hwnd, hdc);
2658     }
2659
2660     return 0;
2661 }
2662
2663
2664 static LRESULT
2665 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
2666 {
2667     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2668     TBUTTON_INFO *btnPtr;
2669     POINT pt;
2670     INT   nHit;
2671     INT   nOldIndex = -1;
2672     HDC   hdc;
2673     BOOL  bSendMessage = TRUE;
2674
2675     if (infoPtr->hwndToolTip)
2676         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
2677                             WM_LBUTTONUP, wParam, lParam);
2678
2679     pt.x = (INT)LOWORD(lParam);
2680     pt.y = (INT)HIWORD(lParam);
2681     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
2682
2683     if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
2684         infoPtr->bCaptured = FALSE;
2685         ReleaseCapture ();
2686         btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
2687         btnPtr->fsState &= ~TBSTATE_PRESSED;
2688
2689         if (nHit == infoPtr->nButtonDown) {
2690             if (btnPtr->fsStyle & TBSTYLE_CHECK) {
2691                 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
2692                     nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
2693                         infoPtr->nButtonDown);
2694                     if (nOldIndex == infoPtr->nButtonDown)
2695                         bSendMessage = FALSE;
2696                     if ((nOldIndex != infoPtr->nButtonDown) && 
2697                         (nOldIndex != -1))
2698                         infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
2699                     btnPtr->fsState |= TBSTATE_CHECKED;
2700                 }
2701                 else {
2702                     if (btnPtr->fsState & TBSTATE_CHECKED)
2703                         btnPtr->fsState &= ~TBSTATE_CHECKED;
2704                     else
2705                         btnPtr->fsState |= TBSTATE_CHECKED;
2706                 }
2707             }
2708         }
2709         else
2710             bSendMessage = FALSE;
2711
2712         hdc = GetDC (hwnd);
2713         if (nOldIndex != -1)
2714             TOOLBAR_DrawButton (hwnd, &infoPtr->buttons[nOldIndex], hdc);
2715         TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2716         ReleaseDC (hwnd, hdc);
2717
2718         if (bSendMessage)
2719             SendMessageA (infoPtr->hwndNotify, WM_COMMAND,
2720                           MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
2721
2722         infoPtr->nButtonDown = -1;
2723         infoPtr->nOldHit = -1;
2724     }
2725
2726     return 0;
2727 }
2728
2729
2730 static LRESULT
2731 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
2732 {
2733     TBUTTON_INFO *btnPtr, *oldBtnPtr;
2734     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2735     POINT pt;
2736     INT   nHit;
2737     HDC   hdc;
2738
2739     if (infoPtr->hwndToolTip)
2740         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
2741                             WM_MOUSEMOVE, wParam, lParam);
2742
2743     pt.x = (INT)LOWORD(lParam);
2744     pt.y = (INT)HIWORD(lParam);
2745
2746     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
2747
2748     if (infoPtr->nOldHit != nHit)
2749     {
2750         /* Remove the effect of an old hot button */
2751         if(infoPtr->nOldHit == infoPtr->nHotItem)
2752         {
2753             oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
2754             oldBtnPtr->bHot = FALSE;
2755                     
2756             InvalidateRect (hwnd, &oldBtnPtr->rect, TRUE);
2757         }
2758
2759         /* It's not a separator or in nowhere. It's a hot button. */
2760         if (nHit >= 0)
2761         {
2762             btnPtr = &infoPtr->buttons[nHit];
2763             btnPtr->bHot = TRUE;
2764
2765             hdc = GetDC (hwnd);
2766             TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2767             ReleaseDC (hwnd, hdc);
2768
2769             infoPtr->nHotItem = nHit;
2770         }
2771
2772     if (infoPtr->bCaptured) {
2773             btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
2774             if (infoPtr->nOldHit == infoPtr->nButtonDown) {
2775                 btnPtr->fsState &= ~TBSTATE_PRESSED;
2776                 hdc = GetDC (hwnd);
2777                 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2778                 ReleaseDC (hwnd, hdc);
2779             }
2780             else if (nHit == infoPtr->nButtonDown) {
2781                 btnPtr->fsState |= TBSTATE_PRESSED;
2782                 hdc = GetDC (hwnd);
2783                 TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
2784                 ReleaseDC (hwnd, hdc);
2785             }
2786         }
2787         infoPtr->nOldHit = nHit;
2788     }
2789     return 0;
2790 }
2791
2792
2793 inline static LRESULT
2794 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2795 {
2796 /*    if (wndPtr->dwStyle & CCS_NODIVIDER) */
2797         return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
2798 /*    else */
2799 /*      return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
2800 }
2801
2802
2803 inline static LRESULT
2804 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2805 {
2806     if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
2807         ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
2808
2809     return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
2810 }
2811
2812
2813 static LRESULT
2814 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2815 {
2816     TOOLBAR_INFO *infoPtr;
2817
2818     /* allocate memory for info structure */
2819     infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
2820     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
2821
2822     /* paranoid!! */
2823     infoPtr->dwStructSize = sizeof(TBBUTTON);
2824
2825     /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
2826     if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
2827         HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
2828         SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
2829     }
2830
2831     return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
2832 }
2833
2834
2835 static LRESULT
2836 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
2837 {
2838     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2839     RECT rcWindow;
2840     HDC hdc;
2841
2842     if (dwStyle & WS_MINIMIZE)
2843         return 0; /* Nothing to do */
2844
2845     DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
2846
2847     if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
2848         return 0;
2849
2850     if (!(dwStyle & CCS_NODIVIDER))
2851     {
2852         GetWindowRect (hwnd, &rcWindow);
2853         OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
2854         DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
2855     }
2856
2857     ReleaseDC( hwnd, hdc );
2858
2859     return 0;
2860 }
2861
2862
2863 inline static LRESULT
2864 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
2865 {
2866     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2867     LPNMHDR lpnmh = (LPNMHDR)lParam;
2868
2869     TRACE("passing WM_NOTIFY!\n");
2870
2871     if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
2872         SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,   wParam, lParam);
2873
2874 #if 0
2875         if (lpnmh->code == TTN_GETDISPINFOA) {
2876             LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
2877
2878             FIXME("retrieving ASCII string\n");
2879
2880         }
2881         else if (lpnmh->code == TTN_GETDISPINFOW) {
2882             LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
2883
2884             FIXME("retrieving UNICODE string\n");
2885
2886         }
2887 #endif
2888     }
2889
2890     return 0;
2891 }
2892
2893
2894 static LRESULT
2895 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
2896 {
2897     HDC hdc;
2898     PAINTSTRUCT ps;
2899
2900     TOOLBAR_CalcToolbar( hwnd );
2901     hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
2902     TOOLBAR_Refresh (hwnd, hdc);
2903     if (!wParam)
2904         EndPaint (hwnd, &ps);
2905     return 0;
2906 }
2907
2908
2909 static LRESULT
2910 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
2911 {
2912     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2913     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2914     RECT parent_rect;
2915     HWND parent;
2916     /* INT32  x, y; */
2917     INT  cx, cy;
2918     INT  flags;
2919     UINT uPosFlags = 0;
2920
2921     /* Resize deadlock check */
2922     if (infoPtr->bAutoSize) {
2923         infoPtr->bAutoSize = FALSE;
2924         return 0;
2925     }
2926
2927     flags = (INT) wParam;
2928
2929     /* FIXME for flags =
2930      * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
2931      */
2932
2933     TRACE("sizing toolbar!\n");
2934
2935     if (flags == SIZE_RESTORED) {
2936         /* width and height don't apply */
2937         parent = GetParent (hwnd);
2938         GetClientRect(parent, &parent_rect);
2939
2940         if (dwStyle & CCS_NORESIZE) {
2941             uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
2942
2943             /* FIXME */
2944 /*          infoPtr->nWidth = parent_rect.right - parent_rect.left; */
2945             cy = infoPtr->nHeight;
2946             cx = infoPtr->nWidth;
2947             TOOLBAR_CalcToolbar (hwnd);
2948             infoPtr->nWidth = cx;
2949             infoPtr->nHeight = cy;
2950         }
2951         else {
2952             infoPtr->nWidth = parent_rect.right - parent_rect.left;
2953             TOOLBAR_CalcToolbar (hwnd);
2954             cy = infoPtr->nHeight;
2955             cx = infoPtr->nWidth;
2956         }
2957
2958         if (dwStyle & CCS_NOPARENTALIGN) {
2959             uPosFlags |= SWP_NOMOVE;
2960             cy = infoPtr->nHeight;
2961             cx = infoPtr->nWidth;
2962         }
2963
2964         if (!(dwStyle & CCS_NODIVIDER))
2965             cy += GetSystemMetrics(SM_CYEDGE);
2966
2967         SetWindowPos (hwnd, 0, parent_rect.left, parent_rect.top,
2968                         cx, cy, uPosFlags | SWP_NOZORDER);
2969     }
2970     return 0;
2971 }
2972
2973
2974 static LRESULT
2975 TOOLBAR_StyleChanged (HWND hwnd, WPARAM wParam, LPARAM lParam)
2976 {
2977     TOOLBAR_AutoSize (hwnd, wParam, lParam);
2978
2979     InvalidateRect(hwnd, NULL, FALSE);
2980
2981     return 0;
2982 }
2983
2984
2985
2986 static LRESULT WINAPI
2987 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2988 {
2989     switch (uMsg)
2990     {
2991         case TB_ADDBITMAP:
2992             return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
2993
2994         case TB_ADDBUTTONSA:
2995             return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
2996
2997 /*      case TB_ADDBUTTONSW: */
2998
2999         case TB_ADDSTRINGA:
3000             return TOOLBAR_AddStringA (hwnd, wParam, lParam);
3001
3002         case TB_ADDSTRINGW:
3003             return TOOLBAR_AddStringW (hwnd, wParam, lParam);
3004
3005         case TB_AUTOSIZE:
3006             return TOOLBAR_AutoSize (hwnd, wParam, lParam);
3007
3008         case TB_BUTTONCOUNT:
3009             return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
3010
3011         case TB_BUTTONSTRUCTSIZE:
3012             return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
3013
3014         case TB_CHANGEBITMAP:
3015             return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
3016
3017         case TB_CHECKBUTTON:
3018             return TOOLBAR_CheckButton (hwnd, wParam, lParam);
3019
3020         case TB_COMMANDTOINDEX:
3021             return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
3022
3023         case TB_CUSTOMIZE:
3024             return TOOLBAR_Customize (hwnd);
3025
3026         case TB_DELETEBUTTON:
3027             return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
3028
3029         case TB_ENABLEBUTTON:
3030             return TOOLBAR_EnableButton (hwnd, wParam, lParam);
3031
3032 /*      case TB_GETANCHORHIGHLIGHT:             */ /* 4.71 */
3033
3034         case TB_GETBITMAP:
3035             return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
3036
3037         case TB_GETBITMAPFLAGS:
3038             return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
3039
3040         case TB_GETBUTTON:
3041             return TOOLBAR_GetButton (hwnd, wParam, lParam);
3042
3043         case TB_GETBUTTONINFOA:
3044             return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
3045
3046 /*      case TB_GETBUTTONINFOW:         */ /* 4.71 */
3047
3048         case TB_GETBUTTONSIZE:
3049             return TOOLBAR_GetButtonSize (hwnd);
3050
3051         case TB_GETBUTTONTEXTA:
3052             return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
3053
3054 /*      case TB_GETBUTTONTEXTW: */
3055 /*      case TB_GETCOLORSCHEME:                 */ /* 4.71 */
3056
3057         case TB_GETDISABLEDIMAGELIST:
3058             return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
3059
3060         case TB_GETEXTENDEDSTYLE:
3061             return TOOLBAR_GetExtendedStyle (hwnd);
3062
3063         case TB_GETHOTIMAGELIST:
3064             return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
3065
3066 /*      case TB_GETHOTITEM:                     */ /* 4.71 */
3067
3068         case TB_GETIMAGELIST:
3069             return TOOLBAR_GetImageList (hwnd, wParam, lParam);
3070
3071 /*      case TB_GETINSERTMARK:                  */ /* 4.71 */
3072 /*      case TB_GETINSERTMARKCOLOR:             */ /* 4.71 */
3073
3074         case TB_GETITEMRECT:
3075             return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
3076
3077         case TB_GETMAXSIZE:
3078             return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
3079
3080 /*      case TB_GETOBJECT:                      */ /* 4.71 */
3081 /*      case TB_GETPADDING:                     */ /* 4.71 */
3082
3083         case TB_GETRECT:
3084             return TOOLBAR_GetRect (hwnd, wParam, lParam);
3085
3086         case TB_GETROWS:
3087             return TOOLBAR_GetRows (hwnd, wParam, lParam);
3088
3089         case TB_GETSTATE:
3090             return TOOLBAR_GetState (hwnd, wParam, lParam);
3091
3092         case TB_GETSTYLE:
3093             return TOOLBAR_GetStyle (hwnd, wParam, lParam);
3094
3095         case TB_GETTEXTROWS:
3096             return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
3097
3098         case TB_GETTOOLTIPS:
3099             return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
3100
3101         case TB_GETUNICODEFORMAT:
3102             return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
3103
3104         case TB_HIDEBUTTON:
3105             return TOOLBAR_HideButton (hwnd, wParam, lParam);
3106
3107         case TB_HITTEST:
3108             return TOOLBAR_HitTest (hwnd, wParam, lParam);
3109
3110         case TB_INDETERMINATE:
3111             return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
3112
3113         case TB_INSERTBUTTONA:
3114             return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
3115
3116 /*      case TB_INSERTBUTTONW: */
3117 /*      case TB_INSERTMARKHITTEST:              */ /* 4.71 */
3118
3119         case TB_ISBUTTONCHECKED:
3120             return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
3121
3122         case TB_ISBUTTONENABLED:
3123             return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
3124
3125         case TB_ISBUTTONHIDDEN:
3126             return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
3127
3128         case TB_ISBUTTONHIGHLIGHTED:
3129             return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
3130
3131         case TB_ISBUTTONINDETERMINATE:
3132             return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
3133
3134         case TB_ISBUTTONPRESSED:
3135             return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
3136
3137 /*      case TB_LOADIMAGES:                     */ /* 4.70 */
3138 /*      case TB_MAPACCELERATORA:                */ /* 4.71 */
3139 /*      case TB_MAPACCELERATORW:                */ /* 4.71 */
3140 /*      case TB_MARKBUTTON:                     */ /* 4.71 */
3141 /*      case TB_MOVEBUTTON:                     */ /* 4.71 */
3142
3143         case TB_PRESSBUTTON:
3144             return TOOLBAR_PressButton (hwnd, wParam, lParam);
3145
3146 /*      case TB_REPLACEBITMAP: */
3147
3148         case TB_SAVERESTOREA:
3149             return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
3150
3151 /*      case TB_SAVERESTOREW: */
3152 /*      case TB_SETANCHORHIGHLIGHT:             */ /* 4.71 */
3153
3154         case TB_SETBITMAPSIZE:
3155             return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
3156
3157         case TB_SETBUTTONINFOA:
3158             return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
3159
3160 /*      case TB_SETBUTTONINFOW:                 */ /* 4.71 */
3161
3162         case TB_SETBUTTONSIZE:
3163             return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
3164
3165         case TB_SETBUTTONWIDTH:
3166             return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
3167
3168         case TB_SETCMDID:
3169             return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
3170
3171 /*      case TB_SETCOLORSCHEME:                 */ /* 4.71 */
3172
3173         case TB_SETDISABLEDIMAGELIST:
3174             return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
3175
3176         case TB_SETDRAWTEXTFLAGS:
3177             return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
3178
3179         case TB_SETEXTENDEDSTYLE:
3180             return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
3181
3182         case TB_SETHOTIMAGELIST:
3183             return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
3184
3185 /*      case TB_SETHOTITEM:                     */ /* 4.71 */
3186
3187         case TB_SETIMAGELIST:
3188             return TOOLBAR_SetImageList (hwnd, wParam, lParam);
3189
3190         case TB_SETINDENT:
3191             return TOOLBAR_SetIndent (hwnd, wParam, lParam);
3192
3193 /*      case TB_SETINSERTMARK:                  */ /* 4.71 */
3194
3195         case TB_SETINSERTMARKCOLOR:
3196             return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
3197
3198         case TB_SETMAXTEXTROWS:
3199             return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
3200
3201 /*      case TB_SETPADDING:                     */ /* 4.71 */
3202
3203         case TB_SETPARENT:
3204             return TOOLBAR_SetParent (hwnd, wParam, lParam);
3205
3206         case TB_SETROWS:
3207             return TOOLBAR_SetRows (hwnd, wParam, lParam);
3208
3209         case TB_SETSTATE:
3210             return TOOLBAR_SetState (hwnd, wParam, lParam);
3211
3212         case TB_SETSTYLE:
3213             return TOOLBAR_SetStyle (hwnd, wParam, lParam);
3214
3215         case TB_SETTOOLTIPS:
3216             return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
3217
3218         case TB_SETUNICODEFORMAT:
3219             return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
3220
3221
3222 /*      case WM_CHAR: */
3223
3224         case WM_CREATE:
3225             return TOOLBAR_Create (hwnd, wParam, lParam);
3226
3227         case WM_DESTROY:
3228             return TOOLBAR_Destroy (hwnd, wParam, lParam);
3229
3230         case WM_ERASEBKGND:
3231             return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
3232
3233 /*      case WM_GETFONT: */
3234 /*      case WM_KEYDOWN: */
3235 /*      case WM_KILLFOCUS: */
3236
3237         case WM_LBUTTONDBLCLK:
3238             return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
3239
3240         case WM_LBUTTONDOWN:
3241             return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
3242
3243         case WM_LBUTTONUP:
3244             return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
3245
3246         case WM_MOUSEMOVE:
3247             return TOOLBAR_MouseMove (hwnd, wParam, lParam);
3248
3249         case WM_NCACTIVATE:
3250             return TOOLBAR_NCActivate (hwnd, wParam, lParam);
3251
3252         case WM_NCCALCSIZE:
3253             return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
3254
3255         case WM_NCCREATE:
3256             return TOOLBAR_NCCreate (hwnd, wParam, lParam);
3257
3258         case WM_NCPAINT:
3259             return TOOLBAR_NCPaint (hwnd, wParam, lParam);
3260
3261         case WM_NOTIFY:
3262             return TOOLBAR_Notify (hwnd, wParam, lParam);
3263
3264 /*      case WM_NOTIFYFORMAT: */
3265
3266         case WM_PAINT:
3267             return TOOLBAR_Paint (hwnd, wParam);
3268
3269         case WM_SIZE:
3270             return TOOLBAR_Size (hwnd, wParam, lParam);
3271
3272         case WM_STYLECHANGED:
3273             return TOOLBAR_StyleChanged (hwnd, wParam, lParam);
3274
3275 /*      case WM_SYSCOLORCHANGE: */
3276
3277 /*      case WM_WININICHANGE: */
3278
3279         case WM_CHARTOITEM:
3280         case WM_COMMAND:
3281         case WM_DRAWITEM:
3282         case WM_MEASUREITEM:
3283         case WM_VKEYTOITEM:
3284             return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
3285
3286         default:
3287             if (uMsg >= WM_USER)
3288                 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
3289                      uMsg, wParam, lParam);
3290             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3291     }
3292     return 0;
3293 }
3294
3295
3296 VOID
3297 TOOLBAR_Register (void)
3298 {
3299     WNDCLASSA wndClass;
3300
3301     if (GlobalFindAtomA (TOOLBARCLASSNAMEA)) return;
3302
3303     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
3304     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
3305     wndClass.lpfnWndProc   = (WNDPROC)ToolbarWindowProc;
3306     wndClass.cbClsExtra    = 0;
3307     wndClass.cbWndExtra    = sizeof(TOOLBAR_INFO *);
3308     wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
3309     wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
3310     wndClass.lpszClassName = TOOLBARCLASSNAMEA;
3311  
3312     RegisterClassA (&wndClass);
3313 }
3314
3315
3316 VOID
3317 TOOLBAR_Unregister (void)
3318 {
3319     if (GlobalFindAtomA (TOOLBARCLASSNAMEA))
3320         UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);
3321 }
3322