]> git.saurik.com Git - wxWidgets.git/blame - src/os2/app.cpp
function key support
[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//
9ed0fac8
DW
229bool wxApp::Initialize(
230 HAB vHab
231)
0e320a79 232{
7e99520b
DW
233#if defined(wxUSE_CONSOLEDEBUG)
234 #if wxUSE_CONSOLEDEBUG
235/***********************************************/
236/* Code for using stdout debug */
237/* To use it you mast link app as "Window" - EK*/
238/***********************************************/
239 {
240 PPIB pib;
241 PTIB tib;
242
243 printf("In console\n");
244
245 DosGetInfoBlocks(&tib, &pib);
246/* Try morphing into a PM application. */
247// if(pib->pib_ultype == 2) /* VIO */
248 pib->pib_ultype = 3;
249 }
250/**********************************************/
251/**********************************************/
252 #endif //wxUSE_CONSOLEDEBUG
253#endif
254
13a4ea8d 255 wxBuffer = new wxChar[1500]; // FIXME; why?
0e320a79 256
d88de032 257 wxClassInfo::InitializeClasses();
0e320a79 258
8df85a61
DW
259#if wxUSE_THREADS
260 wxPendingEventsLocker = new wxCriticalSection;
261#endif
262
d88de032
DW
263 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
264 wxTheColourDatabase->Initialize();
265
266 wxInitializeStockLists();
267 wxInitializeStockObjects();
0e320a79 268
d88de032
DW
269 wxBitmap::InitStandardHandlers();
270
54ffa107
DW
271 //
272 // OS2 has to have an anchorblock
273 //
274 vHab = WinInitialize(0);
275
276 if (!vHab)
277 return FALSE;
278 else
279 vHabmain = vHab;
280
281 // Some people may wish to use this, but
282 // probably it shouldn't be here by default.
283#ifdef __WXDEBUG__
284 // wxRedirectIOToConsole();
285#endif
286
d88de032
DW
287 wxWinHandleList = new wxList(wxKEY_INTEGER);
288
289 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
290 // PLEASE DO NOT ALTER THIS.
1b3d5e55 291#if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
d88de032
DW
292 extern char wxDummyChar;
293 if (wxDummyChar) wxDummyChar++;
294#endif
295
61243a51 296 // wxSetKeyboardHook(TRUE);
d88de032
DW
297
298 wxModule::RegisterModules();
299 if (!wxModule::InitializeModules())
300 return FALSE;
54ffa107 301 RegisterWindowClasses(vHab);
d88de032 302 return TRUE;
8df85a61 303} // end of wxApp::Initialize
d88de032 304
7e99520b 305const char* CANTREGISTERCLASS = " Can't register Class ";
d88de032
DW
306// ---------------------------------------------------------------------------
307// RegisterWindowClasses
308// ---------------------------------------------------------------------------
309
9ed0fac8
DW
310bool wxApp::RegisterWindowClasses(
311 HAB vHab
312)
d88de032 313{
914589c2
DW
314 ERRORID vError = 0L;
315 wxString sError;
3b9e3455 316
f23208ca
DW
317 if (!::WinRegisterClass( vHab
318 ,wxFrameClassName
51c1d535 319 ,wxFrameWndProc
f9efbe3a 320 ,CS_SIZEREDRAW | CS_SYNCPAINT
a0606634 321 ,sizeof(ULONG)
f23208ca 322 ))
d88de032 323 {
914589c2
DW
324 vError = ::WinGetLastError(vHab);
325 sError = wxPMErrorToStr(vError);
326 wxLogLastError(sError);
d88de032
DW
327 return FALSE;
328 }
329
f23208ca
DW
330 if (!::WinRegisterClass( vHab
331 ,wxFrameClassNameNoRedraw
51c1d535 332 ,wxWndProc
f23208ca 333 ,0
51c1d535 334 ,sizeof(ULONG)
f23208ca 335 ))
d88de032 336 {
914589c2
DW
337 vError = ::WinGetLastError(vHab);
338 sError = wxPMErrorToStr(vError);
339 wxLogLastError(sError);
d88de032
DW
340 return FALSE;
341 }
342
f23208ca
DW
343 if (!::WinRegisterClass( vHab
344 ,wxMDIFrameClassName
51c1d535 345 ,wxWndProc
f6bcfd97 346 ,CS_SIZEREDRAW | CS_MOVENOTIFY | CS_SYNCPAINT
51c1d535 347 ,sizeof(ULONG)
f23208ca 348 ))
d88de032 349 {
914589c2
DW
350 vError = ::WinGetLastError(vHab);
351 sError = wxPMErrorToStr(vError);
352 wxLogLastError(sError);
d88de032
DW
353 return FALSE;
354 }
0e320a79 355
f23208ca
DW
356 if (!::WinRegisterClass( vHab
357 ,wxMDIFrameClassNameNoRedraw
51c1d535 358 ,wxWndProc
f23208ca 359 ,0
51c1d535 360 ,sizeof(ULONG)
f23208ca 361 ))
d88de032 362 {
914589c2
DW
363 vError = ::WinGetLastError(vHab);
364 sError = wxPMErrorToStr(vError);
365 wxLogLastError(sError);
d88de032
DW
366 return FALSE;
367 }
368
f23208ca
DW
369 if (!::WinRegisterClass( vHab
370 ,wxMDIChildFrameClassName
51c1d535 371 ,wxWndProc
f23208ca 372 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
51c1d535 373 ,sizeof(ULONG)
f23208ca 374 ))
d88de032 375 {
914589c2
DW
376 vError = ::WinGetLastError(vHab);
377 sError = wxPMErrorToStr(vError);
378 wxLogLastError(sError);
d88de032
DW
379 return FALSE;
380 }
381
f23208ca
DW
382 if (!::WinRegisterClass( vHab
383 ,wxMDIChildFrameClassNameNoRedraw
51c1d535 384 ,wxWndProc
f23208ca 385 ,CS_HITTEST
51c1d535 386 ,sizeof(ULONG)
f23208ca 387 ))
d88de032 388 {
914589c2
DW
389 vError = ::WinGetLastError(vHab);
390 sError = wxPMErrorToStr(vError);
391 wxLogLastError(sError);
d88de032
DW
392 return FALSE;
393 }
394
f23208ca
DW
395 if (!::WinRegisterClass( vHab
396 ,wxPanelClassName
51c1d535 397 ,wxWndProc
f23208ca 398 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
51c1d535 399 ,sizeof(ULONG)
f23208ca 400 ))
d88de032 401 {
914589c2
DW
402 vError = ::WinGetLastError(vHab);
403 sError = wxPMErrorToStr(vError);
404 wxLogLastError(sError);
d88de032
DW
405 return FALSE;
406 }
407
f23208ca
DW
408 if (!::WinRegisterClass( vHab
409 ,wxCanvasClassName
51c1d535 410 ,wxWndProc
54ffa107 411 ,CS_SIZEREDRAW | CS_HITTEST | CS_SYNCPAINT
51c1d535 412 ,sizeof(ULONG)
f23208ca 413 ))
d88de032 414 {
914589c2
DW
415 vError = ::WinGetLastError(vHab);
416 sError = wxPMErrorToStr(vError);
417 wxLogLastError(sError);
d88de032
DW
418 return FALSE;
419 }
0256cfeb
DW
420 if (!::WinRegisterClass( vHab
421 ,wxCanvasClassNameNR
422 ,wxWndProc
423 ,CS_HITTEST | CS_SYNCPAINT
424 ,sizeof(ULONG)
425 ))
426 {
427 vError = ::WinGetLastError(vHab);
428 sError = wxPMErrorToStr(vError);
429 wxLogLastError(sError);
430 return FALSE;
431 }
d88de032 432 return TRUE;
8df85a61 433} // end of wxApp::RegisterWindowClasses
d88de032 434
8df85a61
DW
435//
436// Cleans up any wxWindows internal structures left lying around
437//
0e320a79
DW
438void wxApp::CleanUp()
439{
8df85a61
DW
440 //
441 // COMMON CLEANUP
442 //
d88de032
DW
443
444#if wxUSE_LOG
8df85a61
DW
445
446 //
447 // Flush the logged messages if any and install a 'safer' log target: the
d88de032
DW
448 // default one (wxLogGui) can't be used after the resources are freed just
449 // below and the user suppliedo ne might be even more unsafe (using any
450 // wxWindows GUI function is unsafe starting from now)
8df85a61 451 //
d88de032
DW
452 wxLog::DontCreateOnDemand();
453
8df85a61
DW
454 //
455 // This will flush the old messages if any
456 //
d88de032
DW
457 delete wxLog::SetActiveTarget(new wxLogStderr);
458#endif // wxUSE_LOG
459
8df85a61 460 //
d88de032 461 // One last chance for pending objects to be cleaned up
8df85a61 462 //
d88de032
DW
463 wxTheApp->DeletePendingObjects();
464
465 wxModule::CleanUpModules();
0e320a79 466
d88de032 467 wxDeleteStockObjects();
0e320a79 468
8df85a61 469 //
d88de032 470 // Destroy all GDI lists, etc.
8df85a61 471 //
d88de032 472 wxDeleteStockLists();
0e320a79 473
d88de032
DW
474 delete wxTheColourDatabase;
475 wxTheColourDatabase = NULL;
0e320a79 476
d88de032 477 wxBitmap::CleanUpHandlers();
0e320a79 478
d88de032
DW
479 delete[] wxBuffer;
480 wxBuffer = NULL;
0e320a79 481
8df85a61
DW
482 //
483 // PM-SPECIFIC CLEANUP
484 //
0e320a79 485
61243a51 486 // wxSetKeyboardHook(FALSE);
9ed0fac8 487
d88de032 488 if (wxSTD_FRAME_ICON)
9ed0fac8 489 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
d88de032 490 if (wxSTD_MDICHILDFRAME_ICON)
9ed0fac8 491 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
d88de032 492 if (wxSTD_MDIPARENTFRAME_ICON)
9ed0fac8 493 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
d88de032
DW
494
495 if (wxDEFAULT_FRAME_ICON)
9ed0fac8 496 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
d88de032 497 if (wxDEFAULT_MDICHILDFRAME_ICON)
9ed0fac8 498 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
d88de032 499 if (wxDEFAULT_MDIPARENTFRAME_ICON)
9ed0fac8
DW
500 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
501
d88de032
DW
502 if ( wxDisableButtonBrush )
503 {
504// TODO: ::DeleteObject( wxDisableButtonBrush );
505 }
506
507 if (wxWinHandleList)
508 delete wxWinHandleList;
509
d88de032 510 delete wxPendingEvents;
8df85a61 511#if wxUSE_THREADS
d88de032
DW
512 delete wxPendingEventsLocker;
513 // If we don't do the following, we get an apparent memory leak.
514 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
515#endif
0e320a79 516
d88de032 517 wxClassInfo::CleanUpClasses();
0e320a79 518
468e327a
SN
519 // Delete Message queue
520 if (wxTheApp->m_hMq)
521 ::WinDestroyMsgQueue(wxTheApp->m_hMq);
522
d88de032
DW
523 delete wxTheApp;
524 wxTheApp = NULL;
77cd51c3 525
0e320a79 526#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
d88de032
DW
527 // At this point we want to check if there are any memory
528 // blocks that aren't part of the wxDebugContext itself,
529 // as a special case. Then when dumping we need to ignore
530 // wxDebugContext, too.
531 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
532 {
533 wxLogDebug(wxT("There were memory leaks."));
534 wxDebugContext::Dump();
535 wxDebugContext::PrintStatistics();
536 }
537 // wxDebugContext::SetStream(NULL, NULL);
0e320a79 538#endif
77cd51c3 539
d88de032
DW
540#if wxUSE_LOG
541 // do it as the very last thing because everything else can log messages
542 delete wxLog::SetActiveTarget(NULL);
543#endif // wxUSE_LOG
8df85a61 544} // end of wxApp::CleanUp
0e320a79 545
7e99520b
DW
546//----------------------------------------------------------------------
547// Main wxWindows entry point
548//----------------------------------------------------------------------
9ed0fac8
DW
549int wxEntry(
550 int argc
551, char* argv[]
552)
d88de032 553{
9dea36ef 554 HAB vHab = 0;
d88de032 555
9ed0fac8
DW
556 if (!wxApp::Initialize(vHab))
557 return 0;
d88de032 558
9ed0fac8
DW
559 //
560 // create the application object or ensure that one already exists
561 //
562 if (!wxTheApp)
563 {
426d5745
DW
564 // The app may have declared a global application object, but we recommend
565 // the IMPLEMENT_APP macro is used instead, which sets an initializer
566 // function for delayed, dynamic app object construction.
567 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
568 wxT("No initializer - use IMPLEMENT_APP macro.") );
569 wxTheApp = (*wxApp::GetInitializerFunction()) ();
9ed0fac8 570 }
426d5745 571 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
9ed0fac8 572 wxTheApp->argc = argc;
d88de032 573
9ed0fac8
DW
574#if wxUSE_UNICODE
575 wxTheApp->argv = new wxChar*[argc+1];
576
577 int nArgc = 0;
578
579 while (nArgc < argc)
580 {
581 wxTheApp->argv[nArgc] = wxStrdup(wxConvLibc.cMB2WX(argv[nArgc]));
582 nArgc++;
583 }
584 wxTheApp->argv[nArgc] = (wxChar *)NULL;
585#else
586 wxTheApp->argv = argv;
587#endif
d88de032 588
9ed0fac8 589 wxString sName(wxFileNameFromPath(argv[0]));
d88de032 590
9ed0fac8
DW
591 wxStripExtension(sName);
592 wxTheApp->SetAppName(sName);
d88de032 593
9ed0fac8 594 int nRetValue = 0;
d88de032 595
9ed0fac8
DW
596 if (!wxTheApp->OnInitGui())
597 nRetValue = -1;
d88de032 598
9ed0fac8
DW
599 if (nRetValue == 0)
600 {
601 if (wxTheApp->OnInit())
d88de032 602 {
2b5f62a0 603 wxTheApp->OnRun();
7bed7a50 604 }
51c1d535
DW
605 // Normal exit
606 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
607 if (pTopWindow)
d88de032 608 {
51c1d535
DW
609 // Forcibly delete the window.
610 if (pTopWindow->IsKindOf(CLASSINFO(wxFrame)) ||
611 pTopWindow->IsKindOf(CLASSINFO(wxDialog)) )
612 {
613 pTopWindow->Close(TRUE);
614 wxTheApp->DeletePendingObjects();
615 }
616 else
617 {
618 delete pTopWindow;
619 wxTheApp->SetTopWindow(NULL);
620 }
d88de032 621 }
9ed0fac8 622 }
7e99520b
DW
623 else // app initialization failed
624 {
625 wxLogLastError(" Gui initialization failed, exitting");
626 }
627#if wxUSE_CONSOLEDEBUG
628 printf("wxTheApp->OnExit ");
629 fflush(stdout);
630#endif
2b5f62a0 631 nRetValue = wxTheApp->OnExit();
7e99520b
DW
632#if wxUSE_CONSOLEDEBUG
633 printf("wxApp::CleanUp ");
634 fflush(stdout);
635#endif
9ed0fac8 636 wxApp::CleanUp();
7e99520b
DW
637#if wxUSE_CONSOLEDEBUG
638 printf("return %i ", nRetValue);
639 fflush(stdout);
640#endif
9ed0fac8 641 return(nRetValue);
8df85a61 642} // end of wxEntry
77cd51c3 643
9ed0fac8 644bool wxApp::OnInitGui()
d88de032 645{
914589c2
DW
646 ERRORID vError;
647 wxString sError;
77cd51c3 648
19193a2c
KB
649 if (!wxAppBase::OnInitGui())
650 return FALSE;
651
f23208ca 652 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
914589c2
DW
653 if (!m_hMq)
654 {
655 vError = ::WinGetLastError(vHabmain);
656 sError = wxPMErrorToStr(vError);
657 wxLogDebug(sError);
658 return FALSE;
659 }
19193a2c 660
9ed0fac8 661 return TRUE;
8df85a61 662} // end of wxApp::OnInitGui
0e320a79 663
0e320a79
DW
664wxApp::wxApp()
665{
d88de032
DW
666 m_topWindow = NULL;
667 wxTheApp = this;
d88de032
DW
668
669 argc = 0;
670 argv = NULL;
9ed0fac8 671 m_nPrintMode = wxPRINT_WINDOWS;
9ed0fac8 672 m_bAuto3D = TRUE;
468e327a 673 m_hMq = 0;
3958ae62
SN
674 m_maxSocketHandles = 0;
675 m_maxSocketNr = 0;
676 m_sockCallbackInfo = 0;
8df85a61 677} // end of wxApp::wxApp
d88de032
DW
678
679wxApp::~wxApp()
680{
8df85a61 681 //
d88de032 682 // Delete command-line args
8df85a61 683 //
039bec17 684#if wxUSE_UNICODE
8df85a61
DW
685 int i;
686
d88de032
DW
687 for (i = 0; i < argc; i++)
688 {
689 delete[] argv[i];
690 }
691 delete[] argv;
039bec17 692#endif
8df85a61 693} // end of wxApp::~wxApp
0e320a79
DW
694
695bool wxApp::Initialized()
696{
d88de032
DW
697 if (GetTopWindow())
698 return TRUE;
699 else
700 return FALSE;
8df85a61 701} // end of wxApp::Initialized
0e320a79 702
9ed0fac8
DW
703//
704// Get and process a message, returning FALSE if WM_QUIT
705// received (and also set the flag telling the app to exit the main loop)
706//
3958ae62 707
d88de032
DW
708bool wxApp::DoMessage()
709{
468e327a 710 BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0);
9ed0fac8
DW
711
712 if (bRc == 0)
d88de032
DW
713 {
714 // got WM_QUIT
9ed0fac8 715 m_bKeepGoing = FALSE;
d88de032
DW
716 return FALSE;
717 }
9ed0fac8 718 else if (bRc == -1)
d88de032
DW
719 {
720 // should never happen, but let's test for it nevertheless
721 wxLogLastError("GetMessage");
722 }
723 else
724 {
725#if wxUSE_THREADS
9ed0fac8
DW
726 wxASSERT_MSG( wxThread::IsMain()
727 ,wxT("only the main thread can process Windows messages")
728 );
d88de032 729
9ed0fac8
DW
730 static bool sbHadGuiLock = TRUE;
731 static wxMsgArray svSavedMessages;
d88de032 732
9ed0fac8 733 //
8df85a61 734 // If a secondary thread owns is doing GUI calls, save all messages for
d88de032
DW
735 // later processing - we can't process them right now because it will
736 // lead to recursive library calls (and we're not reentrant)
9ed0fac8
DW
737 //
738 if (!wxGuiOwnedByMainThread())
d88de032 739 {
9ed0fac8 740 sbHadGuiLock = FALSE;
d88de032 741
8df85a61
DW
742 //
743 // Leave out WM_COMMAND messages: too dangerous, sometimes
d88de032 744 // the message will be processed twice
8df85a61 745 //
d88de032 746 if ( !wxIsWaitingForThread() ||
9ed0fac8 747 svCurrentMsg.msg != WM_COMMAND )
d88de032 748 {
9ed0fac8 749 svSavedMessages.Add(svCurrentMsg);
d88de032 750 }
d88de032
DW
751 return TRUE;
752 }
753 else
754 {
9ed0fac8 755 //
8df85a61 756 // Have we just regained the GUI lock? if so, post all of the saved
d88de032
DW
757 // messages
758 //
9ed0fac8 759 if (!sbHadGuiLock )
d88de032 760 {
9ed0fac8 761 sbHadGuiLock = TRUE;
d88de032 762
9ed0fac8
DW
763 size_t nCount = svSavedMessages.Count();
764
765 for (size_t n = 0; n < nCount; n++)
d88de032 766 {
9ed0fac8 767 QMSG vMsg = svSavedMessages[n];
d88de032 768
ed2b77fc 769 DoMessage((WXMSG*)&vMsg);
d88de032 770 }
9ed0fac8 771 svSavedMessages.Empty();
d88de032
DW
772 }
773 }
d88de032
DW
774#endif // wxUSE_THREADS
775
3febf684 776 //
d88de032 777 // Process the message
3febf684
DW
778 //
779 DoMessage((WXMSG *)&svCurrentMsg);
d88de032 780 }
d88de032 781 return TRUE;
8df85a61 782} // end of wxApp::DoMessage
d88de032 783
3febf684
DW
784void wxApp::DoMessage(
785 WXMSG* pMsg
786)
787{
788 if (!ProcessMessage((WXMSG *)&svCurrentMsg))
789 {
790 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
791 }
792} // end of wxApp::DoMessage
793
9ed0fac8
DW
794//////////////////////////////////////////////////////////////////////////////
795//
796// Keep trying to process messages until WM_QUIT
797// received.
798//
799// If there are messages to be processed, they will all be
800// processed and OnIdle will not be called.
801// When there are no more messages, OnIdle is called.
802// If OnIdle requests more time,
803// it will be repeatedly called so long as there are no pending messages.
804// A 'feature' of this is that once OnIdle has decided that no more processing
805// is required, then it won't get processing time until further messages
806// are processed (it'll sit in DoMessage).
807//
808//////////////////////////////////////////////////////////////////////////////
0e320a79
DW
809int wxApp::MainLoop()
810{
9ed0fac8 811 m_bKeepGoing = TRUE;
d88de032 812
9ed0fac8 813 while (m_bKeepGoing)
d88de032
DW
814 {
815#if wxUSE_THREADS
816 wxMutexGuiLeaveOrEnter();
817#endif // wxUSE_THREADS
3958ae62 818 while (!Pending() && ProcessIdle())
5b3ed311 819 {
3958ae62
SN
820 HandleSockets();
821 wxUsleep(10000);
5b3ed311 822 }
3958ae62
SN
823 HandleSockets();
824 if (Pending())
825 DoMessage();
826 else
827 wxUsleep(10000);
828
d88de032 829 }
9ed0fac8 830 return (int)svCurrentMsg.mp1;
8df85a61 831} // end of wxApp::MainLoop
0e320a79 832
9ed0fac8 833//
0e320a79 834// Returns TRUE if more time is needed.
9ed0fac8 835//
0e320a79
DW
836bool wxApp::ProcessIdle()
837{
9ed0fac8 838 wxIdleEvent vEvent;
0e320a79 839
9ed0fac8
DW
840 vEvent.SetEventObject(this);
841 ProcessEvent(vEvent);
842 return vEvent.MoreRequested();
8df85a61 843} // end of wxApp::ProcessIdle
d88de032 844
0e320a79
DW
845void wxApp::ExitMainLoop()
846{
a23692f0
DW
847 ::WinPostMsg(NULL, WM_QUIT, 0, 0);
848} // end of wxApp::ExitMainLoop
0e320a79 849
0e320a79
DW
850bool wxApp::Pending()
851{
43543d98 852 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
a23692f0 853} // end of wxApp::Pending
0e320a79 854
0e320a79
DW
855void wxApp::Dispatch()
856{
d88de032 857 DoMessage();
0e320a79
DW
858}
859
9ed0fac8
DW
860//////////////////////////////////////////////////////////////////////////////
861//
862// Give all windows a chance to preprocess
863// the message. Some may have accelerator tables, or have
864// MDI complications.
865//
866//////////////////////////////////////////////////////////////////////////////
867bool wxApp::ProcessMessage(
868 WXMSG* pWxmsg
869)
0e320a79 870{
f6bcfd97
BP
871 QMSG* pMsg = (PQMSG)pWxmsg;
872 HWND hWnd = pMsg->hwnd;
9ed0fac8
DW
873 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
874 wxWindow* pWnd;
d88de032 875
05a8bfed 876 //
e58dab20 877 // Pass non-system timer messages to the wxTimerProc
05a8bfed 878 //
e58dab20
DW
879 if (pMsg->msg == WM_TIMER &&
880 (SHORT1FROMMP(pMsg->mp1) != TID_CURSOR &&
881 SHORT1FROMMP(pMsg->mp1) != TID_FLASHWINDOW &&
b3260bce
DW
882 SHORT1FROMMP(pMsg->mp1) != TID_SCROLL &&
883 SHORT1FROMMP(pMsg->mp1) != 0x0000
e58dab20 884 ))
496fd9fb 885 wxTimerProc(NULL, 0, (int)pMsg->mp1, 0);
05a8bfed 886
54ffa107
DW
887 //
888 // Allow the window to prevent certain messages from being
889 // translated/processed (this is currently used by wxTextCtrl to always
890 // grab Ctrl-C/V/X, even if they are also accelerators in some parent)
891 //
892 if (pWndThis && !pWndThis->OS2ShouldPreProcessMessage(pWxmsg))
893 {
894 return FALSE;
895 }
896
9ed0fac8 897 //
8df85a61 898 // For some composite controls (like a combobox), wndThis might be NULL
d88de032
DW
899 // because the subcontrol is not a wxWindow, but only the control itself
900 // is - try to catch this case
9ed0fac8
DW
901 //
902 while (hWnd && !pWndThis)
d88de032 903 {
9ed0fac8
DW
904 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
905 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
d88de032 906 }
0e320a79 907
f6bcfd97
BP
908 //
909 // Try translations first; find the youngest window with
f09d8a3b
DW
910 // a translation table. OS/2 has case sensative accels, so
911 // this block, coded by BK, removes that and helps make them
912 // case insensative.
f6bcfd97 913 //
f09d8a3b 914 if(pMsg->msg == WM_CHAR)
f6bcfd97 915 {
f09d8a3b
DW
916 PBYTE pChmsg = (PBYTE)&(pMsg->msg);
917 USHORT uSch = CHARMSG(pChmsg)->chr;
918 bool bRc;
919
920 //
921 // Do not process keyup events
922 //
923 if(!(CHARMSG(pChmsg)->fs & KC_KEYUP))
924 {
925 if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0)
f1f22049 926 CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch);
f09d8a3b 927
7e99520b 928
5b3ed311
DW
929 for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() )
930 {
931 if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE)
932 break;
933 }
7e99520b 934
f09d8a3b
DW
935 if(!bRc) // untranslated, should restore original value
936 CHARMSG(pChmsg)->chr = uSch;
937 }
f6bcfd97 938 }
8df85a61 939 //
d88de032 940 // Anyone for a non-translation message? Try youngest descendants first.
8df85a61 941 //
e604d44b
DW
942// for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
943// {
944// if (pWnd->OS2ProcessMessage(pWxmsg))
945// return TRUE;
946// }
d88de032 947 return FALSE;
8df85a61 948} // end of wxApp::ProcessMessage
0e320a79 949
2b5f62a0
VZ
950bool gbInOnIdle = FALSE;
951
9ed0fac8
DW
952void wxApp::OnIdle(
953 wxIdleEvent& rEvent
954)
d88de032 955{
d88de032 956
9ed0fac8 957 //
d88de032 958 // Avoid recursion (via ProcessEvent default case)
9ed0fac8 959 //
2b5f62a0 960 if (gbInOnIdle)
d88de032 961 return;
0e320a79 962
2b5f62a0 963 gbInOnIdle = TRUE;
0e320a79 964
8df85a61
DW
965 //
966 // If there are pending events, we must process them: pending events
967 // are either events to the threads other than main or events posted
968 // with wxPostEvent() functions
969 //
970 ProcessPendingEvents();
971
9ed0fac8 972 //
d88de032 973 // 'Garbage' collection of windows deleted with Close().
9ed0fac8 974 //
d88de032 975 DeletePendingObjects();
0e320a79 976
d88de032 977#if wxUSE_LOG
8df85a61
DW
978 //
979 // Flush the logged messages if any
980 //
981 wxLog::FlushActive();
d88de032 982#endif // wxUSE_LOG
0e320a79 983
893758d5
DW
984#if wxUSE_DC_CACHEING
985 // automated DC cache management: clear the cached DCs and bitmap
986 // if it's likely that the app has finished with them, that is, we
987 // get an idle event and we're not dragging anything.
19193a2c
KB
988 if (!::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &&
989 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &&
990 !::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2))
893758d5
DW
991 wxDC::ClearCache();
992#endif // wxUSE_DC_CACHEING
993
8df85a61 994 //
d88de032 995 // Send OnIdle events to all windows
8df85a61 996 //
9ed0fac8 997 if (SendIdleEvents())
d88de032 998 {
9ed0fac8 999 //
d88de032
DW
1000 // SendIdleEvents() returns TRUE if at least one window requested more
1001 // idle events
9ed0fac8
DW
1002 //
1003 rEvent.RequestMore(TRUE);
d88de032 1004 }
2b5f62a0 1005 gbInOnIdle = FALSE;
8df85a61 1006} // end of wxApp::OnIdle
9779893b 1007
0e320a79
DW
1008// Send idle event to all top-level windows
1009bool wxApp::SendIdleEvents()
1010{
9ed0fac8
DW
1011 bool bNeedMore = FALSE;
1012 wxWindowList::Node* pNode = wxTopLevelWindows.GetFirst();
d88de032 1013
9ed0fac8 1014 while (pNode)
d88de032 1015 {
9ed0fac8 1016 wxWindow* pWin = pNode->GetData();
0e320a79 1017
9ed0fac8
DW
1018 if (SendIdleEvents(pWin))
1019 bNeedMore = TRUE;
1020 pNode = pNode->GetNext();
1021 }
1022 return bNeedMore;
8df85a61 1023} // end of wxApp::SendIdleEvents
0e320a79 1024
9ed0fac8 1025//
0e320a79 1026// Send idle event to window and all subwindows
9ed0fac8
DW
1027//
1028bool wxApp::SendIdleEvents(
1029 wxWindow* pWin
1030)
0e320a79 1031{
9ed0fac8
DW
1032 bool bNeedMore = FALSE;
1033 wxIdleEvent vEvent;
1034
1035 vEvent.SetEventObject(pWin);
1036 pWin->GetEventHandler()->ProcessEvent(vEvent);
0e320a79 1037
9ed0fac8
DW
1038 if (vEvent.MoreRequested())
1039 bNeedMore = TRUE;
0e320a79 1040
9ed0fac8 1041 wxNode* pNode = pWin->GetChildren().First();
0e320a79 1042
9ed0fac8 1043 while (pNode)
d88de032 1044 {
9ed0fac8 1045 wxWindow* pWin = (wxWindow*) pNode->Data();
0e320a79 1046
9ed0fac8
DW
1047 if (SendIdleEvents(pWin))
1048 bNeedMore = TRUE;
1049 pNode = pNode->Next();
d88de032 1050 }
9ed0fac8 1051 return bNeedMore;
8df85a61 1052} // end of wxApp::SendIdleEvents
0e320a79
DW
1053
1054void wxApp::DeletePendingObjects()
1055{
9ed0fac8
DW
1056 wxNode* pNode = wxPendingDelete.First();
1057
1058 while (pNode)
d88de032 1059 {
9ed0fac8 1060 wxObject* pObj = (wxObject *)pNode->Data();
77cd51c3 1061
9ed0fac8 1062 delete pObj;
0e320a79 1063
9ed0fac8
DW
1064 if (wxPendingDelete.Member(pObj))
1065 delete pNode;
0e320a79 1066
9ed0fac8 1067 //
d88de032
DW
1068 // Deleting one object may have deleted other pending
1069 // objects, so start from beginning of list again.
9ed0fac8
DW
1070 //
1071 pNode = wxPendingDelete.First();
d88de032 1072 }
8df85a61 1073} // end of wxApp::DeletePendingObjects
0e320a79 1074
9ed0fac8
DW
1075void wxApp::OnEndSession(
1076 wxCloseEvent& WXUNUSED(rEvent))
0e320a79 1077{
d88de032
DW
1078 if (GetTopWindow())
1079 GetTopWindow()->Close(TRUE);
8df85a61 1080} // end of wxApp::OnEndSession
0e320a79 1081
9ed0fac8 1082//
d88de032
DW
1083// Default behaviour: close the application with prompts. The
1084// user can veto the close, and therefore the end session.
9ed0fac8
DW
1085//
1086void wxApp::OnQueryEndSession(
1087 wxCloseEvent& rEvent
1088)
0e320a79 1089{
d88de032
DW
1090 if (GetTopWindow())
1091 {
9ed0fac8
DW
1092 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
1093 rEvent.Veto(TRUE);
d88de032 1094 }
8df85a61 1095} // end of wxApp::OnQueryEndSession
0e320a79 1096
e2478fde 1097void wxApp::Exit()
0e320a79 1098{
d88de032 1099 wxApp::CleanUp();
e2478fde
VZ
1100
1101 // VZ: must really exit somehow, insert appropriate OS/2 syscall (FIXME)
1102 wxAppConsole::Exit();
ee453a16 1103} // end of wxExit
0e320a79 1104
8df85a61 1105//
d88de032 1106// Yield to incoming messages
8df85a61 1107//
8461e4c2 1108bool wxApp::Yield(bool onlyIfNeeded)
0e320a79 1109{
8461e4c2
VZ
1110 static bool s_inYield = FALSE;
1111
1112 if ( s_inYield )
1113 {
1114 if ( !onlyIfNeeded )
1115 {
1116 wxFAIL_MSG( _T("wxYield() called recursively") );
1117 }
1118
1119 return FALSE;
1120 }
1121
9dea36ef 1122 HAB vHab = 0;
dde11e60 1123 QMSG vMsg;
ee453a16 1124
8df85a61
DW
1125 //
1126 // Disable log flushing from here because a call to wxYield() shouldn't
1127 // normally result in message boxes popping up &c
1128 //
1129 wxLog::Suspend();
1130
8461e4c2 1131 s_inYield = TRUE;
8b63ae37 1132
8df85a61 1133 //
d88de032
DW
1134 // We want to go back to the main message loop
1135 // if we see a WM_QUIT. (?)
8df85a61 1136 //
dde11e60 1137 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
d88de032 1138 {
8df85a61
DW
1139#if wxUSE_THREADS
1140 wxMutexGuiLeaveOrEnter();
1141#endif // wxUSE_THREADS
dde11e60 1142 if (!wxTheApp->DoMessage())
d88de032
DW
1143 break;
1144 }
8df85a61 1145 //
d88de032 1146 // If they are pending events, we must process them.
8df85a61
DW
1147 //
1148 if (wxTheApp)
1149 wxTheApp->ProcessPendingEvents();
1150
1151 //
1152 // Let the logs be flashed again
1153 //
1154 wxLog::Resume();
8461e4c2 1155 s_inYield = FALSE;
d88de032 1156 return TRUE;
8df85a61 1157} // end of wxYield
d88de032 1158
3958ae62
SN
1159int wxApp::AddSocketHandler(int handle, int mask,
1160 void (*callback)(void*), void * gsock)
1161{
1162 int find;
1163 struct GsocketCallbackInfo
1164 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
1165
1166 for (find = 0; find < m_maxSocketHandles; find++)
1167 if (CallbackInfo[find].handle == -1)
1168 break;
1169 if (find == m_maxSocketHandles)
1170 {
1171 // Allocate new memory
1172 m_sockCallbackInfo = realloc(m_sockCallbackInfo,
1173 (m_maxSocketHandles+=10)*
1174 sizeof(struct GsocketCallbackInfo));
1175 CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
1176 for (find = m_maxSocketHandles - 10; find < m_maxSocketHandles; find++)
1177 CallbackInfo[find].handle = -1;
1178 find = m_maxSocketHandles - 10;
1179 }
1180 CallbackInfo[find].proc = callback;
1181 CallbackInfo[find].type = mask;
1182 CallbackInfo[find].handle = handle;
1183 CallbackInfo[find].gsock = gsock;
1184 if (mask & wxSockReadMask)
1185 FD_SET(handle, &m_readfds);
1186 if (mask & wxSockWriteMask)
1187 FD_SET(handle, &m_writefds);
1188 if (handle >= m_maxSocketNr)
1189 m_maxSocketNr = handle + 1;
1190 return find;
1191}
1192
1193void wxApp::RemoveSocketHandler(int handle)
1194{
1195 struct GsocketCallbackInfo
1196 *CallbackInfo = (struct GsocketCallbackInfo *)m_sockCallbackInfo;
1197 if (handle < m_maxSocketHandles)
1198 {
1199 if (CallbackInfo[handle].type & wxSockReadMask)
1200 FD_CLR(CallbackInfo[handle].handle, &m_readfds);
1201 if (CallbackInfo[handle].type & wxSockWriteMask)
1202 FD_CLR(CallbackInfo[handle].handle, &m_writefds);
1203 CallbackInfo[handle].handle = -1;
1204 }
1205}
1206
8df85a61
DW
1207//-----------------------------------------------------------------------------
1208// wxWakeUpIdle
1209//-----------------------------------------------------------------------------
1210
e2478fde 1211void wxApp::WakeUpIdle()
8df85a61
DW
1212{
1213 //
1214 // Send the top window a dummy message so idle handler processing will
1215 // start up again. Doing it this way ensures that the idle handler
1216 // wakes up in the right thread (see also wxWakeUpMainThread() which does
1217 // the same for the main app thread only)
1218 //
1219 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
1220
1221 if (pTopWindow)
1222 {
1223 if ( !::WinPostMsg(GetHwndOf(pTopWindow), WM_NULL, (MPARAM)0, (MPARAM)0))
1224 {
1225 //
1226 // Should never happen
1227 //
1228 wxLogLastError("PostMessage(WM_NULL)");
1229 }
1230 }
1231} // end of wxWakeUpIdle
d88de032 1232
76990f63 1233HAB wxGetInstance()
d88de032 1234{
76990f63 1235 return vHabmain;
d88de032
DW
1236}
1237
76990f63
DW
1238void wxSetInstance(
1239 HAB vHab
1240)
d88de032 1241{
76990f63 1242 vHabmain = vHab;
0e320a79
DW
1243}
1244