Added xxx_Unregister() functions to all common controls.
[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 "windows.h"
18 #include "commctrl.h"
19 #include "tooltips.h"
20 #include "win.h"
21 #include "debug.h"
22
23 #define ID_TIMERSHOW   1    /* show delay timer */
24 #define ID_TIMERPOP    2    /* auto pop timer */
25 #define ID_TIMERLEAVE  3    /* tool leave timer */
26
27 /* property name of tooltip window handle */
28 #define TT_SUBCLASS_PROP "CC32SubclassInfo"
29
30 #define TOOLTIPS_GetInfoPtr(wndPtr) ((TOOLTIPS_INFO *)wndPtr->wExtra[0])
31
32
33 LRESULT CALLBACK
34 TOOLTIPS_SubclassProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam);
35
36
37 static VOID
38 TOOLTIPS_Refresh (WND *wndPtr, HDC32 hdc)
39 {
40     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
41     RECT32 rc;
42     INT32 oldBkMode;
43     HFONT32 hOldFont;
44     UINT32 uFlags = DT_EXTERNALLEADING;
45
46     if (infoPtr->nMaxTipWidth > -1)
47         uFlags |= DT_WORDBREAK;
48     if (wndPtr->dwStyle & TTS_NOPREFIX)
49         uFlags |= DT_NOPREFIX;
50     GetClientRect32 (wndPtr->hwndSelf, &rc);
51     rc.left   += (2 + infoPtr->rcMargin.left);
52     rc.top    += (2 + infoPtr->rcMargin.top);
53     rc.right  -= (2 + infoPtr->rcMargin.right);
54     rc.bottom -= (2 + infoPtr->rcMargin.bottom);
55     oldBkMode = SetBkMode32 (hdc, TRANSPARENT);
56     SetTextColor32 (hdc, infoPtr->clrText);
57     hOldFont = SelectObject32 (hdc, infoPtr->hFont);
58     DrawText32A (hdc, infoPtr->szTipText, -1, &rc, uFlags);
59     SelectObject32 (hdc, hOldFont);
60     if (oldBkMode != TRANSPARENT)
61         SetBkMode32 (hdc, oldBkMode);
62 }
63
64
65 static VOID
66 TOOLTIPS_GetTipText (WND *wndPtr, TOOLTIPS_INFO *infoPtr, INT32 nTool)
67 {
68     TTTOOL_INFO *toolPtr = &infoPtr->tools[nTool];
69
70     if ((toolPtr->hinst) && (HIWORD((UINT32)toolPtr->lpszText) == 0)) {
71         TRACE (tooltips, "get res string %x %x\n",
72                toolPtr->hinst, (int)toolPtr->lpszText);
73         LoadString32A (toolPtr->hinst, (UINT32)toolPtr->lpszText,
74                        infoPtr->szTipText, INFOTIPSIZE);
75     }
76     else if (toolPtr->lpszText) {
77         if (toolPtr->lpszText == LPSTR_TEXTCALLBACK32A) {
78             NMTTDISPINFO32A ttnmdi;
79
80             /* fill NMHDR struct */
81             ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFO32A));
82             ttnmdi.hdr.hwndFrom = wndPtr->hwndSelf;
83             ttnmdi.hdr.idFrom = toolPtr->uId;
84             ttnmdi.hdr.code = TTN_GETDISPINFO32A;
85             ttnmdi.lpszText = infoPtr->szTipText;
86             ttnmdi.uFlags = toolPtr->uFlags;
87             ttnmdi.lParam = toolPtr->lParam;
88
89             TRACE (tooltips, "hdr.idFrom = %x\n", ttnmdi.hdr.idFrom);
90             SendMessage32A (toolPtr->hwnd, WM_NOTIFY,
91                             (WPARAM32)toolPtr->uId, (LPARAM)&ttnmdi);
92
93             if ((ttnmdi.hinst) && (HIWORD((UINT32)ttnmdi.szText) == 0)) {
94                 LoadString32A (ttnmdi.hinst, (UINT32)ttnmdi.szText,
95                                infoPtr->szTipText, INFOTIPSIZE);
96                 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
97                     toolPtr->hinst = ttnmdi.hinst;
98                     toolPtr->lpszText = ttnmdi.szText;
99                 }
100             }
101             else if (ttnmdi.szText[0]) {
102                 lstrcpyn32A (infoPtr->szTipText, ttnmdi.szText, 80);
103                 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
104                     INT32 len = lstrlen32A (ttnmdi.szText) + 1;
105                     toolPtr->hinst = 0;
106                     toolPtr->lpszText = COMCTL32_Alloc (len);
107                     lstrcpy32A (toolPtr->lpszText, ttnmdi.szText);
108                 }
109             }
110             else if (ttnmdi.lpszText == 0) {
111                 /* no text available */
112                 infoPtr->szTipText[0] = '\0';
113             }
114             else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACK32A) {
115                 if (ttnmdi.lpszText != infoPtr->szTipText)
116                     lstrcpyn32A (infoPtr->szTipText, ttnmdi.lpszText,
117                                  INFOTIPSIZE);
118                 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
119                     INT32 len = lstrlen32A (ttnmdi.lpszText) + 1;
120                     toolPtr->hinst = 0;
121                     toolPtr->lpszText = COMCTL32_Alloc (len);
122                     lstrcpy32A (toolPtr->lpszText, ttnmdi.lpszText);
123                 }
124             }
125             else {
126                 ERR (tooltips, "recursive text callback!\n");
127                 infoPtr->szTipText[0] = '\0';
128             }
129         }
130         else
131             lstrcpyn32A (infoPtr->szTipText, toolPtr->lpszText, INFOTIPSIZE);
132     }
133     else
134         /* no text available */
135         infoPtr->szTipText[0] = '\0';
136
137     TRACE (tooltips, "\"%s\"\n", infoPtr->szTipText);
138 }
139
140
141 static VOID
142 TOOLTIPS_CalcTipSize (WND *wndPtr, TOOLTIPS_INFO *infoPtr, LPSIZE32 lpSize)
143 {
144     HDC32 hdc;
145     HFONT32 hOldFont;
146     UINT32 uFlags = DT_EXTERNALLEADING | DT_CALCRECT;
147     RECT32 rc = {0, 0, 0, 0};
148
149     if (infoPtr->nMaxTipWidth > -1) {
150         rc.right = infoPtr->nMaxTipWidth;
151         uFlags |= DT_WORDBREAK;
152     }
153     if (wndPtr->dwStyle & TTS_NOPREFIX)
154         uFlags |= DT_NOPREFIX;
155     TRACE (tooltips, "\"%s\"\n", infoPtr->szTipText);
156
157     hdc = GetDC32 (wndPtr->hwndSelf);
158     hOldFont = SelectObject32 (hdc, infoPtr->hFont);
159     DrawText32A (hdc, infoPtr->szTipText, -1, &rc, uFlags);
160     SelectObject32 (hdc, hOldFont);
161     ReleaseDC32 (wndPtr->hwndSelf, hdc);
162
163     lpSize->cx = rc.right - rc.left + 4 + 
164                  infoPtr->rcMargin.left + infoPtr->rcMargin.right;
165     lpSize->cy = rc.bottom - rc.top + 4 +
166                  infoPtr->rcMargin.bottom + infoPtr->rcMargin.top;
167 }
168
169
170 static VOID
171 TOOLTIPS_Show (WND *wndPtr, TOOLTIPS_INFO *infoPtr)
172 {
173     TTTOOL_INFO *toolPtr;
174     RECT32 rect;
175     SIZE32 size;
176     NMHDR hdr;
177
178     if (infoPtr->nTool == -1) {
179         TRACE (tooltips, "invalid tool (-1)!\n");
180         return;
181     }
182
183     infoPtr->nCurrentTool = infoPtr->nTool;
184
185     TRACE (tooltips, "Show tooltip pre %d!\n", infoPtr->nTool);
186
187     TOOLTIPS_GetTipText (wndPtr, infoPtr, infoPtr->nCurrentTool);
188
189     if (infoPtr->szTipText[0] == '\0') {
190         infoPtr->nCurrentTool = -1;
191         return;
192     }
193
194     TRACE (tooltips, "Show tooltip %d!\n", infoPtr->nCurrentTool);
195     toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
196
197     hdr.hwndFrom = wndPtr->hwndSelf;
198     hdr.idFrom = toolPtr->uId;
199     hdr.code = TTN_SHOW;
200     SendMessage32A (toolPtr->hwnd, WM_NOTIFY,
201                     (WPARAM32)toolPtr->uId, (LPARAM)&hdr);
202
203     TRACE (tooltips, "\"%s\"\n", infoPtr->szTipText);
204
205     TOOLTIPS_CalcTipSize (wndPtr, infoPtr, &size);
206     TRACE (tooltips, "size %d - %d\n", size.cx, size.cy);
207
208     if (toolPtr->uFlags & TTF_CENTERTIP) {
209         RECT32 rc;
210
211         if (toolPtr->uFlags & TTF_IDISHWND)
212             GetWindowRect32 ((HWND32)toolPtr->uId, &rc);
213         else {
214             rc = toolPtr->rect;
215             MapWindowPoints32 (toolPtr->hwnd, (HWND32)0, (LPPOINT32)&rc, 2);
216         }
217         rect.left = (rc.left + rc.right - size.cx) / 2;
218         rect.top  = rc.bottom + 2;
219     }
220     else {
221         GetCursorPos32 ((LPPOINT32)&rect);
222         rect.top += 20;
223     }
224
225     /* FIXME: check position */
226
227     TRACE (tooltips, "pos %d - %d\n", rect.left, rect.top);
228
229     rect.right = rect.left + size.cx;
230     rect.bottom = rect.top + size.cy;
231
232     AdjustWindowRectEx32 (&rect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle);
233
234     SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, rect.left, rect.top,
235                     rect.right - rect.left, rect.bottom - rect.top,
236                     SWP_SHOWWINDOW);
237
238     SetTimer32 (wndPtr->hwndSelf, ID_TIMERPOP, infoPtr->nAutoPopTime, 0);
239 }
240
241
242 static VOID
243 TOOLTIPS_Hide (WND *wndPtr, TOOLTIPS_INFO *infoPtr)
244 {
245     TTTOOL_INFO *toolPtr;
246     NMHDR hdr;
247
248     if (infoPtr->nCurrentTool == -1)
249         return;
250
251     toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
252     TRACE (tooltips, "Hide tooltip %d!\n", infoPtr->nCurrentTool);
253     KillTimer32 (wndPtr->hwndSelf, ID_TIMERPOP);
254
255     hdr.hwndFrom = wndPtr->hwndSelf;
256     hdr.idFrom = toolPtr->uId;
257     hdr.code = TTN_POP;
258     SendMessage32A (toolPtr->hwnd, WM_NOTIFY,
259                     (WPARAM32)toolPtr->uId, (LPARAM)&hdr);
260
261     infoPtr->nCurrentTool = -1;
262
263     SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0,
264                     SWP_NOZORDER | SWP_HIDEWINDOW);
265 }
266
267
268 static VOID
269 TOOLTIPS_TrackShow (WND *wndPtr, TOOLTIPS_INFO *infoPtr)
270 {
271     TTTOOL_INFO *toolPtr;
272     RECT32 rect;
273     SIZE32 size;
274     NMHDR hdr;
275
276     if (infoPtr->nTrackTool == -1) {
277         TRACE (tooltips, "invalid tracking tool (-1)!\n");
278         return;
279     }
280
281     TRACE (tooltips, "show tracking tooltip pre %d!\n", infoPtr->nTrackTool);
282
283     TOOLTIPS_GetTipText (wndPtr, infoPtr, infoPtr->nTrackTool);
284
285     if (infoPtr->szTipText[0] == '\0') {
286         infoPtr->nTrackTool = -1;
287         return;
288     }
289
290     TRACE (tooltips, "show tracking tooltip %d!\n", infoPtr->nTrackTool);
291     toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
292
293     hdr.hwndFrom = wndPtr->hwndSelf;
294     hdr.idFrom = toolPtr->uId;
295     hdr.code = TTN_SHOW;
296     SendMessage32A (toolPtr->hwnd, WM_NOTIFY,
297                     (WPARAM32)toolPtr->uId, (LPARAM)&hdr);
298
299     TRACE (tooltips, "\"%s\"\n", infoPtr->szTipText);
300
301     TOOLTIPS_CalcTipSize (wndPtr, infoPtr, &size);
302     TRACE (tooltips, "size %d - %d\n", size.cx, size.cy);
303
304     if (toolPtr->uFlags & TTF_ABSOLUTE) {
305         rect.left = infoPtr->xTrackPos;
306         rect.top  = infoPtr->yTrackPos;
307
308         if (toolPtr->uFlags & TTF_CENTERTIP) {
309             rect.left -= (size.cx / 2);
310             rect.top  -= (size.cy / 2);
311         }
312     }
313     else {
314         RECT32 rcTool;
315
316         if (toolPtr->uFlags & TTF_IDISHWND)
317             GetWindowRect32 ((HWND32)toolPtr->uId, &rcTool);
318         else {
319             rcTool = toolPtr->rect;
320             MapWindowPoints32 (toolPtr->hwnd, (HWND32)0, (LPPOINT32)&rcTool, 2);
321         }
322
323         GetCursorPos32 ((LPPOINT32)&rect);
324         rect.top += 20;
325
326         if (toolPtr->uFlags & TTF_CENTERTIP) {
327             rect.left -= (size.cx / 2);
328             rect.top  -= (size.cy / 2);
329         }
330
331         /* smart placement */
332         if ((rect.left + size.cx > rcTool.left) && (rect.left < rcTool.right) &&
333             (rect.top + size.cy > rcTool.top) && (rect.top < rcTool.bottom))
334             rect.left = rcTool.right;
335     }
336
337     TRACE (tooltips, "pos %d - %d\n", rect.left, rect.top);
338
339     rect.right = rect.left + size.cx;
340     rect.bottom = rect.top + size.cy;
341
342     AdjustWindowRectEx32 (&rect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle);
343
344     SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, rect.left, rect.top,
345                     rect.right - rect.left, rect.bottom - rect.top,
346                     SWP_SHOWWINDOW);
347 }
348
349
350 static VOID
351 TOOLTIPS_TrackHide (WND *wndPtr, TOOLTIPS_INFO *infoPtr)
352 {
353     TTTOOL_INFO *toolPtr;
354     NMHDR hdr;
355
356     if (infoPtr->nTrackTool == -1)
357         return;
358
359     toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
360     TRACE (tooltips, "hide tracking tooltip %d!\n", infoPtr->nTrackTool);
361
362     hdr.hwndFrom = wndPtr->hwndSelf;
363     hdr.idFrom = toolPtr->uId;
364     hdr.code = TTN_POP;
365     SendMessage32A (toolPtr->hwnd, WM_NOTIFY,
366                     (WPARAM32)toolPtr->uId, (LPARAM)&hdr);
367
368     SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0,
369                     SWP_NOZORDER | SWP_HIDEWINDOW);
370 }
371
372
373 static INT32
374 TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFO32A lpToolInfo)
375 {
376     TTTOOL_INFO *toolPtr;
377     INT32 nTool;
378
379     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
380         toolPtr = &infoPtr->tools[nTool];
381
382         if (!(toolPtr->uFlags & TTF_IDISHWND) && 
383             (lpToolInfo->hwnd == toolPtr->hwnd) &&
384             (lpToolInfo->uId == toolPtr->uId))
385             return nTool;
386     }
387
388     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
389         toolPtr = &infoPtr->tools[nTool];
390
391         if ((toolPtr->uFlags & TTF_IDISHWND) &&
392             (lpToolInfo->uId == toolPtr->uId))
393             return nTool;
394     }
395
396     return -1;
397 }
398
399
400 static INT32
401 TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO *infoPtr, HWND32 hwnd, LPPOINT32 lpPt)
402 {
403     TTTOOL_INFO *toolPtr;
404     INT32  nTool;
405
406     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
407         toolPtr = &infoPtr->tools[nTool];
408
409         if (!(toolPtr->uFlags & TTF_IDISHWND)) {
410             if (hwnd != toolPtr->hwnd)
411                 continue;
412             if (!PtInRect32 (&toolPtr->rect, *lpPt))
413                 continue;
414             return nTool;
415         }
416     }
417
418     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
419         toolPtr = &infoPtr->tools[nTool];
420
421         if (toolPtr->uFlags & TTF_IDISHWND) {
422             if ((HWND32)toolPtr->uId == hwnd)
423                 return nTool;
424         }
425     }
426
427     return -1;
428 }
429
430
431 static INT32
432 TOOLTIPS_GetToolFromMessage (TOOLTIPS_INFO *infoPtr, HWND32 hwndTool)
433 {
434     DWORD   dwPos;
435     POINT32 pt;
436
437     dwPos = GetMessagePos ();
438     pt.x = (INT32)LOWORD(dwPos);
439     pt.y = (INT32)HIWORD(dwPos);
440     ScreenToClient32 (hwndTool, &pt);
441
442     return TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
443 }
444
445
446 static BOOL32
447 TOOLTIPS_IsWindowActive (HWND32 hwnd)
448 {
449     HWND32 hwndActive = GetActiveWindow32 ();
450     if (!hwndActive)
451         return FALSE;
452     if (hwndActive == hwnd)
453         return TRUE;
454     return IsChild32 (hwndActive, hwnd);
455 }
456
457
458 static INT32
459 TOOLTIPS_CheckTool (WND *wndPtr, BOOL32 bShowTest)
460 {
461     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
462     POINT32 pt;
463     HWND32 hwndTool;
464     INT32 nTool;
465
466     GetCursorPos32 (&pt);
467     hwndTool =
468         SendMessage32A (wndPtr->hwndSelf, TTM_WINDOWFROMPOINT, 0, (LPARAM)&pt);
469     if (hwndTool == 0)
470         return -1;
471
472     ScreenToClient32 (hwndTool, &pt);
473     nTool = TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
474     if (nTool == -1)
475         return -1;
476
477     if (!(wndPtr->dwStyle & TTS_ALWAYSTIP) && bShowTest) {
478         if (!TOOLTIPS_IsWindowActive (wndPtr->owner->hwndSelf))
479             return -1;
480     }
481
482     TRACE (tooltips, "tool %d\n", nTool);
483
484     return nTool;
485 }
486
487
488 static LRESULT
489 TOOLTIPS_Activate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
490 {
491     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
492
493     infoPtr->bActive = (BOOL32)wParam;
494
495     if (infoPtr->bActive)
496         TRACE (tooltips, "activate!\n");
497
498     if (!(infoPtr->bActive) && (infoPtr->nCurrentTool != -1)) 
499         TOOLTIPS_Hide (wndPtr, infoPtr);
500
501     return 0;
502 }
503
504
505 static LRESULT
506 TOOLTIPS_AddTool32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
507 {
508     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
509     LPTTTOOLINFO32A lpToolInfo = (LPTTTOOLINFO32A)lParam;
510     TTTOOL_INFO *toolPtr;
511
512     if (lpToolInfo == NULL)
513         return FALSE;
514     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZE32A)
515         return FALSE;
516
517     TRACE (tooltips, "add tool (%x) %x %d%s!\n",
518            wndPtr->hwndSelf, lpToolInfo->hwnd, lpToolInfo->uId,
519            (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
520
521     if (infoPtr->uNumTools == 0) {
522         infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
523         toolPtr = infoPtr->tools;
524     }
525     else {
526         TTTOOL_INFO *oldTools = infoPtr->tools;
527         infoPtr->tools =
528             COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
529         memcpy (infoPtr->tools, oldTools,
530                 infoPtr->uNumTools * sizeof(TTTOOL_INFO));
531         COMCTL32_Free (oldTools);
532         toolPtr = &infoPtr->tools[infoPtr->uNumTools];
533     }
534
535     infoPtr->uNumTools++;
536
537     /* copy tool data */
538     toolPtr->uFlags = lpToolInfo->uFlags;
539     toolPtr->hwnd   = lpToolInfo->hwnd;
540     toolPtr->uId    = lpToolInfo->uId;
541     toolPtr->rect   = lpToolInfo->rect;
542     toolPtr->hinst  = lpToolInfo->hinst;
543
544     if ((lpToolInfo->hinst) && (HIWORD((INT32)lpToolInfo->lpszText) == 0)) {
545         TRACE (tooltips, "add string id %x!\n", (int)lpToolInfo->lpszText);
546         toolPtr->lpszText = lpToolInfo->lpszText;
547     }
548     else if (lpToolInfo->lpszText) {
549         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACK32A) {
550             TRACE (tooltips, "add CALLBACK!\n");
551             toolPtr->lpszText = lpToolInfo->lpszText;
552         }
553         else {
554             INT32 len = lstrlen32A (lpToolInfo->lpszText);
555             TRACE (tooltips, "add text \"%s\"!\n", lpToolInfo->lpszText);
556             toolPtr->lpszText = COMCTL32_Alloc (len + 1);
557             lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
558         }
559     }
560
561     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFO32A))
562         toolPtr->lParam = lpToolInfo->lParam;
563
564     /* install subclassing hook */
565     if (toolPtr->uFlags & TTF_SUBCLASS) {
566         if (toolPtr->uFlags & TTF_IDISHWND) {
567             LPTT_SUBCLASS_INFO lpttsi =
568                 (LPTT_SUBCLASS_INFO)GetProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
569             if (lpttsi == NULL) {
570                 lpttsi =
571                     (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
572                 lpttsi->wpOrigProc = 
573                     (WNDPROC32)SetWindowLong32A ((HWND32)toolPtr->uId,
574                     GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
575                 lpttsi->hwndToolTip = wndPtr->hwndSelf;
576                 lpttsi->uRefCount++;
577                 SetProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP,
578                             (HANDLE32)lpttsi);
579             }
580             else
581                 WARN (tooltips, "A window tool must only be listed once!\n");
582         }
583         else {
584             LPTT_SUBCLASS_INFO lpttsi =
585                 (LPTT_SUBCLASS_INFO)GetProp32A (toolPtr->hwnd, TT_SUBCLASS_PROP);
586             if (lpttsi == NULL) {
587                 lpttsi =
588                     (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
589                 lpttsi->wpOrigProc = 
590                     (WNDPROC32)SetWindowLong32A (toolPtr->hwnd,
591                     GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
592                 lpttsi->hwndToolTip = wndPtr->hwndSelf;
593                 lpttsi->uRefCount++;
594                 SetProp32A (toolPtr->hwnd, TT_SUBCLASS_PROP, (HANDLE32)lpttsi);
595             }
596             else
597                 lpttsi->uRefCount++;
598         }
599         TRACE (tooltips, "subclassing installed!\n");
600     }
601
602     return TRUE;
603 }
604
605
606 // << TOOLTIPS_AddTool32W >>
607
608
609 static LRESULT
610 TOOLTIPS_DelTool32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
611 {
612     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
613     LPTTTOOLINFO32A lpToolInfo = (LPTTTOOLINFO32A)lParam;
614     TTTOOL_INFO *toolPtr;
615     INT32 nTool;
616
617     if (lpToolInfo == NULL)
618         return 0;
619     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZE32A)
620         return 0;
621     if (infoPtr->uNumTools == 0)
622         return 0;
623
624     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
625     if (nTool == -1) return 0;
626
627     TRACE (tooltips, "tool %d\n", nTool);
628
629     /* delete text string */
630     toolPtr = &infoPtr->tools[nTool]; 
631     if ((toolPtr->hinst) && (toolPtr->lpszText)) {
632         if (toolPtr->lpszText != LPSTR_TEXTCALLBACK32A)
633             COMCTL32_Free (toolPtr->lpszText);
634     }
635
636     /* remove subclassing */
637     if (toolPtr->uFlags & TTF_SUBCLASS) {
638         if (toolPtr->uFlags & TTF_IDISHWND) {
639             LPTT_SUBCLASS_INFO lpttsi =
640                 (LPTT_SUBCLASS_INFO)GetProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
641             if (lpttsi) {
642                 SetWindowLong32A ((HWND32)toolPtr->uId, GWL_WNDPROC,
643                                   (LONG)lpttsi->wpOrigProc);
644                 RemoveProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
645                 COMCTL32_Free (&lpttsi);
646             }
647             else
648                 ERR (tooltips, "Invalid data handle!\n");
649         }
650         else {
651             LPTT_SUBCLASS_INFO lpttsi =
652                 (LPTT_SUBCLASS_INFO)GetProp32A (toolPtr->hwnd, TT_SUBCLASS_PROP);
653             if (lpttsi) {
654                 if (lpttsi->uRefCount == 1) {
655                     SetWindowLong32A ((HWND32)toolPtr->uId, GWL_WNDPROC,
656                                       (LONG)lpttsi->wpOrigProc);
657                     RemoveProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
658                     COMCTL32_Free (&lpttsi);
659                 }
660                 else
661                     lpttsi->uRefCount--;
662             }
663             else
664                 ERR (tooltips, "Invalid data handle!\n");
665         }
666     }
667
668     /* delete tool from tool list */
669     if (infoPtr->uNumTools == 1) {
670         COMCTL32_Free (infoPtr->tools);
671         infoPtr->tools = NULL;
672     }
673     else {
674         TTTOOL_INFO *oldTools = infoPtr->tools;
675         infoPtr->tools =
676             COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
677
678         if (nTool > 0)
679             memcpy (&infoPtr->tools[0], &oldTools[0],
680                     nTool * sizeof(TTTOOL_INFO));
681
682         if (nTool < infoPtr->uNumTools - 1)
683             memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
684                     (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
685
686         COMCTL32_Free (oldTools);
687     }
688
689     infoPtr->uNumTools--;
690
691     return 0;
692 }
693
694
695 // << TOOLTIPS_DelTool32W >>
696
697
698 static LRESULT
699 TOOLTIPS_EnumTools32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
700 {
701     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
702     UINT32 uIndex = (UINT32)wParam;
703     LPTTTOOLINFO32A lpToolInfo = (LPTTTOOLINFO32A)lParam;
704     TTTOOL_INFO *toolPtr;
705
706     if (lpToolInfo == NULL)
707         return FALSE;
708     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZE32A)
709         return FALSE;
710     if (uIndex >= infoPtr->uNumTools)
711         return FALSE;
712
713     TRACE (tooltips, "index=%u\n", uIndex);
714
715     toolPtr = &infoPtr->tools[uIndex];
716
717     /* copy tool data */
718     lpToolInfo->uFlags   = toolPtr->uFlags;
719     lpToolInfo->hwnd     = toolPtr->hwnd;
720     lpToolInfo->uId      = toolPtr->uId;
721     lpToolInfo->rect     = toolPtr->rect;
722     lpToolInfo->hinst    = toolPtr->hinst;
723     lpToolInfo->lpszText = toolPtr->lpszText;
724
725     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFO32A))
726         lpToolInfo->lParam = toolPtr->lParam;
727
728     return TRUE;
729 }
730
731
732 // << TOOLTIPS_EnumTools32W >>
733
734
735 static LRESULT
736 TOOLTIPS_GetCurrentTool32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
737 {
738     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
739     LPTTTOOLINFO32A lpToolInfo = (LPTTTOOLINFO32A)lParam;
740     TTTOOL_INFO *toolPtr;
741
742     if (lpToolInfo == NULL)
743         return FALSE;
744     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZE32A)
745         return FALSE;
746
747     if (lpToolInfo) {
748         if (infoPtr->nCurrentTool > -1) {
749             toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
750
751             /* copy tool data */
752             lpToolInfo->uFlags   = toolPtr->uFlags;
753             lpToolInfo->rect     = toolPtr->rect;
754             lpToolInfo->hinst    = toolPtr->hinst;
755             lpToolInfo->lpszText = toolPtr->lpszText;
756
757             if (lpToolInfo->cbSize >= sizeof(TTTOOLINFO32A))
758                 lpToolInfo->lParam = toolPtr->lParam;
759
760             return TRUE;
761         }
762         else
763             return FALSE;
764     }
765     else
766         return (infoPtr->nCurrentTool != -1);
767
768     return FALSE;
769 }
770
771
772 // << TOOLTIPS_GetCurrentTool32W >>
773
774
775 static LRESULT
776 TOOLTIPS_GetDelayTime (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
777 {
778     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
779
780     switch (wParam) {
781         case TTDT_AUTOMATIC:
782             return infoPtr->nAutomaticTime;
783
784         case TTDT_RESHOW:
785             return infoPtr->nReshowTime;
786
787         case TTDT_AUTOPOP:
788             return infoPtr->nAutoPopTime;
789
790         case TTDT_INITIAL:
791             return infoPtr->nInitialTime;
792     }
793
794     return 0;
795 }
796
797
798 static LRESULT
799 TOOLTIPS_GetMargin (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
800 {
801     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
802     LPRECT32 lpRect = (LPRECT32)lParam;
803
804     lpRect->left   = infoPtr->rcMargin.left;
805     lpRect->right  = infoPtr->rcMargin.right;
806     lpRect->bottom = infoPtr->rcMargin.bottom;
807     lpRect->top    = infoPtr->rcMargin.top;
808
809     return 0;
810 }
811
812
813 __inline__ static LRESULT
814 TOOLTIPS_GetMaxTipWidth (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
815 {
816     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
817
818     return infoPtr->nMaxTipWidth;
819 }
820
821
822 static LRESULT
823 TOOLTIPS_GetText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
824 {
825     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
826     LPTTTOOLINFO32A lpToolInfo = (LPTTTOOLINFO32A)lParam;
827     INT32 nTool;
828
829     if (lpToolInfo == NULL)
830         return 0;
831     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZE32A)
832         return 0;
833
834     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
835     if (nTool == -1) return 0;
836
837     lstrcpy32A (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText);
838
839     return 0;
840 }
841
842
843 // << TOOLTIPS_GetText32W >>
844
845
846 __inline__ static LRESULT
847 TOOLTIPS_GetTipBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
848 {
849     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
850     return infoPtr->clrBk;
851 }
852
853
854 __inline__ static LRESULT
855 TOOLTIPS_GetTipTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
856 {
857     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
858     return infoPtr->clrText;
859 }
860
861
862 __inline__ static LRESULT
863 TOOLTIPS_GetToolCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
864 {
865     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
866     return infoPtr->uNumTools;
867 }
868
869
870 static LRESULT
871 TOOLTIPS_GetToolInfo32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
872 {
873     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
874     LPTTTOOLINFO32A lpToolInfo = (LPTTTOOLINFO32A)lParam;
875     TTTOOL_INFO *toolPtr;
876     INT32 nTool;
877
878     if (lpToolInfo == NULL)
879         return FALSE;
880     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZE32A)
881         return FALSE;
882     if (infoPtr->uNumTools == 0)
883         return FALSE;
884
885     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
886     if (nTool == -1) return FALSE;
887
888     TRACE (tooltips, "tool %d\n", nTool);
889
890     toolPtr = &infoPtr->tools[nTool];
891
892     /* copy tool data */
893     lpToolInfo->uFlags   = toolPtr->uFlags;
894     lpToolInfo->rect     = toolPtr->rect;
895     lpToolInfo->hinst    = toolPtr->hinst;
896     lpToolInfo->lpszText = toolPtr->lpszText;
897
898     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFO32A))
899         lpToolInfo->lParam = toolPtr->lParam;
900
901     return TRUE;
902 }
903
904
905 // << TOOLTIPS_GetToolInfo32W >>
906
907
908 static LRESULT
909 TOOLTIPS_HitTest32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
910 {
911     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
912     LPTTHITTESTINFO32A lptthit = (LPTTHITTESTINFO32A)lParam;
913     TTTOOL_INFO *toolPtr;
914     INT32 nTool;
915
916     if (lptthit == 0)
917         return FALSE;
918
919     nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt);
920     if (nTool == -1)
921         return FALSE;
922
923     TRACE (tooltips, "tool %d!\n", nTool);
924
925     /* copy tool data */
926     toolPtr = &infoPtr->tools[nTool];
927     lptthit->ti.cbSize   = sizeof(TTTOOLINFO32A);
928     lptthit->ti.uFlags   = toolPtr->uFlags;
929     lptthit->ti.hwnd     = toolPtr->hwnd;
930     lptthit->ti.uId      = toolPtr->uId;
931     lptthit->ti.rect     = toolPtr->rect;
932     lptthit->ti.hinst    = toolPtr->hinst;
933     lptthit->ti.lpszText = toolPtr->lpszText;
934     lptthit->ti.lParam   = toolPtr->lParam;
935
936     return TRUE;
937 }
938
939
940 // << TOOLTIPS_HitTest32W >>
941
942
943 static LRESULT
944 TOOLTIPS_NewToolRect32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
945 {
946     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
947     LPTTTOOLINFO32A lpti = (LPTTTOOLINFO32A)lParam;
948     INT32 nTool;
949
950     if (lpti == NULL)
951         return 0;
952     if (lpti->cbSize < TTTOOLINFO_V1_SIZE32A)
953         return FALSE;
954
955     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpti);
956     if (nTool == -1) return 0;
957
958     infoPtr->tools[nTool].rect = lpti->rect;
959
960     return 0;
961 }
962
963
964 // << TOOLTIPS_NewToolRect32W >>
965
966
967 __inline__ static LRESULT
968 TOOLTIPS_Pop (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
969 {
970     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
971
972     TOOLTIPS_Hide (wndPtr, infoPtr);
973
974     return 0;
975 }
976
977
978 static LRESULT
979 TOOLTIPS_RelayEvent (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
980 {
981     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
982     LPMSG32 lpMsg = (LPMSG32)lParam;
983     POINT32 pt;
984
985     if (lParam == 0) {
986         ERR (tooltips, "lpMsg == NULL!\n");
987         return 0;
988     }
989
990     switch (lpMsg->message) {
991         case WM_LBUTTONDOWN:
992         case WM_LBUTTONUP:
993         case WM_MBUTTONDOWN:
994         case WM_MBUTTONUP:
995         case WM_RBUTTONDOWN:
996         case WM_RBUTTONUP:
997             pt = lpMsg->pt;
998             ScreenToClient32 (lpMsg->hwnd, &pt);
999             infoPtr->nOldTool = infoPtr->nTool;
1000             infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
1001             TRACE (tooltips, "tool (%x) %d %d\n",
1002                    wndPtr->hwndSelf, infoPtr->nOldTool, infoPtr->nTool);
1003             TOOLTIPS_Hide (wndPtr, infoPtr);
1004             break;
1005
1006         case WM_MOUSEMOVE:
1007             pt = lpMsg->pt;
1008             ScreenToClient32 (lpMsg->hwnd, &pt);
1009             infoPtr->nOldTool = infoPtr->nTool;
1010             infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
1011             TRACE (tooltips, "tool (%x) %d %d\n",
1012                    wndPtr->hwndSelf, infoPtr->nOldTool, infoPtr->nTool);
1013             TRACE (tooltips, "WM_MOUSEMOVE (%04x %d %d)\n",
1014                    wndPtr->hwndSelf, pt.x, pt.y);
1015             if ((infoPtr->bActive) && (infoPtr->nTool != infoPtr->nOldTool)) {
1016                 if (infoPtr->nOldTool == -1) {
1017                     SetTimer32 (wndPtr->hwndSelf, ID_TIMERSHOW,
1018                                 infoPtr->nInitialTime, 0);
1019                     TRACE (tooltips, "timer 1 started!\n");
1020                 }
1021                 else {
1022                     TOOLTIPS_Hide (wndPtr, infoPtr);
1023                     SetTimer32 (wndPtr->hwndSelf, ID_TIMERSHOW,
1024                                 infoPtr->nReshowTime, 0);
1025                     TRACE (tooltips, "timer 2 started!\n");
1026                 }
1027             }
1028             if (infoPtr->nCurrentTool != -1) {
1029                 SetTimer32 (wndPtr->hwndSelf, ID_TIMERLEAVE, 100, 0);
1030                 TRACE (tooltips, "timer 3 started!\n");
1031             }
1032             break;
1033     }
1034
1035     return 0;
1036 }
1037
1038
1039 static LRESULT
1040 TOOLTIPS_SetDelayTime (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1041 {
1042     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1043     INT32 nTime = (INT32)LOWORD(lParam);
1044
1045     switch (wParam) {
1046         case TTDT_AUTOMATIC:
1047             if (nTime == 0) {
1048                 infoPtr->nAutomaticTime = 500;
1049                 infoPtr->nReshowTime    = 100;
1050                 infoPtr->nAutoPopTime   = 5000;
1051                 infoPtr->nInitialTime   = 500;
1052             }
1053             else {
1054                 infoPtr->nAutomaticTime = nTime;
1055                 infoPtr->nReshowTime    = nTime / 5;
1056                 infoPtr->nAutoPopTime   = nTime * 10;
1057                 infoPtr->nInitialTime   = nTime;
1058             }
1059             break;
1060
1061         case TTDT_RESHOW:
1062             infoPtr->nReshowTime = nTime;
1063             break;
1064
1065         case TTDT_AUTOPOP:
1066             infoPtr->nAutoPopTime = nTime;
1067             break;
1068
1069         case TTDT_INITIAL:
1070             infoPtr->nInitialTime = nTime;
1071             break;
1072     }
1073
1074     return 0;
1075 }
1076
1077
1078 static LRESULT
1079 TOOLTIPS_SetMargin (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1080 {
1081     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1082     LPRECT32 lpRect = (LPRECT32)lParam;
1083
1084     infoPtr->rcMargin.left   = lpRect->left;
1085     infoPtr->rcMargin.right  = lpRect->right;
1086     infoPtr->rcMargin.bottom = lpRect->bottom;
1087     infoPtr->rcMargin.top    = lpRect->top;
1088
1089     return 0;
1090 }
1091
1092
1093 __inline__ static LRESULT
1094 TOOLTIPS_SetMaxTipWidth (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1095 {
1096     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1097     INT32 nTemp = infoPtr->nMaxTipWidth;
1098
1099     infoPtr->nMaxTipWidth = (INT32)lParam;
1100
1101     return nTemp;
1102 }
1103
1104
1105 __inline__ static LRESULT
1106 TOOLTIPS_SetTipBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1107 {
1108     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1109
1110     infoPtr->clrBk = (COLORREF)wParam;
1111
1112     return 0;
1113 }
1114
1115
1116 __inline__ static LRESULT
1117 TOOLTIPS_SetTipTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1118 {
1119     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1120
1121     infoPtr->clrText = (COLORREF)wParam;
1122
1123     return 0;
1124 }
1125
1126
1127 static LRESULT
1128 TOOLTIPS_SetToolInfo32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1129 {
1130     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1131     LPTTTOOLINFO32A lpToolInfo = (LPTTTOOLINFO32A)lParam;
1132     TTTOOL_INFO *toolPtr;
1133     INT32 nTool;
1134
1135     if (lpToolInfo == NULL)
1136         return 0;
1137     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZE32A)
1138         return 0;
1139
1140     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1141     if (nTool == -1) return 0;
1142
1143     TRACE (tooltips, "tool %d\n", nTool);
1144
1145     toolPtr = &infoPtr->tools[nTool];
1146
1147     /* copy tool data */
1148     toolPtr->uFlags = lpToolInfo->uFlags;
1149     toolPtr->hwnd   = lpToolInfo->hwnd;
1150     toolPtr->uId    = lpToolInfo->uId;
1151     toolPtr->rect   = lpToolInfo->rect;
1152     toolPtr->hinst  = lpToolInfo->hinst;
1153
1154     if ((lpToolInfo->hinst) && (HIWORD((INT32)lpToolInfo->lpszText) == 0)) {
1155         TRACE (tooltips, "set string id %x!\n", (INT32)lpToolInfo->lpszText);
1156         toolPtr->lpszText = lpToolInfo->lpszText;
1157     }
1158     else if (lpToolInfo->lpszText) {
1159         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACK32A)
1160             toolPtr->lpszText = lpToolInfo->lpszText;
1161         else {
1162             INT32 len = lstrlen32A (lpToolInfo->lpszText);
1163             COMCTL32_Free (toolPtr->lpszText);
1164             toolPtr->lpszText = COMCTL32_Alloc (len + 1);
1165             lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
1166         }
1167     }
1168
1169     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFO32A))
1170         toolPtr->lParam = lpToolInfo->lParam;
1171
1172     return 0;
1173 }
1174
1175
1176 // << TOOLTIPS_SetToolInfo32W >>
1177
1178
1179 static LRESULT
1180 TOOLTIPS_TrackActivate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1181 {
1182     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1183     LPTTTOOLINFO32A lpToolInfo = (LPTTTOOLINFO32A)lParam;
1184
1185     if (lpToolInfo == NULL)
1186         return 0;
1187     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZE32A)
1188         return FALSE;
1189
1190     if ((BOOL32)wParam) {
1191         /* activate */
1192         infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1193         if (infoPtr->nTrackTool != -1) {
1194             TRACE (tooltips, "activated!\n");
1195             infoPtr->bTrackActive = TRUE;
1196             TOOLTIPS_TrackShow (wndPtr, infoPtr);
1197         }
1198     }
1199     else {
1200         /* deactivate */
1201         TOOLTIPS_TrackHide (wndPtr, infoPtr);
1202
1203         infoPtr->bTrackActive = FALSE;
1204         infoPtr->nTrackTool = -1;
1205
1206         TRACE (tooltips, "deactivated!\n");
1207     }
1208
1209     return 0;
1210 }
1211
1212
1213 static LRESULT
1214 TOOLTIPS_TrackPosition (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1215 {
1216     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1217
1218     infoPtr->xTrackPos = (INT32)LOWORD(lParam);
1219     infoPtr->yTrackPos = (INT32)HIWORD(lParam);
1220
1221     if (infoPtr->bTrackActive) {
1222         TRACE (tooltips, "[%d %d]\n",
1223                infoPtr->xTrackPos, infoPtr->yTrackPos);
1224
1225         TOOLTIPS_TrackShow (wndPtr, infoPtr);
1226     }
1227
1228     return 0;
1229 }
1230
1231
1232 static LRESULT
1233 TOOLTIPS_Update (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1234 {
1235     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1236
1237     if (infoPtr->nCurrentTool != -1)
1238         UpdateWindow32 (wndPtr->hwndSelf);
1239
1240     return 0;
1241 }
1242
1243
1244 static LRESULT
1245 TOOLTIPS_UpdateTipText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1246 {
1247     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1248     LPTTTOOLINFO32A lpToolInfo = (LPTTTOOLINFO32A)lParam;
1249     TTTOOL_INFO *toolPtr;
1250     INT32 nTool;
1251
1252     if (lpToolInfo == NULL)
1253         return 0;
1254     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZE32A)
1255         return FALSE;
1256
1257     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1258     if (nTool == -1) return 0;
1259
1260     TRACE (tooltips, "tool %d\n", nTool);
1261
1262     toolPtr = &infoPtr->tools[nTool];
1263
1264     /* copy tool text */
1265     toolPtr->hinst  = lpToolInfo->hinst;
1266
1267     if ((lpToolInfo->hinst) && (HIWORD((INT32)lpToolInfo->lpszText) == 0)){
1268         toolPtr->lpszText = lpToolInfo->lpszText;
1269     }
1270     else if (lpToolInfo->lpszText) {
1271         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACK32A)
1272             toolPtr->lpszText = lpToolInfo->lpszText;
1273         else {
1274             INT32 len = lstrlen32A (lpToolInfo->lpszText);
1275             COMCTL32_Free (toolPtr->lpszText);
1276             toolPtr->lpszText = COMCTL32_Alloc (len + 1);
1277             lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
1278         }
1279     }
1280
1281     return 0;
1282 }
1283
1284
1285 // << TOOLTIPS_UpdateTipText32W >>
1286
1287
1288 static LRESULT
1289 TOOLTIPS_WindowFromPoint (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1290 {
1291     return WindowFromPoint32 (*((LPPOINT32)lParam));
1292 }
1293
1294
1295
1296 static LRESULT
1297 TOOLTIPS_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1298 {
1299     TOOLTIPS_INFO *infoPtr;
1300     NONCLIENTMETRICS32A nclm;
1301
1302     /* allocate memory for info structure */
1303     infoPtr = (TOOLTIPS_INFO *)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO));
1304     wndPtr->wExtra[0] = (DWORD)infoPtr;
1305
1306     if (infoPtr == NULL) {
1307         ERR (tooltips, "could not allocate info memory!\n");
1308         return 0;
1309     }
1310
1311     /* initialize info structure */
1312     infoPtr->bActive = TRUE;
1313     infoPtr->bTrackActive = FALSE;
1314     infoPtr->clrBk   = GetSysColor32 (COLOR_INFOBK);
1315     infoPtr->clrText = GetSysColor32 (COLOR_INFOTEXT);
1316
1317     nclm.cbSize = sizeof(NONCLIENTMETRICS32A);
1318     SystemParametersInfo32A (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1319     infoPtr->hFont = CreateFontIndirect32A (&nclm.lfStatusFont);
1320
1321     infoPtr->nMaxTipWidth = -1;
1322     infoPtr->nTool = -1;
1323     infoPtr->nOldTool = -1;
1324     infoPtr->nCurrentTool = -1;
1325     infoPtr->nTrackTool = -1;
1326
1327     infoPtr->nAutomaticTime = 500;
1328     infoPtr->nReshowTime    = 100;
1329     infoPtr->nAutoPopTime   = 5000;
1330     infoPtr->nInitialTime   = 500;
1331
1332     SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0,
1333                     SWP_NOZORDER | SWP_HIDEWINDOW);
1334
1335     return 0;
1336 }
1337
1338
1339 static LRESULT
1340 TOOLTIPS_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1341 {
1342     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1343     TTTOOL_INFO *toolPtr;
1344     INT32 i;
1345
1346     /* free tools */
1347     if (infoPtr->tools) {
1348         for (i = 0; i < infoPtr->uNumTools; i++) {
1349             toolPtr = &infoPtr->tools[i];
1350             if ((toolPtr->hinst) && (toolPtr->lpszText)) {
1351                 if (toolPtr->lpszText != LPSTR_TEXTCALLBACK32A)
1352                     COMCTL32_Free (toolPtr->lpszText);
1353             }
1354
1355             /* remove subclassing */
1356             if (toolPtr->uFlags & TTF_SUBCLASS) {
1357                 LPTT_SUBCLASS_INFO lpttsi;
1358
1359                 if (toolPtr->uFlags & TTF_IDISHWND)
1360                     lpttsi = (LPTT_SUBCLASS_INFO)GetProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
1361                 else
1362                     lpttsi = (LPTT_SUBCLASS_INFO)GetProp32A (toolPtr->hwnd, TT_SUBCLASS_PROP);
1363
1364                 if (lpttsi) {
1365                     SetWindowLong32A ((HWND32)toolPtr->uId, GWL_WNDPROC,
1366                                       (LONG)lpttsi->wpOrigProc);
1367                     RemoveProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
1368                     COMCTL32_Free (&lpttsi);
1369                 }
1370             }
1371         }
1372         COMCTL32_Free (infoPtr->tools);
1373     }
1374
1375     /* delete font */
1376     DeleteObject32 (infoPtr->hFont);
1377
1378     /* free tool tips info data */
1379     COMCTL32_Free (infoPtr);
1380
1381     return 0;
1382 }
1383
1384
1385 static LRESULT
1386 TOOLTIPS_EraseBackground (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1387 {
1388     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1389     RECT32 rect;
1390     HBRUSH32 hBrush;
1391
1392     hBrush = CreateSolidBrush32 (infoPtr->clrBk);
1393     GetClientRect32 (wndPtr->hwndSelf, &rect);
1394     FillRect32 ((HDC32)wParam, &rect, hBrush);
1395     DeleteObject32 (hBrush);
1396
1397     return FALSE;
1398 }
1399
1400
1401 static LRESULT
1402 TOOLTIPS_GetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1403 {
1404     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1405
1406     return infoPtr->hFont;
1407 }
1408
1409
1410 static LRESULT
1411 TOOLTIPS_MouseMessage (WND *wndPtr, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
1412 {
1413     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1414
1415     TOOLTIPS_Hide (wndPtr, infoPtr);
1416
1417     return 0;
1418 }
1419
1420
1421 static LRESULT
1422 TOOLTIPS_NCCreate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1423 {
1424     wndPtr->dwStyle &= 0x0000FFFF;
1425     wndPtr->dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
1426
1427     return TRUE;
1428 }
1429
1430
1431 static LRESULT
1432 TOOLTIPS_NCHitTest (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1433 {
1434     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1435     INT32 nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool;
1436
1437     TRACE (tooltips, " nTool=%d\n", nTool);
1438
1439     if ((nTool > -1) && (nTool < infoPtr->uNumTools)) {
1440         if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) {
1441             TRACE (tooltips, "-- in transparent mode!\n");
1442             return HTTRANSPARENT;
1443         }
1444     }
1445
1446     return DefWindowProc32A (wndPtr->hwndSelf, WM_NCHITTEST, wParam, lParam);
1447 }
1448
1449
1450 static LRESULT
1451 TOOLTIPS_Paint (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1452 {
1453     HDC32 hdc;
1454     PAINTSTRUCT32 ps;
1455
1456     hdc = (wParam == 0) ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
1457     TOOLTIPS_Refresh (wndPtr, hdc);
1458     if (!wParam)
1459         EndPaint32 (wndPtr->hwndSelf, &ps);
1460     return 0;
1461 }
1462
1463
1464 static LRESULT
1465 TOOLTIPS_SetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1466 {
1467     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1468
1469     infoPtr->hFont = (HFONT32)wParam;
1470
1471     if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
1472         FIXME (tooltips, "full redraw needed!\n");
1473     }
1474
1475     return 0;
1476 }
1477
1478
1479 static LRESULT
1480 TOOLTIPS_Timer (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1481 {
1482     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1483
1484     TRACE (tooltips, "timer %d (%x) expired!\n", wParam, wndPtr->hwndSelf);
1485
1486     switch (wParam)
1487     {
1488         case ID_TIMERSHOW:
1489             KillTimer32 (wndPtr->hwndSelf, ID_TIMERSHOW);
1490             if (TOOLTIPS_CheckTool (wndPtr, TRUE) == infoPtr->nTool)
1491                 TOOLTIPS_Show (wndPtr, infoPtr);
1492             break;
1493
1494         case ID_TIMERPOP:
1495             TOOLTIPS_Hide (wndPtr, infoPtr);
1496             break;
1497
1498         case ID_TIMERLEAVE:
1499             KillTimer32 (wndPtr->hwndSelf, ID_TIMERLEAVE);
1500             if (TOOLTIPS_CheckTool (wndPtr, FALSE) == -1) {
1501                 infoPtr->nTool = -1;
1502                 infoPtr->nOldTool = -1;
1503                 TOOLTIPS_Hide (wndPtr, infoPtr);
1504             }
1505             break;
1506     }
1507     return 0;
1508 }
1509
1510
1511 static LRESULT
1512 TOOLTIPS_WinIniChange (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1513 {
1514     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1515     NONCLIENTMETRICS32A nclm;
1516
1517     infoPtr->clrBk   = GetSysColor32 (COLOR_INFOBK);
1518     infoPtr->clrText = GetSysColor32 (COLOR_INFOTEXT);
1519
1520     DeleteObject32 (infoPtr->hFont);
1521     nclm.cbSize = sizeof(NONCLIENTMETRICS32A);
1522     SystemParametersInfo32A (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1523     infoPtr->hFont = CreateFontIndirect32A (&nclm.lfStatusFont);
1524
1525     return 0;
1526 }
1527
1528
1529 LRESULT CALLBACK
1530 TOOLTIPS_SubclassProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
1531 {
1532     LPTT_SUBCLASS_INFO lpttsi =
1533         (LPTT_SUBCLASS_INFO)GetProp32A (hwnd, TT_SUBCLASS_PROP);
1534     WND *wndPtr;
1535     TOOLTIPS_INFO *infoPtr;
1536     UINT32 nTool;
1537
1538     switch (uMsg) {
1539         case WM_LBUTTONDOWN:
1540         case WM_LBUTTONUP:
1541         case WM_MBUTTONDOWN:
1542         case WM_MBUTTONUP:
1543         case WM_RBUTTONDOWN:
1544         case WM_RBUTTONUP:
1545             {
1546                 wndPtr = WIN_FindWndPtr(lpttsi->hwndToolTip);
1547                 infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1548                 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
1549
1550                 TRACE (tooltips, "subclassed mouse message %04x\n", uMsg);
1551                 infoPtr->nOldTool = infoPtr->nTool;
1552                 infoPtr->nTool = nTool;
1553                 TOOLTIPS_Hide (wndPtr, infoPtr);
1554             }
1555             break;
1556
1557         case WM_MOUSEMOVE:
1558             {
1559                 wndPtr = WIN_FindWndPtr(lpttsi->hwndToolTip);
1560                 infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1561                 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
1562
1563                 TRACE (tooltips, "subclassed WM_MOUSEMOVE\n");
1564                 infoPtr->nOldTool = infoPtr->nTool;
1565                 infoPtr->nTool = nTool;
1566
1567                 if ((infoPtr->bActive) &&
1568                     (infoPtr->nTool != infoPtr->nOldTool)) {
1569                     if (infoPtr->nOldTool == -1) {
1570                         SetTimer32 (wndPtr->hwndSelf, ID_TIMERSHOW,
1571                                     infoPtr->nInitialTime, 0);
1572                         TRACE (tooltips, "timer 1 started!\n");
1573                     }
1574                     else {
1575                         TOOLTIPS_Hide (wndPtr, infoPtr);
1576                         SetTimer32 (wndPtr->hwndSelf, ID_TIMERSHOW,
1577                                 infoPtr->nReshowTime, 0);
1578                         TRACE (tooltips, "timer 2 started!\n");
1579                     }
1580                 }
1581                 if (infoPtr->nCurrentTool != -1) {
1582                     SetTimer32 (wndPtr->hwndSelf, ID_TIMERLEAVE, 100, 0);
1583                     TRACE (tooltips, "timer 3 started!\n");
1584                 }
1585             }
1586             break;
1587     }
1588
1589     return CallWindowProc32A (lpttsi->wpOrigProc, hwnd, uMsg, wParam, lParam);
1590 }
1591
1592
1593 LRESULT CALLBACK
1594 TOOLTIPS_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
1595 {
1596     WND *wndPtr = WIN_FindWndPtr(hwnd);
1597
1598     switch (uMsg)
1599     {
1600         case TTM_ACTIVATE:
1601             return TOOLTIPS_Activate (wndPtr, wParam, lParam);
1602
1603         case TTM_ADDTOOL32A:
1604             return TOOLTIPS_AddTool32A (wndPtr, wParam, lParam);
1605
1606 //      case TTM_ADDTOOL32W:
1607
1608         case TTM_DELTOOL32A:
1609             return TOOLTIPS_DelTool32A (wndPtr, wParam, lParam);
1610
1611 //      case TTM_DELTOOL32W:
1612
1613         case TTM_ENUMTOOLS32A:
1614             return TOOLTIPS_EnumTools32A (wndPtr, wParam, lParam);
1615
1616 //      case TTM_ENUMTOOLS32W:
1617
1618         case TTM_GETCURRENTTOOL32A:
1619             return TOOLTIPS_GetCurrentTool32A (wndPtr, wParam, lParam);
1620
1621 //      case TTM_GETCURRENTTOOL32W:
1622
1623         case TTM_GETDELAYTIME:
1624             return TOOLTIPS_GetDelayTime (wndPtr, wParam, lParam);
1625
1626         case TTM_GETMARGIN:
1627             return TOOLTIPS_GetMargin (wndPtr, wParam, lParam);
1628
1629         case TTM_GETMAXTIPWIDTH:
1630             return TOOLTIPS_GetMaxTipWidth (wndPtr, wParam, lParam);
1631
1632         case TTM_GETTEXT32A:
1633             return TOOLTIPS_GetText32A (wndPtr, wParam, lParam);
1634
1635 //      case TTM_GETTEXT32W:
1636
1637         case TTM_GETTIPBKCOLOR:
1638             return TOOLTIPS_GetTipBkColor (wndPtr, wParam, lParam);
1639
1640         case TTM_GETTIPTEXTCOLOR:
1641             return TOOLTIPS_GetTipTextColor (wndPtr, wParam, lParam);
1642
1643         case TTM_GETTOOLCOUNT:
1644             return TOOLTIPS_GetToolCount (wndPtr, wParam, lParam);
1645
1646         case TTM_GETTOOLINFO32A:
1647             return TOOLTIPS_GetToolInfo32A (wndPtr, wParam, lParam);
1648
1649 //      case TTM_GETTOOLINFO32W:
1650
1651         case TTM_HITTEST32A:
1652             return TOOLTIPS_HitTest32A (wndPtr, wParam, lParam);
1653
1654 //      case TTM_HITTEST32W:
1655
1656         case TTM_NEWTOOLRECT32A:
1657             return TOOLTIPS_NewToolRect32A (wndPtr, wParam, lParam);
1658
1659 //      case TTM_NEWTOOLRECT32W:
1660
1661         case TTM_POP:
1662             return TOOLTIPS_Pop (wndPtr, wParam, lParam);
1663
1664         case TTM_RELAYEVENT:
1665             return TOOLTIPS_RelayEvent (wndPtr, wParam, lParam);
1666
1667         case TTM_SETDELAYTIME:
1668             return TOOLTIPS_SetDelayTime (wndPtr, wParam, lParam);
1669
1670         case TTM_SETMARGIN:
1671             return TOOLTIPS_SetMargin (wndPtr, wParam, lParam);
1672
1673         case TTM_SETMAXTIPWIDTH:
1674             return TOOLTIPS_SetMaxTipWidth (wndPtr, wParam, lParam);
1675
1676         case TTM_SETTIPBKCOLOR:
1677             return TOOLTIPS_SetTipBkColor (wndPtr, wParam, lParam);
1678
1679         case TTM_SETTIPTEXTCOLOR:
1680             return TOOLTIPS_SetTipTextColor (wndPtr, wParam, lParam);
1681
1682         case TTM_SETTOOLINFO32A:
1683             return TOOLTIPS_SetToolInfo32A (wndPtr, wParam, lParam);
1684
1685 //      case TTM_SETTOOLINFO32W:
1686
1687         case TTM_TRACKACTIVATE:
1688             return TOOLTIPS_TrackActivate (wndPtr, wParam, lParam);
1689
1690         case TTM_TRACKPOSITION:
1691             return TOOLTIPS_TrackPosition (wndPtr, wParam, lParam);
1692
1693         case TTM_UPDATE:
1694             return TOOLTIPS_Update (wndPtr, wParam, lParam);
1695
1696         case TTM_UPDATETIPTEXT32A:
1697             return TOOLTIPS_UpdateTipText32A (wndPtr, wParam, lParam);
1698
1699 //      case TTM_UPDATETIPTEXT32W:
1700
1701         case TTM_WINDOWFROMPOINT:
1702             return TOOLTIPS_WindowFromPoint (wndPtr, wParam, lParam);
1703
1704
1705         case WM_CREATE:
1706             return TOOLTIPS_Create (wndPtr, wParam, lParam);
1707
1708         case WM_DESTROY:
1709             return TOOLTIPS_Destroy (wndPtr, wParam, lParam);
1710
1711         case WM_ERASEBKGND:
1712             return TOOLTIPS_EraseBackground (wndPtr, wParam, lParam);
1713
1714         case WM_GETFONT:
1715             return TOOLTIPS_GetFont (wndPtr, wParam, lParam);
1716
1717         case WM_LBUTTONDOWN:
1718         case WM_LBUTTONUP:
1719         case WM_MBUTTONDOWN:
1720         case WM_MBUTTONUP:
1721         case WM_RBUTTONDOWN:
1722         case WM_RBUTTONUP:
1723         case WM_MOUSEMOVE:
1724             return TOOLTIPS_MouseMessage (wndPtr, uMsg, wParam, lParam);
1725
1726         case WM_NCCREATE:
1727             return TOOLTIPS_NCCreate (wndPtr, wParam, lParam);
1728
1729         case WM_NCHITTEST:
1730             return TOOLTIPS_NCHitTest (wndPtr, wParam, lParam);
1731
1732         case WM_PAINT:
1733             return TOOLTIPS_Paint (wndPtr, wParam, lParam);
1734
1735         case WM_SETFONT:
1736             return TOOLTIPS_SetFont (wndPtr, wParam, lParam);
1737
1738         case WM_TIMER:
1739             return TOOLTIPS_Timer (wndPtr, wParam, lParam);
1740
1741         case WM_WININICHANGE:
1742             return TOOLTIPS_WinIniChange (wndPtr, wParam, lParam);
1743
1744         default:
1745             if (uMsg >= WM_USER)
1746                 ERR (tooltips, "unknown msg %04x wp=%08x lp=%08lx\n",
1747                      uMsg, wParam, lParam);
1748             return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
1749     }
1750     return 0;
1751 }
1752
1753
1754 VOID
1755 TOOLTIPS_Register (VOID)
1756 {
1757     WNDCLASS32A wndClass;
1758
1759     if (GlobalFindAtom32A (TOOLTIPS_CLASS32A)) return;
1760
1761     ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
1762     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
1763     wndClass.lpfnWndProc   = (WNDPROC32)TOOLTIPS_WindowProc;
1764     wndClass.cbClsExtra    = 0;
1765     wndClass.cbWndExtra    = sizeof(TOOLTIPS_INFO *);
1766     wndClass.hCursor       = LoadCursor32A (0, IDC_ARROW32A);
1767     wndClass.hbrBackground = 0;
1768     wndClass.lpszClassName = TOOLTIPS_CLASS32A;
1769  
1770     RegisterClass32A (&wndClass);
1771 }
1772
1773
1774 VOID
1775 TOOLTIPS_Unregister (VOID)
1776 {
1777     if (GlobalFindAtom32A (TOOLTIPS_CLASS32A))
1778         UnregisterClass32A (TOOLTIPS_CLASS32A, (HINSTANCE32)NULL);
1779 }
1780