tooltips.c 74.5 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3
/*
 * Tool tip control
 *
4
 * Copyright 1998, 1999 Eric Kohl
Robert Shearman's avatar
Robert Shearman committed
5
 * Copyright 2004 Robert Shearman
Alexandre Julliard's avatar
Alexandre Julliard committed
6
 *
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
21 22
 * NOTES
 *
Robert Shearman's avatar
Robert Shearman committed
23 24 25 26 27 28 29
 * This code was audited for completeness against the documented features
 * of Comctl32.dll version 6.0 on Sep. 08, 2004, by Robert Shearman.
 * 
 * Unless otherwise noted, we believe this code to be complete, as per
 * the specification mentioned above.
 * If you discover missing features or bugs please note them below.
 * 
Alexandre Julliard's avatar
Alexandre Julliard committed
30
 * TODO:
Alexandre Julliard's avatar
Alexandre Julliard committed
31
 *   - Custom draw support.
Robert Shearman's avatar
Robert Shearman committed
32 33 34 35 36 37 38 39 40 41 42
 *   - Animation.
 *   - Links.
 *   - Messages:
 *     o TTM_ADJUSTRECT
 *     o TTM_GETTITLEA
 *     o TTM_GETTTILEW
 *     o TTM_POPUP
 *   - Styles:
 *     o TTS_NOANIMATE
 *     o TTS_NOFADE
 *     o TTS_CLOSE
Alexandre Julliard's avatar
Alexandre Julliard committed
43 44 45
 *
 * Testing:
 *   - Run tests using Waite Group Windows95 API Bible Volume 2.
Alexandre Julliard's avatar
Alexandre Julliard committed
46 47 48
 *     The second cdrom (chapter 3) contains executables activate.exe,
 *     curtool.exe, deltool.exe, enumtools.exe, getinfo.exe, getiptxt.exe,
 *     hittest.exe, needtext.exe, newrect.exe, updtext.exe and winfrpt.exe.
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
 *
 *   Timer logic.
 *
 * One important point to remember is that tools don't necessarily get
 * a WM_MOUSEMOVE once the cursor leaves the tool, an example is when
 * a tool sets TTF_IDISHWND (i.e. an entire window is a tool) because
 * here WM_MOUSEMOVEs only get sent when the cursor is inside the
 * client area.  Therefore the only reliable way to know that the
 * cursor has left a tool is to keep a timer running and check the
 * position every time it expires.  This is the role of timer
 * ID_TIMERLEAVE.
 *
 *
 * On entering a tool (detected in a relayed WM_MOUSEMOVE) we start
 * ID_TIMERSHOW, if this times out and we're still in the tool we show
 * the tip.  On showing a tip we start both ID_TIMERPOP and
 * ID_TIMERLEAVE.  On hiding a tooltip we kill ID_TIMERPOP.
 * ID_TIMERPOP is restarted on every relayed WM_MOUSEMOVE.  If
 * ID_TIMERPOP expires the tool is hidden and ID_TIMERPOP is killed.
 * ID_TIMERLEAVE remains running - this is important as we need to
 * determine when the cursor leaves the tool.
 *
 * When ID_TIMERLEAVE expires or on a relayed WM_MOUSEMOVE if we're
 * still in the tool do nothing (apart from restart ID_TIMERPOP if
 * this is a WM_MOUSEMOVE) (ID_TIMERLEAVE remains running).  If we've
 * left the tool and entered another one then hide the tip and start
 * ID_TIMERSHOW with time ReshowTime and kill ID_TIMERLEAVE.  If we're
 * outside all tools hide the tip and kill ID_TIMERLEAVE.  On Relayed
 * mouse button messages hide the tip but leave ID_TIMERLEAVE running,
 * this again will let us keep track of when the cursor leaves the
 * tool.
 *
 *
 * infoPtr->nTool is the tool the mouse was on on the last relayed MM
 * or timer expiry or -1 if the mouse was not on a tool.
84
 *
85 86 87 88 89
 * infoPtr->nCurrentTool is the tool for which the tip is currently
 * displaying text for or -1 if the tip is not shown.  Actually this
 * will only ever be infoPtr-nTool or -1, so it could be changed to a
 * BOOL.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
90
 */
91

92 93


94
#include <stdarg.h>
95
#include <string.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
96

97
#include "windef.h"
98
#include "winbase.h"
99
#include "wine/unicode.h"
100 101 102
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
103
#include "commctrl.h"
104
#include "comctl32.h"
105
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
106

107
WINE_DEFAULT_DEBUG_CHANNEL(tooltips);
108

Robert Shearman's avatar
Robert Shearman committed
109 110
static HICON hTooltipIcons[TTI_ERROR+1];

111 112 113 114
typedef struct
{
    UINT      uFlags;
    HWND      hwnd;
115
    BOOL      bNotifyUnicode;
Frank Richter's avatar
Frank Richter committed
116
    UINT_PTR  uId;
117 118 119 120
    RECT      rect;
    HINSTANCE hinst;
    LPWSTR      lpszText;
    LPARAM      lParam;
121
} TTTOOL_INFO;
122 123 124 125 126 127 128 129 130 131 132


typedef struct
{
    WCHAR      szTipText[INFOTIPSIZE];
    BOOL     bActive;
    BOOL     bTrackActive;
    UINT     uNumTools;
    COLORREF   clrBk;
    COLORREF   clrText;
    HFONT    hFont;
Robert Shearman's avatar
Robert Shearman committed
133
    HFONT    hTitleFont;
134 135 136
    INT      xTrackPos;
    INT      yTrackPos;
    INT      nMaxTipWidth;
137
    INT      nTool; /* tool that mouse was on on last relayed mouse move */
138 139 140 141 142 143
    INT      nCurrentTool;
    INT      nTrackTool;
    INT      nReshowTime;
    INT      nAutoPopTime;
    INT      nInitialTime;
    RECT     rcMargin;
144
    BOOL     bToolBelow;
Robert Shearman's avatar
Robert Shearman committed
145 146
    LPWSTR   pszTitle;
    HICON    hTitleIcon;
147 148 149

    TTTOOL_INFO *tools;
} TOOLTIPS_INFO;
150

151 152 153
#define ID_TIMERSHOW   1    /* show delay timer */
#define ID_TIMERPOP    2    /* auto pop timer */
#define ID_TIMERLEAVE  3    /* tool leave timer */
Alexandre Julliard's avatar
Alexandre Julliard committed
154

155

156
#define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongPtrW (hWindow, 0))
Alexandre Julliard's avatar
Alexandre Julliard committed
157

158 159
/* offsets from window edge to start of text */
#define NORMAL_TEXT_MARGIN 2
160
#define BALLOON_TEXT_MARGIN (NORMAL_TEXT_MARGIN+8)
161 162 163
/* value used for CreateRoundRectRgn that specifies how much
 * each corner is curved */
#define BALLOON_ROUNDEDNESS 20
164 165 166
#define BALLOON_STEMHEIGHT 13
#define BALLOON_STEMWIDTH 10
#define BALLOON_STEMINDENT 20
Alexandre Julliard's avatar
Alexandre Julliard committed
167

Robert Shearman's avatar
Robert Shearman committed
168 169 170 171 172
#define BALLOON_ICON_TITLE_SPACING 8 /* horizontal spacing between icon and title */
#define BALLOON_TITLE_TEXT_SPACING 8 /* vertical spacing between icon/title and main text */
#define ICON_HEIGHT 16
#define ICON_WIDTH  16

Robert Shearman's avatar
Robert Shearman committed
173
static LRESULT CALLBACK
174
TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uId, DWORD_PTR dwRef);
Alexandre Julliard's avatar
Alexandre Julliard committed
175 176


Robert Shearman's avatar
Robert Shearman committed
177 178
inline static UINT_PTR
TOOLTIPS_GetTitleIconIndex(HICON hIcon)
Robert Shearman's avatar
Robert Shearman committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
{
    UINT i;
    for (i = 0; i <= TTI_ERROR; i++)
        if (hTooltipIcons[i] == hIcon)
            return i;
    return (UINT_PTR)hIcon;
}

static void
TOOLTIPS_InitSystemSettings (TOOLTIPS_INFO *infoPtr)
{
    NONCLIENTMETRICSW nclm;

    infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
    infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);

    DeleteObject (infoPtr->hFont);
    nclm.cbSize = sizeof(nclm);
197
    SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(nclm), &nclm, 0);
Robert Shearman's avatar
Robert Shearman committed
198 199 200 201 202 203 204
    infoPtr->hFont = CreateFontIndirectW (&nclm.lfStatusFont);

    DeleteObject (infoPtr->hTitleFont);
    nclm.lfStatusFont.lfWeight = FW_BOLD;
    infoPtr->hTitleFont = CreateFontIndirectW (&nclm.lfStatusFont);
}

Robert Shearman's avatar
Robert Shearman committed
205
static void
206
TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
Alexandre Julliard's avatar
Alexandre Julliard committed
207
{
208
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(hwnd);
209 210 211 212 213
    RECT rc;
    INT oldBkMode;
    HFONT hOldFont;
    HBRUSH hBrush;
    UINT uFlags = DT_EXTERNALLEADING;
214 215
    HRGN hRgn = NULL;
    DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
Alexandre Julliard's avatar
Alexandre Julliard committed
216

Alexandre Julliard's avatar
Alexandre Julliard committed
217 218
    if (infoPtr->nMaxTipWidth > -1)
	uFlags |= DT_WORDBREAK;
219
    if (GetWindowLongW (hwnd, GWL_STYLE) & TTS_NOPREFIX)
Alexandre Julliard's avatar
Alexandre Julliard committed
220
	uFlags |= DT_NOPREFIX;
221
    GetClientRect (hwnd, &rc);
222

223
    hBrush = CreateSolidBrush(infoPtr->clrBk);
224

Robert Shearman's avatar
Robert Shearman committed
225 226 227
    oldBkMode = SetBkMode (hdc, TRANSPARENT);
    SetTextColor (hdc, infoPtr->clrText);

228 229 230 231
    if (dwStyle & TTS_BALLOON)
    {
        /* create a region to store result into */
        hRgn = CreateRectRgn(0, 0, 0, 0);
232

233 234 235 236 237 238
        GetWindowRgn(hwnd, hRgn);

        /* fill the background */
        FillRgn(hdc, hRgn, hBrush);
        DeleteObject(hBrush);
        hBrush = NULL;
Robert Shearman's avatar
Robert Shearman committed
239 240 241 242 243 244 245 246
    }
    else
    {
        /* fill the background */
        FillRect(hdc, &rc, hBrush);
        DeleteObject(hBrush);
        hBrush = NULL;
    }
247

Robert Shearman's avatar
Robert Shearman committed
248 249
    if ((dwStyle & TTS_BALLOON) || infoPtr->pszTitle)
    {
250 251 252 253 254
        /* calculate text rectangle */
        rc.left   += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.left);
        rc.top    += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.top);
        rc.right  -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.right);
        rc.bottom -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.bottom);
255
        if(infoPtr->bToolBelow) rc.top += BALLOON_STEMHEIGHT;
Robert Shearman's avatar
Robert Shearman committed
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277

        if (infoPtr->pszTitle)
        {
            RECT rcTitle = {rc.left, rc.top, rc.right, rc.bottom};
            int height;
            BOOL icon_present;

            /* draw icon */
            icon_present = infoPtr->hTitleIcon && 
                DrawIconEx(hdc, rc.left, rc.top, infoPtr->hTitleIcon,
                           ICON_WIDTH, ICON_HEIGHT, 0, NULL, DI_NORMAL);
            if (icon_present)
                rcTitle.left += ICON_WIDTH + BALLOON_ICON_TITLE_SPACING;

            rcTitle.bottom = rc.top + ICON_HEIGHT;

            /* draw title text */
            hOldFont = SelectObject (hdc, infoPtr->hTitleFont);
            height = DrawTextW(hdc, infoPtr->pszTitle, -1, &rcTitle, DT_BOTTOM | DT_SINGLELINE | DT_NOPREFIX);
            SelectObject (hdc, hOldFont);
            rc.top += height + BALLOON_TITLE_TEXT_SPACING;
        }
278 279 280 281 282 283 284 285 286 287 288
    }
    else
    {
        /* calculate text rectangle */
        rc.left   += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.left);
        rc.top    += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.top);
        rc.right  -= (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.right);
        rc.bottom -= (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.bottom);
    }

    /* draw text */
Robert Shearman's avatar
Robert Shearman committed
289
    hOldFont = SelectObject (hdc, infoPtr->hFont);
290
    DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
291
    /* be polite and reset the things we changed in the dc */
292
    SelectObject (hdc, hOldFont);
293 294 295 296 297 298 299 300 301 302 303 304 305 306
    SetBkMode (hdc, oldBkMode);

    if (dwStyle & TTS_BALLOON)
    {
        /* frame region because default window proc doesn't do it */
        INT width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
        INT height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);

        hBrush = GetSysColorBrush(COLOR_WINDOWFRAME);
        FrameRgn(hdc, hRgn, hBrush, width, height);
    }

    if (hRgn)
        DeleteObject(hRgn);
Alexandre Julliard's avatar
Alexandre Julliard committed
307 308
}

309 310 311 312 313 314 315 316 317 318 319 320 321 322
static void TOOLTIPS_GetDispInfoA(HWND hwnd, TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr)
{
    NMTTDISPINFOA ttnmdi;

    /* fill NMHDR struct */
    ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFOA));
    ttnmdi.hdr.hwndFrom = hwnd;
    ttnmdi.hdr.idFrom = toolPtr->uId;
    ttnmdi.hdr.code = TTN_GETDISPINFOA;
    ttnmdi.lpszText = (LPSTR)&ttnmdi.szText;
    ttnmdi.uFlags = toolPtr->uFlags;
    ttnmdi.lParam = toolPtr->lParam;

    TRACE("hdr.idFrom = %x\n", ttnmdi.hdr.idFrom);
323
    SendMessageW(toolPtr->hwnd, WM_NOTIFY,
324 325
                 (WPARAM)toolPtr->uId, (LPARAM)&ttnmdi);

