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