Release 960818

Sun Aug 18 12:17:54 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [files/drive.c]
	Added 'Filesystem' option in drives configuration.

	* [files/dos_fs.c] 
	Added handling of case-insensitive filesystems.

	* [memory/selector.c] [include/stackframe.h]
	Removed MAKE_SEGPTR.

	* [misc/commdlg.c] [multimedia/mcistring.c]
	Replaced MAKE_SEGPTR by the SEGPTR_* macros.

	* [objects/bitblt.c] [windows/graphics.c]
	Use an intermediary pixmap to avoid some BadMatch errors on
	XGetImage().

Sun Aug 18 09:21:27 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [windows/message.c]
	Added handling of WM_NC...mouse messages in JOURNALRECORD hook.

	* [misc/ver.c]
	Fixed a bad string result in VerQueryValue[16|32A|32W].

Fri Aug 16 19:55:04 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [if1632/crtdll.spec] [misc/crtdll.c]
	More additions to get win95 programs further down the road.

	* [if1632/kernel.spec] [loader/module.c]
	GetModuleName() added.
	LoadModule(): params->showCmd can be NULL.

	* [if1632/kernel32.spec] [if1632/thunk.c]
	ThunkConnect32() stub added.

	* [loader/resource.c]
	Entries include lastentry.

	* [misc/shell.c] [files/file.c]
	Made progman work again.

Fri Aug 16 09:00:00 1996  Alex Korobka <alex@phm30.pharm.sunysb.edu>
	
	* [windows/defwnd.c] [windows/winpos.c] [windows/painting.c]
	Icon painting fixes.

	* [windows/winpos.c] [windows/painting.c]
	Enforce and follow hrgnUpdate more closely to cut down on
	redundant RedrawWindow() calls.

	* [windows/event.c]
	Process ConfigureNotify only for managed windows.

	* [windows/winpos.c]
	Do not redraw parent if the window was hidden before SetWindowPos().

	* [windows/nonclient.c]
	Omit some nonclient decoration painting for managed windows.

	* [controls/menu.c] [windows/mdi.c] [windows/nonclient.c]
	Implemented WM_NEXTMENU.

	* [controls/listbox.c]
	Multicolumn listboxes return WVR_VREDRAW on WM_NCCALCSIZE.

	* [misc/shell.c]
	Added .ICO file handling to ExtractIcon().
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 43b4ddc..f67c44c 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -14,6 +14,7 @@
 #include "winpos.h"
 #include "string32.h"
 #include "syscolor.h"
+#include "sysmetrics.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "spy.h"
@@ -101,7 +102,6 @@
 {
     switch(msg)
     {
-    case WM_PAINTICON: 
     case WM_NCPAINT:
 	return NC_HandleNCPaint( wndPtr->hwndSelf, (HRGN)wParam );
 
@@ -116,7 +116,7 @@
 	return NC_HandleNCLButtonDblClk( wndPtr, wParam, lParam );
 
     case WM_NCACTIVATE:
-	return NC_HandleNCActivate( wndPtr->hwndSelf, wParam );
+	return NC_HandleNCActivate( wndPtr, wParam );
 
     case WM_NCDESTROY:
 	if (wndPtr->text) HeapFree( SystemHeap, 0, wndPtr->text );
@@ -125,12 +125,26 @@
 	if (wndPtr->pHScroll) HeapFree( SystemHeap, 0, wndPtr->pHScroll );
         wndPtr->pVScroll = wndPtr->pHScroll = NULL;
 	return 0;
-	
+
+    case WM_PAINTICON:
     case WM_PAINT:
 	{
-	    PAINTSTRUCT16 paintstruct;
-	    BeginPaint16( wndPtr->hwndSelf, &paintstruct );
-	    EndPaint16( wndPtr->hwndSelf, &paintstruct );
+	    PAINTSTRUCT16 ps;
+	    HDC		  hdc = BeginPaint16( wndPtr->hwndSelf, &ps );
+	    if( hdc ) 
+	    {
+	      if( (wndPtr->dwStyle & WS_MINIMIZE) && wndPtr->class->hIcon )
+	      {
+	        int x = (wndPtr->rectWindow.right - wndPtr->rectWindow.left -
+			SYSMETRICS_CXICON)/2;
+	        int y = (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top -
+			SYSMETRICS_CYICON)/2;
+		dprintf_win(stddeb,"Painting class icon: vis rect=(%i,%i - %i,%i)\n",
+		ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom );
+	        DrawIcon( hdc, x, y, wndPtr->class->hIcon );
+	      }
+	      EndPaint16( wndPtr->hwndSelf, &ps );
+	    }
 	    return 0;
 	}
 
@@ -164,18 +178,33 @@
     case WM_ICONERASEBKGND:
 	{
 	    if (!wndPtr->class->hbrBackground) return 0;
-            if (wndPtr->class->hbrBackground <= (HBRUSH)(COLOR_MAX+1))
+
+	    /* FIXME: should fill icon text with hbrushActiveCaption 
+		      instead of this */
+
+	    if (wndPtr->dwStyle & WS_MINIMIZE )
+	    {
+		 if( wndPtr->flags & WIN_NCACTIVATED )
+		 {
+		   FillWindow( GetParent(wndPtr->hwndSelf), wndPtr->hwndSelf,
+                               (HDC)wParam, sysColorObjects.hbrushActiveCaption );
+		   return 1;
+		 }
+
+		 /* FIXME: should draw parent' background somehow
+			     (e.g for textured desktop) ? */
+	    }
+
+	    if (wndPtr->class->hbrBackground <= (HBRUSH)(COLOR_MAX+1))
             {
-                 HBRUSH hbrush;
-                 hbrush = CreateSolidBrush(
-                     GetSysColor(((DWORD)wndPtr->class->hbrBackground)-1));
+                HBRUSH hbrush = CreateSolidBrush( 
+			        GetSysColor(((DWORD)wndPtr->class->hbrBackground)-1));
                  FillWindow( GetParent(wndPtr->hwndSelf), wndPtr->hwndSelf,
                              (HDC)wParam, hbrush);
                  DeleteObject (hbrush);
             }
-            else
-	         FillWindow( GetParent(wndPtr->hwndSelf), wndPtr->hwndSelf,
-                             (HDC)wParam, wndPtr->class->hbrBackground );
+            else FillWindow( GetParent(wndPtr->hwndSelf), wndPtr->hwndSelf,
+                                  (HDC)wParam, wndPtr->class->hbrBackground );
 	    return 1;
 	}
 
diff --git a/windows/dialog.c b/windows/dialog.c
index 21ff837..3f3bace 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -12,7 +12,6 @@
 #include "heap.h"
 #include "win.h"
 #include "ldt.h"
-#include "stackframe.h"
 #include "string32.h"
 #include "user.h"
 #include "winproc.h"
@@ -724,33 +723,28 @@
 {
     WND * wndPtr;
     DIALOGINFO * dlgInfo;
-    HANDLE msgHandle;
-    MSG16* lpmsg;
+    MSG16 msg;
     INT32 retval;
 
       /* Owner must be a top-level window */
     owner = WIN_GetTopParent( owner );
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
-    if (!(msgHandle = USER_HEAP_ALLOC( sizeof(MSG16) ))) return -1;
-    lpmsg = (MSG16 *) USER_HEAP_LIN_ADDR( msgHandle );
     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
     EnableWindow( owner, FALSE );
     ShowWindow( hwnd, SW_SHOW );
 
-    while (MSG_InternalGetMessage( (SEGPTR)USER_HEAP_SEG_ADDR(msgHandle), hwnd, owner,
-                                   MSGF_DIALOGBOX, PM_REMOVE,
-                                   !(wndPtr->dwStyle & DS_NOIDLEMSG) ))
+    while (MSG_InternalGetMessage(&msg, hwnd, owner, MSGF_DIALOGBOX, PM_REMOVE,
+                                  !(wndPtr->dwStyle & DS_NOIDLEMSG) ))
     {
-	if (!IsDialogMessage( hwnd, lpmsg))
+	if (!IsDialogMessage( hwnd, &msg))
 	{
-	    TranslateMessage( lpmsg );
-	    DispatchMessage( lpmsg );
+	    TranslateMessage( &msg );
+	    DispatchMessage( &msg );
 	}
 	if (dlgInfo->fEnd) break;
     }
     retval = dlgInfo->msgResult;
     DestroyWindow( hwnd );
-    USER_HEAP_FREE( msgHandle );
     EnableWindow( owner, TRUE );
     return retval;
 }
diff --git a/windows/event.c b/windows/event.c
index 9ea4349..c59b378 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -398,9 +398,9 @@
     rect.right  = rect.left + event->width;
     rect.bottom = rect.top + event->height;
 
-    RedrawWindow32( pWnd->hwndSelf, &rect, 0,
-                    RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
-                    (event->count ? 0 : RDW_ERASENOW) );
+    PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
+                        RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
+                        (event->count ? 0 : RDW_ERASENOW), 0 );
 }
 
 
@@ -420,9 +420,9 @@
     rect.right  = rect.left + event->width;
     rect.bottom = rect.top + event->height;
 
-    RedrawWindow32( pWnd->hwndSelf, &rect, 0,
-                    RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
-                    (event->count ? 0 : RDW_ERASENOW) );
+    PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
+                        RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
+                        (event->count ? 0 : RDW_ERASENOW), 0 );
 }
 
 
