GLK: Split the windows.cpp file into separate files for each window class

This commit is contained in:
Paul Gilbert 2018-10-21 23:14:50 -07:00 committed by Paul Gilbert
parent 0d3ad2dc8a
commit 8708ed4f9a
11 changed files with 2063 additions and 1823 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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