X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=libchimara%2Fstream.c;h=f6abec64885e4718783485df6a72e14efd9d185d;hb=cbd4cb7f8c62b2ba51329a4cb082a96115a7529d;hp=804399213ae7cbe87ebcbb96134130d5d4d51dd6;hpb=0b85f1dd5993e2ed111ec2ba13bbbb4ebda06ada;p=rodin%2Fchimara.git diff --git a/libchimara/stream.c b/libchimara/stream.c index 8043992..f6abec6 100644 --- a/libchimara/stream.c +++ b/libchimara/stream.c @@ -7,17 +7,19 @@ #include #include "chimara-glk-private.h" -extern ChimaraGlkPrivate *glk_data; +extern GPrivate *glk_data_key; /* Internal function: create a stream with a specified rock value */ -static strid_t -stream_new_common(glui32 rock, glui32 fmode, enum StreamType type) +strid_t +stream_new_common(glui32 rock) { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); + strid_t str = g_new0(struct glk_stream_struct, 1); str->magic = MAGIC_STREAM; str->rock = rock; - str->file_mode = fmode; - str->type = type; + if(glk_data->register_obj) + str->disprock = (*glk_data->register_obj)(str, gidisp_Class_Stream); /* Add it to the global stream list */ glk_data->stream_list = g_list_prepend(glk_data->stream_list, str); @@ -26,15 +28,50 @@ stream_new_common(glui32 rock, glui32 fmode, enum StreamType type) return str; } -/* Internal function: create a window stream to go with window. */ -strid_t -window_stream_new(winid_t window) +/* 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) { - /* Create stream and connect it to window */ - strid_t str = stream_new_common(0, filemode_Write, STREAM_TYPE_WINDOW); - str->window = window; - str->style = "normal"; - return 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); +} + +/* Internal function: Stuff to do upon closing any type of stream. Call only + from Glk thread. */ +void +stream_close_common(strid_t str, stream_result_t *result) +{ + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); + + if(glk_data->unregister_obj) + { + (*glk_data->unregister_obj)(str, gidisp_Class_Stream, str->disprock); + str->disprock.ptr = NULL; + } + + /* If the stream was one or more windows' echo streams, set those to NULL */ + winid_t win; + for(win = glk_window_iterate(NULL, NULL); win; + win = glk_window_iterate(win, NULL)) + if(win->echo_stream == str) + win->echo_stream = NULL; + + /* Return the character counts */ + if(result) + { + result->readcount = str->read_count; + result->writecount = str->write_count; + } + + trash_stream_thread_independent(glk_data, str); } /** @@ -52,7 +89,8 @@ strid_t glk_stream_iterate(strid_t str, glui32 *rockptr) { VALID_STREAM_OR_NULL(str, return NULL); - + + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); GList *retnode; if(str == NULL) @@ -96,6 +134,8 @@ void glk_stream_set_current(strid_t str) { VALID_STREAM_OR_NULL(str, return); + + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); if(str != NULL && str->file_mode == filemode_Read) { @@ -116,6 +156,7 @@ glk_stream_set_current(strid_t str) strid_t glk_stream_get_current() { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); return glk_data->current_stream; } @@ -130,6 +171,7 @@ glk_stream_get_current() void glk_put_char(unsigned char ch) { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); VALID_STREAM(glk_data->current_stream, return); glk_put_char_stream(glk_data->current_stream, ch); } @@ -145,6 +187,7 @@ glk_put_char(unsigned char ch) void glk_put_char_uni(glui32 ch) { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); VALID_STREAM(glk_data->current_stream, return); glk_put_char_stream_uni(glk_data->current_stream, ch); } @@ -156,7 +199,7 @@ glk_put_char_uni(glui32 ch) * Prints a null-terminated string to the current stream. It is exactly * equivalent to * |[ - * for (ptr = @s; *ptr; ptr++) + * for (ptr = s; *ptr; ptr++) * #glk_put_char(*ptr); * ]| * However, it may be more efficient. @@ -164,6 +207,7 @@ glk_put_char_uni(glui32 ch) void glk_put_string(char *s) { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); VALID_STREAM(glk_data->current_stream, return); glk_put_string_stream(glk_data->current_stream, s); } @@ -179,6 +223,7 @@ glk_put_string(char *s) void glk_put_string_uni(glui32 *s) { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); VALID_STREAM(glk_data->current_stream, return); glk_put_string_stream_uni(glk_data->current_stream, s); } @@ -191,14 +236,15 @@ glk_put_string_uni(glui32 *s) * Prints a block of characters to the current stream. It is exactly equivalent * to: * |[ - * for (i = 0; i < @len; i++) - * #glk_put_char(@buf[i]); + * for (i = 0; i < len; i++) + * #glk_put_char(buf[i]); * ]| * However, it may be more efficient. */ void glk_put_buffer(char *buf, glui32 len) { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); VALID_STREAM(glk_data->current_stream, return); glk_put_buffer_stream(glk_data->current_stream, buf, len); } @@ -214,6 +260,7 @@ glk_put_buffer(char *buf, glui32 len) void glk_put_buffer_uni(glui32 *buf, glui32 len) { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); VALID_STREAM(glk_data->current_stream, return); glk_put_buffer_stream_uni(glk_data->current_stream, buf, len); } @@ -223,7 +270,7 @@ glk_put_buffer_uni(glui32 *buf, glui32 len) * @buf: An allocated buffer, or %NULL. * @buflen: Length of @buf. * @fmode: Mode in which the buffer will be opened. Must be one of - * #filemode_Read, #filemode_Write, or #filemode_ReadWrite. + * %filemode_Read, %filemode_Write, or %filemode_ReadWrite. * @rock: The new stream's rock value. * * Opens a stream which reads from or writes to a space in memory. @buf points @@ -240,11 +287,21 @@ glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock) { g_return_val_if_fail(fmode != filemode_WriteAppend, NULL); - strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_MEMORY); - str->buffer = buf; + strid_t str = stream_new_common(rock); + str->file_mode = fmode; + str->type = STREAM_TYPE_MEMORY; str->mark = 0; - str->buflen = buflen; str->unicode = FALSE; + + if(buf && buflen) + { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); + str->buffer = buf; + str->buflen = buflen; + if(glk_data->register_arr) + str->buffer_rock = (*glk_data->register_arr)(buf, buflen, "&+#!Cn"); + } + return str; } @@ -253,7 +310,7 @@ glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock) * @buf: An allocated buffer, or %NULL. * @buflen: Length of @buf. * @fmode: Mode in which the buffer will be opened. Must be one of - * #filemode_Read, #filemode_Write, or #filemode_ReadWrite. + * %filemode_Read, %filemode_Write, or %filemode_ReadWrite. * @rock: The new stream's rock value. * * Works just like glk_stream_open_memory(), except that the buffer is an array @@ -268,16 +325,26 @@ glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, glui32 fmode, glui32 rock { g_return_val_if_fail(fmode != filemode_WriteAppend, NULL); - strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_MEMORY); - str->ubuffer = buf; + strid_t str = stream_new_common(rock); + str->file_mode = fmode; + str->type = STREAM_TYPE_MEMORY; str->mark = 0; - str->buflen = buflen; str->unicode = TRUE; + + if(buf && buflen) + { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); + str->ubuffer = buf; + str->buflen = buflen; + if(glk_data->register_arr) + str->buffer_rock = (*glk_data->register_arr)(buf, buflen, "&+#!Iu"); + } + return str; } /* Internal function: create a stream using the given parameters. */ -static strid_t +strid_t file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) { VALID_FILEREF(fileref, return NULL); @@ -339,7 +406,9 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) } } - strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_FILE); + strid_t str = stream_new_common(rock); + str->file_mode = fmode; + str->type = STREAM_TYPE_FILE; str->file_pointer = fp; str->binary = binary; str->unicode = unicode; @@ -353,15 +422,15 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) /** * glk_stream_open_file: * @fileref: Indicates the file which will be opened. - * @fmode: Mode in which the file will be opened. Can be any of #filemode_Read, - * #filemode_Write, #filemode_WriteAppend, or #filemode_ReadWrite. + * @fmode: Mode in which the file will be opened. Can be any of %filemode_Read, + * %filemode_Write, %filemode_WriteAppend, or %filemode_ReadWrite. * @rock: The new stream's rock value. * * 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 + * %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 + * @fmode is %filemode_WriteAppend, the file mark is set to the end of the * file. * * When writing in binary mode, Unicode values (characters greater than 255) @@ -381,8 +450,8 @@ glk_stream_open_file(frefid_t fileref, glui32 fmode, glui32 rock) /** * glk_stream_open_file_uni: * @fileref: Indicates the file which will be opened. - * @fmode: Mode in which the file will be opened. Can be any of #filemode_Read, - * #filemode_Write, #filemode_WriteAppend, or #filemode_ReadWrite. + * @fmode: Mode in which the file will be opened. Can be any of %filemode_Read, + * %filemode_Write, %filemode_WriteAppend, or %filemode_ReadWrite. * @rock: The new stream's rock value. * * This works just like glk_stream_open_file(), except that in binary mode, @@ -432,9 +501,18 @@ glk_stream_close(strid_t str, stream_result_t *result) return; case STREAM_TYPE_MEMORY: - /* Do nothing */ + { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); + if(glk_data->unregister_arr) + { + if(str->unicode) + (*glk_data->unregister_arr)(str->ubuffer, str->buflen, "&+#!Iu", str->buffer_rock); + else + (*glk_data->unregister_arr)(str->buffer, str->buflen, "&+#!Cn", str->buffer_rock); + } + } break; - + case STREAM_TYPE_FILE: if(fclose(str->file_pointer) != 0) IO_WARNING( "Failed to close file", str->filename, g_strerror(errno) ); @@ -447,32 +525,3 @@ glk_stream_close(strid_t str, stream_result_t *result) stream_close_common(str, result); } - -/* Internal function: Stuff to do upon closing any type of stream. */ -void -stream_close_common(strid_t str, stream_result_t *result) -{ - /* 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; - - /* If it was one or more windows' echo streams, set those to NULL */ - winid_t win; - for(win = glk_window_iterate(NULL, NULL); win; - win = glk_window_iterate(win, NULL)) - if(win->echo_stream == str) - win->echo_stream = NULL; - - /* Return the character counts */ - if(result) - { - result->readcount = str->read_count; - result->writecount = str->write_count; - } - - str->magic = MAGIC_FREE; - g_free(str); -}