Release 960528

Tue May 28 19:36:36 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/combo.c]
	Destroy the listbox and edit control when destroying the
	combo. This should prevent crashes on application exit.

	* [misc/system.c] [if1632/system.spec]
	Implemented InquireSystem().

	* [loader/task.c] [windows/message.c] [windows/queue.c]
	First attempt at inter-task SendMessage(). Still has a lot of
	problems.

Tue May 28 14:26:04 1996  Peter Bajusz  <hyp-x@inf.bme.hu>

	* [windows/mdi.c]
	Fixed MDITile with iconic children.

Mon May 27 20:28:18 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [misc/commdlg.c]
	ChooseFont dialog:
	- complete rewrite of FontFamilyEnumProc() and FontStyleEnumProc()
	  not real available font types (e.g. "Bold") can not selected
	- supporting more CF_LIMITSIZE- and CF_...ONLY- flags

	* [objects/font.c]
	In FONT_MatchFont perform check if "lfFaceName" is family from X11
	only if "lfFaceName" is a windows font family then do a call of
	FONT_TranslateName() : this results in better font selections in 
	ChooseFont() or applications like charmap.exe or write.exe.
	Added a ParseFontParms() call if necessary in function 
	FONT_MatchFont(): we need a font name as basis for GetTextFace() 
	even if there isn't one...

	* [resources/TODO]
	Inventory of resource translations in sysres_??.rc

Fri May 24 16:33:28 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [misc/registry.c]
	_w95_loadreg: use offset to determine next RGDB position too.

Thu May 23 19:35:38 1996  Greg Kreider <kreider@natlab.research.philips.com>

	* [controls/combo.c]
	Fixed size of combo, lbox, and button (lb sometimes off by 2 pixels).

	* [misc/main.c]
	Result of option "-fixedmap" is to turn flag on.

Thu May 23 19:15:41 1996  Ronan Waide  <root@waider.ie>

	* [misc/shell.c]
	ShellExecute and FindExecutable now both use common code to
	determine the required executable file.
diff --git a/ANNOUNCE b/ANNOUNCE
index e675cea..b2c5356 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,13 +1,12 @@
-This is release 960521 of Wine the MS Windows emulator.  This is still a
+This is release 960528 of Wine the MS Windows emulator.  This is still a
 developer's only release.  There are many bugs and many unimplemented API
 features.  Most applications still do not work.
 
 Patches should be submitted to "julliard@lrc.epfl.ch".  Please don't
 forget to include a ChangeLog entry.
 
-WHAT'S NEW with Wine-960521: (see ChangeLog for details)
-	- Even more Win32 support.
-	- Winhelp clone should compile OK.
+WHAT'S NEW with Wine-960528: (see ChangeLog for details)
+	- First attempt at inter-task SendMessage(); still broken.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -16,10 +15,10 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-    sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960521.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960521.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960521.tar.gz
-    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960521.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960528.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960528.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960528.tar.gz
+    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960528.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index 2a032fd..488637b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,62 @@
 ----------------------------------------------------------------------
+Tue May 28 19:36:36 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [controls/combo.c]
+	Destroy the listbox and edit control when destroying the
+	combo. This should prevent crashes on application exit.
+
+	* [misc/system.c] [if1632/system.spec]
+	Implemented InquireSystem().
+
+	* [loader/task.c] [windows/message.c] [windows/queue.c]
+	First attempt at inter-task SendMessage(). Still has a lot of
+	problems.
+
+Tue May 28 14:26:04 1996  Peter Bajusz  <hyp-x@inf.bme.hu>
+
+	* [windows/mdi.c]
+	Fixed MDITile with iconic children.
+
+Mon May 27 20:28:18 1996  Albrecht Kleine  <kleine@ak.sax.de>
+
+	* [misc/commdlg.c]
+	ChooseFont dialog:
+	- complete rewrite of FontFamilyEnumProc() and FontStyleEnumProc()
+	  not real available font types (e.g. "Bold") can not selected
+	- supporting more CF_LIMITSIZE- and CF_...ONLY- flags
+
+	* [objects/font.c]
+	In FONT_MatchFont perform check if "lfFaceName" is family from X11
+	only if "lfFaceName" is a windows font family then do a call of
+	FONT_TranslateName() : this results in better font selections in 
+	ChooseFont() or applications like charmap.exe or write.exe.
+	Added a ParseFontParms() call if necessary in function 
+	FONT_MatchFont(): we need a font name as basis for GetTextFace() 
+	even if there isn't one...
+
+	* [resources/TODO]
+	Inventory of resource translations in sysres_??.rc
+
+Fri May 24 16:33:28 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [misc/registry.c]
+	_w95_loadreg: use offset to determine next RGDB position too.
+
+Thu May 23 19:35:38 1996  Greg Kreider <kreider@natlab.research.philips.com>
+
+	* [controls/combo.c]
+	Fixed size of combo, lbox, and button (lb sometimes off by 2 pixels).
+
+	* [misc/main.c]
+	Result of option "-fixedmap" is to turn flag on.
+
+Thu May 23 19:15:41 1996  Waider  <root@waider.ie>
+
+	* [misc/shell.c]
+	ShellExecute and FindExecutable now both use common code to
+	determine the required executable file.
+
+----------------------------------------------------------------------
 Tue May 21 14:06:07 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
 	* [controls/button.c]
diff --git a/controls/combo.c b/controls/combo.c
index 37e6718..409f720 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -145,7 +145,6 @@
   {
    case CBS_SIMPLE:            /* edit control, list always visible  */
      lboxrect=rect;    
-     lboxrect.left +=8;
      dprintf_combo(stddeb,"CBS_SIMPLE\n");
      style= WS_BORDER |  WS_CHILD | WS_VISIBLE | WS_VSCROLL;
      SetRectEmpty16(&lphc->RectButton);
@@ -162,10 +161,9 @@
      lphc->RectButton = rect;
      lphc->RectButton.left = lphc->RectButton.right - 6 - CBitWidth;
      lphc->RectButton.bottom = lphc->RectButton.top + lphl->StdItemHeight;
-     SetWindowPos(hwnd, 0, 0, 0, rect.right - rect.left + 2*SYSMETRICS_CXBORDER,
+     SetWindowPos(hwnd, 0, 0, 0, rect.right -rect.left + 2*SYSMETRICS_CXBORDER,
 		 lphl->StdItemHeight + 2*SYSMETRICS_CYBORDER,
-		 SWP_NOMOVE | SWP_NOZORDER);
-     rect.right=lphc->RectButton.left - 8;
+		 SWP_NOMOVE | SWP_NOZORDER | SWP_NOSENDCHANGING);
      dprintf_combo(stddeb,(cstyle & 3)==CBS_DROPDOWN ? "CBS_DROPDOWN\n": "CBS_DROPDOWNLIST\n");
      break;
      
@@ -175,8 +173,9 @@
 
   if ((cstyle & 3) != CBS_DROPDOWNLIST)
       lphc->hWndEdit = CreateWindow16(MAKE_SEGPTR(editName), (SEGPTR)0,
-				  WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | ES_LEFT | WS_BORDER,
-				  0, 0, rect.right, lphl->StdItemHeight,
+				  WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | ES_LEFT,
+				  0, 0, rect.right-6-CBitWidth,
+				  lphl->StdItemHeight+2*SYSMETRICS_CYBORDER,
 				  hwnd, (HMENU)ID_EDIT, WIN_GetWindowInstance(hwnd), 0L);
 				  
   lboxrect.top+=lphc->LBoxTop;
@@ -210,11 +209,10 @@
  */
 static LRESULT CBDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-  LPHEADLIST lphl = ComboGetListHeader(hwnd);
+  LPHEADCOMBO lphc = ComboGetStorageHeader(hwnd);
 
-  ListBoxResetContent(lphl);
-  DestroyListBoxStruct(lphl);
-  dprintf_combo(stddeb,"Combo WM_DESTROY %p !\n", lphl);
+  if (lphc->hWndEdit) DestroyWindow( lphc->hWndEdit );
+  if (lphc->hWndLBox) DestroyWindow( lphc->hWndLBox );
   return 0;
 }
 
@@ -233,8 +231,16 @@
   RECT16 rect;
   
   hdc = BeginPaint16(hwnd, &ps);
