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