1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef GLK_STREAMS_H 24 #define GLK_STREAMS_H 25 26 #include "common/scummsys.h" 27 #include "common/file.h" 28 #include "common/savefile.h" 29 #include "common/str.h" 30 #include "glk/glk_types.h" 31 32 namespace Glk { 33 34 #define SAVEGAME_VERSION 1 35 36 class Window; 37 class Streams; 38 39 enum FileUsage { 40 fileusage_Data = 0x00, 41 fileusage_SavedGame = 0x01, 42 fileusage_Transcript = 0x02, 43 fileusage_InputRecord = 0x03, 44 fileusage_TypeMask = 0x0f, 45 46 fileusage_TextMode = 0x100, 47 fileusage_BinaryMode = 0x000 48 }; 49 50 enum FileMode { 51 filemode_Write = 0x01, 52 filemode_Read = 0x02, 53 filemode_ReadWrite = 0x03, 54 filemode_WriteAppend = 0x05 55 }; 56 57 enum SeekMode { 58 seekmode_Start = 0, 59 seekmode_Current = 1, 60 seekmode_End = 2 61 }; 62 63 struct StreamResult { 64 uint _readCount; 65 uint _writeCount; 66 }; 67 typedef StreamResult stream_result_t; 68 69 /** 70 * File details 71 */ 72 struct FileReference { 73 uint _rock; 74 int _slotNumber; 75 Common::String _description; 76 Common::String _filename; 77 FileUsage _fileType; 78 bool _textMode; 79 gidispatch_rock_t _dispRock; 80 81 /** 82 * Constructor 83 */ 84 FileReference(); 85 86 /** 87 * Constructor 88 */ 89 FileReference(int slot, const Common::String &desc, uint usage, uint rock = 0); 90 91 /** 92 * Destructor 93 */ 94 ~FileReference(); 95 96 /** 97 * Get savegame filename 98 */ 99 const Common::String getSaveName() const; 100 101 /** 102 * Returns true if the given file exists 103 */ 104 bool exists() const; 105 106 /** 107 * Delete the given file 108 */ 109 void deleteFile(); 110 }; 111 112 typedef FileReference *frefid_t; 113 typedef Common::Array< Common::SharedPtr<FileReference> > FileRefArray; 114 115 116 /** 117 * Base class for streams 118 */ 119 class Stream { 120 public: 121 Streams *_streams; 122 Stream *_prev; 123 Stream *_next; 124 uint _rock; 125 gidispatch_rock_t _dispRock; 126 bool _unicode; 127 uint _readCount; 128 uint _writeCount; 129 bool _readable, _writable; 130 public: 131 /** 132 * Constructor 133 */ 134 Stream(Streams *streams, bool readable, bool writable, uint rock, bool unicode); 135 136 /** 137 * Destructor 138 */ 139 virtual ~Stream(); 140 141 /** 142 * Get the next stream 143 */ 144 Stream *getNext(uint *rock) const; 145 146 /** 147 * Get the rock value for the stream 148 */ getRock()149 uint getRock() const { 150 return _rock; 151 } 152 153 /** 154 * Fill out the total amount read and/or written 155 */ 156 void fillResult(StreamResult *result); 157 158 /** 159 * Close and delete the stream 160 */ 161 void close(StreamResult *result = nullptr); 162 163 /** 164 * Write a character 165 */ 166 virtual void putChar(unsigned char ch) = 0; 167 168 /** 169 * Write a unicode character 170 */ 171 virtual void putCharUni(uint32 ch) = 0; 172 173 /** 174 * Write a buffer 175 */ 176 virtual void putBuffer(const char *buf, size_t len) = 0; 177 178 /** 179 * Write a unicode character 180 */ 181 virtual void putBufferUni(const uint32 *buf, size_t len) = 0; 182 183 /** 184 * Remove a string from the end of the stream, if indeed it is at the end 185 */ unputBuffer(const char * buf,size_t len)186 virtual void unputBuffer(const char *buf, size_t len) {} 187 188 /** 189 * Remove a string from the end of the stream, if indeed it is at the end 190 */ unputBufferUni(const uint32 * buf,size_t len)191 virtual void unputBufferUni(const uint32 *buf, size_t len) {} 192 193 /** 194 * Send a line to the stream with a trailing newline 195 */ echoLine(const char * buf,uint len)196 void echoLine(const char *buf, uint len) { 197 putBuffer(buf, len); 198 putChar('\n'); 199 }; 200 201 /** 202 * Send a line to the stream with a trailing newline 203 */ echoLineUni(const uint32 * buf,uint len)204 void echoLineUni(const uint32 *buf, uint len) { 205 putBufferUni(buf, len); 206 putCharUni('\n'); 207 } 208 getPosition()209 virtual uint getPosition() const { 210 return 0; 211 } 212 setPosition(int pos,uint seekMode)213 virtual void setPosition(int pos, uint seekMode) {} 214 setStyle(uint val)215 virtual void setStyle(uint val) {} 216 217 /** 218 * Get a character from the stream 219 */ getChar()220 virtual int getChar() { 221 return -1; 222 } 223 224 /** 225 * Get a unicode character from the stream 226 */ getCharUni()227 virtual int getCharUni() { 228 return -1; 229 } 230 231 /** 232 * Get a buffer 233 */ getBuffer(char * buf,uint len)234 virtual uint getBuffer(char *buf, uint len) { 235 return 0; 236 } 237 238 /** 239 * Get a unicode buffer 240 */ getBufferUni(uint32 * buf,uint len)241 virtual uint getBufferUni(uint32 *buf, uint len) { 242 return 0; 243 } 244 245 /** 246 * Get a line 247 */ getLine(char * buf,uint len)248 virtual uint getLine(char *buf, uint len) { 249 return 0; 250 } 251 252 /** 253 * Get a unicode line 254 */ getLineUni(uint32 * ubuf,uint len)255 virtual uint getLineUni(uint32 *ubuf, uint len) { 256 return 0; 257 } 258 259 /** 260 * Set a hyperlink 261 */ setHyperlink(uint linkVal)262 virtual void setHyperlink(uint linkVal) {} 263 264 /** 265 * Set the style colors 266 */ 267 virtual void setZColors(uint fg, uint bg); 268 269 /** 270 * Set the reverse video style 271 */ 272 virtual void setReverseVideo(bool reverse); 273 274 /** 275 * Cast a stream to a ScummVM write stream 276 */ 277 virtual operator Common::WriteStream *() const { return nullptr; } 278 279 /** 280 * Cast a stream to a ScummVM read stream 281 */ 282 virtual operator Common::SeekableReadStream *() const { return nullptr; } 283 }; 284 typedef Stream *strid_t; 285 286 /** 287 * Implements the stream for writing text to a window 288 */ 289 class WindowStream : public Stream { 290 private: 291 Window *_window; 292 public: 293 /** 294 * Constructor 295 */ 296 WindowStream(Streams *streams, Window *window, uint rock = 0, bool unicode = true) : Stream(streams,false,true,rock,unicode)297 Stream(streams, false, true, rock, unicode), _window(window) {} 298 299 /** 300 * Destructor 301 */ 302 ~WindowStream() override; 303 304 /** 305 * Close the stream 306 */ 307 virtual void close(StreamResult *result = nullptr); 308 309 /** 310 * Write a character 311 */ 312 void putChar(unsigned char ch) override; 313 314 /** 315 * Write a unicode character 316 */ 317 void putCharUni(uint32 ch) override; 318 319 /** 320 * Write a buffer 321 */ 322 void putBuffer(const char *buf, size_t len) override; 323 324 /** 325 * Write a unicode character 326 */ 327 void putBufferUni(const uint32 *buf, size_t len) override; 328 329 /** 330 * Remove a string from the end of the stream, if indeed it is at the end 331 */ 332 void unputBuffer(const char *buf, size_t len) override; 333 334 /** 335 * Remove a string from the end of the stream, if indeed it is at the end 336 */ 337 void unputBufferUni(const uint32 *buf, size_t len) override; 338 339 void setStyle(uint val) override; 340 341 /** 342 * Set a hyperlink 343 */ 344 void setHyperlink(uint linkVal) override; 345 346 /** 347 * Set the style colors 348 */ 349 void setZColors(uint fg, uint bg) override; 350 351 /** 352 * Set the reverse video style 353 */ 354 void setReverseVideo(bool reverse) override; 355 }; 356 357 /** 358 * Implements an in-memory stream 359 */ 360 class MemoryStream : public Stream { 361 private: 362 void *_buf; ///< unsigned char* for latin1, uint* for unicode 363 void *_bufPtr; 364 void *_bufEnd; 365 void *_bufEof; 366 size_t _bufLen; ///< # of bytes for latin1, # of 4-byte words for unicode 367 gidispatch_rock_t _arrayRock; 368 public: 369 /** 370 * Constructor 371 */ 372 MemoryStream(Streams *streams, void *buf, size_t buflen, FileMode mode, uint rock = 0, bool unicode = true); 373 374 /** 375 * Destructor 376 */ 377 ~MemoryStream() override; 378 379 /** 380 * Write a character 381 */ 382 void putChar(unsigned char ch) override; 383 384 /** 385 * Write a unicode character 386 */ 387 void putCharUni(uint32 ch) override; 388 389 /** 390 * Write a buffer 391 */ 392 void putBuffer(const char *buf, size_t len) override; 393 394 /** 395 * Write a unicode character 396 */ 397 void putBufferUni(const uint32 *buf, size_t len) override; 398 399 uint getPosition() const override; 400 401 void setPosition(int pos, uint seekMode) override; 402 403 /** 404 * Get a character from the stream 405 */ 406 int getChar() override; 407 408 /** 409 * Get a unicode character from the stream 410 */ 411 int getCharUni() override; 412 413 /** 414 * Get a buffer 415 */ 416 uint getBuffer(char *buf, uint len) override; 417 418 /** 419 * Get a unicode buffer 420 */ 421 uint getBufferUni(uint32 *buf, uint len) override; 422 423 /** 424 * Get a line 425 */ 426 uint getLine(char *buf, uint len) override; 427 428 /** 429 * Get a unicode line 430 */ 431 uint getLineUni(uint32 *ubuf, uint len) override; 432 }; 433 434 /** 435 * Base class for I/O streams 436 */ 437 class IOStream : public Stream { 438 private: 439 Common::SeekableReadStream *_inStream; 440 Common::WriteStream *_outStream; 441 uint _lastOp; ///< 0, filemode_Write, or filemode_Read 442 private: 443 /** 444 * Ensure the stream is ready for the given operation 445 */ 446 void ensureOp(FileMode mode); 447 448 /** 449 * Put a UTF8 character 450 */ 451 void putCharUtf8(uint val); 452 453 /** 454 * Get a UTF8 character 455 */ 456 int getCharUtf8(); 457 protected: 458 bool _textFile; 459 public: 460 /** 461 * Constructor 462 */ IOStream(Streams * streams,bool readable,bool writable,uint rock,bool unicode)463 IOStream(Streams *streams, bool readable, bool writable, uint rock, bool unicode) : 464 Stream(streams, readable, writable, rock, unicode) {} Stream(streams,false,false,rock,false)465 IOStream(Streams *streams, uint rock = 0) : Stream(streams, false, false, rock, false), 466 _inStream(nullptr), _outStream(nullptr), _lastOp(0), _textFile(false) {} 467 IOStream(Streams *streams, Common::SeekableReadStream *inStream, uint rock = 0) : Stream(streams,true,false,rock,false)468 Stream(streams, true, false, rock, false), _inStream(inStream), _outStream(nullptr), _lastOp(0), _textFile(false) {} 469 IOStream(Streams *streams, Common::WriteStream *outStream, uint rock = 0) : Stream(streams,false,true,rock,false)470 Stream(streams, false, true, rock, false), _inStream(nullptr), _outStream(outStream), _lastOp(0), _textFile(false) {} 471 472 /** 473 * Sets the stream to use 474 */ setStream(Common::SeekableReadStream * rs)475 void setStream(Common::SeekableReadStream *rs) { 476 _inStream = rs; 477 _outStream = nullptr; 478 _readable = true; 479 _writable = false; 480 } 481 482 /** 483 * Sets the stream to use 484 */ setStream(Common::WriteStream * ws)485 void setStream(Common::WriteStream *ws) { 486 _inStream = nullptr; 487 _outStream = ws; 488 _readable = false; 489 _writable = true; 490 } 491 492 /** 493 * Write a character 494 */ 495 void putChar(unsigned char ch) override; 496 497 /** 498 * Write a unicode character 499 */ 500 void putCharUni(uint32 ch) override; 501 502 /** 503 * Write a buffer 504 */ 505 void putBuffer(const char *buf, size_t len) override; 506 507 /** 508 * Write a unicode character 509 */ 510 void putBufferUni(const uint32 *buf, size_t len) override; 511 512 uint getPosition() const override; 513 514 void setPosition(int pos, uint seekMode) override; 515 516 /** 517 * Get a character from the stream 518 */ 519 int getChar() override; 520 521 /** 522 * Get a unicode character from the stream 523 */ 524 int getCharUni() override; 525 526 /** 527 * Get a buffer 528 */ 529 uint getBuffer(char *buf, uint len) override; 530 531 /** 532 * Get a unicode buffer 533 */ 534 uint getBufferUni(uint32 *buf, uint len) override; 535 536 /** 537 * Get a line 538 */ 539 uint getLine(char *buf, uint len) override; 540 541 /** 542 * Get a unicode line 543 */ 544 uint getLineUni(uint32 *ubuf, uint len) override; 545 546 /** 547 * Cast a stream to a ScummVM write stream 548 */ 549 operator Common::WriteStream *() const override { return _outStream; } 550 551 /** 552 * Cast a stream to a ScummVM read stream 553 */ 554 operator Common::SeekableReadStream *() const override { return _inStream; } 555 }; 556 557 /** 558 * Implements a file stream 559 */ 560 class FileStream : public IOStream { 561 private: 562 Common::File _file; 563 Common::InSaveFile *_inSave; 564 Common::OutSaveFile *_outSave; 565 public: 566 /** 567 * Constructor 568 */ 569 FileStream(Streams *streams, frefid_t fref, uint fmode, uint rock, bool unicode); 570 571 /** 572 * Destructor 573 */ 574 ~FileStream() override; 575 }; 576 577 /** 578 * Streams manager 579 */ 580 class Streams { 581 friend class Stream; 582 private: 583 Stream *_streamList; 584 Stream *_currentStream; 585 FileRefArray _fileReferences; 586 private: 587 /** 588 * Adds a created stream to the list 589 */ 590 void addStream(Stream *stream); 591 592 /** 593 * Remove a stream 594 */ 595 void removeStream(Stream *stream); 596 public: 597 /** 598 * Constructor 599 */ 600 Streams(); 601 602 /** 603 * Destructor 604 */ 605 ~Streams(); 606 607 /** 608 * Open a file stream 609 */ 610 FileStream *openFileStream(frefid_t fref, uint fmode, uint rock = 0, bool unicode = false); 611 612 /** 613 * Open a ScummVM read stream 614 */ 615 IOStream *openStream(Common::SeekableReadStream *rs, uint rock = 0); 616 617 /** 618 * Open a ScummVM write stream 619 */ 620 IOStream *openStream(Common::WriteStream *ws, uint rock = 0); 621 622 /** 623 * Open a window stream 624 */ 625 WindowStream *openWindowStream(Window *window); 626 627 /** 628 * Open a memory stream 629 */ 630 MemoryStream *openMemoryStream(void *buf, size_t buflen, FileMode mode, uint rock = 0, bool unicode = true); 631 632 /** 633 * Delete a stream 634 */ deleteStream(Stream * stream)635 void deleteStream(Stream *stream) { 636 delete stream; 637 } 638 639 /** 640 * Start an Iteration through streams 641 */ 642 Stream *getFirst(uint *rock); 643 644 /** 645 * Set the current output stream 646 */ setCurrent(Stream * stream)647 void setCurrent(Stream *stream) { 648 assert(!stream || stream->_writable); 649 _currentStream = stream; 650 } 651 652 /** 653 * Gets the current output stream 654 */ getCurrent()655 Stream *getCurrent() const { 656 return _currentStream; 657 } 658 659 /** 660 * Prompt for a savegame to load or save, and populate a file reference from the result 661 */ 662 frefid_t createByPrompt(uint usage, FileMode fmode, uint rock); 663 664 /** 665 * Create a new file reference 666 */ 667 frefid_t createRef(int slot, const Common::String &desc, uint usage, uint rock); 668 669 /** 670 * Create a new file reference 671 */ 672 frefid_t createRef(const Common::String &filename, uint usage, uint rock); 673 674 /** 675 * Create a new temporary file reference 676 */ 677 frefid_t createTemp(uint usage, uint rock); 678 679 /** 680 * Create a new file reference from an old one 681 */ 682 frefid_t createFromRef(frefid_t fref, uint usage, uint rock); 683 684 /** 685 * Delete a file reference 686 */ 687 void deleteRef(frefid_t fref); 688 689 /** 690 * Iterates to the next file reference following the specified one, 691 * or the first if null is passed 692 */ 693 frefid_t iterate(frefid_t fref, uint *rock); 694 }; 695 696 } // End of namespace Glk 697 698 #endif 699