Release 970101

Wed Jan  1 15:36:17 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/listbox.c]
	Use FindFirstFile/FindNextFile in LISTBOX_Directory.

	* [files/dos_fs.c]
	Rewrote FindFirstFile/FindNextFile to use DOSFS_FindNext().

	* [files/file.c] [files/directory.c]
	Use Win32 kernel objects and handles for file handles.
	Unified SearchPath() and OpenFile().

	* [loader/builtin.c]
	Moved to if1632/ directory.

	* [tools/build.c] [debugger/*] [miscemu/*]
	Win16 register functions now receive the same CONTEXT * structure
	as Win32 functions.

	* [include/sigcontext.h] [miscemu/instr.c]
	Added new macros to get register values from the SIGCONTEXT
	structure (only used for instruction emulation now).

	* [scheduler/process.c] [scheduler/thread.c] (New files)
	Allocate process and thread structures.

	* [scheduler/process.c] [win32/k32obj.c]
	Added Win32 kernel objects and handles management.

	* [loader/task.c]
	Create a Win32 process and thread for every Win16 task.

	* [misc/commdlg.c] [misc/shell.c] [windows/msgbox.c]
	Built-in resources are now in Win32 format. This also avoids
	16-bit callbacks for built-in dialogs.

	* [misc/lzexpand.c]
	Differentiate between 16-bit and 32-bit file handles.

	* [miscemu/int*.c]
	Moved all int emulation to msdos/ directory.

	* [msdos/*]
	New directory msdos/ contains all MS-DOS emulation code that can
	also be used for Winelib; this should enable Winelib apps to use
	DOS3Call and related functions.

	* [rc/winerc.c]
	A few bug fixes for Win32 resource format.

	* [windows/winpos.c]
	Hack in WINPOS_ReorderOwnerPopups() to avoid X crashed (still not
	right though).

Sun Dec 29 17:47:55 1996  O. Flebbe <flebbe@science-computing.uni-tuebingen.de>

	* [loader/pe_image.c]
	Make sure BSS of a PE_Image is zero.

Sat Dec 28 22:15:34 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [windows/scroll.c]
	ScrollWindowEx() rewrite, ScrollDC() fix.

	* [windows/nonclient.c] [controls/menu.c]
	Fixed Alt-Space crashes in dialogs.

	* [windows/event.c] [windows/message.c]
	Some changes in mouse message generation.

Thu Dec 26 09:25:24 1996  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [debugger/stabs.c]
	Dummy DEBUG_ReadExecutableDbgInfo provided for !__ELF__ case.

Tue Dec 24 00:59:05 MET 1996  Martin Buck <martin-2.buck@student.uni-ulm.de>

	* [windows/event.c]
	Changed XK_Page_{Up,Down} to XK_{Prior,Next} for X11R5
	compatibility.
diff --git a/windows/caret.c b/windows/caret.c
index ca11b7e..da49ee4 100644
--- a/windows/caret.c
+++ b/windows/caret.c
@@ -11,7 +11,6 @@
 /* #define DEBUG_CARET */
 #include "debug.h"
 
-
 typedef struct
 {
     HWND32     hwnd;
@@ -35,16 +34,24 @@
 
 static CARET Caret = { 0, 0, FALSE, 0, 0, 2, 12, 0, 500, 0 };
 
-
 /*****************************************************************
  *              CARET_GetHwnd
  */
-HWND32 CARET_GetHwnd()
+HWND32 CARET_GetHwnd(void)
 {
     return Caret.hwnd;
 }
 
 /*****************************************************************
+ *              CARET_GetRect
+ */
+void CARET_GetRect(LPRECT32 lprc)
+{
+    lprc->right = (lprc->left = Caret.x) + Caret.width - 1;
+    lprc->bottom = (lprc->top = Caret.y) + Caret.height - 1;
+}
+
+/*****************************************************************
  *               CARET_DisplayCaret
  */
 static void CARET_DisplayCaret( DISPLAY_CARET status )
diff --git a/windows/dialog.c b/windows/dialog.c
index bd03f44..20437e1 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -458,9 +458,10 @@
 /***********************************************************************
  *           DIALOG_CreateIndirect
  */
-static HWND DIALOG_CreateIndirect( HINSTANCE32 hInst, LPCSTR dlgTemplate,
-                                   HWND owner, DLGPROC16 dlgProc,
-                                   LPARAM param, WINDOWPROCTYPE procType )
+HWND32 DIALOG_CreateIndirect( HINSTANCE32 hInst, LPCSTR dlgTemplate,
+                              BOOL32 win32Template, HWND32 owner,
+                              DLGPROC16 dlgProc, LPARAM param,
+                              WINDOWPROCTYPE procType )
 {
     HMENU16 hMenu = 0;
     HFONT16 hFont = 0;
@@ -475,7 +476,7 @@
       /* Parse dialog template */
 
     if (!dlgTemplate) return 0;
-    if (procType != WIN_PROC_16)
+    if (win32Template)
         dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
     else
         dlgTemplate = DIALOG_ParseTemplate16( dlgTemplate, &template );
@@ -593,7 +594,7 @@
     /* Create controls */
 
     if (!DIALOG_CreateControls( wndPtr, dlgTemplate, template.nbItems,
-                                hInst, (procType != WIN_PROC_16) ))
+                                hInst, win32Template ))
     {
         DestroyWindow( hwnd );
         return 0;
@@ -692,7 +693,7 @@
                                     HWND16 owner, DLGPROC16 dlgProc,
                                     LPARAM param )
 {
-    return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
+    return DIALOG_CreateIndirect( hInst, dlgTemplate, FALSE, owner,
                                   dlgProc, param, WIN_PROC_16 );
 }
 
@@ -704,7 +705,7 @@
                                      HWND32 owner, DLGPROC32 dlgProc,
                                      LPARAM param )
 {
-    return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
+    return DIALOG_CreateIndirect( hInst, dlgTemplate, TRUE, owner,
                                   (DLGPROC16)dlgProc, param, WIN_PROC_32A );
 }
 
@@ -716,7 +717,7 @@
                                      HWND32 owner, DLGPROC32 dlgProc,
                                      LPARAM param )
 {
-    return DIALOG_CreateIndirect( hInst, dlgTemplate, owner,
+    return DIALOG_CreateIndirect( hInst, dlgTemplate, TRUE, owner,
                                   (DLGPROC16)dlgProc, param, WIN_PROC_32W );
 }
 
@@ -724,7 +725,7 @@
 /***********************************************************************
  *           DIALOG_DoDialogBox
  */
-static INT32 DIALOG_DoDialogBox( HWND hwnd, HWND owner )
+INT32 DIALOG_DoDialogBox( HWND32 hwnd, HWND32 owner )
 {
     WND * wndPtr;
     DIALOGINFO * dlgInfo;
@@ -832,7 +833,7 @@
  *           DialogBoxIndirectParam32A   (USER32.135)
  */
 INT32 DialogBoxIndirectParam32A( HINSTANCE32 hInstance, LPCVOID template,
-                                 HWND32 owner, DLGPROC32 dlgProc ,LPARAM param)
+                                 HWND32 owner, DLGPROC32 dlgProc, LPARAM param)
 {
     HWND32 hwnd = CreateDialogIndirectParam32A( hInstance, template,
                                                 owner, dlgProc, param );
@@ -845,7 +846,7 @@
  *           DialogBoxIndirectParam32W   (USER32.137)
  */
 INT32 DialogBoxIndirectParam32W( HINSTANCE32 hInstance, LPCVOID template,
-                                 HWND32 owner, DLGPROC32 dlgProc ,LPARAM param)
+                                 HWND32 owner, DLGPROC32 dlgProc, LPARAM param)
 {
     HWND32 hwnd = CreateDialogIndirectParam32W( hInstance, template,
                                                 owner, dlgProc, param );
diff --git a/windows/event.c b/windows/event.c
index d01c38b..ac851e3 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -20,13 +20,13 @@
 #include <X11/Xatom.h>
 
 #include "windows.h"
+#include "winnt.h"
 #include "gdi.h"
 #include "heap.h"
 #include "queue.h"
 #include "win.h"
 #include "class.h"
 #include "clipboard.h"
-#include "debugger.h"
 #include "message.h"
 #include "module.h"
 #include "options.h"
@@ -35,7 +35,6 @@
 #include "drive.h"
 #include "dos_fs.h"
 #include "shell.h"
-#include "registers.h"
 #include "xmalloc.h"
 #include "keyboard.h"
 #include "stddebug.h"
@@ -65,7 +64,7 @@
 BOOL AsyncMouseButtonsStates[NB_BUTTONS];
 BYTE InputKeyStateTable[256];
 
-
+static INT16  captureHT = HTCLIENT;
 static HWND32 captureWnd = 0;
 static BOOL32 InputEnabled = TRUE;
 
@@ -542,10 +541,12 @@
 	   keysym, ksname, ascii_chars, Str[0], Str);
 	}
 
+#if 0
     /* Ctrl-Alt-Return enters the debugger */
     if ((keysym == XK_Return) && (event->type == KeyPress) &&
         (event->state & ControlMask) && (event->state & Mod1Mask))
         DEBUG_EnterDebugger();
