Release 940201

Tue Feb  1 21:14:47 1994  Bob Amstadt  (bob@pooh)

	* [loader/selector.c]
	Added function CreateNewSegments().  Modified IPCCopySelector
	to allow aliasing to any arbitrary memory space.

	* [memory/global.c]
	Fixed potential bug in GlobalGetFreeSegments().

	* [memory/linear.c]
	Created functions GlobalLinearLock() and GlobalLinearUnlock().

Tue Feb  1 05:51:43 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [controls/widgets.c]
	Removed CAPTION window class.

	* [loader/cursor.c]
	Bug fix in LoadCursor(): don't allocate memory every time for
	built-in cursors.

	* [windows/clipping.c]
	Invalidate child windows in InvalidateRgn().

	* [windows/defwnd.c]
	Added repaint of the caption when changing window text.

	* [windows/event.c]
	Modified SetCapture() to allow keyboard events while capturing.

	* [windows/message.c]
	New function MSG_GetHardwareMessage(), to do mouse tracking
	without returning control to the Windows program.

	* [windows/nonclient.c]
	A couple of changes in frame drawing for DLGMODALFRAME windows.
	Rewritten window moving code, to use MSG_GetHardwareMessage()
	instead of non-client mouse events (this is the way Windows
	does it), and to send WM_ENTERSIZEMOVE messages.
	Removed WM_NCBUTTONUP and WM_NCMOUSEMOVE handlers.

	* [windows/win.c]
	Allocate temporary structures on the USER heap instead of
	using GlobalAlloc().

	* [windows/winpos.c]
	Added function WINPOS_GetMinMaxInfo() to get sizing informations.

Jan 31, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [windows/nonclient.c]
	Call to StdDrawScrollBar() during NC's drawing.
	Call to NC_ScrollBarButtonDown() on NC mouse events WM_LBUTTONDOWN.
	Call to NC_ScrollBarButtonUp() on NC mouse events WM_LBUTTONUP.
	Call to NC_ScrollBarMouseMove() on NC mouse events WM_MOUSEMOVE.

	* [controls/menu.c]
	New GetSubMenu() function.
	Move GetMenu() & SetMenu() functions from 'windows/win.c'.

	* [controls/listbox.c]
	Start changes to satisfy recent changes in scrollbars/windows.

	* [loader/resource.c]
	Put some code in LoadAccelerators() stub.
	New TranslateAccelerator() function.

	* [windows/win.c]
	Remove GetMenu() & SetMenu() functions.
	Call to NC_CreateScrollBars() if required by CreateWindow().

Mon Jan 24 10:40:10 EST 1994 John Richardson (jrichard@cs.uml.edu)

        * [window/win.c]
        Added functions EnumWindows, EnumChildWindows, and helper
        WIN_EnumChildWin.  EnumWindows won't list all wine windows
        because GetDesktopWindow isn't complete.  However, the code
        is in place for it to work correctly and only needs 
        GetDesktopWindow to do so.  

Tue Jan 25 05:51:47 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [windows/defwnd.c]
	Added handling of activation messages (WM_ACTIVATE,
	WM_NCACTIVATE, WM_MOUSEACTIVATE)

	* [windows/event.c]
	De-activate the window when losing input focus.

	* [windows/focus.c]
	Bug fix in SetFocus().

	* [windows/message.c]
	Added activation of the window on mouse-clicks.

	* [windows/nonclient.c]
	Changed non-client area painting to use the correct colors
	depending upon the activation state.
	Added WM_NCACTIVATE message handling.
	Fixed a couple of bugs in window moving and resizing.

	* [windows/winpos.c]
	Implemented Get/SetActiveWindow().
	Implemented SWP_NOACTIVATE flag in SetWindowPos().

Jan 17, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [misc/message.c]
	MessageBox has a CaptionBar for his title except for
		MB_SYSTEMMODAL with MB_ICONHAND.

	* [windows/nonclient.c]
	Call to NC_TrackSysMenu on SysMenu button mouse click.

	* [windows/defwnd.c]
	Call to NC_TrackSysMenu on Alt key (VK_MENU).

	* [controls/menu.c]
	New GetSystemMenu() function.
	New CopySystemMenu() internal function.
	New NC_TrackSysMenu() internal function.

	* [include/windows.h]
	New WM_INITMENU, WM_INITMENUPOPUP, WM_MENUSELECT & WM_MENUCHAR defines.
diff --git a/ChangeLog b/ChangeLog
index 1aa6162..a957c33 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,130 @@
+Tue Feb  1 21:14:47 1994  Bob Amstadt  (bob@pooh)
+
+	* [loader/selector.c]
+	Added function CreateNewSegments().  Modified IPCCopySelector
+	to allow aliasing to any arbitrary memory space.
+
+	* [memory/global.c]
+	Fixed potential bug in GlobalGetFreeSegments().
+
+	* [memory/linear.c]
+	Created functions GlobalLinearLock() and GlobalLinearUnlock().
+
+Tue Feb  1 05:51:43 1994  julliard@di.epfl.ch (Alexandre Julliard)
+
+	* [controls/widgets.c]
+	Removed CAPTION window class.
+
+	* [loader/cursor.c]
+	Bug fix in LoadCursor(): don't allocate memory every time for
+	built-in cursors.
+
+	* [windows/clipping.c]
+	Invalidate child windows in InvalidateRgn().
+
+	* [windows/defwnd.c]
+	Added repaint of the caption when changing window text.
+
+	* [windows/event.c]
+	Modified SetCapture() to allow keyboard events while capturing.
+
+	* [windows/message.c]
+	New function MSG_GetHardwareMessage(), to do mouse tracking
+	without returning control to the Windows program.
+
+	* [windows/nonclient.c]
+	A couple of changes in frame drawing for DLGMODALFRAME windows.
+	Rewritten window moving code, to use MSG_GetHardwareMessage()
+	instead of non-client mouse events (this is the way Windows
+	does it), and to send WM_ENTERSIZEMOVE messages.
+	Removed WM_NCBUTTONUP and WM_NCMOUSEMOVE handlers.
+
+	* [windows/win.c]
+	Allocate temporary structures on the USER heap instead of
+	using GlobalAlloc().
+
+	* [windows/winpos.c]
+	Added function WINPOS_GetMinMaxInfo() to get sizing informations.
+
+Jan 31, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [windows/nonclient.c]
+	Call to StdDrawScrollBar() during NC's drawing.
+	Call to NC_ScrollBarButtonDown() on NC mouse events WM_LBUTTONDOWN.
+	Call to NC_ScrollBarButtonUp() on NC mouse events WM_LBUTTONUP.
+	Call to NC_ScrollBarMouseMove() on NC mouse events WM_MOUSEMOVE.
+
+	* [controls/menu.c]
+	New GetSubMenu() function.
+	Move GetMenu() & SetMenu() functions from 'windows/win.c'.
+
+	* [controls/combo.c]
+	Start changes to satisfy recent changes in scrollbars/windows.
+
+	* [loader/resource.c]
+	Put some code in LoadAccelerators() stub.
+	New TranslateAccelerator() function.
+
+	* [windows/win.c]
+	Remove GetMenu() & SetMenu() functions.
+	Call to NC_CreateScrollBars() if required by CreateWindow().
+
+----------------------------------------------------------------------
+Mon Jan 24 10:40:10 EST 1994 John Richardson (jrichard@cs.uml.edu)
+
+        * [window/win.c]
+        Added functions EnumWindows, EnumChildWindows, and helper
+        WIN_EnumChildWin.  EnumWindows won't list all wine windows
+        because GetDesktopWindow isn't complete.  However, the code
+        is in place for it to work correctly and only needs 
+        GetDesktopWindow to do so.  
+
+Tue Jan 25 05:51:47 1994  julliard@di.epfl.ch (Alexandre Julliard)
+
+	* [windows/defwnd.c]
+	Added handling of activation messages (WM_ACTIVATE,
+	WM_NCACTIVATE, WM_MOUSEACTIVATE)
+
+	* [windows/event.c]
+	De-activate the window when losing input focus.
+
+	* [windows/focus.c]
+	Bug fix in SetFocus().
+
+	* [windows/message.c]
+	Added activation of the window on mouse-clicks.
+
+	* [windows/nonclient.c]
+	Changed non-client area painting to use the correct colors
+	depending upon the activation state.
+	Added WM_NCACTIVATE message handling.
+	Fixed a couple of bugs in window moving and resizing.
+
+	* [windows/winpos.c]
+	Implemented Get/SetActiveWindow().
+	Implemented SWP_NOACTIVATE flag in SetWindowPos().
+
+Jan 17, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [misc/message.c]
+	MessageBox has a CaptionBar for his title except for
+		MB_SYSTEMMODAL with MB_ICONHAND.
+
+	* [windows/nonclient.c]
+	Call to NC_TrackSysMenu on SysMenu button mouse click.
+
+	* [windows/defwnd.c]
+	Call to NC_TrackSysMenu on Alt key (VK_MENU).
+
+	* [controls/menu.c]
+	New GetSystemMenu() function.
+	New CopySystemMenu() internal function.
+	New NC_TrackSysMenu() internal function.
+
+	* [include/windows.h]
+	New WM_INITMENU, WM_INITMENUPOPUP, WM_MENUSELECT & WM_MENUCHAR defines.
+
+----------------------------------------------------------------------
 Thu Jan 13 11:45:13 1994  John Richardson <jrichard@cs.uml.edu>
 
 	* [window/win.c]
diff --git a/DEVELOPERS-HINTS b/DEVELOPERS-HINTS
new file mode 100644
index 0000000..3321aa9
--- /dev/null
+++ b/DEVELOPERS-HINTS
@@ -0,0 +1,81 @@
+This is intend to be a document to help new developers get started.
+Existing developers should feel free to add there comments.
+
+RESERVING WINE PROJECT ARES:
+
+If you wish to work on a specific set of API functions.  Send
+mail to wine-project@amscons.com.  The automatic mail handler
+will provide you with instructions.
+
+SUBMITTING YOUR WORK:
+
+Submissions of code for inclussion into Wine should be sent to
+bob@amscons.com (Bob Amstadt).  You MUST provide a suitable
+ChangeLog entry for any work that you submit.  I prefer new code
+to be submitted as diffs off of the latest release.  Releases are
+every Tuesday evening (approximately 19:00 PST or Wednesday 03:00 GMT).
+
+MEMORY AND SEGMENTS:
+
+NE (Win16) executables consist of multiple segments.  The Wine loader
+loads each segment into a unique location the Wine processes memory
+and assigns a selector to that segment.  To make address conversion
+simpler, Wine loads the segments in such a way that the segmented
+address (16:16) is stored in memory the same way as the 32-bit linear
+address.  For example, the segmented address 1237:89AB can be at the
+address 0x123789AB in the Wine process space.
+
+This also implies that a Win16 program cannot access any arbitrary
+memory location.  If a pointer needs to be returned to a Win16 program,
+then the memory block must be allocated using either GlobalAlloc()
+or HEAP_Alloc().  The HEAP_* functions are faster than the Global*
+functions but are only capable of managing a 64k memory block.  The
+HEAP_* functions are used to implement local heaps.  Wine should
+never call Local* functions.  These functions are reserved for use
+by Win16 programs only!
+
+The following code fragment should be used to establish a new Wine
+local heap:
+
+	#include "heap.h"
+
+	#define MY_HEAP_SIZE	0x10000		/* Must be <= 64k */
+
+	int MyHeapHandle;
+	void *MyHeapBase;
+	MDESC *MyHeap;
+
+		...
+
+	int InitMyHeap()
+	{
+	    MyHeapHandle = GlobalAlloc(GMEM_FIXED, MY_HEAP_SIZE);
+	    if (MyHeapHandle == 0)
+		return -1;
+	    MyHeapBase = GlobalLock(MyHeapHandle);
+	    HEAP_Init(&MyHeap, MyHeapBase, MY_HEAP_SIZE);
+	    return 0;
+	}
+
+Memory blocks greater than 64 kilobytes in length must be allocated
+using GlobalAlloc().  Because of our special memory mapping, GlobalLock()
+cannot be used to obtain the address of a linearly accessible memory
+block that is greater than 64kB in length.  Instead GlobalLinearLock()
+should be used.  The inverse function GlobalLinearUnlock() must be 
+called before the block can be freed with GlobalFree().
+
+API ENTRY POINTS:
+
+Because Win16 programs use a 16-bit stack and because they can only
+call 16:16 addressed functions, all API entry points must be at low
+address offsets and must have the arguments translated and moved to
+Wines 32-bit stack.  This task is handled by the code in the "if1632"
+directory.  To define a new API entry point handler you must place a
+new entry in the appropriate API specification file.  These files are
+named *.spec.  For example, the API specification file for the USER DLL
+is contained in the file user.spec.  These entries are processed by
+the "build" program to create dll_*.s and dll_tab_*.c.  The dll_*.s
+files contain the entry point code for each API call, and the dll_tab_*.s
+files contain tables used by relay.c to translate arguments and transfer
+control to the proper handler.  The format of the *.spec files is
+documented in the file "tools/build-spec.txt".
\ No newline at end of file
diff --git a/Imakefile b/Imakefile
index 26b35f4..05b5b4f 100644
--- a/Imakefile
+++ b/Imakefile
@@ -1,21 +1,22 @@
 #include "Wine.tmpl"
 
 /*
- * This is the first try at using Imakefiles. There are probably many
- * problems and things I haven't even considered. I do not have a Linux
- * system to test them on, just NetBSD, so you may need to change things
- * like the the SYSLIBS definition below...
+ * This is the second try at using Imakefiles. There are probably many
+ * problems and things I haven't even considered. I do not have a fixed
+ * Linux system to test them on, but thanks to Thomas Michlmayr
+ * <tmichl@cosy.sbg.ac.at> for use of one of his boxes. 
  *
- * Peter Galbavy, 5th Dec 1993 peter@wonderland.org
+ * SEE BELOW ABOUT DEBUGGING AND LINUX
+ *
+ * Peter Galbavy, 31st Jan 1994: peter@wonderland.org
  */
 
-#define IHaveSubDirs
+#define IHaveSubdirs
 #define	PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' 'CC=$(CC)'
 
 SUBDIRS = \
 	tools \
 	controls \
-	debugger \
 	etc \
 	if1632 \
 	include \
@@ -26,6 +27,21 @@
 	test \
 	windows
 
+/*
+ * due to me not having the time and resources to test this, debugging
+ * has been left out by for now of the Imakefiles. To put it back you have
+ * to add:
+ *	debugger
+ * to the SUBDIRS list and:
+ *	debugger
+ *	readline.o
+ * to the OBJS list.
+ *
+ * Not doing this will make the build fail in loader/signal.c, with an
+ * unresolved reference to wine_debug. Comment out the line for now...
+ * sigh. Fixed soon.
+ */
+
 WINEDIR = $(LIBDIR)/wine
 
 OBJS = \
@@ -35,32 +51,29 @@
 	memory.o \
 	misc.o \
 	objects.o \
-	windows.o \
-	debugger.o \
-	readline.o
+	windows.o
 
 #ifdef i386BsdArchitecture
 SYSLIBS = -ll -lm -li386 -lgnumalloc
 #else
-#ifdef LinuxArchitechture
+#ifdef LinuxArchitecture
 SYSLIBS = -lm
 #endif
 #endif
 
-AllTarget(wine)
-
-NamedTargetSubdirs($(OBJS),$(SUBDIRS),"making",PassCDebugFlags,all)
-MakefileSubdirs($(SUBDIRS))
+MakeSubdirs($(SUBDIRS))
 DependSubdirs($(SUBDIRS))
-IncludesSubdirs($(SUBDIRS))
-CleanSubdirs($(SUBDIRS))
+
+#ifdef i386BsdArchitecture
+AllTarget(wine)
+#endif
 
 NormalProgramTarget(wine,$(OBJS),XawClientDepLibs,XawClientLibs,$(SYSLIBS))
 
+#ifdef LinuxArchitecture
+AllTarget(wine)
+#endif
+
 depend::
 
 install::
-
-includes::
-
-clean::
diff --git a/Makefile b/Makefile
index 033a5bf..bbae18a 100644
--- a/Makefile
+++ b/Makefile
@@ -27,6 +27,9 @@
 	rm -f *~ *.o *#
 	@for i in tools $(SUBDIRS); do (cd $$i && $(MAKE) clean) || exit; done
 
+patchclean:
+	rm -f `find . -name '*.orig' -o -name '*.rej'`
+
 $(TARGET): dummy
 	@for i in tools $(SUBDIRS); \
 	do (cd $$i && echo $$i && $(MAKE) INCLUDE_DIR=../$(INCLUDE_DIR) \
@@ -36,5 +39,5 @@
 depend:
 	@for i in tools $(SUBDIRS); \
 	     do (cd $$i && echo $$i && \
-	     $(MAKE) INCLUDE_DIR=../$(INCLUDE_DIR) depend) \
+	     $(MAKE) INCLUDE_DIR=../$(INCLUDE_DIR) COPTS="$(COPTS)" depend) \
 	     || exit; done
diff --git a/README b/README
index 1b23e05..6b0e42a 100644
--- a/README
+++ b/README
@@ -41,6 +41,17 @@
 Have a nice game of solitaire, but be careful.  Emulation isn't perfect.
 So, occassionally it will crash.
 
+WHAT'S NEW with Wine-940201: (see ChangeLog for details)
+	- Support for huge data structures.
+	- FreeBSD support.
+	- Many many bug fixes
+
+WHAT'S NEW with version 0.8: (see ChangeLog for details)
+	- Eliminated Xt-dependent code.  Thanks to Alexandre and Martin.
+	- EnumWindows() and EnumChildWindows()
+	- Activating and deactivating of windows.
+	- More work on system menus.
+
 WHAT'S NEW with version 0.7: (see ChangeLog for details)
 	- Eliminated Xt-dependent code.  Thanks to Alexandre and Martin.
 	- Other bug fixes.
diff --git a/bsdmake.patch b/bsdmake.patch
index 68fa157..92dc3a5 100644
--- a/bsdmake.patch
+++ b/bsdmake.patch
@@ -1,15 +1,22 @@
-diff -ruN ../Backup//Makefile ./Makefile
---- ../Backup//Makefile	Tue Sep 14 09:47:00 1993
-+++ ./Makefile	Thu Sep 16 09:59:52 1993
-@@ -7,7 +7,7 @@
- ######################################################################
- # These definitions are for the top level
- TARGET=wine
--LIBS=-L. -L/usr/X386/lib -lXext -lXaw -lXt -lXmu -lX11 -lm
-+LIBS=-L. -L/usr/X386/lib -lXext -lXaw -lXt -lXmu -lX11 -lm -li386 -lgnumalloc -ll
- OBJS=if1632/if1632.o controls/controls.o loader/loader.o \
- 	memory/memory.o misc/misc.o objects/objects.o windows/windows.o
- SUBDIRS=if1632 controls loader memory misc objects windows
+*** Makefile.orig	Tue Jan 18 12:36:47 1994
+--- Makefile	Mon Jan 24 22:34:06 1994
+***************
+*** 8,14 ****
+  ######################################################################
+  # These definitions are for the top level
+  TARGET=wine
+! LIBS=-L/usr/X386/lib -lX11 -lm
+  OBJS=if1632/if1632.o controls/controls.o loader/loader.o \
+  	memory/memory.o misc/misc.o objects/objects.o windows/windows.o debugger/debugger.o
+  SUBDIRS=if1632 controls loader memory misc objects windows debugger
+--- 8,14 ----
+  ######################################################################
+  # These definitions are for the top level
+  TARGET=wine
+! LIBS=-L/usr/X386/lib -lX11 -lm -li386 -lgnumalloc -ll
+  OBJS=if1632/if1632.o controls/controls.o loader/loader.o \
+  	memory/memory.o misc/misc.o objects/objects.o windows/windows.o debugger/debugger.o
+  SUBDIRS=if1632 controls loader memory misc objects windows debugger
 diff -ruN ../Backup//controls/Makefile ./controls/Makefile
 --- ../Backup//controls/Makefile	Sat Sep 11 22:13:44 1993
 +++ ./controls/Makefile	Thu Sep 16 10:00:24 1993
diff --git a/controls/Imakefile b/controls/Imakefile
index aee3e14..22fb4af 100644
--- a/controls/Imakefile
+++ b/controls/Imakefile
@@ -3,30 +3,24 @@
 MODULE = controls
 
 SRCS = \
-	menu.c \
-	widgets.c \
 	button.c \
-	scroll.c \
-	listbox.c \
+	caption.c \
 	combo.c \
+	listbox.c \
+	menu.c \
+	scroll.c \
 	static.c \
-	SmeMenuButto.c \
-	WinLabel.c \
-	WinCommand.c \
-	WinMenuButto.c
+	widgets.c
 
 OBJS = \
-	menu.o \
-	widgets.o \
 	button.o \
-	scroll.o \
-	listbox.o \
+	caption.o \
 	combo.o \
+	listbox.o \
+	menu.o \
+	scroll.o \
 	static.o \
-	SmeMenuButto.o \
-	WinLabel.o \
-	WinCommand.o \
-	WinMenuButto.o
+	widgets.o
 
 WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
 DependTarget()
diff --git a/controls/button.c b/controls/button.c
index aad2aa1..7ecd9db 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -512,8 +512,8 @@
     FillRect(hDC, &rc, hBrush);
 
     textlen = GetWindowTextLength(hWnd);
-    hText = LocalAlloc(LMEM_MOVEABLE, textlen+1);
-    text = LocalLock(hText);
+    hText = USER_HEAP_ALLOC(0, textlen+1);
+    text = USER_HEAP_ADDR(hText);
     GetWindowText(hWnd, text, textlen+1);
     GetTextMetrics(hDC, &tm);
 
@@ -555,8 +555,7 @@
 	DrawFocusRect(hDC, &rc);
     }
 
-    LocalUnlock(hText);
-    LocalFree(hText);
+    USER_HEAP_FREE(hText);
     GlobalUnlock(hWnd);
     EndPaint(hWnd, &ps);
 }
@@ -725,8 +724,8 @@
     FillRect(hDC, &rc, hBrush);
 
     textlen = GetWindowTextLength(hWnd);
-    hText = LocalAlloc(LMEM_MOVEABLE, textlen+1);
-    text = LocalLock(hText);
+    hText = USER_HEAP_ALLOC(0, textlen+1);
+    text = USER_HEAP_ADDR(hText);
     GetWindowText(hWnd, text, textlen+1);
     GetTextMetrics(hDC, &tm);
 
@@ -760,8 +759,7 @@
 	DrawFocusRect(hDC, &rc);
     }
 
-    LocalUnlock(hText);
-    LocalFree(hText);
+    USER_HEAP_FREE(hText);
     GlobalUnlock(hWnd);
     EndPaint(hWnd, &ps);
 }
@@ -900,8 +898,8 @@
     FillRect(hDC, &rc, hBrush);
 
     textlen = GetWindowTextLength(hWnd);
-    hText = LocalAlloc(LMEM_MOVEABLE, textlen+1);
-    text = LocalLock(hText);
+    hText = USER_HEAP_ALLOC(0, textlen+1);
+    text = USER_HEAP_ADDR(hText);
     GetWindowText(hWnd, text, textlen+1);
     GetTextExtentPoint(hDC, text, textlen, &size);
 
@@ -913,8 +911,7 @@
     rc.bottom = size.cy;
     DrawText(hDC, text, textlen, &rc, DT_SINGLELINE);
 
-    LocalUnlock(hText);
-    LocalFree(hText);
+    USER_HEAP_FREE(hText);
     EndPaint(hWnd, &ps);
 }
 
diff --git a/controls/combo.c b/controls/combo.c
index f4af8dc..2bcde7f 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -66,9 +66,15 @@
 	lphc->hWndDrop = CreateWindow("BUTTON", "", 
         	WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_OWNERDRAW,
         	width - 16, 0, 16, 16, hwnd, 1, wndPtr->hInstance, 0L);
