GLK: FROTZ: Added skeleton classes for ZMachine windows

This commit is contained in:
Paul Gilbert 2019-01-01 18:31:07 -08:00
parent 4568e498ca
commit c43f625fd8
7 changed files with 313 additions and 120 deletions

View file

@ -33,13 +33,11 @@ namespace Frotz {
GlkInterface::GlkInterface(OSystem *syst, const GlkGameDescription &gameDesc) :
GlkAPI(syst, gameDesc),
_pics(nullptr), oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0),
curr_fg(-2), curr_bg(-2), curr_font(1), prev_font(1), temp_font(0),
curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_upper(nullptr),
gos_lower(nullptr), gos_curwin(nullptr), gos_linepending(0), gos_linebuf(nullptr),
gos_linewin(nullptr), gos_channel(nullptr), cwin(0), mwin(0), mouse_x(0), mouse_y(0),
menu_selected(0), enable_wrapping(false), enable_scripting(false),
enable_scrolling(false), enable_buffering(false), next_sample(0), next_volume(0),
_pics(nullptr), oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0), curr_fg(-2), curr_bg(-2),
curr_font(1), prev_font(1), temp_font(0), curr_status_ht(0), mach_status_ht(0), gos_status(nullptr),
gos_curwin(nullptr), gos_linepending(0), gos_linebuf(nullptr), gos_linewin(nullptr),
gos_channel(nullptr), cwin(0), mwin(0), mouse_x(0), mouse_y(0), menu_selected(0), enable_wrapping(false),
enable_scripting(false), enable_scrolling(false), enable_buffering(false), next_sample(0), next_volume(0),
_soundLocked(false), _soundPlaying(false) {
Common::fill(&statusline[0], &statusline[256], '\0');
}
@ -103,47 +101,14 @@ void GlkInterface::initialize() {
* Get the screen size
*/
gos_lower = glk_window_open(0, 0, 0, wintype_TextGrid, 0);
if (!gos_lower)
gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
glk_window_get_size(gos_lower, &width, &height);
glk_window_close(gos_lower, nullptr);
_wp._lower = glk_window_open(0, 0, 0, wintype_TextGrid, 0);
if (!_wp._lower)
_wp._lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
glk_window_get_size(_wp._lower, &width, &height);
glk_window_close(_wp._lower, nullptr);
gos_channel = nullptr;
/*
* Icky magic bit setting
*/
if (h_version == V3 && _tandyBit)
h_config |= CONFIG_TANDY;
if (h_version == V3 && gos_upper)
h_config |= CONFIG_SPLITSCREEN;
if (h_version == V3 && !gos_upper)
h_config |= CONFIG_NOSTATUSLINE;
if (h_version >= V4)
h_config |= CONFIG_BOLDFACE | CONFIG_EMPHASIS |
CONFIG_FIXED | CONFIG_TIMEDINPUT | CONFIG_COLOUR;
if (h_version >= V5)
h_flags &= ~(GRAPHICS_FLAG | MOUSE_FLAG | MENU_FLAG);
if ((h_version >= 5) && (h_flags & SOUND_FLAG))
h_flags |= SOUND_FLAG;
if ((h_version == 3) && (h_flags & OLD_SOUND_FLAG))
h_flags |= OLD_SOUND_FLAG;
if ((h_version == 6) && (_sound != 0))
h_config |= CONFIG_SOUND;
if (h_version >= V5 && (h_flags & UNDO_FLAG))
if (_undo_slots == 0)
h_flags &= ~UNDO_FLAG;
h_screen_cols = width;
h_screen_rows = height;
@ -180,14 +145,48 @@ void GlkInterface::initialize() {
if (_storyId == BEYOND_ZORK)
showBeyondZorkTitle();
gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
gos_upper = glk_window_open(gos_lower,
winmethod_Above | winmethod_Fixed,
0,
wintype_TextGrid, 0);
_wp._lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
_wp._upper = glk_window_open(_wp._lower, winmethod_Above | winmethod_Fixed, 0, wintype_TextGrid, 0);
glk_set_window(gos_lower);
gos_curwin = gos_lower;
glk_set_window(_wp._lower);
gos_curwin = _wp._lower;
/*
* Icky magic bit setting
*/
if (h_version == V3 && _tandyBit)
h_config |= CONFIG_TANDY;
if (h_version == V3 && _wp._upper)
h_config |= CONFIG_SPLITSCREEN;
if (h_version == V3 && !_wp._upper)
h_config |= CONFIG_NOSTATUSLINE;
if (h_version >= V4)
h_config |= CONFIG_BOLDFACE | CONFIG_EMPHASIS |
CONFIG_FIXED | CONFIG_TIMEDINPUT | CONFIG_COLOUR;
if (h_version >= V5)
h_flags &= ~(GRAPHICS_FLAG | MOUSE_FLAG | MENU_FLAG);
if ((h_version >= 5) && (h_flags & SOUND_FLAG))
h_flags |= SOUND_FLAG;
if ((h_version == 3) && (h_flags & OLD_SOUND_FLAG))
h_flags |= OLD_SOUND_FLAG;
if ((h_version == 6) && (_sound != 0))
h_config |= CONFIG_SOUND;
if (h_version >= V5 && (h_flags & UNDO_FLAG))
if (_undo_slots == 0)
h_flags &= ~UNDO_FLAG;
/*
* Miscellaneous
*/
// Set the screen colors
garglk_set_zcolors(_defaultForeground, _defaultBackground);
@ -199,7 +198,7 @@ void GlkInterface::initialize() {
// since the arrow keys the original used are in use now for cycling prior commands
if (_storyId == BEYOND_ZORK) {
uint32 KEYCODES[2] = { keycode_PageUp, keycode_PageDown };
glk_set_terminators_line_event(gos_lower, KEYCODES, 2);
glk_set_terminators_line_event(_wp._lower, KEYCODES, 2);
}
}
@ -322,12 +321,12 @@ void GlkInterface::start_next_sample() {
void GlkInterface::gos_update_width() {
uint width;
if (gos_upper) {
glk_window_get_size(gos_upper, &width, nullptr);
if (_wp._upper) {
glk_window_get_size(_wp._upper, &width, nullptr);
h_screen_cols = width;
SET_BYTE(H_SCREEN_COLS, width);
if ((uint)curx > width) {
glk_window_move_cursor(gos_upper, 0, cury - 1);
glk_window_move_cursor(_wp._upper, 0, cury - 1);
curx = 1;
}
}
@ -337,8 +336,8 @@ void GlkInterface::gos_update_height() {
uint height_upper;
uint height_lower;
if (gos_curwin) {
glk_window_get_size(gos_upper, nullptr, &height_upper);
glk_window_get_size(gos_lower, nullptr, &height_lower);
glk_window_get_size(_wp._upper, nullptr, &height_upper);
glk_window_get_size(_wp._lower, nullptr, &height_lower);
h_screen_rows = height_upper + height_lower + 1;
SET_BYTE(H_SCREEN_ROWS, h_screen_rows);
}
@ -346,11 +345,11 @@ void GlkInterface::gos_update_height() {
void GlkInterface::reset_status_ht() {
uint height;
if (gos_upper) {
glk_window_get_size(gos_upper, nullptr, &height);
if (_wp._upper) {
glk_window_get_size(_wp._upper, nullptr, &height);
if ((uint)mach_status_ht != height) {
glk_window_set_arrangement(
glk_window_get_parent(gos_upper),
glk_window_get_parent(_wp._upper),
winmethod_Above | winmethod_Fixed,
mach_status_ht, nullptr);
}
@ -359,23 +358,21 @@ void GlkInterface::reset_status_ht() {
void GlkInterface::erase_window(zword w) {
if (w == 0)
glk_window_clear(gos_lower);
else if (gos_upper) {
glk_window_clear(_wp._lower);
else if (_wp._upper) {
#ifdef GARGLK
garglk_set_reversevideo_stream(
glk_window_get_stream(gos_upper),
true);
garglk_set_reversevideo_stream(glk_window_get_stream(_wp._upper), true);
#endif /* GARGLK */
memset(statusline, ' ', sizeof statusline);
glk_window_clear(gos_upper);
glk_window_clear(_wp._upper);
reset_status_ht();
curr_status_ht = 0;
}
}
void GlkInterface::split_window(zword lines) {
if (!gos_upper)
if (!_wp._upper)
return;
// The top line is always set for V1 to V3 games
@ -385,10 +382,10 @@ void GlkInterface::split_window(zword lines) {
if (!lines || lines > curr_status_ht) {
uint height;
glk_window_get_size(gos_upper, nullptr, &height);
glk_window_get_size(_wp._upper, nullptr, &height);
if (lines != height)
glk_window_set_arrangement(
glk_window_get_parent(gos_upper),
glk_window_get_parent(_wp._upper),
winmethod_Above | winmethod_Fixed,
lines, nullptr);
curr_status_ht = lines;
@ -396,13 +393,13 @@ void GlkInterface::split_window(zword lines) {
mach_status_ht = lines;
if (cury > lines)
{
glk_window_move_cursor(gos_upper, 0, 0);
glk_window_move_cursor(_wp._upper, 0, 0);
curx = cury = 1;
}
gos_update_width();
if (h_version == V3)
glk_window_clear(gos_upper);
glk_window_clear(_wp._upper);
}
void GlkInterface::restart_screen() {
@ -471,9 +468,9 @@ void GlkInterface::smartstatusline() {
memcpy(buf + 1 + scoreofs, c, scorelen * sizeof(zchar));
memcpy(buf + 1, a, roomlen * sizeof(zchar));
glk_window_move_cursor(gos_upper, 0, 0);
glk_window_move_cursor(_wp._upper, 0, 0);
glk_put_buffer_uni(buf, h_screen_cols);
glk_window_move_cursor(gos_upper, cury - 1, curx - 1);
glk_window_move_cursor(_wp._upper, cury - 1, curx - 1);
}
void GlkInterface::gos_cancel_pending_line() {
@ -510,7 +507,7 @@ void GlkInterface::os_draw_picture(int picture, winid_t win, const Common::Rect
zchar GlkInterface::os_read_key(int timeout, bool show_cursor) {
event_t ev;
winid_t win = gos_curwin ? gos_curwin : gos_lower;
winid_t win = gos_curwin ? gos_curwin : _wp._lower;
if (gos_linepending)
gos_cancel_pending_line();
@ -536,7 +533,7 @@ zchar GlkInterface::os_read_key(int timeout, bool show_cursor) {
glk_request_timer_events(0);
if (gos_upper && mach_status_ht < curr_status_ht)
if (_wp._upper && mach_status_ht < curr_status_ht)
reset_status_ht();
curr_status_ht = 0;
@ -558,7 +555,7 @@ zchar GlkInterface::os_read_key(int timeout, bool show_cursor) {
zchar GlkInterface::os_read_line(int max, zchar *buf, int timeout, int width, int continued) {
event_t ev;
winid_t win = gos_curwin ? gos_curwin : gos_lower;
winid_t win = gos_curwin ? gos_curwin : _wp._lower;
if (!continued && gos_linepending)
gos_cancel_pending_line();
@ -592,7 +589,7 @@ zchar GlkInterface::os_read_line(int max, zchar *buf, int timeout, int width, in
buf[ev.val1] = '\0';
// If the upper status line area was expanded to show a text box/quotation, restore it back
if (gos_upper && mach_status_ht < curr_status_ht)
if (_wp._upper && mach_status_ht < curr_status_ht)
reset_status_ht();
curr_status_ht = 0;

View file

@ -25,6 +25,7 @@
#include "glk/glk_api.h"
#include "glk/frotz/mem.h"
#include "glk/frotz/windows.h"
namespace Glk {
namespace Frotz {
@ -67,9 +68,8 @@ public:
int curr_status_ht;
int mach_status_ht;
Windows _wp;
winid_t gos_status;
winid_t gos_upper;
winid_t gos_lower;
winid_t gos_curwin;
int gos_linepending;
zchar *gos_linebuf;

View file

@ -26,7 +26,7 @@ namespace Glk {
namespace Frotz {
void Processor::screen_mssg_on() {
if (gos_curwin == gos_lower) {
if (gos_curwin == _wp._lower) {
oldstyle = curstyle;
glk_set_style(style_Preformatted);
glk_put_string("\n ");
@ -34,7 +34,7 @@ void Processor::screen_mssg_on() {
}
void Processor::screen_mssg_off() {
if (gos_curwin == gos_lower) {
if (gos_curwin == _wp._lower) {
glk_put_char('\n');
zargs[0] = 0;
z_set_text_style();
@ -98,7 +98,7 @@ uint32 Processor::zchar_to_unicode_rune(zchar c) {
void Processor::screen_char(zchar c) {
if (gos_linepending && (gos_curwin == gos_linewin)) {
gos_cancel_pending_line();
if (gos_curwin == gos_upper) {
if (gos_curwin == _wp._upper) {
curx = 1;
cury ++;
}
@ -119,7 +119,7 @@ void Processor::screen_char(zchar c) {
fixforced = false;
}
if (gos_upper && gos_curwin == gos_upper) {
if (_wp._upper && gos_curwin == _wp._upper) {
if (c == '\n' || c == ZC_RETURN) {
glk_put_char('\n');
curx = 1;
@ -151,7 +151,7 @@ void Processor::screen_char(zchar c) {
curx++;
}
}
} else if (gos_curwin == gos_lower) {
} else if (gos_curwin == _wp._lower) {
if (c == ZC_RETURN)
glk_put_char('\n');
else {
@ -200,7 +200,7 @@ store((zword)os_buffer_screen((zargs[0] == (zword)-1) ? -1 : zargs[0]));
void Processor::z_erase_line() {
int i;
if (gos_upper && gos_curwin == gos_upper) {
if (_wp._upper && gos_curwin == _wp._upper) {
for (i = 0; i < h_screen_cols + 1 - curx; i++)
glk_put_char(' ');
glk_window_move_cursor(gos_curwin, curx - 1, cury - 1);
@ -211,34 +211,33 @@ void Processor::z_erase_window() {
short w = zargs[0];
if (w == -2)
{
if (gos_upper) {
glk_set_window(gos_upper);
if (_wp._upper) {
glk_set_window(_wp._upper);
#ifdef GARGLK
garglk_set_zcolors(curr_fg, curr_bg);
#endif /* GARGLK */
glk_window_clear(gos_upper);
glk_window_clear(_wp._upper);
glk_set_window(gos_curwin);
}
glk_window_clear(gos_lower);
glk_window_clear(_wp._lower);
}
if (w == -1)
{
if (gos_upper) {
glk_set_window(gos_upper);
if (_wp._upper) {
glk_set_window(_wp._upper);
#ifdef GARGLK
garglk_set_zcolors(curr_fg, curr_bg);
#endif /* GARGLK */
glk_window_clear(gos_upper);
glk_window_clear(_wp._upper);
}
glk_window_clear(gos_lower);
glk_window_clear(_wp._lower);
split_window(0);
glk_set_window(gos_lower);
gos_curwin = gos_lower;
glk_set_window(_wp._lower);
gos_curwin = _wp._lower;
}
if (w == 0)
glk_window_clear(gos_lower);
if (w == 1 && gos_upper)
glk_window_clear(gos_upper);
if (w >= 0 && _wp[w])
glk_window_clear(_wp[w]);
}
void Processor::z_get_cursor() {
@ -260,7 +259,7 @@ void Processor::z_print_table() {
// Write text in width x height rectangle
for (i = 0; i < zargs[2]; i++, curx = xs, cury++) {
glk_window_move_cursor(cwin == 0 ? gos_lower : gos_upper, xs - 1, cury - 1);
glk_window_move_cursor(_wp[cwin], xs - 1, cury - 1);
for (j = 0; j < zargs[1]; j++) {
LOW_BYTE(addr, c);
@ -384,7 +383,7 @@ void Processor::z_set_font() {
void Processor::z_set_cursor() {
int x = (int16)zargs[1], y = (int16)zargs[0];
assert(gos_upper);
assert(_wp._upper);
flush_buffer();
@ -394,7 +393,8 @@ void Processor::z_set_cursor() {
}
if (!x || !y) {
Point cursorPos = gos_upper->getCursor();
winid_t win = _wp._upper;
Point cursorPos = win->getCursor();
if (!x)
x = cursorPos.x;
if (!y)
@ -409,7 +409,7 @@ void Processor::z_set_cursor() {
reset_status_ht();
}
glk_window_move_cursor(gos_upper, curx - 1, cury - 1);
glk_window_move_cursor(_wp._upper, curx - 1, cury - 1);
}
void Processor::z_set_text_style() {
@ -468,12 +468,12 @@ void Processor::z_set_window() {
cwin = zargs[0];
if (cwin == 0) {
glk_set_window(gos_lower);
gos_curwin = gos_lower;
glk_set_window(_wp._lower);
gos_curwin = _wp._lower;
} else {
if (gos_upper)
glk_set_window(gos_upper);
gos_curwin = gos_upper;
if (_wp._upper)
glk_set_window(_wp._upper);
gos_curwin = _wp._upper;
}
if (cwin == 0)
@ -500,7 +500,7 @@ void Processor::z_show_status() {
bool brief = false;
if (!gos_upper)
if (!_wp._upper)
return;
// One V5 game (Wishbringer Solid Gold) contains this opcode by accident,
@ -519,15 +519,15 @@ void Processor::z_show_status() {
LOW_WORD(addr, global2);
// Move to top of the status window, and print in reverse style.
glk_set_window(gos_upper);
gos_curwin = gos_upper;
glk_set_window(_wp._upper);
gos_curwin = _wp._upper;
#ifdef GARGLK
garglk_set_reversevideo(true);
#endif /* GARGLK */
curx = cury = 1;
glk_window_move_cursor(gos_upper, 0, 0);
glk_window_move_cursor(_wp._upper, 0, 0);
// If the screen width is below 55 characters then we have to use
// the brief status line format
@ -580,8 +580,8 @@ void Processor::z_show_status() {
pad_status_line (0);
// Return to the lower window
glk_set_window(gos_lower);
gos_curwin = gos_lower;
glk_set_window(_wp._lower);
gos_curwin = _wp._lower;
}
void Processor::z_split_window() {

View file

@ -51,7 +51,8 @@ void Processor::z_draw_picture() {
if (!x || !y) {
// Currently I only support getting the cursor for the text grid area
assert(cwin == 1);
Point cursPos = gos_upper->getCursor();
winid_t win = _wp._upper;
Point cursPos = win->getCursor();
// use cursor column if x-coordinate is 0
if (!x)
x = cursPos.x;
@ -82,18 +83,18 @@ void Processor::z_draw_picture() {
if (_storyId == ARTHUR && pic == 54)
delta = h_screen_width / 160;
os_draw_picture(mapper[i].pic1, gos_lower, Point(x + delta, y + height1));
os_draw_picture(mapper[i].pic2, gos_lower, Point(x + width1 - width2 - delta, y + height1));
os_draw_picture(mapper[i].pic1, _wp._lower, Point(x + delta, y + height1));
os_draw_picture(mapper[i].pic2, _wp._lower, Point(x + width1 - width2 - delta, y + height1));
}
}
os_draw_picture(pic, gos_lower, Point(x, y));
os_draw_picture(pic, _wp._lower, Point(x, y));
if (_storyId == SHOGUN && pic == 3) {
uint height, width;
os_picture_data(59, &height, &width);
os_draw_picture(59, gos_lower, Point(h_screen_width - width + 1, y));
os_draw_picture(59, _wp._lower, Point(h_screen_width - width + 1, y));
}
}

View file

@ -0,0 +1,97 @@
/* 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/frotz/screen.h"
#include "glk/conf.h"
#include "common/file.h"
#include "graphics/fonts/ttf.h"
#include "image/bmp.h"
namespace Glk {
namespace Frotz {
FrotzScreen::FrotzScreen() : Glk::Screen() {
g_conf->_tStyles[style_User1].font = CUSTOM;
g_conf->_gStyles[style_User1].font = CUSTOM;
g_conf->_tStyles[style_User2].font = CUSTOM2;
}
void FrotzScreen::loadFonts(Common::Archive *archive) {
Screen::loadFonts(archive);
// Add character graphics font
Image::BitmapDecoder decoder;
Common::File f;
if (!f.open("infocom_graphics.bmp", *archive))
error("Could not load font");
Common::Point fontSize(_fonts[0]->getMaxCharWidth(), _fonts[0]->getFontHeight());
decoder.loadStream(f);
_fonts.push_back(new Frotz::BitmapFont(*decoder.getSurface(), fontSize));
f.close();
// Add Runic font. It provides cleaner versions of the runic characters in the
// character graphics font
if (!f.open("NotoSansRunic-Regular.ttf", *archive))
error("Could not load font");
_fonts.push_back(Graphics::loadTTFFont(f, g_conf->_propInfo._size, Graphics::kTTFSizeModeCharacter));
f.close();
}
/*--------------------------------------------------------------------------*/
BitmapFont::BitmapFont(const Graphics::Surface &src, const Common::Point &size,
uint srcWidth, uint srcHeight, unsigned char startingChar) :
_startingChar(startingChar), _size(size) {
assert(src.format.bytesPerPixel == 1);
assert((src.w % srcWidth) == 0);
assert((src.h % srcHeight) == 0);
// Set up a characters array
_chars.resize((src.w / srcWidth) * (src.h / srcHeight));
// Iterate through loading characters
Common::Rect r(srcWidth, srcHeight);
int charsPerRow = src.w / srcWidth;
for (uint idx = 0; idx < _chars.size(); ++idx) {
r.moveTo((idx % charsPerRow) * srcWidth, (idx / charsPerRow) * srcHeight);
_chars[idx].create(size.x, size.y, src.format);
_chars[idx].transBlitFrom(src, r, Common::Rect(0, 0, size.x, size.y));
}
}
void BitmapFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
const Graphics::ManagedSurface &c = _chars[chr - _startingChar];
for (int yCtr = 0; yCtr < c.h; ++yCtr) {
const byte *srcP = (const byte *)c.getBasePtr(0, yCtr);
for (int xCtr = 0; xCtr < c.w; ++xCtr, ++srcP) {
if (!*srcP)
dst->hLine(x + xCtr, y + yCtr, x + xCtr, color);
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View file

@ -0,0 +1,97 @@
/* 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 GLK_FROTZ_WINDOWS
#define GLK_FROTZ_WINDOWS
namespace Glk {
namespace Frotz {
/**
* Represents one of the virtual windows
*/
class Window {
private:
winid_t _win;
public:
/**
* Constructor
*/
Window() : _win(nullptr) {}
/**
* Assignment operator
*/
Window &operator=(winid_t win) {
_win = win;
return *this;
}
/**
* Cast operator for getting a Glk window
*/
operator winid_t() const { return _win; }
/**
* Cast operator for testing if the window is valid (present)
*/
operator bool() const { return _win != nullptr; }
/**
* Property access. There are the following properties defined by the spec:
* 0 y coordinate 6 left margin size 12 font number
* 1 x coordinate 7 right margin size 13 font size
* 2 y size 8 newline interrupt routine 14 attributes
* 3 x size 9 interrupt countdown 15 line count
* 4 y cursor 10 text style 16 true foreground colour
* 5 x cursor 11 colour data 17 true background colour
*/
};
/**
* The Z-machine has 8 virtual windows
*/
class Windows {
private:
Window _windows[8];
public:
Window &_lower;
Window &_upper;
public:
/**
* Constructor
*/
Windows() : _lower(_windows[0]), _upper(_windows[1]) {}
/**
* Array access
*/
Window &operator[](uint idx) {
assert(idx < 8);
return _windows[idx];
}
};
} // End of namespace Frotz
} // End of namespace Glk
#endif

View file

@ -53,6 +53,7 @@ MODULE_OBJS := \
frotz/quetzal.o \
frotz/screen.o \
frotz/sound_folder.o \
frotz/windows.o \
glulxe/detection.o \
glulxe/glulxe.o \
magnetic/detection.o \