+
+  GetClientRect16(hwnd, &rect);
+  CBCheckSize(hwnd);
+  /* 1 for button border */
+  rect.right = lphc->RectButton.left - 1;
+
   if (hComboBit != 0 && !IsRectEmpty16(&lphc->RectButton))
   {
+    Rectangle(hdc,lphc->RectButton.left-1,lphc->RectButton.top-1,
+	      lphc->RectButton.right+1,lphc->RectButton.bottom+1);
     GRAPH_DrawReliefRect(hdc, &lphc->RectButton, 2, 2, FALSE);
     GRAPH_DrawBitmap(hdc, hComboBit,
 		     lphc->RectButton.left + 2,lphc->RectButton.top + 2,
@@ -258,11 +264,6 @@
 #endif
   if (hBrush == 0) hBrush = GetStockObject(WHITE_BRUSH);
 
-  GetClientRect16(hwnd, &rect);
-
-  CBCheckSize(hwnd);
-  rect.right -= (lphc->RectButton.right - lphc->RectButton.left);
-
   lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
   if (lpls != NULL) {  
     FillRect16(hdc, &rect, hBrush);
@@ -630,17 +631,17 @@
   LONG         cstyle = GetWindowLong(hwnd,GWL_STYLE);
   RECT16       cRect,wRect;
 
-  /* TODO - The size of combo's and their listboxes is still broken */
-
   if (lphc->hWndLBox == 0) return FALSE;
 
   GetClientRect16(hwnd,&cRect);
   GetWindowRect16(hwnd,&wRect);
 
-  dprintf_combo(stddeb,"CBCheckSize: cRect %d,%d-%d,%d  wRect %d,%d-%d,%d\n",
-		cRect.left,cRect.top,cRect.right,cRect.bottom,
+  dprintf_combo(stddeb,
+	 "CBCheckSize: hwnd %04x Rect %d,%d-%d,%d  wRect %d,%d-%d,%d\n", 
+		hwnd,cRect.left,cRect.top,cRect.right,cRect.bottom,
 		wRect.left,wRect.top,wRect.right,wRect.bottom);
   if ((cstyle & 3) == CBS_SIMPLE  ) return TRUE ;
+
   if ((cRect.bottom - cRect.top) > 
       (lphl->StdItemHeight + 2*SYSMETRICS_CYBORDER)) {
     SetWindowPos(hwnd, 0, 0, 0, 
@@ -649,23 +650,29 @@
 		 SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE );
     GetClientRect16(hwnd,&cRect);
     GetWindowRect16(hwnd,&wRect);
+
+    lphc->RectButton.right = cRect.right;
+    lphc->RectButton.left = cRect.right - 2*SYSMETRICS_CXBORDER - 4 
+                            - CBitWidth;
+    lphc->RectButton.top = cRect.top;
+    lphc->RectButton.bottom = cRect.bottom;
   }
 
-  switch (cstyle & 3) {
-    case CBS_SIMPLE:
-      break;
-    case CBS_DROPDOWN:
-    case CBS_DROPDOWNLIST:
+  if (cRect.right < lphc->RectButton.left) {
+    /* if the button is outside the window, move it in */
+    if ((wRect.right - wRect.left - 2*SYSMETRICS_CXBORDER) == (cRect.right - cRect.left)) {
       lphc->RectButton.right = cRect.right;
       lphc->RectButton.left = cRect.right - 2*SYSMETRICS_CXBORDER - 4 
 	                       - CBitWidth;
       lphc->RectButton.top = cRect.top;
       lphc->RectButton.bottom = cRect.bottom;
-      break;
-    default:
-      fprintf(stderr,"CBCheckSize: style %lx not recognized!\n",cstyle);
-      return FALSE;
     }
+    /* otherwise we need to make the client include the button */
+    else
+      SetWindowPos(hwnd, 0, 0, 0, lphc->RectButton.right,
+		   lphl->StdItemHeight+2*SYSMETRICS_CYBORDER, 
+		   SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE );
+  }
 
   CBLCheckSize(hwnd);
   return TRUE;
@@ -1116,7 +1123,7 @@
   LPLISTSTRUCT lpls;
   HWND         hWndLBox;
   RECT16 cRect,wRect,lRect,lwRect;
-  int totheight;
+  int totheight,dw;
   char className[80];
 
   GetClassName32A(hwnd,className,80);
@@ -1143,12 +1150,16 @@
   for (lpls=lphl->lpFirst; lpls != NULL; lpls=lpls->lpNext)
     totheight += lpls->mis.itemHeight;
 
+  dw = cRect.right-cRect.left+2*SYSMETRICS_CXBORDER+SYSMETRICS_CXVSCROLL;
+  dw -= lwRect.right-lwRect.left;
+  dw -= SYSMETRICS_CXVSCROLL;
+
   /* TODO: This isn't really what windows does */
-  if (lRect.bottom-lRect.top < 3*lphl->StdItemHeight) {
-    dprintf_combo(stddeb,"    Changing; totHeight %d  StdItemHght %d\n",
-		totheight,lphl->StdItemHeight);
+  if ((lRect.bottom-lRect.top < 3*lphl->StdItemHeight) || dw) {
+    dprintf_combo(stddeb,"    Changing; totHeight %d  StdItemHght %d  dw %d\n",
+		  totheight,lphl->StdItemHeight,dw);
     SetWindowPos(hWndLBox, 0, lRect.left, lRect.top, 
-		 lwRect.right-lwRect.left, totheight+2*SYSMETRICS_CYBORDER, 
+		 lwRect.right-lwRect.left+dw, totheight+2*SYSMETRICS_CYBORDER, 
 		 SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE );
   }
   return TRUE;
diff --git a/if1632/system.spec b/if1632/system.spec
index 0b727a1..1352396 100644
--- a/if1632/system.spec
+++ b/if1632/system.spec
@@ -1,12 +1,12 @@
 name	system
 type	win16
 
-1 stub InquireSystem
+1 pascal   InquireSystem(word word word) InquireSystem
 2 stub CreateSystemTimer
 3 stub KillSystemTimer
 4 stub EnableSystemTimers
 5 stub DisableSystemTimers
-6 pascal GetSystemmsecCount() GetTickCount
+6 pascal   GetSystemMSecCount() GetTickCount
 7 return Get80x87SaveSize 0 94
 8 stub Save80x87State
 9 stub Restore80x87State
diff --git a/if1632/user.spec b/if1632/user.spec
index e9b2b7c..2444720 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -114,7 +114,7 @@
 112 pascal16 WaitMessage() WaitMessage
 113 pascal16 TranslateMessage(ptr) TranslateMessage
 114 pascal   DispatchMessage(ptr) DispatchMessage
-115 stub ReplyMessage
+115 pascal16 ReplyMessage(long) ReplyMessage
 116 pascal16 PostAppMessage(word word word long) PostAppMessage
 118 pascal16 RegisterWindowMessage(segptr) RegisterWindowMessage16
 117 stub WindowFromDC
@@ -315,7 +315,7 @@
 325 pascal16 PaintRect(word word word word ptr) PaintRect
 326 pascal16 GetControlBrush(word word word) GetControlBrush
 331 pascal16 EnableHardwareInput(word) EnableHardwareInput
-332 return UserYield 0 0
+332 pascal16 UserYield() UserYield
 333 stub IsUserIdle
 334 pascal   GetQueueStatus(word) GetQueueStatus
 335 pascal16 GetInputState() GetInputState
@@ -426,6 +426,11 @@
 482 pascal16 EnableScrollBar(word word word) EnableScrollBar
 483 pascal16 SystemParametersInfo(word word ptr word) SystemParametersInfo
 #484 __GP
+# Stubs for Hebrew version
+489 pascal16 USER_489() stub_USER_489
+490 pascal16 USER_490() stub_USER_490
+492 pascal16 USER_492() stub_USER_492
+496 pascal16 USER_496() stub_USER_496
 499 pascal16 WNetErrorText(word ptr word) WNetErrorText
 501 pascal16 WNetOpenJob(ptr ptr word ptr)  WNetOpenJob
 502 pascal16 WNetCloseJob(word ptr ptr) WNetCloseJob
@@ -514,10 +519,6 @@
 890 stub InstallIMT
 891 stub UninstallIMT
 # Stubs for Hebrew version
-489 pascal16 USER_489() stub_USER_489
-490 pascal16 USER_490() stub_USER_490
-492 pascal16 USER_492() stub_USER_492
-496 pascal16 USER_496() stub_USER_496
 902 pascal16 USER_902() stub_USER_902
 905 pascal16 USER_905() stub_USER_905
 906 pascal16 USER_906() stub_USER_906
diff --git a/include/commdlg.h b/include/commdlg.h
index 84965e4..624822b 100644
--- a/include/commdlg.h
+++ b/include/commdlg.h
@@ -283,19 +283,6 @@
 #define CDERR_NOHOOK           0x000B
 #define CDERR_REGISTERMSGFAIL  0x000C
 
-/************************************************************************
-*                 COMMDLG Resources placed in Wine SYSRES.DLL		    *
-************************************************************************/
-
-#define OPENFILEDLG    			3
-#define SAVEFILEDLG    			4
-#define PRINTDLG	       		5
-#define PRINTSETUPDLG			6
-#define FONTDLG		       		7
-#define COLORDLG	       		8
-#define FINDDLG		       		9
-#define REPLACEDLG	       		10
-
 BOOL  ChooseColor(LPCHOOSECOLOR lpChCol);
 DWORD CommDlgExtendedError(void);
 BOOL  FindText(LPFINDREPLACE lpFind);
diff --git a/include/event.h b/include/event.h
deleted file mode 100644
index 4019f1d..0000000
--- a/include/event.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __WINE_EVENT_H
-#define __WINE_EVENT_H
-
-extern void EVENT_ProcessEvent( XEvent *event );  /* event.c */
-extern void EVENT_RegisterWindow( Window w, HWND hwnd );  /* event.c */
-extern void EVENT_DummyMotionNotify(void);  /* event.c */
-
-#endif /* __WINE_EVENT_H */
diff --git a/include/message.h b/include/message.h
index 870695c..1fc0266 100644
--- a/include/message.h
+++ b/include/message.h
@@ -7,14 +7,27 @@
 #ifndef __WINE_MESSAGE_H
 #define __WINE_MESSAGE_H
 
-#include "windows.h"
+#include "win.h"
+#include "queue.h"
 
 extern DWORD MSG_WineStartTicks;  /* Ticks at Wine startup */
 
-extern void MSG_Synchronize();
-extern BOOL MSG_WaitXEvent( LONG maxWait );
+/* message.c */
 extern BOOL MSG_GetHardwareMessage( LPMSG msg );
 extern BOOL MSG_InternalGetMessage( SEGPTR msg, HWND hwnd, HWND hwndOwner,
 				    short code, WORD flags, BOOL sendIdle );
 
+/* timer.c */
+extern void TIMER_RemoveWindowTimers( HWND hwnd );
+extern void TIMER_RemoveQueueTimers( HQUEUE hqueue );
+extern void TIMER_SwitchQueue( HQUEUE hOldQueue, HQUEUE hNewQueue );
+extern LONG TIMER_GetNextExp(void);
+
+/* event.c */
+extern BOOL EVENT_WaitXEvent( LONG maxWait );
+extern void EVENT_Synchronize(void);
+extern void EVENT_ProcessEvent( XEvent *event );
+extern void EVENT_RegisterWindow( Window w, HWND hwnd );
+extern void EVENT_DummyMotionNotify(void);
+
 #endif  /* __WINE_MESSAGE_H */
diff --git a/include/queue.h b/include/queue.h
index fba9398..6230b89 100644
--- a/include/queue.h
+++ b/include/queue.h
@@ -42,16 +42,17 @@
   DWORD     SendMessageReturn;      /* 28 Return value for SendMessage */
   WORD      wPostQMsg;              /* 2c PostQuitMessage flag */
   WORD      wExitCode;              /* 2e PostQuitMessage exit code */
-  WORD      reserved3[3];           /* 30 Unknown */
+  WORD      flags;                  /* 30 Queue flags */
+  WORD      reserved3[2];           /* 32 Unknown */
   WORD      wWinVersion;            /* 36 Expected Windows version */
   HQUEUE    InSendMessageHandle;    /* 38 Queue of task that sent a message */
   HTASK     hSendingTask;           /* 3a Handle of task that sent a message */
   HTASK     hPrevSendingTask;       /* 3c Handle of previous sender */
   WORD      wPaintCount;            /* 3e Number of WM_PAINT needed */
   WORD      wTimerCount;            /* 40 Number of timers for this task */
-  WORD      tempStatus;             /* 42 State reset by GetQueueStatus */
-  WORD      status;                 /* 44 Queue state */
-  WORD      wakeMask;               /* 46 Task wake-up mask */
+  WORD      changeBits;             /* 42 Changed wake-up bits */
+  WORD      wakeBits;               /* 44 Queue wake-up bits */
+  WORD      wakeMask;               /* 46 Queue wake-up mask */
   WORD      SendMsgReturnPtrs[3];   /* 48 Near ptr to return values (?) */
   HANDLE    hCurHook;               /* 4e Current hook */
   HANDLE    hooks[WH_NB_HOOKS];     /* 50 Task hooks list */
@@ -63,9 +64,19 @@
 #pragma pack(4)
 #endif
 
+/* Extra (undocumented) queue wake bits; not sure about the values */
+#define QS_SMRESULT      0x0100  /* Queue has a SendMessage() result */
+#define QS_SMPARAMSFREE  0x0200  /* SendMessage() parameters are available */
+
+/* Queue flags */
+#define QUEUE_FLAG_REPLIED  0x0001  /* Replied to a SendMessage() */
+
 extern void QUEUE_DumpQueue( HQUEUE hQueue );
 extern void QUEUE_WalkQueues(void);
 extern MESSAGEQUEUE *QUEUE_GetSysQueue(void);
+extern void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit );
+extern void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue );
+extern void QUEUE_WaitBits( WORD bits );
 extern void QUEUE_IncPaintCount( HQUEUE hQueue );
 extern void QUEUE_DecPaintCount( HQUEUE hQueue );
 extern void QUEUE_IncTimerCount( HQUEUE hQueue );
diff --git a/include/windows.h b/include/windows.h
index 5d64c15..03cf15b 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -3188,6 +3188,7 @@
 BOOL       PlayMetaFile(HDC,HANDLE);
 void       PlayMetaFileRecord(HDC,LPHANDLETABLE,LPMETARECORD,WORD);
 BOOL       PostAppMessage(HANDLE,WORD,WORD,LONG);
+void       PostEvent(HTASK);
 BOOL       PostMessage(HWND,WORD,WORD,LONG);
 void       PostQuitMessage(INT);
 WORD       PrestoChangoSelector(WORD,WORD);
@@ -3211,7 +3212,7 @@
 BOOL       RemoveFontResource(LPSTR);
 BOOL       RemoveMenu(HMENU,UINT,UINT);
 HANDLE     RemoveProp(HWND,SEGPTR);
-void       ReplyMessage(LONG);
+void       ReplyMessage(LRESULT);
 HDC        ResetDC(HDC,LPVOID);
 BOOL       ResizePalette(HPALETTE16,UINT);
 BOOL       RestoreDC(HDC,short);
@@ -3338,6 +3339,7 @@
 SEGPTR     WIN16_GlobalLock16(HGLOBAL16);
 SEGPTR     WIN16_LockResource(HANDLE);
 SEGPTR     WIN16_lstrcpyn(SEGPTR,SEGPTR,WORD);
+BOOL       WaitEvent(HTASK);
 void       WaitMessage(void);
 int        WaitSoundState(int);
 HANDLE     WinExec(LPSTR,WORD);
diff --git a/loader/task.c b/loader/task.c
index 44443f6..db91fd0 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
 #include "windows.h"
 #include "task.h"
 #include "callback.h"
@@ -16,6 +17,7 @@
 #include "debugger.h"
 #include "global.h"
 #include "instance.h"
+#include "message.h"
 #include "miscemu.h"
 #include "module.h"
 #include "neexe.h"
@@ -33,7 +35,6 @@
   /* Must not be greater than 64k, or MAKE_SEGPTR won't work */
 #define STACK32_SIZE 0x10000
 
-extern void TIMER_SwitchQueue(HQUEUE, HQUEUE );
 extern void USER_AppExit(HTASK, HINSTANCE, HQUEUE );
 /* ------ Internal variables ------ */
 
@@ -441,13 +442,8 @@
     pTask->hPrevInstance = hPrevInstance;
     pTask->hModule       = hModule;
     pTask->hParent       = hCurrentTask;
-#ifdef WINELIB
-    pTask->curdrive      = 'C' - 'A' + 0x80;
-    strcpy( pTask->curdir, "\\" );
-#else
     pTask->curdrive      = filename[0] - 'A' + 0x80;
     strcpy( pTask->curdir, filename+2 );
-#endif
     pTask->magic         = TDB_MAGIC;
     pTask->nCmdShow      = cmdShow;
 
@@ -631,7 +627,7 @@
     if (hTaskToKill && (hTaskToKill != hCurrentTask))
     {
         /* If another task is already marked for destruction, */
-        /* we call kill it now, as we are in another context. */
+        /* we can kill it now, as we are in another context.  */ 
         TASK_DeleteTask( hTaskToKill );
     }
 
@@ -679,11 +675,11 @@
         hTaskToKill = 0;
     }
 
-      /* If current task is locked, simply return */
+    /* Flush any X events that happened in the meantime */
 
-    if (hLockedTask) return;
+    EVENT_WaitXEvent( 0 );
 
-      /* Find a task to yield to */
+    /* Find a task to yield to */
 
     pOldTask = (TDB *)GlobalLock16( hCurrentTask );
     if (pOldTask && pOldTask->hYieldTo)
@@ -695,23 +691,26 @@
             hTask = 0;
     }
 
-    if (!hTask)
+    while (!hTask)
     {
+        /* Find a task that has an event pending */
+
         hTask = hFirstTask;
         while (hTask)
         {
             pNewTask = (TDB *)GlobalLock16( hTask );
-            if (pNewTask->nEvents && (hTask != hCurrentTask)) break;
+            if (pNewTask->nEvents) break;
             hTask = pNewTask->hNext;
         }
+        if (hLockedTask && (hTask != hLockedTask)) hTask = 0;
+        if (hTask) break;
+
+        /* No task found, wait for some events to come in */
+
+        EVENT_WaitXEvent( TIMER_GetNextExp() );
     }
 
-     /* If there's a task to kill, switch to any other task, */
-     /* even if it doesn't have events pending. */
-
-    if (!hTask && hTaskToKill) hTask = hFirstTask;
-
-    if (!hTask) return;  /* Do nothing */
+    if (hTask == hCurrentTask) return;  /* Nothing to do */
 
     pNewTask = (TDB *)GlobalLock16( hTask );
     dprintf_task( stddeb, "Switching to task %04x (%.8s)\n",
@@ -842,8 +841,9 @@
         return FALSE;
     }
     TASK_SCHEDULE();
-    /* When we get back here, we have an event (or the task is the only one) */
+    /* When we get back here, we have an event */
     if (pTask->nEvents > 0) pTask->nEvents--;
+    else fprintf( stderr, "WaitEvent: reschedule returned without event\n" );
     return TRUE;
 }
 
@@ -921,12 +921,28 @@
  */
 void DirectedYield( HTASK hTask )
 {
-    TDB *pCurTask;
+    TDB *pCurTask = (TDB *)GlobalLock16( hCurrentTask );
+    pCurTask->hYieldTo = hTask;
+    OldYield();
+}
 
-    if ((pCurTask = (TDB *)GlobalLock16( hCurrentTask )) != NULL)
-        pCurTask->hYieldTo = hTask;
+
+/***********************************************************************
+ *           UserYield  (USER.332)
+ */
+void UserYield(void)
+{
+    TDB *pCurTask = (TDB *)GlobalLock16( hCurrentTask );
+    MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( pCurTask->hQueue );
+    /* Handle sent messages */
+    if (queue && (queue->wakeBits & QS_SENDMESSAGE))
+        QUEUE_ReceiveMessage( queue );
 
     OldYield();
+
+    queue = (MESSAGEQUEUE *)GlobalLock16( pCurTask->hQueue );
+    if (queue && (queue->wakeBits & QS_SENDMESSAGE))
+        QUEUE_ReceiveMessage( queue );
 }
 
 
@@ -935,7 +951,10 @@
  */
 void Yield(void)
 {
-    DirectedYield( 0 );
+    TDB *pCurTask = (TDB *)GlobalLock16( hCurrentTask );
+    if (pCurTask) pCurTask->hYieldTo = 0;
+    if (pCurTask && pCurTask->hQueue) UserYield();
+    else OldYield();
 }
 
 
@@ -1177,11 +1196,7 @@
 
       /* Check the owner for module handle */
 
-#ifndef WINELIB
     owner = FarGetOwner( handle );
-#else
-    owner = NULL;
-#endif
     if (!(ptr = GlobalLock16( owner ))) return 0;
     if (((NE_MODULE *)ptr)->magic == NE_SIGNATURE) return owner;
 
diff --git a/memory/global.c b/memory/global.c
index 022ad4e..c8e4d5d 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -820,9 +820,6 @@
 #endif
 }
 