@@ -683,26 +683,17 @@
     }
     else
     {
-      /* Managed window; most of this code is shamelessly
-       * stolen from SetWindowPos - FIXME: outdated
-       */
-      
         WND *wndPtr;
 	WINDOWPOS16 *winpos;
 	RECT16 newWindowRect, newClientRect;
         HRGN hrgnOldPos, hrgnNewPos;
 
-	if (!(wndPtr = WIN_FindWndPtr( hwnd )))
-	{
-	    dprintf_event(stddeb,"ConfigureNotify: invalid HWND %04x\n",hwnd);
+	if (!(wndPtr = WIN_FindWndPtr( hwnd )) ||
+	    !(wndPtr->flags & WIN_MANAGED) )
 	    return;
-	}
 	
         if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
 
-        /* Artificial messages - what is this for? */
-	SendMessage16(hwnd, WM_ENTERSIZEMOVE, 0, 0);
-	SendMessage16(hwnd, WM_EXITSIZEMOVE, 0, 0);
 
 	/* Fill WINDOWPOS struct */
 	winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
@@ -744,8 +735,9 @@
         SEGPTR_FREE(winpos);
 
         /* full window drag leaves unrepainted garbage without this */
-        RedrawWindow32( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
-                        RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW );
+        PAINT_RedrawWindow( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
+                            RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW,
+                            RDW_C_USEHRGN );
         DeleteObject(hrgnOldPos);
         DeleteObject(hrgnNewPos);
     }
diff --git a/windows/graphics.c b/windows/graphics.c
index 221bc02..e64aa2f 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -581,6 +581,7 @@
  */
 COLORREF GetPixel( HDC hdc, short x, short y )
 {
+    static Pixmap pixmap = 0;
     XImage * image;
     int pixel;
 
@@ -595,8 +596,21 @@
 
     x = dc->w.DCOrgX + XLPTODP( dc, x );
     y = dc->w.DCOrgY + YLPTODP( dc, y );
-    image = XGetImage( display, dc->u.x.drawable, x, y,
-		       1, 1, AllPlanes, ZPixmap );
+    if (dc->w.flags & DC_MEMORY)
+    {
+        image = XGetImage( display, dc->u.x.drawable, x, y, 1, 1,
+                           AllPlanes, ZPixmap );
+    }
+    else
+    {
+        /* If we are reading from the screen, use a temporary copy */
+        /* to avoid a BadMatch error */
+        if (!pixmap) pixmap = XCreatePixmap( display, rootWindow,
+                                             1, 1, dc->w.bitsPerPixel );
+        XCopyArea( display, dc->u.x.drawable, pixmap, BITMAP_colorGC,
+                   x, y, 1, 1, 0, 0 );
+        image = XGetImage( display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
+    }
     pixel = XGetPixel( image, 0, 0 );
     XDestroyImage( image );
     
diff --git a/windows/mdi.c b/windows/mdi.c
index 3d1984c..96307bf 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -25,7 +25,6 @@
 #include "user.h"
 #include "menu.h"
 #include "resource.h"
-#include "stackframe.h"
 #include "struct32.h"
 #include "sysmetrics.h"
 #include "stddebug.h"
@@ -129,8 +128,7 @@
  DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
 
  /* walk the rest of MDI children to prevent gaps in the id 
-  * sequence and in the menu child list 
-  */
+  * sequence and in the menu child list */
 
  for( index = id+1; index <= clientInfo->nActiveChildren + 
                              clientInfo->idFirstChild; index++ )
@@ -1223,6 +1221,29 @@
 	    MoveWindow(hwndMDIClient, 0, 0, 
 		       LOWORD(lParam), HIWORD(lParam), TRUE);
 	    break;
+
+	  case WM_NEXTMENU:
+
+            wndPtr = WIN_FindWndPtr(hwndMDIClient);
+            ci     = (MDICLIENTINFO*)wndPtr->wExtra;
+
+	    if( !(wndPtr->parent->dwStyle & WS_MINIMIZE) 
+		&& ci->hwndActiveChild && !ci->hwndChildMaximized )
+	      {
+		/* control menu is between the frame system menu and 
+		 * the first entry of menu bar */
+
+		if( wParam == VK_LEFT ) 
+		  { if( wndPtr->parent->wIDmenu != LOWORD(lParam) ) break; }
+		else if( wParam == VK_RIGHT )
+		  { if( GetSystemMenu( wndPtr->parent->hwndSelf, 0) 
+				       != LOWORD(lParam) ) break; }
+		else break;
+		
+		return MAKELONG( GetSystemMenu(ci->hwndActiveChild, 0), 
+				 ci->hwndActiveChild );
+	      }
+	    break;
 	}
     }
     
@@ -1420,13 +1441,19 @@
 
       case WM_MENUCHAR:
 
-	/* MDI children don't have menus */
+	/* MDI children don't have menu bars */
 	PostMessage( clientWnd->parent->hwndSelf, WM_SYSCOMMAND, 
 				          (WPARAM)SC_KEYMENU, (LPARAM)wParam);
 	return 0x00010000L;
 
       case WM_NEXTMENU:
-	   /* set current menu to child system menu */
+
+	if( wParam == VK_LEFT )		/* switch to frame system menu */
+	  return MAKELONG( GetSystemMenu(clientWnd->parent->hwndSelf, 0), 
+			   clientWnd->parent->hwndSelf );
+	if( wParam == VK_RIGHT )	/* to frame menu bar */
+	  return MAKELONG( clientWnd->parent->wIDmenu,
+			   clientWnd->parent->hwndSelf );
 
 	break;	
     }
@@ -1468,7 +1495,7 @@
 
       case WM_MENUCHAR:
 
-	/* MDI children don't have menus */
+	/* MDI children don't have menu bars */
 	PostMessage( clientWnd->parent->hwndSelf, WM_SYSCOMMAND, 
                      (WPARAM)SC_KEYMENU, (LPARAM)LOWORD(wParam) );
 	return 0x00010000L;
diff --git a/windows/message.c b/windows/message.c
index 82870e4..4d5b558 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -16,7 +16,6 @@
 #include "heap.h"
 #include "hook.h"
 #include "spy.h"
-#include "stackframe.h"
 #include "winpos.h"
 #include "atom.h"
 #include "dde.h"
@@ -59,11 +58,12 @@
     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;
-    MOUSEHOOKSTRUCT16 hook = { msg->pt, 0, HTCLIENT, 0 };
 
     BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
 		       (msg->message == WM_RBUTTONDOWN) ||
@@ -73,12 +73,23 @@
 
     if ((msg->hwnd = GetCapture()) != 0)
     {
+        BOOL32 ret;
+
 	ScreenToClient16( msg->hwnd, &pt );
 	msg->lParam = MAKELONG( pt.x, pt.y );
         /* No need to further process the message */
-        hook.hwnd = msg->hwnd;
-        return !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
-                                msg->message, (LPARAM)MAKE_SEGPTR(&hook));
+
+        if (!HOOK_GetHook( WH_MOUSE, GetTaskQueue(0)) ||
+            !(hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16)))
+            return TRUE;
+        hook->pt           = msg->pt;
+        hook->hwnd         = msg->hwnd;
+        hook->wHitTestCode = HTCLIENT;
+        hook->dwExtraInfo  = 0;
+        ret = !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
+                               msg->message, (LPARAM)SEGPTR_GET(hook));
+        SEGPTR_FREE(hook);
+        return ret;
     }
    
     hittest = WINPOS_WindowFromPoint( msg->pt, &pWnd );
@@ -100,7 +111,7 @@
         /* Send the WM_PARENTNOTIFY message */
 
         WIN_SendParentNotify( msg->hwnd, msg->message, 0,
-                              MAKELONG( msg->pt.x, msg->pt.y ) );
+                              MAKELPARAM( msg->pt.x, msg->pt.y ) );
 
         /* Activate the window if needed */
 
@@ -167,11 +178,21 @@
 	msg->message += WM_NCLBUTTONDOWN - WM_LBUTTONDOWN;
     }
     msg->lParam = MAKELONG( pt.x, pt.y );
-    
-    hook.hwnd = msg->hwnd;
-    hook.wHitTestCode = hittest;
-    return !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
-                            msg->message, (LPARAM)MAKE_SEGPTR(&hook));
+
+    /* Call the WH_MOUSE hook */
+
+    if (!HOOK_GetHook( WH_MOUSE, GetTaskQueue(0)) ||
+        !(hook = SEGPTR_NEW(MOUSEHOOKSTRUCT16)))
+        return TRUE;
+
+    hook->pt           = msg->pt;
+    hook->hwnd         = msg->hwnd;
+    hook->wHitTestCode = hittest;
+    hook->dwExtraInfo  = 0;
+    ret = !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
+                           msg->message, (LPARAM)SEGPTR_GET(hook) );
+    SEGPTR_FREE(hook);
+    return ret;
 }
 
 
@@ -214,6 +235,46 @@
                             msg->wParam, msg->lParam );
 }
 
