toolbar.c 123 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3
/*
 * Toolbar control
 *
4
 * Copyright 1998,1999 Eric Kohl
5
 * Copyright 2000 Eric Kohl for CodeWeavers
Alexandre Julliard's avatar
Alexandre Julliard committed
6 7
 *
 * TODO:
8 9
 *   - A little bug in TOOLBAR_DrawMasked()
 *   - Button wrapping (under construction).
Alexandre Julliard's avatar
Alexandre Julliard committed
10
 *   - Messages.
11
 *   - Notifications (under construction).
12
 *   - Fix TB_SETROWS.
Alexandre Julliard's avatar
Alexandre Julliard committed
13
 *   - Tooltip support (almost complete).
14 15
 *   - Unicode suppport (under construction).
 *   - Fix TOOLBAR_SetButtonInfo32A/W.
16 17
 *   - TBSTYLE_AUTOSIZE for toolbar and buttons.
 *   - I_IMAGECALLBACK support.
18
 *   - iString of -1 is undocumented
19 20 21 22 23 24 25
 *   - Customization dialog:
 *      - Add flat look.
 *      - Minor buglet in 'available buttons' list:
 *        Buttons are not listed in M$-like order. M$ seems to use a single
 *        internal list to store the button information of both listboxes.
 *      - Drag list support.
 *      - Help and Reset button support.
Alexandre Julliard's avatar
Alexandre Julliard committed
26 27 28 29 30 31 32 33
 *
 * Testing:
 *   - Run tests using Waite Group Windows95 API Bible Volume 2.
 *     The second cdrom contains executables addstr.exe, btncount.exe,
 *     btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
 *     enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
 *     indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
 *     setparnt.exe, setrows.exe, toolwnd.exe.
Alexandre Julliard's avatar
Alexandre Julliard committed
34
 *   - Microsofts controlspy examples.
35
 *   - Charles Petzold's 'Programming Windows': gadgets.exe
Alexandre Julliard's avatar
Alexandre Julliard committed
36 37
 */

38 39
#include <string.h>

40
#include "winbase.h"
41 42
#include "windef.h"
#include "wingdi.h"
43
#include "winuser.h"
44
#include "wine/unicode.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
45
#include "commctrl.h"
46
#include "imagelist.h"
47
#include "comctl32.h"
48
#include "debugtools.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
49

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
DEFAULT_DEBUG_CHANNEL(toolbar);

typedef struct
{
    INT iBitmap;
    INT idCommand;
    BYTE  fsState;
    BYTE  fsStyle;
    DWORD dwData;
    INT iString;

    BOOL bHot;
    INT nRow;
    RECT rect;
} TBUTTON_INFO; 

typedef struct
{
    DWORD      dwStructSize;   /* size of TBBUTTON struct */
    INT      nHeight;        /* height of the toolbar */
    INT      nWidth;         /* width of the toolbar */
    INT      nButtonHeight;
    INT      nButtonWidth;
    INT      nBitmapHeight;
    INT      nBitmapWidth;
    INT      nIndent;
    INT      nRows;           /* number of button rows */
    INT      nMaxTextRows;    /* maximum number of text rows */
    INT      cxMin;           /* minimum button width */
    INT      cxMax;           /* maximum button width */
    INT      nNumButtons;     /* number of buttons */
    INT      nNumBitmaps;     /* number of bitmaps */
    INT      nNumStrings;     /* number of strings */
    BOOL     bUnicode;        /* ASCII (FALSE) or Unicode (TRUE)? */
    BOOL     bCaptured;       /* mouse captured? */
    INT      nButtonDown;
    INT      nOldHit;
    INT      nHotItem;        /* index of the "hot" item */
    HFONT    hFont;           /* text font */
    HIMAGELIST himlInt;         /* image list created internally */
    HIMAGELIST himlDef;         /* default image list */
    HIMAGELIST himlHot;         /* hot image list */
    HIMAGELIST himlDis;         /* disabled image list */
    HWND     hwndToolTip;     /* handle to tool tip control */
    HWND     hwndNotify;      /* handle to the window that gets notifications */
    BOOL     bTransparent;    /* background transparency flag */
    BOOL     bAutoSize;       /* auto size deadlock indicator */
    BOOL     bAnchor;         /* anchor highlight enabled */
    DWORD      dwExStyle;       /* extended toolbar style */
    DWORD      dwDTFlags;       /* DrawText flags */

    COLORREF   clrInsertMark;   /* insert mark color */
    RECT     rcBound;         /* bounding rectangle */
    INT      iVersion;

    TBUTTON_INFO *buttons;      /* pointer to button array */
    LPWSTR       *strings;      /* pointer to string array */
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
} TOOLBAR_INFO, *PTOOLBAR_INFO;


/* used by customization dialog */
typedef struct
{
    PTOOLBAR_INFO tbInfo;
    HWND          tbHwnd;
} CUSTDLG_INFO, *PCUSTDLG_INFO;

typedef struct
{
    TBBUTTON btn;
    BOOL     bVirtual;
    BOOL     bRemovable;
    CHAR     text[64];
} CUSTOMBUTTON, *PCUSTOMBUTTON;

125

Alexandre Julliard's avatar
Alexandre Julliard committed
126 127 128
#define SEPARATOR_WIDTH    8
#define TOP_BORDER         2
#define BOTTOM_BORDER      2
129
#define DDARROW_WIDTH      11 
Alexandre Julliard's avatar
Alexandre Julliard committed
130

131
#define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongA(hwnd,0))
132
#define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE)
133
#define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE)
134 135 136 137 138 139 140 141 142 143 144 145 146 147

static LPWSTR
TOOLBAR_GetText(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
{
    LPWSTR lpText = NULL;

    /* FIXME: iString == -1 is undocumented */
    if ((HIWORD(btnPtr->iString) != 0) && (btnPtr->iString != -1))
        lpText = (LPWSTR)btnPtr->iString;
    else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
        lpText = infoPtr->strings[btnPtr->iString];
    
    return lpText;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
148

149 150 151 152 153 154 155 156 157
static BOOL 
TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index)
{
    if ((index>=0) && (index < infoPtr->nNumBitmaps))
      return TRUE;
    else
      return FALSE;
}

158

Alexandre Julliard's avatar
Alexandre Julliard committed
159
static void
160
TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc)
Alexandre Julliard's avatar
Alexandre Julliard committed
161
{
162 163 164
    INT x = (lpRect->left + lpRect->right) / 2 - 1;
    INT yBottom = lpRect->bottom - 3;
    INT yTop = lpRect->top + 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
165

166 167 168
    SelectObject ( hdc, GetSysColorPen (COLOR_3DSHADOW));
    MoveToEx (hdc, x, yBottom, NULL);
    LineTo (hdc, x, yTop);
Alexandre Julliard's avatar
Alexandre Julliard committed
169
    x++;
170 171 172
    SelectObject ( hdc, GetSysColorPen (COLOR_3DHILIGHT));
    MoveToEx (hdc, x, yBottom, NULL);
    LineTo (hdc, x, yTop);
Alexandre Julliard's avatar
Alexandre Julliard committed
173 174
}

175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
static void
TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, INT colorRef)
{
    INT x, y;
    SelectObject ( hdc, GetSysColorPen (colorRef));
    x = left + 2;
    y = top + 8;
    MoveToEx (hdc, x, y, NULL);
    LineTo (hdc, x+5, y++); x++;
    MoveToEx (hdc, x, y, NULL);
    LineTo (hdc, x+3, y++); x++;
    MoveToEx (hdc, x, y, NULL);
    LineTo (hdc, x+1, y++);
}

190 191
/*
 * Draw the text string for this button.
192 193 194
 * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
 * 	is non-zero, so we can simply check himlDef to see if we have
 *      an image list
195
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
196 197
static void
TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
198
		    HDC hdc, INT nState, DWORD dwStyle)
Alexandre Julliard's avatar
Alexandre Julliard committed
199
{
200 201 202
    RECT   rcText = btnPtr->rect;
    HFONT  hOldFont;
    INT    nOldBkMode;
Alexandre Julliard's avatar
Alexandre Julliard committed
203
    COLORREF clrOld;
204
    LPWSTR lpText = NULL;
205
    HIMAGELIST himl = infoPtr->himlDef;
206

207
    TRACE ("iString: %x\n", btnPtr->iString);
208 209

    /* get a pointer to the text */
210
    lpText = TOOLBAR_GetText(infoPtr, btnPtr);
211

212
    TRACE ("lpText: %s\n", debugstr_w(lpText));
Alexandre Julliard's avatar
Alexandre Julliard committed
213 214

    /* draw text */
215
    if (lpText) {
216

217
	InflateRect (&rcText, -3, -3);
218

219
	if (himl && TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
220 221 222
		if ((dwStyle & TBSTYLE_LIST) &&
		    ((btnPtr->fsStyle & TBSTYLE_AUTOSIZE) == 0) &&
		    (btnPtr->iBitmap != I_IMAGENONE)) {
223 224 225 226 227
		    rcText.left += infoPtr->nBitmapWidth;
		}
		else {
		    rcText.top += infoPtr->nBitmapHeight;
		}
228
	}
229

Alexandre Julliard's avatar
Alexandre Julliard committed
230
	if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
231
	    OffsetRect (&rcText, 1, 1);
Alexandre Julliard's avatar
Alexandre Julliard committed
232

233 234
	hOldFont = SelectObject (hdc, infoPtr->hFont);
	nOldBkMode = SetBkMode (hdc, TRANSPARENT);
Alexandre Julliard's avatar
Alexandre Julliard committed
235
	if (!(nState & TBSTATE_ENABLED)) {
236 237
	    clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DHILIGHT));
	    OffsetRect (&rcText, 1, 1);
238
	    DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
239 240
	    SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
	    OffsetRect (&rcText, -1, -1);
241
	    DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
Alexandre Julliard's avatar
Alexandre Julliard committed
242 243
	}
	else if (nState & TBSTATE_INDETERMINATE) {
244
	    clrOld = SetTextColor (hdc, GetSysColor (COLOR_3DSHADOW));
245
	    DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
Alexandre Julliard's avatar
Alexandre Julliard committed
246 247
	}
	else {
248
	    clrOld = SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
249
	    DrawTextW (hdc, lpText, -1, &rcText, infoPtr->dwDTFlags);
Alexandre Julliard's avatar
Alexandre Julliard committed
250 251
	}

252 253
	SetTextColor (hdc, clrOld);
	SelectObject (hdc, hOldFont);
Alexandre Julliard's avatar
Alexandre Julliard committed
254
	if (nOldBkMode != TRANSPARENT)
255
	    SetBkMode (hdc, nOldBkMode);
Alexandre Julliard's avatar
Alexandre Julliard committed
256 257 258 259
    }
}


Alexandre Julliard's avatar
Alexandre Julliard committed
260
static void
261
TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect)
Alexandre Julliard's avatar
Alexandre Julliard committed
262
{
263
    HBRUSH hbr = SelectObject (hdc, COMCTL32_hPattern55AABrush);
264 265 266 267
    INT cx = lpRect->right - lpRect->left;
    INT cy = lpRect->bottom - lpRect->top;
    PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
    SelectObject (hdc, hbr);
Alexandre Julliard's avatar
Alexandre Julliard committed
268 269 270 271 272
}


static void
TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
273
		    HDC hdc, INT x, INT y)
Alexandre Julliard's avatar
Alexandre Julliard committed
274 275 276 277
{
    /* FIXME: this function is a hack since it uses image list
	      internals directly */

278
    HIMAGELIST himl = infoPtr->himlDef;
279
    HBITMAP hbmMask;
280 281 282 283 284 285 286 287 288
    HDC hdcImageList;
    HDC hdcMask;

    if (!himl)
	return;

    /* create new dc's */
    hdcImageList = CreateCompatibleDC (0);
    hdcMask = CreateCompatibleDC (0);
Alexandre Julliard's avatar
Alexandre Julliard committed
289

290
    /* create new bitmap */
291 292
    hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
    SelectObject (hdcMask, hbmMask);
293 294

    /* copy the mask bitmap */
295 296 297 298
    SelectObject (hdcImageList, himl->hbmMask);
    SetBkColor (hdcImageList, RGB(255, 255, 255));
    SetTextColor (hdcImageList, RGB(0, 0, 0));
    BitBlt (hdcMask, 0, 0, himl->cx, himl->cy,
299 300 301
	      hdcImageList, himl->cx * btnPtr->iBitmap, 0, SRCCOPY);

    /* draw the new mask */
302 303
    SelectObject (hdc, GetSysColorBrush (COLOR_3DHILIGHT));
    BitBlt (hdc, x+1, y+1, himl->cx, himl->cy,
304
	      hdcMask, 0, 0, 0xB8074A);
Alexandre Julliard's avatar
Alexandre Julliard committed
305

306 307
    SelectObject (hdc, GetSysColorBrush (COLOR_3DSHADOW));
    BitBlt (hdc, x, y, himl->cx, himl->cy,
308
	      hdcMask, 0, 0, 0xB8074A);
Alexandre Julliard's avatar
Alexandre Julliard committed
309

310 311 312
    DeleteObject (hbmMask);
    DeleteDC (hdcMask);
    DeleteDC (hdcImageList);
Alexandre Julliard's avatar
Alexandre Julliard committed
313 314 315
}


Alexandre Julliard's avatar
Alexandre Julliard committed
316
static void
317
TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
Alexandre Julliard's avatar
Alexandre Julliard committed
318
{
319 320
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
321 322
    BOOL hasDropDownArrow = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
	                    (btnPtr->fsStyle & TBSTYLE_DROPDOWN);
323
    RECT rc, rcArrow, rcBitmap;
Alexandre Julliard's avatar
Alexandre Julliard committed
324

325 326
    if (btnPtr->fsState & TBSTATE_HIDDEN)
	return;
Alexandre Julliard's avatar
Alexandre Julliard committed
327 328

    rc = btnPtr->rect;
329
    CopyRect (&rcArrow, &rc);
330
    CopyRect(&rcBitmap, &rc);
331 332 333 334 335 336 337 338 339 340 341

    FillRect( hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));

    if (hasDropDownArrow)
    {
	if (dwStyle & TBSTYLE_FLAT)
            rc.right = max(rc.left, rc.right - DDARROW_WIDTH);
	else
            rc.right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
	rcArrow.left = rc.right; 
    }
342

343 344 345 346 347 348 349
    /* Center the bitmap horizontally and vertically */
    rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2;

    if(TOOLBAR_HasText(infoPtr, btnPtr))
        rcBitmap.top+=2; /* this looks to be the correct value from vmware comparison - cmm */
    else
        rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2;
350

351 352
    TRACE("iBitmap: %d\n", btnPtr->iBitmap);

353
    /* separator */
Alexandre Julliard's avatar
Alexandre Julliard committed
354
    if (btnPtr->fsStyle & TBSTYLE_SEP) {
355 356 357 358 359 360
        /* with the FLAT style, iBitmap is the width and has already */
        /* been taken into consideration in calculating the width    */
        /* so now we need to draw the vertical separator             */
        /* empirical tests show that iBitmap can/will be non-zero    */
        /* when drawing the vertical bar...      */
        if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */)
361
	    TOOLBAR_DrawFlatSeparator (&rc, hdc);
Alexandre Julliard's avatar
Alexandre Julliard committed
362 363
	return;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
364

Alexandre Julliard's avatar
Alexandre Julliard committed
365 366
    /* disabled */
    if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
367
	if (!(dwStyle & TBSTYLE_FLAT))
368
	{
369 370
	    DrawEdge (hdc, &rc, EDGE_RAISED,
		      BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
371 372 373 374
            if (hasDropDownArrow)
            DrawEdge (hdc, &rcArrow, EDGE_RAISED,
		      BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
	}
375
	
376 377 378 379 380 381
        if (hasDropDownArrow)
	{
	    TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1, COLOR_3DHIGHLIGHT);
	    TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_3DSHADOW);
	}

382 383
	if (infoPtr->himlDis && 
            TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
384
	    ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
385
			rcBitmap.left, rcBitmap.top, ILD_NORMAL);
386
	else
387
	    TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
Alexandre Julliard's avatar
Alexandre Julliard committed
388

389
	TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
Alexandre Julliard's avatar
Alexandre Julliard committed
390
	return;
Alexandre Julliard's avatar
Alexandre Julliard committed
391 392
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
393 394
    /* pressed TBSTYLE_BUTTON */
    if (btnPtr->fsState & TBSTATE_PRESSED) {
395
	if (dwStyle & TBSTYLE_FLAT)
396
	{
397
	    DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
398 399 400
            if (hasDropDownArrow)
	    DrawEdge (hdc, &rcArrow, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE | BF_ADJUST);
	}
401
	else
402
	{
403
	    DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
404 405 406 407 408 409 410
            if (hasDropDownArrow)
	    DrawEdge (hdc, &rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_ADJUST);
	}

        if (hasDropDownArrow)
	    TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);

411
        if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
412
	    ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
413
			rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
414

415
	TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
Alexandre Julliard's avatar
Alexandre Julliard committed
416 417
	return;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
418

419
    /* checked TBSTYLE_CHECK */
Alexandre Julliard's avatar
Alexandre Julliard committed
420 421
    if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
	(btnPtr->fsState & TBSTATE_CHECKED)) {
422
	if (dwStyle & TBSTYLE_FLAT)
423
	    DrawEdge (hdc, &rc, BDR_SUNKENOUTER,
Alexandre Julliard's avatar
Alexandre Julliard committed
424 425
			BF_RECT | BF_MIDDLE | BF_ADJUST);
	else
426
	    DrawEdge (hdc, &rc, EDGE_SUNKEN,
Alexandre Julliard's avatar
Alexandre Julliard committed
427
			BF_RECT | BF_MIDDLE | BF_ADJUST);
Alexandre Julliard's avatar
Alexandre Julliard committed
428

Alexandre Julliard's avatar
Alexandre Julliard committed
429
	TOOLBAR_DrawPattern (hdc, &rc);
430
        
431
        if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
432
	    ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
433
			rcBitmap.left + 1, rcBitmap.top + 1, ILD_NORMAL);
434
	TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
Alexandre Julliard's avatar
Alexandre Julliard committed
435 436
	return;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
437

Alexandre Julliard's avatar
Alexandre Julliard committed
438 439
    /* indeterminate */	
    if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
440
	DrawEdge (hdc, &rc, EDGE_RAISED,
Alexandre Julliard's avatar
Alexandre Julliard committed
441
		    BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
Alexandre Julliard's avatar
Alexandre Julliard committed
442

Alexandre Julliard's avatar
Alexandre Julliard committed
443
	TOOLBAR_DrawPattern (hdc, &rc);
444
	TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top);
445
	TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
Alexandre Julliard's avatar
Alexandre Julliard committed
446
	return;
Alexandre Julliard's avatar
Alexandre Julliard committed
447
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
448

449
    /* normal state */
450 451
    if (dwStyle & TBSTYLE_FLAT)
    {
452
	if (btnPtr->bHot)
453
	{
454
	    DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
455 456 457
            if (hasDropDownArrow)
	    DrawEdge (hdc, &rcArrow, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE);
	}
458
        else
459
	{
460
            FrameRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE));
461 462 463 464 465 466
            if (hasDropDownArrow)
            FrameRect(hdc, &rcArrow, GetSysColorBrush(COLOR_BTNFACE));
	}

        if (hasDropDownArrow)
	    TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top, COLOR_WINDOWFRAME);
467

468
	if (btnPtr->bHot && infoPtr->himlHot &&
469
            TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
470
	    ImageList_Draw (infoPtr->himlHot, btnPtr->iBitmap, hdc,
471
			rcBitmap.left, rcBitmap.top, ILD_NORMAL);
472
	else if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
473
	    ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
474
			rcBitmap.left, rcBitmap.top, ILD_NORMAL);
475
    }
476 477 478
    else
    {
	DrawEdge (hdc, &rc, EDGE_RAISED,
Alexandre Julliard's avatar
Alexandre Julliard committed
479
		BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
480

481 482 483 484 485 486 487
        if (hasDropDownArrow)
	{
	    DrawEdge (hdc, &rcArrow, EDGE_RAISED,
		    BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
	    TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top, COLOR_WINDOWFRAME);
	}

488
        if (TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap))
489
	    ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
490
			rcBitmap.left, rcBitmap.top, ILD_NORMAL);
491
    }
492

493
    TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState, dwStyle);
Alexandre Julliard's avatar
Alexandre Julliard committed
494 495 496 497
}


static void
498
TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
Alexandre Julliard's avatar
Alexandre Julliard committed
499
{
500
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
501
    TBUTTON_INFO *btnPtr;
502
    INT i;
503
    RECT rcTemp;
Alexandre Julliard's avatar
Alexandre Julliard committed
504

505 506 507 508
    /* if imagelist belongs to the app, it can be changed
       by the app after setting it */
    if (infoPtr->himlDef != infoPtr->himlInt)
        infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
509
    /* redraw necessary buttons */
Alexandre Julliard's avatar
Alexandre Julliard committed
510
    btnPtr = infoPtr->buttons;
Alexandre Julliard's avatar
Alexandre Julliard committed
511
    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
512 513 514 515
    {
        if(IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)))
            TOOLBAR_DrawButton (hwnd, btnPtr, hdc);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
