https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2fdfb411b69932e765ed8b64646cae76f3e3193f

commit 2fdfb411b69932e765ed8b64646cae76f3e3193f
Author:     Hermès Bélusca-Maïto <[email protected]>
AuthorDate: Sun Jan 28 22:10:51 2018 +0100
Commit:     Hermès Bélusca-Maïto <[email protected]>
CommitDate: Tue Nov 6 00:09:14 2018 +0100

    [REACTOS] Add a TreeList control (TreeView with columns).
    
    Add the TreeList control from Anton Zechner and Sébastien Kirche
    from https://github.com/sebkirche/treelist (under GPL-3.0+) as a
    *TEMPORARY* solution until a better-suited control for ReactOS is
    developed.
    
    - Compilation fixes for the TreeList control.
---
 base/setup/reactos/CMakeLists.txt |     1 +
 base/setup/reactos/treelist.c     | 13733 ++++++++++++++++++++++++++++++++++++
 base/setup/reactos/treelist.h     |   493 ++
 3 files changed, 14227 insertions(+)

diff --git a/base/setup/reactos/CMakeLists.txt 
b/base/setup/reactos/CMakeLists.txt
index 39225e758e..8c58f9e360 100644
--- a/base/setup/reactos/CMakeLists.txt
+++ b/base/setup/reactos/CMakeLists.txt
@@ -11,6 +11,7 @@ list(APPEND SOURCE
     spapisup/infsupp.c
     drivepage.c
     reactos.c
+    treelist.c
     reactos.h)
 
 file(GLOB reactos_rc_deps res/*.*)
diff --git a/base/setup/reactos/treelist.c b/base/setup/reactos/treelist.c
new file mode 100644
index 0000000000..1681b6189a
--- /dev/null
+++ b/base/setup/reactos/treelist.c
@@ -0,0 +1,13733 @@
+/*
+ * PROJECT:     ReactOS GUI first stage setup application
+ * LICENSE:     GPL-3.0-or-later (https://spdx.org/licenses/GPL-3.0-or-later)
+ * PURPOSE:     Implements a TreeList control: a tree window with columns.
+ * COPYRIGHT:   Copyright (C) Anton Zechner ([email protected]) 2007
+ *              Copyright (C) S�bastien Kirche ([email protected]) 2014
+ *
+ * NOTE: Taken from the TreeList code found at 
https://github.com/sebkirche/treelist
+ */
+
+//*****************************************************************************
+//*
+//*
+//*            TreeListWnd.cpp
+//*
+//*
+//*****************************************************************************
+//
+//     This code creates a tree window with a list
+//
+//
+//     Copyright (C) Anton Zechner ([email protected]) 2007
+//     Copyright (C) S�bastien Kirche ([email protected]) 2014
+//
+//     TreeListWnd is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+//     Sourcecode which use TreeListWnd must be published. Commercial users
+//     must published their code too, or make an licence agreement with me.
+//
+//
+//     TreeListWnd wird unter GNU GENERAL PUBLIC LICENSE (GPL) vertreiben.
+//     Sourcecode welcher TreeListWnd verwendet muss ver�ffendlicht werden.
+//     Komerzielle Nutzer m�ssen ihren Code ebenfalls ver�ffentlichen, oder
+//     eine Nutzungsvereinbarung mit mir treffen.
+//
+//
+//     Version:        2.04
+//
+#ifdef         UNICODE
+#ifndef           _UNICODE
+#define    _UNICODE
+#endif
+#endif
+
+#if 0
+    #include   <stdio.h>
+    #include   <windows.h>
+    #include   <string.h>
+    #include   <malloc.h>
+    #include   <tchar.h>
+#else
+    #include "reactos.h"
+#endif
+
+#define new(TYPE, numElems) \
+    HeapAlloc(GetProcessHeap(), 0, (numElems) * sizeof(TYPE))
+#define delete(ptr) \
+    HeapFree(GetProcessHeap(), 0, (ptr))
+
+
+#include       "treelist.h"
+
+#ifndef                GWLP_USERDATA
+#define        GWLP_USERDATA           GWL_USERDATA
+#endif
+#ifndef        GWLP_WNDPROC
+#define        GWLP_WNDPROC            GWL_WNDPROC
+#endif
+#ifndef           _WIN64
+#ifndef                SetWindowLongPtr
+#define                SetWindowLongPtr        SetWindowLong
+#endif
+#ifndef                GetWindowLongPtr
+#define                GetWindowLongPtr        GetWindowLong
+#endif
+#ifndef                DWORD_PTR
+#define                DWORD_PTR                       DWORD
+#endif
+#ifndef                LONG_PTR
+#define                LONG_PTR                        LONG
+#endif
+#endif
+#ifdef         UNICODE
+#define        str_len                         (unsigned)wcslen
+#define        str_cmp                         wcscmp
+#define        str_ncpy                        wcsncpy
+#define        str_ncmp                        wcsncmp
+#define        str_icmp                   _wcsicmp
+#else
+#define        str_len                         (unsigned)strlen
+#define        str_cmp                         strcmp
+#define        str_ncpy                        strncpy
+#define        str_ncmp                        strncmp
+#define        str_icmp                   _stricmp
+#endif
+#ifndef                WM_MOUSEWHEEL
+#define                WM_MOUSEWHEEL           0x020A
+#endif
+#ifndef                WHEEL_DELTA
+#define                WHEEL_DELTA                     120
+#endif
+#ifndef                MAX_COLUMNS
+#define        MAX_COLUMNS                     32
+#endif
+#define                MAX_COLORS                      16
+#define        EN_SETTEXT                      0x1000
+#define        EN_RETURN                       0x1578
+#define        EN_ESCAPE                       0x1579
+#define        ID_TOOLTIPCHECK         0x3912
+#define        SORT_NOUPDATE           1234567
+#define        VK_ISACHAR                      0x01000000
+#define        FIRST_LINE                      0xFFFFFFFE
+#define        FROM_HEADER                     0x88776655
+#define        I_CCB                           I_CHILDRENCALLBACK
+#define        U(h)                            ((unsigned)(h))
+#define        THEMEIMGLIST            ((HIMAGELIST)1)
+#define        GetHandle(h)            ((TreeListData*)GetWindowLongPtr(h,0))
+#define        TVIF_ALL                        
(TVIF_CHILDREN|TVIF_HANDLE|TVIF_IMAGE|TVIF_PARAM|TVIF_SELECTEDIMAGE|TVIF_STATE|TVIF_TEXT)
+#define        UNLOCK(d)                       ReleaseSemaphore(d->hSem,1,NULL)
+#define        LOCK(d)                         
WaitForSingleObject(d->hSem,INFINITE)
+#define        TVIS_EDIT(m)            
((1<<m)&((1<<TVAX_EDIT)|(1<<TVAX_COMBO)|(1<<TVAX_STEPED)|(1<<TVAX_CHECKED)))
+#define        TVIS_BASEFLAGS          
(TVIS_EXPANDED|TVIS_EXPANDEDONCE|TVIS_EXPANDPARTIAL|TVIS_SELECTED)
+#define        TVIS_TRACKED            (TVIX_TRACKED<<16)
+#define        TVIS_BKCOLOR            (TVIX_BKCOLOR<<16)
+#undef TVIS_FOCUSED
+#define        TVIS_FOCUSED            (TVIX_FOCUSED<<16)
+#define        TVIS_TEXTCOLOR          (TVIX_TEXTCOLOR<<16)
+#define        TVC_ONLYFOCUS           TVIF_ONLYFOCUS
+#define        TVC_UNSELECT            0x4000
+#define        TVC_DESELECT            0x8000
+#define        DEFAULT_IDENT           19
+#define        DEFAULT_SHIFT           7
+#ifndef                BPBF_COMPATIBLEBITMAP
+#define        BPBF_COMPATIBLEBITMAP   0
+#endif
+#ifndef                TVP_GLYPH
+#define                TVP_GLYPH                       2
+#endif
+#ifndef                GLPS_CLOSED
+#define                GLPS_CLOSED                     1
+#endif
+#ifndef                GLPS_OPENED
+#define                GLPS_OPENED                     2
+#endif
+#ifndef                BP_CHECKBOX
+#define                BP_CHECKBOX                     3
+#endif
+#ifndef                CBS_UNCHECKEDNORMAL
+#define                CBS_UNCHECKEDNORMAL 1
+#endif
+#ifndef                CBS_CHECKEDNORMAL
+#define                CBS_CHECKEDNORMAL       5
+#endif
+
+
+#define        TVAX_NONE                       (TVAE_NONE   >>TVAE_MODEPOS)// 
No automatic edit
+#define        TVAX_EDIT                       (TVAE_EDIT       
>>TVAE_MODEPOS)// automatic edit with edit
+#define        TVAX_COMBO                      (TVAE_COMBO      
>>TVAE_MODEPOS)// automatic edit with ComboBox
+#define        TVAX_CBLIST                     (TVAE_CBLIST >>TVAE_MODEPOS)// 
automatic edit with  ComboListBox
+#define        TVAX_STEP                       (TVAE_STEP       
>>TVAE_MODEPOS)// Einzelnes Weiterschalten mit Enter
+#define        TVAX_STEPED                     (TVAE_STEPED >>TVAE_MODEPOS)// 
Einzelnes Weiterschalten mit Enter und Edit
+#define        TVAX_CHECK                      (TVAE_CHECK      
>>TVAE_MODEPOS)// automatic edit with  CheckBox
+#define        TVAX_CHECKED            (TVAE_CHECKED>>TVAE_MODEPOS)// 
automatic edit with CheckBox and Edit
+
+#define        TVIX_VARBUTTON          0x01                                    
        // buttons are not permanent
+#define        TVIX_HASBUTTON          0x02                                    
        // entry has button
+#define        TVIX_HASIMAGE           0x04                                    
        // entry has icon
+#define        TVIX_TRACKED            0x08                                    
        // entry under the cursor
+#define        TVIX_TEXTCOLOR          0x10                                    
        // entry has its own text color
+#define        TVIX_BKCOLOR            0x20                                    
        // entry has its own backround color
+#define        TVIX_FOCUSED            0x40                                    
        // entry has the focus
+
+typedef struct {
+       LPARAM          lParam;                                                 
                        // LPARAM argument for the item
+       LPTSTR          pText;                                                  
                        // pointer to the item text
+       UINT            uState;                                                 
                        // item state
+       int                     iImage;                                         
                                // item image index 
+       int                     iSelectedImage;                                 
                        // item selected image index
+       unsigned        uShowPos;                                               
                        // Ist die Position in der Sichtbarliste (0=unsichtbar)
+       unsigned        uFirstChild;                                            
                // Ist die Nummer des ersten Kind-Eintrages (0=keines)
+       unsigned        uLastChild;                                             
                        // Ist die Nummer des letzten Kind-Eintrages (0=keines)
+       unsigned        uPrevItem;                                              
                        // Ist die Nummer des vorherigen Eintrages (0=keines)
+       unsigned        uNextItem;                                              
                        // Ist die Nummer des n�chsten Eintrages (0=keines)
+       unsigned        uParent;                                                
                        // Ist die Nummer des Elterneintrages (0=Root)
+       unsigned        uLevel;                                                 
                        // Ist die Ebene des Eintrages (0=Root)
+       int             iTextPixels;                                            
                // Ist die Breites des Textes in Pixel
+       WORD            uTextSize;                                              
                        // L�nge des Textes in Zeichen
+       BYTE            bCallback;                                              
                        // Sind Bits f�r Callbacks
+       BYTE            bFlags;                                                 
                        // Diverse Flags
+       COLORREF        uColorText;                                             
                        // Spezielle Textfarbe
+       COLORREF        uColorBk;                                               
                        // Spezielle Hintergrundfarbe
+} BaseItem;
+
+typedef struct {
+       LPTSTR          pText;                                                  
                        // Zeiger auf Tree-Text
+       UINT            uState;                                                 
                        // Zustand des Eintrages
+       int                     iImage;                                         
                                // Ist die Nummer des an zu zeigenden Icons
+       int             iTextPixels;                                            
                // Ist die Breites des Textes in Pixel
+       WORD            uTextSize;                                              
                        // L�nge des Textes in Zeichen
+       BYTE            bCallback;                                              
                        // Sind Bits f�r Callbacks
+       BYTE            bFlags;                                                 
                        // Diverse Flags
+       COLORREF        uColorText;                                             
                        // Spezielle Textfarbe
+       COLORREF        uColorBk;                                               
                        // Spezielle Hintergrundfarbe
+} ExtraItem;
+
+typedef struct {
+       void       *pCbData;                                                    
                // Data for autoedit
+       INT         iCbIcon;                                                    
                // Starting offset for in icon list for autoedit
+       short           sSize;                                                  
                        // width of the column
+       short           sReal;                                                  
                        // real width of the column
+       short           sMin;                                                   
                        // minimum width
+       short       sFixed;                                                     
                        // fixed width
+       BYTE            bMinEx;                                                 
                        // the width cannot be less than min width
+       BYTE            bWeight;                                                
                        // weight for variable columns
+       BYTE            bNext;                                                  
                        // Ist die Spalte die nach der eigenen sichtbar ist     
(gespeicherte Reihenfolge)
+       BYTE            bIndex;                                                 
                        // Ist die Spalte in der diese Reihe sichtbar ist 
(sichtbarer Index)
+       BYTE        bAlign;                                                     
                        // Text alignment
+       BYTE        bEdit;                                                      
                        // Automaisches Editiern einer Spalte (siehe 
TVAE_???>>7)
+       BYTE        bFlags;                                                     
                        // Automaisches Editiern einer Spalte (siehe TVAE_???)
+       BYTE        bEnable;                                                    
                // Automaisches einer mit Statebits aktivieren
+       BYTE        bCbSize;                                                    
                // Maximum number of entries in the data list
+       BYTE        bCbChar;                                                    
                // separator for the data list
+       BYTE        bMark;                                                      
                        // is column marked ?
+       BYTE        bDummy[32 - 23 - sizeof(void *)];                   // 
padding bytes - 32 bytes alignment
+} ColumnData;
+
+typedef struct {
+       HWND            hWnd;                                                   
                        // handle of the control
+       HANDLE          hSem;                                                   
                        // access semaphore
+       LPVOID          hTheme;                                                 
                        // Handle f�r benutztes Thema (TREELIST)
+       LPVOID          hThemeBt;                                               
                        // Handle f�r benutztes Thema (BUTTON)
+       WNDPROC         pProcId3;                                               
                        // Fenster Funktion f�r ID3 Fenster
+       HIMAGELIST      hStates;                                                
                        // Handle der Icon-Liste f�r States und Overlay
+       HIMAGELIST      hImages;                                                
                        // Handle der Icon-Liste
+       HIMAGELIST      hChecks;                                                
                        // Handle der Icon-Liste f�r die Checkboxen in den 
Spalten
+       HIMAGELIST      hSubImg;                                                
                        // Handle der Icon-Liste f�r die Spalten
+       HIMAGELIST      hHeadImg;                                               
                        // Handle for header images
+       HFONT           hFontN;                                                 
                        // Normal font
+       HFONT           hFontB;                                                 
                        // Bold fonts
+       HFONT           hFontL;                                                 
                        // Last used font
+       HFONT           hFontT;                                                 
                        // Tooltip font
+       HWND            hEdit;                                                  
                        // Handle des Edit-Fensters
+       HWND            hHeader;                                                
                        // Handle des Header Fensters
+       HWND            hToolTip;                                               
                        // Handle des Tooltip-Fensters
+       WNDPROC         pToolProc;                                              
                        // Alte Fensterfunktion des Tooltips
+       COLORREF        uColors[MAX_COLORS];                                    
        // 0=Hintergrundfarbe  1=Abwechselnte Farbe  2=Farbe f�r Trennlinien  
3=Textfarbe
+       int                     iFontHeight;                                    
                        // Ist die H�he des Fonts
+       int                     iFontLine;                                      
                                // Ist die Position der Linie beim 
unterstreichen
+       int                     iFontOff;                                       
                                // Ist die Position um der ein Text horizontal 
verschoben wird
+       int                     iStatesMode;                                    
                        // Die hStates Image-Liste wurde f�r die Checkboxen 
erzeugt
+       int                     iStatesXsize;                                   
                        // Breite der States und Overlay Icons
+       int                     iStatesYsize;                                   
                        // H�he   der States und Overlay Icons
+       int                     iChecksMode;                                    
                        // Die hChecks Image-Liste wurde f�r die Checkboxen 
erzeugt
+       int                     iChecksXsize;                                   
                        // Breite der States und Overlay Icons
+       int                     iChecksYsize;                                   
                        // H�he   der States und Overlay Icons
+       int                     iImagesXsize;                                   
                        // Breite der Icons
+       int                     iImagesYsize;                                   
                        // H�he   der Icons
+       int                     iSubImgMode;                                    
                        // Die SubImg Image-Liste ist nicht die hImages Liste
+       int                     iSubImgXsize;                                   
                        // Breite der Icons
+       int                     iSubImgYsize;                                   
                        // H�he   der Icons
+       int                     iRowHeight;                                     
                                // Ist die H�he einer Zeile
+       int                     iAllWeight;                                     
                                // Das Gewicht aller variablen Spalten
+       int                     iVarSize;                                       
                                // Ist die Breite aller variablen Spalten
+       int                     iFixSize;                                       
                                // Ist die Breite aller fixen Spalten
+       int                     iIndent;                                        
                                // Einr�ckung der Kindereint�ge
+       int                     iShift;                                         
                                // Einr�ckung der vertikalen Linien
+       int                     iAutoAdd;                                       
                                // Offset zum Open-Icon  f�r 
TVS_EX_AUTOEXPANDICON
+       int                     iMaxSizeX;                                      
                                // Die Gr��e des breitesten sichtbaren Eintrages
+       unsigned        uItemPosCount;                                          
                // Anzahl der sichtbaren Eintr�ge
+       unsigned   *pItemPos;                                                   
                // Liste mit den Offsets der sichtbaren Eintr�ge
+       BaseItem  **pTreeItems;                                                 
                // Zeiger auf Item Zeiger
+       ExtraItem **pExtraItems[MAX_COLUMNS - 1];                               
// Zeiger auf die Spalteneintr�ge
+       unsigned        uTreeItemsMax;                                          
                // Gr��e der Liste mit den vorhanden Eintr�ge (alociert um 1 
gr��er)
+       unsigned        uTreeItemsCount;                                        
                // Anzahl der vorhanden Eintr�ge
+       unsigned        uNextSeachPos;                                          
                // N�chste Position zum suchen von freien Eintr�gen
+       unsigned        uUserDataSize;                                          
                // Ist die Gr��e der Userdaten in einem Eintrag
+       unsigned        uFirstChild;                                            
                // Ist die Nummer des ersten Kind-Eintrages (0=keines)
+       unsigned        uLastChild;                                             
                        // Ist die Nummer des letzten Kind-Eintrages (0=keines)
+       unsigned        uSingleSel;                                             
                        // Ist die Nummer des gew�hlten Eintrages (bei 
Checkboxen)
+       unsigned        uScrollX;                                               
                        // Aktuelle X-Scroll-Position
+       unsigned        uScrollY;                                               
                        // Aktuelle Y-Scroll-Position
+       unsigned        uSizeX;                                                 
                        // Aktuelle X-Fenster-Gr��e
+       unsigned        uSizeY;                                                 
                        // Aktuelle Y-Fenster-Gr��e
+       unsigned        uSizeYsub;                                              
                        // Aktuelle Y-Fenster-Gr��e ohne Header
+       unsigned        uStyle;                                                 
                        // Ist der aktuele Style des Fensters
+       unsigned        uStyleEx;                                               
                        // Erweiterte Sytle-Flags (siehe TVS_EX_???)
+       unsigned        uStartPixel;                                            
                // Ist die Y-Koordinate bei der der erste Eintrag beginnt
+       unsigned        uMaxEnties;                                             
                        // Anzahl der sichtbaren Eintr�ge (inkl. halbsichtbare)
+       unsigned        uPageEnties;                                            
                // Anzahl der sichtbaren Eintr�ge (ohne  halbsichtbare)
+       unsigned        uColumnCount;                                           
                // Anzahl der Spalten
+       unsigned        uColumnCountVar;                                        
                // Anzahl der variabeln Spalten
+       unsigned        uSelectedCount;                                         
                // Anzahl der ausgew�hlten Eintr�ge
+       unsigned        uSelectedBase;                                          
                // Ist der Eintrag ab dem gew�hlt wurde
+       unsigned        uSelectedItem;                                          
                // Ist der Eintrag der gerade gew�hlt ist
+       unsigned        uSelectedSub;                                           
                // Ist die Spalte die gerade gew�hlt ist
+       unsigned        uFocusItem;                                             
                        // Ist der Eintrag der einen leeren Focus hat
+       unsigned        uFocusSub;                                              
                        // Ist die Spalte die einen leeren Focus hat
+       unsigned        uToolTipItem;                                           
                // Ist der ToolTip-Eintrag der gerade gew�hlt ist
+       unsigned        uToolTipShow;                                           
                // Ist die Zeitverz�gerung in 500 ms Schritten f�r das Tooltip
+       unsigned        uToolTipSub;                                            
                // Ist die ToolTip-Spalte die gerade gew�hlt ist
+       POINT           sToolTipPos;                                            
                // Ist die globale Koordinate des ToolTips
+       unsigned        uEditMode;                                              
                        // Ist der Modus des Editfensters (0=Edit 1=ComboBox 
2=ComboBox fix)
+       unsigned        uEditItem;                                              
                        // Ist der Eintrag der gerade editiert wird
+       unsigned        uEditSub;                                               
                        // Ist die Spalte die gerade editiert wird
+       unsigned        uOldXPage;                                              
                        // Alte Werte f�r X-Scroll-Bar
+       unsigned        uOldXCount;                                             
                        //                      *
+       unsigned        uOldYPage;                                              
                        // Alte Werte f�r Y-Scroll-Bar
+       unsigned        uOldYCount;                                             
                        //                      *
+       unsigned        uTrippleB;                                              
                        // Bereite des "..." Strings f�r den fetten Fonts
+       unsigned        uTrippleN;                                              
                        // Bereite des "..." Strings f�r den normalen Fonts
+       unsigned        uTrackedItem;                                           
                // Ist der Eintrag der unterstrichen werden soll
+       unsigned        uTrackedSub;                                            
                // Ist die Spalte des Eintrages der unterstrichen werden soll
+       unsigned        uInsertMark;                                            
                // Ist der Eintrag mit der Einf�gemarke
+       unsigned        uMarkedCols;                                            
                // Anzahl der markierten Spalten
+       unsigned        uDragFlags;                                             
                        // Welche Maustasten sind an
+       unsigned        uDragItem;                                              
                        // Eintrag f�r Dragoperation
+       unsigned        uDragSub;                                               
                        // Untereintrag f�r Dragoperation
+       unsigned        uLastSel;                                               
                        // Letzte Textauswahl beim Editieren
+       unsigned        uLastMove;                                              
                        // Letzte Cursorposition bei WM_MOUSEMOVE
+       unsigned        uButtonPos;                                             
                        // Wo wurde eine Maustaste wurde zuletzt gedr�ckt
+       unsigned        uButtonLast;                                            
                // Wann wurde eine Maustaste wurde zuletzt gedr�ckt
+       unsigned        uToolTipSize;                                           
                // Textspeichergr��e f�r Tooltip
+       LPTSTR          pToolTipText;                                           
                // Textspeicher f�r Tooltip
+       TCHAR           cTempText1   [260];                                     
                // Erster Textpuffer f�r Callbacks
+       TCHAR           cTempText2   [260];                                     
                // Zeiter Textpuffer f�r Callbacks
+       ColumnData      aColumn      [MAX_COLUMNS];                             
        // Daten der Spalten
+       int                     aColumnXpos  [MAX_COLUMNS + 2];                 
        // Array mit den Positionen der Spalten
+       BYTE            aColumnPos   [MAX_COLUMNS + 2];                         
// Array mit Anzeigepositionen der Spalten
+       char            cColorChanged[MAX_COLORS ];                             
        // Welche Farbe wurden ver�ndert
+       char        cColumnStart;                                               
                // Wurde das Autoeditiren mit einer WM_CHAR Eingabe gestartet
+       char            cFixedHeight;                                           
                // Ist eine fixe H�he eingestellt
+       char            cLockChanges;                                           
                // Sperren von Fenster�nderungen
+       char            cHasRootRow;                                            
                // Wird gesetzt wenn eine Root-Spalte eingef�gt wird
+       char            cKeyIgnore;                                             
                        // Die n�chste Taste nicht f�r Sucher verwenden
+       char            cClickFlag;                                             
                        // Merker f�r LBUTTON-DOWN bei Multiselect
+       char            cClickEdit;                                             
                        // Merker f�r LBUTTON-DOWN bei Edit-Click
+       char            cIsEnabled;                                             
                        // Ist das Fenster freigegeben
+       char            cHasFocus;                                              
                        // Hat das Fenster den Focus
+       char            cReSelect;                                              
                        // Soll die Auswahl neu selektiert werden
+       char            cGlyphOk;                                               
                        // Die Schaltf�che �ber Themen zeichnen
+       char            cEditCb;                                                
                        // Muss das Edit-Fenster einen Callback aufrufen
+       char            cButtonFlag;                                            
                // Welche Maustaste wurde zuletzt gedr�ckt
