use wxEventLoop in wxApp under wxMSW; factored out common code from wxX11/wxMotif...
[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_TOOLTIPS
80 #include "wx/tooltip.h"
81 #endif // wxUSE_TOOLTIPS
82
83 #include <string.h>
84 #include <ctype.h>
85
86 // ---------------------------------------------------------------------------
87 // global variables
88 // ---------------------------------------------------------------------------
89
90 extern wxChar* wxBuffer;
91 extern wxList* wxWinHandleList;
92 extern wxList WXDLLEXPORT wxPendingDelete;
93 extern wxCursor* g_globalCursor;
94
95 HAB vHabmain = NULLHANDLE;
96 QMSG svCurrentMsg;
97
98
99 HICON wxSTD_FRAME_ICON = (HICON) NULL;
100 HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
101 HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
102
103 HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
104 HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
105 HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
106
107 HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
108
109 MRESULT EXPENTRY wxWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
110 MRESULT EXPENTRY wxFrameWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
111
112 // ===========================================================================
113 // implementation
114 // ===========================================================================
115
116 // ---------------------------------------------------------------------------
117 // helper struct and functions for socket handling
118 // ---------------------------------------------------------------------------
119
120 struct GsocketCallbackInfo{
121 void (*proc)(void *);
122 int type;
123 int handle;
124 void* gsock;
125 };
126
127 // These defines and wrapper functions are used here and in gsockpm.c
128 #define wxSockReadMask 0x01
129 #define wxSockWriteMask 0x02
130
131 #ifdef __EMX__
132 extern "C"
133 int wxAppAddSocketHandler(int handle, int mask,
134 void (*callback)(void*), void * gsock)
135 {
136 return wxTheApp->AddSocketHandler(handle, mask, callback, gsock);
137 }
138 extern "C"
139 void wxAppRemoveSocketHandler(int handle)
140 {
141 wxTheApp->RemoveSocketHandler(handle);
142 }
143 #else
144 // Linkage mode problems using callbacks with extern C in a .cpp module
145 int wxAppAddSocketHandler(int handle, int mask,
146 void (*callback)(void*), void * gsock)
147 {
148 return wxTheApp->AddSocketHandler(handle, mask, callback, gsock);
149 }
150 void wxAppRemoveSocketHandler(int handle)
151 {
152 wxTheApp->RemoveSocketHandler(handle);
153 }
154 #endif
155
156 void wxApp::HandleSockets()
157 {
158 bool pendingEvent = FALSE;
159
160 // Check whether it's time for Gsocket operation
161 if (m_maxSocketHandles > 0 && m_maxSocketNr > 0)
162 {
163 fd_set readfds = m_readfds;
164 fd_set writefds = m_writefds;
165 struct timeval timeout;
166 int i;
167 struct GsocketCallbackInfo
168 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
169 timeout.tv_sec = 0;
170 timeout.tv_usec = 0;
171 if ( select(m_maxSocketNr, &readfds, &writefds, 0, &timeout) > 0)
172 {
173 for (i = m_lastUsedHandle + 1; i != m_lastUsedHandle;
174 (i < m_maxSocketNr - 1) ? i++ : (i = 0))
175 {
176 if (FD_ISSET(i, &readfds))
177 {
178 int r;
179 for (r = 0; r < m_maxSocketHandles; r++){
180 if(CallbackInfo[r].handle == i &&
181 CallbackInfo[r].type == wxSockReadMask)
182 break;
183 }
184 if (r < m_maxSocketHandles)
185 {
186 CallbackInfo[r].proc(CallbackInfo[r].gsock);
187 pendingEvent = TRUE;
188 }
189 }
190 if (FD_ISSET(i, &writefds))
191 {
192 int r;
193 for (r = 0; r < m_maxSocketHandles; r++)
194 if(CallbackInfo[r].handle == i &&
195 CallbackInfo[r].type == wxSockWriteMask)
196 break;
197 if (r < m_maxSocketHandles)
198 {
199 CallbackInfo[r].proc(CallbackInfo[r].gsock);
200 pendingEvent = TRUE;
201 }
202 }
203 }
204 m_lastUsedHandle = i;
205 }
206 if (pendingEvent)
207 ProcessPendingEvents();
208 }
209 }
210 // ---------------------------------------------------------------------------
211 // wxApp
212 // ---------------------------------------------------------------------------
213
214 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
215
216 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
217 EVT_IDLE(wxApp::OnIdle)
218 EVT_END_SESSION(wxApp::OnEndSession)
219 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
220 END_EVENT_TABLE()
221
222 //
223 // Initialize
224 //
225 bool wxApp::Initialize(int& argc, wxChar **argv)
226 {
227 if ( !wxAppBase::Initialize(argc, argv) )
228 return false;
229
230 #if defined(wxUSE_CONSOLEDEBUG)
231 #if wxUSE_CONSOLEDEBUG
232 /***********************************************/
233 /* Code for using stdout debug */
234 /* To use it you mast link app as "Window" - EK*/
235 /***********************************************/
236 {
237 PPIB pib;
238 PTIB tib;
239
240 printf("In console\n");
241
242 DosGetInfoBlocks(&tib, &pib);
243 /* Try morphing into a PM application. */
244 // if(pib->pib_ultype == 2) /* VIO */
245 pib->pib_ultype = 3;
246 }
247 /**********************************************/
248 /**********************************************/
249 #endif //wxUSE_CONSOLEDEBUG
250 #endif
251
252 //
253 // OS2 has to have an anchorblock
254 //
255 vHabmain = WinInitialize(0);
256
257 if (!vHabmain)
258 {
259 // TODO: at least give some error message here...
260 wxAppBase::CleanUp();
261
262 return FALSE;
263 }
264
265 wxBuffer = new wxChar[1500]; // FIXME; why?
266
267 // Some people may wish to use this, but
268 // probably it shouldn't be here by default.
269 #ifdef __WXDEBUG__
270 // wxRedirectIOToConsole();
271 #endif
272
273 wxWinHandleList = new wxList(wxKEY_INTEGER);
274
275 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
276 // PLEASE DO NOT ALTER THIS.
277 #if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
278 extern char wxDummyChar;
279 if (wxDummyChar) wxDummyChar++;
280 #endif
281
282 // wxSetKeyboardHook(TRUE);
283
284 RegisterWindowClasses(vHabmain);
285
286 return TRUE;
287 } // end of wxApp::Initialize
288
289 const char* CANTREGISTERCLASS = " Can't register Class ";
290 // ---------------------------------------------------------------------------
291 // RegisterWindowClasses
292 // ---------------------------------------------------------------------------
293
294 bool wxApp::RegisterWindowClasses(
295 HAB vHab
296 )
297 {
298 ERRORID vError = 0L;
299 wxString sError;
300
301 if (!::WinRegisterClass( vHab
302 ,wxFrameClassName
303 ,wxFrameWndProc
304 ,CS_SIZEREDRAW | CS_SYNCPAINT
305 ,sizeof(ULONG)
306 ))
307 {
308 vError = ::WinGetLastError(vHab);
309 sError = wxPMErrorToStr(vError);
310 wxLogLastError(sError);
311 return FALSE;
312 }
313
314 if (!::WinRegisterClass( vHab
315 ,wxFrameClassNameNoRedraw
316 ,wxWndProc
317 ,0
318 ,sizeof(ULONG)
319 ))
320 {
321 vError = ::WinGetLastError(vHab);
322 sError = wxPMErrorToStr(vError);
323 wxLogLastError(sError);
324 return FALSE;
325 }
326
327 if (!::WinRegisterClass( vHab
328 ,wxMDIFrameClassName
329 ,wxWndProc
330 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
331 ,sizeof(ULONG)
332 ))
333 {
334 vError = ::WinGetLastError(vHab);
335 sError = wxPMErrorToStr(vError);
336 wxLogLastError(sError);
337 return FALSE;
338 }
339
340 if (!::WinRegisterClass( vHab
341 ,wxMDIFrameClassNameNoRedraw
342 ,wxWndProc
343 ,0
344 ,sizeof(ULONG)
345 ))
346 {
347 vError = ::WinGetLastError(vHab);
348 sError = wxPMErrorToStr(vError);
349 wxLogLastError(sError);
350 return FALSE;
351 }
352
353 if (!::WinRegisterClass( vHab
354 ,wxMDIChildFrameClassName
355 ,wxWndProc
356 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
357 ,sizeof(ULONG)
358 ))
359 {
360 vError = ::WinGetLastError(vHab);
361 sError = wxPMErrorToStr(vError);
362 wxLogLastError(sError);
363 return FALSE;
364 }
365
366 if (!::WinRegisterClass( vHab
367 ,wxMDIChildFrameClassNameNoRedraw
368 ,wxWndProc
369 ,CS_HITTEST
370 ,sizeof(ULONG)
371 ))
372 {
373 vError = ::WinGetLastError(vHab);
374 sError = wxPMErrorToStr(vError);
375 wxLogLastError(sError);
376 return FALSE;
377 }
378
379 if (!::WinRegisterClass( vHab
380 ,wxPanelClassName
381 ,wxWndProc
382 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
383 ,sizeof(ULONG)
384 ))
385 {
386 vError = ::WinGetLastError(vHab);
387 sError = wxPMErrorToStr(vError);
388 wxLogLastError(sError);
389 return FALSE;
390 }
391
392 if (!::WinRegisterClass( vHab
393 ,wxCanvasClassName
394 ,wxWndProc
395 ,CS_SIZEREDRAW | CS_HITTEST | CS_SYNCPAINT
396 ,sizeof(ULONG)
397 ))
398 {
399 vError = ::WinGetLastError(vHab);
400 sError = wxPMErrorToStr(vError);
401 wxLogLastError(sError);
402 return FALSE;
403 }
404 if (!::WinRegisterClass( vHab
405 ,wxCanvasClassNameNR
406 ,wxWndProc
407 ,CS_HITTEST | CS_SYNCPAINT
408 ,sizeof(ULONG)
409 ))
410 {
411 vError = ::WinGetLastError(vHab);
412 sError = wxPMErrorToStr(vError);
413 wxLogLastError(sError);
414 return FALSE;
415 }
416 return TRUE;
417 } // end of wxApp::RegisterWindowClasses
418
419 //
420 // Cleans up any wxWindows internal structures left lying around
421 //
422 void wxApp::CleanUp()
423 {
424 delete[] wxBuffer;
425 wxBuffer = NULL;
426
427 //
428 // PM-SPECIFIC CLEANUP
429 //
430
431 // wxSetKeyboardHook(FALSE);
432
433 if (wxSTD_FRAME_ICON)
434 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
435 if (wxSTD_MDICHILDFRAME_ICON)
436 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
437 if (wxSTD_MDIPARENTFRAME_ICON)
438 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
439
440 if (wxDEFAULT_FRAME_ICON)
441 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
442 if (wxDEFAULT_MDICHILDFRAME_ICON)
443 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
444 if (wxDEFAULT_MDIPARENTFRAME_ICON)
445 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
446
447 if ( wxDisableButtonBrush )
448 {
449 // TODO: ::DeleteObject( wxDisableButtonBrush );
450 }
451
452 if (wxWinHandleList)
453 delete wxWinHandleList;
454
455 // Delete Message queue
456 if (wxTheApp->m_hMq)
457 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
458
459 wxAppBase::CleanUp();
460 } // end of wxApp::CleanUp
461
462 bool wxApp::OnInitGui()
463 {
464 ERRORID vError;
465 wxString sError;
466
467 if (!wxAppBase::OnInitGui())
468 return FALSE;
469
470 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
471 if (!m_hMq)
472 {
473 vError = ::WinGetLastError(vHabmain);
474 sError = wxPMErrorToStr(vError);
475 wxLogDebug(sError);
476 return FALSE;
477 }
478
479 return TRUE;
480 } // end of wxApp::OnInitGui
481
482 wxApp::wxApp()
483 {
484 argc = 0;
485 argv = NULL;
486 m_nPrintMode = wxPRINT_WINDOWS;
487 m_hMq = 0;
488 m_maxSocketHandles = 0;
489 m_maxSocketNr = 0;
490 m_sockCallbackInfo = 0;
491 } // end of wxApp::wxApp
492
493 wxApp::~wxApp()
494 {
495 //
496 // Delete command-line args
497 //
498 #if wxUSE_UNICODE
499 int i;
500
501 for (i = 0; i < argc; i++)
502 {
503 delete[] argv[i];
504 }
505 delete[] argv;
506 #endif
507 } // end of wxApp::~wxApp
508
509 bool wxApp::Initialized()
510 {
511 if (GetTopWindow())
512 return TRUE;
513 else
514 return FALSE;
515 } // end of wxApp::Initialized
516
517 //
518 // Get and process a message, returning FALSE if WM_QUIT
519 // received (and also set the flag telling the app to exit the main loop)
520 //
521
522 bool wxApp::DoMessage()
523 {
524 BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
525
526 if (bRc == 0)
527 {
528 // got WM_QUIT
529 m_bKeepGoing = FALSE;
530 return FALSE;
531 }
532 else if (bRc == -1)
533 {
534 // should never happen, but let's test for it nevertheless
535 wxLogLastError("GetMessage");
536 }
537 else
538 {
539 #if wxUSE_THREADS
540 wxASSERT_MSG( wxThread::IsMain()
541 ,wxT("only the main thread can process Windows messages")
542 );
543
544 static bool sbHadGuiLock = TRUE;
545 static wxMsgArray svSavedMessages;
546
547 //
548 // If a secondary thread owns is doing GUI calls, save all messages for
549 // later processing - we can't process them right now because it will
550 // lead to recursive library calls (and we're not reentrant)
551 //
552 if (!wxGuiOwnedByMainThread())
553 {
554 sbHadGuiLock = FALSE;
555
556 //
557 // Leave out WM_COMMAND messages: too dangerous, sometimes
558 // the message will be processed twice
559 //
560 if ( !wxIsWaitingForThread() ||
561 svCurrentMsg.msg != WM_COMMAND )
562 {
563 svSavedMessages.Add(svCurrentMsg);
564 }
565 return TRUE;
566 }
567 else
568 {
569 //
570 // Have we just regained the GUI lock? if so, post all of the saved
571 // messages
572 //
573 if (!sbHadGuiLock )
574 {
575 sbHadGuiLock = TRUE;
576
577 size_t nCount = svSavedMessages.Count();
578
579 for (size_t n = 0; n < nCount; n++)
580 {
581 QMSG vMsg = svSavedMessages[n];
582
583 DoMessage((WXMSG*)&vMsg);
584 }
585 svSavedMessages.Empty();
586 }
587 }
588 #endif // wxUSE_THREADS
589
590 //
591 // Process the message
592 //
593 DoMessage((WXMSG *)&svCurrentMsg);
594 }
595 return TRUE;
596 } // end of wxApp::DoMessage
597
598 void wxApp::DoMessage(
599 WXMSG* pMsg
600 )
601 {
602 if (!ProcessMessage((WXMSG *)&svCurrentMsg))
603 {
604 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
605 }
606 } // end of wxApp::DoMessage
607
608 //////////////////////////////////////////////////////////////////////////////
609 //
610 // Keep trying to process messages until WM_QUIT
611 // received.
612 //
613 // If there are messages to be processed, they will all be
614 // processed and OnIdle will not be called.
615 // When there are no more messages, OnIdle is called.
616 // If OnIdle requests more time,
617 // it will be repeatedly called so long as there are no pending messages.
618 // A 'feature' of this is that once OnIdle has decided that no more processing
619 // is required, then it won't get processing time until further messages
620 // are processed (it'll sit in DoMessage).
621 //
622 //////////////////////////////////////////////////////////////////////////////
623 int wxApp::MainLoop()
624 {
625 m_bKeepGoing = TRUE;
626
627 while (m_bKeepGoing)
628 {
629 #if wxUSE_THREADS
630 wxMutexGuiLeaveOrEnter();
631 #endif // wxUSE_THREADS
632 while (!Pending() && ProcessIdle())
633 {
634 HandleSockets();
635 wxUsleep(10);
636 }
637 HandleSockets();
638 if (Pending())
639 DoMessage();
640 else
641 wxUsleep(10);
642
643 }
644 return (int)svCurrentMsg.mp1;
645 } // end of wxApp::MainLoop
646
647 void wxApp::ExitMainLoop()
648 {
649 ::WinPostMsg(NULL, WM_QUIT, 0, 0);
650 } // end of wxApp::ExitMainLoop
651
652 bool wxApp::Pending()
653 {
654 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
655 } // end of wxApp::Pending
656
657 bool wxApp::Dispatch()
658 {
659 return DoMessage();
660 }
661
662 //////////////////////////////////////////////////////////////////////////////
663 //
664 // Give all windows a chance to preprocess
665 // the message. Some may have accelerator tables, or have
666 // MDI complications.
667 //
668 //////////////////////////////////////////////////////////////////////////////
669 bool wxApp::ProcessMessage(
670 WXMSG* pWxmsg
671 )
672 {
673 QMSG* pMsg = (PQMSG)pWxmsg;
674 HWND hWnd = pMsg->hwnd;
675 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
676 wxWindow* pWnd;
677
678 //
679 // Pass non-system timer messages to the wxTimerProc
680 //
681 if (pMsg->msg == WM_TIMER &&
682 (SHORT1FROMMP(pMsg->mp1) != TID_CURSOR &&
683 SHORT1FROMMP(pMsg->mp1) != TID_FLASHWINDOW &&
684 SHORT1FROMMP(pMsg->mp1) != TID_SCROLL &&
685 SHORT1FROMMP(pMsg->mp1) != 0x0000
686 ))
687 wxTimerProc(NULL, 0, (int)pMsg->mp1, 0);
688
689 //
690 // Allow the window to prevent certain messages from being
691 // translated/processed (this is currently used by wxTextCtrl to always
692 // grab Ctrl-C/V/X, even if they are also accelerators in some parent)
693 //
694 if (pWndThis && !pWndThis->OS2ShouldPreProcessMessage(pWxmsg))
695 {
696 return FALSE;
697 }
698
699 //
700 // For some composite controls (like a combobox), wndThis might be NULL
701 // because the subcontrol is not a wxWindow, but only the control itself
702 // is - try to catch this case
703 //
704 while (hWnd && !pWndThis)
705 {
706 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
707 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
708 }
709
710 //
711 // Try translations first; find the youngest window with
712 // a translation table. OS/2 has case sensative accels, so
713 // this block, coded by BK, removes that and helps make them
714 // case insensative.
715 //
716 if(pMsg->msg == WM_CHAR)
717 {
718 PBYTE pChmsg = (PBYTE)&(pMsg->msg);
719 USHORT uSch = CHARMSG(pChmsg)->chr;
720 bool bRc;
721
722 //
723 // Do not process keyup events
724 //
725 if(!(CHARMSG(pChmsg)->fs & KC_KEYUP))
726 {
727 if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0)
728 CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
729
730
731 for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
732 {
733 if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
734 break;
735 }
736
737 if(!bRc) // untranslated, should restore original value
738 CHARMSG(pChmsg)->chr = uSch;
739 }
740 }
741 //
742 // Anyone for a non-translation message? Try youngest descendants first.
743 //
744 // for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
745 // {
746 // if (pWnd->OS2ProcessMessage(pWxmsg))
747 // return TRUE;
748 // }
749 return FALSE;
750 } // end of wxApp::ProcessMessage
751
752 bool gbInOnIdle = FALSE;
753
754 void wxApp::OnIdle(
755 wxIdleEvent& rEvent
756 )
757 {
758
759 //
760 // Avoid recursion (via ProcessEvent default case)
761 //
762 if (gbInOnIdle)
763 return;
764
765 gbInOnIdle = TRUE;
766
767 wxAppBase::OnIdle(rEvent);
768
769 #if wxUSE_DC_CACHEING
770 // automated DC cache management: clear the cached DCs and bitmap
771 // if it's likely that the app has finished with them, that is, we
772 // get an idle event and we're not dragging anything.
773 if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &&
774 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &&
775 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2))
776 wxDC::ClearCache();
777 #endif // wxUSE_DC_CACHEING
778
779 gbInOnIdle = FALSE;
780 } // end of wxApp::OnIdle
781
782 void wxApp::OnEndSession(
783 wxCloseEvent& WXUNUSED(rEvent))
784 {
785 if (GetTopWindow())
786 GetTopWindow()->Close(TRUE);
787 } // end of wxApp::OnEndSession
788
789 //
790 // Default behaviour: close the application with prompts. The
791 // user can veto the close, and therefore the end session.
792 //
793 void wxApp::OnQueryEndSession(
794 wxCloseEvent& rEvent
795 )
796 {
797 if (GetTopWindow())
798 {
799 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
800 rEvent.Veto(TRUE);
801 }
802 } // end of wxApp::OnQueryEndSession
803
804 void wxApp::Exit()
805 {
806 wxApp::CleanUp();
807
808 // VZ: must really exit somehow, insert appropriate OS/2 syscall (FIXME)
809 wxAppConsole::Exit();
810 } // end of wxExit
811
812 //
813 // Yield to incoming messages
814 //
815 bool wxApp::Yield(bool onlyIfNeeded)
816 {
817 static bool s_inYield = FALSE;
818
819 if ( s_inYield )
820 {
821 if ( !onlyIfNeeded )
822 {
823 wxFAIL_MSG( _T("wxYield() called recursively") );
824 }
825
826 return FALSE;
827 }
828
829 HAB vHab = 0;
830 QMSG vMsg;
831
832 //
833 // Disable log flushing from here because a call to wxYield() shouldn't
834 // normally result in message boxes popping up &c
835 //
836 wxLog::Suspend();
837
838 s_inYield = TRUE;
839
840 //
841 // We want to go back to the main message loop
842 // if we see a WM_QUIT. (?)
843 //
844 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
845 {
846 #if wxUSE_THREADS
847 wxMutexGuiLeaveOrEnter();
848 #endif // wxUSE_THREADS
849 if (!wxTheApp->DoMessage())
850 break;
851 }
852 //
853 // If they are pending events, we must process them.
854 //
855 if (wxTheApp)
856 wxTheApp->ProcessPendingEvents();
857
858 HandleSockets();
859 //
860 // Let the logs be flashed again
861 //
862 wxLog::Resume();
863 s_inYield = FALSE;
864 return TRUE;
865 } // end of wxYield
866
867 int wxApp::AddSocketHandler(int handle, int mask,
868 void (*callback)(void*), void * gsock)
869 {
870 int find;
871 struct GsocketCallbackInfo
872 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
873
874 for (find = 0; find < m_maxSocketHandles; find++)
875 if (CallbackInfo[find].handle == -1)
876 break;
877 if (find == m_maxSocketHandles)
878 {
879 // Allocate new memory
880 m_sockCallbackInfo = realloc(m_sockCallbackInfo,
881 (m_maxSocketHandles+=10)*
882 sizeof(struct GsocketCallbackInfo));
883 CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
884 for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++)
885 CallbackInfo[find].handle = -1;
886 find = m_maxSocketHandles - 10;
887 }
888 CallbackInfo[find].proc = callback;
889 CallbackInfo[find].type = mask;
890 CallbackInfo[find].handle = handle;
891 CallbackInfo[find].gsock = gsock;
892 if (mask & wxSockReadMask)
893 FD_SET(handle, &m_readfds);
894 if (mask & wxSockWriteMask)
895 FD_SET(handle, &m_writefds);
896 if (handle >= m_maxSocketNr)
897 m_maxSocketNr = handle + 1;
898 return find;
899 }
900
901 void wxApp::RemoveSocketHandler(int handle)
902 {
903 struct GsocketCallbackInfo
904 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
905 if (handle < m_maxSocketHandles)
906 {
907 if (CallbackInfo[handle].type & wxSockReadMask)
908 FD_CLR(CallbackInfo[handle].handle, &m_readfds);
909 if (CallbackInfo[handle].type & wxSockWriteMask)
910 FD_CLR(CallbackInfo[handle].handle, &m_writefds);
911 CallbackInfo[handle].handle = -1;
912 }
913 }
914
915 //-----------------------------------------------------------------------------
916 // wxWakeUpIdle
917 //-----------------------------------------------------------------------------
918
919 void wxApp::WakeUpIdle()
920 {
921 //
922 // Send the top window a dummy message so idle handler processing will
923 // start up again. Doing it this way ensures that the idle handler
924 // wakes up in the right thread (see also wxWakeUpMainThread() which does
925 // the same for the main app thread only)
926 //
927 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
928
929 if (pTopWindow)
930 {
931 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
932 {
933 //
934 // Should never happen
935 //
936 wxLogLastError("PostMessage(WM_NULL)");
937 }
938 }
939 } // end of wxWakeUpIdle
940
941 HAB wxGetInstance()
942 {
943 return vHabmain;
944 }
945
946 void wxSetInstance(
947 HAB vHab
948 )
949 {
950 vHabmain = vHab;
951 }
952