516 517
}

Alexandre Julliard's avatar
Alexandre Julliard committed
518
static void
519
TOOLBAR_MeasureString(HWND hwnd, INT index, LPSIZE lpSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
520
{
521
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
522
    TBUTTON_INFO *btnPtr;
523 524
    HDC hdc;
    HFONT hOldFont;
525

Alexandre Julliard's avatar
Alexandre Julliard committed
526 527
    lpSize->cx = 0;
    lpSize->cy = 0;
528 529
    hdc = GetDC (0);
    hOldFont = SelectObject (hdc, infoPtr->hFont);
Alexandre Julliard's avatar
Alexandre Julliard committed
530

531 532 533 534 535 536 537
    btnPtr = &infoPtr->buttons[index];

    if (!(btnPtr->fsState & TBSTATE_HIDDEN) &&
         (btnPtr->iString > -1) &&
         (btnPtr->iString < infoPtr->nNumStrings)) 
    {
        LPWSTR lpText = infoPtr->strings[btnPtr->iString];
538
        GetTextExtentPoint32W (hdc, lpText, strlenW (lpText), lpSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
539 540
    }

541 542
    SelectObject (hdc, hOldFont);
    ReleaseDC (0, hdc);
Alexandre Julliard's avatar
Alexandre Julliard committed
543

544
    TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
Alexandre Julliard's avatar
Alexandre Julliard committed
545 546
}

547 548 549 550 551 552 553 554 555 556 557 558 559 560
static void
TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    TBUTTON_INFO *btnPtr;
    INT i;
    SIZE sz;


    lpSize->cx = 0;
    lpSize->cy = 0;

    btnPtr = infoPtr->buttons;
    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
561 562 563 564 565 566 567 568
        if(TOOLBAR_HasText(infoPtr, btnPtr))
        {
            TOOLBAR_MeasureString(hwnd,i,&sz);
            if (sz.cx > lpSize->cx)
                lpSize->cx = sz.cx;
            if (sz.cy > lpSize->cy)
                lpSize->cy = sz.cy;
        }
569 570
    }

571
    TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy);
572 573
}

574 575 576 577 578 579 580 581 582 583 584
/***********************************************************************
* 		TOOLBAR_WrapToolbar
*
* This function walks through the buttons and seperators in the 
* toolbar, and sets the TBSTATE_WRAP flag only on those items where 
* wrapping should occur based on the width of the toolbar window.  
* It does *not* calculate button placement itself.  That task 
* takes place in TOOLBAR_CalcToolbar. If the program wants to manage 
* the toolbar wrapping on it's own, it can use the TBSTYLE_WRAPPABLE 
* flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
*/ 
Alexandre Julliard's avatar
Alexandre Julliard committed
585

Alexandre Julliard's avatar
Alexandre Julliard committed
586
static void
587
TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle )
Alexandre Julliard's avatar
Alexandre Julliard committed
588
{
589
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
590 591 592 593 594 595 596 597 598 599 600 601 602 603
    TBUTTON_INFO *btnPtr;
    INT x, cx, i, j;
    RECT rc;
    BOOL bWrap, bButtonWrap;

    /* 	When the toolbar window style is not TBSTYLE_WRAPABLE,	*/ 
    /*	no layout is necessary. Applications may use this style */
    /*	to perform their own layout on the toolbar. 		*/
    if( !(dwStyle & TBSTYLE_WRAPABLE) )
	return;

    btnPtr = infoPtr->buttons;
    x  = infoPtr->nIndent;

604 605 606 607
    /* this can get the parents width, to know how far we can extend
     * this toolbar.  We cannot use its height, as there may be multiple
     * toolbars in a rebar control
     */
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
    GetClientRect( GetParent(hwnd), &rc );
    infoPtr->nWidth = rc.right - rc.left;
    bButtonWrap = FALSE;

    for (i = 0; i < infoPtr->nNumButtons; i++ )
    {
	bWrap = FALSE;
	btnPtr[i].fsState &= ~TBSTATE_WRAP;
	
	if (btnPtr[i].fsState & TBSTATE_HIDDEN)
	    continue;

	/* UNDOCUMENTED: If a separator has a non zero bitmap index, */
	/* it is the actual width of the separator. This is used for */
	/* custom controls in toolbars.                              */
	if (btnPtr[i].fsStyle & TBSTYLE_SEP)
	    cx = (btnPtr[i].iBitmap > 0) ?  
			btnPtr[i].iBitmap : SEPARATOR_WIDTH;
	else
	    cx = infoPtr->nButtonWidth;

	/* Two or more adjacent separators form a separator group.   */ 
	/* The first separator in a group should be wrapped to the   */
	/* next row if the previous wrapping is on a button.	     */
	if( bButtonWrap &&
		(btnPtr[i].fsStyle & TBSTYLE_SEP) && 
		(i + 1 < infoPtr->nNumButtons ) &&
		(btnPtr[i + 1].fsStyle & TBSTYLE_SEP) ) 
	{
	    btnPtr[i].fsState |= TBSTATE_WRAP;
	    x = infoPtr->nIndent;
	    i++;
	    bButtonWrap = FALSE;
	    continue;
	}

	/* The layout makes sure the bitmap is visible, but not the button. */
	if ( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2 
		 > infoPtr->nWidth ) 
	{
	    BOOL bFound = FALSE;

	    /* 	If the current button is a separator and not hidden,  */ 
	    /*	go to the next until it reaches a non separator.      */
	    /*	Wrap the last separator if it is before a button.     */
	    while( ( (btnPtr[i].fsStyle & TBSTYLE_SEP) || 
			(btnPtr[i].fsState & TBSTATE_HIDDEN) ) && 
			i < infoPtr->nNumButtons )
	    {
		i++;
		bFound = TRUE;
	    }
    
	    if( bFound && i < infoPtr->nNumButtons )
	    {
		i--;
		btnPtr[i].fsState |= TBSTATE_WRAP;
		x = infoPtr->nIndent;
		bButtonWrap = FALSE;
		continue;
	    }
	    else if ( i >= infoPtr->nNumButtons)
		break;

	    /* 	If the current button is not a separator, find the last  */ 
	    /*	separator and wrap it.   				 */
	    for ( j = i - 1; j >= 0  &&  !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
	    {
		if ((btnPtr[j].fsStyle & TBSTYLE_SEP) &&
			!(btnPtr[j].fsState & TBSTATE_HIDDEN))
		{
		    bFound = TRUE; 
		    i = j; 
		    x = infoPtr->nIndent;
		    btnPtr[j].fsState |= TBSTATE_WRAP;
		    bButtonWrap = FALSE; 
		    break;
		}
	    }

	    /* 	If no separator available for wrapping, wrap one of 	*/
	    /*  non-hidden previous button.  			     	*/
	    if (!bFound)
	    {
		for ( j = i - 1; 
			j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
		{
		    if (btnPtr[j].fsState & TBSTATE_HIDDEN) 
			continue;

		    bFound = TRUE; 
		    i = j; 
		    x = infoPtr->nIndent;
		    btnPtr[j].fsState |= TBSTATE_WRAP;
		    bButtonWrap = TRUE;
		    break;
		}
	    }

	    /* If all above failed, wrap the current button. */
	    if (!bFound)  
	    {
		btnPtr[i].fsState |= TBSTATE_WRAP;
		bFound = TRUE;
		x = infoPtr->nIndent;
		if (btnPtr[i].fsState & TBSTYLE_SEP )
		    bButtonWrap = FALSE;
		else
		    bButtonWrap = TRUE;
	    }		    
	}
	else
	    x += cx;
    }
}
723 724


725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
/***********************************************************************
* 		TOOLBAR_CalcToolbar
*
* This function calculates button and separator placement. It first 
* calculates the button sizes, gets the toolbar window width and then 
* calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap 
* on. It assigns a new location to each item and sends this location to
* the tooltip window if appropriate. Finally, it updates the rcBound 
* rect and calculates the new required toolbar window height. 
*/  

static void
TOOLBAR_CalcToolbar (HWND hwnd)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
740
    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
741
    TBUTTON_INFO *btnPtr;
742
    INT i, nRows, nSepRows;
743 744
    INT x, y, cx, cy;
    SIZE  sizeString;
745
    BOOL bWrap;
746
    BOOL usesBitmaps = FALSE;
747
    BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
Alexandre Julliard's avatar
Alexandre Julliard committed
748

749
    TOOLBAR_CalcStrings (hwnd, &sizeString);
Alexandre Julliard's avatar
Alexandre Julliard committed
750

751 752
    if (dwStyle & TBSTYLE_LIST)
    {
753 754 755 756
	infoPtr->nButtonHeight = max(infoPtr->nBitmapHeight, sizeString.cy) + 6;
	infoPtr->nButtonWidth = infoPtr->nBitmapWidth + sizeString.cx + 6;
    }
    else {
757 758 759 760 761
        for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
        {
	    if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
	        usesBitmaps = TRUE;
        }
762

763 764 765 766 767 768 769 770 771 772
        if (sizeString.cy > 0)
        {
            if (usesBitmaps)
	      infoPtr->nButtonHeight = sizeString.cy +
                  infoPtr->nBitmapHeight + 6;
            else 
                infoPtr->nButtonHeight = sizeString.cy + 6;
        }
        else if (infoPtr->nButtonHeight < infoPtr->nBitmapHeight + 6)
	    infoPtr->nButtonHeight = infoPtr->nBitmapHeight + 6;
Alexandre Julliard's avatar
Alexandre Julliard committed
773

774 775 776 777
        if (sizeString.cx > infoPtr->nBitmapWidth)
	    infoPtr->nButtonWidth = sizeString.cx + 6;
        else if (infoPtr->nButtonWidth < infoPtr->nBitmapWidth + 6)
	    infoPtr->nButtonWidth = infoPtr->nBitmapWidth + 6;
778
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
779

780 781 782 783 784
    if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
        infoPtr->nButtonWidth = infoPtr->cxMin;
    if ( infoPtr->cxMax >= 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
        infoPtr->nButtonWidth = infoPtr->cxMax;

785
    TOOLBAR_WrapToolbar( hwnd, dwStyle );
786

Alexandre Julliard's avatar
Alexandre Julliard committed
787
    x  = infoPtr->nIndent;
788
    y  = (dwStyle & TBSTYLE_FLAT) ? 0 : TOP_BORDER;
789

790
   /*
791
    * We will set the height below, and we set the width on entry 
792 793 794
    * so we do not reset them here.. 
    */
#if 0
795 796 797 798
    GetClientRect( hwnd, &rc );
    /* get initial values for toolbar */
    infoPtr->nWidth  = rc.right - rc.left;
    infoPtr->nHeight = rc.bottom - rc.top;
799
#endif
800 801

    /* from above, minimum is a button, and possible text */
Alexandre Julliard's avatar
Alexandre Julliard committed
802
    cx = infoPtr->nButtonWidth;
803

804
    /* cannot use just ButtonHeight, we may have no buttons! */
805
    if (infoPtr->nNumButtons > 0)
806 807
        infoPtr->nHeight = infoPtr->nButtonHeight;

808 809
    cy = infoPtr->nHeight;

810
    nRows = nSepRows = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
811 812 813 814 815

    infoPtr->rcBound.top = y;
    infoPtr->rcBound.left = x;
    infoPtr->rcBound.bottom = y + cy;
    infoPtr->rcBound.right = x;
Alexandre Julliard's avatar
Alexandre Julliard committed
816 817

    btnPtr = infoPtr->buttons;
818 819 820 821 822 823

    /* do not base height/width on parent, if the parent is a */
    /* rebar control it could have multiple rows of toolbars  */
/*    GetClientRect( GetParent(hwnd), &rc ); */
/*    cx = rc.right - rc.left; */
/*    cy = rc.bottom - rc.top; */
Alexandre Julliard's avatar
Alexandre Julliard committed
824

825 826 827 828 829
    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
    {
	bWrap = FALSE;
	if (btnPtr->fsState & TBSTATE_HIDDEN)
	{
830
	    SetRectEmpty (&btnPtr->rect);
Alexandre Julliard's avatar
Alexandre Julliard committed
831
	    continue;
832 833 834 835 836
	}

	    /* UNDOCUMENTED: If a separator has a non zero bitmap index, */
	    /* it is the actual width of the separator. This is used for */
	    /* custom controls in toolbars.                              */
837
	if (btnPtr->fsStyle & TBSTYLE_SEP)
838 839
		cx = (btnPtr->iBitmap > 0) ?
		     btnPtr->iBitmap : SEPARATOR_WIDTH;
840 841
	else
	{
842 843 844 845 846 847 848 849
            if (btnPtr->fsStyle & TBSTYLE_AUTOSIZE) 
            {
              SIZE sz;
              TOOLBAR_MeasureString(hwnd,i,&sz);
              cx = sz.cx + 6;
            }
            else
	      cx = infoPtr->nButtonWidth;
850 851 852

	    if (hasDropDownArrows && (btnPtr->fsStyle & TBSTYLE_DROPDOWN))
	      cx += DDARROW_WIDTH; 
853 854
	}
	cy = infoPtr->nHeight;
855

856
	if (btnPtr->fsState & TBSTATE_WRAP )
857 858
		    bWrap = TRUE;

859
	SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
Alexandre Julliard's avatar
Alexandre Julliard committed
860

Alexandre Julliard's avatar
Alexandre Julliard committed
861 862 863 864 865 866
	if (infoPtr->rcBound.left > x)
	    infoPtr->rcBound.left = x;
	if (infoPtr->rcBound.right < x + cx)
	    infoPtr->rcBound.right = x + cx;
	if (infoPtr->rcBound.bottom < y + cy)
	    infoPtr->rcBound.bottom = y + cy;
Alexandre Julliard's avatar
Alexandre Julliard committed
867

868 869 870
	/* Set the toolTip only for non-hidden, non-separator button */
	if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & TBSTYLE_SEP )) 
	{
871
	    TTTOOLINFOA ti;
Alexandre Julliard's avatar
Alexandre Julliard committed
872

873 874
	    ZeroMemory (&ti, sizeof(TTTOOLINFOA));
	    ti.cbSize = sizeof(TTTOOLINFOA);
875
	    ti.hwnd = hwnd;
Alexandre Julliard's avatar
Alexandre Julliard committed
876 877
	    ti.uId = btnPtr->idCommand;
	    ti.rect = btnPtr->rect;
878
	    SendMessageA (infoPtr->hwndToolTip, TTM_NEWTOOLRECTA,
Alexandre Julliard's avatar
Alexandre Julliard committed
879 880 881
			    0, (LPARAM)&ti);
	}

882 883 884 885 886 887
	/* btnPtr->nRow is zero based. The space between the rows is 	*/
	/* also considered as a row. 					*/
	btnPtr->nRow = nRows + nSepRows;
	if( bWrap )
	{
	    if ( !(btnPtr->fsStyle & TBSTYLE_SEP) )
888
	        y += cy;
889 890 891 892 893 894 895 896 897 898 899 900 901
	    else 
	    {   
		/* UNDOCUMENTED: If a separator has a non zero bitmap index, */
		/* it is the actual width of the separator. This is used for */
		/* custom controls in toolbars. 			     */
		y += cy + ( (btnPtr->iBitmap > 0 ) ? 
			btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3; 
	     
		/* nSepRows is used to calculate the extra height follwoing  */ 	 
		/* the last row.					     */
		nSepRows++;
	    }
	    x = infoPtr->nIndent;
Alexandre Julliard's avatar
Alexandre Julliard committed
902 903
		nRows++;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
904
	else
Alexandre Julliard's avatar
Alexandre Julliard committed
905
	    x += cx;
Alexandre Julliard's avatar
Alexandre Julliard committed
906
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
907

908 909 910 911 912 913
    /* infoPtr->nRows is the number of rows on the toolbar */
    infoPtr->nRows = nRows + nSepRows + 1;

    /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following 	*/
    /* the last row. 							*/
    infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight + 
914
		       	nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
915 916
			nSepRows * (infoPtr->nBitmapHeight + 1) + 
			BOTTOM_BORDER; 
917
    TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
Alexandre Julliard's avatar
Alexandre Julliard committed
918 919 920
}


921
static INT
922
TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt)
Alexandre Julliard's avatar
Alexandre Julliard committed
923
{
924
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
925
    TBUTTON_INFO *btnPtr;
926
    INT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
927 928
    
    btnPtr = infoPtr->buttons;
Alexandre Julliard's avatar
Alexandre Julliard committed
929
    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
Alexandre Julliard's avatar
Alexandre Julliard committed
930 931 932
	if (btnPtr->fsState & TBSTATE_HIDDEN)
	    continue;

Alexandre Julliard's avatar
Alexandre Julliard committed
933
	if (btnPtr->fsStyle & TBSTYLE_SEP) {
934
	    if (PtInRect (&btnPtr->rect, *lpPt)) {
935
		TRACE(" ON SEPARATOR %d!\n", i);
Alexandre Julliard's avatar
Alexandre Julliard committed
936 937 938 939
		return -i;
	    }
	}
	else {
940
	    if (PtInRect (&btnPtr->rect, *lpPt)) {
941
		TRACE(" ON BUTTON %d!\n", i);
Alexandre Julliard's avatar
Alexandre Julliard committed
942 943 944 945 946
		return i;
	    }
	}
    }

947
    TRACE(" NOWHERE!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
948 949 950 951
    return -1;
}


952 953
static INT
TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand)
Alexandre Julliard's avatar
Alexandre Julliard committed
954 955
{
    TBUTTON_INFO *btnPtr;
956
    INT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
957 958

    btnPtr = infoPtr->buttons;
Alexandre Julliard's avatar
Alexandre Julliard committed
959
    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
Alexandre Julliard's avatar
Alexandre Julliard committed
960
	if (btnPtr->idCommand == idCommand) {
961
	    TRACE("command=%d index=%d\n", idCommand, i);
Alexandre Julliard's avatar
Alexandre Julliard committed
962
	    return i;
Alexandre Julliard's avatar
Alexandre Julliard committed
963
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
964
    }
965
    TRACE("no index found for command=%d\n", idCommand);
Alexandre Julliard's avatar
Alexandre Julliard committed
966 967 968 969
    return -1;
}


970 971
static INT
TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex)
Alexandre Julliard's avatar
Alexandre Julliard committed
972 973
{
    TBUTTON_INFO *btnPtr;
974
    INT nRunIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011

    if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
	return -1;

    /* check index button */
    btnPtr = &infoPtr->buttons[nIndex];
    if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
	if (btnPtr->fsState & TBSTATE_CHECKED)
	    return nIndex;
    }

    /* check previous buttons */
    nRunIndex = nIndex - 1;
    while (nRunIndex >= 0) {
	btnPtr = &infoPtr->buttons[nRunIndex];
	if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
	    if (btnPtr->fsState & TBSTATE_CHECKED)
		return nRunIndex;
	}
	else
	    break;
	nRunIndex--;
    }

    /* check next buttons */
    nRunIndex = nIndex + 1;
    while (nRunIndex < infoPtr->nNumButtons) {
	btnPtr = &infoPtr->buttons[nRunIndex];	
	if ((btnPtr->fsStyle & TBSTYLE_CHECKGROUP) == TBSTYLE_CHECKGROUP) {
	    if (btnPtr->fsState & TBSTATE_CHECKED)
		return nRunIndex;
	}
	else
	    break;
	nRunIndex++;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
1012 1013 1014 1015
    return -1;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1016
static VOID
1017 1018
TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
		    WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1019
{
1020
    MSG msg;
Alexandre Julliard's avatar
Alexandre Julliard committed
1021 1022 1023 1024 1025 1026 1027 1028 1029

    msg.hwnd = hwndMsg;
    msg.message = uMsg;
    msg.wParam = wParam;
    msg.lParam = lParam;
    msg.time = GetMessageTime ();
    msg.pt.x = LOWORD(GetMessagePos ());
    msg.pt.y = HIWORD(GetMessagePos ());

1030
    SendMessageA (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
Alexandre Julliard's avatar
Alexandre Julliard committed
1031 1032
}

1033 1034 1035 1036 1037

/***********************************************************************
 * TOOLBAR_CustomizeDialogProc
 * This function implements the toolbar customization dialog.
 */
1038
static BOOL WINAPI
1039 1040
TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
1041 1042 1043
    PCUSTDLG_INFO custInfo = (PCUSTDLG_INFO)GetWindowLongA (hwnd, DWL_USER);
    PCUSTOMBUTTON btnInfo;
    NMTOOLBARA nmtb;
1044 1045 1046 1047

    switch (uMsg)
    {
	case WM_INITDIALOG:
1048 1049
	    custInfo = (PCUSTDLG_INFO)lParam;
	    SetWindowLongA (hwnd, DWL_USER, (DWORD)custInfo);
1050

1051
	    if (custInfo)
1052
	    {
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
		char Buffer[256];
		int i = 0;
		int index;

		/* send TBN_QUERYINSERT notification */
		nmtb.hdr.hwndFrom = hwnd;
		nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
		nmtb.hdr.code     = TBN_QUERYINSERT;
		nmtb.iItem = custInfo->tbInfo->nNumButtons;

		if (!SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
				   (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
		    return FALSE;

		/* add items to 'toolbar buttons' list and check if removable */
		for (i = 0; i < custInfo->tbInfo->nNumButtons; i++)
1069
		{
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
		    btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
		    memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
		    btnInfo->btn.fsStyle = TBSTYLE_SEP;
		    btnInfo->bVirtual = FALSE;
		    LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);

		    /* send TBN_QUERYDELETE notification */
		    nmtb.hdr.hwndFrom = hwnd;
		    nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
		    nmtb.hdr.code     = TBN_QUERYDELETE;
		    nmtb.iItem = i;

		    btnInfo->bRemovable = SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
							(WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);

		    index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, 0);
		    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
		}
1088

1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
		/* insert separator button into 'available buttons' list */
		btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
		memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
		btnInfo->btn.fsStyle = TBSTYLE_SEP;
		btnInfo->bVirtual = FALSE;
		btnInfo->bRemovable = TRUE;
		LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
		index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
		SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);

		/* insert all buttons into dsa */
		for (i = 0;; i++)
		{
		    /* send TBN_GETBUTTONINFO notification */
		    nmtb.hdr.hwndFrom = hwnd;
		    nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
		    nmtb.hdr.code     = TBN_GETBUTTONINFOA;
		    nmtb.iItem = i;
		    nmtb.pszText = Buffer;
		    nmtb.cchText = 256;

		    if (!SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
				       (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
			break;

		    TRACE("style: %x\n", nmtb.tbButton.fsStyle);		

		    /* insert button into the apropriate list */
		    index = TOOLBAR_GetButtonIndex (custInfo->tbInfo, nmtb.tbButton.idCommand);
		    if (index == -1)
1119
		    {
1120 1121 1122 1123 1124 1125 1126 1127 1128
			btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
			memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
			btnInfo->bVirtual = FALSE;
			btnInfo->bRemovable = TRUE;
			if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
			    strcpy (btnInfo->text, nmtb.pszText);

			index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
			SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1129 1130 1131
		    }
		    else
		    {
1132 1133 1134 1135 1136 1137
			btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
			memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON));
			if (!(nmtb.tbButton.fsStyle & TBSTYLE_SEP))
			    strcpy (btnInfo->text, nmtb.pszText);

			SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
1138 1139 1140
		    }
		}

1141 1142 1143
		/* select first item in the 'available' list */
		SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, 0, 0);

1144
		/* append 'virtual' separator button to the 'toolbar buttons' list */
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
		btnInfo = (PCUSTOMBUTTON)COMCTL32_Alloc(sizeof(CUSTOMBUTTON));
		memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
		btnInfo->btn.fsStyle = TBSTYLE_SEP;
		btnInfo->bVirtual = TRUE;
		btnInfo->bRemovable = FALSE;
		LoadStringA (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
		index = (int)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
		SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);

		/* select last item in the 'toolbar' list */
		SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index, 0);
		SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETTOPINDEX, index, 0);

		/* set focus and disable buttons */
		PostMessageA (hwnd, WM_USER, 0, 0);
