Wrote behavior of Backspace key during line input in text grid windows.
[rodin/chimara.git] / src / strio.c
index de6ccb48f5ed9057cb15dd5606078b7b527a1a77..974a1099b79f0f1005a4e75f95245e2c08e69f55 100644 (file)
@@ -4,8 +4,6 @@
 #include <glib.h>
 #include <glib/gstdio.h>
 
-#define min(x,y) ( (x > y)? y : x )
-
 /*
  *
  **************** WRITING FUNCTIONS ********************************************
@@ -48,21 +46,62 @@ convert_latin1_to_utf8(gchar *s, gsize len)
        
        if(utf8 == NULL)
        {
-               error_dialog(NULL, error, "Error during latin1->utf8 conversion: ");
+               g_warning("Error during latin1->utf8 conversion: %s", error->message);
                return NULL;
        }
        
        return utf8;
 }
 
-/* Internal function: write a UTF-8 string to a window's text buffer. */
+/* Internal function: write a UTF-8 string to a text grid window's text buffer. */
+static void
+write_utf8_to_grid(winid_t win, gchar *s)
+{
+    /* Number of characters to insert */
+    glong length = g_utf8_strlen(s, -1);
+    glong chars_left = length;
+    
+    gdk_threads_enter();
+    
+    GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(win->widget) );
+    GtkTextMark *cursor = gtk_text_buffer_get_mark(buffer, "cursor_position");
+    
+    /* Get cursor position */
+    GtkTextIter start;
+    gtk_text_buffer_get_iter_at_mark(buffer, &start, cursor);
+    /* Spaces available on this line */
+    gint available_space = win->width - gtk_text_iter_get_line_offset(&start);
+    
+    while(chars_left > available_space && !gtk_text_iter_is_end(&start))
+    {
+        GtkTextIter end = start;
+        gtk_text_iter_forward_to_line_end(&end);
+        gtk_text_buffer_delete(buffer, &start, &end);
+        gtk_text_buffer_insert(buffer, &start, s + (length - chars_left), available_space);
+        chars_left -= available_space;
+        gtk_text_iter_forward_line(&start);
+        available_space = win->width;
+    }
+    if(!gtk_text_iter_is_end(&start))
+    {
+        GtkTextIter end = start;
+        gtk_text_iter_forward_chars(&end, chars_left);
+        gtk_text_buffer_delete(buffer, &start, &end);
+        gtk_text_buffer_insert(buffer, &start, s + (length - chars_left), -1);
+    }
+    
+    gtk_text_buffer_move_mark(buffer, cursor, &start);
+    
+    gdk_threads_leave();
+}
+
+/* Internal function: write a UTF-8 string to a text buffer window's text buffer. */
 static void
 write_utf8_to_window(winid_t win, gchar *s)
 {
        gdk_threads_enter();
 
-       GtkTextBuffer *buffer = 
-               gtk_text_view_get_buffer( GTK_TEXT_VIEW(win->widget) );
+       GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(win->widget) );
 
        GtkTextIter iter;
        gtk_text_buffer_get_end_iter(buffer, &iter);
@@ -71,15 +110,15 @@ write_utf8_to_window(winid_t win, gchar *s)
        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:
@@ -87,6 +126,21 @@ write_buffer_to_stream(strid_t str, gchar *buf, glui32 len)
                                case wintype_Graphics:
                                        str->write_count += len;
                                        break;
+                                       
+                           /* Text grid window */
+                           case wintype_TextGrid:
+                           {
+                               gchar *utf8 = convert_latin1_to_utf8(buf, len);
+                               if(utf8)
+                               {
+                                   /* FIXME: What to do if string contains \n? Split the input string at newlines and write each string separately? */
+                                   write_utf8_to_grid(str->window, utf8);
+                                   g_free(utf8);
+                               }
+                           }
+                               str->write_count += len;
+                               break;
+                                       
                                /* Text buffer window */        
                                case wintype_TextBuffer:
                                {
@@ -100,8 +154,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 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 */
@@ -119,7 +172,7 @@ write_buffer_to_stream(strid_t str, gchar *buf, glui32 len)
                        }
                        if(!str->unicode && str->buffer)
                        {
-                               int copycount = min(len, str->buflen - str->mark);
+                               int copycount = MIN(len, str->buflen - str->mark);
                                memmove(str->buffer + str->mark, buf, copycount);
                                str->mark += copycount;
                        }
@@ -155,8 +208,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__);
        }
 }
 
@@ -299,10 +351,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)
@@ -354,8 +405,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;
        }
 }
@@ -375,19 +425,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;
@@ -396,7 +444,7 @@ 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;
                        }
@@ -411,14 +459,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;
@@ -436,8 +482,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;
                                }
@@ -457,8 +502,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;
        }
 }
@@ -484,11 +528,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:
                {
@@ -496,14 +539,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;
@@ -522,9 +563,8 @@ glk_get_line_stream(strid_t str, char *buf, glui32 len)
                        else
                        {
                                if(str->buffer) /* if not, copycount stays 0 */
-                                       copycount = min(len - 1, str->buflen - str->mark);
-                               char *endptr = 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';
@@ -543,8 +583,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';
@@ -594,8 +633,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;
        }
 }
@@ -631,7 +669,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;
@@ -683,7 +721,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)
@@ -712,8 +750,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;
        }
 }