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