]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/app.cpp
fix wxStringOutputStream::Write() in Unicode build when the output overlaps a boundar...
[wxWidgets.git] / src / mgl / app.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mgl/app.cpp
3 // Author: Vaclav Slavik
4 // based on GTK and MSW implementations
5 // Id: $Id$
6 // Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
12
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16
17 #include "wx/app.h"
18
19 #ifndef WX_PRECOMP
20 #include "wx/settings.h"
21 #include "wx/frame.h"
22 #include "wx/dialog.h"
23 #include "wx/log.h"
24 #include "wx/intl.h"
25 #include "wx/module.h"
26 #endif
27
28 #include "wx/evtloop.h"
29 #include "wx/fontutil.h"
30 #include "wx/univ/theme.h"
31 #include "wx/univ/renderer.h"
32 #include "wx/univ/colschem.h"
33 #include "wx/sysopt.h"
34 #include "wx/mgl/private.h"
35 #include "wx/private/fontmgr.h"
36
37 //-----------------------------------------------------------------------------
38 // wxApp::Exit()
39 //-----------------------------------------------------------------------------
40
41 void wxApp::Exit()
42 {
43 MGL_exit();
44 exit(0);
45 }
46
47 //-----------------------------------------------------------------------------
48 // wxYield
49 //-----------------------------------------------------------------------------
50
51 static bool gs_inYield = false;
52
53 bool wxApp::Yield(bool onlyIfNeeded)
54 {
55 if ( gs_inYield )
56 {
57 if ( !onlyIfNeeded )
58 {
59 wxFAIL_MSG( wxT("wxYield called recursively" ) );
60 }
61
62 return false;
63 }
64
65 #if wxUSE_THREADS
66 if ( !wxThread::IsMain() )
67 {
68 // can't process events from other threads, MGL is thread-unsafe
69 return true;
70 }
71 #endif // wxUSE_THREADS
72
73 gs_inYield = true;
74
75 wxLog::Suspend();
76
77 if ( wxEventLoop::GetActive() )
78 {
79 while (wxEventLoop::GetActive()->Pending())
80 wxEventLoop::GetActive()->Dispatch();
81 }
82
83 /* it's necessary to call ProcessIdle() to update the frames sizes which
84 might have been changed (it also will update other things set from
85 OnUpdateUI() which is a nice (and desired) side effect) */
86 while (wxTheApp->ProcessIdle()) { }
87
88 wxLog::Resume();
89
90 gs_inYield = false;
91
92 return true;
93 }
94
95
96 //-----------------------------------------------------------------------------
97 // wxWakeUpIdle
98 //-----------------------------------------------------------------------------
99
100 void wxApp::WakeUpIdle()
101 {
102 #if wxUSE_THREADS
103 if (!wxThread::IsMain())
104 wxMutexGuiEnter();
105 #endif
106
107 while (wxTheApp->ProcessIdle())
108 ;
109
110 #if wxUSE_THREADS
111 if (!wxThread::IsMain())
112 wxMutexGuiLeave();
113 #endif
114 }
115
116 //-----------------------------------------------------------------------------
117 // Root window
118 //-----------------------------------------------------------------------------
119
120 class wxRootWindow : public wxWindow
121 {
122 public:
123 wxRootWindow() : wxWindow(NULL, wxID_ANY)
124 {
125 SetMGLwindow_t(MGL_wmGetRootWindow(g_winMng));
126 SetBackgroundColour(wxTHEME_COLOUR(DESKTOP));
127 }
128 virtual ~wxRootWindow()
129 {
130 // we don't want to delete MGL_WM's rootWnd
131 m_wnd = NULL;
132 }
133
134 virtual bool AcceptsFocus() const { return false; }
135
136 DECLARE_DYNAMIC_CLASS(wxRootWindow)
137 };
138
139 IMPLEMENT_DYNAMIC_CLASS(wxRootWindow, wxWindow)
140
141 static wxRootWindow *gs_rootWindow = NULL;
142
143 //-----------------------------------------------------------------------------
144 // MGL initialization
145 //-----------------------------------------------------------------------------
146
147 static bool wxCreateMGL_WM(const wxVideoMode& displayMode)
148 {
149 int mode;
150 int refresh = MGL_DEFAULT_REFRESH;
151
152 #if wxUSE_SYSTEM_OPTIONS
153 if ( wxSystemOptions::HasOption(wxT("mgl.screen-refresh")) )
154 refresh = wxSystemOptions::GetOptionInt(wxT("mgl.screen-refresh"));
155 #endif
156
157 mode = MGL_findMode(displayMode.GetWidth(),
158 displayMode.GetHeight(),
159 displayMode.GetDepth());
160 if ( mode == -1 )
161 {
162 wxLogError(_("Mode %ix%i-%i not available."),
163 displayMode.GetWidth(),
164 displayMode.GetHeight(),
165 displayMode.GetDepth());
166 return false;
167 }
168 g_displayDC = new MGLDisplayDC(mode, 1, refresh);
169 if ( !g_displayDC->isValid() )
170 {
171 delete g_displayDC;
172 g_displayDC = NULL;
173 return false;
174 }
175
176 g_winMng = MGL_wmCreate(g_displayDC->getDC());
177 if (!g_winMng)
178 return false;
179
180 return true;
181 }
182
183 static void wxDestroyMGL_WM()
184 {
185 if ( g_winMng )
186 {
187 MGL_wmDestroy(g_winMng);
188 g_winMng = NULL;
189 }
190 if ( g_displayDC )
191 {
192 delete g_displayDC;
193 g_displayDC = NULL;
194 }
195 }
196
197 //-----------------------------------------------------------------------------
198 // wxApp
199 //-----------------------------------------------------------------------------
200
201 IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
202
203 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
204 EVT_IDLE(wxAppBase::OnIdle)
205 END_EVENT_TABLE()
206
207
208 wxApp::wxApp()
209 {
210 }
211
212 wxApp::~wxApp()
213 {
214 }
215
216 wxVideoMode wxGetDefaultDisplayMode()
217 {
218 wxString mode;
219 unsigned w, h, bpp;
220
221 if ( !wxGetEnv(wxT("WXMODE"), &mode) ||
222 (wxSscanf(mode.c_str(), _T("%ux%u-%u"), &w, &h, &bpp) != 3) )
223 {
224 w = 640, h = 480, bpp = 16;
225 }
226
227 return wxVideoMode(w, h, bpp);
228 }
229
230 bool wxApp::SetDisplayMode(const wxVideoMode& mode)
231 {
232 if ( !mode.IsOk() )
233 {
234 return false;
235 }
236 if ( g_displayDC != NULL )
237 {
238 // FIXME_MGL -- we currently don't allow to switch video mode
239 // more than once. This can hopefully be changed...
240 wxFAIL_MSG(wxT("Can't change display mode after intialization!"));
241 return false;
242 }
243
244 if ( !wxCreateMGL_WM(mode) )
245 return false;
246 gs_rootWindow = new wxRootWindow;
247
248 m_displayMode = mode;
249
250 return true;
251 }
252
253 bool wxApp::OnInitGui()
254 {
255 if ( !wxAppBase::OnInitGui() )
256 return false;
257
258 #ifdef __WXDEBUG__
259 // MGL redirects stdout and stderr to physical console, so lets redirect
260 // it to file in debug build. Do it only when WXSTDERR environment variable is set
261 wxString redirect;
262 if ( wxGetEnv(wxT("WXSTDERR"), &redirect) )
263 freopen(redirect.mb_str(), "wt", stderr);
264 #endif // __WXDEBUG__
265
266 wxLog *oldLog = wxLog::SetActiveTarget(new wxLogGui);
267 if ( oldLog ) delete oldLog;
268
269 return true;
270 }
271
272 bool wxApp::Initialize(int& argc, wxChar **argv)
273 {
274 #ifdef __DJGPP__
275 // VS: disable long filenames under DJGPP as the very first thing,
276 // since SciTech MGL doesn't like them much...
277 wxSetEnv(wxT("LFN"), wxT("N"));
278 #endif
279
280 // intialize MGL before creating wxFontsManager since it uses MGL funcs
281 if ( MGL_init(".", NULL) == 0 )
282 {
283 wxLogError(_("Cannot initialize SciTech MGL!"));
284 return false;
285 }
286
287 if ( !wxAppBase::Initialize(argc, argv) )
288 {
289 MGL_exit();
290 return false;
291 }
292
293 #if wxUSE_INTL
294 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
295 #endif
296
297 return true;
298 }
299
300 // Modules are cleaned up after wxApp::CleanUp(), and some modules may
301 // require MGL to still be alive, e.g. the stock fonts need the fonts
302 // manager. So append this module last minute in wxApp::CleanUp() to close
303 // down MGL after all the other modules have been cleaned up.
304 //
305 struct wxMGLFinalCleanup: public wxModule
306 {
307 bool OnInit() { return true; }
308
309 void OnExit()
310 {
311 wxFontsManager::CleanUp();
312
313 wxDestroyMGL_WM();
314 MGL_exit();
315 }
316 };
317
318 void wxApp::CleanUp()
319 {
320 delete gs_rootWindow;
321
322 wxAppBase::CleanUp();
323
324 wxModule::RegisterModule(new wxMGLFinalCleanup);
325 }