+#endif
 
     xkey = LOWORD(keysym);
     key_type = HIBYTE(xkey);
@@ -585,8 +586,8 @@
 	    case XK_Delete :
 	    case XK_Home :
 	    case XK_End :
-	    case XK_Page_Up :
-	    case XK_Page_Down :
+	    case XK_Prior :
+	    case XK_Next :
 	    case XK_Left :
 	    case XK_Up :
 	    case XK_Right :
@@ -1082,20 +1083,13 @@
     return;
 }
 
-
 /**********************************************************************
- *		SetCapture16   (USER.18)
+ *              EVENT_Capture
+ * 
+ * We need this to be able to generate double click messages
+ * when menu code captures mouse in the window without CS_DBLCLK style.
  */
-HWND16 SetCapture16( HWND16 hwnd )
-{
-    return (HWND16)SetCapture32( hwnd );
-}
-
-
-/**********************************************************************
- *		SetCapture32   (USER32.463)
- */
-HWND32 SetCapture32( HWND32 hwnd )
+HWND32 EVENT_Capture(HWND32 hwnd, INT16 ht)
 {
     Window win;
     HWND32 old_capture_wnd = captureWnd;
@@ -1105,17 +1099,45 @@
         ReleaseCapture();
         return old_capture_wnd;
     }
-    if (!(win = WIN_GetXWindow( hwnd ))) return 0;
-    if (XGrabPointer(display, win, False, 
+    if ((win = WIN_GetXWindow( hwnd )))
+    {
+        if (XGrabPointer(display, win, False,
                      ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
                      GrabModeAsync, GrabModeAsync,
                      None, None, CurrentTime ) == GrabSuccess)
-    {
-	dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
-	captureWnd   = hwnd;
-	return old_capture_wnd;
+	{
+            dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
+            captureWnd   = hwnd;
+	    captureHT    = ht;
+            return old_capture_wnd;
+        }
     }
-    else return 0;
+    return 0;
+}
+
+/**********************************************************************
+ *              EVENT_GetCaptureInfo
+ */
+INT16 EVENT_GetCaptureInfo()
+{
+    return captureHT;
+}
+
+/**********************************************************************
+ *		SetCapture16   (USER.18)
+ */
+HWND16 SetCapture16( HWND16 hwnd )
+{
+    return (HWND16)EVENT_Capture( hwnd, HTCLIENT );
+}
+
+
+/**********************************************************************
+ *		SetCapture32   (USER32.463)
+ */
+HWND32 SetCapture32( HWND32 hwnd )
+{
+    return EVENT_Capture( hwnd, HTCLIENT );
 }
 
 
@@ -1163,8 +1185,7 @@
 /***********************************************************************
  *           Mouse_Event   (USER.299)
  */
-#ifndef WINELIB
-void Mouse_Event( SIGCONTEXT *context )
+void Mouse_Event( CONTEXT *context )
 {
     /* Register values:
      * AX = mouse event
@@ -1199,7 +1220,6 @@
         hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
                         rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
 }
-#endif
 
 
 /**********************************************************************
diff --git a/windows/mdi.c b/windows/mdi.c
index e0b2474..f780b72 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -838,7 +838,6 @@
 BOOL MDI_AugmentFrameMenu(MDICLIENTINFO* ci, WND *frame, HWND hChild)
 {
  WND*		child = WIN_FindWndPtr(hChild);
- HGLOBAL16      handle;
  HMENU16  	hSysPopup = 0;
 
  dprintf_mdi(stddeb,"MDI_AugmentFrameMenu: frame %p,child %04x\n",frame,hChild);
@@ -847,9 +846,8 @@
 
  /* create a copy of sysmenu popup and insert it into frame menu bar */
 
- if (!(handle = SYSRES_LoadResource( SYSRES_MENU_SYSMENU ))) return 0;
- hSysPopup = LoadMenuIndirect16( GlobalLock16( handle ) );
- SYSRES_FreeResource( handle );
+ if (!(hSysPopup = LoadMenuIndirect32A(SYSRES_GetResPtr(SYSRES_MENU_SYSMENU))))
+     return 0;
  
  dprintf_mdi(stddeb,"\t\tgot popup %04x\n in sysmenu %04x",hSysPopup,child->hSysMenu);
  
diff --git a/windows/message.c b/windows/message.c
index dcfec8d..70b3043 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -32,7 +32,8 @@
 #define HWND_BROADCAST16  ((HWND16)0xffff)
 #define HWND_BROADCAST32  ((HWND32)0xffffffff)
 
-typedef enum { SYSQ_MSG_ABANDON, SYSQ_MSG_SKIP, SYSQ_MSG_ACCEPT } SYSQ_STATUS;
+typedef enum { SYSQ_MSG_ABANDON, SYSQ_MSG_SKIP, 
+               SYSQ_MSG_ACCEPT, SYSQ_MSG_CONTINUE } SYSQ_STATUS;
 
 extern BOOL MouseButtonsStates[3];
 extern BOOL AsyncMouseButtonsStates[3];
@@ -50,62 +51,64 @@
 static INT32 debugSMRL = 0;       /* intertask SendMessage() recursion level */
 
 /***********************************************************************
+ *           MSG_CheckFilter
+ */
+BOOL32 MSG_CheckFilter(WORD uMsg, DWORD filter)
+{
+   if( filter )
+       return (uMsg >= LOWORD(filter) && uMsg <= HIWORD(filter));
+   return TRUE;
+}
+
+/***********************************************************************
  *           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:
- * - Find the window for this message.
- * - 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.
+ * to the user, left in the queue, or skipped entirely (in this case
+ * HIWORD contains hit test code).
  */
-static SYSQ_STATUS MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
+static DWORD MSG_TranslateMouseMsg( HWND16 hWndScope, DWORD filter, 
+				    MSG16 *msg, BOOL32 remove )
 {
-    WND *pWnd;
-    BOOL eatMsg = FALSE;
-    INT16 hittest;
-    MOUSEHOOKSTRUCT16 *hook;
-    BOOL32 ret;
-    static DWORD lastClickTime = 0;
-    static WORD  lastClickMsg = 0;
-    static POINT16 lastClickPos = { 0, 0 };
-    POINT16 pt = msg->pt;
-    MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16(GetTaskQueue(0));
+    static DWORD   dblclk_time_limit = 0;
+    static UINT16     clk_message = 0;
+    static HWND16     clk_hwnd = 0;
+    static POINT16    clk_pos = { 0, 0 };
 
-    BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
-		       (msg->message == WM_RBUTTONDOWN) ||
-		       (msg->message == WM_MBUTTONDOWN));
+    WND *pWnd;
+    HWND16 hWnd;
+    INT16 ht, hittest, sendSC = 0;
+    UINT16 message = msg->message;
+    POINT16 screen_pt, pt;
+    HANDLE16 hQ = GetTaskQueue(0);
+    MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16(hQ);
+    BOOL32 eatMsg = FALSE;
+    BOOL32 mouseClick = ((message == WM_LBUTTONDOWN) ||
+		         (message == WM_RBUTTONDOWN) ||
+		         (message == WM_MBUTTONDOWN))?1:0;
+    SYSQ_STATUS ret = 0;
 
       /* Find the window */
 
-    if ((msg->hwnd = GetCapture16()) != 0)
+    ht = hittest = HTCLIENT;
+    hWnd = GetCapture16();
+    if( !hWnd )
     {
-        BOOL32 ret;
-
-	ScreenToClient16( msg->hwnd, &pt );
-	msg->lParam = MAKELONG( pt.x, pt.y );
-        /* No need to further process the message */
-
-        if (!HOOK_IsHooked( WH_MOUSE ) ||
-            !(hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16)))
-            return SYSQ_MSG_ACCEPT;
-        hook->pt           = msg->pt;
-        hook->hwnd         = msg->hwnd;
-        hook->wHitTestCode = HTCLIENT;
-        hook->dwExtraInfo  = 0;
-        ret = !HOOK_CallHooks16( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
-                                 msg->message, (LPARAM)SEGPTR_GET(hook));
-        SEGPTR_FREE(hook);
-        return ret ? SYSQ_MSG_ACCEPT : SYSQ_MSG_SKIP ;
+	sendSC = 1;
+	ht = hittest = WINPOS_WindowFromPoint( WIN_GetDesktop(), msg->pt, &pWnd );
+	if( !pWnd ) pWnd = WIN_GetDesktop();
+	hWnd = pWnd->hwndSelf;
+    } 
+    else 
+    {
+	pWnd = WIN_FindWndPtr(hWnd);
+	ht = EVENT_GetCaptureInfo();
     }
-   
-    hittest = WINPOS_WindowFromPoint( WIN_GetDesktop(), msg->pt, &pWnd );
-    if (pWnd->hmemTaskQ != GetTaskQueue(0))
+
+	/* stop if not the right queue */
+
+    if (pWnd->hmemTaskQ != hQ)
     {
         /* Not for the current task */
         if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
@@ -114,127 +117,147 @@
         if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
         return SYSQ_MSG_ABANDON;
     }
-    pCursorQueue = queue;
-    msg->hwnd    = pWnd->hwndSelf;
 
-    if ((hittest != HTERROR) && mouseClick)
+	/* check if hWnd is within hWndScope */
+
+    if( hWndScope && hWnd != hWndScope )
+	if( !IsChild(hWndScope, hWnd) ) return SYSQ_MSG_CONTINUE;
+
+    if( mouseClick )
     {
-        HWND hwndTop = WIN_GetTopParent( msg->hwnd );
+	/* translate double clicks -
+	 * note that ...MOUSEMOVEs can slip in between
+	 * ...BUTTONDOWN and ...BUTTONDBLCLK messages */
 
-        /* Send the WM_PARENTNOTIFY message */
-
-        WIN_SendParentNotify( msg->hwnd, msg->message, 0,
-                              MAKELPARAM( msg->pt.x, msg->pt.y ) );
-
-        /* Activate the window if needed */
-
-        if (msg->hwnd != GetActiveWindow() &&
-            msg->hwnd != GetDesktopWindow16())
-        {
-            LONG ret = SendMessage16( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
-                                    MAKELONG( hittest, msg->message ) );
-
-            if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
-                eatMsg = TRUE;
-
-            if (((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT)) 
-                && hwndTop != GetActiveWindow() )
-                WINPOS_SetActiveWindow( hwndTop, TRUE , TRUE );
-        }
-    }
-
-      /* Send the WM_SETCURSOR message */
-
-    SendMessage16( msg->hwnd, WM_SETCURSOR, (WPARAM16)msg->hwnd,
-                   MAKELONG( hittest, msg->message ));
-    if (eatMsg) return SYSQ_MSG_SKIP;
-
-      /* Check for double-click */
-
-    if (mouseClick)
-    {
-	BOOL dbl_click = FALSE;
-
-	if ((msg->message == lastClickMsg) &&
-	    (msg->time - lastClickTime < doubleClickSpeed) &&
-	    (abs(msg->pt.x - lastClickPos.x) < SYSMETRICS_CXDOUBLECLK/2) &&
-	    (abs(msg->pt.y - lastClickPos.y) < SYSMETRICS_CYDOUBLECLK/2))
-	    dbl_click = TRUE;
-
-	if (dbl_click && (hittest == HTCLIENT))
+	if( pWnd->class->style & CS_DBLCLKS || ht != HTCLIENT )
 	{
-	    /* Check whether window wants the double click message. */
-            dbl_click = (pWnd->class->style & CS_DBLCLKS) != 0;
-	}
-
-	if (dbl_click) switch(msg->message)
-	{
-	    case WM_LBUTTONDOWN: msg->message = WM_LBUTTONDBLCLK; break;
-	    case WM_RBUTTONDOWN: msg->message = WM_RBUTTONDBLCLK; break;
-	    case WM_MBUTTONDOWN: msg->message = WM_MBUTTONDBLCLK; break;
-	}
-
-	if (remove)
-	{
-	    lastClickTime = msg->time;
-	    lastClickMsg  = msg->message;
-	    lastClickPos  = msg->pt;
+           if ((message == clk_message) && (hWnd == clk_hwnd) &&
+               (msg->time - dblclk_time_limit < doubleClickSpeed) &&
+               (abs(msg->pt.x - clk_pos.x) < SYSMETRICS_CXDOUBLECLK/2) &&
+               (abs(msg->pt.y - clk_pos.y) < SYSMETRICS_CYDOUBLECLK/2))
+	   {
+	      message += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
+	      mouseClick++;   /* == 2 */
+	   }
 	}
     }
+    screen_pt = pt = msg->pt;
 
-      /* Build the translated message */
-
-    if (hittest == HTCLIENT)
-        ScreenToClient16( msg->hwnd, &pt );
-    else
+    if (hittest != HTCLIENT)
     {
+	message += ((INT16)WM_NCMOUSEMOVE - WM_MOUSEMOVE);
 	msg->wParam = hittest;
-	msg->message += WM_NCLBUTTONDOWN - WM_LBUTTONDOWN;
     }
-    msg->lParam = MAKELONG( pt.x, pt.y );
+    else ScreenToClient16( hWnd, &pt );
 
-    /* Call the WH_MOUSE hook */
+	/* check message filter */
 
-    if (!HOOK_IsHooked( WH_MOUSE ) ||
-        !(hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16)))
-        return SYSQ_MSG_ACCEPT;
+    if (!MSG_CheckFilter(message, filter)) return SYSQ_MSG_CONTINUE;
 
-    hook->pt           = msg->pt;
-    hook->hwnd         = msg->hwnd;
-    hook->wHitTestCode = hittest;
-    hook->dwExtraInfo  = 0;
-    ret = !HOOK_CallHooks16( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
-                             msg->message, (LPARAM)SEGPTR_GET(hook) );
-    SEGPTR_FREE(hook);
-    return ret ? SYSQ_MSG_ACCEPT : SYSQ_MSG_SKIP;
+    pCursorQueue = queue;
+
+	/* call WH_MOUSE */
+
+    if (HOOK_IsHooked( WH_MOUSE ))
+    { 
+	MOUSEHOOKSTRUCT16 *hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16);
+	if( hook )
+	{
+	    hook->pt           = screen_pt;
+	    hook->hwnd         = hWnd;
+	    hook->wHitTestCode = hittest;
+	    hook->dwExtraInfo  = 0;
+	    ret = HOOK_CallHooks16( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
+	                            message, (LPARAM)SEGPTR_GET(hook) );
+	    SEGPTR_FREE(hook);
+	}
+	if( ret ) return MAKELONG((INT16)SYSQ_MSG_SKIP, hittest);
+    }
+
+    if ((hittest == HTERROR) || (hittest == HTNOWHERE)) 
+	eatMsg = sendSC = 1;
+    else if( remove && mouseClick )
+    {
+        HWND hwndTop = WIN_GetTopParent( hWnd );
+
+	if( mouseClick == 1 )
+	{
+	    /* set conditions */
+	    dblclk_time_limit = msg->time;
+	       clk_message = msg->message;
+	       clk_hwnd = hWnd;
+	       clk_pos = screen_pt;
+	} else 
+	    /* got double click - zero them out */
+	    dblclk_time_limit = clk_hwnd = 0;
+
+	if( sendSC )
+	{
+            /* Send the WM_PARENTNOTIFY,
+	     * note that even for double/nonclient clicks
+	     * notification message is still WM_L/M/RBUTTONDOWN.
+	     */
+
+            WIN_SendParentNotify( hWnd, msg->message, 0,
+                              MAKELPARAM( screen_pt.x, screen_pt.y ) );
+
+            /* Activate the window if needed */
+
+            if (hWnd != GetActiveWindow() && hWnd != GetDesktopWindow16())
+            {
+                LONG ret = SendMessage16( hWnd, WM_MOUSEACTIVATE, hwndTop,
+                                          MAKELONG( hittest, message ) );
+
+                if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
+                         eatMsg = TRUE;
+
+                if (((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT)) 
+                      && hwndTop != GetActiveWindow() )
+                      if (!WINPOS_SetActiveWindow( hwndTop, TRUE , TRUE ))
+			 eatMsg = TRUE;
+            }
+	}
+    } else sendSC = (remove && sendSC);
+
+     /* Send the WM_SETCURSOR message */
+
+    if (sendSC)
+        SendMessage16( hWnd, WM_SETCURSOR, (WPARAM16)hWnd,
+                       MAKELONG( hittest, message ));
+    if (eatMsg) return MAKELONG( (UINT16)SYSQ_MSG_SKIP, hittest);
+
+    msg->hwnd    = hWnd;
+    msg->message = message;
+    msg->lParam  = MAKELONG( pt.x, pt.y );
+    return SYSQ_MSG_ACCEPT;
 }
 
 
 /***********************************************************************
- *           MSG_TranslateKeyboardMsg
+ *           MSG_TranslateKbdMsg
  *
  * Translate an keyboard hardware event into a real message.
- * Return value indicates whether the translated message must be passed
- * to the user.
  */
