- set_font (GTK_WIDGET (de), font_desc);
- gtk_container_foreach (GTK_CONTAINER (de), set_font, font_desc);
-}
-
-
-\f
-
-
-static void
-emit_selected_signal (PsppireDataEditor *de)
-{
- gboolean data_selected = data_is_selected (de);
-
- g_signal_emit (de, data_editor_signals[DATA_SELECTION_CHANGED], 0, data_selected);
-}
-
-
-static void
-on_activate (PsppireDataEditor *de)
-{
- gint row, col;
- psppire_sheet_get_active_cell (PSPPIRE_SHEET (de->data_sheet[0]), &row, &col);
-
-
- if ( row < psppire_data_store_get_case_count (de->data_store)
- &&
- col < psppire_var_store_get_var_cnt (de->var_store))
- {
- emit_selected_signal (de);
- return ;
- }
-
- emit_selected_signal (de);
-}
-
-
-static void
-on_select_range (PsppireDataEditor *de)
-{
- PsppireSheetRange range;
-
- psppire_sheet_get_selected_range (PSPPIRE_SHEET (de->data_sheet[0]), &range);
-
- if ( range.rowi < psppire_data_store_get_case_count (de->data_store)
- &&
- range.coli < psppire_var_store_get_var_cnt (de->var_store))
- {
- emit_selected_signal (de);
- return;
- }
-
- emit_selected_signal (de);
-}
-
-
-static gboolean
-on_switch_page (PsppireDataEditor *de, GtkNotebookPage *p,
- gint pagenum, gpointer data)
-{
- switch (pagenum)
- {
- case PSPPIRE_DATA_EDITOR_DATA_VIEW:
- gtk_widget_grab_focus (de->data_vbox);
- on_select_range (de);
- break;
- case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
- gtk_widget_grab_focus (de->var_sheet);
- emit_selected_signal (de);
- break;
- default:
- break;
- };
-
- return TRUE;
-}
-
-
-
-static gboolean
-data_is_selected (PsppireDataEditor *de)
-{
- PsppireSheetRange range;
- gint row, col;
-
- if ( gtk_notebook_get_current_page (GTK_NOTEBOOK (de)) != PSPPIRE_DATA_EDITOR_DATA_VIEW)
- return FALSE;
-
- psppire_sheet_get_active_cell (PSPPIRE_SHEET (de->data_sheet[0]), &row, &col);
-
- if ( row >= psppire_data_store_get_case_count (de->data_store)
- ||
- col >= psppire_var_store_get_var_cnt (de->var_store))
- {
- return FALSE;
- }
-
- psppire_sheet_get_selected_range (PSPPIRE_SHEET (de->data_sheet[0]), &range);
-
- if ( range.rowi >= psppire_data_store_get_case_count (de->data_store)
- ||
- range.coli >= psppire_var_store_get_var_cnt (de->var_store))
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-static void
-on_select_row (PsppireSheet *sheet, gint row, PsppireDataEditor *de)
-{
- g_signal_emit (de, data_editor_signals[CASES_SELECTED], 0, row);
-}
-
-
-static void
-on_select_variable (PsppireSheet *sheet, gint var, PsppireDataEditor *de)
-{
- g_signal_emit (de, data_editor_signals[VARIABLES_SELECTED], 0, var);
-}
-
-
-\f
-
-/* Clipboard stuff */
-
-
-#include <data/casereader.h>
-#include <data/case-map.h>
-#include <data/casewriter.h>
-
-#include <data/data-out.h>
-#include "xalloc.h"
-
-/* A casereader and dictionary holding the data currently in the clip */
-static struct casereader *clip_datasheet = NULL;
-static struct dictionary *clip_dict = NULL;
-
-
-static void data_sheet_update_clipboard (PsppireSheet *);
-
-/* Set the clip according to the currently
- selected range in the data sheet */
-static void
-data_sheet_set_clip (PsppireSheet *sheet)
-{
- int i;
- struct casewriter *writer ;
- PsppireSheetRange range;
- PsppireDataStore *ds;
- struct case_map *map = NULL;
- casenumber max_rows;
- size_t max_columns;
- gint row0, rowi;
- gint col0, coli;
-
- ds = PSPPIRE_DATA_STORE (psppire_sheet_get_model (sheet));
-
- psppire_sheet_get_selected_range (sheet, &range);
-
- col0 = MIN (range.col0, range.coli);
- coli = MAX (range.col0, range.coli);
- row0 = MIN (range.row0, range.rowi);
- rowi = MAX (range.row0, range.rowi);
-
- /* If nothing selected, then use active cell */
- if ( row0 < 0 || col0 < 0 )
- {
- gint row, col;
- psppire_sheet_get_active_cell (sheet, &row, &col);
-
- row0 = rowi = row;
- col0 = coli = col;
- }
-
- /* The sheet range can include cells that do not include data.
- Exclude them from the range. */
- max_rows = psppire_data_store_get_case_count (ds);
- if (rowi >= max_rows)
- {
- if (max_rows == 0)
- return;
- rowi = max_rows - 1;
- }
- max_columns = dict_get_var_cnt (ds->dict->dict);
- if (coli >= max_columns)
- {
- if (max_columns == 0)
- return;
- coli = max_columns - 1;
- }
-
- /* Destroy any existing clip */
- if ( clip_datasheet )
- {
- casereader_destroy (clip_datasheet);
- clip_datasheet = NULL;
- }
-
- if ( clip_dict )
- {
- dict_destroy (clip_dict);
- clip_dict = NULL;
- }
-
- /* Construct clip dictionary. */
- clip_dict = dict_create (dict_get_encoding (ds->dict->dict));
- for (i = col0; i <= coli; i++)
- dict_clone_var_assert (clip_dict, dict_get_var (ds->dict->dict, i));
-
- /* Construct clip data. */
- map = case_map_by_name (ds->dict->dict, clip_dict);
- writer = autopaging_writer_create (dict_get_proto (clip_dict));
- for (i = row0; i <= rowi ; ++i )
- {
- struct ccase *old = psppire_data_store_get_case (ds, i);
- if (old != NULL)
- casewriter_write (writer, case_map_execute (map, old));
- else
- casewriter_force_error (writer);
- }
- case_map_destroy (map);
-
- clip_datasheet = casewriter_make_reader (writer);
-
- data_sheet_update_clipboard (sheet);
-}
-
-enum {
- SELECT_FMT_NULL,
- SELECT_FMT_TEXT,
- SELECT_FMT_HTML
-};
-
-
-/* Perform data_out for case CC, variable V, appending to STRING */
-static void
-data_out_g_string (GString *string, const struct variable *v,
- const struct ccase *cc)
-{
- const struct fmt_spec *fs = var_get_print_format (v);
- const union value *val = case_data (cc, v);
-
- char *s = data_out (val, var_get_encoding (v), fs);
-
- g_string_append (string, s);
-
- g_free (s);
-}
-
-static GString *
-clip_to_text (void)
-{
- casenumber r;
- GString *string;
-
- const size_t val_cnt = caseproto_get_n_widths (casereader_get_proto (clip_datasheet));
- const casenumber case_cnt = casereader_get_case_cnt (clip_datasheet);
- const size_t var_cnt = dict_get_var_cnt (clip_dict);
-
- string = g_string_sized_new (10 * val_cnt * case_cnt);
-
- for (r = 0 ; r < case_cnt ; ++r )
- {
- int c;
- struct ccase *cc;
-
- cc = casereader_peek (clip_datasheet, r);
- if (cc == NULL)
- {
- g_warning ("Clipboard seems to have inexplicably shrunk");
- break;
- }
-
- for (c = 0 ; c < var_cnt ; ++c)
- {
- const struct variable *v = dict_get_var (clip_dict, c);
- data_out_g_string (string, v, cc);
- if ( c < val_cnt - 1 )
- g_string_append (string, "\t");
- }
-
- if ( r < case_cnt)
- g_string_append (string, "\n");
-
- case_unref (cc);
- }
-
- return string;
-}
-
-
-static GString *
-clip_to_html (void)
-{
- casenumber r;
- GString *string;
-
- const size_t val_cnt = caseproto_get_n_widths (casereader_get_proto (clip_datasheet));
- const casenumber case_cnt = casereader_get_case_cnt (clip_datasheet);
- const size_t var_cnt = dict_get_var_cnt (clip_dict);
-
- /* Guestimate the size needed */
- string = g_string_sized_new (80 + 20 * val_cnt * case_cnt);
-
- g_string_append (string,
- "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
-
- g_string_append (string, "<table>\n");
- for (r = 0 ; r < case_cnt ; ++r )
- {
- int c;
- struct ccase *cc = casereader_peek (clip_datasheet, r);
- if (cc == NULL)
- {
- g_warning ("Clipboard seems to have inexplicably shrunk");
- break;
- }
- g_string_append (string, "<tr>\n");
-
- for (c = 0 ; c < var_cnt ; ++c)
- {
- const struct variable *v = dict_get_var (clip_dict, c);
- g_string_append (string, "<td>");
- data_out_g_string (string, v, cc);
- g_string_append (string, "</td>\n");
- }
-
- g_string_append (string, "</tr>\n");
-
- case_unref (cc);
- }
- g_string_append (string, "</table>\n");
-
- return string;
-}
-
-
-
-static void
-clipboard_get_cb (GtkClipboard *clipboard,
- GtkSelectionData *selection_data,
- guint info,
- gpointer data)
-{
- GString *string = NULL;
-
- switch (info)
- {
- case SELECT_FMT_TEXT:
- string = clip_to_text ();
- break;
- case SELECT_FMT_HTML:
- string = clip_to_html ();
- 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
-clipboard_clear_cb (GtkClipboard *clipboard,
- gpointer data)
-{
- dict_destroy (clip_dict);
- clip_dict = NULL;
-
- casereader_destroy (clip_datasheet);
- clip_datasheet = NULL;
-}
-
-
-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 }
-};
-
-
-
-static void
-data_sheet_update_clipboard (PsppireSheet *sheet)
-{
- GtkClipboard *clipboard =
- gtk_widget_get_clipboard (GTK_WIDGET (sheet),
- GDK_SELECTION_CLIPBOARD);
-
- if (!gtk_clipboard_set_with_owner (clipboard, targets,
- G_N_ELEMENTS (targets),
- clipboard_get_cb, clipboard_clear_cb,
- G_OBJECT (sheet)))
- clipboard_clear_cb (clipboard, sheet);
-}
-
-
-
-/* A callback for when the clipboard contents have been received */
-static void
-data_sheet_contents_received_callback (GtkClipboard *clipboard,
- GtkSelectionData *sd,
- gpointer data)
-{
- gint count = 0;
- gint row, column;
- gint next_row, next_column;
- gint first_column;
- char *c;
- PsppireDataEditor *data_editor = data;
-
- if ( sd->length < 0 )
- return;
-
- if ( sd->type != gdk_atom_intern ("UTF8_STRING", FALSE))
- return;
-
- c = (char *) sd->data;
-
- /* Paste text to selected position */
- psppire_sheet_get_active_cell (PSPPIRE_SHEET (data_editor->data_sheet[0]),
- &row, &column);
-
- g_return_if_fail (row >= 0);
- g_return_if_fail (column >= 0);
-
- first_column = column;
- next_row = row;
- next_column = column;
- while (count < sd->length)
- {
- char *s = c;
-
- row = next_row;
- column = next_column;
- while (*c != '\t' && *c != '\n' && count < sd->length)
- {
- c++;
- count++;
- }
- if ( *c == '\t')
- {
- next_row = row ;
- next_column = column + 1;
- }
- else if ( *c == '\n')
- {
- next_row = row + 1;
- next_column = first_column;
- }
- *c++ = '\0';
- count++;
-
-
- /* Append some new cases if pasting beyond the last row */
- if ( row >= psppire_data_store_get_case_count (data_editor->data_store))
- psppire_data_store_insert_new_case (data_editor->data_store, row);
-
- psppire_data_store_set_string (data_editor->data_store, s, row, column);
- }
-}
-
-
-static void
-on_owner_change (GtkClipboard *clip, GdkEventOwnerChange *event, gpointer data)
-{
- gint i;
- gboolean compatible_target = FALSE;
- PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
-
- for (i = 0 ; i < sizeof (targets) / sizeof(targets[0]) ; ++i )
- {
- GdkAtom atom = gdk_atom_intern (targets[i].target, TRUE);
- if ( gtk_clipboard_wait_is_target_available (clip, atom))
- {
- compatible_target = TRUE;
- break;
- }
- }