-#ifndef WINELIB
-
-#endif  /* WINELIB */
 
 /***********************************************************************
  *           GlobalAlloc32   (KERNEL32.315)
diff --git a/memory/local.c b/memory/local.c
index 00c564d..7bc0546 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -310,11 +310,16 @@
 
     dprintf_local(stddeb, "LocalInit: %04x %04x-%04x\n", selector, start, end);
     if (!selector) selector = CURRENT_DS;
-    pHeapInfo = LOCAL_GetHeap(selector);
 
-    if (pHeapInfo)  {
-      fprintf( stderr, "LocalInit: Heap %04x initialized twice.\n", selector);
-      if (debugging_local) LOCAL_PrintHeap(selector);
+    if (debugging_heap)
+    {
+        /* If debugging_heap is set, the global heap blocks are cleared */
+        /* before use, so we can test for double initialization. */
+        if (LOCAL_GetHeap(selector))
+        {
+            fprintf( stderr, "LocalInit: Heap %04x initialized twice.\n", selector);
+            if (debugging_local) LOCAL_PrintHeap(selector);
+        }
     }
 
     if (start == 0) {
diff --git a/misc/Makefile.in b/misc/Makefile.in
index b2030ee..6ef8e00 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -26,6 +26,7 @@
 	sound.c \
 	spy.c \
 	stress.c \
+	system.c \
 	toolhelp.c \
 	user.c \
 	ver.c \
diff --git a/misc/clipboard.c b/misc/clipboard.c
index bbac7a2..0cc5848 100644
--- a/misc/clipboard.c
+++ b/misc/clipboard.c
@@ -150,7 +150,7 @@
 		XInternAtom(display,"PRIMARY_TEXT",False),
 		WIN_GetXWindow(hWndClipboardOwner),CurrentTime);
 	/* TODO: need time-out for broken clients */
-	while(wait_for_selection)MSG_WaitXEvent(-1);
+	while(wait_for_selection) EVENT_WaitXEvent(-1);
     }
     while(TRUE) {
 	if (lpFormat == NULL) return 0;
diff --git a/misc/commdlg.c b/misc/commdlg.c
index a0569f7..9dae2c0 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -2144,7 +2144,7 @@
 {
     HANDLE hInst, hDlgTmpl;
     BOOL bRet;
-    dprintf_commdlg(stddeb,"ChoseFont\n");
+    dprintf_commdlg(stddeb,"ChooseFont\n");
     hDlgTmpl = SYSRES_LoadResource( SYSRES_DIALOG_CHOOSE_FONT );
     hInst = WIN_GetWindowInstance( lpChFont->hwndOwner );
     bRet = DialogBoxIndirectParam( hInst, hDlgTmpl, lpChFont->hwndOwner,
@@ -2178,6 +2178,7 @@
  return FALSE;
 }
 
+
 /***********************************************************************
  *                FontFamilyEnumProc                       (COMMDLG.19)
  */
@@ -2186,73 +2187,135 @@
   int i;
   WORD w;
   HWND hwnd=LOWORD(lParam);
+  HWND hDlg=GetParent(hwnd);
+  LPCHOOSEFONT lpcf=(LPCHOOSEFONT)GetWindowLong(hDlg, DWL_USER); 
 
   dprintf_commdlg(stddeb,"FontFamilyEnumProc: font=%s (nFontType=%d)\n",
      			lplf->lfFaceName,nFontType);
+
+  if (lpcf->Flags & CF_FIXEDPITCHONLY)
+   if (!(lplf->lfPitchAndFamily & FIXED_PITCH))
+     return 1;
+  if (lpcf->Flags & CF_ANSIONLY)
+   if (lplf->lfCharSet != ANSI_CHARSET)
+     return 1;
+  if (lpcf->Flags & CF_TTONLY)
+   if (!(nFontType & 0x0004))   /* this means 'TRUETYPE_FONTTYPE' */
+     return 1;   
+
   i=SendMessage16(hwnd,CB_ADDSTRING,0,(LPARAM)MAKE_SEGPTR(lplf->lfFaceName));
   if (i!=CB_ERR)
   {
     w=(lplf->lfCharSet << 8) | lplf->lfPitchAndFamily;
     SendMessage16(hwnd, CB_SETITEMDATA,i,MAKELONG(nFontType,w));
-    return 1 ;
+    return 1 ;        /* store some important font information */
   }
   else
     return 0;
 }
 
+/*************************************************************************
+ *              SetFontStylesToCombo2                           [internal]
+ *
+ * Fill font style information into combobox  (without using font.c directly)
+ */
+static int SetFontStylesToCombo2(HWND hwnd, HDC hdc, LPLOGFONT lplf ,LPTEXTMETRIC lptm)
+{
+   #define FSTYLES 4
+   struct FONTSTYLE
+          { int italic; 
+            int weight;
+            char stname[20]; };
+   static struct FONTSTYLE fontstyles[FSTYLES]={ 
+          { 0,FW_NORMAL,"Regular"},{0,FW_BOLD,"Bold"},
+          { 1,FW_NORMAL,"Italic"}, {1,FW_BOLD,"Bold Italic"}};
+   HFONT hf;                      
+   int i,j;
+
+   for (i=0;i<FSTYLES;i++)
+   {
+     lplf->lfItalic=fontstyles[i].italic;
+     lplf->lfWeight=fontstyles[i].weight;
+     hf=CreateFontIndirect(lplf);
+     hf=SelectObject(hdc,hf);
+     GetTextMetrics(hdc,lptm);
+     hf=SelectObject(hdc,hf);
+     DeleteObject(hf);
+
+     if (lptm->tmWeight==fontstyles[i].weight &&
+         lptm->tmItalic==fontstyles[i].italic)    /* font successful created ? */
+     {
+       j=SendMessage16(hwnd,CB_ADDSTRING,0,(LPARAM)MAKE_SEGPTR(fontstyles[i].stname));
+       if (j==CB_ERR) return 1;
+       j=SendMessage16(hwnd, CB_SETITEMDATA, j, 
+                                 MAKELONG(fontstyles[i].weight,fontstyles[i].italic));
+       if (j==CB_ERR) return 1;                                 
+     }
+   }  
+  return 0;
+ }
+
+/*************************************************************************
+ *              SetFontSizesToCombo3                           [internal]
+ */
+static int SetFontSizesToCombo3(HWND hwnd, LPLOGFONT lplf, LPCHOOSEFONT lpcf)
+{
+  int sizes[]={8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72,0};
+  int h,i,j;
+  char buffer[20];
+  
+  for (i=0;sizes[i] && !lplf->lfHeight;i++)
+  {
+   h=lplf->lfHeight ? lplf->lfHeight : sizes[i];
+
+   if (  (!(lpcf->Flags & CF_LIMITSIZE))  ||
+           ((lpcf->Flags & CF_LIMITSIZE) && (h >= lpcf->nSizeMin) && (h <= lpcf->nSizeMax)))
+   {
+      sprintf(buffer,"%2d",h);
+      j=SendMessage16(hwnd,CB_FINDSTRING,-1,(LPARAM)MAKE_SEGPTR(buffer));
+      if (j==CB_ERR)
+      {
+        j=SendMessage16(hwnd,CB_ADDSTRING,0,(LPARAM)MAKE_SEGPTR(buffer));
+        if (j==CB_ERR) return 1;
+        j=SendMessage16(hwnd, CB_SETITEMDATA, j, h); 
+        if (j==CB_ERR) return 1;
+      }
+   }  
+  }  
+ return 0;
+}
+
+
 /***********************************************************************
  *                 FontStyleEnumProc                     (COMMDLG.18)
  */
 int FontStyleEnumProc(LPLOGFONT lplf ,LPTEXTMETRIC lptm, int nFontType, LPARAM lParam)
 {
-  int j;
-  char buffer[20];
-/*  HWND hcmb2=LOWORD(lParam);*/
+  HWND hcmb2=LOWORD(lParam);
   HWND hcmb3=HIWORD(lParam);
-  LPLOGFONT lf=lplf;
-
+  HWND hDlg=GetParent(hcmb3);
+  LPCHOOSEFONT lpcf=(LPCHOOSEFONT)GetWindowLong(hDlg, DWL_USER); 
+  int i;
+  
   dprintf_commdlg(stddeb,"FontStyleEnumProc: (nFontType=%d)\n",nFontType);
   dprintf_commdlg(stddeb,"  %s h=%d w=%d e=%d o=%d wg=%d i=%d u=%d s=%d ch=%d op=%d cp=%d q=%d pf=%xh\n",
-	lf->lfFaceName,lf->lfHeight,lf->lfWidth,lf->lfEscapement,lf->lfOrientation,
-	lf->lfWeight,lf->lfItalic,lf->lfUnderline,lf->lfStrikeOut,lf->lfCharSet,
-	lf->lfOutPrecision,lf->lfClipPrecision,lf->lfQuality,lf->lfPitchAndFamily);
+	lplf->lfFaceName,lplf->lfHeight,lplf->lfWidth,lplf->lfEscapement,lplf->lfOrientation,
+	lplf->lfWeight,lplf->lfItalic,lplf->lfUnderline,lplf->lfStrikeOut,lplf->lfCharSet,
+	lplf->lfOutPrecision,lplf->lfClipPrecision,lplf->lfQuality,lplf->lfPitchAndFamily);
 
-#if 1         /* VERSION A: use some predefined height values */                       
-  /* FIXME: if (!(nFontType & RASTER_FONTTYPE))......... */
-  {
-    int sizes[]={8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72,0};  
-    int i;
-    if (!SendMessage16(hcmb3,CB_GETCOUNT,0,0)) 
-    {
-      i=0;
-      while (sizes[i])
-      {
-        sprintf(buffer,"%d",sizes[i]);
-        j=SendMessage16(hcmb3,CB_INSERTSTRING,-1,(LPARAM)MAKE_SEGPTR(buffer));
-        SendMessage16(hcmb3, CB_SETITEMDATA, j, MAKELONG(sizes[i],0));
-        i++;
-      }
-    }
-  }
-  return 0; 
-#endif
+  if (SetFontSizesToCombo3(hcmb3, lplf ,lpcf))
+   return 0;
 
-#if 0        /* VERSION B: use only lplf->lfHeight values */
+  if (!SendMessage16(hcmb2,CB_GETCOUNT,0,0))
   {
-    if (lplf->lfHeight)
-    {
-      sprintf(buffer,"%3d",lplf->lfHeight);
-      j=SendMessage16(hcmb3,CB_FINDSTRING,-1,(LPARAM)MAKE_SEGPTR(buffer));
-      if (j==CB_ERR)
-      {
-       j=SendMessage16(hcmb3,CB_ADDSTRING,0,(LPARAM)MAKE_SEGPTR(buffer));
-       SendMessage16(hcmb3, CB_SETITEMDATA, j, MAKELONG(lplf->lfHeight,lplf->lfWidth));
-      } 
-    } 
+       HDC hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
+       i=SetFontStylesToCombo2(hcmb2,hdc,lplf,lptm);
+       if (!(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC))
+         ReleaseDC(hDlg,hdc);
+       if (i)
+        return 0;  
   }
   return 1 ;
-#endif  
-
 }
 
 
