Release 980927

Sun Sep 27 14:25:38 1998  Petter Reinholdtsen <pere@td.org.uit.no>

	* [files/drive.c]
	Make sure GetDriveType32A() handles param NULL.  Added some
	doc on function.

Sun Sep 27 14:07:26 1998  Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>

	* [controls/edit.c] [windows/win.c]
	Don't call SetWindowLong() in EDIT_WM_NCREATE.
	Fix SetWindowLong(GWL_[EX]STYLE) to work for 16bit windows. Remove
	UpdateWindow() call. 

Sun Sep 27 13:41:22 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [scheduler/*.c] [server/event.c] [server/mutex.c]
	  [server/semaphore.c]
	Implemented server-side synchronisation objects.

Sun Sep 27 01:13:35 1998  Alex Priem <alexp@sci.kun.nl>

	* [dlls/comctl32/treeview.c] [include/treeview.h] [include/comctl.h]
	Treeview implementation.

	* [dlls/comctl32/trackbar.c] [include/trackbar.h] 
	Trackbar implementation.

Sat Sep 26 20:49:13 1998  Ulrich Weigand <weigand@informatik.uni-erlangen.de>

	* [if1632/thunk.c] [tools/build.c] [win32/kernel32.c]
	Bugfix: several problems with flat thunks fixed.

	* [memory/selector.c]
	Bugfix: IsBad...Ptr16 didn't work for limit_in_pages segments.

	* [scheduler/thread.c]
	Bugfix: CreateThread: Allow id parameter == NULL.

	* [objects/gdiobj.c]
	Bugfix: IsGDIObject: Return correct object type for stock objects.

	* [msdos/dpmi.c]
	Bugfix: fixed typo in INT_DoRealModeInt.

	* [msdos/int21.c]
	Bugfix: int21 READ *must* use WIN16_hread, not _hread16.

	* [if1632/kernel.spec] [if1632/dummy.c] [if1632/thunk.c]
	  [loader/ne/module.c] [scheduler/event.c] [scheduler/synchro.c]
	  [scheduler/thread.c] [win32/kernel32.c] [win32/ordinals.c]
	Added names/stubs for all undocumented KERNEL routines (Win95).
	Added the following undoc. 16-bit equivalents to Win32 routines:
	KERNEL.441-443,449-453,456-462,471-476,479-486,488.
	Added stubs for some other KERNEL routines.

	* [memory/heap.c] [memory/global.c] [include/global.h]
	Implemented Local32... 32-bit local heap routines (KERNEL.208-215, 229).

	* [miscemu/instr.c] [loader/module.c] [include/module.h]
	Implemented __GP fault handling and HasGPHandler (KERNEL.338).

	* [misc/error.c]
	Implemented LogParamErrorRegs (KERNEL.327).

	* [loader/task.c] [include/windows.h]
	Implemented GetCodeInfo (KERNEL.104).

	* [loader/task.c] [scheduler/thread.c] [include/thread.h]
	Implemented [GS]etThreadQueue and [GS]etFastQueue (KERNEL.463/4, 624/5).

	* [if1632/gdi.spec] [objects/dc.c] [objects/dib.c]
	  [objects/bitmap.c] [include/windows.h]
	Bugfix: fixed wrong parameter for CreateDIBSection16.
	Added [GS]etDIBColorTable16, stub for GetBoundsRect16.
	Partially implemented BITMAP_GetObject16 for DIBs.

	* [if1632/gdi.spec] [relay32/gdi32.spec] [objects/palette.c]
	Added some GDI stubs.

	* [if1632/Makefile.in] [if1632/display.spec] [if1632/mouse.spec]
	  [if1632/keyboard.spec] [if1632/builtin.c] [windows/keyboard.c]
	Added some stubs for Win16 drivers: KEYBOARD, MOUSE, DISPLAY.

	* [if1632/wprocs.spec] [msdos/vxd.c]
	Added some stubs for VxDs: VMM, ConfigMG, TimerAPI.

	* [msdos/int2f.c]
	Added some stubs for real-mode network drivers.

Sat Sep 26 18:18:18 1998  Marcus Meissner <marcus@jet.franken.de>

	* [configure.in]
	Merged in some more of the FreeBSD ports/emulators/wine patches. 
	(Maintainer(s) of this port: You can just submit these
	patches to Alexandre directly.)

	 * [loader/pe_image.c]
	Check filesize of image against size derived from header
	to spot truncated executeables without crashing.

	* [files/directory.c]
	Set envvar "COMSPEC". One win32(!!) program crashes without it.

	* [multimedia/mmio.c]
	Added mmioSetInfo32.

	* [include/file.h]
	Return STD_ERROR_HANDLE for AUX and PRT dos handles.

	* [loader/module.c]
	Handle executeables with spaces in their names a bit better in
	CreateProcess.

	* [relay32/msvfw32.spec][if1632/msvideo.spec][multimedia/msvideo.c][include/vfw.h]
	Started on MS Video support (can load Win32 ICMs).

	* [tools/testrun]
	A bit smarter use of ps.

	* [memory/virtual.c]
	Report PAGE_GUARDed pages as PAGE_PROTECTED (AutoCAD LT R17 fails
	without that check (since Win95 doesn't know about PAGE_GUARD)).

Sat Sep 26 15:04:05 1998  Ove Kaaven <ovek@arcticnet.no>

	* [include/miscemu.h] [if1632/builtin.c] [loader/task.c]
	  [miscemu/instr.c] [msdos/dpmi.c] [msdos/int21.c]
	  [msdos/interrupts.c] [windows/user.c]
	INT_[S|G]etHandler was renamed to INT_[S|G]etPMHandler.
	Added handlers to deal with real-mode interrupts; DOS
	programs are now able to hook real-mode interrupts.

	* [loader/dos/module.c] [msdos/dosmem.c] [msdos/int21.c]
	Moved real-mode interrupt table initialization to
	msdos/dosmem.c, and made new V86 tasks get a full copy
	of the existing "system memory" instead of almost empty
	space. Misc fixes.

	* [include/dosexe.h] [loader/dos/module.c] [msdos/dpmi.c]
	  [msdos/int2f.c]
	First shot at letting DOS programs start up DPMI (but DPMI
	is still disabled for DOS programs, for pkunzip's sake).

	* [include/debugger.h] [debugger/break.c] [debugger/dbg.y]
	  [debugger/registers.c] [debugger/memory.c] [debugger/info.c]
	  [loader/dos/dosvm.c]
	First shot at making Wine's debugger work for DOS programs.
	The -debug flag works, as do "nexti" and "stepi".

Sat Sep 26 13:13:13 1998  Juergen Schmied <juergen.schmied@metronet.de>

	* [dlls/shell32/dataobject.c]
	New classes IEnumFORMATETC implemented, IDataObject stubs.
	
	* [dlls/shell32/*.*][relay32/shell32.spec]
	Bugfixes.
	New: ICM_InsertItem(), ILCreateFromPath().
	Implemented: ILCloneFirst().
	Stubs: ILIsEqual(), ILFindChild(), SHLogILFromFSIL(),
	  PathMatchSpec(), PathIsExe().
	Changed: ILGetSize(), _ILIsDesktop(), PathCombine().

	* [include/shlobj.h]
	New SHLGUID's
	New structures: DVTARGETDEVICE32, STGMEDIUM32, FORMATETC32,
	CLIPFORMAT32.
	New interfaces: IEnumFORMATETC, IDataObject, ICommDlgBrowser
	IDockingWindowFrame, IServiceProvider.

	* [dlls/shell32/folders.c]
	Stubs for IShellLink.

	* [loader/resource.c]
	Small fixes.

	* [misc/crtdll.c][relay32/crtdll.spec]
	New __dllonexit().

	* [windows/message.c]
	SendNotifyMessageA, SendMessageCallBack32A half implemented.

	* [controls/edit.c]
	EDIT_WM_SetText set EF_UPDATE flag not for ES_MULTILINE.

	* [files/file.c]
	Handling of fileposition fixed.

Fri Sep 25 18:13:30 1998  Patrik Stridvall <ps@leissner.se>

	* [include/windows.h] [include/wintypes.h]
	  [ole/ole2nls.h] [relay32/kernel32.spec]
	Implemented EnumDateFormats and EnumTimeFormats.
	Only adds US English support.

	* [Makefile.in] [configure.in] 
	  [dlls/Makefile.in] [dlls/psapi/Makefile.in] 
	  [dlls/psapi/psapi_main.c] 
	New files to implement stubs for PSAPI.DLL (NT only).

	* [relay32/Makefile.in] [relay32/builtin32.c] 
	  [relay32/psapi.spec]
	New spec file for PSAPI.DLL (NT only).

	* [scheduler/handle.c]
	HANDLE_GetObjPtr should only interpret the pseudo handles as the
	current thread or the current process if a thread or a process is
	requested.

	* [include/winversion.h] [misc/version.c]
	Adds the global function VERSION_GetVersion() so functions can
	have different behavior depending on the -winver flag.

	* [include/oledlg.h] [ole/oledlg.c]
	Minor fixes. 

	* [windows/winproc.c]
	Minor changes.

	* [include/imm.h] [misc/imm.c]
	Now returns correct values under both Windows 95 and NT 4.0.

Thu Sep 24 22:11:44 1998  Kristian Nielsen  <kristian.nielsen@risoe.dk>

	* [configure.in] [include/acconfig.h] [include/thread.h]
	  [scheduler/sysdeps.c]
	Autoconfig test for non-reentrant libc.

Wed Sep 23 19:52:12 1998  Matthew Becker <mbecker@glasscity.net>

	* [*/*.c]
	Miscellaneous documentation updates and debugging output 
	standardizations.

	* [objects/clipping.c]
	Added ExtSelectClipRgn.

Wed Sep 23 00:03:28 EDT 1998  Pete Ratzlaff <pratzlaff@cfa.harvard.edu>

	* [include/windows.h] [if1632/user.spec] [relay32/user32.spec]
	  [windows/keyboard.c]
	Added, marginally implemented, GetKeyboardLayoutName().
	Only returns US English keyboard name.

