diff options
| -rw-r--r-- | engines/gargoyle/module.mk | 6 | ||||
| -rw-r--r-- | engines/gargoyle/window_graphics.cpp | 89 | ||||
| -rw-r--r-- | engines/gargoyle/window_graphics.h | 91 | ||||
| -rw-r--r-- | engines/gargoyle/window_pair.cpp | 125 | ||||
| -rw-r--r-- | engines/gargoyle/window_pair.h | 64 | ||||
| -rw-r--r-- | engines/gargoyle/window_text_buffer.cpp | 602 | ||||
| -rw-r--r-- | engines/gargoyle/window_text_buffer.h | 198 | ||||
| -rw-r--r-- | engines/gargoyle/window_text_grid.cpp | 665 | ||||
| -rw-r--r-- | engines/gargoyle/window_text_grid.h | 180 | ||||
| -rw-r--r-- | engines/gargoyle/windows.cpp | 1459 | ||||
| -rw-r--r-- | engines/gargoyle/windows.h | 407 | 
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 | 