-	lphc->hWndEdit = CreateWindow("STATIC", "", 
-        	WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | SS_LEFT,
-        	0, 0, width - 16, 16, hwnd, 1, wndPtr->hInstance, 0L);
+        if (wndPtr->dwStyle & CBS_SIMPLE)
+/*	    lphc->hWndEdit = CreateWindow("EDIT", "", */
+	    lphc->hWndEdit = CreateWindow("STATIC", "", 
+		WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | SS_LEFT,
+		0, 0, width - 16, 16, hwnd, 1, wndPtr->hInstance, 0L);
+	else
+	    lphc->hWndEdit = CreateWindow("STATIC", "", 
+		WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | SS_LEFT,
+		0, 0, width - 16, 16, hwnd, 1, wndPtr->hInstance, 0L);
 	lphc->hWndLBox = CreateWindow("LISTBOX", "", 
         	WS_CHILD | WS_CLIPCHILDREN | WS_BORDER | WS_VSCROLL | LBS_NOTIFY,
         	wndPtr->rectClient.left, wndPtr->rectClient.top + 16, width, height, 
@@ -128,7 +134,7 @@
             switch(HIWORD(lParam))
         	{
         	case LBN_SELCHANGE:
-		    lphc->dwState = lphc->dwState & (CB_SHOWDROPDOWN ^ 0xFFFF);
+		    lphc->dwState = lphc->dwState & (CB_SHOWDROPDOWN ^ 0xFFFFFFFFL);
 		    ShowWindow(lphc->hWndLBox, SW_HIDE);
 		    y = SendMessage(lphc->hWndLBox, LB_GETCURSEL, 0, 0L);
 		    if (y != LB_ERR) {
diff --git a/controls/listbox.c b/controls/listbox.c
index b1dfb73..642d47e 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -79,11 +79,11 @@
 	else
 	    lphl->hWndLogicParent = GetParent(hwnd);
 	lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
-	if (wndPtr->hWndVScroll != (HWND)NULL) {
+	if (wndPtr->dwStyle & WS_VSCROLL) {
 	    SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
 	    ShowScrollBar(hwnd, SB_VERT, FALSE);
 	    }
-	if (wndPtr->hWndHScroll != (HWND)NULL) {
+	if (wndPtr->dwStyle & WS_HSCROLL) {
 	    SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
 	    ShowScrollBar(hwnd, SB_HORZ, FALSE);
 	    }
@@ -225,7 +225,7 @@
 	        lphl = ListBoxGetStorageHeader(hwnd);
 		if (lphl->FirstVisible > 1) {
 		    lphl->FirstVisible--;
-		    if (wndPtr->hWndVScroll != (HWND)NULL)
+		    if (wndPtr->dwStyle & WS_VSCROLL)
 			SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 		    InvalidateRect(hwnd, NULL, TRUE);
 		    UpdateWindow(hwnd);
@@ -237,7 +237,7 @@
 	        lphl = ListBoxGetStorageHeader(hwnd);
 		if (lphl->FirstVisible < lphl->ItemsCount) {
 		    lphl->FirstVisible++;
-		    if (wndPtr->hWndVScroll != (HWND)NULL)
+		    if (wndPtr->dwStyle & WS_VSCROLL)
 			SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 		    InvalidateRect(hwnd, NULL, TRUE);
 		    UpdateWindow(hwnd);
@@ -310,7 +310,7 @@
 	if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
 	    ListBoxSetCurSel(hwnd, lphl->ItemFocused);
 	    }
-	if (wndPtr->hWndVScroll != (HWND)NULL)
+	if (wndPtr->dwStyle & WS_VSCROLL)
 	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
         InvalidateRect(hwnd, NULL, TRUE);
         UpdateWindow(hwnd);
@@ -419,7 +419,7 @@
         printf("ListBox LB_SETTOPINDEX wParam=%x !\n", wParam);
         lphl = ListBoxGetStorageHeader(hwnd);
 	lphl->FirstVisible = wParam;
-	if (wndPtr->hWndVScroll != (HWND)NULL)
+	if (wndPtr->dwStyle & WS_VSCROLL)
 	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 	InvalidateRect(hwnd, NULL, TRUE);
 	UpdateWindow(hwnd);
@@ -482,10 +482,10 @@
 		    MAKELONG(hwnd, CTLCOLOR_LISTBOX));
 	if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
 	GetClientRect(hwnd, &rect);
-	if ((wndPtr->hWndVScroll != (HWND)NULL) &&
-	    IsWindowVisible(wndPtr->hWndVScroll)) rect.right -= 16;
-	if ((wndPtr->hWndHScroll != (HWND)NULL) &&
-	    IsWindowVisible(wndPtr->hWndHScroll)) rect.bottom -= 16;
+/*
+	if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
+	if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
+*/
 	FillRect(hdc, &rect, hBrush);
 	maxwidth = rect.right;
 	rect.right = lphl->ColumnsWidth;
@@ -531,9 +531,11 @@
 EndOfPaint:
     EndPaint( hwnd, &ps );
     if ((lphl->ItemsCount > lphl->ItemsVisible) &
-	(wndPtr->hWndVScroll != (HWND)NULL)) {
+	(wndPtr->dwStyle & WS_VSCROLL)) {
+/*
         InvalidateRect(wndPtr->hWndVScroll, NULL, TRUE);
         UpdateWindow(wndPtr->hWndVScroll);
+*/
  	}
 }
 
@@ -563,10 +565,8 @@
 		    MAKELONG(hwnd, CTLCOLOR_LISTBOX));
 	if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
 	GetClientRect(hwnd, &rect);
-	if ((wndPtr->hWndVScroll != (HWND)NULL) &&
-	    IsWindowVisible(wndPtr->hWndVScroll)) rect.right -= 16;
-	if ((wndPtr->hWndHScroll != (HWND)NULL) &&
-	    IsWindowVisible(wndPtr->hWndHScroll)) rect.bottom -= 16;
+	if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
+	if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
 	FillRect(hdc, &rect, hBrush);
 	maxwidth = rect.right;
 	rect.right = lphl->ColumnsWidth;
@@ -612,9 +612,11 @@
 EndOfPaint:
     EndPaint( hwnd, &ps );
     if ((lphl->ItemsCount > lphl->ItemsVisible) &
-	(wndPtr->hWndVScroll != (HWND)NULL)) {
+	(wndPtr->dwStyle & WS_VSCROLL)) {
+/*
         InvalidateRect(wndPtr->hWndVScroll, NULL, TRUE);
         UpdateWindow(wndPtr->hWndVScroll);
+*/
         }
 }
 
@@ -634,10 +636,8 @@
     lpls = lphl->lpFirst;
     if (lpls == NULL) return LB_ERR;
     GetClientRect(hwnd, &rect);
-    if ((wndPtr->hWndVScroll != (HWND)NULL) &&
-	IsWindowVisible(wndPtr->hWndVScroll)) rect.right -= 16;
-    if ((wndPtr->hWndHScroll != (HWND)NULL) &&
-	IsWindowVisible(wndPtr->hWndHScroll)) rect.bottom -= 16;
+    if (wndPtr->dwStyle & WS_VSCROLL) rect.right -= 16;
+    if (wndPtr->dwStyle & WS_HSCROLL) rect.bottom -= 16;
     h = w2 = 0;
     w = lphl->ColumnsWidth;
     for(i = 1; i <= lphl->ItemsCount; i++) {
@@ -720,10 +720,10 @@
     lplsnew->dis.itemID = lphl->ItemsCount;
     lplsnew->dis.itemData = (DWORD)newstr;
     lplsnew->hData = hTemp;
-    if (wndPtr->hWndVScroll != (HWND)NULL)
+    if (wndPtr->dwStyle & WS_VSCROLL)
 	SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, 
 	    (lphl->FirstVisible != 1));
-    if (wndPtr->hWndHScroll != (HWND)NULL && lphl->ItemsPerColumn != 0)
+    if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
 	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
 	    lphl->ItemsPerColumn + 1, (lphl->FirstVisible != 1));
     if (lphl->FirstVisible >= (lphl->ItemsCount - lphl->ItemsVisible)) {
@@ -731,9 +731,9 @@
         UpdateWindow(hwnd);
         }
     if ((lphl->ItemsCount - lphl->FirstVisible) == lphl->ItemsVisible) {
-	if (wndPtr->hWndVScroll != (HWND)NULL)
+	if (wndPtr->dwStyle & WS_VSCROLL)
 	    ShowScrollBar(hwnd, SB_VERT, TRUE);
-	if (wndPtr->hWndHScroll != (HWND)NULL)
+	if (wndPtr->dwStyle & WS_HSCROLL)
 	    ShowScrollBar(hwnd, SB_HORZ, TRUE);
 	}
     return lphl->ItemsCount;
@@ -779,17 +779,17 @@
     lplsnew->dis.itemID = lphl->ItemsCount;
     lplsnew->dis.itemData = (DWORD)newstr;
     lplsnew->hData = hTemp;
-   if (wndPtr->hWndVScroll != (HWND)NULL)
+    if (wndPtr->dwStyle & WS_VSCROLL)
 	SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, 
 	    (lphl->FirstVisible != 1));
-    if (wndPtr->hWndHScroll != (HWND)NULL && lphl->ItemsPerColumn != 0)
+    if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
 	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
 	    lphl->ItemsPerColumn + 1, (lphl->FirstVisible != 1));
     if (((lphl->ItemsCount - lphl->FirstVisible) == lphl->ItemsVisible) && 
         (lphl->ItemsVisible != 0)) {
-	if (wndPtr->hWndVScroll != (HWND)NULL)
+	if (wndPtr->dwStyle & WS_VSCROLL)
 	    ShowScrollBar(hwnd, SB_VERT, TRUE);
-	if (wndPtr->hWndHScroll != (HWND)NULL)
+	if (wndPtr->dwStyle & WS_HSCROLL)
 	    ShowScrollBar(hwnd, SB_HORZ, TRUE);
 	}
     if ((lphl->FirstVisible <= uIndex) &&
@@ -851,15 +851,15 @@
     lphl->ItemsCount--;
     if (lpls->hData != 0) USER_HEAP_FREE(lpls->hData);
     if (lpls->hMem != 0) USER_HEAP_FREE(lpls->hMem);
-    if (wndPtr->hWndVScroll != (HWND)NULL)
+    if (wndPtr->dwStyle & WS_VSCROLL)
 	SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
-    if (wndPtr->hWndHScroll != (HWND)NULL && lphl->ItemsPerColumn != 0)
+    if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
 	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
 	    lphl->ItemsPerColumn + 1, TRUE);
     if (lphl->ItemsCount < lphl->ItemsVisible) {
-	if (wndPtr->hWndVScroll != (HWND)NULL)
+	if (wndPtr->dwStyle & WS_VSCROLL)
 	    ShowScrollBar(hwnd, SB_VERT, FALSE);
-	if (wndPtr->hWndHScroll != (HWND)NULL)
+	if (wndPtr->dwStyle & WS_HSCROLL)
 	    ShowScrollBar(hwnd, SB_HORZ, FALSE);
 	}
     if ((lphl->FirstVisible <= uIndex) &&
@@ -922,14 +922,14 @@
 	SendMessage(wndPtr->hwndParent, WM_COMMAND, 
     	    wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
 
-    if (wndPtr->hWndVScroll != (HWND)NULL)
+    if (wndPtr->dwStyle & WS_VSCROLL)
 	SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
-    if (wndPtr->hWndHScroll != (HWND)NULL && lphl->ItemsPerColumn != 0)
+    if ((wndPtr->dwStyle & WS_HSCROLL) && lphl->ItemsPerColumn != 0)
 	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
 	    lphl->ItemsPerColumn + 1, TRUE);
-    if (wndPtr->hWndVScroll != (HWND)NULL)
+    if (wndPtr->dwStyle & WS_VSCROLL)
 	ShowScrollBar(hwnd, SB_VERT, FALSE);
-    if (wndPtr->hWndHScroll != (HWND)NULL)
+    if (wndPtr->dwStyle & WS_HSCROLL)
 	ShowScrollBar(hwnd, SB_HORZ, FALSE);
     InvalidateRect(hwnd, NULL, TRUE);
     UpdateWindow(hwnd);
diff --git a/controls/menu.c b/controls/menu.c
index 8c43e6f..add8f18 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -4,18 +4,26 @@
 
 /*
 #define DEBUG_MENU
+#define DEBUG_SYSMENU
 */
 #define USE_POPUPMENU
 
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
 #include "windows.h"
+#include "sysmetrics.h"
 #include "menu.h"
 #include "heap.h"
 #include "win.h"
 #include "bitmaps/check_bitmap"
 #include "bitmaps/nocheck_bitmap"
 
+#define SC_ABOUTWINE     SC_SCREENSAVE+1
+#define SC_SYSMENU	 SC_SCREENSAVE+2
+#define SC_ABOUTWINEDLG	 SC_SCREENSAVE+3
+
+extern HINSTANCE hSysRes;
+HMENU	hSysMenu = 0;
 HBITMAP hStdCheck = 0;
 HBITMAP hStdMnArrow = 0;
 
@@ -40,9 +48,12 @@
 LPSTR GetShortCutString(LPSTR str);
 WORD GetShortCutPos(LPSTR str);
 BOOL HideAllSubPopupMenu(LPPOPUPMENU menu);
+HMENU CopySysMenu();
 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu);
 void SetMenuLogicalParent(HMENU hMenu, HWND hWnd);
 
+BOOL FAR PASCAL AboutWine_Proc(HWND hDlg, WORD msg, WORD wParam, LONG lParam);
+
 /***********************************************************************
  *           PopupMenuWndProc
  */
@@ -98,13 +109,26 @@
 	return 0;
     case WM_COMMAND:
 	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-#ifdef DEBUG_MENU
-    	printf("PopupMenu // push to lower parent WM_COMMAND !\n");
-#endif
-	if (lppop->hWndParent != (HWND)NULL)
+	if (lppop->hWndParent != (HWND)NULL) {
 	    SendMessage(lppop->hWndParent, WM_COMMAND, wParam, lParam);
-	else 
-	    SendMessage(lppop->ownerWnd, WM_COMMAND, wParam, lParam);
+#ifdef DEBUG_MENU
+	    printf("PopupMenu // push to lower parent WM_COMMAND !\n");
+#endif
+	    }
+	else {
+	    if (lppop->SysFlag == 0) {
+		SendMessage(lppop->ownerWnd, WM_COMMAND, wParam, lParam);
+#ifdef DEBUG_MENU
+		printf("PopupMenu // push to Owner WM_COMMAND !\n");
+#endif
+		}
+	    else {
+#ifdef DEBUG_SYSMENU
+		printf("PopupMenu // push to Owner WM_SYSCOMMAND !\n");
+#endif
+		SendMessage(lppop->ownerWnd, WM_SYSCOMMAND, wParam, lParam);
+		}
+	    }
 	if (lppop->BarFlags == 0) ShowWindow(hwnd, SW_HIDE);
     	break;
     case WM_SHOWWINDOW:
@@ -169,16 +193,18 @@
 		GetClientRect(hwnd, &rect);
 		if (lppop->BarFlags != 0) {
 		    y = rect.bottom - rect.top;
+		    GetWindowRect(hwnd, &rect);
+		    y += rect.top;
 		    TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-			lpitem->rect.left, 0, 
-			0, lppop->ownerWnd, (LPRECT)NULL);
+			rect.left + lpitem->rect.left, 
+			y, 0, lppop->ownerWnd, (LPRECT)NULL);
 		    }
 		else {
 		    x = rect.right;
 		    GetWindowRect(hwnd, &rect);
 		    x += rect.left;
 		    TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-			x, lpitem->rect.top,
+			x, rect.top + lpitem->rect.top,
 			0, lppop->ownerWnd, (LPRECT)NULL);
 		    }
 		break;
