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