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