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