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