]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/app.cpp
rtti api mods added
[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#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)
61extern "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
90extern wxChar* wxBuffer;
91extern wxList* wxWinHandleList;
92extern wxList WXDLLEXPORT wxPendingDelete;
93extern wxCursor* g_globalCursor;
94
95HAB vHabmain = NULLHANDLE;
96QMSG svCurrentMsg;
97
98
99HICON wxSTD_FRAME_ICON = (HICON) NULL;
100HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
101HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
102
103HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
104HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
105HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
106
107HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
108
109MRESULT EXPENTRY wxWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
110MRESULT 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
120struct 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__
132extern "C"
133int wxAppAddSocketHandler(int handle, int mask,
134 void (*callback)(void*), void * gsock)
135{
136 return wxTheApp->AddSocketHandler(handle, mask, callback, gsock);
137}
138extern "C"
139void wxAppRemoveSocketHandler(int handle)
140{
141 wxTheApp->RemoveSocketHandler(handle);
142}
143#else
144// Linkage mode problems using callbacks with extern C in a .cpp module
145int wxAppAddSocketHandler(int handle, int mask,
146 void (*callback)(void*), void * gsock)
147{
148 return wxTheApp->AddSocketHandler(handle, mask, callback, gsock);
149}
150void wxAppRemoveSocketHandler(int handle)
151{
152 wxTheApp->RemoveSocketHandler(handle);
153}
154#endif
155
156void 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//
225bool 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(vHab);
285
286 return TRUE;
287} // end of wxApp::Initialize
288
289const char* CANTREGISTERCLASS = " Can't register Class ";
290// ---------------------------------------------------------------------------
291// RegisterWindowClasses
292// ---------------------------------------------------------------------------
293
294bool 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//
422void 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 wxPendingEvents;
456#if wxUSE_THREADS
457 delete wxPendingEventsLocker;
458 // If we don't do the following, we get an apparent memory leak.
459 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
460#endif
461
462 // Delete Message queue
463 if (wxTheApp->m_hMq)
464 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
465
466 wxAppBase::CleanUp();
467} // end of wxApp::CleanUp
468
469bool wxApp::OnInitGui()
470{
471 ERRORID vError;
472 wxString sError;
473
474 if (!wxAppBase::OnInitGui())
475 return FALSE;
476
477 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
478 if (!m_hMq)
479 {
480 vError = ::WinGetLastError(vHabmain);
481 sError = wxPMErrorToStr(vError);
482 wxLogDebug(sError);
483 return FALSE;
484 }
485
486 return TRUE;
487} // end of wxApp::OnInitGui
488
489wxApp::wxApp()
490{
491 m_topWindow = NULL;
492 wxTheApp = this;
493
494 argc = 0;
495 argv = NULL;
496 m_nPrintMode = wxPRINT_WINDOWS;
497 m_hMq = 0;
498 m_maxSocketHandles = 0;
499 m_maxSocketNr = 0;
500 m_sockCallbackInfo = 0;
501} // end of wxApp::wxApp
502
503wxApp::~wxApp()
504{
505 //
506 // Delete command-line args
507 //
508#if wxUSE_UNICODE
509 int i;
510
511 for (i = 0; i < argc; i++)
512 {
513 delete[] argv[i];
514 }
515 delete[] argv;
516#endif
517} // end of wxApp::~wxApp
518
519bool wxApp::Initialized()
520{
521 if (GetTopWindow())
522 return TRUE;
523 else
524 return FALSE;
525} // end of wxApp::Initialized
526
527//
528// Get and process a message, returning FALSE if WM_QUIT
529// received (and also set the flag telling the app to exit the main loop)
530//
531
532bool wxApp::DoMessage()
533{
534 BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
535
536 if (bRc == 0)
537 {
538 // got WM_QUIT
539 m_bKeepGoing = FALSE;
540 return FALSE;
541 }
542 else if (bRc == -1)
543 {
544 // should never happen, but let's test for it nevertheless
545 wxLogLastError("GetMessage");
546 }
547 else
548 {
549#if wxUSE_THREADS
550 wxASSERT_MSG( wxThread::IsMain()
551 ,wxT("only the main thread can process Windows messages")
552 );
553
554 static bool sbHadGuiLock = TRUE;
555 static wxMsgArray svSavedMessages;
556
557 //
558 // If a secondary thread owns is doing GUI calls, save all messages for
559 // later processing - we can't process them right now because it will
560 // lead to recursive library calls (and we're not reentrant)
561 //
562 if (!wxGuiOwnedByMainThread())
563 {
564 sbHadGuiLock = FALSE;
565
566 //
567 // Leave out WM_COMMAND messages: too dangerous, sometimes
568 // the message will be processed twice
569 //
570 if ( !wxIsWaitingForThread() ||
571 svCurrentMsg.msg != WM_COMMAND )
572 {
573 svSavedMessages.Add(svCurrentMsg);
574 }
575 return TRUE;
576 }
577 else
578 {
579 //
580 // Have we just regained the GUI lock? if so, post all of the saved
581 // messages
582 //
583 if (!sbHadGuiLock )
584 {
585 sbHadGuiLock = TRUE;
586
587 size_t nCount = svSavedMessages.Count();
588
589 for (size_t n = 0; n < nCount; n++)
590 {
591 QMSG vMsg = svSavedMessages[n];
592
593 DoMessage((WXMSG*)&vMsg);
594 }
595 svSavedMessages.Empty();
596 }
597 }
598#endif // wxUSE_THREADS
599
600 //
601 // Process the message
602 //
603 DoMessage((WXMSG *)&svCurrentMsg);
604 }
605 return TRUE;
606} // end of wxApp::DoMessage
607
608void wxApp::DoMessage(
609 WXMSG* pMsg
610)
611{
612 if (!ProcessMessage((WXMSG *)&svCurrentMsg))
613 {
614 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
615 }
616} // end of wxApp::DoMessage
617
618//////////////////////////////////////////////////////////////////////////////
619//
620// Keep trying to process messages until WM_QUIT
621// received.
622//
623// If there are messages to be processed, they will all be
624// processed and OnIdle will not be called.
625// When there are no more messages, OnIdle is called.
626// If OnIdle requests more time,
627// it will be repeatedly called so long as there are no pending messages.
628// A 'feature' of this is that once OnIdle has decided that no more processing
629// is required, then it won't get processing time until further messages
630// are processed (it'll sit in DoMessage).
631//
632//////////////////////////////////////////////////////////////////////////////
633int wxApp::MainLoop()
634{
635 m_bKeepGoing = TRUE;
636
637 while (m_bKeepGoing)
638 {
639#if wxUSE_THREADS
640 wxMutexGuiLeaveOrEnter();
641#endif // wxUSE_THREADS
642 while (!Pending() && ProcessIdle())
643 {
644 HandleSockets();
645 wxUsleep(10);
646 }
647 HandleSockets();
648 if (Pending())
649 DoMessage();
650 else
651 wxUsleep(10);
652
653 }
654 return (int)svCurrentMsg.mp1;
655} // end of wxApp::MainLoop
656
657void wxApp::ExitMainLoop()
658{
659 ::WinPostMsg(NULL, WM_QUIT, 0, 0);
660} // end of wxApp::ExitMainLoop
661
662bool wxApp::Pending()
663{
664 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
665} // end of wxApp::Pending
666
667void wxApp::Dispatch()
668{
669 DoMessage();
670}
671
672//////////////////////////////////////////////////////////////////////////////
673//
674// Give all windows a chance to preprocess
675// the message. Some may have accelerator tables, or have
676// MDI complications.
677//
678//////////////////////////////////////////////////////////////////////////////
679bool wxApp::ProcessMessage(
680 WXMSG* pWxmsg
681)
682{
683 QMSG* pMsg = (PQMSG)pWxmsg;
684 HWND hWnd = pMsg->hwnd;
685 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
686 wxWindow* pWnd;
687
688 //
689 // Pass non-system timer messages to the wxTimerProc
690 //
691 if (pMsg->msg == WM_TIMER &&
692 (SHORT1FROMMP(pMsg->mp1) != TID_CURSOR &&
693 SHORT1FROMMP(pMsg->mp1) != TID_FLASHWINDOW &&
694 SHORT1FROMMP(pMsg->mp1) != TID_SCROLL &&
695 SHORT1FROMMP(pMsg->mp1) != 0x0000
696 ))
697 wxTimerProc(NULL, 0, (int)pMsg->mp1, 0);
698
699 //
700 // Allow the window to prevent certain messages from being
701 // translated/processed (this is currently used by wxTextCtrl to always
702 // grab Ctrl-C/V/X, even if they are also accelerators in some parent)
703 //
704 if (pWndThis && !pWndThis->OS2ShouldPreProcessMessage(pWxmsg))
705 {
706 return FALSE;
707 }
708
709 //
710 // For some composite controls (like a combobox), wndThis might be NULL
711 // because the subcontrol is not a wxWindow, but only the control itself
712 // is - try to catch this case
713 //
714 while (hWnd && !pWndThis)
715 {
716 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
717 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
718 }
719
720 //
721 // Try translations first; find the youngest window with
722 // a translation table. OS/2 has case sensative accels, so
723 // this block, coded by BK, removes that and helps make them
724 // case insensative.
725 //
726 if(pMsg->msg == WM_CHAR)
727 {
728 PBYTE pChmsg = (PBYTE)&(pMsg->msg);
729 USHORT uSch = CHARMSG(pChmsg)->chr;
730 bool bRc;
731
732 //
733 // Do not process keyup events
734 //
735 if(!(CHARMSG(pChmsg)->fs & KC_KEYUP))
736 {
737 if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0)
738 CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
739
740
741 for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
742 {
743 if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
744 break;
745 }
746
747 if(!bRc) // untranslated, should restore original value
748 CHARMSG(pChmsg)->chr = uSch;
749 }
750 }
751 //
752 // Anyone for a non-translation message? Try youngest descendants first.
753 //
754// for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
755// {
756// if (pWnd->OS2ProcessMessage(pWxmsg))
757// return TRUE;
758// }
759 return FALSE;
760} // end of wxApp::ProcessMessage
761
762bool gbInOnIdle = FALSE;
763
764void wxApp::OnIdle(
765 wxIdleEvent& rEvent
766)
767{
768
769 //
770 // Avoid recursion (via ProcessEvent default case)
771 //
772 if (gbInOnIdle)
773 return;
774
775 gbInOnIdle = TRUE;
776
777 wxAppBase::OnIdle(event);
778
779#if wxUSE_DC_CACHEING
780 // automated DC cache management: clear the cached DCs and bitmap
781 // if it's likely that the app has finished with them, that is, we
782 // get an idle event and we're not dragging anything.
783 if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &&
784 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &&
785 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2))
786 wxDC::ClearCache();
787#endif // wxUSE_DC_CACHEING
788
789 gbInOnIdle = FALSE;
790} // end of wxApp::OnIdle
791
792void wxApp::OnEndSession(
793 wxCloseEvent& WXUNUSED(rEvent))
794{
795 if (GetTopWindow())
796 GetTopWindow()->Close(TRUE);
797} // end of wxApp::OnEndSession
798
799//
800// Default behaviour: close the application with prompts. The
801// user can veto the close, and therefore the end session.
802//
803void wxApp::OnQueryEndSession(
804 wxCloseEvent& rEvent
805)
806{
807 if (GetTopWindow())
808 {
809 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
810 rEvent.Veto(TRUE);
811 }
812} // end of wxApp::OnQueryEndSession
813
814void wxApp::Exit()
815{
816 wxApp::CleanUp();
817
818 // VZ: must really exit somehow, insert appropriate OS/2 syscall (FIXME)
819 wxAppConsole::Exit();
820} // end of wxExit
821
822//
823// Yield to incoming messages
824//
825bool wxApp::Yield(bool onlyIfNeeded)
826{
827 static bool s_inYield = FALSE;
828
829 if ( s_inYield )
830 {
831 if ( !onlyIfNeeded )
832 {
833 wxFAIL_MSG( _T("wxYield() called recursively") );
834 }
835
836 return FALSE;
837 }
838
839 HAB vHab = 0;
840 QMSG vMsg;
841
842 //
843 // Disable log flushing from here because a call to wxYield() shouldn't
844 // normally result in message boxes popping up &c
845 //
846 wxLog::Suspend();
847
848 s_inYield = TRUE;
849
850 //
851 // We want to go back to the main message loop
852 // if we see a WM_QUIT. (?)
853 //
854 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
855 {
856#if wxUSE_THREADS
857 wxMutexGuiLeaveOrEnter();
858#endif // wxUSE_THREADS
859 if (!wxTheApp->DoMessage())
860 break;
861 }
862 //
863 // If they are pending events, we must process them.
864 //
865 if (wxTheApp)
866 wxTheApp->ProcessPendingEvents();
867
868 HandleSockets();
869 //
870 // Let the logs be flashed again
871 //
872 wxLog::Resume();
873 s_inYield = FALSE;
874 return TRUE;
875} // end of wxYield
876
877int wxApp::AddSocketHandler(int handle, int mask,
878 void (*callback)(void*), void * gsock)
879{
880 int find;
881 struct GsocketCallbackInfo
882 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
883
884 for (find = 0; find < m_maxSocketHandles; find++)
885 if (CallbackInfo[find].handle == -1)
886 break;
887 if (find == m_maxSocketHandles)
888 {
889 // Allocate new memory
890 m_sockCallbackInfo = realloc(m_sockCallbackInfo,
891 (m_maxSocketHandles+=10)*
892 sizeof(struct GsocketCallbackInfo));
893 CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
894 for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++)
895 CallbackInfo[find].handle = -1;
896 find = m_maxSocketHandles - 10;
897 }
898 CallbackInfo[find].proc = callback;
899 CallbackInfo[find].type = mask;
900 CallbackInfo[find].handle = handle;
901 CallbackInfo[find].gsock = gsock;
902 if (mask & wxSockReadMask)
903 FD_SET(handle, &m_readfds);
904 if (mask & wxSockWriteMask)
905 FD_SET(handle, &m_writefds);
906 if (handle >= m_maxSocketNr)
907 m_maxSocketNr = handle + 1;
908 return find;
909}
910
911void wxApp::RemoveSocketHandler(int handle)
912{
913 struct GsocketCallbackInfo
914 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
915 if (handle < m_maxSocketHandles)
916 {
917 if (CallbackInfo[handle].type & wxSockReadMask)
918 FD_CLR(CallbackInfo[handle].handle, &m_readfds);
919 if (CallbackInfo[handle].type & wxSockWriteMask)
920 FD_CLR(CallbackInfo[handle].handle, &m_writefds);
921 CallbackInfo[handle].handle = -1;
922 }
923}
924
925//-----------------------------------------------------------------------------
926// wxWakeUpIdle
927//-----------------------------------------------------------------------------
928
929void wxApp::WakeUpIdle()
930{
931 //
932 // Send the top window a dummy message so idle handler processing will
933 // start up again. Doing it this way ensures that the idle handler
934 // wakes up in the right thread (see also wxWakeUpMainThread() which does
935 // the same for the main app thread only)
936 //
937 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
938
939 if (pTopWindow)
940 {
941 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
942 {
943 //
944 // Should never happen
945 //
946 wxLogLastError("PostMessage(WM_NULL)");
947 }
948 }
949} // end of wxWakeUpIdle
950
951HAB wxGetInstance()
952{
953 return vHabmain;
954}
955
956void wxSetInstance(
957 HAB vHab
958)
959{
960 vHabmain = vHab;
961}
962