+/***********************************************************************
+ *           MSG_JournalRecordMsg
+ *
+ * Build an EVENTMSG structure and call JOURNALRECORD hook
+ */
+static void MSG_JournalRecordMsg( MSG16 *msg )
+{
+    EVENTMSG16 *event = SEGPTR_NEW(EVENTMSG16);
+    if (!event) return;
+    event->message = msg->message;
+    event->time = msg->time;
+    if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
+    {
+        event->paramL = (msg->wParam & 0xFF) | (HIWORD(msg->lParam) << 8);
+        event->paramH = msg->lParam & 0x7FFF;  
+        if (HIWORD(msg->lParam) & 0x0100)
+            event->paramH |= 0x8000;               /* special_key - bit */
+        HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0,
+                        (LPARAM)SEGPTR_GET(event) );
+    }
+    else if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST))
+    {
+        event->paramL = LOWORD(msg->lParam);       /* X pos */
+        event->paramH = HIWORD(msg->lParam);       /* Y pos */ 
+        ClientToScreen16( msg->hwnd, (LPPOINT16)&event->paramL );
+        HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0,
+                        (LPARAM)SEGPTR_GET(event) );
+    }
+    else if ((msg->message >= WM_NCMOUSEMOVE) &&
+             (msg->message <= WM_NCMBUTTONDBLCLK))
+    {
+        event->paramL = LOWORD(msg->lParam);       /* X pos */
+        event->paramH = HIWORD(msg->lParam);       /* Y pos */ 
+        event->message += WM_MOUSEMOVE-WM_NCMOUSEMOVE;/* give no info about NC area */
+        HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0,
+                        (LPARAM)SEGPTR_GET(event) );
+    }
+    SEGPTR_FREE(event);
+}
+
 
 /***********************************************************************
  *           MSG_PeekHardwareMsg
@@ -246,10 +307,20 @@
         }
         else  /* Non-standard hardware event */
         {
-            HARDWAREHOOKSTRUCT16 hook = { msg->hwnd, msg->message,
-                                          msg->wParam, msg->lParam };
-            if (HOOK_CallHooks( WH_HARDWARE, remove ? HC_ACTION : HC_NOREMOVE,
-                                0, (LPARAM)MAKE_SEGPTR(&hook) )) continue;
+            HARDWAREHOOKSTRUCT16 *hook;
+            if ((hook = SEGPTR_NEW(HARDWAREHOOKSTRUCT16)))
+            {
+                BOOL32 ret;
+                hook->hWnd     = msg->hwnd;
+                hook->wMessage = msg->message;
+                hook->wParam   = msg->wParam;
+                hook->lParam   = msg->lParam;
+                ret = HOOK_CallHooks( WH_HARDWARE,
+                                      remove ? HC_ACTION : HC_NOREMOVE,
+                                      0, (LPARAM)SEGPTR_GET(hook) );
+                SEGPTR_FREE(hook);
+                if (ret) continue;
+            }
         }
 
           /* Check message against filters */
@@ -261,35 +332,7 @@
             (GetWindowTask16(msg->hwnd) != GetCurrentTask()))
             continue;  /* Not for this task */
         if (remove && HOOK_GetHook( WH_JOURNALRECORD, GetTaskQueue(0) ))
-        {
-            EVENTMSG16 *event = SEGPTR_NEW(EVENTMSG16);
-            if (event)
-            {
-                event->message = msg->message;
-                event->time = msg->time;
-                if ((msg->message >= WM_KEYFIRST) &&
-                    (msg->message <= WM_KEYLAST))
-                {
-                    event->paramL = (msg->wParam & 0xFF) |
-                                    (HIWORD(msg->lParam) << 8);
-                    event->paramH = msg->lParam & 0x7FFF;  
-                    if (HIWORD(msg->lParam) & 0x0100)
-                        event->paramH |= 0x8000;  /* special_key - bit */
-                    HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION,
-                                    0, (LPARAM)SEGPTR_GET(event) );
-                }
-                else if ((msg->message >= WM_MOUSEFIRST) &&
-                         (msg->message <= WM_MOUSELAST))
-                {
-                    event->paramL = LOWORD(msg->lParam);       /* X pos */
-                    event->paramH = HIWORD(msg->lParam);       /* Y pos */ 
-                    ClientToScreen16( msg->hwnd, (LPPOINT16)&event->paramL );
-                    HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION,
-                                    0, (LPARAM)SEGPTR_GET(event) );
-                }
-                SEGPTR_FREE(event);
-            }
-        }
+            MSG_JournalRecordMsg( msg );
         if (remove) QUEUE_RemoveMsg( sysMsgQueue, pos );
         return TRUE;
     }
@@ -336,7 +379,7 @@
 
     if (queue->hWnd)
     {
-        fprintf( stderr, "Nested SendMessage() not supported\n" );
+        fprintf( stderr, "Nested SendMessage(), msg %04x skipped\n", msg );
         return 0;
     }
     queue->hWnd   = hwnd;
@@ -479,24 +522,31 @@
 
 	if ((msgQueue->wakeBits & mask) & QS_PAINT)
 	{
+	    WND* wndPtr;
 	    msg->hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
 	    msg->message = WM_PAINT;
 	    msg->wParam = 0;
 	    msg->lParam = 0;
-            if( msg->hwnd &&
-              (!hwnd || msg->hwnd == hwnd || IsChild(hwnd,msg->hwnd)) )
-              {
-                WND* wndPtr = WIN_FindWndPtr(msg->hwnd);
 
-	        /* FIXME: WM_PAINTICON should be sent sometimes */
+	    if ((wndPtr = WIN_FindWndPtr(msg->hwnd)))
+	    {
+                if( wndPtr->dwStyle & WS_MINIMIZE &&
+                    wndPtr->class->hIcon )
+                {
+                    msg->message = WM_PAINTICON;
+                    msg->wParam = 1;
+                }
 
-                if( wndPtr->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
-                  {
-                    wndPtr->flags &= ~WIN_INTERNAL_PAINT;
-                    QUEUE_DecPaintCount( hQueue );
-                  }
-                break;
-              }
+                if( !hwnd || msg->hwnd == hwnd || IsChild(hwnd,msg->hwnd) )
+                {
+                    if( wndPtr->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
+                    {
+                        wndPtr->flags &= ~WIN_INTERNAL_PAINT;
+                        QUEUE_DecPaintCount( hQueue );
+                    }
+                    break;
+                }
+	    }
 	}
 
         /* Check for timer messages, but yield first */
@@ -535,36 +585,52 @@
  * 'hwnd' must be the handle of the dialog or menu window.
  * 'code' is the message filter value (MSGF_??? codes).
  */
-BOOL MSG_InternalGetMessage( SEGPTR msg, HWND hwnd, HWND hwndOwner, short code,
+BOOL MSG_InternalGetMessage( MSG16 *msg, HWND hwnd, HWND hwndOwner, short code,
 			     WORD flags, BOOL sendIdle ) 
 {
     for (;;)
     {
 	if (sendIdle)
 	{
-	    if (!MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
-                                  0, 0, 0, flags, TRUE ))
+	    if (!MSG_PeekMessage( msg, 0, 0, 0, flags, TRUE ))
 	    {
 		  /* No message present -> send ENTERIDLE and wait */
                 if (IsWindow(hwndOwner))
                     SendMessage16( hwndOwner, WM_ENTERIDLE,
                                    code, (LPARAM)hwnd );
-		MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
-                                 0, 0, 0, flags, FALSE );
+		MSG_PeekMessage( msg, 0, 0, 0, flags, FALSE );
 	    }
 	}
 	else  /* Always wait for a message */
-	    MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
-                             0, 0, 0, flags, FALSE );
+	    MSG_PeekMessage( msg, 0, 0, 0, flags, FALSE );
 
-	if (!CallMsgFilter( msg, code ))
-            return (((MSG16 *)PTR_SEG_TO_LIN(msg))->message != WM_QUIT);
+        /* Call message filters */
 
-	  /* Message filtered -> remove it from the queue */
-	  /* if it's still there. */
-	if (!(flags & PM_REMOVE))
-	    MSG_PeekMessage( (MSG16 *)PTR_SEG_TO_LIN(msg),
-                             0, 0, 0, PM_REMOVE, TRUE );
+        if (HOOK_GetHook( WH_SYSMSGFILTER, GetTaskQueue(0) ) ||
+            HOOK_GetHook( WH_MSGFILTER, GetTaskQueue(0) ))
+        {
+            MSG16 *pmsg = SEGPTR_NEW(MSG16);
+            if (pmsg)
+            {
+                BOOL32 ret;
+                *pmsg = *msg;
+                ret = (HOOK_CallHooks( WH_SYSMSGFILTER, code, 0,
+                                       (LPARAM)SEGPTR_GET(pmsg) ) ||
+                       HOOK_CallHooks( WH_MSGFILTER, code, 0,
+                                       (LPARAM)SEGPTR_GET(pmsg) ));
+                SEGPTR_FREE(pmsg);
+                if (ret)
+                {
+                    /* Message filtered -> remove it from the queue */
+                    /* if it's still there. */
+                    if (!(flags & PM_REMOVE))
+                        MSG_PeekMessage( msg, 0, 0, 0, PM_REMOVE, TRUE );
+                    continue;
+                }
+            }
+        }
+
+        return (msg->message != WM_QUIT);
     }
 }
 
@@ -665,13 +731,6 @@
 {
     WND * wndPtr;
     LRESULT ret;
-    struct
-    {
-	LPARAM   lParam;
-	WPARAM16 wParam;
-	UINT16   wMsg;
-	HWND16   hWnd;
-    } msgstruct = { lParam, wParam, msg, hwnd };
 
 #ifdef CONFIG_IPC
     MSG16 DDE_msg = { hwnd, msg, wParam, lParam };
@@ -694,19 +753,37 @@
         return TRUE;
     }
 
-    HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1,
-                    (LPARAM)MAKE_SEGPTR(&msgstruct) );
-    hwnd   = msgstruct.hWnd;
-    msg    = msgstruct.wMsg;
-    wParam = msgstruct.wParam;
-    lParam = msgstruct.lParam;
+    if (HOOK_GetHook( WH_CALLWNDPROC, GetTaskQueue(0) ))
+    { 
+        struct msgstruct
+        {
+            LPARAM   lParam;
+            WPARAM16 wParam;
+            UINT16   wMsg;
+            HWND16   hWnd;
+        } *pmsg;
+        
+        if ((pmsg = SEGPTR_NEW(struct msgstruct)))
+        {
+            pmsg->hWnd   = hwnd;
+            pmsg->wMsg   = msg;
+            pmsg->wParam = wParam;
+            pmsg->lParam = lParam;
+            HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1,
+                            (LPARAM)SEGPTR_GET(pmsg) );
+            hwnd   = pmsg->hWnd;
+            msg    = pmsg->wMsg;
+            wParam = pmsg->wParam;
+            lParam = pmsg->lParam;
+        }
+    }
 
     if (!(wndPtr = WIN_FindWndPtr( hwnd )))
     {
         fprintf( stderr, "SendMessage16: invalid hwnd %04x\n", hwnd );
         return 0;
     }