Tue Sep 22 16:32:41 1998  Marcel Baur <mbaur@iiic.ethz.ch>

	* [programs/control/*]
	New Winelib application.

Mon Sep 21 00:29:18 1998  Peter Hunnisett <hunnise@nortel.ca>

	* [include/dplay.h][multimedia/dplay.c][ole/compobj.c]
	Added all DirectPlayLobby interfaces and enhanced DirectPlay
	and DirectPlayLobby support. Still not all that much. Useful
	enough if you just need to start a program, don't try any
	real dplay/lobby stuff.

	* [documentation/status/directplay]
	Added a very little bit.

	* [graphics/ddraw.c]
	- Call to SetWindowLong32A wasn't working because there was no
	  memory set aside when the window class was registered.
	- Fixed some xlib reference counting and change the behaviour
	  of DirectDrawSurface3_SetPalette to mimic observed behaviour
	  (palette is associated will all backbuffers)
	- Also stored all palette colour fields and spit back our saved
	  colour fields rather than query X for them.
	- Added plenty of AddRef and Release traces.
	- Added Xlib support for using -desktop option.
	- Fixed Xlib message handling. Messages weren't being passed to
	  the application. Fixes mouse movements in some xlib DDraw games.
	- Added a few stubs.

	* [windows/win.c][include/winerror.h]
	Fixed up some error handling in WIN_SetWindowLong. SetLastError
	wasn't being used. Could cause problems with 0 return codes.
	Added new error in winerror (1400).

	* [AUTHORS] [include/authors.h]
	Added myself as a Wine author.

Sun Sep 20 21:22:44 1998  Alexander Larsson  <alla@lysator.liu.se>

	* [loader/module.c]
	Changed GetModuleFileName32A so that is returns the
	long version of the filename. Note that just the name
	is long, not the directories.

Sat Sep 19 20:05:30 1998 Per Ångström <pang@mind.nu> 

	* [controls/menu.c]
	Made a couple of fixes to make life easier for applications that alter
	their menus at runtime.

	* [windows/defdlg.c]
	Removed the cast of the return value from dialog procedures to a 16-bit
	bool. The return value needs to retain all its 32 bits, since it is not 
	always a bool, such as when responding to the WM_NCHITTEST message.

Fri Sep 18 11:30:38 1998  Sergey Turchanov <turchanov@usa.net>

	* [loader/resource.c]
	Fixed very funny bug (though gravely affecting further excecution)
	with FindResource[Ex]32 functions.

	* [include/multimon.h] [windows/multimon.c] [relay32/user32.spec]
	  [include/windows.h] [windows/sysmetrics.c]
	Default implementation for Multimonitor API.

	* [include/windows.h] [windows/winpos.c]
	Fixed incorrect declaration (and behaviour) of GetWindowRect32.

Wed Sep 16 10:21:15 1998  Gerard Patel <G.Patel@Wanadoo.fr>

	* [controls/edit.c]
	Fixed EDIT_EM_GetLine to use correctly length of lines.

Tue Sep 15 20:40:16 1998  Eric Kohl <ekohl@abo.rhein-zeitung.de>

	* [misc/tweak.c][include/tweak.h][controls/menu.c]
	Replaced the tweak graphic routines by calls to DrawEdge32().

	* [misc/tweak.c][include/tweak.h][documentation/win95look]
	  [wine.ini][*/*]
	Changed "look and feel" selection. Allows Win3.1, Win95 and
	Win98 (no GUI code implemented) look and feel.

	* [dlls/comctl32/header.c][include/header.h][include/commctrl.h]
	Started callback item support and did some minor improvements.

	* [dlls/comctl32/imagelist.c]
	Fixed bug in transparent image display.
	ImageList_GetIcon is still buggy :-(

	* [dlls/comctl32/toolbar.c]
	Fixed button drawing (partial hack).

	* [dlls/comctl32/commctrl.c]
	Fixed MenuHelp().

	* [controls/button.c]
	Added 3d effect for groupbox.

	* [windows/msgbox.c]
	Added font support for message boxes.

	* [windows/nonclient.c]
	Fixed window moving bug.

	* [dlls/comctl32/*.c]
	Various improvements.

	* [dlls/comctl32/listview.c][dlls/comctl32/rebar.c]
	  [include/commctrl.h]
	More messages.

	* [windows/syscolor.c][include/windows.h]
	Introduced new Win98 system colors.

Tue Sep 15 18:29:45 1998 Wesley Filardo <eightknots@aol.com>

	* [files/profile.c]
	Added support in PROFILE_LoadWineIni for -config option

	* [misc/main.c] [include/options.h]
	Added -config option.

Tue Sep 15 18:22:26 1998  Petter Reinholdtsen <pere@td.org.uit.no>

	* [documentation/Makefile.in]
	Make sure directory exists before installing into it.

Tue Sep 15 01:47:33 1998  Pablo Saratxaga <pablo.sarachaga@ping.be>

	* [ole/nls/*] [ole/ole2nls.c] [include/winnls.h]
	Fixed a few errors and completed some NLS files.

Mon Sep 14 01:23:45 1998  Joseph Pranevich <knight@baltimore.wwaves.com>

	* [include/miscemu.h] [msdos/interrupts.c]
	Removed a compilation warning, added INT 25 to the list of interrupts
	callable from DOS applications, added a debug message when unsupported
	interrupts are used.

Sun Sep 13 19:55:22 1998  Lawson Whitney <lawson_whitney@juno.com>

	* [if1632/relay.c]
	CallProcEx32W should not reverse arguments.

Sun Aug 17 21:18:12 1998  Eric Pouech  <eric.pouech@lemel.fr>

	* [multimedia/midi.c] [multimedia/init.c] [multimedia/mmsys.c] 
	  [include/multimedia.h] [include/mmsystem.h] 
	  [multimedia/Makefile.in] [multimedia/midipatch.c]
	  [if1632/multimedia.spec]
	Made MIDI input and output functional on OSS capable systems.

	* [multimedia/timer.c]
	Changes to trigger callbacks at the accurate pace even when
	fake timers are used.
diff --git a/dlls/comctl32/animate.c b/dlls/comctl32/animate.c
index 9303711..9c2fc19 100644
--- a/dlls/comctl32/animate.c
+++ b/dlls/comctl32/animate.c
@@ -14,6 +14,8 @@
  */
 
 #include "windows.h"
+#include "winnt.h"
+#include "winbase.h"
 #include "commctrl.h"
 #include "animate.h"
 #include "win.h"
@@ -23,34 +25,136 @@
 #define ANIMATE_GetInfoPtr(wndPtr) ((ANIMATE_INFO *)wndPtr->wExtra[0])
 
 
+static BOOL32
+ANIMATE_LoadRes32A (ANIMATE_INFO *infoPtr, HINSTANCE32 hInst, LPSTR lpName)
+{
+    HRSRC32 hrsrc;
+    HGLOBAL32 handle;
+
+    hrsrc = FindResource32A (hInst, lpName, "AVI");
+    if (!hrsrc)
+	return FALSE;
+
+    handle = LoadResource32 (hInst, hrsrc);
+    if (!handle)
+	return FALSE;
+
+    infoPtr->lpAvi = LockResource32 (handle);
+    if (!infoPtr->lpAvi)
+	return FALSE;
+
+    return TRUE;
+}
+
+
+static BOOL32
+ANIMATE_LoadFile32A (ANIMATE_INFO *infoPtr, LPSTR lpName)
+{
+    HANDLE32 handle;
+
+    infoPtr->hFile =
+	CreateFile32A (lpName, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+		       FILE_ATTRIBUTE_NORMAL, 0);
+    if (!infoPtr->hFile)
+	return FALSE;
+
+    handle =
+	CreateFileMapping32A (infoPtr->hFile, NULL, PAGE_READONLY | SEC_COMMIT,
+			      0, 0, NULL);
+    if (!handle) {
+	CloseHandle (infoPtr->hFile);
+	infoPtr->hFile = 0;
+	return FALSE;
+    }
+
+    infoPtr->lpAvi = MapViewOfFile (handle, FILE_MAP_READ, 0, 0, 0);
+    if (!infoPtr->lpAvi) {
+	CloseHandle (infoPtr->hFile);
+	infoPtr->hFile = 0;
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+static VOID
+ANIMATE_Free (ANIMATE_INFO *infoPtr)
+{
+    if (infoPtr->hFile) {
+	UnmapViewOfFile (infoPtr->lpAvi);
+	CloseHandle (infoPtr->hFile);
+	infoPtr->lpAvi = NULL;
+    }
+    else {
+	GlobalFree32 (infoPtr->lpAvi);
+	infoPtr->lpAvi = NULL;
+    }
+}
+
+
+static VOID
+ANIMATE_GetAviInfo (infoPtr)
+{
+
+
+}
+
+
 static LRESULT
 ANIMATE_Open32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(wndPtr);
+    HINSTANCE32 hInstance = (HINSTANCE32)wParam;
+
+    ANIMATE_Free (infoPtr);
 
     if (!lParam) {
-
-	FIXME (animate, "close avi: empty stub!\n");
-
+	TRACE (animate, "closing avi!\n");
 	return TRUE;
     }
     
     if (HIWORD(lParam)) {
-
 	FIXME (animate, "(\"%s\") empty stub!\n", (LPSTR)lParam);
 
+	if (ANIMATE_LoadRes32A (infoPtr, hInstance, (LPSTR)lParam)) {
+
+	    FIXME (animate, "AVI resource found!\n");
+
+	}
+	else {
+	    FIXME (animate, "No AVI resource found!\n");
+	    if (ANIMATE_LoadFile32A (infoPtr, (LPSTR)lParam)) {
+		FIXME (animate, "AVI file found!\n");
+	    }
+	    else {
+		FIXME (animate, "No AVI file found!\n");
+		return FALSE;
+	    }
+	}
     }
     else {
-
 	FIXME (animate, "(%u) empty stub!\n", (WORD)LOWORD(lParam));
 
+	if (ANIMATE_LoadRes32A (infoPtr, hInstance,
+				MAKEINTRESOURCE32A((INT32)lParam))) {
+	    FIXME (animate, "AVI resource found!\n");
+	}
+	else {
+	    FIXME (animate, "No AVI resource found!\n");
+	    return FALSE;
+	}
     }
 
+    ANIMATE_GetAviInfo (infoPtr);
 
     return TRUE;
 }
 
 
+// << ANIMATE_Open32W >>
+
+
 static LRESULT
 ANIMATE_Play (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
@@ -131,7 +235,8 @@
     ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(wndPtr);
 
 
-
+    /* free avi data */
+    ANIMATE_Free (infoPtr);
 
     /* free animate info data */
     COMCTL32_Free (infoPtr);
diff --git a/dlls/comctl32/comctl32undoc.c b/dlls/comctl32/comctl32undoc.c
index e45f77f..430dd67 100644
--- a/dlls/comctl32/comctl32undoc.c
+++ b/dlls/comctl32/comctl32undoc.c
@@ -10,7 +10,8 @@
  *     COMCTL32.DLL (internally).
  *
  * TODO
- *     - Write documentation.
+ *     - Add more functions.
+ *     - Write some documentation.
  */
 
 #include <string.h>
@@ -27,6 +28,22 @@
 
 
 /**************************************************************************
+ * COMCTL32_11 [COMCTL32.11]
+ */
+
+DWORD WINAPI
+COMCTL32_11 (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3,
+	     DWORD dwParam4, DWORD dwParam5, DWORD dwParam6)
+{
+
+    FIXME (commctrl, "(%08lx, %08lx, %08lx, %08lx, %08lx, %08lx): empty stub\n",
+	   dwParam1, dwParam2, dwParam3, dwParam4, dwParam5, dwParam6);
+
+    return 0;
+}
+
+
+/**************************************************************************
  * Alloc [COMCTL32.71]
  *
  * Allocates memory block from the dll's local heap
@@ -153,6 +170,25 @@
 
 
 /**************************************************************************
+ * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
+ * lists.
+ *
+ *
+ */
+
+typedef struct tagMRUINFO
+{
+    DWORD  dwParam1;
+    DWORD  dwParam2;
+    DWORD  dwParam3;
+    HKEY   hkeyMain;
+    LPCSTR lpszSubKey;
+    DWORD  dwParam6;
+} MRUINFO, *LPMRUINFO;
+ 
+
+
+/**************************************************************************
  * CreateMRUListA [COMCTL32.151]
  *
  * PARAMS
@@ -161,54 +197,233 @@
  * RETURNS
  */
 
-DWORD WINAPI
-CreateMRUList32A (DWORD dwParam)
+LPVOID WINAPI
+CreateMRUListEx32A (LPMRUINFO lpmi, DWORD dwParam2,
+		    DWORD dwParam3, DWORD dwParam4);
+
+LPVOID WINAPI
+CreateMRUList32A (LPMRUINFO lpmi)
 {
-
-    FIXME (commctrl, "(%lx)\n", dwParam);
-
-    return 1;
+     return CreateMRUListEx32A (lpmi, 0, 0, 0);
 }
 
 
 
+DWORD WINAPI
+FreeMRUList32A (LPVOID ptr)
+{
+    FIXME (commctrl, "(%p) empty stub!\n", ptr);
+
+    COMCTL32_Free (ptr);
+
+    return TRUE;
+}
+
+
+
+
+
+
+LPVOID WINAPI
+CreateMRUListEx32A (LPMRUINFO lpmi, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
+{
+    DWORD  dwLocal1;
+    HKEY   hkeyResult;
+    DWORD  dwLocal3;
+    LPVOID lMRU;
+    DWORD  dwLocal5;
+    DWORD  dwLocal6;
+    DWORD  dwLocal7;
+    DWORD  dwDisposition;
+
+    /* internal variables */
+    LPVOID ptr;
+
+    FIXME (commctrl, "(%p) empty stub!\n", lpmi);
+
+    if (lpmi) {
+	FIXME (commctrl, "(%lx %lx %lx %lx \"%s\" %lx)\n",
+	       lpmi->dwParam1, lpmi->dwParam2, lpmi->dwParam3,
+	       lpmi->hkeyMain, lpmi->lpszSubKey, lpmi->dwParam6);
+    }
+
+    /* dummy pointer creation */
+    ptr = COMCTL32_Alloc (32);
+
+    FIXME (commctrl, "-- ret = %p\n", ptr);
+
+    return ptr;
+}
+
+
+
+DWORD WINAPI
+AddMRUData (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{
+
+    FIXME (commctrl, "(%lx %lx %lx) empty stub!\n",
+	   dwParam1, dwParam2, dwParam3);
+
+    return 0;
+}
+
+
+DWORD WINAPI
+FindMRUData (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
+{
+
+    FIXME (commctrl, "(%lx %lx %lx %lx) empty stub!\n",
+	   dwParam1, dwParam2, dwParam3, dwParam4);
+
+    return -1;
+}
+
+
+
+/**************************************************************************
+ * Str_GetPtrA [COMCTL32.233]
+ *
+ * PARAMS
+ *     lpSrc   [I]
+ *     lpDest  [O]
+ *     nMaxLen [I]
+ *
+ * RETURNS
+ */
+
+INT32 WINAPI
+Str_GetPtr32A (LPCSTR lpSrc, LPSTR lpDest, INT32 nMaxLen)
+{
+    INT32 len;
+
+    TRACE (commctrl, "(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
+
+    if (!lpDest && lpSrc)
+	return lstrlen32A (lpSrc);
+
+    if (nMaxLen == 0)
+	return 0;
+
+    if (lpSrc == NULL) {
+	lpDest[0] = '\0';
+	return 0;
+    }
+
+    len = lstrlen32A (lpSrc);
+    if (len >= nMaxLen)
+	len = nMaxLen - 1;
+
+    RtlMoveMemory (lpDest, lpSrc, len);
+    lpDest[len] = '\0';
+
+    return len;
+}
+
 
 /**************************************************************************
  * Str_SetPtrA [COMCTL32.234]
  *
  * PARAMS
- *     dwParam1 [I]
- *     dwParam2 [I]
+ *     lppDest [O]
+ *     lpSrc   [I]
  *
  * RETURNS
  */
 
 BOOL32 WINAPI
-COMCTL32_Str_SetPtrA (LPSTR lpStr, LPVOID *lpPtr)
+Str_SetPtr32A (LPSTR *lppDest, LPCSTR lpSrc)
+{
+    TRACE (commctrl, "(%p %p)\n", lppDest, lpSrc);
+ 
+    if (lpSrc) {
+	LPSTR ptr = COMCTL32_ReAlloc (lppDest, lstrlen32A (lpSrc) + 1);
+	if (!ptr)
+	    return FALSE;
+	lstrcpy32A (ptr, lpSrc);
+	*lppDest = ptr;
+    }
+    else {
+	if (*lppDest) {
+	    COMCTL32_Free (*lppDest);
+	    *lppDest = NULL;
+	}
+    }
+
+    return TRUE;
+}
+
+
+/**************************************************************************
+ * Str_GetPtrW [COMCTL32.235]
+ *
+ * PARAMS
+ *     lpSrc   [I]
+ *     lpDest  [O]
+ *     nMaxLen [I]
+ *
+ * RETURNS
+ */
+
+INT32 WINAPI
+Str_GetPtr32W (LPCWSTR lpSrc, LPWSTR lpDest, INT32 nMaxLen)
 {
     INT32 len;
-    LPSTR ptr;
 
-    TRACE (commctrl, "(%p %p)\n", lpStr, lpPtr);
+    TRACE (commctrl, "(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
+
+    if (!lpDest && lpSrc)
+	return lstrlen32W (lpSrc);
+
+    if (nMaxLen == 0)
+	return 0;
+
+    if (lpSrc == NULL) {
+	lpDest[0] = L'\0';
+	return 0;
+    }
+
+    len = lstrlen32W (lpSrc);
+    if (len >= nMaxLen)
+	len = nMaxLen - 1;
+
+    RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
+    lpDest[len] = L'\0';
+
+    return len;
+}
+
+
+/**************************************************************************
+ * Str_SetPtrW [COMCTL32.236]
+ *
+ * PARAMS
+ *     lpDest [O]
+ *     lpSrc  [I]
+ *
+ * RETURNS
+ */
+
+BOOL32 WINAPI
+Str_SetPtr32W (LPWSTR *lppDest, LPCWSTR lpSrc)
+{
+    TRACE (commctrl, "(%p %p)\n", lppDest, lpSrc);
  
-    if (lpStr) {
-	len = lstrlen32A (lpStr);
-	ptr = COMCTL32_ReAlloc (lpPtr, len + 1);
-	if (!(ptr))
+    if (lpSrc) {
+	INT32 len = lstrlen32W (lpSrc) + 1;
+	LPWSTR ptr = COMCTL32_ReAlloc (lppDest, len * sizeof(WCHAR));
+	if (!ptr)
 	    return FALSE;
-	lstrcpy32A (ptr, lpStr);
-	if (!lpPtr)
-	    return FALSE;
-	*lpPtr = ptr;
-	return TRUE;
+	lstrcpy32W (ptr, lpSrc);
+	*lppDest = ptr;
+    }
+    else {
+	if (*lppDest) {
+	    COMCTL32_Free (*lppDest);
+	    *lppDest = NULL;
+	}
     }
 
-    if (*lpPtr) {
-	COMCTL32_Free (*lpPtr);
-	return TRUE;
-    }
-
-    return FALSE;
+    return TRUE;
 }
 
 
@@ -636,7 +851,7 @@
 BOOL32 WINAPI
 DPA_Grow (const HDPA hdpa, INT32 nGrow)
 {
-    FIXME (commctrl, "(%p %d) stub!\n", hdpa, nGrow);
+    TRACE (commctrl, "(%p %d)\n", hdpa, nGrow);
 
     if (!hdpa)
 	return FALSE;
@@ -676,7 +891,7 @@
     if (!hdpa)
 	return NULL;
 
-    FIXME (commctrl, "(%p %p) stub!\n", hdpa, hdpaNew);
+    TRACE (commctrl, "(%p %p)\n", hdpa, hdpaNew);
 
     if (!hdpaNew) {
 	/* create a new DPA */
@@ -1019,7 +1234,7 @@
     LPVOID t, v;
     INT32  i, j;
 
-    if (l > r) {
+    if (r > l) {
 	v = lpPtrs[r];
 	i = l - 1;
 	j = r;
@@ -1064,7 +1279,9 @@
 
     TRACE (commctrl, "(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
 
-    DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1, pfnCompare, lParam);
+    if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
+	DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
+		       pfnCompare, lParam);
 
     return TRUE;
 }
@@ -1107,6 +1324,8 @@
 	INT32 l, r, x, n;
 	LPVOID *lpPtr;
 
+	TRACE (commctrl, "binary search\n");
+
 	l = (nStart == -1) ? 0 : nStart;
 	r = hdpa->nItemCount - 1;
 	lpPtr = hdpa->ptrs;
@@ -1138,7 +1357,7 @@
 	LPVOID *lpPtr;
 	INT32  nIndex;
 
-	FIXME (commctrl, "linear search\n");
+	TRACE (commctrl, "linear search\n");
 	
 	nIndex = (nStart == -1)? 0 : nStart;
 	lpPtr = hdpa->ptrs;
@@ -1267,3 +1486,63 @@
     return atoi(lpString);
 }
 
+
+/**************************************************************************
+ * COMCTL32_385 [COMCTL32.385]
+ */
+
+DWORD WINAPI
+COMCTL32_385 (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{
+
+    FIXME (commctrl, "(%08lx, %08lx, %08lx): empty stub\n",
+	   dwParam1, dwParam2, dwParam3);
+
+    return 0;
+}
+
+
+/**************************************************************************
+ * COMCTL32_386 [COMCTL32.386]
+ */
+
+DWORD WINAPI
+COMCTL32_386 (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{
+
+    FIXME (commctrl, "(%08lx, %08lx, %08lx): empty stub\n",
+	   dwParam1, dwParam2, dwParam3);
+
+    return 0;
+}
+
+
+/**************************************************************************
+ * COMCTL32_387 [COMCTL32.387]
+ */
+
+DWORD WINAPI
+COMCTL32_387 (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{
+
+    FIXME (commctrl, "(%08lx, %08lx, %08lx): empty stub\n",
+	   dwParam1, dwParam2, dwParam3);
+
+    return 0;
+}
+
+
+/**************************************************************************
+ * COMCTL32_388 [COMCTL32.388]
+ */
+
+DWORD WINAPI
+COMCTL32_388 (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{
+
+    FIXME (commctrl, "(%08lx, %08lx, %08lx): empty stub\n",
+	   dwParam1, dwParam2, dwParam3);
+
+    return 0;
+}
+
diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c
index 0c6f00e..b0b5c7c 100644
--- a/dlls/comctl32/commctrl.c
+++ b/dlls/comctl32/commctrl.c
@@ -32,10 +32,13 @@
  * ComCtl32LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
  *
  * PARAMS
- *     hinstDLL    [I]
+ *     hinstDLL    [I] handle to the 'dlls' instance
  *     fdwReason   [I]
  *     lpvReserved [I]
  *
+ * RETURNS
+ *     Success: TRUE
+ *     Failure: FALSE
  */
 
 BOOL32 WINAPI
@@ -68,59 +71,64 @@
  * MenuHelp [COMCTL32.2]
  *
  * PARAMS
- *     uMsg
- *     wParam
- *     lParam
- *     hMainMenu
- *     hInst
- *     hwndStatus
- *     lpwIDs
+ *     uMsg       [I]
+ *     wParam     [I]
+ *     lParam     [I]
+ *     hMainMenu  [I] handle to the applications main menu
+ *     hInst      [I]
+ *     hwndStatus [I] handle to the status bar window
+ *     lpwIDs     [I] pointer to an array of intergers (see NOTES)
  *
  * RETURNS
- *     None
+ *     No return value
  *
  * NOTES
- *     Some features are still missing because of incomplete WM_MENUSELECT
- *     messages (16->32 bit conversion).
+ *     The official documentation is incomplete!
  */
 
 VOID WINAPI
 MenuHelp (UINT32 uMsg, WPARAM32 wParam, LPARAM lParam, HMENU32 hMainMenu,
 	  HINSTANCE32 hInst, HWND32 hwndStatus, LPUINT32 lpwIDs)
 {
-    char szStatusText[128];
+    UINT32 uMenuID = 0;
 
-    if (!IsWindow32 (hwndStatus)) return;
+    if (!IsWindow32 (hwndStatus))
+	return;
 
     switch (uMsg) {
 	case WM_MENUSELECT:
-            TRACE (commctrl, "WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
-                   wParam, lParam);
+	    TRACE (commctrl, "WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
+		   wParam, lParam);
 
             if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
                 /* menu was closed */
+		TRACE (commctrl, "menu was closed!\n");
                 SendMessage32A (hwndStatus, SB_SIMPLE, FALSE, 0);
             }
-            else {
-                if (HIWORD(wParam) & MF_POPUP) {
-		    FIXME (commctrl, "popup 0x%08x 0x%08lx\n", wParam, lParam);
+	    else {
+		/* menu item was selected */
+		if (HIWORD(wParam) & MF_POPUP)
+		    uMenuID = (UINT32)*(lpwIDs+1);
+		else
+		    uMenuID = (UINT32)LOWORD(wParam);
+		TRACE (commctrl, "uMenuID = %u\n", uMenuID);
 
-                    szStatusText[0] = 0;
-                }
-                else {
-                    TRACE (commctrl, "menu item selected!\n");
-                    if (!LoadString32A (hInst, LOWORD(wParam), szStatusText, 128))
-                        szStatusText[0] = 0;
-                }
-                SendMessage32A (hwndStatus, SB_SETTEXT32A, 255 | SBT_NOBORDERS,
-                                (LPARAM)szStatusText);
-                SendMessage32A (hwndStatus, SB_SIMPLE, TRUE, 0);
-            }
-            break;
+		if (uMenuID) {
+		    CHAR szText[256];
 
-        default:
-            WARN (commctrl, "Invalid Message!\n");
-            break;
+		    if (!LoadString32A (hInst, uMenuID, szText, 256))
+			szText[0] = 0;
+
+		    SendMessage32A (hwndStatus, SB_SETTEXT32A,
+				    255 | SBT_NOBORDERS, (LPARAM)szText);
+		    SendMessage32A (hwndStatus, SB_SIMPLE, TRUE, 0);
+		}
+	    }
+	    break;
+
+	default:
+	    WARN (commctrl, "Invalid Message!\n");
+	    break;
     }
 }
 
@@ -198,10 +206,10 @@
  *     lpInfo [I] pointer to an array of integers
  *
  * RETURNS
- *     None.
+ *     No return value.
  *
  * NOTES
- *
+ *     The official documentation is incomplete!
  */
 
 VOID WINAPI
@@ -244,6 +252,9 @@
  *     lprc  [I] pointer to a rectangle
  *     text  [I] pointer to the text
  *     style [I] 
+ *
+ * RETURNS
+ *     No return value.
  */
 
 VOID WINAPI
@@ -281,6 +292,9 @@
  *     lprc  [I] pointer to a rectangle
  *     text  [I] pointer to the text
  *     style [I] 
+ *
+ * RETURNS
+ *     No return value.
  */
 
 VOID WINAPI
@@ -293,8 +307,19 @@
 
 
 /***********************************************************************
- * CreateStatusWindow32A [COMCTL32.6][COMCTL32.21]
+ * CreateStatusWindow32A [COMCTL32.6][COMCTL32.21] Creates a status bar
+ *
+ * PARAMS
+ *     style  [I]
+ *     text   [I]
+ *     parent [I] handle to the parent window
+ *     wid    [I]
+ *
+ * RETURNS
+ *     Success: handle to the control
+ *     Failure: 0
  */
+
 HWND32 WINAPI
 CreateStatusWindow32A (INT32 style, LPCSTR text, HWND32 parent, UINT32 wid)
 {
@@ -306,20 +331,51 @@
 
 
 /***********************************************************************
- *           CreateStatusWindow32W   (COMCTL32.22)
+ * CreateStatusWindow32W [COMCTL32.22] Creates a status bar control
+ *
+ * PARAMS
+ *     style  [I]
+ *     text   [I]
+ *     parent [I]
+ *     wid    [I]
+ *
+ * RETURNS
+ *     Success: handle to the control
+ *     Failure: 0
  */
-HWND32 WINAPI CreateStatusWindow32W( INT32 style, LPCWSTR text, HWND32 parent,
-                                     UINT32 wid )
+
+HWND32 WINAPI
+CreateStatusWindow32W (INT32 style, LPCWSTR text, HWND32 parent, UINT32 wid)
 {
-    return CreateWindow32W((LPCWSTR)STATUSCLASSNAME32W, text, style, 
+    return CreateWindow32W((LPCWSTR)STATUSCLASSNAME32W, text, style,
 			   CW_USEDEFAULT32, CW_USEDEFAULT32,
-			   CW_USEDEFAULT32, CW_USEDEFAULT32, 
+			   CW_USEDEFAULT32, CW_USEDEFAULT32,
 			   parent, wid, 0, 0);
 }
 
+
 /***********************************************************************
- *           CreateUpDownControl  (COMCTL32.16)
+ * CreateUpDownControl [COMCTL32.16] Creates an Up-Down control
+ *
+ * PARAMS
+ *     style
+ *     x
+ *     y
+ *     cx
+ *     cy
+ *     parent
+ *     id
+ *     inst
+ *     buddy
+ *     maxVal [I]
+ *     minVal [I]
+ *     curVal [I]
+ *
+ * RETURNS
+ *     Success: handle to the control
+ *     Failure: 0
  */
+
 HWND32 WINAPI
 CreateUpDownControl (DWORD style, INT32 x, INT32 y, INT32 cx, INT32 cy,
 		     HWND32 parent, INT32 id, HINSTANCE32 inst,
@@ -344,7 +400,10 @@
  * Registers the common controls.
  *
  * PARAMS
- *     None.
+ *     No parameters.
+ *
+ * RETURNS
+ *     No return values.
  *
  * NOTES
  *     This function is just a dummy.
@@ -364,7 +423,11 @@
  * Registers the common controls.
  *
  * PARAMS
- *     lpInitCtrls [I] pointer to a INITCOMMONCONTROLS structure.
+ *     lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
+ *
+ * RETURNS
+ *     Success: TRUE
+ *     Failure: FALSE
  *
  * NOTES
  *     Only the additinal common controls are registered by this function.
@@ -399,37 +462,36 @@
 	    case ICC_HOTKEY_CLASS:
 		break;
 
-      /* advanced classes - not included in Win95 */
-      case ICC_DATE_CLASSES:
-        TRACE (commctrl, "No month calendar class implemented!\n");
-        TRACE (commctrl, "No date picker class implemented!\n");
-        TRACE (commctrl, "No time picker class implemented!\n");
-        UPDOWN_Register ();
-        break;
+	    /* advanced classes - not included in Win95 */
+	    case ICC_DATE_CLASSES:
+		FIXME (commctrl, "No month calendar class implemented!\n");
+		FIXME (commctrl, "No date picker class implemented!\n");
+		FIXME (commctrl, "No time picker class implemented!\n");
+		break;
 
-      case ICC_USEREX_CLASSES:
-	COMBOEX_Register ();
-        break;
+	    case ICC_USEREX_CLASSES:
+		COMBOEX_Register ();
+		break;
 
-      case ICC_COOL_CLASSES:
-	REBAR_Register ();
-        break;
+	    case ICC_COOL_CLASSES:
+		REBAR_Register ();
+		break;
 
-      case ICC_INTERNET_CLASSES:
-        TRACE (commctrl, "No IPAddress class implemented!\n");
-        break;
+	    case ICC_INTERNET_CLASSES:
+		FIXME (commctrl, "No IPAddress class implemented!\n");
+		break;
 
-      case ICC_PAGESCROLLER_CLASS:
-	PAGER_Register ();
-        break;
+	    case ICC_PAGESCROLLER_CLASS:
+		PAGER_Register ();
+		break;
 
-      case ICC_NATIVEFNTCTL_CLASS:
-        TRACE (commctrl, "No native font class implemented!\n");
-        break;
+	    case ICC_NATIVEFNTCTL_CLASS:
+		FIXME (commctrl, "No native font class implemented!\n");
+		break;
 
-      default:
-        WARN (commctrl, "Unknown class! dwICC=0x%lX\n", dwMask);
-        break;
+	    default:
+		WARN (commctrl, "Unknown class! dwICC=0x%lX\n", dwMask);
+		break;
 	}
     }
 
@@ -438,10 +500,26 @@
 
 
 /***********************************************************************
- * CreateToolbarEx [COMCTL32.32]
+ * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
  *
+ * PARAMS
+ *     hwnd
+ *     style
+ *     wID
+ *     nBitmaps
+ *     hBMInst
+ *     wBMID
+ *     lpButtons
+ *     iNumButtons
+ *     dxButton
+ *     dyButton
+ *     dxBitmap
+ *     dyBitmap
+ *     uStructSize
  *
- *
+ * RETURNS
+ *     Success: handle to the tool bar control
+ *     Failure: 0
  */
 
 HWND32 WINAPI
@@ -600,10 +678,24 @@
 
 
 /***********************************************************************
- * CreateToolbar [COMCTL32.7]
+ * CreateToolbar [COMCTL32.7] Creates a tool bar control
  *
+ * PARAMS
+ *     hwnd
+ *     style
+ *     wID
+ *     nBitmaps
+ *     hBMInst
+ *     wBMID
+ *     lpButtons
+ *     iNumButtons
  *
+ * RETURNS
+ *     Success: handle to the tool bar control
+ *     Failure: 0
  *
+ * NOTES
+ *     Do not use this functions anymore. Use CreateToolbarEx instead.
  */
 
 HWND32 WINAPI
@@ -625,22 +717,25 @@
  * PARAMS
  *     pdvi [O] pointer to version information structure.
  *
- * REURNS
+ * RETURNS
  *     Success: S_OK
  *     Failure: E_INVALIDARG
+ *
+ * NOTES
+ *     Returns version of a comctl32.dll from IE4.01 SP1.
  */
 
 HRESULT WINAPI
 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
 {
     if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
-        WARN(ver, "wrong DLLVERSIONINFO size from app");
+        WARN (commctrl, "wrong DLLVERSIONINFO size from app");
 	return E_INVALIDARG;
     }
 
     pdvi->dwMajorVersion = 4;
     pdvi->dwMinorVersion = 72;
-    pdvi->dwBuildNumber = 2106;
+    pdvi->dwBuildNumber = 3110;
     pdvi->dwPlatformID = 1;
 
     TRACE (commctrl, "%lu.%lu.%lu.%lu\n",
diff --git a/dlls/comctl32/header.c b/dlls/comctl32/header.c
index 813512c..a2d86fc 100644
--- a/dlls/comctl32/header.c
+++ b/dlls/comctl32/header.c
@@ -5,7 +5,7 @@
  *
  *  TODO:
  *   - Imagelist support (partially).
- *   - Callback items.
+ *   - Callback items (under construction).
  *   - Order list support.
  *   - Control specific cursors (over dividers).
  *   - Hottrack support (partially).
@@ -22,7 +22,6 @@
 #include "windows.h"
 #include "commctrl.h"
 #include "header.h"
-#include "heap.h"
 #include "win.h"
 #include "debug.h"
 
@@ -446,7 +445,7 @@
 HEADER_SendHeaderNotify (WND *wndPtr, UINT32 code, INT32 iItem)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);   
-    NMHEADERA nmhdr;
+    NMHEADER32A nmhdr;
     HDITEM32A nmitem;
 
     nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
@@ -455,11 +454,13 @@
     nmhdr.iItem = iItem;
     nmhdr.iButton = 0;
     nmhdr.pitem = &nmitem;
-    nmitem.mask = infoPtr->items[iItem].mask;
+    nmitem.mask = 0;
     nmitem.cxy = infoPtr->items[iItem].cxy;
     nmitem.hbm = infoPtr->items[iItem].hbm;
-    nmitem.pszText = infoPtr->items[iItem].pszText;
-    nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax;
+    nmitem.pszText = NULL;
+    nmitem.cchTextMax = 0;
+//    nmitem.pszText = infoPtr->items[iItem].pszText;
+//    nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax;
     nmitem.fmt = infoPtr->items[iItem].fmt;
     nmitem.lParam = infoPtr->items[iItem].lParam;
     nmitem.iOrder = infoPtr->items[iItem].iOrder;
@@ -473,7 +474,7 @@
 static BOOL32
 HEADER_SendClickNotify (WND *wndPtr, UINT32 code, INT32 iItem)
 {
-    NMHEADERA nmhdr;
+    NMHEADER32A nmhdr;
 
     nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
     nmhdr.hdr.idFrom = wndPtr->wIDmenu;
@@ -499,21 +500,19 @@
 HEADER_DeleteItem (WND *wndPtr, WPARAM32 wParam)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
+    INT32 iItem = (INT32)wParam;
     HDC32 hdc;
-    INT32 iItem;
-
-    iItem = (INT32)wParam;
 
     TRACE(header, "[iItem=%d]\n", iItem);
     
-    if ((iItem < 0) || (iItem > infoPtr->uNumItem - 1))
+    if ((iItem < 0) || (iItem >= (INT32)infoPtr->uNumItem))
         return FALSE;
 
     if (infoPtr->uNumItem == 1) {
         TRACE(header, "Simple delete!\n");
         if (infoPtr->items[0].pszText)
-            HeapFree (GetProcessHeap (), 0, infoPtr->items[0].pszText);
-        HeapFree (GetProcessHeap (), 0, infoPtr->items);
+            COMCTL32_Free (infoPtr->items[0].pszText);
+        COMCTL32_Free (infoPtr->items);
         infoPtr->items = 0;
         infoPtr->uNumItem = 0;
     }
@@ -522,11 +521,10 @@
         TRACE(header, "Complex delete! [iItem=%d]\n", iItem);
 
         if (infoPtr->items[iItem].pszText)
-            HeapFree (GetProcessHeap (), 0, infoPtr->items[iItem].pszText);
+            COMCTL32_Free (infoPtr->items[iItem].pszText);
 
         infoPtr->uNumItem--;
-        infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                    sizeof (HEADER_ITEM) * infoPtr->uNumItem);
+        infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
         /* pre delete copy */
         if (iItem > 0) {
             memcpy (&infoPtr->items[0], &oldItems[0],
@@ -539,7 +537,7 @@
                     (infoPtr->uNumItem - iItem) * sizeof(HEADER_ITEM));
         }
 
-        HeapFree (GetProcessHeap (), 0, oldItems);
+        COMCTL32_Free (oldItems);
     }
 
     HEADER_SetItemBounds (wndPtr);
@@ -565,60 +563,45 @@
 HEADER_GetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
-    HDITEM32A *phdi;
-    INT32     iItem;
-    UINT32    uMask;
+    HDITEM32A   *phdi = (HDITEM32A*)lParam;
+    INT32       nItem = (INT32)wParam;
+    HEADER_ITEM *lpItem;
 
-    phdi = (HDITEM32A*)lParam;
-    iItem = (INT32)wParam;
-
-    if (phdi == NULL)
+    if (!phdi)
 	return FALSE;
-    if ((iItem < 0) || (iItem > infoPtr->uNumItem - 1))
+    if ((nItem < 0) || (nItem >= (INT32)infoPtr->uNumItem))
         return FALSE;
 
-    TRACE (header, "[iItem=%d]\n", iItem);
+    TRACE (header, "[nItem=%d]\n", nItem);
 
-    uMask = phdi->mask;
-    if (uMask == 0)
+    if (phdi->mask == 0)
 	return TRUE;
-    phdi->mask = 0;
 
-    if (uMask & infoPtr->items[iItem].mask & HDI_BITMAP) {
-	phdi->hbm = infoPtr->items[iItem].hbm;
-        phdi->mask |= HDI_BITMAP;
+    lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
+    if (phdi->mask & HDI_BITMAP)
+	phdi->hbm = lpItem->hbm;
+
+    if (phdi->mask & HDI_FORMAT)
+	phdi->fmt = lpItem->fmt;
+
+    if (phdi->mask & HDI_WIDTH)
+	phdi->cxy = lpItem->cxy;
+
+    if (phdi->mask & HDI_LPARAM)
+	phdi->lParam = lpItem->lParam;
+
+    if (phdi->mask & HDI_TEXT) {
+	if (lpItem->pszText != LPSTR_TEXTCALLBACK32A)
+	    lstrcpyn32A (phdi->pszText, lpItem->pszText, phdi->cchTextMax);
+	else
+	    phdi->pszText = LPSTR_TEXTCALLBACK32A;
     }
 
-    if (uMask & infoPtr->items[iItem].mask & HDI_FORMAT) {
-	phdi->fmt = infoPtr->items[iItem].fmt;
-        phdi->mask |= HDI_FORMAT;
-    }
+    if (phdi->mask & HDI_IMAGE)
+	phdi->iImage = lpItem->iImage;
 
-    if (uMask & infoPtr->items[iItem].mask & HDI_WIDTH) {
-	phdi->cxy = infoPtr->items[iItem].cxy;
-        phdi->mask |= HDI_WIDTH;
-    }
-
-    if (uMask & infoPtr->items[iItem].mask & HDI_LPARAM) {
-	phdi->lParam = infoPtr->items[iItem].lParam;
-        phdi->mask |= HDI_LPARAM;
-    }
-
-    if (uMask & infoPtr->items[iItem].mask & HDI_TEXT) {
-	phdi->pszText = infoPtr->items[iItem].pszText;
-	phdi->cchTextMax = infoPtr->items[iItem].cchTextMax;
-        phdi->mask |= HDI_TEXT;
-    }
-
-    if (uMask & infoPtr->items[iItem].mask & HDI_IMAGE) {
-	phdi->iImage = infoPtr->items[iItem].iImage;
-        phdi->mask |= HDI_IMAGE;
-    }
-
-    if (uMask & infoPtr->items[iItem].mask & HDI_ORDER) {
-	phdi->iOrder = infoPtr->items[iItem].iOrder;
-        phdi->mask |= HDI_ORDER;
-    }
+    if (phdi->mask & HDI_ORDER)
+	phdi->iOrder = lpItem->iOrder;
 
     return TRUE;
 }
@@ -637,13 +620,10 @@
 HEADER_GetItemRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
-    INT32 iItem;
-    LPRECT32 lpRect;
+    INT32 iItem = (INT32)wParam;
+    LPRECT32 lpRect = (LPRECT32)lParam;
 
-    iItem = (INT32)wParam;
-    lpRect = (LPRECT32)lParam;
-
-    if ((iItem < 0) || (iItem > infoPtr->uNumItem - 1))
+    if ((iItem < 0) || (iItem >= (INT32)infoPtr->uNumItem))
         return FALSE;
 
     lpRect->left   = infoPtr->items[iItem].rect.left;
@@ -670,70 +650,72 @@
 HEADER_InsertItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
-    HDITEM32A *phdi = (HDITEM32A*)lParam;
-    INT32     iItem = (INT32)wParam;
-    HDC32     hdc;
-    INT32     len;
+    HDITEM32A   *phdi = (HDITEM32A*)lParam;
+    INT32       nItem = (INT32)wParam;
+    HEADER_ITEM *lpItem;
+    HDC32       hdc;
+    INT32       len;
 
-    if (phdi == NULL) return -1;
-    if (iItem < 0) return -1;
-    if (iItem > infoPtr->uNumItem)
-        iItem = infoPtr->uNumItem;
+    if ((phdi == NULL) || (nItem < 0))
+	return -1;
+
+    if (nItem > infoPtr->uNumItem)
+        nItem = infoPtr->uNumItem;
 
     if (infoPtr->uNumItem == 0) {
-        infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                    sizeof (HEADER_ITEM));
+        infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM));
         infoPtr->uNumItem++;
     }
     else {
         HEADER_ITEM *oldItems = infoPtr->items;
 
         infoPtr->uNumItem++;
-        infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                    sizeof (HEADER_ITEM) * infoPtr->uNumItem);
+        infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
         /* pre insert copy */
-        if (iItem > 0) {
+        if (nItem > 0) {
             memcpy (&infoPtr->items[0], &oldItems[0],
-                    iItem * sizeof(HEADER_ITEM));
+                    nItem * sizeof(HEADER_ITEM));
         }
 
         /* post insert copy */
-        if (iItem < infoPtr->uNumItem - 1) {
-            memcpy (&infoPtr->items[iItem+1], &oldItems[iItem],
-                    (infoPtr->uNumItem - iItem) * sizeof(HEADER_ITEM));
+        if (nItem < infoPtr->uNumItem - 1) {
+            memcpy (&infoPtr->items[nItem+1], &oldItems[nItem],
+                    (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM));
         }
 
-        HeapFree (GetProcessHeap (), 0, oldItems);
+	COMCTL32_Free (oldItems);
     }
 
-    infoPtr->items[iItem].bDown = FALSE;
+    lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
+    lpItem->bDown = FALSE;
 
-    infoPtr->items[iItem].mask = phdi->mask;
     if (phdi->mask & HDI_WIDTH)
-        infoPtr->items[iItem].cxy = phdi->cxy;
+	lpItem->cxy = phdi->cxy;
 
     if (phdi->mask & HDI_TEXT) {
-        len = lstrlen32A (phdi->pszText);
-        infoPtr->items[iItem].pszText =
-            HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len+1);
-        lstrcpy32A (infoPtr->items[iItem].pszText, phdi->pszText);
-        infoPtr->items[iItem].cchTextMax = phdi->cchTextMax;
+	if (phdi->pszText != LPSTR_TEXTCALLBACK32A) {
+	    len = lstrlen32A (phdi->pszText);
+	    lpItem->pszText = COMCTL32_Alloc (len+1);
+	    lstrcpy32A (lpItem->pszText, phdi->pszText);
+	}
+	else
+	    lpItem->pszText = LPSTR_TEXTCALLBACK32A;
     }
 
     if (phdi->mask & HDI_FORMAT)
-        infoPtr->items[iItem].fmt = phdi->fmt;
+	lpItem->fmt = phdi->fmt;
 
     if (phdi->mask & HDI_BITMAP)
-        infoPtr->items[iItem].hbm = phdi->hbm;
+        lpItem->hbm = phdi->hbm;
 
     if (phdi->mask & HDI_LPARAM)
-        infoPtr->items[iItem].lParam = phdi->lParam;
+        lpItem->lParam = phdi->lParam;
 
     if (phdi->mask & HDI_IMAGE)
-        infoPtr->items[iItem].iImage = phdi->iImage;
+        lpItem->iImage = phdi->iImage;
 
     if (phdi->mask & HDI_ORDER)
-        infoPtr->items[iItem].iOrder = phdi->iOrder;
+        lpItem->iOrder = phdi->iOrder;
 
     HEADER_SetItemBounds (wndPtr);
 
@@ -741,7 +723,7 @@
     HEADER_Refresh (wndPtr, hdc);
     ReleaseDC32 (wndPtr->hwndSelf, hdc);
 
-    return iItem;
+    return nItem;
 }
 
 
@@ -798,60 +780,52 @@
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
     HDITEM32A *phdi = (HDITEM32A*)lParam;
-    INT32 iItem = (INT32)wParam;
+    INT32 nItem = (INT32)wParam;
+    HEADER_ITEM *lpItem;
     HDC32 hdc;
 
     if (phdi == NULL)
 	return FALSE;
-    if ((iItem < 0) || (iItem > infoPtr->uNumItem - 1))
+    if ((nItem < 0) || (nItem >= (INT32)infoPtr->uNumItem))
         return FALSE;
 
-    TRACE (header, "[iItem=%d]\n", iItem);
+    TRACE (header, "[nItem=%d]\n", nItem);
 
-    if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, iItem))
+    if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, nItem))
 	return FALSE;
 
-    if (phdi->mask & HDI_BITMAP) {
-	infoPtr->items[iItem].hbm = phdi->hbm;
-	infoPtr->items[iItem].mask  |= HDI_BITMAP;
-    }
+    lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
+    if (phdi->mask & HDI_BITMAP)
+	lpItem->hbm = phdi->hbm;
 
-    if (phdi->mask & HDI_FORMAT) {
-	infoPtr->items[iItem].fmt = phdi->fmt;
-	infoPtr->items[iItem].mask  |= HDI_FORMAT;
-    }
+    if (phdi->mask & HDI_FORMAT)
+	lpItem->fmt = phdi->fmt;
 
-    if (phdi->mask & HDI_LPARAM) {
-	infoPtr->items[iItem].lParam = phdi->lParam;
-	infoPtr->items[iItem].mask  |= HDI_LPARAM;
-    }
+    if (phdi->mask & HDI_LPARAM)
+	lpItem->lParam = phdi->lParam;
 
     if (phdi->mask & HDI_TEXT) {
-        INT32 len = lstrlen32A (phdi->pszText);
-        if (infoPtr->items[iItem].pszText)
-	    HeapFree (GetProcessHeap (), 0, infoPtr->items[iItem].pszText);
-        infoPtr->items[iItem].pszText =
-            HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len+1);
-        lstrcpy32A (infoPtr->items[iItem].pszText, phdi->pszText);
-        infoPtr->items[iItem].cchTextMax = phdi->cchTextMax;
+	if (phdi->pszText != LPSTR_TEXTCALLBACK32A) {
+	    INT32 len = lstrlen32A (phdi->pszText);
+	    if (lpItem->pszText)
+		COMCTL32_Free (lpItem->pszText);
+	    lpItem->pszText = COMCTL32_Alloc (len+1);
+	    lstrcpy32A (lpItem->pszText, phdi->pszText);
+	}
+	else
+	    lpItem->pszText = LPSTR_TEXTCALLBACK32A;
     }
 
-    if (phdi->mask & HDI_WIDTH) {
-	infoPtr->items[iItem].cxy = phdi->cxy;
-	infoPtr->items[iItem].mask  |= HDI_WIDTH;
-    }
+    if (phdi->mask & HDI_WIDTH)
+	lpItem->cxy = phdi->cxy;
 
-    if (phdi->mask & HDI_IMAGE) {
-	infoPtr->items[iItem].iImage = phdi->iImage;
-	infoPtr->items[iItem].mask  |= HDI_IMAGE;
-    }
+    if (phdi->mask & HDI_IMAGE)
+	lpItem->iImage = phdi->iImage;
 
-    if (phdi->mask & HDI_ORDER) {
-	infoPtr->items[iItem].iOrder = phdi->iOrder;
-	infoPtr->items[iItem].mask  |= HDI_ORDER;
-    }
+    if (phdi->mask & HDI_ORDER)
+	lpItem->iOrder = phdi->iOrder;
 
-    HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A, iItem);
+    HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A, nItem);
 
     HEADER_SetItemBounds (wndPtr);
     hdc = GetDC32 (wndPtr->hwndSelf);
@@ -870,8 +844,7 @@
     HFONT32 hOldFont;
     HDC32   hdc;
 
-    infoPtr = (HEADER_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                        sizeof(HEADER_INFO));
+    infoPtr = (HEADER_INFO *)COMCTL32_Alloc (sizeof(HEADER_INFO));
     wndPtr->wExtra[0] = (DWORD)infoPtr;
 
     infoPtr->uNumItem = 0;
@@ -902,26 +875,28 @@
 HEADER_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
-    INT32 iItem;
+    HEADER_ITEM *lpItem;
+    INT32 nItem;
 
     if (infoPtr->items) {
-        for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) {
-            if (infoPtr->items[iItem].pszText)
-                HeapFree (GetProcessHeap (), 0, infoPtr->items[iItem].pszText);
+	lpItem = (HEADER_ITEM*)infoPtr->items;
+        for (nItem = 0; nItem < infoPtr->uNumItem; nItem++, lpItem++) {
+	    if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACK32A))
+		COMCTL32_Free (lpItem->pszText);
         }
-        HeapFree (GetProcessHeap (), 0, infoPtr->items);
+        COMCTL32_Free (infoPtr->items);
     }
 
     if (infoPtr->himl)
 	ImageList_Destroy (infoPtr->himl);
 
-    HeapFree (GetProcessHeap (), 0, infoPtr);
+    COMCTL32_Free (infoPtr);
 
     return 0;
 }
 
 
-static LRESULT
+static __inline__ LRESULT
 HEADER_GetFont (WND *wndPtr)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
@@ -935,16 +910,16 @@
 {
     POINT32 pt;
     UINT32  flags;
-    INT32   iItem;
+    INT32   nItem;
 
     pt.x = (INT32)LOWORD(lParam); 
     pt.y = (INT32)HIWORD(lParam);
-    HEADER_InternalHitTest (wndPtr, &pt, &flags, &iItem);
+    HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
 
     if ((wndPtr->dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER))
-	HEADER_SendHeaderNotify (wndPtr, HDN_ITEMDBLCLICK32A, iItem);
+	HEADER_SendHeaderNotify (wndPtr, HDN_ITEMDBLCLICK32A, nItem);
     else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
-	HEADER_SendHeaderNotify (wndPtr, HDN_DIVIDERDBLCLICK32A, iItem);
+	HEADER_SendHeaderNotify (wndPtr, HDN_DIVIDERDBLCLICK32A, nItem);
 
     return 0;
 }
@@ -956,45 +931,45 @@
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
     POINT32 pt;
     UINT32  flags;
-    INT32   iItem;
+    INT32   nItem;
     HDC32   hdc;
 
     pt.x = (INT32)LOWORD(lParam); 
     pt.y = (INT32)HIWORD(lParam);
