tooltips.c 74.8 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 2029
		if( toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
                    Free (toolPtr->lpszText);
2030 2031 2032
		toolPtr->lpszText = NULL;
	    }
	    if (lpToolInfo->lpszText) {
2033 2034
		INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText,
					      -1, NULL, 0);
2035
		toolPtr->lpszText = Alloc (len * sizeof(WCHAR));
2036 2037
		MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
				    toolPtr->lpszText, len);
2038
	    }
Alexandre Julliard's avatar
Alexandre Julliard committed
2039 2040 2041
	}
    }

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

    return 0;
}


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

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

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

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

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

2098
    if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
2099 2100
	toolPtr->lParam = lpToolInfo->lParam;

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

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

2111 2112
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2113 2114 2115


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

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

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

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

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

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

    return 0;
}


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

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

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

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

    return 0;
}


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

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

    return 0;
}


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

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

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

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

    toolPtr = &infoPtr->tools[nTool];

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

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

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

Alexandre Julliard's avatar
Alexandre Julliard committed
2234 2235 2236 2237
    return 0;
}


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

    if (lpToolInfo == NULL)
	return 0;
2248
    if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE)
2249 2250 2251 2252 2253 2254
	return FALSE;

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

2255
    TRACE("tool %d\n", nTool);
2256 2257 2258 2259 2260 2261

    toolPtr = &infoPtr->tools[nTool];

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

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

2283
    if(infoPtr->nCurrentTool == -1) return 0;
2284 2285
    /* force repaint */
    if (infoPtr->bActive)
2286
	TOOLTIPS_Show (hwnd, infoPtr);
2287
    else if (infoPtr->bTrackActive)
2288
	TOOLTIPS_TrackShow (hwnd, infoPtr);
2289

2290 2291
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2292 2293 2294


static LRESULT
2295
TOOLTIPS_WindowFromPoint (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2296
{
2297
    return (LRESULT)WindowFromPoint (*((LPPOINT)lParam));
Alexandre Julliard's avatar
Alexandre Julliard committed
2298 2299
}

Alexandre Julliard's avatar
Alexandre Julliard committed
2300 2301 2302


static LRESULT
2303
TOOLTIPS_Create (HWND hwnd, const CREATESTRUCTW *lpcs)
Alexandre Julliard's avatar
Alexandre Julliard committed
2304 2305 2306 2307
{
    TOOLTIPS_INFO *infoPtr;

    /* allocate memory for info structure */
2308
    infoPtr = (TOOLTIPS_INFO *)Alloc (sizeof(TOOLTIPS_INFO));
2309
    SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
2310 2311 2312

    /* initialize info structure */
    infoPtr->bActive = TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2313
    infoPtr->bTrackActive = FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
2314 2315 2316 2317

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

Robert Shearman's avatar
Robert Shearman committed
2320 2321 2322
    /* initialize colours and fonts */
    TOOLTIPS_InitSystemSettings(infoPtr);

2323
    TOOLTIPS_SetDelayTime(hwnd, TTDT_AUTOMATIC, 0L);
Alexandre Julliard's avatar
Alexandre Julliard committed
2324

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

Alexandre Julliard's avatar
Alexandre Julliard committed
2327 2328 2329 2330 2331
    return 0;
}


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

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

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

Robert Shearman's avatar
Robert Shearman committed
2364 2365 2366 2367 2368 2369 2370
    /* 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 */
2371
    DeleteObject (infoPtr->hFont);
Robert Shearman's avatar
Robert Shearman committed
2372
    DeleteObject (infoPtr->hTitleFont);
Alexandre Julliard's avatar
Alexandre Julliard committed
2373

Alexandre Julliard's avatar
Alexandre Julliard committed
2374
    /* free tool tips info data */
2375
    Free (infoPtr);
2376
    SetWindowLongPtrW(hwnd, 0, 0);
Alexandre Julliard's avatar
Alexandre Julliard committed
2377 2378 2379 2380 2381
    return 0;
}


