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