-    HEADER_InternalHitTest (wndPtr, &pt, &flags, &iItem);
+    HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
 
     if ((wndPtr->dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER)) {
 	SetCapture32 (wndPtr->hwndSelf);
 	infoPtr->bCaptured = TRUE;   
 	infoPtr->bPressed  = TRUE;
-	infoPtr->iMoveItem = iItem;
+	infoPtr->iMoveItem = nItem;
 
-	infoPtr->items[iItem].bDown = TRUE;
+	infoPtr->items[nItem].bDown = TRUE;
 
 	/* Send WM_CUSTOMDRAW */
 	hdc = GetDC32 (wndPtr->hwndSelf);
-	HEADER_RefreshItem (wndPtr, hdc, iItem);
+	HEADER_RefreshItem (wndPtr, hdc, nItem);
 	ReleaseDC32 (wndPtr->hwndSelf, hdc);
 
-	TRACE (header, "Pressed item %d!\n", iItem);
+	TRACE (header, "Pressed item %d!\n", nItem);
     } 
     else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN)) {
-	if (!(HEADER_SendHeaderNotify (wndPtr, HDN_BEGINTRACK32A, iItem))) {
+	if (!(HEADER_SendHeaderNotify (wndPtr, HDN_BEGINTRACK32A, nItem))) {
 	    SetCapture32 (wndPtr->hwndSelf);
 	    infoPtr->bCaptured = TRUE;   
 	    infoPtr->bTracking = TRUE;
-	    infoPtr->iMoveItem = iItem;
-	    infoPtr->nOldWidth = infoPtr->items[iItem].cxy;
-	    infoPtr->xTrackOffset = infoPtr->items[iItem].rect.right - pt.x;
+	    infoPtr->iMoveItem = nItem;
+	    infoPtr->nOldWidth = infoPtr->items[nItem].cxy;
+	    infoPtr->xTrackOffset = infoPtr->items[nItem].rect.right - pt.x;
 
 	    if (!(wndPtr->dwStyle & HDS_FULLDRAG)) {
-		infoPtr->xOldTrack = infoPtr->items[iItem].rect.right;
+		infoPtr->xOldTrack = infoPtr->items[nItem].rect.right;
 		hdc = GetDC32 (wndPtr->hwndSelf);
 		HEADER_DrawTrackLine (wndPtr, hdc, infoPtr->xOldTrack);
 		ReleaseDC32 (wndPtr->hwndSelf, hdc);
 	    }
 
-	    TRACE (header, "Begin tracking item %d!\n", iItem);
+	    TRACE (header, "Begin tracking item %d!\n", nItem);
 	}
     }
 
@@ -1008,15 +983,15 @@
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
     POINT32 pt;
     UINT32  flags;
-    INT32   iItem, nWidth;
+    INT32   nItem, nWidth;
     HDC32   hdc;
 
     pt.x = (INT32)LOWORD(lParam);
     pt.y = (INT32)HIWORD(lParam);
-    HEADER_InternalHitTest (wndPtr, &pt, &flags, &iItem);
+    HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
 
     if (infoPtr->bPressed) {
-	if ((iItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER)) {
+	if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER)) {
 	    infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
 	    hdc = GetDC32 (wndPtr->hwndSelf);
 	    HEADER_RefreshItem (wndPtr, hdc, infoPtr->iMoveItem);
@@ -1040,8 +1015,7 @@
 	    if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, infoPtr->iMoveItem))
 		infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
 	    else {
-		nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left +
-		infoPtr->xTrackOffset;
+		nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
 		if (nWidth < 0)
 		    nWidth = 0;
 		infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
@@ -1071,16 +1045,16 @@
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
     POINT32 pt;
     UINT32  flags;
-    INT32   iItem, nWidth;
+    INT32   nItem, nWidth;
     HDC32   hdc;
 
     pt.x = (INT32)LOWORD(lParam);
     pt.y = (INT32)HIWORD(lParam);
-    HEADER_InternalHitTest (wndPtr, &pt, &flags, &iItem);
+    HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
 
     if ((wndPtr->dwStyle & HDS_BUTTONS) && (wndPtr->dwStyle & HDS_HOTTRACK)) {
 	if (flags & (HHT_ONHEADER | HHT_ONDIVIDER | HHT_ONDIVOPEN))
-	    infoPtr->iHotItem = iItem;
+	    infoPtr->iHotItem = nItem;
 	else
 	    infoPtr->iHotItem = -1;
 	hdc = GetDC32 (wndPtr->hwndSelf);
@@ -1090,7 +1064,7 @@
 
     if (infoPtr->bCaptured) {
 	if (infoPtr->bPressed) {
-	    if ((iItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER))
+	    if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER))
 		infoPtr->items[infoPtr->iMoveItem].bDown = TRUE;
 	    else
 		infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
@@ -1105,8 +1079,7 @@
 		if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, infoPtr->iMoveItem))
 		    infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
 		else {
-		    nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left +
-		    infoPtr->xTrackOffset;
+		    nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
 		    if (nWidth < 0)
 			nWidth = 0;
 		    infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
@@ -1170,14 +1143,14 @@
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
     POINT32 pt;
     UINT32  flags;
-    INT32   iItem;
+    INT32   nItem;
 
     TRACE (header, "code=0x%X  id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
 
     GetCursorPos32 (&pt);
     ScreenToClient32 (wndPtr->hwndSelf, &pt);
 
-    HEADER_InternalHitTest (wndPtr, &pt, &flags, &iItem);
+    HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
 
     if (flags == HHT_ONDIVIDER)
         SetCursor32 (infoPtr->hcurDivider);
@@ -1238,18 +1211,25 @@
 	case HDM_GETITEM32A:
 	    return HEADER_GetItem32A (wndPtr, wParam, lParam);
 
+//	case HDM_GETITEM32W:
+
 	case HDM_GETITEMCOUNT:
 	    return HEADER_GetItemCount (wndPtr);
 
 	case HDM_GETITEMRECT:
 	    return HEADER_GetItemRect (wndPtr, wParam, lParam);
 
+//	case HDM_GETORDERARRAY:
+//	case HDM_GETUNICODEFORMAT:
+
 	case HDM_HITTEST:
 	    return HEADER_HitTest (wndPtr, wParam, lParam);
 
 	case HDM_INSERTITEM32A:
 	    return HEADER_InsertItem32A (wndPtr, wParam, lParam);
 
+//	case HDM_INSERTITEM32W:
+
 	case HDM_LAYOUT:
 	    return HEADER_Layout (wndPtr, wParam, lParam);
 
@@ -1259,6 +1239,10 @@
 	case HDM_SETITEM32A:
 	    return HEADER_SetItem32A (wndPtr, wParam, lParam);
 
+//	case HDM_SETITEM32W:
+//	case HDM_SETORDERARRAY:
+//	case HDM_SETUNICODEFORMAT:
+
 
         case WM_CREATE:
             return HEADER_Create (wndPtr, wParam, lParam);
diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c
index 6fbbd33..0aec07d 100644
--- a/dlls/comctl32/imagelist.c
+++ b/dlls/comctl32/imagelist.c
@@ -5,9 +5,7 @@
  *
  *  TODO:
  *    - Fix xBitmap and yBitmap in ImageList_DrawIndirect.
- *    - Fix ILD_TRANSPARENT error in ImageList_DrawIndirect.
- *    - Fix ImageList_GetIcon (might be a result of the
- *      ILD_TRANSPARENT error in ImageList_DrawIndirect).
+ *    - Fix ImageList_GetIcon.
  *    - Fix drag functions.
  *    - Fix ImageList_Read and ImageList_Write.
  *    - Fix ImageList_SetFilter (undocumented).
@@ -146,11 +144,11 @@
 {
     HDC32    hdcSrc, hdcDst;
     INT32    nFirstIndex, nImageCount;
-    INT32    nStartX, nRunX, nRunY;
+    INT32    nStartX;
     BITMAP32 bmp;
 
-    if (himl == NULL) return (-1);
-    if (hbmImage == 0) return (-1);
+    if (!himl || !hbmImage)
+	return -1;
 
     GetObject32A (hbmImage, sizeof(BITMAP32), (LPVOID)&bmp);
     nImageCount = bmp.bmWidth / himl->cx;
@@ -158,56 +156,33 @@
     if (himl->cCurImage + nImageCount >= himl->cMaxImage)
         IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
 
+    nStartX = himl->cCurImage * himl->cx;
+
     hdcSrc = CreateCompatibleDC32 (0);
     hdcDst = CreateCompatibleDC32 (0);
 
+    /* copy image bitmap */
     SelectObject32 (hdcDst, himl->hbmImage);
     SelectObject32 (hdcSrc, hbmImage);
-
     BitBlt32 (hdcDst, himl->cCurImage * himl->cx, 0,
               bmp.bmWidth, himl->cy, hdcSrc, 0, 0, SRCCOPY);
           
     if (himl->hbmMask) {
         if (hbmMask) {
+	    /* copy mask bitmap */
             SelectObject32 (hdcDst, himl->hbmMask);
             SelectObject32 (hdcSrc, hbmMask);
-            BitBlt32 (hdcDst, himl->cCurImage * himl->cx, 0,
-                      bmp.bmWidth, himl->cy, hdcSrc, 0, 0, SRCCOPY);
-
-            /* fix transparent areas of the image bitmap*/
-            SelectObject32 (hdcSrc, himl->hbmMask);
-            SelectObject32 (hdcDst, himl->hbmImage);
-            nStartX = himl->cCurImage * himl->cx;
-
-            for (nRunY = 0; nRunY < himl->cy; nRunY++) {
-                for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++) {
-                    if (GetPixel32 (hdcSrc, nStartX + nRunX, nRunY) !=
-                        RGB(0, 0, 0))
-                        SetPixel32 (hdcDst, nStartX + nRunX, nRunY, 
-                                    RGB(0, 0, 0));
-                }
-            }
+            BitBlt32 (hdcDst, nStartX, 0, bmp.bmWidth, himl->cy,
+		      hdcSrc, 0, 0, SRCCOPY);
         }
         else {
-            /* create mask from the imagelist's background color */
+	    /* copy monochrome image to the mask bitmap */
             SelectObject32 (hdcDst, himl->hbmMask);
-            SelectObject32 (hdcSrc, himl->hbmImage);
-            nStartX = himl->cCurImage * himl->cx;
-            for (nRunY = 0; nRunY < himl->cy; nRunY++) {
-                for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++) {
-                    if (GetPixel32 (hdcSrc, nStartX + nRunX, nRunY) ==
-                        himl->clrBk)
-                    {
-                        SetPixel32 (hdcSrc, nStartX + nRunX, nRunY, 
-                                    RGB(0, 0, 0));
-                        SetPixel32 (hdcDst, nStartX + nRunX, nRunY, 
-                                    RGB(255, 255, 255));
-                    }
-                    else
-                        SetPixel32 (hdcDst, nStartX + nRunX, nRunY, 
-                                    RGB(0, 0, 0));        
-                }
-            }
+            SelectObject32 (hdcSrc, hbmImage);
+	    SetBkColor32 (hdcSrc, GetNearestColor32 (hdcSrc,
+			  GetPixel32 (hdcSrc, 0, 0)));
+	    BitBlt32 (hdcDst, nStartX, 0, bmp.bmWidth, himl->cy,
+		      hdcSrc, nStartX, 0, SRCCOPY);
         }
     }
 
@@ -217,7 +192,7 @@
     nFirstIndex = himl->cCurImage;
     himl->cCurImage += nImageCount;
 
-    return (nFirstIndex);
+    return nFirstIndex;
 }
 
 
@@ -249,9 +224,9 @@
  * specified bitmap using the mask color.
  *
  * PARAMS
- *     himl     [I] image list handle.
- *     hbmImage [I] image bitmap handle.
- *     clrMask  [I] mask color.
+ *     himl    [I] handle to image list.
+ *     hBitmap [I] handle to bitmap
+ *     clrMask [I] mask color.
  *
  * RETURNS
  *     Success: Index of the first new image.
@@ -259,20 +234,18 @@
  */
 
 INT32 WINAPI
-ImageList_AddMasked (HIMAGELIST himl, HBITMAP32 hbmImage, COLORREF clrMask)
+ImageList_AddMasked (HIMAGELIST himl, HBITMAP32 hBitmap, COLORREF clrMask)
 {
-    HDC32    hdcImageList, hdcImage, hdcMask;
+    HDC32    hdcImage, hdcMask, hdcBitmap;
     INT32    nIndex, nImageCount;
     BITMAP32 bmp;
-    INT32    nStartX, nRunX, nRunY;
-    COLORREF bkColor;
 
     if (himl == NULL)
-	return (-1);
+	return -1;
 
-    bkColor = (clrMask == CLR_NONE) ? himl->clrBk : clrMask;
+    if (!GetObject32A (hBitmap, sizeof(BITMAP32), &bmp))
+	return -1;
 
-    GetObject32A (hbmImage, sizeof(BITMAP32), &bmp);
     nImageCount = bmp.bmWidth / himl->cx;
 
     if (himl->cCurImage + nImageCount >= himl->cMaxImage)
@@ -281,39 +254,34 @@
     nIndex = himl->cCurImage;
     himl->cCurImage += nImageCount;
 
-    hdcImageList = CreateCompatibleDC32 (0);
-    hdcImage = CreateCompatibleDC32 (0);
+    hdcImage  = CreateCompatibleDC32 (0);
+    hdcBitmap = CreateCompatibleDC32 (0);
 
-    SelectObject32 (hdcImageList, himl->hbmImage);
-    SelectObject32 (hdcImage, hbmImage);
-    BitBlt32 (hdcImageList, nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
-              hdcImage, 0, 0, SRCCOPY);
+    SelectObject32 (hdcBitmap, hBitmap);
+    SelectObject32 (hdcImage, himl->hbmImage);
+    BitBlt32 (hdcImage, nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
+              hdcBitmap, 0, 0, SRCCOPY);
 
     if (himl->hbmMask) {
-        /* create Mask */
+	COLORREF bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
+	    GetNearestColor32 (hdcBitmap, GetPixel32 (hdcBitmap, 0, 0));
+
+	/* create mask from image */
         hdcMask = CreateCompatibleDC32 (0);
         SelectObject32 (hdcMask, himl->hbmMask);
-        nStartX = nIndex * himl->cx;
-        for (nRunY = 0; nRunY < himl->cy; nRunY++) {
-            for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++) {
-                if (GetPixel32 (hdcImageList, nStartX + nRunX, nRunY) ==
-                    bkColor) {
-                    SetPixel32 (hdcImageList, nStartX + nRunX, nRunY,
-                                RGB(0, 0, 0));
-                    SetPixel32 (hdcMask, nStartX + nRunX, nRunY,
-                                RGB(255, 255, 255));
-                }
-                else
-                    SetPixel32 (hdcMask, nStartX + nRunX, nRunY, RGB(0, 0, 0));
-            }
-        }
+
+	/* create monochrome image to the mask bitmap */
+	SetBkColor32 (hdcBitmap, bkColor);
+	BitBlt32 (hdcMask, nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
+		  hdcBitmap, 0, 0, SRCCOPY);
+
         DeleteDC32 (hdcMask);
     }
 
-    DeleteDC32 (hdcImageList);
     DeleteDC32 (hdcImage);
+    DeleteDC32 (hdcBitmap);
   
-    return (nIndex);
+    return nIndex;
 }
 
 
@@ -969,6 +937,8 @@
     {
 	/* draw the mask */
 	SelectObject32 (hdcImageList, himlLocal->hbmMask);
+	SetBkColor32 (hdcImageList, RGB(255, 255, 255));
+	SetTextColor32 (hdcImageList, RGB(0, 0, 0));
 	BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
 		  hdcImageList, himlLocal->cx * pimldp->i, 0,
 		  bMaskTrans ? SRCAND : SRCCOPY);
@@ -989,8 +959,7 @@
         }
 
         BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
-                  hdcImageList, himlLocal->cx * pimldp->i, 0,
-                  SRCPAINT);
+                  hdcImageList, himlLocal->cx * pimldp->i, 0, SRCPAINT);
 
         if (bBlend25 || bBlend50)
         {
@@ -1225,7 +1194,7 @@
 {
     ICONINFO ii;
     HICON32  hIcon;
-    HDC32    hdc;
+    HDC32    hdcSrc, hdcDst;
     INT32    nWidth, nHeight;
 
     if (himl == NULL) return 0;
@@ -1234,27 +1203,36 @@
     nWidth = GetSystemMetrics32 (SM_CXICON);
     nHeight = GetSystemMetrics32 (SM_CYICON);
 
+    hdcSrc = CreateCompatibleDC32(0);
+    hdcDst = CreateCompatibleDC32(0);
+
     ii.fIcon = TRUE;
     ii.xHotspot = 0;
     ii.yHotspot = 0;
-    ii.hbmMask  = CreateBitmap32 (nWidth, nHeight, 1, 1, NULL);
-    ii.hbmColor = CreateBitmap32 (nWidth, nHeight, 1, himl->uBitsPixel, NULL);
+    ii.hbmMask  = CreateCompatibleBitmap32 (hdcDst, nWidth, nHeight);
+    ii.hbmColor = CreateCompatibleBitmap32 (hdcDst, nWidth, nHeight);
 
-    hdc = CreateCompatibleDC32(0);
-
-    /* draw image*/
-    SelectObject32 (hdc, ii.hbmColor);
-    PatBlt32 (hdc, 0, 0, nWidth, nHeight, BLACKNESS);
-    ImageList_Draw (himl, i, hdc, 0, 0, fStyle | ILD_TRANSPARENT);
 
     /* draw mask*/
-    SelectObject32 (hdc, ii.hbmMask);
-    PatBlt32 (hdc, 0, 0, nWidth, nHeight, WHITENESS);
-    ImageList_Draw (himl, i, hdc, 0, 0, fStyle | ILD_MASK);
+    SelectObject32 (hdcDst, ii.hbmMask);
+    if (himl->hbmMask) {
+	SelectObject32 (hdcSrc, himl->hbmMask);
+	BitBlt32 (hdcDst, 0, 0, nWidth, nHeight,
+		  hdcSrc, i * himl->cx, 0, SRCCOPY);
+    }
+    else
+	PatBlt32 (hdcDst, 0, 0, nWidth, nHeight, BLACKNESS);
+
+    /* draw image*/
+    SelectObject32 (hdcDst, ii.hbmColor);
+    SelectObject32 (hdcSrc, himl->hbmImage);
+    BitBlt32 (hdcDst, 0, 0, nWidth, nHeight,
+	      hdcSrc, i * himl->cx, 0, SRCCOPY);
 
     hIcon = CreateIconIndirect (&ii);    
 
-    DeleteDC32 (hdc);
+    DeleteDC32 (hdcSrc);
+    DeleteDC32 (hdcDst);
     DeleteObject32 (ii.hbmMask);
     DeleteObject32 (ii.hbmColor);
 
@@ -2040,7 +2018,7 @@
  * Sets the image size of the bitmap and deletes all images.
  *
  * PARAMS
- *     himl [I] image list handle
+ *     himl [I] handle to image list
  *     cx   [I] image width
  *     cy   [I] image height
  *
@@ -2054,7 +2032,8 @@
 {
     INT32 nCount;
 
-    if (himl == NULL) return (FALSE);
+    if (!himl)
+	return FALSE;
 
     /* remove all images*/
     himl->cMaxImage  = himl->cInitial + himl->cGrow;
@@ -2088,7 +2067,7 @@
  * Resizes an image list to the specified number of images.
  *
  * PARAMS
- *     himl        [I] image list handle
+ *     himl        [I] handle to image list
  *     iImageCount [I] number of images in the image list
  *
  * RETURNS
@@ -2103,9 +2082,12 @@
     HBITMAP32 hbmNewBitmap;
     INT32     nNewCount, nCopyCount;
 
-    if (himl == NULL) return (FALSE);
-    if (himl->cCurImage <= iImageCount) return (FALSE);
-    if (himl->cMaxImage > iImageCount) return (TRUE);
+    if (!himl)
+	return FALSE;
+    if (himl->cCurImage <= iImageCount)
+	return FALSE;
+    if (himl->cMaxImage > iImageCount)
+	return TRUE;
 
     nNewCount = iImageCount + himl->cGrow;
     nCopyCount = _MIN(himl->cCurImage, iImageCount);
@@ -2126,7 +2108,7 @@
     }
     else
     {
-        WARN (imagelist, "Could not create new image bitmap !\n");
+        ERR (imagelist, "Could not create new image bitmap !\n");
     }
 
     if (himl->hbmMask)
@@ -2144,7 +2126,7 @@
         }
         else
         {
-            WARN (imagelist, "Could not create new mask bitmap!\n");
+            ERR (imagelist, "Could not create new mask bitmap!\n");
         }
     }
 
@@ -2156,7 +2138,7 @@
     if (himl->cCurImage > nCopyCount)
         himl->cCurImage = nCopyCount;
 
-    return (TRUE);
+    return TRUE;
 }
 
 
@@ -2178,8 +2160,12 @@
 BOOL32 WINAPI
 ImageList_SetOverlayImage (HIMAGELIST himl, INT32 iImage, INT32 iOverlay)
 {
-    if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE)) return (FALSE);
-    if ((iImage < 0) || (iImage > himl->cCurImage)) return (FALSE);
+    if (!himl)
+	return FALSE;
+    if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
+	return FALSE;
+    if ((iImage < 0) || (iImage > himl->cCurImage))
+	return FALSE;
     
     himl->nOvlIdx[iOverlay - 1] = iImage;
     return TRUE;
@@ -2210,9 +2196,10 @@
 BOOL32 WINAPI
 ImageList_Write (HIMAGELIST himl, LPSTREAM32 pstm)
 {
-    FIXME (imagelist, "empty stub!\n");
+    if (!himl)
+	return FALSE;
 
-    if (himl == NULL) return (FALSE);
+    FIXME (imagelist, "empty stub!\n");
 
     return FALSE;
 }
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 91fe4cb..0c24d9c 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -9,8 +9,8 @@
  *     Eric <ekohl@abo.rhein-zeitung.de>
  *
  * TODO:
- *   - All messages.
- *   - All notifications.
+ *   - Most messages.
+ *   - Most notifications.
  */
 
 #include "windows.h"
@@ -26,7 +26,7 @@
 static VOID
 LISTVIEW_Refresh (WND *wndPtr, HDC32 hdc)
 {
-    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+//    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
 
 
 
@@ -34,6 +34,124 @@
 
 
 
+// << LISTVIEW_ApproximateViewRect >>
+// << LISTVIEW_Arrange >>
+// << LISTVIEW_CreateDragImage >>
+
+
+static LRESULT
+LISTVIEW_DeleteAllItems (WND *wndPtr)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    INT32 nItem;
+    LISTVIEW_ITEM *lpItem;
+    NMLISTVIEW nmlv;
+    BOOL32 bNotify;
+
+    if (infoPtr->nItemCount == 0)
+	return TRUE;
+
+    TRACE (listview, "\n");
+
+    /* send LVN_DELETEALLITEMS notification */
+    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code     = LVN_DELETEALLITEMS;
+    nmlv.iItem        = -1;
+    bNotify =
+	!(BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+				 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    nmlv.hdr.code     = LVN_DELETEITEM;
+
+    for (nItem = 0; nItem < infoPtr->nItemCount; nItem++) {
+	/* send notification */
+	if (bNotify) {
+	    nmlv.iItem = nItem;
+	    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+			    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+	}
+
+	/* get item pointer */
+	lpItem = (LISTVIEW_ITEM*)DPA_GetPtr (infoPtr->hdpaItems, nItem);
+
+	/* delete item strings */
+	if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACK32A))
+	    COMCTL32_Free (lpItem->pszText);
+
+	/* free item data */
+	COMCTL32_Free (lpItem);
+    }
+
+    DPA_DeleteAllPtrs (infoPtr->hdpaItems);
+    infoPtr->nItemCount = 0;
+
+    return TRUE;
+}
+
+
+static LRESULT
+LISTVIEW_DeleteColumn (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    INT32 nColumn = (INT32)wParam;
+
+    /* FIXME ??? */
+    if (infoPtr->nItemCount > 0)
+	return FALSE;
+
+    if (!SendMessage32A (infoPtr->hwndHeader, HDM_DELETEITEM, wParam, 0))
+	return FALSE;
+
+    infoPtr->nColumnCount--;
+
+    FIXME (listview, "semi stub!\n");
+
+    return TRUE;
+}
+
+
+static LRESULT
+LISTVIEW_DeleteItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    INT32 nItem = (INT32)wParam;
+    LISTVIEW_ITEM *lpItem;
+    NMLISTVIEW nmlv;
+
+    if ((nItem < 0) || (nItem >= infoPtr->nItemCount))
+	return FALSE;
+
+    TRACE (listview, "(%d)\n", nItem);
+
+    /* send notification */
+    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code     = LVN_DELETEITEM;
+    nmlv.iItem        = nItem;
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    /* remove from item array */
+    lpItem = (LISTVIEW_ITEM*)DPA_DeletePtr (infoPtr->hdpaItems, nItem);
+
+    /* delete item strings */
+    if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACK32A))
+	COMCTL32_Free (lpItem->pszText);
+
+    /* free item data */
+    COMCTL32_Free (lpItem);
+
+    infoPtr->nItemCount--;
+
+    return TRUE;
+}
+
+
+// << LISTVIEW_EditLabel >>
+// << LISTVIEW_EnsureVisible >>
 // << LISTVIEW_FindItem >>
 
 
@@ -47,6 +165,75 @@
 
 
 // << LISTVIEW_GetBkImage >>
+// << LISTVIEW_GetCallbackMask >>
+
+
+static LRESULT
+LISTVIEW_GetColumn32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVCOLUMN32A lpcol = (LPLVCOLUMN32A)lParam;
+    INT32 nIndex = (INT32)wParam;
+    HDITEM32A hdi;
+
+    if (!lpcol)
+	return FALSE;
+
+    TRACE (listview, "(%d %p)\n", nIndex, lpcol);
+
+    ZeroMemory (&hdi, sizeof(HDITEM32A));
+
+    if (lpcol->mask & LVCF_FMT)
+	hdi.mask |= HDI_FORMAT;
+
+    if (lpcol->mask & LVCF_WIDTH)
+        hdi.mask |= HDI_WIDTH;
+
+    if (lpcol->mask & LVCF_TEXT)
+        hdi.mask |= (HDI_TEXT | HDI_FORMAT);
+
+    if (lpcol->mask & LVCF_IMAGE)
+        hdi.mask |= HDI_IMAGE;
+
+    if (lpcol->mask & LVCF_ORDER)
+        hdi.mask |= HDI_ORDER;
+
+    if (!SendMessage32A (infoPtr->hwndHeader, HDM_GETITEM32A,
+		    wParam, (LPARAM)&hdi))
+	return FALSE;
+
+    if (lpcol->mask & LVCF_FMT) {
+	lpcol->fmt = 0;
+
+	if (hdi.fmt & HDF_LEFT)
+	    lpcol->fmt |= LVCFMT_LEFT;
+	else if (hdi.fmt & HDF_RIGHT)
+	    lpcol->fmt |= LVCFMT_RIGHT;
+	else if (hdi.fmt & HDF_CENTER)
+	    lpcol->fmt |= LVCFMT_CENTER;
+
+	if (hdi.fmt & HDF_IMAGE)
+	    lpcol->fmt |= LVCFMT_COL_HAS_IMAGES;
+    }
+
+    if (lpcol->mask & LVCF_WIDTH)
+	lpcol->cx = hdi.cxy;
+
+    if ((lpcol->mask & LVCF_TEXT) && (lpcol->pszText))
+	lstrcpyn32A (lpcol->pszText, hdi.pszText, lpcol->cchTextMax);
+
+    if (lpcol->mask & LVCF_IMAGE)
+	lpcol->iImage = hdi.iImage;
+
+    if (lpcol->mask & LVCF_ORDER)
+	lpcol->iOrder = hdi.iOrder;
+
+    return TRUE;
+}
+
+
+// << LISTVIEW_GetColumn32W >>
+// << LISTVIEW_GetColumnOrderArray >>
 
 
 __inline__ static LRESULT
@@ -64,6 +251,9 @@
 }
 
 
+// << LISTVIEW_GetCountPerPage >>
+// << LISTVIEW_GetEditControl >>
+// << LISTVIEW_GetExtendedListviewStyle >>
 
 
 __inline__ static LRESULT
@@ -75,6 +265,11 @@
 }
 
 
+// << LISTVIEW_GetHotCursor >>
+// << LISTVIEW_GetHotItem >>
+// << LISTVIEW_GetHoverTime >>
+
+
 static LRESULT
 LISTVIEW_GetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
@@ -97,19 +292,62 @@
 }
 
 
+// << LISTVIEW_GetISearchString >>
+
+
 static LRESULT
 LISTVIEW_GetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVITEM32A lpItem = (LPLVITEM32A)lParam;
+    LISTVIEW_ITEM *lpRow, *lpSubItem;
 
-    FIXME (listview, "(0x%08x) empty stub!\n", wParam);
+    if (!lpItem)
+	return FALSE;
 
+    if ((lpItem->iItem < 0) || (lpItem->iItem >= infoPtr->nItemCount))
+	return FALSE;
 
+    if ((lpItem->iSubItem < 0) || (lpItem->iSubItem >= infoPtr->nColumnCount))
+	return FALSE;
+
+    FIXME (listview, "(%d %d %p)\n",
+	   lpItem->iItem, lpItem->iSubItem, lpItem);
+
+    lpRow = DPA_GetPtr (infoPtr->hdpaItems, lpItem->iItem);
+    if (!lpRow)
+	return FALSE;
+
+    lpSubItem = &lpRow[lpItem->iSubItem];
+    if (!lpSubItem)
+	return FALSE;
+
+    if (lpItem->mask & LVIF_STATE)
+	lpItem->state = lpSubItem->state & lpItem->stateMask;
+
+    if (lpItem->mask & LVIF_TEXT) {
+	if (lpSubItem->pszText == LPSTR_TEXTCALLBACK32A)
+	    lpItem->pszText = LPSTR_TEXTCALLBACK32A;
+	else
+	    Str_GetPtr32A (lpSubItem->pszText, lpItem->pszText,
+			   lpItem->cchTextMax);
+    }
+
+    if (lpItem->mask & LVIF_IMAGE)
+	 lpItem->iImage = lpSubItem->iImage;
+
+    if (lpItem->mask & LVIF_PARAM)
+	lpItem->lParam = lpSubItem->lParam;
+
+    if (lpItem->mask & LVIF_INDENT)
+	lpItem->iIndent = lpSubItem->iIndent;
 
     return TRUE;
 }
 
 
+// << LISTVIEW_GetItem32W >>
+
 
 __inline__ static LRESULT
 LISTVIEW_GetItemCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
@@ -119,6 +357,93 @@
 }
 
 
+static LRESULT
+LISTVIEW_GetItemPosition (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPPOINT32 lpPt = (LPPOINT32)lParam;
+    INT32 nIndex = (INT32)wParam;
+
+    if (!lpPt)
+	return FALSE;
+    if ((nIndex < 0) || (nIndex >= infoPtr->nItemCount))
+	return FALSE;
+
+    FIXME (listview, "returning position [0,0]!\n");
+    lpPt->x = 0;
+    lpPt->y = 0;
+
+    return TRUE;
+}
+
+
+// << LISTVIEW_GetItemRect >>
+// << LISTVIEW_GetItemSpacing >>
+// << LISTVIEW_GetItemState >>
+
+
+static LRESULT
+LISTVIEW_GetItemText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVITEM32A lpItem = (LPLVITEM32A)lParam;
+    INT32 nItem = (INT32)wParam;
+    LISTVIEW_ITEM *lpRow, *lpSubItem;
+
+    TRACE (listview, "(%d %p)\n", nItem, lpItem);
+
+    lpRow = DPA_GetPtr (infoPtr->hdpaItems, lpItem->iItem);
+    if (!lpRow)
+	return 0;
+
+    lpSubItem = &lpRow[lpItem->iSubItem];
+    if (!lpSubItem)
+	return 0;
+
+    if (lpSubItem->pszText == LPSTR_TEXTCALLBACK32A) {
+	lpItem->pszText = LPSTR_TEXTCALLBACK32A;
+	return 0;
+    }
+    else
+	return Str_GetPtr32A (lpSubItem->pszText, lpItem->pszText,
+			      lpItem->cchTextMax);
+}
+
+
+// << LISTVIEW_GetItemText32A >>
+
+
+static LRESULT
+LISTVIEW_GetNextItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    INT32 nStart = (INT32)wParam;
+    UINT32 uFlags = (UINT32)LOWORD(lParam);
+
+    FIXME (listview, "(%d, 0x%x); empty stub!\n", nStart, uFlags);
+
+
+    return -1;
+}
+
+
+// << LISTVIEW_GetNumberOfWorkAreas >>
+// << LISTVIEW_GetOrigin >>
+
+
+static LRESULT
+LISTVIEW_GetSelectedCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    TRACE (listview, ": empty stub (returns 0)!\n");
+
+    return 0;
+}
+
+
+// << LISTVIEW_GetSelectionMark >>
+
 
 static LRESULT
 LISTVIEW_GetStringWidth32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
@@ -132,7 +457,7 @@
     if (!lpsz)
 	return 0;
 
-    TRACE (listview, "(%s) empty stub!\n", lpsz);
+    TRACE (listview, "(%s)\n", lpsz);
 
     hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
     hdc = GetDC32 (0);
@@ -149,22 +474,42 @@
 
 
 
+__inline__ static LRESULT
+LISTVIEW_GetTextBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    return infoPtr->clrTextBk;
+}
+
+
+__inline__ static LRESULT
+LISTVIEW_GetTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    return infoPtr->clrText;
+}
+
+
 static LRESULT
 LISTVIEW_InsertColumn32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
     LPLVCOLUMN32A lpcol = (LPLVCOLUMN32A)lParam;
+    INT32 nIndex = (INT32)wParam;
     HDITEM32A hdi;
+    INT32 nResult;
 
-    if (!lpcol)
+    if ((!lpcol) || (infoPtr->nItemCount > 0))
 	return -1;
 
-    TRACE (listview, "(%d %p) empty stub!\n", (INT32)wParam, lpcol);
+    FIXME (listview, "(%d %p): semi stub!\n", nIndex, lpcol);
 
     ZeroMemory (&hdi, sizeof(HDITEM32A));
 
     if (lpcol->mask & LVCF_FMT) {
-	if (wParam == 0)
+	if (nIndex == 0)
 	    hdi.fmt |= HDF_LEFT;
 	else if (lpcol->fmt & LVCFMT_LEFT)
 	    hdi.fmt |= HDF_LEFT;
@@ -200,11 +545,90 @@
 	hdi.iOrder = lpcol->iOrder;
     }
 
-    return (LRESULT)SendMessage32A (infoPtr->hwndHeader, HDM_INSERTITEM32A,
-				    wParam, (LPARAM)&hdi);
+    nResult = SendMessage32A (infoPtr->hwndHeader, HDM_INSERTITEM32A,
+			      wParam, (LPARAM)&hdi);
+    if (nResult == -1)
+	return -1;
+
+    infoPtr->nColumnCount++;
+
+    return nResult;
 }
 
 
+// << LISTVIEW_InsertColumn32W >>
+
+
+static LRESULT
+LISTVIEW_InsertItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVITEM32A lpItem = (LPLVITEM32A)lParam;
+    LISTVIEW_ITEM *lpListItem;
+    INT32 nIndex;
+    NMLISTVIEW nmlv;
+
+    if (!lpItem)
+	return -1;
+
+    if ((!infoPtr->nColumnCount) || (lpItem->iSubItem))
+	return -1;
+
+    FIXME (listview, "(%d %p)\n", lpItem->iItem, lpItem);
+
+    lpListItem = (LISTVIEW_ITEM*)COMCTL32_Alloc (infoPtr->nColumnCount * sizeof(LISTVIEW_ITEM));
+    nIndex = DPA_InsertPtr (infoPtr->hdpaItems, lpItem->iItem, lpListItem);
+    if (nIndex == -1)
+	return -1;
+
+    if (lpItem->mask & LVIF_STATE)
+	lpListItem[0].state = lpItem->state;
+
+    if (lpItem->mask & LVIF_TEXT) {
+	if (lpItem->pszText == LPSTR_TEXTCALLBACK32A)
+	    lpListItem[0].pszText = LPSTR_TEXTCALLBACK32A;
+	else
+	    Str_SetPtr32A (&lpListItem[0].pszText, lpItem->pszText);
+    }
+
+    if (lpItem->mask & LVIF_IMAGE)
+	lpListItem[0].iImage = lpItem->iImage;
+
+    if (lpItem->mask & LVIF_PARAM)
+	lpListItem[0].lParam = lpItem->lParam;
+
+    if (lpItem->mask & LVIF_INDENT)
+	lpListItem[0].iIndent = lpItem->iIndent;
+
+    infoPtr->nItemCount++;
+
+    /* send notification */
+    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code     = LVN_INSERTITEM;
+    nmlv.iItem        = nIndex;
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    return nIndex;
+}
+
+
+// << LISTVIEW_InsertItem32W >>
+
+
+static LRESULT
+LISTVIEW_RedrawItems (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+//    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    FIXME (listview, "(%d - %d): empty stub!\n",
+	   (INT32)wParam, (INT32)lParam);
+
+    return TRUE;
+}
+
 
 
 static LRESULT
@@ -212,10 +636,11 @@
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
 
-    if (!(infoPtr)) return FALSE;
+    if (!infoPtr)
+	return FALSE;
 
     /* set background color */
-    TRACE (listview, "0x%06x\n", (COLORREF)lParam);
+    TRACE (listview, "0x%06lx\n", (COLORREF)lParam);
     infoPtr->clrBk = (COLORREF)lParam;
 
     return TRUE;
@@ -223,6 +648,65 @@
 
 
 static LRESULT
+LISTVIEW_SetColumn32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVCOLUMN32A lpcol = (LPLVCOLUMN32A)lParam;
+    INT32 nIndex = (INT32)wParam;
+    HDITEM32A hdi;
+
+    if (!lpcol)
+	return -1;
+
+    FIXME (listview, "(%d %p): semi stub!\n", nIndex, lpcol);
+
+    ZeroMemory (&hdi, sizeof(HDITEM32A));
+
+    if (lpcol->mask & LVCF_FMT) {
+	if (nIndex == 0)
+	    hdi.fmt |= HDF_LEFT;
+	else if (lpcol->fmt & LVCFMT_LEFT)
+	    hdi.fmt |= HDF_LEFT;
+	else if (lpcol->fmt & LVCFMT_RIGHT)
+	    hdi.fmt |= HDF_RIGHT;
+	else if (lpcol->fmt & LVCFMT_CENTER)
+	    hdi.fmt |= HDF_CENTER;
+
+	if (lpcol->fmt & LVCFMT_COL_HAS_IMAGES)
+	    hdi.fmt |= HDF_IMAGE;
+	    
+	hdi.mask |= HDI_FORMAT;
+    }
+
+    if (lpcol->mask & LVCF_WIDTH) {
+        hdi.mask |= HDI_WIDTH;
+	hdi.cxy = lpcol->cx;
+    }
+    
+    if (lpcol->mask & LVCF_TEXT) {
+        hdi.mask |= (HDI_TEXT | HDI_FORMAT);
+	hdi.pszText = lpcol->pszText;
+	hdi.fmt |= HDF_STRING;
+    }
+
+    if (lpcol->mask & LVCF_IMAGE) {
+        hdi.mask |= HDI_IMAGE;
+	hdi.iImage = lpcol->iImage;
+    }
+
+    if (lpcol->mask & LVCF_ORDER) {
+        hdi.mask |= HDI_ORDER;
+	hdi.iOrder = lpcol->iOrder;
+    }
+
+    return (LRESULT)SendMessage32A (infoPtr->hwndHeader, HDM_SETITEM32A,
+				    wParam, (LPARAM)&hdi);
+}
+
+
+
+
+static LRESULT
 LISTVIEW_SetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
