/* Add it to the global stream list */
glk_data->stream_list = g_list_prepend(glk_data->stream_list, str);
str->stream_list = glk_data->stream_list;
-
- return str;
-}
-/* Internal function: stream closing stuff that is safe to call from either the
- main thread or the Glk thread. */
-void
-trash_stream_thread_independent(ChimaraGlkPrivate *glk_data, strid_t str)
-{
- /* Remove the stream from the global stream list */
- glk_data->stream_list = g_list_delete_link(glk_data->stream_list, str->stream_list);
-
- /* If it was the current output stream, set that to NULL */
- if(glk_data->current_stream == str)
- glk_data->current_stream = NULL;
-
- str->magic = MAGIC_FREE;
- g_free(str);
+ return str;
}
/* Internal function: Stuff to do upon closing any type of stream. Call only
result->writecount = str->write_count;
}
- trash_stream_thread_independent(glk_data, str);
+ /* Remove the stream from the global stream list */
+ glk_data->stream_list = g_list_delete_link(glk_data->stream_list, str->stream_list);
+
+ /* If it was the current output stream, set that to NULL */
+ if(glk_data->current_stream == str)
+ glk_data->current_stream = NULL;
+
+ str->magic = MAGIC_FREE;
+ g_free(str);
}
/**
* @str: A stream.
*
* Retrieves the stream @str's rock value. See <link
- * linkend="chimara-Rocks">Rocks</link>.
+ * linkend="chimara-Rocks">Rocks</link>. Window streams always have rock 0; all
+ * other streams return whatever rock you created them with.
*
* Returns: A rock value.
*/
* equivalent to
* |[
* for (ptr = s; *ptr; ptr++)
- * #glk_put_char(*ptr);
+ * glk_put_char(*ptr);
* ]|
* However, it may be more efficient.
*/
* to:
* |[
* for (i = 0; i < len; i++)
- * #glk_put_char(buf[i]);
+ * glk_put_char(buf[i]);
* ]|
* However, it may be more efficient.
*/
str->file_mode = fmode;
str->type = STREAM_TYPE_MEMORY;
str->mark = 0;
+ str->endmark = 0;
str->unicode = FALSE;
if(buf && buflen)
str->file_mode = fmode;
str->type = STREAM_TYPE_MEMORY;
str->mark = 0;
+ str->endmark = 0;
str->unicode = TRUE;
if(buf && buflen)
{
VALID_FILEREF(fileref, return NULL);
- gchar *modestr;
+ const gchar *modestr;
/* Binary mode is 0x000, text mode 0x100 */
gboolean binary = !(fileref->usage & fileusage_TextMode);
switch(fmode)
ILLEGAL_PARAM("Tried to open a nonexistent file, '%s', in read mode", fileref->filename);
return NULL;
}
- modestr = g_strdup(binary? "rb" : "r");
+ modestr = binary? "rb" : "r";
break;
case filemode_Write:
- modestr = g_strdup(binary? "wb" : "w");
+ modestr = binary? "wb" : "w";
break;
case filemode_WriteAppend:
- modestr = g_strdup(binary? "ab" : "a");
- break;
case filemode_ReadWrite:
- if( g_file_test(fileref->filename, G_FILE_TEST_EXISTS) ) {
- modestr = g_strdup(binary? "r+b" : "r+");
- } else {
- modestr = g_strdup(binary? "w+b" : "w+");
+ {
+ /* We have to open the file first and then close it, in order to
+ both make sure it exists and be able to seek in it later */
+ FILE *fp = g_fopen(fileref->filename, binary? "ab" : "a");
+ if(fclose(fp) != 0) {
+ IO_WARNING( "Error opening file", fileref->filename, g_strerror(errno) );
+ return NULL;
}
+ modestr = binary? "r+b" : "r+";
+ }
break;
default:
ILLEGAL_PARAM("Invalid file mode: %u", fmode);
}
FILE *fp = g_fopen(fileref->filename, modestr);
- g_free(modestr);
if(fp == NULL) {
IO_WARNING( "Error opening file", fileref->filename, g_strerror(errno) );
return NULL;
}
+ /* Fast-forward to the end if we are appending */
+ if(fmode == filemode_WriteAppend && fseek(fp, 0, SEEK_END) != 0) {
+ IO_WARNING("Error fast-forwarding file to end", fileref->filename, g_strerror(errno));
+ return NULL;
+ }
+
/* If they opened a file in write mode but didn't specifically get
permission to do so, complain if the file already exists */
if(fileref->orig_filemode == filemode_Read && fmode != filemode_Read) {
* Opens a stream which reads to or writes from a disk file. If @fmode is
* %filemode_Read, the file must already exist; for the other modes, an empty
* file is created if none exists. If @fmode is %filemode_Write, and the file
- * already exists, it is truncated down to zero length (an empty file). If
- * @fmode is %filemode_WriteAppend, the file mark is set to the end of the
- * file.
+ * already exists, it is truncated down to zero length (an empty file); the
+ * other modes do not truncate. If @fmode is %filemode_WriteAppend, the file
+ * mark is set to the end of the file.
+ *
+ * <note><para>
+ * Note, again, that this doesn't match stdio's fopen() call very well. See
+ * <link linkend="filemode-WriteAppend">the file mode constants</link>.
+ * </para></note>
+ *
+ * If the filemode requires the file to exist, but the file does not exist,
+ * glk_stream_open_file() returns %NULL.
+ *
+ * The file may be read or written in text or binary mode; this is determined
+ * by the @fileref argument. Similarly, platform-dependent attributes such as
+ * file type are determined by @fileref. See <link
+ * linkend="chimara-File-References">File References</link>.
*
* When writing in binary mode, Unicode values (characters greater than 255)
* cannot be written to the file. If you try, they will be stored as 0x3F
return file_stream_new(fileref, fmode, rock, TRUE);
}
+/**
+ * glk_stream_open_resource:
+ * @filenum: Resource chunk number to open.
+ * @rock: The new stream's rock value.
+ *
+ * Open the given data resource for reading (only), as a normal stream.
+ *
+ * <note><para>
+ * Note that there is no notion of file usage — the resource does not
+ * have to be specified as <quote>saved game</quote> or whatever.
+ * </para></note>
+ *
+ * If no resource chunk of the given number exists, the open function returns
+ * %NULL.
+ *
+ * As with file streams, a binary resource stream reads the resource as bytes. A
+ * text resource stream reads characters encoded as Latin-1.
+ *
+ * When reading from a resource stream, newlines are not remapped, even if they
+ * normally would be when reading from a text file on the host OS. If you read a
+ * line (glk_get_line_stream() or glk_get_line_stream_uni()), a Unix newline
+ * (0x0A) terminates the line.
+ *
+ * Returns: the new stream, or %NULL.
+ */
+strid_t
+glk_stream_open_resource(glui32 filenum, glui32 rock)
+{
+ g_warning("Not implemented");
+ return NULL;
+}
+
+/**
+ * glk_stream_open_resource_uni:
+ * @filenum: Resource chunk number to open.
+ * @rock: The new stream's rock value.
+ *
+ * Open the given data resource for reading (only), as a Unicode stream. See
+ * glk_stream_open_resource() for more information.
+ *
+ * As with file streams, a binary resource stream reads the resource as
+ * four-byte (big-endian) words. A text resource stream reads characters encoded
+ * as UTF-8.
+ *
+ * <note><para>
+ * Thus, the difference between text and binary resources is only important
+ * when opened as a Unicode stream.
+ * </para></note>
+ *
+ * Returns: the new stream, or %NULL.
+ */
+strid_t
+glk_stream_open_resource_uni(glui32 filenum, glui32 rock)
+{
+ g_warning("Not implemented");
+ return NULL;
+}
+
/**
* glk_stream_close:
* @str: Stream to close.