wxUsleep is supposed to sleep _milli_seconds, not _micro_seconds.
[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(vHab);
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 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
469 bool 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
489 wxApp::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
503 wxApp::~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
519 bool 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
532 bool 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
608 void 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 //////////////////////////////////////////////////////////////////////////////
633 int 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
657 void wxApp::ExitMainLoop()
658 {
659 ::WinPostMsg(NULL, WM_QUIT, 0, 0);
660 } // end of wxApp::ExitMainLoop
661
662 bool wxApp::Pending()
663 {
664 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
665 } // end of wxApp::Pending
666
667 void 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 //////////////////////////////////////////////////////////////////////////////
679 bool 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
762 bool gbInOnIdle = FALSE;
763
764 void 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
792 void 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 //
803 void 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
814 void 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 //
825 bool 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
877 int 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
911 void 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
929 void 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
951 HAB wxGetInstance()
952 {
953 return vHabmain;
954 }
955
956 void wxSetInstance(
957 HAB vHab
958 )
959 {
960 vHabmain = vHab;
961 }
962