Wrote platform-dependent dispatch code
authorPhilip Chimento <philip.chimento@gmail.com>
Wed, 7 Oct 2009 20:45:17 +0000 (20:45 +0000)
committerPhilip Chimento <philip.chimento@gmail.com>
Wed, 7 Oct 2009 20:45:17 +0000 (20:45 +0000)
git-svn-id: http://lassie.dyndns-server.com/svn/gargoyle-gtk@130 ddfedd41-794f-dd11-ae45-00112f111e67

libchimara/Makefile.am
libchimara/chimara-glk-private.h
libchimara/dispatch.c [new file with mode: 0644]
libchimara/fileref.c
libchimara/fileref.h
libchimara/input.c
libchimara/stream.c
libchimara/stream.h
libchimara/window.c
libchimara/window.h

index ba1e1d8d9fae46a8fb68ab1ed64723e0e9f1f44a..64e6ebc5b7286331ed45a71f41a12934f7937c22 100644 (file)
@@ -9,6 +9,7 @@ libchimara_la_SOURCES = \
        case.c \
        charset.c charset.h \
        chimara-glk.c chimara-glk.h chimara-glk-private.h \
        case.c \
        charset.c charset.h \
        chimara-glk.c chimara-glk.h chimara-glk-private.h \
+       dispatch.c \
        event.c event.h \
        fileref.c fileref.h \
        garglk.c garglk.h \
        event.c event.h \
        fileref.c fileref.h \
        garglk.c garglk.h \
index 25417d368524d95c18533cd5b783c1d5fa767611..4a274fba227b7939dbefb78bb6b3960b9e950924 100644 (file)
@@ -6,6 +6,7 @@
 #include <pango/pango.h>
 #include "glk.h"
 #include "gi_blorb.h"
 #include <pango/pango.h>
 #include "glk.h"
 #include "gi_blorb.h"
+#include "gi_dispa.h"
 #include "chimara-glk.h"
 
 G_BEGIN_DECLS
 #include "chimara-glk.h"
 
 G_BEGIN_DECLS