@@ -2264,7 +2327,6 @@
   HDC hdc;
   int i,j,res,init=0;
   long l;
-  char buffer[32];
   FARPROC enumCallback = MODULE_GetWndProcEntry16("FontFamilyEnumProc");
   LPLOGFONT lpxx;
   HCURSOR hcursor=SetCursor(LoadCursor(0,IDC_WAIT));
@@ -2308,21 +2370,6 @@
     ShowWindow(GetDlgItem(hDlg,grp1),SW_HIDE);
     ShowWindow(GetDlgItem(hDlg,stc4),SW_HIDE);
   }
-  
-  /* perhaps this stuff should be moved to FontStyleEnumProc() ?? */
-  strcpy(buffer,"Regular"); 	/* LoadString(hInst,.... ,buffer,LF_FACESIZE);*/
-  j=SendDlgItemMessage16(hDlg,cmb2,CB_ADDSTRING,0,(LPARAM)MAKE_SEGPTR(buffer));
-  SendDlgItemMessage16(hDlg,cmb2, CB_SETITEMDATA, j, MAKELONG(FW_NORMAL,0));
-  strcpy(buffer,"Bold");       	/* LoadString(hInst,.... ,buffer,LF_FACESIZE);*/
-  j=SendDlgItemMessage16(hDlg,cmb2,CB_ADDSTRING,0,(LPARAM)MAKE_SEGPTR(buffer));
-  SendDlgItemMessage16(hDlg,cmb2, CB_SETITEMDATA, j, MAKELONG(FW_BOLD,0));
-  strcpy(buffer,"Italic");	/* LoadString(hInst,.... ,buffer,LF_FACESIZE);*/
-  j=SendDlgItemMessage16(hDlg,cmb2,CB_ADDSTRING,0,(LPARAM)MAKE_SEGPTR(buffer));
-  SendDlgItemMessage16(hDlg,cmb2, CB_SETITEMDATA, j, MAKELONG(FW_NORMAL,1));
-  strcpy(buffer,"Bold Italic");	/* LoadString(hInst,.... ,buffer,LF_FACESIZE);*/
-  j=SendDlgItemMessage16(hDlg,cmb2,CB_ADDSTRING,0,(LPARAM)MAKE_SEGPTR(buffer));
-  SendDlgItemMessage16(hDlg,cmb2, CB_SETITEMDATA, j, MAKELONG(FW_BOLD,1));
-  
   hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
   if (hdc)
   {
@@ -2530,9 +2577,7 @@
 		    hdc=(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
 		    if (hdc)
 		    {
-		      /* only if cmb2 is refilled in  FontStyleEnumProc():
-       		                 SendDlgItemMessage(hDlg,cmb2,CB_RESETCONTENT,0,0); 
-		       */
+                      SendDlgItemMessage16(hDlg,cmb2,CB_RESETCONTENT,0,0); 
 		      SendDlgItemMessage16(hDlg,cmb3,CB_RESETCONTENT,0,0);
 		      i=SendDlgItemMessage16(hDlg,cmb1,CB_GETCURSEL,0,0);
 		      if (i!=CB_ERR)
@@ -2588,14 +2633,12 @@
 		    }
 		    i=SendDlgItemMessage16(hDlg,cmb3,CB_GETCURSEL,0,0);
 		    if (i!=CB_ERR)
-		    {
-		      l=SendDlgItemMessage16(hDlg,cmb3,CB_GETITEMDATA,i,0);
-		      lpxx->lfHeight=-LOWORD(l);
-		      lpxx->lfWidth = 0;  /* FYI: lfWidth is in HIWORD(l); */
-		    }
+		      lpxx->lfHeight=-LOWORD(SendDlgItemMessage16(hDlg,cmb3,CB_GETITEMDATA,i,0));
+		    else
+		      lpxx->lfHeight=0;
 		    lpxx->lfStrikeOut=IsDlgButtonChecked(hDlg,chx1);
 		    lpxx->lfUnderline=IsDlgButtonChecked(hDlg,chx2);
-		    lpxx->lfOrientation=lpxx->lfEscapement=0;
+		    lpxx->lfWidth=lpxx->lfOrientation=lpxx->lfEscapement=0;
 		    lpxx->lfOutPrecision=OUT_DEFAULT_PRECIS;
 		    lpxx->lfClipPrecision=CLIP_DEFAULT_PRECIS;
 		    lpxx->lfQuality=DEFAULT_QUALITY;
@@ -2663,6 +2706,8 @@
       case WM_COMMAND:
                         return CFn_WMCommand(hDlg,wParam,lParam);
       case WM_CHOOSEFONT_GETLOGFONT: 
+                         dprintf_commdlg(stddeb,
+                          "FormatCharDlgProc // WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n", lParam);
                         /* FIXME:  current logfont back to caller */
                         break;
     }
diff --git a/misc/main.c b/misc/main.c
index d1e23ad..85455f7 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -121,7 +121,7 @@
     { "-language",      ".language",        XrmoptionSepArg, (caddr_t)"En" },
     { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
     { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
-    { "-fixedmap",      ".fixedmap",        XrmoptionNoArg,  (caddr_t)NULL },
+    { "-fixedmap",      ".fixedmap",        XrmoptionNoArg,  (caddr_t)"on" },
     { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
     { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
     { "-debugmsg",      ".debugmsg",        XrmoptionSepArg, (caddr_t)NULL },
diff --git a/misc/registry.c b/misc/registry.c
index b9c781b..faaf190 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -810,7 +810,8 @@
  *
  * RGDB_section:
  * 	00:		"RGDB"	- magic
- *	04...1F:	?
+ *	04: DWORD	offset to next RGDB section (perhaps WORD)
+ *	08...1F:	?
  *	20.....:	disk keys
  *
  * disk key:
@@ -1004,10 +1005,10 @@
 	HFILE		hfd;
 	int		fd,lastmodified;
 	char		magic[5];
-	unsigned long	nr,pos,i,where,version,rgdbsection,end;
+	unsigned long	nr,pos,i,where,version,rgdbsection,end,off_next_rgdb;
 	struct	_w95key	*keys;
 	int		nrofdkes;
-	unsigned char	*data,*curdata;
+	unsigned char	*data,*curdata,*nextrgdb;
 	OFSTRUCT	ofs;
 	struct	stat	stbuf;
 
@@ -1083,8 +1084,15 @@
 			continue;
 		}
 		if (keys[nr].dkeaddr) {
+			int	x;
+
+			for (x=sizeof(dke);x--;)
+				if (((char*)&dke)[x])
+					break;
+			if (x==-1)
+				break; /* finished reading if we got only 0 */
 			if (nr)
-				dprintf_reg(stddeb,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr,keys[i].dkeaddr,dkeaddr);
+				dprintf_reg(stddeb,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr,keys[nr].dkeaddr,dkeaddr);
 			continue;
 		}
 		nr2da[i].nr	 = nr;
@@ -1116,7 +1124,8 @@
 	_lclose(hfd);
 	curdata = data;
 	memcpy(magic,curdata,4);
-	curdata+=4;
+	memcpy(&off_next_rgdb,curdata+4,4);
+	nextrgdb = curdata+off_next_rgdb;
 	if (strcmp(magic,"RGDB")) {
 		dprintf_reg(stddeb,"third IFF header not RGDB, but %s\n",magic);
 		return;
@@ -1128,6 +1137,17 @@
 		struct	_w95key	*key,xkey;
 
 		bytesread = 0;
+		if (curdata>=nextrgdb) {
+			curdata = nextrgdb;
+			if (!strncmp(curdata,"RGDB",4)) {
+				memcpy(&off_next_rgdb,curdata+4,4);
+				nextrgdb = curdata+off_next_rgdb;
+				curdata+=0x20;
+			} else {
+				dprintf_reg(stddeb,"at end of RGDB section, but no next header. Breaking.\n");
+				break;
+			}
+		}
 #define XREAD(whereto,len) \
 	if ((curdata-data+len)<end) {\
 		memcpy(whereto,curdata,len);\
@@ -1150,7 +1170,7 @@
 				continue;
 			}
 			if (dkh.nrLS == 0xFFFE) {
-				dprintf_reg(stddeb,"0xFFFE at %lx\n",lseek(fd,0,SEEK_CUR)-bytesread);
+				dprintf_reg(stddeb,"0xFFFE at %x\n",curdata-data);
 				break;
 			}
 			dprintf_reg(stddeb,"haven't found nr %ld.\n",nr);
diff --git a/misc/shell.c b/misc/shell.c
index 0aff5cb..4ee423e 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -105,97 +105,14 @@
     return bRet;
 }
 
-
 /*************************************************************************
- *				ShellExecute		[SHELL.20]
+ *				SHELL_FindExecutable
+ * Utility for code sharing between FindExecutable and ShellExecute
  */
-HINSTANCE ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile, LPSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
-{
-    char cmd[400];
-    char *p,*x;
-    long len;
-    char subclass[200];
-
-    /* OK. We are supposed to lookup the program associated with lpFile,
-     * then to execute it using that program. If lpFile is a program,
-     * we have to pass the parameters. If an instance is already running,
-     * we might have to send DDE commands.
-     *
-     * FIXME: Should also look up WIN.INI [Extensions] section?
-     */
-
-    dprintf_exec(stddeb, "ShellExecute(%04x,'%s','%s','%s','%s',%x)\n",
-		hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
-		lpParameters ? lpParameters : "<null>", 
-		lpDirectory ? lpDirectory : "<null>", iShowCmd);
-
-    if (lpFile==NULL) return 0; /* should not happen */
-    if (lpOperation==NULL) /* default is open */
-      lpOperation="open";
-    p=strrchr(lpFile,'.');
-    if (p!=NULL) {
-      x=p; /* the suffixes in the register database are lowercased */
-      while (*x) {*x=tolower(*x);x++;}
-    }
-    if (p==NULL || !strcmp(p,".exe")) {
-      p=".exe";
-      if (lpParameters) {
-        sprintf(cmd,"%s %s",lpFile,lpParameters);
-      } else {
-        strcpy(cmd,lpFile);
-      }
-    } else {
-      len=200;
-      if (RegQueryValue16((HKEY)HKEY_CLASSES_ROOT,p,subclass,&len)==SHELL_ERROR_SUCCESS) {
-	if (len>20)
-	  fprintf(stddeb,"ShellExecute:subclass with len %ld? (%s), please report.\n",len,subclass);
-	subclass[len]='\0';
-	strcat(subclass,"\\shell\\");
-	strcat(subclass,lpOperation);
-	strcat(subclass,"\\command");
-	dprintf_exec(stddeb,"ShellExecute:looking for %s.\n",subclass);
-	len=400;
-	if (RegQueryValue16((HKEY)HKEY_CLASSES_ROOT,subclass,cmd,&len)==SHELL_ERROR_SUCCESS) {
-	  char *t;
-	  dprintf_exec(stddeb,"ShellExecute:...got %s\n",cmd);
-	  cmd[len]='\0';
-	  t=strstr(cmd,"%1");
-	  if (t==NULL) {
-	    strcat(cmd," ");
-	    strcat(cmd,lpFile);
-	  } else {
-	    char *s;
-	    s=xmalloc(len+strlen(lpFile)+10);
-	    strncpy(s,cmd,t-cmd);
-	    s[t-cmd]='\0';
-	    strcat(s,lpFile);
-	    strcat(s,t+2);
-	    strcpy(cmd,s);
-	    free(s);
-	  }
-	  /* does this use %x magic too? */
-	  if (lpParameters) {
-	    strcat(cmd," ");
-	    strcat(cmd,lpParameters);
-	  }
-	} else {
-	  fprintf(stddeb,"ShellExecute: No %s\\shell\\%s\\command found for \"%s\" suffix.\n",subclass,lpOperation,p);
-	  return (HINSTANCE)31; /* unknown type */
-	}
-      } else {
-	fprintf(stddeb,"ShellExecute: No operation found for \"%s\" suffix.\n",p);
-	return (HINSTANCE)31; /* file not found */
-      }
-    }
-    dprintf_exec(stddeb,"ShellExecute:starting %s\n",cmd);
-    return WinExec(cmd,iShowCmd);
-}
-
-
-/*************************************************************************
- *				FindExecutable		[SHELL.21]
- */
-HINSTANCE FindExecutable(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
+static HINSTANCE SHELL_FindExecutable( LPCSTR lpFile, 
+				      LPCSTR lpDirectory,
+				      LPCSTR lpOperation,
+				      LPSTR lpResult)
 {
     char *extension = NULL; /* pointer to file extension */
     char tmpext[5];         /* local copy to mung as we please */
@@ -208,7 +125,7 @@
     char *tok;              /* token pointer */
     int i;                  /* random counter */
 
-    dprintf_exec(stddeb, "FindExecutable: File %s, Dir %s\n", 
+    dprintf_exec(stddeb, "SHELL_FindExecutable: File %s, Dir %s\n", 
 		 (lpFile != NULL?lpFile:"-"), 
 		 (lpDirectory != NULL?lpDirectory:"-"));
 
@@ -216,7 +133,7 @@
 
     /* trap NULL parameters on entry */
     if (( lpFile == NULL ) || ( lpDirectory == NULL ) || 
-	( lpResult == NULL ))
+	( lpResult == NULL ) || ( lpOperation == NULL ))
     {
 	/* FIXME - should throw a warning, perhaps! */
 	return 2; /* File not found. Close enough, I guess. */
@@ -236,7 +153,7 @@
     else
 	tmpext[4]='\0';
     for (i=0;i<strlen(tmpext);i++) tmpext[i]=tolower(tmpext[i]);
-    dprintf_exec(stddeb, "FindExecutable: %s file\n", tmpext);
+    dprintf_exec(stddeb, "SHELL_FindExecutable: %s file\n", tmpext);
     
     /* Three places to check: */
     /* 1. win.ini, [windows], programs (NB no leading '.') */
@@ -259,7 +176,8 @@
 	{
 	    strcpy(lpResult, lpFile); /* Need to perhaps check that */
 				      /* the file has a path attached */
-	    dprintf_exec(stddeb, "FindExecutable: found %s\n", lpResult);
+	    dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
+			 lpResult);
 	    return 33; /* Greater than 32 to indicate success FIXME */
 		       /* what are the correct values here? */
 	}
@@ -271,10 +189,13 @@
                          &filetypelen ) == SHELL_ERROR_SUCCESS )
     {
 	filetype[filetypelen]='\0';
-	dprintf_exec(stddeb, "File type: %s\n", filetype);
+	dprintf_exec(stddeb, "SHELL_FindExecutable: File type: %s\n",
+		     filetype);
 
-	/* Looking for ...buffer\shell\open\command */
-	strcat( filetype, "\\shell\\open\\command" );
+	/* Looking for ...buffer\shell\lpOperation\command */
+	strcat( filetype, "\\shell\\" );
+	strcat( filetype, lpOperation );
+	strcat( filetype, "\\command" );
 	
 	if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, filetype, command,
                              &commandlen ) == SHELL_ERROR_SUCCESS )
@@ -320,6 +241,70 @@
 	}
     }
 
+    dprintf_exec(stddeb, "SHELL_FindExecutable: returning %s\n", lpResult);
+    return retval;
+}
+
+/*************************************************************************
+ *				ShellExecute		[SHELL.20]
+ */
+HINSTANCE ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile,
+		       LPSTR lpParameters, LPCSTR lpDirectory,
+		       INT iShowCmd)
+{
+    HINSTANCE retval=31;
+    char cmd[256];
+
+    dprintf_exec(stddeb, "ShellExecute(%04x,'%s','%s','%s','%s',%x)\n",
+		hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
+		lpParameters ? lpParameters : "<null>", 
+		lpDirectory ? lpDirectory : "<null>", iShowCmd);
+
+    if (lpFile==NULL) return 0; /* should not happen */
+    if (lpOperation==NULL) /* default is open */
+      lpOperation="open";
+
+    retval = SHELL_FindExecutable( lpFile, lpDirectory, lpOperation, cmd );
+
+    if ( retval <= 32 )
+    {
+	return retval;
+    }
+
+    if (lpParameters)
+    {
+	strcat(cmd," ");
+	strcat(cmd,lpParameters);
+    }
+
+    dprintf_exec(stddeb,"ShellExecute:starting %s\n",cmd);
+    return WinExec(cmd,iShowCmd);
+}
+
+/*************************************************************************
+ *				FindExecutable		[SHELL.21]
+ */
+HINSTANCE FindExecutable(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
+{
+    HINSTANCE retval=31;    /* default - 'No association was found' */
+
+    dprintf_exec(stddeb, "FindExecutable: File %s, Dir %s\n", 
+		 (lpFile != NULL?lpFile:"-"), 
+		 (lpDirectory != NULL?lpDirectory:"-"));
+
+    lpResult[0]='\0'; /* Start off with an empty return string */
+
+    /* trap NULL parameters on entry */
+    if (( lpFile == NULL ) || ( lpDirectory == NULL ) || 
+	( lpResult == NULL ))
+    {
+	/* FIXME - should throw a warning, perhaps! */
+	return 2; /* File not found. Close enough, I guess. */
+    }
+
+    retval = SHELL_FindExecutable( lpFile, lpDirectory, "open",
+				  lpResult );
+
     dprintf_exec(stddeb, "FindExecutable: returning %s\n", lpResult);
     return retval;
 }
diff --git a/misc/system.c b/misc/system.c
new file mode 100644
index 0000000..2b17178
--- /dev/null
+++ b/misc/system.c
@@ -0,0 +1,33 @@
+/*
+ * SYSTEM DLL routines
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <stdio.h>
+#include "windows.h"
+
+
+/***********************************************************************
+ *           InquireSystem   (SYSTEM.1)
+ */
+DWORD InquireSystem( WORD code, WORD drive, BOOL enable )
+{
+    WORD drivetype;
+
+    switch(code)
+    {
+    case 0:  /* Get timer resolution */
+        return 54925;
+
+    case 1:  /* Get drive type */
+        drivetype = GetDriveType( drive );
+        return MAKELONG( drivetype, drivetype );
+
+    case 2:  /* Enable one-drive logic */
+        fprintf( stderr, "InquireSystem(2): set single-drive %d not supported\n", enable );
+        return 0;
+    }
+    fprintf( stderr, "InquireSystem: unknown code %d\n", code );
+    return 0;
+}
diff --git a/misc/user.c b/misc/user.c
index 448d536..b20b262 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -21,7 +21,6 @@
 
 #ifndef WINELIB
 
-extern void 	TIMER_NukeTimers(HWND, HQUEUE);
 extern HTASK	TASK_GetNextTask(HTASK);
 extern void	QUEUE_SetDoomedQueue(HQUEUE);
 
@@ -127,7 +126,7 @@
 
     /* Nuke timers */
 
-    TIMER_NukeTimers( 0, hQueue );
+    TIMER_RemoveQueueTimers( hQueue );
 
     HOOK_FreeQueueHooks( hQueue );
 
diff --git a/objects/font.c b/objects/font.c
index ab57ab2..ff7c0c6 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -26,6 +26,7 @@
 #define MAX_FONTS	256
 static LPLOGFONT lpLogFontList[MAX_FONTS] = { NULL };
 
+static int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz);
 
 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
 			     (((cs)->rbearing|(cs)->lbearing| \
@@ -99,6 +100,27 @@
   return TRUE;
 }
 
+/***********************************************************************
+ *           FONT_ChkX11Family
+ *
+ * returns a valid X11 equivalent if a Windows face name 
+ * is like a X11 family  - or NULL if translation is needed
+ */
+static char *FONT_ChkX11Family(char *winFaceName )
+{
+  static char x11fam[32+2];   /* will be returned */
+  int i;
+
+  for(i = 0; lpLogFontList[i] != NULL; i++)
+    if( !strcasecmp(winFaceName, lpLogFontList[i]->lfFaceName) )
+    {
+	strcpy(x11fam,"*-");
+	return strcat(x11fam,winFaceName);
+    }    
+  return NULL;               /* a FONT_TranslateName() call is needed */
+}
+
+
 
 /***********************************************************************
  *           FONT_TranslateName
@@ -171,7 +193,10 @@
   
     charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
     if (*font->lfFaceName) {
-	family = FONT_TranslateName( font->lfFaceName );
+	family = FONT_ChkX11Family(font->lfFaceName);
+	/*--do _not_ translate if lfFaceName is family from X11  A.K.*/
+	if (!family) 
+	  family = FONT_TranslateName( font->lfFaceName );
 	/* FIX ME: I don't if that's correct but it works J.M. */
 	spacing = '*';
 	}