-    if (wndPtr->hmemTaskQ == QUEUE_GetDoomedQueue())
+    if (QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ))
         return 0;  /* Don't send anything if the task is dying */
     if (wndPtr->hmemTaskQ != GetTaskQueue(0))
         return MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam );
@@ -758,8 +835,9 @@
         return ret;
     }
 
-    if (wndPtr->hmemTaskQ == QUEUE_GetDoomedQueue())
+    if (QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ))
         return 0;  /* Don't send anything if the task is dying */
+
     if (wndPtr->hmemTaskQ != GetTaskQueue(0))
     {
         fprintf( stderr, "SendMessage32A: intertask message not supported\n" );
@@ -800,7 +878,7 @@
         fprintf( stderr, "SendMessage32W: invalid hwnd %08x\n", hwnd );
         return 0;
     }
-    if (wndPtr->hmemTaskQ == QUEUE_GetDoomedQueue())
+    if (QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ))
         return 0;  /* Don't send anything if the task is dying */
     if (wndPtr->hmemTaskQ != GetTaskQueue(0))
     {
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 0846325..64de6c0 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -16,7 +16,6 @@
 #include "menu.h"
 #include "winpos.h"
 #include "scroll.h"
-#include "stackframe.h"
 #include "nonclient.h"
 #include "graphics.h"
 #include "queue.h"
@@ -235,17 +234,20 @@
 {
     RECT16 tmpRect = { 0, 0, 0, 0 };
 
-    NC_AdjustRect( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
-    winRect->left   -= tmpRect.left;
-    winRect->top    -= tmpRect.top;
-    winRect->right  -= tmpRect.right;
-    winRect->bottom -= tmpRect.bottom;
-
-    if (HAS_MENU(pWnd))
+    if( !( pWnd->dwStyle & WS_MINIMIZE ) )
     {
+      NC_AdjustRect( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
+      winRect->left   -= tmpRect.left;
+      winRect->top    -= tmpRect.top;
+      winRect->right  -= tmpRect.right;
+      winRect->bottom -= tmpRect.bottom;
+
+      if (HAS_MENU(pWnd))
+      {
 	winRect->top += MENU_GetMenuBarHeight( pWnd->hwndSelf,
                                                winRect->right - winRect->left,
-                                             -tmpRect.left, -tmpRect.top ) + 1;
+                                              -tmpRect.left, -tmpRect.top ) + 1;
+      }
     }
     return 0;
 }
@@ -430,14 +432,17 @@
     HBITMAP hbitmap;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
-    NC_GetInsideRect( hwnd, &rect );
-    hdcMem = CreateCompatibleDC( hdc );
-    hbitmap = SelectObject( hdcMem, hbitmapClose );
-    BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
-            hdcMem, (wndPtr->dwStyle & WS_CHILD) ? SYSMETRICS_CXSIZE : 0, 0,
-            down ? NOTSRCCOPY : SRCCOPY );
-    SelectObject( hdcMem, hbitmap );
-    DeleteDC( hdcMem );
+    if( !(wndPtr->flags & WIN_MANAGED) )
+    {
+      NC_GetInsideRect( hwnd, &rect );
+      hdcMem = CreateCompatibleDC( hdc );
+      hbitmap = SelectObject( hdcMem, hbitmapClose );
+      BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
+              hdcMem, (wndPtr->dwStyle & WS_CHILD) ? SYSMETRICS_CXSIZE : 0, 0,
+              down ? NOTSRCCOPY : SRCCOPY );
+      SelectObject( hdcMem, hbitmap );
+      DeleteDC( hdcMem );
+    }
 }
 
 