@@ -199,12 +225,40 @@
 	    if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
 		((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
 	    	ShowWindow(lppop->hWnd, SW_HIDE);
-		if (lppop->hWndParent != (HWND)NULL)
+		if (lppop->hWndParent != (HWND)NULL) {
 		    SendMessage(lppop->hWndParent, WM_COMMAND, 
 					lpitem->item_id, 0L);
-		else 
-		    SendMessage(lppop->ownerWnd, WM_COMMAND, 
+#ifdef DEBUG_MENU
+		    printf("PopupMenu // WM_COMMAND to ParentMenu wParam=%d !\n", 
+			lpitem->item_id);
+#endif
+		    }
+		else {
+		    if (lppop->SysFlag == 0) {
+#ifdef DEBUG_MENU
+			printf("PopupMenu // WM_COMMAND wParam=%d !\n", 
+				lpitem->item_id);
+#endif
+			SendMessage(lppop->ownerWnd, WM_COMMAND, 
 					lpitem->item_id, 0L);
+			}
+		    else {
+			if (lpitem->item_id == SC_ABOUTWINE) {
+			    printf("SysMenu // Show 'About Wine ...' !\n");
+/*			    DialogBox(hSysRes, MAKEINTRESOURCE(SC_ABOUTWINEDLG), */
+			    DialogBox(hSysRes, MAKEINTRESOURCE(2), 
+				GetParent(hwnd), (FARPROC)AboutWine_Proc);
+			    }
+			else {
+			    SendMessage(lppop->ownerWnd, WM_SYSCOMMAND,
+						 lpitem->item_id, 0L);
+#ifdef DEBUG_SYSMENU
+			    printf("PopupMenu // WM_SYSCOMMAND wParam=%04X !\n", 
+					lpitem->item_id);
+#endif
+			    }
+			}
+		    }
 #ifdef DEBUG_MENU
 		printf("PopupMenu // SendMessage WM_COMMAND wParam=%d !\n", 
 			lpitem->item_id);
@@ -248,10 +302,9 @@
 		    if (lppop2 == NULL) break;
 		    if (lppop->BarFlags != 0) {
 			lppop2->hWndParent = hwnd;
-			GetClientRect(hwnd, &rect);
-			y = rect.bottom - rect.top;
+			GetWindowRect(hwnd, &rect);
 			TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-				lpitem->rect.left, 0, 
+				lpitem->rect.left, rect.top, 
 				0, lppop->ownerWnd, (LPRECT)NULL);
 			}
 		    }
@@ -747,6 +800,9 @@
     HFONT	hOldFont;
     UINT  	i, OldWidth, TempWidth;
     DWORD	dwRet;
+#ifdef DEBUG_MENUCALC
+	printf("PopupMenuCalcSize hWnd=%04X !\n", hWnd);
+#endif
     lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
     if (lppop == NULL) return;
     if (lppop->nItems == 0) return;
@@ -759,6 +815,9 @@
     lpitem = lppop->firstItem;
     for(i = 0; i < lppop->nItems; i++) {
 	if (lpitem == NULL) break;
+#ifdef DEBUG_MENUCALC
+	printf("PopupMenuCalcSize item #%d !\n", i);
+#endif
 	rect.right = rect.left + lppop->Width;
 	if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
 	    rect.bottom = rect.top + 3;
@@ -788,11 +847,10 @@
     if (OldWidth < lppop->Width) goto CalcAGAIN;
     lppop->Height = rect.bottom;
 #ifdef DEBUG_MENUCALC
-    printf("PopupMenuCalcSize w=%d h=%d !\n", 
-    	lppop->Width, lppop->Height);
+    printf("PopupMenuCalcSize w=%d h=%d !\n", lppop->Width, lppop->Height);
 #endif
     SelectObject(hDC, hOldFont);
-    ReleaseDC(0, hDC);
+    ReleaseDC(hwnd, hDC);
 }
 
 
@@ -1775,6 +1833,7 @@
     menu->hWndParent	  = 0;
     menu->MouseFlags	  = 0;
     menu->BarFlags	  = 0;
+    menu->SysFlag	  = FALSE;
     menu->Width = 100;
     menu->Height = 0;
     return hMenu;
@@ -1798,8 +1857,8 @@
     wndPtr = WIN_FindWndPtr(hWnd);
     lppop->ownerWnd = hWnd;
     if (lppop->hWnd == (HWND)NULL) {
-        lppop->hWnd = CreateWindow("POPUPMENU", "", WS_CHILD | WS_VISIBLE,
-        	x, y, lppop->Width, lppop->Height, hWnd, 0, 
+        lppop->hWnd = CreateWindow("POPUPMENU", "", WS_POPUP | WS_VISIBLE,
+        	x, y, lppop->Width, lppop->Height, (HWND)NULL, 0, 
         	wndPtr->hInstance, (LPSTR)lppop);
         }
     else {
@@ -1828,6 +1887,43 @@
 
 
 /**********************************************************************
+ *			NC_TrackSysMenu		[Internal]
+ */
+void NC_TrackSysMenu(hWnd)
+{
+    RECT	rect;
+    LPPOPUPMENU	lpsys;
+    WND *wndPtr = WIN_FindWndPtr(hWnd);    
+#ifdef DEBUG_MENU
+    printf("NC_TrackSysMenu hWnd=%04X !\n", hWnd);
+#endif
+    if (!wndPtr) return;
+    lpsys = (LPPOPUPMENU)GlobalLock(wndPtr->hSysMenu);
+#ifdef DEBUG_MENU
+    printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
+#endif
+    if (lpsys == NULL) return;
+#ifdef DEBUG_MENU
+    printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
+#endif
+    lpsys->BarFlags = FALSE;
+    lpsys->SysFlag = TRUE;
+    if (!IsWindowVisible(lpsys->hWnd)) {
+	GetWindowRect(hWnd, &rect);
+#ifdef DEBUG_MENU
+	printf("NC_TrackSysMenu lpsys->hWnd=%04X !\n", lpsys->hWnd);
+#endif
+	TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON, 
+		rect.left, rect.top + SYSMETRICS_CYSIZE, 
+		0, hWnd, (LPRECT)NULL);
+	}
+    else {
+	ShowWindow(lpsys->hWnd, SW_HIDE);
+	}
+}
+
+
+/**********************************************************************
  *			SetMenuItemBitmaps	[USER.418]
  */
 BOOL SetMenuItemBitmaps(HMENU hMenu, WORD nPos, WORD wFlags,
@@ -1881,6 +1977,7 @@
     menu->hWndParent	  = 0;
     menu->MouseFlags	  = 0;
     menu->BarFlags	  = TRUE;
+    menu->SysFlag	  = FALSE;
     menu->Width = 100;
     menu->Height = 0;
     return hMenu;
@@ -1923,7 +2020,105 @@
 
 
 /**********************************************************************
- *			DrawMenuBar		[USER.152]
+ *			LoadMenu		[USER.150]
+ */
+HMENU LoadMenu(HINSTANCE instance, char *menu_name)
+{
+    HMENU     		hMenu;
+    HANDLE		hMenu_desc;
+    MENU_HEADER 	*menu_desc;
+
+#ifdef DEBUG_MENU
+    if ((LONG)menu_name & 0xFFFF0000L)
+	printf("LoadMenu: instance %02x, menu '%s'\n", instance, menu_name);
+    else
+	printf("LoadMenu: instance %02x, menu '%04X'\n", instance, menu_name);
+#endif
+    if (instance == (HANDLE)NULL)  instance = hSysRes;
+    if (menu_name == NULL || 
+	(hMenu_desc = RSC_LoadMenu(instance, menu_name)) == 0 ||
+	(menu_desc = (MENU_HEADER *) GlobalLock(hMenu_desc)) == NULL)
+    {
+	return 0;
+    }
+    hMenu = CreateMenu();
+    ParseMenuResource((WORD *) (menu_desc + 1), 0, hMenu);
+    return hMenu;
+}
+
+
+/**********************************************************************
+ *			GetSystemMenu		[USER.156]
+ */
+HMENU GetSystemMenu(HWND hWnd, BOOL bRevert)
+{
+    WND		*wndPtr;
+    wndPtr = WIN_FindWndPtr(hWnd);
+    if (!bRevert) {
+	return wndPtr->hSysMenu;
+	}
+    else {
+	DestroyMenu(wndPtr->hSysMenu);
+	wndPtr->hSysMenu = CopySysMenu();
+	}
+    return wndPtr->hSysMenu;
+}
+
+
+/**********************************************************************
+ *			GetMenu		[USER.157]
+ */
+HMENU GetMenu(HWND hWnd) 
+{ 
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
+    if (wndPtr == NULL) return 0;
+    return wndPtr->wIDmenu;
+}
+
+/**********************************************************************
+ * 			SetMenu 	[USER.158]
+ */
+BOOL SetMenu(HWND hWnd, HMENU hMenu)
+{
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
+    if (wndPtr == NULL) return FALSE;
+    wndPtr->wIDmenu = hMenu;
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *			GetSubMenu		[USER.159]
+ */
+HMENU GetSubMenu(HMENU hMenu, short nPos)
+{
+    HMENU	hSubMenu;
+    LPPOPUPMENU lppop;
+    LPMENUITEM 	lpitem;
+    int		i;
+#ifdef DEBUG_MENU
+    printf("GetSubMenu (%04X, %04X) !\n", hMenu, nPos);
+#endif
+    if (hMenu == 0) return 0;
+    lppop = (LPPOPUPMENU) GlobalLock(hMenu);
+    if (lppop == NULL) return 0;
+    lpitem = lppop->firstItem;
+    for (i = 0; i < lppop->nItems; i++) {
+    	if (lpitem == NULL) break;
+    	if (i == nPos) {
+	    if (lpitem->item_flags & MF_POPUP)
+		return hSubMenu;
+	    else
+		return 0;
+	    }
+    	lpitem = (LPMENUITEM)lpitem->next;
+    	}
+    return 0;
+}
+
+
+/**********************************************************************
+ *			DrawMenuBar		[USER.160]
  */
 void DrawMenuBar(HWND hWnd)
 {
@@ -1940,31 +2135,53 @@
 
 
 /**********************************************************************
- *			LoadMenu		[USER.152]
+ *			CopySysMenu (Internal)
  */
-HMENU LoadMenu(HINSTANCE instance, char *menu_name)
+HMENU CopySysMenu()
 {
     HMENU     		hMenu;
-    HANDLE		hMenu_desc;
-    MENU_HEADER 	*menu_desc;
-
+    LPPOPUPMENU 	menu;
+    LPPOPUPMENU 	sysmenu;
 #ifdef DEBUG_MENU
-    printf("LoadMenu: instance %02x, menu '%s'\n",
-	   instance, menu_name);
+    printf("CopySysMenu entry !\n");
 #endif
-    if (menu_name == NULL || 
-	(hMenu_desc = RSC_LoadMenu(instance, menu_name)) == 0 ||
-	(menu_desc = (MENU_HEADER *) GlobalLock(hMenu_desc)) == NULL)
-    {
-	return 0;
-    }
-    hMenu = CreateMenu();
-    ParseMenuResource((WORD *) (menu_desc + 1), 0, hMenu);
-    
+    if (hSysMenu == 0) {
+	hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(1));
+/*	hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(SC_SYSMENU));*/
+/*	hSysMenu = LoadMenu((HINSTANCE)NULL, "SYSMENU"); */
+	if (hSysMenu == 0) {
+	    printf("SysMenu not found in system resources !\n");
+	    return (HMENU)NULL;
+	    }
+#ifdef DEBUG_MENU
+	else
+	    printf("SysMenu loaded from system resources %04X !\n", hSysMenu);
+#endif
+	}
+    hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
+    menu = (LPPOPUPMENU) GlobalLock(hMenu);
+    sysmenu = (LPPOPUPMENU) GlobalLock(hSysMenu);
+    if (menu != NULL && sysmenu != NULL) {
+	sysmenu->BarFlags = FALSE;
+	memcpy(menu, sysmenu, sizeof(POPUPMENU));
+	}
+    else {
+	printf("CopySysMenu // Bad SysMenu pointers !\n");
+	if (menu != NULL) {
+	    GlobalUnlock(hMenu);
+	    GlobalFree(hMenu);
+	    }
+	return (HMENU)NULL;
+	}
+    GlobalUnlock(hMenu);
+    GlobalUnlock(hSysMenu);
     return hMenu;
 }
 
 
+/**********************************************************************
+ *			ParseMenuResource (for Xlib version)
+ */
 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu)
 {
     WORD 	*item;
@@ -1975,12 +2192,10 @@
     level++;
     next_item = first_item;
     i = 0;
-    do
-    {
+    do {
 	i++;
 	item = next_item;
-	if (*item & MF_POPUP)
-	{
+	if (*item & MF_POPUP) {
 	    MENU_POPUPITEM *popup_item = (MENU_POPUPITEM *) item;
 	    next_item = (WORD *) (popup_item->item_text + 
 				  strlen(popup_item->item_text) + 1);
@@ -1988,20 +2203,19 @@
 	    next_item = ParseMenuResource(next_item, level, hSubMenu);
 	    AppendMenu(hMenu, popup_item->item_flags, 
 	    	hSubMenu, popup_item->item_text);
-	}
-	else
-	{
+	    }
+	else {
 	    MENU_NORMALITEM *normal_item = (MENU_NORMALITEM *) item;
 	    next_item = (WORD *) (normal_item->item_text + 
 				  strlen(normal_item->item_text) + 1);
 	    AppendMenu(hMenu, normal_item->item_flags, 
 	    	normal_item->item_id, normal_item->item_text);
+	    }
 	}
-    }
     while (!(*item & MF_END));
-
     return next_item;
 }
 
+
 #endif
 
diff --git a/controls/scroll.c b/controls/scroll.c
index 47da5bf..0f2aa84 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -8,12 +8,12 @@
 /*
 #define DEBUG_SCROLL
 */
-
 static char Copyright[] = "Copyright Martin Ayotte, 1993";
 
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
 #include "windows.h"
+#include "sysmetrics.h"
 #include "scroll.h"
 #include "heap.h"
 #include "win.h"
@@ -30,33 +30,39 @@
 HBITMAP hLfArrowD = 0;
 HBITMAP hRgArrowD = 0;
 
-LPHEADSCROLL ScrollBarGetWindowAndStorage(HWND hwnd, WND **wndPtr);
-LPHEADSCROLL ScrollBarGetStorageHeader(HWND hwnd);
-void StdDrawScrollBar(HWND hwnd);
-int CreateScrollBarStruct(HWND hwnd);
+LPHEADSCROLL ScrollBarGetWindowAndStorage(HWND hWnd, WND **wndPtr);
+LPHEADSCROLL ScrollBarGetStorageHeader(HWND hWnd);
+LPHEADSCROLL GetScrollObjectHandle(HWND hWnd, int nBar);
+void ScrollBarButtonDown(HWND hWnd, int nBar, int x, int y);
+void ScrollBarButtonUp(HWND hWnd, int nBar, int x, int y);
+void ScrollBarMouseMove(HWND hWnd, int nBar, WORD wParam, int x, int y);
+void StdDrawScrollBar(HWND hWnd, HDC hDC, int nBar, LPRECT lprect, LPHEADSCROLL lphs);
+int CreateScrollBarStruct(HWND hWnd);
+void NC_CreateScrollBars(HWND hWnd);
+LPHEADSCROLL AllocScrollBar(DWORD dwStyle, int width, int height);
 
 
 /***********************************************************************
  *           WIDGETS_ScrollBarWndProc
  */
-LONG ScrollBarWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+LONG ScrollBarWndProc( HWND hWnd, WORD message, WORD wParam, LONG lParam )
 {    
     WORD	wRet;
     short	x, y;
     short	width, height;
     WND  	*wndPtr;
     LPHEADSCROLL lphs;
-    LPDRAWITEMSTRUCT lpdis;
-    HDC		hMemDC;
+    PAINTSTRUCT ps;
+    HDC		hDC;
     BITMAP	bm;
-    RECT 	rect;
+    RECT 	rect, rect2;
     static RECT rectsel;
     switch(message)
     {
     case WM_CREATE:
-	CreateScrollBarStruct(hwnd);
+	CreateScrollBarStruct(hWnd);
 #ifdef DEBUG_SCROLL
-        printf("ScrollBar Creation up=%X down=%X!\n", lphs->hWndUp, lphs->hWndDown);
+        printf("ScrollBar Creation !\n");
 #endif
 	if (hUpArrow == (HBITMAP)NULL) 
 	    hUpArrow = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_UPARROWI));
@@ -76,197 +82,271 @@
 	    hRgArrowD = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_RGARROWD));
 	return 0;
     case WM_DESTROY:
-	lphs = ScrollBarGetWindowAndStorage(hwnd, &wndPtr);
+	lphs = ScrollBarGetWindowAndStorage(hWnd, &wndPtr);
 	if (lphs == 0) return 0;
 #ifdef DEBUG_SCROLL
         printf("ScrollBar WM_DESTROY %lX !\n", lphs);
 #endif
-	DestroyWindow(lphs->hWndUp);
-	DestroyWindow(lphs->hWndDown);
 	free(lphs);
 	*((LPHEADSCROLL *)&wndPtr->wExtra[1]) = 0;
 	return 0;
 	
-    case WM_COMMAND:
-#ifdef DEBUG_SCROLL
-        printf("ScrollBar WM_COMMAND wParam=%X lParam=%lX !\n", wParam, lParam);
-#endif
-	lphs = ScrollBarGetWindowAndStorage(hwnd, &wndPtr);
-	if (HIWORD(lParam) != BN_CLICKED) return 0;
-        if (LOWORD(lParam) == lphs->hWndUp)
-            SendMessage(wndPtr->hwndParent, lphs->Direction, 
-            	SB_LINEUP, MAKELONG(0, hwnd));
-        if (LOWORD(lParam) == lphs->hWndDown)
-            SendMessage(wndPtr->hwndParent, lphs->Direction, 
-            	SB_LINEDOWN, MAKELONG(0, hwnd));
-/*
-	SetFocus(hwnd);
-*/
-	return 0;
-
     case WM_LBUTTONDOWN:
-	lphs = ScrollBarGetWindowAndStorage(hwnd, &wndPtr);
-/*
-	SetFocus(hwnd);
-*/
-	SetCapture(hwnd);
-	GetClientRect(hwnd, &rect);
-	if (lphs->Direction == WM_VSCROLL) {
-	    y = HIWORD(lParam);
-#ifdef DEBUG_SCROLL
-	    printf("WM_LBUTTONDOWN y=%d cur+right=%d %d\n", 
-	    	y, lphs->CurPix + rect.right, lphs->CurPix + (rect.right << 1));
-#endif
-	    if (y < (lphs->CurPix + rect.right)) 
-	        SendMessage(wndPtr->hwndParent, lphs->Direction, 
-	        	SB_PAGEUP, MAKELONG(0, hwnd));
-	    if (y > (lphs->CurPix + (rect.right << 1))) 
-	        SendMessage(wndPtr->hwndParent, lphs->Direction, 
-	        	SB_PAGEDOWN, MAKELONG(0, hwnd));
-	    if ((y > (lphs->CurPix + rect.right)) &&
-	        (y < (lphs->CurPix + (rect.right << 1)))) {
-	        lphs->ThumbActive = TRUE;
-#ifdef DEBUG_SCROLL
-	        printf("THUMB DOWN !\n");
-#endif
-	        }
-	    }
-	else {
-	    x = LOWORD(lParam);
-#ifdef DEBUG_SCROLL
-	    printf("WM_LBUTTONDOWN x=%d Cur+bottom=%d %d\n",
-	    	 x, lphs->CurPix + rect.bottom, lphs->CurPix + (rect.bottom << 1));
-#endif
-	    if (x < (lphs->CurPix + rect.bottom))
-	        SendMessage(wndPtr->hwndParent, lphs->Direction, 
-	        	SB_PAGEUP, MAKELONG(0, hwnd));
-	    if (x > (lphs->CurPix + (rect.bottom << 1)))
-	        SendMessage(wndPtr->hwndParent, lphs->Direction, 
-	        	SB_PAGEDOWN, MAKELONG(0, hwnd));
-	    if ((x > (lphs->CurPix + rect.bottom)) &&
-		(x < (lphs->CurPix + (rect.bottom << 1)))) {
-	        lphs->ThumbActive = TRUE;
-#ifdef DEBUG_SCROLL
-	        printf("THUMB DOWN !\n");
-#endif
-		}
-	    }
+	SetCapture(hWnd);
+	ScrollBarButtonDown(hWnd, SB_CTL, LOWORD(lParam), HIWORD(lParam));
 	break;
     case WM_LBUTTONUP:
-	lphs = ScrollBarGetStorageHeader(hwnd);
-        lphs->ThumbActive = FALSE;
 	ReleaseCapture();
+	ScrollBarButtonUp(hWnd, SB_CTL, LOWORD(lParam), HIWORD(lParam));
 	break;
 
     case WM_MOUSEMOVE:
-        if ((wParam & MK_LBUTTON) != 0) {
-	    lphs = ScrollBarGetWindowAndStorage(hwnd, &wndPtr);
-	    if (lphs->ThumbActive == 0) break;
-	    GetClientRect(hwnd, &rect);
-	    if (lphs->Direction == WM_VSCROLL)
-		y = HIWORD(lParam) - rect.right - (rect.right >> 1);
-	    else
-		y = LOWORD(lParam) - rect.bottom - (rect.bottom >> 1);
-	    x = (y * (lphs->MaxVal - lphs->MinVal) / 
-	    		lphs->MaxPix) + lphs->MinVal;
-#ifdef DEBUG_SCROLL
-	    printf("Scroll WM_MOUSEMOVE val=%d pix=%d\n", x, y);
-#endif
-            SendMessage(wndPtr->hwndParent, lphs->Direction, 
-            		SB_THUMBTRACK, MAKELONG(x, hwnd));
-	    }
+	ScrollBarMouseMove(hWnd, SB_CTL, wParam, LOWORD(lParam), HIWORD(lParam));
 	break;
     case WM_KEYDOWN:
     case WM_KEYUP:
     case WM_CHAR:
-	lphs = ScrollBarGetWindowAndStorage(hwnd, &wndPtr);
+	lphs = ScrollBarGetWindowAndStorage(hWnd, &wndPtr);
 	return(SendMessage(wndPtr->hwndParent, message, wParam, lParam));
 
-    case WM_SIZE:
-	lphs = ScrollBarGetWindowAndStorage(hwnd, &wndPtr);
-	width  = LOWORD(lParam);
-	height = HIWORD(lParam);
-	if (lphs->Direction == WM_VSCROLL) {
-	    MoveWindow(lphs->hWndUp, 0, 0, width, width, TRUE);
-	    MoveWindow(lphs->hWndDown, 0, height - width, width, width, TRUE);
-	    }
-	else {
-	    MoveWindow(lphs->hWndUp, 0, 0, height, height, TRUE);
-	    MoveWindow(lphs->hWndDown, width - height, 0, height, height, TRUE);
-	    }
-	break;
-    case WM_DRAWITEM:
+    case WM_TIMER:
 #ifdef DEBUG_SCROLL
-	    printf("Scroll WM_DRAWITEM w=%04X l=%08X\n", wParam, lParam);
+        printf("ScrollBar WM_TIMER wParam=%X lParam=%lX !\n", wParam, lParam);
 #endif
-        lpdis = (LPDRAWITEMSTRUCT)lParam;
-	if (lpdis->CtlType == ODT_BUTTON && lpdis->itemAction == ODA_DRAWENTIRE) {
-	    hMemDC = CreateCompatibleDC(lpdis->hDC);
-	    if (lpdis->CtlID == 1) {
-		GetObject(hUpArrow, sizeof(BITMAP), (LPSTR)&bm);
-		SelectObject(hMemDC, hUpArrow);
-/*		BitBlt(lpdis->hDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY); */
-		StretchBlt(lpdis->hDC, 0, 0, lpdis->rcItem.right, lpdis->rcItem.right,
-			hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
-		}
-	    if (lpdis->CtlID == 2) {
-		GetObject(hDnArrow, sizeof(BITMAP), (LPSTR)&bm);
-		SelectObject(hMemDC, hDnArrow);
-		BitBlt(lpdis->hDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-		}
-	    if (lpdis->CtlID == 3) {
-		GetObject(hLfArrow, sizeof(BITMAP), (LPSTR)&bm);
-		SelectObject(hMemDC, hLfArrow);
-		BitBlt(lpdis->hDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-		}
-	    if (lpdis->CtlID == 4) {
-		GetObject(hRgArrow, sizeof(BITMAP), (LPSTR)&bm);
-		SelectObject(hMemDC, hRgArrow);
-		BitBlt(lpdis->hDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-		}
-	    DeleteDC(hMemDC);
+	lphs = ScrollBarGetWindowAndStorage(hWnd, &wndPtr);
+	KillTimer(hWnd, wParam);
+	switch(lphs->ButtonDown) {
+	    case 0:
+		lphs->TimerPending = FALSE;
+		return 0;
+	    case 1:
+	    case 3:
+		SendMessage(wndPtr->hwndParent, lphs->Direction, 
+			SB_LINEUP, MAKELONG(0, hWnd));
+		break;
+	    case 2:
+	    case 4:
+		SendMessage(wndPtr->hwndParent, lphs->Direction, 
+			SB_LINEDOWN, MAKELONG(0, hWnd));
+		break;
+	    case 5:
+		SendMessage(wndPtr->hwndParent, lphs->Direction, 
+			SB_PAGEUP, MAKELONG(0, hWnd));
+		break;
+	    case 6:
+		SendMessage(wndPtr->hwndParent, lphs->Direction, 
+			SB_PAGEDOWN, MAKELONG(0, hWnd));
+		break;
 	    }
-	if (lpdis->CtlType == ODT_BUTTON && lpdis->itemAction == ODA_SELECT) {
-	    hMemDC = CreateCompatibleDC(lpdis->hDC);
-	    if (lpdis->CtlID == 1) {
-		GetObject(hUpArrowD, sizeof(BITMAP), (LPSTR)&bm);
-		SelectObject(hMemDC, hUpArrowD);
-		BitBlt(lpdis->hDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-		}
-	    if (lpdis->CtlID == 2) {
-		GetObject(hDnArrowD, sizeof(BITMAP), (LPSTR)&bm);
-		SelectObject(hMemDC, hDnArrowD);
-		BitBlt(lpdis->hDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-		}
-	    if (lpdis->CtlID == 3) {
-		GetObject(hLfArrowD, sizeof(BITMAP), (LPSTR)&bm);
-		SelectObject(hMemDC, hLfArrowD);
-		BitBlt(lpdis->hDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-		}
-	    if (lpdis->CtlID == 4) {
-		GetObject(hRgArrowD, sizeof(BITMAP), (LPSTR)&bm);
-		SelectObject(hMemDC, hRgArrowD);
-		BitBlt(lpdis->hDC, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-		}
-	    DeleteDC(hMemDC);
-	    }
-	break;
+	SetTimer(hWnd, 1, 100, NULL);
+	return 0;
+
     case WM_PAINT:
-	StdDrawScrollBar(hwnd);
+	hDC = BeginPaint(hWnd, &ps);
+	lphs = ScrollBarGetStorageHeader(hWnd);
+	if (lphs != NULL) {
+	    GetClientRect(hWnd, &rect);
+	    StdDrawScrollBar(hWnd, hDC, SB_CTL, &rect, lphs);
+	    }
+	EndPaint(hWnd, &ps);
 	break;
     default:
-	return DefWindowProc( hwnd, message, wParam, lParam );
+	return DefWindowProc( hWnd, message, wParam, lParam );
     }
 return(0);
 }
 
 
 
-LPHEADSCROLL ScrollBarGetWindowAndStorage(HWND hwnd, WND **wndPtr)
+void ScrollBarButtonDown(HWND hWnd, int nBar, int x, int y)
+{
+    LPHEADSCROLL lphs;
+    HWND	hWndParent;
+    RECT	rect, rect2;
+    int		width, height;
+    LONG	dwOwner;
+    lphs = GetScrollObjectHandle(hWnd, nBar);
+	    printf("ScrollBarButtonDown // x=%d y=%d\n", x, y);
+#ifdef DEBUG_SCROLL
+	    printf("ScrollBarButtonDown // x=%d y=%d\n", x, y);
+#endif
+    if (nBar == SB_CTL) {
+	hWndParent = GetParent(hWnd);
+	dwOwner = MAKELONG(0, lphs->hWndOwner);
+	}
+    else {
+	hWndParent = hWnd;
+	dwOwner = 0L;
+	}
+/*
+    SetFocus(lphs->hWndOwner);
+*/
+    if (nBar != SB_CTL) {
+	GetWindowRect(lphs->hWndOwner, &rect);
+	x -= rect.left;
+	y -= rect.top;
+	}
+    CopyRect(&rect, &lphs->rect);
+    printf("ScrollDown / x=%d y=%d left=%d top=%d right=%d bottom=%d \n",
+    	x, y, rect.left, rect.top, rect.right, rect.bottom);
+    if (lphs->Direction == WM_VSCROLL) {
+	y -= rect.top;
+	width = rect.right - rect.left;
+	if (y < (lphs->CurPix + width)) {
+	    if (y < width) {
+		lphs->ButtonDown = 1;
+		CopyRect(&rect2, &rect);
+		rect2.bottom = rect2.top + width;
+		InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
+	    printf("ScrollBarButtonDown // SB_LINEUP \n");
+	        SendMessage(hWndParent, lphs->Direction, 
+				SB_LINEUP, dwOwner);
+		}
+	    else {
+		lphs->ButtonDown = 5;
+	    printf("ScrollBarButtonDown // SB_PAGEUP \n");
+		SendMessage(hWndParent, lphs->Direction, 
+				SB_PAGEUP, dwOwner);
+		}
+	    }
+	if (y > (lphs->CurPix + (width << 1))) {
+	    if (y > (rect.bottom - width)) {
+		lphs->ButtonDown = 2;
+		CopyRect(&rect2, &rect);
+		rect2.top = rect2.bottom - width;
+		InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
+	    printf("ScrollBarButtonDown // SB_LINEDOWN \n");
+	        SendMessage(hWndParent, lphs->Direction, 
+				SB_LINEDOWN, dwOwner);
+		}
+	    else {
+		lphs->ButtonDown = 6;
+	    printf("ScrollBarButtonDown // SB_PAGEDOWN \n");
+		SendMessage(hWndParent, lphs->Direction, 
+				SB_PAGEDOWN, dwOwner);
+		}
+	    }
+	if ((y > (lphs->CurPix + width)) &&
+	    (y < (lphs->CurPix + (width << 1)))) {
+	    lphs->ThumbActive = TRUE;
+#ifdef DEBUG_SCROLL
+	    printf("THUMB DOWN !\n");
+#endif
+	    }
+	}
+    else {
+	x -= rect.left;
+	height = rect.bottom - rect.top;
+	if (x < (lphs->CurPix + height)) {
+	    if (x < height) {
+		lphs->ButtonDown = 3;
+		CopyRect(&rect2, &rect);
+		rect2.right = rect2.left + height;
+		InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
+	        SendMessage(hWndParent, lphs->Direction, 
+				SB_LINEUP, dwOwner);
+		}
+	    else {
+		lphs->ButtonDown = 5;
+		SendMessage(hWndParent, lphs->Direction, 
+				SB_PAGEUP, dwOwner);
+		}
+	    }
+	if (x > (lphs->CurPix + (height << 1))) {
+	    if (x > (rect.right - rect.left - height)) {
+		lphs->ButtonDown = 4;
+		CopyRect(&rect2, &rect);
+		rect2.left = rect2.right - height;
+		InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
+	        SendMessage(hWndParent, lphs->Direction, 
+				SB_LINEDOWN, dwOwner);
+		}
+	    else {
+		lphs->ButtonDown = 6;
+		SendMessage(hWndParent, lphs->Direction, 
+				SB_PAGEDOWN, dwOwner);
+		}
+	    }
+	if ((x > (lphs->CurPix + height)) &&
+	    (x < (lphs->CurPix + (height << 1)))) {
+	    lphs->ThumbActive = TRUE;
+#ifdef DEBUG_SCROLL
+	    printf("THUMB DOWN !\n");
+#endif
+	    }
+	}
+    if (lphs->ButtonDown != 0) {
+	UpdateWindow(lphs->hWndOwner);
+	if (!lphs->TimerPending && nBar == SB_CTL) {
+	    lphs->TimerPending = TRUE;
+	    SetTimer(lphs->hWndOwner, 1, 500, NULL);
+	    }
+	}
+}
+
+
+void ScrollBarButtonUp(HWND hWnd, int nBar, int x, int y)
+{
+    LPHEADSCROLL lphs;
+    RECT	rect, rect2;
+    printf("ScrollBarButtonUp // x=%d y=%d\n", x, y); 
+#ifdef DEBUG_SCROLL
+    printf("ScrollBarButtonUp // x=%d y=%d\n", x, y); 
+#endif
+    lphs = GetScrollObjectHandle(hWnd, nBar);
+    lphs->ThumbActive = FALSE;
+    if (lphs->ButtonDown != 0) {
+	lphs->ButtonDown = 0;
+	GetClientRect(lphs->hWndOwner, &rect);
+	InvalidateRect(lphs->hWndOwner, &rect, TRUE);
+	UpdateWindow(lphs->hWndOwner);
+	}
+}
+
+
+void ScrollBarMouseMove(HWND hWnd, int nBar, WORD wParam, int x, int y)
+{
+    LPHEADSCROLL lphs;
+    HWND	hWndParent;
+    HWND	hWndOwner;
+    LONG	dwOwner;
+    if ((wParam & MK_LBUTTON) == 0) return;
+#ifdef DEBUG_SCROLL
+    printf("ScrollBarButtonMove // w=%04X x=%d y=%d \n", wParam, x, y);
+#endif
+    lphs = GetScrollObjectHandle(hWnd, nBar);
+    if (lphs->ThumbActive == 0) return;
+    if (nBar == SB_CTL) {
+	hWndParent = GetParent(hWnd);
+	hWndOwner = lphs->hWndOwner;
+	}
+    else {
+	hWndParent = hWnd;
+	hWndOwner = 0;
+	}
+    if (lphs->Direction == WM_VSCROLL) {
+	int butsiz = lphs->rect.right - lphs->rect.left;
+	y = y - butsiz - (butsiz >> 1);
+	}
+    else {
+	int butsiz = lphs->rect.bottom - lphs->rect.top;
+	y = x - butsiz - (butsiz >> 1);
+	}
+    x = (y * (lphs->MaxVal - lphs->MinVal) / 
+		lphs->MaxPix) + lphs->MinVal;
+#ifdef DEBUG_SCROLL
+    printf("Scroll WM_MOUSEMOVE val=%d pix=%d\n", x, y);
+#endif
+    SendMessage(hWndParent, lphs->Direction, 
+	SB_THUMBTRACK, MAKELONG(x, hWndOwner));
+}
+
+
+LPHEADSCROLL ScrollBarGetWindowAndStorage(HWND hWnd, WND **wndPtr)
 {
     WND  *Ptr;
     LPHEADSCROLL lphs;
-    *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
+    *(wndPtr) = Ptr = WIN_FindWndPtr(hWnd);
     if (Ptr == 0) {
     	printf("Bad Window handle on ScrollBar !\n");
     	return 0;
@@ -276,11 +356,11 @@
 }
 
 
-LPHEADSCROLL ScrollBarGetStorageHeader(HWND hwnd)
+LPHEADSCROLL ScrollBarGetStorageHeader(HWND hWnd)
 {
     WND  *wndPtr;
     LPHEADSCROLL lphs;
-    wndPtr = WIN_FindWndPtr(hwnd);
+    wndPtr = WIN_FindWndPtr(hWnd);
     if (wndPtr == 0) {
     	printf("Bad Window handle on ScrollBar !\n");
     	return 0;
@@ -290,106 +370,138 @@
 }
 
 
-void StdDrawScrollBar(HWND hwnd)
+void StdDrawScrollBar(HWND hWnd, HDC hDC, int nBar, LPRECT lprect, LPHEADSCROLL lphs)
 {
-    LPHEADSCROLL lphs;
-    PAINTSTRUCT ps;
-    HBRUSH hBrush;
-    HDC hdc;
-    RECT rect;
-    UINT  i, w, h, siz;
+    HWND	hWndParent;
+    HBRUSH 	hBrush;
+    HDC 	hMemDC;
+    BITMAP	bm;
+    RECT 	rect;
+    UINT  	i, w, h, siz;
     char	C[128];
-    hdc = BeginPaint( hwnd, &ps );
-    if (!IsWindowVisible(hwnd)) {
-	EndPaint( hwnd, &ps );
-	return;
-	}
-    hBrush = SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WORD)hdc,
-			MAKELONG(hwnd, CTLCOLOR_SCROLLBAR));
+    if (lphs == NULL) return;
+#ifdef DEBUG_SCROLL
+    if (lphs->Direction == WM_VSCROLL)
+        printf("StdDrawScrollBar Vertical left=%d top=%d right=%d bottom=%d !\n", 
+        	lprect->left, lprect->top, lprect->right, lprect->bottom);
+    else
+        printf("StdDrawScrollBar Horizontal left=%d top=%d right=%d bottom=%d !\n", 
+        	lprect->left, lprect->top, lprect->right, lprect->bottom);
+#endif
+    if (nBar == SB_CTL)
+	hWndParent = GetParent(hWnd);
+    else
+	hWndParent = lphs->hWndOwner;
+    hBrush = SendMessage(hWndParent, WM_CTLCOLOR, (WORD)hDC,
+			MAKELONG(hWnd, CTLCOLOR_SCROLLBAR));
     if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(LTGRAY_BRUSH);
-    lphs = ScrollBarGetStorageHeader(hwnd);
-    if (lphs == NULL) goto EndOfPaint;
-    GetClientRect(hwnd, &rect);
+    CopyRect(&lphs->rect, lprect);
+    CopyRect(&rect, lprect);
     w = rect.right - rect.left;
     h = rect.bottom - rect.top;
+    hMemDC = CreateCompatibleDC(hDC);
     if (lphs->Direction == WM_VSCROLL) {
+	GetObject(hUpArrow, sizeof(BITMAP), (LPSTR)&bm);
+	if (lphs->ButtonDown == 1)
+	    SelectObject(hMemDC, hUpArrowD);
+	else
+	    SelectObject(hMemDC, hUpArrow);
+	BitBlt(hDC, rect.left, rect.top, 
+		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+/*
+	StretchBlt(hDC, 0, 0, lpdis->rcItem.right, lpdis->rcItem.right,
+			hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
+*/
+	GetObject(hDnArrow, sizeof(BITMAP), (LPSTR)&bm);
+	if (lphs->ButtonDown == 2)
+	    SelectObject(hMemDC, hDnArrowD);
+	else
+	    SelectObject(hMemDC, hDnArrow);
+	BitBlt(hDC, rect.left, rect.bottom - bm.bmHeight, 
+		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
 	rect.top += w;
 	rect.bottom -= w;
 	}
     else {
+	GetObject(hLfArrow, sizeof(BITMAP), (LPSTR)&bm);
+	if (lphs->ButtonDown == 3)
+	    SelectObject(hMemDC, hLfArrowD);
+	else
+	    SelectObject(hMemDC, hLfArrow);
+	BitBlt(hDC, rect.left, rect.top, 
+		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+	GetObject(hRgArrow, sizeof(BITMAP), (LPSTR)&bm);
+	if (lphs->ButtonDown == 4)
+	    SelectObject(hMemDC, hRgArrowD);
+	else
+	    SelectObject(hMemDC, hRgArrow);
+	BitBlt(hDC, rect.right - bm.bmWidth, rect.top, 
+		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
 	rect.left += h;
 	rect.right -= h;
 	}
-    FillRect(hdc, &rect, hBrush);
+    DeleteDC(hMemDC);
+    FillRect(hDC, &rect, hBrush);
     if (lphs->Direction == WM_VSCROLL)
-	SetRect(&rect, 0, lphs->CurPix + w, w, lphs->CurPix + (w << 1));
+	SetRect(&rect, rect.left, rect.top + lphs->CurPix, 
+		rect.left + w, rect.top + lphs->CurPix + w);
     else
-	SetRect(&rect, lphs->CurPix + h, 0, lphs->CurPix + (h << 1), h);
-    FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH));
+	SetRect(&rect, rect.left + lphs->CurPix, rect.top, 
+		rect.left + lphs->CurPix + h, rect.top + h);
+/*
+    if (lphs->Direction == WM_VSCROLL)
+	SetRect(&rect, rect.left, rect.top + lphs->CurPix + w, 
+		rect.left + w, rect.top + lphs->CurPix + (w << 1));
+    else
+	SetRect(&rect, rect.left + lphs->CurPix + h, rect.top, 
+		rect.left + lphs->CurPix + (h << 1), rect.top + h);
+*/
+    FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
     InflateRect(&rect, -1, -1);
-    FillRect(hdc, &rect, GetStockObject(LTGRAY_BRUSH));
-    DrawReliefRect(hdc, rect, 2, 0);
+    FillRect(hDC, &rect, GetStockObject(LTGRAY_BRUSH));
+    DrawReliefRect(hDC, rect, 2, 0);
     InflateRect(&rect, -3, -3);
-    DrawReliefRect(hdc, rect, 1, 1);
-    if (!lphs->ThumbActive) {
-	InvalidateRect(lphs->hWndUp, NULL, TRUE);
-	UpdateWindow(lphs->hWndUp);
-	InvalidateRect(lphs->hWndDown, NULL, TRUE);
-	UpdateWindow(lphs->hWndDown);
-	}
-EndOfPaint:
-    EndPaint( hwnd, &ps );
+    DrawReliefRect(hDC, rect, 1, 1);
 }
 
 
 
-int CreateScrollBarStruct(HWND hwnd)
+int CreateScrollBarStruct(HWND hWnd)
 {
     RECT	rect;
     int		width, height;
     WND  *wndPtr;
     LPHEADSCROLL lphs;
-    wndPtr = WIN_FindWndPtr(hwnd);
+    wndPtr = WIN_FindWndPtr(hWnd);
     lphs = (LPHEADSCROLL)malloc(sizeof(HEADSCROLL));
     if (lphs == 0) {
     	printf("Bad Memory Alloc on ScrollBar !\n");
     	return 0;
     	}
-
 #ifdef DEBUG_SCROLL
         printf("CreateScrollBarStruct %lX !\n", lphs);
 #endif
     *((LPHEADSCROLL *)&wndPtr->wExtra[1]) = lphs;
+    lphs->hWndOwner = hWnd;
     lphs->ThumbActive = FALSE;
+    lphs->TimerPending = FALSE;
+    lphs->ButtonDown = 0;
     lphs->MinVal = 0;
     lphs->MaxVal = 100;
     lphs->CurVal = 0;
     lphs->CurPix = 0;
     width = wndPtr->rectClient.right - wndPtr->rectClient.left;
     height = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+    CopyRect(&lphs->rect, &wndPtr->rectClient);
     if (width <= height)
 	{
 	lphs->MaxPix = height - 3 * width;
 	lphs->Direction = WM_VSCROLL;
-	lphs->hWndUp = CreateWindow("BUTTON", "", 
-        	WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
-        	0, 0, width, width, hwnd, 1, wndPtr->hInstance, 0L);
-	lphs->hWndDown = CreateWindow("BUTTON", "", 
-        	WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
-        	0, height - width, width, width, hwnd, 2,
-        	wndPtr->hInstance, 0L);
 	}
     else
 	{
 	lphs->MaxPix = width - 3 * height;
 	lphs->Direction = WM_HSCROLL;
-	lphs->hWndUp = CreateWindow("BUTTON", "", 
-        	WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
-        	0, 0, height, height, hwnd, 3, wndPtr->hInstance, 0L);
-	lphs->hWndDown = CreateWindow("BUTTON", "", 
-        	WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
-        	width - height, 0, height, height, hwnd, 4,
-        	wndPtr->hInstance, 0L);
 	}
     if (lphs->MaxPix < 1)  lphs->MaxPix = 1;
     if (wndPtr->hCursor == (HCURSOR)NULL)
@@ -398,31 +510,90 @@
 }
 
 
+
+LPHEADSCROLL AllocScrollBar(DWORD dwStyle, int width, int height)
+{
+    LPHEADSCROLL lphs;
+    lphs = (LPHEADSCROLL)malloc(sizeof(HEADSCROLL));
+    if (lphs == 0) {
+    	printf("Bad Memory Alloc on ScrollBar !\n");
+    	return NULL;
+    	}
+    lphs->ThumbActive = FALSE;
+    lphs->TimerPending = FALSE;
+    lphs->ButtonDown = 0;
+    lphs->MinVal = 0;
+    lphs->MaxVal = 100;
+    lphs->CurVal = 0;
+    lphs->CurPix = 0;
+    if (dwStyle & WS_VSCROLL) {
+	lphs->MaxPix = height - 3 * width;
+	lphs->Direction = WM_VSCROLL;
+	}
+    else {
+	lphs->MaxPix = width - 3 * height;
+	lphs->Direction = WM_HSCROLL;
+	}
+    if (lphs->MaxPix < 1)  lphs->MaxPix = 1;
+    return lphs;
+}
+
+
+void NC_CreateScrollBars(HWND hWnd)
+{
+    RECT	rect;
+    int		width, height;
+    WND  	*wndPtr;
+    LPHEADSCROLL lphs;
+    wndPtr = WIN_FindWndPtr(hWnd);
+    width = wndPtr->rectClient.right - wndPtr->rectClient.left;
+    height = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+    if (wndPtr->dwStyle & WS_VSCROLL) {
+	if (wndPtr->dwStyle & WS_HSCROLL) height -= SYSMETRICS_CYHSCROLL;
+	lphs = AllocScrollBar(WS_VSCROLL, SYSMETRICS_CXVSCROLL, height);
+#ifdef DEBUG_SCROLL
+        printf("NC_CreateScrollBars Vertical %lX !\n", lphs);
+#endif
+	lphs->hWndOwner = hWnd;
+	wndPtr->VScroll = lphs;
+	}
+    if (wndPtr->dwStyle & WS_HSCROLL) {
+	if (wndPtr->dwStyle & WS_VSCROLL) width -= SYSMETRICS_CYVSCROLL;
+	lphs = AllocScrollBar(WS_HSCROLL, width, SYSMETRICS_CYHSCROLL);
+#ifdef DEBUG_SCROLL
+        printf("NC_CreateScrollBars Horizontal %lX !\n", lphs);
+#endif
+	lphs->hWndOwner = hWnd;
+	wndPtr->HScroll = lphs;
+	}
+}
+
+
 /*************************************************************************
- *			GetScrollWindowHandle
+ *			GetScrollObjectHandle
  */
-HWND GetScrollWindowHandle(HWND hWnd, int nBar)
+LPHEADSCROLL GetScrollObjectHandle(HWND hWnd, int nBar)
 {
     WND *wndPtr;
+    LPHEADSCROLL lphs;
     if (nBar != SB_CTL) {
-    wndPtr = WIN_FindWndPtr(hWnd);
-    	if (nBar == SB_VERT) return wndPtr->hWndVScroll;
-    	if (nBar == SB_HORZ) return wndPtr->hWndHScroll;
-    	return (HWND)NULL;
+	wndPtr = WIN_FindWndPtr(hWnd);
+    	if (nBar == SB_VERT) return (LPHEADSCROLL)wndPtr->VScroll;
+    	if (nBar == SB_HORZ) return (LPHEADSCROLL)wndPtr->HScroll;
+    	return NULL;
 	}
-    return hWnd;
+    return ScrollBarGetStorageHeader(hWnd);
 }
 
 
 /*************************************************************************
  *			SetScrollPos [USER.62]
  */
-int SetScrollPos(HWND hwnd, int nBar, int nPos, BOOL bRedraw)
+int SetScrollPos(HWND hWnd, int nBar, int nPos, BOOL bRedraw)
 {
     int nRet;
     LPHEADSCROLL lphs;
-    hwnd = GetScrollWindowHandle(hwnd, nBar);
-    lphs = ScrollBarGetStorageHeader(hwnd);
+    lphs = GetScrollObjectHandle(hWnd, nBar);
     if (lphs == NULL) return 0;
     nRet = lphs->CurVal;
     lphs->CurVal = (short)nPos;
@@ -436,9 +607,9 @@
     printf("SetScrollPos min=%d max=%d\n", 
 	    lphs->MinVal, lphs->MaxVal);
 #endif
-    if ((bRedraw) && (IsWindowVisible(hwnd))) {
-        InvalidateRect(hwnd, NULL, TRUE);
-        UpdateWindow(hwnd);
+    if ((bRedraw) && (IsWindowVisible(lphs->hWndOwner))) {
+        InvalidateRect(lphs->hWndOwner, &lphs->rect, TRUE);
+        UpdateWindow(lphs->hWndOwner);
         }
     return nRet;
 }
@@ -448,11 +619,10 @@
 /*************************************************************************
  *			GetScrollPos [USER.63]
  */
-int GetScrollPos(HWND hwnd, int nBar)
+int GetScrollPos(HWND hWnd, int nBar)
 {
     LPHEADSCROLL lphs;
-    hwnd = GetScrollWindowHandle(hwnd, nBar);
-    lphs = ScrollBarGetStorageHeader(hwnd);
+    lphs = GetScrollObjectHandle(hWnd, nBar);
     if (lphs == NULL) return 0;
     return lphs->CurVal;
 }
@@ -462,11 +632,10 @@
 /*************************************************************************
  *			SetScrollRange [USER.64]
  */
-void SetScrollRange(HWND hwnd, int nBar, int MinPos, int MaxPos, BOOL bRedraw)
+void SetScrollRange(HWND hWnd, int nBar, int MinPos, int MaxPos, BOOL bRedraw)
 {
     LPHEADSCROLL lphs;
-    hwnd = GetScrollWindowHandle(hwnd, nBar);
-    lphs = ScrollBarGetStorageHeader(hwnd);
+    lphs = GetScrollObjectHandle(hWnd, nBar);
     if (lphs == NULL) return;
     lphs->MinVal = (short)MinPos;
     lphs->MaxVal = (short)MaxPos;
@@ -478,9 +647,9 @@
 #ifdef DEBUG_SCROLL
     printf("SetScrollRange min=%d max=%d\n", lphs->MinVal, lphs->MaxVal);
 #endif
-    if ((bRedraw) && (IsWindowVisible(hwnd))) {
-        InvalidateRect(hwnd, NULL, TRUE);
-        UpdateWindow(hwnd);
+    if ((bRedraw) && (IsWindowVisible(lphs->hWndOwner))) {
+        InvalidateRect(lphs->hWndOwner, &lphs->rect, TRUE);
+        UpdateWindow(lphs->hWndOwner);
         }
 }
 
@@ -489,11 +658,10 @@
 /*************************************************************************
  *			GetScrollRange [USER.65]
  */
-void GetScrollRange(HWND hwnd, int nBar, LPINT lpMin, LPINT lpMax)
+void GetScrollRange(HWND hWnd, int nBar, LPINT lpMin, LPINT lpMax)
 {
     LPHEADSCROLL lphs;
-    hwnd = GetScrollWindowHandle(hwnd, nBar);
-    lphs = ScrollBarGetStorageHeader(hwnd);
+    lphs = GetScrollObjectHandle(hWnd, nBar);
     if (lphs == NULL) return;
     *lpMin = lphs->MinVal;
     *lpMax = lphs->MaxVal;
@@ -519,16 +687,20 @@
 	}
     wndPtr = WIN_FindWndPtr(hWnd);
     if ((wBar == SB_VERT) || (wBar == SB_BOTH)) {
+/*
     	if (bFlag)
 	    ShowWindow(wndPtr->hWndVScroll, SW_SHOW);
 	else
 	    ShowWindow(wndPtr->hWndVScroll, SW_HIDE);
+*/
 	}
     if ((wBar == SB_HORZ) || (wBar == SB_BOTH)) {
+/*
     	if (bFlag)
 	    ShowWindow(wndPtr->hWndHScroll, SW_SHOW);
 	else
 	    ShowWindow(wndPtr->hWndHScroll, SW_HIDE);
+*/
 	}
 }
 
diff --git a/controls/static.c b/controls/static.c
index 558110b..655d2fe 100644
--- a/controls/static.c
+++ b/controls/static.c
@@ -149,8 +149,8 @@
     GetClientRect(hwnd, &rc);
 
     textlen = GetWindowTextLength(hwnd);
-    hText = LocalAlloc(LMEM_MOVEABLE, textlen+1);
-    text = LocalLock(hText);
+    hText = USER_HEAP_ALLOC(0, textlen+1);
+    text = USER_HEAP_ADDR(hText);
     GetWindowText(hwnd, text, textlen+1);
 
     switch (style & 0x0000000F)
@@ -185,8 +185,7 @@
     FillRect(hdc, &rc, hBrush);
     DrawText(hdc, text, textlen, &rc, wFormat);
 
-    LocalUnlock(hText);
-    LocalFree(hText);
+    USER_HEAP_FREE(hText);
     GlobalUnlock(hwnd);
     EndPaint(hwnd, &ps);
 }
diff --git a/controls/widgets.c b/controls/widgets.c
index 02d10b4..37b74f1 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -7,7 +7,6 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include "windows.h"
-#include "win.h"
 #include "dialog.h"
 
 
@@ -17,7 +16,6 @@
 LONG ListBoxWndProc  ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
 LONG ComboBoxWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
 LONG PopupMenuWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG CaptionBarWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
 
 
 static WNDCLASS WIDGETS_BuiltinClasses[] =
@@ -34,8 +32,6 @@
       0, 0, 0, 0, NULL, "COMBOBOX" },
     { CS_GLOBALCLASS, (LONG(*)())PopupMenuWndProc, 0, 8,
       0, 0, 0, 0, NULL, "POPUPMENU" },
-    { CS_GLOBALCLASS, (LONG(*)())CaptionBarWndProc, 0, 8,
-      0, 0, 0, 0, NULL, "CAPTION" },
     { CS_GLOBALCLASS, (LONG(*)())DefDlgProc, 0, DLGWINDOWEXTRA,
       0, 0, 0, 0, NULL, DIALOG_CLASS_NAME }
 };
diff --git a/debugger/Makefile b/debugger/Makefile
index 78954c0..6a27140 100644
--- a/debugger/Makefile
+++ b/debugger/Makefile
@@ -1,4 +1,4 @@
-CFLAGS=-g -I../include -DUSE_READLINE
+CFLAGS=-g -I../include -DUSE_READLINE ${COPTS}
 LIBS= readline/libedit.a
 OBJS=dbg.tab.o hash.o lex.yy.o info.o i386-pinsn.o
 #YACC=bison -v -d
diff --git a/debugger/dtest.c b/debugger/dtest.c
index bbad04e..3872cbf 100644
--- a/debugger/dtest.c
+++ b/debugger/dtest.c
@@ -58,7 +58,7 @@
 	segv_act.sa_handler = (__sighandler_t) win_fault;
 	sigaction(SIGSEGV, &segv_act, NULL);
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
         sigset_t sig_mask;
         
         sigemptyset(&sig_mask);
diff --git a/debugger/regpos.h b/debugger/regpos.h
index d3c3a4f..01d2e00 100644
--- a/debugger/regpos.h
+++ b/debugger/regpos.h
@@ -25,7 +25,8 @@
 #define  RN_CR2			21
 #endif
 
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#define  RN_OLDMASK		1
 /* Register numbers */
 #define  RN_ESP			2
 #define  RN_EBP			3
@@ -50,6 +51,8 @@
 #ifdef linux
 #define  SC_GS			regval[RN_GS]
 #define  SC_FS			regval[RN_FS]
+#define  I387			regval[RN_I387]
+#define  CR2			regval[RN_CR2]
 #endif
 #define  SC_ES			regval[RN_ES]
 #define  SC_DS			regval[RN_DS]
@@ -68,7 +71,4 @@
 #define  SC_EFLAGS		regval[RN_EFLAGS]
 #define  ESP_AT_SIGNAL		regval[RN_ESP_AT_SIGNAL]
 #define  SC_SS			regval[RN_SS]
-#define  I387			regval[RN_I387]
 #define  OLDMASK		regval[RN_OLDMASK]
-#define  CR2			regval[RN_CR2]
-
diff --git a/if1632/Imakefile b/if1632/Imakefile
index 8c11afd..4c36d99 100644
--- a/if1632/Imakefile
+++ b/if1632/Imakefile
@@ -7,6 +7,11 @@
 	callback.c \
 	relay.c
 
+/*
+ * Hack alert. There appear to be no object files, 'cause a very
+ * nasty rule below links *.o together, which is a generally bad idea,
+ * but I can't see how else to do it.
+ */
 OBJS = \
 	call.o \
 	callback.o \
@@ -25,9 +30,11 @@
 MakeDllFromSpec(win87em,$(TOP)/$(MODULE))
 
 /*
- * Yes I know *.o is not veru clever, but can you do it cleaner ?
+ * Yes I know *.o is not very clever, but can you do it cleaner ?
  */
-WineRelocatableTarget($(TOP)/$(MODULE),*.o,$(OBJS))
+WineRelocatableTarget($(TOP)/$(MODULE),*.o,)
+
+$(TOP)/$(MODULE).o: $(OBJS)
 
 clean::
 	$(RM) dll*
diff --git a/if1632/Makefile b/if1632/Makefile
index 0746063..3607324 100644
--- a/if1632/Makefile
+++ b/if1632/Makefile
@@ -10,6 +10,10 @@
 
 OBJS=$(MUST_BE_LINKED_FIRST) callback.o relay.o
 
+# Uncomment the following 2 lines for use with FreeBSD
+# %.o: %.S
+#	$(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) $(COPTS) -c -o $@ $<
+
 default: if1632.o
 
 if1632.o: $(OBJS)
diff --git a/if1632/call.S b/if1632/call.S
index c8ac030..8853496 100644
--- a/if1632/call.S
+++ b/if1632/call.S
@@ -4,7 +4,7 @@
 #ifdef linux
 #define UDATASEL 0x2b
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #define UDATASEL 0x27
 #endif
 	.data
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 86a1508..15021aa 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -78,6 +78,7 @@
 134 pascal GetWindowsDirectory(ptr word) GetWindowsDirectory(1 2)
 135 pascal GetSystemDirectory(ptr word) GetSystemDirectory(1 2)
 136 pascal GetDriveType(byte) GetWindowsDirectory(1)
+152 return GetNumTasks 0 1
 154 return GlobalNotify 4 0
 163 pascal GlobalLRUOldest(word) ReturnArg(1)
 164 pascal GlobalLRUNewest(word) ReturnArg(1)
diff --git a/if1632/relay.c b/if1632/relay.c
index fba4f52..52f7d42 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -19,7 +19,7 @@
 #include "prototypes.h"
 #include "dlls.h"
 
-/* #define DEBUG_RELAY */
+/* #define DEBUG_RELAY /* */
 
 #define N_BUILTINS	8
 
diff --git a/if1632/user.spec b/if1632/user.spec
index ebd04ea..5303a75 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -46,10 +46,14 @@
 49  pascal IsWindowVisible(word) IsWindowVisible(1)
 50  pascal FindWindow(ptr ptr) FindWindow(1 2)
 53  pascal DestroyWindow(word) DestroyWindow(1)
+54  pascal EnumWindows(ptr long) EnumWindows(1 2)
+55  pascal EnumChildWindows(word ptr long) EnumChildWindows(1 2 3)
 56  pascal MoveWindow(word word word word word word) 
            MoveWindow(1 2 3 4 5 6)
 57  pascal RegisterClass(ptr) RegisterClass(1)
 58  pascal GetClassName(word ptr word) GetClassName(1 2 3)
+59  pascal SetActiveWindow(word) SetActiveWindow(1)
+60  pascal GetActiveWindow() GetActiveWindow()
 61  pascal ScrollWindow(word s_word s_word ptr ptr) ScrollWindow(1 2 3 4 5)
 62  pascal SetScrollPos(word word word word) SetScrollPos(1 2 3 4)
 63  pascal GetScrollPos(word word) GetScrollPos(1 2)
@@ -122,8 +126,10 @@
 152 pascal DestroyMenu(word) DestroyMenu(1)
 154 pascal CheckMenuItem(word word word) CheckMenuItem(1 2 3)
 155 pascal EnableMenuItem(word word word) EnableMenuItem(1 2 3)
+156 pascal GetSystemMenu(word word) GetSystemMenu(1 2)
 157 pascal GetMenu(word) GetMenu(1)
 158 pascal SetMenu(word word) SetMenu(1 2)
+159 pascal GetSubMenu(word word) GetSubMenu(1 2)
 160 pascal DrawMenuBar(word) DrawMenuBar(1)
 163 pascal CreateCaret(word word word word) CreateCaret(1 2 3 4)
 164 pascal DestroyCaret() DestroyCaret()
@@ -138,6 +144,7 @@
 175 pascal LoadBitmap(word ptr) LoadBitmap(1 2)
 176 pascal LoadString(word word ptr s_word) LoadString(1 2 3 4)
 177 pascal LoadAccelerators(word ptr) LoadAccelerators(1 2)
+178 pascal TranslateAccelerator(word word ptr) TranslateAccelerator(1 2 3)
 179 pascal GetSystemMetrics(word) GetSystemMetrics(1)
 180 pascal GetSysColor(word) GetSysColor(1)
 181 pascal SetSysColors(word ptr ptr) SetSysColors(1 2 3)
diff --git a/include/accel.h b/include/accel.h
new file mode 100644
index 0000000..6ea4084d
--- /dev/null
+++ b/include/accel.h
@@ -0,0 +1,22 @@
+/*
+ * structure definitions for ACCELERATORS
+ *
+ * Copyright  Martin Ayotte, 1994
+ *
+ */
+
+typedef struct {
+	WORD		wEvent;
+	WORD		wIDval;
+	BYTE		type;
+	} ACCELENTRY, *LPACCELENTRY;
+
+typedef struct {
+	WORD		wCount;
+	ACCELENTRY 	tbl[1];
+	} ACCELHEADER, *LPACCELHEADER;
+
+#define VIRTKEY_ACCEL	0x01
+#define SHIFT_ACCEL	0x04
+#define CONTROL_ACCEL	0x08
+#define SYSTEM_ACCEL	0x80
diff --git a/include/heap.h b/include/heap.h
index efbcd0d..2b3b157 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -6,6 +6,9 @@
 #ifndef HEAP_H
 #define HEAP_H
 
+/**********************************************************************
+ * LOCAL HEAP STRUCTURES AND FUNCTIONS
+ */
 typedef struct heap_mem_desc_s
 {
     struct heap_mem_desc_s *prev, *next;
@@ -20,7 +23,44 @@
 extern void *HEAP_ReAlloc(MDESC **free_list, void *old_block, 
 			  int new_size, unsigned int flags);
 
+/**********************************************************************
+ * GLOBAL HEAP STRUCTURES AND FUNCTIONS:
+ *
+ * Global memory pool descriptor.  Segments MUST be maintained in segment
+ * ascending order.  If not the reallocation routine will die a horrible
+ * death.
+ *
+ * handle  = 0, this descriptor contains the address of a free pool.
+ *        != 0, this describes an allocated block.
+ *
+ * sequence = 0, this is not a huge block
+ *          > 0, this is a portion of a huge block
+ *          =-1, this is a free segment
+ *
+ * addr	      - address of this memory block.
+ *
+ * length     - used to maintain huge blocks.
+ */
+typedef struct global_mem_desc_s
+{
+    struct global_mem_desc_s *next;
+    struct global_mem_desc_s *prev;
+    unsigned short handle;
+    short sequence;
+    void *addr;
+    int length;
+    int lock_count;
+    void *linear_addr;
+    int linear_key;
+    int linear_count;
+} GDESC;
+
+extern GDESC *GlobalList;
+
 extern void *GlobalQuickAlloc(int size);
 extern unsigned int GlobalHandleFromPointer(void *block);
+extern GDESC *GlobalGetGDesc(unsigned int block);
+extern void *GlobalLinearLock(unsigned int block);
+extern unsigned int GlobalLinearUnlock(unsigned int block);
 
 #endif /* HEAP_H */
diff --git a/include/menu.h b/include/menu.h
index fa74240..34cdb2c 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -54,6 +54,7 @@
     WORD	FocusedItem;
     WORD	MouseFlags;
     WORD	BarFlags;
+    BOOL	SysFlag;
     WORD	Width;
     WORD	Height;
 } POPUPMENU, *LPPOPUPMENU;
diff --git a/include/message.h b/include/message.h
index d64b4fc..fc3054d 100644
--- a/include/message.h
+++ b/include/message.h
@@ -51,5 +51,6 @@
 extern BOOL MSG_CreateSysMsgQueue( int size );
 extern void hardware_event(HWND hwnd, WORD message, WORD wParam, LONG lParam,
 			   WORD xPos, WORD yPos, DWORD time, DWORD extraInfo);
+extern BOOL MSG_GetHardwareMessage( LPMSG msg );
 
 #endif  /* MESSAGE_H */
diff --git a/include/prototypes.h b/include/prototypes.h
index 69fc97b..8bd189d 100644
--- a/include/prototypes.h
+++ b/include/prototypes.h
@@ -28,6 +28,10 @@
 
 extern struct segment_descriptor_s *GetNextSegment(unsigned int flags,
 						   unsigned int limit);
+extern struct segment_descriptor_s *CreateNewSegments(int code_flag, 
+						      int read_only, 
+						      int length, 
+						      int n_segments);
 extern struct mz_header_s *CurrentMZHeader;
 extern struct ne_header_s *CurrentNEHeader;
 extern int CurrentNEFile;
diff --git a/include/scroll.h b/include/scroll.h
index 4dd4e7d..2804a46 100644
--- a/include/scroll.h
+++ b/include/scroll.h
@@ -9,12 +9,23 @@
     short	MaxVal;
     short	MaxPix;
     short	CurPix;
+    RECT	rect;
     BOOL	ThumbActive;
+    BOOL	TimerPending;
+    WORD	ButtonDown;
     WORD	Direction;
     DWORD	dwStyle;
-    HWND	hWndUp;
-    HWND	hWndDown;
+    HWND	hWndOwner;
 } HEADSCROLL;
 typedef HEADSCROLL FAR* LPHEADSCROLL;
 
 
+
+void ScrollBarButtonDown(HWND hWnd, int nBar, int x, int y);
+void ScrollBarButtonUp(HWND hWnd, int nBar, int x, int y);
+void ScrollBarMouseMove(HWND hWnd, int nBar, WORD wParam, int x, int y);
+void StdDrawScrollBar(HWND hWnd, HDC hDC, int nBar, LPRECT lprect, LPHEADSCROLL lphs);
+int CreateScrollBarStruct(HWND hWnd);
+void NC_CreateScrollBars(HWND hWnd);
+
+
diff --git a/include/segmem.h b/include/segmem.h
index d4f6fd8..f2bf2d6 100644
--- a/include/segmem.h
+++ b/include/segmem.h
@@ -48,6 +48,8 @@
 #endif
 } SEGDESC;
 
+extern int IPCCopySelector(int i_old, unsigned long new, int swap_type);
+
 /*
  * Additional flags
  */
diff --git a/include/win.h b/include/win.h
index 12800c7..371b036 100644
--- a/include/win.h
+++ b/include/win.h
@@ -38,15 +38,15 @@
     HANDLE       hdce;           /* Window DCE (if CS_OWNDC or CS_CLASSDC) */
     HMENU        hmenuSystem;    /* System menu */
     HCURSOR      hCursor;    	 /* Window Current Cursor */
-    HWND         hWndVScroll;    /* Verti. ScrollBar handle of the window */
-    HWND         hWndHScroll;    /* Horiz. ScrollBar handle of the window */
+    void	 *VScroll;	 /* Vertical ScrollBar Struct Pointer */
+    void	 *HScroll;	 /* Horizontal ScrollBar Struct Pointer */
     WORD         wIDmenu;        /* ID or hmenu (from CreateWindow) */
     HANDLE       hText;          /* Handle of window text */
     WORD         flags;          /* Misc. flags */
     Window       window;         /* X window */
     LPMENUBAR	 menuBarPtr;	 /* Menu bar */
+    HMENU	 hSysMenu;	 /* window's copy of System Menu */
     HWND	 hWndMenuBar;	 /* Menu bar */
-    HWND	 hWndCaption;	 /* Caption bar */
     WORD         wExtra[1];      /* Window extra bytes */
 } WND;
 
diff --git a/include/windows.h b/include/windows.h
index a4064c3..a6f8c98 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -222,6 +222,17 @@
 #define GW_OWNER	4
 #define GW_CHILD	5
 
+  /* WM_GETMINMAXINFO struct */
+typedef struct
+{
+    POINT   ptReserved;
+    POINT   ptMaxSize;
+    POINT   ptMaxPosition;
+    POINT   ptMinTrackSize;
+    POINT   ptMaxTrackSize;
+} MINMAXINFO;
+
+
   /* WM_WINDOWPOSCHANGING/CHANGED struct */
 typedef struct
 {
@@ -249,6 +260,17 @@
 #define WPF_SETMINPOSITION      0x0001
 #define WPF_RESTORETOMAXIMIZED  0x0002
 
+  /* WM_MOUSEACTIVATE return values */
+#define MA_ACTIVATE             1
+#define MA_ACTIVATEANDEAT       2
+#define MA_NOACTIVATE           3
+#define MA_NOACTIVATEANDEAT     4
+
+  /* WM_ACTIVATE wParam values */
+#define WA_INACTIVE             0
+#define WA_ACTIVE               1
+#define WA_CLICKACTIVE          2
+
   /* WM_NCCALCSIZE parameter structure */
 typedef struct
 {
@@ -1271,6 +1293,9 @@
 
 #define WM_PARENTNOTIFY     0x0210
 
+#define WM_ENTERSIZEMOVE    0x0231
+#define WM_EXITSIZEMOVE     0x0232
+
   /* misc messages */
 #define WM_NULL             0x0000
 #define WM_USER             0x0400
@@ -1349,6 +1374,13 @@
 #define TPM_CENTERALIGN 0x0004
 #define TPM_RIGHTALIGN  0x0008
 
+/* Menu messages */
+#define WM_INITMENU         0x0116
+#define WM_INITMENUPOPUP    0x0117
+
+#define WM_MENUSELECT       0x011F
+#define WM_MENUCHAR         0x0120
+
 #define MF_INSERT 0
 #define MF_CHANGE 0x0080
 #define MF_APPEND 0x0100
@@ -2254,7 +2286,7 @@
 Fb(HBRUSH,CreateHatchBrush,short,a,COLORREF,b)
 Fb(HCURSOR,LoadCursor,HANDLE,a,LPSTR,b)
 Fb(HICON,LoadIcon,HANDLE,a,LPSTR,b)
-Fb(HMENU,GetSubMenu,HMENU,a,int,b)
+Fb(HMENU,GetSubMenu,HMENU,a,short,b)
 Fb(HMENU,GetSystemMenu,HWND,a,BOOL,b)
 Fb(HMENU,LoadMenu,HANDLE,a,LPSTR,b)
 Fb(HWND,ChildWindowFromPoint,HWND,a,POINT,b)
diff --git a/include/wine.h b/include/wine.h
index dbc034c..7931c48 100644
--- a/include/wine.h
+++ b/include/wine.h
@@ -57,7 +57,7 @@
 };
 #endif
 
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <signal.h>
 #define sigcontext_struct sigcontext
 #define HZ 100
diff --git a/loader/Imakefile b/loader/Imakefile
index 9c5130a..f831435 100644
--- a/loader/Imakefile
+++ b/loader/Imakefile
@@ -3,6 +3,8 @@
 MODULE = loader
 
 SRCS = \
+	int1a.c \
+	int21.c \
 	dump.c \
 	files.c \
 	ldt.c \
@@ -15,6 +17,8 @@
 	cursor.c
 
 OBJS = \
+	int1a.o \
+	int21.o \
 	dump.o \
 	files.o \
 	ldt.o \
diff --git a/loader/cursor.c b/loader/cursor.c
index 3bf7577..ff8c7bd 100644
--- a/loader/cursor.c
+++ b/loader/cursor.c
@@ -30,6 +30,24 @@
 extern HINSTANCE hSysRes;
 extern Window winHasCursor;
 
+static struct { LPSTR name; HCURSOR cursor; } system_cursor[] =
+{
+    { IDC_ARROW, 0 },
+    { IDC_IBEAM, 0 },
+    { IDC_WAIT, 0 },
+    { IDC_CROSS, 0 },
+    { IDC_UPARROW, 0 },
+    { IDC_SIZE, 0 },
+    { IDC_ICON, 0 },
+    { IDC_SIZENWSE, 0 },
+    { IDC_SIZENESW, 0 },
+    { IDC_SIZEWE, 0 },
+    { IDC_SIZENS, 0 }
+};
+
+#define NB_SYS_CURSORS  (sizeof(system_cursor)/sizeof(system_cursor[0]))
+
+
 /**********************************************************************
  *			LoadCursor [USER.173]
  */
@@ -51,8 +69,22 @@
     printf("LoadCursor: instance = %04x, name = %08x\n",
 	   instance, cursor_name);
 #endif    
+
+    if (!instance)
+    {
+	for (i = 0; i < NB_SYS_CURSORS; i++)
+	    if (system_cursor[i].name == cursor_name)
+	    {
+		hCursor = system_cursor[i].cursor;
+		break;
+	    }
+	if (i == NB_SYS_CURSORS) return 0;
+	if (hCursor) return hCursor;
+    }
     hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L); 
     if (hCursor == (HCURSOR)NULL) return 0;
+    if (!instance) system_cursor[i].cursor = hCursor;
+
 #ifdef DEBUG_CURSOR
     printf("LoadCursor Alloc hCursor=%X\n", hCursor);
 #endif    
@@ -203,9 +235,9 @@
     int i, j;
 #ifdef DEBUG_RESOURCE
     printf("CreateCursor: inst=%04x nXhotspot=%d  nYhotspot=%d nWidth=%d nHeight=%d\n",  
-	nXhotspot, nYhotspot, nWidth, nHeight);
+       instance, nXhotspot, nYhotspot, nWidth, nHeight);
     printf("CreateCursor: inst=%04x lpANDbitPlane=%08X lpXORbitPlane=%08X\n",
-	LPSTR lpANDbitPlane, LPSTR lpXORbitPlane);
+	instance, lpANDbitPlane, lpXORbitPlane);
 #endif    
     if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
     hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L); 
diff --git a/loader/ldt.c b/loader/ldt.c
index 235f1eb..8ac6b1e 100644
--- a/loader/ldt.c
+++ b/loader/ldt.c
@@ -6,7 +6,7 @@
 #include <errno.h>
 
 #include "prototypes.h"
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <machine/segments.h>
 #endif
 
@@ -21,7 +21,7 @@
     unsigned long *lp;
     unsigned long base_addr, limit;
     int type, dpl, i;
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
     struct segment_descriptor *sd;
 #endif
     
@@ -29,7 +29,7 @@
 	exit(1);
     
     lp = (unsigned long *) buffer;
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
     sd = (struct segment_descriptor *) buffer;
 #endif
     
@@ -47,7 +47,7 @@
 	type = (*lp >> 10) & 5;
 	dpl = (*lp >> 13) & 3;
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
         type = sd->sd_type;
         dpl = sd->sd_dpl;
 	sd++;
diff --git a/loader/ldtlib.c b/loader/ldtlib.c
index 3945537..76924fe 100644
--- a/loader/ldtlib.c
+++ b/loader/ldtlib.c
@@ -11,7 +11,7 @@
 
 _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <machine/segments.h>
 
 extern int i386_get_ldt(int, union descriptor *, int);
@@ -43,7 +43,7 @@
 #ifdef linux
     return modify_ldt(0, buffer, 32 * sizeof(struct modify_ldt_ldt_s));
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
     return i386_get_ldt(0, (union descriptor *)buffer, 32);
 #endif
 }
@@ -66,7 +66,7 @@
 
     return modify_ldt(1, &ldt_info, sizeof(ldt_info));
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
     struct segment_descriptor *sd;
     int ret;
     
diff --git a/loader/resource.c b/loader/resource.c
index da059d1..bf2d185 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -14,6 +14,7 @@
 #include "gdi.h"
 #include "wine.h"
 #include "icon.h"
+#include "accel.h"
 
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 
@@ -388,6 +389,7 @@
     DeleteDC(hMemDC);
     DeleteDC(hMemDC2);
     ReleaseDC(GetDesktopWindow(), hdc);
+    GlobalUnlock(hIcon);
     return hIcon;
 }
 
@@ -407,12 +409,97 @@
 
 
 /**********************************************************************
- *					LoadAccelerators
+ *			LoadAccelerators	[USER.177]
  */
-HANDLE
-LoadAccelerators(HANDLE instance, LPSTR lpTableName)
+HANDLE LoadAccelerators(HANDLE instance, LPSTR lpTableName)
 {
-  fprintf(stderr,"LoadAccelerators: (%d),%d\n",instance,lpTableName);
+    HANDLE 	hAccel;
+    HANDLE 	rsc_mem;
+    BYTE 	*lp;
+    ACCELHEADER	*lpAccelTbl;
+    int 	i, image_size;
+#ifdef DEBUG_ACCEL
+    if (((LONG)lpTableName & 0xFFFF0000L) == 0L)
+	printf("LoadAccelerators: instance = %04X, name = %08X\n",
+			instance, lpTableName);
+    else
+	printf("LoadAccelerators: instance = %04X, name = '%s'\n",
+			instance, lpTableName);
+#endif
+    if (instance == (HANDLE)NULL)  instance = hSysRes;
+    rsc_mem = RSC_LoadResource(instance, lpTableName, NE_RSCTYPE_ACCELERATOR, 
+			       &image_size);
+    if (rsc_mem == (HANDLE)NULL) {
+	printf("LoadAccelerators / AccelTable %04X not Found !\n", lpTableName);
+	return 0;
+	}
+    lp = (BYTE *)GlobalLock(rsc_mem);
+    if (lp == NULL) {
+	GlobalFree(rsc_mem);
+	return 0;
+	}
+#ifdef DEBUG_ACCEL
+    printf("LoadAccelerators / image_size=%d\n", image_size);
+#endif
+    hAccel = GlobalAlloc(GMEM_MOVEABLE, 
+    	sizeof(ACCELHEADER) + sizeof(ACCELENTRY) + image_size);
+    lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
+    lpAccelTbl->wCount = 0;
+    for (i = 0; ; i++) {
+	lpAccelTbl->tbl[i].type = *(lp++);
+	lpAccelTbl->tbl[i].wEvent = *((WORD *)lp);
+	lp += 2;
+	lpAccelTbl->tbl[i].wIDval = *((WORD *)lp);
+	lp += 2;
+    	if (lpAccelTbl->tbl[i].wEvent == 0) break;
+#ifdef DEBUG_ACCEL
+	printf("Accelerator #%u / event=%04X id=%04X type=%02X \n", 
+		i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval, 
+		lpAccelTbl->tbl[i].type);
+#endif
+	lpAccelTbl->wCount++;
+ 	}
+    GlobalUnlock(hAccel);
+    GlobalUnlock(rsc_mem);
+    GlobalFree(rsc_mem);
+    return hAccel;
+}
+
+/**********************************************************************
+ *			TranslateAccelerator 	[USER.178]
+ */
+int TranslateAccelerator(HWND hWnd, HANDLE hAccel, LPMSG msg)
+{
+    ACCELHEADER	*lpAccelTbl;
+    int 	i, image_size;
+    if (hAccel == 0 || msg == NULL) return 0;
+    if (msg->message != WM_KEYDOWN &&
+    	msg->message != WM_KEYUP &&
+    	msg->message != WM_CHAR) return 0;
+#ifdef DEBUG_ACCEL
+    printf("TranslateAccelerators hAccel=%04X !\n", hAccel);
+#endif
+    lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
+    for (i = 0; i < lpAccelTbl->wCount; i++) {
+/*	if (lpAccelTbl->tbl[i].type & SHIFT_ACCEL) { */
+/*	if (lpAccelTbl->tbl[i].type & CONTROL_ACCEL) { */
+	if (lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) {
+	    if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
+		msg->message == WM_KEYDOWN) {
+		SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
+		return 1;
+		}
+	    if (msg->message == WM_KEYUP) return 1;
+	    }
+	else {
+	    if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
+		msg->message == WM_CHAR) {
+		SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
+		return 1;
+		}
+	    }
+	}
+    GlobalUnlock(hAccel);
     return 0;
 }
 
