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