@@ -447,12 +452,17 @@
 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
 {
     RECT16 rect;
-    NC_GetInsideRect( hwnd, &rect );
-    GRAPH_DrawBitmap( hdc, (IsZoomed(hwnd) ?
-			    (down ? hbitmapRestoreD : hbitmapRestore) :
-			    (down ? hbitmapMaximizeD : hbitmapMaximize)),
-		     rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
-		     0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+    if( !(wndPtr->flags & WIN_MANAGED) )
+    {
+      NC_GetInsideRect( hwnd, &rect );
+      GRAPH_DrawBitmap( hdc, (IsZoomed(hwnd) ?
+			     (down ? hbitmapRestoreD : hbitmapRestore) :
+			     (down ? hbitmapMaximizeD : hbitmapMaximize)),
+		        rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
+		        0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
+    }
 }
 
 
@@ -463,11 +473,15 @@
 {
     RECT16 rect;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
-    NC_GetInsideRect( hwnd, &rect );
-    if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE + 1;
-    GRAPH_DrawBitmap( hdc, (down ? hbitmapMinimizeD : hbitmapMinimize),
-		     rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
-		     0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
+
+    if( !(wndPtr->flags & WIN_MANAGED) )
+    {
+      NC_GetInsideRect( hwnd, &rect );
+      if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE + 1;
+      GRAPH_DrawBitmap( hdc, (down ? hbitmapMinimizeD : hbitmapMinimize),
+		        rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
+		        0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
+    }
 }
 
 
@@ -587,6 +601,8 @@
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     char buffer[256];
 
+    if (wndPtr->flags & WIN_MANAGED) return;
+
     if (!hbitmapClose)
     {
 	if (!(hbitmapClose = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_CLOSE) )))
@@ -658,7 +674,8 @@
 
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
-    if (!wndPtr || !(wndPtr->dwStyle & WS_VISIBLE)) return; /* Nothing to do */
+    if (!wndPtr || wndPtr->dwStyle & WS_MINIMIZE ||
+	!WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
 
     active  = wndPtr->flags & WIN_NCACTIVATED;
 
@@ -666,29 +683,6 @@
 
     if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
 
-    /*
-     * If this is an icon, we don't want to do any more nonclient painting
-     * of the window manager.
-     * If there is a class icon to draw, draw it
-     */
-    if (IsIconic(hwnd))
-    {
-        if (wndPtr->class->hIcon)
-        {
-            SendMessage16(hwnd, WM_ICONERASEBKGND, (WPARAM)hdc, 0);
-            DrawIcon( hdc, 0, 0, wndPtr->class->hIcon );
-        }
-        ReleaseDC(hwnd, hdc);
-        wndPtr->flags &= ~WIN_INTERNAL_PAINT;
-        if( wndPtr->hrgnUpdate )
-          {
-            DeleteObject( wndPtr->hrgnUpdate );
-            QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
-            wndPtr->hrgnUpdate = 0;
-          }
-        return;
-    }
-
     if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
 		        wndPtr->rectClient.top-wndPtr->rectWindow.top,
 		        wndPtr->rectClient.right-wndPtr->rectWindow.left,
@@ -776,14 +770,23 @@
  *
  * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
  */
-LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
+LONG NC_HandleNCActivate( WND *wndPtr, WPARAM wParam )
 {
-    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    WORD wStateChange;
 
-    if (wParam != 0) wndPtr->flags |= WIN_NCACTIVATED;
-    else wndPtr->flags &= ~WIN_NCACTIVATED;
+    if( wParam ) wStateChange = !(wndPtr->flags & WIN_NCACTIVATED);
+    else wStateChange = wndPtr->flags & WIN_NCACTIVATED;
 
-    NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
+    if( wStateChange )
+    {
+      if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
+      else wndPtr->flags &= ~WIN_NCACTIVATED;
+
+      if( wndPtr->dwStyle & WS_MINIMIZE )
+	PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW, 0 );
+      else
+	NC_DoNCPaint( wndPtr->hwndSelf, (HRGN)1, FALSE );
+    }
     return TRUE;
 }
 
@@ -841,6 +844,21 @@
     return (LONG)SetCursor( LoadCursor16( 0, IDC_ARROW ) );
 }
 
+/***********************************************************************
+ *           NC_GetSysPopupPos
+ */
+BOOL 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;
+}
 
 /***********************************************************************
  *           NC_TrackSysMenu
@@ -854,19 +872,16 @@
     int iconic = wndPtr->dwStyle & WS_MINIMIZE;
 
     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
     {
 	  /* Otherwise track the system menu like a normal popup menu */
-	NC_GetInsideRect( hwnd, &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;
+
+	NC_GetSysPopupPos( wndPtr, &rect );
 	if (!iconic) NC_DrawSysButton( hwnd, hdc, TRUE );
-	TrackPopupMenu16( wndPtr->hSysMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
+	TrackPopupMenu16( GetSystemMenu(hwnd, 0), TPM_LEFTALIGN | TPM_LEFTBUTTON,
                           rect.left, rect.bottom, 0, hwnd, &rect );
 	if (!iconic) NC_DrawSysButton( hwnd, hdc, FALSE );
     }
@@ -908,8 +923,7 @@
 	SetCapture(hwnd);
 	while(!hittest)
 	{
-            MSG_InternalGetMessage( MAKE_SEGPTR(&msg), 0, 0, MSGF_SIZE,
-                                    PM_REMOVE, FALSE );
+            MSG_InternalGetMessage( &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE );
 	    switch(msg.message)
 	    {
 	    case WM_MOUSEMOVE:
@@ -1048,8 +1062,7 @@
     {
         int dx = 0, dy = 0;
 
-        MSG_InternalGetMessage( MAKE_SEGPTR(&msg), 0, 0, MSGF_SIZE,
-                                PM_REMOVE, FALSE );
+        MSG_InternalGetMessage( &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE );
 
 	  /* Exit on button-up, Return, or Esc */
 	if ((msg.message == WM_LBUTTONUP) ||
@@ -1151,7 +1164,7 @@
     do
     {
 	BOOL oldstate = pressed;
-        MSG_InternalGetMessage( MAKE_SEGPTR(&msg), 0, 0, 0, PM_REMOVE, FALSE );
+        MSG_InternalGetMessage( &msg, 0, 0, 0, PM_REMOVE, FALSE );
 
 	pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
 	if (pressed != oldstate)
diff --git a/windows/painting.c b/windows/painting.c
index 29a58cb..40f5dff 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -88,10 +88,13 @@
  */
 HDC16 BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps ) 
 {
+    BOOL32 bIcon;
     HRGN hrgnUpdate;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
 
+    bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
+
     wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
 
     if (wndPtr->flags & WIN_NEEDS_NCPAINT) WIN_UpdateNCArea( wndPtr, TRUE );
@@ -107,13 +110,15 @@
 
     dprintf_win(stddeb,"hrgnUpdate = %04x, ", hrgnUpdate);
 
-    lps->hdc = GetDCEx( hwnd, hrgnUpdate, DCX_INTERSECTRGN | DCX_WINDOWPAINT | DCX_USESTYLE );
+    /* When bIcon is TRUE hrgnUpdate is automatically in window coordinates
+     * (because rectClient == rectWindow for WS_MINIMIZE windows).
+     */
+
+    lps->hdc = GetDCEx( hwnd, hrgnUpdate, DCX_INTERSECTRGN | DCX_WINDOWPAINT |
+                        DCX_USESTYLE | (bIcon ? DCX_WINDOW : 0) );
 
     dprintf_win(stddeb,"hdc = %04x\n", lps->hdc);
 
-    /* pseudocode from "Internals" doesn't delete hrgnUpdate - yet another clue
-       that ReleaseDC should take care of it (hence DCX_KEEPCLIPRGN) */
-
     if (!lps->hdc)
     {
         fprintf(stderr, "GetDCEx() failed in BeginPaint(), hwnd=%04x\n", hwnd);
@@ -126,7 +131,9 @@
     if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
     {
         wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
-        lps->fErase = !SendMessage16(hwnd, WM_ERASEBKGND, (WPARAM)lps->hdc, 0);
+        lps->fErase = !SendMessage16(hwnd, (bIcon) ? WM_ICONERASEBKGND
+                                                   : WM_ERASEBKGND,
+                                     (WPARAM)lps->hdc, 0 );
     }
     else lps->fErase = TRUE;
 
@@ -218,20 +225,32 @@
 
 
 /***********************************************************************
- *           RedrawWindow32    (USER32.425)
+ *           PAINT_RedrawWindow
+ *
+ * Note: Windows uses WM_SYNCPAINT to cut down the number of intertask
+ * SendMessage() calls. From SDK:
+ *   This message avoids lots of inter-app message traffic
+ *   by switching to the other task and continuing the
+ *   recursion there.
+ * 
+ * wParam         = flags
+ * LOWORD(lParam) = hrgnClip
+ * HIWORD(lParam) = hwndSkip  (not used; always NULL)
  */
-BOOL32 RedrawWindow32( HWND32 hwnd, const RECT32 *rectUpdate,
-                       HRGN32 hrgnUpdate, UINT32 flags )
+BOOL32 PAINT_RedrawWindow( HWND32 hwnd, const RECT32 *rectUpdate,
+                         HRGN32 hrgnUpdate, UINT32 flags, UINT32 control )
 {
+    BOOL32 bIcon;
     HRGN hrgn;
     RECT32 rectClient;
-    WND * wndPtr;
+    WND* wndPtr;
 
     if (!hwnd) hwnd = GetDesktopWindow();
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
     if (!IsWindowVisible(hwnd) || (wndPtr->flags & WIN_NO_REDRAW))
         return TRUE;  /* No redraw needed */
 
+    bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
     if (rectUpdate)
     {
         dprintf_win(stddeb, "RedrawWindow: %04x %d,%d-%d,%d %04x flags=%04x\n",
@@ -283,7 +302,7 @@
 	   }
 	else
              if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
-	flags |= RDW_FRAME;  /* Force invalidating the frame of children */
+	flags |= RDW_FRAME;  /* Force children frame invalidation */
     }
     else if (flags & RDW_VALIDATE)  /* Validate */
     {
@@ -335,7 +354,8 @@
 
     if (flags & RDW_UPDATENOW)
     {
-        if (wndPtr->hrgnUpdate) SendMessage16( hwnd, WM_PAINT, 0, 0 );
+        if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */
+            SendMessage16( hwnd, (bIcon) ? WM_PAINTICON : WM_PAINT, bIcon, 0 );
     }
     else if (flags & RDW_ERASENOW)
     {
@@ -345,18 +365,16 @@
         if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
         {
             HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
-                               DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN | DCX_WINDOWPAINT);
+                               DCX_INTERSECTRGN | DCX_USESTYLE |
+                               DCX_KEEPCLIPRGN | DCX_WINDOWPAINT |
+                               (bIcon ? DCX_WINDOW : 0) );
             if (hdc)
             {
-              /* Don't send WM_ERASEBKGND to icons */
-              /* (WM_ICONERASEBKGND is sent during processing of WM_NCPAINT) */
-                if (!(wndPtr->dwStyle & WS_MINIMIZE) ||
-                    !wndPtr->class->hIcon)
-                {
-                    if (SendMessage16( hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0 ))
-                        wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
-                }
-                ReleaseDC( hwnd, hdc );
+               if (SendMessage16( hwnd, (bIcon) ? WM_ICONERASEBKGND
+						: WM_ERASEBKGND,
+                                  (WPARAM)hdc, 0 ))
+                  wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
+               ReleaseDC( hwnd, hdc );
             }
         }
     }
@@ -364,42 +382,65 @@
       /* Recursively process children */
 
     if (!(flags & RDW_NOCHILDREN) &&
-	((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)))
+        ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) &&
+	!(wndPtr->dwStyle & WS_MINIMIZE) )
     {
-	if (hrgnUpdate)
+        if ( hrgnUpdate || rectUpdate )
 	{
-	    HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
-	    if (!hrgn) return TRUE;
-	    for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
-	    {
-		CombineRgn( hrgn, hrgnUpdate, 0, RGN_COPY );
-		OffsetRgn( hrgn, -wndPtr->rectClient.left,
-			         -wndPtr->rectClient.top );
-		RedrawWindow32( wndPtr->hwndSelf, NULL, hrgn, flags );
-	    }
-	    DeleteObject( hrgn );
+	   if( !(hrgn = CreateRectRgn( 0, 0, 0, 0 )) ) return TRUE;
+	   if( !hrgnUpdate )
+	     {
+	        control |= (RDW_C_DELETEHRGN | RDW_C_USEHRGN);
+ 	        if( !(hrgnUpdate = CreateRectRgnIndirect32( rectUpdate )) )
+                {
+                    DeleteObject( hrgn );
+                    return TRUE;
+                }
+	     }
+           for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
+	     if( wndPtr->dwStyle & WS_VISIBLE )
+	       {
+                 SetRectRgn( hrgn, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
+                                   wndPtr->rectWindow.right, wndPtr->rectWindow.bottom);
+                 if( CombineRgn( hrgn, hrgn, hrgnUpdate, RGN_AND ) != NULLREGION )
+                 {
+		   if( control & RDW_C_USEHRGN &&
+		       wndPtr->dwStyle & WS_CLIPSIBLINGS ) 
+		       CombineRgn( hrgnUpdate, hrgnUpdate, hrgn, RGN_DIFF );
+
+                   OffsetRgn( hrgn, -wndPtr->rectClient.left,
+                                 -wndPtr->rectClient.top );
+                   PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn, flags, RDW_C_USEHRGN );
+                 }
+               }
+	   DeleteObject( hrgn );
+	   if( control & RDW_C_DELETEHRGN ) DeleteObject( hrgnUpdate );
 	}
-	else
-	{
-	    RECT32 rect;
-	    for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
-	    {
-		if (rectUpdate)
-		{
-		    rect = *rectUpdate;
-		    OffsetRect32( &rect, -wndPtr->rectClient.left,
-                                         -wndPtr->rectClient.top );
-		    RedrawWindow32( wndPtr->hwndSelf, &rect, 0, flags );
-		}
-		else RedrawWindow32( wndPtr->hwndSelf, NULL, 0, flags );
-	    }
-	}
+	else for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
+		  PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, flags, 0 );
+
     }
     return TRUE;
 }
 
 
 /***********************************************************************
+ *           RedrawWindow32    (USER32.425)
+ */
+BOOL32 RedrawWindow32( HWND32 hwnd, const RECT32 *rectUpdate,
+                       HRGN32 hrgnUpdate, UINT32 flags )
+{
+    WND* wnd = WIN_FindWndPtr( hwnd );
+
+    /* check if there is something to redraw */
+
+    return ( wnd && WIN_IsWindowDrawable( wnd, !(flags & RDW_FRAME) ) )
+           ? PAINT_RedrawWindow( hwnd, rectUpdate, hrgnUpdate, flags, 0 )
+	   : 1;
+}
+
+
+/***********************************************************************
  *           RedrawWindow16    (USER.290)
  */
 BOOL16 RedrawWindow16( HWND16 hwnd, const RECT16 *rectUpdate,
@@ -429,7 +470,7 @@
  */
 void InvalidateRgn( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase )
 {
-    RedrawWindow32(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0));
+    RedrawWindow32(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
 }
 
 
diff --git a/windows/queue.c b/windows/queue.c
index 3ae6306..b827727 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -84,11 +84,11 @@
 
 
 /***********************************************************************
- *	     QUEUE_GetDoomedQueue/QUEUE_SetDoomedQueue
+ *	     QUEUE_IsDoomedQueue
  */
-HQUEUE16 QUEUE_GetDoomedQueue()
+BOOL32 QUEUE_IsDoomedQueue( HQUEUE16 hQueue )
 {
-    return hDoomedQueue;
+    return (hDoomedQueue && (hQueue == hDoomedQueue));
 }
 
 
diff --git a/windows/scroll.c b/windows/scroll.c
index 7c11953..9b8d699 100644
--- a/windows/scroll.c
+++ b/windows/scroll.c
@@ -41,6 +41,8 @@
                                 (int)((clipRect)?clipRect->right:0), 
                                 (int)((clipRect)?clipRect->bottom:0));
 
+    if ( !wndScroll || !WIN_IsWindowDrawable( wndScroll, TRUE ) ) return;
+
     if ( !rect ) /* do not clip children */
        {
 	  GetClientRect16(hwnd, &rc);
@@ -87,10 +89,8 @@
                      SWP_DEFERERASE );
     }
 
-    /* RDW_ALLCHILDREN is to account for dialog controls */
-
-    RedrawWindow32( hwnd, NULL, hrgnUpdate, RDW_ALLCHILDREN |
-					    RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW);
+    PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_ALLCHILDREN |
+			    RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW, RDW_C_USEHRGN );
 
     DeleteObject(hrgnUpdate);
     if( hCaretWnd ) ShowCaret(hCaretWnd);
@@ -250,8 +250,8 @@
 
     if (flags | SW_INVALIDATE)
     {
-	RedrawWindow32( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
-                        ((flags & SW_ERASE) ? RDW_ERASENOW : 0));
+	PAINT_RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
+                        ((flags & SW_ERASE) ? RDW_ERASENOW : 0), 0 );
     }
 
     ReleaseDC(hwnd, hdc);