1160 1161 1162
	    }
	    return TRUE;

1163 1164 1165 1166 1167 1168 1169
	case WM_USER:
	    EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
	    EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
	    EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), FALSE);
	    SetFocus (GetDlgItem (hwnd, IDC_TOOLBARBTN_LBOX));
	    return TRUE;

1170 1171 1172 1173 1174 1175 1176
	case WM_CLOSE:
	    EndDialog(hwnd, FALSE);
	    return TRUE;

	case WM_COMMAND:
	    switch (LOWORD(wParam))
	    {
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386
		case IDC_TOOLBARBTN_LBOX:
		    if (HIWORD(wParam) == LBN_SELCHANGE)
		    {
			PCUSTOMBUTTON btnInfo;
			NMTOOLBARA nmtb;
			int count;
			int index;

			count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
			index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);

			/* send TBN_QUERYINSERT notification */
			nmtb.hdr.hwndFrom = hwnd;
			nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
			nmtb.hdr.code     = TBN_QUERYINSERT;
			nmtb.iItem = index;

			SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
				      (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);

			/* get list box item */
			btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);

			if (index == (count - 1))
			{
			    /* last item (virtual separator) */
			    EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
			    EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
			}
			else if (index == (count - 2))
			{
			    /* second last item (last non-virtual item) */
			    EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
			    EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
			}
			else if (index == 0)
			{
			    /* first item */
			    EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
			    EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
			}
			else
			{
			    EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
			    EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
			}

			EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), btnInfo->bRemovable);
		    }
		    break;

		case IDC_MOVEUP_BTN:
		    {
			PCUSTOMBUTTON btnInfo;
			int index;
			int count;

			count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
			index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
			TRACE("Move up: index %d\n", index);

			/* send TBN_QUERYINSERT notification */
			nmtb.hdr.hwndFrom = hwnd;
			nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
			nmtb.hdr.code     = TBN_QUERYINSERT;
			nmtb.iItem = index;

			if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
					  (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
			{
			    btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);

			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index-1, 0);
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index-1, (LPARAM)btnInfo);
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index-1 , 0);

			    if (index <= 1)
				EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
			    else if (index >= (count - 3))
				EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);

			    SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
			    SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index-1, (LPARAM)&(btnInfo->btn));
			}
		    }
		    break;

		case IDC_MOVEDN_BTN: /* move down */
		    {
			PCUSTOMBUTTON btnInfo;
			int index;
			int count;

			count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
			index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
			TRACE("Move up: index %d\n", index);

			/* send TBN_QUERYINSERT notification */
			nmtb.hdr.hwndFrom = hwnd;
			nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
			nmtb.hdr.code     = TBN_QUERYINSERT;
			nmtb.iItem = index;

			if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
					  (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
			{
			    btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);

			    /* move button down */
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index+1, 0);
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index+1, (LPARAM)btnInfo);
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index+1 , 0);

			    if (index == 0)
				EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
			    else if (index >= (count - 3))
				EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);

			    SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
			    SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index+1, (LPARAM)&(btnInfo->btn));
			}
		    }
		    break;

		case IDC_REMOVE_BTN: /* remove button */
		    {
			PCUSTOMBUTTON btnInfo;
			int index;

			index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
			TRACE("Remove: index %d\n", index);

			/* send TBN_QUERYDELETE notification */
			nmtb.hdr.hwndFrom = hwnd;
			nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
			nmtb.hdr.code     = TBN_QUERYDELETE;
			nmtb.iItem = index;

			if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
					  (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
			{
			    btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_DELETESTRING, index, 0);
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index , 0);

			    SendMessageA (custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);

			    /* insert into 'available button' list */
			    if (!(btnInfo->btn.fsStyle & TBSTYLE_SEP))
			    {
				index = (int)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, 0);
				SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
			    }
			    else
				COMCTL32_Free (btnInfo);
			}
		    }
		    break;

		case IDOK: /* Add button */
		    {
			int index;
			int count;

			count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
			index = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0);
			TRACE("Add: index %d\n", index);

			/* send TBN_QUERYINSERT notification */
			nmtb.hdr.hwndFrom = hwnd;
			nmtb.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
			nmtb.hdr.code     = TBN_QUERYINSERT;
			nmtb.iItem = index;

			if (SendMessageA (custInfo->tbInfo->hwndNotify, WM_NOTIFY,
					  (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb))
			{
			    btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, index, 0);

			    if (index != 0)
			    {
				/* remove from 'available buttons' list */
				SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_DELETESTRING, index, 0);
				if (index == count-1)
				    SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index-1 , 0);
				else
				    SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, index , 0);
			    }
			    else
			    {
				PCUSTOMBUTTON btnNew;

				/* duplicate 'separator' button */
				btnNew = (PCUSTOMBUTTON)COMCTL32_Alloc (sizeof(CUSTOMBUTTON));
				memcpy (btnNew, btnInfo, sizeof(CUSTOMBUTTON));
				btnInfo = btnNew;
			    }

			    /* insert into 'toolbar button' list */
			    index = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_INSERTSTRING, index, 0);
			    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);

			    SendMessageA (custInfo->tbHwnd, TB_INSERTBUTTONA, index, (LPARAM)&(btnInfo->btn));
			}
		    }
		    break;

1387 1388 1389 1390 1391 1392 1393
		case IDCANCEL:
		    EndDialog(hwnd, FALSE);
		    break;
	    }
	    return TRUE;

	case WM_DESTROY:
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
	    {
		int count;
		int i;

		/* delete items from 'toolbar buttons' listbox*/
		count = SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
		for (i = 0; i < count; i++)
		{
		    btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, i, 0);
		    COMCTL32_Free(btnInfo);
		    SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, 0, 0);
		}
		SendDlgItemMessageA (hwnd, IDC_TOOLBARBTN_LBOX, LB_RESETCONTENT, 0, 0);


		/* delete items from 'available buttons' listbox*/
		count = SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
		for (i = 0; i < count; i++)
		{
		    btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, i, 0);
		    COMCTL32_Free(btnInfo);
		    SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, i, 0);
		}
		SendDlgItemMessageA (hwnd, IDC_AVAILBTN_LBOX, LB_RESETCONTENT, 0, 0);
            }
1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431
	    return TRUE;

	case WM_DRAWITEM:
	    if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
	    {
		LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
		RECT rcButton;
		RECT rcText;
		HPEN hOldPen;
		HBRUSH hOldBrush;
		COLORREF oldText = 0;
		COLORREF oldBk = 0;

1432 1433 1434
		/* get item data */
		btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageA (hwnd, wParam, LB_GETITEMDATA, (WPARAM)lpdis->itemID, 0);
		if (btnInfo == NULL)
1435
		{
1436 1437
		    FIXME("btnInfo invalid!\n");
		    return TRUE;
1438 1439
		}

1440 1441 1442 1443 1444 1445
		/* set colors and select objects */
		oldBk = SetBkColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
		if (btnInfo->bVirtual)
		   oldText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
		else
		   oldText = SetTextColor (lpdis->hDC, GetSysColor((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHTTEXT:COLOR_WINDOWTEXT));
1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
		hOldPen = SelectObject (lpdis->hDC, GetSysColorPen ((lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW));
		hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));

		/* fill background rectangle */
		Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
			   lpdis->rcItem.right, lpdis->rcItem.bottom);

		/* calculate button and text rectangles */
		CopyRect (&rcButton, &lpdis->rcItem);
		InflateRect (&rcButton, -1, -1);
		CopyRect (&rcText, &rcButton);
1457
		rcButton.right = rcButton.left + custInfo->tbInfo->nBitmapWidth + 6;
1458 1459 1460 1461 1462 1463 1464 1465 1466
		rcText.left = rcButton.right + 2;

		/* draw focus rectangle */
		if (lpdis->itemState & ODS_FOCUS)
		    DrawFocusRect (lpdis->hDC, &lpdis->rcItem);

		/* draw button */
		DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);

1467
		/* draw image and text */
1468 1469 1470 1471
		if ((btnInfo->btn.fsStyle & TBSTYLE_SEP) == 0)
		    ImageList_Draw (custInfo->tbInfo->himlDef, btnInfo->btn.iBitmap, lpdis->hDC,
				    rcButton.left+3, rcButton.top+3, ILD_NORMAL);
		DrawTextA (lpdis->hDC,  btnInfo->text, -1, &rcText,
1472 1473
			       DT_LEFT | DT_VCENTER | DT_SINGLELINE);

1474
		/* delete objects and reset colors */
1475 1476
		SelectObject (lpdis->hDC, hOldBrush);
		SelectObject (lpdis->hDC, hOldPen);
1477 1478
		SetBkColor (lpdis->hDC, oldBk);
		SetTextColor (lpdis->hDC, oldText);
1479 1480 1481 1482 1483 1484 1485 1486 1487 1488

		return TRUE;
	    }
	    return FALSE;

	case WM_MEASUREITEM:
	    if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
	    {
		MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;

1489 1490
		if (custInfo && custInfo->tbInfo)
		    lpmis->itemHeight = custInfo->tbInfo->nBitmapHeight + 8;
1491
		else
1492
		    lpmis->itemHeight = 15 + 8; /* default height */
1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503

		return TRUE;
	    }
	    return FALSE;

	default:
	    return FALSE;
    }
}


1504 1505 1506 1507
/***********************************************************************
 * TOOLBAR_AddBitmap:  Add the bitmaps to the default image list.
 *
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
1508
static LRESULT
1509
TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1510
{
1511
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1512
    LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam;
1513
    INT nIndex = 0, nButtons, nCount;
1514
    HBITMAP hbmLoad;
Alexandre Julliard's avatar
Alexandre Julliard committed
1515

1516
    TRACE("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
1517
    if (!lpAddBmp)
Alexandre Julliard's avatar
Alexandre Julliard committed
1518 1519
	return -1;

1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
    if (lpAddBmp->hInst == HINST_COMMCTRL)
    {
	if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR)
	    nButtons = 15;
	else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR)
	    nButtons = 13;
	else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR)
	    nButtons = 5;
	else
	    return -1;
1530

1531
	TRACE ("adding %d internal bitmaps!\n", nButtons);
1532

1533
	/* Windows resize all the buttons to the size of a newly added standard image */
1534
	if (lpAddBmp->nID & 1) 
1535
	{
1536
	    /* large icons */
1537 1538 1539
	    /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap 
             * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this 
             */
1540
	    SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
1541
			  MAKELPARAM((WORD)24, (WORD)24));
1542
	    SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
1543
			  MAKELPARAM((WORD)31, (WORD)30));
1544 1545 1546 1547 1548 1549 1550 1551
	}	
	else 
	{
	    /* small icons */
	    SendMessageA (hwnd, TB_SETBITMAPSIZE, 0,
			  MAKELPARAM((WORD)16, (WORD)16));
	    SendMessageA (hwnd, TB_SETBUTTONSIZE, 0,
			  MAKELPARAM((WORD)22, (WORD)22));
1552
	}
1553 1554
	
	TOOLBAR_CalcToolbar (hwnd);
1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567
    }
    else
    {
	nButtons = (INT)wParam;
	if (nButtons <= 0)
	    return -1;
	
	TRACE ("adding %d bitmaps!\n", nButtons);
    }
    
    if (!(infoPtr->himlDef)) {
	/* create new default image list */
	TRACE ("creating default image list!\n");
1568

1569
	infoPtr->himlDef =
1570
	    ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
1571 1572
			      ILC_COLOR | ILC_MASK, nButtons, 2);
	infoPtr->himlInt = infoPtr->himlDef;
Alexandre Julliard's avatar
Alexandre Julliard committed
1573 1574
    }

1575 1576
    nCount = ImageList_GetImageCount(infoPtr->himlDef);

1577 1578 1579
    /* Add bitmaps to the default image list */
    if (lpAddBmp->hInst == (HINSTANCE)0)
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
1580
	nIndex = 
1581
	    ImageList_AddMasked (infoPtr->himlDef, (HBITMAP)lpAddBmp->nID,
Alexandre Julliard's avatar
Alexandre Julliard committed
1582
				 CLR_DEFAULT);
Alexandre Julliard's avatar
Alexandre Julliard committed
1583
    }
1584 1585
    else if (lpAddBmp->hInst == HINST_COMMCTRL)
    {
1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
	/* Add system bitmaps */
	switch (lpAddBmp->nID)
    {
	    case IDB_STD_SMALL_COLOR:
		hbmLoad = LoadBitmapA (COMCTL32_hModule,
				       MAKEINTRESOURCEA(IDB_STD_SMALL));
		nIndex = ImageList_AddMasked (infoPtr->himlDef,
					      hbmLoad, CLR_DEFAULT);
		DeleteObject (hbmLoad);
		break;

	    case IDB_STD_LARGE_COLOR:
		hbmLoad = LoadBitmapA (COMCTL32_hModule,
				       MAKEINTRESOURCEA(IDB_STD_LARGE));
		nIndex = ImageList_AddMasked (infoPtr->himlDef,
					      hbmLoad, CLR_DEFAULT);
		DeleteObject (hbmLoad);
		break;

	    case IDB_VIEW_SMALL_COLOR:
		hbmLoad = LoadBitmapA (COMCTL32_hModule,
				       MAKEINTRESOURCEA(IDB_VIEW_SMALL));
		nIndex = ImageList_AddMasked (infoPtr->himlDef,
					      hbmLoad, CLR_DEFAULT);
		DeleteObject (hbmLoad);
		break;

	    case IDB_VIEW_LARGE_COLOR:
		hbmLoad = LoadBitmapA (COMCTL32_hModule,
				       MAKEINTRESOURCEA(IDB_VIEW_LARGE));
		nIndex = ImageList_AddMasked (infoPtr->himlDef,
					      hbmLoad, CLR_DEFAULT);
		DeleteObject (hbmLoad);
		break;

	    case IDB_HIST_SMALL_COLOR:
		hbmLoad = LoadBitmapA (COMCTL32_hModule,
				       MAKEINTRESOURCEA(IDB_HIST_SMALL));
		nIndex = ImageList_AddMasked (infoPtr->himlDef,
					      hbmLoad, CLR_DEFAULT);
		DeleteObject (hbmLoad);
		break;

	    case IDB_HIST_LARGE_COLOR:
		hbmLoad = LoadBitmapA (COMCTL32_hModule,
				       MAKEINTRESOURCEA(IDB_HIST_LARGE));
		nIndex = ImageList_AddMasked (infoPtr->himlDef,
					      hbmLoad, CLR_DEFAULT);
		DeleteObject (hbmLoad);
		break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1636

1637
	    default:
1638
	nIndex = ImageList_GetImageCount (infoPtr->himlDef);
1639 1640 1641
		ERR ("invalid imagelist!\n");
		break;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
1642
    }
1643 1644
    else
    {
1645 1646 1647
	hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
	nIndex = ImageList_AddMasked (infoPtr->himlDef, hbmLoad, CLR_DEFAULT);
	DeleteObject (hbmLoad);
Alexandre Julliard's avatar
Alexandre Julliard committed
1648 1649
    }

1650 1651 1652 1653 1654 1655
    if (nIndex != -1)
    {
       INT imagecount = ImageList_GetImageCount(infoPtr->himlDef);

       if (infoPtr->nNumBitmaps + nButtons != imagecount)
       {
1656
         WARN("Desired images do not match received images : Previous image number %i Previous images in list %i added %i expecting total %i, Images in list %i\n",
1657 1658 1659 1660 1661 1662 1663 1664
	      infoPtr->nNumBitmaps, nCount, imagecount - nCount,
	      infoPtr->nNumBitmaps+nButtons,imagecount);

	 infoPtr->nNumBitmaps = imagecount;
       }
       else
         infoPtr->nNumBitmaps += nButtons;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1665

1666 1667
    InvalidateRect(hwnd, NULL, FALSE);

Alexandre Julliard's avatar
Alexandre Julliard committed
1668
    return nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
1669 1670 1671 1672
}


static LRESULT
1673
TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1674
{
1675
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1676
    LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
1677
    INT nOldButtons, nNewButtons, nAddButtons, nCount;
Alexandre Julliard's avatar
Alexandre Julliard committed
1678

1679
    TRACE("adding %d buttons!\n", wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
1680

1681
    nAddButtons = (UINT)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
1682 1683 1684 1685 1686
    nOldButtons = infoPtr->nNumButtons;
    nNewButtons = nOldButtons + nAddButtons;

    if (infoPtr->nNumButtons == 0) {
	infoPtr->buttons =
Alexandre Julliard's avatar
Alexandre Julliard committed
1687
	    COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
Alexandre Julliard's avatar
Alexandre Julliard committed
1688 1689 1690 1691
    }
    else {
	TBUTTON_INFO *oldButtons = infoPtr->buttons;
	infoPtr->buttons =
Alexandre Julliard's avatar
Alexandre Julliard committed
1692
	    COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
Alexandre Julliard's avatar
Alexandre Julliard committed
1693 1694
	memcpy (&infoPtr->buttons[0], &oldButtons[0],
		nOldButtons * sizeof(TBUTTON_INFO));
Alexandre Julliard's avatar
Alexandre Julliard committed
1695
        COMCTL32_Free (oldButtons);
Alexandre Julliard's avatar
Alexandre Julliard committed
1696 1697 1698 1699
    }

    infoPtr->nNumButtons = nNewButtons;

Alexandre Julliard's avatar
Alexandre Julliard committed
1700
    /* insert new button data */
Alexandre Julliard's avatar
Alexandre Julliard committed
1701
    for (nCount = 0; nCount < nAddButtons; nCount++) {
Alexandre Julliard's avatar
Alexandre Julliard committed
1702 1703 1704 1705 1706 1707 1708
	TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
	btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
	btnPtr->idCommand = lpTbb[nCount].idCommand;
	btnPtr->fsState   = lpTbb[nCount].fsState;
	btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
	btnPtr->dwData    = lpTbb[nCount].dwData;
	btnPtr->iString   = lpTbb[nCount].iString;
1709
	btnPtr->bHot      = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1710 1711

	if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
1712
	    TTTOOLINFOA ti;
Alexandre Julliard's avatar
Alexandre Julliard committed
1713

1714 1715
	    ZeroMemory (&ti, sizeof(TTTOOLINFOA));
	    ti.cbSize   = sizeof (TTTOOLINFOA);
1716
	    ti.hwnd     = hwnd;
Alexandre Julliard's avatar
Alexandre Julliard committed
1717
	    ti.uId      = btnPtr->idCommand;
Alexandre Julliard's avatar
Alexandre Julliard committed
1718
	    ti.hinst    = 0;
1719
	    ti.lpszText = LPSTR_TEXTCALLBACKA;
Alexandre Julliard's avatar
Alexandre Julliard committed
1720

1721
	    SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
Alexandre Julliard's avatar
Alexandre Julliard committed
1722 1723
			    0, (LPARAM)&ti);
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
1724 1725
    }

1726 1727
    TOOLBAR_CalcToolbar (hwnd);

1728
    InvalidateRect(hwnd, NULL, FALSE);
Alexandre Julliard's avatar
Alexandre Julliard committed
1729 1730 1731 1732 1733

    return TRUE;
}


1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787
static LRESULT
TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
    INT nOldButtons, nNewButtons, nAddButtons, nCount;

    TRACE("adding %d buttons!\n", wParam);

    nAddButtons = (UINT)wParam;
    nOldButtons = infoPtr->nNumButtons;
    nNewButtons = nOldButtons + nAddButtons;

    if (infoPtr->nNumButtons == 0) {
	infoPtr->buttons =
	    COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
    }
    else {
	TBUTTON_INFO *oldButtons = infoPtr->buttons;
	infoPtr->buttons =
	    COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
	memcpy (&infoPtr->buttons[0], &oldButtons[0],
		nOldButtons * sizeof(TBUTTON_INFO));
        COMCTL32_Free (oldButtons);
    }

    infoPtr->nNumButtons = nNewButtons;

    /* insert new button data */
    for (nCount = 0; nCount < nAddButtons; nCount++) {
	TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount];
	btnPtr->iBitmap   = lpTbb[nCount].iBitmap;
	btnPtr->idCommand = lpTbb[nCount].idCommand;
	btnPtr->fsState   = lpTbb[nCount].fsState;
	btnPtr->fsStyle   = lpTbb[nCount].fsStyle;
	btnPtr->dwData    = lpTbb[nCount].dwData;
	btnPtr->iString   = lpTbb[nCount].iString;
	btnPtr->bHot      = FALSE;

	if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & TBSTYLE_SEP)) {
	    TTTOOLINFOW ti;

	    ZeroMemory (&ti, sizeof(TTTOOLINFOW));
	    ti.cbSize   = sizeof (TTTOOLINFOW);
	    ti.hwnd     = hwnd;
	    ti.uId      = btnPtr->idCommand;
	    ti.hinst    = 0;
	    ti.lpszText = LPSTR_TEXTCALLBACKW;

	    SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
			    0, (LPARAM)&ti);
	}
    }

