Release 960616 wine-960616
authorAlexandre Julliard <julliard@winehq.org>
Sun, 16 Jun 1996 16:16:05 +0000 (16:16 +0000)
committerAlexandre Julliard <julliard@winehq.org>
Sun, 16 Jun 1996 16:16:05 +0000 (16:16 +0000)
Sun Jun 16 16:51:31 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

* [memory/heap.c]
Fixed bug in HeapRealloc (thanks to Bruce Milner).

* [misc/wsprintf.c]
Fixed argument size for %c format in wsprintf16().

* [objects/dc.c]
Don't free hFirstBitmap for saved DCs.

* [windows/event.c]
Added timer handling in EVENT_WaitXEvent().

* [windows/message.c]
In MSG_TranslateMouseMsg and MSG_TranslateKbdMsg, check if the
event is for the current task; if not, wake the other task.

* [windows/queue.c] [include/queue.h]
Added 'self' handle in queue structure.

* [windows/timer.c]
Added TIMER_ExpireTimers() function to mark expired timers and
wake up the corresponding tasks.

Thu Jun 13 01:46:33 EDT 1996  William Magro <wmagro@tc.cornell.edu>

* [windows/mapping.c]
First point in list was mapped multiple times in DPtoLP and
  LPtoDP.  Other points were not mapped.

Wed Jun 12 18:08:45 1996  Alex Korobka <alex@phm30.pharm.sunysb.edu>

* [misc/shell.c]
Some fixes for ExtractIcon function family.

* [documentation/user_module]
Chapter about windowing and messaging subsystems.

22 files changed:
ANNOUNCE
ChangeLog
documentation/user_module [new file with mode: 0644]
include/message.h
include/queue.h
include/windows.h
library/miscstubs.c
loader/task.c
memory/heap.c
misc/clipboard.c
misc/shell.c
misc/wsprintf.c
objects/dc.c
windows/class.c
windows/dce.c
windows/event.c
windows/mapping.c
windows/message.c
windows/nonclient.c
windows/queue.c
windows/timer.c
windows/win.c

index b4f14d30ffcd7b17ac39a16dd12829deacb2d89e..9196873214778f24ad39fc4b58b71fa7579a70dc 100644 (file)
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,12 +1,12 @@
-This is release 960611 of Wine, the MS Windows emulator.  This is still a
+This is release 960616 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 correctly.
 
 Patches should be submitted to "julliard@lrc.epfl.ch".  Please don't
 forget to include a ChangeLog entry.
 
-WHAT'S NEW with Wine-960611: (see ChangeLog for details)
-       - (surprise) More Win32 code.
+WHAT'S NEW with Wine-960616: (see ChangeLog for details)
+       - Inter-task messaging begins to work.
        - Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -15,10 +15,10 @@ Because of lags created by using mirror, this message may reach you before
 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-960611.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960611.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960611.tar.gz
-    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960611.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960616.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960616.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960616.tar.gz
+    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960616.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
index 0d6d6c1adfa2034bec27bb748922e5f1ac58b7e6..855adb2007ed78395d08468253be599e6c15ca34 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+----------------------------------------------------------------------
+Sun Jun 16 16:51:31 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+       * [memory/heap.c]
+       Fixed bug in HeapRealloc (thanks to Bruce Milner).
+
+       * [misc/wsprintf.c]
+       Fixed argument size for %c format in wsprintf16().
+
+       * [objects/dc.c]
+       Don't free hFirstBitmap for saved DCs.
+
+       * [windows/event.c]
+       Added timer handling in EVENT_WaitXEvent().
+
+       * [windows/message.c]
+       In MSG_TranslateMouseMsg and MSG_TranslateKbdMsg, check if the
+       event is for the current task; if not, wake the other task.
+
+       * [windows/queue.c] [include/queue.h]
+       Added 'self' handle in queue structure.
+
+       * [windows/timer.c]
+       Added TIMER_ExpireTimers() function to mark expired timers and
+       wake up the corresponding tasks.
+
+Thu Jun 13 01:46:33 EDT 1996  William Magro <wmagro@tc.cornell.edu>
+
+       * [windows/mapping.c]
+       First point in list was mapped multiple times in DPtoLP and
+       LPtoDP.  Other points were not mapped.
+
+Wed Jun 12 18:08:45 1996  Alex Korobka <alex@phm30.pharm.sunysb.edu>
+
+       * [misc/shell.c]
+       Some fixes for ExtractIcon function family.
+
+       * [documentation/user_module]
+       Chapter about windowing and messaging subsystems.
+
 ----------------------------------------------------------------------
 Tue Jun 11 15:20:43 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