diff --git a/windows/win.c b/windows/win.c
index 63e8564..95e7923 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -224,7 +224,11 @@
     HWND hwndRet;
     WND *pWnd = pWndDesktop;
 
-    /* Note: the desktop window never gets WM_PAINT messages */
+    /* Note: the desktop window never gets WM_PAINT messages 
+     * The real reason why is because Windows DesktopWndProc
+     * does ValidateRgn inside WM_ERASEBKGND handler.
+     */
+
     pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
 
     for ( ; pWnd ; pWnd = pWnd->next )
@@ -265,7 +269,7 @@
  * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
  * the window has the WS_EX_NOPARENTNOTIFY style.
  */
-void WIN_SendParentNotify( HWND32 hwnd, WORD event, WORD idChild, LONG lValue )
+void WIN_SendParentNotify(HWND32 hwnd, WORD event, WORD idChild, LPARAM lValue)
 {
     LPPOINT16 lppt = (LPPOINT16)&lValue;
     WND     *wndPtr = WIN_FindWndPtr( hwnd );
@@ -274,10 +278,7 @@
     /* if lValue contains cursor coordinates they have to be
      * mapped to the client area of parent window */
 
-    if (bMouse) MapWindowPoints16(0, hwnd, lppt, 1);
-#ifndef WINELIB32
-    else lValue = MAKELONG( LOWORD(lValue), idChild );
-#endif
+    if (bMouse) MapWindowPoints16( 0, hwnd, lppt, 1 );
 
     while (wndPtr)
     {
@@ -291,12 +292,8 @@
         }
 
         wndPtr = wndPtr->parent;
-#ifdef WINELIB32
 	SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY, 
                         MAKEWPARAM( event, idChild ), lValue );
-#else
-	SendMessage16( wndPtr->hwndSelf, WM_PARENTNOTIFY, event, (LPARAM)lValue);
-#endif
     }
 }
 
@@ -364,7 +361,6 @@
 BOOL32 WIN_CreateDesktopWindow(void)
 {
     CLASS *class;
-    HDC hdc;
     HWND hwndDesktop;
 
     dprintf_win(stddeb,"Creating desktop window\n");
@@ -415,11 +411,7 @@
     WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
     EVENT_RegisterWindow( pWndDesktop );
     SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
-    if ((hdc = GetDC( hwndDesktop )) != 0)
-    {
-        SendMessage32A( hwndDesktop, WM_ERASEBKGND, hdc, 0 );
-        ReleaseDC( hwndDesktop, hdc );
-    }
+    pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
     return TRUE;
 }
 
@@ -705,7 +697,7 @@
                                                    wndPtr->rectClient.top ));
     } 
 
-    WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
+    WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LPARAM)hwnd );
     if (!IsWindow(hwnd)) return 0;
 
     /* Show the window, maximizing or minimizing if needed */
@@ -904,7 +896,7 @@
 		      SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
     if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
 	ReleaseCapture();
-    WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
+    WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
 
     CLIPBOARD_DisOwn( hwnd );
 
@@ -1543,8 +1535,29 @@
     return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
 }
 
- 
- 
+/***********************************************************************
+ *           WIN_IsWindowDrawable
+ * 
+ * hwnd is drawable when it is visible, all parents are not 
+ * minimized, and it is itself not minimized unless we are 
+ * trying to draw icon and the default class icon is set.
+ */
+BOOL32 WIN_IsWindowDrawable( WND* wnd , BOOL32 icon )
+{
+  HWND   hwnd= wnd->hwndSelf;
+  BOOL32 yes = TRUE;
+
+  while(wnd && yes)
+  { 
+    if( wnd->dwStyle & WS_MINIMIZE )
+	if( wnd->hwndSelf != hwnd ) break;
+	else if( icon && wnd->class->hIcon ) break;
+
+    yes = yes && (wnd->dwStyle & WS_VISIBLE);
+    wnd = wnd->parent; }      
+  return (!wnd && yes);
+}
+
 /*******************************************************************
  *         GetTopWindow    (USER.229)
  */
@@ -1824,8 +1837,8 @@
         }
         else
         {
-            RedrawWindow32( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
-                            RDW_UPDATENOW | RDW_FRAME );
+            PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
+					  RDW_UPDATENOW | RDW_FRAME, 0 );
             wndPtr->flags &= ~WIN_NCACTIVATED;
         }
         return TRUE;
diff --git a/windows/winpos.c b/windows/winpos.c
index c6132bb..cfbb72e 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -16,7 +16,6 @@
 #include "hook.h"
 #include "message.h"
 #include "queue.h"
-#include "stackframe.h"
 #include "options.h"
 #include "winpos.h"
 #include "dce.h"
@@ -32,6 +31,11 @@
 #define  SWP_AGG_STATUSFLAGS \
     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
 
+#define SMC_NOCOPY		0x0001
+#define SMC_NOPARENTERASE	0x0002
+#define SMC_DRAWFRAME		0x0004
+#define SMC_SETXPOS		0x0008
+
 /* ----- external functions ----- */
 
 extern void 	FOCUS_SwitchFocus( HWND , HWND );
@@ -574,6 +578,7 @@
                 y  = wndPtr->ptIconPos.y;
                 cx = SYSMETRICS_CXICON;
                 cy = SYSMETRICS_CYICON;
+		swpflags |= SWP_NOCOPYBITS;
             }
             else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
 	    break;
@@ -597,6 +602,7 @@
 		         swpflags |= SWP_NOSIZE | SWP_NOMOVE;
 			 break;
 			}
+		    else swpflags |= SWP_NOCOPYBITS;
 
                 cx = maxSize.x;
                 cy = maxSize.y;
@@ -650,6 +656,7 @@
                     cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
                     cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
                 }
+		swpflags |= SWP_NOCOPYBITS;
             }
             else if (wndPtr->dwStyle & WS_MAXIMIZE)
             {
@@ -1179,11 +1186,14 @@
         pWndCur = wndPtr->next;
         while (pWndCur != pWndPrevAfter)
         {
-            RECT16 rect = pWndCur->rectWindow;
-            OffsetRect16( &rect, -wndPtr->rectClient.left,
+            RECT32 rect = { pWndCur->rectWindow.left,
+			    pWndCur->rectWindow.top,
+			    pWndCur->rectWindow.right,
+			    pWndCur->rectWindow.bottom };
+            OffsetRect32( &rect, -wndPtr->rectClient.left,
                           -wndPtr->rectClient.top );
-            RedrawWindow16( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
-                            RDW_FRAME | RDW_ERASE );
+            PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
+                              RDW_FRAME | RDW_ERASE, 0 );
             pWndCur = pWndCur->next;
         }
     }
@@ -1194,11 +1204,14 @@
         WIN_LinkWindow( hwnd, hwndAfter );
         while (pWndCur != wndPtr)
         {
-            RECT16 rect = wndPtr->rectWindow;
-            OffsetRect16( &rect, -pWndCur->rectClient.left,
+            RECT32 rect = { pWndCur->rectWindow.left,
+                            pWndCur->rectWindow.top,
+                            pWndCur->rectWindow.right,
+                            pWndCur->rectWindow.bottom };
+            OffsetRect32( &rect, -pWndCur->rectClient.left,
                           -pWndCur->rectClient.top );
-            RedrawWindow16( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
-                            RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE );
+            PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
+                              RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
             pWndCur = pWndCur->next;
         }
     }
@@ -1288,7 +1301,7 @@
  * update regions are in window client coordinates
  * client and window rectangles are in parent client coordinates
  */
-static void WINPOS_SizeMoveClean(WND* Wnd, HRGN oldVisRgn, LPRECT16 lpOldWndRect, LPRECT16 lpOldClientRect, BOOL bNoCopy )
+static UINT WINPOS_SizeMoveClean(WND* Wnd, HRGN oldVisRgn, LPRECT16 lpOldWndRect, LPRECT16 lpOldClientRect, UINT uFlags )
 {
  HRGN newVisRgn    = DCE_GetVisRgn(Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS );
  HRGN dirtyRgn     = CreateRectRgn(0,0,0,0);
@@ -1301,16 +1314,14 @@
 		   Wnd->rectClient.left,Wnd->rectClient.top,Wnd->rectClient.right,Wnd->rectClient.bottom,
 		   lpOldClientRect->left,lpOldClientRect->top,lpOldClientRect->right,lpOldClientRect->bottom);
 
