2020-06-08 16:04:41 -04:00
|
|
|
/* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2020-06-09 00:06:21 -04:00
|
|
|
#include "gui/filebrowser-dialog.h"
|
|
|
|
|
2020-06-12 12:21:31 -04:00
|
|
|
#include "common/memstream.h"
|
|
|
|
#include "common/savefile.h"
|
|
|
|
|
2020-06-08 16:04:41 -04:00
|
|
|
#include "director/director.h"
|
|
|
|
#include "director/lingo/lingo.h"
|
2020-06-09 23:05:27 -04:00
|
|
|
#include "director/lingo/xlibs/fileio.h"
|
2020-06-08 16:04:41 -04:00
|
|
|
|
|
|
|
namespace Director {
|
|
|
|
|
2020-06-10 18:52:38 +02:00
|
|
|
static const char *xlibName = "FileIO";
|
2020-06-09 23:05:27 -04:00
|
|
|
|
2020-06-08 16:04:41 -04:00
|
|
|
static struct MethodProto {
|
|
|
|
const char *name;
|
|
|
|
void (*func)(int);
|
|
|
|
int minArgs; // -1 -- arglist
|
|
|
|
int maxArgs;
|
2020-06-09 23:05:27 -04:00
|
|
|
int type;
|
2020-06-08 16:04:41 -04:00
|
|
|
int version;
|
2020-06-09 23:05:27 -04:00
|
|
|
} xlibMethods[] = {
|
|
|
|
{ "delete", FileIO::m_delete, 0, 0, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "dispose", FileIO::m_dispose, 0, 0, kXObj, 2 }, // D2
|
|
|
|
{ "fileName", FileIO::m_fileName, 0, 0, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "getLength", FileIO::m_getLength, 0, 0, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "getPosition", FileIO::m_getPosition, 0, 0, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "new", FileIO::m_new, 2, 2, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "readChar", FileIO::m_readChar, 0, 0, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "readLine", FileIO::m_readLine, 0, 0, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "readToken", FileIO::m_readToken, 2, 2, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "readWord", FileIO::m_readWord, 0, 0, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "setPosition", FileIO::m_setPosition, 1, 1, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "writeChar", FileIO::m_writeChar, 1, 1, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ "writeString", FileIO::m_writeString, 1, 1, kXObj | kXtraObj, 2 }, // D2
|
|
|
|
{ 0, 0, 0, 0, 0, 0 }
|
2020-06-08 16:04:41 -04:00
|
|
|
};
|
|
|
|
|
2020-06-09 23:05:27 -04:00
|
|
|
void FileIO::initialize(int type) {
|
|
|
|
if (type & kXObj) {
|
|
|
|
if (!g_lingo->_globalvars.contains(xlibName)) {
|
|
|
|
FileObject *xobj = new FileObject(kXObj);
|
|
|
|
xobj->initMethods();
|
|
|
|
g_lingo->_globalvars[xlibName] = Symbol();
|
|
|
|
g_lingo->_globalvars[xlibName].name = new Common::String(xlibName);
|
|
|
|
g_lingo->_globalvars[xlibName].global = true;
|
|
|
|
g_lingo->_globalvars[xlibName].type = OBJECT;
|
|
|
|
g_lingo->_globalvars[xlibName].u.obj = xobj;
|
|
|
|
} else {
|
|
|
|
warning("FileIO XObject already initialized");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (type & kXtraObj) {
|
|
|
|
// TODO - Implement Xtra
|
2020-06-08 16:04:41 -04:00
|
|
|
}
|
2020-06-09 23:05:27 -04:00
|
|
|
}
|
2020-06-08 16:04:41 -04:00
|
|
|
|
2020-06-09 23:05:27 -04:00
|
|
|
// Initialization/disposal
|
2020-06-08 16:04:41 -04:00
|
|
|
|
2020-06-09 23:05:27 -04:00
|
|
|
void FileObject::initMethods() {
|
|
|
|
for (MethodProto *mtd = xlibMethods; mtd->name; mtd++) {
|
|
|
|
if (mtd->version > g_lingo->_vm->getVersion() || !(type & mtd->type))
|
2020-06-08 16:04:41 -04:00
|
|
|
continue;
|
|
|
|
|
|
|
|
Symbol sym;
|
|
|
|
sym.name = new Common::String(mtd->name);
|
|
|
|
sym.type = FBLTIN;
|
|
|
|
sym.nargs = mtd->minArgs;
|
|
|
|
sym.maxArgs = mtd->maxArgs;
|
2020-06-09 23:05:27 -04:00
|
|
|
sym.targetType = mtd->type;
|
2020-06-08 16:04:41 -04:00
|
|
|
sym.u.bltin = mtd->func;
|
2020-06-09 23:05:27 -04:00
|
|
|
methods[mtd->name] = sym;
|
2020-06-08 16:04:41 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-09 23:05:27 -04:00
|
|
|
Object *FileObject::clone() {
|
|
|
|
FileObject *res = new FileObject(type);
|
2020-06-09 00:06:21 -04:00
|
|
|
res->disposed = disposed;
|
|
|
|
res->prototype = this;
|
|
|
|
res->properties = properties;
|
|
|
|
res->methods = methods;
|
|
|
|
res->inheritanceLevel = inheritanceLevel + 1;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2020-06-09 23:05:27 -04:00
|
|
|
void FileObject::dispose() {
|
2020-06-09 12:26:37 -04:00
|
|
|
disposed = true;
|
|
|
|
|
|
|
|
if (filename) {
|
|
|
|
delete filename;
|
|
|
|
filename = nullptr;
|
|
|
|
}
|
|
|
|
if (inFile) {
|
|
|
|
delete inFile;
|
|
|
|
if (inStream != inFile)
|
|
|
|
delete inStream;
|
|
|
|
inFile = nullptr;
|
|
|
|
inStream = nullptr;
|
|
|
|
}
|
|
|
|
if (outFile) {
|
|
|
|
outFile->write(outStream->getData(), outStream->size());
|
|
|
|
outFile->finalize();
|
|
|
|
delete outFile;
|
|
|
|
delete outStream;
|
|
|
|
outFile = nullptr;
|
|
|
|
outStream = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-12 13:36:27 -04:00
|
|
|
void FileIO::saveFileError() {
|
|
|
|
Common::SaveFileManager *saves = g_system->getSavefileManager();
|
|
|
|
if (saves->getError().getCode()) {
|
|
|
|
warning("SaveFileManager error %d: %s", saves->getError().getCode(), saves->getErrorDesc().c_str());
|
|
|
|
g_lingo->push(Datum(kErrorIO));
|
|
|
|
} else {
|
|
|
|
g_lingo->push(Datum(kErrorFileNotFound));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-08 16:04:41 -04:00
|
|
|
void FileIO::m_new(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 00:06:21 -04:00
|
|
|
|
|
|
|
Datum d2 = g_lingo->pop();
|
|
|
|
Datum d1 = g_lingo->pop();
|
|
|
|
|
2020-06-12 13:36:27 -04:00
|
|
|
Common::SaveFileManager *saves = g_system->getSavefileManager();
|
2020-06-09 00:06:21 -04:00
|
|
|
Common::String option = *d1.u.s;
|
|
|
|
Common::String filename = *d2.u.s;
|
|
|
|
|
|
|
|
if (option.hasPrefix("?")) {
|
|
|
|
option = option.substr(1);
|
2020-06-11 22:01:55 -04:00
|
|
|
GUI::FileBrowserDialog browser(0, "txt", option.equalsIgnoreCase("write") ? GUI::kFBModeSave : GUI::kFBModeLoad);
|
2020-06-09 00:06:21 -04:00
|
|
|
if (browser.runModal() <= 0) {
|
|
|
|
g_lingo->push(Datum(kErrorFileNotFound));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
filename = browser.getResult();
|
2020-06-11 18:34:05 -04:00
|
|
|
} else if (!filename.hasSuffixIgnoreCase(".txt")) {
|
2020-06-11 10:39:43 -04:00
|
|
|
filename += ".txt";
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (option.equalsIgnoreCase("read")) {
|
2020-06-12 13:36:27 -04:00
|
|
|
me->inFile = saves->openForLoading(filename);
|
2020-06-09 12:26:37 -04:00
|
|
|
me->inStream = me->inFile;
|
|
|
|
if (!me->inFile) {
|
2020-06-12 13:36:27 -04:00
|
|
|
saveFileError();
|
2020-06-09 12:26:37 -04:00
|
|
|
delete me;
|
2020-06-09 00:06:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (option.equalsIgnoreCase("write")) {
|
2020-06-09 12:26:37 -04:00
|
|
|
// OutSaveFile is not seekable so create a separate seekable stream
|
|
|
|
// which will be written to the outfile upon disposal
|
2020-06-12 13:36:27 -04:00
|
|
|
me->outFile = saves->openForSaving(filename, false);
|
2020-06-09 12:26:37 -04:00
|
|
|
me->outStream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
|
|
|
|
if (!me->outFile) {
|
2020-06-12 13:36:27 -04:00
|
|
|
saveFileError();
|
2020-06-09 12:26:37 -04:00
|
|
|
delete me;
|
2020-06-09 00:06:21 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (option.equalsIgnoreCase("append")) {
|
2020-06-12 13:36:27 -04:00
|
|
|
Common::InSaveFile *inFile = saves->openForLoading(filename);
|
2020-06-09 13:31:01 -04:00
|
|
|
if (!inFile) {
|
2020-06-12 13:36:27 -04:00
|
|
|
saveFileError();
|
2020-06-09 13:31:01 -04:00
|
|
|
delete me;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
me->outStream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
|
2020-06-11 18:34:33 -04:00
|
|
|
byte b = inFile->readByte();
|
|
|
|
while (!inFile->eos() && !inFile->err()) {
|
|
|
|
me->outStream->writeByte(b);
|
|
|
|
b = inFile->readByte();
|
|
|
|
}
|
|
|
|
delete inFile;
|
2020-06-12 13:36:27 -04:00
|
|
|
me->outFile = saves->openForSaving(filename, false);
|
2020-06-09 13:31:01 -04:00
|
|
|
if (!me->outFile) {
|
2020-06-12 13:36:27 -04:00
|
|
|
saveFileError();
|
2020-06-09 13:31:01 -04:00
|
|
|
delete me;
|
|
|
|
return;
|
|
|
|
}
|
2020-06-09 00:06:21 -04:00
|
|
|
} else {
|
|
|
|
error("Unsupported FileIO option: '%s'", option.c_str());
|
|
|
|
}
|
|
|
|
|
2020-06-09 12:26:37 -04:00
|
|
|
me->filename = new Common::String(filename);
|
|
|
|
|
2020-06-08 16:04:41 -04:00
|
|
|
Datum res;
|
|
|
|
res.type = OBJECT;
|
2020-06-09 00:06:21 -04:00
|
|
|
res.u.obj = me;
|
2020-06-08 16:04:41 -04:00
|
|
|
g_lingo->push(res);
|
|
|
|
}
|
|
|
|
|
2020-06-09 00:06:21 -04:00
|
|
|
void FileIO::m_dispose(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 12:26:37 -04:00
|
|
|
me->dispose();
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Read
|
|
|
|
|
|
|
|
void FileIO::m_readChar(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 12:26:37 -04:00
|
|
|
|
|
|
|
if (!me->inStream || me->inStream->eos() || me->inStream->err()) {
|
|
|
|
g_lingo->push(Datum(kErrorEOF));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ch = me->inStream->readByte();
|
|
|
|
if (me->inStream->eos() || me->inStream->err()) {
|
|
|
|
ch = kErrorEOF;
|
|
|
|
}
|
|
|
|
g_lingo->push(Datum(ch));
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FileIO::m_readLine(int nargs) {
|
2020-06-09 12:26:37 -04:00
|
|
|
// file(mReadLine) is equivalent to file(mReadToken, "", RETURN)
|
|
|
|
// See D4 Using Lingo p. 323
|
2020-06-09 00:06:21 -04:00
|
|
|
|
2020-06-09 12:26:37 -04:00
|
|
|
g_lingo->push(Datum(""));
|
|
|
|
g_lingo->push(Datum("\n"));
|
|
|
|
FileIO::m_readToken(2);
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FileIO::m_readWord(int nargs) {
|
2020-06-09 12:26:37 -04:00
|
|
|
// file(mReadWord) is equivalent to file(mReadToken, " ", " " & RETURN)
|
|
|
|
// See D4 Using Lingo p. 323
|
|
|
|
|
|
|
|
g_lingo->push(Datum(" "));
|
|
|
|
g_lingo->push(Datum(" \n"));
|
|
|
|
FileIO::m_readToken(2);
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FileIO::m_readToken(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 12:26:37 -04:00
|
|
|
|
|
|
|
Datum d2 = g_lingo->pop();
|
|
|
|
Datum d1 = g_lingo->pop();
|
|
|
|
|
|
|
|
Common::String skipString = *d1.u.s;
|
|
|
|
Common::String breakString = *d2.u.s;
|
|
|
|
|
|
|
|
if (!me->inStream || me->inStream->eos() || me->inStream->err()) {
|
|
|
|
g_lingo->push(Datum(""));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::String tok = "";
|
|
|
|
char ch;
|
|
|
|
do {
|
|
|
|
ch = me->inStream->readByte();
|
|
|
|
if (me->inStream->eos() || me->inStream->err()) {
|
|
|
|
g_lingo->push(Datum(tok));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} while (skipString.contains(ch));
|
|
|
|
|
|
|
|
while (!breakString.contains(ch)) {
|
|
|
|
tok += ch;
|
|
|
|
ch = me->inStream->readByte();
|
|
|
|
|
|
|
|
if (me->inStream->eos() || me->inStream->err()) {
|
|
|
|
g_lingo->push(Datum(tok));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Include the break character when the skipString is empty
|
|
|
|
if (skipString.size() == 0) {
|
|
|
|
tok += ch;
|
|
|
|
} else {
|
|
|
|
me->inStream->seek(-1, SEEK_CUR);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_lingo->push(Datum(tok));
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write
|
|
|
|
|
|
|
|
void FileIO::m_writeChar(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 12:26:37 -04:00
|
|
|
Datum d = g_lingo->pop();
|
|
|
|
|
|
|
|
if (!me->outStream) {
|
|
|
|
g_lingo->push(Datum(kErrorReadOnly));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
me->outStream->writeByte(d.asInt());
|
|
|
|
g_lingo->push(Datum(kErrorNone));
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FileIO::m_writeString(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 00:06:21 -04:00
|
|
|
Datum d = g_lingo->pop();
|
|
|
|
|
2020-06-09 12:26:37 -04:00
|
|
|
if (!me->outStream) {
|
2020-06-09 00:06:21 -04:00
|
|
|
g_lingo->push(Datum(kErrorReadOnly));
|
2020-06-09 12:26:37 -04:00
|
|
|
return;
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
2020-06-09 12:26:37 -04:00
|
|
|
|
|
|
|
me->outStream->writeString(d.asString());
|
|
|
|
g_lingo->push(Datum(kErrorNone));
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Other
|
|
|
|
|
|
|
|
void FileIO::m_getPosition(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 12:26:37 -04:00
|
|
|
|
|
|
|
if (me->inStream) {
|
|
|
|
g_lingo->push(Datum(me->inStream->pos()));
|
|
|
|
} else if (me->outStream) {
|
|
|
|
g_lingo->push(Datum(me->outStream->pos()));
|
|
|
|
} else {
|
|
|
|
warning("FileIO: No file open");
|
|
|
|
g_lingo->push(Datum(kErrorFileNotOpen));
|
|
|
|
}
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FileIO::m_setPosition(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 12:26:37 -04:00
|
|
|
Datum d = g_lingo->pop();
|
|
|
|
int pos = d.asInt();
|
|
|
|
|
|
|
|
if (me->inStream) {
|
|
|
|
if (pos <= me->inStream->size()) {
|
|
|
|
me->inStream->seek(pos, SEEK_SET);
|
|
|
|
g_lingo->push(Datum(kErrorNone));
|
|
|
|
} else {
|
|
|
|
me->inStream->seek(me->inStream->size(), SEEK_SET);
|
|
|
|
g_lingo->push(Datum(kErrorInvalidPos));
|
|
|
|
}
|
|
|
|
} else if (me->outStream) {
|
|
|
|
if (pos <= me->outStream->size()) {
|
|
|
|
me->outStream->seek(pos, SEEK_SET);
|
|
|
|
g_lingo->push(Datum(kErrorNone));
|
|
|
|
} else {
|
|
|
|
me->outStream->seek(me->outStream->size(), SEEK_SET);
|
|
|
|
g_lingo->push(Datum(kErrorInvalidPos));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
warning("FileIO: No file open");
|
|
|
|
g_lingo->push(Datum(kErrorFileNotOpen));
|
|
|
|
}
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FileIO::m_getLength(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 12:26:37 -04:00
|
|
|
|
|
|
|
if (me->inStream) {
|
|
|
|
g_lingo->push(Datum(me->inStream->size()));
|
|
|
|
} else if (me->outStream) {
|
|
|
|
g_lingo->push(Datum(me->outStream->size()));
|
|
|
|
} else {
|
|
|
|
warning("FileIO: No file open");
|
|
|
|
g_lingo->push(Datum(kErrorFileNotOpen));
|
|
|
|
}
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FileIO::m_fileName(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 12:26:37 -04:00
|
|
|
|
|
|
|
if (me->filename) {
|
|
|
|
g_lingo->push(Datum(*me->filename));
|
|
|
|
} else {
|
|
|
|
warning("FileIO: No file open");
|
|
|
|
g_lingo->push(Datum(kErrorFileNotOpen));
|
|
|
|
}
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FileIO::m_delete(int nargs) {
|
2020-06-09 23:05:27 -04:00
|
|
|
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMeObj);
|
2020-06-09 12:26:37 -04:00
|
|
|
|
|
|
|
if (me->filename) {
|
|
|
|
Common::String filename = *me->filename;
|
|
|
|
me->dispose();
|
|
|
|
if (g_system->getSavefileManager()->removeSavefile(filename)) {
|
|
|
|
g_lingo->push(Datum(kErrorNone));
|
|
|
|
} else {
|
|
|
|
g_lingo->push(Datum(kErrorIO));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
warning("FileIO: No file open");
|
|
|
|
g_lingo->push(Datum(kErrorFileNotOpen));
|
|
|
|
}
|
2020-06-09 00:06:21 -04:00
|
|
|
}
|
|
|
|
|
2020-06-08 16:04:41 -04:00
|
|
|
} // End of namespace Director
|