@@ -446,12 +533,12 @@
 
     if (((int) resource_name & 0xffff0000) == 0)
     {
-	r->size_shift = FindResourceByNumber(&r->nameinfo, type_name,
+	r->size_shift = FindResourceByNumber(&r->nameinfo, (int)type_name,
 					     (int) resource_name | 0x8000);
     }
     else
     {
-	r->size_shift = FindResourceByName(&r->nameinfo, type_name, 
+	r->size_shift = FindResourceByName(&r->nameinfo, (int)type_name, 
 					   resource_name);
     }
     
@@ -683,14 +770,12 @@
     if (instance == (HANDLE)NULL)  instance = hSysRes;
     if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
 
-printf("before RSC_Load\n");
     rsc_mem = RSC_LoadResource(instance, bmp_name, NE_RSCTYPE_BITMAP, 
 			       &image_size);
     if (rsc_mem == (HANDLE)NULL) {
 	printf("LoadBitmap / BitMap %04X not Found !\n", bmp_name);
 	return 0;
 	}
-printf("before GlobalLock\n");
     lp = (long *) GlobalLock(rsc_mem);
     if (lp == NULL)
     {
diff --git a/loader/selector.c b/loader/selector.c
index 38ad26f..76c66ba 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -14,7 +14,7 @@
 #include <linux/a.out.h>
 #include <linux/ldt.h>
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <sys/mman.h>
 #endif
 #include <errno.h>
@@ -23,13 +23,14 @@
 #include "prototypes.h"
 #include "wine.h"
 
+/* #define DEBUG_SELECTORS /* */
 
 #ifdef linux
 #define DEV_ZERO
 #define UTEXTSEL 0x23
 #endif
 
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <machine/segments.h>
 #define PAGE_SIZE getpagesize()
 #define MODIFY_LDT_CONTENTS_DATA	0
@@ -59,7 +60,7 @@
 extern int Argc;
 
 /**********************************************************************
- *					FindUnusedSelector
+ *					FindUnusedSelectors
  */
 int
 FindUnusedSelectors(int n_selectors)
@@ -87,95 +88,123 @@
     return i - n_selectors + 1;
 }
 
-/**********************************************************************
- *					FindUnusedSelector
- */
-int
-FindUnusedSelector(void)
-{
-    int i;
-    
-    for (i = LastUsedSelector + 1; i != LastUsedSelector; i++)
-    {
-	if (i >= MAX_SELECTORS)
-	    i = FIRST_SELECTOR;
-	
-	if (!SelectorMap[i])
-	    break;
-    }
-    
-    if (i == LastUsedSelector)
-	return 0;
-
-    LastUsedSelector = i;
-    return i;
-}
-
 #ifdef HAVE_IPC
 /**********************************************************************
  *					IPCCopySelector
+ *
+ * Created a shared memory copy of a segment:
+ *
+ *	- at a new selector location (if "new" is a 16-bit value)
+ *	- at an arbitrary memory location (if "new" is a 32-bit value)
  */
 int
-IPCCopySelector(int i_old, int i_new, int swap_type)
+IPCCopySelector(int i_old, unsigned long new, int swap_type)
 {
     SEGDESC *s_new, *s_old;
+    int i_new;
+    void *base_addr;
 
-    s_old = &Segments[i_old];
-    s_new = &Segments[i_new];
+    s_old  = &Segments[i_old];
 
-    SelectorMap[i_new] = i_new;
-    
-    s_new->selector  = (i_new << 3) | 0x0007;
-    s_new->base_addr = (void *) ((long) s_new->selector << 16);
-    s_new->length    = s_old->length;
-    s_new->flags     = s_old->flags;
-    s_new->owner     = s_old->owner;
-    if (swap_type)
+    if (new & 0xffff0000)
     {
-	if (s_old->type == MODIFY_LDT_CONTENTS_DATA)
-	    s_new->type = MODIFY_LDT_CONTENTS_CODE;
-	else
-	    s_new->type = MODIFY_LDT_CONTENTS_DATA;
+	/**************************************************************
+	 * Let's set the address parameter for no segment.
+	 */
+	i_new = -1;
+	s_new = NULL;
+	base_addr = (void *) new;
     }
     else
-	s_new->type      = s_old->type;
-	
+    {
+	/***************************************************************
+	 * We need to fill in the segment descriptor for segment "new".
+	 */
+	i_new = new;
+	s_new = &Segments[i_new];
+
+	SelectorMap[i_new] = i_new;
+    
+	s_new->selector  = (i_new << 3) | 0x0007;
+	s_new->base_addr = (void *) ((long) s_new->selector << 16);
+	s_new->length    = s_old->length;
+	s_new->flags     = s_old->flags;
+	s_new->owner     = s_old->owner;
+	if (swap_type)
+	{
+	    if (s_old->type == MODIFY_LDT_CONTENTS_DATA)
+		s_new->type = MODIFY_LDT_CONTENTS_CODE;
+	    else
+		s_new->type = MODIFY_LDT_CONTENTS_DATA;
+	}
+	else
+	    s_new->type = s_old->type;
+
+	base_addr = s_new->base_addr;
+    }
+
+    /******************************************************************
+     * If we don't have a shared memory key for s_old, then we need
+     * to get one.  In this case, we'll also have to copy the data
+     * to protect it.
+     */
     if (s_old->shm_key == 0)
     {
 	s_old->shm_key = shmget(IPC_PRIVATE, s_old->length, 0600);
 	if (s_old->shm_key == 0)
 	{
-	    memset(s_new, 0, sizeof(*s_new));
-	    return 0;
+	    if (s_new)
+		memset(s_new, 0, sizeof(*s_new));
+	    return -1;
 	}
-	if (shmat(s_old->shm_key, s_new->base_addr, 0) == NULL)
+	if (shmat(s_old->shm_key, base_addr, 0) == NULL)
 	{
-	    memset(s_new, 0, sizeof(*s_new));
+	    if (s_new)
+		memset(s_new, 0, sizeof(*s_new));
 	    shmctl(s_old->shm_key, IPC_RMID, NULL);
-	    return 0;
+	    return -1;
 	}
-	memcpy(s_new->base_addr, s_old->base_addr, s_new->length);
+	memcpy(base_addr, s_old->base_addr, s_old->length);
 	munmap(s_old->base_addr, 
 	       ((s_old->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
 	shmat(s_old->shm_key, s_old->base_addr, 0);
     }
+    /******************************************************************
+     * If have shared memory key s_old, then just attach the new
+     * address.
+     */
     else
     {
-	if (shmat(s_old->shm_key, s_new->base_addr, 0) == NULL)
+	if (shmat(s_old->shm_key, base_addr, 0) == NULL)
 	{
-	    memset(s_new, 0, sizeof(*s_new));
-	    return 0;
+	    if (s_new)
+		memset(s_new, 0, sizeof(*s_new));
+	    return -1;
 	}
     }
-    s_new->shm_key = s_old->shm_key;
 
-    if (set_ldt_entry(i_new, (unsigned long) s_new->base_addr, 
-		      s_new->length - 1, 0, s_new->type, 0, 0) < 0)
+    /******************************************************************
+     * If we are creating a new segment, then we also need to update
+     * the LDT to include the new selector.  In this return the
+     * new selector.
+     */
+    if (s_new)
     {
-	return 0;
-    }
+	s_new->shm_key = s_old->shm_key;
 
-    return s_new->selector;
+	if (set_ldt_entry(i_new, (unsigned long) base_addr, 
+			  s_old->length - 1, 0, s_new->type, 0, 0) < 0)
+	{
+	    return -1;
+	}
+
+	return s_new->selector;
+    }
+    /******************************************************************
+     * No new segment.  So, just return the shared memory key.
+     */
+    else
+	return s_old->shm_key;
 }
 #endif
 
@@ -190,15 +219,20 @@
 {
     SEGDESC *s_new, *s_old;
     int i_new, i_old;
+    int selector;
     
-    i_new = FindUnusedSelector();
+    i_new = FindUnusedSelectors(1);
     s_new = &Segments[i_new];
     
     if (old_selector)
     {
 	i_old = (old_selector >> 3);
 #ifdef HAVE_IPC
-	return IPCCopySelector(i_old, i_new, 0);
+	selector = IPCCopySelector(i_old, i_new, 0);
+	if (selector < 0)
+	    return 0;
+	else
+	    return selector;
 #else
 	s_old = &Segments[i_old];
 	s_new->selector = (i_new << 3) | 0x0007;
@@ -428,64 +462,72 @@
 }
 
 /**********************************************************************
- *					CreateNewSegment
+ *					CreateNewSegments
  */
 SEGDESC *
-CreateNewSegment(int code_flag, int read_only, int length)
+CreateNewSegments(int code_flag, int read_only, int length, int n_segments)
 {
-    SEGDESC *s;
+    SEGDESC *s, *first_segment;
     int contents;
-    int i;
+    int i, last_i;
     
-    i = FindUnusedSelector();
+    i = FindUnusedSelectors(n_segments);
+
+#ifdef DEBUG_SELECTORS    
+    fprintf(stderr, 
+	    "Using %d segments starting at index %d.\n", n_segments, i);
+#endif
 
     /*
      * Fill in selector info.
      */
-    s = &Segments[i];
-    if (code_flag)
+    first_segment = s = &Segments[i];
+    for (last_i = i + n_segments; i < last_i; i++, s++)
     {
-	contents = MODIFY_LDT_CONTENTS_CODE;
-	s->flags = 0;
-    }
-    else
-    {
-	contents = MODIFY_LDT_CONTENTS_DATA;
-	s->flags = NE_SEGFLAGS_DATA;
-    }
-    
-    s->selector = (i << 3) | 0x0007;
-    s->length = length;
+	if (code_flag)
+	{
+	    contents = MODIFY_LDT_CONTENTS_CODE;
+	    s->flags = 0;
+	}
+	else
+	{
+	    contents = MODIFY_LDT_CONTENTS_DATA;
+	    s->flags = NE_SEGFLAGS_DATA;
+	}
+	
+	s->selector = (i << 3) | 0x0007;
+	s->length = length;
 #ifdef DEV_ZERO
-    if (zfile == NULL)
-	zfile = fopen("/dev/zero","r");
-    s->base_addr = (void *) mmap((char *) (s->selector << 16),
-				 ((s->length + PAGE_SIZE - 1) & 
-				  ~(PAGE_SIZE - 1)),
-				 PROT_EXEC | PROT_READ | PROT_WRITE,
-				 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
-
+	if (zfile == NULL)
+	    zfile = fopen("/dev/zero","r");
+	s->base_addr = (void *) mmap((char *) (s->selector << 16),
+				     ((s->length + PAGE_SIZE - 1) & 
+				      ~(PAGE_SIZE - 1)),
+				     PROT_EXEC | PROT_READ | PROT_WRITE,
+				     MAP_FIXED | MAP_PRIVATE, 
+				     fileno(zfile), 0);
 #else
-    s->base_addr = (void *) mmap((char *) (s->selector << 16),
-				 ((s->length + PAGE_SIZE - 1) & 
-				  ~(PAGE_SIZE - 1)),
-				 PROT_EXEC | PROT_READ | PROT_WRITE,
-				 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
-
+	s->base_addr = (void *) mmap((char *) (s->selector << 16),
+				     ((s->length + PAGE_SIZE - 1) & 
+				      ~(PAGE_SIZE - 1)),
+				     PROT_EXEC | PROT_READ | PROT_WRITE,
+				     MAP_FIXED | MAP_PRIVATE | MAP_ANON, 
+				     -1, 0);
 #endif
 
-    if (set_ldt_entry(i, (unsigned long) s->base_addr, 
-		      (s->length - 1) & 0xffff, 0, 
-		      contents, read_only, 0) < 0)
-    {
-	memset(s, 0, sizeof(*s));
-	return NULL;
+	if (set_ldt_entry(i, (unsigned long) s->base_addr, 
+			  (s->length - 1) & 0xffff, 0, 
+			  contents, read_only, 0) < 0)
+	{
+	    memset(s, 0, sizeof(*s));
+	    return NULL;
+	}
+
+	SelectorMap[i] = (unsigned short) i;
+	s->type = contents;
     }
 
-    SelectorMap[i] = (unsigned short) i;
-    s->type = contents;
-    
-    return s;
+    return first_segment;
 }
 
 /**********************************************************************
@@ -494,7 +536,7 @@
 SEGDESC *
 GetNextSegment(unsigned int flags, unsigned int limit)
 {
-    return CreateNewSegment(0, 0, limit);
+    return CreateNewSegments(0, 0, limit, 1);
 }
 
 /**********************************************************************
@@ -672,7 +714,7 @@
     char *p;
     SEGDESC * s;
 
-    s = CreateNewSegment(0, 0, PAGE_SIZE);
+    s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
     if (s == NULL)
 	return NULL;
 
@@ -702,7 +744,7 @@
     char *p1, *p2;
     int i;
 
-    s = CreateNewSegment(0, 0, PAGE_SIZE);
+    s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
 
     /*
      * Fill PSP
@@ -835,8 +877,8 @@
 		read_only = 1;
 	}
 
-	stmp = CreateNewSegment(!(s->flags & NE_SEGFLAGS_DATA), read_only,
-				s->length);
+	stmp = CreateNewSegments(!(s->flags & NE_SEGFLAGS_DATA), read_only,
+				s->length, 1);
 	s->base_addr = stmp->base_addr;
 	s->selector = stmp->selector;
 	
@@ -874,7 +916,7 @@
     if(!EnvironmentSelector) {
 	    EnvironmentSelector = CreateEnvironment();
 	    PSP_Selector = CreatePSP();
-	    MakeProcThunks = CreateNewSegment(1, 0, 0x10000);
+	    MakeProcThunks = CreateNewSegments(1, 0, 0x10000, 1);
     };
 
     return selectors;
diff --git a/loader/signal.c b/loader/signal.c
index b2a492e..be88b96 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -3,7 +3,7 @@
 #include <stdlib.h>
 #include <time.h>
 
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <sys/syscall.h>
 #else
 #include <syscall.h>
@@ -55,7 +55,7 @@
 	if(signal != SIGSEGV) exit(1);
 	if((scp->sc_cs & 7) != 7){
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 /*         set_es(0x27); set_ds(0x27); */
 	if(signal != SIGBUS) exit(1);
 	if(scp->sc_cs == 0x1f){
@@ -134,7 +134,7 @@
 		(void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
 	wine_sigaction(SIGSEGV, &segv_act, NULL);
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
         struct sigstack ss;
         sigset_t sig_mask;
         
diff --git a/loader/wine.c b/loader/wine.c
index 48c5e2b..11aed62 100644
--- a/loader/wine.c
+++ b/loader/wine.c
@@ -363,11 +363,11 @@
 
     if (ss_reg == 0)
     {
-	fprintf(stderr, "SS is 0.  Send email to bob@amscons.com.\n");
-	fprintf(stderr, "    No. Really.  I want to know what programs\n");
-	fprintf(stderr, "    do this.\n");
+	fprintf(stderr, "SS is 0\n");
     }
 
+    LinearTest();
+
     rv = CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
     printf ("rv = %x\n", rv);
 }
diff --git a/memory/Makefile b/memory/Makefile
index f3ff2c7..d9abf4c 100644
--- a/memory/Makefile
+++ b/memory/Makefile
@@ -1,6 +1,6 @@
 CFLAGS=$(COPTS) $(DEBUGOPTS) -I$(INCLUDE_DIR)
 
-OBJS=global.o heap.o atom.o
+OBJS=global.o heap.o atom.o linear.o
 
 default: memory.o
 
diff --git a/memory/global.c b/memory/global.c
index bf11b37..76b558f 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -7,37 +7,37 @@
 #include "heap.h"
 #include "segmem.h"
 
-/*
- * Global memory pool descriptor.  Segments MUST be maintained in segment
- * ascending order.  If not the reallocation routine will die a horrible
- * death.
- *
- * handle  = 0, this descriptor contains the address of a free pool.
- *        != 0, this describes an allocated block.
- *
- * sequence = 0, this is not a huge block
- *          > 0, this is a portion of a huge block
- *          =-1, this is a free segment
- *
- * addr	      - address of this memory block.
- *
- * length     - used to maintain huge blocks.
- *
- */
-typedef struct global_mem_desc_s
-{
-    struct global_mem_desc_s *next;
-    struct global_mem_desc_s *prev;
-    unsigned short handle;
-    short sequence;
-    void *addr;
-    int length;
-    int lock_count;
-} GDESC;
-
 GDESC *GlobalList = NULL;
 static unsigned short next_unused_handle = 1;
 
+/**********************************************************************
+ *					GlobalGetGDesc
+ */
+GDESC *GlobalGetGDesc(unsigned int block)
+{
+    GDESC *g;
+
+    if (block == 0)
+	return NULL;
+
+    /*
+     * Find GDESC for this block.
+     */
+    if (block & 0xffff0000)
+    {
+	for (g = GlobalList; g != NULL; g = g->next)
+	    if (g->handle > 0 && (unsigned int) g->addr == block)
+		break;
+    }
+    else
+    {
+	for (g = GlobalList; g != NULL; g = g->next)
+	    if (g->handle == block)
+		break;
+    }
+
+    return g;
+}
 
 /**********************************************************************
  *					GlobalGetFreeSegments
@@ -91,13 +91,14 @@
 	/*
 	 * Allocate segments.
 	 */
-	for (count = 0; count < n_segments; count++)
+	s = CreateNewSegments(0, 0, 0x10000, n_segments);
+	if (s == NULL) 
 	{
-	    s = GetNextSegment(flags, 0x10000);
-	    if (s == NULL) {
-		printf("GlobalGetFreeSegments // bad GetNextSegment !\n");
-		return NULL;
-		}
+	    printf("GlobalGetFreeSegments // bad CreateNewSegments !\n");
+	    return NULL;
+	}
+	for (count = 0; count < n_segments; count++, s++)
+	{
 	    g = (GDESC *) malloc(sizeof(*g));
 	    if (g == NULL) {
 		printf("GlobalGetFreeSegments // bad GDESC malloc !\n");
@@ -109,6 +110,9 @@
 	    g->sequence = -1;
 	    g->addr = s->base_addr;
 	    g->length = s->length;
+	    g->linear_addr = NULL;
+	    g->linear_key = 0;
+	    g->linear_count = 0;
 	    if (!(flags & GLOBAL_FLAGS_MOVEABLE))
 		g->lock_count = 1;
 	    else
@@ -138,6 +142,9 @@
 	    }
 	g->sequence = i + 1;
 	g->length = n_segments;
+	g->linear_addr = NULL; 
+	g->linear_key = 0;
+	g->linear_count = 0;
     }
 
     return g_start;
@@ -223,6 +230,9 @@
 	g->handle = next_unused_handle;
 	g->sequence = 0;
 	g->addr = m;
+	g->linear_addr = NULL;
+	g->linear_key = 0;
+	g->linear_count = 0;
 	g->length = size;
 	g->next = g_prev->next;
 	if (g->next) g->next->prev = g;
diff --git a/memory/linear.c b/memory/linear.c
new file mode 100644
index 0000000..af403e2
--- /dev/null
+++ b/memory/linear.c
@@ -0,0 +1,193 @@
+static char RCSId[] = "$Id$";
+static char Copyright[] = "Copyright  Robert J. Amstadt, 1994";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "prototypes.h"
+#include "heap.h"
+#include "segmem.h"
+
+#ifdef HAVE_IPC
+static key_t MemoryKeys[SHMSEG];	/* Keep track of keys were using */
+static int   LinearInitialized = 0;
+#endif
+
+
+#ifdef HAVE_IPC
+/**********************************************************************
+ *					LinearFindSpace
+ */
+int 
+LinearFindSpace(int n_segments)
+{
+    int i, n;
+    
+    if (!LinearInitialized)
+    {
+	memset(MemoryKeys, -1, sizeof(MemoryKeys));
+	return 0;
+    }
+
+    for (i = 0, n = 0; i < SHMSEG, n != n_segments; i++)
+    {
+	if (MemoryKeys[i] < 0)
+	    n++;
+	else
+	    n = 0;
+    }
+    
+    if (n != n_segments)
+	return -1;
+    else
+	return i - n;
+}
+#endif /* HAVE_IPC */
+
+/**********************************************************************
+ *					GlobalLinearLock
+ *
+ * OK, this is an evil beast.  We will do one of two things:
+ *
+ *	1. If the data item <= 64k, then just call GlobalLock().
+ *	2. If the data item > 64k, then map memory.
+ */
+void *
+GlobalLinearLock(unsigned int block)
+{
+    GDESC *g, *g_first;
+    int loc_idx;
+    unsigned long addr;
+    int i;
+    
+    /******************************************************************
+     * Get GDESC for this block.
+     */
+    g_first = GlobalGetGDesc(block);
+    if (g_first == NULL)
+	return 0;
+
+    /******************************************************************
+     * Is block less then 64k in length?
+     */
+    if (g_first->sequence != 1 || g_first->length == 1)
+    {
+	return (void *) GlobalLock(block);
+    }
+
+    /******************************************************************
+     * If there is already a linear lock on this memory, then
+     * just return a pointer to it.
+     */
+    if (g_first->linear_count)
+    {
+	g_first->linear_count++;
+	return g_first->linear_addr;
+    }
+    
+    /******************************************************************
+     * No luck.  We need to do the linear mapping right now.
+     */
+#ifdef HAVE_IPC
+    loc_idx = LinearFindSpace(g_first->length);
+    if (loc_idx < 0)
+	return NULL;
+    
+    addr = (unsigned long) SHM_RANGE_START + (0x10000 * loc_idx);
+    g = g_first;
+    for (i = loc_idx; 
+	 i < loc_idx + g_first->length; 
+	 i++, addr += 0x10000, g = g->next)
+    {
+	if ((MemoryKeys[i] = IPCCopySelector(g->handle >> 3, addr, 0)) < 0)
+	    return NULL;
+	g->linear_addr = (void *) addr;
+	g->linear_count = 1;
+    }
+#endif /* HAVE_IPC */
+
+    return g_first->linear_addr;
+}
+
+/**********************************************************************
+ *					GlobalLinearUnlock
+ *
+ */
+unsigned int
+GlobalLinearUnlock(unsigned int block)
+{
+    GDESC *g, *g_first;
+    int loc_idx;
+    int i;
+    
+    /******************************************************************
+     * Get GDESC for this block.
+     */
+    g_first = GlobalGetGDesc(block);
+    if (g_first == NULL)
+	return block;
+
+    /******************************************************************
+     * Is block less then 64k in length?
+     */
+    if (g_first->sequence != 1 || g_first->length == 1)
+    {
+	return GlobalUnlock(block);
+    }
+
+    /******************************************************************
+     * Make sure we have a lock on this block.
+     */
+#ifdef HAVE_IPC
+    if (g_first->linear_count > 1)
+    {
+	g_first->linear_count--;
+    }
+    else if (g_first->linear_count == 1)
+    {
+	g = g_first;
+	loc_idx = (((unsigned int) g_first - (unsigned int) SHM_RANGE_START) 
+		   / 0x10000);
+	for (i = 0; i < g_first->length; i++, g = g->next)
+	{
+	    shmdt(g->linear_addr);
+	    g->linear_addr = NULL;
+	    MemoryKeys[i] = -1;
+	}
+	
+	g_first->linear_count = 0;
+	return 0;
+    }
+#endif /* HAVE_IPC */
+
+    return 0;
+}
+/**********************************************************************/
+
+LinearTest()
+{
+#if 0
+    unsigned int handle;
+    int *seg_ptr;
+    int *lin_ptr;
+    int seg, i;
+    int *p;
+
+    handle = GlobalAlloc(0, 0x40000);
+    seg_ptr = GlobalLock(handle);
+    lin_ptr = GlobalLinearLock(handle);
+
+    for (seg = 0; seg < 4; seg++)
+    {
+	p = (int *) ((char *) seg_ptr + (0x80000 * seg));
+	for (i = 0; i < (0x10000 / sizeof(int)); i++, p++)
+	    *p = (seg * (0x10000 / sizeof(int))) + i;
+    }
+    
+    p = lin_ptr;
+    for (i = 0; i < (0x40000 / sizeof(int)); i++, p++)
+    {
+	if (*p != i)
+	    printf("lin_ptr[%x] = %x\n", i, *p);
+    }
+#endif
+}
diff --git a/misc/Imakefile b/misc/Imakefile
index 53eda76..b628e2e 100644
--- a/misc/Imakefile
+++ b/misc/Imakefile
@@ -3,37 +3,45 @@
 MODULE = misc
 
 SRCS = \
-	kernel.c \
-	user.c \
-	rect.c \
-	file.c \
-	sound.c \
+	comm.c \
+	dos.c \
+	dos_fs.c \
 	emulate.c \
-	keyboard.c \
-	profile.c \
-	lstr.c \
 	exec.c \
-	message.c \
+	file.c \
 	int1a.c \
 	int21.c \
-	dos_fs.c \
+	kernel.c \
+	keyboard.c \
+	lstr.c \
+	main.c \
+	message.c \
+	profile.c \
+	rect.c \
+	sound.c \
+	spy.c \
+	user.c \
 	xt.c
 
 OBJS = \
-	kernel.o \
-	user.o \
-	rect.o \
-	file.o \
-	sound.o \
+	comm.o \
+	dos.o \
+	dos_fs.o \
 	emulate.o \
-	keyboard.o \
-	profile.o \
-	lstr.o \
 	exec.o \
-	message.o \
+	file.o \
 	int1a.o \
 	int21.o \
-	dos_fs.o \
+	kernel.o \
+	keyboard.o \
+	lstr.o \
+	main.o \
+	message.o \
+	profile.o \
+	rect.o \
+	sound.o \
+	spy.o \
+	user.o \
 	xt.o
 
 WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
diff --git a/misc/comm.c b/misc/comm.c
index ca65c0d..d9f5344 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -8,7 +8,7 @@
 #include <fcntl.h>
 #include <string.h>
 #include <sys/stat.h>
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <errno.h>
 #include <sys/ioctl.h>
 #endif
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
index b8f052e..3840972 100644
--- a/misc/dos_fs.c
+++ b/misc/dos_fs.c
@@ -13,7 +13,7 @@
 #ifdef __linux__
 #include <sys/vfs.h>
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <sys/types.h>
 #include <sys/mount.h>
 #endif
diff --git a/misc/int21.c b/misc/int21.c
index 4d1ae70..6caaa7c 100644
--- a/misc/int21.c
+++ b/misc/int21.c
@@ -1,7 +1,9 @@
 #include <time.h>
 #include <fcntl.h>
 #include <errno.h>
+#ifndef __STDC__
 #include <malloc.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
diff --git a/misc/message.c b/misc/message.c
index f6fb52f..364b460 100644
--- a/misc/message.c
+++ b/misc/message.c
@@ -6,7 +6,14 @@
 
 static char Copyright[] = "Copyright Martin Ayotte, 1993";
 
-#include "windows.h"
+#define DEBUG_MSGBOX
+
+#include <windows.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "prototypes.h"
 #include "heap.h"
 #include "win.h"
 
@@ -26,7 +33,6 @@
 } MSGBOX;
 typedef MSGBOX FAR* LPMSGBOX;
 
-
 LONG SystemMessageBoxProc(HWND hwnd, WORD message, WORD wParam, LONG lParam);
 
 /**************************************************************************
@@ -40,8 +46,11 @@
     WNDCLASS  	wndClass;
     MSG	    	msg;
     MSGBOX	mb;
+    DWORD	dwStyle;
     wndPtr = WIN_FindWndPtr(hWnd);
+#ifdef DEBUG_MSGBOX
     printf( "MessageBox: '%s'\n", str );
+#endif
     wndClass.style           = CS_HREDRAW | CS_VREDRAW ;
     wndClass.lpfnWndProc     = (WNDPROC)SystemMessageBoxProc;
     wndClass.cbClsExtra      = 0;
@@ -58,8 +67,9 @@
     mb.Str = str;
     mb.wType = type;
     mb.ActiveFlg = TRUE;
-    hDlg = CreateWindow("MESSAGEBOX", title, 
-    	WS_POPUP | WS_DLGFRAME | WS_VISIBLE, 100, 150, 400, 120,
+    dwStyle = WS_POPUP | WS_DLGFRAME | WS_VISIBLE;
+    if ((type & (MB_SYSTEMMODAL | MB_TASKMODAL)) == 0) dwStyle |= WS_CAPTION;
+    hDlg = CreateWindow("MESSAGEBOX", title, dwStyle, 100, 150, 400, 120,
     	(HWND)NULL, (HMENU)NULL, wndPtr->hInstance, (LPSTR)&mb);
     if (hDlg == 0) return 0;
     while(TRUE) {
@@ -68,8 +78,10 @@
 	TranslateMessage(&msg);
 	DispatchMessage(&msg);
 	}
-    printf( "after MessageBox !\n");
     if (!UnregisterClass("MESSAGEBOX", wndPtr->hInstance)) return 0;
+#ifdef DEBUG_MSGBOX
+    printf( "MessageBox return %04X !\n", mb.wRetVal);
+#endif
     return(mb.wRetVal);
 }
 
@@ -219,7 +231,9 @@
 	    EndPaint(hWnd, &ps);
 	    break;
 	case WM_DESTROY:
+#ifdef DEBUG_MSGBOX
 	    printf("MessageBox WM_DESTROY !\n");
+#endif
 	    ReleaseCapture();
 	    lpmb = MsgBoxGetStorageHeader(hWnd);
 	    lpmb->ActiveFlg = FALSE;
@@ -227,6 +241,9 @@
 	    if (lpmb->hWndYes) DestroyWindow(lpmb->hWndYes);
 	    if (lpmb->hWndNo) DestroyWindow(lpmb->hWndNo);
 	    if (lpmb->hWndCancel) DestroyWindow(lpmb->hWndCancel);
+#ifdef DEBUG_MSGBOX
+	    printf("MessageBox WM_DESTROY end !\n");
+#endif
 	    break;
 	case WM_COMMAND:
 	    lpmb = MsgBoxGetStorageHeader(hWnd);
@@ -257,17 +274,41 @@
     HFONT	hOldFont;
     RECT 	rect;
     BITMAP	bm;
-    char 	C[80];
     int 	X;
-    static HBITMAP	hBitMap;
+    OFSTRUCT	ofstruct;
+    static LPSTR	ptr;
+    static char 	str[256];
+    static HBITMAP	hBitMap = 0;
+    static BOOL		CreditMode;
+    static HANDLE	hFile = 0;
     switch (msg) {
     case WM_INITDIALOG:
-	strcpy(C, "WINELOGO");
-	hBitMap = LoadBitmap((HINSTANCE)NULL, (LPSTR)C);
+	CreditMode = FALSE;
+	strcpy(str, "WINELOGO");
+	hBitMap = LoadBitmap((HINSTANCE)NULL, (LPSTR)str);
+/*	getcwd(str, 256);
+	strcat(str, ";");
+	strcat(str, getenv("HOME"));
+	strcat(str, ";");
+	strcat(str, getenv("WINEPATH")); */
+	strcpy(str, "PROPOSED_LICENSE");
+	printf("str = '%s'\n", str);
+	hFile = KERNEL_OpenFile((LPSTR)str, &ofstruct, OF_READ);
+	ptr = (LPSTR)malloc(2048);
+	lseek(hFile, 0L, SEEK_SET);
+	KERNEL__lread(hFile, ptr, 2000L);
+	close(hFile);
 	return TRUE;
     case WM_PAINT:
 	hDC = BeginPaint(hDlg, &ps);
 	GetClientRect(hDlg, &rect);
+	if (CreditMode) {
+	    FillRect(hDC, &rect, GetStockObject(WHITE_BRUSH));
+	    InflateRect(&rect, -8, -8);
+	    DrawText(hDC, ptr, -1, &rect, DT_LEFT | DT_WORDBREAK);
+	    EndPaint(hDlg, &ps);
+	    return TRUE;
+	    }
 	FillRect(hDC, &rect, GetStockObject(GRAY_BRUSH));
 	InflateRect(&rect, -3, -3);
 	FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
@@ -283,8 +324,26 @@
     case WM_COMMAND:
 	switch (wParam)
 	    {
+	    case IDYES:
+		if (!CreditMode) {
+		    SetWindowPos(hDlg, (HWND)NULL, 0, 0, 640, 480, 
+				SWP_NOMOVE | SWP_NOZORDER);
+		    }
+		else {
+		    SetWindowPos(hDlg, (HWND)NULL, 0, 0, 320, 250, 
+				SWP_NOMOVE | SWP_NOZORDER);
+		    }
+		CreditMode = !CreditMode;
+		ShowWindow(GetDlgItem(hDlg, IDYES), CreditMode ? SW_HIDE : SW_SHOW);
+		ShowWindow(GetDlgItem(hDlg, IDOK), CreditMode ? SW_HIDE : SW_SHOW);
+		InvalidateRect(hDlg, (LPRECT)NULL, TRUE);
+		UpdateWindow(hDlg);
+		return TRUE;
+	    case IDCANCEL:
 	    case IDOK:
-CloseDLG:	EndDialog(hDlg, TRUE);
+CloseDLG:	if (hBitMap != 0 ) DeleteObject(hBitMap);
+		if (ptr != NULL) free(ptr);
+		EndDialog(hDlg, TRUE);
 		return TRUE;
 	    default:
 		return TRUE;
diff --git a/objects/palette.c b/objects/palette.c
index f107a61..0ff149e 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -10,7 +10,7 @@
 #ifdef linux
 #include <values.h>
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <limits.h>
 #define MAXINT INT_MAX
 #endif
diff --git a/sysres.dll b/sysres.dll
index 0a61ba9..8b55d67 100755
--- a/sysres.dll
+++ b/sysres.dll
Binary files differ
diff --git a/test/widget.exe b/test/widget.exe
index 95413e0..42d1465 100755
--- a/test/widget.exe
+++ b/test/widget.exe
Binary files differ
diff --git a/tools/build.c b/tools/build.c
index d596493..7343b76 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -9,7 +9,7 @@
 #ifdef linux
 #define UTEXTSEL 0x23
 #endif
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
 #define UTEXTSEL 0x1f
 #endif
 
diff --git a/windows/Imakefile b/windows/Imakefile
index b16652f..5aa561e 100644
--- a/windows/Imakefile
+++ b/windows/Imakefile
@@ -3,46 +3,54 @@
 MODULE = windows
 
 SRCS = \
+	caret.c \
 	class.c \
+	clipping.c \
 	dc.c \
 	dce.c \
-	event.c \
-	message.c \
-	win.c \
-	timer.c \
-	graphics.c \
-	clipping.c \
-	mapping.c \
-	painting.c \
-	keyboard.c \
-	utility.c \
-	syscolor.c \
-	defwnd.c \
 	defdlg.c \
+	defwnd.c \
 	dialog.c \
+	event.c \
 	focus.c \
-	scroll.c
+	graphics.c \
+	keyboard.c \
+	mapping.c \
+	message.c \
+	nonclient.c \
+	painting.c \
+	scroll.c \
+	syscolor.c \
+	sysmetrics.c \
+	timer.c \
+	utility.c \
+	win.c \
+	winpos.c
 
 OBJS = \
+	caret.o \
 	class.o \
+	clipping.o \
 	dc.o \
 	dce.o \
-	event.o \
-	message.o \
-	win.o \
-	timer.o \
-	graphics.o \
-	clipping.o \
-	mapping.o \
-	painting.o \
-	keyboard.o \
-	utility.o \
-	syscolor.o \
-	defwnd.o \
 	defdlg.o \
+	defwnd.o \
 	dialog.o \
+	event.o \
 	focus.o \
-	scroll.o
+	graphics.o \
+	keyboard.o \
+	mapping.o \
+	message.o \
+	nonclient.o \
+	painting.o \
+	scroll.o \
+	syscolor.o \
+	sysmetrics.o \
+	timer.o \
+	utility.o \
+	win.o \
+	winpos.o
 
 WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
 DependTarget()
diff --git a/windows/clipping.c b/windows/clipping.c
index 3c759a6..28d0da9 100644
--- a/windows/clipping.c
+++ b/windows/clipping.c
@@ -38,6 +38,16 @@
     else MSG_IncPaintCount( wndPtr->hmemTaskQ );
     wndPtr->hrgnUpdate = newRgn;
     if (erase) wndPtr->flags |= WIN_ERASE_UPDATERGN;
+
+      /* Invalidate the children overlapping the region */
+
+    if (wndPtr->dwStyle & WS_CLIPCHILDREN) return;
+    for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
+    {
+	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
+	if (hrgn && !RectInRegion( hrgn, &wndPtr->rectWindow )) continue;
+	InvalidateRgn( hwnd, hrgn, erase );
+    }
 }
 
 
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 95bb0f0..62f9f50 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -13,14 +13,34 @@
 #include "user.h"
 
 extern LONG NC_HandleNCPaint( HWND hwnd, HRGN hrgn );
+extern LONG NC_HandleNCActivate( HWND hwnd, WORD wParam );
 extern LONG NC_HandleNCCalcSize( HWND hwnd, NCCALCSIZE_PARAMS *params );
 extern LONG NC_HandleNCHitTest( HWND hwnd, POINT pt );
 extern LONG NC_HandleNCLButtonDown( HWND hwnd, WORD wParam, LONG lParam );
-extern LONG NC_HandleNCLButtonUp( HWND hwnd, WORD wParam, LONG lParam );
 extern LONG NC_HandleNCLButtonDblClk( HWND hwnd, WORD wParam, LONG lParam );
-extern LONG NC_HandleNCMouseMove( HWND hwnd, WORD wParam, POINT pt );
 extern LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt );
 extern LONG NC_HandleSetCursor( HWND hwnd, WORD wParam, LONG lParam );
+extern void NC_TrackSysMenu( HWND hwnd ); /* menu.c */
+
+
+
+/***********************************************************************
+ *           DEFWND_SetText
+ *
+ * Set the window text.
+ */
+void DEFWND_SetText( HWND hwnd, LPSTR text )
+{
+    LPSTR textPtr;
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (wndPtr->hText) USER_HEAP_FREE( wndPtr->hText );
+    wndPtr->hText = USER_HEAP_ALLOC( LMEM_MOVEABLE, strlen(text) + 2 );
+    textPtr = (LPSTR) USER_HEAP_ADDR( wndPtr->hText );
+    strcpy( textPtr, text );
+        /* for use by edit control */
+    *(textPtr + strlen(text) + 1) = '\0';
+}
 
 
 /***********************************************************************
@@ -43,15 +63,7 @@
 	{
 	    CREATESTRUCT * createStruct = (CREATESTRUCT *)lParam;
 	    if (createStruct->lpszName)
-	    {
-		  /* Allocate space for window text */
-		wndPtr->hText = USER_HEAP_ALLOC(GMEM_MOVEABLE, 
-					strlen(createStruct->lpszName) + 2);
-		textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
-		strcpy(textPtr, createStruct->lpszName);
-		*(textPtr + strlen(createStruct->lpszName) + 1) = '\0';
-		                         /* for use by edit control */
-	    }
+		DEFWND_SetText( hwnd, createStruct->lpszName );
 	    return 1;
 	}
 
@@ -67,14 +79,11 @@
     case WM_NCLBUTTONDOWN:
 	return NC_HandleNCLButtonDown( hwnd, wParam, lParam );
 
-    case WM_NCLBUTTONUP:
-	return NC_HandleNCLButtonUp( hwnd, wParam, lParam );
-
     case WM_NCLBUTTONDBLCLK:
 	return NC_HandleNCLButtonDblClk( hwnd, wParam, lParam );
 
-    case WM_NCMOUSEMOVE:
-	return NC_HandleNCMouseMove( hwnd, wParam, MAKEPOINT(lParam) );
+    case WM_NCACTIVATE:
+	return NC_HandleNCActivate( hwnd, wParam );
 
     case WM_NCDESTROY:
 	{
@@ -95,6 +104,19 @@
 	DestroyWindow( hwnd );
 	return 0;
 
+    case WM_MOUSEACTIVATE:
+	if (wndPtr->dwStyle & WS_CHILD)
+	{
+	    LONG ret = SendMessage( wndPtr->hwndParent, WM_MOUSEACTIVATE,
+				    wParam, lParam );
+	    if (ret) return ret;
+	}
+	return MA_ACTIVATE;
+
+    case WM_ACTIVATE:
+	if (wParam) SetFocus( hwnd );
+	break;
+
     case WM_WINDOWPOSCHANGED:
 	{
 	    WINDOWPOS * winPos = (WINDOWPOS *)lParam;
@@ -170,16 +192,9 @@
 	}
 
     case WM_SETTEXT:
-	{
-	    if (wndPtr->hText)
-		USER_HEAP_FREE(wndPtr->hText);
-
-	    wndPtr->hText = USER_HEAP_ALLOC(GMEM_MOVEABLE, 
-					    strlen((LPSTR)lParam) + 1);
-	    textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
-	    strcpy(textPtr, (LPSTR)lParam);
-	    return (0L);
-	}
+	DEFWND_SetText( hwnd, (LPSTR)lParam );
+	NC_HandleNCPaint( hwnd, (HRGN)1 );  /* Repaint caption */
+	return 0;
 
     case WM_SETCURSOR:
 	if (wndPtr->dwStyle & WS_CHILD)
@@ -193,6 +208,7 @@
     case WM_SYSKEYDOWN:
     	if (wParam == VK_MENU) {
     	    printf("VK_MENU Pressed // hMenu=%04X !\n", GetMenu(hwnd));
+	    NC_TrackSysMenu(hwnd);
     	    }
     	break;    	
     case WM_SYSKEYUP:
diff --git a/windows/dialog.c b/windows/dialog.c
index 6316e34..9f0b64a 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -9,6 +9,7 @@
 #include "windows.h"
 #include "dialog.h"
 #include "win.h"
+#include "user.h"
 
 
   /* Dialog base units */
@@ -510,14 +511,13 @@
  */
 void SetDlgItemInt( HWND hwnd, WORD id, WORD value, BOOL fSigned )
 {
-    HANDLE hText = LocalAlloc( LMEM_MOVEABLE, 10 );
-    char * str = (char *) LocalLock( hText );
+    HANDLE hText = USER_HEAP_ALLOC(0, 10 );
+    char * str = (char *) USER_HEAP_ADDR( hText );
 
     if (fSigned) sprintf( str, "%d", value );
     else sprintf( str, "%u", value );
     SendDlgItemMessage( hwnd, id, WM_SETTEXT, 0, (DWORD)str );
-    LocalUnlock( hText );
-    LocalFree( hText );
+    USER_HEAP_FREE( hText );
 }
 
 
@@ -534,9 +534,9 @@
     if (translated) *translated = FALSE;
     if (!(len = SendDlgItemMessage( hwnd, id, WM_GETTEXTLENGTH, 0, 0 )))
 	return 0;
-    if (!(hText = LocalAlloc(LMEM_MOVEABLE, len+1 )))
+    if (!(hText = USER_HEAP_ALLOC(0, len+1 )))
 	return 0;
-    str = (char *) LocalLock( hText );
+    str = (char *) USER_HEAP_ADDR( hText );
     if (SendDlgItemMessage( hwnd, id, WM_GETTEXT, len+1, (DWORD)str ))
     {
 	char * endptr;
@@ -555,8 +555,7 @@
 	    }
 	}
     }
-    LocalUnlock( hText );
-    LocalFree( hText );
+    USER_HEAP_FREE( hText );
     return (WORD)result;
 }
 
diff --git a/windows/event.c b/windows/event.c
index ba1c0a3..155c66f 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -18,6 +18,8 @@
 
 extern Display * display;
 
+extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
+
   /* X context to associate a hwnd to an X window */
 static XContext winContext = 0;
 
@@ -453,10 +455,11 @@
  */
 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
 {
-
     WND * wndPtr = WIN_FindWndPtr( hwnd );
-
     if (!wndPtr) return;
+
+    if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
+
     if (wndPtr->dwStyle & WS_DISABLED) {
 	return;
     }
@@ -503,8 +506,8 @@
 	return 0;
     
     rv = XGrabPointer(display, wnd_p->window, False, 
-		      ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
-		      GrabModeAsync, GrabModeSync, None, None, CurrentTime);
+		      ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
+		      GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
 
     if (rv == GrabSuccess)
     {
diff --git a/windows/focus.c b/windows/focus.c
index a2d2b8d..0e88138 100644
--- a/windows/focus.c
+++ b/windows/focus.c
@@ -24,6 +24,7 @@
     WND *wndPtr;
 
     hWndPrevFocus = hWndFocus;
+    hWndFocus = hwnd;
 
     if (hwnd == 0)
     {
diff --git a/windows/message.c b/windows/message.c
index b41dbf8..de06f28 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -24,6 +24,7 @@
 
 extern BOOL TIMER_CheckTimer( DWORD *next );      /* timer.c */
 extern void EVENT_ProcessEvent( XEvent *event );  /* event.c */
+extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
   
 extern Display * display;
 
@@ -195,32 +196,65 @@
  *           MSG_TranslateMouseMsg
  *
  * Translate an mouse hardware event into a real mouse message.
+ * Return value indicates whether the translated message must be passed
+ * to the user.
  * Actions performed:
  * - Translate button-down messages in double-clicks.
  * - Send the WM_NCHITTEST message to find where the cursor is.
+ * - Activate the window if needed.
  * - Translate the message into a non-client message, or translate
  *   the coordinates to client coordinates.
  * - Send the WM_SETCURSOR message.
  */
-static void MSG_TranslateMouseMsg( MSG *msg )
+static BOOL MSG_TranslateMouseMsg( MSG *msg )
 {
+    BOOL eatMsg = FALSE;
     static DWORD lastClickTime = 0;
     static WORD  lastClickMsg = 0;
     static POINT lastClickPos = { 0, 0 };
 
+    BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
+		       (msg->message == WM_RBUTTONDOWN) ||
+		       (msg->message == WM_MBUTTONDOWN));
+
+      /* Send the WM_NCHITTEST message */
+
     LONG hittest_result = SendMessage( msg->hwnd, WM_NCHITTEST, 0,
 				       MAKELONG( msg->pt.x, msg->pt.y ) );
+
+      /* Activate the window if needed */
+
+    if (mouseClick)
+    {
+	HWND parent, hwndTop = msg->hwnd;	
+	while ((parent = GetParent(hwndTop)) != 0) hwndTop = parent;
+	if (hwndTop != GetActiveWindow())
+	{
+	    LONG ret = SendMessage( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
+				    MAKELONG( hittest_result, msg->message ) );
+	    if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
+		eatMsg = TRUE;
+	    if ((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
+	    {
+		SetWindowPos( hwndTop, HWND_TOP, 0, 0, 0, 0,
+			      SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
+		WINPOS_ChangeActiveWindow( hwndTop, TRUE );
+	    }
+	}
+    }
+
+      /* Send the WM_SETCURSOR message */
+
     SendMessage( msg->hwnd, WM_SETCURSOR, msg->hwnd,
 		 MAKELONG( hittest_result, msg->message ));
+    if (eatMsg) return FALSE;
 
-    if ((msg->message == WM_LBUTTONDOWN) ||
-        (msg->message == WM_RBUTTONDOWN) ||
-        (msg->message == WM_MBUTTONDOWN))
+      /* Check for double-click */
+
+    if (mouseClick)
     {
 	BOOL dbl_click = FALSE;
 
-	  /* Check for double-click */
-
 	if ((msg->message == lastClickMsg) &&
 	    (msg->time - lastClickTime < doubleClickSpeed) &&
 	    (abs(msg->pt.x - lastClickPos.x) < SYSMETRICS_CXDOUBLECLK/2) &&
@@ -247,6 +281,8 @@
 	lastClickPos  = msg->pt;
     }
 
+      /* Build the translated message */
+
     msg->lParam = MAKELONG( msg->pt.x, msg->pt.y );
     if (hittest_result == HTCLIENT)
     {
@@ -257,6 +293,7 @@
 	msg->wParam = hittest_result;
 	msg->message += WM_NCLBUTTONDOWN - WM_LBUTTONDOWN;
     }
+    return TRUE;
 }
 
 
@@ -351,6 +388,33 @@
 
 		    
 /***********************************************************************
+ *           MSG_GetHardwareMessage
+ *
+ * Like GetMessage(), but only return mouse and keyboard events.
+ * Used internally for window moving and resizing. Mouse messages
+ * are not translated.
+ */
+BOOL MSG_GetHardwareMessage( LPMSG msg )
+{
+    int pos;
+    XEvent event;
+
+    while(1)
+    {    
+	if ((pos = MSG_FindMsg( sysMsgQueue, 0, 0, 0 )) != -1)
+	{
+	    *msg = sysMsgQueue->messages[pos].msg;
+	    MSG_RemoveMsg( sysMsgQueue, pos );
+	    break;
+	}
+	XNextEvent( display, &event );
+	EVENT_ProcessEvent( &event );
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           SetTaskQueue  (KERNEL.34)
  */
 WORD SetTaskQueue( HANDLE hTask, HANDLE hQueue )
@@ -505,9 +569,14 @@
 	    msgQueue->GetMessagePosVal       = *(DWORD *)&msg->pt;
 	    msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
 
-	    if (flags & PM_REMOVE) MSG_RemoveMsg( sysMsgQueue, pos );
 	    if ((msg->message >= WM_MOUSEFIRST) &&
-		(msg->message <= WM_MOUSELAST)) MSG_TranslateMouseMsg( msg );
+		(msg->message <= WM_MOUSELAST))
+		if (!MSG_TranslateMouseMsg( msg )) 
+		{
+		    MSG_RemoveMsg( sysMsgQueue, pos );
+		    continue;
+		}
+	    if (flags & PM_REMOVE) MSG_RemoveMsg( sysMsgQueue, pos );
 	    break;
 	}
 
diff --git a/windows/nonclient.c b/windows/nonclient.c
index d326ab9..8f84802 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -7,7 +7,10 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
 
 #include "win.h"
+#include "message.h"
 #include "sysmetrics.h"
+#include "user.h"
+#include "scroll.h"
 
 
 static HBITMAP hbitmapClose = 0;
@@ -18,15 +21,12 @@
 static HBITMAP hbitmapRestore = 0;
 static HBITMAP hbitmapRestoreD = 0;
 
-  /* Hit test code returned when the mouse is captured. */
-  /* Used to direct NC mouse messages to the correct part of the window. */
-static WORD captureHitTest = HTCLIENT; 
+extern void NC_TrackSysMenu( HWND hwnd ); /* menu.c */
+extern void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
+			    POINT *minTrack, POINT *maxTrack );  /* winpos.c */
 
-  /* Point where the current capture started. Used for SC_SIZE and SC_MOVE. */
-static POINT capturePoint;
+extern Display * display;
 
-  /* Current window rectangle when a move or resize is in progress. */
-static RECT sizingRect;
 
   /* Some useful macros */
 #define HAS_DLGFRAME(style,exStyle) \
@@ -136,7 +136,10 @@
 
       /* Remove frame from rectangle */
     if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
+    {
 	InflateRect( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
+	if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) InflateRect( rect, -1, 0);
+    }
     else
     {
 	if (HAS_THICKFRAME( wndPtr->dwStyle ))
@@ -264,7 +267,7 @@
 #ifdef DEBUG_NONCLIENT
     printf( "NC_HandleNCHitTest: hwnd=%x pt=%d,%d\n", hwnd, pt.x, pt.y );
 #endif
-    if (hwnd == GetCapture()) return captureHitTest;
+    if (hwnd == GetCapture()) return HTCLIENT;
     return NC_InternalNCHitTest( hwnd, pt );
 }
 
@@ -272,18 +275,16 @@
 /***********************************************************************
  *           NC_DrawSysButton
  */
-static void NC_DrawSysButton( HWND hwnd, HDC hdc )
+static void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
 {
     RECT rect;
-    BOOL down;
     HDC hdcMem = CreateCompatibleDC( hdc );
     if (hdcMem)
     {
 	NC_GetInsideRect( hwnd, &rect );
-	down = ((GetCapture() == hwnd) && (captureHitTest == HTSYSMENU));
 	SelectObject( hdcMem, hbitmapClose );
-	BitBlt( hdc, rect.left-1, rect.top-1, SYSMETRICS_CXSIZE+1,
-	       SYSMETRICS_CYSIZE+1, hdcMem, 0, 0, down ? NOTSRCCOPY : SRCCOPY);
+	BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE,
+	       SYSMETRICS_CYSIZE, hdcMem, 1, 1, down ? NOTSRCCOPY : SRCCOPY );
 	DeleteDC( hdcMem );
     }
 }
@@ -292,15 +293,13 @@
 /***********************************************************************
  *           NC_DrawMaxButton
  */
-static void NC_DrawMaxButton( HWND hwnd, HDC hdc )
+static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
 {
     RECT rect;
-    BOOL down;
     HDC hdcMem = CreateCompatibleDC( hdc );
     if (hdcMem)
     {
 	NC_GetInsideRect( hwnd, &rect );
-	down = ((GetCapture() == hwnd) && (captureHitTest == HTMAXBUTTON));
 	if (IsZoomed(hwnd))
 	    SelectObject( hdcMem, down ? hbitmapRestoreD : hbitmapRestore );
 	else SelectObject( hdcMem, down ? hbitmapMaximizeD : hbitmapMaximize );
@@ -314,7 +313,7 @@
 /***********************************************************************
  *           NC_DrawMinButton
  */
-static void NC_DrawMinButton( HWND hwnd, HDC hdc )
+static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
 {
     RECT rect;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
@@ -324,8 +323,7 @@
 	NC_GetInsideRect( hwnd, &rect );
 	if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
 	    rect.right -= SYSMETRICS_CXSIZE + 1;	
-	if ((GetCapture() == hwnd) && (captureHitTest == HTMINBUTTON))
-	    SelectObject( hdcMem, hbitmapMinimizeD );
+	if (down) SelectObject( hdcMem, hbitmapMinimizeD );
 	else SelectObject( hdcMem, hbitmapMinimize );
 	BitBlt( hdc, rect.right - SYSMETRICS_CXSIZE - 1, rect.top - 1,
 	      SYSMETRICS_CXSIZE+2, SYSMETRICS_CYSIZE+2, hdcMem, 0, 0, SRCCOPY);
@@ -346,8 +344,8 @@
 
     if (dlgFrame)
     {
-	width = SYSMETRICS_CXDLGFRAME;
-	height = SYSMETRICS_CYDLGFRAME;
+	width = SYSMETRICS_CXDLGFRAME - 1;
+	height = SYSMETRICS_CYDLGFRAME - 1;
     }
     else
     {
@@ -412,12 +410,9 @@
  *
  * Draw the frame used when moving or resizing window.
  */
-static void NC_DrawMovingFrame( HWND hwnd, RECT *rect )
+static void NC_DrawMovingFrame( HDC hdc, RECT *rect, BOOL thickframe )
 {
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    HDC hdc = GetDC( 0 );
-
-    if (HAS_THICKFRAME( wndPtr->dwStyle ))
+    if (thickframe)
     {
 	SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
 	PatBlt( hdc, rect->left, rect->top,
@@ -433,7 +428,6 @@
 	        rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
     }
     else DrawFocusRect( hdc, rect );
-    ReleaseDC( 0, hdc );
 }
 
 
@@ -443,10 +437,12 @@
  * Draw the window caption.
  * The correct pen for the window frame must be selected in the DC.
  */
-static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style )
+static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
+			    DWORD style, BOOL active )
 {
     RECT r = *rect;
     HBRUSH hbrushCaption;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
     char buffer[256];
 
     if (!hbitmapClose)
@@ -461,52 +457,66 @@
 	hbitmapRestoreD  = LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORED) );
     }
     
-    hbrushCaption = CreateSolidBrush( GetSysColor( COLOR_ACTIVECAPTION ) );
+    if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
+    {
+	HBRUSH hbrushWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
+	HBRUSH hbrushOld = SelectObject( hdc, hbrushWindow );
+	PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
+	PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
+	PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
+	r.left++;
+	r.right--;
+	SelectObject( hdc, hbrushOld );
+	DeleteObject( hbrushWindow );
+    }
+
+    if (active)
+	hbrushCaption = CreateSolidBrush( GetSysColor(COLOR_ACTIVECAPTION) );
+    else hbrushCaption = CreateSolidBrush( GetSysColor(COLOR_INACTIVECAPTION));
 
     MoveTo( hdc, r.left, r.bottom );
     LineTo( hdc, r.right-1, r.bottom );
 
     if (style & WS_SYSMENU)
     {
-	NC_DrawSysButton( hwnd, hdc );
+	NC_DrawSysButton( hwnd, hdc, FALSE );
 	r.left += SYSMETRICS_CXSIZE + 1;
 	MoveTo( hdc, r.left - 1, r.top );
 	LineTo( hdc, r.left - 1, r.bottom );
     }
     if (style & WS_MAXIMIZEBOX)
     {
-	NC_DrawMaxButton( hwnd, hdc );
+	NC_DrawMaxButton( hwnd, hdc, FALSE );
 	r.right -= SYSMETRICS_CXSIZE + 1;
     }
     if (style & WS_MINIMIZEBOX)
     {
-	NC_DrawMinButton( hwnd, hdc );
+	NC_DrawMinButton( hwnd, hdc, FALSE );
 	r.right -= SYSMETRICS_CXSIZE + 1;
     }
 
     FillRect( hdc, &r, hbrushCaption );
+    DeleteObject( hbrushCaption );
 
     if (GetWindowText( hwnd, buffer, 256 ))
     {
-	SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
+	if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
+	else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
 	SetBkMode( hdc, TRANSPARENT );
-	DrawText( hdc, buffer, -1, &r,
-		 DT_SINGLELINE | DT_CENTER | DT_VCENTER );
+	DrawText( hdc, buffer, -1, &r, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
     }
-
-    DeleteObject( hbrushCaption );
 }
 
 
 /***********************************************************************
- *           NC_HandleNCPaint
+ *           NC_DoNCPaint
  *
- * Handle a WM_NCPAINT message. Called from DefWindowProc().
+ * Paint the non-client area.
  */
-LONG NC_HandleNCPaint( HWND hwnd, HRGN hrgn )
+static void NC_DoNCPaint( HWND hwnd, HRGN hrgn, BOOL active )
 {
     HDC hdc;
-    RECT rect;
+    RECT rect, rect2;
     HBRUSH hbrushBorder = 0;
     HPEN hpenFrame = 0;
 
@@ -516,13 +526,13 @@
     printf( "NC_HandleNCPaint: %d %d\n", hwnd, hrgn );
 #endif
 
-    if (!wndPtr || !hrgn) return 0;
+    if (!wndPtr || !hrgn) return;
     if (!(wndPtr->dwStyle & (WS_BORDER | WS_DLGFRAME | WS_THICKFRAME)))
-	return 0;  /* Nothing to do! */
+	return;  /* Nothing to do! */
 
     if (hrgn == 1) hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
     else hdc = GetDCEx( hwnd, hrgn, DCX_CACHE | DCX_WINDOW | DCX_INTERSECTRGN);
-    if (!hdc) return 0;
+    if (!hdc) return;
     if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
 		        wndPtr->rectClient.top-wndPtr->rectWindow.top,
 		        wndPtr->rectClient.right-wndPtr->rectWindow.left,
@@ -530,7 +540,7 @@
 	== NULLREGION)
     {
 	ReleaseDC( hwnd, hdc );
-	return 0;
+	return;
     }
 
     rect.top = rect.left = 0;
@@ -539,7 +549,9 @@
 
     hpenFrame = CreatePen( PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME) );
     SelectObject( hdc, hpenFrame );
-    hbrushBorder = CreateSolidBrush( GetSysColor(COLOR_ACTIVEBORDER) );
+    if (active)
+	hbrushBorder = CreateSolidBrush( GetSysColor(COLOR_ACTIVEBORDER) );
+    else hbrushBorder = CreateSolidBrush( GetSysColor(COLOR_INACTIVEBORDER) );
     SelectObject( hdc, hbrushBorder );
 
     if ((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME))
@@ -552,34 +564,36 @@
 	InflateRect( &rect, -1, -1 );
     }
 
-    if ((wndPtr->dwStyle & WS_DLGFRAME) &&
-	((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) || 
-	 !(wndPtr->dwStyle & WS_BORDER))) NC_DrawFrame( hdc, &rect, TRUE );
-    else if (wndPtr->dwStyle & WS_THICKFRAME) NC_DrawFrame(hdc, &rect, FALSE);
+    if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle )) 
+	NC_DrawFrame( hdc, &rect, TRUE );
+    else if (wndPtr->dwStyle & WS_THICKFRAME)
+	NC_DrawFrame(hdc, &rect, FALSE);
 
     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
     {
 	RECT r = rect;
 	rect.top += SYSMETRICS_CYSIZE + 1;
 	r.bottom = rect.top - 1;
-	if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
-	{
-	    HBRUSH hbrushWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
-	    HBRUSH hbrushOld = SelectObject( hdc, hbrushWindow );
-	    PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1, PATCOPY );
-	    PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
-	    PatBlt( hdc, r.left, r.top, r.right-r.left, 1, PATCOPY );
-	    r.left++;
-	    r.right--;
-	    r.top++;
-	    SelectObject( hdc, hbrushOld );
-	    DeleteObject( hbrushWindow );
-	}
-	NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle );
+	NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
     }
 
     if (wndPtr->dwStyle & (WS_VSCROLL | WS_HSCROLL))
     {
+	if (wndPtr->dwStyle & WS_VSCROLL) {
+	    int bottom = rect.bottom;
+	    if (wndPtr->dwStyle & WS_HSCROLL) bottom -= SYSMETRICS_CYHSCROLL;
+	    SetRect(&rect2, rect.right - SYSMETRICS_CXVSCROLL, rect.top,
+		    rect.right, bottom); 
+	    StdDrawScrollBar(hwnd, hdc, SB_VERT, &rect2, (LPHEADSCROLL)wndPtr->VScroll);
+	    }
+	if (wndPtr->dwStyle & WS_HSCROLL) {
+	    int right = rect.right;
+	    if (wndPtr->dwStyle & WS_VSCROLL) right -= SYSMETRICS_CYVSCROLL;
+	    SetRect(&rect2, rect.left, rect.bottom - SYSMETRICS_CYHSCROLL,
+		    right, rect.bottom);
+	    StdDrawScrollBar(hwnd, hdc, SB_HORZ, &rect2, (LPHEADSCROLL)wndPtr->HScroll);
+	    }
+/*
 	HBRUSH hbrushScroll = CreateSolidBrush( GetSysColor(COLOR_SCROLLBAR) );
 	HBRUSH hbrushOld = SelectObject( hdc, hbrushScroll );
 	if (wndPtr->dwStyle & WS_VSCROLL)
@@ -590,16 +604,245 @@
 		    rect.right-rect.left, SYSMETRICS_CYHSCROLL, PATCOPY );
 	SelectObject( hdc, hbrushOld );
 	DeleteObject( hbrushScroll );
+*/
     }    
 
     ReleaseDC( hwnd, hdc );
     if (hbrushBorder) DeleteObject( hbrushBorder );
     if (hpenFrame) DeleteObject( hpenFrame );    
+}
+
+
+/***********************************************************************
+ *           NC_HandleNCPaint
+ *
+ * Handle a WM_NCPAINT message. Called from DefWindowProc().
+ */
+LONG NC_HandleNCPaint( HWND hwnd, HRGN hrgn )
+{
+    NC_DoNCPaint( hwnd, hrgn, (hwnd == GetActiveWindow()) );
     return 0;
 }
 
 
 /***********************************************************************
+ *           NC_HandleNCActivate
+ *
+ * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
+ */
+LONG NC_HandleNCActivate( HWND hwnd, WORD wParam )
+{
+    NC_DoNCPaint( hwnd, (HRGN)1, wParam );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           NC_DoSizeMove
+ *
+ * Perform SC_MOVE and SC_SIZE commands.
+ */
+static void NC_DoSizeMove( HWND hwnd, WORD wParam, POINT pt )
+{
+    MSG msg;
+    WORD hittest;
+    RECT sizingRect;
+    HDC hdc;
+    BOOL thickframe;
+    POINT minTrack, maxTrack, capturePoint = pt;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (IsZoomed(hwnd) || IsIconic(hwnd) || !IsWindowVisible(hwnd)) return;
+    hittest = wParam & 0x0f;
+    thickframe = HAS_THICKFRAME( wndPtr->dwStyle );
+
+    if ((wParam & 0xfff0) == SC_MOVE)
+    {
+	if (!(wndPtr->dwStyle & WS_CAPTION)) return;
+	if (!hittest)
+	{
+	      /* Move pointer at the center of the caption */
+	    RECT rect;
+	    POINT point;
+	    NC_GetInsideRect( hwnd, &rect );
+	    if (wndPtr->dwStyle & WS_SYSMENU)
+		rect.left += SYSMETRICS_CXSIZE + 1;
+	    if (wndPtr->dwStyle & WS_MINIMIZEBOX)
+		rect.right -= SYSMETRICS_CXSIZE + 1;
+	    if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
+		rect.right -= SYSMETRICS_CXSIZE + 1;
+	    point.x = wndPtr->rectWindow.left + (rect.right - rect.left) / 2;
+	    point.y = wndPtr->rectWindow.top + rect.top + SYSMETRICS_CYSIZE/2;
+	    if (wndPtr->dwStyle & WS_CHILD)
+		ClientToScreen( wndPtr->hwndParent, &point );
+	    SetCursorPos( point.x, point.y );
+	    hittest = HTCAPTION;
+	    capturePoint = point;
+	}
+    }
+    else  /* SC_SIZE */
+    {
+	if (!thickframe) return;
+	if (hittest) hittest += HTLEFT-1;
+    }
+
+    WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
+    SendMessage( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
+
+    if (wndPtr->dwStyle & WS_CHILD) hdc = GetDC( wndPtr->hwndParent );
+    else
+    {  /* Grab the server only when moving top-level windows */
+	hdc = GetDC( 0 );
+	XGrabServer( display );
+    }
+    SetCapture( hwnd );    
+    sizingRect = wndPtr->rectWindow;
+    NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
+
+    while(1)
+    {
+	int dx = 0, dy = 0;
+
+	MSG_GetHardwareMessage( &msg );
+
+	  /* Exit on button-up, Return, or Esc */
+	if ((msg.message == WM_LBUTTONUP) ||
+	    ((msg.message == WM_KEYDOWN) && 
+	     ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
+
+	if (wndPtr->dwStyle & WS_CHILD)
+	    ScreenToClient( wndPtr->hwndParent, &msg.pt );
+
+	switch(msg.message)
+	{
+	case WM_MOUSEMOVE:
+	    dx = msg.pt.x - capturePoint.x;
+	    dy = msg.pt.y - capturePoint.y;
+	    break;
+
+	case WM_KEYDOWN:
+	    switch(msg.wParam)
+	    {
+	        case VK_UP:    msg.pt.y -= 8; break;
+		case VK_DOWN:  msg.pt.y += 8; break;
+		case VK_LEFT:  msg.pt.x -= 8; break;
+		case VK_RIGHT: msg.pt.x += 8; break;		
+	    }
+	    SetCursorPos( msg.pt.x, msg.pt.y );
+	    break;
+	}	
+
+	if (dx || dy)
+	{
+	    RECT newRect = sizingRect;
+	    switch(hittest)
+	    {
+	    case HTCAPTION:
+		OffsetRect( &newRect, dx, dy );
+		break;
+	    case HTLEFT:
+		newRect.left += dx;
+		break;
+	    case HTRIGHT:
+		newRect.right += dx;
+		break;
+	    case HTTOP:
+		newRect.top += dy;
+		break;
+	    case HTTOPLEFT:
+		newRect.left += dx;
+		newRect.top  += dy;
+		break;
+	    case HTTOPRIGHT:
+		newRect.right += dx;
+		newRect.top   += dy;
+		break;
+	    case HTBOTTOM:
+		newRect.bottom += dy;
+		break;
+	    case HTBOTTOMLEFT:
+		newRect.left   += dx;
+		newRect.bottom += dy;
+		break;
+	    case HTBOTTOMRIGHT:
+		newRect.right  += dx;
+		newRect.bottom += dy;
+		break; 
+	    }	    
+	    NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
+	    NC_DrawMovingFrame( hdc, &newRect, thickframe );
+	    capturePoint = msg.pt;
+	    sizingRect = newRect;
+	}
+    }
+
+    NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
+    ReleaseCapture();
+    if (wndPtr->dwStyle & WS_CHILD) ReleaseDC( wndPtr->hwndParent, hdc );
+    else
+    {
+	ReleaseDC( 0, hdc );
+	XUngrabServer( display );
+    }
+    SendMessage( hwnd, WM_EXITSIZEMOVE, 0, 0 );
+
+      /* If Esc key, don't move the window */
+    if ((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) return;
+
+    if (hittest != HTCAPTION)
+	SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
+		     sizingRect.right - sizingRect.left,
+		     sizingRect.bottom - sizingRect.top,
+		     SWP_NOACTIVATE | SWP_NOZORDER );
+    else SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, 0, 0,
+		      SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
+}
+
+
+/***********************************************************************
+ *           NC_TrackMinMaxBox
+ *
+ * Track a mouse button press on the minimize or maximize box.
+ */
+static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
+{
+    MSG msg;
+    HDC hdc = GetWindowDC( hwnd );
+    BOOL pressed = TRUE;
+
+    SetCapture( hwnd );
+    if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, TRUE );
+    else NC_DrawMaxButton( hwnd, hdc, TRUE );
+
+    do
+    {
+	BOOL oldstate = pressed;
+	MSG_GetHardwareMessage( &msg );
+
+	pressed = (NC_InternalNCHitTest( hwnd, msg.pt ) == wParam);
+	if (pressed != oldstate)
+	{
+	    if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, pressed );
+	    else NC_DrawMaxButton( hwnd, hdc, pressed );	    
+	}
+    } while (msg.message != WM_LBUTTONUP);
+
+    if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, FALSE );
+    else NC_DrawMaxButton( hwnd, hdc, FALSE );
+
+    ReleaseCapture();
+    ReleaseDC( hwnd, hdc );
+    if (!pressed) return;
+
+    if (wParam == HTMINBUTTON) 
+	SendMessage( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&msg.pt );
+    else
+	SendMessage( hwnd, WM_SYSCOMMAND, 
+		  IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, *(LONG*)&msg.pt );
+}
+
+
+/***********************************************************************
  *           NC_HandleNCLButtonDown
  *
  * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
@@ -611,39 +854,28 @@
     switch(wParam)  /* Hit test */
     {
     case HTCAPTION:
-	if (GetCapture() != hwnd)
-	    SendMessage( hwnd, WM_SYSCOMMAND, SC_MOVE, lParam );
+	SendMessage( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
 	break;
 
     case HTSYSMENU:
-	captureHitTest = wParam;
-	SetCapture( hwnd );
-	NC_DrawSysButton( hwnd, hdc );
+	NC_DrawSysButton( hwnd, hdc, TRUE );
+	NC_TrackSysMenu(hwnd);
 	break;
 
     case HTMENU:
 	break;
 
     case HTHSCROLL:
-	if (GetCapture() != hwnd)
-	    SendMessage( hwnd, WM_SYSCOMMAND, SC_HSCROLL, lParam );
+	SendMessage( hwnd, WM_SYSCOMMAND, SC_HSCROLL, lParam );
 	break;
 
     case HTVSCROLL:
-	if (GetCapture() != hwnd)
-	    SendMessage( hwnd, WM_SYSCOMMAND, SC_VSCROLL, lParam );
+	SendMessage( hwnd, WM_SYSCOMMAND, SC_VSCROLL, lParam );
 	break;
 
     case HTMINBUTTON:
-	captureHitTest = wParam;
-	SetCapture( hwnd );
-	NC_DrawMinButton( hwnd, hdc );
-	break;
-
     case HTMAXBUTTON:
-	captureHitTest = wParam;
-	SetCapture( hwnd );
-	NC_DrawMaxButton( hwnd, hdc );
+	NC_TrackMinMaxBox( hwnd, wParam );
 	break;
 
     case HTLEFT:
@@ -654,9 +886,7 @@
     case HTBOTTOM:
     case HTBOTTOMLEFT:
     case HTBOTTOMRIGHT:
-	if (GetCapture() != hwnd)
-	    SendMessage( hwnd, WM_SYSCOMMAND,
-			 SC_SIZE + wParam - HTLEFT + 1, lParam );
+	SendMessage( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - HTLEFT+1, lParam);
 	break;
 
     case HTBORDER:
@@ -669,79 +899,6 @@
 
 
 /***********************************************************************
- *           NC_HandleNCLButtonUp
- *
- * Handle a WM_NCLBUTTONUP message. Called from DefWindowProc().
- */
-LONG NC_HandleNCLButtonUp( HWND hwnd, WORD wParam, LONG lParam )
-{
-    HDC hdc;
-    WORD hittest;
-
-    if (hwnd != GetCapture()) return 0;
-
-    ReleaseCapture();
-    captureHitTest = HTCLIENT;
-    hdc = GetWindowDC( hwnd );
-    hittest = NC_InternalNCHitTest( hwnd, MAKEPOINT(lParam) );
-
-    switch(wParam)  /* Hit test */
-    {
-    case HTCAPTION:  /* End of window moving */
-	NC_DrawMovingFrame( hwnd, &sizingRect );
-	SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, 0, 0,
-		      SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
-	break;
-
-    case HTSYSMENU:
-	NC_DrawSysButton( hwnd, hdc );
-	break;
-
-    case HTMENU:
-    case HTHSCROLL:
-    case HTVSCROLL:
-	break;
-
-    case HTMINBUTTON:
-	NC_DrawMinButton( hwnd, hdc );
-	if (hittest == HTMINBUTTON)
-	    SendMessage( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, lParam );
-	break;
-
-    case HTMAXBUTTON:
-	NC_DrawMaxButton( hwnd, hdc );
-	if (hittest == HTMAXBUTTON)
-	{
-	    if (IsZoomed(hwnd))
-		SendMessage( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
-	    else SendMessage( hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, lParam );
-	}
-	break;
-
-    case HTLEFT:
-    case HTRIGHT:
-    case HTTOP:
-    case HTTOPLEFT:
-    case HTTOPRIGHT:
-    case HTBOTTOM:
-    case HTBOTTOMLEFT:
-    case HTBOTTOMRIGHT:  /* End of window resizing */
-	NC_DrawMovingFrame( hwnd, &sizingRect );
-	SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
-		      sizingRect.right - sizingRect.left,
-		      sizingRect.bottom - sizingRect.top,
-		      SWP_NOACTIVATE | SWP_NOZORDER );
-	break;
-
-    case HTBORDER:
-	    break;
-    }
-    ReleaseDC( hwnd, hdc );
-    return 0;
-}
-
-
-/***********************************************************************
  *           NC_HandleNCLButtonDblClk
  *
  * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
@@ -763,73 +920,6 @@
 
 
 /***********************************************************************
- *           NC_HandleNCMouseMove
- *
- * Handle a WM_NCMOUSEMOVE message. Called from DefWindowProc().
- */
-LONG NC_HandleNCMouseMove( HWND hwnd, WORD wParam, POINT pt )
-{
-    RECT newRect;
-
-    if (hwnd != GetCapture()) return 0;
-    newRect = sizingRect;
-
-    switch(wParam)  /* Hit test */
-    {
-    case HTCAPTION:
-	OffsetRect( &newRect, pt.x - capturePoint.x, pt.y - capturePoint.y);
-	break;
-
-    case HTLEFT:
-	newRect.left += pt.x - capturePoint.x;
-	break;
-
-    case HTRIGHT:
-	newRect.right += pt.x - capturePoint.x;
-	break;
-
-    case HTTOP:
-	newRect.top += pt.y - capturePoint.y;
-	break;
-
-    case HTTOPLEFT:
-	newRect.left += pt.x - capturePoint.x;
-	newRect.top  += pt.y - capturePoint.y;
-	break;
-
-    case HTTOPRIGHT:
-	newRect.right += pt.x - capturePoint.x;
-	newRect.top   += pt.y - capturePoint.y;
-	break;
-
-    case HTBOTTOM:
-	newRect.bottom += pt.y - capturePoint.y;
-	break;
-
-    case HTBOTTOMLEFT:
-	newRect.left   += pt.x - capturePoint.x;
-	newRect.bottom += pt.y - capturePoint.y;
-	break;
-
-    case HTBOTTOMRIGHT:
-	newRect.right  += pt.x - capturePoint.x;
-	newRect.bottom += pt.y - capturePoint.y;
-	break;
- 
-    default:
-	return 0;  /* Nothing to do */
-   }
-
-    NC_DrawMovingFrame( hwnd, &sizingRect );
-    NC_DrawMovingFrame( hwnd, &newRect );
-    capturePoint = pt;
-    sizingRect = newRect;
-
-    return 0;
-}
-
-
-/***********************************************************************
  *           NC_HandleSysCommand
  *
  * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
@@ -842,27 +932,13 @@
     printf( "Handling WM_SYSCOMMAND %x %d,%d\n", wParam, pt.x, pt.y );
 #endif
 
+    if (wndPtr->dwStyle & WS_CHILD) ScreenToClient( wndPtr->hwndParent, &pt );
+
     switch (wParam & 0xfff0)
     {
     case SC_SIZE:
-	if (!HAS_THICKFRAME(wndPtr->dwStyle)) break;
-	if (IsZoomed(hwnd) || IsIconic(hwnd)) break;
-	if (wParam & 0x0f) captureHitTest = (wParam & 0x0f) + HTLEFT - 1;
-	else captureHitTest = HTBORDER;
-	capturePoint = pt;
-	SetCapture( hwnd );
-	GetWindowRect( hwnd, &sizingRect );
-	NC_DrawMovingFrame( hwnd, &sizingRect );
-	break;
-
     case SC_MOVE:
-	if (!(wndPtr->dwStyle & WS_CAPTION)) break;
-	if (IsZoomed(hwnd) || IsIconic(hwnd)) break;
-	captureHitTest = HTCAPTION;
-	capturePoint = pt;
-	SetCapture( hwnd );
-	GetWindowRect( hwnd, &sizingRect );
-	NC_DrawMovingFrame( hwnd, &sizingRect );
+	NC_DoSizeMove( hwnd, wParam, pt );
 	break;
 
     case SC_MINIMIZE:
@@ -886,6 +962,7 @@
 
     case SC_VSCROLL:
     case SC_HSCROLL:
+	break;
     case SC_MOUSEMENU:
     case SC_KEYMENU:
     case SC_ARRANGE:
@@ -956,3 +1033,5 @@
     SetCursor( LoadCursor( 0, IDC_ARROW ) );
     return TRUE;
 }
+
+
diff --git a/windows/timer.c b/windows/timer.c
index da64961..2a40bec 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -142,7 +142,10 @@
     pTimer->proc    = proc;
     TIMER_InsertTimer( pTimer );
     MSG_IncTimerCount( GetTaskQueue(0) );
-    return id;
+    if (!id)
+	return TRUE;
+    else
+	return id;
 }
 
 
diff --git a/windows/win.c b/windows/win.c
index 95730dd..5cef378 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -16,11 +16,13 @@
 #include "user.h"
 #include "dce.h"
 #include "sysmetrics.h"
+#include "scroll.h"
 
 extern Display * display;
 extern Colormap COLOR_WinColormap;
 
 extern void EVENT_RegisterWindow( Window w, HWND hwnd );  /* event.c */
+extern HMENU CopySysMenu(); /* menu.c */
 
 HWND firstWindow = 0;
 
@@ -256,10 +258,10 @@
     wndPtr->hText             = 0;
     wndPtr->flags             = 0;
     wndPtr->hCursor           = 0;
-    wndPtr->hWndVScroll       = 0;
-    wndPtr->hWndHScroll       = 0;
+    wndPtr->VScroll           = NULL;
+    wndPtr->HScroll           = NULL;
+    wndPtr->hSysMenu          = 0;
     wndPtr->hWndMenuBar       = 0;
-    wndPtr->hWndCaption       = 0;
 
     if (classPtr->wc.cbWndExtra)
 	memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
@@ -311,8 +313,8 @@
 
       /* Send the WM_CREATE message */
 	
-    hcreateStruct = GlobalAlloc( GMEM_MOVEABLE, sizeof(CREATESTRUCT) );
-    createStruct = (CREATESTRUCT *) GlobalLock( hcreateStruct );
+    hcreateStruct = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(CREATESTRUCT) );
+    createStruct = (CREATESTRUCT *) USER_HEAP_ADDR( hcreateStruct );
     createStruct->lpCreateParams = data;
     createStruct->hInstance      = instance;
     createStruct->hMenu          = menu;
@@ -333,22 +335,20 @@
 	  /* Send WM_NCCALCSIZE message */
 	NCCALCSIZE_PARAMS *params;
 	HANDLE hparams;
-	hparams = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) );
+	hparams = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(*params) );
 	if (hparams)
 	{
-	    params = (NCCALCSIZE_PARAMS *) GlobalLock( hparams );
+	    params = (NCCALCSIZE_PARAMS *) USER_HEAP_ADDR( hparams );
 	    params->rgrc[0] = wndPtr->rectWindow;
 	    params->lppos = NULL;
 	    SendMessage( hwnd, WM_NCCALCSIZE, FALSE, (LONG)params );
 	    wndPtr->rectClient = params->rgrc[0];
-	    GlobalUnlock( hparams );
-	    GlobalFree( hparams );
+	    USER_HEAP_FREE( hparams );
 	}	
 	wmcreate = SendMessage( hwnd, WM_CREATE, 0, (LONG)createStruct );
     }
 
