From db61f4e0500c96503fbb69a78d7e7aafb2d71300 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 4 Nov 2018 19:24:46 -0800 Subject: GLK: Add miscellaneous stream methods --- engines/gargoyle/glk.cpp | 86 ++++++++------- engines/gargoyle/streams.cpp | 241 ++++++++++++++++++++++++++++++++++++++++++- engines/gargoyle/streams.h | 37 +++++++ 3 files changed, 323 insertions(+), 41 deletions(-) diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp index 53c9093fdf..43b6d0a2e8 100644 --- a/engines/gargoyle/glk.cpp +++ b/engines/gargoyle/glk.cpp @@ -184,35 +184,35 @@ winid_t Glk::glk_window_open(winid_t split, glui32 method, glui32 size, glui32 w } void Glk::glk_window_close(winid_t win, stream_result_t *result) { - if (!win) { - warning("glk_window_close: invalid ref"); - } else { + if (win) { _windows->windowClose(win, result); + } else { + warning("glk_window_close: invalid ref"); } } void Glk::glk_window_get_size(winid_t win, glui32 *width, glui32 *height) { - if (!win) { - warning("window_get_size: invalid ref"); - } else { + if (win) { win->getSize(width, height); + } else { + warning("window_get_size: invalid ref"); } } void Glk::glk_window_set_arrangement(winid_t win, glui32 method, glui32 size, winid_t keywin) { - if (!win) { - warning("window_set_arrangement: invalid ref"); - } else { + if (win) { win->setArrangement(method, size, keywin); + } else { + warning("window_set_arrangement: invalid ref"); } } void Glk::glk_window_get_arrangement(winid_t win, glui32 *method, glui32 *size, winid_t *keyWin) { - if (!win) { - warning("window_get_arrangement: invalid ref"); - } else { + if (win) { win->getArrangement(method, size, keyWin); + } else { + warning("window_get_arrangement: invalid ref"); } } @@ -232,21 +232,21 @@ winid_t Glk::glk_window_iterate(winid_t win, glui32 *rock) { } glui32 Glk::glk_window_get_rock(winid_t win) { - if (!win) { + if (win) { + return win->_rock; + } else { warning("window_get_rock: invalid ref."); return 0; } - - return win->_rock; } glui32 Glk::glk_window_get_type(winid_t win) { - if (!win) { + if (win) { + return win->_type; + } else { warning("window_get_parent: invalid ref"); return 0; } - - return win->_type; } winid_t Glk::glk_window_get_parent(winid_t win) { @@ -298,27 +298,27 @@ void Glk::glk_window_clear(winid_t win) { } void Glk::glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) { - if (!win) { - warning("window_move_cursor: invalid ref"); - } else { + if (win) { win->moveCursor(Point(xpos, ypos)); + } else { + warning("window_move_cursor: invalid ref"); } } strid_t Glk::glk_window_get_stream(winid_t win) { - if (!win) { + if (win) { + return win->_stream; + } else { warning("window_get_stream: invalid ref"); return nullptr; } - - return win->_stream; } void Glk::glk_window_set_echo_stream(winid_t win, strid_t str) { - if (!win) { - warning("window_set_echo_stream: invalid window id"); - } else { + if (win) { win->_echoStream = str; + } else { + warning("window_set_echo_stream: invalid window id"); } } @@ -361,19 +361,19 @@ glui32 Glk::glk_stream_get_rock(strid_t str) const { } void Glk::glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekMode) { - if (!str) { - warning("stream_set_position: invalid ref"); - } else { + if (str) { str->setPosition(pos, seekMode); + } else { + warning("stream_set_position: invalid ref"); } } glui32 Glk::glk_stream_get_position(strid_t str) const { - if (!str) { + if (str) { + return str->getPosition(); + } else { warning("stream_get_position: invalid ref"); return 0; - } else { - return str->getPosition(); } } @@ -427,21 +427,29 @@ void Glk::glk_set_style_stream(strid_t str, glui32 styl) { glsi32 Glk::glk_get_char_stream(strid_t str) { if (str) { + return str->getChar(); + } else { 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) { - // TODO - return 0; + if (str) { + return str->getLine(buf, len); + } else { + warning("get_line_stream: invalid ref"); + return 0; + } } glui32 Glk::glk_get_buffer_stream(strid_t str, char *buf, glui32 len) { - // TODO - return 0; + if (str) { + return str->getBuffer(buf, len); + } else { + warning("get_line_stream: invalid ref"); + return 0; + } } void Glk::glk_stylehint_set(glui32 wintype, glui32 style, glui32 hint, glsi32 val) { diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp index 0dc82eda10..24917c56dd 100644 --- a/engines/gargoyle/streams.cpp +++ b/engines/gargoyle/streams.cpp @@ -400,6 +400,63 @@ glsi32 MemoryStream::getCharUni() { } } +glui32 MemoryStream::getBuffer(char *buf, glui32 len) { + if (!_readable) + return 0; + + if (_bufPtr >= _bufEnd) { + len = 0; + } else { + if (!_unicode) { + unsigned char *bp = (unsigned char *)_bufPtr; + if (bp + len > (unsigned char *)_bufEnd) { + glui32 lx; + lx = (bp + len) - (unsigned char *)_bufEnd; + if (lx < len) + len -= lx; + else + len = 0; + } + + if (len) { + memcpy(buf, bp, len); + bp += len; + if (bp >(unsigned char *)_bufEof) + _bufEof = bp; + } + + _readCount += len; + _bufPtr = bp; + } else { + glui32 *bp = (glui32 *)_bufPtr; + if (bp + len > (glui32 *)_bufEnd) { + glui32 lx; + lx = (bp + len) - (glui32 *)_bufEnd; + if (lx < len) + len -= lx; + else + len = 0; + } + if (len) { + glui32 i; + for (i = 0; i < len; i++) { + glui32 ch = *bp++; + if (ch > 0xff) + ch = '?'; + *buf++ = (char)ch; + } + if (bp > (glui32 *)_bufEof) + _bufEof = bp; + } + + _readCount += len; + _bufPtr = bp; + } + } + + return len; +} + glui32 MemoryStream::getBufferUni(glui32 *buf, glui32 len) { if (!_readable) return 0; @@ -452,6 +509,66 @@ glui32 MemoryStream::getBufferUni(glui32 *buf, glui32 len) { return len; } +glui32 MemoryStream::getLine(char *buf, glui32 len) { + glui32 lx; + bool gotNewline; + + if (len == 0) + return 0; + + len -= 1; /* for the terminal null */ + if (!_unicode) { + if (_bufPtr >= _bufEnd) { + len = 0; + } else { + if ((char *)_bufPtr + len > (char *)_bufEnd) { + lx = ((char *)_bufPtr + len) - (char *)_bufEnd; + if (lx < len) + len -= lx; + else + len = 0; + } + } + + gotNewline = false; + for (lx = 0; lx < len && !gotNewline; lx++) { + buf[lx] = ((char *)_bufPtr)[lx]; + gotNewline = (buf[lx] == '\n'); + } + + buf[lx] = '\0'; + _bufPtr = ((char *)_bufPtr) + lx; + } else { + if (_bufPtr >= _bufEnd) { + len = 0; + } else { + if ((char *)_bufPtr + len > (char *)_bufEnd) { + lx = ((char *)_bufPtr + len) - (char *)_bufEnd; + if (lx < len) + len -= lx; + else + len = 0; + } + } + + gotNewline = false; + for (lx = 0; lx < len && !gotNewline; lx++) { + glui32 ch; + ch = ((glui32 *)_bufPtr)[lx]; + if (ch >= 0x100) + ch = '?'; + buf[lx] = (char)ch; + gotNewline = (ch == '\n'); + } + + buf[lx] = '\0'; + _bufPtr = ((glui32 *)_bufPtr) + lx; + } + + _readCount += lx; + return lx; +} + glui32 MemoryStream::getLineUni(glui32 *ubuf, glui32 len) { bool gotNewline; int lx; @@ -509,8 +626,8 @@ glui32 MemoryStream::getLineUni(glui32 *ubuf, glui32 len) { /*--------------------------------------------------------------------------*/ FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 rock, bool unicode) : - Stream(streams, true, false, rock, unicode), _lastOp(0), _textFile(false), - _inFile(nullptr), _outFile(nullptr), _inStream(nullptr) { + Stream(streams, fmode == filemode_Read, fmode != filemode_Read, rock, unicode), _lastOp(0), + _textFile(fref->_textMode), _inFile(nullptr), _outFile(nullptr), _inStream(nullptr) { Common::String fname = fref->_slotNumber == -1 ? fref->_filename : fref->getSaveName(); if (fmode == filemode_Write || fmode == filemode_ReadWrite || fmode == filemode_WriteAppend) { @@ -839,6 +956,56 @@ glsi32 FileStream::getCharUni() { } } +glui32 FileStream::getBuffer(char *buf, glui32 len) { + ensureOp(filemode_Read); + if (!_unicode) { + glui32 res; + res = _inStream->read(buf, len); + _readCount += res; + return res; + } else if (_textFile) { + glui32 lx; + for (lx = 0; lx= 0x100) + ch = '?'; + buf[lx] = (char)ch; + } + return lx; + } else { + glui32 lx; + for (lx = 0; lx < len; lx++) { + int res; + glui32 ch; + res = _inStream->readByte(); + if (res == -1) + break; + ch = (res & 0xFF); + res = _inStream->readByte(); + if (res == -1) + break; + ch = (ch << 8) | (res & 0xFF); + res = _inStream->readByte(); + if (res == -1) + break; + ch = (ch << 8) | (res & 0xFF); + res = _inStream->readByte(); + if (res == -1) + break; + ch = (ch << 8) | (res & 0xFF); + _readCount++; + if (ch >= 0x100) + ch = '?'; + buf[lx] = (char)ch; + } + return lx; + } +} + glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) { if (!_readable) return 0; @@ -897,6 +1064,76 @@ glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) { } } +glui32 FileStream::getLine(char *buf, glui32 len) { + glui32 lx; + bool gotNewline; + + if (len == 0) + return 0; + + ensureOp(filemode_Read); + if (!_unicode) { + char *res = buf; + for (; len > 0; ++res, --len) { + *res = _inStream->readByte(); + if (*res == '\n') + break; + } + *res = '\0'; + + lx = strlen(buf); + _readCount += lx; + return lx; + } else if (_textFile) { + len -= 1; // for the terminal null + gotNewline = false; + for (lx = 0; lx < len && !gotNewline; lx++) { + glui32 ch; + ch = getCharUtf8(); + if (ch == -1) + break; + _readCount++; + if (ch >= 0x100) + ch = '?'; + buf[lx] = (char)ch; + gotNewline = (ch == '\n'); + } + buf[lx] = '\0'; + return lx; + } else { + len -= 1; // for the terminal null + gotNewline = false; + for (lx = 0; lx < len && !gotNewline; lx++) { + int res; + glui32 ch; + res = _inStream->readByte(); + if (res == -1) + break; + ch = (res & 0xFF); + res = _inStream->readByte(); + if (res == -1) + break; + ch = (ch << 8) | (res & 0xFF); + res = _inStream->readByte(); + if (res == -1) + break; + ch = (ch << 8) | (res & 0xFF); + res = _inStream->readByte(); + if (res == -1) + break; + ch = (ch << 8) | (res & 0xFF); + _readCount++; + if (ch >= 0x100) + ch = '?'; + buf[lx] = (char)ch; + gotNewline = (ch == '\n'); + } + + buf[lx] = '\0'; + return lx; + } +} + glui32 FileStream::getLineUni(glui32 *ubuf, glui32 len) { bool gotNewline; int lx; diff --git a/engines/gargoyle/streams.h b/engines/gargoyle/streams.h index dad67816e3..16f63dbf0b 100644 --- a/engines/gargoyle/streams.h +++ b/engines/gargoyle/streams.h @@ -100,6 +100,13 @@ struct FileReference { */ FileReference() : _rock(0), _slotNumber(-1), _fileType(fileusage_Data), _textMode(false) {} + /** + * Constructor + */ + FileReference(int slot, const Common::String &desc, glui32 usage, glui32 rock = 0) : + _rock(rock), _slotNumber(slot), _description(desc), + _fileType((FileUsage)(usage & fileusage_TypeMask)), _textMode(usage & fileusage_TextMode) {} + /** * Get savegame filename */ @@ -216,11 +223,21 @@ public: */ virtual glsi32 getCharUni() { return -1; } + /** + * Get a buffer + */ + virtual glui32 getBuffer(char *buf, glui32 len) { return 0; } + /** * Get a unicode buffer */ virtual glui32 getBufferUni(glui32 *buf, glui32 len) { return 0; } + /** + * Get a line + */ + virtual glui32 getLine(char *buf, glui32 len) { return 0; } + /** * Get a unicode line */ @@ -329,11 +346,21 @@ public: */ virtual glsi32 getCharUni() override; + /** + * Get a buffer + */ + virtual glui32 getBuffer(char *buf, glui32 len) override; + /** * Get a unicode buffer */ virtual glui32 getBufferUni(glui32 *buf, glui32 len) override; + /** + * Get a line + */ + virtual glui32 getLine(char *buf, glui32 len) override; + /** * Get a unicode line */ @@ -421,11 +448,21 @@ public: */ virtual glsi32 getCharUni() override; + /** + * Get a buffer + */ + virtual glui32 getBuffer(char *buf, glui32 len) override; + /** * Get a unicode buffer */ virtual glui32 getBufferUni(glui32 *buf, glui32 len) override; + /** + * Get a line + */ + virtual glui32 getLine(char *buf, glui32 len) override; + /** * Get a unicode line */ -- cgit v1.2.3