aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/windows.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/windows.cpp')
-rw-r--r--engines/glk/windows.cpp773
1 files changed, 773 insertions, 0 deletions
diff --git a/engines/glk/windows.cpp b/engines/glk/windows.cpp
new file mode 100644
index 0000000000..d982f6ccb5
--- /dev/null
+++ b/engines/glk/windows.cpp
@@ -0,0 +1,773 @@
+/* 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/gargoyle.h"
+#include "glk/screen.h"
+#include "glk/streams.h"
+#include "common/algorithm.h"
+#include "common/textconsole.h"
+
+namespace Gargoyle {
+
+bool Windows::_overrideReverse;
+bool Windows::_overrideFgSet;
+bool Windows::_overrideBgSet;
+bool Windows::_forceRedraw;
+bool Windows::_claimSelect;
+bool Windows::_moreFocus;
+int Windows::_overrideFgVal;
+int Windows::_overrideBgVal;
+int Windows::_zcolor_fg;
+int Windows::_zcolor_bg;
+byte Windows::_zcolor_LightGrey[3];
+byte Windows::_zcolor_Foreground[3];
+byte Windows::_zcolor_Background[3];
+byte Windows::_zcolor_Bright[3];
+
+/*--------------------------------------------------------------------------*/
+
+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[0] = _zcolor_LightGrey[1] = _zcolor_LightGrey[2] = 181;
+ _zcolor_Foreground[0] = _zcolor_Foreground[1] = _zcolor_Foreground[2] = 0;
+ _zcolor_Background[0] = _zcolor_Background[1] = _zcolor_Background[2] = 0;
+ _zcolor_Bright[0] = _zcolor_Bright[1] = _zcolor_Bright[2] = 0;
+}
+
+Window *Windows::windowOpen(Window *splitwin, glui32 method, glui32 size,
+ glui32 wintype, glui32 rock) {
+ Window *newwin, *oldparent;
+ PairWindow *pairWin;
+ glui32 val;
+
+ _forceRedraw = true;
+
+ if (!_rootWin) {
+ if (splitwin) {
+ warning("window_open: ref must be 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) {
+ warning("window_open: invalid method (bad direction)");
+ return nullptr;
+ }
+
+ oldparent = splitwin->_parent;
+ if (oldparent && oldparent->_type != wintype_Pair) {
+ warning("window_open: parent window is not Pair");
+ return nullptr;
+ }
+ }
+
+ assert(wintype != wintype_Pair);
+ newwin = newWindow(wintype, rock);
+ if (!newwin) {
+ warning("window_open: unable to create window");
+ return nullptr;
+ }
+
+ if (!splitwin) {
+ _rootWin = newwin;
+ } else {
+ // create pairWin, with newwin as the key
+ pairWin = newPairWindow(method, newwin, size);
+ pairWin->_child1 = splitwin;
+ pairWin->_child2 = newwin;
+
+ splitwin->_parent = pairWin;
+ newwin->_parent = pairWin;
+ pairWin->_parent = oldparent;
+
+ if (oldparent) {
+ PairWindow *parentWin = dynamic_cast<PairWindow *>(oldparent);
+ assert(parentWin);
+ if (parentWin->_child1 == splitwin)
+ parentWin->_child1 = pairWin;
+ else
+ parentWin->_child2 = pairWin;
+ } else {
+ _rootWin = pairWin;
+ }
+ }
+
+ rearrange();
+
+ return newwin;
+}
+
+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 (win == pairWin->_child1) {
+ sibWin = pairWin->_child2;
+ } else if (win == pairWin->_child2) {
+ sibWin = pairWin->_child1;
+ } else {
+ warning("windowClose: window tree is corrupted");
+ return;
+ }
+
+ grandparWin = dynamic_cast<PairWindow *>(pairWin->_parent);
+ if (!grandparWin) {
+ _rootWin = sibWin;
+ sibWin->_parent = nullptr;
+ } else {
+ if (grandparWin->_child1 == pairWin)
+ grandparWin->_child1 = sibWin;
+ else
+ grandparWin->_child2 = 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);
+
+ // This probably isn't necessary, but the child *is* gone, so just in case.
+ if (win == pairWin->_child1)
+ pairWin->_child1 = nullptr;
+ else if (win == pairWin->_child2)
+ pairWin->_child2 = nullptr;
+
+ // Now we can delete the parent pair.
+ pairWin->close(false);
+
+ // Sort out the arrangements
+ rearrange();
+ }
+}
+
+Window *Windows::newWindow(glui32 type, glui32 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(glui32 method, Window *key, glui32 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;
+
+ if (g_conf->_lockCols) {
+ int desired_width = g_conf->_wMarginSaveX * 2 + g_conf->_cellW * g_conf->_cols;
+ if (desired_width > g_conf->_imageW)
+ g_conf->_wMarginX = g_conf->_wMarginSaveX;
+ else
+ g_conf->_wMarginX = (g_conf->_imageW - g_conf->_cellW * g_conf->_cols) / 2;
+ }
+
+ if (g_conf->_lockRows) {
+ int desired_height = g_conf->_wMarginSaveY * 2 + g_conf->_cellH * g_conf->_rows;
+ if (desired_height > g_conf->_imageH)
+ g_conf->_wMarginY = g_conf->_wMarginSaveY;
+ else
+ g_conf->_wMarginY = (g_conf->_imageH - g_conf->_cellH * 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(glui32 key) {
+ if (_moreFocus) {
+ inputMoreFocus();
+ } 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 = 0;
+}
+
+void Windows::redrawRect(const Rect &r) {
+ _drawSelect = true;
+ repaint(r);
+}
+
+void Windows::repaint(const Rect &box) {
+ g_vm->_events->redraw();
+}
+
+byte *Windows::rgbShift(byte *rgb) {
+ _zcolor_Bright[0] = (rgb[0] + 0x30) < 0xff ? (rgb[0] + 0x30) : 0xff;
+ _zcolor_Bright[1] = (rgb[1] + 0x30) < 0xff ? (rgb[1] + 0x30) : 0xff;
+ _zcolor_Bright[2] = (rgb[2] + 0x30) < 0xff ? (rgb[2] + 0x30) : 0xff;
+
+ return _zcolor_Bright;
+}
+
+/*--------------------------------------------------------------------------*/
+
+Windows::iterator &Windows::iterator::operator++() {
+ _current = _windows->iterateTreeOrder(_current);
+ 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) {
+ if (!pairWin->_backward)
+ return pairWin->_child1;
+ else
+ return pairWin->_child2;
+ } else {
+ while (win->_parent) {
+ pairWin = dynamic_cast<PairWindow *>(win->_parent);
+ assert(pairWin);
+
+ if (!pairWin->_backward) {
+ if (win == pairWin->_child1)
+ return pairWin->_child2;
+ } else {
+ if (win == pairWin->_child2)
+ return pairWin->_child1;
+ }
+
+ win = pairWin;
+ }
+
+ return nullptr;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+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),
+ _echoLineInputBase(true), _lineTerminatorsBase(nullptr), _termCt(0), _echoStream(nullptr) {
+ _attr.fgset = 0;
+ _attr.bgset = 0;
+ _attr.reverse = 0;
+ _attr.style = 0;
+ _attr.fgcolor = 0;
+ _attr.bgcolor = 0;
+ _attr.hyper = 0;
+
+ Common::copy(&g_conf->_windowColor[0], &g_conf->_windowColor[3], &_bgColor[0]);
+ Common::copy(&g_conf->_moreColor[0], &g_conf->_moreColor[3], _fgColor);
+ _dispRock.num = 0;
+
+ Streams &streams = *g_vm->_streams;
+ _stream = streams.openWindowStream(this);
+}
+
+Window::~Window() {
+ if (g_vm->gli_unregister_obj)
+ (*g_vm->gli_unregister_obj)(this, gidisp_Class_Window, _dispRock);
+
+
+ _echoStream = nullptr;
+ delete _stream;
+
+ delete[] _lineTerminatorsBase;
+
+ Window *prev = _prev;
+ Window *next = _next;
+
+ if (prev)
+ prev->_next = next;
+ else
+ _windows->_windowList = next;
+ if (next)
+ next->_prev = prev;
+}
+
+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) {
+ pairWin->_child1->close(recurse);
+ pairWin->_child2->close(recurse);
+ }
+
+ // Finally, delete the window
+ delete this;
+}
+
+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, glui32 maxlen, glui32 initlen) {
+ warning("requestLineEvent: window does not support keyboard input");
+}
+
+void Window::requestLineEventUni(glui32 *buf, glui32 maxlen, glui32 initlen) {
+ warning("requestLineEventUni: window does not support keyboard input");
+}
+
+void Window::redraw() {
+ if (Windows::_forceRedraw) {
+ unsigned char *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(glui32 arg) {
+ warning("acceptReadLine:: window does not support keyboard input");
+}
+
+void Window::acceptReadChar(glui32 arg) {
+ warning("acceptReadChar:: window does not support keyboard input");
+}
+
+void Window::getArrangement(glui32 *method, glui32 *size, Window **keyWin) {
+ warning("getArrangement: not a Pair window");
+}
+
+void Window::setArrangement(glui32 method, glui32 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(glui32 color, const Rect &box) {
+ warning("fillRect: not a graphics window");
+}
+
+void Window::setBackgroundColor(glui32 color) {
+ warning("setBackgroundColor: not a graphics window");
+}
+
+const WindowStyle *Window::getStyles() const {
+ warning("getStyles: not a text window");
+ return nullptr;
+}
+
+void Window::setTerminatorsLineEvent(glui32 *keycodes, glui32 count) {
+ if (dynamic_cast<TextBufferWindow *>(this) || dynamic_cast<TextGridWindow *>(this)) {
+ delete _lineTerminatorsBase;
+ _lineTerminatorsBase = nullptr;
+
+ if (!keycodes || count == 0) {
+ _termCt = 0;
+ } else {
+ _lineTerminatorsBase = new glui32[count + 1];
+ if (_lineTerminatorsBase) {
+ memcpy(_lineTerminatorsBase, keycodes, count * sizeof(glui32));
+ _lineTerminatorsBase[count] = 0;
+ _termCt = count;
+ }
+ }
+ } else {
+ warning("setTerminatorsLineEvent: window does not support keyboard input");
+ }
+}
+
+bool Window::checkTerminator(glui32 ch) {
+ if (ch == keycode_Escape)
+ return true;
+ else if (ch >= keycode_Func12 && ch <= keycode_Func1)
+ return true;
+ else
+ return false;
+}
+
+bool Window::imageDraw(glui32 image, glui32 align, glsi32 val1, glsi32 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(glui32 *width, glui32 *height) const {
+ if (width)
+ *width = 0;
+ if (height)
+ *height = 0;
+}
+
+/*--------------------------------------------------------------------------*/
+
+BlankWindow::BlankWindow(Windows *windows, uint32 rock) : Window(windows, rock) {
+ _type = wintype_Blank;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Attributes::clear() {
+ fgset = 0;
+ bgset = 0;
+ fgcolor = 0;
+ bgcolor = 0;
+ reverse = false;
+ hyper = 0;
+ style = 0;
+}
+
+byte *Attributes::attrBg(WindowStyle *styles) {
+ int revset = reverse || (styles[style].reverse && !Windows::_overrideReverse);
+
+ int zfset = fgset ? fgset : Windows::_overrideFgSet;
+ int zbset = bgset ? bgset : Windows::_overrideBgSet;
+
+ int zfore = fgset ? fgcolor : Windows::_overrideFgVal;
+ int zback = bgset ? bgcolor : Windows::_overrideBgVal;
+
+ if (zfset && zfore != Windows::_zcolor_fg) {
+ Windows::_zcolor_Foreground[0] = (zfore >> 16) & 0xff;
+ Windows::_zcolor_Foreground[1] = (zfore >> 8) & 0xff;
+ Windows::_zcolor_Foreground[2] = (zfore) & 0xff;
+ Windows::_zcolor_fg = zfore;
+ }
+
+ if (zbset && zback != Windows::_zcolor_bg) {
+ Windows::_zcolor_Background[0] = (zback >> 16) & 0xff;
+ Windows::_zcolor_Background[1] = (zback >> 8) & 0xff;
+ Windows::_zcolor_Background[2] = (zback) & 0xff;
+ 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 && !memcmp(styles[style].fg, Windows::_zcolor_Background, 3))
+ return Windows::_zcolor_LightGrey;
+ else
+ return styles[style].fg;
+ }
+}
+
+byte *Attributes::attrFg(WindowStyle *styles) {
+ int revset = reverse || (styles[style].reverse && !Windows::_overrideReverse);
+
+ int zfset = fgset ? fgset : Windows::_overrideFgSet;
+ int zbset = bgset ? bgset : Windows::_overrideBgSet;
+
+ int zfore = fgset ? fgcolor : Windows::_overrideFgVal;
+ int zback = bgset ? bgcolor : Windows::_overrideBgVal;
+
+ if (zfset && zfore != Windows::_zcolor_fg) {
+ Windows::_zcolor_Foreground[0] = (zfore >> 16) & 0xff;
+ Windows::_zcolor_Foreground[1] = (zfore >> 8) & 0xff;
+ Windows::_zcolor_Foreground[2] = (zfore) & 0xff;
+ Windows::_zcolor_fg = zfore;
+ }
+
+ if (zbset && zback != Windows::_zcolor_bg) {
+ Windows::_zcolor_Background[0] = (zback >> 16) & 0xff;
+ Windows::_zcolor_Background[1] = (zback >> 8) & 0xff;
+ Windows::_zcolor_Background[2] = (zback) & 0xff;
+ 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 && !memcmp(styles[style].fg, Windows::_zcolor_Background, 3))
+ return Windows::_zcolor_LightGrey;
+ else
+ return styles[style].fg;
+ } else {
+ if (zbset)
+ return Windows::_zcolor_Background;
+ else
+ return styles[style].bg;
+ }
+}
+
+} // End of namespace Gargoyle