aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base/main.cpp2
-rw-r--r--common/archive.cpp4
-rw-r--r--common/archive.h2
-rw-r--r--common/events.h3
-rw-r--r--engines/agi/agi.cpp1
-rw-r--r--engines/agi/preagi_common.cpp2
-rw-r--r--engines/agi/preagi_mickey.cpp1
-rw-r--r--engines/agi/preagi_troll.cpp2
-rw-r--r--engines/agi/preagi_winnie.cpp1
-rw-r--r--engines/agos/animation.cpp1
-rw-r--r--engines/agos/detection.cpp1
-rw-r--r--engines/cine/cine.cpp1
-rw-r--r--engines/cine/detection.cpp1
-rw-r--r--engines/cine/main_loop.cpp1
-rw-r--r--engines/cine/various.cpp1
-rw-r--r--engines/dialogs.cpp2
-rw-r--r--engines/engine.cpp14
-rw-r--r--engines/engine.h27
-rw-r--r--engines/game.cpp19
-rw-r--r--engines/game.h25
-rw-r--r--engines/gob/gob.cpp1
-rw-r--r--engines/gob/util.cpp2
-rw-r--r--engines/metaengine.h4
-rw-r--r--engines/parallaction/detection.cpp1
-rw-r--r--engines/parallaction/objects.h2
-rw-r--r--engines/saga/detection.cpp1
-rw-r--r--engines/touche/detection.cpp1
-rw-r--r--gui/dialog.h1
-rw-r--r--gui/eval.cpp333
-rw-r--r--gui/eval.h125
-rw-r--r--gui/newgui.cpp2
-rw-r--r--gui/theme-config.cpp813
-rw-r--r--gui/themes/scummtheme.py6
33 files changed, 1359 insertions, 44 deletions
diff --git a/base/main.cpp b/base/main.cpp
index 93e2c71c8f..d571363f4a 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -44,8 +44,6 @@
#include "common/system.h"
#include "gui/newgui.h"
#include "gui/message.h"
-#include "gui/ThemeEngine.h"
-#include "gui/ThemeParser.h"
#if defined(_WIN32_WCE)
#include "backends/platform/wince/CELauncherDialog.h"
diff --git a/common/archive.cpp b/common/archive.cpp
index 40c2f01ee6..96ead55abd 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -156,13 +156,13 @@ SeekableReadStream *FSDirectory::openFile(const String &name) {
return stream;
}
-FSDirectory *FSDirectory::getSubDirectory(const String &name) {
+FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth) {
if (name.empty() || !_node.isDirectory()) {
return 0;
}
FSNode node = lookupCache(_subDirCache, name);
- return new FSDirectory(node);
+ return new FSDirectory(node, depth);
}
void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) {
diff --git a/common/archive.h b/common/archive.h
index 2fc86b1b57..c8d22124fd 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -164,7 +164,7 @@ public:
* Create a new FSDirectory pointing to a sub directory of the instance.
* @return a new FSDirectory instance
*/
- FSDirectory *getSubDirectory(const String &name);
+ FSDirectory *getSubDirectory(const String &name, int depth = 1);
virtual bool hasFile(const String &name);
virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern);
diff --git a/common/events.h b/common/events.h
index f01282765a..dd45ca18c1 100644
--- a/common/events.h
+++ b/common/events.h
@@ -44,6 +44,7 @@ namespace Common {
* indicates which button was pressed.
*/
enum EventType {
+ EVENT_INVALID = 0,
/** A key was pressed, details in Event::kbd. */
EVENT_KEYDOWN = 1,
/** A key was released, details in Event::kbd. */
@@ -121,6 +122,8 @@ struct Event {
* screen area as defined by the most recent call to initSize().
*/
Common::Point mouse;
+
+ Event() : type(EVENT_INVALID), synthetic(false) {}
};
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index a17bdc50cf..3c1ec5efde 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -25,6 +25,7 @@
#include "common/md5.h"
+#include "common/events.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/config-manager.h"
diff --git a/engines/agi/preagi_common.cpp b/engines/agi/preagi_common.cpp
index ce085ad165..ad26879ca1 100644
--- a/engines/agi/preagi_common.cpp
+++ b/engines/agi/preagi_common.cpp
@@ -30,6 +30,8 @@
#include "agi/preagi_common.h"
+#include "common/events.h"
+
namespace Agi {
// Screen functions
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp
index db2e01a04b..e942a19d3f 100644
--- a/engines/agi/preagi_mickey.cpp
+++ b/engines/agi/preagi_mickey.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "common/events.h"
#include "common/savefile.h"
#include "common/stream.h"
diff --git a/engines/agi/preagi_troll.cpp b/engines/agi/preagi_troll.cpp
index db663797f9..1806c35662 100644
--- a/engines/agi/preagi_troll.cpp
+++ b/engines/agi/preagi_troll.cpp
@@ -28,6 +28,8 @@
#include "agi/preagi_troll.h"
#include "agi/graphics.h"
+#include "common/events.h"
+
#include "graphics/cursorman.h"
namespace Agi {
diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp
index c58d7518ac..38e711c330 100644
--- a/engines/agi/preagi_winnie.cpp
+++ b/engines/agi/preagi_winnie.cpp
@@ -29,6 +29,7 @@
#include "graphics/cursorman.h"
+#include "common/events.h"
#include "common/savefile.h"
#include "common/stream.h"
diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp
index 9f8b3f8643..c39e476d5e 100644
--- a/engines/agos/animation.cpp
+++ b/engines/agos/animation.cpp
@@ -26,6 +26,7 @@
#include "common/endian.h"
+#include "common/events.h"
#include "common/system.h"
#include "graphics/cursorman.h"
diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp
index 12f281d0dc..6cc4d16044 100644
--- a/engines/agos/detection.cpp
+++ b/engines/agos/detection.cpp
@@ -28,6 +28,7 @@
#include "common/advancedDetector.h"
#include "common/config-manager.h"
#include "common/savefile.h"
+#include "common/system.h"
#include "agos/agos.h"
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index 2c0fdc7d88..d12ba61480 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "common/events.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/config-manager.h"
diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp
index 91ef964a0b..97299d266c 100644
--- a/engines/cine/detection.cpp
+++ b/engines/cine/detection.cpp
@@ -28,6 +28,7 @@
#include "base/plugins.h"
#include "common/advancedDetector.h"
+#include "common/system.h"
#include "cine/cine.h"
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index abebe90299..e88340479f 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
+#include "common/events.h"
#include "common/system.h"
#include "cine/main_loop.h"
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 92fd35d865..1bd3d3967c 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -25,6 +25,7 @@
#include "common/endian.h"
+#include "common/events.h"
#include "common/savefile.h"
#include "cine/cine.h"
diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp
index b069e198a9..97c55d4a1f 100644
--- a/engines/dialogs.cpp
+++ b/engines/dialogs.cpp
@@ -104,7 +104,7 @@ MainMenuDialog::MainMenuDialog(Engine *engine)
new GUI::ButtonWidget(this, "GlobalMenu.About", "About", kAboutCmd, 'A');
_rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", "Return to Launcher", kRTLCmd, 'R');
- _rtlButton->setEnabled(_engine->hasFeature(MetaEngine::kSupportsRTL));
+ _rtlButton->setEnabled(_engine->hasFeature(Engine::kSupportsRTL));
new GUI::ButtonWidget(this, "GlobalMenu.Quit", "Quit", kQuitCmd, 'Q');
diff --git a/engines/engine.cpp b/engines/engine.cpp
index c99187d2f2..a17f1e5153 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -31,6 +31,7 @@
#include "engines/engine.h"
#include "common/config-manager.h"
+#include "common/events.h"
#include "common/file.h"
#include "common/timer.h"
#include "common/savefile.h"
@@ -250,13 +251,20 @@ void Engine::quitGame() {
_eventMan->pushEvent(event);
}
-bool Engine::hasFeature(MetaEngine::MetaEngineFeature f) {
- // TODO: In each engine, keep a ref to the corresponding MetaEngine?
+bool Engine::shouldQuit() const {
+ return (_eventMan->shouldQuit() || _eventMan->shouldRTL());
+}
+
+bool Engine::hasFeature(EngineFeature f) {
+ // TODO: Get rid of this hack!!!
+ if (f != kSupportsRTL)
+ return false;
+
const EnginePlugin *plugin = 0;
Common::String gameid = ConfMan.get("gameid");
gameid.toLowercase();
EngineMan.findGame(gameid, &plugin);
assert(plugin);
- return ( (*plugin)->hasFeature(f) );
+ return ( (*plugin)->hasFeature(MetaEngine::kSupportsRTL) );
}
diff --git a/engines/engine.h b/engines/engine.h
index 2bc44ab415..69caafac49 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -26,12 +26,9 @@
#define ENGINES_ENGINE_H
#include "common/scummsys.h"
-#include "common/events.h"
#include "common/fs.h"
#include "common/str.h"
-#include "engines/metaengine.h"
-
class OSystem;
namespace Audio {
@@ -73,7 +70,7 @@ protected:
const Common::String _targetName; // target name for saves
- const Common::FSNode _gameDataDir;
+ const Common::FSNode _gameDataDir; // FIXME: Get rid of this
private:
/**
@@ -151,7 +148,7 @@ public:
* Return whether the ENGINE should quit respectively should return to the
* launcher.
*/
- bool shouldQuit() const { return (_eventMan->shouldQuit() || _eventMan->shouldRTL()); }
+ bool shouldQuit() const;
/**
* Pause or resume the engine. This should stop/resume any audio playback
@@ -176,14 +173,24 @@ public:
*/
void openMainMenuDialog();
+
+ /**
+ * A feature in this context means an ability of the engine which can be
+ * either available or not.
+ */
+ enum EngineFeature {
+ /**
+ * 'Return to launcher' feature is supported, i.e., EVENT_RTL is handled.
+ */
+ kSupportsRTL
+ };
+
/**
- * Determine whether the engine supports the specified MetaEngine feature.
+ * Determine whether the engine supports the specified feature.
*
- * FIXME: This should not call through to the MetaEngine, but rather should support
- * its own list of features. In particular, kSupportsRTL should be an EngineFeature,
- * not a MetaEngineFeature.
+ * @todo Let this return false by default, or even turn it into a pure virtual method.
*/
- bool hasFeature(MetaEngine::MetaEngineFeature f);
+ bool hasFeature(EngineFeature f);
public:
diff --git a/engines/game.cpp b/engines/game.cpp
index b3cb140e0a..5011685412 100644
--- a/engines/game.cpp
+++ b/engines/game.cpp
@@ -38,6 +38,25 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla
return 0;
}
+GameDescriptor::GameDescriptor() {
+ setVal("gameid", "");
+ setVal("description", "");
+}
+
+GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd) {
+ setVal("gameid", pgd.gameid);
+ setVal("description", pgd.description);
+}
+
+GameDescriptor::GameDescriptor(const Common::String &g, const Common::String &d, Common::Language l, Common::Platform p) {
+ setVal("gameid", g);
+ setVal("description", d);
+ if (l != Common::UNK_LANG)
+ setVal("language", Common::getLanguageCode(l));
+ if (p != Common::kPlatformUnknown)
+ setVal("platform", Common::getPlatformCode(p));
+}
+
void GameDescriptor::updateDesc(const char *extra) {
// TODO: The format used here (LANG/PLATFORM/EXTRA) is not set in stone.
// We may want to change the order (PLATFORM/EXTRA/LANG, anybody?), or
diff --git a/engines/game.h b/engines/game.h
index a1eed7acd9..a07a71b7e6 100644
--- a/engines/game.h
+++ b/engines/game.h
@@ -62,25 +62,12 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla
*/
class GameDescriptor : public Common::StringMap {
public:
- GameDescriptor() {
- setVal("gameid", "");
- setVal("description", "");
- }
-
- GameDescriptor(const PlainGameDescriptor &pgd) {
- setVal("gameid", pgd.gameid);
- setVal("description", pgd.description);
- }
-
- GameDescriptor(const Common::String &g, const Common::String &d, Common::Language l = Common::UNK_LANG,
- Common::Platform p = Common::kPlatformUnknown) {
- setVal("gameid", g);
- setVal("description", d);
- if (l != Common::UNK_LANG)
- setVal("language", Common::getLanguageCode(l));
- if (p != Common::kPlatformUnknown)
- setVal("platform", Common::getPlatformCode(p));
- }
+ GameDescriptor();
+ GameDescriptor(const PlainGameDescriptor &pgd);
+ GameDescriptor(const Common::String &gameid,
+ const Common::String &description,
+ Common::Language language = Common::UNK_LANG,
+ Common::Platform platform = Common::kPlatformUnknown);
/**
* Update the description string by appending (LANG/PLATFORM/EXTRA) to it.
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 7e364e891d..e1543e9277 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -24,6 +24,7 @@
*/
#include "common/endian.h"
+#include "common/events.h"
#include "base/plugins.h"
#include "common/config-manager.h"
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index c3c874b2fb..f04818d4a7 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -33,6 +33,8 @@
#include "gob/video.h"
#include "gob/sound/sound.h"
+#include "common/events.h"
+
namespace Gob {
Util::Util(GobEngine *vm) : _vm(vm) {
diff --git a/engines/metaengine.h b/engines/metaengine.h
index 542cee683b..194acc94d7 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -26,7 +26,6 @@
#define ENGINES_METAENGINE_H
#include "common/scummsys.h"
-#include "common/str.h"
#include "common/error.h"
#include "engines/game.h"
@@ -37,6 +36,7 @@ class OSystem;
namespace Common {
class FSList;
+ class String;
}
/**
@@ -134,7 +134,7 @@ public:
*/
enum MetaEngineFeature {
/**
- * 'Return to launcher' feature is supported, i.e., EVENT_RTL is handled-
+ * 'Return to launcher' feature is supported, i.e., EVENT_RTL is handled.
*/
kSupportsRTL,
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp
index d2444c642e..cbaa994e47 100644
--- a/engines/parallaction/detection.cpp
+++ b/engines/parallaction/detection.cpp
@@ -27,6 +27,7 @@
#include "common/config-manager.h"
#include "common/advancedDetector.h"
+#include "common/system.h"
#include "parallaction/parallaction.h"
diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h
index 431d12504e..eee69383b6 100644
--- a/engines/parallaction/objects.h
+++ b/engines/parallaction/objects.h
@@ -100,7 +100,7 @@ enum ZoneFlags {
enum CommandFlags {
- kFlagsAll = 0x7FFFFFFFU,
+ kFlagsAll = 0xFFFFFFFFU,
kFlagsVisited = 1,
kFlagsExit = 0x10000000,
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index 4a10261d9b..57979ab008 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -31,6 +31,7 @@
#include "common/config-manager.h"
#include "common/advancedDetector.h"
+#include "common/system.h"
#include "saga/displayinfo.h"
#include "saga/rscfile.h"
diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp
index bbc605ba46..72676fd930 100644
--- a/engines/touche/detection.cpp
+++ b/engines/touche/detection.cpp
@@ -26,6 +26,7 @@
#include "common/config-manager.h"
#include "common/advancedDetector.h"
#include "common/savefile.h"
+#include "common/system.h"
#include "base/plugins.h"
diff --git a/gui/dialog.h b/gui/dialog.h
index bc5ce6b6e0..71edb63ee3 100644
--- a/gui/dialog.h
+++ b/gui/dialog.h
@@ -42,7 +42,6 @@ enum {
};
class Dialog : public GuiObject {
- // TANOKU-TODO: remove newgui from here
friend class NewGui;
protected:
Widget *_mouseWidget;
diff --git a/gui/eval.cpp b/gui/eval.cpp
new file mode 100644
index 0000000000..716006c108
--- /dev/null
+++ b/gui/eval.cpp
@@ -0,0 +1,333 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/system.h"
+#include "gui/eval.h"
+#include "gui/widget.h"
+#include "gui/newgui.h"
+
+#include "graphics/scaler.h"
+
+namespace GUI {
+
+static bool isdelim(char c) {
+ return strchr(" ;,+-<>/*%^=()", c) != 0 || c == 9 || c == '\n' || !c;
+}
+
+Eval::Eval() {
+ loadConstants();
+}
+
+Eval::~Eval() {
+ _vars.clear();
+ _aliases.clear();
+}
+
+int Eval::eval(const String &input, const String &section, const String &name, int startpos) {
+ int result;
+
+ debug(5, "%s=%s", name.c_str(), input.c_str());
+
+ strncpy(_input, input.c_str(), 256);
+ _section = section;
+ _name = name;
+ _startpos = startpos;
+
+ _pos = 0;
+
+ getToken();
+
+ if (_tokenType == tString)
+ return EVAL_STRING_VAR;
+
+ if (!*_token)
+ exprError(eBadExpr);
+
+ level2(&result);
+
+ debug(5, "Result: %d", result);
+
+ return result;
+}
+
+void Eval::level2(int *result) {
+ char op;
+ int hold;
+
+ level3(result);
+
+ while ((op = *_token) == '+' || op == '-') {
+ getToken();
+ level3(&hold);
+ arith(op, result, &hold);
+ }
+}
+
+void Eval::level3(int *result) {
+ char op;
+ int hold;
+
+ level4(result);
+
+ while ((op = *_token) == '*' || op == '/' || op == '%') {
+ getToken();
+ level4(&hold);
+ arith(op, result, &hold);
+ }
+}
+
+void Eval::level4(int *result) {
+ char op;
+
+ op = 0;
+ if ((_tokenType == tDelimiter) && (*_token == '+' || *_token == '-')) {
+ op = *_token;
+ getToken();
+ }
+
+ level5(result);
+
+ if (op)
+ unary(op, result);
+}
+
+void Eval::level5(int *result) {
+ if ((*_token == '(') && (_tokenType == tDelimiter)) {
+ getToken();
+
+ level2(result);
+
+ if (*_token != ')')
+ exprError(eUnclosedBracket);
+ getToken();
+ } else {
+ primitive(result);
+ }
+}
+
+void Eval::primitive(int *result) {
+ if (*_token == ')')
+ exprError(eExtraBracket);
+
+ switch (_tokenType) {
+ case tVariable:
+ *result = getVar_(_token);
+ if (*result == EVAL_UNDEF_VAR)
+ exprError(eUndefVar);
+ getToken();
+ return;
+ case tNumber:
+ *result = atoi(_token);
+ getToken();
+ return;
+ default:
+ exprError(eSyntaxError);
+ }
+}
+
+void Eval::arith(char op, int *r, int *h) {
+ switch (op) {
+ case '-':
+ *r = *r - *h;
+ break;
+ case '+':
+ *r = *r + *h;
+ break;
+ case '*':
+ *r = *r * *h;
+ break;
+ case '/':
+ *r = (*r) / (*h);
+ break;
+ case '%':
+ *r = (*r) % (*h);
+ break;
+ }
+}
+
+void Eval::unary(char op, int *r) {
+ if (op == '-')
+ *r = -(*r);
+}
+
+void Eval::getToken() {
+ char *temp;
+
+ _tokenType = tNone;
+ temp = _token;
+
+ if (_input[_pos] == 0) {
+ *_token = 0;
+ _tokenType = tDelimiter;
+ return;
+ }
+ while (isspace(_input[_pos]))
+ _pos++;
+
+ if (_input[_pos] == '"') {
+ _pos++;
+ while (_input[_pos] != '"' && _input[_pos] != '\n')
+ *temp++ = _input[_pos++];
+
+ if (_input[_pos] == '\n')
+ exprError(eMissingQuote);
+
+ _pos++;
+ *temp = 0;
+
+ _tokenType = tString;
+ return;
+ }
+
+ if (isdigit(_input[_pos])) {
+ while (!isdelim(_input[_pos]))
+ *temp++ = _input[_pos++];
+ *temp = 0;
+
+ _tokenType = tNumber;
+ return;
+ }
+
+ if (isalpha(_input[_pos])) {
+ while (!isdelim(_input[_pos]))
+ *temp++ = _input[_pos++];
+ *temp = 0;
+ _tokenType = tVariable;
+ return;
+ }
+
+ if (!_tokenType && isdelim(_input[_pos])) {
+ *temp++ = _input[_pos++];
+ *temp = 0;
+ _tokenType = tDelimiter;
+ }
+}
+
+void Eval::exprError(EvalErrors err) {
+ static const char *errors[] = {
+ "Syntax error",
+ "Extra ')'",
+ "Missing ')'",
+ "Bad expression",
+ "Undefined variable",
+ "Missing '\"'"
+ };
+
+ error("%s in section [%s] expression: \"%s\" start is at: %d near token '%s'",
+ errors[err], _section.c_str(), _name.c_str(), _pos + _startpos, _token);
+}
+
+struct BuiltinConsts {
+ const char *name;
+ int value;
+};
+
+static const BuiltinConsts builtinConsts[] = {
+ {"kButtonWidth", GUI::kButtonWidth},
+ {"kButtonHeight", GUI::kButtonHeight},
+ {"kSliderWidth", GUI::kSliderWidth},
+ {"kSliderHeight", GUI::kSliderHeight},
+
+ {"kBigButtonWidth", GUI::kBigButtonWidth},
+ {"kBigButtonHeight", GUI::kBigButtonHeight},
+ {"kBigSliderWidth", GUI::kBigSliderWidth},
+ {"kBigSliderHeight", GUI::kBigSliderHeight},
+
+ {"kNormalWidgetSize", GUI::kNormalWidgetSize},
+ {"kBigWidgetSize", GUI::kBigWidgetSize},
+
+ {"kThumbnailWidth", kThumbnailWidth},
+
+ {"kTextAlignLeft", kTextAlignLeft},
+ {"kTextAlignRight", kTextAlignRight},
+ {"kTextAlignCenter", kTextAlignCenter},
+
+ {"kFontStyleBold", Theme::kFontStyleBold},
+ {"kFontStyleNormal", Theme::kFontStyleNormal},
+ {"kFontStyleItalic", Theme::kFontStyleItalic},
+
+ {"kFontStyleFixedBold", Theme::kFontStyleFixedBold},
+ {"kFontStyleFixedNormal", Theme::kFontStyleFixedNormal},
+ {"kFontStyleFixedItalic", Theme::kFontStyleFixedItalic},
+
+ {"kShadingNone", Theme::kShadingNone},
+ {"kShadingDim", Theme::kShadingDim},
+ {"kShadingLuminance", Theme::kShadingLuminance},
+
+ {"false", 0},
+ {"true", 1},
+ {NULL, 0}
+};
+
+void Eval::loadConstants() {
+ int i;
+
+ for (i = 0; builtinConsts[i].name; i++)
+ _vars[builtinConsts[i].name] = builtinConsts[i].value;
+}
+
+int Eval::getBuiltinVar(const char *s) {
+ if (!strcmp(s, "w"))
+ return g_system->getOverlayWidth();
+
+ if (!strcmp(s, "h"))
+ return g_system->getOverlayHeight();
+
+ return EVAL_UNDEF_VAR;
+}
+
+int Eval::getVar_(const Common::String &s, bool includeAliases) {
+ int val;
+
+ val = getBuiltinVar(s.c_str());
+
+ if (val != EVAL_UNDEF_VAR)
+ return val;
+
+ const Common::String *var = &s;
+ if (includeAliases) {
+ AliasesMap::const_iterator itera = _aliases.find(s);
+ if (itera != _aliases.end())
+ var = &(itera->_value);
+ }
+
+ VariablesMap::const_iterator iterv = _vars.find(*var);
+ if (iterv != _vars.end())
+ return iterv->_value;
+
+ return EVAL_UNDEF_VAR;
+}
+
+void Eval::setVar(const String &section, const String &name, const String &value) {
+ _vars[name.c_str() + 4] = eval(value, section, name, 0);
+}
+
+void Eval::reset() {
+ _vars.clear();
+ _aliases.clear();
+ loadConstants();
+}
+
+} // end of namespace GUI
diff --git a/gui/eval.h b/gui/eval.h
new file mode 100644
index 0000000000..47c8313903
--- /dev/null
+++ b/gui/eval.h
@@ -0,0 +1,125 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GUI_EVAL_H
+#define GUI_EVAL_H
+
+#include "common/str.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+
+namespace GUI {
+
+using Common::String;
+using Common::HashMap;
+
+enum {
+ EVAL_UNDEF_VAR = -13375,
+ EVAL_STRING_VAR = -13376
+};
+
+class Eval {
+public:
+ Eval();
+ ~Eval();
+
+ int eval(const String &input, const String &section, const String &name, int startpos);
+ void setVar(const String &section, const String &name, const String &value);
+
+ void setParent(const String &name);
+
+ void setVar(const String &name, int val) { _vars[name] = val; }
+ void setStringVar(const String &name, const String &val) { _strings[name] = val; }
+ void setAlias(const Common::String &name, const String &val) { _aliases[name] = val; }
+
+ int getVar(const Common::String &s) { return getVar_(s); }
+ int getVar(const Common::String &s, int def) {
+ int val = getVar_(s);
+ return (val == EVAL_UNDEF_VAR) ? def : val;
+ }
+
+ const String &getStringVar(const Common::String &name) { return _strings[name]; }
+
+ uint getNumVars() { return _vars.size(); }
+
+ void reset();
+
+ char *lastToken() { return _token; }
+
+ typedef HashMap<String, int> VariablesMap;
+ typedef HashMap<String, String> AliasesMap;
+ typedef HashMap<String, String> StringsMap;
+
+private:
+ enum TokenTypes {
+ tNone,
+ tDelimiter,
+ tVariable,
+ tNumber,
+ tString
+ };
+
+ enum EvalErrors {
+ eSyntaxError,
+ eExtraBracket,
+ eUnclosedBracket,
+ eBadExpr,
+ eUndefVar,
+ eMissingQuote
+ };
+
+
+ void getToken();
+ void level2(int *);
+ void level3(int *);
+ void level4(int *);
+ void level5(int *);
+ void primitive(int *);
+ void arith(char op, int *r, int *h);
+ void unary(char op, int *r);
+ void exprError(EvalErrors error);
+ int getVar_(const Common::String &s, bool includeAliases = true);
+ int getBuiltinVar(const char *s);
+ void loadConstants();
+
+ char _input[256];
+ String _section;
+ String _name;
+
+ int _startpos;
+
+ TokenTypes _tokenType;
+ int _pos;
+
+ char _token[256];
+
+ AliasesMap _aliases;
+ VariablesMap _vars;
+ StringsMap _strings;
+};
+
+} // end of namespace GUI
+
+#endif
diff --git a/gui/newgui.cpp b/gui/newgui.cpp
index 1fa0038ff2..1520aacaea 100644
--- a/gui/newgui.cpp
+++ b/gui/newgui.cpp
@@ -88,7 +88,7 @@ NewGui::NewGui() : _redrawStatus(kRedrawDisabled),
memset(_cursor, 0xFF, sizeof(_cursor));
- ConfMan.registerDefault("gui_theme", "default");
+ ConfMan.registerDefault("gui_theme", "scummodern.zip");
Common::String themefile(ConfMan.get("gui_theme"));
if (themefile.compareToIgnoreCase("default") == 0)
themefile = "builtin";
diff --git a/gui/theme-config.cpp b/gui/theme-config.cpp
new file mode 100644
index 0000000000..9fc23c5e7d
--- /dev/null
+++ b/gui/theme-config.cpp
@@ -0,0 +1,813 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "gui/theme.h"
+#include "gui/eval.h"
+
+namespace GUI {
+
+const char *Theme::_defaultConfigINI =
+"# Define our classic greenish theme here\n"
+"[320xY]\n"
+"def_widgetSize=kNormalWidgetSize\n"
+"def_buttonWidth=kButtonWidth\n"
+"def_buttonHeight=kButtonHeight\n"
+"def_sliderWidth=kSliderWidth\n"
+"def_sliderHeight=kSliderHeight\n"
+"def_kLineHeight=12\n"
+"def_kFontHeight=10\n"
+"def_insetX=10\n"
+"def_insetY=10\n"
+"def_insetW=(w - 2 * 10)\n"
+"def_insetH=(h - 30)\n"
+"def_gameOptionsLabelWidth=60\n"
+"def_tabPopupsLabelW=100\n"
+"def_aboutXOff=3\n"
+"def_aboutYOff=2\n"
+"def_aboutOuterBorder=10\n"
+"def_scummmainHOffset=8\n"
+"def_scummmainVSpace=5\n"
+"def_scummmainVAddOff=2\n"
+"def_scummmainButtonWidth=90\n"
+"def_scummmainButtonHeight=16\n"
+"def_scummhelpX=5\n"
+"def_scummhelpW=(w - 2 * 5)\n"
+"def_midiControlsSpacing=1\n"
+"def_vcAudioTabIndent=0\n"
+"def_vcAudioTabSpacing=2\n"
+"use=XxY\n"
+"\n"
+"# Override audio tab\n"
+"set_parent=gameoptions\n"
+"vBorder=5\n"
+"\n"
+"# audio tab\n"
+"opYoffset=vBorder\n"
+"useWithPrefix=audioControls globaloptions_\n"
+"useWithPrefix=subtitleControls globaloptions_\n"
+"\n"
+"# volume tab\n"
+"opYoffset=vBorder\n"
+"useWithPrefix=volumeControls globaloptions_\n"
+"\n"
+"# audio tab\n"
+"opYoffset=vBorder\n"
+"gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight + 6)\n"
+"useWithPrefix=audioControls gameoptions_\n"
+"useWithPrefix=subtitleControls gameoptions_\n"
+"\n"
+"# volume tab\n"
+"opYoffset=vBorder\n"
+"gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight + 6)\n"
+"useWithPrefix=volumeControls gameoptions_\n"
+"\n"
+"TabWidget.tabWidth=0\n"
+"TabWidget.tabHeight=16\n"
+"TabWidget.titleVPad=2\n"
+"# Scumm Saveload dialog\n"
+"scummsaveload=8 8 (w - 2 * 8) (h - 16)\n"
+"set_parent=scummsaveload\n"
+"scummsaveload_title=10 2 (parent.w - 2 * 10) kLineHeight\n"
+"scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y)\n"
+"scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 22)) 18\n"
+"scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n"
+"scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h\n"
+"scummsaveload_delete=prev.x2 prev.y prev.w prev.h\n"
+"scummsaveload_extinfo.visible=false\n"
+"\n"
+"# MM NES resolution\n"
+"[256x240]\n"
+"useAsIs=320xY\n"
+"\n"
+"[XxY]\n"
+"def_widgetSize=kBigWidgetSize\n"
+"def_buttonWidth=kBigButtonWidth\n"
+"def_buttonHeight=kBigButtonHeight\n"
+"def_sliderWidth=kBigSliderWidth\n"
+"def_sliderHeight=kBigSliderHeight\n"
+"def_kLineHeight=16\n"
+"def_kFontHeight=14\n"
+"def_insetX=10\n"
+"def_insetY=20\n"
+"def_insetW=(w - 2 * 10)\n"
+"def_insetH=(h - 2 * 40)\n"
+"def_gameOptionsLabelWidth=90\n"
+"def_tabPopupsLabelW=150\n"
+"def_aboutXOff=8\n"
+"def_aboutYOff=5\n"
+"def_aboutOuterBorder=80\n"
+"def_globalmainHOffset=52\n"
+"def_scummmainHOffset=12\n"
+"def_scummmainVSpace=7\n"
+"def_scummmainVAddOff=3\n"
+"def_scummmainButtonWidth=160\n"
+"def_scummmainButtonHeight=28\n"
+"def_scummhelpW=370\n"
+"def_scummhelpX=((w - scummhelpW) / 2)\n"
+"def_midiControlsSpacing=2\n"
+"def_vcAudioTabIndent=10\n"
+"def_vcAudioTabSpacing=4\n"
+"##### Widgets config\n"
+"ListWidget.leftPadding=4\n"
+"ListWidget.rightPadding=0\n"
+"ListWidget.topPadding=2\n"
+"ListWidget.bottomPadding=2\n"
+"ListWidget.hlLeftPadding=2\n"
+"ListWidget.hlRightPadding=1\n"
+"PopUpWidget.leftPadding=4\n"
+"PopUpWidget.rightPadding=0\n"
+"TabWidget.tabWidth=70\n"
+"TabWidget.tabHeight=21\n"
+"TabWidget.titleVPad=2\n"
+"\n"
+"###### chooser\n"
+"opHeight=(h * 7 / 10)\n"
+"useWithPrefix=chooser defaultChooser_\n"
+"\n"
+"##### browser\n"
+"brW=((w * 7) / 8)\n"
+"brH=((h * 9) / 10)\n"
+"browser=((w - brW) / 2) ((h - brH) / 2) brW brH\n"
+"set_parent=browser\n"
+"browser_headline=10 kLineHeight (parent.w - 2 * 10) kLineHeight\n"
+"browser_headline.align=kTextAlignCenter\n"
+"browser_path=10 prev.y2 prev.w prev.h\n"
+"browser_list=10 prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14)\n"
+"browser_up=10 (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n"
+"browser_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n"
+"browser_choose=(prev.x2 + 10) prev.y prev.w prev.h\n"
+"\n"
+"##### launcher\n"
+"hBorder=10\n"
+"launcher_version=hBorder 8 (w - 2 * hBorder) kLineHeight\n"
+"launcher_version.align=kTextAlignCenter\n"
+"top=(h - 8 - buttonHeight)\n"
+"numButtons=4\n"
+"space=8\n"
+"butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons)\n"
+"launcher_quit_button=hBorder top butWidth buttonHeight\n"
+"launcher_about_button=(prev.x2 + space) prev.y prev.w prev.h\n"
+"launcher_options_button=(prev.x2 + space) prev.y prev.w prev.h\n"
+"launcher_start_button=(prev.x2 + space) prev.y prev.w prev.h\n"
+"top=(top - buttonHeight * 2)\n"
+"numButtons=4\n"
+"space=10\n"
+"butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons)\n"
+"launcher_loadGame_button=hBorder top butWidth buttonHeight\n"
+"launcher_addGame_button=(prev.x2 + space) prev.y prev.w prev.h\n"
+"launcher_editGame_button=(prev.x2 + space) prev.y prev.w prev.h\n"
+"launcher_removeGame_button=(prev.x2 + space) prev.y prev.w prev.h\n"
+"launcher_list=hBorder (kLineHeight + 16) (w - 2 * hBorder) (top - kLineHeight - 20)\n"
+"\n"
+"### global options\n"
+"globaloptions=insetX insetY insetW insetH\n"
+"set_parent=globaloptions\n"
+"vBorder=5\n"
+"globaloptions_tabwidget=0 vBorder parent.w (parent.h - buttonHeight - 8 - 2 * vBorder)\n"
+"\n"
+"# graphics tab\n"
+"opYoffset=vBorder\n"
+"opXoffset=0\n"
+"useWithPrefix=graphicsControls globaloptions_\n"
+"\n"
+"# audio tab\n"
+"opYoffset=vBorder\n"
+"useWithPrefix=audioControls globaloptions_\n"
+"useWithPrefix=subtitleControls globaloptions_\n"
+"\n"
+"# volume tab\n"
+"opYoffset=vBorder\n"
+"useWithPrefix=volumeControls globaloptions_\n"
+"\n"
+"# MIDI tab\n"
+"opYoffset=vBorder\n"
+"useWithPrefix=midiControls globaloptions_\n"
+"\n"
+"# paths tab\n"
+"yoffset=vBorder\n"
+"glOff=((buttonHeight - kLineHeight) / 2 + 2)\n"
+"globaloptions_savebutton=10 yoffset (buttonWidth + 5) buttonHeight\n"
+"globaloptions_savepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n"
+"yoffset=(yoffset + buttonHeight + 4)\n"
+"globaloptions_extrabutton=10 yoffset (buttonWidth + 5) buttonHeight\n"
+"globaloptions_extrapath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n"
+"yoffset=(yoffset + buttonHeight + 4)\n"
+"globaloptions_themebutton=10 yoffset (buttonWidth + 5) buttonHeight\n"
+"globaloptions_themepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n"
+"yoffset=(yoffset + buttonHeight + 4)\n"
+"globaloptions_pluginsbutton=10 yoffset (buttonWidth + 5) buttonHeight\n"
+"globaloptions_pluginspath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n"
+"yoffset=(yoffset + buttonHeight + 4)\n"
+"globaloptions_keysbutton=10 yoffset (buttonWidth + 5) buttonHeight\n"
+"\n"
+"# Misc options\n"
+"yoffset=vBorder\n"
+"glOff=((buttonHeight - kLineHeight) / 2 + 2)\n"
+"globaloptions_themebutton2=10 yoffset buttonWidth buttonHeight\n"
+"globaloptions_curtheme=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight\n"
+"yoffset=(yoffset + buttonHeight + 4)\n"
+"globaloptions_autosaveperiod=10 yoffset (parent.w - 10 - 25) (kLineHeight + 2)\n"
+"\n"
+"globaloptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n"
+"globaloptions_ok=(prev.x2 + 10) prev.y prev.w prev.h\n"
+"\n"
+"### game options\n"
+"gameoptions=insetX insetY insetW insetH\n"
+"set_parent=gameoptions\n"
+"vBorder=5\n"
+"gox=5\n"
+"gow=(parent.w - 15)\n"
+"\n"
+"gameoptions_tabwidget=0 vBorder parent.w (parent.h - buttonHeight - 8 - 2 * vBorder)\n"
+"\n"
+"# game tab\n"
+"opYoffset=vBorder\n"
+"gameoptions_id=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight\n"
+"gameoptions_id.align=kTextAlignRight\n"
+"gameoptions_domain=prev.x2 (prev.y - 1) (parent.w - gameOptionsLabelWidth - 10 - gox) (prev.h + 2)\n"
+"opYoffset=(opYoffset + prev.h + 5)\n"
+"gameoptions_name=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight\n"
+"gameoptions_name.align=kTextAlignRight\n"
+"gameoptions_desc=prev.x2 (prev.y - 1) (parent.w - gameOptionsLabelWidth - 10 - gox) (prev.h + 2)\n"
+"opYoffset=(opYoffset + prev.h + 7)\n"
+"gameoptions_lang=gox (opYoffset - 1) gow (kLineHeight + 2)\n"
+"opYoffset=(opYoffset + prev.h + 5)\n"
+"gameoptions_platform=prev.x opYoffset prev.w prev.h\n"
+"opYoffset=(opYoffset + prev.h + 5)\n"
+"\n"
+"# paths tab\n"
+"opYoffset=vBorder\n"
+"goOff=((buttonHeight - kLineHeight) / 2 + 2)\n"
+"gameoptions_savepath=gox opYoffset (buttonWidth + 5) buttonHeight\n"
+"gameoptions_savepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight\n"
+"opYoffset=(opYoffset + buttonHeight + 4)\n"
+"gameoptions_extrapath=gox opYoffset (buttonWidth + 5) buttonHeight\n"
+"gameoptions_extrapathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight\n"
+"opYoffset=(opYoffset + buttonHeight + 4)\n"
+"gameoptions_gamepath=gox opYoffset (buttonWidth + 5) buttonHeight\n"
+"gameoptions_gamepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight\n"
+"opYoffset=(opYoffset + buttonHeight + 4)\n"
+"\n"
+"# graphics tab\n"
+"opYoffset=vBorder\n"
+"opXoffset=gox\n"
+"gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight)\n"
+"useWithPrefix=graphicsControls gameoptions_\n"
+"\n"
+"# audio tab\n"
+"opYoffset=vBorder\n"
+"gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight)\n"
+"useWithPrefix=audioControls gameoptions_\n"
+"useWithPrefix=subtitleControls gameoptions_\n"
+"\n"
+"# volume tab\n"
+"opYoffset=vBorder\n"
+"gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight)\n"
+"useWithPrefix=volumeControls gameoptions_\n"
+"\n"
+"# midi tab\n"
+"opYoffset=vBorder\n"
+"gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight)\n"
+"useWithPrefix=midiControls gameoptions_\n"
+"\n"
+"gameoptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n"
+"gameoptions_ok=(prev.x2 + 10) prev.y prev.w prev.h\n"
+"\n"
+"### keys dialog\n"
+"keysdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 4)\n"
+"set_parent=keysdialog\n"
+"keysdialog_map=(parent.w - buttonWidth - 10) (10 + 2 * kLineHeight) buttonWidth buttonHeight\n"
+"keysdialog_ok=prev.x (prev.y2 + 4) prev.w prev.h\n"
+"keysdialog_cancel=prev.x (prev.y2 + 4) prev.w prev.h\n"
+"keysdialog_action=10 10 (parent.w - 20) kLineHeight\n"
+"keysdialog_action.align=kTextAlignCenter\n"
+"keysdialog_list=prev.x (prev.y + 2 * kLineHeight) (parent.w - buttonWidth - 30) (parent.h - kLineHeight * 6)\n"
+"keysdialog_mapping=prev.x (prev.y + prev.h + kLineHeight) (parent.w - buttonWidth - 20) kLineHeight\n"
+"\n"
+"### mass add dialog\n"
+"massadddialog=10 20 300 174\n"
+"set_parent=massadddialog\n"
+"massadddialog_caption=10 (10 + 1 * kLineHeight) (parent.w - 2*10) kLineHeight\n"
+"massadddialog_caption.align=kTextAlignCenter\n"
+"massadddialog_dirprogress=10 (10 + 3 * kLineHeight) (parent.w - 2*10) kLineHeight\n"
+"massadddialog_dirprogress.align=kTextAlignCenter\n"
+"massadddialog_gameprogress=10 (10 + 4 * kLineHeight) (parent.w - 2*10) kLineHeight\n"
+"massadddialog_gameprogress.align=kTextAlignCenter\n"
+"massadddialog_ok=((parent.w - (buttonWidth * 2)) / 2) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n"
+"massadddialog_cancel=(prev.x2 + 10) prev.y prev.w prev.h\n"
+"\n"
+"\n"
+"##### SCUMM dialogs\n"
+"scummDummyDialog=0 80 0 16\n"
+"\n"
+"use=scummmain\n"
+"## Engine config\n"
+"# note that scummconfig size depends on overall height\n"
+"# hence it is on the end of the list\n"
+"opYoffset=8\n"
+"useWithPrefix=volumeControls scummconfig_\n"
+"useWithPrefix=subtitleControls scummconfig_\n"
+"opYoffset=(opYoffset + buttonHeight)\n"
+"opYoffset=(opYoffset + buttonHeight + 4)\n"
+"soWidth=(39 + 3 * buttonWidth)\n"
+"scummconfig_keys=(soWidth - 3 * (buttonWidth + 4) + 6) opYoffset (buttonWidth - 10) buttonHeight\n"
+"scummconfig_cancel=(prev.x2 + 4) prev.y (prev.w + 10) prev.h\n"
+"scummconfig_ok=(prev.x2 + 4) prev.y prev.w prev.h\n"
+"opYoffset=(opYoffset + buttonHeight)\n"
+"scummconfig=((w - soWidth) / 2) ((h - opYoffset) / 2) soWidth (opYoffset + 8)\n"
+"\n"
+"## Help\n"
+"scummHelpNumLines=15\n"
+"shH=(5 + (2 + scummHelpNumLines) * kFontHeight + buttonHeight + 7)\n"
+"scummhelp=scummhelpX ((h - shH) / 2) scummhelpW shH\n"
+"scummhelp_title=10 5 scummhelpW kFontHeight\n"
+"scummhelp_key.x=10\n"
+"scummhelp_key.yoffset=5\n"
+"scummhelp_key.w=80\n"
+"scummhelp_key.h=kFontHeight\n"
+"scummhelp_dsc.x=90\n"
+"scummhelp_dsc.yoffset=5\n"
+"scummhelp_dsc.w=(scummhelpW - 10 - 90)\n"
+"scummhelp_dsc.h=kFontHeight\n"
+"scummhelp_prev=10 (5 + kFontHeight * (scummHelpNumLines + 2) + 2) buttonWidth buttonHeight\n"
+"scummhelp_next=(prev.x2 + 8) prev.y prev.w prev.h\n"
+"scummhelp_close=(scummhelpW - 8 - buttonWidth) prev.y prev.w prev.h\n"
+"\n"
+"# Saveload dialog\n"
+"scummsaveload=8 8 (w - 2 * 8) (h - 16)\n"
+"set_parent=scummsaveload\n"
+"scummsaveload_title=10 2 (parent.w - 2 * 10 - 180) kLineHeight\n"
+"scummsaveload_title.align=kTextAlignCenter\n"
+"scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y)\n"
+"scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 18)) 22\n"
+"scummsaveload_thumbnail.hPad=4\n"
+"scummsaveload_thumbnail.vPad=4\n"
+"scummsaveload_thumbnail.fillR=0\n"
+"scummsaveload_thumbnail.fillG=0\n"
+"scummsaveload_thumbnail.fillB=0\n"
+"scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n"
+"scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h\n"
+"scummsaveload_delete=prev.x (prev.y - 30) prev.w prev.h\n"
+"scummsaveload_extinfo.visible=true\n"
+"\n"
+"############################################\n"
+"[chooser]\n"
+"chooserW=(w - 2 * 8)\n"
+"chooser=((w - chooserW) / 2) ((h - opHeight) / 2) chooserW opHeight\n"
+"chooser_headline=10 6 (chooserW - 2 * 10) (kLineHeight)\n"
+"chooser_headline.align=kTextAlignCenter\n"
+"chooser_list=10 (6 + kLineHeight + 2) prev.w (opHeight - self.y - buttonHeight - 12)\n"
+"chooser_cancel=(chooserW - 2 * (buttonWidth + 10)) (opHeight - buttonHeight - 8) buttonWidth buttonHeight\n"
+"chooser_ok=(prev.x2 + 10) prev.y prev.w prev.h\n"
+"\n"
+"[graphicsControls]\n"
+"gcx=10\n"
+"gcw=(parent.w - 2 * 10)\n"
+"grModePopup=(gcx - 5) (opYoffset - 1) (gcw + 5) (kLineHeight + 2)\n"
+"opYoffset=(opYoffset + kLineHeight + 4)\n"
+"grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h\n"
+"opYoffset=(opYoffset + kLineHeight + 4)\n"
+"grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - 5) buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight)\n"
+"grAspectCheckbox=prev.x opYoffset prev.w prev.h\n"
+"opYoffset=(opYoffset + buttonHeight)\n"
+"\n"
+"[audioControls]\n"
+"aux=10\n"
+"auw=(parent.w - 2 * 10)\n"
+"auMidiPopup=(aux - 5) (opYoffset - 1) (auw + 5) (kLineHeight + 2)\n"
+"opYoffset=(opYoffset + buttonHeight + 4)\n"
+"auSampleRatePopup=(aux - 5) (opYoffset - 1) (auw + 5) (kLineHeight + 2)\n"
+"opYoffset=(opYoffset + buttonHeight + 4)\n"
+"\n"
+"[volumeControls]\n"
+"vctextw=(95 + vcAudioTabIndent)\n"
+"vcxoff=(opXoffset + vctextw + 15)\n"
+"vcx=(opXoffset + 10)\n"
+"vcMusicText=vcx (opYoffset + 2) vctextw kLineHeight\n"
+"vcMusicText.align=kTextAlignRight\n"
+"vcMusicSlider=vcxoff opYoffset sliderWidth sliderHeight\n"
+"vcMusicLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight\n"
+"opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing)\n"
+"vcSfxText=vcx (opYoffset + 2) vctextw kLineHeight\n"
+"vcSfxText.align=kTextAlignRight\n"
+"vcSfxSlider=vcxoff opYoffset sliderWidth sliderHeight\n"
+"vcSfxLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight\n"
+"opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing)\n"
+"vcSpeechText=vcx (opYoffset + 2) vctextw kLineHeight\n"
+"vcSpeechText.align=kTextAlignRight\n"
+"vcSpeechSlider=vcxoff opYoffset sliderWidth sliderHeight\n"
+"vcSpeechLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight\n"
+"opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing)\n"
+"\n"
+"[midiControls]\n"
+"mcx=10\n"
+"mcFontButton=mcx opYoffset buttonWidth buttonHeight\n"
+"mcFontPath=(prev.x2 + 20) (opYoffset + 3) (parent.w - (buttonWidth + 20) - 15 - kLineHeight - 10) kLineHeight\n"
+"mcFontClearButton=(prev.x2 + 10) (opYoffset + 2) kLineHeight kLineHeight\n"
+"opYoffset=(opYoffset + buttonHeight + 2 * midiControlsSpacing)\n"
+"mcMixedCheckbox=mcx opYoffset (parent.w - mcx - 5) buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n"
+"mcMt32Checkbox=mcx opYoffset prev.w buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n"
+"mcGSCheckbox=mcx opYoffset prev.w buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n"
+"mcMidiGainText=mcx (opYoffset + 2) 95 kLineHeight\n"
+"mcMidiGainText.align=kTextAlignRight\n"
+"mcMidiGainSlider=(prev.x2 + 10) opYoffset sliderWidth sliderHeight\n"
+"mcMidiGainLabel=(prev.x2 + 10) (opYoffset + 2) 40 kLineHeight\n"
+"opYoffset=(opYoffset + sliderHeight + midiControlsSpacing)\n"
+"\n"
+"[subtitleControls]\n"
+"sbx=(opXoffset + 10)\n"
+"sbYoff=(buttonHeight / 8)\n"
+"sbOff=((sliderHeight - kLineHeight) / 2 + 2)\n"
+"sbtextw=(100 + vcAudioTabIndent)\n"
+"opYoffset=(opYoffset + sbYoff)\n"
+"subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight\n"
+"subToggleDesc.align=kTextAlignRight\n"
+"subToggleButton=prev.x2 (opYoffset - sbYoff) (buttonWidth + 54) buttonHeight\n"
+"opYoffset=(opYoffset + buttonHeight + 6)\n"
+"subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight\n"
+"subSubtitleSpeedDesc.align=kTextAlignRight\n"
+"subSubtitleSpeedSlider=prev.x2 opYoffset sliderWidth sliderHeight\n"
+"subSubtitleSpeedLabel=(prev.x2 + 10) (opYoffset + sbOff) 24 kLineHeight\n"
+"opYoffset=(opYoffset + sliderHeight + 8)\n"
+"\n"
+"[scummmain]\n"
+"## Main dialog\n"
+"# note that scummmain size depends on overall height\n"
+"smY=(scummmainVSpace + scummmainVAddOff)\n"
+"scummmain_resume=scummmainHOffset smY scummmainButtonWidth scummmainButtonHeight\n"
+"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n"
+"smY=(smY + scummmainVSpace)\n"
+"scummmain_load=prev.x smY prev.w prev.h\n"
+"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n"
+"scummmain_save=prev.x smY prev.w prev.h\n"
+"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n"
+"smY=(smY + scummmainVSpace)\n"
+"scummmain_options=prev.x smY prev.w prev.h\n"
+"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n"
+"scummmain_about=prev.x smY prev.w prev.h\n"
+"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n"
+"scummmain_help=prev.x smY prev.w prev.h\n"
+"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n"
+"smY=(smY + scummmainVSpace)\n"
+"scummmain_quit=prev.x smY prev.w prev.h\n"
+"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n"
+"smW=(scummmainButtonWidth + 2 * scummmainHOffset)\n"
+"smH=(smY + scummmainVSpace)\n"
+"scummmain=((w - smW) / 2) ((h - smH) / 2) smW smH\n"
+"\n"
+"#### Global Main Menu Dialog"
+"[globalmain]\n"
+"# note that globalmain size depends on overall height\n"
+"hBorder=10\n"
+"gmW=(scummmainButtonWidth + (2 * scummmainHOffset) + 80)\n"
+"global_title=hBorder 8 (gmW - 2 * hBorder) kLineHeight\n"
+"global_title.align=kTextAlignCenter\n"
+"global_version=hBorder 25 (gmW - 2 * hBorder) kLineHeight\n"
+"global_version.align=kTextAlignCenter\n"
+"gmY=((scummmainVSpace * 7)+ scummmainVAddOff)\n"
+"globalmain_resume=globalmainHOffset gmY scummmainButtonWidth scummmainButtonHeight\n"
+"gmY=(gmY + scummmainButtonHeight + scummmainVAddOff)\n"
+"gmY=(gmY + scummmainVSpace)\n"
+"globalmain_options=prev.x gmY prev.w prev.h\n"
+"gmY=(gmY + scummmainButtonHeight + scummmainVAddOff)\n"
+"globalmain_about=prev.x gmY prev.w prev.h\n"
+"gmY=(gmY + scummmainButtonHeight + scummmainVAddOff)\n"
+"gmY=(gmY + scummmainVSpace)\n"
+"globalmain_rtl=prev.x gmY prev.w prev.h\n"
+"gmY=(gmY + scummmainButtonHeight + scummmainVAddOff)\n"
+"globalmain_quit=prev.x gmY prev.w prev.h\n"
+"gmY=(gmY + scummmainButtonHeight + scummmainVAddOff)\n"
+"gmH=(gmY + scummmainVSpace)\n"
+"globalmain=((w - gmW) / 2) ((h - gmH) / 2) gmW gmH\n"
+"\n"
+"# PSP GUI\n"
+"[480x272]\n"
+"def_buttonWidth=100\n"
+"def_buttonHeight=23\n"
+"def_insetX=20\n"
+"def_insetY=10\n"
+"def_insetW=(w - 2 * insetX)\n"
+"def_insetH=(h - 13 - insetY)\n"
+"def_launcherVersionX=50\n"
+"def_launcherVersionY=5\n"
+"def_midiControlsSpacing=2\n"
+"def_gameOptionsOverrideVPad=10\n"
+"def_aboutXOff=3\n"
+"def_aboutYOff=2\n"
+"def_aboutOuterBorder=10\n"
+"\n"
+"use=XxY\n"
+"";
+
+using Common::String;
+
+void Theme::processSingleLine(const String &section, const String &prefix, const String &name, const String &str) {
+ int level = 0;
+ int start = 0;
+ uint i;
+ int value;
+ const char *selfpostfixes[] = {"self.x", "self.y", "self.w", "self.h"};
+ const char *postfixesXYWH[] = {".x", ".y", ".w", ".h"};
+ const char *postfixesRGB[] = {".r", ".g", ".b"};
+ int npostfix = 0;
+ const String prefixedname(prefix + name);
+
+ // Make self.BLAH work, but not self.ANYTHING.BLAH
+ if (!strchr(prefixedname.c_str(), '.')) {
+ for (i = 0; i < ARRAYSIZE(postfixesXYWH); i++) {
+ String to(prefixedname);
+
+ to += postfixesXYWH[i];
+
+ _evaluator->setAlias(selfpostfixes[i], to);
+ _evaluator->setVar(to, EVAL_UNDEF_VAR);
+ }
+ }
+
+ // Count the number of parameters, so that we know if they're meant to
+ // be XY[WH] or RGB.
+
+ int ntmppostfix = 0;
+
+ for (i = 0; i < str.size(); i++) {
+ if (isspace(str[i]) && level == 0) {
+ ntmppostfix++;
+ }
+
+ if (str[i] == '(')
+ level++;
+ else if (str[i] == ')') {
+ if (level == 0) {
+ error("Extra ')' in section: [%s] expression: \"%s\" start is at: %d",
+ section.c_str(), name.c_str(), start);
+ }
+ level--;
+ }
+ }
+
+ if (level > 0)
+ error("Missing ')' in section: [%s] expression: \"%s\" start is at: %d",
+ section.c_str(), name.c_str(), start);
+
+ const char **postfixes = (ntmppostfix == 2) ? postfixesRGB : postfixesXYWH;
+
+ // Now do it for real, only this time we already know the parentheses
+ // are balanced.
+
+ for (i = 0; i < str.size(); i++) {
+ if (isspace(str[i]) && level == 0) {
+ value = _evaluator->eval(String(&(str.c_str()[start]), i - start), section, name + postfixes[npostfix], start);
+ _evaluator->setVar(prefixedname + postfixes[npostfix++], value);
+ start = i + 1;
+ }
+ if (str[i] == '(')
+ level++;
+ else if (str[i] == ')')
+ level--;
+ }
+
+ value = _evaluator->eval(String(&(str.c_str()[start]), i - start), section, name + postfixes[npostfix], start);
+
+ if (value == EVAL_STRING_VAR)
+ _evaluator->setStringVar(prefixedname, _evaluator->lastToken());
+
+ // process VAR=VALUE construct
+ if (npostfix == 0) {
+ _evaluator->setVar(name, value);
+
+ // Fix bug #1742561: "GUI: Missaligned text"
+ // "blah.align=foo" should be prefixed too
+ _evaluator->setVar(prefixedname, value);
+ } else {
+ _evaluator->setVar(prefixedname + postfixes[npostfix], value);
+ }
+
+ // If we have all 4 parameters, set .x2 and .y2
+ if (npostfix == 3) {
+ _evaluator->setVar(prefixedname + ".x2",
+ _evaluator->getVar(prefixedname + ".x") + _evaluator->getVar(prefixedname + ".w"));
+ _evaluator->setVar(prefixedname + ".y2",
+ _evaluator->getVar(prefixedname + ".y") + _evaluator->getVar(prefixedname + ".h"));
+ }
+
+ if (npostfix != 0)
+ setSpecialAlias("prev", prefixedname);
+}
+
+
+void Theme::processResSection(Common::ConfigFile &config, const String &name, bool skipDefs, const String &prefix) {
+ debug(3, "Reading section: [%s]", name.c_str());
+
+ const Common::ConfigFile::SectionKeyList &keys = config.getKeys(name);
+
+ Common::ConfigFile::SectionKeyList::const_iterator iterk;
+ for (iterk = keys.begin(); iterk != keys.end(); ++iterk) {
+ if (iterk->key == "set_parent") {
+ setSpecialAlias("parent", prefix + iterk->value);
+ continue;
+ }
+ if (iterk->key.hasPrefix("set_")) {
+ _evaluator->setAlias(iterk->key.c_str() + 4, prefix + iterk->value);
+ continue;
+ }
+ if (iterk->key.hasPrefix("def_")) {
+ if (!skipDefs)
+ _evaluator->setVar(name, prefix + iterk->key, iterk->value);
+ continue;
+ }
+ if (iterk->key == "use") {
+ if (iterk->value == name)
+ error("Theme section [%s]: cannot use itself", name.c_str());
+ if (!config.hasSection(iterk->value))
+ error("Undefined use of section [%s]", iterk->value.c_str());
+ processResSection(config, iterk->value, true);
+ continue;
+ }
+ if (iterk->key == "useAsIs") {
+ if (iterk->value == name)
+ error("Theme section [%s]: cannot use itself", name.c_str());
+ if (!config.hasSection(iterk->value))
+ error("Undefined use of section [%s]", iterk->value.c_str());
+ processResSection(config, iterk->value);
+ continue;
+ }
+ if (iterk->key == "useWithPrefix") {
+ const char *temp = iterk->value.c_str();
+ const char *pos = strrchr(temp, ' ');
+
+ if (pos == NULL)
+ error("2 arguments required for useWithPrefix keyword");
+
+ String n(temp, strchr(temp, ' ') - temp);
+ String pref(pos + 1);
+
+ if (n == name)
+ error("Theme section [%s]: cannot use itself", n.c_str());
+ if (!config.hasSection(n))
+ error("Undefined use of section [%s]", n.c_str());
+ processResSection(config, n, true, pref);
+ continue;
+ }
+ processSingleLine(name, prefix, iterk->key, iterk->value);
+ }
+}
+
+void Theme::setSpecialAlias(const String &alias, const String &name) {
+ const char *postfixes[] = {".x", ".y", ".w", ".h", ".x2", ".y2"};
+ int i;
+
+ for (i = 0; i < ARRAYSIZE(postfixes); i++) {
+ String from(alias + postfixes[i]);
+ String to(name + postfixes[i]);
+
+ _evaluator->setAlias(from.c_str(), to);
+ }
+}
+
+bool Theme::isThemeLoadingRequired() {
+ int x = g_system->getOverlayWidth(), y = g_system->getOverlayHeight();
+
+ if (_loadedThemeX == x && _loadedThemeY == y)
+ return false;
+
+ _loadedThemeX = x;
+ _loadedThemeY = y;
+
+ return true;
+}
+
+bool Theme::sectionIsSkipped(Common::ConfigFile &config, const char *name, int w, int h) {
+ if (!config.hasKey("skipFor", name))
+ return false;
+
+ String res;
+
+ config.getKey("skipFor", name, res);
+
+ int x, y;
+ int phase = 0;
+ const char *ptr = res.c_str();
+
+ x = y = 0;
+
+ while (phase != 3) {
+ switch (phase) {
+ case 0:
+ if (*ptr >= '0' && *ptr <= '9') {
+ x = x * 10 + *ptr - '0';
+ } else if (*ptr == 'X') {
+ phase = 1;
+ } else if (*ptr == 'x') {
+ phase = 1;
+ } else {
+ error("Syntax error. Wrong resolution in skipFor in section %s", name);
+ }
+ break;
+ case 1:
+ if (*ptr >= '0' && *ptr <= '9') {
+ y = y * 10 + *ptr - '0';
+ } else if (*ptr == 'Y' || !*ptr || *ptr == ',') {
+ phase = 2;
+
+ if ((x == w || x == 0) && (y == h || y == 0))
+ return true;
+ if (!*ptr)
+ return false;
+ if (*ptr == ',') {
+ phase = x = y = 0;
+ }
+ } else {
+ error("Syntax error. Wrong resolution in skipFor in section %s", name);
+ }
+ break;
+ case 2:
+ if (*ptr == ',') {
+ phase = x = y = 0;
+ } else if (!*ptr) {
+ if ((x == w || x == 0) && (y == h || y == 0))
+ return true;
+ return false;
+ } else {
+ error ("Syntax error. Wrong resolution in skipFor in section %s", name);
+ }
+ break;
+ default:
+ break;
+ }
+
+ ptr++;
+ }
+
+ return false;
+}
+
+void Theme::loadTheme(Common::ConfigFile &config, bool reset) {
+ char name[80];
+ int x = g_system->getOverlayWidth(), y = g_system->getOverlayHeight();
+
+ if (reset)
+ _evaluator->reset();
+
+ strcpy(name, "XxY");
+ if (config.hasSection(name) && !sectionIsSkipped(config, "XxY", x, y))
+ processResSection(config, name);
+
+ sprintf(name, "%dxY", x);
+ if (config.hasSection(name) && !sectionIsSkipped(config, name, x, y))
+ processResSection(config, name);
+
+ sprintf(name, "Xx%d", y);
+ if (config.hasSection(name) && !sectionIsSkipped(config, name, x, y))
+ processResSection(config, name);
+
+ sprintf(name, "%dx%d", x, y);
+ if (config.hasSection(name) && !sectionIsSkipped(config, name, x, y))
+ processResSection(config, name);
+
+ debug(3, "Number of variables: %d", _evaluator->getNumVars());
+}
+
+void Theme::loadTheme(Common::ConfigFile &config, bool reset, bool doBackendSpecificPostProcessing) {
+ loadTheme(config, reset);
+
+ if (doBackendSpecificPostProcessing && !g_system->getExtraThemeConfig().empty()) {
+ Common::ConfigFile myConfig;
+ Common::String myConfigINI = g_system->getExtraThemeConfig();
+ Common::MemoryReadStream s((const byte *)myConfigINI.c_str(), myConfigINI.size());
+ myConfig.loadFromStream(s);
+ loadTheme(myConfig, false);
+ }
+}
+
+} // End of namespace GUI
diff --git a/gui/themes/scummtheme.py b/gui/themes/scummtheme.py
index da0b88cf61..6199289e66 100644
--- a/gui/themes/scummtheme.py
+++ b/gui/themes/scummtheme.py
@@ -5,6 +5,8 @@ import re
import os
import zipfile
+THEME_FILE_EXTENSIONS = ('.stx', '.bmp', '.fcc')
+
def buildTheme(themeName):
if not os.path.isdir(themeName) or not os.path.isfile(os.path.join(themeName, "THEMERC")):
print "Invalid theme name: " + themeName
@@ -14,9 +16,11 @@ def buildTheme(themeName):
print "Building '" + themeName + "' theme:"
os.chdir(themeName)
+
+ zf.write('THEMERC', './THEMERC')
for filename in os.listdir('.'):
- if os.path.isfile(filename) and not filename[0] == '.':
+ if os.path.isfile(filename) and not filename[0] == '.' and filename.endswith(THEME_FILE_EXTENSIONS):
zf.write(filename, './' + filename)
print " Adding file: " + filename