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