3 * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
4 * Copyright 1998,1999 Alex Priem <alexp@sci.kun.nl>
8 * list-handling stuff: sort, sorted insertitem.
9 * [should be merged with mm-handling stuff as done in listview]
11 -small array containing info about positions.
12 -better implementation of RefreshItem:
13 1) draw lines between parents
15 3) draw lines from parent<->items.
16 -implement partial drawing?
17 * -drag&drop: TVM_CREATEDRAGIMAGE should create drag bitmap.
18 * -scrollbars: horizontal scrollbar doesn't work.
22 * FIXME: check fontsize. (uRealItemHeight)
23 * test focusItem (redraw in different color)
26 better implementation.
27 * WM_HSCROLL is broken.
28 * use separate routine to get item text/image.
30 * Separate drawing/calculation.
32 * FIXMEs (for personal use)
33 Expand: -ctlmacro expands twice ->toggle.
34 -DblClick: ctlmacro.exe's NM_DBLCLK seems to go wrong (returns FALSE).
35 -treehelper: stack corruption makes big window.
47 /* ffs should be in <string.h>. */
49 /* Defines, since they do not need to return previous state, and nr
50 * has no side effects in this file.
52 #define tv_test_bit(nr,bf) (((LPBYTE)bf)[nr>>3]&(1<<(nr&7)))
53 #define tv_set_bit(nr,bf) ((LPBYTE)bf)[nr>>3]|=(1<<(nr&7))
54 #define tv_clear_bit(nr,bf) ((LPBYTE)bf)[nr>>3]&=~(1<<(nr&7))
57 #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
60 TREEVIEW_SendSimpleNotify (WND *wndPtr, UINT code);
62 TREEVIEW_SendTreeviewNotify (WND *wndPtr, UINT code, UINT action,
63 HTREEITEM oldItem, HTREEITEM newItem);
65 TREEVIEW_SendTreeviewDnDNotify (WND *wndPtr, UINT code, HTREEITEM dragItem,
68 TREEVIEW_SendDispInfoNotify (WND *wndPtr, TREEVIEW_ITEM *wineItem,
69 UINT code, UINT what);
71 TREEVIEW_SendCustomDrawNotify (WND *wndPtr, DWORD dwDrawStage, HDC hdc,
74 TREEVIEW_SendCustomDrawItemNotify (WND *wndPtr, HDC hdc,
75 TREEVIEW_ITEM *tvItem, UINT uItemDrawState);
77 TREEVIEW_DoSelectItem (WND *wndPtr, INT action, HTREEITEM newSelect, INT cause);
79 TREEVIEW_Refresh (WND *wndPtr);
81 static LRESULT CALLBACK
82 TREEVIEW_Edit_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam,
89 /* helper functions. Work with the assumption that validity of operands
90 is checked beforehand, and that tree state is valid. */
92 /* FIXME: MS documentation says `GetNextVisibleItem' returns NULL
93 if not succesfull'. Probably only applies to derefencing infoPtr
94 (ie we are offered a valid treeview structure)
95 and not whether there is a next `visible' child.
96 FIXME: check other failures.
101 static TREEVIEW_ITEM *
102 TREEVIEW_ValidItem (TREEVIEW_INFO *infoPtr,HTREEITEM handle)
105 if ((!handle) || (handle>infoPtr->uMaxHandle)) return NULL;
106 if (tv_test_bit ((INT)handle, infoPtr->freeList)) return NULL;
108 return & infoPtr->items[(INT)handle];
113 static TREEVIEW_ITEM *TREEVIEW_GetPrevListItem (TREEVIEW_INFO *infoPtr,
114 TREEVIEW_ITEM *tvItem)
117 TREEVIEW_ITEM *wineItem;
119 if (tvItem->upsibling) {
120 wineItem=& infoPtr->items[(INT)tvItem->upsibling];
121 if ((wineItem->firstChild) && (wineItem->state & TVIS_EXPANDED)) {
122 wineItem=& infoPtr->items[(INT)wineItem->firstChild];
123 while (wineItem->sibling)
124 wineItem= & infoPtr->items[(INT)wineItem->sibling];
130 while (wineItem->parent) {
131 wineItem=& infoPtr->items[(INT)wineItem->parent];
132 if (wineItem->upsibling)
133 return (& infoPtr->items[(INT)wineItem->upsibling]);
140 static TREEVIEW_ITEM *TREEVIEW_GetNextListItem (TREEVIEW_INFO *infoPtr,
141 TREEVIEW_ITEM *tvItem)
144 TREEVIEW_ITEM *wineItem;
146 if ((tvItem->firstChild) && (tvItem->state & TVIS_EXPANDED))
147 return (& infoPtr->items[(INT)tvItem->firstChild]);
151 return (& infoPtr->items[(INT)tvItem->sibling]);
154 while (wineItem->parent) {
155 wineItem=& infoPtr->items [(INT)wineItem->parent];
156 if (wineItem->sibling)
157 return (& infoPtr->items [(INT)wineItem->sibling]);
160 return NULL; /* was wineItem */
163 static TREEVIEW_ITEM *TREEVIEW_GetLastListItem (TREEVIEW_INFO *infoPtr,
164 TREEVIEW_ITEM *tvItem)
167 TREEVIEW_ITEM *wineItem;
170 while (wineItem->sibling)
171 wineItem=& infoPtr->items [(INT)wineItem->sibling];
177 static void TREEVIEW_RemoveAllChildren (WND *wndPtr,
178 TREEVIEW_ITEM *parentItem)
181 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
182 TREEVIEW_ITEM *killItem;
185 kill=(INT)parentItem->firstChild;
187 tv_set_bit ( kill, infoPtr->freeList);
188 killItem=& infoPtr->items[kill];
189 if (killItem->pszText!=LPSTR_TEXTCALLBACKA)
190 COMCTL32_Free (killItem->pszText);
191 TREEVIEW_SendTreeviewNotify (wndPtr, TVN_DELETEITEM, 0, (HTREEITEM)kill, 0);
192 if (killItem->firstChild)
193 TREEVIEW_RemoveAllChildren (wndPtr, killItem);
194 kill=(INT)killItem->sibling;
197 if (parentItem->cChildren>0) {
198 infoPtr->uNumItems -= parentItem->cChildren;
199 parentItem->firstChild = 0;
200 parentItem->cChildren = 0;
207 TREEVIEW_RemoveItem (WND *wndPtr, TREEVIEW_ITEM *wineItem)
210 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
211 TREEVIEW_ITEM *parentItem, *upsiblingItem, *siblingItem;
214 iItem=(INT)wineItem->hItem;
215 tv_set_bit(iItem,infoPtr->freeList);
216 infoPtr->uNumItems--;
218 if (wineItem->pszText!=LPSTR_TEXTCALLBACKA)
219 COMCTL32_Free (wineItem->pszText);
221 TREEVIEW_SendTreeviewNotify (wndPtr, TVN_DELETEITEM, 0, (HTREEITEM)iItem, 0);
223 if (wineItem->firstChild)
224 TREEVIEW_RemoveAllChildren (wndPtr,wineItem);
226 if (wineItem->parent) {
227 parentItem=& infoPtr->items [(INT)wineItem->parent];
228 switch (parentItem->cChildren) {
229 case I_CHILDRENCALLBACK:
230 FIXME (treeview,"we don't handle I_CHILDRENCALLBACK yet\n");
233 parentItem->cChildren=0;
234 parentItem->firstChild=0;
237 parentItem->cChildren--;
238 if ((INT)parentItem->firstChild==iItem)
239 parentItem->firstChild=wineItem->sibling;
243 if (iItem==(INT)infoPtr->TopRootItem)
244 infoPtr->TopRootItem=(HTREEITEM)wineItem->sibling;
245 if (wineItem->upsibling) {
246 upsiblingItem=& infoPtr->items [(INT)wineItem->upsibling];
247 upsiblingItem->sibling=wineItem->sibling;
249 if (wineItem->sibling) {
250 siblingItem=& infoPtr->items [(INT)wineItem->sibling];
251 siblingItem->upsibling=wineItem->upsibling;
259 /* Note:TREEVIEW_RemoveTree doesn't remove infoPtr itself */
261 static void TREEVIEW_RemoveTree (WND *wndPtr)
264 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
265 TREEVIEW_ITEM *killItem;
268 for (i=1; i<=(INT)infoPtr->uMaxHandle; i++)
269 if (!tv_test_bit (i, infoPtr->freeList)) {
270 killItem=& infoPtr->items [i];
271 if (killItem->pszText!=LPSTR_TEXTCALLBACKA)
272 COMCTL32_Free (killItem->pszText);
273 TREEVIEW_SendTreeviewNotify
274 (wndPtr, TVN_DELETEITEM, 0, killItem->hItem, 0);
277 if (infoPtr->uNumPtrsAlloced) {
278 COMCTL32_Free (infoPtr->items);
279 COMCTL32_Free (infoPtr->freeList);
280 infoPtr->uNumItems=0;
281 infoPtr->uNumPtrsAlloced=0;
282 infoPtr->uMaxHandle=0;
293 TREEVIEW_GetImageList (WND *wndPtr, WPARAM wParam, LPARAM lParam)
295 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
297 TRACE (treeview,"\n");
298 if (infoPtr==NULL) return 0;
300 if ((INT)wParam == TVSIL_NORMAL)
301 return (LRESULT) infoPtr->himlNormal;
302 if ((INT)wParam == TVSIL_STATE)
303 return (LRESULT) infoPtr->himlState;
309 TREEVIEW_SetImageList (WND *wndPtr, WPARAM wParam, LPARAM lParam)
311 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
314 TRACE (treeview,"\n");
315 switch ((INT)wParam) {
317 himlTemp = infoPtr->himlNormal;
318 infoPtr->himlNormal = (HIMAGELIST)lParam;
319 return (LRESULT)himlTemp;
322 himlTemp = infoPtr->himlState;
323 infoPtr->himlState = (HIMAGELIST)lParam;
324 return (LRESULT)himlTemp;
327 return (LRESULT)NULL;
333 TREEVIEW_SetItemHeight (WND *wndPtr, WPARAM wParam)
335 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
336 INT cx,cy,prevHeight=infoPtr->uItemHeight;
339 TRACE (treeview,"\n");
341 hdc=GetDC (wndPtr->hwndSelf);
342 infoPtr->uItemHeight=-1;
346 ImageList_GetIconSize (infoPtr->himlNormal, &cx, &cy);
348 if (wParam>cy) cy=wParam;
349 infoPtr->uItemHeight=cy;
351 if (!(wndPtr->dwStyle & TVS_NONEVENHEIGHT))
352 infoPtr->uItemHeight = (INT) wParam & 0xfffffffe;
357 TREEVIEW_GetItemHeight (WND *wndPtr)
359 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
361 TRACE (treeview,"\n");
362 return infoPtr->uItemHeight;
366 TREEVIEW_SetTextColor (WND *wndPtr, WPARAM wParam, LPARAM lParam)
368 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
369 COLORREF prevColor=infoPtr->clrText;
371 TRACE (treeview,"\n");
372 infoPtr->clrText=(COLORREF) lParam;
373 return (LRESULT) prevColor;
377 TREEVIEW_GetBkColor (WND *wndPtr)
379 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
381 TRACE (treeview,"\n");
382 return (LRESULT) infoPtr->clrText;
386 TREEVIEW_SetBkColor (WND *wndPtr, WPARAM wParam, LPARAM lParam)
388 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
389 COLORREF prevColor=infoPtr->clrBk;
391 TRACE (treeview,"\n");
392 infoPtr->clrBk=(COLORREF) lParam;
393 return (LRESULT) prevColor;
397 TREEVIEW_GetTextColor (WND *wndPtr)
399 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
401 TRACE (treeview,"\n");
402 return (LRESULT) infoPtr->clrBk;
409 /* FIXME: draw background (infoPtr->clrBk) */
412 /* cdmode: custom draw mode as received from app. in first NMCUSTOMDRAW
416 TREEVIEW_DrawItem (WND *wndPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
419 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
420 INT oldBkMode,center,xpos,cx,cy, cditem, drawmode;
421 TREEVIEW_ITEM *parentItem;
424 UINT uTextJustify = DT_LEFT;
425 HPEN hOldPen, hnewPen;
430 if (wineItem->state & TVIS_BOLD)
431 hOldFont = SelectObject (hdc, infoPtr->hBoldFont);
433 hOldFont = SelectObject (hdc, infoPtr->hFont);
436 if (infoPtr->cdmode & CDRF_NOTIFYITEMDRAW) {
437 drawmode=CDDS_ITEMPREPAINT;
438 if (infoPtr->cdmode & CDRF_NOTIFYSUBITEMDRAW) drawmode|=CDDS_SUBITEM;
439 cditem=TREEVIEW_SendCustomDrawItemNotify (wndPtr, hdc, wineItem, drawmode);
440 TRACE (treeview,"cditem:%d\n",cditem);
441 if (cditem & CDRF_SKIPDEFAULT)
446 hnewPen = CreatePen(PS_DOT, 0, GetSysColor(COLOR_WINDOWTEXT) );
447 hOldPen = SelectObject( hdc, hnewPen );
450 if (wineItem->parent) {
451 parentItem=TREEVIEW_ValidItem (infoPtr, wineItem->parent);
452 upper=parentItem->rect;
458 center=(r.top+r.bottom)/2;
461 if (wndPtr->dwStyle & TVS_HASLINES) {
463 if ((wndPtr->dwStyle & TVS_LINESATROOT) && (wineItem->iLevel==0)) {
464 points[0].y=points[1].y=center;
465 points[2].y=upper.top;
466 points[1].x=points[2].x=upper.left;
467 points[0].x=upper.left+12;
470 Polyline (hdc,points,3);
473 points[0].y=points[1].y=center;
474 points[2].y=upper.top;
475 points[1].x=points[2].x=upper.left+13;
476 points[0].x=upper.left+25;
478 Polyline (hdc,points,3);
482 DeleteObject(hnewPen);
483 SelectObject(hdc, hOldPen);
485 if ((wndPtr->dwStyle & TVS_HASBUTTONS) && (wndPtr->dwStyle & TVS_HASLINES) &&
486 (wineItem->cChildren)) {
487 Rectangle (hdc, xpos-4, center-4, xpos+5, center+5);
488 MoveToEx (hdc, xpos-2, center, NULL);
489 LineTo (hdc, xpos+3, center);
490 if (!(wineItem->state & TVIS_EXPANDED)) {
491 MoveToEx (hdc, xpos, center-2, NULL);
492 LineTo (hdc, xpos, center+3);
499 if (wineItem->mask & (TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
502 if (infoPtr->himlNormal) himlp=&infoPtr->himlNormal;
504 if ((wineItem->state & TVIS_SELECTED) && (wineItem->iSelectedImage)) {
505 if (infoPtr->himlState) himlp=&infoPtr->himlState;
506 if (wineItem->iSelectedImage==I_IMAGECALLBACK)
507 TREEVIEW_SendDispInfoNotify (wndPtr, wineItem,
508 TVN_GETDISPINFO, TVIF_SELECTEDIMAGE);
509 } else { /* NOT selected */
510 if (wineItem->iImage==I_IMAGECALLBACK)
511 TREEVIEW_SendDispInfoNotify (wndPtr, wineItem,
512 TVN_GETDISPINFO, TVIF_IMAGE);
516 ImageList_Draw (*himlp, wineItem->iImage, hdc, xpos-2, r.top+1, ILD_NORMAL);
517 ImageList_GetIconSize (*himlp, &cx, &cy);
524 if ((wineItem->mask & TVIF_TEXT) && (wineItem->pszText)) {
526 if (wineItem->state & (TVIS_SELECTED | TVIS_DROPHILITED) ) {
527 oldBkMode = SetBkMode(hdc, OPAQUE);
528 oldBkColor= SetBkColor (hdc, GetSysColor( COLOR_HIGHLIGHT));
529 SetTextColor (hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
531 oldBkMode = SetBkMode(hdc, TRANSPARENT);
535 wineItem->text.left=r.left;
536 wineItem->text.right=r.right;
537 if (infoPtr->clrText==-1)
538 SetTextColor (hdc, COLOR_BTNTEXT);
540 SetTextColor (hdc, infoPtr->clrText); /* FIXME: setback retval */
542 if (wineItem->pszText== LPSTR_TEXTCALLBACKA) {
543 TRACE (treeview,"LPSTR_TEXTCALLBACK\n");
544 TREEVIEW_SendDispInfoNotify (wndPtr, wineItem,
545 TVN_GETDISPINFO, TVIF_TEXT);
548 DrawTextA (hdc, wineItem->pszText, lstrlenA(wineItem->pszText), &r,
549 uTextJustify|DT_VCENTER|DT_SINGLELINE);
551 if (oldBkMode != TRANSPARENT)
552 SetBkMode(hdc, oldBkMode);
553 if (wineItem->state & (TVIS_SELECTED | TVIS_DROPHILITED))
554 SetBkColor (hdc, oldBkColor);
557 if (cditem & CDRF_NOTIFYPOSTPAINT)
558 TREEVIEW_SendCustomDrawItemNotify (wndPtr, hdc, wineItem,
561 SelectObject (hdc, hOldFont);
571 TREEVIEW_GetItemRect (WND *wndPtr, WPARAM wParam, LPARAM lParam)
573 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
574 TREEVIEW_ITEM *wineItem;
578 TRACE (treeview,"\n");
579 if (infoPtr==NULL) return FALSE;
581 if (infoPtr->Timer & TV_REFRESH_TIMER_SET)
582 TREEVIEW_Refresh (wndPtr); /* we want a rect for the current view */
584 iItem = (HTREEITEM *) lParam;
585 wineItem = TREEVIEW_ValidItem (infoPtr, *iItem);
586 if (!wineItem) return FALSE;
588 wineItem=& infoPtr->items[ (INT)*iItem ];
589 if (!wineItem->visible) return FALSE;
591 lpRect = (LPRECT)lParam;
592 if (lpRect == NULL) return FALSE;
595 lpRect->left = wineItem->text.left;
596 lpRect->right = wineItem->text.right;
597 lpRect->bottom = wineItem->text.bottom;
598 lpRect->top = wineItem->text.top;
600 lpRect->left = wineItem->rect.left;
601 lpRect->right = wineItem->rect.right;
602 lpRect->bottom = wineItem->rect.bottom;
603 lpRect->top = wineItem->rect.top;
606 TRACE (treeview,"[L:%d R:%d T:%d B:%d]\n", lpRect->left,lpRect->right,
607 lpRect->top,lpRect->bottom);
614 TREEVIEW_GetVisibleCount (WND *wndPtr, WPARAM wParam, LPARAM lParam)
617 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
619 return (LRESULT) infoPtr->uVisibleHeight / infoPtr->uRealItemHeight;
625 TREEVIEW_SetItemA (WND *wndPtr, WPARAM wParam, LPARAM lParam)
627 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
628 TREEVIEW_ITEM *wineItem;
632 tvItem=(LPTVITEMEXA) lParam;
633 iItem=(INT)tvItem->hItem;
634 TRACE (treeview,"item %d,mask %x\n",iItem,tvItem->mask);
636 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
637 if (!wineItem) return FALSE;
639 if (tvItem->mask & TVIF_CHILDREN) {
640 wineItem->cChildren=tvItem->cChildren;
643 if (tvItem->mask & TVIF_IMAGE) {
644 wineItem->iImage=tvItem->iImage;
647 if (tvItem->mask & TVIF_INTEGRAL) {
648 wineItem->iIntegral=tvItem->iIntegral;
649 FIXME (treeview," TVIF_INTEGRAL not supported yet\n");
652 if (tvItem->mask & TVIF_PARAM) {
653 wineItem->lParam=tvItem->lParam;
656 if (tvItem->mask & TVIF_SELECTEDIMAGE) {
657 wineItem->iSelectedImage=tvItem->iSelectedImage;
660 if (tvItem->mask & TVIF_STATE) {
661 wineItem->state=tvItem->state & tvItem->stateMask;
664 if (tvItem->mask & TVIF_TEXT) {
665 if (tvItem->pszText!=LPSTR_TEXTCALLBACKA) {
666 len=lstrlenA (tvItem->pszText);
667 if (len>wineItem->cchTextMax)
668 wineItem->pszText= COMCTL32_ReAlloc (wineItem->pszText, len+1);
669 lstrcpynA (wineItem->pszText, tvItem->pszText,len);
671 if (wineItem->cchTextMax) {
672 COMCTL32_Free (wineItem->pszText);
673 wineItem->cchTextMax=0;
675 wineItem->pszText=LPSTR_TEXTCALLBACKA;
687 TREEVIEW_Refresh (WND *wndPtr)
690 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
695 INT iItem, indent, x, y, cx, height, itemHeight;
696 INT viewtop,viewbottom,viewleft,viewright;
697 TREEVIEW_ITEM *wineItem, *prevItem;
699 TRACE (treeview,"\n");
701 hdc=GetDC (wndPtr->hwndSelf);
703 if (infoPtr->Timer & TV_REFRESH_TIMER_SET) {
704 KillTimer (wndPtr->hwndSelf, TV_REFRESH_TIMER);
705 infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
709 GetClientRect (wndPtr->hwndSelf, &rect);
710 if ((rect.left-rect.right ==0) || (rect.top-rect.bottom==0)) return;
712 infoPtr->cdmode=TREEVIEW_SendCustomDrawNotify
713 (wndPtr, CDDS_PREPAINT, hdc, rect);
715 if (infoPtr->cdmode==CDRF_SKIPDEFAULT) {
716 ReleaseDC (wndPtr->hwndSelf, hdc);
720 infoPtr->uVisibleHeight= rect.bottom-rect.top;
721 infoPtr->uVisibleWidth= rect.right-rect.left;
724 viewbottom=infoPtr->cy + rect.bottom-rect.top;
725 viewleft=infoPtr->cx;
726 viewright=infoPtr->cx + rect.right-rect.left;
730 /* draw background */
732 hbrBk = GetSysColorBrush (COLOR_WINDOW);
733 FillRect(hdc, &rect, hbrBk);
736 iItem=(INT)infoPtr->TopRootItem;
737 infoPtr->firstVisible=0;
741 TRACE (treeview, "[%d %d %d %d]\n",viewtop,viewbottom,viewleft,viewright);
745 wineItem= & infoPtr->items[iItem];
746 wineItem->iLevel=indent;
748 ImageList_GetIconSize (infoPtr->himlNormal, &cx, &itemHeight);
749 if (infoPtr->uItemHeight>itemHeight)
750 itemHeight=infoPtr->uItemHeight;
752 GetTextMetricsA (hdc, &tm);
753 if ((tm.tmHeight + tm.tmExternalLeading) > itemHeight)
754 itemHeight=tm.tmHeight + tm.tmExternalLeading;
756 infoPtr->uRealItemHeight=itemHeight;
759 /* FIXME: remove this in later stage */
761 if (wineItem->pszText!=LPSTR_TEXTCALLBACK32A)
762 TRACE (treeview, "%d %d [%d %d %d %d] (%s)\n",y,x,
763 wineItem->rect.top, wineItem->rect.bottom,
764 wineItem->rect.left, wineItem->rect.right,
767 TRACE (treeview, "%d [%d %d %d %d] (CALLBACK)\n",
769 wineItem->rect.top, wineItem->rect.bottom,
770 wineItem->rect.left, wineItem->rect.right);
773 height=itemHeight * wineItem->iIntegral +1;
774 if ((y >= viewtop) && (y <= viewbottom) &&
775 (x >= viewleft ) && (x <= viewright)) {
776 wineItem->visible = TRUE;
777 wineItem->rect.top = y - infoPtr->cy + rect.top;
778 wineItem->rect.bottom = wineItem->rect.top + height ;
779 wineItem->rect.left = x - infoPtr->cx + rect.left;
780 wineItem->rect.right = rect.right;
781 wineItem->text.left = wineItem->rect.left;
782 wineItem->text.top = wineItem->rect.top;
783 wineItem->text.right= wineItem->rect.right;
784 wineItem->text.bottom=wineItem->rect.bottom;
785 if (!infoPtr->firstVisible)
786 infoPtr->firstVisible=wineItem->hItem;
787 TREEVIEW_DrawItem (wndPtr, hdc, wineItem);
790 wineItem->visible = FALSE;
791 wineItem->rect.left = wineItem->rect.top = 0;
792 wineItem->rect.right= wineItem->rect.bottom = 0;
793 wineItem->text.left = wineItem->text.top = 0;
794 wineItem->text.right= wineItem->text.bottom = 0;
797 /* look up next item */
799 if ((wineItem->firstChild) && (wineItem->state & TVIS_EXPANDED)) {
800 iItem=(INT)wineItem->firstChild;
803 if (x>infoPtr->uTotalWidth)
804 infoPtr->uTotalWidth=x;
807 iItem=(INT)wineItem->sibling;
808 while ((!iItem) && (indent>0)) {
812 wineItem=&infoPtr->items[(INT)wineItem->parent];
813 iItem=(INT)wineItem->sibling;
819 /* FIXME: infoPtr->uTotalWidth should also take item label into account */
820 /* FIXME: or should query item sizes (ie check CDRF_NEWFONT) */
822 infoPtr->uTotalHeight=y;
823 if (y >= (viewbottom-viewtop)) {
824 if (!(infoPtr->uInternalStatus & TV_VSCROLL))
825 ShowScrollBar (wndPtr->hwndSelf, SB_VERT, TRUE);
826 infoPtr->uInternalStatus |=TV_VSCROLL;
827 SetScrollRange (wndPtr->hwndSelf, SB_VERT, 0,
828 y - infoPtr->uVisibleHeight, FALSE);
829 SetScrollPos (wndPtr->hwndSelf, SB_VERT, infoPtr->cy, TRUE);
832 if (infoPtr->uInternalStatus & TV_VSCROLL)
833 ShowScrollBar (wndPtr->hwndSelf, SB_VERT, FALSE);
834 infoPtr->uInternalStatus &= ~TV_VSCROLL;
838 if (infoPtr->cdmode & CDRF_NOTIFYPOSTPAINT)
839 infoPtr->cdmode=TREEVIEW_SendCustomDrawNotify
840 (wndPtr, CDDS_POSTPAINT, hdc, rect);
842 ReleaseDC (wndPtr->hwndSelf, hdc);
843 TRACE (treeview,"done\n");
848 TREEVIEW_HandleTimer ( WND *wndPtr, WPARAM wParam, LPARAM lParam)
850 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
852 TRACE (treeview, " %d\n",wParam);
853 if (!infoPtr) return FALSE;
856 case TV_REFRESH_TIMER:
857 KillTimer (wndPtr->hwndSelf, TV_REFRESH_TIMER);
858 infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
859 SendMessageA (wndPtr->hwndSelf, WM_PAINT, 0, 0);
862 KillTimer (wndPtr->hwndSelf, TV_EDIT_TIMER);
863 infoPtr->Timer &= ~TV_EDIT_TIMER_SET;
866 ERR (treeview,"got unknown timer\n");
874 TREEVIEW_QueueRefresh (WND *wndPtr)
877 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
879 TRACE (treeview,"\n");
880 if (infoPtr->Timer & TV_REFRESH_TIMER_SET) {
881 KillTimer (wndPtr->hwndSelf, TV_REFRESH_TIMER);
884 SetTimer (wndPtr->hwndSelf, TV_REFRESH_TIMER, TV_REFRESH_DELAY, 0);
885 infoPtr->Timer|=TV_REFRESH_TIMER_SET;
891 TREEVIEW_GetItemA (WND *wndPtr, WPARAM wParam, LPARAM lParam)
893 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
895 TREEVIEW_ITEM *wineItem;
898 tvItem=(LPTVITEMEXA) lParam;
899 iItem=(INT)tvItem->hItem;
900 TRACE (treeview,"item %d<%p>, txt %p, img %p, action %x\n", iItem,
901 tvItem, tvItem->pszText, & tvItem->iImage, tvItem->mask);
903 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
904 if (!wineItem) return FALSE;
906 if (tvItem->mask & TVIF_CHILDREN) {
907 if (TVIF_CHILDREN==I_CHILDRENCALLBACK)
908 FIXME (treeview,"I_CHILDRENCALLBACK not supported\n");
909 tvItem->cChildren=wineItem->cChildren;
912 if (tvItem->mask & TVIF_HANDLE) {
913 tvItem->hItem=wineItem->hItem;
916 if (tvItem->mask & TVIF_IMAGE) {
917 tvItem->iImage=wineItem->iImage;
920 if (tvItem->mask & TVIF_INTEGRAL) {
921 tvItem->iIntegral=wineItem->iIntegral;
922 FIXME (treeview," TVIF_INTEGRAL not supported yet\n");
925 if (tvItem->mask & TVIF_PARAM) {
926 tvItem->lParam=wineItem->lParam;
929 if (tvItem->mask & TVIF_SELECTEDIMAGE) {
930 tvItem->iSelectedImage=wineItem->iSelectedImage;
933 if (tvItem->mask & TVIF_STATE) {
934 tvItem->state=wineItem->state & tvItem->stateMask;
937 if (tvItem->mask & TVIF_TEXT) {
938 if (wineItem->pszText == LPSTR_TEXTCALLBACKA) {
939 tvItem->pszText = LPSTR_TEXTCALLBACKA; /* FIXME:send notification? */
940 ERR (treeview," GetItem called with LPSTR_TEXTCALLBACK\n");
942 else if (wineItem->pszText) {
943 lstrcpynA (tvItem->pszText, wineItem->pszText, tvItem->cchTextMax);
952 /* FIXME: check implementation of TVGN_NEXT/TVGN_NEXTVISIBLE */
955 TREEVIEW_GetNextItem (WND *wndPtr, WPARAM wParam, LPARAM lParam)
958 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
959 TREEVIEW_ITEM *wineItem, *returnItem;
960 INT iItem, retval, flag;
963 if (!infoPtr) return FALSE;
965 iItem = (INT) lParam;
968 case TVGN_ROOT: retval=(INT)infoPtr->TopRootItem;
970 case TVGN_CARET:retval=(INT)infoPtr->selectedItem;
972 case TVGN_FIRSTVISIBLE:
973 TREEVIEW_Refresh (wndPtr);
974 /* FIXME:we should only recalculate, not redraw */
975 retval=(INT)infoPtr->firstVisible;
977 case TVGN_DROPHILITE:
978 retval=(INT)infoPtr->dropItem;
982 TRACE (treeview,"flags:%x, returns %u\n", flag, retval);
986 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
988 if (!wineItem) return FALSE;
991 case TVGN_NEXT: retval=(INT)wineItem->sibling;
994 retval=(INT)wineItem->upsibling;
997 retval=(INT)wineItem->parent;
1000 retval=(INT)wineItem->firstChild;
1002 case TVGN_LASTVISIBLE:
1003 returnItem=TREEVIEW_GetLastListItem (infoPtr,wineItem);
1005 case TVGN_NEXTVISIBLE:
1006 returnItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
1008 case TVGN_PREVIOUSVISIBLE:
1009 returnItem=TREEVIEW_GetPrevListItem (infoPtr, wineItem);
1011 default: FIXME (treeview,"Unknown msg %x,item %x\n", flag,iItem);
1016 TRACE (treeview,"flags:%x, item %d;returns %d\n", flag, iItem,
1017 (INT)returnItem->hItem);
1018 return (INT)returnItem->hItem;
1021 TRACE (treeview,"flags:%x, item %d;returns %d\n", flag, iItem,retval);
1027 TREEVIEW_GetCount (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1029 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1031 TRACE (treeview," %d\n",infoPtr->uNumItems);
1032 return (LRESULT) infoPtr->uNumItems;
1038 /* the method used below isn't the most memory-friendly, but it avoids
1039 a lot of memory reallocations */
1041 /* BTW: we waste handle 0; 0 is not an allowed handle. */
1044 TREEVIEW_InsertItemA (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1047 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1048 TVINSERTSTRUCTA *ptdi;
1050 TREEVIEW_ITEM *wineItem, *parentItem, *prevsib, *sibItem;
1051 INT iItem,listItems,i,len;
1053 ptdi = (LPTVINSERTSTRUCTA) lParam;
1055 /* check if memory is available */
1057 if (infoPtr->uNumPtrsAlloced==0) {
1058 infoPtr->items = COMCTL32_Alloc (TVITEM_ALLOC*sizeof (TREEVIEW_ITEM));
1059 infoPtr->freeList= COMCTL32_Alloc ((1+(TVITEM_ALLOC>>5)) * sizeof (INT));
1060 infoPtr->uNumPtrsAlloced=TVITEM_ALLOC;
1061 infoPtr->TopRootItem=(HTREEITEM)1;
1064 if (infoPtr->uNumItems == (infoPtr->uNumPtrsAlloced-1) ) {
1065 TREEVIEW_ITEM *oldItems = infoPtr->items;
1066 INT *oldfreeList = infoPtr->freeList;
1068 infoPtr->uNumPtrsAlloced*=2;
1069 infoPtr->items = COMCTL32_Alloc (infoPtr->uNumPtrsAlloced*sizeof (TREEVIEW_ITEM));
1070 infoPtr->freeList= COMCTL32_Alloc ((1+(infoPtr->uNumPtrsAlloced>>5))*sizeof (INT));
1072 memcpy (&infoPtr->items[0], &oldItems[0],
1073 infoPtr->uNumPtrsAlloced/2 * sizeof(TREEVIEW_ITEM));
1074 memcpy (&infoPtr->freeList[0], &oldfreeList[0],
1075 infoPtr->uNumPtrsAlloced>>6 * sizeof(INT));
1077 COMCTL32_Free (oldItems);
1078 COMCTL32_Free (oldfreeList);
1082 infoPtr->uNumItems++;
1084 if ((INT)infoPtr->uMaxHandle==(infoPtr->uNumItems-1)) {
1085 iItem=infoPtr->uNumItems;
1086 infoPtr->uMaxHandle = (HTREEITEM)((INT)infoPtr->uMaxHandle + 1);
1087 } else { /* check freelist */
1088 for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) {
1089 if (infoPtr->freeList[i]) {
1090 iItem=ffs (infoPtr->freeList[i])-1;
1091 tv_clear_bit(iItem,&infoPtr->freeList[i]);
1098 for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++)
1099 TRACE (treeview,"%8x\n",infoPtr->freeList[i]);
1101 if (!iItem) ERR (treeview, "Argh -- can't find free item.\n");
1103 tvItem= & ptdi->DUMMYUNIONNAME.itemex;
1104 wineItem=& infoPtr->items[iItem];
1106 if ((ptdi->hParent==TVI_ROOT) || (ptdi->hParent==0)) {
1109 sibItem=&infoPtr->items [(INT)infoPtr->TopRootItem];
1110 listItems=infoPtr->uNumItems;
1113 parentItem= &infoPtr->items[(INT)ptdi->hParent];
1114 if (!parentItem->firstChild)
1115 parentItem->firstChild=(HTREEITEM)iItem;
1116 wineItem->parent=ptdi->hParent;
1117 sibItem=&infoPtr->items [(INT)parentItem->firstChild];
1118 parentItem->cChildren++;
1119 listItems=parentItem->cChildren;
1122 wineItem->upsibling=0; /* needed in case we're the first item in a list */
1123 wineItem->sibling=0;
1124 wineItem->firstChild=0;
1125 wineItem->hItem=(HTREEITEM)iItem;
1129 switch ((INT)ptdi->hInsertAfter) {
1131 if (wineItem->parent) {
1132 wineItem->sibling=parentItem->firstChild;
1133 parentItem->firstChild=(HTREEITEM)iItem;
1135 wineItem->sibling=infoPtr->TopRootItem;
1136 infoPtr->TopRootItem=(HTREEITEM)iItem;
1138 sibItem->upsibling=(HTREEITEM)iItem;
1141 if (sibItem==wineItem) break;
1142 while (sibItem->sibling) {
1144 sibItem=&infoPtr->items [(INT)sibItem->sibling];
1146 sibItem->sibling=(HTREEITEM)iItem;
1147 wineItem->upsibling=sibItem->hItem;
1150 FIXME (treeview, "Sorted insert not implemented yet\n");
1153 while ((sibItem->sibling) && (sibItem->hItem!=ptdi->hInsertAfter))
1156 sibItem=&infoPtr->items [(INT)sibItem->sibling];
1158 if (sibItem->hItem!=ptdi->hInsertAfter) {
1159 ERR (treeview, "tried to insert item after nonexisting handle.\n");
1163 if (sibItem->sibling) {
1164 sibItem=&infoPtr->items [(INT)sibItem->sibling];
1165 sibItem->upsibling=(HTREEITEM)iItem;
1166 wineItem->sibling=sibItem->hItem;
1168 prevsib->sibling=(HTREEITEM)iItem;
1169 wineItem->upsibling=prevsib->hItem;
1175 /* Fill in info structure */
1177 TRACE (treeview,"new item %d; parent %d, mask %x\n", iItem,
1178 (INT)wineItem->parent,tvItem->mask);
1180 wineItem->mask=tvItem->mask;
1181 wineItem->iIntegral=1;
1183 if (tvItem->mask & TVIF_CHILDREN) {
1184 wineItem->cChildren=tvItem->cChildren;
1185 if (tvItem->cChildren==I_CHILDRENCALLBACK)
1186 FIXME (treeview," I_CHILDRENCALLBACK not supported\n");
1190 if (tvItem->mask & TVIF_IMAGE)
1191 wineItem->iImage=tvItem->iImage;
1193 /* If the application sets TVIF_INTEGRAL without
1194 supplying a TVITEMEX structure, it's toast */
1196 if (tvItem->mask & TVIF_INTEGRAL)
1197 wineItem->iIntegral=tvItem->iIntegral;
1199 if (tvItem->mask & TVIF_PARAM)
1200 wineItem->lParam=tvItem->lParam;
1202 if (tvItem->mask & TVIF_SELECTEDIMAGE)
1203 wineItem->iSelectedImage=tvItem->iSelectedImage;
1205 if (tvItem->mask & TVIF_STATE) {
1206 wineItem->state=tvItem->state;
1207 wineItem->stateMask=tvItem->stateMask;
1210 if (tvItem->mask & TVIF_TEXT) {
1211 if (tvItem->pszText!=LPSTR_TEXTCALLBACKA) {
1212 TRACE (treeview,"(%p,%s)\n", &tvItem->pszText, tvItem->pszText);
1213 len = lstrlenA (tvItem->pszText)+1;
1214 wineItem->pszText= COMCTL32_Alloc (len+1);
1215 lstrcpyA (wineItem->pszText, tvItem->pszText);
1216 wineItem->cchTextMax=len;
1219 TRACE (treeview,"LPSTR_TEXTCALLBACK\n");
1220 wineItem->pszText = LPSTR_TEXTCALLBACKA;
1221 wineItem->cchTextMax = 0;
1225 TREEVIEW_QueueRefresh (wndPtr);
1227 return (LRESULT) iItem;
1235 TREEVIEW_DeleteItem (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1237 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1239 TREEVIEW_ITEM *wineItem;
1241 TRACE (treeview,"\n");
1242 if (!infoPtr) return FALSE;
1244 if (lParam == (INT)TVI_ROOT) {
1245 TREEVIEW_RemoveTree (wndPtr);
1247 iItem= (INT) lParam;
1248 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
1249 if (!wineItem) return FALSE;
1250 TRACE (treeview,"%s\n",wineItem->pszText);
1251 TREEVIEW_RemoveItem (wndPtr, wineItem);
1254 TREEVIEW_QueueRefresh (wndPtr);
1262 TREEVIEW_GetIndent (WND *wndPtr)
1264 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1266 TRACE (treeview,"\n");
1267 return infoPtr->uIndent;
1271 TREEVIEW_SetIndent (WND *wndPtr, WPARAM wParam)
1273 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1276 TRACE (treeview,"\n");
1277 newIndent=(INT) wParam;
1278 if (newIndent < MINIMUM_INDENT) newIndent=MINIMUM_INDENT;
1279 infoPtr->uIndent=newIndent;
1285 TREEVIEW_GetToolTips (WND *wndPtr)
1288 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1290 TRACE (treeview,"\n");
1291 return infoPtr->hwndToolTip;
1296 TREEVIEW_SetToolTips (WND *wndPtr, WPARAM wParam)
1299 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1302 TRACE (treeview,"\n");
1303 prevToolTip=infoPtr->hwndToolTip;
1304 infoPtr->hwndToolTip= (HWND) wParam;
1311 TREEVIEW_GetEditControl (WND *wndPtr)
1314 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1316 return infoPtr->hwndEdit;
1320 TREEVIEW_Edit_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam,
1324 case WM_ERASEBKGND: {
1326 HDC hdc = (HDC) wParam;
1327 GetClientRect (hwnd, &rc);
1328 Rectangle (hdc, rc.left, rc.top, rc.right, rc.bottom);
1332 return DLGC_WANTARROWS | DLGC_WANTALLKEYS;
1334 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1340 /* should handle edit control messages here */
1343 TREEVIEW_Command (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1346 TRACE (treeview, "%x %ld\n",wParam, lParam);
1348 switch (HIWORD(wParam)) {
1350 FIXME (treeview, "got EN_UPDATE.\n");
1353 FIXME (treeview, "got EN_KILLFOCUS.\n");
1356 return SendMessageA (GetParent (wndPtr->hwndSelf),
1357 WM_COMMAND, wParam, lParam);
1366 TREEVIEW_Size (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1369 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1374 if (infoPtr->bAutoSize) {
1375 infoPtr->bAutoSize = FALSE;
1378 infoPtr->bAutoSize = TRUE;
1381 parent = GetParent (wndPtr->hwndSelf);
1382 GetClientRect(parent, &parent_rect);
1385 SetWindowPos (wndPtr->hwndSelf, 0, parent_rect.left, parent_rect.top,
1386 cx, cy, SWP_NOZORDER);
1388 FIXME (treeview,"WM_SIZE flag %x %lx not handled\n", wParam, lParam);
1391 TREEVIEW_QueueRefresh (wndPtr);
1398 TREEVIEW_StyleChanged (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1400 LPSTYLESTRUCT lpss=(LPSTYLESTRUCT) lParam;
1402 TRACE (treeview,"(%x %lx)\n",wParam,lParam);
1404 if (wParam & (GWL_STYLE))
1405 wndPtr->dwStyle=lpss->styleNew;
1406 if (wParam & (GWL_EXSTYLE))
1407 wndPtr->dwExStyle=lpss->styleNew;
1413 TREEVIEW_Create (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1415 TREEVIEW_INFO *infoPtr;
1420 TRACE (treeview,"wnd %x\n",wndPtr->hwndSelf);
1421 /* allocate memory for info structure */
1422 infoPtr = (TREEVIEW_INFO *) COMCTL32_Alloc (sizeof(TREEVIEW_INFO));
1424 wndPtr->wExtra[0] = (DWORD)infoPtr;
1426 if (infoPtr == NULL) {
1427 ERR (treeview, "could not allocate info memory!\n");
1431 if ((TREEVIEW_INFO*)wndPtr->wExtra[0] != infoPtr) {
1432 ERR (treeview, "pointer assignment error!\n");
1436 hdc=GetDC (wndPtr->hwndSelf);
1438 /* set default settings */
1439 infoPtr->uInternalStatus=0;
1440 infoPtr->uNumItems=0;
1441 infoPtr->clrBk = GetSysColor (COLOR_WINDOW);
1442 infoPtr->clrText = GetSysColor (COLOR_BTNTEXT);
1445 infoPtr->uIndent = 15;
1446 infoPtr->himlNormal = NULL;
1447 infoPtr->himlState = NULL;
1448 infoPtr->uItemHeight = -1;
1449 GetTextMetricsA (hdc, &tm);
1450 infoPtr->hFont = GetStockObject (DEFAULT_GUI_FONT);
1451 GetObjectA (infoPtr->hFont, sizeof (LOGFONTA), &logFont);
1452 logFont.lfWeight=FW_BOLD;
1453 infoPtr->hBoldFont = CreateFontIndirectA (&logFont);
1455 infoPtr->items = NULL;
1456 infoPtr->selectedItem=0;
1457 infoPtr->clrText=-1; /* use system color */
1458 infoPtr->dropItem=0;
1461 infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
1462 infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
1465 infoPtr->hwndToolTip=0;
1466 if (!(wndPtr->dwStyle & TVS_NOTOOLTIPS)) { /* Create tooltip control */
1469 infoPtr->hwndToolTip =
1470 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
1471 CW_USEDEFAULT, CW_USEDEFAULT,
1472 CW_USEDEFAULT, CW_USEDEFAULT,
1473 wndPtr->hwndSelf, 0, 0, 0);
1475 /* Send NM_TOOLTIPSCREATED notification */
1476 if (infoPtr->hwndToolTip) {
1477 NMTOOLTIPSCREATED nmttc;
1479 nmttc.hdr.hwndFrom = wndPtr->hwndSelf;
1480 nmttc.hdr.idFrom = wndPtr->wIDmenu;
1481 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1482 nmttc.hwndToolTips = infoPtr->hwndToolTip;
1484 SendMessageA (GetParent (wndPtr->hwndSelf), WM_NOTIFY,
1485 (WPARAM)wndPtr->wIDmenu, (LPARAM)&nmttc);
1488 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1489 ti.cbSize = sizeof(TTTOOLINFOA);
1490 ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_TRANSPARENT ;
1491 ti.hwnd = wndPtr->hwndSelf;
1493 ti.lpszText = "Test"; /* LPSTR_TEXTCALLBACK; */
1494 SetRectEmpty (&ti.rect);
1496 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA, 0, (LPARAM)&ti);
1500 infoPtr->hwndEdit = CreateWindowExA ( 0, "EDIT",NULL,
1501 WS_CHILD | WS_BORDER | ES_AUTOHSCROLL | ES_WANTRETURN,
1503 wndPtr->hwndSelf, 0,0,0);
1504 /* FIXME: (HMENU)IDTVEDIT, pcs->hInstance, 0); */
1506 SendMessageA ( infoPtr->hwndEdit, WM_SETFONT, infoPtr->hFont, FALSE);
1507 infoPtr->wpEditOrig= (WNDPROC)
1508 SetWindowLongA (infoPtr->hwndEdit,GWL_WNDPROC,
1509 (LONG) TREEVIEW_Edit_SubclassProc);
1511 ReleaseDC (wndPtr->hwndSelf, hdc);
1519 TREEVIEW_Destroy (WND *wndPtr)
1521 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1523 TRACE (treeview,"\n");
1524 TREEVIEW_RemoveTree (wndPtr);
1525 if (infoPtr->Timer & TV_REFRESH_TIMER_SET)
1526 KillTimer (wndPtr->hwndSelf, TV_REFRESH_TIMER);
1527 if (infoPtr->hwndToolTip)
1528 DestroyWindow (infoPtr->hwndToolTip);
1530 COMCTL32_Free (infoPtr);
1536 TREEVIEW_Paint (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1541 TRACE (treeview,"\n");
1542 hdc = wParam==0 ? BeginPaint (wndPtr->hwndSelf, &ps) : (HDC)wParam;
1543 TREEVIEW_Refresh (wndPtr);
1545 EndPaint (wndPtr->hwndSelf, &ps);
1546 TRACE (treeview,"done\n");
1548 return DefWindowProcA (wndPtr->hwndSelf, WM_PAINT, wParam, lParam);
1552 TREEVIEW_SetFocus (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1554 TREEVIEW_SendSimpleNotify (wndPtr, NM_SETFOCUS);
1555 SendMessageA (wndPtr->hwndSelf, WM_PAINT, 0, 0);
1560 TREEVIEW_KillFocus (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1562 TREEVIEW_SendSimpleNotify (wndPtr, NM_KILLFOCUS);
1563 SendMessageA (wndPtr->hwndSelf, WM_PAINT, 0, 0);
1568 TREEVIEW_EraseBackground (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1570 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1571 HBRUSH hBrush = CreateSolidBrush (infoPtr->clrBk);
1574 TRACE (treeview,"\n");
1575 GetClientRect (wndPtr->hwndSelf, &rect);
1576 FillRect ((HDC)wParam, &rect, hBrush);
1577 DeleteObject (hBrush);
1593 TREEVIEW_SendSimpleNotify (WND *wndPtr, UINT code)
1597 TRACE (treeview, "%x\n",code);
1598 nmhdr.hwndFrom = wndPtr->hwndSelf;
1599 nmhdr.idFrom = wndPtr->wIDmenu;
1602 return (BOOL) SendMessageA (GetParent (wndPtr->hwndSelf), WM_NOTIFY,
1603 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1609 TREEVIEW_SendTreeviewNotify (WND *wndPtr, UINT code, UINT action,
1610 HTREEITEM oldItem, HTREEITEM newItem)
1613 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1615 TREEVIEW_ITEM *wineItem;
1617 TRACE (treeview,"code:%x action:%x olditem:%x newitem:%x\n",
1618 code,action,(INT)oldItem,(INT)newItem);
1619 nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
1620 nmhdr.hdr.idFrom = wndPtr->wIDmenu;
1621 nmhdr.hdr.code = code;
1622 nmhdr.action = action;
1624 wineItem=& infoPtr->items[(INT)oldItem];
1625 nmhdr.itemOld.mask = wineItem->mask;
1626 nmhdr.itemOld.hItem = wineItem->hItem;
1627 nmhdr.itemOld.state = wineItem->state;
1628 nmhdr.itemOld.stateMask = wineItem->stateMask;
1629 nmhdr.itemOld.iImage = wineItem->iImage;
1630 nmhdr.itemOld.pszText = wineItem->pszText;
1631 nmhdr.itemOld.cchTextMax= wineItem->cchTextMax;
1632 nmhdr.itemOld.iImage = wineItem->iImage;
1633 nmhdr.itemOld.iSelectedImage = wineItem->iSelectedImage;
1634 nmhdr.itemOld.cChildren = wineItem->cChildren;
1635 nmhdr.itemOld.lParam = wineItem->lParam;
1639 wineItem=& infoPtr->items[(INT)newItem];
1640 nmhdr.itemNew.mask = wineItem->mask;
1641 nmhdr.itemNew.hItem = wineItem->hItem;
1642 nmhdr.itemNew.state = wineItem->state;
1643 nmhdr.itemNew.stateMask = wineItem->stateMask;
1644 nmhdr.itemNew.iImage = wineItem->iImage;
1645 nmhdr.itemNew.pszText = wineItem->pszText;
1646 nmhdr.itemNew.cchTextMax= wineItem->cchTextMax;
1647 nmhdr.itemNew.iImage = wineItem->iImage;
1648 nmhdr.itemNew.iSelectedImage = wineItem->iSelectedImage;
1649 nmhdr.itemNew.cChildren = wineItem->cChildren;
1650 nmhdr.itemNew.lParam = wineItem->lParam;
1656 return (BOOL)SendMessageA (GetParent (wndPtr->hwndSelf), WM_NOTIFY,
1657 (WPARAM)wndPtr->wIDmenu, (LPARAM)&nmhdr);
1662 TREEVIEW_SendTreeviewDnDNotify (WND *wndPtr, UINT code, HTREEITEM dragItem,
1665 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1667 TREEVIEW_ITEM *wineItem;
1669 TRACE (treeview,"code:%x dragitem:%x\n", code,(INT)dragItem);
1671 nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
1672 nmhdr.hdr.idFrom = wndPtr->wIDmenu;
1673 nmhdr.hdr.code = code;
1675 wineItem=& infoPtr->items[(INT)dragItem];
1676 nmhdr.itemNew.mask = wineItem->mask;
1677 nmhdr.itemNew.hItem = wineItem->hItem;
1678 nmhdr.itemNew.state = wineItem->state;
1679 nmhdr.itemNew.lParam = wineItem->lParam;
1681 nmhdr.ptDrag.x = pt.x;
1682 nmhdr.ptDrag.y = pt.y;
1684 return (BOOL)SendMessageA (GetParent (wndPtr->hwndSelf), WM_NOTIFY,
1685 (WPARAM)wndPtr->wIDmenu, (LPARAM)&nmhdr);
1692 TREEVIEW_SendDispInfoNotify (WND *wndPtr, TREEVIEW_ITEM *wineItem,
1693 UINT code, UINT what)
1699 TRACE (treeview,"item %d, action %x\n",(INT)wineItem->hItem,what);
1701 tvdi.hdr.hwndFrom = wndPtr->hwndSelf;
1702 tvdi.hdr.idFrom = wndPtr->wIDmenu;
1703 tvdi.hdr.code = code;
1704 tvdi.item.mask = what;
1705 tvdi.item.hItem = wineItem->hItem;
1706 tvdi.item.state = wineItem->state;
1707 tvdi.item.lParam = wineItem->lParam;
1708 tvdi.item.pszText = COMCTL32_Alloc (128*sizeof(char));
1709 buf = tvdi.item.pszText;
1710 retval=(BOOL)SendMessageA (GetParent (wndPtr->hwndSelf), WM_NOTIFY,
1711 (WPARAM)wndPtr->wIDmenu, (LPARAM)&tvdi);
1712 if (what & TVIF_TEXT) {
1713 wineItem->pszText = tvdi.item.pszText;
1714 if (buf==tvdi.item.pszText) {
1715 wineItem->cchTextMax = 128;
1717 TRACE (treeview,"user-supplied buffer\n");
1718 COMCTL32_Free (buf);
1719 wineItem->cchTextMax = 0;
1722 if (what & TVIF_SELECTEDIMAGE)
1723 wineItem->iSelectedImage = tvdi.item.iSelectedImage;
1724 if (what & TVIF_IMAGE)
1725 wineItem->iImage = tvdi.item.iImage;
1726 if (what & TVIF_CHILDREN)
1727 wineItem->cChildren = tvdi.item.cChildren;
1735 TREEVIEW_SendCustomDrawNotify (WND *wndPtr, DWORD dwDrawStage, HDC hdc,
1738 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1739 NMTVCUSTOMDRAW nmcdhdr;
1740 LPNMCUSTOMDRAW nmcd;
1742 TRACE (treeview,"drawstage:%lx hdc:%x\n", dwDrawStage, hdc);
1744 nmcd= & nmcdhdr.nmcd;
1745 nmcd->hdr.hwndFrom = wndPtr->hwndSelf;
1746 nmcd->hdr.idFrom = wndPtr->wIDmenu;
1747 nmcd->hdr.code = NM_CUSTOMDRAW;
1748 nmcd->dwDrawStage= dwDrawStage;
1750 nmcd->rc.left = rc.left;
1751 nmcd->rc.right = rc.right;
1752 nmcd->rc.bottom = rc.bottom;
1753 nmcd->rc.top = rc.top;
1754 nmcd->dwItemSpec = 0;
1755 nmcd->uItemState = 0;
1756 nmcd->lItemlParam= 0;
1757 nmcdhdr.clrText = infoPtr->clrText;
1758 nmcdhdr.clrTextBk= infoPtr->clrBk;
1761 return (BOOL)SendMessageA (GetParent (wndPtr->hwndSelf), WM_NOTIFY,
1762 (WPARAM)wndPtr->wIDmenu, (LPARAM)&nmcdhdr);
1768 /* FIXME: need to find out when the flags in uItemState need to be set */
1771 TREEVIEW_SendCustomDrawItemNotify (WND *wndPtr, HDC hdc,
1772 TREEVIEW_ITEM *wineItem, UINT uItemDrawState)
1774 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1775 NMTVCUSTOMDRAW nmcdhdr;
1776 LPNMCUSTOMDRAW nmcd;
1777 DWORD dwDrawStage,dwItemSpec;
1780 dwDrawStage=CDDS_ITEM | uItemDrawState;
1781 dwItemSpec=(DWORD)wineItem->hItem;
1783 if (wineItem->hItem==infoPtr->selectedItem) uItemState|=CDIS_SELECTED;
1784 if (wineItem->hItem==infoPtr->focusItem) uItemState|=CDIS_FOCUS;
1785 if (wineItem->hItem==infoPtr->hotItem) uItemState|=CDIS_HOT;
1787 nmcd= & nmcdhdr.nmcd;
1788 nmcd->hdr.hwndFrom = wndPtr->hwndSelf;
1789 nmcd->hdr.idFrom = wndPtr->wIDmenu;
1790 nmcd->hdr.code = NM_CUSTOMDRAW;
1791 nmcd->dwDrawStage= dwDrawStage;
1793 nmcd->rc.left = wineItem->rect.left;
1794 nmcd->rc.right = wineItem->rect.right;
1795 nmcd->rc.bottom = wineItem->rect.bottom;
1796 nmcd->rc.top = wineItem->rect.top;
1797 nmcd->dwItemSpec = dwItemSpec;
1798 nmcd->uItemState = uItemState;
1799 nmcd->lItemlParam= wineItem->lParam;
1801 nmcdhdr.clrText = infoPtr->clrText;
1802 nmcdhdr.clrTextBk= infoPtr->clrBk;
1803 nmcdhdr.iLevel = wineItem->iLevel;
1805 TRACE (treeview,"drawstage:%lx hdc:%x item:%lx, itemstate:%x\n",
1806 dwDrawStage, hdc, dwItemSpec, uItemState);
1808 return (BOOL)SendMessageA (GetParent (wndPtr->hwndSelf), WM_NOTIFY,
1809 (WPARAM)wndPtr->wIDmenu, (LPARAM)&nmcdhdr);
1814 /* Note:If the specified item is the child of a collapsed parent item,
1815 the parent's list of child items is (recursively) expanded to reveal the
1816 specified item. This is mentioned for TREEVIEW_SelectItem; don't
1817 know if it also applies here.
1822 TREEVIEW_Expand (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1824 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1825 TREEVIEW_ITEM *wineItem, *parentItem;
1829 flag= (UINT) wParam;
1830 expand= (INT) lParam;
1831 TRACE (treeview,"flags:%x item:%x\n", expand, wParam);
1832 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)expand);
1833 if (!wineItem) return 0;
1834 if (!wineItem->cChildren) return 0;
1836 if (wineItem->cChildren==I_CHILDRENCALLBACK) {
1837 FIXME (treeview,"we don't handle I_CHILDRENCALLBACK yet\n");
1841 if (flag & TVE_TOGGLE) { /* FIXME: check exact behaviour here */
1842 flag &= ~TVE_TOGGLE; /* ie: bitwise ops or 'case' ops */
1843 if (wineItem->state & TVIS_EXPANDED)
1844 flag |= TVE_COLLAPSE;
1850 case TVE_COLLAPSERESET:
1851 if (!wineItem->state & TVIS_EXPANDED) return 0;
1852 wineItem->state &= ~(TVIS_EXPANDEDONCE | TVIS_EXPANDED);
1853 TREEVIEW_RemoveAllChildren (wndPtr, wineItem);
1857 if (!wineItem->state & TVIS_EXPANDED) return 0;
1858 wineItem->state &= ~TVIS_EXPANDED;
1862 if (wineItem->state & TVIS_EXPANDED) return 0;
1863 if (wineItem->parent) {
1864 parentItem=TREEVIEW_ValidItem(infoPtr,wineItem->parent);
1865 TREEVIEW_Expand (wndPtr, wParam, (LPARAM) wineItem->parent);
1867 if (!(wineItem->state & TVIS_EXPANDEDONCE)) {
1868 if (TREEVIEW_SendTreeviewNotify (wndPtr, TVN_ITEMEXPANDING,
1869 0, 0, (HTREEITEM)expand))
1870 return FALSE; /* FIXME: OK? */
1871 wineItem->state |= TVIS_EXPANDED | TVIS_EXPANDEDONCE;
1872 TREEVIEW_SendTreeviewNotify (wndPtr, TVN_ITEMEXPANDED,
1873 0, 0, (HTREEITEM)expand);
1875 wineItem->state |= TVIS_EXPANDED;
1877 case TVE_EXPANDPARTIAL:
1878 FIXME (treeview, "TVE_EXPANDPARTIAL not implemented\n");
1879 wineItem->state ^=TVIS_EXPANDED;
1880 wineItem->state |=TVIS_EXPANDEDONCE;
1884 TREEVIEW_QueueRefresh (wndPtr);
1893 static TREEVIEW_ITEM *
1894 TREEVIEW_HitTestPoint (WND *wndPtr, POINT pt)
1896 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1897 TREEVIEW_ITEM *wineItem;
1900 GetClientRect (wndPtr->hwndSelf, &rect);
1902 if (!infoPtr->firstVisible) return NULL;
1904 wineItem=&infoPtr->items [(INT)infoPtr->firstVisible];
1906 while ((wineItem!=NULL) && (pt.y > wineItem->rect.bottom))
1907 wineItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
1919 TREEVIEW_HitTest (WND *wndPtr, LPARAM lParam)
1921 LPTVHITTESTINFO lpht=(LPTVHITTESTINFO) lParam;
1922 TREEVIEW_ITEM *wineItem;
1926 GetClientRect (wndPtr->hwndSelf, &rect);
1930 if (x < rect.left) status|=TVHT_TOLEFT;
1931 if (x > rect.right) status|=TVHT_TORIGHT;
1932 if (y < rect.top ) status|=TVHT_ABOVE;
1933 if (y > rect.bottom) status|=TVHT_BELOW;
1939 wineItem=TREEVIEW_HitTestPoint (wndPtr, lpht->pt);
1941 lpht->flags=TVHT_NOWHERE;
1945 if (x>wineItem->rect.right) {
1946 lpht->flags|=TVHT_ONITEMRIGHT;
1947 return (LRESULT) wineItem->hItem;
1950 if (x<wineItem->rect.left+10) lpht->flags|=TVHT_ONITEMBUTTON;
1952 lpht->flags=TVHT_ONITEMLABEL; /* FIXME: implement other flags */
1953 lpht->hItem=wineItem->hItem;
1955 return (LRESULT) wineItem->hItem;
1962 TREEVIEW_LButtonDoubleClick (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1964 TREEVIEW_ITEM *wineItem;
1967 TRACE (treeview,"\n");
1968 pt.x = (INT)LOWORD(lParam);
1969 pt.y = (INT)HIWORD(lParam);
1970 SetFocus (wndPtr->hwndSelf);
1972 wineItem=TREEVIEW_HitTestPoint (wndPtr, pt);
1973 if (!wineItem) return 0;
1974 TRACE (treeview,"item %d \n",(INT)wineItem->hItem);
1976 if (TREEVIEW_SendSimpleNotify (wndPtr, NM_DBLCLK)!=TRUE) { /* FIXME!*/
1977 wineItem->state &= ~TVIS_EXPANDEDONCE;
1978 TREEVIEW_Expand (wndPtr, (WPARAM) TVE_TOGGLE, (LPARAM) wineItem->hItem);
1986 TREEVIEW_LButtonDown (WND *wndPtr, WPARAM wParam, LPARAM lParam)
1988 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1992 ht.pt.x = (INT)LOWORD(lParam);
1993 ht.pt.y = (INT)HIWORD(lParam);
1995 SetFocus (wndPtr->hwndSelf);
1996 iItem=TREEVIEW_HitTest (wndPtr, (LPARAM) &ht);
1997 TRACE (treeview,"item %d \n",iItem);
1998 if (ht.flags & TVHT_ONITEMBUTTON) {
1999 TREEVIEW_Expand (wndPtr, (WPARAM) TVE_TOGGLE, (LPARAM) iItem);
2002 infoPtr->uInternalStatus|=TV_LDRAG;
2004 if (TREEVIEW_DoSelectItem (wndPtr, TVGN_CARET, (HTREEITEM)iItem, TVC_BYMOUSE))
2012 TREEVIEW_LButtonUp (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2014 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2015 TREEVIEW_ITEM *editItem;
2019 pt.x = (INT)LOWORD(lParam);
2020 pt.y = (INT)HIWORD(lParam);
2022 TRACE (treeview,"\n");
2023 if (TREEVIEW_SendSimpleNotify (wndPtr, NM_CLICK)) return 0;
2024 editItem=TREEVIEW_HitTestPoint (wndPtr, pt);
2025 if (!editItem) return 0;
2027 infoPtr->uInternalStatus &= ~(TV_LDRAG | TV_LDRAGGING);
2029 if (wndPtr->dwStyle & TVS_EDITLABELS) {
2031 ret=TREEVIEW_SendDispInfoNotify (wndPtr, editItem,
2032 TVN_BEGINLABELEDIT, 0);
2034 printf ("edit started..\n");
2036 infoPtr->editItem=editItem->hItem;
2037 SetWindowPos ( infoPtr->hwndEdit, HWND_TOP, r->left, r->top,
2038 r->right - r->left + 5,
2039 r->bottom - r->top + 2,
2041 SetFocus (infoPtr->hwndEdit);
2042 SetWindowTextA ( infoPtr->hwndEdit, editItem->pszText );
2043 SendMessageA ( infoPtr->hwndEdit, EM_SETSEL, 0, -1 );
2053 TREEVIEW_RButtonDown (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2055 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2057 TRACE (treeview,"\n");
2058 infoPtr->uInternalStatus|=TV_RDRAG;
2063 TREEVIEW_RButtonUp (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2065 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2067 TRACE (treeview,"\n");
2068 if (TREEVIEW_SendSimpleNotify (wndPtr, NM_RCLICK)) return 0;
2069 infoPtr->uInternalStatus&= ~(TV_RDRAG | TV_RDRAGGING);
2075 TREEVIEW_MouseMove (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2077 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2078 TREEVIEW_ITEM *hotItem;
2081 pt.x=(INT) LOWORD (lParam);
2082 pt.y=(INT) HIWORD (lParam);
2083 hotItem=TREEVIEW_HitTestPoint (wndPtr, pt);
2084 if (!hotItem) return 0;
2085 infoPtr->focusItem=hotItem->hItem;
2087 if (wndPtr->dwStyle & TVS_DISABLEDRAGDROP) return 0;
2089 if (infoPtr->uInternalStatus & TV_LDRAG) {
2090 TREEVIEW_SendTreeviewDnDNotify (wndPtr, TVN_BEGINDRAG, hotItem->hItem, pt);
2091 infoPtr->uInternalStatus &= ~TV_LDRAG;
2092 infoPtr->uInternalStatus |= TV_LDRAGGING;
2093 infoPtr->dropItem=hotItem->hItem;
2097 if (infoPtr->uInternalStatus & TV_RDRAG) {
2098 TREEVIEW_SendTreeviewDnDNotify (wndPtr, TVN_BEGINRDRAG, hotItem->hItem, pt);
2099 infoPtr->uInternalStatus &= ~TV_RDRAG;
2100 infoPtr->uInternalStatus |= TV_RDRAGGING;
2101 infoPtr->dropItem=hotItem->hItem;
2110 TREEVIEW_CreateDragImage (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2112 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2113 TREEVIEW_ITEM *dragItem;
2117 HBITMAP hbmp,hOldbmp;
2123 TRACE (treeview,"\n");
2124 if (!(infoPtr->himlNormal)) return 0;
2125 dragItem=TREEVIEW_ValidItem (infoPtr, (HTREEITEM) lParam);
2127 if (!dragItem) return 0;
2128 itemtxt=dragItem->pszText;
2130 hwtop=GetDesktopWindow ();
2131 htopdc= GetDC (hwtop);
2132 hdc=CreateCompatibleDC (htopdc);
2134 hOldFont=SelectObject (hdc, infoPtr->hFont);
2135 GetTextExtentPoint32A (hdc, itemtxt, lstrlenA (itemtxt), &size);
2136 TRACE (treeview,"%d %d %s %d\n",size.cx,size.cy,itemtxt,lstrlenA(itemtxt));
2137 hbmp=CreateCompatibleBitmap (htopdc, size.cx, size.cy);
2138 hOldbmp=SelectObject (hdc, hbmp);
2140 ImageList_GetIconSize (infoPtr->himlNormal, &cx, &cy);
2142 if (cy>size.cy) size.cy=cy;
2144 infoPtr->dragList=ImageList_Create (size.cx, size.cy, ILC_COLOR, 10, 10);
2145 ImageList_Draw (infoPtr->himlNormal, dragItem->iImage, hdc, 0, 0, ILD_NORMAL);
2148 ImageList_GetImageInfo (infoPtr->himlNormal, dragItem->hItem, &iminfo);
2149 ImageList_AddMasked (infoPtr->dragList, iminfo.hbmImage, CLR_DEFAULT);
2152 /* draw item text */
2154 SetRect (&rc, cx, 0, size.cx,size.cy);
2155 DrawTextA (hdc, itemtxt, lstrlenA (itemtxt), &rc, DT_LEFT);
2156 SelectObject (hdc, hOldFont);
2157 SelectObject (hdc, hOldbmp);
2159 ImageList_Add (infoPtr->dragList, hbmp, 0);
2162 DeleteObject (hbmp);
2163 ReleaseDC (hwtop, htopdc);
2165 return (LRESULT)infoPtr->dragList;
2170 /* FIXME: handle NM_KILLFocus enzo */
2173 TREEVIEW_DoSelectItem (WND *wndPtr, INT action, HTREEITEM newSelect, INT cause)
2176 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2177 TREEVIEW_ITEM *prevItem,*wineItem, *parentItem;
2180 TRACE (treeview,"item %x, flag %x, cause %x\n", (INT)newSelect, action, cause);
2181 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)newSelect);
2184 if (wineItem->parent) {
2185 parentItem=TREEVIEW_ValidItem (infoPtr, wineItem->parent);
2186 if (!(parentItem->state & TVIS_EXPANDED))
2187 TREEVIEW_Expand (wndPtr, TVE_EXPAND, (LPARAM) wineItem->parent);
2193 prevSelect=(INT)infoPtr->selectedItem;
2194 if ((HTREEITEM)prevSelect==newSelect) return FALSE;
2195 prevItem= TREEVIEW_ValidItem (infoPtr, (HTREEITEM)prevSelect);
2197 if (TREEVIEW_SendTreeviewNotify (wndPtr, TVN_SELCHANGING,
2198 cause, (HTREEITEM)prevSelect, (HTREEITEM)newSelect))
2199 return FALSE; /* FIXME: OK? */
2201 if (prevItem) prevItem->state &= ~TVIS_SELECTED;
2202 infoPtr->selectedItem=(HTREEITEM)newSelect;
2203 if (wineItem) wineItem->state |=TVIS_SELECTED;
2205 TREEVIEW_SendTreeviewNotify (wndPtr, TVN_SELCHANGED,
2206 cause, (HTREEITEM)prevSelect, (HTREEITEM)newSelect);
2208 case TVGN_DROPHILITE:
2209 prevItem= TREEVIEW_ValidItem (infoPtr, infoPtr->dropItem);
2210 if (prevItem) prevItem->state &= ~TVIS_DROPHILITED;
2211 infoPtr->dropItem=(HTREEITEM)newSelect;
2212 if (wineItem) wineItem->state |=TVIS_DROPHILITED;
2214 case TVGN_FIRSTVISIBLE:
2215 FIXME (treeview, "FIRSTVISIBLE not implemented\n");
2219 TREEVIEW_QueueRefresh (wndPtr);
2226 TREEVIEW_SelectItem (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2229 return TREEVIEW_DoSelectItem (wndPtr, wParam, (HTREEITEM) lParam, TVC_UNKNOWN);
2236 TREEVIEW_GetFont (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2239 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2241 TRACE (treeview,"%x\n",infoPtr->hFont);
2242 return infoPtr->hFont;
2246 TREEVIEW_SetFont (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2249 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2252 HFONT hFont, hOldFont;
2256 TRACE (treeview,"%x %lx\n",wParam, lParam);
2258 infoPtr->hFont = (HFONT)wParam;
2260 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
2262 GetObjectA (infoPtr->hFont, sizeof (LOGFONTA), &logFont);
2263 logFont.lfWeight=FW_BOLD;
2264 infoPtr->hBoldFont = CreateFontIndirectA (&logFont);
2267 hOldFont = SelectObject (hdc, hFont);
2268 GetTextMetricsA (hdc, &tm);
2269 height= tm.tmHeight + tm.tmExternalLeading;
2270 if (height>infoPtr->uRealItemHeight)
2271 infoPtr->uRealItemHeight=height;
2272 SelectObject (hdc, hOldFont);
2276 TREEVIEW_QueueRefresh (wndPtr);
2282 /* FIXME: does KEYDOWN also send notifications?? If so, use
2283 TREEVIEW_DoSelectItem.
2288 TREEVIEW_KeyDown (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2290 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2291 TREEVIEW_ITEM *prevItem,*newItem;
2295 TRACE (treeview,"%x %lx\n",wParam, lParam);
2296 prevSelect=(INT)infoPtr->selectedItem;
2297 if (!prevSelect) return FALSE;
2299 prevItem= TREEVIEW_ValidItem (infoPtr, (HTREEITEM)prevSelect);
2304 newItem=TREEVIEW_GetPrevListItem (infoPtr, prevItem);
2306 newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
2309 newItem=TREEVIEW_GetNextListItem (infoPtr, prevItem);
2310 if (!newItem) newItem=prevItem;
2313 newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
2316 newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
2317 newItem=TREEVIEW_GetLastListItem (infoPtr, newItem);
2323 FIXME (treeview, "%x not implemented\n", wParam);
2327 if (!newItem) return FALSE;
2329 if (prevItem!=newItem) {
2330 prevItem->state &= ~TVIS_SELECTED;
2331 newItem->state |= TVIS_SELECTED;
2332 infoPtr->selectedItem=newItem->hItem;
2333 TREEVIEW_QueueRefresh (wndPtr);
2343 TREEVIEW_VScroll (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2346 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2349 TRACE (treeview,"wp %x, lp %lx\n", wParam, lParam);
2350 if (!infoPtr->uInternalStatus & TV_VSCROLL) return FALSE;
2352 switch (LOWORD (wParam)) {
2354 if (!infoPtr->cy) return FALSE;
2355 infoPtr->cy -= infoPtr->uRealItemHeight;
2356 if (infoPtr->cy < 0) infoPtr->cy=0;
2359 maxHeight=infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
2360 if (infoPtr->cy == maxHeight) return FALSE;
2361 infoPtr->cy += infoPtr->uRealItemHeight;
2362 if (infoPtr->cy > maxHeight)
2363 infoPtr->cy = maxHeight;
2366 if (!infoPtr->cy) return FALSE;
2367 infoPtr->cy -= infoPtr->uVisibleHeight;
2368 if (infoPtr->cy < 0) infoPtr->cy=0;
2371 maxHeight=infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
2372 if (infoPtr->cy == maxHeight) return FALSE;
2373 infoPtr->cy += infoPtr->uVisibleHeight;
2374 if (infoPtr->cy > maxHeight)
2375 infoPtr->cy = maxHeight;
2378 infoPtr->cy = HIWORD (wParam);
2383 TREEVIEW_QueueRefresh (wndPtr);
2388 TREEVIEW_HScroll (WND *wndPtr, WPARAM wParam, LPARAM lParam)
2390 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
2393 TRACE (treeview,"wp %lx, lp %x\n", lParam, wParam);
2395 if (!infoPtr->uInternalStatus & TV_HSCROLL) return FALSE;
2397 switch (LOWORD (wParam)) {
2399 if (!infoPtr->cx) return FALSE;
2400 infoPtr->cx -= infoPtr->uRealItemHeight;
2401 if (infoPtr->cx < 0) infoPtr->cx=0;
2404 maxWidth=infoPtr->uTotalWidth-infoPtr->uVisibleWidth;
2405 if (infoPtr->cx == maxWidth) return FALSE;
2406 infoPtr->cx += infoPtr->uRealItemHeight; /*FIXME */
2407 if (infoPtr->cx > maxWidth)
2408 infoPtr->cx = maxWidth;
2411 if (!infoPtr->cx) return FALSE;
2412 infoPtr->cx -= infoPtr->uVisibleWidth;
2413 if (infoPtr->cx < 0) infoPtr->cx=0;
2416 maxWidth=infoPtr->uTotalWidth-infoPtr->uVisibleWidth;
2417 if (infoPtr->cx == maxWidth) return FALSE;
2418 infoPtr->cx += infoPtr->uVisibleWidth;
2419 if (infoPtr->cx > maxWidth)
2420 infoPtr->cx = maxWidth;
2423 infoPtr->cx = HIWORD (wParam);
2428 TREEVIEW_QueueRefresh (wndPtr);
2436 TREEVIEW_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2438 WND *wndPtr = WIN_FindWndPtr(hwnd);
2442 case TVM_INSERTITEMA:
2443 return TREEVIEW_InsertItemA (wndPtr, wParam, lParam);
2445 case TVM_INSERTITEMW:
2446 FIXME (treeview, "Unimplemented msg TVM_INSERTITEM32W\n");
2449 case TVM_DELETEITEM:
2450 return TREEVIEW_DeleteItem (wndPtr, wParam, lParam);
2453 return TREEVIEW_Expand (wndPtr, wParam, lParam);
2455 case TVM_GETITEMRECT:
2456 return TREEVIEW_GetItemRect (wndPtr, wParam, lParam);
2459 return TREEVIEW_GetCount (wndPtr, wParam, lParam);
2462 return TREEVIEW_GetIndent (wndPtr);
2465 return TREEVIEW_SetIndent (wndPtr, wParam);
2467 case TVM_GETIMAGELIST:
2468 return TREEVIEW_GetImageList (wndPtr, wParam, lParam);
2470 case TVM_SETIMAGELIST:
2471 return TREEVIEW_SetImageList (wndPtr, wParam, lParam);
2473 case TVM_GETNEXTITEM:
2474 return TREEVIEW_GetNextItem (wndPtr, wParam, lParam);
2476 case TVM_SELECTITEM:
2477 return TREEVIEW_SelectItem (wndPtr, wParam, lParam);
2480 return TREEVIEW_GetItemA (wndPtr, wParam, lParam);
2483 FIXME (treeview, "Unimplemented msg TVM_GETITEM32W\n");
2487 return TREEVIEW_SetItemA (wndPtr, wParam, lParam);
2490 FIXME (treeview, "Unimplemented msg TVM_SETITEMW\n");
2493 case TVM_EDITLABELA:
2494 FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32A \n");
2497 case TVM_EDITLABELW:
2498 FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32W \n");
2501 case TVM_GETEDITCONTROL:
2502 return TREEVIEW_GetEditControl (wndPtr);
2504 case TVM_GETVISIBLECOUNT:
2505 return TREEVIEW_GetVisibleCount (wndPtr, wParam, lParam);
2508 return TREEVIEW_HitTest (wndPtr, lParam);
2510 case TVM_CREATEDRAGIMAGE:
2511 return TREEVIEW_CreateDragImage (wndPtr, wParam, lParam);
2513 case TVM_SORTCHILDREN:
2514 FIXME (treeview, "Unimplemented msg TVM_SORTCHILDREN\n");
2517 case TVM_ENSUREVISIBLE:
2518 FIXME (treeview, "Unimplemented msg TVM_ENSUREVISIBLE\n");
2521 case TVM_SORTCHILDRENCB:
2522 FIXME (treeview, "Unimplemented msg TVM_SORTCHILDRENCB\n");
2525 case TVM_ENDEDITLABELNOW:
2526 FIXME (treeview, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
2529 case TVM_GETISEARCHSTRINGA:
2530 FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
2533 case TVM_GETISEARCHSTRINGW:
2534 FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
2537 case TVM_GETTOOLTIPS:
2538 return TREEVIEW_GetToolTips (wndPtr);
2540 case TVM_SETTOOLTIPS:
2541 return TREEVIEW_SetToolTips (wndPtr, wParam);
2543 case TVM_SETINSERTMARK:
2544 FIXME (treeview, "Unimplemented msg TVM_SETINSERTMARK\n");
2547 case TVM_SETITEMHEIGHT:
2548 return TREEVIEW_SetItemHeight (wndPtr, wParam);
2550 case TVM_GETITEMHEIGHT:
2551 return TREEVIEW_GetItemHeight (wndPtr);
2553 case TVM_SETBKCOLOR:
2554 return TREEVIEW_SetBkColor (wndPtr, wParam, lParam);
2556 case TVM_SETTEXTCOLOR:
2557 return TREEVIEW_SetTextColor (wndPtr, wParam, lParam);
2559 case TVM_GETBKCOLOR:
2560 return TREEVIEW_GetBkColor (wndPtr);
2562 case TVM_GETTEXTCOLOR:
2563 return TREEVIEW_GetTextColor (wndPtr);
2565 case TVM_SETSCROLLTIME:
2566 FIXME (treeview, "Unimplemented msg TVM_SETSCROLLTIME\n");
2569 case TVM_GETSCROLLTIME:
2570 FIXME (treeview, "Unimplemented msg TVM_GETSCROLLTIME\n");
2573 case TVM_SETINSERTMARKCOLOR:
2574 FIXME (treeview, "Unimplemented msg TVM_SETINSERTMARKCOLOR\n");
2577 case TVM_SETUNICODEFORMAT:
2578 FIXME (treeview, "Unimplemented msg TVM_SETUNICODEFORMAT\n");
2581 case TVM_GETUNICODEFORMAT:
2582 FIXME (treeview, "Unimplemented msg TVM_GETUNICODEFORMAT\n");
2586 return TREEVIEW_Command (wndPtr, wParam, lParam);
2589 return TREEVIEW_Create (wndPtr, wParam, lParam);
2592 return TREEVIEW_Destroy (wndPtr);
2594 /* case WM_ENABLE: */
2597 return TREEVIEW_EraseBackground (wndPtr, wParam, lParam);
2600 return DLGC_WANTARROWS | DLGC_WANTCHARS;
2603 return TREEVIEW_Paint (wndPtr, wParam, lParam);
2606 return TREEVIEW_GetFont (wndPtr, wParam, lParam);
2609 return TREEVIEW_SetFont (wndPtr, wParam, lParam);
2612 return TREEVIEW_KeyDown (wndPtr, wParam, lParam);
2616 return TREEVIEW_SetFocus (wndPtr, wParam, lParam);
2619 return TREEVIEW_KillFocus (wndPtr, wParam, lParam);
2622 case WM_LBUTTONDOWN:
2623 return TREEVIEW_LButtonDown (wndPtr, wParam, lParam);
2626 return TREEVIEW_LButtonUp (wndPtr, wParam, lParam);
2628 case WM_LBUTTONDBLCLK:
2629 return TREEVIEW_LButtonDoubleClick (wndPtr, wParam, lParam);
2631 case WM_RBUTTONDOWN:
2632 return TREEVIEW_RButtonDown (wndPtr, wParam, lParam);
2635 return TREEVIEW_RButtonUp (wndPtr, wParam, lParam);
2638 return TREEVIEW_MouseMove (wndPtr, wParam, lParam);
2641 /* case WM_SYSCOLORCHANGE: */
2642 case WM_STYLECHANGED:
2643 return TREEVIEW_StyleChanged (wndPtr, wParam, lParam);
2645 /* case WM_SETREDRAW: */
2648 return TREEVIEW_HandleTimer (wndPtr, wParam, lParam);
2651 return TREEVIEW_Size (wndPtr, wParam,lParam);
2654 return TREEVIEW_HScroll (wndPtr, wParam, lParam);
2656 return TREEVIEW_VScroll (wndPtr, wParam, lParam);
2659 printf ("drawItem\n");
2660 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2663 if (uMsg >= WM_USER)
2664 FIXME (treeview, "Unknown msg %04x wp=%08x lp=%08lx\n",
2665 uMsg, wParam, lParam);
2666 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2673 TREEVIEW_Register (VOID)
2677 TRACE (treeview,"\n");
2679 if (GlobalFindAtomA (WC_TREEVIEWA)) return;
2681 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2682 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
2683 wndClass.lpfnWndProc = (WNDPROC)TREEVIEW_WindowProc;
2684 wndClass.cbClsExtra = 0;
2685 wndClass.cbWndExtra = sizeof(TREEVIEW_INFO *);
2686 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
2687 wndClass.hbrBackground = 0;
2688 wndClass.lpszClassName = WC_TREEVIEWA;
2690 RegisterClassA (&wndClass);
2695 TREEVIEW_Unregister (VOID)
2697 if (GlobalFindAtomA (WC_TREEVIEWA))
2698 UnregisterClassA (WC_TREEVIEWA, (HINSTANCE)NULL);