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