]> git.saurik.com Git - wxWidgets.git/blame - src/os2/app.cpp
fixed VC++ warning in release build
[wxWidgets.git] / src / os2 / app.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
3// Purpose: wxApp
d88de032 4// Author: David Webster
0e320a79 5// Modified by:
d88de032 6// Created: 10/13/99
0e320a79 7// RCS-ID: $Id$
d88de032
DW
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
272ebf16
SN
12#ifdef __GNUG__
13 #pragma implementation "app.h"
14#endif
15
d88de032
DW
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"
cb21bd1b
SN
34 #include "wx/wxchar.h"
35 #include "wx/icon.h"
36 #include "wx/timer.h"
0e320a79
DW
37#endif
38
0e320a79
DW
39#include "wx/log.h"
40#include "wx/module.h"
d88de032
DW
41
42#include "wx/os2/private.h"
43
29d83fc1
DW
44#ifdef __EMX__
45
19193a2c
KB
46#include <sys/ioctl.h>
47#include <sys/select.h>
29d83fc1
DW
48
49#else
50
65b851bb 51#include <nerrno.h>
19193a2c
KB
52#include <sys/ioctl.h>
53#include <sys/select.h>
54#include <sys/time.h>
29d83fc1 55
19193a2c 56#endif //
29d83fc1 57
3958ae62 58#ifndef __EMX__
29d83fc1 59
3958ae62 60#define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
19193a2c
KB
61extern "C" int _System bsdselect(int,
62 struct fd_set *,
63 struct fd_set *,
64 struct fd_set *,
65 struct timeval *);
3958ae62
SN
66#endif
67
d88de032
DW
68#if wxUSE_THREADS
69 #include "wx/thread.h"
70
9ed0fac8
DW
71 // define the array of QMSG strutures
72 WX_DECLARE_OBJARRAY(QMSG, wxMsgArray);
d88de032
DW
73
74 #include "wx/arrimpl.cpp"
75
9ed0fac8 76 WX_DEFINE_OBJARRAY(wxMsgArray);
d88de032 77#endif // wxUSE_THREADS
0e320a79 78
8df85a61
DW
79#if wxUSE_TOOLTIPS
80 #include "wx/tooltip.h"
81#endif // wxUSE_TOOLTIPS
82
0e320a79 83#include <string.h>
d88de032
DW
84#include <ctype.h>
85
86// ---------------------------------------------------------------------------
87// global variables
88// ---------------------------------------------------------------------------
89
9ed0fac8 90extern wxChar* wxBuffer;
9ed0fac8
DW
91extern wxList* wxWinHandleList;
92extern wxList WXDLLEXPORT wxPendingDelete;
9ed0fac8 93extern wxCursor* g_globalCursor;
0e320a79 94
8df85a61 95HAB vHabmain = NULLHANDLE;
9ed0fac8 96QMSG svCurrentMsg;
d88de032 97
d88de032 98
9ed0fac8
DW
99HICON wxSTD_FRAME_ICON = (HICON) NULL;
100HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
d88de032
DW
101HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
102
9ed0fac8
DW
103HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
104HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
105HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
d88de032
DW
106
107HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
108
51c1d535
DW
109MRESULT EXPENTRY wxWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
110MRESULT EXPENTRY wxFrameWndProc( HWND hWnd,ULONG message,MPARAM mp1,MPARAM mp2);
111
d88de032
DW
112// ===========================================================================
113// implementation
114// ===========================================================================
115
3958ae62
SN
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
29d83fc1 131#ifdef __EMX__
3958ae62
SN
132extern "C"
133int wxAppAddSocketHandler(int handle, int mask,
29d83fc1 134 void (*callback)(void*), void * gsock)
3958ae62
SN
135{
136 return wxTheApp->AddSocketHandler(handle, mask, callback, gsock);
137}
3958ae62
SN
138extern "C"
139void wxAppRemoveSocketHandler(int handle)
140{
141 wxTheApp->RemoveSocketHandler(handle);
142}
29d83fc1
DW
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
3958ae62
SN
155
156void wxApp::HandleSockets()
157{
29d83fc1 158 bool pendingEvent = FALSE;
3958ae62
SN
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);
29d83fc1 189 pendingEvent = TRUE;
3958ae62
SN
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);
29d83fc1 203 pendingEvent = TRUE;
3958ae62
SN
204 wxYield();
205 }
206 }
207 }
208 m_lastUsedHandle = i;
209 }
210 if (pendingEvent)
211 wxYield();
212 }
213}
d88de032
DW
214// ---------------------------------------------------------------------------
215// wxApp
216// ---------------------------------------------------------------------------
217
d88de032 218 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
0e320a79 219
d88de032
DW
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()
0e320a79 225
8df85a61
DW
226//
227// Initialize
228//
05e2b077 229bool wxApp::Initialize(int& argc, wxChar **argv)
0e320a79 230{
94826170
VZ
231 if ( !wxAppBase::Initialize(argc, argv) )
232 return false;
233
7e99520b
DW
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
54ffa107
DW
256 //
257 // OS2 has to have an anchorblock
258 //
94826170
VZ
259 vHabmain = WinInitialize(0);
260
261 if (!vHabmain)
262 {
263 // TODO: at least give some error message here...
264 wxAppBase::CleanUp();
54ffa107 265
54ffa107 266 return FALSE;
94826170
VZ
267 }
268
269 wxBuffer = new wxChar[1500]; // FIXME; why?
54ffa107
DW
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
d88de032
DW
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.
1b3d5e55 281#if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
d88de032
DW
282 extern char wxDummyChar;
283 if (wxDummyChar) wxDummyChar++;
284#endif
285
61243a51 286 // wxSetKeyboardHook(TRUE);
d88de032 287
54ffa107 288 RegisterWindowClasses(vHab);
94826170 289
d88de032 290 return TRUE;
8df85a61 291} // end of wxApp::Initialize
d88de032 292
7e99520b 293const char* CANTREGISTERCLASS = " Can't register Class ";
d88de032
DW
294// ---------------------------------------------------------------------------
295// RegisterWindowClasses
296// ---------------------------------------------------------------------------
297
9ed0fac8
DW
298bool wxApp::RegisterWindowClasses(
299 HAB vHab
300)
d88de032 301{
914589c2
DW
302 ERRORID vError = 0L;
303 wxString sError;
3b9e3455 304
f23208ca
DW
305 if (!::WinRegisterClass( vHab
306 ,wxFrameClassName
51c1d535 307 ,wxFrameWndProc
f9efbe3a 308 ,CS_SIZEREDRAW | CS_SYNCPAINT
a0606634 309 ,sizeof(ULONG)
f23208ca 310 ))
d88de032 311 {
914589c2
DW
312 vError = ::WinGetLastError(vHab);
313 sError = wxPMErrorToStr(vError);
314 wxLogLastError(sError);
d88de032
DW
315 return FALSE;
316 }
317
f23208ca
DW
318 if (!::WinRegisterClass( vHab
319 ,wxFrameClassNameNoRedraw
51c1d535 320 ,wxWndProc
f23208ca 321 ,0
51c1d535 322 ,sizeof(ULONG)
f23208ca 323 ))
d88de032 324 {
914589c2
DW
325 vError = ::WinGetLastError(vHab);
326 sError = wxPMErrorToStr(vError);
327 wxLogLastError(sError);
d88de032
DW
328 return FALSE;
329 }
330
f23208ca
DW
331 if (!::WinRegisterClass( vHab
332 ,wxMDIFrameClassName
51c1d535 333 ,wxWndProc
f6bcfd97 334 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
51c1d535 335 ,sizeof(ULONG)
f23208ca 336 ))
d88de032 337 {
914589c2
DW
338 vError = ::WinGetLastError(vHab);
339 sError = wxPMErrorToStr(vError);
340 wxLogLastError(sError);
d88de032
DW
341 return FALSE;
342 }
0e320a79 343
f23208ca
DW
344 if (!::WinRegisterClass( vHab
345 ,wxMDIFrameClassNameNoRedraw
51c1d535 346 ,wxWndProc
f23208ca 347 ,0
51c1d535 348 ,sizeof(ULONG)
f23208ca 349 ))
d88de032 350 {
914589c2
DW
351 vError = ::WinGetLastError(vHab);
352 sError = wxPMErrorToStr(vError);
353 wxLogLastError(sError);
d88de032
DW
354 return FALSE;
355 }
356
f23208ca
DW
357 if (!::WinRegisterClass( vHab
358 ,wxMDIChildFrameClassName
51c1d535 359 ,wxWndProc
f23208ca 360 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
51c1d535 361 ,sizeof(ULONG)
f23208ca 362 ))
d88de032 363 {
914589c2
DW
364 vError = ::WinGetLastError(vHab);
365 sError = wxPMErrorToStr(vError);
366 wxLogLastError(sError);
d88de032
DW
367 return FALSE;
368 }
369
f23208ca
DW
370 if (!::WinRegisterClass( vHab
371 ,wxMDIChildFrameClassNameNoRedraw
51c1d535 372 ,wxWndProc
f23208ca 373 ,CS_HITTEST
51c1d535 374 ,sizeof(ULONG)
f23208ca 375 ))
d88de032 376 {
914589c2
DW
377 vError = ::WinGetLastError(vHab);
378 sError = wxPMErrorToStr(vError);
379 wxLogLastError(sError);
d88de032
DW
380 return FALSE;
381 }
382
f23208ca
DW
383 if (!::WinRegisterClass( vHab
384 ,wxPanelClassName
51c1d535 385 ,wxWndProc
f23208ca 386 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
51c1d535 387 ,sizeof(ULONG)
f23208ca 388 ))
d88de032 389 {
914589c2
DW
390 vError = ::WinGetLastError(vHab);
391 sError = wxPMErrorToStr(vError);
392 wxLogLastError(sError);
d88de032
DW
393 return FALSE;
394 }
395
f23208ca
DW
396 if (!::WinRegisterClass( vHab
397 ,wxCanvasClassName
51c1d535 398 ,wxWndProc
54ffa107 399 ,CS_SIZEREDRAW | CS_HITTEST | CS_SYNCPAINT
51c1d535 400 ,sizeof(ULONG)
f23208ca 401 ))
d88de032 402 {
914589c2
DW
403 vError = ::WinGetLastError(vHab);
404 sError = wxPMErrorToStr(vError);
405 wxLogLastError(sError);
d88de032
DW
406 return FALSE;
407 }
0256cfeb
DW
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 }
d88de032 420 return TRUE;
8df85a61 421} // end of wxApp::RegisterWindowClasses
d88de032 422
8df85a61
DW
423//
424// Cleans up any wxWindows internal structures left lying around
425//
0e320a79
DW
426void wxApp::CleanUp()
427{
d88de032
DW
428 delete[] wxBuffer;
429 wxBuffer = NULL;
0e320a79 430
8df85a61
DW
431 //
432 // PM-SPECIFIC CLEANUP
433 //
0e320a79 434
61243a51 435 // wxSetKeyboardHook(FALSE);
9ed0fac8 436
d88de032 437 if (wxSTD_FRAME_ICON)
9ed0fac8 438 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
d88de032 439 if (wxSTD_MDICHILDFRAME_ICON)
9ed0fac8 440 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
d88de032 441 if (wxSTD_MDIPARENTFRAME_ICON)
9ed0fac8 442 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
d88de032
DW
443
444 if (wxDEFAULT_FRAME_ICON)
9ed0fac8 445 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
d88de032 446 if (wxDEFAULT_MDICHILDFRAME_ICON)
9ed0fac8 447 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
d88de032 448 if (wxDEFAULT_MDIPARENTFRAME_ICON)
9ed0fac8
DW
449 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
450
d88de032
DW
451 if ( wxDisableButtonBrush )
452 {
453// TODO: ::DeleteObject( wxDisableButtonBrush );
454 }
455
456 if (wxWinHandleList)
457 delete wxWinHandleList;
458
d88de032 459 delete wxPendingEvents;
8df85a61 460#if wxUSE_THREADS
d88de032
DW
461 delete wxPendingEventsLocker;
462 // If we don't do the following, we get an apparent memory leak.
463 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
464#endif
0e320a79 465
468e327a
SN
466 // Delete Message queue
467 if (wxTheApp->m_hMq)
468 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
469
94826170 470 wxAppBase::CleanUp();
8df85a61 471} // end of wxApp::CleanUp
0e320a79 472
9ed0fac8 473bool wxApp::OnInitGui()
d88de032 474{
914589c2
DW
475 ERRORID vError;
476 wxString sError;
77cd51c3 477
19193a2c
KB
478 if (!wxAppBase::OnInitGui())
479 return FALSE;
480
f23208ca 481 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
914589c2
DW
482 if (!m_hMq)
483 {
484 vError = ::WinGetLastError(vHabmain);
485 sError = wxPMErrorToStr(vError);
486 wxLogDebug(sError);
487 return FALSE;
488 }
19193a2c 489
9ed0fac8 490 return TRUE;
8df85a61 491} // end of wxApp::OnInitGui
0e320a79 492
0e320a79
DW
493wxApp::wxApp()
494{
d88de032
DW
495 m_topWindow = NULL;
496 wxTheApp = this;
d88de032
DW
497
498 argc = 0;
499 argv = NULL;
9ed0fac8 500 m_nPrintMode = wxPRINT_WINDOWS;
9ed0fac8 501 m_bAuto3D = TRUE;
468e327a 502 m_hMq = 0;
3958ae62
SN
503 m_maxSocketHandles = 0;
504 m_maxSocketNr = 0;
505 m_sockCallbackInfo = 0;
8df85a61 506} // end of wxApp::wxApp
d88de032
DW
507
508wxApp::~wxApp()
509{
8df85a61 510 //
d88de032 511 // Delete command-line args
8df85a61 512 //
039bec17 513#if wxUSE_UNICODE
8df85a61
DW
514 int i;
515
d88de032
DW
516 for (i = 0; i < argc; i++)
517 {
518 delete[] argv[i];
519 }
520 delete[] argv;
039bec17 521#endif
8df85a61 522} // end of wxApp::~wxApp
0e320a79
DW
523
524bool wxApp::Initialized()
525{
d88de032
DW
526 if (GetTopWindow())
527 return TRUE;
528 else
529 return FALSE;
8df85a61 530} // end of wxApp::Initialized
0e320a79 531
9ed0fac8
DW
532//
533// Get and process a message, returning FALSE if WM_QUIT
534// received (and also set the flag telling the app to exit the main loop)
535//
3958ae62 536
d88de032
DW
537bool wxApp::DoMessage()
538{
468e327a 539 BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
9ed0fac8
DW
540
541 if (bRc == 0)
d88de032
DW
542 {
543 // got WM_QUIT
9ed0fac8 544 m_bKeepGoing = FALSE;
d88de032
DW
545 return FALSE;
546 }
9ed0fac8 547 else if (bRc == -1)
d88de032
DW
548 {
549 // should never happen, but let's test for it nevertheless
550 wxLogLastError("GetMessage");
551 }
552 else
553 {
554#if wxUSE_THREADS
9ed0fac8
DW
555 wxASSERT_MSG( wxThread::IsMain()
556 ,wxT("only the main thread can process Windows messages")
557 );
d88de032 558
9ed0fac8
DW
559 static bool sbHadGuiLock = TRUE;
560 static wxMsgArray svSavedMessages;
d88de032 561
9ed0fac8 562 //
8df85a61 563 // If a secondary thread owns is doing GUI calls, save all messages for
d88de032
DW
564 // later processing - we can't process them right now because it will
565 // lead to recursive library calls (and we're not reentrant)
9ed0fac8
DW
566 //
567 if (!wxGuiOwnedByMainThread())
d88de032 568 {
9ed0fac8 569 sbHadGuiLock = FALSE;
d88de032 570
8df85a61
DW
571 //
572 // Leave out WM_COMMAND messages: too dangerous, sometimes
d88de032 573 // the message will be processed twice
8df85a61 574 //
d88de032 575 if ( !wxIsWaitingForThread() ||
9ed0fac8 576 svCurrentMsg.msg != WM_COMMAND )
d88de032 577 {
9ed0fac8 578 svSavedMessages.Add(svCurrentMsg);
d88de032 579 }
d88de032
DW
580 return TRUE;
581 }
582 else
583 {
9ed0fac8 584 //
8df85a61 585 // Have we just regained the GUI lock? if so, post all of the saved
d88de032
DW
586 // messages
587 //
9ed0fac8 588 if (!sbHadGuiLock )
d88de032 589 {
9ed0fac8 590 sbHadGuiLock = TRUE;
d88de032 591
9ed0fac8
DW
592 size_t nCount = svSavedMessages.Count();
593
594 for (size_t n = 0; n < nCount; n++)
d88de032 595 {
9ed0fac8 596 QMSG vMsg = svSavedMessages[n];
d88de032 597
ed2b77fc 598 DoMessage((WXMSG*)&vMsg);
d88de032 599 }
9ed0fac8 600 svSavedMessages.Empty();
d88de032
DW
601 }
602 }
d88de032
DW
603#endif // wxUSE_THREADS
604
3febf684 605 //
d88de032 606 // Process the message
3febf684
DW
607 //
608 DoMessage((WXMSG *)&svCurrentMsg);
d88de032 609 }
d88de032 610 return TRUE;
8df85a61 611} // end of wxApp::DoMessage
d88de032 612
3febf684
DW
613void wxApp::DoMessage(
614 WXMSG* pMsg
615)
616{
617 if (!ProcessMessage((WXMSG *)&svCurrentMsg))
618 {
619 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
620 }
621} // end of wxApp::DoMessage
622
9ed0fac8
DW
623//////////////////////////////////////////////////////////////////////////////
624//
625// Keep trying to process messages until WM_QUIT
626// received.
627//
628// If there are messages to be processed, they will all be
629// processed and OnIdle will not be called.
630// When there are no more messages, OnIdle is called.
631// If OnIdle requests more time,
632// it will be repeatedly called so long as there are no pending messages.
633// A 'feature' of this is that once OnIdle has decided that no more processing
634// is required, then it won't get processing time until further messages
635// are processed (it'll sit in DoMessage).
636//
637//////////////////////////////////////////////////////////////////////////////
0e320a79
DW
638int wxApp::MainLoop()
639{
9ed0fac8 640 m_bKeepGoing = TRUE;
d88de032 641
9ed0fac8 642 while (m_bKeepGoing)
d88de032
DW
643 {
644#if wxUSE_THREADS
645 wxMutexGuiLeaveOrEnter();
646#endif // wxUSE_THREADS
3958ae62 647 while (!Pending() && ProcessIdle())
5b3ed311 648 {
3958ae62
SN
649 HandleSockets();
650 wxUsleep(10000);
5b3ed311 651 }
3958ae62
SN
652 HandleSockets();
653 if (Pending())
654 DoMessage();
655 else
656 wxUsleep(10000);
657
d88de032 658 }
9ed0fac8 659 return (int)svCurrentMsg.mp1;
8df85a61 660} // end of wxApp::MainLoop
0e320a79 661
9ed0fac8 662//
0e320a79 663// Returns TRUE if more time is needed.
9ed0fac8 664//
0e320a79
DW
665bool wxApp::ProcessIdle()
666{
9ed0fac8 667 wxIdleEvent vEvent;
0e320a79 668
9ed0fac8
DW
669 vEvent.SetEventObject(this);
670 ProcessEvent(vEvent);
671 return vEvent.MoreRequested();
8df85a61 672} // end of wxApp::ProcessIdle
d88de032 673
0e320a79
DW
674void wxApp::ExitMainLoop()
675{
a23692f0
DW
676 ::WinPostMsg(NULL, WM_QUIT, 0, 0);
677} // end of wxApp::ExitMainLoop
0e320a79 678
0e320a79
DW
679bool wxApp::Pending()
680{
43543d98 681 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
a23692f0 682} // end of wxApp::Pending
0e320a79 683
0e320a79
DW
684void wxApp::Dispatch()
685{
d88de032 686 DoMessage();
0e320a79
DW
687}
688
9ed0fac8
DW
689//////////////////////////////////////////////////////////////////////////////
690//
691// Give all windows a chance to preprocess
692// the message. Some may have accelerator tables, or have
693// MDI complications.
694//
695//////////////////////////////////////////////////////////////////////////////
696bool wxApp::ProcessMessage(
697 WXMSG* pWxmsg
698)
0e320a79 699{
f6bcfd97
BP
700 QMSG* pMsg = (PQMSG)pWxmsg;
701 HWND hWnd = pMsg->hwnd;
9ed0fac8
DW
702 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
703 wxWindow* pWnd;
d88de032 704
05a8bfed 705 //
e58dab20 706 // Pass non-system timer messages to the wxTimerProc
05a8bfed 707 //
e58dab20
DW
708 if (pMsg->msg == WM_TIMER &&
709 (SHORT1FROMMP(pMsg->mp1) != TID_CURSOR &&
710 SHORT1FROMMP(pMsg->mp1) != TID_FLASHWINDOW &&
b3260bce
DW
711 SHORT1FROMMP(pMsg->mp1) != TID_SCROLL &&
712 SHORT1FROMMP(pMsg->mp1) != 0x0000
e58dab20 713 ))
496fd9fb 714 wxTimerProc(NULL, 0, (int)pMsg->mp1, 0);
05a8bfed 715
54ffa107
DW
716 //
717 // Allow the window to prevent certain messages from being
718 // translated/processed (this is currently used by wxTextCtrl to always
719 // grab Ctrl-C/V/X, even if they are also accelerators in some parent)
720 //
721 if (pWndThis && !pWndThis->OS2ShouldPreProcessMessage(pWxmsg))
722 {
723 return FALSE;
724 }
725
9ed0fac8 726 //
8df85a61 727 // For some composite controls (like a combobox), wndThis might be NULL
d88de032
DW
728 // because the subcontrol is not a wxWindow, but only the control itself
729 // is - try to catch this case
9ed0fac8
DW
730 //
731 while (hWnd && !pWndThis)
d88de032 732 {
9ed0fac8
DW
733 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
734 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
d88de032 735 }
0e320a79 736
f6bcfd97
BP
737 //
738 // Try translations first; find the youngest window with
f09d8a3b
DW
739 // a translation table. OS/2 has case sensative accels, so
740 // this block, coded by BK, removes that and helps make them
741 // case insensative.
f6bcfd97 742 //
f09d8a3b 743 if(pMsg->msg == WM_CHAR)
f6bcfd97 744 {
f09d8a3b
DW
745 PBYTE pChmsg = (PBYTE)&(pMsg->msg);
746 USHORT uSch = CHARMSG(pChmsg)->chr;
747 bool bRc;
748
749 //
750 // Do not process keyup events
751 //
752 if(!(CHARMSG(pChmsg)->fs & KC_KEYUP))
753 {
754 if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0)
f1f22049 755 CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
f09d8a3b 756
7e99520b 757
5b3ed311
DW
758 for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
759 {
760 if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
761 break;
762 }
7e99520b 763
f09d8a3b
DW
764 if(!bRc) // untranslated, should restore original value
765 CHARMSG(pChmsg)->chr = uSch;
766 }
f6bcfd97 767 }
8df85a61 768 //
d88de032 769 // Anyone for a non-translation message? Try youngest descendants first.
8df85a61 770 //
e604d44b
DW
771// for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
772// {
773// if (pWnd->OS2ProcessMessage(pWxmsg))
774// return TRUE;
775// }
d88de032 776 return FALSE;
8df85a61 777} // end of wxApp::ProcessMessage
0e320a79 778
2b5f62a0
VZ
779bool gbInOnIdle = FALSE;
780
9ed0fac8
DW
781void wxApp::OnIdle(
782 wxIdleEvent& rEvent
783)
d88de032 784{
d88de032 785
9ed0fac8 786 //
d88de032 787 // Avoid recursion (via ProcessEvent default case)
9ed0fac8 788 //
2b5f62a0 789 if (gbInOnIdle)
d88de032 790 return;
0e320a79 791
2b5f62a0 792 gbInOnIdle = TRUE;
0e320a79 793
8df85a61
DW
794 //
795 // If there are pending events, we must process them: pending events
796 // are either events to the threads other than main or events posted
797 // with wxPostEvent() functions
798 //
799 ProcessPendingEvents();
800
9ed0fac8 801 //
d88de032 802 // 'Garbage' collection of windows deleted with Close().
9ed0fac8 803 //
d88de032 804 DeletePendingObjects();
0e320a79 805
d88de032 806#if wxUSE_LOG
8df85a61
DW
807 //
808 // Flush the logged messages if any
809 //
810 wxLog::FlushActive();
d88de032 811#endif // wxUSE_LOG
0e320a79 812
893758d5
DW
813#if wxUSE_DC_CACHEING
814 // automated DC cache management: clear the cached DCs and bitmap
815 // if it's likely that the app has finished with them, that is, we
816 // get an idle event and we're not dragging anything.
19193a2c
KB
817 if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &&
818 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &&
819 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2))
893758d5
DW
820 wxDC::ClearCache();
821#endif // wxUSE_DC_CACHEING
822
8df85a61 823 //
d88de032 824 // Send OnIdle events to all windows
8df85a61 825 //
9ed0fac8 826 if (SendIdleEvents())
d88de032 827 {
9ed0fac8 828 //
d88de032
DW
829 // SendIdleEvents() returns TRUE if at least one window requested more
830 // idle events
9ed0fac8
DW
831 //
832 rEvent.RequestMore(TRUE);
d88de032 833 }
2b5f62a0 834 gbInOnIdle = FALSE;
8df85a61 835} // end of wxApp::OnIdle
9779893b 836
0e320a79
DW
837// Send idle event to all top-level windows
838bool wxApp::SendIdleEvents()
839{
9ed0fac8
DW
840 bool bNeedMore = FALSE;
841 wxWindowList::Node* pNode = wxTopLevelWindows.GetFirst();
d88de032 842
9ed0fac8 843 while (pNode)
d88de032 844 {
9ed0fac8 845 wxWindow* pWin = pNode->GetData();
0e320a79 846
9ed0fac8
DW
847 if (SendIdleEvents(pWin))
848 bNeedMore = TRUE;
849 pNode = pNode->GetNext();
850 }
851 return bNeedMore;
8df85a61 852} // end of wxApp::SendIdleEvents
0e320a79 853
9ed0fac8 854//
0e320a79 855// Send idle event to window and all subwindows
9ed0fac8
DW
856//
857bool wxApp::SendIdleEvents(
858 wxWindow* pWin
859)
0e320a79 860{
9ed0fac8
DW
861 bool bNeedMore = FALSE;
862 wxIdleEvent vEvent;
863
864 vEvent.SetEventObject(pWin);
865 pWin->GetEventHandler()->ProcessEvent(vEvent);
0e320a79 866
9ed0fac8
DW
867 if (vEvent.MoreRequested())
868 bNeedMore = TRUE;
0e320a79 869
9ed0fac8 870 wxNode* pNode = pWin->GetChildren().First();
0e320a79 871
9ed0fac8 872 while (pNode)
d88de032 873 {
9ed0fac8 874 wxWindow* pWin = (wxWindow*) pNode->Data();
0e320a79 875
9ed0fac8
DW
876 if (SendIdleEvents(pWin))
877 bNeedMore = TRUE;
878 pNode = pNode->Next();
d88de032 879 }
9ed0fac8 880 return bNeedMore;
8df85a61 881} // end of wxApp::SendIdleEvents
0e320a79 882
9ed0fac8
DW
883void wxApp::OnEndSession(
884 wxCloseEvent& WXUNUSED(rEvent))
0e320a79 885{
d88de032
DW
886 if (GetTopWindow())
887 GetTopWindow()->Close(TRUE);
8df85a61 888} // end of wxApp::OnEndSession
0e320a79 889
9ed0fac8 890//
d88de032
DW
891// Default behaviour: close the application with prompts. The
892// user can veto the close, and therefore the end session.
9ed0fac8
DW
893//
894void wxApp::OnQueryEndSession(
895 wxCloseEvent& rEvent
896)
0e320a79 897{
d88de032
DW
898 if (GetTopWindow())
899 {
9ed0fac8
DW
900 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
901 rEvent.Veto(TRUE);
d88de032 902 }
8df85a61 903} // end of wxApp::OnQueryEndSession
0e320a79 904
e2478fde 905void wxApp::Exit()
0e320a79 906{
d88de032 907 wxApp::CleanUp();
e2478fde
VZ
908
909 // VZ: must really exit somehow, insert appropriate OS/2 syscall (FIXME)
910 wxAppConsole::Exit();
ee453a16 911} // end of wxExit
0e320a79 912
8df85a61 913//
d88de032 914// Yield to incoming messages
8df85a61 915//
8461e4c2 916bool wxApp::Yield(bool onlyIfNeeded)
0e320a79 917{
8461e4c2
VZ
918 static bool s_inYield = FALSE;
919
920 if ( s_inYield )
921 {
922 if ( !onlyIfNeeded )
923 {
924 wxFAIL_MSG( _T("wxYield() called recursively") );
925 }
926
927 return FALSE;
928 }
929
9dea36ef 930 HAB vHab = 0;
dde11e60 931 QMSG vMsg;
ee453a16 932
8df85a61
DW
933 //
934 // Disable log flushing from here because a call to wxYield() shouldn't
935 // normally result in message boxes popping up &c
936 //
937 wxLog::Suspend();
938
8461e4c2 939 s_inYield = TRUE;
8b63ae37 940
8df85a61 941 //
d88de032
DW
942 // We want to go back to the main message loop
943 // if we see a WM_QUIT. (?)
8df85a61 944 //
dde11e60 945 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
d88de032 946 {
8df85a61
DW
947#if wxUSE_THREADS
948 wxMutexGuiLeaveOrEnter();
949#endif // wxUSE_THREADS
dde11e60 950 if (!wxTheApp->DoMessage())
d88de032
DW
951 break;
952 }
8df85a61 953 //
d88de032 954 // If they are pending events, we must process them.
8df85a61
DW
955 //
956 if (wxTheApp)
957 wxTheApp->ProcessPendingEvents();
958
959 //
960 // Let the logs be flashed again
961 //
962 wxLog::Resume();
8461e4c2 963 s_inYield = FALSE;
d88de032 964 return TRUE;
8df85a61 965} // end of wxYield
d88de032 966
3958ae62
SN
967int wxApp::AddSocketHandler(int handle, int mask,
968 void (*callback)(void*), void * gsock)
969{
970 int find;
971 struct GsocketCallbackInfo
972 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
973
974 for (find = 0; find < m_maxSocketHandles; find++)
975 if (CallbackInfo[find].handle == -1)
976 break;
977 if (find == m_maxSocketHandles)
978 {
979 // Allocate new memory
980 m_sockCallbackInfo = realloc(m_sockCallbackInfo,
981 (m_maxSocketHandles+=10)*
982 sizeof(struct GsocketCallbackInfo));
983 CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
984 for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++)
985 CallbackInfo[find].handle = -1;
986 find = m_maxSocketHandles - 10;
987 }
988 CallbackInfo[find].proc = callback;
989 CallbackInfo[find].type = mask;
990 CallbackInfo[find].handle = handle;
991 CallbackInfo[find].gsock = gsock;
992 if (mask & wxSockReadMask)
993 FD_SET(handle, &m_readfds);
994 if (mask & wxSockWriteMask)
995 FD_SET(handle, &m_writefds);
996 if (handle >= m_maxSocketNr)
997 m_maxSocketNr = handle + 1;
998 return find;
999}
1000
1001void wxApp::RemoveSocketHandler(int handle)
1002{
1003 struct GsocketCallbackInfo
1004 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
1005 if (handle < m_maxSocketHandles)
1006 {
1007 if (CallbackInfo[handle].type & wxSockReadMask)
1008 FD_CLR(CallbackInfo[handle].handle, &m_readfds);
1009 if (CallbackInfo[handle].type & wxSockWriteMask)
1010 FD_CLR(CallbackInfo[handle].handle, &m_writefds);
1011 CallbackInfo[handle].handle = -1;
1012 }
1013}
1014
8df85a61
DW
1015//-----------------------------------------------------------------------------
1016// wxWakeUpIdle
1017//-----------------------------------------------------------------------------
1018
e2478fde 1019void wxApp::WakeUpIdle()
8df85a61
DW
1020{
1021 //
1022 // Send the top window a dummy message so idle handler processing will
1023 // start up again. Doing it this way ensures that the idle handler
1024 // wakes up in the right thread (see also wxWakeUpMainThread() which does
1025 // the same for the main app thread only)
1026 //
1027 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
1028
1029 if (pTopWindow)
1030 {
1031 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
1032 {
1033 //
1034 // Should never happen
1035 //
1036 wxLogLastError("PostMessage(WM_NULL)");
1037 }
1038 }
1039} // end of wxWakeUpIdle
d88de032 1040
76990f63 1041HAB wxGetInstance()
d88de032 1042{
76990f63 1043 return vHabmain;
d88de032
DW
1044}
1045
76990f63
DW
1046void wxSetInstance(
1047 HAB vHab
1048)
d88de032 1049{
76990f63 1050 vHabmain = vHab;
0e320a79
DW
1051}
1052