Release 960331

Sun Mar 31 13:54:46 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [tools/build.c]
	Changed BuildSpec32Files() to generate assembly instead of C code.
	Unified -spec16 and -spec32 options; DLL type is now determined by
	the 'type' declaration in the .spec file.
	New -stdcall option to build all stdcall assembly relays.

	* [if1632/relay.c] [if1632/relay32.c] [include/dlls.h]
	Started to unify 16- and 32-bit builtin DLLs.

	* [loader/module.c]
	Added MODULE_GetWndProcEntry32() to mirror MODULE_GetWndProcEntry16().

	* [loader/pe_image.c] [loader/resource.c]
	All modules now have a NE signature, and can be distinguished by
	the NE_FFLAGS_WIN32 flag.

	* [windows/alias.c]
	Aliases for built-in window procedures are now all created at
	startup in ALIAS_Init().

Fri Mar 29 14:56:39 1996  Greg Kreider <kreider@natlab.research.philips.com>

	* [controls/combo.c]
	Limit rectangle to clear to size of item when painting combo, not
 	default.  Only draw items in list when there is enough room for them.

	* [controls/listbox.c]
	Get the measure of every item that's added and store in the item's
 	data structure.  Scroll listbox if mouse near edge of box.  Only
 	draw items in list when there is enough room.

Fri Mar 29 12:00:00 1996  Alex Korobka <alex@phm30.pharm.sunysb.edu>

	* [windows/defwnd.c] [windows/dialog.c] [windows/mdi.c]
	  [windows/nonclient.c] [controls/menu.c] 
	Various changes for better keyboard handling. 

	* [windows/event.c] [windows/message.c] [misc/keyboard.c]
	Proper keyboard message ordering, working GetKeyState() (finally!), 
	improvements in ToAscii().

	* [windows/win.c] [windows/message.c]
	Small improvements in WIN_FindWinToRepaint.

	* [windows/win.c] [windows/painting.c] [windows/nonclient.c]
	Put update region in WM_NCPAINT wParam.

	* [loader/task.c]
	Kill task timers when task is deleted, switch timers to the
	new queue in SetTaskQueue().

	* [loader/signal.c] [miscemu/dosmem.c]
	Added SIGALRM signal handler to increment BIOS clock. 

	* [windows/win.c] [windows/winpos.c] [windows/mdi.c]
	Fixed ChildWindowFromPoint(), WM_PARENTNOTIFY and its handling by
	MDI client.

	* [windows/winpos.c]
	Improvements in handling of owned popups. "Floating" toolboxes 
	work better now. 

Thu Mar 28 12:38:29 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [misc/registry.c]
	New file, registry rewrite including win32 extensions
	- Unicode
	- multiple valus per key
	- different datatypes for values
	- multiple rootkeys
	- saving and loading in different registries.

	* [include/winreg.h]
	New file, definitions and structs for registry.

	* [include/winerror.h]
	Some new error defines added... there are more, someone please
 	check a (real-)windows winerror.h.
	
	* [if1632/shell.spec] [if1632/advapi32.spec] [if1632/kernel.spec]
	Registry specs added.

	* [if1632/relay.c]
	Switch internal SHELL.DLL to default 'used'.

	* [win32/string32.c] [include/string32.h]
	Some new functions added.
	char should be unsigned char when converting to 16bit ints.

	* [misc/shell.c] [include/shell.h] [win32/advapi.c]
	Removed old registry functions.

Tue Mar 26 15:01:46 1996  Frans van Dorsselaer <dorssel@rulhm1.leidenuniv.nl>

	* [include/bitmaps/ocr_ibeam]
	Fixed the position of the hotspot.

	* [objects/text.c]
	Fixed a few bugs in TEXT_TabbedTextOut().

	* [windows/event.c]
	Fixed the order of the bits in the KeyStateTable.
	0x80 is the up/down-bit.  0x01 is the toggle bit.

	* [loader/resource.c] [windows/mdi.c] [controls/edit.c]
	Fixed the calls to GetKeyState().

Tue Mar 26 08:43:15 1996  Robert Pouliot <krynos@qbc.clic.net>

	* [resources/sysres_Fr.rc] [resources/TODO]
	Updated FIND_TEXT and REPLACE_TEXT to work like the English version.

Mon Mar 25 17:38:59 1996  Tristan Tarrant <tst@dcs.ed.ac.uk>

	* [resources/sysres_it.rc]
	Added support for Italian [It] language.
diff --git a/windows/alias.c b/windows/alias.c
index df87319..5716094 100644
--- a/windows/alias.c
+++ b/windows/alias.c
@@ -7,6 +7,7 @@
 
 #include "windows.h"
 #include "alias.h"
+#include "module.h"
 
 #include "stddebug.h"
 #include "debug.h"
@@ -22,6 +23,22 @@
 
 int ALIAS_UseAliases;
 
+/* Aliased window procedures */
+extern LRESULT ButtonWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT StaticWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT ScrollBarWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT ListBoxWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT ComboBoxWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT ComboLBoxWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT EditWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT PopupMenuWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT DesktopWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT DefDlgProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT MDIClientWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT AboutDlgProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT CARET_Callback( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT SystemMessageBoxProc( HWND, UINT, WPARAM, LPARAM );
+
 /* closed hashing */
 static int ALIAS_LocateHash(DWORD value)
 {
@@ -41,6 +58,48 @@
 	return hash;
 }
 
+
+/***********************************************************************
+ *           ALIAS_RegisterWndProcAlias
+ */
+static void ALIAS_RegisterWndProcAlias( DWORD Wine, const char *name )
+{
+    FARPROC Win16Proc, Win32Proc;
+
+    Win16Proc = MODULE_GetWndProcEntry16( name );
+    Win32Proc = MODULE_GetWndProcEntry32( name );
+    ALIAS_RegisterAlias( Wine, (DWORD)Win16Proc, (DWORD)Win32Proc );
+}
+
+
+/***********************************************************************
+ *           ALIAS_Init
+ *
+ * Create aliases for the standard window procedures.
+ */
+BOOL ALIAS_Init(void)
+{
+    ALIAS_RegisterWndProcAlias( (DWORD)ButtonWndProc, "ButtonWndProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)StaticWndProc, "StaticWndProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)ScrollBarWndProc, "ScrollBarWndProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)ListBoxWndProc, "ListBoxWndProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)ComboBoxWndProc, "ComboBoxWndProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)ComboLBoxWndProc, "ComboLBoxWndProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)EditWndProc, "EditWndProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)PopupMenuWndProc, "PopupMenuWndProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)DesktopWndProc, "DesktopWndProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)DefDlgProc, "DefDlgProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)MDIClientWndProc, "MDIClientWndProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)AboutDlgProc, "AboutDlgProc" );
+    ALIAS_RegisterWndProcAlias( (DWORD)CARET_Callback, "CARET_Callback" );
+    ALIAS_RegisterWndProcAlias( (DWORD)SystemMessageBoxProc, "SystemMessageBoxProc" );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           ALIAS_RegisterAlias
+ */
 void ALIAS_RegisterAlias(DWORD Wine,DWORD Win16, DWORD Win32)
 {
     int whash = 0, w16hash = 0, w32hash = 0, recno=0;
diff --git a/windows/caret.c b/windows/caret.c
index b753d86..294fac5 100644
--- a/windows/caret.c
+++ b/windows/caret.c
@@ -6,9 +6,7 @@
  */
 
 #include "windows.h"
-#include "selectors.h"
-#include "alias.h"
-#include "relay32.h"
+#include "module.h"
 #include "stddebug.h"
 /* #define DEBUG_CARET */
 #include "debug.h"
@@ -88,7 +86,7 @@
 {
     if (Caret.timerid) KillSystemTimer((HWND)0, Caret.timerid);
     Caret.timerid = SetSystemTimer((HWND)0, 0, Caret.timeout,
-			(FARPROC)GetWndProcEntry16("CARET_Callback"));
+                                   MODULE_GetWndProcEntry16("CARET_Callback"));
 }
 
 
