Added tracking support and fixed loading of resource strings.
[wine] / dlls / comctl32 / tooltips.c
1 /*
2  * Tool tip control
3  *
4  * Copyright 1998 Eric Kohl
5  *
6  * TODO:
7  *   - Tracking tooltips (finished, except smart placement).
8  *   - Transparent tooltips (under construction).
9  *   - TTS_ALWAYSTIP (undefined).
10  *   - Unicode support.
11  *   - Custom draw support.
12  *   - The "lParam" variable from NMTTDISPINFO32A is not handled
13  *     in TOOLTIPS_GetTipText.
14  *
15  * Testing:
16  *   - Run tests using Waite Group Windows95 API Bible Volume 2.
17  *     The second cdrom (chapter 3) contains executables activate.exe,
18  *     curtool.exe, deltool.exe, enumtools.exe, getinfo.exe, getiptxt.exe,
19  *     hittest.exe, needtext.exe, newrect.exe, updtext.exe and winfrpt.exe.
20  */
21
22 #include "windows.h"
23 #include "commctrl.h"
24 #include "tooltips.h"
25 #include "win.h"
26 #include "debug.h"
27
28
29 #define ID_TIMER1  1    /* show delay timer */
30 #define ID_TIMER2  2    /* auto pop timer */
31 #define ID_TIMER3  3    /* tool leave timer */
32
33 /* property name of tooltip window handle */
34 #define TT_SUBCLASS_PROP "CC32SubclassInfo"
35
36 #define TOOLTIPS_GetInfoPtr(wndPtr) ((TOOLTIPS_INFO *)wndPtr->wExtra[0])
37
38
39 LRESULT CALLBACK
40 TOOLTIPS_SubclassProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam);
41
42
43 static VOID
44 TOOLTIPS_Refresh (WND *wndPtr, HDC32 hdc)
45 {
46     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
47     RECT32 rc;
48     INT32 oldBkMode;
49     HFONT32 hOldFont;
50     UINT32 uFlags = DT_EXTERNALLEADING;
51
52     if (infoPtr->nMaxTipWidth > -1)
53         uFlags |= DT_WORDBREAK;
54     if (wndPtr->dwStyle & TTS_NOPREFIX)
55         uFlags |= DT_NOPREFIX;
56     GetClientRect32 (wndPtr->hwndSelf, &rc);
57     rc.left   += (2 + infoPtr->rcMargin.left);
58     rc.top    += (2 + infoPtr->rcMargin.top);
59     rc.right  -= (2 + infoPtr->rcMargin.right);
60     rc.bottom -= (2 + infoPtr->rcMargin.bottom);
61     oldBkMode = SetBkMode32 (hdc, TRANSPARENT);
62     SetTextColor32 (hdc, infoPtr->clrText);
63     hOldFont = SelectObject32 (hdc, infoPtr->hFont);
64     DrawText32A (hdc, infoPtr->szTipText, -1, &rc, uFlags);
65     SelectObject32 (hdc, hOldFont);
66     if (oldBkMode != TRANSPARENT)
67         SetBkMode32 (hdc, oldBkMode);
68 }
69
70
71 static VOID
72 TOOLTIPS_GetTipText (WND *wndPtr, TOOLTIPS_INFO *infoPtr, INT32 nTool)
73 {
74     TTTOOL_INFO *toolPtr = &infoPtr->tools[nTool];
75
76     if ((toolPtr->hinst) && (HIWORD((UINT32)toolPtr->lpszText) == 0)) {
77         TRACE (tooltips, "get res string %x %x\n",
78                toolPtr->hinst, (int)toolPtr->lpszText);
79         LoadString32A (toolPtr->hinst, (UINT32)toolPtr->lpszText,
80                        infoPtr->szTipText, INFOTIPSIZE);
81     }
82     else if (toolPtr->lpszText) {
83         if (toolPtr->lpszText == LPSTR_TEXTCALLBACK32A) {
84             NMTTDISPINFO32A ttnmdi;
85
86             /* fill NMHDR struct */
87             ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFO32A));
88             ttnmdi.hdr.hwndFrom = wndPtr->hwndSelf;
89             ttnmdi.hdr.idFrom = toolPtr->uId;
90             ttnmdi.hdr.code = TTN_GETDISPINFO32A;
91             ttnmdi.uFlags = toolPtr->uFlags;
92             ttnmdi.lpszText = infoPtr->szTipText;
93
94             TRACE (tooltips, "hdr.idFrom = %x\n", ttnmdi.hdr.idFrom);
95             SendMessage32A (toolPtr->hwnd, WM_NOTIFY,
96                             (WPARAM32)toolPtr->uId, (LPARAM)&ttnmdi);
97
98             if ((ttnmdi.hinst) && (HIWORD((UINT32)ttnmdi.szText) == 0)) {
99                 LoadString32A (ttnmdi.hinst, (UINT32)ttnmdi.szText,
100                                infoPtr->szTipText, INFOTIPSIZE);
101                 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
102                     toolPtr->hinst = ttnmdi.hinst;
103                     toolPtr->lpszText = ttnmdi.szText;
104                 }
105             }
106             else if (ttnmdi.szText[0]) {
107                 lstrcpyn32A (infoPtr->szTipText, ttnmdi.szText, 80);
108                 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
109                     INT32 len = lstrlen32A (ttnmdi.szText) + 1;
110                     toolPtr->hinst = 0;
111                     toolPtr->lpszText = COMCTL32_Alloc (len);
112                     lstrcpy32A (toolPtr->lpszText, ttnmdi.szText);
113                 }
114             }
115             else if (ttnmdi.lpszText == 0) {
116                 /* no text available */
117                 infoPtr->szTipText[0] = '\0';
118             }
119             else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACK32A) {
120                 if (ttnmdi.lpszText != infoPtr->szTipText)
121                     lstrcpyn32A (infoPtr->szTipText, ttnmdi.lpszText,
122                                  INFOTIPSIZE);
123                 if (ttnmdi.uFlags & TTF_DI_SETITEM) {
124                     INT32 len = lstrlen32A (ttnmdi.lpszText) + 1;
125                     toolPtr->hinst = 0;
126                     toolPtr->lpszText = COMCTL32_Alloc (len);
127                     lstrcpy32A (toolPtr->lpszText, ttnmdi.lpszText);
128                 }
129             }
130             else {
131                 ERR (tooltips, "recursive text callback!\n");
132                 infoPtr->szTipText[0] = '\0';
133             }
134         }
135         else
136             lstrcpyn32A (infoPtr->szTipText, toolPtr->lpszText, INFOTIPSIZE);
137     }
138     else
139         /* no text available */
140         infoPtr->szTipText[0] = '\0';
141
142     TRACE (tooltips, "\"%s\"\n", infoPtr->szTipText);
143 }
144
145
146 static VOID
147 TOOLTIPS_CalcTipSize (WND *wndPtr, TOOLTIPS_INFO *infoPtr, LPSIZE32 lpSize)
148 {
149     HDC32 hdc;
150     HFONT32 hOldFont;
151     UINT32 uFlags = DT_EXTERNALLEADING | DT_CALCRECT;
152     RECT32 rc = {0, 0, 0, 0};
153
154     if (infoPtr->nMaxTipWidth > -1) {
155         rc.right = infoPtr->nMaxTipWidth;
156         uFlags |= DT_WORDBREAK;
157     }
158     if (wndPtr->dwStyle & TTS_NOPREFIX)
159         uFlags |= DT_NOPREFIX;
160     TRACE (tooltips, "\"%s\"\n", infoPtr->szTipText);
161
162     hdc = GetDC32 (wndPtr->hwndSelf);
163     hOldFont = SelectObject32 (hdc, infoPtr->hFont);
164     DrawText32A (hdc, infoPtr->szTipText, -1, &rc, uFlags);
165     GetTextExtentPoint32A (hdc, infoPtr->szTipText, lstrlen32A(infoPtr->szTipText), lpSize);
166     SelectObject32 (hdc, hOldFont);
167     ReleaseDC32 (wndPtr->hwndSelf, hdc);
168
169     lpSize->cx = rc.right - rc.left + 4 + 
170                  infoPtr->rcMargin.left + infoPtr->rcMargin.right;
171     lpSize->cy = rc.bottom - rc.top + 4 +
172                  infoPtr->rcMargin.bottom + infoPtr->rcMargin.top;
173 }
174
175
176 static VOID
177 TOOLTIPS_Show (WND *wndPtr, TOOLTIPS_INFO *infoPtr)
178 {
179     TTTOOL_INFO *toolPtr;
180     RECT32 rect;
181     SIZE32 size;
182     NMHDR hdr;
183
184     if (infoPtr->nTool == -1) {
185         TRACE (tooltips, "invalid tool (-1)!\n");
186         return;
187     }
188
189     infoPtr->nCurrentTool = infoPtr->nTool;
190
191     TRACE (tooltips, "Show tooltip pre %d!\n", infoPtr->nTool);
192
193     TOOLTIPS_GetTipText (wndPtr, infoPtr, infoPtr->nCurrentTool);
194
195     if (infoPtr->szTipText[0] == '\0') {
196         infoPtr->nCurrentTool = -1;
197         return;
198     }
199
200     TRACE (tooltips, "Show tooltip %d!\n", infoPtr->nCurrentTool);
201     toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
202
203     hdr.hwndFrom = wndPtr->hwndSelf;
204     hdr.idFrom = toolPtr->uId;
205     hdr.code = TTN_SHOW;
206     SendMessage32A (toolPtr->hwnd, WM_NOTIFY,
207                     (WPARAM32)toolPtr->uId, (LPARAM)&hdr);
208
209     TRACE (tooltips, "\"%s\"\n", infoPtr->szTipText);
210
211     TOOLTIPS_CalcTipSize (wndPtr, infoPtr, &size);
212     TRACE (tooltips, "size %d - %d\n", size.cx, size.cy);
213
214     if (toolPtr->uFlags & TTF_CENTERTIP) {
215         RECT32 rc;
216
217         if (toolPtr->uFlags & TTF_IDISHWND)
218             GetWindowRect32 ((HWND32)toolPtr->uId, &rc);
219         else {
220             rc = toolPtr->rect;
221             MapWindowPoints32 (toolPtr->hwnd, (HWND32)0, (LPPOINT32)&rc, 2);
222         }
223         rect.left = (rc.left + rc.right - size.cx) / 2;
224         rect.top  = rc.bottom + 2;
225     }
226     else {
227         GetCursorPos32 ((LPPOINT32)&rect);
228         rect.top += 20;
229     }
230
231     TRACE (tooltips, "pos %d - %d\n", rect.left, rect.top);
232
233     rect.right = rect.left + size.cx;
234     rect.bottom = rect.top + size.cy;
235
236     AdjustWindowRectEx32 (&rect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle);
237
238     SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, rect.left, rect.top,
239                     rect.right - rect.left, rect.bottom - rect.top,
240                     SWP_SHOWWINDOW);
241
242     SetTimer32 (wndPtr->hwndSelf, ID_TIMER2, infoPtr->nAutoPopTime, 0);
243 }
244
245
246 static VOID
247 TOOLTIPS_Hide (WND *wndPtr, TOOLTIPS_INFO *infoPtr)
248 {
249     TTTOOL_INFO *toolPtr;
250     NMHDR hdr;
251
252     if (infoPtr->nCurrentTool == -1)
253         return;
254
255     toolPtr = &infoPtr->tools[infoPtr->nCurrentTool];
256     TRACE (tooltips, "Hide tooltip %d!\n", infoPtr->nCurrentTool);
257     KillTimer32 (wndPtr->hwndSelf, ID_TIMER2);
258
259     hdr.hwndFrom = wndPtr->hwndSelf;
260     hdr.idFrom = toolPtr->uId;
261     hdr.code = TTN_POP;
262     SendMessage32A (toolPtr->hwnd, WM_NOTIFY,
263                     (WPARAM32)toolPtr->uId, (LPARAM)&hdr);
264
265     infoPtr->nCurrentTool = -1;
266
267     SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0,
268                     SWP_NOZORDER | SWP_HIDEWINDOW);
269 }
270
271
272 static VOID
273 TOOLTIPS_TrackShow (WND *wndPtr, TOOLTIPS_INFO *infoPtr)
274 {
275     TTTOOL_INFO *toolPtr;
276     RECT32 rect;
277     SIZE32 size;
278     NMHDR hdr;
279
280     if (infoPtr->nTrackTool == -1) {
281         TRACE (tooltips, "invalid tracking tool (-1)!\n");
282         return;
283     }
284
285     TRACE (tooltips, "show tracking tooltip pre %d!\n", infoPtr->nTrackTool);
286
287     TOOLTIPS_GetTipText (wndPtr, infoPtr, infoPtr->nTrackTool);
288
289     if (infoPtr->szTipText[0] == '\0') {
290         infoPtr->nTrackTool = -1;
291         return;
292     }
293
294     TRACE (tooltips, "show tracking tooltip %d!\n", infoPtr->nTrackTool);
295     toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
296
297     hdr.hwndFrom = wndPtr->hwndSelf;
298     hdr.idFrom = toolPtr->uId;
299     hdr.code = TTN_SHOW;
300     SendMessage32A (toolPtr->hwnd, WM_NOTIFY,
301                     (WPARAM32)toolPtr->uId, (LPARAM)&hdr);
302
303     TRACE (tooltips, "\"%s\"\n", infoPtr->szTipText);
304
305     TOOLTIPS_CalcTipSize (wndPtr, infoPtr, &size);
306     TRACE (tooltips, "size %d - %d\n", size.cx, size.cy);
307
308     if (toolPtr->uFlags & TTF_ABSOLUTE) {
309         rect.left = infoPtr->xTrackPos;
310         rect.top  = infoPtr->yTrackPos;
311
312         if (toolPtr->uFlags & TTF_CENTERTIP) {
313             rect.left -= (size.cx / 2);
314             rect.top  -= (size.cy / 2);
315         }
316     }
317     else {
318 #if 0
319         /* FIXME: do smart placement */
320         RECT32 rcTool;
321
322         if (toolPtr->uFlags & TTF_IDISHWND)
323             GetWindowRect32 ((HWND32)toolPtr->uId, &rcTool);
324         else {
325             rcTool = toolPtr->rect;
326             MapWindowPoints32 (toolPtr->hwnd, (HWND32)0, (LPPOINT32)&rcTool, 2);
327         }
328 #endif
329         GetCursorPos32 ((LPPOINT32)&rect);
330         rect.top += 20;
331 #if 0
332         /* smart placement */
333         if ((rect.left + size.cx > rcTool.left) && (rect.left < rcTool.right))
334             rect.left = rcTool.right;
335
336         if ((rect.top + size.cy > rcTool.top) &&
337             (rect.top < rcTool.bottom))
338             rect.top = rcTool.bottom;
339
340
341         if (toolPtr->uFlags & TTF_CENTERTIP) {
342
343         }
344 #endif
345     }
346
347     TRACE (tooltips, "pos %d - %d\n", rect.left, rect.top);
348
349     rect.right = rect.left + size.cx;
350     rect.bottom = rect.top + size.cy;
351
352     AdjustWindowRectEx32 (&rect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle);
353
354     SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, rect.left, rect.top,
355                     rect.right - rect.left, rect.bottom - rect.top,
356                     SWP_SHOWWINDOW);
357 }
358
359
360 static VOID
361 TOOLTIPS_TrackHide (WND *wndPtr, TOOLTIPS_INFO *infoPtr)
362 {
363     TTTOOL_INFO *toolPtr;
364     NMHDR hdr;
365
366     if (infoPtr->nTrackTool == -1)
367         return;
368
369     toolPtr = &infoPtr->tools[infoPtr->nTrackTool];
370     TRACE (tooltips, "hide tracking tooltip %d!\n", infoPtr->nTrackTool);
371
372     hdr.hwndFrom = wndPtr->hwndSelf;
373     hdr.idFrom = toolPtr->uId;
374     hdr.code = TTN_POP;
375     SendMessage32A (toolPtr->hwnd, WM_NOTIFY,
376                     (WPARAM32)toolPtr->uId, (LPARAM)&hdr);
377
378     SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0,
379                     SWP_NOZORDER | SWP_HIDEWINDOW);
380 }
381
382
383 static INT32
384 TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFO32A lpToolInfo)
385 {
386     TTTOOL_INFO *toolPtr;
387     INT32 nTool;
388
389     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
390         toolPtr = &infoPtr->tools[nTool];
391
392         if (!(toolPtr->uFlags & TTF_IDISHWND) && 
393             (lpToolInfo->hwnd == toolPtr->hwnd) &&
394             (lpToolInfo->uId == toolPtr->uId))
395             return nTool;
396     }
397
398     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
399         toolPtr = &infoPtr->tools[nTool];
400
401         if ((toolPtr->uFlags & TTF_IDISHWND) &&
402             (lpToolInfo->uId == toolPtr->uId))
403             return nTool;
404     }
405
406     return -1;
407 }
408
409
410 static INT32
411 TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO *infoPtr, HWND32 hwnd, LPPOINT32 lpPt)
412 {
413     TTTOOL_INFO *toolPtr;
414     INT32  nTool;
415
416     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
417         toolPtr = &infoPtr->tools[nTool];
418
419         if (!(toolPtr->uFlags & TTF_IDISHWND)) {
420             if (hwnd != toolPtr->hwnd)
421                 continue;
422             if (!PtInRect32 (&toolPtr->rect, *lpPt))
423                 continue;
424             return nTool;
425         }
426     }
427
428     for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) {
429         toolPtr = &infoPtr->tools[nTool];
430
431         if (toolPtr->uFlags & TTF_IDISHWND) {
432             if ((HWND32)toolPtr->uId == hwnd)
433                 return nTool;
434         }
435     }
436
437     return -1;
438 }
439
440
441 static INT32
442 TOOLTIPS_GetToolFromMessage (TOOLTIPS_INFO *infoPtr, HWND32 hwndTool)
443 {
444     DWORD   dwPos;
445     POINT32 pt;
446
447     dwPos = GetMessagePos ();
448     pt.x = (INT32)LOWORD(dwPos);
449     pt.y = (INT32)HIWORD(dwPos);
450     ScreenToClient32 (hwndTool, &pt);
451
452     return TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
453 }
454
455
456 static INT32
457 TOOLTIPS_CheckTool (WND *wndPtr, BOOL32 bShowTest)
458 {
459     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
460     POINT32 pt;
461     HWND32 hwndTool;
462     INT32 nTool;
463
464     GetCursorPos32 (&pt);
465     hwndTool =
466         SendMessage32A (wndPtr->hwndSelf, TTM_WINDOWFROMPOINT, 0, (LPARAM)&pt);
467     if (hwndTool == 0)
468         return -1;
469
470     ScreenToClient32 (hwndTool, &pt);
471     nTool = TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt);
472     if (nTool == -1)
473         return -1;
474
475 #if 0
476     if (!(wndPtr->dwStyle & TTS_ALWAYSTIP) && bShowTest) {
477         if (!IsWindowEnabled32 (infoPtr->tools[infoPtr->nTool].hwnd))
478             return -1;
479     }
480 #endif
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_TIMER1,
1018                                 infoPtr->nInitialTime, 0);
1019                     TRACE (tooltips, "timer 1 started!\n");
1020                 }
1021                 else {
1022                     TOOLTIPS_Hide (wndPtr, infoPtr);
1023                     SetTimer32 (wndPtr->hwndSelf, ID_TIMER1,
1024                                 infoPtr->nReshowTime, 0);
1025                     TRACE (tooltips, "timer 2 started!\n");
1026                 }
1027             }
1028             if (infoPtr->nCurrentTool != -1) {
1029                 SetTimer32 (wndPtr->hwndSelf, ID_TIMER3, 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     TTTOOL_INFO *toolPtr = &infoPtr->tools[infoPtr->nTool];
1415
1416     if (toolPtr->uFlags & TTF_TRANSPARENT) {
1417         FIXME (tooltips, "transparent tooltips not implemented yet!\n");
1418 #if 0
1419         POINT32 pt;
1420         RECT32  rc;
1421
1422         pt.x = (INT32)LOWORD(lParam);
1423         pt.y = (INT32)HIWORD(lParam);
1424
1425         GetClientRect32 (toolPtr->hwnd, &rc);
1426         ScreenToClient32 (toolPtr->hwnd, &pt);
1427         if (PtInRect32 (&rc, pt))
1428             SendMessage32A (toolPtr->hwnd, uMsg, wParam, lParam);
1429 #endif
1430     }
1431     else
1432         TOOLTIPS_Hide (wndPtr, infoPtr);
1433
1434     return 0;
1435 }
1436
1437
1438 static LRESULT
1439 TOOLTIPS_NcCreate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1440 {
1441     wndPtr->dwStyle &= 0x0000FFFF;
1442     wndPtr->dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
1443
1444     return TRUE;
1445 }
1446
1447
1448 static LRESULT
1449 TOOLTIPS_Paint (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1450 {
1451     HDC32 hdc;
1452     PAINTSTRUCT32 ps;
1453
1454     hdc = (wParam == 0) ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
1455     TOOLTIPS_Refresh (wndPtr, hdc);
1456     if (!wParam)
1457         EndPaint32 (wndPtr->hwndSelf, &ps);
1458     return 0;
1459 }
1460
1461
1462 static LRESULT
1463 TOOLTIPS_SetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1464 {
1465     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1466
1467     infoPtr->hFont = (HFONT32)wParam;
1468
1469     if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
1470         FIXME (tooltips, "full redraw needed!\n");
1471     }
1472
1473     return 0;
1474 }
1475
1476
1477 static LRESULT
1478 TOOLTIPS_Timer (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1479 {
1480     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1481
1482     TRACE (tooltips, "timer %d (%x) expired!\n", wParam, wndPtr->hwndSelf);
1483
1484     switch (wParam)
1485     {
1486         case ID_TIMER1:
1487             KillTimer32 (wndPtr->hwndSelf, ID_TIMER1);
1488             if (TOOLTIPS_CheckTool (wndPtr, TRUE) == infoPtr->nTool)
1489                 TOOLTIPS_Show (wndPtr, infoPtr);
1490             break;
1491
1492         case ID_TIMER2:
1493             TOOLTIPS_Hide (wndPtr, infoPtr);
1494             break;
1495
1496         case ID_TIMER3:
1497             KillTimer32 (wndPtr->hwndSelf, ID_TIMER3);
1498             if (TOOLTIPS_CheckTool (wndPtr, FALSE) == -1) {
1499                 infoPtr->nTool = -1;
1500                 infoPtr->nOldTool = -1;
1501                 TOOLTIPS_Hide (wndPtr, infoPtr);
1502             }
1503             break;
1504     }
1505     return 0;
1506 }
1507
1508
1509 static LRESULT
1510 TOOLTIPS_WinIniChange (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1511 {
1512     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1513     NONCLIENTMETRICS32A nclm;
1514
1515     infoPtr->clrBk   = GetSysColor32 (COLOR_INFOBK);
1516     infoPtr->clrText = GetSysColor32 (COLOR_INFOTEXT);
1517
1518     DeleteObject32 (infoPtr->hFont);
1519     nclm.cbSize = sizeof(NONCLIENTMETRICS32A);
1520     SystemParametersInfo32A (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1521     infoPtr->hFont = CreateFontIndirect32A (&nclm.lfStatusFont);
1522
1523     return 0;
1524 }
1525
1526
1527 LRESULT CALLBACK
1528 TOOLTIPS_SubclassProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
1529 {
1530     LPTT_SUBCLASS_INFO lpttsi =
1531         (LPTT_SUBCLASS_INFO)GetProp32A (hwnd, TT_SUBCLASS_PROP);
1532     WND *wndPtr;
1533     TOOLTIPS_INFO *infoPtr;
1534     UINT32 nTool;
1535
1536     switch (uMsg) {
1537         case WM_LBUTTONDOWN:
1538         case WM_LBUTTONUP:
1539         case WM_MBUTTONDOWN:
1540         case WM_MBUTTONUP:
1541         case WM_RBUTTONDOWN:
1542         case WM_RBUTTONUP:
1543             {
1544                 wndPtr = WIN_FindWndPtr(lpttsi->hwndToolTip);
1545                 infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1546                 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
1547
1548                 TRACE (tooltips, "subclassed mouse message %04x\n", uMsg);
1549                 infoPtr->nOldTool = infoPtr->nTool;
1550                 infoPtr->nTool = nTool;
1551                 TOOLTIPS_Hide (wndPtr, infoPtr);
1552             }
1553             break;
1554
1555         case WM_MOUSEMOVE:
1556             {
1557                 wndPtr = WIN_FindWndPtr(lpttsi->hwndToolTip);
1558                 infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
1559                 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
1560
1561                 TRACE (tooltips, "subclassed WM_MOUSEMOVE\n");
1562                 infoPtr->nOldTool = infoPtr->nTool;
1563                 infoPtr->nTool = nTool;
1564
1565                 if ((infoPtr->bActive) &&
1566                     (infoPtr->nTool != infoPtr->nOldTool)) {
1567                     if (infoPtr->nOldTool == -1) {
1568                         SetTimer32 (wndPtr->hwndSelf, ID_TIMER1,
1569                                     infoPtr->nInitialTime, 0);
1570                         TRACE (tooltips, "timer 1 started!\n");
1571                     }
1572                     else {
1573                         TOOLTIPS_Hide (wndPtr, infoPtr);
1574                         SetTimer32 (wndPtr->hwndSelf, ID_TIMER1,
1575                                 infoPtr->nReshowTime, 0);
1576                         TRACE (tooltips, "timer 2 started!\n");
1577                     }
1578                 }
1579                 if (infoPtr->nCurrentTool != -1) {
1580                     SetTimer32 (wndPtr->hwndSelf, ID_TIMER3, 100, 0);
1581                     TRACE (tooltips, "timer 3 started!\n");
1582                 }
1583             }
1584             break;
1585     }
1586
1587     return CallWindowProc32A (lpttsi->wpOrigProc, hwnd, uMsg, wParam, lParam);
1588 }
1589
1590
1591 LRESULT CALLBACK
1592 TOOLTIPS_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
1593 {
1594     WND *wndPtr = WIN_FindWndPtr(hwnd);
1595
1596     switch (uMsg)
1597     {
1598         case TTM_ACTIVATE:
1599             return TOOLTIPS_Activate (wndPtr, wParam, lParam);
1600
1601         case TTM_ADDTOOL32A:
1602             return TOOLTIPS_AddTool32A (wndPtr, wParam, lParam);
1603
1604 //      case TTM_ADDTOOL32W:
1605
1606         case TTM_DELTOOL32A:
1607             return TOOLTIPS_DelTool32A (wndPtr, wParam, lParam);
1608
1609 //      case TTM_DELTOOL32W:
1610
1611         case TTM_ENUMTOOLS32A:
1612             return TOOLTIPS_EnumTools32A (wndPtr, wParam, lParam);
1613
1614 //      case TTM_ENUMTOOLS32W:
1615
1616         case TTM_GETCURRENTTOOL32A:
1617             return TOOLTIPS_GetCurrentTool32A (wndPtr, wParam, lParam);
1618
1619 //      case TTM_GETCURRENTTOOL32W:
1620
1621         case TTM_GETDELAYTIME:
1622             return TOOLTIPS_GetDelayTime (wndPtr, wParam, lParam);
1623
1624         case TTM_GETMARGIN:
1625             return TOOLTIPS_GetMargin (wndPtr, wParam, lParam);
1626
1627         case TTM_GETMAXTIPWIDTH:
1628             return TOOLTIPS_GetMaxTipWidth (wndPtr, wParam, lParam);
1629
1630         case TTM_GETTEXT32A:
1631             return TOOLTIPS_GetText32A (wndPtr, wParam, lParam);
1632
1633 //      case TTM_GETTEXT32W:
1634
1635         case TTM_GETTIPBKCOLOR:
1636             return TOOLTIPS_GetTipBkColor (wndPtr, wParam, lParam);
1637
1638         case TTM_GETTIPTEXTCOLOR:
1639             return TOOLTIPS_GetTipTextColor (wndPtr, wParam, lParam);
1640
1641         case TTM_GETTOOLCOUNT:
1642             return TOOLTIPS_GetToolCount (wndPtr, wParam, lParam);
1643
1644         case TTM_GETTOOLINFO32A:
1645             return TOOLTIPS_GetToolInfo32A (wndPtr, wParam, lParam);
1646
1647 //      case TTM_GETTOOLINFO32W:
1648
1649         case TTM_HITTEST32A:
1650             return TOOLTIPS_HitTest32A (wndPtr, wParam, lParam);
1651
1652 //      case TTM_HITTEST32W:
1653
1654         case TTM_NEWTOOLRECT32A:
1655             return TOOLTIPS_NewToolRect32A (wndPtr, wParam, lParam);
1656
1657 //      case TTM_NEWTOOLRECT32W:
1658
1659         case TTM_POP:
1660             return TOOLTIPS_Pop (wndPtr, wParam, lParam);
1661
1662         case TTM_RELAYEVENT:
1663             return TOOLTIPS_RelayEvent (wndPtr, wParam, lParam);
1664
1665         case TTM_SETDELAYTIME:
1666             return TOOLTIPS_SetDelayTime (wndPtr, wParam, lParam);
1667
1668         case TTM_SETMARGIN:
1669             return TOOLTIPS_SetMargin (wndPtr, wParam, lParam);
1670
1671         case TTM_SETMAXTIPWIDTH:
1672             return TOOLTIPS_SetMaxTipWidth (wndPtr, wParam, lParam);
1673
1674         case TTM_SETTIPBKCOLOR:
1675             return TOOLTIPS_SetTipBkColor (wndPtr, wParam, lParam);
1676
1677         case TTM_SETTIPTEXTCOLOR:
1678             return TOOLTIPS_SetTipTextColor (wndPtr, wParam, lParam);
1679
1680         case TTM_SETTOOLINFO32A:
1681             return TOOLTIPS_SetToolInfo32A (wndPtr, wParam, lParam);
1682
1683 //      case TTM_SETTOOLINFO32W:
1684
1685         case TTM_TRACKACTIVATE:
1686             return TOOLTIPS_TrackActivate (wndPtr, wParam, lParam);
1687
1688         case TTM_TRACKPOSITION:
1689             return TOOLTIPS_TrackPosition (wndPtr, wParam, lParam);
1690
1691         case TTM_UPDATE:
1692             return TOOLTIPS_Update (wndPtr, wParam, lParam);
1693
1694         case TTM_UPDATETIPTEXT32A:
1695             return TOOLTIPS_UpdateTipText32A (wndPtr, wParam, lParam);
1696
1697 //      case TTM_UPDATETIPTEXT32W:
1698
1699         case TTM_WINDOWFROMPOINT:
1700             return TOOLTIPS_WindowFromPoint (wndPtr, wParam, lParam);
1701
1702
1703         case WM_CREATE:
1704             return TOOLTIPS_Create (wndPtr, wParam, lParam);
1705
1706         case WM_DESTROY:
1707             return TOOLTIPS_Destroy (wndPtr, wParam, lParam);
1708
1709         case WM_ERASEBKGND:
1710             return TOOLTIPS_EraseBackground (wndPtr, wParam, lParam);
1711
1712         case WM_GETFONT:
1713             return TOOLTIPS_GetFont (wndPtr, wParam, lParam);
1714
1715 //      case WM_GETTEXT:
1716 //      case WM_GETTEXTLENGTH:
1717
1718         case WM_LBUTTONDOWN:
1719         case WM_LBUTTONUP:
1720         case WM_MBUTTONDOWN:
1721         case WM_MBUTTONUP:
1722         case WM_RBUTTONDOWN:
1723         case WM_RBUTTONUP:
1724         case WM_MOUSEMOVE:
1725             return TOOLTIPS_MouseMessage (wndPtr, uMsg, wParam, lParam);
1726
1727         case WM_NCCREATE:
1728             return TOOLTIPS_NcCreate (wndPtr, wParam, lParam);
1729
1730 //      case WM_NCHITTEST:
1731 //      case WM_NOTIFYFORMAT:
1732
1733         case WM_PAINT:
1734             return TOOLTIPS_Paint (wndPtr, wParam, lParam);
1735
1736 //      case WM_PRINTCLIENT:
1737
1738         case WM_SETFONT:
1739             return TOOLTIPS_SetFont (wndPtr, wParam, lParam);
1740
1741 //      case WM_STYLECHANGED:
1742
1743         case WM_TIMER:
1744             return TOOLTIPS_Timer (wndPtr, wParam, lParam);
1745
1746         case WM_WININICHANGE:
1747             return TOOLTIPS_WinIniChange (wndPtr, wParam, lParam);
1748
1749         default:
1750             if (uMsg >= WM_USER)
1751                 ERR (tooltips, "unknown msg %04x wp=%08x lp=%08lx\n",
1752                      uMsg, wParam, lParam);
1753             return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
1754     }
1755     return 0;
1756 }
1757
1758
1759 VOID
1760 TOOLTIPS_Register (VOID)
1761 {
1762     WNDCLASS32A wndClass;
1763
1764     if (GlobalFindAtom32A (TOOLTIPS_CLASS32A)) return;
1765
1766     ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
1767     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
1768     wndClass.lpfnWndProc   = (WNDPROC32)TOOLTIPS_WindowProc;
1769     wndClass.cbClsExtra    = 0;
1770     wndClass.cbWndExtra    = sizeof(TOOLTIPS_INFO *);
1771     wndClass.hCursor       = LoadCursor32A (0, IDC_ARROW32A);
1772     wndClass.hbrBackground = 0;
1773     wndClass.lpszClassName = TOOLTIPS_CLASS32A;
1774  
1775     RegisterClass32A (&wndClass);
1776 }
1777
1778
1779 VOID
1780 TOOLTIPS_Unregister (VOID)
1781 {
1782     if (GlobalFindAtom32A (TOOLTIPS_CLASS32A))
1783         UnregisterClass32A (TOOLTIPS_CLASS32A, (HINSTANCE32)NULL);
1784 }
1785