+} TreeListData;
+
+typedef        HRESULT(WINAPI *SetWindowThemeT)(HWND, LPCWSTR, LPCWSTR);
+typedef        HRESULT(WINAPI *EndBufferedPtT)(HANDLE, BOOL);
+typedef        HANDLE(WINAPI *BeginBufferedPnT)(HDC, RECT *, DWORD, LPVOID, 
HDC *);
+typedef        HRESULT(WINAPI *BufferedPtInitT)(VOID);
+typedef        HRESULT(WINAPI *BufferedPtInitT)(VOID);
+typedef        LPVOID (WINAPI *OpenThemeDataT)(HWND hwnd, LPCWSTR 
pszClassList);
+typedef        HRESULT(WINAPI *CloseThemeDataT)(LPVOID);
+typedef        HRESULT(WINAPI *DrawThemeBackgT)(LPVOID, HDC, int, int, const 
RECT *, const RECT *);
+typedef        HRESULT(WINAPI *GetThemeBackgRcT)(LPVOID, HDC, int, int, 
LPCRECT, LPRECT);
+typedef BOOL (WINAPI *IsAppThemedT)();
+typedef BOOL (WINAPI *IsThemeActiveT)();
+
+static HMODULE                 hUxThemeDll             = NULL;
+static SetWindowThemeT pSetWindowTheme = NULL;
+static EndBufferedPtT  pEndBufferedPt  = NULL;
+static BeginBufferedPnT        pBeginBufferedPt = NULL;
+static BufferedPtInitT pBufferedPtInit = NULL;
+static BufferedPtInitT pBufferedPtExit = NULL;
+static OpenThemeDataT  pOpenThemeData  = NULL;
+static CloseThemeDataT pCloseThemeData = NULL;
+static DrawThemeBackgT pDrawThemeBackg = NULL;
+static GetThemeBackgRcT        pGetThemeBackgRc = NULL;
+static IsAppThemedT            pIsAppThemed    = NULL;
+static IsThemeActiveT  pIsThemeActive  = NULL;
+static HPEN                            hPatternPen             = NULL;
+static HFONT                   hDefaultFontN   = NULL;
+static HFONT                   hDefaultFontB   = NULL;
+static LONG                            lWindowCount    = -1;
+#ifndef __REACTOS__
+static RECT                            sToolRect = { -2, 0, 2, 64};
+#endif
+static TCHAR                   cKeyData[16];
+static unsigned                uKeyLast;
+static unsigned                uKeyPos;
+static void                            TreeListDraw(HWND hWnd, HDC hDc, RECT 
*pRect);
+static LRESULT CALLBACK TreeListProc(HWND hWnd, UINT uMsg, WPARAM wParam, 
LPARAM lParam);
+static int                             TreeListSelectItem(TreeListData *pData, 
unsigned uItem, unsigned uSubItem, int iMode);
+static int                             TreeListGetItemRect(TreeListData 
*pData, unsigned uItem, unsigned uFlags, RECT *pRect);
+static int                             TreeListStartNotifyEdit(TreeListData 
*pData, unsigned uItem, unsigned uSub, WPARAM wParam, LPARAM lParam);
+static int                             TreeListStartAutoEdit(TreeListData 
*pData, unsigned uColumn, WPARAM wParam, LPARAM lParam);
+static int                             TreeListEndLabelEdit(TreeListData 
*pData, int iMode);
+static BOOL                            bDrawWithTheme = FALSE;
+
+//*****************************************************************************
+//*
+//*            TreeListRegister
+//*
+//*****************************************************************************
+//     Registiert das TreeList Fenster.
+//     Ergibt 1 wenn das Fenster erfolgreich registiert wurde.
+int TreeListRegister(HINSTANCE hInstance) {
+
+       static int              iIsRegistered = FALSE;
+       WNDCLASSEX              sClass;
+
+       OutputDebugString(TEXT("TreeListRegister() - before checking\n"));
+
+       if(iIsRegistered)
+               return TRUE;
+
+       OutputDebugString(TEXT("TreeListRegister() - before registration\n"));
+
+       memset(&sClass, 0, sizeof(sClass));
+       sClass.cbSize           = sizeof(sClass);
+       sClass.style            = CS_DBLCLKS | CS_GLOBALCLASS;
+       sClass.lpfnWndProc      = TreeListProc;
+       sClass.cbClsExtra       = 0;
+       sClass.cbWndExtra       = sizeof(TreeListData *);
+       sClass.hInstance        = hInstance;
+       sClass.hIcon            = NULL;
+       sClass.hCursor          = LoadCursor(NULL, IDC_ARROW);
+       sClass.hbrBackground    = NULL;
+       sClass.lpszMenuName     = NULL;
+       sClass.hIconSm          = NULL;
+       sClass.lpszClassName    = _T(TVC_CLASSNAME);
+
+       if(!RegisterClassEx(&sClass))
+               return 0;
+
+       OutputDebugString(TEXT("TreeListRegister() - registration done\n"));
+       iIsRegistered = TRUE;
+
+       return TRUE;
+}
+
+BOOL TreeListUnregister(HINSTANCE hInstance){
+       return UnregisterClass(_T(TVC_CLASSNAME),hInstance);
+}
+
+//*****************************************************************************
+//*
+//*            GlobalInit
+//*
+//*****************************************************************************
+static void GlobalInit() {
+
+       LOGBRUSH        sLog;
+       long            lCount;
+
+
+
+       lCount = InterlockedIncrement(&lWindowCount);
+       if(lCount > 0)
+               return;
+
+       sLog.lbColor = GetSysColor(COLOR_BTNSHADOW);
+       sLog.lbStyle = PS_SOLID;
+       sLog.lbHatch = 0;
+       hPatternPen  = ExtCreatePen(PS_COSMETIC | PS_ALTERNATE, 1, &sLog, 0, 
NULL);
+
+       if(!hPatternPen) {
+               hPatternPen = CreatePen(PS_DOT, 1, RGB(0, 0, 0));
+       }
+
+
+       if(!hUxThemeDll) {
+               hUxThemeDll = LoadLibrary(_T("UxTheme.dll"));
+               if(hUxThemeDll) {
+                       pSetWindowTheme  = 
(SetWindowThemeT)GetProcAddress(hUxThemeDll, "SetWindowTheme");
+                       pEndBufferedPt   = 
(EndBufferedPtT)GetProcAddress(hUxThemeDll, "EndBufferedPaint");
+                       pBeginBufferedPt = 
(BeginBufferedPnT)GetProcAddress(hUxThemeDll, "BeginBufferedPaint");
+                       pBufferedPtInit  = 
(BufferedPtInitT)GetProcAddress(hUxThemeDll, "BufferedPaintInit");
+                       pBufferedPtExit  = 
(BufferedPtInitT)GetProcAddress(hUxThemeDll, "BufferedPaintUnInit");
+                       pOpenThemeData   = 
(OpenThemeDataT)GetProcAddress(hUxThemeDll, "OpenThemeData");
+                       pCloseThemeData  = 
(CloseThemeDataT)GetProcAddress(hUxThemeDll, "CloseThemeData");
+                       pDrawThemeBackg  = 
(DrawThemeBackgT)GetProcAddress(hUxThemeDll, "DrawThemeBackground");
+                       pGetThemeBackgRc = 
(GetThemeBackgRcT)GetProcAddress(hUxThemeDll, "GetThemeBackgroundContentRect");
+                       pIsAppThemed     = 
(IsAppThemedT)GetProcAddress(hUxThemeDll, "IsAppThemed");
+                       pIsThemeActive   = 
(IsThemeActiveT)GetProcAddress(hUxThemeDll, "IsThemeActive");
+
+                       if(pIsAppThemed && pIsThemeActive)
+                               bDrawWithTheme = pIsAppThemed() && 
pIsThemeActive();
+               }
+       }
+
+       if(pBufferedPtInit) {
+               pBufferedPtInit();
+       }
+
+}
+
+
+//*****************************************************************************
+//*
+//*            GlobalDeinit
+//*
+//*****************************************************************************
+static void GlobalDeinit() {
+
+       int     lCount;
+
+       lCount = InterlockedDecrement(&lWindowCount);
+       if(lCount >= 0)
+               return;
+
+       if(hDefaultFontN) {
+               DeleteObject(hDefaultFontN);
+               hDefaultFontN = NULL;
+       }
+
+       if(hDefaultFontB) {
+               DeleteObject(hDefaultFontB);
+               hDefaultFontB = NULL;
+       }
+
+       if(hPatternPen) {
+               DeleteObject(hPatternPen);
+               hPatternPen = NULL;
+       }
+
+       if(pBufferedPtExit) {
+               pBufferedPtExit();
+       }
+
+}
+
+
+//*****************************************************************************
+//*
+//*            SendNotify
+//*
+//*****************************************************************************
+//     Sendet eine WM_NOTIFY Nachricht and das Elternfenster
+//     pData           : Zeiger auf die Fensterdaten
+//     pNotify         : Zeiger auf die Notify-Daten
+//     Ergibt den R�ckgabewert der WM_NOTIFY Nachrich
+static LRESULT SendNotify(TreeListData *pData, NMHDR   *pNotify) {
+
+       pNotify->hwndFrom       = pData->hWnd;
+       pNotify->idFrom         = GetWindowLong(pNotify->hwndFrom, GWL_ID);
+
+       return SendMessage(GetParent(pNotify->hwndFrom), WM_NOTIFY, 
pNotify->idFrom, (LPARAM)pNotify);
+}
+
+
+//*****************************************************************************
+//*
+//*            CallbackEntry
+//*
+//*****************************************************************************
+//     Sendet eine WM_NOTIFY Nachricht and das Elternfenster um Daten zuholen
+//     pData           : Zeiger auf die Fensterdaten
+//     pEntry          : Zeiger auf den Eintrag
+//     uItem           : Nummer des Eintrages
+//     uFlags          : Welche Daten sollen abgefragt werden
+//     Ergibt den R�ckgabewert der WM_NOTIFY Nachrich
+static void CallbackEntry(TreeListData *pData, BaseItem *pEntry, unsigned 
uItem, unsigned uFlags, int *iImage, unsigned *uTextSize, LPCTSTR *pText) {
+
+       NMTVDISPINFO    sInfo;
+
+       sInfo.item.mask                         = TVIF_HANDLE | TVIF_PARAM | 
TVIF_STATE | uFlags;
+       sInfo.item.lParam                       = pEntry->lParam;
+       sInfo.item.hItem                        = (HTREEITEM)uItem;
+       sInfo.item.state                        = pEntry->uState;
+       sInfo.item.stateMask            = 0xFFFFFFFF;
+       sInfo.item.iImage                       = I_IMAGECALLBACK;
+       sInfo.item.iSelectedImage       = I_IMAGECALLBACK;
+       sInfo.item.cChildren            = I_CHILDRENCALLBACK;
+
+       if(uFlags & TVIF_TEXT) {
+               if(*uTextSize) {
+                       pData->cTempText2[sizeof(pData->cTempText2) / 
sizeof(TCHAR) - 1]        = 0;
+                       pData->cTempText2[0]    = 0;
+                       sInfo.item.pszText              = pData->cTempText2;
+                       sInfo.item.cchTextMax   = sizeof(pData->cTempText2) / 
sizeof(TCHAR) - 1;
+               } else {
+                       pData->cTempText1[sizeof(pData->cTempText1) / 
sizeof(TCHAR) - 1]        = 0;
+                       pData->cTempText1[0]    = 0;
+                       sInfo.item.pszText              = pData->cTempText1;
+                       sInfo.item.cchTextMax   = sizeof(pData->cTempText1) / 
sizeof(TCHAR) - 1;
+               }
+       } else {
+               sInfo.item.pszText              = 0;
+               sInfo.item.cchTextMax   = 0;
+       }
+
+       sInfo.hdr.hwndFrom      = pData->hWnd;
+       sInfo.hdr.idFrom        = GetWindowLong(pData->hWnd, GWL_ID);
+       sInfo.hdr.code          = TVN_GETDISPINFO;
+
+       UNLOCK(pData);
+       SendMessage(GetParent(sInfo.hdr.hwndFrom), WM_NOTIFY, sInfo.hdr.idFrom, 
(LPARAM)&sInfo);
+       LOCK(pData);
+
+       if(uFlags & TVIF_IMAGE) {
+               if(!(pEntry->uState & TVIS_SELECTED))
+                       *iImage = sInfo.item.iImage;
+       } else
+               if(uFlags & TVIF_SELECTEDIMAGE) {
+                       if(pEntry->uState & TVIS_SELECTED)
+                               *iImage = sInfo.item.iSelectedImage;
+               }
+
+       if(uFlags & TVIF_CHILDREN) {
+               switch(sInfo.item.cChildren) {
+                       case  0:
+                               pEntry->bFlags    &= ~TVIX_HASBUTTON;
+                               pEntry->bFlags    |=  TVIX_VARBUTTON;
+                               break;
+
+                       case  1:
+                               pEntry->bFlags    &= ~TVIX_VARBUTTON;
+                               pEntry->bFlags    |=  TVIX_HASBUTTON;
+                               break;
+
+                       default
+                                       :
+                               pEntry->bFlags    |=  TVIX_VARBUTTON;
+
+                               if(pEntry->uFirstChild)
+                                       pEntry->bFlags |=  TVIX_HASBUTTON;
+                               else
+                                       pEntry->bFlags &= ~TVIX_HASBUTTON;
+               }
+       }
+
+       if(uFlags & TVIF_TEXT) {
+               *pText          = sInfo.item.pszText;
+               *uTextSize      = str_len(sInfo.item.pszText);
+               pEntry->iTextPixels = 0;
+       }
+
+}
+
+//*****************************************************************************
+//*
+//*            CallbackExtra
+//*
+//*****************************************************************************
+//     Sendet eine WM_NOTIFY Nachricht and das Elternfenster um Daten zuholen
+//     pData           : Zeiger auf die Fensterdaten
+//     pEntry          : Zeiger auf den Eintrag
+//     uItem           : Nummer des Eintrages
+//     uFlags          : Welche Daten sollen abgefragt werden
+//     Ergibt den R�ckgabewert der WM_NOTIFY Nachrich
+static void CallbackExtra(TreeListData *pData, BaseItem *pEntry, ExtraItem 
*pExtra, unsigned uItem, unsigned uSub, unsigned uFlags, int *iImage, unsigned 
*uTextSize, LPCTSTR *pText) {
+
+       NMTVDISPINFO    sInfo;
+
+       sInfo.item.mask                         = TVIF_HANDLE | TVIF_PARAM | 
TVIF_STATE | TVIF_SUBITEM | uFlags;
+       sInfo.item.lParam                       = pEntry->lParam;
+       sInfo.item.hItem                        = (HTREEITEM)uItem;
+       sInfo.item.state                        = pExtra->uState;
+       sInfo.item.state                   |= (pEntry->uState & TVIS_BASEFLAGS);
+       sInfo.item.stateMask            = 0xFFFFFFFF;
+       sInfo.item.iImage                       = I_IMAGECALLBACK;
+       sInfo.item.iSelectedImage       = I_IMAGECALLBACK;
+       sInfo.item.cChildren            = uSub;
+
+       if(uFlags & TVIF_TEXT) {
+               pData->cTempText1[sizeof(pData->cTempText1) / sizeof(TCHAR) - 
1]        = 0;
+               pData->cTempText1[0]    = 0;
+               sInfo.item.pszText              = pData->cTempText1;
+               sInfo.item.cchTextMax   = sizeof(pData->cTempText1) / 
sizeof(TCHAR) - 1;
+       } else {
+               sInfo.item.pszText              = 0;
+               sInfo.item.cchTextMax   = 0;
+       }
+
+       sInfo.hdr.hwndFrom      = pData->hWnd;
+       sInfo.hdr.idFrom        = GetWindowLong(pData->hWnd, GWL_ID);
+       sInfo.hdr.code          = TVN_GETDISPINFO;
+
+       UNLOCK(pData);
+       SendMessage(GetParent(sInfo.hdr.hwndFrom), WM_NOTIFY, sInfo.hdr.idFrom, 
(LPARAM)&sInfo);
+       LOCK(pData);
+
+
+       if(uFlags & TVIF_IMAGE)
+               *iImage = sInfo.item.iImage;
+       if(uFlags & TVIF_TEXT) {
+               *pText          = sInfo.item.pszText;
+               *uTextSize      = str_len(sInfo.item.pszText);
+       }
+
+}
+
+//*****************************************************************************
+//*
+//*            EditProc
+//*
+//*****************************************************************************
+//     Ist die Fensterfunktion f�r das Edit Fenster
+static LRESULT CALLBACK EditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam) {
+
+       TreeListData   *pData;
+       WNDPROC                 pProc;
+       DWORD                   dwStop;
+       DWORD                   dwStart;
+       DWORD                   dwCount;
+       LRESULT                 lResult;
+       HWND                    hParent;
+       HWND                    hCombo;
+       int                             iDelta;
+       int                             iState;
+       int                             iPos;
+       int                             iId;
+
+
+       hParent = GetParent(hWnd);
+       iId             = GetWindowLong(hWnd, GWL_ID);
+
+       if(iId == 3) {
+               hCombo  = hWnd;
+               pData   = GetHandle(hParent);
+               pProc   = pData->pProcId3;
+       } else {
+               hCombo  = hParent;
+               hParent = GetParent(hParent);
+               pData   = GetHandle(hParent);
+               pProc   = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+       }
+
+       if(uMsg == WM_KEYDOWN) {
+               if(wParam == VK_RETURN) {
+                       SendMessage(hParent, WM_COMMAND, MAKELONG(3, 
EN_RETURN), (LPARAM)hWnd);
+                       return 0;
+               }
+
+               if(wParam == VK_ESCAPE) {
+                       SendMessage(hParent, WM_COMMAND, MAKELONG(3, 
EN_ESCAPE), (LPARAM)hWnd);
+                       return 0;
+               }
+
+               if((pData->uStyleEx & TVS_EX_STEPOUT) && 
!(GetAsyncKeyState(VK_SHIFT) & 0x8000)) {
+                       switch(wParam) {                                        
                                        // Aus Fenster springen
+
+                               case VK_UP:
+                                       if(pData->uEditMode)
+                                               break;
+                                       PostMessage(hParent, WM_COMMAND, 
MAKELONG(3, EN_RETURN), (LPARAM)hWnd);
+                                       PostMessage(hParent, WM_KEYDOWN, VK_UP  
, 0x00500001);
+                                       PostMessage(hParent, WM_KEYUP  , VK_UP  
, 0x00500001);
+                                       return 0;
+
+                               case VK_DOWN:
+                                       if(pData->uEditMode)
+                                               break;
+                                       PostMessage(hParent, WM_COMMAND, 
MAKELONG(3, EN_RETURN), (LPARAM)hWnd);
+                                       PostMessage(hParent, WM_KEYDOWN, 
VK_DOWN, 0x00500001);
+                                       PostMessage(hParent, WM_KEYUP  , 
VK_DOWN, 0x00500001);
+                                       return 0;
+
+                               case VK_LEFT:
+                                       if(pData->uEditMode && iId == 3)
+                                               break;
+                                       SendMessage(hWnd, EM_GETSEL, 
(WPARAM)&dwStart, (LPARAM)&dwStop);
+                                       if(dwStart || dwStop)
+                                               break;
+                                       PostMessage(hParent, WM_COMMAND, 
MAKELONG(3, EN_RETURN), (LPARAM)hWnd);
+                                       PostMessage(hParent, WM_KEYDOWN, 
VK_LEFT, 0x00500001);
+                                       PostMessage(hParent, WM_KEYUP  , 
VK_LEFT, 0x00500001);
+                                       return 0;
+
+                               case VK_RIGHT:
+                                       if(pData->uEditMode && iId == 3)
+                                               break;
+                                       SendMessage(hWnd, EM_GETSEL, 
(WPARAM)&dwStart, (LPARAM)&dwStop);
+                                       dwCount = (DWORD)SendMessage(hWnd, 
EM_LINELENGTH, 0, 0);
+                                       if(dwCount > dwStart)
+                                               break;
+                                       if(dwCount > dwStop)
+                                               break;
+
+                                       PostMessage(hParent, WM_COMMAND, 
MAKELONG(3, EN_RETURN), (LPARAM)hWnd);
+                                       PostMessage(hParent, WM_KEYDOWN, 
VK_RIGHT, 0x00500001);
+                                       PostMessage(hParent, WM_KEYUP  , 
VK_RIGHT, 0x00500001);
+                                       return 0;
+                       }
+               }
+
+               if(wParam == VK_DOWN && pData->uEditMode) {
+                       if(!SendMessage(hCombo, CB_GETDROPPEDSTATE, 0, 0)) {
+                               SendMessage(hCombo, CB_SHOWDROPDOWN, 1, 0);
+                               return 0;
+                       }
+               }
+       } else
+               if(uMsg == WM_CHAR) {
+                       if(wParam == VK_RETURN) {
+                               return 0;
+                       }
+
+                       if(wParam == VK_ESCAPE) {
+                               return 0;
+                       }
+               } else
+                       if(uMsg == WM_COMMAND) {
+                               if(wParam == MAKELONG(3, EN_ESCAPE) || wParam 
== MAKELONG(3, EN_RETURN)) {
+                                       SendMessage(hParent, WM_COMMAND, 
wParam, (LPARAM)hWnd);
+                                       return 0;
+                               }
+                       } else
+                               if(uMsg == WM_MOUSEWHEEL) {
+                                       iState = (int)CallWindowProc(pProc, 
hWnd, CB_GETDROPPEDSTATE, 0, 0);
+                                       if(iState) {
+                                               iDelta  = (short)HIWORD(wParam);
+                                               iDelta /= WHEEL_DELTA;
+                                               iPos    = 
(int)CallWindowProc(pProc, hWnd, CB_GETTOPINDEX, 0, 0);
+                                               iPos   -= iDelta;
+                                               CallWindowProc(pProc, hWnd, 
CB_SETTOPINDEX, iPos, 0);
+                                               return 0;
+                                       }
+                               } else
+                                       if(uMsg == WM_GETDLGCODE) {             
                                                // Welche Tasten werden im 
Dialog benutzt
+                                               return DLGC_WANTALLKEYS;
+                                       } else
+                                               if(uMsg == WM_SETTEXT) {
+                                                       lResult = 
CallWindowProc(pProc, hWnd, uMsg, wParam, lParam);;
+                                                       SendMessage(hParent, 
WM_COMMAND, MAKELONG(3, EN_SETTEXT), (LPARAM)hWnd);
+                                                       return lResult;
+                                               }
+
+       return CallWindowProc(pProc, hWnd, uMsg, wParam, lParam);
+}
+
+//*****************************************************************************
+//*
+//*            ToolProc
+//*
+//*****************************************************************************
+//     Ist die Fensterfunktion f�r das ToolTip Fenster
+static LRESULT CALLBACK ToolProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam) {
+
+       TreeListData   *pData;
+       POINT                   sPoint;
+       UINT                    uPos;
+
+       if(uMsg == WM_SETFOCUS) {
+               SetFocus((HWND)lParam);
+               return 0;
+       }
+
+       pData = (TreeListData *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+       if(uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST) {                     
        // Mausklicks auf Tooltip zum Elternfenster
+               sPoint.x = LOWORD(lParam);
+               sPoint.y = HIWORD(lParam);
+
+               ClientToScreen(hWnd       , &sPoint);
+               ScreenToClient(pData->hWnd, &sPoint);
+
+               uPos = MAKELONG(sPoint.x, sPoint.y);
+
+               return TreeListProc(pData->hWnd, uMsg, wParam, uPos);
+       }
+
+       return CallWindowProc(pData->pToolProc, hWnd, uMsg, wParam, lParam);
+}
+
+//*****************************************************************************
+//*
+//*            ChangeColSize
+//*
+//*****************************************************************************
+//     �ndert die Gr��e der variablen Spalten
+//     pData           : Zeiger auf die Fensterdaten
+//     iDelta          : Ist die Gr��en�nderung in Pixel
+static void ChangeColSize(TreeListData *pData, int iDelta) {
+
+       unsigned        uPos;
+       HDITEM          sItem;
+       RECT            sRect;
+       TV_COLSIZE      sNotify;
+       int                     iWeight;
+       int                     iValue;
+       int                     iPoint;
+       int                     iStart;
+       int                     iSize;
+       int                     iRest;
+       int                     iOff;
+       int                     iNum;
+       int                     iCnt;
+       int                     iAll;
+       int                     iVar;
+       int                     iFix;
+
+       sItem.mask      = HDI_WIDTH;
+       iAll            = pData->iAllWeight;
+       iCnt            = pData->uColumnCountVar;
+
+       if(iCnt <= 1) {                                                         
                        // Nur eine variable Spalte
+               for(uPos = 0; uPos < pData->uColumnCount; uPos++) {
+                       iWeight = pData->aColumn[uPos].bWeight;
+                       if(!iWeight)
+                               continue;
+
+                       iValue    =     pData->aColumn[uPos].sSize;
+                       iValue   += iDelta;
+                       sItem.cxy = iValue;
+
+                       pData->aColumn[uPos].sSize = (short)iValue;
+                       pData->iVarSize            =        iValue;
+
+                       if(sItem.cxy < pData->aColumn[uPos].sMin) {
+                               sItem.cxy = pData->aColumn[uPos].sMin;
+                       }
+
+                       if(pData->aColumn[uPos].sReal != sItem.cxy) {   // 
�ndert sich die Breite
+                               pData->aColumn[uPos].sReal      = 
(short)sItem.cxy;
+                               Header_SetItem(pData->hHeader, uPos, &sItem);
+
+                               if(pData->uStyleEx & TVS_EX_HEADERCHGNOTIFY) {
+                                       sNotify.hdr.code                        
= TVN_COLUMNCHANGED;
+                                       sNotify.uColumn                         
= uPos;
+                                       sNotify.uIndex                          
= pData->aColumn[uPos].bIndex;
+                                       sNotify.uPosX                           
= pData->aColumnXpos[uPos];
+                                       sNotify.iSize                           
= sItem.cxy;
+
+                                       UNLOCK(pData);
+                                       SendNotify(pData, &sNotify.hdr);
+                                       LOCK(pData);
+                               }
+                       }
+
+                       break;
+               }
+
+               return;
+       }
+
+       if(iDelta > 0)
+               iStart = (pData->uSizeX) % iAll;
+       else
+               iStart = (pData->uSizeX - iDelta) % iAll;
+
+       iOff   = 0;
+
+       for(uPos = 0;; uPos++) {                                                
                        // Suchen die Anfangsspalte
+               iWeight = pData->aColumn[uPos].bWeight;
+               if(!iWeight)
+                       continue;
+
+               iOff += iWeight;
+               if(iOff > iStart)
+                       break;
+       }
+
+
+       iPoint          = 0;
+       iSize           = iDelta / iAll;
+       iRest           = iDelta % iAll;
+       iNum            = iRest;
+       iOff       -= iStart;
+
+       iWeight         = iOff;
+       iValue          = pData->aColumn[uPos].sSize;
+       iValue     += iSize * iWeight;
+       iPoint     += iRest * iWeight;
+       iValue     += iPoint / iAll;
+       iNum       -= iPoint / iAll;
+       iPoint     %= iAll;
+
+       pData->aColumn[uPos].sSize = (short)iValue;
+
+
+       if(iWeight >= pData->aColumn[uPos].bWeight) {                   // 
Wurde die ganze Spalte berechnet
+               iCnt--;
+               iOff = 0;
+       }
+
+       while(iCnt > 0) {
+               uPos++;
+
+               if(uPos >= pData->uColumnCount)
+                       uPos = 0;
+               iWeight = pData->aColumn[uPos].bWeight;
+               if(!iWeight)
+                       continue;
+
+               iValue          = pData->aColumn[uPos].sSize;
+
+               iCnt--;
+               if(iCnt) {
+                       iValue += iSize * iWeight;
+                       iPoint += iRest * iWeight;
+                       iValue += iPoint / iAll;
+                       iNum   -= iPoint / iAll;
+                       iPoint %= iAll;
+               } else {
+                       iWeight -= iOff;
+                       iValue += iSize * iWeight;
+                       iValue += iNum;
+               }
+
+               pData->aColumn[uPos].sSize = (short)iValue;
+       }
+
+       iVar   =  0;
+       iFix   =  0;
+       iCnt   =  pData->uColumnCountVar;
+
+       for(uPos = 0; iCnt > 0; uPos++) {                                       
                // Ausgeben der neuen Breiten
+               iWeight = pData->aColumn[uPos].bWeight;
+               if(!iWeight) {
+                       iFix     +=     pData->aColumn[uPos].sSize;
+                       continue;
+               }
+
+               iVar     +=     pData->aColumn[uPos].sSize;
+               sItem.cxy = pData->aColumn[uPos].sSize;
+
+               if(sItem.cxy < pData->aColumn[uPos].sMin) {
+                       sItem.cxy = pData->aColumn[uPos].sMin;
+               }
+
+               if(pData->aColumn[uPos].sReal != sItem.cxy) {           // 
�ndert sich die Breite
+                       pData->aColumn[uPos].sReal  = (short)sItem.cxy;
+                       Header_SetItem(pData->hHeader, uPos, &sItem);
+
+                       if(pData->uStyleEx & TVS_EX_HEADERCHGNOTIFY) {
+                               sNotify.hdr.code                        = 
TVN_COLUMNCHANGED;
+                               sNotify.uColumn                         = uPos;
+                               sNotify.uIndex                          = 
pData->aColumn[uPos].bIndex;
+                               sNotify.uPosX                           = 
pData->aColumnXpos[uPos];
+                               sNotify.iSize                           = 
sItem.cxy;
+
+                               UNLOCK(pData);
+                               SendNotify(pData, &sNotify.hdr);
+                               LOCK(pData);
+                       }
+               }
+
+               iCnt--;
+       }
+
+       pData->iFixSize = iFix;
+       pData->iVarSize = iVar;
+
+       if(iDelta > 0) {
+               GetClientRect(pData->hHeader, &sRect);
+               InvalidateRect(pData->hHeader, NULL, FALSE);
+       }
+
+}
+
+//*****************************************************************************
+//*
+//*            CreateToolTip
+//*
+//*****************************************************************************
+//     Erzeugt ein ToolTip Fenster
+//     pData           : Zeiger auf die Fensterdaten
+static void CreateToolTip(TreeListData *pData) {
+
+       TOOLINFO        sInfo;
+
+       if(pData->hToolTip)
+               return;
+
+       pData->hToolTip    = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP, 
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, pData->hWnd, NULL, 
NULL, NULL);
+       pData->pToolProc   = (WNDPROC)GetWindowLongPtr(pData->hToolTip, 
GWLP_WNDPROC);
+
+       sInfo.cbSize       = sizeof(TOOLINFO);
+       sInfo.uFlags       = TTF_ABSOLUTE | TTF_TRACK | TTF_IDISHWND;
+       sInfo.hwnd         = pData->hWnd;
+       sInfo.hinst                = NULL;
+       sInfo.uId          = (LPARAM)(pData->hWnd);
+       sInfo.lpszText     = LPSTR_TEXTCALLBACK;
+
+       GetClientRect(pData->hWnd, &sInfo.rect);
+       SendMessage(pData->hToolTip, TTM_ADDTOOL, 0, (LPARAM)&sInfo);
+       SendMessage(pData->hToolTip, TTM_SETMAXTIPWIDTH, 0, 10000);
+       SetWindowLong(pData->hToolTip, GWL_ID, 2);
+       SetWindowLongPtr(pData->hToolTip, GWLP_USERDATA, (LPARAM)pData);
+       SetWindowLongPtr(pData->hToolTip, GWLP_WNDPROC , (LPARAM)ToolProc);
+}
+
+//*****************************************************************************
+//*
+//*            CreateStateImageList
+//*
+//*****************************************************************************
+//     Erzeugt eine Image-Liste mit zwei Checkboxen
+//     pData           : Zeiger auf die Fensterdaten
+//     iMode           : Welche Imageliste soll erzeugt werden (0=hStates 
1=hChecks)
+static void CreateStateImageList(TreeListData *pData, int iMode) {
+
+       BITMAPINFO      sInfo;
+       BYTE            aMem[0x1000];
+       HDC                     hDcSrc;
+       HDC                     hDc;
+       HBITMAP         hBmp;
+       HBITMAP         hBmpNew;
+       RECT            sRect;
+       int                     iBits;
+
+       if(pOpenThemeData) {                                                    
                // �ber Thema zeichnen
+               if(!pData->hThemeBt) {
+                       pData->hThemeBt = pOpenThemeData(pData->hWnd, 
L"BUTTON");
+               }
+
+               if(pData->hThemeBt) {
+                       if(iMode) {
+                               if(pData->hChecks && pData->hChecks != 
THEMEIMGLIST) {
+                                       ImageList_Destroy(pData->hChecks);
+                               }
+
+                               pData->hChecks          = THEMEIMGLIST;
+                               pData->iChecksXsize     = 16;
+                               pData->iChecksYsize     = 16;
+                               pData->iChecksMode      = 1;
+                       } else {
+                               if(pData->hStates && pData->hStates != 
THEMEIMGLIST) {
+                                       ImageList_Destroy(pData->hStates);
+                               }
+
+                               pData->hStates          = THEMEIMGLIST;
+                               pData->iStatesXsize     = 16;
+                               pData->iStatesYsize     = 16;
+                               pData->iStatesMode      = 1;
+                       }
+
+                       return;
+               }
+       }
+
+       if(iMode) {
+               if(pData->hChecks && pData->hChecks != THEMEIMGLIST)
+                       return;
+       } else {
+               if(pData->hStates && pData->hStates != THEMEIMGLIST)
+                       return;
+       }
+
+       hDcSrc  = GetDC(NULL);
+       hDc             = CreateCompatibleDC(NULL);
+       hBmp    = CreateCompatibleBitmap(hDcSrc, 16 * 3, 16);
+
+       SelectObject(hDc, hBmp);
+       SelectObject(hDc, GetStockObject(NULL_PEN));
+       SetBkMode(hDc, OPAQUE);
+       SetBkColor(hDc, GetSysColor(COLOR_WINDOW));
+       SelectObject(hDc, GetSysColorBrush(COLOR_HIGHLIGHT));
+       Rectangle(hDc, -1, -1, 16 * 3 + 2, 16 + 2);
+
+       sRect.top         = 8 - 6;
+       sRect.bottom  = 8 + 7;
+       sRect.left    = 16 * 1 + 8 - 7;
+       sRect.right   = 16 * 1 + 8 + 6;
+
+       DrawFrameControl(hDc, &sRect, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_FLAT);
+
+       sRect.left    = 16 * 2 + 8 - 7;
+       sRect.right   = 16 * 2 + 8 + 6;
+
+       DrawFrameControl(hDc, &sRect, DFC_BUTTON, DFCS_BUTTONCHECK | 
DFCS_CHECKED | DFCS_FLAT);
+
+       iBits = GetDeviceCaps(hDc, BITSPIXEL);
+
+       sInfo.bmiHeader.biSize                  = sizeof(BITMAPINFOHEADER);
+       sInfo.bmiHeader.biWidth                 = 16 * 3;
+       sInfo.bmiHeader.biHeight                = 16;
+       sInfo.bmiHeader.biPlanes                = 1;
+       sInfo.bmiHeader.biBitCount              = (WORD)iBits;
+       sInfo.bmiHeader.biCompression   = BI_RGB;
+       sInfo.bmiHeader.biSizeImage             = 0;
+       sInfo.bmiHeader.biXPelsPerMeter = 0;
+       sInfo.bmiHeader.biYPelsPerMeter = 0;
+       sInfo.bmiHeader.biClrUsed               = (iBits > 8) ? 0 : 1 << iBits;;
+       sInfo.bmiHeader.biClrImportant  = (iBits > 8) ? 0 : 1 << iBits;;
+
+       GetDIBits(hDc, hBmp, 0, 0 , NULL, &sInfo, (iBits > 8) ? DIB_RGB_COLORS 
: DIB_PAL_COLORS);
+       GetDIBits(hDc, hBmp, 0, 16, aMem, &sInfo, (iBits > 8) ? DIB_RGB_COLORS 
: DIB_PAL_COLORS);
+
+       hBmpNew = CreateCompatibleBitmap(hDc, 16 * 3, 16);
+
+       SetDIBits(hDc, hBmpNew, 0, 16, aMem, &sInfo, (iBits > 8) ? 
DIB_RGB_COLORS : DIB_PAL_COLORS);
+
+       if(iMode == 0) {
+               pData->hStates          = ImageList_Create(16, 16, ILC_COLORDDB 
| ILC_MASK, 3, 14);
+               pData->iStatesXsize     = 16;
+               pData->iStatesYsize     = 16;
+               pData->iStatesMode      = 1;
+
+               ImageList_AddMasked(pData->hStates, hBmpNew, 
GetSysColor(COLOR_HIGHLIGHT));
+       } else {
+               pData->hChecks          = ImageList_Create(16, 16, ILC_COLORDDB 
| ILC_MASK, 3, 14);
+               pData->iChecksXsize     = 16;
+               pData->iChecksYsize     = 16;
+               pData->iChecksMode      = 1;
+
+               ImageList_AddMasked(pData->hChecks, hBmpNew, 
GetSysColor(COLOR_HIGHLIGHT));
+       }
+
+       DeleteObject(hBmpNew);
+       DeleteObject(hBmp);
+       DeleteDC(hDc);
+       ReleaseDC(NULL, hDcSrc);
+}
+
+//*****************************************************************************
+//*
+//*            CreateDragImage
+//*
+//*****************************************************************************
+//     Erzeugt eine Image-Liste mit zwei Checkboxen
+//     pData           : Zeiger auf die Fensterdaten
+//     uSub            : Ist die Spalte f�r die das Drag-Image erzeugt werden 
soll
+//     Ergibt ein Handle mit der Imageliste oder NULL bei einem Fehler
+static HIMAGELIST CreateDragImage(TreeListData *pData, unsigned uItem, 
unsigned uSub) {
+
+       ExtraItem  *pExtra;
+       BaseItem   *pEntry;
+       HIMAGELIST      hList;
+       BITMAPINFO      sInfo;
+       BYTE       *pMem;
+       HDC                     hDcSrc;
+       HDC                     hDc;
+       HBITMAP         hBmp;
+       HBITMAP         hBmpNew;
+       RECT            sRect;
+       unsigned        uTSize;
+       int                     iAdd;
+       int                     iBits;
+       int                     iWidth;
+       int                     iHeigh;
+       int                     iImage;
+       int                     iYpos;
+       LPCTSTR         pText;
+
+       if(uItem > pData->uTreeItemsMax)
+               return NULL;
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry)
+               return 0;
+
+       iHeigh = pData->iFontHeight;
+
+       if(uSub) {                                                              
                                // Image f�r Extraeintrag erzeugen
+               if(uSub >= pData->uColumnCount)
+                       return 0;
+
+               pExtra = pData->pExtraItems[uSub - 1][uItem];
+               if(!pExtra) {
+                       pText  = _T("????");
+                       uTSize = 4;
+                       iImage = -1;
+                       iWidth = pData->iFontHeight * 4;
+               } else {
+                       pText  = pExtra->pText;
+                       uTSize = pExtra->uTextSize;
+                       iImage = pExtra->iImage;
+                       iWidth = pExtra->iTextPixels;
+
+                       if(pExtra->bCallback & (TVIF_IMAGE | TVIF_TEXT)) {
+                               CallbackExtra(pData, pEntry, pExtra, uItem, 
uSub, pExtra->bCallback, &iImage, &uTSize, &pText);
+                       }
+               }
+       } else {                                                                
                                        // Image f�r Haupteintrag erzeugen
+               pText  = pEntry->pText;
+               uTSize = pEntry->uTextSize;
+               iImage = pEntry->iImage;
+               iWidth = pEntry->iTextPixels;
+
+               if(pEntry->bCallback & (TVIF_IMAGE | TVIF_TEXT)) {
+                       CallbackEntry(pData, pEntry, uItem, pEntry->bCallback, 
&iImage, &uTSize, &pText);
+               }
+       }
+
+       if(pData->hImages && iImage >= 0) {                                     
                // Gr��en f�r Images anpassen
+               if(iHeigh < pData->iImagesYsize)
+                       iHeigh = pData->iImagesYsize;
+               iAdd    = pData->iImagesXsize + 2;
+               iWidth += iAdd;
+       } else {
+               iAdd   = 0;
+               iImage = 1;
+       }
+
+       if(iWidth > 240)
+               iWidth = 240;
+       if(iHeigh > 32)
+               iHeigh = 32;
+
+       pMem = new(BYTE, iHeigh * (iWidth + 4) * 4 + 1024);
+       if(!pMem)
+               return NULL;
+
+       hDcSrc  = GetDC(NULL);
+       hDc             = CreateCompatibleDC(NULL);
+       hBmp    = CreateCompatibleBitmap(hDcSrc, iWidth, iHeigh);
+
+       SelectObject(hDc, hBmp);
+       SelectObject(hDc, GetStockObject(NULL_PEN));
+       SelectObject(hDc, (pEntry->uState & TVIS_BOLD) ? pData->hFontB : 
pData->hFontN);
+       SetTextColor(hDc, pData->uColors[TVC_TEXT]);
+       SetBkColor(hDc, RGB(123, 77, 91));
+
+       sRect.top         = 0;
+       sRect.bottom  = iHeigh;
+       sRect.left    = 0;
+       sRect.right   = iWidth;
+       iYpos             = (iHeigh - pData->iFontHeight) / 2;
+
+       ExtTextOut(hDc, iAdd, iYpos, ETO_OPAQUE | ETO_CLIPPED, &sRect, pText, 
uTSize, NULL);
+
+       if(iImage >= 0) {
+               SetBkColor(hDc, GetSysColor(COLOR_WINDOW));
+               ImageList_Draw(pData->hImages, iImage, hDc, 0, 0, 
ILD_TRANSPARENT);
+       }
+
+       iBits = GetDeviceCaps(hDc, BITSPIXEL);
+
+       sInfo.bmiHeader.biSize                  = sizeof(BITMAPINFOHEADER);
+       sInfo.bmiHeader.biWidth                 = iWidth;
+       sInfo.bmiHeader.biHeight                = iHeigh;
+       sInfo.bmiHeader.biPlanes                = 1;
+       sInfo.bmiHeader.biBitCount              = (WORD)iBits;
+       sInfo.bmiHeader.biCompression   = BI_RGB;
+       sInfo.bmiHeader.biSizeImage             = 0;
+       sInfo.bmiHeader.biXPelsPerMeter = 0;
+       sInfo.bmiHeader.biYPelsPerMeter = 0;
+       sInfo.bmiHeader.biClrUsed               = (iBits > 8) ? 0 : 1 << iBits;;
+       sInfo.bmiHeader.biClrImportant  = (iBits > 8) ? 0 : 1 << iBits;;
+
+       GetDIBits(hDc, hBmp, 0, 0     , NULL, &sInfo, (iBits > 8) ? 
DIB_RGB_COLORS : DIB_PAL_COLORS);
+       GetDIBits(hDc, hBmp, 0, iHeigh, pMem, &sInfo, (iBits > 8) ? 
DIB_RGB_COLORS : DIB_PAL_COLORS);
+
+       hBmpNew = CreateCompatibleBitmap(hDc, iWidth, iHeigh);
+
+       SetDIBits(hDc, hBmpNew, 0, iHeigh, pMem, &sInfo, (iBits > 8) ? 
DIB_RGB_COLORS : DIB_PAL_COLORS);
+
+       hList = ImageList_Create(iWidth, iHeigh, ILC_COLORDDB | ILC_MASK, 1, 0);
+
+       ImageList_AddMasked(hList, hBmpNew, RGB(123, 77, 91));
+
+       DeleteObject(hBmpNew);
+       DeleteObject(hBmp);
+       DeleteDC(hDc);
+       ReleaseDC(NULL, hDcSrc);
+
+       delete(pMem);
+
+       return hList;
+}
+
+
+//*****************************************************************************
+//*
+//*            UpdateColorsList
+//*
+//*****************************************************************************
+//     Aktualisiert alle Farben
+//     pData           : Zeiger auf die Fensterdaten
+static void UpdateColorsList(TreeListData *pData) {
+
+       unsigned        uColOdd;
+       unsigned        uColor;
+       int             iDiff;
+       int             iSum;
+
+       if(!pData->cColorChanged[TVC_BK     ])
+               pData->uColors[TVC_BK     ]  = GetSysColor(COLOR_WINDOW);
+       if(!pData->cColorChanged[TVC_BOX    ])
+               pData->uColors[TVC_BOX    ]  = GetSysColor(COLOR_BTNSHADOW);
+       if(!pData->cColorChanged[TVC_EVEN   ])
+               pData->uColors[TVC_EVEN   ]  = GetSysColor(COLOR_WINDOW);
+       if(!pData->cColorChanged[TVC_TEXT   ])
+               pData->uColors[TVC_TEXT   ]  = GetSysColor(COLOR_WINDOWTEXT);
+       if(!pData->cColorChanged[TVC_LINE   ])
+               pData->uColors[TVC_LINE   ]  = GetSysColor(COLOR_WINDOWTEXT);
+       if(!pData->cColorChanged[TVC_FRAME  ])
+               pData->uColors[TVC_FRAME  ]  = GetSysColor(COLOR_3DFACE);
+       if(!pData->cColorChanged[TVC_TRACK  ])
+               pData->uColors[TVC_TRACK  ]  = GetSysColor(COLOR_WINDOWTEXT) ^ 
RGB(0, 0, 255);
+       if(!pData->cColorChanged[TVC_INSERT ])
+               pData->uColors[TVC_INSERT ]  = GetSysColor(COLOR_INFOBK);
+       if(!pData->cColorChanged[TVC_ODD    ])
+               pData->uColors[TVC_ODD    ]  = GetSysColor(COLOR_INFOBK);
+       if(!pData->cColorChanged[TVC_BOXBG  ])
+               pData->uColors[TVC_BOXBG  ]  = GetSysColor(COLOR_WINDOW);
+       if(!pData->cColorChanged[TVC_COLBK  ])
+               pData->uColors[TVC_COLBK  ]  = GetSysColor(COLOR_WINDOW);
+       if(!pData->cColorChanged[TVC_COLODD ])
+               pData->uColors[TVC_COLODD ]  = GetSysColor(COLOR_BTNSHADOW);
+       if(!pData->cColorChanged[TVC_COLEVEN])
+               pData->uColors[TVC_COLEVEN]  = GetSysColor(COLOR_WINDOW);
+       if(!pData->cColorChanged[TVC_GRAYED ])
+               pData->uColors[TVC_GRAYED ]  = GetSysColor(COLOR_SCROLLBAR);
+
+
+       if(pData->hTheme && !pData->cColorChanged[TVC_BOXBG] && 
!pData->cColorChanged[TVC_BOX] && !pData->cColorChanged[TVC_LINE]) {
+               pData->cGlyphOk = 1;
+       } else {
+               pData->cGlyphOk = 0;
+       }
+
+
+       if(!pData->cColorChanged[TVC_GRAYED]) {
+               pData->uColors[TVC_GRAYED]  = (GetSysColor(COLOR_SCROLLBAR) & 
0x00FEFEFE) >> 1;
+               pData->uColors[TVC_GRAYED] += (GetSysColor(COLOR_WINDOW) & 
0x00FEFEFE) >> 1;
+       }
+
+       if(!pData->cColorChanged[TVC_ODD]) {
+               uColOdd = pData->uColors[TVC_ODD];
+               iDiff   = ((uColOdd) & 0xFF) - ((pData->uColors[TVC_EVEN]) & 
0xFF);
+               iSum  = iDiff * iDiff;
+               iDiff   = ((uColOdd >> 8) & 0xFF) - ((pData->uColors[TVC_EVEN] 
>> 8) & 0xFF);
+               iSum += iDiff * iDiff;
+               iDiff   = ((uColOdd >> 16) & 0xFF) - ((pData->uColors[TVC_EVEN] 
>> 16) & 0xFF);
+               iSum += iDiff * iDiff;
+
+               if(iSum < 64) {                                                 
                                        // Ist die alternierente Farbe fast 
gleich ?
+                       uColOdd  =   pData->uColors[TVC_EVEN] & 0x0000FFFF;
+                       uColOdd |= ((pData->uColors[TVC_EVEN] & 0x00FF0000) - 
0x00080000) & 0x00FF0000;
+               }
+
+               pData->uColors[TVC_ODD] = uColOdd;
+       }
+
+       if(!pData->cColorChanged[TVC_COLBK]) {
+               uColor = GetSysColor(COLOR_WINDOW);
+               if(uColor & 0x00F00000)
+                       uColor -= 0x00100000;
+               if(uColor & 0x0000F000)
+                       uColor -= 0x00001000;
+               if(uColor & 0x000000F0)
+                       uColor -= 0x00000010;
+
+               pData->uColors[TVC_COLBK] = uColor;
+       }
+
+       if(!pData->cColorChanged[TVC_COLODD]) {
+               uColor = pData->uColors[TVC_ODD];
+               if(uColor & 0x00F00000)
+                       uColor -= 0x00100000;
+               if(uColor & 0x0000F000)
+                       uColor -= 0x00001000;
+               if(uColor & 0x000000F0)
+                       uColor -= 0x00000010;
+
+               pData->uColors[TVC_COLODD] = uColor;
+       }
+
+       if(!pData->cColorChanged[TVC_COLEVEN]) {
+               uColor = GetSysColor(COLOR_WINDOW);
+               if(uColor & 0x00F00000)
+                       uColor -= 0x00100000;
+               if(uColor & 0x0000F000)
+                       uColor -= 0x00001000;
+               if(uColor & 0x000000F0)
+                       uColor -= 0x00000010;
+
+               pData->uColors[TVC_COLEVEN] = uColor;
+       }
+
+       if(!pData->cColorChanged[TVC_MARKODD ])
+               pData->uColors[TVC_MARKODD ]  = ((pData->uColors[TVC_ODD     ] 
>> 3) & 0x1F1F1F) * 7;
+       if(!pData->cColorChanged[TVC_MARKODD ])
+               pData->uColors[TVC_MARKODD ] += ((GetSysColor(COLOR_HIGHLIGHT) 
>> 3) & 0x1F1F1F) * 1;
+       if(!pData->cColorChanged[TVC_MARKEVEN])
+               pData->uColors[TVC_MARKEVEN]  = ((pData->uColors[TVC_EVEN    ] 
>> 3) & 0x1F1F1F) * 7;
+       if(!pData->cColorChanged[TVC_MARKEVEN])
+               pData->uColors[TVC_MARKEVEN] += ((GetSysColor(COLOR_HIGHLIGHT) 
>> 3) & 0x1F1F1F) * 1;
+}
+
+//*****************************************************************************
+//*
+//*            UpdateHeight
+//*
+//*****************************************************************************
+//     Checks if the row height has changed
+//     pData           : pointer to the window data
+//     Returns 1 if changed or 0 else.
+static int UpdateHeight(TreeListData *pData) {
+
+       int             iHeight;
+       RECT    sRect;
+
+       if(pData->cFixedHeight)
+               return 0;
+
+       iHeight = 10;
+
+       if(pData->hChecks)
+               if(iHeight < pData->iChecksYsize + 2)
+                       iHeight = pData->iChecksYsize + 2;
+       if(pData->hStates)
+               if(iHeight < pData->iStatesYsize + 2)
+                       iHeight = pData->iStatesYsize + 2;
+       if(iHeight < pData->iSubImgYsize + 2)
+               iHeight = pData->iSubImgYsize + 2;
+       if(iHeight < pData->iImagesYsize + 2)
+               iHeight = pData->iImagesYsize + 2;
+       if(iHeight < pData->iFontHeight + 2)
+               iHeight = pData->iFontHeight + 2;
+       if(pData->uStyleEx & TVS_EX_ITEMLINES)
+               iHeight++;
+       if(pData->uStyle  & TVS_NONEVENHEIGHT && (iHeight & 1))
+               iHeight++;
+       if(pData->iRowHeight == iHeight)
+               return 0;
+
+       pData->iRowHeight        = iHeight;
+
+       if(pData->uSizeY > pData->uStartPixel) {
+               pData->uMaxEnties  = pData->uSizeY;
+               pData->uMaxEnties -= pData->uStartPixel;
+       } else {
+               pData->uMaxEnties  = 0;
+       }
+
+       pData->uPageEnties       = pData->uMaxEnties;
+       pData->uMaxEnties       += pData->iRowHeight - 1;
+       pData->uMaxEnties   /= pData->iRowHeight;
+       pData->uPageEnties  /= pData->iRowHeight;
+
+       GetClientRect(pData->hWnd, &sRect);
+       InvalidateRect(pData->hWnd, &sRect, FALSE);
+
+       return 1;
+}
+
+//*****************************************************************************
+//*
+//*            UpdateRect
+//*
+//*****************************************************************************
+//     Zeichnet einen Eintrag neu
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist die Nummer des Eintrages
+//     uSub            : Ist die Spaltennummer
+//     Ergibt 1 wenn der Eintrag sichtbar war
+static int UpdateRect(TreeListData *pData, unsigned uItem, unsigned uSub) {
+
+       BaseItem   *pEntry;
+       RECT            sRect;
+       UINT            uNext;
+       UINT            uPos;
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry || !pEntry->uShowPos)
+               return 0;                               // Ist der Eintrag 
aufgeklappt
+
+       uPos = pEntry->uShowPos - pData->uScrollY - 1;
+       if(uPos >= pData->uMaxEnties)
+               return 0;                                       // Eintrag im 
Fenster sichtbar
+
+       uNext             = pData->aColumn[uSub].bNext;
+       sRect.left    = pData->aColumnXpos[uSub ];
+       sRect.left   -= pData->uScrollX;
+       sRect.right       = pData->aColumnXpos[uNext];
+       sRect.right  -= pData->uScrollX;
+       sRect.top     = pData->uStartPixel;
+       sRect.top    += pData->iRowHeight * uPos;
+       sRect.bottom  = pData->iRowHeight + sRect.top;
+
+       InvalidateRect(pData->hWnd, &sRect, FALSE);
+
+       return 1;
+}
+
+//*****************************************************************************
+//*
+//*            UpdateColRect
+//*
+//*****************************************************************************
+//     Zeichnet einen ganze Spalte neu
+//     pData           : Zeiger auf die Fensterdaten
+//     uColumn         : Die nummer der Spalte
+//     Ergibt 1 wenn der Eintrag sichtbar war
+static int UpdateColRect(TreeListData *pData, unsigned uColumn) {
+
+       RECT    sRect;
+       UINT    uNext;
+
+       if(uColumn >= pData->uColumnCount)
+               return 0;
+
+       sRect.left  = pData->aColumnXpos[uColumn];
+       sRect.left -= pData->uScrollX;
+       if(sRect.left > (int)pData->uSizeX)
+               return 0;
+
+       uNext = pData->aColumn[uColumn].bNext;
+
+       sRect.right = pData->aColumnXpos[uNext];
+       sRect.right -= pData->uScrollX;
+       if(sRect.right < 0)
+               return 0;
+
+       sRect.top      = 0;
+       sRect.bottom   = pData->uSizeY;
+
+       InvalidateRect(pData->hWnd, &sRect, FALSE);
+
+       return 1;
+}
+
+//*****************************************************************************
+//*
+//*            UpdateRow
+//*
+//*****************************************************************************
+//     Zeichnet einen Eintrag �ber die ganze Zeile neu
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist die Nummer des Eintrages
+//     Ergibt 1 wenn der Eintrag sichtbar war
+static int UpdateRow(TreeListData *pData, unsigned uItem) {
+
+       BaseItem   *pEntry;
+       RECT            sRect;
+       unsigned        uPos;
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry || !pEntry->uShowPos)
+               return 0;                               // Ist der Eintrag 
aufgeklappt
+
+       uPos = pEntry->uShowPos - pData->uScrollY - 1;
+       if(uPos >= pData->uMaxEnties)
+               return 0;                                       // Eintrag im 
Fenster sichtbar
+
+       sRect.left    = 0;
+       sRect.right   = pData->uSizeX;
+       sRect.top     = pData->uStartPixel;
+       sRect.top    += pData->iRowHeight * uPos;
+       sRect.bottom  = pData->iRowHeight + sRect.top;
+       InvalidateRect(pData->hWnd, &sRect, FALSE);
+
+       return 1;
+}
+
+//*****************************************************************************
+//*
+//*            UpdateView
+//*
+//*****************************************************************************
+//     Redraw the whole window
+//     pData           : Zeiger auf die Fensterdaten
+//     Ergibt 1 wenn der Eintrag sichtbar war
+static void UpdateView(TreeListData *pData) {
+
+       RECT    sRect;
+
+       GetClientRect(pData->hWnd, &sRect);
+       sRect.top =    pData->uStartPixel;
+       InvalidateRect(pData->hWnd, &sRect, FALSE);
+
+       if(pData->hHeader && ((pData->uStyleEx & TVS_EX_HIDEHEADERS) == 0)){
+               GetClientRect(pData->hHeader, &sRect);
+               InvalidateRect(pData->hHeader, &sRect, FALSE);
+       }
+}
+
+//*****************************************************************************
+//*
+//*            UpdateScrollX
+//*
+//*****************************************************************************
+//     Aktualisiert die X-Scroolbar
+//     pData           : Zeiger auf die Fensterdaten
+//     Ergibt 1 wenn der sich Einstellungen ver�ndert haben
+static void UpdateScrollX(TreeListData *pData) {
+
+       SCROLLINFO  sInfo;
+       unsigned        uSize;
+       unsigned        uCols;
+
+       uCols = pData->uColumnCount;
+       if(uCols)
+               uSize = pData->aColumnXpos[uCols] - 1;
+       else
+               uSize = pData->iMaxSizeX - 1;
+
+
+       if(pData->uOldXCount == uSize)
+               if(pData->uOldXPage == pData->uSizeX) {
+                       return;
+               }
+
+       pData->uOldXPage        = pData->uSizeX;
+       pData->uOldXCount       = uSize;
+
+       UNLOCK(pData);
+
+       sInfo.cbSize    = sizeof(SCROLLINFO);
+       sInfo.fMask             = SIF_ALL;
+       sInfo.nMin              = 0;
+       sInfo.nMax      = uSize;
+       sInfo.nPage     = pData->uSizeX;
+       sInfo.nPos      = pData->uScrollX;
+       sInfo.nTrackPos = 0;
+
+       if(pData->uStyle & TVS_NOSCROLL) {
+               sInfo.nMax = 0;
+       } else
+               if(pData->uStyleEx & TVS_EX_AUTOHSCROLL) {
+                       sInfo.nMax = 0;
+               } else
+                       if(sInfo.nMax > 0) {
+                               sInfo.nMax--;
+                       }
+
+
+       if((int)sInfo.nPage >= sInfo.nMax && pData->uScrollX > 0) {
+               sInfo.nPos      = 0;
+               pData->uScrollX = 0;
+
+               UpdateView(pData);
+
+               if(pData->hHeader) {
+                       MoveWindow(pData->hHeader, 0, 0, pData->uSizeX, 
pData->uStartPixel, TRUE);
+               }
+       }
+
+       SetScrollInfo(pData->hWnd, SB_HORZ, &sInfo, TRUE);
+
+       LOCK(pData);
+}
+
+//*****************************************************************************
+//*
+//*            UpdateScrollY
+//*
+//*****************************************************************************
+//     Aktualisiert die Y-Scroolbar
+//     pData           : Zeiger auf die Fensterdaten
+//     Ergibt 1 wenn der sich Einstellungen ver�ndert haben
+static void UpdateScrollY(TreeListData *pData) {
+
+       SCROLLINFO  sInfo;
+
+       if(pData->uOldYCount == pData->uItemPosCount)
+               if(pData->uOldYPage == pData->uPageEnties) {
+                       return;
+               }
+
+       pData->uOldYPage        = pData->uPageEnties;
+       pData->uOldYCount       = pData->uItemPosCount;
+
+       UNLOCK(pData);
+
+       sInfo.cbSize    = sizeof(SCROLLINFO);
+       sInfo.fMask             = SIF_ALL;
+       sInfo.nMin              = 0;
+       sInfo.nMax      = pData->uItemPosCount;
+       sInfo.nPage     = pData->uPageEnties;
+       sInfo.nPos      = pData->uScrollY;
+       sInfo.nTrackPos = 0;
+
+       if(pData->uStyle & TVS_NOSCROLL) {
+               sInfo.nMax = 0;
+       }
+
+       if((int)sInfo.nPage >= sInfo.nMax && pData->uScrollY > 0) {
+               sInfo.nPos      = 0;
+               pData->uScrollY = 0;
+
+               UpdateView(pData);
+       }
+
+       SetScrollInfo(pData->hWnd, SB_VERT, &sInfo, TRUE);
+
+       LOCK(pData);
+}
+
+//*****************************************************************************
+//*
+//*            UpdateToolTip
+//*
+//*****************************************************************************
+//     Aktualisiert den Text f�r das Tootip
+//     pData   : Zeiger auf Fensterdaten
+//     uItem   : Item auf den der Mauszeiger zeigt
+//     uFlags  : Flags vom HitTest
+static void UpdateToolTip(TreeListData *pData, unsigned uItem, unsigned 
uFlags) {
+
+       TCHAR                   cTemp[INFOTIPSIZE];
+#ifndef __REACTOS__
+       HWND                    hToolTip;
+#endif
+       NMTVGETINFOTIP  sToolNv;
+       NMTREEVIEW              sNotify;
+       TOOLINFO                sInfo;
+       ExtraItem          *pExtra;
+       BaseItem           *pEntry;
+       LPCTSTR         pText;
+       RECT                    sRect;
+       unsigned                uSize;
+       unsigned                uCol;
+       unsigned                uLen;
+       LRESULT                 lRet;
+       int                             iTemp;
+       // Tooltip ausbelnden
+       if(!uItem || (uItem == pData->uEditItem && TVHT_SUBTOCOL(uFlags) == 
pData->uEditSub)) {
+               if(pData->uToolTipItem)
+                       goto ExitTip;
+               return;
+       }
+
+       pEntry = pData->pTreeItems[uItem];
+
+       if(uFlags & TVHT_ONITEM) {
+               if(pData->uToolTipItem != uItem || pData->uToolTipSub != 0) {
+                       if(!pData->pTreeItems[uItem]) {                         
        // Existiert der Eintag noch ?
+                               goto ExitTip;
+                       }
+
+                       TreeListGetItemRect(pData, uItem, TVIR_GETCOLUMN | 
TVIR_TEXT, &sRect);
+
+                       if(sRect.right > (int)pData->uSizeX) {
+                               sRect.right = pData->uSizeX;
+                       }
+
+                       lRet = 0;
+
+                       if(pData->uStyleEx & TVS_EX_TOOLTIPNOTIFY) {            
// Tooltip-Daten via speziellem Notify holen
+                               sNotify.hdr.code                        = 
TVN_ITEMTOOLTIP;
+                               sNotify.action                          = 0;
+                               sNotify.itemNew.mask            = TVIF_HANDLE | 
TVIF_PARAM | TVIF_STATE | TVIF_SUBITEM;
+                               sNotify.itemNew.hItem           = 
(HTREEITEM)uItem;
+                               sNotify.itemNew.stateMask       = 0xFFFFFFFF;
+                               sNotify.itemNew.state           = 
pEntry->uState;
+                               sNotify.itemNew.lParam          = 
pEntry->lParam;
+                               sNotify.itemNew.pszText         = pEntry->pText;
+                               sNotify.itemNew.cchTextMax      = 
pEntry->uTextSize;
+                               sNotify.itemNew.cChildren       = 0;
+                               sNotify.itemOld.mask            = 0;
+                               sNotify.ptDrag.x                        = 
sRect.left;
+                               sNotify.ptDrag.y                        = 
sRect.top;
+
+                               UNLOCK(pData);
+                               lRet = SendNotify(pData, &sNotify.hdr);
+                               LOCK(pData);
+
+                               if(lRet)
+                                       goto UserTip;
+                       } else
+                               if(pData->uStyle & TVS_INFOTIP) {               
                // Tooltip-Daten via normalem Notify holen
+                                       sToolNv.hdr.code                        
= TVN_GETINFOTIP;
+                                       sToolNv.cchTextMax                      
= INFOTIPSIZE;
+                                       sToolNv.hItem                           
= (HTREEITEM)uItem;
+                                       sToolNv.lParam                          
= pEntry->lParam;
+                                       sToolNv.pszText                         
= cTemp;
+
+                                       str_ncpy(cTemp, pEntry->pText, 
INFOTIPSIZE);
+                                       cTemp[INFOTIPSIZE - 1] = 0;
+
+                                       UNLOCK(pData);
+                                       lRet = SendNotify(pData, &sNotify.hdr);
+                                       LOCK(pData);
+
+                                       sNotify.itemNew.mask            = 
TVIF_HANDLE | TVIF_PARAM | TVIF_STATE | TVIF_SUBITEM;
+                                       sNotify.itemNew.hItem           = 
(HTREEITEM)uItem;
+                                       sNotify.itemNew.pszText         = 
sToolNv.pszText;
+                                       sNotify.itemNew.cchTextMax      = 
str_len(sToolNv.pszText);
+                                       sNotify.itemNew.cChildren       = 0;
+                                       sNotify.itemNew.stateMask       = 
0xFFFFFFFF;
+                                       sNotify.itemNew.state           = 
pEntry->uState;
+                                       sNotify.itemNew.lParam          = 
pEntry->lParam;
+                                       sNotify.ptDrag.x                        
= sRect.left;
+                                       sNotify.ptDrag.y                        
= sRect.top;
+
+                                       goto UserTip;
+                               }
+                       // Passt der Text in die Spalte
+                       if(sRect.right - sRect.left <= pEntry->iTextPixels + 4) 
{
+                               pText   = pEntry->pText;
+                               uSize   = pEntry->uTextSize;
+
+                               if(pEntry->bCallback & TVIF_TEXT) {
+                                       CallbackEntry(pData, pEntry, uItem, 
TVIF_TEXT, &iTemp, &uSize, &pText);
+                               }
+
+                               if(!pText || *pText == 0)
+                                       goto ExitTip;
+
+                               uLen = str_len(pText) + 1;
+                               if(uLen >= pData->uToolTipSize) {               
                // Tooltipspeicher vergr��ern
+                                       delete(pData->pToolTipText);
+                                       pData->uToolTipSize = (uLen + 
255)&~0xFF;
+                                       pData->pToolTipText = new(TCHAR, 
pData->uToolTipSize + 4);
+                               }
+
+                               memcpy(pData->pToolTipText, pText, uLen * 
sizeof(TCHAR));
+                               pData->hFontT = (pEntry->uState & TVIS_BOLD) ? 
pData->hFontB : pData->hFontN;
+
+#ifndef __REACTOS__
+                               hToolTip                                = 
pData->hToolTip;
+#endif
+                               pData->sToolTipPos.x    = sRect.left;
+                               pData->sToolTipPos.y    = sRect.top;
+
+                               ClientToScreen(pData->hWnd, 
&pData->sToolTipPos);
+
+                               UNLOCK(pData);
+
+                               sInfo.cbSize                    = sizeof(sInfo);
+                               sInfo.hwnd                              = 
pData->hWnd;
+                               sInfo.uId                               = 
(UINT_PTR)pData->hWnd;
+
+                               if(pData->uToolTipItem) {
+                                       SendMessage(pData->hToolTip, 
TTM_TRACKACTIVATE, 0, (LPARAM)&sInfo);
+                                       pData->uToolTipItem = 0;
+                               }
+
+                               SendMessage(pData->hToolTip, TTM_TRACKPOSITION, 
0, MAKELONG(pData->sToolTipPos.x, pData->sToolTipPos.y));
+                               SendMessage(pData->hToolTip, TTM_TRACKACTIVATE, 
1, (LPARAM)&sInfo);
+
+                               LOCK(pData);
+
+                               pData->uToolTipItem             = uItem;
+                               pData->uToolTipShow     = 0;
+                               pData->uToolTipSub              = 0;
+
+                               SetTimer(pData->hWnd, ID_TOOLTIPCHECK, 1500, 
NULL);
+                       } else {
+                               if(pData->uToolTipItem)
+                                       goto ExitTip;
+                       }
+               }
+
+               return;
+       }
+
+       if(uFlags & (TVHT_ONSUBICON | TVHT_ONSUBLABEL)) {
+               if(pData->uToolTipItem != uItem || TVHT_SUBTOCOL(uFlags) != 
pData->uToolTipSub) {
+                       lRet   = 0;
+                       uCol   = TVHT_SUBTOCOL(uFlags);
+                       pExtra = pData->pExtraItems[uCol - 1][uItem];
+
+                       if(pData->uStyleEx & TVS_EX_TOOLTIPNOTIFY) {            
// Tooltip-Daten via Notify holen
+                               TreeListGetItemRect(pData, uItem, 
TVIR_GETCOLUMN | TVIR_TEXT | TVIR_COLTOSUB(uCol), &sRect);
+
+                               if(sRect.right > (int)pData->uSizeX) {
+                                       sRect.right = pData->uSizeX;
+                               }
+
+                               if(pExtra) {
+                                       sNotify.itemNew.state           = 
pExtra->uState;
+                                       sNotify.itemNew.pszText         = 
pExtra->pText;
+                                       sNotify.itemNew.cchTextMax      = 
pExtra->uTextSize;
+                               } else {
+                                       sNotify.itemNew.state           = 0;
+                                       sNotify.itemNew.cchTextMax      = 0;
+                                       sNotify.itemNew.pszText         = 
_T("");
+                               }
+
+                               sNotify.hdr.code                        = 
TVN_ITEMTOOLTIP;
+                               sNotify.action                          = 0;
+                               sNotify.itemNew.lParam          = 
pEntry->lParam;
+                               sNotify.itemNew.mask            = TVIF_HANDLE | 
TVIF_PARAM | TVIF_STATE | TVIF_SUBITEM;
+                               sNotify.itemNew.hItem           = 
(HTREEITEM)uItem;
+                               sNotify.itemNew.stateMask       = 0xFFFFFFFF;
+                               sNotify.itemNew.cChildren       = uCol;
+                               sNotify.itemOld.mask            = 0;
+                               sNotify.ptDrag.x                        = 
sRect.left;
+                               sNotify.ptDrag.y                        = 
sRect.top;
+
+                               UNLOCK(pData);
+                               lRet = SendNotify(pData, &sNotify.hdr);
+                               LOCK(pData);
+
+                               if(lRet)
+                                       goto UserTip;
+                       }
+
+                       if(pExtra) {                                            
                                // Tooltip auf Unterspalte ?
+                               TreeListGetItemRect(pData, uItem, 
TVIR_GETCOLUMN | TVIR_TEXT | TVIR_COLTOSUB(uCol), &sRect);
+
+                               if(sRect.right > (int)pData->uSizeX) {
+                                       sRect.right = pData->uSizeX;
+                               }
+
+                               if(sRect.right - sRect.left <= 
pExtra->iTextPixels + 4) {
+                                       pText   = pExtra->pText;
+                                       uSize   = pExtra->uTextSize;
+
+                                       if(pExtra->bCallback & TVIF_TEXT) {
+                                               CallbackExtra(pData, pEntry, 
pExtra, uItem, uCol, TVIF_TEXT, &iTemp, &uSize, &pText);
+                                       }
+
+                                       if(!pText || *pText == 0)
+                                               goto ExitTip;
+
+                                       uLen = str_len(pText) + 1;
+                                       if(uLen >= pData->uToolTipSize) {       
                // Tooltipspeicher vergr��ern
+                                               delete(pData->pToolTipText);
+                                               pData->uToolTipSize = (uLen + 
255)&~0xFF;
+                                               pData->pToolTipText = 
new(TCHAR, pData->uToolTipSize + 4);
+                                       }
+
+                                       memcpy(pData->pToolTipText, pText, uLen 
* sizeof(TCHAR));
+                                       pData->hFontT = (pExtra->uState & 
TVIS_BOLD) ? pData->hFontB : pData->hFontN;
+
+                                       pData->sToolTipPos.x    = sRect.left;
+                                       pData->sToolTipPos.y    = sRect.top;
+#ifndef __REACTOS__
+                                       hToolTip                                
= pData->hToolTip;
+#endif
+
+                                       ClientToScreen(pData->hWnd, 
&pData->sToolTipPos);
+
+                                       UNLOCK(pData);
+
+                                       sInfo.cbSize                    = 
sizeof(sInfo);
+                                       sInfo.hwnd                              
= pData->hWnd;
+                                       sInfo.uId                               
= (UINT_PTR)pData->hWnd;
+
+                                       if(pData->uToolTipItem) {
+                                               SendMessage(pData->hToolTip, 
TTM_TRACKACTIVATE, 0, (LPARAM)&sInfo);
+                                               pData->uToolTipItem = 0;
+                                       }
+
+                                       SendMessage(pData->hToolTip, 
TTM_TRACKPOSITION, 0, MAKELONG(pData->sToolTipPos.x, pData->sToolTipPos.y));
+                                       SendMessage(pData->hToolTip, 
TTM_TRACKACTIVATE, 1, (LPARAM)&sInfo);
+
+                                       LOCK(pData);
+
+                                       pData->uToolTipItem             = uItem;
+                                       pData->uToolTipSub              = uCol;
+                                       pData->uToolTipShow     = 0;
+
+                                       SetTimer(pData->hWnd, ID_TOOLTIPCHECK, 
1500, NULL);
+                               } else {
+                                       if(pData->uToolTipItem)
+                                               goto ExitTip;
+                               }
+                       } else {
+                               if(pData->uToolTipItem)
+                                       goto ExitTip;
+                       }
+               }
+
+               return;
+       }
+
+ExitTip:
+
+       if(pData->uToolTipItem) {                                               
                        // Tooltip ausblenden
+               UNLOCK(pData);
+
+               sInfo.cbSize                    = sizeof(sInfo);
+               sInfo.hwnd                              = pData->hWnd;
+               sInfo.uId                               = (UINT_PTR)pData->hWnd;
+
+               SendMessage(pData->hToolTip, TTM_TRACKACTIVATE, 0, 
(LPARAM)&sInfo);
+
+               LOCK(pData);
+
+               pData->uToolTipItem = 0;
+               pData->uToolTipSub      = 0;
+               pData->uToolTipShow = 0;
+
+               KillTimer(pData->hWnd, ID_TOOLTIPCHECK);
+       }
+
+       return;
+
+UserTip:
+
+       pText      = sNotify.itemNew.pszText;                                   
// Soll ein User-Tooltip angezeigt werden
+       uSize      = sNotify.itemNew.cchTextMax;
+       sRect.left = sNotify.ptDrag.x;
+       sRect.top  = sNotify.ptDrag.y;
+
+       if(!pText || *pText == 0)
+               goto ExitTip;
+
+       uLen = str_len(pText) + 1;
+       if(uLen >= pData->uToolTipSize) {                                       
                // Tooltipspeicher vergr��ern
+
+               delete(pData->pToolTipText);
+               pData->uToolTipSize = (uLen + 255)&~0xFF;
+               pData->pToolTipText = new(TCHAR, pData->uToolTipSize + 4);
+       }
+
+       memcpy(pData->pToolTipText, pText, uLen * sizeof(TCHAR));
+       pData->hFontT           = (pEntry->uState & TVIS_BOLD) ? pData->hFontB 
: pData->hFontN;
+
+       ClientToScreen(pData->hWnd, &sNotify.ptDrag);
+       pData->sToolTipPos      = sNotify.ptDrag;
+#ifndef __REACTOS__
+       hToolTip                        = pData->hToolTip;
+#endif
+       // Tooltip verz�gert anzeigen
+       if((sNotify.itemNew.mask & TVIF_TOOLTIPTIME) && sNotify.itemNew.lParam 
> 0) {
+               pData->uToolTipShow = (unsigned)(sNotify.itemNew.lParam + 499) 
/ 500;
+               pData->uToolTipSub      = sNotify.itemNew.cChildren;
+               pData->uToolTipItem = uItem;
+
+               SetTimer(pData->hWnd, ID_TOOLTIPCHECK, 500, NULL);
+
+               return;
+       }
+
+       UNLOCK(pData);
+
+       sInfo.cbSize            = sizeof(sInfo);
+       sInfo.hwnd                      = pData->hWnd;
+       sInfo.uId                       = (UINT_PTR)pData->hWnd;
+
+       if(pData->uToolTipItem) {                                               
                        // Tooltip Fenster aktivieren
+               SendMessage(pData->hToolTip, TTM_TRACKACTIVATE, 0, 
(LPARAM)&sInfo);
+               pData->uToolTipItem = 0;
+       }
+
+       SendMessage(pData->hToolTip, TTM_TRACKPOSITION, 0, 
MAKELONG(sNotify.ptDrag.x, sNotify.ptDrag.y));
+       SendMessage(pData->hToolTip, TTM_TRACKACTIVATE, 1, (LPARAM)&sInfo);
+
+       LOCK(pData);
+
+       pData->uToolTipShow = 0;
+       pData->uToolTipItem = uItem;
+       pData->uToolTipSub      = sNotify.itemNew.cChildren;
+
+       SetTimer(pData->hWnd, ID_TOOLTIPCHECK, 1500, NULL);
+}
+
+//*****************************************************************************
+//*
+//*            CreateFontset
+//*
+//*****************************************************************************
+//  Create the font set (normal, bold, etc...) from the given HFONT
+static int CreateFontset(TreeListData *pData, HFONT hFont){
+       LOGFONT sLog;
+       HFONT hBold;
+       int iRet = 0;
+       
+       if(GetObject(hFont, sizeof(sLog), &sLog)){
+               sLog.lfWeight = FW_BOLD;
+               if((hBold = CreateFontIndirect(&sLog))){
+                       pData->hFontN = hFont;  //store the given font
+                       if(pData->hFontB != hDefaultFontB){
+                               //if the current bold is not the default bold, 
free it
+                               DeleteObject(pData->hFontB);
+                       }
+                       pData->hFontB = hBold;  //store the created bold 
+                       iRet = 1;
+               }
+       }
+       return iRet;
+}
+
+//*****************************************************************************
+//*
+//*            UpdateFont
+//*
+//*****************************************************************************
+//     Erzeugt einen den fetten Font f�r das Fenster
+//     pData           : Zeiger auf die Fensterdaten
+//     iRedraw         : Soll das Fenster neugezeichnet werden
+//     Ergibt 1 wenn der Font ver�ndert wurde
+static int UpdateFont(TreeListData *pData) {
+
+       int                     iPos;
+       int                     iRet;
+       HDC                     hDc;
+       LOGFONT         sLog;
+       SIZE            sSize;
+       TEXTMETRIC      sMetrics;
+       BaseItem   *pEntry;
+       BaseItem  **pList;
+       ExtraItem  *pExtra;
+       ExtraItem **pItems;
+       unsigned        uSub;
+
+       if(!hDefaultFontN) {                                                    
                        // Den Standard-Font erzeugen
+               SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(sLog), 
&sLog, 0);
+               sLog.lfWeight = FW_NORMAL;
+               hDefaultFontN = CreateFontIndirect(&sLog);
+               sLog.lfWeight = FW_BOLD;
+               hDefaultFontB = CreateFontIndirect(&sLog);
+       }
+
+
+       if(!pData->hFontN)
+               pData->hFontN = hDefaultFontN;
+       if(!pData->hFontB)
+               pData->hFontB = hDefaultFontB;
+
+/*
+       if(pData->hFontN == hDefaultFontN) {                                    
        // Ist der Standard-Font eingestellt
+               pData->hFontB = hDefaultFontB;
+       } else {
+               pData->hFontB = pData->hFontN;
+       }
+*/
+
+       if(pData->hFontN != pData->hFontL) {
+               pData->hFontL = pData->hFontN;
+
+               hDc = GetDC(NULL);
+               SelectObject(hDc, pData->hFontN);
+               GetTextMetrics(hDc, &sMetrics);
+               pData->iFontHeight =  sMetrics.tmHeight;
+               pData->iFontLine   =  sMetrics.tmAscent + 1;
+               pData->iFontOff    = (sMetrics.tmPitchAndFamily & 
TMPF_FIXED_PITCH) ? 0 : -1;
+               ReleaseDC(NULL, hDc);
+
+               pList = pData->pTreeItems;
+               iPos  = pData->uTreeItemsMax;
+
+               for(; iPos >= 0; iPos--) {                                      
                        // Alle Textbreiten zur�cksetzen
+                       pEntry = pList[iPos];
+                       if(!pEntry)
+                               continue;
+
+                       pEntry->iTextPixels = 0;
+               }
+
+
+               for(uSub = 1; uSub < pData->uColumnCount; uSub++) {
+                       iPos    = pData->uTreeItemsMax;
+                       pItems  = pData->pExtraItems[uSub - 1];
+
+                       for(; iPos >= 0; iPos--) {
+                               pExtra = pItems[iPos];
+                               if(!pExtra)
+                                       continue;
+
+                               pExtra->iTextPixels = 0;
+                       }
+               }
+
+               iRet = 1;
+       } else {
+               iRet = 0;
+       }
+
+       // compute Width of "..." text
+       hDc = GetDC(NULL);
+       SelectObject(hDc, pData->hFontN);
+       GetTextExtentExPoint(hDc, _T("..."), 3, 256, NULL, NULL, &sSize);
+       pData->uTrippleN =  sSize.cx;
+       SelectObject(hDc, pData->hFontB);
+       GetTextExtentExPoint(hDc, _T("..."), 3, 256, NULL, NULL, &sSize);
+       pData->uTrippleB =  sSize.cx;
+       ReleaseDC(NULL, hDc);
+
+       return iRet;
+}
+
+
+//*****************************************************************************
+//*
+//*            UpdateItems
+//*
+//*****************************************************************************
+//     Berechnet die Positionen der Zeilen f�r die sichtbaren Eintr�ge
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist der Eintrag ab dem begonnen wird
+static void UpdateItems(TreeListData *pData, unsigned uItem) {
+
+       unsigned        uPos;
+       unsigned        uOld;
+       unsigned        uNum;
+       unsigned        uTemp;
+       unsigned        uStart;
+       unsigned   *pLines;
+       BaseItem  **pItems;
+       BaseItem   *pEntry;
+       BaseItem   *pTemp;
+       RECT            sRect;
+
+       uOld    = pData->uItemPosCount;
+       pLines  = pData->pItemPos;
+       pItems  = pData->pTreeItems;
+
+       if(!uItem) {                                                            
                                // Am Anfang beginnen
+               uItem = pData->uFirstChild;
+               if(!uItem) {                                                    
                                // Leere Liste
+                       if(!uOld)
+                               return;
+
+                       for(uNum = 0; uNum < uOld; uNum++) {                    
                // Die alten Eintr�ge zur�cksetzen
+                               uTemp = pLines[uNum];
+                               if(!uTemp)
+                                       continue;
+                               pLines[uNum] = 0;
+                               pTemp = pItems[uTemp];
+                               if(!pTemp)
+                                       continue;
+                               pTemp->uShowPos = 0;
+                       }
+
+                       pData->uItemPosCount = 0;
+
+                       GetClientRect(pData->hWnd, &sRect);
+                       InvalidateRect(pData->hWnd, &sRect, TRUE);
+
+                       memset(pLines, 0, sizeof(unsigned)*uOld);
+                       return;
+               }
+
+               for(uNum = 0; uNum < uOld; uNum++) {                            
                // Die alten Eintr�ge zur�cksetzen
+                       uTemp = pLines[uNum];
+                       if(!uTemp)
+                               continue;
+                       pLines[uNum] = 0;
+                       pTemp = pItems[uTemp];
+                       if(!pTemp)
+                               continue;
+                       pTemp->uShowPos = 0;
+               }
+
+               pEntry                   = pItems[uItem];
+               pEntry->uShowPos = 1;
+               pLines[0]                = uItem;
+               uPos                     = 1;
+               uStart                   = 0;
+       } else {                                                                
                                        // Bei einem Eintrag beginnen
+               pEntry                   = pItems[uItem];
+               uPos                     = pEntry->uShowPos;
+               if(uPos)
+                       uStart   = uPos - 1;
+               else
+                       uStart   = 0;
+
+               for(uNum = uPos; uNum < uOld; uNum++) {                         
                // Die alten Eintr�ge zur�cksetzen
+                       uTemp = pLines[uNum];
+                       if(!uTemp)
+                               continue;
+                       pLines[uNum] = 0;
+                       pTemp = pItems[uTemp];
+                       if(!pTemp)
+                               continue;
+                       pTemp->uShowPos = 0;
+               }
+       }
+
+       for(;;) {                                                               
                                        // Die Zeilen neu zuordnen
+               if(pEntry->uFirstChild && (pEntry->uState & TVIS_EXPANDED)) {
+                       uItem = pEntry->uFirstChild;
+               } else
+                       if(pEntry->uNextItem) {
+                               uItem = pEntry->uNextItem;
+                       } else {
+                               for(;;) {
+                                       uItem = pEntry->uParent;
+                                       if(!uItem)
+                                               break;
+
+                                       pEntry = pItems[uItem];
+                                       if(pEntry->uNextItem) {                 
                        // Gibt es etwas in der gleichen Ebene
+                                               uItem = pEntry->uNextItem;
+                                               break;
+                                       }
+                               }
+
+                               if(!uItem)
+                                       break;
+                       }
+
+               pEntry = pItems[uItem];
+
+               if(pLines[uPos] != uItem) {
+                       pLines[uPos] = uItem;
+               } else {
+                       if(uStart == uPos)
+                               uStart++;
+               }
+
+               uPos++;
+               pEntry->uShowPos = uPos;
+       }
+
+       pData->uItemPosCount = uPos;
+
+       if(uStart > pData->uScrollY)                                            
                // Neu zu zeichnenten Bereich bestimmen
+               uStart -= pData->uScrollY;
+       else
+               uStart = 0;
+
+       GetClientRect(pData->hWnd, &sRect);
+
+       sRect.top = pData->uStartPixel + pData->iRowHeight * uStart;
+
+       if(sRect.top <= sRect.bottom) {
+               InvalidateRect(pData->hWnd, &sRect, FALSE);
+       }
+
+       if(uOld != uPos)
+               UpdateScrollY(pData);
+}
+
+//*****************************************************************************
+//*
+//*            UpdateColumns
+//*
+//*****************************************************************************
+//     Pr�ft ob es Ver�nderungen in Spaltenbreiten gab
+//     pData           : Zeiger auf die Fensterdaten
+//     Ergibt die Breite ab der die Spalten ver�ndert wurden oder 0x10000
+static int UpdateColumns(TreeListData *pData) {
+#ifndef __REACTOS__
+       HWND    hHeader;
+#endif
+       UINT    uNext;
+       UINT    uCol;
+       UINT    uSub;
+       int             iSize;
+       int             iNum;
+       int             iNow;
+       int             iOld;
+       int             iRet;
+
+#ifndef __REACTOS__
+       hHeader = pData->hHeader;
+#endif
+       pData->aColumnXpos[0] = 0;
+
+       iRet = 0x10000;
+       iOld = 0;
+       iNow = 0;
+
+       for(uCol = 0; uCol < pData->uColumnCount;) {                            
        // Suche die erste ge�nderte Spalte
+               uSub  = pData->aColumnPos[uCol];
+               iSize = pData->aColumn[uSub].sReal;
+               uSub  = pData->aColumn[uSub].bNext;
+               iOld  = iNow;
+               iNow += iSize;
+               uCol += 1;
+
+               if(uCol == 1)
+                       iNow -= 1;
+               if(iNow < iOld)
+                       iNow  = iOld;
+               if(uSub == pData->uColumnCount)
+                       if(iNow >= (int)pData->uSizeX - 1) {
+                               iNow++;
+                       }
+
+               iNum = pData->aColumnXpos[uSub];
+
+               if(iNum == iNow)
+                       continue;
+               if(iNum == 0)
+                       iNum = iOld;
+               if(iNum >= iNow) {
+                       iRet = iOld;
+               } else {
+                       iRet = iOld;
+
+                       if(pData->uSelectedItem) {                              
                // Problem bei ausgew�hlten leeren Eintr�gen
+                               uNext = 
pData->aColumn[pData->uSelectedSub].bNext;
+                               if(uNext == uSub) {
+                                       UpdateRect(pData, pData->uSelectedItem, 
pData->uSelectedSub);
+                               }
+                       }
+
+                       if(pData->uTrackedItem) {
+                               uNext = 
pData->aColumn[pData->uTrackedSub].bNext;
+                               if(uNext == uSub) {
+                                       UpdateRect(pData, pData->uTrackedItem, 
pData->uTrackedSub);
+                               }
+                       }
+               }
+
+               pData->aColumnXpos[uSub] = iNow;
+               break;
+       }
+
+       while(uCol < pData->uColumnCount) {                                     
                // Restliche Spalten berechen
+               iOld  = iNow;
+               uSub  = pData->aColumnPos[uCol];
+               iNow += pData->aColumn[uSub].sReal;
+               uSub  = pData->aColumn[uSub].bNext;
+               uCol += 1;
+
+               if(uCol == pData->uColumnCount)
+                       if(iNow >= (int)pData->uSizeX - 1) {
+                               iNow++;
+                       }
+
+               pData->aColumnXpos[uSub] = iNow;
+       }
+
+       pData->aColumnXpos[pData->uColumnCount + 1] = pData->uSizeX + 1;
+
+       return iRet;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListSetOrderArray
+//*
+//*****************************************************************************
+//     Stellt die anzeige Reihenfolge der Spalten ein
+//     pData           : Zeiger auf die Fensterdaten
+//     uItems          : Ist die Nummer des Eintrages
+//     pArray          : Zeiger auf die Eintr�ge. Null steht f�r die 
Standartreihenfolge.
+//                               z.B. {0,2,1} meint die sichtbare Reihenfolge 
Col0,Col2,Col1
+//                               Der erste Eintrag muss 0 immer sein.
+//     Ergibt   1 = Ok
+//                      0 = Fehler
+static int TreeListSetOrderArray(TreeListData *pData, unsigned uItems, 
unsigned *pArray) {
+
+       BYTE            aFlags[MAX_COLUMNS + 1];
+       UINT            aArray[MAX_COLUMNS + 1];
+       TV_COLSIZE      sNotify;
+       UINT            uDiff;
+       UINT            uCol;
+       UINT            uSub;
+
+       if(!pArray) {                                                           
                                // Spezialreihenfolge setzen
+               if(uItems == FROM_HEADER) {                                     
                        // Array aus Header holen
+                       if(!Header_GetOrderArray(pData->hHeader, 
pData->uColumnCount, aArray)) {
+                               return 0;
+                       }
+
+                       if(aArray[0] != 0) {
+                               return 0;
+                       }
+               } else {
+                       for(uCol = pData->uColumnCount; uCol > 0; uCol++) {     
        // Standartreihenfolge
+                               uCol--;
+                               aArray[uCol] = uCol;
+                       }
+               }
+
+               uItems = pData->uColumnCount;
+               pArray = aArray;
+       } else {                                                                
                                        // Pr�fe Array
+               if(pData->uColumnCount != uItems || uItems == 0 || *pArray) {
+                       return 0;
+               }
+       }
+
+       memset(aFlags, 0, sizeof(aFlags) - 1);
+
+       for(uCol = 0, uDiff = 0; uCol < uItems; uCol++) {                       
                // Die Eintr�ge pr�fen
+               uSub    = pArray[uCol];
+               if(uSub >= uItems)
+                       return 0;
+               if(aFlags[uSub])
+                       return 0;
+
+               aFlags[uSub] = (BYTE)uCol;
+
+               uDiff |= uCol ^ pData->aColumnPos[uSub];
+       }
+
+       if(uDiff == 0) {                                                        
                                // Alles blieb gleich
+               return 1;
+       }
+
+       aFlags[0     ] = 0;
+       aFlags[uItems] = (BYTE)uItems;
+
+       for(uCol = 1; uCol < uItems; uCol++) {                                  
                // Die Eintr�ge anpassen
+               pData->aColumnPos[uCol]         = (BYTE)pArray[uCol];
+       }
+
+       for(uCol = 0; uCol < uItems; uCol++) {
+               uSub                                            = aFlags[uCol];
+               pData->aColumn[uCol].bIndex     = (BYTE)uSub;
+               pData->aColumn[uCol].bNext      = pData->aColumnPos[uSub + 1];
+       }
+
+       Header_SetOrderArray(pData->hHeader, uItems, pArray);
+       UpdateColumns(pData);
+       UpdateView(pData);
+
+       if(pData->uStyleEx & TVS_EX_HEADERCHGNOTIFY) {                          
// Alle Spalten haben sich ver�ndert
+               UNLOCK(pData);
+
+               for(uCol = 0; uCol < uItems; uCol++) {
+                       sNotify.hdr.code        = TVN_COLUMNCHANGED;
+                       sNotify.uColumn         = uCol;
+                       sNotify.uIndex          = pData->aColumn[uCol].bIndex;
+                       sNotify.uPosX           = pData->aColumnXpos[uCol];
+                       sNotify.iSize           = pData->aColumn[uCol].sReal;
+
+                       SendNotify(pData, &sNotify.hdr);
+               }
+
+               LOCK(pData);
+       }
+
+       return 1;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListToggleItem
+//*
+//*****************************************************************************
+//     Klappt bei einem Eintrag die Kinder um, und schickt alle 
Notify-Nachrichten.
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist die Nummer des Eintrages
+//     uAddFlags       : Sind die State-Flags die hinzugef�gt werden sollen
+//                               Bits 0..3 entahlen das Kommando, bei 
automatisch ermitteln
+//     Ergibt  -1 = Fehler
+//                      0 = Ausgef�hrt
+//                      1 = Abbruch
+static int TreeListToggleItem(TreeListData *pData, unsigned uItem, unsigned 
uAddFlags) {
+
+       NMTREEVIEW      sNotify;
+       BaseItem  **pList;
+       BaseItem   *pEntry;
+       BaseItem   *pTemp;
+       unsigned        uAction;
+       unsigned        uLevel;
+       unsigned        uNext;
+       LRESULT         lRet;
+       BOOL            bDo;
+
+       if(uItem > pData->uTreeItemsMax)
+               return 0;
+
+       pList  = pData->pTreeItems;
+       pEntry = pList[uItem];
+       if(!pEntry)
+               return -1;
+
+       uAction = uAddFlags & 0x0F;
+       if(!uAction) {
+               uAction = ((pEntry->uState ^ TVIS_EXPANDED) & (TVIS_EXPANDED | 
TVIS_EXPANDPARTIAL)) ? TVE_EXPAND : TVE_COLLAPSE;
+       }
+
+       sNotify.action                          =  uAction;
+       sNotify.hdr.code                        =  TVN_ITEMEXPANDING;
+       sNotify.itemNew.mask            =  TVIF_HANDLE | TVIF_PARAM | 
TVIF_STATE;
+       sNotify.itemNew.hItem           = (HTREEITEM)uItem;
+       sNotify.itemNew.stateMask       =  0xFFFFFFFF;
+       sNotify.itemNew.state           =  pEntry->uState;
+       sNotify.itemNew.lParam          =  pEntry->lParam;
+       sNotify.itemNew.pszText         = (LPTSTR) - 1;
+       sNotify.itemNew.cchTextMax      =  -1;
+       sNotify.itemOld.mask            =  0;
+       sNotify.ptDrag.x                        =  0;
+       sNotify.ptDrag.y                        =  0;
+
+       UNLOCK(pData);
+
+       lRet = SendNotify(pData, &sNotify.hdr);
+
+       LOCK(pData);
+
+       pList  = pData->pTreeItems;
+       pEntry = pList[uItem];
+
+       if(pEntry == 0)
+               return -1;                                                      
                // Eintrag inzischen gel�scht ?
+       if(lRet  != 0)
+               return  1;                                                      
                // User-Abbruch ?
+
+       if(uAction == TVE_EXPAND) {                                             
                        // Aufklappen
+               if(pEntry->uState & TVIS_EXPANDED) {
+                       bDo = FALSE;                                            
                        // Nur von + auf -
+               } else {
+                       pEntry->uState |= TVIS_EXPANDED;                        
        // Kinder Aufklappen
+                       bDo = TRUE;
+               }
+       } else {                                                                
                                        // Zuklappen
+               pEntry->uState &= ~TVIS_EXPANDED;
+               bDo        = TRUE;
+       }
+
+       pEntry->uState &= ~TVIS_EXPANDPARTIAL;
+       pEntry->uState |=  uAddFlags&~0x0F;
+
+       if(pEntry->uShowPos && bDo) {
+               if(pEntry->uState & TVIS_EXPANDED) {                            
        // Kinderfenster aktuallisieren
+                       uLevel                  =  0;
+                       uNext                   =  pEntry->uFirstChild;
+
+                       while(uNext) {
+                               pTemp = pList[uNext];
+                               pTemp->uShowPos = 0;
+
+                               if(pTemp->uFirstChild) {
+                                       uNext = pTemp->uFirstChild;
+                                       uLevel++;
+                                       continue;
+                               }
+
+                               if(pTemp->uNextItem) {
+                                       uNext = pTemp->uNextItem;
+                                       continue;
+                               }
+
+                               if(uLevel == 0)
+                                       break;
+
+                               uNext = pList[pTemp->uParent]->uNextItem;
+                               uLevel--;
+                       }
+               }
+
+               UpdateItems(pData, uItem);
+       }
+
+       sNotify.action                          =  uAction;
+       sNotify.hdr.code                        =  TVN_ITEMEXPANDED;
+       sNotify.itemNew.mask            =  TVIF_HANDLE | TVIF_PARAM | 
TVIF_STATE;
+       sNotify.itemNew.hItem           = (HTREEITEM)uItem;
+       sNotify.itemNew.stateMask       =  0xFFFFFFFF;
+       sNotify.itemNew.state           =  pEntry->uState;
+       sNotify.itemNew.lParam          =  pEntry->lParam;
+       sNotify.itemNew.pszText         = (LPTSTR) - 1;
+       sNotify.itemNew.cchTextMax      =  -1;
+       sNotify.itemOld.mask            =  0;
+       sNotify.ptDrag.x                        =  0;
+       sNotify.ptDrag.y                        =  0;
+
+       UNLOCK(pData);
+
+       SendNotify(pData, &sNotify.hdr);
+
+       LOCK(pData);
+
+       pList  = pData->pTreeItems;
+       pEntry = pData->pTreeItems[uItem];
+
+       if(!pEntry)
+               return -1;                                                      
                // Eintrag inzischen gel�scht ?
+
+       if(uAction == TVE_EXPAND) {                                             
                        // ONCE setzen nach Expandieren
+               pEntry->uState |= TVIS_EXPANDEDONCE;
+       }
+
+       if(pData->uSelectedItem && bDo) {                                       
                // Ist der ausgew�hlten Eintrag sichtbar ?
+               pEntry = pList[pData->uSelectedItem];
+               if(!pEntry) {
+                       pData->uSelectedItem = 0;
+                       pData->uSelectedSub      = 0;
+               } else
+                       if(!pEntry->uShowPos) {
+                               while(!pEntry->uShowPos) {
+                                       uItem  = pEntry->uParent;
+                                       pEntry = pList[uItem];
+                               }
+
+                               TreeListSelectItem(pData, uItem, 
pData->uSelectedSub, TVC_UNKNOWN);
+                       }
+       }
+
+       if(bDo == FALSE) {                                                      
                                // Nur von + auf -
+               UpdateRect(pData, uItem, 0);
+       }
+
+       return 0;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListGetItemRect
+//*
+//*****************************************************************************
+//     Holt das Rechteck eines Eintrages
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist die Nummer des Eintrages
+//     uFlags          : Bit 0   : 0=volle Zeile  1=nur Text
+//                               Bit 7   : 1=nur Spalte
+//                               Bit 24.. : Spaltennummer
+//     Ergibt 1 wenn der Eintrag sichtbar war
+static int TreeListGetItemRect(TreeListData *pData, unsigned uItem, unsigned 
uFlags, RECT *pRect) {
+
+       ExtraItem  *pExtra;
+       BaseItem   *pEntry;
+       unsigned        uNext;
+       unsigned        uPos;
+       unsigned        uSub;
+
+       if(uItem > pData->uTreeItemsMax) {
+               memset(pRect, 0, sizeof(RECT));
+               return 0;
+       }
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry->uShowPos) {                                                 
                // Ist der Eintrag aufgeklappt
+               memset(pRect, 0, sizeof(RECT));
+               return 0;
+       }
+
+       uPos = pEntry->uShowPos - pData->uScrollY - 1;
+       if(uPos >= pData->uMaxEnties) {                                         
                // Eintrag im Fenster sichtbar
+               memset(pRect, 0, sizeof(RECT));
+               return 0;
+       }
+
+       pRect->top     = pData->uStartPixel;
+       pRect->top    += pData->iRowHeight * uPos;
+       pRect->bottom  = pData->iRowHeight + pRect->top;
+
+       if((uFlags & 0xFC) == TVIR_GETCOLUMN) {                                 
        // Nur Spalten
+               uSub = uFlags >> 24;
+               if(uSub >= pData->uColumnCount)
+                       uSub = 0;
+
+               uNext              = pData->aColumn[uSub].bNext;
+               pRect->left    = pData->aColumnXpos[uSub];
+               pRect->left   -= pData->uScrollX;
+               pRect->right   = pData->aColumnXpos[uNext];
+               pRect->right  -= pData->uScrollX;
+       } else {
+               uSub               = 0;
+               pRect->left    = 0;
+               pRect->left   -= pData->uScrollX;
+               pRect->right   = pData->uSizeX;
+       }
+
+       if(uFlags & TVIR_TEXT) {                                                
                        // Nur Text ausgeben
+               if(uSub > 0) {
+                       pExtra =  pData ->pExtraItems[uSub - 1][uItem];
+
+                       if(pData->aColumn[uSub].bEdit == TVAX_CHECK) {
+                               pRect->left += pData->iChecksXsize;
+                               if(pRect->left > pRect->right)
+                                       pRect->left = pRect->right;
+                       } else
+                               if(pExtra && pExtra->bFlags & TVIX_HASIMAGE) {
+                                       pRect->left += pData->iImagesXsize;
+                                       if(pRect->left > pRect->right)
+                                               pRect->left = pRect->right;
+                               }
+               } else {
+                       if(pData->cHasRootRow) {                                
                        // Root-Linien ausgleichen
+                               pRect->left += pData->iIndent;
+                       }
+
+                       pRect->left += pData->iIndent * pEntry->uLevel;
+
+                       if(pData->hStates) {
+                               pRect->left += pData->iStatesXsize;
+                       }
+
+                       if(!(pData->uStyle & TVS_HASLINES)) {
+                               pRect->left -= 1;
+                       }
+
+                       if(pData->uStyleEx & TVS_EX_ITEMLINES) {
+                               pRect->left += 1;
+                               if(pEntry->bFlags & TVIX_HASIMAGE)
+                                       pRect->left++;
+                       }
+
+                       if(pEntry->bFlags & TVIX_HASIMAGE) {
+                               pRect->left += pData->iImagesXsize;
+                       }
+
+                       if(pRect->left > pRect->right) {
+                               pRect->left = pRect->right;
+                       }
+               }
+       }
+
+       return 1;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListEnsureVisible
+//*
+//*****************************************************************************
+//     Macht einen Eintrag sichtbar
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist die Nummer des Eintrages
+//     uSub            : Untereintrag der sichtbar sein soll
+//                                             0xFFFFFFFF nur Zeile
+//                                             FIRST_LINE als oberster Eintrag
+//     Ergibt 1 wenn nur zum Eintrag gescrollt wurde bzw. 0 wenn aufgeklapt 
wurde
+static int TreeListEnsureVisible(TreeListData *pData, unsigned uItem, unsigned 
uSub) {
+
+       BaseItem   *pEntry;
+       BaseItem   *pTemp;
+       unsigned        uTemp;
+       unsigned        uNext;
+       unsigned        uPos;
+       int                     iNum;
+       int                     iAnf;
+       int                     iOff;
+       int                     iEnd;
+       int                     iMax;
+       int                     iRet;
+
+       if(uItem > pData->uTreeItemsMax)
+               return -1;
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry)
+               return -1;
+
+       uPos = pEntry->uShowPos;
+       if(!uPos) {                                                             
                                // Zweige aufklappen wenn Eintrag zugeklappt
+
+               iRet = 0;
+
+               for(pTemp = pEntry;;) {
+                       uTemp = pTemp->uParent;
+                       pTemp = pData->pTreeItems[uTemp];
+                       if(!pTemp)
+                               break;
+                       if((pTemp->uState & TVIS_EXPANDED) == 0) {
+                               if(TreeListToggleItem(pData, uTemp, 0))
+                                       return 0;
+                       }
+               }
+
+               pEntry = pData->pTreeItems[uItem];
+               if(!pEntry)
+                       return 0;
+
+               uPos = pEntry->uShowPos;
+               if(!uPos)
+                       return 0;
+       } else {                                                                
                                        // Nur Scrollen
+               iRet = 1;
+       }
+
+       uPos--;
+       if(uPos < pData->uScrollY) {                                            
                // Vor erster Zeile
+               pData->uScrollY = uPos;
+               SetScrollPos(pData->hWnd, SB_VERT, uPos, TRUE);
+               UpdateView(pData);
+       } else
+               if(uSub == FIRST_LINE) {                                        
                        // Als ersten Eintrag
+                       if(uPos != pData->uScrollY) {
+                               pData->uScrollY = uPos;
+                               SetScrollPos(pData->hWnd, SB_VERT, uPos, TRUE);
+                               UpdateView(pData);
+                       }
+
+                       return iRet;
+               } else
+                       if(uPos >= pData->uScrollY + pData->uPageEnties) {      
        // Nach letzter Zeile
+                               iOff  = uPos - (pData->uPageEnties - 1);
+                               iMax  = pData->uItemPosCount;
+                               iMax -= pData->uPageEnties - 1;
+
+                               if(iOff >= iMax)
+                                       iOff = iMax;
+                               if(iOff < 0)
+                                       iOff = 0;
+                               if(iOff != (int)pData->uScrollY) {
+                                       pData->uScrollY = iOff;
+                                       SetScrollPos(pData->hWnd, SB_VERT, 
iOff, TRUE);
+                                       UpdateView(pData);
+                               }
+                       }
+
+       if(uSub < pData->uColumnCount) {                                        
                // Horizontal einrichten
+               uNext = pData->aColumn[uSub].bNext;
+               iNum  = pData->uSizeX;
+               iOff  = pData->uScrollX;
+               iAnf  = pData->aColumnXpos[uSub ];
+               iEnd  = pData->aColumnXpos[uNext];
+
+               if(iOff + iNum < iAnf)
+                       iOff = iAnf;
+               if(iOff     >= iEnd)
+                       iOff = iAnf;
+               if(iOff + iNum < iEnd)
+                       iOff = iEnd - iNum;
+               if(iOff     > iAnf)
+                       iOff = iAnf;
+
+               iMax  = pData->aColumnXpos[pData->uColumnCount];
+               iMax -= pData->uSizeX / 2;
+
+               if(iOff > iMax)
+                       iOff = iMax;
+               if(iOff <   0)
+                       iOff = 0;
+               if(iOff != (int)pData->uScrollX) {
+                       pData->uScrollX = iOff;
+                       SetScrollPos(pData->hWnd, SB_HORZ, iOff, TRUE);
+                       UpdateView(pData);
+                       MoveWindow(pData->hHeader, -iOff, 0, iNum + iOff, 
pData->uStartPixel, TRUE);
+               }
+       }
+       return iRet;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListIsVisible
+//*
+//*****************************************************************************
+//     Pr�ft ob ein Eintrag sichtbar ist
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist die Nummer des Eintrages
+//     uSub            : Untereintrag der gepr�ft werden soll
+//                                             0xFFFFFFFF nur Zeile pr�fen
+//     Ergibt den Zustand des Eintrages:
+//                                -1 = Unbekannter Eintrag
+//                                     0 = Eintrag ist zugeklappt
+//                                     1 = Eintrag ist aufgeklappt aber nicht 
sichtbar
+//                                     2 = Eintrag ist aufgeklappt und 
teilweise sichtbar
+//                                     3 = Eintrag ist aufgeklappt und Spalte 
ist nur teilweise sichtbar
+//                                     4 = Eintrag ist aufgeklappt und ganz 
sichtbar
+static int TreeListIsVisible(TreeListData *pData, unsigned uItem, unsigned 
uSub) {
+
+       BaseItem   *pEntry;
+       unsigned        uNext;
+       unsigned        uPos;
+       int                     iNum;
+       int                     iAnf;
+       int                     iOff;
+       int                     iEnd;
+
+       if(uItem > pData->uTreeItemsMax)
+               return -1;
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry)
+               return -1;
+
+       uPos = pEntry->uShowPos;
+       if(!uPos) {                                                             
                                // Ist der Eintrag zugeklappt
+               return 0;
+       }
+
+       uPos--;
+       if(uPos < pData->uScrollY) {                                            
                // Vor erster Zeile
+
+               return 1;
+       }
+
+       if(uPos >= pData->uScrollY + pData->uMaxEnties) {                       
        // Nach letzter Zeile
+               return 1;
+       }
+
+       if(uPos == pData->uScrollY + pData->uPageEnties) {                      
// Auf halbsichtbarer Zeile
+               if(uSub < pData->uColumnCount) {
+                       uNext = pData->aColumn[uSub].bNext;
+                       iNum  = pData->uSizeX;
+                       iOff  = pData->uScrollX;
+                       iAnf  = pData->aColumnXpos[uSub ];
+                       iEnd  = pData->aColumnXpos[uNext];
+
+                       if(iOff + iNum < iAnf)
+                               return 1;
+                       if(iOff     >= iEnd)
+                               return 1;
+               }
+
+               return 2;
+       }
+
+       if(uSub < pData->uColumnCount) {                                        
                // Spalte pr�fen
+               uNext = pData->aColumn[uSub].bNext;
+               iNum  = pData->uSizeX;
+               iOff  = pData->uScrollX;
+               iAnf  = pData->aColumnXpos[uSub ];
+               iEnd  = pData->aColumnXpos[uNext];
+
+               if(iOff + iNum < iAnf)
+                       return 1;
+               if(iOff     >= iEnd)
+                       return 1;
+               if(iOff + iNum < iEnd)
+                       return 3;
+               if(iOff     > iAnf)
+                       return 3;
+       }
+
+       return 4;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListDeleteItem
+//*
+//*****************************************************************************
+//     L�scht einen Eintrag aus dem Fenster
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist die Nummer des Eintrages der gel�scht werden soll
+//     iMode           : Wie soll der Eintrag gel�scht werden
+//                                     0 = Eintrag l�schen und nicht neu 
zeichnen
+//                                     1 = Eintrag l�schen und neu zeichnen
+//                                     2 = Nur Kindereintr�ge l�schen und neu 
zeichnen
+//     Ergibt 1 wenn der Eintrag gel�scht wurde.
+static int TreeListDeleteItem(TreeListData *pData, unsigned uItem, int iMode) {
+
+       NMTREEVIEW      sNotify;
+       ExtraItem **pList;
+       ExtraItem  *pExtra;
+       BaseItem   *pEntry;
+       BaseItem   *pTemp;
+       unsigned        uPos;
+       int                     iOff;
+       int                     iMax;
+
+       if(pData->cLockChanges)
+               return 0;
+
+       if(uItem > pData->uTreeItemsMax) {                                      
                // Pr�fe den Eintrag
+               if(uItem != U(TVI_ROOT))
+                       return 0;                                       // 
Alles l�schen
+               if(pData->uLastChild == 0)
+                       return 0;
+
+               while(pData->uLastChild) {
+                       TreeListDeleteItem(pData, pData->uLastChild, 0);
+               }
+
+               pData->uItemPosCount = 0;
+
+               UpdateScrollY(pData);
+               UpdateView(pData);
+
+               return 1;
+       }
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry) {                                                           
                                // Pr�fe den Eintrag
+               if(uItem != 0)
+                       return 0;                                               
        // Alles l�schen
+               if(pData->uLastChild == 0)
+                       return 0;
+
+               while(pData->uLastChild) {
+                       TreeListDeleteItem(pData, pData->uLastChild, 0);
+               }
+
+               pData->uItemPosCount = 0;
+
+               UpdateScrollY(pData);
+               UpdateView(pData);
+
+               return 1;
+       }
+
+       if(iMode == 2) {                                                        
                                // Nur Kindereintr�ge l�schen
+               if(!pEntry->uFirstChild) {
+                       return 0;
+               }
+
+               while(pEntry->uLastChild) {                                     
                // Alle Kinder l�schen
+                       TreeListDeleteItem(pData, pEntry->uLastChild, 0);
+               }
+
+               uPos = pEntry->uShowPos;
+               if(uPos) {
+                       UpdateItems(pData, uItem);
+               }
+
+               return 1;
+       }
+
+       while(pEntry->uLastChild) {                                             
                // Alle Kinder l�schen
+               TreeListDeleteItem(pData, pEntry->uLastChild, 0);
+       }
+
+       if(uItem == pData->uSelectedItem) {                                     
                // Einen ausgew�hlten Eintrag l�schen
+               sNotify.hdr.code                        = TVN_SELCHANGED;
+               sNotify.action                          = TVC_UNKNOWN;
+               sNotify.itemOld.mask            = TVIF_HANDLE | TVIF_PARAM | 
TVIF_STATE | TVIF_SUBITEM | TVIF_PARAM;
+               sNotify.itemOld.hItem           = (HTREEITEM)uItem;
+               sNotify.itemOld.stateMask       = 0xFFFFFFFF;
+               sNotify.itemOld.state           = pEntry->uState&~TVIS_SELECTED;
+               sNotify.itemOld.lParam          = pEntry->lParam;
+               sNotify.itemOld.cChildren       = 0;
+               sNotify.itemOld.pszText         = (LPTSTR) - 1;
+               sNotify.itemOld.cchTextMax      = -1;
+               sNotify.itemNew.mask            = TVIF_HANDLE | TVIF_PARAM | 
TVIF_STATE | TVIF_SUBITEM | TVIF_PARAM;
+               sNotify.itemNew.hItem           = NULL;
+               sNotify.itemNew.stateMask       = 0xFFFFFFFF;
+               sNotify.itemNew.state           = 0;
+               sNotify.itemNew.lParam          = 0;
+               sNotify.itemNew.cChildren       = 0;
+               sNotify.itemNew.pszText         = (LPTSTR) - 1;
+               sNotify.itemNew.cchTextMax      = -1;
+               sNotify.ptDrag.x                        = 0;
+               sNotify.ptDrag.y                        = 0;
+
+               UNLOCK(pData);
+               SendNotify(pData, &sNotify.hdr);                                
                // Bekant geben das der Eintrag nicht mehr ausgew�hlt ist
+               LOCK(pData);
+
+               pData->uSelectedItem = 0;
+               pData->uSelectedSub  = 0;
+       }
+
+       sNotify.hdr.code                        = TVN_DELETEITEM;
+       sNotify.itemNew.mask            = 0;
+       sNotify.itemOld.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE;
+       sNotify.itemOld.hItem           = (HTREEITEM)uItem;
+       sNotify.itemOld.lParam          = pEntry->lParam;
+       sNotify.itemOld.pszText         = (LPTSTR) - 1;
+       sNotify.itemNew.stateMask       = 0xFFFFFFFF;
+       sNotify.itemNew.state           = pEntry->uState;
+       sNotify.itemOld.cchTextMax      = -1;
+       sNotify.ptDrag.x                        = 0;
+       sNotify.ptDrag.y                        = 0;
+
+       UNLOCK(pData);
+       SendNotify(pData, &sNotify.hdr);
+       LOCK(pData);
+
+       pEntry = pData->pTreeItems[uItem];                                      
// Pr�fen ob der Eintrag noch existiert
+       if(!pEntry)
+               return 0;
+
+       if(uItem == pData->uTrackedItem) {                                      
                // Einen unterstrichenen Eintrag l�schen
+               pData->uTrackedItem  = 0;
+               pData->uTrackedSub   = 0;
+       }
+
+       if(pData->uInsertMark == uItem) {
+               pData->uInsertMark = 0;
+       }
+
+       if(pData->uSingleSel == uItem) {
+               pData->uSingleSel = 0;
+       }
+
+       if(pEntry->uPrevItem) {                                                 
                // Gibt es einen vorherigen Eintrag
+               pTemp                    = pData->pTreeItems[pEntry->uPrevItem];
+               pTemp->uNextItem = pEntry->uNextItem;
+       } else {
+               if(pEntry->uParent) {                                           
                        // Neues erstes Kind in Elterneintrag
+                       pTemp                      = 
pData->pTreeItems[pEntry->uParent];
+                       pTemp->uFirstChild = pEntry->uNextItem;
+               } else {
+                       pData->uFirstChild = pEntry->uNextItem;
+               }
+       }
+
+       if(pEntry->uNextItem) {                                                 
                // Gibt es einen vorherigen Eintrag
+               pTemp                    = pData->pTreeItems[pEntry->uNextItem];
+               pTemp->uPrevItem = pEntry->uPrevItem;
+       } else {
+               if(pEntry->uParent) {                                           
                        // Neues letztes Kind in Elterneintrag
+                       pTemp                     = 
pData->pTreeItems[pEntry->uParent];
+                       pTemp->uLastChild = pEntry->uPrevItem;
+
+                       if(pTemp->uFirstChild == 0 && pTemp->uLastChild == 0) {
+                               pTemp->bFlags &= ~TVIX_HASBUTTON;
+                       }
+               } else {
+                       pData->uLastChild = pEntry->uPrevItem;
+               }
+       }
+
+       for(uPos = 1; uPos < pData->uColumnCount; uPos++) {                     
        // Alle Extraeintr�ge l�schen
+               pList = pData->pExtraItems[uPos - 1];
+
+               pExtra = pList[uItem];
+               if(!pExtra)
+                       continue;
+
+               pList[uItem] = NULL;
+
+               if(pExtra->pText) {
+                       pExtra->uTextSize = 0;
+                       delete(pExtra->pText);
+               }
+
+               delete(pExtra);
+       }
+
+
+       pData->pTreeItems[uItem] = NULL;                                        
        // Den Eintrag l�schen
+
+       if(pEntry->pText) {
+               pEntry->uTextSize = 0;
+               delete(pEntry->pText);
+       }
+
+       if(iMode) {                                                             
                                // Den Eintrag neuzeichnen
+               uItem =   pEntry->uPrevItem;
+               if(!uItem && !pEntry->uNextItem) {
+                       uItem = pEntry->uParent;
+                       if(!uItem)
+                               uPos = 1;
+                       else
+                               uPos = pData->pTreeItems[uItem]->uShowPos;
+               } else {
+                       uPos = pEntry->uShowPos;
+               }
+
+               if(uPos) {
+                       UpdateItems(pData, uItem);
+               }
+       }
+
+       if(pEntry->uState & TVIS_SELECTED)                                      
        // Ausgew�hlte Eintr�ge runterz�hlen
+               if(pData->uSelectedCount > 0) {
+                       pData->uSelectedCount--;
+               }
+
+       delete(pEntry);
+
+       pData->uTreeItemsCount--;
+
+       iOff  = pData->uScrollY;                                                
                // Pr�fe die Scrollposition
+       iMax  = pData->uItemPosCount;
+       iMax -= pData->uPageEnties - 1;
+
+       if(iOff >= iMax)
+               iOff = iMax;
+       if(iOff < 0)
+               iOff = 0;
+       if(iOff != (int)pData->uScrollY) {
+               pData->uScrollY = iOff;
+               SetScrollPos(pData->hWnd, SB_VERT, iOff, TRUE);
+               UpdateView(pData);
+       }
+
+       return 1;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListXorSelectItem
+//*
+//*****************************************************************************
+//     W�hlt einen Eintrag ab bzw. an
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist die Nummer des Eintrages der ausgew�hlt werden 
soll
+//     iMode           : Ist der Grund f�r die �nderung
+//                                             TVC_BYKEYBOARD
+//                                             TVC_BYMOUSE
+//                                             TVC_UNKNOWN
+//     Ergibt          1 wenn der Eintrag ab/angew�hlt wurde
+//                             0 wenn der Eintrag nicht ver�ndert wurde
+static int TreeListXorSelectItem(TreeListData *pData, unsigned uItem, int 
iMode) {
+
+       NMTREEVIEW      sNotify;
+       BaseItem   *pEntry;
+       unsigned        uOld;
+       unsigned        uRet;
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry)
+               return 0;
+       if(uItem == pData->uSelectedItem)
+               return 0;
+
+       uOld = pEntry->uState;
+
+       sNotify.hdr.code                        = TVN_SELCHANGING;
+       sNotify.action                          = iMode;
+       sNotify.itemNew.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE 
| TVIF_SUBITEM | TVIF_PARAM;
+       sNotify.itemNew.hItem           = (HTREEITEM)uItem;
+       sNotify.itemNew.stateMask       = 0xFFFFFFFF;
+       sNotify.itemNew.state           = pEntry->uState;
+       sNotify.itemNew.lParam          = pEntry->lParam;
+       sNotify.itemNew.cChildren       = 0;
+       sNotify.itemNew.pszText         = (LPTSTR) - 1;
+       sNotify.itemNew.cchTextMax      = -1;
+       sNotify.itemOld.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE 
| TVIF_SUBITEM | TVIF_PARAM;
+       sNotify.itemOld.hItem           = NULL;
+       sNotify.itemOld.stateMask       = 0xFFFFFFFF;
+       sNotify.itemOld.state           = 0;
+       sNotify.itemOld.lParam          = 0;
+       sNotify.itemOld.cChildren       = 0;
+       sNotify.itemOld.pszText         = (LPTSTR) - 1;
+       sNotify.itemOld.cchTextMax      = -1;
+       sNotify.ptDrag.x                        = 0;
+       sNotify.ptDrag.y                        = 0;
+
+       UNLOCK(pData);
+       uRet = U(SendNotify(pData, &sNotify.hdr));
+       LOCK(pData);
+
+       if(uRet)
+               return 0;
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry)
+               return 0;
+       pEntry->uState ^= TVIS_SELECTED;
+
+       sNotify.hdr.code                        = TVN_SELCHANGED;
+       sNotify.action                          = iMode;
+       sNotify.itemNew.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE 
| TVIF_SUBITEM | TVIF_PARAM;
+       sNotify.itemNew.hItem           = (HTREEITEM)uItem;
+       sNotify.itemNew.stateMask       = 0xFFFFFFFF;
+       sNotify.itemNew.state           = pEntry->uState;
+       sNotify.itemNew.lParam          = pEntry->lParam;
+       sNotify.itemNew.cChildren       = 0;
+       sNotify.itemNew.pszText         = (LPTSTR) - 1;
+       sNotify.itemNew.cchTextMax      = -1;
+       sNotify.itemOld.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE 
| TVIF_SUBITEM | TVIF_PARAM;
+       sNotify.itemOld.hItem           = NULL;
+       sNotify.itemOld.stateMask       = 0xFFFFFFFF;
+       sNotify.itemOld.state           = 0;
+       sNotify.itemOld.lParam          = 0;
+       sNotify.itemOld.cChildren       = 0;
+       sNotify.itemOld.pszText         = (LPTSTR) - 1;
+       sNotify.itemOld.cchTextMax      = -1;
+       sNotify.ptDrag.x                        = 0;
+       sNotify.ptDrag.y                        = 0;
+
+       UNLOCK(pData);
+       SendNotify(pData, &sNotify.hdr);
+       LOCK(pData);
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry)
+               return 0;
+       if(pEntry->uShowPos) {
+               if(pData->uStyleEx & TVS_EX_FULLROWMARK)
+                       UpdateRow(pData, uItem);
+               else
+                       UpdateRect(pData, uItem, 0);
+       }
+
+       if((uOld ^ pEntry->uState)&TVIS_SELECTED) {
+               if(pEntry->uState & TVIS_SELECTED)
+                       pData->uSelectedCount++;
+               else
+                       pData->uSelectedCount--;
+       }
+
+       return 1;
+}
+
+
+//*****************************************************************************
+//*
+//*            TreeListRemoveFocus
+//*
+//*****************************************************************************
+//     W�hlt den Focus ab
+//     pData           : Zeiger auf die Fensterdaten
+static void TreeListRemoveFocus(TreeListData *pData) {
+
+       ExtraItem  *pExtra;
+       BaseItem   *pEntry;
+       unsigned        uItem;
+       unsigned        uSub;
+
+       if(!pData->uFocusItem)
+               return;
+
+       uItem  = pData->uFocusItem;
+       pEntry = pData->pTreeItems[uItem];
+
+       if(pEntry) {
+               pEntry->bFlags &= ~TVIX_FOCUSED;
+
+               uSub = pData->uFocusSub;
+
+               if(uSub) {
+                       pExtra = pData->pExtraItems[uSub - 1][uItem];
+                       if(pExtra)
+                               pExtra->bFlags &= ~TVIX_FOCUSED;
+               }
+
+               UpdateRect(pData, uItem, uSub);
+       }
+
+       pData->uFocusItem = 0;
+       pData->uFocusSub  = 0;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListSetFocus
+//*
+//*****************************************************************************
+//     W�hlt den Focus-Eintrag
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Eintrag f�r den Focus (0xFFFFFFFF=keine �nderung)
+//     uSub            : Spalte f�r den Focus  (0xFFFFFFFF=keine �nderung)
+//     Ergibt 1 wenn der Focus gesetzt wurde, bzw 0 bei einem Fehler
+static int  TreeListSetFocus(TreeListData *pData, unsigned uItem, unsigned 
uSub) {
+
+       ExtraItem  *pExtra;
+       BaseItem   *pEntry;
+       BaseItem   *pTemp;
+       unsigned        uTemp;
+       unsigned        uCol;
+
+       if(pData->uFocusItem) {
+               if(uSub == 0xFFFFFFFF)
+                       uSub = pData->uFocusSub;
+               if(uItem == 0xFFFFFFFF)
+                       uItem = pData->uFocusItem;
+       } else {
+               if(uSub == 0xFFFFFFFF)
+                       uSub = pData->uSelectedSub;
+               if(uItem == 0xFFFFFFFF)
+                       uItem = pData->uSelectedItem;
+       }
+
+       if(pData->uFocusItem == uItem)
+               if(pData->uFocusSub == uSub)
+                       return 1;
+
+       if(!uItem) {                                                            
                                // Focus abw�hlen
+               TreeListRemoveFocus(pData);
+               return 1;
+       }
+
+
+       if(uItem > pData->uTreeItemsMax) {                                      
                // Den Eintrag pr�fen
+               return 0;
+       }
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry) {
+               return 0;
+       }
+
+       if(!(pData->uStyleEx & TVS_EX_SUBSELECT))
+               uSub = 0;
+
+       if(!(pData->uStyleEx & TVS_EX_MULTISELECT)) {                           
// Einzel auswahl
+               return TreeListSelectItem(pData, uItem, uSub, TVC_UNKNOWN);
+       }
+
+       uTemp  = pData->uFocusItem;
+       pTemp  = pData->pTreeItems[uTemp];
+
+       if(pTemp) {                                                             
                                // Den alten Eintrag abw�hlen
+               pTemp->bFlags &= ~TVIX_FOCUSED;
+               uCol = pData->uFocusSub;
+
+               if(uCol) {
+                       pExtra = pData->pExtraItems[uCol - 1][uTemp];
+                       if(pExtra)
+                               pExtra->bFlags &= ~TVIX_FOCUSED;
+               }
+
+               UpdateRect(pData, uItem, uSub);
+       }
+
+
+       if(uSub) {                                                              
                                // Neuen Eintrag w�hlen
+               pExtra = pData->pExtraItems[uSub - 1][uItem];
+               if(pExtra)
+                       pExtra->bFlags |= TVIX_FOCUSED;
+       } else {
+               pEntry->bFlags |= TVIX_FOCUSED;
+       }
+
+       pData->uFocusItem = uItem;
+       pData->uFocusSub  = uSub;
+
+       if(pEntry->uState & TVIS_SELECTED) {                                    
        // Auch die Auswahl nachziehen
+               if(pData->uSelectedItem != uItem) {
+                       uTemp = pData->uSelectedItem;
+                       uCol  = pData->uSelectedSub;
+               } else {
+                       uTemp = 0;
+                       uCol  = pData->uSelectedSub;
+               }
+
+               pData->uSelectedItem = uItem;
+               pData->uSelectedSub  = uSub;
+
+               if(pData->uStyleEx & TVS_EX_FULLROWMARK) {
+                       uCol = uSub + 1;
+               }
+
+               if(uTemp) {
+                       if(uCol != uSub)
+                               UpdateRow(pData, uTemp);
+                       else
+                               UpdateRect(pData, uTemp, uCol);
+               }
+
+
+               if(uCol != uSub)
+                       UpdateRow(pData, uItem);
+               else
+                       UpdateRect(pData, uItem, uCol);
+       } else {
+               UpdateRect(pData, uItem, uSub);
+       }
+
+       return 1;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListSelectItem
+//*
+//*****************************************************************************
+//     W�hlt einen Eintrag aus
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist die Nummer des Eintrages der ausgew�hlt werden 
soll
+//     uSubItem        : Ist die Spalte die gew�hlt werden soll
+//     iMode           : Ist der Grund f�r die �nderung
+//                                             TVC_BYKEYBOARD
+//                                             TVC_BYMOUSE
+//                                             TVC_UNKNOWN
+//                                             TVC_ONLYFOCUS   (nur der Focus 
hat sich ver�ndert)
+//                                             TVC_DESELECT    (dieses Flag 
l�scht die alte Auswahl)
+//                                             TVC_UNSELECT    (dieses Flag 
l�scht Auswahl bei MultiSel)
+//     Ergibt          2 wenn der Eintrag gew�hlt und umgeklapt wurde
+//                             1 wenn der Eintrag gew�hlt wurde
+//                             0 wenn der Eintrag nicht gew�hlt wurde
+static int TreeListSelectItem(TreeListData *pData, unsigned uItem, unsigned 
uSubItem, int iMode) {
+
+       NMTREEVIEW      sNotify;
+       ExtraItem  *pExtra;
+       BaseItem   *pEntry;
+       BaseItem   *pTemp;
+       LPARAM          lParam;
+       LPARAM          lPaOld;
+       unsigned        uState;
+       unsigned        uStOld;
+       unsigned        uNext;
+       unsigned        uPos;
+       unsigned        uOld;
+       unsigned        uSub;
+       unsigned        uRet;
+       int                     iDel;
+       int                     iSel;
+
+       uOld = pData->uSelectedItem;
+       uSub = pData->uSelectedSub;
+
+       if(uSubItem >= pData->uColumnCount && uSubItem > 0)
+               return 0;
+       if(uItem   > pData->uTreeItemsMax)
+               return 0;
+       if(uItem   == uOld)
+               if(uSubItem == uSub)
+                       if(pData->uSelectedCount <= 1 || !(pData->uStyleEx & 
TVS_EX_MULTISELECT)) {
+                               return 1;
+                       }
+
+       if(pData->uStyleEx & TVS_EX_MULTISELECT) {                              
        // Ist die Mehrfachauswahl m�glich
+               iSel = iMode & TVC_UNSELECT;
+               iDel = iMode & TVC_DESELECT;
+               if(!iDel) {
+                       if(pData->uStyleEx & (TVS_EX_FULLROWMARK | 
TVS_EX_SUBSELECT))
+                               UpdateRow(pData, uOld);
+                       else
+                               UpdateRect(pData, uOld, uSub);
+
+                       uOld = 0;
+                       uSub = 0;
+               } else {                                                        
                                        // Alle gew�hlten Eintr�ge abw�hlen
+                       if(pData->uSelectedCount > 1 && pData->uTreeItemsMax) {
+                               for(uPos = pData->uTreeItemsMax; uPos; uPos--) {
+                                       pEntry = pData->pTreeItems[uPos];
+                                       if(!pEntry || !(pEntry->uState & 
TVIS_SELECTED))
+                                               continue;
+                                       if(TreeListXorSelectItem(pData, uPos, 
iMode))
+                                               if(!pData->uSelectedCount)
+                                                       break;          // 
Wurden alle Eintr�ge abgew�hlt
+                               }
+                       }
+               }
+       } else {                                                                
                                        // Altes Select l�schen
+               iMode &= ~TVC_ONLYFOCUS;
+               iDel   =  1;
+               iSel   =  0;
+       }
+
+       iMode &= ~(TVC_DESELECT | TVC_UNSELECT);
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry) {                                                           
                                // Neuen Statatus holen
+               if(uItem)
+                       return 0;
+               uState = 0;
+               lParam = 0;
+       } else {
+               uState = pEntry->uState;
+               lParam = pEntry->lParam;
+
+               if(uSubItem) {
+                       uState &= TVIS_BASEFLAGS;
+                       pExtra  = pData->pExtraItems[uSubItem - 1][uItem];
+                       if(pExtra)
+                               uState |= pExtra->uState;
+               }
+       }
+
+       pTemp = pData->pTreeItems[uOld];
+       if(!pTemp) {                                                            
                                // Alten Status holen
+               uStOld = 0;
+               lPaOld = 0;
+       } else {
+               uStOld = pTemp->uState;
+               lPaOld = pTemp->lParam;
+
+               if(uSub) {
+                       uStOld &= TVIS_BASEFLAGS;
+                       pExtra  = pData->pExtraItems[uSub - 1][uOld];
+                       if(pExtra)
+                               uStOld |= pExtra->uState;
+               }
+       }
+
+       sNotify.hdr.code                        = TVN_SELCHANGING;
+       sNotify.action                          = iMode;
+       sNotify.itemNew.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE 
| TVIF_SUBITEM | TVIF_PARAM;
+       sNotify.itemNew.hItem           = (HTREEITEM)uItem;
+       sNotify.itemNew.stateMask       = 0xFFFFFFFF;
+       sNotify.itemNew.state           = uState;
+       sNotify.itemNew.lParam          = lParam;
+       sNotify.itemNew.cChildren       = uSubItem;
+       sNotify.itemNew.pszText         = (LPTSTR) - 1;
+       sNotify.itemNew.cchTextMax      = -1;
+       sNotify.itemOld.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE 
| TVIF_SUBITEM | TVIF_PARAM;
+       sNotify.itemOld.hItem           = (HTREEITEM)uOld;
+       sNotify.itemOld.stateMask       = 0xFFFFFFFF;
+       sNotify.itemOld.state           = uStOld;
+       sNotify.itemNew.lParam          = lPaOld;
+       sNotify.itemOld.cChildren       = uSub;
+       sNotify.itemOld.pszText         = (LPTSTR) - 1;
+       sNotify.itemOld.cchTextMax      = -1;
+       sNotify.ptDrag.x                        = 0;
+       sNotify.ptDrag.y                        = 0;
+
+
+       UNLOCK(pData);
+
+       if(SendNotify(pData, &sNotify.hdr)) {                                   
        // Abfragen ob der Eintrag gew�hlt werden darf
+               LOCK(pData);
+               return 0;
+       }
+
+       LOCK(pData);
+
+       if(uItem) {                                                             
                                // Pr�fen ob der Eintrag noch existiert
+               pEntry = pData->pTreeItems[uItem];
+               if(!pEntry)
+                       return 0;
+       }
+
+       if(iDel) {
+               uOld    = pData->uSelectedItem;
+               pTemp   = pData->pTreeItems[uOld];
+       }
+
+
+       if(pTemp) {                                                             
                                // Den alten Eintrag abw�hlen
+               if(pTemp->uShowPos) {                                           
                        // Den Eintrag neu zeichnen
+                       if((pData->uStyleEx & TVS_EX_FULLROWMARK) || 
pData->uSelectedSub)
+                               UpdateRow(pData, uOld);
+                       else
+                               UpdateRect(pData, uOld, uSub);
+               }
+
+               if(pTemp->uState & TVIS_SELECTED) {
+                       uStOld            &= ~TVIS_SELECTED;
+                       pTemp->uState &= ~TVIS_SELECTED;
+
+                       if(pData->uSelectedCount > 0) {
+                               pData->uSelectedCount -= 1;
+                       }
+               }
+
+               pData->uSelectedSub    = 0;
+               pData->uSelectedItem   = 0;
+       } else {
+               uOld  = 0;
+       }
+
+
+       if(uItem) {                                                             
                                // Den neuen Eintrag w�hlen
+               if(iSel) {
+                       if(pEntry->uState & TVIS_SELECTED) {
+                               uState                            &= 
~TVIS_SELECTED;
+                               pEntry->uState        &= ~TVIS_SELECTED;
+                               if(pData->uSelectedCount)
+                                       pData->uSelectedCount--;
+                       }
+               } else {
+                       if(!(pEntry->uState & TVIS_SELECTED)) {
+                               uState                            |= 
TVIS_SELECTED;
+                               pEntry->uState        |= TVIS_SELECTED;
+                               pData->uSelectedCount += 1;
+                       }
+               }
+
+               if(uSubItem && uSubItem < pData->uColumnCount) {
+                       pExtra = pData->pExtraItems[uSubItem - 1][uItem];
+                       if(!pExtra) {
+                               pExtra  = new(ExtraItem, 1);
+                               memset(pExtra, 0, sizeof(ExtraItem));
+                               pExtra->iImage = TV_NOIMAGE;
+                               pExtra->uState = pEntry->uState & (TVIS_BOLD | 
TVIS_UNDERLINE);
+                               pData->pExtraItems[uSubItem - 1][uItem] = 
pExtra;
+                       }
+
+                       uState  = pExtra->uState;
+                       uState |= pEntry->uState & TVIS_BASEFLAGS;
+               } else {
+                       uState  = pEntry->uState;
+               }
+
+               if(pEntry->uShowPos) {                                          
                // Den Eintrag neu zeichnen
+                       if(pData->uStyleEx & (TVS_EX_FULLROWMARK | 
TVS_EX_SUBSELECT))
+                               UpdateRow(pData, uItem);
+                       else
+                               UpdateRect(pData, uItem, uSubItem);
+               }
+
+               pData->uSelectedSub  = uSubItem;
+               pData->uSelectedItem = uItem;
+       } else {
+               pData->uSelectedItem = 0;
+               pData->uSelectedSub  = 0;
+               uState                           = 0;
+       }
+
+       sNotify.hdr.code                        = TVN_SELCHANGED;
+       sNotify.action                          = iMode;
+       sNotify.itemNew.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE 
| TVIF_SUBITEM | TVIF_PARAM;
+       sNotify.itemNew.hItem           = (HTREEITEM)uItem;
+       sNotify.itemNew.stateMask       = 0xFFFFFFFF;
+       sNotify.itemNew.state           = uState;
+       sNotify.itemNew.lParam          = lParam;
+       sNotify.itemNew.cChildren       = uSubItem;
+       sNotify.itemNew.pszText         = (LPTSTR) - 1;
+       sNotify.itemNew.cchTextMax      = -1;
+       sNotify.itemOld.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE 
| TVIF_SUBITEM | TVIF_PARAM;
+       sNotify.itemOld.hItem           = (HTREEITEM)uOld;
+       sNotify.itemOld.stateMask       = 0xFFFFFFFF;
+       sNotify.itemOld.state           = uStOld;
+       sNotify.itemOld.lParam          = lPaOld;
+       sNotify.itemOld.cChildren       = uSub;
+       sNotify.itemOld.pszText         = (LPTSTR) - 1;
+       sNotify.itemOld.cchTextMax      = -1;
+       sNotify.ptDrag.x                        = 0;
+       sNotify.ptDrag.y                        = 0;
+
+       UNLOCK(pData);
+       SendNotify(pData, &sNotify.hdr);
+       LOCK(pData);
+
+       if(!(pData->uStyle & TVS_SINGLEEXPAND)) {                               
        // Einzelmodus aktiv
+               if(pData->uStyle & TVS_SHOWSELALWAYS)
+                       if(pData->uSelectedItem) {
+                               TreeListEnsureVisible(pData, 
pData->uSelectedItem, pData->uSelectedSub);
+                       }
+
+               return 1;
+       }
+
+
+       
//*****************************************************************************
+
+
+       sNotify.hdr.code                        = TVN_SINGLEEXPAND;
+       sNotify.action                          = iMode;
+       sNotify.itemNew.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE;
+       sNotify.itemNew.hItem           = (HTREEITEM)uItem;
+       sNotify.itemNew.stateMask       = 0xFFFFFFFF;
+       sNotify.itemNew.state           = (pEntry) ? pEntry->uState : 0;
+       sNotify.itemNew.cChildren       = 0;
+       sNotify.itemNew.pszText         = (LPTSTR) - 1;
+       sNotify.itemNew.cchTextMax      = -1;
+       sNotify.itemOld.mask            = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE;
+       sNotify.itemOld.hItem           = (HTREEITEM)uOld;
+       sNotify.itemOld.stateMask       = 0xFFFFFFFF;
+       sNotify.itemOld.state           = (pTemp) ? pTemp->uState : 0;
+       sNotify.itemOld.cChildren       = 0;
+       sNotify.itemOld.pszText         = (LPTSTR) - 1;
+       sNotify.itemOld.cchTextMax      = -1;
+       sNotify.ptDrag.x                        = 0;
+       sNotify.ptDrag.y                        = 0;
+
+       UNLOCK(pData);
+       uRet = U(SendNotify(pData, &sNotify.hdr));                              
        // Anfragen ob die Zweige umgeklappt werden d�rfen