diff --git a/documentation/user_module b/documentation/user_module
new file mode 100644 (file)
index 0000000..6b6bfd7
--- /dev/null
@@ -0,0 +1,217 @@
+USER MODULE
+===========
+
+USER implements windowing and messaging subsystems. It also 
+contains code for common controls and for other miscellaneous 
+stuff (rectangles, clipboard, WNet, etc). Wine USER code is 
+located in windows/, controls/, and misc/ directories.
+
+1. Windowing subsystem
+
+   Windows are arranged into parent/child hierarchy with one
+   common ancestor for all windows (desktop window). Each window
+   structure contains a pointer to the immediate ancestor (parent 
+   window if WS_CHILD style bit is set), a pointer to the sibling 
+   (returned by GetWindow(..., GW_NEXT)), a pointer to the owner 
+   window (set only for popup window if it was created with valid 
+   hwndParent parameter), and a pointer to the first child
+   window (GetWindow(.., GW_CHILD)). All popup and non-child windows
+   are therefore placed in the first level of this hierarchy and their
+   ancestor link (wnd->parent) points to the desktop window.
+
+   Desktop window                      - root window
+    |     \      '-.
+    |      \        '-.
+   popup -> wnd1  ->  wnd2             - top level windows    
+    |       \   '-.      '-.
+    |        \     '-.      '-.
+   child1  child2 -> child3  child4     - child windows
+  
+   Horizontal arrows denote sibling relationship, vertical lines
+   - ancestor/child. To summarize, all windows with the same immediate 
+   ancestor are sibling windows, all windows which do not have desktop 
+   as their immediate ancestor are child windows. Popup windows behave
+   as topmost top-level windows unless they are owned. In this case the
+   only requirement is that they must precede their owners in the top-level 
+   sibling list (they are not topmost). Child windows are confined to the
+   client area of their parent windows (client area is where window gets
+   to do its own drawing, non-client area consists of caption, menu, borders,
+   intrinsic scrollbars, and minimize/maximize/close buttons). 
+  
+   Another fairly important concept is "z-order". It is derived from
+   the ancestor/child hierarchy and is used to determine "above/below"
+   relationship. For instance, in the example above, z-order is
+   child1->popup->child2->child3->wnd1->child4->wnd2->desktop. Current 
+   active window ("foreground window" in Win32) is moved to the front
+   of z-order unless its top-level ancestor owns popup windows.
+
+   All these issues are dealt with (or supposed to be) in 
+   windows/winpos.c
+
+   Wine specifics: in default and managed mode each top-level window
+   gets its own X counterpart with desktop window being basically a 
+   fake stub. In desktop mode, however, only desktop window has X
+   window associated with it.
+
+2. Messaging subsystem
+
+   Each Windows task/thread has its own message queue - this is where
+   it gets messages from. Messages can be generated on the fly
+   (WM_PAINT, WM_NCPAINT, WM_TIMER), they can be created by the system
+   (hardware messages), they can be posted by other tasks/threads
+   (PostMessage), or they can be sent by other tasks/threads (SendMessage).
+   
+   Message priority:
+
+   First the system looks for sent messages, then for posted messages,
+   then for hardware messages, then it checks if the queue has the
+   "dirty window" bit set, and, finally, it checks for expired
+   timers. See windows/message.c.
+
+   From all these different types of messages, only posted messages go
+   directly into the private message queue. System messages (even in
+   Win95) are first collected in the system message queue and then
+   they either sit there until Get/PeekMessage gets to process them
+   or, as in Win95, if system queue is getting clobbered, a special
+   thread ("raw input thread") assigns them to the private
+   queues. Sent messages are queued separately and the sender sleeps
+   until it gets a reply. Special messages are generated on the fly
+   depending on the window/queue state. If the window update region is
+   not empty, the system sets the QS_PAINT bit in the owning queue and
+   eventually this window receives a WM_PAINT message (WM_NCPAINT too
+   if the update region intersects with the non-client area). A timer
+   event is raised when one of the queue timers expire. Depending on
+   the timer parameters DispatchMessage either calls the callback
+   function or the window procedure. If there are no messages pending
+   the task/thread sleeps until messages appear.
+
+   There are several tricky moments (open for discussion) - 
+
+    a) System message order has to be honored and messages should be
+       processed within correct task/thread context. Therefore when
+       Get/PeekMessage encounters unassigned system message and this
+       message appears not to be for the current task/thread it should
+       either skip it (or get rid of it by moving it into the private
+       message queue of the target task/thread - Win95, AFAIK) and
+       look further or roll back and then yield until this message
+       gets processed when system switches to the correct context
+       (Win16). In the first case we lose correct message ordering, in
+       the second case we have the infamous synchronous system message
+       queue. Here is a post to one of the OS/2 newsgroup I found to
+       be relevant:
+
+       " Here's the problem in a nutshell, and there is no good solution.
+       Every possible solution creates a different problem.
+
+       With a windowing system, events can go to many different windows.
+       Most are sent by applications or by the OS when things relating to
+       that window happen (like repainting, timers, etc.)
+
+       Mouse input events go to the window you click on (unless some window
+       captures the mouse).
+
+       So far, no problem.  Whenever an event happens, you put a message on
+       the target window's message queue.  Every process has a message
+       queue.  If the process queue fills up, the messages back up onto the
+       system queue.
+
+       This is the first cause of apps hanging the GUI.  If an app doesn't
+       handle messages and they back up into the system queue, other apps
+       can't get any more messages.  The reason is that the next message in
+       line can't go anywhere, and the system won't skip over it.
+       
+       This can be fixed by making apps have bigger private message queues.
+       The SIQ fix does this.  PMQSIZE does this for systems without the SIQ
+       fix.  Applications can also request large queues on their own.
+
+       Another source of the problem, however, happens when you include
+       keyboard events.  When you press a key, there's no easy way to know
+       what window the keystroke message should be delivered to.
+
+       Most windowing systems use a concept known as "focus".  The window
+       with focus gets all incoming keyboard messages.  Focus can be changed
+       from window to window by apps or by users clicking on winodws.
+
+       This is the second source of the problem.  Suppose window A has focus.
+       You click on window B and start typing before the window gets focus.
+       Where should the keystrokes go?  On the one hand, they should go to A
+       until the focus actually changes to B.  On the other hand, you
+       probably want the keystrokes to go to B, since you clicked there
+       first.
+
+       OS/2's solution is that when a focus-changing event happens (like
+       clicking on a window), OS/2 holds all messages in the system queue
+       until the focus change actually happens.  This way, subsequent
+       keystrokes go to the window you clicked on, even if it takes a while
+       for that window to get focus.
+
+       The downside is that if the window takes a real long time to get focus
+       (maybe it's not handling events, or maybe the window losing focus
+       isn't handling events), everything backs up in the system queue and
+       the system appears hung.
+
+       There are a few solutions to this problem.
+
+       One is to make focus policy asynchronous.  That is, focus changing has
+       absolutely nothing to do with the keyboard.  If you click on a window
+       and start typing before the focus actually changes, the keystrokes go
+       to the first window until focus changes, then they go to the second.
+       This is what X-windows does.
+
+       Another is what NT does.  When focus changes, keyboard events are held
+       in the system message queue, but other events are allowed through.
+       This is "asynchronous" because the messages in the system queue are
+       delivered to the application queues in a different order from that
+       with which they were posted.  If a bad app won't handle the "lose
+       focus" message, it's of no consequence - the app receiving focus will
+       get its "gain focus" message, and the keystrokes will go to it.
+
+       The NT solution also takes care of the application queue filling up
+       problem.  Since the system delivers messages asynchronously, messages
+       waiting in the system queue will just sit there and the rest of the
+       messages will be delivered to their apps.
+
+       The OS/2 SIQ solution is this:  When a focus-changing event happens,
+       in addition to blocking further messages from the application queues,
+       a timer is started.  When the timer goes off, if the focus change has
+       not yet happened, the bad app has its focus taken away and all
+       messages targetted at that window are skipped.  When the bad app
+       finally handles the focus change message, OS/2 will detect this and
+       stop skipping its messages.
+
+
+       As for the pros and cons:
+
+       The X-windows solution is probably the easiest.  The problem is that
+       users generally don't like having to wait for the focus to change
+       before they start typing.  On many occasions, you can type and the
+       characters end up in the wrong window because something (usually heavy
+       system load) is preventing the focus change from happening in a timely
+       manner.
+       
+       The NT solution seems pretty nice, but making the system message queue
+       asynchronous can cause similar problems to the X-windows problem.
+       Since messages can be delivered out of order, programs must not assume
+       that two messages posted in a particular order will be delivered in
+       that same order.  This can break legacy apps, but since Win32 always
+       had an asynchronous queue, it is fair to simply tell app designers
+       "don't do that".  It's harder to tell app designers something like
+       that on OS/2 - they'll complain "you changed the rules and our apps
+       are breaking."
+       
+       The OS/2 solution's problem is that nothing happens until you try to
+       change window focus, and then wait for the timeout.  Until then, the
+       bad app is not detected and nothing is done." (by David Charlap)
+       
+
+    b) Intertask/interthread SendMessage. The system has to inform the
+       target queue about the forthcoming message, then it has to
+       carry out the context switch and wait until the result is
+       available.  In Win16 it is done by putting necessary parameters
+       into the queue structure and do a DirectedYield() call.
+       However, in Win32 there could be several messages pending sent
+       by preemptively executing threads, and in this case SendMessage
+       has to build some sort of message queue for sent
+       messages. Another issue is what to do with messages sent to the
+       sender when it is blocked inside its own SendMessage. At this
+       point Wine does not address any of these problems.
index 72f64adc198b131cc929b5a220f7714395b00dd8..365ee5996062ae95bd99b32021cc348fa252c595 100644 (file)
@@ -13,7 +13,6 @@
 extern DWORD MSG_WineStartTicks;  /* Ticks at Wine startup */
 
 /* message.c */