-    GlobalUnlock( hcreateStruct );
-    GlobalFree( hcreateStruct );
+    USER_HEAP_FREE( hcreateStruct );
 
     if (wmcreate == -1)
     {
@@ -364,14 +364,9 @@
 
       /* Create scrollbars */
 
-#if 0
-    if (windowName != NULL) SetWindowText(hwnd, windowName);
-    if ((style & WS_CAPTION) == WS_CAPTION) {
-	wndPtr->hWndCaption = CreateWindow("CAPTION", "",
-		WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
-		0, -20, width, 20, hwnd, 1, instance, 0L);
+    if ((style & WS_SYSMENU) == WS_SYSMENU) {
+	wndPtr->hSysMenu = CopySysMenu();
 	}
-#endif
     if (((style & WS_CHILD) != WS_CHILD) && (wndPtr->wIDmenu != 0)) {
 	lpbar = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
 	if (lpbar != NULL) {
@@ -381,25 +376,11 @@
 		0, 0, width, 20, hwnd, 2, instance, (LPSTR)lpbar);
 	    }
 	}
-    if ((style & WS_VSCROLL) == WS_VSCROLL)
-    {
-	wndPtr->hWndVScroll = CreateWindow("SCROLLBAR", "",
-		WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_VERT,
-		wndPtr->rectClient.right-wndPtr->rectClient.left, 0,
-                SYSMETRICS_CXVSCROLL,
-		wndPtr->rectClient.bottom-wndPtr->rectClient.top,
-                hwnd, 3, instance, 0L);
-    }
-    if ((style & WS_HSCROLL) == WS_HSCROLL)
-    {
-	wndPtr->hWndHScroll = CreateWindow("SCROLLBAR", "",
-		WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_HORZ,
-		0, wndPtr->rectClient.bottom-wndPtr->rectClient.top,
-                wndPtr->rectClient.right-wndPtr->rectClient.left,
-		SYSMETRICS_CYHSCROLL,
-                hwnd, 4, instance, 0L);
-    }
-
+      /* Create scrollbars */
+    if ((style & WS_VSCROLL) == WS_VSCROLL ||
+	(style & WS_HSCROLL) == WS_HSCROLL) {
+    	NC_CreateScrollBars(hwnd);
+	}
     EVENT_RegisterWindow( wndPtr->window, hwnd );
 
     WIN_SendParentNotify( hwnd, wndPtr, WM_CREATE );
@@ -429,8 +410,8 @@
     
       /* Destroy all children */
 
-    if (wndPtr->hWndVScroll) DestroyWindow(wndPtr->hWndVScroll);
-    if (wndPtr->hWndHScroll) DestroyWindow(wndPtr->hWndHScroll);
+    if (wndPtr->VScroll) free(wndPtr->VScroll);
+    if (wndPtr->HScroll) free(wndPtr->HScroll);
     while (wndPtr->hwndChild)  /* The child removes itself from the list */
 	DestroyWindow( wndPtr->hwndChild );
 
@@ -445,6 +426,9 @@
     if (wndPtr->flags & WIN_OWN_DC) DCE_FreeDCE( wndPtr->hdce );
     classPtr->cWindows--;
     USER_HEAP_FREE( hwnd );
+/*
+    printf("End of DestroyWindow // hwnd=%04X !\n", hwnd);
+*/
     return TRUE;
 }
 