@@ -68,6 +69,11 @@ struct _ChimaraGlkPrivate {
        giblorb_map_t *resource_map;
        /* File stream pointing to the blorb used as current resource map */
        strid_t resource_file;
        giblorb_map_t *resource_map;
        /* File stream pointing to the blorb used as current resource map */
        strid_t resource_file;
+       /* Callbacks for registering and unregistering dispatch objects */
+       gidispatch_rock_t (*register_obj)(void *, glui32);
+       void (*unregister_obj)(void *, glui32, gidispatch_rock_t);
+       gidispatch_rock_t (*register_arr)(void *, glui32, char *);
+       void (*unregister_arr)(void *, glui32, char *, gidispatch_rock_t);
 
        /* *** Platform-dependent Glk library data *** */
        /* Flag for functions to find out if they are being called from startup code */
 
        /* *** Platform-dependent Glk library data *** */
        /* Flag for functions to find out if they are being called from startup code */
diff --git a/libchimara/dispatch.c b/libchimara/dispatch.c
new file mode 100644 (file)
index 0000000..b1f84da
--- /dev/null
@@ -0,0 +1,58 @@
+#include <libchimara/glk.h>
+#include "chimara-glk-private.h"
+#include "window.h"
+#include "stream.h"
+#include "fileref.h"
+
+extern GPrivate *glk_data_key;
+
+void 
+gidispatch_set_object_registry(gidispatch_rock_t (*regi)(void *obj, glui32 objclass), void (*unregi)(void *obj, glui32 objclass, gidispatch_rock_t objrock))
+{
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       winid_t win;
+    strid_t str;
+    frefid_t fref;
+    
+    glk_data->register_obj = regi;
+    glk_data->unregister_obj = unregi;
+    
+    if(glk_data->register_obj) 
+       {
+        /* It's now necessary to go through all existing objects, and register them. */
+        for(win = glk_window_iterate(NULL, NULL); win; win = glk_window_iterate(win, NULL))
+            win->disprock = (*glk_data->register_obj)(win, gidisp_Class_Window);
+        for(str = glk_stream_iterate(NULL, NULL); str; str = glk_stream_iterate(str, NULL))
+            str->disprock = (*glk_data->register_obj)(str, gidisp_Class_Stream);
+        for(fref = glk_fileref_iterate(NULL, NULL); fref; fref = glk_fileref_iterate(fref, NULL))
+            fref->disprock = (*glk_data->register_obj)(fref, gidisp_Class_Fileref);
+    }
+}
+
+gidispatch_rock_t 
+gidispatch_get_objrock(void *obj, glui32 objclass)
+{
+       switch(objclass) 
+       {
+               case gidisp_Class_Window:
+                       return ((winid_t)obj)->disprock;
+               case gidisp_Class_Stream:
+                       return ((strid_t)obj)->disprock;
+               case gidisp_Class_Fileref:
+                       return ((frefid_t)obj)->disprock;
+               default: 
+               {
+                       gidispatch_rock_t dummy;
+                       dummy.num = 0;
+                       return dummy;
+               }
+       }
+}
+
+void 
+gidispatch_set_retained_registry(gidispatch_rock_t (*regi)(void *array, glui32 len, char *typecode), void (*unregi)(void *array, glui32 len, char *typecode, gidispatch_rock_t objrock))
+{
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       glk_data->register_arr = regi;
+       glk_data->unregister_arr = unregi;
+}
index 97c6e487bb62a02c79b4af9c8665a50f220b9edd..937933cedd914badf737bfba208d9d4d94151331 100644 (file)
@@ -6,9 +6,55 @@
 #include "fileref.h"
 #include "magic.h"
 #include "chimara-glk-private.h"
 #include "fileref.h"
 #include "magic.h"
 #include "chimara-glk-private.h"
+#include "gi_dispa.h"
 
 extern GPrivate *glk_data_key;
 
 
 extern GPrivate *glk_data_key;
 
+/* Internal function: create a fileref using the given parameters. */
+frefid_t
+fileref_new(gchar *filename, glui32 rock, glui32 usage, glui32 orig_filemode)
+{
+       g_return_val_if_fail(filename != NULL, NULL);
+
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       
+       frefid_t f = g_new0(struct glk_fileref_struct, 1);
+       f->magic = MAGIC_FILEREF;
+       f->rock = rock;
+       if(glk_data->register_obj)
+               f->disprock = (*glk_data->register_obj)(f, gidisp_Class_Fileref);
+       
+       f->filename = g_strdup(filename);
+       f->usage = usage;
+       f->orig_filemode = orig_filemode;
+       
+       /* Add it to the global fileref list */
+       glk_data->fileref_list = g_list_prepend(glk_data->fileref_list, f);
+       f->fileref_list = glk_data->fileref_list;
+       
+       return f;
+}
+
+static void
+fileref_close_common(frefid_t fref)
+{
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       
+       glk_data->fileref_list = g_list_delete_link(glk_data->fileref_list, fref->fileref_list);
+
+       if(glk_data->unregister_obj)
+       {
+               (*glk_data->unregister_obj)(fref, gidisp_Class_Fileref, fref->disprock);
+               fref->disprock.ptr = NULL;
+       }
+       
+       if(fref->filename)
+               g_free(fref->filename);
+       
+       fref->magic = MAGIC_FREE;
+       g_free(fref);
+}
+
 /**
  * glk_fileref_iterate:
  * @fref: A file reference, or %NULL.
 /**
  * glk_fileref_iterate:
  * @fref: A file reference, or %NULL.
@@ -57,28 +103,6 @@ glk_fileref_get_rock(frefid_t fref)
        return fref->rock;
 }
 
        return fref->rock;
 }
 
-/* Internal function: create a fileref using the given parameters. */
-frefid_t
-fileref_new(gchar *filename, glui32 rock, glui32 usage, glui32 orig_filemode)
-{
-       g_return_val_if_fail(filename != NULL, NULL);
-
-       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
-       
-       frefid_t f = g_new0(struct glk_fileref_struct, 1);
-       f->magic = MAGIC_FILEREF;
-       f->rock = rock;
-       f->filename = g_strdup(filename);
-       f->usage = usage;
-       f->orig_filemode = orig_filemode;
-       
-       /* Add it to the global fileref list */
-       glk_data->fileref_list = g_list_prepend(glk_data->fileref_list, f);
-       f->fileref_list = glk_data->fileref_list;
-       
-       return f;
-}
-
 /**
  * glk_fileref_create_temp:
  * @usage: Bitfield with one or more of the <code>fileusage_</code> constants.
 /**
  * glk_fileref_create_temp:
  * @usage: Bitfield with one or more of the <code>fileusage_</code> constants.
@@ -200,8 +224,7 @@ glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock)
                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                NULL);
                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                NULL);
-                       gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser),
-                               GTK_FILE_CHOOSER_ACTION_OPEN);
+                       gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser), GTK_FILE_CHOOSER_ACTION_OPEN);
                        break;
                case filemode_Write:
                        chooser = gtk_file_chooser_dialog_new("Select a file to save to", NULL,
                        break;
                case filemode_Write:
                        chooser = gtk_file_chooser_dialog_new("Select a file to save to", NULL,
@@ -209,10 +232,8 @@ glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock)
                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                NULL);
                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                NULL);
-                       gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser),
-                               GTK_FILE_CHOOSER_ACTION_SAVE);
-                       gtk_file_chooser_set_do_overwrite_confirmation(
-                               GTK_FILE_CHOOSER(chooser), TRUE);
+                       gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser), GTK_FILE_CHOOSER_ACTION_SAVE);
+                       gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(chooser), TRUE);
                        break;
                case filemode_ReadWrite:
                case filemode_WriteAppend:
                        break;
                case filemode_ReadWrite:
                case filemode_WriteAppend:
@@ -221,8 +242,7 @@ glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock)
                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                NULL);
                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                NULL);
-                       gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser),
-                               GTK_FILE_CHOOSER_ACTION_SAVE);
+                       gtk_file_chooser_set_action(GTK_FILE_CHOOSER(chooser), GTK_FILE_CHOOSER_ACTION_SAVE);
                        break;
                default:
                        ILLEGAL_PARAM("Unknown file mode: %u", fmode);
                        break;
                default:
                        ILLEGAL_PARAM("Unknown file mode: %u", fmode);
@@ -239,8 +259,7 @@ glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock)
                gdk_threads_leave();
                return NULL;
        }
                gdk_threads_leave();
                return NULL;
        }
-       gchar *filename = 
-               gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(chooser) );
+       gchar *filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(chooser) );
        frefid_t f = fileref_new(filename, rock, usage, fmode);
        g_free(filename);
        gtk_widget_destroy(chooser);
        frefid_t f = fileref_new(filename, rock, usage, fmode);
        g_free(filename);
        gtk_widget_destroy(chooser);
@@ -380,15 +399,7 @@ void
 glk_fileref_destroy(frefid_t fref)
 {
        VALID_FILEREF(fref, return);
 glk_fileref_destroy(frefid_t fref)
 {
        VALID_FILEREF(fref, return);
-
-       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
-       
-       glk_data->fileref_list = g_list_delete_link(glk_data->fileref_list, fref->fileref_list);
-       if(fref->filename)
-               g_free(fref->filename);
-       
-       fref->magic = MAGIC_FREE;
-       g_free(fref);
+       fileref_close_common(fref);
 }
 
 /**
 }
 
 /**
index 9dd8e50f5a0e180f2b96931c016695a6fc36294e..c2d8f4666b2124e94f860804a8f96dac3e39a982 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <gtk/gtk.h>
 #include "glk.h"
 
 #include <gtk/gtk.h>
 #include "glk.h"
+#include "gi_dispa.h"
 
 /**
  * glk_fileref_struct:
 
 /**
  * glk_fileref_struct:
@@ -14,6 +15,7 @@ struct glk_fileref_struct
 {
        /*< private >*/
        glui32 magic, rock;
 {
        /*< private >*/
        glui32 magic, rock;
+       gidispatch_rock_t disprock;
        /* Pointer to the list node in the global fileref list that contains this
        fileref */
        GList* fileref_list;
        /* Pointer to the list node in the global fileref list that contains this
        fileref */
        GList* fileref_list;
index 804bb083bd715782314d7bcf4a1e836be49d2713..7394ce3b702b458b73fc9cdbaecffd7065d7d14e 100644 (file)
@@ -1,6 +1,9 @@
 #include "charset.h"
 #include "magic.h"
 #include "input.h"
 #include "charset.h"
 #include "magic.h"
 #include "input.h"
+#include "chimara-glk-private.h"
+
+extern GPrivate *glk_data_key;
 
 /* Forward declarations */
 static int flush_text_buffer(winid_t win);
 
 /* Forward declarations */
 static int flush_text_buffer(winid_t win);
@@ -224,6 +227,11 @@ glk_request_line_event(winid_t win, char* buf, glui32 maxlen, glui32 initlen)
        g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
        g_return_if_fail(initlen <= maxlen);
 
        g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
        g_return_if_fail(initlen <= maxlen);
 
+       /* Register the buffer */
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       if(glk_data->register_arr)
+        win->buffer_rock = (*glk_data->register_arr)(buf, maxlen, "&+#!Cn");
+       
        win->input_request_type = INPUT_REQUEST_LINE;
        win->line_input_buffer = buf;
        win->line_input_buffer_max_len = maxlen;
        win->input_request_type = INPUT_REQUEST_LINE;
        win->line_input_buffer = buf;
        win->line_input_buffer_max_len = maxlen;
@@ -268,6 +276,11 @@ glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, glui32 initl
        g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
        g_return_if_fail(initlen <= maxlen);
 
        g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
        g_return_if_fail(initlen <= maxlen);
 
+       /* Register the buffer */
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       if(glk_data->register_arr)
+        win->buffer_rock = (*glk_data->register_arr)(buf, maxlen, "&+#!Iu");
+
        win->input_request_type = INPUT_REQUEST_LINE_UNICODE;
        win->line_input_buffer_unicode = buf;
        win->line_input_buffer_max_len = maxlen;
        win->input_request_type = INPUT_REQUEST_LINE_UNICODE;
        win->line_input_buffer_unicode = buf;
        win->line_input_buffer_max_len = maxlen;
@@ -338,6 +351,15 @@ glk_cancel_line_event(winid_t win, event_t *event)
                chars_written = flush_text_buffer(win);
        }
 
                chars_written = flush_text_buffer(win);
        }
 
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       if(glk_data->unregister_arr) 
+       {
+               if(win->input_request_type == INPUT_REQUEST_LINE_UNICODE)
+                       (*glk_data->unregister_arr)(win->line_input_buffer_unicode, win->line_input_buffer_max_len, "&+#!Iu", win->buffer_rock);
+               else
+               (*glk_data->unregister_arr)(win->line_input_buffer, win->line_input_buffer_max_len, "&+#!Cn", win->buffer_rock);
+    }
+       
        if(event != NULL && chars_written > 0) {
                event->type = evtype_LineInput;
                event->val1 = chars_written;
        if(event != NULL && chars_written > 0) {
                event->type = evtype_LineInput;
                event->val1 = chars_written;
@@ -567,6 +589,15 @@ after_window_insert_text(GtkTextBuffer *textbuffer, GtkTextIter *location, gchar
 
         int chars_written = flush_text_buffer(win);
                event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(win->widget, CHIMARA_TYPE_GLK)), evtype_LineInput, win, chars_written, 0);
 
         int chars_written = flush_text_buffer(win);
                event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(win->widget, CHIMARA_TYPE_GLK)), evtype_LineInput, win, chars_written, 0);