-extern BOOL MSG_GetHardwareMessage( LPMSG16 msg );
 extern BOOL MSG_InternalGetMessage( SEGPTR msg, HWND hwnd, HWND hwndOwner,
                                    short code, WORD flags, BOOL sendIdle );
 
@@ -21,13 +20,16 @@ extern BOOL MSG_InternalGetMessage( SEGPTR msg, HWND hwnd, HWND hwndOwner,
 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);
+extern LONG TIMER_GetNextExpiration(void);
+extern void TIMER_ExpireTimers(void);
+extern BOOL TIMER_GetTimerMsg( MSG16 *msg, HWND hwnd,
+                               HQUEUE hQueue, BOOL remove );
 
 /* event.c */
-extern BOOL EVENT_WaitXEvent( LONG maxWait );
+extern BOOL EVENT_WaitXEvent( BOOL sleep );
 extern void EVENT_Synchronize(void);
 extern void EVENT_ProcessEvent( XEvent *event );
-extern void EVENT_RegisterWindow( Window w, HWND hwnd );
+extern void EVENT_RegisterWindow( WND *pWnd );
 extern void EVENT_DummyMotionNotify(void);
 
 #endif  /* __WINE_MESSAGE_H */
index 553f7a41e6f1b04cf48733235efd6b5ebd13f5af..cffd7e3bf8eb1793d38110b0c064392c7f24508c 100644 (file)
@@ -32,7 +32,7 @@ typedef struct tagMESSAGEQUEUE
   WORD      queueSize;              /* 0c Size of the queue */
   DWORD     GetMessageTimeVal WINE_PACKED;  /* 0e Value for GetMessageTime */
   DWORD     GetMessagePosVal WINE_PACKED;   /* 12 Value for GetMessagePos */
-  WORD      reserved1;              /* 16 Unknown */
+  HQUEUE    self;                   /* 16 Handle to self (was: reserved) */
   DWORD     GetMessageExtraInfoVal; /* 18 Value for GetMessageExtraInfo */
   WORD      reserved2;              /* 1c Unknown */
   LPARAM    lParam WINE_PACKED;     /* 1e Next 4 values set by SendMessage */
@@ -75,6 +75,7 @@ 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_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit );
 extern void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue );
 extern void QUEUE_WaitBits( WORD bits );
 extern void QUEUE_IncPaintCount( HQUEUE hQueue );
index 64363f0470ce28e930784e0dec89c918b7e37a04..d60ce19a04054f7a203e6054ac66b56a3030cafb 100644 (file)
@@ -469,6 +469,7 @@ DECL_WINELIB_TYPE(LPNCCALCSIZE_PARAMS);
 
   /* CallMsgFilter() values */
 #define MSGF_DIALOGBOX      0
+#define MSGF_MESSAGEBOX     1
 #define MSGF_MENU           2
 #define MSGF_MOVE           3
 #define MSGF_SIZE           4
index ed8aaa7e7f8ac6516635d4e4aa358afbce73c4d1..fa59b22456accd65bd198a40355b973d4257ae7b 100644 (file)
@@ -84,7 +84,7 @@ WNDPROC MODULE_GetWndProcEntry16( char *name )
   MAP_STR_TO_PROC("ColorDlgProc",ColorDlgProc);
   MAP_STR_TO_PROC("ComboBoxWndProc",ComboBoxWndProc);
   MAP_STR_TO_PROC("ComboLBoxWndProc",ComboLBoxWndProc);
-  MAP_STR_TO_PROC("DefDlgProc",DefDlgProc);
+  MAP_STR_TO_PROC("DefDlgProc",DefDlgProc16);
   MAP_STR_TO_PROC("EditWndProc",EditWndProc);
   MAP_STR_TO_PROC("FileOpenDlgProc",FileOpenDlgProc);
   MAP_STR_TO_PROC("FileSaveDlgProc",FileSaveDlgProc);
index 8132b9de0c6dfcf5aeb9276d7833108a58b1a65a..b422d76b556b35161a32d84c35d4c02f640cba64 100644 (file)
@@ -677,7 +677,7 @@ void TASK_Reschedule(void)
 
     /* Flush any X events that happened in the meantime */
 
-    EVENT_WaitXEvent( 0 );
+    EVENT_WaitXEvent( FALSE );
 
     /* Find a task to yield to */
 
@@ -707,7 +707,7 @@ void TASK_Reschedule(void)
 
         /* No task found, wait for some events to come in */
 
-        EVENT_WaitXEvent( TIMER_GetNextExp() );
+        EVENT_WaitXEvent( TRUE );
     }
 
     if (hTask == hCurrentTask) return;  /* Nothing to do */
index 462cf77a0bf5eb1a8a9fc860e6897a20c6157f63..241116120e0037401217012173a15ac6ff4eb2c7 100644 (file)
@@ -1005,6 +1005,7 @@ LPVOID HeapReAlloc( HANDLE32 heap, DWORD flags, LPVOID ptr, DWORD size )
                 SetLastError( ERROR_OUTOFMEMORY );
                 return NULL;
             }
+            HEAP_ShrinkBlock( subheap, pArena, size );
         }
         else  /* Do it the hard way */
         {
@@ -1029,6 +1030,7 @@ LPVOID HeapReAlloc( HANDLE32 heap, DWORD flags, LPVOID ptr, DWORD size )
                                + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE);
             pInUse->threadId = GetCurrentTask();
             pInUse->magic    = ARENA_INUSE_MAGIC;
+            HEAP_ShrinkBlock( subheap, pInUse, size );
             memcpy( pInUse + 1, pArena + 1, oldSize );
 
             /* Free the previous block */
@@ -1038,11 +1040,7 @@ LPVOID HeapReAlloc( HANDLE32 heap, DWORD flags, LPVOID ptr, DWORD size )
             pArena  = pInUse;
         }
     }
-
-
-    /* Shrink the block */
-
-    HEAP_ShrinkBlock( subheap, pArena, size );
+    else HEAP_ShrinkBlock( subheap, pArena, size );  /* Shrink the block */
 
     /* Clear the extra bytes if needed */
 
index 4ff267ca3f4b05b26c36574a80ff542080e56340..d25775cd39db9744fe3f75bda7c865a014bdb611 100644 (file)
@@ -129,7 +129,7 @@ BOOL CLIPBOARD_RequestXSelection()
                     WIN_GetXWindow(hWnd),CurrentTime);
 
   /* TODO: need time-out for broken clients */
-  while(wait_for_selection) EVENT_WaitXEvent(-1);
+  while(wait_for_selection) EVENT_WaitXEvent( TRUE );
 
   return (BOOL)ClipFormats[0].wDataPresent;
 }