@@ -196,7 +221,6 @@
       family = "*-*";
       break;
     }
-    
     oldheight = height;
     oldspacing = spacing;
     while (TRUE) {
@@ -239,6 +263,10 @@
             }
     }
     dprintf_font(stddeb,"        Found '%s'\n", *names );
+    if (!*font->lfFaceName)
+      ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
+      /* we need a font name for function GetTextFace() even if there isn't one ;-) */  
+    
     fontStruct = XLoadQueryFont( display, *names );
     XFreeFontNames( names );
     return fontStruct;
@@ -878,7 +906,10 @@
     }
     dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
     ParseFontParms(names[i], 2, str, sizeof(str));
+#if 0
+    /* not necessary because new function FONT_ChkX11Family() */
     if (strcmp(str, "fixed") == 0) strcat(str, "sys");
+#endif    
     AnsiUpper(str);
     strcpy(lpNewFont->lfFaceName, str);
     ParseFontParms(names[i], 8, str, sizeof(str));
diff --git a/resources/TODO b/resources/TODO
index dbd7c26..1263235 100644
--- a/resources/TODO
+++ b/resources/TODO
@@ -28,15 +28,11 @@
 Frans van Dorsselaer
 dorssel@rulhm1.LeidenUniv.nl
 ***************************************************************