+
+               ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+               if(glk_data->unregister_arr) 
+               {
+            if(win->input_request_type == INPUT_REQUEST_LINE_UNICODE)
+                               (*glk_data->unregister_arr)(win->line_input_buffer_unicode, win->line_input_buffer_max_len, "&+#!Iu", win->buffer_rock);
+                       else
+                (*glk_data->unregister_arr)(win->line_input_buffer, win->line_input_buffer_max_len, "&+#!Cn", win->buffer_rock);
+        }
        }
 }
 
        }
 }
 
@@ -579,5 +610,13 @@ on_input_entry_activate(GtkEntry *input_entry, winid_t win)
 
        int chars_written = flush_text_grid(win);
        event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(win->widget, CHIMARA_TYPE_GLK)), evtype_LineInput, win, chars_written, 0);
 
        int chars_written = flush_text_grid(win);
        event_throw(CHIMARA_GLK(gtk_widget_get_ancestor(win->widget, CHIMARA_TYPE_GLK)), evtype_LineInput, win, chars_written, 0);
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       if(glk_data->unregister_arr) 
+       {
+        if(win->input_request_type == INPUT_REQUEST_LINE_UNICODE)
+                       (*glk_data->unregister_arr)(win->line_input_buffer_unicode, win->line_input_buffer_max_len, "&+#!Iu", win->buffer_rock);
+               else
+            (*glk_data->unregister_arr)(win->line_input_buffer, win->line_input_buffer_max_len, "&+#!Cn", win->buffer_rock);
+    }
 }
 
 }
 
