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 flags for traversing child lists.
24 (DESCEND_ALWAYS, DESCEND_NEVER, DESCEND_VISIBLE)
25 -DblClick: ctlmacro.exe's NM_DBLCLK seems to go wrong (returns FALSE).
37 /* ffs should be in <string.h>. */
39 /* Defines, since they do not need to return previous state, and nr
40 * has no side effects in this file.
42 #define tv_test_bit(nr,bf) (((LPBYTE)bf)[nr>>3]&(1<<(nr&7)))
43 #define tv_set_bit(nr,bf) ((LPBYTE)bf)[nr>>3]|=(1<<(nr&7))
44 #define tv_clear_bit(nr,bf) ((LPBYTE)bf)[nr>>3]&=~(1<<(nr&7))
47 #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
50 TREEVIEW_SendSimpleNotify (WND
*wndPtr
, UINT32 code
);
52 TREEVIEW_SendTreeviewNotify (WND
*wndPtr
, UINT32 code
, UINT32 action
,
53 INT32 oldItem
, INT32 newItem
, POINT32 pt
);
55 TREEVIEW_SelectItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
);
57 TREEVIEW_Refresh (WND
*wndPtr
);
63 /* helper functions. Work with the assumption that validity of operands
64 is checked beforehand */
66 /* FIXME: MS documentation says `GetNextVisibleItem' returns NULL
67 if not succesfull'. Probably means derefencing, and not whether
68 there is a next `visible' child. */
71 static TREEVIEW_ITEM
*
72 TREEVIEW_ValidItem (TREEVIEW_INFO
*infoPtr
,int handle
)
75 if ((!handle
) || (handle
>infoPtr
->uMaxHandle
)) return NULL
;
76 if (tv_test_bit (handle
, infoPtr
->freeList
)) return NULL
;
78 return & infoPtr
->items
[handle
];
83 static TREEVIEW_ITEM
*TREEVIEW_GetPrevListItem (TREEVIEW_INFO
*infoPtr
,
84 TREEVIEW_ITEM
*tvItem
)
87 TREEVIEW_ITEM
*wineItem
;
89 if (tvItem
->upsibling
) {
90 wineItem
=& infoPtr
->items
[tvItem
->upsibling
];
91 if ((wineItem
->firstChild
) && (wineItem
->state
& TVIS_EXPANDED
)) {
92 wineItem
=& infoPtr
->items
[wineItem
->firstChild
];
93 while (wineItem
->sibling
)
94 wineItem
= & infoPtr
->items
[wineItem
->sibling
];
100 while (wineItem
->parent
) {
101 wineItem
=& infoPtr
->items
[wineItem
->parent
];
102 if (wineItem
->upsibling
)
103 return (& infoPtr
->items
[wineItem
->upsibling
]);
110 static TREEVIEW_ITEM
*TREEVIEW_GetNextListItem (TREEVIEW_INFO
*infoPtr
,
111 TREEVIEW_ITEM
*tvItem
)
114 TREEVIEW_ITEM
*wineItem
;
116 if ((tvItem
->firstChild
) && (tvItem
->state
& TVIS_EXPANDED
))
117 return (& infoPtr
->items
[tvItem
->firstChild
]);
120 return (& infoPtr
->items
[tvItem
->sibling
]);
123 while (wineItem
->parent
) {
124 wineItem
=& infoPtr
->items
[wineItem
->parent
];
125 if (wineItem
->sibling
)
126 return (& infoPtr
->items
[wineItem
->sibling
]);
132 static TREEVIEW_ITEM
*TREEVIEW_GetLastListItem (TREEVIEW_INFO
*infoPtr
)
135 TREEVIEW_ITEM
*wineItem
;
138 if (infoPtr
->TopRootItem
)
139 wineItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
140 while (wineItem
->sibling
)
141 wineItem
=& infoPtr
->items
[wineItem
->sibling
];
150 TREEVIEW_RemoveItem (TREEVIEW_INFO
*infoPtr
, TREEVIEW_ITEM
*wineItem
)
153 TREEVIEW_ITEM
*parentItem
, *upsiblingItem
, *siblingItem
;
156 iItem
=wineItem
->hItem
;
157 tv_set_bit(iItem
,infoPtr
->freeList
);
158 infoPtr
->uNumItems
--;
160 if (wineItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
161 COMCTL32_Free (wineItem
->pszText
);
163 if (wineItem
->parent
) {
164 parentItem
=& infoPtr
->items
[ wineItem
->parent
];
165 if (parentItem
->cChildren
==1) {
166 parentItem
->cChildren
=0;
167 parentItem
->firstChild
=0;
170 parentItem
->cChildren
--;
171 if (parentItem
->firstChild
==iItem
)
172 parentItem
->firstChild
=wineItem
->sibling
;
176 if (iItem
==infoPtr
->TopRootItem
)
177 infoPtr
->TopRootItem
=wineItem
->sibling
;
178 if (wineItem
->upsibling
) {
179 upsiblingItem
=& infoPtr
->items
[wineItem
->upsibling
];
180 upsiblingItem
->sibling
=wineItem
->sibling
;
182 if (wineItem
->sibling
) {
183 siblingItem
=& infoPtr
->items
[wineItem
->sibling
];
184 siblingItem
->upsibling
=wineItem
->upsibling
;
190 static void TREEVIEW_RemoveAllChildren (TREEVIEW_INFO
*infoPtr
,
191 TREEVIEW_ITEM
*parentItem
)
194 TREEVIEW_ITEM
*killItem
;
197 kill
=parentItem
->firstChild
;
199 tv_set_bit ( kill
, infoPtr
->freeList
);
200 killItem
=& infoPtr
->items
[kill
];
201 if (killItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
202 COMCTL32_Free (killItem
->pszText
);
203 kill
=killItem
->sibling
;
205 infoPtr
->uNumItems
-= parentItem
->cChildren
;
206 parentItem
->firstChild
= 0;
207 parentItem
->cChildren
= 0;
211 /* Note:TREEVIEW_RemoveTree doesn't remove infoPtr itself */
213 static void TREEVIEW_RemoveTree (TREEVIEW_INFO
*infoPtr
)
217 TREEVIEW_ITEM
*killItem
;
220 for (i
=1; i
<=infoPtr
->uMaxHandle
; i
++)
221 if (!tv_test_bit (i
, infoPtr
->freeList
)) {
222 killItem
=& infoPtr
->items
[i
];
223 if (killItem
->pszText
!=LPSTR_TEXTCALLBACK32A
)
224 COMCTL32_Free (killItem
->pszText
);
227 if (infoPtr
->uNumPtrsAlloced
) {
228 COMCTL32_Free (infoPtr
->items
);
229 COMCTL32_Free (infoPtr
->freeList
);
230 infoPtr
->uNumItems
=0;
231 infoPtr
->uNumPtrsAlloced
=0;
232 infoPtr
->uMaxHandle
=0;
246 TREEVIEW_GetImageList (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
248 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
250 TRACE (treeview
,"\n");
251 if (infoPtr
==NULL
) return 0;
253 if ((INT32
)wParam
== TVSIL_NORMAL
)
254 return (LRESULT
) infoPtr
->himlNormal
;
255 if ((INT32
)wParam
== TVSIL_STATE
)
256 return (LRESULT
) infoPtr
->himlState
;
265 TREEVIEW_SetImageList (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
267 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
270 TRACE (treeview
,"\n");
271 switch ((INT32
)wParam
) {
273 himlTemp
= infoPtr
->himlNormal
;
274 infoPtr
->himlNormal
= (HIMAGELIST
)lParam
;
275 return (LRESULT
)himlTemp
;
278 himlTemp
= infoPtr
->himlState
;
279 infoPtr
->himlState
= (HIMAGELIST
)lParam
;
280 return (LRESULT
)himlTemp
;
283 return (LRESULT
)NULL
;
289 TREEVIEW_SetItemHeight (WND
*wndPtr
, WPARAM32 wParam
)
291 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
292 INT32 prevHeight
=infoPtr
->uItemHeight
;
296 TRACE (treeview
,"\n");
298 hdc
=GetDC32 (wndPtr
->hwndSelf
);
299 infoPtr
->uItemHeight
=-1;
300 GetTextMetrics32A (hdc
, &tm
);
301 infoPtr
->uRealItemHeight
= tm
.tmHeight
+ tm
.tmExternalLeading
;
302 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
306 /* FIXME: check wParam > imagelist height */
308 if (!(wndPtr
->dwStyle
& TVS_NONEVENHEIGHT
))
309 infoPtr
->uItemHeight
= (INT32
) wParam
& 0xfffffffe;
314 TREEVIEW_GetItemHeight (WND
*wndPtr
)
316 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
318 TRACE (treeview
,"\n");
319 return infoPtr
->uItemHeight
;
323 TREEVIEW_SetTextColor (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
325 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
326 COLORREF prevColor
=infoPtr
->clrText
;
328 TRACE (treeview
,"\n");
329 infoPtr
->clrText
=(COLORREF
) lParam
;
330 return (LRESULT
) prevColor
;
334 TREEVIEW_GetTextColor (WND
*wndPtr
)
336 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
338 TRACE (treeview
,"\n");
339 return (LRESULT
) infoPtr
->clrText
;
344 TREEVIEW_DrawItem (WND
*wndPtr
, HDC32 hdc
, TREEVIEW_ITEM
*wineItem
,
345 TREEVIEW_ITEM
*upperItem
, int indent
)
347 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
348 INT32 oldBkMode
,center
,xpos
;
350 UINT32 uTextJustify
= DT_LEFT
;
351 HPEN32 hOldPen
, hnewPen
,hRootPen
;
354 hnewPen
= CreatePen32(PS_DOT
, 0, GetSysColor32(COLOR_WINDOWTEXT
) );
355 hOldPen
= SelectObject32( hdc
, hnewPen
);
359 upper
=upperItem
->rect
;
364 center
=(r
.top
+r
.bottom
)/2;
367 if (wndPtr
->dwStyle
& TVS_HASLINES
) {
369 if ((wndPtr
->dwStyle
& TVS_LINESATROOT
) && (indent
==0)) {
370 points
[0].y
=points
[1].y
=center
;
371 points
[2].y
=upper
.top
;
372 points
[1].x
=points
[2].x
=upper
.left
;
373 points
[0].x
=upper
.left
+12;
376 Polyline32 (hdc
,points
,3);
379 points
[0].y
=points
[1].y
=center
;
380 points
[2].y
=upper
.top
;
381 points
[1].x
=points
[2].x
=upper
.left
+13;
382 points
[0].x
=upper
.left
+25;
384 Polyline32 (hdc
,points
,3);
388 DeleteObject32(hnewPen
);
389 SelectObject32(hdc
, hOldPen
);
391 if ((wndPtr
->dwStyle
& TVS_HASBUTTONS
) && (wineItem
->cChildren
)) {
393 hRootPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOW) );
394 SelectObject32( hdc, hRootPen );
397 Rectangle32 (hdc
, xpos
-4, center
-4, xpos
+5, center
+5);
398 MoveToEx32 (hdc
, xpos
-2, center
, NULL
);
399 LineTo32 (hdc
, xpos
+3, center
);
400 if (!(wineItem
->state
& TVIS_EXPANDED
)) {
401 MoveToEx32 (hdc
, xpos
, center
-2, NULL
);
402 LineTo32 (hdc
, xpos
, center
+3);
404 /* DeleteObject32(hRootPen); */
410 if (wineItem
->mask
& TVIF_IMAGE
) {
411 if (wineItem
->iImage
!=I_IMAGECALLBACK
) {
412 if (infoPtr
->himlNormal
) {
413 ImageList_Draw (infoPtr
->himlNormal
,wineItem
->iImage
, hdc
,
414 xpos
-2, r
.top
+1, ILD_NORMAL
);
421 if ((wineItem
->mask
& TVIF_TEXT
) && (wineItem
->pszText
)) {
422 if (wineItem
->state
& TVIS_SELECTED
) {
423 oldBkMode
= SetBkMode32(hdc
, OPAQUE
);
424 oldBkColor
= SetBkColor32 (hdc
, GetSysColor32( COLOR_HIGHLIGHT
));
425 SetTextColor32 (hdc
, GetSysColor32(COLOR_HIGHLIGHTTEXT
));
427 oldBkMode
= SetBkMode32(hdc
, TRANSPARENT
);
431 if (infoPtr
->clrText
==-1)
432 SetTextColor32 (hdc
, COLOR_BTNTEXT
);
434 SetTextColor32 (hdc
, infoPtr
->clrText
); /* FIXME: retval */
435 if (wineItem
->pszText
!= LPSTR_TEXTCALLBACK32A
)
436 DrawText32A (hdc
, wineItem
->pszText
, lstrlen32A(wineItem
->pszText
),
437 &r
, uTextJustify
|DT_VCENTER
|DT_SINGLELINE
);
439 /* send TVN_GETDISPINFO notification */
440 TRACE (treeview
,"LPSTR_TEXTCALLBACK\n");
442 if (oldBkMode
!= TRANSPARENT
)
443 SetBkMode32(hdc
, oldBkMode
);
444 if (wineItem
->state
& TVIS_SELECTED
)
445 SetBkColor32 (hdc
, oldBkColor
);
448 return wineItem
->rect
.right
;
458 TREEVIEW_GetItemRect (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
460 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
461 TREEVIEW_ITEM
*wineItem
;
465 TRACE (treeview
,"\n");
466 if (infoPtr
==NULL
) return FALSE
;
468 iItem
= (INT32
)lParam
;
469 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
470 if (!wineItem
) return FALSE
;
472 wineItem
=& infoPtr
->items
[ iItem
];
473 if (!wineItem
->visible
) return FALSE
;
475 lpRect
= (LPRECT32
)lParam
;
476 if (lpRect
== NULL
) return FALSE
;
478 if ((INT32
) wParam
) {
479 lpRect
->left
= wineItem
->text
.left
;
480 lpRect
->right
= wineItem
->text
.right
;
481 lpRect
->bottom
= wineItem
->text
.bottom
;
482 lpRect
->top
= wineItem
->text
.top
;
484 lpRect
->left
= wineItem
->rect
.left
;
485 lpRect
->right
= wineItem
->rect
.right
;
486 lpRect
->bottom
= wineItem
->rect
.bottom
;
487 lpRect
->top
= wineItem
->rect
.top
;
496 TREEVIEW_GetVisibleCount (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
499 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
501 TRACE (treeview
,"\n");
502 return (LRESULT
) infoPtr
->uVisibleHeight
/ infoPtr
->uRealItemHeight
;
508 TREEVIEW_SetItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
510 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
511 TREEVIEW_ITEM
*wineItem
;
515 tvItem
=(LPTVITEM
) lParam
;
517 TRACE (treeview
,"item %d,mask %x\n",iItem
,tvItem
->mask
);
519 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
520 if (!wineItem
) return FALSE
;
522 if (tvItem
->mask
& TVIF_CHILDREN
) {
523 wineItem
->cChildren
=tvItem
->cChildren
;
526 if (tvItem
->mask
& TVIF_IMAGE
) {
527 wineItem
->iImage
=tvItem
->iImage
;
530 if (tvItem
->mask
& TVIF_INTEGRAL
) {
531 /* wineItem->iIntegral=tvItem->iIntegral; */
534 if (tvItem
->mask
& TVIF_PARAM
) {
535 wineItem
->lParam
=tvItem
->lParam
;
538 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
) {
539 wineItem
->iSelectedImage
=tvItem
->iSelectedImage
;
542 if (tvItem
->mask
& TVIF_STATE
) {
543 wineItem
->state
=tvItem
->state
& tvItem
->stateMask
;
546 if (tvItem
->mask
& TVIF_TEXT
) {
547 len
=lstrlen32A (tvItem
->pszText
);
548 if (len
>wineItem
->cchTextMax
)
549 wineItem
->pszText
= COMCTL32_ReAlloc (wineItem
->pszText
, len
+1);
550 lstrcpyn32A (wineItem
->pszText
, tvItem
->pszText
,len
);
561 TREEVIEW_Refresh (WND
*wndPtr
)
564 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
565 HFONT32 hFont
, hOldFont
;
569 INT32 iItem
, indent
, x
, y
, height
;
570 INT32 viewtop
,viewbottom
,viewleft
,viewright
;
571 TREEVIEW_ITEM
*wineItem
, *prevItem
;
573 TRACE (treeview
,"\n");
575 hdc
=GetDC32 (wndPtr
->hwndSelf
);
577 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
) {
578 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
579 infoPtr
->Timer
&= ~TV_REFRESH_TIMER_SET
;
583 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
584 if ((rect
.left
-rect
.right
==0) || (rect
.top
-rect
.bottom
==0)) return;
586 viewbottom
=infoPtr
->cy
+ rect
.bottom
-rect
.top
;
587 viewleft
=infoPtr
->cx
;
588 viewright
=infoPtr
->cx
+ rect
.right
-rect
.left
;
590 infoPtr
->uVisibleHeight
=viewbottom
- viewtop
;
592 hFont
= infoPtr
->hFont
;
593 hOldFont
= SelectObject32 (hdc
, hFont
);
595 /* draw background */
596 hbrBk
= GetSysColorBrush32(COLOR_WINDOW
);
597 FillRect32(hdc
, &rect
, hbrBk
);
600 iItem
=infoPtr
->TopRootItem
;
601 infoPtr
->firstVisible
=0;
605 TRACE (treeview
, "[%d %d %d %d]\n",viewtop
,viewbottom
,viewleft
,viewright
);
609 wineItem
= & infoPtr
->items
[iItem
];
611 TRACE (treeview
, "%d %d [%d %d %d %d] (%s)\n",y
,x
,
612 wineItem
->rect
.top
, wineItem
->rect
.bottom
,
613 wineItem
->rect
.left
, wineItem
->rect
.right
,
616 height
=infoPtr
->uRealItemHeight
* wineItem
->iIntegral
;
617 if ((y
>= viewtop
) && (y
<= viewbottom
) &&
618 (x
>= viewleft
) && (x
<= viewright
)) {
619 wineItem
->rect
.top
= y
- infoPtr
->cy
+ rect
.top
;
620 wineItem
->rect
.bottom
= wineItem
->rect
.top
+ height
;
621 wineItem
->rect
.left
= x
- infoPtr
->cx
+ rect
.left
;
622 wineItem
->rect
.right
= rect
.right
;
623 if (!infoPtr
->firstVisible
)
624 infoPtr
->firstVisible
=wineItem
->hItem
;
625 TREEVIEW_DrawItem (wndPtr
, hdc
, wineItem
, prevItem
, indent
);
628 wineItem
->rect
.top
= wineItem
->rect
.bottom
= -1;
629 wineItem
->rect
.left
= wineItem
->rect
.right
= -1;
632 /* look up next item */
634 if ((wineItem
->firstChild
) && (wineItem
->state
& TVIS_EXPANDED
)) {
635 iItem
=wineItem
->firstChild
;
640 iItem
=wineItem
->sibling
;
641 while ((!iItem
) && (indent
>0)) {
645 wineItem
=&infoPtr
->items
[wineItem
->parent
];
646 iItem
=wineItem
->sibling
;
652 infoPtr
->uTotalHeight
=y
;
653 if (y
>= (viewbottom
-viewtop
)) {
654 if (!(infoPtr
->uInternalStatus
& TV_VSCROLL
))
655 ShowScrollBar32 (wndPtr
->hwndSelf
, SB_VERT
, TRUE
);
656 infoPtr
->uInternalStatus
|=TV_VSCROLL
;
657 SetScrollRange32 (wndPtr
->hwndSelf
, SB_VERT
, 0,
658 y
- infoPtr
->uVisibleHeight
, FALSE
);
659 SetScrollPos32 (wndPtr
->hwndSelf
, SB_VERT
, infoPtr
->cy
, TRUE
);
662 if (infoPtr
->uInternalStatus
& TV_VSCROLL
)
663 ShowScrollBar32 (wndPtr
->hwndSelf
, SB_VERT
, FALSE
);
664 infoPtr
->uInternalStatus
&= ~TV_VSCROLL
;
668 SelectObject32 (hdc
, hOldFont
);
669 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
674 TREEVIEW_HandleTimer ( WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
676 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
678 TRACE (treeview
, " %d\n",wParam
);
679 if (!infoPtr
) return FALSE
;
682 case TV_REFRESH_TIMER
:
683 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
684 infoPtr
->Timer
&= ~TV_REFRESH_TIMER_SET
;
685 TREEVIEW_Refresh (wndPtr
);
688 KillTimer32 (wndPtr
->hwndSelf
, TV_EDIT_TIMER
);
689 infoPtr
->Timer
&= ~TV_EDIT_TIMER_SET
;
698 TREEVIEW_QueueRefresh (WND
*wndPtr
)
701 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
703 TRACE (treeview
,"\n");
704 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
) {
705 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
708 SetTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
, TV_REFRESH_DELAY
, 0);
709 infoPtr
->Timer
|=TV_REFRESH_TIMER_SET
;
715 TREEVIEW_GetItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
717 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
719 TREEVIEW_ITEM
*wineItem
;
722 TRACE (treeview
,"\n");
723 tvItem
=(LPTVITEM
) lParam
;
726 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
727 if (!wineItem
) return FALSE
;
730 if (tvItem
->mask
& TVIF_CHILDREN
) {
731 tvItem
->cChildren
=wineItem
->cChildren
;
734 if (tvItem
->mask
& TVIF_HANDLE
) {
735 tvItem
->hItem
=wineItem
->hItem
;
738 if (tvItem
->mask
& TVIF_IMAGE
) {
739 tvItem
->iImage
=wineItem
->iImage
;
742 if (tvItem
->mask
& TVIF_INTEGRAL
) {
743 /* tvItem->iIntegral=wineItem->iIntegral; */
746 if (tvItem
->mask
& TVIF_PARAM
) {
747 tvItem
->lParam
=wineItem
->lParam
;
750 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
) {
751 tvItem
->iSelectedImage
=wineItem
->iSelectedImage
;
754 if (tvItem
->mask
& TVIF_STATE
) {
755 tvItem
->state
=wineItem
->state
& tvItem
->stateMask
;
758 if (tvItem
->mask
& TVIF_TEXT
) {
759 if (wineItem
->pszText
== LPSTR_TEXTCALLBACK32A
) {
760 tvItem
->pszText
= LPSTR_TEXTCALLBACK32A
;
762 else if (wineItem
->pszText
) {
763 lstrcpyn32A (tvItem
->pszText
, wineItem
->pszText
, tvItem
->cchTextMax
);
772 /* FIXME: check implementation of TVGN_NEXT/TVGN_NEXTVISIBLE */
776 TREEVIEW_GetNextItem32 (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
779 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
780 TREEVIEW_ITEM
*wineItem
;
784 TRACE (treeview
,"item:%lu, flags:%x\n", lParam
, wParam
);
785 if (!infoPtr
) return FALSE
;
787 flag
= (INT32
) wParam
;
789 case TVGN_ROOT
: return (LRESULT
) infoPtr
->TopRootItem
;
790 case TVGN_CARET
: return (LRESULT
) infoPtr
->selectedItem
;
791 case TVGN_FIRSTVISIBLE
:
792 TREEVIEW_Refresh (wndPtr
);
793 return (LRESULT
) infoPtr
->firstVisible
;
794 case TVGN_DROPHILITE
:
795 return (LRESULT
) infoPtr
->dropItem
;
798 iItem
= (INT32
) lParam
;
799 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
800 if (!wineItem
) return FALSE
;
803 case TVGN_NEXT
: return (LRESULT
) wineItem
->sibling
;
804 case TVGN_PREVIOUS
: return (LRESULT
) wineItem
->upsibling
;
805 case TVGN_PARENT
: return (LRESULT
) wineItem
->parent
;
806 case TVGN_CHILD
: return (LRESULT
) wineItem
->firstChild
;
807 case TVGN_LASTVISIBLE
:
808 wineItem
=TREEVIEW_GetLastListItem (infoPtr
);
810 case TVGN_NEXTVISIBLE
:
811 wineItem
=TREEVIEW_GetNextListItem (infoPtr
,wineItem
);
812 TRACE (treeview
,"(%s)\n",wineItem
->pszText
);
814 case TVGN_PREVIOUSVISIBLE
:
815 wineItem
=TREEVIEW_GetPrevListItem (infoPtr
, wineItem
);
816 TRACE (treeview
,"(%s)\n",wineItem
->pszText
);
818 default: FIXME (treeview
,"Unknown msg %x,item %x\n", flag
,iItem
);
822 if (wineItem
) return (LRESULT
) wineItem
->hItem
;
824 FIXME (treeview
, "returning 0\n");
830 TREEVIEW_GetCount (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
832 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
834 TRACE (treeview
,"\n");
835 return (LRESULT
) infoPtr
->uNumItems
;
841 /* the method used below isn't the most memory-friendly, but it avoids
842 a lot of memory reallocations */
844 /* BTW: we waste handle 0; 0 is not an allowed handle. Fix this by
845 decreasing infoptr->items with 1, and increasing it by 1 if
846 it is referenced in mm-handling stuff? */
849 TREEVIEW_InsertItem32A (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
852 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
853 TVINSERTSTRUCT
*ptdi
;
855 TREEVIEW_ITEM
*wineItem
, *parentItem
, *prevsib
, *sibItem
;
856 INT32 iItem
,listItems
,i
,len
;
858 TRACE (treeview
,"\n");
859 ptdi
= (TVINSERTSTRUCT
*) lParam
;
861 /* check if memory is available */
863 if (infoPtr
->uNumPtrsAlloced
==0) {
864 infoPtr
->items
= COMCTL32_Alloc (TVITEM_ALLOC
*sizeof (TREEVIEW_ITEM
));
865 infoPtr
->freeList
= COMCTL32_Alloc ((1+(TVITEM_ALLOC
>>5)) * sizeof (INT32
));
866 infoPtr
->uNumPtrsAlloced
=TVITEM_ALLOC
;
867 infoPtr
->TopRootItem
=1;
870 if (infoPtr
->uNumItems
== (infoPtr
->uNumPtrsAlloced
-1) ) {
871 TREEVIEW_ITEM
*oldItems
= infoPtr
->items
;
872 INT32
*oldfreeList
= infoPtr
->freeList
;
874 infoPtr
->uNumPtrsAlloced
*=2;
875 infoPtr
->items
= COMCTL32_Alloc ( infoPtr
->uNumPtrsAlloced
* sizeof (TREEVIEW_ITEM
));
876 infoPtr
->freeList
= COMCTL32_Alloc ((1+(infoPtr
->uNumPtrsAlloced
>>5))*sizeof (INT32
));
878 memcpy (&infoPtr
->items
[0], &oldItems
[0],
879 infoPtr
->uNumPtrsAlloced
/2 * sizeof(TREEVIEW_ITEM
));
880 memcpy (&infoPtr
->freeList
[0], &oldfreeList
[0],
881 infoPtr
->uNumPtrsAlloced
>>6 * sizeof(INT32
));
883 COMCTL32_Free (oldItems
);
884 COMCTL32_Free (oldfreeList
);
888 infoPtr
->uNumItems
++;
890 if (infoPtr
->uMaxHandle
==(infoPtr
->uNumItems
-1)) {
891 iItem
=infoPtr
->uNumItems
;
892 infoPtr
->uMaxHandle
++;
894 else { /* check freelist */
895 for (i
=0; i
<infoPtr
->uNumPtrsAlloced
>>5; i
++) {
896 if (infoPtr
->freeList
[i
]) {
897 iItem
=ffs (infoPtr
->freeList
[i
]);
898 tv_clear_bit(iItem
,&infoPtr
->freeList
[i
]);
903 if (!iItem
) ERR (treeview
, "Argh -- can't find free item.\n");
905 tvItem
= & ptdi
->item
;
906 wineItem
=& infoPtr
->items
[iItem
];
910 if ((ptdi
->hParent
==TVI_ROOT
) || (ptdi
->hParent
==0)) {
913 sibItem
=&infoPtr
->items
[infoPtr
->TopRootItem
];
914 listItems
=infoPtr
->uNumItems
;
917 parentItem
= &infoPtr
->items
[ptdi
->hParent
];
918 if (!parentItem
->firstChild
)
919 parentItem
->firstChild
=iItem
;
920 wineItem
->parent
=ptdi
->hParent
;
921 sibItem
=&infoPtr
->items
[parentItem
->firstChild
];
922 parentItem
->cChildren
++;
923 listItems
=parentItem
->cChildren
;
926 wineItem
->upsibling
=0; /* needed in case we're the first item in a list */
928 wineItem
->firstChild
=0;
932 switch (ptdi
->hInsertAfter
) {
933 case TVI_FIRST
: wineItem
->sibling
=infoPtr
->TopRootItem
;
934 infoPtr
->TopRootItem
=iItem
;
937 while (sibItem
->sibling
) {
939 sibItem
=&infoPtr
->items
[sibItem
->sibling
];
941 sibItem
->sibling
=iItem
;
943 wineItem
->upsibling
=prevsib
->hItem
;
945 wineItem
->sibling
=0; /* terminate list */
948 FIXME (treeview
, "Sorted insert not implemented yet\n");
951 while ((sibItem
->sibling
) && (sibItem
->sibling
!=iItem
)) {
953 sibItem
=&infoPtr
->items
[sibItem
->sibling
];
955 if (sibItem
->sibling
)
956 WARN (treeview
, "Buggy program tried to insert item after nonexisting handle.");
957 sibItem
->upsibling
=iItem
;
958 wineItem
->sibling
=sibItem
->hItem
;
960 wineItem
->upsibling
=prevsib
->hItem
;
966 /* Fill in info structure */
968 TRACE (treeview
,"item %d, mask %x\n",iItem
, tvItem
->mask
);
969 wineItem
->mask
=tvItem
->mask
;
970 wineItem
->hItem
=iItem
;
971 wineItem
->iIntegral
=1;
973 if (tvItem
->mask
& TVIF_CHILDREN
)
974 wineItem
->cChildren
=tvItem
->cChildren
;
976 if (tvItem
->mask
& TVIF_IMAGE
)
977 wineItem
->iImage
=tvItem
->iImage
;
979 /* if (tvItem->mask & TVIF_INTEGRAL)
980 wineItem->iIntegral=tvItem->iIntegral; */
983 if (tvItem
->mask
& TVIF_PARAM
)
984 wineItem
->lParam
=tvItem
->lParam
;
986 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
)
987 wineItem
->iSelectedImage
=tvItem
->iSelectedImage
;
989 if (tvItem
->mask
& TVIF_STATE
) {
990 wineItem
->state
=tvItem
->state
;
991 wineItem
->stateMask
=tvItem
->stateMask
;
994 if (tvItem
->mask
& TVIF_TEXT
) {
995 TRACE (treeview
,"(%s)\n", tvItem
->pszText
);
996 if (tvItem
->pszText
!=LPSTR_TEXTCALLBACK32A
) {
997 len
= lstrlen32A (tvItem
->pszText
)+1;
998 wineItem
->pszText
= COMCTL32_Alloc (len
+1);
999 lstrcpy32A (wineItem
->pszText
, tvItem
->pszText
);
1000 wineItem
->cchTextMax
=len
;
1003 wineItem
->pszText
= LPSTR_TEXTCALLBACK32A
;
1004 TRACE (treeview
,"LPSTR_TEXTCALLBACK\n");
1005 wineItem
->cchTextMax
= 0;
1009 TREEVIEW_QueueRefresh (wndPtr
);
1011 return (LRESULT
) iItem
;
1017 TREEVIEW_DeleteItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1019 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1022 TREEVIEW_ITEM
*wineItem
;
1024 TRACE (treeview
,"\n");
1025 if (!infoPtr
) return FALSE
;
1027 if ((INT32
) lParam
== TVI_ROOT
) {
1028 TREEVIEW_RemoveTree (infoPtr
);
1030 iItem
= (INT32
) lParam
;
1031 wineItem
= TREEVIEW_ValidItem (infoPtr
, iItem
);
1032 if (!wineItem
) return FALSE
;
1033 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_DELETEITEM
, 0, iItem
, 0, pt
);
1034 TREEVIEW_RemoveItem (infoPtr
, wineItem
);
1037 TREEVIEW_QueueRefresh (wndPtr
);
1044 TREEVIEW_GetIndent (WND
*wndPtr
)
1046 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1048 TRACE (treeview
,"\n");
1049 return infoPtr
->uIndent
;
1053 TREEVIEW_SetIndent (WND
*wndPtr
, WPARAM32 wParam
)
1055 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1058 TRACE (treeview
,"\n");
1059 newIndent
=(INT32
) wParam
;
1060 if (newIndent
< MINIMUM_INDENT
) newIndent
=MINIMUM_INDENT
;
1061 infoPtr
->uIndent
=newIndent
;
1067 TREEVIEW_GetToolTips (WND
*wndPtr
)
1070 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1072 TRACE (treeview
,"\n");
1073 return infoPtr
->hwndToolTip
;
1078 TREEVIEW_SetToolTips (WND
*wndPtr
, WPARAM32 wParam
)
1081 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1084 TRACE (treeview
,"\n");
1085 prevToolTip
=infoPtr
->hwndToolTip
;
1086 infoPtr
->hwndToolTip
= (HWND32
) wParam
;
1097 TREEVIEW_Create (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1099 TREEVIEW_INFO
*infoPtr
;
1103 TRACE (treeview
,"\n");
1104 /* allocate memory for info structure */
1105 infoPtr
= (TREEVIEW_INFO
*) COMCTL32_Alloc (sizeof(TREEVIEW_INFO
));
1107 wndPtr
->wExtra
[0] = (DWORD
)infoPtr
;
1109 if (infoPtr
== NULL
) {
1110 ERR (treeview
, "could not allocate info memory!\n");
1114 if ((TREEVIEW_INFO
*)wndPtr
->wExtra
[0] != infoPtr
) {
1115 ERR (treeview
, "pointer assignment error!\n");
1119 hdc
=GetDC32 (wndPtr
->hwndSelf
);
1121 /* set default settings */
1122 infoPtr
->uInternalStatus
=0;
1123 infoPtr
->uNumItems
=0;
1124 infoPtr
->clrBk
= GetSysColor32 (COLOR_WINDOW
);
1125 infoPtr
->clrText
= GetSysColor32 (COLOR_BTNTEXT
);
1128 infoPtr
->uIndent
= 15;
1129 infoPtr
->himlNormal
= NULL
;
1130 infoPtr
->himlState
= NULL
;
1131 infoPtr
->uItemHeight
= -1;
1132 GetTextMetrics32A (hdc
, &tm
);
1133 infoPtr
->hFont
= GetStockObject32 (DEFAULT_GUI_FONT
);
1134 infoPtr
->uRealItemHeight
= tm
.tmHeight
+ tm
.tmExternalLeading
;
1136 infoPtr
->items
= NULL
;
1137 infoPtr
->selectedItem
=0;
1138 infoPtr
->clrText
=-1; /* use system color */
1139 infoPtr
->dropItem
=0;
1142 infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
1143 infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
1146 infoPtr
->hwndToolTip
=0;
1147 if (!(wndPtr
->dwStyle
& TVS_NOTOOLTIPS
)) { /* Create tooltip control */
1150 infoPtr
->hwndToolTip
=
1151 CreateWindowEx32A (0, TOOLTIPS_CLASS32A
, NULL
, 0,
1152 CW_USEDEFAULT32
, CW_USEDEFAULT32
,
1153 CW_USEDEFAULT32
, CW_USEDEFAULT32
,
1154 wndPtr
->hwndSelf
, 0, 0, 0);
1156 /* Send NM_TOOLTIPSCREATED notification */
1157 if (infoPtr
->hwndToolTip
) {
1158 NMTOOLTIPSCREATED nmttc
;
1160 nmttc
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
1161 nmttc
.hdr
.idFrom
= wndPtr
->wIDmenu
;
1162 nmttc
.hdr
.code
= NM_TOOLTIPSCREATED
;
1163 nmttc
.hwndToolTips
= infoPtr
->hwndToolTip
;
1165 SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
1166 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&nmttc
);
1169 ZeroMemory (&ti
, sizeof(TTTOOLINFO32A
));
1170 ti
.cbSize
= sizeof(TTTOOLINFO32A
);
1171 ti
.uFlags
= TTF_IDISHWND
| TTF_TRACK
| TTF_TRANSPARENT
;
1172 ti
.hwnd
= wndPtr
->hwndSelf
;
1174 ti
.lpszText
= "Test"; /* LPSTR_TEXTCALLBACK; */
1175 SetRectEmpty32 (&ti
.rect
);
1177 SendMessage32A (infoPtr
->hwndToolTip
, TTM_ADDTOOL32A
, 0, (LPARAM
)&ti
);
1180 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1188 TREEVIEW_Destroy (WND
*wndPtr
)
1190 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1192 TRACE (treeview
,"\n");
1193 TREEVIEW_RemoveTree (infoPtr
);
1194 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
)
1195 KillTimer32 (wndPtr
->hwndSelf
, TV_REFRESH_TIMER
);
1196 if (infoPtr
->hwndToolTip
)
1197 DestroyWindow32 (infoPtr
->hwndToolTip
);
1199 COMCTL32_Free (infoPtr
);
1205 TREEVIEW_Paint (WND
*wndPtr
, WPARAM32 wParam
)
1210 TRACE (treeview
,"\n");
1211 hdc
= wParam
==0 ? BeginPaint32 (wndPtr
->hwndSelf
, &ps
) : (HDC32
)wParam
;
1212 TREEVIEW_QueueRefresh (wndPtr
);
1214 EndPaint32 (wndPtr
->hwndSelf
, &ps
);
1221 TREEVIEW_EraseBackground (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1223 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1224 HBRUSH32 hBrush
= CreateSolidBrush32 (infoPtr
->clrBk
);
1227 TRACE (treeview
,"\n");
1228 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
1229 FillRect32 ((HDC32
)wParam
, &rect
, hBrush
);
1230 DeleteObject32 (hBrush
);
1243 TREEVIEW_SendSimpleNotify (WND
*wndPtr
, UINT32 code
)
1247 TRACE (treeview
, "%x\n",code
);
1248 nmhdr
.hwndFrom
= wndPtr
->hwndSelf
;
1249 nmhdr
.idFrom
= wndPtr
->wIDmenu
;
1252 return (BOOL32
) SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
1253 (WPARAM32
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1260 TREEVIEW_SendTreeviewNotify (WND
*wndPtr
, UINT32 code
, UINT32 action
,
1261 INT32 oldItem
, INT32 newItem
, POINT32 pt
)
1263 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1265 TREEVIEW_ITEM
*wineItem
;
1267 TRACE (treeview
,"code:%x action:%x olditem:%x newitem:%x\n",
1268 code
,action
,oldItem
,newItem
);
1269 nmhdr
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
1270 nmhdr
.hdr
.idFrom
= wndPtr
->wIDmenu
;
1271 nmhdr
.hdr
.code
= code
;
1272 nmhdr
.action
= action
;
1274 wineItem
=& infoPtr
->items
[oldItem
];
1275 nmhdr
.itemOld
.mask
= wineItem
->mask
;
1276 nmhdr
.itemOld
.hItem
= wineItem
->hItem
;
1277 nmhdr
.itemOld
.state
= wineItem
->state
;
1278 nmhdr
.itemOld
.stateMask
= wineItem
->stateMask
;
1279 nmhdr
.itemOld
.iImage
= wineItem
->iImage
;
1280 nmhdr
.itemOld
.pszText
= wineItem
->pszText
;
1281 nmhdr
.itemOld
.cchTextMax
= wineItem
->cchTextMax
;
1282 nmhdr
.itemOld
.iImage
= wineItem
->iImage
;
1283 nmhdr
.itemOld
.iSelectedImage
= wineItem
->iSelectedImage
;
1284 nmhdr
.itemOld
.cChildren
= wineItem
->cChildren
;
1285 nmhdr
.itemOld
.lParam
= wineItem
->lParam
;
1289 wineItem
=& infoPtr
->items
[newItem
];
1290 nmhdr
.itemNew
.mask
= wineItem
->mask
;
1291 nmhdr
.itemNew
.hItem
= wineItem
->hItem
;
1292 nmhdr
.itemNew
.state
= wineItem
->state
;
1293 nmhdr
.itemNew
.stateMask
= wineItem
->stateMask
;
1294 nmhdr
.itemNew
.iImage
= wineItem
->iImage
;
1295 nmhdr
.itemNew
.pszText
= wineItem
->pszText
;
1296 nmhdr
.itemNew
.cchTextMax
= wineItem
->cchTextMax
;
1297 nmhdr
.itemNew
.iImage
= wineItem
->iImage
;
1298 nmhdr
.itemNew
.iSelectedImage
= wineItem
->iSelectedImage
;
1299 nmhdr
.itemNew
.cChildren
= wineItem
->cChildren
;
1300 nmhdr
.itemNew
.lParam
= wineItem
->lParam
;
1303 nmhdr
.ptDrag
.x
= pt
.x
;
1304 nmhdr
.ptDrag
.y
= pt
.y
;
1306 return (BOOL32
)SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
1307 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&nmhdr
);
1315 TREEVIEW_Expand (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1317 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1318 TREEVIEW_ITEM
*wineItem
;
1323 flag
= (UINT32
) wParam
;
1324 expandItem
= (INT32
) lParam
;
1325 TRACE (treeview
,"flags:%x item:%x\n", expandItem
, wParam
);
1326 wineItem
= TREEVIEW_ValidItem (infoPtr
, expandItem
);
1327 if (!wineItem
) return 0;
1328 if (!wineItem
->cChildren
) return 0;
1330 if (flag
& TVE_TOGGLE
) { /* FIXME: check exact behaviour here */
1331 flag
&= ~TVE_TOGGLE
; /* ie: bitwise ops or 'case' ops */
1332 if (wineItem
->state
& TVIS_EXPANDED
)
1333 flag
|= TVE_COLLAPSE
;
1339 case TVE_COLLAPSERESET
:
1340 if (!wineItem
->state
& TVIS_EXPANDED
) return 0;
1341 wineItem
->state
&= ~(TVIS_EXPANDEDONCE
| TVIS_EXPANDED
);
1342 TREEVIEW_RemoveAllChildren (infoPtr
, wineItem
);
1346 if (!wineItem
->state
& TVIS_EXPANDED
) return 0;
1347 wineItem
->state
&= ~TVIS_EXPANDED
;
1351 if (wineItem
->state
& TVIS_EXPANDED
) return 0;
1352 if (!(wineItem
->state
& TVIS_EXPANDEDONCE
)) {
1353 if (TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_ITEMEXPANDING
,
1354 0, 0, expandItem
, pt
))
1355 return FALSE
; /* FIXME: OK? */
1356 wineItem
->state
|= TVIS_EXPANDED
| TVIS_EXPANDEDONCE
;
1357 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_ITEMEXPANDED
,
1358 0, 0, expandItem
, pt
);
1360 wineItem
->state
|= TVIS_EXPANDED
;
1362 case TVE_EXPANDPARTIAL
:
1363 FIXME (treeview
, "TVE_EXPANDPARTIAL not implemented\n");
1364 wineItem
->state
^=TVIS_EXPANDED
;
1365 wineItem
->state
|=TVIS_EXPANDEDONCE
;
1369 TREEVIEW_QueueRefresh (wndPtr
);
1377 TREEVIEW_HitTest (WND
*wndPtr
, LPTVHITTESTINFO lpht
)
1379 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1380 TREEVIEW_ITEM
*wineItem
;
1386 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
1387 TRACE (treeview
,"(%d,%d)\n",lpht
->pt
.x
, lpht
->pt
.y
);
1392 if (x
< rect
.left
) status
|=TVHT_TOLEFT
;
1393 if (x
> rect
.right
) status
|=TVHT_TORIGHT
;
1394 if (y
< rect
.top
) status
|=TVHT_ABOVE
;
1395 if (y
> rect
.bottom
) status
|=TVHT_BELOW
;
1401 if (!infoPtr
->firstVisible
) WARN (treeview
,"Can't fetch first visible item");
1402 wineItem
=&infoPtr
->items
[infoPtr
->firstVisible
];
1404 while ((wineItem
!=NULL
) && (y
> wineItem
->rect
.bottom
))
1405 wineItem
=TREEVIEW_GetNextListItem (infoPtr
,wineItem
);
1407 if (wineItem
==NULL
) {
1408 lpht
->flags
=TVHT_NOWHERE
;
1412 if (x
>wineItem
->rect
.right
) {
1413 lpht
->flags
|=TVHT_ONITEMRIGHT
;
1414 return wineItem
->hItem
;
1418 if (x
<wineItem
->rect
.left
+10) lpht
->flags
|=TVHT_ONITEMBUTTON
;
1420 lpht
->flags
=TVHT_ONITEMLABEL
; /* FIXME: implement other flags */
1423 lpht
->hItem
=wineItem
->hItem
;
1424 return wineItem
->hItem
;
1429 TREEVIEW_HitTest32 (WND
*wndPtr
, LPARAM lParam
)
1432 return (LRESULT
) TREEVIEW_HitTest (wndPtr
, (LPTVHITTESTINFO
) lParam
);
1439 TREEVIEW_LButtonDoubleClick (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1441 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1442 TREEVIEW_ITEM
*wineItem
;
1446 TRACE (treeview
,"\n");
1447 ht
.pt
.x
= (INT32
)LOWORD(lParam
);
1448 ht
.pt
.y
= (INT32
)HIWORD(lParam
);
1449 SetFocus32 (wndPtr
->hwndSelf
);
1451 iItem
=TREEVIEW_HitTest (wndPtr
, &ht
);
1452 TRACE (treeview
,"item %d \n",iItem
);
1453 wineItem
=TREEVIEW_ValidItem (infoPtr
, iItem
);
1454 if (!wineItem
) return 0;
1456 if (TREEVIEW_SendSimpleNotify (wndPtr
, NM_DBLCLK
)!=TRUE
) { /* FIXME!*/
1457 wineItem
->state
&= ~TVIS_EXPANDEDONCE
;
1458 TREEVIEW_Expand (wndPtr
, (WPARAM32
) TVE_TOGGLE
, (LPARAM
) iItem
);
1466 TREEVIEW_LButtonDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1471 TRACE (treeview
,"\n");
1472 ht
.pt
.x
= (INT32
)LOWORD(lParam
);
1473 ht
.pt
.y
= (INT32
)HIWORD(lParam
);
1475 SetFocus32 (wndPtr
->hwndSelf
);
1476 iItem
=TREEVIEW_HitTest (wndPtr
, &ht
);
1477 TRACE (treeview
,"item %d \n",iItem
);
1478 if (ht
.flags
& TVHT_ONITEMBUTTON
) {
1479 TREEVIEW_Expand (wndPtr
, (WPARAM32
) TVE_TOGGLE
, (LPARAM
) iItem
);
1482 if (TREEVIEW_SelectItem (wndPtr
, (WPARAM32
) TVGN_CARET
, (LPARAM
) iItem
))
1491 TREEVIEW_RButtonDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1494 TRACE (treeview
,"\n");
1501 /* FIXME: If the specified item is the child of a collapsed parent item,
1502 expand parent's list of child items to reveal the specified item.
1506 TREEVIEW_SelectItem (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1508 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1509 TREEVIEW_ITEM
*prevItem
,*wineItem
;
1510 INT32 action
,prevSelect
, newSelect
;
1513 TRACE (treeview
,"item %lx, flag %x\n", lParam
, wParam
);
1514 newSelect
= (INT32
) lParam
;
1515 wineItem
= TREEVIEW_ValidItem (infoPtr
, newSelect
);
1516 if (!wineItem
) return FALSE
;
1517 prevSelect
=infoPtr
->selectedItem
;
1518 prevItem
= TREEVIEW_ValidItem (infoPtr
, prevSelect
);
1522 action
= (INT32
) wParam
;
1526 if (TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_SELCHANGING
, TVC_BYMOUSE
,
1527 prevSelect
, newSelect
,dummy
))
1528 return FALSE
; /* FIXME: OK? */
1530 if (prevItem
) prevItem
->state
&= ~TVIS_SELECTED
;
1531 infoPtr
->selectedItem
=newSelect
;
1532 wineItem
->state
|=TVIS_SELECTED
;
1533 TREEVIEW_SendTreeviewNotify (wndPtr
, TVN_SELCHANGED
,
1534 TVC_BYMOUSE
, prevSelect
, newSelect
, dummy
);
1536 case TVGN_DROPHILITE
:
1537 FIXME (treeview
, "DROPHILITE not implemented");
1539 case TVGN_FIRSTVISIBLE
:
1540 FIXME (treeview
, "FIRSTVISIBLE not implemented");
1544 TREEVIEW_QueueRefresh (wndPtr
);
1553 TREEVIEW_GetFont (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1556 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1558 TRACE (treeview
,"%x\n",infoPtr
->hFont
);
1559 return infoPtr
->hFont
;
1563 TREEVIEW_SetFont (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1566 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1568 HFONT32 hFont
, hOldFont
;
1571 TRACE (treeview
,"%x %lx\n",wParam
, lParam
);
1573 infoPtr
->hFont
= (HFONT32
)wParam
;
1575 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject32 (SYSTEM_FONT
);
1578 hOldFont
= SelectObject32 (hdc
, hFont
);
1579 GetTextMetrics32A (hdc
, &tm
);
1580 infoPtr
->uRealItemHeight
= tm
.tmHeight
+ tm
.tmExternalLeading
;
1581 SelectObject32 (hdc
, hOldFont
);
1582 ReleaseDC32 (0, hdc
);
1585 TREEVIEW_QueueRefresh (wndPtr
);
1591 /* FIXME: does KEYDOWN also send notifications?? If so, use
1592 TREEVIEW_SelectItem.
1597 TREEVIEW_KeyDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1599 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1600 TREEVIEW_ITEM
*prevItem
,*newItem
;
1604 TRACE (treeview
,"%x %lx\n",wParam
, lParam
);
1605 prevSelect
=infoPtr
->selectedItem
;
1606 if (!prevSelect
) return FALSE
;
1608 prevItem
= TREEVIEW_ValidItem (infoPtr
, prevSelect
);
1613 newItem
=TREEVIEW_GetPrevListItem (infoPtr
, prevItem
);
1615 newItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
1618 newItem
=TREEVIEW_GetNextListItem (infoPtr
, prevItem
);
1619 if (!newItem
) newItem
=prevItem
;
1622 newItem
=& infoPtr
->items
[infoPtr
->TopRootItem
];
1625 newItem
=TREEVIEW_GetLastListItem (infoPtr
);
1631 FIXME (treeview
, "%x not implemented\n", wParam
);
1635 if (!newItem
) return FALSE
;
1637 if (prevItem
!=newItem
) {
1638 prevItem
->state
&= ~TVIS_SELECTED
;
1639 newItem
->state
|= TVIS_SELECTED
;
1640 infoPtr
->selectedItem
=newItem
->hItem
;
1641 TREEVIEW_QueueRefresh (wndPtr
);
1651 TREEVIEW_VScroll (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1654 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1657 TRACE (treeview
,"wp %x, lp %lx\n", wParam
, lParam
);
1658 if (!infoPtr
->uInternalStatus
& TV_VSCROLL
) return FALSE
;
1660 switch (LOWORD (wParam
)) {
1662 if (!infoPtr
->cy
) return FALSE
;
1663 infoPtr
->cy
-= infoPtr
->uRealItemHeight
;
1664 if (infoPtr
->cy
< 0) infoPtr
->cy
=0;
1667 maxHeight
=infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
1668 if (infoPtr
->cy
== maxHeight
) return FALSE
;
1669 infoPtr
->cy
+= infoPtr
->uRealItemHeight
;
1670 if (infoPtr
->cy
> maxHeight
)
1671 infoPtr
->cy
= maxHeight
;
1674 if (!infoPtr
->cy
) return FALSE
;
1675 infoPtr
->cy
-= infoPtr
->uVisibleHeight
;
1676 if (infoPtr
->cy
< 0) infoPtr
->cy
=0;
1679 maxHeight
=infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
1680 if (infoPtr
->cy
== maxHeight
) return FALSE
;
1681 infoPtr
->cy
+= infoPtr
->uVisibleHeight
;
1682 if (infoPtr
->cy
> maxHeight
)
1683 infoPtr
->cy
= maxHeight
;
1686 infoPtr
->cy
= HIWORD (wParam
);
1691 TREEVIEW_QueueRefresh (wndPtr
);
1696 TREEVIEW_HScroll (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1698 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(wndPtr
);
1700 TRACE (treeview
,"wp %lx, lp %x\n", lParam
, wParam
);
1702 if (!infoPtr
->uInternalStatus
& TV_HSCROLL
) return FALSE
;
1710 TREEVIEW_WindowProc (HWND32 hwnd
, UINT32 uMsg
, WPARAM32 wParam
, LPARAM lParam
)
1712 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1716 case TVM_INSERTITEM32A
:
1717 return TREEVIEW_InsertItem32A (wndPtr
, wParam
, lParam
);
1719 case TVM_INSERTITEM32W
:
1720 FIXME (treeview
, "Unimplemented msg TVM_INSERTITEM32W\n");
1723 case TVM_DELETEITEM
:
1724 return TREEVIEW_DeleteItem (wndPtr
, wParam
, lParam
);
1727 return TREEVIEW_Expand (wndPtr
, wParam
, lParam
);
1729 case TVM_GETITEMRECT
:
1730 return TREEVIEW_GetItemRect (wndPtr
, wParam
, lParam
);
1733 return TREEVIEW_GetCount (wndPtr
, wParam
, lParam
);
1736 return TREEVIEW_GetIndent (wndPtr
);
1739 return TREEVIEW_SetIndent (wndPtr
, wParam
);
1741 case TVM_GETIMAGELIST
:
1742 return TREEVIEW_GetImageList (wndPtr
, wParam
, lParam
);
1744 case TVM_SETIMAGELIST
:
1745 return TREEVIEW_SetImageList (wndPtr
, wParam
, lParam
);
1747 case TVM_GETNEXTITEM
:
1748 return TREEVIEW_GetNextItem32 (wndPtr
, wParam
, lParam
);
1750 case TVM_SELECTITEM
:
1751 return TREEVIEW_SelectItem (wndPtr
, wParam
, lParam
);
1753 case TVM_GETITEM32A
:
1754 return TREEVIEW_GetItem (wndPtr
, wParam
, lParam
);
1756 case TVM_GETITEM32W
:
1757 FIXME (treeview
, "Unimplemented msg TVM_GETITEM32W\n");
1760 case TVM_SETITEM32A
:
1761 return TREEVIEW_SetItem (wndPtr
, wParam
, lParam
);
1763 case TVM_SETITEM32W
:
1764 FIXME (treeview
, "Unimplemented msg TVM_SETITEMW\n");
1767 case TVM_EDITLABEL32A
:
1768 FIXME (treeview
, "Unimplemented msg TVM_EDITLABEL32A \n");
1771 case TVM_EDITLABEL32W
:
1772 FIXME (treeview
, "Unimplemented msg TVM_EDITLABEL32W \n");
1775 case TVM_GETEDITCONTROL
:
1776 FIXME (treeview
, "Unimplemented msg TVM_GETEDITCONTROL\n");
1779 case TVM_GETVISIBLECOUNT
:
1780 return TREEVIEW_GetVisibleCount (wndPtr
, wParam
, lParam
);
1783 return TREEVIEW_HitTest32 (wndPtr
, lParam
);
1785 case TVM_CREATEDRAGIMAGE
:
1786 FIXME (treeview
, "Unimplemented msg TVM_CREATEDRAGIMAGE\n");
1789 case TVM_SORTCHILDREN
:
1790 FIXME (treeview
, "Unimplemented msg TVM_SORTCHILDREN\n");
1793 case TVM_ENSUREVISIBLE
:
1794 FIXME (treeview
, "Unimplemented msg TVM_ENSUREVISIBLE\n");
1797 case TVM_SORTCHILDRENCB
:
1798 FIXME (treeview
, "Unimplemented msg TVM_SORTCHILDRENCB\n");
1801 case TVM_ENDEDITLABELNOW
:
1802 FIXME (treeview
, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
1805 case TVM_GETISEARCHSTRING32A
:
1806 FIXME (treeview
, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
1809 case TVM_GETISEARCHSTRING32W
:
1810 FIXME (treeview
, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
1813 case TVM_GETTOOLTIPS
:
1814 return TREEVIEW_GetToolTips (wndPtr
);
1816 case TVM_SETTOOLTIPS
:
1817 return TREEVIEW_SetToolTips (wndPtr
, wParam
);
1819 case TVM_SETINSERTMARK
:
1820 FIXME (treeview
, "Unimplemented msg TVM_SETINSERTMARK\n");
1823 case TVM_SETITEMHEIGHT
:
1824 return TREEVIEW_SetItemHeight (wndPtr
, wParam
);
1826 case TVM_GETITEMHEIGHT
:
1827 return TREEVIEW_GetItemHeight (wndPtr
);
1829 case TVM_SETBKCOLOR
:
1830 FIXME (treeview
, "Unimplemented msg TVM_SETBKCOLOR\n");
1833 case TVM_SETTEXTCOLOR
:
1834 return TREEVIEW_SetTextColor (wndPtr
, wParam
, lParam
);
1836 case TVM_GETBKCOLOR
:
1837 FIXME (treeview
, "Unimplemented msg TVM_GETBKCOLOR\n");
1840 case TVM_GETTEXTCOLOR
:
1841 return TREEVIEW_GetTextColor (wndPtr
);
1843 case TVM_SETSCROLLTIME
:
1844 FIXME (treeview
, "Unimplemented msg TVM_SETSCROLLTIME\n");
1847 case TVM_GETSCROLLTIME
:
1848 FIXME (treeview
, "Unimplemented msg TVM_GETSCROLLTIME\n");
1851 case TVM_SETINSERTMARKCOLOR
:
1852 FIXME (treeview
, "Unimplemented msg TVM_SETINSERTMARKCOLOR\n");
1855 case TVM_SETUNICODEFORMAT
:
1856 FIXME (treeview
, "Unimplemented msg TVM_SETUNICODEFORMAT\n");
1859 case TVM_GETUNICODEFORMAT
:
1860 FIXME (treeview
, "Unimplemented msg TVM_GETUNICODEFORMAT\n");
1863 /* case WM_COMMAND: */
1866 return TREEVIEW_Create (wndPtr
, wParam
, lParam
);
1869 return TREEVIEW_Destroy (wndPtr
);
1871 /* case WM_ENABLE: */
1874 return TREEVIEW_EraseBackground (wndPtr
, wParam
, lParam
);
1877 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
1880 return TREEVIEW_Paint (wndPtr
, wParam
);
1883 return TREEVIEW_GetFont (wndPtr
, wParam
, lParam
);
1886 return TREEVIEW_SetFont (wndPtr
, wParam
, lParam
);
1889 return TREEVIEW_KeyDown (wndPtr
, wParam
, lParam
);
1892 /* case WM_KILLFOCUS: */
1893 /* case WM_SETFOCUS: */
1896 case WM_LBUTTONDOWN
:
1897 return TREEVIEW_LButtonDown (wndPtr
, wParam
, lParam
);
1899 case WM_LBUTTONDBLCLK
:
1900 return TREEVIEW_LButtonDoubleClick (wndPtr
, wParam
, lParam
);
1902 case WM_RBUTTONDOWN
:
1903 return TREEVIEW_RButtonDown (wndPtr
, wParam
, lParam
);
1906 /* case WM_SYSCOLORCHANGE: */
1907 /* case WM_STYLECHANGED: */
1908 /* case WM_SETREDRAW: */
1911 return TREEVIEW_HandleTimer (wndPtr
, wParam
, lParam
);
1915 return TREEVIEW_HScroll (wndPtr
, wParam
, lParam
);
1917 return TREEVIEW_VScroll (wndPtr
, wParam
, lParam
);
1920 if (uMsg
>= WM_USER
)
1921 FIXME (treeview
, "Unknown msg %04x wp=%08x lp=%08lx\n",
1922 uMsg
, wParam
, lParam
);
1923 return DefWindowProc32A (hwnd
, uMsg
, wParam
, lParam
);
1930 TREEVIEW_Register (VOID
)
1932 WNDCLASS32A wndClass
;
1934 TRACE (treeview
,"\n");
1936 if (GlobalFindAtom32A (WC_TREEVIEW32A
)) return;
1938 ZeroMemory (&wndClass
, sizeof(WNDCLASS32A
));
1939 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1940 wndClass
.lpfnWndProc
= (WNDPROC32
)TREEVIEW_WindowProc
;
1941 wndClass
.cbClsExtra
= 0;
1942 wndClass
.cbWndExtra
= sizeof(TREEVIEW_INFO
*);
1943 wndClass
.hCursor
= LoadCursor32A (0, IDC_ARROW32A
);
1944 wndClass
.hbrBackground
= 0;
1945 wndClass
.lpszClassName
= WC_TREEVIEW32A
;
1947 RegisterClass32A (&wndClass
);
1952 TREEVIEW_Unregister (VOID
)
1954 if (GlobalFindAtom32A (WC_TREEVIEW32A
))
1955 UnregisterClass32A (WC_TREEVIEW32A
, (HINSTANCE32
)NULL
);