Top |
The Types of File ReferencesThe Types of File References — Four different ways to create a file reference |
There are four different functions for creating a fileref, depending on how
you wish to specify it. Remember that it is always possible that a fileref
creation will fail and return NULL
.
frefid_t glk_fileref_create_temp (glui32 usage
,glui32 rock
);
Creates a reference to a temporary file. It is always a new file (one which does not yet exist). The file (once created) will be somewhere out of the player's way.
This is why no name is specified; the player will never need to know it.
A temporary file should never be used for long-term storage. It may be deleted automatically when the program exits, or at some later time, say when the machine is turned off or rebooted. You do not have to worry about deleting it yourself.
frefid_t glk_fileref_create_by_prompt (glui32 usage
,glui32 fmode
,glui32 rock
);
Creates a reference to a file by asking the player to locate it. The library may simply prompt the player to type a name, or may use a platform-native file navigation tool. (The prompt, if any, is inferred from the usage argument.)
Chimara
Chimara uses a GtkFileChooserDialog. The default starting location for the dialog may be set with
glkunix_set_base_file()
.
fmode
must be one of these values:
The file must already exist; and the player will be asked to select from existing files which match the usage. |
|
The file should not exist; if the player selects an existing file, he will be warned that it will be replaced. |
|
The file may or may not exist; if it already exists, the player will be warned that it will be modified. |
|
Same behavior as |
The fmode
argument should generally match the fmode
which will be used to
open the file.
It is likely that the prompt or file tool will have a “cancel” option.
If the player chooses this, glk_fileref_create_by_prompt()
will return
NULL
.
This is a major reason why you should make sure the return value is valid
before you use it.
The recommended file suffixes for files are .glkdata
for fileusage_Data
,
.glksave
for fileusage_SavedGame
, .txt
for fileusage_Transcript
and
fileusage_InputRecord
.
frefid_t glk_fileref_create_by_name (glui32 usage
,char *name
,glui32 rock
);
This creates a reference to a file with a specific name. The file will be in a fixed location relevant to your program, and visible to the player.
This usually means “in the same directory as your program.”
Chimara
In Chimara, the file is created in the directory last set by
glkunix_set_base_file()
, and otherwise in the current working directory.
Earlier versions of the Glk spec specified that the library may have to extend, truncate, or change your name argument in order to produce a legal native filename. This remains true. However, since Glk was originally proposed, the world has largely reached consensus about what a filename looks like. Therefore, it is worth including some recommended library behavior here. Libraries that share this behavior will more easily be able to exchange files, which may be valuable both to authors (distributing data files for games) and for players (moving data between different computers or different applications).
The library should take the given filename argument, and delete any
characters illegal for a filename. This will include all of the following
characters (and more, if the OS requires it): slash, backslash, angle
brackets (less-than and greater-than), colon, double-quote, pipe (vertical
bar), question-mark, asterisk. The library should also truncate the argument
at the first period (delete the first period and any following characters).
If the result is the empty string, change it to the string "null"
.
It should then append an appropriate suffix, depending on the usage:
.glkdata
for fileusage_Data
, .glksave
for fileusage_SavedGame
, .txt
for fileusage_Transcript
and fileusage_InputRecord
.
The above behavior is not a requirement of the Glk spec. Older implementations can continue doing what they do. Some programs (e.g. web-based interpreters) may not have access to a traditional filesystem at all, and to them these recommendations will be meaningless.
On the other side of the coin, the game file should not press these limitations. Best practice is for the game to pass a filename containing only letters and digits, beginning with a letter, and not mixing upper and lower case. Avoid overly-long filenames.
The earlier Glk spec gave more stringent recommendations: “No more than 8 characters, consisting entirely of upper-case letters and numbers, starting with a letter”. The DOS era is safely contained, if not over, so this has been relaxed. The I7 manual recommends “23 characters or fewer”.
To address other complications:
Some filesystems are case-insensitive. If you create two filerefs with
the names File
and FILE
, they
may wind up pointing to the same file, or they may not. Avoid doing
this.
Some programs will look for all files in the same directory as the
program itself (or, for interpreted games, in the same directory as the
game file). Others may keep files in a data-specific directory
appropriate for the user (e.g., ~/Library
on MacOS).
If a game interpreter uses a data-specific directory, there is a question of whether to use a common location, or divide it into game-specific subdirectories. (Or to put it another way: should the namespace of named files be per-game or app-wide?) Since data files may be exchanged between games, they should be given an app-wide namespace. In contrast, saved games should be per-game, as they can never be exchanged. Transcripts and input records can go either way.
When updating an older library to follow these recommendations, consider backwards compatibility for games already installed. When opening an existing file (that is, not in a write-only mode) it may be worth looking under the older name (suffix) if the newer one does not already exist.
Game-save files are already stored with a variety of file suffixes, since that usage goes back to the oldest IF interpreters, long predating Glk. It is reasonable to treat them in some special way, while hewing closer to these recommendations for data files.
frefid_t glk_fileref_create_from_fileref (glui32 usage
,frefid_t fref
,glui32 rock
);
This copies an existing file reference fref
, but changes the usage. (The
original fileref is not modified.)
The use of this function can be tricky. If you change the type of the fileref
(fileusage_Data
, fileusage_SavedGame
, etc), the new reference may or may
not point to the same actual disk file.
Most platforms use suffixes to indicate file type, so it typically will not. See the earlier comments about recommended file suffixes.
If you do this, and open both file references for writing, the results are unpredictable. It is safest to change the type of a fileref only if it refers to a nonexistent file.
If you change the mode of a fileref (fileusage_TextMode
,
fileusage_BinaryMode
), but leave the rest of the type unchanged, the new
fileref will definitely point to the same disk file as the old one.
Obviously, if you write to a file in text mode and then read from it in binary mode, the results are platform-dependent.