index 72b36a84087eadbdb0f54662e40c4779a6263947..a7f991d9f0805b370300c727ee859fcc10ad9bda 100644 (file)
 extern GPrivate *glk_data_key;
 
 /* Internal function: create a stream with a specified rock value */
 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;
 {
        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);
                
        /* Add it to the global stream list */
        glk_data->stream_list = g_list_prepend(glk_data->stream_list, str);
@@ -28,15 +28,41 @@ stream_new_common(glui32 rock, glui32 fmode, enum StreamType type)
        return str;
 }
 
        return str;
 }
 
-/* Internal function: create a window stream to go with window. */
-strid_t
-window_stream_new(winid_t window)
+/* Internal function: Stuff to do upon closing any type of stream. */
+void
+stream_close_common(strid_t str, stream_result_t *result)
 {
 {
-       /* 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;
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       
+       /* 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;
+
+       if(glk_data->unregister_obj)
+       {
+               (*glk_data->unregister_obj)(str, gidisp_Class_Stream, str->disprock);
+               str->disprock.ptr = NULL;
+       }
+       
+       /* Return the character counts */
+       if(result) 
+       {
+               result->readcount = str->read_count;
+               result->writecount = str->write_count;
+       }
+       
+       str->magic = MAGIC_FREE;
+       g_free(str);
 }
 
 /**
 }
 
 /**
@@ -252,11 +278,21 @@ glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock)
 {
        g_return_val_if_fail(fmode != filemode_WriteAppend, NULL);
        
 {
        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->mark = 0;
-       str->buflen = buflen;
        str->unicode = FALSE;
        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;
 }
 
        return str;
 }
 
@@ -280,11 +316,21 @@ glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, glui32 fmode, glui32 rock
 {
        g_return_val_if_fail(fmode != filemode_WriteAppend, NULL);
        
 {
        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->mark = 0;
-       str->buflen = buflen;
        str->unicode = TRUE;
        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;
 }
 
        return str;
 }
 
@@ -351,7 +397,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;
        str->file_pointer = fp;
        str->binary = binary;
        str->unicode = unicode;
@@ -444,9 +492,18 @@ glk_stream_close(strid_t str, stream_result_t *result)
                        return;
                        
                case STREAM_TYPE_MEMORY:
                        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;
                        break;
-                       
+               
                case STREAM_TYPE_FILE:
                        if(fclose(str->file_pointer) != 0)
                                IO_WARNING( "Failed to close file", str->filename, g_strerror(errno) );
                case STREAM_TYPE_FILE:
                        if(fclose(str->file_pointer) != 0)
                                IO_WARNING( "Failed to close file", str->filename, g_strerror(errno) );
@@ -459,34 +516,3 @@ glk_stream_close(strid_t str, stream_result_t *result)
 
        stream_close_common(str, 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)
-{
-       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
-       
-       /* 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);
-}
index 1f9f3c82596e4f45222bcca3a660bb0741108c7f..9636fac2c49b3c853c04ed9bbf522ae5cdfa0a42 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <gtk/gtk.h>
 #include "glk.h"
 
 #include <gtk/gtk.h>
 #include "glk.h"
+#include "gi_dispa.h"
 #include "window.h"
 #include "fileref.h"
 
 #include "window.h"
 #include "fileref.h"
 
@@ -23,6 +24,7 @@ struct glk_stream_struct
 {
        /*< private >*/
        glui32 magic, rock;
 {
        /*< private >*/
        glui32 magic, rock;
+       gidispatch_rock_t disprock;
        /* Pointer to the list node in the global stream list that contains this
        stream */
        GList* stream_list;
        /* Pointer to the list node in the global stream list that contains this
        stream */
        GList* stream_list;
@@ -40,6 +42,7 @@ struct glk_stream_struct
        glui32 *ubuffer;
        glui32 mark;
        glui32 buflen;
        glui32 *ubuffer;
        glui32 mark;
        glui32 buflen;
+       gidispatch_rock_t buffer_rock;
        /* Specific to file streams */
        FILE *file_pointer;
        gboolean binary;
        /* Specific to file streams */
        FILE *file_pointer;
        gboolean binary;
@@ -48,8 +51,8 @@ struct glk_stream_struct
        gchar *style; /* Name of the current style */
 };
 
        gchar *style; /* Name of the current style */
 };
 
