scummvm/engines/glk/glk_api.cpp
Paul Gilbert f1d9722f3b GLK: FROTZ: Add support for pair windows to have more than 2 children
This is primarily for the V6 games, which have up to 8 windows
on-screen at the same time in arbitray positions
ext
2019-01-02 18:18:11 -08:00

1213 lines
29 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/glk_api.h"
#include "glk/conf.h"
#include "glk/events.h"
#include "glk/picture.h"
#include "glk/sound.h"
#include "glk/streams.h"
#include "glk/unicode.h"
#include "glk/windows.h"
#include "glk/window_graphics.h"
#include "glk/window_text_buffer.h"
#include "glk/window_pair.h"
#include "common/translation.h"
namespace Glk {
GlkAPI::GlkAPI(OSystem *syst, const GlkGameDescription &gameDesc) :
GlkEngine(syst, gameDesc), _gliFirstEvent(false) {
// Set uppercase/lowercase tables
int ix, res;
for (ix = 0; ix < 256; ix++) {
_charToupperTable[ix] = ix;
_charTolowerTable[ix] = ix;
}
for (ix = 0; ix < 256; ix++) {
if (ix >= 'A' && ix <= 'Z')
res = ix + ('a' - 'A');
else if (ix >= 0xC0 && ix <= 0xDE && ix != 0xD7)
res = ix + 0x20;
else
res = 0;
if (res) {
_charTolowerTable[ix] = res;
_charToupperTable[res] = ix;
}
}
}
void GlkAPI::glk_exit(void) {
glk_put_string(_("[ press any key to exit ]"));
_events->waitForPress();
// Trigger a ScumMVM shutdown of game
quitGame();
Common::Event e;
g_system->getEventManager()->pollEvent(e);
}
void GlkAPI::glk_set_interrupt_handler(void(*func)(void)) {
// This library doesn't handle interrupts.
}
void GlkAPI::glk_tick(void) {
// Nothing needed
}
uint GlkAPI::glk_gestalt(uint id, uint val) {
return glk_gestalt_ext(id, val, nullptr, 0);
}
uint GlkAPI::glk_gestalt_ext(uint id, uint val, uint *arr, uint arrlen) {
switch (id) {
case gestalt_Version:
return 0x00000703;
case gestalt_LineInput:
if (val >= 32 && val < 0x10ffff)
return true;
else
return false;
case gestalt_CharInput:
if (val >= 32 && val < 0x10ffff)
return true;
else if (val == keycode_Return)
return true;
else
return false;
case gestalt_CharOutput:
if (val >= 32 && val < 0x10ffff) {
if (arr && arrlen >= 1)
arr[0] = 1;
return gestalt_CharOutput_ExactPrint;
} else {
// cheaply, we don't do any translation of printed characters,
// so the output is always one character even if it's wrong.
if (arr && arrlen >= 1)
arr[0] = 1;
return gestalt_CharOutput_CannotPrint;
}
case gestalt_MouseInput:
if (val == wintype_TextGrid)
return true;
if (val == wintype_Graphics)
return true;
return false;
case gestalt_Graphics:
case gestalt_GraphicsTransparency:
return g_conf->_graphics;
case gestalt_DrawImage:
if (val == wintype_TextBuffer)
return g_conf->_graphics;
if (val == wintype_Graphics)
return g_conf->_graphics;
return false;
case gestalt_Sound:
case gestalt_SoundVolume:
case gestalt_SoundMusic:
case gestalt_SoundNotify:
return g_conf->_sound;
case gestalt_LineTerminatorKey:
return Window::checkBasicTerminators(val);
case gestalt_Timer:
case gestalt_Unicode:
case gestalt_UnicodeNorm:
case gestalt_Hyperlinks:
case gestalt_HyperlinkInput:
case gestalt_LineInputEcho:
case gestalt_LineTerminators:
case gestalt_DateTime:
case gestalt_GarglkText:
return true;
case gestalt_Sound2:
default:
return false;
}
}
unsigned char GlkAPI::glk_char_to_lower(unsigned char ch) {
return _charTolowerTable[ch];
}
unsigned char GlkAPI::glk_char_to_upper(unsigned char ch) {
return _charToupperTable[ch];
}
winid_t GlkAPI::glk_window_get_root(void) const {
return _windows->getRoot();
}
winid_t GlkAPI::glk_window_open(winid_t split, uint method, uint size, uint wintype, uint rock) const {
return _windows->windowOpen(split, method, size, wintype, rock);
}
void GlkAPI::glk_window_close(winid_t win, stream_result_t *result) {
if (win) {
_windows->windowClose(win, result);
} else {
warning("glk_window_close: invalid ref");
}
}
void GlkAPI::glk_window_get_size(winid_t win, uint *width, uint *height) {
if (win) {
win->getSize(width, height);
} else {
warning("window_get_size: invalid ref");
}
}
void GlkAPI::glk_window_set_arrangement(winid_t win, uint method, uint size, winid_t keywin) {
if (win) {
win->setArrangement(method, size, keywin);
} else {
warning("window_set_arrangement: invalid ref");
}
}
void GlkAPI::glk_window_get_arrangement(winid_t win, uint *method,
uint *size, winid_t *keyWin) {
if (win) {
win->getArrangement(method, size, keyWin);
} else {
warning("window_get_arrangement: invalid ref");
}
}
winid_t GlkAPI::glk_window_iterate(winid_t win, uint *rock) {
win = win ? win->_next : _windows->getRoot();
if (win) {
if (rock)
*rock = win->_rock;
return win;
}
if (rock)
*rock = 0;
return nullptr;
}
uint GlkAPI::glk_window_get_rock(winid_t win) {
if (win) {
return win->_rock;
} else {
warning("window_get_rock: invalid ref.");
return 0;
}
}
uint GlkAPI::glk_window_get_type(winid_t win) {
if (win) {
return win->_type;
} else {
warning("window_get_parent: invalid ref");
return 0;
}
}
winid_t GlkAPI::glk_window_get_parent(winid_t win) {
if (!win) {
warning("window_get_parent: invalid ref");
return 0;
}
return win->_parent;
}
winid_t GlkAPI::glk_window_get_sibling(winid_t win) {
if (!win) {
warning("window_get_sibling: invalid ref");
return nullptr;
}
PairWindow *parentWin = dynamic_cast<PairWindow *>(win->_parent);
if (!parentWin)
return nullptr;
int index = parentWin->_children.indexOf(win);
if (index == ((int)parentWin->_children.size() - 1))
return parentWin->_children.front();
else if (index >= 0)
return parentWin->_children[index + 1];
return nullptr;
}
void GlkAPI::glk_window_clear(winid_t win) {
if (!win) {
warning("window_clear: invalid ref");
} else {
if (win->_lineRequest || win->_lineRequestUni) {
if (g_conf->_safeClicks && _events->_forceClick) {
glk_cancel_line_event(win, nullptr);
_events->_forceClick = false;
win->clear();
} else {
warning("window_clear: window has pending line request");
return;
}
}
// Clear the window
win->clear();
}
}
void GlkAPI::glk_window_move_cursor(winid_t win, uint xpos, uint ypos) {
if (win) {
win->moveCursor(Point(xpos, ypos));
} else {
warning("window_move_cursor: invalid ref");
}
}
strid_t GlkAPI::glk_window_get_stream(winid_t win) {
if (win) {
return win->_stream;
} else {
warning("window_get_stream: invalid ref");
return nullptr;
}
}
void GlkAPI::glk_window_set_echo_stream(winid_t win, strid_t str) {
if (win) {
win->_echoStream = str;
} else {
warning("window_set_echo_stream: invalid window id");
}
}
strid_t GlkAPI::glk_window_get_echo_stream(winid_t win) {
if (!win) {
warning("window_get_echo_stream: invalid ref");
return nullptr;
}
return win->_echoStream;
}
void GlkAPI::glk_set_window(winid_t win) {
_streams->setCurrent(win ? win->_stream : nullptr);
}
strid_t GlkAPI::glk_stream_open_file(frefid_t fileref, FileMode fmode, uint rock) {
return _streams->openFileStream(fileref, fmode, rock, false);
}
strid_t GlkAPI::glk_stream_open_memory(char *buf, uint buflen, FileMode fmode, uint rock) {
return _streams->openMemoryStream(buf, buflen, fmode, rock, false);
}
void GlkAPI::glk_stream_close(strid_t str, stream_result_t *result) {
str->close(result);
}
strid_t GlkAPI::glk_stream_iterate(strid_t str, uint *rockptr) const {
return str ? str->getNext(rockptr) : _streams->getFirst(rockptr);
}
uint GlkAPI::glk_stream_get_rock(strid_t str) const {
if (!str) {
warning("stream_get_rock: invalid ref");
return 0;
}
return str->getRock();
}
void GlkAPI::glk_stream_set_position(strid_t str, int pos, uint seekMode) {
if (str) {
str->setPosition(pos, seekMode);
} else {
warning("stream_set_position: invalid ref");
}
}
uint GlkAPI::glk_stream_get_position(strid_t str) const {
if (str) {
return str->getPosition();
} else {
warning("stream_get_position: invalid ref");
return 0;
}
}
void GlkAPI::glk_stream_set_current(strid_t str) {
_streams->setCurrent(str);
}
strid_t GlkAPI::glk_stream_get_current(void) {
return _streams->getCurrent();
}
void GlkAPI::glk_put_char(unsigned char ch) {
_streams->getCurrent()->putChar(ch);
}
void GlkAPI::glk_put_char_stream(strid_t str, unsigned char ch) {
if (str) {
str->putChar(ch);
} else {
warning("put_char_stream: invalid ref");
}
}
void GlkAPI::glk_put_string(const char *s) {
_streams->getCurrent()->putBuffer(s, strlen(s));
}
void GlkAPI::glk_put_string_stream(strid_t str, const char *s) {
str->putBuffer(s, strlen(s));
}
void GlkAPI::glk_put_buffer(const char *buf, uint len) {
_streams->getCurrent()->putBuffer(buf, len);
}
void GlkAPI::glk_put_buffer_stream(strid_t str, const char *buf, uint len) {
str->putBuffer(buf, len);
}
void GlkAPI::glk_set_style(uint styl) {
_streams->getCurrent()->setStyle(styl);
}
void GlkAPI::glk_set_style_stream(strid_t str, uint styl) {
if (str) {
str->setStyle(styl);
} else {
warning("set_style_stream: invalid ref");
}
}
int GlkAPI::glk_get_char_stream(strid_t str) {
if (str) {
return str->getChar();
} else {
warning("get_char_stream: invalid ref");
return -1;
}
}
uint GlkAPI::glk_get_line_stream(strid_t str, char *buf, uint len) {
if (str) {
return str->getLine(buf, len);
} else {
warning("get_line_stream: invalid ref");
return 0;
}
}
uint GlkAPI::glk_get_buffer_stream(strid_t str, char *buf, uint len) {
if (str) {
return str->getBuffer(buf, len);
} else {
warning("get_line_stream: invalid ref");
return 0;
}
}
void GlkAPI::glk_stylehint_set(uint wintype, uint style, uint hint, int val) {
WindowStyle *styles;
bool p, b, i;
if (wintype == wintype_AllTypes) {
glk_stylehint_set(wintype_TextGrid, style, hint, val);
glk_stylehint_set(wintype_TextBuffer, style, hint, val);
return;
}
if (wintype == wintype_TextGrid)
styles = g_conf->_gStyles;
else if (wintype == wintype_TextBuffer)
styles = g_conf->_tStyles;
else
return;
if (!g_conf->_styleHint)
return;
switch (hint) {
case stylehint_TextColor:
styles[style].fg[0] = (val >> 16) & 0xff;
styles[style].fg[1] = (val >> 8) & 0xff;
styles[style].fg[2] = (val) & 0xff;
break;
case stylehint_BackColor:
styles[style].bg[0] = (val >> 16) & 0xff;
styles[style].bg[1] = (val >> 8) & 0xff;
styles[style].bg[2] = (val) & 0xff;
break;
case stylehint_ReverseColor:
styles[style].reverse = (val != 0);
break;
case stylehint_Proportional:
if (wintype == wintype_TextBuffer) {
p = val > 0;
b = styles[style].isBold();
i = styles[style].isItalic();
styles[style].font = WindowStyle::makeFont(p, b, i);
}
break;
case stylehint_Weight:
p = styles[style].isProp();
b = val > 0;
i = styles[style].isItalic();
styles[style].font = WindowStyle::makeFont(p, b, i);
break;
case stylehint_Oblique:
p = styles[style].isProp();
b = styles[style].isBold();
i = val > 0;
styles[style].font = WindowStyle::makeFont(p, b, i);
break;
}
if (wintype == wintype_TextBuffer && style == style_Normal && hint == stylehint_BackColor) {
memcpy(g_conf->_windowColor, styles[style].bg, 3);
}
if (wintype == wintype_TextBuffer && style == style_Normal && hint == stylehint_TextColor) {
memcpy(g_conf->_propInfo._moreColor, styles[style].fg, 3);
memcpy(g_conf->_propInfo._caretColor, styles[style].fg, 3);
}
}
void GlkAPI::glk_stylehint_clear(uint wintype, uint style, uint hint) {
WindowStyle *styles;
const WindowStyle *defaults;
if (wintype == wintype_AllTypes) {
glk_stylehint_clear(wintype_TextGrid, style, hint);
glk_stylehint_clear(wintype_TextBuffer, style, hint);
return;
}
if (wintype == wintype_TextGrid) {
styles = g_conf->_gStyles;
defaults = g_conf->_gStylesDefault;
} else if (wintype == wintype_TextBuffer) {
styles = g_conf->_tStyles;
defaults = g_conf->_tStylesDefault;
} else {
return;
}
if (!g_conf->_styleHint)
return;
switch (hint) {
case stylehint_TextColor:
styles[style].fg[0] = defaults[style].fg[0];
styles[style].fg[1] = defaults[style].fg[1];
styles[style].fg[2] = defaults[style].fg[2];
break;
case stylehint_BackColor:
styles[style].bg[0] = defaults[style].bg[0];
styles[style].bg[1] = defaults[style].bg[1];
styles[style].bg[2] = defaults[style].bg[2];
break;
case stylehint_ReverseColor:
styles[style].reverse = defaults[style].reverse;
break;
case stylehint_Proportional:
case stylehint_Weight:
case stylehint_Oblique:
styles[style].font = defaults[style].font;
break;
}
}
uint GlkAPI::glk_style_distinguish(winid_t win, uint style1, uint style2) {
const WindowStyle *styles = win->getStyles();
if (!styles)
return false;
return styles[style1] == styles[style2] ? 0 : 1;
}
bool GlkAPI::glk_style_measure(winid_t win, uint style, uint hint, uint *result) {
const WindowStyle *styles = win->getStyles();
if (!styles)
return false;
switch (hint) {
case stylehint_Indentation:
case stylehint_ParaIndentation:
*result = 0;
break;
case stylehint_Justification:
*result = stylehint_just_LeftFlush;
break;
case stylehint_Size:
*result = 1;
break;
case stylehint_Weight:
*result =
(styles[style].font == PROPB || styles[style].font == PROPZ ||
styles[style].font == MONOB || styles[style].font == MONOZ);
break;
case stylehint_Oblique:
*result =
(styles[style].font == PROPI || styles[style].font == PROPZ ||
styles[style].font == MONOI || styles[style].font == MONOZ);
break;
case stylehint_Proportional:
*result =
(styles[style].font == PROPR || styles[style].font == PROPI ||
styles[style].font == PROPB || styles[style].font == PROPZ);
break;
case stylehint_TextColor:
*result =
(styles[style].fg[0] << 16) | (styles[style].fg[1] << 8) | (styles[style].fg[2]);
break;
case stylehint_BackColor:
*result =
(styles[style].bg[0] << 16) | (styles[style].bg[1] << 8) | (styles[style].bg[2]);
break;
case stylehint_ReverseColor:
*result = styles[style].reverse;
break;
default:
return false;
}
return true;
}
frefid_t GlkAPI::glk_fileref_create_temp(uint usage, uint rock) {
return _streams->createTemp(usage, rock);
}
frefid_t GlkAPI::glk_fileref_create_by_name(uint usage, const char *name, uint rock) {
// Take out all dangerous characters
Common::String tempName(name);
for (uint idx = 0; idx < tempName.size(); ++idx) {
if (tempName[idx] == '/' || tempName[idx] == '\\' || tempName[idx] == ':')
tempName.setChar(idx, '-');
}
return _streams->createRef(tempName, usage, rock);
}
frefid_t GlkAPI::glk_fileref_create_by_prompt(uint usage, FileMode fmode, uint rock) {
return _streams->createByPrompt(usage, fmode, rock);
}
frefid_t GlkAPI::glk_fileref_create_from_fileref(uint usage, frefid_t fref, uint rock) {
if (!fref) {
warning("fileref_create_from_fileref: invalid ref");
return nullptr;
} else {
return _streams->createFromRef(fref, usage, rock);
}
}
void GlkAPI::glk_fileref_destroy(frefid_t fref) {
_streams->deleteRef(fref);
}
frefid_t GlkAPI::glk_fileref_iterate(frefid_t fref, uint *rockptr) {
return _streams->iterate(fref, rockptr);
}
uint GlkAPI::glk_fileref_get_rock(frefid_t fref) {
if (!fref) {
warning("fileref_get_rock: invalid ref.");
return 0;
} else {
return fref->_rock;
}
}
void GlkAPI::glk_fileref_delete_file(frefid_t fref) {
fref->deleteFile();
}
uint GlkAPI::glk_fileref_does_file_exist(frefid_t fref) {
return fref->exists();
}
void GlkAPI::glk_select(event_t *event) {
if (!_gliFirstEvent) {
_windows->inputGuessFocus();
_gliFirstEvent = true;
}
_events->getEvent(event, false);
}
void GlkAPI::glk_select_poll(event_t *event) {
if (!_gliFirstEvent) {
_windows->inputGuessFocus();
_gliFirstEvent = true;
}
_events->getEvent(event, true);
}
void GlkAPI::glk_request_timer_events(uint millisecs) {
_events->setTimerInterval(millisecs);
}
void GlkAPI::glk_request_line_event(winid_t win, char *buf, uint maxlen, uint initlen) {
if (!win) {
warning("request_line_event: invalid ref");
} else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
|| win->_lineRequestUni) {
warning("request_line_event: window already has keyboard request");
} else {
win->requestLineEvent(buf, maxlen, initlen);
}
}
void GlkAPI::glk_request_char_event(winid_t win) {
if (!win) {
warning("request_char_event: invalid ref");
} else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
|| win->_lineRequestUni) {
warning("request_char_event: window already has keyboard request");
} else {
win->requestCharEvent();
}
}
void GlkAPI::glk_request_mouse_event(winid_t win) {
if (!win) {
warning("request_mouse_event: invalid ref");
} else {
win->requestMouseEvent();
}
}
void GlkAPI::glk_cancel_line_event(winid_t win, event_t *event) {
if (!win) {
warning("cancel_line_event: invalid ref");
} else {
win->cancelLineEvent(event);
}
}
void GlkAPI::glk_cancel_char_event(winid_t win) {
if (!win) {
warning("glk_cancel_char_event: invalid ref");
} else {
win->cancelCharEvent();
}
}
void GlkAPI::glk_cancel_mouse_event(winid_t win) {
if (!win) {
warning("cancel_mouse_event: invalid ref");
} else {
win->cancelMouseEvent();
}
}
void GlkAPI::glk_set_echo_line_event(winid_t win, uint val) {
if (!win) {
warning("set_echo_line_event: invalid ref");
} else {
win->setEchoLineEvent(val);
}
}
void GlkAPI::glk_set_terminators_line_event(winid_t win, const uint32 *keycodes, uint count) {
if (!win) {
warning("set_terminators_line_event: invalid ref");
} else {
win->setTerminatorsLineEvent(keycodes, count);
}
}
uint GlkAPI::glk_buffer_to_lower_case_uni(uint32 *buf, uint len, uint numchars) {
return bufferChangeCase(buf, len, numchars, CASE_LOWER, COND_ALL, true);
}
uint GlkAPI::glk_buffer_to_upper_case_uni(uint32 *buf, uint len, uint numchars) {
return bufferChangeCase(buf, len, numchars, CASE_UPPER, COND_ALL, true);
}
uint GlkAPI::glk_buffer_to_title_case_uni(uint32 *buf, uint len,
uint numchars, uint lowerrest) {
return bufferChangeCase(buf, len, numchars, CASE_TITLE, COND_LINESTART, lowerrest);
}
void GlkAPI::glk_put_char_uni(uint32 ch) {
_streams->getCurrent()->putCharUni(ch);
}
void GlkAPI::glk_put_string_uni(const uint32 *s) {
_streams->getCurrent()->putBufferUni(s, strlen_uni(s));
}
void GlkAPI::glk_put_buffer_uni(const uint32 *buf, uint len) {
_streams->getCurrent()->putBufferUni(buf, len);
}
void GlkAPI::glk_put_char_stream_uni(strid_t str, uint32 ch) {
if (str) {
str->putCharUni(ch);
} else {
warning("put_char_stream_uni: invalid ref");
}
}
void GlkAPI::glk_put_string_stream_uni(strid_t str, const uint32 *s) {
if (str) {
str->putBufferUni(s, strlen_uni(s));
} else {
warning("put_string_stream_uni: invalid ref");
}
}
void GlkAPI::glk_put_buffer_stream_uni(strid_t str, const uint32 *buf, uint len) {
if (str) {
str->putBufferUni(buf, len);
} else {
warning("put_buffer_stream_uni: invalid ref");
}
}
int GlkAPI::glk_get_char_stream_uni(strid_t str) {
if (str) {
return str->getCharUni();
} else {
warning("get_char_stream_uni: invalid ref");
return -1;
}
}
uint GlkAPI::glk_get_buffer_stream_uni(strid_t str, uint32 *buf, uint len) {
if (str) {
return str->getBufferUni(buf, len);
} else {
warning("get_buffer_stream_uni: invalid ref");
return 0;
}
}
uint GlkAPI::glk_get_line_stream_uni(strid_t str, uint32 *buf, uint len) {
if (str) {
return str->getLineUni(buf, len);
} else {
warning("get_line_stream_uni: invalid ref");
return (uint) - 1;
}
}
strid_t GlkAPI::glk_stream_open_file_uni(frefid_t fileref, FileMode fmode, uint rock) {
return _streams->openFileStream(fileref, fmode, rock, true);
}
strid_t GlkAPI::glk_stream_open_memory_uni(uint32 *buf, uint buflen, FileMode fmode, uint rock) {
return _streams->openMemoryStream(buf, buflen, fmode, rock, true);
}
void GlkAPI::glk_request_char_event_uni(winid_t win) {
if (!win) {
warning("request_char_event_uni: invalid ref");
} else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
|| win->_lineRequestUni) {
warning("request_char_event_uni: window already has keyboard request");
} else {
win->requestCharEvent();
}
}
void GlkAPI::glk_request_line_event_uni(winid_t win, uint32 *buf, uint maxlen, uint initlen) {
if (!win) {
warning("request_line_event_uni: invalid ref");
} else if (win->_charRequest || win->_lineRequest || win->_charRequestUni
|| win->_lineRequestUni) {
warning("request_line_event_uni: window already has keyboard request");
} else {
win->requestLineEventUni(buf, maxlen, initlen);
}
}
uint GlkAPI::glk_buffer_canon_decompose_uni(uint32 *buf, uint len, uint numchars) {
// TODO
return 0;
}
uint GlkAPI::glk_buffer_canon_normalize_uni(uint32 *buf, uint len, uint numchars) {
return 0;
}
bool GlkAPI::glk_image_draw(winid_t win, uint image, int val1, int val2) {
if (!win) {
warning("image_draw: invalid ref");
} else if (g_conf->_graphics) {
TextBufferWindow *textWin = dynamic_cast<TextBufferWindow *>(win);
GraphicsWindow *gfxWin = dynamic_cast<GraphicsWindow *>(win);
if (textWin)
textWin->drawPicture(image, val1, false, 0, 0);
else if (gfxWin)
gfxWin->drawPicture(image, val1, val2, false, 0, 0);
}
return false;
}
bool GlkAPI::glk_image_draw_scaled(winid_t win, uint image, int val1, int val2,
uint width, uint height) {
if (!win) {
warning("image_draw_scaled: invalid ref");
} else if (g_conf->_graphics) {
TextBufferWindow *textWin = dynamic_cast<TextBufferWindow *>(win);
GraphicsWindow *gfxWin = dynamic_cast<GraphicsWindow *>(win);
if (textWin)
textWin->drawPicture(image, val1, true, width, height);
else if (gfxWin)
gfxWin->drawPicture(image, val1, val2, true, width, height);
}
return false;
}
bool GlkAPI::glk_image_get_info(uint image, uint *width, uint *height) {
if (!g_conf->_graphics)
return false;
Picture *pic = g_vm->_pictures->load(image);
if (!pic)
return false;
if (width)
*width = pic->w;
if (height)
*height = pic->h;
return true;
}
void GlkAPI::glk_window_flow_break(winid_t win) {
if (!win) {
warning("window_erase_rect: invalid ref");
} else {
win->flowBreak();
}
}
void GlkAPI::glk_window_erase_rect(winid_t win, int left, int top, uint width, uint height) {
if (!win) {
warning("window_erase_rect: invalid ref");
} else {
win->eraseRect(false, Rect(left, top, left + width, top + height));
}
}
void GlkAPI::glk_window_fill_rect(winid_t win, uint color, int left, int top,
uint width, uint height) {
if (!win) {
warning("window_fill_rect: invalid ref");
} else {
win->eraseRect(color, Rect(left, top, left + width, top + height));
}
}
void GlkAPI::glk_window_set_background_color(winid_t win, uint color) {
if (!win) {
warning("window_set_background_color: invalid ref");
} else {
win->setBackgroundColor(color);
}
}
schanid_t GlkAPI::glk_schannel_create(uint rock) {
return _sounds->create(rock);
}
void GlkAPI::glk_schannel_destroy(schanid_t chan) {
if (chan) {
delete chan;
} else {
warning("schannel_dest roy: invalid ref");
}
}
schanid_t GlkAPI::glk_schannel_iterate(schanid_t chan, uint *rockptr) {
return _sounds->iterate(chan, rockptr);
}
uint GlkAPI::glk_schannel_get_rock(schanid_t chan) {
if (chan) {
return chan->_rock;
} else {
warning("schannel_get_rock: invalid ref");
return 0;
}
}
uint GlkAPI::glk_schannel_play(schanid_t chan, uint snd) {
if (chan) {
return chan->play(snd);
} else {
warning("schannel_play_ext: invalid ref");
return 0;
}
}
uint GlkAPI::glk_schannel_play_ext(schanid_t chan, uint snd, uint repeats, uint notify) {
if (chan) {
return chan->play(snd, repeats, notify);
} else {
warning("schannel_play_ext: invalid ref");
return 0;
}
}
void GlkAPI::glk_schannel_stop(schanid_t chan) {
if (chan) {
chan->stop();
} else {
warning("schannel_stop: invalid ref");
}
}
void GlkAPI::glk_schannel_set_volume(schanid_t chan, uint vol) {
if (chan) {
chan->setVolume(vol);
} else {
warning("schannel_set_volume: invalid ref");
}
}
void GlkAPI::glk_sound_load_hint(uint snd, uint flag) {
// No implementation
}
schanid_t GlkAPI::glk_schannel_create_ext(uint rock, uint volume) {
// No implementation
return nullptr;
}
uint GlkAPI::glk_schannel_play_multi(schanid_t *chanarray, uint chancount,
uint *sndarray, uint soundcount, uint notify) {
// No implementation
return 0;
}
void GlkAPI::glk_schannel_pause(schanid_t chan) {
if (chan) {
chan->pause();
} else {
warning("schannel_pause: invalid ref");
}
}
void GlkAPI::glk_schannel_unpause(schanid_t chan) {
if (chan) {
chan->unpause();
} else {
warning("schannel_unpause: invalid ref");
}
}
void GlkAPI::glk_schannel_set_volume_ext(schanid_t chan, uint vol,
uint duration, uint notify) {
if (chan) {
chan->setVolume(vol, duration, notify);
} else {
warning("schannel_set_volume_ext: invalid ref");
}
}
void GlkAPI::glk_set_hyperlink(uint linkval) {
_streams->getCurrent()->setHyperlink(linkval);
}
void GlkAPI::glk_set_hyperlink_stream(strid_t str, uint linkval) {
if (str)
str->setHyperlink(linkval);
}
void GlkAPI::glk_request_hyperlink_event(winid_t win) {
if (!win) {
warning("request_hyperlink_event: invalid ref");
} else {
win->requestHyperlinkEvent();
}
}
void GlkAPI::glk_cancel_hyperlink_event(winid_t win) {
if (win) {
win->cancelHyperlinkEvent();
} else {
warning("cancel_hyperlink_event: invalid ref");
}
}
/*--------------------------------------------------------------------------*/
void GlkAPI::glk_current_time(glktimeval_t *time) {
TimeAndDate td;
*time = td;
}
int GlkAPI::glk_current_simple_time(uint factor) {
assert(factor);
TimeAndDate td;
return td / factor;
}
void GlkAPI::glk_time_to_date_utc(const glktimeval_t *time, glkdate_t *date) {
// TODO: timezones aren't currently supported
*date = TimeAndDate(*time);
}
void GlkAPI::glk_time_to_date_local(const glktimeval_t *time, glkdate_t *date) {
*date = TimeAndDate(*time);
}
void GlkAPI::glk_simple_time_to_date_utc(int time, uint factor, glkdate_t *date) {
TimeSeconds secs = (int64)time * factor;
*date = TimeAndDate(secs);
}
void GlkAPI::glk_simple_time_to_date_local(int time, uint factor, glkdate_t *date) {
TimeSeconds secs = (int64)time * factor;
*date = TimeAndDate(secs);
}
void GlkAPI::glk_date_to_time_utc(const glkdate_t *date, glktimeval_t *time) {
// WORKAROUND: timezones aren't currently supported
*time = TimeAndDate(*date);
}
void GlkAPI::glk_date_to_time_local(const glkdate_t *date, glktimeval_t *time) {
*time = TimeAndDate(*date);
}
int GlkAPI::glk_date_to_simple_time_utc(const glkdate_t *date, uint factor) {
// WORKAROUND: timezones aren't currently supported
assert(factor);
TimeSeconds ts = TimeAndDate(*date);
return ts / factor;
}
int GlkAPI::glk_date_to_simple_time_local(const glkdate_t *date, uint factor) {
assert(factor);
TimeSeconds ts = TimeAndDate(*date);
return ts / factor;
}
/*--------------------------------------------------------------------------*/
/* XXX non-official Glk functions */
const char *GlkAPI::garglk_fileref_get_name(frefid_t fref) const {
return fref->_filename.c_str();
}
void GlkAPI::garglk_set_program_name(const char *name) {
// Program name isn't displayed
}
void GlkAPI::garglk_set_program_info(const char *info) {
// Program info isn't displayed
}
void GlkAPI::garglk_set_story_name(const char *name) {
// Story name isn't displayed
}
void GlkAPI::garglk_set_story_title(const char *title) {
// Story title isn't displayed
}
void GlkAPI::garglk_set_config(const char *name) {
// No implementation
}
void GlkAPI::garglk_unput_string(const char *str) {
_streams->getCurrent()->unputBuffer(str, strlen(str));
}
void GlkAPI::garglk_unput_string_uni(const uint32 *str) {
_streams->getCurrent()->unputBufferUni(str, strlen_uni(str));
}
void GlkAPI::garglk_set_zcolors(uint fg, uint bg) {
_streams->getCurrent()->setZColors(fg, bg);
}
void GlkAPI::garglk_set_zcolors_stream(strid_t str, uint fg, uint bg) {
if (str) {
str->setZColors(fg, bg);
} else {
warning("set_style_stream: Invalid ref");
}
}
void GlkAPI::garglk_set_reversevideo(uint reverse) {
_streams->getCurrent()->setReverseVideo(reverse != 0);
}
void GlkAPI::garglk_set_reversevideo_stream(strid_t str, uint reverse) {
if (str) {
str->setReverseVideo(reverse != 0);
} else {
warning("set_reversevideo: Invalid ref");
}
}
} // End of namespace Glk