#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
+// To UG: there's no point in putting this #if here
+// 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
+#if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__)
+ #include <ole2.h>
+#endif
+
#include <string.h>
#include <ctype.h>
-#if defined(__WIN95__) && !defined(__GNUWIN32__)
+#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__)
#include <commctrl.h>
#endif
-// use debug CRT functions for memory leak detections in VC++ if we're not
-// using wxWindows own methods
-#if defined(__WXDEBUG__) && defined(_MSC_VER) && !wxUSE_GLOBAL_MEMORY_OPERATORS && !defined(__NO_VC_CRTDBG__)
- #define wxUSE_VC_CRTDBG
-#else
- #undef wxUSE_VC_CRTDBG
-#endif
-
-#ifdef wxUSE_VC_CRTDBG
- // VC++ uses this macro as debug/release mode indicator
- #ifndef _DEBUG
- #define _DEBUG
- #endif
-
- #include <crtdbg.h>
-#endif
+#include "wx/msw/msvcrt.h"
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
bool wxApp::Initialize()
{
- wxBuffer = new char[1500];
+ // Some people may wish to use this, but
+ // probably it shouldn't be here by default.
+#ifdef __WXDEBUG__
+// wxRedirectIOToConsole();
+#endif
-#ifdef wxUSE_VC_CRTDBG
- // do check for memory leaks on program exit
- // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free
- // deallocated memory which may be used to simulate low-memory condition)
- _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
-#endif // debug build under MS VC++
+ wxBuffer = new char[1500];
wxClassInfo::InitializeClasses();
#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))
{
return FALSE;
}
*/
-
+
+#if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__)
// we need to initialize OLE library
if ( FAILED(::OleInitialize(NULL)) )
wxFatalError(_("Cannot initialize OLE"));
+#endif
-#if CTL3D
+#if wxUSE_CTL3D
if (!Ctl3dRegister(wxhInstance))
wxFatalError("Cannot register CTL3D");
wxWinHandleList = new wxList(wxKEY_INTEGER);
- // This is to foil optimizations in Visual C++ that
- // throw out dummy.obj.
-#if (_MSC_VER >= 800) && !defined(WXMAKINGDLL)
+ // This is to foil optimizations in Visual C++ that throw out dummy.obj.
+ // PLEASE DO NOT ALTER THIS.
+#if defined(__VISUALC__) && !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))
void wxApp::CleanUp()
{
//// COMMON CLEANUP
+
+ // flush the logged messages if any
+ wxLog *pLog = wxLog::GetActiveTarget();
+ if ( pLog != NULL && pLog->HasPendingMessages() )
+ pLog->Flush();
+
+ // One last chance for pending objects to be cleaned up
+ wxTheApp->DeletePendingObjects();
+
wxModule::CleanUpModules();
#if wxUSE_WX_RESOURCES
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 ) ;
+#if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__)
::OleUninitialize();
+#endif
-#if CTL3D
+#if wxUSE_CTL3D
Ctl3dUnregister(wxhInstance);
#endif
#if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL))
+// temporarily disable this warning
+#ifdef __VISUALC__
+ #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)
{
-#ifndef __WXDEBUG__ // take everything into a try-except block in release build
- try {
+ // do check for memory leaks on program exit
+ // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free
+ // deallocated memory which may be used to simulate low-memory condition)
+ wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
+
+ // 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(__VISUALC__)
+ #define CATCH_PROGRAM_EXCEPTIONS
+
+ __try {
+#else
+ #undef CATCH_PROGRAM_EXCEPTIONS
#endif
wxhInstance = (HINSTANCE) hInstance;
{
retValue = wxTheApp->OnRun();
}
+ else
+ // We want to initialize, but not run or exit immediately.
+ return 1;
}
//else: app initialization failed, so we skipped OnRun()
wxTheApp->OnExit();
- // flush the logged messages if any
- wxLog *pLog = wxLog::GetActiveTarget();
- if ( pLog != NULL && pLog->HasPendingMessages() )
- pLog->Flush();
-
-
wxApp::CleanUp();
return retValue;
-#ifndef __WXDEBUG__ // 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 __VISUALC__
+ #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;
}
if (event.MoreRequested())
needMore = TRUE;
- wxNode* node = win->GetChildren()->First();
+ wxNode* node = win->GetChildren().First();
while (node)
{
wxWindow* win = (wxWindow*) node->Data();
}
}
-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(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__TWIN32__))
#include "main.cpp"
#endif