+       LOCK(pData);
+
+
+       pTemp   = pData->pTreeItems[uOld ];                                     
        // Zeiger neu holen falls es �nderungen gab
+       pEntry  = pData->pTreeItems[uItem];
+
+       while(pTemp && pEntry) {                                                
                        // Beide Zweige sysnchronisieren
+               if(pEntry->uLevel > pTemp->uLevel) {
+                       uNext  = pEntry->uParent;
+
+                       if(!(uRet & TVNRET_SKIPNEW))
+                               if(!(pEntry->uState & TVIS_EXPANDED)) {
+                                       TreeListToggleItem(pData, uItem, 0);
+                               }
+
+                       pEntry = pData->pTreeItems[uNext];
+                       uItem  = uNext;
+
+                       if(!uItem)
+                               break;
+
+                       continue;
+               }
+
+               if(uItem == uOld)
+                       goto EndSel;                                            
        // Bis zum gleichen Knoten
+
+               uNext  = pTemp->uParent;
+
+               if(!(uRet & TVNRET_SKIPOLD))
+                       if(pTemp->uState & TVIS_EXPANDED) {
+                               TreeListToggleItem(pData, uOld, 0);
+                       }
+
+               pTemp  = pData->pTreeItems[uNext];
+               uOld   = uNext;
+       }
+
+       if(!uItem) {
+               if(!(uRet & TVNRET_SKIPOLD))
+                       while(pTemp) {                                          
                                // Alten Zweig zuklappen
+                               uNext = pTemp->uParent;
+
+                               if(pTemp->uState & TVIS_EXPANDED) {
+                                       TreeListToggleItem(pData, uOld, 0);
+                               }
+
+                               pTemp = pData->pTreeItems[uNext];
+                               uOld  = uNext;
+                       }
+
+               goto EndSel;
+       }
+
+       if(!uOld) {
+               if(!(uRet & TVNRET_SKIPNEW))
+                       while(pEntry) {                                         
                                // Neuen Zweig aufklappen
+                               uNext = pEntry->uParent;
+
+                               if(!(pEntry->uState & TVIS_EXPANDED)) {
+                                       TreeListToggleItem(pData, uItem, 0);
+                               }
+
+                               pEntry = pData->pTreeItems[uNext];
+                               uItem  = uNext;
+                       }
+       }
+
+EndSel:
+
+       if(pData->uStyle & TVS_SHOWSELALWAYS)
+               if(pData->uSelectedItem) {
+                       TreeListEnsureVisible(pData, pData->uSelectedItem, 
pData->uSelectedSub);
+               }
+
+       return 2;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListSelectChilds
+//*
+//*****************************************************************************
+//     W�hlt einen Eintrag aus
+//     pData           : Zeiger auf die Fensterdaten
+//     uItem           : Ist die Nummer des Eintrages der ausgew�hlt werden 
soll
+//     iMode           : Bit 0 = Untereint�ge auch �ndern
+//                               Bit 1 = Eintr�ge abw�hlen
+//     Ergibt 1 wenn die Auswahl funktioniert hat, bzw. 0 bei einem Fehler
+static int TreeListSelectChilds(TreeListData *pData, unsigned uItem, int 
iMode) {
+
+       BaseItem   *pEntry;
+       unsigned        uLevel;
+       unsigned        uXor;
+
+       if(!(pData->uStyleEx & TVS_EX_MULTISELECT))
+               return 0;
+
+       uLevel = 0;
+
+       if(uItem == U(TVI_ROOT)) {
+               uItem  = pData->uFirstChild;
+       } else {
+               if(uItem > pData->uTreeItemsMax)
+                       return 0;
+       }
+
+       if(!pData->pTreeItems[uItem]) {
+               return 0;
+       }
+
+
+       uXor   = (iMode & TVIS_DESELECT) ? 0 : TVIS_SELECTED;
+       iMode &= TVIS_WITHCHILDS;
+
+       for(;;) {
+               pEntry = pData->pTreeItems[uItem];
+
+               if((pEntry->uState ^ uXor)&TVIS_SELECTED) {
+                       TreeListXorSelectItem(pData, uItem, TVC_UNKNOWN);
+               }
+
+               if(iMode && pEntry->uFirstChild) {                              
        // Auch Kinder �ndern
+                       uItem = pEntry->uFirstChild;
+                       uLevel++;
+                       continue;
+               }
+
+               for(;;) {                                                       
                                        // Eine Ebene h�her
+                       uItem = pEntry->uNextItem;
+                       if(uItem != 0)
+                               break;
+                       if(uLevel == 0)
+                               return 1;
+
+                       uLevel--;
+
+                       uItem  = pEntry->uParent;
+                       pEntry = pData->pTreeItems[uItem];
+               }
+       }
+}
+
+//*****************************************************************************
+//*
+//*            TreeListInsertItem
+//*
+//*****************************************************************************
+//     F�gt einen Eintrag ins Fenster ein
+//     pData           : Zeiger auf die Fensterdaten
+//     pInsert         : Zeiger auf die ein zu f�genden Daten
+//     Ergibt die Einf�geposition des neuen Eintrages oder 0 bei einem Fehler
+static unsigned TreeListInsertItem(TreeListData *pData, TV_INSERTSTRUCT 
*pInsert) {
+
+       char       *pTemp;
+       BYTE            bFlag;
+       LPCTSTR     pText;
+       LPCTSTR     pTextTemp;
+       PFNTVSORTEX pCompare;
+       ExtraItem **pExOld[MAX_COLUMNS];
+       ExtraItem **pExNew[MAX_COLUMNS];
+       BaseItem   *pNew;
+       BaseItem  **pOld;
+       BaseItem  **pItems;
+       BaseItem   *pEntry;
+       BaseItem   *pParent;
+       unsigned   *pPosNew;
+       unsigned   *pPosOld;
+       unsigned   *pFirst;
+       unsigned   *pLast;
+       unsigned        uBefore;
+       unsigned        uParent;
+       unsigned        uAfter;
+       unsigned        uFirst;
+       unsigned        uSize;
+       unsigned        uBits;
+       unsigned        uItem;
+       unsigned        uNext;
+       unsigned        uMax;
+       unsigned        uPos;
+       unsigned        uNum;
+       int                     iCmp;
+       int                     iNone;
+       int                     iCount;
+       int                     iShift;
+
+       if(pData->cLockChanges)
+               return 0;
+
+       uParent = U(pInsert->hParent);
+       if(uParent > pData->uTreeItemsMax) {                                    
        // Pr�fe das Elternelement
+               if(pInsert->hParent != TVI_ROOT) {
+                       return 0;
+               }
+
+               pParent = NULL;
+       } else {
+               pParent = pData->pTreeItems[uParent];
+               if(!pParent) {
+                       if(uParent)
+                               return 0;
+                       pParent = NULL;
+               }
+       }
+
+       if(pData->uTreeItemsCount + 1 > pData->uTreeItemsMax) {         // 
Gr��e der Liste erh�hen
+               pPosOld = pData->pItemPos;
+               pOld    = pData->pTreeItems;
+               uMax    = pData->uTreeItemsMax;
+               uMax   += pData->uTreeItemsMax / 2;
+               uMax   += 64;
+               pItems  = new(BaseItem*, uMax + 1);
+
+               if(!pItems) {
+                       return 0;
+               }
+
+               pPosNew = new(unsigned, uMax);
+               if(!pPosNew) {
+                       delete(pItems);
+                       return 0;
+               }
+
+               for(uPos = 1; uPos < pData->uColumnCount; uPos++) {
+                       pExOld[uPos] = pData->pExtraItems[uPos - 1];
+                       pExNew[uPos] = new(ExtraItem*, uMax + 1);
+
+                       if(!pExNew[uPos]) {
+                               for(uPos--; uPos > 0; uPos--)
+                                       delete(pExNew[uPos]);
+                               delete(pPosNew);
+                               delete(pItems);
+                               return 0;
+                       }
+               }
+
+               memcpy(pItems , pData->pTreeItems       , sizeof(BaseItem *) * 
(pData->uTreeItemsMax + 1));
+               memset(pItems + pData->uTreeItemsMax + 1, 0, sizeof(BaseItem *) 
* (uMax - pData->uTreeItemsMax));
+               memcpy(pPosNew, pData->pItemPos         , sizeof(unsigned) * 
(pData->uTreeItemsCount));
+               memset(pPosNew + pData->uTreeItemsCount, 0, sizeof(unsigned) * 
(uMax - pData->uTreeItemsCount));
+
+               for(uPos = 1; uPos < pData->uColumnCount; uPos++) {
+                       memcpy(pExNew[uPos], pExOld[uPos]            , 
sizeof(ExtraItem *) * (pData->uTreeItemsMax + 1));
+                       memset(pExNew[uPos] + pData->uTreeItemsMax + 1, 0, 
sizeof(ExtraItem *) * (uMax - pData->uTreeItemsMax));
+                       pData->pExtraItems[uPos - 1] = pExNew[uPos];
+                       delete(pExOld[uPos]);
+               }
+
+               pData->uTreeItemsMax = uMax;
+               pData->pTreeItems        = pItems;
+               pData->pItemPos          = pPosNew;
+               delete(pPosOld);
+               delete(pOld);
+       }
+
+       //******************** Den neuen Eintrag erzeugen 
*****************************
+       pItems  = pData->pTreeItems;
+       uPos    = pData->uNextSeachPos + 1;
+       pTemp   = new(char, sizeof(BaseItem) + pData->uUserDataSize);
+       pNew    = (BaseItem *)pTemp;
+
+       if(!pNew) {                                                             
                                // Konnte der Speicher reserviert werden
+               return 0;
+       }
+
+       if(pData->uUserDataSize) {                                              
                // Die Userdaten auf 0 setzen
+               memset(pTemp + sizeof(BaseItem), 0, pData->uUserDataSize);
+       }
+
+       for(;; uPos++) {                                                        
                                // Suche freie Position
+               if(uPos > pData->uTreeItemsMax)
+                       uPos = 1;
+               if(pItems[uPos] == NULL)
+                       break;
+       }
+
+       pData->uNextSeachPos = uPos;
+
+       memset(pNew, 0, sizeof(BaseItem));                                      
        // Erstelle den neuen Eintrag
+       pNew->iImage = TV_NOIMAGE;
+       pNew->iSelectedImage = TV_NOIMAGE;
+
+       uBits = pInsert->item.mask;
+
+       if(uBits & TVIF_STATE) {
+               pNew->uState = pInsert->item.state & pInsert->item.stateMask;
+       } else {
+               if(pData->uStyle  & TVS_CHECKBOXES)
+                       if(!(pData->uStyleEx & TVS_EX_BITCHECKBOX)) {
+                               pNew->uState = 0x1000;
+                       }
+       }
+
+       if(uBits & TVIF_PARAM) {
+               pNew->lParam = pInsert->item.lParam;
+       }
+
+       if(uBits & TVIF_IMAGE) {
+               pNew->iImage = pInsert->item.iImage;
+               if(pNew->iImage == I_IMAGECALLBACK)
+                       pNew->bCallback |= TVIF_IMAGE;
+       }
+
+       if(uBits & TVIF_SELECTEDIMAGE) {
+               pNew->iSelectedImage = pInsert->item.iSelectedImage;
+               if(pNew->iSelectedImage == I_IMAGECALLBACK)
+                       pNew->bCallback |= TVIF_SELECTEDIMAGE;
+       }
+
+       if(uBits & TVIF_CHILDREN) {                                             
                        // Art der Schaltfl�chen
+               switch(pInsert->item.cChildren) {
+                       case  0:
+                               break;
+                       case  1:
+                               pNew->bFlags   |= TVIX_HASBUTTON;
+                               break;
+                       case  I_CCB:
+                               pNew->bCallback |= TVIF_CHILDREN;
+                               break;
+                       default
+                                       :
+                               pNew->bFlags   |= TVIX_VARBUTTON;
+                               break;
+               }
+       } else {
+               pNew->bFlags |= TVIX_VARBUTTON;
+       }
+
+       if(pData->uStyle & TVS_SINGLEEXPAND) {                                  
        // Nicht aufklappen bei Einzelmodus
+               pNew->uState &= ~TVIS_EXPANDED;
+       }
+
+       if(uBits & TVIF_TEXT) {                                                 
                        // Text einf�gen
+               if(pInsert->item.pszText == LPSTR_TEXTCALLBACK) {
+                       pNew->bCallback |= TVIF_TEXT;
+                       pNew->uTextSize = 0;
+                       pNew->pText             = 0;
+               } else {
+                       pNew->uTextSize = (WORD)str_len(pInsert->item.pszText);
+                       pNew->pText             = new(TCHAR, pNew->uTextSize + 
1);
+                       memcpy(pNew->pText, pInsert->item.pszText, 
sizeof(TCHAR) * (pNew->uTextSize + 1));
+               }
+       } else {
+               pNew->pText             = new(TCHAR, 1);
+               pNew->pText[0]  = 0;
+               pNew->uTextSize = 0;
+       }
+
+       if(!pParent) {                                                          
                        // Einen Root-Eintrag einf�gen
+               pNew->uParent   = 0;
+               uParent                 = 0;
+               bFlag                   = 0;
+               uFirst                  = 0xFFFFFFFF;
+               pFirst                  = &pData->uFirstChild;
+               pLast                   = &pData->uLastChild;
+       } else {                                                                
                                        // Einen Tree-Eintrag einf�gen
+               pNew->uParent   =  uParent;
+               pNew->uLevel    =  pParent->uLevel + 1;
+               uFirst                  =  pParent->uFirstChild;
+               pFirst                  = &pParent->uFirstChild;
+               pLast                   = &pParent->uLastChild;
+               bFlag                   =  pParent->bFlags;
+
+               if(pParent->bFlags & TVIX_VARBUTTON) {
+                       pParent->bFlags |= TVIX_HASBUTTON;
+               }
+       }
+
+       //******************** Eintrage einf�gen 
**************************************
+       uAfter = U(pInsert->hInsertAfter);
+
+       switch(uAfter) {
+               case U(TVI_BEFORE):                                             
                                // Nach einem Eintrag einf�gen
+                       if(pParent) {                                           
                                // Einen Root-Eintrag einf�gen
+                               pEntry  = pParent;
+                               pParent ->bFlags  = bFlag;
+                               uParent = pParent->uParent;
+                               pParent = pItems  [uParent];
+
+                               if(!pParent) {
+                                       pNew->uParent   = 0;
+                                       pNew->uLevel    = 0;
+                                       uParent                 = 0;
+                                       uFirst                  = 0xFFFFFFFF;
+                                       pFirst                  = 
&pData->uFirstChild;
+                                       pLast                   = 
&pData->uLastChild;
+                               } else {                                        
                                        // Einen Tree-Eintrag einf�gen
+                                       pNew->uParent   =  uParent;
+                                       pNew->uLevel    =  pParent->uLevel + 1;
+                                       uFirst                  =  
pParent->uFirstChild;
+                                       pFirst                  = 
&pParent->uFirstChild;
+                                       pLast                   = 
&pParent->uLastChild;
+
+                                       if(pParent->bFlags & TVIX_VARBUTTON) {
+                                               pParent->bFlags |= 
TVIX_HASBUTTON;
+                                       }
+                               }
+
+                               if(pEntry->uPrevItem) {
+                                       uAfter = pEntry->uPrevItem;
+                                       goto DoInsert;
+                               }
+                       }
+
+               case U(TVI_FIRST):                                              
                                // Am Anfang einf�gen
+                       if(pFirst[0]) {                                         
                        // Gibt es schon Eintr�ge
+                               pEntry = pItems[pFirst[0]];
+                               pEntry->uPrevItem = uPos;
+                       } else {
+                               pFirst[0] = uPos;
+                               pLast [0] = uPos;
+                               break;
+                       }
+
+                       pNew ->uNextItem = pFirst[0];                           
        // Eintrag einf�gen
+                       pFirst[0]                = uPos;
+                       break;
+
+               case U(TVI_ROOT):                                               
                                // Als Root-Eintrag einf�gen
+                       pNew->uParent   = 0;
+                       uParent                 = 0;
+                       pFirst                  = &pData->uFirstChild;
+                       pLast                   = &pData->uLastChild;
+
+               case U(TVI_LAST):                                               
                                // Am Ende einf�gen
+                       if(pLast[0]) {                                          
                        // Gibt es schon Eintr�ge
+                               pEntry = pItems[pLast[0]];
+                               pEntry->uNextItem = uPos;
+                       } else {
+                               pFirst[0] = uPos;
+                               pLast [0] = uPos;
+                               break;
+                       }
+
+                       pNew ->uPrevItem = pLast[0];                            
        // Eintrag einf�gen
+                       pLast[0]                 = uPos;
+                       break;
+
+
+               case U(TVI_SORTEX):                                             
                                // Einf�gen mittels Funktion
+                       uItem = pFirst[0];
+                       if(!uItem) {                                            
                                // Gibt es keine Kindeintr�ge
+                               pFirst[0] = uPos;
+                               pLast [0] = uPos;
+                               break;
+                       }
+
+                       if(pNew->bCallback & TVIF_TEXT) {                       
                // Text �ber Callback holen
+                               uSize = 1;
+                               LOCK(pData);
+                               CallbackEntry(pData, pNew, uPos, TVIF_TEXT, 
&iNone, &uSize, &pText);
+                               UNLOCK(pData);
+                       } else {
+                               pText = pNew->pText;
+                       }
+
+                       pData->cLockChanges = 1;
+
+                       pCompare = (PFNTVSORTEX)(pInsert->item.hItem);
+                       if(!pCompare)
+                               break;
+                       uNext    = uItem;
+                       iCount   = 0;
+                       uBefore  = 0;
+
+                       while(uNext) {                                          
                        // Z�hle die Eintr�ge
+                               iCount++;
+                               uNext = pItems[uNext]->uNextItem;
+                       }
+
+                       while(iCount > 0) {                                     
                                                // Binary-Seach Algorithnus
+                               iShift = iCount / 2;
+                               uNext  = uItem;
+
+                               while(iShift > 0) {
+                                       uNext  = pItems[uNext]->uNextItem;
+                                       iShift--;
+                               }
+
+                               pEntry  = pItems[uNext];
+                               if(pEntry->bCallback & TVIF_TEXT) {             
                // Text �ber Callback holen
+                                       uSize = 0;
+                                       LOCK(pData);
+                                       CallbackEntry(pData, pEntry, uItem, 
TVIF_TEXT, &iNone, &uSize, &pTextTemp);
+                                       UNLOCK(pData);
+                               } else {
+                                       pTextTemp = pEntry->pText;
+                               }
+
+                               iCmp = pCompare(pData->hWnd, (HTREEITEM)uNext, 
pTextTemp, pText, pEntry->lParam, pInsert->item.lParam);
+                               if(iCmp < 0) {
+                                       iCount -= (iCount + 1) / 2;
+                                       continue;
+                               }
+
+                               if(iCmp > 0) {
+                                       iCount -= iCount / 2 + 1;
+                                       uBefore = uNext;
+                                       uItem   = pItems[uNext]->uNextItem;
+                                       continue;
+                               }
+
+                               uBefore = pEntry->uPrevItem;
+                               uItem   = uNext;
+                               break;
+                       }
+
+                       pData->cLockChanges = 0;
+
+                       pNew->uNextItem = uItem;
+                       pNew->uPrevItem = uBefore;
+
+                       if(uBefore) {                                           
                                // Vorherigen Eintrag anpassen
+                               pEntry = pItems[uBefore];
+                               pEntry->uNextItem = uPos;
+                       } else {                                                
                                        // Am Anfang einf�gen
+                               pFirst[0] = uPos;
+                       }
+
+                       if(uItem) {                                             
                                // N�chsten Eintrag anpassen
+                               pEntry = pItems[uItem];
+                               pEntry->uPrevItem = uPos;
+                       } else {                                                
                                        // Am Ende anh�ngen
+                               pLast[0] = uPos;
+                       }
+                       break;
+
+               case U(TVI_SORT):                                               
                                // Alphapetisch einf�gen
+                       uItem = pFirst[0];
+                       if(!uItem) {                                            
                                // Gibt es keine Kindeintr�ge
+                               pFirst[0] = uPos;
+                               pLast [0] = uPos;
+                               break;
+                       }
+
+                       if(pNew->bCallback & TVIF_TEXT) {                       
                // Text �ber Callback holen
+                               uSize = 1;
+                               LOCK(pData);
+                               CallbackEntry(pData, pNew, uPos, TVIF_TEXT, 
&iNone, &uSize, &pText);
+                               UNLOCK(pData);
+                       } else {
+                               pText = pNew->pText;
+                       }
+
+                       pData->cLockChanges = 1;
+
+                       uNext   = uItem;
+                       iCount  = 0;
+                       uBefore = 0;
+
+                       while(uNext) {                                          
                        // Z�hle die Eintr�ge
+                               iCount++;
+                               uNext = pItems[uNext]->uNextItem;
+                       }
+
+                       while(iCount > 0) {                                     
                                                // Binary-Seach Algorithnus
+                               iShift = iCount / 2;
+                               uNext  = uItem;
+
+                               while(iShift > 0) {
+                                       uNext  = pItems[uNext]->uNextItem;
+                                       iShift--;
+                               }
+
+
+                               pEntry  = pItems[uNext];
+                               if(pEntry->bCallback & TVIF_TEXT) {             
                // Text �ber Callback holen
+                                       uSize = 0;
+                                       LOCK(pData);
+                                       CallbackEntry(pData, pEntry, uItem, 
TVIF_TEXT, &iNone, &uSize, &pTextTemp);
+                                       UNLOCK(pData);
+                               } else {
+                                       pTextTemp = pEntry->pText;
+                               }
+
+                               iCmp = str_icmp(pText, pTextTemp);
+
+                               if(iCmp < 0) {
+                                       iCount -= (iCount + 1) / 2;
+                                       continue;
+                               }
+
+                               if(iCmp > 0) {
+                                       iCount -= iCount / 2 + 1;
+                                       uBefore = uNext;
+                                       uItem   = pItems[uNext]->uNextItem;
+                                       continue;
+                               }
+
+                               uBefore = pEntry->uPrevItem;
+                               uItem   = uNext;
+                               break;
+                       }
+
+
+                       pData->cLockChanges = 0;
+
+                       pNew->uNextItem = uItem;
+                       pNew->uPrevItem = uBefore;
+
+                       if(uBefore) {                                           
                                // Vorherigen Eintrag anpassen
+                               pEntry = pItems[uBefore];
+                               pEntry->uNextItem = uPos;
+                       } else {                                                
                                        // Am Anfang einf�gen
+                               pFirst[0] = uPos;
+                       }
+
+                       if(uItem) {                                             
                                // N�chsten Eintrag anpassen
+                               pEntry = pItems[uItem];
+                               pEntry->uPrevItem = uPos;
+                       } else {                                                
                                        // Am Ende anh�ngen
+                               pLast[0] = uPos;
+                       }
+                       break;
+
+               case U(TVI_AFTER):                                              
                                // Nach einem Eintrag einf�gen
+                       uAfter  = uParent;
+
+                       if(pParent) {                                           
                                // Einen Root-Eintrag einf�gen
+                               pParent ->bFlags  = bFlag;
+                               uParent = pParent->uParent;
+                               pParent = pItems  [uParent];
+
+                               if(!pParent) {
+                                       pNew->uParent   = 0;
+                                       pNew->uLevel    = 0;
+                                       uParent                 = 0;
+                                       uFirst                  = 0xFFFFFFFF;
+                                       pFirst                  = 
&pData->uFirstChild;
+                                       pLast                   = 
&pData->uLastChild;
+                               } else {                                        
                                        // Einen Tree-Eintrag einf�gen
+                                       pNew->uParent   =  uParent;
+                                       pNew->uLevel    =  pParent->uLevel + 1;
+                                       uFirst                  =  
pParent->uFirstChild;
+                                       pFirst                  = 
&pParent->uFirstChild;
+                                       pLast                   = 
&pParent->uLastChild;
+
+                                       if(pParent->bFlags & TVIX_VARBUTTON) {
+                                               pParent->bFlags |= 
TVIX_HASBUTTON;
+                                       }
+                               }
+                       }
+
+               default
+                               :                                               
                                                // Hinter einen Eintrag einf�gen
+DoInsert:
+                       uItem = pFirst[0];
+                       if(!uItem) {                                            
                                // Gibt es keine Kindeintr�ge
+                               pFirst[0] = uPos;
+                               pLast [0] = uPos;
+                               break;
+                       }
+
+                       if(uAfter > pData->uTreeItemsMax) {
+                               if((uAfter & 0xFFF00000) == 0xFFE00000) {       
                // In einer genauen Reihe nach Patent einf�gen
+                                       uAfter &= 0xFFFFF;
+
+                                       uItem = pFirst[0];
+                                       if(!uItem) {                            
                                // Gibt es keine Kindeintr�ge
+                                               pFirst[0] = uPos;
+                                               pLast [0] = uPos;
+                                               break;
+                                       }
+
+                                       if(uAfter == 0) {                       
                                // In die erste Reihe einf�gen
+                                               pEntry = pItems[uItem];
+                                               pEntry->uPrevItem = uPos;
+                                               pNew  ->uNextItem = uItem;
+                                               pFirst[0]                 = 
uPos;
+                                               break;
+                                       }
+
+                                       uNum    = 1;
+                                       uBefore = 0;
+                                       // Suche Einf�gereihe
+                                       for(; uItem; uItem = 
pItems[uItem]->uNextItem) {
+                                               uBefore = uItem;
+
+                                               if(uNum == uAfter) {
+                                                       uItem = 
pItems[uItem]->uNextItem;
+                                                       break;
+                                               }
+
+                                               uNum++;
+                                       }
+
+                                       pNew->uNextItem = uItem;
+                                       pNew->uPrevItem = uBefore;
+
+                                       if(uBefore) {                           
                                // Vorherigen Eintrag anpassen
+                                               pEntry = pItems[uBefore];
+                                               pEntry->uNextItem = uPos;
+                                       } else {                                
                                        // Am Anfang einf�gen
+                                               pFirst[0] = uPos;
+                                       }
+
+                                       if(uItem) {                             
                                // N�chsten Eintrag anpassen
+                                               pEntry = pItems[uItem];
+                                               pEntry->uPrevItem = uPos;
+                                       } else {                                
                                        // Am Ende anh�ngen
+                                               pLast[0] = uPos;
+                                       }
+
+                                       break;
+                               }
+
+                               pEntry  = NULL;
+                       } else {
+                               pEntry  = pItems[uAfter];
+                       }
+
+                       if(pEntry && uParent == pEntry->uParent) {              
        // Stimmt der Elterneintrag ?
+                               uItem   = pEntry->uNextItem;
+                               uBefore = uAfter;
+                       } else {
+                               uItem   = 0;
+                               uBefore = pLast[0];
+                               pEntry  = pItems[uBefore];
+                       }
+
+                       pNew->uNextItem = uItem;
+                       pNew->uPrevItem = uBefore;
+
+                       if(uBefore) {                                           
                                // Vorherigen Eintrag anpassen
+                               pEntry->uNextItem = uPos;
+                       } else {                                                
                                        // Am Anfang einf�gen
+                               pFirst[0] = uPos;
+                       }
+
+                       if(uItem) {                                             
                                // N�chsten Eintrag anpassen
+                               pEntry = pItems[uItem];
+                               pEntry->uPrevItem = uPos;
+                       } else {                                                
                                        // Am Ende anh�ngen
+                               pLast[0] = uPos;
+                       }
+
+                       break;
+       }
+
+       pItems[uPos] = pNew;
+       pData->uTreeItemsCount++;
+       // Die Anzeigezeilen akualisieren
+       if(!pParent || !uFirst || (pParent->uState & TVIS_EXPANDED)) {
+               uItem = pNew->uPrevItem;
+               if(!uItem)
+                       uItem = uParent;
+
+               if(!uItem)
+                       UpdateItems(pData, 0);
+               else {
+                       pEntry = pItems[uItem];
+                       if(pEntry && pEntry->uShowPos)
+                               UpdateItems(pData, uItem);
+               }
+       }
+
+       if(pNew->uState & TVIS_SELECTED) {                                      
                // Den ausgew�hlten Eintrag ausw�hlen
+               TreeListSelectItem(pData, uPos, 0, TVC_UNKNOWN);
+       }
+
+       return uPos;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListSetItem
+//*
+//*****************************************************************************
+//     �ndert einen Eintrag im Fenster
+//     pData           : Zeiger auf die Fensterdaten
+//     pItem           : Zeiger auf die ein zu �ndernden Daten
+//     Ergibt 1 wenn ok oder 0 bei einem Fehler
+static int TreeListSetItem(TreeListData *pData, const TV_ITEM *pItem) {
+
+       BYTE                    bCall;
+       BYTE                    bFlags;
+       ExtraItem         **pList;
+       ExtraItem          *pExtra;
+       BaseItem           *pEntry;
+       unsigned                uChange;
+       unsigned                uMask;
+       unsigned                uBits;
+       unsigned                uItem;
+       unsigned                uSub;
+       unsigned                uLen;
+       int                             iVal;
+       int                             iRet;
+
+       uChange = 0;
+
+       uItem = U(pItem->hItem);
+       if(uItem > pData->uTreeItemsMax)
+               return 0;
+
+       pEntry = pData->pTreeItems[uItem];
+       if(!pEntry)
+               return 0;
+
+       uBits = pItem->mask;
+
+       if(uBits & TVIF_SUBITEM) {                                              
                        // Einen Extraeintrag �ndern
+               uSub = pItem->cChildren;
+               if(uSub > 0) {
+                       if(uSub >= pData->uColumnCount)
+                               return 0;
+                       pList   = pData->pExtraItems[uSub - 1];
+                       pExtra  = pList[uItem];
+
+                       if(!pExtra) {                                           
                                // Einen neuen Eintrag erzeugen
+                               pExtra  = new(ExtraItem, 1);
+                               memset(pExtra, 0, sizeof(ExtraItem));
+                               pExtra->iImage = TV_NOIMAGE;
+                               pExtra->uState = pEntry->uState & (TVIS_BOLD | 
TVIS_UNDERLINE);
+                               pList[uItem]   = pExtra;
+                       }
+
+                       if(uBits & TVIF_PARAM) {
+                               pEntry->lParam  = pItem->lParam;
+                       }
+
+                       if((uBits & TVIF_IMAGE) && pExtra->iImage != 
pItem->iImage) {
+                               if(pData->hImages)
+                                       uChange = 1;
+                               pExtra->iImage = pItem->iImage;
+                               if(pExtra->iImage == I_IMAGECALLBACK)
+                                       pExtra->bCallback |= TVIF_IMAGE;
+                               else
+                                       pExtra->bCallback &= TVIF_IMAGE;
+                       }
+
+                       if(uBits & TVIF_TEXT) {                                 
                        // Einen neuen Text einstellen
+                               if(pItem->pszText == LPSTR_TEXTCALLBACK) {
+                                       if(pExtra->pText)
+                                               delete(pExtra->pText);
+                                       pExtra->bCallback |= TVIF_TEXT;
+                                       pExtra->uTextSize = 0;
+                                       pExtra->pText     = 0;
+                                       uChange                   = 1;
+                               } else {
+                                       uLen = str_len(pItem->pszText);
+
+                                       if(uLen > pExtra->uTextSize || 
!pExtra->pText) {
+                                               if(pExtra->pText)
+                                                       delete(pExtra->pText);
+                                               pExtra->pText = new(TCHAR, uLen 
+ 1);
+                                       }
+
+                                       memcpy(pExtra->pText, pItem->pszText, 
(uLen + 1)*sizeof(TCHAR));
+                                       pExtra->bCallback  &= ~TVIF_TEXT;
+                                       pExtra->uTextSize   = (WORD)uLen;
+                                       pExtra->iTextPixels = 0;
+                                       uChange = 1;
+                               }
+                       }
+
+                       if(uBits & TVIF_STATE) {                                
                        // Den Status �ndern
+                               uMask                   =  
pItem->stateMask&~TVIS_BASEFLAGS;
+                               uBits                   =  uMask & 
(pExtra->uState ^ pItem->state);
+                               uBits              |= (pItem->stateMask & 
TVIS_BASEFLAGS) & (pEntry->uState ^ pItem->state);
+                               pExtra->uState &= ~uMask;
+                               pExtra->uState |=  uMask & pItem->state;
+
+                               if((uBits & (TVIS_OVERLAYMASK | TVIS_CUT)) && 
(pData->hImages || pData->aColumn[uSub].bEdit >= TVAX_CHECK)) {
+                                       uChange = 1;                            
                                // Ein Icon hats sich ver�ndert
+                               }
+
+                               if(uBits & (TVIS_BOLD | TVIS_DROPHILITED)) {
+                                       pExtra->iTextPixels = 0;
+                                       uChange = 1;
+                               }
+
+                               if((uBits & TVIS_EXPANDED) && 
pEntry->uFirstChild) {
+                                       iVal = TreeListToggleItem(pData, uItem, 
0);
+                                       if(iVal < 0)
+                                               return 0;
+
+                                       pEntry = pData->pTreeItems[uItem];
+                                       if(!pEntry)
+                                               return 0;
+                               }
+
+                               if(uBits & TVIS_SELECTED) {                     
                        // Hat sich die Auswahl ge�ndert
+                                       iVal = (pData->uStyleEx & 
TVS_EX_SUBSELECT) ? uSub : 0;
+
+                                       if(pItem->state & TVIS_SELECTED) {
+                                               iRet = 
TreeListSelectItem(pData, uItem, iVal, TVC_UNKNOWN);
+                                       } else
+                                               if(pData->uStyleEx & 
TVS_EX_MULTISELECT) {
+                                                       
TreeListSelectItem(pData, 0  , 0, TVC_UNKNOWN);
+                                                       iRet = 
TreeListXorSelectItem(pData, uItem, TVC_UNKNOWN);
+                                               } else {
+                                                       iRet = 
TreeListSelectItem(pData, 0, 0, TVC_UNKNOWN);
+                                               }
+
+                                       pEntry = pData->pTreeItems[uItem];
+                                       if(!pEntry)
+                                               return 0;
+
+                                       if(iRet >= 2) {
+                                               pList   = 
pData->pExtraItems[uSub - 1];
+                                               pExtra  = pList[uItem];
+                                               if(!pExtra)
+                                                       return 0;
+                                       } else
+                                               if(iRet == 1) {
+                                                       uChange = 1;
+                                               }
+                               }
+                       }
+
+                       if(!uChange || !pEntry->uShowPos)
+                               return 1;               // Neuzeichnen des 
Eintrages
+
+                       UpdateRect(pData, uItem, uSub);
+
+                       return 1;
+               }
+
+               uBits &= ~TVIF_CHILDREN;
+       }
+
+       //******************** Einen Basis Eintrag �ndern 
*****************************
+       if(uBits & TVIF_PARAM) {
+               pEntry->lParam  = pItem->lParam;
+       }
+
+       if((uBits & TVIF_IMAGE) && pEntry->iImage != pItem->iImage) {
+               pEntry->iImage = pItem->iImage;
+               if(!(pEntry->uState & TVIS_SELECTED) && pData->hImages)
+                       uChange = 1;
+               if(pEntry->iImage == I_IMAGECALLBACK)
+                       pEntry->bCallback |= TVIF_IMAGE;
+               else
+                       pEntry->bCallback &= TVIF_IMAGE;
+       }
+
+       if((uBits & TVIF_SELECTEDIMAGE) && pEntry->iSelectedImage != 
pItem->iSelectedImage) {
+               pEntry->iSelectedImage = pItem->iSelectedImage;
+               if((pEntry->uState & TVIS_SELECTED) && pData->hImages)
+                       uChange = 1;
+               if(pEntry->iSelectedImage == I_IMAGECALLBACK)
+                       pEntry->bCallback |= TVIF_SELECTEDIMAGE;
+               else
+                       pEntry->bCallback &= TVIF_SELECTEDIMAGE;
+       }
+
+       if(uBits & TVIF_CHILDREN) {
+               bCall  = pEntry->bCallback;
+               bFlags = pEntry->bFlags;
+
+               switch(pItem->cChildren) {
+                       case  0:
+                               pEntry->bCallback &= ~TVIF_CHILDREN;
+                               pEntry->bFlags    &= ~TVIX_HASBUTTON;
+                               pEntry->bFlags    |=  TVIX_VARBUTTON;
+                               break;
+
+                       case  1:
+                               pEntry->bCallback &= ~TVIF_CHILDREN;
+                               pEntry->bFlags    &=  TVIX_VARBUTTON;
+                               pEntry->bFlags    |=  TVIX_HASBUTTON;
+                               break;
+
+                       case  I_CCB:
+                               pEntry->bCallback |=  TVIF_CHILDREN;
+                               pEntry->bFlags    &= ~TVIX_VARBUTTON;
+                               break;
+
+                       default
+                                       :
+                               pEntry->bCallback &= ~TVIF_CHILDREN;
+                               pEntry->bFlags    |=  TVIX_VARBUTTON;
+
+                               if(pEntry->uFirstChild)
+                                       pEntry->bFlags |= TVIX_HASBUTTON;
+                               else
+                                       pEntry->bFlags &= ~TVIX_HASBUTTON;
+               }
+
+               if(bCall != pEntry->bCallback || bFlags != pEntry->bFlags) {
+                       uChange = 1;
+               }
+       }
+
+       if(uBits & TVIF_TEXT) {                                                 
                        // Einen neuen Text einstellen
+               if(pItem->pszText == LPSTR_TEXTCALLBACK) {
+                       if(pEntry->pText)
+                               delete(pEntry->pText);
+                       pEntry->bCallback |= TVIF_TEXT;
+                       pEntry->uTextSize = 0;
+                       pEntry->pText     = 0;
+                       uChange                   = 1;
+               } else {
+                       uLen = str_len(pItem->pszText);
+
+                       if(uLen > pEntry->uTextSize) {
+                               if(pEntry->pText)
+                                       delete(pEntry->pText);
+                               pEntry->pText = new(TCHAR, uLen + 1);
+                       }
+
+                       memcpy(pEntry->pText, pItem->pszText, (uLen + 
1)*sizeof(TCHAR));
+                       pEntry->bCallback  &= ~TVIF_TEXT;
+                       pEntry->uTextSize   = (WORD)uLen;
+                       pEntry->iTextPixels = 0;
+                       uChange = 1;
+               }
+       }
+
+       if(uBits & TVIF_STATE) {
+               uMask = pItem->stateMask;
+
+               if(pData->uStyle & TVS_SINGLEEXPAND) {                          
        // Nicht aufklappen bei Einzelmodus
+                       uMask &= ~TVIS_EXPANDED;
+               }
+
+               uBits                   =  uMask & (pEntry->uState ^ 
pItem->state);
+               pEntry->uState &= ~uMask;
+               pEntry->uState |=  uMask & pItem->state;
+
+
+               if((uBits & (TVIS_OVERLAYMASK | TVIS_CUT)) && pData->hImages) {
+                       uChange = 1;
+               }
+
+               if(uBits & TVIS_STATEIMAGEMASK) {                               
                // Haben sich die State-Bits ver�ndert
+                       if(pData->hStates) {
+                               uChange = 1;
+                       }
+
+                       if(pData->uStyleEx & TVS_EX_BITCHECKBOX) {
+                               if(pEntry->uState & 0x1000) {
+                                       pData->uSingleSel = uItem;
+                               } else
+                                       if(pData->uSingleSel == uItem) {
+                                               pData->uSingleSel = 0;
+                                       }
+                       } else {
+                               if((pEntry->uState & TVIS_STATEIMAGEMASK) == 
0x2000) {
+                                       pData->uSingleSel = uItem;
+                               } else
+                                       if(pData->uSingleSel == uItem) {
+                                               pData->uSingleSel = 0;
+                                       }
+                       }
+               }
+
+               if(uBits & (TVIS_BOLD | TVIS_DROPHILITED)) {
+                       pEntry->iTextPixels = 0;
+                       uChange = 1;
+               }
+
+               if(uBits & TVIS_SELECTED) {                                     
                        // Hat sich die Auswahl ge�ndert
+                       pEntry->uState ^= TVIS_SELECTED;
+
+                       if(pItem->state & TVIS_SELECTED) {
+                               iRet = TreeListSelectItem(pData, uItem, 0, 
TVC_UNKNOWN);
+                       } else
+                               if(pData->uStyleEx & TVS_EX_MULTISELECT) {
+                                       TreeListSelectItem(pData, 0  , 0, 
TVC_UNKNOWN);
+                                       iRet = TreeListXorSelectItem(pData, 
uItem, TVC_UNKNOWN);
+                               } else {
+                                       iRet = TreeListSelectItem(pData, 0, 0, 
TVC_UNKNOWN);
+                               }
+
+                       pEntry = pData->pTreeItems[uItem];
+                       if(!pEntry)
+                               return 0;
+
+                       if(iRet == 1) {
+                               uChange = 1;
+                       }
+               }
+
+               if((uBits & TVIS_EXPANDED) && pEntry->uFirstChild) {    // 
Sollen Teile auf/zugeklappt werden
+                       uMask              &= TVIS_EXPANDPARTIAL | 
TVIS_EXPANDPARTIAL;
+                       pEntry->uState ^= TVIS_EXPANDED;
+                       pEntry->uState ^= uBits & uMask;
+                       iVal                    = uMask & pItem->state;
+
+                       iRet = TreeListToggleItem(pData, uItem, iVal);
+                       if(iRet) {                                              
                                // Abbruch oder Fehler beim Auf/Zuklappen
+                               if(uChange && pEntry->uShowPos) {               
                // Neuzeichnen des Eintrages
+                                       UpdateRect(pData, uItem, 0);
+                               }
+
+                               return 0;
+                       }
+
+                       pEntry->uState &= ~uMask;
+                       pEntry->uState |=  iVal;
+               }
+       }
+
+       if(uChange && pEntry->uShowPos) {                                       
                // Neuzeichnen des Eintrages
+               UpdateRect(pData, uItem, 0);
+       }
+       return 1;
+}
+
+
+//*****************************************************************************
+//*
+//*            TreeListGetItem
+//*
+//*****************************************************************************
+//     Daten vone einem Eintrag abfragen
... 9270 lines suppressed ...

Reply via email to