Release 960928

Fri Sep 27 14:18:42 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/button.c]
	Fixed focus rectangle size and clipping.

	* [controls/scroll.c]
	Converted to Win32 and added support for scroll page.
	Completed SetScrollInfo() and implemented other Win32 functions.

	* [files/file.c]
	Removed FILE_Read() (use _lread32 instead).

	* [objects/dce.c] [include/dce.h]
	Allocate DCE on the Win32 heap, and use pointers instead of
	handles.
	Implemented Win32 version of DC functions.

	* [windows/painting.c]
	Attempt to make CS_PARENTDC style work again.

Wed Sep 25 23:40:52 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [windows/dce.c] [windows/winpos.c]
	Override SaveUnder attribute when painting took place
	in a window below. Force X to raise activated window 
	in seamless mode.

	* [misc/clipboard.c] [windows/event.c]
	Translation between DOS and Unix text formats and several
	other fixes for the sudden selection loss.

	* [windows/message.c]
	Apply "first" and "last" when checking for WM_QUIT in 
        MSG_PeekMessage().

	* [windows/win.c]
	Rearranged DestroyWindow() to fit "Windows Internals"
	description.

	* [windows/win.c] [windows/winpos.c] [windows/nonclient.c]
	Misc. fixes to CBT hook calls.

	* [controls/menu.c] [misc/user.c]
	Fixup resident popup menu window so that it doesn't get
	destroyed by USER_AppExit().

	* [loader/module.c] [loader/task.c] [windows/event.c]
	Process "unsafe" X events outside the scheduler to prevent
	deadlocks.

	* [windows/message.c] [windows/queue.c] [windows/winpos.c]
	Lots of fixes for better Win16 multitasking.

Wed Sep 25 20:36:30 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [include/windows.h]
	Added some missing HOOK defines.

	* [misc/shell.c][if1632/shell32.spec][include/shell.h]
	SHGetFileInfoA stub added (win95 mplayer.exe /play bla.avi).

	* [win32/console.c][include/wincon.h]
	GetConsoleScreenBufferInfo, GetLargestConsoleWindowSize added.

	* [misc/registry.c]
	Some null ptr fixes.

	* [loader/pe_image.c]
	Fixed exported function lookup. (msvcrt20.dll)
	Add debugsyms for entrypoint, exported functions and sections.

	* [multimedia/mmsystem.c]
	MCIOpen: support for element opens (mplayer.exe /play bla.avi).

	* [several]
	Added several missing things/stubs/simple thunks from win32
	to win16 code.

Sat Sep 21 17:27:44 1996  O.Flebbe  <flebbe@science-computing.uni-tuebingen.de>

	* [windows/property.c]
	Fixed debugging of 16 Bit RemoveProp().

	* [debugger/memory.c]
	Added DEBUG_checkmap_bad() for linux.

Thu Sep 19 20:48:31 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [windows/event.c] [windows/hook.c]
	Use EnableHardwareInput() for JournalPlayback hook.

	* [controls/listbox.c]
	Changed handling of LB_GETITEMRECT in empty listboxes.

Thu Sep 19 13:34:35 1996  Slaven Rezic  <eserte@cs.tu-berlin.de>

	* [misc/main.c]
	Fixes to X resources handling.	

Wed Sep 18 00:31:15 1996  Huw D. M. Davies <h.davies1@physics.oxford.ac.uk>

	* [objects/metafile.c] [include/gdi.h] [objects/dc.c]
	Individual handle table created for each metafile. Fixed
 	GlobalReAlloc() bug in MF_AddHandleDC() (was MF_AddHandleInternal).

	* [windows/graphics.c] [objects/dc.c]
	Rectangle() changed to work better with wide pens and PS_NULL.
	Use JoinMiter.

	* [windows/winpos.c]
	Make the whole (non X) window invalid on resize if CS_[VH]REDRAW
 	is set.

	* [windows/nonclient.c]
	AdjustWindowRectEx() should perform calculations even if the
 	window is minimized.

	* [windows/mdi.c]
	Better handling of system button painting. Maximized windows can
 	contain scroll bars. Icons now maximize properly.

	* [windows/defwnd.c] [windows/nonclient.c] [controls/menu.c]
	Improved greying of items in system menu. WM_INITMEMUPOPUP no
 	longer caught in DefWndProc, DEFWND_InitSysMenuPopup moved to
 	menu.c.

