]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/app.cpp
Default wxDateTime objects are now 'invalid',
[wxWidgets.git] / src / os2 / app.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
3// Purpose: wxApp
4// Author: David Webster
5// Modified by:
6// Created: 10/13/99
7// RCS-ID: $Id$
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifndef WX_PRECOMP
16 #include "wx/frame.h"
17 #include "wx/app.h"
18 #include "wx/utils.h"
19 #include "wx/gdicmn.h"
20 #include "wx/pen.h"
21 #include "wx/brush.h"
22 #include "wx/cursor.h"
23 #include "wx/icon.h"
24 #include "wx/palette.h"
25 #include "wx/dc.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/intl.h"
29 #include "wx/dynarray.h"
30 #include "wx/wxchar.h"
31 #include "wx/icon.h"
32 #include "wx/timer.h"
33#endif
34
35#include "wx/log.h"
36#include "wx/module.h"
37
38#include "wx/os2/private.h"
39
40#if defined(__VISAGECPP__) && __IBMCPP__ < 400
41#include <machine\endian.h>
42#include <ioctl.h>
43#include <select.h>
44#include <unistd.h>
45#else
46#include <sys\ioctl.h>
47#include <sys\select.h>
48#ifndef __EMX__
49#define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
50int _System bsdselect(int,
51 struct fd_set *,
52 struct fd_set *,
53 struct fd_set *,
54 struct timeval *);
55#endif
56#endif
57
58#if wxUSE_THREADS
59 #include "wx/thread.h"
60
61 // define the array of QMSG strutures
62 WX_DECLARE_OBJARRAY(QMSG, wxMsgArray);
63
64 #include "wx/arrimpl.cpp"
65
66 WX_DEFINE_OBJARRAY(wxMsgArray);
67#endif // wxUSE_THREADS
68
69#if wxUSE_WX_RESOURCES
70 #include "wx/resource.h"
71#endif
72
73#if wxUSE_TOOLTIPS
74 #include "wx/tooltip.h"
75#endif // wxUSE_TOOLTIPS
76
77#include <string.h>
78#include <ctype.h>
79
80// ---------------------------------------------------------------------------
81// global variables
82// ---------------------------------------------------------------------------
83
84extern wxChar* wxBuffer;
85extern wxList* wxWinHandleList;
86extern wxList WXDLLEXPORT wxPendingDelete;
87extern wxCursor* g_globalCursor;
88
89HAB vHabmain = NULLHANDLE;
90QMSG svCurrentMsg;
91wxApp* wxTheApp = NULL;
92
93// NB: all "NoRedraw" classes must have the same names as the "normal" classes
94// with NR suffix - wxWindow::OS2Create() supposes this
95wxChar wxFrameClassName[] = wxT("wxFrameClass");
96wxChar wxFrameClassNameNoRedraw[] = wxT("wxFrameClassNR");
97wxChar wxMDIFrameClassName[] = wxT("wxMDIFrameClass");
98wxChar wxMDIFrameClassNameNoRedraw[] = wxT("wxMDIFrameClassNR");
99wxChar wxMDIChildFrameClassName[] = wxT("wxMDIChildFrameClass");
100wxChar wxMDIChildFrameClassNameNoRedraw[] = wxT("wxMDIChildFrameClassNR");
101wxChar wxPanelClassName[] = wxT("wxPanelClass");
102wxChar wxCanvasClassName[] = wxT("wxCanvasClass");
103
104HICON wxSTD_FRAME_ICON = (HICON) NULL;
105HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
106HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
107
108HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
109HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
110HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
111
112HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
113
114MRESULT EXPENTRY wxWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
115MRESULT EXPENTRY wxFrameWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
116
117// ===========================================================================
118// implementation
119// ===========================================================================
120
121// ---------------------------------------------------------------------------
122// helper struct and functions for socket handling
123// ---------------------------------------------------------------------------
124
125struct GsocketCallbackInfo{
126 void (*proc)(void *);
127 int type;
128 int handle;
129 void* gsock;
130};
131
132// These defines and wrapper functions are used here and in gsockpm.c
133#define wxSockReadMask 0x01
134#define wxSockWriteMask 0x02
135
136extern "C"
137int wxAppAddSocketHandler(int handle, int mask,
138 void (*callback)(void*), void * gsock)
139{
140 return wxTheApp->AddSocketHandler(handle, mask, callback, gsock);
141}
142
143extern "C"
144void wxAppRemoveSocketHandler(int handle)
145{
146 wxTheApp->RemoveSocketHandler(handle);
147}
148
149void wxApp::HandleSockets()
150{
151 bool pendingEvent = false;
152
153 // Check whether it's time for Gsocket operation
154 if (m_maxSocketHandles > 0 && m_maxSocketNr > 0)
155 {
156 fd_set readfds = m_readfds;
157 fd_set writefds = m_writefds;
158 struct timeval timeout;
159 int i;
160 struct GsocketCallbackInfo
161 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
162 int r = 0;
163 timeout.tv_sec = 0;
164 timeout.tv_usec = 0;
165 if ( select(m_maxSocketNr, &readfds, &writefds, 0, &timeout) > 0)
166 {
167 for (i = m_lastUsedHandle + 1; i != m_lastUsedHandle; i++)
168 {
169 if (i == m_maxSocketNr)
170 i = 0;
171 if (FD_ISSET(i, &readfds))
172 {
173 int r;
174 for (r = 0; r < m_maxSocketHandles; r++){
175 if(CallbackInfo[r].handle == i &&
176 CallbackInfo[r].type == wxSockReadMask)
177 break;
178 }
179 if (r < m_maxSocketHandles)
180 {
181 CallbackInfo[r].proc(CallbackInfo[r].gsock);
182 pendingEvent = true;
183 wxYield();
184 }
185 }
186 if (FD_ISSET(i, &writefds))
187 {
188 int r;
189 for (r = 0; r < m_maxSocketHandles; r++)
190 if(CallbackInfo[r].handle == i &&
191 CallbackInfo[r].type == wxSockWriteMask)
192 break;
193 if (r < m_maxSocketHandles)
194 {
195 CallbackInfo[r].proc(CallbackInfo[r].gsock);
196 pendingEvent = true;
197 wxYield();
198 }
199 }
200 }
201 m_lastUsedHandle = i;
202 }
203 if (pendingEvent)
204 wxYield();
205 }
206}
207// ---------------------------------------------------------------------------
208// wxApp
209// ---------------------------------------------------------------------------
210
211 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
212
213 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
214 EVT_IDLE(wxApp::OnIdle)
215 EVT_END_SESSION(wxApp::OnEndSession)
216 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
217 END_EVENT_TABLE()
218
219//
220// Initialize
221//
222bool wxApp::Initialize(
223 HAB vHab
224)
225{
226#if defined(wxUSE_CONSOLEDEBUG)
227 #if wxUSE_CONSOLEDEBUG
228/***********************************************/
229/* Code for using stdout debug */
230/* To use it you mast link app as "Window" - EK*/
231/***********************************************/
232 {
233 PPIB pib;
234 PTIB tib;
235
236 printf("In console\n");
237
238 DosGetInfoBlocks(&tib, &pib);
239/* Try morphing into a PM application. */
240// if(pib->pib_ultype == 2) /* VIO */
241 pib->pib_ultype = 3;
242 }
243/**********************************************/
244/**********************************************/
245 #endif //wxUSE_CONSOLEDEBUG
246#endif
247
248 //
249 // OS2 has to have an anchorblock
250 //
251 vHab = WinInitialize(0);
252
253 if (!vHab)
254 return FALSE;
255 else
256 vHabmain = vHab;
257
258 // Some people may wish to use this, but
259 // probably it shouldn't be here by default.
260#ifdef __WXDEBUG__
261 // wxRedirectIOToConsole();
262#endif
263
264 wxBuffer = new wxChar[1500]; // FIXME; why?
265
266 wxClassInfo::InitializeClasses();
267
268#if wxUSE_THREADS
269 wxPendingEventsLocker = new wxCriticalSection;
270#endif
271
272 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
273 wxTheColourDatabase->Initialize();
274
275 wxInitializeStockLists();
276 wxInitializeStockObjects();
277
278#if wxUSE_WX_RESOURCES
279 wxInitializeResourceSystem();
280#endif
281
282 wxBitmap::InitStandardHandlers();
283
284 RegisterWindowClasses(vHab);
285 wxWinHandleList = new wxList(wxKEY_INTEGER);
286
287 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
288 // PLEASE DO NOT ALTER THIS.
289#if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
290 extern char wxDummyChar;
291 if (wxDummyChar) wxDummyChar++;
292#endif
293
294 // wxSetKeyboardHook(TRUE);
295
296 wxModule::RegisterModules();
297 if (!wxModule::InitializeModules())
298 return FALSE;
299 return TRUE;
300} // end of wxApp::Initialize
301
302const char* CANTREGISTERCLASS = " Can't register Class ";
303// ---------------------------------------------------------------------------
304// RegisterWindowClasses
305// ---------------------------------------------------------------------------
306
307bool wxApp::RegisterWindowClasses(
308 HAB vHab
309)
310{
311 APIRET rc;
312 ERRORID vError = 0L;
313 wxString sError;
314
315 if (!::WinRegisterClass( vHab
316 ,wxFrameClassName
317 ,wxFrameWndProc
318 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT | CS_CLIPCHILDREN
319 ,sizeof(ULONG)
320 ))
321 {
322 vError = ::WinGetLastError(vHab);
323 sError = wxPMErrorToStr(vError);
324 wxLogLastError(sError);
325 return FALSE;
326 }
327
328 if (!::WinRegisterClass( vHab
329 ,wxFrameClassNameNoRedraw
330 ,wxWndProc
331 ,0
332 ,sizeof(ULONG)
333 ))
334 {
335 vError = ::WinGetLastError(vHab);
336 sError = wxPMErrorToStr(vError);
337 wxLogLastError(sError);
338 return FALSE;
339 }
340
341 if (!::WinRegisterClass( vHab
342 ,wxMDIFrameClassName
343 ,wxWndProc
344 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
345 ,sizeof(ULONG)
346 ))
347 {
348 vError = ::WinGetLastError(vHab);
349 sError = wxPMErrorToStr(vError);
350 wxLogLastError(sError);
351 return FALSE;
352 }
353
354 if (!::WinRegisterClass( vHab
355 ,wxMDIFrameClassNameNoRedraw
356 ,wxWndProc
357 ,0
358 ,sizeof(ULONG)
359 ))
360 {
361 vError = ::WinGetLastError(vHab);
362 sError = wxPMErrorToStr(vError);
363 wxLogLastError(sError);
364 return FALSE;
365 }
366
367 if (!::WinRegisterClass( vHab
368 ,wxMDIChildFrameClassName
369 ,wxWndProc
370 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
371 ,sizeof(ULONG)
372 ))
373 {
374 vError = ::WinGetLastError(vHab);
375 sError = wxPMErrorToStr(vError);
376 wxLogLastError(sError);
377 return FALSE;
378 }
379
380 if (!::WinRegisterClass( vHab
381 ,wxMDIChildFrameClassNameNoRedraw
382 ,wxWndProc
383 ,CS_HITTEST
384 ,sizeof(ULONG)
385 ))
386 {
387 vError = ::WinGetLastError(vHab);
388 sError = wxPMErrorToStr(vError);
389 wxLogLastError(sError);
390 return FALSE;
391 }
392
393 if (!::WinRegisterClass( vHab
394 ,wxPanelClassName
395 ,wxWndProc
396 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
397 ,sizeof(ULONG)
398 ))
399 {
400 vError = ::WinGetLastError(vHab);
401 sError = wxPMErrorToStr(vError);
402 wxLogLastError(sError);
403 return FALSE;
404 }
405
406 if (!::WinRegisterClass( vHab
407 ,wxCanvasClassName
408 ,wxWndProc
409 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT | CS_CLIPCHILDREN
410 ,sizeof(ULONG)
411 ))
412 {
413 vError = ::WinGetLastError(vHab);
414 sError = wxPMErrorToStr(vError);
415 wxLogLastError(sError);
416 return FALSE;
417 }
418 return TRUE;
419} // end of wxApp::RegisterWindowClasses
420
421//
422// Cleans up any wxWindows internal structures left lying around
423//
424void wxApp::CleanUp()
425{
426 //
427 // COMMON CLEANUP
428 //
429
430#if wxUSE_LOG
431
432 //
433 // Flush the logged messages if any and install a 'safer' log target: the
434 // default one (wxLogGui) can't be used after the resources are freed just
435 // below and the user suppliedo ne might be even more unsafe (using any
436 // wxWindows GUI function is unsafe starting from now)
437 //
438 wxLog::DontCreateOnDemand();
439
440 //
441 // This will flush the old messages if any
442 //
443 delete wxLog::SetActiveTarget(new wxLogStderr);
444#endif // wxUSE_LOG
445
446 //
447 // One last chance for pending objects to be cleaned up
448 //
449 wxTheApp->DeletePendingObjects();
450
451 wxModule::CleanUpModules();
452
453#if wxUSE_WX_RESOURCES
454 wxCleanUpResourceSystem();
455#endif
456
457 wxDeleteStockObjects();
458
459 //
460 // Destroy all GDI lists, etc.
461 //
462 wxDeleteStockLists();
463
464 delete wxTheColourDatabase;
465 wxTheColourDatabase = NULL;
466
467 wxBitmap::CleanUpHandlers();
468
469 delete[] wxBuffer;
470 wxBuffer = NULL;
471
472 //
473 // PM-SPECIFIC CLEANUP
474 //
475
476 // wxSetKeyboardHook(FALSE);
477
478 if (wxSTD_FRAME_ICON)
479 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
480 if (wxSTD_MDICHILDFRAME_ICON)
481 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
482 if (wxSTD_MDIPARENTFRAME_ICON)
483 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
484
485 if (wxDEFAULT_FRAME_ICON)
486 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
487 if (wxDEFAULT_MDICHILDFRAME_ICON)
488 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
489 if (wxDEFAULT_MDIPARENTFRAME_ICON)
490 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
491
492 if ( wxDisableButtonBrush )
493 {
494// TODO: ::DeleteObject( wxDisableButtonBrush );
495 }
496
497 if (wxWinHandleList)
498 delete wxWinHandleList;
499
500 delete wxPendingEvents;
501#if wxUSE_THREADS
502 delete wxPendingEventsLocker;
503 // If we don't do the following, we get an apparent memory leak.
504 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
505#endif
506
507 wxClassInfo::CleanUpClasses();
508
509 // Delete Message queue
510 if (wxTheApp->m_hMq)
511 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
512
513 delete wxTheApp;
514 wxTheApp = NULL;
515
516#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
517 // At this point we want to check if there are any memory
518 // blocks that aren't part of the wxDebugContext itself,
519 // as a special case. Then when dumping we need to ignore
520 // wxDebugContext, too.
521 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
522 {
523 wxLogDebug(wxT("There were memory leaks."));
524 wxDebugContext::Dump();
525 wxDebugContext::PrintStatistics();
526 }
527 // wxDebugContext::SetStream(NULL, NULL);
528#endif
529
530#if wxUSE_LOG
531 // do it as the very last thing because everything else can log messages
532 delete wxLog::SetActiveTarget(NULL);
533#endif // wxUSE_LOG
534} // end of wxApp::CleanUp
535
536//----------------------------------------------------------------------
537// Main wxWindows entry point
538//----------------------------------------------------------------------
539int wxEntry(
540 int argc
541, char* argv[]
542)
543{
544 HAB vHab = 0;
545
546 if (!wxApp::Initialize(vHab))
547 return 0;
548
549 //
550 // create the application object or ensure that one already exists
551 //
552 if (!wxTheApp)
553 {
554 // The app may have declared a global application object, but we recommend
555 // the IMPLEMENT_APP macro is used instead, which sets an initializer
556 // function for delayed, dynamic app object construction.
557 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
558 wxT("No initializer - use IMPLEMENT_APP macro.") );
559 wxTheApp = (*wxApp::GetInitializerFunction()) ();
560 }
561 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
562 wxTheApp->argc = argc;
563
564#if wxUSE_UNICODE
565 wxTheApp->argv = new wxChar*[argc+1];
566
567 int nArgc = 0;
568
569 while (nArgc < argc)
570 {
571 wxTheApp->argv[nArgc] = wxStrdup(wxConvLibc.cMB2WX(argv[nArgc]));
572 nArgc++;
573 }
574 wxTheApp->argv[nArgc] = (wxChar *)NULL;
575#else
576 wxTheApp->argv = argv;
577#endif
578
579 wxString sName(wxFileNameFromPath(argv[0]));
580
581 wxStripExtension(sName);
582 wxTheApp->SetAppName(sName);
583
584 int nRetValue = 0;
585
586 if (!wxTheApp->OnInitGui())
587 nRetValue = -1;
588
589 if (nRetValue == 0)
590 {
591 if (wxTheApp->OnInit())
592 {
593 nRetValue = wxTheApp->OnRun();
594 }
595 // Normal exit
596 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
597 if (pTopWindow)
598 {
599 // Forcibly delete the window.
600 if (pTopWindow->IsKindOf(CLASSINFO(wxFrame)) ||
601 pTopWindow->IsKindOf(CLASSINFO(wxDialog)) )
602 {
603 pTopWindow->Close(TRUE);
604 wxTheApp->DeletePendingObjects();
605 }
606 else
607 {
608 delete pTopWindow;
609 wxTheApp->SetTopWindow(NULL);
610 }
611 }
612 }
613 else // app initialization failed
614 {
615 wxLogLastError(" Gui initialization failed, exitting");
616 }
617#if wxUSE_CONSOLEDEBUG
618 printf("wxTheApp->OnExit ");
619 fflush(stdout);
620#endif
621 wxTheApp->OnExit();
622#if wxUSE_CONSOLEDEBUG
623 printf("wxApp::CleanUp ");
624 fflush(stdout);
625#endif
626 wxApp::CleanUp();
627#if wxUSE_CONSOLEDEBUG
628 printf("return %i ", nRetValue);
629 fflush(stdout);
630#endif
631 return(nRetValue);
632} // end of wxEntry
633
634bool wxApp::OnInitGui()
635{
636 ERRORID vError;
637 wxString sError;
638
639 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
640 if (!m_hMq)
641 {
642 vError = ::WinGetLastError(vHabmain);
643 sError = wxPMErrorToStr(vError);
644 wxLogDebug(sError);
645 return FALSE;
646 }
647 return TRUE;
648} // end of wxApp::OnInitGui
649
650//
651// Static member initialization
652//
653wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
654
655wxApp::wxApp()
656{
657 m_topWindow = NULL;
658 wxTheApp = this;
659 m_wantDebugOutput = TRUE;
660
661 argc = 0;
662 argv = NULL;
663 m_nPrintMode = wxPRINT_WINDOWS;
664 m_exitOnFrameDelete = TRUE;
665 m_bAuto3D = TRUE;
666 m_hMq = 0;
667 m_maxSocketHandles = 0;
668 m_maxSocketNr = 0;
669 m_sockCallbackInfo = 0;
670} // end of wxApp::wxApp
671
672wxApp::~wxApp()
673{
674 //
675 // Delete command-line args
676 //
677#if wxUSE_UNICODE
678 int i;
679
680 for (i = 0; i < argc; i++)
681 {
682 delete[] argv[i];
683 }
684 delete[] argv;
685#endif
686} // end of wxApp::~wxApp
687
688bool wxApp::Initialized()
689{
690 if (GetTopWindow())
691 return TRUE;
692 else
693 return FALSE;
694} // end of wxApp::Initialized
695
696//
697// Get and process a message, returning FALSE if WM_QUIT
698// received (and also set the flag telling the app to exit the main loop)
699//
700
701bool wxApp::DoMessage()
702{
703 BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
704
705 if (bRc == 0)
706 {
707 // got WM_QUIT
708 m_bKeepGoing = FALSE;
709 return FALSE;
710 }
711 else if (bRc == -1)
712 {
713 // should never happen, but let's test for it nevertheless
714 wxLogLastError("GetMessage");
715 }
716 else
717 {
718#if wxUSE_THREADS
719 wxASSERT_MSG( wxThread::IsMain()
720 ,wxT("only the main thread can process Windows messages")
721 );
722
723 static bool sbHadGuiLock = TRUE;
724 static wxMsgArray svSavedMessages;
725
726 //
727 // If a secondary thread owns is doing GUI calls, save all messages for
728 // later processing - we can't process them right now because it will
729 // lead to recursive library calls (and we're not reentrant)
730 //
731 if (!wxGuiOwnedByMainThread())
732 {
733 sbHadGuiLock = FALSE;
734
735 //
736 // Leave out WM_COMMAND messages: too dangerous, sometimes
737 // the message will be processed twice
738 //
739 if ( !wxIsWaitingForThread() ||
740 svCurrentMsg.msg != WM_COMMAND )
741 {
742 svSavedMessages.Add(svCurrentMsg);
743 }
744 return TRUE;
745 }
746 else
747 {
748 //
749 // Have we just regained the GUI lock? if so, post all of the saved
750 // messages
751 //
752 if (!sbHadGuiLock )
753 {
754 sbHadGuiLock = TRUE;
755
756 size_t nCount = svSavedMessages.Count();
757
758 for (size_t n = 0; n < nCount; n++)
759 {
760 QMSG vMsg = svSavedMessages[n];
761
762 if ( !ProcessMessage((WXMSG *)&vMsg) )
763 {
764 ::WinDispatchMsg(vHabmain, &vMsg);
765 }
766 }
767 svSavedMessages.Empty();
768 }
769 }
770#endif // wxUSE_THREADS
771
772 // Process the message
773 if (!ProcessMessage((WXMSG *)&svCurrentMsg))
774 {
775 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
776 }
777 }
778 return TRUE;
779} // end of wxApp::DoMessage
780
781//////////////////////////////////////////////////////////////////////////////
782//
783// Keep trying to process messages until WM_QUIT
784// received.
785//
786// If there are messages to be processed, they will all be
787// processed and OnIdle will not be called.
788// When there are no more messages, OnIdle is called.
789// If OnIdle requests more time,
790// it will be repeatedly called so long as there are no pending messages.
791// A 'feature' of this is that once OnIdle has decided that no more processing
792// is required, then it won't get processing time until further messages
793// are processed (it'll sit in DoMessage).
794//
795//////////////////////////////////////////////////////////////////////////////
796int wxApp::MainLoop()
797{
798 m_bKeepGoing = TRUE;
799
800 while (m_bKeepGoing)
801 {
802#if wxUSE_THREADS
803 wxMutexGuiLeaveOrEnter();
804#endif // wxUSE_THREADS
805 while (!Pending() && ProcessIdle())
806 {
807 HandleSockets();
808 wxUsleep(10000);
809 }
810 HandleSockets();
811 if (Pending())
812 DoMessage();
813 else
814 wxUsleep(10000);
815
816 }
817 return (int)svCurrentMsg.mp1;
818} // end of wxApp::MainLoop
819
820//
821// Returns TRUE if more time is needed.
822//
823bool wxApp::ProcessIdle()
824{
825 wxIdleEvent vEvent;
826
827 vEvent.SetEventObject(this);
828 ProcessEvent(vEvent);
829 return vEvent.MoreRequested();
830} // end of wxApp::ProcessIdle
831
832void wxApp::ExitMainLoop()
833{
834 m_bKeepGoing = FALSE;
835}
836
837bool wxApp::Pending()
838{
839 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
840}
841
842void wxApp::Dispatch()
843{
844 DoMessage();
845}
846
847//////////////////////////////////////////////////////////////////////////////
848//
849// Give all windows a chance to preprocess
850// the message. Some may have accelerator tables, or have
851// MDI complications.
852//
853//////////////////////////////////////////////////////////////////////////////
854bool wxApp::ProcessMessage(
855 WXMSG* pWxmsg
856)
857{
858 QMSG* pMsg = (PQMSG)pWxmsg;
859 HWND hWnd = pMsg->hwnd;
860 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
861 wxWindow* pWnd;
862
863#if wxUSE_TOOLTIPS
864 //
865 // We must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to
866 // popup the tooltip bubbles
867 //
868 if (pWndThis && (pMsg->msg == WM_MOUSEMOVE))
869 {
870 wxToolTip* pToolTip = pWndThis->GetToolTip();
871 if (pToolTip)
872 {
873 pToolTip->RelayEvent(pWxmsg);
874 }
875 }
876#endif // wxUSE_TOOLTIPS
877
878 //
879 // We must relay Timer events to wxTimer's processing function
880 //
881 if (pMsg->msg == WM_TIMER)
882 wxTimerProc(NULL, 0, (int)pMsg->mp1, 0);
883
884 //
885 // For some composite controls (like a combobox), wndThis might be NULL
886 // because the subcontrol is not a wxWindow, but only the control itself
887 // is - try to catch this case
888 //
889 while (hWnd && !pWndThis)
890 {
891 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
892 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
893 }
894
895 //
896 // Try translations first; find the youngest window with
897 // a translation table. OS/2 has case sensative accels, so
898 // this block, coded by BK, removes that and helps make them
899 // case insensative.
900 //
901 if(pMsg->msg == WM_CHAR)
902 {
903 PBYTE pChmsg = (PBYTE)&(pMsg->msg);
904 USHORT uSch = CHARMSG(pChmsg)->chr;
905 bool bRc;
906
907 //
908 // Do not process keyup events
909 //
910 if(!(CHARMSG(pChmsg)->fs & KC_KEYUP))
911 {
912 if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0)
913 CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
914
915
916 for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
917 {
918 if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
919 break;
920 }
921
922 if(!bRc) // untranslated, should restore original value
923 CHARMSG(pChmsg)->chr = uSch;
924 }
925 }
926 //
927 // Anyone for a non-translation message? Try youngest descendants first.
928 //
929// for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
930// {
931// if (pWnd->OS2ProcessMessage(pWxmsg))
932// return TRUE;
933// }
934 return FALSE;
935} // end of wxApp::ProcessMessage
936
937void wxApp::OnIdle(
938 wxIdleEvent& rEvent
939)
940{
941 static bool sbInOnIdle = FALSE;
942
943 //
944 // Avoid recursion (via ProcessEvent default case)
945 //
946 if (sbInOnIdle)
947 return;
948
949 sbInOnIdle = TRUE;
950
951 //
952 // If there are pending events, we must process them: pending events
953 // are either events to the threads other than main or events posted
954 // with wxPostEvent() functions
955 //
956 ProcessPendingEvents();
957
958 //
959 // 'Garbage' collection of windows deleted with Close().
960 //
961 DeletePendingObjects();
962
963#if wxUSE_LOG
964 //
965 // Flush the logged messages if any
966 //
967 wxLog::FlushActive();
968#endif // wxUSE_LOG
969
970 //
971 // Send OnIdle events to all windows
972 //
973 if (SendIdleEvents())
974 {
975 //
976 // SendIdleEvents() returns TRUE if at least one window requested more
977 // idle events
978 //
979 rEvent.RequestMore(TRUE);
980 }
981 sbInOnIdle = FALSE;
982} // end of wxApp::OnIdle
983
984// Send idle event to all top-level windows
985bool wxApp::SendIdleEvents()
986{
987 bool bNeedMore = FALSE;
988 wxWindowList::Node* pNode = wxTopLevelWindows.GetFirst();
989
990 while (pNode)
991 {
992 wxWindow* pWin = pNode->GetData();
993
994 if (SendIdleEvents(pWin))
995 bNeedMore = TRUE;
996 pNode = pNode->GetNext();
997 }
998 return bNeedMore;
999} // end of wxApp::SendIdleEvents
1000
1001//
1002// Send idle event to window and all subwindows
1003//
1004bool wxApp::SendIdleEvents(
1005 wxWindow* pWin
1006)
1007{
1008 bool bNeedMore = FALSE;
1009 wxIdleEvent vEvent;
1010
1011 vEvent.SetEventObject(pWin);
1012 pWin->GetEventHandler()->ProcessEvent(vEvent);
1013
1014 if (vEvent.MoreRequested())
1015 bNeedMore = TRUE;
1016
1017 wxNode* pNode = pWin->GetChildren().First();
1018
1019 while (pNode)
1020 {
1021 wxWindow* pWin = (wxWindow*) pNode->Data();
1022
1023 if (SendIdleEvents(pWin))
1024 bNeedMore = TRUE;
1025 pNode = pNode->Next();
1026 }
1027 return bNeedMore;
1028} // end of wxApp::SendIdleEvents
1029
1030void wxApp::DeletePendingObjects()
1031{
1032 wxNode* pNode = wxPendingDelete.First();
1033
1034 while (pNode)
1035 {
1036 wxObject* pObj = (wxObject *)pNode->Data();
1037
1038 delete pObj;
1039
1040 if (wxPendingDelete.Member(pObj))
1041 delete pNode;
1042
1043 //
1044 // Deleting one object may have deleted other pending
1045 // objects, so start from beginning of list again.
1046 //
1047 pNode = wxPendingDelete.First();
1048 }
1049} // end of wxApp::DeletePendingObjects
1050
1051void wxApp::OnEndSession(
1052 wxCloseEvent& WXUNUSED(rEvent))
1053{
1054 if (GetTopWindow())
1055 GetTopWindow()->Close(TRUE);
1056} // end of wxApp::OnEndSession
1057
1058//
1059// Default behaviour: close the application with prompts. The
1060// user can veto the close, and therefore the end session.
1061//
1062void wxApp::OnQueryEndSession(
1063 wxCloseEvent& rEvent
1064)
1065{
1066 if (GetTopWindow())
1067 {
1068 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
1069 rEvent.Veto(TRUE);
1070 }
1071} // end of wxApp::OnQueryEndSession
1072
1073void wxExit()
1074{
1075 wxLogError(_("Fatal error: exiting"));
1076
1077 wxApp::CleanUp();
1078} // end of wxExit
1079
1080static bool gs_inYield = FALSE;
1081
1082//
1083// Yield to incoming messages
1084//
1085bool wxYield()
1086{
1087 HAB vHab = 0;
1088 QMSG vMsg;
1089
1090 //
1091 // Disable log flushing from here because a call to wxYield() shouldn't
1092 // normally result in message boxes popping up &c
1093 //
1094 wxLog::Suspend();
1095
1096 gs_inYield = TRUE;
1097
1098 //
1099 // We want to go back to the main message loop
1100 // if we see a WM_QUIT. (?)
1101 //
1102 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
1103 {
1104#if wxUSE_THREADS
1105 wxMutexGuiLeaveOrEnter();
1106#endif // wxUSE_THREADS
1107 if (!wxTheApp->DoMessage())
1108 break;
1109 }
1110 //
1111 // If they are pending events, we must process them.
1112 //
1113 if (wxTheApp)
1114 wxTheApp->ProcessPendingEvents();
1115
1116 //
1117 // Let the logs be flashed again
1118 //
1119 wxLog::Resume();
1120 gs_inYield = FALSE;
1121 return TRUE;
1122} // end of wxYield
1123
1124// Yield to incoming messages; but fail silently if recursion is detected.
1125bool wxYieldIfNeeded()
1126{
1127 if (gs_inYield)
1128 return FALSE;
1129
1130 return wxYield();
1131}
1132
1133wxIcon wxApp::GetStdIcon(
1134 int nWhich
1135) const
1136{
1137 switch(nWhich)
1138 {
1139 case wxICON_INFORMATION:
1140 return wxIcon("wxICON_INFO");
1141
1142 case wxICON_QUESTION:
1143 return wxIcon("wxICON_QUESTION");
1144
1145 case wxICON_EXCLAMATION:
1146 return wxIcon("wxICON_WARNING");
1147
1148 default:
1149 wxFAIL_MSG(wxT("requested non existent standard icon"));
1150 // still fall through
1151
1152 case wxICON_HAND:
1153 return wxIcon("wxICON_ERROR");
1154 }
1155 return wxIcon("wxICON_ERROR");
1156} // end of wxApp::GetStdIcon
1157
1158int wxApp::AddSocketHandler(int handle, int mask,
1159 void (*callback)(void*), void * gsock)
1160{
1161 int find;
1162 struct GsocketCallbackInfo
1163 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
1164
1165 for (find = 0; find < m_maxSocketHandles; find++)
1166 if (CallbackInfo[find].handle == -1)
1167 break;
1168 if (find == m_maxSocketHandles)
1169 {
1170 // Allocate new memory
1171 m_sockCallbackInfo = realloc(m_sockCallbackInfo,
1172 (m_maxSocketHandles+=10)*
1173 sizeof(struct GsocketCallbackInfo));
1174 CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
1175 for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++)
1176 CallbackInfo[find].handle = -1;
1177 find = m_maxSocketHandles - 10;
1178 }
1179 CallbackInfo[find].proc = callback;
1180 CallbackInfo[find].type = mask;
1181 CallbackInfo[find].handle = handle;
1182 CallbackInfo[find].gsock = gsock;
1183 if (mask & wxSockReadMask)
1184 FD_SET(handle, &m_readfds);
1185 if (mask & wxSockWriteMask)
1186 FD_SET(handle, &m_writefds);
1187 if (handle >= m_maxSocketNr)
1188 m_maxSocketNr = handle + 1;
1189 return find;
1190}
1191
1192void wxApp::RemoveSocketHandler(int handle)
1193{
1194 struct GsocketCallbackInfo
1195 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
1196 if (handle < m_maxSocketHandles)
1197 {
1198 if (CallbackInfo[handle].type & wxSockReadMask)
1199 FD_CLR(CallbackInfo[handle].handle, &m_readfds);
1200 if (CallbackInfo[handle].type & wxSockWriteMask)
1201 FD_CLR(CallbackInfo[handle].handle, &m_writefds);
1202 CallbackInfo[handle].handle = -1;
1203 }
1204}
1205
1206//-----------------------------------------------------------------------------
1207// wxWakeUpIdle
1208//-----------------------------------------------------------------------------
1209
1210void wxWakeUpIdle()
1211{
1212 //
1213 // Send the top window a dummy message so idle handler processing will
1214 // start up again. Doing it this way ensures that the idle handler
1215 // wakes up in the right thread (see also wxWakeUpMainThread() which does
1216 // the same for the main app thread only)
1217 //
1218 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
1219
1220 if (pTopWindow)
1221 {
1222 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
1223 {
1224 //
1225 // Should never happen
1226 //
1227 wxLogLastError("PostMessage(WM_NULL)");
1228 }
1229 }
1230} // end of wxWakeUpIdle
1231
1232HAB wxGetInstance()
1233{
1234 return vHabmain;
1235}
1236
1237void wxSetInstance(
1238 HAB vHab
1239)
1240{
1241 vHabmain = vHab;
1242}
1243