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).
36 /* ffs should be in <string.h>. */
38 /* Defines, since they do not need to return previous state, and nr
39 * has no side effects in this file.
41 #define tv_test_bit(nr,bf) (((LPBYTE)bf)[nr>>3]&(1<<(nr&7)))
42 #define tv_set_bit(nr,bf) ((LPBYTE)bf)[nr>>3]|=(1<<(nr&7))
43 #define tv_clear_bit(nr,bf) ((LPBYTE)bf)[nr>>3]&=~(1<<(nr&7))
46 #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
49 TREEVIEW_SendSimpleNotify (WND
*wndPtr
, UINT32 code
);
51 TREEVIEW_SendTreeviewNotify (WND
*wndPtr
, UINT32 code
, UINT32 action
,
52 INT32 oldItem
, INT32 newItem
, POINT32 pt
);
54 TREEVIEW_SelectItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
);
56 TREEVIEW_Refresh (WND
*wndPtr
, HDC32 hdc
);
62 /* helper functions. Work with the assumption that validity of operands
63 is checked beforehand */
66 static TREEVIEW_ITEM
*
67 TREEVIEW_ValidItem (TREEVIEW_INFO
*infoPtr
,int handle
)
70 if ((!handle
) || (handle
>infoPtr
->uMaxHandle
)) return NULL
;
71 if (tv_test_bit (handle
, infoPtr
->freeList
)) return NULL
;
73 return & infoPtr
->items
[handle
];
78 static TREEVIEW_ITEM
*TREEVIEW_GetPrevListItem (TREEVIEW_INFO
*infoPtr
,
79 TREEVIEW_ITEM
*tvItem
)
82 TREEVIEW_ITEM
*wineItem
;
84 if (tvItem
->upsibling
) {
85 wineItem
=& infoPtr
->items
[tvItem
->upsibling
];
86 if ((wineItem
->firstChild
) && (wineItem
->state
& TVIS_EXPANDED
)) {
87 wineItem
=& infoPtr
->items
[wineItem
->firstChild
];
88 while (wineItem
->sibling
)
89 wineItem
= & infoPtr
->items
[wineItem
->sibling
];
95 while (wineItem
->parent
) {
96 wineItem
=& infoPtr
->items
[wineItem
->parent
];
97 if (wineItem
->upsibling
)
98 return (& infoPtr
->items
[wineItem
->upsibling
]);
105 static TREEVIEW_ITEM
*TREEVIEW_GetNextListItem (TREEVIEW_INFO
*infoPtr
,
106 TREEVIEW_ITEM
*tvItem
)
109 TREEVIEW_ITEM
*wineItem
;
111 if ((tvItem
->firstChild
) && (tvItem
->state
& TVIS_EXPANDED
))
112 return (& infoPtr
->items
[tvItem
->firstChild
]);
115 return (& infoPtr
->items
[tvItem
->sibling
]);
118 while (wineItem
->parent
) {
119 wineItem
=& infoPtr
->items
[wineItem
->parent
];
120 if (wineItem
->sibling
)
121 return (& infoPtr
->items
[wineItem
->sibling
]);
127 static TREEVIEW_ITEM
*TREEVIEW_GetLastListItem (TREEVIEW_INFO
*infoPtr
)
130 TREEVIEW_ITEM
*wineItem
;
133 if (infoPtr
->TopRootItem
)
134 wineItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
135 while (wineItem
->sibling
)
136 wineItem
=& infoPtr
->items
[wineItem
->sibling
];
145 TREEVIEW_RemoveItem (TREEVIEW_INFO
*infoPtr
, TREEVIEW_ITEM
*wineItem
)
148 TREEVIEW_ITEM
*parentItem
, *upsiblingItem
, *siblingItem
;
151 iItem
=wineItem
->hItem
;
152 tv_set_bit(iItem
,infoPtr
->freeList
);
153 infoPtr
->uNumItems
--;
155 if (wineItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
156 HeapFree (GetProcessHeap (), 0, wineItem
->pszText
);
158 if (wineItem
->parent
) {
159 parentItem
=& infoPtr
->items
[ wineItem
->parent
];
160 if (parentItem
->cChildren
==1) {
161 parentItem
->cChildren
=0;
162 parentItem
->firstChild
=0;
165 parentItem
->cChildren
--;
166 if (parentItem
->firstChild
==iItem
)
167 parentItem
->firstChild
=wineItem
->sibling
;
171 if (iItem
==infoPtr
->TopRootItem
)
172 infoPtr
->TopRootItem
=wineItem
->sibling
;
173 if (wineItem
->upsibling
) {
174 upsiblingItem
=& infoPtr
->items
[wineItem
->upsibling
];
175 upsiblingItem
->sibling
=wineItem
->sibling
;
177 if (wineItem
->sibling
) {
178 siblingItem
=& infoPtr
->items
[wineItem
->sibling
];
179 siblingItem
->upsibling
=wineItem
->upsibling
;
185 static void TREEVIEW_RemoveAllChildren (TREEVIEW_INFO
*infoPtr
,
186 TREEVIEW_ITEM
*parentItem
)
189 TREEVIEW_ITEM
*killItem
;
192 kill
=parentItem
->firstChild
;
194 tv_set_bit ( kill
, infoPtr
->freeList
);
195 killItem
=& infoPtr
->items
[kill
];
196 if (killItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
197 HeapFree (GetProcessHeap (), 0, killItem
->pszText
);
198 kill
=killItem
->sibling
;
200 infoPtr
->uNumItems
-= parentItem
->cChildren
;
201 parentItem
->firstChild
= 0;
202 parentItem
->cChildren
= 0;
206 /* Note:TREEVIEW_RemoveTree doesn't remove infoPtr itself */
208 static void TREEVIEW_RemoveTree (TREEVIEW_INFO
*infoPtr
)
212 TREEVIEW_ITEM
*killItem
;
215 for (i
=1; i
<=infoPtr
->uMaxHandle
; i
++)
216 if (!tv_test_bit (i
, infoPtr
->freeList
)) {
217 killItem
=& infoPtr
->items
[i
];
218 if (killItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
219 HeapFree (GetProcessHeap (), 0, killItem
->pszText
);
222 if (infoPtr
->uNumPtrsAlloced
) {
223 HeapFree (GetProcessHeap (), 0, infoPtr
->items
);
224 HeapFree (GetProcessHeap (), 0, infoPtr
->freeList
);
225 infoPtr
->uNumItems
=0;
226 infoPtr
->uNumPtrsAlloced
=0;
227 infoPtr
->uMaxHandle
=0;
241 TREEVIEW_GetImageList (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
243 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
245 TRACE (treeview
,"\n");
247 if (infoPtr
==NULL
) return 0;
249 if ((INT32
)wParam
== TVSIL_NORMAL
)
250 return (LRESULT
) infoPtr
->himlNormal
;
251 if ((INT32
)wParam
== TVSIL_STATE
)
252 return (LRESULT
) infoPtr
->himlState
;
261 TREEVIEW_SetImageList (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
263 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
266 switch ((INT32
)wParam
) {
268 himlTemp
= infoPtr
->himlNormal
;
269 infoPtr
->himlNormal
= (HIMAGELIST
)lParam
;
270 return (LRESULT
)himlTemp
;
273 himlTemp
= infoPtr
->himlState
;
274 infoPtr
->himlState
= (HIMAGELIST
)lParam
;
275 return (LRESULT
)himlTemp
;
278 return (LRESULT
)NULL
;
284 TREEVIEW_SetItemHeight (WND
*wndPtr
, WPARAM32 wParam
)
286 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
287 INT32 prevHeight
=infoPtr
->uItemHeight
;
293 hdc
=GetDC32 (wndPtr
->hwndSelf
);
294 infoPtr
->uItemHeight
=-1;
295 GetTextMetrics32A (hdc
, &tm
);
296 infoPtr
->uRealItemHeight
= tm
.tmHeight
+ tm
.tmExternalLeading
;
297 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
301 /* FIXME: check wParam > imagelist height */
303 if (!(wndPtr
->dwStyle
& TVS_NONEVENHEIGHT
))
304 infoPtr
->uItemHeight
= (INT32
) wParam
& 0xfffffffe;
309 TREEVIEW_GetItemHeight (WND
*wndPtr
)
311 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
313 return infoPtr
->uItemHeight
;
317 TREEVIEW_SetTextColor (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
319 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
320 COLORREF prevColor
=infoPtr
->clrText
;
322 infoPtr
->clrText
=(COLORREF
) lParam
;
323 return (LRESULT
) prevColor
;
327 TREEVIEW_GetTextColor (WND
*wndPtr
)
329 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
331 return (LRESULT
) infoPtr
->clrText
;
336 TREEVIEW_DrawItem (WND
*wndPtr
, HDC32 hdc
, TREEVIEW_ITEM
*wineItem
,
337 TREEVIEW_ITEM
*upperItem
, int indent
)
339 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
340 INT32 oldBkMode
,center
,xpos
;
342 UINT32 uTextJustify
= DT_LEFT
;
343 HPEN32 hOldPen
, hnewPen
,hRootPen
;
346 hnewPen
= CreatePen32(PS_DOT
, 0, GetSysColor32(COLOR_WINDOWTEXT
) );
347 hOldPen
= SelectObject32( hdc
, hnewPen
);
351 upper
=upperItem
->rect
;
356 center
=(r
.top
+r
.bottom
)/2;
359 if (wndPtr
->dwStyle
& TVS_HASLINES
) {
361 if ((wndPtr
->dwStyle
& TVS_LINESATROOT
) && (indent
==0)) {
362 points
[0].y
=points
[1].y
=center
;
363 points
[2].y
=upper
.top
;
364 points
[1].x
=points
[2].x
=upper
.left
;
365 points
[0].x
=upper
.left
+12;
368 Polyline32 (hdc
,points
,3);
371 points
[0].y
=points
[1].y
=center
;
372 points
[2].y
=upper
.top
;
373 points
[1].x
=points
[2].x
=upper
.left
+13;
374 points
[0].x
=upper
.left
+25;
376 Polyline32 (hdc
,points
,3);
380 DeleteObject32(hnewPen
);
381 SelectObject32(hdc
, hOldPen
);
383 if ((wndPtr
->dwStyle
& TVS_HASBUTTONS
) && (wineItem
->cChildren
)) {
385 hRootPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOW) );
386 SelectObject32( hdc, hRootPen );
389 Rectangle32 (hdc
, xpos
-4, center
-4, xpos
+5, center
+5);
390 MoveToEx32 (hdc
, xpos
-2, center
, NULL
);
391 LineTo32 (hdc
, xpos
+3, center
);
392 if (!(wineItem
->state
& TVIS_EXPANDED
)) {
393 MoveToEx32 (hdc
, xpos
, center
-2, NULL
);
394 LineTo32 (hdc
, xpos
, center
+3);
396 /* DeleteObject32(hRootPen); */
402 if (wineItem
->mask
& TVIF_IMAGE
) {
403 if (wineItem
->iImage
!=I_IMAGECALLBACK
) {
404 if (infoPtr
->himlNormal
) {
405 ImageList_Draw (infoPtr
->himlNormal
,wineItem
->iImage
, hdc
,
406 xpos
-2, r
.top
+1, ILD_NORMAL
);
413 if ((wineItem
->mask
& TVIF_TEXT
) && (wineItem
->pszText
)) {
414 if (wineItem
->state
& TVIS_SELECTED
) {
415 oldBkMode
= SetBkMode32(hdc
, OPAQUE
);
416 oldBkColor
= SetBkColor32 (hdc
, GetSysColor32( COLOR_HIGHLIGHT
));
417 SetTextColor32 (hdc
, GetSysColor32(COLOR_HIGHLIGHTTEXT
));
420 oldBkMode
= SetBkMode32(hdc
, TRANSPARENT
);
424 if (infoPtr
->clrText
==-1)
425 SetTextColor32 (hdc
, COLOR_BTNTEXT
);
427 SetTextColor32 (hdc
, infoPtr
->clrText
); /* FIXME: retval */
428 DrawText32A(hdc
, wineItem
->pszText
, lstrlen32A(wineItem
->pszText
),
429 &r
, uTextJustify
|DT_VCENTER
|DT_SINGLELINE
);
430 if (oldBkMode
!= TRANSPARENT
)
431 SetBkMode32(hdc
, oldBkMode
);
432 if (wineItem
->state
& TVIS_SELECTED
)
433 SetBkColor32 (hdc
, oldBkColor
);
436 return wineItem
->rect
.right
;
446 TREEVIEW_GetItemRect (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
448 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
449 TREEVIEW_ITEM
*wineItem
;
453 TRACE (treeview
,"\n");
454 if (infoPtr
==NULL
) return FALSE
;
456 iItem
= (INT32
)lParam
;
457 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
458 if (!wineItem
) return FALSE
;
460 wineItem
=& infoPtr
->items
[ iItem
];
461 if (!wineItem
->visible
) return FALSE
;
463 lpRect
= (LPRECT32
)lParam
;
464 if (lpRect
== NULL
) return FALSE
;
466 if ((INT32
) wParam
) {
467 lpRect
->left
= wineItem
->text
.left
;
468 lpRect
->right
= wineItem
->text
.right
;
469 lpRect
->bottom
= wineItem
->text
.bottom
;
470 lpRect
->top
= wineItem
->text
.top
;
472 lpRect
->left
= wineItem
->rect
.left
;
473 lpRect
->right
= wineItem
->rect
.right
;
474 lpRect
->bottom
= wineItem
->rect
.bottom
;
475 lpRect
->top
= wineItem
->rect
.top
;
484 TREEVIEW_GetVisibleCount (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
487 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
489 TRACE (treeview
,"\n");
491 return (LRESULT
) infoPtr
->uVisibleHeight
/ infoPtr
->uRealItemHeight
;
497 TREEVIEW_SetItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
499 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
500 TREEVIEW_ITEM
*wineItem
;
504 TRACE (treeview
,"\n");
505 tvItem
=(LPTVITEM
) lParam
;
508 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
509 if (!wineItem
) return FALSE
;
511 if (tvItem
->mask
& TVIF_CHILDREN
) {
512 wineItem
->cChildren
=tvItem
->cChildren
;
515 if (tvItem
->mask
& TVIF_IMAGE
) {
516 wineItem
->iImage
=tvItem
->iImage
;
519 if (tvItem
->mask
& TVIF_INTEGRAL
) {
520 /* wineItem->iIntegral=tvItem->iIntegral; */
523 if (tvItem
->mask
& TVIF_PARAM
) {
524 wineItem
->lParam
=tvItem
->lParam
;
527 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
) {
528 wineItem
->iSelectedImage
=tvItem
->iSelectedImage
;
531 if (tvItem
->mask
& TVIF_STATE
) {
532 wineItem
->state
=tvItem
->state
& tvItem
->stateMask
;
535 if (tvItem
->mask
& TVIF_TEXT
) {
536 len
=lstrlen32A (tvItem
->pszText
);
537 if (len
>wineItem
->cchTextMax
) {
538 HeapFree (GetProcessHeap (), 0, wineItem
->pszText
);
539 wineItem
->pszText
= HeapAlloc (GetProcessHeap (),
540 HEAP_ZERO_MEMORY
, len
+1);
542 lstrcpyn32A (wineItem
->pszText
, tvItem
->pszText
,len
);
553 TREEVIEW_Refresh (WND
*wndPtr
, HDC32 hdc
)
556 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
557 HFONT32 hFont
, hOldFont
;
560 INT32 iItem
, indent
, x
, y
, height
;
561 INT32 viewtop
,viewbottom
,viewleft
,viewright
;
562 TREEVIEW_ITEM
*wineItem
, *prevItem
;
564 TRACE (treeview
,"\n");
566 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
) {
567 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
568 infoPtr
->Timer
&= ~TV_REFRESH_TIMER_SET
;
572 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
573 if ((rect
.left
-rect
.right
==0) || (rect
.top
-rect
.bottom
==0)) return;
575 viewbottom
=infoPtr
->cy
+ rect
.bottom
-rect
.top
;
576 viewleft
=infoPtr
->cx
;
577 viewright
=infoPtr
->cx
+ rect
.right
-rect
.left
;
579 infoPtr
->uVisibleHeight
=viewbottom
- viewtop
;
581 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject32 (DEFAULT_GUI_FONT
);
582 hOldFont
= SelectObject32 (hdc
, hFont
);
584 /* draw background */
585 hbrBk
= GetSysColorBrush32(COLOR_WINDOW
);
586 FillRect32(hdc
, &rect
, hbrBk
);
589 iItem
=infoPtr
->TopRootItem
;
590 infoPtr
->firstVisible
=0;
594 TRACE (treeview
, "[%d %d %d %d]\n",viewtop
,viewbottom
,viewleft
,viewright
);
598 wineItem
= & infoPtr
->items
[iItem
];
600 TRACE (treeview
, "%d %d [%d %d %d %d] (%s)\n",y
,x
,
601 wineItem
->rect
.top
, wineItem
->rect
.bottom
,
602 wineItem
->rect
.left
, wineItem
->rect
.right
,
605 height
=infoPtr
->uRealItemHeight
* wineItem
->iIntegral
;
606 if ((y
>= viewtop
) && (y
<= viewbottom
) &&
607 (x
>= viewleft
) && (x
<= viewright
)) {
608 wineItem
->rect
.top
= y
- infoPtr
->cy
+ rect
.top
;
609 wineItem
->rect
.bottom
= wineItem
->rect
.top
+ height
;
610 wineItem
->rect
.left
= x
- infoPtr
->cx
+ rect
.left
;
611 wineItem
->rect
.right
= rect
.right
;
612 if (!infoPtr
->firstVisible
)
613 infoPtr
->firstVisible
=wineItem
->hItem
;
614 TREEVIEW_DrawItem (wndPtr
, hdc
, wineItem
, prevItem
, indent
);
617 wineItem
->rect
.top
= wineItem
->rect
.bottom
= -1;
618 wineItem
->rect
.left
= wineItem
->rect
.right
= -1;
621 /* look up next item */
623 if ((wineItem
->firstChild
) && (wineItem
->state
& TVIS_EXPANDED
)) {
624 iItem
=wineItem
->firstChild
;
629 iItem
=wineItem
->sibling
;
630 while ((!iItem
) && (indent
>0)) {
634 wineItem
=&infoPtr
->items
[wineItem
->parent
];
635 iItem
=wineItem
->sibling
;
641 infoPtr
->uTotalHeight
=y
;
642 if (y
>= (viewbottom
-viewtop
)) {
643 if (!(infoPtr
->uInternalStatus
& TV_VSCROLL
))
644 ShowScrollBar32 (wndPtr
->hwndSelf
, SB_VERT
, TRUE
);
645 infoPtr
->uInternalStatus
|=TV_VSCROLL
;
646 SetScrollRange32 (wndPtr
->hwndSelf
, SB_VERT
, 0,
647 y
- infoPtr
->uVisibleHeight
, FALSE
);
648 SetScrollPos32 (wndPtr
->hwndSelf
, SB_VERT
, infoPtr
->cy
, TRUE
);
651 if (infoPtr
->uInternalStatus
& TV_VSCROLL
)
652 ShowScrollBar32 (wndPtr
->hwndSelf
, SB_VERT
, FALSE
);
653 infoPtr
->uInternalStatus
&= ~TV_VSCROLL
;
657 SelectObject32 (hdc
, hOldFont
);
662 TREEVIEW_HandleTimer ( WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
664 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
667 if (!infoPtr
) return FALSE
;
669 TRACE (treeview
, "timer\n");
672 case TV_REFRESH_TIMER
:
673 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
674 infoPtr
->Timer
&= ~TV_REFRESH_TIMER_SET
;
675 hdc
=GetDC32 (wndPtr
->hwndSelf
);
676 TREEVIEW_Refresh (wndPtr
, hdc
);
677 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
680 KillTimer32 (wndPtr
->hwndSelf
, TV_EDIT_TIMER
);
681 infoPtr
->Timer
&= ~TV_EDIT_TIMER_SET
;
690 TREEVIEW_QueueRefresh (WND
*wndPtr
)
693 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
695 TRACE (treeview
,"queued\n");
696 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
) {
697 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
700 SetTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
, TV_REFRESH_DELAY
, 0);
701 infoPtr
->Timer
|=TV_REFRESH_TIMER_SET
;
707 TREEVIEW_GetItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
709 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
711 TREEVIEW_ITEM
*wineItem
;
714 TRACE (treeview
,"\n");
715 tvItem
=(LPTVITEM
) lParam
;
718 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
719 if (!wineItem
) return FALSE
;
722 if (tvItem
->mask
& TVIF_CHILDREN
) {
723 tvItem
->cChildren
=wineItem
->cChildren
;
726 if (tvItem
->mask
& TVIF_HANDLE
) {
727 tvItem
->hItem
=wineItem
->hItem
;
730 if (tvItem
->mask
& TVIF_IMAGE
) {
731 tvItem
->iImage
=wineItem
->iImage
;
734 if (tvItem
->mask
& TVIF_INTEGRAL
) {
735 /* tvItem->iIntegral=wineItem->iIntegral; */
738 if (tvItem
->mask
& TVIF_PARAM
) {
739 tvItem
->lParam
=wineItem
->lParam
;
742 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
) {
743 tvItem
->iSelectedImage
=wineItem
->iSelectedImage
;
746 if (tvItem
->mask
& TVIF_STATE
) {
747 tvItem
->state
=wineItem
->state
& tvItem
->stateMask
;
750 if (tvItem
->mask
& TVIF_TEXT
) {
751 if (wineItem
->pszText
== LPSTR_TEXTCALLBACK32A
) {
752 tvItem
->pszText
= LPSTR_TEXTCALLBACK32A
;
754 else if (wineItem
->pszText
) {
755 lstrcpyn32A (tvItem
->pszText
, wineItem
->pszText
, tvItem
->cchTextMax
);
765 TREEVIEW_GetNextItem32 (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
768 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
769 TREEVIEW_ITEM
*wineItem
;
773 TRACE (treeview
,"item:%lu, flags:%x\n", lParam
, wParam
);
774 if (!infoPtr
) return FALSE
;
776 flag
= (INT32
) wParam
;
778 case TVGN_ROOT
: return (LRESULT
) infoPtr
->TopRootItem
;
779 case TVGN_CARET
: return (LRESULT
) infoPtr
->selectedItem
;
780 case TVGN_FIRSTVISIBLE
: return (LRESULT
) infoPtr
->firstVisible
;
781 case TVGN_DROPHILITE
: return (LRESULT
) infoPtr
->dropItem
;
784 iItem
= (INT32
) lParam
;
785 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
786 if (!wineItem
) return FALSE
;
789 case TVGN_NEXT
: return (LRESULT
) wineItem
->sibling
;
790 case TVGN_PREVIOUS
: return (LRESULT
) wineItem
->upsibling
;
791 case TVGN_PARENT
: return (LRESULT
) wineItem
->parent
;
792 case TVGN_CHILD
: return (LRESULT
) wineItem
->firstChild
;
793 case TVGN_LASTVISIBLE
: FIXME (treeview
,"TVGN_LASTVISIBLE not implemented\n");
795 case TVGN_NEXTVISIBLE
: wineItem
=TREEVIEW_GetNextListItem
798 return (LRESULT
) wineItem
->hItem
;
801 case TVGN_PREVIOUSVISIBLE
: wineItem
=TREEVIEW_GetPrevListItem
804 return (LRESULT
) wineItem
->hItem
;
807 default: FIXME (treeview
,"Unknown msg %x,item %x\n", flag
,iItem
);
815 TREEVIEW_GetCount (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
817 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
819 return (LRESULT
) infoPtr
->uNumItems
;
825 /* the method used below isn't the most memory-friendly, but it avoids
826 a lot of memory reallocations */
828 /* BTW: we waste handle 0; 0 is not an allowed handle. Fix this by
829 decreasing infoptr->items with 1, and increasing it by 1 if
830 it is referenced in mm-handling stuff? */
833 TREEVIEW_InsertItem32A (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
836 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
837 TVINSERTSTRUCT
*ptdi
;
839 TREEVIEW_ITEM
*wineItem
, *parentItem
, *prevsib
, *sibItem
;
840 INT32 iItem
,listItems
,i
,len
;
842 TRACE (treeview
,"\n");
843 ptdi
= (TVINSERTSTRUCT
*) lParam
;
845 /* check if memory is available */
847 if (infoPtr
->uNumPtrsAlloced
==0) {
848 infoPtr
->items
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
849 TVITEM_ALLOC
*sizeof (TREEVIEW_ITEM
));
850 infoPtr
->freeList
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
851 (1+(TVITEM_ALLOC
>>5)) *sizeof (INT32
));
852 infoPtr
->uNumPtrsAlloced
=TVITEM_ALLOC
;
853 infoPtr
->TopRootItem
=1;
856 if (infoPtr
->uNumItems
== (infoPtr
->uNumPtrsAlloced
-1) ) {
857 TREEVIEW_ITEM
*oldItems
= infoPtr
->items
;
858 INT32
*oldfreeList
= infoPtr
->freeList
;
860 infoPtr
->uNumPtrsAlloced
*=2;
861 infoPtr
->items
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
862 infoPtr
->uNumPtrsAlloced
*sizeof (TREEVIEW_ITEM
));
863 infoPtr
->freeList
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
864 (1+(infoPtr
->uNumPtrsAlloced
>>5))*sizeof (INT32
));
866 memcpy (&infoPtr
->items
[0], &oldItems
[0],
867 infoPtr
->uNumPtrsAlloced
/2 * sizeof(TREEVIEW_ITEM
));
868 memcpy (&infoPtr
->freeList
[0], &oldfreeList
[0],
869 (infoPtr
->uNumPtrsAlloced
>>6) * sizeof(INT32
));
871 HeapFree (GetProcessHeap (), 0, oldItems
);
872 HeapFree (GetProcessHeap (), 0, oldfreeList
);
876 infoPtr
->uNumItems
++;
878 if (infoPtr
->uMaxHandle
==(infoPtr
->uNumItems
-1)) {
879 iItem
=infoPtr
->uNumItems
;
880 infoPtr
->uMaxHandle
++;
882 else { /* check freelist */
883 for (i
=0; i
<infoPtr
->uNumPtrsAlloced
>>5; i
++) {
884 if (infoPtr
->freeList
[i
]) {
885 iItem
=ffs (infoPtr
->freeList
[i
]);
886 tv_clear_bit(iItem
,&infoPtr
->freeList
[i
]);
891 if (!iItem
) ERR (treeview
, "Argh -- can't find free item.\n");
893 tvItem
= & ptdi
->item
;
894 wineItem
=& infoPtr
->items
[iItem
];
898 if ((ptdi
->hParent
==TVI_ROOT
) || (ptdi
->hParent
==0)) {
901 sibItem
=&infoPtr
->items
[infoPtr
->TopRootItem
];
902 listItems
=infoPtr
->uNumItems
;
905 parentItem
= &infoPtr
->items
[ptdi
->hParent
];
906 if (!parentItem
->firstChild
)
907 parentItem
->firstChild
=iItem
;
908 wineItem
->parent
=ptdi
->hParent
;
909 sibItem
=&infoPtr
->items
[parentItem
->firstChild
];
910 parentItem
->cChildren
++;
911 listItems
=parentItem
->cChildren
;
914 wineItem
->upsibling
=0; /* needed in case we're the first item in a list */
916 wineItem
->firstChild
=0;
920 switch (ptdi
->hInsertAfter
) {
921 case TVI_FIRST
: wineItem
->sibling
=infoPtr
->TopRootItem
;
922 infoPtr
->TopRootItem
=iItem
;
925 while (sibItem
->sibling
) {
927 sibItem
=&infoPtr
->items
[sibItem
->sibling
];
929 sibItem
->sibling
=iItem
;
931 wineItem
->upsibling
=prevsib
->hItem
;
933 wineItem
->sibling
=0; /* terminate list */
936 FIXME (treeview
, "Sorted insert not implemented yet\n");
939 while ((sibItem
->sibling
) && (sibItem
->sibling
!=iItem
)) {
941 sibItem
=&infoPtr
->items
[sibItem
->sibling
];
943 if (sibItem
->sibling
)
944 WARN (treeview
, "Buggy program tried to insert item after nonexisting handle.");
945 sibItem
->upsibling
=iItem
;
946 wineItem
->sibling
=sibItem
->hItem
;
948 wineItem
->upsibling
=prevsib
->hItem
;
954 /* Fill in info structure */
956 wineItem
->mask
=tvItem
->mask
;
957 wineItem
->hItem
=iItem
;
958 wineItem
->iIntegral
=1;
960 if (tvItem
->mask
& TVIF_CHILDREN
)
961 wineItem
->cChildren
=tvItem
->cChildren
;
963 if (tvItem
->mask
& TVIF_IMAGE
)
964 wineItem
->iImage
=tvItem
->iImage
;
966 /* if (tvItem->mask & TVIF_INTEGRAL)
967 wineItem->iIntegral=tvItem->iIntegral; */
970 if (tvItem
->mask
& TVIF_PARAM
)
971 wineItem
->lParam
=tvItem
->lParam
;
973 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
)
974 wineItem
->iSelectedImage
=tvItem
->iSelectedImage
;
976 if (tvItem
->mask
& TVIF_STATE
) {
977 wineItem
->state
=tvItem
->state
;
978 wineItem
->stateMask
=tvItem
->stateMask
;
981 if (tvItem
->mask
& TVIF_TEXT
) {
982 TRACE (treeview
,"(%s)\n", tvItem
->pszText
);
983 if (tvItem
->pszText
!=LPSTR_TEXTCALLBACK32A
) {
984 len
= lstrlen32A (tvItem
->pszText
)+1;
986 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, len
+1);
987 lstrcpy32A (wineItem
->pszText
, tvItem
->pszText
);
988 wineItem
->cchTextMax
=len
;
991 wineItem
->pszText
= LPSTR_TEXTCALLBACK32A
;
992 wineItem
->cchTextMax
= 0;
996 TREEVIEW_QueueRefresh (wndPtr
);
998 return (LRESULT
) iItem
;
1004 TREEVIEW_DeleteItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1006 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1009 TREEVIEW_ITEM
*wineItem
;
1011 TRACE (treeview
,"\n");
1012 if (!infoPtr
) return FALSE
;
1014 if ((INT32
) lParam
== TVI_ROOT
) {
1015 TREEVIEW_RemoveTree (infoPtr
);
1017 iItem
= (INT32
) lParam
;
1018 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
1019 if (!wineItem
) return FALSE
;
1020 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_DELETEITEM
, 0, iItem
, 0, pt
);
1021 TREEVIEW_RemoveItem (infoPtr
, wineItem
);
1024 TREEVIEW_QueueRefresh (wndPtr
);
1031 TREEVIEW_GetIndent (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1033 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1035 return infoPtr
->uIndent
;
1039 TREEVIEW_SetIndent (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1041 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1044 newIndent
=(INT32
) wParam
;
1045 if (newIndent
< MINIMUM_INDENT
) newIndent
=MINIMUM_INDENT
;
1046 infoPtr
->uIndent
=newIndent
;
1056 TREEVIEW_Create (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1058 TREEVIEW_INFO
*infoPtr
;
1062 TRACE (treeview
,"\n");
1063 /* allocate memory for info structure */
1064 infoPtr
= (TREEVIEW_INFO
*)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
1065 sizeof(TREEVIEW_INFO
));
1067 wndPtr
->wExtra
[0] = (DWORD
)infoPtr
;
1069 if (infoPtr
== NULL
) {
1070 ERR (treeview
, "could not allocate info memory!\n");
1074 if ((TREEVIEW_INFO
*)wndPtr
->wExtra
[0] != infoPtr
) {
1075 ERR (treeview
, "pointer assignment error!\n");
1079 hdc
=GetDC32 (wndPtr
->hwndSelf
);
1081 /* set default settings */
1082 infoPtr
->uInternalStatus
=0;
1083 infoPtr
->uNumItems
=0;
1084 infoPtr
->clrBk
= GetSysColor32 (COLOR_WINDOW
);
1085 infoPtr
->clrText
= GetSysColor32 (COLOR_BTNTEXT
);
1088 infoPtr
->uIndent
= 15;
1089 infoPtr
->himlNormal
= NULL
;
1090 infoPtr
->himlState
= NULL
;
1091 infoPtr
->uItemHeight
= -1;
1092 GetTextMetrics32A (hdc
, &tm
);
1093 infoPtr
->uRealItemHeight
= tm
.tmHeight
+ tm
.tmExternalLeading
;
1095 infoPtr
->items
= NULL
;
1096 infoPtr
->selectedItem
=0;
1097 infoPtr
->clrText
=-1; /* use system color */
1098 infoPtr
->dropItem
=0;
1101 infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
1102 infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
1105 if (wndPtr
->dwStyle
& TBSTYLE_TOOLTIPS
) {
1106 /* Create tooltip control */
1107 // infoPtr->hwndToolTip = CreateWindowEx32A (....);
1109 /* Send TV_TOOLTIPSCREATED notification */
1112 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1120 TREEVIEW_Destroy (WND
*wndPtr
)
1122 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1124 TREEVIEW_RemoveTree (infoPtr
);
1125 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
)
1126 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
1128 HeapFree (GetProcessHeap (), 0, infoPtr
);
1135 TREEVIEW_Paint (WND
*wndPtr
, WPARAM32 wParam
)
1140 hdc
= wParam
==0 ? BeginPaint32 (wndPtr
->hwndSelf
, &ps
) : (HDC32
)wParam
;
1141 TREEVIEW_QueueRefresh (wndPtr
);
1143 EndPaint32 (wndPtr
->hwndSelf
, &ps
);
1150 TREEVIEW_EraseBackground (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1152 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1153 HBRUSH32 hBrush
= CreateSolidBrush32 (infoPtr
->clrBk
);
1156 TRACE (treeview
,"\n");
1157 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
1158 FillRect32 ((HDC32
)wParam
, &rect
, hBrush
);
1159 DeleteObject32 (hBrush
);
1172 TREEVIEW_SendSimpleNotify (WND
*wndPtr
, UINT32 code
)
1176 TRACE (treeview
, "%x\n",code
);
1177 nmhdr
.hwndFrom
= wndPtr
->hwndSelf
;
1178 nmhdr
.idFrom
= wndPtr
->wIDmenu
;
1181 return (BOOL32
) SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
1182 (WPARAM32
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1189 TREEVIEW_SendTreeviewNotify (WND
*wndPtr
, UINT32 code
, UINT32 action
,
1190 INT32 oldItem
, INT32 newItem
, POINT32 pt
)
1192 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1194 TREEVIEW_ITEM
*wineItem
;
1196 TRACE (treeview
,"code:%x action:%x olditem:%x newitem:%x\n",
1197 code
,action
,oldItem
,newItem
);
1198 nmhdr
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
1199 nmhdr
.hdr
.idFrom
= wndPtr
->wIDmenu
;
1200 nmhdr
.hdr
.code
= code
;
1201 nmhdr
.action
= action
;
1203 wineItem
=& infoPtr
->items
[oldItem
];
1204 nmhdr
.itemOld
.mask
= wineItem
->mask
;
1205 nmhdr
.itemOld
.hItem
= wineItem
->hItem
;
1206 nmhdr
.itemOld
.state
= wineItem
->state
;
1207 nmhdr
.itemOld
.stateMask
= wineItem
->stateMask
;
1208 nmhdr
.itemOld
.iImage
= wineItem
->iImage
;
1209 nmhdr
.itemOld
.pszText
= wineItem
->pszText
;
1210 nmhdr
.itemOld
.cchTextMax
= wineItem
->cchTextMax
;
1211 nmhdr
.itemOld
.iImage
= wineItem
->iImage
;
1212 nmhdr
.itemOld
.iSelectedImage
= wineItem
->iSelectedImage
;
1213 nmhdr
.itemOld
.cChildren
= wineItem
->cChildren
;
1214 nmhdr
.itemOld
.lParam
= wineItem
->lParam
;
1218 wineItem
=& infoPtr
->items
[newItem
];
1219 nmhdr
.itemNew
.mask
= wineItem
->mask
;
1220 nmhdr
.itemNew
.hItem
= wineItem
->hItem
;
1221 nmhdr
.itemNew
.state
= wineItem
->state
;
1222 nmhdr
.itemNew
.stateMask
= wineItem
->stateMask
;
1223 nmhdr
.itemNew
.iImage
= wineItem
->iImage
;
1224 nmhdr
.itemNew
.pszText
= wineItem
->pszText
;
1225 nmhdr
.itemNew
.cchTextMax
= wineItem
->cchTextMax
;
1226 nmhdr
.itemNew
.iImage
= wineItem
->iImage
;
1227 nmhdr
.itemNew
.iSelectedImage
= wineItem
->iSelectedImage
;
1228 nmhdr
.itemNew
.cChildren
= wineItem
->cChildren
;
1229 nmhdr
.itemNew
.lParam
= wineItem
->lParam
;
1232 nmhdr
.ptDrag
.x
= pt
.x
;
1233 nmhdr
.ptDrag
.y
= pt
.y
;
1235 return (BOOL32
)SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
1236 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&nmhdr
);
1244 TREEVIEW_Expand (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1246 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1247 TREEVIEW_ITEM
*wineItem
;
1252 flag
= (UINT32
) wParam
;
1253 expandItem
= (INT32
) lParam
;
1254 TRACE (treeview
,"flags:%x item:%x\n", expandItem
, wParam
);
1255 wineItem
= TREEVIEW_ValidItem (infoPtr
, expandItem
);
1256 if (!wineItem
) return 0;
1257 if (!wineItem
->cChildren
) return 0;
1259 if (flag
& TVE_TOGGLE
) { /* FIXME: check exact behaviour here */
1260 flag
&= ~TVE_TOGGLE
; /* ie: bitwise ops or 'case' ops */
1261 if (wineItem
->state
& TVIS_EXPANDED
)
1262 flag
|= TVE_COLLAPSE
;
1268 case TVE_COLLAPSERESET
:
1269 if (!wineItem
->state
& TVIS_EXPANDED
) return 0;
1270 wineItem
->state
&= ~(TVIS_EXPANDEDONCE
| TVIS_EXPANDED
);
1271 TREEVIEW_RemoveAllChildren (infoPtr
, wineItem
);
1275 if (!wineItem
->state
& TVIS_EXPANDED
) return 0;
1276 wineItem
->state
&= ~TVIS_EXPANDED
;
1280 if (wineItem
->state
& TVIS_EXPANDED
) return 0;
1281 if (!(wineItem
->state
& TVIS_EXPANDEDONCE
)) {
1282 if (TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_ITEMEXPANDING
,
1283 0, 0, expandItem
, pt
))
1284 return FALSE
; /* FIXME: OK? */
1285 wineItem
->state
|= TVIS_EXPANDED
| TVIS_EXPANDEDONCE
;
1286 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_ITEMEXPANDED
,
1287 0, 0, expandItem
, pt
);
1289 wineItem
->state
|= TVIS_EXPANDED
;
1291 case TVE_EXPANDPARTIAL
:
1292 FIXME (treeview
, "TVE_EXPANDPARTIAL not implemented\n");
1293 wineItem
->state
^=TVIS_EXPANDED
;
1294 wineItem
->state
|=TVIS_EXPANDEDONCE
;
1298 TREEVIEW_QueueRefresh (wndPtr
);
1306 TREEVIEW_HitTest (WND
*wndPtr
, LPTVHITTESTINFO lpht
)
1308 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1309 TREEVIEW_ITEM
*wineItem
;
1315 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
1316 TRACE (treeview
,"(%d,%d)\n",lpht
->pt
.x
, lpht
->pt
.y
);
1321 if (x
< rect
.left
) status
|=TVHT_TOLEFT
;
1322 if (x
> rect
.right
) status
|=TVHT_TORIGHT
;
1323 if (y
< rect
.top
) status
|=TVHT_ABOVE
;
1324 if (y
> rect
.bottom
) status
|=TVHT_BELOW
;
1330 if (!infoPtr
->firstVisible
) WARN (treeview
,"Can't fetch first visible item");
1331 wineItem
=&infoPtr
->items
[infoPtr
->firstVisible
];
1333 while ((wineItem
!=NULL
) && (y
> wineItem
->rect
.bottom
))
1334 wineItem
=TREEVIEW_GetNextListItem (infoPtr
,wineItem
);
1336 if (wineItem
==NULL
) {
1337 lpht
->flags
=TVHT_NOWHERE
;
1341 if (x
>wineItem
->rect
.right
) {
1342 lpht
->flags
|=TVHT_ONITEMRIGHT
;
1343 return wineItem
->hItem
;
1347 if (x
<wineItem
->rect
.left
+10) lpht
->flags
|=TVHT_ONITEMBUTTON
;
1349 lpht
->flags
=TVHT_ONITEMLABEL
; /* FIXME: implement other flags */
1352 lpht
->hItem
=wineItem
->hItem
;
1353 return wineItem
->hItem
;
1358 TREEVIEW_HitTest32 (WND
*wndPtr
, LPARAM lParam
)
1361 return (LRESULT
) TREEVIEW_HitTest (wndPtr
, (LPTVHITTESTINFO
) lParam
);
1368 TREEVIEW_LButtonDoubleClick (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1370 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1371 TREEVIEW_ITEM
*wineItem
;
1375 TRACE (treeview
,"\n");
1376 ht
.pt
.x
= (INT32
)LOWORD(lParam
);
1377 ht
.pt
.y
= (INT32
)HIWORD(lParam
);
1378 SetFocus32 (wndPtr
->hwndSelf
);
1380 iItem
=TREEVIEW_HitTest (wndPtr
, &ht
);
1381 TRACE (treeview
,"item %d \n",iItem
);
1382 wineItem
=TREEVIEW_ValidItem (infoPtr
, iItem
);
1383 if (!wineItem
) return 0;
1385 if (TREEVIEW_SendSimpleNotify (wndPtr
, NM_DBLCLK
)!=TRUE
) { /* FIXME!*/
1386 wineItem
->state
&= ~TVIS_EXPANDEDONCE
;
1387 TREEVIEW_Expand (wndPtr
, (WPARAM32
) TVE_TOGGLE
, (LPARAM
) iItem
);
1395 TREEVIEW_LButtonDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1400 TRACE (treeview
,"\n");
1401 ht
.pt
.x
= (INT32
)LOWORD(lParam
);
1402 ht
.pt
.y
= (INT32
)HIWORD(lParam
);
1404 SetFocus32 (wndPtr
->hwndSelf
);
1405 iItem
=TREEVIEW_HitTest (wndPtr
, &ht
);
1406 TRACE (treeview
,"item %d \n",iItem
);
1407 if (ht
.flags
& TVHT_ONITEMBUTTON
) {
1408 TREEVIEW_Expand (wndPtr
, (WPARAM32
) TVE_TOGGLE
, (LPARAM
) iItem
);
1411 if (TREEVIEW_SelectItem (wndPtr
, (WPARAM32
) TVGN_CARET
, (LPARAM
) iItem
))
1420 TREEVIEW_RButtonDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1429 /* FIXME: If the specified item is the child of a collapsed parent item,
1430 expand parent's list of child items to reveal the specified item.
1434 TREEVIEW_SelectItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1436 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1437 TREEVIEW_ITEM
*prevItem
,*wineItem
;
1438 INT32 action
,prevSelect
, newSelect
;
1441 TRACE (treeview
,"item %lx, flag %x\n", lParam
, wParam
);
1442 newSelect
= (INT32
) lParam
;
1443 wineItem
= TREEVIEW_ValidItem (infoPtr
, newSelect
);
1444 if (!wineItem
) return FALSE
;
1445 prevSelect
=infoPtr
->selectedItem
;
1446 prevItem
= TREEVIEW_ValidItem (infoPtr
, prevSelect
);
1450 action
= (INT32
) wParam
;
1454 if (TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_SELCHANGING
, TVC_BYMOUSE
,
1455 prevSelect
, newSelect
,dummy
))
1456 return FALSE
; /* FIXME: OK? */
1458 if (prevItem
) prevItem
->state
&= ~TVIS_SELECTED
;
1459 infoPtr
->selectedItem
=newSelect
;
1460 wineItem
->state
|=TVIS_SELECTED
;
1461 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_SELCHANGED
,
1462 TVC_BYMOUSE
, prevSelect
, newSelect
, dummy
);
1464 case TVGN_DROPHILITE
:
1465 FIXME (treeview
, "DROPHILITE not implemented");
1467 case TVGN_FIRSTVISIBLE
:
1468 FIXME (treeview
, "FIRSTVISIBLE not implemented");
1472 TREEVIEW_QueueRefresh (wndPtr
);
1479 /* FIXME: does KEYDOWN also send notifications?? If so, use
1480 TREEVIEW_SelectItem.
1485 TREEVIEW_KeyDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1487 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1488 TREEVIEW_ITEM
*prevItem
,*newItem
;
1492 TRACE (treeview
,"%x %lx\n",wParam
, lParam
);
1493 prevSelect
=infoPtr
->selectedItem
;
1494 if (!prevSelect
) return FALSE
;
1496 prevItem
= TREEVIEW_ValidItem (infoPtr
, prevSelect
);
1501 newItem
=TREEVIEW_GetPrevListItem (infoPtr
, prevItem
);
1503 newItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
1506 newItem
=TREEVIEW_GetNextListItem (infoPtr
, prevItem
);
1507 if (!newItem
) newItem
=prevItem
;
1510 newItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
1513 newItem
=TREEVIEW_GetLastListItem (infoPtr
);
1519 FIXME (treeview
, "%x not implemented\n", wParam
);
1523 if (!newItem
) return FALSE
;
1525 if (prevItem
!=newItem
) {
1526 prevItem
->state
&= ~TVIS_SELECTED
;
1527 newItem
->state
|= TVIS_SELECTED
;
1528 infoPtr
->selectedItem
=newItem
->hItem
;
1529 TREEVIEW_QueueRefresh (wndPtr
);
1539 TREEVIEW_VScroll (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1542 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1545 TRACE (treeview
,"wp %x, lp %lx\n", wParam
, lParam
);
1546 if (!infoPtr
->uInternalStatus
& TV_VSCROLL
) return FALSE
;
1548 switch (LOWORD (wParam
)) {
1550 if (!infoPtr
->cy
) return FALSE
;
1551 infoPtr
->cy
-= infoPtr
->uRealItemHeight
;
1552 if (infoPtr
->cy
< 0) infoPtr
->cy
=0;
1555 maxHeight
=infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
1556 if (infoPtr
->cy
== maxHeight
) return FALSE
;
1557 infoPtr
->cy
+= infoPtr
->uRealItemHeight
;
1558 if (infoPtr
->cy
> maxHeight
)
1559 infoPtr
->cy
= maxHeight
;
1562 if (!infoPtr
->cy
) return FALSE
;
1563 infoPtr
->cy
-= infoPtr
->uVisibleHeight
;
1564 if (infoPtr
->cy
< 0) infoPtr
->cy
=0;
1567 maxHeight
=infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
1568 if (infoPtr
->cy
== maxHeight
) return FALSE
;
1569 infoPtr
->cy
+= infoPtr
->uVisibleHeight
;
1570 if (infoPtr
->cy
> maxHeight
)
1571 infoPtr
->cy
= maxHeight
;
1574 infoPtr
->cy
= HIWORD (wParam
);
1579 TREEVIEW_QueueRefresh (wndPtr
);
1584 TREEVIEW_HScroll (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1586 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1588 TRACE (treeview
,"wp %lx, lp %x\n", lParam
, wParam
);
1590 if (!infoPtr
->uInternalStatus
& TV_HSCROLL
) return FALSE
;
1598 TREEVIEW_WindowProc (HWND32 hwnd
, UINT32 uMsg
, WPARAM32 wParam
, LPARAM lParam
)
1600 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1604 case TVM_INSERTITEM32A
:
1605 return TREEVIEW_InsertItem32A (wndPtr
, wParam
, lParam
);
1607 case TVM_INSERTITEM32W
:
1608 FIXME (treeview
, "Unimplemented msg TVM_INSERTITEM32W\n");
1611 case TVM_DELETEITEM
:
1612 return TREEVIEW_DeleteItem (wndPtr
, wParam
, lParam
);
1615 return TREEVIEW_Expand (wndPtr
, wParam
, lParam
);
1617 case TVM_GETITEMRECT
:
1618 return TREEVIEW_GetItemRect (wndPtr
, wParam
, lParam
);
1621 return TREEVIEW_GetCount (wndPtr
, wParam
, lParam
);
1624 return TREEVIEW_GetIndent (wndPtr
, wParam
, lParam
);
1627 return TREEVIEW_SetIndent (wndPtr
, wParam
, lParam
);
1629 case TVM_GETIMAGELIST
:
1630 return TREEVIEW_GetImageList (wndPtr
, wParam
, lParam
);
1632 case TVM_SETIMAGELIST
:
1633 return TREEVIEW_SetImageList (wndPtr
, wParam
, lParam
);
1635 case TVM_GETNEXTITEM
:
1636 return TREEVIEW_GetNextItem32 (wndPtr
, wParam
, lParam
);
1638 case TVM_SELECTITEM
:
1639 return TREEVIEW_SelectItem (wndPtr
, wParam
, lParam
);
1641 case TVM_GETITEM32A
:
1642 return TREEVIEW_GetItem (wndPtr
, wParam
, lParam
);
1644 case TVM_GETITEM32W
:
1645 FIXME (treeview
, "Unimplemented msg TVM_GETITEM32W\n");
1648 case TVM_SETITEM32A
:
1649 return TREEVIEW_SetItem (wndPtr
, wParam
, lParam
);
1651 case TVM_SETITEM32W
:
1652 FIXME (treeview
, "Unimplemented msg TVM_SETITEMW\n");
1655 case TVM_EDITLABEL32A
:
1656 FIXME (treeview
, "Unimplemented msg TVM_EDITLABEL32A \n");
1659 case TVM_EDITLABEL32W
:
1660 FIXME (treeview
, "Unimplemented msg TVM_EDITLABEL32W \n");
1663 case TVM_GETEDITCONTROL
:
1664 FIXME (treeview
, "Unimplemented msg TVM_GETEDITCONTROL\n");
1667 case TVM_GETVISIBLECOUNT
:
1668 return TREEVIEW_GetVisibleCount (wndPtr
, wParam
, lParam
);
1671 return TREEVIEW_HitTest32 (wndPtr
, lParam
);
1673 case TVM_CREATEDRAGIMAGE
:
1674 FIXME (treeview
, "Unimplemented msg TVM_CREATEDRAGIMAGE\n");
1677 case TVM_SORTCHILDREN
:
1678 FIXME (treeview
, "Unimplemented msg TVM_SORTCHILDREN\n");
1681 case TVM_ENSUREVISIBLE
:
1682 FIXME (treeview
, "Unimplemented msg TVM_ENSUREVISIBLE\n");
1685 case TVM_SORTCHILDRENCB
:
1686 FIXME (treeview
, "Unimplemented msg TVM_SORTCHILDRENCB\n");
1689 case TVM_ENDEDITLABELNOW
:
1690 FIXME (treeview
, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
1693 case TVM_GETISEARCHSTRING32A
:
1694 FIXME (treeview
, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
1697 case TVM_GETISEARCHSTRING32W
:
1698 FIXME (treeview
, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
1701 case TVM_SETTOOLTIPS
:
1702 FIXME (treeview
, "Unimplemented msg TVM_SETTOOLTIPS\n");
1705 case TVM_GETTOOLTIPS
:
1706 FIXME (treeview
, "Unimplemented msg TVM_GETTOOLTIPS\n");
1709 case TVM_SETINSERTMARK
:
1710 FIXME (treeview
, "Unimplemented msg TVM_SETINSERTMARK\n");
1713 case TVM_SETITEMHEIGHT
:
1714 return TREEVIEW_SetItemHeight (wndPtr
, wParam
);
1716 case TVM_GETITEMHEIGHT
:
1717 return TREEVIEW_GetItemHeight (wndPtr
);
1719 case TVM_SETBKCOLOR
:
1720 FIXME (treeview
, "Unimplemented msg TVM_SETBKCOLOR\n");
1723 case TVM_SETTEXTCOLOR
:
1724 return TREEVIEW_SetTextColor (wndPtr
, wParam
, lParam
);
1726 case TVM_GETBKCOLOR
:
1727 FIXME (treeview
, "Unimplemented msg TVM_GETBKCOLOR\n");
1730 case TVM_GETTEXTCOLOR
:
1731 return TREEVIEW_GetTextColor (wndPtr
);
1733 case TVM_SETSCROLLTIME
:
1734 FIXME (treeview
, "Unimplemented msg TVM_SETSCROLLTIME\n");
1737 case TVM_GETSCROLLTIME
:
1738 FIXME (treeview
, "Unimplemented msg TVM_GETSCROLLTIME\n");
1741 case TVM_SETINSERTMARKCOLOR
:
1742 FIXME (treeview
, "Unimplemented msg TVM_SETINSERTMARKCOLOR\n");
1745 case TVM_SETUNICODEFORMAT
:
1746 FIXME (treeview
, "Unimplemented msg TVM_SETUNICODEFORMAT\n");
1749 case TVM_GETUNICODEFORMAT
:
1750 FIXME (treeview
, "Unimplemented msg TVM_GETUNICODEFORMAT\n");
1756 return TREEVIEW_Create (wndPtr
, wParam
, lParam
);
1759 return TREEVIEW_Destroy (wndPtr
);
1764 return TREEVIEW_EraseBackground (wndPtr
, wParam
, lParam
);
1767 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
1770 return TREEVIEW_Paint (wndPtr
, wParam
);
1776 return TREEVIEW_KeyDown (wndPtr
, wParam
, lParam
);
1779 // case WM_KILLFOCUS:
1780 // case WM_SETFOCUS:
1783 case WM_LBUTTONDOWN
:
1784 return TREEVIEW_LButtonDown (wndPtr
, wParam
, lParam
);
1786 case WM_LBUTTONDBLCLK
:
1787 return TREEVIEW_LButtonDoubleClick (wndPtr
, wParam
, lParam
);
1789 case WM_RBUTTONDOWN
:
1790 return TREEVIEW_RButtonDown (wndPtr
, wParam
, lParam
);
1793 // case WM_SYSCOLORCHANGE:
1794 // case WM_STYLECHANGED:
1795 // case WM_SETREDRAW:
1798 return TREEVIEW_HandleTimer (wndPtr
, wParam
, lParam
);
1802 return TREEVIEW_HScroll (wndPtr
, wParam
, lParam
);
1804 return TREEVIEW_VScroll (wndPtr
, wParam
, lParam
);
1807 if (uMsg
>= WM_USER
)
1808 FIXME (treeview
, "Unknown msg %04x wp=%08x lp=%08lx\n",
1809 uMsg
, wParam
, lParam
);
1810 return DefWindowProc32A (hwnd
, uMsg
, wParam
, lParam
);
1817 TREEVIEW_Register (VOID
)
1819 WNDCLASS32A wndClass
;
1821 TRACE (treeview
,"\n");
1823 if (GlobalFindAtom32A (WC_TREEVIEW32A
)) return;
1825 ZeroMemory (&wndClass
, sizeof(WNDCLASS32A
));
1826 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1827 wndClass
.lpfnWndProc
= (WNDPROC32
)TREEVIEW_WindowProc
;
1828 wndClass
.cbClsExtra
= 0;
1829 wndClass
.cbWndExtra
= sizeof(TREEVIEW_INFO
*);
1830 wndClass
.hCursor
= LoadCursor32A (0, IDC_ARROW32A
);
1831 wndClass
.hbrBackground
= 0;
1832 wndClass
.lpszClassName
= WC_TREEVIEW32A
;
1834 RegisterClass32A (&wndClass
);
1839 TREEVIEW_Unregister (VOID
)
1841 if (GlobalFindAtom32A (WC_TREEVIEW32A
))
1842 UnregisterClass32A (WC_TREEVIEW32A
, (HINSTANCE32
)NULL
);