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