-G_GNUC_INTERNAL strid_t window_stream_new(winid_t window);
 G_GNUC_INTERNAL strid_t file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode);
 G_GNUC_INTERNAL strid_t file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode);
+G_GNUC_INTERNAL strid_t stream_new_common(glui32 rock);
 G_GNUC_INTERNAL void stream_close_common(strid_t str, stream_result_t *result);
 
 #endif
 G_GNUC_INTERNAL void stream_close_common(strid_t str, stream_result_t *result);
 
 #endif
index bbfe49db68658f134ee667503044a19b5117ceb3..53f264dc91200ebdfcce700dfdc7db822d2d3b2b 100644 (file)
@@ -2,9 +2,54 @@
 #include "window.h"
 #include "magic.h"
 #include "chimara-glk-private.h"
 #include "window.h"
 #include "magic.h"
 #include "chimara-glk-private.h"
+#include "gi_dispa.h"
 
 extern GPrivate *glk_data_key;
 
 
 extern GPrivate *glk_data_key;
 
+static winid_t
+window_new_common(glui32 rock)
+{
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       winid_t win = g_new0(struct glk_window_struct, 1);
+       
+       win->magic = MAGIC_WINDOW;
+       win->rock = rock;
+       if(glk_data->register_obj)
+               win->disprock = (*glk_data->register_obj)(win, gidisp_Class_Window);
+       
+       win->window_node = g_node_new(win);
+       
+       /* Every window has a window stream, but printing to it might have no effect */
+       win->window_stream = stream_new_common(0);
+       win->window_stream->file_mode = filemode_Write;
+       win->window_stream->type = STREAM_TYPE_WINDOW;
+       win->window_stream->window = win;
+       win->window_stream->style = "normal";
+       
+       win->echo_stream = NULL;
+       win->input_request_type = INPUT_REQUEST_NONE;
+       win->line_input_buffer = NULL;
+       win->line_input_buffer_unicode = NULL;
+
+       return win;
+}
+
+static void
+window_close_common(winid_t win)
+{
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       
+       if(glk_data->unregister_obj) 
+       {
+        (*glk_data->unregister_obj)(win, gidisp_Class_Window, win->disprock);
+        win->disprock.ptr = NULL;
+    }
+
+       g_node_destroy(win->window_node);
+       win->magic = MAGIC_FREE;
+       g_free(win);
+}
+
 /**
  * glk_window_iterate:
  * @win: A window, or %NULL.
 /**
  * glk_window_iterate:
  * @win: A window, or %NULL.
@@ -391,11 +436,8 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype,
        gdk_threads_enter();
        
        /* Create the new window */
        gdk_threads_enter();
        
        /* Create the new window */
