Optimized include/*.h: (recursively) include all headers needed by
[wine/testsucceed.git] / dlls / comctl32 / treeview.c
blob63d283374050e0261a39e20a84cde751096906b7
1 /* Treeview control
3 * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
4 * Copyright 1998,1999 Alex Priem <alexp@sci.kun.nl>
7 * TODO:
8 * list-handling stuff: sort, sorted insertitem.
9 * [should be merged with mm-handling stuff as done in listview]
10 * refreshtreeview:
11 -small array containing info about positions.
12 -better implementation of RefreshItem:
13 1) draw lines between parents
14 2) draw items
15 3) draw lines from parent<->items.
16 -implement partial drawing?
17 * -drag&drop: TVM_CREATEDRAGIMAGE should create drag bitmap.
18 * -scrollbars: horizontal scrollbar doesn't work.
19 * -Unicode messages
20 * -check custom draw
21 * -I_CHILDRENCALLBACK
22 * FIXME: check fontsize. (uRealItemHeight)
23 * test focusItem (redraw in different color)
24 uHotItem
25 Edit: needs timer
26 better implementation.
27 * WM_HSCROLL is broken.
28 * use separate routine to get item text/image.
30 * Separate drawing/calculation.
32 * FIXMEs (for personal use)
33 Expand: -ctlmacro expands twice ->toggle.
34 -DblClick: ctlmacro.exe's NM_DBLCLK seems to go wrong (returns FALSE).
35 -treehelper: stack corruption makes big window.
40 #include <string.h>
41 #include "winbase.h"
42 #include "commctrl.h"
43 #include "treeview.h"
44 #include "win.h"
45 #include "debug.h"
47 /* ffs should be in <string.h>. */
49 /* Defines, since they do not need to return previous state, and nr
50 * has no side effects in this file.
52 #define tv_test_bit(nr,bf) (((LPBYTE)bf)[nr>>3]&(1<<(nr&7)))
53 #define tv_set_bit(nr,bf) ((LPBYTE)bf)[nr>>3]|=(1<<(nr&7))
54 #define tv_clear_bit(nr,bf) ((LPBYTE)bf)[nr>>3]&=~(1<<(nr&7))
57 #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
59 static BOOL32
60 TREEVIEW_SendSimpleNotify (WND *wndPtr, UINT32 code);
61 static BOOL32
62 TREEVIEW_SendTreeviewNotify (WND *wndPtr, UINT32 code, UINT32 action,
63 HTREEITEM oldItem, HTREEITEM newItem);
64 static BOOL32
65 TREEVIEW_SendTreeviewDnDNotify (WND *wndPtr, UINT32 code, HTREEITEM dragItem,
66 POINT32 pt);
67 static BOOL32
68 TREEVIEW_SendDispInfoNotify (WND *wndPtr, TREEVIEW_ITEM *wineItem,
69 UINT32 code, UINT32 what);
70 static BOOL32
71 TREEVIEW_SendCustomDrawNotify (WND *wndPtr, DWORD dwDrawStage, HDC32 hdc,
72 RECT32 rc);
73 static BOOL32
74 TREEVIEW_SendCustomDrawItemNotify (WND *wndPtr, HDC32 hdc,
75 TREEVIEW_ITEM *tvItem, UINT32 uItemDrawState);
76 static LRESULT
77 TREEVIEW_DoSelectItem (WND *wndPtr, INT32 action, HTREEITEM newSelect, INT32 cause);
78 static void
79 TREEVIEW_Refresh (WND *wndPtr);
81 static LRESULT CALLBACK
82 TREEVIEW_Edit_SubclassProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam,
83 LPARAM lParam);
89 /* helper functions. Work with the assumption that validity of operands
90 is checked beforehand, and that tree state is valid. */
92 /* FIXME: MS documentation says `GetNextVisibleItem' returns NULL
93 if not succesfull'. Probably only applies to derefencing infoPtr
94 (ie we are offered a valid treeview structure)
95 and not whether there is a next `visible' child.
96 FIXME: check other failures.
101 static TREEVIEW_ITEM *
102 TREEVIEW_ValidItem (TREEVIEW_INFO *infoPtr,HTREEITEM handle)
105 if ((!handle) || (handle>infoPtr->uMaxHandle)) return NULL;
106 if (tv_test_bit ((INT32)handle, infoPtr->freeList)) return NULL;
108 return & infoPtr->items[(INT32)handle];
113 static TREEVIEW_ITEM *TREEVIEW_GetPrevListItem (TREEVIEW_INFO *infoPtr,
114 TREEVIEW_ITEM *tvItem)
117 TREEVIEW_ITEM *wineItem;
119 if (tvItem->upsibling) {
120 wineItem=& infoPtr->items[(INT32)tvItem->upsibling];
121 if ((wineItem->firstChild) && (wineItem->state & TVIS_EXPANDED)) {
122 wineItem=& infoPtr->items[(INT32)wineItem->firstChild];
123 while (wineItem->sibling)
124 wineItem= & infoPtr->items[(INT32)wineItem->sibling];
126 return wineItem;
129 wineItem=tvItem;
130 while (wineItem->parent) {
131 wineItem=& infoPtr->items[(INT32)wineItem->parent];
132 if (wineItem->upsibling)
133 return (& infoPtr->items[(INT32)wineItem->upsibling]);
136 return wineItem;
140 static TREEVIEW_ITEM *TREEVIEW_GetNextListItem (TREEVIEW_INFO *infoPtr,
141 TREEVIEW_ITEM *tvItem)
144 TREEVIEW_ITEM *wineItem;
146 if ((tvItem->firstChild) && (tvItem->state & TVIS_EXPANDED))
147 return (& infoPtr->items[(INT32)tvItem->firstChild]);
150 if (tvItem->sibling)
151 return (& infoPtr->items[(INT32)tvItem->sibling]);
153 wineItem=tvItem;
154 while (wineItem->parent) {
155 wineItem=& infoPtr->items [(INT32)wineItem->parent];
156 if (wineItem->sibling)
157 return (& infoPtr->items [(INT32)wineItem->sibling]);
160 return NULL; /* was wineItem */
163 static TREEVIEW_ITEM *TREEVIEW_GetLastListItem (TREEVIEW_INFO *infoPtr,
164 TREEVIEW_ITEM *tvItem)
167 TREEVIEW_ITEM *wineItem;
169 wineItem=tvItem;
170 while (wineItem->sibling)
171 wineItem=& infoPtr->items [(INT32)wineItem->sibling];
173 return wineItem;
177 static void TREEVIEW_RemoveAllChildren (WND *wndPtr,
178 TREEVIEW_ITEM *parentItem)
181 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
182 TREEVIEW_ITEM *killItem;
183 INT32 kill;
185 kill=(INT32)parentItem->firstChild;
186 while (kill) {
187 tv_set_bit ( kill, infoPtr->freeList);
188 killItem=& infoPtr->items[kill];
189 if (killItem->pszText!=LPSTR_TEXTCALLBACK32A)
190 COMCTL32_Free (killItem->pszText);
191 TREEVIEW_SendTreeviewNotify (wndPtr, TVN_DELETEITEM, 0, (HTREEITEM)kill, 0);
192 if (killItem->firstChild)
193 TREEVIEW_RemoveAllChildren (wndPtr, killItem);
194 kill=(INT32)killItem->sibling;
197 if (parentItem->cChildren>0) {
198 infoPtr->uNumItems -= parentItem->cChildren;
199 parentItem->firstChild = 0;
200 parentItem->cChildren = 0;
206 static void
207 TREEVIEW_RemoveItem (WND *wndPtr, TREEVIEW_ITEM *wineItem)
210 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
211 TREEVIEW_ITEM *parentItem, *upsiblingItem, *siblingItem;
212 INT32 iItem;
214 iItem=(INT32)wineItem->hItem;
215 tv_set_bit(iItem,infoPtr->freeList);
216 infoPtr->uNumItems--;
217 parentItem=NULL;
218 if (wineItem->pszText!=LPSTR_TEXTCALLBACK32A)
219 COMCTL32_Free (wineItem->pszText);
221 TREEVIEW_SendTreeviewNotify (wndPtr, TVN_DELETEITEM, 0, (HTREEITEM)iItem, 0);
223 if (wineItem->firstChild)
224 TREEVIEW_RemoveAllChildren (wndPtr,wineItem);
226 if (wineItem->parent) {
227 parentItem=& infoPtr->items [(INT32)wineItem->parent];
228 switch (parentItem->cChildren) {
229 case I_CHILDRENCALLBACK:
230 FIXME (treeview,"we don't handle I_CHILDRENCALLBACK yet\n");
231 break;
232 case 1:
233 parentItem->cChildren=0;
234 parentItem->firstChild=0;
235 return;
236 default:
237 parentItem->cChildren--;
238 if ((INT32)parentItem->firstChild==iItem)
239 parentItem->firstChild=wineItem->sibling;
243 if (iItem==(INT32)infoPtr->TopRootItem)
244 infoPtr->TopRootItem=(HTREEITEM)wineItem->sibling;
245 if (wineItem->upsibling) {
246 upsiblingItem=& infoPtr->items [(INT32)wineItem->upsibling];
247 upsiblingItem->sibling=wineItem->sibling;
249 if (wineItem->sibling) {
250 siblingItem=& infoPtr->items [(INT32)wineItem->sibling];
251 siblingItem->upsibling=wineItem->upsibling;
259 /* Note:TREEVIEW_RemoveTree doesn't remove infoPtr itself */
261 static void TREEVIEW_RemoveTree (WND *wndPtr)
264 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
265 TREEVIEW_ITEM *killItem;
266 int i;
268 for (i=1; i<=(INT32)infoPtr->uMaxHandle; i++)
269 if (!tv_test_bit (i, infoPtr->freeList)) {
270 killItem=& infoPtr->items [i];
271 if (killItem->pszText!=LPSTR_TEXTCALLBACK32A)
272 COMCTL32_Free (killItem->pszText);
273 TREEVIEW_SendTreeviewNotify
274 (wndPtr, TVN_DELETEITEM, 0, killItem->hItem, 0);
277 if (infoPtr->uNumPtrsAlloced) {
278 COMCTL32_Free (infoPtr->items);
279 COMCTL32_Free (infoPtr->freeList);
280 infoPtr->uNumItems=0;
281 infoPtr->uNumPtrsAlloced=0;
282 infoPtr->uMaxHandle=0;
292 static LRESULT
293 TREEVIEW_GetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
295 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
297 TRACE (treeview,"\n");
298 if (infoPtr==NULL) return 0;
300 if ((INT32)wParam == TVSIL_NORMAL)
301 return (LRESULT) infoPtr->himlNormal;
302 if ((INT32)wParam == TVSIL_STATE)
303 return (LRESULT) infoPtr->himlState;
305 return 0;
308 static LRESULT
309 TREEVIEW_SetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
311 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
312 HIMAGELIST himlTemp;
314 TRACE (treeview,"\n");
315 switch ((INT32)wParam) {
316 case TVSIL_NORMAL:
317 himlTemp = infoPtr->himlNormal;
318 infoPtr->himlNormal = (HIMAGELIST)lParam;
319 return (LRESULT)himlTemp;
321 case TVSIL_STATE:
322 himlTemp = infoPtr->himlState;
323 infoPtr->himlState = (HIMAGELIST)lParam;
324 return (LRESULT)himlTemp;
327 return (LRESULT)NULL;
332 static LRESULT
333 TREEVIEW_SetItemHeight (WND *wndPtr, WPARAM32 wParam)
335 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
336 INT32 cx,cy,prevHeight=infoPtr->uItemHeight;
337 HDC32 hdc;
339 TRACE (treeview,"\n");
340 if (wParam==-1) {
341 hdc=GetDC32 (wndPtr->hwndSelf);
342 infoPtr->uItemHeight=-1;
343 return prevHeight;
346 ImageList_GetIconSize (infoPtr->himlNormal, &cx, &cy);
348 if (wParam>cy) cy=wParam;
349 infoPtr->uItemHeight=cy;
351 if (!(wndPtr->dwStyle & TVS_NONEVENHEIGHT))
352 infoPtr->uItemHeight = (INT32) wParam & 0xfffffffe;
353 return prevHeight;
356 static LRESULT
357 TREEVIEW_GetItemHeight (WND *wndPtr)
359 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
361 TRACE (treeview,"\n");
362 return infoPtr->uItemHeight;
365 static LRESULT
366 TREEVIEW_SetTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
368 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
369 COLORREF prevColor=infoPtr->clrText;
371 TRACE (treeview,"\n");
372 infoPtr->clrText=(COLORREF) lParam;
373 return (LRESULT) prevColor;
376 static LRESULT
377 TREEVIEW_GetBkColor (WND *wndPtr)
379 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
381 TRACE (treeview,"\n");
382 return (LRESULT) infoPtr->clrText;
385 static LRESULT
386 TREEVIEW_SetBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
388 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
389 COLORREF prevColor=infoPtr->clrBk;
391 TRACE (treeview,"\n");
392 infoPtr->clrBk=(COLORREF) lParam;
393 return (LRESULT) prevColor;
396 static LRESULT
397 TREEVIEW_GetTextColor (WND *wndPtr)
399 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
401 TRACE (treeview,"\n");
402 return (LRESULT) infoPtr->clrBk;
409 /* FIXME: draw background (infoPtr->clrBk) */
412 /* cdmode: custom draw mode as received from app. in first NMCUSTOMDRAW
413 notification */
415 static void
416 TREEVIEW_DrawItem (WND *wndPtr, HDC32 hdc, TREEVIEW_ITEM *wineItem)
419 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
420 INT32 oldBkMode,center,xpos,cx,cy, cditem, drawmode;
421 TREEVIEW_ITEM *parentItem;
422 COLORREF oldBkColor;
423 HFONT32 hOldFont;
424 UINT32 uTextJustify = DT_LEFT;
425 HPEN32 hOldPen, hnewPen;
426 RECT32 r,upper;
428 HIMAGELIST *himlp;
430 if (wineItem->state & TVIS_BOLD)
431 hOldFont = SelectObject32 (hdc, infoPtr->hBoldFont);
432 else
433 hOldFont = SelectObject32 (hdc, infoPtr->hFont);
435 cditem=0;
436 if (infoPtr->cdmode & CDRF_NOTIFYITEMDRAW) {
437 drawmode=CDDS_ITEMPREPAINT;
438 if (infoPtr->cdmode & CDRF_NOTIFYSUBITEMDRAW) drawmode|=CDDS_SUBITEM;
439 cditem=TREEVIEW_SendCustomDrawItemNotify (wndPtr, hdc, wineItem, drawmode);
440 TRACE (treeview,"cditem:%d\n",cditem);
441 if (cditem & CDRF_SKIPDEFAULT)
442 return;
446 hnewPen = CreatePen32(PS_DOT, 0, GetSysColor32(COLOR_WINDOWTEXT) );
447 hOldPen = SelectObject32( hdc, hnewPen );
449 r=wineItem->rect;
450 if (wineItem->parent) {
451 parentItem=TREEVIEW_ValidItem (infoPtr, wineItem->parent);
452 upper=parentItem->rect;
454 else {
455 upper.top=0;
456 upper.left=8;
458 center=(r.top+r.bottom)/2;
459 xpos=r.left+8;
461 if (wndPtr->dwStyle & TVS_HASLINES) {
462 POINT32 points[3];
463 if ((wndPtr->dwStyle & TVS_LINESATROOT) && (wineItem->iLevel==0)) {
464 points[0].y=points[1].y=center;
465 points[2].y=upper.top;
466 points[1].x=points[2].x=upper.left;
467 points[0].x=upper.left+12;
468 points[2].y+=5;
470 Polyline32 (hdc,points,3);
472 else {
473 points[0].y=points[1].y=center;
474 points[2].y=upper.top;
475 points[1].x=points[2].x=upper.left+13;
476 points[0].x=upper.left+25;
477 points[2].y+=5;
478 Polyline32 (hdc,points,3);
482 DeleteObject32(hnewPen);
483 SelectObject32(hdc, hOldPen);
485 if ((wndPtr->dwStyle & TVS_HASBUTTONS) && (wndPtr->dwStyle & TVS_HASLINES) &&
486 (wineItem->cChildren)) {
487 Rectangle32 (hdc, xpos-4, center-4, xpos+5, center+5);
488 MoveToEx32 (hdc, xpos-2, center, NULL);
489 LineTo32 (hdc, xpos+3, center);
490 if (!(wineItem->state & TVIS_EXPANDED)) {
491 MoveToEx32 (hdc, xpos, center-2, NULL);
492 LineTo32 (hdc, xpos, center+3);
497 xpos+=13;
499 if (wineItem->mask & (TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
501 himlp=NULL;
502 if (infoPtr->himlNormal) himlp=&infoPtr->himlNormal;
504 if ((wineItem->state & TVIS_SELECTED) && (wineItem->iSelectedImage)) {
505 if (infoPtr->himlState) himlp=&infoPtr->himlState;
506 if (wineItem->iSelectedImage==I_IMAGECALLBACK)
507 TREEVIEW_SendDispInfoNotify (wndPtr, wineItem,
508 TVN_GETDISPINFO, TVIF_SELECTEDIMAGE);
509 } else { /* NOT selected */
510 if (wineItem->iImage==I_IMAGECALLBACK)
511 TREEVIEW_SendDispInfoNotify (wndPtr, wineItem,
512 TVN_GETDISPINFO, TVIF_IMAGE);
515 if (himlp) {
516 ImageList_Draw (*himlp, wineItem->iImage, hdc, xpos-2, r.top+1, ILD_NORMAL);
517 ImageList_GetIconSize (*himlp, &cx, &cy);
518 xpos+=cx;
523 r.left=xpos;
524 if ((wineItem->mask & TVIF_TEXT) && (wineItem->pszText)) {
526 if (wineItem->state & (TVIS_SELECTED | TVIS_DROPHILITED) ) {
527 oldBkMode = SetBkMode32(hdc, OPAQUE);
528 oldBkColor= SetBkColor32 (hdc, GetSysColor32( COLOR_HIGHLIGHT));
529 SetTextColor32 (hdc, GetSysColor32(COLOR_HIGHLIGHTTEXT));
530 } else {
531 oldBkMode = SetBkMode32(hdc, TRANSPARENT);
533 r.left += 3;
534 r.right -= 3;
535 wineItem->text.left=r.left;
536 wineItem->text.right=r.right;
537 if (infoPtr->clrText==-1)
538 SetTextColor32 (hdc, COLOR_BTNTEXT);
539 else
540 SetTextColor32 (hdc, infoPtr->clrText); /* FIXME: setback retval */
542 if (wineItem->pszText== LPSTR_TEXTCALLBACK32A) {
543 TRACE (treeview,"LPSTR_TEXTCALLBACK\n");
544 TREEVIEW_SendDispInfoNotify (wndPtr, wineItem,
545 TVN_GETDISPINFO, TVIF_TEXT);
548 DrawText32A (hdc, wineItem->pszText, lstrlen32A(wineItem->pszText), &r,
549 uTextJustify|DT_VCENTER|DT_SINGLELINE);
551 if (oldBkMode != TRANSPARENT)
552 SetBkMode32(hdc, oldBkMode);
553 if (wineItem->state & (TVIS_SELECTED | TVIS_DROPHILITED))
554 SetBkColor32 (hdc, oldBkColor);
557 if (cditem & CDRF_NOTIFYPOSTPAINT)
558 TREEVIEW_SendCustomDrawItemNotify (wndPtr, hdc, wineItem,
559 CDDS_ITEMPOSTPAINT);
561 SelectObject32 (hdc, hOldFont);
570 static LRESULT
571 TREEVIEW_GetItemRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
573 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
574 TREEVIEW_ITEM *wineItem;
575 HTREEITEM *iItem;
576 LPRECT32 lpRect;
578 TRACE (treeview,"\n");
579 if (infoPtr==NULL) return FALSE;
581 if (infoPtr->Timer & TV_REFRESH_TIMER_SET)
582 TREEVIEW_Refresh (wndPtr); /* we want a rect for the current view */
584 iItem = (HTREEITEM *) lParam;
585 wineItem = TREEVIEW_ValidItem (infoPtr, *iItem);
586 if (!wineItem) return FALSE;
588 wineItem=& infoPtr->items[ (INT32)*iItem ];
589 if (!wineItem->visible) return FALSE;
591 lpRect = (LPRECT32)lParam;
592 if (lpRect == NULL) return FALSE;
594 if ((INT32) wParam) {
595 lpRect->left = wineItem->text.left;
596 lpRect->right = wineItem->text.right;
597 lpRect->bottom = wineItem->text.bottom;
598 lpRect->top = wineItem->text.top;
599 } else {
600 lpRect->left = wineItem->rect.left;
601 lpRect->right = wineItem->rect.right;
602 lpRect->bottom = wineItem->rect.bottom;
603 lpRect->top = wineItem->rect.top;
606 TRACE (treeview,"[L:%d R:%d T:%d B:%d]\n", lpRect->left,lpRect->right,
607 lpRect->top,lpRect->bottom);
608 return TRUE;
613 static LRESULT
614 TREEVIEW_GetVisibleCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
617 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
619 return (LRESULT) infoPtr->uVisibleHeight / infoPtr->uRealItemHeight;
624 static LRESULT
625 TREEVIEW_SetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
627 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
628 TREEVIEW_ITEM *wineItem;
629 TVITEMEX32A *tvItem;
630 INT32 iItem,len;
632 tvItem=(LPTVITEMEX32A) lParam;
633 iItem=(INT32)tvItem->hItem;
634 TRACE (treeview,"item %d,mask %x\n",iItem,tvItem->mask);
636 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
637 if (!wineItem) return FALSE;
639 if (tvItem->mask & TVIF_CHILDREN) {
640 wineItem->cChildren=tvItem->cChildren;
643 if (tvItem->mask & TVIF_IMAGE) {
644 wineItem->iImage=tvItem->iImage;
647 if (tvItem->mask & TVIF_INTEGRAL) {
648 wineItem->iIntegral=tvItem->iIntegral;
649 FIXME (treeview," TVIF_INTEGRAL not supported yet\n");
652 if (tvItem->mask & TVIF_PARAM) {
653 wineItem->lParam=tvItem->lParam;
656 if (tvItem->mask & TVIF_SELECTEDIMAGE) {
657 wineItem->iSelectedImage=tvItem->iSelectedImage;
660 if (tvItem->mask & TVIF_STATE) {
661 wineItem->state=tvItem->state & tvItem->stateMask;
664 if (tvItem->mask & TVIF_TEXT) {
665 if (tvItem->pszText!=LPSTR_TEXTCALLBACK32A) {
666 len=lstrlen32A (tvItem->pszText);
667 if (len>wineItem->cchTextMax)
668 wineItem->pszText= COMCTL32_ReAlloc (wineItem->pszText, len+1);
669 lstrcpyn32A (wineItem->pszText, tvItem->pszText,len);
670 } else {
671 if (wineItem->cchTextMax) {
672 COMCTL32_Free (wineItem->pszText);
673 wineItem->cchTextMax=0;
675 wineItem->pszText=LPSTR_TEXTCALLBACK32A;
679 return TRUE;
686 static void
687 TREEVIEW_Refresh (WND *wndPtr)
690 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
691 TEXTMETRIC32A tm;
692 HBRUSH32 hbrBk;
693 RECT32 rect;
694 HDC32 hdc;
695 INT32 iItem, indent, x, y, cx, height, itemHeight;
696 INT32 viewtop,viewbottom,viewleft,viewright;
697 TREEVIEW_ITEM *wineItem, *prevItem;
699 TRACE (treeview,"\n");
701 hdc=GetDC32 (wndPtr->hwndSelf);
703 if (infoPtr->Timer & TV_REFRESH_TIMER_SET) {
704 KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
705 infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
709 GetClientRect32 (wndPtr->hwndSelf, &rect);
710 if ((rect.left-rect.right ==0) || (rect.top-rect.bottom==0)) return;
712 infoPtr->cdmode=TREEVIEW_SendCustomDrawNotify
713 (wndPtr, CDDS_PREPAINT, hdc, rect);
715 if (infoPtr->cdmode==CDRF_SKIPDEFAULT) {
716 ReleaseDC32 (wndPtr->hwndSelf, hdc);
717 return;
720 infoPtr->uVisibleHeight= rect.bottom-rect.top;
721 infoPtr->uVisibleWidth= rect.right-rect.left;
723 viewtop=infoPtr->cy;
724 viewbottom=infoPtr->cy + rect.bottom-rect.top;
725 viewleft=infoPtr->cx;
726 viewright=infoPtr->cx + rect.right-rect.left;
730 /* draw background */
732 hbrBk = GetSysColorBrush32 (COLOR_WINDOW);
733 FillRect32(hdc, &rect, hbrBk);
736 iItem=(INT32)infoPtr->TopRootItem;
737 infoPtr->firstVisible=0;
738 wineItem=NULL;
739 indent=0;
740 x=y=0;
741 TRACE (treeview, "[%d %d %d %d]\n",viewtop,viewbottom,viewleft,viewright);
743 while (iItem) {
744 prevItem=wineItem;
745 wineItem= & infoPtr->items[iItem];
746 wineItem->iLevel=indent;
748 ImageList_GetIconSize (infoPtr->himlNormal, &cx, &itemHeight);
749 if (infoPtr->uItemHeight>itemHeight)
750 itemHeight=infoPtr->uItemHeight;
752 GetTextMetrics32A (hdc, &tm);
753 if ((tm.tmHeight + tm.tmExternalLeading) > itemHeight)
754 itemHeight=tm.tmHeight + tm.tmExternalLeading;
756 infoPtr->uRealItemHeight=itemHeight;
759 /* FIXME: remove this in later stage */
761 if (wineItem->pszText!=LPSTR_TEXTCALLBACK32A)
762 TRACE (treeview, "%d %d [%d %d %d %d] (%s)\n",y,x,
763 wineItem->rect.top, wineItem->rect.bottom,
764 wineItem->rect.left, wineItem->rect.right,
765 wineItem->pszText);
766 else
767 TRACE (treeview, "%d [%d %d %d %d] (CALLBACK)\n",
768 wineItem->hItem,
769 wineItem->rect.top, wineItem->rect.bottom,
770 wineItem->rect.left, wineItem->rect.right);
773 height=itemHeight * wineItem->iIntegral +1;
774 if ((y >= viewtop) && (y <= viewbottom) &&
775 (x >= viewleft ) && (x <= viewright)) {
776 wineItem->visible = TRUE;
777 wineItem->rect.top = y - infoPtr->cy + rect.top;
778 wineItem->rect.bottom = wineItem->rect.top + height ;
779 wineItem->rect.left = x - infoPtr->cx + rect.left;
780 wineItem->rect.right = rect.right;
781 wineItem->text.left = wineItem->rect.left;
782 wineItem->text.top = wineItem->rect.top;
783 wineItem->text.right= wineItem->rect.right;
784 wineItem->text.bottom=wineItem->rect.bottom;
785 if (!infoPtr->firstVisible)
786 infoPtr->firstVisible=wineItem->hItem;
787 TREEVIEW_DrawItem (wndPtr, hdc, wineItem);
789 else {
790 wineItem->visible = FALSE;
791 wineItem->rect.left = wineItem->rect.top = 0;
792 wineItem->rect.right= wineItem->rect.bottom = 0;
793 wineItem->text.left = wineItem->text.top = 0;
794 wineItem->text.right= wineItem->text.bottom = 0;
797 /* look up next item */
799 if ((wineItem->firstChild) && (wineItem->state & TVIS_EXPANDED)) {
800 iItem=(INT32)wineItem->firstChild;
801 indent++;
802 x+=infoPtr->uIndent;
803 if (x>infoPtr->uTotalWidth)
804 infoPtr->uTotalWidth=x;
806 else {
807 iItem=(INT32)wineItem->sibling;
808 while ((!iItem) && (indent>0)) {
809 indent--;
810 x-=infoPtr->uIndent;
811 prevItem=wineItem;
812 wineItem=&infoPtr->items[(INT32)wineItem->parent];
813 iItem=(INT32)wineItem->sibling;
816 y +=height;
817 } /* while */
819 /* FIXME: infoPtr->uTotalWidth should also take item label into account */
820 /* FIXME: or should query item sizes (ie check CDRF_NEWFONT) */
822 infoPtr->uTotalHeight=y;
823 if (y >= (viewbottom-viewtop)) {
824 if (!(infoPtr->uInternalStatus & TV_VSCROLL))
825 ShowScrollBar32 (wndPtr->hwndSelf, SB_VERT, TRUE);
826 infoPtr->uInternalStatus |=TV_VSCROLL;
827 SetScrollRange32 (wndPtr->hwndSelf, SB_VERT, 0,
828 y - infoPtr->uVisibleHeight, FALSE);
829 SetScrollPos32 (wndPtr->hwndSelf, SB_VERT, infoPtr->cy, TRUE);
831 else {
832 if (infoPtr->uInternalStatus & TV_VSCROLL)
833 ShowScrollBar32 (wndPtr->hwndSelf, SB_VERT, FALSE);
834 infoPtr->uInternalStatus &= ~TV_VSCROLL;
838 if (infoPtr->cdmode & CDRF_NOTIFYPOSTPAINT)
839 infoPtr->cdmode=TREEVIEW_SendCustomDrawNotify
840 (wndPtr, CDDS_POSTPAINT, hdc, rect);
842 ReleaseDC32 (wndPtr->hwndSelf, hdc);
843 TRACE (treeview,"done\n");
847 static LRESULT
848 TREEVIEW_HandleTimer ( WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
850 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
852 TRACE (treeview, " %d\n",wParam);
853 if (!infoPtr) return FALSE;
855 switch (wParam) {
856 case TV_REFRESH_TIMER:
857 KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
858 infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
859 SendMessage32A (wndPtr->hwndSelf, WM_PAINT, 0, 0);
860 return 0;
861 case TV_EDIT_TIMER:
862 KillTimer32 (wndPtr->hwndSelf, TV_EDIT_TIMER);
863 infoPtr->Timer &= ~TV_EDIT_TIMER_SET;
864 return 0;
865 default:
866 ERR (treeview,"got unknown timer\n");
869 return 1;
873 static void
874 TREEVIEW_QueueRefresh (WND *wndPtr)
877 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
879 TRACE (treeview,"\n");
880 if (infoPtr->Timer & TV_REFRESH_TIMER_SET) {
881 KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
884 SetTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER, TV_REFRESH_DELAY, 0);
885 infoPtr->Timer|=TV_REFRESH_TIMER_SET;
890 static LRESULT
891 TREEVIEW_GetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
893 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
894 LPTVITEMEX32A tvItem;
895 TREEVIEW_ITEM *wineItem;
896 INT32 iItem;
898 tvItem=(LPTVITEMEX32A) lParam;
899 iItem=(INT32)tvItem->hItem;
900 TRACE (treeview,"item %d<%p>, txt %p, img %p, action %x\n", iItem,
901 tvItem, tvItem->pszText, & tvItem->iImage, tvItem->mask);
903 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
904 if (!wineItem) return FALSE;
906 if (tvItem->mask & TVIF_CHILDREN) {
907 if (TVIF_CHILDREN==I_CHILDRENCALLBACK)
908 FIXME (treeview,"I_CHILDRENCALLBACK not supported\n");
909 tvItem->cChildren=wineItem->cChildren;
912 if (tvItem->mask & TVIF_HANDLE) {
913 tvItem->hItem=wineItem->hItem;
916 if (tvItem->mask & TVIF_IMAGE) {
917 tvItem->iImage=wineItem->iImage;
920 if (tvItem->mask & TVIF_INTEGRAL) {
921 tvItem->iIntegral=wineItem->iIntegral;
922 FIXME (treeview," TVIF_INTEGRAL not supported yet\n");
925 if (tvItem->mask & TVIF_PARAM) {
926 tvItem->lParam=wineItem->lParam;
929 if (tvItem->mask & TVIF_SELECTEDIMAGE) {
930 tvItem->iSelectedImage=wineItem->iSelectedImage;
933 if (tvItem->mask & TVIF_STATE) {
934 tvItem->state=wineItem->state & tvItem->stateMask;
937 if (tvItem->mask & TVIF_TEXT) {
938 if (wineItem->pszText == LPSTR_TEXTCALLBACK32A) {
939 tvItem->pszText = LPSTR_TEXTCALLBACK32A; /* FIXME:send notification? */
940 ERR (treeview," GetItem called with LPSTR_TEXTCALLBACK\n");
942 else if (wineItem->pszText) {
943 lstrcpyn32A (tvItem->pszText, wineItem->pszText, tvItem->cchTextMax);
947 return TRUE;
952 /* FIXME: check implementation of TVGN_NEXT/TVGN_NEXTVISIBLE */
954 static LRESULT
955 TREEVIEW_GetNextItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
958 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
959 TREEVIEW_ITEM *wineItem, *returnItem;
960 INT32 iItem, retval, flag;
963 if (!infoPtr) return FALSE;
964 flag = (INT32) wParam;
965 iItem = (INT32) lParam;
966 retval=0;
967 switch (flag) {
968 case TVGN_ROOT: retval=(INT32)infoPtr->TopRootItem;
969 break;
970 case TVGN_CARET:retval=(INT32)infoPtr->selectedItem;
971 break;
972 case TVGN_FIRSTVISIBLE:
973 TREEVIEW_Refresh (wndPtr);
974 /* FIXME:we should only recalculate, not redraw */
975 retval=(INT32)infoPtr->firstVisible;
976 break;
977 case TVGN_DROPHILITE:
978 retval=(INT32)infoPtr->dropItem;
979 break;
981 if (retval) {
982 TRACE (treeview,"flags:%x, returns %u\n", flag, retval);
983 return retval;
986 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
987 returnItem = NULL;
988 if (!wineItem) return FALSE;
990 switch (flag) {
991 case TVGN_NEXT: retval=(INT32)wineItem->sibling;
992 break;
993 case TVGN_PREVIOUS:
994 retval=(INT32)wineItem->upsibling;
995 break;
996 case TVGN_PARENT:
997 retval=(INT32)wineItem->parent;
998 break;
999 case TVGN_CHILD:
1000 retval=(INT32)wineItem->firstChild;
1001 break;
1002 case TVGN_LASTVISIBLE:
1003 returnItem=TREEVIEW_GetLastListItem (infoPtr,wineItem);
1004 break;
1005 case TVGN_NEXTVISIBLE:
1006 returnItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
1007 break;
1008 case TVGN_PREVIOUSVISIBLE:
1009 returnItem=TREEVIEW_GetPrevListItem (infoPtr, wineItem);
1010 break;
1011 default: FIXME (treeview,"Unknown msg %x,item %x\n", flag,iItem);
1012 break;
1015 if (returnItem) {
1016 TRACE (treeview,"flags:%x, item %d;returns %d\n", flag, iItem,
1017 (INT32)returnItem->hItem);
1018 return (INT32)returnItem->hItem;
1021 TRACE (treeview,"flags:%x, item %d;returns %d\n", flag, iItem,retval);
1022 return retval;
1026 static LRESULT
1027 TREEVIEW_GetCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1029 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1031 TRACE (treeview," %d\n",infoPtr->uNumItems);
1032 return (LRESULT) infoPtr->uNumItems;
1038 /* the method used below isn't the most memory-friendly, but it avoids
1039 a lot of memory reallocations */
1041 /* BTW: we waste handle 0; 0 is not an allowed handle. */
1043 static LRESULT
1044 TREEVIEW_InsertItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1047 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1048 TVINSERTSTRUCT32A *ptdi;
1049 TVITEMEX32A *tvItem;
1050 TREEVIEW_ITEM *wineItem, *parentItem, *prevsib, *sibItem;
1051 INT32 iItem,listItems,i,len;
1053 ptdi = (LPTVINSERTSTRUCT32A) lParam;
1055 /* check if memory is available */
1057 if (infoPtr->uNumPtrsAlloced==0) {
1058 infoPtr->items = COMCTL32_Alloc (TVITEM_ALLOC*sizeof (TREEVIEW_ITEM));
1059 infoPtr->freeList= COMCTL32_Alloc ((1+(TVITEM_ALLOC>>5)) * sizeof (INT32));
1060 infoPtr->uNumPtrsAlloced=TVITEM_ALLOC;
1061 infoPtr->TopRootItem=(HTREEITEM)1;
1064 if (infoPtr->uNumItems == (infoPtr->uNumPtrsAlloced-1) ) {
1065 TREEVIEW_ITEM *oldItems = infoPtr->items;
1066 INT32 *oldfreeList = infoPtr->freeList;
1068 infoPtr->uNumPtrsAlloced*=2;
1069 infoPtr->items = COMCTL32_Alloc (infoPtr->uNumPtrsAlloced*sizeof (TREEVIEW_ITEM));
1070 infoPtr->freeList= COMCTL32_Alloc ((1+(infoPtr->uNumPtrsAlloced>>5))*sizeof (INT32));
1072 memcpy (&infoPtr->items[0], &oldItems[0],
1073 infoPtr->uNumPtrsAlloced/2 * sizeof(TREEVIEW_ITEM));
1074 memcpy (&infoPtr->freeList[0], &oldfreeList[0],
1075 infoPtr->uNumPtrsAlloced>>6 * sizeof(INT32));
1077 COMCTL32_Free (oldItems);
1078 COMCTL32_Free (oldfreeList);
1081 iItem=0;
1082 infoPtr->uNumItems++;
1084 if ((INT32)infoPtr->uMaxHandle==(infoPtr->uNumItems-1)) {
1085 iItem=infoPtr->uNumItems;
1086 infoPtr->uMaxHandle = (HTREEITEM)((INT32)infoPtr->uMaxHandle + 1);
1087 } else { /* check freelist */
1088 for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) {
1089 if (infoPtr->freeList[i]) {
1090 iItem=ffs (infoPtr->freeList[i])-1;
1091 tv_clear_bit(iItem,&infoPtr->freeList[i]);
1092 iItem+=i<<5;
1093 break;
1098 for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++)
1099 TRACE (treeview,"%8x\n",infoPtr->freeList[i]);
1101 if (!iItem) ERR (treeview, "Argh -- can't find free item.\n");
1103 tvItem= & ptdi->DUMMYUNIONNAME.itemex;
1104 wineItem=& infoPtr->items[iItem];
1106 if ((ptdi->hParent==TVI_ROOT) || (ptdi->hParent==0)) {
1107 parentItem=NULL;
1108 wineItem->parent=0;
1109 sibItem=&infoPtr->items [(INT32)infoPtr->TopRootItem];
1110 listItems=infoPtr->uNumItems;
1112 else {
1113 parentItem= &infoPtr->items[(INT32)ptdi->hParent];
1114 if (!parentItem->firstChild)
1115 parentItem->firstChild=(HTREEITEM)iItem;
1116 wineItem->parent=ptdi->hParent;
1117 sibItem=&infoPtr->items [(INT32)parentItem->firstChild];
1118 parentItem->cChildren++;
1119 listItems=parentItem->cChildren;
1122 wineItem->upsibling=0; /* needed in case we're the first item in a list */
1123 wineItem->sibling=0;
1124 wineItem->firstChild=0;
1125 wineItem->hItem=(HTREEITEM)iItem;
1127 if (listItems>1) {
1128 prevsib=NULL;
1129 switch ((INT32)ptdi->hInsertAfter) {
1130 case TVI_FIRST:
1131 if (wineItem->parent) {
1132 wineItem->sibling=parentItem->firstChild;
1133 parentItem->firstChild=(HTREEITEM)iItem;
1134 } else {
1135 wineItem->sibling=infoPtr->TopRootItem;
1136 infoPtr->TopRootItem=(HTREEITEM)iItem;
1138 sibItem->upsibling=(HTREEITEM)iItem;
1139 break;
1140 case TVI_LAST:
1141 if (sibItem==wineItem) break;
1142 while (sibItem->sibling) {
1143 prevsib=sibItem;
1144 sibItem=&infoPtr->items [(INT32)sibItem->sibling];
1146 sibItem->sibling=(HTREEITEM)iItem;
1147 wineItem->upsibling=sibItem->hItem;
1148 break;
1149 case TVI_SORT:
1150 FIXME (treeview, "Sorted insert not implemented yet\n");
1151 break;
1152 default:
1153 while ((sibItem->sibling) && (sibItem->hItem!=ptdi->hInsertAfter))
1155 prevsib=sibItem;
1156 sibItem=&infoPtr->items [(INT32)sibItem->sibling];
1158 if (sibItem->hItem!=ptdi->hInsertAfter) {
1159 ERR (treeview, "tried to insert item after nonexisting handle.\n");
1160 break;
1162 prevsib=sibItem;
1163 if (sibItem->sibling) {
1164 sibItem=&infoPtr->items [(INT32)sibItem->sibling];
1165 sibItem->upsibling=(HTREEITEM)iItem;
1166 wineItem->sibling=sibItem->hItem;
1168 prevsib->sibling=(HTREEITEM)iItem;
1169 wineItem->upsibling=prevsib->hItem;
1170 break;
1175 /* Fill in info structure */
1177 TRACE (treeview,"new item %d; parent %d, mask %x\n", iItem,
1178 (INT32)wineItem->parent,tvItem->mask);
1180 wineItem->mask=tvItem->mask;
1181 wineItem->iIntegral=1;
1183 if (tvItem->mask & TVIF_CHILDREN) {
1184 wineItem->cChildren=tvItem->cChildren;
1185 if (tvItem->cChildren==I_CHILDRENCALLBACK)
1186 FIXME (treeview," I_CHILDRENCALLBACK not supported\n");
1190 if (tvItem->mask & TVIF_IMAGE)
1191 wineItem->iImage=tvItem->iImage;
1193 /* If the application sets TVIF_INTEGRAL without
1194 supplying a TVITEMEX structure, it's toast */
1196 if (tvItem->mask & TVIF_INTEGRAL)
1197 wineItem->iIntegral=tvItem->iIntegral;
1199 if (tvItem->mask & TVIF_PARAM)
1200 wineItem->lParam=tvItem->lParam;
1202 if (tvItem->mask & TVIF_SELECTEDIMAGE)
1203 wineItem->iSelectedImage=tvItem->iSelectedImage;
1205 if (tvItem->mask & TVIF_STATE) {
1206 wineItem->state=tvItem->state;
1207 wineItem->stateMask=tvItem->stateMask;
1210 if (tvItem->mask & TVIF_TEXT) {
1211 if (tvItem->pszText!=LPSTR_TEXTCALLBACK32A) {
1212 TRACE (treeview,"(%p,%s)\n", &tvItem->pszText, tvItem->pszText);
1213 len = lstrlen32A (tvItem->pszText)+1;
1214 wineItem->pszText= COMCTL32_Alloc (len+1);
1215 lstrcpy32A (wineItem->pszText, tvItem->pszText);
1216 wineItem->cchTextMax=len;
1218 else {
1219 TRACE (treeview,"LPSTR_TEXTCALLBACK\n");
1220 wineItem->pszText = LPSTR_TEXTCALLBACK32A;
1221 wineItem->cchTextMax = 0;
1225 TREEVIEW_QueueRefresh (wndPtr);
1227 return (LRESULT) iItem;
1234 static LRESULT
1235 TREEVIEW_DeleteItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1237 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1238 INT32 iItem;
1239 TREEVIEW_ITEM *wineItem;
1241 TRACE (treeview,"\n");
1242 if (!infoPtr) return FALSE;
1244 if (lParam == (INT32)TVI_ROOT) {
1245 TREEVIEW_RemoveTree (wndPtr);
1246 } else {
1247 iItem= (INT32) lParam;
1248 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
1249 if (!wineItem) return FALSE;
1250 TRACE (treeview,"%s\n",wineItem->pszText);
1251 TREEVIEW_RemoveItem (wndPtr, wineItem);
1254 TREEVIEW_QueueRefresh (wndPtr);
1256 return TRUE;
1261 static LRESULT
1262 TREEVIEW_GetIndent (WND *wndPtr)
1264 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1266 TRACE (treeview,"\n");
1267 return infoPtr->uIndent;
1270 static LRESULT
1271 TREEVIEW_SetIndent (WND *wndPtr, WPARAM32 wParam)
1273 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1274 INT32 newIndent;
1276 TRACE (treeview,"\n");
1277 newIndent=(INT32) wParam;
1278 if (newIndent < MINIMUM_INDENT) newIndent=MINIMUM_INDENT;
1279 infoPtr->uIndent=newIndent;
1281 return 0;
1284 static LRESULT
1285 TREEVIEW_GetToolTips (WND *wndPtr)
1288 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1290 TRACE (treeview,"\n");
1291 return infoPtr->hwndToolTip;
1295 static LRESULT
1296 TREEVIEW_SetToolTips (WND *wndPtr, WPARAM32 wParam)
1299 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1300 HWND32 prevToolTip;
1302 TRACE (treeview,"\n");
1303 prevToolTip=infoPtr->hwndToolTip;
1304 infoPtr->hwndToolTip= (HWND32) wParam;
1306 return prevToolTip;
1310 LRESULT CALLBACK
1311 TREEVIEW_GetEditControl (WND *wndPtr)
1314 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1316 return infoPtr->hwndEdit;
1319 LRESULT CALLBACK
1320 TREEVIEW_Edit_SubclassProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam,
1321 LPARAM lParam)
1323 switch (uMsg) {
1324 case WM_ERASEBKGND: {
1325 RECT32 rc;
1326 HDC32 hdc = (HDC32) wParam;
1327 GetClientRect32 (hwnd, &rc);
1328 Rectangle32 (hdc, rc.left, rc.top, rc.right, rc.bottom);
1329 return -1;
1331 case WM_GETDLGCODE:
1332 return DLGC_WANTARROWS | DLGC_WANTALLKEYS;
1333 default:
1334 return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
1336 return 0;
1340 /* should handle edit control messages here */
1342 static LRESULT
1343 TREEVIEW_Command (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1346 TRACE (treeview, "%x %ld\n",wParam, lParam);
1348 switch (HIWORD(wParam)) {
1349 case EN_UPDATE:
1350 FIXME (treeview, "got EN_UPDATE.\n");
1351 break;
1352 case EN_KILLFOCUS:
1353 FIXME (treeview, "got EN_KILLFOCUS.\n");
1354 break;
1355 default:
1356 return SendMessage32A (GetParent32 (wndPtr->hwndSelf),
1357 WM_COMMAND, wParam, lParam);
1359 return 0;
1365 static LRESULT
1366 TREEVIEW_Size (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1369 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1370 RECT32 parent_rect;
1371 UINT32 cx,cy;
1372 HWND32 parent;
1374 if (infoPtr->bAutoSize) {
1375 infoPtr->bAutoSize = FALSE;
1376 return 0;
1378 infoPtr->bAutoSize = TRUE;
1380 if (!wParam) {
1381 parent = GetParent32 (wndPtr->hwndSelf);
1382 GetClientRect32(parent, &parent_rect);
1383 cx=LOWORD (lParam);
1384 cy=HIWORD (lParam);
1385 SetWindowPos32 (wndPtr->hwndSelf, 0, parent_rect.left, parent_rect.top,
1386 cx, cy, SWP_NOZORDER);
1387 } else {
1388 FIXME (treeview,"WM_SIZE flag %x %lx not handled\n", wParam, lParam);
1391 TREEVIEW_QueueRefresh (wndPtr);
1392 return 0;
1397 static LRESULT
1398 TREEVIEW_StyleChanged (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1400 LPSTYLESTRUCT lpss=(LPSTYLESTRUCT) lParam;
1402 TRACE (treeview,"(%x %lx)\n",wParam,lParam);
1404 if (wParam & (GWL_STYLE))
1405 wndPtr->dwStyle=lpss->styleNew;
1406 if (wParam & (GWL_EXSTYLE))
1407 wndPtr->dwExStyle=lpss->styleNew;
1409 return 0;
1412 static LRESULT
1413 TREEVIEW_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1415 TREEVIEW_INFO *infoPtr;
1416 LOGFONT32A logFont;
1417 TEXTMETRIC32A tm;
1418 HDC32 hdc;
1420 TRACE (treeview,"wnd %x\n",wndPtr->hwndSelf);
1421 /* allocate memory for info structure */
1422 infoPtr = (TREEVIEW_INFO *) COMCTL32_Alloc (sizeof(TREEVIEW_INFO));
1424 wndPtr->wExtra[0] = (DWORD)infoPtr;
1426 if (infoPtr == NULL) {
1427 ERR (treeview, "could not allocate info memory!\n");
1428 return 0;
1431 if ((TREEVIEW_INFO*)wndPtr->wExtra[0] != infoPtr) {
1432 ERR (treeview, "pointer assignment error!\n");
1433 return 0;
1436 hdc=GetDC32 (wndPtr->hwndSelf);
1438 /* set default settings */
1439 infoPtr->uInternalStatus=0;
1440 infoPtr->uNumItems=0;
1441 infoPtr->clrBk = GetSysColor32 (COLOR_WINDOW);
1442 infoPtr->clrText = GetSysColor32 (COLOR_BTNTEXT);
1443 infoPtr->cy = 0;
1444 infoPtr->cx = 0;
1445 infoPtr->uIndent = 15;
1446 infoPtr->himlNormal = NULL;
1447 infoPtr->himlState = NULL;
1448 infoPtr->uItemHeight = -1;
1449 GetTextMetrics32A (hdc, &tm);
1450 infoPtr->hFont = GetStockObject32 (DEFAULT_GUI_FONT);
1451 GetObject32A (infoPtr->hFont, sizeof (LOGFONT32A), &logFont);
1452 logFont.lfWeight=FW_BOLD;
1453 infoPtr->hBoldFont = CreateFontIndirect32A (&logFont);
1455 infoPtr->items = NULL;
1456 infoPtr->selectedItem=0;
1457 infoPtr->clrText=-1; /* use system color */
1458 infoPtr->dropItem=0;
1461 infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
1462 infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
1465 infoPtr->hwndToolTip=0;
1466 if (!(wndPtr->dwStyle & TVS_NOTOOLTIPS)) { /* Create tooltip control */
1467 TTTOOLINFO32A ti;
1469 infoPtr->hwndToolTip =
1470 CreateWindowEx32A (0, TOOLTIPS_CLASS32A, NULL, 0,
1471 CW_USEDEFAULT32, CW_USEDEFAULT32,
1472 CW_USEDEFAULT32, CW_USEDEFAULT32,
1473 wndPtr->hwndSelf, 0, 0, 0);
1475 /* Send NM_TOOLTIPSCREATED notification */
1476 if (infoPtr->hwndToolTip) {
1477 NMTOOLTIPSCREATED nmttc;
1479 nmttc.hdr.hwndFrom = wndPtr->hwndSelf;
1480 nmttc.hdr.idFrom = wndPtr->wIDmenu;
1481 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1482 nmttc.hwndToolTips = infoPtr->hwndToolTip;
1484 SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
1485 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmttc);
1488 ZeroMemory (&ti, sizeof(TTTOOLINFO32A));
1489 ti.cbSize = sizeof(TTTOOLINFO32A);
1490 ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_TRANSPARENT ;
1491 ti.hwnd = wndPtr->hwndSelf;
1492 ti.uId = 0;
1493 ti.lpszText = "Test"; /* LPSTR_TEXTCALLBACK; */
1494 SetRectEmpty32 (&ti.rect);
1496 SendMessage32A (infoPtr->hwndToolTip, TTM_ADDTOOL32A, 0, (LPARAM)&ti);
1500 infoPtr->hwndEdit = CreateWindowEx32A ( 0, "EDIT",NULL,
1501 WS_CHILD | WS_BORDER | ES_AUTOHSCROLL | ES_WANTRETURN,
1502 0, 0, 0, 0,
1503 wndPtr->hwndSelf, 0,0,0);
1504 /* FIXME: (HMENU)IDTVEDIT, pcs->hInstance, 0); */
1506 SendMessage32A ( infoPtr->hwndEdit, WM_SETFONT, infoPtr->hFont, FALSE);
1507 infoPtr->wpEditOrig= (WNDPROC32)
1508 SetWindowLong32A (infoPtr->hwndEdit,GWL_WNDPROC,
1509 (LONG) TREEVIEW_Edit_SubclassProc);
1511 ReleaseDC32 (wndPtr->hwndSelf, hdc);
1513 return 0;
1518 static LRESULT
1519 TREEVIEW_Destroy (WND *wndPtr)
1521 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1523 TRACE (treeview,"\n");
1524 TREEVIEW_RemoveTree (wndPtr);
1525 if (infoPtr->Timer & TV_REFRESH_TIMER_SET)
1526 KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
1527 if (infoPtr->hwndToolTip)
1528 DestroyWindow32 (infoPtr->hwndToolTip);
1530 COMCTL32_Free (infoPtr);
1531 return 0;
1535 static LRESULT
1536 TREEVIEW_Paint (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1538 HDC32 hdc;
1539 PAINTSTRUCT32 ps;
1541 TRACE (treeview,"\n");
1542 hdc = wParam==0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
1543 TREEVIEW_Refresh (wndPtr);
1544 if(!wParam)
1545 EndPaint32 (wndPtr->hwndSelf, &ps);
1546 TRACE (treeview,"done\n");
1548 return DefWindowProc32A (wndPtr->hwndSelf, WM_PAINT, wParam, lParam);
1551 static LRESULT
1552 TREEVIEW_SetFocus (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1554 TREEVIEW_SendSimpleNotify (wndPtr, NM_SETFOCUS);
1555 SendMessage32A (wndPtr->hwndSelf, WM_PAINT, 0, 0);
1556 return 0;
1559 static LRESULT
1560 TREEVIEW_KillFocus (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1562 TREEVIEW_SendSimpleNotify (wndPtr, NM_KILLFOCUS);
1563 SendMessage32A (wndPtr->hwndSelf, WM_PAINT, 0, 0);
1564 return 0;
1567 static LRESULT
1568 TREEVIEW_EraseBackground (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1570 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1571 HBRUSH32 hBrush = CreateSolidBrush32 (infoPtr->clrBk);
1572 RECT32 rect;
1574 TRACE (treeview,"\n");
1575 GetClientRect32 (wndPtr->hwndSelf, &rect);
1576 FillRect32 ((HDC32)wParam, &rect, hBrush);
1577 DeleteObject32 (hBrush);
1578 return TRUE;
1586 /* Notifications */
1592 static BOOL32
1593 TREEVIEW_SendSimpleNotify (WND *wndPtr, UINT32 code)
1595 NMHDR nmhdr;
1597 TRACE (treeview, "%x\n",code);
1598 nmhdr.hwndFrom = wndPtr->hwndSelf;
1599 nmhdr.idFrom = wndPtr->wIDmenu;
1600 nmhdr.code = code;
1602 return (BOOL32) SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
1603 (WPARAM32)nmhdr.idFrom, (LPARAM)&nmhdr);
1608 static BOOL32
1609 TREEVIEW_SendTreeviewNotify (WND *wndPtr, UINT32 code, UINT32 action,
1610 HTREEITEM oldItem, HTREEITEM newItem)
1613 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1614 NMTREEVIEW32A nmhdr;
1615 TREEVIEW_ITEM *wineItem;
1617 TRACE (treeview,"code:%x action:%x olditem:%x newitem:%x\n",
1618 code,action,(INT32)oldItem,(INT32)newItem);
1619 nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
1620 nmhdr.hdr.idFrom = wndPtr->wIDmenu;
1621 nmhdr.hdr.code = code;
1622 nmhdr.action = action;
1623 if (oldItem) {
1624 wineItem=& infoPtr->items[(INT32)oldItem];
1625 nmhdr.itemOld.mask = wineItem->mask;
1626 nmhdr.itemOld.hItem = wineItem->hItem;
1627 nmhdr.itemOld.state = wineItem->state;
1628 nmhdr.itemOld.stateMask = wineItem->stateMask;
1629 nmhdr.itemOld.iImage = wineItem->iImage;
1630 nmhdr.itemOld.pszText = wineItem->pszText;
1631 nmhdr.itemOld.cchTextMax= wineItem->cchTextMax;
1632 nmhdr.itemOld.iImage = wineItem->iImage;
1633 nmhdr.itemOld.iSelectedImage = wineItem->iSelectedImage;
1634 nmhdr.itemOld.cChildren = wineItem->cChildren;
1635 nmhdr.itemOld.lParam = wineItem->lParam;
1638 if (newItem) {
1639 wineItem=& infoPtr->items[(INT32)newItem];
1640 nmhdr.itemNew.mask = wineItem->mask;
1641 nmhdr.itemNew.hItem = wineItem->hItem;
1642 nmhdr.itemNew.state = wineItem->state;
1643 nmhdr.itemNew.stateMask = wineItem->stateMask;
1644 nmhdr.itemNew.iImage = wineItem->iImage;
1645 nmhdr.itemNew.pszText = wineItem->pszText;
1646 nmhdr.itemNew.cchTextMax= wineItem->cchTextMax;
1647 nmhdr.itemNew.iImage = wineItem->iImage;
1648 nmhdr.itemNew.iSelectedImage = wineItem->iSelectedImage;
1649 nmhdr.itemNew.cChildren = wineItem->cChildren;
1650 nmhdr.itemNew.lParam = wineItem->lParam;
1653 nmhdr.ptDrag.x = 0;
1654 nmhdr.ptDrag.y = 0;
1656 return (BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
1657 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmhdr);
1661 static BOOL32
1662 TREEVIEW_SendTreeviewDnDNotify (WND *wndPtr, UINT32 code, HTREEITEM dragItem,
1663 POINT32 pt)
1665 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1666 NMTREEVIEW32A nmhdr;
1667 TREEVIEW_ITEM *wineItem;
1669 TRACE (treeview,"code:%x dragitem:%x\n", code,(INT32)dragItem);
1671 nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
1672 nmhdr.hdr.idFrom = wndPtr->wIDmenu;
1673 nmhdr.hdr.code = code;
1674 nmhdr.action = 0;
1675 wineItem=& infoPtr->items[(INT32)dragItem];
1676 nmhdr.itemNew.mask = wineItem->mask;
1677 nmhdr.itemNew.hItem = wineItem->hItem;
1678 nmhdr.itemNew.state = wineItem->state;
1679 nmhdr.itemNew.lParam = wineItem->lParam;
1681 nmhdr.ptDrag.x = pt.x;
1682 nmhdr.ptDrag.y = pt.y;
1684 return (BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
1685 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmhdr);
1691 static BOOL32
1692 TREEVIEW_SendDispInfoNotify (WND *wndPtr, TREEVIEW_ITEM *wineItem,
1693 UINT32 code, UINT32 what)
1695 NMTVDISPINFO32A tvdi;
1696 BOOL32 retval;
1697 char *buf;
1699 TRACE (treeview,"item %d, action %x\n",(INT32)wineItem->hItem,what);
1701 tvdi.hdr.hwndFrom = wndPtr->hwndSelf;
1702 tvdi.hdr.idFrom = wndPtr->wIDmenu;
1703 tvdi.hdr.code = code;
1704 tvdi.item.mask = what;
1705 tvdi.item.hItem = wineItem->hItem;
1706 tvdi.item.state = wineItem->state;
1707 tvdi.item.lParam = wineItem->lParam;
1708 tvdi.item.pszText = COMCTL32_Alloc (128*sizeof(char));
1709 buf = tvdi.item.pszText;
1710 retval=(BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
1711 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&tvdi);
1712 if (what & TVIF_TEXT) {
1713 wineItem->pszText = tvdi.item.pszText;
1714 if (buf==tvdi.item.pszText) {
1715 wineItem->cchTextMax = 128;
1716 } else {
1717 TRACE (treeview,"user-supplied buffer\n");
1718 COMCTL32_Free (buf);
1719 wineItem->cchTextMax = 0;
1722 if (what & TVIF_SELECTEDIMAGE)
1723 wineItem->iSelectedImage = tvdi.item.iSelectedImage;
1724 if (what & TVIF_IMAGE)
1725 wineItem->iImage = tvdi.item.iImage;
1726 if (what & TVIF_CHILDREN)
1727 wineItem->cChildren = tvdi.item.cChildren;
1729 return retval;
1734 static BOOL32
1735 TREEVIEW_SendCustomDrawNotify (WND *wndPtr, DWORD dwDrawStage, HDC32 hdc,
1736 RECT32 rc)
1738 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1739 NMTVCUSTOMDRAW nmcdhdr;
1740 LPNMCUSTOMDRAW nmcd;
1742 TRACE (treeview,"drawstage:%lx hdc:%x\n", dwDrawStage, hdc);
1744 nmcd= & nmcdhdr.nmcd;
1745 nmcd->hdr.hwndFrom = wndPtr->hwndSelf;
1746 nmcd->hdr.idFrom = wndPtr->wIDmenu;
1747 nmcd->hdr.code = NM_CUSTOMDRAW;
1748 nmcd->dwDrawStage= dwDrawStage;
1749 nmcd->hdc = hdc;
1750 nmcd->rc.left = rc.left;
1751 nmcd->rc.right = rc.right;
1752 nmcd->rc.bottom = rc.bottom;
1753 nmcd->rc.top = rc.top;
1754 nmcd->dwItemSpec = 0;
1755 nmcd->uItemState = 0;
1756 nmcd->lItemlParam= 0;
1757 nmcdhdr.clrText = infoPtr->clrText;
1758 nmcdhdr.clrTextBk= infoPtr->clrBk;
1759 nmcdhdr.iLevel = 0;
1761 return (BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
1762 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmcdhdr);
1768 /* FIXME: need to find out when the flags in uItemState need to be set */
1770 static BOOL32
1771 TREEVIEW_SendCustomDrawItemNotify (WND *wndPtr, HDC32 hdc,
1772 TREEVIEW_ITEM *wineItem, UINT32 uItemDrawState)
1774 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1775 NMTVCUSTOMDRAW nmcdhdr;
1776 LPNMCUSTOMDRAW nmcd;
1777 DWORD dwDrawStage,dwItemSpec;
1778 UINT32 uItemState;
1780 dwDrawStage=CDDS_ITEM | uItemDrawState;
1781 dwItemSpec=(DWORD)wineItem->hItem;
1782 uItemState=0;
1783 if (wineItem->hItem==infoPtr->selectedItem) uItemState|=CDIS_SELECTED;
1784 if (wineItem->hItem==infoPtr->focusItem) uItemState|=CDIS_FOCUS;
1785 if (wineItem->hItem==infoPtr->hotItem) uItemState|=CDIS_HOT;
1787 nmcd= & nmcdhdr.nmcd;
1788 nmcd->hdr.hwndFrom = wndPtr->hwndSelf;
1789 nmcd->hdr.idFrom = wndPtr->wIDmenu;
1790 nmcd->hdr.code = NM_CUSTOMDRAW;
1791 nmcd->dwDrawStage= dwDrawStage;
1792 nmcd->hdc = hdc;
1793 nmcd->rc.left = wineItem->rect.left;
1794 nmcd->rc.right = wineItem->rect.right;
1795 nmcd->rc.bottom = wineItem->rect.bottom;
1796 nmcd->rc.top = wineItem->rect.top;
1797 nmcd->dwItemSpec = dwItemSpec;
1798 nmcd->uItemState = uItemState;
1799 nmcd->lItemlParam= wineItem->lParam;
1801 nmcdhdr.clrText = infoPtr->clrText;
1802 nmcdhdr.clrTextBk= infoPtr->clrBk;
1803 nmcdhdr.iLevel = wineItem->iLevel;
1805 TRACE (treeview,"drawstage:%lx hdc:%x item:%lx, itemstate:%x\n",
1806 dwDrawStage, hdc, dwItemSpec, uItemState);
1808 return (BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
1809 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmcdhdr);
1814 /* Note:If the specified item is the child of a collapsed parent item,
1815 the parent's list of child items is (recursively) expanded to reveal the
1816 specified item. This is mentioned for TREEVIEW_SelectItem; don't
1817 know if it also applies here.
1821 static LRESULT
1822 TREEVIEW_Expand (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1824 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1825 TREEVIEW_ITEM *wineItem, *parentItem;
1826 UINT32 flag;
1827 INT32 expand;
1829 flag= (UINT32) wParam;
1830 expand= (INT32) lParam;
1831 TRACE (treeview,"flags:%x item:%x\n", expand, wParam);
1832 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)expand);
1833 if (!wineItem) return 0;
1834 if (!wineItem->cChildren) return 0;
1836 if (wineItem->cChildren==I_CHILDRENCALLBACK) {
1837 FIXME (treeview,"we don't handle I_CHILDRENCALLBACK yet\n");
1838 return 0;
1841 if (flag & TVE_TOGGLE) { /* FIXME: check exact behaviour here */
1842 flag &= ~TVE_TOGGLE; /* ie: bitwise ops or 'case' ops */
1843 if (wineItem->state & TVIS_EXPANDED)
1844 flag |= TVE_COLLAPSE;
1845 else
1846 flag |= TVE_EXPAND;
1849 switch (flag) {
1850 case TVE_COLLAPSERESET:
1851 if (!wineItem->state & TVIS_EXPANDED) return 0;
1852 wineItem->state &= ~(TVIS_EXPANDEDONCE | TVIS_EXPANDED);
1853 TREEVIEW_RemoveAllChildren (wndPtr, wineItem);
1854 break;
1856 case TVE_COLLAPSE:
1857 if (!wineItem->state & TVIS_EXPANDED) return 0;
1858 wineItem->state &= ~TVIS_EXPANDED;
1859 break;
1861 case TVE_EXPAND:
1862 if (wineItem->state & TVIS_EXPANDED) return 0;
1863 if (wineItem->parent) {
1864 parentItem=TREEVIEW_ValidItem(infoPtr,wineItem->parent);
1865 TREEVIEW_Expand (wndPtr, wParam, (LPARAM) wineItem->parent);
1867 if (!(wineItem->state & TVIS_EXPANDEDONCE)) {
1868 if (TREEVIEW_SendTreeviewNotify (wndPtr, TVN_ITEMEXPANDING,
1869 0, 0, (HTREEITEM)expand))
1870 return FALSE; /* FIXME: OK? */
1871 wineItem->state |= TVIS_EXPANDED | TVIS_EXPANDEDONCE;
1872 TREEVIEW_SendTreeviewNotify (wndPtr, TVN_ITEMEXPANDED,
1873 0, 0, (HTREEITEM)expand);
1875 wineItem->state |= TVIS_EXPANDED;
1876 break;
1877 case TVE_EXPANDPARTIAL:
1878 FIXME (treeview, "TVE_EXPANDPARTIAL not implemented\n");
1879 wineItem->state ^=TVIS_EXPANDED;
1880 wineItem->state |=TVIS_EXPANDEDONCE;
1881 break;
1884 TREEVIEW_QueueRefresh (wndPtr);
1886 return TRUE;
1893 static TREEVIEW_ITEM *
1894 TREEVIEW_HitTest (WND *wndPtr, POINT32 pt)
1896 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1897 TREEVIEW_ITEM *wineItem;
1898 RECT32 rect;
1900 GetClientRect32 (wndPtr->hwndSelf, &rect);
1902 if (!infoPtr->firstVisible) return NULL;
1904 wineItem=&infoPtr->items [(INT32)infoPtr->firstVisible];
1906 while ((wineItem!=NULL) && (pt.y > wineItem->rect.bottom))
1907 wineItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
1909 if (!wineItem)
1910 return NULL;
1912 return wineItem;
1918 static LRESULT
1919 TREEVIEW_HitTest32 (WND *wndPtr, LPARAM lParam)
1921 LPTVHITTESTINFO lpht=(LPTVHITTESTINFO) lParam;
1922 TREEVIEW_ITEM *wineItem;
1923 RECT32 rect;
1924 UINT32 status,x,y;
1926 GetClientRect32 (wndPtr->hwndSelf, &rect);
1927 status=0;
1928 x=lpht->pt.x;
1929 y=lpht->pt.y;
1930 if (x < rect.left) status|=TVHT_TOLEFT;
1931 if (x > rect.right) status|=TVHT_TORIGHT;
1932 if (y < rect.top ) status|=TVHT_ABOVE;
1933 if (y > rect.bottom) status|=TVHT_BELOW;
1934 if (status) {
1935 lpht->flags=status;
1936 return 0;
1939 wineItem=TREEVIEW_HitTest (wndPtr, lpht->pt);
1940 if (!wineItem) {
1941 lpht->flags=TVHT_NOWHERE;
1942 return 0;
1945 if (x>wineItem->rect.right) {
1946 lpht->flags|=TVHT_ONITEMRIGHT;
1947 return (LRESULT) wineItem->hItem;
1950 if (x<wineItem->rect.left+10) lpht->flags|=TVHT_ONITEMBUTTON;
1952 lpht->flags=TVHT_ONITEMLABEL; /* FIXME: implement other flags */
1953 lpht->hItem=wineItem->hItem;
1955 return (LRESULT) wineItem->hItem;
1961 LRESULT
1962 TREEVIEW_LButtonDoubleClick (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1964 TREEVIEW_ITEM *wineItem;
1965 POINT32 pt;
1967 TRACE (treeview,"\n");
1968 pt.x = (INT32)LOWORD(lParam);
1969 pt.y = (INT32)HIWORD(lParam);
1970 SetFocus32 (wndPtr->hwndSelf);
1972 wineItem=TREEVIEW_HitTest (wndPtr, pt);
1973 if (!wineItem) return 0;
1974 TRACE (treeview,"item %d \n",(INT32)wineItem->hItem);
1976 if (TREEVIEW_SendSimpleNotify (wndPtr, NM_DBLCLK)!=TRUE) { /* FIXME!*/
1977 wineItem->state &= ~TVIS_EXPANDEDONCE;
1978 TREEVIEW_Expand (wndPtr, (WPARAM32) TVE_TOGGLE, (LPARAM) wineItem->hItem);
1980 return TRUE;
1985 static LRESULT
1986 TREEVIEW_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1988 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1989 INT32 iItem;
1990 TVHITTESTINFO ht;
1992 ht.pt.x = (INT32)LOWORD(lParam);
1993 ht.pt.y = (INT32)HIWORD(lParam);
1995 SetFocus32 (wndPtr->hwndSelf);
1996 iItem=TREEVIEW_HitTest32 (wndPtr, (LPARAM) &ht);
1997 TRACE (treeview,"item %d \n",iItem);
1998 if (ht.flags & TVHT_ONITEMBUTTON) {
1999 TREEVIEW_Expand (wndPtr, (WPARAM32) TVE_TOGGLE, (LPARAM) iItem);
2002 infoPtr->uInternalStatus|=TV_LDRAG;
2004 if (TREEVIEW_DoSelectItem (wndPtr, TVGN_CARET, (HTREEITEM)iItem, TVC_BYMOUSE))
2005 return 0;
2008 return 0;
2011 static LRESULT
2012 TREEVIEW_LButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2014 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2015 TREEVIEW_ITEM *editItem;
2016 INT32 ret;
2017 POINT32 pt;
2019 pt.x = (INT32)LOWORD(lParam);
2020 pt.y = (INT32)HIWORD(lParam);
2022 TRACE (treeview,"\n");
2023 if (TREEVIEW_SendSimpleNotify (wndPtr, NM_CLICK)) return 0;
2024 editItem=TREEVIEW_HitTest (wndPtr, pt);
2025 if (!editItem) return 0;
2027 infoPtr->uInternalStatus &= ~(TV_LDRAG | TV_LDRAGGING);
2029 if (wndPtr->dwStyle & TVS_EDITLABELS) {
2030 RECT32 *r;
2031 ret=TREEVIEW_SendDispInfoNotify (wndPtr, editItem,
2032 TVN_BEGINLABELEDIT, 0);
2033 if (ret) return 0;
2034 printf ("edit started..\n");
2035 r=& editItem->rect;
2036 infoPtr->editItem=editItem->hItem;
2037 SetWindowPos32 ( infoPtr->hwndEdit, HWND_TOP, r->left, r->top,
2038 r->right - r->left + 5,
2039 r->bottom - r->top + 2,
2040 SWP_SHOWWINDOW );
2041 SetFocus32 (infoPtr->hwndEdit);
2042 SetWindowText32A ( infoPtr->hwndEdit, editItem->pszText );
2043 SendMessage32A ( infoPtr->hwndEdit, EM_SETSEL32, 0, -1 );
2048 return 0;
2052 static LRESULT
2053 TREEVIEW_RButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2055 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2057 TRACE (treeview,"\n");
2058 infoPtr->uInternalStatus|=TV_RDRAG;
2059 return 0;
2062 static LRESULT
2063 TREEVIEW_RButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2065 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2067 TRACE (treeview,"\n");
2068 if (TREEVIEW_SendSimpleNotify (wndPtr, NM_RCLICK)) return 0;
2069 infoPtr->uInternalStatus&= ~(TV_RDRAG | TV_RDRAGGING);
2070 return 0;
2074 static LRESULT
2075 TREEVIEW_MouseMove (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2077 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2078 TREEVIEW_ITEM *hotItem;
2079 POINT32 pt;
2081 pt.x=(INT32) LOWORD (lParam);
2082 pt.y=(INT32) HIWORD (lParam);
2083 hotItem=TREEVIEW_HitTest (wndPtr, pt);
2084 if (!hotItem) return 0;
2085 infoPtr->focusItem=hotItem->hItem;
2087 if (wndPtr->dwStyle & TVS_DISABLEDRAGDROP) return 0;
2089 if (infoPtr->uInternalStatus & TV_LDRAG) {
2090 TREEVIEW_SendTreeviewDnDNotify (wndPtr, TVN_BEGINDRAG, hotItem->hItem, pt);
2091 infoPtr->uInternalStatus &= ~TV_LDRAG;
2092 infoPtr->uInternalStatus |= TV_LDRAGGING;
2093 infoPtr->dropItem=hotItem->hItem;
2094 return 0;
2097 if (infoPtr->uInternalStatus & TV_RDRAG) {
2098 TREEVIEW_SendTreeviewDnDNotify (wndPtr, TVN_BEGINRDRAG, hotItem->hItem, pt);
2099 infoPtr->uInternalStatus &= ~TV_RDRAG;
2100 infoPtr->uInternalStatus |= TV_RDRAGGING;
2101 infoPtr->dropItem=hotItem->hItem;
2102 return 0;
2105 return 0;
2109 static LRESULT
2110 TREEVIEW_CreateDragImage (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2112 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2113 TREEVIEW_ITEM *dragItem;
2114 INT32 cx,cy;
2115 HDC32 hdc,htopdc;
2116 HWND32 hwtop;
2117 HBITMAP32 hbmp,hOldbmp;
2118 SIZE32 size;
2119 RECT32 rc;
2120 HFONT32 hOldFont;
2121 char *itemtxt;
2123 TRACE (treeview,"\n");
2124 if (!(infoPtr->himlNormal)) return 0;
2125 dragItem=TREEVIEW_ValidItem (infoPtr, (HTREEITEM) lParam);
2127 if (!dragItem) return 0;
2128 itemtxt=dragItem->pszText;
2130 hwtop=GetDesktopWindow32 ();
2131 htopdc= GetDC32 (hwtop);
2132 hdc=CreateCompatibleDC32 (htopdc);
2134 hOldFont=SelectObject32 (hdc, infoPtr->hFont);
2135 GetTextExtentPoint32A (hdc, itemtxt, lstrlen32A (itemtxt), &size);
2136 TRACE (treeview,"%d %d %s %d\n",size.cx,size.cy,itemtxt,lstrlen32A(itemtxt));
2137 hbmp=CreateCompatibleBitmap32 (htopdc, size.cx, size.cy);
2138 hOldbmp=SelectObject32 (hdc, hbmp);
2140 ImageList_GetIconSize (infoPtr->himlNormal, &cx, &cy);
2141 size.cx+=cx;
2142 if (cy>size.cy) size.cy=cy;
2144 infoPtr->dragList=ImageList_Create (size.cx, size.cy, ILC_COLOR, 10, 10);
2145 ImageList_Draw (infoPtr->himlNormal, dragItem->iImage, hdc, 0, 0, ILD_NORMAL);
2148 ImageList_GetImageInfo (infoPtr->himlNormal, dragItem->hItem, &iminfo);
2149 ImageList_AddMasked (infoPtr->dragList, iminfo.hbmImage, CLR_DEFAULT);
2152 /* draw item text */
2154 SetRect32 (&rc, cx, 0, size.cx,size.cy);
2155 DrawText32A (hdc, itemtxt, lstrlen32A (itemtxt), &rc, DT_LEFT);
2156 SelectObject32 (hdc, hOldFont);
2157 SelectObject32 (hdc, hOldbmp);
2159 ImageList_Add (infoPtr->dragList, hbmp, 0);
2161 DeleteDC32 (hdc);
2162 DeleteObject32 (hbmp);
2163 ReleaseDC32 (hwtop, htopdc);
2165 return (LRESULT)infoPtr->dragList;
2170 /* FIXME: handle NM_KILLFocus enzo */
2172 static LRESULT
2173 TREEVIEW_DoSelectItem (WND *wndPtr, INT32 action, HTREEITEM newSelect, INT32 cause)
2176 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2177 TREEVIEW_ITEM *prevItem,*wineItem, *parentItem;
2178 INT32 prevSelect;
2180 TRACE (treeview,"item %x, flag %x, cause %x\n", (INT32)newSelect, action, cause);
2181 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)newSelect);
2183 if (wineItem) {
2184 if (wineItem->parent) {
2185 parentItem=TREEVIEW_ValidItem (infoPtr, wineItem->parent);
2186 if (!(parentItem->state & TVIS_EXPANDED))
2187 TREEVIEW_Expand (wndPtr, TVE_EXPAND, (LPARAM) wineItem->parent);
2191 switch (action) {
2192 case TVGN_CARET:
2193 prevSelect=(INT32)infoPtr->selectedItem;
2194 if ((HTREEITEM)prevSelect==newSelect) return FALSE;
2195 prevItem= TREEVIEW_ValidItem (infoPtr, (HTREEITEM)prevSelect);
2196 if (newSelect)
2197 if (TREEVIEW_SendTreeviewNotify (wndPtr, TVN_SELCHANGING,
2198 cause, (HTREEITEM)prevSelect, (HTREEITEM)newSelect))
2199 return FALSE; /* FIXME: OK? */
2201 if (prevItem) prevItem->state &= ~TVIS_SELECTED;
2202 infoPtr->selectedItem=(HTREEITEM)newSelect;
2203 if (wineItem) wineItem->state |=TVIS_SELECTED;
2204 if (newSelect)
2205 TREEVIEW_SendTreeviewNotify (wndPtr, TVN_SELCHANGED,
2206 cause, (HTREEITEM)prevSelect, (HTREEITEM)newSelect);
2207 break;
2208 case TVGN_DROPHILITE:
2209 prevItem= TREEVIEW_ValidItem (infoPtr, infoPtr->dropItem);
2210 if (prevItem) prevItem->state &= ~TVIS_DROPHILITED;
2211 infoPtr->dropItem=(HTREEITEM)newSelect;
2212 if (wineItem) wineItem->state |=TVIS_DROPHILITED;
2213 break;
2214 case TVGN_FIRSTVISIBLE:
2215 FIXME (treeview, "FIRSTVISIBLE not implemented\n");
2216 break;
2219 TREEVIEW_QueueRefresh (wndPtr);
2221 return TRUE;
2225 static LRESULT
2226 TREEVIEW_SelectItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2229 return TREEVIEW_DoSelectItem (wndPtr, wParam, (HTREEITEM) lParam, TVC_UNKNOWN);
2235 static LRESULT
2236 TREEVIEW_GetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2239 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2241 TRACE (treeview,"%x\n",infoPtr->hFont);
2242 return infoPtr->hFont;
2245 static LRESULT
2246 TREEVIEW_SetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2249 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2250 TEXTMETRIC32A tm;
2251 LOGFONT32A logFont;
2252 HFONT32 hFont, hOldFont;
2253 INT32 height;
2254 HDC32 hdc;
2256 TRACE (treeview,"%x %lx\n",wParam, lParam);
2258 infoPtr->hFont = (HFONT32)wParam;
2260 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
2262 GetObject32A (infoPtr->hFont, sizeof (LOGFONT32A), &logFont);
2263 logFont.lfWeight=FW_BOLD;
2264 infoPtr->hBoldFont = CreateFontIndirect32A (&logFont);
2266 hdc = GetDC32 (0);
2267 hOldFont = SelectObject32 (hdc, hFont);
2268 GetTextMetrics32A (hdc, &tm);
2269 height= tm.tmHeight + tm.tmExternalLeading;
2270 if (height>infoPtr->uRealItemHeight)
2271 infoPtr->uRealItemHeight=height;
2272 SelectObject32 (hdc, hOldFont);
2273 ReleaseDC32 (0, hdc);
2275 if (lParam)
2276 TREEVIEW_QueueRefresh (wndPtr);
2278 return 0;
2282 /* FIXME: does KEYDOWN also send notifications?? If so, use
2283 TREEVIEW_DoSelectItem.
2287 static LRESULT
2288 TREEVIEW_KeyDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2290 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2291 TREEVIEW_ITEM *prevItem,*newItem;
2292 int prevSelect;
2295 TRACE (treeview,"%x %lx\n",wParam, lParam);
2296 prevSelect=(INT32)infoPtr->selectedItem;
2297 if (!prevSelect) return FALSE;
2299 prevItem= TREEVIEW_ValidItem (infoPtr, (HTREEITEM)prevSelect);
2301 newItem=NULL;
2302 switch (wParam) {
2303 case VK_UP:
2304 newItem=TREEVIEW_GetPrevListItem (infoPtr, prevItem);
2305 if (!newItem)
2306 newItem=& infoPtr->items[(INT32)infoPtr->TopRootItem];
2307 break;
2308 case VK_DOWN:
2309 newItem=TREEVIEW_GetNextListItem (infoPtr, prevItem);
2310 if (!newItem) newItem=prevItem;
2311 break;
2312 case VK_HOME:
2313 newItem=& infoPtr->items[(INT32)infoPtr->TopRootItem];
2314 break;
2315 case VK_END:
2316 newItem=& infoPtr->items[(INT32)infoPtr->TopRootItem];
2317 newItem=TREEVIEW_GetLastListItem (infoPtr, newItem);
2318 break;
2319 case VK_PRIOR:
2320 case VK_NEXT:
2321 case VK_BACK:
2322 case VK_RETURN:
2323 FIXME (treeview, "%x not implemented\n", wParam);
2324 break;
2327 if (!newItem) return FALSE;
2329 if (prevItem!=newItem) {
2330 prevItem->state &= ~TVIS_SELECTED;
2331 newItem->state |= TVIS_SELECTED;
2332 infoPtr->selectedItem=newItem->hItem;
2333 TREEVIEW_QueueRefresh (wndPtr);
2334 return TRUE;
2337 return FALSE;
2342 static LRESULT
2343 TREEVIEW_VScroll (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2346 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2347 int maxHeight;
2349 TRACE (treeview,"wp %x, lp %lx\n", wParam, lParam);
2350 if (!infoPtr->uInternalStatus & TV_VSCROLL) return FALSE;
2352 switch (LOWORD (wParam)) {
2353 case SB_LINEUP:
2354 if (!infoPtr->cy) return FALSE;
2355 infoPtr->cy -= infoPtr->uRealItemHeight;
2356 if (infoPtr->cy < 0) infoPtr->cy=0;
2357 break;
2358 case SB_LINEDOWN:
2359 maxHeight=infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
2360 if (infoPtr->cy == maxHeight) return FALSE;
2361 infoPtr->cy += infoPtr->uRealItemHeight;
2362 if (infoPtr->cy > maxHeight)
2363 infoPtr->cy = maxHeight;
2364 break;
2365 case SB_PAGEUP:
2366 if (!infoPtr->cy) return FALSE;
2367 infoPtr->cy -= infoPtr->uVisibleHeight;
2368 if (infoPtr->cy < 0) infoPtr->cy=0;
2369 break;
2370 case SB_PAGEDOWN:
2371 maxHeight=infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
2372 if (infoPtr->cy == maxHeight) return FALSE;
2373 infoPtr->cy += infoPtr->uVisibleHeight;
2374 if (infoPtr->cy > maxHeight)
2375 infoPtr->cy = maxHeight;
2376 break;
2377 case SB_THUMBTRACK:
2378 infoPtr->cy = HIWORD (wParam);
2379 break;
2383 TREEVIEW_QueueRefresh (wndPtr);
2384 return TRUE;
2387 static LRESULT
2388 TREEVIEW_HScroll (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
2390 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2391 int maxWidth;
2393 TRACE (treeview,"wp %lx, lp %x\n", lParam, wParam);
2395 if (!infoPtr->uInternalStatus & TV_HSCROLL) return FALSE;
2397 switch (LOWORD (wParam)) {
2398 case SB_LINEUP:
2399 if (!infoPtr->cx) return FALSE;
2400 infoPtr->cx -= infoPtr->uRealItemHeight;
2401 if (infoPtr->cx < 0) infoPtr->cx=0;
2402 break;
2403 case SB_LINEDOWN:
2404 maxWidth=infoPtr->uTotalWidth-infoPtr->uVisibleWidth;
2405 if (infoPtr->cx == maxWidth) return FALSE;
2406 infoPtr->cx += infoPtr->uRealItemHeight; /*FIXME */
2407 if (infoPtr->cx > maxWidth)
2408 infoPtr->cx = maxWidth;
2409 break;
2410 case SB_PAGEUP:
2411 if (!infoPtr->cx) return FALSE;
2412 infoPtr->cx -= infoPtr->uVisibleWidth;
2413 if (infoPtr->cx < 0) infoPtr->cx=0;
2414 break;
2415 case SB_PAGEDOWN:
2416 maxWidth=infoPtr->uTotalWidth-infoPtr->uVisibleWidth;
2417 if (infoPtr->cx == maxWidth) return FALSE;
2418 infoPtr->cx += infoPtr->uVisibleWidth;
2419 if (infoPtr->cx > maxWidth)
2420 infoPtr->cx = maxWidth;
2421 break;
2422 case SB_THUMBTRACK:
2423 infoPtr->cx = HIWORD (wParam);
2424 break;
2428 TREEVIEW_QueueRefresh (wndPtr);
2429 return TRUE;
2435 LRESULT WINAPI
2436 TREEVIEW_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
2438 WND *wndPtr = WIN_FindWndPtr(hwnd);
2441 switch (uMsg) {
2442 case TVM_INSERTITEM32A:
2443 return TREEVIEW_InsertItem32A (wndPtr, wParam, lParam);
2445 case TVM_INSERTITEM32W:
2446 FIXME (treeview, "Unimplemented msg TVM_INSERTITEM32W\n");
2447 return 0;
2449 case TVM_DELETEITEM:
2450 return TREEVIEW_DeleteItem (wndPtr, wParam, lParam);
2452 case TVM_EXPAND:
2453 return TREEVIEW_Expand (wndPtr, wParam, lParam);
2455 case TVM_GETITEMRECT:
2456 return TREEVIEW_GetItemRect (wndPtr, wParam, lParam);
2458 case TVM_GETCOUNT:
2459 return TREEVIEW_GetCount (wndPtr, wParam, lParam);
2461 case TVM_GETINDENT:
2462 return TREEVIEW_GetIndent (wndPtr);
2464 case TVM_SETINDENT:
2465 return TREEVIEW_SetIndent (wndPtr, wParam);
2467 case TVM_GETIMAGELIST:
2468 return TREEVIEW_GetImageList (wndPtr, wParam, lParam);
2470 case TVM_SETIMAGELIST:
2471 return TREEVIEW_SetImageList (wndPtr, wParam, lParam);
2473 case TVM_GETNEXTITEM:
2474 return TREEVIEW_GetNextItem (wndPtr, wParam, lParam);
2476 case TVM_SELECTITEM:
2477 return TREEVIEW_SelectItem (wndPtr, wParam, lParam);
2479 case TVM_GETITEM32A:
2480 return TREEVIEW_GetItem32A (wndPtr, wParam, lParam);
2482 case TVM_GETITEM32W:
2483 FIXME (treeview, "Unimplemented msg TVM_GETITEM32W\n");
2484 return 0;
2486 case TVM_SETITEM32A:
2487 return TREEVIEW_SetItem32A (wndPtr, wParam, lParam);
2489 case TVM_SETITEM32W:
2490 FIXME (treeview, "Unimplemented msg TVM_SETITEMW\n");
2491 return 0;
2493 case TVM_EDITLABEL32A:
2494 FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32A \n");
2495 return 0;
2497 case TVM_EDITLABEL32W:
2498 FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32W \n");
2499 return 0;
2501 case TVM_GETEDITCONTROL:
2502 return TREEVIEW_GetEditControl (wndPtr);
2504 case TVM_GETVISIBLECOUNT:
2505 return TREEVIEW_GetVisibleCount (wndPtr, wParam, lParam);
2507 case TVM_HITTEST:
2508 return TREEVIEW_HitTest32 (wndPtr, lParam);
2510 case TVM_CREATEDRAGIMAGE:
2511 return TREEVIEW_CreateDragImage (wndPtr, wParam, lParam);
2513 case TVM_SORTCHILDREN:
2514 FIXME (treeview, "Unimplemented msg TVM_SORTCHILDREN\n");
2515 return 0;
2517 case TVM_ENSUREVISIBLE:
2518 FIXME (treeview, "Unimplemented msg TVM_ENSUREVISIBLE\n");
2519 return 0;
2521 case TVM_SORTCHILDRENCB:
2522 FIXME (treeview, "Unimplemented msg TVM_SORTCHILDRENCB\n");
2523 return 0;
2525 case TVM_ENDEDITLABELNOW:
2526 FIXME (treeview, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
2527 return 0;
2529 case TVM_GETISEARCHSTRING32A:
2530 FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
2531 return 0;
2533 case TVM_GETISEARCHSTRING32W:
2534 FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
2535 return 0;
2537 case TVM_GETTOOLTIPS:
2538 return TREEVIEW_GetToolTips (wndPtr);
2540 case TVM_SETTOOLTIPS:
2541 return TREEVIEW_SetToolTips (wndPtr, wParam);
2543 case TVM_SETINSERTMARK:
2544 FIXME (treeview, "Unimplemented msg TVM_SETINSERTMARK\n");
2545 return 0;
2547 case TVM_SETITEMHEIGHT:
2548 return TREEVIEW_SetItemHeight (wndPtr, wParam);
2550 case TVM_GETITEMHEIGHT:
2551 return TREEVIEW_GetItemHeight (wndPtr);
2553 case TVM_SETBKCOLOR:
2554 return TREEVIEW_SetBkColor (wndPtr, wParam, lParam);
2556 case TVM_SETTEXTCOLOR:
2557 return TREEVIEW_SetTextColor (wndPtr, wParam, lParam);
2559 case TVM_GETBKCOLOR:
2560 return TREEVIEW_GetBkColor (wndPtr);
2562 case TVM_GETTEXTCOLOR:
2563 return TREEVIEW_GetTextColor (wndPtr);
2565 case TVM_SETSCROLLTIME:
2566 FIXME (treeview, "Unimplemented msg TVM_SETSCROLLTIME\n");
2567 return 0;
2569 case TVM_GETSCROLLTIME:
2570 FIXME (treeview, "Unimplemented msg TVM_GETSCROLLTIME\n");
2571 return 0;
2573 case TVM_SETINSERTMARKCOLOR:
2574 FIXME (treeview, "Unimplemented msg TVM_SETINSERTMARKCOLOR\n");
2575 return 0;
2577 case TVM_SETUNICODEFORMAT:
2578 FIXME (treeview, "Unimplemented msg TVM_SETUNICODEFORMAT\n");
2579 return 0;
2581 case TVM_GETUNICODEFORMAT:
2582 FIXME (treeview, "Unimplemented msg TVM_GETUNICODEFORMAT\n");
2583 return 0;
2585 case WM_COMMAND:
2586 return TREEVIEW_Command (wndPtr, wParam, lParam);
2588 case WM_CREATE:
2589 return TREEVIEW_Create (wndPtr, wParam, lParam);
2591 case WM_DESTROY:
2592 return TREEVIEW_Destroy (wndPtr);
2594 /* case WM_ENABLE: */
2596 case WM_ERASEBKGND:
2597 return TREEVIEW_EraseBackground (wndPtr, wParam, lParam);
2599 case WM_GETDLGCODE:
2600 return DLGC_WANTARROWS | DLGC_WANTCHARS;
2602 case WM_PAINT:
2603 return TREEVIEW_Paint (wndPtr, wParam, lParam);
2605 case WM_GETFONT:
2606 return TREEVIEW_GetFont (wndPtr, wParam, lParam);
2608 case WM_SETFONT:
2609 return TREEVIEW_SetFont (wndPtr, wParam, lParam);
2611 case WM_KEYDOWN:
2612 return TREEVIEW_KeyDown (wndPtr, wParam, lParam);
2615 case WM_SETFOCUS:
2616 return TREEVIEW_SetFocus (wndPtr, wParam, lParam);
2618 case WM_KILLFOCUS:
2619 return TREEVIEW_KillFocus (wndPtr, wParam, lParam);
2622 case WM_LBUTTONDOWN:
2623 return TREEVIEW_LButtonDown (wndPtr, wParam, lParam);
2625 case WM_LBUTTONUP:
2626 return TREEVIEW_LButtonUp (wndPtr, wParam, lParam);
2628 case WM_LBUTTONDBLCLK:
2629 return TREEVIEW_LButtonDoubleClick (wndPtr, wParam, lParam);
2631 case WM_RBUTTONDOWN:
2632 return TREEVIEW_RButtonDown (wndPtr, wParam, lParam);
2634 case WM_RBUTTONUP:
2635 return TREEVIEW_RButtonUp (wndPtr, wParam, lParam);
2637 case WM_MOUSEMOVE:
2638 return TREEVIEW_MouseMove (wndPtr, wParam, lParam);
2641 /* case WM_SYSCOLORCHANGE: */
2642 case WM_STYLECHANGED:
2643 return TREEVIEW_StyleChanged (wndPtr, wParam, lParam);
2645 /* case WM_SETREDRAW: */
2647 case WM_TIMER:
2648 return TREEVIEW_HandleTimer (wndPtr, wParam, lParam);
2650 case WM_SIZE:
2651 return TREEVIEW_Size (wndPtr, wParam,lParam);
2653 case WM_HSCROLL:
2654 return TREEVIEW_HScroll (wndPtr, wParam, lParam);
2655 case WM_VSCROLL:
2656 return TREEVIEW_VScroll (wndPtr, wParam, lParam);
2658 case WM_DRAWITEM:
2659 printf ("drawItem\n");
2660 return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
2662 default:
2663 if (uMsg >= WM_USER)
2664 FIXME (treeview, "Unknown msg %04x wp=%08x lp=%08lx\n",
2665 uMsg, wParam, lParam);
2666 return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
2668 return 0;
2672 VOID
2673 TREEVIEW_Register (VOID)
2675 WNDCLASS32A wndClass;
2677 TRACE (treeview,"\n");
2679 if (GlobalFindAtom32A (WC_TREEVIEW32A)) return;
2681 ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
2682 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
2683 wndClass.lpfnWndProc = (WNDPROC32)TREEVIEW_WindowProc;
2684 wndClass.cbClsExtra = 0;
2685 wndClass.cbWndExtra = sizeof(TREEVIEW_INFO *);
2686 wndClass.hCursor = LoadCursor32A (0, IDC_ARROW32A);
2687 wndClass.hbrBackground = 0;
2688 wndClass.lpszClassName = WC_TREEVIEW32A;
2690 RegisterClass32A (&wndClass);
2694 VOID
2695 TREEVIEW_Unregister (VOID)
2697 if (GlobalFindAtom32A (WC_TREEVIEW32A))
2698 UnregisterClass32A (WC_TREEVIEW32A, (HINSTANCE32)NULL);