Removed calls to internal (non-exported) wine functions.
[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 "wine/winestring.h"
46 #include "commctrl.h"
47 #include "imagelist.h"
48 #include "comctl32.h"
49 #include "debugtools.h"
50
51 DEFAULT_DEBUG_CHANNEL(toolbar);
52
53 typedef struct
54 {
55     INT iBitmap;
56     INT idCommand;
57     BYTE  fsState;
58     BYTE  fsStyle;
59     DWORD dwData;
60     INT iString;
61
62     BOOL bHot;
63     INT nRow;
64     RECT rect;
65 } TBUTTON_INFO; 
66
67 typedef struct
68 {
69     DWORD      dwStructSize;   /* size of TBBUTTON struct */
70     INT      nHeight;        /* height of the toolbar */
71     INT      nWidth;         /* width of the toolbar */
72     INT      nButtonHeight;
73     INT      nButtonWidth;
74     INT      nBitmapHeight;
75     INT      nBitmapWidth;
76     INT      nIndent;
77     INT      nRows;           /* number of button rows */
78     INT      nMaxTextRows;    /* maximum number of text rows */
79     INT      cxMin;           /* minimum button width */
80     INT      cxMax;           /* maximum button width */
81     INT      nNumButtons;     /* number of buttons */
82     INT      nNumBitmaps;     /* number of bitmaps */
83     INT      nNumStrings;     /* number of strings */
84     BOOL     bUnicode;        /* ASCII (FALSE) or Unicode (TRUE)? */
85     BOOL     bCaptured;       /* mouse captured? */
86     INT      nButtonDown;
87     INT      nOldHit;
88     INT      nHotItem;        /* index of the "hot" item */
89     HFONT    hFont;           /* text font */
90     HIMAGELIST himlInt;         /* image list created internally */
91     HIMAGELIST himlDef;         /* default image list */
92     HIMAGELIST himlHot;         /* hot image list */
93     HIMAGELIST himlDis;         /* disabled image list */
94     HWND     hwndToolTip;     /* handle to tool tip control */
95     HWND     hwndNotify;      /* handle to the window that gets notifications */
96     BOOL     bTransparent;    /* background transparency flag */
97     BOOL     bAutoSize;       /* auto size deadlock indicator */
98     BOOL     bAnchor;         /* anchor highlight enabled */
99     DWORD      dwExStyle;       /* extended toolbar style */
100     DWORD      dwDTFlags;       /* DrawText flags */
101
102     COLORREF   clrInsertMark;   /* insert mark color */
103     RECT     rcBound;         /* bounding rectangle */
104     INT      iVersion;
105
106     TBUTTON_INFO *buttons;      /* pointer to button array */
107     LPWSTR       *strings;      /* pointer to string array */
108 } TOOLBAR_INFO, *PTOOLBAR_INFO;
109
110
111 /* used by customization dialog */
112 typedef struct
113 {
114     PTOOLBAR_INFO tbInfo;
115     HWND          tbHwnd;
116 } CUSTDLG_INFO, *PCUSTDLG_INFO;
117
118 typedef struct
119 {
120     TBBUTTON btn;
121     BOOL     bVirtual;
122     BOOL     bRemovable;
123     CHAR     text[64];
124 } CUSTOMBUTTON, *PCUSTOMBUTTON;
125
126
127 #define SEPARATOR_WIDTH    8
128 #define TOP_BORDER         2
129 #define BOTTOM_BORDER      2
130 #define DDARROW_WIDTH      11 
131
132 #define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
133 #define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
134 #define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
135
136 static LPWSTR
137 TOOLBAR_GetText(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
138 {
139     LPWSTR lpText = NULL;
140
141     /* FIXME: iString == -1 is undocumented */
142     if ((HIWORD(btnPtr->iString) != 0) && (btnPtr->iString != -1))
143         lpText = (LPWSTR)btnPtr->iString;
144     else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
145         lpText = infoPtr->strings[btnPtr->iString];
146     
147     return lpText;
148 }
149
150 static BOOL 
151 TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
152 {
153     if ((index>=0) && (index < infoPtr->nNumBitmaps))
154       return TRUE;
155     else
156       return FALSE;
157 }
158
159
160 static void
161 TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
162 {
163     INT x = (lpRect->left + lpRect->right) / 2 - 1;
164     INT yBottom = lpRect->bottom - 3;
165     INT yTop = lpRect->top + 1;
166
167     SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
168     MoveToEx (hdc, x, yBottom, NULL);
169     LineTo (hdc, x, yTop);
170     x++;
171     SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
172     MoveToEx (hdc, x, yBottom, NULL);
173     LineTo (hdc, x, yTop);
174 }
175
176 static void
177 TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, INT colorRef)
178 {
179     INT x, y;
180     SelectObject ( hdc, GetSysColorPen (colorRef));
181     x = left + 2;
182     y = top + 8;
183     MoveToEx (hdc, x, y, NULL);
184     LineTo (hdc, x+5, y++); x++;
185     MoveToEx (hdc, x, y, NULL);
186     LineTo (hdc, x+3, y++); x++;
187     MoveToEx (hdc, x, y, NULL);
188     LineTo (hdc, x+1, y++);
189 }
190
191 /*
192  * Draw the text string for this button.
193  * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
194  *      is non-zero, so we can simply check himlDef to see if we have
195  *      an image list
196  */
197 static void
198 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
199                     HDC hdc, INT nState, DWORD dwStyle)
200 {
201     RECT   rcText = btnPtr->rect;
202     HFONT  hOldFont;
203     INT    nOldBkMode;
204     COLORREF clrOld;
205     LPWSTR lpText = NULL;
206     HIMAGELIST himl = infoPtr->himlDef;
207
208     TRACE ("iString: %x\n", btnPtr->iString);
209
210     /* get a pointer to the text */
211     lpText = TOOLBAR_GetText(infoPtr, btnPtr);
212
213     TRACE ("lpText: \"%s\"\n", debugstr_w(lpText));
214
215     /* draw text */
216     if (lpText) {
217
218         InflateRect (&rcText, -3, -3);
219
220         if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
221                 if ((dwStyle & TBSTYLE_LIST) &&
222                     ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
223                     (btnPtr->iBitmap != I_IMAGENONE)) {
224                     rcText.left += infoPtr->nBitmapWidth;
225                 }
226                 else {
227                     rcText.top += infoPtr->nBitmapHeight;
228                 }
229         }
230
231         if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
232             OffsetRect (&rcText, 1, 1);
233
234         hOldFont = SelectObject (hdc, infoPtr->hFont);
235         nOldBkMode = SetBkMode (hdc, TRANSPARENT);
236         if (!(nState & TBSTATE_ENABLED)) {
237             clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
238             OffsetRect (&rcText, 1, 1);
239             DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
240             SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
241             OffsetRect (&rcText, -1, -1);
242             DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
243         }
244         else if (nState & TBSTATE_INDETERMINATE) {
245             clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
246             DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
247         }
248         else {
249             clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
250             DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
251         }
252
253         SetTextColor (hdc, clrOld);
254         SelectObject (hdc, hOldFont);
255         if (nOldBkMode != TRANSPARENT)
256             SetBkMode (hdc, nOldBkMode);
257     }
258 }
259
260
261 static void
262 TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
263 {
264     HBRUSH hbr = SelectObject (hdc, COMCTL32_hPattern55AABrush);
265     INT cx = lpRect->right - lpRect->left;
266     INT cy = lpRect->bottom - lpRect->top;
267     PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
268     SelectObject (hdc, hbr);
269 }
270
271
272 static void
273 TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
274                     HDC hdc, INT x, INT y)
275 {
276     /* FIXME: this function is a hack since it uses image list
277               internals directly */
278
279     HIMAGELIST himl = infoPtr->himlDef;
280     HBITMAP hbmMask;
281     HDC hdcImageList;
282     HDC hdcMask;
283
284     if (!himl)
285         return;
286
287     /* create new dc's */
288     hdcImageList = CreateCompatibleDC (0);
289     hdcMask = CreateCompatibleDC (0);
290
291     /* create new bitmap */
292     hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
293     SelectObject (hdcMask, hbmMask);
294
295     /* copy the mask bitmap */
296     SelectObject (hdcImageList, himl->hbmMask);
297     SetBkColor (hdcImageList, RGB(255, 255, 255));
298     SetTextColor (hdcImageList, RGB(0, 0, 0));
299     BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
300               hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);
301
302     /* draw the new mask */
303     SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
304     BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
305               hdcMask, 0, 0, 0xB8074A);
306
307     SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
308     BitBlt (hdc, x, y, himl->cx, himl->cy,
309               hdcMask, 0, 0, 0xB8074A);
310
311     DeleteObject (hbmMask);
312     DeleteDC (hdcMask);
313     DeleteDC (hdcImageList);
314 }
315
316
317 static void
318 TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
319 {
320     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
321     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
322     BOOL hasDropDownArrow = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
323                             (btnPtr->fsStyle & TBSTYLE_DROPDOWN);
324     RECT rc, rcArrow, rcBitmap;
325
326     if (btnPtr->fsState & TBSTATE_HIDDEN)
327         return;
328
329     rc = btnPtr->rect;
330     CopyRect (&rcArrow, &rc);
331     CopyRect(&rcBitmap, &rc);
332
333     FillRect( hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
334
335     if (hasDropDownArrow)
336     {
337         if (dwStyle & TBSTYLE_FLAT)
338             rc.right = max(rc.left, rc.right - DDARROW_WIDTH);
339         else
340             rc.right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
341         rcArrow.left = rc.right; 
342     }
343
344     /* Center the bitmap horizontally and vertically */
345     rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;
346
347     if(TOOLBAR_HasText(infoPtr, btnPtr))
348         rcBitmap.top+=2; /* this looks to be the correct value from vmware comparison - cmm */
349     else
350         rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;
351
352     TRACE("iBitmap: %d\n", btnPtr->iBitmap);
353
354     /* separator */
355     if (btnPtr->fsStyle & TBSTYLE_SEP) {
356         /* with the FLAT style, iBitmap is the width and has already */
357         /* been taken into consideration in calculating the width    */
358         /* so now we need to draw the vertical separator             */
359         /* empirical tests show that iBitmap can/will be non-zero    */
360         /* when drawing the vertical bar...      */
361         if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */)
362             TOOLBAR_DrawFlatSeparator (&rc, hdc);
363         return;
364     }
365
366     /* disabled */
367     if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
368         if (!(dwStyle & TBSTYLE_FLAT))
369         {
370             DrawEdge (hdc, &rc, EDGE_RAISED,
371                       BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
372             if (hasDropDownArrow)
373             DrawEdge (hdc, &rcArrow, EDGE_RAISED,
374                       BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
375         }
376         
377         if (hasDropDownArrow)
378         {
379             TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1, COLOR_3DHIGHLIGHT);
380             TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_3DSHADOW);
381         }
382
383         if (infoPtr->himlDis && 
384             TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
385             ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
386                         rcBitmap.left, rcBitmap.top, ILD_NORMAL);
387         else
388             TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
389
390         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
391         return;
392     }
393
394     /* pressed TBSTYLE_BUTTON */
395     if (btnPtr->fsState & TBSTATE_PRESSED) {
396         if (dwStyle & TBSTYLE_FLAT)
397         {
398             DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
399             if (hasDropDownArrow)
400             DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
401         }
402         else
403         {
404             DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
405             if (hasDropDownArrow)
406             DrawEdge (hdc, &rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
407         }
408
409         if (hasDropDownArrow)
410             TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
411
412         if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
413             ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
414                         rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
415
416         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
417         return;
418     }
419
420     /* checked TBSTYLE_CHECK */
421     if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
422         (btnPtr->fsState & TBSTATE_CHECKED)) {
423         if (dwStyle & TBSTYLE_FLAT)
424             DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
425                         BF_RECT | BF_MIDDLE | BF_ADJUST);
426         else
427             DrawEdge (hdc, &rc, EDGE_SUNKEN,
428                         BF_RECT | BF_MIDDLE | BF_ADJUST);
429
430         TOOLBAR_DrawPattern (hdc, &rc);
431         
432         if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
433             ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
434                         rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
435         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
436         return;
437     }
438
439     /* indeterminate */ 
440     if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
441         DrawEdge (hdc, &rc, EDGE_RAISED,
442                     BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
443
444         TOOLBAR_DrawPattern (hdc, &rc);
445         TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
446         TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
447         return;
448     }
449
450     /* normal state */
451     if (dwStyle & TBSTYLE_FLAT)
452     {
453         if (btnPtr->bHot)
454         {
455             DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
456             if (hasDropDownArrow)
457             DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
458         }
459         else
460         {
461             FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
462             if (hasDropDownArrow)
463             FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
464         }
465
466         if (hasDropDownArrow)
467             TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
468
469         if (btnPtr->bHot && infoPtr->himlHot &&
470             TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
471             ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
472                         rcBitmap.left, rcBitmap.top, ILD_NORMAL);
473         else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
474             ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
475                         rcBitmap.left, rcBitmap.top, ILD_NORMAL);
476     }
477     else
478     {
479         DrawEdge (hdc, &rc, EDGE_RAISED,
480                 BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
481
482         if (hasDropDownArrow)
483         {
484             DrawEdge (hdc, &rcArrow, EDGE_RAISED,
485                     BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
486             TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
487         }
488
489         if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
490             ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
491                         rcBitmap.left, rcBitmap.top, ILD_NORMAL);
492     }
493
494     TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
495 }
496
497
498 static void
499 TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
500 {
501     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
502     TBUTTON_INFO *btnPtr;
503     INT i;
504     RECT rcTemp;
505
506     /* redraw necessary buttons */
507     btnPtr = infoPtr->buttons;
508     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
509     {
510         if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
511             TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
512     }
513 }
514
515 static void
516 TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
517 {
518     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
519     TBUTTON_INFO *btnPtr;
520     HDC hdc;
521     HFONT hOldFont;
522
523     lpSize->cx = 0;
524     lpSize->cy = 0;
525     hdc = GetDC (0);
526     hOldFont = SelectObject (hdc, infoPtr->hFont);
527
528     btnPtr = &infoPtr->buttons[index];
529
530     if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
531          (btnPtr->iString > -1) &&
532          (btnPtr->iString < infoPtr->nNumStrings)) 
533     {
534         LPWSTR lpText = infoPtr->strings[btnPtr->iString];
535         GetTextExtentPoint32W (hdc, lpText, lstrlenW (lpText), lpSize);
536     }
537
538     SelectObject (hdc, hOldFont);
539     ReleaseDC (0, hdc);
540
541     TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
542 }
543
544 static void
545 TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
546 {
547     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
548     TBUTTON_INFO *btnPtr;
549     INT i;
550     SIZE sz;
551
552
553     lpSize->cx = 0;
554     lpSize->cy = 0;
555
556     btnPtr = infoPtr->buttons;
557     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
558         if(TOOLBAR_HasText(infoPtr, btnPtr))
559         {
560             TOOLBAR_MeasureString(hwnd,i,&sz);
561             if (sz.cx > lpSize->cx)
562                 lpSize->cx = sz.cx;
563             if (sz.cy > lpSize->cy)
564                 lpSize->cy = sz.cy;
565         }
566     }
567
568     TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
569 }
570
571 /***********************************************************************
572 *               TOOLBAR_WrapToolbar
573 *
574 * This function walks through the buttons and seperators in the 
575 * toolbar, and sets the TBSTATE_WRAP flag only on those items where 
576 * wrapping should occur based on the width of the toolbar window.  
577 * It does *not* calculate button placement itself.  That task 
578 * takes place in TOOLBAR_CalcToolbar. If the program wants to manage 
579 * the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE 
580 * flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
581 */ 
582
583 static void
584 TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
585 {
586     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
587     TBUTTON_INFO *btnPtr;
588     INT x, cx, i, j;
589     RECT rc;
590     BOOL bWrap, bButtonWrap;
591
592     /*  When the toolbar window style is not TBSTYLE_WRAPABLE,  */ 
593     /*  no layout is necessary. Applications may use this style */
594     /*  to perform their own layout on the toolbar.             */
595     if( !(dwStyle & TBSTYLE_WRAPABLE) )
596         return;
597
598     btnPtr = infoPtr->buttons;
599     x  = infoPtr->nIndent;
600
601     /* this can get the parents width, to know how far we can extend
602      * this toolbar.  We cannot use its height, as there may be multiple
603      * toolbars in a rebar control
604      */
605     GetClientRect( GetParent(hwnd), &rc );
606     infoPtr->nWidth = rc.right - rc.left;
607     bButtonWrap = FALSE;
608
609     for (i = 0; i < infoPtr->nNumButtons; i++ )
610     {
611         bWrap = FALSE;
612         btnPtr[i].fsState &= ~TBSTATE_WRAP;
613         
614         if (btnPtr[i].fsState & TBSTATE_HIDDEN)
615             continue;
616
617         /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
618         /* it is the actual width of the separator. This is used for */
619         /* custom controls in toolbars.                              */
620         if (btnPtr[i].fsStyle & TBSTYLE_SEP)
621             cx = (btnPtr[i].iBitmap > 0) ?  
622                         btnPtr[i].iBitmap : SEPARATOR_WIDTH;
623         else
624             cx = infoPtr->nButtonWidth;
625
626         /* Two or more adjacent separators form a separator group.   */ 
627         /* The first separator in a group should be wrapped to the   */
628         /* next row if the previous wrapping is on a button.         */
629         if( bButtonWrap &&
630                 (btnPtr[i].fsStyle & TBSTYLE_SEP) && 
631                 (i + 1 < infoPtr->nNumButtons ) &&
632                 (btnPtr[i + 1].fsStyle & TBSTYLE_SEP) ) 
633         {
634             btnPtr[i].fsState |= TBSTATE_WRAP;
635             x = infoPtr->nIndent;
636             i++;
637             bButtonWrap = FALSE;
638             continue;
639         }
640
641         /* The layout makes sure the bitmap is visible, but not the button. */
642         if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2 
643                  > infoPtr->nWidth ) 
644         {
645             BOOL bFound = FALSE;
646
647             /*  If the current button is a separator and not hidden,  */ 
648             /*  go to the next until it reaches a non separator.      */
649             /*  Wrap the last separator if it is before a button.     */
650             while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) || 
651                         (btnPtr[i].fsState & TBSTATE_HIDDEN) ) && 
652                         i < infoPtr->nNumButtons )
653             {
654                 i++;
655                 bFound = TRUE;
656             }
657     
658             if( bFound && i < infoPtr->nNumButtons )
659             {
660                 i--;
661                 btnPtr[i].fsState |= TBSTATE_WRAP;
662                 x = infoPtr->nIndent;
663                 bButtonWrap = FALSE;
664                 continue;
665             }
666             else if ( i >= infoPtr->nNumButtons)
667                 break;
668
669             /*  If the current button is not a separator, find the last  */ 
670             /*  separator and wrap it.                                   */
671             for ( j = i - 1; j >= 0  &&  !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
672             {
673                 if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
674                         !(btnPtr[j].fsState & TBSTATE_HIDDEN))
675                 {
676                     bFound = TRUE; 
677                     i = j; 
678                     x = infoPtr->nIndent;
679                     btnPtr[j].fsState |= TBSTATE_WRAP;
680                     bButtonWrap = FALSE; 
681                     break;
682                 }
683             }
684
685             /*  If no separator available for wrapping, wrap one of     */
686             /*  non-hidden previous button.                             */
687             if (!bFound)
688             {
689                 for ( j = i - 1; 
690                         j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
691                 {
692                     if (btnPtr[j].fsState & TBSTATE_HIDDEN) 
693                         continue;
694
695                     bFound = TRUE; 
696                     i = j; 
697                     x = infoPtr->nIndent;
698                     btnPtr[j].fsState |= TBSTATE_WRAP;
699                     bButtonWrap = TRUE;
700                     break;
701                 }
702             }
703
704             /* If all above failed, wrap the current button. */
705             if (!bFound)  
706             {
707                 btnPtr[i].fsState |= TBSTATE_WRAP;
708                 bFound = TRUE;
709                 x = infoPtr->nIndent;
710                 if (btnPtr[i].fsState & TBSTYLE_SEP )
711                     bButtonWrap = FALSE;
712                 else
713                     bButtonWrap = TRUE;
714             }               
715         }
716         else
717             x += cx;
718     }
719 }
720
721
722 /***********************************************************************
723 *               TOOLBAR_CalcToolbar
724 *
725 * This function calculates button and separator placement. It first 
726 * calculates the button sizes, gets the toolbar window width and then 
727 * calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap 
728 * on. It assigns a new location to each item and sends this location to
729 * the tooltip window if appropriate. Finally, it updates the rcBound 
730 * rect and calculates the new required toolbar window height. 
731 */  
732
733 static void
734 TOOLBAR_CalcToolbar (HWND hwnd)
735 {
736     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
737     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
738     TBUTTON_INFO *btnPtr;
739     INT i, nRows, nSepRows;
740     INT x, y, cx, cy;
741     SIZE  sizeString;
742     BOOL bWrap;
743     BOOL usesBitmaps = FALSE;
744     BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
745
746     TOOLBAR_CalcStrings (hwnd, &sizeString);
747
748     if (dwStyle & TBSTYLE_LIST)
749     {
750         infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
751         infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
752     }
753     else {
754         for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
755         {
756             if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
757                 usesBitmaps = TRUE;
758         }
759
760         if (sizeString.cy > 0)
761         {
762             if (usesBitmaps)
763               infoPtr->nButtonHeight = sizeString.cy +
764                   infoPtr->nBitmapHeight + 6;
765             else 
766                 infoPtr->nButtonHeight = sizeString.cy + 6;
767         }
768         else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
769             infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
770
771         if (sizeString.cx > infoPtr->nBitmapWidth)
772             infoPtr->nButtonWidth = sizeString.cx + 6;
773         else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
774             infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
775     }
776
777     if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
778         infoPtr->nButtonWidth = infoPtr->cxMin;
779     if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
780         infoPtr->nButtonWidth = infoPtr->cxMax;
781
782     TOOLBAR_WrapToolbar( hwnd, dwStyle );
783
784     x  = infoPtr->nIndent;
785     y  = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
786
787    /*
788     * We will set the height below, and we set the width on entry 
789     * so we do not reset them here.. 
790     */
791 #if 0
792     GetClientRect( hwnd, &rc );
793     /* get initial values for toolbar */
794     infoPtr->nWidth  = rc.right - rc.left;
795     infoPtr->nHeight = rc.bottom - rc.top;
796 #endif
797
798     /* from above, minimum is a button, and possible text */
799     cx = infoPtr->nButtonWidth;
800
801     /* cannot use just ButtonHeight, we may have no buttons! */
802     if (infoPtr->nNumButtons > 0)
803         infoPtr->nHeight = infoPtr->nButtonHeight;
804
805     cy = infoPtr->nHeight;
806
807     nRows = nSepRows = 0;
808
809     infoPtr->rcBound.top = y;
810     infoPtr->rcBound.left = x;
811     infoPtr->rcBound.bottom = y + cy;
812     infoPtr->rcBound.right = x;
813
814     btnPtr = infoPtr->buttons;
815
816     /* do not base height/width on parent, if the parent is a */
817     /* rebar control it could have multiple rows of toolbars  */
818 /*    GetClientRect( GetParent(hwnd), &rc ); */
819 /*    cx = rc.right - rc.left; */
820 /*    cy = rc.bottom - rc.top; */
821
822     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
823     {
824         bWrap = FALSE;
825         if (btnPtr->fsState & TBSTATE_HIDDEN)
826         {
827             SetRectEmpty (&btnPtr->rect);
828             continue;
829         }
830
831             /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
832             /* it is the actual width of the separator. This is used for */
833             /* custom controls in toolbars.                              */
834         if (btnPtr->fsStyle & TBSTYLE_SEP)
835                 cx = (btnPtr->iBitmap > 0) ?
836                      btnPtr->iBitmap : SEPARATOR_WIDTH;
837         else
838         {
839             if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE) 
840             {
841               SIZE sz;
842               TOOLBAR_MeasureString(hwnd,i,&sz);
843               cx = sz.cx + 6;
844             }
845             else
846               cx = infoPtr->nButtonWidth;
847
848             if (hasDropDownArrows && (btnPtr->fsStyle & TBSTYLE_DROPDOWN))
849               cx += DDARROW_WIDTH; 
850         }
851         cy = infoPtr->nHeight;
852
853         if (btnPtr->fsState & TBSTATE_WRAP )
854                     bWrap = TRUE;
855
856         SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
857
858         if (infoPtr->rcBound.left > x)
859             infoPtr->rcBound.left = x;
860         if (infoPtr->rcBound.right < x + cx)
861             infoPtr->rcBound.right = x + cx;
862         if (infoPtr->rcBound.bottom < y + cy)
863             infoPtr->rcBound.bottom = y + cy;
864
865         /* Set the toolTip only for non-hidden, non-separator button */
866         if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP )) 
867         {
868             TTTOOLINFOA ti;
869
870             ZeroMemory (&ti, sizeof(TTTOOLINFOA));
871             ti.cbSize = sizeof(TTTOOLINFOA);
872             ti.hwnd = hwnd;
873             ti.uId = btnPtr->idCommand;
874             ti.rect = btnPtr->rect;
875             SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
876                             0, (LPARAM)&ti);
877         }
878
879         /* btnPtr->nRow is zero based. The space between the rows is    */
880         /* also considered as a row.                                    */
881         btnPtr->nRow = nRows + nSepRows;
882         if( bWrap )
883         {
884             if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
885                 y += cy;
886             else 
887             {   
888                 /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
889                 /* it is the actual width of the separator. This is used for */
890                 /* custom controls in toolbars.                              */
891                 y += cy + ( (btnPtr->iBitmap > 0 ) ? 
892                         btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3; 
893              
894                 /* nSepRows is used to calculate the extra height follwoing  */          
895                 /* the last row.                                             */
896                 nSepRows++;
897             }
898             x = infoPtr->nIndent;
899                 nRows++;
900         }
901         else
902             x += cx;
903     }
904
905     /* infoPtr->nRows is the number of rows on the toolbar */
906     infoPtr->nRows = nRows + nSepRows + 1;
907
908     /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following   */
909     /* the last row.                                                    */
910     infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight + 
911                         nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
912                         nSepRows * (infoPtr->nBitmapHeight + 1) + 
913                         BOTTOM_BORDER; 
914     TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
915 }
916
917
918 static INT
919 TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
920 {
921     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
922     TBUTTON_INFO *btnPtr;
923     INT i;
924     
925     btnPtr = infoPtr->buttons;
926     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
927         if (btnPtr->fsState & TBSTATE_HIDDEN)
928             continue;
929
930         if (btnPtr->fsStyle & TBSTYLE_SEP) {
931             if (PtInRect (&btnPtr->rect, *lpPt)) {
932                 TRACE(" ON SEPARATOR %d!\n", i);
933                 return -i;
934             }
935         }
936         else {
937             if (PtInRect (&btnPtr->rect, *lpPt)) {
938                 TRACE(" ON BUTTON %d!\n", i);
939                 return i;
940             }
941         }
942     }
943
944     TRACE(" NOWHERE!\n");
945     return -1;
946 }
947
948
949 static INT
950 TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
951 {
952     TBUTTON_INFO *btnPtr;
953     INT i;
954
955     btnPtr = infoPtr->buttons;
956     for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
957         if (btnPtr->idCommand == idCommand) {
958             TRACE("command=%d index=%d\n", idCommand, i);
959             return i;
960         }
961     }
962     TRACE("no index found for command=%d\n", idCommand);
963     return -1;
964 }
965
966
967 static INT
968 TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
969 {
970     TBUTTON_INFO *btnPtr;
971     INT nRunIndex;
972
973     if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
974         return -1;
975
976     /* check index button */
977     btnPtr = &infoPtr->buttons[nIndex];
978     if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
979         if (btnPtr->fsState & TBSTATE_CHECKED)
980             return nIndex;
981     }
982
983     /* check previous buttons */
984     nRunIndex = nIndex - 1;
985     while (nRunIndex >= 0) {
986         btnPtr = &infoPtr->buttons[nRunIndex];
987         if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
988             if (btnPtr->fsState & TBSTATE_CHECKED)
989                 return nRunIndex;
990         }
991         else
992             break;
993         nRunIndex--;
994     }
995
996     /* check next buttons */
997     nRunIndex = nIndex + 1;
998     while (nRunIndex < infoPtr->nNumButtons) {
999         btnPtr = &infoPtr->buttons[nRunIndex];  
1000         if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
1001             if (btnPtr->fsState & TBSTATE_CHECKED)
1002                 return nRunIndex;
1003         }
1004         else
1005             break;
1006         nRunIndex++;
1007     }
1008
1009     return -1;
1010 }
1011
1012
1013 static VOID
1014 TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
1015                     WPARAM wParam, LPARAM lParam)
1016 {
1017     MSG msg;
1018
1019     msg.hwnd = hwndMsg;
1020     msg.message = uMsg;
1021     msg.wParam = wParam;
1022     msg.lParam = lParam;
1023     msg.time = GetMessageTime ();
1024     msg.pt.x = LOWORD(GetMessagePos ());
1025     msg.pt.y = HIWORD(GetMessagePos ());
1026
1027     SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
1028 }
1029
1030
1031 /***********************************************************************
1032  * TOOLBAR_CustomizeDialogProc
1033  * This function implements the toolbar customization dialog.
1034  */
1035 static BOOL WINAPI
1036 TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1037 {
1038     PCUSTDLG_INFO custInfo = (PCUSTDLG_INFO)GetWindowLongA (hwnd, DWL_USER);
1039     PCUSTOMBUTTON btnInfo;
1040     NMTOOLBARA nmtb;
1041
1042     switch (uMsg)
1043     {
1044         case WM_INITDIALOG:
1045             custInfo = (PCUSTDLG_INFO)lParam;
1046             SetWindowLongA (hwnd, DWL_USER, (DWORD)custInfo);
1047
1048             if (custInfo)
1049             {
1050                 char Buffer[256];
1051                 int i = 0;
1052                 int index;
1053
1054                 /* send TBN_QUERYINSERT notification */
1055                 nmtb.hdr.hwndFrom = hwnd;
1056                 nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1057                 nmtb.hdr.code     = TBN_QUERYINSERT;
1058                 nmtb.iItem = custInfo->tbInfo->nNumButtons;
1059
1060                 if (!SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1061                                    (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1062                     return FALSE;
1063
1064                 /* add items to 'toolbar buttons' list and check if removable */
1065                 for (i = 0; i < custInfo->tbInfo->nNumButtons; i++)
1066                 {
1067                     btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1068                     memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1069                     btnInfo->btn.fsStyle = TBSTYLE_SEP;
1070                     btnInfo->bVirtual = FALSE;
1071                     LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1072
1073                     /* send TBN_QUERYDELETE notification */
1074                     nmtb.hdr.hwndFrom = hwnd;
1075                     nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1076                     nmtb.hdr.code     = TBN_QUERYDELETE;
1077                     nmtb.iItem = i;
1078
1079                     btnInfo->bRemovable = SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1080                                                         (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
1081
1082                     index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, 0);
1083                     SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1084                 }
1085
1086                 /* insert separator button into 'available buttons' list */
1087                 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1088                 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1089                 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1090                 btnInfo->bVirtual = FALSE;
1091                 btnInfo->bRemovable = TRUE;
1092                 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1093                 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1094                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1095
1096                 /* insert all buttons into dsa */
1097                 for (i = 0;; i++)
1098                 {
1099                     /* send TBN_GETBUTTONINFO notification */
1100                     nmtb.hdr.hwndFrom = hwnd;
1101                     nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1102                     nmtb.hdr.code     = TBN_GETBUTTONINFOA;
1103                     nmtb.iItem = i;
1104                     nmtb.pszText = Buffer;
1105                     nmtb.cchText = 256;
1106
1107                     if (!SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1108                                        (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1109                         break;
1110
1111                     TRACE("style: %x\n", nmtb.tbButton.fsStyle);                
1112
1113                     /* insert button into the apropriate list */
1114                     index = TOOLBAR_GetButtonIndex (custInfo->tbInfo, nmtb.tbButton.idCommand);
1115                     if (index == -1)
1116                     {
1117                         btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1118                         memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1119                         btnInfo->bVirtual = FALSE;
1120                         btnInfo->bRemovable = TRUE;
1121                         if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1122                             strcpy (btnInfo->text, nmtb.pszText);
1123
1124                         index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1125                         SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1126                     }
1127                     else
1128                     {
1129                         btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1130                         memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
1131                         if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
1132                             strcpy (btnInfo->text, nmtb.pszText);
1133
1134                         SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1135                     }
1136                 }
1137
1138                 /* select first item in the 'available' list */
1139                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, 0, 0);
1140
1141                 /* append 'virtual' separator button to the 'toolbar buttons' list */
1142                 btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
1143                 memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
1144                 btnInfo->btn.fsStyle = TBSTYLE_SEP;
1145                 btnInfo->bVirtual = TRUE;
1146                 btnInfo->bRemovable = FALSE;
1147                 LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
1148                 index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
1149                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1150
1151                 /* select last item in the 'toolbar' list */
1152                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index, 0);
1153                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETTOPINDEX, index, 0);
1154
1155                 /* set focus and disable buttons */
1156                 PostMessageA (hwnd, WM_USER, 0, 0);
1157             }
1158             return TRUE;
1159
1160         case WM_USER:
1161             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1162             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1163             EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), FALSE);
1164             SetFocus (GetDlgItem (hwnd, IDC_TOOLBARBTN_LBOX));
1165             return TRUE;
1166
1167         case WM_CLOSE:
1168             EndDialog(hwnd, FALSE);
1169             return TRUE;
1170
1171         case WM_COMMAND:
1172             switch (LOWORD(wParam))
1173             {
1174                 case IDC_TOOLBARBTN_LBOX:
1175                     if (HIWORD(wParam) == LBN_SELCHANGE)
1176                     {
1177                         PCUSTOMBUTTON btnInfo;
1178                         NMTOOLBARA nmtb;
1179                         int count;
1180                         int index;
1181
1182                         count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1183                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1184
1185                         /* send TBN_QUERYINSERT notification */
1186                         nmtb.hdr.hwndFrom = hwnd;
1187                         nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1188                         nmtb.hdr.code     = TBN_QUERYINSERT;
1189                         nmtb.iItem = index;
1190
1191                         SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1192                                       (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
1193
1194                         /* get list box item */
1195                         btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1196
1197                         if (index == (count - 1))
1198                         {
1199                             /* last item (virtual separator) */
1200                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1201                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1202                         }
1203                         else if (index == (count - 2))
1204                         {
1205                             /* second last item (last non-virtual item) */
1206                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1207                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1208                         }
1209                         else if (index == 0)
1210                         {
1211                             /* first item */
1212                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1213                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1214                         }
1215                         else
1216                         {
1217                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1218                             EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1219                         }
1220
1221                         EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), btnInfo->bRemovable);
1222                     }
1223                     break;
1224
1225                 case IDC_MOVEUP_BTN:
1226                     {
1227                         PCUSTOMBUTTON btnInfo;
1228                         int index;
1229                         int count;
1230
1231                         count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1232                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1233                         TRACE("Move up: index %d\n", index);
1234
1235                         /* send TBN_QUERYINSERT notification */
1236                         nmtb.hdr.hwndFrom = hwnd;
1237                         nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1238                         nmtb.hdr.code     = TBN_QUERYINSERT;
1239                         nmtb.iItem = index;
1240
1241                         if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1242                                           (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1243                         {
1244                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1245
1246                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1247                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index-1, 0);
1248                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index-1, (LPARAM)btnInfo);
1249                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1250
1251                             if (index <= 1)
1252                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
1253                             else if (index >= (count - 3))
1254                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
1255
1256                             SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1257                             SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index-1, (LPARAM)&(btnInfo->btn));
1258                         }
1259                     }
1260                     break;
1261
1262                 case IDC_MOVEDN_BTN: /* move down */
1263                     {
1264                         PCUSTOMBUTTON btnInfo;
1265                         int index;
1266                         int count;
1267
1268                         count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1269                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1270                         TRACE("Move up: index %d\n", index);
1271
1272                         /* send TBN_QUERYINSERT notification */
1273                         nmtb.hdr.hwndFrom = hwnd;
1274                         nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1275                         nmtb.hdr.code     = TBN_QUERYINSERT;
1276                         nmtb.iItem = index;
1277
1278                         if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1279                                           (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1280                         {
1281                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1282
1283                             /* move button down */
1284                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1285                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index+1, 0);
1286                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index+1, (LPARAM)btnInfo);
1287                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index+1 , 0);
1288
1289                             if (index == 0)
1290                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
1291                             else if (index >= (count - 3))
1292                                 EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
1293
1294                             SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1295                             SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index+1, (LPARAM)&(btnInfo->btn));
1296                         }
1297                     }
1298                     break;
1299
1300                 case IDC_REMOVE_BTN: /* remove button */
1301                     {
1302                         PCUSTOMBUTTON btnInfo;
1303                         int index;
1304
1305                         index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1306                         TRACE("Remove: index %d\n", index);
1307
1308                         /* send TBN_QUERYDELETE notification */
1309                         nmtb.hdr.hwndFrom = hwnd;
1310                         nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1311                         nmtb.hdr.code     = TBN_QUERYDELETE;
1312                         nmtb.iItem = index;
1313
1314                         if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1315                                           (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1316                         {
1317                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
1318                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
1319                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index , 0);
1320
1321                             SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
1322
1323                             /* insert into 'available button' list */
1324                             if (!(btnInfo->btn.fsStyle & TBSTYLE_SEP))
1325                             {
1326                                 index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
1327                                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1328                             }
1329                             else
1330                                 COMCTL32_Free (btnInfo);
1331                         }
1332                     }
1333                     break;
1334
1335                 case IDOK: /* Add button */
1336                     {
1337                         int index;
1338                         int count;
1339
1340                         count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1341                         index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0);
1342                         TRACE("Add: index %d\n", index);
1343
1344                         /* send TBN_QUERYINSERT notification */
1345                         nmtb.hdr.hwndFrom = hwnd;
1346                         nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
1347                         nmtb.hdr.code     = TBN_QUERYINSERT;
1348                         nmtb.iItem = index;
1349
1350                         if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
1351                                           (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
1352                         {
1353                             btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, index, 0);
1354
1355                             if (index != 0)
1356                             {
1357                                 /* remove from 'available buttons' list */
1358                                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_DELETESTRING, index, 0);
1359                                 if (index == count-1)
1360                                     SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index-1 , 0);
1361                                 else
1362                                     SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index , 0);
1363                             }
1364                             else
1365                             {
1366                                 PCUSTOMBUTTON btnNew;
1367
1368                                 /* duplicate 'separator' button */
1369                                 btnNew = (PCUSTOMBUTTON)COMCTL32_Alloc (sizeof(CUSTOMBUTTON));
1370                                 memcpy (btnNew, btnInfo, sizeof(CUSTOMBUTTON));
1371                                 btnInfo = btnNew;
1372                             }
1373
1374                             /* insert into 'toolbar button' list */
1375                             index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
1376                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index, 0);
1377                             SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1378
1379                             SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index, (LPARAM)&(btnInfo->btn));
1380                         }
1381                     }
1382                     break;
1383
1384                 case IDCANCEL:
1385                     EndDialog(hwnd, FALSE);
1386                     break;
1387             }
1388             return TRUE;
1389
1390         case WM_DESTROY:
1391             {
1392                 int count;
1393                 int i;
1394
1395                 /* delete items from 'toolbar buttons' listbox*/
1396                 count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
1397                 for (i = 0; i < count; i++)
1398                 {
1399                     btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, i, 0);
1400                     COMCTL32_Free(btnInfo);
1401                     SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, 0, 0);
1402                 }
1403                 SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_RESETCONTENT, 0, 0);
1404
1405
1406                 /* delete items from 'available buttons' listbox*/
1407                 count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
1408                 for (i = 0; i < count; i++)
1409                 {
1410                     btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, i, 0);
1411                     COMCTL32_Free(btnInfo);
1412                     SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, i, 0);
1413                 }
1414                 SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_RESETCONTENT, 0, 0);
1415             }
1416             return TRUE;
1417
1418         case WM_DRAWITEM:
1419             if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1420             {
1421                 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
1422                 RECT rcButton;
1423                 RECT rcText;
1424                 HPEN hOldPen;
1425                 HBRUSH hOldBrush;
1426                 COLORREF oldText = 0;
1427                 COLORREF oldBk = 0;
1428
1429                 /* get item data */
1430                 btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, wParam, LB_GETITEMDATA, (WPARAM)lpdis->itemID, 0);
1431                 if (btnInfo == NULL)
1432                 {
1433                     FIXME("btnInfo invalid!\n");
1434                     return TRUE;
1435                 }
1436
1437                 /* set colors and select objects */
1438                 oldBk = SetBkColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1439                 if (btnInfo->bVirtual)
1440                    oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
1441                 else
1442                    oldText = SetTextColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHTTEXT:COLOR_WINDOWTEXT));
1443                 hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1444                 hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
1445
1446                 /* fill background rectangle */
1447                 Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
1448                            lpdis->rcItem.right, lpdis->rcItem.bottom);
1449
1450                 /* calculate button and text rectangles */
1451                 CopyRect (&rcButton, &lpdis->rcItem);
1452                 InflateRect (&rcButton, -1, -1);
1453                 CopyRect (&rcText, &rcButton);
1454                 rcButton.right = rcButton.left + custInfo->tbInfo->nBitmapWidth + 6;
1455                 rcText.left = rcButton.right + 2;
1456
1457                 /* draw focus rectangle */
1458                 if (lpdis->itemState & ODS_FOCUS)
1459                     DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
1460
1461                 /* draw button */
1462                 DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
1463
1464                 /* draw image and text */
1465                 if ((btnInfo->btn.fsStyle & TBSTYLE_SEP) == 0)
1466                     ImageList_Draw (custInfo->tbInfo->himlDef, btnInfo->btn.iBitmap, lpdis->hDC,
1467                                     rcButton.left+3, rcButton.top+3, ILD_NORMAL);
1468                 DrawTextA (lpdis->hDC,  btnInfo->text, -1, &rcText,
1469                                DT_LEFT | DT_VCENTER | DT_SINGLELINE);
1470
1471                 /* delete objects and reset colors */
1472                 SelectObject (lpdis->hDC, hOldBrush);
1473                 SelectObject (lpdis->hDC, hOldPen);
1474                 SetBkColor (lpdis->hDC, oldBk);
1475                 SetTextColor (lpdis->hDC, oldText);
1476
1477                 return TRUE;
1478             }
1479             return FALSE;
1480
1481         case WM_MEASUREITEM:
1482             if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
1483             {
1484                 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
1485
1486                 if (custInfo && custInfo->tbInfo)
1487                     lpmis->itemHeight = custInfo->tbInfo->nBitmapHeight + 8;
1488                 else
1489                     lpmis->itemHeight = 15 + 8; /* default height */
1490
1491                 return TRUE;
1492             }
1493             return FALSE;
1494
1495         default:
1496             return FALSE;
1497     }
1498 }
1499
1500
1501 /***********************************************************************
1502  * TOOLBAR_AddBitmap:  Add the bitmaps to the default image list.
1503  *
1504  */
1505 static LRESULT
1506 TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
1507 {
1508     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1509     LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1510     INT nIndex = 0, nButtons, nCount;
1511     HBITMAP hbmLoad;
1512
1513     TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1514     if (!lpAddBmp)
1515         return -1;
1516
1517     if (lpAddBmp->hInst == HINST_COMMCTRL)
1518     {
1519         if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
1520             nButtons = 15;
1521         else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
1522             nButtons = 13;
1523         else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
1524             nButtons = 5;
1525         else
1526             return -1;
1527
1528         TRACE ("adding %d internal bitmaps!\n", nButtons);
1529
1530         /* Windows resize all the buttons to the size of a newly added standard image */
1531         if (lpAddBmp->nID & 1) 
1532         {
1533             /* large icons */
1534             /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap 
1535              * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this 
1536              */
1537             SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1538                           MAKELPARAM((WORD)24, (WORD)24));
1539             SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1540                           MAKELPARAM((WORD)31, (WORD)30));
1541         }       
1542         else 
1543         {
1544             /* small icons */
1545             SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1546                           MAKELPARAM((WORD)16, (WORD)16));
1547             SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1548                           MAKELPARAM((WORD)22, (WORD)22));
1549         }
1550     }
1551     else
1552     {
1553         nButtons = (INT)wParam;
1554         if (nButtons <= 0)
1555             return -1;
1556         
1557         TRACE ("adding %d bitmaps!\n", nButtons);
1558     }
1559     
1560     if (!(infoPtr->himlDef)) {
1561         /* create new default image list */
1562         TRACE ("creating default image list!\n");
1563
1564         infoPtr->himlDef =
1565             ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1566                               ILC_COLOR | ILC_MASK, nButtons, 2);
1567         infoPtr->himlInt = infoPtr->himlDef;
1568     }
1569
1570     nCount = ImageList_GetImageCount(infoPtr->himlDef);
1571
1572     /* Add bitmaps to the default image list */
1573     if (lpAddBmp->hInst == (HINSTANCE)0)
1574     {
1575         nIndex = 
1576             ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
1577                                  CLR_DEFAULT);
1578     }
1579     else if (lpAddBmp->hInst == HINST_COMMCTRL)
1580     {
1581         /* Add system bitmaps */
1582         switch (lpAddBmp->nID)
1583     {
1584             case IDB_STD_SMALL_COLOR:
1585                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1586                                        MAKEINTRESOURCEA(IDB_STD_SMALL));
1587                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1588                                               hbmLoad, CLR_DEFAULT);
1589                 DeleteObject (hbmLoad);
1590                 break;
1591
1592             case IDB_STD_LARGE_COLOR:
1593                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1594                                        MAKEINTRESOURCEA(IDB_STD_LARGE));
1595                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1596                                               hbmLoad, CLR_DEFAULT);
1597                 DeleteObject (hbmLoad);
1598                 break;
1599
1600             case IDB_VIEW_SMALL_COLOR:
1601                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1602                                        MAKEINTRESOURCEA(IDB_VIEW_SMALL));
1603                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1604                                               hbmLoad, CLR_DEFAULT);
1605                 DeleteObject (hbmLoad);
1606                 break;
1607
1608             case IDB_VIEW_LARGE_COLOR:
1609                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1610                                        MAKEINTRESOURCEA(IDB_VIEW_LARGE));
1611                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1612                                               hbmLoad, CLR_DEFAULT);
1613                 DeleteObject (hbmLoad);
1614                 break;
1615
1616             case IDB_HIST_SMALL_COLOR:
1617                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1618                                        MAKEINTRESOURCEA(IDB_HIST_SMALL));
1619                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1620                                               hbmLoad, CLR_DEFAULT);
1621                 DeleteObject (hbmLoad);
1622                 break;
1623
1624             case IDB_HIST_LARGE_COLOR:
1625                 hbmLoad = LoadBitmapA (COMCTL32_hModule,
1626                                        MAKEINTRESOURCEA(IDB_HIST_LARGE));
1627                 nIndex = ImageList_AddMasked (infoPtr->himlDef,
1628                                               hbmLoad, CLR_DEFAULT);
1629                 DeleteObject (hbmLoad);
1630                 break;
1631
1632             default:
1633         nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1634                 ERR ("invalid imagelist!\n");
1635                 break;
1636         }
1637     }
1638     else
1639     {
1640         hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
1641         nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
1642         DeleteObject (hbmLoad);
1643     }
1644
1645     if (nIndex != -1)
1646     {
1647        INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);
1648
1649        if (infoPtr->nNumBitmaps + nButtons != imagecount)
1650        {
1651          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",
1652               infoPtr->nNumBitmaps, nCount, imagecount - nCount,
1653               infoPtr->nNumBitmaps+nButtons,imagecount);
1654
1655          infoPtr->nNumBitmaps = imagecount;
1656        }
1657        else
1658          infoPtr->nNumBitmaps += nButtons;
1659     }
1660
1661     InvalidateRect(hwnd, NULL, FALSE);
1662
1663     return nIndex;
1664 }
1665
1666
1667 static LRESULT
1668 TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1669 {
1670     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1671     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1672     INT nOldButtons, nNewButtons, nAddButtons, nCount;
1673
1674     TRACE("adding %d buttons!\n", wParam);
1675
1676     nAddButtons = (UINT)wParam;
1677     nOldButtons = infoPtr->nNumButtons;
1678     nNewButtons = nOldButtons + nAddButtons;
1679
1680     if (infoPtr->nNumButtons == 0) {
1681         infoPtr->buttons =
1682             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1683     }
1684     else {
1685         TBUTTON_INFO *oldButtons = infoPtr->buttons;
1686         infoPtr->buttons =
1687             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1688         memcpy (&infoPtr->buttons[0], &oldButtons[0],
1689                 nOldButtons * sizeof(TBUTTON_INFO));
1690         COMCTL32_Free (oldButtons);
1691     }
1692
1693     infoPtr->nNumButtons = nNewButtons;
1694
1695     /* insert new button data */
1696     for (nCount = 0; nCount < nAddButtons; nCount++) {
1697         TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1698         btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
1699         btnPtr->idCommand = lpTbb[nCount].idCommand;
1700         btnPtr->fsState   = lpTbb[nCount].fsState;
1701         btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
1702         btnPtr->dwData    = lpTbb[nCount].dwData;
1703         btnPtr->iString   = lpTbb[nCount].iString;
1704         btnPtr->bHot      = FALSE;
1705
1706         if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1707             TTTOOLINFOA ti;
1708
1709             ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1710             ti.cbSize   = sizeof (TTTOOLINFOA);
1711             ti.hwnd     = hwnd;
1712             ti.uId      = btnPtr->idCommand;
1713             ti.hinst    = 0;
1714             ti.lpszText = LPSTR_TEXTCALLBACKA;
1715
1716             SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
1717                             0, (LPARAM)&ti);
1718         }
1719     }
1720
1721     InvalidateRect(hwnd, NULL, FALSE);
1722
1723     return TRUE;
1724 }
1725
1726
1727 static LRESULT
1728 TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1729 {
1730     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1731     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1732     INT nOldButtons, nNewButtons, nAddButtons, nCount;
1733
1734     TRACE("adding %d buttons!\n", wParam);
1735
1736     nAddButtons = (UINT)wParam;
1737     nOldButtons = infoPtr->nNumButtons;
1738     nNewButtons = nOldButtons + nAddButtons;
1739
1740     if (infoPtr->nNumButtons == 0) {
1741         infoPtr->buttons =
1742             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1743     }
1744     else {
1745         TBUTTON_INFO *oldButtons = infoPtr->buttons;
1746         infoPtr->buttons =
1747             COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
1748         memcpy (&infoPtr->buttons[0], &oldButtons[0],
1749                 nOldButtons * sizeof(TBUTTON_INFO));
1750         COMCTL32_Free (oldButtons);
1751     }
1752
1753     infoPtr->nNumButtons = nNewButtons;
1754
1755     /* insert new button data */
1756     for (nCount = 0; nCount < nAddButtons; nCount++) {
1757         TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
1758         btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
1759         btnPtr->idCommand = lpTbb[nCount].idCommand;
1760         btnPtr->fsState   = lpTbb[nCount].fsState;
1761         btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
1762         btnPtr->dwData    = lpTbb[nCount].dwData;
1763         btnPtr->iString   = lpTbb[nCount].iString;
1764         btnPtr->bHot      = FALSE;
1765
1766         if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1767             TTTOOLINFOW ti;
1768
1769             ZeroMemory (&ti, sizeof(TTTOOLINFOW));
1770             ti.cbSize   = sizeof (TTTOOLINFOW);
1771             ti.hwnd     = hwnd;
1772             ti.uId      = btnPtr->idCommand;
1773             ti.hinst    = 0;
1774             ti.lpszText = LPSTR_TEXTCALLBACKW;
1775
1776             SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
1777                             0, (LPARAM)&ti);
1778         }
1779     }
1780
1781     InvalidateRect(hwnd, NULL, FALSE);
1782
1783     return TRUE;
1784 }
1785
1786
1787 static LRESULT
1788 TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1789 {
1790     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1791     INT nIndex;
1792
1793     if ((wParam) && (HIWORD(lParam) == 0)) {
1794         char szString[256];
1795         INT len;
1796         TRACE("adding string from resource!\n");
1797
1798         len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
1799                              szString, 256);
1800
1801         TRACE("len=%d \"%s\"\n", len, szString);
1802         nIndex = infoPtr->nNumStrings;
1803         if (infoPtr->nNumStrings == 0) {
1804             infoPtr->strings =
1805                 COMCTL32_Alloc (sizeof(LPWSTR));
1806         }
1807         else {
1808             LPWSTR *oldStrings = infoPtr->strings;
1809             infoPtr->strings =
1810                 COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1811             memcpy (&infoPtr->strings[0], &oldStrings[0],
1812                     sizeof(LPWSTR) * infoPtr->nNumStrings);
1813             COMCTL32_Free (oldStrings);
1814         }
1815
1816         infoPtr->strings[infoPtr->nNumStrings] =
1817             COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1818         lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], szString);
1819         infoPtr->nNumStrings++;
1820     }
1821     else {
1822         LPSTR p = (LPSTR)lParam;
1823         INT len;
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 = lstrlenA (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             infoPtr->strings[infoPtr->nNumStrings] =
1848                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1849             lstrcpyAtoW (infoPtr->strings[infoPtr->nNumStrings], p);
1850             infoPtr->nNumStrings++;
1851
1852             p += (len+1);
1853         }
1854     }
1855
1856     return nIndex;
1857 }
1858
1859
1860 static LRESULT
1861 TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1862 {
1863 #define MAX_RESOURCE_STRING_LENGTH 512
1864     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1865     INT nIndex;
1866
1867     if ((wParam) && (HIWORD(lParam) == 0)) {
1868         WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1869         INT len;
1870         TRACE("adding string from resource!\n");
1871
1872         len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1873                              szString, MAX_RESOURCE_STRING_LENGTH);
1874
1875         TRACE("len=%d \"%s\"\n", len, debugstr_w(szString));
1876         TRACE("First char: 0x%x\n", *szString);
1877         if (szString[0] == L'|')
1878         {
1879             PWSTR p = szString + 1;
1880                 
1881             nIndex = infoPtr->nNumStrings;
1882             while (*p != L'|') {
1883
1884             if (infoPtr->nNumStrings == 0) {
1885                 infoPtr->strings =
1886                     COMCTL32_Alloc (sizeof(LPWSTR));
1887             }
1888             else {
1889                 LPWSTR *oldStrings = infoPtr->strings;
1890                 infoPtr->strings =
1891                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1892                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1893                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1894                 COMCTL32_Free (oldStrings);
1895             }
1896
1897             len = COMCTL32_StrChrW (p, L'|') - p;
1898             TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1899             infoPtr->strings[infoPtr->nNumStrings] =
1900                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1901             lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1902             infoPtr->nNumStrings++;
1903
1904                 p += (len+1);
1905             }
1906         }
1907         else
1908         {
1909             nIndex = infoPtr->nNumStrings;
1910             if (infoPtr->nNumStrings == 0) {
1911                 infoPtr->strings =
1912                     COMCTL32_Alloc (sizeof(LPWSTR));
1913             }
1914             else {
1915                 LPWSTR *oldStrings = infoPtr->strings;
1916                 infoPtr->strings =
1917                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1918                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1919                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1920                 COMCTL32_Free (oldStrings);
1921             }
1922
1923             infoPtr->strings[infoPtr->nNumStrings] =
1924                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1925             strcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1926             infoPtr->nNumStrings++;
1927         }
1928     }
1929     else {
1930         LPWSTR p = (LPWSTR)lParam;
1931         INT len;
1932
1933         if (p == NULL)
1934             return -1;
1935         TRACE("adding string(s) from array!\n");
1936         nIndex = infoPtr->nNumStrings;
1937         while (*p) {
1938             len = lstrlenW (p);
1939
1940             TRACE("len=%d \"%s\"\n", len, debugstr_w(p));
1941             if (infoPtr->nNumStrings == 0) {
1942                 infoPtr->strings =
1943                     COMCTL32_Alloc (sizeof(LPWSTR));
1944             }
1945             else {
1946                 LPWSTR *oldStrings = infoPtr->strings;
1947                 infoPtr->strings =
1948                     COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
1949                 memcpy (&infoPtr->strings[0], &oldStrings[0],
1950                         sizeof(LPWSTR) * infoPtr->nNumStrings);
1951                 COMCTL32_Free (oldStrings);
1952             }
1953
1954             infoPtr->strings[infoPtr->nNumStrings] =
1955                 COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1956             strcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1957             infoPtr->nNumStrings++;
1958
1959             p += (len+1);
1960         }
1961     }
1962
1963     return nIndex;
1964 }
1965
1966
1967 static LRESULT
1968 TOOLBAR_AutoSize (HWND hwnd)
1969 {
1970     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1971     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1972     RECT parent_rect;
1973     RECT window_rect;
1974     HWND parent;
1975     INT  x, y;
1976     INT  cx, cy;
1977     UINT uPosFlags = SWP_NOZORDER;
1978
1979     TRACE("resize forced, style=%lx!\n", dwStyle);
1980
1981     parent = GetParent (hwnd);
1982     GetClientRect(parent, &parent_rect);
1983
1984     x = parent_rect.left;
1985     y = parent_rect.top;
1986
1987     /* FIXME: we should be able to early out if nothing */
1988     /* has changed with nWidth != parent_rect width */
1989
1990     if (dwStyle & CCS_NORESIZE) {
1991         uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
1992         cx = 0;
1993         cy = 0;
1994     }
1995     else {
1996         infoPtr->nWidth = parent_rect.right - parent_rect.left;
1997         InvalidateRect( hwnd, NULL, TRUE );
1998         cy = infoPtr->nHeight;
1999         cx = infoPtr->nWidth;
2000
2001         if (dwStyle & CCS_NOMOVEY) {
2002                 GetWindowRect(hwnd, &window_rect);
2003                 ScreenToClient(parent, (LPPOINT)&window_rect.left);
2004                 y = window_rect.top;
2005         }
2006     }
2007
2008     if (dwStyle & CCS_NOPARENTALIGN)
2009         uPosFlags |= SWP_NOMOVE;
2010
2011     if (!(dwStyle & CCS_NODIVIDER))
2012         cy += GetSystemMetrics(SM_CYEDGE);
2013
2014     if (dwStyle & WS_BORDER)
2015     {
2016         x = y = 1;
2017         cy += GetSystemMetrics(SM_CYEDGE);
2018         cx += GetSystemMetrics(SM_CYEDGE);
2019     }
2020
2021     infoPtr->bAutoSize = TRUE;
2022     SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
2023                         cx, cy, uPosFlags);
2024     /* The following line makes sure that the infoPtr->bAutoSize is turned off after
2025      * the setwindowpos calls */
2026     infoPtr->bAutoSize = FALSE;
2027
2028     return 0;
2029 }
2030
2031
2032 static LRESULT
2033 TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
2034 {
2035     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2036
2037     return infoPtr->nNumButtons;
2038 }
2039
2040
2041 static LRESULT
2042 TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
2043 {
2044     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2045
2046     if (infoPtr == NULL) {
2047         ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
2048         ERR("infoPtr == NULL!\n");
2049         return 0;
2050     }
2051
2052     infoPtr->dwStructSize = (DWORD)wParam;
2053
2054     return 0;
2055 }
2056
2057
2058 static LRESULT
2059 TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2060 {
2061     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2062     TBUTTON_INFO *btnPtr;
2063     INT nIndex;
2064
2065     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2066     if (nIndex == -1)
2067         return FALSE;
2068
2069     btnPtr = &infoPtr->buttons[nIndex];
2070     btnPtr->iBitmap = LOWORD(lParam);
2071
2072     /* we HAVE to erase the background, the new bitmap could be */
2073     /* transparent */
2074     InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2075
2076     return TRUE;
2077 }
2078
2079
2080 static LRESULT
2081 TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2082 {
2083     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2084     TBUTTON_INFO *btnPtr;
2085     INT nIndex;
2086     INT nOldIndex = -1;
2087     BOOL bChecked = FALSE;
2088
2089     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2090     if (nIndex == -1)
2091         return FALSE;
2092
2093     btnPtr = &infoPtr->buttons[nIndex];
2094
2095     if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
2096         return FALSE;
2097
2098     bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;
2099
2100     if (LOWORD(lParam) == FALSE)
2101         btnPtr->fsState &= ~TBSTATE_CHECKED;
2102     else {
2103         if (btnPtr->fsStyle & TBSTYLE_GROUP) {
2104             nOldIndex = 
2105                 TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
2106             if (nOldIndex == nIndex)
2107                 return 0;
2108             if (nOldIndex != -1)
2109                 infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
2110         }
2111         btnPtr->fsState |= TBSTATE_CHECKED;
2112     }
2113
2114     if( bChecked != LOWORD(lParam) )
2115     {
2116         if (nOldIndex != -1)
2117         {
2118             InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
2119                 TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
2120         }
2121         InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2122     }
2123
2124     /* FIXME: Send a WM_NOTIFY?? */
2125
2126     return TRUE;
2127 }
2128
2129
2130 static LRESULT
2131 TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
2132 {
2133     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2134
2135     return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2136 }
2137
2138
2139 static LRESULT
2140 TOOLBAR_Customize (HWND hwnd)
2141 {
2142     CUSTDLG_INFO custInfo;
2143     LRESULT ret;
2144     LPCVOID template;
2145     HRSRC hRes;
2146     NMHDR nmhdr;
2147
2148     custInfo.tbInfo = TOOLBAR_GetInfoPtr (hwnd);
2149     custInfo.tbHwnd = hwnd;
2150
2151     /* send TBN_BEGINADJUST notification */
2152     nmhdr.hwndFrom = hwnd;
2153     nmhdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
2154     nmhdr.code     = TBN_BEGINADJUST;
2155
2156     SendMessageA (custInfo.tbInfo->hwndNotify, WM_NOTIFY,
2157                   (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
2158
2159     if (!(hRes = FindResourceA (COMCTL32_hModule,
2160                                 MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
2161                                 RT_DIALOGA)))
2162         return FALSE;
2163
2164     if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
2165         return FALSE;
2166
2167     ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
2168                                    (LPDLGTEMPLATEA)template,
2169                                    hwnd,
2170                                    (DLGPROC)TOOLBAR_CustomizeDialogProc,
2171                                    (LPARAM)&custInfo);
2172
2173     /* send TBN_ENDADJUST notification */
2174     nmhdr.code = TBN_ENDADJUST;
2175     SendMessageA (custInfo.tbInfo->hwndNotify, WM_NOTIFY,
2176                   (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
2177
2178     return ret;
2179 }
2180
2181
2182 static LRESULT
2183 TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2184 {
2185     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2186     INT nIndex = (INT)wParam;
2187
2188     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2189         return FALSE;
2190
2191     if ((infoPtr->hwndToolTip) && 
2192         !(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
2193         TTTOOLINFOA ti;
2194
2195         ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2196         ti.cbSize   = sizeof (TTTOOLINFOA);
2197         ti.hwnd     = hwnd;
2198         ti.uId      = infoPtr->buttons[nIndex].idCommand;
2199
2200         SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
2201     }
2202
2203     if (infoPtr->nNumButtons == 1) {
2204         TRACE(" simple delete!\n");
2205         COMCTL32_Free (infoPtr->buttons);
2206         infoPtr->buttons = NULL;
2207         infoPtr->nNumButtons = 0;
2208     }
2209     else {
2210         TBUTTON_INFO *oldButtons = infoPtr->buttons;
2211         TRACE("complex delete! [nIndex=%d]\n", nIndex);
2212
2213         infoPtr->nNumButtons--;
2214         infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
2215         if (nIndex > 0) {
2216             memcpy (&infoPtr->buttons[0], &oldButtons[0],
2217                     nIndex * sizeof(TBUTTON_INFO));
2218         }
2219
2220         if (nIndex < infoPtr->nNumButtons) {
2221             memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
2222                     (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
2223         }
2224
2225         COMCTL32_Free (oldButtons);
2226     }
2227
2228     InvalidateRect (hwnd, NULL, TRUE);
2229
2230     return TRUE;
2231 }
2232
2233
2234 static LRESULT
2235 TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2236 {
2237     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2238     TBUTTON_INFO *btnPtr;
2239     INT nIndex;
2240     DWORD bState;
2241
2242     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2243     if (nIndex == -1)
2244         return FALSE;
2245
2246     btnPtr = &infoPtr->buttons[nIndex];
2247
2248     bState = btnPtr->fsState & TBSTATE_ENABLED;
2249
2250     /* update the toolbar button state */
2251     if(LOWORD(lParam) == FALSE) {
2252         btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
2253     } else {
2254         btnPtr->fsState |= TBSTATE_ENABLED;
2255     }
2256
2257     /* redraw the button only if the state of the button changed */
2258     if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
2259     {
2260         InvalidateRect(hwnd, &btnPtr->rect,
2261             TOOLBAR_HasText(infoPtr, btnPtr));
2262     }
2263
2264     return TRUE;
2265 }
2266
2267
2268 static inline LRESULT
2269 TOOLBAR_GetAnchorHighlight (HWND hwnd)
2270 {
2271     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2272
2273     return infoPtr->bAnchor;
2274 }
2275
2276
2277 static LRESULT
2278 TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
2279 {
2280     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2281     INT nIndex;
2282
2283     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2284     if (nIndex == -1)
2285         return -1;
2286
2287     return infoPtr->buttons[nIndex].iBitmap;
2288 }
2289
2290
2291 static inline LRESULT
2292 TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
2293 {
2294     return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
2295 }
2296
2297
2298 static LRESULT
2299 TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
2300 {
2301     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2302     LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2303     INT nIndex = (INT)wParam;
2304     TBUTTON_INFO *btnPtr;
2305
2306     if (infoPtr == NULL)
2307         return FALSE;
2308
2309     if (lpTbb == NULL)
2310         return FALSE;
2311
2312     if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
2313         return FALSE;
2314
2315     btnPtr = &infoPtr->buttons[nIndex];
2316     lpTbb->iBitmap   = btnPtr->iBitmap;
2317     lpTbb->idCommand = btnPtr->idCommand;
2318     lpTbb->fsState   = btnPtr->fsState;
2319     lpTbb->fsStyle   = btnPtr->fsStyle;
2320     lpTbb->dwData    = btnPtr->dwData;
2321     lpTbb->iString   = btnPtr->iString;
2322
2323     return TRUE;
2324 }
2325
2326
2327 static LRESULT
2328 TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2329 {
2330     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2331     LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
2332     TBUTTON_INFO *btnPtr;
2333     INT nIndex;
2334
2335     if (infoPtr == NULL)
2336         return -1;
2337     if (lpTbInfo == NULL)
2338         return -1;
2339     if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2340         return -1;
2341
2342     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2343     if (nIndex == -1)
2344         return -1;
2345
2346     btnPtr = &infoPtr->buttons[nIndex];
2347
2348     if (lpTbInfo->dwMask & TBIF_COMMAND)
2349         lpTbInfo->idCommand = btnPtr->idCommand;
2350     if (lpTbInfo->dwMask & TBIF_IMAGE)
2351         lpTbInfo->iImage = btnPtr->iBitmap;
2352     if (lpTbInfo->dwMask & TBIF_LPARAM)
2353         lpTbInfo->lParam = btnPtr->dwData;
2354     if (lpTbInfo->dwMask & TBIF_SIZE)
2355         lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2356     if (lpTbInfo->dwMask & TBIF_STATE)
2357         lpTbInfo->fsState = btnPtr->fsState;
2358     if (lpTbInfo->dwMask & TBIF_STYLE)
2359         lpTbInfo->fsStyle = btnPtr->fsStyle;
2360      if (lpTbInfo->dwMask & TBIF_TEXT) {
2361          if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
2362          {      
2363              lstrcpynWtoA (lpTbInfo->pszText,
2364                            (LPWSTR)infoPtr->strings[btnPtr->iString],
2365                            lpTbInfo->cchText);
2366          }
2367          else lpTbInfo->pszText[0]=0;
2368     }
2369     return nIndex;
2370 }
2371
2372
2373 static LRESULT
2374 TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2375 {
2376     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2377     LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
2378     TBUTTON_INFO *btnPtr;
2379     INT nIndex;
2380
2381     if (infoPtr == NULL)
2382         return -1;
2383     if (lpTbInfo == NULL)
2384         return -1;
2385     if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
2386         return -1;
2387
2388     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2389     if (nIndex == -1)
2390         return -1;
2391
2392     btnPtr = &infoPtr->buttons[nIndex];
2393
2394     if (lpTbInfo->dwMask & TBIF_COMMAND)
2395         lpTbInfo->idCommand = btnPtr->idCommand;
2396     if (lpTbInfo->dwMask & TBIF_IMAGE)
2397         lpTbInfo->iImage = btnPtr->iBitmap;
2398     if (lpTbInfo->dwMask & TBIF_LPARAM)
2399         lpTbInfo->lParam = btnPtr->dwData;
2400     if (lpTbInfo->dwMask & TBIF_SIZE)
2401         lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
2402     if (lpTbInfo->dwMask & TBIF_STATE)
2403         lpTbInfo->fsState = btnPtr->fsState;
2404     if (lpTbInfo->dwMask & TBIF_STYLE)
2405         lpTbInfo->fsStyle = btnPtr->fsStyle;
2406     if (lpTbInfo->dwMask & TBIF_TEXT) {
2407         if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
2408             lstrcpynW (lpTbInfo->pszText,
2409                        (LPWSTR)infoPtr->strings[btnPtr->iString],
2410                        lpTbInfo->cchText);
2411     }
2412
2413     return nIndex;
2414 }
2415
2416
2417 static LRESULT
2418 TOOLBAR_GetButtonSize (HWND hwnd)
2419 {
2420     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2421
2422     return MAKELONG((WORD)infoPtr->nButtonWidth,
2423                     (WORD)infoPtr->nButtonHeight);
2424 }
2425
2426
2427 static LRESULT
2428 TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
2429 {
2430     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2431     INT nIndex, nStringIndex;
2432
2433     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2434     if (nIndex == -1)
2435         return -1;
2436
2437     nStringIndex = infoPtr->buttons[nIndex].iString;
2438
2439     TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
2440
2441     if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
2442         return -1;
2443
2444     if (lParam == 0)
2445         return -1;
2446
2447     lstrcpyWtoA ((LPSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
2448
2449     return lstrlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
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 lstrlenW ((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 = lstrlenA((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 FALSE;
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