@@ -252,6 +736,150 @@
 
 
 
+static LRESULT
+LISTVIEW_SetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVITEM32A lpItem = (LPLVITEM32A)lParam;
+    LISTVIEW_ITEM *lpRow, *lpSubItem;
+    NMLISTVIEW nmlv;
+
+    if (!lpItem)
+	return FALSE;
+
+    if ((lpItem->iItem < 0) || (lpItem->iItem >= infoPtr->nItemCount))
+	return FALSE;
+
+    if ((lpItem->iSubItem < 0) || (lpItem->iSubItem >= infoPtr->nColumnCount))
+	return FALSE;
+
+    /* send LVN_ITEMCHANGING notification */
+    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code     = LVN_ITEMCHANGING;
+    nmlv.iItem        = lpItem->iItem;
+    nmlv.iSubItem     = lpItem->iSubItem;
+    nmlv.uChanged     = lpItem->mask;
+
+    if (!SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+			 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv))
+	return FALSE;
+
+    TRACE (listview, "(%d %d %p)\n",
+	   lpItem->iItem, lpItem->iSubItem, lpItem);
+
+    lpRow = DPA_GetPtr (infoPtr->hdpaItems, lpItem->iItem);
+    if (!lpRow)
+	return FALSE;
+
+    lpSubItem = &lpRow[lpItem->iSubItem];
+    if (!lpSubItem)
+	return FALSE;
+
+    if (lpItem->mask & LVIF_STATE)
+	lpSubItem->state = (lpSubItem->state & lpItem->stateMask) | lpItem->state;
+
+    if (lpItem->mask & LVIF_TEXT) {
+	if (lpItem->pszText == LPSTR_TEXTCALLBACK32A) {
+	    if ((lpSubItem->pszText) &&
+		(lpSubItem->pszText != LPSTR_TEXTCALLBACK32A))
+		COMCTL32_Free (lpSubItem->pszText);
+	    lpSubItem->pszText = LPSTR_TEXTCALLBACK32A;
+	}
+	else {
+	    if (lpSubItem->pszText == LPSTR_TEXTCALLBACK32A)
+		lpSubItem->pszText = NULL;
+	    Str_SetPtr32A (&lpSubItem->pszText, lpItem->pszText);
+	}
+    }
+
+    if (lpItem->mask & LVIF_IMAGE)
+	lpSubItem->iImage = lpItem->iImage;
+
+    if (lpItem->mask & LVIF_PARAM)
+	lpSubItem->lParam = lpItem->lParam;
+
+    if (lpItem->mask & LVIF_INDENT)
+	lpSubItem->iIndent = lpItem->iIndent;
+
+    /* send LVN_ITEMCHANGED notification */
+    nmlv.hdr.code = LVN_ITEMCHANGED;
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    return TRUE;
+}
+
+
+// << LISTVIEW_SetItem32W >>
+// << LISTVIEW_SetItemCount >>
+
+
+static LRESULT
+LISTVIEW_SetItemPosition (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    INT32 nIndex = (INT32)wParam;
+
+    if ((nIndex < 0) || (nIndex >= infoPtr->nItemCount))
+	return FALSE;
+
+    FIXME (listview, "setting position [%d, %d]!\n",
+	   (INT32)LOWORD(lParam), (INT32)HIWORD(lParam));
+
+    /* FIXME: set position */
+
+    return TRUE;
+}
+
+
+static LRESULT
+LISTVIEW_SetTextBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    if (!infoPtr)
+	return FALSE;
+
+    /* set text background color */
+    TRACE (listview, "0x%06lx\n", (COLORREF)lParam);
+    infoPtr->clrTextBk = (COLORREF)lParam;
+
+    return TRUE;
+}
+
+
+static LRESULT
+LISTVIEW_SetTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    if (!infoPtr)
+	return FALSE;
+
+    /* set text color */
+    TRACE (listview, "0x%06lx\n", (COLORREF)lParam);
+    infoPtr->clrText = (COLORREF)lParam;
+
+    return TRUE;
+}
+
+
+
+static LRESULT
+LISTVIEW_SortItems (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+//    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    FIXME (listview, "empty stub!\n");
+
+    /* fake success */
+    return TRUE;
+}
+
+
+
 
 static LRESULT
 LISTVIEW_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
@@ -261,9 +889,13 @@
     LOGFONT32A logFont;
     DWORD dwStyle = WS_CHILD | WS_VISIBLE; 
 
+    TRACE (listview, "styles 0x%08lx 0x%08lx\n",
+	   wndPtr->dwStyle, wndPtr->dwExStyle);
 
     /* initialize info structure */
     infoPtr->clrBk = CLR_NONE;
+    infoPtr->clrText = RGB(0, 0, 0); /* preliminary */
+    infoPtr->clrTextBk = RGB(255, 255, 255); /* preliminary */
 
     if (!(wndPtr->dwStyle & LVS_REPORT) ||
 	 (wndPtr->dwStyle & LVS_NOCOLUMNHEADER))
@@ -286,8 +918,7 @@
     SendMessage32A (infoPtr->hwndHeader, WM_SETFONT,
 		    (WPARAM32)infoPtr->hFont, (LPARAM)TRUE);
 
-
-    infoPtr->hdsaItems = DSA_Create (sizeof(LISTVIEW_ITEM), 10);
+    infoPtr->hdpaItems = DPA_Create (10);
 
     return 0;
 }
@@ -298,7 +929,11 @@
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
 
-    DSA_Destroy (infoPtr->hdsaItems);
+    /* delete all items */
+    LISTVIEW_DeleteAllItems (wndPtr);
+
+    /* destroy dpa */
+    DPA_Destroy (infoPtr->hdpaItems);
 
     /* destroy header */
     if (infoPtr->hwndHeader)
@@ -330,7 +965,8 @@
 	DeleteObject32 (hBrush);
 	return FALSE;
     }
-    return FALSE;
+
+    return TRUE;
 }
 
 
@@ -345,7 +981,78 @@
 
 // << LISTVIEW_HScroll >>
 // << LISTVIEW_KeyDown >>
-// << LISTVIEW_KillFocus >>
+
+
+static LRESULT
+LISTVIEW_KillFocus (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMHDR nmh;
+
+    FIXME (listview, "semi stub!\n");
+
+    nmh.hwndFrom = wndPtr->hwndSelf;
+    nmh.idFrom   = wndPtr->wIDmenu;
+    nmh.code = NM_KILLFOCUS;
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmh);
+
+    infoPtr->bFocus = FALSE;
+
+    return 0;
+}
+
+
+static LRESULT
+LISTVIEW_LButtonDblClk (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMLISTVIEW nmlv;
+
+    FIXME (listview, "semi stub!\n");
+
+    ZeroMemory (&nmlv, sizeof(NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code = NM_DBLCLK;
+    nmlv.iItem    = -1;
+    nmlv.iSubItem = 0;
+    nmlv.ptAction.x = (INT32)LOWORD(lParam);
+    nmlv.ptAction.y = (INT32)HIWORD(lParam);
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    return 0;
+}
+
+
+static LRESULT
+LISTVIEW_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMLISTVIEW nmlv;
+
+    FIXME (listview, "semi stub!\n");
+
+    ZeroMemory (&nmlv, sizeof(NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code = NM_CLICK;
+    nmlv.iItem    = -1;
+    nmlv.iSubItem = 0;
+    nmlv.ptAction.x = (INT32)LOWORD(lParam);
+    nmlv.ptAction.y = (INT32)HIWORD(lParam);
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    if (!infoPtr->bFocus)
+	SetFocus32 (wndPtr->hwndSelf);
+
+    return 0;
+}
 
 
 static LRESULT
@@ -387,6 +1094,25 @@
 
 
 static LRESULT
+LISTVIEW_Notify (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPNMHDR lpnmh = (LPNMHDR)lParam;
+
+    if (lpnmh->hwndFrom == infoPtr->hwndHeader) {
+
+	FIXME (listview, "WM_NOTIFY from header!\n");
+    }
+    else {
+
+	FIXME (listview, "WM_NOTIFY from unknown source!\n");
+    }
+
+    return 0;
+}
+
+
+static LRESULT
 LISTVIEW_Paint (WND *wndPtr, WPARAM32 wParam)
 {
     HDC32 hdc;
@@ -400,6 +1126,73 @@
 }
 
 
+static LRESULT
+LISTVIEW_RButtonDblClk (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMLISTVIEW nmlv;
+
+    FIXME (listview, "semi stub!\n");
+
+    ZeroMemory (&nmlv, sizeof(NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code = NM_RDBLCLK;
+    nmlv.iItem    = -1;
+    nmlv.iSubItem = 0;
+    nmlv.ptAction.x = (INT32)LOWORD(lParam);
+    nmlv.ptAction.y = (INT32)HIWORD(lParam);
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    return 0;
+}
+
+
+static LRESULT
+LISTVIEW_RButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMLISTVIEW nmlv;
+
+    FIXME (listview, "semi stub!\n");
+
+    ZeroMemory (&nmlv, sizeof(NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code = NM_RCLICK;
+    nmlv.iItem    = -1;
+    nmlv.iSubItem = 0;
+    nmlv.ptAction.x = (INT32)LOWORD(lParam);
+    nmlv.ptAction.y = (INT32)HIWORD(lParam);
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    return 0;
+}
+
+
+static LRESULT
+LISTVIEW_SetFocus (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMHDR nmh;
+
+    FIXME (listview, "semi stub!\n");
+
+    nmh.hwndFrom = wndPtr->hwndSelf;
+    nmh.idFrom   = wndPtr->wIDmenu;
+    nmh.code = NM_SETFOCUS;
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmh);
+
+    infoPtr->bFocus = TRUE;
+
+    return 0;
+}
 
 
 static LRESULT
@@ -433,24 +1226,28 @@
 LISTVIEW_Size (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
-    HDLAYOUT hl;
-    WINDOWPOS32 wp;
-    RECT32 rc;
-
-    rc.top = 0;
-    rc.left = 0;
-    rc.right = LOWORD(lParam);
-    rc.bottom = HIWORD(lParam);
-
-    hl.prc = &rc;
-    hl.pwpos = &wp;
-    SendMessage32A (infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl);
-
-    SetWindowPos32 (infoPtr->hwndHeader, wndPtr->hwndSelf,
-		    wp.x, wp.y, wp.cx, wp.cy, wp.flags);
 
     GetClientRect32 (wndPtr->hwndSelf, &infoPtr->rcList);
-    infoPtr->rcList.top += wp.cy;
+
+    if (wndPtr->dwStyle & LVS_REPORT) {
+	HDLAYOUT hl;
+	WINDOWPOS32 wp;
+	RECT32 rc;
+
+	rc.top = 0;
+	rc.left = 0;
+	rc.right = LOWORD(lParam);
+	rc.bottom = HIWORD(lParam);
+
+	hl.prc = &rc;
+	hl.pwpos = &wp;
+	SendMessage32A (infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl);
+
+	SetWindowPos32 (infoPtr->hwndHeader, wndPtr->hwndSelf,
+			wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+
+	infoPtr->rcList.top += wp.cy;
+    }
 
     return 0;
 }
@@ -463,24 +1260,54 @@
 
     switch (uMsg)
     {
-//	case LVM_DELETEALLITEMS:
+//	case LVM_APPROXIMATEVIEWRECT:
+//	case LVM_ARRANGE:
+//	case LVM_CREATEDRAGIMAGE:
 
-        case LVM_GETBKCOLOR:
+	case LVM_DELETEALLITEMS:
+	    return LISTVIEW_DeleteAllItems (wndPtr);
+
+	case LVM_DELETECOLUMN:
+	    return LISTVIEW_DeleteColumn (wndPtr, wParam, lParam);
+
+	case LVM_DELETEITEM:
+	    return LISTVIEW_DeleteItem (wndPtr, wParam, lParam);
+
+//	case LVM_EDITLABEL:
+//	case LVM_ENSUREVISIBLE:
+//	case LVM_FINDITEM:
+
+	case LVM_GETBKCOLOR:
 	    return LISTVIEW_GetBkColor (wndPtr, wParam, lParam);
 
+//	case LVM_GETBKIMAGE:
+//	case LVM_GETCALLBACKMASK:
 
-        case LVM_GETCOLUMNWIDTH:
+	case LVM_GETCOLUMN32A:
+	    return LISTVIEW_GetColumn32A (wndPtr, wParam, lParam);
+
+//	case LVM_GETCOLUMN32W:
+//	case LVM_GETCOLUMNORDERARRAY:
+
+	case LVM_GETCOLUMNWIDTH:
 	    return LISTVIEW_GetColumnWidth (wndPtr, wParam, lParam);
 
+//	case LVM_GETCOUNTPERPAGE:
+//	case LVM_GETEDITCONTROL:
+//	case LVM_GETEXTENDEDLISTVIEWSTYLE:
 
-        case LVM_GETHEADER:
+	case LVM_GETHEADER:
 	    return LISTVIEW_GetHeader (wndPtr, wParam, lParam);
 
-//	case LVM_GETISEARCHSTRING:
+//	case LVM_GETHOTCURSOR:
+//	case LVM_GETHOTITEM:
+//	case LVM_GETHOVERTIME:
 
 	case LVM_GETIMAGELIST:
 	    return LISTVIEW_GetImageList (wndPtr, wParam, lParam);
 
+//	case LVM_GETISEARCHSTRING:
+
 	case LVM_GETITEM32A:
 	    return LISTVIEW_GetItem32A (wndPtr, wParam, lParam);
 
@@ -489,7 +1316,28 @@
 	case LVM_GETITEMCOUNT:
 	    return LISTVIEW_GetItemCount (wndPtr, wParam, lParam);
 
-//	case LVM_GETSELECTEDCOUNT:
+	case LVM_GETITEMPOSITION:
+	    return LISTVIEW_GetItemPosition (wndPtr, wParam, lParam);
+
+//	case LVM_GETITEMRECT:
+//	case LVM_GETITEMSPACING:
+//	case LVM_GETITEMSTATE:
+
+	case LVM_GETITEMTEXT32A:
+	    return LISTVIEW_GetItemText32A (wndPtr, wParam, lParam);
+
+//	case LVM_GETITEMTEXT32W:
+
+	case LVM_GETNEXTITEM:
+	    return LISTVIEW_GetNextItem (wndPtr, wParam, lParam);
+
+//	case LVM_GETNUMBEROFWORKAREAS:
+//	case LVM_GETORIGIN:
+
+	case LVM_GETSELECTEDCOUNT:
+	    return LISTVIEW_GetSelectedCount (wndPtr, wParam, lParam);
+
+//	case LVM_GETSELECTIONMARK:
 
 	case LVM_GETSTRINGWIDTH32A:
 	    return LISTVIEW_GetStringWidth32A (wndPtr, wParam, lParam);
@@ -497,26 +1345,85 @@
 //	case LVM_GETSTRINGWIDTH32W:
 //	case LVM_GETSUBITEMRECT:
 
+	case LVM_GETTEXTBKCOLOR:
+	    return LISTVIEW_GetTextBkColor (wndPtr, wParam, lParam);
+
+	case LVM_GETTEXTCOLOR:
+	    return LISTVIEW_GetTextColor (wndPtr, wParam, lParam);
+
+//	case LVM_GETTOOLTIPS:
+//	case LVM_GETTOPINDEX:
+//	case LVM_GETUNICODEFORMAT:
+//	case LVM_GETVIEWRECT:
+//	case LVM_GETWORKAREAS:
+//	case LVM_HITTEST:
+
 	case LVM_INSERTCOLUMN32A:
 	    return LISTVIEW_InsertColumn32A (wndPtr, wParam, lParam);
 
-
 //	case LVM_INSERTCOLUMN32W:
 
-//	case LVM_INSERTITEM32A:
+	case LVM_INSERTITEM32A:
+	    return LISTVIEW_InsertItem32A (wndPtr, wParam, lParam);
+
 //	case LVM_INSERTITEM32W:
 
+	case LVM_REDRAWITEMS:
+	    return LISTVIEW_RedrawItems (wndPtr, wParam, lParam);
+
+//	case LVM_SCROLL:
 
 	case LVM_SETBKCOLOR:
 	    return LISTVIEW_SetBkColor (wndPtr, wParam, lParam);
 
+//	case LVM_SETBKIMAGE:
+//	case LVM_SETCALLBACKMASK:
+
+	case LVM_SETCOLUMN32A:
+	    return LISTVIEW_SetColumn32A (wndPtr, wParam, lParam);
+
+//	case LVM_SETCOLUMN32W:
+//	case LVM_SETCOLUMNORDERARRAY:
+//	case LVM_SETCOLUMNWIDTH:
+//	case LVM_SETEXTENDEDLISTVIEWSTYLE:
+//	case LVM_SETHOTCURSOR:
+//	case LVM_SETHOTITEM:
+//	case LVM_SETHOVERTIME:
+//	case LVM_SETICONSPACING:
 	
 	case LVM_SETIMAGELIST:
 	    return LISTVIEW_SetImageList (wndPtr, wParam, lParam);
 
-//	case LVM_SETITEMPOSITION:
+	case LVM_SETITEM32A:
+	    return LISTVIEW_SetItem32A (wndPtr, wParam, lParam);
 
-//	case LVM_SORTITEMS:
+//	case LVM_SETITEM32W:
+//	case LVM_SETITEMCOUNT:
+
+	case LVM_SETITEMPOSITION:
+	    return LISTVIEW_SetItemPosition (wndPtr, wParam, lParam);
+
+//	case LVM_SETITEMPOSITION32:
+//	case LVM_SETITEMSTATE:
+//	case LVM_SETITEMTEXT:
+//	case LVM_SETSELECTIONMARK:
+
+	case LVM_SETTEXTBKCOLOR:
+	    return LISTVIEW_SetTextBkColor (wndPtr, wParam, lParam);
+
+	case LVM_SETTEXTCOLOR:
+	    return LISTVIEW_SetTextColor (wndPtr, wParam, lParam);
+
+//	case LVM_SETTOOLTIPS:
+//	case LVM_SETUNICODEFORMAT:
+//	case LVM_SETWORKAREAS:
+
+	case LVM_SORTITEMS:
+	    return LISTVIEW_SortItems (wndPtr, wParam, lParam);
+
+//	case LVM_SUBITEMHITTEST:
+//	case LVM_UPDATE:
+
 
 
 //	case WM_CHAR:
@@ -538,6 +1445,16 @@
 	    return LISTVIEW_GetFont (wndPtr, wParam, lParam);
 
 //	case WM_HSCROLL:
+//	case WM_KEYDOWN:
+
+	case WM_KILLFOCUS:
+	    return LISTVIEW_KillFocus (wndPtr, wParam, lParam);
+
+	case WM_LBUTTONDBLCLK:
+	    return LISTVIEW_LButtonDblClk (wndPtr, wParam, lParam);
+
+	case WM_LBUTTONDOWN:
+	    return LISTVIEW_LButtonDown (wndPtr, wParam, lParam);
 
 //	case WM_MOUSEMOVE:
 //	    return LISTVIEW_MouseMove (wndPtr, wParam, lParam);
@@ -548,13 +1465,20 @@
 	case WM_NCDESTROY:
 	    return LISTVIEW_NCDestroy (wndPtr, wParam, lParam);
 
-//	case WM_NOTIFY:
+	case WM_NOTIFY:
+	    return LISTVIEW_Notify (wndPtr, wParam, lParam);
 
 	case WM_PAINT:
 	    return LISTVIEW_Paint (wndPtr, wParam);
 
-//	case WM_RBUTTONDOWN:
-//	case WM_SETFOCUS:
+	case WM_RBUTTONDBLCLK:
+	    return LISTVIEW_RButtonDblClk (wndPtr, wParam, lParam);
+
+	case WM_RBUTTONDOWN:
+	    return LISTVIEW_RButtonDown (wndPtr, wParam, lParam);
+
+	case WM_SETFOCUS:
+	    return LISTVIEW_SetFocus (wndPtr, wParam, lParam);
 
 	case WM_SETFONT:
 	    return LISTVIEW_SetFont (wndPtr, wParam, lParam);
diff --git a/dlls/comctl32/pager.c b/dlls/comctl32/pager.c
index e5c231e..815a55f 100644
--- a/dlls/comctl32/pager.c
+++ b/dlls/comctl32/pager.c
@@ -169,7 +169,7 @@
     SetParent32 (infoPtr->hwndChild, wndPtr->hwndSelf);
     SetWindowPos32 (infoPtr->hwndChild, wndPtr->hwndSelf,
 		    0, 0, 40, 40, SWP_SHOWWINDOW);
-    RedrawWindow32 (wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE);
+    RedrawWindow32 (wndPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE);
 
     return 0;
 }
diff --git a/dlls/comctl32/progress.c b/dlls/comctl32/progress.c
index 3acb294..ad08872 100644
--- a/dlls/comctl32/progress.c
+++ b/dlls/comctl32/progress.c
@@ -8,9 +8,8 @@
  */
 
 #include "windows.h"
-#include "progress.h"
 #include "commctrl.h"
-#include "heap.h"
+#include "progress.h"
 #include "win.h"
 #include "debug.h"
 
@@ -185,8 +184,7 @@
     case WM_CREATE:
       /* allocate memory for info struct */
       infoPtr = 
-	(PROGRESS_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                    sizeof(PROGRESS_INFO));
+	(PROGRESS_INFO *)COMCTL32_Alloc (sizeof(PROGRESS_INFO));
       wndPtr->wExtra[0] = (DWORD)infoPtr;
 
       /* initialize the info struct */
@@ -200,8 +198,8 @@
       break;
     
     case WM_DESTROY:
-      TRACE(progress, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
-      HeapFree (GetProcessHeap (), 0, infoPtr);
+      TRACE (progress, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
+      COMCTL32_Free (infoPtr);
       break;
 
     case WM_ERASEBKGND:
@@ -328,11 +326,12 @@
 
 
 /***********************************************************************
- *           PROGRESS_Register [Internal]
+ * PROGRESS_Register [Internal]
  *
  * Registers the progress bar window class.
  * 
  */
+
 void 
 PROGRESS_Register(void)
 {
diff --git a/dlls/comctl32/rebar.c b/dlls/comctl32/rebar.c
index b27b5f5..2936d96 100644
--- a/dlls/comctl32/rebar.c
+++ b/dlls/comctl32/rebar.c
@@ -16,7 +16,6 @@
 #include "windows.h"
 #include "commctrl.h"
 #include "rebar.h"
-#include "heap.h"
 #include "win.h"
 #include "debug.h"
 
@@ -42,10 +41,24 @@
 
 
 
-
-
 // << REBAR_BeginDrag >>
-// << REBAR_DeleteBand >>
+
+
+static LRESULT
+REBAR_DeleteBand (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (wndPtr);
+    UINT32 uBand = (UINT32)wParam;
+
+    if (uBand >= infoPtr->uNumBands)
+	return FALSE;
+
+    FIXME (rebar, "deleting band %u!\n", uBand);
+
+    return TRUE;
+}
+
+
 // << REBAR_DragMove >>
 // << REBAR_EndDrag >>
 // << REBAR_GetBandBorders >>
@@ -246,16 +259,13 @@
     TRACE (rebar, "insert band at %u!\n", uIndex);
 
     if (infoPtr->uNumBands == 0) {
-	infoPtr->bands =
-	    (REBAR_BAND *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-				     sizeof (REBAR_BAND));
+	infoPtr->bands = (REBAR_BAND *)COMCTL32_Alloc (sizeof (REBAR_BAND));
 	uIndex = 0;
     }
     else {
 	REBAR_BAND *oldBands = infoPtr->bands;
 	infoPtr->bands =
-	    (REBAR_BAND *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-				     (infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
+	    (REBAR_BAND *)COMCTL32_Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
 	if (((INT32)uIndex == -1) || (uIndex > infoPtr->uNumBands))
 	    uIndex = infoPtr->uNumBands;
 
@@ -271,7 +281,7 @@
 		    (infoPtr->uNumBands - uIndex - 1) * sizeof(REBAR_BAND));
 	}
 
-	HeapFree (GetProcessHeap (), 0, &oldBands);
+	COMCTL32_Free (&oldBands);
     }
 
     infoPtr->uNumBands++;
@@ -292,8 +302,7 @@
     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
 	INT32 len = lstrlen32A (lprbbi->lpText);
 	if (len > 0) {
-	    lpBand->lpText = 
-		(LPSTR)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
+	    lpBand->lpText = (LPSTR)COMCTL32_Alloc (len + 1);
 	    lstrcpy32A (lpBand->lpText, lprbbi->lpText);
 	}
     }
@@ -377,8 +386,7 @@
 /*
 	INT32 len = lstrlen32A (lprbbi->lpText);
 	if (len > 0) {
-	    lpBand->lpText = 
-		(LPSTR)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
+	    lpBand->lpText = (LPSTR)COMCTL32_Alloc (len + 1);
 	    lstrcpy32A (lpBand->lpText, lprbbi->lpText);
 	}
 */
@@ -566,13 +574,13 @@
 
 	    /* delete text strings */
 	    if (lpBand->lpText) {
-		HeapFree (GetProcessHeap (), 0, lpBand->lpText);
+		COMCTL32_Free (lpBand->lpText);
 		lpBand->lpText = NULL;
 	    }
 	}
 
 	/* free band array */
-	HeapFree (GetProcessHeap (), 0, infoPtr->bands);
+	COMCTL32_Free (infoPtr->bands);
 	infoPtr->bands = NULL;
     }
 
@@ -608,7 +616,10 @@
     switch (uMsg)
     {
 //	case RB_BEGINDRAG:
-//	case RB_DELETEBAND:
+
+	case RB_DELETEBAND:
+	    return REBAR_DeleteBand (wndPtr, wParam, lParam);
+
 //	case RB_DRAGMOVE:
 //	case RB_ENDDRAG:
 //	case RB_GETBANDBORDERS:
@@ -621,7 +632,6 @@
 	case RB_GETBANDINFO32A:
 	    return REBAR_GetBandInfo32A (wndPtr, wParam, lParam);
 
-
 //	case RB_GETBANDINFO32W:
 
 	case RB_GETBARHEIGHT:
diff --git a/dlls/comctl32/status.c b/dlls/comctl32/status.c
index 6536fa9..a2c710e 100644
--- a/dlls/comctl32/status.c
+++ b/dlls/comctl32/status.c
@@ -6,9 +6,8 @@
  */
 
 #include "windows.h"
-#include "status.h"
 #include "commctrl.h"
-#include "heap.h"
+#include "status.h"
 #include "win.h"
 #include "debug.h"
 
@@ -528,17 +527,16 @@
     if (oldNumParts > self->numParts) {
 	for (i = self->numParts ; i < oldNumParts; i++) {
 	    if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
-		HeapFree(GetProcessHeap (), 0, self->parts[i].text);
+		COMCTL32_Free (self->parts[i].text);
 	}
     }
     else if (oldNumParts < self->numParts) {
-	tmp = HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY,
-			sizeof(STATUSWINDOWPART) * self->numParts);
+	tmp = COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * self->numParts);
 	for (i = 0; i < oldNumParts; i++) {
 	    tmp[i] = self->parts[i];
 	}
 	if (self->parts)
-	    HeapFree(GetProcessHeap (), 0, self->parts);
+	    COMCTL32_Free (self->parts);
 	self->parts = tmp;
     }
     
@@ -614,10 +612,10 @@
     else {
 	/* duplicate string */
 	if (part->text)
-	    HeapFree (GetProcessHeap (), 0, part->text);
+	    COMCTL32_Free (part->text);
 	part->text = 0;
 	if (text && (len = lstrlen32A(text))) {
-	    part->text = HeapAlloc (GetProcessHeap (), 0, len+1);
+	    part->text = COMCTL32_Alloc (len+1);
 	    lstrcpy32A(part->text, text);
 	}
     }
@@ -694,8 +692,7 @@
     HDC32	hdc;
     STATUSWINDOWINFO *self;
 
-    self = (STATUSWINDOWINFO*)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-					 sizeof(STATUSWINDOWINFO));
+    self = (STATUSWINDOWINFO*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO));
     wndPtr->wExtra[0] = (DWORD)self;
 
     self->numParts = 1;
@@ -717,8 +714,7 @@
     self->part0.hIcon = 0;
 
     /* initialize first part */
-    self->parts = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-			     sizeof(STATUSWINDOWPART));
+    self->parts = COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
     self->parts[0].bound = rect;
     self->parts[0].text = 0;
     self->parts[0].x = -1;
@@ -726,7 +722,7 @@
     self->parts[0].hIcon = 0;
 
     if ((len = lstrlen32A (lpCreate->lpszName))) {
-        self->parts[0].text = HeapAlloc (GetProcessHeap (), 0, len + 1);
+        self->parts[0].text = COMCTL32_Alloc (len + 1);
         lstrcpy32A (self->parts[0].text, lpCreate->lpszName);
     }
 
@@ -781,11 +777,11 @@
 
     for (i = 0; i < self->numParts; i++) {
 	if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
-	    HeapFree(GetProcessHeap (), 0, self->parts[i].text);
+	    COMCTL32_Free (self->parts[i].text);
     }
     if (self->part0.text && (self->part0.style != SBT_OWNERDRAW))
-	HeapFree(GetProcessHeap (), 0, self->part0.text);
-    HeapFree(GetProcessHeap (), 0, self->parts);
+	COMCTL32_Free (self->part0.text);
+    COMCTL32_Free (self->parts);
 
     /* delete default font */
     if (self->hDefaultFont)
@@ -795,7 +791,7 @@
     if (self->hwndToolTip)
 	DestroyWindow32 (self->hwndToolTip);
 
-    HeapFree(GetProcessHeap (), 0, self);
+    COMCTL32_Free (self);
 
     return 0;
 }
@@ -939,10 +935,10 @@
     part = &self->parts[0];
     /* duplicate string */
     if (part->text)
-        HeapFree(GetProcessHeap (), 0, part->text);
+        COMCTL32_Free (part->text);
     part->text = 0;
     if (lParam && (len = lstrlen32A((LPCSTR)lParam))) {
-        part->text = HeapAlloc (GetProcessHeap (), 0, len+1);
+        part->text = COMCTL32_Alloc (len+1);
         lstrcpy32A (part->text, (LPCSTR)lParam);
     }
 
diff --git a/dlls/comctl32/toolbar.c b/dlls/comctl32/toolbar.c
index a1ac4e3..2a89d4b 100644
--- a/dlls/comctl32/toolbar.c
+++ b/dlls/comctl32/toolbar.c
@@ -4,11 +4,9 @@
  * Copyright 1998 Eric Kohl
  *
  * TODO:
- *   - Bitmap drawing.
  *   - Button wrapping.
  *   - Messages.
  *   - Notifications.
- *   - Fix TB_GETBITMAPFLAGS.
  *   - Fix TB_GETROWS and TB_SETROWS.
  *   - Tooltip support (almost complete).
  *   - Unicode suppport.
@@ -27,11 +25,10 @@
  */
 
 #include "windows.h"
-#include "sysmetrics.h"
 #include "commctrl.h"
+#include "sysmetrics.h"
 #include "cache.h"
 #include "toolbar.h"
-#include "heap.h"
 #include "win.h"
 #include "debug.h"
 
@@ -67,13 +64,13 @@
 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
 		    HDC32 hdc, INT32 nState)
 {
-    RECT32 rcText = btnPtr->rect;
-    HFONT32 hOldFont;
-    INT32   nOldBkMode;
+    RECT32   rcText = btnPtr->rect;
+    HFONT32  hOldFont;
+    INT32    nOldBkMode;
+    COLORREF clrOld;
 
     /* draw text */
     if ((btnPtr->iString > -1) && (btnPtr->iString < infoPtr->nNumStrings)) {
-
 	InflateRect32 (&rcText, -3, -3);
 	rcText.top += infoPtr->nBitmapHeight;
 	if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
@@ -82,28 +79,27 @@
 	hOldFont = SelectObject32 (hdc, infoPtr->hFont);
 	nOldBkMode = SetBkMode32 (hdc, TRANSPARENT);
 	if (!(nState & TBSTATE_ENABLED)) {
-	    COLORREF clrOld = 
-		SetTextColor32 (hdc, GetSysColor32 (COLOR_3DHILIGHT));
+	    clrOld = SetTextColor32 (hdc, GetSysColor32 (COLOR_3DHILIGHT));
 	    OffsetRect32 (&rcText, 1, 1);
-	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1, &rcText,
-			 DT_CENTER);
+	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1,
+			 &rcText, infoPtr->dwDTFlags);
 	    SetTextColor32 (hdc, GetSysColor32 (COLOR_3DSHADOW));
 	    OffsetRect32 (&rcText, -1, -1);
-	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1, &rcText,
-			 DT_CENTER);
-	    SetTextColor32 (hdc, clrOld);
+	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1,
+			 &rcText, infoPtr->dwDTFlags);
 	}
 	else if (nState & TBSTATE_INDETERMINATE) {
-	    COLORREF clrOld = 
-		SetTextColor32 (hdc, GetSysColor32 (COLOR_3DSHADOW));
-	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1, &rcText,
-			 DT_CENTER);
-	    SetTextColor32 (hdc, clrOld);
+	    clrOld = SetTextColor32 (hdc, GetSysColor32 (COLOR_3DSHADOW));
+	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1,
+			 &rcText, infoPtr->dwDTFlags);
 	}