static LRESULT
2382
TOOLTIPS_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2383
{
2384
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2385

2386
    return (LRESULT)infoPtr->hFont;
Alexandre Julliard's avatar
Alexandre Julliard committed
2387 2388 2389
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2390
static LRESULT
2391
TOOLTIPS_MouseMessage (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2392
{
2393
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2394

2395
    TOOLTIPS_Hide (hwnd, infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
2396 2397 2398 2399 2400 2401

    return 0;
}


static LRESULT
2402
TOOLTIPS_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2403
{
2404 2405
    DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
    DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE);
2406

2407
    dwStyle &= ~(WS_CHILD | /*WS_MAXIMIZE |*/ WS_BORDER | WS_DLGFRAME);
2408
    dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
2409 2410 2411 2412 2413

    /* 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;

2414
    SetWindowLongW (hwnd, GWL_STYLE, dwStyle);
Alexandre Julliard's avatar
Alexandre Julliard committed
2415

2416
    dwExStyle |= WS_EX_TOOLWINDOW;
2417
    SetWindowLongW (hwnd, GWL_EXSTYLE, dwExStyle);
2418

Alexandre Julliard's avatar
Alexandre Julliard committed
2419 2420 2421 2422
    return TRUE;
}


2423
static LRESULT
2424
TOOLTIPS_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2425
{
2426
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2427
    INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool;
2428

2429
    TRACE(" nTool=%d\n", nTool);
2430 2431 2432

    if ((nTool > -1) && (nTool < infoPtr->uNumTools)) {
	if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) {
2433
	    TRACE("-- in transparent mode!\n");
2434 2435 2436 2437
	    return HTTRANSPARENT;
	}
    }

2438
    return DefWindowProcW (hwnd, WM_NCHITTEST, wParam, lParam);
2439 2440 2441
}


2442 2443 2444
static LRESULT
TOOLTIPS_NotifyFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
2445
    FIXME ("hwnd=%p wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
2446 2447 2448 2449 2450

    return 0;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2451
static LRESULT
2452
TOOLTIPS_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2453
{
2454 2455
    HDC hdc;
    PAINTSTRUCT ps;
Alexandre Julliard's avatar
Alexandre Julliard committed
2456

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


static LRESULT
2466
TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2467
{
2468
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2469
    LOGFONTW lf;
Alexandre Julliard's avatar
Alexandre Julliard committed
2470

2471
    if(!GetObjectW((HFONT)wParam, sizeof(lf), &lf))
2472
        return 0;
2473

Robert Shearman's avatar
Robert Shearman committed
2474
    DeleteObject (infoPtr->hFont);
2475
    infoPtr->hFont = CreateFontIndirectW(&lf);
Alexandre Julliard's avatar
Alexandre Julliard committed
2476

Robert Shearman's avatar
Robert Shearman committed
2477 2478 2479 2480
    DeleteObject (infoPtr->hTitleFont);
    lf.lfWeight = FW_BOLD;
    infoPtr->hTitleFont = CreateFontIndirectW(&lf);

Alexandre Julliard's avatar
Alexandre Julliard committed
2481
    if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
2482
	FIXME("full redraw needed!\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
2483 2484 2485 2486
    }

    return 0;
}
2487

2488
/******************************************************************
2489
 * TOOLTIPS_GetTextLength
2490 2491 2492 2493 2494 2495 2496
 *
 * 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
2497
 */
2498
static LRESULT
2499
TOOLTIPS_GetTextLength(HWND hwnd, WPARAM wParam, LPARAM lParam)
2500 2501
{
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2502
    return strlenW(infoPtr->szTipText);
2503
}
2504

2505 2506 2507 2508 2509 2510 2511 2512 2513 2514
/******************************************************************
 * 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
2515
 */
2516 2517 2518 2519
static LRESULT
TOOLTIPS_OnWMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2520 2521
    LRESULT res;
    LPWSTR pszText = (LPWSTR)lParam;
2522

2523
    if(!infoPtr->szTipText || !wParam)
2524 2525
        return 0;

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

Alexandre Julliard's avatar
Alexandre Julliard committed
2532
static LRESULT
2533
TOOLTIPS_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2534
{
2535
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2536
    INT nOldTool;
Alexandre Julliard's avatar
Alexandre Julliard committed
2537

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

2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554
    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);
2555
	TRACE("tool (%p) %d %d %d\n", hwnd, nOldTool,
2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569
	      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
2570
	    }
2571 2572 2573 2574 2575 2576
	}
	break;

    default:
        ERR("Unknown timer id %d\n", wParam);
	break;
Alexandre Julliard's avatar
Alexandre Julliard committed
2577 2578 2579 2580 2581
    }
    return 0;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
2582
static LRESULT
2583
TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
2584
{
2585
    TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
2586

Robert Shearman's avatar
Robert Shearman committed
2587
    TOOLTIPS_InitSystemSettings (infoPtr);
Alexandre Julliard's avatar
Alexandre Julliard committed
2588 2589 2590

    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
2591 2592


Robert Shearman's avatar
Robert Shearman committed
2593
static LRESULT CALLBACK
2594
TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uID, DWORD_PTR dwRef)
Alexandre Julliard's avatar
Alexandre Julliard committed
2595
{
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609
    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;
2610
	TOOLTIPS_RelayEvent((HWND)dwRef, 0, (LPARAM)&msg);
2611 2612 2613 2614
	break;

    default:
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
2615
    }
2616
    return DefSubclassProc(hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2617 2618 2619
}


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

2631
	case TTM_ADDTOOLA:
2632
	    return TOOLTIPS_AddToolA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2633

2634
	case TTM_ADDTOOLW:
2635
	    return TOOLTIPS_AddToolW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2636

2637
	case TTM_DELTOOLA:
2638
	    return TOOLTIPS_DelToolA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2639

2640
	case TTM_DELTOOLW:
2641
	    return TOOLTIPS_DelToolW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2642

2643
	case TTM_ENUMTOOLSA:
2644
	    return TOOLTIPS_EnumToolsA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2645

2646
	case TTM_ENUMTOOLSW:
2647
	    return TOOLTIPS_EnumToolsW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2648

2649 2650 2651
	case TTM_GETBUBBLESIZE:
	    return TOOLTIPS_GetBubbleSize (hwnd, wParam, lParam);

2652
	case TTM_GETCURRENTTOOLA:
2653
	    return TOOLTIPS_GetCurrentToolA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2654

2655
	case TTM_GETCURRENTTOOLW:
2656
	    return TOOLTIPS_GetCurrentToolW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2657 2658

	case TTM_GETDELAYTIME:
2659
	    return TOOLTIPS_GetDelayTime (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2660 2661

	case TTM_GETMARGIN:
2662
	    return TOOLTIPS_GetMargin (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2663 2664

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

2667
	case TTM_GETTEXTA:
2668
	    return TOOLTIPS_GetTextA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2669

2670
	case TTM_GETTEXTW:
2671
	    return TOOLTIPS_GetTextW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2672 2673

	case TTM_GETTIPBKCOLOR:
2674
	    return TOOLTIPS_GetTipBkColor (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2675 2676

	case TTM_GETTIPTEXTCOLOR:
2677
	    return TOOLTIPS_GetTipTextColor (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2678 2679

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

2682
	case TTM_GETTOOLINFOA:
2683
	    return TOOLTIPS_GetToolInfoA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2684

2685
	case TTM_GETTOOLINFOW:
2686
	    return TOOLTIPS_GetToolInfoW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2687

2688
	case TTM_HITTESTA:
2689
	    return TOOLTIPS_HitTestA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2690

2691
	case TTM_HITTESTW:
2692
	    return TOOLTIPS_HitTestW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2693

2694
	case TTM_NEWTOOLRECTA:
2695
	    return TOOLTIPS_NewToolRectA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2696

2697
	case TTM_NEWTOOLRECTW:
2698
	    return TOOLTIPS_NewToolRectW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2699 2700

	case TTM_POP:
2701
	    return TOOLTIPS_Pop (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2702 2703

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

Alexandre Julliard's avatar
Alexandre Julliard committed
2706
	case TTM_SETDELAYTIME:
2707
	    return TOOLTIPS_SetDelayTime (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2708 2709

	case TTM_SETMARGIN:
2710
	    return TOOLTIPS_SetMargin (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2711 2712

	case TTM_SETMAXTIPWIDTH:
2713
	    return TOOLTIPS_SetMaxTipWidth (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2714 2715

	case TTM_SETTIPBKCOLOR:
2716
	    return TOOLTIPS_SetTipBkColor (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2717 2718

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

Robert Shearman's avatar
Robert Shearman committed
2721 2722 2723 2724 2725 2726
	case TTM_SETTITLEA:
	    return TOOLTIPS_SetTitleA (hwnd, wParam, lParam);

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

2727
	case TTM_SETTOOLINFOA:
2728
	    return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2729

2730
	case TTM_SETTOOLINFOW:
2731
	    return TOOLTIPS_SetToolInfoW (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2732 2733

	case TTM_TRACKACTIVATE:
2734
	    return TOOLTIPS_TrackActivate (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2735 2736

	case TTM_TRACKPOSITION:
2737
	    return TOOLTIPS_TrackPosition (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2738 2739

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

2742
	case TTM_UPDATETIPTEXTA:
2743
	    return TOOLTIPS_UpdateTipTextA (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2744

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

	case TTM_WINDOWFROMPOINT:
2749
	    return TOOLTIPS_WindowFromPoint (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2750 2751 2752


	case WM_CREATE:
2753
	    return TOOLTIPS_Create (hwnd, (LPCREATESTRUCTW)lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2754 2755

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

Alexandre Julliard's avatar
Alexandre Julliard committed
2758
	case WM_ERASEBKGND:
2759 2760
	    /* we draw the background in WM_PAINT */
	    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
2761

Alexandre Julliard's avatar
Alexandre Julliard committed
2762
	case WM_GETFONT:
2763
	    return TOOLTIPS_GetFont (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2764

Robert Shearman's avatar
Robert Shearman committed
2765 2766
	case WM_GETTEXT:
	    return TOOLTIPS_OnWMGetText (hwnd, wParam, lParam);
2767

Robert Shearman's avatar
Robert Shearman committed
2768
	case WM_GETTEXTLENGTH:
2769
	    return TOOLTIPS_GetTextLength (hwnd, wParam, lParam);
2770

2771 2772 2773 2774 2775 2776
	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
2777
	case WM_MOUSEMOVE:
2778
	    return TOOLTIPS_MouseMessage (hwnd, uMsg, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2779 2780

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

2783
	case WM_NCHITTEST:
2784
	    return TOOLTIPS_NCHitTest (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2785

2786 2787
	case WM_NOTIFYFORMAT:
	    return TOOLTIPS_NotifyFormat (hwnd, wParam, lParam);
2788

2789
	case WM_PRINTCLIENT:
Alexandre Julliard's avatar
Alexandre Julliard committed
2790
	case WM_PAINT:
2791
	    return TOOLTIPS_Paint (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2792 2793

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

Alexandre Julliard's avatar
Alexandre Julliard committed
2796
	case WM_TIMER:
2797
	    return TOOLTIPS_Timer (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2798

Alexandre Julliard's avatar
Alexandre Julliard committed
2799
	case WM_WININICHANGE:
2800
	    return TOOLTIPS_WinIniChange (hwnd, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
2801 2802

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


2811
VOID
2812
TOOLTIPS_Register (void)
Alexandre Julliard's avatar
Alexandre Julliard committed
2813
{
2814
    WNDCLASSW wndClass;
Alexandre Julliard's avatar
Alexandre Julliard committed
2815

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

2825
    RegisterClassW (&wndClass);
Robert Shearman's avatar
Robert Shearman committed
2826 2827 2828 2829 2830 2831 2832 2833

    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
2834
}
2835 2836 2837


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