-1996, April, 7th
+1996, May
 
 Subject: ChooseColor
          ===========
 
-Today I introduced ChooseColor() to commdlg.c.
-Because this old resource was insufficient I wrote a new one
-(including some new static contols).
-
 Please delete the old CHOOSECOLOR in YOUR sysres_??.rc   
 and insert the new CHOOSECOLOR from sysres_En.rc to YOUR 
 language file and translate this as you like it - 
@@ -48,6 +44,7 @@
 * French
 * Italian
 * Korean
+* Finnish
 ...to be continued......
 
 Thank you.
@@ -56,15 +53,16 @@
 kleine@ak.sax.de
 
 **************************************************************
-1996, May, 2nd
+1996, May
 
-Subject ChooseFont
+Subject: ChooseFont
 
 Just like ChooseColor, please copy CHOSEFONT from sysres_EN.rc,
 and translate it to your language. It's okay for:
 
 * English
 * German
+* Finnish
 .....
 
 Thank you.
diff --git a/windows/event.c b/windows/event.c
index be015bf..53beabe 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -9,11 +9,15 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <errno.h>
 #include <X11/keysym.h>
 #include <X11/Xlib.h>
 #include <X11/Xresource.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
+
 #include "windows.h"
 #include "gdi.h"
 #include "heap.h"
@@ -260,6 +264,91 @@
 
 
 /***********************************************************************
+ *           EVENT_WaitXEvent
+ *
+ * Wait for an X event, but at most maxWait milliseconds (-1 for no timeout).
+ * Return TRUE if an event is pending, FALSE on timeout or error
+ * (for instance lost connection with the server).
+ */
+BOOL EVENT_WaitXEvent( LONG maxWait )
+{
+    fd_set read_set;
+    struct timeval timeout;
+    XEvent event;
+    int fd = ConnectionNumber(display);
+
+    if (!XPending(display) && (maxWait != -1))
+    {
+        FD_ZERO( &read_set );
+        FD_SET( fd, &read_set );
+
+	timeout.tv_usec = (maxWait % 1000) * 1000;
+	timeout.tv_sec = maxWait / 1000;
+
+#ifdef CONFIG_IPC
+	sigsetjmp(env_wait_x, 1);
+	stop_wait_op= CONT;
+	    
+	if (DDE_GetRemoteMessage()) {
+	    while(DDE_GetRemoteMessage())
+		;
+	    return TRUE;
+	}
+	stop_wait_op= STOP_WAIT_X;
+	/* The code up to the next "stop_wait_op= CONT" must be reentrant  */
+	if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
+	    !XPending(display)) {
+	    stop_wait_op= CONT;
+	    return FALSE;
+	} else {
+	    stop_wait_op= CONT;
+	}
+#else  /* CONFIG_IPC */
+	if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
+            return FALSE;  /* Timeout or error */
+#endif  /* CONFIG_IPC */
+
+    }
+
+    /* Process the event (and possibly others that occurred in the meantime) */
+    do
+    {
+
+#ifdef CONFIG_IPC
+        if (DDE_GetRemoteMessage())
+        {
+            while(DDE_GetRemoteMessage()) ;
+            return TRUE;
+        }
+#endif  /* CONFIG_IPC */
+
+        XNextEvent( display, &event );
+        EVENT_ProcessEvent( &event );
+    }
+    while (XPending( display ));
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           EVENT_Synchronize
+ *
+ * Synchronize with the X server. Should not be used too often.
+ */
+void EVENT_Synchronize()
+{
+    XEvent event;
+
+    XSync( display, False );
+    while (XPending( display ))
+    {
+	XNextEvent( display, &event );
+	EVENT_ProcessEvent( &event );
+    }    
+}
+
+
+/***********************************************************************
  *           EVENT_XStateToKeyState
  *
  * Translate a X event state (Button1Mask, ShiftMask, etc...) to
diff --git a/windows/mdi.c b/windows/mdi.c
index 22efc97..b515e58 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -773,12 +773,16 @@
                 if( !listTop )
                     break;
                 
-                if( listTop->hChild )
+                /* skip iconized childs from tiling */
+                while (!listTop->hChild)
                 {
-                    SetWindowPos(listTop->hChild, 0, x, y, xsize, ysize, 
-				 SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
-		    y += ysize;
-                }
+    	            listPrev = listTop->prev;
+    	            free(listTop);
+    	            listTop = listPrev;
+    	        }                
+                SetWindowPos(listTop->hChild, 0, x, y, xsize, ysize, 
+                             SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
+                y += ysize;
     	        listPrev = listTop->prev;
     	        free(listTop);
     	        listTop = listPrev;
diff --git a/windows/message.c b/windows/message.c
index 7e1799b..aef426c 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -8,14 +8,12 @@
 #include <string.h>
 #include <sys/time.h>
 #include <sys/types.h>
-#include <errno.h>
 
 #include "message.h"
 #include "win.h"
 #include "gdi.h"
 #include "sysmetrics.h"
 #include "hook.h"
-#include "event.h"
 #include "spy.h"
 #include "winpos.h"
 #include "atom.h"
@@ -204,7 +202,7 @@
     int i, pos = sysMsgQueue->nextMessage;
 
     /* If the queue is empty, attempt to fill it */
-    if (!sysMsgQueue->msgCount && XPending(display)) MSG_WaitXEvent( 0 );
+    if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( 0 );
 
     for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
     {
@@ -278,6 +276,7 @@
  */
 BOOL MSG_GetHardwareMessage( LPMSG msg )
 {
+#if 0
     int pos;
     XEvent event;
     MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
@@ -293,92 +292,83 @@
 	XNextEvent( display, &event );
 	EVENT_ProcessEvent( &event );
     }
+#endif
+    MSG_PeekMessage( msg, 0, WM_KEYFIRST, WM_MOUSELAST, PM_REMOVE, 0 );
     return TRUE;
 }
 
 
 /***********************************************************************
- *           MSG_Synchronize
+ *           MSG_SendMessage
  *
- * Synchronize with the X server. Should not be used too often.
+ * Implementation of an inter-task SendMessage.
  */
-void MSG_Synchronize()
+LRESULT MSG_SendMessage( HQUEUE hDestQueue, HWND hwnd, UINT msg,
+                         WPARAM wParam, LPARAM lParam )
 {
-    XEvent event;
+    MESSAGEQUEUE *queue, *destQ;
 
-    XSync( display, False );
-    while (XPending( display ))
+    if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return 0;
+    if (!(destQ = (MESSAGEQUEUE*)GlobalLock16( hDestQueue ))) return 0;
+
+    if (IsTaskLocked())
     {
-	XNextEvent( display, &event );
-	EVENT_ProcessEvent( &event );
-    }    
+        fprintf( stderr, "SendMessage: task is locked\n" );
+        return 0;
+    }
+
+    if (queue->hWnd)
+    {
+        fprintf( stderr, "Nested SendMessage() not supported\n" );
+        return 0;
+    }
+    queue->hWnd   = hwnd;
+    queue->msg    = msg;
+    queue->wParam = wParam;
+    queue->lParam = lParam;
+    queue->hPrevSendingTask = destQ->hSendingTask;
+    destQ->hSendingTask = GetTaskQueue(0);
+    QUEUE_SetWakeBit( destQ, QS_SENDMESSAGE );
+
+    /* Wait for the result */
+
+    printf( "SendMessage %04x to %04x\n", msg, hDestQueue );
+
+    if (!(queue->wakeBits & QS_SMRESULT))
+    {
+        DirectedYield( hDestQueue );
+        QUEUE_WaitBits( QS_SMRESULT );
+    }
+    printf( "SendMessage %04x to %04x: got %08x\n",
+            msg, hDestQueue, queue->SendMessageReturn );
+    queue->wakeBits &= ~QS_SMRESULT;
+    return queue->SendMessageReturn;
 }
 
 
 /***********************************************************************
- *           MSG_WaitXEvent
- *
- * Wait for an X event, but at most maxWait milliseconds (-1 for no timeout).
- * Return TRUE if an event is pending, FALSE on timeout or error
- * (for instance lost connection with the server).
+ *           ReplyMessage   (USER.115)
  */
-BOOL MSG_WaitXEvent( LONG maxWait )
+void ReplyMessage( LRESULT result )
 {
-    fd_set read_set;
-    struct timeval timeout;
-    XEvent event;
-    int fd = ConnectionNumber(display);
+    MESSAGEQUEUE *senderQ;
+    MESSAGEQUEUE *queue;
 
-    if (!XPending(display) && (maxWait != -1))
+    printf( "ReplyMessage\n " );
+    if (!(queue = (MESSAGEQUEUE*)GlobalLock16( GetTaskQueue(0) ))) return;
+    if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->InSendMessageHandle)))
+        return;
+    for (;;)
     {
-        FD_ZERO( &read_set );
-        FD_SET( fd, &read_set );
-
-	timeout.tv_usec = (maxWait % 1000) * 1000;
-	timeout.tv_sec = maxWait / 1000;
-
-#ifdef CONFIG_IPC
-	sigsetjmp(env_wait_x, 1);
-	stop_wait_op= CONT;
-	    
-	if (DDE_GetRemoteMessage()) {
-	    while(DDE_GetRemoteMessage())
-		;
-	    return TRUE;
-	}
-	stop_wait_op= STOP_WAIT_X;
-	/* The code up to the next "stop_wait_op= CONT" must be reentrant  */
-	if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
-	    !XPending(display)) {
-	    stop_wait_op= CONT;
-	    return FALSE;
-	} else {
-	    stop_wait_op= CONT;
-	}
-#else  /* CONFIG_IPC */
-	if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
-            return FALSE;  /* Timeout or error */
-#endif  /* CONFIG_IPC */
-
+        if (queue->wakeBits & QS_SENDMESSAGE) QUEUE_ReceiveMessage( queue );
+        else if (senderQ->wakeBits & QS_SMRESULT) Yield();
+        else break;
     }
-
-    /* Process the event (and possibly others that occurred in the meantime) */
-    do
-    {
-
-#ifdef CONFIG_IPC
-        if (DDE_GetRemoteMessage())
-        {
-            while(DDE_GetRemoteMessage()) ;
-            return TRUE;
-        }
-#endif  /* CONFIG_IPC */
-
-        XNextEvent( display, &event );
-        EVENT_ProcessEvent( &event );
-    }
-    while (XPending( display ));
-    return TRUE;
+    printf( "ReplyMessage: res = %08x\n", result );
+    senderQ->SendMessageReturn = result;
+    queue->InSendMessageHandle = 0;
+    QUEUE_SetWakeBit( senderQ, QS_SMRESULT );
+    DirectedYield( queue->hSendingTask );
 }
 
 
@@ -397,58 +387,51 @@
     DDE_TestDDE(hwnd);	/* do we have dde handling in the window ?*/
     DDE_GetRemoteMessage();
 #endif  /* CONFIG_IPC */
-    
+
+    mask = QS_POSTMESSAGE | QS_SENDMESSAGE;  /* Always selected */
     if (first || last)
     {
-	mask = QS_POSTMESSAGE;  /* Always selectioned */
 	if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
 	if ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) mask |= QS_MOUSE;
 	if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
 	if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
 	if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
     }