1788 1789
    TOOLBAR_CalcToolbar (hwnd);

1790 1791 1792 1793
    InvalidateRect(hwnd, NULL, FALSE);

    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1794 1795 1796


static LRESULT
1797
TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1798
{
1799
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1800
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
1801

1802
    if ((wParam) && (HIWORD(lParam) == 0)) {
Alexandre Julliard's avatar
Alexandre Julliard committed
1803
	char szString[256];
1804
	INT len, lenW;
1805
	TRACE("adding string from resource!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1806

1807
	len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam,
Alexandre Julliard's avatar
Alexandre Julliard committed
1808 1809
			     szString, 256);

1810
	TRACE("len=%d \"%s\"\n", len, szString);
Alexandre Julliard's avatar
Alexandre Julliard committed
1811 1812 1813
	nIndex = infoPtr->nNumStrings;
	if (infoPtr->nNumStrings == 0) {
	    infoPtr->strings =
1814
		COMCTL32_Alloc (sizeof(LPWSTR));
Alexandre Julliard's avatar
Alexandre Julliard committed
1815 1816
	}
	else {
1817
	    LPWSTR *oldStrings = infoPtr->strings;
Alexandre Julliard's avatar
Alexandre Julliard committed
1818
	    infoPtr->strings =
1819
		COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
Alexandre Julliard's avatar
Alexandre Julliard committed
1820
	    memcpy (&infoPtr->strings[0], &oldStrings[0],
1821
		    sizeof(LPWSTR) * infoPtr->nNumStrings);
Alexandre Julliard's avatar
Alexandre Julliard committed
1822
	    COMCTL32_Free (oldStrings);
Alexandre Julliard's avatar
Alexandre Julliard committed
1823 1824
	}

1825 1826 1827 1828
        lenW = MultiByteToWideChar( CP_ACP, 0, szString, -1, NULL, 0 );
        infoPtr->strings[infoPtr->nNumStrings] = COMCTL32_Alloc (sizeof(WCHAR)*lenW);
        MultiByteToWideChar( CP_ACP, 0, szString, -1,
                             infoPtr->strings[infoPtr->nNumStrings], lenW );
Alexandre Julliard's avatar
Alexandre Julliard committed
1829 1830 1831
	infoPtr->nNumStrings++;
    }
    else {
1832
	LPSTR p = (LPSTR)lParam;
1833
	INT len, lenW;
Alexandre Julliard's avatar
Alexandre Julliard committed
1834

1835 1836
	if (p == NULL)
	    return -1;
1837
	TRACE("adding string(s) from array!\n");
1838

Alexandre Julliard's avatar
Alexandre Julliard committed
1839 1840
	nIndex = infoPtr->nNumStrings;
	while (*p) {
1841
	    len = strlen (p);
1842
	    TRACE("len=%d \"%s\"\n", len, p);
Alexandre Julliard's avatar
Alexandre Julliard committed
1843 1844 1845

	    if (infoPtr->nNumStrings == 0) {
		infoPtr->strings =
1846
		    COMCTL32_Alloc (sizeof(LPWSTR));
Alexandre Julliard's avatar
Alexandre Julliard committed
1847 1848
	    }
	    else {
1849
		LPWSTR *oldStrings = infoPtr->strings;
Alexandre Julliard's avatar
Alexandre Julliard committed
1850
		infoPtr->strings =
1851
		    COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
Alexandre Julliard's avatar
Alexandre Julliard committed
1852
		memcpy (&infoPtr->strings[0], &oldStrings[0],
1853
			sizeof(LPWSTR) * infoPtr->nNumStrings);
Alexandre Julliard's avatar
Alexandre Julliard committed
1854
		COMCTL32_Free (oldStrings);
Alexandre Julliard's avatar
Alexandre Julliard committed
1855 1856
	    }

1857 1858 1859 1860
            lenW = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
            infoPtr->strings[infoPtr->nNumStrings] = COMCTL32_Alloc (sizeof(WCHAR)*lenW);
            MultiByteToWideChar( CP_ACP, 0, p, -1,
                                 infoPtr->strings[infoPtr->nNumStrings], lenW );
Alexandre Julliard's avatar
Alexandre Julliard committed
1861 1862 1863 1864 1865 1866 1867 1868 1869 1870
	    infoPtr->nNumStrings++;

	    p += (len+1);
	}
    }

    return nIndex;
}


1871
static LRESULT
1872
TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1873
{
1874
#define MAX_RESOURCE_STRING_LENGTH 512
1875
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
1876
    INT nIndex;
1877 1878

    if ((wParam) && (HIWORD(lParam) == 0)) {
1879
	WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
1880
	INT len;
1881
	TRACE("adding string from resource!\n");
1882

1883
	len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
1884
			     szString, MAX_RESOURCE_STRING_LENGTH);
1885

1886
	TRACE("len=%d %s\n", len, debugstr_w(szString));
1887 1888 1889 1890 1891 1892 1893
	TRACE("First char: 0x%x\n", *szString);
	if (szString[0] == L'|')
	{
	    PWSTR p = szString + 1;
		
	    nIndex = infoPtr->nNumStrings;
	    while (*p != L'|') {
1894

1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908
	    if (infoPtr->nNumStrings == 0) {
		infoPtr->strings =
		    COMCTL32_Alloc (sizeof(LPWSTR));
	    }
	    else {
		LPWSTR *oldStrings = infoPtr->strings;
		infoPtr->strings =
		    COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
		memcpy (&infoPtr->strings[0], &oldStrings[0],
			sizeof(LPWSTR) * infoPtr->nNumStrings);
		COMCTL32_Free (oldStrings);
	    }

	    len = COMCTL32_StrChrW (p, L'|') - p;
1909
	    TRACE("len=%d %s\n", len, debugstr_w(p));
1910 1911
	    infoPtr->strings[infoPtr->nNumStrings] =
		COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1912
	    lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len);
1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935
	    infoPtr->nNumStrings++;

		p += (len+1);
	    }
	}
	else
	{
            nIndex = infoPtr->nNumStrings;
            if (infoPtr->nNumStrings == 0) {
                infoPtr->strings =
                    COMCTL32_Alloc (sizeof(LPWSTR));
            }
            else {
                LPWSTR *oldStrings = infoPtr->strings;
                infoPtr->strings =
                    COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
                memcpy (&infoPtr->strings[0], &oldStrings[0],
                        sizeof(LPWSTR) * infoPtr->nNumStrings);
                COMCTL32_Free (oldStrings);
            }

            infoPtr->strings[infoPtr->nNumStrings] =
                COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1936
            strcpyW (infoPtr->strings[infoPtr->nNumStrings], szString);
1937 1938
            infoPtr->nNumStrings++;
        }
1939 1940 1941
    }
    else {
	LPWSTR p = (LPWSTR)lParam;
1942
	INT len;
1943 1944 1945

	if (p == NULL)
	    return -1;
1946
	TRACE("adding string(s) from array!\n");
1947 1948
	nIndex = infoPtr->nNumStrings;
	while (*p) {
1949
	    len = strlenW (p);
1950

1951
	    TRACE("len=%d %s\n", len, debugstr_w(p));
1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966
	    if (infoPtr->nNumStrings == 0) {
		infoPtr->strings =
		    COMCTL32_Alloc (sizeof(LPWSTR));
	    }
	    else {
		LPWSTR *oldStrings = infoPtr->strings;
		infoPtr->strings =
		    COMCTL32_Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
		memcpy (&infoPtr->strings[0], &oldStrings[0],
			sizeof(LPWSTR) * infoPtr->nNumStrings);
		COMCTL32_Free (oldStrings);
	    }

	    infoPtr->strings[infoPtr->nNumStrings] =
		COMCTL32_Alloc (sizeof(WCHAR)*(len+1));
1967
	    strcpyW (infoPtr->strings[infoPtr->nNumStrings], p);
1968 1969 1970 1971 1972 1973 1974 1975
	    infoPtr->nNumStrings++;

	    p += (len+1);
	}
    }

    return nIndex;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1976 1977 1978


