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