Applied patch #827025 (Removes last warnings from emulator util); Cosmetic cleanup.
[wxWidgets.git] / utils / emulator / src / emulator.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: emulator.cpp
3 // Purpose: Emulator wxWindows sample
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
17 #pragma implementation "emulator.h"
18 #endif
19
20 // ----------------------------------------------------------------------------
21 // headers
22 // ----------------------------------------------------------------------------
23
24 // For compilers that support precompilation, includes "wx/wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 // for all others, include the necessary headers (this file is usually all you
32 // need because it includes almost all "standard" wxWindows headers)
33 #ifndef WX_PRECOMP
34 #include "wx/wx.h"
35 #endif
36
37 #include "wx/confbase.h"
38 #include "wx/fileconf.h"
39 #include "wx/cmdline.h"
40 #include "wx/image.h"
41
42 #ifdef __WXX11__
43 #include "wx/x11/reparent.h"
44 #endif
45
46 #include "emulator.h"
47
48 // ----------------------------------------------------------------------------
49 // resources
50 // ----------------------------------------------------------------------------
51
52 // the application icon (under Windows and OS/2 it is in resources)
53 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
54 #include "emulator.xpm"
55 #endif
56
57 // ----------------------------------------------------------------------------
58 // event tables and other macros for wxWindows
59 // ----------------------------------------------------------------------------
60
61 // the event tables connect the wxWindows events with the functions (event
62 // handlers) which process them. It can be also done at run-time, but for the
63 // simple menu events like this the static method is much simpler.
64 BEGIN_EVENT_TABLE(wxEmulatorFrame, wxFrame)
65 EVT_MENU(Emulator_Quit, wxEmulatorFrame::OnQuit)
66 EVT_MENU(Emulator_About, wxEmulatorFrame::OnAbout)
67 EVT_CLOSE(wxEmulatorFrame::OnCloseWindow)
68 END_EVENT_TABLE()
69
70 // Create a new application object: this macro will allow wxWindows to create
71 // the application object during program execution (it's better than using a
72 // static object for many reasons) and also declares the accessor function
73 // wxGetApp() which will return the reference of the right type (i.e. wxEmulatorApp and
74 // not wxApp)
75 IMPLEMENT_APP(wxEmulatorApp)
76
77 static const wxCmdLineEntryDesc sg_cmdLineDesc[] =
78 {
79 { wxCMD_LINE_OPTION, _T("u"), _T("use-display"), _T("display number to use (default 100)") },
80
81 { wxCMD_LINE_SWITCH, _T("h"), _T("help"), _T("displays help on the command line parameters") },
82 { wxCMD_LINE_SWITCH, _T("v"), _T("version"), _T("print version") },
83
84 { wxCMD_LINE_PARAM, NULL, NULL, _T("config file 1"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
85
86 { wxCMD_LINE_NONE }
87 };
88
89
90 // ============================================================================
91 // implementation
92 // ============================================================================
93
94 // ----------------------------------------------------------------------------
95 // the application class
96 // ----------------------------------------------------------------------------
97
98 wxEmulatorApp::wxEmulatorApp()
99 {
100 m_xnestWindow = NULL;
101 m_containerWindow = NULL;
102 m_displayNumber = wxT("100");
103 m_xnestPID = 0;
104
105 }
106
107 // 'Main program' equivalent: the program execution "starts" here
108 bool wxEmulatorApp::OnInit()
109 {
110 wxLog::SetTimestamp(NULL);
111 wxInitAllImageHandlers();
112
113 wxString currentDir = wxGetCwd();
114
115 // Use argv to get current app directory
116 m_appDir = wxFindAppPath(argv[0], currentDir, wxT("WXEMUDIR"));
117
118 // If the development version, go up a directory.
119 #ifdef __WXMSW__
120 if ((m_appDir.Right(5).CmpNoCase(_T("DEBUG")) == 0) ||
121 (m_appDir.Right(11).CmpNoCase(_T("DEBUGSTABLE")) == 0) ||
122 (m_appDir.Right(7).CmpNoCase(_T("RELEASE")) == 0) ||
123 (m_appDir.Right(13).CmpNoCase(_T("RELEASESTABLE")) == 0)
124 )
125 m_appDir = wxPathOnly(m_appDir);
126 #endif
127
128 // Parse the command-line parameters and options
129 wxCmdLineParser parser(sg_cmdLineDesc, argc, argv);
130 int res;
131 {
132 wxLogNull log;
133 res = parser.Parse();
134 }
135 if (res == -1 || res > 0 || parser.Found(wxT("h")))
136 {
137 #ifdef __X__
138 wxLog::SetActiveTarget(new wxLogStderr);
139 #endif
140 parser.Usage();
141 return false;
142 }
143 if (parser.Found(wxT("v")))
144 {
145 #ifdef __X__
146 wxLog::SetActiveTarget(new wxLogStderr);
147 #endif
148 wxString msg;
149 msg.Printf(wxT("wxWindows PDA Emulator (c) Julian Smart, 2002 Version %.2f, %s"), wxEMULATOR_VERSION, __DATE__);
150 wxLogMessage(msg);
151 return false;
152 }
153 if (parser.Found(wxT("u"), & m_displayNumber))
154 {
155 // Should only be number, so strip out anything before
156 // and including a : character
157 if (m_displayNumber.Find(wxT(':')) != -1)
158 {
159 m_displayNumber = m_displayNumber.AfterFirst(wxT(':'));
160 }
161 }
162 if (parser.GetParamCount() == 0)
163 {
164 m_emulatorInfo.m_emulatorFilename = wxT("default.wxe");
165 }
166 else if (parser.GetParamCount() > 0)
167 {
168 m_emulatorInfo.m_emulatorFilename = parser.GetParam(0);
169 }
170
171 // Load the emulation info
172 if (!LoadEmulator(m_appDir))
173 {
174 //wxMessageBox(wxT("Sorry, could not load this emulator. Please check bitmaps are valid."));
175 return false;
176 }
177
178 // create the main application window
179 wxEmulatorFrame *frame = new wxEmulatorFrame(_T("wxEmulator"),
180 wxPoint(50, 50), wxSize(450, 340));
181
182 frame->SetStatusText(m_emulatorInfo.m_emulatorTitle, 0);
183
184 wxString sizeStr;
185 sizeStr.Printf(wxT("Screen: %dx%d"), (int) m_emulatorInfo.m_emulatorScreenSize.x,
186 (int) m_emulatorInfo.m_emulatorScreenSize.y);
187 frame->SetStatusText(sizeStr, 1);
188
189 m_containerWindow = new wxEmulatorContainer(frame, wxID_ANY);
190
191 frame->SetClientSize(m_emulatorInfo.m_emulatorDeviceSize.x,
192 m_emulatorInfo.m_emulatorDeviceSize.y);
193
194 // and show it (the frames, unlike simple controls, are not shown when
195 // created initially)
196 frame->Show(true);
197
198 #ifdef __WXX11__
199 m_xnestWindow = new wxAdoptedWindow;
200
201 wxString cmd;
202 cmd.Printf(wxT("Xnest :%s -geometry %dx%d"),
203 m_displayNumber.c_str(),
204 (int) m_emulatorInfo.m_emulatorScreenSize.x,
205 (int) m_emulatorInfo.m_emulatorScreenSize.y);
206
207 // Asynchronously executes Xnest
208 m_xnestPID = wxExecute(cmd);
209 if (0 == m_xnestPID)
210 {
211 frame->Destroy();
212 wxMessageBox(wxT("Sorry, could not run Xnest. Please check your PATH."));
213 return false;
214 }
215
216 wxReparenter reparenter;
217 if (!reparenter.WaitAndReparent(m_containerWindow, m_xnestWindow, wxT("Xnest")))
218 {
219 wxMessageBox(wxT("Sorry, could not reparent Xnest.."));
220 frame->Destroy();
221 return false;
222 }
223
224 #endif
225 m_containerWindow->DoResize();
226
227 // success: wxApp::OnRun() will be called which will enter the main message
228 // loop and the application will run. If we returned false here, the
229 // application would exit immediately.
230 return true;
231 }
232
233 // Prepend the current program directory to the name
234 wxString wxEmulatorApp::GetFullAppPath(const wxString& filename) const
235 {
236 wxString path(m_appDir);
237 if (path.Last() != '\\' && path.Last() != '/' && filename[0] != '\\' && filename[0] != '/')
238 #ifdef __X__
239 path += '/';
240 #else
241 path += '\\';
242 #endif
243 path += filename;
244
245 return path;
246 }
247
248
249 // Load the specified emulator.
250 // For now, hard-wired. TODO: make this configurable
251 bool wxEmulatorApp::LoadEmulator(const wxString& appDir)
252 {
253 // Load config file and bitmaps
254 return m_emulatorInfo.Load(appDir);
255 }
256
257 // ----------------------------------------------------------------------------
258 // main frame
259 // ----------------------------------------------------------------------------
260
261 // frame constructor
262 wxEmulatorFrame::wxEmulatorFrame(const wxString& title,
263 const wxPoint& pos, const wxSize& size)
264 : wxFrame(NULL, wxID_ANY, title, pos, size)
265 {
266 // set the frame icon
267 SetIcon(wxICON(emulator));
268
269 #if wxUSE_MENUS
270 // create a menu bar
271 wxMenu *menuFile = new wxMenu;
272
273 // the "About" item should be in the help menu
274 wxMenu *helpMenu = new wxMenu;
275 helpMenu->Append(Emulator_About, _T("&About...\tF1"), _T("Show about dialog"));
276
277 menuFile->Append(Emulator_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
278
279 // now append the freshly created menu to the menu bar...
280 wxMenuBar *menuBar = new wxMenuBar();
281 menuBar->Append(menuFile, _T("&File"));
282 menuBar->Append(helpMenu, _T("&Help"));
283
284 // ... and attach this menu bar to the frame
285 SetMenuBar(menuBar);
286 #endif // wxUSE_MENUS
287
288 #if wxUSE_STATUSBAR
289 // create a status bar just for fun (by default with 1 pane only)
290 CreateStatusBar(2);
291 #endif // wxUSE_STATUSBAR
292 }
293
294
295 // event handlers
296
297 void wxEmulatorFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
298 {
299 // true is to force the frame to close
300 Close(true);
301 }
302
303 void wxEmulatorFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
304 {
305 wxString msg;
306 msg.Printf( _T("wxEmulator is an environment for testing embedded X11 apps.\n"));
307
308 wxMessageBox(msg, _T("About wxEmulator"), wxOK | wxICON_INFORMATION, this);
309 }
310
311 void wxEmulatorFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
312 {
313 #ifdef __WXX11__
314 if (wxGetApp().m_xnestWindow)
315 {
316 wxGetApp().m_xnestWindow->SetHandle((WXWindow) NULL);
317 }
318 #endif
319 this->Destroy();
320 if (wxGetApp().m_xnestPID > 0)
321 {
322 wxKill(wxGetApp().m_xnestPID);
323 wxGetApp().m_xnestPID = 0;
324 }
325 }
326
327 IMPLEMENT_CLASS(wxEmulatorContainer, wxWindow)
328
329 BEGIN_EVENT_TABLE(wxEmulatorContainer, wxWindow)
330 EVT_SIZE(wxEmulatorContainer::OnSize)
331 EVT_PAINT(wxEmulatorContainer::OnPaint)
332 EVT_ERASE_BACKGROUND(wxEmulatorContainer::OnEraseBackground)
333 END_EVENT_TABLE()
334
335 wxEmulatorContainer::wxEmulatorContainer(wxWindow* parent, wxWindowID id):
336 wxWindow(parent, id, wxDefaultPosition, wxDefaultSize)
337 {
338 }
339
340 void wxEmulatorContainer::OnSize(wxSizeEvent& WXUNUSED(event))
341 {
342 DoResize();
343 }
344
345 void wxEmulatorContainer::DoResize()
346 {
347 wxSize sz = GetClientSize();
348 if (wxGetApp().m_xnestWindow
349 #ifdef __WXX11__
350 && wxGetApp().m_xnestWindow->GetMainWindow()
351 #endif
352 )
353 {
354 int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
355 int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
356
357 int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
358 int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
359
360 x += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.x;
361 y += wxGetApp().m_emulatorInfo.m_emulatorScreenPosition.y;
362
363 wxGetApp().m_xnestWindow->Move(x, y);
364 }
365 Refresh();
366 }
367
368 void wxEmulatorContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
369 {
370 wxPaintDC dc(this);
371
372 wxSize sz = GetClientSize();
373 if (wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap.Ok())
374 {
375 int deviceWidth = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.x;
376 int deviceHeight = wxGetApp().m_emulatorInfo.m_emulatorDeviceSize.y;
377
378 int x = wxMax(0, (int) ((sz.x - deviceWidth)/2.0));
379 int y = wxMax(0, (int) ((sz.y - deviceHeight)/2.0));
380
381 dc.DrawBitmap(wxGetApp().m_emulatorInfo.m_emulatorBackgroundBitmap, x, y);
382 }
383 }
384
385 void wxEmulatorContainer::OnEraseBackground(wxEraseEvent& event)
386 {
387 wxDC* dc wxDUMMY_INITIALIZE(NULL);
388
389 if (event.GetDC())
390 {
391 dc = event.GetDC();
392 }
393 else
394 {
395 dc = new wxClientDC(this);
396 }
397
398 dc->SetBackground(wxBrush(wxGetApp().m_emulatorInfo.m_emulatorBackgroundColour, wxSOLID));
399 dc->Clear();
400
401 if (!event.GetDC())
402 delete dc;
403 }
404
405 // Information about the emulator decorations
406
407 void wxEmulatorInfo::Copy(const wxEmulatorInfo& info)
408 {
409 m_emulatorFilename = info.m_emulatorFilename;
410 m_emulatorTitle = info.m_emulatorTitle;
411 m_emulatorDescription = info.m_emulatorDescription;
412 m_emulatorScreenPosition = info.m_emulatorScreenPosition;
413 m_emulatorScreenSize = info.m_emulatorScreenSize;
414 m_emulatorBackgroundBitmap = info.m_emulatorBackgroundBitmap;
415 m_emulatorBackgroundBitmapName = info.m_emulatorBackgroundBitmapName;
416 m_emulatorBackgroundColour = info.m_emulatorBackgroundColour;
417 m_emulatorDeviceSize = info.m_emulatorDeviceSize;
418 }
419
420 // Initialisation
421 void wxEmulatorInfo::Init()
422 {
423 m_emulatorDeviceSize = wxSize(260, 340);
424 m_emulatorScreenSize = wxSize(240, 320);
425 }
426
427 // Loads bitmaps
428 bool wxEmulatorInfo::Load(const wxString& appDir)
429 {
430 // Try to find absolute path
431 wxString absoluteConfigPath = m_emulatorFilename;
432 if ( !::wxIsAbsolutePath(absoluteConfigPath) )
433 {
434 wxString currDir = wxGetCwd();
435 absoluteConfigPath = currDir + wxString(wxFILE_SEP_PATH) + m_emulatorFilename;
436 if ( !wxFile::Exists(absoluteConfigPath) )
437 {
438 absoluteConfigPath = appDir + wxString(wxFILE_SEP_PATH)
439 + m_emulatorFilename;
440 }
441 }
442
443 if ( !wxFile::Exists(absoluteConfigPath) )
444 {
445 wxString str;
446 str.Printf( wxT("Could not find config file %s"),
447 absoluteConfigPath.c_str() );
448
449 wxMessageBox(str);
450 return false;
451 }
452
453 wxString rootPath = wxPathOnly(absoluteConfigPath);
454
455 {
456 wxFileConfig config(wxT("wxEmulator"), wxT("wxWindows"),
457 absoluteConfigPath, wxEmptyString, wxCONFIG_USE_LOCAL_FILE);
458
459 config.Read(wxT("/General/title"), & m_emulatorTitle);
460 config.Read(wxT("/General/description"), & m_emulatorDescription);
461 config.Read(wxT("/General/backgroundBitmap"), & m_emulatorBackgroundBitmapName);
462
463 wxString colString;
464 if (config.Read(wxT("/General/backgroundColour"), & colString) ||
465 config.Read(wxT("/General/backgroundColor"), & colString)
466 )
467 {
468 m_emulatorBackgroundColour = wxHexStringToColour(colString);
469 }
470
471 int x = 0, y = 0, w = 0, h = 0, dw = 0, dh = 0;
472 config.Read(wxT("/General/screenX"), & x);
473 config.Read(wxT("/General/screenY"), & y);
474 config.Read(wxT("/General/screenWidth"), & w);
475 config.Read(wxT("/General/screenHeight"), & h);
476 if (config.Read(wxT("/General/deviceWidth"), & dw) && config.Read(wxT("/General/deviceHeight"), & dh))
477 {
478 m_emulatorDeviceSize = wxSize(dw, dh);
479 }
480
481 m_emulatorScreenPosition = wxPoint(x, y);
482 m_emulatorScreenSize = wxSize(w, h);
483 }
484
485 if (!m_emulatorBackgroundBitmapName.IsEmpty())
486 {
487 wxString absoluteBackgroundBitmapName = rootPath + wxString(wxFILE_SEP_PATH) + m_emulatorBackgroundBitmapName;
488 if ( !wxFile::Exists(absoluteBackgroundBitmapName) )
489 {
490 wxString str;
491 str.Printf( wxT("Could not find bitmap %s"),
492 absoluteBackgroundBitmapName.c_str() );
493 wxMessageBox(str);
494 return false;
495 }
496
497 wxBitmapType type = wxDetermineImageType(m_emulatorBackgroundBitmapName);
498 if (type == wxBITMAP_TYPE_INVALID)
499 return false;
500
501 if (!m_emulatorBackgroundBitmap.LoadFile(m_emulatorBackgroundBitmapName, type))
502 {
503 wxString str;
504 str.Printf( wxT("Could not load bitmap file %s"),
505 m_emulatorBackgroundBitmapName.c_str() );
506 wxMessageBox(str);
507 return false;
508 }
509
510 m_emulatorDeviceSize = wxSize(m_emulatorBackgroundBitmap.GetWidth(),
511 m_emulatorBackgroundBitmap.GetHeight());
512 }
513 return true;
514 }
515
516 // Returns the image type, or -1, determined from the extension.
517 wxBitmapType wxDetermineImageType(const wxString& filename)
518 {
519 wxString path, name, ext;
520
521 wxSplitPath(filename, & path, & name, & ext);
522
523 ext.MakeLower();
524 if (ext == _T("jpg") || ext == _T("jpeg"))
525 return wxBITMAP_TYPE_JPEG;
526 if (ext == _T("gif"))
527 return wxBITMAP_TYPE_GIF;
528 if (ext == _T("bmp"))
529 return wxBITMAP_TYPE_BMP;
530 if (ext == _T("png"))
531 return wxBITMAP_TYPE_PNG;
532 if (ext == _T("pcx"))
533 return wxBITMAP_TYPE_PCX;
534 if (ext == _T("tif") || ext == _T("tiff"))
535 return wxBITMAP_TYPE_TIF;
536
537 return wxBITMAP_TYPE_INVALID;
538 }
539
540 // Convert a colour to a 6-digit hex string
541 wxString wxColourToHexString(const wxColour& col)
542 {
543 wxString hex;
544
545 hex += wxDecToHex(col.Red());
546 hex += wxDecToHex(col.Green());
547 hex += wxDecToHex(col.Blue());
548
549 return hex;
550 }
551
552 // Convert 6-digit hex string to a colour
553 wxColour wxHexStringToColour(const wxString& hex)
554 {
555 unsigned int r = wxHexToDec(hex.Mid(0, 2));
556 unsigned int g = wxHexToDec(hex.Mid(2, 2));
557 unsigned int b = wxHexToDec(hex.Mid(4, 2));
558
559 return wxColour(r, g, b);
560 }
561
562 // Find the absolute path where this application has been run from.
563 // argv0 is wxTheApp->argv[0]
564 // cwd is the current working directory (at startup)
565 // appVariableName is the name of a variable containing the directory for this app, e.g.
566 // MYAPPDIR. This is checked first.
567
568 wxString wxFindAppPath(const wxString& argv0, const wxString& cwd, const wxString& appVariableName)
569 {
570 wxString str;
571
572 // Try appVariableName
573 if (!appVariableName.IsEmpty())
574 {
575 str = wxGetenv(appVariableName);
576 if (!str.IsEmpty())
577 return str;
578 }
579
580 if (wxIsAbsolutePath(argv0))
581 return wxPathOnly(argv0);
582 else
583 {
584 // Is it a relative path?
585 wxString currentDir(cwd);
586 if (!wxEndsWithPathSeparator(currentDir))
587 currentDir += wxFILE_SEP_PATH;
588
589 str = currentDir + argv0;
590 if ( wxFile::Exists(str) )
591 return wxPathOnly(str);
592 }
593
594 // OK, it's neither an absolute path nor a relative path.
595 // Search PATH.
596
597 wxPathList pathList;
598 pathList.AddEnvList(wxT("PATH"));
599 str = pathList.FindAbsoluteValidPath(argv0);
600 if (!str.IsEmpty())
601 return wxPathOnly(str);
602
603 // Failed
604 return wxEmptyString;
605 }
606