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