aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/forbidden.h49
-rw-r--r--common/macresman.cpp31
-rw-r--r--common/str.cpp54
-rw-r--r--common/system.cpp98
-rw-r--r--common/system.h209
-rw-r--r--common/xmlparser.cpp23
-rw-r--r--common/xmlparser.h2
7 files changed, 346 insertions, 120 deletions
diff --git a/common/forbidden.h b/common/forbidden.h
index c551110d0e..9cba19cf5e 100644
--- a/common/forbidden.h
+++ b/common/forbidden.h
@@ -34,6 +34,9 @@
* Backend files may #define FORBIDDEN_SYMBOL_ALLOW_ALL if they
* have to access functions like fopen, fread etc.
* Regular code, esp. code in engines/, should never do that.
+ * To ease transition, though, we allow re-enabling selected symbols
+ * in frontend code. However, this should only be used as a temporary
+ * measure. Especially new code should avoid this at all costs.
*/
#ifndef FORBIDDEN_SYMBOL_ALLOW_ALL
@@ -51,7 +54,7 @@
* the compiler will hopefully print along with its own error message),
* we try to make clear what is causing the error.
*/
-#define FORBIDDEN_SYMBOL_REPLACEMENT FORBIDDEN SYMBOL !%*
+#define FORBIDDEN_SYMBOL_REPLACEMENT FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_printf
@@ -79,6 +82,21 @@
#define FILE FORBIDDEN_SYMBOL_REPLACEMENT
#endif
+#ifndef FORBIDDEN_SYMBOL_EXCEPTION_stdin
+#undef stdin
+#define stdin FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
+
+#ifndef FORBIDDEN_SYMBOL_EXCEPTION_stdout
+#undef stdout
+#define stdout FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
+
+#ifndef FORBIDDEN_SYMBOL_EXCEPTION_stderr
+#undef stderr
+#define stderr FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
+
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fopen
#undef fopen
#define fopen(a,b) FORBIDDEN_SYMBOL_REPLACEMENT
@@ -124,22 +142,41 @@
#define fputc(a,b) FORBIDDEN_SYMBOL_REPLACEMENT
#endif
+#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fgets
+#undef fgets
+#define fgets(a,b,c) FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
+
+#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fputs
+#undef fputs
+#define fputs(a,b) FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_getc
#undef getc
#define getc(a) FORBIDDEN_SYMBOL_REPLACEMENT
#endif
-#ifndef FORBIDDEN_SYMBOL_EXCEPTION_getchar
-#undef getchar
-#define getchar() FORBIDDEN_SYMBOL_REPLACEMENT
-#endif
-
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_putc
#undef putc
#define putc(a,b) FORBIDDEN_SYMBOL_REPLACEMENT
#endif
+#ifndef FORBIDDEN_SYMBOL_EXCEPTION_gets
+#undef gets
+#define gets(a) FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
+
+#ifndef FORBIDDEN_SYMBOL_EXCEPTION_puts
+#undef puts
+#define puts(a) FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
+
+#ifndef FORBIDDEN_SYMBOL_EXCEPTION_getchar
+#undef getchar
+#define getchar() FORBIDDEN_SYMBOL_REPLACEMENT
+#endif
+
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_putchar
#undef putchar
#define putchar(a) FORBIDDEN_SYMBOL_REPLACEMENT
diff --git a/common/macresman.cpp b/common/macresman.cpp
index 70c6e0a7ce..c1cab8b96a 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -32,7 +32,6 @@
#ifdef MACOSX
#include "common/config-manager.h"
-#include "backends/fs/stdiostream.h"
#endif
namespace Common {
@@ -108,14 +107,17 @@ bool MacResManager::open(String filename) {
#ifdef MACOSX
// Check the actual fork on a Mac computer
String fullPath = ConfMan.get("path") + "/" + filename + "/..namedfork/rsrc";
- SeekableReadStream *macResForkRawStream = StdioStream::makeFromPath(fullPath, false);
+ FSNode resFsNode = FSNode(fullPath);
+ if (resFsNode.exists()) {
+ SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();;
- if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
- _baseFileName = filename;
- return true;
- }
+ if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
+ _baseFileName = filename;
+ return true;
+ }
- delete macResForkRawStream;
+ delete macResForkRawStream;
+ }
#endif
File *file = new File();
@@ -168,14 +170,17 @@ bool MacResManager::open(FSNode path, String filename) {
#ifdef MACOSX
// Check the actual fork on a Mac computer
String fullPath = path.getPath() + "/" + filename + "/..namedfork/rsrc";
- SeekableReadStream *macResForkRawStream = StdioStream::makeFromPath(fullPath, false);
+ FSNode resFsNode = FSNode(fullPath);
+ if (resFsNode.exists()) {
+ SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();;
- if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
- _baseFileName = filename;
- return true;
- }
+ if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
+ _baseFileName = filename;
+ return true;
+ }
- delete macResForkRawStream;
+ delete macResForkRawStream;
+ }
#endif
// First, let's try to see if the Mac converted name exists
diff --git a/common/str.cpp b/common/str.cpp
index 740e7b6a06..223188bdd6 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -19,11 +19,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "common/str.h"
#include "common/hash-str.h"
-#include "common/util.h"
-
+#include "common/list.h"
#include "common/memorypool.h"
+#include "common/str.h"
+#include "common/util.h"
#include <stdarg.h>
@@ -256,7 +256,7 @@ String &String::operator=(char c) {
String &String::operator+=(const char *str) {
if (_str <= str && str <= _str + _size)
- return operator+=(Common::String(str));
+ return operator+=(String(str));
int len = strlen(str);
if (len > 0) {
@@ -270,7 +270,7 @@ String &String::operator+=(const char *str) {
String &String::operator+=(const String &str) {
if (&str == this)
- return operator+=(Common::String(str));
+ return operator+=(String(str));
int len = str._size;
if (len > 0) {
@@ -612,7 +612,7 @@ char *trim(char *t) {
return rtrim(ltrim(t));
}
-Common::String lastPathComponent(const Common::String &path, const char sep) {
+String lastPathComponent(const String &path, const char sep) {
const char *str = path.c_str();
const char *last = str + path.size();
@@ -622,7 +622,7 @@ Common::String lastPathComponent(const Common::String &path, const char sep) {
// Path consisted of only slashes -> return empty string
if (last == str)
- return Common::String();
+ return String();
// Now scan the whole component
const char *first = last - 1;
@@ -632,24 +632,26 @@ Common::String lastPathComponent(const Common::String &path, const char sep) {
if (*first == sep)
first++;
- return Common::String(first, last);
+ return String(first, last);
}
-Common::String normalizePath(const Common::String &path, const char sep) {
+String normalizePath(const String &path, const char sep) {
if (path.empty())
return path;
const char *cur = path.c_str();
- Common::String result;
+ String result;
// If there is a leading slash, preserve that:
if (*cur == sep) {
result += sep;
+ // Skip over multiple leading slashes, so "//" equals "/"
while (*cur == sep)
++cur;
}
- // Scan till the end of the String
+ // Scan for path components till the end of the String
+ List<String> comps;
while (*cur != 0) {
const char *start = cur;
@@ -657,18 +659,16 @@ Common::String normalizePath(const Common::String &path, const char sep) {
while (*cur != sep && *cur != 0)
cur++;
- const Common::String component(start, cur);
-
- // Skip empty components and dot components, add all others
- if (!component.empty() && component != ".") {
- // Add a separator before the component, unless the result
- // string already ends with one (which happens only if the
- // path *starts* with a separator).
- if (!result.empty() && result.lastChar() != sep)
- result += sep;
+ const String component(start, cur);
- // Add the component
- result += component;
+ if (component.empty() || component == ".") {
+ // Skip empty components and dot components
+ } else if (!comps.empty() && component == ".." && comps.back() != "..") {
+ // If stack is non-empty and top is not "..", remove top
+ comps.pop_back();
+ } else {
+ // Add the component to the stack
+ comps.push_back(component);
}
// Skip over separator chars
@@ -676,6 +676,14 @@ Common::String normalizePath(const Common::String &path, const char sep) {
cur++;
}
+ // Finally, assemble all components back into a path
+ while (!comps.empty()) {
+ result += comps.front();
+ comps.pop_front();
+ if (!comps.empty())
+ result += sep;
+ }
+
return result;
}
@@ -749,7 +757,7 @@ String tag2string(uint32 tag) {
if (!isprint((unsigned char)str[i]))
str[i] = '.';
}
- return Common::String(str);
+ return String(str);
}
size_t strlcpy(char *dst, const char *src, size_t size) {
diff --git a/common/system.cpp b/common/system.cpp
index 1f2f8cc6d5..fae7a3ef34 100644
--- a/common/system.cpp
+++ b/common/system.cpp
@@ -20,34 +20,71 @@
*
*/
-// Disable symbol overrides so that we can use system headers.
-// FIXME: Necessary for the PS2 port, should get rid of this eventually.
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#define FORBIDDEN_SYMBOL_EXCEPTION_exit
+#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
+#define FORBIDDEN_SYMBOL_EXCEPTION_fputs
+#define FORBIDDEN_SYMBOL_EXCEPTION_fflush
+#define FORBIDDEN_SYMBOL_EXCEPTION_stdout
+#define FORBIDDEN_SYMBOL_EXCEPTION_stderr
#include "common/system.h"
+#include "common/events.h"
+#include "common/fs.h"
+#include "common/savefile.h"
#include "common/str.h"
+#include "common/textconsole.h"
-#ifdef __PLAYSTATION2__
- // for those replaced fopen/fread/etc functions
- #include "backends/platform/ps2/fileio.h"
-
- #define fputs(str, file) ps2_fputs(str, file)
- #define fflush(a) ps2_fflush(a)
-#endif
-
-#ifdef __DS__
- #include "backends/fs/ds/ds-fs.h"
-
- #define fputs(str, file) DS::std_fwrite(str, strlen(str), 1, file)
- #define fflush(file) DS::std_fflush(file)
-#endif
+#include "backends/audiocd/default/default-audiocd.h"
+#include "backends/fs/fs-factory.h"
+#include "backends/timer/default/default-timer.h"
OSystem *g_system = 0;
OSystem::OSystem() {
+ _audiocdManager = 0;
+ _eventManager = 0;
+ _timerManager = 0;
+ _savefileManager = 0;
+ _fsFactory = 0;
}
OSystem::~OSystem() {
+ delete _audiocdManager;
+ _audiocdManager = 0;
+
+ delete _eventManager;
+ _eventManager = 0;
+
+ delete _timerManager;
+ _timerManager = 0;
+
+ delete _savefileManager;
+ _savefileManager = 0;
+
+ delete _fsFactory;
+ _fsFactory = 0;
+}
+
+void OSystem::initBackend() {
+ // Verify all managers has been set
+ if (!_audiocdManager)
+ error("Backend failed to instantiate audio CD manager");
+ if (!_eventManager)
+ error("Backend failed to instantiate event manager");
+ if (!_timerManager)
+ error("Backend failed to instantiate timer manager");
+
+ // TODO: We currently don't check _savefileManager, because at least
+ // on the Nintendo DS, it is possible that none is set. That should
+ // probably be treated as "saving is not possible". Or else the NDS
+ // port needs to be changed to always set a _savefileManager
+// if (!_savefileManager)
+// error("Backend failed to instantiate savefile manager");
+
+ // TODO: We currently don't check _fsFactory because not all ports
+ // set it.
+// if (!_fsFactory)
+// error("Backend failed to instantiate fs factory");
}
bool OSystem::setGraphicsMode(const char *name) {
@@ -76,16 +113,41 @@ void OSystem::fatalError() {
exit(1);
}
+FilesystemFactory *OSystem::getFilesystemFactory() {
+ assert(_fsFactory);
+ return _fsFactory;
+}
+
+Common::SeekableReadStream *OSystem::createConfigReadStream() {
+ Common::FSNode file(getDefaultConfigFileName());
+ return file.createReadStream();
+}
+
+Common::WriteStream *OSystem::createConfigWriteStream() {
+#ifdef __DC__
+ return 0;
+#else
+ Common::FSNode file(getDefaultConfigFileName());
+ return file.createWriteStream();
+#endif
+}
+
+Common::String OSystem::getDefaultConfigFileName() {
+ return "scummvm.ini";
+}
+
void OSystem::logMessage(LogMessageType::Type type, const char *message) {
+#if !defined(__PLAYSTATION2__) && !defined(__DS__)
FILE *output = 0;
- if (type == LogMessageType::kDebug)
+ if (type == LogMessageType::kInfo || type == LogMessageType::kDebug)
output = stdout;
else
output = stderr;
fputs(message, output);
fflush(output);
+#endif
}
Common::String OSystem::getSystemLanguage() const {
diff --git a/common/system.h b/common/system.h
index b584739b77..d26bc593aa 100644
--- a/common/system.h
+++ b/common/system.h
@@ -73,6 +73,7 @@ struct TimeDate {
namespace LogMessageType {
enum Type {
+ kInfo,
kError,
kWarning,
kDebug
@@ -95,6 +96,72 @@ protected:
OSystem();
virtual ~OSystem();
+protected:
+ /**
+ * @name Module slots
+ *
+ * For backend authors only, the following pointers (= "slots) to various
+ * subsystem managers / factories / etc. can and should be set to
+ * a suitable instance of the respective type.
+ *
+ * For some of the slots, a default instance is set if your backend
+ * does not do so. For details, please look at the documentation of
+ * each slot.
+ *
+ * A backend may setup slot values in its initBackend() method,
+ * its constructor or somewhere in between. But it must a slot's value
+ * no later than in its initBackend() implementation, because
+ * OSystem::initBackend() will create any default instances if
+ * none has been set yet (and for other slots, will verify that
+ * one has been set; if not, an error may be generated).
+ */
+ //@{
+
+ /**
+ * No default value is provided for _audiocdManager by OSystem.
+ * However, BaseBackend::initBackend() does set a default value
+ * if none has been set before.
+ *
+ * @note _audiocdManager is deleted by the OSystem destructor.
+ */
+ AudioCDManager *_audiocdManager;
+
+ /**
+ * No default value is provided for _eventManager by OSystem.
+ * However, BaseBackend::initBackend() does set a default value
+ * if none has been set before.
+ *
+ * @note _eventManager is deleted by the OSystem destructor.
+ */
+ Common::EventManager *_eventManager;
+
+ /**
+ * No default value is provided for _timerManager by OSystem.
+ *
+ * @note _timerManager is deleted by the OSystem destructor.
+ */
+ Common::TimerManager *_timerManager;
+
+ /**
+ * No default value is provided for _savefileManager by OSystem.
+ *
+ * @note _savefileManager is deleted by the OSystem destructor.
+ */
+ Common::SaveFileManager *_savefileManager;
+
+ /**
+ * No default value is provided for _fsFactory by OSystem.
+ *
+ * Note that _fsFactory is typically required very early on,
+ * so it usually should be set in the backends constructor or shortly
+ * thereafter, and before initBackend() is called.
+ *
+ * @note _fsFactory is deleted by the OSystem destructor.
+ */
+ FilesystemFactory *_fsFactory;
+
+ //@}
+
public:
/**
@@ -105,7 +172,7 @@ public:
* parent class. They should do so near the end of their own
* implementation.
*/
- virtual void initBackend() { }
+ virtual void initBackend();
/**
* Allows the backend to perform engine specific init.
@@ -128,11 +195,19 @@ public:
* - fullscreen mode
* - aspect ration correction
* - a virtual keyboard for text entry (on PDAs)
+ *
+ * One has to distinguish between the *availability* of a feature,
+ * which can be checked using hasFeature(), and its *state*.
+ * For example, the SDL backend *has* the kFeatureFullscreenMode,
+ * so hasFeature returns true for it. On the other hand,
+ * fullscreen mode may be active or not; this can be determined
+ * by checking the state via getFeatureState(). Finally, to
+ * switch between fullscreen and windowed mode, use setFeatureState().
*/
enum Feature {
/**
- * If your backend supports both a windowed and a fullscreen mode,
- * then this feature flag can be used to switch between the two.
+ * If supported, this feature flag can be used to switch between
+ * windowed and fullscreen mode.
*/
kFeatureFullscreenMode,
@@ -144,10 +219,10 @@ public:
* pixels). When the backend support this, then games running at
* 320x200 pixels should be scaled up to 320x240 pixels. For all other
* resolutions, ignore this feature flag.
- * @note You can find utility functions in common/scaler.h which can
- * be used to implement aspect ratio correction. In particular,
+ * @note Backend implementors can find utility functions in common/scaler.h
+ * which can be used to implement aspect ratio correction. In
* stretch200To240() can stretch a rect, including (very fast)
- * interpolation, and works in-place.
+ * particular, interpolation, and works in-place.
*/
kFeatureAspectRatioCorrection,
@@ -159,43 +234,58 @@ public:
kFeatureVirtualKeyboard,
/**
- * This flag determines whether or not the cursor can have its own palette.
+ * Backends supporting this feature allow specifying a custom palette
+ * for the cursor. The custom palette is used if the feature state
+ * is set to true by the client code via setFeatureState().
+ *
* It is currently used only by some Macintosh versions of Humongous
- * Entertainment games. If the backend doesn't implement this feature then
- * the engine switches to b/w versions of cursors.
+ * Entertainment games. If the backend doesn't implement this feature
+ * then the engine switches to b/w versions of cursors.
* The GUI also relies on this feature for mouse cursors.
- *
- * To enable the cursor palette call "disableCursorPalette" with false.
- * @see disableCursorPalette
*/
- kFeatureCursorHasPalette,
+ kFeatureCursorPalette,
/**
- * Set to true if the overlay pixel format has an alpha channel.
- * This should only be set if it offers at least 3-4 bits of accuracy,
- * as opposed to a single alpha bit.
+ * A backend have this feature if its overlay pixel format has an alpha
+ * channel which offers at least 3-4 bits of accuracy (as opposed to
+ * just a single alpha bit).
+ *
+ * This feature has no associated state.
*/
kFeatureOverlaySupportsAlpha,
/**
- * Set to true to iconify the window.
+ * Client code can set the state of this feature to true in order to
+ * iconify the application window.
*/
kFeatureIconifyWindow,
/**
- * This feature, set to true, is a hint toward the backend to disable all
- * key filtering/mapping, in cases where it would be beneficial to do so.
- * As an example case, this is used in the agi engine's predictive dialog.
+ * Setting the state of this feature to true tells the backend to disable
+ * all key filtering/mapping, in cases where it would be beneficial to do so.
+ * As an example case, this is used in the AGI engine's predictive dialog.
* When the dialog is displayed this feature is set so that backends with
* phone-like keypad temporarily unmap all user actions which leads to
* comfortable word entry. Conversely, when the dialog exits the feature
* is set to false.
+ *
+ * TODO: The word 'beneficial' above is very unclear. Beneficial to
+ * whom and for what??? Just giving an example is not enough.
+ *
* TODO: Fingolfin suggests that the way the feature is used can be
* generalized in this sense: Have a keyboard mapping feature, which the
* engine queries for to assign keys to actions ("Here's my default key
* map for these actions, what do you want them set to?").
*/
- kFeatureDisableKeyFiltering
+ kFeatureDisableKeyFiltering,
+
+ /**
+ * The presence of this feature indicates whether the displayLogFile()
+ * call is supported.
+ *
+ * This feature has no associated state.
+ */
+ kFeatureDisplayLogFile
};
/**
@@ -367,7 +457,7 @@ public:
* reset the scale to x1 so the screen will not be too big when starting
* the game.
*/
- virtual void resetGraphicsScale() = 0;
+ virtual void resetGraphicsScale() {}
#ifdef USE_RGB_COLOR
/**
@@ -770,25 +860,13 @@ public:
* The palette entries from 'start' till (start+num-1) will be replaced - so
* a full palette update is accomplished via start=0, num=256.
*
- * Backends which implement it should have kFeatureCursorHasPalette flag set
+ * Backends which implement it should have kFeatureCursorPalette flag set
*
* @see setPalette
- * @see kFeatureCursorHasPalette
+ * @see kFeatureCursorPalette
*/
virtual void setCursorPalette(const byte *colors, uint start, uint num) {}
- /**
- * Disable or enable cursor palette.
- *
- * Backends which implement it should have kFeatureCursorHasPalette flag set
- *
- * @param disable True to disable, false to enable.
- *
- * @see setPalette
- * @see kFeatureCursorHasPalette
- */
- virtual void disableCursorPalette(bool disable) {}
-
//@}
@@ -813,13 +891,17 @@ public:
* Return the timer manager singleton. For more information, refer
* to the TimerManager documentation.
*/
- virtual Common::TimerManager *getTimerManager() = 0;
+ inline Common::TimerManager *getTimerManager() {
+ return _timerManager;
+ }
/**
* Return the event manager singleton. For more information, refer
* to the EventManager documentation.
*/
- virtual Common::EventManager *getEventManager() = 0;
+ inline Common::EventManager *getEventManager() {
+ return _eventManager;
+ }
/**
* Register hardware keys with keymapper
@@ -909,7 +991,9 @@ public:
* Return the audio cd manager. For more information, refer to the
* AudioCDManager documentation.
*/
- virtual AudioCDManager *getAudioCDManager() = 0;
+ inline AudioCDManager *getAudioCDManager() {
+ return _audiocdManager;
+ }
//@}
@@ -943,7 +1027,8 @@ public:
* rectangle over the regular screen content; or in a message box beneath
* it; etc.).
*
- * Currently, only pure ASCII messages can be expected to show correctly.
+ * The message is expected to be provided in the current TranslationManager
+ * charset.
*
* @note There is a default implementation in BaseBackend which uses a
* TimedMessageDialog to display the message. Hence implementing
@@ -958,14 +1043,16 @@ public:
* and other modifiable persistent game data. For more information,
* refer to the SaveFileManager documentation.
*/
- virtual Common::SaveFileManager *getSavefileManager() = 0;
+ inline Common::SaveFileManager *getSavefileManager() {
+ return _savefileManager;
+ }
/**
* Returns the FilesystemFactory object, depending on the current architecture.
*
* @return the FSNode factory for the current architecture
*/
- virtual FilesystemFactory *getFilesystemFactory() = 0;
+ virtual FilesystemFactory *getFilesystemFactory();
/**
* Add system specific Common::Archive objects to the given SearchSet.
@@ -984,7 +1071,7 @@ public:
* ReadStream instance. It is the callers responsiblity to delete
* the stream after use.
*/
- virtual Common::SeekableReadStream *createConfigReadStream() = 0;
+ virtual Common::SeekableReadStream *createConfigReadStream();
/**
* Open the default config file for writing, by returning a suitable
@@ -993,7 +1080,14 @@ public:
*
* May return 0 to indicate that writing to config file is not possible.
*/
- virtual Common::WriteStream *createConfigWriteStream() = 0;
+ virtual Common::WriteStream *createConfigWriteStream();
+
+ /**
+ * Get the default file name (or even path) where the user configuration
+ * of ScummVM will be saved.
+ * Note that not all ports may use this.
+ */
+ virtual Common::String getDefaultConfigFileName();
/**
* Logs a given message.
@@ -1010,6 +1104,33 @@ public:
virtual void logMessage(LogMessageType::Type type, const char *message);
/**
+ * Open the log file in a way that allows the user to review it,
+ * and possibly email it (or parts of it) to the ScummVM team,
+ * e.g. as part of a bug report.
+ *
+ * On a desktop operating system, this would typically launch
+ * some kind of (external) text editor / viewer.
+ * On a phone, it might also cause a context switch to another
+ * application. Finally, on some ports, it might not be supported
+ * at all, and so do nothing.
+ *
+ * The kFeatureDisplayLogFile feature flag can be used to
+ * test whether this call has been implemented by the active
+ * backend.
+ *
+ * @return true if all seems to have gone fine, false if an error occurred
+ *
+ * @note An error could mean that the log file did not exist,
+ * or the editor could not launch. However, a return value of true does
+ * not guarantee that the user actually will see the log file.
+ *
+ * @note It is up to the backend to ensure that the system is in a state
+ * that allows the user to actually see the displayed log files. This
+ * might for example require leaving fullscreen mode.
+ */
+ virtual bool displayLogFile() { return false; }
+
+ /**
* Returns the locale of the system.
*
* This returns the currently set up locale of the system, on which
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp
index 9bd052fb3d..5217c4e82c 100644
--- a/common/xmlparser.cpp
+++ b/common/xmlparser.cpp
@@ -22,9 +22,7 @@
// FIXME: Avoid using fprintf
#define FORBIDDEN_SYMBOL_EXCEPTION_fprintf
-
-// FIXME: Avoid using vfprintf
-#define FORBIDDEN_SYMBOL_EXCEPTION_vfprintf
+#define FORBIDDEN_SYMBOL_EXCEPTION_stderr
#include "common/xmlparser.h"
@@ -83,7 +81,7 @@ void XMLParser::close() {
_stream = 0;
}
-bool XMLParser::parserError(const char *errorString, ...) {
+bool XMLParser::parserError(const Common::String &errStr) {
_state = kParserError;
const int startPosition = _stream->pos();
@@ -134,12 +132,7 @@ bool XMLParser::parserError(const char *errorString, ...) {
fprintf(stderr, "%c", _stream->readByte());
fprintf(stderr, "\n\nParser error: ");
-
- va_list args;
- va_start(args, errorString);
- vfprintf(stderr, errorString, args);
- va_end(args);
-
+ fprintf(stderr, "%s", errStr.c_str());
fprintf(stderr, "\n\n");
return false;
@@ -181,16 +174,16 @@ bool XMLParser::parseActiveKey(bool closed) {
for (List<XMLKeyLayout::XMLKeyProperty>::const_iterator i = key->layout->properties.begin(); i != key->layout->properties.end(); ++i) {
if (i->required && !localMap.contains(i->name))
- return parserError("Missing required property '%s' inside key '%s'", i->name.c_str(), key->name.c_str());
+ return parserError("Missing required property '" + i->name + "' inside key '" + key->name + "'");
else if (localMap.contains(i->name))
keyCount--;
}
if (keyCount > 0)
- return parserError("Unhandled property inside key '%s'.", key->name.c_str());
+ return parserError("Unhandled property inside key '" + key->name + "'.");
} else {
- return parserError("Unexpected key in the active scope ('%s').", key->name.c_str());
+ return parserError("Unexpected key in the active scope ('" + key->name + "').");
}
// check if any of the parents must be ignored.
@@ -205,7 +198,7 @@ bool XMLParser::parseActiveKey(bool closed) {
// when keyCallback() fails, a parserError() must be set.
// We set it manually in that case.
if (_state != kParserError)
- parserError("Unhandled exception when parsing '%s' key.", key->name.c_str());
+ parserError("Unhandled exception when parsing '" + key->name + "' key.");
return false;
}
@@ -395,7 +388,7 @@ bool XMLParser::parse() {
case kParserNeedPropertyName:
if (activeClosure) {
if (!closeKey()) {
- parserError("Missing data when closing key '%s'.", _activeKey.top()->name.c_str());
+ parserError("Missing data when closing key '" + _activeKey.top()->name + "'.");
break;
}
diff --git a/common/xmlparser.h b/common/xmlparser.h
index 84fca294a0..7923e43a37 100644
--- a/common/xmlparser.h
+++ b/common/xmlparser.h
@@ -274,7 +274,7 @@ protected:
* Parser error always returns "false" so we can pass the return value
* directly and break down the parsing.
*/
- bool parserError(const char *errorString, ...) GCC_PRINTF(2, 3);
+ bool parserError(const Common::String &errStr);
/**
* Skips spaces/whitelines etc.