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