summaryrefslogtreecommitdiffstats
path: root/src/app
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-06-25 19:59:17 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-06-25 19:59:17 +0200
commitb08a63790c0fbeacb3f96a74e3eb15abe8c70dab (patch)
tree7260140ae1ea308bd256370c6fcbbc57dbd13441 /src/app
parentf58918031c001a0159eaf8f18d4e451e70089d30 (diff)
downloadcolobot-b08a63790c0fbeacb3f96a74e3eb15abe8c70dab.tar.gz
colobot-b08a63790c0fbeacb3f96a74e3eb15abe8c70dab.tar.bz2
colobot-b08a63790c0fbeacb3f96a74e3eb15abe8c70dab.zip
SDL project
- added (very basic) SDL template in CApplication and CEngine - split project into two targets: colobot_old (dependent on DirectX and WinAPI) and colobot_new (dependent on SDL and OpenGL) - moved sound.h/cpp to old/ and created new template in Snd namespace - added platform-independent dialog boxes in app/system.h/cpp
Diffstat (limited to 'src/app')
-rw-r--r--src/app/app.cpp504
-rw-r--r--src/app/app.h111
-rw-r--r--src/app/main.cpp41
-rw-r--r--src/app/system.cpp253
-rw-r--r--src/app/system.h57
5 files changed, 908 insertions, 58 deletions
diff --git a/src/app/app.cpp b/src/app/app.cpp
index 0938f2a..726d32d 100644
--- a/src/app/app.cpp
+++ b/src/app/app.cpp
@@ -19,5 +19,507 @@
#include "app/app.h"
+#include "app/system.h"
+#include "common/iman.h"
-// TODO implementation
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+
+
+/**
+ * \struct ApplicationPrivate Private data of CApplication class
+ *
+ * Contains SDL-specific variables that should not be visible outside application module.
+ */
+struct ApplicationPrivate
+{
+ //! Display surface
+ SDL_Surface *surface;
+ //! Currently handled event
+ SDL_Event currentEvent;
+ //! Joystick
+ SDL_Joystick *joystick;
+ //! Index of joystick device
+ int joystickDevice;
+
+ ApplicationPrivate()
+ {
+ memset(&currentEvent, 0, sizeof(SDL_Event));
+ surface = NULL;
+ joystick = NULL;
+ joystickDevice = 0;
+ }
+};
+
+
+CApplication::CApplication()
+{
+ m_private = new ApplicationPrivate();
+ m_exitCode = 0;
+
+ m_iMan = new CInstanceManager();
+ m_event = new CEvent(m_iMan);
+
+ m_engine = 0;
+ m_robotMain = 0;
+ m_sound = 0;
+
+ m_keyState = 0;
+ m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ m_vidMemTotal = 0;
+ m_active = false;
+ m_activateApp = false;
+ m_ready = false;
+ m_joystick = false;
+ m_time = 0.0f;
+
+ for (int i = 0; i < 32; i++)
+ {
+ m_joyButton[i] = false;
+ }
+
+ m_windowTitle = "COLOBOT";
+
+ m_appUseZBuffer = true;
+ m_appUseStereo = true;
+ m_showStats = false;
+ m_debugMode = false;
+ m_audioState = true;
+ m_audioTrack = true;
+ m_niceMouse = false;
+ m_setupMode = true;
+
+ ResetKey();
+}
+
+CApplication::~CApplication()
+{
+ delete m_private;
+ m_private = NULL;
+
+ delete m_iMan;
+ m_iMan = NULL;
+}
+
+Error CApplication::ParseArguments(int argc, char *argv[])
+{
+ for (int i = 1; i < argc; ++i)
+ {
+ std::string arg = argv[i];
+
+ if (arg == "-debug")
+ {
+ m_showStats = true;
+ SetDebugMode(true);
+ }
+ else if (arg == "-audiostate")
+ {
+ m_audioState = false;
+ }
+ else if (arg == "-audiotrack")
+ {
+ m_audioTrack = false;
+ }
+ // TODO else {} report invalid argument
+ }
+
+ return ERR_OK;
+}
+
+bool CApplication::Create()
+{
+/*
+TODO
+ Full screen by default unless in debug mode
+ if (! m_debugMode)
+ m_deviceConfig.fullScreen = true;
+
+ int full = 0;
+ if (GetProfileInt("Device", "FullScreen", full))
+ m_deviceConfig.fullScreen = full == 1;
+*/
+
+ // Temporarily -- only in windowed mode
+ m_deviceConfig.fullScreen = false;
+
+/*
+TODO
+ // Create the 3D engine.
+ m_engine = new CEngine(m_iMan, this);
+
+ // Initialize the app's custom scene stuff
+ if (! m_engine->OneTimeSceneInit())
+ {
+ SystemDialog(SDT_ERROR, "COLOBOT - Error", m_engine->RetError());
+ return false;
+ }
+
+ // Create the sound instance.
+ m_sound = new CSound(m_iMan);
+
+ // Create the robot application.
+ m_robotMain = new CRobotMain(m_iMan);
+*/
+
+
+ Uint32 initFlags = SDL_INIT_VIDEO;
+ if (m_joystick)
+ initFlags |= SDL_INIT_JOYSTICK;
+
+ if (SDL_Init(initFlags) < 0)
+ {
+ SystemDialog( SDT_ERROR, "COLOBOT - Error", "SDL initialization error:\n" + std::string(SDL_GetError()) );
+ return false;
+ }
+
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+ if (! videoInfo)
+ {
+ SystemDialog( SDT_ERROR, "COLOBOT - Error", "SDL error while getting video info:\n " + std::string(SDL_GetError()) );
+ return false;
+ }
+
+ Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
+
+ if (m_deviceConfig.resizeable)
+ videoFlags |= SDL_RESIZABLE;
+
+ // Use hardware surface if available
+ if (videoInfo->hw_available)
+ videoFlags |= SDL_HWSURFACE;
+ else
+ videoFlags |= SDL_SWSURFACE;
+
+ // Enable hardware blit if available
+ if (videoInfo->blit_hw)
+ videoFlags |= SDL_HWACCEL;
+
+ if (m_deviceConfig.fullScreen)
+ videoFlags |= SDL_FULLSCREEN;
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) == 0)
+ {
+ SystemDialog( SDT_ERROR, "COLOBOT - Error", std::string("SDL_Image initialization error:\n") +
+ std::string(IMG_GetError()) );
+ return false;
+ }
+
+ m_private->surface = SDL_SetVideoMode(m_deviceConfig.width, m_deviceConfig.height,
+ m_deviceConfig.bpp, videoFlags);
+
+ if (! m_private->surface)
+ {
+ SystemDialog( SDT_ERROR, "COLOBT - Error", std::string("SDL error while setting video mode:\n") +
+ std::string(SDL_GetError()) );
+ return false;
+ }
+
+ SDL_WM_SetCaption(m_windowTitle.c_str(), m_windowTitle.c_str());
+
+ SDL_EnableUNICODE(1);
+
+
+/*
+TODO
+
+ InitJoystick();
+
+ if ( !GetProfileInt("Setup", "Sound3D", b3D) )
+ {
+ b3D = true;
+ }
+ m_pSound->SetDebugMode(m_bDebugMode);
+ m_pSound->Create(m_hWnd, b3D);
+ m_pSound->CacheAll();
+ m_pSound->SetState(m_bAudioState);
+ m_pSound->SetAudioTrack(m_bAudioTrack);
+ m_pSound->SetCDpath(m_CDpath);
+
+ // First execution?
+ if ( !GetProfileInt("Setup", "ObjectDirty", iValue) )
+ {
+ m_pD3DEngine->FirstExecuteAdapt(true);
+ }
+
+ // Creates the file colobot.ini at the first execution.
+ m_pRobotMain->CreateIni();
+
+ m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+
+ m_engine->TimeInit();
+*/
+
+ // The app is ready to go
+ m_ready = true;
+
+ return true;
+}
+
+void CApplication::Destroy()
+{
+ if (m_private->joystick != NULL)
+ {
+ SDL_JoystickClose(m_private->joystick);
+ m_private->joystick = NULL;
+ }
+
+ SDL_FreeSurface(m_private->surface);
+ m_private->surface = NULL;
+
+ IMG_Quit();
+
+ SDL_Quit();
+}
+
+int CApplication::Run()
+{
+ m_active = true;
+
+ while (m_private->currentEvent.type != SDL_QUIT)
+ {
+ // Use SDL_PeepEvents() if the app is active, so we can use idle time to
+ // render the scene. Else, use SDL_PollEvent() to avoid eating CPU time.
+ int count = 0;
+ if (m_active)
+ {
+ SDL_PumpEvents();
+ count = SDL_PeepEvents(&m_private->currentEvent, 1, SDL_GETEVENT, SDL_ALLEVENTS);
+ }
+ else
+ {
+ SDL_PollEvent(&m_private->currentEvent);
+ }
+
+ // If received an event
+ if ((m_active && count > 0) || (!m_active))
+ {
+ ParseEvent();
+ }
+
+ // Render a frame during idle time (no messages are waiting)
+ if (m_active && m_ready)
+ {
+ Event event;
+ while (m_event->GetEvent(event))
+ {
+ if (event.event == EVENT_QUIT)
+ {
+ goto end; // exit both loops
+ }
+
+ //m_robotMain->EventProcess(event);
+ }
+
+ //if ( !RetNiceMouse())
+ //{
+ // SetMouseType(m_engine->RetMouseType());
+ //}
+
+ // If an error occurs, push quit event to the queue
+ if (! Render())
+ {
+ SDL_Event quitEvent;
+ memset(&quitEvent, 0, sizeof(SDL_Event));
+ quitEvent.type = SDL_QUIT;
+ SDL_PushEvent(&quitEvent);
+ }
+ }
+ }
+
+end:
+ //m_sound->StopMusic();
+ Destroy();
+
+ return m_exitCode;
+}
+
+void CApplication::ParseEvent()
+{
+/* Event event;
+
+ if (m_private->currentEvent.type == SDL_MOUSEBUTTONDOWN)
+ {
+ if (m_private->currentEvent.button.button == SDL_BUTTON_LEFT)
+ event.event = EVENT_LBUTTONDOWN;
+ else if (m_private->currentEvent.button.button == SDL_BUTTON_RIGHT)
+ event.event = EVENT_RBUTTONDOWN;
+ }
+ else if (m_private->currentEvent.type == SDL_MOUSEBUTTONUP)
+ {
+ if (m_private->currentEvent.button.button == SDL_BUTTON_LEFT)
+ event.event = EVENT_LBUTTONUP;
+ else if (m_private->currentEvent.button.button == SDL_BUTTON_RIGHT)
+ event.event = EVENT_RBUTTONUP;
+ }
+ else if (m_private->currentEvent.type == SDL_MOUSEMOTION)
+ {
+ event.event = EVENT_MOUSEMOVE;
+ }
+ else if (m_private->currentEvent.type == SDL_KEYDOWN)
+ {
+ event.event = EVENT_KEYDOWN;
+ }
+ else if (m_private->currentEvent.type == SDL_KEYUP)
+ {
+ event.event = EVENT_KEYUP;
+ }
+
+ if (m_robotMain != NULL && event.event != EVENT_NULL)
+ {
+ m_robotMain->EventProcess(event);
+ }
+ if (m_engine != NULL)
+ {
+ m_engine->MsgProc( hWnd, uMsg, wParam, lParam );
+ }
+
+ ProcessEvent(event);*/
+}
+
+void CApplication::ProcessEvent(Event event)
+{
+
+}
+
+bool CApplication::Render()
+{
+ bool result = m_engine->Render();
+ if (! result)
+ return false;
+
+ if (m_deviceConfig.doubleBuf)
+ SDL_GL_SwapBuffers();
+
+ return true;
+}
+
+void CApplication::Pause(bool pause)
+{
+ // TODO
+}
+
+void CApplication::SetMousePos(Math::Point pos)
+{
+ // TODO
+}
+
+void CApplication::StepSimulation(float rTime)
+{
+ // TODO
+}
+
+void SetShowStat(bool show)
+{
+ // TODO
+}
+
+bool CApplication::RetShowStat()
+{
+ // TODO
+ return false;
+}
+
+void CApplication::SetDebugMode(bool mode)
+{
+ // TODO
+}
+
+bool CApplication::RetDebugMode()
+{
+ // TODO
+ return false;
+}
+
+bool CApplication::RetSetupMode()
+{
+ // TODO
+ return false;
+}
+
+void CApplication::FlushPressKey()
+{
+ // TODO
+}
+
+void CApplication::ResetKey()
+{
+ // TODO
+}
+
+void CApplication::SetKey(int keyRank, int option, int key)
+{
+ // TODO
+}
+
+int CApplication::RetKey(int keyRank, int option)
+{
+ // TODO
+ return 0;
+}
+
+void CApplication::SetJoystick(bool enable)
+{
+ // TODO
+}
+
+bool CApplication::RetJoystick()
+{
+ // TODO
+ return false;
+}
+
+void SetMouseType(Gfx::MouseType type)
+{
+ // TODO
+}
+
+void SetNiceMouse(bool nice)
+{
+ // TODO
+}
+
+bool CApplication::RetNiceMouse()
+{
+ return false;
+}
+
+bool CApplication::RetNiceMouseCap()
+{
+ return false;
+}
+
+bool CApplication::WriteScreenShot(char *filename, int width, int height)
+{
+ // TODO
+}
+
+void CApplication::InitText()
+{
+ // TODO
+}
+
+void CApplication::DrawSuppl()
+{
+ // TODO
+}
+
+void CApplication::ShowStats()
+{
+ // TODO
+}
+
+void CApplication::OutputText(long x, long y, char* str)
+{
+ // TODO
+}
diff --git a/src/app/app.h b/src/app/app.h
index ee4965d..ee6184f 100644
--- a/src/app/app.h
+++ b/src/app/app.h
@@ -21,40 +21,59 @@
#include "common/misc.h"
+#include "graphics/common/device.h"
#include "graphics/common/engine.h"
+#include <string>
+
class CInstanceManager;
class CEvent;
class CRobotMain;
class CSound;
+struct ApplicationPrivate;
+
+/**
+ * \class CApplication Main application
+ *
+ * This class is responsible for creating and handling main application window,
+ * receiving events, etc.
+ *
+ * ...
+ */
class CApplication
{
public:
+ //! Constructor (can only be called once!)
CApplication();
+ //! Destructor
~CApplication();
+public:
+ //! Parses commandline arguments
+ Error ParseArguments(int argc, char *argv[]);
+ //! Initializes the application
+ bool Create();
+ //! Main event loop
+ int Run();
+
protected:
- //LRESULT OnQuerySuspend( DWORD dwFlags );
- //LRESULT OnResumeSuspend( DWORD dwData );
+ //! Cleans up before exit
+ void Destroy();
+ //! Processes an SDL event to Event struct
+ void ParseEvent();
+ //! Handles some incoming events
+ void ProcessEvent(Event event);
+ //! Renders the image in window
+ bool Render();
public:
- Error RegQuery();
- Error AudioQuery();
- Error CheckMistery(char *strCmdLine);
- int GetVidMemTotal();
- bool IsVideo8MB();
- bool IsVideo32MB();
- //HRESULT Create( HINSTANCE, TCHAR* );
- int Run();
- //LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
void Pause(bool pause);
- //Math::Point ConvPosToInterface(HWND hWnd, LPARAM lParam);
+ void StepSimulation(float rTime);
+
void SetMousePos(Math::Point pos);
- void StepSimul(float rTime);
- char* RetCDpath();
void SetShowStat(bool show);
bool RetShowStat();
@@ -62,30 +81,21 @@ public:
bool RetDebugMode();
bool RetSetupMode();
- bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
- bool RetFullScreen();
- bool ChangeDevice(char *device, char *mode, bool bFull);
-
void FlushPressKey();
void ResetKey();
void SetKey(int keyRank, int option, int key);
int RetKey(int keyRank, int option);
- void SetJoystick(bool bEnable);
+ void SetJoystick(bool enable);
bool RetJoystick();
void SetMouseType(Gfx::MouseType type);
- void SetNiceMouse(bool bNice);
+ void SetNiceMouse(bool nice);
bool RetNiceMouse();
bool RetNiceMouseCap();
bool WriteScreenShot(char *filename, int width, int height);
- //bool GetRenderDC(HDC &hDC);
- //bool ReleaseRenderDC(HDC &hDC);
- //PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
- //bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
-
protected:
//HRESULT ConfirmDevice( DDCAPS* pddDriverCaps, D3DDEVICEDESC7* pd3dDeviceDesc );
//HRESULT Initialize3DEnvironment();
@@ -102,55 +112,42 @@ protected:
void OutputText(long x, long y, char* str);
protected:
+ //! Private (SDL-dependent data)
+ ApplicationPrivate* m_private;
CInstanceManager* m_iMan;
+ Gfx::DeviceConfig m_deviceConfig;
+ Gfx::CEngine* m_engine;
CEvent* m_event;
+ CRobotMain* m_robotMain;
+ CSound* m_sound;
- //HINSTANCE m_instance;
- //HWND m_hWnd;
- //D3DEnum_DeviceInfo* m_pDeviceInfo;
- //LPDIRECTDRAW7 m_pDD;
- //LPDIRECT3D7 m_pD3D;
- //LPDIRECT3DDEVICE7 m_pD3DDevice;
- //LPDIRECTDRAWSURFACE7 m_pddsRenderTarget;
- //DDSURFACEDESC2 m_ddsdRenderTarget;
- //LPDIRECTDRAWSURFACE7 m_pddsDepthBuffer;
-
- //HANDLE m_thread;
- //DWORD m_threadId;
+ //! Code to return at exit
+ int m_exitCode;
- char m_CDpath[100];
-
- //CD3DFramework7* m_pFramework;
bool m_active;
bool m_activateApp;
bool m_ready;
bool m_joystick;
+ std::string m_windowTitle;
long m_vidMemTotal;
- char* m_strWindowTitle;
- bool m_bAppUseZBuffer;
- bool m_bAppUseStereo;
- bool m_bShowStats;
- bool m_bDebugMode;
- bool m_bAudioState;
- bool m_bAudioTrack;
- bool m_bNiceMouse;
- bool m_bSetupMode;
- //HRESULT (*m_fnConfirmDevice)(DDCAPS*, D3DDEVICEDESC7*);
-
-public:
- Gfx::CEngine* m_pD3DEngine;
- CRobotMain* m_pRobotMain;
- CSound* m_pSound;
+ bool m_appUseZBuffer;
+ bool m_appUseStereo;
+ bool m_showStats;
+ bool m_debugMode;
+ bool m_audioState;
+ bool m_audioTrack;
+ bool m_niceMouse;
+ bool m_setupMode;
int m_keyState;
Math::Vector m_axeKey;
Math::Vector m_axeJoy;
bool m_joyButton[32];
Math::Point m_mousePos;
- long m_mshMouseWheel;
+ long m_mouseWheel;
- float m_aTime;
+ float m_time;
long m_key[50][2];
};
diff --git a/src/app/main.cpp b/src/app/main.cpp
new file mode 100644
index 0000000..28d21ee
--- /dev/null
+++ b/src/app/main.cpp
@@ -0,0 +1,41 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// main.cpp
+
+#include "app/app.h"
+#include "app/system.h"
+#include "common/misc.h"
+#include "common/restext.h"
+
+
+//! Entry point to the program
+int main(int argc, char *argv[])
+{
+ CApplication app; // single instance of the application
+
+ Error err = app.ParseArguments(argc, argv);
+ if (err != ERR_OK)
+ {
+ SystemDialog(SDT_ERROR, "COLOBOT", "Invalid commandline arguments!\n");
+ }
+
+ if (! app.Create())
+ return 0;
+
+ return app.Run();
+}
diff --git a/src/app/system.cpp b/src/app/system.cpp
new file mode 100644
index 0000000..4f7cd26
--- /dev/null
+++ b/src/app/system.cpp
@@ -0,0 +1,253 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// system.cpp
+
+#include "app/system.h"
+
+#include "common/config.h"
+
+#if defined(PLATFORM_WINDOWS)
+#include <windows.h>
+#elif defined(PLATFORM_LINUX)
+#include <cstdlib>
+#else
+#include <iostream>
+#endif
+
+
+
+SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message);
+SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message);
+SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message);
+
+/**
+ * Displays a system dialog with info, error, question etc. message.
+ *
+ * \param type type of dialog
+ * \param message text of message (in UTF-8)
+ * \param title dialog title (in UTF-8)
+ * \returns result (which button was clicked)
+ */
+SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message)
+{
+ #if defined(PLATFORM_WINDOWS)
+ return SystemDialog_Windows(type, title, message);
+ #elif defined(PLATFORM_LINUX)
+ return SystemDialog_Linux(type, title, message);
+ #else
+ return SystemDialog_Other(type, title, message);
+ #endif
+}
+
+
+
+#if defined(PLATFORM_WINDOWS)
+
+// Convert a wide Unicode string to an UTF8 string
+std::string UTF8_Encode_Windows(const std::wstring &wstr)
+{
+ int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
+ std::string strTo(size_needed, 0);
+ WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
+ return strTo;
+}
+
+// Convert an UTF8 string to a wide Unicode String
+std::wstring UTF8_Decode_Windows(const std::string &str)
+{
+ int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
+ std::wstring wstrTo(size_needed, 0);
+ MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
+ return wstrTo;
+}
+
+SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message)
+{
+ unsigned int windowsType = 0;
+ std::wstring windowsMessage = UTF8_Decode_Windows(message);
+ std::wstring windowsTitle = UTF8_Decode_Windows(title);
+
+ switch (type)
+ {
+ case SDT_INFO:
+ default:
+ windowsType = MB_ICONINFORMATION|MB_OK;
+ break;
+ case SDT_WARNING:
+ windowsType = MB_ICONWARNING|MB_OK;
+ break;
+ case SDT_ERROR:
+ windowsType = MB_ICONERROR|MB_OK;
+ break;
+ case SDT_YES_NO:
+ windowsType = MB_ICONQUESTION|MB_YESNO;
+ break;
+ case SDT_OK_CANCEL:
+ windowsType = MB_ICONWARNING|MB_OKCANCEL;
+ break;
+ }
+
+ switch (MessageBoxW(NULL, windowsMessage.c_str(), windowsTitle.c_str(), windowsType))
+ {
+ case IDOK:
+ return SDR_OK;
+ case IDCANCEL:
+ return SDR_CANCEL;
+ case IDYES:
+ return SDR_YES;
+ case IDNO:
+ return SDR_NO;
+ default:
+ break;
+ }
+
+ return SDR_OK;
+}
+
+#elif defined(PLATFORM_LINUX)
+
+SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message)
+{
+ std::string options = "";
+ switch (type)
+ {
+ case SDT_INFO:
+ default:
+ options = "--info";
+ break;
+ case SDT_WARNING:
+ options = "--warning";
+ break;
+ case SDT_ERROR:
+ options = "--error";
+ break;
+ case SDT_YES_NO:
+ options = "--question --ok-label=\"Yes\" --cancel-label=\"No\"";
+ break;
+ case SDT_OK_CANCEL:
+ options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\"";
+ break;
+ }
+
+ std::string command = "zenity " + options + " --text=\"" + message + "\" --title=\"" + title + "\"";
+ int code = system(command.c_str());
+
+ SystemDialogResult result = SDR_OK;
+ switch (type)
+ {
+ case SDT_YES_NO:
+ result = code ? SDR_NO : SDR_YES;
+ break;
+ case SDT_OK_CANCEL:
+ result = code ? SDR_CANCEL : SDR_OK;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+#else
+
+SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message)
+{
+ switch (type)
+ {
+ case SDT_INFO:
+ std::cout << "INFO: ";
+ break;
+ case SDT_WARNING:
+ std::cout << "WARNING:";
+ break;
+ case SDT_ERROR:
+ std::cout << "ERROR: ";
+ break;
+ case SDT_YES_NO:
+ case SDT_OK_CANCEL:
+ std::cout << "QUESTION: ";
+ break;
+ }
+
+ std::cout << message << std::endl;
+
+ std::string line;
+
+ SystemDialogResult result = SDR_OK;
+
+ bool done = false;
+ while (!done)
+ {
+ switch (type)
+ {
+ case SDT_INFO:
+ case SDT_WARNING:
+ case SDT_ERROR:
+ std::cout << "Press ENTER to continue";
+ break;
+
+ case SDT_YES_NO:
+ std::cout << "Type 'Y' for Yes or 'N' for No";
+ break;
+
+ case SDT_OK_CANCEL:
+ std::cout << "Type 'O' for OK or 'C' for Cancel";
+ break;
+ }
+
+ std::getline(std::cin, line);
+
+ switch (type)
+ {
+ case SDT_INFO:
+ case SDT_WARNING:
+ case SDT_ERROR:
+ done = true;
+ break;
+
+ case SDT_YES_NO:
+ if (line == "Y" || line == "y")
+ {
+ result = SDR_YES;
+ done = true;
+ }
+ else if (line == "N" || line == "n")
+ {
+ result = SDR_NO;
+ done = true;
+ }
+ break;
+
+ case SDT_OK_CANCEL:
+ if (line == "O" || line == "o")
+ {
+ done = true;
+ result = SDR_OK;
+ }
+ else if (line == "C" || line == "c")
+ {
+ done = true;
+ result = SDR_CANCEL;
+ }
+ break;
+ }
+ }
+
+ return result;
+}
+#endif // if defined(PLATFORM_WINDOWS)
diff --git a/src/app/system.h b/src/app/system.h
new file mode 100644
index 0000000..fd1c051
--- /dev/null
+++ b/src/app/system.h
@@ -0,0 +1,57 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// system.h
+
+#pragma once
+
+
+#include <string>
+
+
+/**
+ * \enum SysDialogType Type of system dialog
+ */
+enum SystemDialogType
+{
+ //! Information message
+ SDT_INFO,
+ //! Warning message
+ SDT_WARNING,
+ //! Error message
+ SDT_ERROR,
+ //! Yes/No question
+ SDT_YES_NO,
+ //! Ok/Cancel question
+ SDT_OK_CANCEL
+};
+
+/**
+ * \enum SysDialogResult Result of system dialog
+ *
+ * Means which button was pressed.
+ */
+enum SystemDialogResult
+{
+ SDR_OK,
+ SDR_CANCEL,
+ SDR_YES,
+ SDR_NO
+};
+
+//! Displays a system dialog
+SystemDialogResult SystemDialog(SystemDialogType, const std::string &title, const std::string &message);