3 * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
4 * Copyright 1998 Alex Priem <alexp@sci.kun.nl>
8 * - Nearly all notifications.
10 * list-handling stuff: sort, sorted insertitem.
13 -small array containing info about positions.
14 -better implementation of DrawItem (connecting lines).
15 -implement partial drawing?
16 * Expand: -ctlmacro expands twice ->toggle.
23 -GetNextItem: add flag for traversing visible items
24 -DblClick: ctlmacro.exe's NM_DBLCLK seems to go wrong (returns FALSE).
34 #include <asm/bitops.h> /* FIXME: linux specific */
36 #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
39 TREEVIEW_SendSimpleNotify (WND
*wndPtr
, UINT32 code
);
41 TREEVIEW_SendTreeviewNotify (WND
*wndPtr
, UINT32 code
, UINT32 action
,
42 INT32 oldItem
, INT32 newItem
, POINT32 pt
);
44 TREEVIEW_SelectItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
);
46 TREEVIEW_Refresh (WND
*wndPtr
, HDC32 hdc
);
52 /* helper functions. Work with the assumption that validity of operands
53 is checked beforehand */
56 static TREEVIEW_ITEM
*
57 TREEVIEW_ValidItem (TREEVIEW_INFO
*infoPtr
,int handle
)
60 if ((!handle
) || (handle
>infoPtr
->uMaxHandle
)) return NULL
;
61 if (test_bit (handle
, infoPtr
->freeList
)) return NULL
;
63 return & infoPtr
->items
[handle
];
68 static TREEVIEW_ITEM
*TREEVIEW_GetPrevListItem (TREEVIEW_INFO
*infoPtr
,
69 TREEVIEW_ITEM
*tvItem
)
72 TREEVIEW_ITEM
*wineItem
;
74 if (tvItem
->upsibling
)
75 return (& infoPtr
->items
[tvItem
->upsibling
]);
78 while (wineItem
->parent
) {
79 wineItem
=& infoPtr
->items
[wineItem
->parent
];
80 if (wineItem
->upsibling
)
81 return (& infoPtr
->items
[wineItem
->upsibling
]);
87 static TREEVIEW_ITEM
*TREEVIEW_GetNextListItem (TREEVIEW_INFO
*infoPtr
,
88 TREEVIEW_ITEM
*tvItem
)
91 TREEVIEW_ITEM
*wineItem
;
94 return (& infoPtr
->items
[tvItem
->sibling
]);
97 while (wineItem
->parent
) {
98 wineItem
=& infoPtr
->items
[wineItem
->parent
];
99 if (wineItem
->sibling
)
100 return (& infoPtr
->items
[wineItem
->sibling
]);
106 static TREEVIEW_ITEM
*TREEVIEW_GetLastListItem (TREEVIEW_INFO
*infoPtr
)
109 TREEVIEW_ITEM
*wineItem
;
112 if (infoPtr
->TopRootItem
)
113 wineItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
114 while (wineItem
->sibling
)
115 wineItem
=& infoPtr
->items
[wineItem
->sibling
];
124 TREEVIEW_RemoveItem (TREEVIEW_INFO
*infoPtr
, TREEVIEW_ITEM
*wineItem
)
127 TREEVIEW_ITEM
*parentItem
, *upsiblingItem
, *siblingItem
;
130 iItem
=wineItem
->hItem
;
131 set_bit ( iItem
& 31, &infoPtr
->freeList
[iItem
>>5]);
132 infoPtr
->uNumItems
--;
134 if (wineItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
135 HeapFree (GetProcessHeap (), 0, wineItem
->pszText
);
137 if (wineItem
->parent
) {
138 parentItem
=& infoPtr
->items
[ wineItem
->parent
];
139 if (parentItem
->cChildren
==1) {
140 parentItem
->cChildren
=0;
141 parentItem
->firstChild
=0;
144 parentItem
->cChildren
--;
145 if (parentItem
->firstChild
==iItem
)
146 parentItem
->firstChild
=wineItem
->sibling
;
150 if (iItem
==infoPtr
->TopRootItem
)
151 infoPtr
->TopRootItem
=wineItem
->sibling
;
152 if (wineItem
->upsibling
) {
153 upsiblingItem
=& infoPtr
->items
[wineItem
->upsibling
];
154 upsiblingItem
->sibling
=wineItem
->sibling
;
156 if (wineItem
->sibling
) {
157 siblingItem
=& infoPtr
->items
[wineItem
->sibling
];
158 siblingItem
->upsibling
=wineItem
->upsibling
;
164 static void TREEVIEW_RemoveAllChildren (TREEVIEW_INFO
*infoPtr
,
165 TREEVIEW_ITEM
*parentItem
)
168 TREEVIEW_ITEM
*killItem
;
171 kill
=parentItem
->firstChild
;
173 set_bit ( kill
& 31, &infoPtr
->freeList
[kill
>>5]);
174 killItem
=& infoPtr
->items
[kill
];
175 if (killItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
176 HeapFree (GetProcessHeap (), 0, killItem
->pszText
);
177 kill
=killItem
->sibling
;
179 infoPtr
->uNumItems
-= parentItem
->cChildren
;
180 parentItem
->firstChild
= 0;
181 parentItem
->cChildren
= 0;
185 /* Note:TREEVIEW_RemoveTree doesn't remove infoPtr itself */
187 static void TREEVIEW_RemoveTree (TREEVIEW_INFO
*infoPtr
)
191 TREEVIEW_ITEM
*killItem
;
194 for (i
=1; i
<=infoPtr
->uMaxHandle
; i
++)
195 if (!test_bit (i
, infoPtr
->freeList
)) {
196 killItem
=& infoPtr
->items
[i
];
197 if (killItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
198 HeapFree (GetProcessHeap (), 0, killItem
->pszText
);
201 if (infoPtr
->uNumPtrsAlloced
) {
202 HeapFree (GetProcessHeap (), 0, infoPtr
->items
);
203 HeapFree (GetProcessHeap (), 0, infoPtr
->freeList
);
204 infoPtr
->uNumItems
=0;
205 infoPtr
->uNumPtrsAlloced
=0;
206 infoPtr
->uMaxHandle
=0;
220 TREEVIEW_GetImageList (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
222 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
224 TRACE (treeview
,"\n");
226 if (infoPtr
==NULL
) return 0;
228 if ((INT32
)wParam
== TVSIL_NORMAL
)
229 return (LRESULT
) infoPtr
->himlNormal
;
230 if ((INT32
)wParam
== TVSIL_STATE
)
231 return (LRESULT
) infoPtr
->himlState
;
240 TREEVIEW_SetImageList (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
242 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
245 switch ((INT32
)wParam
) {
247 himlTemp
= infoPtr
->himlNormal
;
248 infoPtr
->himlNormal
= (HIMAGELIST
)lParam
;
249 return (LRESULT
)himlTemp
;
252 himlTemp
= infoPtr
->himlState
;
253 infoPtr
->himlState
= (HIMAGELIST
)lParam
;
254 return (LRESULT
)himlTemp
;
257 return (LRESULT
)NULL
;
263 TREEVIEW_SetItemHeight (WND
*wndPtr
, WPARAM32 wParam
)
265 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
266 INT32 prevHeight
=infoPtr
->uItemHeight
;
272 hdc
=GetDC32 (wndPtr
->hwndSelf
);
273 infoPtr
->uItemHeight
=-1;
274 GetTextMetrics32A (hdc
, &tm
);
275 infoPtr
->uRealItemHeight
= tm
.tmHeight
+ tm
.tmExternalLeading
;
276 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
280 /* FIXME: check wParam > imagelist height */
282 if (!(wndPtr
->dwStyle
& TVS_NONEVENHEIGHT
))
283 infoPtr
->uItemHeight
= (INT32
) wParam
& 0xfffffffe;
288 TREEVIEW_GetItemHeight (WND
*wndPtr
)
290 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
292 return infoPtr
->uItemHeight
;
296 TREEVIEW_SetTextColor (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
298 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
299 COLORREF prevColor
=infoPtr
->clrText
;
301 infoPtr
->clrText
=(COLORREF
) lParam
;
302 return (LRESULT
) prevColor
;
306 TREEVIEW_GetTextColor (WND
*wndPtr
)
308 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
310 return (LRESULT
) infoPtr
->clrText
;
315 TREEVIEW_DrawItem (WND
*wndPtr
, HDC32 hdc
, TREEVIEW_ITEM
*wineItem
,
316 TREEVIEW_ITEM
*upperItem
, int indent
)
318 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
319 INT32 oldBkMode
,center
,xpos
;
321 UINT32 uTextJustify
= DT_LEFT
;
322 HPEN32 hOldPen
, hnewPen
,hRootPen
;
325 hnewPen
= CreatePen32(PS_DOT
, 0, GetSysColor32(COLOR_WINDOWTEXT
) );
326 hOldPen
= SelectObject32( hdc
, hnewPen
);
330 upper
=upperItem
->rect
;
335 center
=(r
.top
+r
.bottom
)/2;
338 if (wndPtr
->dwStyle
& TVS_HASLINES
) {
340 if ((wndPtr
->dwStyle
& TVS_LINESATROOT
) && (indent
==0)) {
341 points
[0].y
=points
[1].y
=center
;
342 points
[2].y
=upper
.top
;
343 points
[1].x
=points
[2].x
=upper
.left
;
344 points
[0].x
=upper
.left
+12;
347 Polyline32 (hdc
,points
,3);
350 points
[0].y
=points
[1].y
=center
;
351 points
[2].y
=upper
.top
;
352 points
[1].x
=points
[2].x
=upper
.left
+13;
353 points
[0].x
=upper
.left
+25;
355 Polyline32 (hdc
,points
,3);
359 DeleteObject32(hnewPen
);
360 SelectObject32(hdc
, hOldPen
);
362 if ((wndPtr
->dwStyle
& TVS_HASBUTTONS
) && (wineItem
->cChildren
)) {
364 hRootPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOW) );
365 SelectObject32( hdc, hRootPen );
368 Rectangle32 (hdc
, xpos
-4, center
-4, xpos
+5, center
+5);
369 MoveToEx32 (hdc
, xpos
-2, center
, NULL
);
370 LineTo32 (hdc
, xpos
+3, center
);
371 if (!(wineItem
->state
& TVIS_EXPANDED
)) {
372 MoveToEx32 (hdc
, xpos
, center
-2, NULL
);
373 LineTo32 (hdc
, xpos
, center
+3);
375 /* DeleteObject32(hRootPen); */
381 if (wineItem
->mask
& TVIF_IMAGE
) {
382 if (wineItem
->iImage
!=I_IMAGECALLBACK
) {
383 if (infoPtr
->himlNormal
) {
384 ImageList_Draw (infoPtr
->himlNormal
,wineItem
->iImage
, hdc
,
385 xpos
-2, r
.top
+1, ILD_NORMAL
);
392 if ((wineItem
->mask
& TVIF_TEXT
) && (wineItem
->pszText
)) {
393 if (wineItem
->state
& TVIS_SELECTED
) {
394 oldBkMode
= SetBkMode32(hdc
, OPAQUE
);
395 oldBkColor
= SetBkColor32 (hdc
, GetSysColor32( COLOR_HIGHLIGHT
));
396 SetTextColor32 (hdc
, GetSysColor32(COLOR_HIGHLIGHTTEXT
));
399 oldBkMode
= SetBkMode32(hdc
, TRANSPARENT
);
403 if (infoPtr
->clrText
==-1)
404 SetTextColor32 (hdc
, COLOR_BTNTEXT
);
406 SetTextColor32 (hdc
, infoPtr
->clrText
); /* FIXME: retval */
407 DrawText32A(hdc
, wineItem
->pszText
, lstrlen32A(wineItem
->pszText
),
408 &r
, uTextJustify
|DT_VCENTER
|DT_SINGLELINE
);
409 if (oldBkMode
!= TRANSPARENT
)
410 SetBkMode32(hdc
, oldBkMode
);
411 if (wineItem
->state
& TVIS_SELECTED
)
412 SetBkColor32 (hdc
, oldBkColor
);
415 return wineItem
->rect
.right
;
425 TREEVIEW_GetItemRect (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
427 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
428 TREEVIEW_ITEM
*wineItem
;
432 TRACE (treeview
,"\n");
433 if (infoPtr
==NULL
) return FALSE
;
435 iItem
= (INT32
)lParam
;
436 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
437 if (!wineItem
) return FALSE
;
439 wineItem
=& infoPtr
->items
[ iItem
];
440 if (!wineItem
->visible
) return FALSE
;
442 lpRect
= (LPRECT32
)lParam
;
443 if (lpRect
== NULL
) return FALSE
;
445 if ((INT32
) wParam
) {
446 lpRect
->left
= wineItem
->text
.left
;
447 lpRect
->right
= wineItem
->text
.right
;
448 lpRect
->bottom
= wineItem
->text
.bottom
;
449 lpRect
->top
= wineItem
->text
.top
;
451 lpRect
->left
= wineItem
->rect
.left
;
452 lpRect
->right
= wineItem
->rect
.right
;
453 lpRect
->bottom
= wineItem
->rect
.bottom
;
454 lpRect
->top
= wineItem
->rect
.top
;
463 TREEVIEW_GetVisibleCount (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
466 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
468 TRACE (treeview
,"\n");
470 return (LRESULT
) infoPtr
->uVisibleHeight
/ infoPtr
->uRealItemHeight
;
476 TREEVIEW_SetItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
478 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
479 TREEVIEW_ITEM
*wineItem
;
483 TRACE (treeview
,"\n");
484 tvItem
=(LPTVITEM
) lParam
;
487 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
488 if (!wineItem
) return FALSE
;
490 if (tvItem
->mask
& TVIF_CHILDREN
) {
491 wineItem
->cChildren
=tvItem
->cChildren
;
494 if (tvItem
->mask
& TVIF_IMAGE
) {
495 wineItem
->iImage
=tvItem
->iImage
;
498 if (tvItem
->mask
& TVIF_INTEGRAL
) {
499 /* wineItem->iIntegral=tvItem->iIntegral; */
502 if (tvItem
->mask
& TVIF_PARAM
) {
503 wineItem
->lParam
=tvItem
->lParam
;
506 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
) {
507 wineItem
->iSelectedImage
=tvItem
->iSelectedImage
;
510 if (tvItem
->mask
& TVIF_STATE
) {
511 wineItem
->state
=tvItem
->state
& tvItem
->stateMask
;
514 if (tvItem
->mask
& TVIF_TEXT
) {
515 len
=tvItem
->cchTextMax
;
516 if (len
>wineItem
->cchTextMax
) {
517 HeapFree (GetProcessHeap (), 0, wineItem
->pszText
);
518 wineItem
->pszText
= HeapAlloc (GetProcessHeap (),
519 HEAP_ZERO_MEMORY
, len
+1);
521 lstrcpyn32A (wineItem
->pszText
, tvItem
->pszText
,len
);
532 TREEVIEW_Refresh (WND
*wndPtr
, HDC32 hdc
)
535 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
536 HFONT32 hFont
, hOldFont
;
539 INT32 iItem
, indent
, x
, y
, height
;
540 INT32 viewtop
,viewbottom
,viewleft
,viewright
;
541 TREEVIEW_ITEM
*wineItem
, *prevItem
;
543 TRACE (treeview
,"\n");
545 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
) {
546 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
547 infoPtr
->Timer
&= ~TV_REFRESH_TIMER_SET
;
551 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
552 if ((rect
.left
-rect
.right
==0) || (rect
.top
-rect
.bottom
==0)) return;
554 viewbottom
=infoPtr
->cy
+ rect
.bottom
-rect
.top
;
555 viewleft
=infoPtr
->cx
;
556 viewright
=infoPtr
->cx
+ rect
.right
-rect
.left
;
558 infoPtr
->uVisibleHeight
=viewbottom
- viewtop
;
560 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject32 (DEFAULT_GUI_FONT
);
561 hOldFont
= SelectObject32 (hdc
, hFont
);
563 /* draw background */
564 hbrBk
= GetSysColorBrush32(COLOR_WINDOW
);
565 FillRect32(hdc
, &rect
, hbrBk
);
568 iItem
=infoPtr
->TopRootItem
;
569 infoPtr
->firstVisible
=0;
573 TRACE (treeview
, "[%d %d %d %d]\n",viewtop
,viewbottom
,viewleft
,viewright
);
577 wineItem
= & infoPtr
->items
[iItem
];
579 TRACE (treeview
, "%d %d [%d %d %d %d] (%s)\n",y
,x
,
580 wineItem
->rect
.top
, wineItem
->rect
.bottom
,
581 wineItem
->rect
.left
, wineItem
->rect
.right
,
584 height
=infoPtr
->uRealItemHeight
* wineItem
->iIntegral
;
585 if ((y
>= viewtop
) && (y
<= viewbottom
) &&
586 (x
>= viewleft
) && (x
<= viewright
)) {
587 wineItem
->rect
.top
= y
- infoPtr
->cy
+ rect
.top
;
588 wineItem
->rect
.bottom
= wineItem
->rect
.top
+ height
;
589 wineItem
->rect
.left
= x
- infoPtr
->cx
+ rect
.left
;
590 wineItem
->rect
.right
= rect
.right
;
591 if (!infoPtr
->firstVisible
)
592 infoPtr
->firstVisible
=wineItem
->hItem
;
593 TREEVIEW_DrawItem (wndPtr
, hdc
, wineItem
, prevItem
, indent
);
596 wineItem
->rect
.top
= wineItem
->rect
.bottom
= -1;
597 wineItem
->rect
.left
= wineItem
->rect
.right
= -1;
600 /* look up next item */
602 if ((wineItem
->firstChild
) && (wineItem
->state
& TVIS_EXPANDED
)) {
603 iItem
=wineItem
->firstChild
;
608 iItem
=wineItem
->sibling
;
609 while ((!iItem
) && (indent
>0)) {
613 wineItem
=&infoPtr
->items
[wineItem
->parent
];
614 iItem
=wineItem
->sibling
;
620 infoPtr
->uTotalHeight
=y
;
621 if (y
>= (viewbottom
-viewtop
)) {
622 if (!(infoPtr
->uInternalStatus
& TV_VSCROLL
))
623 ShowScrollBar32 (wndPtr
->hwndSelf
, SB_VERT
, TRUE
);
624 infoPtr
->uInternalStatus
|=TV_VSCROLL
;
625 SetScrollRange32 (wndPtr
->hwndSelf
, SB_VERT
, 0,
626 y
- infoPtr
->uVisibleHeight
, FALSE
);
627 SetScrollPos32 (wndPtr
->hwndSelf
, SB_VERT
, infoPtr
->cy
, TRUE
);
630 if (infoPtr
->uInternalStatus
& TV_VSCROLL
)
631 ShowScrollBar32 (wndPtr
->hwndSelf
, SB_VERT
, FALSE
);
632 infoPtr
->uInternalStatus
&= ~TV_VSCROLL
;
636 SelectObject32 (hdc
, hOldFont
);
641 TREEVIEW_HandleTimer ( WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
643 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
646 if (!infoPtr
) return FALSE
;
648 TRACE (treeview
, "timer\n");
651 case TV_REFRESH_TIMER
:
652 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
653 infoPtr
->Timer
&= ~TV_REFRESH_TIMER_SET
;
654 hdc
=GetDC32 (wndPtr
->hwndSelf
);
655 TREEVIEW_Refresh (wndPtr
, hdc
);
656 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
659 KillTimer32 (wndPtr
->hwndSelf
, TV_EDIT_TIMER
);
660 infoPtr
->Timer
&= ~TV_EDIT_TIMER_SET
;
669 TREEVIEW_QueueRefresh (WND
*wndPtr
)
672 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
674 TRACE (treeview
,"queued\n");
675 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
) {
676 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
679 SetTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
, TV_REFRESH_DELAY
, 0);
680 infoPtr
->Timer
|=TV_REFRESH_TIMER_SET
;
686 TREEVIEW_GetItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
688 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
690 TREEVIEW_ITEM
*wineItem
;
693 TRACE (treeview
,"\n");
694 tvItem
=(LPTVITEM
) lParam
;
697 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
698 if (!wineItem
) return FALSE
;
701 if (tvItem
->mask
& TVIF_CHILDREN
) {
702 tvItem
->cChildren
=wineItem
->cChildren
;
705 if (tvItem
->mask
& TVIF_HANDLE
) {
706 tvItem
->hItem
=wineItem
->hItem
;
709 if (tvItem
->mask
& TVIF_IMAGE
) {
710 tvItem
->iImage
=wineItem
->iImage
;
713 if (tvItem
->mask
& TVIF_INTEGRAL
) {
714 /* tvItem->iIntegral=wineItem->iIntegral; */
717 if (tvItem
->mask
& TVIF_PARAM
) {
718 tvItem
->lParam
=wineItem
->lParam
;
721 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
) {
722 tvItem
->iSelectedImage
=wineItem
->iSelectedImage
;
725 if (tvItem
->mask
& TVIF_STATE
) {
726 tvItem
->state
=wineItem
->state
& tvItem
->stateMask
;
729 if (tvItem
->mask
& TVIF_TEXT
) {
730 len
=wineItem
->cchTextMax
;
731 if (wineItem
->cchTextMax
>tvItem
->cchTextMax
)
732 len
=tvItem
->cchTextMax
-1;
733 lstrcpyn32A (tvItem
->pszText
, tvItem
->pszText
,len
);
742 TREEVIEW_GetNextItem32 (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
745 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
746 TREEVIEW_ITEM
*wineItem
;
750 TRACE (treeview
,"item:%lu, flags:%x\n", lParam
, wParam
);
751 if (!infoPtr
) return FALSE
;
753 flag
= (INT32
) wParam
;
755 case TVGN_ROOT
: return (LRESULT
) infoPtr
->TopRootItem
;
756 case TVGN_CARET
: return (LRESULT
) infoPtr
->selectedItem
;
757 case TVGN_FIRSTVISIBLE
: return (LRESULT
) infoPtr
->firstVisible
;
758 case TVGN_DROPHILITE
: return (LRESULT
) infoPtr
->dropItem
;
761 iItem
= (INT32
) lParam
;
762 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
763 if (!wineItem
) return FALSE
;
766 case TVGN_NEXT
: return (LRESULT
) wineItem
->sibling
;
767 case TVGN_PREVIOUS
: return (LRESULT
) wineItem
->upsibling
;
768 case TVGN_PARENT
: return (LRESULT
) wineItem
->parent
;
769 case TVGN_CHILD
: return (LRESULT
) wineItem
->firstChild
;
770 case TVGN_LASTVISIBLE
: FIXME (treeview
,"TVGN_LASTVISIBLE not implemented\n");
772 case TVGN_NEXTVISIBLE
: wineItem
=TREEVIEW_GetNextListItem
775 return (LRESULT
) wineItem
->hItem
;
778 case TVGN_PREVIOUSVISIBLE
: wineItem
=TREEVIEW_GetPrevListItem
781 return (LRESULT
) wineItem
->hItem
;
784 default: FIXME (treeview
,"Unknown msg %x,item %x\n", flag
,iItem
);
792 TREEVIEW_GetCount (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
794 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
796 return (LRESULT
) infoPtr
->uNumItems
;
802 /* the method used below isn't the most memory-friendly, but it avoids
803 a lot of memory reallocations */
805 /* BTW: we waste handle 0; 0 is not an allowed handle. Fix this by
806 decreasing infoptr->items with 1, and increasing it by 1 if
807 it is referenced in mm-handling stuff? */
810 TREEVIEW_InsertItem32A (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
813 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
814 TVINSERTSTRUCT
*ptdi
;
816 TREEVIEW_ITEM
*wineItem
, *parentItem
, *prevsib
, *sibItem
;
817 INT32 iItem
,listItems
,i
,len
;
819 TRACE (treeview
,"\n");
820 ptdi
= (TVINSERTSTRUCT
*) lParam
;
822 /* check if memory is available */
824 if (infoPtr
->uNumPtrsAlloced
==0) {
825 infoPtr
->items
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
826 TVITEM_ALLOC
*sizeof (TREEVIEW_ITEM
));
827 infoPtr
->freeList
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
828 (1+(TVITEM_ALLOC
>>5)) *sizeof (INT32
));
829 infoPtr
->uNumPtrsAlloced
=TVITEM_ALLOC
;
830 infoPtr
->TopRootItem
=1;
833 if (infoPtr
->uNumItems
== (infoPtr
->uNumPtrsAlloced
-1) ) {
834 TREEVIEW_ITEM
*oldItems
= infoPtr
->items
;
835 INT32
*oldfreeList
= infoPtr
->freeList
;
837 infoPtr
->uNumPtrsAlloced
*=2;
838 infoPtr
->items
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
839 infoPtr
->uNumPtrsAlloced
*sizeof (TREEVIEW_ITEM
));
840 infoPtr
->freeList
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
841 (1+(infoPtr
->uNumPtrsAlloced
>>5))*sizeof (INT32
));
843 memcpy (&infoPtr
->items
[0], &oldItems
[0],
844 infoPtr
->uNumPtrsAlloced
/2 * sizeof(TREEVIEW_ITEM
));
845 memcpy (&infoPtr
->freeList
[0], &oldfreeList
[0],
846 infoPtr
->uNumPtrsAlloced
>>6 * sizeof(INT32
));
848 HeapFree (GetProcessHeap (), 0, oldItems
);
849 HeapFree (GetProcessHeap (), 0, oldfreeList
);
853 infoPtr
->uNumItems
++;
855 if (infoPtr
->uMaxHandle
==(infoPtr
->uNumItems
-1)) {
856 iItem
=infoPtr
->uNumItems
;
857 infoPtr
->uMaxHandle
++;
859 else { /* check freelist */
860 for (i
=0; i
<infoPtr
->uNumPtrsAlloced
>>5; i
++) {
861 if (infoPtr
->freeList
[i
]) {
862 iItem
=ffs (infoPtr
->freeList
[i
]);
863 clear_bit (iItem
& 31, & infoPtr
->freeList
[i
]);
868 if (!iItem
) ERR (treeview
, "Argh -- can't find free item.\n");
870 tvItem
= & ptdi
->item
;
871 wineItem
=& infoPtr
->items
[iItem
];
875 if ((ptdi
->hParent
==TVI_ROOT
) || (ptdi
->hParent
==0)) {
878 sibItem
=&infoPtr
->items
[infoPtr
->TopRootItem
];
879 listItems
=infoPtr
->uNumItems
;
882 parentItem
= &infoPtr
->items
[ptdi
->hParent
];
883 if (!parentItem
->firstChild
)
884 parentItem
->firstChild
=iItem
;
885 wineItem
->parent
=ptdi
->hParent
;
886 sibItem
=&infoPtr
->items
[parentItem
->firstChild
];
887 parentItem
->cChildren
++;
888 listItems
=parentItem
->cChildren
;
891 wineItem
->upsibling
=0; /* needed in case we're the first item in a list */
893 wineItem
->firstChild
=0;
897 switch (ptdi
->hInsertAfter
) {
898 case TVI_FIRST
: wineItem
->sibling
=infoPtr
->TopRootItem
;
899 infoPtr
->TopRootItem
=iItem
;
902 while (sibItem
->sibling
) {
904 sibItem
=&infoPtr
->items
[sibItem
->sibling
];
906 sibItem
->sibling
=iItem
;
908 wineItem
->upsibling
=prevsib
->hItem
;
910 wineItem
->sibling
=0; /* terminate list */
913 FIXME (treeview
, "Sorted insert not implemented yet\n");
916 while ((sibItem
->sibling
) && (sibItem
->sibling
!=iItem
)) {
918 sibItem
=&infoPtr
->items
[sibItem
->sibling
];
920 if (sibItem
->sibling
)
921 WARN (treeview
, "Buggy program tried to insert item after nonexisting handle.");
922 sibItem
->upsibling
=iItem
;
923 wineItem
->sibling
=sibItem
->hItem
;
925 wineItem
->upsibling
=prevsib
->hItem
;
931 /* Fill in info structure */
933 wineItem
->mask
=tvItem
->mask
;
934 wineItem
->hItem
=iItem
;
935 wineItem
->iIntegral
=1;
937 if (tvItem
->mask
& TVIF_CHILDREN
)
938 wineItem
->cChildren
=tvItem
->cChildren
;
940 if (tvItem
->mask
& TVIF_IMAGE
)
941 wineItem
->iImage
=tvItem
->iImage
;
943 /* if (tvItem->mask & TVIF_INTEGRAL)
944 wineItem->iIntegral=tvItem->iIntegral; */
947 if (tvItem
->mask
& TVIF_PARAM
)
948 wineItem
->lParam
=tvItem
->lParam
;
950 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
)
951 wineItem
->iSelectedImage
=tvItem
->iSelectedImage
;
953 if (tvItem
->mask
& TVIF_STATE
) {
954 wineItem
->state
=tvItem
->state
;
955 wineItem
->stateMask
=tvItem
->stateMask
;
958 if (tvItem
->mask
& TVIF_TEXT
) {
959 TRACE (treeview
,"(%s)\n", tvItem
->pszText
);
960 if (tvItem
->pszText
!=LPSTR_TEXTCALLBACK32A
) {
961 len
= lstrlen32A (tvItem
->pszText
)+1;
963 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, len
+1);
964 lstrcpy32A (wineItem
->pszText
, tvItem
->pszText
);
965 wineItem
->cchTextMax
=len
;
969 TREEVIEW_QueueRefresh (wndPtr
);
971 return (LRESULT
) iItem
;
977 TREEVIEW_DeleteItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
979 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
982 TREEVIEW_ITEM
*wineItem
;
984 TRACE (treeview
,"\n");
985 if (!infoPtr
) return FALSE
;
987 if ((INT32
) lParam
== TVI_ROOT
) {
988 TREEVIEW_RemoveTree (infoPtr
);
990 iItem
= (INT32
) lParam
;
991 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
992 if (!wineItem
) return FALSE
;
993 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_DELETEITEM
, 0, iItem
, 0, pt
);
994 TREEVIEW_RemoveItem (infoPtr
, wineItem
);
997 TREEVIEW_QueueRefresh (wndPtr
);
1004 TREEVIEW_GetIndent (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1006 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1008 return infoPtr
->uIndent
;
1012 TREEVIEW_SetIndent (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1014 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1017 newIndent
=(INT32
) wParam
;
1018 if (newIndent
< MINIMUM_INDENT
) newIndent
=MINIMUM_INDENT
;
1019 infoPtr
->uIndent
=newIndent
;
1029 TREEVIEW_Create (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1031 TREEVIEW_INFO
*infoPtr
;
1035 TRACE (treeview
,"\n");
1036 /* allocate memory for info structure */
1037 infoPtr
= (TREEVIEW_INFO
*)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
1038 sizeof(TREEVIEW_INFO
));
1040 wndPtr
->wExtra
[0] = (DWORD
)infoPtr
;
1042 if (infoPtr
== NULL
) {
1043 ERR (treeview
, "could not allocate info memory!\n");
1047 if ((TREEVIEW_INFO
*)wndPtr
->wExtra
[0] != infoPtr
) {
1048 ERR (treeview
, "pointer assignment error!\n");
1052 hdc
=GetDC32 (wndPtr
->hwndSelf
);
1054 /* set default settings */
1055 infoPtr
->uInternalStatus
=0;
1056 infoPtr
->uNumItems
=0;
1057 infoPtr
->clrBk
= GetSysColor32 (COLOR_WINDOW
);
1058 infoPtr
->clrText
= GetSysColor32 (COLOR_BTNTEXT
);
1061 infoPtr
->uIndent
= 15;
1062 infoPtr
->himlNormal
= NULL
;
1063 infoPtr
->himlState
= NULL
;
1064 infoPtr
->uItemHeight
= -1;
1065 GetTextMetrics32A (hdc
, &tm
);
1066 infoPtr
->uRealItemHeight
= tm
.tmHeight
+ tm
.tmExternalLeading
;
1068 infoPtr
->items
= NULL
;
1069 infoPtr
->selectedItem
=0;
1070 infoPtr
->clrText
=-1; /* use system color */
1071 infoPtr
->dropItem
=0;
1074 infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
1075 infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
1078 if (wndPtr
->dwStyle
& TBSTYLE_TOOLTIPS
) {
1079 /* Create tooltip control */
1080 // infoPtr->hwndToolTip = CreateWindowEx32A (....);
1082 /* Send TV_TOOLTIPSCREATED notification */
1085 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1093 TREEVIEW_Destroy (WND
*wndPtr
)
1095 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1097 TREEVIEW_RemoveTree (infoPtr
);
1098 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
)
1099 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
1101 HeapFree (GetProcessHeap (), 0, infoPtr
);
1108 TREEVIEW_Paint (WND
*wndPtr
, WPARAM32 wParam
)
1113 hdc
= wParam
==0 ? BeginPaint32 (wndPtr
->hwndSelf
, &ps
) : (HDC32
)wParam
;
1114 TREEVIEW_QueueRefresh (wndPtr
);
1116 EndPaint32 (wndPtr
->hwndSelf
, &ps
);
1123 TREEVIEW_EraseBackground (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1125 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1126 HBRUSH32 hBrush
= CreateSolidBrush32 (infoPtr
->clrBk
);
1129 TRACE (treeview
,"\n");
1130 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
1131 FillRect32 ((HDC32
)wParam
, &rect
, hBrush
);
1132 DeleteObject32 (hBrush
);
1145 TREEVIEW_SendSimpleNotify (WND
*wndPtr
, UINT32 code
)
1149 TRACE (treeview
, "%x\n",code
);
1150 nmhdr
.hwndFrom
= wndPtr
->hwndSelf
;
1151 nmhdr
.idFrom
= wndPtr
->wIDmenu
;
1154 return (BOOL32
) SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
1155 (WPARAM32
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1162 TREEVIEW_SendTreeviewNotify (WND
*wndPtr
, UINT32 code
, UINT32 action
,
1163 INT32 oldItem
, INT32 newItem
, POINT32 pt
)
1165 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1167 TREEVIEW_ITEM
*wineItem
;
1169 TRACE (treeview
,"code:%x action:%x olditem:%x newitem:%x\n",
1170 code
,action
,oldItem
,newItem
);
1171 nmhdr
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
1172 nmhdr
.hdr
.idFrom
= wndPtr
->wIDmenu
;
1173 nmhdr
.hdr
.code
= code
;
1174 nmhdr
.action
= action
;
1176 wineItem
=& infoPtr
->items
[oldItem
];
1177 nmhdr
.itemOld
.mask
= wineItem
->mask
;
1178 nmhdr
.itemOld
.hItem
= wineItem
->hItem
;
1179 nmhdr
.itemOld
.state
= wineItem
->state
;
1180 nmhdr
.itemOld
.stateMask
= wineItem
->stateMask
;
1181 nmhdr
.itemOld
.iImage
= wineItem
->iImage
;
1182 nmhdr
.itemOld
.pszText
= wineItem
->pszText
;
1183 nmhdr
.itemOld
.cchTextMax
= wineItem
->cchTextMax
;
1184 nmhdr
.itemOld
.iImage
= wineItem
->iImage
;
1185 nmhdr
.itemOld
.iSelectedImage
= wineItem
->iSelectedImage
;
1186 nmhdr
.itemOld
.cChildren
= wineItem
->cChildren
;
1187 nmhdr
.itemOld
.lParam
= wineItem
->lParam
;
1191 wineItem
=& infoPtr
->items
[newItem
];
1192 nmhdr
.itemNew
.mask
= wineItem
->mask
;
1193 nmhdr
.itemNew
.hItem
= wineItem
->hItem
;
1194 nmhdr
.itemNew
.state
= wineItem
->state
;
1195 nmhdr
.itemNew
.stateMask
= wineItem
->stateMask
;
1196 nmhdr
.itemNew
.iImage
= wineItem
->iImage
;
1197 nmhdr
.itemNew
.pszText
= wineItem
->pszText
;
1198 nmhdr
.itemNew
.cchTextMax
= wineItem
->cchTextMax
;
1199 nmhdr
.itemNew
.iImage
= wineItem
->iImage
;
1200 nmhdr
.itemNew
.iSelectedImage
= wineItem
->iSelectedImage
;
1201 nmhdr
.itemNew
.cChildren
= wineItem
->cChildren
;
1202 nmhdr
.itemNew
.lParam
= wineItem
->lParam
;
1205 nmhdr
.ptDrag
.x
= pt
.x
;
1206 nmhdr
.ptDrag
.y
= pt
.y
;
1208 return (BOOL32
)SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
1209 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&nmhdr
);
1217 TREEVIEW_Expand (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1219 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1220 TREEVIEW_ITEM
*wineItem
;
1225 flag
= (UINT32
) wParam
;
1226 expandItem
= (INT32
) lParam
;
1227 TRACE (treeview
,"flags:%x item:%x\n", expandItem
, wParam
);
1228 wineItem
= TREEVIEW_ValidItem (infoPtr
, expandItem
);
1229 if (!wineItem
) return 0;
1230 if (!wineItem
->cChildren
) return 0;
1232 if (flag
& TVE_TOGGLE
) { /* FIXME: check exact behaviour here */
1233 flag
&= ~TVE_TOGGLE
; /* ie: bitwise ops or 'case' ops */
1234 if (wineItem
->state
& TVIS_EXPANDED
)
1235 flag
|= TVE_COLLAPSE
;
1241 case TVE_COLLAPSERESET
:
1242 if (!wineItem
->state
& TVIS_EXPANDED
) return 0;
1243 wineItem
->state
&= ~(TVIS_EXPANDEDONCE
| TVIS_EXPANDED
);
1244 TREEVIEW_RemoveAllChildren (infoPtr
, wineItem
);
1248 if (!wineItem
->state
& TVIS_EXPANDED
) return 0;
1249 wineItem
->state
&= ~TVIS_EXPANDED
;
1253 if (wineItem
->state
& TVIS_EXPANDED
) return 0;
1254 if (!(wineItem
->state
& TVIS_EXPANDEDONCE
)) {
1255 if (TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_ITEMEXPANDING
,
1256 0, 0, expandItem
, pt
))
1257 return FALSE
; /* FIXME: OK? */
1258 wineItem
->state
|= TVIS_EXPANDED
| TVIS_EXPANDEDONCE
;
1259 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_ITEMEXPANDED
,
1260 0, 0, expandItem
, pt
);
1262 wineItem
->state
|= TVIS_EXPANDED
;
1264 case TVE_EXPANDPARTIAL
:
1265 FIXME (treeview
, "TVE_EXPANDPARTIAL not implemented\n");
1266 wineItem
->state
^=TVIS_EXPANDED
;
1267 wineItem
->state
|=TVIS_EXPANDEDONCE
;
1271 TREEVIEW_QueueRefresh (wndPtr
);
1279 TREEVIEW_HitTest (WND
*wndPtr
, LPTVHITTESTINFO lpht
)
1281 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1282 TREEVIEW_ITEM
*wineItem
;
1288 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
1289 TRACE (treeview
,"(%d,%d)\n",lpht
->pt
.x
, lpht
->pt
.y
);
1294 if (x
< rect
.left
) status
|=TVHT_TOLEFT
;
1295 if (x
> rect
.right
) status
|=TVHT_TORIGHT
;
1296 if (y
< rect
.top
) status
|=TVHT_ABOVE
;
1297 if (y
> rect
.bottom
) status
|=TVHT_BELOW
;
1303 if (!infoPtr
->firstVisible
) WARN (treeview
,"Can't fetch first visible item");
1304 wineItem
=&infoPtr
->items
[infoPtr
->firstVisible
];
1306 while ((wineItem
!=NULL
) && (y
> wineItem
->rect
.bottom
))
1307 wineItem
=TREEVIEW_GetNextListItem (infoPtr
,wineItem
);
1309 if (wineItem
==NULL
) {
1310 lpht
->flags
=TVHT_NOWHERE
;
1314 if (x
>wineItem
->rect
.right
) {
1315 lpht
->flags
|=TVHT_ONITEMRIGHT
;
1316 return wineItem
->hItem
;
1320 if (x
<wineItem
->rect
.left
+10) lpht
->flags
|=TVHT_ONITEMBUTTON
;
1322 lpht
->flags
=TVHT_ONITEMLABEL
; /* FIXME: implement other flags */
1325 lpht
->hItem
=wineItem
->hItem
;
1326 return wineItem
->hItem
;
1331 TREEVIEW_HitTest32 (WND
*wndPtr
, LPARAM lParam
)
1334 return (LRESULT
) TREEVIEW_HitTest (wndPtr
, (LPTVHITTESTINFO
) lParam
);
1341 TREEVIEW_LButtonDoubleClick (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1343 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1344 TREEVIEW_ITEM
*wineItem
;
1348 TRACE (treeview
,"\n");
1349 ht
.pt
.x
= (INT32
)LOWORD(lParam
);
1350 ht
.pt
.y
= (INT32
)HIWORD(lParam
);
1351 SetFocus32 (wndPtr
->hwndSelf
);
1353 iItem
=TREEVIEW_HitTest (wndPtr
, &ht
);
1354 TRACE (treeview
,"item %d \n",iItem
);
1355 wineItem
=TREEVIEW_ValidItem (infoPtr
, iItem
);
1356 if (!wineItem
) return 0;
1358 if (TREEVIEW_SendSimpleNotify (wndPtr
, NM_DBLCLK
)!=TRUE
) { /* FIXME!*/
1359 wineItem
->state
&= ~TVIS_EXPANDEDONCE
;
1360 TREEVIEW_Expand (wndPtr
, (WPARAM32
) TVE_TOGGLE
, (LPARAM
) iItem
);
1368 TREEVIEW_LButtonDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1373 TRACE (treeview
,"\n");
1374 ht
.pt
.x
= (INT32
)LOWORD(lParam
);
1375 ht
.pt
.y
= (INT32
)HIWORD(lParam
);
1377 SetFocus32 (wndPtr
->hwndSelf
);
1378 iItem
=TREEVIEW_HitTest (wndPtr
, &ht
);
1379 TRACE (treeview
,"item %d \n",iItem
);
1380 if (ht
.flags
& TVHT_ONITEMBUTTON
) {
1381 TREEVIEW_Expand (wndPtr
, (WPARAM32
) TVE_TOGGLE
, (LPARAM
) iItem
);
1384 if (TREEVIEW_SelectItem (wndPtr
, (WPARAM32
) TVGN_CARET
, (LPARAM
) iItem
))
1393 TREEVIEW_RButtonDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1402 /* FIXME: If the specified item is the child of a collapsed parent item,
1403 expand parent's list of child items to reveal the specified item.
1407 TREEVIEW_SelectItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1409 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1410 TREEVIEW_ITEM
*prevItem
,*wineItem
;
1411 INT32 action
,prevSelect
, newSelect
;
1414 TRACE (treeview
,"item %lx, flag %x\n", lParam
, wParam
);
1415 newSelect
= (INT32
) lParam
;
1416 wineItem
= TREEVIEW_ValidItem (infoPtr
, newSelect
);
1417 if (!wineItem
) return FALSE
;
1418 prevSelect
=infoPtr
->selectedItem
;
1419 prevItem
= TREEVIEW_ValidItem (infoPtr
, prevSelect
);
1423 action
= (INT32
) wParam
;
1427 if (TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_SELCHANGING
, TVC_BYMOUSE
,
1428 prevSelect
, newSelect
,dummy
))
1429 return FALSE
; /* FIXME: OK? */
1431 if (prevItem
) prevItem
->state
&= ~TVIS_SELECTED
;
1432 infoPtr
->selectedItem
=newSelect
;
1433 wineItem
->state
|=TVIS_SELECTED
;
1434 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_SELCHANGED
,
1435 TVC_BYMOUSE
, prevSelect
, newSelect
, dummy
);
1437 case TVGN_DROPHILITE
:
1438 FIXME (treeview
, "DROPHILITE not implemented");
1440 case TVGN_FIRSTVISIBLE
:
1441 FIXME (treeview
, "FIRSTVISIBLE not implemented");
1445 TREEVIEW_QueueRefresh (wndPtr
);
1452 /* FIXME: does KEYDOWN also send notifications?? If so, use
1453 TREEVIEW_SelectItem.
1458 TREEVIEW_KeyDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1460 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1461 TREEVIEW_ITEM
*prevItem
,*newItem
;
1465 TRACE (treeview
,"%x %lx",wParam
, lParam
);
1466 prevSelect
=infoPtr
->selectedItem
;
1467 if (!prevSelect
) return FALSE
;
1469 prevItem
= TREEVIEW_ValidItem (infoPtr
, prevSelect
);
1474 newItem
=TREEVIEW_GetPrevListItem (infoPtr
, prevItem
);
1476 newItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
1479 newItem
=TREEVIEW_GetNextListItem (infoPtr
, prevItem
);
1480 if (!newItem
) newItem
=prevItem
;
1483 newItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
1486 newItem
=TREEVIEW_GetLastListItem (infoPtr
);
1492 FIXME (treeview
, "%x not implemented\n", wParam
);
1496 if (!newItem
) return FALSE
;
1498 if (prevItem
!=newItem
) {
1499 prevItem
->state
&= ~TVIS_SELECTED
;
1500 newItem
->state
|= TVIS_SELECTED
;
1501 infoPtr
->selectedItem
=newItem
->hItem
;
1502 TREEVIEW_QueueRefresh (wndPtr
);
1512 TREEVIEW_VScroll (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1515 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1518 TRACE (treeview
,"wp %x, lp %lx\n", wParam
, lParam
);
1519 if (!infoPtr
->uInternalStatus
& TV_VSCROLL
) return FALSE
;
1521 switch (LOWORD (wParam
)) {
1523 if (!infoPtr
->cy
) return FALSE
;
1524 infoPtr
->cy
-= infoPtr
->uRealItemHeight
;
1525 if (infoPtr
->cy
< 0) infoPtr
->cy
=0;
1528 maxHeight
=infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
1529 if (infoPtr
->cy
== maxHeight
) return FALSE
;
1530 infoPtr
->cy
+= infoPtr
->uRealItemHeight
;
1531 if (infoPtr
->cy
> maxHeight
)
1532 infoPtr
->cy
= maxHeight
;
1535 if (!infoPtr
->cy
) return FALSE
;
1536 infoPtr
->cy
-= infoPtr
->uVisibleHeight
;
1537 if (infoPtr
->cy
< 0) infoPtr
->cy
=0;
1540 maxHeight
=infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
1541 if (infoPtr
->cy
== maxHeight
) return FALSE
;
1542 infoPtr
->cy
+= infoPtr
->uVisibleHeight
;
1543 if (infoPtr
->cy
> maxHeight
)
1544 infoPtr
->cy
= maxHeight
;
1547 infoPtr
->cy
= HIWORD (wParam
);
1552 TREEVIEW_QueueRefresh (wndPtr
);
1557 TREEVIEW_HScroll (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1559 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1561 TRACE (treeview
,"wp %lx, lp %x\n", lParam
, wParam
);
1563 if (!infoPtr
->uInternalStatus
& TV_HSCROLL
) return FALSE
;
1571 TREEVIEW_WindowProc (HWND32 hwnd
, UINT32 uMsg
, WPARAM32 wParam
, LPARAM lParam
)
1573 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1577 case TVM_INSERTITEM32A
:
1578 return TREEVIEW_InsertItem32A (wndPtr
, wParam
, lParam
);
1580 case TVM_INSERTITEM32W
:
1581 FIXME (treeview
, "Unimplemented msg TVM_INSERTITEM32W\n");
1584 case TVM_DELETEITEM
:
1585 return TREEVIEW_DeleteItem (wndPtr
, wParam
, lParam
);
1588 return TREEVIEW_Expand (wndPtr
, wParam
, lParam
);
1590 case TVM_GETITEMRECT
:
1591 return TREEVIEW_GetItemRect (wndPtr
, wParam
, lParam
);
1594 return TREEVIEW_GetCount (wndPtr
, wParam
, lParam
);
1597 return TREEVIEW_GetIndent (wndPtr
, wParam
, lParam
);
1600 return TREEVIEW_SetIndent (wndPtr
, wParam
, lParam
);
1602 case TVM_GETIMAGELIST
:
1603 return TREEVIEW_GetImageList (wndPtr
, wParam
, lParam
);
1605 case TVM_SETIMAGELIST
:
1606 return TREEVIEW_SetImageList (wndPtr
, wParam
, lParam
);
1608 case TVM_GETNEXTITEM
:
1609 return TREEVIEW_GetNextItem32 (wndPtr
, wParam
, lParam
);
1611 case TVM_SELECTITEM
:
1612 return TREEVIEW_SelectItem (wndPtr
, wParam
, lParam
);
1614 case TVM_GETITEM32A
:
1615 return TREEVIEW_GetItem (wndPtr
, wParam
, lParam
);
1617 case TVM_GETITEM32W
:
1618 FIXME (treeview
, "Unimplemented msg TVM_GETITEM32W\n");
1621 case TVM_SETITEM32A
:
1622 return TREEVIEW_SetItem (wndPtr
, wParam
, lParam
);
1624 case TVM_SETITEM32W
:
1625 FIXME (treeview
, "Unimplemented msg TVM_SETITEMW\n");
1628 case TVM_EDITLABEL32A
:
1629 FIXME (treeview
, "Unimplemented msg TVM_EDITLABEL32A \n");
1632 case TVM_EDITLABEL32W
:
1633 FIXME (treeview
, "Unimplemented msg TVM_EDITLABEL32W \n");
1636 case TVM_GETEDITCONTROL
:
1637 FIXME (treeview
, "Unimplemented msg TVM_GETEDITCONTROL\n");
1640 case TVM_GETVISIBLECOUNT
:
1641 return TREEVIEW_GetVisibleCount (wndPtr
, wParam
, lParam
);
1644 return TREEVIEW_HitTest32 (wndPtr
, lParam
);
1646 case TVM_CREATEDRAGIMAGE
:
1647 FIXME (treeview
, "Unimplemented msg TVM_CREATEDRAGIMAGE\n");
1650 case TVM_SORTCHILDREN
:
1651 FIXME (treeview
, "Unimplemented msg TVM_SORTCHILDREN\n");
1654 case TVM_ENSUREVISIBLE
:
1655 FIXME (treeview
, "Unimplemented msg TVM_ENSUREVISIBLE\n");
1658 case TVM_SORTCHILDRENCB
:
1659 FIXME (treeview
, "Unimplemented msg TVM_SORTCHILDRENCB\n");
1662 case TVM_ENDEDITLABELNOW
:
1663 FIXME (treeview
, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
1666 case TVM_GETISEARCHSTRING32A
:
1667 FIXME (treeview
, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
1670 case TVM_GETISEARCHSTRING32W
:
1671 FIXME (treeview
, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
1674 case TVM_SETTOOLTIPS
:
1675 FIXME (treeview
, "Unimplemented msg TVM_SETTOOLTIPS\n");
1678 case TVM_GETTOOLTIPS
:
1679 FIXME (treeview
, "Unimplemented msg TVM_GETTOOLTIPS\n");
1682 case TVM_SETINSERTMARK
:
1683 FIXME (treeview
, "Unimplemented msg TVM_SETINSERTMARK\n");
1686 case TVM_SETITEMHEIGHT
:
1687 return TREEVIEW_SetItemHeight (wndPtr
, wParam
);
1689 case TVM_GETITEMHEIGHT
:
1690 return TREEVIEW_GetItemHeight (wndPtr
);
1692 case TVM_SETBKCOLOR
:
1693 FIXME (treeview
, "Unimplemented msg TVM_SETBKCOLOR\n");
1696 case TVM_SETTEXTCOLOR
:
1697 return TREEVIEW_SetTextColor (wndPtr
, wParam
, lParam
);
1699 case TVM_GETBKCOLOR
:
1700 FIXME (treeview
, "Unimplemented msg TVM_GETBKCOLOR\n");
1703 case TVM_GETTEXTCOLOR
:
1704 return TREEVIEW_GetTextColor (wndPtr
);
1706 case TVM_SETSCROLLTIME
:
1707 FIXME (treeview
, "Unimplemented msg TVM_SETSCROLLTIME\n");
1710 case TVM_GETSCROLLTIME
:
1711 FIXME (treeview
, "Unimplemented msg TVM_GETSCROLLTIME\n");
1714 case TVM_SETINSERTMARKCOLOR
:
1715 FIXME (treeview
, "Unimplemented msg TVM_SETINSERTMARKCOLOR\n");
1718 case TVM_SETUNICODEFORMAT
:
1719 FIXME (treeview
, "Unimplemented msg TVM_SETUNICODEFORMAT\n");
1722 case TVM_GETUNICODEFORMAT
:
1723 FIXME (treeview
, "Unimplemented msg TVM_GETUNICODEFORMAT\n");
1729 return TREEVIEW_Create (wndPtr
, wParam
, lParam
);
1732 return TREEVIEW_Destroy (wndPtr
);
1737 return TREEVIEW_EraseBackground (wndPtr
, wParam
, lParam
);
1740 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
1743 return TREEVIEW_Paint (wndPtr
, wParam
);
1749 return TREEVIEW_KeyDown (wndPtr
, wParam
, lParam
);
1752 // case WM_KILLFOCUS:
1753 // case WM_SETFOCUS:
1756 case WM_LBUTTONDOWN
:
1757 return TREEVIEW_LButtonDown (wndPtr
, wParam
, lParam
);
1759 case WM_LBUTTONDBLCLK
:
1760 return TREEVIEW_LButtonDoubleClick (wndPtr
, wParam
, lParam
);
1762 case WM_RBUTTONDOWN
:
1763 return TREEVIEW_RButtonDown (wndPtr
, wParam
, lParam
);
1766 // case WM_SYSCOLORCHANGE:
1767 // case WM_STYLECHANGED:
1768 // case WM_SETREDRAW:
1771 return TREEVIEW_HandleTimer (wndPtr
, wParam
, lParam
);
1775 return TREEVIEW_HScroll (wndPtr
, wParam
, lParam
);
1777 return TREEVIEW_VScroll (wndPtr
, wParam
, lParam
);
1780 if (uMsg
>= WM_USER
)
1781 FIXME (treeview
, "Unknown msg %04x wp=%08x lp=%08lx\n",
1782 uMsg
, wParam
, lParam
);
1783 return DefWindowProc32A (hwnd
, uMsg
, wParam
, lParam
);
1790 TREEVIEW_Register (void)
1792 WNDCLASS32A wndClass
;
1794 TRACE (treeview
,"\n");
1796 if (GlobalFindAtom32A (WC_TREEVIEW32A
)) return;
1798 ZeroMemory (&wndClass
, sizeof(WNDCLASS32A
));
1799 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1800 wndClass
.lpfnWndProc
= (WNDPROC32
)TREEVIEW_WindowProc
;
1801 wndClass
.cbClsExtra
= 0;
1802 wndClass
.cbWndExtra
= sizeof(TREEVIEW_INFO
*);
1803 wndClass
.hCursor
= LoadCursor32A (0, IDC_ARROW32A
);
1804 wndClass
.hbrBackground
= 0;
1805 wndClass
.lpszClassName
= WC_TREEVIEW32A
;
1807 RegisterClass32A (&wndClass
);