+
+ gdk_threads_enter();
+
+ /* We only create one window and don't support any more than that */
+ winid_t win = g_new0(struct glk_window_struct, 1);
+ glk_data->root_window = g_node_new(win);
+
+ win->rock = rock;
+ win->type = wintype;
+ win->window_node = glk_data->root_window;
+
+ switch(wintype)
+ {
+ case wintype_Blank:
+ {
+ /* A blank window will be a label without any text */
+ GtkWidget *label = gtk_label_new("");
+ gtk_widget_show(label);
+
+ win->widget = label;
+ win->frame = label;
+ /* 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;
+
+ case wintype_TextBuffer:
+ {
+ GtkWidget *scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
+ GtkWidget *textview = gtk_text_view_new();
+ GtkTextBuffer *textbuffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(textview) );
+
+ gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(textview), GTK_WRAP_WORD_CHAR );
+ gtk_text_view_set_editable( GTK_TEXT_VIEW(textview), FALSE );
+
+ gtk_container_add( GTK_CONTAINER(scrolledwindow), textview );
+ gtk_widget_show_all(scrolledwindow);
+
+ win->widget = textview;
+ win->frame = scrolledwindow;
+ /* Determine the size of a "0" character in pixels" */
+ PangoLayout *zero = gtk_widget_create_pango_layout(textview, "0");
+ 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 );
+ g_signal_handler_block( G_OBJECT(textview), win->keypress_handler );
+
+ win->insert_text_handler = g_signal_connect_after( G_OBJECT(textbuffer), "insert-text", G_CALLBACK(after_window_insert_text), win );
+ g_signal_handler_block( G_OBJECT(textbuffer), win->insert_text_handler );
+
+ /* Create an editable tag to indicate uneditable parts of the window
+ (for line input) */
+ gtk_text_buffer_create_tag(textbuffer, "uneditable", "editable", FALSE, "editable-set", TRUE, NULL);
+
+ /* Mark the position where the user will input text */
+ GtkTextIter end;
+ gtk_text_buffer_get_end_iter(textbuffer, &end);
+ gtk_text_buffer_create_mark(textbuffer, "input_position", &end, TRUE);
+ }
+ break;
+
+ default:
+ gdk_threads_leave();
+ g_warning("%s: unsupported window type", __func__);
+ g_free(win);
+ g_node_destroy(glk_data->root_window);
+ glk_data->root_window = NULL;
+ return NULL;
+ }
+
+ /* Put the frame widget into our container */
+ gtk_widget_set_parent(win->frame, GTK_WIDGET(glk_data->self));
+ gtk_widget_queue_resize(GTK_WIDGET(glk_data->self));