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