ALL: Synced with ScummVM - rev: 33a47d23b8

This commit is contained in:
Pawel Kolodziejski 2020-09-03 02:01:03 +02:00
parent acd114234f
commit d5304e2568
261 changed files with 79849 additions and 60443 deletions

2
.gitignore vendored
View file

@ -47,6 +47,8 @@ lib*.a
/README.html*
/NEWS
/NEWS.html
/CONTRIBUTING
/CONTRIBUTING.html
/build*
/staging

9
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,9 @@
Thank you for considering contributing to ResidualVM.
Please make sure to read our guidelines for contributions on our
[wiki](https://wiki.scummvm.org/index.php/Developer_Central). In particular:
* [Coding style](https://wiki.scummvm.org/index.php/Code_Formatting_Conventions)
* [Portability](https://wiki.scummvm.org/index.php/Coding_Conventions)
* [Commit message style](https://wiki.scummvm.org/index.php/Commit_Guidelines)
* License: GPLv2+

View file

@ -203,6 +203,11 @@ ifdef AMIGAOS
AMIGA_DATE = $(shell gdate '+%d.%m.%Y')
VERFLAGS += -DAMIGA_DATE=\"$(AMIGA_DATE)\"
endif
ifdef MORPHOS
# MorphOS needs date in specific format for the version cookie
AMIGA_DATE = $(shell date +"%-d.%-m.%Y")
VERFLAGS += -DAMIGA_DATE=\"$(AMIGA_DATE)\"
endif
######################################################################
# Get git's working copy information
@ -247,7 +252,7 @@ VERFILE := $(DISTDIR)/$(DISTNAME)/base/internal_version.h
ifdef USE_PANDOC
# Convert README.md and NEWS.md to plain text for any platform that might require it
PANDOC_CONVERT: README$(PANDOCEXT) NEWS$(PANDOCEXT)
PANDOC_CONVERT: README$(PANDOCEXT) CONTRIBUTING$(PANDOCEXT) NEWS$(PANDOCEXT)
@sed -i'' -e "s/NEWS.md/NEWS$(PANDOCEXT)/g" README$(PANDOCEXT)
@sed -i'' -e "s/CONTRIBUTING.md/CONTRIBUTING$(PANDOCEXT)/g" README$(PANDOCEXT)
@ -285,7 +290,7 @@ dist-src: \
@#DEB-src?
# Common files
DIST_FILES_DOCS:=$(addprefix $(srcdir)/,AUTHORS COPYING COPYING.BSD COPYING.LGPL COPYING.FREEFONT COPYING.OFL COPYING.ISC COPYING.LUA COPYING.MIT COPYING.TINYGL COPYRIGHT KNOWN_BUGS NEWS.md README.md)
DIST_FILES_DOCS:=$(addprefix $(srcdir)/,AUTHORS COPYING COPYING.BSD COPYING.LGPL COPYING.FREEFONT COPYING.OFL COPYING.ISC COPYING.LUA COPYING.MIT COPYING.TINYGL COPYRIGHT KNOWN_BUGS NEWS.md README.md CONTRIBUTING.md)
ifdef USE_PANDOC
DIST_FILES_DOCS+=README$(PANDOCEXT) NEWS$(PANDOCEXT)
endif

View file

@ -91,11 +91,11 @@ SeekableAudioStream *SeekableAudioStream::openStreamFile(const Common::String &b
#pragma mark --- LoopingAudioStream ---
#pragma mark -
LoopingAudioStream::LoopingAudioStream(RewindableAudioStream *stream, uint loops, DisposeAfterUse::Flag disposeAfterUse)
LoopingAudioStream::LoopingAudioStream(RewindableAudioStream *stream, uint loops, DisposeAfterUse::Flag disposeAfterUse, bool rewind)
: _parent(stream, disposeAfterUse), _loops(loops), _completeIterations(0) {
assert(stream);
if (!stream->rewind()) {
if (rewind && !stream->rewind()) {
// TODO: Properly indicate error
_loops = _completeIterations = 1;
}

View file

@ -118,7 +118,7 @@ public:
* @param loops How often to loop (0 = infinite)
* @param disposeAfterUse Destroy the stream after the LoopingAudioStream has finished playback.
*/
LoopingAudioStream(RewindableAudioStream *stream, uint loops, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
LoopingAudioStream(RewindableAudioStream *stream, uint loops, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES, bool rewind = true);
int readBuffer(int16 *buffer, const int numSamples);
bool endOfData() const;

View file

@ -39,6 +39,8 @@ namespace Audio {
//
// In addition, also MS IMA ADPCM is supported. See
// <http://wiki.multimedia.cx/index.php?title=Microsoft_IMA_ADPCM>.
//
// XA ADPCM support is based on FFmpeg/libav
ADPCMStream::ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
: _stream(stream, disposeAfterUse),
@ -119,6 +121,106 @@ int16 Oki_ADPCMStream::decodeOKI(byte code) {
#pragma mark -
int XA_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
int samples;
byte *data = new byte[128];
for (samples = 0; samples < numSamples && !endOfData(); samples++) {
if (_decodedSampleCount == 0) {
uint32 bytesLeft = _stream->size() - _stream->pos();
if (bytesLeft < 128) {
_stream->skip(bytesLeft);
memset(&buffer[samples], 0, (numSamples - samples) * sizeof(uint16));
samples = numSamples;
break;
}
_stream->read(data, 128);
decodeXA(data);
_decodedSampleIndex = 0;
}
// _decodedSamples acts as a FIFO of depth 2 or 4;
buffer[samples] = _decodedSamples[_decodedSampleIndex++];
_decodedSampleCount--;
}
delete[] data;
return samples;
}
static const int s_xaTable[5][2] = {
{ 0, 0 },
{ 60, 0 },
{ 115, -52 },
{ 98, -55 },
{ 122, -60 }
};
void XA_ADPCMStream::decodeXA(const byte *src) {
int16 *leftChannel = _decodedSamples;
int16 *rightChannel = _decodedSamples + 1;
for (int i = 0; i < 4; i++) {
int shift = 12 - (src[4 + i * 2] & 0xf);
int filter = src[4 + i * 2] >> 4;
int f0 = s_xaTable[filter][0];
int f1 = s_xaTable[filter][1];
int16 s_1 = _status.ima_ch[0].sample[0];
int16 s_2 = _status.ima_ch[0].sample[1];
for (int j = 0; j < 28; j++) {
byte d = src[16 + i + j * 4];
int t = (int8)(d << 4) >> 4;
int s = (t << shift) + ((s_1 * f0 + s_2 * f1 + 32) >> 6);
s_2 = s_1;
s_1 = CLIP<int>(s, -32768, 32767);
*leftChannel = s_1;
leftChannel += _channels;
_decodedSampleCount++;
}
if (_channels == 2) {
_status.ima_ch[0].sample[0] = s_1;
_status.ima_ch[0].sample[1] = s_2;
s_1 = _status.ima_ch[1].sample[0];
s_2 = _status.ima_ch[1].sample[1];
}
shift = 12 - (src[5 + i * 2] & 0xf);
filter = src[5 + i * 2] >> 4;
f0 = s_xaTable[filter][0];
f1 = s_xaTable[filter][1];
for (int j = 0; j < 28; j++) {
byte d = src[16 + i + j * 4];
int t = (int8)d >> 4;
int s = (t << shift) + ((s_1 * f0 + s_2 * f1 + 32) >> 6);
s_2 = s_1;
s_1 = CLIP<int>(s, -32768, 32767);
if (_channels == 2) {
*rightChannel = s_1;
rightChannel += 2;
} else {
*leftChannel++ = s_1;
}
_decodedSampleCount++;
}
if (_channels == 2) {
_status.ima_ch[1].sample[0] = s_1;
_status.ima_ch[1].sample[1] = s_2;
} else {
_status.ima_ch[0].sample[0] = s_1;
_status.ima_ch[0].sample[1] = s_2;
}
}
}
#pragma mark -
int DVI_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
int samples;
byte data;
@ -474,6 +576,8 @@ SeekableAudioStream *makeADPCMStream(Common::SeekableReadStream *stream, Dispose
return new Apple_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
case kADPCMDK3:
return new DK3_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
case kADPCMXA:
return new XA_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign);
default:
error("Unsupported ADPCM encoding");
break;
@ -501,6 +605,7 @@ PacketizedAudioStream *makePacketizedADPCMStream(ADPCMType type, int rate, int c
// Filter out types we can't support (they're not fully stateless)
switch (type) {
case kADPCMOki:
case kADPCMXA:
case kADPCMDVI:
return 0;
default:

View file

@ -59,7 +59,8 @@ enum ADPCMType {
kADPCMMS, // Microsoft ADPCM
kADPCMDVI, // Intel DVI IMA ADPCM
kADPCMApple, // Apple QuickTime IMA ADPCM
kADPCMDK3 // Duck DK3 IMA ADPCM
kADPCMDK3, // Duck DK3 IMA ADPCM
kADPCMXA // XA ADPCM
};
/**
@ -88,7 +89,7 @@ SeekableAudioStream *makeADPCMStream(
* packets as individual AudioStreams like returned by makeADPCMStream.
*
* Due to the ADPCM types not necessarily supporting stateless
* streaming, OKI and DVI are not supported by this function
* streaming, OKI, XA and DVI are not supported by this function
* and will return NULL.
*
* @param type the compression type used

View file

@ -54,6 +54,7 @@ protected:
struct {
int32 last;
int32 stepIndex;
int16 sample[2];
} ima_ch[2];
} _status;
@ -97,6 +98,24 @@ private:
int16 _decodedSamples[2];
};
class XA_ADPCMStream : public ADPCMStream {
public:
XA_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign)
: ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { _decodedSampleCount = 0; }
virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
virtual int readBuffer(int16 *buffer, const int numSamples);
protected:
void decodeXA(const byte *src);
private:
uint8 _decodedSampleCount;
uint8 _decodedSampleIndex;
int16 _decodedSamples[28 * 2 * 4];
};
class Ima_ADPCMStream : public ADPCMStream {
protected:
int16 decodeIMA(byte code, int channel = 0); // Default to using the left channel/using one channel

View file

@ -255,7 +255,9 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
// If the expressly selected driver or device cannot be found (no longer compiled in, turned off, etc.)
// we display a warning and continue.
failedDevStr = selDevStr;
Common::String warningMsg = Common::String::format(_("The selected audio device '%s' was not found (e.g. might be turned off or disconnected)."), failedDevStr.c_str()) + " " + _("Attempting to fall back to the next available device...");
Common::U32String warningMsg = Common::U32String::format(
_("The selected audio device '%s' was not found (e.g. might be turned off or disconnected)."), failedDevStr.c_str())
+ Common::U32String(" ") + _("Attempting to fall back to the next available device...");
GUI::MessageDialog dialog(warningMsg);
dialog.runModal();
}
@ -267,7 +269,9 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
} else {
// If the expressly selected device cannot be used we display a warning and continue.
failedDevStr = getDeviceString(hdl, MidiDriver::kDeviceName);
Common::String warningMsg = Common::String::format(_("The selected audio device '%s' cannot be used. See log file for more information."), failedDevStr.c_str()) + " " + _("Attempting to fall back to the next available device...");
Common::U32String warningMsg = Common::U32String::format(
_("The selected audio device '%s' cannot be used. See log file for more information."), failedDevStr.c_str())
+ Common::U32String(" ") + _("Attempting to fall back to the next available device...");
GUI::MessageDialog dialog(warningMsg);
dialog.runModal();
}
@ -303,7 +307,9 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
// we display a warning and continue. Don't warn about the missing device if we did already (this becomes relevant if the
// missing device is selected as preferred device and also as GM or MT-32 device).
if (failedDevStr != devStr) {
Common::String warningMsg = Common::String::format(_("The preferred audio device '%s' was not found (e.g. might be turned off or disconnected)."), devStr.c_str()) + " " + _("Attempting to fall back to the next available device...");
Common::U32String warningMsg = Common::U32String::format(
_("The preferred audio device '%s' was not found (e.g. might be turned off or disconnected)."), devStr.c_str())
+ Common::U32String(" ") + _("Attempting to fall back to the next available device...");
GUI::MessageDialog dialog(warningMsg);
dialog.runModal();
}
@ -318,7 +324,9 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
// Don't warn about the failing device if we did already (this becomes relevant if the failing
// device is selected as preferred device and also as GM or MT-32 device).
if (failedDevStr != getDeviceString(hdl, MidiDriver::kDeviceName)) {
Common::String warningMsg = Common::String::format(_("The preferred audio device '%s' cannot be used. See log file for more information."), getDeviceString(hdl, MidiDriver::kDeviceName).c_str()) + " " + _("Attempting to fall back to the next available device...");
Common::U32String warningMsg = Common::U32String::format(
_("The preferred audio device '%s' cannot be used. See log file for more information."), getDeviceString(hdl, MidiDriver::kDeviceName).c_str())
+ Common::U32String(" ") + _("Attempting to fall back to the next available device...");
GUI::MessageDialog dialog(warningMsg);
dialog.runModal();
}

View file

@ -187,6 +187,8 @@ MixerImpl::~MixerImpl() {
}
void MixerImpl::setReady(bool ready) {
Common::StackLock lock(_mutex);
_mixerReady = ready;
}

View file

@ -76,7 +76,7 @@ public:
MixerImpl(uint sampleRate);
~MixerImpl();
virtual bool isReady() const { return _mixerReady; }
virtual bool isReady() const { Common::StackLock lock(_mutex); return _mixerReady; }
virtual void playStream(
SoundType type,

View file

@ -25,8 +25,8 @@
#include "common/translation.h"
MusicDevice::MusicDevice(MusicPluginObject const *musicPlugin, Common::String name, MusicType mt) :
_musicDriverName(_(musicPlugin->getName())), _musicDriverId(musicPlugin->getId()),
_name(_(name)), _type(mt) {
_musicDriverName(musicPlugin->getName()), _musicDriverId(musicPlugin->getId()),
_name(name), _type(mt) {
}
Common::String MusicDevice::getCompleteName() {
@ -57,5 +57,5 @@ Common::String MusicDevice::getCompleteId() {
}
MidiDriver::DeviceHandle MusicDevice::getHandle() {
return (MidiDriver::DeviceHandle)Common::hashit(getCompleteId().c_str());
return (MidiDriver::DeviceHandle)Common::hashit(getCompleteId());
}

View file

@ -33,19 +33,13 @@
#include "gui/message.h"
void BaseBackend::displayMessageOnOSD(const char *msg) {
void BaseBackend::displayMessageOnOSD(const Common::U32String &msg) {
// Display the message for 1.5 seconds
GUI::TimedMessageDialog dialog(msg, 1500);
dialog.runModal();
}
void BaseBackend::initBackend() {
// Init Event manager
#ifndef DISABLE_DEFAULT_EVENT_MANAGER
if (!_eventManager)
_eventManager = new DefaultEventManager(getDefaultEventSource());
#endif
// Init audio CD manager
#ifndef DISABLE_DEFAULT_AUDIOCD_MANAGER
if (!_audiocdManager)
@ -61,3 +55,13 @@ void BaseBackend::fillScreen(uint32 col) {
screen->fillRect(Common::Rect(screen->w, screen->h), col);
unlockScreen();
}
void EventsBaseBackend::initBackend() {
// Init Event manager
#ifndef DISABLE_DEFAULT_EVENT_MANAGER
if (!_eventManager)
_eventManager = new DefaultEventManager(this);
#endif
BaseBackend::initBackend();
}

View file

@ -27,20 +27,17 @@
#include "common/events.h"
class BaseBackend : public OSystem {
protected:
virtual Common::EventSource *getDefaultEventSource() = 0;
public:
virtual void initBackend();
virtual void displayMessageOnOSD(const char *msg);
virtual void displayMessageOnOSD(const Common::U32String &msg);
virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) {}
virtual void fillScreen(uint32 col);
};
class EventsBaseBackend : public BaseBackend, Common::EventSource {
protected:
virtual Common::EventSource *getDefaultEventSource() { return this; }
class EventsBaseBackend : virtual public BaseBackend, Common::EventSource {
public:
virtual void initBackend();
};

View file

@ -153,8 +153,8 @@ void CloudManager::replaceStorage(Storage *storage, uint32 index) {
_currentStorageIndex = index;
if (_storages[index].username == "") {
// options' Cloud tab believes Storage is connected once it has non-empty username
_storages[index].username = _("<syncing...>");
_storages[index].lastSyncDate = _("<right now>");
_storages[index].username = Common::convertFromU32String(_("<syncing...>"));
_storages[index].lastSyncDate = Common::convertFromU32String(_("<right now>"));
_storages[index].usedBytes = 0;
}
save();

View file

@ -343,13 +343,13 @@ void Storage::directoryDownloadedCallback(FileArrayResponse response) {
_downloadFolderRequest = nullptr;
_runningRequestsMutex.unlock();
Common::String message;
Common::U32String message;
if (response.value.size()) {
message = Common::String::format(_("Download complete.\nFailed to download %u files."), response.value.size());
message = Common::U32String::format(_("Download complete.\nFailed to download %u files."), response.value.size());
} else {
message = _("Download complete.");
}
Common::OSDMessageQueue::instance().addMessage(message.c_str());
Common::OSDMessageQueue::instance().addMessage(message);
}
void Storage::directoryDownloadedErrorCallback(Networking::ErrorResponse error) {

View file

@ -35,40 +35,28 @@
#include <gtk/gtk.h>
Common::DialogManager::DialogResult GtkDialogManager::showFileBrowser(const char *title, Common::FSNode &choice, bool isDirBrowser) {
Common::DialogManager::DialogResult GtkDialogManager::showFileBrowser(const Common::U32String &title, Common::FSNode &choice, bool isDirBrowser) {
if (!gtk_init_check(NULL, NULL))
return kDialogError;
DialogResult result = kDialogCancel;
// Get current encoding
Common::String guiEncoding = "ASCII";
#ifdef USE_TRANSLATION
guiEncoding = TransMan.getCurrentCharset();
#endif
Common::Encoding utf8("utf-8", guiEncoding);
// Convert labels to UTF-8
char *utf8Title = utf8.convert(title, strlen(title));
Common::String choose = _("Choose");
char *utf8Choose = utf8.convert(choose.c_str(), choose.size());
Common::String cancel = _("Cancel");
char* utf8Cancel = utf8.convert(cancel.c_str(), cancel.size());
Common::String utf8Title = title.encode();
Common::String utf8Choose = _("Choose").encode();
Common::String utf8Cancel = _("Cancel").encode();
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
if (isDirBrowser) {
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
}
#if GTK_CHECK_VERSION(3,20,0)
GtkFileChooserNative *native = gtk_file_chooser_native_new(utf8Title, NULL, action, utf8Choose, utf8Cancel);
GtkFileChooserNative *native = gtk_file_chooser_native_new(utf8Title.c_str(), NULL, action, utf8Choose.c_str(), utf8Cancel.c_str());
GtkFileChooser *chooser = GTK_FILE_CHOOSER(native);
#else
GtkWidget *dialog = gtk_file_chooser_dialog_new(utf8Title, NULL, action, utf8Choose, GTK_RESPONSE_ACCEPT, utf8Cancel, GTK_RESPONSE_CANCEL, NULL);
GtkWidget *dialog = gtk_file_chooser_dialog_new(utf8Title.c_str(), NULL, action, utf8Choose.c_str(), GTK_RESPONSE_ACCEPT, utf8Cancel.c_str(), GTK_RESPONSE_CANCEL, NULL);
GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
#endif
free(utf8Cancel);
free(utf8Choose);
free(utf8Title);
// Customize dialog
gtk_file_chooser_set_show_hidden(chooser, ConfMan.getBool("gui_browser_show_hidden", Common::ConfigManager::kApplicationDomain));

View file

@ -30,7 +30,7 @@
class GtkDialogManager : public Common::DialogManager {
public:
virtual DialogResult showFileBrowser(const char *title, Common::FSNode &choice, bool isDirBrowser);
virtual DialogResult showFileBrowser(const Common::U32String &title, Common::FSNode &choice, bool isDirBrowser);
};
#endif

View file

@ -27,10 +27,11 @@
#include "common/fs.h"
#include "common/dialogs.h"
#include "common/ustr.h"
class MacOSXDialogManager : public Common::DialogManager {
public:
virtual DialogResult showFileBrowser(const char *title, Common::FSNode &choice, bool isDirBrowser);
virtual DialogResult showFileBrowser(const Common::U32String &title, Common::FSNode &choice, bool isDirBrowser);
};
#endif

View file

@ -75,14 +75,7 @@
showHiddenFilesButton = [[NSButton alloc] init];
[showHiddenFilesButton setButtonType:NSSwitchButton];
#ifdef USE_TRANSLATION
CFStringRef encStr = CFStringCreateWithCString(NULL, TransMan.getCurrentCharset().c_str(), kCFStringEncodingASCII);
CFStringEncoding stringEncoding = CFStringConvertIANACharSetNameToEncoding(encStr);
CFRelease(encStr);
#else
CFStringEncoding stringEncoding = kCFStringEncodingASCII;
#endif
CFStringRef hiddenFilesString = CFStringCreateWithCString(0, _("Show hidden files"), stringEncoding);
CFStringRef hiddenFilesString = CFStringCreateWithCString(0, _("Show hidden files").encode().c_str(), kCFStringEncodingUTF8);
[showHiddenFilesButton setTitle:(NSString*)hiddenFilesString];
CFRelease(hiddenFilesString);
@ -128,22 +121,15 @@
@end
Common::DialogManager::DialogResult MacOSXDialogManager::showFileBrowser(const char *title, Common::FSNode &choice, bool isDirBrowser) {
Common::DialogManager::DialogResult MacOSXDialogManager::showFileBrowser(const Common::U32String &title, Common::FSNode &choice, bool isDirBrowser) {
DialogResult result = kDialogCancel;
// Get current encoding
#ifdef USE_TRANSLATION
CFStringRef encStr = CFStringCreateWithCString(NULL, TransMan.getCurrentCharset().c_str(), kCFStringEncodingASCII);
CFStringEncoding stringEncoding = CFStringConvertIANACharSetNameToEncoding(encStr);
CFRelease(encStr);
#else
CFStringEncoding stringEncoding = kCFStringEncodingASCII;
#endif
CFStringEncoding stringEncoding = kCFStringEncodingUTF8;
// Convert labels to NSString
CFStringRef titleRef = CFStringCreateWithCString(0, title, stringEncoding);
CFStringRef chooseRef = CFStringCreateWithCString(0, _("Choose"), stringEncoding);
CFStringRef titleRef = CFStringCreateWithCString(0, title.encode().c_str(), stringEncoding);
CFStringRef chooseRef = CFStringCreateWithCString(0, _("Choose").encode().c_str(), stringEncoding);
beginDialog();

View file

@ -95,12 +95,12 @@ HRESULT getShellPath(IShellItem *item, Common::String &path) {
char *str = Win32::unicodeToAnsi(name);
path = Common::String(str);
CoTaskMemFree(name);
delete[] str;
free(str);
}
return hr;
}
Common::DialogManager::DialogResult Win32DialogManager::showFileBrowser(const char *title, Common::FSNode &choice, bool isDirBrowser) {
Common::DialogManager::DialogResult Win32DialogManager::showFileBrowser(const Common::U32String &title, Common::FSNode &choice, bool isDirBrowser) {
DialogResult result = kDialogError;
// Do nothing if not running on Windows Vista or later
@ -130,14 +130,15 @@ Common::DialogManager::DialogResult Win32DialogManager::showFileBrowser(const ch
hr = dialog->SetOptions(dwOptions);
}
LPWSTR str = Win32::ansiToUnicode(title, Win32::getCurrentCharset());
hr = dialog->SetTitle(str);
delete[] str;
LPWSTR dialogTitle = Win32::UTF8ToUnicode(title.encode().c_str());
hr = dialog->SetTitle(dialogTitle);
free(dialogTitle);
str = Win32::ansiToUnicode(_("Choose"), Win32::getCurrentCharset());
hr = dialog->SetOkButtonLabel(str);
delete[] str;
LPWSTR okTitle = Win32::UTF8ToUnicode(_("Choose").encode().c_str());
hr = dialog->SetOkButtonLabel(okTitle);
free(okTitle);
LPWSTR str;
if (ConfMan.hasKey("browser_lastpath")) {
str = Win32::ansiToUnicode(ConfMan.get("browser_lastpath").c_str());
IShellItem *item = NULL;
@ -145,7 +146,7 @@ Common::DialogManager::DialogResult Win32DialogManager::showFileBrowser(const ch
if (SUCCEEDED(hr)) {
hr = dialog->SetDefaultFolder(item);
}
delete[] str;
free(str);
}
// Show dialog

View file

@ -27,6 +27,7 @@
#include "common/fs.h"
#include "common/dialogs.h"
#include "common/ustr.h"
class SdlWindow_Win32;
@ -34,7 +35,7 @@ class Win32DialogManager : public Common::DialogManager {
public:
Win32DialogManager(SdlWindow_Win32 *window);
virtual ~Win32DialogManager();
virtual DialogResult showFileBrowser(const char *title, Common::FSNode &choice, bool isDirBrowser);
virtual DialogResult showFileBrowser(const Common::U32String &title, Common::FSNode &choice, bool isDirBrowser);
private:
SdlWindow_Win32 *_window;

View file

@ -312,6 +312,7 @@ Common::Keymap *DefaultEventManager::getGlobalKeymap() {
act->setEvent(EVENT_MUTE);
globalKeymap->addAction(act);
if (!g_system->hasFeature(OSystem::kFeatureNoQuit)) {
act = new Action("QUIT", _("Quit"));
act->setEvent(EVENT_QUIT);
@ -332,6 +333,7 @@ Common::Keymap *DefaultEventManager::getGlobalKeymap() {
#endif
globalKeymap->addAction(act);
}
act = new Action("DEBUGGER", _("Open Debugger"));
act->addDefaultInputMapping("C+A+d");

View file

@ -426,7 +426,7 @@ bool SdlEventSource::pollEvent(Common::Event &event) {
#endif
// If the screen changed, send an Common::EVENT_SCREEN_CHANGED
int screenID = ((OSystem_SDL *)g_system)->getGraphicsManager()->getScreenChangeID();
int screenID = g_system->getScreenChangeID();
if (screenID != _lastScreenID) {
_lastScreenID = screenID;
event.type = Common::EVENT_SCREEN_CHANGED;
@ -963,7 +963,7 @@ bool SdlEventSource::handleResizeEvent(Common::Event &event, int w, int h) {
_graphicsManager->notifyResize(w, h);
// If the screen changed, send an Common::EVENT_SCREEN_CHANGED
int screenID = ((OSystem_SDL *)g_system)->getGraphicsManager()->getScreenChangeID();
int screenID = g_system->getScreenChangeID();
if (screenID != _lastScreenID) {
_lastScreenID = screenID;
event.type = Common::EVENT_SCREEN_CHANGED;

View file

@ -103,7 +103,7 @@ public:
virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) = 0;
virtual void setCursorPalette(const byte *colors, uint start, uint num) = 0;
virtual void displayMessageOnOSD(const char *msg) {}
virtual void displayMessageOnOSD(const Common::U32String &msg) {}
virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) {}

View file

@ -305,7 +305,7 @@ void SdlGraphicsManager::saveScreenshot() {
#endif
for (int n = 0;; n++) {
filename = Common::String::format("scummvm%s%s-%05d.%s", currentTarget.empty() ? "" : "-",
filename = Common::String::format("residualvm%s%s-%05d.%s", currentTarget.empty() ? "" : "-",
currentTarget.c_str(), n, extension);
Common::FSNode file = Common::FSNode(screenshotsPath + filename);

View file

@ -26,7 +26,7 @@
namespace Common {
Action::Action(const char *i, const String &des) :
Action::Action(const char *i, const U32String &des) :
id(i),
description(des),
_shouldTriggerOnKbdRepeats(false) {

View file

@ -28,6 +28,7 @@
#include "common/array.h"
#include "common/events.h"
#include "common/str.h"
#include "common/ustr.h"
namespace Common {
@ -42,7 +43,7 @@ struct Action {
/** unique id used for saving/loading to config */
const char *id;
/** Human readable description */
String description;
U32String description;
/** Event to be sent when mapped key is pressed */
Event event;
@ -52,7 +53,7 @@ private:
bool _shouldTriggerOnKbdRepeats;
public:
Action(const char *id, const String &description);
Action(const char *id, const U32String &description);
void setEvent(const Event &evt) {
event = evt;

View file

@ -33,7 +33,7 @@
namespace Common {
Keymap::Keymap(KeymapType type, const String &id, const String &description) :
Keymap::Keymap(KeymapType type, const String &id, const U32String &description) :
_type(type),
_id(id),
_description(description),
@ -44,6 +44,17 @@ Keymap::Keymap(KeymapType type, const String &id, const String &description) :
}
Keymap::Keymap(KeymapType type, const String &id, const String &description) :
_type(type),
_id(id),
_description(U32String(description)),
_enabled(true),
_configDomain(nullptr),
_hardwareInputSet(nullptr),
_backendDefaultBindings(nullptr) {
}
Keymap::~Keymap() {
for (ActionArray::iterator it = _actions.begin(); it != _actions.end(); ++it)
delete *it;

View file

@ -80,6 +80,7 @@ public:
typedef Array<Action *> ActionArray;
Keymap(KeymapType type, const String &id, const U32String &description);
Keymap(KeymapType type, const String &id, const String &description);
~Keymap();
void setConfigDomain(ConfigManager::Domain *configDomain);
@ -155,7 +156,7 @@ public:
void saveMappings();
const String &getId() const { return _id; }
const String &getDescription() const { return _description; }
const U32String &getDescription() const { return _description; }
KeymapType getType() const { return _type; }
/**
@ -180,7 +181,7 @@ private:
KeymapType _type;
String _id;
String _description;
U32String _description;
bool _enabled;

View file

@ -222,9 +222,13 @@ void RemapWidget::startRemapping(uint actionIndex) {
_actions[actionIndex].keyButton->setLabel("...");
_actions[actionIndex].keyButton->setTooltip("");
_actions[actionIndex].keyButton->markAsDirty();
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
}
void RemapWidget::stopRemapping() {
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
_remapKeymap = nullptr;
_remapAction = nullptr;
@ -274,10 +278,10 @@ void RemapWidget::refreshKeymap() {
ActionRow &row = _actions[i];
if (!row.actionText) {
row.actionText = new GUI::StaticTextWidget(widgetsBoss(), 0, 0, 0, 0, "", Graphics::kTextAlignStart, nullptr, GUI::ThemeEngine::kFontStyleNormal);
row.actionText = new GUI::StaticTextWidget(widgetsBoss(), 0, 0, 0, 0, U32String(""), Graphics::kTextAlignStart, U32String(""), GUI::ThemeEngine::kFontStyleNormal);
row.actionText->setLabel(row.action->description);
row.keyButton = new GUI::DropdownButtonWidget(widgetsBoss(), 0, 0, 0, 0, "", nullptr, kRemapCmd + i);
row.keyButton = new GUI::DropdownButtonWidget(widgetsBoss(), 0, 0, 0, 0, U32String(""), U32String(""), kRemapCmd + i);
row.keyButton->appendEntry(_("Reset to defaults"), kResetActionCmd + i);
row.keyButton->appendEntry(_("Clear mapping"), kClearCmd + i);
}
@ -304,7 +308,7 @@ void RemapWidget::refreshKeymap() {
KeymapTitleRow &keymapTitle = _keymapSeparators[row.keymap];
if (!keymapTitle.descriptionText) {
keymapTitle.descriptionText = new GUI::StaticTextWidget(widgetsBoss(), 0, 0, 0, 0, row.keymap->getDescription(), Graphics::kTextAlignStart);
keymapTitle.resetButton = new GUI::ButtonWidget(widgetsBoss(), 0, 0, 0, 0, "", nullptr, kResetKeymapCmd + i);
keymapTitle.resetButton = new GUI::ButtonWidget(widgetsBoss(), 0, 0, 0, 0, U32String(""), U32String(""), kResetKeymapCmd + i);
// I18N: Button to reset keymap mappings to defaults
keymapTitle.resetButton->setLabel(_("Reset"));

67
backends/mixer/mixer.h Normal file
View file

@ -0,0 +1,67 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef BACKENDS_MIXER_ABSTRACT_H
#define BACKENDS_MIXER_ABSTRACT_H
#include "audio/mixer_intern.h"
/**
* Abstract class for mixer manager. Subclasses
* implement the real functionality.
*/
class MixerManager {
public:
MixerManager() : _mixer(0), _audioSuspended(false) {}
virtual ~MixerManager() { delete _mixer; }
/**
* Initialize and setups the mixer
*/
virtual void init() = 0;
/**
* Get the audio mixer implementation
*/
Audio::Mixer *getMixer() { return (Audio::Mixer *)_mixer; }
// Used by LinuxMoto Port
/**
* Pauses the audio system
*/
virtual void suspendAudio() = 0;
/**
* Resumes the audio system
*/
virtual int resumeAudio() = 0;
protected:
/** The mixer implementation */
Audio::MixerImpl *_mixer;
/** State of the audio system */
bool _audioSuspended;
};
#endif

View file

@ -38,19 +38,12 @@
#define SAMPLES_PER_SEC 44100
#endif
SdlMixerManager::SdlMixerManager()
:
_mixer(0),
_audioSuspended(false) {
}
SdlMixerManager::~SdlMixerManager() {
_mixer->setReady(false);
SDL_CloseAudio();
delete _mixer;
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
void SdlMixerManager::init() {

View file

@ -24,7 +24,7 @@
#define BACKENDS_MIXER_SDL_H
#include "backends/platform/sdl/sdl-sys.h"
#include "audio/mixer_intern.h"
#include "backends/mixer/mixer.h"
/**
* SDL mixer manager. It wraps the actual implementation
@ -32,9 +32,8 @@
* the SDL audio subsystem and the callback for the
* audio mixer implementation.
*/
class SdlMixerManager {
class SdlMixerManager : public MixerManager {
public:
SdlMixerManager();
virtual ~SdlMixerManager();
/**
@ -42,11 +41,6 @@ public:
*/
virtual void init();
/**
* Get the audio mixer implementation
*/
Audio::Mixer *getMixer() { return (Audio::Mixer *)_mixer; }
// Used by Event recorder
/**
@ -60,18 +54,12 @@ public:
virtual int resumeAudio();
protected:
/** The mixer implementation */
Audio::MixerImpl *_mixer;
/**
* The obtained audio specification after opening the
* audio system.
*/
SDL_AudioSpec _obtained;
/** State of the audio system */
bool _audioSuspended;
/**
* Returns the desired audio specification
*/

View file

@ -22,181 +22,173 @@
#include "backends/modular-backend.h"
#include "backends/audiocd/audiocd.h"
#include "backends/graphics/graphics.h"
#include "backends/graphics/resvm-graphics.h" // ResidualVM specific
#include "backends/mixer/mixer.h"
#include "backends/mutex/mutex.h"
#include "gui/EventRecorder.h"
#include "audio/mixer.h"
#include "common/timer.h"
#include "graphics/pixelformat.h"
#include "graphics/pixelbuffer.h" // ResidualVM specific:
ModularBackend::ModularBackend()
ModularGraphicsBackend::ModularGraphicsBackend()
:
_mutexManager(0),
_graphicsManager(0),
_mixer(0) {
_graphicsManager(0) {
}
ModularBackend::~ModularBackend() {
ModularGraphicsBackend::~ModularGraphicsBackend() {
delete _graphicsManager;
_graphicsManager = 0;
delete _mixer;
_mixer = 0;
// _timerManager needs to be deleted before _mutexManager to avoid a crash.
delete _timerManager;
_timerManager = 0;
delete _mutexManager;
_mutexManager = 0;
}
bool ModularBackend::hasFeature(Feature f) {
bool ModularGraphicsBackend::hasFeature(Feature f) {
return _graphicsManager->hasFeature(f);
}
void ModularBackend::setFeatureState(Feature f, bool enable) {
void ModularGraphicsBackend::setFeatureState(Feature f, bool enable) {
_graphicsManager->setFeatureState(f, enable);
}
bool ModularBackend::getFeatureState(Feature f) {
bool ModularGraphicsBackend::getFeatureState(Feature f) {
return _graphicsManager->getFeatureState(f);
}
GraphicsManager *ModularBackend::getGraphicsManager() {
GraphicsManager *ModularGraphicsBackend::getGraphicsManager() {
assert(_graphicsManager);
return (GraphicsManager *)_graphicsManager;
}
const OSystem::GraphicsMode *ModularBackend::getSupportedGraphicsModes() const {
const OSystem::GraphicsMode *ModularGraphicsBackend::getSupportedGraphicsModes() const {
return _graphicsManager->getSupportedGraphicsModes();
}
int ModularBackend::getDefaultGraphicsMode() const {
int ModularGraphicsBackend::getDefaultGraphicsMode() const {
return _graphicsManager->getDefaultGraphicsMode();
}
bool ModularBackend::setGraphicsMode(int mode) {
bool ModularGraphicsBackend::setGraphicsMode(int mode) {
return _graphicsManager->setGraphicsMode(mode);
}
int ModularBackend::getGraphicsMode() const {
int ModularGraphicsBackend::getGraphicsMode() const {
return _graphicsManager->getGraphicsMode();
}
const OSystem::GraphicsMode *ModularBackend::getSupportedShaders() const {
const OSystem::GraphicsMode *ModularGraphicsBackend::getSupportedShaders() const {
return _graphicsManager->getSupportedShaders();
}
int ModularBackend::getDefaultShader() const {
int ModularGraphicsBackend::getDefaultShader() const {
return _graphicsManager->getDefaultShader();
}
bool ModularBackend::setShader(int id) {
bool ModularGraphicsBackend::setShader(int id) {
return _graphicsManager->setShader(id);
}
int ModularBackend::getShader() const {
int ModularGraphicsBackend::getShader() const {
return _graphicsManager->getShader();
}
const OSystem::GraphicsMode *ModularBackend::getSupportedStretchModes() const {
const OSystem::GraphicsMode *ModularGraphicsBackend::getSupportedStretchModes() const {
return _graphicsManager->getSupportedStretchModes();
}
int ModularBackend::getDefaultStretchMode() const {
int ModularGraphicsBackend::getDefaultStretchMode() const {
return _graphicsManager->getDefaultStretchMode();
}
bool ModularBackend::setStretchMode(int mode) {
bool ModularGraphicsBackend::setStretchMode(int mode) {
return _graphicsManager->setStretchMode(mode);
}
int ModularBackend::getStretchMode() const {
int ModularGraphicsBackend::getStretchMode() const {
return _graphicsManager->getStretchMode();
}
void ModularBackend::resetGraphicsScale() {
void ModularGraphicsBackend::resetGraphicsScale() {
_graphicsManager->resetGraphicsScale();
}
#ifdef USE_RGB_COLOR
Graphics::PixelFormat ModularBackend::getScreenFormat() const {
Graphics::PixelFormat ModularGraphicsBackend::getScreenFormat() const {
return _graphicsManager->getScreenFormat();
}
Common::List<Graphics::PixelFormat> ModularBackend::getSupportedFormats() const {
Common::List<Graphics::PixelFormat> ModularGraphicsBackend::getSupportedFormats() const {
return _graphicsManager->getSupportedFormats();
}
#endif
// ResidualVM specific method
void ModularBackend::setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) {
void ModularGraphicsBackend::setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) {
_graphicsManager->setupScreen(screenW, screenH, fullscreen, accel3d);
}
// ResidualVM specific method
Graphics::PixelBuffer ModularBackend::getScreenPixelBuffer() {
Graphics::PixelBuffer ModularGraphicsBackend::getScreenPixelBuffer() {
return _graphicsManager->getScreenPixelBuffer();
}
// ResidualVM specific method
void ModularBackend::suggestSideTextures(Graphics::Surface *left, Graphics::Surface *right) {
void ModularGraphicsBackend::suggestSideTextures(Graphics::Surface *left, Graphics::Surface *right) {
_graphicsManager->suggestSideTextures(left, right);
}
void ModularBackend::initSize(uint w, uint h, const Graphics::PixelFormat *format ) {
void ModularGraphicsBackend::initSize(uint w, uint h, const Graphics::PixelFormat *format ) {
_graphicsManager->initSize(w, h, format);
}
void ModularBackend::initSizeHint(const Graphics::ModeList &modes) {
void ModularGraphicsBackend::initSizeHint(const Graphics::ModeList &modes) {
_graphicsManager->initSizeHint(modes);
}
int ModularBackend::getScreenChangeID() const {
int ModularGraphicsBackend::getScreenChangeID() const {
return _graphicsManager->getScreenChangeID();
}
void ModularBackend::beginGFXTransaction() {
void ModularGraphicsBackend::beginGFXTransaction() {
_graphicsManager->beginGFXTransaction();
}
OSystem::TransactionError ModularBackend::endGFXTransaction() {
OSystem::TransactionError ModularGraphicsBackend::endGFXTransaction() {
return _graphicsManager->endGFXTransaction();
}
int16 ModularBackend::getHeight() {
int16 ModularGraphicsBackend::getHeight() {
return _graphicsManager->getHeight();
}
int16 ModularBackend::getWidth() {
int16 ModularGraphicsBackend::getWidth() {
return _graphicsManager->getWidth();
}
PaletteManager *ModularBackend::getPaletteManager() {
PaletteManager *ModularGraphicsBackend::getPaletteManager() {
return _graphicsManager;
}
void ModularBackend::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {
void ModularGraphicsBackend::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {
_graphicsManager->copyRectToScreen(buf, pitch, x, y, w, h);
}
Graphics::Surface *ModularBackend::lockScreen() {
Graphics::Surface *ModularGraphicsBackend::lockScreen() {
return _graphicsManager->lockScreen();
}
void ModularBackend::unlockScreen() {
void ModularGraphicsBackend::unlockScreen() {
_graphicsManager->unlockScreen();
}
void ModularBackend::fillScreen(uint32 col) {
void ModularGraphicsBackend::fillScreen(uint32 col) {
_graphicsManager->fillScreen(col);
}
void ModularBackend::updateScreen() {
void ModularGraphicsBackend::updateScreen() {
#ifdef ENABLE_EVENTRECORDER
g_eventRec.preDrawOverlayGui();
#endif
@ -208,100 +200,135 @@ void ModularBackend::updateScreen() {
#endif
}
void ModularBackend::setShakePos(int shakeXOffset, int shakeYOffset) {
void ModularGraphicsBackend::setShakePos(int shakeXOffset, int shakeYOffset) {
_graphicsManager->setShakePos(shakeXOffset, shakeYOffset);
}
void ModularBackend::setFocusRectangle(const Common::Rect& rect) {
void ModularGraphicsBackend::setFocusRectangle(const Common::Rect& rect) {
_graphicsManager->setFocusRectangle(rect);
}
void ModularBackend::clearFocusRectangle() {
void ModularGraphicsBackend::clearFocusRectangle() {
_graphicsManager->clearFocusRectangle();
}
void ModularBackend::showOverlay() {
void ModularGraphicsBackend::showOverlay() {
_graphicsManager->showOverlay();
}
void ModularBackend::hideOverlay() {
void ModularGraphicsBackend::hideOverlay() {
_graphicsManager->hideOverlay();
}
Graphics::PixelFormat ModularBackend::getOverlayFormat() const {
Graphics::PixelFormat ModularGraphicsBackend::getOverlayFormat() const {
return _graphicsManager->getOverlayFormat();
}
void ModularBackend::clearOverlay() {
void ModularGraphicsBackend::clearOverlay() {
_graphicsManager->clearOverlay();
}
void ModularBackend::grabOverlay(void *buf, int pitch) {
void ModularGraphicsBackend::grabOverlay(void *buf, int pitch) {
_graphicsManager->grabOverlay(buf, pitch);
}
void ModularBackend::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {
void ModularGraphicsBackend::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {
_graphicsManager->copyRectToOverlay(buf, pitch, x, y, w, h);
}
int16 ModularBackend::getOverlayHeight() {
int16 ModularGraphicsBackend::getOverlayHeight() {
return _graphicsManager->getOverlayHeight();
}
int16 ModularBackend::getOverlayWidth() {
int16 ModularGraphicsBackend::getOverlayWidth() {
return _graphicsManager->getOverlayWidth();
}
bool ModularBackend::showMouse(bool visible) {
bool ModularGraphicsBackend::showMouse(bool visible) {
return _graphicsManager->showMouse(visible);
}
// ResidualVM specific method
bool ModularBackend::lockMouse(bool visible) {
bool ModularGraphicsBackend::lockMouse(bool visible) {
return _graphicsManager->lockMouse(visible);
}
void ModularBackend::warpMouse(int x, int y) {
void ModularGraphicsBackend::warpMouse(int x, int y) {
_eventManager->purgeMouseEvents();
_graphicsManager->warpMouse(x, y);
}
void ModularBackend::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
void ModularGraphicsBackend::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
_graphicsManager->setMouseCursor(buf, w, h, hotspotX, hotspotY, keycolor, dontScale, format);
}
void ModularBackend::setCursorPalette(const byte *colors, uint start, uint num) {
void ModularGraphicsBackend::setCursorPalette(const byte *colors, uint start, uint num) {
_graphicsManager->setCursorPalette(colors, start, num);
}
OSystem::MutexRef ModularBackend::createMutex() {
void ModularGraphicsBackend::displayMessageOnOSD(const Common::U32String &msg) {
_graphicsManager->displayMessageOnOSD(msg);
}
void ModularGraphicsBackend::displayActivityIconOnOSD(const Graphics::Surface *icon) {
_graphicsManager->displayActivityIconOnOSD(icon);
}
ModularMixerBackend::ModularMixerBackend()
:
_mixerManager(0) {
}
ModularMixerBackend::~ModularMixerBackend() {
// _audiocdManager needs to be deleted before _mixerManager to avoid a crash.
delete _audiocdManager;
_audiocdManager = 0;
delete _mixerManager;
_mixerManager = 0;
}
MixerManager *ModularMixerBackend::getMixerManager() {
assert(_mixerManager);
return _mixerManager;
}
Audio::Mixer *ModularMixerBackend::getMixer() {
assert(_mixerManager);
return getMixerManager()->getMixer();
}
ModularMutexBackend::ModularMutexBackend()
:
_mutexManager(0) {
}
ModularMutexBackend::~ModularMutexBackend() {
// _timerManager needs to be deleted before _mutexManager to avoid a crash.
delete _timerManager;
_timerManager = 0;
delete _mutexManager;
_mutexManager = 0;
}
OSystem::MutexRef ModularMutexBackend::createMutex() {
assert(_mutexManager);
return _mutexManager->createMutex();
}
void ModularBackend::lockMutex(MutexRef mutex) {
void ModularMutexBackend::lockMutex(MutexRef mutex) {
assert(_mutexManager);
_mutexManager->lockMutex(mutex);
}
void ModularBackend::unlockMutex(MutexRef mutex) {
void ModularMutexBackend::unlockMutex(MutexRef mutex) {
assert(_mutexManager);
_mutexManager->unlockMutex(mutex);
}
void ModularBackend::deleteMutex(MutexRef mutex) {
void ModularMutexBackend::deleteMutex(MutexRef mutex) {
assert(_mutexManager);
_mutexManager->deleteMutex(mutex);
}
Audio::Mixer *ModularBackend::getMixer() {
assert(_mixer);
return (Audio::Mixer *)_mixer;
}
void ModularBackend::displayMessageOnOSD(const char *msg) {
_graphicsManager->displayMessageOnOSD(msg);
}
void ModularBackend::displayActivityIconOnOSD(const Graphics::Surface *icon) {
_graphicsManager->displayActivityIconOnOSD(icon);
}

View file

@ -27,15 +27,16 @@
class GraphicsManager;
class ResVmGraphicsManager; // ResidualVM specific
class MixerManager;
class MutexManager;
/**
* Base class for modular backends.
* Base classes for modular backends.
*
* It wraps most functions to their manager equivalent, but not
* They wrap most functions to their manager equivalent, but not
* all OSystem functions are implemented here.
*
* A backend derivated from this class, will need to implement
* A backend derivated from these classes, will need to implement
* these functions on its own:
* OSystem::pollEvent()
* OSystem::getMillis()
@ -46,10 +47,10 @@ class MutexManager;
* And, it should also initialize all the managers variables
* declared in this class, or override their related functions.
*/
class ModularBackend : public BaseBackend {
class ModularGraphicsBackend : virtual public BaseBackend {
public:
ModularBackend();
virtual ~ModularBackend();
ModularGraphicsBackend();
virtual ~ModularGraphicsBackend();
/** @name Features */
//@{
@ -120,6 +121,50 @@ public:
//@}
/** @name Miscellaneous */
//@{
virtual void displayMessageOnOSD(const Common::U32String &msg) override final;
virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) override final;
//@}
protected:
/** @name Managers variables */
//@{
ResVmGraphicsManager *_graphicsManager; // ResidualVM: was GraphicsManager
//@}
};
class ModularMixerBackend : virtual public BaseBackend {
public:
ModularMixerBackend();
virtual ~ModularMixerBackend();
/** @name Sound */
//@{
virtual MixerManager *getMixerManager();
virtual Audio::Mixer *getMixer() override final;
//@}
protected:
/** @name Managers variables */
//@{
MixerManager *_mixerManager;
//@}
};
class ModularMutexBackend : virtual public BaseBackend {
public:
ModularMutexBackend();
virtual ~ModularMutexBackend();
/** @name Mutex handling */
//@{
@ -130,28 +175,11 @@ public:
//@}
/** @name Sound */
//@{
virtual Audio::Mixer *getMixer() override;
//@}
/** @name Miscellaneous */
//@{
virtual void displayMessageOnOSD(const char *msg) override final;
virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) override final;
//@}
protected:
/** @name Managers variables */
//@{
MutexManager *_mutexManager;
ResVmGraphicsManager *_graphicsManager; // ResidualVM: was GraphicsManager
Audio::Mixer *_mixer;
//@}
};

View file

@ -137,6 +137,11 @@ ifdef USE_OPENGL
MODULE_OBJS += \
graphics/openglsdl/openglsdl-graphics.o
endif
ifdef USE_DISCORD
MODULE_OBJS += \
presence/discord/discord.o
endif
endif
ifdef POSIX
@ -210,6 +215,12 @@ MODULE_OBJS += \
fs/amigaos4/amigaos4-fs-factory.o
endif
ifdef MORPHOS
MODULE_OBJS += \
fs/morphos/morphos-fs.o \
fs/morphos/morphos-fs-factory.o
endif
ifdef RISCOS
MODULE_OBJS += \
events/riscossdl/riscossdl-events.o \
@ -270,6 +281,11 @@ MODULE_OBJS += \
fs/n64/romfsstream.o
endif
ifeq ($(BACKEND),null)
MODULE_OBJS += \
mixer/null/null-mixer.o
endif
ifeq ($(BACKEND),openpandora)
MODULE_OBJS += \
events/openpandora/op-events.o \
@ -314,7 +330,7 @@ endif
ifdef ENABLE_EVENTRECORDER
MODULE_OBJS += \
mixer/nullmixer/nullsdl-mixer.o \
mixer/null/null-mixer.o \
saves/recorder/recorder-saves.o
endif

View file

@ -57,35 +57,35 @@ void CreateDirectoryHandler::handle(Client &client) {
// check that <path> is not an absolute root
if (path == "" || path == "/") {
handleError(client, HandlerUtils::toUtf8(_("Can't create directory here!")));
handleError(client, Common::convertFromU32String(_("Can't create directory here!")));
return;
}
// check that <path> contains no '../'
if (HandlerUtils::hasForbiddenCombinations(path)) {
handleError(client, HandlerUtils::toUtf8(_("Invalid path!")));
handleError(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
// transform virtual path to actual file system one
Common::String prefixToRemove = "", prefixToAdd = "";
if (!transformPath(path, prefixToRemove, prefixToAdd) || path.empty()) {
handleError(client, HandlerUtils::toUtf8(_("Invalid path!")));
handleError(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
// check that <path> exists, is directory and isn't forbidden
AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(path);
if (!HandlerUtils::permittedPath(node->getPath())) {
handleError(client, HandlerUtils::toUtf8(_("Invalid path!")));
handleError(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
if (!node->exists()) {
handleError(client, HandlerUtils::toUtf8(_("Parent directory doesn't exists!")));
handleError(client, Common::convertFromU32String(_("Parent directory doesn't exists!")));
return;
}
if (!node->isDirectory()) {
handleError(client, HandlerUtils::toUtf8(_("Can't create a directory within a file!")));
handleError(client, Common::convertFromU32String(_("Can't create a directory within a file!")));
return;
}
@ -95,20 +95,20 @@ void CreateDirectoryHandler::handle(Client &client) {
node = g_system->getFilesystemFactory()->makeFileNodePath(path + name);
if (node->exists()) {
if (!node->isDirectory()) {
handleError(client, HandlerUtils::toUtf8(_("There is a file with that name in the parent directory!")));
handleError(client, Common::convertFromU32String(_("There is a file with that name in the parent directory!")));
return;
}
} else {
// create the <directory_name> in <path>
if (!node->createDirectory()) {
handleError(client, HandlerUtils::toUtf8(_("Failed to create the directory!")));
handleError(client, Common::convertFromU32String(_("Failed to create the directory!")));
return;
}
}
// if json requested, respond with it
if (client.queryParameter("answer_json") == "true") {
setJsonResponseHandler(client, "success", HandlerUtils::toUtf8(_("Directory created successfully!")));
setJsonResponseHandler(client, "success", Common::convertFromU32String(_("Directory created successfully!")));
return;
}
@ -117,9 +117,9 @@ void CreateDirectoryHandler::handle(Client &client) {
client,
Common::String::format(
"%s<br/><a href=\"files?path=%s\">%s</a>",
HandlerUtils::toUtf8(_("Directory created successfully!")).c_str(),
Common::convertFromU32String(_("Directory created successfully!")).c_str(),
client.queryParameter("path").c_str(),
HandlerUtils::toUtf8(_("Back to parent directory")).c_str()
Common::convertFromU32String(_("Back to parent directory")).c_str()
),
(client.queryParameter("ajax") == "true" ? "/filesAJAX?path=" : "/files?path=") +
LocalWebserver::urlEncodeQueryParameterValue(client.queryParameter("path"))

View file

@ -40,40 +40,40 @@ void DownloadFileHandler::handle(Client &client) {
// check that <path> is not an absolute root
if (path == "" || path == "/") {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Invalid path!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
// check that <path> contains no '../'
if (HandlerUtils::hasForbiddenCombinations(path)) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Invalid path!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
// transform virtual path to actual file system one
Common::String prefixToRemove = "", prefixToAdd = "";
if (!transformPath(path, prefixToRemove, prefixToAdd, false) || path.empty()) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Invalid path!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
// check that <path> exists, is directory and isn't forbidden
AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(path);
if (!HandlerUtils::permittedPath(node->getPath())) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Invalid path!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
if (!node->exists()) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("The file doesn't exist!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("The file doesn't exist!")));
return;
}
if (node->isDirectory()) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Can't download a directory!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Can't download a directory!")));
return;
}
Common::SeekableReadStream *stream = node->createReadStream();
if (stream == nullptr) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Failed to read the file!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Failed to read the file!")));
return;
}

View file

@ -56,7 +56,7 @@ void FilesAjaxPageHandler::handle(Client &client) {
// load stylish response page from the archive
Common::SeekableReadStream *const stream = HandlerUtils::getArchiveFile(FILES_PAGE_NAME);
if (stream == nullptr) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("The page is not available without the resources. Make sure file wwwroot.zip from ResidualVM distribution is available in 'themepath'.")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("The page is not available without the resources. Make sure file wwwroot.zip from ResidualVM distribution is available in 'themepath'.")));
return;
}
@ -64,16 +64,16 @@ void FilesAjaxPageHandler::handle(Client &client) {
Common::String path = client.queryParameter("path");
//these occur twice:
replace(response, "{create_directory_button}", HandlerUtils::toUtf8(_("Create directory")));
replace(response, "{create_directory_button}", HandlerUtils::toUtf8(_("Create directory")));
replace(response, "{upload_files_button}", HandlerUtils::toUtf8(_("Upload files"))); //tab
replace(response, "{upload_file_button}", HandlerUtils::toUtf8(_("Upload files"))); //button in the tab
replace(response, "{create_directory_desc}", HandlerUtils::toUtf8(_("Type new directory name:")));
replace(response, "{upload_file_desc}", HandlerUtils::toUtf8(_("Select a file to upload:")));
replace(response, "{or_upload_directory_desc}", HandlerUtils::toUtf8(_("Or select a directory (works in Chrome only):")));
replace(response, "{index_of}", HandlerUtils::toUtf8(_("Index of ")));
replace(response, "{loading}", HandlerUtils::toUtf8(("Loading...")));
replace(response, "{error}", HandlerUtils::toUtf8(_("Error occurred")));
replace(response, "{create_directory_button}", _("Create directory").encode());
replace(response, "{create_directory_button}", _("Create directory").encode());
replace(response, "{upload_files_button}", _("Upload files").encode()); //tab
replace(response, "{upload_file_button}", _("Upload files").encode()); //button in the tab
replace(response, "{create_directory_desc}", _("Type new directory name:").encode());
replace(response, "{upload_file_desc}", _("Select a file to upload:").encode());
replace(response, "{or_upload_directory_desc}", _("Or select a directory (works in Chrome only):").encode());
replace(response, "{index_of}", _("Index of ").encode());
replace(response, "{loading}", ("Loading..."));
replace(response, "{error}", _("Error occurred").encode());
replace(response, "{start_path}", encodeDoubleQuotesAndSlashes(path));
LocalWebserver::setClientGetHandler(client, response);
}

View file

@ -78,8 +78,8 @@ Common::String getDisplayPath(Common::String s) {
bool FilesPageHandler::listDirectory(Common::String path, Common::String &content, const Common::String &itemTemplate) {
if (path == "" || path == "/") {
if (ConfMan.hasKey("rootpath", "cloud"))
addItem(content, itemTemplate, IT_DIRECTORY, "/root/", HandlerUtils::toUtf8(_("File system root")));
addItem(content, itemTemplate, IT_DIRECTORY, "/saves/", HandlerUtils::toUtf8(_("Saved games")));
addItem(content, itemTemplate, IT_DIRECTORY, "/root/", Common::convertFromU32String(_("File system root")));
addItem(content, itemTemplate, IT_DIRECTORY, "/saves/", Common::convertFromU32String(_("Saved games")));
return true;
}
@ -116,7 +116,7 @@ bool FilesPageHandler::listDirectory(Common::String path, Common::String &conten
filePath = "/";
else
filePath = parentPath(prefixToAdd + filePath);
addItem(content, itemTemplate, IT_PARENT_DIRECTORY, filePath, HandlerUtils::toUtf8(_("Parent directory")));
addItem(content, itemTemplate, IT_PARENT_DIRECTORY, filePath, Common::convertFromU32String(_("Parent directory")));
}
// fill the content
@ -215,21 +215,21 @@ void FilesPageHandler::handle(Client &client) {
// show an error message if failed to list directory
if (!listDirectory(path, content, itemTemplate)) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("ResidualVM couldn't list the directory you specified.")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("ResidualVM couldn't list the directory you specified.")).c_str());
return;
}
//these occur twice:
replace(response, "{create_directory_button}", HandlerUtils::toUtf8(_("Create directory")));
replace(response, "{create_directory_button}", HandlerUtils::toUtf8(_("Create directory")));
replace(response, "{create_directory_button}", _("Create directory").encode());
replace(response, "{create_directory_button}", _("Create directory").encode());
replace(response, "{path}", encodeDoubleQuotes(client.queryParameter("path")));
replace(response, "{path}", encodeDoubleQuotes(client.queryParameter("path")));
replace(response, "{upload_files_button}", HandlerUtils::toUtf8(_("Upload files"))); //tab
replace(response, "{upload_file_button}", HandlerUtils::toUtf8(_("Upload files"))); //button in the tab
replace(response, "{create_directory_desc}", HandlerUtils::toUtf8(_("Type new directory name:")));
replace(response, "{upload_file_desc}", HandlerUtils::toUtf8(_("Select a file to upload:")));
replace(response, "{or_upload_directory_desc}", HandlerUtils::toUtf8(_("Or select a directory (works in Chrome only):")));
replace(response, "{index_of_directory}", Common::String::format("%s %s", HandlerUtils::toUtf8(_("Index of")).c_str(), encodeHtmlEntities(getDisplayPath(client.queryParameter("path"))).c_str()));
replace(response, "{upload_files_button}", _("Upload files").encode()); //tab
replace(response, "{upload_file_button}", _("Upload files").encode()); //button in the tab
replace(response, "{create_directory_desc}", _("Type new directory name:").encode());
replace(response, "{upload_file_desc}", _("Select a file to upload:").encode());
replace(response, "{or_upload_directory_desc}", _("Or select a directory (works in Chrome only):").encode());
replace(response, "{index_of_directory}", Common::String::format("%s %s", _("Index of").encode().c_str(), encodeHtmlEntities(getDisplayPath(client.queryParameter("path"))).c_str()));
replace(response, "{content}", content);
LocalWebserver::setClientGetHandler(client, response);
}

View file

@ -39,8 +39,8 @@ void IndexPageHandler::handle(Client &client) {
client,
Common::String::format(
"%s<br/><a href=\"files\">%s</a>",
HandlerUtils::toUtf8(_("This is a local webserver index page.")).c_str(),
HandlerUtils::toUtf8(_("Open Files manager")).c_str()
Common::convertFromU32String(_("This is a local webserver index page.")).c_str(),
Common::convertFromU32String(_("Open Files manager")).c_str()
),
"/filesAJAX"
);

View file

@ -42,8 +42,8 @@ Common::JSONObject ListAjaxHandler::listDirectory(Common::String path) {
if (path == "" || path == "/") {
if (ConfMan.hasKey("rootpath", "cloud"))
addItem(itemsList, IT_DIRECTORY, "/root/", HandlerUtils::toUtf8(_("File system root")));
addItem(itemsList, IT_DIRECTORY, "/saves/", HandlerUtils::toUtf8(_("Saved games")));
addItem(itemsList, IT_DIRECTORY, "/root/", Common::convertFromU32String(_("File system root")));
addItem(itemsList, IT_DIRECTORY, "/saves/", Common::convertFromU32String(_("Saved games")));
successResult.setVal("items", new Common::JSONValue(itemsList));
return successResult;
}
@ -81,7 +81,7 @@ Common::JSONObject ListAjaxHandler::listDirectory(Common::String path) {
filePath = "/";
else
filePath = parentPath(prefixToAdd + filePath);
addItem(itemsList, IT_PARENT_DIRECTORY, filePath, HandlerUtils::toUtf8(_("Parent directory")));
addItem(itemsList, IT_PARENT_DIRECTORY, filePath, Common::convertFromU32String(_("Parent directory")));
}
// fill the content

View file

@ -40,35 +40,35 @@ void UploadFileHandler::handle(Client &client) {
// check that <path> is not an absolute root
if (path == "" || path == "/" || path == "\\") {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Invalid path!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
// check that <path> contains no '../'
if (HandlerUtils::hasForbiddenCombinations(path)) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Invalid path!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
// transform virtual path to actual file system one
Common::String prefixToRemove = "", prefixToAdd = "";
if (!transformPath(path, prefixToRemove, prefixToAdd, false) || path.empty()) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Invalid path!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
// check that <path> exists, is directory and isn't forbidden
AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(path);
if (!HandlerUtils::permittedPath(node->getPath())) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Invalid path!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
return;
}
if (!node->exists()) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("The parent directory doesn't exist!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("The parent directory doesn't exist!")));
return;
}
if (!node->isDirectory()) {
HandlerUtils::setFilesManagerErrorMessageHandler(client, HandlerUtils::toUtf8(_("Can't upload into a file!")));
HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Can't upload into a file!")));
return;
}

View file

@ -172,21 +172,6 @@ bool HandlerUtils::permittedPath(const Common::String path) {
return hasPermittedPrefix(path) && !isBlacklisted(path);
}
Common::String HandlerUtils::toUtf8(const char *text) {
#ifdef USE_TRANSLATION
Common::String guiEncoding = TransMan.getCurrentCharset();
if (guiEncoding != "ASCII") {
char *utf8Text = Common::Encoding::convert("utf-8", guiEncoding, text, strlen(text));
if (utf8Text != nullptr) {
Common::String str(utf8Text);
free(utf8Text);
return str;
}
}
#endif
return Common::String(text);
}
void HandlerUtils::setMessageHandler(Client &client, Common::String message, Common::String redirectTo) {
Common::String response = "<html><head><title>ResidualVM</title><meta charset=\"utf-8\"/></head><body>{message}</body></html>";
@ -210,7 +195,7 @@ void HandlerUtils::setFilesManagerErrorMessageHandler(Client &client, Common::St
message.c_str(),
client.queryParameter("ajax") == "true" ? "AJAX" : "",
"%2F", //that's encoded "/"
toUtf8(_("Back to the files manager")).c_str()
Common::convertFromU32String(_("Back to the files manager")).c_str()
),
redirectTo
);

View file

@ -41,8 +41,6 @@ public:
static bool hasPermittedPrefix(const Common::String &path);
static bool permittedPath(const Common::String path);
static Common::String toUtf8(const char*);
static void setMessageHandler(Client &client, Common::String message, Common::String redirectTo = "");
static void setFilesManagerErrorMessageHandler(Client &client, Common::String message, Common::String redirectTo = "");
};

View file

@ -66,7 +66,7 @@ void UploadFileClientHandler::handle(Client *client) {
// fail on suspicious headers
if (_headersStream->size() > Reader::SUSPICIOUS_HEADERS_SIZE) {
setErrorMessageHandler(*client, HandlerUtils::toUtf8(_("Invalid request: headers are too long!")));
setErrorMessageHandler(*client, Common::convertFromU32String(_("Invalid request: headers are too long!")));
}
break;
@ -108,7 +108,7 @@ void UploadFileClientHandler::handleBlockHeaders(Client *client) {
// fail on suspicious headers
if (_headersStream->size() > Reader::SUSPICIOUS_HEADERS_SIZE) {
setErrorMessageHandler(*client, HandlerUtils::toUtf8(_("Invalid request: headers are too long!")));
setErrorMessageHandler(*client, Common::convertFromU32String(_("Invalid request: headers are too long!")));
}
// search for "upload_file" field
@ -134,11 +134,11 @@ void UploadFileClientHandler::handleBlockHeaders(Client *client) {
path += '/';
AbstractFSNode *originalNode = g_system->getFilesystemFactory()->makeFileNodePath(path + filename);
if (!HandlerUtils::permittedPath(originalNode->getPath())) {
setErrorMessageHandler(*client, HandlerUtils::toUtf8(_("Invalid path!")));
setErrorMessageHandler(*client, Common::convertFromU32String(_("Invalid path!")));
return;
}
if (originalNode->exists()) {
setErrorMessageHandler(*client, HandlerUtils::toUtf8(_("There is a file with that name in the parent directory!")));
setErrorMessageHandler(*client, Common::convertFromU32String(_("There is a file with that name in the parent directory!")));
return;
}
@ -152,7 +152,7 @@ void UploadFileClientHandler::handleBlockHeaders(Client *client) {
Common::DumpFile *f = new Common::DumpFile();
if (!f->open(originalNode->getPath(), true)) {
delete f;
setErrorMessageHandler(*client, HandlerUtils::toUtf8(_("Failed to upload the file!")));
setErrorMessageHandler(*client, Common::convertFromU32String(_("Failed to upload the file!")));
return;
}
@ -181,7 +181,7 @@ void UploadFileClientHandler::handleBlockContent(Client *client) {
if (client->noMoreContent()) {
// if no file field was found - failure
if (_uploadedFiles == 0) {
setErrorMessageHandler(*client, HandlerUtils::toUtf8(_("No file was passed!")));
setErrorMessageHandler(*client, Common::convertFromU32String(_("No file was passed!")));
} else {
setSuccessHandler(*client);
}
@ -199,9 +199,9 @@ void UploadFileClientHandler::setSuccessHandler(Client &client) {
client,
Common::String::format(
"%s<br/><a href=\"files?path=%s\">%s</a>",
HandlerUtils::toUtf8(_("Uploaded successfully!")).c_str(),
Common::convertFromU32String(_("Uploaded successfully!")).c_str(),
client.queryParameter("path").c_str(),
HandlerUtils::toUtf8(_("Back to parent directory")).c_str()
Common::convertFromU32String(_("Back to parent directory")).c_str()
),
(client.queryParameter("ajax") == "true" ? "/filesAJAX?path=" : "/files?path=") +
LocalWebserver::urlEncodeQueryParameterValue(client.queryParameter("path"))

View file

@ -22,6 +22,8 @@
#if defined(__ANDROID__)
#define FORBIDDEN_SYMBOL_EXCEPTION_getenv(a)
// Allow use of stuff in <time.h>
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
@ -53,11 +55,16 @@
#include "common/events.h"
#include "common/config-manager.h"
#include "backends/keymapper/keymapper.h"
#include "backends/audiocd/default/default-audiocd.h"
#include "backends/events/default/default-events.h"
#include "backends/mutex/pthread/pthread-mutex.h"
#include "backends/saves/default/default-saves.h"
#include "backends/timer/default/default-timer.h"
#include "backends/keymapper/keymapper.h"
#include "backends/keymapper/keymapper-defaults.h"
#include "backends/keymapper/standard-actions.h"
#include "backends/platform/android/jni-android.h"
#include "backends/platform/android/android.h"
#include "backends/platform/android/graphics.h"
@ -153,10 +160,10 @@ OSystem_Android::~OSystem_Android() {
delete _timerManager;
_timerManager = 0;
deleteMutex(_event_queue_lock);
delete _event_queue_lock;
delete _mutexManager;
_mutexManager = 0;
delete _savefileManager;
_savefileManager = 0;
}
void *OSystem_Android::timerThreadFunc(void *arg) {

View file

@ -69,7 +69,7 @@ int main(int argc, char *argv[]) {
assert(g_system);
// Pre-initialize the backend.
((OSystem_AmigaOS *)g_system)->init();
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());

View file

@ -25,6 +25,7 @@
#include "backends/platform/sdl/macosx/appmenu_osx.h"
#include "common/translation.h"
#include "common/ustr.h"
#include "backends/platform/sdl/macosx/macosx-compat.h"
#include <Cocoa/Cocoa.h>
@ -41,6 +42,16 @@
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
typedef unsigned long NSUInteger;
// Those are not defined in the 10.4 SDK, but they are defined when targetting
// Mac OS X 10.4 or above in the 10.5 SDK. So hopfully that means it works with 10.4 as well.
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
enum {
NSUTF32StringEncoding = 0x8c000100,
NSUTF32BigEndianStringEncoding = 0x98000100,
NSUTF32LittleEndianStringEncoding = 0x9c000100
};
#endif
#endif
// Apple added setAppleMenu in 10.5 and removed it in 10.6.
@ -132,16 +143,21 @@ static void openFromBundle(NSString *file) {
}
@end
NSString *constructNSStringFromCString(const char *rawCString, CFStringEncoding stringEncoding) {
return (NSString *)CFStringCreateWithCString(NULL, rawCString, stringEncoding);
NSString *constructNSStringFromU32String(const Common::U32String &rawU32String) {
#ifdef SCUMM_LITTLE_ENDIAN
NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
#else
NSStringEncoding stringEncoding = NSUTF32BigEndianStringEncoding;
#endif
return [[NSString alloc] initWithBytes:rawU32String.c_str() length:4*rawU32String.size() encoding: stringEncoding];
}
static NSMenu *addMenu(const char *title, CFStringEncoding encoding, NSString *key, SEL setAs) {
static NSMenu *addMenu(const Common::U32String &title, NSString *key, SEL setAs) {
if (setAs && ![NSApp respondsToSelector:setAs]) {
return nil;
}
NSString *str = constructNSStringFromCString(title, encoding);
NSString *str = constructNSStringFromU32String(title);
NSMenu *menu = [[NSMenu alloc] initWithTitle:str];
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:str action:nil keyEquivalent:key];
@ -158,8 +174,8 @@ static NSMenu *addMenu(const char *title, CFStringEncoding encoding, NSString *k
return menu;
}
static void addMenuItem(const char *title, CFStringEncoding encoding, id target, SEL selector, NSString *key, NSMenu *parent, NSEventModifierFlags flags = 0) {
NSString *nsString = constructNSStringFromCString(title, encoding);
static void addMenuItem(const Common::U32String &title, id target, SEL selector, NSString *key, NSMenu *parent, NSEventModifierFlags flags = 0) {
NSString *nsString = constructNSStringFromU32String(title);
NSMenuItem *menuItem = [[NSMenuItem alloc]
initWithTitle:nsString
action:selector
@ -189,48 +205,38 @@ void replaceApplicationMenuItems() {
}
NSString *nsString = NULL;
// Get current encoding
#ifdef USE_TRANSLATION
nsString = constructNSStringFromCString(TransMan.getCurrentCharset().c_str(), NSASCIIStringEncoding);
CFStringEncoding stringEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)nsString);
[nsString release];
#else
CFStringEncoding stringEncoding = kCFStringEncodingASCII;
#endif
NSMenu *appleMenu = addMenu("ResidualVM", kCFStringEncodingASCII, @"", @selector(setAppleMenu:));
NSMenu *appleMenu = addMenu(Common::U32String("ResidualVM"), @"", @selector(setAppleMenu:));
if (appleMenu) {
addMenuItem(_("About ResidualVM"), stringEncoding, nil, @selector(orderFrontStandardAboutPanel:), @"", appleMenu);
addMenuItem(_("About ResidualVM"), nil, @selector(orderFrontStandardAboutPanel:), @"", appleMenu);
[appleMenu addItem:[NSMenuItem separatorItem]];
addMenuItem(_("Hide ResidualVM"), stringEncoding, nil, @selector(hide:), @"h", appleMenu);
addMenuItem(_("Hide Others"), stringEncoding, nil, @selector(hideOtherApplications:), @"h", appleMenu, (NSEventModifierFlagOption|NSEventModifierFlagCommand));
addMenuItem(_("Show All"), stringEncoding, nil, @selector(unhideAllApplications:), @"", appleMenu);
addMenuItem(_("Hide ResidualVM"), nil, @selector(hide:), @"h", appleMenu);
addMenuItem(_("Hide Others"), nil, @selector(hideOtherApplications:), @"h", appleMenu, (NSEventModifierFlagOption|NSEventModifierFlagCommand));
addMenuItem(_("Show All"), nil, @selector(unhideAllApplications:), @"", appleMenu);
[appleMenu addItem:[NSMenuItem separatorItem]];
addMenuItem(_("Quit ResidualVM"), stringEncoding, nil, @selector(terminate:), @"q", appleMenu);
addMenuItem(_("Quit ResidualVM"), nil, @selector(terminate:), @"q", appleMenu);
}
NSMenu *windowMenu = addMenu(_("Window"), stringEncoding, @"", @selector(setWindowsMenu:));
NSMenu *windowMenu = addMenu(_("Window"), @"", @selector(setWindowsMenu:));
if (windowMenu) {
addMenuItem(_("Minimize"), stringEncoding, nil, @selector(performMiniaturize:), @"m", windowMenu);
addMenuItem(_("Minimize"), nil, @selector(performMiniaturize:), @"m", windowMenu);
}
NSMenu *helpMenu = addMenu(_("Help"), stringEncoding, @"", @selector(setHelpMenu:));
NSMenu *helpMenu = addMenu(_("Help"), @"", @selector(setHelpMenu:));
if (helpMenu) {
if (!delegate) {
delegate = [[ScummVMMenuHandler alloc] init];
}
addMenuItem(_("User Manual"), stringEncoding, delegate, @selector(openUserManual), @"", helpMenu);
addMenuItem(_("User Manual"), delegate, @selector(openUserManual), @"", helpMenu);
[helpMenu addItem:[NSMenuItem separatorItem]];
addMenuItem(_("General Information"), stringEncoding, delegate, @selector(openReadme), @"", helpMenu);
addMenuItem(_("What's New in ResidualVM"), stringEncoding, delegate, @selector(openNews), @"", helpMenu);
addMenuItem(_("General Information"), delegate, @selector(openReadme), @"", helpMenu);
addMenuItem(_("What's New in ResidualVM"), delegate, @selector(openNews), @"", helpMenu);
[helpMenu addItem:[NSMenuItem separatorItem]];
addMenuItem(_("Credits"), stringEncoding, delegate, @selector(openCredits), @"", helpMenu);
addMenuItem(_("GPL License"), stringEncoding, delegate, @selector(openLicenseGPL), @"", helpMenu);
addMenuItem(_("LGPL License"), stringEncoding, delegate, @selector(openLicenseLGPL), @"", helpMenu);
addMenuItem(_("Freefont License"), stringEncoding, delegate, @selector(openLicenseFreefont), @"", helpMenu);
addMenuItem(_("OFL License"), stringEncoding, delegate, @selector(openLicenseOFL), @"", helpMenu);
addMenuItem(_("BSD License"), stringEncoding, delegate, @selector(openLicenseBSD), @"", helpMenu);
addMenuItem(_("Credits"), delegate, @selector(openCredits), @"", helpMenu);
addMenuItem(_("GPL License"), delegate, @selector(openLicenseGPL), @"", helpMenu);
addMenuItem(_("LGPL License"), delegate, @selector(openLicenseLGPL), @"", helpMenu);
addMenuItem(_("Freefont License"), delegate, @selector(openLicenseFreefont), @"", helpMenu);
addMenuItem(_("OFL License"), delegate, @selector(openLicenseOFL), @"", helpMenu);
addMenuItem(_("BSD License"), delegate, @selector(openLicenseBSD), @"", helpMenu);
}
[appleMenu release];

View file

@ -35,7 +35,7 @@ int main(int argc, char *argv[]) {
assert(g_system);
// Pre initialize the backend
((OSystem_MacOSX *)g_system)->init();
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());

View file

@ -139,11 +139,11 @@ bool OSystem_MacOSX::hasTextInClipboard() {
return hasTextInClipboardMacOSX();
}
Common::String OSystem_MacOSX::getTextFromClipboard() {
Common::U32String OSystem_MacOSX::getTextFromClipboard() {
return getTextFromClipboardMacOSX();
}
bool OSystem_MacOSX::setTextInClipboard(const Common::String &text) {
bool OSystem_MacOSX::setTextInClipboard(const Common::U32String &text) {
return setTextInClipboardMacOSX(text);
}

View file

@ -34,8 +34,8 @@ public:
virtual bool displayLogFile();
virtual bool hasTextInClipboard();
virtual Common::String getTextFromClipboard();
virtual bool setTextInClipboard(const Common::String &text);
virtual Common::U32String getTextFromClipboard();
virtual bool setTextInClipboard(const Common::U32String &text);
virtual bool openUrl(const Common::String &url);

View file

@ -24,10 +24,11 @@
#define PLATFORM_SDL_MACOSX_WRAPPER_H
#include <common/str.h>
#include <common/ustr.h>
bool hasTextInClipboardMacOSX();
Common::String getTextFromClipboardMacOSX();
bool setTextInClipboardMacOSX(const Common::String &text);
Common::U32String getTextFromClipboardMacOSX();
bool setTextInClipboardMacOSX(const Common::U32String &text);
Common::String getDesktopPathMacOSX();
#endif

View file

@ -25,6 +25,7 @@
#include "backends/platform/sdl/macosx/macosx_wrapper.h"
#include "common/translation.h"
#include "backends/platform/sdl/macosx/macosx-compat.h"
#include <AppKit/NSPasteboard.h>
#include <Foundation/NSArray.h>
@ -32,43 +33,67 @@
#include <AvailabilityMacros.h>
#include <CoreFoundation/CFString.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
typedef unsigned long NSUInteger;
// Those are not defined in the 10.4 SDK, but they are defined when targetting
// Mac OS X 10.4 or above in the 10.5 SDK. So hopfully that means it works with 10.4 as well.
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
enum {
NSUTF32StringEncoding = 0x8c000100,
NSUTF32BigEndianStringEncoding = 0x98000100,
NSUTF32LittleEndianStringEncoding = 0x9c000100
};
#endif
#endif
bool hasTextInClipboardMacOSX() {
return [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]] != nil;
}
Common::String getTextFromClipboardMacOSX() {
Common::U32String getTextFromClipboardMacOSX() {
if (!hasTextInClipboardMacOSX())
return Common::String();
return Common::U32String();
// Note: on OS X 10.6 and above it is recommanded to use NSPasteboardTypeString rather than NSStringPboardType.
// But since we still target older version use NSStringPboardType.
NSPasteboard *pb = [NSPasteboard generalPasteboard];
NSString *str = [pb stringForType:NSStringPboardType];
if (str == nil)
return Common::String();
return Common::U32String();
// If translations are supported, use the current TranslationManager charset and otherwise
// use ASCII. If the string cannot be represented using the requested encoding we get a null
// pointer below, which is fine as ScummVM would not know what to do with the string anyway.
#ifdef USE_TRANSLATION
NSString* encStr = [NSString stringWithCString:TransMan.getCurrentCharset().c_str() encoding:NSASCIIStringEncoding];
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)encStr));
#ifdef SCUMM_LITTLE_ENDIAN
NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
#else
NSStringEncoding encoding = NSISOLatin1StringEncoding;
NSStringEncoding stringEncoding = NSUTF32BigEndianStringEncoding;
#endif
return Common::String([str cStringUsingEncoding:encoding]);
NSUInteger textLength = [str length];
uint32 *text = new uint32[textLength];
if (![str getBytes:text maxLength:4*textLength usedLength:NULL encoding: stringEncoding options:0 range:NSMakeRange(0, textLength) remainingRange:NULL]) {
delete[] text;
return Common::U32String();
}
Common::U32String u32String(text, textLength);
delete[] text;
return u32String;
}
bool setTextInClipboardMacOSX(const Common::String &text) {
bool setTextInClipboardMacOSX(const Common::U32String &text) {
NSPasteboard *pb = [NSPasteboard generalPasteboard];
[pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
#ifdef USE_TRANSLATION
NSString* encStr = [NSString stringWithCString:TransMan.getCurrentCharset().c_str() encoding:NSASCIIStringEncoding];
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)encStr));
#ifdef SCUMM_LITTLE_ENDIAN
NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
#else
NSStringEncoding encoding = NSISOLatin1StringEncoding;
NSStringEncoding stringEncoding = NSUTF32BigEndianStringEncoding;
#endif
return [pb setString:[NSString stringWithCString:text.c_str() encoding:encoding] forType:NSStringPboardType];
NSString *nsstring = [[NSString alloc] initWithBytes:text.c_str() length:4*text.size() encoding: stringEncoding];
bool status = [pb setString:nsstring forType:NSStringPboardType];
[nsstring release];
return status;
}
Common::String getDesktopPathMacOSX() {

View file

@ -35,7 +35,7 @@ int main(int argc, char *argv[]) {
assert(g_system);
// Pre initialize the backend
((OSystem_POSIX *)g_system)->init();
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());

View file

@ -40,7 +40,7 @@ int main(int argc, char *argv[]) {
assert(g_system);
// Pre initialize the backend
((OSystem_PS3 *)g_system)->init();
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());

View file

@ -35,7 +35,7 @@ int main(int argc, char *argv[]) {
assert(g_system);
// Pre initialize the backend
((OSystem_RISCOS *)g_system)->init();
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());

View file

@ -202,8 +202,10 @@ bool SdlWindow::getSDLWMInformation(SDL_SysWMinfo *info) const {
SDL_VERSION(&info->version);
#if SDL_VERSION_ATLEAST(2, 0, 0)
return _window ? (SDL_GetWindowWMInfo(_window, info) == SDL_TRUE) : false;
#else
#elif !defined(__MORPHOS__)
return SDL_GetWMInfo(info);
#else
return false;
#endif
}

View file

@ -30,6 +30,10 @@
#include "common/translation.h"
#include "common/encoding.h"
#ifdef USE_DISCORD
#include "backends/presence/discord/discord.h"
#endif
#include "backends/saves/default/default-saves.h"
// Audio CD support was removed with SDL 2.0
@ -90,7 +94,6 @@ OSystem_SDL::OSystem_SDL()
_initedSDLnet(false),
#endif
_logger(0),
_mixerManager(0),
_eventSource(0),
_eventSourceWrapper(nullptr),
_window(0) {
@ -100,7 +103,7 @@ OSystem_SDL::~OSystem_SDL() {
SDL_ShowCursor(SDL_ENABLE);
// Delete the various managers here. Note that the ModularBackend
// destructor would also take care of this for us. However, various
// destructors would also take care of this for us. However, various
// of our managers must be deleted *before* we call SDL_Quit().
// Hence, we perform the destruction on our own.
delete _savefileManager;
@ -138,6 +141,11 @@ OSystem_SDL::~OSystem_SDL() {
delete _logger;
_logger = 0;
#ifdef USE_DISCORD
delete _presence;
_presence = 0;
#endif
#ifdef USE_SDL_NET
if (_initedSDLnet) SDLNet_Quit();
#endif
@ -179,7 +187,7 @@ bool OSystem_SDL::hasFeature(Feature f) {
if (f == kFeatureJoystickDeadzone || f == kFeatureKbdMouseSpeed) {
return _eventSource->isJoystickConnected();
}
return ModularBackend::hasFeature(f);
return ModularGraphicsBackend::hasFeature(f);
}
void OSystem_SDL::initBackend() {
@ -282,9 +290,13 @@ void OSystem_SDL::initBackend() {
// Setup a custom program icon.
_window->setupIcon();
#ifdef USE_DISCORD
_presence = new DiscordPresence();
#endif
_inited = true;
ModularBackend::initBackend();
BaseBackend::initBackend();
// We have to initialize the graphics manager before the event manager
// so the virtual keyboard can be initialized, but we have to add the
@ -383,9 +395,14 @@ void OSystem_SDL::engineInit() {
// Add the started engine to the list of recent tasks
_taskbarManager->addRecent(ConfMan.getActiveDomainName(), ConfMan.get("description"));
// Set the overlay icon the current running engine
// Set the overlay icon to the current running engine
_taskbarManager->setOverlayIcon(ConfMan.getActiveDomainName(), ConfMan.get("description"));
#endif
#ifdef USE_DISCORD
// Set the presence status to the current running engine
_presence->updateStatus(ConfMan.get("gameid"), ConfMan.get("description"));
#endif
_eventSource->setEngineRunning(true);
}
@ -397,6 +414,10 @@ void OSystem_SDL::engineDone() {
#ifdef USE_TASKBAR
// Remove overlay icon
_taskbarManager->setOverlayIcon("", "");
#endif
#ifdef USE_DISCORD
// Reset presence status
_presence->updateStatus("", "");
#endif
_eventSource->setEngineRunning(false);
}
@ -486,7 +507,7 @@ void OSystem_SDL::setupScreen(uint screenW, uint screenH, bool fullscreen, bool
sdlGraphicsManager->activateManager();
}
ModularBackend::setupScreen(screenW, screenH, fullscreen, accel3d);
ModularGraphicsBackend::setupScreen(screenW, screenH, fullscreen, accel3d);
}
Common::Array<uint> OSystem_SDL::getSupportedAntiAliasingLevels() const {
@ -517,7 +538,7 @@ void OSystem_SDL::fatalError() {
}
Common::KeymapArray OSystem_SDL::getGlobalKeymaps() {
Common::KeymapArray globalMaps = ModularBackend::getGlobalKeymaps();
Common::KeymapArray globalMaps = BaseBackend::getGlobalKeymaps();
SdlGraphicsManager *graphicsManager = dynamic_cast<SdlGraphicsManager *>(_graphicsManager);
globalMaps.push_back(graphicsManager->getKeymap());
@ -588,7 +609,7 @@ Common::String OSystem_SDL::getSystemLanguage() const {
// Detect the language from the locale
if (locale.empty()) {
return ModularBackend::getSystemLanguage();
return BaseBackend::getSystemLanguage();
} else {
int length = 0;
@ -606,7 +627,7 @@ Common::String OSystem_SDL::getSystemLanguage() const {
return Common::String(locale.c_str(), length);
}
#else // USE_DETECTLANG
return ModularBackend::getSystemLanguage();
return BaseBackend::getSystemLanguage();
#endif // USE_DETECTLANG
}
@ -615,41 +636,22 @@ bool OSystem_SDL::hasTextInClipboard() {
return SDL_HasClipboardText() == SDL_TRUE;
}
Common::String OSystem_SDL::getTextFromClipboard() {
if (!hasTextInClipboard()) return "";
Common::U32String OSystem_SDL::getTextFromClipboard() {
if (!hasTextInClipboard()) return Common::U32String("");
char *text = SDL_GetClipboardText();
// The string returned by SDL is in UTF-8. Convert to the
// current TranslationManager encoding or ISO-8859-1.
#ifdef USE_TRANSLATION
char *conv_text = SDL_iconv_string(TransMan.getCurrentCharset().c_str(), "UTF-8", text, SDL_strlen(text) + 1);
#else
char *conv_text = SDL_iconv_string("ISO-8859-1", "UTF-8", text, SDL_strlen(text) + 1);
#endif
if (conv_text) {
SDL_free(text);
text = conv_text;
}
Common::String strText = text;
Common::String utf8Text(text);
Common::U32String strText = utf8Text.decode();
SDL_free(text);
return strText;
}
bool OSystem_SDL::setTextInClipboard(const Common::String &text) {
// The encoding we need to use is UTF-8. Assume we currently have the
// current TranslationManager encoding or ISO-8859-1.
#ifdef USE_TRANSLATION
char *utf8_text = SDL_iconv_string("UTF-8", TransMan.getCurrentCharset().c_str(), text.c_str(), text.size() + 1);
#else
char *utf8_text = SDL_iconv_string("UTF-8", "ISO-8859-1", text.c_str(), text.size() + 1);
#endif
if (utf8_text) {
int status = SDL_SetClipboardText(utf8_text);
SDL_free(utf8_text);
return status == 0;
}
return SDL_SetClipboardText(text.c_str()) == 0;
bool OSystem_SDL::setTextInClipboard(const Common::U32String &text) {
// The encoding we need to use is UTF-8.
Common::String utf8Text = text.encode();
return SDL_SetClipboardText(utf8Text.c_str()) == 0;
}
#endif
@ -682,12 +684,7 @@ void OSystem_SDL::getTimeAndDate(TimeDate &td) const {
td.tm_wday = t.tm_wday;
}
Audio::Mixer *OSystem_SDL::getMixer() {
assert(_mixerManager);
return getMixerManager()->getMixer();
}
SdlMixerManager *OSystem_SDL::getMixerManager() {
MixerManager *OSystem_SDL::getMixerManager() {
assert(_mixerManager);
#ifdef ENABLE_EVENTRECORDER
@ -882,7 +879,7 @@ void OSystem_SDL::setupGraphicsModes() {
#endif // ResidualVM
char *OSystem_SDL::convertEncoding(const char *to, const char *from, const char *string, size_t length) {
#if SDL_VERSION_ATLEAST(1, 2, 10)
#if SDL_VERSION_ATLEAST(1, 2, 10) && !defined(__MORPHOS__)
int zeroBytes = 1;
if (Common::String(from).hasPrefixIgnoreCase("utf-16"))
zeroBytes = 2;
@ -924,7 +921,7 @@ char *OSystem_SDL::convertEncoding(const char *to, const char *from, const char
SDL_free(result);
return finalResult;
#else
return ModularBackend::convertEncoding(to, from, string, length);
return BaseBackend::convertEncoding(to, from, string, length);
#endif // SDL_VERSION_ATLEAST(1, 2, 10)
}

View file

@ -30,18 +30,22 @@
#include "backends/events/sdl/sdl-events.h"
#include "backends/log/log.h"
#include "backends/platform/sdl/sdl-window.h"
#include "common/array.h"
#ifdef USE_DISCORD
class DiscordPresence;
#endif
// ResidualVM - Start
#ifdef USE_OPENGL
#include "backends/graphics/openglsdl/openglsdl-graphics.h"
#endif
// ResidualVM - End
#include "common/array.h"
/**
* Base OSystem class for all SDL ports.
*/
class OSystem_SDL : public ModularBackend {
class OSystem_SDL : public ModularMutexBackend, public ModularMixerBackend, public ModularGraphicsBackend {
public:
OSystem_SDL();
virtual ~OSystem_SDL();
@ -51,14 +55,7 @@ public:
* instantiating the backend. Early needed managers are
* created here.
*/
virtual void init();
/**
* Get the Mixer Manager instance. Not to confuse with getMixer(),
* that returns Audio::Mixer. The Mixer Manager is a SDL wrapper class
* for the Audio::Mixer. Used by other managers.
*/
virtual SdlMixerManager *getMixerManager();
virtual void init() override;
virtual bool hasFeature(Feature f) override;
@ -79,8 +76,8 @@ public:
#if SDL_VERSION_ATLEAST(2, 0, 0)
// Clipboard
virtual bool hasTextInClipboard() override;
virtual Common::String getTextFromClipboard() override;
virtual bool setTextInClipboard(const Common::String &text) override;
virtual Common::U32String getTextFromClipboard() override;
virtual bool setTextInClipboard(const Common::U32String &text) override;
#endif
virtual void setWindowCaption(const char *caption) override;
@ -88,7 +85,7 @@ public:
virtual uint32 getMillis(bool skipRecord = false) override;
virtual void delayMillis(uint msecs) override;
virtual void getTimeAndDate(TimeDate &td) const override;
virtual Audio::Mixer *getMixer() override;
virtual MixerManager *getMixerManager() override;
virtual Common::TimerManager *getTimerManager() override;
virtual Common::SaveFileManager *getSavefileManager() override;
@ -110,6 +107,10 @@ protected:
bool _initedSDLnet;
#endif
#ifdef USE_DISCORD
DiscordPresence *_presence;
#endif
/**
* The path of the currently open log file, if any.
*
@ -120,12 +121,6 @@ protected:
*/
Common::String _logFilePath;
/**
* Mixer manager that configures and setups SDL for
* the wrapped Audio::Mixer, the true mixer.
*/
SdlMixerManager *_mixerManager;
/**
* The event source we use for obtaining SDL events.
*/
@ -146,7 +141,6 @@ protected:
#endif
// End of ResidualVM specific code
virtual Common::EventSource *getDefaultEventSource() override { return _eventSource; }
/**
* Initialze the SDL library.

View file

@ -61,7 +61,7 @@ int main(int argc, char *argv[]) {
assert(g_system);
// Pre initialize the backend
((OSystem_Win32 *)g_system)->init();
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());

View file

@ -474,18 +474,12 @@ char *OSystem_Win32::convertEncoding(const char* to, const char *from, const cha
}
memcpy(tmpStr, string, length);
} else {
// Win32::ansiToUnicode uses new to allocate the memory. We need to copy it into an array
// allocated with malloc as it is going to be freed using free.
WCHAR *tmpStr2 = Win32::ansiToUnicode(string, Win32::getCodePageId(from));
if (!tmpStr2) {
tmpStr = Win32::ansiToUnicode(string, Win32::getCodePageId(from));
if (!tmpStr) {
if (newString != nullptr)
free(newString);
return nullptr;
}
size_t size = wcslen(tmpStr2) + 1; // +1 for the terminating null wchar
tmpStr = (WCHAR *) malloc(sizeof(WCHAR) * size);
memcpy(tmpStr, tmpStr2, sizeof(WCHAR) * size);
delete[] tmpStr2;
}
if (newString != nullptr)
@ -501,15 +495,7 @@ char *OSystem_Win32::convertEncoding(const char* to, const char *from, const cha
} else {
result = Win32::unicodeToAnsi(tmpStr, Win32::getCodePageId(to));
free(tmpStr);
if (!result)
return nullptr;
// Win32::unicodeToAnsi uses new to allocate the memory. We need to copy it into an array
// allocated with malloc as it is going to be freed using free.
size_t size = strlen(result) + 1;
char *resultCopy = (char *) malloc(sizeof(char) * size);
memcpy(resultCopy, result, sizeof(char) * size);
delete[] result;
return resultCopy;
return result;
}
}

View file

@ -85,7 +85,7 @@ wchar_t *ansiToUnicode(const char *s, uint codePage) {
DWORD size = MultiByteToWideChar(codePage, 0, s, -1, NULL, 0);
if (size > 0) {
LPWSTR result = new WCHAR[size];
LPWSTR result = (LPWSTR)calloc(size, sizeof(WCHAR));
if (MultiByteToWideChar(codePage, 0, s, -1, result, size) != 0)
return result;
}
@ -97,7 +97,7 @@ char *unicodeToAnsi(const wchar_t *s, uint codePage) {
DWORD size = WideCharToMultiByte(codePage, 0, s, -1, NULL, 0, 0, 0);
if (size > 0) {
char *result = new char[size];
char *result = (char *)calloc(size, sizeof(char));
if (WideCharToMultiByte(codePage, 0, s, -1, result, size, 0, 0) != 0)
return result;
}
@ -105,19 +105,16 @@ char *unicodeToAnsi(const wchar_t *s, uint codePage) {
return NULL;
}
uint getCurrentCharset() {
#ifdef USE_TRANSLATION
Common::String charset = TransMan.getCurrentCharset();
if (charset == "iso-8859-2")
return 28592;
if (charset == "iso-8859-5")
return 28595;
if (charset == "iso-8859-7")
return 28597;
if (charset == "iso-8859-8")
return 28598;
#endif
return 28591;
wchar_t *UTF8ToUnicode(const char *s) {
DWORD size = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
if (size > 0) {
LPWSTR result = (LPWSTR)calloc(size, sizeof(WCHAR));
if (MultiByteToWideChar(CP_UTF8, 0, s, -1, result, size) != 0)
return result;
}
return NULL;
}
}

View file

@ -43,6 +43,7 @@ bool confirmWindowsVersion(int majorVersion, int minorVersion);
* Used to interact with Win32 Unicode APIs with no ANSI fallback.
*
* @param s Source string
* @param c Code Page, by default is CP_ACP (default Windows ANSI code page)
* @return Converted string
*
* @note Return value must be freed by the caller.
@ -53,13 +54,23 @@ wchar_t *ansiToUnicode(const char *s, uint codePage = CP_ACP);
* Used to interact with Win32 Unicode APIs with no ANSI fallback.
*
* @param s Source string
* @param c Code Page, by default is CP_ACP (default Windows ANSI code page)
* @return Converted string
*
* @note Return value must be freed by the caller.
*/
char *unicodeToAnsi(const wchar_t *s, uint codePage = CP_ACP);
uint getCurrentCharset();
/**
* Converts a C string encoded in UTF8-multibyte char into a Windows wide-character string.
* Used to interact with Win32 Unicode APIs with no ANSI fallback.
*
* @param s Source string, encoded in UTF8
* @return Converted string
*
* @note Return value must be freed by the caller.
*/
wchar_t *UTF8ToUnicode(const char *s);
}

View file

@ -0,0 +1,59 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
#include "backends/presence/discord/discord.h"
#ifdef USE_DISCORD
#include "common/translation.h"
#include <discord_rpc.h>
#include <time.h>
#define DISCORD_CLIENT_ID "714287866464698470"
DiscordPresence::DiscordPresence() {
Discord_Initialize(DISCORD_CLIENT_ID, nullptr, 0, nullptr);
updateStatus("", "");
}
DiscordPresence::~DiscordPresence() {
Discord_ClearPresence();
Discord_Shutdown();
}
void DiscordPresence::updateStatus(const Common::String &name, const Common::String &description) {
Common::String gameName = name.empty() ? "residualvm" : name;
Common::String gameDesc = description.empty() ? _("Launcher").encode() : description;
DiscordRichPresence presence;
memset(&presence, 0, sizeof(presence));
presence.largeImageKey = gameName.c_str();
presence.largeImageText = gameDesc.c_str();
presence.details = gameDesc.c_str();
presence.smallImageKey = "residualvm";
presence.smallImageText = "ResidualVM";
presence.startTimestamp = time(0);
Discord_UpdatePresence(&presence);
}
#endif

View file

@ -18,37 +18,33 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* This is a utility for create the translations.dat file from all the po files.
* The generated files is used by ScummVM to propose translation of its GUI.
*/
#ifndef CP_PARSER_H
#define CP_PARSER_H
#ifndef BACKENDS_DISCORD_H
#define BACKENDS_DISCORD_H
#include "create_translations.h"
#include "common/scummsys.h"
#include <string>
#ifdef USE_DISCORD
#include "common/str.h"
/**
* Codepage description.
*
* This includes a name, and the codepage -> unicode mapping.
* Manager for interacting with the Discord Rich Presence API.
*/
class Codepage {
class DiscordPresence {
public:
Codepage(const std::string &name, const uint32 *mapping);
const std::string &getName() const { return _name; }
uint32 getMapping(unsigned char src) const { return _mapping[src]; }
private:
std::string _name;
uint32 _mapping[256];
DiscordPresence();
~DiscordPresence();
/**
* Updates the Discord presence status with game information.
* Blank parameters default to no game running (Launcher).
*
* @param name Game ID and icon to display.
* @param description Game name to display.
*/
void updateStatus(const Common::String &name, const Common::String &description);
};
/**
* Parse the codepage file and create a codepage.
*/
Codepage *parseCodepageMapping(const std::string &filename);
#endif
#endif

View file

@ -32,4 +32,3 @@ Common::InSaveFile *RecorderSaveFileManager::openForLoading(const Common::String
Common::StringArray RecorderSaveFileManager::listSaveFiles(const Common::String &pattern) {
return g_eventRec.listSaveFiles(pattern);
}

View file

@ -136,7 +136,7 @@ void Win32TaskbarManager::setOverlayIcon(const Common::String &name, const Commo
DestroyIcon(pIcon);
delete[] desc;
free(desc);
}
void Win32TaskbarManager::setProgressValue(int completed, int total) {
@ -267,7 +267,7 @@ void Win32TaskbarManager::setCount(int count) {
// Sets the overlay icon
LPWSTR desc = Win32::ansiToUnicode(Common::String::format("Found games: %d", count).c_str());
_taskbar->SetOverlayIcon(_window->getHwnd(), _icon, desc);
delete[] desc;
free(desc);
}
void Win32TaskbarManager::addRecent(const Common::String &name, const Common::String &description) {
@ -301,7 +301,7 @@ void Win32TaskbarManager::addRecent(const Common::String &name, const Common::St
link->SetIconLocation(icon, 0);
delete[] icon;
free(icon);
}
// The link's display name must be set via property store.
@ -321,8 +321,8 @@ void Win32TaskbarManager::addRecent(const Common::String &name, const Common::St
// SHAddToRecentDocs will cause the games to be added to the Recent list, allowing the user to pin them.
SHAddToRecentDocs(SHARD_LINK, link);
link->Release();
delete[] game;
delete[] desc;
free(game);
free(desc);
}
}

View file

@ -177,7 +177,7 @@ void SpeechDispatcherManager::updateState(SpeechDispatcherManager::SpeechEvent e
}
}
bool SpeechDispatcherManager::say(Common::String str, Action action, Common::String charset) {
bool SpeechDispatcherManager::say(const Common::U32String &str, Action action) {
pthread_mutex_lock(&_speechMutex);
// reinitialize if needed
@ -194,22 +194,7 @@ bool SpeechDispatcherManager::say(Common::String str, Action action, Common::Str
return true;
}
if (charset.empty()) {
#ifdef USE_TRANSLATION
charset = TransMan.getCurrentCharset();
#else
charset = "ASCII";
#endif
}
char *tmpStr = Common::Encoding::convert("UTF-8", charset, str.c_str(), str.size());
if (tmpStr == nullptr) {
warning("Cannot convert from %s encoding for text to speech", charset.c_str());
pthread_mutex_unlock(&_speechMutex);
return true;
}
Common::String strUtf8 = tmpStr;
free(tmpStr);
Common::String strUtf8 = str.encode();
if (!_speechQueue.empty() && action == INTERRUPT_NO_REPEAT &&
_speechQueue.front() == strUtf8 && isSpeaking()) {

View file

@ -29,6 +29,7 @@
#include "common/text-to-speech.h"
#include "common/str.h"
#include "common/ustr.h"
#include "common/list.h"
#include "common/mutex.h"
@ -59,7 +60,7 @@ public:
SpeechDispatcherManager();
virtual ~SpeechDispatcherManager() override;
virtual bool say(Common::String str, Action action, Common::String charset = "") override;
virtual bool say(const Common::U32String &str, Action action) override;
virtual bool stop() override;
virtual bool pause() override;

View file

@ -29,13 +29,14 @@
#include "common/text-to-speech.h"
#include "common/queue.h"
#include "common/ustr.h"
class MacOSXTextToSpeechManager : public Common::TextToSpeechManager {
public:
MacOSXTextToSpeechManager();
virtual ~MacOSXTextToSpeechManager() override;
virtual bool say(Common::String str, Action action, Common::String charset = "") override;
virtual bool say(const Common::U32String &str, Action action) override;
virtual bool stop() override;
virtual bool pause() override;
@ -64,12 +65,7 @@ public:
private:
virtual void updateVoices() override;
struct SpeechText {
Common::String text;
Common::String encoding;
SpeechText(const Common::String& txt, const Common::String& enc) : text(txt), encoding(enc) {}
};
Common::Queue<SpeechText> _messageQueue;
Common::Queue<Common::String> _messageQueue;
Common::String _currentSpeech;
bool _paused;
};

View file

@ -81,7 +81,8 @@ MacOSXTextToSpeechManager::~MacOSXTextToSpeechManager() {
[synthesizerDelegate release];
}
bool MacOSXTextToSpeechManager::say(Common::String text, Action action, Common::String encoding) {
bool MacOSXTextToSpeechManager::say(const Common::U32String &text, Action action) {
Common::String textToSpeak = text.encode();
if (isSpeaking()) {
// Interruptions are done on word boundaries for nice transitions.
// Should we interrupt immediately?
@ -94,25 +95,19 @@ bool MacOSXTextToSpeechManager::say(Common::String text, Action action, Common::
// If the new speech is the one being currently said, continue that speech but clear the queue.
// And otherwise both clear the queue and interrupt the current speech.
_messageQueue.clear();
if (_currentSpeech == text)
if (_currentSpeech == textToSpeak)
return true;
[synthesizer stopSpeakingAtBoundary:NSSpeechWordBoundary];
} else if (action == QUEUE_NO_REPEAT) {
if (!_messageQueue.empty()) {
if (_messageQueue.back().text == text)
if (_messageQueue.back() == textToSpeak)
return true;
} else if (_currentSpeech == text)
} else if (_currentSpeech == textToSpeak)
return true;
}
}
if (encoding.empty()) {
#ifdef USE_TRANSLATION
encoding = TransMan.getCurrentCharset();
#endif
}
_messageQueue.push(SpeechText(text, encoding));
_messageQueue.push(textToSpeak);
if (!isSpeaking())
startNextSpeech();
return true;
@ -122,20 +117,17 @@ bool MacOSXTextToSpeechManager::startNextSpeech() {
_currentSpeech.clear();
if (_messageQueue.empty())
return false;
SpeechText text = _messageQueue.pop();
// Get current encoding
CFStringEncoding stringEncoding = kCFStringEncodingASCII;
if (!text.encoding.empty()) {
CFStringRef encStr = CFStringCreateWithCString(NULL, text.encoding.c_str(), kCFStringEncodingASCII);
stringEncoding = CFStringConvertIANACharSetNameToEncoding(encStr);
CFRelease(encStr);
}
CFStringRef textNSString = CFStringCreateWithCString(NULL, text.text.c_str(), stringEncoding);
Common::String textToSpeak = _messageQueue.pop();
// Get current encoding
CFStringEncoding stringEncoding = kCFStringEncodingUTF8;
CFStringRef textNSString = CFStringCreateWithCString(NULL, textToSpeak.c_str(), stringEncoding);
bool status = [synthesizer startSpeakingString:(NSString *)textNSString];
CFRelease(textNSString);
if (status)
_currentSpeech = text.text;
_currentSpeech = textToSpeak;
return status;
}

View file

@ -174,7 +174,7 @@ DWORD WINAPI startSpeech(LPVOID parameters) {
return 0;
}
bool WindowsTextToSpeechManager::say(Common::String str, Action action, Common::String charset) {
bool WindowsTextToSpeechManager::say(const Common::U32String &str, Action action) {
if (_speechState == BROKEN || _speechState == NO_VOICE) {
warning("The text to speech cannot speak in this state");
return true;
@ -183,18 +183,13 @@ bool WindowsTextToSpeechManager::say(Common::String str, Action action, Common::
if (isSpeaking() && action == DROP)
return true;
if (charset.empty()) {
#ifdef USE_TRANSLATION
charset = TransMan.getCurrentCharset();
#else
charset = "ASCII";
#endif
}
Common::String strToSpeak = str.encode();
Common::String charset = "UTF-8";
// We have to set the pitch by prepending xml code at the start of the said string;
Common::String pitch= Common::String::format("<pitch absmiddle=\"%d\">", _ttsState->_pitch / 10);
str.replace((uint32)0, 0, pitch);
WCHAR *strW = (WCHAR *) Common::Encoding::convert("UTF-16", charset, str.c_str(), str.size());
Common::String pitch = Common::String::format("<pitch absmiddle=\"%d\">", _ttsState->_pitch / 10);
strToSpeak.replace((uint32)0, 0, pitch);
WCHAR *strW = (WCHAR *) Common::Encoding::convert("UTF-16", charset, strToSpeak.c_str(), strToSpeak.size());
if (strW == nullptr) {
warning("Cannot convert from %s encoding for text to speech", charset.c_str());
return true;
@ -362,7 +357,7 @@ void WindowsTextToSpeechManager::createVoice(void *cpVoiceToken) {
if (SUCCEEDED(hr)) {
buffer = Win32::unicodeToAnsi(descW);
desc = buffer;
delete[] buffer;
free(buffer);
CoTaskMemFree(descW);
}
@ -389,9 +384,7 @@ void WindowsTextToSpeechManager::createVoice(void *cpVoiceToken) {
warning("Could not get the language attribute for voice: %s", desc.c_str());
return;
}
buffer = Win32::unicodeToAnsi(data);
Common::String language = lcidToLocale(buffer);
delete[] buffer;
Common::String language = lcidToLocale(data);
CoTaskMemFree(data);
// only get the voices for the current language
@ -407,9 +400,7 @@ void WindowsTextToSpeechManager::createVoice(void *cpVoiceToken) {
warning("Could not get the gender attribute for voice: %s", desc.c_str());
return;
}
buffer = Win32::unicodeToAnsi(data);
Common::TTSVoice::Gender gender = !strcmp(buffer, "Male") ? Common::TTSVoice::MALE : Common::TTSVoice::FEMALE;
delete[] buffer;
Common::TTSVoice::Gender gender = !wcscmp(data, L"Male") ? Common::TTSVoice::MALE : Common::TTSVoice::FEMALE;
CoTaskMemFree(data);
// age
@ -419,35 +410,31 @@ void WindowsTextToSpeechManager::createVoice(void *cpVoiceToken) {
warning("Could not get the age attribute for voice: %s", desc.c_str());
return;
}
buffer = Win32::unicodeToAnsi(data);
Common::TTSVoice::Age age = !strcmp(buffer, "Adult") ? Common::TTSVoice::ADULT : Common::TTSVoice::UNKNOWN_AGE;
delete[] buffer;
Common::TTSVoice::Age age = !wcscmp(data, L"Adult") ? Common::TTSVoice::ADULT : Common::TTSVoice::UNKNOWN_AGE;
CoTaskMemFree(data);
_ttsState->_availableVoices.push_back(Common::TTSVoice(gender, age, (void *) voiceToken, desc));
}
int strToInt(Common::String str) {
str.toUppercase();
int strToInt(WCHAR *str) {
int result = 0;
for (unsigned i = 0; i < str.size(); i++) {
if (str[i] < '0' || (str[i] > '9' && str[i] < 'A') || str[i] > 'F')
for (unsigned i = 0; i < wcslen(str); i++) {
WCHAR c = towupper(str[i]);
if (c < L'0' || (c > L'9' && c < L'A') || c > L'F')
break;
int num = (str[i] <= '9') ? str[i] - '0' : str[i] - 55;
int num = (c <= L'9') ? c - L'0' : c - 55;
result = result * 16 + num;
}
return result;
}
Common::String WindowsTextToSpeechManager::lcidToLocale(Common::String lcid) {
Common::String WindowsTextToSpeechManager::lcidToLocale(WCHAR *lcid) {
LCID locale = strToInt(lcid);
int nchars = GetLocaleInfoW(locale, LOCALE_SISO639LANGNAME, NULL, 0);
wchar_t *languageCode = new wchar_t[nchars];
GetLocaleInfoW(locale, LOCALE_SISO639LANGNAME, languageCode, nchars);
char *resultTmp = Win32::unicodeToAnsi(languageCode);
Common::String result = resultTmp;
int nchars = GetLocaleInfoA(locale, LOCALE_SISO639LANGNAME, NULL, 0);
char *languageCode = new char[nchars];
GetLocaleInfoA(locale, LOCALE_SISO639LANGNAME, languageCode, nchars);
Common::String result = languageCode;
delete[] languageCode;
free(resultTmp);
return result;
}

View file

@ -29,6 +29,7 @@
#include "common/text-to-speech.h"
#include "common/str.h"
#include "common/ustr.h"
#include "common/list.h"
@ -51,7 +52,7 @@ public:
WindowsTextToSpeechManager();
virtual ~WindowsTextToSpeechManager() override;
virtual bool say(Common::String str, Action action, Common::String charset = "") override;
virtual bool say(const Common::U32String &str, Action action) override;
virtual bool stop() override;
virtual bool pause() override;
@ -77,7 +78,7 @@ private:
void init();
virtual void updateVoices() override;
void createVoice(void *cpVoiceToken);
Common::String lcidToLocale(Common::String lcid);
Common::String lcidToLocale(WCHAR *lcid);
SpeechState _speechState;
Common::String _lastSaid;
HANDLE _thread;

View file

@ -29,11 +29,10 @@
#include "common/textconsole.h"
static volatile bool timerInstalled = false;
OSystem::MutexRef timerMutex;
static Uint32 timer_handler(Uint32 interval, void *param) {
if (!timerInstalled)
return interval;
Common::StackLock lock(timerMutex);
((DefaultTimerManager *)param)->handler();
return interval;
@ -45,16 +44,17 @@ SdlTimerManager::SdlTimerManager() {
error("Could not initialize SDL: %s", SDL_GetError());
}
timerInstalled = true;
// Creates the timer callback
_timerID = SDL_AddTimer(10, &timer_handler, this);
}
SdlTimerManager::~SdlTimerManager() {
timerInstalled = false;
Common::StackLock lock(timerMutex);
// Removes the timer callback
SDL_RemoveTimer(_timerID);
SDL_QuitSubSystem(SDL_INIT_TIMER);
}
#endif

View file

@ -70,13 +70,8 @@ MacOSXUpdateManager::MacOSXUpdateManager() {
// Set appcast URL
[sparkleUpdater setFeedURL:[NSURL URLWithString:feedbackURL]];
// Get current encoding
CFStringRef encStr = CFStringCreateWithCString(NULL, TransMan.getCurrentCharset().c_str(), kCFStringEncodingASCII);
CFStringEncoding stringEncoding = CFStringConvertIANACharSetNameToEncoding(encStr);
CFRelease(encStr);
// Add "Check for Updates..." menu item
CFStringRef title = CFStringCreateWithCString(NULL, _("Check for Updates..."), stringEncoding);
CFStringRef title = CFStringCreateWithCString(NULL, _("Check for Updates...").encode().c_str(), kCFStringEncodingUTF8);
NSMenuItem *updateMenuItem = [applicationMenu insertItemWithTitle:(NSString *)title action:@selector(checkForUpdates:) keyEquivalent:@"" atIndex:1];
CFRelease(title);

View file

@ -248,7 +248,6 @@ void registerDefaults() {
// Graphics
ConfMan.registerDefault("fullscreen", false);
ConfMan.registerDefault("filtering", false);
ConfMan.registerDefault("show_fps", false);
ConfMan.registerDefault("aspect_ratio", false);
/* ResidualVM - not used
ConfMan.registerDefault("gfx_mode", "normal");
@ -993,7 +992,7 @@ static Common::Error listSaves(const Common::String &singleTarget) {
" ---- ------------------------------------------------------\n");
for (SaveStateList::const_iterator x = saveList.begin(); x != saveList.end(); ++x) {
printf(" %-4d %s\n", x->getSaveSlot(), x->getDescription().c_str());
printf(" %-4d %s\n", x->getSaveSlot(), x->getDescription().encode().c_str());
// TODO: Could also iterate over the full hashmap, printing all key-value pairs
}
atLeastOneFound = true;
@ -1056,8 +1055,8 @@ static DetectedGames getGameList(const Common::FSNode &dir) {
DetectionResults detectionResults = EngineMan.detectGames(files);
if (detectionResults.foundUnknownGames()) {
Common::String report = detectionResults.generateUnknownGameReport(false, 80);
g_system->logMessage(LogMessageType::kInfo, report.c_str());
Common::U32String report = detectionResults.generateUnknownGameReport(false, 80);
g_system->logMessage(LogMessageType::kInfo, report.encode().c_str());
}
return detectionResults.listRecognizedGames();

View file

@ -261,7 +261,7 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
if (token.equalsIgnoreCase("all"))
DebugMan.enableAllDebugChannels();
else if (!DebugMan.enableDebugChannel(token))
warning(_("Engine does not support debug level '%s'"), token.c_str());
warning("Engine does not support debug level '%s'", token.c_str());
}
#ifdef USE_TRANSLATION

View file

@ -22,7 +22,6 @@
#include "base/plugins.h"
#include "common/translation.h"
#include "common/func.h"
#include "common/debug.h"
#include "common/config-manager.h"
@ -362,7 +361,7 @@ void PluginManagerUncached::loadFirstPlugin() {
bool PluginManagerUncached::loadNextPlugin() {
unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false);
if (!_currentPlugin)
if (!_currentPlugin || _currentPlugin == _allEnginePlugins.end())
return false;
for (++_currentPlugin; _currentPlugin != _allEnginePlugins.end(); ++_currentPlugin) {

View file

@ -52,6 +52,11 @@
#include "common/hash-str.h"
#include "common/rect.h"
#ifndef DONT_TEST_UNICODE_STRING_LITERAL
const char16_t *u16str = u"\u00DAnicode string";
const char32_t *u32str = U"\u00DAnicode string";
#endif
#ifndef DONT_TEST_INITIALIZIER_LIST1
#ifndef USE_INITIALIZIER_LIST_REPLACEMENT
#include <initializer_list>

View file

@ -56,7 +56,7 @@
* to properly work in exports (i.e. release tar balls etc.).
*/
const char *gScummVMVersion = SCUMMVM_VERSION SCUMMVM_REVISION;
#ifdef __amigaos4__
#if defined(__amigaos4__) || defined(__MORPHOS__)
static const char *version_cookie __attribute__((used)) = "$VER: ResidualVM " SCUMMVM_VERSION SCUMMVM_REVISION " (" AMIGA_DATE ")";
#endif
const char *gScummVMBuildDate = __DATE__ " " __TIME__;

View file

@ -88,9 +88,12 @@ bool AchievementsManager::setAchievement(const String &id, const String &display
_iniFile->saveToSaveFile(_iniFileName);
if (!displayedMessage.empty() && g_system) {
String msg;
msg = Common::String::format("%s\n%s", _("Achievement unlocked!"), displayedMessage.c_str());
g_system->displayMessageOnOSD(msg.c_str());
U32String msg;
msg = Common::U32String::format(Common::U32String("%S\n%S"),
_("Achievement unlocked!").c_str(),
Common::U32String(displayedMessage).c_str()
);
g_system->displayMessageOnOSD(msg);
}
return true;

View file

@ -392,13 +392,14 @@ protected:
/**
* Double linked list with sorted nodes.
*/
template<class T>
template<class T, typename CompareArgType = const void *>
class SortedArray : public Array<T> {
public:
typedef int (*Comparator)(CompareArgType, CompareArgType);
typedef T *iterator;
typedef uint size_type;
SortedArray(int (*comparator)(const void *, const void *)) {
SortedArray(Comparator comparator) {
_comparator = comparator;
}
@ -435,7 +436,7 @@ private:
// Based on code Copyright (C) 2008-2009 Ksplice, Inc.
// Author: Tim Abbott <tabbott@ksplice.com>
// Licensed under GPLv2+
T *bsearchMin(void *key) {
T *bsearchMin(CompareArgType key) {
uint start_ = 0, end_ = this->_size;
int result;
@ -445,16 +446,14 @@ private:
result = this->_comparator(key, this->_storage[mid]);
if (result < 0)
end_ = mid;
else if (result > 0)
start_ = mid + 1;
else
return &this->_storage[mid];
start_ = mid + 1;
}
return &this->_storage[start_];
}
int (*_comparator)(const void *, const void *);
Comparator _comparator;
};
} // End of namespace Common

View file

@ -58,7 +58,7 @@ public:
* @param isDirBrowser Restrict selection to directories
* @return The dialog result
*/
virtual DialogResult showFileBrowser(const char *title, FSNode &choice, bool isDirBrowser = false) { return kDialogError; }
virtual DialogResult showFileBrowser(const Common::U32String &title, FSNode &choice, bool isDirBrowser = false) { return kDialogError; }
protected:
bool _wasFullscreen;

View file

@ -180,10 +180,6 @@ char *Encoding::conversion(const String &to, const String &from, const char *str
result = g_system->convertEncoding(addUtfEndianness(to).c_str(),
addUtfEndianness(from).c_str(), string, length);
if (result == nullptr) {
result = convertTransManMapping(addUtfEndianness(to).c_str(), addUtfEndianness(from).c_str(), string, length);
}
if (result == nullptr) {
result = convertConversionTable(addUtfEndianness(to).c_str(), addUtfEndianness(from).c_str(), string, length);
}
@ -239,7 +235,7 @@ char *Encoding::convertIconv(const char *to, const char *from, const char *strin
}
dst = buffer + (dst - oldString);
outSize = stringSize - (dst - buffer);
memset(dst, 0, stringSize / 2);
memset(dst, 0, outSize);
} else {
error = true;
break;
@ -277,81 +273,6 @@ char *Encoding::convertIconv(const char *to, const char *from, const char *strin
#endif //USE_ICONV
}
// This algorithm is able to convert only between the current TransMan charset
// and UTF-32, but if it fails, it tries to at least convert from the current
// TransMan encoding to UTF-32 and then it calls convert() again with that.
char *Encoding::convertTransManMapping(const char *to, const char *from, const char *string, size_t length) {
#ifdef USE_TRANSLATION
String currentCharset = TransMan.getCurrentCharset();
if (currentCharset.equalsIgnoreCase(from)) {
// We can use the transMan mapping directly
uint32 *partialResult = (uint32 *)calloc(sizeof(uint32), (length + 1));
if (!partialResult) {
warning("Couldn't allocate memory for encoding conversion");
return nullptr;
}
const uint32 *mapping = TransMan.getCharsetMapping();
if (mapping == 0) {
for(unsigned i = 0; i < length; i++) {
partialResult[i] = string[i];
}
} else {
for(unsigned i = 0; i < length; i++) {
partialResult[i] = mapping[(unsigned char)string[i]] & 0x7FFFFFFF;
}
}
char *finalResult = convert(to, "UTF-32", (char *)partialResult, length * 4);
free(partialResult);
return finalResult;
} else if (currentCharset.equalsIgnoreCase(to) && String(from).hasPrefixIgnoreCase("utf-32")) {
bool swapEndian = false;
char *newString = nullptr;
#ifdef SCUMM_BIG_ENDIAN
if (String(from).hasSuffixIgnoreCase("LE"))
swapEndian = true;
#else
if (String(from).hasSuffixIgnoreCase("BE"))
swapEndian = true;
#endif
if (swapEndian) {
if (String(from).hasPrefixIgnoreCase("utf-16"))
newString = switchEndian(string, length, 16);
if (String(from).hasPrefixIgnoreCase("utf-32"))
newString = switchEndian(string, length, 32);
if (newString != nullptr)
string = newString;
else
return nullptr;
}
// We can do reverse mapping
const uint32 *mapping = TransMan.getCharsetMapping();
const uint32 *src = (const uint32 *)string;
char *result = (char *)calloc(sizeof(char), (length + 4));
if (!result) {
warning("Couldn't allocate memory for encoding conversion");
if (newString != nullptr)
free(newString);
return nullptr;
}
for (unsigned i = 0; i < length; i++) {
for (int j = 0; j < 256; j++) {
if ((mapping[j] & 0x7FFFFFFF) == src[i]) {
result[i] = j;
break;
}
}
}
if (newString != nullptr)
free(newString);
return result;
} else
return nullptr;
#else
return nullptr;
#endif // USE_TRANSLATION
}
static uint32 g_cp850ConversionTable[] = {
0x0000, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
0x25d8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,

View file

@ -172,22 +172,6 @@ class Encoding {
*/
static char *convertIconv(const char *to, const char *from, const char *string, size_t length);
/**
* Tries to use the TransMan to convert the string. It can convert only
* between UTF-32 and the current GUI charset. It also tries to convert
* from the current GUI charset to UTF-32 and then it calls convert() again.
*
* The result has to be freed after use.
*
* @param to Name of the encoding the strings will be converted to
* @param from Name of the encoding the strings will be converted from
* @param string String that should be converted.
* @param length Length of the string to convert in bytes.
*
* @return Converted string (must be freed) or nullptr if the conversion failed
*/
static char *convertTransManMapping(const char *to, const char *from, const char *string, size_t length);
/**
* Uses conversion table to convert the string to unicode and from that
* to the final encoding. Important encodings, that aren't supported by

View file

@ -72,6 +72,7 @@ bool INIFile::loadFromStream(SeekableReadStream &stream) {
KeyValue kv;
String comment;
int lineno = 0;
section.name = _defaultSectionName;
// TODO: Detect if a section occurs multiple times (or likewise, if
// a key occurs multiple times inside one section).
@ -297,6 +298,9 @@ void INIFile::renameSection(const String &oldName, const String &newName) {
// - merge the two sections "oldName" and "newName"
}
void INIFile::setDefaultSectionName(const String &name) {
_defaultSectionName = name;
}
bool INIFile::hasKey(const String &key, const String &section) const {
if (!isValidName(key)) {

View file

@ -105,6 +105,8 @@ public:
void removeSection(const String &section);
void renameSection(const String &oldName, const String &newName);
void setDefaultSectionName(const String &name); ///< sets initial section name for section-less ini files
bool hasKey(const String &key, const String &section) const;
bool getKey(const String &key, const String &section, String &value) const;
void setKey(const String &key, const String &section, const String &value);
@ -118,6 +120,7 @@ public:
void allowNonEnglishCharacters();
private:
String _defaultSectionName;
SectionList _sections;
bool _allowNonEnglishCharacters;

View file

@ -25,7 +25,7 @@
#include "common/scummsys.h"
#if defined(__amigaos4__)
#if defined(__amigaos4__) || defined(__MORPHOS__)
// KEYCODE_LESS and KEYCODE_GREATER are already defined in AmigaOS, inside
// include/include_h/intuition/intuition.h (bug #3121350)
#if defined(KEYCODE_LESS) && defined(KEYCODE_GREATER)

View file

@ -33,7 +33,7 @@ namespace Common {
* Simple memory based 'stream', which implements the ReadStream interface for
* a plain memory block.
*/
class MemoryReadStream : public SeekableReadStream {
class MemoryReadStream : virtual public SeekableReadStream {
private:
const byte * const _ptrOrig;
const byte *_ptr;
@ -80,8 +80,8 @@ public:
*/
class MemoryReadStreamEndian : public MemoryReadStream, public SeekableReadStreamEndian {
public:
MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian)
: MemoryReadStream(buf, len), SeekableReadStreamEndian(bigEndian), ReadStreamEndian(bigEndian) {}
MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO)
: MemoryReadStream(buf, len, disposeMemory), SeekableReadStreamEndian(bigEndian), ReadStreamEndian(bigEndian) {}
int32 pos() const { return MemoryReadStream::pos(); }
int32 size() const { return MemoryReadStream::size(); }

View file

@ -47,7 +47,7 @@ void Mutex::unlock() {
#pragma mark -
StackLock::StackLock(MutexRef mutex, const char *mutexName)
StackLock::StackLock(OSystem::MutexRef mutex, const char *mutexName)
: _mutex(mutex), _mutexName(mutexName) {
lock();
}

View file

@ -30,23 +30,17 @@ namespace Common {
class Mutex;
/**
* An pseudo-opaque mutex type. See OSystem::createMutex etc. for more details.
*/
typedef OSystem::MutexRef MutexRef;
/**
* Auxillary class to (un)lock a mutex on the stack.
*/
class StackLock {
MutexRef _mutex;
OSystem::MutexRef _mutex;
const char *_mutexName;
void lock();
void unlock();
public:
explicit StackLock(MutexRef mutex, const char *mutexName = nullptr);
explicit StackLock(OSystem::MutexRef mutex, const char *mutexName = nullptr);
explicit StackLock(const Mutex &mutex, const char *mutexName = nullptr);
~StackLock();
};
@ -58,7 +52,7 @@ public:
class Mutex {
friend class StackLock;
MutexRef _mutex;
OSystem::MutexRef _mutex;
public:
Mutex();

View file

@ -38,7 +38,7 @@ void OSDMessageQueue::registerEventSource() {
g_system->getEventManager()->getEventDispatcher()->registerSource(this, false);
}
void OSDMessageQueue::addMessage(const char *msg) {
void OSDMessageQueue::addMessage(const Common::U32String &msg) {
_mutex.lock();
_messages.push(msg);
_mutex.unlock();
@ -50,8 +50,8 @@ bool OSDMessageQueue::pollEvent(Common::Event &event) {
uint t = g_system->getMillis();
if (t - _lastUpdate >= kMinimumDelay) {
_lastUpdate = t;
String msg = _messages.pop();
g_system->displayMessageOnOSD(msg.c_str());
Common::U32String msg = _messages.pop();
g_system->displayMessageOnOSD(msg);
}
}
_mutex.unlock();

View file

@ -26,6 +26,7 @@
#include "common/events.h"
#include "common/singleton.h"
#include "common/str.h"
#include "common/ustr.h"
#include "common/queue.h"
#include "common/mutex.h"
@ -48,7 +49,7 @@ public:
/**
* Add a message to the OSD message queue.
*/
void addMessage(const char *msg);
void addMessage(const Common::U32String &msg);
/**
* Common::EventSource interface
@ -63,7 +64,7 @@ public:
private:
Mutex _mutex;
Queue<String> _messages;
Queue<U32String> _messages;
uint32 _lastUpdate;
};

View file

@ -633,7 +633,11 @@ Graphics::Surface *PlaybackFile::getScreenShot(int number) {
void PlaybackFile::updateHeader() {
if (_mode == kWrite) {
StringArray dummy;
g_system->getSavefileManager()->updateSavefilesList(dummy);
_readStream = g_system->getSavefileManager()->openForLoading(_header.fileName);
assert (_readStream);
}
_readStream->seek(0);
skipHeader();

View file

@ -267,6 +267,34 @@ struct Rect {
int x = cx - w / 2, y = cy - h / 2;
return Rect(x, y, x + w, y + h);
}
/**
* Given target surface with size clip, this function ensures that
* blit arguments dst, rect are within clip rectangle.
* @param dst blit destination coordinates
* @param rect blit source rectangle
* @param clip clip rectangle (size of destination surface)
*/
static bool getBlitRect(Point &dst, Rect &rect, const Rect &clip) {
if (dst.x < clip.left) {
rect.left += clip.left - dst.x;
dst.x = clip.left;
}
if (dst.y < clip.top) {
rect.top += clip.top - dst.y;
dst.y = clip.top;
}
int right = dst.x + rect.right;
if (right > clip.right)
rect.right -= right - clip.right;
int bottom = dst.y + rect.bottom;
if (bottom > clip.bottom)
rect.bottom -= bottom - clip.bottom;
return !rect.isEmpty();
}
};
} // End of namespace Common

View file

@ -282,7 +282,7 @@
#define SCUMM_LITTLE_ENDIAN
#elif defined(__amigaos4__) || defined(__N64__) || defined(__WII__)
#elif defined(__MORPHOS__) || defined(__amigaos4__) || defined(__N64__) || defined(__WII__)
#define SCUMM_BIG_ENDIAN
#define SCUMM_NEED_ALIGNMENT

View file

@ -433,7 +433,7 @@ public:
inline MemoryReadStream toStream(const index_type index = 0, size_type numEntries = kSpanMaxSize) const {
if (numEntries == kSpanMaxSize) {
numEntries = impl().size();
numEntries = impl().size() - index;
}
impl().validate(index, numEntries * sizeof(value_type));

View file

@ -25,6 +25,7 @@
#include "common/array.h"
#include "common/str.h"
#include "common/ustr.h"
namespace Common {
@ -32,6 +33,7 @@ namespace Common {
* An array of of strings.
*/
typedef Array<String> StringArray;
typedef Array<U32String> U32StringArray;
} // End of namespace Common

Some files were not shown because too many files have changed in this diff Show more