-    else mask = QS_MOUSE | QS_KEY | QS_POSTMESSAGE | QS_TIMER | QS_PAINT;
+    else mask |= QS_MOUSE | QS_KEY | QS_TIMER | QS_PAINT;
+
+    if (IsTaskLocked()) flags |= PM_NOYIELD;
 
     while(1)
     {    
 	hQueue   = GetTaskQueue(0);
         msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
         if (!msgQueue) return FALSE;
+        msgQueue->changeBits = 0;
 
-	  /* First handle a message put by SendMessage() */
-	if (msgQueue->status & QS_SENDMESSAGE)
-	{
-	    if (!hwnd || (msgQueue->hWnd == hwnd))
-	    {
-		if ((!first && !last) || 
-		    ((msgQueue->msg >= first) && (msgQueue->msg <= last)))
-		{
-		    msg->hwnd    = msgQueue->hWnd;
-		    msg->message = msgQueue->msg;
-		    msg->wParam  = msgQueue->wParam;
-		    msg->lParam  = msgQueue->lParam;
-		    if (flags & PM_REMOVE) msgQueue->status &= ~QS_SENDMESSAGE;
-		    break;
-		}
-	    }
-	}
+        /* First handle a message put by SendMessage() */
+
+	if (msgQueue->wakeBits & QS_SENDMESSAGE)
+            QUEUE_ReceiveMessage( msgQueue );
     
-	  /* Now find a normal message */
-	pos = QUEUE_FindMsg( msgQueue, hwnd, first, last );
-	if (pos != -1)
-	{
-	    QMSG *qmsg = &msgQueue->messages[pos];
-	    *msg = qmsg->msg;
-	    msgQueue->GetMessageTimeVal      = msg->time;
-	    msgQueue->GetMessagePosVal       = *(DWORD *)&msg->pt;
-	    msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
+        /* Now find a normal message */
 
-	    if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, pos );
-	    break;
-	}
+        if (((msgQueue->wakeBits & mask) & QS_POSTMESSAGE) &&
+            ((pos = QUEUE_FindMsg( msgQueue, hwnd, first, last )) != -1))
+        {
+            QMSG *qmsg = &msgQueue->messages[pos];
+            *msg = qmsg->msg;
+            msgQueue->GetMessageTimeVal      = msg->time;
+            msgQueue->GetMessagePosVal       = *(DWORD *)&msg->pt;
+            msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
 
-	  /* Now find a hardware event */
-        if (MSG_PeekHardwareMsg( msg, hwnd, first, last, flags & PM_REMOVE ))
+            if (flags & PM_REMOVE) QUEUE_RemoveMsg( msgQueue, pos );
+            break;
+        }
+
+        /* Now find a hardware event */
+
+        if (((msgQueue->wakeBits & mask) & (QS_MOUSE | QS_KEY)) &&
+            MSG_PeekHardwareMsg( msg, hwnd, first, last, flags & PM_REMOVE ))
         {
             /* Got one */
 	    msgQueue->GetMessageTimeVal      = msg->time;
@@ -457,7 +440,8 @@
             break;
         }
 
-	  /* Now handle a WM_QUIT message */
+        /* Now handle a WM_QUIT message */
+
 	if (msgQueue->wPostQMsg)
 	{
 	    msg->hwnd    = hwnd;
@@ -467,8 +451,14 @@
 	    break;
 	}
 
-	  /* Now find a WM_PAINT message */
-	if ((msgQueue->status & QS_PAINT) && (mask & QS_PAINT))
+        /* Check again for SendMessage */
+
+ 	if (msgQueue->wakeBits & QS_SENDMESSAGE)
+            QUEUE_ReceiveMessage( msgQueue );
+
+        /* Now find a WM_PAINT message */
+
+	if ((msgQueue->wakeBits & mask) & QS_PAINT)
 	{
 	    msg->hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
 	    msg->message = WM_PAINT;
@@ -490,23 +480,28 @@
               }
 	}
 
-	  /* Finally handle WM_TIMER messages */
-	if ((msgQueue->status & QS_TIMER) && (mask & QS_TIMER))
+        /* Check for timer messages, but yield first */
+
+        if (!(flags & PM_NOYIELD))
+        {
+            UserYield();
+            if (msgQueue->wakeBits & QS_SENDMESSAGE)
+                QUEUE_ReceiveMessage( msgQueue );
+        }
+	if ((msgQueue->wakeBits & mask) & QS_TIMER)
 	{
 	    if (TIMER_CheckTimer( &nextExp, msg, hwnd, flags & PM_REMOVE ))
 		break;  /* Got a timer msg */
 	}
 	else nextExp = -1;  /* No timeout needed */
 
-        Yield();
-
-	  /* Wait until something happens */
         if (peek)
         {
-            if (!MSG_WaitXEvent( 0 )) return FALSE;  /* No pending event */
+            if (!(flags & PM_NOYIELD)) UserYield();
+            return FALSE;
         }
-        else  /* Wait for an event, then restart the loop */
-            MSG_WaitXEvent( nextExp );
+        msgQueue->wakeMask = mask;
+        QUEUE_WaitBits( mask );
     }
 
       /* We got a message */
@@ -534,7 +529,9 @@
                                   0, 0, 0, flags, TRUE ))
 	    {
 		  /* No message present -> send ENTERIDLE and wait */
-		SendMessage16( hwndOwner, WM_ENTERIDLE, code, (LPARAM)hwnd );
+                if (IsWindow(hwndOwner))
+                    SendMessage16( hwndOwner, WM_ENTERIDLE,
+                                   code, (LPARAM)hwnd );
 		MSG_PeekMessage( (MSG *)PTR_SEG_TO_LIN(msg),
                                  0, 0, 0, flags, FALSE );
 	    }
@@ -679,6 +676,7 @@
         return TRUE;
     }
 
+
     HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1,
                     (LPARAM)MAKE_SEGPTR(&msgstruct) );
     hwnd   = msgstruct.hWnd;
@@ -686,12 +684,21 @@
     wParam = msgstruct.wParam;
     lParam = msgstruct.lParam;
 
-    SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) 
+    if (!(wndPtr = WIN_FindWndPtr( hwnd )))
     {
-        SPY_ExitMessage( SPY_RESULT_INVALIDHWND16, hwnd, msg, 0 );
+        fprintf( stderr, "SendMessage16: invalid hwnd %04x\n", hwnd );
         return 0;
     }
+    if (wndPtr->hmemTaskQ != GetTaskQueue(0))
+    {
+#if 0
+        fprintf( stderr, "SendMessage16: intertask message not supported\n" );
+        return 0;
+#endif
+        return MSG_SendMessage( wndPtr->hmemTaskQ, hwnd, msg, wParam, lParam );
+    }
+
+    SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wParam, lParam );
     ret = CallWindowProc16( wndPtr->lpfnWndProc, hwnd, msg, wParam, lParam );
     SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, ret );
     return ret;
@@ -719,12 +726,18 @@
 
     /* FIXME: call hooks */
 
-    SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) 
+    if (!(wndPtr = WIN_FindWndPtr( hwnd )))
     {
-        SPY_ExitMessage( SPY_RESULT_INVALIDHWND32, hwnd, msg, 0 );
+        fprintf( stderr, "SendMessage32A: invalid hwnd %08x\n", hwnd );
         return 0;
     }
+    if (wndPtr->hmemTaskQ != GetTaskQueue(0))
+    {
+        fprintf( stderr, "SendMessage32A: intertask message not supported\n" );
+        return 0;
+    }
+
+    SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
     ret = CallWindowProc32A( (WNDPROC32)wndPtr->lpfnWndProc,
                              hwnd, msg, wParam, lParam );
     SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
@@ -753,12 +766,18 @@
 
     /* FIXME: call hooks */
 
-    SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) 
+    if (!(wndPtr = WIN_FindWndPtr( hwnd )))
     {
-        SPY_ExitMessage( SPY_RESULT_INVALIDHWND32, hwnd, msg, 0 );
+        fprintf( stderr, "SendMessage32W: invalid hwnd %08x\n", hwnd );
         return 0;
     }
+    if (wndPtr->hmemTaskQ != GetTaskQueue(0))
+    {
+        fprintf( stderr, "SendMessage32W: intertask message not supported\n" );
+        return 0;
+    }
+
+    SPY_EnterMessage( SPY_SENDMESSAGE32, hwnd, msg, wParam, lParam );
     ret = CallWindowProc32W( (WNDPROC32)wndPtr->lpfnWndProc,
                              hwnd, msg, wParam, lParam );
     SPY_ExitMessage( SPY_RESULT_OK32, hwnd, msg, ret );
@@ -781,14 +800,14 @@
     
     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
     if ((queue->wPostQMsg) || 
-        (queue->status & (QS_SENDMESSAGE | QS_PAINT)) ||
+        (queue->wakeBits & (QS_SENDMESSAGE | QS_PAINT)) ||
         (queue->msgCount) || (QUEUE_GetSysQueue()->msgCount) )
         return;
-    if ((queue->status & QS_TIMER) && 
+    if ((queue->wakeBits & QS_TIMER) && 
         TIMER_CheckTimer( &nextExp, &msg, 0, FALSE))
         return;
     /* FIXME: (dde) must check DDE & X-events simultaneously */
-    MSG_WaitXEvent( nextExp );
+    EVENT_WaitXEvent( nextExp );
 }
 
 
@@ -927,14 +946,13 @@
 
 
 /***********************************************************************
- *			InSendMessage	(USER.192
- *
- * According to the book, this should return true iff the current message
- * was send from another application. In that case, the application should
- * invoke ReplyMessage before calling message relevant API.
- * Currently, Wine will always return FALSE, as there is no other app.
+ *           InSendMessage    (USER.192)
  */
 BOOL InSendMessage()
 {
-	return FALSE;
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) )))
+        return 0;
+    return (BOOL)queue->InSendMessageHandle;
 }
diff --git a/windows/queue.c b/windows/queue.c
index 5935bac..e465ebb 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include "module.h"
 #include "queue.h"
+#include "task.h"
 #include "win.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -63,7 +64,7 @@
              pq->nextFreeMessage, (unsigned)pq->lParam, pq->queueSize,
              (unsigned)pq->SendMessageReturn, pq->wWinVersion, pq->InSendMessageHandle,
              pq->wPaintCount, pq->hSendingTask, pq->wTimerCount,
-             pq->hPrevSendingTask, pq->status, pq->wakeMask, pq->hCurHook);
+             pq->hPrevSendingTask, pq->wakeBits, pq->wakeMask, pq->hCurHook);
 }
 
 
@@ -102,6 +103,7 @@
     HQUEUE hQueue;
     MESSAGEQUEUE * msgQueue;
     int queueSize;
+    TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
 
     dprintf_msg(stddeb,"Creating message queue...\n");
 
@@ -111,7 +113,7 @@
     msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
     msgQueue->msgSize = sizeof(QMSG);
     msgQueue->queueSize = size;
-    msgQueue->wWinVersion = 0;  /* FIXME? */
+    msgQueue->wWinVersion = pTask ? pTask->version : 0;
     GlobalUnlock16( hQueue );
     return hQueue;
 }