Mon Sep 16 21:30:00 1996  Uwe Bonnes <bon@elektron.ikp.physik.th-darmstadt.de>

	* [several files]
	Fix missing includes and wrong printing arguments.

	* [controls/listbox.c]
	Don't sort drives in ListBoxDirectory().
	
Sat Sep 14 09:05:47 1996  Petri Tuomola <ptuomola@xs4all.nl>

	* [windows/dialog.c]
	Fixed handling of Shift-TAB in dialogs.

Thu Sep 12 18:31:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>

	* [if1632/gdi32.spec]
	Added SelectClipRgn - call win16 version.

	* [if1632/user32.spec]
	Added GetAsyncKeyState, GetMenuItemID and GetMenuStringA.

	* [include/wincon.h]
	Added COORD and SMALL_RECT typedefs, moved CONSOLE_SCREEN_BUFFER_INFO
	out of #if 0 protected portion of file.

	* [loader/pe_image.c]
	PE_InitTEB() - Tidy up, bug fix to stack pointer value (Borland
	programs now work better)

	* [win32/console.c]
	Added stub functions for GetConsoleScreenBufferInfo and 
	GetLargestConsoleWindowSize

	* [win32/findfile.c]
	FindFirstFile32A() - removed erroneous strcpy

	* [windows/keyboard.c]
	GetAsyncKeyState() - bug fix - now returns value as per Microsoft
	specification. NB - I still have doubts about some other functions
	in this file.
diff --git a/windows/queue.c b/windows/queue.c
index ca6b4d9..aeff35c 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -15,11 +15,15 @@
 #define MAX_QUEUE_SIZE   120  /* Max. size of a message queue */
 
 static HQUEUE16 hFirstQueue = 0;
+static HQUEUE16 hDoomedQueue = 0;
 static HQUEUE16 hmemSysMsgQueue = 0;
+static MESSAGEQUEUE *sysMsgQueue = NULL;
+
 static MESSAGEQUEUE *pMouseQueue = NULL;  /* Queue for last mouse message */
 static MESSAGEQUEUE *pKbdQueue = NULL;    /* Queue for last kbd message */
-static HQUEUE16 hDoomedQueue = 0;
-static MESSAGEQUEUE *sysMsgQueue = NULL;
+
+MESSAGEQUEUE *pCursorQueue = NULL; 
+MESSAGEQUEUE *pActiveQueue = NULL;
 
 /***********************************************************************
  *	     QUEUE_DumpQueue
@@ -119,9 +123,10 @@
     if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, queueSize )))
         return 0;
     msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
-    msgQueue->self = hQueue;
-    msgQueue->msgSize = sizeof(QMSG);
-    msgQueue->queueSize = size;
+    msgQueue->self        = hQueue;
+    msgQueue->msgSize     = sizeof(QMSG);
+    msgQueue->queueSize   = size;
+    msgQueue->wakeBits    = msgQueue->changeBits = QS_SMPARAMSFREE;
     msgQueue->wWinVersion = pTask ? pTask->version : 0;
     GlobalUnlock16( hQueue );
     return hQueue;
@@ -136,6 +141,7 @@
 BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
 {
     MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)GlobalLock16(hQueue);
+    HQUEUE16  senderQ;
     HQUEUE16 *pPrev;
 
     dprintf_msg(stddeb,"Deleting message queue %04x\n", hQueue);
@@ -145,6 +151,19 @@
 	dprintf_msg(stddeb,"DeleteMsgQueue: invalid argument.\n");
 	return 0;
     }
+    if( pCursorQueue == msgQueue ) pCursorQueue = NULL;
+    if( pActiveQueue == msgQueue ) pActiveQueue = NULL;
+
+    /* flush sent messages */
+    senderQ = msgQueue->hSendingTask;
+    while( senderQ )
+    {
+      MESSAGEQUEUE* sq = (MESSAGEQUEUE*)GlobalLock16(senderQ);
+      if( !sq ) break;
+      sq->SendMessageReturn = 0L;
+      QUEUE_SetWakeBit( sq, QS_SMRESULT );
+      senderQ = sq->hPrevSendingTask;
+    }
 
     pPrev = &hFirstQueue;
     while (*pPrev && (*pPrev != hQueue))
