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