#include "wx/dc.h"
#include "wx/dialog.h"
#include "wx/msgdlg.h"
+ #include "wx/intl.h"
+ #include "wx/dynarray.h"
#endif
#include "wx/msw/private.h"
#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
// 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__) && !defined(__SALFORDC__)
#include <ole2.h>
#endif
+
// #endif
#include <string.h>
#include <ctype.h>
-#if defined(__WIN95__) && !defined(__GNUWIN32__)
+#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__)
#include <commctrl.h>
#endif
/* Need to undef new if including crtdbg.h */
#ifdef new
- #undef new
+ #undef new
#endif
#include <crtdbg.h>
#if defined(__WXDEBUG__) && wxUSE_GLOBAL_MEMORY_OPERATORS && wxUSE_DEBUG_NEW_ALWAYS
- #define new new(__FILE__,__LINE__)
+ #define new new(__FILE__,__LINE__)
#endif
-
-#endif
+#endif // wxUSE_VC_CRTDBG
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;
char wxPanelClassName[] = "wxPanelClass";
char wxCanvasClassName[] = "wxCanvasClass";
-HICON wxSTD_FRAME_ICON = NULL;
-HICON wxSTD_MDICHILDFRAME_ICON = NULL;
-HICON wxSTD_MDIPARENTFRAME_ICON = NULL;
+HICON wxSTD_FRAME_ICON = (HICON) NULL;
+HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
+HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
-HICON wxDEFAULT_FRAME_ICON = NULL;
-HICON wxDEFAULT_MDICHILDFRAME_ICON = NULL;
-HICON wxDEFAULT_MDIPARENTFRAME_ICON = NULL;
+HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
+HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
+HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
-HBRUSH wxDisableButtonBrush = 0;
+HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
LRESULT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
long wxApp::sm_lastMessageTime = 0;
-#ifdef __WIN95__
- static HINSTANCE gs_hRichEdit = NULL;
+#if defined(__WIN95__) && !defined(__TWIN32__)
+#define wxUSE_RICHEDIT 1
+#else
+#define wxUSE_RICHEDIT 0
+#endif
+
+#if wxUSE_RICHEDIT
+ static HINSTANCE gs_hRichEdit = (HINSTANCE) NULL;
#endif
//// Initialize
#if defined(__WIN95__)
InitCommonControls();
+
+#if wxUSE_RICHEDIT
gs_hRichEdit = LoadLibrary("RICHED32.DLL");
- if (gs_hRichEdit == NULL)
+ if (gs_hRichEdit == (HINSTANCE) NULL)
{
wxMessageBox("Could not initialise Rich Edit DLL");
}
+#endif
+
#endif
int iMsg = 96;
-
+
// for OLE, enlarge message queue to be as large as possible
while (!SetMessageQueue(iMsg) && (iMsg -= 8));
/*
DWORD dwOleVer;
dwOleVer = CoBuildVersion();
-
+
// check the OLE library version
if (rmm != HIWORD(dwOleVer))
{
}
*/
-#ifndef __GNUWIN32__
+#if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__)
// we need to initialize OLE library
if ( FAILED(::OleInitialize(NULL)) )
wxFatalError(_("Cannot initialize OLE"));
// This is to foil optimizations in Visual C++ that
// throw out dummy.obj.
-#if (_MSC_VER >= 800) && !defined(WXMAKINGDLL)
+ // PLEASE DO NOT ALTER THIS.
+#if defined(_MSC_VER) && !defined(WXMAKINGDLL)
extern char wxDummyChar;
if (wxDummyChar) wxDummyChar++;
#endif
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = sizeof( DWORD ); // was 4
wndclass.hInstance = wxhInstance;
- wndclass.hIcon = NULL; // wxSTD_FRAME_ICON;
- wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hIcon = (HICON) NULL; // wxSTD_FRAME_ICON;
+ wndclass.hCursor = LoadCursor( (HINSTANCE) NULL, IDC_ARROW );
wndclass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1) ;
// wndclass.hbrBackground = GetStockObject( WHITE_BRUSH );
wndclass.lpszMenuName = NULL;
wndclass1.cbClsExtra = 0;
wndclass1.cbWndExtra = sizeof( DWORD ); // was 4
wndclass1.hInstance = wxhInstance;
- wndclass1.hIcon = NULL; // wxSTD_MDIPARENTFRAME_ICON;
- wndclass1.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass1.hIcon = (HICON) NULL; // wxSTD_MDIPARENTFRAME_ICON;
+ wndclass1.hCursor = LoadCursor( (HINSTANCE) NULL, IDC_ARROW );
// wndclass1.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1) ;
- wndclass1.hbrBackground = NULL;
+ wndclass1.hbrBackground = (HBRUSH) NULL;
wndclass1.lpszMenuName = NULL;
wndclass1.lpszClassName = wxMDIFrameClassName;
wndclass4.cbClsExtra = 0;
wndclass4.cbWndExtra = sizeof( DWORD ); // was 4
wndclass4.hInstance = wxhInstance;
- wndclass4.hIcon = NULL; // wxSTD_MDICHILDFRAME_ICON;
- wndclass4.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass4.hIcon = (HICON) NULL; // wxSTD_MDICHILDFRAME_ICON;
+ wndclass4.hCursor = LoadCursor( (HINSTANCE) NULL, IDC_ARROW );
// TODO: perhaps this should be NULL so that Windows doesn't
// paint the background itself (would OnEraseBackground duplicate
// this?)
wndclass2.cbClsExtra = 0;
wndclass2.cbWndExtra = sizeof( DWORD ); // was 4
wndclass2.hInstance = wxhInstance;
- wndclass2.hIcon = NULL;
- wndclass2.hCursor = NULL;
+ wndclass2.hIcon = (HICON) NULL;
+ wndclass2.hCursor = (HCURSOR) NULL;
// wndclass2.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1) ;
wndclass2.hbrBackground = (HBRUSH) GetStockObject( LTGRAY_BRUSH );
wndclass2.lpszMenuName = NULL;
wndclass3.cbClsExtra = 0;
wndclass3.cbWndExtra = sizeof( DWORD ); // was 4
wndclass3.hInstance = wxhInstance;
- wndclass3.hIcon = NULL;
- wndclass3.hCursor = NULL;
+ wndclass3.hIcon = (HICON) NULL;
+ wndclass3.hCursor = (HCURSOR) NULL;
// wndclass3.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ;
- wndclass3.hbrBackground = NULL;
+ wndclass3.hbrBackground = (HBRUSH) NULL;
wndclass3.lpszMenuName = NULL;
wndclass3.lpszClassName = wxCanvasClassName;
if (!RegisterClass( &wndclass3))
wxSetKeyboardHook(FALSE);
#ifdef __WIN95__
- if (gs_hRichEdit != NULL)
+
+#if wxUSE_RICHEDIT
+ if (gs_hRichEdit != (HINSTANCE) NULL)
FreeLibrary(gs_hRichEdit);
#endif
+#endif
+
#if wxUSE_PENWINDOWS
wxCleanUpPenWin();
#endif
if ( wxDisableButtonBrush )
::DeleteObject( wxDisableButtonBrush ) ;
-#ifndef __GNUWIN32__
+#if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__)
::OleUninitialize();
#endif
#if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL))
+// temporarily disable this warning
+#ifdef _MSC_VER
+ #pragma warning(disable: 4715) // not all control paths return a value
+#endif // Visual C++
+
//// Main wxWindows entry point
int wxEntry(WXHINSTANCE hInstance,
WXHINSTANCE WXUNUSED(hPrevInstance),
int nCmdShow,
bool enterLoop)
{
-#if !defined(__WXDEBUG__) && !defined(__BORLANDC__) // take everything into a try-except block in release build
- try {
+ // take everything into a try-except block in release build
+ // FIXME other compilers must support Win32 SEH (structured exception
+ // handling) too, just find the appropriate keyword in their docs!
+ // Please note that it's _not_ the same as C++ exceptions!
+#if !defined(__WXDEBUG__) && defined(_MSC_VER)
+ #define CATCH_PROGRAM_EXCEPTIONS
+
+ __try {
+#else
+ #undef CATCH_PROGRAM_EXCEPTIONS
#endif
wxhInstance = (HINSTANCE) hInstance;
wxApp::CleanUp();
return retValue;
-#if !defined(__WXDEBUG__) && !defined(__BORLANDC__) // catch exceptions only in release build
+
+#ifdef CATCH_PROGRAM_EXCEPTIONS
}
- except ( EXCEPTION_EXECUTE_HANDLER ) {
+ __except ( EXCEPTION_EXECUTE_HANDLER ) {
/*
if ( wxTheApp )
wxTheApp->OnFatalException();
*/
::ExitProcess(3); // the same exit code as abort()
+
+ // NOTREACHED
}
-#endif //debug
+#endif // CATCH_PROGRAM_EXCEPTIONS
}
+// restore warning state
+#ifdef _MSC_VER
+ #pragma warning(default: 4715) // not all control paths return a value
+#endif // Visual C++
+
#else /* _WINDLL */
//// Entry point for DLLs
/*
* 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;
- // 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;
+ 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" );
+
+ 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;
+
+ // leave out WM_COMMAND messages: too dangerous, sometimes
+ // the message will be processed twice
+ if ( !wxIsWaitingForThread() ||
+ s_currentMsg.message != WM_COMMAND )
+ {
+ 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;
}
/*
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;
void wxApp::Dispatch()
{
- if (!DoMessage())
- m_keepGoing = FALSE;
+ DoMessage();
}
/*
// Try translations first; find the youngest window with
// a translation table.
- for (hWnd = msg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
+ for (hWnd = msg->hwnd; hWnd != (HWND) NULL; hWnd = ::GetParent(hWnd))
{
wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd);
if (wnd)
}
// Anyone for a non-translation message? Try youngest descendants first.
- for (hWnd = msg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
+ for (hWnd = msg->hwnd; hWnd != (HWND) NULL; hWnd = ::GetParent(hWnd))
{
wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd);
if (wnd)
void wxApp::OnIdle(wxIdleEvent& event)
{
- static bool inOnIdle = FALSE;
-
- // Avoid recursion (via ProcessEvent default case)
- if (inOnIdle)
- return;
+ static bool s_inOnIdle = FALSE;
- inOnIdle = TRUE;
+ // Avoid recursion (via ProcessEvent default case)
+ if ( s_inOnIdle )
+ return;
- // 'Garbage' collection of windows deleted with Close().
- DeletePendingObjects();
+ s_inOnIdle = TRUE;
- // flush the logged messages if any
- wxLog *pLog = wxLog::GetActiveTarget();
- if ( pLog != NULL && pLog->HasPendingMessages() )
- pLog->Flush();
+ // 'Garbage' collection of windows deleted with Close().
+ DeletePendingObjects();
- // Send OnIdle events to all windows
- bool needMore = SendIdleEvents();
-// bool needMore = FALSE;
+ // flush the logged messages if any
+ wxLog *pLog = wxLog::GetActiveTarget();
+ if ( pLog != NULL && pLog->HasPendingMessages() )
+ pLog->Flush();
- 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;
}
}
}
-void wxApp::OnEndSession(wxCloseEvent& event)
+void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
{
if (GetTopWindow())
GetTopWindow()->Close(TRUE);
// 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;
}
// For some reason, with MSVC++ 1.5, WinMain isn't linked in properly
// if in a separate file. So include it here to ensure it's linked.
-#if (defined(_MSC_VER) && !defined(__WIN32__)) || defined(__GNUWIN32__)
+#if (defined(_MSC_VER) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__TWIN32__))
#include "main.cpp"
#endif