diff options
author | Paul Gilbert | 2018-10-18 20:13:06 -0700 |
---|---|---|
committer | Paul Gilbert | 2018-12-08 19:05:59 -0800 |
commit | 77f357e72f1f1bfad93b3b1c54f6f57b67131ba7 (patch) | |
tree | 8f4ce6c78727727081f085dacfddffa54f86ef02 | |
parent | 74080143da579b2db0521ec204a172719c096bc5 (diff) | |
download | scummvm-rg350-77f357e72f1f1bfad93b3b1c54f6f57b67131ba7.tar.gz scummvm-rg350-77f357e72f1f1bfad93b3b1c54f6f57b67131ba7.tar.bz2 scummvm-rg350-77f357e72f1f1bfad93b3b1c54f6f57b67131ba7.zip |
GLK: Add window creation
-rw-r--r-- | engines/gargoyle/gargoyle.cpp | 10 | ||||
-rw-r--r-- | engines/gargoyle/gargoyle.h | 5 | ||||
-rw-r--r-- | engines/gargoyle/glk.cpp | 13 | ||||
-rw-r--r-- | engines/gargoyle/glk.h | 14 | ||||
-rw-r--r-- | engines/gargoyle/glk_types.h | 9 | ||||
-rw-r--r-- | engines/gargoyle/module.mk | 1 | ||||
-rw-r--r-- | engines/gargoyle/scott/scott.cpp | 1 | ||||
-rw-r--r-- | engines/gargoyle/windows.cpp | 244 | ||||
-rw-r--r-- | engines/gargoyle/windows.h | 223 |
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 |