aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/tads/os_frob_tads.cpp
diff options
context:
space:
mode:
authorPaul Gilbert2019-05-18 13:26:57 -1000
committerPaul Gilbert2019-05-24 18:21:06 -0700
commit3d9e03af554814bee10f112c2efa0b7f0b722489 (patch)
treef174c8004d0c554dae124df63d874f78d2e88e5d /engines/glk/tads/os_frob_tads.cpp
parentfcb2592ec24f983c49f1e2e1b4f41cc9659a9229 (diff)
downloadscummvm-rg350-3d9e03af554814bee10f112c2efa0b7f0b722489.tar.gz
scummvm-rg350-3d9e03af554814bee10f112c2efa0b7f0b722489.tar.bz2
scummvm-rg350-3d9e03af554814bee10f112c2efa0b7f0b722489.zip
GLK: TADS2: Soooo much more implementation
Diffstat (limited to 'engines/glk/tads/os_frob_tads.cpp')
-rw-r--r--engines/glk/tads/os_frob_tads.cpp476
1 files changed, 476 insertions, 0 deletions
diff --git a/engines/glk/tads/os_frob_tads.cpp b/engines/glk/tads/os_frob_tads.cpp
new file mode 100644
index 0000000000..8c8d3f10c0
--- /dev/null
+++ b/engines/glk/tads/os_frob_tads.cpp
@@ -0,0 +1,476 @@
+/* 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.
+ *
+ */
+
+#include "glk/tads/os_frob_tads.h"
+#include "common/file.h"
+#include "common/memstream.h"
+
+namespace Glk {
+namespace TADS {
+
+static osfildef *openForReading(const char *fname) {
+ Common::File f;
+ if (f.open(fname))
+ return f.readStream(f.size());
+
+ Common::InSaveFile *save = g_system->getSavefileManager()->openForLoading(fname);
+ return save;
+}
+
+static osfildef *openForWriting(const char *fname) {
+ return g_system->getSavefileManager()->openForSaving(fname, false);
+}
+
+int osfacc(const char *fname) {
+ return Common::File::exists(fname) ? 1 : 0;
+}
+
+osfildef *osfoprt(const char *fname, os_filetype_t typ) {
+ return openForReading(fname);
+}
+
+osfildef *osfoprtv(const char *fname, os_filetype_t typ) {
+ return openForReading(fname);
+}
+
+osfildef *osfopwt(const char *fname, os_filetype_t typ) {
+ return openForWriting(fname);
+}
+
+osfildef *osfoprwt(const char *fname, os_filetype_t typ) {
+ warning("ScummVM files can't be opened for both reading and writing simultaneously");
+ return openForWriting(fname);
+}
+
+osfildef *osfoprwtt(const char *fname, os_filetype_t typ) {
+ warning("ScummVM files can't be opened for both reading and writing simultaneously");
+ return openForWriting(fname);
+}
+
+osfildef *osfopwb(const char *fname, os_filetype_t typ) {
+ return openForWriting(fname);
+}
+
+osfildef *osfoprs(const char *fname, os_filetype_t typ) {
+ return openForReading(fname);
+}
+
+osfildef *osfoprb(const char *fname, os_filetype_t typ) {
+ return openForReading(fname);
+}
+
+osfildef *osfoprbv(const char *fname, os_filetype_t typ) {
+ return openForReading(fname);
+}
+
+osfildef *osfoprwb(const char *fname, os_filetype_t typ) {
+ warning("ScummVM files can't be opened for both reading and writing simultaneously");
+ return openForWriting(fname);
+}
+
+osfildef *osfoprwtb(const char *fname, os_filetype_t typ) {
+ warning("ScummVM files can't be opened for both reading and writing simultaneously");
+ return openForWriting(fname);
+}
+
+osfildef *osfdup(osfildef *orig, const char *mode) {
+ Common::SeekableReadStream *rs = dynamic_cast<Common::SeekableReadStream *>(orig);
+ int32 currPos = rs->pos();
+
+ rs->seek(0);
+ osfildef *result = rs->readStream(rs->size());
+ rs->seek(currPos);
+
+ return result;
+}
+
+void os_settype(const char *f, os_filetype_t typ) {
+ // No implementation
+}
+
+char *osfgets(char *buf, size_t count, osfildef *fp) {
+ Common::ReadStream *rs = dynamic_cast<Common::ReadStream *>(fp);
+ char *ptr = buf;
+ char c;
+ while (!rs->eos() && --count > 0) {
+ c = rs->readByte();
+ if (c == '\n' || c == '\0')
+ break;
+ *ptr++ = c;
+ }
+
+ *ptr++ = '\0';
+ return buf;
+}
+
+int osfputs(const char *str, osfildef *fp) {
+ return dynamic_cast<Common::WriteStream *>(fp)->write(str, strlen(str)) == strlen(str) ? 0 : -1;
+}
+
+void os_fprintz(osfildef *fp, const char *str) {
+ dynamic_cast<Common::WriteStream *>(fp)->write(str, strlen(str));
+}
+
+void os_fprint(osfildef *fp, const char *str, size_t len) {
+ Common::String s(str, str + MIN(len, strlen(str)));
+ dynamic_cast<Common::WriteStream *>(fp)->write(s.c_str(), s.size());
+}
+
+int osfwb(osfildef *fp, const void *buf, size_t bufl) {
+ return dynamic_cast<Common::WriteStream *>(fp)->write(buf, bufl) == bufl ? 0 : 1;
+}
+
+int osfflush(osfildef *fp) {
+ return dynamic_cast<Common::WriteStream *>(fp)->flush() ? 0 : 1;
+}
+
+int osfgetc(osfildef *fp) {
+ return dynamic_cast<Common::ReadStream *>(fp)->readByte();
+}
+
+int osfrb(osfildef *fp, void *buf, size_t bufl) {
+ return dynamic_cast<Common::ReadStream *>(fp)->read(buf, bufl) == bufl ? 0 : 1;
+}
+
+size_t osfrbc(osfildef *fp, void *buf, size_t bufl) {
+ return dynamic_cast<Common::ReadStream *>(fp)->read(buf, bufl);
+}
+
+long osfpos(osfildef *fp) {
+ return dynamic_cast<Common::SeekableReadStream *>(fp)->pos();
+}
+
+int osfseek(osfildef *fp, long pos, int mode) {
+ return dynamic_cast<Common::SeekableReadStream *>(fp)->seek(pos, mode);
+}
+
+void osfcls(osfildef *fp) {
+ delete fp;
+}
+
+int osfdel(const char *fname) {
+ return g_system->getSavefileManager()->removeSavefile(fname) ? 0 : 1;
+}
+
+int os_rename_file(const char *oldname, const char *newname) {
+ return g_system->getSavefileManager()->renameSavefile(oldname, newname);
+}
+
+
+bool os_locate(const char *fname, int flen, const char *arg0, char *buf, size_t bufsiz) {
+ Common::String name = !flen ? Common::String(fname) : Common::String(fname, fname + flen);
+
+ if (!Common::File::exists(fname))
+ return false;
+
+ strncpy(buf, name.c_str(), bufsiz - 1);
+ buf[bufsiz - 1] = '\0';
+ return true;
+}
+
+osfildef *os_create_tempfile(const char *fname, char *buf) {
+ strcpy(buf, "tmpfile");
+ return new Common::MemoryReadWriteStream(DisposeAfterUse::YES);
+}
+
+int osfdel_temp(const char *fname) {
+ // Temporary files in ScummVM are just memory streams, so there isn't a file to delete
+ return 0;
+}
+
+void os_get_tmp_path(char *buf) {
+ strcpy(buf, "");
+}
+
+int os_gen_temp_filename(char *buf, size_t buflen) {
+ error("TODO: If results from this are being passed to file open methods, will need to do further work");
+}
+
+/* ------------------------------------------------------------------------ */
+
+void os_set_pwd(const char *dir) {
+ // No implementation
+}
+
+void os_set_pwd_file(const char *filename) {
+ // No implementation
+}
+
+bool os_mkdir(const char *dir, int create_parents) {
+ // Unsupported
+ return false;
+}
+
+bool os_rmdir(const char *dir) {
+ // Unsupported
+ return false;
+}
+
+/* ------------------------------------------------------------------------ */
+
+void os_defext(char *fname, const char *ext) {
+ if (!strchr(fname, '.'))
+ strcat(fname, ext);
+}
+
+void os_addext(char *fname, const char *ext) {
+ strcat(fname, ext);
+}
+
+void os_remext(char *fname) {
+ char *p = strchr(fname, '.');
+ if (p)
+ *p = '\0';
+}
+
+bool os_file_names_equal(const char *a, const char *b) {
+ return !strcmp(a, b);
+}
+
+const char *os_get_root_name(const char *buf) {
+ return buf;
+}
+
+bool os_is_file_absolute(const char *fname) {
+ return false;
+}
+
+void os_get_path_name(char *pathbuf, size_t pathbuflen, const char *fname) {
+ strcpy(pathbuf, "");
+}
+
+void os_build_full_path(char *fullpathbuf, size_t fullpathbuflen,
+ const char *path, const char *filename) {
+ strcpy(fullpathbuf, filename);
+}
+
+void os_combine_paths(char *fullpathbuf, size_t pathbuflen,
+ const char *path, const char *filename) {
+ strcpy(fullpathbuf, filename);
+}
+
+bool os_get_abs_filename(char *result_buf, size_t result_buf_size,
+ const char *filename) {
+ strcpy(result_buf, filename);
+ return true;
+}
+
+bool os_get_rel_path(char *result_buf, size_t result_buf_size,
+ const char *basepath, const char *filename) {
+ strcpy(result_buf, filename);
+ return true;
+}
+
+bool os_is_file_in_dir(const char *filename, const char *path,
+ bool include_subdirs, bool match_self) {
+ assert(!include_subdirs && !match_self);
+
+ return Common::File::exists(filename);
+}
+
+
+
+/* ------------------------------------------------------------------------ */
+/*
+* Convert an OS filename path to URL-style format. This isn't a true URL
+* conversion; rather, it simply expresses a filename in Unix-style
+* notation, as a series of path elements separated by '/' characters.
+* Unlike true URLs, we don't use % encoding or a scheme prefix (file://,
+* etc).
+*
+* The result path never ends in a trailing '/', unless the entire result
+* path is "/". This is for consistency; even if the source path ends with
+* a local path separator, the result doesn't.
+*
+* If the local file system syntax uses '/' characters as ordinary filename
+* characters, these must be replaced with some other suitable character in
+* the result, since otherwise they'd be taken as path separators when the
+* URL is parsed. If possible, the substitution should be reversible with
+* respect to os_cvt_dir_url(), so that the same URL read back in on this
+* same platform will produce the same original filename. One particular
+* suggestion is that if the local system uses '/' to delimit what would be
+* a filename extension on other platforms, replace '/' with '.', since
+* this will provide reversibility as well as a good mapping if the URL is
+* read back in on another platform.
+*
+* The local equivalents of "." and "..", if they exist, are converted to
+* "." and ".." in the URL notation.
+*
+* Examples:
+*
+*. Windows: images\rooms\startroom.jpg -> images/rooms/startroom.jpg
+*. Windows: ..\startroom.jpg -> ../startroom.jpg
+*. Mac: :images:rooms:startroom.jpg -> images/rooms/startroom.jpg
+*. Mac: ::startroom.jpg -> ../startroom.jpg
+*. VMS: [.images.rooms]startroom.jpg -> images/rooms/startroom.jpg
+*. VMS: [-.images]startroom.jpg -> ../images/startroom.jpg
+*. Unix: images/rooms/startroom.jpg -> images/rooms/startroom.jpg
+*. Unix: ../images/startroom.jpg -> ../images/startroom.jpg
+*
+* If the local name is an absolute path in the local file system (e.g.,
+* Unix /file, Windows C:\file), translate as follows. If the local
+* operating system uses a volume or device designator (Windows C:, VMS
+* SYS$DISK:, etc), make the first element of the path the exact local
+* syntax for the device designator: /C:/ on Windows, /SYS$DISK:/ on VMS,
+* etc. Include the local syntax for the device prefix. For a system like
+* Unix with a unified file system root ("/"), simply start with the root
+* directory. Examples:
+*
+*. Windows: C:\games\deep.gam -> /C:/games/deep.gam
+*. Windows: C:games\deep.gam -> /C:./games/deep.gam
+*. Windows: \\SERVER\DISK\games\deep.gam -> /\\SERVER/DISK/games/deep.gam
+*. Mac OS 9: Hard Disk:games:deep.gam -> /Hard Disk:/games/deep.gam
+*. VMS: SYS$DISK:[games]deep.gam -> /SYS$DISK:/games/deep.gam
+*. Unix: /games/deep.gam -> /games/deep.gam
+*
+* Rationale: it's effectively impossible to create a truly portable
+* representation of an absolute path. Operating systems are too different
+* in the way they represent root paths, and even if that were solvable, a
+* root path is essentially unusable across machines anyway because it
+* creates a dependency on the contents of a particular machine's disk. So
+* if we're called upon to translate an absolute path, we can forget about
+* trying to be truly portable and instead focus on round-trip fidelity -
+* i.e., making sure that applying os_cvt_url_dir() to our result recovers
+* the exact original path, assuming it's done on the same operating
+* system. The approach outlined above should achieve round-trip fidelity
+* when a local path is converted to a URL and back on the same machine,
+* since the local URL-to-path converter should recognize its own special
+* type of local absolute path prefix. It also produces reasonable results
+* on other platforms - see the os_cvt_url_dir() comments below for
+* examples of the decoding results for absolute paths moved to new
+* platforms. The result when a device-rooted absolute path is encoded on
+* one machine and then decoded on another will generally be a local path
+* with a root on the default device/volume and an outermost directory with
+* a name based on the original machine's device/volume name. This
+* obviously won't reproduce the exact original path, but since that's
+* impossible anyway, this is probably as good an approximation as we can
+* create.
+*
+* Character sets: the input could be in local or UTF-8 character sets.
+* The implementation shouldn't care, though - just treat bytes in the
+* range 0-127 as plain ASCII, and everything else as opaque. I.e., do not
+* quote or otherwise modify characters outside the 0-127 range.
+*/
+void os_cvt_dir_url(char *result_buf, size_t result_buf_size,
+ const char *src_path);
+
+/*
+* Convert a URL-style path into a filename path expressed in the local
+* file system's syntax. Fills in result_buf with a file path, constructed
+* using the local file system syntax, that corresponds to the path in
+* src_url expressed in URL-style syntax. Examples:
+*
+* images/rooms/startroom.jpg ->
+*. Windows -> images\rooms\startroom.jpg
+*. Mac OS 9 -> :images:rooms:startroom.jpg
+*. VMS -> [.images.rooms]startroom.jpg
+*
+* The source format isn't a true URL; it's simply a series of path
+* elements separated by '/' characters. Unlike true URLs, our input
+* format doesn't use % encoding and doesn't have a scheme (file://, etc).
+* (Any % in the source is treated as an ordinary character and left as-is,
+* even if it looks like a %XX sequence. Anything that looks like a scheme
+* prefix is left as-is, with any // treated as path separators.
+*
+* images/file%20name.jpg ->
+*. Windows -> images\file%20name.jpg
+*
+* file://images/file.jpg ->
+*. Windows -> file_\\images\file.jpg
+*
+* Any characters in the path that are invalid in the local file system
+* naming rules are converted to "_", unless "_" is itself invalid, in
+* which case they're converted to "X". One exception is that if '/' is a
+* valid local filename character (rather than a path separator as it is on
+* Unix and Windows), it can be used as the replacement for the character
+* that os_cvt_dir_url uses as its replacement for '/', so that this
+* substitution is reversible when a URL is generated and then read back in
+* on this same platform.
+*
+* images/file:name.jpg ->
+*. Windows -> images\file_name.jpg
+*. Mac OS 9 -> :images:file_name.jpg
+*. Unix -> images/file:name.jpg
+*
+* The path elements "." and ".." are specifically defined as having their
+* Unix meanings: "." is an alias for the preceding path element, or the
+* working directory if it's the first element, and ".." is an alias for
+* the parent of the preceding element. When these appear as path
+* elements, this routine translates them to the appropriate local
+* conventions. "." may be translated simply by removing it from the path,
+* since it reiterates the previous path element. ".." may be translated
+* by removing the previous element - HOWEVER, if ".." appears as the first
+* element, it has to be retained and translated to the equivalent local
+* notation, since it will have to be applied later, when the result_buf
+* path is actually used to open a file, at which point it will combined
+* with the working directory or another base path.
+*
+*. /images/../file.jpg -> [Windows] file.jpg
+*. ../images/file.jpg ->
+*. Windows -> ..\images\file.jpg
+*. Mac OS 9 -> ::images:file.jpg
+*. VMS -> [-.images]file.jpg
+*
+* If the URL path is absolute (starts with a '/'), the routine inspects
+* the path to see if it was created by the same OS, according to the local
+* rules for converting absolute paths in os_cvt_dir_url() (see). If so,
+* we reverse the encoding done there. If it doesn't appear that the name
+* was created by the same operating system - that is, if reversing the
+* encoding doesn't produce a valid local filename - then we create a local
+* absolute path as follows. If the local system uses device/volume
+* designators, we start with the current working device/volume or some
+* other suitable default volume. We then add the first element of the
+* path, if any, as the root directory name, applying the usual "_" or "X"
+* substitution for any characters that aren't allowed in local names. The
+* rest of the path is handled in the usual fashion.
+*
+*. /images/file.jpg ->
+*. Windows -> \images\file.jpg
+*. Unix -> /images/file.jpg
+*
+*. /c:/images/file.jpg ->
+*. Windows -> c:\images\file.jpg
+*. Unix -> /c:/images/file.jpg
+*. VMS -> SYS$DISK:[c__.images]file.jpg
+*
+*. /Hard Disk:/images/file.jpg ->
+*. Windows -> \Hard Disk_\images\file.jpg
+*. Unix -> SYS$DISK:[Hard_Disk_.images]file.jpg
+*
+* Note how the device/volume prefix becomes the top-level directory when
+* moving a path across machines. It's simply not possible to reconstruct
+* the exact original path in such cases, since device/volume syntax rules
+* have little in common across systems. But this seems like a good
+* approximation in that (a) it produces a valid local path, and (b) it
+* gives the user a reasonable basis for creating a set of folders to mimic
+* the original source system, if they want to use that approach to port
+* the data rather than just changing the paths internally in the source
+* material.
+*
+* Character sets: use the same rules as for os_cvt_dir_url().
+*/
+void os_cvt_url_dir(char *result_buf, size_t result_buf_size,
+ const char *src_url);
+
+
+} // End of namespace TADS
+} // End of namespace Glk