mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-26 12:48:16 +00:00
f1d9722f3b
This is primarily for the V6 games, which have up to 8 windows on-screen at the same time in arbitray positions ext
1213 lines
29 KiB
C++
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
|