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