From a24b27b14ac72f5f88d9dce57f79f5b9039fe482 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 3 Nov 2018 12:13:41 -0700 Subject: GLK: Create glk fileref methods --- engines/gargoyle/files.cpp | 79 ++++++++++++++++++++++++++++++++++++++++----- engines/gargoyle/files.h | 45 ++++++++++++++++++++++++-- engines/gargoyle/gargoyle.h | 5 +++ engines/gargoyle/glk.cpp | 42 +++++++++++++++--------- engines/gargoyle/glk.h | 12 +++---- 5 files changed, 148 insertions(+), 35 deletions(-) diff --git a/engines/gargoyle/files.cpp b/engines/gargoyle/files.cpp index c3f1367c66..e14a315f09 100644 --- a/engines/gargoyle/files.cpp +++ b/engines/gargoyle/files.cpp @@ -21,12 +21,15 @@ */ #include "gargoyle/files.h" +#include "gargoyle/gargoyle.h" #include "gui/saveload.h" +#include "common/file.h" +#include "common/savefile.h" #include "common/translation.h" namespace Gargoyle { -frefid_t Files::prompt(glui32 usage, FileMode fmode, glui32 rock) { +frefid_t Files::createByPrompt(glui32 usage, FileMode fmode, glui32 rock) { switch (usage & fileusage_TypeMask) { case fileusage_SavedGame: { if (fmode == filemode_Write) { @@ -64,34 +67,94 @@ frefid_t Files::prompt(glui32 usage, FileMode fmode, glui32 rock) { } frefid_t Files::createRef(int slot, const Common::String &desc, glui32 usage, glui32 rock) { - _fileReferences.push_back(FileReference()); - frefid_t fref = &_fileReferences.back(); - + frefid_t fref = new FileReference(); fref->_slotNumber = slot; fref->_description = desc; fref->_textMode = ((usage & fileusage_TextMode) != 0); fref->_fileType = (FileUsage)(usage & fileusage_TypeMask); + + _fileReferences.push_back(FileRefArray::value_type(fref)); return fref; } frefid_t Files::createRef(const Common::String &filename, glui32 usage, glui32 rock) { - _fileReferences.push_back(FileReference()); - frefid_t fref = &_fileReferences.back(); - + frefid_t fref = new FileReference(); fref->_filename = filename; fref->_textMode = ((usage & fileusage_TextMode) != 0); fref->_fileType = (FileUsage)(usage & fileusage_TypeMask); + + _fileReferences.push_back(FileRefArray::value_type(fref)); return fref; } +frefid_t Files::createTemp(glui32 usage, glui32 rock) { + return createRef(Common::String::format("%s.tmp", g_vm->getTargetName().c_str()), + usage, rock); +} + +frefid_t Files::createFromRef(frefid_t fref, glui32 usage, glui32 rock) { + return createRef(fref->_filename, usage, rock); +} + void Files::deleteRef(frefid_t fref) { for (uint idx = 0; idx < _fileReferences.size(); ++idx) { - if (&_fileReferences[idx] == fref) { + if (_fileReferences[idx].get() == fref) { _fileReferences.remove_at(idx); return; } } } +frefid_t Files::iterate(frefid_t fref, glui32 *rock) { + // Find reference following the specified one + int index = -1; + for (uint idx = 0; idx < _fileReferences.size(); ++idx) { + if (fref == nullptr || _fileReferences[idx].get() == fref) { + if (idx < (_fileReferences.size() - 1)) + index = idx + 1; + break; + } + } + + if (index != -1) { + if (rock) + *rock = _fileReferences[index].get()->_rock; + return _fileReferences[index].get(); + } + + if (rock) + *rock = 0; + return nullptr; +} + +/*--------------------------------------------------------------------------*/ + +const Common::String FileReference::getSaveName() const { + assert(_slotNumber != -1); + return Common::String::format("%s.%.3d", g_vm->getTargetName().c_str(), _slotNumber); +} + +bool FileReference::exists() const { + Common::String filename; + + if (_slotNumber == -1) { + if (Common::File::exists(_filename)) + return true; + filename = _filename; + } else { + filename = getSaveName(); + } + + // Check for a savegame (or other file in the save folder) with that name + Common::InSaveFile *inSave = g_system->getSavefileManager()->openForLoading(filename); + bool result = inSave != nullptr; + delete inSave; + return result; +} + +void FileReference::deleteFile() { + Common::String filename = (_slotNumber == -1) ? _filename : getSaveName(); + g_system->getSavefileManager()->removeSavefile(filename); +} } // End of namespace Gargoyle diff --git a/engines/gargoyle/files.h b/engines/gargoyle/files.h index cfd757b053..7e7ebfb726 100644 --- a/engines/gargoyle/files.h +++ b/engines/gargoyle/files.h @@ -25,6 +25,7 @@ #include "gargoyle/glk_types.h" #include "common/array.h" +#include "common/ptr.h" #include "common/str.h" namespace Gargoyle { @@ -65,17 +66,39 @@ struct FileReference { FileUsage _fileType; bool _textMode; gidispatch_rock_t _dispRock; + + /** + * Constructor + */ + FileReference() : _rock(0), _slotNumber(-1), _fileType(fileusage_Data), _textMode(false) {} + + /** + * Get savegame filename + */ + const Common::String getSaveName() const; + + /** + * Returns true if the given file exists + */ + bool exists() const; + + /** + * Delete the given file + */ + void deleteFile(); }; + typedef FileReference *frefid_t; +typedef Common::Array< Common::SharedPtr > FileRefArray; class Files { private: - Common::Array _fileReferences; + FileRefArray _fileReferences; public: /** - * Prompt for a file + * Prompt for a savegame to load or save, and populate a file reference from the result */ - frefid_t prompt(glui32 usage, FileMode fmode, glui32 rock); + frefid_t createByPrompt(glui32 usage, FileMode fmode, glui32 rock); /** * Create a new file reference @@ -87,10 +110,26 @@ public: */ frefid_t createRef(const Common::String &filename, glui32 usage, glui32 rock); + /** + * Create a new temporary file reference + */ + frefid_t createTemp(glui32 usage, glui32 rock); + + /** + * Create a new file reference from an old one + */ + frefid_t createFromRef(frefid_t fref, glui32 usage, glui32 rock); + /** * Delete a file reference */ void deleteRef(frefid_t fref); + + /** + * Iterates to the next file reference following the specified one, + * or the first if null is passed + */ + frefid_t iterate(frefid_t fref, glui32 *rock); }; } // End of namespace Gargoyle diff --git a/engines/gargoyle/gargoyle.h b/engines/gargoyle/gargoyle.h index 3538b4c825..651499e4e8 100644 --- a/engines/gargoyle/gargoyle.h +++ b/engines/gargoyle/gargoyle.h @@ -138,6 +138,11 @@ public: * Returns the primary filename for the game */ const Common::String &GargoyleEngine::getFilename() const; + + /** + * Return the game engine's target name + */ + const Common::String &getTargetName() const { return _targetName; } }; extern GargoyleEngine *g_vm; diff --git a/engines/gargoyle/glk.cpp b/engines/gargoyle/glk.cpp index 2f9f57ed84..7805207eb0 100644 --- a/engines/gargoyle/glk.cpp +++ b/engines/gargoyle/glk.cpp @@ -459,23 +459,31 @@ glui32 Glk::glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *res } frefid_t Glk::glk_fileref_create_temp(glui32 usage, glui32 rock) { - // TODO - return nullptr; + return _files->createTemp(usage, rock); } -frefid_t Glk::glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock) { - // TODO - return nullptr; +frefid_t Glk::glk_fileref_create_by_name(glui32 usage, const char *name, glui32 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 _files->createRef(tempName, usage, rock); } frefid_t Glk::glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock) { - // TODO - return nullptr; + return _files->createByPrompt(usage, fmode, rock); } frefid_t Glk::glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) { - // TODO - return nullptr; + if (!fref) { + warning("fileref_create_from_fileref: invalid ref"); + return nullptr; + } else { + return _files->createFromRef(fref, usage, rock); + } } void Glk::glk_fileref_destroy(frefid_t fref) { @@ -483,22 +491,24 @@ void Glk::glk_fileref_destroy(frefid_t fref) { } frefid_t Glk::glk_fileref_iterate(frefid_t fref, glui32 *rockptr) { - // TODO - return nullptr; + return _files->iterate(fref, rockptr); } glui32 Glk::glk_fileref_get_rock(frefid_t fref) { - // TODO - return 0; + if (!fref) { + warning("fileref_get_rock: invalid ref."); + return 0; + } else { + return fref->_rock; + } } void Glk::glk_fileref_delete_file(frefid_t fref) { - // TODO + fref->deleteFile(); } glui32 Glk::glk_fileref_does_file_exist(frefid_t fref) { - // TODO - return 0; + return fref->exists(); } void Glk::glk_select(event_t *event) { diff --git a/engines/gargoyle/glk.h b/engines/gargoyle/glk.h index 0124cb1b40..ccd2e5b20d 100644 --- a/engines/gargoyle/glk.h +++ b/engines/gargoyle/glk.h @@ -112,16 +112,12 @@ public: glsi32 val); void glk_stylehint_clear(glui32 wintype, glui32 styl, glui32 hint); glui32 glk_style_distinguish(winid_t win, glui32 styl1, glui32 styl2); - glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint, - glui32 *result); + glui32 glk_style_measure(winid_t win, glui32 styl, glui32 hint, glui32 *result); frefid_t glk_fileref_create_temp(glui32 usage, glui32 rock); - frefid_t glk_fileref_create_by_name(glui32 usage, char *name, - glui32 rock); - frefid_t glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, - glui32 rock); - frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, - glui32 rock); + frefid_t glk_fileref_create_by_name(glui32 usage, const char *name, glui32 rock); + frefid_t glk_fileref_create_by_prompt(glui32 usage, FileMode fmode, glui32 rock); + frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock); void glk_fileref_destroy(frefid_t fref); frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr); glui32 glk_fileref_get_rock(frefid_t fref); -- cgit v1.2.3