-	else
-	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1, &rcText,
-			 DT_CENTER);
+	else {
+	    clrOld = SetTextColor32 (hdc, GetSysColor32 (COLOR_BTNTEXT));
+	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1,
+			 &rcText, infoPtr->dwDTFlags);
+	}
 
+	SetTextColor32 (hdc, clrOld);
 	SelectObject32 (hdc, hOldFont);
 	if (nOldBkMode != TRANSPARENT)
 	    SetBkMode32 (hdc, nOldBkMode);
@@ -112,6 +108,46 @@
 
 
 static void
+TOOLBAR_DrawPattern (HDC32 hdc, LPRECT32 lpRect)
+{
+    HBRUSH32 hbr = SelectObject32 (hdc, CACHE_GetPattern55AABrush ());
+    INT32 cx = lpRect->right - lpRect->left;
+    INT32 cy = lpRect->bottom - lpRect->top;
+    PatBlt32 (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
+    SelectObject32 (hdc, hbr);
+}
+
+
+static void
+TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
+		    HDC32 hdc, INT32 x, INT32 y)
+{
+    /* FIXME: this function is a hack since it uses image list
+	      internals directly */
+
+    HDC32 hdcImageList = CreateCompatibleDC32 (0);
+    HIMAGELIST himl = infoPtr->himlDef;
+
+    /* draw the mask */
+    SelectObject32 (hdcImageList, himl->hbmMask);
+    SetBkColor32 (hdcImageList, RGB(255, 255, 255));
+    SetTextColor32 (hdcImageList, RGB(0, 0, 0));
+
+    SelectObject32 (hdc, GetSysColorBrush32 (COLOR_3DHILIGHT));
+    BitBlt32 (hdc, x+1, y+1, himl->cx, himl->cy,
+	      hdcImageList, himl->cx * btnPtr->iBitmap, 0,
+		  0xB8074A);
+
+    SelectObject32 (hdc, GetSysColorBrush32 (COLOR_3DSHADOW));
+    BitBlt32 (hdc, x, y, himl->cx, himl->cy,
+	      hdcImageList, himl->cx * btnPtr->iBitmap, 0,
+		  0xB8074A);
+
+    DeleteDC32 (hdcImageList);
+}
+
+
+static void
 TOOLBAR_DrawButton (WND *wndPtr, TBUTTON_INFO *btnPtr, HDC32 hdc)
 {
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
@@ -129,12 +165,11 @@
 
     /* disabled */
     if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
-	HICON32 hIcon;
 	DrawEdge32 (hdc, &rc, EDGE_RAISED,
 		    BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
 
-//	ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
-//			rc.left+1, rc.top+1, ILD_NORMAL);
+	TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
+
 	TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState);
 	return;
     }
@@ -152,7 +187,6 @@
     /* checked TBSTYLE_CHECK*/
     if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
 	(btnPtr->fsState & TBSTATE_CHECKED)) {
-	HBRUSH32 hbr;
 	if (bFlat)
 	    DrawEdge32 (hdc, &rc, BDR_SUNKENOUTER,
 			BF_RECT | BF_MIDDLE | BF_ADJUST);
@@ -160,10 +194,7 @@
 	    DrawEdge32 (hdc, &rc, EDGE_SUNKEN,
 			BF_RECT | BF_MIDDLE | BF_ADJUST);
 
-	hbr = SelectObject32 (hdc, CACHE_GetPattern55AABrush ());
-	PatBlt32 (hdc, rc.left, rc.top, rc.right - rc.left,
-		  rc.bottom - rc.top, 0x00FA0089);
-	SelectObject32 (hdc, hbr);
+	TOOLBAR_DrawPattern (hdc, &rc);
 	ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
 			rc.left+2, rc.top+2, ILD_NORMAL);
 	TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState);
@@ -172,16 +203,11 @@
 
     /* indeterminate */	
     if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
-	HBRUSH32 hbr;
 	DrawEdge32 (hdc, &rc, EDGE_RAISED,
 		    BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
 
-	hbr = SelectObject32 (hdc, CACHE_GetPattern55AABrush ());
-	PatBlt32 (hdc, rc.left, rc.top, rc.right - rc.left,
-		  rc.bottom - rc.top, 0x00FA0089);
-	SelectObject32 (hdc, hbr);
-//	ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
-//			rc.left+1, rc.top+1, ILD_NORMAL);
+	TOOLBAR_DrawPattern (hdc, &rc);
+	TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
 	TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState);
 	return;
     }
@@ -495,7 +521,7 @@
     if (lpAddBmp->hInst == (HINSTANCE32)0) {
 	nIndex = 
 	    ImageList_AddMasked (infoPtr->himlDef, (HBITMAP32)lpAddBmp->nID,
-				 GetSysColor32 (COLOR_3DFACE));
+				 CLR_DEFAULT);
     }
     else if (lpAddBmp->hInst == HINST_COMMCTRL) {
 	/* add internal bitmaps */
@@ -510,7 +536,7 @@
 	HBITMAP32 hBmp =
 	    LoadBitmap32A (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
 
-	nIndex = ImageList_Add (infoPtr->himlDef, hBmp, (HBITMAP32)0);
+	nIndex = ImageList_AddMasked (infoPtr->himlDef, hBmp, CLR_DEFAULT);
 
 	DeleteObject32 (hBmp); 
     }
@@ -538,17 +564,15 @@
 
     if (infoPtr->nNumButtons == 0) {
 	infoPtr->buttons =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-		       sizeof (TBUTTON_INFO) * nNewButtons);
+	    COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
     }
     else {
 	TBUTTON_INFO *oldButtons = infoPtr->buttons;
 	infoPtr->buttons =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-		       sizeof (TBUTTON_INFO) * nNewButtons);
+	    COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
 	memcpy (&infoPtr->buttons[0], &oldButtons[0],
 		nOldButtons * sizeof(TBUTTON_INFO));
-        HeapFree (GetProcessHeap (), 0, oldButtons);
+        COMCTL32_Free (oldButtons);
     }
 
     infoPtr->nNumButtons = nNewButtons;
@@ -609,20 +633,19 @@
 	nIndex = infoPtr->nNumStrings;
 	if (infoPtr->nNumStrings == 0) {
 	    infoPtr->strings =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(char *));
+		COMCTL32_Alloc (sizeof(char *));
 	}
 	else {
 	    char **oldStrings = infoPtr->strings;
 	    infoPtr->strings =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-			   sizeof(char *) * (infoPtr->nNumStrings + 1));
+		COMCTL32_Alloc (sizeof(char *) * (infoPtr->nNumStrings + 1));
 	    memcpy (&infoPtr->strings[0], &oldStrings[0],
 		    sizeof(char *) * infoPtr->nNumStrings);
-	    HeapFree (GetProcessHeap (), 0, oldStrings);
+	    COMCTL32_Free (oldStrings);
 	}
 
 	infoPtr->strings[infoPtr->nNumStrings] =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(char)*(len+1));
+	    COMCTL32_Alloc (sizeof(char)*(len+1));
 	lstrcpy32A (infoPtr->strings[infoPtr->nNumStrings], szString);
 	infoPtr->nNumStrings++;
     }
@@ -639,20 +662,19 @@
 
 	    if (infoPtr->nNumStrings == 0) {
 		infoPtr->strings =
-		    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(char *));
+		    COMCTL32_Alloc (sizeof(char *));
 	    }
 	    else {
 		char **oldStrings = infoPtr->strings;
 		infoPtr->strings =
-		    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-			       sizeof(char *) * (infoPtr->nNumStrings + 1));
+		    COMCTL32_Alloc (sizeof(char *) * (infoPtr->nNumStrings + 1));
 		memcpy (&infoPtr->strings[0], &oldStrings[0],
 			sizeof(char *) * infoPtr->nNumStrings);
-		HeapFree (GetProcessHeap (), 0, oldStrings);
+		COMCTL32_Free (oldStrings);
 	    }
 
 	    infoPtr->strings[infoPtr->nNumStrings] =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(char)*(len+1));
+		COMCTL32_Alloc (sizeof(char)*(len+1));
 	    lstrcpy32A (infoPtr->strings[infoPtr->nNumStrings], p);
 	    infoPtr->nNumStrings++;
 
@@ -841,7 +863,7 @@
 
     if (infoPtr->nNumButtons == 1) {
 	TRACE (toolbar, " simple delete!\n");
-	HeapFree (GetProcessHeap (), 0, infoPtr->buttons);
+	COMCTL32_Free (infoPtr->buttons);
 	infoPtr->buttons = NULL;
 	infoPtr->nNumButtons = 0;
     }
@@ -850,8 +872,7 @@
         TRACE(toolbar, "complex delete! [nIndex=%d]\n", nIndex);
 
 	infoPtr->nNumButtons--;
-	infoPtr->buttons = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-				      sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
+	infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
         if (nIndex > 0) {
             memcpy (&infoPtr->buttons[0], &oldButtons[0],
                     nIndex * sizeof(TBUTTON_INFO));
@@ -862,7 +883,7 @@
                     (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
         }
 
-        HeapFree (GetProcessHeap (), 0, oldButtons);
+	COMCTL32_Free (oldButtons);
     }
 
     TOOLBAR_CalcToolbar (wndPtr);
@@ -911,17 +932,16 @@
 
     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
     if (nIndex == -1)
-	return 0;
+	return -1;
 
     return infoPtr->buttons[nIndex].iBitmap;
 }
 
 
-static LRESULT
+static __inline__ LRESULT
 TOOLBAR_GetBitmapFlags (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-    FIXME (toolbar, "stub!\n");
-    return 0;
+    return (GetDeviceCaps32 (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
 }
 
 
@@ -1312,8 +1332,7 @@
 
     oldButtons = infoPtr->buttons;
     infoPtr->nNumButtons++;
-    infoPtr->buttons = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-				  sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
+    infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
     /* pre insert copy */
     if (nIndex > 0) {
 	memcpy (&infoPtr->buttons[0], &oldButtons[0],
@@ -1348,7 +1367,7 @@
 		(infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
     }
 
-    HeapFree (GetProcessHeap (), 0, oldButtons);
+    COMCTL32_Free (oldButtons);
 
     TOOLBAR_CalcToolbar (wndPtr);
 
@@ -1486,6 +1505,7 @@
 static LRESULT
 TOOLBAR_SaveRestore32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
+#if 0
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
     LPTBSAVEPARAMS32A lpSave = (LPTBSAVEPARAMS32A)lParam;
 
@@ -1506,6 +1526,7 @@
 
 
     }
+#endif
 
     return 0;
 }
@@ -1565,13 +1586,13 @@
 	if ((btnPtr->iString >= 0) || 
 	    (btnPtr->iString < infoPtr->nNumStrings)) {
 #if 0
-	    CHAR *lpString = infoPtr->strings[btnPtr->iString];
+	    CHAR **lpString = &infoPtr->strings[btnPtr->iString];
 	    INT32 len = lstrlen32A (lptbbi->pszText);
-
-	    lpString = HeapReAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(char)*(len+1));
-
+	    *lpString = COMCTL32_ReAlloc (lpString, sizeof(char)*(len+1));
 #endif
 
+	    /* this is the ultimate sollution */
+//	    Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText);
 	}
     }
 
@@ -1654,7 +1675,18 @@
 }
 
 
-// << TOOLBAR_SetDrawTextFlags >>
+static LRESULT
+TOOLBAR_SetDrawTextFlags (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    DWORD dwTemp;
+
+    dwTemp = infoPtr->dwDTFlags;
+    infoPtr->dwDTFlags =
+	(infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
+
+    return (LRESULT)dwTemp;
+}
 
 
 static LRESULT
@@ -1910,6 +1942,7 @@
     infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
     infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
     infoPtr->nHotItem = -1;
+    infoPtr->dwDTFlags = DT_CENTER;
 
     SystemParametersInfo32A (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
     infoPtr->hFont = CreateFontIndirect32A (&logFont);
@@ -1951,16 +1984,16 @@
 
     /* delete button data */
     if (infoPtr->buttons)
-	HeapFree (GetProcessHeap (), 0, infoPtr->buttons);
+	COMCTL32_Free (infoPtr->buttons);
 
     /* delete strings */
     if (infoPtr->strings) {
 	INT32 i;
 	for (i = 0; i < infoPtr->nNumStrings; i++)
 	    if (infoPtr->strings[i])
-		HeapFree (GetProcessHeap (), 0, infoPtr->strings[i]);
+		COMCTL32_Free (infoPtr->strings[i]);
 
-	HeapFree (GetProcessHeap (), 0, infoPtr->strings);
+	COMCTL32_Free (infoPtr->strings);
     }
 
     /* destroy default image list */
@@ -1980,7 +2013,7 @@
 	DeleteObject32 (infoPtr->hFont);
 
     /* free toolbar info data */
-    HeapFree (GetProcessHeap (), 0, infoPtr);
+    COMCTL32_Free (infoPtr);
 
     return 0;
 }
@@ -2178,7 +2211,15 @@
 }
 
 
-// << TOOLBAR_NCActivate >>
+__inline__ static LRESULT
+TOOLBAR_NCActivate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+//    if (wndPtr->dwStyle & CCS_NODIVIDER)
+	return DefWindowProc32A (wndPtr->hwndSelf, WM_NCACTIVATE,
+				 wParam, lParam);
+//    else
+//	return TOOLBAR_NCPaint (wndPtr, wParam, lParam);
+}
 
 
 __inline__ static LRESULT
@@ -2197,8 +2238,7 @@
     TOOLBAR_INFO *infoPtr;
 
     /* allocate memory for info structure */
-    infoPtr = (TOOLBAR_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                   sizeof(TOOLBAR_INFO));
+    infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
     wndPtr->wExtra[0] = (DWORD)infoPtr;
 
     if (infoPtr == NULL) {
@@ -2568,7 +2608,8 @@
 	case TB_SETDISABLEDIMAGELIST:
 	    return TOOLBAR_SetDisabledImageList (wndPtr, wParam, lParam);
 
-//	case TB_SETDRAWTEXTFLAGS:		/* 4.71 */
+	case TB_SETDRAWTEXTFLAGS:
+	    return TOOLBAR_SetDrawTextFlags (wndPtr, wParam, lParam);
 
 	case TB_SETEXTENDEDSTYLE:
 	    return TOOLBAR_SetExtendedStyle (wndPtr, wParam, lParam);
@@ -2640,8 +2681,8 @@
 	case WM_MOUSEMOVE:
 	    return TOOLBAR_MouseMove (wndPtr, wParam, lParam);
 
-//	case WM_NCACTIVATE:
-//	    return TOOLBAR_NCActivate (wndPtr, wParam, lParam);
+	case WM_NCACTIVATE:
+	    return TOOLBAR_NCActivate (wndPtr, wParam, lParam);
 
 	case WM_NCCALCSIZE:
 	    return TOOLBAR_NCCalcSize (wndPtr, wParam, lParam);
diff --git a/dlls/comctl32/tooltips.c b/dlls/comctl32/tooltips.c
index 93ea5f3..419f605 100644
--- a/dlls/comctl32/tooltips.c
+++ b/dlls/comctl32/tooltips.c
@@ -21,7 +21,6 @@
 #include "windows.h"
 #include "commctrl.h"
 #include "tooltips.h"
-#include "heap.h"
 #include "win.h"
 #include "debug.h"
 
@@ -108,8 +107,7 @@
 		if (ttnmdi.uFlags & TTF_DI_SETITEM) {
 		    INT32 len = lstrlen32A (ttnmdi.szText) + 1;
 		    toolPtr->hinst = 0;
-		    toolPtr->lpszText =	
-			HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len);
+		    toolPtr->lpszText =	COMCTL32_Alloc (len);
 		    lstrcpy32A (toolPtr->lpszText, ttnmdi.szText);
 		}
 	    }
@@ -124,8 +122,7 @@
 		if (ttnmdi.uFlags & TTF_DI_SETITEM) {
 		    INT32 len = lstrlen32A (ttnmdi.lpszText) + 1;
 		    toolPtr->hinst = 0;
-		    toolPtr->lpszText =	
-			HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len);
+		    toolPtr->lpszText =	COMCTL32_Alloc (len);
 		    lstrcpy32A (toolPtr->lpszText, ttnmdi.lpszText);
 		}
 	    }
@@ -177,7 +174,7 @@
 TOOLTIPS_Show (WND *wndPtr, TOOLTIPS_INFO *infoPtr)
 {
     TTTOOL_INFO *toolPtr;
-    POINT32 pt;
+    RECT32 rect;
     SIZE32 size;
     NMHDR hdr;
 
@@ -212,31 +209,37 @@
     TRACE (tooltips, "size %d - %d\n", size.cx, size.cy);
 
     if ((toolPtr->uFlags & TTF_TRACK) && (toolPtr->uFlags & TTF_ABSOLUTE)) {
-	pt.x = infoPtr->xTrackPos;
-	pt.y = infoPtr->yTrackPos;
+	rect.left = infoPtr->xTrackPos;
+	rect.top  = infoPtr->yTrackPos;
     }
     else if (toolPtr->uFlags & TTF_CENTERTIP) {
-	RECT32 rect;
+	RECT32 rc;
 
 	if (toolPtr->uFlags & TTF_IDISHWND)
-	    GetWindowRect32 ((HWND32)toolPtr->uId, &rect);
+	    GetWindowRect32 ((HWND32)toolPtr->uId, &rc);
 	else {
-	    rect = toolPtr->rect;
-	    MapWindowPoints32 (toolPtr->hwnd, (HWND32)0, (LPPOINT32)&rect, 2);
+	    rc = toolPtr->rect;
+	    MapWindowPoints32 (toolPtr->hwnd, (HWND32)0, (LPPOINT32)&rc, 2);
 	}
-	pt.x = (rect.left + rect.right - size.cx) / 2;
-	pt.y = rect.bottom + 2;
+	rect.left = (rc.left + rc.right - size.cx) / 2;
+	rect.top  = rc.bottom + 2;
     }
     else {
-	GetCursorPos32 (&pt);
-	pt.y += 20;
+	GetCursorPos32 ((LPPOINT32)&rect);
+	rect.top += 20;
     }
 
-    TRACE (tooltips, "pos %d - %d\n", pt.x, pt.y);
+    TRACE (tooltips, "pos %d - %d\n", rect.left, rect.top);
+
+    rect.right = rect.left + size.cx;
+    rect.bottom = rect.top + size.cy;
+
+    AdjustWindowRectEx32 (&rect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle);
 
 //    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 1, 1,
-    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, pt.x, pt.y,
-		    size.cx, size.cy, SWP_SHOWWINDOW);
+    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, rect.left, rect.top,
+		    rect.right - rect.left, rect.bottom - rect.top,
+		    SWP_SHOWWINDOW);
 
     SetTimer32 (wndPtr->hwndSelf, ID_TIMER2, infoPtr->nAutoPopTime, 0);
 }
@@ -263,7 +266,8 @@
 
     infoPtr->nCurrentTool = -1;
 
-    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0, SWP_HIDEWINDOW);
+    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0,
+		    SWP_NOZORDER | SWP_HIDEWINDOW);
 }
 
 
@@ -406,19 +410,16 @@
 	   (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
 
     if (infoPtr->uNumTools == 0) {
-	infoPtr->tools =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-		       sizeof(TTTOOL_INFO));
+	infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
 	toolPtr = infoPtr->tools;
     }
     else {
 	TTTOOL_INFO *oldTools = infoPtr->tools;
 	infoPtr->tools =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-		       sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
+	    COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
 	memcpy (infoPtr->tools, oldTools,
 		infoPtr->uNumTools * sizeof(TTTOOL_INFO));
-	HeapFree (GetProcessHeap (), 0, oldTools);
+	COMCTL32_Free (oldTools);
 	toolPtr = &infoPtr->tools[infoPtr->uNumTools];
     }
 
@@ -443,8 +444,7 @@
 	else {
 	    INT32 len = lstrlen32A (lpToolInfo->lpszText);
 	    TRACE (tooltips, "add text \"%s\"!\n", lpToolInfo->lpszText);
-	    toolPtr->lpszText =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
+	    toolPtr->lpszText =	COMCTL32_Alloc (len + 1);
 	    lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
 	}
     }
@@ -458,8 +458,8 @@
 	    LPTT_SUBCLASS_INFO lpttsi =
 		(LPTT_SUBCLASS_INFO)GetProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
 	    if (lpttsi == NULL) {
-		lpttsi = (LPTT_SUBCLASS_INFO)HeapAlloc (GetProcessHeap(),
-		    HEAP_ZERO_MEMORY, sizeof(TT_SUBCLASS_INFO));
+		lpttsi =
+		    (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
 		lpttsi->wpOrigProc = 
 		    (WNDPROC32)SetWindowLong32A ((HWND32)toolPtr->uId,
 		    GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
@@ -475,8 +475,8 @@
 	    LPTT_SUBCLASS_INFO lpttsi =
 		(LPTT_SUBCLASS_INFO)GetProp32A (toolPtr->hwnd, TT_SUBCLASS_PROP);
 	    if (lpttsi == NULL) {
-		lpttsi = (LPTT_SUBCLASS_INFO)HeapAlloc (GetProcessHeap(),
-		    HEAP_ZERO_MEMORY, sizeof(TT_SUBCLASS_INFO));
+		lpttsi =
+		    (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
 		lpttsi->wpOrigProc = 
 		    (WNDPROC32)SetWindowLong32A (toolPtr->hwnd,
 		    GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
@@ -521,7 +521,7 @@
     toolPtr = &infoPtr->tools[nTool]; 
     if ((toolPtr->hinst) && (toolPtr->lpszText)) {
 	if (toolPtr->lpszText != LPSTR_TEXTCALLBACK32A)
-	    HeapFree (GetProcessHeap (), 0, toolPtr->lpszText);
+	    COMCTL32_Free (toolPtr->lpszText);
     }
 
     /* remove subclassing */
@@ -533,7 +533,7 @@
 		SetWindowLong32A ((HWND32)toolPtr->uId, GWL_WNDPROC,
 				  (LONG)lpttsi->wpOrigProc);
 		RemoveProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
-		HeapFree (GetProcessHeap(), 0, &lpttsi);
+		COMCTL32_Free (&lpttsi);
 	    }
 	    else
 		ERR (tooltips, "Invalid data handle!\n");
@@ -546,7 +546,7 @@
 		    SetWindowLong32A ((HWND32)toolPtr->uId, GWL_WNDPROC,
 				      (LONG)lpttsi->wpOrigProc);
 		    RemoveProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
-		    HeapFree (GetProcessHeap(), 0, &lpttsi);
+		    COMCTL32_Free (&lpttsi);
 		}
 		else
 		    lpttsi->uRefCount--;
@@ -558,14 +558,13 @@
 
     /* delete tool from tool list */
     if (infoPtr->uNumTools == 1) {
-	HeapFree (GetProcessHeap (), 0, infoPtr->tools);
+	COMCTL32_Free (infoPtr->tools);
 	infoPtr->tools = NULL;
     }
     else {
 	TTTOOL_INFO *oldTools = infoPtr->tools;
 	infoPtr->tools =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-		       sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
+	    COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
 
 	if (nTool > 0)
 	    memcpy (&infoPtr->tools[0], &oldTools[0],
@@ -575,7 +574,7 @@
 	    memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
 		    (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
 
-	HeapFree (GetProcessHeap (), 0, oldTools);
+	COMCTL32_Free (oldTools);
     }
 
     infoPtr->uNumTools--;
@@ -1051,9 +1050,8 @@
 	    toolPtr->lpszText = lpToolInfo->lpszText;
 	else {
 	    INT32 len = lstrlen32A (lpToolInfo->lpszText);
-	    HeapFree (GetProcessHeap (), 0, toolPtr->lpszText);
-	    toolPtr->lpszText =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
+	    COMCTL32_Free (toolPtr->lpszText);
+	    toolPtr->lpszText =	COMCTL32_Alloc (len + 1);
 	    lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
 	}
     }
@@ -1160,9 +1158,8 @@
 	    toolPtr->lpszText = lpToolInfo->lpszText;
 	else {
 	    INT32 len = lstrlen32A (lpToolInfo->lpszText);
-	    HeapFree (GetProcessHeap (), 0, toolPtr->lpszText);
-	    toolPtr->lpszText =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
+	    COMCTL32_Free (toolPtr->lpszText);
+	    toolPtr->lpszText =	COMCTL32_Alloc (len + 1);
 	    lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
 	}
     }
@@ -1189,8 +1186,7 @@
     NONCLIENTMETRICS32A nclm;
 
     /* allocate memory for info structure */
-    infoPtr = (TOOLTIPS_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-					  sizeof(TOOLTIPS_INFO));
+    infoPtr = (TOOLTIPS_INFO *)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO));
     wndPtr->wExtra[0] = (DWORD)infoPtr;
 
     if (infoPtr == NULL) {
@@ -1219,7 +1215,8 @@
     infoPtr->nAutoPopTime   = 5000;
     infoPtr->nInitialTime   = 500;
 
-    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0, SWP_HIDEWINDOW);
+    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0,
+		    SWP_NOZORDER | SWP_HIDEWINDOW);
 
     return 0;
 }
@@ -1230,15 +1227,15 @@
 {
     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
     TTTOOL_INFO *toolPtr;
+    INT32 i;
 
     /* free tools */
     if (infoPtr->tools) {
-	INT32 i;
 	for (i = 0; i < infoPtr->uNumTools; i++) {
 	    toolPtr = &infoPtr->tools[i];
 	    if ((toolPtr->hinst) && (toolPtr->lpszText)) {
 		if (toolPtr->lpszText != LPSTR_TEXTCALLBACK32A)
-		    HeapFree (GetProcessHeap (), 0, toolPtr->lpszText);
+		    COMCTL32_Free (toolPtr->lpszText);
 	    }
 
 	    /* remove subclassing */
@@ -1254,18 +1251,18 @@
 		    SetWindowLong32A ((HWND32)toolPtr->uId, GWL_WNDPROC,
 				      (LONG)lpttsi->wpOrigProc);
 		    RemoveProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
-		    HeapFree (GetProcessHeap(), 0, &lpttsi);
+		    COMCTL32_Free (&lpttsi);
 		}
 	    }
 	}
-	HeapFree (GetProcessHeap (), 0, infoPtr->tools);
+	COMCTL32_Free (infoPtr->tools);
     }
 
     /* delete font */
     DeleteObject32 (infoPtr->hFont);
 
     /* free tool tips info data */
-    HeapFree (GetProcessHeap (), 0, infoPtr);
+    COMCTL32_Free (infoPtr);
 
     return 0;
 }
@@ -1327,7 +1324,10 @@
 TOOLTIPS_NcCreate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     wndPtr->dwStyle &= 0x0000FFFF;
-    wndPtr->dwStyle |= (WS_POPUP | WS_BORDER);
+    wndPtr->dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
+
+//    FIXME (tooltips, "style 0x%08x\n", wndPtr->dwStyle);
+//    SetParent32 (wndPtr->hwndSelf, NULL);
 
     return TRUE;
 }
diff --git a/dlls/comctl32/trackbar.c b/dlls/comctl32/trackbar.c
index f80f433..6470916 100644
--- a/dlls/comctl32/trackbar.c
+++ b/dlls/comctl32/trackbar.c
@@ -1,21 +1,31 @@
 /*
  * Trackbar control
  *
- * Copyright 1998 Eric Kohl
+ * Copyright 1998 Eric Kohli <ekohl@abo.rhein-zeitung.de>
+ * Copyright 1998 Alex Priem <alexp@sci.kun.nl>
  *
  * NOTES
- *   Development in progress. Author needed! Any volunteers?
- *   I will only improve this control once in a while.
- *     Eric <ekohl@abo.rhein-zeitung.de>
+
  *
  * TODO:
  *   - Some messages.
- *   - display code.
- *   - user interaction.
- *   - tic handling.
- *   - All notifications.
+ *   - more display code.
+ *   - dragging slider
+ *   - better tic handling.
+ *   - more notifications.
+ *   - tooltips
  */
 
+/* known bugs:
+
+	-TBM_SETRANGEMAX & TBM_SETRANGEMIN should only change the view of the
+   trackbar, not the actual amount of tics in the list.
+	-TBM_GETTIC & TBM_GETTICPOS shouldn't rely on infoPtr->tics being sorted.
+  	-code currently only handles horizontal trackbars correct.
+*/
+
+
+
 #include "windows.h"
 #include "commctrl.h"
 #include "trackbar.h"
@@ -27,88 +37,303 @@
 #define TRACKBAR_GetInfoPtr(wndPtr) ((TRACKBAR_INFO *)wndPtr->wExtra[0])
 
 
