Implemented _ultow() and export [Nt/Zw]QueryVolumeInformationFile().
[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     else
1551     {
1552         nButtons = (INT)wParam;
1553         if (nButtons <= 0)
1554             return -1;
1555         
1556         TRACE ("adding %d bitmaps!\n", nButtons);
1557     }
1558     
1559     if (!(infoPtr->himlDef)) {
1560         /* create new default image list */
1561         TRACE ("creating default image list!\n");
1562
1563         infoPtr->himlDef =
1564             ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1565                               ILC_COLOR | ILC_MASK, nButtons, 2);
1566         infoPtr->himlInt = infoPtr->himlDef;
1567     }
1568
1569     nCount = ImageList_GetImageCount(infoPtr->himlDef);
1570
1571     /* Add bitmaps to the default image list */
1572     if (lpAddBmp->hInst == (HINSTANCE)0)
1573     {
1574         nIndex = 
1575             ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1576                                  CLR_DEFAULT);
1577     }
1578     else if (lpAddBmp->hInst == HINST_COMMCTRL)
1579     {
1580         /* Add system bitmaps */
1581         switch (lpAddBmp->nID)
1582     {
1583             case IDB_STD_SMALL_COLOR:
1584                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1585                                        MAKEINTRESOURCEA(IDB_STD_SMALL));
1586                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1587                                               hbmLoad, CLR_DEFAULT);
1588                 DeleteObject (hbmLoad);
1589                 break;
1590
1591             case IDB_STD_LARGE_COLOR:
1592                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1593                                        MAKEINTRESOURCEA(IDB_STD_LARGE));
1594                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1595                                               hbmLoad, CLR_DEFAULT);
1596                 DeleteObject (hbmLoad);
1597                 break;
1598
1599             case IDB_VIEW_SMALL_COLOR:
1600                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1601                                        MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1602                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1603                                               hbmLoad, CLR_DEFAULT);
1604                 DeleteObject (hbmLoad);
1605                 break;
1606
1607             case IDB_VIEW_LARGE_COLOR:
1608                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1609                                        MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1610                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1611                                               hbmLoad, CLR_DEFAULT);
1612                 DeleteObject (hbmLoad);
1613                 break;
1614
1615             case IDB_HIST_SMALL_COLOR:
1616                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1617                                        MAKEINTRESOURCEA(IDB_HIST_SMALL));
1618                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1619                                               hbmLoad, CLR_DEFAULT);
1620                 DeleteObject (hbmLoad);
1621                 break;
1622
1623             case IDB_HIST_LARGE_COLOR:
1624                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1625                                        MAKEINTRESOURCEA(IDB_HIST_LARGE));
1626                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1627                                               hbmLoad, CLR_DEFAULT);
1628                 DeleteObject (hbmLoad);
1629                 break;
1630
1631             default:
1632         nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1633                 ERR ("invalid imagelist!\n");
1634                 break;
1635         }
1636     }
1637     else
1638     {
1639         hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1640         nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1641         DeleteObject (hbmLoad);
1642     }
1643
1644     if (nIndex != -1)
1645     {
1646        INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1647
1648        if (infoPtr->nNumBitmaps + nButtons != imagecount)
1649        {
1650          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",
1651               infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1652               infoPtr->nNumBitmaps+nButtons,imagecount);
1653
1654          infoPtr->nNumBitmaps = imagecount;
1655        }
1656        else
1657          infoPtr->nNumBitmaps += nButtons;
1658     }
1659
1660     InvalidateRect(hwnd, NULL, FALSE);
1661
1662     return nIndex;
1663 }
1664
1665
1666 static LRESULT
1667 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1668 {
1669     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1670     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1671     INT nOldButtons, nNewButtons, nAddButtons, nCount;
1672
1673     TRACE("adding %d buttons!\n", wParam);
1674
1675     nAddButtons = (UINT)wParam;
1676     nOldButtons = infoPtr->nNumButtons;
1677     nNewButtons = nOldButtons + nAddButtons;
1678
1679     if (infoPtr->nNumButtons == 0) {
1680         infoPtr->buttons =
1681             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1682     }
1683     else {
1684         TBUTTON_INFO *oldButtons = infoPtr->buttons;
1685         infoPtr->buttons =
1686             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1687         memcpy (&infoPtr->buttons[0], &oldButtons[0],
1688                 nOldButtons * sizeof(TBUTTON_INFO));
1689         COMCTL32_Free (oldButtons);
1690     }
1691
1692     infoPtr->nNumButtons = nNewButtons;
1693
1694     /* insert new button data */
1695     for (nCount = 0; nCount < nAddButtons; nCount++) {
1696         TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1697         btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
1698         btnPtr->idCommand = lpTbb[nCount].idCommand;
1699         btnPtr->fsState   = lpTbb[nCount].fsState;
1700         btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
1701         btnPtr->dwData    = lpTbb[nCount].dwData;
1702         btnPtr->iString   = lpTbb[nCount].iString;
1703         btnPtr->bHot      = FALSE;
1704
1705         if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1706             TTTOOLINFOA ti;
1707
1708             ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1709             ti.cbSize   = sizeof (TTTOOLINFOA);
1710             ti.hwnd     = hwnd;
1711             ti.uId      = btnPtr->idCommand;
1712             ti.hinst    = 0;
1713             ti.lpszText = LPSTR_TEXTCALLBACKA;
1714
1715             SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1716                             0, (LPARAM)&ti);
1717         }
1718     }
1719
1720     InvalidateRect(hwnd, NULL, FALSE);
1721
1722     return TRUE;
1723 }
1724
1725
1726 static LRESULT
1727 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1728 {
1729     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1730     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1731     INT nOldButtons, nNewButtons, nAddButtons, nCount;
1732
1733     TRACE("adding %d buttons!\n", wParam);
1734
1735     nAddButtons = (UINT)wParam;
1736     nOldButtons = infoPtr->nNumButtons;
1737     nNewButtons = nOldButtons + nAddButtons;
1738
1739     if (infoPtr->nNumButtons == 0) {
1740         infoPtr->buttons =
1741             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1742     }
1743     else {
1744         TBUTTON_INFO *oldButtons = infoPtr->buttons;
1745         infoPtr->buttons =
1746             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1747         memcpy (&infoPtr->buttons[0], &oldButtons[0],
1748                 nOldButtons * sizeof(TBUTTON_INFO));
1749         COMCTL32_Free (oldButtons);
1750     }
1751
1752     infoPtr->nNumButtons = nNewButtons;
1753
1754     /* insert new button data */
1755     for (nCount = 0; nCount < nAddButtons; nCount++) {
1756         TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1757         btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
1758         btnPtr->idCommand = lpTbb[nCount].idCommand;
1759         btnPtr->fsState   = lpTbb[nCount].fsState;
1760         btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
1761         btnPtr->dwData    = lpTbb[nCount].dwData;
1762         btnPtr->iString   = lpTbb[nCount].iString;
1763         btnPtr->bHot      = FALSE;
1764
1765         if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1766             TTTOOLINFOW ti;
1767
1768             ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1769             ti.cbSize   = sizeof (TTTOOLINFOW);
1770             ti.hwnd     = hwnd;
1771             ti.uId      = btnPtr->idCommand;
1772             ti.hinst    = 0;
1773             ti.lpszText = LPSTR_TEXTCALLBACKW;
1774
1775             SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1776                             0, (LPARAM)&ti);
1777         }
1778     }
1779
1780     InvalidateRect(hwnd, NULL, FALSE);
1781
1782     return TRUE;
1783 }
1784
1785
1786 static LRESULT
1787 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1788 {
1789     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1790     INT nIndex;
1791
1792     if ((wParam) && (HIWORD(lParam) == 0)) {
1793         char szString[256];
1794         INT len, lenW;
1795         TRACE("adding string from resource!\n");
1796
1797         len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1798                              szString, 256);
1799
1800         TRACE("len=%d \"%s\"\n", len, szString);
1801         nIndex = infoPtr->nNumStrings;
1802         if (infoPtr->nNumStrings == 0) {
1803             infoPtr->strings =
1804                 COMCTL32_Alloc (sizeof(LPWSTR));
1805         }
1806         else {
1807             LPWSTR *oldStrings = infoPtr->strings;
1808             infoPtr->strings =
1809                 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1810             memcpy (&infoPtr->strings[0], &oldStrings[0],
1811                     sizeof(LPWSTR) * infoPtr->nNumStrings);
1812             COMCTL32_Free (oldStrings);
1813         }
1814
1815         lenW = MultiByteToWideChar( CP_ACP, 0, szString, -1, NULL, 0 );
1816         infoPtr->strings[infoPtr->nNumStrings] = COMCTL32_Alloc (sizeof(WCHAR)*lenW);
1817         MultiByteToWideChar( CP_ACP, 0, szString, -1,
1818                              infoPtr->strings[infoPtr->nNumStrings], lenW );
1819         infoPtr->nNumStrings++;
1820     }
1821     else {
1822         LPSTR p = (LPSTR)lParam;
1823         INT len, lenW;
1824
1825         if (p == NULL)
1826             return -1;
1827         TRACE("adding string(s) from array!\n");
1828
1829         nIndex = infoPtr->nNumStrings;
1830         while (*p) {
1831             len = strlen (p);
1832             TRACE("len=%d \"%s\"\n", len, p);
1833
1834             if (infoPtr->nNumStrings == 0) {
1835                 infoPtr->strings =
1836                     COMCTL32_Alloc (sizeof(LPWSTR));
1837             }
1838             else {
1839                 LPWSTR *oldStrings = infoPtr->strings;
1840                 infoPtr->strings =
1841                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1842                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1843                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1844                 COMCTL32_Free (oldStrings);
1845             }
1846
1847             lenW = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
1848             infoPtr->strings[infoPtr->nNumStrings] = COMCTL32_Alloc (sizeof(WCHAR)*lenW);
1849             MultiByteToWideChar( CP_ACP, 0, p, -1,
1850                                  infoPtr->strings[infoPtr->nNumStrings], lenW );
1851             infoPtr->nNumStrings++;
1852
1853             p += (len+1);
1854         }
1855     }
1856
1857     return nIndex;
1858 }
1859
1860
1861 static LRESULT
1862 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1863 {
1864 #define MAX_RESOURCE_STRING_LENGTH 512
1865     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1866     INT nIndex;
1867
1868     if ((wParam) && (HIWORD(lParam) == 0)) {
1869         WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1870         INT len;
1871         TRACE("adding string from resource!\n");
1872
1873         len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1874                              szString, MAX_RESOURCE_STRING_LENGTH);
1875
1876         TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1877         TRACE("First char: 0x%x\n", *szString);
1878         if (szString[0] == L'|')
1879         {
1880             PWSTR p = szString + 1;
1881                 
1882             nIndex = infoPtr->nNumStrings;
1883             while (*p != L'|') {
1884
1885             if (infoPtr->nNumStrings == 0) {
1886                 infoPtr->strings =
1887                     COMCTL32_Alloc (sizeof(LPWSTR));
1888             }
1889             else {
1890                 LPWSTR *oldStrings = infoPtr->strings;
1891                 infoPtr->strings =
1892                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1893                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1894                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1895                 COMCTL32_Free (oldStrings);
1896             }
1897
1898             len = COMCTL32_StrChrW (p, L'|') - p;
1899             TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1900             infoPtr->strings[infoPtr->nNumStrings] =
1901                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1902             lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1903             infoPtr->nNumStrings++;
1904
1905                 p += (len+1);
1906             }
1907         }
1908         else
1909         {
1910             nIndex = infoPtr->nNumStrings;
1911             if (infoPtr->nNumStrings == 0) {
1912                 infoPtr->strings =
1913                     COMCTL32_Alloc (sizeof(LPWSTR));
1914             }
1915             else {
1916                 LPWSTR *oldStrings = infoPtr->strings;
1917                 infoPtr->strings =
1918                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1919                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1920                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1921                 COMCTL32_Free (oldStrings);
1922             }
1923
1924             infoPtr->strings[infoPtr->nNumStrings] =
1925                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1926             strcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1927             infoPtr->nNumStrings++;
1928         }
1929     }
1930     else {
1931         LPWSTR p = (LPWSTR)lParam;
1932         INT len;
1933
1934         if (p == NULL)
1935             return -1;
1936         TRACE("adding string(s) from array!\n");
1937         nIndex = infoPtr->nNumStrings;
1938         while (*p) {
1939             len = strlenW (p);
1940
1941             TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1942             if (infoPtr->nNumStrings == 0) {
1943                 infoPtr->strings =
1944                     COMCTL32_Alloc (sizeof(LPWSTR));
1945             }
1946             else {
1947                 LPWSTR *oldStrings = infoPtr->strings;
1948                 infoPtr->strings =
1949                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1950                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1951                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1952                 COMCTL32_Free (oldStrings);
1953             }
1954
1955             infoPtr->strings[infoPtr->nNumStrings] =
1956                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1957             strcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1958             infoPtr->nNumStrings++;
1959
1960             p += (len+1);
1961         }
1962     }
1963
1964     return nIndex;
1965 }
1966
1967
1968 static LRESULT
1969 TOOLBAR_AutoSize (HWND hwnd)
1970 {
1971     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1972     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1973     RECT parent_rect;
1974     RECT window_rect;
1975     HWND parent;
1976     INT  x, y;
1977     INT  cx, cy;
1978     UINT uPosFlags = SWP_NOZORDER;
1979
1980     TRACE("resize forced, style=%lx!\n", dwStyle);
1981
1982     parent = GetParent (hwnd);
1983     GetClientRect(parent, &parent_rect);
1984
1985     x = parent_rect.left;
1986     y = parent_rect.top;
1987
1988     /* FIXME: we should be able to early out if nothing */
1989     /* has changed with nWidth != parent_rect width */
1990
1991     if (dwStyle & CCS_NORESIZE) {
1992         uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1993         cx = 0;
1994         cy = 0;
1995     }
1996     else {
1997         infoPtr->nWidth = parent_rect.right - parent_rect.left;
1998         InvalidateRect( hwnd, NULL, TRUE );
1999         cy = infoPtr->nHeight;
2000         cx = infoPtr->nWidth;
2001
2002         if (dwStyle & CCS_NOMOVEY) {
2003                 GetWindowRect(hwnd, &window_rect);
2004                 ScreenToClient(parent, (LPPOINT)&window_rect.left);
2005                 y = window_rect.top;
2006         }
2007     }
2008
2009     if (dwStyle & CCS_NOPARENTALIGN)
2010         uPosFlags |= SWP_NOMOVE;
2011
2012     if (!(dwStyle & CCS_NODIVIDER))
2013         cy += GetSystemMetrics(SM_CYEDGE);
2014
2015     if (dwStyle & WS_BORDER)
2016     {
2017         x = y = 1;
2018         cy += GetSystemMetrics(SM_CYEDGE);
2019         cx += GetSystemMetrics(SM_CYEDGE);
2020     }
2021
2022     infoPtr->bAutoSize = TRUE;
2023     SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
2024                         cx, cy, uPosFlags);
2025     /* The following line makes sure that the infoPtr->bAutoSize is turned off after
2026      * the setwindowpos calls */
2027     infoPtr->bAutoSize = FALSE;
2028
2029     return 0;
2030 }
2031
2032
2033 static LRESULT
2034 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
2035 {
2036     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2037
2038     return infoPtr->nNumButtons;
2039 }
2040
2041
2042 static LRESULT
2043 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2044 {
2045     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2046
2047     if (infoPtr == NULL) {
2048         ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
2049         ERR("infoPtr == NULL!\n");
2050         return 0;
2051     }
2052
2053     infoPtr->dwStructSize = (DWORD)wParam;
2054
2055     return 0;
2056 }
2057
2058
2059 static LRESULT
2060 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2061 {
2062     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2063     TBUTTON_INFO *btnPtr;
2064     INT nIndex;
2065
2066     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2067     if (nIndex == -1)
2068         return FALSE;
2069
2070     btnPtr = &infoPtr->buttons[nIndex];
2071     btnPtr->iBitmap = LOWORD(lParam);
2072
2073     /* we HAVE to erase the background, the new bitmap could be */
2074     /* transparent */
2075     InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2076
2077     return TRUE;
2078 }
2079
2080
2081 static LRESULT
2082 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2083 {
2084     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2085     TBUTTON_INFO *btnPtr;
2086     INT nIndex;
2087     INT nOldIndex = -1;
2088     BOOL bChecked = FALSE;
2089
2090     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2091     if (nIndex == -1)
2092         return FALSE;
2093
2094     btnPtr = &infoPtr->buttons[nIndex];
2095
2096     if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
2097         return FALSE;
2098
2099     bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
2100
2101     if (LOWORD(lParam) == FALSE)
2102         btnPtr->fsState &= ~TBSTATE_CHECKED;
2103     else {
2104         if (btnPtr->fsStyle & TBSTYLE_GROUP) {
2105             nOldIndex = 
2106                 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
2107             if (nOldIndex == nIndex)
2108                 return 0;
2109             if (nOldIndex != -1)
2110                 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
2111         }
2112         btnPtr->fsState |= TBSTATE_CHECKED;
2113     }
2114
2115     if( bChecked != LOWORD(lParam) )
2116     {
2117         if (nOldIndex != -1)
2118         {
2119             InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
2120                 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
2121         }
2122         InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2123     }
2124
2125     /* FIXME: Send a WM_NOTIFY?? */
2126
2127     return TRUE;
2128 }
2129
2130
2131 static LRESULT
2132 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
2133 {
2134     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2135
2136     return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2137 }
2138
2139
2140 static LRESULT
2141 TOOLBAR_Customize (HWND hwnd)
2142 {
2143     CUSTDLG_INFO custInfo;
2144     LRESULT ret;
2145     LPCVOID template;
2146     HRSRC hRes;
2147     NMHDR nmhdr;
2148
2149     custInfo.tbInfo = TOOLBAR_GetInfoPtr (hwnd);
2150     custInfo.tbHwnd = hwnd;
2151
2152     /* send TBN_BEGINADJUST notification */
2153     nmhdr.hwndFrom = hwnd;
2154     nmhdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
2155     nmhdr.code     = TBN_BEGINADJUST;
2156
2157     SendMessageA (custInfo.tbInfo->hwndNotify, WM_NOTIFY,
2158                   (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
2159
2160     if (!(hRes = FindResourceA (COMCTL32_hModule,
2161                                 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
2162                                 RT_DIALOGA)))
2163         return FALSE;
2164
2165     if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
2166         return FALSE;
2167
2168     ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
2169                                    (LPDLGTEMPLATEA)template,
2170                                    hwnd,
2171                                    (DLGPROC)TOOLBAR_CustomizeDialogProc,
2172                                    (LPARAM)&custInfo);
2173
2174     /* send TBN_ENDADJUST notification */
2175     nmhdr.code = TBN_ENDADJUST;
2176     SendMessageA (custInfo.tbInfo->hwndNotify, WM_NOTIFY,
2177                   (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
2178
2179     return ret;
2180 }
2181
2182
2183 static LRESULT
2184 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2185 {
2186     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2187     INT nIndex = (INT)wParam;
2188
2189     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2190         return FALSE;
2191
2192     if ((infoPtr->hwndToolTip) && 
2193         !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
2194         TTTOOLINFOA ti;
2195
2196         ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2197         ti.cbSize   = sizeof (TTTOOLINFOA);
2198         ti.hwnd     = hwnd;
2199         ti.uId      = infoPtr->buttons[nIndex].idCommand;
2200
2201         SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
2202     }
2203
2204     if (infoPtr->nNumButtons == 1) {
2205         TRACE(" simple delete!\n");
2206         COMCTL32_Free (infoPtr->buttons);
2207         infoPtr->buttons = NULL;
2208         infoPtr->nNumButtons = 0;
2209     }
2210     else {
2211         TBUTTON_INFO *oldButtons = infoPtr->buttons;
2212         TRACE("complex delete! [nIndex=%d]\n", nIndex);
2213
2214         infoPtr->nNumButtons--;
2215         infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2216         if (nIndex > 0) {
2217             memcpy (&infoPtr->buttons[0], &oldButtons[0],
2218                     nIndex * sizeof(TBUTTON_INFO));
2219         }
2220
2221         if (nIndex < infoPtr->nNumButtons) {
2222             memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
2223                     (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
2224         }
2225
2226         COMCTL32_Free (oldButtons);
2227     }
2228
2229     InvalidateRect (hwnd, NULL, TRUE);
2230
2231     return TRUE;
2232 }
2233
2234
2235 static LRESULT
2236 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2237 {
2238     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2239     TBUTTON_INFO *btnPtr;
2240     INT nIndex;
2241     DWORD bState;
2242
2243     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2244     if (nIndex == -1)
2245         return FALSE;
2246
2247     btnPtr = &infoPtr->buttons[nIndex];
2248
2249     bState = btnPtr->fsState & TBSTATE_ENABLED;
2250
2251     /* update the toolbar button state */
2252     if(LOWORD(lParam) == FALSE) {
2253         btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
2254     } else {
2255         btnPtr->fsState |= TBSTATE_ENABLED;
2256     }
2257
2258     /* redraw the button only if the state of the button changed */
2259     if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
2260     {
2261         InvalidateRect(hwnd, &btnPtr->rect,
2262             TOOLBAR_HasText(infoPtr, btnPtr));
2263     }
2264
2265     return TRUE;
2266 }
2267
2268
2269 static inline LRESULT
2270 TOOLBAR_GetAnchorHighlight (HWND hwnd)
2271 {
2272     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2273
2274     return infoPtr->bAnchor;
2275 }
2276
2277
2278 static LRESULT
2279 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2280 {
2281     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2282     INT nIndex;
2283
2284     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2285     if (nIndex == -1)
2286         return -1;
2287
2288     return infoPtr->buttons[nIndex].iBitmap;
2289 }
2290
2291
2292 static inline LRESULT
2293 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2294 {
2295     return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
2296 }
2297
2298
2299 static LRESULT
2300 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2301 {
2302     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2303     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2304     INT nIndex = (INT)wParam;
2305     TBUTTON_INFO *btnPtr;
2306
2307     if (infoPtr == NULL)
2308         return FALSE;
2309
2310     if (lpTbb == NULL)
2311         return FALSE;
2312
2313     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2314         return FALSE;
2315
2316     btnPtr = &infoPtr->buttons[nIndex];
2317     lpTbb->iBitmap   = btnPtr->iBitmap;
2318     lpTbb->idCommand = btnPtr->idCommand;
2319     lpTbb->fsState   = btnPtr->fsState;
2320     lpTbb->fsStyle   = btnPtr->fsStyle;
2321     lpTbb->dwData    = btnPtr->dwData;
2322     lpTbb->iString   = btnPtr->iString;
2323
2324     return TRUE;
2325 }
2326
2327
2328 static LRESULT
2329 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2330 {
2331     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2332     LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
2333     TBUTTON_INFO *btnPtr;
2334     INT nIndex;
2335
2336     if (infoPtr == NULL)
2337         return -1;
2338     if (lpTbInfo == NULL)
2339         return -1;
2340     if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2341         return -1;
2342
2343     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2344     if (nIndex == -1)
2345         return -1;
2346
2347     btnPtr = &infoPtr->buttons[nIndex];
2348
2349     if (lpTbInfo->dwMask & TBIF_COMMAND)
2350         lpTbInfo->idCommand = btnPtr->idCommand;
2351     if (lpTbInfo->dwMask & TBIF_IMAGE)
2352         lpTbInfo->iImage = btnPtr->iBitmap;
2353     if (lpTbInfo->dwMask & TBIF_LPARAM)
2354         lpTbInfo->lParam = btnPtr->dwData;
2355     if (lpTbInfo->dwMask & TBIF_SIZE)
2356         lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2357     if (lpTbInfo->dwMask & TBIF_STATE)
2358         lpTbInfo->fsState = btnPtr->fsState;
2359     if (lpTbInfo->dwMask & TBIF_STYLE)
2360         lpTbInfo->fsStyle = btnPtr->fsStyle;
2361      if (lpTbInfo->dwMask & TBIF_TEXT) {
2362          if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
2363          {      
2364              if (!WideCharToMultiByte( CP_ACP, 0, (LPWSTR)infoPtr->strings[btnPtr->iString], -1,
2365                                        lpTbInfo->pszText, lpTbInfo->cchText, NULL, NULL ))
2366                  lpTbInfo->pszText[lpTbInfo->cchText-1] = 0;
2367          }
2368          else lpTbInfo->pszText[0]=0;
2369     }
2370     return nIndex;
2371 }
2372
2373
2374 static LRESULT
2375 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2376 {
2377     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2378     LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
2379     TBUTTON_INFO *btnPtr;
2380     INT nIndex;
2381
2382     if (infoPtr == NULL)
2383         return -1;
2384     if (lpTbInfo == NULL)
2385         return -1;
2386     if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
2387         return -1;
2388
2389     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2390     if (nIndex == -1)
2391         return -1;
2392
2393     btnPtr = &infoPtr->buttons[nIndex];
2394
2395     if (lpTbInfo->dwMask & TBIF_COMMAND)
2396         lpTbInfo->idCommand = btnPtr->idCommand;
2397     if (lpTbInfo->dwMask & TBIF_IMAGE)
2398         lpTbInfo->iImage = btnPtr->iBitmap;
2399     if (lpTbInfo->dwMask & TBIF_LPARAM)
2400         lpTbInfo->lParam = btnPtr->dwData;
2401     if (lpTbInfo->dwMask & TBIF_SIZE)
2402         lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2403     if (lpTbInfo->dwMask & TBIF_STATE)
2404         lpTbInfo->fsState = btnPtr->fsState;
2405     if (lpTbInfo->dwMask & TBIF_STYLE)
2406         lpTbInfo->fsStyle = btnPtr->fsStyle;
2407     if (lpTbInfo->dwMask & TBIF_TEXT) {
2408         if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
2409             lstrcpynW (lpTbInfo->pszText,
2410                        (LPWSTR)infoPtr->strings[btnPtr->iString],
2411                        lpTbInfo->cchText);
2412     }
2413
2414     return nIndex;
2415 }
2416
2417
2418 static LRESULT
2419 TOOLBAR_GetButtonSize (HWND hwnd)
2420 {
2421     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2422
2423     return MAKELONG((WORD)infoPtr->nButtonWidth,
2424                     (WORD)infoPtr->nButtonHeight);
2425 }
2426
2427
2428 static LRESULT
2429 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2430 {
2431     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2432     INT nIndex, nStringIndex;
2433
2434     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2435     if (nIndex == -1)
2436         return -1;
2437
2438     nStringIndex = infoPtr->buttons[nIndex].iString;
2439
2440     TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2441
2442     if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2443         return -1;
2444
2445     if (lParam == 0)
2446         return -1;
2447
2448     return WideCharToMultiByte( CP_ACP, 0, (LPWSTR)infoPtr->strings[nStringIndex], -1,
2449                                 (LPSTR)lParam, 0x7fffffff, NULL, NULL ) - 1;
2450 }
2451
2452
2453 static LRESULT
2454 TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2455 {
2456     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2457     INT nIndex, nStringIndex;
2458
2459     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2460     if (nIndex == -1)
2461         return -1;
2462
2463     nStringIndex = infoPtr->buttons[nIndex].iString;
2464
2465     TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2466
2467     if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2468         return -1;
2469
2470     if (lParam == 0)
2471         return -1;
2472
2473     strcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2474
2475     return strlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
2476 }
2477
2478
2479 /* << TOOLBAR_GetColorScheme >> */
2480
2481
2482 static LRESULT
2483 TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2484 {
2485     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2486
2487     return (LRESULT)infoPtr->himlDis;
2488 }
2489
2490
2491 inline static LRESULT
2492 TOOLBAR_GetExtendedStyle (HWND hwnd)
2493 {
2494     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2495
2496     return infoPtr->dwExStyle;
2497 }
2498
2499
2500 static LRESULT
2501 TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2502 {
2503     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2504
2505     return (LRESULT)infoPtr->himlHot;
2506 }
2507
2508
2509 static LRESULT
2510 TOOLBAR_GetHotItem (HWND hwnd)
2511 {
2512     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2513
2514     if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
2515         return -1;
2516
2517     if (infoPtr->nHotItem < 0)
2518         return -1;
2519
2520     return (LRESULT)infoPtr->nHotItem;
2521 }
2522
2523
2524 static LRESULT
2525 TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
2526 {
2527     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2528
2529     return (LRESULT)infoPtr->himlDef;
2530 }
2531
2532
2533 /* << TOOLBAR_GetInsertMark >> */
2534 /* << TOOLBAR_GetInsertMarkColor >> */
2535
2536
2537 static LRESULT
2538 TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2539 {
2540     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2541     TBUTTON_INFO *btnPtr;
2542     LPRECT     lpRect;
2543     INT        nIndex;
2544
2545     if (infoPtr == NULL)
2546         return FALSE;
2547     nIndex = (INT)wParam;
2548     btnPtr = &infoPtr->buttons[nIndex];
2549     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2550         return FALSE;
2551     lpRect = (LPRECT)lParam;
2552     if (lpRect == NULL)
2553         return FALSE;
2554     if (btnPtr->fsState & TBSTATE_HIDDEN)
2555         return FALSE;
2556     
2557     lpRect->left   = btnPtr->rect.left;
2558     lpRect->right  = btnPtr->rect.right;
2559     lpRect->bottom = btnPtr->rect.bottom;
2560     lpRect->top    = btnPtr->rect.top;
2561
2562     return TRUE;
2563 }
2564
2565
2566 static LRESULT
2567 TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2568 {
2569     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2570     LPSIZE lpSize = (LPSIZE)lParam;
2571
2572     if (lpSize == NULL)
2573         return FALSE;
2574
2575     lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
2576     lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
2577
2578     TRACE("maximum size %d x %d\n",
2579            infoPtr->rcBound.right - infoPtr->rcBound.left,
2580            infoPtr->rcBound.bottom - infoPtr->rcBound.top);
2581
2582     return TRUE;
2583 }
2584
2585
2586 /* << TOOLBAR_GetObject >> */
2587 /* << TOOLBAR_GetPadding >> */
2588
2589
2590 static LRESULT
2591 TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
2592 {
2593     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2594     TBUTTON_INFO *btnPtr;
2595     LPRECT     lpRect;
2596     INT        nIndex;
2597
2598     if (infoPtr == NULL)
2599         return FALSE;
2600     nIndex = (INT)wParam;
2601     btnPtr = &infoPtr->buttons[nIndex];
2602     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2603         return FALSE;
2604     lpRect = (LPRECT)lParam;
2605     if (lpRect == NULL)
2606         return FALSE;
2607     
2608     lpRect->left   = btnPtr->rect.left;
2609     lpRect->right  = btnPtr->rect.right;
2610     lpRect->bottom = btnPtr->rect.bottom;
2611     lpRect->top    = btnPtr->rect.top;
2612
2613     return TRUE;
2614 }
2615
2616
2617 static LRESULT
2618 TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2619 {
2620     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2621
2622     if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2623         return infoPtr->nRows;
2624     else
2625         return 1;
2626 }
2627
2628
2629 static LRESULT
2630 TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
2631 {
2632     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2633     INT nIndex;
2634
2635     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2636     if (nIndex == -1)
2637         return -1;
2638
2639     return infoPtr->buttons[nIndex].fsState;
2640 }
2641
2642
2643 static LRESULT
2644 TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
2645 {
2646     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2647     INT nIndex;
2648
2649     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2650     if (nIndex == -1)
2651         return -1;
2652
2653     return infoPtr->buttons[nIndex].fsStyle;
2654 }
2655
2656
2657 static LRESULT
2658 TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
2659 {
2660     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2661
2662     if (infoPtr == NULL)
2663         return 0;
2664
2665     return infoPtr->nMaxTextRows;
2666 }
2667
2668
2669 static LRESULT
2670 TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
2671 {
2672     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2673
2674     if (infoPtr == NULL)
2675         return 0;
2676     return infoPtr->hwndToolTip;
2677 }
2678
2679
2680 static LRESULT
2681 TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2682 {
2683     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2684
2685     TRACE("%s hwnd=0x%x stub!\n", 
2686            infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
2687
2688     return infoPtr->bUnicode;
2689 }
2690
2691
2692 inline static LRESULT
2693 TOOLBAR_GetVersion (HWND hwnd)
2694 {
2695     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2696     return infoPtr->iVersion;
2697 }
2698
2699
2700 static LRESULT
2701 TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2702 {
2703     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2704     TBUTTON_INFO *btnPtr;
2705     INT nIndex;
2706
2707     TRACE("\n");
2708
2709     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2710     if (nIndex == -1)
2711         return FALSE;
2712
2713     btnPtr = &infoPtr->buttons[nIndex];
2714     if (LOWORD(lParam) == FALSE)
2715         btnPtr->fsState &= ~TBSTATE_HIDDEN;
2716     else
2717         btnPtr->fsState |= TBSTATE_HIDDEN;
2718
2719     InvalidateRect (hwnd, NULL, TRUE);
2720
2721     return TRUE;
2722 }
2723
2724
2725 inline static LRESULT
2726 TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2727 {
2728     return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
2729 }
2730
2731
2732 static LRESULT
2733 TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2734 {
2735     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2736     TBUTTON_INFO *btnPtr;
2737     INT nIndex;
2738
2739     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2740     if (nIndex == -1)
2741         return FALSE;
2742
2743     btnPtr = &infoPtr->buttons[nIndex];
2744     if (LOWORD(lParam) == FALSE)
2745         btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
2746     else
2747         btnPtr->fsState |= TBSTATE_INDETERMINATE;
2748
2749     InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
2750
2751     return TRUE;
2752 }
2753
2754
2755 static LRESULT
2756 TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2757 {
2758     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2759     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2760     INT nIndex = (INT)wParam;
2761     TBUTTON_INFO *oldButtons;
2762
2763     if (lpTbb == NULL)
2764         return FALSE;
2765
2766     if (nIndex == -1) {
2767        /* EPP: this seems to be an undocumented call (from my IE4)
2768         * I assume in that case that:
2769         * - lpTbb->iString is a string pointer (not a string index in strings[] table
2770         * - index of insertion is at the end of existing buttons
2771         * I only see this happen with nIndex == -1, but it could have a special
2772         * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
2773         */
2774        int      len;
2775        LPSTR    ptr;
2776
2777        if(lpTbb->iString) {
2778            len = strlen((char*)lpTbb->iString) + 2;
2779            ptr = COMCTL32_Alloc(len);
2780            nIndex = infoPtr->nNumButtons;
2781            strcpy(ptr, (char*)lpTbb->iString);
2782            ptr[len - 1] = 0; /* ended by two '\0' */
2783            lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
2784            COMCTL32_Free(ptr);
2785        }
2786        else {
2787            ERR("lpTbb->iString is NULL\n");
2788            return FALSE;
2789        }
2790
2791     } else if (nIndex < 0)
2792        return FALSE;
2793
2794     TRACE("inserting button index=%d\n", nIndex);
2795     if (nIndex > infoPtr->nNumButtons) {
2796         nIndex = infoPtr->nNumButtons;
2797         TRACE("adjust index=%d\n", nIndex);
2798     }
2799
2800     oldButtons = infoPtr->buttons;
2801     infoPtr->nNumButtons++;
2802     infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2803     /* pre insert copy */
2804     if (nIndex > 0) {
2805         memcpy (&infoPtr->buttons[0], &oldButtons[0],
2806                 nIndex * sizeof(TBUTTON_INFO));
2807     }
2808
2809     /* insert new button */
2810     infoPtr->buttons[nIndex].iBitmap   = lpTbb->iBitmap;
2811     infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2812     infoPtr->buttons[nIndex].fsState   = lpTbb->fsState;
2813     infoPtr->buttons[nIndex].fsStyle   = lpTbb->fsStyle;
2814     infoPtr->buttons[nIndex].dwData    = lpTbb->dwData;
2815     infoPtr->buttons[nIndex].iString   = lpTbb->iString;
2816
2817     if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2818         TTTOOLINFOA ti;
2819
2820         ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2821         ti.cbSize   = sizeof (TTTOOLINFOA);
2822         ti.hwnd     = hwnd;
2823         ti.uId      = lpTbb->idCommand;
2824         ti.hinst    = 0;
2825         ti.lpszText = LPSTR_TEXTCALLBACKA;
2826
2827         SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
2828                         0, (LPARAM)&ti);
2829     }
2830
2831     /* post insert copy */
2832     if (nIndex < infoPtr->nNumButtons - 1) {
2833         memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2834                 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2835     }
2836
2837     COMCTL32_Free (oldButtons);
2838
2839     InvalidateRect (hwnd, NULL, FALSE);
2840
2841     return TRUE;
2842 }
2843
2844
2845 static LRESULT
2846 TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2847 {
2848     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2849     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2850     INT nIndex = (INT)wParam;
2851     TBUTTON_INFO *oldButtons;
2852
2853     if (lpTbb == NULL)
2854         return FALSE;
2855     if (nIndex < 0)
2856         return FALSE;
2857
2858     TRACE("inserting button index=%d\n", nIndex);
2859     if (nIndex > infoPtr->nNumButtons) {
2860         nIndex = infoPtr->nNumButtons;
2861         TRACE("adjust index=%d\n", nIndex);
2862     }
2863
2864     oldButtons = infoPtr->buttons;
2865     infoPtr->nNumButtons++;
2866     infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2867     /* pre insert copy */
2868     if (nIndex > 0) {
2869         memcpy (&infoPtr->buttons[0], &oldButtons[0],
2870                 nIndex * sizeof(TBUTTON_INFO));
2871     }
2872
2873     /* insert new button */
2874     infoPtr->buttons[nIndex].iBitmap   = lpTbb->iBitmap;
2875     infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
2876     infoPtr->buttons[nIndex].fsState   = lpTbb->fsState;
2877     infoPtr->buttons[nIndex].fsStyle   = lpTbb->fsStyle;
2878     infoPtr->buttons[nIndex].dwData    = lpTbb->dwData;
2879     infoPtr->buttons[nIndex].iString   = lpTbb->iString;
2880
2881     if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2882         TTTOOLINFOW ti;
2883
2884         ZeroMemory (&ti, sizeof(TTTOOLINFOW));
2885         ti.cbSize   = sizeof (TTTOOLINFOW);
2886         ti.hwnd     = hwnd;
2887         ti.uId      = lpTbb->idCommand;
2888         ti.hinst    = 0;
2889         ti.lpszText = LPSTR_TEXTCALLBACKW;
2890
2891         SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
2892                         0, (LPARAM)&ti);
2893     }
2894
2895     /* post insert copy */
2896     if (nIndex < infoPtr->nNumButtons - 1) {
2897         memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
2898                 (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
2899     }
2900
2901     COMCTL32_Free (oldButtons);
2902
2903     InvalidateRect (hwnd, NULL, FALSE);
2904
2905     return TRUE;
2906 }
2907
2908
2909 /* << TOOLBAR_InsertMarkHitTest >> */
2910
2911
2912 static LRESULT
2913 TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
2914 {
2915     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2916     INT nIndex;
2917
2918     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2919     if (nIndex == -1)
2920         return FALSE;
2921
2922     return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
2923 }
2924
2925
2926 static LRESULT
2927 TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
2928 {
2929     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2930     INT nIndex;
2931
2932     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2933     if (nIndex == -1)
2934         return FALSE;
2935
2936     return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
2937 }
2938
2939
2940 static LRESULT
2941 TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
2942 {
2943     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2944     INT nIndex;
2945
2946     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2947     if (nIndex == -1)
2948         return TRUE;
2949
2950     return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
2951 }
2952
2953
2954 static LRESULT
2955 TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
2956 {
2957     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2958     INT nIndex;
2959
2960     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2961     if (nIndex == -1)
2962         return FALSE;
2963
2964     return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
2965 }
2966
2967
2968 static LRESULT
2969 TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2970 {
2971     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2972     INT nIndex;
2973
2974     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2975     if (nIndex == -1)
2976         return FALSE;
2977
2978     return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
2979 }
2980
2981
2982 static LRESULT
2983 TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
2984 {
2985     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2986     INT nIndex;
2987
2988     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2989     if (nIndex == -1)
2990         return FALSE;
2991
2992     return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
2993 }
2994
2995
2996 /* << TOOLBAR_LoadImages >> */
2997 /* << TOOLBAR_MapAccelerator >> */
2998 /* << TOOLBAR_MarkButton >> */
2999 /* << TOOLBAR_MoveButton >> */
3000
3001
3002 static LRESULT
3003 TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
3004 {
3005     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3006     TBUTTON_INFO *btnPtr;
3007     INT nIndex;
3008
3009     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3010     if (nIndex == -1)
3011         return FALSE;
3012
3013     btnPtr = &infoPtr->buttons[nIndex];
3014     if (LOWORD(lParam) == FALSE)
3015         btnPtr->fsState &= ~TBSTATE_PRESSED;
3016     else
3017         btnPtr->fsState |= TBSTATE_PRESSED;
3018
3019     InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
3020
3021     return TRUE;
3022 }
3023
3024
3025 /* << TOOLBAR_ReplaceBitmap >> */
3026
3027
3028 static LRESULT
3029 TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3030 {
3031 #if 0
3032     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3033     LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
3034
3035     if (lpSave == NULL) return 0;
3036
3037     if ((BOOL)wParam) {
3038         /* save toolbar information */
3039         FIXME("save to \"%s\" \"%s\"\n",
3040                lpSave->pszSubKey, lpSave->pszValueName);
3041
3042
3043     }
3044     else {
3045         /* restore toolbar information */
3046
3047         FIXME("restore from \"%s\" \"%s\"\n",
3048                lpSave->pszSubKey, lpSave->pszValueName);
3049
3050
3051     }
3052 #endif
3053
3054     return 0;
3055 }
3056
3057
3058 static LRESULT
3059 TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3060 {
3061 #if 0
3062     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3063     LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;
3064
3065     if (lpSave == NULL)
3066         return 0;
3067
3068     if ((BOOL)wParam) {
3069         /* save toolbar information */
3070         FIXME("save to \"%s\" \"%s\"\n",
3071                lpSave->pszSubKey, lpSave->pszValueName);
3072
3073
3074     }
3075     else {
3076         /* restore toolbar information */
3077
3078         FIXME("restore from \"%s\" \"%s\"\n",
3079                lpSave->pszSubKey, lpSave->pszValueName);
3080
3081
3082     }
3083 #endif
3084
3085     return 0;
3086 }
3087
3088
3089 static LRESULT
3090 TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
3091 {
3092     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3093     BOOL bOldAnchor = infoPtr->bAnchor;
3094
3095     infoPtr->bAnchor = (BOOL)wParam;
3096
3097     return (LRESULT)bOldAnchor;
3098 }
3099
3100
3101 static LRESULT
3102 TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3103 {
3104     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3105
3106     if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3107         return FALSE;
3108
3109     if (infoPtr->nNumButtons > 0)
3110         WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
3111              infoPtr->nNumButtons,
3112              infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
3113              LOWORD(lParam), HIWORD(lParam));
3114
3115     infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
3116     infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
3117
3118     /* uses image list internals directly */
3119     if (infoPtr->himlDef) {
3120         infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
3121         infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
3122     }
3123
3124     return TRUE;
3125 }
3126
3127
3128 static LRESULT
3129 TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
3130 {
3131     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3132     LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
3133     TBUTTON_INFO *btnPtr;
3134     INT nIndex;
3135
3136     if (lptbbi == NULL)
3137         return FALSE;
3138     if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
3139         return FALSE;
3140     
3141     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3142     if (nIndex == -1)
3143         return FALSE;
3144
3145     btnPtr = &infoPtr->buttons[nIndex];
3146     if (lptbbi->dwMask & TBIF_COMMAND)
3147         btnPtr->idCommand = lptbbi->idCommand;
3148     if (lptbbi->dwMask & TBIF_IMAGE)
3149         btnPtr->iBitmap = lptbbi->iImage;
3150     if (lptbbi->dwMask & TBIF_LPARAM)
3151         btnPtr->dwData = lptbbi->lParam;
3152 /*    if (lptbbi->dwMask & TBIF_SIZE) */
3153 /*      btnPtr->cx = lptbbi->cx; */
3154     if (lptbbi->dwMask & TBIF_STATE)
3155         btnPtr->fsState = lptbbi->fsState;
3156     if (lptbbi->dwMask & TBIF_STYLE)
3157         btnPtr->fsStyle = lptbbi->fsStyle;
3158
3159     if (lptbbi->dwMask & TBIF_TEXT) {
3160         if ((btnPtr->iString >= 0) || 
3161             (btnPtr->iString < infoPtr->nNumStrings)) {
3162            TRACE("Ooooooch\n");
3163 #if 0
3164             WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
3165             INT len = lstrlenA (lptbbi->pszText);
3166             *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
3167 #endif
3168
3169             /* this is the ultimate sollution */
3170 /*          Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
3171         }
3172     }
3173
3174     return TRUE;
3175 }
3176
3177
3178 static LRESULT
3179 TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
3180 {
3181     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3182     LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
3183     TBUTTON_INFO *btnPtr;
3184     INT nIndex;
3185
3186     if (lptbbi == NULL)
3187         return FALSE;
3188     if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
3189         return FALSE;
3190
3191     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3192     if (nIndex == -1)
3193         return FALSE;
3194
3195     btnPtr = &infoPtr->buttons[nIndex];
3196     if (lptbbi->dwMask & TBIF_COMMAND)
3197         btnPtr->idCommand = lptbbi->idCommand;
3198     if (lptbbi->dwMask & TBIF_IMAGE)
3199         btnPtr->iBitmap = lptbbi->iImage;
3200     if (lptbbi->dwMask & TBIF_LPARAM)
3201         btnPtr->dwData = lptbbi->lParam;
3202 /*    if (lptbbi->dwMask & TBIF_SIZE) */
3203 /*      btnPtr->cx = lptbbi->cx; */
3204     if (lptbbi->dwMask & TBIF_STATE)
3205         btnPtr->fsState = lptbbi->fsState;
3206     if (lptbbi->dwMask & TBIF_STYLE)
3207         btnPtr->fsStyle = lptbbi->fsStyle;
3208
3209     if (lptbbi->dwMask & TBIF_TEXT) {
3210         if ((btnPtr->iString >= 0) ||
3211             (btnPtr->iString < infoPtr->nNumStrings)) {
3212 #if 0
3213             WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
3214             INT len = lstrlenW (lptbbi->pszText);
3215             *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
3216 #endif
3217
3218             /* this is the ultimate solution */
3219 /*          Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
3220         }
3221     }
3222
3223     return TRUE;
3224 }
3225
3226
3227 static LRESULT
3228 TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
3229 {
3230     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3231
3232     if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3233     {
3234         ERR("invalid parameter\n");
3235         return FALSE;
3236     }
3237
3238     /* Button size can only be set before adding any button to the toolbar
3239        according to the documentation.  */
3240     /* this appears to be wrong. WINZIP32.EXE (ver 8) calls this on
3241        one of its buttons after adding it to the toolbar, and it
3242        checks that the return value is nonzero - mjm */
3243     if( infoPtr->nNumButtons != 0 )
3244     {
3245         WARN("Button size set after button in toolbar\n");
3246         return TRUE;
3247     }
3248
3249     infoPtr->nButtonWidth = (INT)LOWORD(lParam);
3250     infoPtr->nButtonHeight = (INT)HIWORD(lParam);
3251     return TRUE;
3252 }
3253
3254
3255 static LRESULT
3256 TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
3257 {
3258     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3259
3260     if (infoPtr == NULL)
3261         return FALSE;
3262
3263     infoPtr->cxMin = (INT)LOWORD(lParam);
3264     infoPtr->cxMax = (INT)HIWORD(lParam);
3265
3266     return TRUE;
3267 }
3268
3269
3270 static LRESULT
3271 TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
3272 {
3273     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3274     INT nIndex = (INT)wParam;
3275
3276     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
3277         return FALSE;
3278
3279     infoPtr->buttons[nIndex].idCommand = (INT)lParam;
3280
3281     if (infoPtr->hwndToolTip) {
3282
3283         FIXME("change tool tip!\n");
3284
3285     }
3286
3287     return TRUE;
3288 }
3289
3290
3291 /* << TOOLBAR_SetColorScheme >> */
3292
3293
3294 static LRESULT
3295 TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3296 {
3297     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3298     HIMAGELIST himlTemp;
3299
3300
3301     himlTemp = infoPtr->himlDis;
3302     infoPtr->himlDis = (HIMAGELIST)lParam;
3303
3304     /* FIXME: redraw ? */
3305
3306     return (LRESULT)himlTemp; 
3307 }
3308
3309
3310 static LRESULT
3311 TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
3312 {
3313     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3314     DWORD dwTemp;
3315
3316     dwTemp = infoPtr->dwDTFlags;
3317     infoPtr->dwDTFlags =
3318         (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
3319
3320     return (LRESULT)dwTemp;
3321 }
3322
3323
3324 static LRESULT
3325 TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3326 {
3327     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3328     DWORD dwTemp;
3329
3330     dwTemp = infoPtr->dwExStyle;
3331     infoPtr->dwExStyle = (DWORD)lParam;
3332
3333     return (LRESULT)dwTemp; 
3334 }
3335
3336
3337 static LRESULT
3338 TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3339 {
3340     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3341     HIMAGELIST himlTemp;
3342
3343     himlTemp = infoPtr->himlHot;
3344     infoPtr->himlHot = (HIMAGELIST)lParam;
3345
3346     /* FIXME: redraw ? */
3347
3348     return (LRESULT)himlTemp; 
3349 }
3350
3351
3352 static LRESULT
3353 TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
3354 {
3355     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
3356     INT nOldHotItem = infoPtr->nHotItem;
3357
3358     if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
3359     {
3360         infoPtr->nHotItem = (INT)wParam;
3361
3362         /* FIXME: What else must be done ??? */
3363
3364     }
3365
3366     if (nOldHotItem < 0)
3367         return -1;
3368
3369     return (LRESULT)nOldHotItem;
3370 }
3371
3372
3373 static LRESULT
3374 TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
3375 {
3376     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3377     HIMAGELIST himlTemp;
3378
3379     himlTemp = infoPtr->himlDef;
3380     infoPtr->himlDef = (HIMAGELIST)lParam;
3381
3382      infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
3383     /* FIXME: redraw ? */
3384
3385     return (LRESULT)himlTemp; 
3386 }
3387
3388
3389 static LRESULT
3390 TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3391 {
3392     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3393
3394     infoPtr->nIndent = (INT)wParam;
3395
3396     TRACE("\n");
3397
3398     /* process only on indent changing */
3399     if(infoPtr->nIndent != (INT)wParam)
3400     {
3401         infoPtr->nIndent = (INT)wParam;
3402         InvalidateRect(hwnd, NULL, FALSE);
3403     }
3404
3405     return TRUE;
3406 }
3407
3408
3409 /* << TOOLBAR_SetInsertMark >> */
3410
3411
3412 static LRESULT
3413 TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
3414 {
3415     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3416
3417     infoPtr->clrInsertMark = (COLORREF)lParam;
3418
3419     /* FIXME : redraw ??*/
3420
3421     return 0;
3422 }
3423
3424
3425 static LRESULT
3426 TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3427 {
3428     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3429
3430     if (infoPtr == NULL)
3431         return FALSE;
3432
3433     infoPtr->nMaxTextRows = (INT)wParam;
3434
3435     return TRUE;
3436 }
3437
3438
3439 /* << TOOLBAR_SetPadding >> */
3440
3441
3442 static LRESULT
3443 TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
3444 {
3445     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3446     HWND hwndOldNotify;
3447
3448     TRACE("\n");
3449
3450     if (infoPtr == NULL)
3451         return 0;
3452     hwndOldNotify = infoPtr->hwndNotify;
3453     infoPtr->hwndNotify = (HWND)wParam;
3454
3455     return hwndOldNotify;
3456 }
3457
3458
3459 static LRESULT
3460 TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
3461 {
3462     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3463     LPRECT lprc = (LPRECT)lParam;
3464
3465     TRACE("\n");
3466
3467     if (LOWORD(wParam) > 1) {
3468         FIXME("multiple rows not supported!\n");
3469     }
3470
3471     if(infoPtr->nRows != LOWORD(wParam))
3472     {
3473         infoPtr->nRows = LOWORD(wParam);
3474
3475         /* repaint toolbar */
3476         InvalidateRect(hwnd, NULL, FALSE);
3477     }
3478
3479     /* return bounding rectangle */
3480     if (lprc) {
3481         lprc->left   = infoPtr->rcBound.left;
3482         lprc->right  = infoPtr->rcBound.right;
3483         lprc->top    = infoPtr->rcBound.top;
3484         lprc->bottom = infoPtr->rcBound.bottom;
3485     }
3486
3487     return 0;
3488 }
3489
3490
3491 static LRESULT
3492 TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
3493 {
3494     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3495     TBUTTON_INFO *btnPtr;
3496     INT nIndex;
3497
3498     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3499     if (nIndex == -1)
3500         return FALSE;
3501
3502     btnPtr = &infoPtr->buttons[nIndex];
3503
3504     /* process state changing if current state doesn't match new state */
3505     if(btnPtr->fsState != LOWORD(lParam))
3506     {
3507         btnPtr->fsState = LOWORD(lParam);
3508         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3509             btnPtr));
3510     }
3511
3512     return TRUE;
3513 }
3514
3515
3516 static LRESULT
3517 TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
3518 {
3519     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3520     TBUTTON_INFO *btnPtr;
3521     INT nIndex;
3522
3523     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
3524     if (nIndex == -1)
3525         return FALSE;
3526
3527     btnPtr = &infoPtr->buttons[nIndex];
3528
3529     /* process style change if current style doesn't match new style */
3530     if(btnPtr->fsStyle != LOWORD(lParam))
3531     {
3532         btnPtr->fsStyle = LOWORD(lParam);
3533         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3534             btnPtr));
3535
3536         if (infoPtr->hwndToolTip) {
3537             FIXME("change tool tip!\n");
3538         }
3539     }
3540
3541     return TRUE;
3542 }
3543
3544
3545 inline static LRESULT
3546 TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
3547 {
3548     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3549
3550     if (infoPtr == NULL)
3551         return 0;
3552     infoPtr->hwndToolTip = (HWND)wParam;
3553     return 0;
3554 }
3555
3556
3557 static LRESULT
3558 TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
3559 {
3560     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3561     BOOL bTemp;
3562
3563     TRACE("%s hwnd=0x%04x stub!\n", 
3564            ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
3565
3566     bTemp = infoPtr->bUnicode;
3567     infoPtr->bUnicode = (BOOL)wParam;
3568
3569     return bTemp;
3570 }
3571
3572
3573 static LRESULT
3574 TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
3575 {
3576     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3577     INT iOldVersion = infoPtr->iVersion;
3578
3579     infoPtr->iVersion = iVersion;
3580
3581     return iOldVersion;
3582 }
3583
3584
3585 static LRESULT
3586 TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
3587 {
3588     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3589     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3590     LOGFONTA logFont;
3591
3592     /* initialize info structure */
3593     infoPtr->nButtonHeight = 22;
3594     infoPtr->nButtonWidth = 24;
3595     infoPtr->nBitmapHeight = 15;
3596     infoPtr->nBitmapWidth = 16;
3597
3598     infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3599     infoPtr->nRows = 1;
3600     infoPtr->nMaxTextRows = 1;
3601     infoPtr->cxMin = -1;
3602     infoPtr->cxMax = -1;
3603     infoPtr->nNumBitmaps = 0;
3604     infoPtr->nNumStrings = 0;
3605
3606     infoPtr->bCaptured = FALSE;
3607     infoPtr->bUnicode = IsWindowUnicode (hwnd);
3608     infoPtr->nButtonDown = -1;
3609     infoPtr->nOldHit = -1;
3610     infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3611     infoPtr->hwndNotify = GetParent (hwnd);
3612     infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3613     infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3614     infoPtr->bAnchor = FALSE; /* no anchor highlighting */
3615     infoPtr->iVersion = 0;
3616
3617     SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
3618     infoPtr->hFont = CreateFontIndirectA (&logFont);
3619
3620     if (dwStyle & TBSTYLE_TOOLTIPS) {
3621         /* Create tooltip control */
3622         infoPtr->hwndToolTip =
3623             CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
3624                                CW_USEDEFAULT, CW_USEDEFAULT,
3625                                CW_USEDEFAULT, CW_USEDEFAULT,
3626                                hwnd, 0, 0, 0);
3627
3628         /* Send NM_TOOLTIPSCREATED notification */
3629         if (infoPtr->hwndToolTip) {
3630             NMTOOLTIPSCREATED nmttc;
3631
3632             nmttc.hdr.hwndFrom = hwnd;
3633             nmttc.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
3634             nmttc.hdr.code = NM_TOOLTIPSCREATED;
3635             nmttc.hwndToolTips = infoPtr->hwndToolTip;
3636
3637             SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3638                           (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
3639         }
3640     }
3641     return 0;
3642 }
3643
3644
3645 static LRESULT
3646 TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
3647 {
3648     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3649
3650     /* delete tooltip control */
3651     if (infoPtr->hwndToolTip)
3652         DestroyWindow (infoPtr->hwndToolTip);
3653
3654     /* delete button data */
3655     if (infoPtr->buttons)
3656         COMCTL32_Free (infoPtr->buttons);
3657
3658     /* delete strings */
3659     if (infoPtr->strings) {
3660         INT i;
3661         for (i = 0; i < infoPtr->nNumStrings; i++)
3662             if (infoPtr->strings[i])
3663                 COMCTL32_Free (infoPtr->strings[i]);
3664
3665         COMCTL32_Free (infoPtr->strings);
3666     }
3667
3668     /* destroy internal image list */
3669     if (infoPtr->himlInt)
3670         ImageList_Destroy (infoPtr->himlInt);
3671
3672     /* delete default font */
3673     if (infoPtr->hFont)
3674         DeleteObject (infoPtr->hFont);
3675
3676     /* free toolbar info data */
3677     COMCTL32_Free (infoPtr);
3678     SetWindowLongA (hwnd, 0, 0);
3679
3680     return 0;
3681 }
3682
3683
3684 static LRESULT
3685 TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
3686 {
3687     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3688
3689     if (infoPtr->bTransparent)
3690         return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
3691
3692     return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
3693 }
3694
3695
3696 static LRESULT
3697 TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3698 {
3699     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3700
3701     return infoPtr->hFont;
3702 }
3703
3704
3705 static LRESULT
3706 TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
3707 {
3708     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3709     TBUTTON_INFO *btnPtr;
3710     POINT pt;
3711     INT   nHit;
3712
3713     pt.x = (INT)LOWORD(lParam);
3714     pt.y = (INT)HIWORD(lParam);
3715     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3716
3717     if (nHit >= 0) {
3718         btnPtr = &infoPtr->buttons[nHit];
3719         if (!(btnPtr->fsState & TBSTATE_ENABLED))
3720             return 0;
3721         SetCapture (hwnd);
3722         infoPtr->bCaptured = TRUE;
3723         infoPtr->nButtonDown = nHit;
3724
3725         btnPtr->fsState |= TBSTATE_PRESSED;
3726
3727         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3728             btnPtr));
3729     }
3730     else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
3731         TOOLBAR_Customize (hwnd);
3732
3733     return 0;
3734 }
3735
3736
3737 static LRESULT
3738 TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3739 {
3740     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3741     TBUTTON_INFO *btnPtr;
3742     POINT pt;
3743     INT   nHit;
3744
3745     if (infoPtr->hwndToolTip)
3746         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3747                             WM_LBUTTONDOWN, wParam, lParam);
3748
3749     pt.x = (INT)LOWORD(lParam);
3750     pt.y = (INT)HIWORD(lParam);
3751     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3752
3753     if (nHit >= 0) {
3754         RECT arrowRect;
3755         btnPtr = &infoPtr->buttons[nHit];
3756         if (!(btnPtr->fsState & TBSTATE_ENABLED))
3757             return 0;
3758
3759         SetCapture (hwnd);
3760         infoPtr->bCaptured = TRUE;
3761         infoPtr->nButtonDown = nHit;
3762         infoPtr->nOldHit = nHit;
3763
3764         btnPtr->fsState |= TBSTATE_PRESSED;
3765         btnPtr->bHot = FALSE;
3766
3767         CopyRect(&arrowRect, &btnPtr->rect);
3768         arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
3769         
3770         /* for EX_DRAWDDARROWS style,  click must be in the drop-down arrow rect */
3771         if ((btnPtr->fsStyle & TBSTYLE_DROPDOWN) &&
3772              !(TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && !PtInRect(&arrowRect, pt))) 
3773         {
3774             NMTOOLBARA nmtb;
3775             /* 
3776              * this time we must force a Redraw, so the btn is
3777              * painted down before CaptureChanged repaints it up
3778              */
3779             RedrawWindow(hwnd,&btnPtr->rect,0,
3780                         RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3781
3782             nmtb.hdr.hwndFrom = hwnd;
3783             nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
3784             nmtb.hdr.code = TBN_DROPDOWN;
3785             nmtb.iItem = btnPtr->idCommand;
3786
3787             SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3788                           (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
3789         }
3790         else
3791         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3792             btnPtr));
3793     }
3794
3795     return 0;
3796 }
3797
3798 static LRESULT
3799 TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3800 {
3801     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3802     TBUTTON_INFO *btnPtr;
3803     POINT pt;
3804     INT   nHit;
3805     INT   nOldIndex = -1;
3806     BOOL  bSendMessage = TRUE;
3807
3808     if (infoPtr->hwndToolTip)
3809         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3810                             WM_LBUTTONUP, wParam, lParam);
3811
3812     pt.x = (INT)LOWORD(lParam);
3813     pt.y = (INT)HIWORD(lParam);
3814     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3815
3816     /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3817     /* if the cursor is still inside of the toolbar */
3818     if((infoPtr->nHotItem >= 0) && (nHit != -1))
3819         infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;
3820
3821     if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
3822         btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3823         btnPtr->fsState &= ~TBSTATE_PRESSED;
3824
3825         if (nHit == infoPtr->nButtonDown) {
3826             if (btnPtr->fsStyle & TBSTYLE_CHECK) {
3827                 if (btnPtr->fsStyle & TBSTYLE_GROUP) {
3828                     nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
3829                         infoPtr->nButtonDown);
3830                     if (nOldIndex == infoPtr->nButtonDown)
3831                         bSendMessage = FALSE;
3832                     if ((nOldIndex != infoPtr->nButtonDown) && 
3833                         (nOldIndex != -1))
3834                         infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
3835                     btnPtr->fsState |= TBSTATE_CHECKED;
3836                 }
3837                 else {
3838                     if (btnPtr->fsState & TBSTATE_CHECKED)
3839                         btnPtr->fsState &= ~TBSTATE_CHECKED;
3840                     else
3841                         btnPtr->fsState |= TBSTATE_CHECKED;
3842                 }
3843             }
3844         }
3845         else
3846             bSendMessage = FALSE;
3847
3848         if (nOldIndex != -1)
3849         {
3850             InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
3851                 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
3852         }
3853
3854         /*
3855          * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
3856          * that resets bCaptured and btn TBSTATE_PRESSED flags,
3857          * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged) 
3858          */
3859         ReleaseCapture ();
3860
3861         if (bSendMessage)
3862             SendMessageA (GetParent(hwnd), WM_COMMAND,
3863                           MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
3864     }
3865
3866     return 0;
3867 }
3868
3869 static LRESULT
3870 TOOLBAR_CaptureChanged(HWND hwnd)
3871 {
3872     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3873     TBUTTON_INFO *btnPtr;
3874
3875     infoPtr->bCaptured = FALSE;
3876
3877     if (infoPtr->nButtonDown >= 0)
3878     {
3879         btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3880         btnPtr->fsState &= ~TBSTATE_PRESSED;
3881
3882         infoPtr->nButtonDown = -1;
3883         infoPtr->nOldHit = -1;
3884
3885         InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
3886             btnPtr));
3887     }
3888     return 0;
3889 }
3890
3891 static LRESULT
3892 TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
3893 {
3894     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3895     TBUTTON_INFO *hotBtnPtr, *btnPtr;
3896
3897     if (infoPtr->nOldHit < 0)
3898       return TRUE;
3899
3900     hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3901
3902     /* Redraw the button if the last button we were over is the hot button and it
3903        is enabled */
3904     if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
3905     {
3906         hotBtnPtr->bHot = FALSE;
3907
3908         InvalidateRect (hwnd, &hotBtnPtr->rect, TOOLBAR_HasText(infoPtr,
3909             hotBtnPtr));
3910     }
3911
3912     /* If the last button we were over is depressed then make it not */
3913     /* depressed and redraw it */
3914     if(infoPtr->nOldHit == infoPtr->nButtonDown)
3915     {
3916       btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3917
3918       btnPtr->fsState &= ~TBSTATE_PRESSED;
3919
3920       InvalidateRect (hwnd, &(btnPtr->rect), TRUE);
3921     }
3922
3923     infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
3924     infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3925
3926     return TRUE;
3927 }
3928
3929 static LRESULT
3930 TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3931 {
3932     TBUTTON_INFO *btnPtr, *oldBtnPtr;
3933     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3934     POINT pt;
3935     INT   nHit;
3936     TRACKMOUSEEVENT trackinfo;
3937
3938     /* fill in the TRACKMOUSEEVENT struct */
3939     trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
3940     trackinfo.dwFlags = TME_QUERY;
3941     trackinfo.hwndTrack = hwnd;
3942     trackinfo.dwHoverTime = HOVER_DEFAULT;
3943
3944     /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
3945     _TrackMouseEvent(&trackinfo);
3946
3947     /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
3948     if(!(trackinfo.dwFlags & TME_LEAVE)) {
3949         trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3950  
3951         /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
3952         /* and can properly deactivate the hot toolbar button */
3953         _TrackMouseEvent(&trackinfo);
3954    }
3955
3956     if (infoPtr->hwndToolTip)
3957         TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
3958                             WM_MOUSEMOVE, wParam, lParam);
3959
3960     pt.x = (INT)LOWORD(lParam);
3961     pt.y = (INT)HIWORD(lParam);
3962
3963     nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
3964
3965     if (infoPtr->nOldHit != nHit)
3966     {
3967         /* Remove the effect of an old hot button if the button was enabled and was
3968            drawn with the hot button effect */
3969         if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem && 
3970                 (infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
3971         {
3972             oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
3973             oldBtnPtr->bHot = FALSE;
3974                     
3975             InvalidateRect (hwnd, &oldBtnPtr->rect,
3976                 TOOLBAR_HasText(infoPtr, oldBtnPtr));
3977         }
3978
3979         /* It's not a separator or in nowhere. It's a hot button. */
3980         if (nHit >= 0)
3981         {
3982             btnPtr = &infoPtr->buttons[nHit];
3983             btnPtr->bHot = TRUE;
3984
3985             infoPtr->nHotItem = nHit;
3986
3987             /* only enabled buttons show hot effect */            
3988             if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
3989             {
3990                 InvalidateRect(hwnd, &btnPtr->rect,
3991                     TOOLBAR_HasText(infoPtr, btnPtr));
3992             }
3993
3994         }
3995
3996     if (infoPtr->bCaptured) {
3997             btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
3998             if (infoPtr->nOldHit == infoPtr->nButtonDown) {
3999                 btnPtr->fsState &= ~TBSTATE_PRESSED;
4000                 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
4001             }
4002             else if (nHit == infoPtr->nButtonDown) {
4003                 btnPtr->fsState |= TBSTATE_PRESSED;
4004                 InvalidateRect(hwnd, &btnPtr->rect, TRUE);
4005             }
4006         }
4007         infoPtr->nOldHit = nHit;
4008     }
4009     return 0;
4010 }
4011
4012
4013 inline static LRESULT
4014 TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4015 {
4016 /*    if (wndPtr->dwStyle & CCS_NODIVIDER) */
4017         return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
4018 /*    else */
4019 /*      return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
4020 }
4021
4022
4023 inline static LRESULT
4024 TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
4025 {
4026     if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
4027         ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
4028
4029     return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
4030 }
4031
4032
4033 static LRESULT
4034 TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
4035 {
4036     TOOLBAR_INFO *infoPtr;
4037
4038     /* allocate memory for info structure */
4039     infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
4040     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
4041
4042     /* paranoid!! */
4043     infoPtr->dwStructSize = sizeof(TBBUTTON);
4044
4045     /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
4046     if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
4047         HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
4048         SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
4049     }
4050
4051     return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
4052 }
4053
4054
4055 static LRESULT
4056 TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
4057 {
4058     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4059     RECT rcWindow;
4060     HDC hdc;
4061
4062     if (dwStyle & WS_MINIMIZE)
4063         return 0; /* Nothing to do */
4064
4065     DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
4066
4067     if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
4068         return 0;
4069
4070     if (!(dwStyle & CCS_NODIVIDER))
4071     {
4072         GetWindowRect (hwnd, &rcWindow);
4073         OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
4074         if( dwStyle & WS_BORDER )
4075             OffsetRect (&rcWindow, 1, 1);
4076         DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
4077     }
4078
4079     ReleaseDC( hwnd, hdc );
4080
4081     return 0;
4082 }
4083
4084
4085 inline static LRESULT
4086 TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
4087 {
4088     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4089     LPNMHDR lpnmh = (LPNMHDR)lParam;
4090
4091     TRACE("passing WM_NOTIFY!\n");
4092
4093     if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
4094         SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,   wParam, lParam);
4095
4096 #if 0
4097         if (lpnmh->code == TTN_GETDISPINFOA) {
4098             LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
4099
4100             FIXME("retrieving ASCII string\n");
4101
4102         }
4103         else if (lpnmh->code == TTN_GETDISPINFOW) {
4104             LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
4105
4106             FIXME("retrieving UNICODE string\n");
4107
4108         }
4109 #endif
4110     }
4111
4112     return 0;
4113 }
4114
4115
4116 static LRESULT
4117 TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
4118 {
4119     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
4120     HDC hdc;
4121     PAINTSTRUCT ps;
4122
4123     TRACE("\n");
4124
4125     TOOLBAR_CalcToolbar( hwnd );
4126
4127     /* fill ps.rcPaint with a default rect */
4128     memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound)); 
4129
4130     hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
4131     TOOLBAR_Refresh (hwnd, hdc, &ps);
4132     if (!wParam) EndPaint (hwnd, &ps);
4133
4134     return 0;
4135 }
4136
4137
4138 static LRESULT
4139 TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
4140 {
4141     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4142     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4143     RECT parent_rect;
4144     RECT window_rect;
4145     HWND parent;
4146     INT  x, y;
4147     INT  cx, cy;
4148     INT  flags;
4149     UINT uPosFlags = 0;
4150
4151     /* Resize deadlock check */
4152     if (infoPtr->bAutoSize) {
4153         infoPtr->bAutoSize = FALSE;
4154         return 0;
4155     }
4156
4157     /* FIXME: optimize to only update size if the new size doesn't */
4158     /* match the current size */
4159
4160     flags = (INT) wParam;
4161
4162     /* FIXME for flags =
4163      * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
4164      */
4165
4166     TRACE("sizing toolbar!\n");
4167
4168     if (flags == SIZE_RESTORED) {
4169         /* width and height don't apply */
4170         parent = GetParent (hwnd);
4171         GetClientRect(parent, &parent_rect);
4172         x = parent_rect.left;
4173         y = parent_rect.top;
4174
4175         if (dwStyle & CCS_NORESIZE) {
4176             uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
4177
4178             /*
4179              * this sets the working width of the toolbar, and
4180              * Calc Toolbar will not adjust it, only the height
4181              */
4182             infoPtr->nWidth = parent_rect.right - parent_rect.left; 
4183             cy = infoPtr->nHeight;
4184             cx = infoPtr->nWidth;
4185             TOOLBAR_CalcToolbar (hwnd);
4186             infoPtr->nWidth = cx;
4187             infoPtr->nHeight = cy;
4188         }
4189         else {
4190             infoPtr->nWidth = parent_rect.right - parent_rect.left;
4191             TOOLBAR_CalcToolbar (hwnd);
4192             cy = infoPtr->nHeight;
4193             cx = infoPtr->nWidth;
4194
4195             if (dwStyle & CCS_NOMOVEY) {
4196                 GetWindowRect(hwnd, &window_rect);
4197                 ScreenToClient(parent, (LPPOINT)&window_rect.left);
4198                 y = window_rect.top;
4199             }
4200         }
4201
4202         if (dwStyle & CCS_NOPARENTALIGN) {
4203             uPosFlags |= SWP_NOMOVE;
4204             cy = infoPtr->nHeight;
4205             cx = infoPtr->nWidth;
4206         }
4207
4208         if (!(dwStyle & CCS_NODIVIDER))
4209             cy += GetSystemMetrics(SM_CYEDGE);
4210
4211         if (dwStyle & WS_BORDER)
4212         {
4213             x = y = 1;
4214             cy += GetSystemMetrics(SM_CYEDGE);
4215             cx += GetSystemMetrics(SM_CYEDGE);
4216         }
4217
4218         SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
4219                         cx, cy, uPosFlags | SWP_NOZORDER);
4220     }
4221     return 0;
4222 }
4223
4224
4225 static LRESULT
4226 TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
4227 {
4228     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
4229
4230     if (nType == GWL_STYLE) {
4231         if (lpStyle->styleNew & TBSTYLE_LIST) {
4232             infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
4233         }
4234         else {
4235             infoPtr->dwDTFlags = DT_CENTER;
4236         }
4237     }
4238
4239     TOOLBAR_AutoSize (hwnd);
4240
4241     InvalidateRect(hwnd, NULL, FALSE);
4242
4243     return 0;
4244 }
4245
4246
4247
4248 static LRESULT WINAPI
4249 ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4250 {
4251
4252     switch (uMsg)
4253     {
4254        case WM_DESTROY:
4255            return TOOLBAR_Destroy (hwnd, wParam, lParam);
4256
4257        case WM_NCCREATE:
4258            return TOOLBAR_NCCreate (hwnd, wParam, lParam);
4259     }
4260
4261     if (!TOOLBAR_GetInfoPtr (hwnd))
4262     {
4263        return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4264     }
4265
4266     switch (uMsg)
4267     {
4268         case TB_ADDBITMAP:
4269             return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
4270
4271         case TB_ADDBUTTONSA:
4272             return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
4273
4274         case TB_ADDBUTTONSW:
4275             return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
4276
4277         case TB_ADDSTRINGA:
4278             return TOOLBAR_AddStringA (hwnd, wParam, lParam);
4279
4280         case TB_ADDSTRINGW:
4281             return TOOLBAR_AddStringW (hwnd, wParam, lParam);
4282
4283         case TB_AUTOSIZE:
4284             return TOOLBAR_AutoSize (hwnd);
4285
4286         case TB_BUTTONCOUNT:
4287             return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
4288
4289         case TB_BUTTONSTRUCTSIZE:
4290             return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
4291
4292         case TB_CHANGEBITMAP:
4293             return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
4294
4295         case TB_CHECKBUTTON:
4296             return TOOLBAR_CheckButton (hwnd, wParam, lParam);
4297
4298         case TB_COMMANDTOINDEX:
4299             return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
4300
4301         case TB_CUSTOMIZE:
4302             return TOOLBAR_Customize (hwnd);
4303
4304         case TB_DELETEBUTTON:
4305             return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
4306
4307         case TB_ENABLEBUTTON:
4308             return TOOLBAR_EnableButton (hwnd, wParam, lParam);
4309
4310         case TB_GETANCHORHIGHLIGHT:
4311             return TOOLBAR_GetAnchorHighlight (hwnd);
4312
4313         case TB_GETBITMAP:
4314             return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
4315
4316         case TB_GETBITMAPFLAGS:
4317             return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
4318
4319         case TB_GETBUTTON:
4320             return TOOLBAR_GetButton (hwnd, wParam, lParam);
4321
4322         case TB_GETBUTTONINFOA:
4323             return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
4324
4325         case TB_GETBUTTONINFOW:
4326             return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
4327
4328         case TB_GETBUTTONSIZE:
4329             return TOOLBAR_GetButtonSize (hwnd);
4330
4331         case TB_GETBUTTONTEXTA:
4332             return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
4333
4334         case TB_GETBUTTONTEXTW:
4335             return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);
4336
4337 /*      case TB_GETCOLORSCHEME:                 */ /* 4.71 */
4338
4339         case TB_GETDISABLEDIMAGELIST:
4340             return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
4341
4342         case TB_GETEXTENDEDSTYLE:
4343             return TOOLBAR_GetExtendedStyle (hwnd);
4344
4345         case TB_GETHOTIMAGELIST:
4346             return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
4347
4348         case TB_GETHOTITEM:
4349             return TOOLBAR_GetHotItem (hwnd);
4350
4351         case TB_GETIMAGELIST:
4352             return TOOLBAR_GetImageList (hwnd, wParam, lParam);
4353
4354 /*      case TB_GETINSERTMARK:                  */ /* 4.71 */
4355 /*      case TB_GETINSERTMARKCOLOR:             */ /* 4.71 */
4356
4357         case TB_GETITEMRECT:
4358             return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
4359
4360         case TB_GETMAXSIZE:
4361             return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
4362
4363 /*      case TB_GETOBJECT:                      */ /* 4.71 */
4364 /*      case TB_GETPADDING:                     */ /* 4.71 */
4365
4366         case TB_GETRECT:
4367             return TOOLBAR_GetRect (hwnd, wParam, lParam);
4368
4369         case TB_GETROWS:
4370             return TOOLBAR_GetRows (hwnd, wParam, lParam);
4371
4372         case TB_GETSTATE:
4373             return TOOLBAR_GetState (hwnd, wParam, lParam);
4374
4375         case TB_GETSTYLE:
4376             return TOOLBAR_GetStyle (hwnd, wParam, lParam);
4377
4378         case TB_GETTEXTROWS:
4379             return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
4380
4381         case TB_GETTOOLTIPS:
4382             return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
4383
4384         case TB_GETUNICODEFORMAT:
4385             return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
4386
4387         case CCM_GETVERSION:
4388             return TOOLBAR_GetVersion (hwnd);
4389
4390         case TB_HIDEBUTTON:
4391             return TOOLBAR_HideButton (hwnd, wParam, lParam);
4392
4393         case TB_HITTEST:
4394             return TOOLBAR_HitTest (hwnd, wParam, lParam);
4395
4396         case TB_INDETERMINATE:
4397             return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
4398
4399         case TB_INSERTBUTTONA:
4400             return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
4401
4402         case TB_INSERTBUTTONW:
4403             return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);
4404
4405 /*      case TB_INSERTMARKHITTEST:              */ /* 4.71 */
4406
4407         case TB_ISBUTTONCHECKED:
4408             return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
4409
4410         case TB_ISBUTTONENABLED:
4411             return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
4412
4413         case TB_ISBUTTONHIDDEN:
4414             return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
4415
4416         case TB_ISBUTTONHIGHLIGHTED:
4417             return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
4418
4419         case TB_ISBUTTONINDETERMINATE:
4420             return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
4421
4422         case TB_ISBUTTONPRESSED:
4423             return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
4424
4425         case TB_LOADIMAGES:                        /* 4.70 */
4426             FIXME("missing standard imagelists\n");
4427             return 0;
4428
4429 /*      case TB_MAPACCELERATORA:                */ /* 4.71 */
4430 /*      case TB_MAPACCELERATORW:                */ /* 4.71 */
4431 /*      case TB_MARKBUTTON:                     */ /* 4.71 */
4432 /*      case TB_MOVEBUTTON:                     */ /* 4.71 */
4433
4434         case TB_PRESSBUTTON:
4435             return TOOLBAR_PressButton (hwnd, wParam, lParam);
4436
4437 /*      case TB_REPLACEBITMAP: */
4438
4439         case TB_SAVERESTOREA:
4440             return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
4441
4442         case TB_SAVERESTOREW:
4443             return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);
4444
4445         case TB_SETANCHORHIGHLIGHT:
4446             return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
4447
4448         case TB_SETBITMAPSIZE:
4449             return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
4450
4451         case TB_SETBUTTONINFOA:
4452             return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
4453
4454         case TB_SETBUTTONINFOW:
4455             return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
4456
4457         case TB_SETBUTTONSIZE:
4458             return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
4459
4460         case TB_SETBUTTONWIDTH:
4461             return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
4462
4463         case TB_SETCMDID:
4464             return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
4465
4466 /*      case TB_SETCOLORSCHEME:                 */ /* 4.71 */
4467
4468         case TB_SETDISABLEDIMAGELIST:
4469             return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
4470
4471         case TB_SETDRAWTEXTFLAGS:
4472             return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
4473
4474         case TB_SETEXTENDEDSTYLE:
4475             return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
4476
4477         case TB_SETHOTIMAGELIST:
4478             return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
4479
4480         case TB_SETHOTITEM:
4481             return TOOLBAR_SetHotItem (hwnd, wParam);
4482
4483         case TB_SETIMAGELIST:
4484             return TOOLBAR_SetImageList (hwnd, wParam, lParam);
4485
4486         case TB_SETINDENT:
4487             return TOOLBAR_SetIndent (hwnd, wParam, lParam);
4488
4489 /*      case TB_SETINSERTMARK:                  */ /* 4.71 */
4490
4491         case TB_SETINSERTMARKCOLOR:
4492             return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
4493
4494         case TB_SETMAXTEXTROWS:
4495             return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
4496
4497 /*      case TB_SETPADDING:                     */ /* 4.71 */
4498
4499         case TB_SETPARENT:
4500             return TOOLBAR_SetParent (hwnd, wParam, lParam);
4501
4502         case TB_SETROWS:
4503             return TOOLBAR_SetRows (hwnd, wParam, lParam);
4504
4505         case TB_SETSTATE:
4506             return TOOLBAR_SetState (hwnd, wParam, lParam);
4507
4508         case TB_SETSTYLE:
4509             return TOOLBAR_SetStyle (hwnd, wParam, lParam);
4510
4511         case TB_SETTOOLTIPS:
4512             return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
4513
4514         case TB_SETUNICODEFORMAT:
4515             return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
4516
4517         case CCM_SETVERSION:
4518             return TOOLBAR_SetVersion (hwnd, (INT)wParam);
4519
4520
4521 /*      case WM_CHAR: */
4522
4523         case WM_CREATE:
4524             return TOOLBAR_Create (hwnd, wParam, lParam);
4525
4526         case WM_ERASEBKGND:
4527             return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
4528
4529         case WM_GETFONT:
4530                 return TOOLBAR_GetFont (hwnd, wParam, lParam);
4531
4532 /*      case WM_KEYDOWN: */
4533 /*      case WM_KILLFOCUS: */
4534
4535         case WM_LBUTTONDBLCLK:
4536             return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
4537
4538         case WM_LBUTTONDOWN:
4539             return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
4540
4541         case WM_LBUTTONUP:
4542             return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
4543
4544         case WM_MOUSEMOVE:
4545             return TOOLBAR_MouseMove (hwnd, wParam, lParam);
4546
4547         case WM_MOUSELEAVE:
4548             return TOOLBAR_MouseLeave (hwnd, wParam, lParam);   
4549
4550         case WM_CAPTURECHANGED:
4551             return TOOLBAR_CaptureChanged(hwnd);        
4552
4553         case WM_NCACTIVATE:
4554             return TOOLBAR_NCActivate (hwnd, wParam, lParam);
4555
4556         case WM_NCCALCSIZE:
4557             return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
4558
4559         case WM_NCPAINT:
4560             return TOOLBAR_NCPaint (hwnd, wParam, lParam);
4561
4562         case WM_NOTIFY:
4563             return TOOLBAR_Notify (hwnd, wParam, lParam);
4564
4565 /*      case WM_NOTIFYFORMAT: */
4566
4567         case WM_PAINT:
4568             return TOOLBAR_Paint (hwnd, wParam);
4569
4570         case WM_SIZE:
4571             return TOOLBAR_Size (hwnd, wParam, lParam);
4572
4573         case WM_STYLECHANGED:
4574             return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
4575
4576 /*      case WM_SYSCOLORCHANGE: */
4577
4578 /*      case WM_WININICHANGE: */
4579
4580         case WM_CHARTOITEM:
4581         case WM_COMMAND:
4582         case WM_DRAWITEM:
4583         case WM_MEASUREITEM:
4584         case WM_VKEYTOITEM:
4585             return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
4586
4587         default:
4588             if (uMsg >= WM_USER)
4589                 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
4590                      uMsg, wParam, lParam);
4591             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
4592     }
4593     return 0;
4594 }
4595
4596
4597 VOID
4598 TOOLBAR_Register (void)
4599 {
4600     WNDCLASSA wndClass;
4601
4602     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4603     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
4604     wndClass.lpfnWndProc   = (WNDPROC)ToolbarWindowProc;
4605     wndClass.cbClsExtra    = 0;
4606     wndClass.cbWndExtra    = sizeof(TOOLBAR_INFO *);
4607     wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
4608     wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
4609     wndClass.lpszClassName = TOOLBARCLASSNAMEA;
4610  
4611     RegisterClassA (&wndClass);
4612 }
4613
4614
4615 VOID
4616 TOOLBAR_Unregister (void)
4617 {
4618     UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);
4619 }
4620