-       winid_t win = g_new0(struct glk_window_struct, 1);
-       win->magic = MAGIC_WINDOW;
-       win->rock = rock;
+       winid_t win = window_new_common(rock);
        win->type = wintype;
        win->type = wintype;
-       win->window_node = g_node_new(win);
 
        switch(wintype)
        {
 
        switch(wintype)
        {
@@ -410,9 +452,6 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype,
                        /* A blank window has no size */
                        win->unit_width = 0;
                        win->unit_height = 0;
                        /* A blank window has no size */
                        win->unit_width = 0;
                        win->unit_height = 0;
-                       /* You can print to a blank window's stream, but it does nothing */
-                       win->window_stream = window_stream_new(win);
-                       win->echo_stream = NULL;
                }
                        break;
                
                }
                        break;
                
@@ -435,13 +474,7 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype,
                        pango_layout_set_font_description(zero, glk_data->monospace_font_desc);
                        pango_layout_get_pixel_size(zero, &(win->unit_width), &(win->unit_height));
                        g_object_unref(zero);
                        pango_layout_set_font_description(zero, glk_data->monospace_font_desc);
                        pango_layout_get_pixel_size(zero, &(win->unit_width), &(win->unit_height));
                        g_object_unref(zero);
-                       
-                       /* Set the other parameters (width and height are set later) */
-                       win->window_stream = window_stream_new(win);
-                       win->echo_stream = NULL;
-                       win->input_request_type = INPUT_REQUEST_NONE;
-                       win->line_input_buffer = NULL;
-                       win->line_input_buffer_unicode = NULL;
+                       /* width and height are set later */
                        
                        /* Connect signal handlers */
                        win->keypress_handler = g_signal_connect( G_OBJECT(textview), "key-press-event", G_CALLBACK(on_window_key_press_event), win );
                        
                        /* Connect signal handlers */
                        win->keypress_handler = g_signal_connect( G_OBJECT(textview), "key-press-event", G_CALLBACK(on_window_key_press_event), win );
