Updated gsocket.c to current unix version, use gsockunx.h instead of gsockos2.h
[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 // 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)
50 int _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
84 extern wxChar* wxBuffer;
85 extern wxList* wxWinHandleList;
86 extern wxList WXDLLEXPORT wxPendingDelete;
87 extern wxCursor* g_globalCursor;
88
89 HAB vHabmain = NULLHANDLE;
90 QMSG svCurrentMsg;
91 wxApp* 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
95 wxChar wxFrameClassName[] = wxT("wxFrameClass");
96 wxChar wxFrameClassNameNoRedraw[] = wxT("wxFrameClassNR");
97 wxChar wxMDIFrameClassName[] = wxT("wxMDIFrameClass");
98 wxChar wxMDIFrameClassNameNoRedraw[] = wxT("wxMDIFrameClassNR");
99 wxChar wxMDIChildFrameClassName[] = wxT("wxMDIChildFrameClass");
100 wxChar wxMDIChildFrameClassNameNoRedraw[] = wxT("wxMDIChildFrameClassNR");
101 wxChar wxPanelClassName[] = wxT("wxPanelClass");
102 wxChar wxCanvasClassName[] = wxT("wxCanvasClass");
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 extern "C"
137 int wxAppAddSocketHandler(int handle, int mask,
138 void (*callback)(void*), void * gsock)
139 {
140 return wxTheApp->AddSocketHandler(handle, mask, callback, gsock);
141 }
142
143 extern "C"
144 void wxAppRemoveSocketHandler(int handle)
145 {
146 wxTheApp->RemoveSocketHandler(handle);
147 }
148
149 void 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 //
222 bool 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
302 const char* CANTREGISTERCLASS = " Can't register Class ";
303 // ---------------------------------------------------------------------------
304 // RegisterWindowClasses
305 // ---------------------------------------------------------------------------
306
307 bool 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 //
424 void 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 //----------------------------------------------------------------------
539 int 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
634 bool 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 //
653 wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
654
655 wxApp::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
672 wxApp::~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
688 bool 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
701 bool 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 //////////////////////////////////////////////////////////////////////////////
796 int 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 //
823 bool wxApp::ProcessIdle()
824 {
825 wxIdleEvent vEvent;
826
827 vEvent.SetEventObject(this);
828 ProcessEvent(vEvent);
829 return vEvent.MoreRequested();
830 } // end of wxApp::ProcessIdle
831
832 void wxApp::ExitMainLoop()
833 {
834 m_bKeepGoing = FALSE;
835 }
836
837 bool wxApp::Pending()
838 {
839 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
840 }
841
842 void 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 //////////////////////////////////////////////////////////////////////////////
854 bool 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
937 void 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
985 bool 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 //
1004 bool 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
1030 void 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
1051 void 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 //
1062 void 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
1073 void wxExit()
1074 {
1075 wxLogError(_("Fatal error: exiting"));
1076
1077 wxApp::CleanUp();
1078 } // end of wxExit
1079
1080 static bool gs_inYield = FALSE;
1081
1082 //
1083 // Yield to incoming messages
1084 //
1085 bool 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.
1125 bool wxYieldIfNeeded()
1126 {
1127 if (gs_inYield)
1128 return FALSE;
1129
1130 return wxYield();
1131 }
1132
1133 wxIcon 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
1158 int 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
1192 void 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
1210 void 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
1232 HAB wxGetInstance()
1233 {
1234 return vHabmain;
1235 }
1236
1237 void wxSetInstance(
1238 HAB vHab
1239 )
1240 {
1241 vHabmain = vHab;
1242 }
1243