aboutsummaryrefslogtreecommitdiff
path: root/engines/gargoyle
diff options
context:
space:
mode:
authorPaul Gilbert2018-10-21 23:14:50 -0700
committerPaul Gilbert2018-12-08 19:05:59 -0800
commit8708ed4f9aead0876d09dd9b6bb9096407cd961c (patch)
tree734e0a0e3f48f267df060a9eed45313dd86781f6 /engines/gargoyle
parent0d3ad2dc8ad49c684e8a74285ec832335d7675e7 (diff)
downloadscummvm-rg350-8708ed4f9aead0876d09dd9b6bb9096407cd961c.tar.gz
scummvm-rg350-8708ed4f9aead0876d09dd9b6bb9096407cd961c.tar.bz2
scummvm-rg350-8708ed4f9aead0876d09dd9b6bb9096407cd961c.zip
GLK: Split the windows.cpp file into separate files for each window class
Diffstat (limited to 'engines/gargoyle')
-rw-r--r--engines/gargoyle/module.mk6
-rw-r--r--engines/gargoyle/window_graphics.cpp89
-rw-r--r--engines/gargoyle/window_graphics.h91
-rw-r--r--engines/gargoyle/window_pair.cpp125
-rw-r--r--engines/gargoyle/window_pair.h64
-rw-r--r--engines/gargoyle/window_text_buffer.cpp602
-rw-r--r--engines/gargoyle/window_text_buffer.h198
-rw-r--r--engines/gargoyle/window_text_grid.cpp665
-rw-r--r--engines/gargoyle/window_text_grid.h180
-rw-r--r--engines/gargoyle/windows.cpp1459
-rw-r--r--engines/gargoyle/windows.h407
11 files changed, 2063 insertions, 1823 deletions
diff --git a/engines/gargoyle/module.mk b/engines/gargoyle/module.mk
index 46f2d31722..e684ff998b 100644
--- a/engines/gargoyle/module.mk
+++ b/engines/gargoyle/module.mk
@@ -11,8 +11,12 @@ MODULE_OBJS := \
picture.o \
streams.o \
string.o \
- window_mask.o \
windows.o \
+ window_mask.o \
+ window_graphics.o \
+ window_pair.o \
+ window_text_buffer.o \
+ window_text_grid.o \
scott/detection.o \
scott/scott.o
diff --git a/engines/gargoyle/window_graphics.cpp b/engines/gargoyle/window_graphics.cpp
new file mode 100644
index 0000000000..cc9a5dd19e
--- /dev/null
+++ b/engines/gargoyle/window_graphics.cpp
@@ -0,0 +1,89 @@
+/* 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/window_graphics.h"
+
+namespace Gargoyle {
+
+GraphicsWindow::GraphicsWindow(Windows *windows, uint32 rock) : Window(windows, rock),
+_w(0), _h(0), _dirty(false), _surface(nullptr) {
+ _type = wintype_Graphics;
+ Common::copy(&_bgColor[0], &_bgColor[3], _bgnd);
+}
+
+GraphicsWindow::~GraphicsWindow() {
+ delete _surface;
+}
+
+void GraphicsWindow::rearrange(const Common::Rect &box) {
+ int newwid, newhgt;
+ int bothwid, bothhgt;
+ int oldw, oldh;
+ Graphics::ManagedSurface *newSurface;
+
+ _bbox = box;
+
+ newwid = box.width();
+ newhgt = box.height();
+ oldw = _w;
+ oldh = _h;
+
+ if (newwid <= 0 || newhgt <= 0) {
+ _w = 0;
+ _h = 0;
+ delete _surface;
+ _surface = NULL;
+ return;
+ }
+
+ bothwid = _w;
+ if (newwid < bothwid)
+ bothwid = newwid;
+ bothhgt = _h;
+ if (newhgt < bothhgt)
+ bothhgt = newhgt;
+
+ newSurface = new Graphics::ManagedSurface(newwid, newhgt,
+ Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0));
+
+ // If the new surface is equal or bigger than the old one, copy it over
+ if (_surface && bothwid && bothhgt)
+ newSurface->blitFrom(*_surface);
+
+ delete _surface;
+ _surface = newSurface;
+ _w = newwid;
+ _h = newhgt;
+
+ touch();
+}
+
+void GraphicsWindow::touch() {
+ _dirty = true;
+ _windows->repaint(_bbox);
+}
+
+void GraphicsWindow::redraw() {
+ // TODO
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_graphics.h b/engines/gargoyle/window_graphics.h
new file mode 100644
index 0000000000..77e49105b2
--- /dev/null
+++ b/engines/gargoyle/window_graphics.h
@@ -0,0 +1,91 @@
+/* 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_WINDOW_GRAPHICS_H
+#define GARGOYLE_WINDOW_GRAPHICS_H
+
+#include "gargoyle/windows.h"
+#include "gargoyle/picture.h"
+
+namespace Gargoyle {
+
+/**
+ * Graphics window
+ */
+class GraphicsWindow : public Window {
+private:
+ void touch();
+public:
+ unsigned char _bgnd[3];
+ bool _dirty;
+ glui32 _w, _h;
+ Graphics::ManagedSurface *_surface;
+public:
+ /**
+ * Constructor
+ */
+ GraphicsWindow(Windows *windows, uint32 rock);
+
+ /**
+ * Destructor
+ */
+ virtual ~GraphicsWindow();
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Get window split size within parent pair window
+ */
+ virtual glui32 getSplit(glui32 size, bool vertical) const override {
+ return size;
+ }
+
+ /**
+ * Cancel a mouse event
+ */
+ virtual void cancelMouseEvent() override { _mouseRequest = false; }
+
+ /**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
+
+ /**
+ * Get the window dimensions
+ */
+ void getSize(glui32 *w, glui32 *h) {
+ *w = _w;
+ *h = _h;
+ }
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/window_pair.cpp b/engines/gargoyle/window_pair.cpp
new file mode 100644
index 0000000000..af3ed4ca38
--- /dev/null
+++ b/engines/gargoyle/window_pair.cpp
@@ -0,0 +1,125 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gargoyle/window_pair.h"
+#include "gargoyle/conf.h"
+
+namespace Gargoyle {
+
+PairWindow::PairWindow(Windows *windows, glui32 method, Window *key, glui32 size) :
+ Window(windows, 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;
+}
+
+void PairWindow::rearrange(const Common::Rect &box) {
+ Common::Rect box1, box2;
+ int min, diff, split, splitwid, max;
+ Window *ch1, *ch2;
+
+ _bbox = box;
+
+ if (_vertical) {
+ min = _bbox.left;
+ max = _bbox.right;
+ } else {
+ min = _bbox.top;
+ max = _bbox.bottom;
+ }
+ diff = max - min;
+
+ // We now figure split.
+ if (_vertical)
+ splitwid = g_conf->_wPaddingX; // want border?
+ else
+ splitwid = g_conf->_wPaddingY; // want border?
+
+ switch (_division) {
+ case winmethod_Proportional:
+ split = (diff * _size) / 100;
+ break;
+
+ case winmethod_Fixed:
+ split = !_key ? 0 : _key->getSplit(_size, _vertical);
+ break;
+
+ default:
+ split = diff / 2;
+ break;
+ }
+
+ if (!_backward)
+ split = max - split - splitwid;
+ else
+ split = min + split;
+
+ if (min >= max) {
+ split = min;
+ } else {
+ if (split < min)
+ split = min;
+ else if (split > max - splitwid)
+ split = max - splitwid;
+ }
+
+ if (_vertical) {
+ box1.left = _bbox.left;
+ box1.right = split;
+ box2.left = split + splitwid;
+ box2.right = _bbox.right;
+ box1.top = _bbox.top;
+ box1.bottom = _bbox.bottom;
+ box2.top = _bbox.top;
+ box2.bottom = _bbox.bottom;
+ } else {
+ box1.top = _bbox.top;
+ box1.bottom = split;
+ box2.top = split + splitwid;
+ box2.bottom = _bbox.bottom;
+ box1.left = _bbox.left;
+ box1.right = _bbox.right;
+ box2.left = _bbox.left;
+ box2.right = _bbox.right;
+ }
+
+ if (!_backward) {
+ ch1 = _child1;
+ ch2 = _child2;
+ } else {
+ ch1 = _child2;
+ ch2 = _child1;
+ }
+
+ ch1->rearrange(box1);
+ ch2->rearrange(box2);
+}
+
+void PairWindow::redraw() {
+ // TODO
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_pair.h b/engines/gargoyle/window_pair.h
new file mode 100644
index 0000000000..b25b324199
--- /dev/null
+++ b/engines/gargoyle/window_pair.h
@@ -0,0 +1,64 @@
+/* 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_WINDOW_PAIR_H
+#define GARGOYLE_WINDOW_PAIR_H
+
+#include "gargoyle/windows.h"
+
+namespace Gargoyle {
+
+/**
+ * Pair window
+ */
+class PairWindow : public Window {
+public:
+ Window *_child1, *_child2;
+
+ /* split info... */
+ glui32 _dir; ///< winmethod_Left, Right, Above, or Below
+ bool _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(Windows *windows, glui32 method, Window *key, glui32 size);
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/window_text_buffer.cpp b/engines/gargoyle/window_text_buffer.cpp
new file mode 100644
index 0000000000..1e85a24f8d
--- /dev/null
+++ b/engines/gargoyle/window_text_buffer.cpp
@@ -0,0 +1,602 @@
+/* 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/window_text_buffer.h"
+#include "gargoyle/conf.h"
+#include "gargoyle/gargoyle.h"
+
+namespace Gargoyle {
+
+TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windows, rock),
+ _historyPos(0), _historyFirst(0), _historyPresent(0), _lastSeen(0), _scrollPos(0),
+ _scrollMax(0), _scrollBack(SCROLLBACK), _width(-1), _height(-1), _inBuf(nullptr),
+ _lineTerminators(nullptr), _echoLineInput(true), _ladjw(0), _radjw(0), _ladjn(0),
+ _radjn(0), _numChars(0), _chars(nullptr), _attrs(nullptr),
+ _spaced(0), _dashed(0), _copyBuf(0), _copyPos(0) {
+ _type = wintype_TextBuffer;
+ Common::fill(&_history[0], &_history[HISTORYLEN], nullptr);
+
+ Common::copy(&g_conf->_tStyles[0], &g_conf->_tStyles[style_NUMSTYLES], styles);
+}
+
+TextBufferWindow::~TextBufferWindow() {
+ if (_inBuf) {
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(_inBuf, _inMax, "&+#!Cn", _inArrayRock);
+ _inBuf = nullptr;
+ }
+
+ delete[] _copyBuf;
+ delete[] _lineTerminators;
+
+ for (int i = 0; i < _scrollBack; i++) {
+ if (_lines[i].lpic)
+ _lines[i].lpic->decrement();
+ if (_lines[i].rpic)
+ _lines[i].rpic->decrement();
+ }
+}
+
+void TextBufferWindow::rearrange(const Common::Rect &box) {
+ Window::rearrange(box);
+ int newwid, newhgt;
+ int rnd;
+
+ newwid = (box.width() - g_conf->_tMarginX * 2 - g_conf->_scrollWidth) / g_conf->_cellW;
+ newhgt = (box.height() - g_conf->_tMarginY * 2) / g_conf->_cellH;
+
+ /* align text with bottom */
+ rnd = newhgt * g_conf->_cellH + g_conf->_tMarginY * 2;
+ _yAdj = (box.height() - rnd);
+ _bbox.top += (box.height() - rnd);
+
+ if (newwid != _width) {
+ _width = newwid;
+ reflow();
+ }
+
+ if (newhgt != _height) {
+ /* scroll up if we obscure new lines */
+ if (_lastSeen >= newhgt - 1)
+ _scrollPos += (_height - newhgt);
+
+ _height = newhgt;
+
+ /* keep window within 'valid' lines */
+ if (_scrollPos > _scrollMax - _height + 1)
+ _scrollPos = _scrollMax - _height + 1;
+ if (_scrollPos < 0)
+ _scrollPos = 0;
+ touchScroll();
+
+ /* allocate copy buffer */
+ if (_copyBuf)
+ delete[] _copyBuf;
+ _copyBuf = new glui32[_height * TBLINELEN];
+
+ for (int i = 0; i < (_height * TBLINELEN); i++)
+ _copyBuf[i] = 0;
+
+ _copyPos = 0;
+ }
+}
+
+void TextBufferWindow::reflow() {
+ int inputbyte = -1;
+ Attributes curattr, oldattr;
+ int i, k, p, s;
+ int x;
+
+ if (_height < 4 || _width < 20)
+ return;
+
+ _lines[0].len = _numChars;
+
+ /* allocate temp buffers */
+ Attributes *attrbuf = new Attributes[SCROLLBACK * TBLINELEN];
+ glui32 *charbuf = new glui32[SCROLLBACK * TBLINELEN];
+ int *alignbuf = new int[SCROLLBACK];
+ Picture **pictbuf = new Picture *[SCROLLBACK];
+ glui32 *hyperbuf = new glui32[SCROLLBACK];
+ int *offsetbuf = new int[SCROLLBACK];
+
+ if (!attrbuf || !charbuf || !alignbuf || !pictbuf || !hyperbuf || !offsetbuf) {
+ delete[] attrbuf;
+ delete[] charbuf;
+ delete[] alignbuf;
+ delete[] pictbuf;
+ delete[] hyperbuf;
+ delete[] offsetbuf;
+ return;
+ }
+
+ /* copy text to temp buffers */
+
+ oldattr = _attr;
+ curattr.clear();
+
+ x = 0;
+ p = 0;
+ s = _scrollMax < SCROLLBACK ? _scrollMax : SCROLLBACK - 1;
+
+ for (k = s; k >= 0; k--) {
+ if (k == 0 && _lineRequest)
+ inputbyte = p + _inFence;
+
+ if (_lines[k].lpic) {
+ offsetbuf[x] = p;
+ alignbuf[x] = imagealign_MarginLeft;
+ pictbuf[x] = _lines[k].lpic;
+
+ if (pictbuf[x]) pictbuf[x]->increment();
+ hyperbuf[x] = _lines[k].lhyper;
+ x++;
+ }
+
+ if (_lines[k].rpic) {
+ offsetbuf[x] = p;
+ alignbuf[x] = imagealign_MarginRight;
+ pictbuf[x] = _lines[k].rpic;
+ if (pictbuf[x]) pictbuf[x]->increment();
+ hyperbuf[x] = _lines[k].rhyper;
+ x++;
+ }
+
+ for (i = 0; i < _lines[k].len; i++) {
+ attrbuf[p] = curattr = _lines[k].attr[i];
+ charbuf[p] = _lines[k].chars[i];
+ p++;
+ }
+
+ if (_lines[k].newline) {
+ attrbuf[p] = curattr;
+ charbuf[p] = '\n';
+ p++;
+ }
+ }
+
+ offsetbuf[x] = -1;
+
+ /* clear window */
+
+ clear();
+
+ /* and dump text back */
+
+ x = 0;
+ for (i = 0; i < p; i++) {
+ if (i == inputbyte)
+ break;
+ _attr = attrbuf[i];
+
+ if (offsetbuf[x] == i) {
+ putPicture(pictbuf[x], alignbuf[x], hyperbuf[x]);
+ x++;
+ }
+
+ putCharUni(charbuf[i]);
+ }
+
+ /* terribly sorry about this... */
+ _lastSeen = 0;
+ _scrollPos = 0;
+
+ if (inputbyte != -1) {
+ _inFence = _numChars;
+ putTextUni(charbuf + inputbyte, p - inputbyte, _numChars, 0);
+ _inCurs = _numChars;
+ }
+
+ // free temp buffers
+ delete[] attrbuf;
+ delete[] charbuf;
+ delete[] alignbuf;
+ delete[] pictbuf;
+ delete[] hyperbuf;
+ delete[] offsetbuf;
+
+ _attr = oldattr;
+
+ touchScroll();
+}
+
+void TextBufferWindow::touchScroll() {
+ _windows->clearSelection();
+ _windows->repaint(_bbox);
+
+ for (int i = 0; i < _scrollMax; i++)
+ _lines[i].dirty = true;
+}
+
+bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
+ if (align == imagealign_MarginRight)
+ {
+ if (_lines[0].rpic || _numChars)
+ return false;
+
+ _radjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
+ _radjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
+ _lines[0].rpic = pic;
+ _lines[0].rm = _radjw;
+ _lines[0].rhyper = linkval;
+ } else {
+ if (align != imagealign_MarginLeft && _numChars)
+ putCharUni('\n');
+
+ if (_lines[0].lpic || _numChars)
+ return false;
+
+ _ladjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
+ _ladjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
+ _lines[0].lpic = pic;
+ _lines[0].lm = _ladjw;
+ _lines[0].lhyper = linkval;
+
+ if (align != imagealign_MarginLeft)
+ flowBreak();
+ }
+
+ return true;
+}
+
+void TextBufferWindow::flowBreak() {
+ // TODO
+}
+
+void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldlen) {
+ // TODO
+}
+
+void TextBufferWindow::touch(int line) {
+ int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
+ _lines[line].dirty = 1;
+ _windows->clearSelection();
+ _windows->repaint(Common::Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
+}
+
+glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
+ return (vertical) ? size * g_conf->_cellW : size * g_conf->_cellH;
+}
+
+void TextBufferWindow::putChar(unsigned char ch) {
+}
+
+void TextBufferWindow::putCharUni(glui32 ch) {
+ /*
+ glui32 bchars[TBLINELEN];
+ Attributes battrs[TBLINELEN];
+ int pw;
+ int bpoint;
+ int saved;
+ int i;
+ int linelen;
+ unsigned char *color;
+
+ gli_tts_speak(&ch, 1);
+
+ pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2 - gli_scroll_width) * GLI_SUBPIX;
+ pw = pw - 2 * SLOP - radjw - ladjw;
+
+ color = Windows::_overrideBgSet ? gli_window_color : bgcolor;
+
+ // oops ... overflow
+ if (numchars + 1 >= TBLINELEN)
+ scrolloneline(dwin, 0);
+
+ if (ch == '\n') {
+ scrolloneline(dwin, 1);
+ return;
+ }
+
+ if (gli_conf_quotes) {
+ // fails for 'tis a wonderful day in the '80s
+ if (gli_conf_quotes > 1 && ch == '\'')
+ {
+ if (numchars == 0 || leftquote(_chars[numchars - 1]))
+ ch = UNI_LSQUO;
+ }
+
+ if (ch == '`')
+ ch = UNI_LSQUO;
+
+ if (ch == '\'')
+ ch = UNI_RSQUO;
+
+ if (ch == '"')
+ {
+ if (numchars == 0 || leftquote(_chars[numchars - 1]))
+ ch = UNI_LDQUO;
+ else
+ ch = UNI_RDQUO;
+ }
+ }
+
+ if (gli_conf_dashes && attr.style != style_Preformatted)
+ {
+ if (ch == '-')
+ {
+ dashed++;
+ if (dashed == 2)
+ {
+ numchars--;
+ if (gli_conf_dashes == 2)
+ ch = UNI_NDASH;
+ else
+ ch = UNI_MDASH;
+ }
+ if (dashed == 3)
+ {
+ numchars--;
+ ch = UNI_MDASH;
+ dashed = 0;
+ }
+ }
+ else
+ dashed = 0;
+ }
+
+ if (gli_conf_spaces && attr.style != style_Preformatted
+ && styles[attr.style].bg == color
+ && !styles[attr.style].reverse)
+ {
+ // turn (period space space) into (period space)
+ if (gli_conf_spaces == 1)
+ {
+ if (ch == '.')
+ spaced = 1;
+ else if (ch == ' ' && spaced == 1)
+ spaced = 2;
+ else if (ch == ' ' && spaced == 2)
+ {
+ spaced = 0;
+ return;
+ }
+ else
+ spaced = 0;
+ }
+
+ // Turn (per sp x) into (per sp sp x)
+ if (gli_conf_spaces == 2)
+ {
+ if (ch == '.')
+ spaced = 1;
+ else if (ch == ' ' && spaced == 1)
+ spaced = 2;
+ else if (ch != ' ' && spaced == 2)
+ {
+ spaced = 0;
+ win_textbuffer_putchar_uni(win, ' ');
+ }
+ else
+ spaced = 0;
+ }
+ }
+
+ _chars[numchars] = ch;
+ attrs[numchars] = attr;
+ numchars++;
+
+ // kill spaces at the end for line width calculation
+ linelen = numchars;
+ while (linelen > 1 && _chars[linelen - 1] == ' '
+ && styles[attrs[linelen - 1].style].bg == color
+ && !styles[attrs[linelen - 1].style].reverse)
+ linelen--;
+
+ if (calcwidth(dwin, _chars, attrs, 0, linelen, -1) >= pw)
+ {
+ bpoint = numchars;
+
+ for (i = numchars - 1; i > 0; i--)
+ if (_chars[i] == ' ')
+ {
+ bpoint = i + 1; // skip space
+ break;
+ }
+
+ saved = numchars - bpoint;
+
+ memcpy(bchars, _chars + bpoint, saved * 4);
+ memcpy(battrs, attrs + bpoint, saved * sizeof(attr_t));
+ numchars = bpoint;
+
+ scrolloneline(dwin, 0);
+
+ memcpy(_chars, bchars, saved * 4);
+ memcpy(attrs, battrs, saved * sizeof(attr_t));
+ numchars = saved;
+ }
+
+ touch(0);
+ */
+}
+
+bool TextBufferWindow::unputCharUni(uint32 ch) {
+ // TODO
+ return false;
+}
+
+void TextBufferWindow::putBuffer(const unsigned char *buf, size_t len) {
+ // TODO
+}
+
+void TextBufferWindow::putBufferUni(const uint32 *buf, size_t len) {
+ // TODO
+}
+
+void TextBufferWindow::moveCursor(const Common::Point &newPos) {
+ // TODO
+}
+
+void TextBufferWindow::clear() {
+ int i;
+
+ _attr.fgset = Windows::_overrideFgSet;
+ _attr.bgset = Windows::_overrideBgSet;
+ _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
+ _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
+ _attr.reverse = false;
+
+ _ladjw = _radjw = 0;
+ _ladjn = _radjn = 0;
+
+ _spaced = 0;
+ _dashed = 0;
+
+ _numChars = 0;
+
+ for (i = 0; i < _scrollBack; i++) {
+ _lines[i].len = 0;
+
+ if (_lines[i].lpic) _lines[i].lpic->decrement();
+ _lines[i].lpic = nullptr;
+ if (_lines[i].rpic) _lines[i].rpic->decrement();
+ _lines[i].rpic = nullptr;
+
+ _lines[i].lhyper = 0;
+ _lines[i].rhyper = 0;
+ _lines[i].lm = 0;
+ _lines[i].rm = 0;
+ _lines[i].newline = 0;
+ _lines[i].dirty = true;
+ _lines[i].repaint = false;
+ }
+
+ _lastSeen = 0;
+ _scrollPos = 0;
+ _scrollMax = 0;
+
+ for (i = 0; i < _height; i++)
+ touch(i);
+}
+
+void TextBufferWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
+ {
+ warning("request_line_event: window already has keyboard request");
+ return;
+ }
+
+ // TODO
+}
+
+void TextBufferWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
+ {
+ warning("request_line_event_uni: window already has keyboard request");
+ return;
+ }
+
+ // TODO
+}
+
+void TextBufferWindow::cancelLineEvent(Event *ev) {
+ gidispatch_rock_t inarrayrock;
+ int ix;
+ int len;
+ void *inbuf;
+ int inmax;
+ int unicode = _lineRequestUni;
+ Event dummyEv;
+
+ if (!ev)
+ ev = &dummyEv;
+
+ g_vm->_events->clearEvent(ev);
+
+ if (!_lineRequest && !_lineRequestUni)
+ return;
+
+ if (!_inBuf)
+ return;
+
+ inbuf = _inBuf;
+ inmax = _inMax;
+ inarrayrock = _inArrayRock;
+
+ len = _numChars - _inFence;
+ if (_echoStream)
+ _echoStream->echoLineUni(_chars + _inFence, len);
+
+ if (len > inmax)
+ len = inmax;
+
+ if (!unicode) {
+ for (ix = 0; ix<len; ix++) {
+ glui32 ch = _chars[_inFence + ix];
+ if (ch > 0xff)
+ ch = '?';
+ ((char *)inbuf)[ix] = (char)ch;
+ }
+ }
+ else {
+ for (ix = 0; ix<len; ix++)
+ ((glui32 *)inbuf)[ix] = _chars[_inFence + ix];
+ }
+
+ _attr = _origAttr;
+
+ ev->_type = evtype_LineInput;
+ ev->_window = this;
+ ev->_val1 = len;
+ ev->_val2 = 0;
+
+ _lineRequest = false;
+ _lineRequestUni = false;
+ if (_lineTerminators) {
+ free(_lineTerminators);
+ _lineTerminators = nullptr;
+ }
+ _inBuf = nullptr;
+ _inMax = 0;
+
+ if (_echoLineInput) {
+ putCharUni('\n');
+ }
+ else {
+ _numChars = _inFence;
+ touch(0);
+ }
+
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
+}
+
+void TextBufferWindow::redraw() {
+ // TODO
+}
+
+/*--------------------------------------------------------------------------*/
+
+TextBufferWindow::TextBufferRow::TextBufferRow() : len(0), newline(0), dirty(false), repaint(false),
+ lpic(nullptr), rpic(nullptr), lhyper(0), rhyper(0), lm(0), rm(0) {
+}
+
+void TextBufferWindow::TextBufferRow::resize(size_t newSize) {
+ chars.clear();
+ attr.clear();
+ chars.resize(newSize);
+ attr.resize(newSize);
+ Common::fill(&chars[0], &chars[0] + newSize, ' ');
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_buffer.h b/engines/gargoyle/window_text_buffer.h
new file mode 100644
index 0000000000..f7427d7320
--- /dev/null
+++ b/engines/gargoyle/window_text_buffer.h
@@ -0,0 +1,198 @@
+/* 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_WINDOW_TEXT_BUFFER_H
+#define GARGOYLE_WINDOW_TEXT_BUFFER_H
+
+#include "gargoyle/windows.h"
+#include "gargoyle/picture.h"
+
+namespace Gargoyle {
+
+/**
+ * Text Buffer window
+ */
+class TextBufferWindow : public Window {
+ /**
+ * Structure for a row within the window
+ */
+ struct TextBufferRow {
+ Common::Array<uint32> chars;
+ Common::Array<Attributes> attr;
+ int len, newline;
+ bool dirty, repaint;
+ Picture *lpic, *rpic;
+ glui32 lhyper, rhyper;
+ int lm, rm;
+
+ /**
+ * Constructor
+ */
+ TextBufferRow();
+
+ /**
+ * Resize the row
+ */
+ void resize(size_t newSize);
+ };
+ typedef Common::Array<TextBufferRow> TextBufferRows;
+private:
+ void reflow();
+ void touchScroll();
+ bool putPicture(Picture *pic, glui32 align, glui32 linkval);
+ void putTextUni(const glui32 *buf, int len, int pos, int oldlen);
+ void flowBreak();
+
+ /**
+ * Mark a given text row as modified
+ */
+ void touch(int line);
+public:
+ int _width, _height;
+ int _spaced;
+ int _dashed;
+
+ TextBufferRows _lines;
+ int _scrollBack;
+
+ int _numChars; ///< number of chars in last line: lines[0]
+ glui32 *_chars; ///< alias to lines[0].chars
+ Attributes *_attrs; ///< alias to lines[0].attrs
+
+ ///< adjust margins temporarily for images
+ int _ladjw;
+ int _ladjn;
+ int _radjw;
+ int _radjn;
+
+ /* Command history. */
+ glui32 *_history[HISTORYLEN];
+ int _historyPos;
+ int _historyFirst, _historyPresent;
+
+ /* for paging */
+ int _lastSeen;
+ int _scrollPos;
+ int _scrollMax;
+
+ /* for line input */
+ void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
+ int _inMax;
+ long _inFence;
+ long _inCurs;
+ Attributes _origAttr;
+ gidispatch_rock_t _inArrayRock;
+
+ glui32 _echoLineInput;
+ glui32 *_lineTerminators;
+
+ /* style hints and settings */
+ WindowStyle styles[style_NUMSTYLES];
+
+ /* for copy selection */
+ glui32 *_copyBuf;
+ int _copyPos;
+public:
+ /**
+ * Constructor
+ */
+ TextBufferWindow(Windows *windows, uint32 rock);
+
+ /**
+ * Destructor
+ */
+ virtual ~TextBufferWindow();
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Get window split size within parent pair window
+ */
+ virtual glui32 getSplit(glui32 size, bool vertical) const override;
+
+ /**
+ * Write a character
+ */
+ virtual void putChar(unsigned char ch) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putCharUni(uint32 ch) override;
+
+ /**
+ * Unput a unicode character
+ */
+ virtual bool unputCharUni(uint32 ch) override;
+
+ /**
+ * Write a buffer
+ */
+ virtual void putBuffer(const unsigned char *buf, size_t len) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putBufferUni(const uint32 *buf, size_t len) override;
+
+ /**
+ * Move the cursor
+ */
+ virtual void moveCursor(const Common::Point &newPos) override;
+
+ /**
+ * Clear the window
+ */
+ virtual void clear() override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Cancel an input line event
+ */
+ virtual void cancelLineEvent(Event *ev) override;
+
+ /**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/window_text_grid.cpp b/engines/gargoyle/window_text_grid.cpp
new file mode 100644
index 0000000000..41444ed33c
--- /dev/null
+++ b/engines/gargoyle/window_text_grid.cpp
@@ -0,0 +1,665 @@
+/* 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/window_text_grid.h"
+#include "gargoyle/conf.h"
+#include "gargoyle/gargoyle.h"
+
+namespace Gargoyle {
+
+TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
+ _type = wintype_TextGrid;
+ _width = _height = 0;
+ _curX = _curY = 0;
+ _inBuf = nullptr;
+ _inOrgX = _inOrgY = 0;
+ _inMax = 0;
+ _inCurs = _inLen = 0;
+ _inArrayRock.num = 0;
+ _lineTerminators = nullptr;
+
+ Common::copy(&g_conf->_gStyles[0], &g_conf->_gStyles[style_NUMSTYLES], styles);
+}
+
+TextGridWindow::~TextGridWindow() {
+ if (_inBuf) {
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(_inBuf, _inMax, "&+#!Cn", _inArrayRock);
+ _inBuf = nullptr;
+ }
+
+ delete[] _lineTerminators;
+}
+
+void TextGridWindow::rearrange(const Common::Rect &box) {
+ Window::rearrange(box);
+ int newwid, newhgt;
+
+ newwid = box.width() / g_conf->_cellW;
+ newhgt = box.height() / g_conf->_cellH;
+
+ if (newwid == _width && newhgt == _height)
+ return;
+
+ _lines.resize(newhgt);
+ for (int y = 0; y < newhgt; ++y) {
+ _lines[y].resize(newwid);
+ touch(y);
+ }
+
+ _attr.clear();
+ _width = newwid;
+ _height = newhgt;
+}
+
+void TextGridWindow::touch(int line) {
+ int y = _bbox.top + line * g_conf->_leading;
+ _lines[line].dirty = true;
+ _windows->repaint(Common::Rect(_bbox.left, y, _bbox.right, y + g_conf->_leading));
+}
+
+glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
+ return vertical ? size * g_conf->_cellW + g_conf->_tMarginX * 2 :
+ size * g_conf->_cellH + g_conf->_tMarginY * 2;
+}
+
+void TextGridWindow::putChar(unsigned char ch) {
+
+}
+
+void TextGridWindow::putCharUni(uint32 ch) {
+ TextGridRow *ln;
+
+ // Canonicalize the cursor position. That is, the cursor may have been
+ // left outside the window area; wrap it if necessary.
+ if (_curX < 0) {
+ _curX = 0;
+ } else if (_curX >= _width) {
+ _curX = 0;
+ _curY++;
+ }
+ if (_curY < 0)
+ _curY = 0;
+ else if (_curY >= _height)
+ return; /* outside the window */
+
+ if (ch == '\n') {
+ /* a newline just moves the cursor. */
+ _curY++;
+ _curX = 0;
+ return;
+ }
+
+ touch(_curY);
+
+ ln = &(_lines[_curY]);
+ ln->_chars[_curX] = ch;
+ ln->_attrs[_curX] = _attr;
+
+ _curX++;
+ // We can leave the cursor outside the window, since it will be
+ // canonicalized next time a character is printed.
+}
+
+bool TextGridWindow::unputCharUni(uint32 ch) {
+ TextGridRow *ln;
+ int oldx = _curX, oldy = _curY;
+
+ /* Move the cursor back. */
+ if (_curX >= _width)
+ _curX = _width - 1;
+ else
+ _curX--;
+
+ /* Canonicalize the cursor position. That is, the cursor may have been
+ left outside the window area; wrap it if necessary. */
+ if (_curX < 0) {
+ _curX = _width - 1;
+ _curY--;
+ }
+ if (_curY < 0)
+ _curY = 0;
+ else if (_curY >= _height)
+ return false; // outside the window
+
+ if (ch == '\n') {
+ // a newline just moves the cursor.
+ if (_curX == _width - 1)
+ return 1; // deleted a newline
+ _curX = oldx;
+ _curY = oldy;
+ return 0; // it wasn't there */
+ }
+
+ ln = &(_lines[_curY]);
+ if (ln->_chars[_curX] == ch) {
+ ln->_chars[_curX] = ' ';
+ ln->_attrs[_curX].clear();
+ touch(_curY);
+ return true; // deleted the char
+ } else {
+ _curX = oldx;
+ _curY = oldy;
+ return false; // it wasn't there
+ }
+}
+
+void TextGridWindow::putBuffer(const unsigned char *buf, size_t len) {
+ // TODO
+}
+
+void TextGridWindow::putBufferUni(const uint32 *buf, size_t len) {
+ // TODO
+}
+
+void TextGridWindow::moveCursor(const Common::Point &pos) {
+ // If the values are negative, they're really huge positive numbers --
+ // remember that they were cast from glui32. So set them huge and
+ // let canonicalization take its course.
+ _curX = (pos.x < 0) ? 32767 : pos.x;
+ _curY = (pos.y < 0) ? 32767 : pos.y;
+}
+
+void TextGridWindow::clear() {
+ _attr.fgset = Windows::_overrideFgSet;
+ _attr.bgset = Windows::_overrideBgSet;
+ _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
+ _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
+ _attr.reverse = false;
+
+ for (int k = 0; k < _height; k++) {
+ TextGridRow &ln = _lines[k];
+ touch(k);
+ for (uint j = 0; j < ln._attrs.size(); ++j) {
+ ln._chars[j] = ' ';
+ ln._attrs[j].clear();
+ }
+ }
+
+ _curX = 0;
+ _curY = 0;
+}
+
+void TextGridWindow::click(const Common::Point &newPos) {
+ int x = newPos.x - _bbox.left;
+ int y = newPos.y - _bbox.top;
+
+ if (_lineRequest || _charRequest || _lineRequestUni || _charRequestUni
+ || _moreRequest || _scrollRequest)
+ _windows->setFocus(this);
+
+ if (_mouseRequest) {
+ g_vm->_events->eventStore(evtype_MouseInput, this, x / g_conf->_cellW, y / g_conf->_leading);
+ _mouseRequest = false;
+ if (g_conf->_safeClicks)
+ g_vm->_events->_forceClick = true;
+ }
+
+ if (_hyperRequest) {
+ glui32 linkval = _windows->getHyperlink(newPos);
+ if (linkval)
+ {
+ g_vm->_events->eventStore(evtype_Hyperlink, this, linkval, 0);
+ _hyperRequest = false;
+ if (g_conf->_safeClicks)
+ g_vm->_events->_forceClick = true;
+ }
+ }
+}
+
+void TextGridWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
+ {
+ warning("request_line_event: window already has keyboard request");
+ return;
+ }
+
+ if ((int)maxlen > (_width - _curX))
+ maxlen = (_width - _curX);
+
+ _inBuf = buf;
+ _inMax = maxlen;
+ _inLen = 0;
+ _inCurs = 0;
+ _inOrgX = _curX;
+ _inOrgY = _curY;
+ _origAttr = _attr;
+ _attr.set(style_Input);
+
+ if (initlen > maxlen)
+ initlen = maxlen;
+
+ if (initlen) {
+ TextGridRow *ln = &_lines[_inOrgY];
+
+ for (glui32 ix = 0; ix < initlen; ix++) {
+ ln->_attrs[_inOrgX + ix].set(style_Input);
+ ln->_chars[_inOrgX + ix] = buf[ix];
+ }
+
+ _inCurs += initlen;
+ _inLen += initlen;
+ _curX = _inOrgX + _inCurs;
+ _curY = _inOrgY;
+
+ touch(_inOrgY);
+ }
+
+ if (_lineTerminatorsBase && _termCt) {
+ _lineTerminators = new glui32[_termCt + 1];
+
+ if (_lineTerminators) {
+ memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
+ _lineTerminators[_termCt] = 0;
+ }
+ }
+
+ if (g_vm->gli_register_arr)
+ _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Cn");
+}
+
+void TextGridWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
+ if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni) {
+ warning("requestLineEventUni: window already has keyboard request");
+ return;
+ }
+
+ if ((int)maxlen > (_width - _curX))
+ maxlen = (_width - _curX);
+
+ _inBuf = buf;
+ _inMax = maxlen;
+ _inLen = 0;
+ _inCurs = 0;
+ _inOrgX = _curX;
+ _inOrgY = _curY;
+ _origAttr = _attr;
+ _attr.set(style_Input);
+
+ if (initlen > maxlen)
+ initlen = maxlen;
+
+ if (initlen) {
+ TextGridRow *ln = &(_lines[_inOrgY]);
+
+ for (glui32 ix = 0; ix<initlen; ix++) {
+ ln->_attrs[_inOrgX + ix].set(style_Input);
+ ln->_chars[_inOrgX + ix] = buf[ix];
+ }
+
+ _inCurs += initlen;
+ _inLen += initlen;
+ _curX = _inOrgX + _inCurs;
+ _curY = _inOrgY;
+
+ touch(_inOrgY);
+ }
+
+ if (_lineTerminatorsBase && _termCt) {
+ _lineTerminators = new glui32[_termCt + 1];
+
+ if (_lineTerminators) {
+ memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
+ _lineTerminators[_termCt] = 0;
+ }
+ }
+
+ if (g_vm->gli_register_arr)
+ _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Iu");
+}
+
+void TextGridWindow::cancelLineEvent(Event *ev) {
+ int ix;
+ void *inbuf;
+ int inmax;
+ int unicode = _lineRequestUni;
+ gidispatch_rock_t inarrayrock;
+ TextGridRow *ln = &_lines[_inOrgY];
+ Event dummyEv;
+
+ if (!ev)
+ ev = &dummyEv;
+
+ g_vm->_events->clearEvent(ev);
+
+ if (!_lineRequest && !_lineRequestUni)
+ return;
+
+
+ inbuf = _inBuf;
+ inmax = _inMax;
+ inarrayrock = _inArrayRock;
+
+ if (!unicode) {
+ for (ix = 0; ix<_inLen; ix++)
+ {
+ glui32 ch = ln->_chars[_inOrgX + ix];
+ if (ch > 0xff)
+ ch = '?';
+ ((char *)inbuf)[ix] = (char)ch;
+ }
+ if (_echoStream)
+ _echoStream->echoLine((char *)_inBuf, _inLen);
+ } else {
+ for (ix = 0; ix<_inLen; ix++)
+ ((glui32 *)inbuf)[ix] = ln->_chars[_inOrgX + ix];
+ if (_echoStream)
+ _echoStream->echoLineUni((glui32 *)inbuf, _inLen);
+ }
+
+ _curY = _inOrgY + 1;
+ _curX = 0;
+ _attr = _origAttr;
+
+ ev->_type = evtype_LineInput;
+ ev->_window = this;
+ ev->_val1 = _inLen;
+ ev->_val2 = 0;
+
+ _lineRequest = false;
+ _lineRequestUni = false;
+
+ if (_lineTerminators) {
+ free(_lineTerminators);
+ _lineTerminators = nullptr;
+ }
+
+ _inBuf = nullptr;
+ _inMax = 0;
+ _inOrgX = 0;
+ _inOrgY = 0;
+
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
+}
+
+void TextGridWindow::acceptReadChar(glui32 arg) {
+ glui32 key;
+
+ switch (arg)
+ {
+ case keycode_Erase:
+ key = keycode_Delete;
+ break;
+ case keycode_MouseWheelUp:
+ case keycode_MouseWheelDown:
+ return;
+ default:
+ key = arg;
+ }
+
+ if (key > 0xff && key < (0xffffffff - keycode_MAXVAL + 1))
+ {
+ if (!(_charRequestUni) || key > 0x10ffff)
+ key = keycode_Unknown;
+ }
+
+ _charRequest = false;
+ _charRequestUni = false;
+ g_vm->_events->eventStore(evtype_CharInput, this, key, 0);
+}
+
+void TextGridWindow::acceptLine(glui32 keycode) {
+ int ix;
+ void *inbuf;
+ int inmax;
+ gidispatch_rock_t inarrayrock;
+ TextGridRow *ln = &(_lines[_inOrgY]);
+ int unicode = _lineRequestUni;
+
+ if (!_inBuf)
+ return;
+
+ inbuf = _inBuf;
+ inmax = _inMax;
+ inarrayrock = _inArrayRock;
+
+ if (!unicode) {
+ for (ix = 0; ix<_inLen; ix++)
+ ((char *)inbuf)[ix] = (char)ln->_chars[_inOrgX + ix];
+ if (_echoStream)
+ _echoStream->echoLine((char *)inbuf, _inLen);
+ } else {
+ for (ix = 0; ix<_inLen; ix++)
+ ((glui32 *)inbuf)[ix] = ln->_chars[_inOrgX + ix];
+ if (_echoStream)
+ _echoStream->echoLineUni((glui32 *)inbuf, _inLen);
+ }
+
+ _curY = _inOrgY + 1;
+ _curX = 0;
+ _attr = _origAttr;
+
+ if (_lineTerminators)
+ {
+ glui32 val2 = keycode;
+ if (val2 == keycode_Return)
+ val2 = 0;
+ g_vm->_events->eventStore(evtype_LineInput, this, _inLen, val2);
+ free(_lineTerminators);
+ _lineTerminators = NULL;
+ } else {
+ g_vm->_events->eventStore(evtype_LineInput, this, _inLen, 0);
+ }
+ _lineRequest = false;
+ _lineRequestUni = false;
+ _inBuf = NULL;
+ _inMax = 0;
+ _inOrgX = 0;
+ _inOrgY = 0;
+
+ if (g_vm->gli_unregister_arr)
+ (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
+}
+
+void TextGridWindow::acceptReadLine(glui32 arg) {
+ int ix;
+ TextGridRow *ln = &(_lines[_inOrgY]);
+
+ if (!_inBuf)
+ return;
+
+ if (_lineTerminators && checkTerminator(arg)) {
+ glui32 *cx;
+ for (cx = _lineTerminators; *cx; cx++) {
+ if (*cx == arg) {
+ acceptLine(arg);
+ return;
+ }
+ }
+ }
+
+ switch (arg) {
+
+ /* Delete keys, during line input. */
+
+ case keycode_Delete:
+ if (_inLen <= 0)
+ return;
+ if (_inCurs <= 0)
+ return;
+ for (ix = _inCurs; ix<_inLen; ix++)
+ ln->_chars[_inOrgX + ix - 1] = ln->_chars[_inOrgX + ix];
+ ln->_chars[_inOrgX + _inLen - 1] = ' ';
+ _inCurs--;
+ _inLen--;
+ break;
+
+ case keycode_Erase:
+ if (_inLen <= 0)
+ return;
+ if (_inCurs >= _inLen)
+ return;
+ for (ix = _inCurs; ix<_inLen - 1; ix++)
+ ln->_chars[_inOrgX + ix] = ln->_chars[_inOrgX + ix + 1];
+ ln->_chars[_inOrgX + _inLen - 1] = ' ';
+ _inLen--;
+ break;
+
+ case keycode_Escape:
+ if (_inLen <= 0)
+ return;
+ for (ix = 0; ix<_inLen; ix++)
+ ln->_chars[_inOrgX + ix] = ' ';
+ _inLen = 0;
+ _inCurs = 0;
+ break;
+
+ /* Cursor movement keys, during line input. */
+
+ case keycode_Left:
+ if (_inCurs <= 0)
+ return;
+ _inCurs--;
+ break;
+
+ case keycode_Right:
+ if (_inCurs >= _inLen)
+ return;
+ _inCurs++;
+ break;
+
+ case keycode_Home:
+ if (_inCurs <= 0)
+ return;
+ _inCurs = 0;
+ break;
+
+ case keycode_End:
+ if (_inCurs >= _inLen)
+ return;
+ _inCurs = _inLen;
+ break;
+
+ case keycode_Return:
+ acceptLine(arg);
+ break;
+
+ default:
+ if (_inLen >= _inMax)
+ return;
+
+ if (arg < 32 || arg > 0xff)
+ return;
+
+ if (g_conf->_caps && (arg > 0x60 && arg < 0x7b))
+ arg -= 0x20;
+
+ for (ix = _inLen; ix>_inCurs; ix--)
+ ln->_chars[_inOrgX + ix] = ln->_chars[_inOrgX + ix - 1];
+ ln->_attrs[_inOrgX + _inLen].set(style_Input);
+ ln->_chars[_inOrgX + _inCurs] = arg;
+
+ _inCurs++;
+ _inLen++;
+ }
+
+ _curX = _inOrgX + _inCurs;
+ _curY = _inOrgY;
+
+ touch(_inOrgY);
+}
+
+void TextGridWindow::redraw() {
+ TextGridRow *ln;
+ int x0, y0;
+ int x, y, w;
+ int i, a, b, k, o;
+ glui32 link;
+ int font;
+ byte *fgcolor, *bgcolor;
+
+ x0 = _bbox.left;
+ y0 = _bbox.top;
+
+ for (i = 0; i < _height; i++) {
+ ln = &_lines[i];
+ if (ln->dirty || Windows::_forceRedraw) {
+ ln->dirty = 0;
+
+ x = x0;
+ y = y0 + i * g_conf->_leading;
+
+ /* clear any stored hyperlink coordinates */
+ _windows->setHyperlink(0, x0, y, x0 + g_conf->_cellW * _width, y + g_conf->_leading);
+
+ a = 0;
+ for (b = 0; b < _width; b++) {
+ if (ln->_attrs[a] == ln->_attrs[b]) {
+ link = ln->_attrs[a].hyper;
+ font = ln->_attrs[a].attrFont(styles);
+ fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
+ bgcolor = ln->_attrs[a].attrBg(styles);
+ w = (b - a) * g_conf->_cellW;
+ _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
+ o = x;
+
+ for (k = a; k < b; k++) {
+ drawStringUni(o * GLI_SUBPIX,
+ y + g_conf->_baseLine, font, fgcolor,
+ &ln->_chars[k], 1, -1);
+ o += g_conf->_cellW;
+ }
+ if (link) {
+ _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
+ g_conf->_linkStyle, g_conf->_linkColor);
+ _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
+ }
+ x += w;
+ a = b;
+ }
+ }
+ link = ln->_attrs[a].hyper;
+ font = ln->_attrs[a].attrFont(styles);
+ fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
+ bgcolor = ln->_attrs[a].attrBg(styles);
+ w = (b - a) * g_conf->_cellW;
+ w += _bbox.right - (x + w);
+ _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
+
+ o = x;
+ for (k = a; k < b; k++) {
+ drawStringUni(o * GLI_SUBPIX,
+ y + g_conf->_baseLine, font, fgcolor,
+ &ln->_chars[k], 1, -1);
+ o += g_conf->_cellW;
+ }
+ if (link) {
+ _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
+ g_conf->_linkStyle, g_conf->_linkColor);
+ _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+void TextGridWindow::TextGridRow::resize(size_t newSize) {
+ _chars.clear();
+ _attrs.clear();
+ _chars.resize(newSize);
+ _attrs.resize(newSize);
+ Common::fill(&_chars[0], &_chars[0] + newSize, ' ');
+}
+
+} // End of namespace Gargoyle
diff --git a/engines/gargoyle/window_text_grid.h b/engines/gargoyle/window_text_grid.h
new file mode 100644
index 0000000000..2c72dde458
--- /dev/null
+++ b/engines/gargoyle/window_text_grid.h
@@ -0,0 +1,180 @@
+/* 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_WINDOW_TEXT_GRID_H
+#define GARGOYLE_WINDOW_TEXT_GRID_H
+
+#include "gargoyle/windows.h"
+
+namespace Gargoyle {
+
+/**
+ * Text Grid window
+ */
+class TextGridWindow : public Window {
+ /**
+ * Structure for a row within the grid window
+ */
+ struct TextGridRow {
+ Common::Array<uint32> _chars;
+ Common::Array<Attributes> _attrs;
+ bool dirty;
+
+ /**
+ * Constructor
+ */
+ TextGridRow() : dirty(false) {}
+
+ /**
+ * Resize the row
+ */
+ void resize(size_t newSize);
+ };
+ typedef Common::Array<TextGridRow> TextGridRows;
+private:
+ /**
+ * Mark a given text row as modified
+ */
+ void touch(int line);
+
+ void acceptReadChar(glui32 arg);
+
+ /**
+ * Return or enter, during line input. Ends line input.
+ */
+ void acceptLine(glui32 keycode);
+
+ /**
+ * Any regular key, during line input.
+ */
+ void acceptReadLine(glui32 arg);
+public:
+ int _width, _height;
+ TextGridRows _lines;
+
+ int _curX, _curY; ///< the window cursor position
+
+ ///< for line input
+ void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
+ int _inOrgX, _inOrgY;
+ int _inMax;
+ int _inCurs, _inLen;
+ Attributes _origAttr;
+ gidispatch_rock_t _inArrayRock;
+ glui32 *_lineTerminators;
+
+ WindowStyle styles[style_NUMSTYLES]; ///< style hints and settings
+public:
+ /**
+ * Constructor
+ */
+ TextGridWindow(Windows *windows, uint32 rock);
+
+ /**
+ * Destructor
+ */
+ virtual ~TextGridWindow();
+
+ /**
+ * Rearranges the window
+ */
+ virtual void rearrange(const Common::Rect &box) override;
+
+ /**
+ * Get window split size within parent pair window
+ */
+ virtual glui32 getSplit(glui32 size, bool vertical) const override;
+
+ /**
+ * Write a character
+ */
+ virtual void putChar(unsigned char ch) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putCharUni(uint32 ch) override;
+
+ /**
+ * Unput a unicode character
+ */
+ virtual bool unputCharUni(uint32 ch) override;
+
+ /**
+ * Write a buffer
+ */
+ virtual void putBuffer(const unsigned char *buf, size_t len) override;
+
+ /**
+ * Write a unicode character
+ */
+ virtual void putBufferUni(const uint32 *buf, size_t len) override;
+
+ /**
+ * Move the cursor
+ */
+ virtual void moveCursor(const Common::Point &newPos) override;
+
+ /**
+ * Clear the window
+ */
+ virtual void clear() override;
+
+ /**
+ * Click the window
+ */
+ virtual void click(const Common::Point &newPos) override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Prepare for inputing a line
+ */
+ virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) override;
+
+ /**
+ * Cancel an input line event
+ */
+ virtual void cancelLineEvent(Event *ev) override;
+
+ /**
+ * Cancel a mouse event
+ */
+ virtual void cancelMouseEvent() override { _mouseRequest = false; }
+
+ /**
+ * Cancel a hyperlink event
+ */
+ virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
+
+ /**
+ * Redraw the window
+ */
+ virtual void redraw() override;
+};
+
+} // End of namespace Gargoyle
+
+#endif
diff --git a/engines/gargoyle/windows.cpp b/engines/gargoyle/windows.cpp
index a625040f8d..cf9b7de77d 100644
--- a/engines/gargoyle/windows.cpp
+++ b/engines/gargoyle/windows.cpp
@@ -21,6 +21,10 @@
*/
#include "gargoyle/windows.h"
+#include "gargoyle/window_graphics.h"
+#include "gargoyle/window_pair.h"
+#include "gargoyle/window_text_buffer.h"
+#include "gargoyle/window_text_grid.h"
#include "gargoyle/conf.h"
#include "gargoyle/gargoyle.h"
#include "gargoyle/streams.h"
@@ -29,9 +33,6 @@
namespace Gargoyle {
-#define MAGIC_WINDOW_NUM (9876)
-#define GLI_SUBPIX 8
-
bool Windows::_overrideReverse;
bool Windows::_overrideFgSet;
bool Windows::_overrideBgSet;
@@ -47,41 +48,6 @@ byte Windows::_zcolor_Bright[3];
/*--------------------------------------------------------------------------*/
-Windows::iterator &Windows::iterator::operator++() {
- if (!_current)
- return *this;
-
- PairWindow *pairWin = dynamic_cast<PairWindow *>(_current);
-
- if (pairWin) {
- _current = !pairWin->_backward ? pairWin->_child1 : pairWin->_child2;
- } else {
- while (_current->_parent) {
- pairWin = dynamic_cast<PairWindow *>(_current->_parent);
-
- if (!pairWin->_backward) {
- if (_current == pairWin->_child1) {
- _current = pairWin->_child2;
- return *this;
- }
- } else {
- if (_current == pairWin->_child2) {
- _current = pairWin->_child1;
- return *this;
- }
- }
-
- _current = pairWin;
- }
-
- _current = nullptr;
- }
-
- return *this;
-}
-
-/*--------------------------------------------------------------------------*/
-
Windows::Windows(Graphics::Screen *screen) :
_screen(screen), _moreFocus(false), _windowList(nullptr),
_rootWin(nullptr), _focusWin(nullptr), _mask(nullptr), _claimSelect(0) {
@@ -286,9 +252,44 @@ byte *Windows::rgbShift(byte *rgb) {
/*--------------------------------------------------------------------------*/
-Window::Window(Windows *windows, glui32 rock) : _magicnum(MAGIC_WINDOW_NUM),
- _windows(windows), _rock(rock), _type(0), _parent(nullptr), _next(nullptr), _prev(nullptr),
- _yAdj(0), _lineRequest(0), _lineRequestUni(0), _charRequest(0), _charRequestUni(0),
+Windows::iterator &Windows::iterator::operator++() {
+ if (!_current)
+ return *this;
+
+ PairWindow *pairWin = dynamic_cast<PairWindow *>(_current);
+
+ if (pairWin) {
+ _current = !pairWin->_backward ? pairWin->_child1 : pairWin->_child2;
+ } else {
+ while (_current->_parent) {
+ pairWin = dynamic_cast<PairWindow *>(_current->_parent);
+
+ if (!pairWin->_backward) {
+ if (_current == pairWin->_child1) {
+ _current = pairWin->_child2;
+ return *this;
+ }
+ } else {
+ if (_current == pairWin->_child2) {
+ _current = pairWin->_child1;
+ return *this;
+ }
+ }
+
+ _current = pairWin;
+ }
+
+ _current = nullptr;
+ }
+
+ return *this;
+}
+
+/*--------------------------------------------------------------------------*/
+
+Window::Window(Windows *windows, glui32 rock) : _windows(windows), _rock(rock),
+ _type(0), _parent(nullptr), _next(nullptr), _prev(nullptr), _yAdj(0),
+ _lineRequest(0), _lineRequestUni(0), _charRequest(0), _charRequestUni(0),
_mouseRequest(0), _hyperRequest(0), _moreRequest(0), _scrollRequest(0), _imageLoaded(0),
_echoLineInput(true), _lineTerminatorsBase(nullptr), _termCt(0), _echoStream(nullptr) {
_attr.fgset = 0;
@@ -369,1382 +370,6 @@ BlankWindow::BlankWindow(Windows *windows, uint32 rock) : Window(windows, rock)
/*--------------------------------------------------------------------------*/
-TextGridWindow::TextGridWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
- _type = wintype_TextGrid;
- _width = _height = 0;
- _curX = _curY = 0;
- _inBuf = nullptr;
- _inOrgX = _inOrgY = 0;
- _inMax = 0;
- _inCurs = _inLen = 0;
- _inArrayRock.num = 0;
- _lineTerminators = nullptr;
-
- Common::copy(&g_conf->_gStyles[0], &g_conf->_gStyles[style_NUMSTYLES], styles);
-}
-
-TextGridWindow::~TextGridWindow() {
- if (_inBuf) {
- if (g_vm->gli_unregister_arr)
- (*g_vm->gli_unregister_arr)(_inBuf, _inMax, "&+#!Cn", _inArrayRock);
- _inBuf = nullptr;
- }
-
- delete[] _lineTerminators;
-}
-
-void TextGridWindow::rearrange(const Common::Rect &box) {
- Window::rearrange(box);
- int newwid, newhgt;
-
- newwid = box.width() / g_conf->_cellW;
- newhgt = box.height() / g_conf->_cellH;
-
- if (newwid == _width && newhgt == _height)
- return;
-
- _lines.resize(newhgt);
- for (int y = 0; y < newhgt; ++y) {
- _lines[y].resize(newwid);
- touch(y);
- }
-
- _attr.clear();
- _width = newwid;
- _height = newhgt;
-}
-
-void TextGridWindow::touch(int line) {
- int y = _bbox.top + line * g_conf->_leading;
- _lines[line].dirty = true;
- _windows->repaint(Common::Rect(_bbox.left, y, _bbox.right, y + g_conf->_leading));
-}
-
-glui32 TextGridWindow::getSplit(glui32 size, bool vertical) const {
- return vertical ? size * g_conf->_cellW + g_conf->_tMarginX * 2 :
- size * g_conf->_cellH + g_conf->_tMarginY * 2;
-}
-
-void TextGridWindow::putChar(unsigned char ch) {
-
-}
-
-void TextGridWindow::putCharUni(uint32 ch) {
- TextGridRow *ln;
-
- // Canonicalize the cursor position. That is, the cursor may have been
- // left outside the window area; wrap it if necessary.
- if (_curX < 0) {
- _curX = 0;
- } else if (_curX >= _width) {
- _curX = 0;
- _curY++;
- }
- if (_curY < 0)
- _curY = 0;
- else if (_curY >= _height)
- return; /* outside the window */
-
- if (ch == '\n') {
- /* a newline just moves the cursor. */
- _curY++;
- _curX = 0;
- return;
- }
-
- touch(_curY);
-
- ln = &(_lines[_curY]);
- ln->_chars[_curX] = ch;
- ln->_attrs[_curX] = _attr;
-
- _curX++;
- // We can leave the cursor outside the window, since it will be
- // canonicalized next time a character is printed.
-}
-
-bool TextGridWindow::unputCharUni(uint32 ch) {
- TextGridRow *ln;
- int oldx = _curX, oldy = _curY;
-
- /* Move the cursor back. */
- if (_curX >= _width)
- _curX = _width - 1;
- else
- _curX--;
-
- /* Canonicalize the cursor position. That is, the cursor may have been
- left outside the window area; wrap it if necessary. */
- if (_curX < 0) {
- _curX = _width - 1;
- _curY--;
- }
- if (_curY < 0)
- _curY = 0;
- else if (_curY >= _height)
- return false; // outside the window
-
- if (ch == '\n') {
- // a newline just moves the cursor.
- if (_curX == _width - 1)
- return 1; // deleted a newline
- _curX = oldx;
- _curY = oldy;
- return 0; // it wasn't there */
- }
-
- ln = &(_lines[_curY]);
- if (ln->_chars[_curX] == ch) {
- ln->_chars[_curX] = ' ';
- ln->_attrs[_curX].clear();
- touch(_curY);
- return true; // deleted the char
- } else {
- _curX = oldx;
- _curY = oldy;
- return false; // it wasn't there
- }
-}
-
-void TextGridWindow::putBuffer(const unsigned char *buf, size_t len) {
- // TODO
-}
-
-void TextGridWindow::putBufferUni(const uint32 *buf, size_t len) {
- // TODO
-}
-
-void TextGridWindow::moveCursor(const Common::Point &pos) {
- // If the values are negative, they're really huge positive numbers --
- // remember that they were cast from glui32. So set them huge and
- // let canonicalization take its course.
- _curX = (pos.x < 0) ? 32767 : pos.x;
- _curY = (pos.y < 0) ? 32767 : pos.y;
-}
-
-void TextGridWindow::clear() {
- _attr.fgset = Windows::_overrideFgSet;
- _attr.bgset = Windows::_overrideBgSet;
- _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
- _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
- _attr.reverse = false;
-
- for (int k = 0; k < _height; k++) {
- TextGridRow &ln = _lines[k];
- touch(k);
- for (uint j = 0; j < ln._attrs.size(); ++j) {
- ln._chars[j] = ' ';
- ln._attrs[j].clear();
- }
- }
-
- _curX = 0;
- _curY = 0;
-}
-
-void TextGridWindow::click(const Common::Point &newPos) {
- int x = newPos.x - _bbox.left;
- int y = newPos.y - _bbox.top;
-
- if (_lineRequest || _charRequest || _lineRequestUni || _charRequestUni
- || _moreRequest || _scrollRequest)
- _windows->setFocus(this);
-
- if (_mouseRequest) {
- g_vm->_events->eventStore(evtype_MouseInput, this, x / g_conf->_cellW, y / g_conf->_leading);
- _mouseRequest = false;
- if (g_conf->_safeClicks)
- g_vm->_events->_forceClick = true;
- }
-
- if (_hyperRequest) {
- glui32 linkval = _windows->getHyperlink(newPos);
- if (linkval)
- {
- g_vm->_events->eventStore(evtype_Hyperlink, this, linkval, 0);
- _hyperRequest = false;
- if (g_conf->_safeClicks)
- g_vm->_events->_forceClick = true;
- }
- }
-}
-
-void TextGridWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
- if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
- {
- warning("request_line_event: window already has keyboard request");
- return;
- }
-
- if ((int)maxlen > (_width - _curX))
- maxlen = (_width - _curX);
-
- _inBuf = buf;
- _inMax = maxlen;
- _inLen = 0;
- _inCurs = 0;
- _inOrgX = _curX;
- _inOrgY = _curY;
- _origAttr = _attr;
- _attr.set(style_Input);
-
- if (initlen > maxlen)
- initlen = maxlen;
-
- if (initlen) {
- TextGridRow *ln = &_lines[_inOrgY];
-
- for (glui32 ix = 0; ix < initlen; ix++) {
- ln->_attrs[_inOrgX + ix].set(style_Input);
- ln->_chars[_inOrgX + ix] = buf[ix];
- }
-
- _inCurs += initlen;
- _inLen += initlen;
- _curX = _inOrgX + _inCurs;
- _curY = _inOrgY;
-
- touch(_inOrgY);
- }
-
- if (_lineTerminatorsBase && _termCt) {
- _lineTerminators = new glui32[_termCt + 1];
-
- if (_lineTerminators) {
- memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
- _lineTerminators[_termCt] = 0;
- }
- }
-
- if (g_vm->gli_register_arr)
- _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Cn");
-}
-
-void TextGridWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
- if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni) {
- warning("requestLineEventUni: window already has keyboard request");
- return;
- }
-
- if ((int)maxlen > (_width - _curX))
- maxlen = (_width - _curX);
-
- _inBuf = buf;
- _inMax = maxlen;
- _inLen = 0;
- _inCurs = 0;
- _inOrgX = _curX;
- _inOrgY = _curY;
- _origAttr = _attr;
- _attr.set(style_Input);
-
- if (initlen > maxlen)
- initlen = maxlen;
-
- if (initlen) {
- TextGridRow *ln = &(_lines[_inOrgY]);
-
- for (glui32 ix = 0; ix<initlen; ix++) {
- ln->_attrs[_inOrgX + ix].set(style_Input);
- ln->_chars[_inOrgX + ix] = buf[ix];
- }
-
- _inCurs += initlen;
- _inLen += initlen;
- _curX = _inOrgX + _inCurs;
- _curY = _inOrgY;
-
- touch(_inOrgY);
- }
-
- if (_lineTerminatorsBase && _termCt) {
- _lineTerminators = new glui32[_termCt + 1];
-
- if (_lineTerminators) {
- memcpy(_lineTerminators, _lineTerminatorsBase, _termCt * sizeof(glui32));
- _lineTerminators[_termCt] = 0;
- }
- }
-
- if (g_vm->gli_register_arr)
- _inArrayRock = (*g_vm->gli_register_arr)(buf, maxlen, "&+#!Iu");
-}
-
-void TextGridWindow::cancelLineEvent(Event *ev) {
- int ix;
- void *inbuf;
- int inmax;
- int unicode = _lineRequestUni;
- gidispatch_rock_t inarrayrock;
- TextGridRow *ln = &_lines[_inOrgY];
- Event dummyEv;
-
- if (!ev)
- ev = &dummyEv;
-
- g_vm->_events->clearEvent(ev);
-
- if (!_lineRequest && !_lineRequestUni)
- return;
-
-
- inbuf = _inBuf;
- inmax = _inMax;
- inarrayrock = _inArrayRock;
-
- if (!unicode) {
- for (ix = 0; ix<_inLen; ix++)
- {
- glui32 ch = ln->_chars[_inOrgX + ix];
- if (ch > 0xff)
- ch = '?';
- ((char *)inbuf)[ix] = (char)ch;
- }
- if (_echoStream)
- _echoStream->echoLine((char *)_inBuf, _inLen);
- } else {
- for (ix = 0; ix<_inLen; ix++)
- ((glui32 *)inbuf)[ix] = ln->_chars[_inOrgX + ix];
- if (_echoStream)
- _echoStream->echoLineUni((glui32 *)inbuf, _inLen);
- }
-
- _curY = _inOrgY + 1;
- _curX = 0;
- _attr = _origAttr;
-
- ev->_type = evtype_LineInput;
- ev->_window = this;
- ev->_val1 = _inLen;
- ev->_val2 = 0;
-
- _lineRequest = false;
- _lineRequestUni = false;
-
- if (_lineTerminators) {
- free(_lineTerminators);
- _lineTerminators = nullptr;
- }
-
- _inBuf = nullptr;
- _inMax = 0;
- _inOrgX = 0;
- _inOrgY = 0;
-
- if (g_vm->gli_unregister_arr)
- (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
-}
-
-void TextGridWindow::acceptReadChar(glui32 arg) {
- glui32 key;
-
- switch (arg)
- {
- case keycode_Erase:
- key = keycode_Delete;
- break;
- case keycode_MouseWheelUp:
- case keycode_MouseWheelDown:
- return;
- default:
- key = arg;
- }
-
- if (key > 0xff && key < (0xffffffff - keycode_MAXVAL + 1))
- {
- if (!(_charRequestUni) || key > 0x10ffff)
- key = keycode_Unknown;
- }
-
- _charRequest = false;
- _charRequestUni = false;
- g_vm->_events->eventStore(evtype_CharInput, this, key, 0);
-}
-
-void TextGridWindow::acceptLine(glui32 keycode) {
- int ix;
- void *inbuf;
- int inmax;
- gidispatch_rock_t inarrayrock;
- TextGridRow *ln = &(_lines[_inOrgY]);
- int unicode = _lineRequestUni;
-
- if (!_inBuf)
- return;
-
- inbuf = _inBuf;
- inmax = _inMax;
- inarrayrock = _inArrayRock;
-
- if (!unicode) {
- for (ix = 0; ix<_inLen; ix++)
- ((char *)inbuf)[ix] = (char)ln->_chars[_inOrgX + ix];
- if (_echoStream)
- _echoStream->echoLine((char *)inbuf, _inLen);
- } else {
- for (ix = 0; ix<_inLen; ix++)
- ((glui32 *)inbuf)[ix] = ln->_chars[_inOrgX + ix];
- if (_echoStream)
- _echoStream->echoLineUni((glui32 *)inbuf, _inLen);
- }
-
- _curY = _inOrgY + 1;
- _curX = 0;
- _attr = _origAttr;
-
- if (_lineTerminators)
- {
- glui32 val2 = keycode;
- if (val2 == keycode_Return)
- val2 = 0;
- g_vm->_events->eventStore(evtype_LineInput, this, _inLen, val2);
- free(_lineTerminators);
- _lineTerminators = NULL;
- } else {
- g_vm->_events->eventStore(evtype_LineInput, this, _inLen, 0);
- }
- _lineRequest = false;
- _lineRequestUni = false;
- _inBuf = NULL;
- _inMax = 0;
- _inOrgX = 0;
- _inOrgY = 0;
-
- if (g_vm->gli_unregister_arr)
- (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
-}
-
-void TextGridWindow::acceptReadLine(glui32 arg) {
- int ix;
- TextGridRow *ln = &(_lines[_inOrgY]);
-
- if (!_inBuf)
- return;
-
- if (_lineTerminators && checkTerminator(arg)) {
- glui32 *cx;
- for (cx = _lineTerminators; *cx; cx++) {
- if (*cx == arg) {
- acceptLine(arg);
- return;
- }
- }
- }
-
- switch (arg) {
-
- /* Delete keys, during line input. */
-
- case keycode_Delete:
- if (_inLen <= 0)
- return;
- if (_inCurs <= 0)
- return;
- for (ix = _inCurs; ix<_inLen; ix++)
- ln->_chars[_inOrgX + ix - 1] = ln->_chars[_inOrgX + ix];
- ln->_chars[_inOrgX + _inLen - 1] = ' ';
- _inCurs--;
- _inLen--;
- break;
-
- case keycode_Erase:
- if (_inLen <= 0)
- return;
- if (_inCurs >= _inLen)
- return;
- for (ix = _inCurs; ix<_inLen - 1; ix++)
- ln->_chars[_inOrgX + ix] = ln->_chars[_inOrgX + ix + 1];
- ln->_chars[_inOrgX + _inLen - 1] = ' ';
- _inLen--;
- break;
-
- case keycode_Escape:
- if (_inLen <= 0)
- return;
- for (ix = 0; ix<_inLen; ix++)
- ln->_chars[_inOrgX + ix] = ' ';
- _inLen = 0;
- _inCurs = 0;
- break;
-
- /* Cursor movement keys, during line input. */
-
- case keycode_Left:
- if (_inCurs <= 0)
- return;
- _inCurs--;
- break;
-
- case keycode_Right:
- if (_inCurs >= _inLen)
- return;
- _inCurs++;
- break;
-
- case keycode_Home:
- if (_inCurs <= 0)
- return;
- _inCurs = 0;
- break;
-
- case keycode_End:
- if (_inCurs >= _inLen)
- return;
- _inCurs = _inLen;
- break;
-
- case keycode_Return:
- acceptLine(arg);
- break;
-
- default:
- if (_inLen >= _inMax)
- return;
-
- if (arg < 32 || arg > 0xff)
- return;
-
- if (g_conf->_caps && (arg > 0x60 && arg < 0x7b))
- arg -= 0x20;
-
- for (ix = _inLen; ix>_inCurs; ix--)
- ln->_chars[_inOrgX + ix] = ln->_chars[_inOrgX + ix - 1];
- ln->_attrs[_inOrgX + _inLen].set(style_Input);
- ln->_chars[_inOrgX + _inCurs] = arg;
-
- _inCurs++;
- _inLen++;
- }
-
- _curX = _inOrgX + _inCurs;
- _curY = _inOrgY;
-
- touch(_inOrgY);
-}
-
-void TextGridWindow::redraw() {
- TextGridRow *ln;
- int x0, y0;
- int x, y, w;
- int i, a, b, k, o;
- glui32 link;
- int font;
- byte *fgcolor, *bgcolor;
-
- x0 = _bbox.left;
- y0 = _bbox.top;
-
- for (i = 0; i < _height; i++) {
- ln = &_lines[i];
- if (ln->dirty || Windows::_forceRedraw) {
- ln->dirty = 0;
-
- x = x0;
- y = y0 + i * g_conf->_leading;
-
- /* clear any stored hyperlink coordinates */
- _windows->setHyperlink(0, x0, y, x0 + g_conf->_cellW * _width, y + g_conf->_leading);
-
- a = 0;
- for (b = 0; b < _width; b++) {
- if (ln->_attrs[a] == ln->_attrs[b]) {
- link = ln->_attrs[a].hyper;
- font = ln->_attrs[a].attrFont(styles);
- fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
- bgcolor = ln->_attrs[a].attrBg(styles);
- w = (b - a) * g_conf->_cellW;
- _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
- o = x;
-
- for (k = a; k < b; k++) {
- drawStringUni(o * GLI_SUBPIX,
- y + g_conf->_baseLine, font, fgcolor,
- &ln->_chars[k], 1, -1);
- o += g_conf->_cellW;
- }
- if (link) {
- _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
- g_conf->_linkStyle, g_conf->_linkColor);
- _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
- }
- x += w;
- a = b;
- }
- }
- link = ln->_attrs[a].hyper;
- font = ln->_attrs[a].attrFont(styles);
- fgcolor = link ? g_conf->_linkColor : ln->_attrs[a].attrFg(styles);
- bgcolor = ln->_attrs[a].attrBg(styles);
- w = (b - a) * g_conf->_cellW;
- w += _bbox.right - (x + w);
- _windows->drawRect(x, y, w, g_conf->_leading, bgcolor);
-
- o = x;
- for (k = a; k < b; k++) {
- drawStringUni(o * GLI_SUBPIX,
- y + g_conf->_baseLine, font, fgcolor,
- &ln->_chars[k], 1, -1);
- o += g_conf->_cellW;
- }
- if (link) {
- _windows->drawRect(x, y + g_conf->_baseLine + 1, w,
- g_conf->_linkStyle, g_conf->_linkColor);
- _windows->setHyperlink(link, x, y, x + w, y + g_conf->_leading);
- }
- }
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-void TextGridWindow::TextGridRow::resize(size_t newSize) {
- _chars.clear();
- _attrs.clear();
- _chars.resize(newSize);
- _attrs.resize(newSize);
- Common::fill(&_chars[0], &_chars[0] + newSize, ' ');
-}
-
-/*--------------------------------------------------------------------------*/
-
-TextBufferWindow::TextBufferWindow(Windows *windows, uint32 rock) : Window(windows, rock),
- _historyPos(0), _historyFirst(0), _historyPresent(0), _lastSeen(0), _scrollPos(0),
- _scrollMax(0), _scrollBack(SCROLLBACK), _width(-1), _height(-1), _inBuf(nullptr),
- _lineTerminators(nullptr), _echoLineInput(true), _ladjw(0), _radjw(0), _ladjn(0),
- _radjn(0), _numChars(0), _chars(nullptr), _attrs(nullptr),
- _spaced(0), _dashed(0), _copyBuf(0), _copyPos(0) {
- _type = wintype_TextBuffer;
- Common::fill(&_history[0], &_history[HISTORYLEN], nullptr);
-
- Common::copy(&g_conf->_tStyles[0], &g_conf->_tStyles[style_NUMSTYLES], styles);
-}
-
-TextBufferWindow::~TextBufferWindow() {
- if (_inBuf) {
- if (g_vm->gli_unregister_arr)
- (*g_vm->gli_unregister_arr)(_inBuf, _inMax, "&+#!Cn", _inArrayRock);
- _inBuf = nullptr;
- }
-
- delete[] _copyBuf;
- delete[] _lineTerminators;
-
- for (int i = 0; i < _scrollBack; i++) {
- if (_lines[i].lpic)
- _lines[i].lpic->decrement();
- if (_lines[i].rpic)
- _lines[i].rpic->decrement();
- }
-}
-
-void TextBufferWindow::rearrange(const Common::Rect &box) {
- Window::rearrange(box);
- int newwid, newhgt;
- int rnd;
-
- newwid = (box.width() - g_conf->_tMarginX * 2 - g_conf->_scrollWidth) / g_conf->_cellW;
- newhgt = (box.height() - g_conf->_tMarginY * 2) / g_conf->_cellH;
-
- /* align text with bottom */
- rnd = newhgt * g_conf->_cellH + g_conf->_tMarginY * 2;
- _yAdj = (box.height() - rnd);
- _bbox.top += (box.height() - rnd);
-
- if (newwid != _width) {
- _width = newwid;
- reflow();
- }
-
- if (newhgt != _height) {
- /* scroll up if we obscure new lines */
- if (_lastSeen >= newhgt - 1)
- _scrollPos += (_height - newhgt);
-
- _height = newhgt;
-
- /* keep window within 'valid' lines */
- if (_scrollPos > _scrollMax - _height + 1)
- _scrollPos = _scrollMax - _height + 1;
- if (_scrollPos < 0)
- _scrollPos = 0;
- touchScroll();
-
- /* allocate copy buffer */
- if (_copyBuf)
- delete[] _copyBuf;
- _copyBuf = new glui32[_height * TBLINELEN];
-
- for (int i = 0; i < (_height * TBLINELEN); i++)
- _copyBuf[i] = 0;
-
- _copyPos = 0;
- }
-}
-
-void TextBufferWindow::reflow() {
- int inputbyte = -1;
- Attributes curattr, oldattr;
- int i, k, p, s;
- int x;
-
- if (_height < 4 || _width < 20)
- return;
-
- _lines[0].len = _numChars;
-
- /* allocate temp buffers */
- Attributes *attrbuf = new Attributes[SCROLLBACK * TBLINELEN];
- glui32 *charbuf = new glui32[SCROLLBACK * TBLINELEN];
- int *alignbuf = new int[SCROLLBACK];
- Picture **pictbuf = new Picture *[SCROLLBACK];
- glui32 *hyperbuf = new glui32[SCROLLBACK];
- int *offsetbuf = new int[SCROLLBACK];
-
- if (!attrbuf || !charbuf || !alignbuf || !pictbuf || !hyperbuf || !offsetbuf) {
- delete[] attrbuf;
- delete[] charbuf;
- delete[] alignbuf;
- delete[] pictbuf;
- delete[] hyperbuf;
- delete[] offsetbuf;
- return;
- }
-
- /* copy text to temp buffers */
-
- oldattr = _attr;
- curattr.clear();
-
- x = 0;
- p = 0;
- s = _scrollMax < SCROLLBACK ? _scrollMax : SCROLLBACK - 1;
-
- for (k = s; k >= 0; k--) {
- if (k == 0 && _lineRequest)
- inputbyte = p + _inFence;
-
- if (_lines[k].lpic) {
- offsetbuf[x] = p;
- alignbuf[x] = imagealign_MarginLeft;
- pictbuf[x] = _lines[k].lpic;
-
- if (pictbuf[x]) pictbuf[x]->increment();
- hyperbuf[x] = _lines[k].lhyper;
- x++;
- }
-
- if (_lines[k].rpic) {
- offsetbuf[x] = p;
- alignbuf[x] = imagealign_MarginRight;
- pictbuf[x] = _lines[k].rpic;
- if (pictbuf[x]) pictbuf[x]->increment();
- hyperbuf[x] = _lines[k].rhyper;
- x++;
- }
-
- for (i = 0; i < _lines[k].len; i++) {
- attrbuf[p] = curattr = _lines[k].attr[i];
- charbuf[p] = _lines[k].chars[i];
- p++;
- }
-
- if (_lines[k].newline) {
- attrbuf[p] = curattr;
- charbuf[p] = '\n';
- p++;
- }
- }
-
- offsetbuf[x] = -1;
-
- /* clear window */
-
- clear();
-
- /* and dump text back */
-
- x = 0;
- for (i = 0; i < p; i++) {
- if (i == inputbyte)
- break;
- _attr = attrbuf[i];
-
- if (offsetbuf[x] == i) {
- putPicture(pictbuf[x], alignbuf[x], hyperbuf[x]);
- x++;
- }
-
- putCharUni(charbuf[i]);
- }
-
- /* terribly sorry about this... */
- _lastSeen = 0;
- _scrollPos = 0;
-
- if (inputbyte != -1) {
- _inFence = _numChars;
- putTextUni(charbuf + inputbyte, p - inputbyte, _numChars, 0);
- _inCurs = _numChars;
- }
-
- // free temp buffers
- delete[] attrbuf;
- delete[] charbuf;
- delete[] alignbuf;
- delete[] pictbuf;
- delete[] hyperbuf;
- delete[] offsetbuf;
-
- _attr = oldattr;
-
- touchScroll();
-}
-
-void TextBufferWindow::touchScroll() {
- _windows->clearSelection();
- _windows->repaint(_bbox);
-
- for (int i = 0; i < _scrollMax; i++)
- _lines[i].dirty = true;
-}
-
-bool TextBufferWindow::putPicture(Picture *pic, glui32 align, glui32 linkval) {
- if (align == imagealign_MarginRight)
- {
- if (_lines[0].rpic || _numChars)
- return false;
-
- _radjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
- _radjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
- _lines[0].rpic = pic;
- _lines[0].rm = _radjw;
- _lines[0].rhyper = linkval;
- } else {
- if (align != imagealign_MarginLeft && _numChars)
- putCharUni('\n');
-
- if (_lines[0].lpic || _numChars)
- return false;
-
- _ladjw = (pic->w + g_conf->_tMarginX) * GLI_SUBPIX;
- _ladjn = (pic->h + g_conf->_cellH - 1) / g_conf->_cellH;
- _lines[0].lpic = pic;
- _lines[0].lm = _ladjw;
- _lines[0].lhyper = linkval;
-
- if (align != imagealign_MarginLeft)
- flowBreak();
- }
-
- return true;
-}
-
-void TextBufferWindow::flowBreak() {
- // TODO
-}
-
-void TextBufferWindow::putTextUni(const glui32 *buf, int len, int pos, int oldlen) {
- // TODO
-}
-
-void TextBufferWindow::touch(int line) {
- int y = _bbox.top + g_conf->_tMarginY + (_height - line - 1) * g_conf->_leading;
- _lines[line].dirty = 1;
- _windows->clearSelection();
- _windows->repaint(Common::Rect(_bbox.left, y - 2, _bbox.right, y + g_conf->_leading + 2));
-}
-
-glui32 TextBufferWindow::getSplit(glui32 size, bool vertical) const {
- return (vertical) ? size * g_conf->_cellW : size * g_conf->_cellH;
-}
-
-void TextBufferWindow::putChar(unsigned char ch) {
-}
-
-void TextBufferWindow::putCharUni(glui32 ch) {
- /*
- glui32 bchars[TBLINELEN];
- Attributes battrs[TBLINELEN];
- int pw;
- int bpoint;
- int saved;
- int i;
- int linelen;
- unsigned char *color;
-
- gli_tts_speak(&ch, 1);
-
- pw = (_bbox.right - _bbox.left - g_conf->_tMarginX * 2 - gli_scroll_width) * GLI_SUBPIX;
- pw = pw - 2 * SLOP - radjw - ladjw;
-
- color = Windows::_overrideBgSet ? gli_window_color : bgcolor;
-
- // oops ... overflow
- if (numchars + 1 >= TBLINELEN)
- scrolloneline(dwin, 0);
-
- if (ch == '\n') {
- scrolloneline(dwin, 1);
- return;
- }
-
- if (gli_conf_quotes) {
- // fails for 'tis a wonderful day in the '80s
- if (gli_conf_quotes > 1 && ch == '\'')
- {
- if (numchars == 0 || leftquote(_chars[numchars - 1]))
- ch = UNI_LSQUO;
- }
-
- if (ch == '`')
- ch = UNI_LSQUO;
-
- if (ch == '\'')
- ch = UNI_RSQUO;
-
- if (ch == '"')
- {
- if (numchars == 0 || leftquote(_chars[numchars - 1]))
- ch = UNI_LDQUO;
- else
- ch = UNI_RDQUO;
- }
- }
-
- if (gli_conf_dashes && attr.style != style_Preformatted)
- {
- if (ch == '-')
- {
- dashed++;
- if (dashed == 2)
- {
- numchars--;
- if (gli_conf_dashes == 2)
- ch = UNI_NDASH;
- else
- ch = UNI_MDASH;
- }
- if (dashed == 3)
- {
- numchars--;
- ch = UNI_MDASH;
- dashed = 0;
- }
- }
- else
- dashed = 0;
- }
-
- if (gli_conf_spaces && attr.style != style_Preformatted
- && styles[attr.style].bg == color
- && !styles[attr.style].reverse)
- {
- // turn (period space space) into (period space)
- if (gli_conf_spaces == 1)
- {
- if (ch == '.')
- spaced = 1;
- else if (ch == ' ' && spaced == 1)
- spaced = 2;
- else if (ch == ' ' && spaced == 2)
- {
- spaced = 0;
- return;
- }
- else
- spaced = 0;
- }
-
- // Turn (per sp x) into (per sp sp x)
- if (gli_conf_spaces == 2)
- {
- if (ch == '.')
- spaced = 1;
- else if (ch == ' ' && spaced == 1)
- spaced = 2;
- else if (ch != ' ' && spaced == 2)
- {
- spaced = 0;
- win_textbuffer_putchar_uni(win, ' ');
- }
- else
- spaced = 0;
- }
- }
-
- _chars[numchars] = ch;
- attrs[numchars] = attr;
- numchars++;
-
- // kill spaces at the end for line width calculation
- linelen = numchars;
- while (linelen > 1 && _chars[linelen - 1] == ' '
- && styles[attrs[linelen - 1].style].bg == color
- && !styles[attrs[linelen - 1].style].reverse)
- linelen--;
-
- if (calcwidth(dwin, _chars, attrs, 0, linelen, -1) >= pw)
- {
- bpoint = numchars;
-
- for (i = numchars - 1; i > 0; i--)
- if (_chars[i] == ' ')
- {
- bpoint = i + 1; // skip space
- break;
- }
-
- saved = numchars - bpoint;
-
- memcpy(bchars, _chars + bpoint, saved * 4);
- memcpy(battrs, attrs + bpoint, saved * sizeof(attr_t));
- numchars = bpoint;
-
- scrolloneline(dwin, 0);
-
- memcpy(_chars, bchars, saved * 4);
- memcpy(attrs, battrs, saved * sizeof(attr_t));
- numchars = saved;
- }
-
- touch(0);
- */
-}
-
-bool TextBufferWindow::unputCharUni(uint32 ch) {
- // TODO
- return false;
-}
-
-void TextBufferWindow::putBuffer(const unsigned char *buf, size_t len) {
- // TODO
-}
-
-void TextBufferWindow::putBufferUni(const uint32 *buf, size_t len) {
- // TODO
-}
-
-void TextBufferWindow::moveCursor(const Common::Point &newPos) {
- // TODO
-}
-
-void TextBufferWindow::clear() {
- int i;
-
- _attr.fgset = Windows::_overrideFgSet;
- _attr.bgset = Windows::_overrideBgSet;
- _attr.fgcolor = Windows::_overrideFgSet ? Windows::_overrideFgVal : 0;
- _attr.bgcolor = Windows::_overrideBgSet ? Windows::_overrideBgVal : 0;
- _attr.reverse = false;
-
- _ladjw = _radjw = 0;
- _ladjn = _radjn = 0;
-
- _spaced = 0;
- _dashed = 0;
-
- _numChars = 0;
-
- for (i = 0; i < _scrollBack; i++) {
- _lines[i].len = 0;
-
- if (_lines[i].lpic) _lines[i].lpic->decrement();
- _lines[i].lpic = nullptr;
- if (_lines[i].rpic) _lines[i].rpic->decrement();
- _lines[i].rpic = nullptr;
-
- _lines[i].lhyper = 0;
- _lines[i].rhyper = 0;
- _lines[i].lm = 0;
- _lines[i].rm = 0;
- _lines[i].newline = 0;
- _lines[i].dirty = true;
- _lines[i].repaint = false;
- }
-
- _lastSeen = 0;
- _scrollPos = 0;
- _scrollMax = 0;
-
- for (i = 0; i < _height; i++)
- touch(i);
-}
-
-void TextBufferWindow::requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) {
- if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
- {
- warning("request_line_event: window already has keyboard request");
- return;
- }
-
- // TODO
-}
-
-void TextBufferWindow::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
- if (_charRequest || _lineRequest || _charRequestUni || _lineRequestUni)
- {
- warning("request_line_event_uni: window already has keyboard request");
- return;
- }
-
- // TODO
-}
-
-void TextBufferWindow::cancelLineEvent(Event *ev) {
- gidispatch_rock_t inarrayrock;
- int ix;
- int len;
- void *inbuf;
- int inmax;
- int unicode = _lineRequestUni;
- Event dummyEv;
-
- if (!ev)
- ev = &dummyEv;
-
- g_vm->_events->clearEvent(ev);
-
- if (!_lineRequest && !_lineRequestUni)
- return;
-
- if (!_inBuf)
- return;
-
- inbuf = _inBuf;
- inmax = _inMax;
- inarrayrock = _inArrayRock;
-
- len = _numChars - _inFence;
- if (_echoStream)
- _echoStream->echoLineUni(_chars + _inFence, len);
-
- if (len > inmax)
- len = inmax;
-
- if (!unicode) {
- for (ix = 0; ix<len; ix++) {
- glui32 ch = _chars[_inFence + ix];
- if (ch > 0xff)
- ch = '?';
- ((char *)inbuf)[ix] = (char)ch;
- }
- }
- else {
- for (ix = 0; ix<len; ix++)
- ((glui32 *)inbuf)[ix] = _chars[_inFence + ix];
- }
-
- _attr = _origAttr;
-
- ev->_type = evtype_LineInput;
- ev->_window = this;
- ev->_val1 = len;
- ev->_val2 = 0;
-
- _lineRequest = false;
- _lineRequestUni = false;
- if (_lineTerminators) {
- free(_lineTerminators);
- _lineTerminators = nullptr;
- }
- _inBuf = nullptr;
- _inMax = 0;
-
- if (_echoLineInput) {
- putCharUni('\n');
- }
- else {
- _numChars = _inFence;
- touch(0);
- }
-
- if (g_vm->gli_unregister_arr)
- (*g_vm->gli_unregister_arr)(inbuf, inmax, unicode ? "&+#!Iu" : "&+#!Cn", inarrayrock);
-}
-
-void TextBufferWindow::redraw() {
- // TODO
-}
-
-/*--------------------------------------------------------------------------*/
-
-TextBufferWindow::TextBufferRow::TextBufferRow() : len(0), newline(0), dirty(false), repaint(false),
- lpic(nullptr), rpic(nullptr), lhyper(0), rhyper(0), lm(0), rm(0) {
-}
-
-void TextBufferWindow::TextBufferRow::resize(size_t newSize) {
- chars.clear();
- attr.clear();
- chars.resize(newSize);
- attr.resize(newSize);
- Common::fill(&chars[0], &chars[0] + newSize, ' ');
-}
-
-/*--------------------------------------------------------------------------*/
-
-GraphicsWindow::GraphicsWindow(Windows *windows, uint32 rock) : Window(windows, rock),
-_w(0), _h(0), _dirty(false), _surface(nullptr) {
- _type = wintype_Graphics;
- Common::copy(&_bgColor[0], &_bgColor[3], _bgnd);
-}
-
-GraphicsWindow::~GraphicsWindow() {
- delete _surface;
-}
-
-void GraphicsWindow::rearrange(const Common::Rect &box) {
- int newwid, newhgt;
- int bothwid, bothhgt;
- int oldw, oldh;
- Graphics::ManagedSurface *newSurface;
-
- _bbox = box;
-
- newwid = box.width();
- newhgt = box.height();
- oldw = _w;
- oldh = _h;
-
- if (newwid <= 0 || newhgt <= 0) {
- _w = 0;
- _h = 0;
- delete _surface;
- _surface = NULL;
- return;
- }
-
- bothwid = _w;
- if (newwid < bothwid)
- bothwid = newwid;
- bothhgt = _h;
- if (newhgt < bothhgt)
- bothhgt = newhgt;
-
- newSurface = new Graphics::ManagedSurface(newwid, newhgt,
- Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0));
-
- // If the new surface is equal or bigger than the old one, copy it over
- if (_surface && bothwid && bothhgt)
- newSurface->blitFrom(*_surface);
-
- delete _surface;
- _surface = newSurface;
- _w = newwid;
- _h = newhgt;
-
- touch();
-}
-
-void GraphicsWindow::touch() {
- _dirty = true;
- _windows->repaint(_bbox);
-}
-
-void GraphicsWindow::redraw() {
- // TODO
-}
-
-/*--------------------------------------------------------------------------*/
-
-PairWindow::PairWindow(Windows *windows, glui32 method, Window *key, glui32 size) :
- Window(windows, 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;
-}
-
-void PairWindow::rearrange(const Common::Rect &box) {
- Common::Rect box1, box2;
- int min, diff, split, splitwid, max;
- Window *ch1, *ch2;
-
- _bbox = box;
-
- if (_vertical) {
- min = _bbox.left;
- max = _bbox.right;
- } else {
- min = _bbox.top;
- max = _bbox.bottom;
- }
- diff = max - min;
-
- // We now figure split.
- if (_vertical)
- splitwid = g_conf->_wPaddingX; // want border?
- else
- splitwid = g_conf->_wPaddingY; // want border?
-
- switch (_division) {
- case winmethod_Proportional:
- split = (diff * _size) / 100;
- break;
-
- case winmethod_Fixed:
- split = !_key ? 0 : _key->getSplit(_size, _vertical);
- break;
-
- default:
- split = diff / 2;
- break;
- }
-
- if (!_backward)
- split = max - split - splitwid;
- else
- split = min + split;
-
- if (min >= max) {
- split = min;
- } else {
- if (split < min)
- split = min;
- else if (split > max - splitwid)
- split = max - splitwid;
- }
-
- if (_vertical) {
- box1.left = _bbox.left;
- box1.right = split;
- box2.left = split + splitwid;
- box2.right = _bbox.right;
- box1.top = _bbox.top;
- box1.bottom = _bbox.bottom;
- box2.top = _bbox.top;
- box2.bottom = _bbox.bottom;
- } else {
- box1.top = _bbox.top;
- box1.bottom = split;
- box2.top = split + splitwid;
- box2.bottom = _bbox.bottom;
- box1.left = _bbox.left;
- box1.right = _bbox.right;
- box2.left = _bbox.left;
- box2.right = _bbox.right;
- }
-
- if (!_backward) {
- ch1 = _child1;
- ch2 = _child2;
- } else {
- ch1 = _child2;
- ch2 = _child1;
- }
-
- ch1->rearrange(box1);
- ch2->rearrange(box2);
-}
-
-void PairWindow::redraw() {
- // TODO
-}
-
-/*--------------------------------------------------------------------------*/
-
void Attributes::clear() {
fgset = 0;
bgset = 0;
diff --git a/engines/gargoyle/windows.h b/engines/gargoyle/windows.h
index 9a09641ca8..a5bc2f43f9 100644
--- a/engines/gargoyle/windows.h
+++ b/engines/gargoyle/windows.h
@@ -31,7 +31,6 @@
#include "gargoyle/events.h"
#include "gargoyle/glk_types.h"
#include "gargoyle/fonts.h"
-#include "gargoyle/picture.h"
#include "gargoyle/streams.h"
#include "gargoyle/window_mask.h"
@@ -43,6 +42,8 @@ class PairWindow;
#define HISTORYLEN 100
#define SCROLLBACK 512
#define TBLINELEN 300
+#define GLI_SUBPIX 8
+
/**
* Main windows manager
@@ -256,7 +257,6 @@ struct Attributes {
class Window : public Draw {
public:
Windows *_windows;
- glui32 _magicnum;
glui32 _rock;
glui32 _type;
@@ -393,409 +393,6 @@ public:
BlankWindow(Windows *windows, uint32 rock);
};
-/**
- * Text Grid window
- */
-class TextGridWindow : public Window {
- /**
- * Structure for a row within the grid window
- */
- struct TextGridRow {
- Common::Array<uint32> _chars;
- Common::Array<Attributes> _attrs;
- bool dirty;
-
- /**
- * Constructor
- */
- TextGridRow() : dirty(false) {}
-
- /**
- * Resize the row
- */
- void resize(size_t newSize);
- };
- typedef Common::Array<TextGridRow> TextGridRows;
-private:
- /**
- * Mark a given text row as modified
- */
- void touch(int line);
-
- void acceptReadChar(glui32 arg);
-
- /**
- * Return or enter, during line input. Ends line input.
- */
- void acceptLine(glui32 keycode);
-
- /**
- * Any regular key, during line input.
- */
- void acceptReadLine(glui32 arg);
-public:
- int _width, _height;
- TextGridRows _lines;
-
- int _curX, _curY; ///< the window cursor position
-
- ///< for line input
- void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
- int _inOrgX, _inOrgY;
- int _inMax;
- int _inCurs, _inLen;
- Attributes _origAttr;
- gidispatch_rock_t _inArrayRock;
- glui32 *_lineTerminators;
-
- WindowStyle styles[style_NUMSTYLES]; ///< style hints and settings
-public:
- /**
- * Constructor
- */
- TextGridWindow(Windows *windows, uint32 rock);
-
- /**
- * Destructor
- */
- virtual ~TextGridWindow();
-
- /**
- * Rearranges the window
- */
- virtual void rearrange(const Common::Rect &box) override;
-
- /**
- * Get window split size within parent pair window
- */
- virtual glui32 getSplit(glui32 size, bool vertical) const override;
-
- /**
- * Write a character
- */
- virtual void putChar(unsigned char ch) override;
-
- /**
- * Write a unicode character
- */
- virtual void putCharUni(uint32 ch) override;
-
- /**
- * Unput a unicode character
- */
- virtual bool unputCharUni(uint32 ch) override;
-
- /**
- * Write a buffer
- */
- virtual void putBuffer(const unsigned char *buf, size_t len) override;
-
- /**
- * Write a unicode character
- */
- virtual void putBufferUni(const uint32 *buf, size_t len) override;
-
- /**
- * Move the cursor
- */
- virtual void moveCursor(const Common::Point &newPos) override;
-
- /**
- * Clear the window
- */
- virtual void clear() override;
-
- /**
- * Click the window
- */
- virtual void click(const Common::Point &newPos) override;
-
- /**
- * Prepare for inputing a line
- */
- virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
-
- /**
- * Prepare for inputing a line
- */
- virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) override;
-
- /**
- * Cancel an input line event
- */
- virtual void cancelLineEvent(Event *ev) override;
-
- /**
- * Cancel a mouse event
- */
- virtual void cancelMouseEvent() override { _mouseRequest = false; }
-
- /**
- * Cancel a hyperlink event
- */
- virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
-
- /**
- * Redraw the window
- */
- virtual void redraw() override;
-};
-
-/**
- * Text Buffer window
- */
-class TextBufferWindow : public Window {
- /**
- * Structure for a row within the window
- */
- struct TextBufferRow {
- Common::Array<uint32> chars;
- Common::Array<Attributes> attr;
- int len, newline;
- bool dirty, repaint;
- Picture *lpic, *rpic;
- glui32 lhyper, rhyper;
- int lm, rm;
-
- /**
- * Constructor
- */
- TextBufferRow();
-
- /**
- * Resize the row
- */
- void resize(size_t newSize);
- };
- typedef Common::Array<TextBufferRow> TextBufferRows;
-private:
- void reflow();
- void touchScroll();
- bool putPicture(Picture *pic, glui32 align, glui32 linkval);
- void putTextUni(const glui32 *buf, int len, int pos, int oldlen);
- void flowBreak();
-
- /**
- * Mark a given text row as modified
- */
- void touch(int line);
-public:
- int _width, _height;
- int _spaced;
- int _dashed;
-
- TextBufferRows _lines;
- int _scrollBack;
-
- int _numChars; ///< number of chars in last line: lines[0]
- glui32 *_chars; ///< alias to lines[0].chars
- Attributes *_attrs; ///< alias to lines[0].attrs
-
- ///< adjust margins temporarily for images
- int _ladjw;
- int _ladjn;
- int _radjw;
- int _radjn;
-
- /* Command history. */
- glui32 *_history[HISTORYLEN];
- int _historyPos;
- int _historyFirst, _historyPresent;
-
- /* for paging */
- int _lastSeen;
- int _scrollPos;
- int _scrollMax;
-
- /* for line input */
- void *_inBuf; ///< unsigned char* for latin1, glui32* for unicode
- int _inMax;
- long _inFence;
- long _inCurs;
- Attributes _origAttr;
- gidispatch_rock_t _inArrayRock;
-
- glui32 _echoLineInput;
- glui32 *_lineTerminators;
-
- /* style hints and settings */
- WindowStyle styles[style_NUMSTYLES];
-
- /* for copy selection */
- glui32 *_copyBuf;
- int _copyPos;
-public:
- /**
- * Constructor
- */
- TextBufferWindow(Windows *windows, uint32 rock);
-
- /**
- * Destructor
- */
- virtual ~TextBufferWindow();
-
- /**
- * Rearranges the window
- */
- virtual void rearrange(const Common::Rect &box) override;
-
- /**
- * Get window split size within parent pair window
- */
- virtual glui32 getSplit(glui32 size, bool vertical) const override;
-
- /**
- * Write a character
- */
- virtual void putChar(unsigned char ch) override;
-
- /**
- * Write a unicode character
- */
- virtual void putCharUni(uint32 ch) override;
-
- /**
- * Unput a unicode character
- */
- virtual bool unputCharUni(uint32 ch) override;
-
- /**
- * Write a buffer
- */
- virtual void putBuffer(const unsigned char *buf, size_t len) override;
-
- /**
- * Write a unicode character
- */
- virtual void putBufferUni(const uint32 *buf, size_t len) override;
-
- /**
- * Move the cursor
- */
- virtual void moveCursor(const Common::Point &newPos) override;
-
- /**
- * Clear the window
- */
- virtual void clear() override;
-
- /**
- * Prepare for inputing a line
- */
- virtual void requestLineEvent(char *buf, glui32 maxlen, glui32 initlen) override;
-
- /**
- * Prepare for inputing a line
- */
- virtual void requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) override;
-
- /**
- * Cancel an input line event
- */
- virtual void cancelLineEvent(Event *ev) override;
-
- /**
- * Cancel a hyperlink event
- */
- virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
-
- /**
- * Redraw the window
- */
- virtual void redraw() override;
-};
-
-/**
- * Graphics window
- */
-class GraphicsWindow : public Window {
-private:
- void touch();
-public:
- unsigned char _bgnd[3];
- bool _dirty;
- glui32 _w, _h;
- Graphics::ManagedSurface *_surface;
-public:
- /**
- * Constructor
- */
- GraphicsWindow(Windows *windows, uint32 rock);
-
- /**
- * Destructor
- */
- virtual ~GraphicsWindow();
-
- /**
- * Rearranges the window
- */
- virtual void rearrange(const Common::Rect &box) override;
-
- /**
- * Get window split size within parent pair window
- */
- virtual glui32 getSplit(glui32 size, bool vertical) const override {
- return size;
- }
-
- /**
- * Cancel a mouse event
- */
- virtual void cancelMouseEvent() override { _mouseRequest = false; }
-
- /**
- * Cancel a hyperlink event
- */
- virtual void cancelHyperlinkEvent() override { _hyperRequest = false; }
-
- /**
- * Redraw the window
- */
- virtual void redraw() override;
-
- /**
- * Get the window dimensions
- */
- void getSize(glui32 *w, glui32 *h) {
- *w = _w;
- *h = _h;
- }
-};
-
-/**
- * Pair window
- */
-class PairWindow : public Window {
-public:
- Window *_child1, *_child2;
-
- /* split info... */
- glui32 _dir; ///< winmethod_Left, Right, Above, or Below
- bool _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(Windows *windows, glui32 method, Window *key, glui32 size);
-
- /**
- * Rearranges the window
- */
- virtual void rearrange(const Common::Rect &box) override;
-
- /**
- * Redraw the window
- */
- virtual void redraw() override;
-};
-
} // End of namespace Gargoyle
#endif