@@ -477,13 +510,6 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype,
                        pango_layout_set_font_description(zero, glk_data->default_font_desc);
                        pango_layout_get_pixel_size(zero, &(win->unit_width), &(win->unit_height));
                        g_object_unref(zero);
                        pango_layout_set_font_description(zero, glk_data->default_font_desc);
                        pango_layout_get_pixel_size(zero, &(win->unit_width), &(win->unit_height));
                        g_object_unref(zero);
-                       
-                       /* Set the other parameters */
-                       win->window_stream = window_stream_new(win);
-                       win->echo_stream = NULL;
-                       win->input_request_type = INPUT_REQUEST_NONE;
-                       win->line_input_buffer = NULL;
-                       win->line_input_buffer_unicode = NULL;
 
                        /* Connect signal handlers */
                        win->keypress_handler = g_signal_connect( G_OBJECT(textview), "key-press-event", G_CALLBACK(on_window_key_press_event), win );
 
                        /* Connect signal handlers */
                        win->keypress_handler = g_signal_connect( G_OBJECT(textview), "key-press-event", G_CALLBACK(on_window_key_press_event), win );
@@ -524,14 +550,8 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype,
        {
                /* When splitting, construct a new parent window
                 * copying most characteristics from the window that is being split */
        {
                /* When splitting, construct a new parent window
                 * copying most characteristics from the window that is being split */
-               winid_t pair = g_new0(struct glk_window_struct, 1);
-               pair->magic = MAGIC_WINDOW;
-               pair->rock = 0;
+               winid_t pair = window_new_common(0);
                pair->type = wintype_Pair;
                pair->type = wintype_Pair;
-               pair->window_node = g_node_new(pair);
-               /* You can print to a pair window's window stream, but it has no effect */
-               pair->window_stream = window_stream_new(pair);
-               pair->echo_stream = NULL;
 
                /* The pair window must know about its children's split method */
                pair->key_window = win;
 
                /* The pair window must know about its children's split method */
                pair->key_window = win;
@@ -636,8 +656,7 @@ free_winids_below(winid_t win)
                free_winids_below(win->window_node->children->data);
                free_winids_below(win->window_node->children->next->data);
        }
                free_winids_below(win->window_node->children->data);
                free_winids_below(win->window_node->children->next->data);
        }
