]> git.saurik.com Git - wxWidgets.git/blame - src/os2/app.cpp
fixed text control creation broken by my MacPreControlCreate() change
[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
54ffa107 284 RegisterWindowClasses(vHab);
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
d88de032 455 delete wxPendingEvents;
8df85a61 456#if wxUSE_THREADS
d88de032
DW
457 delete wxPendingEventsLocker;
458 // If we don't do the following, we get an apparent memory leak.
459 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
460#endif
0e320a79 461
468e327a
SN
462 // Delete Message queue
463 if (wxTheApp->m_hMq)
464 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
465
94826170 466 wxAppBase::CleanUp();
8df85a61 467} // end of wxApp::CleanUp
0e320a79 468
9ed0fac8 469bool wxApp::OnInitGui()
d88de032 470{
914589c2
DW
471 ERRORID vError;
472 wxString sError;
77cd51c3 473
19193a2c
KB
474 if (!wxAppBase::OnInitGui())
475 return FALSE;
476
f23208ca 477 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
914589c2
DW
478 if (!m_hMq)
479 {
480 vError = ::WinGetLastError(vHabmain);
481 sError = wxPMErrorToStr(vError);
482 wxLogDebug(sError);
483 return FALSE;
484 }
19193a2c 485
9ed0fac8 486 return TRUE;
8df85a61 487} // end of wxApp::OnInitGui
0e320a79 488
0e320a79
DW
489wxApp::wxApp()
490{
d88de032
DW
491 m_topWindow = NULL;
492 wxTheApp = this;
d88de032
DW
493
494 argc = 0;
495 argv = NULL;
9ed0fac8 496 m_nPrintMode = wxPRINT_WINDOWS;
468e327a 497 m_hMq = 0;
3958ae62
SN
498 m_maxSocketHandles = 0;
499 m_maxSocketNr = 0;
500 m_sockCallbackInfo = 0;
8df85a61 501} // end of wxApp::wxApp
d88de032
DW
502
503wxApp::~wxApp()
504{
8df85a61 505 //
d88de032 506 // Delete command-line args
8df85a61 507 //
039bec17 508#if wxUSE_UNICODE
8df85a61
DW
509 int i;
510
d88de032
DW
511 for (i = 0; i < argc; i++)
512 {
513 delete[] argv[i];
514 }
515 delete[] argv;
039bec17 516#endif
8df85a61 517} // end of wxApp::~wxApp
0e320a79
DW
518
519bool wxApp::Initialized()
520{
d88de032
DW
521 if (GetTopWindow())
522 return TRUE;
523 else
524 return FALSE;
8df85a61 525} // end of wxApp::Initialized
0e320a79 526
9ed0fac8
DW
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//
3958ae62 531
d88de032
DW
532bool wxApp::DoMessage()
533{
468e327a 534 BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
9ed0fac8
DW
535
536 if (bRc == 0)
d88de032
DW
537 {
538 // got WM_QUIT
9ed0fac8 539 m_bKeepGoing = FALSE;
d88de032
DW
540 return FALSE;
541 }
9ed0fac8 542 else if (bRc == -1)
d88de032
DW
543 {
544 // should never happen, but let's test for it nevertheless
545 wxLogLastError("GetMessage");
546 }
547 else
548 {
549#if wxUSE_THREADS
9ed0fac8
DW
550 wxASSERT_MSG( wxThread::IsMain()
551 ,wxT("only the main thread can process Windows messages")
552 );
d88de032 553
9ed0fac8
DW
554 static bool sbHadGuiLock = TRUE;
555 static wxMsgArray svSavedMessages;
d88de032 556
9ed0fac8 557 //
8df85a61 558 // If a secondary thread owns is doing GUI calls, save all messages for
d88de032
DW
559 // later processing - we can't process them right now because it will
560 // lead to recursive library calls (and we're not reentrant)
9ed0fac8
DW
561 //
562 if (!wxGuiOwnedByMainThread())
d88de032 563 {
9ed0fac8 564 sbHadGuiLock = FALSE;
d88de032 565
8df85a61
DW
566 //
567 // Leave out WM_COMMAND messages: too dangerous, sometimes
d88de032 568 // the message will be processed twice
8df85a61 569 //
d88de032 570 if ( !wxIsWaitingForThread() ||
9ed0fac8 571 svCurrentMsg.msg != WM_COMMAND )
d88de032 572 {
9ed0fac8 573 svSavedMessages.Add(svCurrentMsg);
d88de032 574 }
d88de032
DW
575 return TRUE;
576 }
577 else
578 {
9ed0fac8 579 //
8df85a61 580 // Have we just regained the GUI lock? if so, post all of the saved
d88de032
DW
581 // messages
582 //
9ed0fac8 583 if (!sbHadGuiLock )
d88de032 584 {
9ed0fac8 585 sbHadGuiLock = TRUE;
d88de032 586
9ed0fac8
DW
587 size_t nCount = svSavedMessages.Count();
588
589 for (size_t n = 0; n < nCount; n++)
d88de032 590 {
9ed0fac8 591 QMSG vMsg = svSavedMessages[n];
d88de032 592
ed2b77fc 593 DoMessage((WXMSG*)&vMsg);
d88de032 594 }
9ed0fac8 595 svSavedMessages.Empty();
d88de032
DW
596 }
597 }
d88de032
DW
598#endif // wxUSE_THREADS
599
3febf684 600 //
d88de032 601 // Process the message
3febf684
DW
602 //
603 DoMessage((WXMSG *)&svCurrentMsg);
d88de032 604 }
d88de032 605 return TRUE;
8df85a61 606} // end of wxApp::DoMessage
d88de032 607
3febf684
DW
608void 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
9ed0fac8
DW
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//////////////////////////////////////////////////////////////////////////////
0e320a79
DW
633int wxApp::MainLoop()
634{
9ed0fac8 635 m_bKeepGoing = TRUE;
d88de032 636
9ed0fac8 637 while (m_bKeepGoing)
d88de032
DW
638 {
639#if wxUSE_THREADS
640 wxMutexGuiLeaveOrEnter();
641#endif // wxUSE_THREADS
3958ae62 642 while (!Pending() && ProcessIdle())
5b3ed311 643 {
3958ae62 644 HandleSockets();
5c9ee6dd 645 wxUsleep(10);
5b3ed311 646 }
3958ae62
SN
647 HandleSockets();
648 if (Pending())
649 DoMessage();
650 else
5c9ee6dd 651 wxUsleep(10);
3958ae62 652
d88de032 653 }
9ed0fac8 654 return (int)svCurrentMsg.mp1;
8df85a61 655} // end of wxApp::MainLoop
0e320a79 656
0e320a79
DW
657void wxApp::ExitMainLoop()
658{
a23692f0
DW
659 ::WinPostMsg(NULL, WM_QUIT, 0, 0);
660} // end of wxApp::ExitMainLoop
0e320a79 661
0e320a79
DW
662bool wxApp::Pending()
663{
43543d98 664 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
a23692f0 665} // end of wxApp::Pending
0e320a79 666
0e320a79
DW
667void wxApp::Dispatch()
668{
d88de032 669 DoMessage();
0e320a79
DW
670}
671
9ed0fac8
DW
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//////////////////////////////////////////////////////////////////////////////
679bool wxApp::ProcessMessage(
680 WXMSG* pWxmsg
681)
0e320a79 682{
f6bcfd97
BP
683 QMSG* pMsg = (PQMSG)pWxmsg;
684 HWND hWnd = pMsg->hwnd;
9ed0fac8
DW
685 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
686 wxWindow* pWnd;
d88de032 687
05a8bfed 688 //
e58dab20 689 // Pass non-system timer messages to the wxTimerProc
05a8bfed 690 //
e58dab20
DW
691 if (pMsg->msg == WM_TIMER &&
692 (SHORT1FROMMP(pMsg->mp1) != TID_CURSOR &&
693 SHORT1FROMMP(pMsg->mp1) != TID_FLASHWINDOW &&
b3260bce
DW
694 SHORT1FROMMP(pMsg->mp1) != TID_SCROLL &&
695 SHORT1FROMMP(pMsg->mp1) != 0x0000
e58dab20 696 ))
496fd9fb 697 wxTimerProc(NULL, 0, (int)pMsg->mp1, 0);
05a8bfed 698
54ffa107
DW
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
9ed0fac8 709 //
8df85a61 710 // For some composite controls (like a combobox), wndThis might be NULL
d88de032
DW
711 // because the subcontrol is not a wxWindow, but only the control itself
712 // is - try to catch this case
9ed0fac8
DW
713 //
714 while (hWnd && !pWndThis)
d88de032 715 {
9ed0fac8
DW
716 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
717 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
d88de032 718 }
0e320a79 719
f6bcfd97
BP
720 //
721 // Try translations first; find the youngest window with
f09d8a3b
DW
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.
f6bcfd97 725 //
f09d8a3b 726 if(pMsg->msg == WM_CHAR)
f6bcfd97 727 {
f09d8a3b
DW
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)
f1f22049 738 CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
f09d8a3b 739
7e99520b 740
5b3ed311
DW
741 for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
742 {
743 if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
744 break;
745 }
7e99520b 746
f09d8a3b
DW
747 if(!bRc) // untranslated, should restore original value
748 CHARMSG(pChmsg)->chr = uSch;
749 }
f6bcfd97 750 }
8df85a61 751 //
d88de032 752 // Anyone for a non-translation message? Try youngest descendants first.
8df85a61 753 //
e604d44b
DW
754// for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
755// {
756// if (pWnd->OS2ProcessMessage(pWxmsg))
757// return TRUE;
758// }
d88de032 759 return FALSE;
8df85a61 760} // end of wxApp::ProcessMessage
0e320a79 761
2b5f62a0
VZ
762bool gbInOnIdle = FALSE;
763
9ed0fac8
DW
764void wxApp::OnIdle(
765 wxIdleEvent& rEvent
766)
d88de032 767{
d88de032 768
9ed0fac8 769 //
d88de032 770 // Avoid recursion (via ProcessEvent default case)
9ed0fac8 771 //
2b5f62a0 772 if (gbInOnIdle)
d88de032 773 return;
0e320a79 774
2b5f62a0 775 gbInOnIdle = TRUE;
955a9197
JS
776
777 wxAppBase::OnIdle(event);
0e320a79 778
893758d5
DW
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.
19193a2c
KB
783 if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &&
784 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &&
785 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2))
893758d5
DW
786 wxDC::ClearCache();
787#endif // wxUSE_DC_CACHEING
788
2b5f62a0 789 gbInOnIdle = FALSE;
8df85a61 790} // end of wxApp::OnIdle
9779893b 791
9ed0fac8
DW
792void wxApp::OnEndSession(
793 wxCloseEvent& WXUNUSED(rEvent))
0e320a79 794{
d88de032
DW
795 if (GetTopWindow())
796 GetTopWindow()->Close(TRUE);
8df85a61 797} // end of wxApp::OnEndSession
0e320a79 798
9ed0fac8 799//
d88de032
DW
800// Default behaviour: close the application with prompts. The
801// user can veto the close, and therefore the end session.
9ed0fac8
DW
802//
803void wxApp::OnQueryEndSession(
804 wxCloseEvent& rEvent
805)
0e320a79 806{
d88de032
DW
807 if (GetTopWindow())
808 {
9ed0fac8
DW
809 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
810 rEvent.Veto(TRUE);
d88de032 811 }
8df85a61 812} // end of wxApp::OnQueryEndSession
0e320a79 813
e2478fde 814void wxApp::Exit()
0e320a79 815{
d88de032 816 wxApp::CleanUp();
e2478fde
VZ
817
818 // VZ: must really exit somehow, insert appropriate OS/2 syscall (FIXME)
819 wxAppConsole::Exit();
ee453a16 820} // end of wxExit
0e320a79 821
8df85a61 822//
d88de032 823// Yield to incoming messages
8df85a61 824//
8461e4c2 825bool wxApp::Yield(bool onlyIfNeeded)
0e320a79 826{
8461e4c2
VZ
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
9dea36ef 839 HAB vHab = 0;
dde11e60 840 QMSG vMsg;
ee453a16 841
8df85a61
DW
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
8461e4c2 848 s_inYield = TRUE;
8b63ae37 849
8df85a61 850 //
d88de032
DW
851 // We want to go back to the main message loop
852 // if we see a WM_QUIT. (?)
8df85a61 853 //
dde11e60 854 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
d88de032 855 {
8df85a61
DW
856#if wxUSE_THREADS
857 wxMutexGuiLeaveOrEnter();
858#endif // wxUSE_THREADS
dde11e60 859 if (!wxTheApp->DoMessage())
d88de032
DW
860 break;
861 }
8df85a61 862 //
d88de032 863 // If they are pending events, we must process them.
8df85a61
DW
864 //
865 if (wxTheApp)
866 wxTheApp->ProcessPendingEvents();
867
5c9ee6dd 868 HandleSockets();
8df85a61
DW
869 //
870 // Let the logs be flashed again
871 //
872 wxLog::Resume();
8461e4c2 873 s_inYield = FALSE;
d88de032 874 return TRUE;
8df85a61 875} // end of wxYield
d88de032 876
3958ae62
SN
877int 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
911void 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
8df85a61
DW
925//-----------------------------------------------------------------------------
926// wxWakeUpIdle
927//-----------------------------------------------------------------------------
928
e2478fde 929void wxApp::WakeUpIdle()
8df85a61
DW
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
d88de032 950
76990f63 951HAB wxGetInstance()
d88de032 952{
76990f63 953 return vHabmain;
d88de032
DW
954}
955
76990f63
DW
956void wxSetInstance(
957 HAB vHab
958)
d88de032 959{
76990f63 960 vHabmain = vHab;
0e320a79
DW
961}
962