@@ -493,25 +477,6 @@
     }
 }
 
-/**********************************************************************
- *	     GetMenu	    (USER.157)
- */
-HMENU GetMenu( HWND hwnd ) 
-{ 
-    WND * wndPtr = WIN_FindWndPtr(hwnd);
-    if (wndPtr == NULL)
-	return 0;
-    return wndPtr->wIDmenu;
-}
-
-/**********************************************************************
- *           SetMenu        (USER.158)
- */
-BOOL SetMenu(HWND hwnd, HMENU hmenu)
-{
-    return FALSE;
-}
-
 
 /**********************************************************************
  *           GetDesktopWindow        (USER.286)
@@ -842,3 +807,127 @@
     if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
     return GetWindow( hwnd, flag );
 }
+
+
+
+
+/*******************************************************************
+ *    EnumWindows             (USER.54)
+ * 
+ *  o gets the desktop window and iterates over all the windows
+ *    which are direct decendents of the desktop * by iterating over
+ *    the desktop's child window and all the child windows next
+ *    pointers
+ *
+ *  o call wndenumprc for every child window the desktop has
+ *    (parameters to Callback16 passed backwards so they are
+ *    put in in pascal calling order)
+ *
+ *  o if wndenumprc returns 0 exit
+ * 
+ *  * remove the HAS_DESKTOP_WINDOW ifdef when the GetDesktopWindow() call
+ *    is fixed to actually return the desktop window
+ * 
+ */
+BOOL EnumWindows(FARPROC wndenumprc, LPARAM lParam)
+{
+    HWND hwnd = GetDesktopWindow(); 
+    WND *wndPtr;
+    int result;
+
+#ifdef DEBUG_ENUM
+    printf("EnumWindows\n");
+#endif 
+#ifdef HAS_DESKTOP_WINDOW 
+    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+    hwnd = wndPtr->hwndChild;
+#else
+    hwnd = firstWindow;
+#endif
+
+    while (hwnd) {
+      char *ptr;
+
+        if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
+              return 0;
+      }
+#ifdef DEBUG_ENUM
+      if (XFetchName(display, wndPtr->window, &ptr) && ptr)
+              printf("found a window (%s)\n", ptr);
+      else 
+              printf("found nameless parent window\n");
+#endif 
+      result = CallBack16(wndenumprc, 2, lParam, (int) hwnd);
+      if ( ! result )  {
+              return 0;
+      }
+      hwnd=wndPtr->hwndNext;
+    }
+    return 1; /* for now */
+}
+
+/*******************************************************************
+ *    WIN_EnumChildWin
+ *
+ *   o hwnd is the first child to use, loop until all next windows
+ *     are processed
+ * 
+ *   o call wdnenumprc with parameters in inverse order (pascal)
+ *
+ *   o call ourselves with the next child window
+ * 
+ */
+static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
+{
+    WND *wndPtr;
+    int result;
+
+
+    while (hwnd) {
+      char *ptr;
+      if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
+            return 0;
+        }
+#ifdef DEBUG_ENUM
+      if (XFetchName(display, wndPtr->window, &ptr) && ptr)
+              printf("EnumChild: found a child window (%s)\n", ptr);
+      else 
+              printf("EnumChild: nameless child\n");
+      
+        if (!(wndPtr->dwStyle & WS_CHILD)) {
+           printf("this is not a child window!  What is it doing here?\n");
+           return 0;
+      }
+#endif
+        if (!CallBack16(wndenumprc, 2, lParam, (int) hwnd)) {
+                return 0;
+      }
+      if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) {
+          return 0;
+      }
+        hwnd=wndPtr->hwndNext;
+    } 
+    return 1;
+}
+
+/*******************************************************************
+ *    EnumChildWindows        (USER.55)
+ *
+ *   o gets the first child of hwnd
+ *
+ *   o calls WIN_EnumChildWin to do a recursive decent of child windows
+ */
+BOOL EnumChildWindows(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
+{
+    WND *wndPtr;
+
+#ifdef DEBUG_ENUM
+    printf("EnumChildWindows\n");
+#endif
+
+    if (hwnd == 0) return 0;
+    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+    hwnd = wndPtr->hwndChild;
+    return WIN_EnumChildWin(hwnd, wndenumprc, lParam);         
+}
+
diff --git a/windows/winpos.c b/windows/winpos.c
index ad23161..49d091f 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -6,10 +6,14 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#include "sysmetrics.h"
+#include "user.h"
 #include "win.h"
 
 extern Display * display;
 
+static HWND hwndActive = 0;  /* Currently active window */
+
 
 /***********************************************************************
  *           GetWindowRect   (USER.32)
@@ -156,6 +160,28 @@
 }
 
 
+/*******************************************************************
+ *         GetActiveWindow    (USER.60)
+ */
+HWND GetActiveWindow()
+{
+    return hwndActive;
+}
+
+
+/*******************************************************************
+ *         SetActiveWindow    (USER.59)
+ */
+HWND SetActiveWindow( HWND hwnd )
+{
+    HWND prev = hwndActive;
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return 0;
+    SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
+    return prev;
+}
+
+
 /***********************************************************************
  *           BringWindowToTop   (USER.45)
  */
@@ -204,6 +230,7 @@
 
 	case SW_SHOWMINNOACTIVE:
 	case SW_SHOWMINIMIZED:
+	case SW_SHOWMAXIMIZED:
 	case SW_MINIMIZE:
 	    wndPtr->dwStyle |= WS_MINIMIZE;
 	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
@@ -211,15 +238,23 @@
 	    break;
 
 	case SW_SHOWNA:
-	case SW_SHOWNOACTIVATE:
 	case SW_MAXIMIZE:
-	case SW_SHOWMAXIMIZED:
 	case SW_SHOW:
+	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+	    break;
+
 	case SW_NORMAL:
 	case SW_SHOWNORMAL:
+	case SW_SHOWNOACTIVATE:
+	case SW_RESTORE:
 	    wndPtr->dwStyle &= ~WS_MINIMIZE;
-	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
-		        SWP_NOACTIVATE | SWP_NOZORDER;
+	    wndPtr->dwStyle &= ~WS_MAXIMIZE;
+	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+	    if (cmd == SW_SHOWNOACTIVATE)
+	    {
+		swpflags |= SWP_NOZORDER;
+		if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
+	    }
 	    break;
     }
     SendMessage( hwnd, WM_SHOWWINDOW, (cmd != SW_HIDE), 0 );