-static VOID
-TRACKBAR_Refresh (WND *wndPtr, HDC32 hdc)
+/* Used by TRACKBAR_Refresh to find out which parts of the control 
+	need to be recalculated */
+
+#define TB_THUMBCHANGED 	1
+#define TB_SELECTIONCHANGED 2
+
+
+
+static BOOL32 TRACKBAR_SendNotify (WND *wndPtr, UINT32 code);
+
+void TRACKBAR_RecalculateTics (TRACKBAR_INFO *infoPtr)
+
 {
-    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
-    RECT32 rcClient, rcChannel;
+    int i,tic,nrTics;
 
-    GetClientRect32 (wndPtr->hwndSelf, &rcClient);
+	if (infoPtr->uTicFreq) 
+    	nrTics=(infoPtr->nRangeMax - infoPtr->nRangeMin)/infoPtr->uTicFreq;
+	else {
+		nrTics=0;
+		HeapFree (SystemHeap,0,infoPtr->tics);
+		infoPtr->tics=NULL;
+		infoPtr->uNumTics=0;
+		return;
+	}
 
-    /* draw channel */
-    rcChannel = infoPtr->rcChannel;
-    DrawEdge32 (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
-    if (wndPtr->dwStyle & TBS_ENABLESELRANGE) {
-	/* fill the channel */
-	HBRUSH32 hbr = CreateSolidBrush32 (RGB(255,255,255));
-	FillRect32 (hdc, &rcChannel, hbr);
-	DeleteObject32 (hbr);
+    if (nrTics!=infoPtr->uNumTics) {
+    	infoPtr->tics=HeapReAlloc( SystemHeap, 0, infoPtr->tics,
+                           (nrTics+1)*sizeof (DWORD));
+    	infoPtr->uNumTics=nrTics;
     }
-
-    /* draw ticks */
-    if (!(wndPtr->dwStyle & TBS_NOTICKS)) {
-
-    }
-
-    /* draw thumb */
-    if (!(wndPtr->dwStyle & TBS_NOTHUMB)) {
-
-    }
-
-    if (infoPtr->bFocus)
-	DrawFocusRect32 (hdc, &rcClient);
+	infoPtr->uNumTics=nrTics;
+    tic=infoPtr->nRangeMin+infoPtr->uTicFreq;
+    for (i=0; i<nrTics; i++,tic+=infoPtr->uTicFreq)
+               infoPtr->tics[i]=tic;
 }
 
 
+
+static INT32
+TRACKBAR_ConvertPositionToTic (WND *wndPtr, TRACKBAR_INFO *infoPtr, POINT32 pt) 
+{
+	double newpos,newtic;
+    int i,range,width,delta,currentdelta,currenttic;
+
+/* buggy */
+
+    range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+    width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+	
+	newpos=(pt.x-infoPtr->rcChannel.left) / (double) width;
+
+	newtic=infoPtr->nRangeMin+newpos*range;
+	currenttic=0;
+	currentdelta=currenttic-infoPtr->nRangeMin;
+	for (i=0; i<infoPtr->uNumTics; i++) {
+		delta=newtic-infoPtr->tics[i];
+		if ((delta>0) && (delta<currentdelta)) {
+			currentdelta=delta;
+			currenttic=i;
+		}
+	}
+	return (INT32) currenttic;
+}
+
 static VOID
-TRACKBAR_Calc (WND *wndPtr, TRACKBAR_INFO *infoPtr, LPRECT32 lpRect)
+TRACKBAR_Calc (WND *wndPtr, TRACKBAR_INFO *infoPtr)
 {
     INT32 cyChannel;
+	RECT32 lpRect,*channel = & infoPtr->rcChannel;
+
+    GetClientRect32 (wndPtr->hwndSelf, &lpRect);
 
     if (wndPtr->dwStyle & TBS_ENABLESELRANGE)
-	cyChannel = MAX(infoPtr->uThumbLen - 8, 4);
+		cyChannel = MAX(infoPtr->uThumbLen - 8, 4);
     else
-	cyChannel = 4;
+		cyChannel = 4;
 
     /* calculate channel rect */
     if (wndPtr->dwStyle & TBS_VERT) {
-	infoPtr->rcChannel.top = lpRect->top + 8;
-	infoPtr->rcChannel.bottom = lpRect->bottom - 8;
+		channel->top    = lpRect.top + 8;
+		channel->bottom = lpRect.bottom - 8;
 
-	if (wndPtr->dwStyle & TBS_BOTH) {
-	    infoPtr->rcChannel.left = (lpRect->bottom - cyChannel ) / 2;
-	    infoPtr->rcChannel.right = (lpRect->bottom + cyChannel) / 2;
+			if (wndPtr->dwStyle & TBS_BOTH) {
+	    		channel->left  = (lpRect.bottom - cyChannel) / 2;
+	    		channel->right = (lpRect.bottom + cyChannel) / 2;
+			}
+			else if (wndPtr->dwStyle & TBS_LEFT) {
+	    			channel->left  = lpRect.left + 10;
+	    			channel->right = channel->left + cyChannel;
+				}
+				else { /* TBS_RIGHT */
+	    			channel->right = lpRect.right - 10;
+	    			channel->left  = channel->right - cyChannel;
+				}
+   	}
+   	else {
+			channel->left = lpRect.left + 8;
+			channel->right = lpRect.right - 8;
+			if (wndPtr->dwStyle & TBS_BOTH) {
+	    		channel->top		= (lpRect.bottom - cyChannel) / 2;
+	    		channel->bottom 	= (lpRect.bottom + cyChannel) / 2;
+			}
+			else if (wndPtr->dwStyle & TBS_TOP) {
+	    			channel->top    = lpRect.top + 10;
+	    			channel->bottom = channel->top + cyChannel;
+				}
+				else { /* TBS_BOTTOM */
+	    			channel->bottom = lpRect.bottom - 10;
+	    			channel->top    = channel->bottom - cyChannel;
+				}
 	}
-	else if (wndPtr->dwStyle & TBS_LEFT) {
-	    infoPtr->rcChannel.left = lpRect->left + 10;
-	    infoPtr->rcChannel.right = infoPtr->rcChannel.left + cyChannel;
-	}
-	else {
-	    /* TBS_RIGHT */
-	    infoPtr->rcChannel.right = lpRect->right - 10;
-	    infoPtr->rcChannel.left = infoPtr->rcChannel.right - cyChannel;
-	}
-    }
-    else {
-	infoPtr->rcChannel.left = lpRect->left + 8;
-	infoPtr->rcChannel.right = lpRect->right - 8;
-
-	if (wndPtr->dwStyle & TBS_BOTH) {
-	    infoPtr->rcChannel.top = (lpRect->bottom - cyChannel ) / 2;
-	    infoPtr->rcChannel.bottom = (lpRect->bottom + cyChannel) / 2;
-	}
-	else if (wndPtr->dwStyle & TBS_TOP) {
-	    infoPtr->rcChannel.top = lpRect->top + 10;
-	    infoPtr->rcChannel.bottom = infoPtr->rcChannel.top + cyChannel;
-	}
-	else {
-	    /* TBS_BOTTOM */
-	    infoPtr->rcChannel.bottom = lpRect->bottom - 10;
-	    infoPtr->rcChannel.top = infoPtr->rcChannel.bottom - cyChannel;
-	}
-    }
 }
 
+static VOID
+TRACKBAR_CalcThumb (WND *wndPtr, TRACKBAR_INFO *infoPtr)
+
+{
+	RECT32 *thumb;
+	int range, width;
+	
+	thumb=&infoPtr->rcThumb;
+	range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+    width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+
+	thumb->left  = infoPtr->rcChannel.left +
+					width*(65536*infoPtr->nPos/range)/65536 - 5;
+	thumb->right  = thumb->left + 10;
+	thumb->top	  = infoPtr->rcChannel.top - 1;
+	thumb->bottom = infoPtr->rcChannel.top + infoPtr->uThumbLen - 8;
+}
+
+static VOID
+TRACKBAR_CalcSelection (WND *wndPtr, TRACKBAR_INFO *infoPtr)
+{
+	RECT32 *selection;
+	int range, width;
+
+	selection= & infoPtr->rcSelection;
+	range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+    width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+	
+	selection->left   = infoPtr->rcChannel.left +
+						width*(65536*infoPtr->nSelMin/range)/65536;
+	selection->right  = infoPtr->rcChannel.left +
+						width*(65536*infoPtr->nSelMax/range)/65536;
+	selection->top    = infoPtr->rcChannel.top + 2;
+    selection->bottom = infoPtr->rcChannel.bottom - 2;
+}
+
+
+
+static VOID
+TRACKBAR_Refresh (WND *wndPtr, HDC32 hdc)
+{
+	TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+	RECT32 rcClient, rcChannel, rcSelection;
+	HBRUSH32 hBrush = CreateSolidBrush32 (infoPtr->clrBk);
+	INT32 x,y,tic;
+	int i,range,width;
+
+    GetClientRect32 (wndPtr->hwndSelf, &rcClient);
+	hBrush = CreateSolidBrush32 (infoPtr->clrBk);
+	FillRect32 (hdc, &rcClient, hBrush);
+    DeleteObject32 (hBrush);
+
+	
+	
+	if (infoPtr->flags & TB_THUMBCHANGED) 
+		TRACKBAR_CalcThumb	(wndPtr, infoPtr);
+	if (infoPtr->flags & TB_SELECTIONCHANGED)
+		TRACKBAR_CalcSelection (wndPtr, infoPtr);
+	infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED);
+
+    /* draw channel */
+
+    rcChannel = infoPtr->rcChannel;
+    rcSelection= infoPtr->rcSelection;
+    DrawEdge32 (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
+
+    if (wndPtr->dwStyle & TBS_ENABLESELRANGE) {		 /* fill the channel */
+		HBRUSH32 hbr = CreateSolidBrush32 (RGB(255,255,255));
+		FillRect32 (hdc, &rcChannel, hbr);
+		if (rcSelection.left!=rcSelection.right) {
+			hbr=CreateSolidBrush32 (COLOR_HIGHLIGHT); 
+			FillRect32 (hdc, &rcSelection, hbr);
+		}
+		DeleteObject32 (hbr);
+    }
+
+
+    /* draw tics */
+
+    if (!(wndPtr->dwStyle & TBS_NOTICKS)) {
+		COLORREF clrTic=GetSysColor32 (COLOR_3DDKSHADOW);
+
+    	x=rcChannel.left;
+    	y=rcChannel.bottom+2;
+		range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+		width=rcChannel.right - rcChannel.left;
+    	if (wndPtr->dwStyle & TBS_VERT) { /* swap x/y */
+        }
+
+    if ((wndPtr->dwStyle & TBS_TOP) || (wndPtr->dwStyle & TBS_BOTH)) {
+        /* draw upper tics */
+     }
+
+//    if (!((wndPtr->dwStyle & TBS_TOP) || (!(wndPtr->dwStyle & TBS_BOTH)))) 
+        /* draw lower tics */
+//    if (wndPtr->dwStyle & TBS_AUTOTICKS) 
+        for (i=0; i<infoPtr->uNumTics; i++) {
+			tic=infoPtr->tics[i];
+			if ((tic>infoPtr->nRangeMin) && (tic<infoPtr->nRangeMax)) {
+            	x=rcChannel.left + width*(65536*tic/range)/65536;
+            	SetPixel32 (hdc, x,y+5, clrTic);
+            	SetPixel32 (hdc, x,y+6, clrTic);
+            	SetPixel32 (hdc, x,y+7, clrTic);
+			}
+          }
+	   if ((wndPtr->dwStyle & TBS_ENABLESELRANGE) && 
+		   (rcSelection.left!=rcSelection.right)) {
+			x=rcChannel.left + width*(65536*infoPtr->nSelMin/range)/65536 - 1;
+           	SetPixel32 (hdc, x,y+6, clrTic);
+           	SetPixel32 (hdc, x,y+7, clrTic);
+			x=rcChannel.left + width*(65536*infoPtr->nSelMax/range)/65536 + 1; 
+           	SetPixel32 (hdc, x,y+6, clrTic);
+           	SetPixel32 (hdc, x,y+7, clrTic);
+		}
+		
+	   x=rcChannel.left;
+       SetPixel32 (hdc, x,y+5, clrTic);
+       SetPixel32 (hdc, x,y+6, clrTic);
+       SetPixel32 (hdc, x,y+7, clrTic);
+       SetPixel32 (hdc, x,y+8, clrTic);
+	   x=rcChannel.right;
+       SetPixel32 (hdc, x,y+5, clrTic);
+       SetPixel32 (hdc, x,y+6, clrTic);
+       SetPixel32 (hdc, x,y+7, clrTic);
+       SetPixel32 (hdc, x,y+8, clrTic);
+//     }
+    }
+
+ 
+     /* draw thumb */
+
+     if (!(wndPtr->dwStyle & TBS_NOTHUMB)) {
+        HBRUSH32 hbr = CreateSolidBrush32 (COLOR_BACKGROUND);
+		RECT32 thumb = infoPtr->rcThumb;
+
+		SelectObject32 (hdc, hbr);
+		
+		if (wndPtr->dwStyle & TBS_BOTH) {
+        	FillRect32 (hdc, &thumb, hbr);
+  			DrawEdge32 (hdc, &thumb, EDGE_RAISED, BF_TOPLEFT);
+		} else {
+
+		POINT32 points[6];
+		RECT32 triangle;	/* for correct shadows of thumb */
+
+ 			/* first, fill the thumb */
+		
+		SetPolyFillMode32 (hdc,WINDING);
+		points[0].x=thumb.left;
+		points[0].y=thumb.top;
+		points[1].x=thumb.right - 1;
+		points[1].y=thumb.top;
+		points[2].x=thumb.right - 1;
+		points[2].y=thumb.bottom -2;
+		points[3].x=(thumb.right + thumb.left-1)/2;
+		points[3].y=thumb.bottom+4;
+		points[4].x=thumb.left;
+		points[4].y=thumb.bottom -2;
+		points[5].x=points[0].x;
+		points[5].y=points[0].y;
+		Polygon32 (hdc, points, 6);
+		DrawEdge32 (hdc, &thumb, EDGE_RAISED, BF_TOPLEFT);
+//		DrawEdge32 (hdc, &thumb, EDGE_SUNKEN, BF_BOTTOMRIGHT);
+
+			/* draw notch */
+
+		triangle.right = thumb.right+5;
+		triangle.left  = points[3].x+5;
+		triangle.top   = thumb.bottom +5;
+		triangle.bottom= thumb.bottom +1;
+		DrawEdge32 (hdc, &triangle, EDGE_SUNKEN, BF_DIAGONAL | BF_TOP | BF_RIGHT);
+		triangle.left  = thumb.left+6;
+		triangle.right = points[3].x+6;
+		DrawEdge32 (hdc, &triangle, EDGE_RAISED, BF_DIAGONAL | BF_TOP | BF_LEFT);
+		}
+		DeleteObject32 (hbr);
+     }
+
+    if (infoPtr->bFocus)
+		DrawFocusRect32 (hdc, &rcClient);
+}
+
+
+
 
 static VOID
 TRACKBAR_AlignBuddies (WND *wndPtr, TRACKBAR_INFO *infoPtr)
@@ -169,11 +394,12 @@
 
     infoPtr->nSelMin = 0;
     infoPtr->nSelMax = 0;
+	infoPtr->flags |=TB_SELECTIONCHANGED;
 
     if ((BOOL32)wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -186,16 +412,15 @@
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
     if (infoPtr->tics) {
-	FIXME (trackbar, "is this correct??\n");
-	HeapFree (GetProcessHeap (), 0, infoPtr->tics);
-	infoPtr->tics = NULL;
-	infoPtr->uNumTics = 2;
+		HeapFree (GetProcessHeap (), 0, infoPtr->tics);
+		infoPtr->tics = NULL;
+		infoPtr->uNumTics = 0;
     }
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -207,9 +432,8 @@
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
-    if (wParam)
-	/* buddy is left or above */
-	return (LRESULT)infoPtr->hwndBuddyLA;
+    if (wParam)		 /* buddy is left or above */
+		return (LRESULT)infoPtr->hwndBuddyLA;
 
     /* buddy is right or below */
     return (LRESULT) infoPtr->hwndBuddyRB;
@@ -223,7 +447,7 @@
     LPRECT32 lprc = (LPRECT32)lParam;
 
     if (lprc == NULL)
-	return 0;
+		return 0;
 
     lprc->left   = infoPtr->rcChannel.left;
     lprc->right  = infoPtr->rcChannel.right;
@@ -249,9 +473,9 @@
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
     if (wndPtr->dwStyle & TBS_NOTICKS)
-	return 0;
+		return 0;
 
-    return infoPtr->uNumTics;
+    return infoPtr->uNumTics+2;
 }
 
 
@@ -273,7 +497,6 @@
 }
 
 
-// << TRACKBAR_GetPTics >>
 
 
 static LRESULT
@@ -320,20 +543,78 @@
     return infoPtr->uThumbLen;
 }
 
+static LRESULT
+TRACKBAR_GetPTics (WND *wndPtr)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+    
+   return (LRESULT) infoPtr->tics;
+}
+
+static LRESULT
+TRACKBAR_GetThumbRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+    LPRECT32 lprc = (LPRECT32)lParam;
+    
+    if (lprc == NULL)
+   		return 0; 
+   
+    lprc->left   = infoPtr->rcThumb.left;
+    lprc->right  = infoPtr->rcThumb.right;
+    lprc->bottom = infoPtr->rcThumb.bottom;
+    lprc->top    = infoPtr->rcThumb.top;
+   
+    return 0;
+}  
 
 
-// << TRACKBAR_GetThumbRect >>
-//	case TBM_GETTIC:
-//	case TBM_GETTICPOS:
 
 
+
+static LRESULT
+TRACKBAR_GetTic (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+
+{
+ TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+ INT32 iTic;
+
+ iTic=(INT32) wParam;
+ if ((iTic<0) || (iTic>infoPtr->uNumTics)) 
+	return -1;
+
+ return (LRESULT) infoPtr->tics[iTic];
+
+}
+
+
+static LRESULT
+TRACKBAR_GetTicPos (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+
+{
+ TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+ INT32 iTic, range, width, pos;
+ 
+
+ iTic=(INT32 ) wParam;
+ if ((iTic<0) || (iTic>infoPtr->uNumTics)) 
+	return -1;
+
+ range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+ width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+ pos=infoPtr->rcChannel.left + width*(65536*infoPtr->tics[iTic]/range)/65536;
+
+
+ return (LRESULT) pos;
+}
+
 static LRESULT
 TRACKBAR_GetToolTips (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
     if (wndPtr->dwStyle & TBS_TOOLTIPS)
-	return (LRESULT)infoPtr->hwndToolTip;
+		return (LRESULT)infoPtr->hwndToolTip;
     return 0;
 }
 
@@ -355,11 +636,11 @@
 	FIXME (trackbar, "move buddy!\n");
     }
     else {
-	/* buddy is right or below */
-	hwndTemp = infoPtr->hwndBuddyRB;
-	infoPtr->hwndBuddyRB = (HWND32)lParam;
+		/* buddy is right or below */
+		hwndTemp = infoPtr->hwndBuddyRB;
+		infoPtr->hwndBuddyRB = (HWND32)lParam;
 
-	FIXME (trackbar, "move buddy!\n");
+		FIXME (trackbar, "move buddy!\n");
     }
 
     TRACKBAR_AlignBuddies (wndPtr, infoPtr);
@@ -404,11 +685,12 @@
 
     if (infoPtr->nPos > infoPtr->nRangeMax)
 	infoPtr->nPos = infoPtr->nRangeMax;
+	infoPtr->flags |=TB_THUMBCHANGED;
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -419,20 +701,26 @@
 TRACKBAR_SetRange (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
-
     infoPtr->nRangeMin = (INT32)LOWORD(lParam);
     infoPtr->nRangeMax = (INT32)HIWORD(lParam);
 
-    if (infoPtr->nPos < infoPtr->nRangeMin)
-	infoPtr->nPos = infoPtr->nRangeMin;
+    if (infoPtr->nPos < infoPtr->nRangeMin) {
+		infoPtr->nPos = infoPtr->nRangeMin;
+		infoPtr->flags |=TB_THUMBCHANGED;
+	}
 
-    if (infoPtr->nPos > infoPtr->nRangeMax)
-	infoPtr->nPos = infoPtr->nRangeMax;
+    if (infoPtr->nPos > infoPtr->nRangeMax) {
+		infoPtr->nPos = infoPtr->nRangeMax;
+		infoPtr->flags |=TB_THUMBCHANGED;
+	}
+
+	infoPtr->nPageSize=(infoPtr->nRangeMax -  infoPtr->nRangeMin)/5;
+	TRACKBAR_RecalculateTics (infoPtr);
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -445,13 +733,18 @@
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
     infoPtr->nRangeMax = (INT32)lParam;
-    if (infoPtr->nPos > infoPtr->nRangeMax)
-	infoPtr->nPos = infoPtr->nRangeMax;
+    if (infoPtr->nPos > infoPtr->nRangeMax) {
+		infoPtr->nPos = infoPtr->nRangeMax;
+		infoPtr->flags |=TB_THUMBCHANGED;
+	}
+
+	infoPtr->nPageSize=(infoPtr->nRangeMax -  infoPtr->nRangeMin)/5;
+	TRACKBAR_RecalculateTics (infoPtr);
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -464,39 +757,62 @@
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
     infoPtr->nRangeMin = (INT32)lParam;
-    if (infoPtr->nPos < infoPtr->nRangeMin)
-	infoPtr->nPos = infoPtr->nRangeMin;
+    if (infoPtr->nPos < infoPtr->nRangeMin) {
+		infoPtr->nPos = infoPtr->nRangeMin;
+		infoPtr->flags |=TB_THUMBCHANGED;
+	}
+
+	infoPtr->nPageSize=(infoPtr->nRangeMax -  infoPtr->nRangeMin)/5;
+	TRACKBAR_RecalculateTics (infoPtr);
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
 }
 
+static LRESULT
+TRACKBAR_SetTicFreq (WND *wndPtr, WPARAM32 wParam)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+	HDC32 hdc;
+	
+    if (wndPtr->dwStyle & TBS_AUTOTICKS) 
+           	infoPtr->uTicFreq=(UINT32) wParam; 
+	
+	TRACKBAR_RecalculateTics (infoPtr);
+
+	hdc = GetDC32 (wndPtr->hwndSelf);
+    TRACKBAR_Refresh (wndPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
+	return 0;
+}   
+
 
 static LRESULT
 TRACKBAR_SetSel (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
-    if (!wndPtr->dwStyle & TBS_ENABLESELRANGE)
-	return 0;
-
     infoPtr->nSelMin = (INT32)LOWORD(lParam);
     infoPtr->nSelMax = (INT32)HIWORD(lParam);
+	infoPtr->flags |=TB_SELECTIONCHANGED;
+
+    if (!wndPtr->dwStyle & TBS_ENABLESELRANGE)
+		return 0;
 
     if (infoPtr->nSelMin < infoPtr->nRangeMin)
-	infoPtr->nSelMin = infoPtr->nRangeMin;
+		infoPtr->nSelMin = infoPtr->nRangeMin;
     if (infoPtr->nSelMax > infoPtr->nRangeMax)
-	infoPtr->nSelMax = infoPtr->nRangeMax;
+		infoPtr->nSelMax = infoPtr->nRangeMax;
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -512,13 +828,15 @@
 	return 0;
 
     infoPtr->nSelMax = (INT32)lParam;
+	infoPtr->flags  |=TB_SELECTIONCHANGED;
+	
     if (infoPtr->nSelMax > infoPtr->nRangeMax)
-	infoPtr->nSelMax = infoPtr->nRangeMax;
+		infoPtr->nSelMax = infoPtr->nRangeMax;
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -534,13 +852,14 @@
 	return 0;
 
     infoPtr->nSelMin = (INT32)lParam;
+	infoPtr->flags  |=TB_SELECTIONCHANGED;
     if (infoPtr->nSelMin < infoPtr->nRangeMin)
-	infoPtr->nSelMin = infoPtr->nRangeMin;
+		infoPtr->nSelMin = infoPtr->nRangeMin;
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -551,10 +870,16 @@
 TRACKBAR_SetThumbLength (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+	HDC32 hdc;
 
     if (wndPtr->dwStyle & TBS_FIXEDLENGTH)
-	infoPtr->uThumbLen = (UINT32)wParam;
+		infoPtr->uThumbLen = (UINT32)wParam;
 
+	hdc = GetDC32 (wndPtr->hwndSelf);
+	infoPtr->flags |=TB_THUMBCHANGED;
+	TRACKBAR_Refresh (wndPtr, hdc);
+	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+	
     return 0;
 }
 
@@ -564,19 +889,24 @@
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
     INT32 nPos = (INT32)lParam;
+	HDC32 hdc;
 
-    if (nPos < infoPtr->nRangeMin)
-	return FALSE;
-    if (nPos > infoPtr->nRangeMax)
-	return FALSE;
+    if ((nPos < infoPtr->nRangeMin) || (nPos> infoPtr->nRangeMax))
+		return FALSE;
 
-    FIXME (trackbar, "%d - empty stub!\n", nPos);
+	infoPtr->uNumTics++;
+    infoPtr->tics=HeapReAlloc( SystemHeap, 0, infoPtr->tics,
+                           (infoPtr->uNumTics)*sizeof (DWORD));
+    infoPtr->tics[infoPtr->uNumTics-1]=nPos;
+
+ 	hdc = GetDC32 (wndPtr->hwndSelf);
+    TRACKBAR_Refresh (wndPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
 
     return TRUE;
 }
 
 
-//	case TBM_SETTICFREQ:
 
 
 static LRESULT
@@ -586,7 +916,7 @@
     INT32 fTemp = infoPtr->fLocation;
 
     infoPtr->fLocation = (INT32)wParam;
-
+	
     return fTemp;
 }
 
@@ -605,6 +935,19 @@
 //	case TBM_SETUNICODEFORMAT:
 
 
+static LRESULT
+TRACKBAR_InitializeThumb (WND *wndPtr)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+
+    infoPtr->uThumbLen = 23;   /* initial thumb length */
+
+	TRACKBAR_Calc (wndPtr,infoPtr);
+	TRACKBAR_CalcThumb (wndPtr, infoPtr);
+	infoPtr->flags &= ~TB_SELECTIONCHANGED;
+
+	return 0;
+}
 
 
 static LRESULT
@@ -617,18 +960,21 @@
     wndPtr->wExtra[0] = (DWORD)infoPtr;
 
 
-    /* default values */
-    infoPtr->nRangeMin = 0;
+    infoPtr->nRangeMin = 0;			 /* default values */
     infoPtr->nRangeMax = 100;
     infoPtr->nLineSize = 1;
     infoPtr->nPageSize = 20;
     infoPtr->nSelMin   = 0;
     infoPtr->nSelMax   = 0;
     infoPtr->nPos      = 0;
-    infoPtr->uThumbLen = 23;   /* initial thumb length */
-    infoPtr->uNumTics  = 2;    /* default start and end tic */
 
+    infoPtr->uNumTics  = 0;    /* start and end tic are not included in count*/
+	infoPtr->uTicFreq  = 1;
+	infoPtr->tics	   = NULL;
+	infoPtr->clrBk	   = GetSysColor32 (COLOR_BACKGROUND);
 
+	TRACKBAR_InitializeThumb (wndPtr);
+	
     return 0;
 }
 
@@ -667,12 +1013,64 @@
 TRACKBAR_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
-
+	int prevPlace,range,width,clickPlace,prevPos;
+	
     SetFocus32 (wndPtr->hwndSelf);
 
+	clickPlace=(INT32)LOWORD(lParam);
+    range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+    width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+    prevPlace = infoPtr->rcChannel.left +
+                    width*(65536*infoPtr->nPos/range)/65536;
+	printf ("%d->%d\n",prevPlace,clickPlace);
+
+	prevPos	= infoPtr->nPos;
+	if (clickPlace > prevPlace) {					/* similar to VK_NEXT */
+		infoPtr->nPos += infoPtr->nPageSize;
+        if (infoPtr->nPos > infoPtr->nRangeMax)
+			infoPtr->nPos = infoPtr->nRangeMax;
+		TRACKBAR_SendNotify (wndPtr, TB_PAGEUP);  
+	} else {
+        infoPtr->nPos -= infoPtr->nPageSize;	/* similar to VK_PRIOR */
+        if (infoPtr->nPos < infoPtr->nRangeMin)
+            infoPtr->nPos = infoPtr->nRangeMin;
+        TRACKBAR_SendNotify (wndPtr, TB_PAGEDOWN);
+	}
+
+	printf ("%d->%d\n",prevPos,infoPtr->nPos);
+	if (prevPos!=infoPtr->nPos) {
+    	HDC32 hdc;
+
+    	hdc=GetDC32 (wndPtr->hwndSelf);
+		infoPtr->flags |=TB_THUMBCHANGED;
+    	TRACKBAR_Refresh (wndPtr, hdc);
+    	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+ 	}
+
+
     return 0;
 }
 
+static LRESULT
+TRACKBAR_LButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+
+    FIXME (trackbar,"stub\n");
+
+	TRACKBAR_SendNotify (wndPtr, TB_ENDTRACK);
+
+    return 0;
+}
+
+static LRESULT
+TRACKBAR_CaptureChanged (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    FIXME (trackbar,"stub\n");
+
+	TRACKBAR_SendNotify (wndPtr, TB_ENDTRACK);
+	return 0;
+}
 
 static LRESULT
 TRACKBAR_Paint (WND *wndPtr, WPARAM32 wParam)
@@ -708,11 +1106,8 @@
 TRACKBAR_Size (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
-    RECT32 rcClient;
 
-    GetClientRect32 (wndPtr->hwndSelf, &rcClient);
-
-    TRACKBAR_Calc (wndPtr, infoPtr, &rcClient);
+    TRACKBAR_Calc (wndPtr, infoPtr);
     TRACKBAR_AlignBuddies (wndPtr, infoPtr);
 
     return 0;
@@ -720,9 +1115,111 @@
 
 
 // << TRACKBAR_Timer >>
-// << TRACKBAR_WinIniChange >>
 
 
+static BOOL32
+TRACKBAR_SendNotify (WND *wndPtr, UINT32 code)
+
+{
+    TRACE (trackbar, "%x\n",code);
+	if (wndPtr->dwStyle & TBS_VERT) 
+    	return (BOOL32) SendMessage32A (GetParent32 (wndPtr->hwndSelf), 
+						WM_VSCROLL, (WPARAM32)code, (LPARAM) wndPtr->hwndSelf);
+
+   	return (BOOL32) SendMessage32A (GetParent32 (wndPtr->hwndSelf), 
+						WM_HSCROLL, (WPARAM32)code, (LPARAM) wndPtr->hwndSelf);
+}
+
+static LRESULT
+TRACKBAR_MouseMove (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+			
+	
+ 	return TRUE;
+}
+
+
+static LRESULT
+TRACKBAR_KeyDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+	INT32 pos;
+
+    TRACE (trackbar, "%x\n",wParam);
+
+	pos=infoPtr->nPos;
+	switch (wParam) {
+		case VK_LEFT:
+		case VK_UP: 
+			if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
+			infoPtr->nPos -= infoPtr->nLineSize;
+			if (infoPtr->nPos < infoPtr->nRangeMin) 
+				infoPtr->nPos = infoPtr->nRangeMin;
+			TRACKBAR_SendNotify (wndPtr, TB_LINEUP);
+			break;
+		case VK_RIGHT:
+		case VK_DOWN: 
+			if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
+			infoPtr->nPos += infoPtr->nLineSize;
+			if (infoPtr->nPos > infoPtr->nRangeMax) 
+				infoPtr->nPos = infoPtr->nRangeMax;
+			TRACKBAR_SendNotify (wndPtr, TB_LINEDOWN);
+            break;
+		case VK_NEXT:
+			if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
+			infoPtr->nPos += infoPtr->nPageSize;
+			if (infoPtr->nPos > infoPtr->nRangeMax) 
+				infoPtr->nPos = infoPtr->nRangeMax;
+			 TRACKBAR_SendNotify (wndPtr, TB_PAGEUP);
+            break;
+		case VK_PRIOR:
+			if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
+			infoPtr->nPos -= infoPtr->nPageSize;
+			if (infoPtr->nPos < infoPtr->nRangeMin) 
+				infoPtr->nPos = infoPtr->nRangeMin;
+			TRACKBAR_SendNotify (wndPtr, TB_PAGEDOWN);
+            break;
+		case VK_HOME: 
+			if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
+			infoPtr->nPos = infoPtr->nRangeMin;
+			TRACKBAR_SendNotify (wndPtr, TB_TOP);
+            break;
+		case VK_END: 
+			if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
+			infoPtr->nPos = infoPtr->nRangeMax;
+	 		TRACKBAR_SendNotify (wndPtr, TB_BOTTOM);
+            break;
+	}
+
+ if (pos!=infoPtr->nPos) { 
+	HDC32 hdc;
+
+	hdc=GetDC32 (wndPtr->hwndSelf);
+	infoPtr->flags |=TB_THUMBCHANGED;
+	TRACKBAR_Refresh (wndPtr, hdc);
+	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+ }
+
+ return TRUE;
+}
+
+static LRESULT
+TRACKBAR_KeyUp (WND *wndPtr, WPARAM32 wParam)
+{
+	switch (wParam) {
+		case VK_LEFT:
+		case VK_UP: 
+		case VK_RIGHT:
+		case VK_DOWN: 
+		case VK_NEXT:
+		case VK_PRIOR:
+		case VK_HOME: 
+		case VK_END: 	TRACKBAR_SendNotify (wndPtr, TB_ENDTRACK);
+	}
+ return TRUE;
+}
+
 LRESULT WINAPI
 TRACKBAR_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
 {
@@ -754,7 +1251,8 @@
 	case TBM_GETPOS:
 	    return TRACKBAR_GetPos (wndPtr, wParam, lParam);
 
-//	case TBM_GETPTICS:
+	case TBM_GETPTICS:
+		 return TRACKBAR_GetPTics (wndPtr);
 
 	case TBM_GETRANGEMAX:
 	    return TRACKBAR_GetRangeMax (wndPtr, wParam, lParam);
@@ -771,10 +1269,15 @@
 	case TBM_GETTHUMBLENGTH:
 	    return TRACKBAR_GetThumbLength (wndPtr, wParam, lParam);
 
-//	case TBM_GETTHUMBRECT:
-//	case TBM_GETTIC:
-//	case TBM_GETTICPOS:
+	case TBM_GETTHUMBRECT:
+        return TRACKBAR_GetThumbRect (wndPtr, wParam, lParam);
 
+    case TBM_GETTIC:
+        return TRACKBAR_GetTic (wndPtr, wParam, lParam);
+ 
+    case TBM_GETTICPOS:
+        return TRACKBAR_GetTicPos (wndPtr, wParam, lParam);
+ 
 	case TBM_GETTOOLTIPS:
 	    return TRACKBAR_GetToolTips (wndPtr, wParam, lParam);
 
@@ -816,7 +1319,9 @@
 	case TBM_SETTIC:
 	    return TRACKBAR_SetTic (wndPtr, wParam, lParam);
 
-//	case TBM_SETTICFREQ:
+    case TBM_SETTICFREQ:
+       return TRACKBAR_SetTicFreq (wndPtr, wParam);
+
 
 	case TBM_SETTIPSIDE:
 	    return TRACKBAR_SetTipSide (wndPtr, wParam, lParam);
@@ -827,7 +1332,8 @@
 //	case TBM_SETUNICODEFORMAT:
 
 
-//	case WM_CAPTURECHANGED:
+	case WM_CAPTURECHANGED:
+	    return TRACKBAR_CaptureChanged (wndPtr, wParam, lParam);
 
 	case WM_CREATE:
 	    return TRACKBAR_Create (wndPtr, wParam, lParam);
@@ -843,9 +1349,11 @@
 	case WM_GETDLGCODE:
 	    return DLGC_WANTARROWS;
 
-//	case WM_KEYDOWN:
-
-//	case WM_KEYUP:
+ 	case WM_KEYDOWN:
+       return TRACKBAR_KeyDown (wndPtr, wParam, lParam);
+        
+  	case WM_KEYUP:
+       return TRACKBAR_KeyUp (wndPtr, wParam);
 
 	case WM_KILLFOCUS:
 	    return TRACKBAR_KillFocus (wndPtr, wParam, lParam);
@@ -853,10 +1361,11 @@
 	case WM_LBUTTONDOWN:
 	    return TRACKBAR_LButtonDown (wndPtr, wParam, lParam);
 
-//	case WM_LBUTTONUP:
+	case WM_LBUTTONUP:
+	    return TRACKBAR_LButtonUp (wndPtr, wParam, lParam);
 
-//	case WM_MOUSEMOVE:
-//	    return TRACKBAR_MouseMove (wndPtr, wParam, lParam);
+	case WM_MOUSEMOVE:
+	    return TRACKBAR_MouseMove (wndPtr, wParam, lParam);
 
 	case WM_PAINT:
 	    return TRACKBAR_Paint (wndPtr, wParam);
@@ -869,7 +1378,8 @@
 
 //	case WM_TIMER:
 
-//	case WM_WININICHANGE:
+	case WM_WININICHANGE:
+		return TRACKBAR_InitializeThumb (wndPtr);
 
 	default:
 	    if (uMsg >= WM_USER)
diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c
index a4eac47..9b5fcf5 100644
--- a/dlls/comctl32/treeview.c
+++ b/dlls/comctl32/treeview.c
@@ -1,16 +1,28 @@
-/*
- * Treeview control
+/* Treeview control
  *
- * Copyright 1998 Eric Kohl
+ * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
+ * Copyright 1998 Alex Priem <alexp@sci.kun.nl>
  *
- * NOTES
- *   This is just a dummy control. An author is needed! Any volunteers?
- *   I will only improve this control once in a while.
- *     Eric <ekohl@abo.rhein-zeitung.de>
  *
  * TODO:
- *   - All messages.
- *   - All notifications.
+ *   - Nearly all notifications.
+ * 
+ *   list-handling stuff: sort, sorted insertitem.
+ *
+ *   refreshtreeview: 	
+		-small array containing info about positions.
+ 		-better implementation of DrawItem (connecting lines).
+		-implement partial drawing?
+ *   Expand:		-ctlmacro expands twice ->toggle.
+ *  -drag&drop.
+ *  -scrollbars.
+ *  -Unicode messages
+ *  -TVITEMEX 
+ *
+ * FIXMEs:  
+   -GetNextItem: add flag for traversing visible items 
+   -DblClick:	ctlmacro.exe's NM_DBLCLK seems to go wrong (returns FALSE).
+	     
  */
 
 #include "windows.h"
@@ -19,26 +31,225 @@
 #include "heap.h"
 #include "win.h"
 #include "debug.h"
+#include <asm/bitops.h>      /* FIXME: linux specific */
+
+static int TREEVIEW_Timer;
+
 
 
 #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
 
 
 
+#include <asm/bitops.h>      /* FIXME: linux specific */
+
+static int TREEVIEW_Timer;
+
+  
+  #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
+  
+  
+  
+
+static BOOL32
+TREEVIEW_SendSimpleNotify (WND *wndPtr, UINT32 code);
+static BOOL32
+TREEVIEW_SendTreeviewNotify (WND *wndPtr, UINT32 code, UINT32 action, 
+			INT32 oldItem, INT32 newItem, POINT32 pt);
+static LRESULT
+TREEVIEW_SelectItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static void
+TREEVIEW_Refresh (WND *wndPtr, HDC32 hdc);
+
+
+
+
+
+/* helper functions. Work with the assumption that validity of operands 
+   is checked beforehand */
+
+
+static TREEVIEW_ITEM *
+TREEVIEW_ValidItem (TREEVIEW_INFO *infoPtr,int  handle)
+{
+ 
+ if ((!handle) || (handle>infoPtr->uMaxHandle)) return NULL;
+ if (test_bit (handle, infoPtr->freeList)) return NULL;
+
+ return & infoPtr->items[handle];
+}
+
+
+
+static TREEVIEW_ITEM *TREEVIEW_GetPrevListItem (TREEVIEW_INFO *infoPtr, 
+					TREEVIEW_ITEM *tvItem)
+
+{
+ TREEVIEW_ITEM *wineItem;
+
+ if (tvItem->upsibling) 
+		return (& infoPtr->items[tvItem->upsibling]);
+
+ wineItem=tvItem;
+ while (wineItem->parent) {
+	wineItem=& infoPtr->items[wineItem->parent];
+	if (wineItem->upsibling) 
+                return (& infoPtr->items[wineItem->upsibling]);
+ } 
+
+ return NULL;
+}
+
+static TREEVIEW_ITEM *TREEVIEW_GetNextListItem (TREEVIEW_INFO *infoPtr, 
+					TREEVIEW_ITEM *tvItem)
+
+{
+ TREEVIEW_ITEM *wineItem;
+
+ if (tvItem->sibling) 
+		return (& infoPtr->items[tvItem->sibling]);
+
+ wineItem=tvItem;
+ while (wineItem->parent) {
+	wineItem=& infoPtr->items [wineItem->parent];
+	if (wineItem->sibling) 
+                return (& infoPtr->items [wineItem->sibling]);
+ } 
+
+ return NULL;
+}
+
+static TREEVIEW_ITEM *TREEVIEW_GetLastListItem (TREEVIEW_INFO *infoPtr)
+
+{
+  TREEVIEW_ITEM *wineItem;
+  
+ wineItem=NULL;
+ if (infoPtr->TopRootItem) 
+	wineItem=& infoPtr->items [infoPtr->TopRootItem];
+ while (wineItem->sibling) 
+	wineItem=& infoPtr->items [wineItem->sibling];
+
+ return wineItem;
+}
+	
+ 
+
+
+static void
+TREEVIEW_RemoveItem (TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem)
+
+{
+ TREEVIEW_ITEM *parentItem, *upsiblingItem, *siblingItem;
+ INT32 iItem;
+
+ iItem=wineItem->hItem;
+ set_bit ( iItem & 31, &infoPtr->freeList[iItem >>5]);
+ infoPtr->uNumItems--;
+ parentItem=NULL;
+ if (wineItem->pszText!=LPSTR_TEXTCALLBACK32A) 
+	HeapFree (GetProcessHeap (), 0, wineItem->pszText);
+
+ if (wineItem->parent) {
+	parentItem=& infoPtr->items[ wineItem->parent];
+	if (parentItem->cChildren==1) {
+		parentItem->cChildren=0;
+		parentItem->firstChild=0;    
+		return;
+	} else {
+		parentItem->cChildren--;
+		if (parentItem->firstChild==iItem) 
+			parentItem->firstChild=wineItem->sibling;
+		}
+ }
+
+ if (iItem==infoPtr->TopRootItem) 
+	infoPtr->TopRootItem=wineItem->sibling;
+ if (wineItem->upsibling) {
+	upsiblingItem=& infoPtr->items [wineItem->upsibling];
+	upsiblingItem->sibling=wineItem->sibling;
+ }
+ if (wineItem->sibling) {
+	siblingItem=& infoPtr->items [wineItem->sibling];
+	siblingItem->upsibling=wineItem->upsibling;
+ }
+}
+
+
+
+static void TREEVIEW_RemoveAllChildren (TREEVIEW_INFO *infoPtr, 
+					   TREEVIEW_ITEM *parentItem)
+
+{
+ TREEVIEW_ITEM *killItem;
+ INT32	kill;
+ 
+ kill=parentItem->firstChild;
+ while (kill) {
+ 	set_bit ( kill & 31, &infoPtr->freeList[kill >>5]);
+ 	killItem=& infoPtr->items[kill];
+	if (killItem->pszText!=LPSTR_TEXTCALLBACK32A) 
+		HeapFree (GetProcessHeap (), 0, killItem->pszText);
+	kill=killItem->sibling;
+ }
+ infoPtr->uNumItems -= parentItem->cChildren;
+ parentItem->firstChild = 0;
+ parentItem->cChildren = 0;
+}
+
+
+
+static void TREEVIEW_RemoveTree (TREEVIEW_INFO *infoPtr)
+					   
+
+{
+ TREEVIEW_ITEM *killItem;
+ int i;
+
+	/* bummer: if we didn't delete anything, test_bit is overhead */
+ 
+    for (i=1; i<=infoPtr->uMaxHandle; i++) 
+	if (!test_bit (i, infoPtr->freeList)) {
+		killItem=& infoPtr->items [i];	
+		if (killItem->pszText!=LPSTR_TEXTCALLBACK32A)
+			HeapFree (GetProcessHeap (), 0, killItem->pszText);
+	} 
+
+    if (infoPtr->uNumPtrsAlloced) {
+        HeapFree (GetProcessHeap (), 0, infoPtr->items);
+        HeapFree (GetProcessHeap (), 0, infoPtr->freeList);
+        infoPtr->uNumItems=0;
+        infoPtr->uNumPtrsAlloced=0;
+        infoPtr->uMaxHandle=0;
+    }   
+
+	/* this function doesn't remove infoPtr itself */
+}
+
+
+
+
+
+
+
+
+
+
 static LRESULT
 TREEVIEW_GetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-    TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
 
-    switch ((INT32)wParam) {
-	case TVSIL_NORMAL:
-	    return (LRESULT)infoPtr->himlNormal;
+  TRACE (treeview,"\n");
 
-	case TVSIL_STATE:
-	    return (LRESULT)infoPtr->himlState;
-    }
+  if (infoPtr==NULL) return 0;
 
-    return (LRESULT)NULL;
+  if ((INT32)wParam == TVSIL_NORMAL) 
+	return (LRESULT) infoPtr->himlNormal;
+  if ((INT32)wParam == TVSIL_STATE) 
+	return (LRESULT) infoPtr->himlState;
+
+  return 0;
 }
 
 