index 1eb5f540b7c01ee74373e36beeaf1cbd61d716f8..a8eb3f943ac01f66501772797217633179e9640b 100644 (file)
@@ -501,8 +501,8 @@ HICON InternalExtractIcon(HINSTANCE hInstance, LPCSTR lpszExeFileName, UINT nIco
 
                  for( i = nIconIndex; i < nIconIndex + n; i++ ) 
                     {
-                      hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + (i - nIconIndex)
-                                                                                *(WORD*)pData );
+                      hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i
+                                                                 *(WORD*)pData );
                       RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
                       GlobalFree16(hIcon); 
                     }
@@ -547,18 +547,40 @@ HICON ExtractIcon(HINSTANCE hInstance, LPCSTR lpszExeFileName, WORD nIconIndex)
 
 /*************************************************************************
  *                             ExtractAssociatedIcon   [SHELL.36]
+ * 
+ * Return icon for given file (either from file itself or from associated
+ * executable) and patch parameters if needed.
  */
 HICON ExtractAssociatedIcon(HINSTANCE hInst,LPSTR lpIconPath, LPWORD lpiIcon)
 {
     HICON hIcon = ExtractIcon(hInst, lpIconPath, *lpiIcon);
 
-    /* MAKEINTRESOURCE(2) seems to be "default" icon according to Progman 
-     *
-     * For data files it probably should call FindExecutable and load
-     * icon from there. As of now FindExecutable is empty stub.
-     */
+    if( hIcon < 2 )
+      {
+
+       if( hIcon == 1 ) /* no icons found in given file */
+         {
+           char  tempPath[0x80];
+           UINT  uRet = FindExecutable(lpIconPath,NULL,tempPath);
+
+           if( uRet > 32 && tempPath[0] )
+             {
+               strcpy(lpIconPath,tempPath);
+               hIcon = ExtractIcon(hInst, lpIconPath, *lpiIcon);
 
-    if( hIcon < 2 ) hIcon = LoadIcon( hInst, MAKEINTRESOURCE(2));
+               if( hIcon > 2 ) return hIcon;
+             }
+           else hIcon = 0;
+         }
+       
+       if( hIcon == 1 ) 
+         *lpiIcon = 2;   /* MSDOS icon - we found .exe but no icons in it */
+       else
+         *lpiIcon = 6;   /* generic icon - found nothing */
+
+        GetModuleFileName(hInst, lpIconPath, 0x80);
+       hIcon = LoadIcon( hInst, MAKEINTRESOURCE(*lpiIcon));
+      }
 
     return hIcon;
 }
index ac3b8bc197468ef2a416492832cf82d7940fbb2c..f8f77aaa71cdd4005d5933c7ed4570dab46e6084 100644 (file)
@@ -248,7 +248,7 @@ INT16 wvsnprintf16( LPSTR buffer, UINT16 maxlen, LPCSTR spec, LPCVOID args )
         {
         case WPR_CHAR:
             cur_arg = (DWORD)*(CHAR *)args;
-            args = (CHAR *)args + 1;
+            args = (WORD *)args + 1;
             break;
         case WPR_STRING:
             cur_arg = (DWORD)PTR_SEG_TO_LIN( *(SEGPTR *)args );
index 63495609af217bd1ebd2558cf86605fce1a59629..d305001929b1a50f892d0efa1698dd5111747e97 100644 (file)
@@ -621,9 +621,9 @@ BOOL DeleteDC( HDC hdc )
        SelectObject( hdc, STOCK_WHITE_BRUSH );
        SelectObject( hdc, STOCK_SYSTEM_FONT );
        XFreeGC( display, dc->u.x.gc );
+        if (dc->w.flags & DC_MEMORY) DeleteObject( dc->w.hFirstBitmap );
     }
 
-    if (dc->w.flags & DC_MEMORY) DeleteObject( dc->w.hFirstBitmap );
     if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
     if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
     if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
index dc9865cce62df3fa0473ddfe305e2cec2246e4d1..a2a37a2e87b47023df5a98efc7f1050f6d727f5c 100644 (file)
@@ -200,7 +200,7 @@ static BOOL CLASS_FreeClass( CLASS *classPtr )
     if (classPtr->hbrBackground) DeleteObject( classPtr->hbrBackground );
     GlobalDeleteAtom( classPtr->atomName );
     CLASS_SetMenuNameA( classPtr, NULL );
-    CLASS_SetWndProc( classPtr, (WNDPROC16)0, WIN_PROC_16 );
+    CLASS_SetWndProc( classPtr, (HANDLE32)0, WIN_PROC_16 );
     HeapFree( SystemHeap, 0, classPtr );
     return TRUE;
 }
index 8a809c97602780e75da0fd0634440ced8b92f727..f334bb9a706dc08780144af02e71309f8c53952a 100644 (file)
@@ -159,9 +159,8 @@ BOOL DCE_InvalidateDCE(WND* wndScope, RECT16* pRectUpdate)
 
                dprintf_dc(stddeb,"\tgot hwnd %04x\n", wndCurrent->hwndSelf);
   
-               if( wndCurrent->parent != wndScope )
-                   MapWindowPoints16(wndCurrent->parent->hwndSelf, wndScope->hwndSelf,
-                                                                (LPPOINT16)&wndRect, 2);
+               MapWindowPoints16(wndCurrent->parent->hwndSelf, wndScope->hwndSelf,
+                                                              (LPPOINT16)&wndRect, 2);
                if( IntersectRect16(&wndRect,&wndRect,pRectUpdate) )
                    SetHookFlags(dce->hDC, DCHF_INVALIDATEVISRGN);
                break;
index 66fb8190b375c22a26dec800f3983199fb3ec1b8..4f421a4cacbe48c9ce1aa01841f3449b76779de1 100644 (file)
@@ -25,6 +25,7 @@
 #include "class.h"
 #include "clipboard.h"
 #include "debugger.h"
+#include "message.h"
 #include "module.h"
 #include "options.h"
 #include "queue.h"
 #include "dde_proc.h"
 
 
-#ifdef ndef
-#ifndef FamilyAmoeba
-typedef char *XPointer;
-#endif
-#endif
-
-#ifdef WHO_NEEDS_DIRTY_HACKS
-#ifdef sparc
-/* Dirty hack to compile with Sun's OpenWindows */
-typedef char *XPointer;
-#endif
-#endif
-
 #define NB_BUTTONS      3     /* Windows can handle 3 buttons */
 
   /* X context to associate a hwnd to an X window */
@@ -152,13 +140,13 @@ static void EVENT_ButtonRelease( XButtonEvent *event );
 static void EVENT_MotionNotify( XMotionEvent *event );
 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
