From 485e899312d1cf092e7cb52927593be21ef0f263 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 25 Oct 2018 21:45:23 -0700 Subject: GLK: Adding glk stream methods --- engines/gargoyle/glk.cpp | 54 +++++++---- engines/gargoyle/glk.h | 4 +- engines/gargoyle/glk_types.h | 5 - engines/gargoyle/streams.cpp | 214 +++++++++++++++++++++++++++++++++++++++++++ engines/gargoyle/streams.h | 36 ++++++++ 5 files changed, 286 insertions(+), 27 deletions(-) (limited to 'engines') diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp index d81ddf5b63..19933756f3 100644 --- a/engines/gargoyle/glk.cpp +++ b/engines/gargoyle/glk.cpp @@ -335,12 +335,11 @@ strid_t Glk::glk_stream_open_file(frefid_t fileref, FileMode fmode, glui32 rock) } strid_t Glk::glk_stream_open_memory(char *buf, glui32 buflen, FileMode fmode, glui32 rock) { - // TODO - return nullptr; + return _streams->addMemoryStream(buf, buflen, fmode, rock, false); } void Glk::glk_stream_close(strid_t str, stream_result_t *result) { - // TODO + str->close(result); } strid_t Glk::glk_stream_iterate(strid_t str, glui32 *rockptr) const { @@ -356,22 +355,29 @@ glui32 Glk::glk_stream_get_rock(strid_t str) const { return str->getRock(); } -void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) { - // TODO +void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekMode) { + if (!str) { + warning("stream_set_position: invalid ref"); + } else { + str->setPosition(pos, seekMode); + } } -glui32 Glk::glk_stream_get_position(strid_t str) { - // TODO - return 0; +glui32 Glk::glk_stream_get_position(strid_t str) const { + if (!str) { + warning("stream_get_position: invalid ref"); + return 0; + } else { + return str->getPosition(); + } } void Glk::glk_stream_set_current(strid_t str) { - // TODO + _streams->setCurrent(str); } strid_t Glk::glk_stream_get_current(void) { - // TODO - return nullptr; + return _streams->getCurrent(); } void Glk::glk_put_char(unsigned char ch) { @@ -387,32 +393,40 @@ void Glk::glk_put_char_stream(strid_t str, unsigned char ch) { } void Glk::glk_put_string(const char *s) { - // TODO + _streams->getCurrent()->putBuffer(s, strlen(s)); } void Glk::glk_put_string_stream(strid_t str, const char *s) { - // TODO + str->putBuffer(s, strlen(s)); } void Glk::glk_put_buffer(char *buf, glui32 len) { - // TODO + _streams->getCurrent()->putBuffer(buf, len); } void Glk::glk_put_buffer_stream(strid_t str, const char *buf, glui32 len) { - // TODO + str->putBuffer(buf, len); } void Glk::glk_set_style(glui32 styl) { - // TODO + _streams->getCurrent()->setStyle(styl); } void Glk::glk_set_style_stream(strid_t str, glui32 styl) { - // TODO + if (str) { + str->setStyle(styl); + } else { + warning("set_style_stream: invalid ref"); + } } glsi32 Glk::glk_get_char_stream(strid_t str) { - // TODO - return 0; + if (str) { + warning("get_char_stream: invalid ref"); + return -1; + } else { + return str->getChar(); + } } glui32 Glk::glk_get_line_stream(strid_t str, char *buf, glui32 len) { @@ -661,7 +675,7 @@ strid_t Glk::glk_stream_open_file_uni(frefid_t fileref, FileMode fmode, glui32 r } strid_t Glk::glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, FileMode fmode, glui32 rock) { - return _streams->addMemoryStream(buf, buflen, fmode, rock, false); + return _streams->addMemoryStream(buf, buflen, fmode, rock, true); } void Glk::glk_request_char_event_uni(winid_t win) { diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h index e1923b7b02..3b49421d16 100644 --- a/engines/gargoyle/glk.h +++ b/engines/gargoyle/glk.h @@ -96,8 +96,8 @@ public: void glk_stream_close(strid_t str, stream_result_t *result); strid_t glk_stream_iterate(strid_t str, glui32 *rockptr) const; glui32 glk_stream_get_rock(strid_t str) const; - void glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode); - glui32 glk_stream_get_position(strid_t str); + void glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekMode); + glui32 glk_stream_get_position(strid_t str) const; void glk_stream_set_current(strid_t str); strid_t glk_stream_get_current(void); diff --git a/engines/gargoyle/glk_types.h b/engines/gargoyle/glk_types.h index 81d05ac391..a521548047 100644 --- a/engines/gargoyle/glk_types.h +++ b/engines/gargoyle/glk_types.h @@ -46,11 +46,6 @@ class Window; #define GLK_MODULE_DATETIME #define GLK_MODULE_GARGLKTEXT -/** - * These types are opaque object identifiers. They're pointers to opaque - * C structures, which are defined differently by each library. - */ -typedef struct glk_fileref_struct *frefid_t; typedef struct glk_schannel_struct *schanid_t; /** diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp index 749999153c..6a73c5b3e9 100644 --- a/engines/gargoyle/streams.cpp +++ b/engines/gargoyle/streams.cpp @@ -144,6 +144,18 @@ void WindowStream::putBufferUni(const uint32 *buf, size_t len) { _window->_echoStream->putBufferUni(buf, len); } +void WindowStream::setStyle(glui32 val) { + if (!_writable) + return; + + if (val >= style_NUMSTYLES) + val = 0; + + _window->_attr.style = val; + if (_window->_echoStream) + _window->_echoStream->setStyle(val); +} + /*--------------------------------------------------------------------------*/ MemoryStream::MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) : @@ -297,6 +309,66 @@ void MemoryStream::putBufferUni(const uint32 *buf, size_t len) { } } +glui32 MemoryStream::getPosition() const { + if (_unicode) + return ((glui32 *)_bufPtr - (glui32 *)_buf); + else + return ((unsigned char *)_bufPtr - (unsigned char *)_buf); +} + +void MemoryStream::setPosition(glui32 pos, glui32 seekMode) { + if (!_unicode) + { + if (seekMode == seekmode_Current) + pos = ((unsigned char *)_bufPtr - (unsigned char *)_buf) + pos; + else if (seekMode == seekmode_End) + pos = ((unsigned char *)_bufEof - (unsigned char *)_buf) + pos; + else + /* pos = pos */; + if (pos < 0) + pos = 0; + if (pos > (glui32)((unsigned char *)_bufEof - (unsigned char *)_buf)) + pos = ((unsigned char *)_bufEof - (unsigned char *)_buf); + _bufPtr = (unsigned char *)_buf + pos; + } else { + if (seekMode == seekmode_Current) + pos = ((glui32 *)_bufPtr - (glui32 *)_buf) + pos; + else if (seekMode == seekmode_End) + pos = ((glui32 *)_bufEof - (glui32 *)_buf) + pos; + + if (pos < 0) + pos = 0; + if (pos > (glui32)((glui32 *)_bufEof - (glui32 *)_buf)) + pos = ((glui32 *)_bufEof - (glui32 *)_buf); + _bufPtr = (glui32 *)_buf + pos; + } +} + +glsi32 MemoryStream::getChar() { + if (!_readable) + return -1; + + if (_bufPtr < _bufEnd) { + if (!_unicode) { + unsigned char ch; + ch = *((unsigned char *)_bufPtr); + _bufPtr = ((unsigned char *)_bufPtr) + 1; + _readCount++; + return ch; + } else { + glui32 ch; + ch = *((glui32 *)_bufPtr); + _bufPtr = ((glui32 *)_bufPtr) + 1; + _readCount++; + if (ch > 0xff) + ch = '?'; + return ch; + } + } else { + return -1; + } +} + /*--------------------------------------------------------------------------*/ FileStream::FileStream(Streams *streams, uint32 rock, bool unicode) : @@ -409,6 +481,148 @@ void FileStream::putCharUtf8(glui32 val) { } } +glsi32 FileStream::getCharUtf8() { + glui32 res; + glui32 val0, val1, val2, val3; + + if (_inFile->eos()) + return -1; + val0 = _inFile->readByte(); + if (val0 < 0x80) { + res = val0; + return res; + } + + if ((val0 & 0xe0) == 0xc0) { + if (_inFile->eos()) { + warning("incomplete two-byte character"); + return -1; + } + + val1 = _inFile->readByte(); + if ((val1 & 0xc0) != 0x80) { + warning("malformed two-byte character"); + return '?'; + } + + res = (val0 & 0x1f) << 6; + res |= (val1 & 0x3f); + return res; + } + + if ((val0 & 0xf0) == 0xe0) { + val1 = _inFile->readByte(); + val2 = _inFile->readByte(); + if (_inFile->eos()) { + warning("incomplete three-byte character"); + return -1; + } + if ((val1 & 0xc0) != 0x80) { + warning("malformed three-byte character"); + return '?'; + } + if ((val2 & 0xc0) != 0x80) { + warning("malformed three-byte character"); + return '?'; + } + + res = (((val0 & 0xf) << 12) & 0x0000f000); + res |= (((val1 & 0x3f) << 6) & 0x00000fc0); + res |= (((val2 & 0x3f)) & 0x0000003f); + return res; + } + + if ((val0 & 0xf0) == 0xf0) { + if ((val0 & 0xf8) != 0xf0) { + warning("malformed four-byte character"); + return '?'; + } + + val1 = _inFile->readByte(); + val2 = _inFile->readByte(); + val3 = _inFile->readByte(); + if (_inFile->eos()) { + warning("incomplete four-byte character"); + return -1; + } + if ((val1 & 0xc0) != 0x80) { + warning("malformed four-byte character"); + return '?'; + } + if ((val2 & 0xc0) != 0x80) { + warning("malformed four-byte character"); + return '?'; + } + if ((val3 & 0xc0) != 0x80) { + warning("malformed four-byte character"); + return '?'; + } + + res = (((val0 & 0x7) << 18) & 0x1c0000); + res |= (((val1 & 0x3f) << 12) & 0x03f000); + res |= (((val2 & 0x3f) << 6) & 0x000fc0); + res |= (((val3 & 0x3f)) & 0x00003f); + return res; + } + + warning("malformed character"); + return '?'; +} + +glui32 FileStream::getPosition() const { + return _outFile->pos(); +} + +void FileStream::setPosition(glui32 pos, glui32 seekMode) { + _lastOp = 0; + if (_unicode) + pos *= 4; + + error("FileStream::setPosition - seek not yet supported"); +// fseek(str->file, pos, ((seekmode == seekmode_Current) ? 1 : + // ((seekmode == seekmode_End) ? 2 : 0))); +} + +glsi32 FileStream::getChar() { + if (!_readable) + return -1; + + ensureOp(filemode_Read); + int res; + if (!_unicode) { + res = _inFile->readByte(); + } else if (_textFile) { + res = getCharUtf8(); + } else { + glui32 ch; + res = _inFile->readByte(); + if (_inFile->eos()) + return -1; + ch = (res & 0xFF); + res = _inFile->readByte(); + if (_inFile->eos()) + return -1; + ch = (ch << 8) | (res & 0xFF); + res = _inFile->readByte(); + if (_inFile->eos()) + return -1; + ch = (ch << 8) | (res & 0xFF); + res = _inFile->readByte(); + if (_inFile->eos()) + return -1; + ch = (ch << 8) | (res & 0xFF); + res = ch; + } + if (res != -1) { + _readCount++; + if (res >= 0x100) + return '?'; + return (glsi32)res; + } else { + return -1; + } +} + /*--------------------------------------------------------------------------*/ Streams::Streams() : _streamList(nullptr), _currentStream(nullptr) { diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h index 51ab484eb7..8b7da6ff4c 100644 --- a/engines/gargoyle/streams.h +++ b/engines/gargoyle/streams.h @@ -32,6 +32,15 @@ namespace Gargoyle { class Window; class Streams; +struct FileReference { + glui32 _rock; + Common::String _filename; + int _fileType; + int _textMode; + gidispatch_rock_t _dispRock; +}; +typedef FileReference *frefid_t; + struct StreamResult { uint32 _readCount; uint32 _writeCount; @@ -117,6 +126,14 @@ public: putBufferUni(buf, len); putCharUni('\n'); } + + virtual glui32 getPosition() const { return 0; } + + virtual void setPosition(glui32 pos, glui32 seekMode) {} + + virtual void setStyle(glui32 val) {} + + virtual glsi32 getChar() { return -1; } }; typedef Stream *strid_t; @@ -157,6 +174,8 @@ public: * Write a unicode character */ virtual void putBufferUni(const uint32 *buf, size_t len) override; + + virtual void setStyle(glui32 val) override; }; /** @@ -194,6 +213,12 @@ public: * Write a unicode character */ virtual void putBufferUni(const uint32 *buf, size_t len) override; + + virtual glui32 getPosition() const override; + + virtual void setPosition(glui32 pos, glui32 seekMode) override; + + virtual glsi32 getChar() override; }; /** @@ -215,6 +240,11 @@ private: * Put a UTF8 character */ void putCharUtf8(glui32 val); + + /** + * Get a UTF8 character + */ + glsi32 getCharUtf8(); public: /** * Constructor @@ -240,6 +270,12 @@ public: * Write a unicode character */ virtual void putBufferUni(const uint32 *buf, size_t len) override; + + virtual glui32 getPosition() const override; + + virtual void setPosition(glui32 pos, glui32 seekMode) override; + + virtual glsi32 getChar() override; }; /** -- cgit v1.2.3