@@ -68,51 +279,862 @@
 
 
 static LRESULT
-TREEVIEW_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+TREEVIEW_SetItemHeight (WND *wndPtr, WPARAM32 wParam)
 {
-    TREEVIEW_INFO *infoPtr;
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  INT32 prevHeight=infoPtr->uItemHeight;
+  HDC32 hdc;
+  TEXTMETRIC32A tm;
 
-    /* allocate memory for info structure */
-    infoPtr = (TREEVIEW_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                   sizeof(TREEVIEW_INFO));
-    wndPtr->wExtra[0] = (DWORD)infoPtr;
 
-    if (infoPtr == NULL) {
-	ERR (treeview, "could not allocate info memory!\n");
-	return 0;
+  if (wParam==-1) {
+	hdc=GetDC32 (wndPtr->hwndSelf);
+	infoPtr->uItemHeight=-1;
+	GetTextMetrics32A (hdc, &tm);
+    infoPtr->uRealItemHeight= tm.tmHeight + tm.tmExternalLeading;
+	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+	return prevHeight;
+  }
+
+	/* FIXME: check wParam > imagelist height */
+
+  if (!(wndPtr->dwStyle & TVS_NONEVENHEIGHT))
+	infoPtr->uItemHeight = (INT32) wParam & 0xfffffffe;
+  return prevHeight;
+}
+
+static LRESULT
+TREEVIEW_GetItemHeight (WND *wndPtr)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  
+  return infoPtr->uItemHeight;
+}
+  
+static LRESULT
+TREEVIEW_SetTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  COLORREF prevColor=infoPtr->clrText;
+
+  infoPtr->clrText=(COLORREF) lParam;
+  return (LRESULT) prevColor;
+}
+
+static LRESULT
+TREEVIEW_GetTextColor (WND *wndPtr)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+	
+  return (LRESULT) infoPtr->clrText;
+}
+
+
+static INT32
+TREEVIEW_DrawItem (WND *wndPtr, HDC32 hdc, TREEVIEW_ITEM *wineItem, 
+		   TREEVIEW_ITEM *upperItem, int indent)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  INT32  oldBkMode,center,xpos;
+  COLORREF oldBkColor;
+  UINT32 uTextJustify = DT_LEFT;
+  HPEN32 hOldPen, hnewPen,hRootPen;
+  RECT32 r,upper;
+  
+  hnewPen = CreatePen32(PS_DOT, 0, GetSysColor32(COLOR_WINDOWTEXT) );
+  hOldPen = SelectObject32( hdc, hnewPen );
+ 
+  r=wineItem->rect;
+  if (upperItem) 
+	upper=upperItem->rect;
+  else {
+	upper.top=0;
+	upper.left=8;
+  }
+  center=(r.top+r.bottom)/2;
+  xpos=r.left+8;
+
+  if (wndPtr->dwStyle & TVS_HASLINES) {
+	POINT32 points[3];
+	if ((wndPtr->dwStyle & TVS_LINESATROOT) && (indent==0)) {
+		points[0].y=points[1].y=center;
+		points[2].y=upper.top;
+		points[1].x=points[2].x=upper.left;
+		points[0].x=upper.left+12;
+		points[2].y+=5;
+
+ 		Polyline32 (hdc,points,3);
+	}
+	else {
+		points[0].y=points[1].y=center;
+                points[2].y=upper.top;
+                points[1].x=points[2].x=upper.left+13;
+                points[0].x=upper.left+25;
+                points[2].y+=5;
+ 		Polyline32 (hdc,points,3);
+	}
+ }
+
+  DeleteObject32(hnewPen);
+  SelectObject32(hdc, hOldPen);
+
+  if ((wndPtr->dwStyle & TVS_HASBUTTONS) && (wineItem->cChildren)) {
+/*
+  	hRootPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOW) );
+  	SelectObject32( hdc, hRootPen );
+*/
+
+	Rectangle32 (hdc, xpos-4, center-4, xpos+5, center+5);
+	MoveToEx32 (hdc, xpos-2, center, NULL);
+	LineTo32   (hdc, xpos+3, center);
+	if (!(wineItem->state & TVIS_EXPANDED)) {
+		MoveToEx32 (hdc, xpos,   center-2, NULL);
+		LineTo32   (hdc, xpos,   center+3);
+	}
+ /* 	DeleteObject32(hRootPen); */
+        }
+
+
+  xpos+=13;
+
+  if (wineItem->mask & TVIF_IMAGE) {
+	if (wineItem->iImage!=I_IMAGECALLBACK) {
+  		if (infoPtr->himlNormal) {
+  			ImageList_Draw (infoPtr->himlNormal,wineItem->iImage, hdc,
+                      			xpos-2, r.top+1, ILD_NORMAL);
+  			xpos+=15;
+		}
+	}
+  }
+
+  r.left=xpos;
+  if ((wineItem->mask & TVIF_TEXT) && (wineItem->pszText)) {
+	    if (wineItem->state & TVIS_SELECTED) {
+            	oldBkMode = SetBkMode32(hdc, OPAQUE);
+		oldBkColor= SetBkColor32 (hdc, GetSysColor32( COLOR_HIGHLIGHT));
+		SetTextColor32 (hdc, GetSysColor32(COLOR_HIGHLIGHTTEXT));
+	    }
+	    else {
+            	oldBkMode = SetBkMode32(hdc, TRANSPARENT);
+	    }
+            r.left += 3;
+            r.right -= 3;
+			if (infoPtr->clrText==-1)
+            	SetTextColor32 (hdc, COLOR_BTNTEXT);
+			else 
+				SetTextColor32 (hdc, infoPtr->clrText);  /* FIXME: retval */
+            DrawText32A(hdc, wineItem->pszText, lstrlen32A(wineItem->pszText),
+                  &r, uTextJustify|DT_VCENTER|DT_SINGLELINE);
+            if (oldBkMode != TRANSPARENT)
+                SetBkMode32(hdc, oldBkMode);
+	    if (wineItem->state & TVIS_SELECTED)
+		SetBkColor32 (hdc, oldBkColor);
+        }
+
+ return wineItem->rect.right;
+}
+
+
+
+
+
+
+
+static LRESULT
+TREEVIEW_GetItemRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TREEVIEW_ITEM *wineItem;
+  INT32 iItem;
+  LPRECT32 lpRect;
+
+  TRACE (treeview,"\n");
+  if (infoPtr==NULL) return FALSE;
+  
+  iItem = (INT32)lParam;
+  wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
+  if (!wineItem) return FALSE;
+
+  wineItem=& infoPtr->items[ iItem ];
+  if (!wineItem->visible) return FALSE;
+
+  lpRect = (LPRECT32)lParam;
+  if (lpRect == NULL) return FALSE;
+	
+  if ((INT32) wParam) {
+  	lpRect->left	= wineItem->text.left;
+	lpRect->right	= wineItem->text.right;
+	lpRect->bottom	= wineItem->text.bottom;
+	lpRect->top	= wineItem->text.top;
+  } else {
+	lpRect->left 	= wineItem->rect.left;
+	lpRect->right	= wineItem->rect.right;
+	lpRect->bottom  = wineItem->rect.bottom;
+	lpRect->top	= wineItem->rect.top;
+  }
+
+  return TRUE;
+}
+
+
+
+static LRESULT
+TREEVIEW_GetVisibleCount (WND *wndPtr,  WPARAM32 wParam, LPARAM lParam)
+
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+
+  TRACE (treeview,"\n");
+
+  return (LRESULT) infoPtr->uVisibleHeight / infoPtr->uRealItemHeight;
+}
+
+
+
+static LRESULT
+TREEVIEW_SetItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TREEVIEW_ITEM *wineItem;
+  TV_ITEM *tvItem;
+  INT32 iItem,len;
+
+  TRACE (treeview,"\n");
+  tvItem=(LPTVITEM) lParam;
+  iItem=tvItem->hItem;
+
+  wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
+  if (!wineItem) return FALSE;
+
+  if (tvItem->mask & TVIF_CHILDREN) {
+        wineItem->cChildren=tvItem->cChildren;
+  }
+
+  if (tvItem->mask & TVIF_IMAGE) {
+       wineItem->iImage=tvItem->iImage;
+  }
+
+  if (tvItem->mask & TVIF_INTEGRAL) {
+/*        wineItem->iIntegral=tvItem->iIntegral; */
+  }
+
+  if (tvItem->mask & TVIF_PARAM) {
+        wineItem->lParam=tvItem->lParam;
+  }
+
+  if (tvItem->mask & TVIF_SELECTEDIMAGE) {
+        wineItem->iSelectedImage=tvItem->iSelectedImage;
+  }
+
+  if (tvItem->mask & TVIF_STATE) {
+        wineItem->state=tvItem->state & tvItem->stateMask;
+  }
+
+  if (tvItem->mask & TVIF_TEXT) {
+        len=tvItem->cchTextMax;
+        if (len>wineItem->cchTextMax) {
+		HeapFree (GetProcessHeap (), 0, wineItem->pszText);
+                wineItem->pszText= HeapAlloc (GetProcessHeap (), 
+				HEAP_ZERO_MEMORY, len+1);
+	}
+        lstrcpyn32A (wineItem->pszText, tvItem->pszText,len);
+   }
+
+  return TRUE;
+}
+
+
+
+
+
+static void
+TREEVIEW_Refresh (WND *wndPtr, HDC32 hdc)
+
+{
+    TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+    HFONT32 hFont, hOldFont;
+    RECT32 rect;
+    HBRUSH32 hbrBk;
+    INT32 iItem, indent, x, y, height;
+    INT32 viewtop,viewbottom,viewleft,viewright;
+    TREEVIEW_ITEM *wineItem, *prevItem;
+
+    TRACE (treeview,"\n");
+
+    if (TREEVIEW_Timer & TV_REFRESH_TIMER_SET) {
+		KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
+		TREEVIEW_Timer &= ~TV_REFRESH_TIMER_SET;
     }
 
-    if ((TREEVIEW_INFO*)wndPtr->wExtra[0] != infoPtr) {
-	ERR (treeview, "pointer assignment error!\n");
-	return 0;
-    }
+    
+    GetClientRect32 (wndPtr->hwndSelf, &rect);
+    if ((rect.left-rect.right ==0) || (rect.top-rect.bottom==0)) return;
+    viewtop=infoPtr->cy;
+    viewbottom=infoPtr->cy + rect.bottom-rect.top;
+    viewleft=infoPtr->cx;
+    viewright=infoPtr->cx + rect.right-rect.left;
 
-    /* set default settings */
-    infoPtr->clrBk = GetSysColor32 (COLOR_WINDOW);
-    infoPtr->clrText = GetSysColor32 (COLOR_BTNTEXT);
-    infoPtr->himlNormal = NULL;
-    infoPtr->himlState = NULL;
+	infoPtr->uVisibleHeight=viewbottom - viewtop;
+
+    hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (DEFAULT_GUI_FONT);
+    hOldFont = SelectObject32 (hdc, hFont);
+
+    /* draw background */
+    hbrBk = GetSysColorBrush32(COLOR_WINDOW);
+    FillRect32(hdc, &rect, hbrBk);
 
 
-    return 0;
+    iItem=infoPtr->TopRootItem;
+    infoPtr->firstVisible=0;
+    wineItem=NULL;
+    indent=0;
+    x=y=0;
+    TRACE (treeview, "[%d %d %d %d]\n",viewtop,viewbottom,viewleft,viewright);
+
+    while (iItem) {
+		prevItem=wineItem;
+        wineItem= & infoPtr->items[iItem];
+
+		TRACE (treeview, "%d %d [%d %d %d %d] (%s)\n",y,x,
+			wineItem->rect.top, wineItem->rect.bottom,
+			wineItem->rect.left, wineItem->rect.right,
+			wineItem->pszText);
+
+		height=infoPtr->uRealItemHeight * wineItem->iIntegral;
+		if ((y >= viewtop) && (y <= viewbottom) &&
+	    	(x >= viewleft  ) && (x <= viewright)) {
+        		wineItem->rect.top = y - infoPtr->cy + rect.top;
+        		wineItem->rect.bottom = wineItem->rect.top + height ;
+         		wineItem->rect.left = x - infoPtr->cx + rect.left;
+        		wineItem->rect.right = rect.right;
+			if (!infoPtr->firstVisible)
+				infoPtr->firstVisible=wineItem->hItem;
+        		TREEVIEW_DrawItem (wndPtr, hdc, wineItem, prevItem, indent);
+		}
+		else {
+			wineItem->rect.top  = wineItem->rect.bottom = -1;
+			wineItem->rect.left = wineItem->rect.right = -1;
+ 		}
+
+		/* look up next item */
+	
+		if ((wineItem->firstChild) && (wineItem->state & TVIS_EXPANDED)) {
+			iItem=wineItem->firstChild;
+			indent++;
+			x+=infoPtr->uIndent;
+		}
+		else {
+			iItem=wineItem->sibling;
+			while ((!iItem) && (indent>0)) {
+				indent--;
+				x-=infoPtr->uIndent;
+				prevItem=wineItem;
+				wineItem=&infoPtr->items[wineItem->parent];
+				iItem=wineItem->sibling;
+			}
+		}
+        y +=height;
+    }				/* while */
+
+    infoPtr->uTotalHeight=y;
+    if (y >= (viewbottom-viewtop)) {
+ 		if (!(infoPtr->uInternalStatus & TV_VSCROLL))
+			ShowScrollBar32 (wndPtr->hwndSelf, SB_VERT, TRUE);
+		infoPtr->uInternalStatus |=TV_VSCROLL;
+ 		SetScrollRange32 (wndPtr->hwndSelf, SB_VERT, 0, 
+					y - infoPtr->uVisibleHeight, FALSE);
+		SetScrollPos32 (wndPtr->hwndSelf, SB_VERT, infoPtr->cy, TRUE);
+	}
+    else {
+		if (infoPtr->uInternalStatus & TV_VSCROLL) 
+			ShowScrollBar32 (wndPtr->hwndSelf, SB_VERT, FALSE);
+		infoPtr->uInternalStatus &= ~TV_VSCROLL;
+	}
+
+
+    SelectObject32 (hdc, hOldFont);
+}
+
+
+static LRESULT 
+TREEVIEW_HandleTimer ( WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  HDC32 hdc;
+
+  if (!infoPtr) return FALSE;
+ 
+  TRACE (treeview, "timer\n");
+
+  switch (wParam) {
+	case TV_REFRESH_TIMER:
+		KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
+		TREEVIEW_Timer &= ~TV_REFRESH_TIMER_SET;
+		hdc=GetDC32 (wndPtr->hwndSelf);
+		TREEVIEW_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		return 0;
+	case TV_EDIT_TIMER:
+		KillTimer32 (wndPtr->hwndSelf, TV_EDIT_TIMER);
+		TREEVIEW_Timer &= ~TV_EDIT_TIMER_SET;
+		return 0;
+ }
+		
+ return 1;
+}
+
+
+static void
+TREEVIEW_QueueRefresh (WND *wndPtr)
+
+{
+ 
+ TRACE (treeview,"queued\n");
+ if (TREEVIEW_Timer & TV_REFRESH_TIMER_SET) {
+	KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
+ }
+
+ SetTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER, TV_REFRESH_DELAY, 0);
+ TREEVIEW_Timer|=TV_REFRESH_TIMER_SET;
+}
+
+
+
+static LRESULT
+TREEVIEW_GetItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  LPTVITEM      tvItem;
+  TREEVIEW_ITEM *wineItem;
+  INT32         iItem,len;
+
+  TRACE (treeview,"\n");
+  tvItem=(LPTVITEM) lParam;
+  iItem=tvItem->hItem;
+
+  wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
+  if (!wineItem) return FALSE;
+
+
+   if (tvItem->mask & TVIF_CHILDREN) {
+        tvItem->cChildren=wineItem->cChildren;
+   }
+
+   if (tvItem->mask & TVIF_HANDLE) {
+        tvItem->hItem=wineItem->hItem;
+   }
+
+   if (tvItem->mask & TVIF_IMAGE) {
+        tvItem->iImage=wineItem->iImage;
+   }
+
+   if (tvItem->mask & TVIF_INTEGRAL) {
+/*        tvItem->iIntegral=wineItem->iIntegral; */
+   }
+
+   if (tvItem->mask & TVIF_PARAM) {
+        tvItem->lParam=wineItem->lParam;
+   }
+
+   if (tvItem->mask & TVIF_SELECTEDIMAGE) {
+        tvItem->iSelectedImage=wineItem->iSelectedImage;
+   }
+
+   if (tvItem->mask & TVIF_STATE) {
+        tvItem->state=wineItem->state & tvItem->stateMask;
+   }
+
+   if (tvItem->mask & TVIF_TEXT) {
+	len=wineItem->cchTextMax;
+	if (wineItem->cchTextMax>tvItem->cchTextMax) 
+		len=tvItem->cchTextMax-1;
+        lstrcpyn32A (tvItem->pszText, tvItem->pszText,len);
+   }
+
+  return TRUE;
+}
+
+
+
+static LRESULT
+TREEVIEW_GetNextItem32 (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TREEVIEW_ITEM *wineItem;
+  INT32 iItem, flag;
+
+
+  TRACE (treeview,"item:%lu, flags:%x\n", lParam, wParam);
+  if (!infoPtr) return FALSE;
+
+  flag= (INT32) wParam;
+  switch (flag) {
+	case TVGN_ROOT: 	return (LRESULT) infoPtr->TopRootItem;
+	case TVGN_CARET: 	return (LRESULT) infoPtr->selectedItem;
+	case TVGN_FIRSTVISIBLE: return (LRESULT) infoPtr->firstVisible;
+	case TVGN_DROPHILITE:	return (LRESULT) infoPtr->dropItem;
+	}
+	
+  iItem= (INT32) lParam;
+  wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
+  if (!wineItem) return FALSE;
+
+  switch (flag)	{
+	case TVGN_NEXT: 	return (LRESULT) wineItem->sibling;
+	case TVGN_PREVIOUS: 	return (LRESULT) wineItem->upsibling;
+	case TVGN_PARENT: 	return (LRESULT) wineItem->parent;
+	case TVGN_CHILD: 	return (LRESULT) wineItem->firstChild;
+	case TVGN_LASTVISIBLE:  FIXME (treeview,"TVGN_LASTVISIBLE not implemented\n");
+				return 0;
+	case TVGN_NEXTVISIBLE:  wineItem=TREEVIEW_GetNextListItem 
+						(infoPtr,wineItem);
+				if (wineItem) 
+					return (LRESULT) wineItem->hItem;
+				else
+					return (LRESULT) 0;
+	case TVGN_PREVIOUSVISIBLE: wineItem=TREEVIEW_GetPrevListItem
+						(infoPtr, wineItem);
+				if (wineItem) 
+					return (LRESULT) wineItem->hItem;
+				else
+					return (LRESULT) 0;
+	default:	FIXME (treeview,"Unknown msg %x,item %x\n", flag,iItem);
+	}
+
+ return 0;
 }
 
 
 static LRESULT
-TREEVIEW_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+TREEVIEW_GetCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-    TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+
+ return (LRESULT) infoPtr->uNumItems;
+}
 
 
 
 
-    /* free tree view info data */
-    HeapFree (GetProcessHeap (), 0, infoPtr);
+/* the method used below isn't the most memory-friendly, but it avoids 
+   a lot of memory reallocations */ 
+
+/* BTW: we waste handle 0; 0 is not an allowed handle. Fix this by
+        decreasing infoptr->items with 1, and increasing it by 1 if 
+        it is referenced in mm-handling stuff? */
+
+static LRESULT
+TREEVIEW_InsertItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TVINSERTSTRUCT  *ptdi;
+  TV_ITEM 	*tvItem;
+  TREEVIEW_ITEM *wineItem, *parentItem, *prevsib, *sibItem;
+  INT32		iItem,listItems,i,len;
+  
+  TRACE (treeview,"\n");
+  ptdi = (TVINSERTSTRUCT *) lParam;
+
+	/* check if memory is available */
+
+  if (infoPtr->uNumPtrsAlloced==0) {
+        infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
+                                    TVITEM_ALLOC*sizeof (TREEVIEW_ITEM));
+        infoPtr->freeList= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
+                                    (1+(TVITEM_ALLOC>>5)) *sizeof (INT32));
+        infoPtr->uNumPtrsAlloced=TVITEM_ALLOC;
+	infoPtr->TopRootItem=1;
+   }
+
+  if (infoPtr->uNumItems == (infoPtr->uNumPtrsAlloced-1) ) {
+   	TREEVIEW_ITEM *oldItems = infoPtr->items;
+	INT32 *oldfreeList = infoPtr->freeList;
+
+	infoPtr->uNumPtrsAlloced*=2;
+        infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
+                              infoPtr->uNumPtrsAlloced*sizeof (TREEVIEW_ITEM));
+        infoPtr->freeList= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
+                              (1+(infoPtr->uNumPtrsAlloced>>5))*sizeof (INT32));
+
+        memcpy (&infoPtr->items[0], &oldItems[0],
+                    infoPtr->uNumPtrsAlloced/2 * sizeof(TREEVIEW_ITEM));
+        memcpy (&infoPtr->freeList[0], &oldfreeList[0],
+                    infoPtr->uNumPtrsAlloced>>6 * sizeof(INT32));
+
+         HeapFree (GetProcessHeap (), 0, oldItems);  
+         HeapFree (GetProcessHeap (), 0, oldfreeList);  
+    }
+
+  iItem=0;
+  infoPtr->uNumItems++;
+
+  if (infoPtr->uMaxHandle==(infoPtr->uNumItems-1))  { 
+  	iItem=infoPtr->uNumItems;
+  	infoPtr->uMaxHandle++;
+  } 
+  else {					 /* check freelist */
+	for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) {
+		if (infoPtr->freeList[i]) {
+			iItem=ffs (infoPtr->freeList[i]);
+			clear_bit (iItem & 31, & infoPtr->freeList[i]);
+			break;
+		}
+  	 } 
+  }
+  if (!iItem) ERR (treeview, "Argh -- can't find free item.\n");
+  
+  tvItem= & ptdi->item;
+  wineItem=& infoPtr->items[iItem];
+
+
+
+  if ((ptdi->hParent==TVI_ROOT) || (ptdi->hParent==0)) {
+	parentItem=NULL;
+	wineItem->parent=0; 
+	sibItem=&infoPtr->items [infoPtr->TopRootItem];
+	listItems=infoPtr->uNumItems;
+  }
+  else  {
+	parentItem= &infoPtr->items[ptdi->hParent];
+	if (!parentItem->firstChild) 
+		parentItem->firstChild=iItem;
+	wineItem->parent=ptdi->hParent;
+	sibItem=&infoPtr->items [parentItem->firstChild];
+	parentItem->cChildren++;
+	listItems=parentItem->cChildren;
+  }
+
+  wineItem->upsibling=0;  /* needed in case we're the first item in a list */ 
+  wineItem->sibling=0;     
+  wineItem->firstChild=0;
+
+  if (listItems>1) {
+     prevsib=NULL;
+     switch (ptdi->hInsertAfter) {
+		case TVI_FIRST: wineItem->sibling=infoPtr->TopRootItem;
+			infoPtr->TopRootItem=iItem;
+			break;
+		case TVI_LAST:  
+			while (sibItem->sibling) {
+				prevsib=sibItem;
+				sibItem=&infoPtr->items [sibItem->sibling];
+			}
+			sibItem->sibling=iItem;
+			if (prevsib!=NULL) 
+				wineItem->upsibling=prevsib->hItem;
+			else
+  				wineItem->sibling=0; 	/* terminate list */
+			break;
+		case TVI_SORT:  
+			FIXME (treeview, "Sorted insert not implemented yet\n");
+			break;
+		default:	
+			while ((sibItem->sibling) && (sibItem->sibling!=iItem)) {
+				prevsib=sibItem;
+                sibItem=&infoPtr->items [sibItem->sibling];
+            }
+			if (sibItem->sibling) 
+				WARN (treeview, "Buggy program tried to insert item after nonexisting handle.");
+			sibItem->upsibling=iItem;
+			wineItem->sibling=sibItem->hItem;
+			if (prevsib!=NULL) 
+				wineItem->upsibling=prevsib->hItem;
+			break;
+   	}
+   }	
+
+
+/* Fill in info structure */
+
+   wineItem->mask=tvItem->mask;
+   wineItem->hItem=iItem;
+   wineItem->iIntegral=1; 
+
+   if (tvItem->mask & TVIF_CHILDREN)
+	 wineItem->cChildren=tvItem->cChildren;
+
+   if (tvItem->mask & TVIF_IMAGE) 
+	wineItem->iImage=tvItem->iImage;
+
+/*   if (tvItem->mask & TVIF_INTEGRAL) 
+   	wineItem->iIntegral=tvItem->iIntegral;  */
+   
+
+   if (tvItem->mask & TVIF_PARAM) 
+	wineItem->lParam=tvItem->lParam;
+
+   if (tvItem->mask & TVIF_SELECTEDIMAGE) 
+	wineItem->iSelectedImage=tvItem->iSelectedImage;
+
+   if (tvItem->mask & TVIF_STATE) {
+	wineItem->state=tvItem->state;
+	wineItem->stateMask=tvItem->stateMask;
+   }
+
+   if (tvItem->mask & TVIF_TEXT) {
+   	TRACE (treeview,"(%s)\n", tvItem->pszText); 
+	if (tvItem->pszText!=LPSTR_TEXTCALLBACK32A) {
+		len = lstrlen32A (tvItem->pszText)+1;
+		wineItem->pszText=
+			HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len+1);
+		lstrcpy32A (wineItem->pszText, tvItem->pszText);
+		wineItem->cchTextMax=len;
+	}
+   }
+
+   TREEVIEW_QueueRefresh (wndPtr);
+
+   return (LRESULT) iItem;
+}
+
+
+
+static LRESULT
+TREEVIEW_DeleteItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  INT32 iItem;
+  POINT32 pt;
+  TREEVIEW_ITEM *wineItem;
+
+  TRACE (treeview,"\n");
+  if (!infoPtr) return FALSE;
+
+  if ((INT32) lParam == TVI_ROOT) {
+	TREEVIEW_RemoveTree (infoPtr);
+  } else {
+  	iItem= (INT32) lParam;
+  	wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
+  	if (!wineItem) return FALSE;
+	TREEVIEW_SendTreeviewNotify (wndPtr, TVN_DELETEITEM, 0, iItem, 0, pt);
+	TREEVIEW_RemoveItem (infoPtr, wineItem);
+  }
+
+  TREEVIEW_QueueRefresh (wndPtr);
+
+  return TRUE;
+}
+
+
+static LRESULT
+TREEVIEW_GetIndent (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+
+ return infoPtr->uIndent;
+}
+
+static LRESULT
+TREEVIEW_SetIndent (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  INT32 newIndent;
+   
+  newIndent=(INT32) wParam;
+  if (newIndent < MINIMUM_INDENT) newIndent=MINIMUM_INDENT;
+  infoPtr->uIndent=newIndent;
+  
+  return 0;
+}
+
+
+
+
+
+static LRESULT
+TREEVIEW_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TREEVIEW_INFO *infoPtr;
+	HDC32 hdc;
+    TEXTMETRIC32A tm;
+  
+    TRACE (treeview,"\n");
+      /* allocate memory for info structure */
+      infoPtr = (TREEVIEW_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
+                                     sizeof(TREEVIEW_INFO));
+
+    wndPtr->wExtra[0] = (DWORD)infoPtr;
+
+    if (infoPtr == NULL) {
+		ERR (treeview, "could not allocate info memory!\n");
+		return 0;
+    }
+
+    if ((TREEVIEW_INFO*)wndPtr->wExtra[0] != infoPtr) {
+		ERR (treeview, "pointer assignment error!\n");
+		return 0;
+    }
+
+	hdc=GetDC32 (wndPtr->hwndSelf);
+
+    /* set default settings */
+    infoPtr->uInternalStatus=0;
+    infoPtr->uNumItems=0;
+    infoPtr->clrBk = GetSysColor32 (COLOR_WINDOW);
+    infoPtr->clrText = GetSysColor32 (COLOR_BTNTEXT);
+    infoPtr->cy = 0;
+    infoPtr->cx = 0;
+    infoPtr->uIndent = 15;
+    infoPtr->himlNormal = NULL;
+    infoPtr->himlState = NULL;
+	infoPtr->uItemHeight = -1;
+    GetTextMetrics32A (hdc, &tm);
+    infoPtr->uRealItemHeight= tm.tmHeight + tm.tmExternalLeading;
+
+    infoPtr->items = NULL;
+    infoPtr->selectedItem=0;
+    infoPtr->clrText=-1;	/* use system color */
+    infoPtr->dropItem=0;
+
+/*
+    infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
+    infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
+*/
+
+    if (wndPtr->dwStyle & TBSTYLE_TOOLTIPS) {
+        /* Create tooltip control */
+//      infoPtr->hwndToolTip = CreateWindowEx32A (....);
+
+        /* Send TV_TOOLTIPSCREATED notification */
+
+    }
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
 
     return 0;
 }
 
 
