Don't crash if DeviceCapabilities(DC_PAPERNAMES) fails.
[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 %ld x %ld\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 %ld x %ld\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     /* make sure the tooltip has disappeared before deleting it */
884     TOOLTIPS_Hide(hwnd, infoPtr);
885     
886     /* delete text string */
887     toolPtr = &infoPtr->tools[nTool]; 
888     if ((toolPtr->hinst) && (toolPtr->lpszText)) {
889         if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) &&
890              (HIWORD((INT)toolPtr->lpszText) != 0) )
891             COMCTL32_Free (toolPtr->lpszText);
892     }
893
894     /* remove subclassing */
895     if (toolPtr->uFlags & TTF_SUBCLASS) {
896         if (toolPtr->uFlags & TTF_IDISHWND) {
897             LPTT_SUBCLASS_INFO lpttsi =
898                 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
899             if (lpttsi) {
900                 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
901                                   (LONG)lpttsi->wpOrigProc);
902                 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
903                 COMCTL32_Free (&lpttsi);
904             }
905             else
906                 ERR("Invalid data handle!\n");
907         }
908         else {
909             LPTT_SUBCLASS_INFO lpttsi =
910                 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
911             if (lpttsi) {
912                 if (lpttsi->uRefCount == 1) {
913                     SetWindowLongA ((HWND)toolPtr->hwnd, GWL_WNDPROC,
914                                       (LONG)lpttsi->wpOrigProc);
915                     RemovePropA ((HWND)toolPtr->hwnd, COMCTL32_aSubclass);
916                     COMCTL32_Free (&lpttsi);
917                 }
918                 else
919                     lpttsi->uRefCount--;
920             }
921             else
922                 ERR("Invalid data handle!\n");
923         }
924     }
925
926     /* delete tool from tool list */
927     if (infoPtr->uNumTools == 1) {
928         COMCTL32_Free (infoPtr->tools);
929         infoPtr->tools = NULL;
930     }
931     else {
932         TTTOOL_INFO *oldTools = infoPtr->tools;
933         infoPtr->tools =
934             COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
935
936         if (nTool > 0)
937             memcpy (&infoPtr->tools[0], &oldTools[0],
938                     nTool * sizeof(TTTOOL_INFO));
939
940         if (nTool < infoPtr->uNumTools - 1)
941             memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
942                     (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
943
944         COMCTL32_Free (oldTools);
945     }
946
947     /* destroying tool that mouse was on on last relayed mouse move */
948     if (infoPtr->nTool == nTool)
949     {
950         /* no current tool (0 means first tool) */
951         infoPtr->nTool = -1;    
952     }
953     
954     infoPtr->uNumTools--;
955     
956     return 0;
957 }
958
959
960 static LRESULT
961 TOOLTIPS_DelToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
962 {
963     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
964     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
965     TTTOOL_INFO *toolPtr;
966     INT nTool;
967
968     if (lpToolInfo == NULL)
969         return 0;
970     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
971         return 0;
972     if (infoPtr->uNumTools == 0)
973         return 0;
974
975     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
976     if (nTool == -1) return 0;
977
978     TRACE("tool %d\n", nTool);
979
980     /* make sure the tooltip has disappeared before deleting it */
981     TOOLTIPS_Hide(hwnd, infoPtr);    
982     
983     /* delete text string */
984     toolPtr = &infoPtr->tools[nTool]; 
985     if ((toolPtr->hinst) && (toolPtr->lpszText)) {
986         if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) &&
987              (HIWORD((INT)toolPtr->lpszText) != 0) )
988             COMCTL32_Free (toolPtr->lpszText);
989     }
990
991     /* remove subclassing */
992     if (toolPtr->uFlags & TTF_SUBCLASS) {
993         if (toolPtr->uFlags & TTF_IDISHWND) {
994             LPTT_SUBCLASS_INFO lpttsi =
995                 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
996             if (lpttsi) {
997                 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
998                                   (LONG)lpttsi->wpOrigProc);
999                 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
1000                 COMCTL32_Free (&lpttsi);
1001             }
1002             else
1003                 ERR("Invalid data handle!\n");
1004         }
1005         else {
1006             LPTT_SUBCLASS_INFO lpttsi =
1007                 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
1008             if (lpttsi) {
1009                 if (lpttsi->uRefCount == 1) {
1010                     SetWindowLongA ((HWND)toolPtr->hwnd, GWL_WNDPROC,
1011                                       (LONG)lpttsi->wpOrigProc);
1012                     RemovePropA ((HWND)toolPtr->hwnd, COMCTL32_aSubclass);
1013                     COMCTL32_Free (&lpttsi);
1014                 }
1015                 else
1016                     lpttsi->uRefCount--;
1017             }
1018             else
1019                 ERR("Invalid data handle!\n");
1020         }
1021     }
1022
1023     /* delete tool from tool list */
1024     if (infoPtr->uNumTools == 1) {
1025         COMCTL32_Free (infoPtr->tools);
1026         infoPtr->tools = NULL;
1027     }
1028     else {
1029         TTTOOL_INFO *oldTools = infoPtr->tools;
1030         infoPtr->tools =
1031             COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
1032
1033         if (nTool > 0)
1034             memcpy (&infoPtr->tools[0], &oldTools[0],
1035                     nTool * sizeof(TTTOOL_INFO));
1036
1037         if (nTool < infoPtr->uNumTools - 1)
1038             memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
1039                     (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
1040
1041         COMCTL32_Free (oldTools);
1042     }
1043
1044     /* destroying tool that mouse was on on last relayed mouse move */
1045     if (infoPtr->nTool == nTool)
1046     {
1047         /* no current tool (0 means first tool) */
1048         infoPtr->nTool = -1;    
1049     }
1050     
1051     infoPtr->uNumTools--;
1052     
1053     return 0;
1054 }
1055
1056
1057 static LRESULT
1058 TOOLTIPS_EnumToolsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1059 {
1060     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1061     UINT uIndex = (UINT)wParam;
1062     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1063     TTTOOL_INFO *toolPtr;
1064
1065     if (lpToolInfo == NULL)
1066         return FALSE;
1067     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1068         return FALSE;
1069     if (uIndex >= infoPtr->uNumTools)
1070         return FALSE;
1071
1072     TRACE("index=%u\n", uIndex);
1073
1074     toolPtr = &infoPtr->tools[uIndex];
1075
1076     /* copy tool data */
1077     lpToolInfo->uFlags   = toolPtr->uFlags;
1078     lpToolInfo->hwnd     = toolPtr->hwnd;
1079     lpToolInfo->uId      = toolPtr->uId;
1080     lpToolInfo->rect     = toolPtr->rect;
1081     lpToolInfo->hinst    = toolPtr->hinst;
1082 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
1083     lpToolInfo->lpszText = NULL;  /* FIXME */
1084
1085     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1086         lpToolInfo->lParam = toolPtr->lParam;
1087
1088     return TRUE;
1089 }
1090
1091
1092 static LRESULT
1093 TOOLTIPS_EnumToolsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1094 {
1095     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1096     UINT uIndex = (UINT)wParam;
1097     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1098     TTTOOL_INFO *toolPtr;
1099
1100     if (lpToolInfo == NULL)
1101         return FALSE;
1102     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1103         return FALSE;
1104     if (uIndex >= infoPtr->uNumTools)
1105         return FALSE;
1106
1107     TRACE("index=%u\n", uIndex);
1108
1109     toolPtr = &infoPtr->tools[uIndex];
1110
1111     /* copy tool data */
1112     lpToolInfo->uFlags   = toolPtr->uFlags;
1113     lpToolInfo->hwnd     = toolPtr->hwnd;
1114     lpToolInfo->uId      = toolPtr->uId;
1115     lpToolInfo->rect     = toolPtr->rect;
1116     lpToolInfo->hinst    = toolPtr->hinst;
1117 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
1118     lpToolInfo->lpszText = NULL;  /* FIXME */
1119
1120     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1121         lpToolInfo->lParam = toolPtr->lParam;
1122
1123     return TRUE;
1124 }
1125
1126
1127 static LRESULT
1128 TOOLTIPS_GetCurrentToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1129 {
1130     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1131     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1132     TTTOOL_INFO *toolPtr;
1133
1134     if (lpToolInfo == NULL)
1135         return FALSE;
1136     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1137         return FALSE;
1138
1139     if (lpToolInfo) {
1140         if (infoPtr->nCurrentTool > -1) {
1141             toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
1142
1143             /* copy tool data */
1144             lpToolInfo->uFlags   = toolPtr->uFlags;
1145             lpToolInfo->rect     = toolPtr->rect;
1146             lpToolInfo->hinst    = toolPtr->hinst;
1147 /*          lpToolInfo->lpszText = toolPtr->lpszText; */
1148             lpToolInfo->lpszText = NULL;  /* FIXME */
1149
1150             if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1151                 lpToolInfo->lParam = toolPtr->lParam;
1152
1153             return TRUE;
1154         }
1155         else
1156             return FALSE;
1157     }
1158     else
1159         return (infoPtr->nCurrentTool != -1);
1160
1161     return FALSE;
1162 }
1163
1164
1165 static LRESULT
1166 TOOLTIPS_GetCurrentToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1167 {
1168     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1169     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1170     TTTOOL_INFO *toolPtr;
1171
1172     if (lpToolInfo == NULL)
1173         return FALSE;
1174     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1175         return FALSE;
1176
1177     if (lpToolInfo) {
1178         if (infoPtr->nCurrentTool > -1) {
1179             toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
1180
1181             /* copy tool data */
1182             lpToolInfo->uFlags   = toolPtr->uFlags;
1183             lpToolInfo->rect     = toolPtr->rect;
1184             lpToolInfo->hinst    = toolPtr->hinst;
1185 /*          lpToolInfo->lpszText = toolPtr->lpszText; */
1186             lpToolInfo->lpszText = NULL;  /* FIXME */
1187
1188             if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1189                 lpToolInfo->lParam = toolPtr->lParam;
1190
1191             return TRUE;
1192         }
1193         else
1194             return FALSE;
1195     }
1196     else
1197         return (infoPtr->nCurrentTool != -1);
1198
1199     return FALSE;
1200 }
1201
1202
1203 static LRESULT
1204 TOOLTIPS_GetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1205 {
1206     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1207
1208     switch (wParam) {
1209     case TTDT_RESHOW:
1210         return infoPtr->nReshowTime;
1211
1212     case TTDT_AUTOPOP:
1213         return infoPtr->nAutoPopTime;
1214
1215     case TTDT_INITIAL:
1216     case TTDT_AUTOMATIC: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */
1217         return infoPtr->nInitialTime;
1218
1219     default:
1220         WARN("Invalid wParam %x\n", wParam);
1221         break;
1222     }
1223
1224     return -1;
1225 }
1226
1227
1228 static LRESULT
1229 TOOLTIPS_GetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1230 {
1231     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1232     LPRECT lpRect = (LPRECT)lParam;
1233
1234     lpRect->left   = infoPtr->rcMargin.left;
1235     lpRect->right  = infoPtr->rcMargin.right;
1236     lpRect->bottom = infoPtr->rcMargin.bottom;
1237     lpRect->top    = infoPtr->rcMargin.top;
1238
1239     return 0;
1240 }
1241
1242
1243 inline static LRESULT
1244 TOOLTIPS_GetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1245 {
1246     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1247
1248     return infoPtr->nMaxTipWidth;
1249 }
1250
1251
1252 static LRESULT
1253 TOOLTIPS_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1254 {
1255     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1256     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1257     INT nTool;
1258
1259     if (lpToolInfo == NULL)
1260         return 0;
1261     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1262         return 0;
1263
1264     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1265     if (nTool == -1) return 0;
1266
1267     /* NB this API is broken, there is no way for the app to determine
1268        what size buffer it requires nor a way to specify how long the
1269        one it supplies is.  We'll assume it's upto INFOTIPSIZE */
1270
1271     WideCharToMultiByte(CP_ACP, 0, infoPtr->tools[nTool].lpszText, -1,
1272                         lpToolInfo->lpszText, INFOTIPSIZE, NULL, NULL);
1273
1274     return 0;
1275 }
1276
1277
1278 static LRESULT
1279 TOOLTIPS_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1280 {
1281     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1282     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1283     INT nTool;
1284
1285     if (lpToolInfo == NULL)
1286         return 0;
1287     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1288         return 0;
1289
1290     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1291     if (nTool == -1) return 0;
1292
1293     strcpyW (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
1294
1295     return 0;
1296 }
1297
1298
1299 inline static LRESULT
1300 TOOLTIPS_GetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1301 {
1302     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1303     return infoPtr->clrBk;
1304 }
1305
1306
1307 inline static LRESULT
1308 TOOLTIPS_GetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1309 {
1310     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1311     return infoPtr->clrText;
1312 }
1313
1314
1315 inline static LRESULT
1316 TOOLTIPS_GetToolCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1317 {
1318     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1319     return infoPtr->uNumTools;
1320 }
1321
1322
1323 static LRESULT
1324 TOOLTIPS_GetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1325 {
1326     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1327     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1328     TTTOOL_INFO *toolPtr;
1329     INT nTool;
1330
1331     if (lpToolInfo == NULL)
1332         return FALSE;
1333     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1334         return FALSE;
1335     if (infoPtr->uNumTools == 0)
1336         return FALSE;
1337
1338     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1339     if (nTool == -1)
1340         return FALSE;
1341
1342     TRACE("tool %d\n", nTool);
1343
1344     toolPtr = &infoPtr->tools[nTool];
1345
1346     /* copy tool data */
1347     lpToolInfo->uFlags   = toolPtr->uFlags;
1348     lpToolInfo->rect     = toolPtr->rect;
1349     lpToolInfo->hinst    = toolPtr->hinst;
1350 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
1351     lpToolInfo->lpszText = NULL;  /* FIXME */
1352
1353     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1354         lpToolInfo->lParam = toolPtr->lParam;
1355
1356     return TRUE;
1357 }
1358
1359
1360 static LRESULT
1361 TOOLTIPS_GetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1362 {
1363     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1364     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1365     TTTOOL_INFO *toolPtr;
1366     INT nTool;
1367
1368     if (lpToolInfo == NULL)
1369         return FALSE;
1370     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1371         return FALSE;
1372     if (infoPtr->uNumTools == 0)
1373         return FALSE;
1374
1375     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1376     if (nTool == -1)
1377         return FALSE;
1378
1379     TRACE("tool %d\n", nTool);
1380
1381     toolPtr = &infoPtr->tools[nTool];
1382
1383     /* copy tool data */
1384     lpToolInfo->uFlags   = toolPtr->uFlags;
1385     lpToolInfo->rect     = toolPtr->rect;
1386     lpToolInfo->hinst    = toolPtr->hinst;
1387 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
1388     lpToolInfo->lpszText = NULL;  /* FIXME */
1389
1390     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1391         lpToolInfo->lParam = toolPtr->lParam;
1392
1393     return TRUE;
1394 }
1395
1396
1397 static LRESULT
1398 TOOLTIPS_HitTestA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1399 {
1400     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1401     LPTTHITTESTINFOA lptthit = (LPTTHITTESTINFOA)lParam;
1402     TTTOOL_INFO *toolPtr;
1403     INT nTool;
1404
1405     if (lptthit == 0)
1406         return FALSE;
1407
1408     nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
1409     if (nTool == -1)
1410         return FALSE;
1411
1412     TRACE("tool %d!\n", nTool);
1413
1414     /* copy tool data */
1415     if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOA)) {
1416         toolPtr = &infoPtr->tools[nTool];
1417
1418         lptthit->ti.uFlags   = toolPtr->uFlags;
1419         lptthit->ti.hwnd     = toolPtr->hwnd;
1420         lptthit->ti.uId      = toolPtr->uId;
1421         lptthit->ti.rect     = toolPtr->rect;
1422         lptthit->ti.hinst    = toolPtr->hinst;
1423 /*      lptthit->ti.lpszText = toolPtr->lpszText; */
1424         lptthit->ti.lpszText = NULL;  /* FIXME */
1425         lptthit->ti.lParam   = toolPtr->lParam;
1426     }
1427
1428     return TRUE;
1429 }
1430
1431
1432 static LRESULT
1433 TOOLTIPS_HitTestW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1434 {
1435     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1436     LPTTHITTESTINFOW lptthit = (LPTTHITTESTINFOW)lParam;
1437     TTTOOL_INFO *toolPtr;
1438     INT nTool;
1439
1440     if (lptthit == 0)
1441         return FALSE;
1442
1443     nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
1444     if (nTool == -1)
1445         return FALSE;
1446
1447     TRACE("tool %d!\n", nTool);
1448
1449     /* copy tool data */
1450     if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOW)) {
1451         toolPtr = &infoPtr->tools[nTool];
1452
1453         lptthit->ti.uFlags   = toolPtr->uFlags;
1454         lptthit->ti.hwnd     = toolPtr->hwnd;
1455         lptthit->ti.uId      = toolPtr->uId;
1456         lptthit->ti.rect     = toolPtr->rect;
1457         lptthit->ti.hinst    = toolPtr->hinst;
1458 /*      lptthit->ti.lpszText = toolPtr->lpszText; */
1459         lptthit->ti.lpszText = NULL;  /* FIXME */
1460         lptthit->ti.lParam   = toolPtr->lParam;
1461     }
1462
1463     return TRUE;
1464 }
1465
1466
1467 static LRESULT
1468 TOOLTIPS_NewToolRectA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1469 {
1470     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1471     LPTTTOOLINFOA lpti = (LPTTTOOLINFOA)lParam;
1472     INT nTool;
1473
1474     if (lpti == NULL)
1475         return 0;
1476     if (lpti->cbSize < TTTOOLINFO_V1_SIZEA)
1477         return FALSE;
1478
1479     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpti);
1480     if (nTool == -1) return 0;
1481
1482     infoPtr->tools[nTool].rect = lpti->rect;
1483
1484     return 0;
1485 }
1486
1487
1488 static LRESULT
1489 TOOLTIPS_NewToolRectW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1490 {
1491     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1492     LPTTTOOLINFOW lpti = (LPTTTOOLINFOW)lParam;
1493     INT nTool;
1494
1495     if (lpti == NULL)
1496         return 0;
1497     if (lpti->cbSize < TTTOOLINFO_V1_SIZEW)
1498         return FALSE;
1499
1500     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpti);
1501     if (nTool == -1) return 0;
1502
1503     infoPtr->tools[nTool].rect = lpti->rect;
1504
1505     return 0;
1506 }
1507
1508
1509 inline static LRESULT
1510 TOOLTIPS_Pop (HWND hwnd, WPARAM wParam, LPARAM lParam)
1511 {
1512     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1513     TOOLTIPS_Hide (hwnd, infoPtr);
1514
1515     return 0;
1516 }
1517
1518
1519 static LRESULT
1520 TOOLTIPS_RelayEvent (HWND hwnd, WPARAM wParam, LPARAM lParam)
1521 {
1522     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1523     LPMSG lpMsg = (LPMSG)lParam;
1524     POINT pt;
1525     INT nOldTool;
1526
1527     if (lParam == 0) {
1528         ERR("lpMsg == NULL!\n");
1529         return 0;
1530     }
1531
1532     switch (lpMsg->message) {
1533         case WM_LBUTTONDOWN:
1534         case WM_LBUTTONUP:
1535         case WM_MBUTTONDOWN:
1536         case WM_MBUTTONUP:
1537         case WM_RBUTTONDOWN:
1538         case WM_RBUTTONUP:
1539             TOOLTIPS_Hide (hwnd, infoPtr);
1540             break;
1541
1542         case WM_MOUSEMOVE:
1543             pt.x = LOWORD(lpMsg->lParam);
1544             pt.y = HIWORD(lpMsg->lParam);
1545             nOldTool = infoPtr->nTool;
1546             infoPtr->nTool = TOOLTIPS_GetToolFromPoint(infoPtr, lpMsg->hwnd,
1547                                                        &pt);
1548             TRACE("tool (%x) %d %d %d\n", hwnd, nOldTool,
1549                   infoPtr->nTool, infoPtr->nCurrentTool);
1550             TRACE("WM_MOUSEMOVE (%04x %ld %ld)\n", hwnd, pt.x, pt.y);
1551
1552             if (infoPtr->nTool != nOldTool) {
1553                 if(infoPtr->nTool == -1) { /* Moved out of all tools */
1554                     TOOLTIPS_Hide(hwnd, infoPtr);
1555                     KillTimer(hwnd, ID_TIMERLEAVE);
1556                 } else if (nOldTool == -1) { /* Moved from outside */
1557                     if(infoPtr->bActive) {
1558                         SetTimer(hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0);
1559                         TRACE("timer 1 started!\n");
1560                     }
1561                 } else { /* Moved from one to another */
1562                     TOOLTIPS_Hide (hwnd, infoPtr);
1563                     KillTimer(hwnd, ID_TIMERLEAVE);
1564                     if(infoPtr->bActive) {
1565                         SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
1566                         TRACE("timer 1 started!\n");
1567                     }
1568                 }
1569             } else if(infoPtr->nCurrentTool != -1) { /* restart autopop */
1570                 KillTimer(hwnd, ID_TIMERPOP);
1571                 SetTimer(hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0);
1572                 TRACE("timer 2 restarted\n");
1573             }
1574             break;
1575     }
1576
1577     return 0;
1578 }
1579
1580
1581 static LRESULT
1582 TOOLTIPS_SetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1583 {
1584     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1585     INT nTime = (INT)LOWORD(lParam);
1586
1587     switch (wParam) {
1588     case TTDT_AUTOMATIC:
1589         if (nTime <= 0)
1590             nTime = GetDoubleClickTime();
1591         infoPtr->nReshowTime    = nTime / 5;
1592         infoPtr->nAutoPopTime   = nTime * 10;
1593         infoPtr->nInitialTime   = nTime;
1594         break;
1595
1596     case TTDT_RESHOW:
1597         if(nTime < 0)
1598             nTime = GetDoubleClickTime() / 5;
1599         infoPtr->nReshowTime = nTime;
1600         break;
1601
1602     case TTDT_AUTOPOP:
1603         if(nTime < 0)
1604             nTime = GetDoubleClickTime() * 10;
1605         infoPtr->nAutoPopTime = nTime;
1606         break;
1607
1608     case TTDT_INITIAL:
1609         if(nTime < 0)
1610             nTime = GetDoubleClickTime();
1611         infoPtr->nInitialTime = nTime;
1612             break;
1613
1614     default:
1615         WARN("Invalid wParam %x\n", wParam);
1616         break;
1617     }
1618
1619     return 0;
1620 }
1621
1622
1623 static LRESULT
1624 TOOLTIPS_SetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1625 {
1626     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1627     LPRECT lpRect = (LPRECT)lParam;
1628
1629     infoPtr->rcMargin.left   = lpRect->left;
1630     infoPtr->rcMargin.right  = lpRect->right;
1631     infoPtr->rcMargin.bottom = lpRect->bottom;
1632     infoPtr->rcMargin.top    = lpRect->top;
1633
1634     return 0;
1635 }
1636
1637
1638 inline static LRESULT
1639 TOOLTIPS_SetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1640 {
1641     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1642     INT nTemp = infoPtr->nMaxTipWidth;
1643
1644     infoPtr->nMaxTipWidth = (INT)lParam;
1645
1646     return nTemp;
1647 }
1648
1649
1650 inline static LRESULT
1651 TOOLTIPS_SetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1652 {
1653     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1654
1655     infoPtr->clrBk = (COLORREF)wParam;
1656
1657     return 0;
1658 }
1659
1660
1661 inline static LRESULT
1662 TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1663 {
1664     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1665
1666     infoPtr->clrText = (COLORREF)wParam;
1667
1668     return 0;
1669 }
1670
1671
1672 static LRESULT
1673 TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1674 {
1675     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1676     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1677     TTTOOL_INFO *toolPtr;
1678     INT nTool;
1679
1680     if (lpToolInfo == NULL)
1681         return 0;
1682     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1683         return 0;
1684
1685     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1686     if (nTool == -1) return 0;
1687
1688     TRACE("tool %d\n", nTool);
1689
1690     toolPtr = &infoPtr->tools[nTool];
1691
1692     /* copy tool data */
1693     toolPtr->uFlags = lpToolInfo->uFlags;
1694     toolPtr->hwnd   = lpToolInfo->hwnd;
1695     toolPtr->uId    = lpToolInfo->uId;
1696     toolPtr->rect   = lpToolInfo->rect;
1697     toolPtr->hinst  = lpToolInfo->hinst;
1698
1699     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1700         TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText);
1701         toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1702     }
1703     else if (lpToolInfo->lpszText) {
1704         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1705             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1706         else {
1707             if ( (toolPtr->lpszText) &&
1708                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1709                 COMCTL32_Free (toolPtr->lpszText);
1710                 toolPtr->lpszText = NULL;
1711             }
1712             if (lpToolInfo->lpszText) {
1713                 INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText,
1714                                               -1, NULL, 0);
1715                 toolPtr->lpszText = COMCTL32_Alloc (len * sizeof(WCHAR));
1716                 MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
1717                                     toolPtr->lpszText, len);
1718             }
1719         }
1720     }
1721
1722     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1723         toolPtr->lParam = lpToolInfo->lParam;
1724
1725     return 0;
1726 }
1727
1728
1729 static LRESULT
1730 TOOLTIPS_SetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1731 {
1732     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1733     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1734     TTTOOL_INFO *toolPtr;
1735     INT nTool;
1736
1737     if (lpToolInfo == NULL)
1738         return 0;
1739     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1740         return 0;
1741
1742     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1743     if (nTool == -1) return 0;
1744
1745     TRACE("tool %d\n", nTool);
1746
1747     toolPtr = &infoPtr->tools[nTool];
1748
1749     /* copy tool data */
1750     toolPtr->uFlags = lpToolInfo->uFlags;
1751     toolPtr->hwnd   = lpToolInfo->hwnd;
1752     toolPtr->uId    = lpToolInfo->uId;
1753     toolPtr->rect   = lpToolInfo->rect;
1754     toolPtr->hinst  = lpToolInfo->hinst;
1755
1756     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1757         TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText);
1758         toolPtr->lpszText = lpToolInfo->lpszText;
1759     }
1760     else if (lpToolInfo->lpszText) {
1761         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1762             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1763         else {
1764             if ( (toolPtr->lpszText) &&
1765                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1766                 COMCTL32_Free (toolPtr->lpszText);
1767                 toolPtr->lpszText = NULL;
1768             }
1769             if (lpToolInfo->lpszText) {
1770                 INT len = lstrlenW (lpToolInfo->lpszText);
1771                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1772                 strcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1773             }
1774         }
1775     }
1776
1777     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1778         toolPtr->lParam = lpToolInfo->lParam;
1779
1780     return 0;
1781 }
1782
1783
1784 static LRESULT
1785 TOOLTIPS_TrackActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1786 {
1787     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1788     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1789
1790     if (lpToolInfo == NULL)
1791         return 0;
1792     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1793         return FALSE;
1794
1795     if ((BOOL)wParam) {
1796         /* activate */
1797         infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1798         if (infoPtr->nTrackTool != -1) {
1799             TRACE("activated!\n");
1800             infoPtr->bTrackActive = TRUE;
1801             TOOLTIPS_TrackShow (hwnd, infoPtr);
1802         }
1803     }
1804     else {
1805         /* deactivate */
1806         TOOLTIPS_TrackHide (hwnd, infoPtr);
1807
1808         infoPtr->bTrackActive = FALSE;
1809         infoPtr->nTrackTool = -1;
1810
1811         TRACE("deactivated!\n");
1812     }
1813
1814     return 0;
1815 }
1816
1817
1818 static LRESULT
1819 TOOLTIPS_TrackPosition (HWND hwnd, WPARAM wParam, LPARAM lParam)
1820 {
1821     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1822
1823     infoPtr->xTrackPos = (INT)LOWORD(lParam);
1824     infoPtr->yTrackPos = (INT)HIWORD(lParam);
1825
1826     if (infoPtr->bTrackActive) {
1827         TRACE("[%d %d]\n",
1828                infoPtr->xTrackPos, infoPtr->yTrackPos);
1829
1830         TOOLTIPS_TrackShow (hwnd, infoPtr);
1831     }
1832
1833     return 0;
1834 }
1835
1836
1837 static LRESULT
1838 TOOLTIPS_Update (HWND hwnd, WPARAM wParam, LPARAM lParam)
1839 {
1840     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1841
1842     if (infoPtr->nCurrentTool != -1)
1843         UpdateWindow (hwnd);
1844
1845     return 0;
1846 }
1847
1848
1849 static LRESULT
1850 TOOLTIPS_UpdateTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1851 {
1852     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1853     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1854     TTTOOL_INFO *toolPtr;
1855     INT nTool;
1856
1857     if (lpToolInfo == NULL)
1858         return 0;
1859     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1860         return FALSE;
1861
1862     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1863     if (nTool == -1) return 0;
1864
1865     TRACE("tool %d\n", nTool);
1866
1867     toolPtr = &infoPtr->tools[nTool];
1868
1869     /* copy tool text */
1870     toolPtr->hinst  = lpToolInfo->hinst;
1871
1872     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1873         toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1874     }
1875     else if (lpToolInfo->lpszText) {
1876         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1877             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1878         else {
1879             if ( (toolPtr->lpszText) &&
1880                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1881                 COMCTL32_Free (toolPtr->lpszText);
1882                 toolPtr->lpszText = NULL;
1883             }
1884             if (lpToolInfo->lpszText) {
1885                 INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText,
1886                                               -1, NULL, 0);
1887                 toolPtr->lpszText = COMCTL32_Alloc (len * sizeof(WCHAR));
1888                 MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1,
1889                                     toolPtr->lpszText, len);
1890             }
1891         }
1892     }
1893
1894     if(infoPtr->nCurrentTool == -1) return 0;
1895     /* force repaint */
1896     if (infoPtr->bActive)
1897         TOOLTIPS_Show (hwnd, infoPtr);
1898     else if (infoPtr->bTrackActive)
1899         TOOLTIPS_TrackShow (hwnd, infoPtr);
1900
1901     return 0;
1902 }
1903
1904
1905 static LRESULT
1906 TOOLTIPS_UpdateTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1907 {
1908     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1909     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1910     TTTOOL_INFO *toolPtr;
1911     INT nTool;
1912
1913     if (lpToolInfo == NULL)
1914         return 0;
1915     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1916         return FALSE;
1917
1918     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1919     if (nTool == -1)
1920         return 0;
1921
1922     TRACE("tool %d\n", nTool);
1923
1924     toolPtr = &infoPtr->tools[nTool];
1925
1926     /* copy tool text */
1927     toolPtr->hinst  = lpToolInfo->hinst;
1928
1929     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1930         toolPtr->lpszText = lpToolInfo->lpszText;
1931     }
1932     else if (lpToolInfo->lpszText) {
1933         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1934             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1935         else {
1936             if ( (toolPtr->lpszText)  &&
1937                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1938                 COMCTL32_Free (toolPtr->lpszText);
1939                 toolPtr->lpszText = NULL;
1940             }
1941             if (lpToolInfo->lpszText) {
1942                 INT len = lstrlenW (lpToolInfo->lpszText);
1943                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1944                 strcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1945             }
1946         }
1947     }
1948
1949     if(infoPtr->nCurrentTool == -1) return 0;
1950     /* force repaint */
1951     if (infoPtr->bActive)
1952         TOOLTIPS_Show (hwnd, infoPtr);
1953     else if (infoPtr->bTrackActive)
1954         TOOLTIPS_TrackShow (hwnd, infoPtr);
1955
1956     return 0;
1957 }
1958
1959
1960 static LRESULT
1961 TOOLTIPS_WindowFromPoint (HWND hwnd, WPARAM wParam, LPARAM lParam)
1962 {
1963     return WindowFromPoint (*((LPPOINT)lParam));
1964 }
1965
1966
1967
1968 static LRESULT
1969 TOOLTIPS_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1970 {
1971     TOOLTIPS_INFO *infoPtr;
1972     NONCLIENTMETRICSA nclm;
1973     INT nResult;
1974     HWND hParent;
1975
1976     /* allocate memory for info structure */
1977     infoPtr = (TOOLTIPS_INFO *)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO));
1978     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1979
1980     /* initialize info structure */
1981     infoPtr->bActive = TRUE;
1982     infoPtr->bTrackActive = FALSE;
1983     infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
1984     infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
1985
1986     nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1987     SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1988     infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
1989
1990     infoPtr->nMaxTipWidth = -1;
1991     infoPtr->nTool = -1;
1992     infoPtr->nCurrentTool = -1;
1993     infoPtr->nTrackTool = -1;
1994
1995     TOOLTIPS_SetDelayTime(hwnd, TTDT_AUTOMATIC, 0L);
1996
1997     hParent = GetParent(hwnd);
1998     if (hParent) {
1999         nResult = (INT) SendMessageA (hParent, WM_NOTIFYFORMAT,
2000                                   (WPARAM)hwnd, (LPARAM)NF_QUERY);
2001         if (nResult == NFR_ANSI) {
2002             infoPtr->bNotifyUnicode = FALSE;
2003         TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
2004         }
2005         else if (nResult == NFR_UNICODE) {
2006             infoPtr->bNotifyUnicode = TRUE;
2007             TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
2008         }
2009         else {
2010             ERR (" -- WM_NOTIFYFORMAT returns: error!\n");
2011         }
2012     }
2013
2014     SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
2015
2016     return 0;
2017 }
2018
2019
2020 static LRESULT
2021 TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
2022 {
2023     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2024     TTTOOL_INFO *toolPtr;
2025     INT i;
2026
2027     /* free tools */
2028     if (infoPtr->tools) {
2029         for (i = 0; i < infoPtr->uNumTools; i++) {
2030             toolPtr = &infoPtr->tools[i];
2031             if ((toolPtr->hinst) && (toolPtr->lpszText)) {
2032                 if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) &&
2033                      (HIWORD((INT)toolPtr->lpszText) != 0) ) 
2034                 {
2035                     COMCTL32_Free (toolPtr->lpszText);
2036                     toolPtr->lpszText = NULL;
2037                 }
2038             }
2039
2040             /* remove subclassing */
2041         if (toolPtr->uFlags & TTF_SUBCLASS) {
2042             LPTT_SUBCLASS_INFO lpttsi;
2043     
2044             if (toolPtr->uFlags & TTF_IDISHWND) {
2045                 lpttsi = (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
2046                 if (lpttsi) {
2047                     SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
2048                               (LONG)lpttsi->wpOrigProc);
2049                     RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
2050                     COMCTL32_Free (&lpttsi);
2051                 }
2052             }
2053             else {
2054                 lpttsi = (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
2055                 if (lpttsi) {
2056                     SetWindowLongA ((HWND)toolPtr->hwnd, GWL_WNDPROC,
2057                                (LONG)lpttsi->wpOrigProc);
2058                     RemovePropA ((HWND)toolPtr->hwnd, COMCTL32_aSubclass);
2059                     COMCTL32_Free (&lpttsi);
2060                 }
2061             }
2062         }
2063     }
2064         COMCTL32_Free (infoPtr->tools);
2065     }
2066
2067     /* delete font */
2068     DeleteObject (infoPtr->hFont);
2069
2070     /* free tool tips info data */
2071     COMCTL32_Free (infoPtr);
2072     SetWindowLongA(hwnd, 0, 0);
2073     return 0;
2074 }
2075
2076
2077 static LRESULT
2078 TOOLTIPS_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
2079 {
2080     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2081     RECT rect;
2082     HBRUSH hBrush;
2083
2084     hBrush = CreateSolidBrush (infoPtr->clrBk);
2085     GetClientRect (hwnd, &rect);
2086     FillRect ((HDC)wParam, &rect, hBrush);
2087     DeleteObject (hBrush);
2088
2089     return FALSE;
2090 }
2091
2092
2093 static LRESULT
2094 TOOLTIPS_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2095 {
2096     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2097
2098     return infoPtr->hFont;
2099 }
2100
2101
2102 static LRESULT
2103 TOOLTIPS_MouseMessage (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2104 {
2105     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2106
2107     TOOLTIPS_Hide (hwnd, infoPtr);
2108
2109     return 0;
2110 }
2111
2112
2113 static LRESULT
2114 TOOLTIPS_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
2115 {
2116     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2117
2118     dwStyle &= 0x0000FFFF;
2119     dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
2120     SetWindowLongA (hwnd, GWL_STYLE, dwStyle);
2121
2122     return TRUE;
2123 }
2124
2125
2126 static LRESULT
2127 TOOLTIPS_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2128 {
2129     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2130     INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool;
2131
2132     TRACE(" nTool=%d\n", nTool);
2133
2134     if ((nTool > -1) && (nTool < infoPtr->uNumTools)) {
2135         if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) {
2136             TRACE("-- in transparent mode!\n");
2137             return HTTRANSPARENT;
2138         }
2139     }
2140
2141     return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
2142 }
2143
2144
2145 static LRESULT
2146 TOOLTIPS_NotifyFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2147 {
2148     FIXME ("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
2149
2150     return 0;
2151 }
2152
2153
2154 static LRESULT
2155 TOOLTIPS_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
2156 {
2157     HDC hdc;
2158     PAINTSTRUCT ps;
2159
2160     hdc = (wParam == 0) ? BeginPaint (hwnd, &ps) : (HDC)wParam;
2161     TOOLTIPS_Refresh (hwnd, hdc);
2162     if (!wParam)
2163         EndPaint (hwnd, &ps);
2164     return 0;
2165 }
2166
2167
2168 static LRESULT
2169 TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2170 {
2171     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2172
2173     infoPtr->hFont = (HFONT)wParam;
2174
2175     if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
2176         FIXME("full redraw needed!\n");
2177     }
2178
2179     return 0;
2180 }
2181 /******************************************************************
2182  * TOOLTIPS_OnWMGetTextLength
2183  *
2184  * This function is called when the tooltip receive a
2185  * WM_GETTEXTLENGTH message.
2186  * wParam : not used
2187  * lParam : not used
2188  *
2189  * returns the length, in characters, of the tip text
2190  ******************************************************************/
2191 static LRESULT
2192 TOOLTIPS_OnWMGetTextLength(HWND hwnd, WPARAM wParam, LPARAM lParam)
2193 {
2194     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2195     return lstrlenW(infoPtr->szTipText);
2196 }
2197
2198 /******************************************************************
2199  * TOOLTIPS_OnWMGetText
2200  *
2201  * This function is called when the tooltip receive a
2202  * WM_GETTEXT message.
2203  * wParam : specifies the maximum number of characters to be copied
2204  * lParam : is the pointer to the buffer that will receive
2205  *          the tip text
2206  *
2207  * returns the number of characters copied
2208  ******************************************************************/
2209 static LRESULT
2210 TOOLTIPS_OnWMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
2211 {
2212     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2213
2214     if(!infoPtr || !(infoPtr->szTipText))
2215         return 0;
2216
2217     return WideCharToMultiByte(CP_ACP, 0, infoPtr->szTipText, -1,
2218                                (LPSTR)lParam, wParam, NULL, NULL);
2219 }
2220
2221 static LRESULT
2222 TOOLTIPS_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam)
2223 {
2224     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2225     INT nOldTool;
2226
2227     TRACE("timer %d (%x) expired!\n", wParam, hwnd);
2228
2229     switch (wParam) {
2230     case ID_TIMERSHOW:
2231         KillTimer (hwnd, ID_TIMERSHOW);
2232         nOldTool = infoPtr->nTool;
2233         if ((infoPtr->nTool = TOOLTIPS_CheckTool (hwnd, TRUE)) == nOldTool)
2234             TOOLTIPS_Show (hwnd, infoPtr);
2235         break;
2236
2237     case ID_TIMERPOP:
2238         TOOLTIPS_Hide (hwnd, infoPtr);
2239         break;
2240
2241     case ID_TIMERLEAVE:
2242         nOldTool = infoPtr->nTool;
2243         infoPtr->nTool = TOOLTIPS_CheckTool (hwnd, FALSE);
2244         TRACE("tool (%x) %d %d %d\n", hwnd, nOldTool,
2245               infoPtr->nTool, infoPtr->nCurrentTool);
2246         if (infoPtr->nTool != nOldTool) {
2247             if(infoPtr->nTool == -1) { /* Moved out of all tools */
2248                 TOOLTIPS_Hide(hwnd, infoPtr);
2249                 KillTimer(hwnd, ID_TIMERLEAVE);
2250             } else if (nOldTool == -1) { /* Moved from outside */
2251                 ERR("How did this happen?\n");
2252             } else { /* Moved from one to another */
2253                 TOOLTIPS_Hide (hwnd, infoPtr);
2254                 KillTimer(hwnd, ID_TIMERLEAVE);
2255                 if(infoPtr->bActive) {
2256                     SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
2257                     TRACE("timer 1 started!\n");
2258                 }
2259             }
2260         }
2261         break;
2262
2263     default:
2264         ERR("Unknown timer id %d\n", wParam);
2265         break;
2266     }
2267     return 0;
2268 }
2269
2270
2271 static LRESULT
2272 TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
2273 {
2274     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2275     NONCLIENTMETRICSA nclm;
2276
2277     infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
2278     infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
2279
2280     DeleteObject (infoPtr->hFont);
2281     nclm.cbSize = sizeof(NONCLIENTMETRICSA);
2282     SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
2283     infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
2284
2285     return 0;
2286 }
2287
2288
2289 LRESULT CALLBACK
2290 TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2291 {
2292     LPTT_SUBCLASS_INFO lpttsi =
2293         (LPTT_SUBCLASS_INFO)GetPropA (hwnd, COMCTL32_aSubclass);
2294     MSG msg;
2295
2296     switch(uMsg) {
2297     case WM_MOUSEMOVE:
2298     case WM_LBUTTONDOWN:
2299     case WM_LBUTTONUP:
2300     case WM_MBUTTONDOWN:
2301     case WM_MBUTTONUP:
2302     case WM_RBUTTONDOWN:
2303     case WM_RBUTTONUP:
2304         msg.hwnd = hwnd;
2305         msg.message = uMsg;
2306         msg.wParam = wParam;
2307         msg.lParam = lParam;
2308         TOOLTIPS_RelayEvent(lpttsi->hwndToolTip, 0, (LPARAM)&msg);
2309         break;
2310
2311     default:
2312         break;
2313     }
2314     return CallWindowProcA (lpttsi->wpOrigProc, hwnd, uMsg, wParam, lParam);
2315 }
2316
2317
2318 static LRESULT CALLBACK
2319 TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2320 {
2321     TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx\n", hwnd, uMsg, wParam, lParam);
2322     if (!TOOLTIPS_GetInfoPtr(hwnd) && (uMsg != WM_CREATE) && (uMsg != WM_NCCREATE))
2323         return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2324     switch (uMsg)
2325     {
2326         case TTM_ACTIVATE:
2327             return TOOLTIPS_Activate (hwnd, wParam, lParam);
2328
2329         case TTM_ADDTOOLA:
2330             return TOOLTIPS_AddToolA (hwnd, wParam, lParam);
2331
2332         case TTM_ADDTOOLW:
2333             return TOOLTIPS_AddToolW (hwnd, wParam, lParam);
2334
2335         case TTM_DELTOOLA:
2336             return TOOLTIPS_DelToolA (hwnd, wParam, lParam);
2337
2338         case TTM_DELTOOLW:
2339             return TOOLTIPS_DelToolW (hwnd, wParam, lParam);
2340
2341         case TTM_ENUMTOOLSA:
2342             return TOOLTIPS_EnumToolsA (hwnd, wParam, lParam);
2343
2344         case TTM_ENUMTOOLSW:
2345             return TOOLTIPS_EnumToolsW (hwnd, wParam, lParam);
2346
2347         case TTM_GETCURRENTTOOLA:
2348             return TOOLTIPS_GetCurrentToolA (hwnd, wParam, lParam);
2349
2350         case TTM_GETCURRENTTOOLW:
2351             return TOOLTIPS_GetCurrentToolW (hwnd, wParam, lParam);
2352
2353         case TTM_GETDELAYTIME:
2354             return TOOLTIPS_GetDelayTime (hwnd, wParam, lParam);
2355
2356         case TTM_GETMARGIN:
2357             return TOOLTIPS_GetMargin (hwnd, wParam, lParam);
2358
2359         case TTM_GETMAXTIPWIDTH:
2360             return TOOLTIPS_GetMaxTipWidth (hwnd, wParam, lParam);
2361
2362         case TTM_GETTEXTA:
2363             return TOOLTIPS_GetTextA (hwnd, wParam, lParam);
2364
2365         case TTM_GETTEXTW:
2366             return TOOLTIPS_GetTextW (hwnd, wParam, lParam);
2367
2368         case TTM_GETTIPBKCOLOR:
2369             return TOOLTIPS_GetTipBkColor (hwnd, wParam, lParam);
2370
2371         case TTM_GETTIPTEXTCOLOR:
2372             return TOOLTIPS_GetTipTextColor (hwnd, wParam, lParam);
2373
2374         case TTM_GETTOOLCOUNT:
2375             return TOOLTIPS_GetToolCount (hwnd, wParam, lParam);
2376
2377         case TTM_GETTOOLINFOA:
2378             return TOOLTIPS_GetToolInfoA (hwnd, wParam, lParam);
2379
2380         case TTM_GETTOOLINFOW:
2381             return TOOLTIPS_GetToolInfoW (hwnd, wParam, lParam);
2382
2383         case TTM_HITTESTA:
2384             return TOOLTIPS_HitTestA (hwnd, wParam, lParam);
2385
2386         case TTM_HITTESTW:
2387             return TOOLTIPS_HitTestW (hwnd, wParam, lParam);
2388
2389         case TTM_NEWTOOLRECTA:
2390             return TOOLTIPS_NewToolRectA (hwnd, wParam, lParam);
2391
2392         case TTM_NEWTOOLRECTW:
2393             return TOOLTIPS_NewToolRectW (hwnd, wParam, lParam);
2394
2395         case TTM_POP:
2396             return TOOLTIPS_Pop (hwnd, wParam, lParam);
2397
2398         case TTM_RELAYEVENT:
2399             return TOOLTIPS_RelayEvent (hwnd, wParam, lParam);
2400
2401         case TTM_SETDELAYTIME:
2402             return TOOLTIPS_SetDelayTime (hwnd, wParam, lParam);
2403
2404         case TTM_SETMARGIN:
2405             return TOOLTIPS_SetMargin (hwnd, wParam, lParam);
2406
2407         case TTM_SETMAXTIPWIDTH:
2408             return TOOLTIPS_SetMaxTipWidth (hwnd, wParam, lParam);
2409
2410         case TTM_SETTIPBKCOLOR:
2411             return TOOLTIPS_SetTipBkColor (hwnd, wParam, lParam);
2412
2413         case TTM_SETTIPTEXTCOLOR:
2414             return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam);
2415
2416         case TTM_SETTOOLINFOA:
2417             return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
2418
2419         case TTM_SETTOOLINFOW:
2420             return TOOLTIPS_SetToolInfoW (hwnd, wParam, lParam);
2421
2422         case TTM_TRACKACTIVATE:
2423             return TOOLTIPS_TrackActivate (hwnd, wParam, lParam);
2424
2425         case TTM_TRACKPOSITION:
2426             return TOOLTIPS_TrackPosition (hwnd, wParam, lParam);
2427
2428         case TTM_UPDATE:
2429             return TOOLTIPS_Update (hwnd, wParam, lParam);
2430
2431         case TTM_UPDATETIPTEXTA:
2432             return TOOLTIPS_UpdateTipTextA (hwnd, wParam, lParam);
2433
2434         case TTM_UPDATETIPTEXTW:
2435             return TOOLTIPS_UpdateTipTextW (hwnd, wParam, lParam);
2436
2437         case TTM_WINDOWFROMPOINT:
2438             return TOOLTIPS_WindowFromPoint (hwnd, wParam, lParam);
2439
2440
2441         case WM_CREATE:
2442             return TOOLTIPS_Create (hwnd, wParam, lParam);
2443
2444         case WM_DESTROY:
2445             return TOOLTIPS_Destroy (hwnd, wParam, lParam);
2446
2447         case WM_ERASEBKGND:
2448             return TOOLTIPS_EraseBackground (hwnd, wParam, lParam);
2449
2450         case WM_GETFONT:
2451             return TOOLTIPS_GetFont (hwnd, wParam, lParam);
2452
2453         case WM_GETTEXT:
2454             return TOOLTIPS_OnWMGetText (hwnd, wParam, lParam);
2455         
2456         case WM_GETTEXTLENGTH:
2457             return TOOLTIPS_OnWMGetTextLength (hwnd, wParam, lParam);
2458  
2459
2460         case WM_LBUTTONDOWN:
2461         case WM_LBUTTONUP:
2462         case WM_MBUTTONDOWN:
2463         case WM_MBUTTONUP:
2464         case WM_RBUTTONDOWN:
2465         case WM_RBUTTONUP:
2466         case WM_MOUSEMOVE:
2467             return TOOLTIPS_MouseMessage (hwnd, uMsg, wParam, lParam);
2468
2469         case WM_NCCREATE:
2470             return TOOLTIPS_NCCreate (hwnd, wParam, lParam);
2471
2472         case WM_NCHITTEST:
2473             return TOOLTIPS_NCHitTest (hwnd, wParam, lParam);
2474
2475         case WM_NOTIFYFORMAT:
2476             return TOOLTIPS_NotifyFormat (hwnd, wParam, lParam);
2477
2478         case WM_PAINT:
2479             return TOOLTIPS_Paint (hwnd, wParam, lParam);
2480
2481         case WM_SETFONT:
2482             return TOOLTIPS_SetFont (hwnd, wParam, lParam);
2483
2484         case WM_TIMER:
2485             return TOOLTIPS_Timer (hwnd, wParam, lParam);
2486
2487         case WM_WININICHANGE:
2488             return TOOLTIPS_WinIniChange (hwnd, wParam, lParam);
2489
2490         default:
2491             if (uMsg >= WM_USER)
2492                 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2493                      uMsg, wParam, lParam);
2494             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2495     }
2496     return 0;
2497 }
2498
2499
2500 VOID
2501 TOOLTIPS_Register (void)
2502 {
2503     WNDCLASSA wndClass;
2504
2505     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2506     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
2507     wndClass.lpfnWndProc   = (WNDPROC)TOOLTIPS_WindowProc;
2508     wndClass.cbClsExtra    = 0;
2509     wndClass.cbWndExtra    = sizeof(TOOLTIPS_INFO *);
2510     wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
2511     wndClass.hbrBackground = 0;
2512     wndClass.lpszClassName = TOOLTIPS_CLASSA;
2513  
2514     RegisterClassA (&wndClass);
2515 }
2516
2517
2518 VOID
2519 TOOLTIPS_Unregister (void)
2520 {
2521     UnregisterClassA (TOOLTIPS_CLASSA, (HINSTANCE)NULL);
2522 }
2523