Changed some treeview related definitions.
[wine] / dlls / comctl32 / treeview.c
1 /* Treeview control
2  *
3  * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
4  * Copyright 1998 Alex Priem <alexp@sci.kun.nl>
5  *
6  *
7  * TODO:
8  *   - Nearly all notifications.
9  * 
10  *   list-handling stuff: sort, sorted insertitem.
11  *
12  *   refreshtreeview:   
13                 -small array containing info about positions.
14                 -better implementation of DrawItem (connecting lines).
15                 -implement partial drawing?
16  *   Expand:            -ctlmacro expands twice ->toggle.
17  *  -drag&drop.
18  *  -scrollbars.
19  *  -Unicode messages
20  *  -TV_ITEMEX 
21  *
22  * FIXMEs:  
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).
26              
27  */
28
29 #include <string.h>
30 #include "windows.h"
31 #include "commctrl.h"
32 #include "treeview.h"
33 #include "heap.h"
34 #include "win.h"
35 #include "debug.h"
36
37 /* ffs should be in <string.h>. */
38
39 /* Defines, since they do not need to return previous state, and nr
40  * has no side effects in this file.
41  */
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))
45
46
47 #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
48
49 static BOOL32
50 TREEVIEW_SendSimpleNotify (WND *wndPtr, UINT32 code);
51 static BOOL32
52 TREEVIEW_SendTreeviewNotify (WND *wndPtr, UINT32 code, UINT32 action, 
53                         INT32 oldItem, INT32 newItem, POINT32 pt);
54 static LRESULT
55 TREEVIEW_SelectItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
56 static void
57 TREEVIEW_Refresh (WND *wndPtr);
58
59
60
61
62
63 /* helper functions. Work with the assumption that validity of operands 
64    is checked beforehand */
65
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. */
69
70
71 static TREEVIEW_ITEM *
72 TREEVIEW_ValidItem (TREEVIEW_INFO *infoPtr,int  handle)
73 {
74  
75  if ((!handle) || (handle>infoPtr->uMaxHandle)) return NULL;
76  if (tv_test_bit (handle, infoPtr->freeList)) return NULL;
77
78  return & infoPtr->items[handle];
79 }
80
81
82
83 static TREEVIEW_ITEM *TREEVIEW_GetPrevListItem (TREEVIEW_INFO *infoPtr, 
84                                         TREEVIEW_ITEM *tvItem)
85
86 {
87  TREEVIEW_ITEM *wineItem;
88
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];
95                 }
96                 return wineItem;
97  }
98
99  wineItem=tvItem;
100  while (wineItem->parent) {
101         wineItem=& infoPtr->items[wineItem->parent];
102         if (wineItem->upsibling) 
103                 return (& infoPtr->items[wineItem->upsibling]);
104  } 
105
106  return wineItem;
107 }
108
109
110 static TREEVIEW_ITEM *TREEVIEW_GetNextListItem (TREEVIEW_INFO *infoPtr, 
111                                         TREEVIEW_ITEM *tvItem)
112
113 {
114  TREEVIEW_ITEM *wineItem;
115
116  if ((tvItem->firstChild) && (tvItem->state & TVIS_EXPANDED)) 
117                 return (& infoPtr->items[tvItem->firstChild]);
118
119  if (tvItem->sibling) 
120                 return (& infoPtr->items[tvItem->sibling]);
121
122  wineItem=tvItem;
123  while (wineItem->parent) {
124         wineItem=& infoPtr->items [wineItem->parent];
125         if (wineItem->sibling) 
126                 return (& infoPtr->items [wineItem->sibling]);
127  } 
128
129  return wineItem;
130 }
131
132 static TREEVIEW_ITEM *TREEVIEW_GetLastListItem (TREEVIEW_INFO *infoPtr)
133
134 {
135   TREEVIEW_ITEM *wineItem;
136   
137  wineItem=NULL;
138  if (infoPtr->TopRootItem) 
139         wineItem=& infoPtr->items [infoPtr->TopRootItem];
140  while (wineItem->sibling) 
141         wineItem=& infoPtr->items [wineItem->sibling];
142
143  return wineItem;
144 }
145         
146  
147
148
149 static void
150 TREEVIEW_RemoveItem (TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem)
151
152 {
153  TREEVIEW_ITEM *parentItem, *upsiblingItem, *siblingItem;
154  INT32 iItem;
155
156  iItem=wineItem->hItem;
157  tv_set_bit(iItem,infoPtr->freeList);
158  infoPtr->uNumItems--;
159  parentItem=NULL;
160  if (wineItem->pszText!=LPSTR_TEXTCALLBACK32A) 
161         COMCTL32_Free (wineItem->pszText);
162
163  if (wineItem->parent) {
164         parentItem=& infoPtr->items[ wineItem->parent];
165         if (parentItem->cChildren==1) {
166                 parentItem->cChildren=0;
167                 parentItem->firstChild=0;    
168                 return;
169         } else {
170                 parentItem->cChildren--;
171                 if (parentItem->firstChild==iItem) 
172                         parentItem->firstChild=wineItem->sibling;
173                 }
174  }
175
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;
181  }
182  if (wineItem->sibling) {
183         siblingItem=& infoPtr->items [wineItem->sibling];
184         siblingItem->upsibling=wineItem->upsibling;
185  }
186 }
187
188
189
190 static void TREEVIEW_RemoveAllChildren (TREEVIEW_INFO *infoPtr, 
191                                            TREEVIEW_ITEM *parentItem)
192
193 {
194  TREEVIEW_ITEM *killItem;
195  INT32  kill;
196  
197  kill=parentItem->firstChild;
198  while (kill) {
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;
204  }
205  infoPtr->uNumItems -= parentItem->cChildren;
206  parentItem->firstChild = 0;
207  parentItem->cChildren = 0;
208 }
209
210
211 /* Note:TREEVIEW_RemoveTree doesn't remove infoPtr itself */
212
213 static void TREEVIEW_RemoveTree (TREEVIEW_INFO *infoPtr)
214                                            
215
216 {
217         TREEVIEW_ITEM *killItem;
218         int i;
219
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);
225                 } 
226
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;
233     }   
234 }
235
236
237
238
239
240
241
242
243
244
245 static LRESULT
246 TREEVIEW_GetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
247 {
248   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
249
250   TRACE (treeview,"\n");
251   if (infoPtr==NULL) return 0;
252
253   if ((INT32)wParam == TVSIL_NORMAL) 
254         return (LRESULT) infoPtr->himlNormal;
255   if ((INT32)wParam == TVSIL_STATE) 
256         return (LRESULT) infoPtr->himlState;
257
258   return 0;
259 }
260
261
262
263
264 static LRESULT
265 TREEVIEW_SetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
266 {
267     TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
268     HIMAGELIST himlTemp;
269
270     TRACE (treeview,"\n");
271     switch ((INT32)wParam) {
272         case TVSIL_NORMAL:
273             himlTemp = infoPtr->himlNormal;
274             infoPtr->himlNormal = (HIMAGELIST)lParam;
275             return (LRESULT)himlTemp;
276
277         case TVSIL_STATE:
278             himlTemp = infoPtr->himlState;
279             infoPtr->himlState = (HIMAGELIST)lParam;
280             return (LRESULT)himlTemp;
281     }
282
283     return (LRESULT)NULL;
284 }
285
286
287
288 static LRESULT
289 TREEVIEW_SetItemHeight (WND *wndPtr, WPARAM32 wParam)
290 {
291   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
292   INT32 prevHeight=infoPtr->uItemHeight;
293   HDC32 hdc;
294   TEXTMETRIC32A tm;
295
296   TRACE (treeview,"\n");
297   if (wParam==-1) {
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);
303         return prevHeight;
304   }
305
306         /* FIXME: check wParam > imagelist height */
307
308   if (!(wndPtr->dwStyle & TVS_NONEVENHEIGHT))
309         infoPtr->uItemHeight = (INT32) wParam & 0xfffffffe;
310   return prevHeight;
311 }
312
313 static LRESULT
314 TREEVIEW_GetItemHeight (WND *wndPtr)
315 {
316   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
317   
318   TRACE (treeview,"\n");
319   return infoPtr->uItemHeight;
320 }
321   
322 static LRESULT
323 TREEVIEW_SetTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
324 {
325   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
326   COLORREF prevColor=infoPtr->clrText;
327
328   TRACE (treeview,"\n");
329   infoPtr->clrText=(COLORREF) lParam;
330   return (LRESULT) prevColor;
331 }
332
333 static LRESULT
334 TREEVIEW_GetTextColor (WND *wndPtr)
335 {
336   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
337         
338   TRACE (treeview,"\n");
339   return (LRESULT) infoPtr->clrText;
340 }
341
342
343 static INT32
344 TREEVIEW_DrawItem (WND *wndPtr, HDC32 hdc, TREEVIEW_ITEM *wineItem, 
345                    TREEVIEW_ITEM *upperItem, int indent)
346 {
347   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
348   INT32  oldBkMode,center,xpos;
349   COLORREF oldBkColor;
350   UINT32 uTextJustify = DT_LEFT;
351   HPEN32 hOldPen, hnewPen,hRootPen;
352   RECT32 r,upper;
353   
354   hnewPen = CreatePen32(PS_DOT, 0, GetSysColor32(COLOR_WINDOWTEXT) );
355   hOldPen = SelectObject32( hdc, hnewPen );
356  
357   r=wineItem->rect;
358   if (upperItem) 
359         upper=upperItem->rect;
360   else {
361         upper.top=0;
362         upper.left=8;
363   }
364   center=(r.top+r.bottom)/2;
365   xpos=r.left+8;
366
367   if (wndPtr->dwStyle & TVS_HASLINES) {
368         POINT32 points[3];
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;
374                 points[2].y+=5;
375
376                 Polyline32 (hdc,points,3);
377         }
378         else {
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;
383                 points[2].y+=5;
384                 Polyline32 (hdc,points,3);
385         }
386  }
387
388   DeleteObject32(hnewPen);
389   SelectObject32(hdc, hOldPen);
390
391   if ((wndPtr->dwStyle & TVS_HASBUTTONS) && (wineItem->cChildren)) {
392 /*
393         hRootPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOW) );
394         SelectObject32( hdc, hRootPen );
395 */
396
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);
403         }
404  /*     DeleteObject32(hRootPen); */
405         }
406
407
408   xpos+=13;
409
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);
415                         xpos+=15;
416                 }
417         }
418   }
419
420   r.left=xpos;
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));
426             } else {
427                 oldBkMode = SetBkMode32(hdc, TRANSPARENT);
428             }
429         r.left += 3;
430         r.right -= 3;
431                 if (infoPtr->clrText==-1)
432                 SetTextColor32 (hdc, COLOR_BTNTEXT);
433                 else 
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);
438                 else {
439                         /* send TVN_GETDISPINFO notification */
440                         TRACE (treeview,"LPSTR_TEXTCALLBACK\n");
441                 }
442         if (oldBkMode != TRANSPARENT)
443             SetBkMode32(hdc, oldBkMode);
444             if (wineItem->state & TVIS_SELECTED)
445                         SetBkColor32 (hdc, oldBkColor);
446         }
447
448  return wineItem->rect.right;
449 }
450
451
452
453
454
455
456
457 static LRESULT
458 TREEVIEW_GetItemRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
459 {
460   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
461   TREEVIEW_ITEM *wineItem;
462   INT32 iItem;
463   LPRECT32 lpRect;
464
465   TRACE (treeview,"\n");
466   if (infoPtr==NULL) return FALSE;
467   
468   iItem = (INT32)lParam;
469   wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
470   if (!wineItem) return FALSE;
471
472   wineItem=& infoPtr->items[ iItem ];
473   if (!wineItem->visible) return FALSE;
474
475   lpRect = (LPRECT32)lParam;
476   if (lpRect == NULL) return FALSE;
477         
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;
483   } else {
484         lpRect->left    = wineItem->rect.left;
485         lpRect->right   = wineItem->rect.right;
486         lpRect->bottom  = wineItem->rect.bottom;
487         lpRect->top     = wineItem->rect.top;
488   }
489
490   return TRUE;
491 }
492
493
494
495 static LRESULT
496 TREEVIEW_GetVisibleCount (WND *wndPtr,  WPARAM32 wParam, LPARAM lParam)
497
498 {
499   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
500
501   TRACE (treeview,"\n");
502   return (LRESULT) infoPtr->uVisibleHeight / infoPtr->uRealItemHeight;
503 }
504
505
506
507 static LRESULT
508 TREEVIEW_SetItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
509 {
510   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
511   TREEVIEW_ITEM *wineItem;
512   TV_ITEM *tvItem;
513   INT32 iItem,len;
514
515   tvItem=(LPTV_ITEM) lParam;
516   iItem=tvItem->hItem;
517   TRACE (treeview,"item %d,mask %x\n",iItem,tvItem->mask);
518
519   wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
520   if (!wineItem) return FALSE;
521
522   if (tvItem->mask & TVIF_CHILDREN) {
523         wineItem->cChildren=tvItem->cChildren;
524   }
525
526   if (tvItem->mask & TVIF_IMAGE) {
527        wineItem->iImage=tvItem->iImage;
528   }
529
530   if (tvItem->mask & TVIF_INTEGRAL) {
531 /*        wineItem->iIntegral=tvItem->iIntegral; */
532   }
533
534   if (tvItem->mask & TVIF_PARAM) {
535         wineItem->lParam=tvItem->lParam;
536   }
537
538   if (tvItem->mask & TVIF_SELECTEDIMAGE) {
539         wineItem->iSelectedImage=tvItem->iSelectedImage;
540   }
541
542   if (tvItem->mask & TVIF_STATE) {
543         wineItem->state=tvItem->state & tvItem->stateMask;
544   }
545
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);
551    }
552
553   return TRUE;
554 }
555
556
557
558
559
560 static void
561 TREEVIEW_Refresh (WND *wndPtr)
562
563 {
564     TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
565     HFONT32 hFont, hOldFont;
566     RECT32 rect;
567     HBRUSH32 hbrBk;
568         HDC32 hdc;
569     INT32 iItem, indent, x, y, height;
570     INT32 viewtop,viewbottom,viewleft,viewright;
571     TREEVIEW_ITEM *wineItem, *prevItem;
572
573     TRACE (treeview,"\n");
574
575         hdc=GetDC32 (wndPtr->hwndSelf);
576
577     if (infoPtr->Timer & TV_REFRESH_TIMER_SET) {
578                 KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
579                 infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
580     }
581
582     
583     GetClientRect32 (wndPtr->hwndSelf, &rect);
584     if ((rect.left-rect.right ==0) || (rect.top-rect.bottom==0)) return;
585     viewtop=infoPtr->cy;
586     viewbottom=infoPtr->cy + rect.bottom-rect.top;
587     viewleft=infoPtr->cx;
588     viewright=infoPtr->cx + rect.right-rect.left;
589
590         infoPtr->uVisibleHeight=viewbottom - viewtop;
591
592     hFont = infoPtr->hFont;
593     hOldFont = SelectObject32 (hdc, hFont);
594
595     /* draw background */
596     hbrBk = GetSysColorBrush32(COLOR_WINDOW);
597     FillRect32(hdc, &rect, hbrBk);
598
599
600     iItem=infoPtr->TopRootItem;
601     infoPtr->firstVisible=0;
602     wineItem=NULL;
603     indent=0;
604     x=y=0;
605     TRACE (treeview, "[%d %d %d %d]\n",viewtop,viewbottom,viewleft,viewright);
606
607     while (iItem) {
608                 prevItem=wineItem;
609         wineItem= & infoPtr->items[iItem];
610
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,
614                         wineItem->pszText);
615
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);
626                 }
627                 else {
628                         wineItem->rect.top  = wineItem->rect.bottom = -1;
629                         wineItem->rect.left = wineItem->rect.right = -1;
630                 }
631
632                 /* look up next item */
633         
634                 if ((wineItem->firstChild) && (wineItem->state & TVIS_EXPANDED)) {
635                         iItem=wineItem->firstChild;
636                         indent++;
637                         x+=infoPtr->uIndent;
638                 }
639                 else {
640                         iItem=wineItem->sibling;
641                         while ((!iItem) && (indent>0)) {
642                                 indent--;
643                                 x-=infoPtr->uIndent;
644                                 prevItem=wineItem;
645                                 wineItem=&infoPtr->items[wineItem->parent];
646                                 iItem=wineItem->sibling;
647                         }
648                 }
649         y +=height;
650     }                           /* while */
651
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);
660         }
661     else {
662                 if (infoPtr->uInternalStatus & TV_VSCROLL) 
663                         ShowScrollBar32 (wndPtr->hwndSelf, SB_VERT, FALSE);
664                 infoPtr->uInternalStatus &= ~TV_VSCROLL;
665         }
666
667
668     SelectObject32 (hdc, hOldFont);
669     ReleaseDC32 (wndPtr->hwndSelf, hdc);
670 }
671
672
673 static LRESULT 
674 TREEVIEW_HandleTimer ( WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
675 {
676   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
677
678   TRACE (treeview, " %d\n",wParam);
679   if (!infoPtr) return FALSE;
680
681   switch (wParam) {
682         case TV_REFRESH_TIMER:
683                 KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
684                 infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
685                 TREEVIEW_Refresh (wndPtr);
686                 return 0;
687         case TV_EDIT_TIMER:
688                 KillTimer32 (wndPtr->hwndSelf, TV_EDIT_TIMER);
689                 infoPtr->Timer &= ~TV_EDIT_TIMER_SET;
690                 return 0;
691  }
692                 
693  return 1;
694 }
695
696
697 static void
698 TREEVIEW_QueueRefresh (WND *wndPtr)
699
700 {
701  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
702
703  TRACE (treeview,"\n");
704  if (infoPtr->Timer & TV_REFRESH_TIMER_SET) {
705         KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
706  }
707
708  SetTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER, TV_REFRESH_DELAY, 0);
709  infoPtr->Timer|=TV_REFRESH_TIMER_SET;
710 }
711
712
713
714 static LRESULT
715 TREEVIEW_GetItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
716 {
717   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
718   LPTV_ITEM      tvItem;
719   TREEVIEW_ITEM *wineItem;
720   INT32         iItem;
721
722   TRACE (treeview,"\n");
723   tvItem=(LPTV_ITEM) lParam;
724   iItem=tvItem->hItem;
725
726   wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
727   if (!wineItem) return FALSE;
728
729
730    if (tvItem->mask & TVIF_CHILDREN) {
731         tvItem->cChildren=wineItem->cChildren;
732    }
733
734    if (tvItem->mask & TVIF_HANDLE) {
735         tvItem->hItem=wineItem->hItem;
736    }
737
738    if (tvItem->mask & TVIF_IMAGE) {
739         tvItem->iImage=wineItem->iImage;
740    }
741
742    if (tvItem->mask & TVIF_INTEGRAL) {
743 /*        tvItem->iIntegral=wineItem->iIntegral; */
744    }
745
746    if (tvItem->mask & TVIF_PARAM) {
747         tvItem->lParam=wineItem->lParam;
748    }
749
750    if (tvItem->mask & TVIF_SELECTEDIMAGE) {
751         tvItem->iSelectedImage=wineItem->iSelectedImage;
752    }
753
754    if (tvItem->mask & TVIF_STATE) {
755         tvItem->state=wineItem->state & tvItem->stateMask;
756    }
757
758    if (tvItem->mask & TVIF_TEXT) {
759         if (wineItem->pszText == LPSTR_TEXTCALLBACK32A) {
760             tvItem->pszText = LPSTR_TEXTCALLBACK32A;
761         }
762         else if (wineItem->pszText) {
763             lstrcpyn32A (tvItem->pszText, wineItem->pszText, tvItem->cchTextMax);
764         }
765    }
766
767   return TRUE;
768 }
769
770
771
772 /* FIXME: check implementation of TVGN_NEXT/TVGN_NEXTVISIBLE */
773
774
775 static LRESULT
776 TREEVIEW_GetNextItem32 (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
777
778 {
779   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
780   TREEVIEW_ITEM *wineItem;
781   INT32 iItem, flag;
782
783
784   TRACE (treeview,"item:%lu, flags:%x\n", lParam, wParam);
785   if (!infoPtr) return FALSE;
786
787   flag= (INT32) wParam;
788   switch (flag) {
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;
796         }
797         
798   iItem= (INT32) lParam;
799   wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
800   if (!wineItem) return FALSE;
801
802   switch (flag) {
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);
809                                 break;
810         case TVGN_NEXTVISIBLE:  
811                                 wineItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
812                                 TRACE (treeview,"(%s)\n",wineItem->pszText);
813                                 break;
814         case TVGN_PREVIOUSVISIBLE: 
815                                 wineItem=TREEVIEW_GetPrevListItem (infoPtr, wineItem);
816                                 TRACE (treeview,"(%s)\n",wineItem->pszText);
817                                 break;
818         default:        FIXME (treeview,"Unknown msg %x,item %x\n", flag,iItem);
819                                 break;
820         }
821
822         if (wineItem) return (LRESULT) wineItem->hItem;
823
824  FIXME (treeview, "returning 0\n");
825  return 0;
826 }
827
828
829 static LRESULT
830 TREEVIEW_GetCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
831 {
832  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
833
834  TRACE (treeview,"\n");
835  return (LRESULT) infoPtr->uNumItems;
836 }
837
838
839
840
841 /* the method used below isn't the most memory-friendly, but it avoids 
842    a lot of memory reallocations */ 
843
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? */
847
848 static LRESULT
849 TREEVIEW_InsertItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
850
851 {
852   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
853   TVINSERTSTRUCTA  *ptdi;
854   TV_ITEM       *tvItem;
855   TREEVIEW_ITEM *wineItem, *parentItem, *prevsib, *sibItem;
856   INT32         iItem,listItems,i,len;
857   
858   TRACE (treeview,"\n");
859   ptdi = (TVINSERTSTRUCTA *) lParam;
860
861         /* check if memory is available */
862
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;
868    }
869
870   if (infoPtr->uNumItems == (infoPtr->uNumPtrsAlloced-1) ) {
871         TREEVIEW_ITEM *oldItems = infoPtr->items;
872         INT32 *oldfreeList = infoPtr->freeList;
873
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));
877
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));
882
883          COMCTL32_Free (oldItems);  
884          COMCTL32_Free (oldfreeList);  
885     }
886
887   iItem=0;
888   infoPtr->uNumItems++;
889
890   if (infoPtr->uMaxHandle==(infoPtr->uNumItems-1))  { 
891         iItem=infoPtr->uNumItems;
892         infoPtr->uMaxHandle++;
893   } 
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]);
899                         break;
900                 }
901          } 
902   }
903   if (!iItem) ERR (treeview, "Argh -- can't find free item.\n");
904   
905   tvItem= & ptdi->item;
906   wineItem=& infoPtr->items[iItem];
907
908
909
910   if ((ptdi->hParent==TVI_ROOT) || (ptdi->hParent==0)) {
911         parentItem=NULL;
912         wineItem->parent=0; 
913         sibItem=&infoPtr->items [infoPtr->TopRootItem];
914         listItems=infoPtr->uNumItems;
915   }
916   else  {
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;
924   }
925
926   wineItem->upsibling=0;  /* needed in case we're the first item in a list */ 
927   wineItem->sibling=0;     
928   wineItem->firstChild=0;
929
930   if (listItems>1) {
931      prevsib=NULL;
932      switch (ptdi->hInsertAfter) {
933                 case TVI_FIRST: wineItem->sibling=infoPtr->TopRootItem;
934                         infoPtr->TopRootItem=iItem;
935                         break;
936                 case TVI_LAST:  
937                         while (sibItem->sibling) {
938                                 prevsib=sibItem;
939                                 sibItem=&infoPtr->items [sibItem->sibling];
940                         }
941                         sibItem->sibling=iItem;
942                         if (prevsib!=NULL) 
943                                 wineItem->upsibling=prevsib->hItem;
944                         else
945                                 wineItem->sibling=0;    /* terminate list */
946                         break;
947                 case TVI_SORT:  
948                         FIXME (treeview, "Sorted insert not implemented yet\n");
949                         break;
950                 default:        
951                         while ((sibItem->sibling) && (sibItem->sibling!=iItem)) {
952                                 prevsib=sibItem;
953                 sibItem=&infoPtr->items [sibItem->sibling];
954             }
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;
959                         if (prevsib!=NULL) 
960                                 wineItem->upsibling=prevsib->hItem;
961                         break;
962         }
963    }    
964
965
966 /* Fill in info structure */
967
968    TRACE (treeview,"item %d, mask %x\n",iItem, tvItem->mask);
969    wineItem->mask=tvItem->mask;
970    wineItem->hItem=iItem;
971    wineItem->iIntegral=1; 
972
973    if (tvItem->mask & TVIF_CHILDREN)
974          wineItem->cChildren=tvItem->cChildren;
975
976    if (tvItem->mask & TVIF_IMAGE) 
977         wineItem->iImage=tvItem->iImage;
978
979 /*   if (tvItem->mask & TVIF_INTEGRAL) 
980         wineItem->iIntegral=tvItem->iIntegral;  */
981    
982
983    if (tvItem->mask & TVIF_PARAM) 
984         wineItem->lParam=tvItem->lParam;
985
986    if (tvItem->mask & TVIF_SELECTEDIMAGE) 
987         wineItem->iSelectedImage=tvItem->iSelectedImage;
988
989    if (tvItem->mask & TVIF_STATE) {
990         wineItem->state=tvItem->state;
991         wineItem->stateMask=tvItem->stateMask;
992    }
993
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;
1001         }
1002         else {
1003             wineItem->pszText = LPSTR_TEXTCALLBACK32A;
1004                 TRACE (treeview,"LPSTR_TEXTCALLBACK\n");
1005             wineItem->cchTextMax = 0;
1006         }
1007    }
1008
1009    TREEVIEW_QueueRefresh (wndPtr);
1010
1011    return (LRESULT) iItem;
1012 }
1013
1014
1015
1016 static LRESULT
1017 TREEVIEW_DeleteItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1018 {
1019   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1020   INT32 iItem;
1021   POINT32 pt;
1022   TREEVIEW_ITEM *wineItem;
1023
1024   TRACE (treeview,"\n");
1025   if (!infoPtr) return FALSE;
1026
1027   if ((INT32) lParam == TVI_ROOT) {
1028         TREEVIEW_RemoveTree (infoPtr);
1029   } else {
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);
1035   }
1036
1037   TREEVIEW_QueueRefresh (wndPtr);
1038
1039   return TRUE;
1040 }
1041
1042
1043 static LRESULT
1044 TREEVIEW_GetIndent (WND *wndPtr)
1045 {
1046  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1047
1048  TRACE (treeview,"\n");
1049  return infoPtr->uIndent;
1050 }
1051
1052 static LRESULT
1053 TREEVIEW_SetIndent (WND *wndPtr, WPARAM32 wParam)
1054 {
1055   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1056   INT32 newIndent;
1057    
1058   TRACE (treeview,"\n");
1059   newIndent=(INT32) wParam;
1060   if (newIndent < MINIMUM_INDENT) newIndent=MINIMUM_INDENT;
1061   infoPtr->uIndent=newIndent;
1062   
1063   return 0;
1064 }
1065
1066 static LRESULT
1067 TREEVIEW_GetToolTips (WND *wndPtr)
1068
1069 {
1070  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1071
1072  TRACE (treeview,"\n");
1073  return infoPtr->hwndToolTip;
1074 }
1075
1076
1077 static LRESULT
1078 TREEVIEW_SetToolTips (WND *wndPtr, WPARAM32 wParam)
1079
1080 {
1081  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1082  HWND32 prevToolTip;
1083
1084  TRACE (treeview,"\n");
1085  prevToolTip=infoPtr->hwndToolTip;
1086  infoPtr->hwndToolTip= (HWND32) wParam;
1087
1088  return prevToolTip;
1089 }
1090
1091
1092
1093
1094
1095
1096 static LRESULT
1097 TREEVIEW_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1098 {
1099     TREEVIEW_INFO *infoPtr;
1100         HDC32 hdc;
1101     TEXTMETRIC32A tm;
1102   
1103     TRACE (treeview,"\n");
1104       /* allocate memory for info structure */
1105       infoPtr = (TREEVIEW_INFO *) COMCTL32_Alloc (sizeof(TREEVIEW_INFO));
1106
1107     wndPtr->wExtra[0] = (DWORD)infoPtr;
1108
1109     if (infoPtr == NULL) {
1110                 ERR (treeview, "could not allocate info memory!\n");
1111                 return 0;
1112     }
1113
1114     if ((TREEVIEW_INFO*)wndPtr->wExtra[0] != infoPtr) {
1115                 ERR (treeview, "pointer assignment error!\n");
1116                 return 0;
1117     }
1118
1119         hdc=GetDC32 (wndPtr->hwndSelf);
1120
1121     /* set default settings */
1122     infoPtr->uInternalStatus=0;
1123     infoPtr->uNumItems=0;
1124     infoPtr->clrBk = GetSysColor32 (COLOR_WINDOW);
1125     infoPtr->clrText = GetSysColor32 (COLOR_BTNTEXT);
1126     infoPtr->cy = 0;
1127     infoPtr->cx = 0;
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;
1135
1136     infoPtr->items = NULL;
1137     infoPtr->selectedItem=0;
1138     infoPtr->clrText=-1;        /* use system color */
1139     infoPtr->dropItem=0;
1140
1141 /*
1142     infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
1143     infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
1144 */
1145
1146         infoPtr->hwndToolTip=0;
1147     if (!(wndPtr->dwStyle & TVS_NOTOOLTIPS)) {   /* Create tooltip control */
1148                 TTTOOLINFO32A ti;
1149
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);
1155
1156         /* Send NM_TOOLTIPSCREATED notification */
1157         if (infoPtr->hwndToolTip) {
1158             NMTOOLTIPSCREATED nmttc;
1159
1160             nmttc.hdr.hwndFrom = wndPtr->hwndSelf;
1161             nmttc.hdr.idFrom = wndPtr->wIDmenu;
1162             nmttc.hdr.code = NM_TOOLTIPSCREATED;
1163             nmttc.hwndToolTips = infoPtr->hwndToolTip;
1164
1165             SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
1166                 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmttc);
1167         }
1168
1169                 ZeroMemory (&ti, sizeof(TTTOOLINFO32A));
1170         ti.cbSize   = sizeof(TTTOOLINFO32A);
1171         ti.uFlags   = TTF_IDISHWND | TTF_TRACK | TTF_TRANSPARENT ;
1172         ti.hwnd     = wndPtr->hwndSelf;
1173         ti.uId      = 0;
1174         ti.lpszText = "Test"; /* LPSTR_TEXTCALLBACK; */
1175         SetRectEmpty32 (&ti.rect);
1176
1177         SendMessage32A (infoPtr->hwndToolTip, TTM_ADDTOOL32A, 0, (LPARAM)&ti);
1178
1179     }
1180     ReleaseDC32 (wndPtr->hwndSelf, hdc);
1181
1182     return 0;
1183 }
1184
1185
1186
1187 static LRESULT 
1188 TREEVIEW_Destroy (WND *wndPtr) 
1189 {
1190    TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1191      
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);
1198
1199    COMCTL32_Free (infoPtr);
1200    return 0;
1201 }
1202
1203
1204 static LRESULT
1205 TREEVIEW_Paint (WND *wndPtr, WPARAM32 wParam)
1206 {
1207     HDC32 hdc;
1208     PAINTSTRUCT32 ps;
1209
1210     TRACE (treeview,"\n");
1211     hdc = wParam==0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
1212     TREEVIEW_QueueRefresh (wndPtr);
1213     if(!wParam)
1214         EndPaint32 (wndPtr->hwndSelf, &ps);
1215     return 0;
1216 }
1217
1218
1219
1220 static LRESULT
1221 TREEVIEW_EraseBackground (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1222 {
1223     TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1224     HBRUSH32 hBrush = CreateSolidBrush32 (infoPtr->clrBk);
1225     RECT32 rect;
1226
1227     TRACE (treeview,"\n");
1228     GetClientRect32 (wndPtr->hwndSelf, &rect);
1229     FillRect32 ((HDC32)wParam, &rect, hBrush);
1230     DeleteObject32 (hBrush);
1231     return TRUE;
1232 }
1233
1234
1235
1236
1237
1238   
1239
1240
1241
1242 static BOOL32
1243 TREEVIEW_SendSimpleNotify (WND *wndPtr, UINT32 code)
1244 {
1245     NMHDR nmhdr;
1246
1247     TRACE (treeview, "%x\n",code);
1248     nmhdr.hwndFrom = wndPtr->hwndSelf;
1249     nmhdr.idFrom   = wndPtr->wIDmenu;
1250     nmhdr.code     = code;
1251
1252     return (BOOL32) SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
1253                                    (WPARAM32)nmhdr.idFrom, (LPARAM)&nmhdr);
1254 }
1255
1256
1257
1258
1259 static BOOL32
1260 TREEVIEW_SendTreeviewNotify (WND *wndPtr, UINT32 code, UINT32 action, 
1261                         INT32 oldItem, INT32 newItem, POINT32 pt)
1262 {
1263   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1264   NM_TREEVIEW nmhdr;
1265   TREEVIEW_ITEM  *wineItem;
1266
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;
1273   if (oldItem) {
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;
1286   }
1287
1288   if (newItem) {
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;
1301   }
1302
1303   nmhdr.ptDrag.x = pt.x;
1304   nmhdr.ptDrag.y = pt.y;
1305
1306   return (BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
1307                                    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmhdr);
1308
1309 }
1310
1311
1312
1313
1314 static LRESULT
1315 TREEVIEW_Expand (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1316 {
1317  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1318  TREEVIEW_ITEM *wineItem;
1319  UINT32 flag;
1320  INT32 expandItem;
1321  POINT32 pt;
1322  
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;
1329
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;
1334         else
1335                 flag |= TVE_EXPAND;
1336  }
1337
1338  switch (flag) {
1339     case TVE_COLLAPSERESET: 
1340                 if (!wineItem->state & TVIS_EXPANDED) return 0;
1341                 wineItem->state &= ~(TVIS_EXPANDEDONCE | TVIS_EXPANDED);
1342                 TREEVIEW_RemoveAllChildren (infoPtr, wineItem);
1343                 break;
1344
1345     case TVE_COLLAPSE: 
1346                 if (!wineItem->state & TVIS_EXPANDED) return 0;
1347                 wineItem->state &= ~TVIS_EXPANDED;
1348                 break;
1349
1350     case TVE_EXPAND: 
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);
1359         }
1360         wineItem->state |= TVIS_EXPANDED;
1361         break;
1362    case TVE_EXPANDPARTIAL:
1363                 FIXME (treeview, "TVE_EXPANDPARTIAL not implemented\n");
1364                 wineItem->state ^=TVIS_EXPANDED;
1365                 wineItem->state |=TVIS_EXPANDEDONCE;
1366                 break;
1367   }
1368  
1369  TREEVIEW_QueueRefresh (wndPtr);
1370
1371  return TRUE;
1372 }
1373
1374
1375
1376 static HTREEITEM
1377 TREEVIEW_HitTest (WND *wndPtr, LPTVHITTESTINFO lpht)
1378 {
1379  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1380  TREEVIEW_ITEM *wineItem;
1381  RECT32 rect;
1382  UINT32 status,x,y;
1383  
1384
1385
1386  GetClientRect32 (wndPtr->hwndSelf, &rect);
1387  TRACE (treeview,"(%d,%d)\n",lpht->pt.x, lpht->pt.y);
1388
1389  status=0;
1390  x=lpht->pt.x;
1391  y=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;
1396  if (status) {
1397         lpht->flags=status;
1398         return 0;
1399  }
1400
1401  if (!infoPtr->firstVisible) WARN (treeview,"Can't fetch first visible item");
1402  wineItem=&infoPtr->items [infoPtr->firstVisible];
1403
1404  while ((wineItem!=NULL) && (y > wineItem->rect.bottom))
1405        wineItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
1406         
1407  if (wineItem==NULL) {
1408         lpht->flags=TVHT_NOWHERE;
1409         return 0;
1410  }
1411
1412  if (x>wineItem->rect.right) {
1413         lpht->flags|=TVHT_ONITEMRIGHT;
1414         return wineItem->hItem;
1415  }
1416  
1417         
1418  if (x<wineItem->rect.left+10) lpht->flags|=TVHT_ONITEMBUTTON;
1419
1420  lpht->flags=TVHT_ONITEMLABEL;    /* FIXME: implement other flags */
1421         
1422
1423  lpht->hItem=wineItem->hItem;
1424  return wineItem->hItem;
1425 }
1426
1427
1428 static LRESULT
1429 TREEVIEW_HitTest32 (WND *wndPtr, LPARAM lParam)
1430 {
1431  
1432   return (LRESULT) TREEVIEW_HitTest (wndPtr, (LPTVHITTESTINFO) lParam);
1433 }
1434
1435
1436
1437
1438 LRESULT
1439 TREEVIEW_LButtonDoubleClick (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1440 {
1441   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1442   TREEVIEW_ITEM *wineItem;
1443   INT32 iItem;
1444   TVHITTESTINFO ht;
1445
1446   TRACE (treeview,"\n");
1447   ht.pt.x = (INT32)LOWORD(lParam);
1448   ht.pt.y = (INT32)HIWORD(lParam);
1449   SetFocus32 (wndPtr->hwndSelf);
1450
1451   iItem=TREEVIEW_HitTest (wndPtr, &ht);
1452   TRACE (treeview,"item %d \n",iItem);
1453   wineItem=TREEVIEW_ValidItem (infoPtr, iItem);
1454   if (!wineItem) return 0;
1455  
1456   if (TREEVIEW_SendSimpleNotify (wndPtr, NM_DBLCLK)!=TRUE) {     /* FIXME!*/
1457         wineItem->state &= ~TVIS_EXPANDEDONCE;
1458         TREEVIEW_Expand (wndPtr, (WPARAM32) TVE_TOGGLE, (LPARAM) iItem);
1459  }
1460  return TRUE;
1461 }
1462
1463
1464
1465 static LRESULT
1466 TREEVIEW_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1467 {
1468   INT32 iItem;
1469   TVHITTESTINFO ht;
1470
1471   TRACE (treeview,"\n");
1472   ht.pt.x = (INT32)LOWORD(lParam);
1473   ht.pt.y = (INT32)HIWORD(lParam);
1474
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);
1480   }
1481         
1482   if (TREEVIEW_SelectItem (wndPtr, (WPARAM32) TVGN_CARET, (LPARAM) iItem))
1483          return 0;
1484
1485   
1486  return 0;
1487 }
1488
1489
1490 static LRESULT
1491 TREEVIEW_RButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1492 {
1493
1494  TRACE (treeview,"\n");
1495  return 0;
1496 }
1497
1498
1499
1500
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.
1503 */
1504
1505 static LRESULT
1506 TREEVIEW_SelectItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1507 {
1508  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1509  TREEVIEW_ITEM *prevItem,*wineItem;
1510  INT32 action,prevSelect, newSelect;
1511  POINT32 dummy;
1512
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);
1519   dummy.x=0;
1520   dummy.y=0;
1521
1522   action= (INT32) wParam;
1523
1524   switch (action) {
1525         case TVGN_CARET: 
1526             if (TREEVIEW_SendTreeviewNotify (wndPtr, TVN_SELCHANGING, TVC_BYMOUSE, 
1527                                                                                 prevSelect, newSelect,dummy)) 
1528                         return FALSE;       /* FIXME: OK? */
1529                 
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);
1535                 break;
1536         case TVGN_DROPHILITE: 
1537                 FIXME (treeview, "DROPHILITE not implemented");
1538                 break;
1539         case TVGN_FIRSTVISIBLE:
1540                 FIXME (treeview, "FIRSTVISIBLE not implemented");
1541                 break;
1542  }
1543  
1544  TREEVIEW_QueueRefresh (wndPtr);
1545   
1546  return TRUE;
1547 }
1548
1549
1550
1551    
1552 static LRESULT
1553 TREEVIEW_GetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1554
1555 {
1556  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1557
1558  TRACE (treeview,"%x\n",infoPtr->hFont);
1559  return infoPtr->hFont;
1560 }
1561
1562 static LRESULT
1563 TREEVIEW_SetFont (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1564
1565 {
1566  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1567  TEXTMETRIC32A tm;
1568  HFONT32 hFont, hOldFont;
1569  HDC32 hdc;
1570
1571  TRACE (treeview,"%x %lx\n",wParam, lParam);
1572  
1573  infoPtr->hFont = (HFONT32)wParam;
1574
1575  hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
1576
1577  hdc = GetDC32 (0);
1578  hOldFont = SelectObject32 (hdc, hFont);
1579  GetTextMetrics32A (hdc, &tm);
1580  infoPtr->uRealItemHeight= tm.tmHeight + tm.tmExternalLeading;
1581  SelectObject32 (hdc, hOldFont);
1582  ReleaseDC32 (0, hdc);
1583
1584  if (lParam)    
1585         TREEVIEW_QueueRefresh (wndPtr);
1586  
1587  return 0;
1588 }
1589
1590
1591 /* FIXME: does KEYDOWN also send notifications?? If so, use 
1592    TREEVIEW_SelectItem.
1593 */
1594
1595
1596 static LRESULT
1597 TREEVIEW_KeyDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1598 {
1599  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1600  TREEVIEW_ITEM *prevItem,*newItem;
1601  int prevSelect;
1602
1603
1604  TRACE (treeview,"%x %lx\n",wParam, lParam);
1605  prevSelect=infoPtr->selectedItem;
1606  if (!prevSelect) return FALSE;
1607
1608  prevItem= TREEVIEW_ValidItem (infoPtr, prevSelect);
1609  
1610  newItem=NULL;
1611  switch (wParam) {
1612         case VK_UP: 
1613                 newItem=TREEVIEW_GetPrevListItem (infoPtr, prevItem);
1614                 if (!newItem) 
1615                         newItem=& infoPtr->items[infoPtr->TopRootItem];
1616                 break;
1617         case VK_DOWN: 
1618                 newItem=TREEVIEW_GetNextListItem (infoPtr, prevItem);
1619                 if (!newItem) newItem=prevItem;
1620                 break;
1621         case VK_HOME:
1622                 newItem=& infoPtr->items[infoPtr->TopRootItem];
1623                 break;
1624         case VK_END:
1625                 newItem=TREEVIEW_GetLastListItem (infoPtr);
1626                 break;
1627         case VK_PRIOR:
1628         case VK_NEXT:
1629         case VK_BACK:
1630         case VK_RETURN:
1631                 FIXME (treeview, "%x not implemented\n", wParam);
1632                 break;
1633  }
1634
1635  if (!newItem) return FALSE;
1636
1637  if (prevItem!=newItem) {
1638         prevItem->state &= ~TVIS_SELECTED;
1639         newItem->state |= TVIS_SELECTED;
1640         infoPtr->selectedItem=newItem->hItem;
1641         TREEVIEW_QueueRefresh (wndPtr);
1642         return TRUE;
1643  }
1644
1645  return FALSE;
1646 }
1647
1648
1649
1650 static LRESULT
1651 TREEVIEW_VScroll (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
1652
1653 {
1654   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1655   int maxHeight;
1656
1657   TRACE (treeview,"wp %x, lp %lx\n", wParam, lParam);
1658   if (!infoPtr->uInternalStatus & TV_VSCROLL) return FALSE;
1659
1660   switch (LOWORD (wParam)) {
1661         case SB_LINEUP: 
1662                         if (!infoPtr->cy) return FALSE;
1663                         infoPtr->cy -= infoPtr->uRealItemHeight;
1664                         if (infoPtr->cy < 0) infoPtr->cy=0;
1665                         break;
1666         case SB_LINEDOWN: 
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;
1672                         break;
1673         case SB_PAGEUP: 
1674                         if (!infoPtr->cy) return FALSE;
1675                         infoPtr->cy -= infoPtr->uVisibleHeight;
1676                         if (infoPtr->cy < 0) infoPtr->cy=0;
1677                         break;
1678         case SB_PAGEDOWN:
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;
1684                         break;
1685         case SB_THUMBTRACK: 
1686                         infoPtr->cy = HIWORD (wParam);
1687                         break;
1688                         
1689   }
1690   
1691   TREEVIEW_QueueRefresh (wndPtr);
1692   return TRUE;
1693 }
1694
1695 static LRESULT
1696 TREEVIEW_HScroll (WND *wndPtr, WPARAM32 wParam, LPARAM lParam) 
1697 {
1698   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
1699
1700   TRACE (treeview,"wp %lx, lp %x\n", lParam, wParam);
1701         
1702   if (!infoPtr->uInternalStatus & TV_HSCROLL) return FALSE;
1703   return TRUE;
1704 }
1705
1706
1707
1708
1709 LRESULT WINAPI
1710 TREEVIEW_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
1711 {
1712   WND *wndPtr = WIN_FindWndPtr(hwnd);
1713   
1714   
1715     switch (uMsg) {
1716         case TVM_INSERTITEM32A:
1717           return TREEVIEW_InsertItem32A (wndPtr, wParam, lParam);
1718
1719         case TVM_INSERTITEM32W:
1720                 FIXME (treeview, "Unimplemented msg TVM_INSERTITEM32W\n");
1721                 return 0;
1722
1723         case TVM_DELETEITEM:
1724                 return TREEVIEW_DeleteItem (wndPtr, wParam, lParam);
1725
1726         case TVM_EXPAND:
1727                 return TREEVIEW_Expand (wndPtr, wParam, lParam);
1728
1729         case TVM_GETITEMRECT:
1730                 return TREEVIEW_GetItemRect (wndPtr, wParam, lParam);
1731
1732         case TVM_GETCOUNT:
1733                 return TREEVIEW_GetCount (wndPtr, wParam, lParam);
1734
1735         case TVM_GETINDENT:
1736                 return TREEVIEW_GetIndent (wndPtr);
1737
1738         case TVM_SETINDENT:
1739                 return TREEVIEW_SetIndent (wndPtr, wParam);
1740
1741         case TVM_GETIMAGELIST:
1742                 return TREEVIEW_GetImageList (wndPtr, wParam, lParam);
1743
1744                 case TVM_SETIMAGELIST:
1745                 return TREEVIEW_SetImageList (wndPtr, wParam, lParam);
1746
1747         case TVM_GETNEXTITEM:
1748                 return TREEVIEW_GetNextItem32 (wndPtr, wParam, lParam);
1749
1750         case TVM_SELECTITEM:
1751                 return TREEVIEW_SelectItem (wndPtr, wParam, lParam);
1752
1753         case TVM_GETITEM32A:
1754                 return TREEVIEW_GetItem (wndPtr, wParam, lParam);
1755
1756         case TVM_GETITEM32W:
1757                 FIXME (treeview, "Unimplemented msg TVM_GETITEM32W\n");
1758                 return 0;
1759
1760         case TVM_SETITEM32A:
1761                 return TREEVIEW_SetItem (wndPtr, wParam, lParam);
1762
1763         case TVM_SETITEM32W:
1764                 FIXME (treeview, "Unimplemented msg TVM_SETITEMW\n");
1765                 return 0;
1766
1767         case TVM_EDITLABEL32A:
1768                 FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32A \n");
1769                 return 0;
1770
1771         case TVM_EDITLABEL32W:
1772                 FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32W \n");
1773                 return 0;
1774
1775         case TVM_GETEDITCONTROL:
1776                 FIXME (treeview, "Unimplemented msg TVM_GETEDITCONTROL\n");
1777                 return 0;
1778
1779         case TVM_GETVISIBLECOUNT:
1780                 return TREEVIEW_GetVisibleCount (wndPtr, wParam, lParam);
1781
1782         case TVM_HITTEST:
1783                 return TREEVIEW_HitTest32 (wndPtr, lParam);
1784
1785         case TVM_CREATEDRAGIMAGE:
1786                 FIXME (treeview, "Unimplemented msg TVM_CREATEDRAGIMAGE\n");
1787                 return 0;
1788   
1789         case TVM_SORTCHILDREN:
1790                 FIXME (treeview, "Unimplemented msg TVM_SORTCHILDREN\n");
1791                 return 0;
1792   
1793         case TVM_ENSUREVISIBLE:
1794                 FIXME (treeview, "Unimplemented msg TVM_ENSUREVISIBLE\n");
1795                 return 0;
1796   
1797         case TVM_SORTCHILDRENCB:
1798                 FIXME (treeview, "Unimplemented msg TVM_SORTCHILDRENCB\n");
1799                 return 0;
1800   
1801         case TVM_ENDEDITLABELNOW:
1802                 FIXME (treeview, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
1803                 return 0;
1804   
1805         case TVM_GETISEARCHSTRING32A:
1806                 FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
1807                 return 0;
1808   
1809         case TVM_GETISEARCHSTRING32W:
1810                 FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
1811                 return 0;
1812   
1813         case TVM_GETTOOLTIPS:
1814                 return TREEVIEW_GetToolTips (wndPtr);
1815
1816         case TVM_SETTOOLTIPS:
1817                 return TREEVIEW_SetToolTips (wndPtr, wParam);
1818   
1819         case TVM_SETINSERTMARK:
1820                 FIXME (treeview, "Unimplemented msg TVM_SETINSERTMARK\n");
1821                 return 0;
1822   
1823         case TVM_SETITEMHEIGHT:
1824                 return TREEVIEW_SetItemHeight (wndPtr, wParam);
1825   
1826         case TVM_GETITEMHEIGHT:
1827                 return TREEVIEW_GetItemHeight (wndPtr);
1828   
1829         case TVM_SETBKCOLOR:
1830                 FIXME (treeview, "Unimplemented msg TVM_SETBKCOLOR\n");
1831                 return 0;
1832         
1833         case TVM_SETTEXTCOLOR:
1834                 return TREEVIEW_SetTextColor (wndPtr, wParam, lParam);
1835   
1836         case TVM_GETBKCOLOR:
1837                 FIXME (treeview, "Unimplemented msg TVM_GETBKCOLOR\n");
1838                 return 0;
1839   
1840         case TVM_GETTEXTCOLOR:
1841                 return TREEVIEW_GetTextColor (wndPtr);
1842   
1843         case TVM_SETSCROLLTIME:
1844                 FIXME (treeview, "Unimplemented msg TVM_SETSCROLLTIME\n");
1845                 return 0;
1846   
1847         case TVM_GETSCROLLTIME:
1848                 FIXME (treeview, "Unimplemented msg TVM_GETSCROLLTIME\n");
1849                 return 0;
1850   
1851         case TVM_SETINSERTMARKCOLOR:
1852                 FIXME (treeview, "Unimplemented msg TVM_SETINSERTMARKCOLOR\n");
1853                 return 0;
1854   
1855         case TVM_SETUNICODEFORMAT:
1856                 FIXME (treeview, "Unimplemented msg TVM_SETUNICODEFORMAT\n");
1857                 return 0;
1858   
1859         case TVM_GETUNICODEFORMAT:
1860                 FIXME (treeview, "Unimplemented msg TVM_GETUNICODEFORMAT\n");
1861                 return 0;
1862   
1863 /*              case WM_COMMAND: */
1864   
1865                 case WM_CREATE:
1866                         return TREEVIEW_Create (wndPtr, wParam, lParam);
1867   
1868                 case WM_DESTROY:
1869                         return TREEVIEW_Destroy (wndPtr);
1870   
1871 /*              case WM_ENABLE: */
1872   
1873                 case WM_ERASEBKGND:
1874                 return TREEVIEW_EraseBackground (wndPtr, wParam, lParam);
1875   
1876                 case WM_GETDLGCODE:
1877                 return DLGC_WANTARROWS | DLGC_WANTCHARS;
1878   
1879                 case WM_PAINT:
1880                 return TREEVIEW_Paint (wndPtr, wParam);
1881   
1882                 case WM_GETFONT:
1883                 return TREEVIEW_GetFont (wndPtr, wParam, lParam);
1884
1885                 case WM_SETFONT:
1886                 return TREEVIEW_SetFont (wndPtr, wParam, lParam);
1887   
1888                 case WM_KEYDOWN:
1889                         return TREEVIEW_KeyDown (wndPtr, wParam, lParam);
1890   
1891   
1892 /*              case WM_KILLFOCUS: */
1893 /*              case WM_SETFOCUS: */
1894   
1895   
1896                 case WM_LBUTTONDOWN:
1897                         return TREEVIEW_LButtonDown (wndPtr, wParam, lParam);
1898   
1899                 case WM_LBUTTONDBLCLK:
1900                         return TREEVIEW_LButtonDoubleClick (wndPtr, wParam, lParam);
1901   
1902                 case WM_RBUTTONDOWN:
1903                         return TREEVIEW_RButtonDown (wndPtr, wParam, lParam);
1904   
1905   
1906 /*              case WM_SYSCOLORCHANGE: */
1907 /*              case WM_STYLECHANGED: */
1908 /*              case WM_SETREDRAW: */
1909   
1910                 case WM_TIMER:
1911                         return TREEVIEW_HandleTimer (wndPtr, wParam, lParam);
1912   
1913 /*              case WM_SIZE: */
1914                 case WM_HSCROLL: 
1915                         return TREEVIEW_HScroll (wndPtr, wParam, lParam);
1916                 case WM_VSCROLL: 
1917                         return TREEVIEW_VScroll (wndPtr, wParam, lParam);
1918   
1919                 default:
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);
1924       }
1925     return 0;
1926 }
1927
1928
1929 VOID
1930 TREEVIEW_Register (VOID)
1931 {
1932     WNDCLASS32A wndClass;
1933
1934     TRACE (treeview,"\n");
1935
1936     if (GlobalFindAtom32A (WC_TREEVIEW32A)) return;
1937
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;
1946  
1947     RegisterClass32A (&wndClass);
1948 }
1949
1950
1951 VOID
1952 TREEVIEW_Unregister (VOID)
1953 {
1954     if (GlobalFindAtom32A (WC_TREEVIEW32A))
1955         UnregisterClass32A (WC_TREEVIEW32A, (HINSTANCE32)NULL);
1956 }
1957