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