Small fixes.
[wine/wine-kai.git] / dlls / comctl32 / tab.c
blob50a3afd1755aa7c893b6c5493ccc09b51b5b460e
1 /*
2 * Tab control
4 * Copyright 1998 Anders Carlsson
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 * ...
16 #include "windows.h"
17 #include "commctrl.h"
18 #include "tab.h"
19 #include "heap.h"
20 #include "win.h"
21 #include "debug.h"
24 #define TAB_GetInfoPtr(wndPtr) ((TAB_INFO *)wndPtr->wExtra[0])
26 static BOOL32
27 TAB_SendSimpleNotify (WND *wndPtr, UINT32 code)
29 NMHDR nmhdr;
31 nmhdr.hwndFrom = wndPtr->hwndSelf;
32 nmhdr.idFrom = wndPtr->wIDmenu;
33 nmhdr.code = code;
35 return (BOOL32) SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
36 (WPARAM32) nmhdr.idFrom, (LPARAM) &nmhdr);
39 static LRESULT
40 TAB_GetCurSel (WND *wndPtr)
42 TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
44 return infoPtr->iSelected;
47 static LRESULT
48 TAB_LButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
50 TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
51 POINT32 pt;
52 RECT32 rect;
53 INT32 iCount;
55 pt.x = (INT32)LOWORD(lParam);
56 pt.y = (INT32)HIWORD(lParam);
58 GetClientRect32 (wndPtr->hwndSelf, &rect);
60 if (PtInRect32 (&rect, pt))
62 for (iCount = 0; iCount < infoPtr->uNumItem; iCount++) {
63 rect = infoPtr->items[iCount].rect;
64 if (PtInRect32 (&rect, pt)) {
65 TRACE(tab, "On Tab, item %d\n", iCount);
67 if (infoPtr->iSelected != iCount) {
68 infoPtr->iSelected = iCount;
70 TAB_SendSimpleNotify(wndPtr, TCN_SELCHANGE);
73 return 0;
78 return 0;
81 static void
82 TAB_SetItemBounds (WND *wndPtr)
84 TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
85 RECT32 rect;
86 HFONT32 hFont, hOldFont;
87 INT32 i, left;
88 SIZE32 size;
89 HDC32 hdc;
91 /* FIXME: Is this needed? */
92 GetClientRect32 (wndPtr->hwndSelf, &rect);
94 hdc = GetDC32(wndPtr->hwndSelf);
96 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
97 hOldFont = SelectObject32 (hdc, hFont);
99 left = rect.left;
101 for (i = 0; i < infoPtr->uNumItem; i++)
103 infoPtr->items[i].rect.left = left;
104 infoPtr->items[i].rect.top = infoPtr->rect.top;
106 GetTextExtentPoint32A(hdc,
107 infoPtr->items[i].pszText,
108 lstrlen32A(infoPtr->items[i].pszText), &size);
109 infoPtr->items[i].rect.right = left + size.cx+2*5;
110 infoPtr->items[i].rect.bottom = infoPtr->rect.top + 20;
111 TRACE(tab, "TextSize: %i - ", size.cx);
112 TRACE(tab, "Rect: T %i, L %i, B %i, R %i\n",
113 infoPtr->items[i].rect.top,
114 infoPtr->items[i].rect.left,
115 infoPtr->items[i].rect.bottom,
116 infoPtr->items[i].rect.right);
117 left += (size.cx + 11);
120 SelectObject32 (hdc, hOldFont);
121 ReleaseDC32 (wndPtr->hwndSelf, hdc);
124 static void
125 TAB_DrawItem (WND *wndPtr, HDC32 hdc, INT32 iItem)
127 TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
128 TAB_ITEM *pti = &infoPtr->items[iItem];
129 RECT32 r;
130 INT32 oldBkMode;
132 HPEN32 hwPen = CreatePen32 (PS_SOLID, 1, RGB (255, 255, 255 ));
133 HPEN32 hbPen = CreatePen32 (PS_SOLID, 1, GetSysColor32 (COLOR_BTNSHADOW));
134 HPEN32 hsdPen = CreatePen32(PS_SOLID, 1, GetSysColor32 (COLOR_BTNTEXT));
135 HPEN32 htmpPen = (HPEN32)NULL;
137 CopyRect32(&r, &pti->rect);
139 htmpPen = hwPen;
140 htmpPen = SelectObject32 (hdc, htmpPen);
141 MoveToEx32 (hdc, r.left, r.bottom, NULL);
142 LineTo32 (hdc, r.left, r.top + 2);
143 LineTo32 (hdc, r.left +2, r.top);
145 LineTo32 (hdc, r.right -1, r.top);
146 htmpPen = SelectObject32 (hdc, htmpPen);
148 htmpPen = SelectObject32 (hdc, hbPen);
149 MoveToEx32 (hdc, r.right-1, r.top, NULL);
150 LineTo32 (hdc,r.right-1, r.bottom-1);
151 hbPen = SelectObject32 (hdc, hsdPen);
152 MoveToEx32 (hdc, r.right, r.top+1, NULL);
153 LineTo32(hdc, r.right,r.bottom);
154 hsdPen = SelectObject32(hdc,htmpPen);
155 DeleteObject32(hwPen);
156 DeleteObject32(hbPen);
157 DeleteObject32(hsdPen);
159 oldBkMode = SetBkMode32(hdc, TRANSPARENT);
160 r.left += 3;
161 r.right -= 3;
162 SetTextColor32 (hdc, COLOR_BTNTEXT);
163 DrawText32A(hdc, pti->pszText, lstrlen32A(pti->pszText),
164 &r, DT_LEFT|DT_SINGLELINE|DT_VCENTER);
165 if (oldBkMode != TRANSPARENT)
166 SetBkMode32(hdc, oldBkMode);
169 static void
170 TAB_DrawBorder (WND *wndPtr, HDC32 hdc)
172 HPEN32 htmPen;
173 HPEN32 hwPen = GetStockObject32(WHITE_PEN);
174 HPEN32 hbPen = GetStockObject32(BLACK_PEN);
175 HPEN32 hShade = CreatePen32 ( PS_SOLID, 1, GetSysColor32 (COLOR_BTNSHADOW));
176 RECT32 rect;
178 htmPen = SelectObject32 (hdc, hwPen);
179 GetClientRect32 (wndPtr->hwndSelf, &rect);
181 MoveToEx32 (hdc, rect.left, rect.bottom, NULL);
182 LineTo32 (hdc, rect.left, rect.top+20);
184 LineTo32 (hdc, rect.right, rect.top+20);
186 hwPen = SelectObject32 (hdc, htmPen);
187 LineTo32 (hdc, rect.right, rect.bottom );
188 LineTo32 (hdc, rect.left, rect.bottom);
189 hbPen = SelectObject32 (hdc, hShade );
190 MoveToEx32 (hdc, rect.right-1, rect.top+20, NULL);
191 LineTo32 (hdc, rect.right-1, rect.bottom-1);
192 LineTo32 (hdc, rect.left, rect.bottom-1);
193 hShade = SelectObject32(hdc, hShade);
194 DeleteObject32 (hShade);
198 static void
199 TAB_Refresh (WND *wndPtr, HDC32 hdc)
201 TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
202 HFONT32 hFont, hOldFont;
203 RECT32 rect;
204 HBRUSH32 hbrBk;
205 INT32 i;
207 TAB_DrawBorder (wndPtr, hdc);
209 for (i = 0; i < infoPtr->uNumItem; i++) {
210 TAB_DrawItem (wndPtr, hdc, i);
215 static LRESULT
216 TAB_Paint (WND *wndPtr, WPARAM32 wParam)
218 HDC32 hdc;
219 PAINTSTRUCT32 ps;
221 hdc = wParam== 0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
222 TAB_Refresh (wndPtr, hdc);
224 if(!wParam)
225 EndPaint32 (wndPtr->hwndSelf, &ps);
226 return 0;
229 static LRESULT
230 TAB_InsertItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
232 TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
233 TCITEM *pti;
234 HDC32 hdc;
235 INT32 iItem, len;
237 pti = (TCITEM*)lParam;
238 iItem = (INT32)wParam;
240 if (iItem < 0) return -1;
241 if (iItem > infoPtr->uNumItem)
242 iItem = infoPtr->uNumItem;
244 if (infoPtr->uNumItem == 0) {
245 infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
246 sizeof (TAB_ITEM));
247 infoPtr->uNumItem++;
249 else {
250 TAB_ITEM *oldItems = infoPtr->items;
252 infoPtr->uNumItem++;
253 infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
254 sizeof (TAB_ITEM) * infoPtr->uNumItem);
256 /* pre insert copy */
257 if (iItem > 0) {
258 memcpy (&infoPtr->items[0], &oldItems[0],
259 iItem * sizeof(TAB_ITEM));
262 /* post insert copy */
263 if (iItem < infoPtr->uNumItem - 1) {
264 memcpy (&infoPtr->items[iItem+1], &oldItems[iItem],
265 (infoPtr->uNumItem - iItem - 1) * sizeof(TAB_ITEM));
269 HeapFree (GetProcessHeap (), 0, oldItems);
272 infoPtr->items[iItem].mask = pti->mask;
273 if (pti->mask & TCIF_TEXT) {
274 len = lstrlen32A (pti->pszText);
275 infoPtr->items[iItem].pszText =
276 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len+1);
277 lstrcpy32A (infoPtr->items[iItem].pszText, pti->pszText);
278 infoPtr->items[iItem].cchTextMax = pti->cchTextMax;
283 if (pti->mask & TCIF_IMAGE)
284 infoPtr->items[iItem].iImage = pti->iImage;
286 if (pti->mask & TCIF_PARAM)
287 infoPtr->items[iItem].lParam = pti->lParam;
289 hdc = GetDC32 (wndPtr->hwndSelf);
290 TAB_Refresh (wndPtr, hdc);
291 ReleaseDC32 (wndPtr->hwndSelf, hdc);
293 TRACE(tab, "[%04x]: added item %d '%s'\n",
294 wndPtr->hwndSelf, iItem, infoPtr->items[iItem].pszText);
296 TAB_SetItemBounds(wndPtr);
297 return iItem;
300 static LRESULT
301 TAB_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
303 TAB_INFO *infoPtr;
305 infoPtr = (TAB_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
306 sizeof(TAB_INFO));
307 wndPtr->wExtra[0] = (DWORD)infoPtr;
309 infoPtr->uNumItem = 0;
310 infoPtr->hFont = 0;
311 infoPtr->items = 0;
312 infoPtr->hcurArrow = LoadCursor32A (0, IDC_ARROW32A);
313 infoPtr->iSelected = -1;
315 TRACE(tab, "Created tab control, hwnd [%04x]\n", wndPtr->hwndSelf);
316 return 0;
319 static LRESULT
320 TAB_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
322 TAB_INFO *infoPtr = TAB_GetInfoPtr(wndPtr);
323 INT32 iItem;
325 if (infoPtr->items) {
326 for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) {
327 if (infoPtr->items[iItem].pszText)
328 HeapFree (GetProcessHeap (), 0, infoPtr->items[iItem].pszText);
330 HeapFree (GetProcessHeap (), 0, infoPtr->items);
333 HeapFree (GetProcessHeap (), 0, infoPtr);
335 return 0;
338 LRESULT WINAPI
339 TAB_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
341 WND *wndPtr = WIN_FindWndPtr(hwnd);
343 switch (uMsg)
346 case TCM_GETCURSEL:
347 return TAB_GetCurSel (wndPtr);
349 case TCM_INSERTITEM:
350 return TAB_InsertItem (wndPtr, wParam, lParam);
352 case WM_CREATE:
353 return TAB_Create (wndPtr, wParam, lParam);
355 case WM_DESTROY:
356 return TAB_Destroy (wndPtr, wParam, lParam);
358 case WM_LBUTTONUP:
359 return TAB_LButtonUp (wndPtr, wParam, lParam);
360 case WM_PAINT:
361 return TAB_Paint (wndPtr, wParam);
364 default:
365 if (uMsg >= WM_USER)
366 ERR (tab, "unknown msg %04x wp=%08x lp=%08lx\n",
367 uMsg, wParam, lParam);
368 return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
370 return 0;
374 void
375 TAB_Register (void)
377 WNDCLASS32A wndClass;
379 if (GlobalFindAtom32A (WC_TABCONTROL32A)) return;
381 ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
382 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
383 wndClass.lpfnWndProc = (WNDPROC32)TAB_WindowProc;
384 wndClass.cbClsExtra = 0;
385 wndClass.cbWndExtra = sizeof(TAB_INFO *);
386 wndClass.hCursor = LoadCursor32A (0, IDC_ARROW32A);
387 wndClass.hbrBackground = 0;
388 wndClass.lpszClassName = WC_TABCONTROL32A;
390 RegisterClass32A (&wndClass);