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