@@ -191,6 +210,9 @@
  */
 void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
 {
+    dprintf_msg(stddeb,"SetWakeBit: queue = %04x (wm=%04x), bit = %04x\n", 
+	                queue->self, queue->wakeMask, bit );
+
     if (bit & QS_MOUSE) pMouseQueue = queue;
     if (bit & QS_KEY) pKbdQueue = queue;
     queue->changeBits |= bit;
@@ -222,9 +244,12 @@
 {
     MESSAGEQUEUE *queue;
 
+    dprintf_msg(stddeb,"WaitBits: q %04x waiting for %04x\n", GetTaskQueue(0), bits);
+
     for (;;)
     {
         if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
+
         if (queue->changeBits & bits)
         {
             /* One of the bits is set; we can return */
@@ -234,9 +259,17 @@
         if (queue->wakeBits & QS_SENDMESSAGE)
         {
             /* Process the sent message immediately */
+
+	    queue->wakeMask = 0;
             QUEUE_ReceiveMessage( queue );
+	    continue;				/* nested sm crux */
         }
+
         queue->wakeMask = bits | QS_SENDMESSAGE;
+	if(queue->changeBits & bits) continue;
+	
+	dprintf_msg(stddeb,"wb: (%04x) wakeMask is %04x, waiting\n", queue->self, queue->wakeMask);
+
         WaitEvent( 0 );
     }
 }
@@ -249,57 +282,55 @@
  */
 void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
 {
-    MESSAGEQUEUE *senderQ;
-    HWND hwnd;
-    UINT msg;
-    WPARAM wParam;
-    LPARAM lParam;
-    LRESULT result = 0;
-    HQUEUE16 oldSender;
+    MESSAGEQUEUE *senderQ = NULL;
+    HQUEUE16      prevSender = 0;
+    QSMCTRL*      prevCtrlPtr = NULL;
+    LRESULT       result = 0;
 
-    printf( "ReceiveMessage\n" );
-    if (!(queue->wakeBits & QS_SENDMESSAGE)) return;
-    if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask))) return;
+    dprintf_msg(stddeb, "ReceiveMessage, queue %04x\n", queue->self );
+    if (!(queue->wakeBits & QS_SENDMESSAGE) ||
+        !(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask))) 
+	{ dprintf_msg(stddeb,"\trcm: nothing to do\n"); return; }
 
-    /* Remove sending queue from the list */
-    oldSender                  = queue->InSendMessageHandle;
     queue->InSendMessageHandle = queue->hSendingTask;
-    queue->hSendingTask        = senderQ->hPrevSendingTask;
-    senderQ->hPrevSendingTask  = 0;
-    if (!queue->hSendingTask)
+    if( !(queue->hSendingTask = senderQ->hPrevSendingTask) )
     {
-        queue->wakeBits &= ~QS_SENDMESSAGE;
-        queue->changeBits &= ~QS_SENDMESSAGE;
+      queue->wakeBits &= ~QS_SENDMESSAGE;	/* no more sent messages */
+      queue->changeBits &= ~QS_SENDMESSAGE;
     }
 
-    /* Get the parameters from the sending task */
-    hwnd   = senderQ->hWnd;
-    msg    = senderQ->msg;
-    wParam = senderQ->wParam;
-    lParam = senderQ->lParam;
-    senderQ->hWnd = 0;
+    /* Remove sending queue from the list */
+    prevSender                 = queue->InSendMessageHandle;
+    prevCtrlPtr		       = queue->smResultCurrent;
+    queue->smResultCurrent     = senderQ->smResultInit;
+
+    dprintf_msg(stddeb, "\trcm: smResultCurrent = %08x, prevCtrl = %08x\n", 
+				(unsigned)queue->smResultCurrent, (unsigned)prevCtrlPtr );
     QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE );
 
-    printf( "ReceiveMessage: calling wnd proc %04x %04x %04x %08x\n",
-            hwnd, msg, wParam, lParam );
+    dprintf_msg(stddeb, "\trcm: calling wndproc - %04x %04x %04x %08x\n",
+            senderQ->hWnd, senderQ->msg, senderQ->wParam, (unsigned)senderQ->lParam );
 
-    /* Call the window procedure */
-    /* FIXME: should we use CallWindowProc here? */
-    if (IsWindow( hwnd ))
+    if (IsWindow( senderQ->hWnd ))
     {
         DWORD extraInfo = queue->GetMessageExtraInfoVal;
         queue->GetMessageExtraInfoVal = senderQ->GetMessageExtraInfoVal;
-        result = SendMessage16( hwnd, msg, wParam, lParam );
-        queue->GetMessageExtraInfoVal = extraInfo;  /* Restore extra info */
-    }
 