Frank Richter's avatar
Frank Richter committed
326 327
    if (IS_INTRESOURCE(ttnmdi.lpszText)) {
        LoadStringW(ttnmdi.hinst, LOWORD(ttnmdi.lpszText),
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
               infoPtr->szTipText, INFOTIPSIZE);
        if (ttnmdi.uFlags & TTF_DI_SETITEM) {
            toolPtr->hinst = ttnmdi.hinst;
            toolPtr->lpszText = (LPWSTR)ttnmdi.lpszText;
        }
    }
    else if (ttnmdi.lpszText == 0) {
        /* no text available */
        infoPtr->szTipText[0] = '\0';
    }
    else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKA) {
        INT max_len = (ttnmdi.lpszText == &ttnmdi.szText[0]) ? 
                sizeof(ttnmdi.szText)/sizeof(ttnmdi.szText[0]) : -1;
        MultiByteToWideChar(CP_ACP, 0, ttnmdi.lpszText, max_len,
                            infoPtr->szTipText, INFOTIPSIZE);
        if (ttnmdi.uFlags & TTF_DI_SETITEM) {
            INT len = MultiByteToWideChar(CP_ACP, 0, ttnmdi.lpszText,
					  max_len, NULL, 0);
            toolPtr->hinst = 0;
            toolPtr->lpszText =	Alloc (len * sizeof(WCHAR));
            MultiByteToWideChar(CP_ACP, 0, ttnmdi.lpszText, -1,
                                toolPtr->lpszText, len);
        }
    }
    else {
        ERR("recursive text callback!\n");
        infoPtr->szTipText[0] = '\0';
    }
}

static void TOOLTIPS_GetDispInfoW(HWND hwnd, TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr)
{
    NMTTDISPINFOW ttnmdi;

    /* fill NMHDR struct */
    ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFOW));
    ttnmdi.hdr.hwndFrom = hwnd;
    ttnmdi.hdr.idFrom = toolPtr->uId;
    ttnmdi.hdr.code = TTN_GETDISPINFOW;
    ttnmdi.lpszText = (LPWSTR)&ttnmdi.szText;
    ttnmdi.uFlags = toolPtr->uFlags;
    ttnmdi.lParam = toolPtr->lParam;

    TRACE("hdr.idFrom = %x\n", ttnmdi.hdr.idFrom);
    SendMessageW(toolPtr->hwnd, WM_NOTIFY,
                 (WPARAM)toolPtr->uId, (LPARAM)&ttnmdi);

Frank Richter's avatar
Frank Richter committed
375 376
    if (IS_INTRESOURCE(ttnmdi.lpszText)) {
        LoadStringW(ttnmdi.hinst, LOWORD(ttnmdi.lpszText),
377 378 379 380 381 382 383 384 385 386 387 388 389
               infoPtr->szTipText, INFOTIPSIZE);
        if (ttnmdi.uFlags & TTF_DI_SETITEM) {
            toolPtr->hinst = ttnmdi.hinst;
            toolPtr->lpszText = ttnmdi.lpszText;
        }
    }
    else if (ttnmdi.lpszText == 0) {
        /* no text available */
        infoPtr->szTipText[0] = '\0';
    }
    else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKW) {
        INT max_len = (ttnmdi.lpszText == &ttnmdi.szText[0]) ? 
                sizeof(ttnmdi.szText)/sizeof(ttnmdi.szText[0]) : INFOTIPSIZE-1;
390
        lstrcpynW(infoPtr->szTipText, ttnmdi.lpszText, max_len);
391 392 393 394 395 396 397 398 399 400 401 402
        if (ttnmdi.uFlags & TTF_DI_SETITEM) {
            INT len = max(strlenW(ttnmdi.lpszText), max_len);
            toolPtr->hinst = 0;
            toolPtr->lpszText =	Alloc ((len+1) * sizeof(WCHAR));
            memcpy(toolPtr->lpszText, ttnmdi.lpszText, (len+1) * sizeof(WCHAR));
        }
    }
    else {
        ERR("recursive text callback!\n");
        infoPtr->szTipText[0] = '\0';
    }
}
Alexandre Julliard's avatar
Alexandre Julliard committed
403

