Fixed bug with tooltips stealing focus whenever a tooltip was created,
[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 "winbase.h"
20 #include "commctrl.h"
21 #include "tooltips.h"
22 #include "debug.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 (tooltips, "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 (tooltips, "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.szText) == 0)) {
111                 LoadStringW (ttnmdi.hinst, (UINT)ttnmdi.szText,
112                                infoPtr->szTipText, INFOTIPSIZE);
113                 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
114                     toolPtr->hinst = ttnmdi.hinst;
115                     toolPtr->lpszText = (LPWSTR)ttnmdi.szText;
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 (tooltips, "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 (tooltips, "\"%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 (tooltips, "\"%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 (tooltips, "invalid tool (-1)!\n");
199         return;
200     }
201
202     infoPtr->nCurrentTool = infoPtr->nTool;
203
204     TRACE (tooltips, "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 (tooltips, "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 (tooltips, "\"%s\"\n", debugstr_w(infoPtr->szTipText));
223
224     TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
225     TRACE (tooltips, "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 (tooltips, "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 (tooltips, "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 (tooltips, "invalid tracking tool (-1)!\n");
304         return;
305     }
306
307     TRACE (tooltips, "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 (tooltips, "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 (tooltips, "\"%s\"\n", debugstr_w(infoPtr->szTipText));
326
327     TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size);
328     TRACE (tooltips, "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 (tooltips, "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 (tooltips, "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 (tooltips, "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 (tooltips, "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 (tooltips, "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 (tooltips, "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 (tooltips, "add CALLBACK!\n");
608             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
609         }
610         else {
611             INT len = lstrlenA (lpToolInfo->lpszText);
612             TRACE (tooltips, "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 (tooltips, "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 (tooltips, "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 (tooltips, "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 (tooltips, "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 (tooltips, "add CALLBACK!\n");
709             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
710         }
711         else {
712             INT len = lstrlenW (lpToolInfo->lpszText);
713             TRACE (tooltips, "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 (tooltips, "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 (tooltips, "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 (tooltips, "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             COMCTL32_Free (toolPtr->lpszText);
790     }
791
792     /* remove subclassing */
793     if (toolPtr->uFlags & TTF_SUBCLASS) {
794         if (toolPtr->uFlags & TTF_IDISHWND) {
795             LPTT_SUBCLASS_INFO lpttsi =
796                 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
797             if (lpttsi) {
798                 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
799                                   (LONG)lpttsi->wpOrigProc);
800                 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
801                 COMCTL32_Free (&lpttsi);
802             }
803             else
804                 ERR (tooltips, "Invalid data handle!\n");
805         }
806         else {
807             LPTT_SUBCLASS_INFO lpttsi =
808                 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
809             if (lpttsi) {
810                 if (lpttsi->uRefCount == 1) {
811                     SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
812                                       (LONG)lpttsi->wpOrigProc);
813                     RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
814                     COMCTL32_Free (&lpttsi);
815                 }
816                 else
817                     lpttsi->uRefCount--;
818             }
819             else
820                 ERR (tooltips, "Invalid data handle!\n");
821         }
822     }
823
824     /* delete tool from tool list */
825     if (infoPtr->uNumTools == 1) {
826         COMCTL32_Free (infoPtr->tools);
827         infoPtr->tools = NULL;
828     }
829     else {
830         TTTOOL_INFO *oldTools = infoPtr->tools;
831         infoPtr->tools =
832             COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
833
834         if (nTool > 0)
835             memcpy (&infoPtr->tools[0], &oldTools[0],
836                     nTool * sizeof(TTTOOL_INFO));
837
838         if (nTool < infoPtr->uNumTools - 1)
839             memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
840                     (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
841
842         COMCTL32_Free (oldTools);
843     }
844
845     infoPtr->uNumTools--;
846
847     return 0;
848 }
849
850
851 static LRESULT
852 TOOLTIPS_DelToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
853 {
854     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
855     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
856     TTTOOL_INFO *toolPtr;
857     INT nTool;
858
859     if (lpToolInfo == NULL)
860         return 0;
861     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
862         return 0;
863     if (infoPtr->uNumTools == 0)
864         return 0;
865
866     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
867     if (nTool == -1) return 0;
868
869     TRACE (tooltips, "tool %d\n", nTool);
870
871     /* delete text string */
872     toolPtr = &infoPtr->tools[nTool]; 
873     if ((toolPtr->hinst) && (toolPtr->lpszText)) {
874         if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
875             COMCTL32_Free (toolPtr->lpszText);
876     }
877
878     /* remove subclassing */
879     if (toolPtr->uFlags & TTF_SUBCLASS) {
880         if (toolPtr->uFlags & TTF_IDISHWND) {
881             LPTT_SUBCLASS_INFO lpttsi =
882                 (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
883             if (lpttsi) {
884                 SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
885                                   (LONG)lpttsi->wpOrigProc);
886                 RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
887                 COMCTL32_Free (&lpttsi);
888             }
889             else
890                 ERR (tooltips, "Invalid data handle!\n");
891         }
892         else {
893             LPTT_SUBCLASS_INFO lpttsi =
894                 (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
895             if (lpttsi) {
896                 if (lpttsi->uRefCount == 1) {
897                     SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
898                                       (LONG)lpttsi->wpOrigProc);
899                     RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
900                     COMCTL32_Free (&lpttsi);
901                 }
902                 else
903                     lpttsi->uRefCount--;
904             }
905             else
906                 ERR (tooltips, "Invalid data handle!\n");
907         }
908     }
909
910     /* delete tool from tool list */
911     if (infoPtr->uNumTools == 1) {
912         COMCTL32_Free (infoPtr->tools);
913         infoPtr->tools = NULL;
914     }
915     else {
916         TTTOOL_INFO *oldTools = infoPtr->tools;
917         infoPtr->tools =
918             COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
919
920         if (nTool > 0)
921             memcpy (&infoPtr->tools[0], &oldTools[0],
922                     nTool * sizeof(TTTOOL_INFO));
923
924         if (nTool < infoPtr->uNumTools - 1)
925             memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
926                     (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
927
928         COMCTL32_Free (oldTools);
929     }
930
931     infoPtr->uNumTools--;
932
933     return 0;
934 }
935
936
937 static LRESULT
938 TOOLTIPS_EnumToolsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
939 {
940     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
941     UINT uIndex = (UINT)wParam;
942     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
943     TTTOOL_INFO *toolPtr;
944
945     if (lpToolInfo == NULL)
946         return FALSE;
947     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
948         return FALSE;
949     if (uIndex >= infoPtr->uNumTools)
950         return FALSE;
951
952     TRACE (tooltips, "index=%u\n", uIndex);
953
954     toolPtr = &infoPtr->tools[uIndex];
955
956     /* copy tool data */
957     lpToolInfo->uFlags   = toolPtr->uFlags;
958     lpToolInfo->hwnd     = toolPtr->hwnd;
959     lpToolInfo->uId      = toolPtr->uId;
960     lpToolInfo->rect     = toolPtr->rect;
961     lpToolInfo->hinst    = toolPtr->hinst;
962 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
963     lpToolInfo->lpszText = NULL;  /* FIXME */
964
965     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
966         lpToolInfo->lParam = toolPtr->lParam;
967
968     return TRUE;
969 }
970
971
972 static LRESULT
973 TOOLTIPS_EnumToolsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
974 {
975     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
976     UINT uIndex = (UINT)wParam;
977     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
978     TTTOOL_INFO *toolPtr;
979
980     if (lpToolInfo == NULL)
981         return FALSE;
982     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
983         return FALSE;
984     if (uIndex >= infoPtr->uNumTools)
985         return FALSE;
986
987     TRACE (tooltips, "index=%u\n", uIndex);
988
989     toolPtr = &infoPtr->tools[uIndex];
990
991     /* copy tool data */
992     lpToolInfo->uFlags   = toolPtr->uFlags;
993     lpToolInfo->hwnd     = toolPtr->hwnd;
994     lpToolInfo->uId      = toolPtr->uId;
995     lpToolInfo->rect     = toolPtr->rect;
996     lpToolInfo->hinst    = toolPtr->hinst;
997 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
998     lpToolInfo->lpszText = NULL;  /* FIXME */
999
1000     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1001         lpToolInfo->lParam = toolPtr->lParam;
1002
1003     return TRUE;
1004 }
1005
1006
1007 static LRESULT
1008 TOOLTIPS_GetCurrentToolA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1009 {
1010     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1011     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1012     TTTOOL_INFO *toolPtr;
1013
1014     if (lpToolInfo == NULL)
1015         return FALSE;
1016     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1017         return FALSE;
1018
1019     if (lpToolInfo) {
1020         if (infoPtr->nCurrentTool > -1) {
1021             toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
1022
1023             /* copy tool data */
1024             lpToolInfo->uFlags   = toolPtr->uFlags;
1025             lpToolInfo->rect     = toolPtr->rect;
1026             lpToolInfo->hinst    = toolPtr->hinst;
1027 /*          lpToolInfo->lpszText = toolPtr->lpszText; */
1028             lpToolInfo->lpszText = NULL;  /* FIXME */
1029
1030             if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1031                 lpToolInfo->lParam = toolPtr->lParam;
1032
1033             return TRUE;
1034         }
1035         else
1036             return FALSE;
1037     }
1038     else
1039         return (infoPtr->nCurrentTool != -1);
1040
1041     return FALSE;
1042 }
1043
1044
1045 static LRESULT
1046 TOOLTIPS_GetCurrentToolW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1047 {
1048     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1049     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1050     TTTOOL_INFO *toolPtr;
1051
1052     if (lpToolInfo == NULL)
1053         return FALSE;
1054     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1055         return FALSE;
1056
1057     if (lpToolInfo) {
1058         if (infoPtr->nCurrentTool > -1) {
1059             toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
1060
1061             /* copy tool data */
1062             lpToolInfo->uFlags   = toolPtr->uFlags;
1063             lpToolInfo->rect     = toolPtr->rect;
1064             lpToolInfo->hinst    = toolPtr->hinst;
1065 /*          lpToolInfo->lpszText = toolPtr->lpszText; */
1066             lpToolInfo->lpszText = NULL;  /* FIXME */
1067
1068             if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1069                 lpToolInfo->lParam = toolPtr->lParam;
1070
1071             return TRUE;
1072         }
1073         else
1074             return FALSE;
1075     }
1076     else
1077         return (infoPtr->nCurrentTool != -1);
1078
1079     return FALSE;
1080 }
1081
1082
1083 static LRESULT
1084 TOOLTIPS_GetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1085 {
1086     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1087
1088     switch (wParam) {
1089         case TTDT_AUTOMATIC:
1090             return infoPtr->nAutomaticTime;
1091
1092         case TTDT_RESHOW:
1093             return infoPtr->nReshowTime;
1094
1095         case TTDT_AUTOPOP:
1096             return infoPtr->nAutoPopTime;
1097
1098         case TTDT_INITIAL:
1099             return infoPtr->nInitialTime;
1100     }
1101
1102     return 0;
1103 }
1104
1105
1106 static LRESULT
1107 TOOLTIPS_GetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1108 {
1109     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1110     LPRECT lpRect = (LPRECT)lParam;
1111
1112     lpRect->left   = infoPtr->rcMargin.left;
1113     lpRect->right  = infoPtr->rcMargin.right;
1114     lpRect->bottom = infoPtr->rcMargin.bottom;
1115     lpRect->top    = infoPtr->rcMargin.top;
1116
1117     return 0;
1118 }
1119
1120
1121 __inline__ static LRESULT
1122 TOOLTIPS_GetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1123 {
1124     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1125
1126     return infoPtr->nMaxTipWidth;
1127 }
1128
1129
1130 static LRESULT
1131 TOOLTIPS_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1132 {
1133     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1134     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1135     INT nTool;
1136
1137     if (lpToolInfo == NULL)
1138         return 0;
1139     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1140         return 0;
1141
1142     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1143     if (nTool == -1) return 0;
1144
1145     lstrcpyWtoA (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
1146
1147     return 0;
1148 }
1149
1150
1151 static LRESULT
1152 TOOLTIPS_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1153 {
1154     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1155     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1156     INT nTool;
1157
1158     if (lpToolInfo == NULL)
1159         return 0;
1160     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1161         return 0;
1162
1163     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1164     if (nTool == -1) return 0;
1165
1166     lstrcpyW (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
1167
1168     return 0;
1169 }
1170
1171
1172 __inline__ static LRESULT
1173 TOOLTIPS_GetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1174 {
1175     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1176     return infoPtr->clrBk;
1177 }
1178
1179
1180 __inline__ static LRESULT
1181 TOOLTIPS_GetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1182 {
1183     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1184     return infoPtr->clrText;
1185 }
1186
1187
1188 __inline__ static LRESULT
1189 TOOLTIPS_GetToolCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1190 {
1191     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1192     return infoPtr->uNumTools;
1193 }
1194
1195
1196 static LRESULT
1197 TOOLTIPS_GetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1198 {
1199     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1200     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1201     TTTOOL_INFO *toolPtr;
1202     INT nTool;
1203
1204     if (lpToolInfo == NULL)
1205         return FALSE;
1206     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1207         return FALSE;
1208     if (infoPtr->uNumTools == 0)
1209         return FALSE;
1210
1211     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1212     if (nTool == -1)
1213         return FALSE;
1214
1215     TRACE (tooltips, "tool %d\n", nTool);
1216
1217     toolPtr = &infoPtr->tools[nTool];
1218
1219     /* copy tool data */
1220     lpToolInfo->uFlags   = toolPtr->uFlags;
1221     lpToolInfo->rect     = toolPtr->rect;
1222     lpToolInfo->hinst    = toolPtr->hinst;
1223 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
1224     lpToolInfo->lpszText = NULL;  /* FIXME */
1225
1226     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1227         lpToolInfo->lParam = toolPtr->lParam;
1228
1229     return TRUE;
1230 }
1231
1232
1233 static LRESULT
1234 TOOLTIPS_GetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1235 {
1236     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1237     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1238     TTTOOL_INFO *toolPtr;
1239     INT nTool;
1240
1241     if (lpToolInfo == NULL)
1242         return FALSE;
1243     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1244         return FALSE;
1245     if (infoPtr->uNumTools == 0)
1246         return FALSE;
1247
1248     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1249     if (nTool == -1)
1250         return FALSE;
1251
1252     TRACE (tooltips, "tool %d\n", nTool);
1253
1254     toolPtr = &infoPtr->tools[nTool];
1255
1256     /* copy tool data */
1257     lpToolInfo->uFlags   = toolPtr->uFlags;
1258     lpToolInfo->rect     = toolPtr->rect;
1259     lpToolInfo->hinst    = toolPtr->hinst;
1260 /*    lpToolInfo->lpszText = toolPtr->lpszText; */
1261     lpToolInfo->lpszText = NULL;  /* FIXME */
1262
1263     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1264         lpToolInfo->lParam = toolPtr->lParam;
1265
1266     return TRUE;
1267 }
1268
1269
1270 static LRESULT
1271 TOOLTIPS_HitTestA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1272 {
1273     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1274     LPTTHITTESTINFOA lptthit = (LPTTHITTESTINFOA)lParam;
1275     TTTOOL_INFO *toolPtr;
1276     INT nTool;
1277
1278     if (lptthit == 0)
1279         return FALSE;
1280
1281     nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
1282     if (nTool == -1)
1283         return FALSE;
1284
1285     TRACE (tooltips, "tool %d!\n", nTool);
1286
1287     /* copy tool data */
1288     if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOA)) {
1289         toolPtr = &infoPtr->tools[nTool];
1290
1291         lptthit->ti.uFlags   = toolPtr->uFlags;
1292         lptthit->ti.hwnd     = toolPtr->hwnd;
1293         lptthit->ti.uId      = toolPtr->uId;
1294         lptthit->ti.rect     = toolPtr->rect;
1295         lptthit->ti.hinst    = toolPtr->hinst;
1296 /*      lptthit->ti.lpszText = toolPtr->lpszText; */
1297         lptthit->ti.lpszText = NULL;  /* FIXME */
1298         lptthit->ti.lParam   = toolPtr->lParam;
1299     }
1300
1301     return TRUE;
1302 }
1303
1304
1305 static LRESULT
1306 TOOLTIPS_HitTestW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1307 {
1308     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1309     LPTTHITTESTINFOW lptthit = (LPTTHITTESTINFOW)lParam;
1310     TTTOOL_INFO *toolPtr;
1311     INT nTool;
1312
1313     if (lptthit == 0)
1314         return FALSE;
1315
1316     nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
1317     if (nTool == -1)
1318         return FALSE;
1319
1320     TRACE (tooltips, "tool %d!\n", nTool);
1321
1322     /* copy tool data */
1323     if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOW)) {
1324         toolPtr = &infoPtr->tools[nTool];
1325
1326         lptthit->ti.uFlags   = toolPtr->uFlags;
1327         lptthit->ti.hwnd     = toolPtr->hwnd;
1328         lptthit->ti.uId      = toolPtr->uId;
1329         lptthit->ti.rect     = toolPtr->rect;
1330         lptthit->ti.hinst    = toolPtr->hinst;
1331 /*      lptthit->ti.lpszText = toolPtr->lpszText; */
1332         lptthit->ti.lpszText = NULL;  /* FIXME */
1333         lptthit->ti.lParam   = toolPtr->lParam;
1334     }
1335
1336     return TRUE;
1337 }
1338
1339
1340 static LRESULT
1341 TOOLTIPS_NewToolRectA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1342 {
1343     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1344     LPTTTOOLINFOA lpti = (LPTTTOOLINFOA)lParam;
1345     INT nTool;
1346
1347     if (lpti == NULL)
1348         return 0;
1349     if (lpti->cbSize < TTTOOLINFO_V1_SIZEA)
1350         return FALSE;
1351
1352     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpti);
1353     if (nTool == -1) return 0;
1354
1355     infoPtr->tools[nTool].rect = lpti->rect;
1356
1357     return 0;
1358 }
1359
1360
1361 static LRESULT
1362 TOOLTIPS_NewToolRectW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1363 {
1364     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1365     LPTTTOOLINFOW lpti = (LPTTTOOLINFOW)lParam;
1366     INT nTool;
1367
1368     if (lpti == NULL)
1369         return 0;
1370     if (lpti->cbSize < TTTOOLINFO_V1_SIZEW)
1371         return FALSE;
1372
1373     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpti);
1374     if (nTool == -1) return 0;
1375
1376     infoPtr->tools[nTool].rect = lpti->rect;
1377
1378     return 0;
1379 }
1380
1381
1382 __inline__ static LRESULT
1383 TOOLTIPS_Pop (HWND hwnd, WPARAM wParam, LPARAM lParam)
1384 {
1385     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1386
1387     TOOLTIPS_Hide (hwnd, infoPtr);
1388
1389     return 0;
1390 }
1391
1392
1393 static LRESULT
1394 TOOLTIPS_RelayEvent (HWND hwnd, WPARAM wParam, LPARAM lParam)
1395 {
1396     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1397     LPMSG lpMsg = (LPMSG)lParam;
1398     POINT pt;
1399
1400     if (lParam == 0) {
1401         ERR (tooltips, "lpMsg == NULL!\n");
1402         return 0;
1403     }
1404
1405     switch (lpMsg->message) {
1406         case WM_LBUTTONDOWN:
1407         case WM_LBUTTONUP:
1408         case WM_MBUTTONDOWN:
1409         case WM_MBUTTONUP:
1410         case WM_RBUTTONDOWN:
1411         case WM_RBUTTONUP:
1412             pt = lpMsg->pt;
1413             ScreenToClient (lpMsg->hwnd, &pt);
1414             infoPtr->nOldTool = infoPtr->nTool;
1415             infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
1416             TRACE (tooltips, "tool (%x) %d %d\n",
1417                    hwnd, infoPtr->nOldTool, infoPtr->nTool);
1418             TOOLTIPS_Hide (hwnd, infoPtr);
1419             break;
1420
1421         case WM_MOUSEMOVE:
1422             pt = lpMsg->pt;
1423             ScreenToClient (lpMsg->hwnd, &pt);
1424             infoPtr->nOldTool = infoPtr->nTool;
1425             infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
1426             TRACE (tooltips, "tool (%x) %d %d\n",
1427                    hwnd, infoPtr->nOldTool, infoPtr->nTool);
1428             TRACE (tooltips, "WM_MOUSEMOVE (%04x %ld %ld)\n",
1429                    hwnd, pt.x, pt.y);
1430             if ((infoPtr->bActive) && (infoPtr->nTool != infoPtr->nOldTool)) {
1431                 if (infoPtr->nOldTool == -1) {
1432                     SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0);
1433                     TRACE (tooltips, "timer 1 started!\n");
1434                 }
1435                 else {
1436                     TOOLTIPS_Hide (hwnd, infoPtr);
1437                     SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
1438                     TRACE (tooltips, "timer 2 started!\n");
1439                 }
1440             }
1441             if (infoPtr->nCurrentTool != -1) {
1442                 SetTimer (hwnd, ID_TIMERLEAVE, 100, 0);
1443                 TRACE (tooltips, "timer 3 started!\n");
1444             }
1445             break;
1446     }
1447
1448     return 0;
1449 }
1450
1451
1452 static LRESULT
1453 TOOLTIPS_SetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1454 {
1455     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1456     INT nTime = (INT)LOWORD(lParam);
1457
1458     switch (wParam) {
1459         case TTDT_AUTOMATIC:
1460             if (nTime == 0) {
1461                 infoPtr->nAutomaticTime = 500;
1462                 infoPtr->nReshowTime    = 100;
1463                 infoPtr->nAutoPopTime   = 5000;
1464                 infoPtr->nInitialTime   = 500;
1465             }
1466             else {
1467                 infoPtr->nAutomaticTime = nTime;
1468                 infoPtr->nReshowTime    = nTime / 5;
1469                 infoPtr->nAutoPopTime   = nTime * 10;
1470                 infoPtr->nInitialTime   = nTime;
1471             }
1472             break;
1473
1474         case TTDT_RESHOW:
1475             infoPtr->nReshowTime = nTime;
1476             break;
1477
1478         case TTDT_AUTOPOP:
1479             infoPtr->nAutoPopTime = nTime;
1480             break;
1481
1482         case TTDT_INITIAL:
1483             infoPtr->nInitialTime = nTime;
1484             break;
1485     }
1486
1487     return 0;
1488 }
1489
1490
1491 static LRESULT
1492 TOOLTIPS_SetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1493 {
1494     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1495     LPRECT lpRect = (LPRECT)lParam;
1496
1497     infoPtr->rcMargin.left   = lpRect->left;
1498     infoPtr->rcMargin.right  = lpRect->right;
1499     infoPtr->rcMargin.bottom = lpRect->bottom;
1500     infoPtr->rcMargin.top    = lpRect->top;
1501
1502     return 0;
1503 }
1504
1505
1506 __inline__ static LRESULT
1507 TOOLTIPS_SetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1508 {
1509     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1510     INT nTemp = infoPtr->nMaxTipWidth;
1511
1512     infoPtr->nMaxTipWidth = (INT)lParam;
1513
1514     return nTemp;
1515 }
1516
1517
1518 __inline__ static LRESULT
1519 TOOLTIPS_SetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1520 {
1521     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1522
1523     infoPtr->clrBk = (COLORREF)wParam;
1524
1525     return 0;
1526 }
1527
1528
1529 __inline__ static LRESULT
1530 TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1531 {
1532     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1533
1534     infoPtr->clrText = (COLORREF)wParam;
1535
1536     return 0;
1537 }
1538
1539
1540 static LRESULT
1541 TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1542 {
1543     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1544     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1545     TTTOOL_INFO *toolPtr;
1546     INT nTool;
1547
1548     if (lpToolInfo == NULL)
1549         return 0;
1550     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1551         return 0;
1552
1553     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1554     if (nTool == -1) return 0;
1555
1556     TRACE (tooltips, "tool %d\n", nTool);
1557
1558     toolPtr = &infoPtr->tools[nTool];
1559
1560     /* copy tool data */
1561     toolPtr->uFlags = lpToolInfo->uFlags;
1562     toolPtr->hwnd   = lpToolInfo->hwnd;
1563     toolPtr->uId    = lpToolInfo->uId;
1564     toolPtr->rect   = lpToolInfo->rect;
1565     toolPtr->hinst  = lpToolInfo->hinst;
1566
1567     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1568         TRACE (tooltips, "set string id %x!\n", (INT)lpToolInfo->lpszText);
1569         toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1570     }
1571     else if (lpToolInfo->lpszText) {
1572         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1573             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1574         else {
1575             if (toolPtr->lpszText) {
1576                 COMCTL32_Free (toolPtr->lpszText);
1577                 toolPtr->lpszText = NULL;
1578             }
1579             if (lpToolInfo->lpszText) {
1580                 INT len = lstrlenA (lpToolInfo->lpszText);
1581                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1582                 lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
1583             }
1584         }
1585     }
1586
1587     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1588         toolPtr->lParam = lpToolInfo->lParam;
1589
1590     return 0;
1591 }
1592
1593
1594 static LRESULT
1595 TOOLTIPS_SetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1596 {
1597     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1598     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1599     TTTOOL_INFO *toolPtr;
1600     INT nTool;
1601
1602     if (lpToolInfo == NULL)
1603         return 0;
1604     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1605         return 0;
1606
1607     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1608     if (nTool == -1) return 0;
1609
1610     TRACE (tooltips, "tool %d\n", nTool);
1611
1612     toolPtr = &infoPtr->tools[nTool];
1613
1614     /* copy tool data */
1615     toolPtr->uFlags = lpToolInfo->uFlags;
1616     toolPtr->hwnd   = lpToolInfo->hwnd;
1617     toolPtr->uId    = lpToolInfo->uId;
1618     toolPtr->rect   = lpToolInfo->rect;
1619     toolPtr->hinst  = lpToolInfo->hinst;
1620
1621     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1622         TRACE (tooltips, "set string id %x!\n", (INT)lpToolInfo->lpszText);
1623         toolPtr->lpszText = lpToolInfo->lpszText;
1624     }
1625     else if (lpToolInfo->lpszText) {
1626         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1627             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1628         else {
1629             if (toolPtr->lpszText) {
1630                 COMCTL32_Free (toolPtr->lpszText);
1631                 toolPtr->lpszText = NULL;
1632             }
1633             if (lpToolInfo->lpszText) {
1634                 INT len = lstrlenW (lpToolInfo->lpszText);
1635                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1636                 lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1637             }
1638         }
1639     }
1640
1641     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1642         toolPtr->lParam = lpToolInfo->lParam;
1643
1644     return 0;
1645 }
1646
1647
1648 static LRESULT
1649 TOOLTIPS_TrackActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1650 {
1651     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1652     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1653
1654     if (lpToolInfo == NULL)
1655         return 0;
1656     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1657         return FALSE;
1658
1659     if ((BOOL)wParam) {
1660         /* activate */
1661         infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1662         if (infoPtr->nTrackTool != -1) {
1663             TRACE (tooltips, "activated!\n");
1664             infoPtr->bTrackActive = TRUE;
1665             TOOLTIPS_TrackShow (hwnd, infoPtr);
1666         }
1667     }
1668     else {
1669         /* deactivate */
1670         TOOLTIPS_TrackHide (hwnd, infoPtr);
1671
1672         infoPtr->bTrackActive = FALSE;
1673         infoPtr->nTrackTool = -1;
1674
1675         TRACE (tooltips, "deactivated!\n");
1676     }
1677
1678     return 0;
1679 }
1680
1681
1682 static LRESULT
1683 TOOLTIPS_TrackPosition (HWND hwnd, WPARAM wParam, LPARAM lParam)
1684 {
1685     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1686
1687     infoPtr->xTrackPos = (INT)LOWORD(lParam);
1688     infoPtr->yTrackPos = (INT)HIWORD(lParam);
1689
1690     if (infoPtr->bTrackActive) {
1691         TRACE (tooltips, "[%d %d]\n",
1692                infoPtr->xTrackPos, infoPtr->yTrackPos);
1693
1694         TOOLTIPS_TrackShow (hwnd, infoPtr);
1695     }
1696
1697     return 0;
1698 }
1699
1700
1701 static LRESULT
1702 TOOLTIPS_Update (HWND hwnd, WPARAM wParam, LPARAM lParam)
1703 {
1704     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1705
1706     if (infoPtr->nCurrentTool != -1)
1707         UpdateWindow (hwnd);
1708
1709     return 0;
1710 }
1711
1712
1713 static LRESULT
1714 TOOLTIPS_UpdateTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1715 {
1716     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1717     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1718     TTTOOL_INFO *toolPtr;
1719     INT nTool;
1720
1721     if (lpToolInfo == NULL)
1722         return 0;
1723     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1724         return FALSE;
1725
1726     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1727     if (nTool == -1) return 0;
1728
1729     TRACE (tooltips, "tool %d\n", nTool);
1730
1731     toolPtr = &infoPtr->tools[nTool];
1732
1733     /* copy tool text */
1734     toolPtr->hinst  = lpToolInfo->hinst;
1735
1736     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1737         toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1738     }
1739     else if (lpToolInfo->lpszText) {
1740         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1741             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1742         else {
1743             if (toolPtr->lpszText) {
1744                 COMCTL32_Free (toolPtr->lpszText);
1745                 toolPtr->lpszText = NULL;
1746             }
1747             if (lpToolInfo->lpszText) {
1748                 INT len = lstrlenA (lpToolInfo->lpszText);
1749                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1750                 lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
1751             }
1752         }
1753     }
1754
1755     /* force repaint */
1756     if (infoPtr->bActive)
1757         TOOLTIPS_Show (hwnd, infoPtr);
1758     else if (infoPtr->bTrackActive)
1759         TOOLTIPS_TrackShow (hwnd, infoPtr);
1760
1761     return 0;
1762 }
1763
1764
1765 static LRESULT
1766 TOOLTIPS_UpdateTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1767 {
1768     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1769     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1770     TTTOOL_INFO *toolPtr;
1771     INT nTool;
1772
1773     if (lpToolInfo == NULL)
1774         return 0;
1775     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1776         return FALSE;
1777
1778     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1779     if (nTool == -1)
1780         return 0;
1781
1782     TRACE (tooltips, "tool %d\n", nTool);
1783
1784     toolPtr = &infoPtr->tools[nTool];
1785
1786     /* copy tool text */
1787     toolPtr->hinst  = lpToolInfo->hinst;
1788
1789     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1790         toolPtr->lpszText = lpToolInfo->lpszText;
1791     }
1792     else if (lpToolInfo->lpszText) {
1793         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1794             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1795         else {
1796             if (toolPtr->lpszText) {
1797                 COMCTL32_Free (toolPtr->lpszText);
1798                 toolPtr->lpszText = NULL;
1799             }
1800             if (lpToolInfo->lpszText) {
1801                 INT len = lstrlenW (lpToolInfo->lpszText);
1802                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1803                 lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1804             }
1805         }
1806     }
1807
1808     /* force repaint */
1809     if (infoPtr->bActive)
1810         TOOLTIPS_Show (hwnd, infoPtr);
1811     else if (infoPtr->bTrackActive)
1812         TOOLTIPS_TrackShow (hwnd, infoPtr);
1813
1814     return 0;
1815 }
1816
1817
1818 static LRESULT
1819 TOOLTIPS_WindowFromPoint (HWND hwnd, WPARAM wParam, LPARAM lParam)
1820 {
1821     return WindowFromPoint (*((LPPOINT)lParam));
1822 }
1823
1824
1825
1826 static LRESULT
1827 TOOLTIPS_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1828 {
1829     TOOLTIPS_INFO *infoPtr;
1830     NONCLIENTMETRICSA nclm;
1831     INT nResult;
1832
1833     /* allocate memory for info structure */
1834     infoPtr = (TOOLTIPS_INFO *)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO));
1835     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1836
1837     /* initialize info structure */
1838     infoPtr->bActive = TRUE;
1839     infoPtr->bTrackActive = FALSE;
1840     infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
1841     infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
1842
1843     nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1844     SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1845     infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
1846
1847     infoPtr->nMaxTipWidth = -1;
1848     infoPtr->nTool = -1;
1849     infoPtr->nOldTool = -1;
1850     infoPtr->nCurrentTool = -1;
1851     infoPtr->nTrackTool = -1;
1852
1853     infoPtr->nAutomaticTime = 500;
1854     infoPtr->nReshowTime    = 100;
1855     infoPtr->nAutoPopTime   = 5000;
1856     infoPtr->nInitialTime   = 500;
1857
1858     nResult = (INT) SendMessageA (GetParent (hwnd), WM_NOTIFYFORMAT,
1859                                   (WPARAM)hwnd, (LPARAM)NF_QUERY);
1860     if (nResult == NFR_ANSI)
1861         FIXME (tooltips, " -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
1862     else if (nResult == NFR_UNICODE)
1863         FIXME (tooltips, " -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
1864     else
1865         FIXME (tooltips, " -- WM_NOTIFYFORMAT returns: error!\n");
1866
1867     SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
1868
1869     return 0;
1870 }
1871
1872
1873 static LRESULT
1874 TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1875 {
1876     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1877     TTTOOL_INFO *toolPtr;
1878     INT i;
1879
1880     /* free tools */
1881     if (infoPtr->tools) {
1882         for (i = 0; i < infoPtr->uNumTools; i++) {
1883             toolPtr = &infoPtr->tools[i];
1884             if ((toolPtr->hinst) && (toolPtr->lpszText)) {
1885                 if (toolPtr->lpszText != LPSTR_TEXTCALLBACKW)
1886                     COMCTL32_Free (toolPtr->lpszText);
1887             }
1888
1889             /* remove subclassing */
1890             if (toolPtr->uFlags & TTF_SUBCLASS) {
1891                 LPTT_SUBCLASS_INFO lpttsi;
1892
1893                 if (toolPtr->uFlags & TTF_IDISHWND)
1894                     lpttsi = (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
1895                 else
1896                     lpttsi = (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
1897
1898                 if (lpttsi) {
1899                     SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
1900                                       (LONG)lpttsi->wpOrigProc);
1901                     RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
1902                     COMCTL32_Free (&lpttsi);
1903                 }
1904             }
1905         }
1906         COMCTL32_Free (infoPtr->tools);
1907     }
1908
1909     /* delete font */
1910     DeleteObject (infoPtr->hFont);
1911
1912     /* free tool tips info data */
1913     COMCTL32_Free (infoPtr);
1914
1915     return 0;
1916 }
1917
1918
1919 static LRESULT
1920 TOOLTIPS_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
1921 {
1922     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1923     RECT rect;
1924     HBRUSH hBrush;
1925
1926     hBrush = CreateSolidBrush (infoPtr->clrBk);
1927     GetClientRect (hwnd, &rect);
1928     FillRect ((HDC)wParam, &rect, hBrush);
1929     DeleteObject (hBrush);
1930
1931     return FALSE;
1932 }
1933
1934
1935 static LRESULT
1936 TOOLTIPS_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
1937 {
1938     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1939
1940     return infoPtr->hFont;
1941 }
1942
1943
1944 static LRESULT
1945 TOOLTIPS_MouseMessage (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1946 {
1947     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1948
1949     TOOLTIPS_Hide (hwnd, infoPtr);
1950
1951     return 0;
1952 }
1953
1954
1955 static LRESULT
1956 TOOLTIPS_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1957 {
1958     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1959
1960     dwStyle &= 0x0000FFFF;
1961     dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
1962     SetWindowLongA (hwnd, GWL_STYLE, dwStyle);
1963
1964     return TRUE;
1965 }
1966
1967
1968 static LRESULT
1969 TOOLTIPS_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1970 {
1971     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1972     INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool;
1973
1974     TRACE (tooltips, " nTool=%d\n", nTool);
1975
1976     if ((nTool > -1) && (nTool < infoPtr->uNumTools)) {
1977         if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) {
1978             TRACE (tooltips, "-- in transparent mode!\n");
1979             return HTTRANSPARENT;
1980         }
1981     }
1982
1983     return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
1984 }
1985
1986
1987 static LRESULT
1988 TOOLTIPS_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
1989 {
1990     HDC hdc;
1991     PAINTSTRUCT ps;
1992
1993     hdc = (wParam == 0) ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1994     TOOLTIPS_Refresh (hwnd, hdc);
1995     if (!wParam)
1996         EndPaint (hwnd, &ps);
1997     return 0;
1998 }
1999
2000
2001 static LRESULT
2002 TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2003 {
2004     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2005
2006     infoPtr->hFont = (HFONT)wParam;
2007
2008     if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
2009         FIXME (tooltips, "full redraw needed!\n");
2010     }
2011
2012     return 0;
2013 }
2014
2015
2016 static LRESULT
2017 TOOLTIPS_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam)
2018 {
2019     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2020
2021     TRACE (tooltips, "timer %d (%x) expired!\n", wParam, hwnd);
2022
2023     switch (wParam)
2024     {
2025         case ID_TIMERSHOW:
2026             KillTimer (hwnd, ID_TIMERSHOW);
2027             if (TOOLTIPS_CheckTool (hwnd, TRUE) == infoPtr->nTool)
2028                 TOOLTIPS_Show (hwnd, infoPtr);
2029             break;
2030
2031         case ID_TIMERPOP:
2032             TOOLTIPS_Hide (hwnd, infoPtr);
2033             break;
2034
2035         case ID_TIMERLEAVE:
2036             KillTimer (hwnd, ID_TIMERLEAVE);
2037             if (TOOLTIPS_CheckTool (hwnd, FALSE) == -1) {
2038                 infoPtr->nTool = -1;
2039                 infoPtr->nOldTool = -1;
2040                 TOOLTIPS_Hide (hwnd, infoPtr);
2041             }
2042             break;
2043     }
2044     return 0;
2045 }
2046
2047
2048 static LRESULT
2049 TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
2050 {
2051     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2052     NONCLIENTMETRICSA nclm;
2053
2054     infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
2055     infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
2056
2057     DeleteObject (infoPtr->hFont);
2058     nclm.cbSize = sizeof(NONCLIENTMETRICSA);
2059     SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
2060     infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
2061
2062     return 0;
2063 }
2064
2065
2066 LRESULT CALLBACK
2067 TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2068 {
2069     LPTT_SUBCLASS_INFO lpttsi =
2070         (LPTT_SUBCLASS_INFO)GetPropA (hwnd, COMCTL32_aSubclass);
2071     TOOLTIPS_INFO *infoPtr;
2072     UINT nTool;
2073
2074     switch (uMsg) {
2075         case WM_LBUTTONDOWN:
2076         case WM_LBUTTONUP:
2077         case WM_MBUTTONDOWN:
2078         case WM_MBUTTONUP:
2079         case WM_RBUTTONDOWN:
2080         case WM_RBUTTONUP:
2081             infoPtr = TOOLTIPS_GetInfoPtr(lpttsi->hwndToolTip);
2082                 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
2083
2084                 TRACE (tooltips, "subclassed mouse message %04x\n", uMsg);
2085                 infoPtr->nOldTool = infoPtr->nTool;
2086                 infoPtr->nTool = nTool;
2087             TOOLTIPS_Hide (lpttsi->hwndToolTip, infoPtr);
2088             break;
2089
2090         case WM_MOUSEMOVE:
2091             infoPtr = TOOLTIPS_GetInfoPtr (lpttsi->hwndToolTip);
2092                 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
2093
2094                 TRACE (tooltips, "subclassed WM_MOUSEMOVE\n");
2095                 infoPtr->nOldTool = infoPtr->nTool;
2096                 infoPtr->nTool = nTool;
2097
2098                 if ((infoPtr->bActive) &&
2099                     (infoPtr->nTool != infoPtr->nOldTool)) {
2100                     if (infoPtr->nOldTool == -1) {
2101                     SetTimer (hwnd, ID_TIMERSHOW,
2102                                     infoPtr->nInitialTime, 0);
2103                         TRACE (tooltips, "timer 1 started!\n");
2104                     }
2105                     else {
2106                     TOOLTIPS_Hide (lpttsi->hwndToolTip, infoPtr);
2107                     SetTimer (hwnd, ID_TIMERSHOW,
2108                                 infoPtr->nReshowTime, 0);
2109                         TRACE (tooltips, "timer 2 started!\n");
2110                     }
2111                 }
2112                 if (infoPtr->nCurrentTool != -1) {
2113                 SetTimer (hwnd, ID_TIMERLEAVE, 100, 0);
2114                     TRACE (tooltips, "timer 3 started!\n");
2115                 }
2116             break;
2117     }
2118
2119     return CallWindowProcA (lpttsi->wpOrigProc, hwnd, uMsg, wParam, lParam);
2120 }
2121
2122
2123 LRESULT CALLBACK
2124 TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2125 {
2126     switch (uMsg)
2127     {
2128         case TTM_ACTIVATE:
2129             return TOOLTIPS_Activate (hwnd, wParam, lParam);
2130
2131         case TTM_ADDTOOLA:
2132             return TOOLTIPS_AddToolA (hwnd, wParam, lParam);
2133
2134         case TTM_ADDTOOLW:
2135             return TOOLTIPS_AddToolW (hwnd, wParam, lParam);
2136
2137         case TTM_DELTOOLA:
2138             return TOOLTIPS_DelToolA (hwnd, wParam, lParam);
2139
2140         case TTM_DELTOOLW:
2141             return TOOLTIPS_DelToolW (hwnd, wParam, lParam);
2142
2143         case TTM_ENUMTOOLSA:
2144             return TOOLTIPS_EnumToolsA (hwnd, wParam, lParam);
2145
2146         case TTM_ENUMTOOLSW:
2147             return TOOLTIPS_EnumToolsW (hwnd, wParam, lParam);
2148
2149         case TTM_GETCURRENTTOOLA:
2150             return TOOLTIPS_GetCurrentToolA (hwnd, wParam, lParam);
2151
2152         case TTM_GETCURRENTTOOLW:
2153             return TOOLTIPS_GetCurrentToolW (hwnd, wParam, lParam);
2154
2155         case TTM_GETDELAYTIME:
2156             return TOOLTIPS_GetDelayTime (hwnd, wParam, lParam);
2157
2158         case TTM_GETMARGIN:
2159             return TOOLTIPS_GetMargin (hwnd, wParam, lParam);
2160
2161         case TTM_GETMAXTIPWIDTH:
2162             return TOOLTIPS_GetMaxTipWidth (hwnd, wParam, lParam);
2163
2164         case TTM_GETTEXTA:
2165             return TOOLTIPS_GetTextA (hwnd, wParam, lParam);
2166
2167         case TTM_GETTEXTW:
2168             return TOOLTIPS_GetTextW (hwnd, wParam, lParam);
2169
2170         case TTM_GETTIPBKCOLOR:
2171             return TOOLTIPS_GetTipBkColor (hwnd, wParam, lParam);
2172
2173         case TTM_GETTIPTEXTCOLOR:
2174             return TOOLTIPS_GetTipTextColor (hwnd, wParam, lParam);
2175
2176         case TTM_GETTOOLCOUNT:
2177             return TOOLTIPS_GetToolCount (hwnd, wParam, lParam);
2178
2179         case TTM_GETTOOLINFOA:
2180             return TOOLTIPS_GetToolInfoA (hwnd, wParam, lParam);
2181
2182         case TTM_GETTOOLINFOW:
2183             return TOOLTIPS_GetToolInfoW (hwnd, wParam, lParam);
2184
2185         case TTM_HITTESTA:
2186             return TOOLTIPS_HitTestA (hwnd, wParam, lParam);
2187
2188         case TTM_HITTESTW:
2189             return TOOLTIPS_HitTestW (hwnd, wParam, lParam);
2190
2191         case TTM_NEWTOOLRECTA:
2192             return TOOLTIPS_NewToolRectA (hwnd, wParam, lParam);
2193
2194         case TTM_NEWTOOLRECTW:
2195             return TOOLTIPS_NewToolRectW (hwnd, wParam, lParam);
2196
2197         case TTM_POP:
2198             return TOOLTIPS_Pop (hwnd, wParam, lParam);
2199
2200         case TTM_RELAYEVENT:
2201             return TOOLTIPS_RelayEvent (hwnd, wParam, lParam);
2202
2203         case TTM_SETDELAYTIME:
2204             return TOOLTIPS_SetDelayTime (hwnd, wParam, lParam);
2205
2206         case TTM_SETMARGIN:
2207             return TOOLTIPS_SetMargin (hwnd, wParam, lParam);
2208
2209         case TTM_SETMAXTIPWIDTH:
2210             return TOOLTIPS_SetMaxTipWidth (hwnd, wParam, lParam);
2211
2212         case TTM_SETTIPBKCOLOR:
2213             return TOOLTIPS_SetTipBkColor (hwnd, wParam, lParam);
2214
2215         case TTM_SETTIPTEXTCOLOR:
2216             return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam);
2217
2218         case TTM_SETTOOLINFOA:
2219             return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
2220
2221         case TTM_SETTOOLINFOW:
2222             return TOOLTIPS_SetToolInfoW (hwnd, wParam, lParam);
2223
2224         case TTM_TRACKACTIVATE:
2225             return TOOLTIPS_TrackActivate (hwnd, wParam, lParam);
2226
2227         case TTM_TRACKPOSITION:
2228             return TOOLTIPS_TrackPosition (hwnd, wParam, lParam);
2229
2230         case TTM_UPDATE:
2231             return TOOLTIPS_Update (hwnd, wParam, lParam);
2232
2233         case TTM_UPDATETIPTEXTA:
2234             return TOOLTIPS_UpdateTipTextA (hwnd, wParam, lParam);
2235
2236         case TTM_UPDATETIPTEXTW:
2237             return TOOLTIPS_UpdateTipTextW (hwnd, wParam, lParam);
2238
2239         case TTM_WINDOWFROMPOINT:
2240             return TOOLTIPS_WindowFromPoint (hwnd, wParam, lParam);
2241
2242
2243         case WM_CREATE:
2244             return TOOLTIPS_Create (hwnd, wParam, lParam);
2245
2246         case WM_DESTROY:
2247             return TOOLTIPS_Destroy (hwnd, wParam, lParam);
2248
2249         case WM_ERASEBKGND:
2250             return TOOLTIPS_EraseBackground (hwnd, wParam, lParam);
2251
2252         case WM_GETFONT:
2253             return TOOLTIPS_GetFont (hwnd, wParam, lParam);
2254
2255         case WM_LBUTTONDOWN:
2256         case WM_LBUTTONUP:
2257         case WM_MBUTTONDOWN:
2258         case WM_MBUTTONUP:
2259         case WM_RBUTTONDOWN:
2260         case WM_RBUTTONUP:
2261         case WM_MOUSEMOVE:
2262             return TOOLTIPS_MouseMessage (hwnd, uMsg, wParam, lParam);
2263
2264         case WM_NCCREATE:
2265             return TOOLTIPS_NCCreate (hwnd, wParam, lParam);
2266
2267         case WM_NCHITTEST:
2268             return TOOLTIPS_NCHitTest (hwnd, wParam, lParam);
2269
2270 /*      case WM_NOTIFYFORMAT: */
2271 /*          return TOOLTIPS_NotifyFormat (hwnd, wParam, lParam); */
2272
2273         case WM_PAINT:
2274             return TOOLTIPS_Paint (hwnd, wParam, lParam);
2275
2276         case WM_SETFONT:
2277             return TOOLTIPS_SetFont (hwnd, wParam, lParam);
2278
2279         case WM_TIMER:
2280             return TOOLTIPS_Timer (hwnd, wParam, lParam);
2281
2282         case WM_WININICHANGE:
2283             return TOOLTIPS_WinIniChange (hwnd, wParam, lParam);
2284
2285         default:
2286             if (uMsg >= WM_USER)
2287                 ERR (tooltips, "unknown msg %04x wp=%08x lp=%08lx\n",
2288                      uMsg, wParam, lParam);
2289             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2290     }
2291     return 0;
2292 }
2293
2294
2295 VOID
2296 TOOLTIPS_Register (VOID)
2297 {
2298     WNDCLASSA wndClass;
2299
2300     if (GlobalFindAtomA (TOOLTIPS_CLASSA)) return;
2301
2302     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2303     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
2304     wndClass.lpfnWndProc   = (WNDPROC)TOOLTIPS_WindowProc;
2305     wndClass.cbClsExtra    = 0;
2306     wndClass.cbWndExtra    = sizeof(TOOLTIPS_INFO *);
2307     wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
2308     wndClass.hbrBackground = 0;
2309     wndClass.lpszClassName = TOOLTIPS_CLASSA;
2310  
2311     RegisterClassA (&wndClass);
2312 }
2313
2314
2315 VOID
2316 TOOLTIPS_Unregister (VOID)
2317 {
2318     if (GlobalFindAtomA (TOOLTIPS_CLASSA))
2319         UnregisterClassA (TOOLTIPS_CLASSA, (HINSTANCE)NULL);
2320 }
2321