+static gboolean
+expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+ struct som_entity *entity = g_object_get_data (G_OBJECT (widget), "entity");
+ GdkWindow *window = widget->window;
+ cairo_t *cairo = gdk_cairo_create (GDK_DRAWABLE (window));
+ struct outp_driver *driver = xr_create_driver (cairo); /* XXX can fail */
+ struct tab_table *t = entity->ext;
+ void *rendering;
+
+ rendering = entity->class->render_init (entity, driver, tab_l (t),
+ tab_r (t), tab_t (t), tab_b (t));
+
+ entity->class->title (rendering, 0, 0,
+ entity->table_num, entity->subtable_num,
+ entity->command_name);
+ entity->class->render (rendering, tab_l (t), tab_t (t),
+ tab_nc (t) - tab_r (t),
+ tab_nr (t) - tab_b (t));
+
+ entity->class->render_free (rendering);
+ driver->class->close_driver (driver);
+ outp_free_driver (driver);
+ return TRUE;
+}
+
+static void
+psppire_output_submit (struct outp_driver *this, struct som_entity *entity)
+{
+ if (the_output_viewer == NULL)
+ {
+ the_output_viewer = PSPPIRE_OUTPUT_WINDOW (psppire_output_window_new ());
+ gtk_widget_show_all (GTK_WIDGET (the_output_viewer));
+ }
+
+ if (entity->type == SOM_TABLE)
+ {
+ GdkWindow *window = GTK_WIDGET (the_output_viewer)->window;
+ cairo_t *cairo = gdk_cairo_create (GDK_DRAWABLE (window));
+ struct outp_driver *driver = xr_create_driver (cairo); /* XXX can fail */
+ struct tab_table *t = entity->ext;
+ GtkTreeStore *store;
+ GtkTreeIter item;
+ GtkTreePath *path;
+ GtkWidget *drawing_area;
+ void *rendering;
+ struct string title;
+ int tw, th;
+
+ tab_ref (t);
+ rendering = entity->class->render_init (entity, driver, tab_l (t),
+ tab_r (t), tab_t (t), tab_b (t));
+ entity->class->area (rendering, &tw, &th);
+
+ drawing_area = gtk_drawing_area_new ();
+ gtk_widget_modify_bg (GTK_WIDGET (drawing_area), GTK_STATE_NORMAL,
+ >k_widget_get_style (drawing_area)->base[GTK_STATE_NORMAL]);
+ g_object_set_data (G_OBJECT (drawing_area),
+ "entity", som_entity_clone (entity));
+ gtk_widget_set_size_request (drawing_area, tw / 1024, th / 1024);
+ gtk_layout_put (the_output_viewer->output, drawing_area,
+ 0, the_output_viewer->y);
+ gtk_widget_show (drawing_area);
+ g_signal_connect (G_OBJECT (drawing_area), "expose_event",
+ G_CALLBACK (expose_event_callback), NULL);
+
+ entity->class->render_free (rendering);
+ driver->class->close_driver (driver);
+ outp_free_driver (driver);
+
+ store = GTK_TREE_STORE (gtk_tree_view_get_model (
+ the_output_viewer->overview));
+
+ ds_init_empty (&title);
+ if (entity->table_num != the_output_viewer->last_table_num)
+ {
+ gtk_tree_store_append (store, &item, NULL);
+
+ ds_put_format (&title, "%d %s",
+ entity->table_num, entity->command_name);
+ gtk_tree_store_set (store, &item,
+ COL_TITLE, ds_cstr (&title),
+ COL_Y, the_output_viewer->y,
+ -1);
+
+ /* XXX shouldn't save a GtkTreeIter */
+ the_output_viewer->last_table_num = entity->table_num;
+ the_output_viewer->last_top_level = item;
+ }
+
+ gtk_tree_store_append (store, &item,
+ &the_output_viewer->last_top_level);
+ ds_clear (&title);
+ ds_put_format (&title, "%d.%d %s",
+ entity->table_num, entity->subtable_num,
+ t->title ? t->title : entity->command_name);
+ gtk_tree_store_set (store, &item,
+ COL_TITLE, ds_cstr (&title),
+ COL_Y, the_output_viewer->y,
+ -1);
+ ds_destroy (&title);
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (store),
+ &the_output_viewer->last_top_level);
+ gtk_tree_view_expand_row (the_output_viewer->overview, path, TRUE);
+ gtk_tree_path_free (path);
+
+ if (tw / 1024 > the_output_viewer->max_width)
+ the_output_viewer->max_width = tw / 1024;
+ the_output_viewer->y += th / 1024;
+
+ gtk_layout_set_size (the_output_viewer->output,
+ the_output_viewer->max_width, the_output_viewer->y);
+ }
+
+ gtk_window_set_urgency_hint (GTK_WINDOW (the_output_viewer), TRUE);
+}
+
+static struct outp_class psppire_output_class =
+ {
+ "PSPPIRE", /* name */
+ true, /* special */
+ NULL, /* open_driver */
+ NULL, /* close_driver */
+ NULL, /* open_page */
+ NULL, /* close_page */
+ NULL, /* flush */
+ NULL, /* output_chart */
+ psppire_output_submit, /* submit */
+ NULL, /* line */
+ NULL, /* text_metrics */
+ NULL, /* text_draw */
+ };