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