Fixed the displaying of the FOURCC codes in _dump_pixelformat.
[wine] / dlls / comctl32 / tooltips.c
1 /*
2  * Tool tip control
3  *
4  * Copyright 1998, 1999 Eric Kohl
5  *
6  * TODO:
7  *   - Unicode support (started).
8  *   - Custom draw support.
9  *
10  * Testing:
11  *   - Run tests using Waite Group Windows95 API Bible Volume 2.
12  *     The second cdrom (chapter 3) contains executables activate.exe,
13  *     curtool.exe, deltool.exe, enumtools.exe, getinfo.exe, getiptxt.exe,
14  *     hittest.exe, needtext.exe, newrect.exe, updtext.exe and winfrpt.exe.
15  *
16  *   Timer logic.
17  *
18  * One important point to remember is that tools don't necessarily get
19  * a WM_MOUSEMOVE once the cursor leaves the tool, an example is when
20  * a tool sets TTF_IDISHWND (i.e. an entire window is a tool) because
21  * here WM_MOUSEMOVEs only get sent when the cursor is inside the
22  * client area.  Therefore the only reliable way to know that the
23  * cursor has left a tool is to keep a timer running and check the
24  * position every time it expires.  This is the role of timer
25  * ID_TIMERLEAVE.
26  *
27  *
28  * On entering a tool (detected in a relayed WM_MOUSEMOVE) we start
29  * ID_TIMERSHOW, if this times out and we're still in the tool we show
30  * the tip.  On showing a tip we start both ID_TIMERPOP and
31  * ID_TIMERLEAVE.  On hiding a tooltip we kill ID_TIMERPOP.
32  * ID_TIMERPOP is restarted on every relayed WM_MOUSEMOVE.  If
33  * ID_TIMERPOP expires the tool is hidden and ID_TIMERPOP is killed.
34  * ID_TIMERLEAVE remains running - this is important as we need to
35  * determine when the cursor leaves the tool.
36  *
37  * When ID_TIMERLEAVE expires or on a relayed WM_MOUSEMOVE if we're
38  * still in the tool do nothing (apart from restart ID_TIMERPOP if
39  * this is a WM_MOUSEMOVE) (ID_TIMERLEAVE remains running).  If we've
40  * left the tool and entered another one then hide the tip and start
41  * ID_TIMERSHOW with time ReshowTime and kill ID_TIMERLEAVE.  If we're
42  * outside all tools hide the tip and kill ID_TIMERLEAVE.  On Relayed
43  * mouse button messages hide the tip but leave ID_TIMERLEAVE running,
44  * this again will let us keep track of when the cursor leaves the
45  * tool.
46  *
47  *
48  * infoPtr->nTool is the tool the mouse was on on the last relayed MM
49  * or timer expiry or -1 if the mouse was not on a tool.
50  * 
51  * infoPtr->nCurrentTool is the tool for which the tip is currently
52  * displaying text for or -1 if the tip is not shown.  Actually this
53  * will only ever be infoPtr-nTool or -1, so it could be changed to a
54  * BOOL.
55  *
56  */
57
58
59
60 #include <string.h>
61
62 #include "winbase.h"
63 #include "wine/unicode.h"
64 #include "commctrl.h"
65 #include "debugtools.h"
66
67 DEFAULT_DEBUG_CHANNEL(tooltips);
68
69 typedef struct
70 {
71     WNDPROC wpOrigProc;
72     HWND    hwndToolTip;
73     UINT    uRefCount;
74 } TT_SUBCLASS_INFO, *LPTT_SUBCLASS_INFO;
75
76
77 typedef struct
78 {
79     UINT      uFlags;
80     HWND      hwnd;
81     UINT      uId;
82     RECT      rect;
83     HINSTANCE hinst;
84     LPWSTR      lpszText;
85     LPARAM      lParam;
86 } TTTOOL_INFO; 
87
88
89 typedef struct
90 {
91     WCHAR      szTipText[INFOTIPSIZE];
92     BOOL     bActive;
93     BOOL     bTrackActive;
94     UINT     uNumTools;
95     COLORREF   clrBk;
96     COLORREF   clrText;
97     HFONT    hFont;
98     INT      xTrackPos;
99     INT      yTrackPos;
100     INT      nMaxTipWidth;
101     INT      nTool;
102     INT      nCurrentTool;
103     INT      nTrackTool;
104     INT      nReshowTime;
105     INT      nAutoPopTime;
106     INT      nInitialTime;
107     RECT     rcMargin;
108     BOOL     bNotifyUnicode;
109
110     TTTOOL_INFO *tools;
111 } TOOLTIPS_INFO;
112
113 #define ID_TIMERSHOW   1    /* show delay timer */
114 #define ID_TIMERPOP    2    /* auto pop timer */
115 #define ID_TIMERLEAVE  3    /* tool leave timer */
116
117
118 extern LPSTR COMCTL32_aSubclass; /* global subclassing atom */
119
120 /* property name of tooltip window handle */
121 /*#define TT_SUBCLASS_PROP "CC32SubclassInfo" */
122
123 #define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongA (hWindow, 0))
124
125
126 LRESULT CALLBACK
127 TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
128
129
130 static VOID
131 TOOLTIPS_Refresh (HWND hwnd, HDC hdc)
132 {
133     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(hwnd);
134     RECT rc;
135     INT oldBkMode;
136     HFONT hOldFont;
137     HBRUSH hBrush;
138     UINT uFlags = DT_EXTERNALLEADING;
139
140     if (infoPtr->nMaxTipWidth > -1)
141         uFlags |= DT_WORDBREAK;
142     if (GetWindowLongA (hwnd, GWL_STYLE) & TTS_NOPREFIX)
143         uFlags |= DT_NOPREFIX;
144     GetClientRect (hwnd, &rc);
145
146     /* fill the background */
147     hBrush = CreateSolidBrush (infoPtr->clrBk);
148     FillRect (hdc, &rc, hBrush);
149     DeleteObject (hBrush);
150
151     /* calculate text rectangle */
152     rc.left   += (2 + infoPtr->rcMargin.left);
153     rc.top    += (2 + infoPtr->rcMargin.top);
154     rc.right  -= (2 + infoPtr->rcMargin.right);
155     rc.bottom -= (2 + infoPtr->rcMargin.bottom);
156
157     /* draw text */
158     oldBkMode = SetBkMode (hdc, TRANSPARENT);
159     SetTextColor (hdc, infoPtr->clrText);
160     hOldFont = SelectObject (hdc, infoPtr->hFont);
161     DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
162     SelectObject (hdc, hOldFont);
163     if (oldBkMode != TRANSPARENT)
164         SetBkMode (hdc, oldBkMode);
165 }
166
167
168 static VOID
169 TOOLTIPS_GetTipText (HWND hwnd, TOOLTIPS_INFO *infoPtr, INT nTool)
170 {
171     TTTOOL_INFO *toolPtr = &infoPtr->tools[nTool];
172
173     if ((toolPtr->hinst) && (HIWORD((UINT)toolPtr->lpszText) == 0)) {
174         /* load a resource */
175         TRACE("load res string %x %x\n",
176                toolPtr->hinst, (int)toolPtr->lpszText);
177         LoadStringW (toolPtr->hinst, (UINT)toolPtr->lpszText,
178                        infoPtr->szTipText, INFOTIPSIZE);
179     }
180     else if (toolPtr->lpszText) {
181         if (toolPtr->lpszText == LPSTR_TEXTCALLBACKW) {
182             NMTTDISPINFOA ttnmdi;
183
184             /* fill NMHDR struct */
185             ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFOA));
186             ttnmdi.hdr.hwndFrom = hwnd;
187             ttnmdi.hdr.idFrom = toolPtr->uId;
188             ttnmdi.hdr.code = TTN_GETDISPINFOA;
189             ttnmdi.lpszText = (LPSTR)&ttnmdi.szText;
190             ttnmdi.uFlags = toolPtr->uFlags;
191             ttnmdi.lParam = toolPtr->lParam;
192
193             TRACE("hdr.idFrom = %x\n", ttnmdi.hdr.idFrom);
194             SendMessageA (toolPtr->hwnd, WM_NOTIFY,
195                             (WPARAM)toolPtr->uId, (LPARAM)&ttnmdi);
196
197             if ((ttnmdi.hinst) && (HIWORD((UINT)ttnmdi.lpszText) == 0)) {
198                 LoadStringW (ttnmdi.hinst, (UINT)ttnmdi.lpszText,
199                                infoPtr->szTipText, INFOTIPSIZE);
200                 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
201                     toolPtr->hinst = ttnmdi.hinst;
202                     toolPtr->lpszText = (LPWSTR)ttnmdi.lpszText;
203                 }
204             }
205             else if (ttnmdi.szText[0]) {
206                 MultiByteToWideChar(CP_ACP, 0, ttnmdi.szText, 80,
207                                     infoPtr->szTipText, INFOTIPSIZE);
208                 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
209                     INT len = MultiByteToWideChar(CP_ACP, 0, ttnmdi.szText,
210                                                   80, NULL, 0);
211                     toolPtr->hinst = 0;
212                     toolPtr->lpszText = COMCTL32_Alloc (len * sizeof(WCHAR));
213                     MultiByteToWideChar(CP_ACP, 0, ttnmdi.szText, 80,
214                                         toolPtr->lpszText, len);
215                 }
216             }
217             else if (ttnmdi.lpszText == 0) {
218                 /* no text available */
219                 infoPtr->szTipText[0] = L'\0';
220             }
221             else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKA) {
222                 MultiByteToWideChar(CP_ACP, 0, ttnmdi.lpszText, -1,
223                                     infoPtr->szTipText, INFOTIPSIZE);
224                 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
225                     INT len = MultiByteToWideChar(CP_ACP, 0, ttnmdi.lpszText,
226                                                   -1, NULL, 0);
227                     toolPtr->hinst = 0;
228                     toolPtr->lpszText = COMCTL32_Alloc (len * sizeof(WCHAR));
229                     MultiByteToWideChar(CP_ACP, 0, ttnmdi.lpszText, -1,
230                                         toolPtr->lpszText, len);
231                 }
232             }
233             else {
234                 ERR("recursive text callback!\n");
235                 infoPtr->szTipText[0] = '\0';
236             }
237         }
238         else {
239             /* the item is a usual (unicode) text */
240             lstrcpynW (infoPtr->szTipText, toolPtr->lpszText, INFOTIPSIZE);
241         }
242     }
243     else {
244         /* no text available */
245         infoPtr->szTipText[0] = L'\0';
246     }
247
248     TRACE("%s\n", debugstr_w(infoPtr->szTipText));
249 }
250
251
252 static VOID
253 TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIPS_INFO *infoPtr, LPSIZE lpSize)
254 {
255     HDC hdc;
256     HFONT hOldFont;
257     UINT uFlags = DT_EXTERNALLEADING | DT_CALCRECT;
258     RECT rc = {0, 0, 0, 0};
259
260     if (infoPtr->nMaxTipWidth > -1) {
261         rc.right = infoPtr->nMaxTipWidth;
262         uFlags |= DT_WORDBREAK;
263     }
264     if (GetWindowLongA (hwnd, GWL_STYLE) & TTS_NOPREFIX)
265         uFlags |= DT_NOPREFIX;
266     TRACE("%s\n", debugstr_w(infoPtr->szTipText));
267
268     hdc = GetDC (hwnd);
269     hOldFont = SelectObject (hdc, infoPtr->hFont);
270     DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags);
271     SelectObject (hdc, hOldFont);
272     ReleaseDC (hwnd, hdc);
273
274     lpSize->cx = rc.right - rc.left + 4 + 
275                  infoPtr->rcMargin.left + infoPtr->rcMargin.right;
276     lpSize->cy = rc.bottom - rc.top + 4 +
277                  infoPtr->rcMargin.bottom + infoPtr->rcMargin.top;
278 }
279
280
281 static VOID
282 TOOLTIPS_Show (HWND hwnd, TOOLTIPS_INFO *infoPtr)
283 {
284     TTTOOL_INFO *toolPtr;
285     RECT rect, wndrect;
286     SIZE size;
287     NMHDR  hdr;
288
289     if (infoPtr->nTool == -1) {
290         TRACE("invalid tool (-1)!\n");
291         return;
292     }
293
294     infoPtr->nCurrentTool = infoPtr->nTool;
295
296     TRACE("Show tooltip pre %d! (%04x)\n", infoPtr->nTool, hwnd);
297
298     TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nCurrentTool);
299
300     if (infoPtr->szTipText[0] == L'\0') {
301         infoPtr->nCurrentTool = -1;
302         return;
303     }
304
305     TRACE("Show tooltip %d!\n", infoPtr->nCurrentTool);
306     toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
307
308     hdr.hwndFrom = hwnd;
309     hdr.idFrom = toolPtr->uId;
310     hdr.code = TTN_SHOW;
311     SendMessageA (toolPtr->hwnd, WM_NOTIFY,
312                     (WPARAM)toolPtr->uId, (LPARAM)&hdr);
313
314     TRACE("%s\n", debugstr_w(infoPtr->szTipText));
315
316     TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
317     TRACE("size %d - %d\n", size.cx, size.cy);
318
319     if (toolPtr->uFlags & TTF_CENTERTIP) {
320         RECT rc;
321
322         if (toolPtr->uFlags & TTF_IDISHWND)
323             GetWindowRect ((HWND)toolPtr->uId, &rc);
324         else {
325             rc = toolPtr->rect;
326             MapWindowPoints (toolPtr->hwnd, (HWND)0, (LPPOINT)&rc, 2);
327         }
328         rect.left = (rc.left + rc.right - size.cx) / 2;
329         rect.top  = rc.bottom + 2;
330     }
331     else {
332         GetCursorPos ((LPPOINT)&rect);
333         rect.top += 20;
334     }
335
336     TRACE("pos %d - %d\n", rect.left, rect.top);
337
338     rect.right = rect.left + size.cx;
339     rect.bottom = rect.top + size.cy;
340
341     /* check position */
342     wndrect.right = GetSystemMetrics( SM_CXSCREEN );
343     if( rect.right > wndrect.right ) {
344            rect.left -= rect.right - wndrect.right + 2;
345            rect.right = wndrect.right - 2;
346     }
347     wndrect.bottom = GetSystemMetrics( SM_CYSCREEN );
348     if( rect.bottom > wndrect.bottom ) {
349         RECT rc;
350
351         if (toolPtr->uFlags & TTF_IDISHWND)
352             GetWindowRect ((HWND)toolPtr->uId, &rc);
353         else {
354             rc = toolPtr->rect;
355             MapWindowPoints (toolPtr->hwnd, (HWND)0, (LPPOINT)&rc, 2);
356         }   
357         rect.bottom = rc.top - 2;
358         rect.top = rect.bottom - size.cy;
359     }
360
361     AdjustWindowRectEx (&rect, GetWindowLongA (hwnd, GWL_STYLE),
362                         FALSE, GetWindowLongA (hwnd, GWL_EXSTYLE));
363
364     SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
365                     rect.right - rect.left, rect.bottom - rect.top,
366                     SWP_SHOWWINDOW | SWP_NOACTIVATE);
367
368     /* repaint the tooltip */
369     InvalidateRect(hwnd, NULL, TRUE);
370     UpdateWindow(hwnd);
371
372     SetTimer (hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0);
373     TRACE("timer 2 started!\n");
374     SetTimer (hwnd, ID_TIMERLEAVE, infoPtr->nReshowTime, 0);
375     TRACE("timer 3 started!\n");
376 }
377
378
379 static VOID
380 TOOLTIPS_Hide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
381 {
382     TTTOOL_INFO *toolPtr;
383     NMHDR hdr;
384
385     TRACE("Hide tooltip %d! (%04x)\n", infoPtr->nCurrentTool, hwnd);
386
387     if (infoPtr->nCurrentTool == -1)
388         return;
389
390     toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
391     KillTimer (hwnd, ID_TIMERPOP);
392
393     hdr.hwndFrom = hwnd;
394     hdr.idFrom = toolPtr->uId;
395     hdr.code = TTN_POP;
396     SendMessageA (toolPtr->hwnd, WM_NOTIFY,
397                     (WPARAM)toolPtr->uId, (LPARAM)&hdr);
398
399     infoPtr->nCurrentTool = -1;
400
401     SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
402                     SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
403 }
404
405
406 static VOID
407 TOOLTIPS_TrackShow (HWND hwnd, TOOLTIPS_INFO *infoPtr)
408 {
409     TTTOOL_INFO *toolPtr;
410     RECT rect;
411     SIZE size;
412     NMHDR hdr;
413
414     if (infoPtr->nTrackTool == -1) {
415         TRACE("invalid tracking tool (-1)!\n");
416         return;
417     }
418
419     TRACE("show tracking tooltip pre %d!\n", infoPtr->nTrackTool);
420
421     TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nTrackTool);
422
423     if (infoPtr->szTipText[0] == L'\0') {
424         infoPtr->nTrackTool = -1;
425         return;
426     }
427
428     TRACE("show tracking tooltip %d!\n", infoPtr->nTrackTool);
429     toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
430
431     hdr.hwndFrom = hwnd;
432     hdr.idFrom = toolPtr->uId;
433     hdr.code = TTN_SHOW;
434     SendMessageA (toolPtr->hwnd, WM_NOTIFY,
435                     (WPARAM)toolPtr->uId, (LPARAM)&hdr);
436
437     TRACE("%s\n", debugstr_w(infoPtr->szTipText));
438
439     TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
440     TRACE("size %d - %d\n", size.cx, size.cy);
441
442     if (toolPtr->uFlags & TTF_ABSOLUTE) {
443         rect.left = infoPtr->xTrackPos;
444         rect.top  = infoPtr->yTrackPos;
445
446         if (toolPtr->uFlags & TTF_CENTERTIP) {
447             rect.left -= (size.cx / 2);
448             rect.top  -= (size.cy / 2);
449         }
450     }
451     else {
452         RECT rcTool;
453
454         if (toolPtr->uFlags & TTF_IDISHWND)
455             GetWindowRect ((HWND)toolPtr->uId, &rcTool);
456         else {
457             rcTool = toolPtr->rect;
458             MapWindowPoints (toolPtr->hwnd, (HWND)0, (LPPOINT)&rcTool, 2);
459         }
460
461         GetCursorPos ((LPPOINT)&rect);
462         rect.top += 20;
463
464         if (toolPtr->uFlags & TTF_CENTERTIP) {
465             rect.left -= (size.cx / 2);
466             rect.top  -= (size.cy / 2);
467         }
468
469         /* smart placement */
470         if ((rect.left + size.cx > rcTool.left) && (rect.left < rcTool.right) &&
471             (rect.top + size.cy > rcTool.top) && (rect.top < rcTool.bottom))
472             rect.left = rcTool.right;
473     }
474
475     TRACE("pos %d - %d\n", rect.left, rect.top);
476
477     rect.right = rect.left + size.cx;
478     rect.bottom = rect.top + size.cy;
479
480     AdjustWindowRectEx (&rect, GetWindowLongA (hwnd, GWL_STYLE),
481                         FALSE, GetWindowLongA (hwnd, GWL_EXSTYLE));
482
483     SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
484                     rect.right - rect.left, rect.bottom - rect.top,
485                     SWP_SHOWWINDOW | SWP_NOACTIVATE );
486
487     InvalidateRect(hwnd, NULL, TRUE);
488     UpdateWindow(hwnd);
489 }
490
491
492 static VOID
493 TOOLTIPS_TrackHide (HWND hwnd, TOOLTIPS_INFO *infoPtr)
494 {
495     TTTOOL_INFO *toolPtr;
496     NMHDR hdr;
497
498     if (infoPtr->nTrackTool == -1)
499         return;
500
501     toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
502     TRACE("hide tracking tooltip %d!\n", infoPtr->nTrackTool);
503
504     hdr.hwndFrom = hwnd;
505     hdr.idFrom = toolPtr->uId;
506     hdr.code = TTN_POP;
507     SendMessageA (toolPtr->hwnd, WM_NOTIFY,
508                     (WPARAM)toolPtr->uId, (LPARAM)&hdr);
509
510     SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
511                     SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
512 }
513
514
515 static INT
516 TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOA lpToolInfo)
517 {
518     TTTOOL_INFO *toolPtr;
519     INT nTool;
520
521     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
522         toolPtr = &infoPtr->tools[nTool];
523
524         if (!(toolPtr->uFlags & TTF_IDISHWND) && 
525             (lpToolInfo->hwnd == toolPtr->hwnd) &&
526             (lpToolInfo->uId == toolPtr->uId))
527             return nTool;
528     }
529
530     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
531         toolPtr = &infoPtr->tools[nTool];
532
533         if ((toolPtr->uFlags & TTF_IDISHWND) &&
534             (lpToolInfo->uId == toolPtr->uId))
535             return nTool;
536     }
537
538     return -1;
539 }
540
541
542 static INT
543 TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOW lpToolInfo)
544 {
545     TTTOOL_INFO *toolPtr;
546     INT nTool;
547
548     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
549         toolPtr = &infoPtr->tools[nTool];
550
551         if (!(toolPtr->uFlags & TTF_IDISHWND) && 
552             (lpToolInfo->hwnd == toolPtr->hwnd) &&
553             (lpToolInfo->uId == toolPtr->uId))
554             return nTool;
555     }
556
557     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
558         toolPtr = &infoPtr->tools[nTool];
559
560         if ((toolPtr->uFlags & TTF_IDISHWND) &&
561             (lpToolInfo->uId == toolPtr->uId))
562             return nTool;
563     }
564
565     return -1;
566 }
567
568
569 static INT
570 TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO *infoPtr, HWND hwnd, LPPOINT lpPt)
571 {
572     TTTOOL_INFO *toolPtr;
573     INT  nTool;
574
575     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
576         toolPtr = &infoPtr->tools[nTool];
577
578         if (!(toolPtr->uFlags & TTF_IDISHWND)) {
579             if (hwnd != toolPtr->hwnd)
580                 continue;
581             if (!PtInRect (&toolPtr->rect, *lpPt))
582                 continue;
583             return nTool;
584         }
585     }
586
587     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
588         toolPtr = &infoPtr->tools[nTool];
589
590         if (toolPtr->uFlags & TTF_IDISHWND) {
591             if ((HWND)toolPtr->uId == hwnd)
592                 return nTool;
593         }
594     }
595
596     return -1;
597 }
598
599
600 static BOOL
601 TOOLTIPS_IsWindowActive (HWND hwnd)
602 {
603     HWND hwndActive = GetActiveWindow ();
604     if (!hwndActive)
605         return FALSE;
606     if (hwndActive == hwnd)
607         return TRUE;
608     return IsChild (hwndActive, hwnd);
609 }
610
611
612 static INT
613 TOOLTIPS_CheckTool (HWND hwnd, BOOL bShowTest)
614 {
615     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
616     POINT pt;
617     HWND hwndTool;
618     INT nTool;
619
620     GetCursorPos (&pt);
621     hwndTool = SendMessageA (hwnd, TTM_WINDOWFROMPOINT, 0, (LPARAM)&pt);
622     if (hwndTool == 0)
623         return -1;
624
625     ScreenToClient (hwndTool, &pt);
626     nTool = TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
627     if (nTool == -1)
628         return -1;
629
630     if (!(GetWindowLongA (hwnd, GWL_STYLE) & TTS_ALWAYSTIP) && bShowTest) {
631         if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd, GW_OWNER)))
632             return -1;
633     }
634
635     TRACE("tool %d\n", nTool);
636
637     return nTool;
638 }
639
640
641 static LRESULT
642 TOOLTIPS_Activate (HWND hwnd, WPARAM wParam, LPARAM lParam)
643 {
644     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
645
646     infoPtr->bActive = (BOOL)wParam;
647
648     if (infoPtr->bActive)
649         TRACE("activate!\n");
650
651     if (!(infoPtr->bActive) && (infoPtr->nCurrentTool != -1))
652         TOOLTIPS_Hide (hwnd, infoPtr);
653
654     return 0;
655 }
656
657
658 static LRESULT
659 TOOLTIPS_AddToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
660 {
661     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
662     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
663     TTTOOL_INFO *toolPtr;
664
665     if (lpToolInfo == NULL)
666         return FALSE;
667     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
668         return FALSE;
669
670     TRACE("add tool (%x) %x %d%s!\n",
671            hwnd, lpToolInfo->hwnd, lpToolInfo->uId,
672            (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
673
674     if (infoPtr->uNumTools == 0) {
675         infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
676         toolPtr = infoPtr->tools;
677     }
678     else {
679         TTTOOL_INFO *oldTools = infoPtr->tools;
680         infoPtr->tools =
681             COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
682         memcpy (infoPtr->tools, oldTools,
683                 infoPtr->uNumTools * sizeof(TTTOOL_INFO));
684         COMCTL32_Free (oldTools);
685         toolPtr = &infoPtr->tools[infoPtr->uNumTools];
686     }
687
688     infoPtr->uNumTools++;
689
690     /* copy tool data */
691     toolPtr->uFlags = lpToolInfo->uFlags;
692     toolPtr->hwnd   = lpToolInfo->hwnd;
693     toolPtr->uId    = lpToolInfo->uId;
694     toolPtr->rect   = lpToolInfo->rect;
695     toolPtr->hinst  = lpToolInfo->hinst;
696
697     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
698         TRACE("add string id %x!\n", (int)lpToolInfo->lpszText);
699         toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
700     }
701     else if (lpToolInfo->lpszText) {
702         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA) {
703             TRACE("add CALLBACK!\n");
704             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
705         }
706         else {
707             INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
708                                           NULL, 0);
709             TRACE("add text \"%s\"!\n", lpToolInfo->lpszText);
710             toolPtr->lpszText = COMCTL32_Alloc (len * sizeof(WCHAR));
711             MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
712                                 toolPtr->lpszText, len);
713         }
714     }
715
716     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
717         toolPtr->lParam = lpToolInfo->lParam;
718
719     /* install subclassing hook */
720     if (toolPtr->uFlags & TTF_SUBCLASS) {
721         if (toolPtr->uFlags & TTF_IDISHWND) {
722             LPTT_SUBCLASS_INFO lpttsi =
723                 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
724             if (lpttsi == NULL) {
725                 lpttsi =
726                     (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
727                 lpttsi->wpOrigProc = 
728                     (WNDPROC)SetWindowLongA ((HWND)toolPtr->uId,
729                     GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
730                 lpttsi->hwndToolTip = hwnd;
731                 lpttsi->uRefCount++;
732                 SetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass,
733                             (HANDLE)lpttsi);
734             }
735             else
736                 WARN("A window tool must only be listed once!\n");
737         }
738         else {
739             LPTT_SUBCLASS_INFO lpttsi =
740                 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
741             if (lpttsi == NULL) {
742                 lpttsi =
743                     (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
744                 lpttsi->wpOrigProc = 
745                     (WNDPROC)SetWindowLongA (toolPtr->hwnd,
746                     GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
747                 lpttsi->hwndToolTip = hwnd;
748                 lpttsi->uRefCount++;
749                 SetPropA (toolPtr->hwnd, COMCTL32_aSubclass, (HANDLE)lpttsi);
750             }
751             else
752                 lpttsi->uRefCount++;
753         }
754         TRACE("subclassing installed!\n");
755     }
756
757     return TRUE;
758 }
759
760
761 static LRESULT
762 TOOLTIPS_AddToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
763 {
764     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
765     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
766     TTTOOL_INFO *toolPtr;
767
768     if (lpToolInfo == NULL)
769         return FALSE;
770     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
771         return FALSE;
772
773     TRACE("add tool (%x) %x %d%s!\n",
774            hwnd, lpToolInfo->hwnd, lpToolInfo->uId,
775            (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
776
777     if (infoPtr->uNumTools == 0) {
778         infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
779         toolPtr = infoPtr->tools;
780     }
781     else {
782         TTTOOL_INFO *oldTools = infoPtr->tools;
783         infoPtr->tools =
784             COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
785         memcpy (infoPtr->tools, oldTools,
786                 infoPtr->uNumTools * sizeof(TTTOOL_INFO));
787         COMCTL32_Free (oldTools);
788         toolPtr = &infoPtr->tools[infoPtr->uNumTools];
789     }
790
791     infoPtr->uNumTools++;
792
793     /* copy tool data */
794     toolPtr->uFlags = lpToolInfo->uFlags;
795     toolPtr->hwnd   = lpToolInfo->hwnd;
796     toolPtr->uId    = lpToolInfo->uId;
797     toolPtr->rect   = lpToolInfo->rect;
798     toolPtr->hinst  = lpToolInfo->hinst;
799
800     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
801         TRACE("add string id %x!\n", (int)lpToolInfo->lpszText);
802         toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
803     }
804     else if (lpToolInfo->lpszText) {
805         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW) {
806             TRACE("add CALLBACK!\n");
807             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
808         }
809         else {
810             INT len = lstrlenW (lpToolInfo->lpszText);
811             TRACE("add text %s!\n",
812                    debugstr_w(lpToolInfo->lpszText));
813             toolPtr->lpszText = COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
814             strcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
815         }
816     }
817
818     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
819         toolPtr->lParam = lpToolInfo->lParam;
820
821     /* install subclassing hook */
822     if (toolPtr->uFlags & TTF_SUBCLASS) {
823         if (toolPtr->uFlags & TTF_IDISHWND) {
824             LPTT_SUBCLASS_INFO lpttsi =
825                 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
826             if (lpttsi == NULL) {
827                 lpttsi =
828                     (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
829                 lpttsi->wpOrigProc = 
830                     (WNDPROC)SetWindowLongA ((HWND)toolPtr->uId,
831                     GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
832                 lpttsi->hwndToolTip = hwnd;
833                 lpttsi->uRefCount++;
834                 SetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass,
835                             (HANDLE)lpttsi);
836             }
837             else
838                 WARN("A window tool must only be listed once!\n");
839         }
840         else {
841             LPTT_SUBCLASS_INFO lpttsi =
842                 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
843             if (lpttsi == NULL) {
844                 lpttsi =
845                     (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
846                 lpttsi->wpOrigProc = 
847                     (WNDPROC)SetWindowLongA (toolPtr->hwnd,
848                     GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
849                 lpttsi->hwndToolTip = hwnd;
850                 lpttsi->uRefCount++;
851                 SetPropA (toolPtr->hwnd, COMCTL32_aSubclass, (HANDLE)lpttsi);
852             }
853             else
854                 lpttsi->uRefCount++;
855         }
856         TRACE("subclassing installed!\n");
857     }
858
859     return TRUE;
860 }
861
862
863 static LRESULT
864 TOOLTIPS_DelToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
865 {
866     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
867     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
868     TTTOOL_INFO *toolPtr;
869     INT nTool;
870
871     if (lpToolInfo == NULL)
872         return 0;
873     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
874         return 0;
875     if (infoPtr->uNumTools == 0)
876         return 0;
877
878     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
879     if (nTool == -1) return 0;
880
881     TRACE("tool %d\n", nTool);
882
883     /* delete text string */
884     toolPtr = &infoPtr->tools[nTool]; 
885     if ((toolPtr->hinst) && (toolPtr->lpszText)) {
886         if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) &&
887              (HIWORD((INT)toolPtr->lpszText) != 0) )
888             COMCTL32_Free (toolPtr->lpszText);
889     }
890
891     /* remove subclassing */
892     if (toolPtr->uFlags & TTF_SUBCLASS) {
893         if (toolPtr->uFlags & TTF_IDISHWND) {
894             LPTT_SUBCLASS_INFO lpttsi =
895                 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
896             if (lpttsi) {
897                 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
898                                   (LONG)lpttsi->wpOrigProc);
899                 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
900                 COMCTL32_Free (&lpttsi);
901             }
902             else
903                 ERR("Invalid data handle!\n");
904         }
905         else {
906             LPTT_SUBCLASS_INFO lpttsi =
907                 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
908             if (lpttsi) {
909                 if (lpttsi->uRefCount == 1) {
910                     SetWindowLongA ((HWND)toolPtr->hwnd, GWL_WNDPROC,
911                                       (LONG)lpttsi->wpOrigProc);
912                     RemovePropA ((HWND)toolPtr->hwnd, COMCTL32_aSubclass);
913                     COMCTL32_Free (&lpttsi);
914                 }
915                 else
916                     lpttsi->uRefCount--;
917             }
918             else
919                 ERR("Invalid data handle!\n");
920         }
921     }
922
923     /* delete tool from tool list */
924     if (infoPtr->uNumTools == 1) {
925         COMCTL32_Free (infoPtr->tools);
926         infoPtr->tools = NULL;
927     }
928     else {
929         TTTOOL_INFO *oldTools = infoPtr->tools;
930         infoPtr->tools =
931             COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
932
933         if (nTool > 0)
934             memcpy (&infoPtr->tools[0], &oldTools[0],
935                     nTool * sizeof(TTTOOL_INFO));
936
937         if (nTool < infoPtr->uNumTools - 1)
938             memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
939                     (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
940
941         COMCTL32_Free (oldTools);
942     }
943
944     infoPtr->uNumTools--;
945
946     return 0;
947 }
948
949
950 static LRESULT
951 TOOLTIPS_DelToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
952 {
953     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
954     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
955     TTTOOL_INFO *toolPtr;
956     INT nTool;
957
958     if (lpToolInfo == NULL)
959         return 0;
960     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
961         return 0;
962     if (infoPtr->uNumTools == 0)
963         return 0;
964
965     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
966     if (nTool == -1) return 0;
967
968     TRACE("tool %d\n", nTool);
969
970     /* delete text string */
971     toolPtr = &infoPtr->tools[nTool]; 
972     if ((toolPtr->hinst) && (toolPtr->lpszText)) {
973         if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) &&
974              (HIWORD((INT)toolPtr->lpszText) != 0) )
975             COMCTL32_Free (toolPtr->lpszText);
976     }
977
978     /* remove subclassing */
979     if (toolPtr->uFlags & TTF_SUBCLASS) {
980         if (toolPtr->uFlags & TTF_IDISHWND) {
981             LPTT_SUBCLASS_INFO lpttsi =
982                 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
983             if (lpttsi) {
984                 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
985                                   (LONG)lpttsi->wpOrigProc);
986                 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
987                 COMCTL32_Free (&lpttsi);
988             }
989             else
990                 ERR("Invalid data handle!\n");
991         }
992         else {
993             LPTT_SUBCLASS_INFO lpttsi =
994                 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
995             if (lpttsi) {
996                 if (lpttsi->uRefCount == 1) {
997                     SetWindowLongA ((HWND)toolPtr->hwnd, GWL_WNDPROC,
998                                       (LONG)lpttsi->wpOrigProc);
999                     RemovePropA ((HWND)toolPtr->hwnd, COMCTL32_aSubclass);
1000                     COMCTL32_Free (&lpttsi);
1001                 }
1002                 else
1003                     lpttsi->uRefCount--;
1004             }
1005             else
1006                 ERR("Invalid data handle!\n");
1007         }
1008     }
1009
1010     /* delete tool from tool list */
1011     if (infoPtr->uNumTools == 1) {
1012         COMCTL32_Free (infoPtr->tools);
1013         infoPtr->tools = NULL;
1014     }
1015     else {
1016         TTTOOL_INFO *oldTools = infoPtr->tools;
1017         infoPtr->tools =
1018             COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
1019
1020         if (nTool > 0)
1021             memcpy (&infoPtr->tools[0], &oldTools[0],
1022                     nTool * sizeof(TTTOOL_INFO));
1023
1024         if (nTool < infoPtr->uNumTools - 1)
1025             memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
1026                     (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
1027
1028         COMCTL32_Free (oldTools);
1029     }
1030
1031     infoPtr->uNumTools--;
1032
1033     return 0;
1034 }
1035
1036
1037 static LRESULT
1038 TOOLTIPS_EnumToolsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1039 {
1040     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1041     UINT uIndex = (UINT)wParam;
1042     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1043     TTTOOL_INFO *toolPtr;
1044
1045     if (lpToolInfo == NULL)
1046         return FALSE;
1047     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1048         return FALSE;
1049     if (uIndex >= infoPtr->uNumTools)
1050         return FALSE;
1051
1052     TRACE("index=%u\n", uIndex);
1053
1054     toolPtr = &infoPtr->tools[uIndex];
1055
1056     /* copy tool data */
1057     lpToolInfo->uFlags   = toolPtr->uFlags;
1058     lpToolInfo->hwnd     = toolPtr->hwnd;
1059     lpToolInfo->uId      = toolPtr->uId;
1060     lpToolInfo->rect     = toolPtr->rect;
1061     lpToolInfo->hinst    = toolPtr->hinst;
1062 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
1063     lpToolInfo->lpszText = NULL;  /* FIXME */
1064
1065     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1066         lpToolInfo->lParam = toolPtr->lParam;
1067
1068     return TRUE;
1069 }
1070
1071
1072 static LRESULT
1073 TOOLTIPS_EnumToolsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1074 {
1075     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1076     UINT uIndex = (UINT)wParam;
1077     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1078     TTTOOL_INFO *toolPtr;
1079
1080     if (lpToolInfo == NULL)
1081         return FALSE;
1082     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1083         return FALSE;
1084     if (uIndex >= infoPtr->uNumTools)
1085         return FALSE;
1086
1087     TRACE("index=%u\n", uIndex);
1088
1089     toolPtr = &infoPtr->tools[uIndex];
1090
1091     /* copy tool data */
1092     lpToolInfo->uFlags   = toolPtr->uFlags;
1093     lpToolInfo->hwnd     = toolPtr->hwnd;
1094     lpToolInfo->uId      = toolPtr->uId;
1095     lpToolInfo->rect     = toolPtr->rect;
1096     lpToolInfo->hinst    = toolPtr->hinst;
1097 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
1098     lpToolInfo->lpszText = NULL;  /* FIXME */
1099
1100     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1101         lpToolInfo->lParam = toolPtr->lParam;
1102
1103     return TRUE;
1104 }
1105
1106
1107 static LRESULT
1108 TOOLTIPS_GetCurrentToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1109 {
1110     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1111     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1112     TTTOOL_INFO *toolPtr;
1113
1114     if (lpToolInfo == NULL)
1115         return FALSE;
1116     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1117         return FALSE;
1118
1119     if (lpToolInfo) {
1120         if (infoPtr->nCurrentTool > -1) {
1121             toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
1122
1123             /* copy tool data */
1124             lpToolInfo->uFlags   = toolPtr->uFlags;
1125             lpToolInfo->rect     = toolPtr->rect;
1126             lpToolInfo->hinst    = toolPtr->hinst;
1127 /*          lpToolInfo->lpszText = toolPtr->lpszText; */
1128             lpToolInfo->lpszText = NULL;  /* FIXME */
1129
1130             if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1131                 lpToolInfo->lParam = toolPtr->lParam;
1132
1133             return TRUE;
1134         }
1135         else
1136             return FALSE;
1137     }
1138     else
1139         return (infoPtr->nCurrentTool != -1);
1140
1141     return FALSE;
1142 }
1143
1144
1145 static LRESULT
1146 TOOLTIPS_GetCurrentToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1147 {
1148     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1149     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1150     TTTOOL_INFO *toolPtr;
1151
1152     if (lpToolInfo == NULL)
1153         return FALSE;
1154     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1155         return FALSE;
1156
1157     if (lpToolInfo) {
1158         if (infoPtr->nCurrentTool > -1) {
1159             toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
1160
1161             /* copy tool data */
1162             lpToolInfo->uFlags   = toolPtr->uFlags;
1163             lpToolInfo->rect     = toolPtr->rect;
1164             lpToolInfo->hinst    = toolPtr->hinst;
1165 /*          lpToolInfo->lpszText = toolPtr->lpszText; */
1166             lpToolInfo->lpszText = NULL;  /* FIXME */
1167
1168             if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1169                 lpToolInfo->lParam = toolPtr->lParam;
1170
1171             return TRUE;
1172         }
1173         else
1174             return FALSE;
1175     }
1176     else
1177         return (infoPtr->nCurrentTool != -1);
1178
1179     return FALSE;
1180 }
1181
1182
1183 static LRESULT
1184 TOOLTIPS_GetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1185 {
1186     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1187
1188     switch (wParam) {
1189     case TTDT_RESHOW:
1190         return infoPtr->nReshowTime;
1191
1192     case TTDT_AUTOPOP:
1193         return infoPtr->nAutoPopTime;
1194
1195     case TTDT_INITIAL:
1196     case TTDT_AUTOMATIC: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */
1197         return infoPtr->nInitialTime;
1198
1199     default:
1200         WARN("Invalid wParam %x\n", wParam);
1201         break;
1202     }
1203
1204     return -1;
1205 }
1206
1207
1208 static LRESULT
1209 TOOLTIPS_GetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1210 {
1211     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1212     LPRECT lpRect = (LPRECT)lParam;
1213
1214     lpRect->left   = infoPtr->rcMargin.left;
1215     lpRect->right  = infoPtr->rcMargin.right;
1216     lpRect->bottom = infoPtr->rcMargin.bottom;
1217     lpRect->top    = infoPtr->rcMargin.top;
1218
1219     return 0;
1220 }
1221
1222
1223 inline static LRESULT
1224 TOOLTIPS_GetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1225 {
1226     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1227
1228     return infoPtr->nMaxTipWidth;
1229 }
1230
1231
1232 static LRESULT
1233 TOOLTIPS_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1234 {
1235     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1236     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1237     INT nTool;
1238
1239     if (lpToolInfo == NULL)
1240         return 0;
1241     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1242         return 0;
1243
1244     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1245     if (nTool == -1) return 0;
1246
1247     /* NB this API is broken, there is no way for the app to determine
1248        what size buffer it requires nor a way to specify how long the
1249        one it supplies is.  We'll assume it's upto INFOTIPSIZE */
1250
1251     WideCharToMultiByte(CP_ACP, 0, infoPtr->tools[nTool].lpszText, -1,
1252                         lpToolInfo->lpszText, INFOTIPSIZE, NULL, NULL);
1253
1254     return 0;
1255 }
1256
1257
1258 static LRESULT
1259 TOOLTIPS_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1260 {
1261     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1262     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1263     INT nTool;
1264
1265     if (lpToolInfo == NULL)
1266         return 0;
1267     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1268         return 0;
1269
1270     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1271     if (nTool == -1) return 0;
1272
1273     strcpyW (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
1274
1275     return 0;
1276 }
1277
1278
1279 inline static LRESULT
1280 TOOLTIPS_GetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1281 {
1282     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1283     return infoPtr->clrBk;
1284 }
1285
1286
1287 inline static LRESULT
1288 TOOLTIPS_GetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1289 {
1290     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1291     return infoPtr->clrText;
1292 }
1293
1294
1295 inline static LRESULT
1296 TOOLTIPS_GetToolCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1297 {
1298     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1299     return infoPtr->uNumTools;
1300 }
1301
1302
1303 static LRESULT
1304 TOOLTIPS_GetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1305 {
1306     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1307     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1308     TTTOOL_INFO *toolPtr;
1309     INT nTool;
1310
1311     if (lpToolInfo == NULL)
1312         return FALSE;
1313     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1314         return FALSE;
1315     if (infoPtr->uNumTools == 0)
1316         return FALSE;
1317
1318     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1319     if (nTool == -1)
1320         return FALSE;
1321
1322     TRACE("tool %d\n", nTool);
1323
1324     toolPtr = &infoPtr->tools[nTool];
1325
1326     /* copy tool data */
1327     lpToolInfo->uFlags   = toolPtr->uFlags;
1328     lpToolInfo->rect     = toolPtr->rect;
1329     lpToolInfo->hinst    = toolPtr->hinst;
1330 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
1331     lpToolInfo->lpszText = NULL;  /* FIXME */
1332
1333     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1334         lpToolInfo->lParam = toolPtr->lParam;
1335
1336     return TRUE;
1337 }
1338
1339
1340 static LRESULT
1341 TOOLTIPS_GetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1342 {
1343     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1344     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1345     TTTOOL_INFO *toolPtr;
1346     INT nTool;
1347
1348     if (lpToolInfo == NULL)
1349         return FALSE;
1350     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1351         return FALSE;
1352     if (infoPtr->uNumTools == 0)
1353         return FALSE;
1354
1355     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1356     if (nTool == -1)
1357         return FALSE;
1358
1359     TRACE("tool %d\n", nTool);
1360
1361     toolPtr = &infoPtr->tools[nTool];
1362
1363     /* copy tool data */
1364     lpToolInfo->uFlags   = toolPtr->uFlags;
1365     lpToolInfo->rect     = toolPtr->rect;
1366     lpToolInfo->hinst    = toolPtr->hinst;
1367 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
1368     lpToolInfo->lpszText = NULL;  /* FIXME */
1369
1370     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1371         lpToolInfo->lParam = toolPtr->lParam;
1372
1373     return TRUE;
1374 }
1375
1376
1377 static LRESULT
1378 TOOLTIPS_HitTestA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1379 {
1380     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1381     LPTTHITTESTINFOA lptthit = (LPTTHITTESTINFOA)lParam;
1382     TTTOOL_INFO *toolPtr;
1383     INT nTool;
1384
1385     if (lptthit == 0)
1386         return FALSE;
1387
1388     nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
1389     if (nTool == -1)
1390         return FALSE;
1391
1392     TRACE("tool %d!\n", nTool);
1393
1394     /* copy tool data */
1395     if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOA)) {
1396         toolPtr = &infoPtr->tools[nTool];
1397
1398         lptthit->ti.uFlags   = toolPtr->uFlags;
1399         lptthit->ti.hwnd     = toolPtr->hwnd;
1400         lptthit->ti.uId      = toolPtr->uId;
1401         lptthit->ti.rect     = toolPtr->rect;
1402         lptthit->ti.hinst    = toolPtr->hinst;
1403 /*      lptthit->ti.lpszText = toolPtr->lpszText; */
1404         lptthit->ti.lpszText = NULL;  /* FIXME */
1405         lptthit->ti.lParam   = toolPtr->lParam;
1406     }
1407
1408     return TRUE;
1409 }
1410
1411
1412 static LRESULT
1413 TOOLTIPS_HitTestW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1414 {
1415     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1416     LPTTHITTESTINFOW lptthit = (LPTTHITTESTINFOW)lParam;
1417     TTTOOL_INFO *toolPtr;
1418     INT nTool;
1419
1420     if (lptthit == 0)
1421         return FALSE;
1422
1423     nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
1424     if (nTool == -1)
1425         return FALSE;
1426
1427     TRACE("tool %d!\n", nTool);
1428
1429     /* copy tool data */
1430     if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOW)) {
1431         toolPtr = &infoPtr->tools[nTool];
1432
1433         lptthit->ti.uFlags   = toolPtr->uFlags;
1434         lptthit->ti.hwnd     = toolPtr->hwnd;
1435         lptthit->ti.uId      = toolPtr->uId;
1436         lptthit->ti.rect     = toolPtr->rect;
1437         lptthit->ti.hinst    = toolPtr->hinst;
1438 /*      lptthit->ti.lpszText = toolPtr->lpszText; */
1439         lptthit->ti.lpszText = NULL;  /* FIXME */
1440         lptthit->ti.lParam   = toolPtr->lParam;
1441     }
1442
1443     return TRUE;
1444 }
1445
1446
1447 static LRESULT
1448 TOOLTIPS_NewToolRectA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1449 {
1450     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1451     LPTTTOOLINFOA lpti = (LPTTTOOLINFOA)lParam;
1452     INT nTool;
1453
1454     if (lpti == NULL)
1455         return 0;
1456     if (lpti->cbSize < TTTOOLINFO_V1_SIZEA)
1457         return FALSE;
1458
1459     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpti);
1460     if (nTool == -1) return 0;
1461
1462     infoPtr->tools[nTool].rect = lpti->rect;
1463
1464     return 0;
1465 }
1466
1467
1468 static LRESULT
1469 TOOLTIPS_NewToolRectW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1470 {
1471     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1472     LPTTTOOLINFOW lpti = (LPTTTOOLINFOW)lParam;
1473     INT nTool;
1474
1475     if (lpti == NULL)
1476         return 0;
1477     if (lpti->cbSize < TTTOOLINFO_V1_SIZEW)
1478         return FALSE;
1479
1480     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpti);
1481     if (nTool == -1) return 0;
1482
1483     infoPtr->tools[nTool].rect = lpti->rect;
1484
1485     return 0;
1486 }
1487
1488
1489 inline static LRESULT
1490 TOOLTIPS_Pop (HWND hwnd, WPARAM wParam, LPARAM lParam)
1491 {
1492     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1493     TOOLTIPS_Hide (hwnd, infoPtr);
1494
1495     return 0;
1496 }
1497
1498
1499 static LRESULT
1500 TOOLTIPS_RelayEvent (HWND hwnd, WPARAM wParam, LPARAM lParam)
1501 {
1502     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1503     LPMSG lpMsg = (LPMSG)lParam;
1504     POINT pt;
1505     INT nOldTool;
1506
1507     if (lParam == 0) {
1508         ERR("lpMsg == NULL!\n");
1509         return 0;
1510     }
1511
1512     switch (lpMsg->message) {
1513         case WM_LBUTTONDOWN:
1514         case WM_LBUTTONUP:
1515         case WM_MBUTTONDOWN:
1516         case WM_MBUTTONUP:
1517         case WM_RBUTTONDOWN:
1518         case WM_RBUTTONUP:
1519             TOOLTIPS_Hide (hwnd, infoPtr);
1520             break;
1521
1522         case WM_MOUSEMOVE:
1523             pt.x = LOWORD(lpMsg->lParam);
1524             pt.y = HIWORD(lpMsg->lParam);
1525             nOldTool = infoPtr->nTool;
1526             infoPtr->nTool = TOOLTIPS_GetToolFromPoint(infoPtr, lpMsg->hwnd,
1527                                                        &pt);
1528             TRACE("tool (%x) %d %d %d\n", hwnd, nOldTool,
1529                   infoPtr->nTool, infoPtr->nCurrentTool);
1530             TRACE("WM_MOUSEMOVE (%04x %ld %ld)\n", hwnd, pt.x, pt.y);
1531
1532             if (infoPtr->nTool != nOldTool) {
1533                 if(infoPtr->nTool == -1) { /* Moved out of all tools */
1534                     TOOLTIPS_Hide(hwnd, infoPtr);
1535                     KillTimer(hwnd, ID_TIMERLEAVE);
1536                 } else if (nOldTool == -1) { /* Moved from outside */
1537                     if(infoPtr->bActive) {
1538                         SetTimer(hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0);
1539                         TRACE("timer 1 started!\n");
1540                     }
1541                 } else { /* Moved from one to another */
1542                     TOOLTIPS_Hide (hwnd, infoPtr);
1543                     KillTimer(hwnd, ID_TIMERLEAVE);
1544                     if(infoPtr->bActive) {
1545                         SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
1546                         TRACE("timer 1 started!\n");
1547                     }
1548                 }
1549             } else if(infoPtr->nCurrentTool != -1) { /* restart autopop */
1550                 KillTimer(hwnd, ID_TIMERPOP);
1551                 SetTimer(hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0);
1552                 TRACE("timer 2 restarted\n");
1553             }
1554             break;
1555     }
1556
1557     return 0;
1558 }
1559
1560
1561 static LRESULT
1562 TOOLTIPS_SetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1563 {
1564     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1565     INT nTime = (INT)LOWORD(lParam);
1566
1567     switch (wParam) {
1568     case TTDT_AUTOMATIC:
1569         if (nTime <= 0)
1570             nTime = GetDoubleClickTime();
1571         infoPtr->nReshowTime    = nTime / 5;
1572         infoPtr->nAutoPopTime   = nTime * 10;
1573         infoPtr->nInitialTime   = nTime;
1574         break;
1575
1576     case TTDT_RESHOW:
1577         if(nTime < 0)
1578             nTime = GetDoubleClickTime() / 5;
1579         infoPtr->nReshowTime = nTime;
1580         break;
1581
1582     case TTDT_AUTOPOP:
1583         if(nTime < 0)
1584             nTime = GetDoubleClickTime() * 10;
1585         infoPtr->nAutoPopTime = nTime;
1586         break;
1587
1588     case TTDT_INITIAL:
1589         if(nTime < 0)
1590             nTime = GetDoubleClickTime();
1591         infoPtr->nInitialTime = nTime;
1592             break;
1593
1594     default:
1595         WARN("Invalid wParam %x\n", wParam);
1596         break;
1597     }
1598
1599     return 0;
1600 }
1601
1602
1603 static LRESULT
1604 TOOLTIPS_SetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1605 {
1606     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1607     LPRECT lpRect = (LPRECT)lParam;
1608
1609     infoPtr->rcMargin.left   = lpRect->left;
1610     infoPtr->rcMargin.right  = lpRect->right;
1611     infoPtr->rcMargin.bottom = lpRect->bottom;
1612     infoPtr->rcMargin.top    = lpRect->top;
1613
1614     return 0;
1615 }
1616
1617
1618 inline static LRESULT
1619 TOOLTIPS_SetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1620 {
1621     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1622     INT nTemp = infoPtr->nMaxTipWidth;
1623
1624     infoPtr->nMaxTipWidth = (INT)lParam;
1625
1626     return nTemp;
1627 }
1628
1629
1630 inline static LRESULT
1631 TOOLTIPS_SetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1632 {
1633     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1634
1635     infoPtr->clrBk = (COLORREF)wParam;
1636
1637     return 0;
1638 }
1639
1640
1641 inline static LRESULT
1642 TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1643 {
1644     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1645
1646     infoPtr->clrText = (COLORREF)wParam;
1647
1648     return 0;
1649 }
1650
1651
1652 static LRESULT
1653 TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1654 {
1655     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1656     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1657     TTTOOL_INFO *toolPtr;
1658     INT nTool;
1659
1660     if (lpToolInfo == NULL)
1661         return 0;
1662     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1663         return 0;
1664
1665     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1666     if (nTool == -1) return 0;
1667
1668     TRACE("tool %d\n", nTool);
1669
1670     toolPtr = &infoPtr->tools[nTool];
1671
1672     /* copy tool data */
1673     toolPtr->uFlags = lpToolInfo->uFlags;
1674     toolPtr->hwnd   = lpToolInfo->hwnd;
1675     toolPtr->uId    = lpToolInfo->uId;
1676     toolPtr->rect   = lpToolInfo->rect;
1677     toolPtr->hinst  = lpToolInfo->hinst;
1678
1679     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1680         TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText);
1681         toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1682     }
1683     else if (lpToolInfo->lpszText) {
1684         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1685             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1686         else {
1687             if ( (toolPtr->lpszText) &&
1688                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1689                 COMCTL32_Free (toolPtr->lpszText);
1690                 toolPtr->lpszText = NULL;
1691             }
1692             if (lpToolInfo->lpszText) {
1693                 INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText,
1694                                               -1, NULL, 0);
1695                 toolPtr->lpszText = COMCTL32_Alloc (len * sizeof(WCHAR));
1696                 MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
1697                                     toolPtr->lpszText, len);
1698             }
1699         }
1700     }
1701
1702     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1703         toolPtr->lParam = lpToolInfo->lParam;
1704
1705     return 0;
1706 }
1707
1708
1709 static LRESULT
1710 TOOLTIPS_SetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1711 {
1712     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1713     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1714     TTTOOL_INFO *toolPtr;
1715     INT nTool;
1716
1717     if (lpToolInfo == NULL)
1718         return 0;
1719     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1720         return 0;
1721
1722     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1723     if (nTool == -1) return 0;
1724
1725     TRACE("tool %d\n", nTool);
1726
1727     toolPtr = &infoPtr->tools[nTool];
1728
1729     /* copy tool data */
1730     toolPtr->uFlags = lpToolInfo->uFlags;
1731     toolPtr->hwnd   = lpToolInfo->hwnd;
1732     toolPtr->uId    = lpToolInfo->uId;
1733     toolPtr->rect   = lpToolInfo->rect;
1734     toolPtr->hinst  = lpToolInfo->hinst;
1735
1736     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1737         TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText);
1738         toolPtr->lpszText = lpToolInfo->lpszText;
1739     }
1740     else if (lpToolInfo->lpszText) {
1741         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1742             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1743         else {
1744             if ( (toolPtr->lpszText) &&
1745                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1746                 COMCTL32_Free (toolPtr->lpszText);
1747                 toolPtr->lpszText = NULL;
1748             }
1749             if (lpToolInfo->lpszText) {
1750                 INT len = lstrlenW (lpToolInfo->lpszText);
1751                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1752                 strcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1753             }
1754         }
1755     }
1756
1757     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1758         toolPtr->lParam = lpToolInfo->lParam;
1759
1760     return 0;
1761 }
1762
1763
1764 static LRESULT
1765 TOOLTIPS_TrackActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1766 {
1767     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1768     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1769
1770     if (lpToolInfo == NULL)
1771         return 0;
1772     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1773         return FALSE;
1774
1775     if ((BOOL)wParam) {
1776         /* activate */
1777         infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1778         if (infoPtr->nTrackTool != -1) {
1779             TRACE("activated!\n");
1780             infoPtr->bTrackActive = TRUE;
1781             TOOLTIPS_TrackShow (hwnd, infoPtr);
1782         }
1783     }
1784     else {
1785         /* deactivate */
1786         TOOLTIPS_TrackHide (hwnd, infoPtr);
1787
1788         infoPtr->bTrackActive = FALSE;
1789         infoPtr->nTrackTool = -1;
1790
1791         TRACE("deactivated!\n");
1792     }
1793
1794     return 0;
1795 }
1796
1797
1798 static LRESULT
1799 TOOLTIPS_TrackPosition (HWND hwnd, WPARAM wParam, LPARAM lParam)
1800 {
1801     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1802
1803     infoPtr->xTrackPos = (INT)LOWORD(lParam);
1804     infoPtr->yTrackPos = (INT)HIWORD(lParam);
1805
1806     if (infoPtr->bTrackActive) {
1807         TRACE("[%d %d]\n",
1808                infoPtr->xTrackPos, infoPtr->yTrackPos);
1809
1810         TOOLTIPS_TrackShow (hwnd, infoPtr);
1811     }
1812
1813     return 0;
1814 }
1815
1816
1817 static LRESULT
1818 TOOLTIPS_Update (HWND hwnd, WPARAM wParam, LPARAM lParam)
1819 {
1820     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1821
1822     if (infoPtr->nCurrentTool != -1)
1823         UpdateWindow (hwnd);
1824
1825     return 0;
1826 }
1827
1828
1829 static LRESULT
1830 TOOLTIPS_UpdateTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1831 {
1832     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1833     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1834     TTTOOL_INFO *toolPtr;
1835     INT nTool;
1836
1837     if (lpToolInfo == NULL)
1838         return 0;
1839     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1840         return FALSE;
1841
1842     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1843     if (nTool == -1) return 0;
1844
1845     TRACE("tool %d\n", nTool);
1846
1847     toolPtr = &infoPtr->tools[nTool];
1848
1849     /* copy tool text */
1850     toolPtr->hinst  = lpToolInfo->hinst;
1851
1852     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1853         toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1854     }
1855     else if (lpToolInfo->lpszText) {
1856         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1857             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1858         else {
1859             if ( (toolPtr->lpszText) &&
1860                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1861                 COMCTL32_Free (toolPtr->lpszText);
1862                 toolPtr->lpszText = NULL;
1863             }
1864             if (lpToolInfo->lpszText) {
1865                 INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText,
1866                                               -1, NULL, 0);
1867                 toolPtr->lpszText = COMCTL32_Alloc (len * sizeof(WCHAR));
1868                 MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
1869                                     toolPtr->lpszText, len);
1870             }
1871         }
1872     }
1873
1874     if(infoPtr->nCurrentTool == -1) return 0;
1875     /* force repaint */
1876     if (infoPtr->bActive)
1877         TOOLTIPS_Show (hwnd, infoPtr);
1878     else if (infoPtr->bTrackActive)
1879         TOOLTIPS_TrackShow (hwnd, infoPtr);
1880
1881     return 0;
1882 }
1883
1884
1885 static LRESULT
1886 TOOLTIPS_UpdateTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1887 {
1888     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1889     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1890     TTTOOL_INFO *toolPtr;
1891     INT nTool;
1892
1893     if (lpToolInfo == NULL)
1894         return 0;
1895     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1896         return FALSE;
1897
1898     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1899     if (nTool == -1)
1900         return 0;
1901
1902     TRACE("tool %d\n", nTool);
1903
1904     toolPtr = &infoPtr->tools[nTool];
1905
1906     /* copy tool text */
1907     toolPtr->hinst  = lpToolInfo->hinst;
1908
1909     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1910         toolPtr->lpszText = lpToolInfo->lpszText;
1911     }
1912     else if (lpToolInfo->lpszText) {
1913         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1914             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1915         else {
1916             if ( (toolPtr->lpszText)  &&
1917                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1918                 COMCTL32_Free (toolPtr->lpszText);
1919                 toolPtr->lpszText = NULL;
1920             }
1921             if (lpToolInfo->lpszText) {
1922                 INT len = lstrlenW (lpToolInfo->lpszText);
1923                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1924                 strcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1925             }
1926         }
1927     }
1928
1929     if(infoPtr->nCurrentTool == -1) return 0;
1930     /* force repaint */
1931     if (infoPtr->bActive)
1932         TOOLTIPS_Show (hwnd, infoPtr);
1933     else if (infoPtr->bTrackActive)
1934         TOOLTIPS_TrackShow (hwnd, infoPtr);
1935
1936     return 0;
1937 }
1938
1939
1940 static LRESULT
1941 TOOLTIPS_WindowFromPoint (HWND hwnd, WPARAM wParam, LPARAM lParam)
1942 {
1943     return WindowFromPoint (*((LPPOINT)lParam));
1944 }
1945
1946
1947
1948 static LRESULT
1949 TOOLTIPS_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1950 {
1951     TOOLTIPS_INFO *infoPtr;
1952     NONCLIENTMETRICSA nclm;
1953     INT nResult;
1954
1955     /* allocate memory for info structure */
1956     infoPtr = (TOOLTIPS_INFO *)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO));
1957     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1958
1959     /* initialize info structure */
1960     infoPtr->bActive = TRUE;
1961     infoPtr->bTrackActive = FALSE;
1962     infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
1963     infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
1964
1965     nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1966     SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1967     infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
1968
1969     infoPtr->nMaxTipWidth = -1;
1970     infoPtr->nTool = -1;
1971     infoPtr->nCurrentTool = -1;
1972     infoPtr->nTrackTool = -1;
1973
1974     TOOLTIPS_SetDelayTime(hwnd, TTDT_AUTOMATIC, 0L);
1975
1976     nResult = (INT) SendMessageA (GetParent (hwnd), WM_NOTIFYFORMAT,
1977                                   (WPARAM)hwnd, (LPARAM)NF_QUERY);
1978     if (nResult == NFR_ANSI) {
1979         infoPtr->bNotifyUnicode = FALSE;
1980         TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
1981     }
1982     else if (nResult == NFR_UNICODE) {
1983         infoPtr->bNotifyUnicode = TRUE;
1984         TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
1985     }
1986     else {
1987         ERR (" -- WM_NOTIFYFORMAT returns: error!\n");
1988     }
1989
1990     SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
1991
1992     return 0;
1993 }
1994
1995
1996 static LRESULT
1997 TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1998 {
1999     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2000     TTTOOL_INFO *toolPtr;
2001     INT i;
2002
2003     /* free tools */
2004     if (infoPtr->tools) {
2005         for (i = 0; i < infoPtr->uNumTools; i++) {
2006             toolPtr = &infoPtr->tools[i];
2007             if ((toolPtr->hinst) && (toolPtr->lpszText)) {
2008                 if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) &&
2009                      (HIWORD((INT)toolPtr->lpszText) != 0) ) 
2010                 {
2011                     COMCTL32_Free (toolPtr->lpszText);
2012                     toolPtr->lpszText = NULL;
2013                 }
2014             }
2015
2016             /* remove subclassing */
2017         if (toolPtr->uFlags & TTF_SUBCLASS) {
2018             LPTT_SUBCLASS_INFO lpttsi;
2019     
2020             if (toolPtr->uFlags & TTF_IDISHWND) {
2021                 lpttsi = (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
2022                 if (lpttsi) {
2023                     SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
2024                               (LONG)lpttsi->wpOrigProc);
2025                     RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
2026                     COMCTL32_Free (&lpttsi);
2027                 }
2028             }
2029             else {
2030                 lpttsi = (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
2031                 if (lpttsi) {
2032                     SetWindowLongA ((HWND)toolPtr->hwnd, GWL_WNDPROC,
2033                                (LONG)lpttsi->wpOrigProc);
2034                     RemovePropA ((HWND)toolPtr->hwnd, COMCTL32_aSubclass);
2035                     COMCTL32_Free (&lpttsi);
2036                 }
2037             }
2038         }
2039     }
2040         COMCTL32_Free (infoPtr->tools);
2041     }
2042
2043     /* delete font */
2044     DeleteObject (infoPtr->hFont);
2045
2046     /* free tool tips info data */
2047     COMCTL32_Free (infoPtr);
2048     SetWindowLongA(hwnd, 0, 0);
2049     return 0;
2050 }
2051
2052
2053 static LRESULT
2054 TOOLTIPS_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
2055 {
2056     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2057     RECT rect;
2058     HBRUSH hBrush;
2059
2060     hBrush = CreateSolidBrush (infoPtr->clrBk);
2061     GetClientRect (hwnd, &rect);
2062     FillRect ((HDC)wParam, &rect, hBrush);
2063     DeleteObject (hBrush);
2064
2065     return FALSE;
2066 }
2067
2068
2069 static LRESULT
2070 TOOLTIPS_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2071 {
2072     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2073
2074     return infoPtr->hFont;
2075 }
2076
2077
2078 static LRESULT
2079 TOOLTIPS_MouseMessage (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2080 {
2081     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2082
2083     TOOLTIPS_Hide (hwnd, infoPtr);
2084
2085     return 0;
2086 }
2087
2088
2089 static LRESULT
2090 TOOLTIPS_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2091 {
2092     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2093
2094     dwStyle &= 0x0000FFFF;
2095     dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
2096     SetWindowLongA (hwnd, GWL_STYLE, dwStyle);
2097
2098     return TRUE;
2099 }
2100
2101
2102 static LRESULT
2103 TOOLTIPS_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2104 {
2105     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2106     INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool;
2107
2108     TRACE(" nTool=%d\n", nTool);
2109
2110     if ((nTool > -1) && (nTool < infoPtr->uNumTools)) {
2111         if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) {
2112             TRACE("-- in transparent mode!\n");
2113             return HTTRANSPARENT;
2114         }
2115     }
2116
2117     return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
2118 }
2119
2120
2121 static LRESULT
2122 TOOLTIPS_NotifyFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2123 {
2124     FIXME ("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
2125
2126     return 0;
2127 }
2128
2129
2130 static LRESULT
2131 TOOLTIPS_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
2132 {
2133     HDC hdc;
2134     PAINTSTRUCT ps;
2135
2136     hdc = (wParam == 0) ? BeginPaint (hwnd, &ps) : (HDC)wParam;
2137     TOOLTIPS_Refresh (hwnd, hdc);
2138     if (!wParam)
2139         EndPaint (hwnd, &ps);
2140     return 0;
2141 }
2142
2143
2144 static LRESULT
2145 TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2146 {
2147     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2148
2149     infoPtr->hFont = (HFONT)wParam;
2150
2151     if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
2152         FIXME("full redraw needed!\n");
2153     }
2154
2155     return 0;
2156 }
2157 /******************************************************************
2158  * TOOLTIPS_OnWMGetTextLength
2159  *
2160  * This function is called when the tooltip receive a
2161  * WM_GETTEXTLENGTH message.
2162  * wParam : not used
2163  * lParam : not used
2164  *
2165  * returns the length, in characters, of the tip text
2166  ******************************************************************/
2167 static LRESULT
2168 TOOLTIPS_OnWMGetTextLength(HWND hwnd, WPARAM wParam, LPARAM lParam)
2169 {
2170     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2171     return lstrlenW(infoPtr->szTipText);
2172 }
2173
2174 /******************************************************************
2175  * TOOLTIPS_OnWMGetText
2176  *
2177  * This function is called when the tooltip receive a
2178  * WM_GETTEXT message.
2179  * wParam : specifies the maximum number of characters to be copied
2180  * lParam : is the pointer to the buffer that will receive
2181  *          the tip text
2182  *
2183  * returns the number of characters copied
2184  ******************************************************************/
2185 static LRESULT
2186 TOOLTIPS_OnWMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
2187 {
2188     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2189
2190     if(!infoPtr || !(infoPtr->szTipText))
2191         return 0;
2192
2193     return WideCharToMultiByte(CP_ACP, 0, infoPtr->szTipText, -1,
2194                                (LPSTR)lParam, wParam, NULL, NULL);
2195 }
2196
2197 static LRESULT
2198 TOOLTIPS_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam)
2199 {
2200     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2201     INT nOldTool;
2202
2203     TRACE("timer %d (%x) expired!\n", wParam, hwnd);
2204
2205     switch (wParam) {
2206     case ID_TIMERSHOW:
2207         KillTimer (hwnd, ID_TIMERSHOW);
2208         nOldTool = infoPtr->nTool;
2209         if ((infoPtr->nTool = TOOLTIPS_CheckTool (hwnd, TRUE)) == nOldTool)
2210             TOOLTIPS_Show (hwnd, infoPtr);
2211         break;
2212
2213     case ID_TIMERPOP:
2214         TOOLTIPS_Hide (hwnd, infoPtr);
2215         break;
2216
2217     case ID_TIMERLEAVE:
2218         nOldTool = infoPtr->nTool;
2219         infoPtr->nTool = TOOLTIPS_CheckTool (hwnd, FALSE);
2220         TRACE("tool (%x) %d %d %d\n", hwnd, nOldTool,
2221               infoPtr->nTool, infoPtr->nCurrentTool);
2222         if (infoPtr->nTool != nOldTool) {
2223             if(infoPtr->nTool == -1) { /* Moved out of all tools */
2224                 TOOLTIPS_Hide(hwnd, infoPtr);
2225                 KillTimer(hwnd, ID_TIMERLEAVE);
2226             } else if (nOldTool == -1) { /* Moved from outside */
2227                 ERR("How did this happen?\n");
2228             } else { /* Moved from one to another */
2229                 TOOLTIPS_Hide (hwnd, infoPtr);
2230                 KillTimer(hwnd, ID_TIMERLEAVE);
2231                 if(infoPtr->bActive) {
2232                     SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
2233                     TRACE("timer 1 started!\n");
2234                 }
2235             }
2236         }
2237         break;
2238
2239     default:
2240         ERR("Unknown timer id %d\n", wParam);
2241         break;
2242     }
2243     return 0;
2244 }
2245
2246
2247 static LRESULT
2248 TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
2249 {
2250     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2251     NONCLIENTMETRICSA nclm;
2252
2253     infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
2254     infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
2255
2256     DeleteObject (infoPtr->hFont);
2257     nclm.cbSize = sizeof(NONCLIENTMETRICSA);
2258     SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
2259     infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
2260
2261     return 0;
2262 }
2263
2264
2265 LRESULT CALLBACK
2266 TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2267 {
2268     LPTT_SUBCLASS_INFO lpttsi =
2269         (LPTT_SUBCLASS_INFO)GetPropA (hwnd, COMCTL32_aSubclass);
2270     MSG msg;
2271
2272     switch(uMsg) {
2273     case WM_MOUSEMOVE:
2274     case WM_LBUTTONDOWN:
2275     case WM_LBUTTONUP:
2276     case WM_MBUTTONDOWN:
2277     case WM_MBUTTONUP:
2278     case WM_RBUTTONDOWN:
2279     case WM_RBUTTONUP:
2280         msg.hwnd = hwnd;
2281         msg.message = uMsg;
2282         msg.wParam = wParam;
2283         msg.lParam = lParam;
2284         TOOLTIPS_RelayEvent(lpttsi->hwndToolTip, 0, (LPARAM)&msg);
2285         break;
2286
2287     default:
2288         break;
2289     }
2290     return CallWindowProcA (lpttsi->wpOrigProc, hwnd, uMsg, wParam, lParam);
2291 }
2292
2293
2294 static LRESULT CALLBACK
2295 TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2296 {
2297     TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx\n", hwnd, uMsg, wParam, lParam);
2298     if (!TOOLTIPS_GetInfoPtr(hwnd) && (uMsg != WM_CREATE) && (uMsg != WM_NCCREATE))
2299         return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2300     switch (uMsg)
2301     {
2302         case TTM_ACTIVATE:
2303             return TOOLTIPS_Activate (hwnd, wParam, lParam);
2304
2305         case TTM_ADDTOOLA:
2306             return TOOLTIPS_AddToolA (hwnd, wParam, lParam);
2307
2308         case TTM_ADDTOOLW:
2309             return TOOLTIPS_AddToolW (hwnd, wParam, lParam);
2310
2311         case TTM_DELTOOLA:
2312             return TOOLTIPS_DelToolA (hwnd, wParam, lParam);
2313
2314         case TTM_DELTOOLW:
2315             return TOOLTIPS_DelToolW (hwnd, wParam, lParam);
2316
2317         case TTM_ENUMTOOLSA:
2318             return TOOLTIPS_EnumToolsA (hwnd, wParam, lParam);
2319
2320         case TTM_ENUMTOOLSW:
2321             return TOOLTIPS_EnumToolsW (hwnd, wParam, lParam);
2322
2323         case TTM_GETCURRENTTOOLA:
2324             return TOOLTIPS_GetCurrentToolA (hwnd, wParam, lParam);
2325
2326         case TTM_GETCURRENTTOOLW:
2327             return TOOLTIPS_GetCurrentToolW (hwnd, wParam, lParam);
2328
2329         case TTM_GETDELAYTIME:
2330             return TOOLTIPS_GetDelayTime (hwnd, wParam, lParam);
2331
2332         case TTM_GETMARGIN:
2333             return TOOLTIPS_GetMargin (hwnd, wParam, lParam);
2334
2335         case TTM_GETMAXTIPWIDTH:
2336             return TOOLTIPS_GetMaxTipWidth (hwnd, wParam, lParam);
2337
2338         case TTM_GETTEXTA:
2339             return TOOLTIPS_GetTextA (hwnd, wParam, lParam);
2340
2341         case TTM_GETTEXTW:
2342             return TOOLTIPS_GetTextW (hwnd, wParam, lParam);
2343
2344         case TTM_GETTIPBKCOLOR:
2345             return TOOLTIPS_GetTipBkColor (hwnd, wParam, lParam);
2346
2347         case TTM_GETTIPTEXTCOLOR:
2348             return TOOLTIPS_GetTipTextColor (hwnd, wParam, lParam);
2349
2350         case TTM_GETTOOLCOUNT:
2351             return TOOLTIPS_GetToolCount (hwnd, wParam, lParam);
2352
2353         case TTM_GETTOOLINFOA:
2354             return TOOLTIPS_GetToolInfoA (hwnd, wParam, lParam);
2355
2356         case TTM_GETTOOLINFOW:
2357             return TOOLTIPS_GetToolInfoW (hwnd, wParam, lParam);
2358
2359         case TTM_HITTESTA:
2360             return TOOLTIPS_HitTestA (hwnd, wParam, lParam);
2361
2362         case TTM_HITTESTW:
2363             return TOOLTIPS_HitTestW (hwnd, wParam, lParam);
2364
2365         case TTM_NEWTOOLRECTA:
2366             return TOOLTIPS_NewToolRectA (hwnd, wParam, lParam);
2367
2368         case TTM_NEWTOOLRECTW:
2369             return TOOLTIPS_NewToolRectW (hwnd, wParam, lParam);
2370
2371         case TTM_POP:
2372             return TOOLTIPS_Pop (hwnd, wParam, lParam);
2373
2374         case TTM_RELAYEVENT:
2375             return TOOLTIPS_RelayEvent (hwnd, wParam, lParam);
2376
2377         case TTM_SETDELAYTIME:
2378             return TOOLTIPS_SetDelayTime (hwnd, wParam, lParam);
2379
2380         case TTM_SETMARGIN:
2381             return TOOLTIPS_SetMargin (hwnd, wParam, lParam);
2382
2383         case TTM_SETMAXTIPWIDTH:
2384             return TOOLTIPS_SetMaxTipWidth (hwnd, wParam, lParam);
2385
2386         case TTM_SETTIPBKCOLOR:
2387             return TOOLTIPS_SetTipBkColor (hwnd, wParam, lParam);
2388
2389         case TTM_SETTIPTEXTCOLOR:
2390             return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam);
2391
2392         case TTM_SETTOOLINFOA:
2393             return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
2394
2395         case TTM_SETTOOLINFOW:
2396             return TOOLTIPS_SetToolInfoW (hwnd, wParam, lParam);
2397
2398         case TTM_TRACKACTIVATE:
2399             return TOOLTIPS_TrackActivate (hwnd, wParam, lParam);
2400
2401         case TTM_TRACKPOSITION:
2402             return TOOLTIPS_TrackPosition (hwnd, wParam, lParam);
2403
2404         case TTM_UPDATE:
2405             return TOOLTIPS_Update (hwnd, wParam, lParam);
2406
2407         case TTM_UPDATETIPTEXTA:
2408             return TOOLTIPS_UpdateTipTextA (hwnd, wParam, lParam);
2409
2410         case TTM_UPDATETIPTEXTW:
2411             return TOOLTIPS_UpdateTipTextW (hwnd, wParam, lParam);
2412
2413         case TTM_WINDOWFROMPOINT:
2414             return TOOLTIPS_WindowFromPoint (hwnd, wParam, lParam);
2415
2416
2417         case WM_CREATE:
2418             return TOOLTIPS_Create (hwnd, wParam, lParam);
2419
2420         case WM_DESTROY:
2421             return TOOLTIPS_Destroy (hwnd, wParam, lParam);
2422
2423         case WM_ERASEBKGND:
2424             return TOOLTIPS_EraseBackground (hwnd, wParam, lParam);
2425
2426         case WM_GETFONT:
2427             return TOOLTIPS_GetFont (hwnd, wParam, lParam);
2428
2429         case WM_GETTEXT:
2430             return TOOLTIPS_OnWMGetText (hwnd, wParam, lParam);
2431         
2432         case WM_GETTEXTLENGTH:
2433             return TOOLTIPS_OnWMGetTextLength (hwnd, wParam, lParam);
2434  
2435
2436         case WM_LBUTTONDOWN:
2437         case WM_LBUTTONUP:
2438         case WM_MBUTTONDOWN:
2439         case WM_MBUTTONUP:
2440         case WM_RBUTTONDOWN:
2441         case WM_RBUTTONUP:
2442         case WM_MOUSEMOVE:
2443             return TOOLTIPS_MouseMessage (hwnd, uMsg, wParam, lParam);
2444
2445         case WM_NCCREATE:
2446             return TOOLTIPS_NCCreate (hwnd, wParam, lParam);
2447
2448         case WM_NCHITTEST:
2449             return TOOLTIPS_NCHitTest (hwnd, wParam, lParam);
2450
2451         case WM_NOTIFYFORMAT:
2452             return TOOLTIPS_NotifyFormat (hwnd, wParam, lParam);
2453
2454         case WM_PAINT:
2455             return TOOLTIPS_Paint (hwnd, wParam, lParam);
2456
2457         case WM_SETFONT:
2458             return TOOLTIPS_SetFont (hwnd, wParam, lParam);
2459
2460         case WM_TIMER:
2461             return TOOLTIPS_Timer (hwnd, wParam, lParam);
2462
2463         case WM_WININICHANGE:
2464             return TOOLTIPS_WinIniChange (hwnd, wParam, lParam);
2465
2466         default:
2467             if (uMsg >= WM_USER)
2468                 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2469                      uMsg, wParam, lParam);
2470             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2471     }
2472     return 0;
2473 }
2474
2475
2476 VOID
2477 TOOLTIPS_Register (void)
2478 {
2479     WNDCLASSA wndClass;
2480
2481     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2482     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
2483     wndClass.lpfnWndProc   = (WNDPROC)TOOLTIPS_WindowProc;
2484     wndClass.cbClsExtra    = 0;
2485     wndClass.cbWndExtra    = sizeof(TOOLTIPS_INFO *);
2486     wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
2487     wndClass.hbrBackground = 0;
2488     wndClass.lpszClassName = TOOLTIPS_CLASSA;
2489  
2490     RegisterClassA (&wndClass);
2491 }
2492
2493
2494 VOID
2495 TOOLTIPS_Unregister (void)
2496 {
2497     UnregisterClassA (TOOLTIPS_CLASSA, (HINSTANCE)NULL);
2498 }
2499