mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-12 20:50:56 +00:00
832418b837
The ScummGlk backend already had a new 'arbitrary' mode allowing for windows to be placed at any position, and on top of each other. This expands on this by ensuring that the background window, which is used for drawing graphics on, appears behind text that gets written. Yet can still appear on top of the text (hiding it) when title screen graphics are being shown
859 lines
22 KiB
C++
859 lines
22 KiB
C++
/* 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 "glk/windows.h"
|
|
#include "glk/window_graphics.h"
|
|
#include "glk/window_pair.h"
|
|
#include "glk/window_text_buffer.h"
|
|
#include "glk/window_text_grid.h"
|
|
#include "glk/conf.h"
|
|
#include "glk/glk.h"
|
|
#include "glk/screen.h"
|
|
#include "glk/streams.h"
|
|
#include "common/algorithm.h"
|
|
#include "common/textconsole.h"
|
|
|
|
namespace Glk {
|
|
|
|
bool Windows::_overrideReverse;
|
|
bool Windows::_overrideFgSet;
|
|
bool Windows::_overrideBgSet;
|
|
bool Windows::_forceRedraw;
|
|
bool Windows::_claimSelect;
|
|
bool Windows::_moreFocus;
|
|
uint Windows::_overrideFgVal;
|
|
uint Windows::_overrideBgVal;
|
|
uint Windows::_zcolor_fg;
|
|
uint Windows::_zcolor_bg;
|
|
uint Windows::_zcolor_LightGrey;
|
|
uint Windows::_zcolor_Foreground;
|
|
uint Windows::_zcolor_Background;
|
|
uint Windows::_zcolor_Bright;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
Windows::Windows(Graphics::Screen *screen) : _screen(screen), _windowList(nullptr),
|
|
_rootWin(nullptr), _focusWin(nullptr) {
|
|
_overrideReverse = false;
|
|
_overrideFgSet = false;
|
|
_overrideBgSet = false;
|
|
_forceRedraw = true;
|
|
_claimSelect = false;
|
|
_moreFocus = false;
|
|
_overrideFgVal = 0;
|
|
_overrideBgVal = 0;
|
|
_zcolor_fg = _zcolor_bg = 0;
|
|
_drawSelect = false;
|
|
|
|
_zcolor_LightGrey = g_system->getScreenFormat().RGBToColor(181, 181, 181);
|
|
_zcolor_Foreground = _zcolor_Background = 0;
|
|
_zcolor_Bright = 0;
|
|
}
|
|
|
|
Windows::~Windows() {
|
|
delete _rootWin;
|
|
}
|
|
|
|
Window *Windows::windowOpen(Window *splitwin, uint method, uint size,
|
|
uint wintype, uint rock) {
|
|
Window *newwin, *oldparent = nullptr;
|
|
PairWindow *pairWin;
|
|
uint val;
|
|
|
|
_forceRedraw = true;
|
|
|
|
if (!_rootWin) {
|
|
if (splitwin) {
|
|
warning("window_open: ref must be nullptr");
|
|
return nullptr;
|
|
}
|
|
|
|
// ignore method and size now
|
|
oldparent = nullptr;
|
|
} else {
|
|
if (!splitwin) {
|
|
warning("window_open: ref must not be nullptr");
|
|
return nullptr;
|
|
}
|
|
|
|
val = (method & winmethod_DivisionMask);
|
|
if (val != winmethod_Fixed && val != winmethod_Proportional) {
|
|
warning("window_open: invalid method (not fixed or proportional)");
|
|
return nullptr;
|
|
}
|
|
|
|
val = (method & winmethod_DirMask);
|
|
if (val != winmethod_Above && val != winmethod_Below && val != winmethod_Left
|
|
&& val != winmethod_Right && val != winmethod_Arbitrary) {
|
|
warning("window_open: invalid method (bad direction)");
|
|
return nullptr;
|
|
}
|
|
|
|
if (splitwin->_type == wintype_Pair) {
|
|
if ((method & winmethod_DirMask) != winmethod_Arbitrary) {
|
|
warning("window_open: Can only add windows to a Pair window in arbitrary mode");
|
|
return nullptr;
|
|
}
|
|
} else {
|
|
oldparent = splitwin->_parent;
|
|
if (oldparent && oldparent->_type != wintype_Pair) {
|
|
warning("window_open: parent window is not Pair");
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
assert(wintype != wintype_Pair);
|
|
newwin = newWindow(wintype, rock);
|
|
if (!newwin) {
|
|
warning("window_open: unable to create window");
|
|
return nullptr;
|
|
}
|
|
|
|
if (!splitwin) {
|
|
_rootWin = newwin;
|
|
} else if (splitwin->_type == wintype_Pair) {
|
|
pairWin = static_cast<PairWindow *>(splitwin);
|
|
pairWin->_dir = winmethod_Arbitrary;
|
|
pairWin->_children.push_back(newwin);
|
|
newwin->_parent = pairWin;
|
|
} else {
|
|
// create pairWin, with newwin as the key
|
|
pairWin = newPairWindow(method, newwin, size);
|
|
pairWin->_children.push_back(splitwin);
|
|
pairWin->_children.push_back(newwin);
|
|
|
|
splitwin->_parent = pairWin;
|
|
newwin->_parent = pairWin;
|
|
pairWin->_parent = oldparent;
|
|
|
|
if (oldparent) {
|
|
PairWindow *parentWin = dynamic_cast<PairWindow *>(oldparent);
|
|
assert(parentWin);
|
|
|
|
for (uint idx = 0; idx < parentWin->_children.size(); ++idx) {
|
|
if (parentWin->_children[idx] == splitwin)
|
|
parentWin->_children[idx] = pairWin;
|
|
}
|
|
} else {
|
|
_rootWin = pairWin;
|
|
}
|
|
}
|
|
|
|
rearrange();
|
|
|
|
return newwin;
|
|
}
|
|
|
|
void Windows::windowClose(Window *win, StreamResult *result) {
|
|
_forceRedraw = true;
|
|
|
|
if (win == _rootWin || win->_parent == nullptr) {
|
|
// Close the root window, which means all windows.
|
|
_rootWin = nullptr;
|
|
|
|
// Begin (simpler) closation
|
|
win->_stream->fillResult(result);
|
|
win->close(true);
|
|
} else {
|
|
// Have to jigger parent
|
|
Window *sibWin;
|
|
PairWindow *pairWin = dynamic_cast<PairWindow *>(win->_parent);
|
|
PairWindow *grandparWin;
|
|
|
|
if (pairWin) {
|
|
int index = pairWin->_children.indexOf(win);
|
|
if (index == -1) {
|
|
warning("windowClose: window tree is corrupted");
|
|
return;
|
|
}
|
|
|
|
// Detach window being closed from parent pair window
|
|
pairWin->_children.remove_at(index);
|
|
win->_parent = nullptr;
|
|
|
|
if (!(pairWin->_dir & winmethod_Arbitrary)) {
|
|
// Get the remaining child window
|
|
assert(pairWin->_children.size() == 1);
|
|
sibWin = pairWin->_children.front();
|
|
|
|
// Detach it from the pair window
|
|
index = pairWin->_children.indexOf(sibWin);
|
|
assert(index >= 0);
|
|
pairWin->_children.remove_at(index);
|
|
|
|
// Set up window as either the singular root, or grandparent pair window if one exists
|
|
grandparWin = dynamic_cast<PairWindow *>(pairWin->_parent);
|
|
if (!grandparWin) {
|
|
_rootWin = sibWin;
|
|
sibWin->_parent = nullptr;
|
|
} else {
|
|
index = grandparWin->_children.indexOf(pairWin);
|
|
grandparWin->_children[index] = sibWin;
|
|
sibWin->_parent = grandparWin;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Begin closation
|
|
win->_stream->fillResult(result);
|
|
|
|
// Close the child window (and descendants), so that key-deletion can
|
|
// crawl up the tree to the root window.
|
|
win->close(true);
|
|
|
|
if (pairWin && !(pairWin->_dir & winmethod_Arbitrary))
|
|
// Now we can delete the parent pair.
|
|
pairWin->close(false);
|
|
|
|
// Sort out the arrangements
|
|
rearrange();
|
|
}
|
|
}
|
|
|
|
Window *Windows::newWindow(uint type, uint rock) {
|
|
Window *win;
|
|
|
|
switch (type) {
|
|
case wintype_Blank:
|
|
win = new BlankWindow(this, rock);
|
|
break;
|
|
case wintype_TextGrid:
|
|
win = new TextGridWindow(this, rock);
|
|
break;
|
|
case wintype_TextBuffer:
|
|
win = new TextBufferWindow(this, rock);
|
|
break;
|
|
case wintype_Graphics:
|
|
win = new GraphicsWindow(this, rock);
|
|
break;
|
|
case wintype_Pair:
|
|
error("Pair windows cannot be created directly");
|
|
default:
|
|
error("Unknown window type");
|
|
}
|
|
|
|
win->_next = _windowList;
|
|
_windowList = win;
|
|
if (win->_next)
|
|
win->_next->_prev = win;
|
|
|
|
return win;
|
|
}
|
|
|
|
PairWindow *Windows::newPairWindow(uint method, Window *key, uint size) {
|
|
PairWindow *pwin = new PairWindow(this, method, key, size);
|
|
pwin->_next = _windowList;
|
|
_windowList = pwin;
|
|
if (pwin->_next)
|
|
pwin->_next->_prev = pwin;
|
|
|
|
return pwin;
|
|
}
|
|
|
|
void Windows::rearrange() {
|
|
if (_rootWin) {
|
|
Rect box;
|
|
Point cell(g_conf->_monoInfo._cellW, g_conf->_monoInfo._cellH);
|
|
|
|
if (g_conf->_lockCols) {
|
|
int desired_width = g_conf->_wMarginSaveX * 2 + cell.x * g_conf->_cols;
|
|
if (desired_width > g_conf->_imageW)
|
|
g_conf->_wMarginX = g_conf->_wMarginSaveX;
|
|
else
|
|
g_conf->_wMarginX = (g_conf->_imageW - cell.x * g_conf->_cols) / 2;
|
|
}
|
|
|
|
if (g_conf->_lockRows) {
|
|
int desired_height = g_conf->_wMarginSaveY * 2 + cell.y * g_conf->_rows;
|
|
if (desired_height > g_conf->_imageH)
|
|
g_conf->_wMarginY = g_conf->_wMarginSaveY;
|
|
else
|
|
g_conf->_wMarginY = (g_conf->_imageH - cell.y * g_conf->_rows) / 2;
|
|
}
|
|
|
|
box.left = g_conf->_wMarginX;
|
|
box.top = g_conf->_wMarginY;
|
|
box.right = g_conf->_imageW - g_conf->_wMarginX;
|
|
box.bottom = g_conf->_imageH - g_conf->_wMarginY;
|
|
|
|
_rootWin->rearrange(box);
|
|
}
|
|
}
|
|
|
|
void Windows::inputGuessFocus() {
|
|
Window *altWin = _focusWin;
|
|
|
|
do {
|
|
if (altWin
|
|
&& (altWin->_lineRequest || altWin->_charRequest ||
|
|
altWin->_lineRequestUni || altWin->_charRequestUni))
|
|
break;
|
|
altWin = iterateTreeOrder(altWin);
|
|
} while (altWin != _focusWin);
|
|
|
|
if (_focusWin != altWin) {
|
|
_focusWin = altWin;
|
|
_forceRedraw = true;
|
|
redraw();
|
|
}
|
|
}
|
|
|
|
void Windows::inputMoreFocus() {
|
|
Window *altWin = _focusWin;
|
|
|
|
do {
|
|
if (altWin && altWin->_moreRequest)
|
|
break;
|
|
altWin = iterateTreeOrder(altWin);
|
|
} while (altWin != _focusWin);
|
|
|
|
_focusWin = altWin;
|
|
}
|
|
|
|
void Windows::inputNextFocus() {
|
|
Window *altWin = _focusWin;
|
|
|
|
do {
|
|
altWin = iterateTreeOrder(altWin);
|
|
if (altWin
|
|
&& (altWin->_lineRequest || altWin->_charRequest ||
|
|
altWin->_lineRequestUni || altWin->_charRequestUni))
|
|
break;
|
|
} while (altWin != _focusWin);
|
|
|
|
if (_focusWin != altWin) {
|
|
_focusWin = altWin;
|
|
_forceRedraw = true;
|
|
redraw();
|
|
}
|
|
}
|
|
|
|
void Windows::inputScrollFocus() {
|
|
Window *altWin = _focusWin;
|
|
|
|
do {
|
|
if (altWin && altWin->_scrollRequest)
|
|
break;
|
|
altWin = iterateTreeOrder(altWin);
|
|
} while (altWin != _focusWin);
|
|
|
|
_focusWin = altWin;
|
|
}
|
|
|
|
void Windows::inputHandleKey(uint key) {
|
|
if (_moreFocus) {
|
|
inputMoreFocus();
|
|
} else if (_focusWin && (_focusWin->_lineRequest || _focusWin->_lineRequestUni) &&
|
|
_focusWin->checkTerminators(key)) {
|
|
// WORKAROUND: Do line terminators checking first. This was first needed for Beyond Zork,
|
|
// since it needs the Page Up/Down keys to scroll the description area rathern than the buffer area
|
|
} else {
|
|
switch (key) {
|
|
case keycode_Tab:
|
|
inputNextFocus();
|
|
return;
|
|
case keycode_PageUp:
|
|
case keycode_PageDown:
|
|
case keycode_MouseWheelUp:
|
|
case keycode_MouseWheelDown:
|
|
inputScrollFocus();
|
|
break;
|
|
default:
|
|
inputGuessFocus();
|
|
break;
|
|
}
|
|
}
|
|
|
|
Window *win = _focusWin;
|
|
if (!win)
|
|
return;
|
|
|
|
bool deferExit = false;
|
|
|
|
TextGridWindow *gridWindow = dynamic_cast<TextGridWindow *>(win);
|
|
TextBufferWindow *bufWindow = dynamic_cast<TextBufferWindow *>(win);
|
|
|
|
if (gridWindow) {
|
|
if (gridWindow->_charRequest || gridWindow->_charRequestUni)
|
|
gridWindow->acceptReadChar(key);
|
|
else if (gridWindow->_lineRequest || gridWindow->_lineRequestUni)
|
|
gridWindow->acceptReadLine(key);
|
|
} else if (bufWindow) {
|
|
if (bufWindow->_charRequest || bufWindow->_charRequestUni)
|
|
bufWindow->acceptReadChar(key);
|
|
else if (bufWindow->_lineRequest || bufWindow->_lineRequestUni)
|
|
bufWindow->acceptReadLine(key);
|
|
else if (bufWindow->_moreRequest || bufWindow->_scrollRequest)
|
|
deferExit = bufWindow->acceptScroll(key);
|
|
}
|
|
|
|
if (!deferExit && g_vm->_terminated)
|
|
g_vm->quitGame();
|
|
}
|
|
|
|
void Windows::inputHandleClick(const Point &pos) {
|
|
if (_rootWin)
|
|
_rootWin->click(pos);
|
|
}
|
|
|
|
void Windows::selectionChanged() {
|
|
_claimSelect = false;
|
|
_forceRedraw = true;
|
|
redraw();
|
|
}
|
|
|
|
void Windows::redraw() {
|
|
_claimSelect = false;
|
|
|
|
if (_forceRedraw) {
|
|
repaint(Rect(0, 0, g_conf->_imageW, g_conf->_imageH));
|
|
g_vm->_screen->fill(g_conf->_windowColor);
|
|
}
|
|
|
|
if (_rootWin)
|
|
_rootWin->redraw();
|
|
|
|
if (_moreFocus)
|
|
refocus(_focusWin);
|
|
|
|
_forceRedraw = false;
|
|
}
|
|
|
|
void Windows::redrawRect(const Rect &r) {
|
|
_drawSelect = true;
|
|
repaint(r);
|
|
}
|
|
|
|
void Windows::repaint(const Rect &box) {
|
|
g_vm->_events->redraw();
|
|
}
|
|
|
|
uint Windows::rgbShift(uint color) {
|
|
uint8 r, g, b;
|
|
Graphics::PixelFormat pf = g_system->getScreenFormat();
|
|
pf.colorToRGB(color, r, g, b);
|
|
|
|
r = ((uint)r + 0x30) < 0xff ? ((uint)r + 0x30) : 0xff;
|
|
g = ((uint)g + 0x30) < 0xff ? ((uint)g + 0x30) : 0xff;
|
|
b = ((uint)b + 0x30) < 0xff ? ((uint)b + 0x30) : 0xff;
|
|
|
|
_zcolor_Bright = pf.RGBToColor(r, g, b);
|
|
return _zcolor_Bright;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
Windows::iterator &Windows::iterator::operator++() {
|
|
_current = _current->_next;
|
|
return *this;
|
|
}
|
|
|
|
Windows::iterator &Windows::iterator::operator--() {
|
|
_current = _current->_prev;
|
|
return *this;
|
|
}
|
|
|
|
void Windows::refocus(Window *win) {
|
|
Window *focus = win;
|
|
do {
|
|
if (focus && focus->_moreRequest) {
|
|
_focusWin = focus;
|
|
return;
|
|
}
|
|
|
|
focus = iterateTreeOrder(focus);
|
|
} while (focus != win);
|
|
|
|
_moreFocus = false;
|
|
}
|
|
|
|
Window *Windows::iterateTreeOrder(Window *win) {
|
|
if (!win)
|
|
return _rootWin;
|
|
|
|
PairWindow *pairWin = dynamic_cast<PairWindow *>(win);
|
|
if (pairWin) {
|
|
return pairWin->_backward ? pairWin->_children.back() : pairWin->_children.front();
|
|
} else {
|
|
while (win->_parent) {
|
|
pairWin = dynamic_cast<PairWindow *>(win->_parent);
|
|
assert(pairWin);
|
|
int index = pairWin->_children.indexOf(win);
|
|
assert(index != -1);
|
|
|
|
if (!pairWin->_backward) {
|
|
if (index < ((int)pairWin->_children.size() - 1))
|
|
return pairWin->_children[index + 1];
|
|
} else {
|
|
if (index > 0)
|
|
return pairWin->_children[index - 1];
|
|
}
|
|
|
|
win = pairWin;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
Window::Window(Windows *windows, uint 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),
|
|
_echoLineInputBase(true), _lineTerminatorsBase(nullptr), _termCt(0), _echoStream(nullptr) {
|
|
_attr.fgset = false;
|
|
_attr.bgset = false;
|
|
_attr.reverse = false;
|
|
_attr.style = 0;
|
|
_attr.fgcolor = 0;
|
|
_attr.bgcolor = 0;
|
|
_attr.hyper = 0;
|
|
|
|
_bgColor = g_conf->_windowColor;
|
|
_fgColor = g_conf->_propInfo._moreColor;
|
|
|
|
Streams &streams = *g_vm->_streams;
|
|
_stream = streams.openWindowStream(this);
|
|
|
|
if (g_vm->gli_register_obj)
|
|
_dispRock = (*g_vm->gli_register_obj)(this, gidisp_Class_Window);
|
|
}
|
|
|
|
Window::~Window() {
|
|
if (g_vm->gli_unregister_obj)
|
|
(*g_vm->gli_unregister_obj)(this, gidisp_Class_Window, _dispRock);
|
|
|
|
// Remove the window from the parent's children list
|
|
PairWindow *parent = dynamic_cast<PairWindow *>(_parent);
|
|
if (parent) {
|
|
int index = parent->_children.indexOf(this);
|
|
if (index != -1)
|
|
parent->_children.remove_at(index);
|
|
}
|
|
|
|
delete[] _lineTerminatorsBase;
|
|
|
|
// Remove the window from the master list of windows
|
|
Window *prev = _prev;
|
|
Window *next = _next;
|
|
|
|
if (prev)
|
|
prev->_next = next;
|
|
else
|
|
_windows->_windowList = next;
|
|
if (next)
|
|
next->_prev = prev;
|
|
|
|
// Delete any attached window stream
|
|
_echoStream = nullptr;
|
|
delete _stream;
|
|
}
|
|
|
|
void Window::close(bool recurse) {
|
|
if (_windows->getFocusWindow() == this)
|
|
// Focused window is being removed
|
|
_windows->setFocus(nullptr);
|
|
|
|
for (Window *wx = _parent; wx; wx = wx->_parent) {
|
|
PairWindow *pairWin = dynamic_cast<PairWindow *>(wx);
|
|
|
|
if (pairWin && pairWin->_key == this) {
|
|
pairWin->_key = nullptr;
|
|
pairWin->_keyDamage = true;
|
|
}
|
|
}
|
|
|
|
PairWindow *pairWin = dynamic_cast<PairWindow *>(this);
|
|
if (pairWin) {
|
|
for (uint idx = 0; idx < pairWin->_children.size(); ++idx)
|
|
pairWin->_children[idx]->close();
|
|
}
|
|
|
|
// Finally, delete the window
|
|
delete this;
|
|
}
|
|
|
|
FontInfo *Window::getFontInfo() {
|
|
error("Tried to get font info for a non-text window");
|
|
}
|
|
|
|
void Window::cancelLineEvent(Event *ev) {
|
|
Event dummyEv;
|
|
if (!ev)
|
|
ev = &dummyEv;
|
|
|
|
ev->clear();
|
|
}
|
|
|
|
void Window::moveCursor(const Point &newPos) {
|
|
warning("moveCursor: not a TextGrid window");
|
|
}
|
|
|
|
void Window::requestLineEvent(char *buf, uint maxlen, uint initlen) {
|
|
warning("requestLineEvent: window does not support keyboard input");
|
|
}
|
|
|
|
void Window::requestLineEventUni(uint32 *buf, uint maxlen, uint initlen) {
|
|
warning("requestLineEventUni: window does not support keyboard input");
|
|
}
|
|
|
|
void Window::redraw() {
|
|
if (Windows::_forceRedraw) {
|
|
uint color = Windows::_overrideBgSet ? g_conf->_windowColor : _bgColor;
|
|
int y0 = _yAdj ? _bbox.top - _yAdj : _bbox.top;
|
|
g_vm->_screen->fillRect(Rect(_bbox.left, y0, _bbox.right, _bbox.bottom), color);
|
|
}
|
|
}
|
|
|
|
void Window::acceptReadLine(uint32 arg) {
|
|
warning("acceptReadLine:: window does not support keyboard input");
|
|
}
|
|
|
|
void Window::acceptReadChar(uint arg) {
|
|
warning("acceptReadChar:: window does not support keyboard input");
|
|
}
|
|
|
|
void Window::getArrangement(uint *method, uint *size, Window **keyWin) {
|
|
warning("getArrangement: not a Pair window");
|
|
}
|
|
|
|
void Window::setArrangement(uint method, uint size, Window *keyWin) {
|
|
warning("setArrangement: not a Pair window");
|
|
}
|
|
|
|
void Window::requestCharEvent() {
|
|
warning("requestCharEvent: window does not support keyboard input");
|
|
}
|
|
|
|
void Window::requestCharEventUni() {
|
|
warning("requestCharEventUni: window does not support keyboard input");
|
|
}
|
|
|
|
void Window::flowBreak() {
|
|
warning("flowBreak: not a text buffer window");
|
|
}
|
|
|
|
void Window::eraseRect(bool whole, const Rect &box) {
|
|
warning("eraseRect: not a graphics window");
|
|
}
|
|
|
|
void Window::fillRect(uint color, const Rect &box) {
|
|
warning("fillRect: not a graphics window");
|
|
}
|
|
|
|
void Window::setBackgroundColor(uint color) {
|
|
warning("setBackgroundColor: not a graphics window");
|
|
}
|
|
|
|
const WindowStyle *Window::getStyles() const {
|
|
warning("getStyles: not a text window");
|
|
return nullptr;
|
|
}
|
|
|
|
void Window::setTerminatorsLineEvent(const uint32 *keycodes, uint count) {
|
|
if (dynamic_cast<TextBufferWindow *>(this) || dynamic_cast<TextGridWindow *>(this)) {
|
|
delete[] _lineTerminatorsBase;
|
|
_lineTerminatorsBase = nullptr;
|
|
|
|
if (!keycodes || count == 0) {
|
|
_termCt = 0;
|
|
} else {
|
|
_lineTerminatorsBase = new uint[count + 1];
|
|
if (_lineTerminatorsBase) {
|
|
memcpy(_lineTerminatorsBase, keycodes, count * sizeof(uint));
|
|
_lineTerminatorsBase[count] = 0;
|
|
_termCt = count;
|
|
}
|
|
}
|
|
} else {
|
|
warning("setTerminatorsLineEvent: window does not support keyboard input");
|
|
}
|
|
}
|
|
|
|
bool Window::checkBasicTerminators(uint32 ch) {
|
|
if (ch == keycode_Escape)
|
|
return true;
|
|
else if (ch >= keycode_Func12 && ch <= keycode_Func1)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool Window::checkTerminators(uint32 ch) {
|
|
if (checkBasicTerminators(ch))
|
|
return true;
|
|
|
|
for (uint idx = 0; idx < _termCt; ++idx) {
|
|
if (_lineTerminatorsBase[idx] == ch)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Window::imageDraw(uint image, uint align, int val1, int val2) {
|
|
if (!g_conf->_graphics)
|
|
return false;
|
|
|
|
TextBufferWindow *bufWin = dynamic_cast<TextBufferWindow *>(this);
|
|
GraphicsWindow *graWin = dynamic_cast<GraphicsWindow *>(this);
|
|
|
|
if (bufWin)
|
|
return bufWin->drawPicture(image, val1, false, 0, 0);
|
|
if (graWin)
|
|
return graWin->drawPicture(image, val1, val2, false, 0, 0);
|
|
|
|
return false;
|
|
}
|
|
|
|
void Window::getSize(uint *width, uint *height) const {
|
|
if (width)
|
|
*width = 0;
|
|
if (height)
|
|
*height = 0;
|
|
}
|
|
|
|
void Window::bringToFront() {
|
|
PairWindow *pairWin = dynamic_cast<PairWindow *>(_parent);
|
|
|
|
if (pairWin && pairWin->_dir == winmethod_Arbitrary && pairWin->_children.back() != this) {
|
|
pairWin->_children.remove(this);
|
|
pairWin->_children.push_back(this);
|
|
Windows::_forceRedraw = true;
|
|
}
|
|
}
|
|
|
|
void Window::sendToBack() {
|
|
PairWindow *pairWin = dynamic_cast<PairWindow *>(_parent);
|
|
|
|
if (pairWin && pairWin->_dir == winmethod_Arbitrary && pairWin->_children.front() != this) {
|
|
pairWin->_children.remove(this);
|
|
pairWin->_children.insert_at(0, this);
|
|
Windows::_forceRedraw = true;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
BlankWindow::BlankWindow(Windows *windows, uint rock) : Window(windows, rock) {
|
|
_type = wintype_Blank;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
WindowStyle::WindowStyle(const WindowStyleStatic &src) : font(src.font), reverse(src.reverse) {
|
|
Graphics::PixelFormat pf = g_system->getScreenFormat();
|
|
fg = pf.RGBToColor(src.fg[0], src.fg[1], src.fg[2]);
|
|
bg = pf.RGBToColor(src.bg[0], src.bg[1], src.bg[1]);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
void Attributes::clear() {
|
|
fgset = false;
|
|
bgset = false;
|
|
fgcolor = 0;
|
|
bgcolor = 0;
|
|
reverse = false;
|
|
hyper = 0;
|
|
style = 0;
|
|
}
|
|
|
|
uint Attributes::attrBg(const WindowStyle *styles) {
|
|
int revset = reverse || (styles[style].reverse && !Windows::_overrideReverse);
|
|
|
|
bool zfset = fgset ? fgset : Windows::_overrideFgSet;
|
|
bool zbset = bgset ? bgset : Windows::_overrideBgSet;
|
|
|
|
uint zfore = fgset ? fgcolor : Windows::_overrideFgVal;
|
|
uint zback = bgset ? bgcolor : Windows::_overrideBgVal;
|
|
|
|
if (zfset && zfore != Windows::_zcolor_fg) {
|
|
Windows::_zcolor_Foreground = zfore;
|
|
Windows::_zcolor_fg = zfore;
|
|
}
|
|
|
|
if (zbset && zback != Windows::_zcolor_bg) {
|
|
Windows::_zcolor_Background = zback;
|
|
Windows::_zcolor_bg = zback;
|
|
}
|
|
|
|
if (!revset) {
|
|
if (zbset)
|
|
return Windows::_zcolor_Background;
|
|
else
|
|
return styles[style].bg;
|
|
} else {
|
|
if (zfset)
|
|
if (zfore == zback)
|
|
return Windows::rgbShift(Windows::_zcolor_Foreground);
|
|
else
|
|
return Windows::_zcolor_Foreground;
|
|
else if (zbset && styles[style].fg == Windows::_zcolor_Background)
|
|
return Windows::_zcolor_LightGrey;
|
|
else
|
|
return styles[style].fg;
|
|
}
|
|
}
|
|
|
|
uint Attributes::attrFg(const WindowStyle *styles) {
|
|
int revset = reverse || (styles[style].reverse && !Windows::_overrideReverse);
|
|
|
|
bool zfset = fgset ? fgset : Windows::_overrideFgSet;
|
|
bool zbset = bgset ? bgset : Windows::_overrideBgSet;
|
|
|
|
uint zfore = fgset ? fgcolor : Windows::_overrideFgVal;
|
|
uint zback = bgset ? bgcolor : Windows::_overrideBgVal;
|
|
|
|
if (zfset && zfore != Windows::_zcolor_fg) {
|
|
Windows::_zcolor_Foreground = zfore;
|
|
Windows::_zcolor_fg = zfore;
|
|
}
|
|
|
|
if (zbset && zback != Windows::_zcolor_bg) {
|
|
Windows::_zcolor_Background = zback;
|
|
Windows::_zcolor_bg = zback;
|
|
}
|
|
|
|
if (!revset) {
|
|
if (zfset)
|
|
if (zfore == zback)
|
|
return Windows::rgbShift(Windows::_zcolor_Foreground);
|
|
else
|
|
return Windows::_zcolor_Foreground;
|
|
else if (zbset && styles[style].fg == Windows::_zcolor_Background)
|
|
return Windows::_zcolor_LightGrey;
|
|
else
|
|
return styles[style].fg;
|
|
} else {
|
|
if (zbset)
|
|
return Windows::_zcolor_Background;
|
|
else
|
|
return styles[style].bg;
|
|
}
|
|
}
|
|
|
|
} // End of namespace Glk
|