@@ -173,6 +175,99 @@
 
 
 /***********************************************************************
+ *           QUEUE_SetWakeBit
+ *
+ * See "Windows Internals", p.449
+ */
+void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
+{
+    queue->changeBits |= bit;
+    queue->wakeBits   |= bit;
+    if (queue->wakeMask & bit)
+    {
+        queue->wakeMask = 0;
+        PostEvent( queue->hTask );
+    }
+}
+
+
+/***********************************************************************
+ *           QUEUE_WaitBits
+ *
+ * See "Windows Internals", p.447
+ */
+void QUEUE_WaitBits( WORD bits )
+{
+    MESSAGEQUEUE *queue;
+
+    for (;;)
+    {
+        if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
+        if (queue->changeBits & bits)
+        {
+            /* One of the bits is set; we can return */
+            queue->wakeMask = 0;
+            return;
+        }
+        if (queue->wakeBits & QS_SENDMESSAGE)
+        {
+            /* Process the sent message immediately */
+            QUEUE_ReceiveMessage( queue );
+        }
+        queue->wakeMask = bits | QS_SENDMESSAGE;
+        WaitEvent( 0 );
+    }
+}
+
+
+/***********************************************************************
+ *           QUEUE_ReceiveMessage
+ *
+ * This routine is called when a sent message is waiting for the queue.
+ */
+void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
+{
+    MESSAGEQUEUE *senderQ;
+    HWND hwnd;
+    UINT msg;
+    WPARAM wParam;
+    LPARAM lParam;
+    LRESULT result = 0;
+
+    printf( "ReceiveMessage\n" );
+    if (!(queue->wakeBits & QS_SENDMESSAGE)) return;
+    if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask))) return;
+
+    /* Remove sending queue from the list */
+    queue->InSendMessageHandle = queue->hSendingTask;
+    queue->hSendingTask        = senderQ->hPrevSendingTask;
+    senderQ->hPrevSendingTask  = 0;
+    if (!queue->hSendingTask) queue->wakeBits &= ~QS_SENDMESSAGE;
+
+    /* Get the parameters from the sending task */
+    hwnd   = senderQ->hWnd;
+    msg    = senderQ->msg;
+    wParam = senderQ->wParam;
+    lParam = senderQ->lParam;
+    senderQ->hWnd = 0;
+    QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE );
+
+    printf( "ReceiveMessage: calling wnd proc %04x %04x %04x %08x\n",
+            hwnd, msg, wParam, lParam );
+
+    /* Call the window procedure */
+    /* FIXME: should we use CallWindowProc here? */
+    if (IsWindow( hwnd )) result = SendMessage16( hwnd, msg, wParam, lParam );
+
+    printf( "ReceiveMessage: wnd proc %04x %04x %04x %08x ret = %08x\n",
+            hwnd, msg, wParam, lParam, result );
+
+    /* Return the result to the sender task */
+    ReplyMessage( result );
+}
+
+
+/***********************************************************************
  *           QUEUE_AddMsg
  *
  * Add a message to the queue. Return FALSE if queue is full.
@@ -199,8 +294,7 @@
     else pos = 0;
     msgQueue->nextFreeMessage = pos;
     msgQueue->msgCount++;
-    msgQueue->status |= QS_POSTMESSAGE;
-    msgQueue->tempStatus |= QS_POSTMESSAGE;
+    QUEUE_SetWakeBit( msgQueue, QS_POSTMESSAGE );
     return TRUE;
 }
 
@@ -258,8 +352,47 @@
 	else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
     }
     msgQueue->msgCount--;
-    if (!msgQueue->msgCount) msgQueue->status &= ~QS_POSTMESSAGE;
-    msgQueue->tempStatus = 0;
+    if (!msgQueue->msgCount) msgQueue->wakeBits &= ~QS_POSTMESSAGE;
+}
+
+
+/***********************************************************************
+ *           QUEUE_WakeSomeone
+ *
+ * Wake a queue upon reception of a hardware event.
+ */
+static void QUEUE_WakeSomeone( UINT message )
+{
+    HWND hwnd;
+    WORD wakeBit;
+    HQUEUE hQueue;
+    MESSAGEQUEUE *queue = NULL;
+
+    if ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST)) wakeBit = QS_KEY;
+    else wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
+
+    if (!(hwnd = GetSysModalWindow()))
+    {
+        hwnd = (wakeBit == QS_KEY) ? GetFocus() : GetCapture();
+        if (!hwnd) hwnd = GetActiveWindow();
+    }
+    if (hwnd)
+    {
+        WND *wndPtr = WIN_FindWndPtr( hwnd );
+        if (wndPtr) queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
+    }
+    else
+    {
+        hQueue = hFirstQueue;
+        while (hQueue)
+        {
+            queue = GlobalLock16( hQueue );
+            if (queue->wakeBits & wakeBit) break;
+            hQueue = queue->next;
+        }
+    }
+    if (!queue) printf( "WakeSomeone: no one found\n" );
+    if (queue) QUEUE_SetWakeBit( queue, wakeBit );
 }
 
 
@@ -274,7 +407,7 @@
 {
     MSG *msg;
     int pos;
-  
+
     if (!sysMsgQueue) return;
     pos = sysMsgQueue->nextFreeMessage;
 
@@ -315,6 +448,7 @@
     else pos = 0;
     sysMsgQueue->nextFreeMessage = pos;
     sysMsgQueue->msgCount++;
+    QUEUE_WakeSomeone( message );
 }
 
 		    
@@ -337,8 +471,7 @@
 
     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
     queue->wPaintCount++;
-    queue->status |= QS_PAINT;
-    queue->tempStatus |= QS_PAINT;    
+    QUEUE_SetWakeBit( queue, QS_PAINT );
 }
 
 
@@ -351,7 +484,7 @@
 
     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
     queue->wPaintCount--;
-    if (!queue->wPaintCount) queue->status &= ~QS_PAINT;
+    if (!queue->wPaintCount) queue->wakeBits &= ~QS_PAINT;
 }
 
 
@@ -364,8 +497,7 @@
 
     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
     queue->wTimerCount++;
-    queue->status |= QS_TIMER;
-    queue->tempStatus |= QS_TIMER;
+    QUEUE_SetWakeBit( queue, QS_TIMER );
 }
 
 
@@ -378,7 +510,7 @@
 
     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
     queue->wTimerCount--;
-    if (!queue->wTimerCount) queue->status &= ~QS_TIMER;
+    if (!queue->wTimerCount) queue->wakeBits &= ~QS_TIMER;
 }
 
 
@@ -448,8 +580,8 @@
     DWORD ret;
 
     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
-    ret = MAKELONG( queue->tempStatus, queue->status );
-    queue->tempStatus = 0;
+    ret = MAKELONG( queue->changeBits, queue->wakeBits );
+    queue->changeBits = 0;
     return ret & MAKELONG( flags, flags );
 }
 
@@ -462,7 +594,7 @@
     MESSAGEQUEUE *queue;
 
     if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return FALSE;
-    return queue->status & (QS_KEY | QS_MOUSEBUTTON);
+    return queue->wakeBits & (QS_KEY | QS_MOUSEBUTTON);
 }
 
 
diff --git a/windows/timer.c b/windows/timer.c
index 9f8cc4a..189fc36 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -65,69 +65,78 @@
  */
 static void TIMER_RemoveTimer( TIMER * pTimer )
 {
-    if (pTimer == pNextTimer) pNextTimer = pTimer->next;
-    else
-    {
-	TIMER * ptr = pNextTimer;
-	while (ptr && (ptr->next != pTimer)) ptr = ptr->next;
-	if (ptr) ptr->next = pTimer->next;
-    }
+    TIMER **ppTimer = &pNextTimer;
+
+    while (*ppTimer && (*ppTimer != pTimer)) ppTimer = &(*ppTimer)->next;
+    if (*ppTimer) *ppTimer = pTimer->next;
     pTimer->next = NULL;
 }
 
+
+/***********************************************************************
+ *           TIMER_ClearTimer
+ *
+ * Clear and remove a timer.
+ */
+static void TIMER_ClearTimer( TIMER * pTimer )
+{
+    TIMER_RemoveTimer( pTimer );
+    QUEUE_DecTimerCount( pTimer->hq );
+    pTimer->hwnd    = 0;
+    pTimer->msg     = 0;
+    pTimer->id      = 0;
+    pTimer->timeout = 0;
+    pTimer->proc    = 0;
+}
+
+
 /***********************************************************************
  *           TIMER_SwitchQueue
  */
 void TIMER_SwitchQueue(HQUEUE old, HQUEUE new)
 {
- TIMER*         pT = pNextTimer;
+    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 (pT)
     {
-      while( (hwnd && pTnext->hwnd == hwnd) ||
-             (hq && pTnext->hq == hq) )
-	   {
-	      QUEUE_DecTimerCount( hQToUpdate );
-              if( !(pT->next = pTnext->next) )
-                  return;
-	   }
-
-      pT = pT->next;
+        if (pT->hq == old) pT->hq = new;
+        pT = pT->next;
     }
 }
 
+
+/***********************************************************************
+ *           TIMER_RemoveWindowTimers
+ *
+ * Remove all timers for a given window.
+ */
+void TIMER_RemoveWindowTimers( HWND hwnd )
+{
+    int i;
+    TIMER *pTimer;
+
+    for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
+	if ((pTimer->hwnd == hwnd) && pTimer->timeout)
+            TIMER_ClearTimer( pTimer );
+}
+
+
+/***********************************************************************
+ *           TIMER_RemoveQueueTimers
+ *
+ * Remove all timers for a given queue.
+ */
+void TIMER_RemoveQueueTimers( HQUEUE hqueue )
+{
+    int i;
+    TIMER *pTimer;
+
+    for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
+	if ((pTimer->hq == hqueue) && pTimer->timeout)
+            TIMER_ClearTimer( pTimer );
+}
+
+
 /***********************************************************************
  *           TIMER_RestartTimers
  *
@@ -142,6 +151,17 @@
 
 			       
 /***********************************************************************
+ *           TIMER_GetNextExp
+ *
+ * Return next timer expiration time, or -1 if none.
+ */
+LONG TIMER_GetNextExp(void)
+{
+    return pNextTimer ? EXPIRE_TIME( pNextTimer, GetTickCount() ) : -1;
+}
+
+
+/***********************************************************************
  *           TIMER_CheckTimer
  *
  * Check whether a timer has expired, and create a message if necessary.
@@ -243,9 +263,8 @@
 {
     int i;
     TIMER * pTimer;
-    HQUEUE  hq;
     
-      /* Find the timer */
+    /* Find the timer */
     
     for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
 	if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
@@ -255,17 +274,9 @@
     if (!sys && (pTimer->msg != WM_TIMER)) return FALSE;
     else if (sys && (pTimer->msg != WM_SYSTIMER)) return FALSE;    
 
-      /* Delete the timer */
+    /* 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( hq );
+    TIMER_ClearTimer( pTimer );
     return TRUE;
 }
 
diff --git a/windows/win.c b/windows/win.c
index 51e419c..c89ef23 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -15,10 +15,10 @@
 #include "dce.h"
 #include "sysmetrics.h"
 #include "cursoricon.h"
-#include "event.h"
 #include "heap.h"
 #include "hook.h"
 #include "menu.h"
+#include "message.h"
 #include "nonclient.h"
 #include "string32.h"
 #include "queue.h"
@@ -333,6 +333,7 @@
 	
     if (!wndPtr) return;
     WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
+    TIMER_RemoveWindowTimers( hwnd );
     wndPtr->dwMagic = 0;  /* Mark it as invalid */
     wndPtr->hwndSelf = 0;
     if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
diff --git a/windows/winpos.c b/windows/winpos.c
index 841b63e..74a8942 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -10,7 +10,6 @@
 #include "module.h"
 #include "user.h"
 #include "win.h"
-#include "event.h"
 #include "hook.h"
 #include "message.h"
 #include "queue.h"
@@ -883,23 +882,17 @@
     }
 
     /* set prev active wnd to current active wnd and send notification */
-    if( (hwndPrevActive = hwndActive) )
+    if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
     {
-/* FIXME: need a Win32 translation for WINELIB32 */
-	if( !SendMessage16(hwndPrevActive, WM_NCACTIVATE, 0, MAKELONG(hWnd,wIconized)) )
+        if (!SendMessage16( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
         {
 	    if (GetSysModalWindow() != hWnd) return 0;
 	    /* disregard refusal if hWnd is sysmodal */
         }
 
-#ifdef WINELIB32
-	SendMessage32A( hwndActive, WM_ACTIVATE,
-		     MAKEWPARAM( WA_INACTIVE, wIconized ),
-		     (LPARAM)hWnd );
-#else
-	SendMessage16(hwndPrevActive, WM_ACTIVATE, WA_INACTIVE, 
-		    MAKELONG(hWnd,wIconized));
-#endif
+	SendMessage32A( hwndPrevActive, WM_ACTIVATE,
+                        MAKEWPARAM( WA_INACTIVE, wIconized ),
+                        (LPARAM)hWnd );
 
 	/* check if something happened during message processing */
 	if( hwndPrevActive != hwndActive ) return 0;
@@ -972,9 +965,7 @@
     wndTemp->hwndLastActive = hWnd;
 
     wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
-/* FIXME: Needs a Win32 translation for WINELIB32 */
-    SendMessage16( hWnd, WM_NCACTIVATE, 1,
-		 MAKELONG(hwndPrevActive,wIconized));
+    SendMessage16( hWnd, WM_NCACTIVATE, TRUE, 0 );
 #ifdef WINELIB32
     SendMessage32A( hWnd, WM_ACTIVATE,
 		 MAKEWPARAM( (fMouse)?WA_CLICKACTIVE:WA_ACTIVE, wIconized),
@@ -1704,7 +1695,7 @@
     
       /* Repaint the window */
 
-    if (wndPtr->window) MSG_Synchronize();  /* Wait for all expose events */
+    if (wndPtr->window) EVENT_Synchronize();  /* Wait for all expose events */
 
     EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */