[REACTOS] Add a TreeList control (TreeView with columns).
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 28 Jan 2018 21:10:51 +0000 (22:10 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 5 Nov 2018 23:09:14 +0000 (00:09 +0100)
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
base/setup/reactos/treelist.c [new file with mode: 0644]
base/setup/reactos/treelist.h [new file with mode: 0644]

index 39225e7..8c58f9e 100644 (file)
@@ -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 (file)
index 0000000..1681b61
--- /dev/null
@@ -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 (az_software@inode.at) 2007
+ *              Copyright (C) Sébastien Kirche (sebastien.kirche@free.fr) 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 (az_software@inode.at) 2007
+//     Copyright (C) Sébastien Kirche (sebastien.kirche@free.fr) 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
+//     pData           : Zeiger auf die Fensterdaten
+//     pItem           : Zeiger auf die den Datenspeicher
+//     Ergibt 1 wenn ok oder 0 bei einem Fehler
+static unsigned TreeListGetItem(TreeListData *pData, TV_ITEM *pItem) {
+
+       ExtraItem         **pList;
+       ExtraItem          *pExtra;
+       BaseItem           *pEntry;
+       unsigned                uBits;
+       unsigned                uItem;
+       unsigned                uSub;
+       unsigned                uLen;
+
+       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 abfragen
+               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) {
+                               pItem->lParam = pEntry->lParam;
+                       }
+
+                       if(uBits & TVIF_IMAGE) {
+                               pItem->iImage = pExtra->iImage;
+                       }
+
+                       if(uBits & TVIF_TEXT) {                                                         // Einen neuen Text einstellen
+                               if(pExtra->pText == LPSTR_TEXTCALLBACK) {
+                                       pItem->pszText = LPSTR_TEXTCALLBACK;
+                               } else
+                                       if(uBits & TVIF_TEXTPTR) {
+                                               if(!pExtra->pText) {
+                                                       pItem->pszText    = _T("");
+                                                       pItem->cchTextMax = 0;
+                                               } else {
+                                                       pItem->pszText    = pExtra->pText;
+                                                       pItem->cchTextMax = pExtra->uTextSize + 1;
+                                               }
+                                       } else {
+                                               if(pExtra->pText) {
+                                                       uLen = pExtra->uTextSize + 1;
+                                                       if(pItem->cchTextMax < (int)uLen) {
+                                                               if(pItem->cchTextMax <= 0) {
+                                                                       uLen = 0;
+                                                               } else {
+                                                                       uLen = pItem->cchTextMax - 1;
+                                                                       pItem->pszText[uLen] = 0;
+                                                               }
+                                                       }
+
+                                                       memcpy(pItem->pszText, pExtra->pText, uLen * sizeof(TCHAR));
+                                               } else {
+                                                       if(pItem->cchTextMax > 0) {
+                                                               pItem->pszText[0] = 0;
+                                                       }
+                                               }
+                                       }
+                       }
+
+                       if(uBits & TVIF_STATE) {
+                               pItem->state  = pExtra->uState&~TVIS_BASEFLAGS;
+                               pItem->state &= pItem->stateMask;
+                       }
+
+                       return 1;
+               }
+
+               if(pEntry->bCallback & TVIF_CHILDREN)
+                       pItem->cChildren = I_CHILDRENCALLBACK;
+               else
+                       pItem->cChildren = (pEntry->uFirstChild) ? 1 : 0;
+
+               uBits &= ~TVIF_CHILDREN;
+       }
+
+
+       //******************** Einen Basis Eintrag ändern *****************************
+       if(uBits & TVIF_PARAM) {
+               pItem->lParam = pEntry->lParam;
+       }
+
+       if(uBits & TVIF_IMAGE) {
+               pItem->iImage = pEntry->iImage;
+       }
+
+       if(uBits & TVIF_SELECTEDIMAGE) {
+               pItem->iSelectedImage = pEntry->iSelectedImage;
+       }
+
+       if(uBits & TVIF_CHILDREN) {
+               if(pEntry->bCallback & TVIF_CHILDREN)
+                       pItem->cChildren = I_CHILDRENCALLBACK;
+               else
+                       pItem->cChildren = (pEntry->uFirstChild) ? 1 : 0;
+       }
+
+       if(uBits & TVIF_TEXT) {                                                                         // Einen neuen Text einstellen
+               if(pEntry->pText == LPSTR_TEXTCALLBACK) {
+                       pItem->pszText = LPSTR_TEXTCALLBACK;
+               } else
+                       if(uBits & TVIF_TEXTPTR) {
+                               pItem->pszText    = pEntry->pText;
+                               pItem->cchTextMax = pEntry->uTextSize + 1;
+                       } else {
+                               uLen = pEntry->uTextSize + 1;
+                               if(pItem->cchTextMax < (int)uLen) {
+                                       if(pItem->cchTextMax <= 0) {
+                                               uLen = 0;
+                                       } else {
+                                               uLen = pItem->cchTextMax - 1;
+                                               pItem->pszText[uLen] = 0;
+                                       }
+                               }
+
+                               memcpy(pItem->pszText, pEntry->pText, uLen * sizeof(TCHAR));
+                       }
+       }
+
+       if(uBits & TVIF_STATE) {
+               pItem->state  = pEntry->uState;
+               pItem->state &= pItem->stateMask;
+       }
+
+       return 1;
+}
+
+//*****************************************************************************
+//*
+//*            TreeListDeleteColumn
+//*
+//*****************************************************************************
+//     Löscht eine Spalte aus dem Header
+//     pData           : Zeiger auf die Fensterdaten
+//     uCol            : Ist die Nummer der Spalte die gelöscht werden soll
+//     Ergibt 1 wenn die Spalte gelöscht wurde
+static int TreeListDeleteColumn(TreeListData *pData, unsigned uCol) {
+
+       ExtraItem **pList;
+       ExtraItem  *pExtra;
+       RECT            sRect;
+       BYTE            bItem;
+       BYTE            bByte;
+       unsigned        uPos;
+       unsigned        uSub;
+       unsigned        uItem;
+       unsigned        uIndex;
+       int                     iDelta;
+       int                     iXoff;
+       int                     iNum;
+       int                     iCnt;
+       int                     iVar;
+       int                     iSub;
+       int                     iAll;
+       int                     iFix;
+
+       if(uCol >= pData->uColumnCount)
+               return 0;
+
+       if(uCol && uCol == pData->uSelectedSub) {                                       // Ist die Auswahl in der Spalte
+               TreeListSelectItem(pData, pData->uSelectedItem, 0, TVC_UNKNOWN);
+       }
+
+       if(uCol && uCol == pData->uEditSub) {
+               pData->uEditSub  = 0;
+               pData->uEditItem = 0;
+               TreeListEndLabelEdit(pData, 0);
+       }
+
+       if(uCol && uCol == pData->uFocusSub) {
+               pData->uFocusSub  = 0;
+               pData->uFocusItem = 0;
+       }
+
+       if(uCol == pData->uTrackedSub) {
+               pData->uTrackedSub  = 0;
+               pData->uTrackedItem = 0;
+       }
+
+       GetClientRect(pData->hWnd, &sRect);
+
+       iDelta  = pData->aColumn[uCol].sSize;
+       iSub    = pData->aColumn[uCol].bWeight;
+       iCnt    = 0;
+       iVar    = 0;
+       iFix    = 0;
+       iAll    = 0;
+
+       for(uPos = 0; uPos < pData->uColumnCount; uPos++) {                             // Zählern der variablen Spalten
+               if(uPos == uCol)
+                       continue;
+               if(pData->aColumn[uPos].bWeight == 0) {
+                       iFix += pData->aColumn[uPos].sSize;
+                       continue;
+               }
+
+               iVar += pData->aColumn[uPos].sSize;
+               iAll += pData->aColumn[uPos].bWeight;
+               iCnt += 1;
+       }
+
+       Header_DeleteItem(pData->hHeader, uCol);
+       pData->uColumnCount--;
+
+       if(pData->uColumnCount > 0) {                                                           // Liste mit Extraeinträgen löschen
+               iNum = uCol - 1;
+               if(iNum < 0)
+                       iNum = 0;
+
+               pList = pData->pExtraItems[iNum];
+               if(pList) {
+                       for(uItem = 0; uItem <= pData->uTreeItemsMax; uItem++) { // Alle Einträge aus der Liste löschen
+                               pExtra = pList[uItem];
+                               if(!pExtra)
+                                       continue;
+
+                               if(pExtra->pText) {
+                                       pExtra->uTextSize = 0;
+                                       delete(pExtra->pText);
+                               }
+
+                               delete(pExtra);
+                       }
+
+                       memmove(pData->pExtraItems + iNum, pData->pExtraItems + iNum + 1, sizeof(pList) * (MAX_COLUMNS - 1 - iNum));
+                       pData->pExtraItems[pData->uColumnCount] = NULL;
+                       delete(pList);
+               }
+       } else {
+               iNum = MAX_COLUMNS;
+       }
+
+       if(pData->aColumn[uCol].bWeight) {
+               pData->uColumnCountVar--;
+       }
+
+       if(pData->aColumn[uCol].bMark) {
+               pData->uMarkedCols--;
+       }
+
+       uSub = pData->aColumnPos[uCol];
+
+       memmove(pData->aColumn + uCol, pData->aColumn + uCol + 1, (MAX_COLUMNS - 1 - uCol)*sizeof(ColumnData));
+
+       for(uIndex = 0; uIndex < uSub; uIndex++) {                                              // Zuordnungs-Array anpassen
+               bItem = pData->aColumnPos[uIndex - 1];
+               if(bItem < uCol)
+                       continue;
+
+               bItem++;
+               pData->aColumnPos[uIndex] = bItem;
+       }
+
+       for(; uIndex <= pData->uColumnCount; uIndex++) {                                // Spaltenpositionen verschieben
+               bItem = pData->aColumnPos[uIndex + 1];
+
+               if(bItem >= uCol) {
+                       uCol--;
+               }
+
+               pData->aColumnPos[uIndex] = bItem;
+       }
+
+       for(uIndex = pData->uColumnCount; uIndex > 0;) {
+               uIndex--;
+               bByte = pData->aColumn[uIndex].bIndex;
+
+               if(bByte >= uSub) {
+                       bByte--;
+                       pData->aColumn[uIndex].bIndex = bByte;
+               }
+
+               pData->aColumn[uIndex].bNext = pData->aColumnPos[bByte + 1];
+       }
+
+       pData->iFixSize   = iFix;
+       pData->iAllWeight = iAll;
+       pData->aColumn[pData->uColumnCount].bWeight = 0;
+
+       if(iCnt && iDelta) {                                                                            // Variable Breiten anpassen
+               ChangeColSize(pData, iDelta);
+       } else {
+               if(iSub && !iCnt) {
+                       pData->iVarSize = 0;
+               }
+       }
+
+       if(pData->uSelectedSub > uCol) {                                                        // Ist die Auswahl vor der Spalte
+               pData->uSelectedSub--;
+       }
+
+       if(pData->uEditSub > uCol) {
+               pData->uEditSub--;
+       }
+
+       if(pData->uFocusSub > uCol) {
+               pData->uFocusSub--;
+       }
+
+       if(pData->uTrackedSub > uCol) {
+               pData->uTrackedSub--;
+       }
+
+       if(!pData->uColumnCount) {                                                              // Den Header löschen
+               DestroyWindow(pData->hHeader);
+               pData->hHeader     = NULL;
+               pData->uStartPixel = 0;
+               pData->iRowHeight  = 1;
+               UpdateHeight(pData);
+               InvalidateRect(pData->hWnd, &sRect, FALSE);
+       }
+
+       iXoff = UpdateColumns(pData);                                                   // Hat sich die Spaltenbreiten verändert
+       if(iXoff < 0x10000) {
+               sRect.left  = iXoff;
+               sRect.left -= pData->uScrollX;
+               sRect.top   = pData->uStartPixel;
+               InvalidateRect(pData->hWnd, &sRect, FALSE);
+       }
+
+       UpdateScrollX(pData);
+
+       return 1;
+}
+
+
+//*****************************************************************************
+//*
+//*            TreeListInsertColumn
+//*
+//*****************************************************************************
+//     Adds a new column in the header
+//     pData           : Zeiger auf die Fensterdaten
+//     uCol            : Ist die Nummer der Spalte die eingefügt wird
+//     pInsert         : Zeiger auf die ein zu fügenden Daten
+//     Returns the positio of the new column or -1 if an error occurs.
+static int TreeListInsertColumn(TreeListData *pData, unsigned uCol, TV_COLUMN *pColumn) {
+
+       ExtraItem **pList;
+       TV_COLSIZE      sNotify;
+       HDITEM          sItem;
+       RECT            sRect;
+       short           sFixed;
+       UINT            uIndex;
+       BYTE            bByte;
+       BYTE            bItem;
+       BYTE            bMark;
+       BYTE            bMinEx;
+       BYTE            bAlign;
+       int                     iWeight;
+       int                     iDelta;
+       int                     iStart;
+       int                     iSize;
+       int                     iXoff;
+       int                     iYoff;
+       int                     iNum;
+       int                     iVar;
+       int                     iAll;
+       int                     iAdd;
+       int                     iMin;
+       int                     iFix;
+
+       GetClientRect(pData->hWnd, &sRect);
+
+       if(!pData->hHeader) {                                                                           // Create a new header
+               iStart = bDrawWithTheme ? GetSystemMetrics(SM_CYHSCROLL) : 17; //SM_CYHSCROLL is not enough tall with themes disabled apps;
+               iYoff  = sRect.top + iStart;
+
+               if(pData->uStyleEx & TVS_EX_HIDEHEADERS) {
+                       iYoff = 0;
+               }
+
+               pData->hHeader = CreateWindow(WC_HEADER, NULL, WS_VISIBLE | WS_CHILD | HDS_HORZ | HDS_BUTTONS | HDS_DRAGDROP, sRect.left, sRect.top, sRect.right, iYoff, pData->hWnd, (HMENU)1, NULL, NULL);
+               if(!pData->hHeader)
+                       return -1;
+
+               pData->uStartPixel = (pData->uStyleEx & TVS_EX_HIDEHEADERS) ? 0 : iStart;
+               pData->iRowHeight  = 1;
+               UpdateHeight(pData);
+
+               InvalidateRect(pData->hWnd, &sRect, FALSE);
+               if(pData->uStyleEx & TVS_EX_HEADEROWNIMGLIST){
+                       SendMessage(pData->hHeader, HDM_SETIMAGELIST, 0, (LPARAM)pData->hHeadImg);
+               } else {
+                       SendMessage(pData->hHeader, HDM_SETIMAGELIST, 0, (LPARAM)pData->hImages);
+               }
+               SendMessage(pData->hHeader, WM_SETFONT, (WPARAM)hDefaultFontN, 0);
+
+               if(pData->uSizeX <= pData->uStartPixel)
+                       pData->uSizeYsub = 0;
+               else
+                       pData->uSizeYsub = pData->uSizeX - pData->uStartPixel;
+       }
+
+       if(pData->uColumnCount >= MAX_COLUMNS) {                                        // Prüfe die Anzahl der Spalten
+               return -1;
+       }
+
+       memset(&sItem, 0, sizeof(sItem));                                                       // Die Spaltendaten zusammenstellen
+
+       if(uCol >= pData->uColumnCount) {
+               uCol = pData->uColumnCount;
+       }
+
+       if(pColumn->mask & TVCF_FMT) {                                                          // text alignment
+               sItem.mask    |= HDI_FORMAT;
+               sItem.fmt      = pColumn->fmt;
+
+               switch(sItem.fmt & HDF_JUSTIFYMASK) {
+                       case HDF_CENTER:
+                               bAlign = DT_CENTER;
+                               break;
+                       case HDF_RIGHT:
+                               bAlign = DT_RIGHT;
+                               break;
+                       default:
+                               bAlign = DT_LEFT;
+                               break;
+               }
+       } else {
+               bAlign = DT_LEFT;
+       }
+
+       if(pColumn->mask & TVCF_IMAGE) {                                                        // Hat die Spalte auch ein Icon
+               sItem.mask    |=  HDI_IMAGE;
+               sItem.iImage   =  pColumn->iImage;
+       }
+
+       if(pColumn->mask & TVCF_TEXT) {                                                         // Auch einen Text übergeben
+               sItem.mask    |=  HDI_TEXT;
+               sItem.pszText  =  pColumn->pszText;
+       }
+
+       if(pColumn->mask & TVCF_MIN) {                                                          // Auch einen Min-Wert übergeben
+               iMin               =  pColumn->iOrder;
+               bMinEx             =  1;
+
+               if(iMin < 0) {
+                       iMin       = -iMin;
+                       bMinEx     =  0;
+               }
+       } else {
+               iMin               =  16;
+               bMinEx             =  0;
+       }
+
+       if(pColumn->mask & TVCF_WIDTH) {                                                        // Fixe Breite für die Spalte
+               iWeight            =  0;
+               sItem.mask    |=  HDI_WIDTH;
+               sItem.cxy          =  pColumn->cx;
+               iSize              =  pColumn->cx;
+               iDelta             = -pColumn->cx;
+               iAdd               =  0;
+       } else {                                                                                                        // Variable vordefinierte Breite
+               if(pColumn->mask & TVCF_VWIDTH)
+                       iWeight =  pColumn->cx;
+               else
+                       iWeight =  1;
+
+               iVar  = pData->iVarSize;
+               iFix  = pData->iFixSize;
+               iAll  = pData->iAllWeight;
+               iSize = pData->uSizeX - iVar - iFix;
+
+               if(iWeight <= 0)
+                       iWeight = 1;
+               if(iWeight > 255)
+                       iWeight = 255;
+
+               if(pData->uColumnCountVar) {                                                    // Gibt es schon variable Spalten
+                       iSize  = (iVar * iWeight) / (iAll + iWeight);
+                       iDelta = -iSize;
+               } else {
+                       iDelta = 0;
+               }
+
+               sItem.mask    |= HDI_WIDTH;
+               sItem.cxy      = iSize;
+               iAdd               = 1;
+
+               if(sItem.cxy < iMin)
+                       sItem.cxy = iMin;
+       }
+
+       uCol = Header_InsertItem(pData->hHeader, uCol, &sItem);
+       if(uCol & 0x80000000)
+               return -1;
+
+       if(pData->uColumnCount > 0) {                                                           // Liste mit Extraeinträgen erzeugen
+               pList = new(ExtraItem*, pData->uTreeItemsMax + 1);
+               if(!pList) {
+                       Header_DeleteItem(pData->hHeader, uCol);
+                       return -1;
+               }
+
+               memset(pList, 0, sizeof(ExtraItem *) * (pData->uTreeItemsMax + 1));
+
+               iNum = uCol - 1;
+               if(iNum < 0)
+                       iNum = 0;
+
+               memmove(pData->pExtraItems + iNum + 1, pData->pExtraItems + iNum, sizeof(pList) * (MAX_COLUMNS - 2 - iNum));
+               pData->pExtraItems[iNum] = pList;
+       }
+
+       memmove(pData->aColumn + uCol + 1, pData->aColumn + uCol, (MAX_COLUMNS - 1 - uCol)*sizeof(ColumnData));
+
+       for(uIndex = pData->uColumnCount + 2; uIndex > uCol; uIndex--) {        // Zuordnungs-Array anpassen
+               bItem = pData->aColumnPos[uIndex - 1];
+               if(bItem >= uCol)
+                       bItem++;
+
+               pData->aColumnPos[uIndex] = bItem;
+       }
+
+       pData->aColumnPos[uCol] = (BYTE)uCol;
+
+       while(uIndex > 0) {
+               uIndex--;
+
+               bItem = pData->aColumnPos[uIndex];
+               if(bItem < uCol)
+                       continue;
+
+               bItem++;
+               pData->aColumnPos[uIndex] = bItem;
+       }
+
+       for(uIndex = pData->uColumnCount;;) {                                           // Folgende Spalten verschieben
+               bByte = pData->aColumn[uIndex].bIndex;
+
+               if(bByte >= uCol) {
+                       bByte++;
+                       pData->aColumn[uIndex].bIndex = bByte;
+               }
+
+               if(uIndex == 0)
+                       break;
+               uIndex--;
+       }
+
+       bMark  = 0;
+       sFixed = 0;
+
+       if(pColumn->mask & TVCF_MARK)                                                   // Ist die Spalte markiert
+               if(pColumn->fmt & TVCFMT_MARK) {
+                       bMark = 1;
+               }
+
+       if(pColumn->mask & TVCF_FIXED)                                                  // Ist die Spalte fixiert
+               if(pColumn->fmt & TVCFMT_FIXED) {
+                       sFixed = (short)((sItem.cxy > 0) ? sItem.cxy : 100);
+               }
+
+       pData->aColumn[uCol].bWeight = (BYTE)iWeight;
+       pData->aColumn[uCol].sReal   = (short)sItem.cxy;
+       pData->aColumn[uCol].sSize   = (short)iSize;
+       pData->aColumn[uCol].sMin    = (short)iMin;
+       pData->aColumn[uCol].bIndex  = (BYTE)uCol;
+       pData->aColumn[uCol].bMinEx  =  bMinEx;
+       pData->aColumn[uCol].bAlign  =  bAlign;
+       pData->aColumn[uCol].bMark   =  bMark;
+       pData->aColumn[uCol].sFixed  =  sFixed;
+       pData->uMarkedCols                      +=      bMark;
+
+
+       for(uIndex = pData->uColumnCount;;) {                                           // Nächste sichtbare Spalten aktualisieren
+               bByte                                            = pData->aColumn[uIndex].bIndex;
+               pData->aColumn[uIndex].bNext = pData->aColumnPos[bByte + 1];
+               if(uIndex == 0)
+                       break;
+               uIndex--;
+       }
+
+       if(pData->uColumnCountVar) {                                                            // Variable Breiten anpassen
+               if(iDelta) {
+                       ChangeColSize(pData, iDelta);
+                       pData->iVarSize  -= iDelta;
+               } else
+                       if(!iAdd) {
+                               pData->iFixSize  += iSize;
+                       }
+       } else {
+               if(iAdd)
+                       pData->iVarSize  = iSize;
+               else
+                       pData->iFixSize += iSize;
+       }
+
+       pData->iAllWeight                       +=  iWeight;
+       pData->uColumnCountVar      +=  iAdd;
+       pData->uColumnCount             +=  1;
+
+       if(pData->uSelectedSub > 0 && pData->uSelectedSub >= uCol) {
+               pData->uSelectedSub++;
+       }
+
+       if(pData->uTrackedSub > 0 && pData->uTrackedSub >= uCol) {
+               pData->uTrackedSub++;
+       }
+
+       if(pData->uFocusSub > 0 && pData->uFocusSub >= uCol) {
+               pData->uFocusSub++;
+       }
+
+       if(pData->uEditSub > 0 && pData->uEditSub >= uCol) {
+               pData->uEditSub++;
+       }
+
+       iXoff = UpdateColumns(pData);                                                   // Hat sich die Spaltenbreiten verändert
+       if(iXoff < 0x10000) {
+               sRect.left  = iXoff;
+               sRect.left -= pData->uScrollX;
+               sRect.top   = pData->uStartPixel;
+               InvalidateRect(pData->hWnd, &sRect, FALSE);
+       }
+
+       UpdateScrollX(pData);
+
+       if(pData->uInsertMark) {                                                                        // Fehlende Infomarken einfügen
+               TV_ITEM         sSet;
+               ExtraItem  *pExtra;
+
+               sSet.mask               = TVIF_SUBITEM;
+               sSet.hItem              = (HTREEITEM)pData->uInsertMark;
+               sSet.cChildren  = uCol;
+
+               TreeListSetItem(pData, &sSet);
+
+               pExtra = pData->pExtraItems[uCol - 1][pData->uInsertMark];
+               if(pExtra) {
+                       pExtra->uColorBk  = pData->uColors[TVC_INSERT];
+                       pExtra->bFlags   |= TVIX_BKCOLOR;
+               }
+       }
+
+       if(pData->uStyleEx & TVS_EX_HEADERCHGNOTIFY) {                          // Geänderte Spalten melden
+               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;
+
+               UNLOCK(pData);
+&nb