X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=src%2Fstrio.c;h=27807246ec54297b7aa3f64888a1ebea1159f7e0;hb=5292406311d31682a850baf059cab01a6f0262b2;hp=3db5e3e3ca6f85351794a6badb05399302a34b00;hpb=9576479a013cce9694bb2e4e045162baed1c2470;p=rodin%2Fchimara.git diff --git a/src/strio.c b/src/strio.c index 3db5e3e..2780724 100644 --- a/src/strio.c +++ b/src/strio.c @@ -4,8 +4,6 @@ #include #include -#define min(x,y) ( (x > y)? y : x ) - /* * **************** WRITING FUNCTIONS ******************************************** @@ -15,8 +13,12 @@ /* Internal function: change illegal (control) characters in a string to a placeholder character. Must free returned string afterwards. */ static gchar * -remove_latin1_control_characters(unsigned char *s, gssize len) +remove_latin1_control_characters(unsigned char *s, gsize len) { + /* If len == 0, then return an empty string, not NULL */ + if(len == 0) + return g_strdup(""); + gchar *retval = g_new0(gchar, len); int i; for(i = 0; i < len; i++) @@ -33,7 +35,7 @@ remove_latin1_control_characters(unsigned char *s, gssize len) Latin-1 control characters by a placeholder first. The UTF-8 string must be freed afterwards. Returns NULL on error. */ static gchar * -convert_latin1_to_utf8(gchar *s, gssize len) +convert_latin1_to_utf8(gchar *s, gsize len) { GError *error = NULL; gchar *utf8; @@ -55,23 +57,26 @@ convert_latin1_to_utf8(gchar *s, gssize len) static void write_utf8_to_window(winid_t win, gchar *s) { - GtkTextBuffer *buffer = - gtk_text_view_get_buffer( GTK_TEXT_VIEW(win->widget) ); + gdk_threads_enter(); + + GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(win->widget) ); GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert(buffer, &iter, s, -1); + + gdk_threads_leave(); } -/* Internal function: write a UTF-8 buffer with length to a stream. */ +/* Internal function: write a Latin-1 buffer with length to a stream. */ static void write_buffer_to_stream(strid_t str, gchar *buf, glui32 len) { - switch(str->stream_type) + switch(str->type) { case STREAM_TYPE_WINDOW: /* Each window type has a different way of printing to it */ - switch(str->window->window_type) + switch(str->window->type) { /* Printing to these windows' streams does nothing */ case wintype_Blank: @@ -83,14 +88,16 @@ write_buffer_to_stream(strid_t str, gchar *buf, glui32 len) case wintype_TextBuffer: { gchar *utf8 = convert_latin1_to_utf8(buf, len); - write_utf8_to_window(str->window, utf8); - g_free(utf8); + if(utf8) + { + write_utf8_to_window(str->window, utf8); + g_free(utf8); + } } str->write_count += len; break; default: - g_warning("%s: Writing to this kind of window unsupported.", - __func__); + g_warning("%s: Writing to this kind of window unsupported.", __func__); } /* Now write the same buffer to the window's echo stream */ @@ -104,12 +111,13 @@ write_buffer_to_stream(strid_t str, gchar *buf, glui32 len) { int foo = 0; while(str->mark < str->buflen && foo < len) - str->ubuffer[str->mark++] = (glui32)buf[foo++]; + str->ubuffer[str->mark++] = (unsigned char)buf[foo++]; } if(!str->unicode && str->buffer) { - memmove(str->buffer + str->mark, buf, - min(len, str->buflen - str->mark)); + int copycount = MIN(len, str->buflen - str->mark); + memmove(str->buffer + str->mark, buf, copycount); + str->mark += copycount; } str->write_count += len; @@ -143,8 +151,7 @@ write_buffer_to_stream(strid_t str, gchar *buf, glui32 len) str->write_count += len; break; default: - g_warning("%s: Writing to this kind of stream unsupported.", - __func__); + g_warning("%s: Writing to this kind of stream unsupported.", __func__); } } @@ -235,7 +242,7 @@ read_utf8_char_from_file(FILE *fp) if(ch == EOF) return -1; readbuffer[foo] = (gchar)ch; - charresult = g_utf8_get_char_validated(readbuffer, foo); + charresult = g_utf8_get_char_validated(readbuffer, foo + 1); /* charresult is -1 if invalid, -2 if incomplete, and the unicode code point otherwise */ } @@ -287,10 +294,9 @@ glsi32 glk_get_char_stream(strid_t str) { g_return_val_if_fail(str != NULL, -1); - g_return_val_if_fail(str->file_mode == filemode_Read - || str->file_mode == filemode_ReadWrite, -1); + g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, -1); - switch(str->stream_type) + switch(str->type) { case STREAM_TYPE_MEMORY: if(str->unicode) @@ -342,8 +348,7 @@ glk_get_char_stream(strid_t str) return (ch > 0xFF)? 0x3F : ch; } default: - g_warning("%s: Reading from this kind of stream unsupported.", - __func__); + g_warning("%s: Reading from this kind of stream unsupported.", __func__); return -1; } } @@ -363,19 +368,17 @@ glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len) { g_return_val_if_fail(str != NULL, 0); - g_return_val_if_fail(str->file_mode == filemode_Read - || str->file_mode == filemode_ReadWrite, 0); + g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, 0); g_return_val_if_fail(buf != NULL, 0); - switch(str->stream_type) + switch(str->type) { case STREAM_TYPE_MEMORY: { int copycount = 0; if(str->unicode) { - while(copycount < len && str->ubuffer - && str->mark < str->buflen) + while(copycount < len && str->ubuffer && str->mark < str->buflen) { glui32 ch = str->ubuffer[str->mark++]; buf[copycount++] = (ch > 0xFF)? '?' : (char)ch; @@ -384,8 +387,9 @@ glk_get_buffer_stream(strid_t str, char *buf, glui32 len) else { if(str->buffer) /* if not, copycount stays 0 */ - copycount = min(len, str->buflen - str->mark); + copycount = MIN(len, str->buflen - str->mark); memmove(buf, str->buffer + str->mark, copycount); + str->mark += copycount; } str->read_count += copycount; @@ -398,14 +402,12 @@ glk_get_buffer_stream(strid_t str, char *buf, glui32 len) { /* Read len characters of 4 bytes each */ unsigned char *readbuffer = g_new0(unsigned char, 4 * len); - size_t count = fread(readbuffer, sizeof(unsigned char), - 4 * len, str->file_pointer); + size_t count = fread(readbuffer, sizeof(unsigned char), 4 * len, str->file_pointer); /* If there was an incomplete character */ if(count % 4 != 0) { count -= count % 4; - g_warning("%s: Incomplete character in binary Unicode " - "file.", __func__); + g_warning("%s: Incomplete character in binary Unicode file.", __func__); } str->read_count += count / 4; @@ -423,8 +425,7 @@ glk_get_buffer_stream(strid_t str, char *buf, glui32 len) } else /* Regular binary file */ { - size_t count = fread(buf, sizeof(char), len, - str->file_pointer); + size_t count = fread(buf, sizeof(char), len, str->file_pointer); str->read_count += count; return count; } @@ -444,8 +445,7 @@ glk_get_buffer_stream(strid_t str, char *buf, glui32 len) return foo; } default: - g_warning("%s: Reading from this kind of stream unsupported.", - __func__); + g_warning("%s: Reading from this kind of stream unsupported.", __func__); return 0; } } @@ -471,11 +471,10 @@ glui32 glk_get_line_stream(strid_t str, char *buf, glui32 len) { g_return_val_if_fail(str != NULL, 0); - g_return_val_if_fail(str->file_mode == filemode_Read - || str->file_mode == filemode_ReadWrite, 0); + g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, 0); g_return_val_if_fail(buf != NULL, 0); - switch(str->stream_type) + switch(str->type) { case STREAM_TYPE_MEMORY: { @@ -483,14 +482,12 @@ glk_get_line_stream(strid_t str, char *buf, glui32 len) if(str->unicode) { /* Do it character-by-character */ - while(copycount < len - 1 && str->ubuffer - && str->mark < str->buflen) + while(copycount < len - 1 && str->ubuffer && str->mark < str->buflen) { glui32 ch = str->ubuffer[str->mark++]; /* Check for Unicode newline; slightly different than in file streams */ - if(ch == 0x0A || ch == 0x85 || ch == 0x0C || ch == 0x2028 - || ch == 0x2029) + if(ch == 0x0A || ch == 0x85 || ch == 0x0C || ch == 0x2028 || ch == 0x2029) { buf[copycount++] = '\n'; break; @@ -509,8 +506,12 @@ glk_get_line_stream(strid_t str, char *buf, glui32 len) else { if(str->buffer) /* if not, copycount stays 0 */ - copycount = min(len, str->buflen - str->mark); - memccpy(buf, str->buffer + str->mark, '\n', copycount); + copycount = MIN(len - 1, str->buflen - str->mark); + char *endptr = memccpy(buf, str->buffer + str->mark, '\n', copycount); + if(endptr) /* newline was found */ + copycount = endptr - buf; /* Real copy count */ + buf[copycount] = '\0'; + str->mark += copycount; } str->read_count += copycount; @@ -525,8 +526,7 @@ glk_get_line_stream(strid_t str, char *buf, glui32 len) int foo; for(foo = 0; foo < len - 1; foo++) { - glsi32 ch = - read_ucs4be_char_from_file(str->file_pointer); + glsi32 ch = read_ucs4be_char_from_file(str->file_pointer); if(ch == -1) { buf[foo] = '\0'; @@ -576,8 +576,7 @@ glk_get_line_stream(strid_t str, char *buf, glui32 len) return foo; } default: - g_warning("%s: Reading from this kind of stream unsupported.", - __func__); + g_warning("%s: Reading from this kind of stream unsupported.", __func__); return 0; } } @@ -613,7 +612,7 @@ glk_stream_get_position(strid_t str) { g_return_val_if_fail(str != NULL, 0); - switch(str->stream_type) + switch(str->type) { case STREAM_TYPE_MEMORY: return str->mark; @@ -665,7 +664,7 @@ glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) g_return_if_fail(!(seekmode == seekmode_Start && pos < 0)); g_return_if_fail(!(seekmode == seekmode_End || pos > 0)); - switch(str->stream_type) + switch(str->type) { case STREAM_TYPE_MEMORY: switch(seekmode) @@ -694,8 +693,7 @@ glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) break; } default: - g_warning("%s: Seeking not supported on this type of stream.", - __func__); + g_warning("%s: Seeking not supported on this type of stream.", __func__); return; } }