-       win->magic = MAGIC_FREE;
-       g_free(win);
+       window_close_common(win);
 }
 
 /**
 }
 
 /**
@@ -729,7 +748,6 @@ glk_window_close(winid_t win, stream_result_t *result)
        /* Parent window changes from a split window into the sibling window */
        /* The parent of any window is either a pair window or NULL */
        GNode *pair_node = win->window_node->parent;
        /* Parent window changes from a split window into the sibling window */
        /* The parent of any window is either a pair window or NULL */
        GNode *pair_node = win->window_node->parent;
-       g_node_destroy(win->window_node);
        /* If win was not the root window: */
        if(pair_node != NULL)
        {
        /* If win was not the root window: */
        if(pair_node != NULL)
        {
@@ -752,19 +770,14 @@ glk_window_close(winid_t win, stream_result_t *result)
                                g_node_append(new_parent_node, sibling_node);
                }
 
                                g_node_append(new_parent_node, sibling_node);
                }
 
-               winid_t pair = (winid_t) pair_node->data;
-               g_node_destroy(pair_node);
-               
-               pair->magic = MAGIC_FREE;
-               g_free(pair);
+               window_close_common( (winid_t) pair_node->data );
        } 
        else /* it was the root window */
        {
                glk_data->root_window = NULL;
        }
 
        } 
        else /* it was the root window */
        {
                glk_data->root_window = NULL;
        }
 
-       win->magic = MAGIC_FREE;
-       g_free(win);
+       window_close_common(win);
 
        /* Schedule a redraw */
        g_mutex_lock(glk_data->arrange_lock);
 
        /* Schedule a redraw */
        g_mutex_lock(glk_data->arrange_lock);
@@ -1226,4 +1239,3 @@ glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos)
        
        gdk_threads_leave();
 }
        
        gdk_threads_leave();
 }
-
index 48ced889e332dc5464c9d5e0d89e26e290ab85cc..fd61ca310cf64131726861fcdc173eede3bfbe56 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <gtk/gtk.h>
 #include "glk.h"
 
 #include <gtk/gtk.h>
 #include "glk.h"
-
+#include "gi_dispa.h"
 #include "stream.h"
 #include "input.h"
 #include "style.h"
 #include "stream.h"
 #include "input.h"
 #include "style.h"
@@ -28,6 +28,7 @@ struct glk_window_struct
 {
        /*< private >*/
        glui32 magic, rock;
 {
        /*< private >*/
        glui32 magic, rock;
+       gidispatch_rock_t disprock;
        /* Pointer to the node in the global tree that contains this window */
        GNode *window_node;
        /* Window parameters */
        /* Pointer to the node in the global tree that contains this window */
        GNode *window_node;
        /* Window parameters */
@@ -55,6 +56,7 @@ struct glk_window_struct
        gchar *line_input_buffer;
        glui32 *line_input_buffer_unicode;
        glui32 line_input_buffer_max_len;
        gchar *line_input_buffer;
        glui32 *line_input_buffer_unicode;
        glui32 line_input_buffer_max_len;
+       gidispatch_rock_t buffer_rock;
        gboolean mouse_input_requested;
        /* Line input field (text grids only) */
        glui32 input_length;
        gboolean mouse_input_requested;
        /* Line input field (text grids only) */
        glui32 input_length;