]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/app.cpp
ODBC updates
[wxWidgets.git] / src / msw / app.cpp
index aa041848e881e8c3ac65859836e8f5ea72361636..e795e424539196bd94c88336e19f8d281f92b19e 100644 (file)
 #include "wx/log.h"
 #include "wx/module.h"
 
+#if wxUSE_THREADS
+    #include "wx/thread.h"
+
+    // define the array of MSG strutures
+    WX_DECLARE_OBJARRAY(MSG, wxMsgArray);
+
+    #include "wx/arrimpl.cpp"
+
+    WX_DEFINE_OBJARRAY(wxMsgArray);
+#endif // wxUSE_THREADS
+
 #if wxUSE_WX_RESOURCES
   #include "wx/resource.h"
 #endif
@@ -47,7 +58,7 @@
 // if you don't do the same for the Ole calls further down.
 // Also, OLE is used not just for drag and drop (it's used by automatn.cpp).
 // #if wxUSE_DRAG_AND_DROP
-#ifndef __GNUWIN32__
+#if !defined(__GNUWIN32__) && !defined(__SC__)
 #include <ole2.h>
 #endif
 // #endif
 extern char *wxBuffer;
 extern char *wxOsVersion;
 extern wxList *wxWinHandleList;
-extern wxList wxPendingDelete;
+extern wxList WXDLLEXPORT wxPendingDelete;
 extern void wxSetKeyboardHook(bool doIt);
 extern wxCursor *g_globalCursor;
 
@@ -196,7 +207,7 @@ bool wxApp::Initialize()
     }
 */
 
-#ifndef __GNUWIN32__
+#if !defined(__GNUWIN32__) && !defined(__SC__)
     // we need to initialize OLE library
     if ( FAILED(::OleInitialize(NULL)) )
       wxFatalError(_("Cannot initialize OLE"));
@@ -513,7 +524,7 @@ void wxApp::CleanUp()
   if ( wxDisableButtonBrush )
     ::DeleteObject( wxDisableButtonBrush ) ;
 
-#ifndef __GNUWIN32__
+#if !defined(__GNUWIN32__) && !defined(__SC__)
   ::OleUninitialize();
 #endif
 
