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