X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=libchimara%2Fstream.c;h=f9a6cf5bf4cea649c405ff7382dc8a5767276707;hb=cbb35cca2d0a87a664e5d72fe71dce45c3030823;hp=afc55be96eb4f0a7b95fffa3283fe63931cb0975;hpb=1589fbfcd406df40d8da4f078dad3327c4862871;p=projects%2Fchimara%2Fchimara.git diff --git a/libchimara/stream.c b/libchimara/stream.c index afc55be..f9a6cf5 100644 --- a/libchimara/stream.c +++ b/libchimara/stream.c @@ -24,7 +24,7 @@ stream_new_common(glui32 rock) /* 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; } @@ -103,7 +103,8 @@ glk_stream_iterate(strid_t str, glui32 *rockptr) * @str: A stream. * * Retrieves the stream @str's rock value. See Rocks. + * linkend="chimara-Rocks">Rocks. Window streams always have rock 0; all + * other streams return whatever rock you created them with. * * Returns: A rock value. */ @@ -192,7 +193,7 @@ glk_put_char_uni(glui32 ch) * equivalent to * |[ * for (ptr = s; *ptr; ptr++) - * #glk_put_char(*ptr); + * glk_put_char(*ptr); * ]| * However, it may be more efficient. */ @@ -229,7 +230,7 @@ glk_put_string_uni(glui32 *s) * to: * |[ * for (i = 0; i < len; i++) - * #glk_put_char(buf[i]); + * glk_put_char(buf[i]); * ]| * However, it may be more efficient. */ @@ -283,6 +284,7 @@ glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock) str->file_mode = fmode; str->type = STREAM_TYPE_MEMORY; str->mark = 0; + str->endmark = 0; str->unicode = FALSE; if(buf && buflen) @@ -321,6 +323,7 @@ glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, glui32 fmode, glui32 rock str->file_mode = fmode; str->type = STREAM_TYPE_MEMORY; str->mark = 0; + str->endmark = 0; str->unicode = TRUE; if(buf && buflen) @@ -341,7 +344,7 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) { 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) @@ -351,20 +354,23 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) 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); @@ -372,12 +378,17 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) } 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) { @@ -421,9 +432,22 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) * 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, again, that this doesn't match stdio's fopen() call very well. See + * the file mode constants. + * + * + * 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 File References. * * 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 @@ -464,6 +488,64 @@ glk_stream_open_file_uni(frefid_t fileref, glui32 fmode, glui32 rock) 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 that there is no notion of file usage — the resource does not + * have to be specified as saved game or whatever. + * + * + * 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. + * + * + * Thus, the difference between text and binary resources is only important + * when opened as a Unicode stream. + * + * + * 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.