-static SYSQ_STATUS MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
+static DWORD MSG_TranslateKbdMsg( HWND16 hWndScope, DWORD filter,
+				  MSG16 *msg, BOOL32 remove )
 {
+    WORD message = msg->message;
+    HWND16 hWnd = GetFocus16();
     WND *pWnd;
 
       /* Should check Ctrl-Esc and PrintScreen here */
 
-    msg->hwnd = GetFocus16();
-    if (!msg->hwnd)
+    if (!hWnd)
     {
 	  /* Send the message to the active window instead,  */
 	  /* translating messages to their WM_SYS equivalent */
 
-	msg->hwnd = GetActiveWindow();
+	hWnd = GetActiveWindow();
 
-	if( msg->message < WM_SYSKEYDOWN )
-	    msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
+	if( message < WM_SYSKEYDOWN )
+	    message += WM_SYSKEYDOWN - WM_KEYDOWN;
     }
-    pWnd = WIN_FindWndPtr( msg->hwnd );
+    pWnd = WIN_FindWndPtr( hWnd );
     if (pWnd && (pWnd->hmemTaskQ != GetTaskQueue(0)))
     {
         /* Not for the current task */
@@ -245,6 +268,14 @@
         if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
         return SYSQ_MSG_ABANDON;
     }
+
+    if (hWndScope && hWnd != hWndScope)
+	if (!IsChild(hWndScope, hWnd)) return SYSQ_MSG_CONTINUE;
+    if (!MSG_CheckFilter(message, filter)) return SYSQ_MSG_CONTINUE;
+
+    msg->hwnd = hWnd;
+    msg->message = message;
+
     return (HOOK_CallHooks16( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
 			      msg->wParam, msg->lParam )
             ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT);
@@ -365,7 +396,13 @@
 		     (LPARAM)SEGPTR_GET(tmpMsg));
   }
   else
