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