No longer directly accessing debuggee memory.
[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     TOOLTIPS_Hide (hwnd, infoPtr);
1408
1409     return 0;
1410 }
1411
1412
1413 static LRESULT
1414 TOOLTIPS_RelayEvent (HWND hwnd, WPARAM wParam, LPARAM lParam)
1415 {
1416     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1417     LPMSG lpMsg = (LPMSG)lParam;
1418     POINT pt;
1419
1420     if (lParam == 0) {
1421         ERR("lpMsg == NULL!\n");
1422         return 0;
1423     }
1424
1425     switch (lpMsg->message) {
1426         case WM_LBUTTONDOWN:
1427         case WM_LBUTTONUP:
1428         case WM_MBUTTONDOWN:
1429         case WM_MBUTTONUP:
1430         case WM_RBUTTONDOWN:
1431         case WM_RBUTTONUP:
1432             pt = lpMsg->pt;
1433             ScreenToClient (lpMsg->hwnd, &pt);
1434             infoPtr->nOldTool = infoPtr->nTool;
1435             infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
1436             TRACE("tool (%x) %d %d\n",
1437                    hwnd, infoPtr->nOldTool, infoPtr->nTool);
1438             TOOLTIPS_Hide (hwnd, infoPtr);
1439             break;
1440
1441         case WM_MOUSEMOVE:
1442             pt = lpMsg->pt;
1443             ScreenToClient (lpMsg->hwnd, &pt);
1444             infoPtr->nOldTool = infoPtr->nTool;
1445             infoPtr->nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lpMsg->hwnd, &pt);
1446             TRACE("tool (%x) %d %d\n",
1447                    hwnd, infoPtr->nOldTool, infoPtr->nTool);
1448             TRACE("WM_MOUSEMOVE (%04x %ld %ld)\n",
1449                    hwnd, pt.x, pt.y);
1450             if ((infoPtr->bActive) && (infoPtr->nTool != infoPtr->nOldTool)) {
1451                 if (infoPtr->nOldTool == -1) {
1452                     SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0);
1453                     TRACE("timer 1 started!\n");
1454                 }
1455                 else {
1456                     TOOLTIPS_Hide (hwnd, infoPtr);
1457                     SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0);
1458                     TRACE("timer 2 started!\n");
1459                 }
1460             }
1461             if (infoPtr->nCurrentTool != -1) {
1462                 SetTimer (hwnd, ID_TIMERLEAVE, 100, 0);
1463                 TRACE("timer 3 started!\n");
1464             }
1465             break;
1466     }
1467
1468     return 0;
1469 }
1470
1471
1472 static LRESULT
1473 TOOLTIPS_SetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam)
1474 {
1475     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1476     INT nTime = (INT)LOWORD(lParam);
1477
1478     switch (wParam) {
1479         case TTDT_AUTOMATIC:
1480             if (nTime == 0) {
1481                 infoPtr->nAutomaticTime = 500;
1482                 infoPtr->nReshowTime    = 100;
1483                 infoPtr->nAutoPopTime   = 5000;
1484                 infoPtr->nInitialTime   = 500;
1485             }
1486             else {
1487                 infoPtr->nAutomaticTime = nTime;
1488                 infoPtr->nReshowTime    = nTime / 5;
1489                 infoPtr->nAutoPopTime   = nTime * 10;
1490                 infoPtr->nInitialTime   = nTime;
1491             }
1492             break;
1493
1494         case TTDT_RESHOW:
1495             infoPtr->nReshowTime = nTime;
1496             break;
1497
1498         case TTDT_AUTOPOP:
1499             infoPtr->nAutoPopTime = nTime;
1500             break;
1501
1502         case TTDT_INITIAL:
1503             infoPtr->nInitialTime = nTime;
1504             break;
1505     }
1506
1507     return 0;
1508 }
1509
1510
1511 static LRESULT
1512 TOOLTIPS_SetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1513 {
1514     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1515     LPRECT lpRect = (LPRECT)lParam;
1516
1517     infoPtr->rcMargin.left   = lpRect->left;
1518     infoPtr->rcMargin.right  = lpRect->right;
1519     infoPtr->rcMargin.bottom = lpRect->bottom;
1520     infoPtr->rcMargin.top    = lpRect->top;
1521
1522     return 0;
1523 }
1524
1525
1526 inline static LRESULT
1527 TOOLTIPS_SetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
1528 {
1529     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1530     INT nTemp = infoPtr->nMaxTipWidth;
1531
1532     infoPtr->nMaxTipWidth = (INT)lParam;
1533
1534     return nTemp;
1535 }
1536
1537
1538 inline static LRESULT
1539 TOOLTIPS_SetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1540 {
1541     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1542
1543     infoPtr->clrBk = (COLORREF)wParam;
1544
1545     return 0;
1546 }
1547
1548
1549 inline static LRESULT
1550 TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1551 {
1552     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1553
1554     infoPtr->clrText = (COLORREF)wParam;
1555
1556     return 0;
1557 }
1558
1559
1560 static LRESULT
1561 TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1562 {
1563     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1564     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1565     TTTOOL_INFO *toolPtr;
1566     INT nTool;
1567
1568     if (lpToolInfo == NULL)
1569         return 0;
1570     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1571         return 0;
1572
1573     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1574     if (nTool == -1) return 0;
1575
1576     TRACE("tool %d\n", nTool);
1577
1578     toolPtr = &infoPtr->tools[nTool];
1579
1580     /* copy tool data */
1581     toolPtr->uFlags = lpToolInfo->uFlags;
1582     toolPtr->hwnd   = lpToolInfo->hwnd;
1583     toolPtr->uId    = lpToolInfo->uId;
1584     toolPtr->rect   = lpToolInfo->rect;
1585     toolPtr->hinst  = lpToolInfo->hinst;
1586
1587     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1588         TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText);
1589         toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1590     }
1591     else if (lpToolInfo->lpszText) {
1592         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1593             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1594         else {
1595             if ( (toolPtr->lpszText) &&
1596                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1597                 COMCTL32_Free (toolPtr->lpszText);
1598                 toolPtr->lpszText = NULL;
1599             }
1600             if (lpToolInfo->lpszText) {
1601                 INT len = lstrlenA (lpToolInfo->lpszText);
1602                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1603                 lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
1604             }
1605         }
1606     }
1607
1608     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA))
1609         toolPtr->lParam = lpToolInfo->lParam;
1610
1611     return 0;
1612 }
1613
1614
1615 static LRESULT
1616 TOOLTIPS_SetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1617 {
1618     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1619     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1620     TTTOOL_INFO *toolPtr;
1621     INT nTool;
1622
1623     if (lpToolInfo == NULL)
1624         return 0;
1625     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1626         return 0;
1627
1628     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1629     if (nTool == -1) return 0;
1630
1631     TRACE("tool %d\n", nTool);
1632
1633     toolPtr = &infoPtr->tools[nTool];
1634
1635     /* copy tool data */
1636     toolPtr->uFlags = lpToolInfo->uFlags;
1637     toolPtr->hwnd   = lpToolInfo->hwnd;
1638     toolPtr->uId    = lpToolInfo->uId;
1639     toolPtr->rect   = lpToolInfo->rect;
1640     toolPtr->hinst  = lpToolInfo->hinst;
1641
1642     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) {
1643         TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText);
1644         toolPtr->lpszText = lpToolInfo->lpszText;
1645     }
1646     else if (lpToolInfo->lpszText) {
1647         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1648             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1649         else {
1650             if ( (toolPtr->lpszText) &&
1651                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1652                 COMCTL32_Free (toolPtr->lpszText);
1653                 toolPtr->lpszText = NULL;
1654             }
1655             if (lpToolInfo->lpszText) {
1656                 INT len = lstrlenW (lpToolInfo->lpszText);
1657                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1658                 lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1659             }
1660         }
1661     }
1662
1663     if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW))
1664         toolPtr->lParam = lpToolInfo->lParam;
1665
1666     return 0;
1667 }
1668
1669
1670 static LRESULT
1671 TOOLTIPS_TrackActivate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1672 {
1673     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1674     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1675
1676     if (lpToolInfo == NULL)
1677         return 0;
1678     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1679         return FALSE;
1680
1681     if ((BOOL)wParam) {
1682         /* activate */
1683         infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1684         if (infoPtr->nTrackTool != -1) {
1685             TRACE("activated!\n");
1686             infoPtr->bTrackActive = TRUE;
1687             TOOLTIPS_TrackShow (hwnd, infoPtr);
1688         }
1689     }
1690     else {
1691         /* deactivate */
1692         TOOLTIPS_TrackHide (hwnd, infoPtr);
1693
1694         infoPtr->bTrackActive = FALSE;
1695         infoPtr->nTrackTool = -1;
1696
1697         TRACE("deactivated!\n");
1698     }
1699
1700     return 0;
1701 }
1702
1703
1704 static LRESULT
1705 TOOLTIPS_TrackPosition (HWND hwnd, WPARAM wParam, LPARAM lParam)
1706 {
1707     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1708
1709     infoPtr->xTrackPos = (INT)LOWORD(lParam);
1710     infoPtr->yTrackPos = (INT)HIWORD(lParam);
1711
1712     if (infoPtr->bTrackActive) {
1713         TRACE("[%d %d]\n",
1714                infoPtr->xTrackPos, infoPtr->yTrackPos);
1715
1716         TOOLTIPS_TrackShow (hwnd, infoPtr);
1717     }
1718
1719     return 0;
1720 }
1721
1722
1723 static LRESULT
1724 TOOLTIPS_Update (HWND hwnd, WPARAM wParam, LPARAM lParam)
1725 {
1726     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1727
1728     if (infoPtr->nCurrentTool != -1)
1729         UpdateWindow (hwnd);
1730
1731     return 0;
1732 }
1733
1734
1735 static LRESULT
1736 TOOLTIPS_UpdateTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1737 {
1738     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1739     LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam;
1740     TTTOOL_INFO *toolPtr;
1741     INT nTool;
1742
1743     if (lpToolInfo == NULL)
1744         return 0;
1745     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEA)
1746         return FALSE;
1747
1748     nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo);
1749     if (nTool == -1) return 0;
1750
1751     TRACE("tool %d\n", nTool);
1752
1753     toolPtr = &infoPtr->tools[nTool];
1754
1755     /* copy tool text */
1756     toolPtr->hinst  = lpToolInfo->hinst;
1757
1758     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1759         toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText;
1760     }
1761     else if (lpToolInfo->lpszText) {
1762         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA)
1763             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1764         else {
1765             if ( (toolPtr->lpszText) &&
1766                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1767                 COMCTL32_Free (toolPtr->lpszText);
1768                 toolPtr->lpszText = NULL;
1769             }
1770             if (lpToolInfo->lpszText) {
1771                 INT len = lstrlenA (lpToolInfo->lpszText);
1772                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1773                 lstrcpyAtoW (toolPtr->lpszText, lpToolInfo->lpszText);
1774             }
1775         }
1776     }
1777
1778     /* force repaint */
1779     if (infoPtr->bActive)
1780         TOOLTIPS_Show (hwnd, infoPtr);
1781     else if (infoPtr->bTrackActive)
1782         TOOLTIPS_TrackShow (hwnd, infoPtr);
1783
1784     return 0;
1785 }
1786
1787
1788 static LRESULT
1789 TOOLTIPS_UpdateTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1790 {
1791     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1792     LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam;
1793     TTTOOL_INFO *toolPtr;
1794     INT nTool;
1795
1796     if (lpToolInfo == NULL)
1797         return 0;
1798     if (lpToolInfo->cbSize < TTTOOLINFO_V1_SIZEW)
1799         return FALSE;
1800
1801     nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo);
1802     if (nTool == -1)
1803         return 0;
1804
1805     TRACE("tool %d\n", nTool);
1806
1807     toolPtr = &infoPtr->tools[nTool];
1808
1809     /* copy tool text */
1810     toolPtr->hinst  = lpToolInfo->hinst;
1811
1812     if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){
1813         toolPtr->lpszText = lpToolInfo->lpszText;
1814     }
1815     else if (lpToolInfo->lpszText) {
1816         if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW)
1817             toolPtr->lpszText = LPSTR_TEXTCALLBACKW;
1818         else {
1819             if ( (toolPtr->lpszText)  &&
1820                  (HIWORD((INT)toolPtr->lpszText) != 0) ) {
1821                 COMCTL32_Free (toolPtr->lpszText);
1822                 toolPtr->lpszText = NULL;
1823             }
1824             if (lpToolInfo->lpszText) {
1825                 INT len = lstrlenW (lpToolInfo->lpszText);
1826                 toolPtr->lpszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1827                 lstrcpyW (toolPtr->lpszText, lpToolInfo->lpszText);
1828             }
1829         }
1830     }
1831
1832     /* force repaint */
1833     if (infoPtr->bActive)
1834         TOOLTIPS_Show (hwnd, infoPtr);
1835     else if (infoPtr->bTrackActive)
1836         TOOLTIPS_TrackShow (hwnd, infoPtr);
1837
1838     return 0;
1839 }
1840
1841
1842 static LRESULT
1843 TOOLTIPS_WindowFromPoint (HWND hwnd, WPARAM wParam, LPARAM lParam)
1844 {
1845     return WindowFromPoint (*((LPPOINT)lParam));
1846 }
1847
1848
1849
1850 static LRESULT
1851 TOOLTIPS_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1852 {
1853     TOOLTIPS_INFO *infoPtr;
1854     NONCLIENTMETRICSA nclm;
1855     INT nResult;
1856
1857     /* allocate memory for info structure */
1858     infoPtr = (TOOLTIPS_INFO *)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO));
1859     SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1860
1861     /* initialize info structure */
1862     infoPtr->bActive = TRUE;
1863     infoPtr->bTrackActive = FALSE;
1864     infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
1865     infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
1866
1867     nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1868     SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1869     infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
1870
1871     infoPtr->nMaxTipWidth = -1;
1872     infoPtr->nTool = -1;
1873     infoPtr->nOldTool = -1;
1874     infoPtr->nCurrentTool = -1;
1875     infoPtr->nTrackTool = -1;
1876
1877     infoPtr->nAutomaticTime = 500;
1878     infoPtr->nReshowTime    = 100;
1879     infoPtr->nAutoPopTime   = 5000;
1880     infoPtr->nInitialTime   = 500;
1881
1882     nResult = (INT) SendMessageA (GetParent (hwnd), WM_NOTIFYFORMAT,
1883                                   (WPARAM)hwnd, (LPARAM)NF_QUERY);
1884     if (nResult == NFR_ANSI) {
1885         infoPtr->bNotifyUnicode = FALSE;
1886         TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n");
1887     }
1888     else if (nResult == NFR_UNICODE) {
1889         infoPtr->bNotifyUnicode = TRUE;
1890         TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n");
1891     }
1892     else {
1893         ERR (" -- WM_NOTIFYFORMAT returns: error!\n");
1894     }
1895
1896     SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE);
1897
1898     return 0;
1899 }
1900
1901
1902 static LRESULT
1903 TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1904 {
1905     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1906     TTTOOL_INFO *toolPtr;
1907     INT i;
1908
1909     /* free tools */
1910     if (infoPtr->tools) {
1911         for (i = 0; i < infoPtr->uNumTools; i++) {
1912             toolPtr = &infoPtr->tools[i];
1913             if ((toolPtr->hinst) && (toolPtr->lpszText)) {
1914                 if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) &&
1915                      (HIWORD((INT)toolPtr->lpszText) != 0) ) 
1916                 {
1917                     COMCTL32_Free (toolPtr->lpszText);
1918                     toolPtr->lpszText = NULL;
1919                 }
1920             }
1921
1922             /* remove subclassing */
1923             if (toolPtr->uFlags & TTF_SUBCLASS) {
1924                 LPTT_SUBCLASS_INFO lpttsi;
1925
1926                 if (toolPtr->uFlags & TTF_IDISHWND)
1927                     lpttsi = (LPTT_SUBCLASS_INFO)GetPropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
1928                 else
1929                     lpttsi = (LPTT_SUBCLASS_INFO)GetPropA (toolPtr->hwnd, COMCTL32_aSubclass);
1930
1931                 if (lpttsi) {
1932                     SetWindowLongA ((HWND)toolPtr->uId, GWL_WNDPROC,
1933                                       (LONG)lpttsi->wpOrigProc);
1934                     RemovePropA ((HWND)toolPtr->uId, COMCTL32_aSubclass);
1935                     COMCTL32_Free (&lpttsi);
1936                 }
1937             }
1938         }
1939         COMCTL32_Free (infoPtr->tools);
1940     }
1941
1942     /* delete font */
1943     DeleteObject (infoPtr->hFont);
1944
1945     /* free tool tips info data */
1946     COMCTL32_Free (infoPtr);
1947
1948     return 0;
1949 }
1950
1951
1952 static LRESULT
1953 TOOLTIPS_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
1954 {
1955     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1956     RECT rect;
1957     HBRUSH hBrush;
1958
1959     hBrush = CreateSolidBrush (infoPtr->clrBk);
1960     GetClientRect (hwnd, &rect);
1961     FillRect ((HDC)wParam, &rect, hBrush);
1962     DeleteObject (hBrush);
1963
1964     return FALSE;
1965 }
1966
1967
1968 static LRESULT
1969 TOOLTIPS_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
1970 {
1971     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1972
1973     return infoPtr->hFont;
1974 }
1975
1976
1977 static LRESULT
1978 TOOLTIPS_MouseMessage (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1979 {
1980     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
1981
1982     TOOLTIPS_Hide (hwnd, infoPtr);
1983
1984     return 0;
1985 }
1986
1987
1988 static LRESULT
1989 TOOLTIPS_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1990 {
1991     DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1992
1993     dwStyle &= 0x0000FFFF;
1994     dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
1995     SetWindowLongA (hwnd, GWL_STYLE, dwStyle);
1996
1997     return TRUE;
1998 }
1999
2000
2001 static LRESULT
2002 TOOLTIPS_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
2003 {
2004     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2005     INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool;
2006
2007     TRACE(" nTool=%d\n", nTool);
2008
2009     if ((nTool > -1) && (nTool < infoPtr->uNumTools)) {
2010         if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) {
2011             TRACE("-- in transparent mode!\n");
2012             return HTTRANSPARENT;
2013         }
2014     }
2015
2016     return DefWindowProcA (hwnd, WM_NCHITTEST, wParam, lParam);
2017 }
2018
2019
2020 static LRESULT
2021 TOOLTIPS_NotifyFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
2022 {
2023     FIXME ("hwnd=%x wParam=%x lParam=%lx\n", hwnd, wParam, lParam);
2024
2025     return 0;
2026 }
2027
2028
2029 static LRESULT
2030 TOOLTIPS_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
2031 {
2032     HDC hdc;
2033     PAINTSTRUCT ps;
2034
2035     hdc = (wParam == 0) ? BeginPaint (hwnd, &ps) : (HDC)wParam;
2036     TOOLTIPS_Refresh (hwnd, hdc);
2037     if (!wParam)
2038         EndPaint (hwnd, &ps);
2039     return 0;
2040 }
2041
2042
2043 static LRESULT
2044 TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2045 {
2046     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2047
2048     infoPtr->hFont = (HFONT)wParam;
2049
2050     if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) {
2051         FIXME("full redraw needed!\n");
2052     }
2053
2054     return 0;
2055 }
2056 /******************************************************************
2057  * TOOLTIPS_OnWMGetTextLength
2058  *
2059  * This function is called when the tooltip receive a
2060  * WM_GETTEXTLENGTH message.
2061  * wParam : not used
2062  * lParam : not used
2063  *
2064  * returns the length, in characters, of the tip text
2065  ******************************************************************/
2066 static LRESULT
2067 TOOLTIPS_OnWMGetTextLength(HWND hwnd, WPARAM wParam, LPARAM lParam)
2068 {
2069     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2070     return lstrlenW(infoPtr->szTipText);
2071 }
2072
2073 /******************************************************************
2074  * TOOLTIPS_OnWMGetText
2075  *
2076  * This function is called when the tooltip receive a
2077  * WM_GETTEXT message.
2078  * wParam : specifies the maximum number of characters to be copied
2079  * lParam : is the pointer to the buffer that will receive
2080  *          the tip text
2081  *
2082  * returns the number of characters copied
2083  ******************************************************************/
2084 static LRESULT
2085 TOOLTIPS_OnWMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam)
2086 {
2087     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2088     INT length;
2089
2090     if(!infoPtr || !(infoPtr->szTipText))
2091         return 0;
2092
2093     length = lstrlenW(infoPtr->szTipText);
2094     /* When wParam is smaller than the lenght of the tip text
2095        copy wParam characters of the tip text and return wParam */
2096     if(wParam < length)
2097     {
2098         lstrcpynWtoA((LPSTR)lParam, infoPtr->szTipText,(UINT)wParam);
2099         return wParam;
2100     }
2101     lstrcpyWtoA((LPSTR)lParam, infoPtr->szTipText);
2102     return length;
2103 }
2104
2105 static LRESULT
2106 TOOLTIPS_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam)
2107 {
2108     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2109
2110     TRACE("timer %d (%x) expired!\n", wParam, hwnd);
2111
2112     switch (wParam)
2113     {
2114         case ID_TIMERSHOW:
2115             KillTimer (hwnd, ID_TIMERSHOW);
2116             if (TOOLTIPS_CheckTool (hwnd, TRUE) == infoPtr->nTool)
2117                 TOOLTIPS_Show (hwnd, infoPtr);
2118             break;
2119
2120         case ID_TIMERPOP:
2121             TOOLTIPS_Hide (hwnd, infoPtr);
2122             break;
2123
2124         case ID_TIMERLEAVE:
2125             KillTimer (hwnd, ID_TIMERLEAVE);
2126             if (TOOLTIPS_CheckTool (hwnd, FALSE) == -1) {
2127                 infoPtr->nTool = -1;
2128                 infoPtr->nOldTool = -1;
2129                 TOOLTIPS_Hide (hwnd, infoPtr);
2130             }
2131             break;
2132     }
2133     return 0;
2134 }
2135
2136
2137 static LRESULT
2138 TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam)
2139 {
2140     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd);
2141     NONCLIENTMETRICSA nclm;
2142
2143     infoPtr->clrBk   = GetSysColor (COLOR_INFOBK);
2144     infoPtr->clrText = GetSysColor (COLOR_INFOTEXT);
2145
2146     DeleteObject (infoPtr->hFont);
2147     nclm.cbSize = sizeof(NONCLIENTMETRICSA);
2148     SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
2149     infoPtr->hFont = CreateFontIndirectA (&nclm.lfStatusFont);
2150
2151     return 0;
2152 }
2153
2154
2155 LRESULT CALLBACK
2156 TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2157 {
2158     LPTT_SUBCLASS_INFO lpttsi =
2159         (LPTT_SUBCLASS_INFO)GetPropA (hwnd, COMCTL32_aSubclass);
2160     TOOLTIPS_INFO *infoPtr;
2161     UINT nTool;
2162
2163     switch (uMsg) {
2164         case WM_LBUTTONDOWN:
2165         case WM_LBUTTONUP:
2166         case WM_MBUTTONDOWN:
2167         case WM_MBUTTONUP:
2168         case WM_RBUTTONDOWN:
2169         case WM_RBUTTONUP:
2170             infoPtr = TOOLTIPS_GetInfoPtr(lpttsi->hwndToolTip);
2171                 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
2172
2173                 TRACE("subclassed mouse message %04x\n", uMsg);
2174                 infoPtr->nOldTool = infoPtr->nTool;
2175                 infoPtr->nTool = nTool;
2176             TOOLTIPS_Hide (lpttsi->hwndToolTip, infoPtr);
2177             break;
2178
2179         case WM_MOUSEMOVE:
2180             infoPtr = TOOLTIPS_GetInfoPtr (lpttsi->hwndToolTip);
2181                 nTool = TOOLTIPS_GetToolFromMessage (infoPtr, hwnd);
2182
2183                 TRACE("subclassed WM_MOUSEMOVE\n");
2184                 infoPtr->nOldTool = infoPtr->nTool;
2185                 infoPtr->nTool = nTool;
2186
2187                 if ((infoPtr->bActive) &&
2188                     (infoPtr->nTool != infoPtr->nOldTool)) {
2189                     if (infoPtr->nOldTool == -1) {
2190                     SetTimer (hwnd, ID_TIMERSHOW,
2191                                     infoPtr->nInitialTime, 0);
2192                         TRACE("timer 1 started!\n");
2193                     }
2194                     else {
2195                     TOOLTIPS_Hide (lpttsi->hwndToolTip, infoPtr);
2196                     SetTimer (hwnd, ID_TIMERSHOW,
2197                                 infoPtr->nReshowTime, 0);
2198                         TRACE("timer 2 started!\n");
2199                     }
2200                 }
2201                 if (infoPtr->nCurrentTool != -1) {
2202                 SetTimer (hwnd, ID_TIMERLEAVE, 100, 0);
2203                     TRACE("timer 3 started!\n");
2204                 }
2205             break;
2206     }
2207
2208     return CallWindowProcA (lpttsi->wpOrigProc, hwnd, uMsg, wParam, lParam);
2209 }
2210
2211
2212 static LRESULT CALLBACK
2213 TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2214 {
2215     switch (uMsg)
2216     {
2217         case TTM_ACTIVATE:
2218             return TOOLTIPS_Activate (hwnd, wParam, lParam);
2219
2220         case TTM_ADDTOOLA:
2221             return TOOLTIPS_AddToolA (hwnd, wParam, lParam);
2222
2223         case TTM_ADDTOOLW:
2224             return TOOLTIPS_AddToolW (hwnd, wParam, lParam);
2225
2226         case TTM_DELTOOLA:
2227             return TOOLTIPS_DelToolA (hwnd, wParam, lParam);
2228
2229         case TTM_DELTOOLW:
2230             return TOOLTIPS_DelToolW (hwnd, wParam, lParam);
2231
2232         case TTM_ENUMTOOLSA:
2233             return TOOLTIPS_EnumToolsA (hwnd, wParam, lParam);
2234
2235         case TTM_ENUMTOOLSW:
2236             return TOOLTIPS_EnumToolsW (hwnd, wParam, lParam);
2237
2238         case TTM_GETCURRENTTOOLA:
2239             return TOOLTIPS_GetCurrentToolA (hwnd, wParam, lParam);
2240
2241         case TTM_GETCURRENTTOOLW:
2242             return TOOLTIPS_GetCurrentToolW (hwnd, wParam, lParam);
2243
2244         case TTM_GETDELAYTIME:
2245             return TOOLTIPS_GetDelayTime (hwnd, wParam, lParam);
2246
2247         case TTM_GETMARGIN:
2248             return TOOLTIPS_GetMargin (hwnd, wParam, lParam);
2249
2250         case TTM_GETMAXTIPWIDTH:
2251             return TOOLTIPS_GetMaxTipWidth (hwnd, wParam, lParam);
2252
2253         case TTM_GETTEXTA:
2254             return TOOLTIPS_GetTextA (hwnd, wParam, lParam);
2255
2256         case TTM_GETTEXTW:
2257             return TOOLTIPS_GetTextW (hwnd, wParam, lParam);
2258
2259         case TTM_GETTIPBKCOLOR:
2260             return TOOLTIPS_GetTipBkColor (hwnd, wParam, lParam);
2261
2262         case TTM_GETTIPTEXTCOLOR:
2263             return TOOLTIPS_GetTipTextColor (hwnd, wParam, lParam);
2264
2265         case TTM_GETTOOLCOUNT:
2266             return TOOLTIPS_GetToolCount (hwnd, wParam, lParam);
2267
2268         case TTM_GETTOOLINFOA:
2269             return TOOLTIPS_GetToolInfoA (hwnd, wParam, lParam);
2270
2271         case TTM_GETTOOLINFOW:
2272             return TOOLTIPS_GetToolInfoW (hwnd, wParam, lParam);
2273
2274         case TTM_HITTESTA:
2275             return TOOLTIPS_HitTestA (hwnd, wParam, lParam);
2276
2277         case TTM_HITTESTW:
2278             return TOOLTIPS_HitTestW (hwnd, wParam, lParam);
2279
2280         case TTM_NEWTOOLRECTA:
2281             return TOOLTIPS_NewToolRectA (hwnd, wParam, lParam);
2282
2283         case TTM_NEWTOOLRECTW:
2284             return TOOLTIPS_NewToolRectW (hwnd, wParam, lParam);
2285
2286         case TTM_POP:
2287             return TOOLTIPS_Pop (hwnd, wParam, lParam);
2288
2289         case TTM_RELAYEVENT:
2290             return TOOLTIPS_RelayEvent (hwnd, wParam, lParam);
2291
2292         case TTM_SETDELAYTIME:
2293             return TOOLTIPS_SetDelayTime (hwnd, wParam, lParam);
2294
2295         case TTM_SETMARGIN:
2296             return TOOLTIPS_SetMargin (hwnd, wParam, lParam);
2297
2298         case TTM_SETMAXTIPWIDTH:
2299             return TOOLTIPS_SetMaxTipWidth (hwnd, wParam, lParam);
2300
2301         case TTM_SETTIPBKCOLOR:
2302             return TOOLTIPS_SetTipBkColor (hwnd, wParam, lParam);
2303
2304         case TTM_SETTIPTEXTCOLOR:
2305             return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam);
2306
2307         case TTM_SETTOOLINFOA:
2308             return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam);
2309
2310         case TTM_SETTOOLINFOW:
2311             return TOOLTIPS_SetToolInfoW (hwnd, wParam, lParam);
2312
2313         case TTM_TRACKACTIVATE:
2314             return TOOLTIPS_TrackActivate (hwnd, wParam, lParam);
2315
2316         case TTM_TRACKPOSITION:
2317             return TOOLTIPS_TrackPosition (hwnd, wParam, lParam);
2318
2319         case TTM_UPDATE:
2320             return TOOLTIPS_Update (hwnd, wParam, lParam);
2321
2322         case TTM_UPDATETIPTEXTA:
2323             return TOOLTIPS_UpdateTipTextA (hwnd, wParam, lParam);
2324
2325         case TTM_UPDATETIPTEXTW:
2326             return TOOLTIPS_UpdateTipTextW (hwnd, wParam, lParam);
2327
2328         case TTM_WINDOWFROMPOINT:
2329             return TOOLTIPS_WindowFromPoint (hwnd, wParam, lParam);
2330
2331
2332         case WM_CREATE:
2333             return TOOLTIPS_Create (hwnd, wParam, lParam);
2334
2335         case WM_DESTROY:
2336             return TOOLTIPS_Destroy (hwnd, wParam, lParam);
2337
2338         case WM_ERASEBKGND:
2339             return TOOLTIPS_EraseBackground (hwnd, wParam, lParam);
2340
2341         case WM_GETFONT:
2342             return TOOLTIPS_GetFont (hwnd, wParam, lParam);
2343
2344         case WM_GETTEXT:
2345             return TOOLTIPS_OnWMGetText (hwnd, wParam, lParam);
2346         
2347         case WM_GETTEXTLENGTH:
2348             return TOOLTIPS_OnWMGetTextLength (hwnd, wParam, lParam);
2349  
2350
2351         case WM_LBUTTONDOWN:
2352         case WM_LBUTTONUP:
2353         case WM_MBUTTONDOWN:
2354         case WM_MBUTTONUP:
2355         case WM_RBUTTONDOWN:
2356         case WM_RBUTTONUP:
2357         case WM_MOUSEMOVE:
2358             return TOOLTIPS_MouseMessage (hwnd, uMsg, wParam, lParam);
2359
2360         case WM_NCCREATE:
2361             return TOOLTIPS_NCCreate (hwnd, wParam, lParam);
2362
2363         case WM_NCHITTEST:
2364             return TOOLTIPS_NCHitTest (hwnd, wParam, lParam);
2365
2366         case WM_NOTIFYFORMAT:
2367             return TOOLTIPS_NotifyFormat (hwnd, wParam, lParam);
2368
2369         case WM_PAINT:
2370             return TOOLTIPS_Paint (hwnd, wParam, lParam);
2371
2372         case WM_SETFONT:
2373             return TOOLTIPS_SetFont (hwnd, wParam, lParam);
2374
2375         case WM_TIMER:
2376             return TOOLTIPS_Timer (hwnd, wParam, lParam);
2377
2378         case WM_WININICHANGE:
2379             return TOOLTIPS_WinIniChange (hwnd, wParam, lParam);
2380
2381         default:
2382             if (uMsg >= WM_USER)
2383                 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2384                      uMsg, wParam, lParam);
2385             return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2386     }
2387     return 0;
2388 }
2389
2390
2391 VOID
2392 TOOLTIPS_Register (void)
2393 {
2394     WNDCLASSA wndClass;
2395
2396     ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2397     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
2398     wndClass.lpfnWndProc   = (WNDPROC)TOOLTIPS_WindowProc;
2399     wndClass.cbClsExtra    = 0;
2400     wndClass.cbWndExtra    = sizeof(TOOLTIPS_INFO *);
2401     wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
2402     wndClass.hbrBackground = 0;
2403     wndClass.lpszClassName = TOOLTIPS_CLASSA;
2404  
2405     RegisterClassA (&wndClass);
2406 }
2407
2408
2409 VOID
2410 TOOLTIPS_Unregister (void)
2411 {
2412     UnregisterClassA (TOOLTIPS_CLASSA, (HINSTANCE)NULL);
2413 }
2414