-    result= QS_MOUSE | QS_KEY;
+  {
+    if( tmpMsg->message == WM_QUEUESYNC )
+        if (HOOK_IsHooked( WH_CBT ))
+            HOOK_CallHooks16( WH_CBT, HCBT_QS, 0, 0L);
+
+    result= QS_MOUSE | QS_KEY; /* ? */
+  }
   SEGPTR_FREE(tmpMsg);
  }
  return result;
@@ -376,35 +413,34 @@
  *
  * Peek for a hardware message matching the hwnd and message filters.
  */
-static BOOL MSG_PeekHardwareMsg( MSG16 *msg, HWND hwnd, WORD first, WORD last,
-                                 BOOL remove )
+static BOOL32 MSG_PeekHardwareMsg( MSG16 *msg, HWND16 hwnd, DWORD filter, BOOL32 remove )
 {
-    SYSQ_STATUS status = SYSQ_MSG_ACCEPT;
+    DWORD status = SYSQ_MSG_ACCEPT;
     MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
-    int i, pos = sysMsgQueue->nextMessage;
+    int i, kbd_msg, pos = sysMsgQueue->nextMessage;
 
     /* If the queue is empty, attempt to fill it */
     if (!sysMsgQueue->msgCount && XPending(display))
         EVENT_WaitXEvent( FALSE, FALSE );
 
-    for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
+    for (i = kbd_msg = 0; i < sysMsgQueue->msgCount; i++, pos++)
     {
         if (pos >= sysMsgQueue->queueSize) pos = 0;
 	*msg = sysMsgQueue->messages[pos].msg;
 
-          /* Translate message; return FALSE immediately on SYSQ_MSG_ABANDON */
+          /* Translate message */
 
         if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
         {
-            if ((status = MSG_TranslateMouseMsg(msg,remove)) == SYSQ_MSG_ABANDON)
-                return FALSE;
+            status = MSG_TranslateMouseMsg(hwnd, filter, msg, remove);
+	    kbd_msg = 0;
         }
         else if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
         {
-            if ((status = MSG_TranslateKeyboardMsg(msg,remove)) == SYSQ_MSG_ABANDON)
-                return FALSE;
+            status = MSG_TranslateKbdMsg(hwnd, filter, msg, remove);
+	    kbd_msg = 1;
         }
-        else  /* Non-standard hardware event */
+        else /* Non-standard hardware event */
         {
             HARDWAREHOOKSTRUCT16 *hook;
             if ((hook = SEGPTR_NEW(HARDWAREHOOKSTRUCT16)))
@@ -418,56 +454,55 @@
                                         remove ? HC_ACTION : HC_NOREMOVE,
                                         0, (LPARAM)SEGPTR_GET(hook) );
                 SEGPTR_FREE(hook);
-                status = ret ? SYSQ_MSG_SKIP : SYSQ_MSG_ACCEPT;
+                if (ret) 
+		{
+		    QUEUE_RemoveMsg( sysMsgQueue, pos );
+		    continue;
+		}
+		status = SYSQ_MSG_ACCEPT; 
             }
         }
 
-        if (status == SYSQ_MSG_SKIP)
-        {
-            if (remove) QUEUE_RemoveMsg( sysMsgQueue, pos );
-            /* FIXME: call CBT_CLICKSKIPPED from here */
-            continue;
-        }
+	switch (LOWORD(status))
+	{
+	   case SYSQ_MSG_ACCEPT:
+		break;
 
-          /* Check message against filters */
+	   case SYSQ_MSG_SKIP:
+                if (HOOK_IsHooked( WH_CBT ))
+                   if( kbd_msg )
+		       HOOK_CallHooks16( WH_CBT, HCBT_KEYSKIPPED, 
+						 msg->wParam, msg->lParam );
+		   else
+		   {
+                       MOUSEHOOKSTRUCT16 *hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16);
+                       if (hook)
+                       {
+                           hook->pt           = msg->pt;
+                           hook->hwnd         = msg->hwnd;
+                           hook->wHitTestCode = HIWORD(status);
+                           hook->dwExtraInfo  = 0;
+                           HOOK_CallHooks16( WH_CBT, HCBT_CLICKSKIPPED ,msg->message,
+                                          (LPARAM)SEGPTR_GET(hook) );
+                           SEGPTR_FREE(hook);
+                       }
+                   }
 
-        if (hwnd && (msg->hwnd != hwnd)) continue;
-        if ((first || last) && 
-            ((msg->message < first) || (msg->message > last))) continue;
+		if (remove)
+		    QUEUE_RemoveMsg( sysMsgQueue, pos );
+		/* continue */
+
+	   case SYSQ_MSG_CONTINUE:
+		continue;
+
+	   case SYSQ_MSG_ABANDON: 
+		return FALSE;
+	}
+
         if (remove)
         {
-            if (HOOK_IsHooked( WH_JOURNALRECORD ))
-                MSG_JournalRecordMsg( msg );
+            if (HOOK_IsHooked( WH_JOURNALRECORD )) MSG_JournalRecordMsg( msg );
             QUEUE_RemoveMsg( sysMsgQueue, pos );
-            
-            /* call CBT hook _after_ message removed from queue */
-	    if (HOOK_IsHooked( WH_CBT ))
-	    {
-	    	if (((msg->message >= WM_MOUSEFIRST) &&
-                     (msg->message <= WM_MOUSELAST)) ||
-	    	    ((msg->message >= WM_NCMOUSEFIRST) &&
-                     (msg->message <= WM_NCMOUSELAST)))
-	    	{
-                    MOUSEHOOKSTRUCT16 *hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16);
-                    if (hook)
-                    {
-	    	  	hook->pt           = msg->pt;
-			hook->hwnd         = msg->hwnd;
-			hook->wHitTestCode = (INT16)SendMessage16( msg->hwnd,
-                                            WM_NCHITTEST, 0,
-                                            MAKELONG( msg->pt.x, msg->pt.y ) );
-			hook->dwExtraInfo  = 0;
-			HOOK_CallHooks16( WH_CBT, HCBT_CLICKSKIPPED ,msg->message, 
-                                          (LPARAM)SEGPTR_GET(hook) );
-			SEGPTR_FREE(hook);
-                    }
-                }
-                else 
-                    if ((msg->message >= WM_KEYFIRST) &&
-                        (msg->message <= WM_KEYLAST))
-		   	HOOK_CallHooks16( WH_CBT, HCBT_KEYSKIPPED,
-                                          msg->wParam, msg->lParam );
-            }
         }
         return TRUE;
     }