@@ -311,10 +346,76 @@
 }
 
 
+/*******************************************************************
+ *         WINPOS_GetMinMaxInfo
+ *
+ * Send a WM_GETMINMAXINFO to the window.
+ */
+void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
+			   POINT *minTrack, POINT *maxTrack )
+{
+    HANDLE minmaxHandle;
+    MINMAXINFO MinMax, *pMinMax;
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+    MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
+    MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
+    MinMax.ptMaxPosition = wndPtr->ptMaxPos;
+    MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
+    MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
+    MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
+    MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
+
+    minmaxHandle = USER_HEAP_ALLOC( LMEM_MOVEABLE, sizeof(MINMAXINFO) );
+    if (minmaxHandle)
+    {
+	pMinMax = (MINMAXINFO *) USER_HEAP_ADDR( minmaxHandle );
+	memcpy( pMinMax, &MinMax, sizeof(MinMax) );	
+	SendMessage( hwnd, WM_GETMINMAXINFO, 0, (LONG)pMinMax );
+    }
+    else pMinMax = &MinMax;
+
+    if (maxSize) *maxSize = pMinMax->ptMaxSize;
+    if (maxPos) *maxPos = pMinMax->ptMaxPosition;
+    if (minTrack) *minTrack = pMinMax->ptMinTrackSize;
+    if (maxTrack) *maxTrack = pMinMax->ptMaxTrackSize;
+    if (minmaxHandle) USER_HEAP_FREE( minmaxHandle );
+}
+
+
+/*******************************************************************
+ *         WINPOS_ChangeActiveWindow
+ *
+ * Change the active window and send the corresponding messages.
+ */
+HWND WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg )
+{
+    HWND prevActive = hwndActive;
+    if (hwnd == hwndActive) return 0;
+    if (hwndActive)
+    {
+	if (!SendMessage( hwndActive, WM_NCACTIVATE, FALSE, 0 )) return 0;
+	SendMessage( hwndActive, WM_ACTIVATE, WA_INACTIVE,
+		     MAKELONG( IsIconic(hwndActive), hwnd ) );
+	/* Send WM_ACTIVATEAPP here */
+    }
+
+    hwndActive = hwnd;
+    if (hwndActive)
+    {
+	/* Send WM_ACTIVATEAPP here */
+	SendMessage( hwnd, WM_NCACTIVATE, TRUE, 0 );
+	SendMessage( hwnd, WM_ACTIVATE, mouseMsg ? WA_CLICKACTIVE : WA_ACTIVE,
+		     MAKELONG( IsIconic(hwnd), prevActive ) );
+    }
+    return prevActive;
+}
+
+
 /***********************************************************************
  *           SetWindowPos   (USER.232)
  */