@@ -557,7 +568,7 @@ int wxEntry(WXHINSTANCE hInstance,
             int nCmdShow,
             bool enterLoop)
 {
-#ifndef __WXDEBUG__ // take everything into a try-except block in release build
+#if !defined(__WXDEBUG__) && !defined(__BORLANDC__) && !defined(__WATCOMC__) // take everything into a try-except block in release build
   try {
 #endif
 
@@ -627,7 +638,7 @@ int wxEntry(WXHINSTANCE hInstance,
   wxApp::CleanUp();
 
   return retValue;
-#ifndef __WXDEBUG__ // catch exceptions only in release build
+#if !defined(__WXDEBUG__) && !defined(__BORLANDC__) && !defined(__WATCOMC__) // catch exceptions only in release build
   }
   except ( EXCEPTION_EXECUTE_HANDLER ) {
     /*
@@ -732,24 +743,82 @@ bool wxApp::Initialized()
 
 /*
  * Get and process a message, returning FALSE if WM_QUIT
- * received.
+ * received (and also set the flag telling the app to exit the main loop)
  *
  */
 bool wxApp::DoMessage()
 {
-  if (!::GetMessage(&s_currentMsg, (HWND) NULL, 0, 0))
-  {
-    return FALSE;
-  }
+    BOOL rc = ::GetMessage(&s_currentMsg, (HWND) NULL, 0, 0);
+    if ( rc == 0 )
+    {
+        // got WM_QUIT
+        m_keepGoing = FALSE;
+        
+        return FALSE;
+    }
+    else if ( rc == -1 )
+    {
+        // should never happen, but let's test for it nevertheless
+        wxLogLastError("GetMessage");
+    }
+    else
+    {
+#if wxUSE_THREADS
+        wxASSERT_MSG( wxThread::IsMain(),
+                      "only the main thread can process Windows messages" );
 
-  // Process the message
-  if (!ProcessMessage((WXMSG *)&s_currentMsg))
-  {
-    ::TranslateMessage(&s_currentMsg);
-    wxApp::sm_lastMessageTime = s_currentMsg.time; /* MATTHEW: timeStamp impl. */
-    ::DispatchMessage(&s_currentMsg);
-  }
-  return TRUE;
+        static bool s_hadGuiLock = TRUE;
+        static wxMsgArray s_aSavedMessages;
+
+        // if a secondary thread owns is doing GUI calls, save all messages for
+        // later processing - we can't process them right now because it will
+        // lead to recursive library calls (and we're not reentrant)
+        if ( !wxGuiOwnedByMainThread() )
+        {
+            s_hadGuiLock = FALSE;
+
+            s_aSavedMessages.Add(s_currentMsg);
+
+            return TRUE;
+        }
+        else
+        {
+            // have we just regained the GUI lock? if so, post all of the saved
+            // messages
+            //
+            // FIXME of course, it's not _exactly_ the same as processing the
+            //       messages normally - expect some things to break...
+            if ( !s_hadGuiLock )
+            {
+                s_hadGuiLock = TRUE;
+
+                size_t count = s_aSavedMessages.Count();
+                for ( size_t n = 0; n < count; n++ )
+                {
+                    MSG& msg = s_aSavedMessages[n];
+
+                    if ( !ProcessMessage((WXMSG *)&msg) )
+                    {
+                        ::TranslateMessage(&msg);
+                        ::DispatchMessage(&msg);
+                    }
+                }
+
+                s_aSavedMessages.Empty();
+            }
+        }
+#endif // wxUSE_THREADS
+
+        // Process the message
+        if ( !ProcessMessage((WXMSG *)&s_currentMsg) )
+        {
+            ::TranslateMessage(&s_currentMsg);
+            wxApp::sm_lastMessageTime = s_currentMsg.time; /* MATTHEW: timeStamp impl. */
+            ::DispatchMessage(&s_currentMsg);
+        }
+    }
+
+    return TRUE;
 }
 
 /*
@@ -769,12 +838,19 @@ bool wxApp::DoMessage()
 int wxApp::MainLoop()
 {
   m_keepGoing = TRUE;
-  while (m_keepGoing)
+
+  while ( m_keepGoing )
   {
-    while (!::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) &&
-           ProcessIdle()) {}
-    if (!DoMessage())
-      m_keepGoing = FALSE;
+    #if wxUSE_THREADS
+        wxMutexGuiLeaveOrEnter();
+    #endif // wxUSE_THREADS
+
+    while ( !::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) &&
+            ProcessIdle() )
+    {
+    }
+
+    DoMessage();
   }
 
   return s_currentMsg.wParam;
@@ -802,8 +878,7 @@ bool wxApp::Pending()
 
 void wxApp::Dispatch()
 {
-    if (!DoMessage())
-      m_keepGoing = FALSE;
+    DoMessage();
 }
 
 /*
@@ -844,45 +919,47 @@ bool wxApp::ProcessMessage(WXMSG *Msg)
 
 void wxApp::OnIdle(wxIdleEvent& event)
 {
-  static bool inOnIdle = FALSE;
+    static bool s_inOnIdle = FALSE;
 
-  // Avoid recursion (via ProcessEvent default case)
-  if (inOnIdle)
-    return;
+    // Avoid recursion (via ProcessEvent default case)
+    if ( s_inOnIdle )
+        return;
 
-  inOnIdle = TRUE;
+    s_inOnIdle = TRUE;
 
-  // 'Garbage' collection of windows deleted with Close().
-  DeletePendingObjects();
+    // 'Garbage' collection of windows deleted with Close().
+    DeletePendingObjects();
 
-  // flush the logged messages if any
-  wxLog *pLog = wxLog::GetActiveTarget();
-  if ( pLog != NULL && pLog->HasPendingMessages() )
-    pLog->Flush();
+    // flush the logged messages if any
+    wxLog *pLog = wxLog::GetActiveTarget();
+    if ( pLog != NULL && pLog->HasPendingMessages() )
+        pLog->Flush();
 
-  // Send OnIdle events to all windows
-  bool needMore = SendIdleEvents();
-//  bool needMore = FALSE;
-
-  if (needMore)
-    event.RequestMore(TRUE);
+    // Send OnIdle events to all windows
+    if ( SendIdleEvents() )
+    {
+        // SendIdleEvents() returns TRUE if at least one window requested more
+        // idle events
+        event.RequestMore(TRUE);
+    }
 
-  inOnIdle = FALSE;
+    s_inOnIdle = FALSE;
 }
 
 // Send idle event to all top-level windows
 bool wxApp::SendIdleEvents()
 {
     bool needMore = FALSE;
-  wxNode* node = wxTopLevelWindows.First();
-  while (node)
-  {
-    wxWindow* win = (wxWindow*) node->Data();
-    if (SendIdleEvents(win))
+    wxNode* node = wxTopLevelWindows.First();
+    while (node)
+    {
+        wxWindow* win = (wxWindow*) node->Data();
+        if (SendIdleEvents(win))
             needMore = TRUE;
 
-    node = node->Next();
-  }
+        node = node->Next();
+    }
+
     return needMore;
 }
 
@@ -1017,7 +1094,7 @@ bool wxYield()
   // if we see a WM_QUIT. (?)
   while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) && msg.message != WM_QUIT)
   {
-    if (!wxTheApp->DoMessage())
+    if ( !wxTheApp->DoMessage() )
       break;
   }