]> git.saurik.com Git - wxWidgets.git/blame - src/os2/app.cpp
Applied patch [ 805147 ] GDI objects are not deselected from DC
[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;
3958ae62
SN
169 timeout.tv_sec = 0;
170 timeout.tv_usec = 0;
171 if ( select(m_maxSocketNr, &readfds, &writefds, 0, &timeout) > 0)
172 {
5c9ee6dd
SN
173 for (i = m_lastUsedHandle + 1; i != m_lastUsedHandle;
174 (i < m_maxSocketNr - 1) ? i++ : (i = 0))
3958ae62 175 {
3958ae62
SN
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);
29d83fc1 187 pendingEvent = TRUE;
3958ae62
SN
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);
29d83fc1 200 pendingEvent = TRUE;
3958ae62
SN
201 }
202 }
203 }
204 m_lastUsedHandle = i;
205 }
206 if (pendingEvent)
5c9ee6dd 207 ProcessPendingEvents();
3958ae62
SN
208 }
209}
d88de032
DW
210// ---------------------------------------------------------------------------
211// wxApp
212// ---------------------------------------------------------------------------
213
d88de032 214 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
0e320a79 215
d88de032
DW
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()
0e320a79 221
8df85a61
DW
222//
223// Initialize
224//
05e2b077 225bool wxApp::Initialize(int& argc, wxChar **argv)
0e320a79 226{
94826170
VZ
227 if ( !wxAppBase::Initialize(argc, argv) )
228 return false;
229
7e99520b
DW
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
54ffa107
DW
252 //
253 // OS2 has to have an anchorblock
254 //
94826170
VZ
255 vHabmain = WinInitialize(0);
256
257 if (!vHabmain)
258 {
259 // TODO: at least give some error message here...
260 wxAppBase::CleanUp();
54ffa107 261
54ffa107 262 return FALSE;
94826170
VZ
263 }
264
265 wxBuffer = new wxChar[1500]; // FIXME; why?
54ffa107
DW
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
d88de032
DW
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.
1b3d5e55 277#if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
d88de032
DW
278 extern char wxDummyChar;
279 if (wxDummyChar) wxDummyChar++;
280#endif
281
61243a51 282 // wxSetKeyboardHook(TRUE);
d88de032 283
459073a9 284 RegisterWindowClasses(vHabmain);
94826170 285
d88de032 286 return TRUE;
8df85a61 287} // end of wxApp::Initialize
d88de032 288
7e99520b 289const char* CANTREGISTERCLASS = " Can't register Class ";
d88de032
DW
290// ---------------------------------------------------------------------------
291// RegisterWindowClasses
292// ---------------------------------------------------------------------------
293
9ed0fac8
DW
294bool wxApp::RegisterWindowClasses(
295 HAB vHab
296)
d88de032 297{
914589c2
DW
298 ERRORID vError = 0L;
299 wxString sError;
3b9e3455 300
f23208ca
DW
301 if (!::WinRegisterClass( vHab
302 ,wxFrameClassName
51c1d535 303 ,wxFrameWndProc
f9efbe3a 304 ,CS_SIZEREDRAW | CS_SYNCPAINT
a0606634 305 ,sizeof(ULONG)
f23208ca 306 ))
d88de032 307 {
914589c2
DW
308 vError = ::WinGetLastError(vHab);
309 sError = wxPMErrorToStr(vError);
310 wxLogLastError(sError);
d88de032
DW
311 return FALSE;
312 }
313
f23208ca
DW
314 if (!::WinRegisterClass( vHab
315 ,wxFrameClassNameNoRedraw
51c1d535 316 ,wxWndProc
f23208ca 317 ,0
51c1d535 318 ,sizeof(ULONG)
f23208ca 319 ))
d88de032 320 {
914589c2
DW
321 vError = ::WinGetLastError(vHab);
322 sError = wxPMErrorToStr(vError);
323 wxLogLastError(sError);
d88de032
DW
324 return FALSE;
325 }
326
f23208ca
DW
327 if (!::WinRegisterClass( vHab
328 ,wxMDIFrameClassName
51c1d535 329 ,wxWndProc
f6bcfd97 330 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
51c1d535 331 ,sizeof(ULONG)
f23208ca 332 ))
d88de032 333 {
914589c2
DW
334 vError = ::WinGetLastError(vHab);
335 sError = wxPMErrorToStr(vError);
336 wxLogLastError(sError);
d88de032
DW
337 return FALSE;
338 }
0e320a79 339
f23208ca
DW
340 if (!::WinRegisterClass( vHab
341 ,wxMDIFrameClassNameNoRedraw
51c1d535 342 ,wxWndProc
f23208ca 343 ,0
51c1d535 344 ,sizeof(ULONG)
f23208ca 345 ))
d88de032 346 {
914589c2
DW
347 vError = ::WinGetLastError(vHab);
348 sError = wxPMErrorToStr(vError);
349 wxLogLastError(sError);
d88de032
DW
350 return FALSE;
351 }
352
f23208ca
DW
353 if (!::WinRegisterClass( vHab
354 ,wxMDIChildFrameClassName
51c1d535 355 ,wxWndProc
f23208ca 356 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
51c1d535 357 ,sizeof(ULONG)
f23208ca 358 ))
d88de032 359 {
914589c2
DW
360 vError = ::WinGetLastError(vHab);
361 sError = wxPMErrorToStr(vError);
362 wxLogLastError(sError);
d88de032
DW
363 return FALSE;
364 }
365
f23208ca
DW
366 if (!::WinRegisterClass( vHab
367 ,wxMDIChildFrameClassNameNoRedraw
51c1d535 368 ,wxWndProc
f23208ca 369 ,CS_HITTEST
51c1d535 370 ,sizeof(ULONG)
f23208ca 371 ))
d88de032 372 {
914589c2
DW
373 vError = ::WinGetLastError(vHab);
374 sError = wxPMErrorToStr(vError);
375 wxLogLastError(sError);
d88de032
DW
376 return FALSE;
377 }
378
f23208ca
DW
379 if (!::WinRegisterClass( vHab
380 ,wxPanelClassName
51c1d535 381 ,wxWndProc
f23208ca 382 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
51c1d535 383 ,sizeof(ULONG)
f23208ca 384 ))
d88de032 385 {
914589c2
DW
386 vError = ::WinGetLastError(vHab);
387 sError = wxPMErrorToStr(vError);
388 wxLogLastError(sError);
d88de032
DW
389 return FALSE;
390 }
391
f23208ca
DW
392 if (!::WinRegisterClass( vHab
393 ,wxCanvasClassName
51c1d535 394 ,wxWndProc
54ffa107 395 ,CS_SIZEREDRAW | CS_HITTEST | CS_SYNCPAINT
51c1d535 396 ,sizeof(ULONG)
f23208ca 397 ))
d88de032 398 {
914589c2
DW
399 vError = ::WinGetLastError(vHab);
400 sError = wxPMErrorToStr(vError);
401 wxLogLastError(sError);
d88de032
DW
402 return FALSE;
403 }
0256cfeb
DW
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 }
d88de032 416 return TRUE;
8df85a61 417} // end of wxApp::RegisterWindowClasses
d88de032 418
8df85a61
DW
419//
420// Cleans up any wxWindows internal structures left lying around
421//
0e320a79
DW
422void wxApp::CleanUp()
423{
d88de032
DW
424 delete[] wxBuffer;
425 wxBuffer = NULL;
0e320a79 426
8df85a61
DW
427 //
428 // PM-SPECIFIC CLEANUP
429 //
0e320a79 430
61243a51 431 // wxSetKeyboardHook(FALSE);
9ed0fac8 432
d88de032 433 if (wxSTD_FRAME_ICON)
9ed0fac8 434 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
d88de032 435 if (wxSTD_MDICHILDFRAME_ICON)
9ed0fac8 436 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
d88de032 437 if (wxSTD_MDIPARENTFRAME_ICON)
9ed0fac8 438 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
d88de032
DW
439
440 if (wxDEFAULT_FRAME_ICON)
9ed0fac8 441 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
d88de032 442 if (wxDEFAULT_MDICHILDFRAME_ICON)
9ed0fac8 443 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
d88de032 444 if (wxDEFAULT_MDIPARENTFRAME_ICON)
9ed0fac8
DW
445 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
446
d88de032
DW
447 if ( wxDisableButtonBrush )
448 {
449// TODO: ::DeleteObject( wxDisableButtonBrush );
450 }
451
452 if (wxWinHandleList)
453 delete wxWinHandleList;
454
468e327a
SN
455 // Delete Message queue
456 if (wxTheApp->m_hMq)
457 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
458
94826170 459 wxAppBase::CleanUp();
8df85a61 460} // end of wxApp::CleanUp
0e320a79 461
9ed0fac8 462bool wxApp::OnInitGui()
d88de032 463{
914589c2
DW
464 ERRORID vError;
465 wxString sError;
77cd51c3 466
19193a2c
KB
467 if (!wxAppBase::OnInitGui())
468 return FALSE;
469
f23208ca 470 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
914589c2
DW
471 if (!m_hMq)
472 {
473 vError = ::WinGetLastError(vHabmain);
474 sError = wxPMErrorToStr(vError);
475 wxLogDebug(sError);
476 return FALSE;
477 }
19193a2c 478
9ed0fac8 479 return TRUE;
8df85a61 480} // end of wxApp::OnInitGui
0e320a79 481
0e320a79
DW
482wxApp::wxApp()
483{
d88de032
DW
484 argc = 0;
485 argv = NULL;
9ed0fac8 486 m_nPrintMode = wxPRINT_WINDOWS;
468e327a 487 m_hMq = 0;
3958ae62
SN
488 m_maxSocketHandles = 0;
489 m_maxSocketNr = 0;
490 m_sockCallbackInfo = 0;
8df85a61 491} // end of wxApp::wxApp
d88de032
DW
492
493wxApp::~wxApp()
494{
8df85a61 495 //
d88de032 496 // Delete command-line args
8df85a61 497 //
039bec17 498#if wxUSE_UNICODE
8df85a61
DW
499 int i;
500
d88de032
DW
501 for (i = 0; i < argc; i++)
502 {
503 delete[] argv[i];
504 }
505 delete[] argv;
039bec17 506#endif
8df85a61 507} // end of wxApp::~wxApp
0e320a79
DW
508
509bool wxApp::Initialized()
510{
d88de032
DW
511 if (GetTopWindow())
512 return TRUE;
513 else
514 return FALSE;
8df85a61 515} // end of wxApp::Initialized
0e320a79 516
9ed0fac8
DW
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//
3958ae62 521
d88de032
DW
522bool wxApp::DoMessage()
523{
468e327a 524 BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
9ed0fac8
DW
525
526 if (bRc == 0)
d88de032
DW
527 {
528 // got WM_QUIT
9ed0fac8 529 m_bKeepGoing = FALSE;
d88de032
DW
530 return FALSE;
531 }
9ed0fac8 532 else if (bRc == -1)
d88de032
DW
533 {
534 // should never happen, but let's test for it nevertheless
535 wxLogLastError("GetMessage");
536 }
537 else
538 {
539#if wxUSE_THREADS
9ed0fac8
DW
540 wxASSERT_MSG( wxThread::IsMain()
541 ,wxT("only the main thread can process Windows messages")
542 );
d88de032 543
9ed0fac8
DW
544 static bool sbHadGuiLock = TRUE;
545 static wxMsgArray svSavedMessages;
d88de032 546
9ed0fac8 547 //
8df85a61 548 // If a secondary thread owns is doing GUI calls, save all messages for
d88de032
DW
549 // later processing - we can't process them right now because it will
550 // lead to recursive library calls (and we're not reentrant)
9ed0fac8
DW
551 //
552 if (!wxGuiOwnedByMainThread())
d88de032 553 {
9ed0fac8 554 sbHadGuiLock = FALSE;
d88de032 555
8df85a61
DW
556 //
557 // Leave out WM_COMMAND messages: too dangerous, sometimes
d88de032 558 // the message will be processed twice
8df85a61 559 //
d88de032 560 if ( !wxIsWaitingForThread() ||
9ed0fac8 561 svCurrentMsg.msg != WM_COMMAND )
d88de032 562 {
9ed0fac8 563 svSavedMessages.Add(svCurrentMsg);
d88de032 564 }
d88de032
DW
565 return TRUE;
566 }
567 else
568 {
9ed0fac8 569 //
8df85a61 570 // Have we just regained the GUI lock? if so, post all of the saved
d88de032
DW
571 // messages
572 //
9ed0fac8 573 if (!sbHadGuiLock )
d88de032 574 {
9ed0fac8 575 sbHadGuiLock = TRUE;
d88de032 576
9ed0fac8
DW
577 size_t nCount = svSavedMessages.Count();
578
579 for (size_t n = 0; n < nCount; n++)
d88de032 580 {
9ed0fac8 581 QMSG vMsg = svSavedMessages[n];
d88de032 582
ed2b77fc 583 DoMessage((WXMSG*)&vMsg);
d88de032 584 }
9ed0fac8 585 svSavedMessages.Empty();
d88de032
DW
586 }
587 }
d88de032
DW
588#endif // wxUSE_THREADS
589
3febf684 590 //
d88de032 591 // Process the message
3febf684
DW
592 //
593 DoMessage((WXMSG *)&svCurrentMsg);
d88de032 594 }
d88de032 595 return TRUE;
8df85a61 596} // end of wxApp::DoMessage
d88de032 597
3febf684
DW
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
9ed0fac8
DW
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//////////////////////////////////////////////////////////////////////////////
0e320a79
DW
623int wxApp::MainLoop()
624{
9ed0fac8 625 m_bKeepGoing = TRUE;
d88de032 626
9ed0fac8 627 while (m_bKeepGoing)
d88de032
DW
628 {
629#if wxUSE_THREADS
630 wxMutexGuiLeaveOrEnter();
631#endif // wxUSE_THREADS
3958ae62 632 while (!Pending() && ProcessIdle())
5b3ed311 633 {
3958ae62 634 HandleSockets();
5c9ee6dd 635 wxUsleep(10);
5b3ed311 636 }
3958ae62
SN
637 HandleSockets();
638 if (Pending())
639 DoMessage();
640 else
5c9ee6dd 641 wxUsleep(10);
3958ae62 642
d88de032 643 }
9ed0fac8 644 return (int)svCurrentMsg.mp1;
8df85a61 645} // end of wxApp::MainLoop
0e320a79 646
0e320a79
DW
647void wxApp::ExitMainLoop()
648{
a23692f0
DW
649 ::WinPostMsg(NULL, WM_QUIT, 0, 0);
650} // end of wxApp::ExitMainLoop
0e320a79 651
0e320a79
DW
652bool wxApp::Pending()
653{
43543d98 654 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
a23692f0 655} // end of wxApp::Pending
0e320a79 656
0e320a79
DW
657void wxApp::Dispatch()
658{
d88de032 659 DoMessage();
0e320a79
DW
660}
661
9ed0fac8
DW
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)
0e320a79 672{
f6bcfd97
BP
673 QMSG* pMsg = (PQMSG)pWxmsg;
674 HWND hWnd = pMsg->hwnd;
9ed0fac8
DW
675 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
676 wxWindow* pWnd;
d88de032 677
05a8bfed 678 //
e58dab20 679 // Pass non-system timer messages to the wxTimerProc
05a8bfed 680 //
e58dab20
DW
681 if (pMsg->msg == WM_TIMER &&
682 (SHORT1FROMMP(pMsg->mp1) != TID_CURSOR &&
683 SHORT1FROMMP(pMsg->mp1) != TID_FLASHWINDOW &&
b3260bce
DW
684 SHORT1FROMMP(pMsg->mp1) != TID_SCROLL &&
685 SHORT1FROMMP(pMsg->mp1) != 0x0000
e58dab20 686 ))
496fd9fb 687 wxTimerProc(NULL, 0, (int)pMsg->mp1, 0);
05a8bfed 688
54ffa107
DW
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
9ed0fac8 699 //
8df85a61 700 // For some composite controls (like a combobox), wndThis might be NULL
d88de032
DW
701 // because the subcontrol is not a wxWindow, but only the control itself
702 // is - try to catch this case
9ed0fac8
DW
703 //
704 while (hWnd && !pWndThis)
d88de032 705 {
9ed0fac8
DW
706 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
707 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
d88de032 708 }
0e320a79 709
f6bcfd97
BP
710 //
711 // Try translations first; find the youngest window with
f09d8a3b
DW
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.
f6bcfd97 715 //
f09d8a3b 716 if(pMsg->msg == WM_CHAR)
f6bcfd97 717 {
f09d8a3b
DW
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)
f1f22049 728 CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
f09d8a3b 729
7e99520b 730
5b3ed311
DW
731 for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
732 {
733 if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
734 break;
735 }
7e99520b 736
f09d8a3b
DW
737 if(!bRc) // untranslated, should restore original value
738 CHARMSG(pChmsg)->chr = uSch;
739 }
f6bcfd97 740 }
8df85a61 741 //
d88de032 742 // Anyone for a non-translation message? Try youngest descendants first.
8df85a61 743 //
e604d44b
DW
744// for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
745// {
746// if (pWnd->OS2ProcessMessage(pWxmsg))
747// return TRUE;
748// }
d88de032 749 return FALSE;
8df85a61 750} // end of wxApp::ProcessMessage
0e320a79 751
2b5f62a0
VZ
752bool gbInOnIdle = FALSE;
753
9ed0fac8
DW
754void wxApp::OnIdle(
755 wxIdleEvent& rEvent
756)
d88de032 757{
d88de032 758
9ed0fac8 759 //
d88de032 760 // Avoid recursion (via ProcessEvent default case)
9ed0fac8 761 //
2b5f62a0 762 if (gbInOnIdle)
d88de032 763 return;
0e320a79 764
2b5f62a0 765 gbInOnIdle = TRUE;
955a9197 766
459073a9 767 wxAppBase::OnIdle(rEvent);
0e320a79 768
893758d5
DW
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.
19193a2c
KB
773 if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &&
774 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &&
775 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2))
893758d5
DW
776 wxDC::ClearCache();
777#endif // wxUSE_DC_CACHEING
778
2b5f62a0 779 gbInOnIdle = FALSE;
8df85a61 780} // end of wxApp::OnIdle
9779893b 781
9ed0fac8
DW
782void wxApp::OnEndSession(
783 wxCloseEvent& WXUNUSED(rEvent))
0e320a79 784{
d88de032
DW
785 if (GetTopWindow())
786 GetTopWindow()->Close(TRUE);
8df85a61 787} // end of wxApp::OnEndSession
0e320a79 788
9ed0fac8 789//
d88de032
DW
790// Default behaviour: close the application with prompts. The
791// user can veto the close, and therefore the end session.
9ed0fac8
DW
792//
793void wxApp::OnQueryEndSession(
794 wxCloseEvent& rEvent
795)
0e320a79 796{
d88de032
DW
797 if (GetTopWindow())
798 {
9ed0fac8
DW
799 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
800 rEvent.Veto(TRUE);
d88de032 801 }
8df85a61 802} // end of wxApp::OnQueryEndSession
0e320a79 803
e2478fde 804void wxApp::Exit()
0e320a79 805{
d88de032 806 wxApp::CleanUp();
e2478fde
VZ
807
808 // VZ: must really exit somehow, insert appropriate OS/2 syscall (FIXME)
809 wxAppConsole::Exit();
ee453a16 810} // end of wxExit
0e320a79 811
8df85a61 812//
d88de032 813// Yield to incoming messages
8df85a61 814//
8461e4c2 815bool wxApp::Yield(bool onlyIfNeeded)
0e320a79 816{
8461e4c2
VZ
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
9dea36ef 829 HAB vHab = 0;
dde11e60 830 QMSG vMsg;
ee453a16 831
8df85a61
DW
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
8461e4c2 838 s_inYield = TRUE;
8b63ae37 839
8df85a61 840 //
d88de032
DW
841 // We want to go back to the main message loop
842 // if we see a WM_QUIT. (?)
8df85a61 843 //
dde11e60 844 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
d88de032 845 {
8df85a61
DW
846#if wxUSE_THREADS
847 wxMutexGuiLeaveOrEnter();
848#endif // wxUSE_THREADS
dde11e60 849 if (!wxTheApp->DoMessage())
d88de032
DW
850 break;
851 }
8df85a61 852 //
d88de032 853 // If they are pending events, we must process them.
8df85a61
DW
854 //
855 if (wxTheApp)
856 wxTheApp->ProcessPendingEvents();
857
5c9ee6dd 858 HandleSockets();
8df85a61
DW
859 //
860 // Let the logs be flashed again
861 //
862 wxLog::Resume();
8461e4c2 863 s_inYield = FALSE;
d88de032 864 return TRUE;
8df85a61 865} // end of wxYield
d88de032 866
3958ae62
SN
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
8df85a61
DW
915//-----------------------------------------------------------------------------
916// wxWakeUpIdle
917//-----------------------------------------------------------------------------
918
e2478fde 919void wxApp::WakeUpIdle()
8df85a61
DW
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
d88de032 940
76990f63 941HAB wxGetInstance()
d88de032 942{
76990f63 943 return vHabmain;
d88de032
DW
944}
945
76990f63
DW
946void wxSetInstance(
947 HAB vHab
948)
d88de032 949{
76990f63 950 vHabmain = vHab;
0e320a79
DW
951}
952