@@ -101,7 +99,7 @@
     {
 	KillSystemTimer((HWND)0, Caret.timerid);
 	Caret.timerid = SetSystemTimer((HWND)0, 0, Caret.timeout,
-			(FARPROC)GetWndProcEntry16("CARET_Callback"));
+                                   MODULE_GetWndProcEntry16("CARET_Callback"));
     }
 }
 
@@ -120,27 +118,6 @@
 
 
 /*****************************************************************
- *               CARET_Initialize
- */
-static void CARET_Initialize()
-{
-    DWORD WineProc,Win16Proc,Win32Proc;
-    static int initialized=0;
-
-    if(!initialized)
-    {
-	WineProc = (DWORD)CARET_Callback;
-	Win16Proc = (DWORD)GetWndProcEntry16("CARET_Callback");
-	Win32Proc = (DWORD)RELAY32_GetEntryPoint(
-				RELAY32_GetBuiltinDLL("WINPROCS32"),
-				"CARET_Callback", 0);
-	ALIAS_RegisterAlias(WineProc, Win16Proc, Win32Proc);
-	initialized=1;
-    }
-}
-
-
-/*****************************************************************
  *               CreateCaret          (USER.163)
  */
 BOOL CreateCaret(HWND hwnd, HBITMAP bitmap, INT width, INT height)
@@ -176,9 +153,6 @@
     Caret.y = 0;
 
     Caret.timeout = GetProfileInt( "windows", "CursorBlinkRate", 750 );
-
-    CARET_Initialize();
-
     return TRUE;
 }
    
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 530c5e5..d081f22 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -21,7 +21,11 @@
   /* Last COLOR id */
 #define COLOR_MAX   COLOR_BTNHIGHLIGHT
 
-static short iMenuKey = 0;
+  /* bits in the dwKeyData */
+#define KEYDATA_ALT 		0x2000
+#define KEYDATA_PREVSTATE	0x4000
+
+static short iF10Key = 0;
 static short iMenuSysKey = 0;
 
 /***********************************************************************
@@ -73,7 +77,7 @@
 
     case WM_PAINTICON: 
     case WM_NCPAINT:
-	return NC_HandleNCPaint( hwnd );
+	return NC_HandleNCPaint( hwnd, (HRGN)wParam );
 
     case WM_NCHITTEST:
         {
@@ -246,7 +250,7 @@
 
     case WM_SETTEXT:
 	DEFWND_SetText( hwnd, (LPSTR)PTR_SEG_TO_LIN(lParam) );
-	NC_HandleNCPaint( hwnd );  /* Repaint caption */
+	NC_HandleNCPaint( hwnd , (HRGN)1 );  /* Repaint caption */
 	return 0;
 
     case WM_SETCURSOR:
@@ -257,47 +261,77 @@
 	return NC_HandleSetCursor( hwnd, wParam, lParam );
 
     case WM_SYSCOMMAND:
-        {
-            POINT pt = { LOWORD(lParam), HIWORD(lParam) };
-            return NC_HandleSysCommand( hwnd, wParam, pt );
-        }
-
+	{
+          POINT pt = { LOWORD(lParam), HIWORD(lParam) };
+          return NC_HandleSysCommand( hwnd, wParam, pt );
+	}
     case WM_KEYDOWN:
 
-	if(wParam == VK_F10) iMenuKey = VK_F10;
+	if(wParam == VK_F10) iF10Key = VK_F10;
 	break;
 
     case WM_SYSKEYDOWN:
-	/* this breaks current pseudo accelerators but
-	   creates a basis for implementing real ones */
 
-	if(wParam == VK_F10) 
-	   {
-	    iMenuKey = VK_F10;
-	    break;
-	   }
-	
-	if (wParam == VK_MENU)
-	   {  
-	    iMenuSysKey = (iMenuSysKey)? 0: 1;
-	    iMenuKey    = 0;
-	}
+	if( HIWORD(lParam) & KEYDATA_ALT )
+	  {
+	    /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
+	      if( wParam == VK_MENU && !iMenuSysKey )
+		iMenuSysKey = 1;
+	      else
+		iMenuSysKey = 0;
+	    
+	    iF10Key = 0;
+
+	  } 
+	else if( wParam == VK_F10 )
+	         iF10Key = 1;
+	     else
+	         if( wParam == VK_ESCAPE && GetKeyState(VK_SHIFT) < 0 )
+		     SendMessage( hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, 
+ 						       (LPARAM)VK_SPACE);
 	break;
 
     case WM_KEYUP:
     case WM_SYSKEYUP:
 
-	if( (wParam == VK_MENU && iMenuSysKey) || 
-	    (wParam == VK_F10 && iMenuKey) )
+	/* Press and release F10 or ALT */
 
-	      /* Send to WS_OVERLAPPED parent. TODO: Handle MDI */
+	if( ( wParam == VK_MENU && iMenuSysKey ) 
+	      || ( wParam == VK_F10 && iF10Key ) )
+
 	      SendMessage( WIN_GetTopParent(hwnd), WM_SYSCOMMAND,
 			   SC_KEYMENU, 0L );
 
-	iMenuSysKey = 0;
-	iMenuKey = 0;
+	iMenuSysKey = iF10Key = 0;
         break;
 