-static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
-static void EVENT_GraphicsExpose( HWND hwnd, XGraphicsExposeEvent *event );
+static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
+static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
-static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event);
-static void EVENT_SelectionNotify( HWND hwnd, XSelectionEvent *event);
-static void EVENT_SelectionClear( HWND hwnd, XSelectionClearEvent *event);
-static void EVENT_ClientMessage( HWND hwnd, XClientMessageEvent *event );
+static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
+static void EVENT_SelectionNotify( XSelectionEvent *event);
+static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
+static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
 
 
 /***********************************************************************
@@ -168,14 +156,14 @@ static void EVENT_ClientMessage( HWND hwnd, XClientMessageEvent *event );
  */
 void EVENT_ProcessEvent( XEvent *event )
 {
-    HWND hwnd;
-    XPointer ptr;
+    WND *pWnd;
     
-    XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
-    hwnd = (HWND) (int)ptr;
+    if (XFindContext( display, ((XAnyEvent *)event)->window, winContext,
+                      (char **)&pWnd ) != 0)
+        return;  /* Not for a registered window */
 
-    dprintf_event(stddeb, "Got event %s for hwnd %04x\n",
-                  event_names[event->type], hwnd );
+    dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
+                   event_names[event->type], pWnd->hwndSelf );
 
     switch(event->type)
     {
@@ -207,46 +195,47 @@ void EVENT_ProcessEvent( XEvent *event )
        break;
 
     case FocusIn:
-        EVENT_FocusIn( hwnd, (XFocusChangeEvent*)event );
+        EVENT_FocusIn( pWnd->hwndSelf, (XFocusChangeEvent*)event );
        break;
 
     case FocusOut:
-       EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
+       EVENT_FocusOut( pWnd->hwndSelf, (XFocusChangeEvent*)event );
        break;
 
     case Expose:
-       EVENT_Expose( hwnd, (XExposeEvent*)event );
+       EVENT_Expose( pWnd, (XExposeEvent *)event );
        break;
 
+    case GraphicsExpose:
+       EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
+        break;
+
     case ConfigureNotify:
-       EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
+       EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
        break;
 
     case SelectionRequest:
-       EVENT_SelectionRequest( hwnd, (XSelectionRequestEvent*)event );
+       EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
        break;
 
     case SelectionNotify:
-       EVENT_SelectionNotify( hwnd, (XSelectionEvent*)event );
+       EVENT_SelectionNotify( (XSelectionEvent *)event );
        break;
 
     case SelectionClear:
-       EVENT_SelectionClear( hwnd, (XSelectionClearEvent*) event );
+       EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
        break;
 
     case ClientMessage:
-       EVENT_ClientMessage( hwnd, (XClientMessageEvent *) event );
+       EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
        break;
 
-    case GraphicsExpose:
-       EVENT_GraphicsExpose( hwnd, (XGraphicsExposeEvent *) event );
-
     case NoExpose:
        break;   
 
     default:    
        dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
-               event_names[event->type], hwnd );
+               event_names[event->type], pWnd->hwndSelf );
        break;
     }
 }
@@ -257,29 +246,31 @@ void EVENT_ProcessEvent( XEvent *event )
  *
  * Associate an X window to a HWND.
  */
-void EVENT_RegisterWindow( Window w, HWND hwnd )
+void EVENT_RegisterWindow( WND *pWnd )
 {
     if (!winContext) winContext = XUniqueContext();
-    XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
+    XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
 }
 
 
 /***********************************************************************
  *           EVENT_WaitXEvent
  *
- * Wait for an X event, but at most maxWait milliseconds (-1 for no timeout).
+ * Wait for an X event, optionally sleeping until one arrives.
  * Return TRUE if an event is pending, FALSE on timeout or error
  * (for instance lost connection with the server).
  */
-BOOL EVENT_WaitXEvent( LONG maxWait )
+BOOL EVENT_WaitXEvent( BOOL sleep )
 {
     fd_set read_set;
     struct timeval timeout;
     XEvent event;
     int fd = ConnectionNumber(display);
 
-    if (!XPending(display) && (maxWait != -1))
+    if (!XPending(display))
     {
+        LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
+
         FD_ZERO( &read_set );
         FD_SET( fd, &read_set );
 
@@ -295,18 +286,23 @@ BOOL EVENT_WaitXEvent( LONG maxWait )
                ;
            return TRUE;
        }
-       stop_wait_op= STOP_WAIT_X;
-       /* The code up to the next "stop_wait_op= CONT" must be reentrant  */
+       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;
+           !XPending(display))
+        {
+           stop_wait_op = CONT;
+            TIMER_ExpireTimers();
            return FALSE;
-       } else {
-           stop_wait_op= CONT;
        }
+        else stop_wait_op = CONT;
 #else  /* CONFIG_IPC */
        if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
-            return FALSE;  /* Timeout or error */
+        {
+            /* Timeout or error */
+            TIMER_ExpireTimers();
+            return FALSE;
+        }
 #endif  /* CONFIG_IPC */
 
     }
@@ -371,19 +367,17 @@ static WORD EVENT_XStateToKeyState( int state )
 /***********************************************************************
  *           EVENT_Expose
  */