@@ -692,7 +727,7 @@
         /* Now find a hardware event */
 
         if (((msgQueue->wakeBits & mask) & (QS_MOUSE | QS_KEY)) &&
-            MSG_PeekHardwareMsg( msg, hwnd, first, last, flags & PM_REMOVE ))
+            MSG_PeekHardwareMsg( msg, hwnd, MAKELONG(first,last), flags & PM_REMOVE ))
         {
             /* Got one */
 	    msgQueue->GetMessageTimeVal      = msg->time;
diff --git a/windows/msgbox.c b/windows/msgbox.c
index 9708381..40d9344 100644
--- a/windows/msgbox.c
+++ b/windows/msgbox.c
@@ -2,11 +2,10 @@
  * Message boxes
  *
  * Copyright 1995 Bernd Schmidt
- *
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <stdio.h>
-#include <malloc.h>
 #include "windows.h"
 #include "dlgs.h"
 #include "heap.h"
@@ -15,19 +14,27 @@
 #include "resource.h"
 #include "task.h"
 
-typedef struct {
-  LPCSTR title;
-  LPCSTR text;
-  WORD  type;
+typedef struct
+{
+    LPCSTR title;
+    LPCSTR text;
+    UINT32 type;
 } MSGBOX, *LPMSGBOX;
 
-LRESULT SystemMessageBoxProc(HWND hwnd,UINT message,WPARAM16 wParam,LPARAM lParam)
+
+/**************************************************************************
+ *           MSGBOX_DlgProc
+ *
+ * Dialog procedure for message boxes.
+ */
+static LRESULT MSGBOX_DlgProc( HWND32 hwnd, UINT32 message,
+                               WPARAM32 wParam, LPARAM lParam )
 {
   LPMSGBOX lpmb;
-  RECT16 rect, textrect;
-  HWND hItem;
+  RECT32 rect, textrect;
+  HWND32 hItem;
   HDC32 hdc;
-  LONG lRet;
+  LRESULT lRet;
   int i, buttons, bwidth, bheight, theight, wwidth, bpos;
   int borheight, iheight, tiheight;
   
@@ -86,21 +93,21 @@
     }
     
     /* Position everything */
-    GetWindowRect16(hwnd, &rect);
+    GetWindowRect32(hwnd, &rect);
     borheight = rect.bottom - rect.top;
     wwidth = rect.right - rect.left;
-    GetClientRect16(hwnd, &rect);
+    GetClientRect32(hwnd, &rect);
     borheight -= rect.bottom - rect.top;
 
     /* Get the icon height */
-    GetWindowRect16(GetDlgItem(hwnd, 1088), &rect);
+    GetWindowRect32(GetDlgItem(hwnd, 1088), &rect);
     iheight = rect.bottom - rect.top;
     
     /* Get the number of visible buttons and their width */
-    GetWindowRect16(GetDlgItem(hwnd, 2), &rect);
+    GetWindowRect32(GetDlgItem(hwnd, 2), &rect);
     bheight = rect.bottom - rect.top;
     bwidth = rect.left;
-    GetWindowRect16(GetDlgItem(hwnd, 1), &rect);
+    GetWindowRect32(GetDlgItem(hwnd, 1), &rect);
     bwidth -= rect.left;
     for (buttons = 0, i = 1; i < 8; i++)
     {
@@ -110,13 +117,13 @@
     
     /* Get the text size */
     hItem = GetDlgItem(hwnd, 100);
-    GetWindowRect16(hItem, &textrect);
-    MapWindowPoints16(0, hwnd, (LPPOINT16)&textrect, 2);
+    GetWindowRect32(hItem, &textrect);
+    MapWindowPoints32(0, hwnd, (LPPOINT32)&textrect, 2);
     
-    GetClientRect16(hItem, &rect);
+    GetClientRect32(hItem, &rect);
     hdc = GetDC32(hItem);
-    lRet = DrawText16( hdc, lpmb->text, -1, &rect,
-                       DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_CALCRECT);
+    lRet = DrawText32A( hdc, lpmb->text, -1, &rect,
+                        DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_CALCRECT);
     theight = rect.bottom  - rect.top;
     tiheight = 16 + MAX(iheight, theight);
     ReleaseDC32(hItem, hdc);
@@ -128,8 +135,8 @@
     
     /* Position the icon */
     hItem = GetDlgItem(hwnd, 1088);
-    GetWindowRect16(hItem, &rect);
-    MapWindowPoints16(0, hwnd, (LPPOINT16)&rect, 2);
+    GetWindowRect32(hItem, &rect);
+    MapWindowPoints32(0, hwnd, (LPPOINT32)&rect, 2);
     SetWindowPos(hItem, 0, rect.left, (tiheight - iheight) / 2, 0, 0,
 		 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
     
@@ -139,7 +146,7 @@
     
     /* Position the buttons */
     bpos = (wwidth - bwidth * buttons) / 2;
-    GetWindowRect16(GetDlgItem(hwnd, 1), &rect);
+    GetWindowRect32(GetDlgItem(hwnd, 1), &rect);
     for (buttons = i = 0; i < 7; i++) {
       /* some arithmetic to get the right order for YesNoCancel windows */
       hItem = GetDlgItem(hwnd, (i + 5) % 7 + 1);
@@ -157,7 +164,8 @@
     break;
     
    case WM_COMMAND:
-    switch (wParam) {
+    switch (wParam)
+    {
      case IDOK:
      case IDCANCEL:
      case IDABORT:
@@ -173,6 +181,7 @@
   return 0;
 }
 
+
 /**************************************************************************
  *           MessageBox16   (USER.1)
  */
@@ -181,61 +190,60 @@
     return MessageBox32A( hwnd, text, title, type );
 }
 
+
 /**************************************************************************
  *           MessageBox32A   (USER32.390)
  */
 INT32 MessageBox32A( HWND32 hWnd, LPCSTR text, LPCSTR title, UINT32 type )
 {
-    HANDLE16 handle;
     MSGBOX mbox;
-    int ret;
-
     mbox.title = title;
     mbox.text  = text;
     mbox.type  = type;
-
-    handle = SYSRES_LoadResource( SYSRES_DIALOG_MSGBOX );
-    if (!handle) return 0;
-    ret = DialogBoxIndirectParam16( WIN_GetWindowInstance(hWnd),
-                                  handle, hWnd,
-                                  MODULE_GetWndProcEntry16("SystemMessageBoxProc"),
-                                  (LONG)&mbox );
-    SYSRES_FreeResource( handle );
-    return ret;
+    return DialogBoxIndirectParam32A( WIN_GetWindowInstance(hWnd),
+                                      SYSRES_GetResPtr( SYSRES_DIALOG_MSGBOX ),
+                                      hWnd, MSGBOX_DlgProc, (LPARAM)&mbox );
 }
 
+
 /**************************************************************************
  *           MessageBox32W   (USER32.395)
  */
-INT32 MessageBox32W( HWND32 hWnd, LPCWSTR text, LPCWSTR title, UINT32 type )
+INT32 MessageBox32W( HWND32 hwnd, LPCWSTR text, LPCWSTR title, UINT32 type )
 {
-    HANDLE16 handle;
-    MSGBOX mbox;
-    int ret;
-
-    mbox.title = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
-    mbox.text  = HEAP_strdupWtoA( GetProcessHeap(), 0, text );
-    mbox.type  = type;
-
-    fprintf(stderr,"MessageBox(%s,%s)\n",mbox.text,mbox.title);
-    handle = SYSRES_LoadResource( SYSRES_DIALOG_MSGBOX );
-    if (!handle) return 0;
-    ret = DialogBoxIndirectParam16( WIN_GetWindowInstance(hWnd),
-                                  handle, hWnd,
-                                  MODULE_GetWndProcEntry16("SystemMessageBoxProc"),
-                                  (LONG)&mbox );
-    SYSRES_FreeResource( handle );
-    HeapFree( GetProcessHeap(), 0, mbox.title );
-    HeapFree( GetProcessHeap(), 0, mbox.text );
+    LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
+    LPSTR textA  = HEAP_strdupWtoA( GetProcessHeap(), 0, text );
+    INT32 ret = MessageBox32A( hwnd, textA, titleA, type );
+    HeapFree( GetProcessHeap(), 0, titleA );
+    HeapFree( GetProcessHeap(), 0, textA );
     return ret;
 }
 
-/**************************************************************************
- *			FatalAppExit  [USER.137]
- */
 
-void FatalAppExit(UINT fuAction, LPCSTR str)
+/**************************************************************************
+ *           FatalAppExit16   (KERNEL.137)
+ */
+void FatalAppExit16( UINT16 action, LPCSTR str )
 {
-  MessageBox16(0, str, NULL, MB_SYSTEMMODAL | MB_OK);
-  TASK_KillCurrentTask(0);
+    FatalAppExit32A( action, str );
+}
+
+
+/**************************************************************************
+ *           FatalAppExit32A   (KERNEL32.108)
+ */
+void FatalAppExit32A( UINT32 action, LPCSTR str )
+{
+    MessageBox32A( 0, str, NULL, MB_SYSTEMMODAL | MB_OK );
+    TASK_KillCurrentTask(0);
+}
+
+
+/**************************************************************************
+ *           FatalAppExit32W   (KERNEL32.109)
+ */
+void FatalAppExit32W( UINT32 action, LPCWSTR str )
+{
+    MessageBox32W( 0, str, NULL, MB_SYSTEMMODAL | MB_OK );
+    TASK_KillCurrentTask(0);
 }
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 4c6a2d5..20e2c6f 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -433,7 +433,7 @@
 /***********************************************************************
  *           NC_DrawSysButton
  */
-void NC_DrawSysButton( HWND hwnd, HDC16 hdc, BOOL down )
+void NC_DrawSysButton( HWND hwnd, HDC16 hdc, BOOL32 down )
 {
     RECT16 rect;
     HDC32 hdcMem;
@@ -844,17 +844,24 @@
 /***********************************************************************
  *           NC_GetSysPopupPos
  */
-BOOL NC_GetSysPopupPos( WND* wndPtr, RECT16* rect )
+BOOL32 NC_GetSysPopupPos( WND* wndPtr, RECT16* rect )
 {
-  if( !wndPtr->hSysMenu ) return FALSE;
-
-  NC_GetInsideRect( wndPtr->hwndSelf, rect );
-  OffsetRect16( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top );
-  if (wndPtr->dwStyle & WS_CHILD)
-     ClientToScreen16( wndPtr->parent->hwndSelf, (POINT16 *)rect );
-  rect->right = rect->left + SYSMETRICS_CXSIZE;
-  rect->bottom = rect->top + SYSMETRICS_CYSIZE;
-  return TRUE;
+  if( wndPtr->hSysMenu )
+  {
+      if( wndPtr->dwStyle & WS_MINIMIZE )
+	  GetWindowRect16( wndPtr->hwndSelf, rect );
+      else
+      {
+  	  NC_GetInsideRect( wndPtr->hwndSelf, rect );
+  	  OffsetRect16( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top );
+  	  if (wndPtr->dwStyle & WS_CHILD)
+     	      ClientToScreen16( wndPtr->parent->hwndSelf, (POINT16 *)rect );
+          rect->right = rect->left + SYSMETRICS_CXSIZE;
+          rect->bottom = rect->top + SYSMETRICS_CYSIZE;
+      }
+      return TRUE;
+  }
+  return FALSE;
 }
 
 /***********************************************************************
@@ -862,29 +869,53 @@
  *
  * Track a mouse button press on the system menu.
  */
-static void NC_TrackSysMenu( HWND hwnd, HDC16 hdc, POINT16 pt )
+static void NC_TrackSysMenu( HWND hwnd, POINT16 pt )
 {
-    RECT16 rect;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    int iconic = wndPtr->dwStyle & WS_MINIMIZE;
-    HMENU16 hmenu;
+    WND*	wndPtr = WIN_FindWndPtr( hwnd );
     
-    if (!(wndPtr->dwStyle & WS_SYSMENU)) return;
-
-    /* If window has a menu, track the menu bar normally if it not minimized */
-    if (HAS_MENU(wndPtr) && !iconic) MENU_TrackMouseMenuBar( hwnd, pt );
-    else
+    if (wndPtr->dwStyle & WS_SYSMENU)
     {
-	  /* Otherwise track the system menu like a normal popup menu */
+	int	iconic, on = 1;
 
-	NC_GetSysPopupPos( wndPtr, &rect );
-	if (!iconic) NC_DrawSysButton( hwnd, hdc, TRUE );
-	hmenu = GetSystemMenu(hwnd, 0);
-	MENU_InitSysMenuPopup(hmenu, wndPtr->dwStyle,
-				    wndPtr->class->style);
-	TrackPopupMenu16( hmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
-                          rect.left, rect.bottom, 0, hwnd, &rect );
-	if (!iconic) NC_DrawSysButton( hwnd, hdc, FALSE );
+	iconic = wndPtr->dwStyle & WS_MINIMIZE;
+
+	if( !iconic ) 
+	{
+	     HDC16	hdc = GetWindowDC32(hwnd);
+	     RECT16	rect, rTrack;
+	     BOOL32 	bNew, bTrack = TRUE;
+	     MSG16	msg;
+	    
+	     NC_GetSysPopupPos( wndPtr, &rect );
+	     rTrack = rect;
+	     MapWindowPoints16( 0, hwnd, (LPPOINT16)&rTrack, 2 );
+
+	     /* track mouse while waiting for WM_LBUTTONUP */
+
+	     NC_DrawSysButton( hwnd, hdc, bTrack );
+	     SetCapture32(hwnd);
+	     do
+	     {
+		msg.message = WM_NULL;
+		PeekMessage16( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE);
+		if( msg.message == WM_MOUSEMOVE )
+		{
+		    if( (bNew = PtInRect16(&rTrack, MAKEPOINT16(msg.lParam))) )
+		    {   if( bTrack ) continue; }
+		    else 
+		    {   if(!bTrack ) continue; }
+		    NC_DrawSysButton( hwnd, hdc, bTrack = bNew);
+		}
+	     } while( msg.message != WM_LBUTTONUP );
+
+	     ReleaseCapture();
+	     ReleaseDC32(hwnd, hdc);
+	     on = PtInRect16(&rTrack, MAKEPOINT16(msg.lParam));
+	} 
+
+	if( on ) 
+	    SendMessage16( hwnd, WM_SYSCOMMAND, 
+			   SC_MOUSEMENU + HTSYSMENU, *((LPARAM*)&pt));
     }
 }
 
@@ -1170,7 +1201,7 @@
 
     if (!moved && (wndPtr->dwStyle & WS_MINIMIZE))
     {
-        NC_TrackSysMenu( hwnd, hdc, pt );
+        NC_TrackSysMenu( hwnd, pt );
         return;
     }
 
@@ -1293,8 +1324,6 @@
  */
 LONG NC_HandleNCLButtonDown( HWND32 hwnd, WPARAM16 wParam, LPARAM lParam )
 {
-    HDC32 hdc;
-
     switch(wParam)  /* Hit test */
     {
     case HTCAPTION:
@@ -1302,9 +1331,7 @@
 	break;
 
     case HTSYSMENU:
-        hdc = GetWindowDC32( hwnd );
-	NC_TrackSysMenu( hwnd, hdc, MAKEPOINT16(lParam) );
-        ReleaseDC32( hwnd, hdc );
+        NC_TrackSysMenu( hwnd, MAKEPOINT16(lParam) );
 	break;
 
     case HTMENU:
@@ -1413,10 +1440,6 @@
 	ShowWindow( hwnd, SW_RESTORE );
 	break;
 
-    case SC_NEXTWINDOW:
-    case SC_PREVWINDOW:
-	break;
-
     case SC_CLOSE:
 	return SendMessage16( hwnd, WM_CLOSE, 0, 0 );
 
@@ -1427,30 +1450,31 @@
 	break;
 
     case SC_MOUSEMENU:
-	MENU_TrackMouseMenuBar( hwnd, pt );
+        MENU_TrackMouseMenuBar( wndPtr, wParam & 0x000F, pt );
 	break;
 
     case SC_KEYMENU:
 	MENU_TrackKbdMenuBar( wndPtr , wParam , pt.x );
 	break;
 	
-    case SC_ARRANGE:
-	break;
-
     case SC_TASKLIST:
-	WinExec( "taskman.exe", SW_SHOWNORMAL ); 
-	break;
-
-    case SC_HOTKEY:
+	WinExec32( "taskman.exe", SW_SHOWNORMAL ); 
 	break;
 
     case SC_SCREENSAVE:
 	if (wParam == SC_ABOUTWINE)
 	{   
-	  extern const char people[];
-	  ShellAbout(hwnd,"WINE",people,0);
+            extern const char people[];
+            ShellAbout32A(hwnd,"Wine",people,0);
         }
 	break;
+  
+    case SC_HOTKEY:
+    case SC_ARRANGE:
+    case SC_NEXTWINDOW:
+    case SC_PREVWINDOW:
+ 	/* FIXME: unimplemented */
+        break;
     }
     return 0;
 }
diff --git a/windows/painting.c b/windows/painting.c
index e3dfda3..42dacc6 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -491,9 +491,18 @@
 
 
 /***********************************************************************
- *           InvalidateRgn   (USER.126) (USER32.328)
+ *           InvalidateRgn16   (USER.126)
  */
-void InvalidateRgn( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase )
+void InvalidateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
+{
+    RedrawWindow32(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
+}
+
+
+/***********************************************************************
+ *           InvalidateRgn32   (USER32.328)
+ */
+void InvalidateRgn32( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase )
 {
     RedrawWindow32(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
 }
@@ -518,9 +527,18 @@
 
 
 /***********************************************************************
- *           ValidateRgn   (USER.128) (USER32.571)
+ *           ValidateRgn16   (USER.128)
  */
-void ValidateRgn( HWND32 hwnd, HRGN32 hrgn )
+void ValidateRgn16( HWND16 hwnd, HRGN16 hrgn )
+{
+    RedrawWindow32( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
+}
+
+
+/***********************************************************************
+ *           ValidateRgn32   (USER32.571)
+ */
+void ValidateRgn32( HWND32 hwnd, HRGN32 hrgn )
 {
     RedrawWindow32( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
 }
diff --git a/windows/scroll.c b/windows/scroll.c
index b416537..8689f90 100644
--- a/windows/scroll.c
+++ b/windows/scroll.c
@@ -9,21 +9,21 @@
 
 #define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <stdlib.h>
-#include "wintypes.h"
+#include "windows.h"
 #include "class.h"
 #include "win.h"
 #include "gdi.h"
+#include "dce.h"
 #include "region.h"
+#include "graphics.h"
 #include "sysmetrics.h"
 #include "stddebug.h"
 #include "debug.h"
 
 extern HWND32 CARET_GetHwnd();			/* windows/caret.c */
+extern void   CARET_GetRect(LPRECT32);
 extern void CLIPPING_UpdateGCRegion(DC* );	/* objects/clipping.c */
 
-static int RgnType;
-
-
 /*************************************************************************
  *             ScrollWindow16   (USER.61)
  */
@@ -38,7 +38,6 @@
                     clipRect ? &clipRect32 : NULL );
 }
 
-
 /*************************************************************************
  *             ScrollWindow32   (USER32.449)
  */
@@ -109,7 +108,14 @@
 			    RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW, RDW_C_USEHRGN );
 
     DeleteObject32( hrgnUpdate );
-    if( hCaretWnd ) ShowCaret(hCaretWnd);
+    if( hCaretWnd ) 
+    {
+	POINT32	pt;
+	GetCaretPos32(&pt);
+	pt.x += dx; pt.y += dy;
+	SetCaretPos(pt.x, pt.y);
+	ShowCaret(hCaretWnd);
+    }
     return TRUE;
 }
 
@@ -134,44 +140,72 @@
 
 /*************************************************************************
  *             ScrollDC32   (USER32.448)
+ * 
+ * Both 'rc' and 'rLClip' are in logical units but update info is 
+ * returned in device coordinates.
  */
 BOOL32 ScrollDC32( HDC32 hdc, INT32 dx, INT32 dy, const RECT32 *rc,
-                   const RECT32 *cliprc, HRGN32 hrgnUpdate, LPRECT32 rcUpdate )
+                   const RECT32 *prLClip, HRGN32 hrgnUpdate, LPRECT32 rcUpdate )
 {
+    RECT32 rDClip, rLClip;
     HRGN32 hrgnClip = 0;
     HRGN32 hrgnScrollClip = 0;
-    RECT32 rectClip;
     POINT32 src, dest;
-    INT32 width, height;
+    INT32  ldx, ldy;
     DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
 
-    dprintf_scroll(stddeb,"ScrollDC: dx=%d dy=%d, hrgnUpdate=%04x rcUpdate = %p cliprc = %p, rc=%d %d %d %d\n",
-                   dx, dy, hrgnUpdate, rcUpdate, cliprc, rc ? rc->left : 0,
-                   rc ? rc->top : 0, rc ? rc->right : 0, rc ? rc->bottom : 0 );
+    dprintf_scroll(stddeb,"ScrollDC: %04x %d,%d hrgnUpdate=%04x rcUpdate = %p cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d)\n",
+                   (HDC16)hdc, dx, dy, hrgnUpdate, rcUpdate, 
+		   prLClip ? prLClip->left : 0, prLClip ? prLClip->top : 0, prLClip ? prLClip->right : 0, prLClip ? prLClip->bottom : 0,
+		   rc ? rc->left : 0, rc ? rc->top : 0, rc ? rc->right : 0, rc ? rc->bottom : 0 );
 
     if ( !dc || !hdc ) return FALSE;
 
-    /* set clipping region */
+/*
+    printf(stddeb,"\t[wndOrgX=%i, wndExtX=%i, vportOrgX=%i, vportExtX=%i]\n",
+		  dc->wndOrgX, dc->wndExtX, dc->vportOrgX, dc->vportExtX );
+    printf(stddeb,"\t[wndOrgY=%i, wndExtY=%i, vportOrgY=%i, vportExtY=%i]\n",
+                  dc->wndOrgY, dc->wndExtY, dc->vportOrgY, dc->vportExtY );
+*/
 
-    if ( !rc ) GetClipBox32( hdc, &rectClip );
-    else rectClip = *rc;
+    /* compute device clipping region */
 
-    if (cliprc)
-	IntersectRect32(&rectClip,&rectClip,cliprc);
+    if ( rc )
+    {
+	rLClip = *rc;
+	rDClip.left = XLPTODP(dc, rc->left); rDClip.right = XLPTODP(dc, rc->right);
+	rDClip.top = YLPTODP(dc, rc->top); rDClip.bottom = YLPTODP(dc, rc->bottom);
+    }
+    else /* maybe we should just return FALSE? */
+    {
+	GetClipBox32( hdc, &rDClip );
+	rLClip.left = XDPTOLP(dc, rDClip.left); rLClip.right = XDPTOLP(dc, rDClip.right);
+	rLClip.top = YDPTOLP(dc, rDClip.top); rLClip.bottom = YDPTOLP(dc, rDClip.bottom);
+    }
 
-    if( rectClip.left >= rectClip.right || rectClip.top >= rectClip.bottom )
+    if (prLClip)
+    {
+	RECT32 r;
+
+	r.left = XLPTODP(dc, prLClip->left); r.right = XLPTODP(dc, prLClip->right);
+	r.top = YLPTODP(dc, prLClip->top); r.bottom = YLPTODP(dc, prLClip->bottom);
+	IntersectRect32(&rLClip,&rLClip,prLClip);
+	IntersectRect32(&rDClip,&rDClip,&r);
+    }
+
+    if( rDClip.left >= rDClip.right || rDClip.top >= rDClip.bottom )
 	return FALSE;
     
     hrgnClip = GetClipRgn16(hdc);
-    hrgnScrollClip = CreateRectRgnIndirect32(&rectClip);
+    hrgnScrollClip = CreateRectRgnIndirect32(&rDClip);
 
     if( hrgnClip )
       {
-        /* save a copy and change cliprgn directly */
+        /* change device clipping region directly */
 
         CombineRgn32( hrgnScrollClip, hrgnClip, 0, RGN_COPY );
-        SetRectRgn( hrgnClip, rectClip.left, rectClip.top,
-                    rectClip.right, rectClip.bottom );
+        SetRectRgn( hrgnClip, rDClip.left, rDClip.top,
+			      rDClip.right, rDClip.bottom );
 
 	CLIPPING_UpdateGCRegion( dc );
       }
@@ -180,80 +214,80 @@
 
     /* translate coordinates */
 
-    if (dx > 0)
-    {
-	src.x = XDPTOLP(dc, rectClip.left);
-	dest.x = XDPTOLP(dc, rectClip.left + abs(dx));
-    }
-    else
-    {
-	src.x = XDPTOLP(dc, rectClip.left + abs(dx));
-	dest.x = XDPTOLP(dc, rectClip.left);
-    }
-    if (dy > 0)
-    {
-	src.y = YDPTOLP(dc, rectClip.top);
-	dest.y = YDPTOLP(dc, rectClip.top + abs(dy));
-    }
-    else
-    {
-	src.y = YDPTOLP(dc, rectClip.top + abs(dy));
-	dest.y = YDPTOLP(dc, rectClip.top);
-    }
+    ldx = dx * dc->wndExtX / dc->vportExtX;
+    ldy = dy * dc->wndExtY / dc->vportExtY;
 
-    width = rectClip.right - rectClip.left - abs(dx);
-    height = rectClip.bottom - rectClip.top - abs(dy);
+    if (dx > 0)
+	dest.x = (src.x = rLClip.left) + ldx;
+    else
+	src.x = (dest.x = rLClip.left) - ldx;
+
+    if (dy > 0)
+	dest.y = (src.y = rLClip.top) + ldy;
+    else
+	src.y = (dest.y = rLClip.top) - ldy;
 
     /* copy bits */
 
-    if (!BitBlt32( hdc, dest.x, dest.y, width, height, hdc, src.x, src.y, 
-                   SRCCOPY))
-	return FALSE;
+    if( rDClip.right - rDClip.left > dx &&
+	rDClip.bottom - rDClip.top > dy )
+    {
+	ldx = rLClip.right - rLClip.left - ldx;
+	ldy = rLClip.bottom - rLClip.top - ldy;
+
+	if (!BitBlt32( hdc, dest.x, dest.y, ldx, ldy,
+		       hdc, src.x, src.y, SRCCOPY))
+	    return FALSE;
+    }
+
+    /* restore clipping region */
+
+    if( hrgnClip )
+    {
+	CombineRgn32( hrgnClip, hrgnScrollClip, 0, RGN_COPY );
+	CLIPPING_UpdateGCRegion( dc );
+	SetRectRgn( hrgnScrollClip, rDClip.left, rDClip.top, 
+				    rDClip.right, rDClip.bottom );
+    }
+    else
+        SelectClipRgn32( hdc, 0 );
 
     /* compute update areas */
 
     if (hrgnUpdate || rcUpdate)
     {
-	HRGN32 hrgn1 = (hrgnUpdate) ? hrgnUpdate : CreateRectRgn32( 0,0,0,0 );
+	HRGN32 hrgn = (hrgnUpdate) ? hrgnUpdate : CreateRectRgn32( 0,0,0,0 );
 
 	if( dc->w.hVisRgn )
 	{
-	  CombineRgn32( hrgn1, dc->w.hVisRgn, 0, RGN_COPY );
-	  CombineRgn32( hrgn1, hrgn1, hrgnClip ? hrgnClip : hrgnScrollClip,
-                        RGN_AND );
-	  OffsetRgn32( hrgn1, dx, dy );
-	  CombineRgn32( hrgn1, dc->w.hVisRgn, hrgn1, RGN_DIFF );
-	  RgnType = CombineRgn32( hrgn1, hrgn1,
-                                  hrgnClip ? hrgnClip : hrgnScrollClip,
-                                  RGN_AND );
+	  CombineRgn32( hrgn, dc->w.hVisRgn, hrgnScrollClip, RGN_AND );
+	  OffsetRgn32( hrgn, dx, dy );
+	  CombineRgn32( hrgn, dc->w.hVisRgn, hrgn, RGN_DIFF );
+	  CombineRgn32( hrgn, hrgn, hrgnScrollClip, RGN_AND );
 	}
 	else
 	{
 	  RECT32 rect;
 
-          rect = rectClip;				/* vertical band */
+          rect = rDClip;				/* vertical band */
           if (dx > 0) rect.right = rect.left + dx;
           else if (dx < 0) rect.left = rect.right + dx;
           else SetRectEmpty32( &rect );
-          SetRectRgn( hrgn1, rect.left, rect.top, rect.right, rect.bottom );
+          SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
 
-          rect = rectClip;				/* horizontal band */
+          rect = rDClip;				/* horizontal band */
           if (dy > 0) rect.bottom = rect.top + dy;
           else if (dy < 0) rect.top = rect.bottom + dy;
           else SetRectEmpty32( &rect );
 
-          RgnType = REGION_UnionRectWithRgn( hrgn1, &rect );
+          REGION_UnionRectWithRgn( hrgn, &rect );
 	}
 
-	if (rcUpdate) GetRgnBox32( hrgn1, rcUpdate );
-	if (!hrgnUpdate) DeleteObject32( hrgn1 );
+	if (rcUpdate) GetRgnBox32( hrgn, rcUpdate );
+	if (!hrgnUpdate) DeleteObject32( hrgn );
     }
 
-    /* restore clipping region */
-
-    SelectClipRgn32( hdc, hrgnClip ? hrgnScrollClip : 0 );
     DeleteObject32( hrgnScrollClip );     
-
     return TRUE;
 }
 
@@ -272,49 +306,156 @@
     if (clipRect) CONV_RECT16TO32( clipRect, &clipRect32 );
     ret = ScrollWindowEx32( hwnd, dx, dy, rect ? &rect32 : NULL,
                             clipRect ? &clipRect32 : NULL, hrgnUpdate,
-                            &rcUpdate32, flags );
+                            (rcUpdate) ? &rcUpdate32 : NULL, flags );
     if (rcUpdate) CONV_RECT32TO16( &rcUpdate32, rcUpdate );
     return ret;
 }
 
+/*************************************************************************
+ *             SCROLL_FixCaret
+ */
+BOOL32 SCROLL_FixCaret(HWND32 hWnd, LPRECT32 lprc, UINT32 flags)
+{
+   HWND32 hCaret = CARET_GetHwnd();
+
+   if( hCaret )
+   {
+       RECT32	rc;
+       CARET_GetRect( &rc );
+       if( hCaret == hWnd ||
+          (flags & SW_SCROLLCHILDREN && IsChild(hWnd, hCaret)) )
+       {
+           POINT32     pt;
+
+           pt.x = rc.left; pt.y = rc.top;
+           MapWindowPoints32( hCaret, hWnd, (LPPOINT32)&rc, 2 );
+           if( IntersectRect32(lprc, lprc, &rc) )
+           {
+               HideCaret(0);
+  	       lprc->left = pt.x; lprc->top = pt.y;
+	       return TRUE;
+           }
+       }
+   }
+   return FALSE;
+}
 
 /*************************************************************************
  *             ScrollWindowEx32   (USER32.450)
- *
- * FIXME: broken, is there a program that actually uses it?
- *
  */
 INT32 ScrollWindowEx32( HWND32 hwnd, INT32 dx, INT32 dy, const RECT32 *rect,
                         const RECT32 *clipRect, HRGN32 hrgnUpdate,
                         LPRECT32 rcUpdate, UINT32 flags )
 {
-    HDC32 hdc;
+    INT32  retVal = NULLREGION;
+    BOOL32 bCaret = FALSE, bOwnRgn = TRUE;
     RECT32 rc, cliprc;
+    WND*   wnd = WIN_FindWndPtr( hwnd );
 
-    fprintf( stderr, "ScrollWindowEx: not fully implemented\n" );
+    if( !wnd || !WIN_IsWindowDrawable( wnd, TRUE )) return ERROR;
 
-    dprintf_scroll(stddeb,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",
-                   dx, dy, flags);
+    if (rect == NULL) GetClientRect32(hwnd, &rc);
+    else rc = *rect;
 
-    hdc = GetDC32(hwnd);
+    if (clipRect) IntersectRect32(&cliprc,&rc,clipRect);
+    else cliprc = rc;
 
-    if (rect == NULL)
-	GetClientRect32(hwnd, &rc);
-    else
-	CopyRect32(&rc, rect);
-    if (clipRect == NULL)
-	GetClientRect32(hwnd, &cliprc);
-    else
-	CopyRect32(&cliprc, clipRect);
-
-    ScrollDC32( hdc, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate );
-
-    if (flags | SW_INVALIDATE)
+    if (!IsRectEmpty32(&cliprc) && (dx || dy))
     {
-	PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
-                        ((flags & SW_ERASE) ? RDW_ERASENOW : 0), 0 );
-    }
+	DC*	dc;
+	HDC32	hDC;
+	BOOL32  bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
+	HRGN32  hrgnClip = CreateRectRgnIndirect32(&cliprc);
 
-    ReleaseDC32(hwnd, hdc);
-    return RgnType;
+dprintf_scroll(stddeb,"ScrollWindowEx: %04x, %d,%d hrgnUpdate=%04x rcUpdate = %p \
+cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d) %04x\n",             
+(HWND16)hwnd, dx, dy, hrgnUpdate, rcUpdate,
+clipRect?clipRect->left:0, clipRect?clipRect->top:0, clipRect?clipRect->right:0, clipRect?clipRect->bottom:0,
+rect?rect->left:0, rect?rect->top:0, rect ?rect->right:0, rect ?rect->bottom:0, (UINT16)flags );
+
+	rc = cliprc;
+	bCaret = SCROLL_FixCaret(hwnd, &rc, flags);
+
+	if( hrgnUpdate ) bOwnRgn = FALSE;
+        else if( bUpdate ) hrgnUpdate = CreateRectRgn32( 0, 0, 0, 0 );
+
+	hDC = GetDCEx32( hwnd, hrgnClip, DCX_CACHE | DCX_USESTYLE | 
+		        (flags & SW_SCROLLCHILDREN) ? DCX_NOCLIPCHILDREN : 0 );
+	if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
+	{
+	    POINT32 dst, src;
+
+	    if( dx > 0 ) dst.x = (src.x = dc->w.DCOrgX + cliprc.left) + dx;
+	    else src.x = (dst.x = dc->w.DCOrgX + cliprc.left) - dx;
+
+	    if( dy > 0 ) dst.y = (src.y = dc->w.DCOrgY + cliprc.top) + dy;
+	    else src.y = (dst.y = dc->w.DCOrgY + cliprc.top) - dy;
+
+	    if( bUpdate )
+  		XSetGraphicsExposures( display, dc->u.x.gc, True );
+	    XSetFunction( display, dc->u.x.gc, GXcopy );
+	    XCopyArea( display, dc->u.x.drawable, dc->u.x.drawable, dc->u.x.gc, 
+		       src.x, src.y, cliprc.right - cliprc.left - abs(dx),
+		       cliprc.bottom - cliprc.top - abs(dy), dst.x, dst.y );
+	    if( bUpdate )
+		XSetGraphicsExposures( display, dc->u.x.gc, False );
+
+	    if( dc->w.hVisRgn && bUpdate )
+	    {
+		CombineRgn32( hrgnUpdate, dc->w.hVisRgn, hrgnClip, RGN_AND );
+		OffsetRgn32( hrgnUpdate, dx, dy );
+		CombineRgn32( hrgnUpdate, dc->w.hVisRgn, hrgnUpdate, RGN_DIFF );
+		CombineRgn32( hrgnUpdate, hrgnUpdate, hrgnClip, RGN_AND );
+
+		if( rcUpdate ) GetRgnBox32( hrgnUpdate, rcUpdate );
+	    }
+	    ReleaseDC32(hwnd, hDC);
+	}
+
+	if( wnd->hrgnUpdate > 1 )
+	{
+	    if( rect || clipRect )
+	    {
+		if( (CombineRgn32( hrgnClip, hrgnClip, 
+				   wnd->hrgnUpdate, RGN_AND ) != NULLREGION) )
+		{
+		    CombineRgn32( wnd->hrgnUpdate, wnd->hrgnUpdate, hrgnClip, RGN_DIFF );
+		    OffsetRgn32( hrgnClip, dx, dy );
+		    CombineRgn32( wnd->hrgnUpdate, wnd->hrgnUpdate, hrgnClip, RGN_OR );
+		}
+	    }
+	    else  
+		OffsetRgn32( wnd->hrgnUpdate, dx, dy );
+	}
+
+	if( flags & SW_SCROLLCHILDREN )
+	{
+	    RECT32	r;
+	    WND* 	w;
+	    for( w = wnd->child; w; w = w->next )
+	    {
+		 CONV_RECT16TO32( &w->rectWindow, &r );
+	         if( IntersectRect32(&r, &r, &cliprc) )
+		     SetWindowPos(w->hwndSelf, 0, w->rectWindow.left + dx,
+				  w->rectWindow.top  + dy, 0,0, SWP_NOZORDER |
+				  SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
+				  SWP_DEFERERASE );
+	    }
+	}
+
+	if( flags & (SW_INVALIDATE | SW_ERASE) )
+            PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
+					((flags & SW_ERASE) ? RDW_ERASENOW : 0), 0 );
+
+	if( bCaret )
+	{
+	    SetCaretPos( rc.left + dx, rc.top + dy );
+	    ShowCaret(0);
+	}
+
+	if( bOwnRgn && hrgnUpdate ) DeleteObject32( hrgnUpdate );
+	DeleteObject32( hrgnClip );
+    }
+    return retVal;
 }
+
diff --git a/windows/winpos.c b/windows/winpos.c
index 3142e14..9061686 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -1346,7 +1346,7 @@
      {
 	while( w != wndPtr->owner )
 	{
-	  hwndLocalPrev = w->hwndSelf;
+          if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
 	  if( hwndLocalPrev == hwndInsertAfter ) break;
 	  w = w->next;
 	}
diff --git a/windows/winproc.c b/windows/winproc.c
index 6cbe823..e8946ee 100644
--- a/windows/winproc.c
+++ b/windows/winproc.c
@@ -9,8 +9,7 @@
 #include "windows.h"
 #include "callback.h"
 #include "heap.h"
-#include "ldt.h"
-#include "registers.h"
+#include "selectors.h"
 #include "stackframe.h"
 #include "struct32.h"
 #include "win.h"