static LRESULT
1979
TOOLBAR_AutoSize (HWND hwnd)
Alexandre Julliard's avatar
Alexandre Julliard committed
1980
{
1981 1982
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1983
    RECT parent_rect;
1984
    RECT window_rect;
1985
    HWND parent;
1986
    INT  x, y;
1987
    INT  cx, cy;
1988
    UINT uPosFlags = SWP_NOZORDER;
Alexandre Julliard's avatar
Alexandre Julliard committed
1989

1990
    TRACE("resize forced, style=%lx!\n", dwStyle);
Alexandre Julliard's avatar
Alexandre Julliard committed
1991

1992
    parent = GetParent (hwnd);
1993
    GetClientRect(parent, &parent_rect);
Alexandre Julliard's avatar
Alexandre Julliard committed
1994

1995 1996 1997
    x = parent_rect.left;
    y = parent_rect.top;

1998 1999 2000
    /* FIXME: we should be able to early out if nothing */
    /* has changed with nWidth != parent_rect width */

2001
    if (dwStyle & CCS_NORESIZE) {
2002
	uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
Alexandre Julliard's avatar
Alexandre Julliard committed
2003 2004 2005 2006 2007
	cx = 0;
	cy = 0;
    }
    else {
	infoPtr->nWidth = parent_rect.right - parent_rect.left;
2008
	TOOLBAR_CalcToolbar (hwnd);
2009
	InvalidateRect( hwnd, NULL, TRUE );
Alexandre Julliard's avatar
Alexandre Julliard committed
2010 2011
	cy = infoPtr->nHeight;
	cx = infoPtr->nWidth;
2012 2013 2014 2015 2016 2017

	if (dwStyle & CCS_NOMOVEY) {
		GetWindowRect(hwnd, &window_rect);
		ScreenToClient(parent, (LPPOINT)&window_rect.left);
		y = window_rect.top;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
2018
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2019

2020
    if (dwStyle & CCS_NOPARENTALIGN)
Alexandre Julliard's avatar
Alexandre Julliard committed
2021
	uPosFlags |= SWP_NOMOVE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2022

2023
    if (!(dwStyle & CCS_NODIVIDER))
2024
	cy += GetSystemMetrics(SM_CYEDGE);
Alexandre Julliard's avatar
Alexandre Julliard committed
2025

2026 2027 2028 2029 2030 2031 2032
    if (dwStyle & WS_BORDER)
    {
        x = y = 1;
        cy += GetSystemMetrics(SM_CYEDGE);
        cx += GetSystemMetrics(SM_CYEDGE);
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
2033
    infoPtr->bAutoSize = TRUE;
2034 2035 2036 2037 2038
    SetWindowPos (hwnd, HWND_TOP, parent_rect.left - x, parent_rect.top - y,
                        cx, cy, uPosFlags);
    /* The following line makes sure that the infoPtr->bAutoSize is turned off after
     * the setwindowpos calls */
    infoPtr->bAutoSize = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2039 2040 2041

    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2042 2043 2044


static LRESULT
2045
TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2046
{
2047
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2048 2049 2050 2051 2052 2053

    return infoPtr->nNumButtons;
}


static LRESULT
2054
TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2055
{
2056
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2057

Alexandre Julliard's avatar
Alexandre Julliard committed
2058
    if (infoPtr == NULL) {
2059 2060
	ERR("(0x%x, 0x%x, 0x%lx)\n", hwnd, wParam, lParam);
	ERR("infoPtr == NULL!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
2061 2062 2063
	return 0;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
2064 2065 2066 2067 2068 2069 2070
    infoPtr->dwStructSize = (DWORD)wParam;

    return 0;
}


static LRESULT
2071
TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2072
{
2073
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2074
    TBUTTON_INFO *btnPtr;
2075
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2076

2077
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2078 2079 2080 2081 2082 2083
    if (nIndex == -1)
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];
    btnPtr->iBitmap = LOWORD(lParam);

2084 2085
    /* we HAVE to erase the background, the new bitmap could be */
    /* transparent */
2086
    InvalidateRect(hwnd, &btnPtr->rect, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
2087 2088 2089 2090 2091 2092

    return TRUE;
}


static LRESULT
2093
TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2094
{
2095
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2096
    TBUTTON_INFO *btnPtr;
2097 2098
    INT nIndex;
    INT nOldIndex = -1;
2099
    BOOL bChecked = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2100

2101
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2102 2103 2104 2105
    if (nIndex == -1)
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];
Alexandre Julliard's avatar
Alexandre Julliard committed
2106 2107 2108 2109

    if (!(btnPtr->fsStyle & TBSTYLE_CHECK))
	return FALSE;

2110 2111
    bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE;

Alexandre Julliard's avatar
Alexandre Julliard committed
2112 2113
    if (LOWORD(lParam) == FALSE)
	btnPtr->fsState &= ~TBSTATE_CHECKED;
Alexandre Julliard's avatar
Alexandre Julliard committed
2114 2115 2116 2117 2118 2119 2120 2121 2122
    else {
	if (btnPtr->fsStyle & TBSTYLE_GROUP) {
	    nOldIndex = 
		TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
	    if (nOldIndex == nIndex)
		return 0;
	    if (nOldIndex != -1)
		infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
2123
	btnPtr->fsState |= TBSTATE_CHECKED;
Alexandre Julliard's avatar
Alexandre Julliard committed
2124
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2125

2126 2127 2128
    if( bChecked != LOWORD(lParam) )
    {
	if (nOldIndex != -1)
2129 2130 2131 2132
        {
            InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
                TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
        }
2133
        InvalidateRect(hwnd, &btnPtr->rect, TRUE);
2134
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2135

Alexandre Julliard's avatar
Alexandre Julliard committed
2136
    /* FIXME: Send a WM_NOTIFY?? */
Alexandre Julliard's avatar
Alexandre Julliard committed
2137

Alexandre Julliard's avatar
Alexandre Julliard committed
2138 2139 2140 2141 2142
    return TRUE;
}


static LRESULT
2143
TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2144
{
2145
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2146

2147
    return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2148 2149 2150
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2151
static LRESULT
2152
TOOLBAR_Customize (HWND hwnd)
Alexandre Julliard's avatar
Alexandre Julliard committed
2153
{
2154
    CUSTDLG_INFO custInfo;
2155 2156 2157 2158
    LRESULT ret;
    LPCVOID template;
    HRSRC hRes;
    NMHDR nmhdr;
Alexandre Julliard's avatar
Alexandre Julliard committed
2159

2160 2161 2162
    custInfo.tbInfo = TOOLBAR_GetInfoPtr (hwnd);
    custInfo.tbHwnd = hwnd;

2163 2164 2165 2166 2167
    /* send TBN_BEGINADJUST notification */
    nmhdr.hwndFrom = hwnd;
    nmhdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
    nmhdr.code     = TBN_BEGINADJUST;

2168
    SendMessageA (custInfo.tbInfo->hwndNotify, WM_NOTIFY,
2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182
		  (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);

    if (!(hRes = FindResourceA (COMCTL32_hModule,
                                MAKEINTRESOURCEA(IDD_TBCUSTOMIZE),
                                RT_DIALOGA)))
	return FALSE;

    if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes)))
	return FALSE;

    ret = DialogBoxIndirectParamA (GetWindowLongA (hwnd, GWL_HINSTANCE),
                                   (LPDLGTEMPLATEA)template,
                                   hwnd,
                                   (DLGPROC)TOOLBAR_CustomizeDialogProc,
2183
                                   (LPARAM)&custInfo);
2184 2185 2186

    /* send TBN_ENDADJUST notification */
    nmhdr.code = TBN_ENDADJUST;
2187
    SendMessageA (custInfo.tbInfo->hwndNotify, WM_NOTIFY,
2188 2189 2190
		  (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);

    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
2191
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2192 2193 2194


static LRESULT
2195
TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2196
{
2197
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2198
    INT nIndex = (INT)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2199

Alexandre Julliard's avatar
Alexandre Julliard committed
2200
    if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
Alexandre Julliard's avatar
Alexandre Julliard committed
2201 2202
	return FALSE;

Alexandre Julliard's avatar
Alexandre Julliard committed
2203 2204
    if ((infoPtr->hwndToolTip) && 
	!(infoPtr->buttons[nIndex].fsStyle & TBSTYLE_SEP)) {
2205
	TTTOOLINFOA ti;
Alexandre Julliard's avatar
Alexandre Julliard committed
2206

2207 2208
	ZeroMemory (&ti, sizeof(TTTOOLINFOA));
	ti.cbSize   = sizeof (TTTOOLINFOA);
2209
	ti.hwnd     = hwnd;
Alexandre Julliard's avatar
Alexandre Julliard committed
2210 2211
	ti.uId      = infoPtr->buttons[nIndex].idCommand;

2212
	SendMessageA (infoPtr->hwndToolTip, TTM_DELTOOLA, 0, (LPARAM)&ti);
Alexandre Julliard's avatar
Alexandre Julliard committed
2213 2214
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
2215
    if (infoPtr->nNumButtons == 1) {
2216
	TRACE(" simple delete!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
2217
	COMCTL32_Free (infoPtr->buttons);
Alexandre Julliard's avatar
Alexandre Julliard committed
2218 2219 2220 2221
	infoPtr->buttons = NULL;
	infoPtr->nNumButtons = 0;
    }
    else {
Alexandre Julliard's avatar
Alexandre Julliard committed
2222
	TBUTTON_INFO *oldButtons = infoPtr->buttons;
2223
        TRACE("complex delete! [nIndex=%d]\n", nIndex);
Alexandre Julliard's avatar
Alexandre Julliard committed
2224

Alexandre Julliard's avatar
Alexandre Julliard committed
2225
	infoPtr->nNumButtons--;
Alexandre Julliard's avatar
Alexandre Julliard committed
2226
	infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
Alexandre Julliard's avatar
Alexandre Julliard committed
2227 2228 2229 2230
        if (nIndex > 0) {
            memcpy (&infoPtr->buttons[0], &oldButtons[0],
                    nIndex * sizeof(TBUTTON_INFO));
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
2231

Alexandre Julliard's avatar
Alexandre Julliard committed
2232 2233 2234 2235 2236
        if (nIndex < infoPtr->nNumButtons) {
            memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
                    (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
        }

Alexandre Julliard's avatar
Alexandre Julliard committed
2237
	COMCTL32_Free (oldButtons);
Alexandre Julliard's avatar
Alexandre Julliard committed
2238 2239
    }

2240 2241
    TOOLBAR_CalcToolbar (hwnd);

2242
    InvalidateRect (hwnd, NULL, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
2243 2244 2245 2246 2247 2248

    return TRUE;
}


static LRESULT
2249
TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2250
{
2251
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2252
    TBUTTON_INFO *btnPtr;
2253
    INT nIndex;
2254
    DWORD bState;
Alexandre Julliard's avatar
Alexandre Julliard committed
2255

2256
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2257 2258 2259 2260
    if (nIndex == -1)
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];
2261 2262 2263 2264 2265 2266 2267

    bState = btnPtr->fsState & TBSTATE_ENABLED;

    /* update the toolbar button state */
    if(LOWORD(lParam) == FALSE) {
 	btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
    } else {
Alexandre Julliard's avatar
Alexandre Julliard committed
2268
	btnPtr->fsState |= TBSTATE_ENABLED;
2269
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2270

2271
    /* redraw the button only if the state of the button changed */
2272
    if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
2273 2274 2275 2276
    {
        InvalidateRect(hwnd, &btnPtr->rect,
            TOOLBAR_HasText(infoPtr, btnPtr));
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2277 2278 2279 2280 2281

    return TRUE;
}


2282 2283 2284 2285 2286 2287 2288
static inline LRESULT
TOOLBAR_GetAnchorHighlight (HWND hwnd)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);

    return infoPtr->bAnchor;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2289 2290 2291


static LRESULT
2292
TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2293
{
2294
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2295
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2296

2297
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2298
    if (nIndex == -1)
Alexandre Julliard's avatar
Alexandre Julliard committed
2299
	return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
2300 2301 2302 2303 2304

    return infoPtr->buttons[nIndex].iBitmap;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
2305
static inline LRESULT
2306
TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2307
{
2308
    return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
2309 2310 2311 2312
}


static LRESULT
2313
TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2314
{
2315
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2316
    LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2317
    INT nIndex = (INT)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2318 2319
    TBUTTON_INFO *btnPtr;

2320 2321 2322 2323 2324
    if (infoPtr == NULL)
	return FALSE;

    if (lpTbb == NULL)
	return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340

    if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];
    lpTbb->iBitmap   = btnPtr->iBitmap;
    lpTbb->idCommand = btnPtr->idCommand;
    lpTbb->fsState   = btnPtr->fsState;
    lpTbb->fsStyle   = btnPtr->fsStyle;
    lpTbb->dwData    = btnPtr->dwData;
    lpTbb->iString   = btnPtr->iString;

    return TRUE;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2341
static LRESULT
2342
TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2343
{
2344
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2345
    LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2346
    TBUTTON_INFO *btnPtr;
2347
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2348

2349 2350 2351 2352
    if (infoPtr == NULL)
	return -1;
    if (lpTbInfo == NULL)
	return -1;
Juergen Schmied's avatar
Juergen Schmied committed
2353
    if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA))
2354
	return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
2355

2356
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373
    if (nIndex == -1)
	return -1;

    btnPtr = &infoPtr->buttons[nIndex];

    if (lpTbInfo->dwMask & TBIF_COMMAND)
	lpTbInfo->idCommand = btnPtr->idCommand;
    if (lpTbInfo->dwMask & TBIF_IMAGE)
	lpTbInfo->iImage = btnPtr->iBitmap;
    if (lpTbInfo->dwMask & TBIF_LPARAM)
	lpTbInfo->lParam = btnPtr->dwData;
    if (lpTbInfo->dwMask & TBIF_SIZE)
	lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
    if (lpTbInfo->dwMask & TBIF_STATE)
	lpTbInfo->fsState = btnPtr->fsState;
    if (lpTbInfo->dwMask & TBIF_STYLE)
	lpTbInfo->fsStyle = btnPtr->fsStyle;
2374 2375 2376
     if (lpTbInfo->dwMask & TBIF_TEXT) {
         if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
         {	
2377 2378 2379
             if (!WideCharToMultiByte( CP_ACP, 0, (LPWSTR)infoPtr->strings[btnPtr->iString], -1,
                                       lpTbInfo->pszText, lpTbInfo->cchText, NULL, NULL ))
                 lpTbInfo->pszText[lpTbInfo->cchText-1] = 0;
2380 2381
         }
         else lpTbInfo->pszText[0]=0;
Alexandre Julliard's avatar
Alexandre Julliard committed
2382 2383 2384 2385 2386
    }
    return nIndex;
}


2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428
static LRESULT
TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam;
    TBUTTON_INFO *btnPtr;
    INT nIndex;

    if (infoPtr == NULL)
	return -1;
    if (lpTbInfo == NULL)
	return -1;
    if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW))
	return -1;

    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
    if (nIndex == -1)
	return -1;

    btnPtr = &infoPtr->buttons[nIndex];

    if (lpTbInfo->dwMask & TBIF_COMMAND)
	lpTbInfo->idCommand = btnPtr->idCommand;
    if (lpTbInfo->dwMask & TBIF_IMAGE)
	lpTbInfo->iImage = btnPtr->iBitmap;
    if (lpTbInfo->dwMask & TBIF_LPARAM)
	lpTbInfo->lParam = btnPtr->dwData;
    if (lpTbInfo->dwMask & TBIF_SIZE)
	lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left);
    if (lpTbInfo->dwMask & TBIF_STATE)
	lpTbInfo->fsState = btnPtr->fsState;
    if (lpTbInfo->dwMask & TBIF_STYLE)
	lpTbInfo->fsStyle = btnPtr->fsStyle;
    if (lpTbInfo->dwMask & TBIF_TEXT) {
	if ((btnPtr->iString >= 0) || (btnPtr->iString < infoPtr->nNumStrings))
	    lstrcpynW (lpTbInfo->pszText,
		       (LPWSTR)infoPtr->strings[btnPtr->iString],
		       lpTbInfo->cchText);
    }

    return nIndex;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2429 2430 2431


static LRESULT
2432
TOOLBAR_GetButtonSize (HWND hwnd)
Alexandre Julliard's avatar
Alexandre Julliard committed
2433
{
2434
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2435 2436 2437 2438

    return MAKELONG((WORD)infoPtr->nButtonWidth,
		    (WORD)infoPtr->nButtonHeight);
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2439 2440 2441


static LRESULT
2442
TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2443
{
2444
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2445
    INT nIndex, nStringIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2446

2447
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2448 2449 2450 2451 2452
    if (nIndex == -1)
	return -1;

    nStringIndex = infoPtr->buttons[nIndex].iString;

2453
    TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);
Alexandre Julliard's avatar
Alexandre Julliard committed
2454 2455 2456 2457

    if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
	return -1;

2458 2459 2460
    if (lParam == 0)
	return -1;

2461 2462
    return WideCharToMultiByte( CP_ACP, 0, (LPWSTR)infoPtr->strings[nStringIndex], -1,
                                (LPSTR)lParam, 0x7fffffff, NULL, NULL ) - 1;
2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484
}


static LRESULT
TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    INT nIndex, nStringIndex;

    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
    if (nIndex == -1)
	return -1;

    nStringIndex = infoPtr->buttons[nIndex].iString;

    TRACE("index=%d stringIndex=%d\n", nIndex, nStringIndex);

    if ((nStringIndex < 0) || (nStringIndex >= infoPtr->nNumStrings))
	return -1;

    if (lParam == 0)
	return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
2485

2486
    strcpyW ((LPWSTR)lParam, (LPWSTR)infoPtr->strings[nStringIndex]);
Alexandre Julliard's avatar
Alexandre Julliard committed
2487

2488
    return strlenW ((LPWSTR)infoPtr->strings[nStringIndex]);
Alexandre Julliard's avatar
Alexandre Julliard committed
2489 2490 2491
}


2492
/* << TOOLBAR_GetColorScheme >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
2493 2494 2495


static LRESULT
2496
TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2497
{
2498
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2499

2500
    return (LRESULT)infoPtr->himlDis;
Alexandre Julliard's avatar
Alexandre Julliard committed
2501 2502 2503
}


Patrik Stridvall's avatar
Patrik Stridvall committed
2504
inline static LRESULT
2505
TOOLBAR_GetExtendedStyle (HWND hwnd)
Alexandre Julliard's avatar
Alexandre Julliard committed
2506
{
2507
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2508 2509 2510

    return infoPtr->dwExStyle;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2511 2512 2513


static LRESULT
2514
TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2515
{
2516
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2517

2518
    return (LRESULT)infoPtr->himlHot;
Alexandre Julliard's avatar
Alexandre Julliard committed
2519 2520 2521
}


2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534
static LRESULT
TOOLBAR_GetHotItem (HWND hwnd)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);

    if (!(GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT))
	return -1;

    if (infoPtr->nHotItem < 0)
	return -1;

    return (LRESULT)infoPtr->nHotItem;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2535 2536 2537


static LRESULT
2538
TOOLBAR_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2539
{
2540
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2541

2542
    return (LRESULT)infoPtr->himlDef;
Alexandre Julliard's avatar
Alexandre Julliard committed
2543 2544 2545
}


2546 2547
/* << TOOLBAR_GetInsertMark >> */
/* << TOOLBAR_GetInsertMarkColor >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
2548 2549 2550


static LRESULT
2551
TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2552
{
2553
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2554
    TBUTTON_INFO *btnPtr;
2555 2556
    LPRECT     lpRect;
    INT        nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2557

2558 2559
    if (infoPtr == NULL)
	return FALSE;
2560
    nIndex = (INT)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2561 2562 2563
    btnPtr = &infoPtr->buttons[nIndex];
    if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
	return FALSE;
2564
    lpRect = (LPRECT)lParam;
2565 2566 2567 2568
    if (lpRect == NULL)
	return FALSE;
    if (btnPtr->fsState & TBSTATE_HIDDEN)
	return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2569 2570 2571 2572 2573 2574 2575 2576 2577 2578
    
    lpRect->left   = btnPtr->rect.left;
    lpRect->right  = btnPtr->rect.right;
    lpRect->bottom = btnPtr->rect.bottom;
    lpRect->top    = btnPtr->rect.top;

    return TRUE;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2579
static LRESULT
2580
TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2581
{
2582
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2583
    LPSIZE lpSize = (LPSIZE)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2584

Alexandre Julliard's avatar
Alexandre Julliard committed
2585 2586 2587
    if (lpSize == NULL)
	return FALSE;

Alexandre Julliard's avatar
Alexandre Julliard committed
2588 2589
    lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
    lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
Alexandre Julliard's avatar
Alexandre Julliard committed
2590

2591
    TRACE("maximum size %d x %d\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
2592 2593
	   infoPtr->rcBound.right - infoPtr->rcBound.left,
	   infoPtr->rcBound.bottom - infoPtr->rcBound.top);
Alexandre Julliard's avatar
Alexandre Julliard committed
2594 2595 2596 2597 2598

    return TRUE;
}


2599 2600
/* << TOOLBAR_GetObject >> */
/* << TOOLBAR_GetPadding >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
2601 2602 2603


static LRESULT
2604
TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2605
{
2606
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2607
    TBUTTON_INFO *btnPtr;
2608 2609
    LPRECT     lpRect;
    INT        nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2610

2611 2612
    if (infoPtr == NULL)
	return FALSE;
2613
    nIndex = (INT)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2614 2615 2616
    btnPtr = &infoPtr->buttons[nIndex];
    if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
	return FALSE;
2617
    lpRect = (LPRECT)lParam;
2618 2619
    if (lpRect == NULL)
	return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2620 2621 2622 2623 2624 2625 2626 2627
    
    lpRect->left   = btnPtr->rect.left;
    lpRect->right  = btnPtr->rect.right;
    lpRect->bottom = btnPtr->rect.bottom;
    lpRect->top    = btnPtr->rect.top;

    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2628 2629 2630


static LRESULT
2631
TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2632
{
2633
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2634

2635
    if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_WRAPABLE)
2636
	return infoPtr->nRows;
Alexandre Julliard's avatar
Alexandre Julliard committed
2637 2638 2639 2640 2641 2642
    else
	return 1;
}


static LRESULT
2643
TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2644
{
2645
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2646
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2647

2648
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2649 2650
    if (nIndex == -1)
	return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
2651 2652 2653 2654 2655 2656

    return infoPtr->buttons[nIndex].fsState;
}


static LRESULT
2657
TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2658
{
2659
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2660
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2661

2662
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
2663 2664
    if (nIndex == -1)
	return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
2665 2666 2667 2668 2669

    return infoPtr->buttons[nIndex].fsStyle;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2670
static LRESULT
2671
TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2672
{
2673
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2674 2675 2676 2677 2678 2679

    if (infoPtr == NULL)
	return 0;

    return infoPtr->nMaxTextRows;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2680 2681 2682


static LRESULT
2683
TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2684
{
2685
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2686

2687 2688
    if (infoPtr == NULL)
	return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
2689 2690 2691 2692
    return infoPtr->hwndToolTip;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2693
static LRESULT
2694
TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2695
{
2696
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2697

2698
    TRACE("%s hwnd=0x%x stub!\n", 
2699
	   infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2700 2701 2702

    return infoPtr->bUnicode;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2703 2704


2705 2706 2707 2708 2709 2710 2711 2712
inline static LRESULT
TOOLBAR_GetVersion (HWND hwnd)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    return infoPtr->iVersion;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2713
static LRESULT
2714
TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2715
{
2716
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2717
    TBUTTON_INFO *btnPtr;
2718
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2719

2720 2721
    TRACE("\n");

2722
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2723 2724 2725 2726 2727 2728 2729 2730 2731
    if (nIndex == -1)
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];
    if (LOWORD(lParam) == FALSE)
	btnPtr->fsState &= ~TBSTATE_HIDDEN;
    else
	btnPtr->fsState |= TBSTATE_HIDDEN;

2732 2733
    TOOLBAR_CalcToolbar (hwnd);

2734
    InvalidateRect (hwnd, NULL, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
2735 2736 2737 2738 2739

    return TRUE;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
2740
inline static LRESULT
2741
TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2742
{
2743
    return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2744 2745 2746
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2747
static LRESULT
2748
TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2749
{
2750
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2751
    TBUTTON_INFO *btnPtr;
2752
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2753

2754
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2755 2756 2757 2758 2759 2760 2761 2762 2763
    if (nIndex == -1)
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];
    if (LOWORD(lParam) == FALSE)
	btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
    else
	btnPtr->fsState |= TBSTATE_INDETERMINATE;

2764
    InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
Alexandre Julliard's avatar
Alexandre Julliard committed
2765 2766 2767 2768 2769 2770

    return TRUE;
}


static LRESULT
2771
TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2772
{
2773
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2774
    LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
2775
    INT nIndex = (INT)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2776 2777
    TBUTTON_INFO *oldButtons;

2778 2779
    if (lpTbb == NULL)
	return FALSE;
2780 2781 2782 2783 2784 2785 2786 2787 2788

    if (nIndex == -1) {
       /* EPP: this seems to be an undocumented call (from my IE4)
	* I assume in that case that:
	* - lpTbb->iString is a string pointer (not a string index in strings[] table
	* - index of insertion is at the end of existing buttons
	* I only see this happen with nIndex == -1, but it could have a special
	* meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
	*/
2789 2790 2791
       int	len;
       LPSTR	ptr;

2792 2793
       /* FIXME: iString == -1 is undocumented */
       if(lpTbb->iString && lpTbb->iString!=-1) {
2794
           len = strlen((char*)lpTbb->iString) + 2;
2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805
           ptr = COMCTL32_Alloc(len);
           nIndex = infoPtr->nNumButtons;
           strcpy(ptr, (char*)lpTbb->iString);
           ptr[len - 1] = 0; /* ended by two '\0' */
           lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr);
           COMCTL32_Free(ptr);
       }
       else {
           ERR("lpTbb->iString is NULL\n");
           return FALSE;
       }
2806 2807 2808

    } else if (nIndex < 0)
       return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2809

2810
    TRACE("inserting button index=%d\n", nIndex);
Alexandre Julliard's avatar
Alexandre Julliard committed
2811 2812
    if (nIndex > infoPtr->nNumButtons) {
	nIndex = infoPtr->nNumButtons;
2813
	TRACE("adjust index=%d\n", nIndex);
Alexandre Julliard's avatar
Alexandre Julliard committed
2814 2815 2816 2817
    }

    oldButtons = infoPtr->buttons;
    infoPtr->nNumButtons++;
Alexandre Julliard's avatar
Alexandre Julliard committed
2818
    infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
Alexandre Julliard's avatar
Alexandre Julliard committed
2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832
    /* pre insert copy */
    if (nIndex > 0) {
	memcpy (&infoPtr->buttons[0], &oldButtons[0],
		nIndex * sizeof(TBUTTON_INFO));
    }

    /* insert new button */
    infoPtr->buttons[nIndex].iBitmap   = lpTbb->iBitmap;
    infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
    infoPtr->buttons[nIndex].fsState   = lpTbb->fsState;
    infoPtr->buttons[nIndex].fsStyle   = lpTbb->fsStyle;
    infoPtr->buttons[nIndex].dwData    = lpTbb->dwData;
    infoPtr->buttons[nIndex].iString   = lpTbb->iString;

Alexandre Julliard's avatar
Alexandre Julliard committed
2833
    if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
2834
	TTTOOLINFOA ti;
Alexandre Julliard's avatar
Alexandre Julliard committed
2835

2836 2837
	ZeroMemory (&ti, sizeof(TTTOOLINFOA));
	ti.cbSize   = sizeof (TTTOOLINFOA);
2838
	ti.hwnd     = hwnd;
Alexandre Julliard's avatar
Alexandre Julliard committed
2839 2840
	ti.uId      = lpTbb->idCommand;
	ti.hinst    = 0;
2841
	ti.lpszText = LPSTR_TEXTCALLBACKA;
Alexandre Julliard's avatar
Alexandre Julliard committed
2842

2843
	SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA,
Alexandre Julliard's avatar
Alexandre Julliard committed
2844 2845 2846
			0, (LPARAM)&ti);
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
2847 2848 2849 2850 2851 2852
    /* post insert copy */
    if (nIndex < infoPtr->nNumButtons - 1) {
	memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
		(infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
2853
    COMCTL32_Free (oldButtons);
Alexandre Julliard's avatar
Alexandre Julliard committed
2854

2855 2856
    TOOLBAR_CalcToolbar (hwnd);

2857
    InvalidateRect (hwnd, NULL, FALSE);
Alexandre Julliard's avatar
Alexandre Julliard committed
2858 2859 2860 2861 2862

    return TRUE;
}


2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926
static LRESULT
TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    LPTBBUTTON lpTbb = (LPTBBUTTON)lParam;
    INT nIndex = (INT)wParam;
    TBUTTON_INFO *oldButtons;

    if (lpTbb == NULL)
	return FALSE;
    if (nIndex < 0)
	return FALSE;

    TRACE("inserting button index=%d\n", nIndex);
    if (nIndex > infoPtr->nNumButtons) {
	nIndex = infoPtr->nNumButtons;
	TRACE("adjust index=%d\n", nIndex);
    }

    oldButtons = infoPtr->buttons;
    infoPtr->nNumButtons++;
    infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
    /* pre insert copy */
    if (nIndex > 0) {
	memcpy (&infoPtr->buttons[0], &oldButtons[0],
		nIndex * sizeof(TBUTTON_INFO));
    }

    /* insert new button */
    infoPtr->buttons[nIndex].iBitmap   = lpTbb->iBitmap;
    infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand;
    infoPtr->buttons[nIndex].fsState   = lpTbb->fsState;
    infoPtr->buttons[nIndex].fsStyle   = lpTbb->fsStyle;
    infoPtr->buttons[nIndex].dwData    = lpTbb->dwData;
    infoPtr->buttons[nIndex].iString   = lpTbb->iString;

    if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & TBSTYLE_SEP)) {
	TTTOOLINFOW ti;

	ZeroMemory (&ti, sizeof(TTTOOLINFOW));
	ti.cbSize   = sizeof (TTTOOLINFOW);
	ti.hwnd     = hwnd;
	ti.uId      = lpTbb->idCommand;
	ti.hinst    = 0;
	ti.lpszText = LPSTR_TEXTCALLBACKW;

	SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW,
			0, (LPARAM)&ti);
    }

    /* post insert copy */
    if (nIndex < infoPtr->nNumButtons - 1) {
	memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex],
		(infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
    }

    COMCTL32_Free (oldButtons);

    InvalidateRect (hwnd, NULL, FALSE);

    return TRUE;
}


2927
/* << TOOLBAR_InsertMarkHitTest >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
2928 2929


Alexandre Julliard's avatar
Alexandre Julliard committed
2930
static LRESULT
2931
TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2932
{
2933
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2934
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2935

2936
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2937 2938 2939 2940 2941 2942 2943 2944
    if (nIndex == -1)
	return FALSE;

    return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
}


static LRESULT
2945
TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2946
{
2947
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2948
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2949

2950
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2951 2952 2953 2954 2955 2956 2957 2958
    if (nIndex == -1)
	return FALSE;

    return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
}


static LRESULT
2959
TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2960
{
2961
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2962
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2963

2964
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2965
    if (nIndex == -1)
2966
	return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2967 2968 2969 2970 2971 2972

    return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
}


static LRESULT
2973
TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2974
{
2975
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2976
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2977

2978
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2979 2980 2981 2982 2983 2984 2985 2986
    if (nIndex == -1)
	return FALSE;

    return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
}


static LRESULT
2987
TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2988
{
2989
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
2990
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
2991

2992
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2993 2994 2995 2996 2997 2998 2999 3000
    if (nIndex == -1)
	return FALSE;

    return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
}


static LRESULT
3001
TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3002
{
3003
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3004
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
3005

3006
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3007 3008 3009 3010 3011 3012 3013
    if (nIndex == -1)
	return FALSE;

    return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
}


3014 3015 3016 3017
/* << TOOLBAR_LoadImages >> */
/* << TOOLBAR_MapAccelerator >> */
/* << TOOLBAR_MarkButton >> */
/* << TOOLBAR_MoveButton >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
3018 3019 3020


static LRESULT
3021
TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3022
{
3023
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3024
    TBUTTON_INFO *btnPtr;
3025
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
3026

3027
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3028 3029 3030 3031 3032 3033 3034 3035 3036
    if (nIndex == -1)
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];
    if (LOWORD(lParam) == FALSE)
	btnPtr->fsState &= ~TBSTATE_PRESSED;
    else
	btnPtr->fsState |= TBSTATE_PRESSED;

3037
    InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr, btnPtr));
Alexandre Julliard's avatar
Alexandre Julliard committed
3038 3039 3040 3041 3042

    return TRUE;
}


3043
/* << TOOLBAR_ReplaceBitmap >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
3044 3045 3046


static LRESULT
3047
TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3048
{
Alexandre Julliard's avatar
Alexandre Julliard committed
3049
#if 0
3050
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3051
    LPTBSAVEPARAMSA lpSave = (LPTBSAVEPARAMSA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3052 3053 3054

    if (lpSave == NULL) return 0;

3055
    if ((BOOL)wParam) {
Alexandre Julliard's avatar
Alexandre Julliard committed
3056
	/* save toolbar information */
3057
	FIXME("save to \"%s\" \"%s\"\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
3058 3059 3060 3061 3062 3063 3064
	       lpSave->pszSubKey, lpSave->pszValueName);


    }
    else {
	/* restore toolbar information */

3065
	FIXME("restore from \"%s\" \"%s\"\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
3066 3067 3068 3069
	       lpSave->pszSubKey, lpSave->pszValueName);


    }
Alexandre Julliard's avatar
Alexandre Julliard committed
3070
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
3071 3072 3073 3074 3075

    return 0;
}


3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116
static LRESULT
TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
#if 0
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    LPTBSAVEPARAMSW lpSave = (LPTBSAVEPARAMSW)lParam;

    if (lpSave == NULL)
	return 0;

    if ((BOOL)wParam) {
	/* save toolbar information */
	FIXME("save to \"%s\" \"%s\"\n",
	       lpSave->pszSubKey, lpSave->pszValueName);


    }
    else {
	/* restore toolbar information */

	FIXME("restore from \"%s\" \"%s\"\n",
	       lpSave->pszSubKey, lpSave->pszValueName);


    }
#endif

    return 0;
}


