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).
35 #if defined(__FreeBSD__)
36 #include <bitstring.h>
37 #define test_bit(bit,name) bit_test(name,bit)
38 #define set_bit(bit,name) bit_set(name,bit)
39 #define clear_bit(bit,name) bit_clear(name,bit)
41 #include <asm/bitops.h> /* FIXME: linux specific */
44 #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
47 TREEVIEW_SendSimpleNotify (WND
*wndPtr
, UINT32 code
);
49 TREEVIEW_SendTreeviewNotify (WND
*wndPtr
, UINT32 code
, UINT32 action
,
50 INT32 oldItem
, INT32 newItem
, POINT32 pt
);
52 TREEVIEW_SelectItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
);
54 TREEVIEW_Refresh (WND
*wndPtr
, HDC32 hdc
);
60 /* helper functions. Work with the assumption that validity of operands
61 is checked beforehand */
64 static TREEVIEW_ITEM
*
65 TREEVIEW_ValidItem (TREEVIEW_INFO
*infoPtr
,int handle
)
68 if ((!handle
) || (handle
>infoPtr
->uMaxHandle
)) return NULL
;
69 if (test_bit (handle
, infoPtr
->freeList
)) return NULL
;
71 return & infoPtr
->items
[handle
];
76 static TREEVIEW_ITEM
*TREEVIEW_GetPrevListItem (TREEVIEW_INFO
*infoPtr
,
77 TREEVIEW_ITEM
*tvItem
)
80 TREEVIEW_ITEM
*wineItem
;
82 if (tvItem
->upsibling
)
83 return (& infoPtr
->items
[tvItem
->upsibling
]);
86 while (wineItem
->parent
) {
87 wineItem
=& infoPtr
->items
[wineItem
->parent
];
88 if (wineItem
->upsibling
)
89 return (& infoPtr
->items
[wineItem
->upsibling
]);
95 static TREEVIEW_ITEM
*TREEVIEW_GetNextListItem (TREEVIEW_INFO
*infoPtr
,
96 TREEVIEW_ITEM
*tvItem
)
99 TREEVIEW_ITEM
*wineItem
;
102 return (& infoPtr
->items
[tvItem
->sibling
]);
105 while (wineItem
->parent
) {
106 wineItem
=& infoPtr
->items
[wineItem
->parent
];
107 if (wineItem
->sibling
)
108 return (& infoPtr
->items
[wineItem
->sibling
]);
114 static TREEVIEW_ITEM
*TREEVIEW_GetLastListItem (TREEVIEW_INFO
*infoPtr
)
117 TREEVIEW_ITEM
*wineItem
;
120 if (infoPtr
->TopRootItem
)
121 wineItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
122 while (wineItem
->sibling
)
123 wineItem
=& infoPtr
->items
[wineItem
->sibling
];
132 TREEVIEW_RemoveItem (TREEVIEW_INFO
*infoPtr
, TREEVIEW_ITEM
*wineItem
)
135 TREEVIEW_ITEM
*parentItem
, *upsiblingItem
, *siblingItem
;
138 iItem
=wineItem
->hItem
;
139 set_bit ( iItem
& 31, &infoPtr
->freeList
[iItem
>>5]);
140 infoPtr
->uNumItems
--;
142 if (wineItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
143 HeapFree (GetProcessHeap (), 0, wineItem
->pszText
);
145 if (wineItem
->parent
) {
146 parentItem
=& infoPtr
->items
[ wineItem
->parent
];
147 if (parentItem
->cChildren
==1) {
148 parentItem
->cChildren
=0;
149 parentItem
->firstChild
=0;
152 parentItem
->cChildren
--;
153 if (parentItem
->firstChild
==iItem
)
154 parentItem
->firstChild
=wineItem
->sibling
;
158 if (iItem
==infoPtr
->TopRootItem
)
159 infoPtr
->TopRootItem
=wineItem
->sibling
;
160 if (wineItem
->upsibling
) {
161 upsiblingItem
=& infoPtr
->items
[wineItem
->upsibling
];
162 upsiblingItem
->sibling
=wineItem
->sibling
;
164 if (wineItem
->sibling
) {
165 siblingItem
=& infoPtr
->items
[wineItem
->sibling
];
166 siblingItem
->upsibling
=wineItem
->upsibling
;
172 static void TREEVIEW_RemoveAllChildren (TREEVIEW_INFO
*infoPtr
,
173 TREEVIEW_ITEM
*parentItem
)
176 TREEVIEW_ITEM
*killItem
;
179 kill
=parentItem
->firstChild
;
181 set_bit ( kill
& 31, &infoPtr
->freeList
[kill
>>5]);
182 killItem
=& infoPtr
->items
[kill
];
183 if (killItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
184 HeapFree (GetProcessHeap (), 0, killItem
->pszText
);
185 kill
=killItem
->sibling
;
187 infoPtr
->uNumItems
-= parentItem
->cChildren
;
188 parentItem
->firstChild
= 0;
189 parentItem
->cChildren
= 0;
193 /* Note:TREEVIEW_RemoveTree doesn't remove infoPtr itself */
195 static void TREEVIEW_RemoveTree (TREEVIEW_INFO
*infoPtr
)
199 TREEVIEW_ITEM
*killItem
;
202 for (i
=1; i
<=infoPtr
->uMaxHandle
; i
++)
203 if (!test_bit (i
, infoPtr
->freeList
)) {
204 killItem
=& infoPtr
->items
[i
];
205 if (killItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
206 HeapFree (GetProcessHeap (), 0, killItem
->pszText
);
209 if (infoPtr
->uNumPtrsAlloced
) {
210 HeapFree (GetProcessHeap (), 0, infoPtr
->items
);
211 HeapFree (GetProcessHeap (), 0, infoPtr
->freeList
);
212 infoPtr
->uNumItems
=0;
213 infoPtr
->uNumPtrsAlloced
=0;
214 infoPtr
->uMaxHandle
=0;
228 TREEVIEW_GetImageList (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
230 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
232 TRACE (treeview
,"\n");
234 if (infoPtr
==NULL
) return 0;
236 if ((INT32
)wParam
== TVSIL_NORMAL
)
237 return (LRESULT
) infoPtr
->himlNormal
;
238 if ((INT32
)wParam
== TVSIL_STATE
)
239 return (LRESULT
) infoPtr
->himlState
;
248 TREEVIEW_SetImageList (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
250 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
253 switch ((INT32
)wParam
) {
255 himlTemp
= infoPtr
->himlNormal
;
256 infoPtr
->himlNormal
= (HIMAGELIST
)lParam
;
257 return (LRESULT
)himlTemp
;
260 himlTemp
= infoPtr
->himlState
;
261 infoPtr
->himlState
= (HIMAGELIST
)lParam
;
262 return (LRESULT
)himlTemp
;
265 return (LRESULT
)NULL
;
271 TREEVIEW_SetItemHeight (WND
*wndPtr
, WPARAM32 wParam
)
273 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
274 INT32 prevHeight
=infoPtr
->uItemHeight
;
280 hdc
=GetDC32 (wndPtr
->hwndSelf
);
281 infoPtr
->uItemHeight
=-1;
282 GetTextMetrics32A (hdc
, &tm
);
283 infoPtr
->uRealItemHeight
= tm
.tmHeight
+ tm
.tmExternalLeading
;
284 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
288 /* FIXME: check wParam > imagelist height */
290 if (!(wndPtr
->dwStyle
& TVS_NONEVENHEIGHT
))
291 infoPtr
->uItemHeight
= (INT32
) wParam
& 0xfffffffe;
296 TREEVIEW_GetItemHeight (WND
*wndPtr
)
298 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
300 return infoPtr
->uItemHeight
;
304 TREEVIEW_SetTextColor (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
306 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
307 COLORREF prevColor
=infoPtr
->clrText
;
309 infoPtr
->clrText
=(COLORREF
) lParam
;
310 return (LRESULT
) prevColor
;
314 TREEVIEW_GetTextColor (WND
*wndPtr
)
316 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
318 return (LRESULT
) infoPtr
->clrText
;
323 TREEVIEW_DrawItem (WND
*wndPtr
, HDC32 hdc
, TREEVIEW_ITEM
*wineItem
,
324 TREEVIEW_ITEM
*upperItem
, int indent
)
326 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
327 INT32 oldBkMode
,center
,xpos
;
329 UINT32 uTextJustify
= DT_LEFT
;
330 HPEN32 hOldPen
, hnewPen
,hRootPen
;
333 hnewPen
= CreatePen32(PS_DOT
, 0, GetSysColor32(COLOR_WINDOWTEXT
) );
334 hOldPen
= SelectObject32( hdc
, hnewPen
);
338 upper
=upperItem
->rect
;
343 center
=(r
.top
+r
.bottom
)/2;
346 if (wndPtr
->dwStyle
& TVS_HASLINES
) {
348 if ((wndPtr
->dwStyle
& TVS_LINESATROOT
) && (indent
==0)) {
349 points
[0].y
=points
[1].y
=center
;
350 points
[2].y
=upper
.top
;
351 points
[1].x
=points
[2].x
=upper
.left
;
352 points
[0].x
=upper
.left
+12;
355 Polyline32 (hdc
,points
,3);
358 points
[0].y
=points
[1].y
=center
;
359 points
[2].y
=upper
.top
;
360 points
[1].x
=points
[2].x
=upper
.left
+13;
361 points
[0].x
=upper
.left
+25;
363 Polyline32 (hdc
,points
,3);
367 DeleteObject32(hnewPen
);
368 SelectObject32(hdc
, hOldPen
);
370 if ((wndPtr
->dwStyle
& TVS_HASBUTTONS
) && (wineItem
->cChildren
)) {
372 hRootPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOW) );
373 SelectObject32( hdc, hRootPen );
376 Rectangle32 (hdc
, xpos
-4, center
-4, xpos
+5, center
+5);
377 MoveToEx32 (hdc
, xpos
-2, center
, NULL
);
378 LineTo32 (hdc
, xpos
+3, center
);
379 if (!(wineItem
->state
& TVIS_EXPANDED
)) {
380 MoveToEx32 (hdc
, xpos
, center
-2, NULL
);
381 LineTo32 (hdc
, xpos
, center
+3);
383 /* DeleteObject32(hRootPen); */
389 if (wineItem
->mask
& TVIF_IMAGE
) {
390 if (wineItem
->iImage
!=I_IMAGECALLBACK
) {
391 if (infoPtr
->himlNormal
) {
392 ImageList_Draw (infoPtr
->himlNormal
,wineItem
->iImage
, hdc
,
393 xpos
-2, r
.top
+1, ILD_NORMAL
);
400 if ((wineItem
->mask
& TVIF_TEXT
) && (wineItem
->pszText
)) {
401 if (wineItem
->state
& TVIS_SELECTED
) {
402 oldBkMode
= SetBkMode32(hdc
, OPAQUE
);
403 oldBkColor
= SetBkColor32 (hdc
, GetSysColor32( COLOR_HIGHLIGHT
));
404 SetTextColor32 (hdc
, GetSysColor32(COLOR_HIGHLIGHTTEXT
));
407 oldBkMode
= SetBkMode32(hdc
, TRANSPARENT
);
411 if (infoPtr
->clrText
==-1)
412 SetTextColor32 (hdc
, COLOR_BTNTEXT
);
414 SetTextColor32 (hdc
, infoPtr
->clrText
); /* FIXME: retval */
415 DrawText32A(hdc
, wineItem
->pszText
, lstrlen32A(wineItem
->pszText
),
416 &r
, uTextJustify
|DT_VCENTER
|DT_SINGLELINE
);
417 if (oldBkMode
!= TRANSPARENT
)
418 SetBkMode32(hdc
, oldBkMode
);
419 if (wineItem
->state
& TVIS_SELECTED
)
420 SetBkColor32 (hdc
, oldBkColor
);
423 return wineItem
->rect
.right
;
433 TREEVIEW_GetItemRect (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
435 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
436 TREEVIEW_ITEM
*wineItem
;
440 TRACE (treeview
,"\n");
441 if (infoPtr
==NULL
) return FALSE
;
443 iItem
= (INT32
)lParam
;
444 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
445 if (!wineItem
) return FALSE
;
447 wineItem
=& infoPtr
->items
[ iItem
];
448 if (!wineItem
->visible
) return FALSE
;
450 lpRect
= (LPRECT32
)lParam
;
451 if (lpRect
== NULL
) return FALSE
;
453 if ((INT32
) wParam
) {
454 lpRect
->left
= wineItem
->text
.left
;
455 lpRect
->right
= wineItem
->text
.right
;
456 lpRect
->bottom
= wineItem
->text
.bottom
;
457 lpRect
->top
= wineItem
->text
.top
;
459 lpRect
->left
= wineItem
->rect
.left
;
460 lpRect
->right
= wineItem
->rect
.right
;
461 lpRect
->bottom
= wineItem
->rect
.bottom
;
462 lpRect
->top
= wineItem
->rect
.top
;
471 TREEVIEW_GetVisibleCount (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
474 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
476 TRACE (treeview
,"\n");
478 return (LRESULT
) infoPtr
->uVisibleHeight
/ infoPtr
->uRealItemHeight
;
484 TREEVIEW_SetItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
486 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
487 TREEVIEW_ITEM
*wineItem
;
491 TRACE (treeview
,"\n");
492 tvItem
=(LPTVITEM
) lParam
;
495 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
496 if (!wineItem
) return FALSE
;
498 if (tvItem
->mask
& TVIF_CHILDREN
) {
499 wineItem
->cChildren
=tvItem
->cChildren
;
502 if (tvItem
->mask
& TVIF_IMAGE
) {
503 wineItem
->iImage
=tvItem
->iImage
;
506 if (tvItem
->mask
& TVIF_INTEGRAL
) {
507 /* wineItem->iIntegral=tvItem->iIntegral; */
510 if (tvItem
->mask
& TVIF_PARAM
) {
511 wineItem
->lParam
=tvItem
->lParam
;
514 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
) {
515 wineItem
->iSelectedImage
=tvItem
->iSelectedImage
;
518 if (tvItem
->mask
& TVIF_STATE
) {
519 wineItem
->state
=tvItem
->state
& tvItem
->stateMask
;
522 if (tvItem
->mask
& TVIF_TEXT
) {
523 len
=tvItem
->cchTextMax
;
524 if (len
>wineItem
->cchTextMax
) {
525 HeapFree (GetProcessHeap (), 0, wineItem
->pszText
);
526 wineItem
->pszText
= HeapAlloc (GetProcessHeap (),
527 HEAP_ZERO_MEMORY
, len
+1);
529 lstrcpyn32A (wineItem
->pszText
, tvItem
->pszText
,len
);
540 TREEVIEW_Refresh (WND
*wndPtr
, HDC32 hdc
)
543 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
544 HFONT32 hFont
, hOldFont
;
547 INT32 iItem
, indent
, x
, y
, height
;
548 INT32 viewtop
,viewbottom
,viewleft
,viewright
;
549 TREEVIEW_ITEM
*wineItem
, *prevItem
;
551 TRACE (treeview
,"\n");
553 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
) {
554 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
555 infoPtr
->Timer
&= ~TV_REFRESH_TIMER_SET
;
559 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
560 if ((rect
.left
-rect
.right
==0) || (rect
.top
-rect
.bottom
==0)) return;
562 viewbottom
=infoPtr
->cy
+ rect
.bottom
-rect
.top
;
563 viewleft
=infoPtr
->cx
;
564 viewright
=infoPtr
->cx
+ rect
.right
-rect
.left
;
566 infoPtr
->uVisibleHeight
=viewbottom
- viewtop
;
568 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject32 (DEFAULT_GUI_FONT
);
569 hOldFont
= SelectObject32 (hdc
, hFont
);
571 /* draw background */
572 hbrBk
= GetSysColorBrush32(COLOR_WINDOW
);
573 FillRect32(hdc
, &rect
, hbrBk
);
576 iItem
=infoPtr
->TopRootItem
;
577 infoPtr
->firstVisible
=0;
581 TRACE (treeview
, "[%d %d %d %d]\n",viewtop
,viewbottom
,viewleft
,viewright
);
585 wineItem
= & infoPtr
->items
[iItem
];
587 TRACE (treeview
, "%d %d [%d %d %d %d] (%s)\n",y
,x
,
588 wineItem
->rect
.top
, wineItem
->rect
.bottom
,
589 wineItem
->rect
.left
, wineItem
->rect
.right
,
592 height
=infoPtr
->uRealItemHeight
* wineItem
->iIntegral
;
593 if ((y
>= viewtop
) && (y
<= viewbottom
) &&
594 (x
>= viewleft
) && (x
<= viewright
)) {
595 wineItem
->rect
.top
= y
- infoPtr
->cy
+ rect
.top
;
596 wineItem
->rect
.bottom
= wineItem
->rect
.top
+ height
;
597 wineItem
->rect
.left
= x
- infoPtr
->cx
+ rect
.left
;
598 wineItem
->rect
.right
= rect
.right
;
599 if (!infoPtr
->firstVisible
)
600 infoPtr
->firstVisible
=wineItem
->hItem
;
601 TREEVIEW_DrawItem (wndPtr
, hdc
, wineItem
, prevItem
, indent
);
604 wineItem
->rect
.top
= wineItem
->rect
.bottom
= -1;
605 wineItem
->rect
.left
= wineItem
->rect
.right
= -1;
608 /* look up next item */
610 if ((wineItem
->firstChild
) && (wineItem
->state
& TVIS_EXPANDED
)) {
611 iItem
=wineItem
->firstChild
;
616 iItem
=wineItem
->sibling
;
617 while ((!iItem
) && (indent
>0)) {
621 wineItem
=&infoPtr
->items
[wineItem
->parent
];
622 iItem
=wineItem
->sibling
;
628 infoPtr
->uTotalHeight
=y
;
629 if (y
>= (viewbottom
-viewtop
)) {
630 if (!(infoPtr
->uInternalStatus
& TV_VSCROLL
))
631 ShowScrollBar32 (wndPtr
->hwndSelf
, SB_VERT
, TRUE
);
632 infoPtr
->uInternalStatus
|=TV_VSCROLL
;
633 SetScrollRange32 (wndPtr
->hwndSelf
, SB_VERT
, 0,
634 y
- infoPtr
->uVisibleHeight
, FALSE
);
635 SetScrollPos32 (wndPtr
->hwndSelf
, SB_VERT
, infoPtr
->cy
, TRUE
);
638 if (infoPtr
->uInternalStatus
& TV_VSCROLL
)
639 ShowScrollBar32 (wndPtr
->hwndSelf
, SB_VERT
, FALSE
);
640 infoPtr
->uInternalStatus
&= ~TV_VSCROLL
;
644 SelectObject32 (hdc
, hOldFont
);
649 TREEVIEW_HandleTimer ( WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
651 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
654 if (!infoPtr
) return FALSE
;
656 TRACE (treeview
, "timer\n");
659 case TV_REFRESH_TIMER
:
660 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
661 infoPtr
->Timer
&= ~TV_REFRESH_TIMER_SET
;
662 hdc
=GetDC32 (wndPtr
->hwndSelf
);
663 TREEVIEW_Refresh (wndPtr
, hdc
);
664 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
667 KillTimer32 (wndPtr
->hwndSelf
, TV_EDIT_TIMER
);
668 infoPtr
->Timer
&= ~TV_EDIT_TIMER_SET
;
677 TREEVIEW_QueueRefresh (WND
*wndPtr
)
680 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
682 TRACE (treeview
,"queued\n");
683 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
) {
684 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
687 SetTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
, TV_REFRESH_DELAY
, 0);
688 infoPtr
->Timer
|=TV_REFRESH_TIMER_SET
;
694 TREEVIEW_GetItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
696 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
698 TREEVIEW_ITEM
*wineItem
;
701 TRACE (treeview
,"\n");
702 tvItem
=(LPTVITEM
) lParam
;
705 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
706 if (!wineItem
) return FALSE
;
709 if (tvItem
->mask
& TVIF_CHILDREN
) {
710 tvItem
->cChildren
=wineItem
->cChildren
;
713 if (tvItem
->mask
& TVIF_HANDLE
) {
714 tvItem
->hItem
=wineItem
->hItem
;
717 if (tvItem
->mask
& TVIF_IMAGE
) {
718 tvItem
->iImage
=wineItem
->iImage
;
721 if (tvItem
->mask
& TVIF_INTEGRAL
) {
722 /* tvItem->iIntegral=wineItem->iIntegral; */
725 if (tvItem
->mask
& TVIF_PARAM
) {
726 tvItem
->lParam
=wineItem
->lParam
;
729 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
) {
730 tvItem
->iSelectedImage
=wineItem
->iSelectedImage
;
733 if (tvItem
->mask
& TVIF_STATE
) {
734 tvItem
->state
=wineItem
->state
& tvItem
->stateMask
;
737 if (tvItem
->mask
& TVIF_TEXT
) {
738 len
=wineItem
->cchTextMax
;
739 if (wineItem
->cchTextMax
>tvItem
->cchTextMax
)
740 len
=tvItem
->cchTextMax
-1;
741 lstrcpyn32A (tvItem
->pszText
, tvItem
->pszText
,len
);
750 TREEVIEW_GetNextItem32 (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
753 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
754 TREEVIEW_ITEM
*wineItem
;
758 TRACE (treeview
,"item:%lu, flags:%x\n", lParam
, wParam
);
759 if (!infoPtr
) return FALSE
;
761 flag
= (INT32
) wParam
;
763 case TVGN_ROOT
: return (LRESULT
) infoPtr
->TopRootItem
;
764 case TVGN_CARET
: return (LRESULT
) infoPtr
->selectedItem
;
765 case TVGN_FIRSTVISIBLE
: return (LRESULT
) infoPtr
->firstVisible
;
766 case TVGN_DROPHILITE
: return (LRESULT
) infoPtr
->dropItem
;
769 iItem
= (INT32
) lParam
;
770 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
771 if (!wineItem
) return FALSE
;
774 case TVGN_NEXT
: return (LRESULT
) wineItem
->sibling
;
775 case TVGN_PREVIOUS
: return (LRESULT
) wineItem
->upsibling
;
776 case TVGN_PARENT
: return (LRESULT
) wineItem
->parent
;
777 case TVGN_CHILD
: return (LRESULT
) wineItem
->firstChild
;
778 case TVGN_LASTVISIBLE
: FIXME (treeview
,"TVGN_LASTVISIBLE not implemented\n");
780 case TVGN_NEXTVISIBLE
: wineItem
=TREEVIEW_GetNextListItem
783 return (LRESULT
) wineItem
->hItem
;
786 case TVGN_PREVIOUSVISIBLE
: wineItem
=TREEVIEW_GetPrevListItem
789 return (LRESULT
) wineItem
->hItem
;
792 default: FIXME (treeview
,"Unknown msg %x,item %x\n", flag
,iItem
);
800 TREEVIEW_GetCount (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
802 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
804 return (LRESULT
) infoPtr
->uNumItems
;
810 /* the method used below isn't the most memory-friendly, but it avoids
811 a lot of memory reallocations */
813 /* BTW: we waste handle 0; 0 is not an allowed handle. Fix this by
814 decreasing infoptr->items with 1, and increasing it by 1 if
815 it is referenced in mm-handling stuff? */
818 TREEVIEW_InsertItem32A (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
821 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
822 TVINSERTSTRUCT
*ptdi
;
824 TREEVIEW_ITEM
*wineItem
, *parentItem
, *prevsib
, *sibItem
;
825 INT32 iItem
,listItems
,i
,len
;
827 TRACE (treeview
,"\n");
828 ptdi
= (TVINSERTSTRUCT
*) lParam
;
830 /* check if memory is available */
832 if (infoPtr
->uNumPtrsAlloced
==0) {
833 infoPtr
->items
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
834 TVITEM_ALLOC
*sizeof (TREEVIEW_ITEM
));
835 infoPtr
->freeList
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
836 (1+(TVITEM_ALLOC
>>5)) *sizeof (INT32
));
837 infoPtr
->uNumPtrsAlloced
=TVITEM_ALLOC
;
838 infoPtr
->TopRootItem
=1;
841 if (infoPtr
->uNumItems
== (infoPtr
->uNumPtrsAlloced
-1) ) {
842 TREEVIEW_ITEM
*oldItems
= infoPtr
->items
;
843 INT32
*oldfreeList
= infoPtr
->freeList
;
845 infoPtr
->uNumPtrsAlloced
*=2;
846 infoPtr
->items
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
847 infoPtr
->uNumPtrsAlloced
*sizeof (TREEVIEW_ITEM
));
848 infoPtr
->freeList
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
849 (1+(infoPtr
->uNumPtrsAlloced
>>5))*sizeof (INT32
));
851 memcpy (&infoPtr
->items
[0], &oldItems
[0],
852 infoPtr
->uNumPtrsAlloced
/2 * sizeof(TREEVIEW_ITEM
));
853 memcpy (&infoPtr
->freeList
[0], &oldfreeList
[0],
854 infoPtr
->uNumPtrsAlloced
>>6 * sizeof(INT32
));
856 HeapFree (GetProcessHeap (), 0, oldItems
);
857 HeapFree (GetProcessHeap (), 0, oldfreeList
);
861 infoPtr
->uNumItems
++;
863 if (infoPtr
->uMaxHandle
==(infoPtr
->uNumItems
-1)) {
864 iItem
=infoPtr
->uNumItems
;
865 infoPtr
->uMaxHandle
++;
867 else { /* check freelist */
868 for (i
=0; i
<infoPtr
->uNumPtrsAlloced
>>5; i
++) {
869 if (infoPtr
->freeList
[i
]) {
870 iItem
=ffs (infoPtr
->freeList
[i
]);
871 clear_bit (iItem
& 31, & infoPtr
->freeList
[i
]);
876 if (!iItem
) ERR (treeview
, "Argh -- can't find free item.\n");
878 tvItem
= & ptdi
->item
;
879 wineItem
=& infoPtr
->items
[iItem
];
883 if ((ptdi
->hParent
==TVI_ROOT
) || (ptdi
->hParent
==0)) {
886 sibItem
=&infoPtr
->items
[infoPtr
->TopRootItem
];
887 listItems
=infoPtr
->uNumItems
;
890 parentItem
= &infoPtr
->items
[ptdi
->hParent
];
891 if (!parentItem
->firstChild
)
892 parentItem
->firstChild
=iItem
;
893 wineItem
->parent
=ptdi
->hParent
;
894 sibItem
=&infoPtr
->items
[parentItem
->firstChild
];
895 parentItem
->cChildren
++;
896 listItems
=parentItem
->cChildren
;
899 wineItem
->upsibling
=0; /* needed in case we're the first item in a list */
901 wineItem
->firstChild
=0;
905 switch (ptdi
->hInsertAfter
) {
906 case TVI_FIRST
: wineItem
->sibling
=infoPtr
->TopRootItem
;
907 infoPtr
->TopRootItem
=iItem
;
910 while (sibItem
->sibling
) {
912 sibItem
=&infoPtr
->items
[sibItem
->sibling
];
914 sibItem
->sibling
=iItem
;
916 wineItem
->upsibling
=prevsib
->hItem
;
918 wineItem
->sibling
=0; /* terminate list */
921 FIXME (treeview
, "Sorted insert not implemented yet\n");
924 while ((sibItem
->sibling
) && (sibItem
->sibling
!=iItem
)) {
926 sibItem
=&infoPtr
->items
[sibItem
->sibling
];
928 if (sibItem
->sibling
)
929 WARN (treeview
, "Buggy program tried to insert item after nonexisting handle.");
930 sibItem
->upsibling
=iItem
;
931 wineItem
->sibling
=sibItem
->hItem
;
933 wineItem
->upsibling
=prevsib
->hItem
;
939 /* Fill in info structure */
941 wineItem
->mask
=tvItem
->mask
;
942 wineItem
->hItem
=iItem
;
943 wineItem
->iIntegral
=1;
945 if (tvItem
->mask
& TVIF_CHILDREN
)
946 wineItem
->cChildren
=tvItem
->cChildren
;
948 if (tvItem
->mask
& TVIF_IMAGE
)
949 wineItem
->iImage
=tvItem
->iImage
;
951 /* if (tvItem->mask & TVIF_INTEGRAL)
952 wineItem->iIntegral=tvItem->iIntegral; */
955 if (tvItem
->mask
& TVIF_PARAM
)
956 wineItem
->lParam
=tvItem
->lParam
;
958 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
)
959 wineItem
->iSelectedImage
=tvItem
->iSelectedImage
;
961 if (tvItem
->mask
& TVIF_STATE
) {
962 wineItem
->state
=tvItem
->state
;
963 wineItem
->stateMask
=tvItem
->stateMask
;
966 if (tvItem
->mask
& TVIF_TEXT
) {
967 TRACE (treeview
,"(%s)\n", tvItem
->pszText
);
968 if (tvItem
->pszText
!=LPSTR_TEXTCALLBACK32A
) {
969 len
= lstrlen32A (tvItem
->pszText
)+1;
971 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, len
+1);
972 lstrcpy32A (wineItem
->pszText
, tvItem
->pszText
);
973 wineItem
->cchTextMax
=len
;
977 TREEVIEW_QueueRefresh (wndPtr
);
979 return (LRESULT
) iItem
;
985 TREEVIEW_DeleteItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
987 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
990 TREEVIEW_ITEM
*wineItem
;
992 TRACE (treeview
,"\n");
993 if (!infoPtr
) return FALSE
;
995 if ((INT32
) lParam
== TVI_ROOT
) {
996 TREEVIEW_RemoveTree (infoPtr
);
998 iItem
= (INT32
) lParam
;
999 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
1000 if (!wineItem
) return FALSE
;
1001 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_DELETEITEM
, 0, iItem
, 0, pt
);
1002 TREEVIEW_RemoveItem (infoPtr
, wineItem
);
1005 TREEVIEW_QueueRefresh (wndPtr
);
1012 TREEVIEW_GetIndent (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1014 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1016 return infoPtr
->uIndent
;
1020 TREEVIEW_SetIndent (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1022 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1025 newIndent
=(INT32
) wParam
;
1026 if (newIndent
< MINIMUM_INDENT
) newIndent
=MINIMUM_INDENT
;
1027 infoPtr
->uIndent
=newIndent
;
1037 TREEVIEW_Create (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1039 TREEVIEW_INFO
*infoPtr
;
1043 TRACE (treeview
,"\n");
1044 /* allocate memory for info structure */
1045 infoPtr
= (TREEVIEW_INFO
*)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
1046 sizeof(TREEVIEW_INFO
));
1048 wndPtr
->wExtra
[0] = (DWORD
)infoPtr
;
1050 if (infoPtr
== NULL
) {
1051 ERR (treeview
, "could not allocate info memory!\n");
1055 if ((TREEVIEW_INFO
*)wndPtr
->wExtra
[0] != infoPtr
) {
1056 ERR (treeview
, "pointer assignment error!\n");
1060 hdc
=GetDC32 (wndPtr
->hwndSelf
);
1062 /* set default settings */
1063 infoPtr
->uInternalStatus
=0;
1064 infoPtr
->uNumItems
=0;
1065 infoPtr
->clrBk
= GetSysColor32 (COLOR_WINDOW
);
1066 infoPtr
->clrText
= GetSysColor32 (COLOR_BTNTEXT
);
1069 infoPtr
->uIndent
= 15;
1070 infoPtr
->himlNormal
= NULL
;
1071 infoPtr
->himlState
= NULL
;
1072 infoPtr
->uItemHeight
= -1;
1073 GetTextMetrics32A (hdc
, &tm
);
1074 infoPtr
->uRealItemHeight
= tm
.tmHeight
+ tm
.tmExternalLeading
;
1076 infoPtr
->items
= NULL
;
1077 infoPtr
->selectedItem
=0;
1078 infoPtr
->clrText
=-1; /* use system color */
1079 infoPtr
->dropItem
=0;
1082 infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
1083 infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
1086 if (wndPtr
->dwStyle
& TBSTYLE_TOOLTIPS
) {
1087 /* Create tooltip control */
1088 // infoPtr->hwndToolTip = CreateWindowEx32A (....);
1090 /* Send TV_TOOLTIPSCREATED notification */
1093 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1101 TREEVIEW_Destroy (WND
*wndPtr
)
1103 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1105 TREEVIEW_RemoveTree (infoPtr
);
1106 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
)
1107 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
1109 HeapFree (GetProcessHeap (), 0, infoPtr
);
1116 TREEVIEW_Paint (WND
*wndPtr
, WPARAM32 wParam
)
1121 hdc
= wParam
==0 ? BeginPaint32 (wndPtr
->hwndSelf
, &ps
) : (HDC32
)wParam
;
1122 TREEVIEW_QueueRefresh (wndPtr
);
1124 EndPaint32 (wndPtr
->hwndSelf
, &ps
);
1131 TREEVIEW_EraseBackground (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1133 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1134 HBRUSH32 hBrush
= CreateSolidBrush32 (infoPtr
->clrBk
);
1137 TRACE (treeview
,"\n");
1138 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
1139 FillRect32 ((HDC32
)wParam
, &rect
, hBrush
);
1140 DeleteObject32 (hBrush
);
1153 TREEVIEW_SendSimpleNotify (WND
*wndPtr
, UINT32 code
)
1157 TRACE (treeview
, "%x\n",code
);
1158 nmhdr
.hwndFrom
= wndPtr
->hwndSelf
;
1159 nmhdr
.idFrom
= wndPtr
->wIDmenu
;
1162 return (BOOL32
) SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
1163 (WPARAM32
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1170 TREEVIEW_SendTreeviewNotify (WND
*wndPtr
, UINT32 code
, UINT32 action
,
1171 INT32 oldItem
, INT32 newItem
, POINT32 pt
)
1173 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1175 TREEVIEW_ITEM
*wineItem
;
1177 TRACE (treeview
,"code:%x action:%x olditem:%x newitem:%x\n",
1178 code
,action
,oldItem
,newItem
);
1179 nmhdr
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
1180 nmhdr
.hdr
.idFrom
= wndPtr
->wIDmenu
;
1181 nmhdr
.hdr
.code
= code
;
1182 nmhdr
.action
= action
;
1184 wineItem
=& infoPtr
->items
[oldItem
];
1185 nmhdr
.itemOld
.mask
= wineItem
->mask
;
1186 nmhdr
.itemOld
.hItem
= wineItem
->hItem
;
1187 nmhdr
.itemOld
.state
= wineItem
->state
;
1188 nmhdr
.itemOld
.stateMask
= wineItem
->stateMask
;
1189 nmhdr
.itemOld
.iImage
= wineItem
->iImage
;
1190 nmhdr
.itemOld
.pszText
= wineItem
->pszText
;
1191 nmhdr
.itemOld
.cchTextMax
= wineItem
->cchTextMax
;
1192 nmhdr
.itemOld
.iImage
= wineItem
->iImage
;
1193 nmhdr
.itemOld
.iSelectedImage
= wineItem
->iSelectedImage
;
1194 nmhdr
.itemOld
.cChildren
= wineItem
->cChildren
;
1195 nmhdr
.itemOld
.lParam
= wineItem
->lParam
;
1199 wineItem
=& infoPtr
->items
[newItem
];
1200 nmhdr
.itemNew
.mask
= wineItem
->mask
;
1201 nmhdr
.itemNew
.hItem
= wineItem
->hItem
;
1202 nmhdr
.itemNew
.state
= wineItem
->state
;
1203 nmhdr
.itemNew
.stateMask
= wineItem
->stateMask
;
1204 nmhdr
.itemNew
.iImage
= wineItem
->iImage
;
1205 nmhdr
.itemNew
.pszText
= wineItem
->pszText
;
1206 nmhdr
.itemNew
.cchTextMax
= wineItem
->cchTextMax
;
1207 nmhdr
.itemNew
.iImage
= wineItem
->iImage
;
1208 nmhdr
.itemNew
.iSelectedImage
= wineItem
->iSelectedImage
;
1209 nmhdr
.itemNew
.cChildren
= wineItem
->cChildren
;
1210 nmhdr
.itemNew
.lParam
= wineItem
->lParam
;
1213 nmhdr
.ptDrag
.x
= pt
.x
;
1214 nmhdr
.ptDrag
.y
= pt
.y
;
1216 return (BOOL32
)SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
1217 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&nmhdr
);
1225 TREEVIEW_Expand (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1227 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1228 TREEVIEW_ITEM
*wineItem
;
1233 flag
= (UINT32
) wParam
;
1234 expandItem
= (INT32
) lParam
;
1235 TRACE (treeview
,"flags:%x item:%x\n", expandItem
, wParam
);
1236 wineItem
= TREEVIEW_ValidItem (infoPtr
, expandItem
);
1237 if (!wineItem
) return 0;
1238 if (!wineItem
->cChildren
) return 0;
1240 if (flag
& TVE_TOGGLE
) { /* FIXME: check exact behaviour here */
1241 flag
&= ~TVE_TOGGLE
; /* ie: bitwise ops or 'case' ops */
1242 if (wineItem
->state
& TVIS_EXPANDED
)
1243 flag
|= TVE_COLLAPSE
;
1249 case TVE_COLLAPSERESET
:
1250 if (!wineItem
->state
& TVIS_EXPANDED
) return 0;
1251 wineItem
->state
&= ~(TVIS_EXPANDEDONCE
| TVIS_EXPANDED
);
1252 TREEVIEW_RemoveAllChildren (infoPtr
, wineItem
);
1256 if (!wineItem
->state
& TVIS_EXPANDED
) return 0;
1257 wineItem
->state
&= ~TVIS_EXPANDED
;
1261 if (wineItem
->state
& TVIS_EXPANDED
) return 0;
1262 if (!(wineItem
->state
& TVIS_EXPANDEDONCE
)) {
1263 if (TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_ITEMEXPANDING
,
1264 0, 0, expandItem
, pt
))
1265 return FALSE
; /* FIXME: OK? */
1266 wineItem
->state
|= TVIS_EXPANDED
| TVIS_EXPANDEDONCE
;
1267 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_ITEMEXPANDED
,
1268 0, 0, expandItem
, pt
);
1270 wineItem
->state
|= TVIS_EXPANDED
;
1272 case TVE_EXPANDPARTIAL
:
1273 FIXME (treeview
, "TVE_EXPANDPARTIAL not implemented\n");
1274 wineItem
->state
^=TVIS_EXPANDED
;
1275 wineItem
->state
|=TVIS_EXPANDEDONCE
;
1279 TREEVIEW_QueueRefresh (wndPtr
);
1287 TREEVIEW_HitTest (WND
*wndPtr
, LPTVHITTESTINFO lpht
)
1289 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1290 TREEVIEW_ITEM
*wineItem
;
1296 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
1297 TRACE (treeview
,"(%d,%d)\n",lpht
->pt
.x
, lpht
->pt
.y
);
1302 if (x
< rect
.left
) status
|=TVHT_TOLEFT
;
1303 if (x
> rect
.right
) status
|=TVHT_TORIGHT
;
1304 if (y
< rect
.top
) status
|=TVHT_ABOVE
;
1305 if (y
> rect
.bottom
) status
|=TVHT_BELOW
;
1311 if (!infoPtr
->firstVisible
) WARN (treeview
,"Can't fetch first visible item");
1312 wineItem
=&infoPtr
->items
[infoPtr
->firstVisible
];
1314 while ((wineItem
!=NULL
) && (y
> wineItem
->rect
.bottom
))
1315 wineItem
=TREEVIEW_GetNextListItem (infoPtr
,wineItem
);
1317 if (wineItem
==NULL
) {
1318 lpht
->flags
=TVHT_NOWHERE
;
1322 if (x
>wineItem
->rect
.right
) {
1323 lpht
->flags
|=TVHT_ONITEMRIGHT
;
1324 return wineItem
->hItem
;
1328 if (x
<wineItem
->rect
.left
+10) lpht
->flags
|=TVHT_ONITEMBUTTON
;
1330 lpht
->flags
=TVHT_ONITEMLABEL
; /* FIXME: implement other flags */
1333 lpht
->hItem
=wineItem
->hItem
;
1334 return wineItem
->hItem
;
1339 TREEVIEW_HitTest32 (WND
*wndPtr
, LPARAM lParam
)
1342 return (LRESULT
) TREEVIEW_HitTest (wndPtr
, (LPTVHITTESTINFO
) lParam
);
1349 TREEVIEW_LButtonDoubleClick (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1351 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1352 TREEVIEW_ITEM
*wineItem
;
1356 TRACE (treeview
,"\n");
1357 ht
.pt
.x
= (INT32
)LOWORD(lParam
);
1358 ht
.pt
.y
= (INT32
)HIWORD(lParam
);
1359 SetFocus32 (wndPtr
->hwndSelf
);
1361 iItem
=TREEVIEW_HitTest (wndPtr
, &ht
);
1362 TRACE (treeview
,"item %d \n",iItem
);
1363 wineItem
=TREEVIEW_ValidItem (infoPtr
, iItem
);
1364 if (!wineItem
) return 0;
1366 if (TREEVIEW_SendSimpleNotify (wndPtr
, NM_DBLCLK
)!=TRUE
) { /* FIXME!*/
1367 wineItem
->state
&= ~TVIS_EXPANDEDONCE
;
1368 TREEVIEW_Expand (wndPtr
, (WPARAM32
) TVE_TOGGLE
, (LPARAM
) iItem
);
1376 TREEVIEW_LButtonDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1381 TRACE (treeview
,"\n");
1382 ht
.pt
.x
= (INT32
)LOWORD(lParam
);
1383 ht
.pt
.y
= (INT32
)HIWORD(lParam
);
1385 SetFocus32 (wndPtr
->hwndSelf
);
1386 iItem
=TREEVIEW_HitTest (wndPtr
, &ht
);
1387 TRACE (treeview
,"item %d \n",iItem
);
1388 if (ht
.flags
& TVHT_ONITEMBUTTON
) {
1389 TREEVIEW_Expand (wndPtr
, (WPARAM32
) TVE_TOGGLE
, (LPARAM
) iItem
);
1392 if (TREEVIEW_SelectItem (wndPtr
, (WPARAM32
) TVGN_CARET
, (LPARAM
) iItem
))
1401 TREEVIEW_RButtonDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1410 /* FIXME: If the specified item is the child of a collapsed parent item,
1411 expand parent's list of child items to reveal the specified item.
1415 TREEVIEW_SelectItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1417 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1418 TREEVIEW_ITEM
*prevItem
,*wineItem
;
1419 INT32 action
,prevSelect
, newSelect
;
1422 TRACE (treeview
,"item %lx, flag %x\n", lParam
, wParam
);
1423 newSelect
= (INT32
) lParam
;
1424 wineItem
= TREEVIEW_ValidItem (infoPtr
, newSelect
);
1425 if (!wineItem
) return FALSE
;
1426 prevSelect
=infoPtr
->selectedItem
;
1427 prevItem
= TREEVIEW_ValidItem (infoPtr
, prevSelect
);
1431 action
= (INT32
) wParam
;
1435 if (TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_SELCHANGING
, TVC_BYMOUSE
,
1436 prevSelect
, newSelect
,dummy
))
1437 return FALSE
; /* FIXME: OK? */
1439 if (prevItem
) prevItem
->state
&= ~TVIS_SELECTED
;
1440 infoPtr
->selectedItem
=newSelect
;
1441 wineItem
->state
|=TVIS_SELECTED
;
1442 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_SELCHANGED
,
1443 TVC_BYMOUSE
, prevSelect
, newSelect
, dummy
);
1445 case TVGN_DROPHILITE
:
1446 FIXME (treeview
, "DROPHILITE not implemented");
1448 case TVGN_FIRSTVISIBLE
:
1449 FIXME (treeview
, "FIRSTVISIBLE not implemented");
1453 TREEVIEW_QueueRefresh (wndPtr
);
1460 /* FIXME: does KEYDOWN also send notifications?? If so, use
1461 TREEVIEW_SelectItem.
1466 TREEVIEW_KeyDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1468 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1469 TREEVIEW_ITEM
*prevItem
,*newItem
;
1473 TRACE (treeview
,"%x %lx",wParam
, lParam
);
1474 prevSelect
=infoPtr
->selectedItem
;
1475 if (!prevSelect
) return FALSE
;
1477 prevItem
= TREEVIEW_ValidItem (infoPtr
, prevSelect
);
1482 newItem
=TREEVIEW_GetPrevListItem (infoPtr
, prevItem
);
1484 newItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
1487 newItem
=TREEVIEW_GetNextListItem (infoPtr
, prevItem
);
1488 if (!newItem
) newItem
=prevItem
;
1491 newItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
1494 newItem
=TREEVIEW_GetLastListItem (infoPtr
);
1500 FIXME (treeview
, "%x not implemented\n", wParam
);
1504 if (!newItem
) return FALSE
;
1506 if (prevItem
!=newItem
) {
1507 prevItem
->state
&= ~TVIS_SELECTED
;
1508 newItem
->state
|= TVIS_SELECTED
;
1509 infoPtr
->selectedItem
=newItem
->hItem
;
1510 TREEVIEW_QueueRefresh (wndPtr
);
1520 TREEVIEW_VScroll (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1523 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1526 TRACE (treeview
,"wp %x, lp %lx\n", wParam
, lParam
);
1527 if (!infoPtr
->uInternalStatus
& TV_VSCROLL
) return FALSE
;
1529 switch (LOWORD (wParam
)) {
1531 if (!infoPtr
->cy
) return FALSE
;
1532 infoPtr
->cy
-= infoPtr
->uRealItemHeight
;
1533 if (infoPtr
->cy
< 0) infoPtr
->cy
=0;
1536 maxHeight
=infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
1537 if (infoPtr
->cy
== maxHeight
) return FALSE
;
1538 infoPtr
->cy
+= infoPtr
->uRealItemHeight
;
1539 if (infoPtr
->cy
> maxHeight
)
1540 infoPtr
->cy
= maxHeight
;
1543 if (!infoPtr
->cy
) return FALSE
;
1544 infoPtr
->cy
-= infoPtr
->uVisibleHeight
;
1545 if (infoPtr
->cy
< 0) infoPtr
->cy
=0;
1548 maxHeight
=infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
1549 if (infoPtr
->cy
== maxHeight
) return FALSE
;
1550 infoPtr
->cy
+= infoPtr
->uVisibleHeight
;
1551 if (infoPtr
->cy
> maxHeight
)
1552 infoPtr
->cy
= maxHeight
;
1555 infoPtr
->cy
= HIWORD (wParam
);
1560 TREEVIEW_QueueRefresh (wndPtr
);
1565 TREEVIEW_HScroll (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1567 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1569 TRACE (treeview
,"wp %lx, lp %x\n", lParam
, wParam
);
1571 if (!infoPtr
->uInternalStatus
& TV_HSCROLL
) return FALSE
;
1579 TREEVIEW_WindowProc (HWND32 hwnd
, UINT32 uMsg
, WPARAM32 wParam
, LPARAM lParam
)
1581 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1585 case TVM_INSERTITEM32A
:
1586 return TREEVIEW_InsertItem32A (wndPtr
, wParam
, lParam
);
1588 case TVM_INSERTITEM32W
:
1589 FIXME (treeview
, "Unimplemented msg TVM_INSERTITEM32W\n");
1592 case TVM_DELETEITEM
:
1593 return TREEVIEW_DeleteItem (wndPtr
, wParam
, lParam
);
1596 return TREEVIEW_Expand (wndPtr
, wParam
, lParam
);
1598 case TVM_GETITEMRECT
:
1599 return TREEVIEW_GetItemRect (wndPtr
, wParam
, lParam
);
1602 return TREEVIEW_GetCount (wndPtr
, wParam
, lParam
);
1605 return TREEVIEW_GetIndent (wndPtr
, wParam
, lParam
);
1608 return TREEVIEW_SetIndent (wndPtr
, wParam
, lParam
);
1610 case TVM_GETIMAGELIST
:
1611 return TREEVIEW_GetImageList (wndPtr
, wParam
, lParam
);
1613 case TVM_SETIMAGELIST
:
1614 return TREEVIEW_SetImageList (wndPtr
, wParam
, lParam
);
1616 case TVM_GETNEXTITEM
:
1617 return TREEVIEW_GetNextItem32 (wndPtr
, wParam
, lParam
);
1619 case TVM_SELECTITEM
:
1620 return TREEVIEW_SelectItem (wndPtr
, wParam
, lParam
);
1622 case TVM_GETITEM32A
:
1623 return TREEVIEW_GetItem (wndPtr
, wParam
, lParam
);
1625 case TVM_GETITEM32W
:
1626 FIXME (treeview
, "Unimplemented msg TVM_GETITEM32W\n");
1629 case TVM_SETITEM32A
:
1630 return TREEVIEW_SetItem (wndPtr
, wParam
, lParam
);
1632 case TVM_SETITEM32W
:
1633 FIXME (treeview
, "Unimplemented msg TVM_SETITEMW\n");
1636 case TVM_EDITLABEL32A
:
1637 FIXME (treeview
, "Unimplemented msg TVM_EDITLABEL32A \n");
1640 case TVM_EDITLABEL32W
:
1641 FIXME (treeview
, "Unimplemented msg TVM_EDITLABEL32W \n");
1644 case TVM_GETEDITCONTROL
:
1645 FIXME (treeview
, "Unimplemented msg TVM_GETEDITCONTROL\n");
1648 case TVM_GETVISIBLECOUNT
:
1649 return TREEVIEW_GetVisibleCount (wndPtr
, wParam
, lParam
);
1652 return TREEVIEW_HitTest32 (wndPtr
, lParam
);
1654 case TVM_CREATEDRAGIMAGE
:
1655 FIXME (treeview
, "Unimplemented msg TVM_CREATEDRAGIMAGE\n");
1658 case TVM_SORTCHILDREN
:
1659 FIXME (treeview
, "Unimplemented msg TVM_SORTCHILDREN\n");
1662 case TVM_ENSUREVISIBLE
:
1663 FIXME (treeview
, "Unimplemented msg TVM_ENSUREVISIBLE\n");
1666 case TVM_SORTCHILDRENCB
:
1667 FIXME (treeview
, "Unimplemented msg TVM_SORTCHILDRENCB\n");
1670 case TVM_ENDEDITLABELNOW
:
1671 FIXME (treeview
, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
1674 case TVM_GETISEARCHSTRING32A
:
1675 FIXME (treeview
, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
1678 case TVM_GETISEARCHSTRING32W
:
1679 FIXME (treeview
, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
1682 case TVM_SETTOOLTIPS
:
1683 FIXME (treeview
, "Unimplemented msg TVM_SETTOOLTIPS\n");
1686 case TVM_GETTOOLTIPS
:
1687 FIXME (treeview
, "Unimplemented msg TVM_GETTOOLTIPS\n");
1690 case TVM_SETINSERTMARK
:
1691 FIXME (treeview
, "Unimplemented msg TVM_SETINSERTMARK\n");
1694 case TVM_SETITEMHEIGHT
:
1695 return TREEVIEW_SetItemHeight (wndPtr
, wParam
);
1697 case TVM_GETITEMHEIGHT
:
1698 return TREEVIEW_GetItemHeight (wndPtr
);
1700 case TVM_SETBKCOLOR
:
1701 FIXME (treeview
, "Unimplemented msg TVM_SETBKCOLOR\n");
1704 case TVM_SETTEXTCOLOR
:
1705 return TREEVIEW_SetTextColor (wndPtr
, wParam
, lParam
);
1707 case TVM_GETBKCOLOR
:
1708 FIXME (treeview
, "Unimplemented msg TVM_GETBKCOLOR\n");
1711 case TVM_GETTEXTCOLOR
:
1712 return TREEVIEW_GetTextColor (wndPtr
);
1714 case TVM_SETSCROLLTIME
:
1715 FIXME (treeview
, "Unimplemented msg TVM_SETSCROLLTIME\n");
1718 case TVM_GETSCROLLTIME
:
1719 FIXME (treeview
, "Unimplemented msg TVM_GETSCROLLTIME\n");
1722 case TVM_SETINSERTMARKCOLOR
:
1723 FIXME (treeview
, "Unimplemented msg TVM_SETINSERTMARKCOLOR\n");
1726 case TVM_SETUNICODEFORMAT
:
1727 FIXME (treeview
, "Unimplemented msg TVM_SETUNICODEFORMAT\n");
1730 case TVM_GETUNICODEFORMAT
:
1731 FIXME (treeview
, "Unimplemented msg TVM_GETUNICODEFORMAT\n");
1737 return TREEVIEW_Create (wndPtr
, wParam
, lParam
);
1740 return TREEVIEW_Destroy (wndPtr
);
1745 return TREEVIEW_EraseBackground (wndPtr
, wParam
, lParam
);
1748 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
1751 return TREEVIEW_Paint (wndPtr
, wParam
);
1757 return TREEVIEW_KeyDown (wndPtr
, wParam
, lParam
);
1760 // case WM_KILLFOCUS:
1761 // case WM_SETFOCUS:
1764 case WM_LBUTTONDOWN
:
1765 return TREEVIEW_LButtonDown (wndPtr
, wParam
, lParam
);
1767 case WM_LBUTTONDBLCLK
:
1768 return TREEVIEW_LButtonDoubleClick (wndPtr
, wParam
, lParam
);
1770 case WM_RBUTTONDOWN
:
1771 return TREEVIEW_RButtonDown (wndPtr
, wParam
, lParam
);
1774 // case WM_SYSCOLORCHANGE:
1775 // case WM_STYLECHANGED:
1776 // case WM_SETREDRAW:
1779 return TREEVIEW_HandleTimer (wndPtr
, wParam
, lParam
);
1783 return TREEVIEW_HScroll (wndPtr
, wParam
, lParam
);
1785 return TREEVIEW_VScroll (wndPtr
, wParam
, lParam
);
1788 if (uMsg
>= WM_USER
)
1789 FIXME (treeview
, "Unknown msg %04x wp=%08x lp=%08lx\n",
1790 uMsg
, wParam
, lParam
);
1791 return DefWindowProc32A (hwnd
, uMsg
, wParam
, lParam
);
1798 TREEVIEW_Register (void)
1800 WNDCLASS32A wndClass
;
1802 TRACE (treeview
,"\n");
1804 if (GlobalFindAtom32A (WC_TREEVIEW32A
)) return;
1806 ZeroMemory (&wndClass
, sizeof(WNDCLASS32A
));
1807 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1808 wndClass
.lpfnWndProc
= (WNDPROC32
)TREEVIEW_WindowProc
;
1809 wndClass
.cbClsExtra
= 0;
1810 wndClass
.cbWndExtra
= sizeof(TREEVIEW_INFO
*);
1811 wndClass
.hCursor
= LoadCursor32A (0, IDC_ARROW32A
);
1812 wndClass
.hbrBackground
= 0;
1813 wndClass
.lpszClassName
= WC_TREEVIEW32A
;
1815 RegisterClass32A (&wndClass
);