+
+
+static void
+append_cell_text (GString *string, const GtkSheet *sheet, gint r, gint c)
+{
+ gchar *celltext = gtk_sheet_cell_get_text (sheet, r, c);
+
+ if ( NULL == celltext)
+ return;
+
+ g_string_append (string, celltext);
+ g_free (celltext);
+}
+
+static GString *
+range_to_text (const GtkSheet *sheet)
+{
+ gint r, c;
+ GString *string;
+
+ if ( !gtk_sheet_range_isvisible (sheet, sheet->range))
+ return NULL;
+
+ string = g_string_sized_new (80);
+
+ for (r = sheet->range.row0; r <= sheet->range.rowi; ++r)
+ {
+ for (c = sheet->range.col0; c < sheet->range.coli; ++c)
+ {
+ append_cell_text (string, sheet, r, c);
+ g_string_append (string, "\t");
+ }
+ append_cell_text (string, sheet, r, c);
+ if ( r < sheet->range.rowi)
+ g_string_append (string, "\n");
+ }
+
+ return string;
+}
+
+static GString *
+range_to_html (const GtkSheet *sheet)
+{
+ gint r, c;
+ GString *string;
+
+ if ( !gtk_sheet_range_isvisible (sheet, sheet->range))
+ return NULL;
+
+ string = g_string_sized_new (480);
+
+ g_string_append (string, "<html>\n");
+ g_string_append (string, "<body>\n");
+ g_string_append (string, "<table>\n");
+ for (r = sheet->range.row0; r <= sheet->range.rowi; ++r)
+ {
+ g_string_append (string, "<tr>\n");
+ for (c = sheet->range.col0; c <= sheet->range.coli; ++c)
+ {
+ g_string_append (string, "<td>");
+ append_cell_text (string, sheet, r, c);
+ g_string_append (string, "</td>\n");
+ }
+ g_string_append (string, "</tr>\n");
+ }
+ g_string_append (string, "</table>\n");
+ g_string_append (string, "</body>\n");
+ g_string_append (string, "</html>\n");
+
+ return string;
+}
+
+enum {
+ SELECT_FMT_NULL,
+ SELECT_FMT_TEXT,
+ SELECT_FMT_HTML
+};
+
+static void
+primary_get_cb (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ guint info,
+ gpointer data)
+{
+ GtkSheet *sheet = GTK_SHEET (data);
+ GString *string = NULL;
+
+ switch (info)
+ {
+ case SELECT_FMT_TEXT:
+ string = range_to_text (sheet);
+ break;
+ case SELECT_FMT_HTML:
+ string = range_to_html (sheet);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ gtk_selection_data_set (selection_data, selection_data->target,
+ 8,
+ (const guchar *) string->str, string->len);
+ g_string_free (string, TRUE);
+}
+
+static void
+primary_clear_cb (GtkClipboard *clipboard,
+ gpointer data)
+{
+ GtkSheet *sheet = GTK_SHEET (data);
+ if ( ! GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
+ return;
+
+ gtk_sheet_real_unselect_range (sheet, NULL);
+}
+
+static void
+gtk_sheet_update_primary_selection (GtkSheet *sheet)
+{
+ static const GtkTargetEntry targets[] = {
+ { "UTF8_STRING", 0, SELECT_FMT_TEXT },
+ { "STRING", 0, SELECT_FMT_TEXT },
+ { "TEXT", 0, SELECT_FMT_TEXT },
+ { "COMPOUND_TEXT", 0, SELECT_FMT_TEXT },
+ { "text/plain;charset=utf-8", 0, SELECT_FMT_TEXT },
+ { "text/plain", 0, SELECT_FMT_TEXT },
+ { "text/html", 0, SELECT_FMT_HTML }
+ };
+
+ GtkClipboard *clipboard;
+
+ if (!GTK_WIDGET_REALIZED (sheet))
+ return;
+
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (sheet),
+ GDK_SELECTION_PRIMARY);
+
+ if (gtk_sheet_range_isvisible (sheet, sheet->range))
+ {
+ if (!gtk_clipboard_set_with_owner (clipboard, targets,
+ G_N_ELEMENTS (targets),
+ primary_get_cb, primary_clear_cb,
+ G_OBJECT (sheet)))
+ primary_clear_cb (clipboard, sheet);
+ }
+ else
+ {
+ if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (sheet))
+ gtk_clipboard_clear (clipboard);
+ }
+}
+