aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--graphics/imageman.cpp29
-rw-r--r--graphics/imageman.h18
-rw-r--r--gui/ThemeNew.cpp1
-rw-r--r--gui/module.mk1
-rw-r--r--gui/newgui.cpp122
-rw-r--r--gui/newgui.h5
-rw-r--r--gui/options.cpp21
-rw-r--r--gui/options.h3
-rw-r--r--gui/theme-config.cpp6
-rw-r--r--gui/theme.h2
-rw-r--r--gui/themebrowser.cpp168
-rw-r--r--gui/themebrowser.h64
-rw-r--r--gui/themes/classic.ini6
-rw-r--r--gui/themes/modern.ini6
14 files changed, 405 insertions, 47 deletions
diff --git a/graphics/imageman.cpp b/graphics/imageman.cpp
index 6139159c56..d4fc9da72d 100644
--- a/graphics/imageman.cpp
+++ b/graphics/imageman.cpp
@@ -43,7 +43,7 @@ ImageManager::~ImageManager() {
_surfaces.clear();
#ifdef USE_ZLIB
for (ZipIterator pos2 = _archives.begin(); pos2 != _archives.end(); ++pos2) {
- unzClose(*pos2);
+ unzClose(pos2->file);
}
_archives.clear();
#endif
@@ -54,11 +54,26 @@ bool ImageManager::addArchive(const Common::String &name) {
unzFile newFile = unzOpen(name.c_str());
if (!newFile)
return false;
- _archives.push_back(newFile);
+ Archive arch;
+ arch.file = newFile;
+ arch.filename = name;
+ _archives.push_back(arch);
#endif
return true;
}
+void ImageManager::remArchive(const Common::String &name) {
+#ifdef USE_ZLIB
+ for (ZipIterator pos = _archives.begin(); pos != _archives.end(); ++pos) {
+ if (pos->filename.compareToIgnoreCase(name) == 0) {
+ unzClose(pos->file);
+ _archives.erase(pos);
+ break;
+ }
+ }
+#endif
+}
+
bool ImageManager::registerSurface(const Common::String &name, Surface *surf) {
if (getSurface(name)) {
return false;
@@ -74,7 +89,7 @@ bool ImageManager::registerSurface(const Common::String &name, Surface *surf) {
#ifdef USE_ZLIB
ZipIterator file = _archives.end();
for (ZipIterator pos = _archives.begin(); pos != _archives.end(); ++pos) {
- if (unzLocateFile(*pos, name.c_str(), 2) == UNZ_OK) {
+ if (unzLocateFile(pos->file, name.c_str(), 2) == UNZ_OK) {
file = pos;
break;
}
@@ -84,12 +99,12 @@ bool ImageManager::registerSurface(const Common::String &name, Surface *surf) {
return false;
unz_file_info fileInfo;
- unzOpenCurrentFile(*file);
- unzGetCurrentFileInfo(*file, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
+ unzOpenCurrentFile(file->file);
+ unzGetCurrentFileInfo(file->file, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
uint8 *buffer = new uint8[fileInfo.uncompressed_size];
assert(buffer);
- unzReadCurrentFile(*file, buffer, fileInfo.uncompressed_size);
- unzCloseCurrentFile(*file);
+ unzReadCurrentFile(file->file, buffer, fileInfo.uncompressed_size);
+ unzCloseCurrentFile(file->file);
Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size);
surf = ImageDecoder::loadFile(stream);
delete [] buffer;
diff --git a/graphics/imageman.h b/graphics/imageman.h
index 6f682c1646..a5fe8f131d 100644
--- a/graphics/imageman.h
+++ b/graphics/imageman.h
@@ -37,7 +37,7 @@ public:
~ImageManager();
/**
- * adds an .zip archive to the pool there the ImagaManager searches
+ * adds an .zip archive to the pool where the ImageManager searches
* for image files
*
* @param name the name of the archive
@@ -45,6 +45,14 @@ public:
*/
bool addArchive(const Common::String &name);
+ /**
+ * deletes an .zip archive from the pool where the Image Manager searches
+ * for image files
+ *
+ * @param name the name of the archive
+ */
+ void remArchive(const Common::String &name);
+
/**
* registers a surface to the ImageManager.
* surf->free(), also delete surf, will be called when the ImageManager will
@@ -84,14 +92,18 @@ private:
};
typedef Common::List<Entry*>::iterator Iterator;
#ifdef USE_ZLIB
- typedef Common::List<unzFile>::iterator ZipIterator;
+ struct Archive {
+ unzFile file;
+ Common::String filename;
+ };
+ typedef Common::List<Archive>::iterator ZipIterator;
#endif
Iterator searchHandle(const Common::String &name);
Common::List<Entry*> _surfaces;
#ifdef USE_ZLIB
- Common::List<unzFile> _archives;
+ Common::List<Archive> _archives;
#endif
};
diff --git a/gui/ThemeNew.cpp b/gui/ThemeNew.cpp
index fc8aadcd51..78afbb487a 100644
--- a/gui/ThemeNew.cpp
+++ b/gui/ThemeNew.cpp
@@ -114,6 +114,7 @@ ThemeNew::~ThemeNew() {
ImageMan.unregisterSurface(_imageHandles[i]);
}
}
+ ImageMan.remArchive(_stylefile + ".zip");
}
bool ThemeNew::init() {
diff --git a/gui/module.mk b/gui/module.mk
index bab4b31c94..9df80d5cbc 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -18,6 +18,7 @@ MODULE_OBJS := \
PopUpWidget.o \
ScrollBarWidget.o \
TabWidget.o \
+ themebrowser.o \
widget.o \
theme.o \
ThemeClassic.o \
diff --git a/gui/newgui.cpp b/gui/newgui.cpp
index 94924f1e84..211068c30f 100644
--- a/gui/newgui.cpp
+++ b/gui/newgui.cpp
@@ -106,35 +106,61 @@ NewGui::NewGui() : _needRedraw(false),
Common::String styleType;
Common::ConfigFile cfg;
+#endif
+
+ if (!loadNewTheme(style)) {
+ warning("falling back to classic style");
+ _theme = new ThemeClassic(_system);
+ assert(_theme);
+ if (!_theme->init()) {
+ error("Couldn't initialize classic theme");
+ }
+ }
+
+ _theme->resetDrawArea();
+ _themeChange = false;
+}
+
+bool NewGui::loadNewTheme(const Common::String &style) {
+ Common::String styleType;
+ Common::ConfigFile cfg;
+
+ Common::String oldTheme = (_theme != 0) ? _theme->getStylefileName() : "";
+ delete _theme;
+
if (Theme::themeConfigUseable(style, "", &styleType, &cfg)) {
if (0 == styleType.compareToIgnoreCase("classic"))
_theme = new ThemeClassic(_system, style, &cfg);
+#ifndef DISABLE_FANCY_THEMES
else if (0 == styleType.compareToIgnoreCase("modern"))
_theme = new ThemeNew(_system, style, &cfg);
+#endif
else
warning("Unsupported theme type '%s'", styleType.c_str());
} else {
warning("Config '%s' is NOT usable for themes or not found", style.c_str());
}
cfg.clear();
-#endif
-
- if (!_theme)
- _theme = new ThemeClassic(_system);
- assert(_theme);
+ if (!_theme)
+ return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false);
- // Init the theme
if (!_theme->init()) {
- warning("Could not initialize your preferred theme, falling back to classic style");
+ warning("Could not initialize your preferred theme");
delete _theme;
- _theme = new ThemeClassic(_system);
- assert(_theme);
- if (!_theme->init()) {
- error("Couldn't initialize classic theme");
- }
+ _theme = 0;
+ loadNewTheme(oldTheme);
+ return false;
}
_theme->resetDrawArea();
+
+ _theme->enable();
+ if (!oldTheme.empty())
+ screenChange();
+
+ _themeChange = true;
+
+ return true;
}
void NewGui::redraw() {
@@ -180,18 +206,8 @@ void NewGui::runLoop() {
bool useStandardCurs = !_theme->ownCursor();
- if (useStandardCurs) {
- const byte palette[] = {
- 255, 255, 255, 0,
- 255, 255, 255, 0,
- 171, 171, 171, 0,
- 87, 87, 87, 0
- };
-
- PaletteMan.pushCursorPalette(palette, 0, 4);
- CursorMan.pushCursor(NULL, 0, 0, 0, 0);
- CursorMan.showMouse(true);
- }
+ if (useStandardCurs)
+ setupCursor();
while (!_dialogStack.empty() && activeDialog == _dialogStack.top()) {
if (_needRedraw) {
@@ -217,6 +233,23 @@ void NewGui::runLoop() {
continue;
Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y);
+
+ // HACK to change the cursor to the new themes one
+ if (_themeChange) {
+ if (useStandardCurs)
+ PaletteMan.popCursorPalette();
+
+ CursorMan.popCursor();
+
+ useStandardCurs = !_theme->ownCursor();
+ if (useStandardCurs)
+ setupCursor();
+
+ _theme->refresh();
+
+ _themeChange = false;
+ redraw();
+ }
switch (event.type) {
case OSystem::EVENT_KEYDOWN:
@@ -270,18 +303,7 @@ void NewGui::runLoop() {
_system->quit();
return;
case OSystem::EVENT_SCREEN_CHANGED:
- _lastScreenChangeID = _system->getScreenChangeID();
-
- // reinit the whole theme
- _theme->refresh();
- // refresh all dialogs
- for (int i = 0; i < _dialogStack.size(); ++i) {
- _dialogStack[i]->reflowLayout();
- }
- // We need to redraw immediately. Otherwise
- // some other event may cause a widget to be
- // redrawn before redraw() has been called.
- redraw();
+ screenChange();
break;
}
}
@@ -361,6 +383,19 @@ void NewGui::closeTopDialog() {
_needRedraw = true;
}
+void NewGui::setupCursor() {
+ const byte palette[] = {
+ 255, 255, 255, 0,
+ 255, 255, 255, 0,
+ 171, 171, 171, 0,
+ 87, 87, 87, 0
+ };
+
+ PaletteMan.pushCursorPalette(palette, 0, 4);
+ CursorMan.pushCursor(NULL, 0, 0, 0, 0);
+ CursorMan.showMouse(true);
+}
+
// Draw the mouse cursor (animated). This is pretty much the same as in old
// SCUMM games, but the code no longer resembles what we have in cursor.cpp
// very much. We could plug in a different cursor here if we like to.
@@ -390,4 +425,19 @@ void NewGui::clearDragWidget() {
_dialogStack.top()->_dragWidget = 0;
}
+void NewGui::screenChange() {
+ _lastScreenChangeID = _system->getScreenChangeID();
+
+ // reinit the whole theme
+ _theme->refresh();
+ // refresh all dialogs
+ for (int i = 0; i < _dialogStack.size(); ++i) {
+ _dialogStack[i]->reflowLayout();
+ }
+ // We need to redraw immediately. Otherwise
+ // some other event may cause a widget to be
+ // redrawn before redraw() has been called.
+ redraw();
+}
+
} // End of namespace GUI
diff --git a/gui/newgui.h b/gui/newgui.h
index 54815a2d51..f40a33ebd2 100644
--- a/gui/newgui.h
+++ b/gui/newgui.h
@@ -70,6 +70,7 @@ public:
bool isActive() const { return ! _dialogStack.empty(); }
+ bool loadNewTheme(const Common::String &file);
Theme *theme() { return _theme; }
Eval *evaluator() { return _theme->_evaluator; }
@@ -113,16 +114,20 @@ protected:
int _cursorAnimateTimer;
byte _cursor[2048];
+ bool _themeChange;
+
void saveState();
void restoreState();
void openDialog(Dialog *dialog);
void closeTopDialog();
+ void screenChange();
void redraw();
void loop();
+ void setupCursor();
void animateCursor();
};
diff --git a/gui/options.cpp b/gui/options.cpp
index ee04fb31a5..007ef48f07 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -21,6 +21,7 @@
#include "common/stdafx.h"
#include "gui/browser.h"
+#include "gui/themebrowser.h"
#include "gui/chooser.h"
#include "gui/eval.h"
#include "gui/newgui.h"
@@ -69,7 +70,8 @@ enum {
kChooseSoundFontCmd = 'chsf',
kChooseSaveDirCmd = 'chos',
kChooseThemeDirCmd = 'chth',
- kChooseExtraDirCmd = 'chex'
+ kChooseExtraDirCmd = 'chex',
+ kChooseThemeCmd = 'chtf'
};
#ifdef SMALL_SCREEN_DEVICE
@@ -685,6 +687,11 @@ GlobalOptionsDialog::GlobalOptionsDialog()
new ButtonWidget(tab, "globaloptions_keysbutton", "Keys", kChooseKeyMappingCmd, 0);
#endif
+ tab->addTab("Misc");
+
+ new ButtonWidget(tab, "globaloptions_themebutton2", "Theme:", kChooseThemeCmd, 0);
+ _curTheme = new StaticTextWidget(tab, "globaloptions_curtheme", ConfMan.get("gui_theme", _domain));
+
// TODO: joystick setting
@@ -797,6 +804,18 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
}
break;
}
+ case kChooseThemeCmd: {
+ ThemeBrowser browser;
+ if (browser.runModal() > 0) {
+ // User made his choice...
+ Common::String theme = browser.selected();
+ if (0 != theme.compareToIgnoreCase(g_gui.theme()->getStylefileName()))
+ if (g_gui.loadNewTheme(theme))
+ _curTheme->setLabel(theme);
+ draw();
+ }
+ break;
+ }
#ifdef SMALL_SCREEN_DEVICE
case kChooseKeyMappingCmd:
_keysDialog->runModal();
diff --git a/gui/options.h b/gui/options.h
index 136b73b0e9..34ced65376 100644
--- a/gui/options.h
+++ b/gui/options.h
@@ -36,6 +36,7 @@ class CheckboxWidget;
class PopUpWidget;
class SliderWidget;
class StaticTextWidget;
+class ListWidget;
class OptionsDialog : public Dialog {
typedef Common::String String;
@@ -152,6 +153,8 @@ protected:
StaticTextWidget *_savePath;
StaticTextWidget *_themePath;
StaticTextWidget *_extraPath;
+
+ StaticTextWidget *_curTheme;
};
} // End of namespace GUI
diff --git a/gui/theme-config.cpp b/gui/theme-config.cpp
index e0d2af458c..253def8f60 100644
--- a/gui/theme-config.cpp
+++ b/gui/theme-config.cpp
@@ -185,6 +185,12 @@ const char *Theme::_defaultConfigINI =
"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"
+"\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"
diff --git a/gui/theme.h b/gui/theme.h
index 4cf3358e30..1c783d8166 100644
--- a/gui/theme.h
+++ b/gui/theme.h
@@ -213,6 +213,8 @@ public:
Eval *_evaluator;
static bool themeConfigUseable(const String &file, const String &style="", String *cStyle=0, Common::ConfigFile *cfg=0);
+
+ const String &getStylefileName() const { return _stylefile; }
protected:
bool loadConfigFile(const String &file);
void getColorFromConfig(const String &name, OverlayColor &col);
diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp
new file mode 100644
index 0000000000..5bda962db1
--- /dev/null
+++ b/gui/themebrowser.cpp
@@ -0,0 +1,168 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2006 The ScummVM project
+ *
+ * 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/stdafx.h"
+#include "gui/themebrowser.h"
+#include "gui/ListWidget.h"
+#include "gui/widget.h"
+#include "gui/theme.h"
+#include "common/fs.h"
+
+namespace GUI {
+
+enum {
+ kChooseCmd = 'Chos'
+};
+
+// TODO: this is a rip off of GUI::Browser right now
+// it will get some more output like theme name,
+// theme style, theme preview(?) in the future
+// but for now this simple browser works,
+// also it will get its own theme config values
+// and not use 'browser_' anymore
+ThemeBrowser::ThemeBrowser() : Dialog("browser") {
+ _fileList = 0;
+
+ new StaticTextWidget(this, "browser_headline", "Select a Theme");
+
+ // Add file list
+ _fileList = new ListWidget(this, "browser_list");
+ _fileList->setNumberingMode(kListNumberingOff);
+ _fileList->setEditable(false);
+
+ _fileList->setHints(THEME_HINT_PLAIN_COLOR);
+
+ // Buttons
+ new ButtonWidget(this, "browser_cancel", "Cancel", kCloseCmd, 0);
+ new ButtonWidget(this, "browser_choose", "Choose", kChooseCmd, 0);
+}
+
+void ThemeBrowser::open() {
+ // Alway refresh file list
+ updateListing();
+
+ // Call super implementation
+ Dialog::open();
+}
+
+void ThemeBrowser::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ switch (cmd) {
+ case kChooseCmd:
+ case kListItemActivatedCmd:
+ case kListItemDoubleClickedCmd:
+ int selection = _fileList->getSelected();
+ if (selection < 0)
+ break;
+ _select = _themes[selection].file;
+ setResult(1);
+ close();
+ break;
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ }
+}
+
+void ThemeBrowser::updateListing() {
+ _themes.clear();
+
+ if (ConfMan.hasKey("themepath"))
+ addDir(_themes, ConfMan.get("themepath"), 0);
+
+#ifdef DATA_PATH
+ addDir(_themes, DATA_PATH);
+#endif
+
+ if (ConfMan.hasKey("extrapath"))
+ addDir(_themes, ConfMan.get("extrapath"));
+
+ addDir(_themes, ".", 0);
+
+ // Populate the ListWidget
+ Common::StringList list;
+
+ for (ThList::const_iterator i = _themes.begin(); i != _themes.end(); ++i)
+ list.push_back(i->name);
+
+ _fileList->setList(list);
+ _fileList->scrollTo(0);
+
+ // Finally, redraw
+ draw();
+}
+
+void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) {
+ if (level < 0)
+ return;
+
+ FilesystemNode node(dir);
+
+ if (!node.isValid())
+ return;
+
+ FSList fslist;
+ if (!node.listDir(fslist, FilesystemNode::kListAll))
+ return;
+
+ for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) {
+ if (i->isDirectory()) {
+ addDir(list, i->path(), level-1);
+ } else {
+ Entry th;
+ if (isTheme(*i, th)) {
+ bool add = true;
+ for (ThList::const_iterator p = list.begin(); p != list.end(); ++p) {
+ if (p->name == th.name || p->file == th.file) {
+ add = false;
+ break;
+ }
+ }
+
+ if (add)
+ list.push_back(th);
+ }
+ }
+ }
+}
+
+bool ThemeBrowser::isTheme(const FilesystemNode &node, Entry &out) {
+ Common::ConfigFile cfg;
+ Common::String type;
+
+ out.file = node.name();
+ for (int i = out.file.size()-1; out.file[i] != '.' && i > 0; --i) {
+ out.file.deleteLastChar();
+ }
+ out.file.deleteLastChar();
+
+ if (out.file.empty())
+ return false;
+
+ if (!Theme::themeConfigUseable(out.file, "", &type, &cfg))
+ return false;
+
+ out.type = type;
+ out.name = out.file;
+
+ return true;
+}
+
+} // end of namespace GUI
+
diff --git a/gui/themebrowser.h b/gui/themebrowser.h
new file mode 100644
index 0000000000..ce38bead9d
--- /dev/null
+++ b/gui/themebrowser.h
@@ -0,0 +1,64 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2006 The ScummVM project
+ *
+ * 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_THEMEBROWSER_H
+#define GUI_THEMEBROWSER_H
+
+#include "gui/dialog.h"
+#include "common/str.h"
+#include "common/fs.h"
+#include "common/array.h"
+
+namespace GUI {
+
+class ListWidget;
+class StaticTextWidget;
+
+class ThemeBrowser : public Dialog {
+public:
+ ThemeBrowser();
+
+ void open();
+ void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+
+ const Common::String &selected() const { return _select; }
+private:
+ struct Entry {
+ Common::String name;
+ Common::String type;
+ Common::String file;
+ };
+
+ ListWidget *_fileList;
+ Common::String _select;
+ typedef Common::Array<Entry> ThList;
+ ThList _themes;
+
+ void updateListing();
+
+ void addDir(ThList &list, const Common::String &dir, int level = 4);
+ bool isTheme(const FilesystemNode &node, Entry &out);
+};
+
+} // end of namespace GUI
+
+#endif
+
diff --git a/gui/themes/classic.ini b/gui/themes/classic.ini
index c26715343d..91f91b1e80 100644
--- a/gui/themes/classic.ini
+++ b/gui/themes/classic.ini
@@ -178,6 +178,12 @@ globaloptions_themepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 2
yoffset=(yoffset + buttonHeight + 4)
globaloptions_keysbutton=10 yoffset (buttonWidth + 5) buttonHeight
+# Misc options
+yoffset=vBorder
+glOff=((buttonHeight - kLineHeight) / 2 + 2)
+globaloptions_themebutton2=10 yoffset buttonWidth buttonHeight
+globaloptions_curtheme=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight
+
globaloptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight
globaloptions_ok=(prev.x2 + 10) prev.y prev.w prev.h
diff --git a/gui/themes/modern.ini b/gui/themes/modern.ini
index 43aee8d33e..f656ee96fd 100644
--- a/gui/themes/modern.ini
+++ b/gui/themes/modern.ini
@@ -298,6 +298,12 @@ globaloptions_themepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 2
yoffset=(yoffset + buttonHeight + 12)
globaloptions_keysbutton=5 yoffset buttonWidth buttonHeight
+# Misc options
+yoffset=vBorder
+glOff=((buttonHeight - kLineHeight) / 2 + 2)
+globaloptions_themebutton2=10 yoffset buttonWidth buttonHeight
+globaloptions_curtheme=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight
+
globaloptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight
globaloptions_ok=(prev.x2 + 10) prev.y prev.w prev.h