Release 980712
[wine.git] / controls / tooltips.c
blob3efcf87c032d3694a3849f4b6737ab0f6ffe374c
1 /*
2 * Tool tip control
4 * Copyright 1998 Eric Kohl
6 * NOTES
7 * PLEASE don't try to improve or change this code right now. Many
8 * features are still missing, but I'm working on it. I want to avoid
9 * any confusion. This note will be removed as soon as most of the
10 * features are implemented.
11 * Eric <ekohl@abo.rhein-zeitung.de>
13 * TODO:
14 * - Most messages.
15 * - All notifications.
17 * Testing:
18 * - Run tests using Waite Group Windows95 API Bible Volume 2.
19 * The second cdrom contains executables enumtools.exe ...
20 * - additional features.
22 * FIXME:
23 * - DelTool32A incomplete.
24 * - GetCurrentTool32A incomplete.
27 #include "windows.h"
28 #include "commctrl.h"
29 #include "tooltips.h"
30 #include "heap.h"
31 #include "win.h"
32 #include "debug.h"
35 #define TOOLTIPS_GetInfoPtr(wndPtr) ((TOOLTIPS_INFO *)wndPtr->wExtra[0])
38 static INT32
39 TOOLTIPS_GetIndexFromInfoA (TOOLTIPS_INFO *infoPtr, LPTOOLINFOA lpToolInfo)
41 TTTOOL_INFO *toolPtr;
42 INT32 nIndex;
44 for (nIndex = 0; nIndex < infoPtr->uNumTools; nIndex++) {
45 toolPtr = &infoPtr->tools[nIndex];
47 if ((lpToolInfo->hwnd == toolPtr->hwnd) &&
48 (lpToolInfo->uId == toolPtr->uId))
49 return nIndex;
52 return -1;
56 static INT32
57 TOOLTIPS_GetIndexFromPoint (TOOLTIPS_INFO *infoPtr, LPPOINT32 lpPt)
59 TTTOOL_INFO *toolPtr;
60 INT32 nIndex;
62 for (nIndex = 0; nIndex < infoPtr->uNumTools; nIndex++) {
63 toolPtr = &infoPtr->tools[nIndex];
65 if (lpToolInfo->uFlags & TTF_IDISHWND) {
66 if (PtInRect (
68 else {
70 return nIndex;
74 return -1;
78 static LRESULT
79 TOOLTIPS_Activate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
81 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
83 infoPtr->bActive = (BOOL32)wParam;
85 if (infoPtr->bActive) {
86 FIXME (tooltips, "activated!\n");
88 else {
89 FIXME (tooltips, "deactivated!\n");
92 return 0;
96 static LRESULT
97 TOOLTIPS_AddTool32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
99 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
100 LPTOOLINFOA lpToolInfo = (LPTOOLINFOA)lParam;
101 TTTOOL_INFO *toolPtr;
103 if (lpToolInfo == NULL) return FALSE;
105 if (infoPtr->uNumTools == 0) {
106 infoPtr->tools =
107 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
108 sizeof(TTTOOL_INFO));
109 toolPtr = infoPtr->tools;
111 else {
112 TTTOOL_INFO *oldTools = infoPtr->tools;
113 infoPtr->tools =
114 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
115 sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
116 memcpy (infoPtr->tools, oldTools,
117 infoPtr->uNumTools * sizeof(TTTOOL_INFO));
118 HeapFree (GetProcessHeap (), 0, oldTools);
119 toolPtr = &infoPtr->tools[infoPtr->uNumTools];
122 infoPtr->uNumTools++;
124 /* copy tool data */
125 toolPtr->uFlags = lpToolInfo->uFlags;
126 toolPtr->hwnd = lpToolInfo->hwnd;
127 toolPtr->uId = lpToolInfo->uId;
128 toolPtr->rect = lpToolInfo->rect;
129 toolPtr->hinst = lpToolInfo->hinst;
131 if (lpToolInfo->hinst) {
132 toolPtr->lpszText = lpToolInfo->lpszText;
134 else if (lpToolInfo->lpszText) {
135 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACK32A)
136 toolPtr->lpszText = lpToolInfo->lpszText;
137 else {
138 INT32 len = lstrlen32A (lpToolInfo->lpszText);
139 toolPtr->lpszText =
140 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
141 lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
145 if (lpToolInfo->cbSize >= sizeof(TOOLINFOA))
146 toolPtr->lParam = lpToolInfo->lParam;
149 return TRUE;
153 // << TOOLTIPS_AddTool32W >>
156 static LRESULT
157 TOOLTIPS_DelTool32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
159 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
160 LPTOOLINFOA lpToolInfo = (LPTOOLINFOA)lParam;
161 TTTOOL_INFO *toolPtr;
162 INT32 nIndex;
164 if (lpToolInfo == NULL) return 0;
165 if (infoPtr->uNumTools == 0) return 0;
167 nIndex = TOOLTIPS_GetIndexFromInfoA (infoPtr, lpToolInfo);
168 if (nIndex == -1) return 0;
170 TRACE (tooltips, "index=%d\n", nIndex);
173 /* delete tool from tool list */
175 toolPtr = &infoPtr->tools[nIndex];
177 // delete text string
178 if ((toolPtr->hinst) && (toolPtr->lpszText)) {
179 if (toolPtr->lpszText != LPSTR_TEXTCALLBACK32A)
180 HeapFree (GetProcessHeap (), 0, toolPtr->lpszText);
185 return 0;
189 // << TOOLTIPS_DelTool32W >>
192 static LRESULT
193 TOOLTIPS_EnumTools32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
195 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
196 UINT32 uIndex = (UINT32)wParam;
197 LPTOOLINFOA lpToolInfo = (LPTOOLINFOA)lParam;
198 TTTOOL_INFO *toolPtr;
200 if (uIndex >= infoPtr->uNumTools) return FALSE;
201 if (lpToolInfo == NULL) return FALSE;
203 TRACE (tooltips, "index=%u\n", uIndex);
205 toolPtr = &infoPtr->tools[uIndex];
207 /* copy tool data */
208 lpToolInfo->uFlags = toolPtr->uFlags;
209 lpToolInfo->hwnd = toolPtr->hwnd;
210 lpToolInfo->uId = toolPtr->uId;
211 lpToolInfo->rect = toolPtr->rect;
212 lpToolInfo->hinst = toolPtr->hinst;
213 lpToolInfo->lpszText = toolPtr->lpszText;
215 if (lpToolInfo->cbSize >= sizeof(TOOLINFOA))
216 lpToolInfo->lParam = toolPtr->lParam;
218 return TRUE;
222 // << TOOLTIPS_EnumTools32W >>
225 static LRESULT
226 TOOLTIPS_GetCurrentTool32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
228 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
229 LPTOOLINFOA lpti = (LPTOOLINFOA)lParam;
231 if (lpti) {
232 if (infoPtr->iCurrentTool > -1) {
233 /* FIXME */
235 return TRUE;
237 else
238 return FALSE;
240 else
241 return (infoPtr->iCurrentTool != -1);
243 return FALSE;
247 // << TOOLTIPS_GetCurrentTool32W >>
248 // << TOOLTIPS_GetDelayTime >>
249 // << TOOLTIPS_GetMargin >>
252 static LRESULT
253 TOOLTIPS_GetMaxTipWidth (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
255 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
257 return infoPtr->iMaxTipWidth;
261 static LRESULT
262 TOOLTIPS_GetText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
264 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
265 LPTOOLINFOA lpti = (LPTOOLINFOA)lParam;
266 INT32 nIndex;
268 if (!(lpti)) return 0;
269 if (lpti->cbSize < sizeof(TOOLINFOA)) return 0;
271 nIndex = TOOLTIPS_GetIndexFromInfoA (infoPtr, lpti);
272 if (nIndex == -1) return 0;
274 lstrcpy32A (lpti->lpszText, infoPtr->tools[nIndex].lpszText);
276 return 0;
280 // << TOOLTIPS_GetText32W >>
283 static LRESULT
284 TOOLTIPS_GetTipBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
286 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
287 return infoPtr->clrBk;
291 static LRESULT
292 TOOLTIPS_GetTipTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
294 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
295 return infoPtr->clrText;
299 static LRESULT
300 TOOLTIPS_GetToolCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
302 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
303 return infoPtr->uNumTools;
307 static LRESULT
308 TOOLTIPS_GetToolInfo32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
310 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
311 LPTOOLINFOA lpToolInfo = (LPTOOLINFOA)lParam;
312 TTTOOL_INFO *toolPtr;
313 INT32 nIndex;
315 if (lpToolInfo == NULL) return FALSE;
316 if (infoPtr->uNumTools == 0) return FALSE;
318 nIndex = TOOLTIPS_GetIndexFromInfoA (infoPtr, lpToolInfo);
319 if (nIndex == -1) return FALSE;
321 TRACE (tooltips, "index=%d\n", nIndex);
323 toolPtr = &infoPtr->tools[nIndex];
325 /* copy tool data */
326 lpToolInfo->uFlags = toolPtr->uFlags;
327 lpToolInfo->rect = toolPtr->rect;
328 lpToolInfo->hinst = toolPtr->hinst;
329 lpToolInfo->lpszText = toolPtr->lpszText;
331 if (lpToolInfo->cbSize >= sizeof(TOOLINFOA))
332 lpToolInfo->lParam = toolPtr->lParam;
334 return TRUE;
338 // << TOOLTIPS_GetToolInfo32W >>
339 // << TOOLTIPS_HitTest32A >>
340 // << TOOLTIPS_HitTest32W >>
343 static LRESULT
344 TOOLTIPS_NewToolRect32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
346 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
347 LPTOOLINFOA lpti = (LPTOOLINFOA)lParam;
348 INT32 nIndex;
350 if (!(lpti)) return 0;
351 if (lpti->cbSize < sizeof(TOOLINFOA)) return 0;
353 nIndex = TOOLTIPS_GetIndexFromInfoA (infoPtr, lpti);
354 if (nIndex == -1) return 0;
356 infoPtr->tools[nIndex].rect = lpti->rect;
358 return 0;
362 // << TOOLTIPS_NewToolRect32W >>
363 // << TOOLTIPS_Pop >>
366 static LRESULT
367 TOOLTIPS_RelayEvent (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
369 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
370 LPMSG16 lpMsg = (LPMSG16)lParam;
372 if (lpMsg == NULL) return 0;
374 if (lpMsg->message == WM_MOUSEMOVE) {
375 FIXME (tooltips, "WM_MOUSEMOVE (%d %d)\n", lpMsg->pt.x, lpMsg->pt.y);
378 // FIXME (tooltips, "empty stub!\n");
380 return 0;
384 // << TOOLTIPS_SetDelayTime >>
385 // << TOOLTIPS_SetMargin >>
388 static LRESULT
389 TOOLTIPS_SetMaxTipWidth (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
391 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
392 INT32 iTemp = infoPtr->iMaxTipWidth;
394 infoPtr->iMaxTipWidth = (INT32)lParam;
396 return iTemp;
400 static LRESULT
401 TOOLTIPS_SetTipBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
403 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
405 infoPtr->clrBk = (COLORREF)wParam;
407 return 0;
411 static LRESULT
412 TOOLTIPS_SetTipTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
414 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
416 infoPtr->clrText = (COLORREF)wParam;
418 return 0;
422 static LRESULT
423 TOOLTIPS_SetToolInfo32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
425 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
426 LPTOOLINFOA lpToolInfo = (LPTOOLINFOA)lParam;
427 TTTOOL_INFO *toolPtr;
428 INT32 nIndex;
430 if (lpToolInfo == NULL) return 0;
432 nIndex = TOOLTIPS_GetIndexFromInfoA (infoPtr, lpToolInfo);
433 if (nIndex == -1) return 0;
435 TRACE (tooltips, "index=%d\n", nIndex);
437 toolPtr = &infoPtr->tools[nIndex];
439 /* copy tool data */
440 toolPtr->uFlags = lpToolInfo->uFlags;
441 toolPtr->hwnd = lpToolInfo->hwnd;
442 toolPtr->uId = lpToolInfo->uId;
443 toolPtr->rect = lpToolInfo->rect;
444 toolPtr->hinst = lpToolInfo->hinst;
446 if (lpToolInfo->lpszText) {
447 if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACK32A)
448 toolPtr->lpszText = lpToolInfo->lpszText;
449 else {
450 INT32 len = lstrlen32A (lpToolInfo->lpszText);
451 HeapFree (GetProcessHeap (), 0, toolPtr->lpszText);
452 toolPtr->lpszText =
453 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
454 lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
458 if (lpToolInfo->cbSize >= sizeof(TOOLINFOA))
459 toolPtr->lParam = lpToolInfo->lParam;
461 return 0;
465 // << TOOLTIPS_SetToolInfo32W >>
466 // << TOOLTIPS_TrackActive >>
467 // << TOOLTIPS_TrackPosition >>
468 // << TOOLTIPS_Update >>
469 // << TOOLTIPS_UpdateTipText32A >>
470 // << TOOLTIPS_UpdateTipText32W >>
471 // << TOOLTIPS_WindowFromPoint >>
474 static LRESULT
475 TOOLTIPS_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
477 TOOLTIPS_INFO *infoPtr;
479 /* allocate memory for info structure */
480 infoPtr = (TOOLTIPS_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
481 sizeof(TOOLTIPS_INFO));
482 wndPtr->wExtra[0] = (DWORD)infoPtr;
484 if (infoPtr == NULL) {
485 ERR (tooltips, "could not allocate info memory!\n");
486 return 0;
489 /* initialize info structure */
490 infoPtr->bActive = TRUE;
491 infoPtr->clrBk = GetSysColor32 (COLOR_INFOBK);
492 infoPtr->clrText = GetSysColor32 (COLOR_INFOTEXT);
493 infoPtr->hFont = NULL;
494 infoPtr->iMaxTipWidth = -1;
495 infoPtr->iCurrentTool = -1;
497 return 0;
501 static LRESULT
502 TOOLTIPS_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
504 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
507 /* free tools */
508 if (infoPtr->tools) {
509 INT32 i;
510 for (i = 0; i < infoPtr->uNumTools; i++) {
511 if ((infoPtr->tools[i].hinst) && (infoPtr->tools[i].lpszText)) {
512 if (infoPtr->tools[i].lpszText != LPSTR_TEXTCALLBACK32A)
513 HeapFree (GetProcessHeap (), 0, infoPtr->tools[i].lpszText);
516 HeapFree (GetProcessHeap (), 0, infoPtr->tools);
519 /* free tool tips info data */
520 HeapFree (GetProcessHeap (), 0, infoPtr);
522 return 0;
526 static LRESULT
527 TOOLTIPS_GetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
529 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
531 return infoPtr->hFont;
535 // << TOOLTIPS_MouseMove >>
536 // << TOOLTIPS_Paint >>
539 static LRESULT
540 TOOLTIPS_SetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
542 TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
544 infoPtr->hFont = (HFONT32)wParam;
546 if (LOWORD(lParam)) {
547 /* redraw */
551 return 0;
555 // << TOOLTIPS_Timer >>
556 // << TOOLTIPS_WinIniChange >>
559 LRESULT WINAPI
560 ToolTipsWindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
562 WND *wndPtr = WIN_FindWndPtr(hwnd);
564 switch (uMsg)
566 case TTM_ACTIVATE:
567 return TOOLTIPS_Activate (wndPtr, wParam, lParam);
569 case TTM_ADDTOOL32A:
570 return TOOLTIPS_AddTool32A (wndPtr, wParam, lParam);
572 // case TTM_ADDTOOL32W:
574 case TTM_DELTOOL32A:
575 return TOOLTIPS_DelTool32A (wndPtr, wParam, lParam);
577 // case TTM_DELTOOL32W:
579 case TTM_ENUMTOOLS32A:
580 return TOOLTIPS_EnumTools32A (wndPtr, wParam, lParam);
582 // case TTM_ENUMTOOLS32W:
584 case TTM_GETCURRENTTOOL32A:
585 return TOOLTIPS_GetCurrentTool32A (wndPtr, wParam, lParam);
587 // case TTM_GETCURRENTTOOL32W:
588 // case TTM_GETDELAYTIME: /* 4.70 */
589 // case TTM_GETMARGIN: /* 4.70 */
591 case TTM_GETMAXTIPWIDTH:
592 return TOOLTIPS_GetMaxTipWidth (wndPtr, wParam, lParam);
594 case TTM_GETTEXT32A:
595 return TOOLTIPS_GetText32A (wndPtr, wParam, lParam);
597 // case TTM_GETTEXT32W:
599 case TTM_GETTIPBKCOLOR:
600 return TOOLTIPS_GetTipBkColor (wndPtr, wParam, lParam);
602 case TTM_GETTIPTEXTCOLOR:
603 return TOOLTIPS_GetTipTextColor (wndPtr, wParam, lParam);
605 case TTM_GETTOOLCOUNT:
606 return TOOLTIPS_GetToolCount (wndPtr, wParam, lParam);
608 case TTM_GETTOOLINFO32A:
609 return TOOLTIPS_GetToolInfo32A (wndPtr, wParam, lParam);
611 // case TTM_GETTOOLINFO32W:
612 // case TTM_HITTEST32A:
613 // case TTM_HITTEST32W:
615 case TTM_NEWTOOLRECT32A:
616 return TOOLTIPS_NewToolRect32A (wndPtr, wParam, lParam);
618 // case TTM_NEWTOOLRECT32W:
619 // case TTM_POP: /* 4.70 */
621 case TTM_RELAYEVENT:
622 return TOOLTIPS_RelayEvent (wndPtr, wParam, lParam);
624 // case TTM_SETDELAYTIME: /* 4.70 */
625 // case TTM_SETMARGIN: /* 4.70 */
627 case TTM_SETMAXTIPWIDTH:
628 return TOOLTIPS_SetMaxTipWidth (wndPtr, wParam, lParam);
630 case TTM_SETTIPBKCOLOR:
631 return TOOLTIPS_SetTipBkColor (wndPtr, wParam, lParam);
633 case TTM_SETTIPTEXTCOLOR:
634 return TOOLTIPS_SetTipTextColor (wndPtr, wParam, lParam);
636 case TTM_SETTOOLINFO32A:
637 return TOOLTIPS_SetToolInfo32A (wndPtr, wParam, lParam);
639 // case TTM_SETTOOLINFO32W:
640 // case TTM_TRACKACTIVE: /* 4.70 */
641 // case TTM_TRACKPOSITION: /* 4.70 */
642 // case TTM_UPDATE: /* 4.71 */
643 // case TTM_UPDATETIPTEXT32A:
644 // case TTM_UPDATETIPTEXT32W:
645 // case TTM_WINDOWFROMPOINT:
648 case WM_CREATE:
649 return TOOLTIPS_Create (wndPtr, wParam, lParam);
651 case WM_DESTROY:
652 return TOOLTIPS_Destroy (wndPtr, wParam, lParam);
654 case WM_GETFONT:
655 return TOOLTIPS_GetFont (wndPtr, wParam, lParam);
657 // case WM_MOUSEMOVE:
658 // return TOOLTIPS_MouseMove (wndPtr, wParam, lParam);
660 // case WM_PAINT:
661 // return TOOLTIPS_Paint (wndPtr, wParam);
663 case WM_SETFONT:
664 return TOOLTIPS_SetFont (wndPtr, wParam, lParam);
666 // case WM_TIMER:
668 // case WM_WININICHANGE:
670 default:
671 if (uMsg >= WM_USER)
672 ERR (tooltips, "unknown msg %04x wp=%08x lp=%08lx\n",
673 uMsg, wParam, lParam);
674 return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
676 return 0;
680 void
681 TOOLTIPS_Register (void)
683 WNDCLASS32A wndClass;
685 if (GlobalFindAtom32A (TOOLTIPS_CLASS32A)) return;
687 ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
688 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
689 wndClass.lpfnWndProc = (WNDPROC32)ToolTipsWindowProc;
690 wndClass.cbClsExtra = 0;
691 wndClass.cbWndExtra = sizeof(TOOLTIPS_INFO *);
692 wndClass.hCursor = LoadCursor32A (0, IDC_ARROW32A);
693 wndClass.hbrBackground = 0;
694 wndClass.lpszClassName = TOOLTIPS_CLASS32A;
696 RegisterClass32A (&wndClass);