+    case WM_SYSCHAR:
+
+	iMenuSysKey = 0;
+
+	if( wParam == VK_RETURN && (wndPtr->dwStyle & WS_MINIMIZE) )
+	  {
+	    PostMessage(hwnd, WM_SYSCOMMAND, (WPARAM)SC_RESTORE, 0L ); 
+	    break;
+	  }  
+
+	if( (HIWORD(lParam) & KEYDATA_ALT) && wParam )
+	  {
+	    if( wParam == VK_TAB || wParam == VK_ESCAPE )
+	      break;
+
+	    if( wParam == VK_SPACE && (wndPtr->dwStyle & WS_CHILD) )
+	      SendMessage( wndPtr->parent->hwndSelf, msg, wParam, lParam );
+	    else
+	      SendMessage(hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)wParam );
+	  } 
+	else
+	  /* check for Ctrl-Esc */
+	  if( wParam != VK_ESCAPE )   
+	      MessageBeep(0);
+	  
+	break;
+
     case WM_SHOWWINDOW:
 	if( !lParam ) return 0; /* sent from ShowWindow */
 
diff --git a/windows/dialog.c b/windows/dialog.c
index 793cffb..a3fc33d 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -655,6 +655,9 @@
 #endif
             }
             break;
+
+	default: 
+	    TranslateMessage( msg );
         }
         break;  /* case WM_KEYDOWN */
 
diff --git a/windows/event.c b/windows/event.c
index eba633f..19fa10a 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -54,8 +54,12 @@
 BOOL AsyncMouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
 BYTE KeyStateTable[256];
 BYTE AsyncKeyStateTable[256];
-static WORD ALTKeyState;
-static HWND captureWnd = 0;
+
+
+       WPARAM   lastEventChar = 0; /* this will have to be changed once
+				    * ToAscii starts working */
+
+static HWND 	captureWnd = 0;
 static BOOL	InputEnabled = TRUE;
 
 /* Keyboard translation tables */
@@ -114,7 +118,8 @@
 	unsigned long count : 16;
 	unsigned long code : 8;
 	unsigned long extended : 1;
-	unsigned long : 4;
+	unsigned long : 2;
+	unsigned long reserved : 2;
 	unsigned long context : 1;
 	unsigned long previous : 1;
 	unsigned long transition : 1;
@@ -303,10 +308,11 @@
     KEYLP keylp;
     BOOL extended = FALSE;
 
