aboutsummaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
authorMax Horn2002-08-21 16:07:07 +0000
committerMax Horn2002-08-21 16:07:07 +0000
commitce46866403fdcc479cf9d67e4d430409b15dadc3 (patch)
tree75ebfaa1ed13f549959d76d3ce101c3e66f5451b /gui
parent662256f25dbe43abf67077a804e225738765f009 (diff)
downloadscummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.tar.gz
scummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.tar.bz2
scummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.zip
Initial revision
svn-id: r4785
Diffstat (limited to 'gui')
-rw-r--r--gui/dialog.cpp22
-rw-r--r--gui/dialog.h2
-rw-r--r--gui/gui.cpp1252
-rw-r--r--gui/gui.h124
-rw-r--r--gui/guimaps.h157
-rw-r--r--gui/newgui.cpp541
-rw-r--r--gui/newgui.h151
7 files changed, 2247 insertions, 2 deletions
diff --git a/gui/dialog.cpp b/gui/dialog.cpp
index ecc444b71d..71b55f8c80 100644
--- a/gui/dialog.cpp
+++ b/gui/dialog.cpp
@@ -28,7 +28,7 @@
#include "ListWidget.h"
#include "config-file.h"
#include "sound/mididrv.h"
-#include "sound/imuse.h"
+#include "scumm/imuse.h"
/*
* TODO list
@@ -407,11 +407,29 @@ AboutDialog::AboutDialog(NewGui *gui)
}
PauseDialog::PauseDialog(NewGui *gui)
- : Dialog (gui, 50, 80, 220, 16)
+ : Dialog (gui, 60, 20, 100, 100)
{
addResText(4, 4, 220, 16, 10);
}
+void PauseDialog::draw()
+{
+ if (_screenBuf) {
+ _gui->blitFrom(_screenBuf, _x, _y, _w, _h);
+ } else {
+ _gui->fillRect(_x, _y, _w, _h, _gui->_bgcolor);
+ _gui->box(_x, _y, _w, _h);
+ }
+ _gui->addDirtyRect(_x, _y, _w, _h);
+
+ _gui->frameRect(10 + _x, 15 + _y, 100, 100, _gui->_color);
+ for (int y = 0; y < 16; ++y)
+ for (int x = 0; x < 16; ++x)
+ _gui->fillRect(10 + _x + x*5, 15 + _y + y*5, 5, 5, y*16 + x);
+
+
+}
+
SoundDialog::SoundDialog(NewGui *gui)
: Dialog (gui, 30, 20, 260, 110)
{
diff --git a/gui/dialog.h b/gui/dialog.h
index 0e9b46222a..55fd464a42 100644
--- a/gui/dialog.h
+++ b/gui/dialog.h
@@ -116,6 +116,8 @@ class PauseDialog : public Dialog {
public:
PauseDialog(NewGui *gui);
+ virtual void draw();
+
virtual void handleMouseDown(int x, int y, int button, int clickCount)
{ close(); }
virtual void handleKeyDown(char key, int modifiers)
diff --git a/gui/gui.cpp b/gui/gui.cpp
new file mode 100644
index 0000000000..270641ae17
--- /dev/null
+++ b/gui/gui.cpp
@@ -0,0 +1,1252 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001/2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "scumm.h"
+#include "sound/mididrv.h"
+#include "scumm/imuse.h"
+#include "gui.h"
+#include "guimaps.h"
+#include "config-file.h"
+
+#include <ctype.h>
+
+#define hline(x, y, x2, color) line(x, y, x2, y, color);
+#define vline(x, y, y2, color) line(x, y, x, y2, color);
+
+#ifdef _WIN32_WCE
+// Additional variables for WinCE specific GUI
+#include "gapi_keys.h"
+extern bool toolbar_drawn;
+extern bool hide_toolbar;
+extern bool draw_keyboard;
+extern bool get_key_mapping;
+extern struct keyops keyMapping;
+extern void save_key_mapping(void);
+extern void do_hide(bool);
+extern void do_quit();
+uint16 _key_mapping_required;
+uint16 _current_page;
+bool keyboard_override;
+bool save_hide_toolbar;
+#else
+#define save_key_mapping() ;
+bool get_key_mapping;
+uint16 _key_mapping_required;
+#endif
+
+enum {
+ GUI_NONE = 0,
+ GUI_RESTEXT = 1,
+ GUI_IMAGE = 2,
+ GUI_STAT = 3,
+ GUI_CUSTOMTEXT = 4,
+ GUI_VARTEXT = 5,
+ GUI_ACTIONTEXT = 6,
+ GUI_KEYTEXT = 7,
+ GUI_SCROLLTEXT = 8,
+ GUI_NEXTTEXT = 9,
+ GUI_UPDOWNARROW = 10,
+ GUI_CHECKBOX = 11
+};
+
+enum {
+ GWF_BORDER = 1,
+ GWF_CLEARBG = 2,
+ GWF_PARENT = 4,
+ GWF_DELAY = 8,
+ GWF_DEFAULT = GWF_BORDER | GWF_CLEARBG,
+ GWF_BUTTON = GWF_BORDER | GWF_CLEARBG | GWF_DELAY
+};
+
+struct GuiWidget {
+ byte _type;
+ byte _page;
+ byte _flags;
+ int16 _x, _y;
+ uint16 _w, _h;
+ uint16 _id;
+ byte _string_number;
+ uint8 _hotkey;
+};
+
+enum {
+ SAVELOAD_DIALOG,
+ PAUSE_DIALOG,
+ SOUND_DIALOG,
+ KEYS_DIALOG,
+ OPTIONS_DIALOG,
+ ABOUT_DIALOG,
+ LAUNCHER_DIALOG,
+ MISC_DIALOG
+};
+
+
+#define IMG_SIZE 8
+
+// Triangles pointing up-/downwards, used for save/load dialog
+static uint32 up_arrow[IMG_SIZE] = {
+ 0x00011000,
+ 0x00011000,
+ 0x00100100,
+ 0x00100100,
+ 0x01000010,
+ 0x01000010,
+ 0x10000001,
+ 0x10000001,
+};
+
+static uint32 down_arrow[IMG_SIZE] = {
+ 0x10000001,
+ 0x10000001,
+ 0x01000010,
+ 0x01000010,
+ 0x00100100,
+ 0x00100100,
+ 0x00011000,
+ 0x00011000,
+};
+
+static uint32 checked_img[IMG_SIZE] = {
+ 0x00000000,
+ 0x01000010,
+ 0x00100100,
+ 0x00011000,
+ 0x00011000,
+ 0x00100100,
+ 0x01000010,
+ 0x00000000,
+};
+
+const GuiWidget launcher_dialog[] = {
+ {GUI_STAT, 0xFF, GWF_DEFAULT, 0, 0, 320, 200, 0, 0},
+ {GUI_CUSTOMTEXT, 0x01, GWF_CLEARBG, 5, 180, 45, 15, 20, 12},
+ {GUI_CUSTOMTEXT, 0x01, GWF_CLEARBG, 130, 180, 65, 15, 21, 17},
+ {GUI_CUSTOMTEXT, 0x01, GWF_CLEARBG, 265, 180, 50, 15, 22, 7},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+const GuiWidget keys_dialog[] = {
+ {GUI_STAT, 0xFF, GWF_DEFAULT, 30, 10, 260, 130, 0, 0},
+
+ // First action
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 11, 10 + 10, 15, 15, 10, 3}, // CUSTOMTEXT_PLUS
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 33, 10 + 10, 15, 15, 11, 4}, // CUSTOMTEXT_MINUS
+ {GUI_ACTIONTEXT, 0x01, GWF_BUTTON, 30 + 11 + 33 + 10, 10 + 10, 100, 15, 100, 1},
+ {GUI_KEYTEXT, 0x01, 0, 30 + 11 + 33 + 120, 10 + 10 + 3, 100, 15, 1, 1},
+
+ //Second action
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 11, 10 + 10 + 15 + 5, 15, 15, 20, 3}, // CUSTOMTEXT_PLUS
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 33, 10 + 10 + 15 + 5, 15, 15, 21, 4}, // CUSTOMTEXT_MINUS
+ {GUI_ACTIONTEXT, 0x01, GWF_BUTTON, 30 + 10 + 33 + 10, 10 + 10 + 15 + 5, 100, 15, 101, 2},
+ {GUI_KEYTEXT, 0x01, 0, 30 + 11 + 33 + 120, 10 + 10 + 15 + 5 + 3, 100, 15, 2, 2},
+
+ //Third action
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 11, 10 + 10 + 15 + 5 + 15 + 5, 15, 15, 30, 3}, // CUSTOMTEXT_PLUS
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 33, 10 + 10 + 15 + 5 + 15 + 5, 15, 15, 31, 4}, // CUSTOMTEXT_MINUS
+ {GUI_ACTIONTEXT, 0x01, GWF_BUTTON, 30 + 10 + 33 + 10, 10 + 10 + 15 + 5 + 15 + 5, 100, 15, 102, 3},
+ {GUI_KEYTEXT, 0x01, 0, 30 + 11 + 33 + 120, 10 + 10 + 15 + 5 + 15 + 5 + 3, 100, 15, 3, 3},
+
+ //Fourth action
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 11, 10 + 10 + 15 + 5 + 15 + 5 + 15 + 5, 15, 15, 40, 3},
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 33, 10 + 10 + 15 + 5 + 15 + 5 + 15 + 5, 15, 15, 41, 4},
+ {GUI_ACTIONTEXT, 0x01, GWF_BUTTON, 30 + 10 + 33 + 10, 10 + 10 + 15 + 5 + 15 + 5 + 15 + 5, 100, 15,
+ 103, 4},
+ {GUI_KEYTEXT, 0x01, 0, 30 + 11 + 33 + 120, 10 + 10 + 15 + 5 + 15 + 5 + 15 + 5 + 3, 100, 15, 4, 4},
+
+ //Fifth action
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 11, 10 + 10 + 15 + 5 + 15 + 5 + 15 + 5 + 15 + 5, 15, 15,
+ 50, 3},
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 33, 10 + 10 + 15 + 5 + 15 + 5 + 15 + 5 + 15 + 5, 15, 15,
+ 51, 4},
+ {GUI_ACTIONTEXT, 0x01, GWF_BUTTON, 30 + 10 + 33 + 10, 10 + 10 + 15 + 5 + 15 + 5 + 15 + 5 + 15 + 5,
+ 100, 15, 104, 5},
+ {GUI_KEYTEXT, 0x01, 0, 30 + 11 + 33 + 120, 10 + 10 + 15 + 5 + 15 + 5 + 15 + 5 + 15 + 5 + 3, 100,
+ 15, 5, 5},
+
+ //OK
+ {GUI_RESTEXT, 0x01, GWF_BUTTON, 30 + 60, 10 + 106, 54, 16, 60, 9},
+ //Previous-Next
+ {GUI_NEXTTEXT, 0x01, GWF_BUTTON, 30 + 120, 10 + 106, 54, 16, 61, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+const GuiWidget about_dialog[] = {
+ {GUI_STAT, 0xFF, GWF_DEFAULT, 30, 10, 260, 134, 0, 0},
+ {GUI_CUSTOMTEXT, 0x01, 0, 30 + 68, 10 + 20, 160, 15, 0, 9}, // Build
+ {GUI_CUSTOMTEXT, 0x01, 0, 30 + 10, 10 + 35, 240, 15, 0, 10}, // ScummVM Url
+ {GUI_CUSTOMTEXT, 0x01, 0, 30 + 75, 10 + 65, 150, 15, 0, 11}, // Lucasarts
+ {GUI_CUSTOMTEXT, 0x01, 0, 30 + 110, 10 + 80, 40, 15, 0, 21}, // Except:
+ {GUI_CUSTOMTEXT, 0x01, 0, 30 + 25, 10 + 95, 210, 15, 0, 22}, // Adventuresoft
+ {GUI_SCROLLTEXT, 0x01, 0, 30 + 95, 10 + 10, 100, 15, 0},
+ {GUI_RESTEXT, 0x01, GWF_BUTTON, 30 + 100, 10 + 112, 54, 16, 40, 9},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+const GuiWidget options_dialog[] = {
+ // Only display the "Keys" options for WinCE
+#ifdef _WIN32_WCE
+ {GUI_STAT, 0xFF, GWF_DEFAULT, 50, 80, 210, 60, 0, 0},
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 50 + 10, 80 + 10, 40, 15, 1, 5, 'S'}, // Sound
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 50 + 10 + 40 + 30, 80 + 10, 40, 15, 2, 6, 'K'}, // Keys
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 50 + 10 + 40 + 30 + 40 + 30, 80 + 10, 40, 15, 3, 7, 'A'}, // About
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 50 + 10, 80 + 10 + 15 + 10, 40, 15, 4, 18, 'M'}, // Misc
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+#else
+ {GUI_STAT, 0xFF, GWF_DEFAULT, 50, 80, 210, 40, 0, 0},
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 50 + 10, 80 + 10, 40, 15, 1, 5, 'S'}, // Sound
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 50 + 10 + 40 + 30, 80 + 10, 40, 15, 3, 7, 'A'}, // About
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 50 + 10 + 40 + 30 + 40 + 30, 80 + 10, 40, 15, 4, 18, 'M'}, // Misc
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+#endif
+};
+
+const GuiWidget misc_dialog[] = {
+ {GUI_STAT, 0xFF, GWF_DEFAULT, 50, 80, 210, 65, 0, 0},
+ {GUI_CHECKBOX, 0x01, GWF_DEFAULT, 50 + 10, 80 + 6, 14, 14, 1, 0, 'S'}, // checkbox for subtitles
+ {GUI_CUSTOMTEXT, 0x01, 0, 50 + 10 + 20, 80 + 10, 140, 15, 0, 19}, // "Show speech subtitles"
+ {GUI_CHECKBOX, 0x01, GWF_DEFAULT, 50 + 10, 80 + 6 + 16, 14, 14, 5, 0, 'A'}, // checkbox for amiga pallete
+ {GUI_CUSTOMTEXT, 0x01, 0, 50 + 10 + 20, 80 + 10 + 15, 140, 15, 0, 20}, // "Amiga pallete conversion"
+ {GUI_RESTEXT, 0x01, GWF_BUTTON, 50 + 10 + 20, 80 + 10 + 15 + 20, 54, 16, 3, 9, 13}, // ok
+ {GUI_RESTEXT, 0x01, GWF_BUTTON, 50 + 10 + 20 + 80, 80 + 10 + 15 + 20, 54, 16, 4, 7}, // cancel
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+const GuiWidget sound_dialog[] = {
+ {GUI_STAT, 0xFF, GWF_DEFAULT, 30, 20, 260, 120, 0, 0},
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 11, 20 + 11, 15, 15, 1, 3}, // Plus
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 33, 20 + 11, 15, 15, 2, 4}, // Minus
+ {GUI_VARTEXT, 0x01, GWF_DEFAULT, 30 + 73, 20 + 11, 128, 15, 3, 0}, // Master
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 11, 20 + 25 + 11, 15, 15, 11, 3}, // Plus
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 33, 20 + 25 + 11, 15, 15, 12, 4}, // Minus
+ {GUI_VARTEXT, 0x01, GWF_BUTTON, 30 + 73, 20 + 25 + 11, 128, 15, 13, 1}, // Music
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 11, 20 + 25 + 25 + 11, 15, 15, 21, 3}, // Plus
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 30 + 33, 20 + 25 + 25 + 11, 15, 15, 22, 4}, // Minus
+ {GUI_VARTEXT, 0x01, GWF_BUTTON, 30 + 73, 20 + 25 + 25 + 11, 128, 15, 23, 2}, // SFX
+ {GUI_RESTEXT, 0x01, GWF_BUTTON, 30 + (260 / 2) - 80, 20 + 25 + 25 + 11 + 25, 54, 16, 40, 9, 13}, /* OK */
+ {GUI_RESTEXT, 0x01, GWF_BUTTON, 30 + (260 / 2), 20 + 25 + 25 + 11 + 25, 54, 16, 50, 7}, /* Cancel */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+const GuiWidget save_load_dialog[] = {
+ {GUI_STAT, 0xFF, GWF_DEFAULT | GWF_PARENT, 30, 20, 260, 124, 0, 0},
+ {GUI_RESTEXT, 0x01, 0, 10, 7, 240, 16, 0, 1}, /* How may I serve you? */
+ {GUI_RESTEXT, 0x02, 0, 10, 7, 240, 16, 0, 2}, /* Select a game to LOAD */
+ {GUI_RESTEXT, 0x04, 0, 10, 7, 240, 16, 0, 3}, /* Name your SAVE game */
+
+ {GUI_STAT, 0xFF, GWF_DEFAULT, 6, 20, 170, 96, 0, 0},
+ {GUI_UPDOWNARROW, 0x01, GWF_BUTTON, 180, 24, 16, 40, 0, 0}, /* Up (dummy) */
+ {GUI_UPDOWNARROW, 0x01, GWF_BUTTON, 180, 72, 16, 40, 0, 1}, /* Down (dummy) */
+ {GUI_UPDOWNARROW, 0xFE, GWF_BUTTON, 180, 24, 16, 40, 1, 0}, /* Up */
+ {GUI_UPDOWNARROW, 0xFE, GWF_BUTTON, 180, 72, 16, 40, 2, 1}, /* Down */
+
+ {GUI_RESTEXT, 0x06, GWF_CLEARBG, 10, 24, 160, 10, 20, 0},
+ {GUI_RESTEXT, 0x06, GWF_CLEARBG, 10, 34, 160, 10, 21, 0},
+ {GUI_RESTEXT, 0x06, GWF_CLEARBG, 10, 44, 160, 10, 22, 0},
+ {GUI_RESTEXT, 0x06, GWF_CLEARBG, 10, 54, 160, 10, 23, 0},
+ {GUI_RESTEXT, 0x06, GWF_CLEARBG, 10, 64, 160, 10, 24, 0},
+ {GUI_RESTEXT, 0x06, GWF_CLEARBG, 10, 74, 160, 10, 25, 0},
+ {GUI_RESTEXT, 0x06, GWF_CLEARBG, 10, 84, 160, 10, 26, 0},
+ {GUI_RESTEXT, 0x06, GWF_CLEARBG, 10, 94, 160, 10, 27, 0},
+ {GUI_RESTEXT, 0x06, GWF_CLEARBG, 10, 104, 160, 10, 28, 0},
+
+ {GUI_RESTEXT, 0x01, GWF_BUTTON, 200, 20, 54, 16, 3, 4, 'S'}, /* Save */
+ {GUI_RESTEXT, 0x01, GWF_BUTTON, 200, 40, 54, 16, 4, 5, 'L'}, /* Load */
+ {GUI_RESTEXT, 0x01, GWF_BUTTON, 200, 60, 54, 16, 5, 6, 'P'}, /* Play */
+ {GUI_CUSTOMTEXT, 0x01, GWF_BUTTON, 200, 80, 54, 16, 9, 17, 'O'}, /* Options */
+ {GUI_RESTEXT, 0x01, GWF_BUTTON, 200, 100, 54, 16, 6, 8, 'Q'}, /* Quit */
+
+ {GUI_RESTEXT, 0x02, GWF_BUTTON, 200, 60, 54, 16, 7, 7}, /* Cancel */
+
+ {GUI_RESTEXT, 0x04, GWF_BUTTON, 200, 40, 54, 16, 8, 9}, /* Ok */
+ {GUI_RESTEXT, 0x04, GWF_BUTTON, 200, 60, 54, 16, 7, 7}, /* Cancel */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+const GuiWidget pause_dialog[] = {
+ {GUI_RESTEXT, 0x01, GWF_DEFAULT, 50, 80, 220, 16, 0, 10},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+
+void Gui::draw(int start, int end)
+{
+ int i;
+
+ if (end == -1)
+ end = start;
+
+ for (i = 0; i < (int)(sizeof(_widgets) / sizeof(_widgets[0])); i++) {
+ const GuiWidget *w = _widgets[i];
+ if (w) {
+ _parentX = 0;
+ _parentY = 0;
+ while (w->_type != GUI_NONE) {
+ if (w->_id >= start && w->_id <= end && (w->_page & (1 << _cur_page))) {
+ drawWidget(w);
+ }
+ if (w->_flags & GWF_PARENT) {
+ _parentX += w->_x;
+ _parentY += w->_y;
+ }
+ w++;
+ }
+ }
+ }
+}
+
+const GuiWidget *Gui::widgetFromPos(int x, int y)
+{
+ int i;
+
+ for (i = sizeof(_widgets) / sizeof(_widgets[0]) - 1; i >= 0; i--) {
+ const GuiWidget *w = _widgets[i];
+ if (w) {
+ while (w->_type != GUI_NONE) {
+ if ((w->_page & (1 << _cur_page)) && w->_id &&
+ (uint16)(x - w->_x) < w->_w && (uint16)(y - w->_y) < w->_h)
+ return w;
+ if (w->_flags & GWF_PARENT) {
+ x -= w->_x;
+ y -= w->_y;
+ }
+ w++;
+ }
+ }
+ }
+ return NULL;
+}
+
+void Gui::drawChar(const char str, int xx, int yy)
+{
+ unsigned int buffer = 0, mask = 0, x, y;
+ byte *tmp;
+ int tempc = _color;
+ _color = _textcolor;
+
+ tmp = &guifont[0];
+ tmp += 224 + (str + 1) * 8;
+
+ byte *ptr = getBasePtr(xx, yy);
+ if (ptr == NULL)
+ return;
+
+ for (y = 0; y < 8; y++) {
+ for (x = 0; x < 8; x++) {
+ unsigned char color;
+ if ((mask >>= 1) == 0) {
+ buffer = *tmp++;
+ mask = 0x80;
+ }
+ color = ((buffer & mask) != 0);
+ if (color)
+ ptr[x] = _color;
+ }
+ ptr += 320;
+ }
+ _color = tempc;
+
+}
+void Gui::drawString(const char *str, int x, int y, int w, byte color, bool center)
+{
+ StringTab *st = &_s->string[5];
+ st->charset = 1;
+ st->center = center;
+ st->color = color;
+ st->xpos = x;
+ st->ypos = y;
+ st->right = x + w;
+
+ if (_s->_gameId) { /* If a game is active.. */
+ _s->_messagePtr = (byte *)str;
+ _s->drawString(5);
+ } else {
+ for (uint letter = 0; letter < strlen(str); letter++)
+ drawChar(str[letter], st->xpos + (letter * 8), st->ypos);
+ }
+}
+
+void Gui::drawWidget(const GuiWidget *w)
+{
+ const char *s;
+ int x, y;
+
+ x = w->_x;
+ y = w->_y;
+
+ if (w->_flags & GWF_CLEARBG)
+ widgetClear(w);
+
+ if (w->_flags & GWF_BORDER) {
+ widgetBorder(w);
+ x += 4;
+ y += 4;
+ }
+
+ switch (w->_type) {
+ case GUI_CUSTOMTEXT:
+ case GUI_VARTEXT:
+ case GUI_KEYTEXT:
+ case GUI_ACTIONTEXT:
+ case GUI_RESTEXT:
+ case GUI_NEXTTEXT:
+ {
+ char text[500];
+ text[0] = '\0';
+
+ switch (w->_type) {
+ case GUI_CUSTOMTEXT:
+ strcpy(text, string_map_table_custom[w->_string_number]);
+ break;
+ case GUI_RESTEXT:
+ s = queryString(w->_string_number, w->_id);
+ if (s)
+ strcpy(text, s);
+ break;
+ case GUI_VARTEXT:
+ sprintf(text, "%s %d", string_map_table_custom[w->_string_number],
+ _gui_variables[w->_string_number]);
+ break;
+ case GUI_SCROLLTEXT:
+ sprintf(text, "%s", _gui_scroller);
+ break;
+#ifdef _WIN32_WCE
+ case GUI_KEYTEXT:
+ strcpy(text, getGAPIKeyName(getAction((_current_page * 5) + w->_string_number - 1)->action_key));
+ break;
+ case GUI_ACTIONTEXT:
+ strcpy(text, getActionName(getAction((_current_page * 5) + w->_string_number - 1)->action_type));
+ break;
+ case GUI_NEXTTEXT:
+ if (_current_page == 0)
+ strcpy(text, "Next");
+ else
+ strcpy(text, "Prev");
+ break;
+
+#endif
+ }
+
+ if (*text) {
+ drawString(text, x + _parentX, y + _parentY, w->_w,
+ (_clickWidget && _clickWidget == w->_id) ? _textcolorhi : _textcolor, false);
+ }
+ break;
+ }
+ case GUI_IMAGE:
+ break;
+ case GUI_UPDOWNARROW:
+ case GUI_CHECKBOX:
+ {
+ uint32 *data;
+ byte color = (_clickWidget && _clickWidget == w->_id) ? _textcolorhi : _textcolor;
+
+ if (w->_type == GUI_UPDOWNARROW) {
+ if (w->_string_number == 0)
+ data = up_arrow;
+ else
+ data = down_arrow;
+ // if not an updownarrow, it must be a checkbox
+ } else {
+ data = checked_img;
+ }
+
+ // Center the image
+ x += w->_w / 2 - IMG_SIZE / 2;
+ y += w->_h / 2 - IMG_SIZE / 2;
+ if (w->_flags & GWF_BORDER) {
+ x -= 4;
+ y -= 4;
+ }
+
+ byte *ptr = getBasePtr(x, y);
+ if (ptr == NULL)
+ return;
+
+ // If the checkbox is checked, or this is not a checkbox, draw the image
+ if ((getCheckboxChecked(w->_id) == true) || (w->_type != GUI_CHECKBOX)) {
+ for (int y2 = 0; y2 < IMG_SIZE; y2++) {
+ uint32 mask = 0xF0000000;
+ for (int x2 = 0; x2 < IMG_SIZE; x2++) {
+ if (data[y2] & mask)
+ ptr[x2] = color;
+ mask >>= 4;
+ }
+ ptr += 320;
+ }
+ }
+ }
+ break;
+ }
+}
+
+void Gui::widgetClear(const GuiWidget *wid)
+{
+ int x = wid->_x;
+ int y = wid->_y;
+ int w = wid->_w;
+ int h = wid->_h;
+ int i;
+
+ byte *ptr = getBasePtr(x, y);
+ if (ptr == NULL)
+ return;
+
+ _s->setVirtscreenDirty(_vs, x + _parentX, y + _parentY, x + _parentX + w, y + _parentY + h);
+
+ if (wid->_flags & GWF_BORDER) {
+ // Inset by 1 pixel in all directions
+ ptr += 320 + 1;
+ w -= 2;
+ h -= 2;
+ }
+
+ while (h--) {
+ for (i = 0; i < w; i++)
+ ptr[i] = _bgcolor;
+ ptr += 320;
+ }
+}
+
+void Gui::widgetBorder(const GuiWidget *w)
+{
+ box(w->_x, w->_y, w->_w, w->_h);
+}
+
+void Gui::box(int x, int y, int width, int height)
+{
+ hline(x + 1, y, x + width - 2, _color);
+ hline(x, y + 1, x + width - 1, _color);
+ vline(x, y + 1, y + height - 2, _color);
+ vline(x + 1, y, y + height - 1, _color);
+
+ hline(x + 1, y + height - 2, x + width - 1, _shadowcolor);
+ hline(x + 1, y + height - 1, x + width - 2, _shadowcolor);
+ vline(x + width - 1, y + 1, y + height - 2, _shadowcolor);
+ vline(x + width - 2, y + 1, y + height - 1, _shadowcolor);
+}
+
+byte *Gui::getBasePtr(int x, int y)
+{
+ x += _parentX;
+ y += _parentY;
+ _vs = _s->findVirtScreen(y);
+
+ if (_vs == NULL)
+ return NULL;
+
+ return _vs->screenPtr + x + (y - _vs->topline) * 320 +
+ _s->_screenStartStrip * 8 + (_s->camera._cur.y - 100) * 320;
+}
+
+void Gui::line(int x, int y, int x2, int y2, byte color)
+{
+ byte *ptr;
+
+ if (x2 < x)
+ x2 ^= x ^= x2 ^= x; // Swap x2 and x
+
+ if (y2 < y)
+ y2 ^= y ^= y2 ^= y; // Swap y2 and y
+
+ ptr = getBasePtr(x, y);
+
+ if (ptr == NULL)
+ return;
+
+ if (x == x2) {
+ /* vertical line */
+ while (y++ <= y2) {
+ *ptr = color;
+ ptr += 320;
+ }
+ } else if (y == y2) {
+ /* horizontal line */
+ while (x++ <= x2) {
+ *ptr++ = color;
+ }
+ }
+}
+
+void Gui::leftMouseClick(int x, int y)
+{
+ const GuiWidget *w = widgetFromPos(x, y);
+ int old;
+
+ _clickTimer = 0;
+
+ old = _clickWidget;
+ _clickWidget = w ? w->_id : 0;
+
+ if (old)
+ draw(old);
+ if (_clickWidget) {
+ draw(_clickWidget);
+ if (w->_flags & GWF_DELAY)
+ _clickTimer = 5;
+ else
+ handleCommand(_clickWidget);
+ }
+
+ if (_dialog == PAUSE_DIALOG)
+ close();
+}
+
+void Gui::handleSoundDialogCommand(int cmd)
+{
+ if (cmd == 50) {
+ close();
+ } else if (cmd == 40) {
+ _s->_sound->_sound_volume_master = _gui_variables[0]; // Master
+ _s->_sound->_sound_volume_music = _gui_variables[1]; // Music
+ _s->_sound->_sound_volume_sfx = _gui_variables[2]; // SFX
+
+ _s->_imuse->set_music_volume(_s->_sound->_sound_volume_music);
+ _s->_imuse->set_master_volume(_s->_sound->_sound_volume_master);
+ _s->_mixer->set_volume(_s->_sound->_sound_volume_sfx);
+ _s->_mixer->set_music_volume(_s->_sound->_sound_volume_music);
+
+ scummcfg->set("master_volume", _s->_sound->_sound_volume_master);
+ scummcfg->set("music_volume", _s->_sound->_sound_volume_music);
+ scummcfg->set("sfx_volume", _s->_sound->_sound_volume_sfx);
+ scummcfg->flush();
+
+ close();
+ } else {
+ if ((cmd % 10) == 1) {
+ _gui_variables[cmd / 10] += 5;
+ if (_gui_variables[cmd / 10] > 256)
+ _gui_variables[cmd / 10] = 256;
+ } else {
+ _gui_variables[cmd / 10] -= 5;
+ if (_gui_variables[cmd / 10] < 0)
+ _gui_variables[cmd / 10] = 0;
+ }
+
+ draw((cmd / 10) * 10 + 3, (cmd / 10) * 10 + 3);
+ }
+}
+
+void Gui::handleOptionsDialogCommand(int cmd)
+{
+ switch (cmd) {
+ case 1:
+ _widgets[0] = sound_dialog;
+ _gui_variables[0] = _s->_sound->_sound_volume_master;
+ _gui_variables[1] = _s->_sound->_sound_volume_music;
+ _gui_variables[2] = _s->_sound->_sound_volume_sfx;
+ _active = true;
+ _cur_page = 0;
+ _dialog = SOUND_DIALOG;
+ draw(0, 100);
+ return;
+ case 2:
+ _key_mapping_required = 0;
+ get_key_mapping = true;
+ _widgets[0] = keys_dialog;
+ _active = true;
+ _cur_page = 0;
+ _dialog = KEYS_DIALOG;
+ draw(0, 200);
+ return;
+ case 3:
+ _widgets[0] = about_dialog;
+ _active = true;
+ _cur_page = 0;
+ _return_to = 0;
+ _dialog = ABOUT_DIALOG;
+ draw(0, 100);
+ return;
+ case 4:
+ _widgets[0] = misc_dialog;
+ _active = true;
+ _cur_page = 0;
+ _return_to = 0;
+ _dialog = MISC_DIALOG;
+ clearCheckboxes();
+ setCheckbox(!(_s->_noSubtitles), 1);
+ if (_s->_features & GF_AMIGA)
+ setCheckbox(true, 5);
+ else
+ setCheckbox(false, 5);
+ draw(0, 100);
+ return;
+ }
+}
+
+void Gui::handleMiscDialogCommand(int cmd)
+{
+ switch (cmd) {
+ case 1:
+ if ((getCheckboxChecked(1)) == true)
+ setCheckbox(false, 1);
+ else
+ setCheckbox(true, 1);
+ draw(1, 1);
+ return;
+ case 5:
+ if (getCheckboxChecked(5) == true)
+ setCheckbox(false, 5);
+ else
+ setCheckbox(true, 5);
+ draw(5, 5);
+ return;
+ case 3:
+ case 4:
+ // OK button - perform the actions of the checkboxes
+ if (cmd == 3) {
+ // The opposite of the checkbox(1) is set because the internal variable is 'no subtitles' but
+ // a "Show subtitles" option makes more usability sense
+ _s->_noSubtitles = (!getCheckboxChecked(1));
+
+ // Amiga pallete conversion checkbox
+ if (getCheckboxChecked(5))
+ _s->_features = _s->_features | GF_AMIGA;
+ else
+ _s->_features = _s->_features & ~GF_AMIGA;
+ _s->_fullRedraw = true;
+ }
+ close();
+ }
+}
+
+void Gui::handleKeysDialogCommand(int cmd)
+{
+#ifdef _WIN32_WCE
+ if (cmd < 100 && cmd != 60 && cmd != 61) {
+
+ if ((cmd % 10) == 1)
+ setNextType((_current_page * 5) + (cmd / 10) - 1);
+ else
+ setPreviousType((_current_page * 5) + (cmd / 10) - 1);
+
+ draw(0, 200);
+
+ return;
+ }
+
+ if (cmd >= 100)
+ _key_mapping_required = cmd;
+
+ if (cmd == 60) {
+ get_key_mapping = false;
+ save_key_mapping();
+ close();
+ }
+
+ if (cmd == 61) {
+ if (!_current_page)
+ _current_page = 1;
+ else
+ _current_page = 0;
+ draw(0, 200);
+ return;
+ }
+#else
+ close();
+#endif
+}
+
+void Gui::handleLauncherDialogCommand(int cmd)
+{
+ debug(9, "handle launcher command\n");
+ switch (cmd) {
+ case 20:
+ close();
+ break;
+ case 21:
+ // Nothing yet
+ break;
+ case 22:
+ _widgets[0] = about_dialog;
+ _active = true;
+ _cur_page = 0;
+ _return_to = LAUNCHER_DIALOG;
+ _dialog = ABOUT_DIALOG;
+ draw(0, 100);
+ debug(9, "about dialog\n");
+ break;
+ default:
+ debug(9, "default\n");
+ close();
+ }
+}
+
+void Gui::handleCommand(int cmd)
+{
+ int lastEdit = _editString;
+ showCaret(false);
+
+ switch (_dialog) {
+ case LAUNCHER_DIALOG:
+ handleLauncherDialogCommand(cmd);
+ return;
+ case SOUND_DIALOG:
+ handleSoundDialogCommand(cmd);
+ return;
+ case OPTIONS_DIALOG:
+ handleOptionsDialogCommand(cmd);
+ return;
+ case MISC_DIALOG:
+ handleMiscDialogCommand(cmd);
+ return;
+ case KEYS_DIALOG:
+ handleKeysDialogCommand(cmd);
+ return;
+ case ABOUT_DIALOG:
+ if (_return_to == LAUNCHER_DIALOG) {
+ _widgets[0] = launcher_dialog;
+ _active = true;
+ _cur_page = 0;
+ _dialog = LAUNCHER_DIALOG;
+ draw(0, 100);
+ } else
+ close();
+ return;
+ }
+
+ // If we get here, it's the SAVELOAD_DIALOG
+
+ switch (cmd) {
+ case 1: /* up button */
+ if (_slotIndex - 9 < 0)
+ return;
+ getSavegameNames(_slotIndex - 9);
+ draw(20, 28);
+ return;
+ case 2: /* down button */
+ if (_slotIndex + 9 > 80)
+ return;
+ getSavegameNames(_slotIndex + 9);
+ draw(20, 28);
+ return;
+ case 3: /* save button */
+ _cur_page = 2;
+ getSavegameNames(1); /* Start at 1, since slot 0 is reserved for autosave */
+ draw(0, 100);
+ return;
+ case 4: /* load button */
+ _cur_page = 1;
+ getSavegameNames(0);
+ draw(0, 100);
+ return;
+ case 5: /* play button */
+ close();
+ return;
+ case 6: /* quit button */
+#ifdef _WIN32_WCE
+ do_quit();
+#endif
+ exit(1);
+ return;
+ case 7: /* cancel button */
+ _cur_page = 0;
+ draw(0, 100);
+ return;
+ case 8: /* ok button (save game) */
+ if (lastEdit == -1 || game_names[lastEdit][0] == 0)
+ return;
+
+ _s->_saveLoadSlot = lastEdit + _slotIndex;
+ _s->_saveLoadCompatible = false;
+ _s->_saveLoadFlag = 1;
+ memcpy(_s->_saveLoadName, game_names[lastEdit], sizeof(_s->_saveLoadName));
+ close();
+ return;
+ case 9: /* options button */
+ options();
+ draw(0, 100);
+ return;
+ default:
+ if (cmd >= 20 && cmd <= 28) {
+ if (_cur_page == 1) {
+ if (valid_games[cmd - 20]) {
+ _s->_saveLoadSlot = cmd - 20 + _slotIndex;
+ _s->_saveLoadCompatible = false;
+ _s->_saveLoadFlag = 2;
+ close();
+ }
+ return;
+ } else if (_cur_page == 2) {
+ _clickWidget = cmd;
+ editString(cmd - 20);
+ }
+ }
+ }
+
+}
+
+void Gui::getSavegameNames(int start)
+{
+ int i;
+ _slotIndex = start;
+
+ for (i = 0; i < 9; i++) {
+ valid_games[i] = _s->getSavegameName(start + i, game_names[i]);
+ }
+}
+
+const char *Gui::queryString(int stringno, int id)
+{
+ static char namebuf[64];
+ char *result;
+ int string;
+
+ if (id >= 20 && id <= 28) {
+ // Save game names
+ sprintf(namebuf, "%2d. %s", id - 20 + _slotIndex, game_names[id - 20]);
+ return namebuf;
+ }
+
+ if (stringno == 0)
+ return NULL;
+
+ if (_s->_features & GF_AFTER_V7)
+ string = _s->_vars[string_map_table_v7[stringno - 1].num];
+ else if (_s->_features & GF_AFTER_V6)
+ string = _s->_vars[string_map_table_v6[stringno - 1].num];
+ else
+ string = string_map_table_v5[stringno - 1].num;
+
+ result = (char *)_s->getStringAddress(string);
+
+ if (!result) { // Gracelessly degrade to english :)
+ if (_s->_features & GF_AFTER_V6)
+ return string_map_table_v6[stringno - 1].string;
+ else
+ return string_map_table_v5[stringno - 1].string;
+ }
+
+ return result;
+}
+
+void Gui::showCaret(bool show)
+{
+ int i;
+ char *s;
+
+ if (_editString == -1)
+ return;
+
+ i = _editLen;
+ s = game_names[_editString];
+
+ if (show) {
+ if (i < SAVEGAME_NAME_LEN - 1) {
+ s[i] = '_';
+ s[i + 1] = 0;
+ }
+ } else {
+ s[i] = 0;
+ }
+
+ draw(_editString + 20);
+
+ if (!show)
+ _editString = -1;
+}
+
+void Gui::editString(int i)
+{
+ char *s = game_names[i];
+ if (!valid_games[i]) {
+ valid_games[i] = true;
+ *s = 0;
+ }
+ _editString = i;
+ _editLen = strlen(s);
+ showCaret(true);
+}
+
+void Gui::addLetter(byte letter)
+{
+ switch (_dialog) {
+ case SAVELOAD_DIALOG:
+ if (_editString == -1)
+ return;
+
+/*
+ FIXME - this code here has no effect at all, since Scumm::convertKeysToClicks()
+ swallows all return key events.
+ // Return pressed?
+ if (letter == '\n' || letter == '\r') {
+ handleCommand(8);
+ return;
+ }
+*/
+
+ if (letter >= 32 && letter < 128 && _editLen < SAVEGAME_NAME_LEN - 1) {
+ game_names[_editString][_editLen++] = letter;
+ } else if (letter == 8 && _editLen > 0) {
+ _editLen--;
+ }
+ showCaret(true);
+ break;
+ case PAUSE_DIALOG:
+ if (letter == 32)
+ close();
+ break;
+
+#ifdef _WIN32_WCE
+ case KEYS_DIALOG:
+ clearActionKey(letter);
+ if (_key_mapping_required)
+ getAction((_current_page * 5) + _key_mapping_required - 100)->action_key = letter;
+ _key_mapping_required = 0;
+ draw(0, 200);
+ break;
+#endif
+ }
+}
+
+bool Gui::getCheckboxChecked(int id)
+{
+ return _cbox_checked[id];
+}
+
+void Gui::setCheckbox(bool state, int id)
+{
+ _cbox_checked[id] = state;
+}
+
+void Gui::clearCheckboxes()
+{
+ for (int id = 0; id <= 100; id++) {
+ _cbox_checked[id] = false;
+ }
+}
+
+void Gui::init(Scumm *s)
+{
+ /* Default GUI colors */
+ _bgcolor = 0;
+ _color = 0;
+ _textcolor = 8; // 15 is nice
+ _textcolorhi = 15;
+ _shadowcolor = 0;
+ _s = s;
+
+ strcpy(_gui_scroller, "Brought to you by:");
+}
+
+void Gui::loop()
+{
+ if (_active && !_inited) {
+ _inited = true;
+ draw(0, 200); // was 100
+ _old_soundsPaused = _s->_sound->_soundsPaused;
+ _s->_sound->pauseSounds(true);
+
+ // Backup old cursor
+ memcpy(_old_grabbedCursor, _s->_grabbedCursor, sizeof(_old_grabbedCursor));
+ _old_cursorWidth = _s->_cursorWidth;
+ _old_cursorHeight = _s->_cursorHeight;
+ _old_cursorHotspotX = _s->_cursorHotspotX;
+ _old_cursorHotspotY = _s->_cursorHotspotY;
+ _old_cursor_mode = _s->_system->show_mouse(true);
+
+ _s->_cursorAnimate++;
+ _s->gdi._cursorActive = 1;
+ }
+ _s->animateCursor();
+ _s->getKeyInput(0);
+ if (_s->_mouseButStat & MBS_LEFT_CLICK) {
+ leftMouseClick(_s->mouse.x, _s->mouse.y);
+ } else if (_s->_lastKeyHit) {
+ if (_dialog != KEYS_DIALOG) {
+ if (_s->_lastKeyHit == 27)
+ close();
+ else {
+ addLetter((unsigned char)_s->_lastKeyHit);
+ checkHotKey(_s->_lastKeyHit);
+ }
+#ifdef _WIN32_WCE
+ } else if (_s->_lastKeyHit > 1000) { // GAPI
+ addLetter(_s->_lastKeyHit - 1000);
+#endif
+ }
+ }
+
+ if (_clickTimer && !--_clickTimer) {
+ int old = _clickWidget;
+ _clickWidget = 0;
+ draw(old);
+ handleCommand(old);
+ }
+
+ _s->drawDirtyScreenParts();
+ _s->_mouseButStat = 0;
+}
+
+void Gui::close()
+{
+ _s->_fullRedraw = true;
+ _s->_completeScreenRedraw = true;
+ _s->_cursorAnimate--;
+
+ // Restore old cursor
+ memcpy(_s->_grabbedCursor, _old_grabbedCursor, sizeof(_old_grabbedCursor));
+ _s->_cursorWidth = _old_cursorWidth;
+ _s->_cursorHeight = _old_cursorHeight;
+ _s->_cursorHotspotX = _old_cursorHotspotX;
+ _s->_cursorHotspotY = _old_cursorHotspotY;
+ _s->updateCursor();
+
+ _s->_system->show_mouse(_old_cursor_mode);
+
+ _s->_sound->pauseSounds(_old_soundsPaused);
+ _active = false;
+ _inited = false;
+
+#ifdef _WIN32_WCE
+
+ // Option dialog can be accessed from the file dialog now, always check
+ if (save_hide_toolbar) {
+ do_hide(true);
+ save_hide_toolbar = false;
+ }
+ if (keyboard_override) {
+ keyboard_override = false;
+ draw_keyboard = false;
+ toolbar_drawn = false;
+ }
+#endif
+}
+
+void Gui::checkHotKey(int keycode)
+{
+ byte page;
+ for (int i = 0; i < (int)(sizeof(_widgets) / sizeof(_widgets[0])); i++) {
+ const GuiWidget *w = _widgets[i];
+ if (w) {
+ while (w->_type != GUI_NONE) {
+
+ // This rubbish is needed because the current page is 0 when really it should be 1
+ if (_cur_page == 0)
+ page = 1;
+ else
+ page = _cur_page;
+
+ // Only check for widgets that are on the current GUI page (otherwise save dialog problems occur)
+ if (w->_page == page) {
+ // Check the actual key pressed, and the uppercase version. For people who have caps lock on
+ if (keycode == w->_hotkey || toupper(keycode) == w->_hotkey)
+ handleCommand(w->_id);
+ }
+ w++;
+ }
+ }
+ }
+}
+
+void Gui::saveLoadDialog()
+{
+ _widgets[0] = save_load_dialog;
+ _editString = -1;
+ _active = true;
+ _cur_page = 0;
+ _dialog = SAVELOAD_DIALOG;
+
+#ifdef _WIN32_WCE
+ save_hide_toolbar = hide_toolbar;
+ if (save_hide_toolbar) {
+ // Display the keyboard while the dialog is running
+ do_hide(false);
+ }
+ if (!draw_keyboard) {
+ keyboard_override = true;
+ draw_keyboard = true;
+ toolbar_drawn = false;
+ }
+#endif
+
+}
+
+void Gui::pause()
+{
+ _widgets[0] = pause_dialog;
+ _active = true;
+ _cur_page = 0;
+ _dialog = PAUSE_DIALOG;
+}
+
+void Gui::options()
+{
+#ifdef _WIN32_WCE
+ _current_page = 0;
+#endif
+ _widgets[0] = options_dialog;
+ _active = true;
+ _cur_page = 0;
+ _dialog = OPTIONS_DIALOG;
+}
+
+void Gui::launcher()
+{
+ _widgets[0] = launcher_dialog;
+ _active = true;
+ _cur_page = 0;
+ _dialog = LAUNCHER_DIALOG;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+void Gui::loop()
+{
+ if (_active && !_inited) {
+ _inited = true;
+ _old_soundsPaused = _s->_soundsPaused;
+ _s->pauseSounds(true);
+
+ // Backup old cursor
+ memcpy(_old_grabbedCursor, _s->_grabbedCursor, sizeof(_old_grabbedCursor));
+ _old_cursorWidth = _s->_cursorWidth;
+ _old_cursorHeight = _s->_cursorHeight;
+ _old_cursorHotspotX = _s->_cursorHotspotX;
+ _old_cursorHotspotY = _s->_cursorHotspotY;
+ _old_cursor_mode = _s->_system->show_mouse(true);
+
+ _s->_cursorAnimate++;
+ _s->gdi._cursorActive = 1;
+ }
+ _s->animateCursor();
+ _s->getKeyInput(0);
+
+ _s->drawDirtyScreenParts();
+ _s->_mouseButStat = 0;
+}
+*/
diff --git a/gui/gui.h b/gui/gui.h
new file mode 100644
index 0000000000..b7755cf226
--- /dev/null
+++ b/gui/gui.h
@@ -0,0 +1,124 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#ifndef GUI_H
+#define GUI_H
+
+// Forward declaration for GuiWidget
+struct GuiWidget;
+
+#define SAVEGAME_NAME_LEN 32
+
+class Gui {
+public:
+ byte _color,_shadowcolor;
+ byte _bgcolor;
+ byte _textcolor;
+ byte _textcolorhi;
+
+ // Init
+ void init(Scumm *s);
+
+ // Dialogs
+ void saveLoadDialog();
+ void pause();
+ void options();
+ void launcher();
+
+ void loop();
+
+ bool isActive() { return _active; }
+
+protected:
+ Scumm *_s;
+ const GuiWidget *_widgets[4];
+ int _return_to;
+ VirtScreen *_vs;
+ int _parentX, _parentY;
+ bool _active;
+ bool _inited;
+ byte _clickTimer;
+ byte _cur_page;
+ byte _dialog;
+ int _clickWidget;
+ char *_queryMess;
+ bool _old_soundsPaused;
+
+ // mouse cursor state
+ bool _old_cursor_mode;
+ int _old_cursorHotspotX, _old_cursorHotspotY, _old_cursorWidth, _old_cursorHeight;
+ byte _old_grabbedCursor[2048];
+
+ // optiondialog specifics
+ int _gui_variables[100];
+
+ // checkboxes
+ bool _cbox_checked[100];
+ const char *_cbox_cfg_key[100];
+
+ // savedialog specifics
+ int _slotIndex;
+ int _editString;
+ int _editLen;
+ bool valid_games[9];
+ char game_names[9][SAVEGAME_NAME_LEN];
+
+ // Drawing
+ void draw(int start, int end);
+ void draw(int item) { draw(item,-1); }
+ void drawWidget(const GuiWidget *w);
+
+ void line(int x, int y, int x2, int y2, byte color);
+ void box(int x, int y, int width, int height);
+
+ //void hline(int x, int y, int x2, byte color);
+ //void vline(int x, int y, int y2, byte color);
+ void drawChar(const char str, int xx, int yy);
+ void drawString(const char *str, int x, int y, int w, byte color, bool center);
+ void widgetClear(const GuiWidget *w);
+ void widgetBorder(const GuiWidget *w);
+ byte *getBasePtr(int x, int y);
+ const GuiWidget *widgetFromPos(int x, int y);
+
+ // Actions
+ void leftMouseClick(int x, int y);
+ void handleCommand(int cmd);
+ void close();
+ const char *queryString(int string, int id);
+ void getSavegameNames(int start);
+ void editString(int index);
+ void showCaret(bool show);
+ void addLetter(byte letter);
+ void queryMessage(const char *msg, const char *alts);
+ byte getDefaultColor(int color);
+ bool getCheckboxChecked(int id);
+ void setCheckbox(bool state, int id);
+ void clearCheckboxes();
+ void checkHotKey(int keycode);
+
+ char _gui_scroller[255];
+
+ void handleSoundDialogCommand(int cmd);
+ void handleOptionsDialogCommand(int cmd);
+ void handleKeysDialogCommand(int cmd);
+ void handleLauncherDialogCommand(int cmd);
+ void handleMiscDialogCommand(int cmd);
+};
+#endif
diff --git a/gui/guimaps.h b/gui/guimaps.h
new file mode 100644
index 0000000000..181dbb6bc9
--- /dev/null
+++ b/gui/guimaps.h
@@ -0,0 +1,157 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#if !defined(guimaps_h)
+#define guimaps_h
+
+struct ResString {
+ int num;
+ char string[80];
+};
+
+// String maps
+static const char* string_map_table_custom[] = {
+ "Master Volume :", //0
+ "Music Volume :", //1
+ "SFX Volume :", //2
+ "+", //3
+ "-", //4
+ "Sound", //5
+ "Keys", //6
+ "About", //7
+ "Pocket ScummVM", //8
+ "Build " SCUMMVM_VERSION " (" SCUMMVM_CVS ")", //9
+ "ScummVM http://scummvm.sourceforge.net", //10
+ "All games (c) LucasArts", //11
+ "Quit", //12
+ "Pause", //13
+ "Save", //14
+ "Skip", //15
+ "Hide", //16
+ "Options", //17
+ "Misc", //18
+ "Show speech subtitles", //19
+ "Amiga palette conversion", //20
+ "Except:", //21
+ "Simon the Sorcerer (c) Adventuresoft", //22
+ "Close" //23
+};
+
+static ResString string_map_table_v7[] = {
+ {96, "game name and version"}, //that's how it's supposed to be
+ {77, "Select a game to LOAD"},
+ {76, "Name your SAVE game"},
+ {70, "save"}, //boot8
+ {71, "load"}, //boot9
+ {72, "play"}, //boot10
+ {73, "cancel"}, //boot11
+ {74, "quit"}, //boot12
+ {75, "ok"}, //boot13
+ {85, "game paused"}, // boot3
+
+ /* this is the almost complete string map for v7
+ {63, "how may I serve you?"},
+ {64, "the dig v1.0"}, //(game name/version)
+ {67, "text display only"},
+ {68, "c:\\dig"}, //boot007 (save path ?)
+ {69, "the dig"}, //boot21 (game name)
+ {70, "save"}, //boot8
+ {71, "load"}, //boot9
+ {72, "play"}, //boot10
+ {73, "cancel"}, //boot11
+ {74, "quit"}, //boot12
+ {75, "ok"}, //boot13
+ {76, "name your save game"}, //boot19
+ {77, "select a game to load"}, //boot20
+ {78, "you must enter a name"},//boot14
+ {79, "saving '%s'"}, //boot17
+ {80, "loading '%s'"}, //boot18
+ {81, "the game was NOT saved"}, //boot15
+ {82, "the game was NOT loaded"}, //boot16
+ {83, "how may I serve you?"},
+ {84, "how may I serve you?"},
+ {85, "game paused"}, // boot3
+ {86, "Are you sure you want to restart"},
+ {87, "Are you sure you want to quit?"}, //boot05
+ {89, "how may I serve you?"},
+ {90, "music"}, //boot22
+ {91, "voice"}, //boot23
+ {92, "sfx"}, //boot24
+ {93, "disabled"}, //boot25
+ {94, "text speed"}, //boot26
+ {95, "text display"}, //boot27
+ {96, "the dig v1.0"},*/
+
+};
+
+static ResString string_map_table_v6[] = {
+ {117, "How may I serve you?"},
+ {109, "Select a game to LOAD"},
+ {108, "Name your SAVE game"},
+ {96, "Save"},
+ {97, "Load"},
+ {98, "Play"},
+ {99, "Cancel"},
+ {100, "Quit"},
+ {101, "Ok"},
+ {93, "Game paused"},
+};
+
+static ResString string_map_table_v5[] = {
+ {28, "How may I serve you?"},
+ {20, "Select a game to LOAD"},
+ {19, "Name your SAVE game"},
+ {7, "Save"},
+ {8, "Load"},
+ {9, "Play"},
+ {10, "Cancel"},
+ {11, "Quit"},
+ {12, "Ok"},
+ {4, "Game paused"}
+};
+
+// Built-in font
+static byte guifont[] = {0,0,99,1,226,8,4,8,6,8,6,0,0,0,0,0,0,0,0,0,0,0,8,2,1,8,0,0,0,0,0,0,0,0,0,0,0,0,4,3,7,8,7,7,8,4,5,5,8,7,4,7,3,8,7,7,7,7,8,7,7,7,7,7,3,4,7,5,7,7,8,7,7,7,7,7,7,7,7,5,7,7,
+7,8,7,7,7,7,7,7,7,7,7,8,7,7,7,5,8,5,8,8,7,7,7,6,7,7,7,7,7,5,6,7,5,8,7,7,7,7,7,7,7,7,7,8,7,7,7,5,3,5,0,8,7,7,7,7,7,7,0,6,7,7,7,5,5,5,7,0,6,8,8,7,7,7,7,7,0,7,7,0,0,
+0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,1,3,6,12,
+24,62,3,0,128,192,96,48,24,124,192,0,0,3,62,24,12,6,3,1,0,192,124,24,48,96,192,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,74,72,0,0,0,0,0,128,128,128,0,0,0,0,0,0,0,0,0,0,0,0,0,60,66,153,161,161,153,66,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,96,96,96,96,0,0,96,0,102,102,102,0,0,0,0,0,102,102,255,102,255,102,102,0,24,62,96,60,6,124,24,0,98,102,12,24,48,102,70,0,60,102,60,56,103,102,63,0,96,48,16,0,0,0,0,0,24,48,96,96,96,48,24,0,96,48,24,24,24,48,96,0,
+0,102,60,255,60,102,0,0,0,24,24,126,24,24,0,0,0,0,0,0,0,48,48,96,0,0,0,126,0,0,0,0,0,0,0,0,0,96,96,0,0,3,6,12,24,48,96,0,60,102,102,102,102,102,60,0,24,24,56,24,24,24,126,0,60,102,6,12,48,96,126,0,60,102,6,28,6,102,60,0,6,
+14,30,102,127,6,6,0,126,96,124,6,6,102,60,0,60,102,96,124,102,102,60,0,126,102,12,24,24,24,24,0,60,102,102,60,102,102,60,0,60,102,102,62,6,102,60,0,0,0,96,0,0,96,0,0,0,0,48,0,0,48,48,96,14,24,48,96,48,24,14,0,0,0,120,0,120,0,0,0,112,24,
+12,6,12,24,112,0,60,102,6,12,24,0,24,0,0,0,0,255,255,0,0,0,24,60,102,126,102,102,102,0,124,102,102,124,102,102,124,0,60,102,96,96,96,102,60,0,120,108,102,102,102,108,120,0,126,96,96,120,96,96,126,0,126,96,96,120,96,96,96,0,60,102,96,110,102,102,60,0,102,102,102,
+126,102,102,102,0,120,48,48,48,48,48,120,0,30,12,12,12,12,108,56,0,102,108,120,112,120,108,102,0,96,96,96,96,96,96,126,0,99,119,127,107,99,99,99,0,102,118,126,126,110,102,102,0,60,102,102,102,102,102,60,0,124,102,102,124,96,96,96,0,60,102,102,102,102,60,14,0,124,102,102,124,
+120,108,102,0,60,102,96,60,6,102,60,0,126,24,24,24,24,24,24,0,102,102,102,102,102,102,60,0,102,102,102,102,102,60,24,0,99,99,99,107,127,119,99,0,102,102,60,24,60,102,102,0,102,102,102,60,24,24,24,0,126,6,12,24,48,96,126,0,120,96,96,96,96,96,120,0,3,6,12,24,48,
+96,192,0,120,24,24,24,24,24,120,0,0,0,0,0,0,219,219,0,0,0,0,0,0,0,0,255,102,102,102,0,0,0,0,0,0,0,60,6,62,102,62,0,0,96,96,124,102,102,124,0,0,0,60,96,96,96,60,0,0,6,6,62,102,102,62,0,0,0,60,102,126,96,60,0,0,14,24,62,24,24,
+24,0,0,0,62,102,102,62,6,124,0,96,96,124,102,102,102,0,0,48,0,112,48,48,120,0,0,12,0,12,12,12,12,120,0,96,96,108,120,108,102,0,0,112,48,48,48,48,120,0,0,0,102,127,127,107,99,0,0,0,124,102,102,102,102,0,0,0,60,102,102,102,60,0,0,0,124,102,102,124,96,
+96,0,0,62,102,102,62,6,6,0,0,124,102,96,96,96,0,0,0,62,96,60,6,124,0,0,24,126,24,24,24,14,0,0,0,102,102,102,102,62,0,0,0,102,102,102,60,24,0,0,0,99,107,127,62,54,0,0,0,102,60,24,60,102,0,0,0,102,102,102,62,12,120,0,0,126,12,24,48,126,0,
+24,48,48,96,48,48,24,0,96,96,96,0,96,96,96,0,96,48,48,24,48,48,96,0,0,0,0,0,0,0,0,0,8,12,14,255,255,14,12,8,60,102,96,96,102,60,24,56,102,0,102,102,102,102,62,0,12,24,60,102,126,96,60,0,24,36,60,6,62,102,62,0,102,0,60,6,62,102,62,0,48,
+24,60,6,62,102,62,0,0,0,0,0,0,0,0,0,0,60,96,96,96,60,24,56,24,36,60,102,126,96,60,0,102,0,60,102,126,96,60,0,48,24,60,102,126,96,60,0,0,216,0,112,48,48,120,0,48,72,0,112,48,48,120,0,96,48,0,112,48,48,120,0,102,24,60,102,126,102,102,0,0,0,
+0,0,0,0,0,0,24,48,124,96,120,96,124,0,0,0,108,26,126,216,110,0,30,40,40,126,72,136,142,0,24,36,60,102,102,102,60,0,102,0,60,102,102,102,60,0,48,24,60,102,102,102,60,0,24,36,0,102,102,102,62,0,48,24,102,102,102,102,62,0,0,0,0,0,0,0,0,0,102,60,102,
+102,102,102,60,0,102,0,102,102,102,102,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,24,60,6,62,102,62,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,28,54,54,124,102,102,124,64,0,0,0};
+#endif
diff --git a/gui/newgui.cpp b/gui/newgui.cpp
new file mode 100644
index 0000000000..8b4cca035a
--- /dev/null
+++ b/gui/newgui.cpp
@@ -0,0 +1,541 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "scumm.h"
+#include "newgui.h"
+#include "guimaps.h"
+#include "gui/dialog.h"
+#include "util.h"
+
+/*
+ * TODO list
+ * - implement the missing / incomplete dialogs
+ * - add more widgets
+ * - allow multi line (l/c/r aligned) text via StaticTextWidget ?
+ * - add "close" widget to all dialogs (with a flag to turn it off) ?
+ * - make dialogs "moveable" ?
+ * - come up with a new look&feel / theme for the GUI
+ * - ...
+ */
+
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+
+NewGui::NewGui(Scumm *s) : _s(s), _use_alpha_blending(false),
+ _need_redraw(false),_prepare_for_gui(true),
+ _pauseDialog(0), _saveLoadDialog(0), _aboutDialog(0), _optionsDialog(0),
+ _currentKeyDown(0)
+{
+}
+
+void NewGui::pauseDialog()
+{
+ if (!_pauseDialog)
+ _pauseDialog = new PauseDialog(this);
+ _pauseDialog->open();
+}
+
+void NewGui::saveloadDialog()
+{
+ if (!_saveLoadDialog)
+ _saveLoadDialog = new SaveLoadDialog(this);
+ _saveLoadDialog->open();
+}
+
+void NewGui::aboutDialog()
+{
+ if (!_aboutDialog)
+ _aboutDialog = new AboutDialog(this);
+ _aboutDialog->open();
+}
+
+void NewGui::optionsDialog()
+{
+ if (!_optionsDialog)
+ _optionsDialog = new OptionsDialog(this);
+ _optionsDialog->open();
+}
+
+void NewGui::soundDialog()
+{
+ if (!_soundDialog)
+ _soundDialog = new SoundDialog(this);
+ _soundDialog->open();
+}
+
+void NewGui::loop()
+{
+ Dialog *activeDialog = _dialogStack.top();
+ int i;
+
+ if (_prepare_for_gui) {
+ ClearBlendCache(_s->_currentPalette, 128);
+ saveState();
+ if (_use_alpha_blending)
+ activeDialog->setupScreenBuf();
+#if 1
+ // FIXME - hack to encode our own custom GUI colors. Since we have to live
+ // with a given 8 bit palette, the result is not always as nice as one
+ // would wish, but this is just an experiment after all.
+ _bgcolor = RGBMatch(_s->_currentPalette, 0, 0, 0);
+
+ _color = RGBMatch(_s->_currentPalette, 80, 80, 80);
+ _shadowcolor = RGBMatch(_s->_currentPalette, 64, 64, 64);
+
+ _textcolor = RGBMatch(_s->_currentPalette, 32, 192, 32);
+ _textcolorhi = RGBMatch(_s->_currentPalette, 0, 256, 0);
+#endif
+
+ _eventList.clear();
+ _currentKeyDown = 0;
+
+ _lastClick.x = _lastClick.y = 0;
+ _lastClick.time = 0;
+ _lastClick.count = 0;
+
+ _prepare_for_gui = false;
+ }
+
+ activeDialog->handleTickle();
+
+ if (_need_redraw) {
+ for (i = 0; i < _dialogStack.size(); i++)
+ _dialogStack[i]->draw();
+ _need_redraw = false;
+ }
+
+ _s->animateCursor();
+
+ if (_eventList.size() > 0)
+ {
+ OSystem::Event t;
+
+ for (i = 0; i < _eventList.size(); i++)
+ {
+ t = _eventList[i];
+
+ switch(t.event_code) {
+ case OSystem::EVENT_KEYDOWN:
+ activeDialog->handleKeyDown(t.kbd.ascii, t.kbd.flags);
+
+ // init continuous event stream
+ _currentKeyDown = t.kbd.ascii;
+ _currentKeyDownFlags = t.kbd.flags;
+ _keyRepeatEvenCount = 1;
+ _keyRepeatLoopCount = 0;
+ break;
+ case OSystem::EVENT_KEYUP:
+ activeDialog->handleKeyUp(t.kbd.ascii, t.kbd.flags);
+ if (t.kbd.ascii == _currentKeyDown)
+ // only stop firing events if it's the current key
+ _currentKeyDown = 0;
+ break;
+ case OSystem::EVENT_MOUSEMOVE:
+ activeDialog->handleMouseMoved(t.mouse.x - activeDialog->_x, t.mouse.y - activeDialog->_y, 0);
+ break;
+ // We don't distinguish between mousebuttons (for now at least)
+ case OSystem::EVENT_LBUTTONDOWN:
+ case OSystem::EVENT_RBUTTONDOWN: {
+ uint32 time = _s->_system->get_msecs();
+ if (_lastClick.count && (time < _lastClick.time + 1000)
+ && ABS(_lastClick.x - t.mouse.x) < 3
+ && ABS(_lastClick.y - t.mouse.y) < 3) {
+ _lastClick.count++;
+ } else {
+ _lastClick.x = t.mouse.x;
+ _lastClick.y = t.mouse.y;
+ _lastClick.count = 1;
+ }
+ _lastClick.time = time;
+ }
+ activeDialog->handleMouseDown(t.mouse.x - activeDialog->_x, t.mouse.y - activeDialog->_y, 1, _lastClick.count);
+ break;
+ case OSystem::EVENT_LBUTTONUP:
+ case OSystem::EVENT_RBUTTONUP:
+ activeDialog->handleMouseUp(t.mouse.x - activeDialog->_x, t.mouse.y - activeDialog->_y, 1, _lastClick.count);
+ break;
+ }
+ }
+
+ _eventList.clear();
+ }
+
+ // check if event should be sent again (keydown)
+ if (_currentKeyDown != 0)
+ {
+ // if only fired once, wait longer
+ if ( _keyRepeatLoopCount >= ((_keyRepeatEvenCount > 1) ? 2 : 4) )
+ // ^ loops to wait first event
+ // ^ loops to wait after first event
+ {
+ // fire event
+ activeDialog->handleKeyDown(_currentKeyDown, _currentKeyDownFlags);
+ _keyRepeatEvenCount++;
+ _keyRepeatLoopCount = 0;
+ }
+ _keyRepeatLoopCount++;
+ }
+
+ _s->drawDirtyScreenParts();
+}
+
+#pragma mark -
+
+void NewGui::saveState()
+{
+ _old_soundsPaused = _s->_sound->_soundsPaused;
+ _s->_sound->pauseSounds(true);
+
+ // Backup old cursor
+ memcpy(_old_grabbedCursor, _s->_grabbedCursor, sizeof(_old_grabbedCursor));
+ _old_cursorWidth = _s->_cursorWidth;
+ _old_cursorHeight = _s->_cursorHeight;
+ _old_cursorHotspotX = _s->_cursorHotspotX;
+ _old_cursorHotspotY = _s->_cursorHotspotY;
+ _old_cursor_mode = _s->_system->show_mouse(true);
+
+ _s->_cursorAnimate++;
+ _s->gdi._cursorActive = 1;
+}
+
+void NewGui::restoreState()
+{
+ _s->_fullRedraw = true;
+ _s->_completeScreenRedraw = true;
+ _s->_cursorAnimate--;
+
+ // Restore old cursor
+ memcpy(_s->_grabbedCursor, _old_grabbedCursor, sizeof(_old_grabbedCursor));
+ _s->_cursorWidth = _old_cursorWidth;
+ _s->_cursorHeight = _old_cursorHeight;
+ _s->_cursorHotspotX = _old_cursorHotspotX;
+ _s->_cursorHotspotY = _old_cursorHotspotY;
+ _s->updateCursor();
+
+ _s->_system->show_mouse(_old_cursor_mode);
+
+ _s->_sound->pauseSounds(_old_soundsPaused);
+}
+
+void NewGui::openDialog(Dialog *dialog)
+{
+ if (_dialogStack.empty())
+ _prepare_for_gui = true;
+ else if (_use_alpha_blending)
+ dialog->setupScreenBuf();
+
+ _dialogStack.push(dialog);
+ _need_redraw = true;
+}
+
+void NewGui::closeTopDialog()
+{
+ // Don't do anything if no dialog is open
+ if (_dialogStack.empty())
+ return;
+
+ // Tear down its screenBuf
+ if (_use_alpha_blending)
+ _dialogStack.top()->teardownScreenBuf();
+
+ // Remove the dialog from the stack
+ _dialogStack.pop();
+ if (_dialogStack.empty())
+ restoreState();
+ else
+ _need_redraw = true;
+}
+
+#pragma mark -
+
+const char *NewGui::queryResString(int stringno)
+{
+ char *result;
+ int string;
+
+ if (stringno == 0)
+ return NULL;
+
+ if (_s->_features & GF_AFTER_V7)
+ string = _s->_vars[string_map_table_v7[stringno - 1].num];
+ else if (_s->_features & GF_AFTER_V6)
+ string = _s->_vars[string_map_table_v6[stringno - 1].num];
+ else
+ string = string_map_table_v5[stringno - 1].num;
+
+ result = (char *)_s->getStringAddress(string);
+
+ if (!result) { // Gracelessly degrade to english :)
+ if (_s->_features & GF_AFTER_V6)
+ return string_map_table_v6[stringno - 1].string;
+ else
+ return string_map_table_v5[stringno - 1].string;
+ }
+
+ return result;
+}
+
+const char *NewGui::queryCustomString(int stringno)
+{
+ return string_map_table_custom[stringno];
+}
+
+
+#pragma mark -
+
+
+byte *NewGui::getBasePtr(int x, int y)
+{
+ VirtScreen *vs = _s->findVirtScreen(y);
+
+ if (vs == NULL)
+ return NULL;
+
+ return vs->screenPtr + x + (y - vs->topline) * 320 +
+ _s->_screenStartStrip * 8 + (_s->camera._cur.y - 100) * 320;
+}
+
+void NewGui::box(int x, int y, int width, int height)
+{
+ hline(x + 1, y, x + width - 2, _color);
+ hline(x, y + 1, x + width - 1, _color);
+ vline(x, y + 1, y + height - 2, _color);
+ vline(x + 1, y, y + height - 1, _color);
+
+ hline(x + 1, y + height - 2, x + width - 1, _shadowcolor);
+ hline(x + 1, y + height - 1, x + width - 2, _shadowcolor);
+ vline(x + width - 1, y + 1, y + height - 2, _shadowcolor);
+ vline(x + width - 2, y + 1, y + height - 1, _shadowcolor);
+}
+
+void NewGui::line(int x, int y, int x2, int y2, byte color)
+{
+ byte *ptr;
+
+ if (x2 < x)
+ x2 ^= x ^= x2 ^= x; // Swap x2 and x
+
+ if (y2 < y)
+ y2 ^= y ^= y2 ^= y; // Swap y2 and y
+
+ ptr = getBasePtr(x, y);
+
+ if (ptr == NULL)
+ return;
+
+ if (x == x2) {
+ /* vertical line */
+ while (y++ <= y2) {
+ *ptr = color;
+ ptr += 320;
+ }
+ } else if (y == y2) {
+ /* horizontal line */
+ while (x++ <= x2) {
+ *ptr++ = color;
+ }
+ }
+}
+
+void NewGui::blendRect(int x, int y, int w, int h, byte color)
+{
+ byte *ptr = getBasePtr(x, y);
+ if (ptr == NULL)
+ return;
+
+ while (h--) {
+ for (int i = 0; i < w; i++) {
+ ptr[i] = Blend(ptr[i], color, _s->_currentPalette);
+ }
+ ptr += 320;
+ }
+}
+
+void NewGui::fillRect(int x, int y, int w, int h, byte color)
+{
+ byte *ptr = getBasePtr(x, y);
+ if (ptr == NULL)
+ return;
+
+ while (h--) {
+ for (int i = 0; i < w; i++) {
+ ptr[i] = color;
+ }
+ ptr += 320;
+ }
+}
+
+void NewGui::checkerRect(int x, int y, int w, int h, byte color)
+{
+ byte *ptr = getBasePtr(x, y);
+ if (ptr == NULL)
+ return;
+
+ while (h--) {
+ for (int i = 0; i < w; i++) {
+ if ((h ^ i) & 1)
+ ptr[i] = color;
+ }
+ ptr += 320;
+ }
+}
+
+void NewGui::frameRect(int x, int y, int w, int h, byte color)
+{
+ int i;
+ byte *ptr, *basePtr = getBasePtr(x, y);
+ if (basePtr == NULL)
+ return;
+
+ ptr = basePtr;
+ for (i = 0; i < w; i++, ptr++)
+ *ptr = color;
+ ptr--;
+ for (i = 0; i < h; i++, ptr += 320)
+ *ptr = color;
+ ptr = basePtr;
+ for (i = 0; i < h; i++, ptr += 320)
+ *ptr = color;
+ ptr -= 320;
+ for (i = 0; i < w; i++, ptr++)
+ *ptr = color;
+}
+
+void NewGui::addDirtyRect(int x, int y, int w, int h)
+{
+ VirtScreen *vs = _s->findVirtScreen(y);
+
+ if (vs != NULL)
+ _s->setVirtscreenDirty(vs, x, y, x + w, y + h);
+}
+
+void NewGui::drawChar(const char str, int xx, int yy)
+{
+ unsigned int buffer = 0, mask = 0, x, y;
+ byte *tmp;
+ int tempc = _color;
+ _color = _textcolor;
+
+ tmp = &guifont[0];
+ tmp += 224 + (str + 1) * 8;
+
+ byte *ptr = getBasePtr(xx, yy);
+ if (ptr == NULL)
+ return;
+
+ for (y = 0; y < 8; y++) {
+ for (x = 0; x < 8; x++) {
+ unsigned char color;
+ if ((mask >>= 1) == 0) {
+ buffer = *tmp++;
+ mask = 0x80;
+ }
+ color = ((buffer & mask) != 0);
+ if (color)
+ ptr[x] = _color;
+ }
+ ptr += 320;
+ }
+ _color = tempc;
+
+}
+
+void NewGui::drawString(const char *str, int x, int y, int w, byte color, int align)
+{
+ if (_s->_gameId) { /* If a game is active.. */
+ StringTab *st = &_s->string[5];
+ st->charset = 1;
+ st->center = (align == kTextAlignCenter);
+ st->color = color;
+
+ if (align == kTextAlignLeft)
+ st->xpos = x;
+ else if (align == kTextAlignCenter)
+ st->xpos = x + w/2;
+ else if (align == kTextAlignRight)
+ st->xpos = x + w - _s->charset.getStringWidth(0, (byte *)str, 0);
+
+ st->ypos = y;
+ st->right = x + w;
+
+ _s->_messagePtr = (byte *)str;
+ _s->drawString(5);
+ } else {
+ // FIXME - support center/right align, use nicer custom font.
+ // Ultimately, we might want to *always* draw our messages this way,
+ // but only if we have a nice font.
+ uint len = strlen(str);
+ for (uint letter = 0; letter < len; letter++)
+ drawChar(str[letter], x + (letter * 8), y);
+ }
+}
+
+/*
+ * Draw an 8x8 bitmap at location (x,y)
+ */
+void NewGui::drawBitmap(uint32 bitmap[8], int x, int y, byte color)
+{
+ byte *ptr = getBasePtr(x, y);
+ if (ptr == NULL)
+ return;
+
+ for (int y2 = 0; y2 < 8; y2++) {
+ uint32 mask = 0xF0000000;
+ for (int x2 = 0; x2 < 8; x2++) {
+ if (bitmap[y2] & mask)
+ ptr[x2] = color;
+ mask >>= 4;
+ }
+ ptr += 320;
+ }
+}
+
+void NewGui::blitTo(byte buffer[320*200], int x, int y, int w, int h)
+{
+ byte *dstPtr = buffer + x + y*320;
+ byte *srcPtr = getBasePtr(x, y);
+ if (srcPtr == NULL)
+ return;
+
+ while (h--) {
+ for (int i = 0; i < w; i++) {
+ *dstPtr++ = *srcPtr++;
+ }
+ dstPtr += 320 - w;
+ srcPtr += 320 - w;
+ }
+}
+
+void NewGui::blitFrom(byte buffer[320*200], int x, int y, int w, int h)
+{
+ byte *srcPtr = buffer + x + y*320;
+ byte *dstPtr = getBasePtr(x, y);
+ if (dstPtr == NULL)
+ return;
+
+ while (h--) {
+ for (int i = 0; i < w; i++) {
+ *dstPtr++ = *srcPtr++;
+ }
+ dstPtr += 320 - w;
+ srcPtr += 320 - w;
+ }
+}
+
diff --git a/gui/newgui.h b/gui/newgui.h
new file mode 100644
index 0000000000..f78f31ee2d
--- /dev/null
+++ b/gui/newgui.h
@@ -0,0 +1,151 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#ifndef NEWGUI_H
+#define NEWGUI_H
+
+#include "scummsys.h"
+#include "system.h" // For events
+#include "util.h"
+
+class Dialog;
+class Scumm;
+
+#define hline(x, y, x2, color) line(x, y, x2, y, color);
+#define vline(x, y, y2, color) line(x, y, x, y2, color);
+
+enum {
+ kTextAlignLeft,
+ kTextAlignCenter,
+ kTextAlignRight,
+};
+
+// Extremly simple stack class, doesn't even do any error checking (for now)
+class DialogStack {
+protected:
+ Dialog *_stack[10]; // Anybody nesting dialogs deeper than 4 is mad anyway
+ int _size;
+public:
+ DialogStack() : _size(0) {}
+
+ bool empty() const { return _size <= 0; }
+ void push(Dialog *d) { _stack[_size++] = d; }
+ Dialog *top() const { return _stack[_size-1]; }
+ void pop() { if (_size > 0) _stack[--_size] = 0; }
+ int size() const { return _size; }
+ Dialog *operator [](int i) { return _stack[i]; }
+};
+
+typedef ScummVM::List<OSystem::Event> EventList;
+
+// This class hopefully will replace the old Gui class completly one day
+class NewGui {
+ friend class Dialog;
+public:
+ byte _color, _shadowcolor;
+ byte _bgcolor;
+ byte _textcolor;
+ byte _textcolorhi;
+
+ // Dialogs
+ void pauseDialog();
+ void saveloadDialog();
+ void aboutDialog();
+ void optionsDialog();
+ void soundDialog();
+
+ void loop();
+
+ bool isActive() { return ! _dialogStack.empty(); }
+
+ NewGui(Scumm *s);
+
+ void handleEvent(const OSystem::Event &event) { _eventList.push_back(event); }
+
+ Scumm *getScumm() { return _s; }
+
+protected:
+ Scumm *_s;
+ bool _use_alpha_blending;
+ bool _need_redraw;
+ bool _prepare_for_gui;
+ DialogStack _dialogStack;
+
+ Dialog *_pauseDialog;
+ Dialog *_saveLoadDialog;
+ Dialog *_aboutDialog;
+ Dialog *_optionsDialog;
+ Dialog *_soundDialog;
+
+ // for continuous events (keyDown)
+ int _currentKeyDown, _currentKeyDownFlags;
+ int _keyRepeatLoopCount;
+ int _keyRepeatEvenCount;
+
+ // sound state
+ bool _old_soundsPaused;
+
+ // mouse cursor state
+ bool _old_cursor_mode;
+ int _old_cursorHotspotX, _old_cursorHotspotY, _old_cursorWidth, _old_cursorHeight;
+ byte _old_grabbedCursor[2048];
+
+ // position and time of last mouse click (used to detect double clicks)
+ struct {
+ int16 x, y; // Position of mouse when the click occured
+ uint32 time; // Time
+ int count; // How often was it already pressed?
+ } _lastClick;
+
+ // List of events to be handled
+ EventList _eventList;
+
+ void saveState();
+ void restoreState();
+
+ void openDialog(Dialog *dialog);
+ void closeTopDialog();
+
+public:
+ // Drawing
+ byte *getBasePtr(int x, int y);
+ void box(int x, int y, int width, int height);
+ void line(int x, int y, int x2, int y2, byte color);
+ void blendRect(int x, int y, int w, int h, byte color);
+ void fillRect(int x, int y, int w, int h, byte color);
+ void checkerRect(int x, int y, int w, int h, byte color);
+ void frameRect(int x, int y, int w, int h, byte color);
+ void addDirtyRect(int x, int y, int w, int h);
+ void drawChar(const char c, int x, int y);
+ void drawString(const char *str, int x, int y, int w, byte color, int align = kTextAlignLeft);
+
+ void drawBitmap(uint32 bitmap[8], int x, int y, byte color);
+ void blitTo(byte buffer[320*200], int x, int y, int w, int h);
+ void blitFrom(byte buffer[320*200], int x, int y, int w, int h);
+
+ // Query a string from the resources
+ const char *queryResString(int stringno);
+
+ // Query a custom string. This is in a seperate method so that we
+ // can easily localize the messages in the future if we want to.
+ const char *queryCustomString(int stringno);
+};
+
+#endif