Robert Shearman's avatar
Robert Shearman committed
404
static void
405
TOOLTIPS_GetTipText (HWND hwnd, TOOLTIPS_INFO *infoPtr, INT nTool)
Alexandre Julliard's avatar
Alexandre Julliard committed
406
{
407
    TTTOOL_INFO *toolPtr = &infoPtr->tools[nTool];
Alexandre Julliard's avatar
Alexandre Julliard committed
408

Frank Richter's avatar
Frank Richter committed
409
    if (IS_INTRESOURCE(toolPtr->lpszText) && toolPtr->hinst) {
410
	/* load a resource */
411
	TRACE("load res string %p %x\n",
Frank Richter's avatar
Frank Richter committed
412 413
	       toolPtr->hinst, LOWORD(toolPtr->lpszText));
	LoadStringW (toolPtr->hinst, LOWORD(toolPtr->lpszText),
Alexandre Julliard's avatar
Alexandre Julliard committed
414 415 416
		       infoPtr->szTipText, INFOTIPSIZE);
    }
    else if (toolPtr->lpszText) {
417
	if (toolPtr->lpszText == LPSTR_TEXTCALLBACKW) {
418 419 420 421
	    if (toolPtr->bNotifyUnicode)
		TOOLTIPS_GetDispInfoW(hwnd, infoPtr, toolPtr);
	    else
		TOOLTIPS_GetDispInfoA(hwnd, infoPtr, toolPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
422
	}
423 424
	else {
	    /* the item is a usual (unicode) text */
425
	    lstrcpynW (infoPtr->szTipText, toolPtr->lpszText, INFOTIPSIZE);
426
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
427
    }
428
    else {
Alexandre Julliard's avatar
Alexandre Julliard committed
429
	/* no text available */
430 431
	infoPtr->szTipText[0] = L'\0';
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
432

433
    TRACE("%s\n", debugstr_w(infoPtr->szTipText));
Alexandre Julliard's avatar
Alexandre Julliard committed
434 435 436
}


Robert Shearman's avatar
Robert Shearman committed
437
static void
438
TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIPS_INFO *infoPtr, LPSIZE lpSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
439
{
440 441
    HDC hdc;
    HFONT hOldFont;
442
    DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
443 444
    UINT uFlags = DT_EXTERNALLEADING | DT_CALCRECT;
    RECT rc = {0, 0, 0, 0};
Robert Shearman's avatar
Robert Shearman committed
445
    SIZE title = {0, 0};
Alexandre Julliard's avatar
Alexandre Julliard committed
446 447 448 449 450

    if (infoPtr->nMaxTipWidth > -1) {
	rc.right = infoPtr->nMaxTipWidth;
	uFlags |= DT_WORDBREAK;
    }
451
    if (style & TTS_NOPREFIX)
Alexandre Julliard's avatar
Alexandre Julliard committed
452
	uFlags |= DT_NOPREFIX;
453
    TRACE("%s\n", debugstr_w(infoPtr->szTipText));
Alexandre Julliard's avatar
Alexandre Julliard committed
454

455
    hdc = GetDC (hwnd);
Robert Shearman's avatar
Robert Shearman committed
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
    if (infoPtr->pszTitle)
    {
        RECT rcTitle = {0, 0, 0, 0};
        TRACE("title %s\n", debugstr_w(infoPtr->pszTitle));
        if (infoPtr->hTitleIcon)
        {
            title.cx = ICON_WIDTH;
            title.cy = ICON_HEIGHT;
        }
        if (title.cx != 0) title.cx += BALLOON_ICON_TITLE_SPACING;
        hOldFont = SelectObject (hdc, infoPtr->hTitleFont);
        DrawTextW(hdc, infoPtr->pszTitle, -1, &rcTitle, DT_SINGLELINE | DT_NOPREFIX | DT_CALCRECT);
        SelectObject (hdc, hOldFont);
        title.cy = max(title.cy, rcTitle.bottom - rcTitle.top) + BALLOON_TITLE_TEXT_SPACING;
        title.cx += (rcTitle.right - rcTitle.left);
    }
472 473 474
    hOldFont = SelectObject (hdc, infoPtr->hFont);
    DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
    SelectObject (hdc, hOldFont);
475
    ReleaseDC (hwnd, hdc);
Alexandre Julliard's avatar
Alexandre Julliard committed
476

Robert Shearman's avatar
Robert Shearman committed
477
    if ((style & TTS_BALLOON) || infoPtr->pszTitle)
478
    {
Robert Shearman's avatar
Robert Shearman committed
479
        lpSize->cx = max(rc.right - rc.left, title.cx) + 2*BALLOON_TEXT_MARGIN +
480
                       infoPtr->rcMargin.left + infoPtr->rcMargin.right;
Robert Shearman's avatar
Robert Shearman committed
481
        lpSize->cy = title.cy + rc.bottom - rc.top + 2*BALLOON_TEXT_MARGIN +
482 483
                       infoPtr->rcMargin.bottom + infoPtr->rcMargin.top +
                       BALLOON_STEMHEIGHT;
484 485 486 487 488 489 490 491
    }
    else
    {
        lpSize->cx = rc.right - rc.left + 2*NORMAL_TEXT_MARGIN +
                       infoPtr->rcMargin.left + infoPtr->rcMargin.right;
        lpSize->cy = rc.bottom - rc.top + 2*NORMAL_TEXT_MARGIN +
                       infoPtr->rcMargin.bottom + infoPtr->rcMargin.top;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
492 493 494
}


Robert Shearman's avatar
Robert Shearman committed
495
static void
496
TOOLTIPS_Show (HWND hwnd, TOOLTIPS_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
497
{
Alexandre Julliard's avatar
Alexandre Julliard committed
498
    TTTOOL_INFO *toolPtr;
499
    RECT rect, wndrect;
500
    SIZE size;
501
    NMHDR  hdr;
502 503
    int ptfx = 0;
    DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
Alexandre Julliard's avatar
Alexandre Julliard committed
504 505

    if (infoPtr->nTool == -1) {
506
	TRACE("invalid tool (-1)!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
507 508
	return;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
509 510 511

    infoPtr->nCurrentTool = infoPtr->nTool;

512
    TRACE("Show tooltip pre %d! (%p)\n", infoPtr->nTool, hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
513

514
    TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nCurrentTool);
Alexandre Julliard's avatar
Alexandre Julliard committed
515

516
    if (infoPtr->szTipText[0] == L'\0') {
Alexandre Julliard's avatar
Alexandre Julliard committed
517 518 519 520
	infoPtr->nCurrentTool = -1;
	return;
    }

521
    TRACE("Show tooltip %d!\n", infoPtr->nCurrentTool);
Alexandre Julliard's avatar
Alexandre Julliard committed
522
    toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
Alexandre Julliard's avatar
Alexandre Julliard committed
523

524
    hdr.hwndFrom = hwnd;
Alexandre Julliard's avatar
Alexandre Julliard committed
525
    hdr.idFrom = toolPtr->uId;
Alexandre Julliard's avatar
Alexandre Julliard committed
526
    hdr.code = TTN_SHOW;
527
    SendMessageW (toolPtr->hwnd, WM_NOTIFY,
528
		    (WPARAM)toolPtr->uId, (LPARAM)&hdr);
Alexandre Julliard's avatar
Alexandre Julliard committed
529

530
    TRACE("%s\n", debugstr_w(infoPtr->szTipText));
Alexandre Julliard's avatar
Alexandre Julliard committed
531

532
    TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
Gerald Pfeifer's avatar
Gerald Pfeifer committed
533
    TRACE("size %ld x %ld\n", size.cx, size.cy);
Alexandre Julliard's avatar
Alexandre Julliard committed
534

535
    if (toolPtr->uFlags & TTF_CENTERTIP) {
536
	RECT rc;
Alexandre Julliard's avatar
Alexandre Julliard committed
537 538

	if (toolPtr->uFlags & TTF_IDISHWND)
539
	    GetWindowRect ((HWND)toolPtr->uId, &rc);
Alexandre Julliard's avatar
Alexandre Julliard committed
540
	else {
Alexandre Julliard's avatar
Alexandre Julliard committed
541
	    rc = toolPtr->rect;
542
	    MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rc, 2);
Alexandre Julliard's avatar
Alexandre Julliard committed
543
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
544
	rect.left = (rc.left + rc.right - size.cx) / 2;
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
	if (style & TTS_BALLOON)
	{
          ptfx = rc.left + ((rc.right - rc.left) / 2);
          if(rect.top - size.cy >= 0)
          {
            rect.top -= size.cy;
            infoPtr->bToolBelow = FALSE;
          }
          else
          {
            infoPtr->bToolBelow = TRUE;
            rect.top += 20;
          }
          rect.left = max(0, rect.left - BALLOON_STEMINDENT);
        }
        else
        {
          rect.top  = rc.bottom + 2;
          infoPtr->bToolBelow = TRUE;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
565 566
    }
    else {
567
	GetCursorPos ((LPPOINT)&rect);
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
	if (style & TTS_BALLOON)
	{
            ptfx = rect.left;
            if(rect.top - size.cy >= 0)
            {
              rect.top -= size.cy;
              infoPtr->bToolBelow = FALSE;
            }
            else
            {
              infoPtr->bToolBelow = TRUE;
              rect.top += 20;
            }
            rect.left = max(0, rect.left - BALLOON_STEMINDENT);
        }
        else
        {
	    rect.top += 20;
	    infoPtr->bToolBelow = TRUE;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
588 589
    }

590
    TRACE("pos %ld - %ld\n", rect.left, rect.top);
Alexandre Julliard's avatar
Alexandre Julliard committed
591 592 593 594

    rect.right = rect.left + size.cx;
    rect.bottom = rect.top + size.cy;

595 596 597 598 599 600 601 602 603 604 605 606 607 608
    /* check position */
    wndrect.right = GetSystemMetrics( SM_CXSCREEN );
    if( rect.right > wndrect.right ) {
	   rect.left -= rect.right - wndrect.right + 2;
	   rect.right = wndrect.right - 2;
    }
    wndrect.bottom = GetSystemMetrics( SM_CYSCREEN );
    if( rect.bottom > wndrect.bottom ) {
        RECT rc;

	if (toolPtr->uFlags & TTF_IDISHWND)
	    GetWindowRect ((HWND)toolPtr->uId, &rc);
	else {
	    rc = toolPtr->rect;
609
	    MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rc, 2);
610
	}
611 612 613 614
	rect.bottom = rc.top - 2;
    	rect.top = rect.bottom - size.cy;
    }

615 616
    AdjustWindowRectEx (&rect, GetWindowLongW (hwnd, GWL_STYLE),
			FALSE, GetWindowLongW (hwnd, GWL_EXSTYLE));
Alexandre Julliard's avatar
Alexandre Julliard committed
617

618
    if (style & TTS_BALLOON)
619 620
    {
        HRGN hRgn;
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
        HRGN hrStem;
        POINT pts[3];

        ptfx -= rect.left;

        if(infoPtr->bToolBelow)
        {
          pts[0].x = ptfx;
          pts[0].y = 0;
          pts[1].x = max(BALLOON_STEMINDENT, ptfx - (BALLOON_STEMWIDTH / 2));
          pts[1].y = BALLOON_STEMHEIGHT;
          pts[2].x = pts[1].x + BALLOON_STEMWIDTH;
          pts[2].y = pts[1].y;
          if(pts[2].x > (rect.right - rect.left) - BALLOON_STEMINDENT)
          {
            pts[2].x = (rect.right - rect.left) - BALLOON_STEMINDENT;
            pts[1].x = pts[2].x - BALLOON_STEMWIDTH;
          }
        }
        else
        {
          pts[0].x = max(BALLOON_STEMINDENT, ptfx - (BALLOON_STEMWIDTH / 2));
          pts[0].y = (rect.bottom - rect.top) - BALLOON_STEMHEIGHT;
          pts[1].x = pts[0].x + BALLOON_STEMWIDTH;
          pts[1].y = pts[0].y;
          pts[2].x = ptfx;
          pts[2].y = (rect.bottom - rect.top);
          if(pts[1].x > (rect.right - rect.left) - BALLOON_STEMINDENT)
          {
            pts[1].x = (rect.right - rect.left) - BALLOON_STEMINDENT;
            pts[0].x = pts[1].x - BALLOON_STEMWIDTH;
          }
        }

        hrStem = CreatePolygonRgn(pts, sizeof(pts) / sizeof(pts[0]), ALTERNATE);
        
        hRgn = CreateRoundRectRgn(0,
                                  (infoPtr->bToolBelow ? BALLOON_STEMHEIGHT : 0),
                                  rect.right - rect.left,
                                  (infoPtr->bToolBelow ? rect.bottom - rect.top : rect.bottom - rect.top - BALLOON_STEMHEIGHT),
                                  BALLOON_ROUNDEDNESS, BALLOON_ROUNDEDNESS);
662

663 664
        CombineRgn(hRgn, hRgn, hrStem, RGN_OR);
        DeleteObject(hrStem);
665 666 667 668 669 670

        SetWindowRgn(hwnd, hRgn, FALSE);
        /* we don't free the region handle as the system deletes it when 
         * it is no longer needed */
    }

671
    SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
Alexandre Julliard's avatar
Alexandre Julliard committed
672
		    rect.right - rect.left, rect.bottom - rect.top,
673
		    SWP_SHOWWINDOW | SWP_NOACTIVATE);
Alexandre Julliard's avatar
Alexandre Julliard committed
674

675
    /* repaint the tooltip */
676 677
    InvalidateRect(hwnd, NULL, TRUE);
    UpdateWindow(hwnd);
678

679
    SetTimer (hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0);
680 681 682
    TRACE("timer 2 started!\n");
    SetTimer (hwnd, ID_TIMERLEAVE, infoPtr->nReshowTime, 0);
    TRACE("timer 3 started!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
683 684 685
}


Robert Shearman's avatar
Robert Shearman committed
686
static void
687
TOOLTIPS_Hide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
Alexandre Julliard's avatar
Alexandre Julliard committed
688
{
Alexandre Julliard's avatar
Alexandre Julliard committed
689
    TTTOOL_INFO *toolPtr;
Alexandre Julliard's avatar
Alexandre Julliard committed
690 691
    NMHDR hdr;

692
    TRACE("Hide tooltip %d! (%p)\n", infoPtr->nCurrentTool, hwnd);
693

Alexandre Julliard's avatar
Alexandre Julliard committed
694 695 696
    if (infoPtr->nCurrentTool == -1)
	return;

Alexandre Julliard's avatar
Alexandre Julliard committed
697
    toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
698
    KillTimer (hwnd, ID_TIMERPOP);
Alexandre Julliard's avatar
Alexandre Julliard committed
699

700
    hdr.hwndFrom = hwnd;
Alexandre Julliard's avatar
Alexandre Julliard committed
701
    hdr.idFrom = toolPtr->uId;
Alexandre Julliard's avatar
Alexandre Julliard committed
702
    hdr.code = TTN_POP;
703
    SendMessageW (toolPtr->hwnd, WM_NOTIFY,
704
		    (WPARAM)toolPtr->uId, (LPARAM)&hdr);
Alexandre Julliard's avatar
Alexandre Julliard committed
705

Alexandre Julliard's avatar
Alexandre Julliard committed
706
    infoPtr->nCurrentTool = -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
707

708
    SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
709
		    SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
Alexandre Julliard's avatar
Alexandre Julliard committed
710 711 712
}


Robert Shearman's avatar
Robert Shearman committed
713
static void
714
TOOLTIPS_TrackShow (HWND hwnd, TOOLTIPS_INFO *infoPtr)
715 716
{
    TTTOOL_INFO *toolPtr;
717 718
    RECT rect;
    SIZE size;
719 720 721
    NMHDR hdr;

    if (infoPtr->nTrackTool == -1) {
722
	TRACE("invalid tracking tool (-1)!\n");
723 724 725
	return;
    }

726
    TRACE("show tracking tooltip pre %d!\n", infoPtr->nTrackTool);
727

728
    TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nTrackTool);
729

730
    if (infoPtr->szTipText[0] == L'\0') {
731 732 733 734
	infoPtr->nTrackTool = -1;
	return;
    }

735
    TRACE("show tracking tooltip %d!\n", infoPtr->nTrackTool);
736 737
    toolPtr = &infoPtr->tools[infoPtr->nTrackTool];

738
    hdr.hwndFrom = hwnd;
739 740
    hdr.idFrom = toolPtr->uId;
    hdr.code = TTN_SHOW;
741
    SendMessageW (toolPtr->hwnd, WM_NOTIFY,
742
		    (WPARAM)toolPtr->uId, (LPARAM)&hdr);
743

744
    TRACE("%s\n", debugstr_w(infoPtr->szTipText));
745

746
    TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
Gerald Pfeifer's avatar
Gerald Pfeifer committed
747
    TRACE("size %ld x %ld\n", size.cx, size.cy);
748 749 750 751 752 753 754 755 756 757 758

    if (toolPtr->uFlags & TTF_ABSOLUTE) {
	rect.left = infoPtr->xTrackPos;
	rect.top  = infoPtr->yTrackPos;

	if (toolPtr->uFlags & TTF_CENTERTIP) {
	    rect.left -= (size.cx / 2);
	    rect.top  -= (size.cy / 2);
	}
    }
    else {
759
	RECT rcTool;
760 761

	if (toolPtr->uFlags & TTF_IDISHWND)
762
	    GetWindowRect ((HWND)toolPtr->uId, &rcTool);
763 764
	else {
	    rcTool = toolPtr->rect;
765
	    MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rcTool, 2);
766
	}
767

768
	GetCursorPos ((LPPOINT)&rect);
769 770 771
	rect.top += 20;

	if (toolPtr->uFlags & TTF_CENTERTIP) {
772 773
	    rect.left -= (size.cx / 2);
	    rect.top  -= (size.cy / 2);
774
	}
775 776 777 778 779

	/* smart placement */
	if ((rect.left + size.cx > rcTool.left) && (rect.left < rcTool.right) &&
	    (rect.top + size.cy > rcTool.top) && (rect.top < rcTool.bottom))
	    rect.left = rcTool.right;
780 781
    }

782
    TRACE("pos %ld - %ld\n", rect.left, rect.top);
783 784 785 786

    rect.right = rect.left + size.cx;
    rect.bottom = rect.top + size.cy;

787 788
    AdjustWindowRectEx (&rect, GetWindowLongW (hwnd, GWL_STYLE),
			FALSE, GetWindowLongW (hwnd, GWL_EXSTYLE));
789

790 791 792 793 794 795 796 797 798 799 800 801
    if (GetWindowLongW(hwnd, GWL_STYLE) & TTS_BALLOON)
    {
        HRGN hRgn;

        /* FIXME: need to add pointy bit using CreatePolyRgn & CombinRgn */
        hRgn = CreateRoundRectRgn(0, 0, rect.right - rect.left, rect.bottom - rect.top, BALLOON_ROUNDEDNESS, BALLOON_ROUNDEDNESS);

        SetWindowRgn(hwnd, hRgn, FALSE);
        /* we don't free the region handle as the system deletes it when 
         * it is no longer needed */
    }

802
    SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
803
		    rect.right - rect.left, rect.bottom - rect.top,
804
		    SWP_SHOWWINDOW | SWP_NOACTIVATE );
805

806 807
    InvalidateRect(hwnd, NULL, TRUE);
    UpdateWindow(hwnd);
808 809 810
}


Robert Shearman's avatar
Robert Shearman committed
811
static void
812
TOOLTIPS_TrackHide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
813 814 815 816
{
    TTTOOL_INFO *toolPtr;
    NMHDR hdr;

817 818
    TRACE("hide tracking tooltip %d\n", infoPtr->nTrackTool);

819 820 821 822 823
    if (infoPtr->nTrackTool == -1)
	return;

    toolPtr = &infoPtr->tools[infoPtr->nTrackTool];

824
    hdr.hwndFrom = hwnd;
825 826
    hdr.idFrom = toolPtr->uId;
    hdr.code = TTN_POP;
827
    SendMessageW (toolPtr->hwnd, WM_NOTIFY,
828
		    (WPARAM)toolPtr->uId, (LPARAM)&hdr);
829

830
    SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
831
		    SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
832 833 834
}


835 836
static INT
TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOA lpToolInfo)
Alexandre Julliard's avatar
Alexandre Julliard committed
837 838
{
    TTTOOL_INFO *toolPtr;
839
    INT nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
840 841 842 843

    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
	toolPtr = &infoPtr->tools[nTool];

844
	if (!(toolPtr->uFlags & TTF_IDISHWND) &&
Alexandre Julliard's avatar
Alexandre Julliard committed
845 846 847 848
	    (lpToolInfo->hwnd == toolPtr->hwnd) &&
	    (lpToolInfo->uId == toolPtr->uId))
	    return nTool;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
849

Alexandre Julliard's avatar
Alexandre Julliard committed
850 851
    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
	toolPtr = &infoPtr->tools[nTool];
Alexandre Julliard's avatar
Alexandre Julliard committed
852

Alexandre Julliard's avatar
Alexandre Julliard committed
853
	if ((toolPtr->uFlags & TTF_IDISHWND) &&
Alexandre Julliard's avatar
Alexandre Julliard committed
854
	    (lpToolInfo->uId == toolPtr->uId))
Alexandre Julliard's avatar
Alexandre Julliard committed
855
	    return nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
856 857 858 859 860
    }

    return -1;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
861

862 863
static INT
TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOW lpToolInfo)
864 865
{
    TTTOOL_INFO *toolPtr;
866
    INT nTool;
867 868 869 870

    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
	toolPtr = &infoPtr->tools[nTool];

871
	if (!(toolPtr->uFlags & TTF_IDISHWND) &&
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
	    (lpToolInfo->hwnd == toolPtr->hwnd) &&
	    (lpToolInfo->uId == toolPtr->uId))
	    return nTool;
    }

    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
	toolPtr = &infoPtr->tools[nTool];

	if ((toolPtr->uFlags & TTF_IDISHWND) &&
	    (lpToolInfo->uId == toolPtr->uId))
	    return nTool;
    }

    return -1;
}


889 890
static INT
TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO *infoPtr, HWND hwnd, LPPOINT lpPt)
Alexandre Julliard's avatar
Alexandre Julliard committed
891 892
{
    TTTOOL_INFO *toolPtr;
893
    INT  nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
894

Alexandre Julliard's avatar
Alexandre Julliard committed
895 896
    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
	toolPtr = &infoPtr->tools[nTool];
Alexandre Julliard's avatar
Alexandre Julliard committed
897

Alexandre Julliard's avatar
Alexandre Julliard committed
898
	if (!(toolPtr->uFlags & TTF_IDISHWND)) {
Alexandre Julliard's avatar
Alexandre Julliard committed
899 900
	    if (hwnd != toolPtr->hwnd)
		continue;
901
	    if (!PtInRect (&toolPtr->rect, *lpPt))
Alexandre Julliard's avatar
Alexandre Julliard committed
902
		continue;
Alexandre Julliard's avatar
Alexandre Julliard committed
903
	    return nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
904 905 906
	}
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
907 908 909 910
    for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
	toolPtr = &infoPtr->tools[nTool];

	if (toolPtr->uFlags & TTF_IDISHWND) {
911
	    if ((HWND)toolPtr->uId == hwnd)
Alexandre Julliard's avatar
Alexandre Julliard committed
912 913 914 915
		return nTool;
	}
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
916 917
    return -1;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
918

Alexandre Julliard's avatar
Alexandre Julliard committed
919

920 921
static BOOL
TOOLTIPS_IsWindowActive (HWND hwnd)
922
{
923
    HWND hwndActive = GetActiveWindow ();
924 925 926 927
    if (!hwndActive)
	return FALSE;
    if (hwndActive == hwnd)
	return TRUE;
928
    return IsChild (hwndActive, hwnd);
929 930 931
}


932
static INT
933
TOOLTIPS_CheckTool (HWND hwnd, BOOL bShowTest)
Alexandre Julliard's avatar
Alexandre Julliard committed
934
{
935
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
936 937 938
    POINT pt;
    HWND hwndTool;
    INT nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
939

940
    GetCursorPos (&pt);
941
    hwndTool = (HWND)SendMessageW (hwnd, TTM_WINDOWFROMPOINT, 0, (LPARAM)&pt);
Alexandre Julliard's avatar
Alexandre Julliard committed
942
    if (hwndTool == 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
943
	return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
944

945
    ScreenToClient (hwndTool, &pt);
Alexandre Julliard's avatar
Alexandre Julliard committed
946
    nTool = TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
Alexandre Julliard's avatar
Alexandre Julliard committed
947 948 949
    if (nTool == -1)
	return -1;

950
    if (!(GetWindowLongW (hwnd, GWL_STYLE) & TTS_ALWAYSTIP) && bShowTest) {
951
	if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd, GW_OWNER)))
Alexandre Julliard's avatar
Alexandre Julliard committed
952 953 954
	    return -1;
    }