-    int count = XLookupString(event, Str, 1, &keysym, &cs);
-    Str[count] = '\0';
-    dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n", 
-	   keysym, count, Str[0], Str);
+    int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
+
+    Str[ascii_chars] = '\0';
+    dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n", 
+	   keysym, ascii_chars, Str[0], Str);
 
     /* Ctrl-Alt-Return enters the debugger */
     if ((keysym == XK_Return) && (event->type == KeyPress) &&
@@ -343,60 +349,59 @@
     }
     else if (key_type == 0)                        /* character key */
     {
-	if (isalnum(key))
-	    vkey = toupper(key);                 /* convert lower to uppercase */
-	else
-	    vkey = 0xbe;
+	if ( isalnum(key) )
+	     vkey = toupper(key);                  /* convert lower to uppercase */
+        else  
+	     vkey = 0xbe;
     }
 
     if (event->type == KeyPress)
     {
-	if (vkey == VK_MENU) ALTKeyState = TRUE;
-	if (!(KeyStateTable[vkey] & 0x0f))
-	    KeyStateTable[vkey] ^= 0x80;
-	KeyStateTable[vkey] |= 0x01;
+        if (!(KeyStateTable[vkey] & 0x80))
+            KeyStateTable[vkey] ^= 0x01;
+	KeyStateTable[vkey] |= 0x80;
 	keylp.lp1.count = 1;
 	keylp.lp1.code = LOBYTE(event->keycode) - 8;
 	keylp.lp1.extended = (extended ? 1 : 0);
-	keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
+	keylp.lp1.reserved = (ascii_chars ? 1 : 0);
+	keylp.lp1.context = ( (event->state & Mod1Mask) || 
+			       (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
 	keylp.lp1.previous = (KeyDown ? 0 : 1);
 	keylp.lp1.transition = 0;
 	dprintf_key(stddeb,"            wParam=%X, lParam=%lX\n", 
 		    vkey, keylp.lp2 );
 	dprintf_key(stddeb,"            KeyState=%X\n", KeyStateTable[vkey]);
-	hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN, 
+	hardware_event( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN, 
 		        vkey, keylp.lp2,
 		        event->x_root - desktopX, event->y_root - desktopY,
 		        event->time, 0 );
 	KeyDown = TRUE;
 
-	/* The key translation ought to take place in TranslateMessage().
-	 * However, there is no way of passing the required information 
-	 * in a Windows message, so TranslateMessage does not currently
-	 * do anything and the translation is done here.
+	/* Currently we use reserved field in the scan-code byte to
+	 * make it possible for TranslateMessage to recognize character keys
+	 * and get them from lastEventChar global variable.
+	 *
+	 * ToAscii should handle it.
 	 */
-	if (count == 1)                /* key has an ASCII representation */
-	{
-	    dprintf_key(stddeb,"WM_CHAR :   wParam=%X\n", (WORD)Str[0] );
-	    PostMessage( GetFocus(), WM_CHAR, (WORD)(unsigned char)(Str[0]), 
-			keylp.lp2 );
-	}
+
+	if( ascii_chars ) lastEventChar = Str[0];
     }
     else
     {
-	if (vkey == VK_MENU) ALTKeyState = FALSE;
-	KeyStateTable[vkey] &= 0xf0;
+	UINT sysKey = KeyStateTable[VK_MENU];
+
+	KeyStateTable[vkey] &= ~0x80; 
 	keylp.lp1.count = 1;
 	keylp.lp1.code = LOBYTE(event->keycode) - 8;
 	keylp.lp1.extended = (extended ? 1 : 0);
+	keylp.lp1.reserved = 0;
 	keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
 	keylp.lp1.previous = 1;
 	keylp.lp1.transition = 1;
 	dprintf_key(stddeb,"            wParam=%X, lParam=%lX\n", 
 		    vkey, keylp.lp2 );
 	dprintf_key(stddeb,"            KeyState=%X\n", KeyStateTable[vkey]);
-	hardware_event( ((ALTKeyState || vkey == VK_MENU) ? 
-			 WM_SYSKEYUP : WM_KEYUP), 
+	hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP, 
 		        vkey, keylp.lp2,
 		        event->x_root - desktopX, event->y_root - desktopY,
 		        event->time, 0 );
diff --git a/windows/keyboard.c b/windows/keyboard.c
index 0c1ae3e..bdf8030 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -15,8 +15,10 @@
 /**********************************************************************
  *		GetKeyState			[USER.106]
  */
-int GetKeyState(int keycode)
+INT GetKeyState(INT keycode)
 {
+    INT retval;
+
     switch(keycode) {
      case VK_LBUTTON:
 	return MouseButtonsStates[0];
@@ -25,8 +27,11 @@
      case VK_RBUTTON:
 	return MouseButtonsStates[2];
      default:
-	return KeyStateTable[keycode];
+	retval = ( (INT)(KeyStateTable[keycode] & 0x80) << 8 ) |
+		   (INT)(KeyStateTable[keycode] & 0x01);
     }
+
+    return retval;
 }
 
 /**********************************************************************
diff --git a/windows/mdi.c b/windows/mdi.c
index f3f8000..a22d1de 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -174,7 +174,10 @@
             if (!wTo || !pWndLast) return 0;
             break;
         }
-        if ((pWnd->dwStyle & WS_VISIBLE) &&
+
+	/* we are not interested in owned popups */
+        if ( !pWnd->owner &&
+	     (pWnd->dwStyle & WS_VISIBLE) &&
             !(pWnd->dwStyle & WS_DISABLED))  /* found one */
         {
             pWndLast = pWnd;
@@ -782,7 +785,7 @@
  
  hSysPopup = GetSystemMenu(hChild,FALSE);
 
- dprintf_mdi(stddeb,"got popup %04x\n in sysmenu %04x",hSysPopup,child->hSysMenu);
+ dprintf_mdi(stddeb,"\t\tgot popup %04x\n in sysmenu %04x",hSysPopup,child->hSysMenu);
  
  if( !InsertMenu(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
                  hSysPopup, (SEGPTR)(DWORD)ci->obmClose) )
@@ -795,6 +798,10 @@
       return 0;
    }
 
+ /* FIXME: add a call to function that sets sysmenu items according
+  *        to the window state. WS_MAXIMIZE -> no SC_SIZE, etc...
+  */
+
  EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
  EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
  EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
@@ -823,6 +830,10 @@
 
  child->dwStyle |= WS_SYSMENU;
 
+  /* FIXME: add a call to function that sets sysmenu items according
+  *        to the window state. WS_MAXIMIZE -> no SC_SIZE, etc...
+  */
+
  RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
  DeleteMenu(frameWnd->wIDmenu,nItems-1,MF_BYPOSITION);
 
@@ -1057,9 +1068,25 @@
 	break;
 	
       case WM_PARENTNOTIFY:
-	if (wParam == WM_LBUTTONDOWN && (ci->hwndHitTest != ci->hwndActiveChild) )
-	     SetWindowPos(ci->hwndHitTest, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
-	break;
+        if( wParam == WM_LBUTTONDOWN )
+          {
+            LPPOINT  lppt = (LPPOINT)(void*)(&lParam);
+            HWND     child = ChildWindowFromPoint(hwnd, *lppt);
+
+	    dprintf_mdi(stddeb,"MDIClient: notification from %04x (%i,%i)\n",child,lppt->x,lppt->y);
+
+            if( child && child != hwnd )
+              {
+                WND*    wnd = WIN_FindWndPtr( child );
+
+                /* if we got owned popup */
+                if( wnd->owner ) child = wnd->owner->hwndSelf;
+
+                if( child != ci->hwndActiveChild )
+                    SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
+              }
+          }
+        return 0;
 
       case WM_SIZE:
 	if( ci->flagChildMaximized )
@@ -1178,10 +1205,6 @@
 
     switch (message)
     {
-      case WM_NCHITTEST:
-	ci->hwndHitTest = hwnd;
-	break;
-	
       case WM_SETTEXT:
 	DefWindowProc(hwnd, message, wParam, lParam);
 	MDI_MenuModifyItem(clientWnd,hwnd);
@@ -1291,6 +1314,12 @@
 	break;
 
       case WM_MENUCHAR:
+
+	/* MDI children don't have menus */
+	PostMessage( clientWnd->parent->hwndSelf, WM_SYSCOMMAND, 
+				          (WPARAM)SC_KEYMENU, (LPARAM)wParam);
+	return 0x00010000L;
+
       case WM_NEXTMENU:
 	   /* set current menu to child system menu */
 
@@ -1321,18 +1350,21 @@
   
   if( wnd->dwStyle & WS_DISABLED ) return 0;
    
-  if( GetKeyState(VK_CONTROL) && !GetKeyState(VK_MENU) )
+  if ((GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_MENU) & 0x8000))
     switch( msg->wParam )
       {
 	case VK_F6:
 	case VK_SEPARATOR:
-	     wParam = (GetKeyState(VK_SHIFT))? SC_NEXTWINDOW: SC_PREVWINDOW;
+	     wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )? SC_NEXTWINDOW: SC_PREVWINDOW;
 	     break;
 	case VK_RBUTTON:
 	     wParam = SC_CLOSE; 
+	     break;
 	default:
 	     return 0;
       }
+  else
+      return 0;
 
   dprintf_mdi(stddeb,"TranslateMDISysAccel: wParam = %04x\n", wParam);
 
diff --git a/windows/message.c b/windows/message.c
index 415f39c..6a88fc6 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -26,10 +26,13 @@
 
 #define HWND_BROADCAST  ((HWND)0xffff)
 
+extern BYTE* 	KeyStateTable;				 /* event.c */
+extern WPARAM	lastEventChar;				 /* event.c */
+
 extern BOOL TIMER_CheckTimer( LONG *next, MSG *msg,
 			      HWND hwnd, BOOL remove );  /* timer.c */
 
-DWORD MSG_WineStartTicks;  /* Ticks at Wine startup */
+DWORD MSG_WineStartTicks;  				 /* Ticks at Wine startup */
 
 static WORD doubleClickSpeed = 452;
 
@@ -180,8 +183,11 @@
     {
 	  /* Send the message to the active window instead,  */
 	  /* translating messages to their WM_SYS equivalent */
+
 	msg->hwnd = GetActiveWindow();
-	msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
+
+	if( msg->message < WM_SYSKEYDOWN )
+	    msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
     }
     return !HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
                             msg->wParam, msg->lParam );
@@ -383,6 +389,7 @@
 {
     int pos, mask;
     MESSAGEQUEUE *msgQueue;
+    HQUEUE	  hQueue;
     LONG nextExp;  /* Next timer expiration time */
 
 #ifdef CONFIG_IPC
@@ -403,7 +410,8 @@
 
     while(1)
     {    
-        msgQueue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) );
+	hQueue   = GetTaskQueue(0);
+        msgQueue = (MESSAGEQUEUE *)GlobalLock( hQueue );
         if (!msgQueue) return FALSE;
 
 	  /* First handle a message put by SendMessage() */
@@ -461,11 +469,24 @@
 	  /* Now find a WM_PAINT message */
 	if ((msgQueue->status & QS_PAINT) && (mask & QS_PAINT))
 	{
-	    msg->hwnd = WIN_FindWinToRepaint( hwnd );
+	    msg->hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
 	    msg->message = WM_PAINT;
 	    msg->wParam = 0;
 	    msg->lParam = 0;
-	    if (msg->hwnd != 0) break;
+            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->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
+                  {
+                    wndPtr->flags &= ~WIN_INTERNAL_PAINT;
+                    QUEUE_DecPaintCount( hQueue );
+                  }
+                break;
+              }
 	}
 
 	  /* Finally handle WM_TIMER messages */
@@ -547,10 +568,14 @@
  */
 BOOL GetMessage( SEGPTR msg, HWND hwnd, UINT first, UINT last ) 
 {
-    MSG_PeekMessage( (MSG *)PTR_SEG_TO_LIN(msg),
+    MSG* lpmsg = (MSG *)PTR_SEG_TO_LIN(msg);
+    MSG_PeekMessage( lpmsg,
                      hwnd, first, last, PM_REMOVE, FALSE );
+
+    dprintf_msg(stddeb,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg->message,
+		     				                 hwnd, first, last );
     HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, 0, (LPARAM)msg );
-    return (((MSG *)PTR_SEG_TO_LIN(msg))->message != WM_QUIT);
+    return (lpmsg->message != WM_QUIT);
 }
 
 
@@ -697,16 +722,35 @@
 
 /***********************************************************************
  *           TranslateMessage   (USER.113)
+ *
+ * This should call ToAscii but it is currently broken
  */
+
+#define ASCII_CHAR_HACK 0x0800
+
 BOOL TranslateMessage( LPMSG msg )
 {
-    int message = msg->message;
+    UINT message = msg->message;
+    /* BYTE wparam[2]; */
     
     if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
 	(message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
     {
-	dprintf_msg(stddeb, "Translating key message\n" );
-	return TRUE;
+	dprintf_msg(stddeb, "Translating key %04x, scancode %04x\n", msg->wParam, 
+							      HIWORD(msg->lParam) );
+
+	if( HIWORD(msg->lParam) & ASCII_CHAR_HACK )
+
+	/*  if( ToAscii( msg->wParam, HIWORD(msg->lParam), (LPSTR)&KeyStateTable,
+				      wparam, 0 ) ) 
+         */
+	      {
+     		message += 2 - (message & 0x0001); 
+
+	        PostMessage( msg->hwnd, message, lastEventChar, msg->lParam );
+
+	        return TRUE;
+	      }
     }
     return FALSE;
 }
diff --git a/windows/msgbox.c b/windows/msgbox.c
index 33ebe2c..c8215fd 100644
--- a/windows/msgbox.c
+++ b/windows/msgbox.c
@@ -7,9 +7,7 @@
 
 #include "windows.h"
 #include "dlgs.h"
-#include "selectors.h"
-#include "alias.h"
-#include "relay32.h"
+#include "module.h"
 #include "win.h"
 #include "resource.h"
 #include "task.h"
@@ -185,27 +183,16 @@
     MSGBOX mbox;
     int ret;
     DWORD WineProc,Win16Proc,Win32Proc;
-    static int initialized = 0;
 
     mbox.title = title;
     mbox.text  = text;
     mbox.type  = type;
 
-    if (!initialized)
-    {
-        WineProc=(DWORD)SystemMessageBoxProc;
-        Win16Proc=(DWORD)GetWndProcEntry16("SystemMessageBoxProc");
-        Win32Proc=(DWORD)RELAY32_GetEntryPoint(RELAY32_GetBuiltinDLL("WINPROCS32"),
-                                               "SystemMessageBoxProc",0);
-        ALIAS_RegisterAlias(WineProc,Win16Proc,Win32Proc);
-        initialized=1;
-    }
-
     handle = SYSRES_LoadResource( SYSRES_DIALOG_MSGBOX );
     if (!handle) return 0;
     ret = DialogBoxIndirectParam( WIN_GetWindowInstance(hWnd),
                                   handle, hWnd,
-                                  GetWndProcEntry16("SystemMessageBoxProc"),
+                                  MODULE_GetWndProcEntry16("SystemMessageBoxProc"),
                                   (LONG)&mbox );
     SYSRES_FreeResource( handle );
     return ret;
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 70b8125..c94ca9c 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -18,6 +18,7 @@
 #include "scroll.h"
 #include "nonclient.h"
 #include "graphics.h"
+#include "queue.h"
 #include "selectors.h"
 #include "stackframe.h"
 #include "stddebug.h"
@@ -618,18 +619,22 @@
 /***********************************************************************
  *           NC_DoNCPaint
  *
- * Paint the non-client area.
+ * Paint the non-client area. clip is currently unused.
  */
-void NC_DoNCPaint( HWND hwnd, BOOL active, BOOL suppress_menupaint )
+void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
 {
-    HDC hdc;
-    RECT rect;
+    HDC 	hdc;
+    RECT 	rect;
+    BOOL	active;
 
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
-    dprintf_nonclient(stddeb, "NC_DoNCPaint: %04x %d\n", hwnd, active );
     if (!wndPtr || !(wndPtr->dwStyle & WS_VISIBLE)) return; /* Nothing to do */
 
+    active  = wndPtr->flags & WIN_NCACTIVATED;
+
+    dprintf_nonclient(stddeb, "NC_DoNCPaint: %04x %d\n", hwnd, active );
+
     if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
 
     /*
@@ -646,6 +651,13 @@
             DrawIcon(hdc, 0, 0, hIcon);
         }
         ReleaseDC(hwnd, hdc);
+        wndPtr->flags &= ~WIN_INTERNAL_PAINT;
+        if( wndPtr->hrgnUpdate )
+          {
+            DeleteObject( wndPtr->hrgnUpdate );
+            QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
+            wndPtr->hrgnUpdate = 0;
+          }
         return;
     }
 
@@ -724,11 +736,9 @@
  *
  * Handle a WM_NCPAINT message. Called from DefWindowProc().
  */
-LONG NC_HandleNCPaint( HWND hwnd )
+LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
 {
-    WND *wndPtr = WIN_FindWndPtr(hwnd);
-
-    NC_DoNCPaint( hwnd, wndPtr->flags & WIN_NCACTIVATED, FALSE );
+    NC_DoNCPaint( hwnd, clip, FALSE );
     return 0;
 }
 
@@ -745,7 +755,7 @@
     if (wParam != 0) wndPtr->flags |= WIN_NCACTIVATED;
     else wndPtr->flags &= ~WIN_NCACTIVATED;
 
-    NC_DoNCPaint( hwnd, (wParam != 0), FALSE );
+    NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
     return TRUE;
 }
 
@@ -1297,7 +1307,7 @@
     dprintf_nonclient(stddeb, "Handling WM_SYSCOMMAND %x %d,%d\n", 
 		      wParam, pt.x, pt.y );
 
-    if (wndPtr->dwStyle & WS_CHILD)
+    if (wndPtr->dwStyle & WS_CHILD && wParam != SC_KEYMENU )
         ScreenToClient( wndPtr->parent->hwndSelf, &pt );
 
     switch (wParam & 0xfff0)
@@ -1336,7 +1346,7 @@
 	break;
 
     case SC_KEYMENU:
-	MENU_TrackKbdMenuBar( hwnd, wParam );
+	MENU_TrackKbdMenuBar( wndPtr , wParam , pt.x );
 	break;
 	
     case SC_ARRANGE:
diff --git a/windows/painting.c b/windows/painting.c
index bd1554c..e8ce1bb 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -17,6 +17,64 @@
   /* Last CTLCOLOR id */
 #define CTLCOLOR_MAX   CTLCOLOR_STATIC
 
+/***********************************************************************
+ *           WIN_UpdateNCArea
+ *
+ */
+void WIN_UpdateNCArea(WND* wnd, BOOL bUpdate)
+{
+    RECT rect = wnd->rectClient;
+    HRGN hClip = 1;
+
+    dprintf_nonclient(stddeb,"NCUpdate: hwnd %04x, hrgnUpdate %04x\n", 
+                      wnd->hwndSelf, wnd->hrgnUpdate );
+
+    /* desktop windows doesn't have nonclient area */
+    if(wnd == WIN_GetDesktop()) 
+    {
+        wnd->flags &= ~WIN_NEEDS_NCPAINT;
+        return;
+    }
+
+    if( wnd->hrgnUpdate > 1 )
+    {
+        MapWindowPoints(wnd->parent->hwndSelf, 0, (POINT*)&rect, 2);
+
+        hClip = CreateRectRgn( 0, 0, 0, 0 );
+        if (!CombineRgn(hClip, wnd->hrgnUpdate, 0, RGN_COPY) )
+        {
+            DeleteObject(hClip);
+            hClip = 1;
+        }
+
+        if (bUpdate)
+        {
+            HRGN hrgn = CreateRectRgnIndirect(&rect);
+            if (hrgn && (CombineRgn(wnd->hrgnUpdate, wnd->hrgnUpdate,
+                                    hrgn, RGN_AND) == NULLREGION))
+            {
+                DeleteObject(wnd->hrgnUpdate);
+                wnd->hrgnUpdate = 1;
+            }
+            DeleteObject( hrgn );
+        }
+    }
+
+    wnd->flags &= ~WIN_NEEDS_NCPAINT;
+
+    if ((wnd->hwndSelf == GetActiveWindow()) &&
+        !(wnd->flags & WIN_NCACTIVATED))
+    {
+        wnd->flags |= WIN_NCACTIVATED;
+        if( hClip > 1) DeleteObject(hClip);
+        hClip = 1;
+    }
+
+    if (hClip) SendMessage( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
+
+    if (hClip > 1) DeleteObject( hClip );
+}
+
 
 /***********************************************************************
  *           BeginPaint    (USER.39)
@@ -27,26 +85,22 @@
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
 
-    hrgnUpdate = wndPtr->hrgnUpdate;  /* Save update region */
-    if (!hrgnUpdate)    /* Create an empty region */
-	if (!(hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
+    wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
 
-    if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
-	QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
+    if (wndPtr->flags & WIN_NEEDS_NCPAINT) WIN_UpdateNCArea( wndPtr, TRUE );
+
+    if (((hrgnUpdate = wndPtr->hrgnUpdate) != 0) ||
+        (wndPtr->flags & WIN_INTERNAL_PAINT))
+        QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
 
     wndPtr->hrgnUpdate = 0;
-    wndPtr->flags &= ~(WIN_NEEDS_BEGINPAINT | WIN_INTERNAL_PAINT);
+    wndPtr->flags &= ~WIN_INTERNAL_PAINT;
 
     HideCaret( hwnd );
 
-    if (wndPtr->flags & WIN_NEEDS_NCPAINT)
-    {
-        wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
-        SendMessage( hwnd, WM_NCPAINT, 0, 0 );
-    }
-
     lps->hdc = GetDCEx( hwnd, hrgnUpdate, DCX_INTERSECTRGN | DCX_USESTYLE );
-    DeleteObject( hrgnUpdate );
+    if(hrgnUpdate > 1) DeleteObject( hrgnUpdate );
+
     if (!lps->hdc)
     {
         fprintf(stderr, "GetDCEx() failed in BeginPaint(), hwnd=%04x\n", hwnd);
@@ -233,10 +287,8 @@
     else if (flags & RDW_ERASENOW)
     {
         if (wndPtr->flags & WIN_NEEDS_NCPAINT)
-        {
-            wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
-            SendMessage( hwnd, WM_NCPAINT, 0, 0 );
-        }
+	    WIN_UpdateNCArea( wndPtr, FALSE);
+
         if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
         {
             HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
diff --git a/windows/timer.c b/windows/timer.c
index ca1a620..9f8cc4a 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -14,6 +14,7 @@
 typedef struct tagTIMER
 {
     HWND             hwnd;
+    HQUEUE	     hq;
     WORD             msg;  /* WM_TIMER or WM_SYSTIMER */
     WORD             id;
     WORD             timeout;
@@ -74,6 +75,58 @@
     pTimer->next = NULL;
 }
 
+/***********************************************************************
+ *           TIMER_SwitchQueue
+ */
+void TIMER_SwitchQueue(HQUEUE old, HQUEUE new)
+{
+ TIMER*         pT = pNextTimer;
+
+ while(pT)
+  {
+   if( pT->hq == old ) pT->hq = new;
+   pT = pT->next;
+  }
+
+}
+
+/***********************************************************************
+ *           TIMER_NukeTimers
+ *
+ * Trash all timers that are bound to the hwnd or hq
+ */
+void TIMER_NukeTimers(HWND hwnd, HQUEUE hq)
+{
+ HQUEUE		hQToUpdate = ( hwnd ) ? GetTaskQueue( GetWindowTask( hwnd ) )
+				      : hq;
+ TIMER*         pT = pNextTimer;
+ TIMER*         pTnext;
+
+ if( !pT ) return;
+
+ while( (hwnd && pT->hwnd == hwnd) ||
+        (hq && pT->hq == hq) )
+      {
+	 QUEUE_DecTimerCount( hQToUpdate );
+         if( !(pT = pNextTimer = pNextTimer->next) )
+             return;
+      }
+
+ /* pT points to the "good" timer */
+
+ while( (pTnext = pT->next) )
+    {
+      while( (hwnd && pTnext->hwnd == hwnd) ||
+             (hq && pTnext->hq == hq) )
+	   {
+	      QUEUE_DecTimerCount( hQToUpdate );
+              if( !(pT->next = pTnext->next) )
+                  return;
+	   }
+
+      pT = pT->next;
+    }
+}
 
 /***********************************************************************
  *           TIMER_RestartTimers
@@ -165,6 +218,8 @@
       /* Add the timer */
 
     pTimer->hwnd    = hwnd;
+    pTimer->hq	    = (hwnd) ? GetTaskQueue( GetWindowTask( hwnd ) )
+			     : GetTaskQueue( 0 );
     pTimer->msg     = sys ? WM_SYSTIMER : WM_TIMER;
     pTimer->id      = id;
     pTimer->timeout = timeout;
@@ -173,7 +228,7 @@
     dprintf_timer(stddeb, "Timer added: %p, %04x, %04x, %04x, %08lx\n", 
 		  pTimer, pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
     TIMER_InsertTimer( pTimer );
-    QUEUE_IncTimerCount( GetTaskQueue(0) );
+    QUEUE_IncTimerCount( pTimer->hq );
     if (!id)
 	return TRUE;
     else
@@ -188,6 +243,7 @@
 {
     int i;
     TIMER * pTimer;
+    HQUEUE  hq;
     
       /* Find the timer */
     
@@ -201,13 +257,15 @@
 
       /* Delete the timer */
 
+    hq = pTimer->hq;
+
     pTimer->hwnd    = 0;
     pTimer->msg     = 0;
     pTimer->id      = 0;
     pTimer->timeout = 0;
     pTimer->proc    = 0;
     TIMER_RemoveTimer( pTimer );
-    QUEUE_DecTimerCount( GetTaskQueue(0) );
+    QUEUE_DecTimerCount( hq );
     return TRUE;
 }
 
diff --git a/windows/win.c b/windows/win.c
index 8511a73..5c0b2ab 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -217,30 +217,43 @@
  *
  * Find a window that needs repaint.
  */
-HWND WIN_FindWinToRepaint( HWND hwnd )
+HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE hQueue )
 {
-    WND * wndPtr;
+    HWND hwndRet;
+    WND *pWnd = pWndDesktop;
 
-      /* Note: the desktop window never gets WM_PAINT messages */
-    wndPtr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
-    for ( ; wndPtr; wndPtr = wndPtr->next)
+    /* Note: the desktop window never gets WM_PAINT messages */
+    pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
+
+    for ( ; pWnd ; pWnd = pWnd->next )
     {
-	dprintf_win( stddeb, "WIN_FindWinToRepaint: %04x, style %08lx\n",
-		     wndPtr->hwndSelf, wndPtr->dwStyle );
-        if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
+        if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
+        {
+            dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
+                         pWnd->hwndSelf );
             continue;
-        if ((wndPtr->dwStyle & WS_MINIMIZE) && (WIN_CLASS_INFO(wndPtr).hIcon))
-            continue;
-	if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
-	    return wndPtr->hwndSelf;
-	if (wndPtr->child)
-	{
-	    HWND child;
-	    if ((child = WIN_FindWinToRepaint( wndPtr->child->hwndSelf )))
-		return child;
-	}
+        }
+        if ((pWnd->hmemTaskQ == hQueue) &&
+            (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
+        
+        if (pWnd->child )
+            if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
+                return hwndRet;
     }
-    return 0;
+    
+    if (!pWnd) return 0;
+    
+    hwndRet = pWnd->hwndSelf;
+
+    /* look among siblings if we got a transparent window */
+    while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
+                    !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
+    {
+        pWnd = pWnd->next;
+    }
+    if (pWnd) hwndRet = pWnd->hwndSelf;
+    dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
+    return hwndRet;
 }
 
 
@@ -252,19 +265,35 @@
  */
 void WIN_SendParentNotify( HWND hwnd, WORD event, WORD idChild, LONG lValue )
 {
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    
-    while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
+    LPPOINT  lppt = (LPPOINT)(void*)(&lValue);
+    WND     *wndPtr = WIN_FindWndPtr( hwnd );
+    BOOL     bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
+
+    /* if lValue contains cursor coordinates they have to be
+     * mapped to the client area of parent window */
+
+    if (bMouse) MapWindowPoints(0, hwnd, lppt, 2);
+#ifndef WINELIB32
+    else lValue = MAKELONG( LOWORD(lValue), idChild );
+#endif
+
+    while (wndPtr)
     {
-        if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) break;
+        if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
+	   !(wndPtr->dwStyle & WS_CHILD)) break;
+
+        if (bMouse)
+        {
+	    lppt->x += wndPtr->rectClient.left;
+	    lppt->y += wndPtr->rectClient.top;
+        }
+
         wndPtr = wndPtr->parent;
 #ifdef WINELIB32
 	SendMessage( wndPtr->hwndSelf, WM_PARENTNOTIFY, 
-		     MAKEWPARAM(event,idChild),
-		     (LPARAM)lValue );
+		     MAKEWPARAM( event, idChild ), lValue );
 #else
-	SendMessage( wndPtr->hwndSelf, WM_PARENTNOTIFY, event,
-		     MAKELPARAM(LOWORD(lValue), idChild) );
+	SendMessage( wndPtr->hwndSelf, WM_PARENTNOTIFY, event, (LPARAM)lValue);
 #endif
     }
 }
@@ -1268,7 +1297,7 @@
         pWndChild = wndPtr->child;  /* ..side effects after wndenumprc  */
         if (!CallEnumWindowsProc( wndenumprc, wndPtr->hwndSelf, lParam ))
             return 0;
-        if (IsWindow(pWndChild->hwndSelf)) /*to prevent too early termination*/
+        if (pWndChild && IsWindow(pWndChild->hwndSelf))
             if (!WIN_EnumChildWin(pWndChild, wndenumprc, lParam)) return 0;
         wndPtr = pWndNext;
     } 
diff --git a/windows/winpos.c b/windows/winpos.c
index 29f3d70..524f285 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -6,7 +6,7 @@
  */
 
 #include "sysmetrics.h"
-#include "selectors.h"
+#include "module.h"
 #include "user.h"
 #include "win.h"
 #include "event.h"
@@ -238,7 +238,7 @@
 
         /* Restart the search from the next sibling */
         wndPtr = (*ppWnd)->next;
-        *ppWnd = wndPtr->parent;
+        *ppWnd = (*ppWnd)->parent;
     }
 }
 
@@ -259,22 +259,29 @@
  */
 HWND ChildWindowFromPoint( HWND hwndParent, POINT pt )
 {
+    /* pt is in the client coordinates */
+
+    WND* wnd = WIN_FindWndPtr(hwndParent);
     RECT rect;
-    HWND hwnd;
-    
-    GetWindowRect( hwndParent, &rect );
+
+    if( !wnd ) return 0;
+
+    /* get client rect fast */
+    rect.top = rect.left = 0;
+    rect.right = wnd->rectClient.right - wnd->rectClient.left;
+    rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
+
     if (!PtInRect( &rect, pt )) return 0;
-    hwnd = GetTopWindow( hwndParent );
-    while (hwnd)
+
+    wnd = wnd->child;
+    while ( wnd )
     {
-	GetWindowRect( hwnd, &rect );
-	if (PtInRect( &rect, pt )) return hwnd;
-	hwnd = GetWindow( hwnd, GW_HWNDNEXT );
+        if (PtInRect( &wnd->rectWindow, pt )) return wnd->hwndSelf;
+        wnd = wnd->next;
     }
     return hwndParent;
 }
 
-
 /*******************************************************************
  *         MapWindowPoints   (USER.258)
  */
@@ -652,10 +659,15 @@
     WND                   *wndPtr          = WIN_FindWndPtr(hWnd);
     WND                   *wndTemp         = WIN_FindWndPtr(hwndActive);
     CBTACTIVATESTRUCT      cbtStruct       = { fMouse , hwndActive };
-    FARPROC                enumCallback    = (FARPROC)GetWndProcEntry16("ActivateAppProc");
+    FARPROC                enumCallback    = MODULE_GetWndProcEntry16("ActivateAppProc");
     ACTIVATESTRUCT         actStruct;
     WORD                   wIconized=0,wRet= 0;
-    HANDLE                 hActiveQ = 0;
+
+    /* FIXME: When proper support for cooperative multitasking is in place 
+     *        hActiveQ will be global 
+     */
+
+    HANDLE                 hActiveQ = 0;   
 
     /* paranoid checks */
     if( !hWnd || hWnd == GetDesktopWindow() || hWnd == hwndActive )
@@ -805,16 +817,24 @@
 
     if( !wndPtr ) return FALSE;
 
-    /* minors are not allowed */
+    /* child windows get WM_CHILDACTIVATE message */
     if( (wndPtr->dwStyle & WS_CHILD) && !( wndPtr->dwStyle & WS_POPUP))
 	return SendMessage(hWnd, WM_CHILDACTIVATE, 0, 0L);
 
+        /* owned popups imply owner activation */
+    if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
+      {
+        wndPtr = wndPtr->owner;
+        if( !wndPtr ) return FALSE;
+	hWnd = wndPtr->hwndSelf;
+      }
+
     if( hWnd == hwndActive ) return FALSE;
 
     if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
 	return FALSE;
 
-    /* switch desktop queue to current active here */
+    /* switch desktop queue to current active */
     if( wndPtr->parent == WIN_GetDesktop())
         WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
 
@@ -947,6 +967,79 @@
     }
 }
 
+/***********************************************************************
+ *           WINPOS_ReorderOwnedPopups
+ *
+ * fix Z order taking into account owned popups -
+ * basically we need to maintain them above owner window
+ */
+HWND WINPOS_ReorderOwnedPopups(HWND hwndInsertAfter, WND* wndPtr, WORD flags)
+{
+ WND* 	w = WIN_GetDesktop();
+
+ w = w->child;
+
+ /* if we are dealing with owned popup... 
+  */
+ if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner && hwndInsertAfter != HWND_TOP )
+   {
+     BOOL bFound = FALSE;
+     HWND hwndLocalPrev = HWND_TOP;
+     HWND hwndNewAfter = 0;
+
+     while( w )
+       {
+         if( !bFound && hwndInsertAfter == hwndLocalPrev )
+             hwndInsertAfter = HWND_TOP;
+
+         if( w->dwStyle & WS_POPUP && w->owner == wndPtr->owner )
+           {
+             bFound = TRUE;
+
+             if( hwndInsertAfter == HWND_TOP )
+               {
+                 hwndInsertAfter = hwndLocalPrev;
+                 break;
+               }
+             hwndNewAfter = hwndLocalPrev;
+           }
+
+         if( w == wndPtr->owner )
+           {
+             /* basically HWND_BOTTOM */
+             hwndInsertAfter = hwndLocalPrev;
+
+             if( bFound )
+                 hwndInsertAfter = hwndNewAfter;
+             break;
+           }
+
+           if( w != wndPtr )
+               hwndLocalPrev = w->hwndSelf;
+
+           w = w->next;
+        }
+   }
+ else 
+   /* or overlapped top-level window... 
+    */
+   if( !(wndPtr->dwStyle & WS_CHILD) )
+      while( w )
+        {
+          if( w == wndPtr ) break;
+
+          if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
+            {
+              SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
+                                        SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
+              hwndInsertAfter = w->hwndSelf;
+            }
+          w = w->next;
+        }
+
+  return hwndInsertAfter;
+}
+
 
 /***********************************************************************
  *           WINPOS_SetXWindowPos
@@ -1079,6 +1172,12 @@
 
     if (!(winpos.flags & SWP_NOZORDER))
     {
+	/* reorder owned popups if hwnd is top-level window 
+         */
+	if( wndPtr->parent == WIN_GetDesktop() )
+	    hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
+							 wndPtr, flags );
+
         if (wndPtr->window)
         {
             WIN_UnlinkWindow( winpos.hwnd );
@@ -1098,9 +1197,14 @@
 
     if (wndPtr->window)
     {
+        HWND bogusInsertAfter = winpos.hwndInsertAfter;
+
+        winpos.hwndInsertAfter = hwndInsertAfter;
         WINPOS_SetXWindowPos( &winpos );
+
         wndPtr->rectWindow = newWindowRect;
         wndPtr->rectClient = newClientRect;
+        winpos.hwndInsertAfter = bogusInsertAfter;
     }
     else
     {