aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2018-10-18 20:13:06 -0700
committerPaul Gilbert2018-12-08 19:05:59 -0800
commit77f357e72f1f1bfad93b3b1c54f6f57b67131ba7 (patch)
tree8f4ce6c78727727081f085dacfddffa54f86ef02
parent74080143da579b2db0521ec204a172719c096bc5 (diff)
downloadscummvm-rg350-77f357e72f1f1bfad93b3b1c54f6f57b67131ba7.tar.gz
scummvm-rg350-77f357e72f1f1bfad93b3b1c54f6f57b67131ba7.tar.bz2
scummvm-rg350-77f357e72f1f1bfad93b3b1c54f6f57b67131ba7.zip
GLK: Add window creation
-rw-r--r--engines/gargoyle/gargoyle.cpp10
-rw-r--r--engines/gargoyle/gargoyle.h5
-rw-r--r--engines/gargoyle/glk.cpp13
-rw-r--r--engines/gargoyle/glk.h14
-rw-r--r--engines/gargoyle/glk_types.h9
-rw-r--r--engines/gargoyle/module.mk1
-rw-r--r--engines/gargoyle/scott/scott.cpp1
-rw-r--r--engines/gargoyle/windows.cpp244
-rw-r--r--engines/gargoyle/windows.h223
9 files changed, 507 insertions, 13 deletions
diff --git a/engines/gargoyle/gargoyle.cpp b/engines/gargoyle/gargoyle.cpp
index 5d3d53c7d5..5401b2c513 100644
--- a/engines/gargoyle/gargoyle.cpp
+++ b/engines/gargoyle/gargoyle.cpp
@@ -29,16 +29,20 @@
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
#include "gargoyle/gargoyle.h"
+#include "gargoyle/events.h"
+#include "gargoyle/windows.h"
namespace Gargoyle {
GargoyleEngine::GargoyleEngine(OSystem *syst, const GargoyleGameDescription *gameDesc) :
- _gameDescription(gameDesc), Engine(syst), _random("Gargoyle") {
- _screen = nullptr;
+ _gameDescription(gameDesc), Engine(syst), _random("Gargoyle"),
+ _events(nullptr), _screen(nullptr), _windows(nullptr) {
}
GargoyleEngine::~GargoyleEngine() {
+ delete _events;
delete _screen;
+ delete _windows;
}
void GargoyleEngine::initialize() {
@@ -50,6 +54,8 @@ void GargoyleEngine::initialize() {
initGraphics(640, 480, false);
_screen = new Graphics::Screen();
+ _events = new Events();
+ _windows = new Windows(_screen);
}
Common::Error GargoyleEngine::run() {
diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h
index 3cfee29c87..c7a7b86ecd 100644
--- a/engines/gargoyle/gargoyle.h
+++ b/engines/gargoyle/gargoyle.h
@@ -33,6 +33,9 @@
namespace Gargoyle {
+class Events;
+class Windows;
+
enum InterpreterType {
INTERPRETER_SCOTT
};
@@ -69,7 +72,9 @@ private:
void initialize();
protected:
const GargoyleGameDescription *_gameDescription;
+ Events *_events;
Graphics::Screen *_screen;
+ Windows *_windows;
Common::RandomSource _random;
int _loadSaveSlot;
diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp
index 82943bd497..278faf5678 100644
--- a/engines/gargoyle/glk.cpp
+++ b/engines/gargoyle/glk.cpp
@@ -21,6 +21,8 @@
*/
#include "gargoyle/glk.h"
+#include "gargoyle/events.h"
+#include "gargoyle/windows.h"
namespace Gargoyle {
@@ -60,15 +62,12 @@ unsigned char Glk::glk_char_to_upper(unsigned char ch) {
return '\0';
}
-winid_t Glk::glk_window_get_root(void) {
- // TODO
- return nullptr;
+winid_t Glk::glk_window_get_root(void) const {
+ return _windows->getRoot();
}
-winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size,
- glui32 wintype, glui32 rock) {
- // TODO
- return nullptr;
+winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, glui32 rock) const {
+ return _windows->windowOpen(split, method, size, wintype, rock);
}
void Glk::glk_window_close(winid_t win, stream_result_t *result) {
diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h
index 55cd563ba3..ce21910a1a 100644
--- a/engines/gargoyle/glk.h
+++ b/engines/gargoyle/glk.h
@@ -25,9 +25,11 @@
#include "gargoyle/gargoyle.h"
#include "gargoyle/glk_types.h"
+#include "gargoyle/windows.h"
namespace Gargoyle {
+
/**
* Implements the GLK interface
*/
@@ -57,9 +59,17 @@ public:
unsigned char glk_char_to_lower(unsigned char ch);
unsigned char glk_char_to_upper(unsigned char ch);
- winid_t glk_window_get_root(void);
+ /**
+ * Get the root window of the window hierarchy
+ */
+ winid_t glk_window_get_root(void) const;
+
+ /**
+ * Open a new window
+ */
winid_t glk_window_open(winid_t split, glui32 method, glui32 size,
- glui32 wintype, glui32 rock);
+ glui32 wintype, glui32 rock = 0) const;
+
void glk_window_close(winid_t win, stream_result_t *result);
void glk_window_get_size(winid_t win, glui32 *widthptr,
glui32 *heightptr);
diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h
index a8227411df..040d666fbe 100644
--- a/engines/gargoyle/glk_types.h
+++ b/engines/gargoyle/glk_types.h
@@ -29,6 +29,7 @@ namespace Gargoyle {
typedef uint32 glui32;
typedef int32 glsi32;
+class Window;
/**
* These are the compile-time conditionals that reveal various Glk optional modules.
@@ -48,7 +49,6 @@ typedef int32 glsi32;
* These types are opaque object identifiers. They're pointers to opaque
* C structures, which are defined differently by each library.
*/
-typedef struct glk_window_struct *winid_t;
typedef struct glk_stream_struct *strid_t;
typedef struct glk_fileref_struct *frefid_t;
typedef struct glk_schannel_struct *schanid_t;
@@ -233,7 +233,7 @@ enum ImageAlign {
struct event_struct {
glui32 type;
- winid_t win;
+ Window *win;
glui32 val1, val2;
};
typedef event_struct event_t;
@@ -265,6 +265,11 @@ struct glkdate_struct {
};
typedef glkdate_struct glkdate_t;
+union gidispatch_rock_t {
+ glui32 num;
+ void *ptr;
+};
+
#endif /* GLK_MODULE_DATETIME */
} // End of namespace Gargoyle
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 7462f7ae28..4a535af612 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -5,6 +5,7 @@ MODULE_OBJS := \
events.o \
gargoyle.o \
glk.o \
+ windows.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/scott/scott.cpp b/engines/gargoyle/scott/scott.cpp
index 42a9088b21..9632408d46 100644
--- a/engines/gargoyle/scott/scott.cpp
+++ b/engines/gargoyle/scott/scott.cpp
@@ -864,6 +864,7 @@ int Scott::PerformLine(int ct) {
case 63:
doneit: Output("The game is now over.\n");
glk_exit();
+ break;
case 64:
break;
case 65:
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
new file mode 100644
index 0000000000..ad03ab860a
--- /dev/null
+++ b/engines/gargoyle/windows.cpp
@@ -0,0 +1,244 @@
+/* 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.
+ *
+ */
+
+#include "gargoyle/windows.h"
+#include "common/algorithm.h"
+#include "common/textconsole.h"
+
+namespace Gargoyle {
+
+#define MAGIC_WINDOW_NUM (9876)
+
+Windows::Windows(Graphics::Screen *screen) : _screen(screen), _forceRedraw(true), _moreFocus(false),
+ _windowList(nullptr), _rootWin(nullptr), _focusWin(nullptr) {
+}
+
+Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock) {
+ Window *newwin, *oldparent;
+ PairWindow *pairwin;
+ glui32 val;
+
+ _forceRedraw = true;
+
+ if (!_rootWin) {
+ if (splitwin) {
+ warning("window_open: ref must be NULL");
+ return nullptr;
+ }
+
+ /* ignore method and size now */
+ oldparent = NULL;
+ } else {
+ if (!splitwin) {
+ warning("window_open: ref must not be NULL");
+ return nullptr;
+ }
+
+ val = (method & winmethod_DivisionMask);
+ if (val != winmethod_Fixed && val != winmethod_Proportional)
+ {
+ warning("window_open: invalid method (not fixed or proportional)");
+ return nullptr;
+ }
+
+ val = (method & winmethod_DirMask);
+ if (val != winmethod_Above && val != winmethod_Below
+ && val != winmethod_Left && val != winmethod_Right)
+ {
+ warning("window_open: invalid method (bad direction)");
+ return nullptr;
+ }
+
+ oldparent = splitwin->parent;
+ if (oldparent && oldparent->_type != wintype_Pair)
+ {
+ warning("window_open: parent window is not Pair");
+ return nullptr;
+ }
+ }
+
+ assert(wintype != wintype_Pair);
+ newwin = newWindow(wintype, rock);
+ if (!newwin) {
+ warning("window_open: unable to create window");
+ return nullptr;
+ }
+
+ if (!splitwin) {
+ _rootWin = newwin;
+ } else {
+ // create pairwin, with newwin as the key
+ pairwin = new PairWindow(method, newwin, size);
+ pairwin->child1 = splitwin;
+ pairwin->child2 = newwin;
+
+ splitwin->parent = pairwin;
+ newwin->parent = pairwin;
+ pairwin->parent = oldparent;
+
+ if (oldparent) {
+ PairWindow *parentWin = dynamic_cast<PairWindow *>(oldparent);
+ assert(parentWin);
+ if (parentWin->child1 == splitwin)
+ parentWin->child1 = pairwin;
+ else
+ parentWin->child2 = pairwin;
+ } else {
+ _rootWin = pairwin;
+ }
+ }
+
+ rearrange();
+
+ return newwin;
+}
+
+Window *Windows::newWindow(glui32 type, glui32 rock) {
+ Window *win;
+
+ switch (type) {
+ case wintype_Blank:
+ win = new BlankWindow(rock);
+ break;
+ case wintype_TextGrid:
+ win = new TextGridWindow(rock);
+ break;
+ case wintype_TextBuffer:
+ win = new TextBufferWindow(rock);
+ break;
+ case wintype_Graphics:
+ win = new GraphicsWindow(rock);
+ break;
+ case wintype_Pair:
+ error("Pair windows cannot be created directly");
+ default:
+ error("Unknown window type");
+ }
+
+ win->next = _windowList;
+ _windowList = win;
+ if (win->next)
+ win->next->prev = win;
+
+ return win;
+}
+
+PairWindow *Windows::newPairWindow(glui32 method, Window *key, glui32 size) {
+ PairWindow *pwin = new PairWindow(method, key, size);
+ pwin->next = _windowList;
+ _windowList = pwin;
+ if (pwin->next)
+ pwin->next->prev = pwin;
+
+ return pwin;
+}
+
+void Windows::rearrange() {
+ // TODO
+ /*
+ if (_rootWin) {
+ rect_t box;
+
+ if (gli_conf_lockcols) {
+ int desired_width = gli_wmarginx_save * 2 + gli_cellw * gli_cols;
+ if (desired_width > gli_image_w)
+ gli_wmarginx = gli_wmarginx_save;
+ else
+ gli_wmarginx = (gli_image_w - gli_cellw * gli_cols) / 2;
+ }
+
+ if (gli_conf_lockrows)
+ {
+ int desired_height = gli_wmarginy_save * 2 + gli_cellh * gli_rows;
+ if (desired_height > gli_image_h)
+ gli_wmarginy = gli_wmarginy_save;
+ else
+ gli_wmarginy = (gli_image_h - gli_cellh * gli_rows) / 2;
+ }
+
+ box.x0 = gli_wmarginx;
+ box.y0 = gli_wmarginy;
+ box.x1 = gli_image_w - gli_wmarginx;
+ box.y1 = gli_image_h - gli_wmarginy;
+ gli_window_rearrange(_rootWin, &box);
+ }
+ */
+}
+
+/*--------------------------------------------------------------------------*/
+
+Window::Window(glui32 rock) : _magicnum(MAGIC_WINDOW_NUM), _rock(rock), _type(0),
+ parent(nullptr), next(nullptr), prev(nullptr),
+ yadj(0), line_request(0), line_request_uni(0), char_request(0), char_request_uni(0),
+ mouse_request(0), hyper_request(0), more_request(0), scroll_request(0), image_loaded(0),
+ echo_line_input(true), line_terminators(nullptr), termct(0), str(nullptr), echostr(nullptr) {
+ attr.fgset = 0;
+ attr.bgset = 0;
+ attr.reverse = 0;
+ attr.style = 0;
+ attr.fgcolor = 0;
+ attr.bgcolor = 0;
+ attr.hyper = 0;
+
+ Common::fill(&bgcolor[0], &bgcolor[3], 3);
+ Common::fill(&fgcolor[0], &fgcolor[3], 3);
+ disprock.num = 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+BlankWindow::BlankWindow(uint32 rock) : Window(rock) {
+ _type = wintype_Blank;
+}
+
+/*--------------------------------------------------------------------------*/
+
+TextGridWindow::TextGridWindow(uint32 rock) : Window(rock) {
+ _type = wintype_TextGrid;
+}
+
+/*--------------------------------------------------------------------------*/
+
+TextBufferWindow::TextBufferWindow(uint32 rock) : Window(rock) {
+ _type = wintype_TextBuffer;
+}
+
+/*--------------------------------------------------------------------------*/
+
+GraphicsWindow::GraphicsWindow(uint32 rock) : Window(rock) {
+ _type = wintype_Graphics;
+}
+
+/*--------------------------------------------------------------------------*/
+
+PairWindow::PairWindow(glui32 method, Window *_key, glui32 _size) : Window(0),
+ dir(method & winmethod_DirMask),
+ division(method & winmethod_DivisionMask),
+ wborder((method & winmethod_BorderMask) == winmethod_Border),
+ vertical(dir == winmethod_Left || dir == winmethod_Right),
+ backward(dir == winmethod_Left || dir == winmethod_Above),
+ key(key), size(size), keydamage(0), child1(nullptr), child2(nullptr) {
+ _type = wintype_Pair;
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
new file mode 100644
index 0000000000..91cbc91a53
--- /dev/null
+++ b/engines/gargoyle/windows.h
@@ -0,0 +1,223 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GARGOYLE_WINDOWS_H
+#define GARGOYLE_WINDOWS_H
+
+#include "common/list.h"
+#include "common/rect.h"
+#include "common/stream.h"
+#include "graphics/screen.h"
+#include "gargoyle/glk_types.h"
+
+namespace Gargoyle {
+
+class Window;
+class PairWindow;
+
+class Windows {
+private:
+ Graphics::Screen *_screen;
+ Window * _windowList; ///< List of all windows
+ Window *_rootWin; ///< The topmost window
+ Window *_focusWin; ///< The window selected by the player
+ bool _forceRedraw;
+ bool _moreFocus;
+private:
+ /**
+ * Create a new window
+ */
+ Window *newWindow(glui32 type, glui32 rock);
+
+ /**
+ * Create a new pair window
+ */
+ PairWindow *newPairWindow(glui32 method, Window *key, glui32 size);
+
+ /**
+ * Rearrange windows
+ */
+ void rearrange();
+public:
+ /**
+ * Constructor
+ */
+ Windows(Graphics::Screen *screen);
+
+ /**
+ * Open a new window
+ */
+ Window *windowOpen(Window *splitwin, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock);
+
+ /**
+ * Return the root window
+ */
+ Window *getRoot() const { return _rootWin; }
+};
+
+/**
+ * Window attributes
+ */
+struct attr_t {
+ unsigned fgset : 1;
+ unsigned bgset : 1;
+ unsigned reverse : 1;
+ unsigned : 1;
+ unsigned style : 4;
+ unsigned fgcolor : 24;
+ unsigned bgcolor : 24;
+ unsigned hyper : 32;
+};
+
+struct WindowPair {
+ Window *owner;
+ Window *child1, *child2;
+
+ // split info...
+ glui32 dir; ///< winmethod_Left, Right, Above, or Below
+ int vertical, backward; ///< flags
+ glui32 division; ///< winmethod_Fixed or winmethod_Proportional
+ Window *key; ///< NULL or a leaf-descendant (not a Pair)
+ int keydamage; ///< used as scratch space in window closing
+ glui32 size; ///< size value
+ glui32 wborder; ///< winMethod_Border, NoBorder
+};
+
+/**
+ * Window definition
+ */
+class Window {
+public:
+ glui32 _magicnum;
+ glui32 _rock;
+ glui32 _type;
+
+ Window *parent; ///< pair window which contains this one
+ Common::Rect bbox;
+ int yadj;
+
+ Common::WriteStream *str; ///< the window stream.
+ Common::WriteStream *echostr; ///< the window's echo stream, if any.
+
+ int line_request;
+ int line_request_uni;
+ int char_request;
+ int char_request_uni;
+ int mouse_request;
+ int hyper_request;
+ int more_request;
+ int scroll_request;
+ int image_loaded;
+
+ glui32 echo_line_input;
+ glui32 *line_terminators;
+ glui32 termct;
+
+ attr_t attr;
+ byte bgcolor[3];
+ byte fgcolor[3];
+
+ gidispatch_rock_t disprock;
+ Window *next, *prev; ///< in the big linked list of windows
+public:
+ /**
+ * Constructor
+ */
+ Window(uint32 rock);
+
+ /**
+ * Destructor
+ */
+ virtual ~Window() {}
+};
+typedef Window *winid_t;
+
+/**
+ * Blank window
+ */
+class BlankWindow : public Window {
+public:
+ /**
+ * Constructor
+ */
+ BlankWindow(uint32 rock);
+};
+
+/**
+ * Text Grid window
+ */
+class TextGridWindow : public Window {
+public:
+ /**
+ * Constructor
+ */
+ TextGridWindow(uint32 rock);
+};
+
+/**
+ * Text Buffer window
+ */
+class TextBufferWindow : public Window {
+public:
+ /**
+ * Constructor
+ */
+ TextBufferWindow(uint32 rock);
+};
+
+/**
+ * Graphics window
+ */
+class GraphicsWindow : public Window {
+public:
+ /**
+ * Constructor
+ */
+ GraphicsWindow(uint32 rock);
+};
+
+/**
+ * Pair window
+ */
+class PairWindow : public Window {
+public:
+ Window *child1, *child2;
+
+ /* split info... */
+ glui32 dir; ///< winmethod_Left, Right, Above, or Below
+ int vertical, backward; ///< flags
+ glui32 division; ///< winmethod_Fixed or winmethod_Proportional
+ Window *key; ///< NULL or a leaf-descendant (not a Pair)
+ int keydamage; ///< used as scratch space in window closing
+ glui32 size; ///< size value
+ glui32 wborder; ///< winMethod_Border, NoBorder
+public:
+ /**
+ * Constructor
+ */
+ PairWindow(glui32 method, Window *_key, glui32 _size);
+};
+
+} // End of namespace Gargoyle
+
+#endif