-static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
+static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
 {
     RECT32 rect;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return;
 
-      /* Make position relative to client area instead of window */
-    rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
-    rect.top  = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
+    /* Make position relative to client area instead of window */
+    rect.left   = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
+    rect.top    = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
     rect.right  = rect.left + event->width;
     rect.bottom = rect.top + event->height;
 
-    RedrawWindow32( hwnd, &rect, 0,
+    RedrawWindow32( pWnd->hwndSelf, &rect, 0,
                     RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
                     (event->count ? 0 : RDW_ERASENOW) );
 }
@@ -391,22 +385,21 @@ static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
 
 /***********************************************************************
  *           EVENT_GraphicsExpose
+ *
  * This is needed when scrolling area is partially obscured
  * by non-Wine X window.
  */
-static void EVENT_GraphicsExpose( HWND hwnd, XGraphicsExposeEvent *event )
+static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
 {
-    RECT16 rect;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return;
+    RECT32 rect;
 
-      /* Make position relative to client area instead of window */
-    rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
-    rect.top  = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
+    /* Make position relative to client area instead of window */
+    rect.left   = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
+    rect.top    = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
     rect.right  = rect.left + event->width;
     rect.bottom = rect.top + event->height;
 
-    RedrawWindow16( hwnd, &rect, 0,
+    RedrawWindow32( pWnd->hwndSelf, &rect, 0,
                     RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
                     (event->count ? 0 : RDW_ERASENOW) );
 }
@@ -712,7 +705,7 @@ static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
 /***********************************************************************
  *           EVENT_SelectionRequest
  */
-static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event )
+static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
 {
     XSelectionEvent result;
     Atom           rprop = None;
@@ -731,7 +724,7 @@ static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event )
         else if(!CLIPBOARD_IsPresent(CF_TEXT)) rprop = None;
        else{
             /* Don't worry if we can't open */
-           BOOL couldOpen=OpenClipboard(hwnd);
+           BOOL couldOpen=OpenClipboard( pWnd->hwndSelf );
            hText=GetClipboardData(CF_TEXT);
            text=GlobalLock16(hText);
            XChangeProperty(display,request,rprop,XA_STRING,
@@ -759,28 +752,28 @@ static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event )
 /***********************************************************************
  *           EVENT_SelectionNotify
  */
-static void EVENT_SelectionNotify(HWND hwnd, XSelectionEvent *event)
+static void EVENT_SelectionNotify( XSelectionEvent *event )
 {
-    if(event->selection!=XA_PRIMARY)return;
-    if(event->target!=XA_STRING)CLIPBOARD_ReadSelection(0,None);
-    CLIPBOARD_ReadSelection(event->requestor,event->property);
+    if (event->selection != XA_PRIMARY) return;
+    if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
+    CLIPBOARD_ReadSelection( event->requestor, event->property );
 }
 
 
 /***********************************************************************
  *           EVENT_SelectionClear
  */
-static void EVENT_SelectionClear(HWND hwnd, XSelectionClearEvent *event)
+static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
 {
-    if(event->selection!=XA_PRIMARY)return;
-    CLIPBOARD_ReleaseSelection(hwnd); 
+    if (event->selection != XA_PRIMARY) return;
+    CLIPBOARD_ReleaseSelection( pWnd->hwndSelf ); 
 }
 
 
 /**********************************************************************
  *           EVENT_ClientMessage
  */
-static void EVENT_ClientMessage (HWND hwnd, XClientMessageEvent *event )
+static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
 {
     static Atom wmProtocols = None;
     static Atom wmDeleteWindow = None;
@@ -796,7 +789,7 @@ static void EVENT_ClientMessage (HWND hwnd, XClientMessageEvent *event )
        dprintf_event( stddeb, "unrecognized ClientMessage\n" );
        return;
     }
-    SendMessage16( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
+    SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
 }
 
 
index 9ae2b69175c1ef6ae388e557d90be468153e1254..3d2be8a9f0088ba62ac7866fdadf76fc840c0967 100644 (file)
@@ -48,6 +48,7 @@ BOOL16 DPtoLP16( HDC16 hdc, LPPOINT16 points, INT16 count )
     {
        points->x = XDPTOLP( dc, points->x );
        points->y = YDPTOLP( dc, points->y );
+        points++;
     }
     return TRUE;
 }
@@ -65,6 +66,7 @@ BOOL32 DPtoLP32( HDC32 hdc, LPPOINT32 points, INT32 count )
     {
        points->x = XDPTOLP( dc, points->x );
        points->y = YDPTOLP( dc, points->y );
+        points++;
     }
     return TRUE;
 }
@@ -82,6 +84,7 @@ BOOL16 LPtoDP16( HDC16 hdc, LPPOINT16 points, INT16 count )
     {
        points->x = XLPTODP( dc, points->x );
        points->y = YLPTODP( dc, points->y );
+        points++;
     }
     return TRUE;
 }
@@ -99,6 +102,7 @@ BOOL32 LPtoDP32( HDC32 hdc, LPPOINT32 points, INT32 count )
     {
        points->x = XLPTODP( dc, points->x );
        points->y = YLPTODP( dc, points->y );
+        points++;
     }
     return TRUE;
 }
index 8ff4af2688e1329eae2768b79213094a20395335..c777683f1439b965d74bd48cb1f0698a40ce9fe8 100644 (file)
 extern BYTE*   KeyStateTable;                           /* event.c */
 extern WPARAM  lastEventChar;                           /* event.c */
 
-extern BOOL TIMER_CheckTimer( LONG *next, MSG16 *msg,
-                             HWND hwnd, BOOL remove );  /* timer.c */
-
-DWORD MSG_WineStartTicks;                               /* Ticks at Wine startup */
+DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
 
 static WORD doubleClickSpeed = 452;
 
@@ -68,9 +65,8 @@ static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
 
       /* Find the window */
 
-    if (GetCapture())
+    if ((msg->hwnd = GetCapture()) != 0)
     {
-       msg->hwnd = GetCapture();
        ScreenToClient16( msg->hwnd, &pt );
        msg->lParam = MAKELONG( pt.x, pt.y );
         /* No need to further process the message */
@@ -80,6 +76,16 @@ static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
     }
    
     hittest = WINPOS_WindowFromPoint( msg->pt, &pWnd );
+    if (pWnd->hmemTaskQ != GetTaskQueue(0))
+    {
+        /* Not for the current task */
+        MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) );
+        if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
+        /* Wake up the other task */
+        queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
+        if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
+        return FALSE;
+    }
     msg->hwnd = pWnd->hwndSelf;
     if ((hittest != HTERROR) && mouseClick)
     {
@@ -172,6 +178,8 @@ static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
  */
 static BOOL MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
 {
+    WND *pWnd;
+
       /* Should check Ctrl-Esc and PrintScreen here */
 
     msg->hwnd = GetFocus();
@@ -185,6 +193,17 @@ static BOOL MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
        if( msg->message < WM_SYSKEYDOWN )
            msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
     }
+    pWnd = WIN_FindWndPtr( msg->hwnd );
+    if (pWnd && (pWnd->hmemTaskQ != GetTaskQueue(0)))
+    {
+        /* Not for the current task */
+        MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) );
+        if (queue) QUEUE_ClearWakeBit( queue, QS_KEY );
+        /* Wake up the other task */
+        queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
+        if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
+        return FALSE;
+    }
     return !HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
                             msg->wParam, msg->lParam );
 }
@@ -202,7 +221,7 @@ static BOOL MSG_PeekHardwareMsg( MSG16 *msg, HWND hwnd, WORD first, WORD last,
     int i, pos = sysMsgQueue->nextMessage;
 
     /* If the queue is empty, attempt to fill it */
-    if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( 0 );
+    if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( FALSE );
 
     for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
     {
@@ -266,38 +285,6 @@ WORD GetDoubleClickTime()
 }              
 
 
-/***********************************************************************
- *           MSG_GetHardwareMessage
- *
- * Like GetMessage(), but only return mouse and keyboard events.
- * Used internally for window moving and resizing. Mouse messages
- * are not translated.
- * Warning: msg->hwnd is always 0.
- */
-BOOL MSG_GetHardwareMessage( LPMSG16 msg )
-{
-#if 0
-    int pos;
-    XEvent event;
-    MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
-
-    while(1)
-    {    
-       if ((pos = QUEUE_FindMsg( sysMsgQueue, 0, 0, 0 )) != -1)
-       {
-           *msg = sysMsgQueue->messages[pos].msg;
-           QUEUE_RemoveMsg( sysMsgQueue, pos );
-           break;
-       }
-       XNextEvent( display, &event );
-       EVENT_ProcessEvent( &event );
-    }
-#endif
-    MSG_PeekMessage( msg, 0, WM_KEYFIRST, WM_MOUSELAST, PM_REMOVE, 0 );
-    return TRUE;
-}
-
-
 /***********************************************************************
  *           MSG_SendMessage
  *
@@ -381,7 +368,6 @@ static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last,
     int pos, mask;
     MESSAGEQUEUE *msgQueue;
     HQUEUE       hQueue;
-    LONG nextExp;  /* Next timer expiration time */
 
 #ifdef CONFIG_IPC
     DDE_TestDDE(hwnd); /* do we have dde handling in the window ?*/
@@ -490,10 +476,8 @@ static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last,
         }
        if ((msgQueue->wakeBits & mask) & QS_TIMER)
        {
-           if (TIMER_CheckTimer( &nextExp, msg, hwnd, flags & PM_REMOVE ))
-               break;  /* Got a timer msg */
+           if (TIMER_GetTimerMsg(msg, hwnd, hQueue, flags & PM_REMOVE)) break;
        }