+
+static LRESULT 
+TREEVIEW_Destroy (WND *wndPtr) 
+{
+   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+     
+   TREEVIEW_RemoveTree (infoPtr);
+
+   HeapFree (GetProcessHeap (), 0, infoPtr);
+
+   return 0;
+}
+
+
+static LRESULT
+TREEVIEW_Paint (WND *wndPtr, WPARAM32 wParam)
+{
+    HDC32 hdc;
+    PAINTSTRUCT32 ps;
+
+    hdc = wParam==0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
+    TREEVIEW_QueueRefresh (wndPtr);
+    if(!wParam)
+        EndPaint32 (wndPtr->hwndSelf, &ps);
+    return 0;
+}
+
+
+
 static LRESULT
 TREEVIEW_EraseBackground (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
@@ -120,6 +1142,7 @@
     HBRUSH32 hBrush = CreateSolidBrush32 (infoPtr->clrBk);
     RECT32 rect;
 
+    TRACE (treeview,"\n");
     GetClientRect32 (wndPtr->hwndSelf, &rect);
     FillRect32 ((HDC32)wParam, &rect, hBrush);
     DeleteObject32 (hBrush);
@@ -128,161 +1151,653 @@
 
 
 
-LRESULT WINAPI
-TREEVIEW_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
+
+
+  
+
+
+
+static BOOL32
+TREEVIEW_SendSimpleNotify (WND *wndPtr, UINT32 code)
 {
-    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    NMHDR nmhdr;
 
-    switch (uMsg)
-    {
+    TRACE (treeview, "%x\n",code);
+    nmhdr.hwndFrom = wndPtr->hwndSelf;
+    nmhdr.idFrom   = wndPtr->wIDmenu;
+    nmhdr.code     = code;
 
-    case TVM_INSERTITEM32A:
-      FIXME (treeview, "Unimplemented msg TVM_INSERTITEM32A\n");
-      return 0;
+    return (BOOL32) SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+                                   (WPARAM32)nmhdr.idFrom, (LPARAM)&nmhdr);
+}
 
-    case TVM_INSERTITEM32W:
-      FIXME (treeview, "Unimplemented msg TVM_INSERTITEM32W\n");
-      return 0;
 
-    case TVM_DELETEITEM:
-      FIXME (treeview, "Unimplemented msg TVM_DELETEITEM\n");
-      return 0;
 
-    case TVM_EXPAND:
-      FIXME (treeview, "Unimplemented msg TVM_EXPAND\n");
-      return 0;
 
-    case TVM_GETITEMRECT:
-      FIXME (treeview, "Unimplemented msg TVM_GETITEMRECT\n");
-      return 0;
+static BOOL32
+TREEVIEW_SendTreeviewNotify (WND *wndPtr, UINT32 code, UINT32 action, 
+			INT32 oldItem, INT32 newItem, POINT32 pt)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  NMTREEVIEW nmhdr;
+  TREEVIEW_ITEM  *wineItem;
 
-    case TVM_GETCOUNT:
-      FIXME (treeview, "Unimplemented msg TVM_GETCOUNT\n");
-      return 0;
+  TRACE (treeview,"code:%x action:%x olditem:%x newitem:%x\n",
+		  code,action,oldItem,newItem);
+  nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
+  nmhdr.hdr.idFrom = wndPtr->wIDmenu;
+  nmhdr.hdr.code = code;
+  nmhdr.action = action;
+  if (oldItem) {
+  	wineItem=& infoPtr->items[oldItem];
+  	nmhdr.itemOld.mask 		= wineItem->mask;
+  	nmhdr.itemOld.hItem		= wineItem->hItem;
+  	nmhdr.itemOld.state		= wineItem->state;
+  	nmhdr.itemOld.stateMask	= wineItem->stateMask;
+  	nmhdr.itemOld.iImage 		= wineItem->iImage;
+  	nmhdr.itemOld.pszText 	= wineItem->pszText;
+  	nmhdr.itemOld.cchTextMax 	= wineItem->cchTextMax;
+  	nmhdr.itemOld.iImage 		= wineItem->iImage;
+  	nmhdr.itemOld.iSelectedImage 	= wineItem->iSelectedImage;
+  	nmhdr.itemOld.cChildren 	= wineItem->cChildren;
+  	nmhdr.itemOld.lParam		= wineItem->lParam;
+  }
 
-    case TVM_GETINDENT:
-      FIXME (treeview, "Unimplemented msg TVM_GETINDENT\n");
-      return 0;
+  if (newItem) {
+  	wineItem=& infoPtr->items[newItem];
+  	nmhdr.itemNew.mask 		= wineItem->mask;
+  	nmhdr.itemNew.hItem		= wineItem->hItem;
+  	nmhdr.itemNew.state		= wineItem->state;
+  	nmhdr.itemNew.stateMask	= wineItem->stateMask;
+  	nmhdr.itemNew.iImage 		= wineItem->iImage;
+  	nmhdr.itemNew.pszText 	= wineItem->pszText;
+  	nmhdr.itemNew.cchTextMax 	= wineItem->cchTextMax;
+  	nmhdr.itemNew.iImage 		= wineItem->iImage;
+  	nmhdr.itemNew.iSelectedImage 	= wineItem->iSelectedImage;
+  	nmhdr.itemNew.cChildren 	= wineItem->cChildren;
+  	nmhdr.itemNew.lParam		= wineItem->lParam;
+  }
 
-    case TVM_SETINDENT:
-      FIXME (treeview, "Unimplemented msg TVM_SETINDENT\n");
-      return 0;
+  nmhdr.ptDrag.x = pt.x;
+  nmhdr.ptDrag.y = pt.y;
 
-	case TVM_GETIMAGELIST:
-	    return TREEVIEW_GetImageList (wndPtr, wParam, lParam);
+  return (BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+                                   (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmhdr);
 
-	case TVM_SETIMAGELIST:
-	    return TREEVIEW_SetImageList (wndPtr, wParam, lParam);
+}
 
-    case TVM_GETNEXTITEM:
-      FIXME (treeview, "Unimplemented msg TVM_GETNEXTITEM\n");
-      return 0;
 
-    case TVM_SELECTITEM:
-      FIXME (treeview, "Unimplemented msg TVM_SELECTITEM \n");
-      return 0;
 
-    case TVM_GETITEM32A:
-      FIXME (treeview, "Unimplemented msg TVM_GETITEM32A\n");
-      return 0;
 
-    case TVM_GETITEM32W:
-      FIXME (treeview, "Unimplemented msg TVM_GETITEM32W\n");
-      return 0;
+static LRESULT
+TREEVIEW_Expand (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+ TREEVIEW_ITEM *wineItem;
+ UINT32 flag;
+ INT32 expandItem;
+ POINT32 pt;
+ 
+ flag= (UINT32) wParam;
+ expandItem= (INT32) lParam;
+ TRACE (treeview,"flags:%x item:%x\n", expandItem, wParam);
+ wineItem = TREEVIEW_ValidItem (infoPtr, expandItem);
+ if (!wineItem) return 0;
+ if (!wineItem->cChildren) return 0;
 
-    case TVM_SETITEM32A:
-      FIXME (treeview, "Unimplemented msg TVM_SETITEM32A\n");
-      return 0;
+ if (flag & TVE_TOGGLE) {		/* FIXME: check exact behaviour here */
+	flag &= ~TVE_TOGGLE;		/* ie: bitwise ops or 'case' ops */
+	if (wineItem->state & TVIS_EXPANDED) 
+		flag |= TVE_COLLAPSE;
+	else
+		flag |= TVE_EXPAND;
+ }
 
-    case TVM_SETITEM32W:
-      FIXME (treeview, "Unimplemented msg TVM_SETITEM32W\n");
-      return 0;
+ switch (flag) {
+    case TVE_COLLAPSERESET: 
+   		if (!wineItem->state & TVIS_EXPANDED) return 0;
+		wineItem->state &= ~(TVIS_EXPANDEDONCE | TVIS_EXPANDED);
+		TREEVIEW_RemoveAllChildren (infoPtr, wineItem);
+		break;
 
-    case TVM_EDITLABEL32A:
-      FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32A\n");
-      return 0;
+    case TVE_COLLAPSE: 
+		if (!wineItem->state & TVIS_EXPANDED) return 0;
+		wineItem->state &= ~TVIS_EXPANDED;
+		break;
 
-    case TVM_EDITLABEL32W:
-      FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32W\n");
-      return 0;
+    case TVE_EXPAND: 
+		if (wineItem->state & TVIS_EXPANDED) return 0;
+		if (!(wineItem->state & TVIS_EXPANDEDONCE)) {
+    		if (TREEVIEW_SendTreeviewNotify (wndPtr, TVN_ITEMEXPANDING, 
+											0, 0, expandItem, pt))
+					return FALSE; 	/* FIXME: OK? */
+		wineItem->state |= TVIS_EXPANDED | TVIS_EXPANDEDONCE;
+    	TREEVIEW_SendTreeviewNotify (wndPtr, TVN_ITEMEXPANDED, 
+											0, 0, expandItem, pt);
+ 	}
+	wineItem->state |= TVIS_EXPANDED;
+	break;
+   case TVE_EXPANDPARTIAL:
+		FIXME (treeview, "TVE_EXPANDPARTIAL not implemented\n");
+		wineItem->state ^=TVIS_EXPANDED;
+		wineItem->state |=TVIS_EXPANDEDONCE;
+		break;
+  }
+ 
+ TREEVIEW_QueueRefresh (wndPtr);
 
-    case TVM_GETEDITCONTROL:
-      FIXME (treeview, "Unimplemented msg TVM_GETEDITCONTROL\n");
-      return 0;
+ return TRUE;
+}
 
-    case TVM_GETVISIBLECOUNT:
-      FIXME (treeview, "Unimplemented msg TVM_GETVISIBLECOUNT\n");
-      return 0;
 
-    case TVM_HITTEST:
-      FIXME (treeview, "Unimplemented msg TVM_HITTEST\n");
-      return 0;
 
-    case TVM_CREATEDRAGIMAGE:
-      FIXME (treeview, "Unimplemented msg TVM_CREATEDRAGIMAGE\n");
-      return 0;
+static HTREEITEM
+TREEVIEW_HitTest (WND *wndPtr, LPTVHITTESTINFO lpht)
+{
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+ TREEVIEW_ITEM *wineItem;
+ RECT32 rect;
+ UINT32 status,x,y;
+ 
 
-    case TVM_SORTCHILDREN:
-      FIXME (treeview, "Unimplemented msg TVM_SORTCHILDREN\n");
-      return 0;
 
-    case TVM_ENSUREVISIBLE:
-      FIXME (treeview, "Unimplemented msg TVM_ENSUREVISIBLE\n");
-      return 0;
+ GetClientRect32 (wndPtr->hwndSelf, &rect);
+ TRACE (treeview,"(%d,%d)\n",lpht->pt.x, lpht->pt.y);
 
-    case TVM_SORTCHILDRENCB:
-      FIXME (treeview, "Unimplemented msg TVM_SORTCHILDRENCB\n");
-      return 0;
+ status=0;
+ x=lpht->pt.x;
+ y=lpht->pt.y;
+ if (x < rect.left)  status|=TVHT_TOLEFT;
+ if (x > rect.right) status|=TVHT_TORIGHT;
+ if (y < rect.top )  status|=TVHT_ABOVE;
+ if (y > rect.bottom) status|=TVHT_BELOW;
+ if (status) {
+	lpht->flags=status;
+	return 0;
+ }
 
-    case TVM_ENDEDITLABELNOW:
-      FIXME (treeview, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
-      return 0;
+ if (!infoPtr->firstVisible) WARN (treeview,"Can't fetch first visible item");
+ wineItem=&infoPtr->items [infoPtr->firstVisible];
 
-    case TVM_GETISEARCHSTRING32A:
-      FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
-      return 0;
+ while ((wineItem!=NULL) && (y > wineItem->rect.bottom))
+       wineItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
+	
+ if (wineItem==NULL) {
+	lpht->flags=TVHT_NOWHERE;
+	return 0;
+ }
 
-    case TVM_GETISEARCHSTRING32W:
-      FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
-      return 0;
+ if (x>wineItem->rect.right) {
+	lpht->flags|=TVHT_ONITEMRIGHT;
+	return wineItem->hItem;
+ }
+ 
+	
+ if (x<wineItem->rect.left+10) lpht->flags|=TVHT_ONITEMBUTTON;
 
-    case TVM_SETTOOLTIPS:
-      FIXME (treeview, "Unimplemented msg TVM_SETTOOLTIPS\n");
-      return 0;
+ lpht->flags=TVHT_ONITEMLABEL;    /* FIXME: implement other flags */
+	
 
-    case TVM_GETTOOLTIPS:
-      FIXME (treeview, "Unimplemented msg TVM_GETTOOLTIPS\n");
-      return 0;
+ lpht->hItem=wineItem->hItem;
+ return wineItem->hItem;
+}
 
-	case WM_CREATE:
-	    return TREEVIEW_Create (wndPtr, wParam, lParam);
 
-	case WM_DESTROY:
-	    return TREEVIEW_Destroy (wndPtr, wParam, lParam);
+static LRESULT
+TREEVIEW_HitTest32 (WND *wndPtr, LPARAM lParam)
+{
+ 
+  return (LRESULT) TREEVIEW_HitTest (wndPtr, (LPTVHITTESTINFO) lParam);
+}
 
-//	case EM_ENABLE:
 
-	case WM_ERASEBKGND:
-	    return TREEVIEW_EraseBackground (wndPtr, wParam, lParam);
 
-	case WM_GETDLGCODE:
-	    return DLGC_WANTARROWS | DLGC_WANTCHARS;
 
-//	case WM_PAINT:
-//	    return TREEVIEW_Paint (wndPtr, wParam);
+LRESULT
+TREEVIEW_LButtonDoubleClick (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TREEVIEW_ITEM *wineItem;
+  INT32 iItem;
+  TVHITTESTINFO ht;
 
-//	case WM_SETFONT:
+  TRACE (treeview,"\n");
+  ht.pt.x = (INT32)LOWORD(lParam);
+  ht.pt.y = (INT32)HIWORD(lParam);
+  SetFocus32 (wndPtr->hwndSelf);
 
-//	case WM_TIMER:
+  iItem=TREEVIEW_HitTest (wndPtr, &ht);
+  TRACE (treeview,"item %d \n",iItem);
+  wineItem=TREEVIEW_ValidItem (infoPtr, iItem);
+  if (!wineItem) return 0;
+ 
+  if (TREEVIEW_SendSimpleNotify (wndPtr, NM_DBLCLK)!=TRUE) {     /* FIXME!*/
+	wineItem->state &= ~TVIS_EXPANDEDONCE;
+	TREEVIEW_Expand (wndPtr, (WPARAM32) TVE_TOGGLE, (LPARAM) iItem);
+ }
+ return TRUE;
+}
 
-//	case WM_VSCROLL:
 
-	default:
-	    if (uMsg >= WM_USER)
+
+static LRESULT
+TREEVIEW_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  INT32 iItem;
+  TVHITTESTINFO ht;
+
+  TRACE (treeview,"\n");
+  ht.pt.x = (INT32)LOWORD(lParam);
+  ht.pt.y = (INT32)HIWORD(lParam);
+
+  SetFocus32 (wndPtr->hwndSelf);
+  iItem=TREEVIEW_HitTest (wndPtr, &ht);
+  TRACE (treeview,"item %d \n",iItem);
+  if (ht.flags & TVHT_ONITEMBUTTON) {
+	TREEVIEW_Expand (wndPtr, (WPARAM32) TVE_TOGGLE, (LPARAM) iItem);
+  }
+	
+  if (TREEVIEW_SelectItem (wndPtr, (WPARAM32) TVGN_CARET, (LPARAM) iItem))
+	 return 0;
+
+  
+ return 0;
+}
+
+
+static LRESULT
+TREEVIEW_RButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+
+ return 0;
+}
+
+
+
+
+/* FIXME: If the specified item is the child of a collapsed parent item,
+expand parent's list of child items to reveal the specified item.
+*/
+
+static LRESULT
+TREEVIEW_SelectItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+ TREEVIEW_ITEM *prevItem,*wineItem;
+ INT32 action,prevSelect, newSelect;
+ POINT32 dummy;
+
+  TRACE (treeview,"item %lx, flag %x\n", lParam, wParam);
+  newSelect= (INT32) lParam;
+  wineItem = TREEVIEW_ValidItem (infoPtr, newSelect);
+  if (!wineItem) return FALSE;
+  prevSelect=infoPtr->selectedItem;
+  prevItem= TREEVIEW_ValidItem (infoPtr, prevSelect);
+  dummy.x=0;
+  dummy.y=0;
+
+  action= (INT32) wParam;
+
+  switch (action) {
+	case TVGN_CARET: 
+	    if (TREEVIEW_SendTreeviewNotify (wndPtr, TVN_SELCHANGING, TVC_BYMOUSE, 
+										prevSelect, newSelect,dummy)) 
+			return FALSE;       /* FIXME: OK? */
+		
+	    if (prevItem) prevItem->state &= ~TVIS_SELECTED;
+  		infoPtr->selectedItem=newSelect;
+		wineItem->state |=TVIS_SELECTED;
+		TREEVIEW_SendTreeviewNotify (wndPtr, TVN_SELCHANGED, 
+				TVC_BYMOUSE, prevSelect, newSelect, dummy);
+		break;
+	case TVGN_DROPHILITE: 
+		FIXME (treeview, "DROPHILITE not implemented");
+		break;
+	case TVGN_FIRSTVISIBLE:
+		FIXME (treeview, "FIRSTVISIBLE not implemented");
+		break;
+ }
+ 
+ TREEVIEW_QueueRefresh (wndPtr);
+  
+ return TRUE;
+}
+
+
+
+/* FIXME: does KEYDOWN also send notifications?? If so, use 
+   TREEVIEW_SelectItem.
+*/
+   
+
+static LRESULT
+TREEVIEW_KeyDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+ TREEVIEW_ITEM *prevItem,*newItem;
+ int prevSelect;
+
+
+ TRACE (treeview,"%x %lx",wParam, lParam);
+ prevSelect=infoPtr->selectedItem;
+ if (!prevSelect) return FALSE;
+
+ prevItem= TREEVIEW_ValidItem (infoPtr, prevSelect);
+ 
+ newItem=NULL;
+ switch (wParam) {
+	case VK_UP: 
+		newItem=TREEVIEW_GetPrevListItem (infoPtr, prevItem);
+		if (!newItem) 
+			newItem=& infoPtr->items[infoPtr->TopRootItem];
+		break;
+	case VK_DOWN: 
+		newItem=TREEVIEW_GetNextListItem (infoPtr, prevItem);
+		if (!newItem) newItem=prevItem;
+		break;
+	case VK_HOME:
+		newItem=& infoPtr->items[infoPtr->TopRootItem];
+		break;
+	case VK_END:
+		newItem=TREEVIEW_GetLastListItem (infoPtr);
+		break;
+	case VK_PRIOR:
+	case VK_NEXT:
+	case VK_BACK:
+	case VK_RETURN:
+		FIXME (treeview, "%x not implemented\n", wParam);
+		break;
+ }
+
+ if (!newItem) return FALSE;
+
+ if (prevItem!=newItem) {
+ 	prevItem->state &= ~TVIS_SELECTED;
+ 	newItem->state |= TVIS_SELECTED;
+ 	infoPtr->selectedItem=newItem->hItem;
+ 	TREEVIEW_QueueRefresh (wndPtr);
+ 	return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+static LRESULT
+TREEVIEW_VScroll (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  int maxHeight;
+
+  TRACE (treeview,"wp %x, lp %lx\n", wParam, lParam);
+  if (!infoPtr->uInternalStatus & TV_VSCROLL) return FALSE;
+
+  switch (LOWORD (wParam)) {
+	case SB_LINEUP: 
+			if (!infoPtr->cy) return FALSE;
+			infoPtr->cy -= infoPtr->uRealItemHeight;
+			if (infoPtr->cy < 0) infoPtr->cy=0;
+			break;
+	case SB_LINEDOWN: 
+			maxHeight=infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
+			if (infoPtr->cy == maxHeight) return FALSE;
+			infoPtr->cy += infoPtr->uRealItemHeight;
+			if (infoPtr->cy > maxHeight) 
+				infoPtr->cy = maxHeight;
+			break;
+	case SB_PAGEUP:	
+			if (!infoPtr->cy) return FALSE;
+			infoPtr->cy -= infoPtr->uVisibleHeight;
+			if (infoPtr->cy < 0) infoPtr->cy=0;
+			break;
+	case SB_PAGEDOWN:
+			maxHeight=infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
+			if (infoPtr->cy == maxHeight) return FALSE;
+			infoPtr->cy += infoPtr->uVisibleHeight;
+            if (infoPtr->cy > maxHeight)
+                infoPtr->cy = maxHeight;
+			break;
+	case SB_THUMBTRACK: 
+			infoPtr->cy = HIWORD (wParam);
+			break;
+			
+  }
+  
+  TREEVIEW_QueueRefresh (wndPtr);
+  return TRUE;
+}
+
+static LRESULT
+TREEVIEW_HScroll (WND *wndPtr, WPARAM32 wParam, LPARAM lParam) 
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+
+  TRACE (treeview,"wp %lx, lp %x\n", lParam, wParam);
+	
+  if (!infoPtr->uInternalStatus & TV_HSCROLL) return FALSE;
+  return TRUE;
+}
+
+
+
+
+  LRESULT WINAPI
+  TREEVIEW_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
+  {
+      WND *wndPtr = WIN_FindWndPtr(hwnd);
+  
+  
+    switch (uMsg) {
+    	case TVM_INSERTITEM32A:
+          return TREEVIEW_InsertItem32A (wndPtr, wParam, lParam);
+
+    	case TVM_INSERTITEM32W:
+      		FIXME (treeview, "Unimplemented msg TVM_INSERTITEM32W\n");
+      		return 0;
+
+    	case TVM_DELETEITEM:
+      		return TREEVIEW_DeleteItem (wndPtr, wParam, lParam);
+
+    	case TVM_EXPAND:
+      		return TREEVIEW_Expand (wndPtr, wParam, lParam);
+
+    	case TVM_GETITEMRECT:
+      		return TREEVIEW_GetItemRect (wndPtr, wParam, lParam);
+
+    	case TVM_GETCOUNT:
+      		return TREEVIEW_GetCount (wndPtr, wParam, lParam);
+
+    	case TVM_GETINDENT:
+      		return TREEVIEW_GetIndent (wndPtr, wParam, lParam);
+
+    	case TVM_SETINDENT:
+      		return TREEVIEW_SetIndent (wndPtr, wParam, lParam);
+
+    	case TVM_GETIMAGELIST:
+      		return TREEVIEW_GetImageList (wndPtr, wParam, lParam);
+
+		case TVM_SETIMAGELIST:
+	    	return TREEVIEW_SetImageList (wndPtr, wParam, lParam);
+
+    	case TVM_GETNEXTITEM:
+      		return TREEVIEW_GetNextItem32 (wndPtr, wParam, lParam);
+
+    	case TVM_SELECTITEM:
+      		return TREEVIEW_SelectItem (wndPtr, wParam, lParam);
+
+    	case TVM_GETITEM32A:
+      		return TREEVIEW_GetItem (wndPtr, wParam, lParam);
+
+    	case TVM_GETITEM32W:
+      		FIXME (treeview, "Unimplemented msg TVM_GETITEM32W\n");
+      		return 0;
+
+    	case TVM_SETITEM32A:
+      		return TREEVIEW_SetItem (wndPtr, wParam, lParam);
+
+    	case TVM_SETITEM32W:
+      		FIXME (treeview, "Unimplemented msg TVM_SETITEMW\n");
+      		return 0;
+
+    	case TVM_EDITLABEL32A:
+      		FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32A \n");
+      		return 0;
+
+    	case TVM_EDITLABEL32W:
+      		FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32W \n");
+      		return 0;
+
+    	case TVM_GETEDITCONTROL:
+      		FIXME (treeview, "Unimplemented msg TVM_GETEDITCONTROL\n");
+      		return 0;
+
+    	case TVM_GETVISIBLECOUNT:
+      		return TREEVIEW_GetVisibleCount (wndPtr, wParam, lParam);
+
+    	case TVM_HITTEST:
+      		return TREEVIEW_HitTest32 (wndPtr, lParam);
+
+    	case TVM_CREATEDRAGIMAGE:
+      		FIXME (treeview, "Unimplemented msg TVM_CREATEDRAGIMAGE\n");
+      		return 0;
+  
+    	case TVM_SORTCHILDREN:
+      		FIXME (treeview, "Unimplemented msg TVM_SORTCHILDREN\n");
+      		return 0;
+  
+    	case TVM_ENSUREVISIBLE:
+      		FIXME (treeview, "Unimplemented msg TVM_ENSUREVISIBLE\n");
+      		return 0;
+  
+    	case TVM_SORTCHILDRENCB:
+      		FIXME (treeview, "Unimplemented msg TVM_SORTCHILDRENCB\n");
+      		return 0;
+  
+    	case TVM_ENDEDITLABELNOW:
+      		FIXME (treeview, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
+      		return 0;
+  
+    	case TVM_GETISEARCHSTRING32A:
+      		FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
+      		return 0;
+  
+    	case TVM_GETISEARCHSTRING32W:
+      		FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
+      		return 0;
+  
+    	case TVM_SETTOOLTIPS:
+      		FIXME (treeview, "Unimplemented msg TVM_SETTOOLTIPS\n");
+      		return 0;
+  
+    	case TVM_GETTOOLTIPS:
+      		FIXME (treeview, "Unimplemented msg TVM_GETTOOLTIPS\n");
+      		return 0;
+  
+    	case TVM_SETINSERTMARK:
+      		FIXME (treeview, "Unimplemented msg TVM_SETINSERTMARK\n");
+      		return 0;
+  
+    	case TVM_SETITEMHEIGHT:
+      		return TREEVIEW_SetItemHeight (wndPtr, wParam);
+  
+    	case TVM_GETITEMHEIGHT:
+      		return TREEVIEW_GetItemHeight (wndPtr);
+  
+    	case TVM_SETBKCOLOR:
+      		FIXME (treeview, "Unimplemented msg TVM_SETBKCOLOR\n");
+      		return 0;
+	
+    	case TVM_SETTEXTCOLOR:
+      		return TREEVIEW_SetTextColor (wndPtr, wParam, lParam);
+  
+    	case TVM_GETBKCOLOR:
+      		FIXME (treeview, "Unimplemented msg TVM_GETBKCOLOR\n");
+      		return 0;
+  
+    	case TVM_GETTEXTCOLOR:
+      		return TREEVIEW_GetTextColor (wndPtr);
+  
+    	case TVM_SETSCROLLTIME:
+      		FIXME (treeview, "Unimplemented msg TVM_SETSCROLLTIME\n");
+      		return 0;
+  
+    	case TVM_GETSCROLLTIME:
+      		FIXME (treeview, "Unimplemented msg TVM_GETSCROLLTIME\n");
+      		return 0;
+  
+    	case TVM_SETINSERTMARKCOLOR:
+      		FIXME (treeview, "Unimplemented msg TVM_SETINSERTMARKCOLOR\n");
+      		return 0;
+  
+    	case TVM_SETUNICODEFORMAT:
+      		FIXME (treeview, "Unimplemented msg TVM_SETUNICODEFORMAT\n");
+      		return 0;
+  
+    	case TVM_GETUNICODEFORMAT:
+      		FIXME (treeview, "Unimplemented msg TVM_GETUNICODEFORMAT\n");
+      		return 0;
+  
+//		case WM_COMMAND:
+  
+		case WM_CREATE:
+			return TREEVIEW_Create (wndPtr, wParam, lParam);
+  
+		case WM_DESTROY:
+			return TREEVIEW_Destroy (wndPtr);
+  
+//		case WM_ENABLE:
+  
+		case WM_ERASEBKGND:
+	    	return TREEVIEW_EraseBackground (wndPtr, wParam, lParam);
+  
+		case WM_GETDLGCODE:
+	    	return DLGC_WANTARROWS | DLGC_WANTCHARS;
+  
+		case WM_PAINT:
+	    	return TREEVIEW_Paint (wndPtr, wParam);
+  
+//		case WM_GETFONT:
+//		case WM_SETFONT:
+  
+		case WM_KEYDOWN:
+			return TREEVIEW_KeyDown (wndPtr, wParam, lParam);
+  
+  
+//		case WM_KILLFOCUS:
+//		case WM_SETFOCUS:
+  
+  
+		case WM_LBUTTONDOWN:
+			return TREEVIEW_LButtonDown (wndPtr, wParam, lParam);
+  
+		case WM_LBUTTONDBLCLK:
+			return TREEVIEW_LButtonDoubleClick (wndPtr, wParam, lParam);
+  
+		case WM_RBUTTONDOWN:
+			return TREEVIEW_RButtonDown (wndPtr, wParam, lParam);
+  
+  
+//		case WM_SYSCOLORCHANGE:
+//		case WM_STYLECHANGED:
+//		case WM_SETREDRAW:
+  
+		case WM_TIMER:
+			return TREEVIEW_HandleTimer (wndPtr, wParam, lParam);
+  
+//		case WM_SIZE:
+		case WM_HSCROLL: 
+			return TREEVIEW_HScroll (wndPtr, wParam, lParam);
+		case WM_VSCROLL: 
+			return TREEVIEW_VScroll (wndPtr, wParam, lParam);
+  
+		default:
+	    	if (uMsg >= WM_USER)
 		FIXME (treeview, "Unknown msg %04x wp=%08x lp=%08lx\n",
-		       uMsg, wParam, lParam);
-	    return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
-    }
+  		     uMsg, wParam, lParam);
+  	    return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
+      }
     return 0;
 }
 
diff --git a/dlls/comctl32/updown.c b/dlls/comctl32/updown.c
index e93b5ef..8ccc64a 100644
--- a/dlls/comctl32/updown.c
+++ b/dlls/comctl32/updown.c
@@ -27,14 +27,12 @@
  */
 
 #include <stdlib.h>
-#include <assert.h>
-#include <string.h>
 #include "windows.h"
+#include "commctrl.h"
 #include "winnls.h"
 #include "sysmetrics.h"
 #include "updown.h"
 #include "graphics.h"
-#include "heap.h"
 #include "win.h"
 #include "debug.h"
 
@@ -249,7 +247,7 @@
     if (!(wndPtr->dwStyle & UDS_NOTHOUSANDS)) {
       char txt2[20], *src = txt1, *dst = txt2;
       if(len%3 > 0){
-	strncpy(dst, src, len%3);
+	lstrcpyn32A (dst, src, len%3);
 	dst += len%3;
 	src += len%3;
       }
@@ -597,9 +595,7 @@
       return TRUE;
 
     case WM_CREATE:
-      infoPtr =
-	(UPDOWN_INFO*)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-				 sizeof(UPDOWN_INFO));
+      infoPtr = (UPDOWN_INFO*)COMCTL32_Alloc (sizeof(UPDOWN_INFO));
       wndPtr->wExtra[0] = (DWORD)infoPtr;
 
       /* initialize the info struct */
@@ -618,9 +614,9 @@
     
     case WM_DESTROY:
       if(infoPtr->AccelVect)
-	free(infoPtr->AccelVect);
+	COMCTL32_Free (infoPtr->AccelVect);
 
-      HeapFree (GetProcessHeap (), 0, infoPtr);
+      COMCTL32_Free (infoPtr);
       wndPtr->wExtra[0] = 0;
 
       TRACE(updown, "UpDown Ctrl destruction, hwnd=%04x\n", hwnd);
@@ -715,13 +711,13 @@
     case UDM_SETACCEL:
       TRACE(updown, "UpDown Ctrl new accel info, hwnd=%04x\n", hwnd);
       if(infoPtr->AccelVect){
-	free(infoPtr->AccelVect);
+	COMCTL32_Free (infoPtr->AccelVect);
 	infoPtr->AccelCount = 0;
 	infoPtr->AccelVect  = 0;
       }
       if(wParam==0)
 	return TRUE;
-      infoPtr->AccelVect = malloc(wParam*sizeof(UDACCEL));
+      infoPtr->AccelVect = COMCTL32_Alloc (wParam*sizeof(UDACCEL));
       if(infoPtr->AccelVect==0)
 	return FALSE;
       memcpy(infoPtr->AccelVect, (void*)lParam, wParam*sizeof(UDACCEL));
@@ -816,9 +812,9 @@
 
     default: 
       if (message >= WM_USER) 
-	WARN(updown, "unknown msg %04x wp=%04x lp=%08lx\n", 
-		     message, wParam, lParam );
-      return DefWindowProc32A( hwnd, message, wParam, lParam ); 
+	ERR (updown, "unknown msg %04x wp=%04x lp=%08lx\n", 
+	     message, wParam, lParam);
+      return DefWindowProc32A (hwnd, message, wParam, lParam); 
     } 
 
     return 0;