From: Philip Chimento Date: Wed, 7 Oct 2009 20:45:17 +0000 (+0000) Subject: Wrote platform-dependent dispatch code X-Git-Url: https://git.stderr.nl/gitweb?a=commitdiff_plain;ds=sidebyside;h=d0d1517f5447d0bd95c6b9769a92054f4c7fcaae;p=rodin%2Fchimara.git Wrote platform-dependent dispatch code git-svn-id: http://lassie.dyndns-server.com/svn/gargoyle-gtk@130 ddfedd41-794f-dd11-ae45-00112f111e67 --- diff --git a/libchimara/Makefile.am b/libchimara/Makefile.am index ba1e1d8..64e6ebc 100644 --- a/libchimara/Makefile.am +++ b/libchimara/Makefile.am @@ -9,6 +9,7 @@ libchimara_la_SOURCES = \ 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 \ diff --git a/libchimara/chimara-glk-private.h b/libchimara/chimara-glk-private.h index 25417d3..4a274fb 100644 --- a/libchimara/chimara-glk-private.h +++ b/libchimara/chimara-glk-private.h @@ -6,6 +6,7 @@ #include #include "glk.h" #include "gi_blorb.h" +#include "gi_dispa.h" #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; + /* 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 */ diff --git a/libchimara/dispatch.c b/libchimara/dispatch.c new file mode 100644 index 0000000..b1f84da --- /dev/null +++ b/libchimara/dispatch.c @@ -0,0 +1,58 @@ +#include +#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; +} diff --git a/libchimara/fileref.c b/libchimara/fileref.c index 97c6e48..937933c 100644 --- a/libchimara/fileref.c +++ b/libchimara/fileref.c @@ -6,9 +6,55 @@ #include "fileref.h" #include "magic.h" #include "chimara-glk-private.h" +#include "gi_dispa.h" 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. @@ -57,28 +103,6 @@ glk_fileref_get_rock(frefid_t fref) 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 fileusage_ 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_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, @@ -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_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: @@ -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_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); @@ -239,8 +259,7 @@ glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock) 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); @@ -380,15 +399,7 @@ void 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); } /** diff --git a/libchimara/fileref.h b/libchimara/fileref.h index 9dd8e50..c2d8f46 100644 --- a/libchimara/fileref.h +++ b/libchimara/fileref.h @@ -3,6 +3,7 @@ #include #include "glk.h" +#include "gi_dispa.h" /** * glk_fileref_struct: @@ -14,6 +15,7 @@ struct glk_fileref_struct { /*< 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; diff --git a/libchimara/input.c b/libchimara/input.c index 804bb08..7394ce3 100644 --- a/libchimara/input.c +++ b/libchimara/input.c @@ -1,6 +1,9 @@ #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); @@ -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); + /* 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; @@ -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); + /* 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; @@ -338,6 +351,15 @@ glk_cancel_line_event(winid_t win, event_t *event) 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; @@ -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); + + 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); + 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); + } } diff --git a/libchimara/stream.c b/libchimara/stream.c index 72b36a8..a7f991d 100644 --- a/libchimara/stream.c +++ b/libchimara/stream.c @@ -10,16 +10,16 @@ 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); @@ -28,15 +28,41 @@ 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: 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); - 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; } @@ -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); - 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; } @@ -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; @@ -444,9 +492,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) ); @@ -459,34 +516,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) -{ - 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); -} diff --git a/libchimara/stream.h b/libchimara/stream.h index 1f9f3c8..9636fac 100644 --- a/libchimara/stream.h +++ b/libchimara/stream.h @@ -3,6 +3,7 @@ #include #include "glk.h" +#include "gi_dispa.h" #include "window.h" #include "fileref.h" @@ -23,6 +24,7 @@ struct glk_stream_struct { /*< 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; @@ -40,6 +42,7 @@ struct glk_stream_struct glui32 *ubuffer; glui32 mark; glui32 buflen; + gidispatch_rock_t buffer_rock; /* Specific to file streams */ FILE *file_pointer; gboolean binary; @@ -48,8 +51,8 @@ struct glk_stream_struct 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 stream_new_common(glui32 rock); G_GNUC_INTERNAL void stream_close_common(strid_t str, stream_result_t *result); #endif diff --git a/libchimara/window.c b/libchimara/window.c index bbfe49d..53f264d 100644 --- a/libchimara/window.c +++ b/libchimara/window.c @@ -2,9 +2,54 @@ #include "window.h" #include "magic.h" #include "chimara-glk-private.h" +#include "gi_dispa.h" 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. @@ -391,11 +436,8 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, 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->window_node = g_node_new(win); 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; - /* 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; @@ -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); - - /* 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 ); @@ -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); - - /* 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 ); @@ -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 */ - 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->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; @@ -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); } - 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; - g_node_destroy(win->window_node); /* 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); } - 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; } - win->magic = MAGIC_FREE; - g_free(win); + window_close_common(win); /* 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(); } - diff --git a/libchimara/window.h b/libchimara/window.h index 48ced88..fd61ca3 100644 --- a/libchimara/window.h +++ b/libchimara/window.h @@ -3,7 +3,7 @@ #include #include "glk.h" - +#include "gi_dispa.h" #include "stream.h" #include "input.h" #include "style.h" @@ -28,6 +28,7 @@ struct glk_window_struct { /*< 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 */ @@ -55,6 +56,7 @@ struct glk_window_struct 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;