-    printf( "ReceiveMessage: wnd proc %04x %04x %04x %08x ret = %08x\n",
-            hwnd, msg, wParam, lParam, result );
+        result = CallWindowProc16( (WNDPROC16)GetWindowLong16(senderQ->hWnd, GWL_WNDPROC),
+				   senderQ->hWnd, senderQ->msg, senderQ->wParam, senderQ->lParam );
+
+        queue->GetMessageExtraInfoVal = extraInfo;  /* Restore extra info */
+	dprintf_msg(stddeb,"\trcm: result =  %08x\n", (unsigned)result );
+    }
+    else dprintf_msg(stddeb,"\trcm: bad hWnd\n");
 
     /* Return the result to the sender task */
     ReplyMessage( result );
 
-    queue->InSendMessageHandle = oldSender;
+    queue->InSendMessageHandle = prevSender;
+    queue->smResultCurrent     = prevCtrlPtr;
+
+    dprintf_msg(stddeb,"ReceiveMessage: done!\n");
 }
 
 
@@ -399,39 +430,44 @@
  */
 static void QUEUE_WakeSomeone( UINT message )
 {
-    HWND hwnd;
-    WORD wakeBit;
-    HQUEUE16 hQueue;
-    MESSAGEQUEUE *queue = NULL;
+    WND*	  wndPtr = NULL;
+    HWND          hwnd;
+    WORD          wakeBit;
+    MESSAGEQUEUE *queue = pCursorQueue;
 
-    if ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST)) wakeBit = QS_KEY;
-    else wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
+    if( (message >= WM_KEYFIRST) && (message <= WM_KEYLAST) )
+    {
+       wakeBit = QS_KEY;
+       if( pActiveQueue ) queue = pActiveQueue;
+    }
+    else 
+    {
+       wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
+       if( (hwnd = GetCapture32()) )
+	 if( (wndPtr = WIN_FindWndPtr( hwnd )) ) 
+	   queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
+    }
 
-    if (!(hwnd = GetSysModalWindow16()))
+    if( (hwnd = GetSysModalWindow16()) )
+      if( (wndPtr = WIN_FindWndPtr( hwnd )) )
+        queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
+
+    if( !queue ) 
     {
-        if (wakeBit == QS_KEY)
-        {
-            if (!(hwnd = GetFocus32())) hwnd = GetActiveWindow();
-        }
-        else hwnd = GetCapture();
+      queue = GlobalLock16( hFirstQueue );
+      while( queue )
+      {
+        if (queue->wakeMask & wakeBit) break;
+        queue = GlobalLock16( queue->next );
+      }
+      if( !queue )
+      { 
+        dprintf_msg(stddeb,"WakeSomeone: couldn't find queue\n"); 
+        return; 
+      }
     }
-    if (hwnd)
-    {
-        WND *wndPtr = WIN_FindWndPtr( hwnd );
-        if (wndPtr) queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
-    }
-    else if (!(queue = pMouseQueue))
-    {
-        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 );
+
+    QUEUE_SetWakeBit( queue, wakeBit );
 }
 
 
@@ -595,15 +631,23 @@
 	dprintf_msg(stddeb,"SetMessageQueue: failed!\n");
 	return FALSE;
     }
+    queuePtr = (MESSAGEQUEUE *)GlobalLock16( hNewQueue );
 
-    /* Free the old message queue */
-    if ((hQueue = GetTaskQueue(0)) != 0) QUEUE_DeleteMsgQueue( hQueue );
+    /* Copy data and free the old message queue */
+    if ((hQueue = GetTaskQueue(0)) != 0) 
+    {
+       MESSAGEQUEUE *oldQ = (MESSAGEQUEUE *)GlobalLock16( hQueue );
+       memcpy( &queuePtr->reserved2, &oldQ->reserved2, 
+			(int)oldQ->messages - (int)(&oldQ->reserved2) );
+       QUEUE_DeleteMsgQueue( hQueue );
+    }
 
     /* Link new queue into list */
-    queuePtr = (MESSAGEQUEUE *)GlobalLock16( hNewQueue );
     queuePtr->hTask = GetCurrentTask();
     queuePtr->next  = hFirstQueue;
     hFirstQueue = hNewQueue;
+    
+    if( !queuePtr->next ) pCursorQueue = queuePtr;
 
     SetTaskQueue( 0, hNewQueue );
     return TRUE;