-/* Unimplemented flags: SWP_NOREDRAW, SWP_NOACTIVATE
+/* Unimplemented flags: SWP_NOREDRAW
  */
 /* Note: all this code should be in the DeferWindowPos() routines,
  * and SetWindowPos() should simply call them.  This will be implemented
@@ -342,8 +443,9 @@
 
       /* Send WM_WINDOWPOSCHANGING message */
 
-    if (!(hmem = GlobalAlloc( GMEM_MOVEABLE,sizeof(WINDOWPOS) ))) return FALSE;
-    winPos = (WINDOWPOS *)GlobalLock( hmem );
+    if (!(hmem = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(WINDOWPOS) )))
+	return FALSE;
+    winPos = (WINDOWPOS *)USER_HEAP_ADDR( hmem );
     winPos->hwnd = hwnd;
     winPos->hwndInsertAfter = hwndInsertAfter;
     winPos->x = x;
@@ -398,16 +500,15 @@
 	NCCALCSIZE_PARAMS *params;
 	HANDLE hparams;
 	
-	if (!(hparams = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) )))
+	if (!(hparams = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(*params) )))
 	    goto Abort;
-	params = (NCCALCSIZE_PARAMS *) GlobalLock( hparams );
+	params = (NCCALCSIZE_PARAMS *) USER_HEAP_ADDR( hparams );
 	params->rgrc[0] = newWindowRect;
 	params->rgrc[1] = wndPtr->rectWindow;
 	params->rgrc[2] = wndPtr->rectClient;
 	params->lppos = winPos;
 	calcsize_result = SendMessage(hwnd, WM_NCCALCSIZE, TRUE, (LONG)params);
-	GlobalUnlock( hparams );
-	GlobalFree( hparams );
+	USER_HEAP_FREE( hparams );
 	newClientRect = params->rgrc[0];
 	/* Handle result here */
     }
@@ -470,6 +571,12 @@
 	XUnmapWindow( display, wndPtr->window );
     }
 
+    if (!(winPos->flags & SWP_NOACTIVATE))
+    {
+	if (!(wndPtr->dwStyle & WS_CHILD))
+	    WINPOS_ChangeActiveWindow( hwnd, FALSE );
+    }
+    
       /* Send WM_NCPAINT message if needed */
     if ((winPos->flags & (SWP_FRAMECHANGED | SWP_SHOWWINDOW)) ||
 	(!(winPos->flags & SWP_NOSIZE)) ||
@@ -482,18 +589,11 @@
     wndPtr->rectWindow = newWindowRect;
     wndPtr->rectClient = newClientRect;
     SendMessage( hwnd, WM_WINDOWPOSCHANGED, 0, (LONG)winPos );
-    GlobalUnlock( hmem );
-    GlobalFree( hmem );
+    USER_HEAP_FREE( hmem );
 
     return TRUE;
 
  Abort:  /* Fatal error encountered */
-    if (hmem)
-    {
-	GlobalUnlock( hmem );
-	GlobalFree( hmem );
-    }
+    if (hmem) USER_HEAP_FREE( hmem );
     return FALSE;
 }
-
-
diff --git a/wine.ini b/wine.ini
index a06ea5c..d8755c4 100644
--- a/wine.ini
+++ b/wine.ini
@@ -22,7 +22,7 @@
 
 [spy]
 ;;;;; Uncomment the following line to activate spying to the console ;;;;;
-;File=CON
+File=CON
 
 ;;;;; Uncomment the following line to activate spying to the spy.log ;;;;;
 ;File=spy.log