X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=libchimara%2Fstream.c;h=f6abec64885e4718783485df6a72e14efd9d185d;hb=cbd4cb7f8c62b2ba51329a4cb082a96115a7529d;hp=aa27a39cf5ca5d8047ede38f072d0eb05b048bc1;hpb=6478a4f44526dde5ec7b1090d97b2255ed2879a1;p=rodin%2Fchimara.git diff --git a/libchimara/stream.c b/libchimara/stream.c index aa27a39..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); } @@ -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); } @@ -199,6 +244,7 @@ glk_put_string_uni(glui32 *s) 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); } @@ -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; } @@ -268,11 +325,21 @@ 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; } @@ -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; @@ -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); -}