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