From c3e774e7847a994b7c3fb5d0e6a516432981a5b6 Mon Sep 17 00:00:00 2001 From: fliep Date: Sun, 3 May 2009 21:49:54 +0000 Subject: [PATCH] Fixed a crash when closing pair windows directly --- src/window.c | 93 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 79 insertions(+), 14 deletions(-) diff --git a/src/window.c b/src/window.c index 053bb48..8922d8f 100644 --- a/src/window.c +++ b/src/window.c @@ -585,14 +585,49 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, * Constraints. * */ -void -glk_window_close(winid_t win, stream_result_t *result) + +static void +dump_window_tree(GNode *node) { - VALID_WINDOW(win, return); + if(node == NULL) { + g_printerr("NULL"); + return; + } + g_printerr("["); + switch(((winid_t)node->data)->type) { + case wintype_Pair: + g_printerr("Pair "); + dump_window_tree(node->children); + dump_window_tree(node->children->next); + g_printerr("]"); + break; + case wintype_TextBuffer: + g_printerr("Buffer]"); + break; + case wintype_TextGrid: + g_printerr("Grid]"); + break; + case wintype_Blank: + g_printerr("Blank]"); + break; + default: + g_printerr("Fucked up - %d]", ((winid_t)node->data)->type); + } +} - /* First close the window stream before trashing the window tree */ +static void +close_window_streams_below(winid_t win, stream_result_t *result) +{ + if(win->type == wintype_Pair) { + close_window_streams_below(win->window_node->children->data, NULL); + close_window_streams_below(win->window_node->children->next->data, NULL); + } stream_close_common(win->window_stream, result); - +} + +static void +destroy_widgets_below(winid_t win) +{ switch(win->type) { case wintype_Blank: @@ -610,23 +645,50 @@ glk_window_close(winid_t win, stream_result_t *result) break; case wintype_Pair: - { - GNode *left = win->window_node->children; - GNode *right = win->window_node->children->next; - glk_window_close(left->data, NULL); - glk_window_close(right->data, NULL); - } + destroy_widgets_below(win->window_node->children->data); + destroy_widgets_below(win->window_node->children->next->data); break; default: ILLEGAL_PARAM("Unknown window type: %u", win->type); return; } +} - /* Parent window changes from a split window into the sibling window */ +static void +free_winids_below(winid_t win) +{ + if(win->type == wintype_Pair) { + free_winids_below(win->window_node->children->data); + free_winids_below(win->window_node->children->next->data); + } + win->magic = MAGIC_FREE; + g_free(win); +} + +void +glk_window_close(winid_t win, stream_result_t *result) +{ + VALID_WINDOW(win, return); + + /* First close all the window streams before trashing the window tree */ + close_window_streams_below(win, result); + + /* Then destroy the widgets of this window and below */ + destroy_widgets_below(win); + + /* Then free the winid_t structures below this node, but not this one itself */ + if(win->type == wintype_Pair) { + free_winids_below(win->window_node->children->data); + free_winids_below(win->window_node->children->next->data); + } + /* So now we should be left with a skeleton tree hanging off this node */ + + /* 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, or was not unhooked from the tree: */ + /* If win was not the root window: */ if(pair_node != NULL) { gboolean new_child_on_left = ( pair_node == g_node_first_sibling(pair_node) ); @@ -653,13 +715,16 @@ glk_window_close(winid_t win, stream_result_t *result) pair->magic = MAGIC_FREE; g_free(pair); + } + else /* it was the root window */ + { + glk_data->root_window = NULL; } win->magic = MAGIC_FREE; g_free(win); /* Schedule a redraw */ - gdk_threads_enter(); gtk_widget_queue_resize( GTK_WIDGET(glk_data->self) ); gdk_threads_leave(); } -- 2.30.2