static LRESULT
TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    BOOL bOldAnchor = infoPtr->bAnchor;

    infoPtr->bAnchor = (BOOL)wParam;

    return (LRESULT)bOldAnchor;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3117

Alexandre Julliard's avatar
Alexandre Julliard committed
3118

Alexandre Julliard's avatar
Alexandre Julliard committed
3119
static LRESULT
3120
TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3121
{
3122
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3123 3124 3125 3126

    if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
	return FALSE;

3127 3128 3129 3130 3131
    if (infoPtr->nNumButtons > 0)
        WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n",
             infoPtr->nNumButtons,
             infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
             LOWORD(lParam), HIWORD(lParam));
3132

3133 3134
    infoPtr->nBitmapWidth = (INT)LOWORD(lParam);
    infoPtr->nBitmapHeight = (INT)HIWORD(lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3135

3136 3137 3138 3139 3140 3141
    /* uses image list internals directly */
    if (infoPtr->himlDef) {
        infoPtr->himlDef->cx = infoPtr->nBitmapWidth;
        infoPtr->himlDef->cy = infoPtr->nBitmapHeight;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
3142 3143 3144 3145
    return TRUE;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
3146
static LRESULT
3147
TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3148
{
3149
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3150
    LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3151
    TBUTTON_INFO *btnPtr;
3152
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
3153 3154 3155

    if (lptbbi == NULL)
	return FALSE;
Juergen Schmied's avatar
Juergen Schmied committed
3156
    if (lptbbi->cbSize < sizeof(TBBUTTONINFOA))
Alexandre Julliard's avatar
Alexandre Julliard committed
3157 3158
	return FALSE;
    
3159
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3160 3161 3162 3163 3164 3165 3166 3167 3168 3169
    if (nIndex == -1)
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];
    if (lptbbi->dwMask & TBIF_COMMAND)
	btnPtr->idCommand = lptbbi->idCommand;
    if (lptbbi->dwMask & TBIF_IMAGE)
	btnPtr->iBitmap = lptbbi->iImage;
    if (lptbbi->dwMask & TBIF_LPARAM)
	btnPtr->dwData = lptbbi->lParam;
3170 3171
/*    if (lptbbi->dwMask & TBIF_SIZE) */
/*	btnPtr->cx = lptbbi->cx; */
Alexandre Julliard's avatar
Alexandre Julliard committed
3172 3173 3174 3175 3176 3177 3178 3179
    if (lptbbi->dwMask & TBIF_STATE)
	btnPtr->fsState = lptbbi->fsState;
    if (lptbbi->dwMask & TBIF_STYLE)
	btnPtr->fsStyle = lptbbi->fsStyle;

    if (lptbbi->dwMask & TBIF_TEXT) {
	if ((btnPtr->iString >= 0) || 
	    (btnPtr->iString < infoPtr->nNumStrings)) {
3180
	   TRACE("Ooooooch\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
3181
#if 0
3182
	    WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
3183
	    INT len = lstrlenA (lptbbi->pszText);
3184
	    *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
Alexandre Julliard's avatar
Alexandre Julliard committed
3185 3186
#endif

Alexandre Julliard's avatar
Alexandre Julliard committed
3187
	    /* this is the ultimate sollution */
3188
/*	    Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
Alexandre Julliard's avatar
Alexandre Julliard committed
3189 3190 3191 3192 3193 3194 3195
	}
    }

    return TRUE;
}


3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235
static LRESULT
TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam;
    TBUTTON_INFO *btnPtr;
    INT nIndex;

    if (lptbbi == NULL)
	return FALSE;
    if (lptbbi->cbSize < sizeof(TBBUTTONINFOW))
	return FALSE;

    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
    if (nIndex == -1)
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];
    if (lptbbi->dwMask & TBIF_COMMAND)
	btnPtr->idCommand = lptbbi->idCommand;
    if (lptbbi->dwMask & TBIF_IMAGE)
	btnPtr->iBitmap = lptbbi->iImage;
    if (lptbbi->dwMask & TBIF_LPARAM)
	btnPtr->dwData = lptbbi->lParam;
/*    if (lptbbi->dwMask & TBIF_SIZE) */
/*	btnPtr->cx = lptbbi->cx; */
    if (lptbbi->dwMask & TBIF_STATE)
	btnPtr->fsState = lptbbi->fsState;
    if (lptbbi->dwMask & TBIF_STYLE)
	btnPtr->fsStyle = lptbbi->fsStyle;

    if (lptbbi->dwMask & TBIF_TEXT) {
	if ((btnPtr->iString >= 0) ||
	    (btnPtr->iString < infoPtr->nNumStrings)) {
#if 0
	    WCHAR **lpString = &infoPtr->strings[btnPtr->iString];
	    INT len = lstrlenW (lptbbi->pszText);
	    *lpString = COMCTL32_ReAlloc (lpString, sizeof(WCHAR)*(len+1));
#endif

3236
	    /* this is the ultimate solution */
3237 3238 3239 3240 3241 3242
/*	    Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText); */
	}
    }

    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3243 3244 3245


static LRESULT
3246
TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3247
{
3248
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3249 3250

    if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0))
3251 3252
    {
        ERR("invalid parameter\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
3253
	return FALSE;
3254
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
3255

3256 3257 3258 3259 3260 3261
    /* The documentation claims you can only change the button size before
     * any button has been added. But this is wrong. 
     * WINZIP32.EXE (ver 8) calls this on one of its buttons after adding 
     * it to the toolbar, and it checks that the return value is nonzero - mjm
     * Further testing shows that we must actually perform the change too.
     */
3262 3263
    infoPtr->nButtonWidth = (INT)LOWORD(lParam);
    infoPtr->nButtonHeight = (INT)HIWORD(lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3264 3265 3266 3267
    return TRUE;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
3268
static LRESULT
3269
TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3270
{
3271
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3272 3273 3274 3275

    if (infoPtr == NULL)
	return FALSE;

3276 3277
    infoPtr->cxMin = (INT)LOWORD(lParam);
    infoPtr->cxMax = (INT)HIWORD(lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3278 3279 3280

    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3281 3282 3283


static LRESULT
3284
TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3285
{
3286
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3287
    INT nIndex = (INT)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3288 3289 3290 3291

    if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
	return FALSE;

3292
    infoPtr->buttons[nIndex].idCommand = (INT)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3293

Alexandre Julliard's avatar
Alexandre Julliard committed
3294 3295
    if (infoPtr->hwndToolTip) {

3296
	FIXME("change tool tip!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
3297 3298 3299

    }

Alexandre Julliard's avatar
Alexandre Julliard committed
3300 3301 3302 3303
    return TRUE;
}


3304
/* << TOOLBAR_SetColorScheme >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
3305 3306 3307


static LRESULT
3308
TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3309
{
3310
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3311 3312
    HIMAGELIST himlTemp;

3313

Alexandre Julliard's avatar
Alexandre Julliard committed
3314 3315 3316 3317 3318 3319 3320 3321 3322
    himlTemp = infoPtr->himlDis;
    infoPtr->himlDis = (HIMAGELIST)lParam;

    /* FIXME: redraw ? */

    return (LRESULT)himlTemp; 
}


Alexandre Julliard's avatar
Alexandre Julliard committed
3323
static LRESULT
3324
TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3325
{
3326
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3327 3328 3329 3330 3331 3332 3333 3334
    DWORD dwTemp;

    dwTemp = infoPtr->dwDTFlags;
    infoPtr->dwDTFlags =
	(infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;

    return (LRESULT)dwTemp;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3335 3336 3337


static LRESULT
3338
TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3339
{
3340
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3341 3342 3343 3344 3345 3346 3347 3348 3349 3350
    DWORD dwTemp;

    dwTemp = infoPtr->dwExStyle;
    infoPtr->dwExStyle = (DWORD)lParam;

    return (LRESULT)dwTemp; 
}


static LRESULT
3351
TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3352
{
3353
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364
    HIMAGELIST himlTemp;

    himlTemp = infoPtr->himlHot;
    infoPtr->himlHot = (HIMAGELIST)lParam;

    /* FIXME: redraw ? */

    return (LRESULT)himlTemp; 
}


3365 3366 3367 3368 3369
static LRESULT
TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
    INT nOldHotItem = infoPtr->nHotItem;
3370
    TBUTTON_INFO *btnPtr;
3371

3372 3373 3374
    if ((INT) wParam < 0 || (INT)wParam > infoPtr->nNumButtons)
        wParam = -2;

3375 3376 3377
    if (GetWindowLongA (hwnd, GWL_STYLE) & TBSTYLE_FLAT)
    {

3378
    	infoPtr->nHotItem = (INT)wParam;
3379
        if ((INT)wParam >=0)
3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392
        {
            btnPtr = &infoPtr->buttons[(INT)wParam];
            btnPtr->bHot = TRUE;
	        InvalidateRect (hwnd, &btnPtr->rect,
                    TOOLBAR_HasText(infoPtr, btnPtr));
        }
        if (nOldHotItem>=0)
        {
            btnPtr = &infoPtr->buttons[nOldHotItem];
            btnPtr->bHot = FALSE;
	        InvalidateRect (hwnd, &btnPtr->rect,
                    TOOLBAR_HasText(infoPtr, btnPtr));
        }
3393 3394 3395 3396 3397 3398 3399
    }

    if (nOldHotItem < 0)
	return -1;

    return (LRESULT)nOldHotItem;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3400 3401 3402


static LRESULT
3403
TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3404
{
3405
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3406 3407 3408 3409 3410
    HIMAGELIST himlTemp;

    himlTemp = infoPtr->himlDef;
    infoPtr->himlDef = (HIMAGELIST)lParam;

3411
     infoPtr->nNumBitmaps = ImageList_GetImageCount(infoPtr->himlDef);
Alexandre Julliard's avatar
Alexandre Julliard committed
3412 3413 3414 3415
    /* FIXME: redraw ? */

    return (LRESULT)himlTemp; 
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3416

Alexandre Julliard's avatar
Alexandre Julliard committed
3417 3418

static LRESULT
3419
TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3420
{
3421
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3422

3423 3424
    infoPtr->nIndent = (INT)wParam;

3425
    TRACE("\n");
3426

3427 3428 3429 3430
    /* process only on indent changing */
    if(infoPtr->nIndent != (INT)wParam)
    {
        infoPtr->nIndent = (INT)wParam;
3431
        TOOLBAR_CalcToolbar (hwnd);
3432 3433
        InvalidateRect(hwnd, NULL, FALSE);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
3434 3435 3436 3437 3438

    return TRUE;
}


3439
/* << TOOLBAR_SetInsertMark >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
3440 3441 3442


static LRESULT
3443
TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3444
{
3445
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3446 3447 3448 3449 3450 3451 3452 3453 3454

    infoPtr->clrInsertMark = (COLORREF)lParam;

    /* FIXME : redraw ??*/

    return 0;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
3455
static LRESULT
3456
TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3457
{
3458
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3459 3460 3461 3462

    if (infoPtr == NULL)
	return FALSE;

3463
    infoPtr->nMaxTextRows = (INT)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3464 3465 3466 3467 3468

    return TRUE;
}


3469
/* << TOOLBAR_SetPadding >> */
Alexandre Julliard's avatar
Alexandre Julliard committed
3470 3471 3472


static LRESULT
3473
TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3474
{
3475
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3476
    HWND hwndOldNotify;
Alexandre Julliard's avatar
Alexandre Julliard committed
3477

3478 3479
    TRACE("\n");

3480 3481
    if (infoPtr == NULL)
	return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
3482
    hwndOldNotify = infoPtr->hwndNotify;
3483
    infoPtr->hwndNotify = (HWND)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3484 3485 3486 3487 3488 3489

    return hwndOldNotify;
}


static LRESULT
3490
TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3491
{
3492
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3493
    LPRECT lprc = (LPRECT)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3494

3495
    TRACE("\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
3496

3497
    if (LOWORD(wParam) > 1) {
3498
	FIXME("multiple rows not supported!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
3499
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
3500

3501 3502 3503 3504
    if(infoPtr->nRows != LOWORD(wParam))
    {
        infoPtr->nRows = LOWORD(wParam);

3505 3506 3507
        /* recalculate toolbar */
        TOOLBAR_CalcToolbar (hwnd);

3508 3509 3510
        /* repaint toolbar */
        InvalidateRect(hwnd, NULL, FALSE);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
3511 3512 3513 3514 3515 3516 3517 3518 3519

    /* return bounding rectangle */
    if (lprc) {
	lprc->left   = infoPtr->rcBound.left;
	lprc->right  = infoPtr->rcBound.right;
	lprc->top    = infoPtr->rcBound.top;
	lprc->bottom = infoPtr->rcBound.bottom;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
3520 3521 3522
    return 0;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
3523 3524

static LRESULT
3525
TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3526
{
3527
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3528
    TBUTTON_INFO *btnPtr;
3529
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
3530

3531
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3532 3533 3534 3535 3536
    if (nIndex == -1)
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];

3537 3538 3539 3540 3541 3542 3543
    /* process state changing if current state doesn't match new state */
    if(btnPtr->fsState != LOWORD(lParam))
    {
        btnPtr->fsState = LOWORD(lParam);
        InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
            btnPtr));
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
3544 3545 3546 3547 3548 3549

    return TRUE;
}


static LRESULT
3550
TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3551
{
3552
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3553
    TBUTTON_INFO *btnPtr;
3554
    INT nIndex;
Alexandre Julliard's avatar
Alexandre Julliard committed
3555

3556
    nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3557 3558 3559 3560 3561
    if (nIndex == -1)
	return FALSE;

    btnPtr = &infoPtr->buttons[nIndex];

3562 3563 3564 3565 3566 3567
    /* process style change if current style doesn't match new style */
    if(btnPtr->fsStyle != LOWORD(lParam))
    {
        btnPtr->fsStyle = LOWORD(lParam);
        InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
            btnPtr));
Alexandre Julliard's avatar
Alexandre Julliard committed
3568

3569 3570 3571
        if (infoPtr->hwndToolTip) {
  	    FIXME("change tool tip!\n");
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
3572 3573
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
3574 3575 3576 3577
    return TRUE;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
3578
inline static LRESULT
3579
TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3580
{
3581
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3582

3583 3584
    if (infoPtr == NULL)
	return 0;
3585
    infoPtr->hwndToolTip = (HWND)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3586 3587 3588 3589
    return 0;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
3590
static LRESULT
3591
TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3592
{
3593
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3594
    BOOL bTemp;
Alexandre Julliard's avatar
Alexandre Julliard committed
3595

3596
    TRACE("%s hwnd=0x%04x stub!\n", 
3597
	   ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3598

Alexandre Julliard's avatar
Alexandre Julliard committed
3599
    bTemp = infoPtr->bUnicode;
3600
    infoPtr->bUnicode = (BOOL)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
3601 3602

    return bTemp;
Alexandre Julliard's avatar
Alexandre Julliard committed
3603
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3604 3605


3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617
static LRESULT
TOOLBAR_SetVersion (HWND hwnd, INT iVersion)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    INT iOldVersion = infoPtr->iVersion;

    infoPtr->iVersion = iVersion;

    return iOldVersion;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
3618
static LRESULT
3619
TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3620
{
3621 3622
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3623
    LOGFONTA logFont;
Alexandre Julliard's avatar
Alexandre Julliard committed
3624 3625

    /* initialize info structure */
Alexandre Julliard's avatar
Alexandre Julliard committed
3626
    infoPtr->nButtonHeight = 22;
3627
    infoPtr->nButtonWidth = 24;
Alexandre Julliard's avatar
Alexandre Julliard committed
3628 3629 3630
    infoPtr->nBitmapHeight = 15;
    infoPtr->nBitmapWidth = 16;

Alexandre Julliard's avatar
Alexandre Julliard committed
3631
    infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
3632
    infoPtr->nRows = 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
3633 3634 3635
    infoPtr->nMaxTextRows = 1;
    infoPtr->cxMin = -1;
    infoPtr->cxMax = -1;
3636 3637
    infoPtr->nNumBitmaps = 0;
    infoPtr->nNumStrings = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
3638

Alexandre Julliard's avatar
Alexandre Julliard committed
3639
    infoPtr->bCaptured = FALSE;
3640
    infoPtr->bUnicode = IsWindowUnicode (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3641 3642
    infoPtr->nButtonDown = -1;
    infoPtr->nOldHit = -1;
3643
    infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */
3644 3645
    infoPtr->hwndNotify = GetParent (hwnd);
    infoPtr->bTransparent = (dwStyle & TBSTYLE_FLAT);
3646
    infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE : DT_CENTER;
3647 3648
    infoPtr->bAnchor = FALSE; /* no anchor highlighting */
    infoPtr->iVersion = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
3649

3650 3651
    SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
    infoPtr->hFont = CreateFontIndirectA (&logFont);
Alexandre Julliard's avatar
Alexandre Julliard committed
3652

3653
    if (dwStyle & TBSTYLE_TOOLTIPS) {
Alexandre Julliard's avatar
Alexandre Julliard committed
3654
	/* Create tooltip control */
Alexandre Julliard's avatar
Alexandre Julliard committed
3655
	infoPtr->hwndToolTip =
3656 3657 3658
	    CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
			       CW_USEDEFAULT, CW_USEDEFAULT,
			       CW_USEDEFAULT, CW_USEDEFAULT,
3659
			       hwnd, 0, 0, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
3660 3661

	/* Send NM_TOOLTIPSCREATED notification */
Alexandre Julliard's avatar
Alexandre Julliard committed
3662 3663
	if (infoPtr->hwndToolTip) {
	    NMTOOLTIPSCREATED nmttc;
Alexandre Julliard's avatar
Alexandre Julliard committed
3664

3665 3666
	    nmttc.hdr.hwndFrom = hwnd;
	    nmttc.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
Alexandre Julliard's avatar
Alexandre Julliard committed
3667 3668 3669
	    nmttc.hdr.code = NM_TOOLTIPSCREATED;
	    nmttc.hwndToolTips = infoPtr->hwndToolTip;

3670
	    SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
3671
			  (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
Alexandre Julliard's avatar
Alexandre Julliard committed
3672
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
3673
    }
3674 3675 3676

    TOOLBAR_CalcToolbar(hwnd);

Alexandre Julliard's avatar
Alexandre Julliard committed
3677 3678 3679 3680 3681
    return 0;
}


static LRESULT
3682
TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3683
{
3684
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3685

Alexandre Julliard's avatar
Alexandre Julliard committed
3686
    /* delete tooltip control */
Alexandre Julliard's avatar
Alexandre Julliard committed
3687
    if (infoPtr->hwndToolTip)
3688
	DestroyWindow (infoPtr->hwndToolTip);
Alexandre Julliard's avatar
Alexandre Julliard committed
3689

Alexandre Julliard's avatar
Alexandre Julliard committed
3690 3691
    /* delete button data */
    if (infoPtr->buttons)
Alexandre Julliard's avatar
Alexandre Julliard committed
3692
	COMCTL32_Free (infoPtr->buttons);
Alexandre Julliard's avatar
Alexandre Julliard committed
3693

Alexandre Julliard's avatar
Alexandre Julliard committed
3694 3695
    /* delete strings */
    if (infoPtr->strings) {
3696
	INT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
3697 3698
	for (i = 0; i < infoPtr->nNumStrings; i++)
	    if (infoPtr->strings[i])
Alexandre Julliard's avatar
Alexandre Julliard committed
3699
		COMCTL32_Free (infoPtr->strings[i]);
Alexandre Julliard's avatar
Alexandre Julliard committed
3700

Alexandre Julliard's avatar
Alexandre Julliard committed
3701
	COMCTL32_Free (infoPtr->strings);
Alexandre Julliard's avatar
Alexandre Julliard committed
3702 3703
    }

3704 3705 3706
    /* destroy internal image list */
    if (infoPtr->himlInt)
	ImageList_Destroy (infoPtr->himlInt);
Alexandre Julliard's avatar
Alexandre Julliard committed
3707

Alexandre Julliard's avatar
Alexandre Julliard committed
3708 3709
    /* delete default font */
    if (infoPtr->hFont)
3710
	DeleteObject (infoPtr->hFont);
Alexandre Julliard's avatar
Alexandre Julliard committed
3711

Alexandre Julliard's avatar
Alexandre Julliard committed
3712
    /* free toolbar info data */
Alexandre Julliard's avatar
Alexandre Julliard committed
3713
    COMCTL32_Free (infoPtr);
3714
    SetWindowLongA (hwnd, 0, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
3715 3716 3717 3718 3719

    return 0;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
3720
static LRESULT
3721
TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3722
{
3723
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3724 3725

    if (infoPtr->bTransparent)
3726
	return SendMessageA (GetParent (hwnd), WM_ERASEBKGND, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3727

3728
    return DefWindowProcA (hwnd, WM_ERASEBKGND, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
3729 3730 3731
}


Eric Pouech's avatar
Eric Pouech committed
3732 3733 3734 3735 3736 3737 3738 3739 3740
static LRESULT
TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);

    return infoPtr->hFont;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
3741
static LRESULT
3742
TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3743
{
3744
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3745
    TBUTTON_INFO *btnPtr;
3746 3747
    POINT pt;
    INT   nHit;
Alexandre Julliard's avatar
Alexandre Julliard committed
3748

3749 3750
    pt.x = (INT)LOWORD(lParam);
    pt.y = (INT)HIWORD(lParam);
3751
    nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
Alexandre Julliard's avatar
Alexandre Julliard committed
3752 3753 3754 3755 3756

    if (nHit >= 0) {
	btnPtr = &infoPtr->buttons[nHit];
	if (!(btnPtr->fsState & TBSTATE_ENABLED))
	    return 0;
3757
	SetCapture (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3758 3759 3760 3761 3762
	infoPtr->bCaptured = TRUE;
	infoPtr->nButtonDown = nHit;

	btnPtr->fsState |= TBSTATE_PRESSED;

3763 3764
        InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
            btnPtr));
Alexandre Julliard's avatar
Alexandre Julliard committed
3765
    }
3766 3767
    else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE)
	TOOLBAR_Customize (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3768 3769 3770 3771 3772 3773

    return 0;
}


static LRESULT
3774
TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3775
{
3776
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3777
    TBUTTON_INFO *btnPtr;
3778 3779
    POINT pt;
    INT   nHit;
Alexandre Julliard's avatar
Alexandre Julliard committed
3780

Alexandre Julliard's avatar
Alexandre Julliard committed
3781
    if (infoPtr->hwndToolTip)
3782
	TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
Alexandre Julliard's avatar
Alexandre Julliard committed
3783 3784
			    WM_LBUTTONDOWN, wParam, lParam);

3785 3786
    pt.x = (INT)LOWORD(lParam);
    pt.y = (INT)HIWORD(lParam);
3787
    nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
Alexandre Julliard's avatar
Alexandre Julliard committed
3788 3789

    if (nHit >= 0) {
3790
	RECT arrowRect;
Alexandre Julliard's avatar
Alexandre Julliard committed
3791 3792 3793 3794
	btnPtr = &infoPtr->buttons[nHit];
	if (!(btnPtr->fsState & TBSTATE_ENABLED))
	    return 0;

3795 3796 3797 3798
	infoPtr->nOldHit = nHit;

	CopyRect(&arrowRect, &btnPtr->rect);
	arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH);
3799

3800
	/* for EX_DRAWDDARROWS style,  click must be in the drop-down arrow rect */
3801
	if ((btnPtr->fsStyle & TBSTYLE_DROPDOWN) &&
3802 3803
	     ((TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && PtInRect(&arrowRect, pt)) ||
	      (!TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle))))
3804 3805
	{
	    NMTOOLBARA nmtb;
3806
	    /*
3807 3808 3809 3810 3811
	     * this time we must force a Redraw, so the btn is
	     * painted down before CaptureChanged repaints it up
	     */
	    RedrawWindow(hwnd,&btnPtr->rect,0,
			RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);
3812 3813 3814 3815 3816 3817 3818 3819 3820

	    nmtb.hdr.hwndFrom = hwnd;
	    nmtb.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
	    nmtb.hdr.code = TBN_DROPDOWN;
	    nmtb.iItem = btnPtr->idCommand;

	    SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,
			  (WPARAM)nmtb.hdr.idFrom, (LPARAM)&nmtb);
	}
3821
	else
3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832
	{
	    SetCapture (hwnd);
	    infoPtr->bCaptured = TRUE;
	    infoPtr->nButtonDown = nHit;

	    btnPtr->fsState |= TBSTATE_PRESSED;
	    btnPtr->bHot = FALSE;

	    InvalidateRect(hwnd, &btnPtr->rect,
			   TOOLBAR_HasText(infoPtr, btnPtr));
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
3833 3834 3835 3836 3837 3838
    }

    return 0;
}

static LRESULT
3839
TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3840
{
3841
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3842
    TBUTTON_INFO *btnPtr;
3843 3844 3845 3846
    POINT pt;
    INT   nHit;
    INT   nOldIndex = -1;
    BOOL  bSendMessage = TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
3847

Alexandre Julliard's avatar
Alexandre Julliard committed
3848
    if (infoPtr->hwndToolTip)
3849
	TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
Alexandre Julliard's avatar
Alexandre Julliard committed
3850 3851
			    WM_LBUTTONUP, wParam, lParam);

3852 3853
    pt.x = (INT)LOWORD(lParam);
    pt.y = (INT)HIWORD(lParam);
3854
    nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
Alexandre Julliard's avatar
Alexandre Julliard committed
3855

3856
    /* restore hot effect to hot button disabled by TOOLBAR_LButtonDown() */
3857 3858
    /* if the cursor is still inside of the toolbar */
    if((infoPtr->nHotItem >= 0) && (nHit != -1))
3859 3860
        infoPtr->buttons[infoPtr->nHotItem].bHot = TRUE;

Alexandre Julliard's avatar
Alexandre Julliard committed
3861 3862
    if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) {
	btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
Alexandre Julliard's avatar
Alexandre Julliard committed
3863
	btnPtr->fsState &= ~TBSTATE_PRESSED;
Alexandre Julliard's avatar
Alexandre Julliard committed
3864

Alexandre Julliard's avatar
Alexandre Julliard committed
3865 3866 3867 3868 3869 3870 3871 3872 3873 3874
	if (nHit == infoPtr->nButtonDown) {
	    if (btnPtr->fsStyle & TBSTYLE_CHECK) {
		if (btnPtr->fsStyle & TBSTYLE_GROUP) {
		    nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr,
			infoPtr->nButtonDown);
		    if (nOldIndex == infoPtr->nButtonDown)
			bSendMessage = FALSE;
		    if ((nOldIndex != infoPtr->nButtonDown) && 
			(nOldIndex != -1))
			infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
Alexandre Julliard's avatar
Alexandre Julliard committed
3875
		    btnPtr->fsState |= TBSTATE_CHECKED;
Alexandre Julliard's avatar
Alexandre Julliard committed
3876 3877 3878 3879 3880 3881 3882
		}
		else {
		    if (btnPtr->fsState & TBSTATE_CHECKED)
			btnPtr->fsState &= ~TBSTATE_CHECKED;
		    else
			btnPtr->fsState |= TBSTATE_CHECKED;
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
3883 3884
	    }
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
3885 3886
	else
	    bSendMessage = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
3887

Alexandre Julliard's avatar
Alexandre Julliard committed
3888
	if (nOldIndex != -1)
3889 3890 3891 3892 3893
        {
            InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect,
                TOOLBAR_HasText(infoPtr, &infoPtr->buttons[nOldIndex]));
        }

3894 3895 3896 3897 3898 3899
	/*
	 * now we can ReleaseCapture, which triggers CAPTURECHANGED msg,
	 * that resets bCaptured and btn TBSTATE_PRESSED flags,
	 * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged) 
	 */
	ReleaseCapture ();
Alexandre Julliard's avatar
Alexandre Julliard committed
3900

3901
	if (bSendMessage)
3902
	    SendMessageA (GetParent(hwnd), WM_COMMAND,
3903
			  MAKEWPARAM(btnPtr->idCommand, 0), (LPARAM)hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
3904 3905 3906 3907 3908
    }

    return 0;
}

3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930
static LRESULT
TOOLBAR_CaptureChanged(HWND hwnd)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    TBUTTON_INFO *btnPtr;

    infoPtr->bCaptured = FALSE;

    if (infoPtr->nButtonDown >= 0)
    {
        btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
       	btnPtr->fsState &= ~TBSTATE_PRESSED;

        infoPtr->nButtonDown = -1;
        infoPtr->nOldHit = -1;

        InvalidateRect(hwnd, &btnPtr->rect, TOOLBAR_HasText(infoPtr,
            btnPtr));
    }
    return 0;
}

3931 3932 3933 3934
static LRESULT
TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3935
    TBUTTON_INFO *hotBtnPtr, *btnPtr;
3936

3937 3938 3939
    if (infoPtr->nOldHit < 0)
      return TRUE;

3940 3941 3942 3943 3944 3945 3946
    hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];

    /* Redraw the button if the last button we were over is the hot button and it
       is enabled */
    if((infoPtr->nOldHit == infoPtr->nHotItem) && (hotBtnPtr->fsState & TBSTATE_ENABLED))
    {
	hotBtnPtr->bHot = FALSE;
3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960

        InvalidateRect (hwnd, &hotBtnPtr->rect, TOOLBAR_HasText(infoPtr,
            hotBtnPtr));
    }

    /* If the last button we were over is depressed then make it not */
    /* depressed and redraw it */
    if(infoPtr->nOldHit == infoPtr->nButtonDown)
    {
      btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];

      btnPtr->fsState &= ~TBSTATE_PRESSED;

      InvalidateRect (hwnd, &(btnPtr->rect), TRUE);
3961 3962 3963 3964 3965 3966 3967
    }

    infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */
    infoPtr->nHotItem = -2; /* It has to be initially different from nOldHit */

    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
3968 3969

static LRESULT
3970
TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
3971
{
3972
    TBUTTON_INFO *btnPtr, *oldBtnPtr;
3973
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
3974 3975
    POINT pt;
    INT   nHit;
3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986
    TRACKMOUSEEVENT trackinfo;

    /* fill in the TRACKMOUSEEVENT struct */
    trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
    trackinfo.dwFlags = TME_QUERY;
    trackinfo.hwndTrack = hwnd;
    trackinfo.dwHoverTime = HOVER_DEFAULT;

    /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
    _TrackMouseEvent(&trackinfo);

3987
    /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
3988 3989
    if(!(trackinfo.dwFlags & TME_LEAVE)) {
        trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
3990
 
3991
        /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
3992 3993 3994
        /* and can properly deactivate the hot toolbar button */
        _TrackMouseEvent(&trackinfo);
   }
Alexandre Julliard's avatar
Alexandre Julliard committed
3995

Alexandre Julliard's avatar
Alexandre Julliard committed
3996
    if (infoPtr->hwndToolTip)
3997
	TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd,
Alexandre Julliard's avatar
Alexandre Julliard committed
3998 3999
			    WM_MOUSEMOVE, wParam, lParam);

4000 4001
    pt.x = (INT)LOWORD(lParam);
    pt.y = (INT)HIWORD(lParam);
4002

4003
    nHit = TOOLBAR_InternalHitTest (hwnd, &pt);
Alexandre Julliard's avatar
Alexandre Julliard committed
4004

4005 4006
    if (infoPtr->nOldHit != nHit)
    {
4007 4008
	/* Remove the effect of an old hot button if the button was enabled and was
	   drawn with the hot button effect */
4009
	if(infoPtr->nOldHit >= 0 && infoPtr->nOldHit == infoPtr->nHotItem && 
4010
		(infoPtr->buttons[infoPtr->nOldHit].fsState & TBSTATE_ENABLED))
4011 4012 4013 4014
	{
	    oldBtnPtr = &infoPtr->buttons[infoPtr->nOldHit];
	    oldBtnPtr->bHot = FALSE;
		    
4015 4016
	    InvalidateRect (hwnd, &oldBtnPtr->rect,
                TOOLBAR_HasText(infoPtr, oldBtnPtr));
4017 4018
	}

4019
	/* It's not a separator or in nowhere. It's a hot button. */
4020 4021 4022 4023 4024 4025
	if (nHit >= 0)
	{
	    btnPtr = &infoPtr->buttons[nHit];
	    btnPtr->bHot = TRUE;

	    infoPtr->nHotItem = nHit;
4026 4027 4028

            /* only enabled buttons show hot effect */            
            if(infoPtr->buttons[nHit].fsState & TBSTATE_ENABLED)
4029 4030 4031 4032 4033
            {
                InvalidateRect(hwnd, &btnPtr->rect,
                    TOOLBAR_HasText(infoPtr, btnPtr));
            }

4034 4035
	}

Alexandre Julliard's avatar
Alexandre Julliard committed
4036 4037 4038 4039
    if (infoPtr->bCaptured) {
	    btnPtr = &infoPtr->buttons[infoPtr->nButtonDown];
	    if (infoPtr->nOldHit == infoPtr->nButtonDown) {
		btnPtr->fsState &= ~TBSTATE_PRESSED;
4040
                InvalidateRect(hwnd, &btnPtr->rect, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
4041 4042 4043
	    }
	    else if (nHit == infoPtr->nButtonDown) {
		btnPtr->fsState |= TBSTATE_PRESSED;
4044
                InvalidateRect(hwnd, &btnPtr->rect, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
4045 4046 4047 4048 4049 4050 4051 4052
	    }
	}
	infoPtr->nOldHit = nHit;
    }
    return 0;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
4053
inline static LRESULT
4054
TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4055
{
4056
/*    if (wndPtr->dwStyle & CCS_NODIVIDER) */
4057
	return DefWindowProcA (hwnd, WM_NCACTIVATE, wParam, lParam);
4058 4059
/*    else */
/*	return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */
Alexandre Julliard's avatar
Alexandre Julliard committed
4060
}
Alexandre Julliard's avatar
Alexandre Julliard committed
4061 4062


Patrik Stridvall's avatar
Patrik Stridvall committed
4063
inline static LRESULT
4064
TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4065
{
4066
    if (!(GetWindowLongA (hwnd, GWL_STYLE) & CCS_NODIVIDER))
4067
	((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE);
Alexandre Julliard's avatar
Alexandre Julliard committed
4068

4069
    return DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4070
}
Alexandre Julliard's avatar
Alexandre Julliard committed
4071 4072 4073


static LRESULT
4074
TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4075
{
Alexandre Julliard's avatar
Alexandre Julliard committed
4076
    TOOLBAR_INFO *infoPtr;
Alexandre Julliard's avatar
Alexandre Julliard committed
4077

Alexandre Julliard's avatar
Alexandre Julliard committed
4078
    /* allocate memory for info structure */
Alexandre Julliard's avatar
Alexandre Julliard committed
4079
    infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
4080
    SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
4081

Alexandre Julliard's avatar
Alexandre Julliard committed
4082
    /* paranoid!! */
Alexandre Julliard's avatar
Alexandre Julliard committed
4083
    infoPtr->dwStructSize = sizeof(TBBUTTON);
Alexandre Julliard's avatar
Alexandre Julliard committed
4084

Alexandre Julliard's avatar
Alexandre Julliard committed
4085
    /* fix instance handle, if the toolbar was created by CreateToolbarEx() */
4086 4087 4088 4089
    if (!GetWindowLongA (hwnd, GWL_HINSTANCE)) {
        HINSTANCE hInst = (HINSTANCE)GetWindowLongA (GetParent (hwnd), GWL_HINSTANCE);
	SetWindowLongA (hwnd, GWL_HINSTANCE, (DWORD)hInst);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
4090

4091
    return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4092 4093 4094 4095
}


static LRESULT
4096
TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4097
{
4098 4099
    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
    RECT rcWindow;
4100
    HDC hdc;
Alexandre Julliard's avatar
Alexandre Julliard committed
4101

4102 4103
    if (dwStyle & WS_MINIMIZE)
	return 0; /* Nothing to do */
Alexandre Julliard's avatar
Alexandre Julliard committed
4104

4105
    DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4106

4107
    if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
Alexandre Julliard's avatar
Alexandre Julliard committed
4108 4109
	return 0;

4110 4111 4112 4113
    if (!(dwStyle & CCS_NODIVIDER))
    {
	GetWindowRect (hwnd, &rcWindow);
	OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
4114 4115
	if( dwStyle & WS_BORDER )
	    OffsetRect (&rcWindow, 1, 1);
4116 4117
	DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
4118

4119
    ReleaseDC( hwnd, hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
4120 4121 4122 4123 4124

    return 0;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
4125
inline static LRESULT
4126
TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4127
{
4128
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
4129 4130
    LPNMHDR lpnmh = (LPNMHDR)lParam;

4131
    TRACE("passing WM_NOTIFY!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
4132

Alexandre Julliard's avatar
Alexandre Julliard committed
4133
    if ((infoPtr->hwndToolTip) && (lpnmh->hwndFrom == infoPtr->hwndToolTip)) {
4134
	SendMessageA (infoPtr->hwndNotify, WM_NOTIFY,	wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4135 4136

#if 0
4137 4138
	if (lpnmh->code == TTN_GETDISPINFOA) {
	    LPNMTTDISPINFOA lpdi = (LPNMTTDISPINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
4139

4140
	    FIXME("retrieving ASCII string\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
4141 4142

	}
4143 4144
	else if (lpnmh->code == TTN_GETDISPINFOW) {
	    LPNMTTDISPINFOW lpdi = (LPNMTTDISPINFOW)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
4145

4146
	    FIXME("retrieving UNICODE string\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
4147 4148 4149

	}
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
4150 4151 4152 4153 4154 4155
    }

    return 0;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
4156
static LRESULT
4157
TOOLBAR_Paint (HWND hwnd, WPARAM wParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4158
{
4159
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd);
4160 4161
    HDC hdc;
    PAINTSTRUCT ps;
Alexandre Julliard's avatar
Alexandre Julliard committed
4162

4163 4164
    TRACE("\n");

4165 4166 4167 4168 4169 4170 4171
    /* fill ps.rcPaint with a default rect */
    memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound)); 

    hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam;
    TOOLBAR_Refresh (hwnd, hdc, &ps);
    if (!wParam) EndPaint (hwnd, &ps);

Alexandre Julliard's avatar
Alexandre Julliard committed
4172 4173 4174 4175 4176
    return 0;
}


static LRESULT
4177
TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4178
{
4179 4180
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
    DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
4181
    RECT parent_rect;
4182
    RECT window_rect;
4183
    HWND parent;
4184
    INT  x, y;
4185 4186 4187
    INT  cx, cy;
    INT  flags;
    UINT uPosFlags = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
4188

Alexandre Julliard's avatar
Alexandre Julliard committed
4189
    /* Resize deadlock check */
Alexandre Julliard's avatar
Alexandre Julliard committed
4190 4191 4192 4193 4194
    if (infoPtr->bAutoSize) {
	infoPtr->bAutoSize = FALSE;
	return 0;
    }

4195 4196 4197
    /* FIXME: optimize to only update size if the new size doesn't */
    /* match the current size */

4198
    flags = (INT) wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
4199 4200

    /* FIXME for flags =
Alexandre Julliard's avatar
Alexandre Julliard committed
4201
     * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
Alexandre Julliard's avatar
Alexandre Julliard committed
4202 4203
     */

4204
    TRACE("sizing toolbar!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
4205

Alexandre Julliard's avatar
Alexandre Julliard committed
4206
    if (flags == SIZE_RESTORED) {
Alexandre Julliard's avatar
Alexandre Julliard committed
4207
	/* width and height don't apply */
4208
	parent = GetParent (hwnd);
4209
	GetClientRect(parent, &parent_rect);
4210 4211
	x = parent_rect.left;
	y = parent_rect.top;
Alexandre Julliard's avatar
Alexandre Julliard committed
4212

4213
	if (dwStyle & CCS_NORESIZE) {
4214
	    uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
Alexandre Julliard's avatar
Alexandre Julliard committed
4215

4216 4217 4218 4219 4220
	    /*
             * this sets the working width of the toolbar, and
             * Calc Toolbar will not adjust it, only the height
             */
	    infoPtr->nWidth = parent_rect.right - parent_rect.left; 
Alexandre Julliard's avatar
Alexandre Julliard committed
4221 4222
	    cy = infoPtr->nHeight;
	    cx = infoPtr->nWidth;
4223
	    TOOLBAR_CalcToolbar (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
4224 4225 4226
	    infoPtr->nWidth = cx;
	    infoPtr->nHeight = cy;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
4227 4228
	else {
	    infoPtr->nWidth = parent_rect.right - parent_rect.left;
4229
	    TOOLBAR_CalcToolbar (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
4230 4231
	    cy = infoPtr->nHeight;
	    cx = infoPtr->nWidth;
4232 4233 4234 4235 4236 4237

	    if (dwStyle & CCS_NOMOVEY) {
		GetWindowRect(hwnd, &window_rect);
		ScreenToClient(parent, (LPPOINT)&window_rect.left);
		y = window_rect.top;
	    }
Alexandre Julliard's avatar
Alexandre Julliard committed
4238
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
4239

4240
	if (dwStyle & CCS_NOPARENTALIGN) {
Alexandre Julliard's avatar
Alexandre Julliard committed
4241
	    uPosFlags |= SWP_NOMOVE;
Alexandre Julliard's avatar
Alexandre Julliard committed
4242 4243
	    cy = infoPtr->nHeight;
	    cx = infoPtr->nWidth;
Alexandre Julliard's avatar
Alexandre Julliard committed
4244
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
4245

4246
	if (!(dwStyle & CCS_NODIVIDER))
4247
	    cy += GetSystemMetrics(SM_CYEDGE);
Alexandre Julliard's avatar
Alexandre Julliard committed
4248

4249 4250 4251 4252 4253 4254
	if (dwStyle & WS_BORDER)
	{
	    x = y = 1;
	    cy += GetSystemMetrics(SM_CYEDGE);
	    cx += GetSystemMetrics(SM_CYEDGE);
	}
4255

4256 4257 4258
	SetWindowPos (hwnd, 0, parent_rect.left - x, parent_rect.top - y,
			cx, cy, uPosFlags | SWP_NOZORDER);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
4259 4260
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
4261 4262


Alexandre Julliard's avatar
Alexandre Julliard committed
4263
static LRESULT
4264
TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
Alexandre Julliard's avatar
Alexandre Julliard committed
4265
{
4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277
    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);

    if (nType == GWL_STYLE) {
	if (lpStyle->styleNew & TBSTYLE_LIST) {
	    infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
	}
	else {
	    infoPtr->dwDTFlags = DT_CENTER;
	}
    }

    TOOLBAR_AutoSize (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
4278

4279
    InvalidateRect(hwnd, NULL, FALSE);
Alexandre Julliard's avatar
Alexandre Julliard committed
4280

Alexandre Julliard's avatar
Alexandre Julliard committed
4281 4282
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
4283 4284 4285



4286
static LRESULT WINAPI
4287
ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
4288
{
4289 4290
    if (!TOOLBAR_GetInfoPtr(hwnd) && (uMsg != WM_NCCREATE))
	return DefWindowProcA( hwnd, uMsg, wParam, lParam );
4291

Alexandre Julliard's avatar
Alexandre Julliard committed
4292 4293 4294
    switch (uMsg)
    {
	case TB_ADDBITMAP:
4295
	    return TOOLBAR_AddBitmap (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4296

4297
	case TB_ADDBUTTONSA:
4298
	    return TOOLBAR_AddButtonsA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4299

4300 4301
	case TB_ADDBUTTONSW:
	    return TOOLBAR_AddButtonsW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4302

4303
	case TB_ADDSTRINGA:
4304
	    return TOOLBAR_AddStringA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4305

4306
	case TB_ADDSTRINGW:
4307
	    return TOOLBAR_AddStringW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4308 4309

	case TB_AUTOSIZE:
4310
	    return TOOLBAR_AutoSize (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
4311 4312

	case TB_BUTTONCOUNT:
4313
	    return TOOLBAR_ButtonCount (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4314 4315

	case TB_BUTTONSTRUCTSIZE:
4316
	    return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4317 4318

	case TB_CHANGEBITMAP:
4319
	    return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4320

Alexandre Julliard's avatar
Alexandre Julliard committed
4321
	case TB_CHECKBUTTON:
4322
	    return TOOLBAR_CheckButton (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4323 4324

	case TB_COMMANDTOINDEX:
4325
	    return TOOLBAR_CommandToIndex (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4326

Alexandre Julliard's avatar
Alexandre Julliard committed
4327
	case TB_CUSTOMIZE:
4328
	    return TOOLBAR_Customize (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
4329 4330

	case TB_DELETEBUTTON:
4331
	    return TOOLBAR_DeleteButton (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4332 4333

	case TB_ENABLEBUTTON:
4334
	    return TOOLBAR_EnableButton (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4335

4336 4337
	case TB_GETANCHORHIGHLIGHT:
	    return TOOLBAR_GetAnchorHighlight (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
4338 4339

	case TB_GETBITMAP:
4340
	    return TOOLBAR_GetBitmap (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4341

Alexandre Julliard's avatar
Alexandre Julliard committed
4342
	case TB_GETBITMAPFLAGS:
4343
	    return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4344 4345

	case TB_GETBUTTON:
4346
	    return TOOLBAR_GetButton (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4347

4348
	case TB_GETBUTTONINFOA:
4349
	    return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4350

4351 4352
	case TB_GETBUTTONINFOW:
	    return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4353 4354

	case TB_GETBUTTONSIZE:
4355
	    return TOOLBAR_GetButtonSize (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
4356

4357
	case TB_GETBUTTONTEXTA:
4358
	    return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4359

4360 4361 4362
	case TB_GETBUTTONTEXTW:
	    return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam);

4363
/*	case TB_GETCOLORSCHEME:			*/ /* 4.71 */
Alexandre Julliard's avatar
Alexandre Julliard committed
4364 4365

	case TB_GETDISABLEDIMAGELIST:
4366
	    return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4367

Alexandre Julliard's avatar
Alexandre Julliard committed
4368
	case TB_GETEXTENDEDSTYLE:
4369
	    return TOOLBAR_GetExtendedStyle (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
4370 4371

	case TB_GETHOTIMAGELIST:
4372
	    return TOOLBAR_GetHotImageList (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4373

4374 4375
	case TB_GETHOTITEM:
	    return TOOLBAR_GetHotItem (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
4376 4377

	case TB_GETIMAGELIST:
4378
	    return TOOLBAR_GetImageList (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4379

4380 4381
/*	case TB_GETINSERTMARK:			*/ /* 4.71 */
/*	case TB_GETINSERTMARKCOLOR:		*/ /* 4.71 */
Alexandre Julliard's avatar
Alexandre Julliard committed
4382 4383

	case TB_GETITEMRECT:
4384
	    return TOOLBAR_GetItemRect (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4385

Alexandre Julliard's avatar
Alexandre Julliard committed
4386
	case TB_GETMAXSIZE:
4387
	    return TOOLBAR_GetMaxSize (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4388

4389 4390
/*	case TB_GETOBJECT:			*/ /* 4.71 */
/*	case TB_GETPADDING:			*/ /* 4.71 */
Alexandre Julliard's avatar
Alexandre Julliard committed
4391 4392

	case TB_GETRECT:
4393
	    return TOOLBAR_GetRect (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4394 4395

	case TB_GETROWS:
4396
	    return TOOLBAR_GetRows (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4397 4398

	case TB_GETSTATE:
4399
	    return TOOLBAR_GetState (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4400 4401

	case TB_GETSTYLE:
4402
	    return TOOLBAR_GetStyle (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4403

Alexandre Julliard's avatar
Alexandre Julliard committed
4404
	case TB_GETTEXTROWS:
4405
	    return TOOLBAR_GetTextRows (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4406 4407

	case TB_GETTOOLTIPS:
4408
	    return TOOLBAR_GetToolTips (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4409

Alexandre Julliard's avatar
Alexandre Julliard committed
4410
	case TB_GETUNICODEFORMAT:
4411
	    return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4412

4413 4414 4415
	case CCM_GETVERSION:
	    return TOOLBAR_GetVersion (hwnd);

Alexandre Julliard's avatar
Alexandre Julliard committed
4416
	case TB_HIDEBUTTON:
4417
	    return TOOLBAR_HideButton (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4418 4419

	case TB_HITTEST:
4420
	    return TOOLBAR_HitTest (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4421

Alexandre Julliard's avatar
Alexandre Julliard committed
4422
	case TB_INDETERMINATE:
4423
	    return TOOLBAR_Indeterminate (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4424

4425
	case TB_INSERTBUTTONA:
4426
	    return TOOLBAR_InsertButtonA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4427

4428 4429 4430
	case TB_INSERTBUTTONW:
	    return TOOLBAR_InsertButtonW (hwnd, wParam, lParam);

4431
/*	case TB_INSERTMARKHITTEST:		*/ /* 4.71 */
Alexandre Julliard's avatar
Alexandre Julliard committed
4432 4433

	case TB_ISBUTTONCHECKED:
4434
	    return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4435 4436

	case TB_ISBUTTONENABLED:
4437
	    return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4438 4439

	case TB_ISBUTTONHIDDEN:
4440
	    return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4441 4442

	case TB_ISBUTTONHIGHLIGHTED:
4443
	    return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4444 4445

	case TB_ISBUTTONINDETERMINATE:
4446
	    return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4447 4448

	case TB_ISBUTTONPRESSED:
4449
	    return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4450

4451 4452 4453 4454
	case TB_LOADIMAGES:			   /* 4.70 */
	    FIXME("missing standard imagelists\n");
	    return 0;

4455 4456
/*	case TB_MAPACCELERATORA:		*/ /* 4.71 */
/*	case TB_MAPACCELERATORW:		*/ /* 4.71 */
4457 4458
/*	case TB_MARKBUTTON:			*/ /* 4.71 */
/*	case TB_MOVEBUTTON:			*/ /* 4.71 */
Alexandre Julliard's avatar
Alexandre Julliard committed
4459 4460

	case TB_PRESSBUTTON:
4461
	    return TOOLBAR_PressButton (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4462

4463
/*	case TB_REPLACEBITMAP: */
Alexandre Julliard's avatar
Alexandre Julliard committed
4464

4465
	case TB_SAVERESTOREA:
4466
	    return TOOLBAR_SaveRestoreA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4467

4468 4469 4470 4471 4472
	case TB_SAVERESTOREW:
	    return TOOLBAR_SaveRestoreW (hwnd, wParam, lParam);

	case TB_SETANCHORHIGHLIGHT:
	    return TOOLBAR_SetAnchorHighlight (hwnd, wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4473 4474

	case TB_SETBITMAPSIZE:
4475
	    return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4476

4477
	case TB_SETBUTTONINFOA:
4478
	    return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4479

4480 4481
	case TB_SETBUTTONINFOW:
	    return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4482 4483

	case TB_SETBUTTONSIZE:
4484
	    return TOOLBAR_SetButtonSize (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4485

Alexandre Julliard's avatar
Alexandre Julliard committed
4486
	case TB_SETBUTTONWIDTH:
4487
	    return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4488 4489

	case TB_SETCMDID:
4490
	    return TOOLBAR_SetCmdId (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4491

4492
/*	case TB_SETCOLORSCHEME:			*/ /* 4.71 */
Alexandre Julliard's avatar
Alexandre Julliard committed
4493 4494

	case TB_SETDISABLEDIMAGELIST:
4495
	    return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4496

Alexandre Julliard's avatar
Alexandre Julliard committed
4497
	case TB_SETDRAWTEXTFLAGS:
4498
	    return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4499 4500

	case TB_SETEXTENDEDSTYLE:
4501
	    return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4502 4503

	case TB_SETHOTIMAGELIST:
4504
	    return TOOLBAR_SetHotImageList (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4505

4506 4507
	case TB_SETHOTITEM:
	    return TOOLBAR_SetHotItem (hwnd, wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4508 4509

	case TB_SETIMAGELIST:
4510
	    return TOOLBAR_SetImageList (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4511 4512

	case TB_SETINDENT:
4513
	    return TOOLBAR_SetIndent (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4514

4515
/*	case TB_SETINSERTMARK:			*/ /* 4.71 */
Alexandre Julliard's avatar
Alexandre Julliard committed
4516 4517

	case TB_SETINSERTMARKCOLOR:
4518
	    return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4519

Alexandre Julliard's avatar
Alexandre Julliard committed
4520
	case TB_SETMAXTEXTROWS:
4521
	    return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4522

4523
/*	case TB_SETPADDING:			*/ /* 4.71 */
Alexandre Julliard's avatar
Alexandre Julliard committed
4524 4525

	case TB_SETPARENT:
4526
	    return TOOLBAR_SetParent (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4527 4528

	case TB_SETROWS:
4529
	    return TOOLBAR_SetRows (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4530 4531

	case TB_SETSTATE:
4532
	    return TOOLBAR_SetState (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4533 4534

	case TB_SETSTYLE:
4535
	    return TOOLBAR_SetStyle (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4536

Alexandre Julliard's avatar
Alexandre Julliard committed
4537
	case TB_SETTOOLTIPS:
4538
	    return TOOLBAR_SetToolTips (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4539

Alexandre Julliard's avatar
Alexandre Julliard committed
4540
	case TB_SETUNICODEFORMAT:
4541
	    return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4542

4543 4544 4545
	case CCM_SETVERSION:
	    return TOOLBAR_SetVersion (hwnd, (INT)wParam);

Alexandre Julliard's avatar
Alexandre Julliard committed
4546

4547
/*	case WM_CHAR: */
Alexandre Julliard's avatar
Alexandre Julliard committed
4548

Alexandre Julliard's avatar
Alexandre Julliard committed
4549
	case WM_CREATE:
4550
	    return TOOLBAR_Create (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4551

4552 4553 4554
	case WM_DESTROY:
	  return TOOLBAR_Destroy (hwnd, wParam, lParam);

Alexandre Julliard's avatar
Alexandre Julliard committed
4555
	case WM_ERASEBKGND:
4556
	    return TOOLBAR_EraseBackground (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4557

Eric Pouech's avatar
Eric Pouech committed
4558 4559 4560
	case WM_GETFONT:
		return TOOLBAR_GetFont (hwnd, wParam, lParam);

4561 4562
/*	case WM_KEYDOWN: */
/*	case WM_KILLFOCUS: */
Alexandre Julliard's avatar
Alexandre Julliard committed
4563

Alexandre Julliard's avatar
Alexandre Julliard committed
4564
	case WM_LBUTTONDBLCLK:
4565
	    return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4566 4567

	case WM_LBUTTONDOWN:
4568
	    return TOOLBAR_LButtonDown (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4569 4570

	case WM_LBUTTONUP:
4571
	    return TOOLBAR_LButtonUp (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4572 4573

	case WM_MOUSEMOVE:
4574
	    return TOOLBAR_MouseMove (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4575

4576 4577 4578
	case WM_MOUSELEAVE:
	    return TOOLBAR_MouseLeave (hwnd, wParam, lParam);	

4579 4580 4581
	case WM_CAPTURECHANGED:
	    return TOOLBAR_CaptureChanged(hwnd);	

Alexandre Julliard's avatar
Alexandre Julliard committed
4582
	case WM_NCACTIVATE:
4583
	    return TOOLBAR_NCActivate (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4584 4585

	case WM_NCCALCSIZE:
4586
	    return TOOLBAR_NCCalcSize (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4587

4588 4589 4590
	case WM_NCCREATE:
	    return TOOLBAR_NCCreate (hwnd, wParam, lParam);

Alexandre Julliard's avatar
Alexandre Julliard committed
4591
	case WM_NCPAINT:
4592
	    return TOOLBAR_NCPaint (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4593

Alexandre Julliard's avatar
Alexandre Julliard committed
4594
	case WM_NOTIFY:
4595
	    return TOOLBAR_Notify (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4596

4597
/*	case WM_NOTIFYFORMAT: */
Alexandre Julliard's avatar
Alexandre Julliard committed
4598 4599

	case WM_PAINT:
4600
	    return TOOLBAR_Paint (hwnd, wParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4601 4602

	case WM_SIZE:
4603
	    return TOOLBAR_Size (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4604 4605

	case WM_STYLECHANGED:
4606
	    return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4607

4608
/*	case WM_SYSCOLORCHANGE: */
Alexandre Julliard's avatar
Alexandre Julliard committed
4609

4610
/*	case WM_WININICHANGE: */
Alexandre Julliard's avatar
Alexandre Julliard committed
4611 4612 4613 4614 4615 4616

	case WM_CHARTOITEM:
	case WM_COMMAND:
	case WM_DRAWITEM:
	case WM_MEASUREITEM:
	case WM_VKEYTOITEM:
4617
	    return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4618 4619 4620

	default:
	    if (uMsg >= WM_USER)
4621
		ERR("unknown msg %04x wp=%08x lp=%08lx\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
4622
		     uMsg, wParam, lParam);
4623
	    return DefWindowProcA (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
4624 4625 4626 4627 4628
    }
    return 0;
}


4629
VOID
Patrik Stridvall's avatar
Patrik Stridvall committed
4630
TOOLBAR_Register (void)
Alexandre Julliard's avatar
Alexandre Julliard committed
4631
{
4632
    WNDCLASSA wndClass;
Alexandre Julliard's avatar
Alexandre Julliard committed
4633

4634
    ZeroMemory (&wndClass, sizeof(WNDCLASSA));
Alexandre Julliard's avatar
Alexandre Julliard committed
4635
    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
4636
    wndClass.lpfnWndProc   = (WNDPROC)ToolbarWindowProc;
Alexandre Julliard's avatar
Alexandre Julliard committed
4637 4638
    wndClass.cbClsExtra    = 0;
    wndClass.cbWndExtra    = sizeof(TOOLBAR_INFO *);
4639 4640 4641
    wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
    wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
    wndClass.lpszClassName = TOOLBARCLASSNAMEA;
Alexandre Julliard's avatar
Alexandre Julliard committed
4642
 
4643
    RegisterClassA (&wndClass);
Alexandre Julliard's avatar
Alexandre Julliard committed
4644
}
4645 4646 4647


VOID
Patrik Stridvall's avatar
Patrik Stridvall committed
4648
TOOLBAR_Unregister (void)
4649
{
4650
    UnregisterClassA (TOOLBARCLASSNAMEA, (HINSTANCE)NULL);
4651 4652
}