The Types of File References

The Types of File References — Four different ways to create a file reference

Functions

Includes

#include <libchimara/glk.h>

Description

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.

Functions

glk_fileref_create_temp ()

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.

Parameters

usage

Bitfield with one or more of the fileusage_ constants.

 

rock

The new fileref's rock value.

 

Returns

A new fileref, or NULL if the fileref creation failed.


glk_fileref_create_by_prompt ()

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:

filemode_Read

The file must already exist; and the player will be asked to select from existing files which match the usage.

filemode_Write

The file should not exist; if the player selects an existing file, he will be warned that it will be replaced.

filemode_ReadWrite

The file may or may not exist; if it already exists, the player will be warned that it will be modified.

filemode_WriteAppend

Same behavior as filemode_ReadWrite.

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.

Parameters

usage

Bitfield with one or more of the fileusage_ constants.

 

fmode

File mode, contolling the dialog's behavior.

 

rock

The new fileref's rock value.

 

Returns

A new fileref, or NULL if the fileref creation failed or the dialog was canceled.


glk_fileref_create_by_name ()

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.

Parameters

usage

Bitfield with one or more of the fileusage_ constants.

 

name

A filename.

 

rock

The new fileref's rock value.

 

Returns

A new fileref, or NULL if the fileref creation failed.


glk_fileref_create_from_fileref ()

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.

Parameters

usage

Bitfield with one or more of the fileusage_ constants.

 

fref

Fileref to copy.

 

rock

The new fileref's rock value.

 

Returns

A new fileref, or NULL if the fileref creation failed.