+ if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
+     (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
+     uFlags |= SMC_DRAWFRAME;
+
  CombineRgn( dirtyRgn, newVisRgn, 0, RGN_COPY);
 
- if( !bNoCopy )
-   {
-     HRGN hRgn = CreateRectRgn( lpOldClientRect->left - lpOldWndRect->left, lpOldClientRect->top - lpOldWndRect->top,
-				lpOldClientRect->right - lpOldWndRect->left, lpOldClientRect->bottom - lpOldWndRect->top);
-     CombineRgn( newVisRgn, newVisRgn, oldVisRgn, RGN_AND ); 
-     CombineRgn( newVisRgn, newVisRgn, hRgn, RGN_AND );
-     DeleteObject(hRgn);
-   }
+ if( !(uFlags & SMC_NOCOPY) )
+   CombineRgn( newVisRgn, newVisRgn, oldVisRgn, RGN_AND ); 
 
  /* map regions to the parent client area */
  
@@ -1331,72 +1342,78 @@
  my =  (Wnd->hrgnUpdate > 1)? CombineRgn( newVisRgn, newVisRgn, Wnd->hrgnUpdate, RGN_DIFF)
                             : COMPLEXREGION;
 
- if( bNoCopy )		/* invalidate Wnd visible region */
+ if( uFlags & SMC_NOCOPY )	/* invalidate Wnd visible region */
    {
-     if (my != NULLREGION)  RedrawWindow32( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
-		            RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
+     if (my != NULLREGION)  PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
+		            RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
    } 
  else			/* bitblt old client area */
    { 
      HDC   hDC;
      int   update;
      HRGN  updateRgn;
+     int   xfrom,yfrom,xto,yto,width,height;
 
-     /* client rect */
+     if( uFlags & SMC_DRAWFRAME )
+       {
+	 /* copy only client area, frame will be redrawn anyway */
 
-     updateRgn = CreateRectRgn( 0,0, Wnd->rectClient.right - Wnd->rectClient.left,
-				Wnd->rectClient.bottom - Wnd->rectClient.top );
+         xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
+         xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
+         width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
+	 updateRgn = CreateRectRgn( 0, 0, width, height );
+	 CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
+	 SetRectRgn( updateRgn, 0, 0, Wnd->rectClient.right - xto, Wnd->rectClient.bottom - yto );
+       }
+     else
+       {
+         xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
+         xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
+         width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
+	 updateRgn = CreateRectRgn( xto - Wnd->rectClient.left,
+				    yto - Wnd->rectClient.top,
+				    Wnd->rectWindow.right - Wnd->rectClient.left,
+				    Wnd->rectWindow.bottom - Wnd->rectClient.top );
+       }
 
-     /* clip visible region with client rect */
+     CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
 
-     my = CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
-
-     /* substract result from client rect to get region that won't be copied */
+     /* substract new visRgn from target rect to get a region that won't be copied */
 
      update = CombineRgn( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
 
      /* Blt valid bits using parent window DC */
 
-     if( my != NULLREGION )
+     if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
        {
-	 int xfrom = lpOldClientRect->left;
-	 int yfrom = lpOldClientRect->top;
-	 int xto = Wnd->rectClient.left;
-	 int yto = Wnd->rectClient.top;
+	 
+	 /* compute clipping region in parent client coordinates */
 
-	 /* check if we can skip copying */
+	 OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top);
+	 CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
 
-	 if( xfrom != xto || yfrom != yto )
-	   {
-	     /* compute clipping region in parent client coordinates */
+         hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn, DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CACHE | DCX_CLIPSIBLINGS);
 
-	     OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top);
-	     CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
-
-             hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn, DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CACHE | DCX_CLIPSIBLINGS);
-
-             BitBlt(hDC, xto, yto, lpOldClientRect->right - lpOldClientRect->left, 
-				   lpOldClientRect->bottom - lpOldClientRect->top,
-				   hDC, xfrom, yfrom, SRCCOPY );
+         BitBlt( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
     
-             ReleaseDC( Wnd->parent->hwndSelf, hDC); 
-	  }
+	 ReleaseDC( Wnd->parent->hwndSelf, hDC); 
        }
 
      if( update != NULLREGION )
-         RedrawWindow32( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
-                         RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
+         PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
+                         RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
+     else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
      DeleteObject( updateRgn );
    }
 
  /* erase uncovered areas */
 
- if( other != NULLREGION )
-     RedrawWindow32( Wnd->parent->hwndSelf, NULL, dirtyRgn,
-                     RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
-
+ if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
+      PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
+                        RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
  DeleteObject(dirtyRgn);
  DeleteObject(newVisRgn);
+ return uFlags;
 }
 
 
@@ -1510,11 +1527,13 @@
 BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, INT x, INT y,
 		   INT cx, INT cy, WORD flags )
 {
-    WINDOWPOS16 winpos;
+    WINDOWPOS16 *winpos;
     WND *	wndPtr;
-    RECT16 	newWindowRect, newClientRect;
+    RECT16 	newWindowRect, newClientRect, oldWindowRect;
     HRGN	visRgn = 0;
+    HWND	tempInsertAfter= 0;
     int 	result = 0;
+    UINT 	uFlags = 0;
 
     dprintf_win(stddeb,"SetWindowPos: hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n", 
 						 hwnd, x, y, x+cx, y+cy, flags);  
@@ -1526,15 +1545,16 @@
     if (wndPtr->dwStyle & WS_VISIBLE) flags &= ~SWP_SHOWWINDOW;
     else
     {
+	uFlags |= SMC_NOPARENTERASE; 
 	flags &= ~SWP_HIDEWINDOW;
 	if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
     }
 
 /*     Check for windows that may not be resized 
        FIXME: this should be done only for Windows 3.0 programs 
- */    if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
+       if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
            flags |= SWP_NOSIZE | SWP_NOMOVE;
-
+*/
       /* Check dimensions */
 
     if (cx <= 0) cx = 1;
@@ -1578,45 +1598,48 @@
 
       /* Fill the WINDOWPOS structure */
 
-    winpos.hwnd = hwnd;
-    winpos.hwndInsertAfter = hwndInsertAfter;
-    winpos.x = x;
-    winpos.y = y;
-    winpos.cx = cx;
-    winpos.cy = cy;
-    winpos.flags = flags;
+    if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return FALSE;
+    winpos->hwnd = hwnd;
+    winpos->hwndInsertAfter = hwndInsertAfter;
+    winpos->x = x;
+    winpos->y = y;
+    winpos->cx = cx;
+    winpos->cy = cy;
+    winpos->flags = flags;
     
       /* Send WM_WINDOWPOSCHANGING message */
 
     if (!(flags & SWP_NOSENDCHANGING))
-	SendMessage16( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)MAKE_SEGPTR(&winpos) );
+	SendMessage16( hwnd, WM_WINDOWPOSCHANGING, 0,
+                       (LPARAM)SEGPTR_GET(winpos) );
 
       /* Calculate new position and size */
 
     newWindowRect = wndPtr->rectWindow;
-    newClientRect = wndPtr->rectClient;
+    newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
+						    : wndPtr->rectClient;
 
-    if (!(winpos.flags & SWP_NOSIZE))
+    if (!(winpos->flags & SWP_NOSIZE))
     {
-        newWindowRect.right  = newWindowRect.left + winpos.cx;
-        newWindowRect.bottom = newWindowRect.top + winpos.cy;
+        newWindowRect.right  = newWindowRect.left + winpos->cx;
+        newWindowRect.bottom = newWindowRect.top + winpos->cy;
     }
-    if (!(winpos.flags & SWP_NOMOVE))
+    if (!(winpos->flags & SWP_NOMOVE))
     {
-        newWindowRect.left    = winpos.x;
-        newWindowRect.top     = winpos.y;
-        newWindowRect.right  += winpos.x - wndPtr->rectWindow.left;
-        newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
+        newWindowRect.left    = winpos->x;
+        newWindowRect.top     = winpos->y;
+        newWindowRect.right  += winpos->x - wndPtr->rectWindow.left;
+        newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
 
-	OffsetRect16( &newClientRect, winpos.x - wndPtr->rectWindow.left, 
-                                      winpos.y - wndPtr->rectWindow.top );
+	OffsetRect16( &newClientRect, winpos->x - wndPtr->rectWindow.left, 
+                                      winpos->y - wndPtr->rectWindow.top );
     }
 
-    winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
+    winpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
 
       /* Reposition window in Z order */
 
-    if (!(winpos.flags & SWP_NOZORDER))
+    if (!(winpos->flags & SWP_NOZORDER))
     {
 	/* reorder owned popups if hwnd is top-level window 
          */
@@ -1626,10 +1649,10 @@
 
         if (wndPtr->window)
         {
-            WIN_UnlinkWindow( winpos.hwnd );
-            WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
+            WIN_UnlinkWindow( winpos->hwnd );
+            WIN_LinkWindow( winpos->hwnd, hwndInsertAfter );
         }
-        else WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
+        else WINPOS_MoveWindowZOrder( winpos->hwnd, hwndInsertAfter );
     }
 
     if ( !wndPtr->window && !(flags & SWP_NOREDRAW) && 
@@ -1640,26 +1663,26 @@
       /* Send WM_NCCALCSIZE message to get new client area */
     if( (flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
       {
-         result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
+         result = WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
 				    &wndPtr->rectWindow, &wndPtr->rectClient,
-				    MAKE_SEGPTR(&winpos), &newClientRect );
+				    SEGPTR_GET(winpos), &newClientRect );
 
          /* FIXME: WVR_ALIGNxxx */
 
          if( newClientRect.left != wndPtr->rectClient.left ||
              newClientRect.top != wndPtr->rectClient.top )
-             winpos.flags &= ~SWP_NOCLIENTMOVE;
+             winpos->flags &= ~SWP_NOCLIENTMOVE;
 
          if( (newClientRect.right - newClientRect.left !=
              wndPtr->rectClient.right - wndPtr->rectClient.left) ||
   	    (newClientRect.bottom - newClientRect.top !=
 	     wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
-	     winpos.flags &= ~SWP_NOCLIENTSIZE;
+	     winpos->flags &= ~SWP_NOCLIENTSIZE;
       }
     else
       if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
 				    newClientRect.top != wndPtr->rectClient.top) )
-	    winpos.flags &= ~SWP_NOCLIENTMOVE;
+	    winpos->flags &= ~SWP_NOCLIENTMOVE;
 
     /* Update active DCEs */
 
@@ -1673,33 +1696,40 @@
         DCE_InvalidateDCE(wndPtr->parent, &rect);
       }
 