955
    TRACE("tool %d\n", nTool);
Alexandre Julliard's avatar
Alexandre Julliard committed
956

Alexandre Julliard's avatar
Alexandre Julliard committed
957
    return nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
958 959 960
}


Alexandre Julliard's avatar
Alexandre Julliard committed
961
static LRESULT
962
TOOLTIPS_Activate (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
963
{
964
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
965

966
    infoPtr->bActive = (BOOL)wParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
967

Alexandre Julliard's avatar
Alexandre Julliard committed
968
    if (infoPtr->bActive)
969
	TRACE("activate!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
970

971
    if (!(infoPtr->bActive) && (infoPtr->nCurrentTool != -1))
972
	TOOLTIPS_Hide (hwnd, infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
973 974 975 976 977 978

    return 0;
}


static LRESULT
979
TOOLTIPS_AddToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
980
{
981
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
982
    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
983
    TTTOOL_INFO *toolPtr;
984
    INT nResult;
Alexandre Julliard's avatar
Alexandre Julliard committed
985

Alexandre Julliard's avatar
Alexandre Julliard committed
986 987
    if (lpToolInfo == NULL)
	return FALSE;
988
    if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
989
	return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
990

991
    TRACE("add tool (%p) %p %d%s!\n",
992
	   hwnd, lpToolInfo->hwnd, lpToolInfo->uId,
Alexandre Julliard's avatar
Alexandre Julliard committed
993 994
	   (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");

Alexandre Julliard's avatar
Alexandre Julliard committed
995
    if (infoPtr->uNumTools == 0) {
996
	infoPtr->tools = Alloc (sizeof(TTTOOL_INFO));
Alexandre Julliard's avatar
Alexandre Julliard committed
997 998 999 1000 1001
	toolPtr = infoPtr->tools;
    }
    else {
	TTTOOL_INFO *oldTools = infoPtr->tools;
	infoPtr->tools =
1002
	    Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
Alexandre Julliard's avatar
Alexandre Julliard committed
1003 1004
	memcpy (infoPtr->tools, oldTools,
		infoPtr->uNumTools * sizeof(TTTOOL_INFO));
1005
	Free (oldTools);
Alexandre Julliard's avatar
Alexandre Julliard committed
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
	toolPtr = &infoPtr->tools[infoPtr->uNumTools];
    }

    infoPtr->uNumTools++;

    /* copy tool data */
    toolPtr->uFlags = lpToolInfo->uFlags;
    toolPtr->hwnd   = lpToolInfo->hwnd;
    toolPtr->uId    = lpToolInfo->uId;
    toolPtr->rect   = lpToolInfo->rect;
    toolPtr->hinst  = lpToolInfo->hinst;

Frank Richter's avatar
Frank Richter committed
1018 1019
    if (IS_INTRESOURCE(lpToolInfo->lpszText)) {
	TRACE("add string id %x!\n", LOWORD(lpToolInfo->lpszText));
1020
	toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
Alexandre Julliard's avatar
Alexandre Julliard committed
1021 1022
    }
    else if (lpToolInfo->lpszText) {
1023
	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA) {
1024
	    TRACE("add CALLBACK!\n");
1025
	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
Alexandre Julliard's avatar
Alexandre Julliard committed
1026
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
1027
	else {
1028 1029
	    INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
					  NULL, 0);
1030
	    TRACE("add text \"%s\"!\n", lpToolInfo->lpszText);
1031
	    toolPtr->lpszText =	Alloc (len * sizeof(WCHAR));
1032 1033
	    MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
				toolPtr->lpszText, len);
Alexandre Julliard's avatar
Alexandre Julliard committed
1034 1035 1036
	}
    }

1037
    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
Alexandre Julliard's avatar
Alexandre Julliard committed
1038 1039
	toolPtr->lParam = lpToolInfo->lParam;

Alexandre Julliard's avatar
Alexandre Julliard committed
1040
    /* install subclassing hook */
Alexandre Julliard's avatar
Alexandre Julliard committed
1041 1042
    if (toolPtr->uFlags & TTF_SUBCLASS) {
	if (toolPtr->uFlags & TTF_IDISHWND) {
1043 1044
	    SetWindowSubclass((HWND)toolPtr->uId, TOOLTIPS_SubclassProc, 1,
			       (DWORD_PTR)hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1045 1046
	}
	else {
1047 1048
	    SetWindowSubclass(toolPtr->hwnd, TOOLTIPS_SubclassProc, 1,
			      (DWORD_PTR)hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1049
	}
1050
	TRACE("subclassing installed!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1051 1052
    }

1053
    nResult = (INT) SendMessageW (toolPtr->hwnd, WM_NOTIFYFORMAT,
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
				  (WPARAM)hwnd, (LPARAM)NF_QUERY);
    if (nResult == NFR_ANSI) {
        toolPtr->bNotifyUnicode = FALSE;
	TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
    } else if (nResult == NFR_UNICODE) {
        toolPtr->bNotifyUnicode = TRUE;
	TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
    } else {
        TRACE (" -- WM_NOTIFYFORMAT returns: error!\n");
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
1065 1066 1067 1068
    return TRUE;
}


1069
static LRESULT
1070
TOOLTIPS_AddToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1071
{
1072
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1073
    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1074
    TTTOOL_INFO *toolPtr;
1075
    INT nResult;
1076 1077 1078

    if (lpToolInfo == NULL)
	return FALSE;
1079
    if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE)
1080 1081
	return FALSE;

1082
    TRACE("add tool (%p) %p %d%s!\n",
1083
	   hwnd, lpToolInfo->hwnd, lpToolInfo->uId,
1084 1085 1086
	   (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");

    if (infoPtr->uNumTools == 0) {
1087
	infoPtr->tools = Alloc (sizeof(TTTOOL_INFO));
1088 1089 1090 1091 1092
	toolPtr = infoPtr->tools;
    }
    else {
	TTTOOL_INFO *oldTools = infoPtr->tools;
	infoPtr->tools =
1093
	    Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
1094 1095
	memcpy (infoPtr->tools, oldTools,
		infoPtr->uNumTools * sizeof(TTTOOL_INFO));
1096
	Free (oldTools);
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
	toolPtr = &infoPtr->tools[infoPtr->uNumTools];
    }

    infoPtr->uNumTools++;

    /* copy tool data */
    toolPtr->uFlags = lpToolInfo->uFlags;
    toolPtr->hwnd   = lpToolInfo->hwnd;
    toolPtr->uId    = lpToolInfo->uId;
    toolPtr->rect   = lpToolInfo->rect;
    toolPtr->hinst  = lpToolInfo->hinst;

Frank Richter's avatar
Frank Richter committed
1109 1110
    if (IS_INTRESOURCE(lpToolInfo->lpszText)) {
	TRACE("add string id %x\n", LOWORD(lpToolInfo->lpszText));
1111 1112 1113
	toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
    }
    else if (lpToolInfo->lpszText) {
1114
	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW) {
1115
	    TRACE("add CALLBACK!\n");
1116
	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1117 1118
	}
	else {
1119
	    INT len = lstrlenW (lpToolInfo->lpszText);
1120
	    TRACE("add text %s!\n",
1121
		   debugstr_w(lpToolInfo->lpszText));
1122
	    toolPtr->lpszText =	Alloc ((len + 1)*sizeof(WCHAR));
1123
	    strcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1124 1125 1126
	}
    }

1127
    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1128 1129 1130 1131 1132
	toolPtr->lParam = lpToolInfo->lParam;

    /* install subclassing hook */
    if (toolPtr->uFlags & TTF_SUBCLASS) {
	if (toolPtr->uFlags & TTF_IDISHWND) {
1133 1134
	    SetWindowSubclass((HWND)toolPtr->uId, TOOLTIPS_SubclassProc, 1,
			      (DWORD_PTR)hwnd);
1135 1136
	}
	else {
1137 1138
	    SetWindowSubclass(toolPtr->hwnd, TOOLTIPS_SubclassProc, 1,
			      (DWORD_PTR)hwnd);
1139
	}
1140
	TRACE("subclassing installed!\n");
1141 1142
    }

1143
    nResult = (INT) SendMessageW (toolPtr->hwnd, WM_NOTIFYFORMAT,
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
				  (WPARAM)hwnd, (LPARAM)NF_QUERY);
    if (nResult == NFR_ANSI) {
        toolPtr->bNotifyUnicode = FALSE;
	TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
    } else if (nResult == NFR_UNICODE) {
        toolPtr->bNotifyUnicode = TRUE;
	TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
    } else {
        TRACE (" -- WM_NOTIFYFORMAT returns: error!\n");
    }

1155 1156
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1157 1158


Robert Shearman's avatar
Robert Shearman committed
1159 1160
static void
TOOLTIPS_DelToolCommon (HWND hwnd, TOOLTIPS_INFO *infoPtr, INT nTool)
Alexandre Julliard's avatar
Alexandre Julliard committed
1161 1162 1163
{
    TTTOOL_INFO *toolPtr;

1164
    TRACE("tool %d\n", nTool);
Alexandre Julliard's avatar
Alexandre Julliard committed
1165

1166 1167 1168
    if (nTool == -1)
        return;

1169 1170
    /* make sure the tooltip has disappeared before deleting it */
    TOOLTIPS_Hide(hwnd, infoPtr);
1171

Alexandre Julliard's avatar
Alexandre Julliard committed
1172
    /* delete text string */
1173
    toolPtr = &infoPtr->tools[nTool];
1174
    if (toolPtr->lpszText) {
1175
	if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) &&
Frank Richter's avatar
Frank Richter committed
1176
	     !IS_INTRESOURCE(toolPtr->lpszText) )
1177
	    Free (toolPtr->lpszText);
Alexandre Julliard's avatar
Alexandre Julliard committed
1178 1179
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
1180 1181 1182
    /* remove subclassing */
    if (toolPtr->uFlags & TTF_SUBCLASS) {
	if (toolPtr->uFlags & TTF_IDISHWND) {
1183
	    RemoveWindowSubclass((HWND)toolPtr->uId, TOOLTIPS_SubclassProc, 1);
Alexandre Julliard's avatar
Alexandre Julliard committed
1184 1185
	}
	else {
1186
	    RemoveWindowSubclass(toolPtr->hwnd, TOOLTIPS_SubclassProc, 1);
Alexandre Julliard's avatar
Alexandre Julliard committed
1187 1188 1189
	}
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
1190 1191
    /* delete tool from tool list */
    if (infoPtr->uNumTools == 1) {
1192
	Free (infoPtr->tools);
Alexandre Julliard's avatar
Alexandre Julliard committed
1193 1194 1195 1196 1197
	infoPtr->tools = NULL;
    }
    else {
	TTTOOL_INFO *oldTools = infoPtr->tools;
	infoPtr->tools =
1198
	    Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
Alexandre Julliard's avatar
Alexandre Julliard committed
1199

Alexandre Julliard's avatar
Alexandre Julliard committed
1200
	if (nTool > 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
1201
	    memcpy (&infoPtr->tools[0], &oldTools[0],
Alexandre Julliard's avatar
Alexandre Julliard committed
1202
		    nTool * sizeof(TTTOOL_INFO));
Alexandre Julliard's avatar
Alexandre Julliard committed
1203

Alexandre Julliard's avatar
Alexandre Julliard committed
1204 1205 1206
	if (nTool < infoPtr->uNumTools - 1)
	    memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
		    (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
Alexandre Julliard's avatar
Alexandre Julliard committed
1207

1208
	Free (oldTools);
Alexandre Julliard's avatar
Alexandre Julliard committed
1209 1210
    }

1211 1212
    /* update any indices affected by delete */

1213 1214
    /* destroying tool that mouse was on on last relayed mouse move */
    if (infoPtr->nTool == nTool)
1215
        /* -1 means no current tool (0 means first tool) */
1216
        infoPtr->nTool = -1;
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
    else if (infoPtr->nTool > nTool)
        infoPtr->nTool--;

    if (infoPtr->nTrackTool == nTool)
        /* -1 means no current tool (0 means first tool) */
        infoPtr->nTrackTool = -1;
    else if (infoPtr->nTrackTool > nTool)
        infoPtr->nTrackTool--;

    if (infoPtr->nCurrentTool == nTool)
        /* -1 means no current tool (0 means first tool) */
        infoPtr->nCurrentTool = -1;
    else if (infoPtr->nCurrentTool > nTool)
        infoPtr->nCurrentTool--;
1231

Alexandre Julliard's avatar
Alexandre Julliard committed
1232
    infoPtr->uNumTools--;
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
}

static LRESULT
TOOLTIPS_DelToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
    INT nTool;

    if (lpToolInfo == NULL)
	return 0;
    if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE)
	return 0;
    if (infoPtr->uNumTools == 0)
	return 0;

    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);

    TOOLTIPS_DelToolCommon (hwnd, infoPtr, nTool);
1252

Alexandre Julliard's avatar
Alexandre Julliard committed
1253 1254 1255 1256
    return 0;
}


1257
static LRESULT
1258
TOOLTIPS_DelToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1259
{
1260
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1261 1262
    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
    INT nTool;
1263 1264 1265

    if (lpToolInfo == NULL)
	return 0;
1266
    if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE)
1267 1268 1269 1270 1271 1272
	return 0;
    if (infoPtr->uNumTools == 0)
	return 0;

    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);

1273
    TOOLTIPS_DelToolCommon (hwnd, infoPtr, nTool);
1274

1275 1276
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1277 1278 1279


static LRESULT
1280
TOOLTIPS_EnumToolsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1281
{
1282
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1283 1284
    UINT uIndex = (UINT)wParam;
    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
1285 1286
    TTTOOL_INFO *toolPtr;

Alexandre Julliard's avatar
Alexandre Julliard committed
1287 1288
    if (lpToolInfo == NULL)
	return FALSE;
1289
    if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
1290 1291 1292
	return FALSE;
    if (uIndex >= infoPtr->uNumTools)
	return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1293

1294
    TRACE("index=%u\n", uIndex);
Alexandre Julliard's avatar
Alexandre Julliard committed
1295 1296 1297 1298 1299 1300 1301 1302 1303

    toolPtr = &infoPtr->tools[uIndex];

    /* copy tool data */
    lpToolInfo->uFlags   = toolPtr->uFlags;
    lpToolInfo->hwnd     = toolPtr->hwnd;
    lpToolInfo->uId      = toolPtr->uId;
    lpToolInfo->rect     = toolPtr->rect;
    lpToolInfo->hinst    = toolPtr->hinst;
1304
/*    lpToolInfo->lpszText = toolPtr->lpszText; */
1305
    lpToolInfo->lpszText = NULL;  /* FIXME */
Alexandre Julliard's avatar
Alexandre Julliard committed
1306

1307
    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
Alexandre Julliard's avatar
Alexandre Julliard committed
1308 1309 1310 1311 1312 1313
	lpToolInfo->lParam = toolPtr->lParam;

    return TRUE;
}


1314
static LRESULT
1315
TOOLTIPS_EnumToolsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1316
{
1317
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1318 1319
    UINT uIndex = (UINT)wParam;
    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1320 1321 1322 1323
    TTTOOL_INFO *toolPtr;

    if (lpToolInfo == NULL)
	return FALSE;
1324
    if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE)
1325 1326 1327 1328
	return FALSE;
    if (uIndex >= infoPtr->uNumTools)
	return FALSE;

1329
    TRACE("index=%u\n", uIndex);
1330 1331 1332 1333 1334 1335 1336 1337 1338

    toolPtr = &infoPtr->tools[uIndex];

    /* copy tool data */
    lpToolInfo->uFlags   = toolPtr->uFlags;
    lpToolInfo->hwnd     = toolPtr->hwnd;
    lpToolInfo->uId      = toolPtr->uId;
    lpToolInfo->rect     = toolPtr->rect;
    lpToolInfo->hinst    = toolPtr->hinst;
1339
/*    lpToolInfo->lpszText = toolPtr->lpszText; */
1340 1341
    lpToolInfo->lpszText = NULL;  /* FIXME */

1342
    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1343 1344 1345 1346
	lpToolInfo->lParam = toolPtr->lParam;

    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1347

1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
static LRESULT
TOOLTIPS_GetBubbleSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
    INT nTool;
    SIZE size;

    if (lpToolInfo == NULL)
	return FALSE;
1358
    if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE)
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370
	return FALSE;

    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
    if (nTool == -1) return 0;

    TRACE("tool %d\n", nTool);

    TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
    TRACE("size %ld x %ld\n", size.cx, size.cy);

    return MAKELRESULT(size.cx, size.cy);
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1371 1372

static LRESULT
1373
TOOLTIPS_GetCurrentToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1374
{
1375
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1376
    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
1377
    TTTOOL_INFO *toolPtr;
Alexandre Julliard's avatar
Alexandre Julliard committed
1378

Alexandre Julliard's avatar
Alexandre Julliard committed
1379 1380
    if (lpToolInfo == NULL)
	return FALSE;
1381
    if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
1382 1383 1384
	return FALSE;

    if (lpToolInfo) {
Alexandre Julliard's avatar
Alexandre Julliard committed
1385 1386 1387 1388
	if (infoPtr->nCurrentTool > -1) {
	    toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];

	    /* copy tool data */
Alexandre Julliard's avatar
Alexandre Julliard committed
1389 1390 1391
	    lpToolInfo->uFlags   = toolPtr->uFlags;
	    lpToolInfo->rect     = toolPtr->rect;
	    lpToolInfo->hinst    = toolPtr->hinst;
1392
/*	    lpToolInfo->lpszText = toolPtr->lpszText; */
1393
	    lpToolInfo->lpszText = NULL;  /* FIXME */
Alexandre Julliard's avatar
Alexandre Julliard committed
1394

1395
	    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
Alexandre Julliard's avatar
Alexandre Julliard committed
1396
		lpToolInfo->lParam = toolPtr->lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
1397 1398 1399 1400 1401 1402 1403

	    return TRUE;
	}
	else
	    return FALSE;
    }
    else
Alexandre Julliard's avatar
Alexandre Julliard committed
1404
	return (infoPtr->nCurrentTool != -1);
Alexandre Julliard's avatar
Alexandre Julliard committed
1405 1406 1407
}


1408
static LRESULT
1409
TOOLTIPS_GetCurrentToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1410
{
1411
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1412
    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1413 1414 1415 1416
    TTTOOL_INFO *toolPtr;

    if (lpToolInfo == NULL)
	return FALSE;
1417
    if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE)
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
	return FALSE;

    if (lpToolInfo) {
	if (infoPtr->nCurrentTool > -1) {
	    toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];

	    /* copy tool data */
	    lpToolInfo->uFlags   = toolPtr->uFlags;
	    lpToolInfo->rect     = toolPtr->rect;
	    lpToolInfo->hinst    = toolPtr->hinst;
1428
/*	    lpToolInfo->lpszText = toolPtr->lpszText; */
1429 1430
	    lpToolInfo->lpszText = NULL;  /* FIXME */

1431
	    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441
		lpToolInfo->lParam = toolPtr->lParam;

	    return TRUE;
	}
	else
	    return FALSE;
    }
    else
	return (infoPtr->nCurrentTool != -1);
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1442 1443 1444


static LRESULT
1445
TOOLTIPS_GetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1446
{
1447
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1448 1449

    switch (wParam) {
1450 1451
    case TTDT_RESHOW:
        return infoPtr->nReshowTime;
Alexandre Julliard's avatar
Alexandre Julliard committed
1452

1453 1454
    case TTDT_AUTOPOP:
        return infoPtr->nAutoPopTime;
Alexandre Julliard's avatar
Alexandre Julliard committed
1455

1456 1457 1458
    case TTDT_INITIAL:
    case TTDT_AUTOMATIC: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */
        return infoPtr->nInitialTime;
Alexandre Julliard's avatar
Alexandre Julliard committed
1459

1460 1461 1462
    default:
        WARN("Invalid wParam %x\n", wParam);
	break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1463 1464
    }

1465
    return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
1466 1467 1468 1469
}


static LRESULT
1470
TOOLTIPS_GetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1471
{
1472
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1473
    LPRECT lpRect = (LPRECT)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
1474 1475 1476 1477 1478 1479 1480 1481

    lpRect->left   = infoPtr->rcMargin.left;
    lpRect->right  = infoPtr->rcMargin.right;
    lpRect->bottom = infoPtr->rcMargin.bottom;
    lpRect->top    = infoPtr->rcMargin.top;

    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1482 1483


Patrik Stridvall's avatar
Patrik Stridvall committed
1484
inline static LRESULT
1485
TOOLTIPS_GetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1486
{
1487
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1488

Alexandre Julliard's avatar
Alexandre Julliard committed
1489
    return infoPtr->nMaxTipWidth;
Alexandre Julliard's avatar
Alexandre Julliard committed
1490 1491 1492 1493
}


static LRESULT
1494
TOOLTIPS_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1495
{
1496
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1497 1498
    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
    INT nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
1499

Alexandre Julliard's avatar
Alexandre Julliard committed
1500 1501
    if (lpToolInfo == NULL)
	return 0;
1502
    if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
1503
	return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1504

Alexandre Julliard's avatar
Alexandre Julliard committed
1505
    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
Alexandre Julliard's avatar
Alexandre Julliard committed
1506
    if (nTool == -1) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1507

1508 1509
    /* NB this API is broken, there is no way for the app to determine
       what size buffer it requires nor a way to specify how long the
1510
       one it supplies is.  We'll assume it's up to INFOTIPSIZE */
1511 1512 1513

    WideCharToMultiByte(CP_ACP, 0, infoPtr->tools[nTool].lpszText, -1,
			lpToolInfo->lpszText, INFOTIPSIZE, NULL, NULL);
Alexandre Julliard's avatar
Alexandre Julliard committed
1514 1515 1516 1517 1518

    return 0;
}


1519
static LRESULT
1520
TOOLTIPS_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1521
{
1522
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1523 1524
    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
    INT nTool;
1525 1526 1527

    if (lpToolInfo == NULL)
	return 0;
1528
    if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE)
1529 1530 1531 1532 1533
	return 0;

    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
    if (nTool == -1) return 0;

1534
    strcpyW (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
1535 1536 1537

    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1538 1539


Patrik Stridvall's avatar
Patrik Stridvall committed
1540
inline static LRESULT
1541
TOOLTIPS_GetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1542
{
1543
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1544 1545 1546 1547
    return infoPtr->clrBk;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
1548
inline static LRESULT
1549
TOOLTIPS_GetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1550
{
1551
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1552 1553 1554 1555
    return infoPtr->clrText;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
1556
inline static LRESULT
1557
TOOLTIPS_GetToolCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1558
{
1559
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1560 1561 1562 1563 1564
    return infoPtr->uNumTools;
}


static LRESULT
1565
TOOLTIPS_GetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1566
{
1567
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1568
    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
1569
    TTTOOL_INFO *toolPtr;
1570
    INT nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
1571

Alexandre Julliard's avatar
Alexandre Julliard committed
1572 1573
    if (lpToolInfo == NULL)
	return FALSE;
1574
    if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
1575 1576 1577
	return FALSE;
    if (infoPtr->uNumTools == 0)
	return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1578

Alexandre Julliard's avatar
Alexandre Julliard committed
1579
    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1580 1581
    if (nTool == -1)
	return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1582

1583
    TRACE("tool %d\n", nTool);
Alexandre Julliard's avatar
Alexandre Julliard committed
1584

Alexandre Julliard's avatar
Alexandre Julliard committed
1585
    toolPtr = &infoPtr->tools[nTool];
Alexandre Julliard's avatar
Alexandre Julliard committed
1586 1587 1588 1589 1590

    /* copy tool data */
    lpToolInfo->uFlags   = toolPtr->uFlags;
    lpToolInfo->rect     = toolPtr->rect;
    lpToolInfo->hinst    = toolPtr->hinst;
1591
/*    lpToolInfo->lpszText = toolPtr->lpszText; */
1592
    lpToolInfo->lpszText = NULL;  /* FIXME */
Alexandre Julliard's avatar
Alexandre Julliard committed
1593

1594
    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
Alexandre Julliard's avatar
Alexandre Julliard committed
1595 1596 1597 1598 1599 1600
	lpToolInfo->lParam = toolPtr->lParam;

    return TRUE;
}


1601
static LRESULT
1602
TOOLTIPS_GetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1603
{
1604
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1605
    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1606
    TTTOOL_INFO *toolPtr;
1607
    INT nTool;
1608 1609 1610

    if (lpToolInfo == NULL)
	return FALSE;
1611
    if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE)
1612 1613 1614 1615 1616 1617 1618 1619
	return FALSE;
    if (infoPtr->uNumTools == 0)
	return FALSE;

    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
    if (nTool == -1)
	return FALSE;

1620
    TRACE("tool %d\n", nTool);
1621 1622 1623 1624 1625 1626 1627

    toolPtr = &infoPtr->tools[nTool];

    /* copy tool data */
    lpToolInfo->uFlags   = toolPtr->uFlags;
    lpToolInfo->rect     = toolPtr->rect;
    lpToolInfo->hinst    = toolPtr->hinst;
1628
/*    lpToolInfo->lpszText = toolPtr->lpszText; */
1629 1630
    lpToolInfo->lpszText = NULL;  /* FIXME */

1631
    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1632 1633 1634 1635
	lpToolInfo->lParam = toolPtr->lParam;

    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1636 1637 1638


static LRESULT
1639
TOOLTIPS_HitTestA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1640
{
1641
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1642
    LPTTHITTESTINFOA lptthit = (LPTTHITTESTINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
1643
    TTTOOL_INFO *toolPtr;
1644
    INT nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
1645 1646 1647 1648

    if (lptthit == 0)
	return FALSE;

Alexandre Julliard's avatar
Alexandre Julliard committed
1649
    nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
Alexandre Julliard's avatar
Alexandre Julliard committed
1650 1651 1652
    if (nTool == -1)
	return FALSE;

1653
    TRACE("tool %d!\n", nTool);
Alexandre Julliard's avatar
Alexandre Julliard committed
1654 1655

    /* copy tool data */
1656
    if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOA)) {
1657 1658 1659 1660 1661 1662 1663
	toolPtr = &infoPtr->tools[nTool];

	lptthit->ti.uFlags   = toolPtr->uFlags;
	lptthit->ti.hwnd     = toolPtr->hwnd;
	lptthit->ti.uId      = toolPtr->uId;
	lptthit->ti.rect     = toolPtr->rect;
	lptthit->ti.hinst    = toolPtr->hinst;
1664
/*	lptthit->ti.lpszText = toolPtr->lpszText; */
1665 1666 1667
	lptthit->ti.lpszText = NULL;  /* FIXME */
	lptthit->ti.lParam   = toolPtr->lParam;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1668 1669 1670 1671 1672

    return TRUE;
}


1673
static LRESULT
1674
TOOLTIPS_HitTestW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1675
{
1676
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1677
    LPTTHITTESTINFOW lptthit = (LPTTHITTESTINFOW)lParam;
1678
    TTTOOL_INFO *toolPtr;
1679
    INT nTool;
1680 1681 1682 1683 1684 1685 1686 1687

    if (lptthit == 0)
	return FALSE;

    nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
    if (nTool == -1)
	return FALSE;

1688
    TRACE("tool %d!\n", nTool);
1689 1690

    /* copy tool data */
1691
    if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOW)) {
1692 1693 1694 1695 1696 1697 1698
	toolPtr = &infoPtr->tools[nTool];

	lptthit->ti.uFlags   = toolPtr->uFlags;
	lptthit->ti.hwnd     = toolPtr->hwnd;
	lptthit->ti.uId      = toolPtr->uId;
	lptthit->ti.rect     = toolPtr->rect;
	lptthit->ti.hinst    = toolPtr->hinst;
1699
/*	lptthit->ti.lpszText = toolPtr->lpszText; */
1700 1701 1702 1703 1704 1705
	lptthit->ti.lpszText = NULL;  /* FIXME */
	lptthit->ti.lParam   = toolPtr->lParam;
    }

    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1706 1707 1708


static LRESULT
1709
TOOLTIPS_NewToolRectA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1710
{
1711
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1712 1713
    LPTTTOOLINFOA lpti = (LPTTTOOLINFOA)lParam;
    INT nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
1714

Alexandre Julliard's avatar
Alexandre Julliard committed
1715 1716
    if (lpti == NULL)
	return 0;
1717
    if (lpti->cbSize < TTTOOLINFOA_V1_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
1718
	return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1719

Alexandre Julliard's avatar
Alexandre Julliard committed
1720
    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpti);
1721 1722 1723

    TRACE("nTool = %d, rect = %s\n", nTool, wine_dbgstr_rect(&lpti->rect));

Alexandre Julliard's avatar
Alexandre Julliard committed
1724
    if (nTool == -1) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1725

Alexandre Julliard's avatar
Alexandre Julliard committed
1726
    infoPtr->tools[nTool].rect = lpti->rect;
Alexandre Julliard's avatar
Alexandre Julliard committed
1727 1728 1729 1730 1731

    return 0;
}


1732
static LRESULT
1733
TOOLTIPS_NewToolRectW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1734
{
1735
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1736 1737
    LPTTTOOLINFOW lpti = (LPTTTOOLINFOW)lParam;
    INT nTool;
1738 1739 1740

    if (lpti == NULL)
	return 0;
1741
    if (lpti->cbSize < TTTOOLINFOW_V1_SIZE)
1742 1743 1744
	return FALSE;

    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpti);
1745 1746 1747

    TRACE("nTool = %d, rect = %s\n", nTool, wine_dbgstr_rect(&lpti->rect));

1748 1749 1750 1751 1752 1753
    if (nTool == -1) return 0;

    infoPtr->tools[nTool].rect = lpti->rect;

    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1754 1755


Patrik Stridvall's avatar
Patrik Stridvall committed
1756
inline static LRESULT
1757
TOOLTIPS_Pop (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1758
{
1759 1760
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
    TOOLTIPS_Hide (hwnd, infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
1761 1762 1763

    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1764 1765 1766


static LRESULT
1767
TOOLTIPS_RelayEvent (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1768
{
1769
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1770 1771
    LPMSG lpMsg = (LPMSG)lParam;
    POINT pt;
1772
    INT nOldTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
1773

Alexandre Julliard's avatar
Alexandre Julliard committed
1774
    if (lParam == 0) {
1775
	ERR("lpMsg == NULL!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1776 1777
	return 0;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1778

Alexandre Julliard's avatar
Alexandre Julliard committed
1779 1780 1781 1782 1783 1784 1785
    switch (lpMsg->message) {
	case WM_LBUTTONDOWN:
	case WM_LBUTTONUP:
	case WM_MBUTTONDOWN:
	case WM_MBUTTONUP:
	case WM_RBUTTONDOWN:
	case WM_RBUTTONUP:
1786
	    TOOLTIPS_Hide (hwnd, infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
1787 1788 1789
	    break;

	case WM_MOUSEMOVE:
1790 1791 1792 1793 1794
	    pt.x = LOWORD(lpMsg->lParam);
	    pt.y = HIWORD(lpMsg->lParam);
	    nOldTool = infoPtr->nTool;
	    infoPtr->nTool = TOOLTIPS_GetToolFromPoint(infoPtr, lpMsg->hwnd,
						       &pt);
1795
	    TRACE("tool (%p) %d %d %d\n", hwnd, nOldTool,
1796
		  infoPtr->nTool, infoPtr->nCurrentTool);
1797
	    TRACE("WM_MOUSEMOVE (%p %ld %ld)\n", hwnd, pt.x, pt.y);
1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814

	    if (infoPtr->nTool != nOldTool) {
	        if(infoPtr->nTool == -1) { /* Moved out of all tools */
		    TOOLTIPS_Hide(hwnd, infoPtr);
		    KillTimer(hwnd, ID_TIMERLEAVE);
		} else if (nOldTool == -1) { /* Moved from outside */
		    if(infoPtr->bActive) {
		        SetTimer(hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0);
			TRACE("timer 1 started!\n");
		    }
		} else { /* Moved from one to another */
		    TOOLTIPS_Hide (hwnd, infoPtr);
		    KillTimer(hwnd, ID_TIMERLEAVE);
		    if(infoPtr->bActive) {
		        SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
			TRACE("timer 1 started!\n");
		    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1815
		}
1816 1817 1818 1819
	    } else if(infoPtr->nCurrentTool != -1) { /* restart autopop */
	        KillTimer(hwnd, ID_TIMERPOP);
		SetTimer(hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0);
		TRACE("timer 2 restarted\n");
1820 1821 1822 1823
	    } else if(infoPtr->nTool != -1 && infoPtr->bActive) {
                /* previous show attempt didn't result in tooltip so try again */
		SetTimer(hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0);
		TRACE("timer 1 started!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1824 1825
	    }
	    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1826 1827
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
1828 1829 1830 1831 1832
    return 0;
}


static LRESULT
1833
TOOLTIPS_SetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1834
{
1835
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1836
    INT nTime = (INT)LOWORD(lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
1837 1838

    switch (wParam) {
1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862
    case TTDT_AUTOMATIC:
        if (nTime <= 0)
	    nTime = GetDoubleClickTime();
	infoPtr->nReshowTime    = nTime / 5;
	infoPtr->nAutoPopTime   = nTime * 10;
	infoPtr->nInitialTime   = nTime;
	break;

    case TTDT_RESHOW:
        if(nTime < 0)
	    nTime = GetDoubleClickTime() / 5;
	infoPtr->nReshowTime = nTime;
	break;

    case TTDT_AUTOPOP:
        if(nTime < 0)
	    nTime = GetDoubleClickTime() * 10;
	infoPtr->nAutoPopTime = nTime;
	break;

    case TTDT_INITIAL:
        if(nTime < 0)
	    nTime = GetDoubleClickTime();
	infoPtr->nInitialTime = nTime;
Alexandre Julliard's avatar
Alexandre Julliard committed
1863 1864
	    break;

1865 1866 1867
    default:
        WARN("Invalid wParam %x\n", wParam);
	break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1868
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1869 1870 1871 1872 1873

    return 0;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1874
static LRESULT
1875
TOOLTIPS_SetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1876
{
1877
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1878
    LPRECT lpRect = (LPRECT)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
1879 1880 1881 1882 1883 1884 1885 1886

    infoPtr->rcMargin.left   = lpRect->left;
    infoPtr->rcMargin.right  = lpRect->right;
    infoPtr->rcMargin.bottom = lpRect->bottom;
    infoPtr->rcMargin.top    = lpRect->top;

    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1887 1888


Patrik Stridvall's avatar
Patrik Stridvall committed
1889
inline static LRESULT
1890
TOOLTIPS_SetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1891
{
1892
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1893
    INT nTemp = infoPtr->nMaxTipWidth;
Alexandre Julliard's avatar
Alexandre Julliard committed
1894

1895
    infoPtr->nMaxTipWidth = (INT)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
1896

Alexandre Julliard's avatar
Alexandre Julliard committed
1897
    return nTemp;
Alexandre Julliard's avatar
Alexandre Julliard committed
1898 1899 1900
}


Patrik Stridvall's avatar
Patrik Stridvall committed
1901
inline static LRESULT
1902
TOOLTIPS_SetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1903
{
1904
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1905 1906 1907 1908 1909 1910 1911

    infoPtr->clrBk = (COLORREF)wParam;

    return 0;
}


Patrik Stridvall's avatar
Patrik Stridvall committed
1912
inline static LRESULT
1913
TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1914
{
1915
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1916 1917 1918 1919 1920 1921 1922

    infoPtr->clrText = (COLORREF)wParam;

    return 0;
}


Robert Shearman's avatar
Robert Shearman committed
1923 1924 1925 1926 1927
static LRESULT
TOOLTIPS_SetTitleA (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
    LPCSTR pszTitle = (LPCSTR)lParam;
1928
    UINT_PTR uTitleIcon = (UINT_PTR)wParam;
Robert Shearman's avatar
Robert Shearman committed
1929 1930
    UINT size;

1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
    TRACE("hwnd = %p, title = %s, icon = %p\n", hwnd, debugstr_a(pszTitle),
        (void*)uTitleIcon);

    Free(infoPtr->pszTitle);

    if (pszTitle)
    {
        size = sizeof(WCHAR)*MultiByteToWideChar(CP_ACP, 0, pszTitle, -1, NULL, 0);
        infoPtr->pszTitle = Alloc(size);
        if (!infoPtr->pszTitle)
            return FALSE;
        MultiByteToWideChar(CP_ACP, 0, pszTitle, -1, infoPtr->pszTitle, size/sizeof(WCHAR));
    }
    else
        infoPtr->pszTitle = NULL;
Robert Shearman's avatar
Robert Shearman committed
1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960

    if (uTitleIcon <= TTI_ERROR)
        infoPtr->hTitleIcon = hTooltipIcons[uTitleIcon];
    else
        infoPtr->hTitleIcon = CopyIcon((HICON)wParam);

    return TRUE;
}


static LRESULT
TOOLTIPS_SetTitleW (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
    LPCWSTR pszTitle = (LPCWSTR)lParam;
1961
    UINT_PTR uTitleIcon = (UINT_PTR)wParam;
Robert Shearman's avatar
Robert Shearman committed
1962 1963
    UINT size;

1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978
    TRACE("hwnd = %p, title = %s, icon = %p\n", hwnd, debugstr_w(pszTitle),
        (void*)uTitleIcon);

    Free(infoPtr->pszTitle);

    if (pszTitle)
    {
        size = (strlenW(pszTitle)+1)*sizeof(WCHAR);
        infoPtr->pszTitle = Alloc(size);
        if (!infoPtr->pszTitle)
            return FALSE;
        memcpy(infoPtr->pszTitle, pszTitle, size);
    }
    else
        infoPtr->pszTitle = NULL;
Robert Shearman's avatar
Robert Shearman committed
1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990

    if (uTitleIcon <= TTI_ERROR)
        infoPtr->hTitleIcon = hTooltipIcons[uTitleIcon];
    else
        infoPtr->hTitleIcon = CopyIcon((HICON)wParam);

    TRACE("icon = %p\n", infoPtr->hTitleIcon);

    return TRUE;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1991
static LRESULT
1992
TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
1993
{
1994
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1995
    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
1996
    TTTOOL_INFO *toolPtr;
1997
    INT nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
1998

Alexandre Julliard's avatar
Alexandre Julliard committed
1999 2000
    if (lpToolInfo == NULL)
	return 0;
2001
    if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
2002
	return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
2003

Alexandre Julliard's avatar
Alexandre Julliard committed
2004 2005
    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
    if (nTool == -1) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
2006

2007
    TRACE("tool %d\n", nTool);
Alexandre Julliard's avatar
Alexandre Julliard committed
2008

Alexandre Julliard's avatar
Alexandre Julliard committed
2009
    toolPtr = &infoPtr->tools[nTool];
Alexandre Julliard's avatar
Alexandre Julliard committed
2010 2011 2012 2013 2014 2015 2016 2017

    /* copy tool data */
    toolPtr->uFlags = lpToolInfo->uFlags;
    toolPtr->hwnd   = lpToolInfo->hwnd;
    toolPtr->uId    = lpToolInfo->uId;
    toolPtr->rect   = lpToolInfo->rect;
    toolPtr->hinst  = lpToolInfo->hinst;

Frank Richter's avatar
Frank Richter committed
2018 2019
    if (IS_INTRESOURCE(lpToolInfo->lpszText)) {
	TRACE("set string id %x\n", LOWORD(lpToolInfo->lpszText));
2020
	toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
Alexandre Julliard's avatar
Alexandre Julliard committed
2021 2022
    }
    else if (lpToolInfo->lpszText) {
2023 2024
	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
Alexandre Julliard's avatar
Alexandre Julliard committed
2025
	else {
2026
	    if ( (toolPtr->lpszText) &&
Frank Richter's avatar
Frank Richter committed
2027
		 !IS_INTRESOURCE(toolPtr->lpszText) ) {
2028
		Free (toolPtr->lpszText);
2029 2030 2031
		toolPtr->lpszText = NULL;
	    }
	    if (lpToolInfo->lpszText) {
2032 2033
		INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText,
					      -1, NULL, 0);
2034
		toolPtr->lpszText = Alloc (len * sizeof(WCHAR));
2035 2036
		MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
				    toolPtr->lpszText, len);
2037
	    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2038 2039 2040
	}
    }

2041
    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
Alexandre Julliard's avatar
Alexandre Julliard committed
2042 2043 2044 2045 2046 2047
	toolPtr->lParam = lpToolInfo->lParam;

    return 0;
}


2048
static LRESULT
2049
TOOLTIPS_SetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2050
{
2051
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2052
    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
2053
    TTTOOL_INFO *toolPtr;
2054
    INT nTool;
2055 2056 2057

    if (lpToolInfo == NULL)
	return 0;
2058
    if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE)
2059 2060 2061 2062 2063
	return 0;

    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
    if (nTool == -1) return 0;

2064
    TRACE("tool %d\n", nTool);
2065 2066 2067 2068 2069 2070 2071 2072 2073 2074

    toolPtr = &infoPtr->tools[nTool];

    /* copy tool data */
    toolPtr->uFlags = lpToolInfo->uFlags;
    toolPtr->hwnd   = lpToolInfo->hwnd;
    toolPtr->uId    = lpToolInfo->uId;
    toolPtr->rect   = lpToolInfo->rect;
    toolPtr->hinst  = lpToolInfo->hinst;

Frank Richter's avatar
Frank Richter committed
2075 2076
    if (IS_INTRESOURCE(lpToolInfo->lpszText)) {
	TRACE("set string id %x!\n", LOWORD(lpToolInfo->lpszText));
2077 2078
	toolPtr->lpszText = lpToolInfo->lpszText;
    }
2079
    else {
2080 2081
	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
2082
	else {
2083
	    if ( (toolPtr->lpszText) &&
Frank Richter's avatar
Frank Richter committed
2084
		 !IS_INTRESOURCE(toolPtr->lpszText) ) {
2085
		Free (toolPtr->lpszText);
2086 2087 2088
		toolPtr->lpszText = NULL;
	    }
	    if (lpToolInfo->lpszText) {
2089
		INT len = lstrlenW (lpToolInfo->lpszText);
2090
		toolPtr->lpszText = Alloc ((len+1)*sizeof(WCHAR));
2091
		strcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
2092 2093 2094 2095
	    }
	}
    }

2096
    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
2097 2098
	toolPtr->lParam = lpToolInfo->lParam;

2099 2100 2101 2102 2103 2104 2105 2106 2107 2108
    if (infoPtr->nCurrentTool == nTool)
    {
        TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nCurrentTool);

        if (infoPtr->szTipText[0] == 0)
            TOOLTIPS_Hide(hwnd, infoPtr);
        else
            TOOLTIPS_Show (hwnd, infoPtr);
    }

2109 2110
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2111 2112 2113


static LRESULT
2114
TOOLTIPS_TrackActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2115
{
2116
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2117

2118
    if ((BOOL)wParam) {
2119 2120 2121 2122 2123 2124 2125
	LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;

	if (lpToolInfo == NULL)
	    return 0;
	if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE)
	    return FALSE;

Alexandre Julliard's avatar
Alexandre Julliard committed
2126 2127 2128
	/* activate */
	infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
	if (infoPtr->nTrackTool != -1) {
2129
	    TRACE("activated!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
2130
	    infoPtr->bTrackActive = TRUE;
2131
	    TOOLTIPS_TrackShow (hwnd, infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
2132 2133 2134 2135
	}
    }
    else {
	/* deactivate */
2136
	TOOLTIPS_TrackHide (hwnd, infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
2137 2138 2139

	infoPtr->bTrackActive = FALSE;
	infoPtr->nTrackTool = -1;
2140

2141
	TRACE("deactivated!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
2142 2143 2144 2145 2146 2147 2148
    }

    return 0;
}


static LRESULT
2149
TOOLTIPS_TrackPosition (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2150
{
2151
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2152

2153 2154
    infoPtr->xTrackPos = (INT)LOWORD(lParam);
    infoPtr->yTrackPos = (INT)HIWORD(lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2155 2156

    if (infoPtr->bTrackActive) {
2157
	TRACE("[%d %d]\n",
2158
	       infoPtr->xTrackPos, infoPtr->yTrackPos);
Alexandre Julliard's avatar
Alexandre Julliard committed
2159

2160
	TOOLTIPS_TrackShow (hwnd, infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
2161 2162 2163 2164 2165 2166 2167
    }

    return 0;
}


static LRESULT
2168
TOOLTIPS_Update (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2169
{
2170
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2171 2172

    if (infoPtr->nCurrentTool != -1)
2173
	UpdateWindow (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2174 2175 2176 2177 2178 2179

    return 0;
}


static LRESULT
2180
TOOLTIPS_UpdateTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2181
{
2182
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2183
    LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
Alexandre Julliard's avatar
Alexandre Julliard committed
2184
    TTTOOL_INFO *toolPtr;
2185
    INT nTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
2186

Alexandre Julliard's avatar
Alexandre Julliard committed
2187 2188
    if (lpToolInfo == NULL)
	return 0;
2189
    if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE)
Alexandre Julliard's avatar
Alexandre Julliard committed
2190
	return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2191 2192 2193 2194

    nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
    if (nTool == -1) return 0;

2195
    TRACE("tool %d\n", nTool);
Alexandre Julliard's avatar
Alexandre Julliard committed
2196 2197 2198 2199 2200 2201

    toolPtr = &infoPtr->tools[nTool];

    /* copy tool text */
    toolPtr->hinst  = lpToolInfo->hinst;

Frank Richter's avatar
Frank Richter committed
2202
    if (IS_INTRESOURCE(lpToolInfo->lpszText)){
2203
	toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
Alexandre Julliard's avatar
Alexandre Julliard committed
2204 2205
    }
    else if (lpToolInfo->lpszText) {
2206 2207
	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
Alexandre Julliard's avatar
Alexandre Julliard committed
2208
	else {
2209
	    if ( (toolPtr->lpszText) &&
Frank Richter's avatar
Frank Richter committed
2210
		 !IS_INTRESOURCE(toolPtr->lpszText) ) {
2211
		Free (toolPtr->lpszText);
2212 2213 2214
		toolPtr->lpszText = NULL;
	    }
	    if (lpToolInfo->lpszText) {
2215 2216
		INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText,
					      -1, NULL, 0);
2217
		toolPtr->lpszText = Alloc (len * sizeof(WCHAR));
2218 2219
		MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
				    toolPtr->lpszText, len);
2220
	    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2221 2222 2223
	}
    }

2224
    if(infoPtr->nCurrentTool == -1) return 0;
2225 2226
    /* force repaint */
    if (infoPtr->bActive)
2227
	TOOLTIPS_Show (hwnd, infoPtr);
2228
    else if (infoPtr->bTrackActive)
2229
	TOOLTIPS_TrackShow (hwnd, infoPtr);
2230

Alexandre Julliard's avatar
Alexandre Julliard committed
2231 2232 2233 2234
    return 0;
}


2235
static LRESULT
2236
TOOLTIPS_UpdateTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
2237
{
2238
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2239
    LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
2240
    TTTOOL_INFO *toolPtr;
2241
    INT nTool;
2242 2243 2244

    if (lpToolInfo == NULL)
	return 0;
2245
    if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE)
2246 2247 2248 2249 2250 2251
	return FALSE;

    nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
    if (nTool == -1)
	return 0;

2252
    TRACE("tool %d\n", nTool);
2253 2254 2255 2256 2257 2258

    toolPtr = &infoPtr->tools[nTool];

    /* copy tool text */
    toolPtr->hinst  = lpToolInfo->hinst;

Frank Richter's avatar
Frank Richter committed
2259
    if (IS_INTRESOURCE(lpToolInfo->lpszText)){
2260 2261 2262
	toolPtr->lpszText = lpToolInfo->lpszText;
    }
    else if (lpToolInfo->lpszText) {
2263 2264
	if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
	    toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
2265
	else {
2266
	    if ( (toolPtr->lpszText)  &&
Frank Richter's avatar
Frank Richter committed
2267
		 !IS_INTRESOURCE(toolPtr->lpszText) ) {
2268
		Free (toolPtr->lpszText);
2269 2270 2271
		toolPtr->lpszText = NULL;
	    }
	    if (lpToolInfo->lpszText) {
2272
		INT len = lstrlenW (lpToolInfo->lpszText);
2273
		toolPtr->lpszText = Alloc ((len+1)*sizeof(WCHAR));
2274
		strcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
2275 2276 2277 2278
	    }
	}
    }

2279
    if(infoPtr->nCurrentTool == -1) return 0;
2280 2281
    /* force repaint */
    if (infoPtr->bActive)
2282
	TOOLTIPS_Show (hwnd, infoPtr);
2283
    else if (infoPtr->bTrackActive)
2284
	TOOLTIPS_TrackShow (hwnd, infoPtr);
2285

2286 2287
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2288 2289 2290


static LRESULT
2291
TOOLTIPS_WindowFromPoint (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2292
{
2293
    return (LRESULT)WindowFromPoint (*((LPPOINT)lParam));
Alexandre Julliard's avatar
Alexandre Julliard committed
2294 2295
}

Alexandre Julliard's avatar
Alexandre Julliard committed
2296 2297 2298


static LRESULT
2299
TOOLTIPS_Create (HWND hwnd, const CREATESTRUCTW *lpcs)
Alexandre Julliard's avatar
Alexandre Julliard committed
2300 2301 2302 2303
{
    TOOLTIPS_INFO *infoPtr;

    /* allocate memory for info structure */
2304
    infoPtr = (TOOLTIPS_INFO *)Alloc (sizeof(TOOLTIPS_INFO));
2305
    SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
2306 2307 2308

    /* initialize info structure */
    infoPtr->bActive = TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2309
    infoPtr->bTrackActive = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2310 2311 2312 2313

    infoPtr->nMaxTipWidth = -1;
    infoPtr->nTool = -1;
    infoPtr->nCurrentTool = -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
2314
    infoPtr->nTrackTool = -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
2315

Robert Shearman's avatar
Robert Shearman committed
2316 2317 2318
    /* initialize colours and fonts */
    TOOLTIPS_InitSystemSettings(infoPtr);

2319
    TOOLTIPS_SetDelayTime(hwnd, TTDT_AUTOMATIC, 0L);
Alexandre Julliard's avatar
Alexandre Julliard committed
2320

2321
    SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
Alexandre Julliard's avatar
Alexandre Julliard committed
2322

Alexandre Julliard's avatar
Alexandre Julliard committed
2323 2324 2325 2326 2327
    return 0;
}


static LRESULT
2328
TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2329
{
2330
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2331
    TTTOOL_INFO *toolPtr;
2332
    UINT i;
Alexandre Julliard's avatar
Alexandre Julliard committed
2333 2334 2335 2336

    /* free tools */
    if (infoPtr->tools) {
	for (i = 0; i < infoPtr->uNumTools; i++) {
Alexandre Julliard's avatar
Alexandre Julliard committed
2337
	    toolPtr = &infoPtr->tools[i];
2338
	    if (toolPtr->lpszText) {
2339
		if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) &&
Frank Richter's avatar
Frank Richter committed
2340
		     !IS_INTRESOURCE(toolPtr->lpszText) )
2341
		{
2342
		    Free (toolPtr->lpszText);
2343 2344
		    toolPtr->lpszText = NULL;
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
2345 2346 2347
	    }

	    /* remove subclassing */
2348 2349
        if (toolPtr->uFlags & TTF_SUBCLASS) {
            if (toolPtr->uFlags & TTF_IDISHWND) {
2350
                RemoveWindowSubclass((HWND)toolPtr->uId, TOOLTIPS_SubclassProc, 1);
2351 2352
            }
            else {
2353
                RemoveWindowSubclass(toolPtr->hwnd, TOOLTIPS_SubclassProc, 1);
2354 2355 2356
            }
        }
    }
2357
	Free (infoPtr->tools);
Alexandre Julliard's avatar
Alexandre Julliard committed
2358 2359
    }

Robert Shearman's avatar
Robert Shearman committed
2360 2361 2362 2363 2364 2365 2366
    /* free title string */
    Free (infoPtr->pszTitle);
    /* free title icon if not a standard one */
    if (TOOLTIPS_GetTitleIconIndex(infoPtr->hTitleIcon) > TTI_ERROR)
        DeleteObject(infoPtr->hTitleIcon);

    /* delete fonts */
2367
    DeleteObject (infoPtr->hFont);
Robert Shearman's avatar
Robert Shearman committed
2368
    DeleteObject (infoPtr->hTitleFont);
Alexandre Julliard's avatar
Alexandre Julliard committed
2369

Alexandre Julliard's avatar
Alexandre Julliard committed
2370
    /* free tool tips info data */
2371
    Free (infoPtr);
2372
    SetWindowLongPtrW(hwnd, 0, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
2373 2374 2375 2376 2377
    return 0;
}


static LRESULT
2378
TOOLTIPS_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2379
{
2380
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2381

2382
    return (LRESULT)infoPtr->hFont;
Alexandre Julliard's avatar
Alexandre Julliard committed
2383 2384 2385
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2386
static LRESULT
2387
TOOLTIPS_MouseMessage (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2388
{
2389
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2390

2391
    TOOLTIPS_Hide (hwnd, infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
2392 2393 2394 2395 2396 2397

    return 0;
}


static LRESULT
2398
TOOLTIPS_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2399
{
2400 2401
    DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
    DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE);
2402

2403
    dwStyle &= ~(WS_CHILD | /*WS_MAXIMIZE |*/ WS_BORDER | WS_DLGFRAME);
2404
    dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
2405 2406 2407 2408 2409

    /* WS_BORDER only draws a border round the window rect, not the
     * window region, therefore it is useless to us in balloon mode */
    if (dwStyle & TTS_BALLOON) dwStyle &= ~WS_BORDER;

2410
    SetWindowLongW (hwnd, GWL_STYLE, dwStyle);
Alexandre Julliard's avatar
Alexandre Julliard committed
2411

2412
    dwExStyle |= WS_EX_TOOLWINDOW;
2413
    SetWindowLongW (hwnd, GWL_EXSTYLE, dwExStyle);
2414

Alexandre Julliard's avatar
Alexandre Julliard committed
2415 2416 2417 2418
    return TRUE;
}


2419
static LRESULT
2420
TOOLTIPS_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2421
{
2422
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2423
    INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool;
2424

2425
    TRACE(" nTool=%d\n", nTool);
2426 2427 2428

    if ((nTool > -1) && (nTool < infoPtr->uNumTools)) {
	if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) {
2429
	    TRACE("-- in transparent mode!\n");
2430 2431 2432 2433
	    return HTTRANSPARENT;
	}
    }

2434
    return DefWindowProcW (hwnd, WM_NCHITTEST, wParam, lParam);
2435 2436 2437
}


2438 2439 2440
static LRESULT
TOOLTIPS_NotifyFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
2441
    FIXME ("hwnd=%p wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
2442 2443 2444 2445 2446

    return 0;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2447
static LRESULT
2448
TOOLTIPS_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2449
{
2450 2451
    HDC hdc;
    PAINTSTRUCT ps;
Alexandre Julliard's avatar
Alexandre Julliard committed
2452

2453 2454
    hdc = (wParam == 0) ? BeginPaint (hwnd, &ps) : (HDC)wParam;
    TOOLTIPS_Refresh (hwnd, hdc);
Alexandre Julliard's avatar
Alexandre Julliard committed
2455
    if (!wParam)
2456
	EndPaint (hwnd, &ps);
Alexandre Julliard's avatar
Alexandre Julliard committed
2457 2458
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2459 2460 2461


static LRESULT
2462
TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2463
{
2464
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2465
    LOGFONTW lf;
Alexandre Julliard's avatar
Alexandre Julliard committed
2466

2467
    if(!GetObjectW((HFONT)wParam, sizeof(lf), &lf))
2468
        return 0;
2469

Robert Shearman's avatar
Robert Shearman committed
2470
    DeleteObject (infoPtr->hFont);
2471
    infoPtr->hFont = CreateFontIndirectW(&lf);
Alexandre Julliard's avatar
Alexandre Julliard committed
2472

Robert Shearman's avatar
Robert Shearman committed
2473 2474 2475 2476
    DeleteObject (infoPtr->hTitleFont);
    lf.lfWeight = FW_BOLD;
    infoPtr->hTitleFont = CreateFontIndirectW(&lf);

Alexandre Julliard's avatar
Alexandre Julliard committed
2477
    if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
2478
	FIXME("full redraw needed!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
2479 2480 2481 2482
    }

    return 0;
}
2483

2484
/******************************************************************
2485
 * TOOLTIPS_GetTextLength
2486 2487 2488 2489 2490 2491 2492
 *
 * This function is called when the tooltip receive a
 * WM_GETTEXTLENGTH message.
 * wParam : not used
 * lParam : not used
 *
 * returns the length, in characters, of the tip text
2493
 */
2494
static LRESULT
2495
TOOLTIPS_GetTextLength(HWND hwnd, WPARAM wParam, LPARAM lParam)
2496 2497
{
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2498
    return strlenW(infoPtr->szTipText);
2499
}
2500

2501 2502 2503 2504 2505 2506 2507 2508 2509 2510
/******************************************************************
 * TOOLTIPS_OnWMGetText
 *
 * This function is called when the tooltip receive a
 * WM_GETTEXT message.
 * wParam : specifies the maximum number of characters to be copied
 * lParam : is the pointer to the buffer that will receive
 *          the tip text
 *
 * returns the number of characters copied
2511
 */
2512 2513 2514 2515
static LRESULT
TOOLTIPS_OnWMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2516 2517
    LRESULT res;
    LPWSTR pszText = (LPWSTR)lParam;
2518

2519
    if(!infoPtr->szTipText || !wParam)
2520 2521
        return 0;

2522 2523 2524 2525
    res = min(strlenW(infoPtr->szTipText)+1, wParam);
    memcpy(pszText, infoPtr->szTipText, res*sizeof(WCHAR));
    pszText[res-1] = '\0';
    return res-1;
2526
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2527

Alexandre Julliard's avatar
Alexandre Julliard committed
2528
static LRESULT
2529
TOOLTIPS_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2530
{
2531
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2532
    INT nOldTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
2533

2534
    TRACE("timer %d (%p) expired!\n", wParam, hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2535

2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550
    switch (wParam) {
    case ID_TIMERSHOW:
        KillTimer (hwnd, ID_TIMERSHOW);
	nOldTool = infoPtr->nTool;
	if ((infoPtr->nTool = TOOLTIPS_CheckTool (hwnd, TRUE)) == nOldTool)
	    TOOLTIPS_Show (hwnd, infoPtr);
	break;

    case ID_TIMERPOP:
        TOOLTIPS_Hide (hwnd, infoPtr);
	break;

    case ID_TIMERLEAVE:
        nOldTool = infoPtr->nTool;
	infoPtr->nTool = TOOLTIPS_CheckTool (hwnd, FALSE);
2551
	TRACE("tool (%p) %d %d %d\n", hwnd, nOldTool,
2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565
	      infoPtr->nTool, infoPtr->nCurrentTool);
	if (infoPtr->nTool != nOldTool) {
	    if(infoPtr->nTool == -1) { /* Moved out of all tools */
	        TOOLTIPS_Hide(hwnd, infoPtr);
		KillTimer(hwnd, ID_TIMERLEAVE);
	    } else if (nOldTool == -1) { /* Moved from outside */
	        ERR("How did this happen?\n");
	    } else { /* Moved from one to another */
	        TOOLTIPS_Hide (hwnd, infoPtr);
		KillTimer(hwnd, ID_TIMERLEAVE);
		if(infoPtr->bActive) {
		    SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
		    TRACE("timer 1 started!\n");
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
2566
	    }
2567 2568 2569 2570 2571 2572
	}
	break;

    default:
        ERR("Unknown timer id %d\n", wParam);
	break;
Alexandre Julliard's avatar
Alexandre Julliard committed
2573 2574 2575 2576 2577
    }
    return 0;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2578
static LRESULT
2579
TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2580
{
2581
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2582

Robert Shearman's avatar
Robert Shearman committed
2583
    TOOLTIPS_InitSystemSettings (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
2584 2585 2586

    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2587 2588


Robert Shearman's avatar
Robert Shearman committed
2589
static LRESULT CALLBACK
2590
TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uID, DWORD_PTR dwRef)
Alexandre Julliard's avatar
Alexandre Julliard committed
2591
{
2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605
    MSG msg;

    switch(uMsg) {
    case WM_MOUSEMOVE:
    case WM_LBUTTONDOWN:
    case WM_LBUTTONUP:
    case WM_MBUTTONDOWN:
    case WM_MBUTTONUP:
    case WM_RBUTTONDOWN:
    case WM_RBUTTONUP:
        msg.hwnd = hwnd;
	msg.message = uMsg;
	msg.wParam = wParam;
	msg.lParam = lParam;
2606
	TOOLTIPS_RelayEvent((HWND)dwRef, 0, (LPARAM)&msg);
2607 2608 2609 2610
	break;

    default:
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
2611
    }
2612
    return DefSubclassProc(hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2613 2614 2615
}


2616
static LRESULT CALLBACK
2617
TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2618
{
2619
    TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd, uMsg, wParam, lParam);
Chris Morgan's avatar
Chris Morgan committed
2620
    if (!TOOLTIPS_GetInfoPtr(hwnd) && (uMsg != WM_CREATE) && (uMsg != WM_NCCREATE))
2621
        return DefWindowProcW (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2622 2623 2624
    switch (uMsg)
    {
	case TTM_ACTIVATE:
2625
	    return TOOLTIPS_Activate (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2626

2627
	case TTM_ADDTOOLA:
2628
	    return TOOLTIPS_AddToolA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2629

2630
	case TTM_ADDTOOLW:
2631
	    return TOOLTIPS_AddToolW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2632

2633
	case TTM_DELTOOLA:
2634
	    return TOOLTIPS_DelToolA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2635

2636
	case TTM_DELTOOLW:
2637
	    return TOOLTIPS_DelToolW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2638

2639
	case TTM_ENUMTOOLSA:
2640
	    return TOOLTIPS_EnumToolsA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2641

2642
	case TTM_ENUMTOOLSW:
2643
	    return TOOLTIPS_EnumToolsW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2644

2645 2646 2647
	case TTM_GETBUBBLESIZE:
	    return TOOLTIPS_GetBubbleSize (hwnd, wParam, lParam);

2648
	case TTM_GETCURRENTTOOLA:
2649
	    return TOOLTIPS_GetCurrentToolA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2650

2651
	case TTM_GETCURRENTTOOLW:
2652
	    return TOOLTIPS_GetCurrentToolW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2653 2654

	case TTM_GETDELAYTIME:
2655
	    return TOOLTIPS_GetDelayTime (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2656 2657

	case TTM_GETMARGIN:
2658
	    return TOOLTIPS_GetMargin (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2659 2660

	case TTM_GETMAXTIPWIDTH:
2661
	    return TOOLTIPS_GetMaxTipWidth (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2662

2663
	case TTM_GETTEXTA:
2664
	    return TOOLTIPS_GetTextA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2665

2666
	case TTM_GETTEXTW:
2667
	    return TOOLTIPS_GetTextW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2668 2669

	case TTM_GETTIPBKCOLOR:
2670
	    return TOOLTIPS_GetTipBkColor (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2671 2672

	case TTM_GETTIPTEXTCOLOR:
2673
	    return TOOLTIPS_GetTipTextColor (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2674 2675

	case TTM_GETTOOLCOUNT:
2676
	    return TOOLTIPS_GetToolCount (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2677

2678
	case TTM_GETTOOLINFOA:
2679
	    return TOOLTIPS_GetToolInfoA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2680

2681
	case TTM_GETTOOLINFOW:
2682
	    return TOOLTIPS_GetToolInfoW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2683

2684
	case TTM_HITTESTA:
2685
	    return TOOLTIPS_HitTestA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2686

2687
	case TTM_HITTESTW:
2688
	    return TOOLTIPS_HitTestW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2689

2690
	case TTM_NEWTOOLRECTA:
2691
	    return TOOLTIPS_NewToolRectA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2692

2693
	case TTM_NEWTOOLRECTW:
2694
	    return TOOLTIPS_NewToolRectW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2695 2696

	case TTM_POP:
2697
	    return TOOLTIPS_Pop (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2698 2699

	case TTM_RELAYEVENT:
2700
	    return TOOLTIPS_RelayEvent (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2701

Alexandre Julliard's avatar
Alexandre Julliard committed
2702
	case TTM_SETDELAYTIME:
2703
	    return TOOLTIPS_SetDelayTime (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2704 2705

	case TTM_SETMARGIN:
2706
	    return TOOLTIPS_SetMargin (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2707 2708

	case TTM_SETMAXTIPWIDTH:
2709
	    return TOOLTIPS_SetMaxTipWidth (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2710 2711

	case TTM_SETTIPBKCOLOR:
2712
	    return TOOLTIPS_SetTipBkColor (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2713 2714

	case TTM_SETTIPTEXTCOLOR:
2715
	    return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2716

Robert Shearman's avatar
Robert Shearman committed
2717 2718 2719 2720 2721 2722
	case TTM_SETTITLEA:
	    return TOOLTIPS_SetTitleA (hwnd, wParam, lParam);

	case TTM_SETTITLEW:
	    return TOOLTIPS_SetTitleW (hwnd, wParam, lParam);

2723
	case TTM_SETTOOLINFOA:
2724
	    return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2725

2726
	case TTM_SETTOOLINFOW:
2727
	    return TOOLTIPS_SetToolInfoW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2728 2729

	case TTM_TRACKACTIVATE:
2730
	    return TOOLTIPS_TrackActivate (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2731 2732

	case TTM_TRACKPOSITION:
2733
	    return TOOLTIPS_TrackPosition (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2734 2735

	case TTM_UPDATE:
2736
	    return TOOLTIPS_Update (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2737

2738
	case TTM_UPDATETIPTEXTA:
2739
	    return TOOLTIPS_UpdateTipTextA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2740

2741
	case TTM_UPDATETIPTEXTW:
2742
	    return TOOLTIPS_UpdateTipTextW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2743 2744

	case TTM_WINDOWFROMPOINT:
2745
	    return TOOLTIPS_WindowFromPoint (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2746 2747 2748


	case WM_CREATE:
2749
	    return TOOLTIPS_Create (hwnd, (LPCREATESTRUCTW)lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2750 2751

	case WM_DESTROY:
2752
	    return TOOLTIPS_Destroy (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2753

Alexandre Julliard's avatar
Alexandre Julliard committed
2754
	case WM_ERASEBKGND:
2755 2756
	    /* we draw the background in WM_PAINT */
	    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
2757

Alexandre Julliard's avatar
Alexandre Julliard committed
2758
	case WM_GETFONT:
2759
	    return TOOLTIPS_GetFont (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2760

Robert Shearman's avatar
Robert Shearman committed
2761 2762
	case WM_GETTEXT:
	    return TOOLTIPS_OnWMGetText (hwnd, wParam, lParam);
2763

Robert Shearman's avatar
Robert Shearman committed
2764
	case WM_GETTEXTLENGTH:
2765
	    return TOOLTIPS_GetTextLength (hwnd, wParam, lParam);
2766

2767 2768 2769 2770 2771 2772
	case WM_LBUTTONDOWN:
	case WM_LBUTTONUP:
	case WM_MBUTTONDOWN:
	case WM_MBUTTONUP:
	case WM_RBUTTONDOWN:
	case WM_RBUTTONUP:
Alexandre Julliard's avatar
Alexandre Julliard committed
2773
	case WM_MOUSEMOVE:
2774
	    return TOOLTIPS_MouseMessage (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2775 2776

	case WM_NCCREATE:
2777
	    return TOOLTIPS_NCCreate (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2778

2779
	case WM_NCHITTEST:
2780
	    return TOOLTIPS_NCHitTest (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2781

2782 2783
	case WM_NOTIFYFORMAT:
	    return TOOLTIPS_NotifyFormat (hwnd, wParam, lParam);
2784

2785
	case WM_PRINTCLIENT:
Alexandre Julliard's avatar
Alexandre Julliard committed
2786
	case WM_PAINT:
2787
	    return TOOLTIPS_Paint (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2788 2789

	case WM_SETFONT:
2790
	    return TOOLTIPS_SetFont (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2791

Alexandre Julliard's avatar
Alexandre Julliard committed
2792
	case WM_TIMER:
2793
	    return TOOLTIPS_Timer (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2794

Alexandre Julliard's avatar
Alexandre Julliard committed
2795
	case WM_WININICHANGE:
2796
	    return TOOLTIPS_WinIniChange (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2797 2798

	default:
2799
	    if ((uMsg >= WM_USER) && (uMsg < WM_APP))
2800
		ERR("unknown msg %04x wp=%08x lp=%08lx\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
2801
		     uMsg, wParam, lParam);
2802
	    return DefWindowProcW (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2803 2804 2805 2806
    }
}


2807
VOID
2808
TOOLTIPS_Register (void)
Alexandre Julliard's avatar
Alexandre Julliard committed
2809
{
2810
    WNDCLASSW wndClass;
Alexandre Julliard's avatar
Alexandre Julliard committed
2811

2812
    ZeroMemory (&wndClass, sizeof(WNDCLASSW));
Alexandre Julliard's avatar
Alexandre Julliard committed
2813
    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
2814
    wndClass.lpfnWndProc   = TOOLTIPS_WindowProc;
Alexandre Julliard's avatar
Alexandre Julliard committed
2815 2816
    wndClass.cbClsExtra    = 0;
    wndClass.cbWndExtra    = sizeof(TOOLTIPS_INFO *);
2817
    wndClass.hCursor       = LoadCursorW (0, (LPWSTR)IDC_ARROW);
Alexandre Julliard's avatar
Alexandre Julliard committed
2818
    wndClass.hbrBackground = 0;
2819
    wndClass.lpszClassName = TOOLTIPS_CLASSW;
2820

2821
    RegisterClassW (&wndClass);
Robert Shearman's avatar
Robert Shearman committed
2822 2823 2824 2825 2826 2827 2828 2829

    hTooltipIcons[TTI_NONE] = NULL;
    hTooltipIcons[TTI_INFO] = LoadImageW(COMCTL32_hModule,
        (LPCWSTR)MAKEINTRESOURCE(IDI_TT_INFO_SM), IMAGE_ICON, 0, 0, 0);
    hTooltipIcons[TTI_WARNING] = LoadImageW(COMCTL32_hModule,
        (LPCWSTR)MAKEINTRESOURCE(IDI_TT_WARN_SM), IMAGE_ICON, 0, 0, 0);
    hTooltipIcons[TTI_ERROR] = LoadImageW(COMCTL32_hModule,
        (LPCWSTR)MAKEINTRESOURCE(IDI_TT_ERROR_SM), IMAGE_ICON, 0, 0, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
2830
}
2831 2832 2833


VOID
2834
TOOLTIPS_Unregister (void)
2835
{
Robert Shearman's avatar
Robert Shearman committed
2836
    int i;
2837 2838
    for (i = TTI_INFO; i <= TTI_ERROR; i++)
        DestroyIcon(hTooltipIcons[i]);
2839
    UnregisterClassW (TOOLTIPS_CLASSW, NULL);
2840
}