]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/app.cpp
Applied patch [ 805147 ] GDI objects are not deselected from DC
[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(vHabmain);
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 Message queue
456 if (wxTheApp->m_hMq)
457 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
458
459 wxAppBase::CleanUp();
460} // end of wxApp::CleanUp
461
462bool 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
482wxApp::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
493wxApp::~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
509bool 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
522bool 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
598void 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//////////////////////////////////////////////////////////////////////////////
623int 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
647void wxApp::ExitMainLoop()
648{
649 ::WinPostMsg(NULL, WM_QUIT, 0, 0);
650} // end of wxApp::ExitMainLoop
651
652bool wxApp::Pending()
653{
654 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
655} // end of wxApp::Pending
656
657void wxApp::Dispatch()
658{
659 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//////////////////////////////////////////////////////////////////////////////
669bool 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
752bool gbInOnIdle = FALSE;
753
754void 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
782void 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//
793void 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
804void 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//
815bool 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
867int 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
901void 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
919void 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
941HAB wxGetInstance()
942{
943 return vHabmain;
944}
945
946void wxSetInstance(
947 HAB vHab
948)
949{
950 vHabmain = vHab;
951}
952