-    /* Perform the moving and resizing */
+    /* change geometry */
+
+    oldWindowRect = wndPtr->rectWindow;
 
     if (wndPtr->window)
     {
-        RECT16 oldWindowRect = wndPtr->rectWindow;
         RECT16 oldClientRect = wndPtr->rectClient;
 
-        HWND bogusInsertAfter = winpos.hwndInsertAfter;
+        tempInsertAfter = winpos->hwndInsertAfter;
 
-        winpos.hwndInsertAfter = hwndInsertAfter;
-        WINPOS_SetXWindowPos( &winpos );
+        winpos->hwndInsertAfter = hwndInsertAfter;
+
+	/* postpone geometry change */
+
+	if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
+	  {
+              WINPOS_SetXWindowPos( winpos );
+	      winpos->hwndInsertAfter = tempInsertAfter;
+	  }
+	else  uFlags |= SMC_SETXPOS;
 
         wndPtr->rectWindow = newWindowRect;
         wndPtr->rectClient = newClientRect;
-        winpos.hwndInsertAfter = bogusInsertAfter;
 
-	/*  FIXME: should do something like WINPOS_SizeMoveClean */
+	if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
+	  if( (oldClientRect.left - oldWindowRect.left !=
+	       newClientRect.left - newWindowRect.left) ||
+	      (oldClientRect.top - oldWindowRect.top !=
+	       newClientRect.top - newWindowRect.top) || winpos->flags & SWP_NOCOPYBITS )
 
-	if( (oldClientRect.left - oldWindowRect.left !=
-	     newClientRect.left - newWindowRect.left) ||
-	    (oldClientRect.top - oldWindowRect.top !=
-	     newClientRect.top - newWindowRect.top) )
-
-	    RedrawWindow32( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
-                            RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE );
-	else
-	    if( winpos.flags & SWP_FRAMECHANGED )
+	      PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
+                              RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
+	  else
+	      if( winpos->flags & SWP_FRAMECHANGED )
 	      {
 		WORD wErase = 0;
 		RECT32 rect;
@@ -1709,8 +1739,8 @@
 		    rect.left = newClientRect.right; rect.top = newClientRect.top;
 		    rect.right = oldClientRect.right; rect.bottom = newClientRect.bottom;
 		    wErase = 1;
-		    RedrawWindow32( wndPtr->hwndSelf, &rect, 0,
-                                RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN );
+		    PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
+                                      RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
                 }
 		if( oldClientRect.bottom > newClientRect.bottom )
                 {
@@ -1718,33 +1748,41 @@
 		    rect.right = (wErase)?oldClientRect.right:newClientRect.right;
 		    rect.bottom = oldClientRect.bottom;
 		    wErase = 1;
-		    RedrawWindow32( wndPtr->hwndSelf, &rect, 0,
-                                RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN );
+		    PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
+                                      RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
                 }
 		if( !wErase ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
 	      }
     }
     else
     {
-        RECT16 oldWindowRect = wndPtr->rectWindow;
 	RECT16 oldClientRect = wndPtr->rectClient;
 
         wndPtr->rectWindow = newWindowRect;
         wndPtr->rectClient = newClientRect;
 
-        if( !(flags & SWP_NOREDRAW) )
+	if( oldClientRect.bottom - oldClientRect.top ==
+	    newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
+
+	if( oldClientRect.right - oldClientRect.left ==
+	    newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
+
+        if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
 	  {
-	    BOOL bNoCopy = (flags & SWP_NOCOPYBITS) || 
-			   (result >= WVR_HREDRAW && result < WVR_VALIDRECTS);
+	    uFlags |=  ((winpos->flags & SWP_NOCOPYBITS) || 
+			(result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
+	    uFlags |=  (winpos->flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
 
-	    if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
-	        /* optimize cleanup by BitBlt'ing where possible */
-
-	        WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect, &oldClientRect, bNoCopy);
+	    if( (winpos->flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
+		uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect, 
+							      &oldClientRect, uFlags);
 	    else
-	       if( winpos.flags & SWP_FRAMECHANGED )
-        	  RedrawWindow32( winpos.hwnd, NULL, 0, RDW_NOCHILDREN | RDW_FRAME ); 
+	      { 
+		/* adjust frame and do not erase parent */
 
+		if( winpos->flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
+		if( winpos->flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
+	      }
 	  }
         DeleteObject(visRgn);
     }
@@ -1754,14 +1792,19 @@
 	wndPtr->dwStyle |= WS_VISIBLE;
         if (wndPtr->window)
         {
+	    if( uFlags & SMC_SETXPOS )
+	    {
+              WINPOS_SetXWindowPos( winpos );
+              winpos->hwndInsertAfter = tempInsertAfter;
+	    }
             XMapWindow( display, wndPtr->window );
         }
         else
         {
             if (!(flags & SWP_NOREDRAW))
-                RedrawWindow32( winpos.hwnd, NULL, 0,
+                PAINT_RedrawWindow( winpos->hwnd, NULL, 0,
                                 RDW_INVALIDATE | RDW_ALLCHILDREN |
-                                RDW_FRAME | RDW_ERASE );
+                                RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
         }
     }
     else if (flags & SWP_HIDEWINDOW)
@@ -1770,25 +1813,35 @@
         if (wndPtr->window)
         {
             XUnmapWindow( display, wndPtr->window );
+	    if( uFlags & SMC_SETXPOS )
+	    {
+              WINPOS_SetXWindowPos( winpos );
+              winpos->hwndInsertAfter = tempInsertAfter;
+	    }
         }
         else
         {
             if (!(flags & SWP_NOREDRAW))
-                RedrawWindow16( wndPtr->parent->hwndSelf, &wndPtr->rectWindow, 0,
-                                RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
+	    {
+	        RECT32 rect = { oldWindowRect.left, oldWindowRect.top,
+				oldWindowRect.right, oldWindowRect.bottom };
+                PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &rect, 0, 
+			RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW, 0);
+	    }
+	    uFlags |= SMC_NOPARENTERASE;
         }
 
-        if ((winpos.hwnd == GetFocus()) || IsChild(winpos.hwnd, GetFocus()))
-            SetFocus( GetParent(winpos.hwnd) );  /* Revert focus to parent */
+        if ((winpos->hwnd == GetFocus()) || IsChild(winpos->hwnd, GetFocus()))
+            SetFocus( GetParent(winpos->hwnd) );  /* Revert focus to parent */
 
-	if (winpos.hwnd == hwndActive)
+	if (winpos->hwnd == hwndActive)
 	{
 	      /* Activate previously active window if possible */
 	    HWND newActive = hwndPrevActive;
-	    if (!IsWindow(newActive) || (newActive == winpos.hwnd))
+	    if (!IsWindow(newActive) || (newActive == winpos->hwnd))
 	    {
 		newActive = GetTopWindow( GetDesktopWindow() );
-		if (newActive == winpos.hwnd)
+		if (newActive == winpos->hwnd)
                     newActive = wndPtr->next ? wndPtr->next->hwndSelf : 0;
 	    }	    
 	    WINPOS_ChangeActiveWindow( newActive, FALSE );
@@ -1798,7 +1851,7 @@
       /* Activate the window */
 
     if (!(flags & SWP_NOACTIVATE))
-	    WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
+	    WINPOS_ChangeActiveWindow( winpos->hwnd, FALSE );
     
       /* Repaint the window */
 
@@ -1806,19 +1859,21 @@
 
     EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
 
-    if (!(flags & SWP_DEFERERASE))
-        RedrawWindow32( wndPtr->parent->hwndSelf, NULL, 0,
-                        RDW_ALLCHILDREN | RDW_ERASENOW );
+    if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
+        PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
+    else if( wndPtr->parent == WIN_GetDesktop() && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
+	PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
 
       /* And last, send the WM_WINDOWPOSCHANGED message */
 
-    dprintf_win(stddeb,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
+    dprintf_win(stddeb,"\tstatus flags = %04x\n", winpos->flags & SWP_AGG_STATUSFLAGS);
 
-    if ( ((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
-	!(winpos.flags & SWP_NOSENDCHANGING))
-        SendMessage16( winpos.hwnd, WM_WINDOWPOSCHANGED,
-                       0, (LPARAM)MAKE_SEGPTR(&winpos) );
+    if ( ((winpos->flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) && 
+	!(winpos->flags & SWP_NOSENDCHANGING))
+        SendMessage16( winpos->hwnd, WM_WINDOWPOSCHANGED,
+                       0, (LPARAM)SEGPTR_GET(winpos) );
 
+    SEGPTR_FREE(winpos);
     return TRUE;
 }
 
diff --git a/windows/winproc.c b/windows/winproc.c
index 79f99c4..d1c89d7 100644
--- a/windows/winproc.c
+++ b/windows/winproc.c
@@ -679,10 +679,6 @@
             *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
             *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
         }
-        else
-        {
-            *pwparam32 = MAKEWPARAM( wParam16, 0  /* FIXME? */ );
-        }
         return 0;
     case WM_SETTEXT:
         *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);