Changed some treeview related definitions.
[wine] / dlls / comctl32 / tab.c
1 /*
2  * Tab control
3  *
4  * Copyright 1998 Anders Carlsson
5  *
6  * TODO:
7  *  Image list support
8  *  Multiline support
9  *  Unicode support
10  *  Updown control support
11  *  Look and feel
12  *  Messages to be added in commctrl.h
13  *  ...
14  */
15
16 #include "windows.h"
17 #include "commctrl.h"
18 #include "tab.h"
19 #include "win.h"
20 #include "debug.h"
21
22
23 #define TAB_GetInfoPtr(wndPtr) ((TAB_INFO *)wndPtr->wExtra[0])
24
25
26
27
28
29
30 static BOOL32
31 TAB_SendSimpleNotify (WND *wndPtr, UINT32 code)
32 {
33     NMHDR nmhdr;
34
35     nmhdr.hwndFrom = wndPtr->hwndSelf;
36     nmhdr.idFrom = wndPtr->wIDmenu;
37     nmhdr.code = code;
38
39     return (BOOL32) SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
40                                     (WPARAM32) nmhdr.idFrom, (LPARAM) &nmhdr);
41 }
42
43 static LRESULT
44 TAB_GetCurSel (WND *wndPtr)
45 {
46     TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
47  
48     return infoPtr->iSelected;
49 }
50
51
52 static LRESULT
53 TAB_SetCurSel (WND *wndPtr,WPARAM32 wParam)
54 {
55     TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
56         INT32 iItem=(INT32) wParam;
57         INT32 prevItem;
58  
59         prevItem=-1;
60         if ((iItem >= 0) && (iItem < infoPtr->uNumItem)) {
61                 prevItem=infoPtr->iSelected;
62         infoPtr->iSelected=iItem;
63         }
64         return prevItem;
65 }
66
67 static LRESULT
68 TAB_LButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
69 {
70     TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
71     POINT32 pt;
72     RECT32 rect;
73     INT32 iCount;
74
75     pt.x = (INT32)LOWORD(lParam);
76     pt.y = (INT32)HIWORD(lParam);
77
78     GetClientRect32 (wndPtr->hwndSelf, &rect);
79
80     if (PtInRect32 (&rect, pt))
81     {
82         for (iCount = 0; iCount < infoPtr->uNumItem; iCount++) {
83             rect = infoPtr->items[iCount].rect;
84             if (PtInRect32 (&rect, pt)) {
85                 TRACE(tab, "On Tab, item %d\n", iCount);
86                 
87                 if (infoPtr->iSelected != iCount) {
88                         infoPtr->iSelected = iCount;
89
90                         TAB_SendSimpleNotify(wndPtr, TCN_SELCHANGE);
91                 }
92                 
93                 return 0;
94             }
95         }
96     }
97
98     return 0;
99 }
100
101
102 static LRESULT
103 TAB_AdjustRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
104 {
105
106         if (wParam==TRUE) {
107                 FIXME (tab,"Should set display rectangle\n");
108         } else {
109                 FIXME (tab,"Should set window rectangle\n");
110         }
111         
112         return 0;
113 }
114
115 static void 
116 TAB_SetItemBounds (WND *wndPtr)
117 {
118     TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
119     RECT32 rect;
120     HFONT32 hFont, hOldFont;
121     INT32 i, left;
122     SIZE32 size;
123     HDC32 hdc;
124
125     /* FIXME: Is this needed? */
126     GetClientRect32 (wndPtr->hwndSelf, &rect);
127     
128     hdc = GetDC32(wndPtr->hwndSelf); 
129     
130     hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
131     hOldFont = SelectObject32 (hdc, hFont);
132
133     left = rect.left;
134     
135     for (i = 0; i < infoPtr->uNumItem; i++)
136     {
137         infoPtr->items[i].rect.left = left;
138         infoPtr->items[i].rect.top = infoPtr->rect.top;
139
140         GetTextExtentPoint32A(hdc, 
141                              infoPtr->items[i].pszText, 
142                              lstrlen32A(infoPtr->items[i].pszText), &size);
143         infoPtr->items[i].rect.right = left + size.cx+2*5;
144         infoPtr->items[i].rect.bottom = infoPtr->rect.top + 20;
145         TRACE(tab, "TextSize: %i - ", size.cx);
146         TRACE(tab, "Rect: T %i, L %i, B %i, R %i\n", 
147               infoPtr->items[i].rect.top,
148               infoPtr->items[i].rect.left,
149               infoPtr->items[i].rect.bottom,
150               infoPtr->items[i].rect.right);    
151         left += (size.cx + 11);
152     }
153
154     SelectObject32 (hdc, hOldFont);
155     ReleaseDC32 (wndPtr->hwndSelf, hdc);
156 }
157                                  
158 static void
159 TAB_DrawItem (WND *wndPtr, HDC32 hdc, INT32 iItem)
160 {
161     TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
162     TAB_ITEM *pti = &infoPtr->items[iItem];
163     RECT32 r;
164     INT32 oldBkMode;
165    
166     HPEN32      hwPen  = GetSysColorPen32 (COLOR_3DHILIGHT);
167     HPEN32      hbPen  = GetSysColorPen32 (COLOR_BTNSHADOW);
168     HPEN32      hsdPen = GetSysColorPen32 (COLOR_BTNTEXT);
169     HPEN32      htmpPen = (HPEN32)NULL;
170
171     CopyRect32(&r, &pti->rect);
172
173     htmpPen = hwPen;
174     htmpPen = SelectObject32 (hdc, htmpPen);
175     MoveToEx32 (hdc, r.left, r.bottom, NULL);
176     LineTo32 (hdc, r.left, r.top + 2);
177     LineTo32 (hdc, r.left +2, r.top);
178
179     LineTo32 (hdc, r.right -1, r.top);
180     htmpPen = SelectObject32 (hdc, htmpPen);
181
182     htmpPen = SelectObject32 (hdc, hbPen);
183     MoveToEx32 (hdc, r.right-1, r.top, NULL);
184     LineTo32 (hdc,r.right-1, r.bottom-1);
185     hbPen = SelectObject32 (hdc, hsdPen);
186     MoveToEx32 (hdc, r.right, r.top+1, NULL);
187     LineTo32(hdc, r.right,r.bottom);
188     hsdPen = SelectObject32(hdc,htmpPen); 
189
190     oldBkMode = SetBkMode32(hdc, TRANSPARENT);
191     r.left += 3;
192     r.right -= 3;
193     SetTextColor32 (hdc, COLOR_BTNTEXT);
194     DrawText32A(hdc, pti->pszText, lstrlen32A(pti->pszText),
195         &r, DT_LEFT|DT_SINGLELINE|DT_VCENTER);
196     if (oldBkMode != TRANSPARENT)
197         SetBkMode32(hdc, oldBkMode);
198 }
199
200 static void
201 TAB_DrawBorder (WND *wndPtr, HDC32 hdc)
202 {
203     HPEN32 htmPen;
204     HPEN32 hwPen  = GetSysColorPen32 (COLOR_3DHILIGHT);
205     HPEN32 hbPen  = GetSysColorPen32 (COLOR_3DDKSHADOW);
206     HPEN32 hShade = GetSysColorPen32 (COLOR_BTNSHADOW);
207
208     RECT32 rect;
209
210     htmPen = SelectObject32 (hdc, hwPen);
211     GetClientRect32 (wndPtr->hwndSelf, &rect);
212
213     MoveToEx32 (hdc, rect.left, rect.bottom, NULL);
214     LineTo32 (hdc, rect.left, rect.top+20); 
215
216     LineTo32 (hdc, rect.right, rect.top+20);
217
218     hwPen = SelectObject32 (hdc, htmPen);
219     LineTo32 (hdc, rect.right, rect.bottom );
220     LineTo32 (hdc, rect.left, rect.bottom);
221     hbPen = SelectObject32 (hdc, hShade );
222     MoveToEx32 (hdc, rect.right-1, rect.top+20, NULL);
223     LineTo32 (hdc, rect.right-1, rect.bottom-1);
224     LineTo32 (hdc, rect.left, rect.bottom-1);
225     hShade = SelectObject32(hdc, hShade);
226 }
227
228     
229 static void
230 TAB_Refresh (WND *wndPtr, HDC32 hdc)
231 {
232     TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
233     HFONT32 hOldFont;
234     INT32 i;
235
236     TAB_DrawBorder (wndPtr, hdc);
237
238         hOldFont = SelectObject32 (hdc, infoPtr->hFont);
239     for (i = 0; i < infoPtr->uNumItem; i++) {
240         TAB_DrawItem (wndPtr, hdc, i);
241     }
242         SelectObject32 (hdc, hOldFont);
243 }
244
245 static LRESULT
246 TAB_Paint (WND *wndPtr, WPARAM32 wParam)
247 {
248     HDC32 hdc;
249     PAINTSTRUCT32 ps;
250     
251     hdc = wParam== 0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
252     TAB_Refresh (wndPtr, hdc);
253     
254     if(!wParam)
255         EndPaint32 (wndPtr->hwndSelf, &ps);
256     return 0;
257 }
258
259 static LRESULT
260 TAB_InsertItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
261 {
262     TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
263     TCITEM32A *pti;
264     HDC32  hdc;
265     INT32 iItem, len;
266
267     pti = (TCITEM32A *)lParam;
268     iItem = (INT32)wParam;
269
270     if (iItem < 0) return -1;
271     if (iItem > infoPtr->uNumItem)
272         iItem = infoPtr->uNumItem;
273
274     if (infoPtr->uNumItem == 0) {
275         infoPtr->items = COMCTL32_Alloc (sizeof (TAB_ITEM));
276         infoPtr->uNumItem++;
277     }
278     else {
279         TAB_ITEM *oldItems = infoPtr->items;
280
281         infoPtr->uNumItem++;
282         infoPtr->items = COMCTL32_Alloc (sizeof (TAB_ITEM) * infoPtr->uNumItem);
283         
284         /* pre insert copy */
285         if (iItem > 0) {
286             memcpy (&infoPtr->items[0], &oldItems[0],
287                     iItem * sizeof(TAB_ITEM));
288         }
289
290         /* post insert copy */
291         if (iItem < infoPtr->uNumItem - 1) {
292             memcpy (&infoPtr->items[iItem+1], &oldItems[iItem],
293                     (infoPtr->uNumItem - iItem - 1) * sizeof(TAB_ITEM));
294
295         }
296         
297         COMCTL32_Free (oldItems);
298     }
299
300     infoPtr->items[iItem].mask = pti->mask;
301     if (pti->mask & TCIF_TEXT) {
302         len = lstrlen32A (pti->pszText);
303         infoPtr->items[iItem].pszText = COMCTL32_Alloc (len+1);
304         lstrcpy32A (infoPtr->items[iItem].pszText, pti->pszText);
305         infoPtr->items[iItem].cchTextMax = pti->cchTextMax;
306     }
307
308     if (pti->mask & TCIF_IMAGE)
309         infoPtr->items[iItem].iImage = pti->iImage;
310
311     if (pti->mask & TCIF_PARAM)
312         infoPtr->items[iItem].lParam = pti->lParam;
313
314     hdc = GetDC32 (wndPtr->hwndSelf);
315     TAB_Refresh (wndPtr, hdc);
316     ReleaseDC32 (wndPtr->hwndSelf, hdc);
317
318     TRACE(tab, "[%04x]: added item %d '%s'\n",
319                 wndPtr->hwndSelf, iItem, infoPtr->items[iItem].pszText);
320
321     TAB_SetItemBounds(wndPtr);
322     return iItem;
323 }
324
325 static LRESULT 
326 TAB_SetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
327 {
328   TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
329   TCITEM32A *tabItem; 
330   TAB_ITEM *wineItem; 
331   INT32    iItem,len;
332
333   iItem=(INT32) wParam;
334   tabItem=(LPTCITEM32A ) lParam;
335   TRACE (tab,"%d %p\n",iItem, tabItem);
336   if ((iItem<0) || (iItem>infoPtr->uNumItem)) return FALSE;
337
338   wineItem=& infoPtr->items[iItem];
339
340   if (tabItem->mask & TCIF_IMAGE) 
341                 wineItem->iImage=tabItem->iImage;
342
343   if (tabItem->mask & TCIF_PARAM) 
344                 wineItem->lParam=tabItem->lParam;
345
346   if (tabItem->mask & TCIF_RTLREADING) 
347                 FIXME (tab,"TCIF_RTLREADING\n");
348
349   if (tabItem->mask & TCIF_STATE) 
350                 wineItem->dwState=tabItem->dwState;
351
352   if (tabItem->mask & TCIF_TEXT) {
353          len=lstrlen32A (tabItem->pszText);
354          if (len>wineItem->cchTextMax) 
355                  wineItem->pszText= COMCTL32_ReAlloc (wineItem->pszText, len+1);
356          lstrcpyn32A (wineItem->pszText, tabItem->pszText, len);
357   }
358
359         return TRUE;
360 }
361
362 static LRESULT 
363 TAB_GetItemCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
364 {
365    TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
366
367    return infoPtr->uNumItem;
368 }
369
370
371 static LRESULT 
372 TAB_GetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
373 {
374    TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
375    TCITEM32A *tabItem;
376    TAB_ITEM *wineItem;
377    INT32    iItem;
378
379   iItem=(INT32) wParam;
380   tabItem=(LPTCITEM32A) lParam;
381   TRACE (tab,"\n");
382   if ((iItem<0) || (iItem>infoPtr->uNumItem)) return FALSE;
383
384   wineItem=& infoPtr->items[iItem];
385
386   if (tabItem->mask & TCIF_IMAGE) 
387                 tabItem->iImage=wineItem->iImage;
388
389   if (tabItem->mask & TCIF_PARAM) 
390                 tabItem->lParam=wineItem->lParam;
391
392   if (tabItem->mask & TCIF_RTLREADING) 
393                 FIXME (tab, "TCIF_RTLREADING\n");
394
395   if (tabItem->mask & TCIF_STATE) 
396                 tabItem->dwState=wineItem->dwState;
397
398   if (tabItem->mask & TCIF_TEXT) 
399          lstrcpyn32A (tabItem->pszText, wineItem->pszText, tabItem->cchTextMax);
400
401         return TRUE;
402 }
403
404 static LRESULT 
405 TAB_DeleteItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
406 {
407    TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
408
409         FIXME (tab,"stub \n");
410         return TRUE;
411 }
412 static LRESULT 
413 TAB_DeleteAllItems (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
414 {
415    TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
416
417         COMCTL32_Free (infoPtr->items);
418         infoPtr->uNumItem=0;
419         
420         return TRUE;
421 }
422
423
424 static LRESULT
425 TAB_GetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
426 {
427   TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
428
429   TRACE (tab,"\n");
430   return (LRESULT)infoPtr->hFont;
431 }
432
433 static LRESULT
434 TAB_SetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
435
436 {
437  TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
438  TEXTMETRIC32A tm;
439  HFONT32 hFont, hOldFont;
440  HDC32 hdc;
441
442  TRACE (tab,"%x %lx\n",wParam, lParam);
443
444  infoPtr->hFont = (HFONT32)wParam;
445
446  hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
447
448  hdc = GetDC32 (0);
449  hOldFont = SelectObject32 (hdc, hFont);
450  GetTextMetrics32A (hdc, &tm);
451  infoPtr->nHeight= tm.tmHeight + tm.tmExternalLeading;
452  SelectObject32 (hdc, hOldFont);
453
454  if (lParam) TAB_Refresh (wndPtr,hdc);
455  ReleaseDC32 (0, hdc);
456
457  return 0;
458 }
459
460
461 static LRESULT
462 TAB_GetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
463 {
464   TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
465
466   TRACE (tab,"\n");
467   return (LRESULT)infoPtr->himl;
468 }
469
470 static LRESULT
471 TAB_SetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
472 {
473     TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
474     HIMAGELIST himlPrev;
475
476     TRACE (tab,"\n");
477     himlPrev = infoPtr->himl;
478         infoPtr->himl= (HIMAGELIST)lParam;
479     return (LRESULT)himlPrev;
480 }
481
482 static LRESULT 
483 TAB_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
484 {
485     TAB_INFO *infoPtr;
486
487     infoPtr = (TAB_INFO *)COMCTL32_Alloc (sizeof(TAB_INFO));
488     wndPtr->wExtra[0] = (DWORD)infoPtr;
489    
490     infoPtr->uNumItem = 0;
491     infoPtr->hFont = 0;
492     infoPtr->items = 0;
493     infoPtr->hcurArrow = LoadCursor32A (0, IDC_ARROW32A);
494     infoPtr->iSelected = -1;  
495   
496     TRACE(tab, "Created tab control, hwnd [%04x]\n", wndPtr->hwndSelf); 
497     return 0;
498 }
499
500 static LRESULT
501 TAB_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
502 {
503     TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
504     INT32 iItem;
505
506     if (infoPtr->items) {
507         for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) {
508             if (infoPtr->items[iItem].pszText)
509                 COMCTL32_Free (infoPtr->items[iItem].pszText);
510         }
511         COMCTL32_Free (infoPtr->items);
512     }
513
514     COMCTL32_Free (infoPtr);
515  
516     return 0;
517 }
518
519 LRESULT WINAPI
520 TAB_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
521 {
522     WND *wndPtr = WIN_FindWndPtr(hwnd);
523
524     switch (uMsg)
525     {
526
527         case TCM_GETIMAGELIST:
528            return TAB_GetImageList (wndPtr, wParam, lParam);
529
530         case TCM_SETIMAGELIST:
531            return TAB_SetImageList (wndPtr, wParam, lParam);
532         
533         case TCM_GETITEMCOUNT:
534             return TAB_GetItemCount (wndPtr, wParam, lParam);
535
536         case TCM_GETITEM32A:
537            return TAB_GetItem32A (wndPtr, wParam, lParam);
538
539         case TCM_GETITEM32W:
540            FIXME (tab, "Unimplemented msg TCM_GETITEM32W\n");
541            return 0;
542
543         case TCM_SETITEM32A:
544            return TAB_SetItem32A (wndPtr, wParam, lParam);
545
546         case TCM_SETITEM32W:
547            FIXME (tab, "Unimplemented msg TCM_GETITEM32W\n");
548            return 0;
549
550         case TCM_DELETEITEM:
551            return TAB_DeleteItem (wndPtr, wParam, lParam);
552
553         case TCM_DELETEALLITEMS:
554            return TAB_DeleteAllItems (wndPtr, wParam, lParam);
555
556         case TCM_GETITEMRECT:
557            FIXME (tab, "Unimplemented msg TCM_GETITEMRECT\n");
558            return 0;
559
560         case TCM_GETCURSEL:
561            return TAB_GetCurSel (wndPtr);
562
563         case TCM_SETCURSEL:
564            return TAB_SetCurSel (wndPtr, wParam);
565
566         case TCM_INSERTITEM32A:
567            return TAB_InsertItem (wndPtr, wParam, lParam);
568
569         case TCM_INSERTITEM32W:
570            FIXME (tab, "Unimplemented msg TCM_INSERTITEM32W\n");
571            return 0;
572
573         case TCM_SETITEMEXTRA:
574            FIXME (tab, "Unimplemented msg TCM_SETITEMEXTRA\n");
575            return 0;
576
577         case TCM_ADJUSTRECT:
578            return TAB_AdjustRect (wndPtr, wParam, lParam);
579
580         case TCM_SETITEMSIZE:
581            FIXME (tab, "Unimplemented msg TCM_SETITEMSIZE\n");
582            return 0;
583
584         case TCM_REMOVEIMAGE:
585            FIXME (tab, "Unimplemented msg TCM_REMOVEIMAGE\n");
586            return 0;
587
588         case TCM_SETPADDING:
589            FIXME (tab, "Unimplemented msg TCM_SETPADDING\n");
590            return 0;
591
592         case TCM_GETROWCOUNT:
593            FIXME (tab, "Unimplemented msg TCM_GETROWCOUNT\n");
594            return 0;
595
596         case TCM_GETTOOLTIPS:
597            FIXME (tab, "Unimplemented msg TCM_GETTOOLTIPS\n");
598            return 0;
599
600         case TCM_SETTOOLTIPS:
601            FIXME (tab, "Unimplemented msg TCM_SETTOOLTIPS\n");
602            return 0;
603
604         case TCM_GETCURFOCUS:
605            FIXME (tab, "Unimplemented msg TCM_GETCURFOCUS\n");
606            return 0;
607
608         case TCM_SETCURFOCUS:
609            FIXME (tab, "Unimplemented msg TCM_SETCURFOCUS\n");
610            return 0;
611
612         case TCM_SETMINTTABWIDTH:
613            FIXME (tab, "Unimplemented msg TCM_SETMINTTABWIDTH\n");
614            return 0;
615
616         case TCM_DESELECTALL:
617            FIXME (tab, "Unimplemented msg TCM_DESELECTALL\n");
618            return 0;
619
620         case WM_GETFONT:
621             return TAB_GetFont (wndPtr, wParam, lParam);
622
623         case WM_SETFONT:
624             return TAB_SetFont (wndPtr, wParam, lParam);
625
626         case WM_CREATE:
627             return TAB_Create (wndPtr, wParam, lParam);
628
629         case WM_DESTROY:
630             return TAB_Destroy (wndPtr, wParam, lParam);
631
632     case WM_GETDLGCODE:
633             return DLGC_WANTARROWS | DLGC_WANTCHARS;
634
635         case WM_LBUTTONUP:
636             return TAB_LButtonUp (wndPtr, wParam, lParam);
637
638         case WM_PAINT:
639             return TAB_Paint (wndPtr, wParam);
640         
641         
642         default:
643             if (uMsg >= WM_USER)
644                 ERR (tab, "unknown msg %04x wp=%08x lp=%08lx\n",
645                      uMsg, wParam, lParam);
646             return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
647     }
648     return 0;
649 }
650
651
652 VOID
653 TAB_Register (VOID)
654 {
655     WNDCLASS32A wndClass;
656
657     if (GlobalFindAtom32A (WC_TABCONTROL32A)) return;
658
659     ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
660     wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
661     wndClass.lpfnWndProc   = (WNDPROC32)TAB_WindowProc;
662     wndClass.cbClsExtra    = 0;
663     wndClass.cbWndExtra    = sizeof(TAB_INFO *);
664     wndClass.hCursor       = LoadCursor32A (0, IDC_ARROW32A);
665     wndClass.hbrBackground = 0;
666     wndClass.lpszClassName = WC_TABCONTROL32A;
667  
668     RegisterClass32A (&wndClass);
669 }
670
671
672 VOID
673 TAB_Unregister (VOID)
674 {
675     if (GlobalFindAtom32A (WC_TABCONTROL32A))
676         UnregisterClass32A (WC_TABCONTROL32A, (HINSTANCE32)NULL);
677 }
678