ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

sdl.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #define FORBIDDEN_SYMBOL_ALLOW_ALL
00024 
00025 #include "backends/platform/sdl/sdl.h"
00026 #include "common/config-manager.h"
00027 #include "gui/EventRecorder.h"
00028 #include "common/taskbar.h"
00029 #include "common/textconsole.h"
00030 #include "common/translation.h"
00031 #include "common/encoding.h"
00032 
00033 #include "backends/saves/default/default-saves.h"
00034 
00035 // Audio CD support was removed with SDL 2.0
00036 #if SDL_VERSION_ATLEAST(2, 0, 0)
00037 #include "backends/audiocd/default/default-audiocd.h"
00038 #else
00039 #include "backends/audiocd/sdl/sdl-audiocd.h"
00040 #endif
00041 
00042 #include "backends/events/default/default-events.h"
00043 // ResidualVM:
00044 // #include "backends/events/sdl/sdl-events.h"
00045 // ResidualVM:
00046 // #include "backends/events/sdl/legacy-sdl-events.h"
00047 #include "backends/events/sdl/resvm-sdl-events.h"
00048 #include "backends/keymapper/hardware-input.h"
00049 #include "backends/mutex/sdl/sdl-mutex.h"
00050 #include "backends/timer/sdl/sdl-timer.h"
00051 #include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
00052 
00053 #ifdef USE_OPENGL
00054 #include "backends/graphics/openglsdl/openglsdl-graphics.h"
00055 //#include "graphics/cursorman.h" // ResidualVM
00056 #include "graphics/opengl/context.h" // ResidualVM specific
00057 #endif
00058 #include "graphics/renderer.h" // ResidualVM specific
00059 
00060 #include <time.h>   // for getTimeAndDate()
00061 
00062 #ifdef USE_DETECTLANG
00063 #ifndef WIN32
00064 #include <locale.h>
00065 #endif // !WIN32
00066 #endif
00067 
00068 #ifdef USE_SDL_NET
00069 #include <SDL_net.h>
00070 #endif
00071 
00072 #if SDL_VERSION_ATLEAST(2, 0, 0)
00073 #include <SDL_clipboard.h>
00074 #endif
00075 
00076 OSystem_SDL::OSystem_SDL()
00077     :
00078 #if 0 // ResidualVM - not used
00079 #ifdef USE_OPENGL
00080     _graphicsModes(),
00081     _graphicsMode(0),
00082     _firstGLMode(0),
00083     _defaultSDLMode(0),
00084     _defaultGLMode(0),
00085 #endif // ResidualVM
00086 #endif
00087     _inited(false),
00088     _initedSDL(false),
00089 #ifdef USE_SDL_NET
00090     _initedSDLnet(false),
00091 #endif
00092     _logger(0),
00093     _mixerManager(0),
00094     _eventSource(0),
00095     _eventSourceWrapper(nullptr),
00096     _window(0) {
00097 }
00098 
00099 OSystem_SDL::~OSystem_SDL() {
00100     SDL_ShowCursor(SDL_ENABLE);
00101 
00102     // Delete the various managers here. Note that the ModularBackend
00103     // destructor would also take care of this for us. However, various
00104     // of our managers must be deleted *before* we call SDL_Quit().
00105     // Hence, we perform the destruction on our own.
00106     delete _savefileManager;
00107     _savefileManager = 0;
00108     if (_graphicsManager) {
00109         dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->deactivateManager();
00110     }
00111     delete _graphicsManager;
00112     _graphicsManager = 0;
00113     delete _window;
00114     _window = 0;
00115     delete _eventManager;
00116     _eventManager = 0;
00117     delete _eventSourceWrapper;
00118     _eventSourceWrapper = nullptr;
00119     delete _eventSource;
00120     _eventSource = 0;
00121     delete _audiocdManager;
00122     _audiocdManager = 0;
00123     delete _mixerManager;
00124     _mixerManager = 0;
00125 
00126 #ifdef ENABLE_EVENTRECORDER
00127     // HACK HACK HACK
00128     // This is nasty.
00129     delete g_eventRec.getTimerManager();
00130 #else
00131     delete _timerManager;
00132 #endif
00133 
00134     _timerManager = 0;
00135     delete _mutexManager;
00136     _mutexManager = 0;
00137 
00138     delete _logger;
00139     _logger = 0;
00140 
00141 #ifdef USE_SDL_NET
00142     if (_initedSDLnet) SDLNet_Quit();
00143 #endif
00144 
00145     SDL_Quit();
00146 }
00147 
00148 void OSystem_SDL::init() {
00149     // Initialize SDL
00150     initSDL();
00151 
00152 #if !SDL_VERSION_ATLEAST(2, 0, 0)
00153     // Enable unicode support if possible
00154     SDL_EnableUNICODE(1);
00155 #endif
00156 
00157     // Disable OS cursor
00158     SDL_ShowCursor(SDL_DISABLE);
00159 
00160     // Creates the early needed managers, if they don't exist yet
00161     // (we check for this to allow subclasses to provide their own).
00162     if (_mutexManager == 0)
00163         _mutexManager = new SdlMutexManager();
00164 
00165     if (_window == 0)
00166         _window = new SdlWindow();
00167 
00168 #if defined(USE_TASKBAR)
00169     if (_taskbarManager == 0)
00170         _taskbarManager = new Common::TaskbarManager();
00171 #endif
00172 
00173 }
00174 
00175 bool OSystem_SDL::hasFeature(Feature f) {
00176 #if SDL_VERSION_ATLEAST(2, 0, 0)
00177     if (f == kFeatureClipboardSupport) return true;
00178 #endif
00179     if (f == kFeatureJoystickDeadzone || f == kFeatureKbdMouseSpeed) {
00180         return _eventSource->isJoystickConnected();
00181     }
00182     return ModularBackend::hasFeature(f);
00183 }
00184 
00185 void OSystem_SDL::initBackend() {
00186     // Check if backend has not been initialized
00187     assert(!_inited);
00188 
00189     if (!_logger)
00190         _logger = new Backends::Log::Log(this);
00191 
00192     if (_logger) {
00193         Common::WriteStream *logFile = createLogFile();
00194         if (logFile)
00195             _logger->open(logFile);
00196     }
00197 
00198 #if SDL_VERSION_ATLEAST(2, 0, 0)
00199     const char *sdlDriverName = SDL_GetCurrentVideoDriver();
00200     // Allow the screen to turn off
00201     SDL_EnableScreenSaver();
00202 #else
00203     const int maxNameLen = 20;
00204     char sdlDriverName[maxNameLen];
00205     sdlDriverName[0] = '\0';
00206     SDL_VideoDriverName(sdlDriverName, maxNameLen);
00207 #endif
00208     debug(1, "Using SDL Video Driver \"%s\"", sdlDriverName);
00209 
00210 // ResidualVM specific code start
00211 #ifdef USE_OPENGL
00212     detectFramebufferSupport();
00213     detectAntiAliasingSupport();
00214 #endif
00215 // ResidualVM specific code end
00216 
00217     // Create the default event source, in case a custom backend
00218     // manager didn't provide one yet.
00219     if (!_eventSource)
00220         _eventSource = new ResVmSdlEventSource(); // ResidualVm: was SdlEventSource
00221 
00222 #if !SDL_VERSION_ATLEAST(2, 0, 0)
00223     // SDL 1 does not generate its own keyboard repeat events.
00224     assert(!_eventSourceWrapper);
00225     _eventSourceWrapper = makeKeyboardRepeatingEventSource(_eventSource);
00226 #endif
00227 
00228     if (!_eventManager) {
00229         _eventManager = new DefaultEventManager(_eventSourceWrapper ? _eventSourceWrapper : _eventSource);
00230     }
00231 
00232     if (_graphicsManager == 0) {
00233 #if 0 // ResidualVM - not used
00234 #ifdef USE_OPENGL
00235         // Setup a list with both SDL and OpenGL graphics modes. We only do
00236         // this whenever the subclass did not already set up an graphics
00237         // manager yet. This is because we don't know the type of the graphics
00238         // manager of the subclass, thus we cannot easily switch between the
00239         // OpenGL one and the set up one. It also is to be expected that the
00240         // subclass does not want any switching of graphics managers anyway.
00241         setupGraphicsModes();
00242 
00243         if (ConfMan.hasKey("gfx_mode")) {
00244             // If the gfx_mode is from OpenGL, create the OpenGL graphics manager
00245             Common::String gfxMode(ConfMan.get("gfx_mode"));
00246             for (uint i = _firstGLMode; i < _graphicsModeIds.size(); ++i) {
00247                 if (!scumm_stricmp(_graphicsModes[i].name, gfxMode.c_str())) {
00248                     _graphicsManager = new OpenGLSdlGraphicsManager(_eventSource, _window);
00249                     _graphicsMode = i;
00250                     break;
00251                 }
00252             }
00253         }
00254 #endif // ResidualVM
00255 #endif
00256 
00257         if (_graphicsManager == 0) {
00258             _graphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window);
00259         }
00260     }
00261 
00262     if (_savefileManager == 0)
00263         _savefileManager = new DefaultSaveFileManager();
00264 
00265     if (_mixerManager == 0) {
00266         _mixerManager = new SdlMixerManager();
00267         // Setup and start mixer
00268         _mixerManager->init();
00269     }
00270 
00271 #ifdef ENABLE_EVENTRECORDER
00272     g_eventRec.registerMixerManager(_mixerManager);
00273 
00274     g_eventRec.registerTimerManager(new SdlTimerManager());
00275 #else
00276     if (_timerManager == 0)
00277         _timerManager = new SdlTimerManager();
00278 #endif
00279 
00280     _audiocdManager = createAudioCDManager();
00281 
00282     // Setup a custom program icon.
00283     _window->setupIcon();
00284 
00285     _inited = true;
00286 
00287     ModularBackend::initBackend();
00288 
00289     // We have to initialize the graphics manager before the event manager
00290     // so the virtual keyboard can be initialized, but we have to add the
00291     // graphics manager as an event observer after initializing the event
00292     // manager.
00293     dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->activateManager();
00294 }
00295 
00296 // ResidualVM specific code - Start
00297 #ifdef USE_OPENGL
00298 void OSystem_SDL::detectFramebufferSupport() {
00299     _capabilities.openGLFrameBuffer = false;
00300 #if defined(USE_GLES2)
00301     // Framebuffers are always available with GLES2
00302     _capabilities.openGLFrameBuffer = true;
00303 #elif !defined(AMIGAOS)
00304     // Spawn a 32x32 window off-screen with a GL context to test if framebuffers are supported
00305 #if SDL_VERSION_ATLEAST(2, 0, 0)
00306     SDL_Window *window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 32, 32, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
00307     if (window) {
00308         SDL_GLContext glContext = SDL_GL_CreateContext(window);
00309         if (glContext) {
00310             OpenGLContext.initialize(OpenGL::kContextGL);
00311             _capabilities.openGLFrameBuffer = OpenGLContext.framebufferObjectSupported;
00312             OpenGLContext.reset();
00313             SDL_GL_DeleteContext(glContext);
00314         }
00315         SDL_DestroyWindow(window);
00316     }
00317 #else
00318     SDL_putenv(const_cast<char *>("SDL_VIDEO_WINDOW_POS=9000,9000"));
00319     SDL_SetVideoMode(32, 32, 0, SDL_OPENGL);
00320     SDL_putenv(const_cast<char *>("SDL_VIDEO_WINDOW_POS=center"));
00321     OpenGLContext.initialize(OpenGL::kContextGL);
00322     _capabilities.openGLFrameBuffer = OpenGLContext.framebufferObjectSupported;
00323     OpenGLContext.reset();
00324 #endif
00325 #endif
00326 }
00327 
00328 void OSystem_SDL::detectAntiAliasingSupport() {
00329     _capabilities.openGLAntiAliasLevels.clear();
00330 
00331     int requestedSamples = 2;
00332     while (requestedSamples <= 32) {
00333         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
00334         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, requestedSamples);
00335 
00336 #if SDL_VERSION_ATLEAST(2, 0, 0)
00337         SDL_Window *window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 32, 32, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
00338         if (window) {
00339             SDL_GLContext glContext = SDL_GL_CreateContext(window);
00340             if (glContext) {
00341                 int actualSamples = 0;
00342                 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &actualSamples);
00343 
00344                 if (actualSamples == requestedSamples) {
00345                     _capabilities.openGLAntiAliasLevels.push_back(requestedSamples);
00346                 }
00347 
00348                 SDL_GL_DeleteContext(glContext);
00349             }
00350 
00351             SDL_DestroyWindow(window);
00352         }
00353 #else
00354         SDL_putenv(const_cast<char *>("SDL_VIDEO_WINDOW_POS=9000,9000"));
00355         SDL_SetVideoMode(32, 32, 0, SDL_OPENGL);
00356         SDL_putenv(const_cast<char *>("SDL_VIDEO_WINDOW_POS=center"));
00357 
00358         int actualSamples = 0;
00359         SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &actualSamples);
00360 
00361         if (actualSamples == requestedSamples) {
00362             _capabilities.openGLAntiAliasLevels.push_back(requestedSamples);
00363         }
00364 #endif
00365 
00366         requestedSamples *= 2;
00367     }
00368 
00369     SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
00370     SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
00371 }
00372 
00373 #endif // USE_OPENGL
00374 // End of ResidualVM specific code
00375 
00376 void OSystem_SDL::engineInit() {
00377 #if SDL_VERSION_ATLEAST(2, 0, 0)
00378     dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->unlockWindowSize();
00379     // Disable screen saver when engine starts
00380     SDL_DisableScreenSaver();
00381 #endif
00382 #ifdef USE_TASKBAR
00383     // Add the started engine to the list of recent tasks
00384     _taskbarManager->addRecent(ConfMan.getActiveDomainName(), ConfMan.get("description"));
00385 
00386     // Set the overlay icon the current running engine
00387     _taskbarManager->setOverlayIcon(ConfMan.getActiveDomainName(), ConfMan.get("description"));
00388 #endif
00389     _eventSource->setEngineRunning(true);
00390 }
00391 
00392 void OSystem_SDL::engineDone() {
00393 #if SDL_VERSION_ATLEAST(2, 0, 0)
00394     dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->unlockWindowSize();
00395     SDL_EnableScreenSaver();
00396 #endif
00397 #ifdef USE_TASKBAR
00398     // Remove overlay icon
00399     _taskbarManager->setOverlayIcon("", "");
00400 #endif
00401     _eventSource->setEngineRunning(false);
00402 }
00403 
00404 void OSystem_SDL::initSDL() {
00405     // Check if SDL has not been initialized
00406     if (!_initedSDL) {
00407         // We always initialize the video subsystem because we will need it to
00408         // be initialized before the graphics managers to retrieve the desktop
00409         // resolution, for example. WebOS also requires this initialization
00410         // or otherwise the application won't start.
00411         uint32 sdlFlags = SDL_INIT_VIDEO;
00412 
00413         if (ConfMan.hasKey("disable_sdl_parachute"))
00414             sdlFlags |= SDL_INIT_NOPARACHUTE;
00415 
00416         // Initialize SDL (SDL Subsystems are initialized in the corresponding sdl managers)
00417         if (SDL_Init(sdlFlags) == -1)
00418             error("Could not initialize SDL: %s", SDL_GetError());
00419 
00420         _initedSDL = true;
00421     }
00422 
00423 #ifdef USE_SDL_NET
00424     // Check if SDL_net has not been initialized
00425     if (!_initedSDLnet) {
00426         // Initialize SDL_net
00427         if (SDLNet_Init() == -1)
00428             error("Could not initialize SDL_net: %s", SDLNet_GetError());
00429 
00430         _initedSDLnet = true;
00431     }
00432 #endif
00433 }
00434 
00435 void OSystem_SDL::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
00436 
00437 #ifdef DATA_PATH
00438     // Add the global DATA_PATH to the directory search list
00439     // FIXME: We use depth = 4 for now, to match the old code. May want to change that
00440     Common::FSNode dataNode(DATA_PATH);
00441     if (dataNode.exists() && dataNode.isDirectory()) {
00442         s.add(DATA_PATH, new Common::FSDirectory(dataNode, 4), priority);
00443     }
00444 #endif
00445 
00446 }
00447 
00448 void OSystem_SDL::setWindowCaption(const char *caption) {
00449     Common::String cap;
00450     byte c;
00451 
00452     // The string caption is supposed to be in LATIN-1 encoding.
00453     // SDL expects UTF-8. So we perform the conversion here.
00454     while ((c = *(const byte *)caption++)) {
00455         if (c < 0x80)
00456             cap += c;
00457         else {
00458             cap += 0xC0 | (c >> 6);
00459             cap += 0x80 | (c & 0x3F);
00460         }
00461     }
00462 
00463     _window->setWindowCaption(cap);
00464 }
00465 
00466 // ResidualVM specific code
00467 #ifdef USE_OPENGL
00468 void OSystem_SDL::setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) {
00469     bool switchedManager = false;
00470     if (accel3d && !dynamic_cast<OpenGLSdlGraphicsManager *>(_graphicsManager)) {
00471         switchedManager = true;
00472     } else if (!accel3d && !dynamic_cast<SurfaceSdlGraphicsManager *>(_graphicsManager)) {
00473         switchedManager = true;
00474     }
00475 
00476     if (switchedManager) {
00477         SdlGraphicsManager *sdlGraphicsManager = dynamic_cast<SdlGraphicsManager *>(_graphicsManager);
00478         sdlGraphicsManager->deactivateManager();
00479         delete _graphicsManager;
00480 
00481         if (accel3d) {
00482             _graphicsManager = sdlGraphicsManager = new OpenGLSdlGraphicsManager(_eventSource, _window, _capabilities);
00483         } else {
00484             _graphicsManager = sdlGraphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window);
00485         }
00486         sdlGraphicsManager->activateManager();
00487     }
00488 
00489     ModularBackend::setupScreen(screenW, screenH, fullscreen, accel3d);
00490 }
00491 
00492 Common::Array<uint> OSystem_SDL::getSupportedAntiAliasingLevels() const {
00493     return _capabilities.openGLAntiAliasLevels;
00494 }
00495 #endif
00496 
00497 void OSystem_SDL::launcherInitSize(uint w, uint h) {
00498     Common::String rendererConfig = ConfMan.get("renderer");
00499     Graphics::RendererType desiredRendererType = Graphics::parseRendererTypeCode(rendererConfig);
00500     Graphics::RendererType matchingRendererType = Graphics::getBestMatchingAvailableRendererType(desiredRendererType);
00501 
00502     bool fullscreen = ConfMan.getBool("fullscreen");
00503 
00504     setupScreen(w, h, fullscreen, matchingRendererType != Graphics::kRendererTypeTinyGL);
00505 }
00506 
00507 // End of ResidualVM specific code
00508 
00509 void OSystem_SDL::quit() {
00510     destroy();
00511     exit(0);
00512 }
00513 
00514 void OSystem_SDL::fatalError() {
00515     destroy();
00516     exit(1);
00517 }
00518 
00519 Common::KeymapArray OSystem_SDL::getGlobalKeymaps() {
00520     Common::KeymapArray globalMaps = ModularBackend::getGlobalKeymaps();
00521 
00522     SdlGraphicsManager *graphicsManager = dynamic_cast<SdlGraphicsManager *>(_graphicsManager);
00523     globalMaps.push_back(graphicsManager->getKeymap());
00524 
00525     return globalMaps;
00526 }
00527 
00528 Common::HardwareInputSet *OSystem_SDL::getHardwareInputSet() {
00529     using namespace Common;
00530 
00531     CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
00532     inputSet->addHardwareInputSet(new MouseHardwareInputSet(defaultMouseButtons));
00533     inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
00534 
00535     if (_eventSource->isJoystickConnected()) {
00536         inputSet->addHardwareInputSet(new JoystickHardwareInputSet(defaultJoystickButtons, defaultJoystickAxes));
00537     }
00538 
00539     return inputSet;
00540 }
00541 
00542 void OSystem_SDL::logMessage(LogMessageType::Type type, const char *message) {
00543     // First log to stdout/stderr
00544     FILE *output = 0;
00545 
00546     if (type == LogMessageType::kInfo || type == LogMessageType::kDebug)
00547         output = stdout;
00548     else
00549         output = stderr;
00550 
00551     fputs(message, output);
00552     fflush(output);
00553 
00554     // Then log into file (via the logger)
00555     if (_logger)
00556         _logger->print(message);
00557 }
00558 
00559 Common::WriteStream *OSystem_SDL::createLogFile() {
00560     // Start out by resetting _logFilePath, so that in case
00561     // of a failure, we know that no log file is open.
00562     _logFilePath.clear();
00563 
00564     Common::String logFile;
00565     if (ConfMan.hasKey("logfile"))
00566         logFile = ConfMan.get("logfile");
00567     else
00568         logFile = getDefaultLogFileName();
00569     if (logFile.empty())
00570         return nullptr;
00571 
00572     Common::FSNode file(logFile);
00573     Common::WriteStream *stream = file.createWriteStream();
00574     if (stream)
00575         _logFilePath = logFile;
00576     return stream;
00577 }
00578 
00579 Common::String OSystem_SDL::getSystemLanguage() const {
00580 #if defined(USE_DETECTLANG) && !defined(WIN32)
00581     // Activating current locale settings
00582     const Common::String locale = setlocale(LC_ALL, "");
00583 
00584     // Restore default C locale to prevent issues with
00585     // portability of sscanf(), atof(), etc.
00586     // See bug #3615148
00587     setlocale(LC_ALL, "C");
00588 
00589     // Detect the language from the locale
00590     if (locale.empty()) {
00591         return ModularBackend::getSystemLanguage();
00592     } else {
00593         int length = 0;
00594 
00595         // Strip out additional information, like
00596         // ".UTF-8" or the like. We do this, since
00597         // our translation languages are usually
00598         // specified without any charset information.
00599         for (int size = locale.size(); length < size; ++length) {
00600             // TODO: Check whether "@" should really be checked
00601             // here.
00602             if (locale[length] == '.' || locale[length] == ' ' || locale[length] == '@')
00603                 break;
00604         }
00605 
00606         return Common::String(locale.c_str(), length);
00607     }
00608 #else // USE_DETECTLANG
00609     return ModularBackend::getSystemLanguage();
00610 #endif // USE_DETECTLANG
00611 }
00612 
00613 #if SDL_VERSION_ATLEAST(2, 0, 0)
00614 bool OSystem_SDL::hasTextInClipboard() {
00615     return SDL_HasClipboardText() == SDL_TRUE;
00616 }
00617 
00618 Common::String OSystem_SDL::getTextFromClipboard() {
00619     if (!hasTextInClipboard()) return "";
00620 
00621     char *text = SDL_GetClipboardText();
00622     // The string returned by SDL is in UTF-8. Convert to the
00623     // current TranslationManager encoding or ISO-8859-1.
00624 #ifdef USE_TRANSLATION
00625     char *conv_text = SDL_iconv_string(TransMan.getCurrentCharset().c_str(), "UTF-8", text, SDL_strlen(text) + 1);
00626 #else
00627     char *conv_text = SDL_iconv_string("ISO-8859-1", "UTF-8", text, SDL_strlen(text) + 1);
00628 #endif
00629     if (conv_text) {
00630         SDL_free(text);
00631         text = conv_text;
00632     }
00633     Common::String strText = text;
00634     SDL_free(text);
00635 
00636     return strText;
00637 }
00638 
00639 bool OSystem_SDL::setTextInClipboard(const Common::String &text) {
00640     // The encoding we need to use is UTF-8. Assume we currently have the
00641     // current TranslationManager encoding or ISO-8859-1.
00642 #ifdef USE_TRANSLATION
00643     char *utf8_text = SDL_iconv_string("UTF-8", TransMan.getCurrentCharset().c_str(), text.c_str(), text.size() + 1);
00644 #else
00645     char *utf8_text = SDL_iconv_string("UTF-8", "ISO-8859-1", text.c_str(), text.size() + 1);
00646 #endif
00647     if (utf8_text) {
00648         int status = SDL_SetClipboardText(utf8_text);
00649         SDL_free(utf8_text);
00650         return status == 0;
00651     }
00652     return SDL_SetClipboardText(text.c_str()) == 0;
00653 }
00654 #endif
00655 
00656 uint32 OSystem_SDL::getMillis(bool skipRecord) {
00657     uint32 millis = SDL_GetTicks();
00658 
00659 #ifdef ENABLE_EVENTRECORDER
00660     g_eventRec.processMillis(millis, skipRecord);
00661 #endif
00662 
00663     return millis;
00664 }
00665 
00666 void OSystem_SDL::delayMillis(uint msecs) {
00667 #ifdef ENABLE_EVENTRECORDER
00668     if (!g_eventRec.processDelayMillis())
00669 #endif
00670         SDL_Delay(msecs);
00671 }
00672 
00673 void OSystem_SDL::getTimeAndDate(TimeDate &td) const {
00674     time_t curTime = time(0);
00675     struct tm t = *localtime(&curTime);
00676     td.tm_sec = t.tm_sec;
00677     td.tm_min = t.tm_min;
00678     td.tm_hour = t.tm_hour;
00679     td.tm_mday = t.tm_mday;
00680     td.tm_mon = t.tm_mon;
00681     td.tm_year = t.tm_year;
00682     td.tm_wday = t.tm_wday;
00683 }
00684 
00685 Audio::Mixer *OSystem_SDL::getMixer() {
00686     assert(_mixerManager);
00687     return getMixerManager()->getMixer();
00688 }
00689 
00690 SdlMixerManager *OSystem_SDL::getMixerManager() {
00691     assert(_mixerManager);
00692 
00693 #ifdef ENABLE_EVENTRECORDER
00694     return g_eventRec.getMixerManager();
00695 #else
00696     return _mixerManager;
00697 #endif
00698 }
00699 
00700 Common::TimerManager *OSystem_SDL::getTimerManager() {
00701 #ifdef ENABLE_EVENTRECORDER
00702     return g_eventRec.getTimerManager();
00703 #else
00704     return _timerManager;
00705 #endif
00706 }
00707 
00708 AudioCDManager *OSystem_SDL::createAudioCDManager() {
00709     // Audio CD support was removed with SDL 2.0
00710 #if SDL_VERSION_ATLEAST(2, 0, 0)
00711     return new DefaultAudioCDManager();
00712 #else
00713     return new SdlAudioCDManager();
00714 #endif
00715 }
00716 
00717 Common::SaveFileManager *OSystem_SDL::getSavefileManager() {
00718 #ifdef ENABLE_EVENTRECORDER
00719     return g_eventRec.getSaveManager(_savefileManager);
00720 #else
00721     return _savefileManager;
00722 #endif
00723 }
00724 
00725 //Not specified in base class
00726 Common::String OSystem_SDL::getScreenshotsPath() {
00727     Common::String path = ConfMan.get("screenshotpath");
00728     if (!path.empty() && !path.hasSuffix("/"))
00729         path += "/";
00730     return path;
00731 }
00732 
00733 #if 0 // ResidualVM - not used
00734 #ifdef USE_OPENGL
00735 
00736 const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const {
00737     if (_graphicsModes.empty()) {
00738         return _graphicsManager->getSupportedGraphicsModes();
00739     } else {
00740         return _graphicsModes.begin();
00741     }
00742 }
00743 
00744 int OSystem_SDL::getDefaultGraphicsMode() const {
00745     if (_graphicsModes.empty()) {
00746         return _graphicsManager->getDefaultGraphicsMode();
00747     } else {
00748         // Return the default graphics mode from the current graphics manager
00749         if (_graphicsMode < _firstGLMode)
00750             return _defaultSDLMode;
00751         else
00752             return _defaultGLMode;
00753     }
00754 }
00755 
00756 bool OSystem_SDL::setGraphicsMode(int mode) {
00757     if (_graphicsModes.empty()) {
00758         return _graphicsManager->setGraphicsMode(mode);
00759     }
00760 
00761     // Check whether a invalid mode is requested.
00762     if (mode < 0 || (uint)mode >= _graphicsModeIds.size()) {
00763         return false;
00764     }
00765 
00766     // Very hacky way to set up the old graphics manager state, in case we
00767     // switch from SDL->OpenGL or OpenGL->SDL.
00768     //
00769     // This is a probably temporary workaround to fix bugs like #3368143
00770     // "SDL/OpenGL: Crash when switching renderer backend".
00771     SdlGraphicsManager *sdlGraphicsManager = dynamic_cast<SdlGraphicsManager *>(_graphicsManager);
00772     SdlGraphicsManager::State state = sdlGraphicsManager->getState();
00773 
00774     bool switchedManager = false;
00775 
00776     // If the new mode and the current mode are not from the same graphics
00777     // manager, delete and create the new mode graphics manager
00778     if (_graphicsMode >= _firstGLMode && mode < _firstGLMode) {
00779         debug(1, "switching to plain SDL graphics");
00780         sdlGraphicsManager->deactivateManager();
00781         delete _graphicsManager;
00782         _graphicsManager = sdlGraphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window);
00783 
00784         switchedManager = true;
00785     } else if (_graphicsMode < _firstGLMode && mode >= _firstGLMode) {
00786         debug(1, "switching to OpenGL graphics");
00787         sdlGraphicsManager->deactivateManager();
00788         delete _graphicsManager;
00789         _graphicsManager = sdlGraphicsManager = new OpenGLSdlGraphicsManager(_eventSource, _window);
00790 
00791         switchedManager = true;
00792     }
00793 
00794     _graphicsMode = mode;
00795 
00796     if (switchedManager) {
00797         sdlGraphicsManager->activateManager();
00798 
00799         // This failing will probably have bad consequences...
00800         if (!sdlGraphicsManager->setState(state)) {
00801             return false;
00802         }
00803 
00804         // Next setup the cursor again
00805         CursorMan.pushCursor(0, 0, 0, 0, 0, 0);
00806         CursorMan.popCursor();
00807 
00808         // Next setup cursor palette if needed
00809         if (_graphicsManager->getFeatureState(kFeatureCursorPalette)) {
00810             CursorMan.pushCursorPalette(0, 0, 0);
00811             CursorMan.popCursorPalette();
00812         }
00813 
00814         _graphicsManager->beginGFXTransaction();
00815         // Oh my god if this failed the client code might just explode.
00816         return _graphicsManager->setGraphicsMode(_graphicsModeIds[mode]);
00817     } else {
00818         return _graphicsManager->setGraphicsMode(_graphicsModeIds[mode]);
00819     }
00820 }
00821 
00822 int OSystem_SDL::getGraphicsMode() const {
00823     if (_graphicsModes.empty()) {
00824         return _graphicsManager->getGraphicsMode();
00825     } else {
00826         return _graphicsMode;
00827     }
00828 }
00829 
00830 void OSystem_SDL::setupGraphicsModes() {
00831     _graphicsModes.clear();
00832     _graphicsModeIds.clear();
00833     _defaultSDLMode = _defaultGLMode = -1;
00834 
00835     // Count the number of graphics modes
00836     const OSystem::GraphicsMode *srcMode;
00837     int defaultMode;
00838 
00839     GraphicsManager *manager = new SurfaceSdlGraphicsManager(_eventSource, _window);
00840     srcMode = manager->getSupportedGraphicsModes();
00841     defaultMode = manager->getDefaultGraphicsMode();
00842     while (srcMode->name) {
00843         if (defaultMode == srcMode->id) {
00844             _defaultSDLMode = _graphicsModes.size();
00845         }
00846         _graphicsModes.push_back(*srcMode);
00847         srcMode++;
00848     }
00849     delete manager;
00850     assert(_defaultSDLMode != -1);
00851 
00852     _firstGLMode = _graphicsModes.size();
00853     manager = new OpenGLSdlGraphicsManager(_eventSource, _window);
00854     srcMode = manager->getSupportedGraphicsModes();
00855     defaultMode = manager->getDefaultGraphicsMode();
00856     while (srcMode->name) {
00857         if (defaultMode == srcMode->id) {
00858             _defaultGLMode = _graphicsModes.size();
00859         }
00860         _graphicsModes.push_back(*srcMode);
00861         srcMode++;
00862     }
00863     delete manager;
00864     manager = nullptr;
00865     assert(_defaultGLMode != -1);
00866 
00867     // Set a null mode at the end
00868     GraphicsMode nullMode;
00869     memset(&nullMode, 0, sizeof(nullMode));
00870     _graphicsModes.push_back(nullMode);
00871 
00872     // Set new internal ids for all modes
00873     int i = 0;
00874     OSystem::GraphicsMode *mode = _graphicsModes.begin();
00875     while (mode->name) {
00876         _graphicsModeIds.push_back(mode->id);
00877         mode->id = i++;
00878         mode++;
00879     }
00880 }
00881 #endif
00882 #endif // ResidualVM
00883 
00884 char *OSystem_SDL::convertEncoding(const char *to, const char *from, const char *string, size_t length) {
00885 #if SDL_VERSION_ATLEAST(1, 2, 10)
00886     int zeroBytes = 1;
00887     if (Common::String(from).hasPrefixIgnoreCase("utf-16"))
00888         zeroBytes = 2;
00889     else if (Common::String(from).hasPrefixIgnoreCase("utf-32"))
00890         zeroBytes = 4;
00891 
00892     char *result;
00893     // SDL_iconv_string() takes char * instead of const char * as it's third parameter
00894     // with some older versions of SDL.
00895 #if SDL_VERSION_ATLEAST(2, 0, 0)
00896     result = SDL_iconv_string(to, from, string, length + zeroBytes);
00897 #else
00898     char *stringCopy = (char *) calloc(sizeof(char), length + zeroBytes);
00899     memcpy(stringCopy, string, length);
00900     result = SDL_iconv_string(to, from, stringCopy, length + zeroBytes);
00901     free(stringCopy);
00902 #endif // SDL_VERSION_ATLEAST(2, 0, 0)
00903     if (result == nullptr)
00904         return nullptr;
00905 
00906     // We need to copy the result, so that we can use SDL_free()
00907     // on the string returned by SDL_iconv_string() and free()
00908     // can then be used on the copyed and returned string.
00909     // Sometimes free() and SDL_free() aren't compatible and
00910     // using free() instead of SDL_free() can cause crashes.
00911     size_t newLength = Common::Encoding::stringLength(result, to);
00912     zeroBytes = 1;
00913     if (Common::String(to).hasPrefixIgnoreCase("utf-16"))
00914         zeroBytes = 2;
00915     else if (Common::String(to).hasPrefixIgnoreCase("utf-32"))
00916         zeroBytes = 4;
00917     char *finalResult = (char *) malloc(newLength + zeroBytes);
00918     if (!finalResult) {
00919         warning("Could not allocate memory for encoding conversion");
00920         SDL_free(result);
00921         return nullptr;
00922     }
00923     memcpy(finalResult, result, newLength + zeroBytes);
00924     SDL_free(result);
00925     return finalResult;
00926 #else
00927     return ModularBackend::convertEncoding(to, from, string, length);
00928 #endif // SDL_VERSION_ATLEAST(1, 2, 10)
00929 }
00930 


Generated on Sat Aug 8 2020 05:01:05 for ResidualVM by doxygen 1.7.1
curved edge   curved edge