-       else nextExp = -1;  /* No timeout needed */
 
         if (peek)
         {
@@ -792,24 +776,7 @@ LRESULT SendMessage32W(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
  */
 void WaitMessage( void )
 {
-    MSG16 msg;
-    MESSAGEQUEUE *queue;
-    LONG nextExp = -1;  /* Next timer expiration time */
-
-#ifdef CONFIG_IPC
-    DDE_GetRemoteMessage();
-#endif  /* CONFIG_IPC */
-    
-    if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
-    if ((queue->wPostQMsg) || 
-        (queue->wakeBits & (QS_SENDMESSAGE | QS_PAINT)) ||
-        (queue->msgCount) || (QUEUE_GetSysQueue()->msgCount) )
-        return;
-    if ((queue->wakeBits & QS_TIMER) && 
-        TIMER_CheckTimer( &nextExp, &msg, 0, FALSE))
-        return;
-    /* FIXME: (dde) must check DDE & X-events simultaneously */
-    EVENT_WaitXEvent( nextExp );
+    QUEUE_WaitBits( QS_ALLINPUT );
 }
 
 
index a51ae71553a27ce82b822a0a6b0d88525d9b5217..67b052dedeac6130c0063f10ea6a81b14257ef3f 100644 (file)
@@ -16,6 +16,7 @@
 #include "menu.h"
 #include "winpos.h"
 #include "scroll.h"
+#include "stackframe.h"
 #include "nonclient.h"
 #include "graphics.h"
 #include "queue.h"
@@ -907,7 +908,8 @@ static LONG NC_StartSizeMove( HWND hwnd, WPARAM wParam, POINT16 *capturePoint )
        SetCapture(hwnd);
        while(!hittest)
        {
-           MSG_GetHardwareMessage( &msg );
+            MSG_InternalGetMessage( MAKE_SEGPTR(&msg), 0, 0, MSGF_SIZE,
+                                    PM_REMOVE, FALSE );
            switch(msg.message)
            {
            case WM_MOUSEMOVE:
@@ -1046,7 +1048,8 @@ static void NC_DoSizeMove( HWND hwnd, WORD wParam, POINT16 pt )
     {
         int dx = 0, dy = 0;
 
-       MSG_GetHardwareMessage( &msg );
+        MSG_InternalGetMessage( MAKE_SEGPTR(&msg), 0, 0, MSGF_SIZE,
+                                PM_REMOVE, FALSE );
 
          /* Exit on button-up, Return, or Esc */
        if ((msg.message == WM_LBUTTONUP) ||
@@ -1148,7 +1151,7 @@ static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
     do
     {
        BOOL oldstate = pressed;
-       MSG_GetHardwareMessage( &msg );
+        MSG_InternalGetMessage( MAKE_SEGPTR(&msg), 0, 0, 0, PM_REMOVE, FALSE );
 
        pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
        if (pressed != oldstate)
index eb457edb67636eab97824489b4c7add79652694e..c1406c1a5863a97d8061bbbfa8b0e51f46259a40 100644 (file)
@@ -16,6 +16,8 @@
 
 static HQUEUE hFirstQueue = 0;
 static HQUEUE hmemSysMsgQueue = 0;
+static MESSAGEQUEUE *pMouseQueue = NULL;  /* Queue for last mouse message */
+static MESSAGEQUEUE *pKbdQueue = NULL;    /* Queue for last kbd message */
 static HQUEUE hDoomedQueue = 0;
 static MESSAGEQUEUE *sysMsgQueue = NULL;
 
@@ -111,6 +113,7 @@ static HQUEUE QUEUE_CreateMsgQueue( int size )
     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->wWinVersion = pTask ? pTask->version : 0;
@@ -144,6 +147,7 @@ BOOL QUEUE_DeleteMsgQueue( HQUEUE hQueue )
         pPrev = &msgQ->next;
     }
     if (*pPrev) *pPrev = msgQueue->next;
+    msgQueue->self = 0;
     GlobalFree16( hQueue );
     return 1;
 }
@@ -181,6 +185,8 @@ MESSAGEQUEUE *QUEUE_GetSysQueue(void)
  */
 void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
 {
+    if (bit & QS_MOUSE) pMouseQueue = queue;
+    if (bit & QS_KEY) pKbdQueue = queue;
     queue->changeBits |= bit;
     queue->wakeBits   |= bit;
     if (queue->wakeMask & bit)
@@ -191,6 +197,16 @@ void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
 }
 
 
+/***********************************************************************
+ *           QUEUE_ClearWakeBit
+ */
+void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit )
+{
+    queue->changeBits &= ~bit;
+    queue->wakeBits   &= ~bit;
+}
+
+
 /***********************************************************************
  *           QUEUE_WaitBits
  *
@@ -233,16 +249,22 @@ void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
     WPARAM wParam;
     LPARAM lParam;
     LRESULT result = 0;
+    HQUEUE oldSender;
 
     printf( "ReceiveMessage\n" );
     if (!(queue->wakeBits & QS_SENDMESSAGE)) return;
     if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask))) return;
 
     /* Remove sending queue from the list */
+    oldSender                  = queue->InSendMessageHandle;
     queue->InSendMessageHandle = queue->hSendingTask;
     queue->hSendingTask        = senderQ->hPrevSendingTask;
     senderQ->hPrevSendingTask  = 0;
-    if (!queue->hSendingTask) queue->wakeBits &= ~QS_SENDMESSAGE;
+    if (!queue->hSendingTask)
+    {
+        queue->wakeBits &= ~QS_SENDMESSAGE;
+        queue->changeBits &= ~QS_SENDMESSAGE;
+    }
 
     /* Get the parameters from the sending task */
     hwnd   = senderQ->hWnd;
@@ -257,13 +279,21 @@ void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
 
     /* Call the window procedure */
     /* FIXME: should we use CallWindowProc here? */
-    if (IsWindow( hwnd )) result = SendMessage16( hwnd, msg, wParam, lParam );
+    if (IsWindow( 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 );
 
     /* Return the result to the sender task */
     ReplyMessage( result );
+
+    queue->InSendMessageHandle = oldSender;
 }
 
 
@@ -373,15 +403,18 @@ static void QUEUE_WakeSomeone( UINT message )
 
     if (!(hwnd = GetSysModalWindow()))
     {
-        hwnd = (wakeBit == QS_KEY) ? GetFocus() : GetCapture();
-        if (!hwnd) hwnd = GetActiveWindow();
+        if (wakeBit == QS_KEY)
+        {
+            if (!(hwnd = GetFocus())) hwnd = GetActiveWindow();
+        }
+        else hwnd = GetCapture();
     }
     if (hwnd)
     {
         WND *wndPtr = WIN_FindWndPtr( hwnd );
         if (wndPtr) queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
     }
-    else
+    else if (!(queue = pMouseQueue))
     {
         hQueue = hFirstQueue;
         while (hQueue)
index 53156d2b70d30e1dcf80355bab61be8214461e3e..31e3940062fc41e255e956726cf2f90d05058241 100644 (file)
@@ -19,7 +19,7 @@ typedef struct tagTIMER
     WORD             id;
     WORD             timeout;
     struct tagTIMER *next;
-    DWORD            expires;
+    DWORD            expires;  /* Next expiration, or 0 if already expired */
     FARPROC          proc;
 } TIMER;
 
@@ -70,6 +70,7 @@ static void TIMER_RemoveTimer( TIMER * pTimer )
     while (*ppTimer && (*ppTimer != pTimer)) ppTimer = &(*ppTimer)->next;
     if (*ppTimer) *ppTimer = pTimer->next;
     pTimer->next = NULL;
+    if (!pTimer->expires) QUEUE_DecTimerCount( pTimer->hq );
 }
 
 
@@ -81,7 +82,6 @@ static void TIMER_RemoveTimer( TIMER * pTimer )
 static void TIMER_ClearTimer( TIMER * pTimer )
 {
     TIMER_RemoveTimer( pTimer );
-    QUEUE_DecTimerCount( pTimer->hq );
     pTimer->hwnd    = 0;
     pTimer->msg     = 0;
     pTimer->id      = 0;
@@ -151,44 +151,58 @@ static void TIMER_RestartTimer( TIMER * pTimer, DWORD curTime )
 
                               
 /***********************************************************************
- *           TIMER_GetNextExp
+ *           TIMER_GetNextExpiration
  *
  * Return next timer expiration time, or -1 if none.
  */
-LONG TIMER_GetNextExp(void)
+LONG TIMER_GetNextExpiration(void)
 {
     return pNextTimer ? EXPIRE_TIME( pNextTimer, GetTickCount() ) : -1;
 }
 
 
 /***********************************************************************
- *           TIMER_CheckTimer
+ *           TIMER_ExpireTimers
  *
- * Check whether a timer has expired, and create a message if necessary.
- * Otherwise, return time until next timer expiration in 'next'.
- * If 'hwnd' is not NULL, only consider timers for this window.
- * If 'remove' is TRUE, remove all expired timers up to the returned one.
+ * Mark expired timers and wake the appropriate queues.
  */
-BOOL TIMER_CheckTimer( LONG *next, MSG16 *msg, HWND hwnd, BOOL remove )
+void TIMER_ExpireTimers(void)
 {
-    TIMER * pTimer = pNextTimer;
+    TIMER *pTimer = pNextTimer;
+    DWORD curTime = GetTickCount();
+
+    while (pTimer && !pTimer->expires)  /* Skip already expired timers */
+        pTimer = pTimer->next;
+    while (pTimer && (pTimer->expires <= curTime))
+    {
+        pTimer->expires = 0;
+        QUEUE_IncTimerCount( pTimer->hq );
+        pTimer = pTimer->next;
+    }
+}
+
+
+/***********************************************************************
+ *           TIMER_GetTimerMsg
+ *
+ * Build a message for an expired timer.
+ */
+BOOL TIMER_GetTimerMsg( MSG16 *msg, HWND hwnd, HQUEUE hQueue, BOOL remove )
+{
+    TIMER *pTimer = pNextTimer;
     DWORD curTime = GetTickCount();
 
     if (hwnd)  /* Find first timer for this window */
        while (pTimer && (pTimer->hwnd != hwnd)) pTimer = pTimer->next;
+    else   /* Find first timer for this queue */
+       while (pTimer && (pTimer->hq != hQueue)) pTimer = pTimer->next;
 
-    if (!pTimer) *next = -1;
-    else *next = EXPIRE_TIME( pTimer, curTime );
-    if (*next != 0) return FALSE;  /* No timer expired */
+    if (!pTimer || (pTimer->expires > curTime)) return FALSE; /* No timer */
+    if (remove)        TIMER_RestartTimer( pTimer, curTime );  /* Restart it */
 
-    if (remove)        /* Restart all timers before pTimer, and then pTimer itself */
-    {
-       while (pNextTimer != pTimer) TIMER_RestartTimer( pNextTimer, curTime );
-       TIMER_RestartTimer( pTimer, curTime );
-    }
+    dprintf_timer( stddeb, "Timer expired: %04x, %04x, %04x, %08lx\n", 
+                  pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
 
-    dprintf_timer(stddeb, "Timer expired: %p, %04x, %04x, %04x, %08lx\n", 
-                 pTimer, pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
       /* Build the message */
     msg->hwnd    = pTimer->hwnd;
     msg->message = pTimer->msg;
@@ -218,10 +232,10 @@ static WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout,
             (pTimer->timeout != 0))
         {
               /* Got one: set new values and return */
+            TIMER_RemoveTimer( pTimer );
             pTimer->timeout = timeout;
-            pTimer->expires = GetTickCount() + timeout;
             pTimer->proc    = proc;
-            TIMER_RemoveTimer( pTimer );
+            pTimer->expires = GetTickCount() + timeout;
             TIMER_InsertTimer( pTimer );
             return id;
         }
@@ -248,7 +262,6 @@ static WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout,
     dprintf_timer(stddeb, "Timer added: %p, %04x, %04x, %04x, %08lx\n", 
                  pTimer, pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
     TIMER_InsertTimer( pTimer );
-    QUEUE_IncTimerCount( pTimer->hq );
     if (!id)
        return TRUE;
     else
index 8c23889ac60c7b92e85ad7417a9174b72806cfcd..c6e5188cffb040a69c522b4e78ce587bbc4ac457 100644 (file)
@@ -347,7 +347,7 @@ static void WIN_DestroyWindow( HWND hwnd )
     if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
     if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
     if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
-    WIN_SetWndProc( wndPtr, (WNDPROC16)0, WIN_PROC_16 );
+    WIN_SetWndProc( wndPtr, (HANDLE32)0, WIN_PROC_16 );
     wndPtr->class->cWindows--;
     USER_HEAP_FREE( hwnd );
 }
@@ -426,7 +426,7 @@ BOOL WIN_CreateDesktopWindow(void)
     pWndDesktop->hProp             = 0;
     pWndDesktop->userdata          = 0;
 
-    EVENT_RegisterWindow( pWndDesktop->window, hwndDesktop );
+    EVENT_RegisterWindow( pWndDesktop );
     SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
     if ((hdc = GetDC( hwndDesktop )) != 0)
     {
@@ -628,7 +628,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
             Window win = WIN_GetXWindow( cs->hwndParent );
             if (win) XSetTransientForHint( display, wndPtr->window, win );
        }
-        EVENT_RegisterWindow( wndPtr->window, hwnd );
+        EVENT_RegisterWindow( wndPtr );
     }
 
     /* Set the window menu */