+2007-08-12 John Darrington <john@darrington.wattle.id.au>
+ Ben Pfaff <blp@gnu.org>
+
+ Implement Edit|Cut operation for datasheet. Patch #6117.
+
+ * automake.mk: Add clipboard.c, clipboard.h.
+
+ * clipboard.c: New file.
+
+ * clipboard.h: New file.
+
+ * data-editor.c (new_data_editor): Connect Edit|Copy to
+ on_edit_copy function.
+ (data_var_select): Enable or disable Edit|Copy as appropriate.
+ (on_edit_copy): New function.
+
+ * data-editor.glade: Connect menu items to new operations.
+
2007-08-12 Ben Pfaff <blp@gnu.org>
* psppire-dict.c (psppire_dict_dump): Don't use
2007-08-13 John Darrington <john@darrington.wattle.id.au>
- * psppire-case-file.c (psppire_case_file_append_case):
+ * psppire-case-file.c (psppire_case_file_append_case):
Deleted unused function.
2007-08-07 John Darrington <john@darrington.wattle.id.au>
- * helper.c (execute_syntax): Set the active file data to NULL at the
+ * helper.c (execute_syntax): Set the active file data to NULL at the
end of the procedure. Thanks to Ben for suggesting this.
- * psppire-case-file.c: Added assertions to the remaining functions
+ * psppire-case-file.c: Added assertions to the remaining functions
on inaccessible objects.
- * psppire-data-store.c psppire-data-store.h: Disconnect or block
- signals on dictionary and case_file, when make_reader has been called.
- Reconnect or unblock them when a new datasheet has been set for the
+ * psppire-data-store.c psppire-data-store.h: Disconnect or block
+ signals on dictionary and case_file, when make_reader has been called.
+ Reconnect or unblock them when a new datasheet has been set for the
data_store.
-
+
2007-08-06 John Darrington <john@darrington.wattle.id.au>
* syntax-editor.glade: Changed some properties to be less annoying.
2007-07-26 John Darrington <john@darrington.wattle.id.au>
- * helper.c helper.h (execute_syntax): removed implicit EXECUTE at end
+ * helper.c helper.h (execute_syntax): removed implicit EXECUTE at end
of commands.
- * data-editor.c data-editor.glade: Added "Run Pending Transformations"
+ * data-editor.c data-editor.glade: Added "Run Pending Transformations"
menuitem.
2007-07-25 John Darrington <john@darrington.wattle.id.au>
- * customentry.c: Redraw button in insensitive state, if the widget's
- "editable" style is FALSE. Don't emit the "clicked" signal if
+ * customentry.c: Redraw button in insensitive state, if the widget's
+ "editable" style is FALSE. Don't emit the "clicked" signal if
"editable" is FALSE.
-
- * var-sheet.c: If variables are long-string variables, then set the
+
+ * var-sheet.c: If variables are long-string variables, then set the
"editable" properties of the entry widgets for the values and missing
cells to FALSE,
2007-07-18 John Darrington <john@darrington.wattle.id.au>
- * psppire-case-file.c psppire-case-file.h psppire-data-store.c
+ * psppire-case-file.c psppire-case-file.h psppire-data-store.c
psppire-dict.c psppire-dict.h psppire-var-store.c : Added the
ability to resize string variables. Fixed associated problems
- inserting/deleting variables.
-
+ inserting/deleting variables.
+
* helper.c helper.h (marshaller_VOID__INT_INT_INT): New marshaller
function.
-
+
2007-07-16 John Darrington <john@darrington.wattle.id.au>
- * data-editor.c: File Open dialog remembers directory. Thanks to
+ * data-editor.c: File Open dialog remembers directory. Thanks to
Ben Pfaff for this suggestion.
-
+
2007-07-15 John Darrington <john@darrington.wattle.id.au>
- * compute-dialog.c: Only generate NUMERIC/STRING command if the
+ * compute-dialog.c: Only generate NUMERIC/STRING command if the
type-and-label dialog was used.
2007-07-12 John Darrington <john@darrington.wattle.id.au>
- * psppire-data-store.c: Added call to g_sheet_model_range_changed to
+ * psppire-data-store.c: Added call to g_sheet_model_range_changed to
ensure that datasheet displays the current store.
* psppire-data-store.h: Formatting tidy up.
2007-07-08 John Darrington <john@darrington.wattle.id.au>
- * data-editor.c data-editor.glade data-editor.h: Implemented
+ * data-editor.c data-editor.glade data-editor.h: Implemented
the "Insert Case" button/dialog.
2007-07-08 John Darrington <john@darrington.wattle.id.au>
* goto-case-dialog.c goto-case-dialog.h (new files)
- * automake.mk data-editor.c data-editor.glade data-editor.h
- psppire-case-file.c psppire-case-file.h psppire-data-store.c
+ * automake.mk data-editor.c data-editor.glade data-editor.h
+ psppire-case-file.c psppire-case-file.h psppire-data-store.c
psppire-data-store.h psppire.glade : Implemented the goto-case dialog
-
+
2007-07-07 John Darrington <john@darrington.wattle.id.au>
-
- * psppire-data-store.c psppire-data-store.h: Made cases number from
- 1 instead of 0.
+
+ * psppire-data-store.c psppire-data-store.h: Made cases number from
+ 1 instead of 0.
* psppire-data-store.c: Added a tooltip like feature to display
- the label of variables.
-
+ the label of variables.
+
2007-07-03 John Darrington <john@darrington.wattle.id.au>
-
- * data-editor.c data-sheet.c: Turned off autoscrolling, and
+
+ * data-editor.c data-sheet.c: Turned off autoscrolling, and
manually move to cell on column click instead.
2007-06-29 John Darrington <john@darrington.wattle.id.au>
- * data-editor.c data-editor.glade psppire-data-store.c
- psppire-data-store.h: Enabled cell reference entry and datum
+ * data-editor.c data-editor.glade psppire-data-store.c
+ psppire-data-store.h: Enabled cell reference entry and datum
entry widgets.
2007-06-29 John Darrington <john@darrington.wattle.id.au>
- * data-editor.c data-sheet.c: Moved update_cell_ref_entry from
+ * data-editor.c data-sheet.c: Moved update_cell_ref_entry from
data-sheet.c to data-editor.c and made it work again.
2007-06-06 Ben Pfaff <blp@gnu.org>
Adapt case sources, sinks, and clients of procedure code to the
new infrastructure.
-
+
* automake.mk: Removed files.
* flexifile-factory.c: Removed, dead code.
* psppire-var-store.c (psppire_var_store_item_editable): Use
var_is_alpha.
-
+
2007-05-07 John Darrington <john@darrington.wattle.id.au>
* psppire-dialog.c psppire-dialog.h: Added "orientation" property,
to allow dialogs to be either vertical or horizontal.
- * comments-dialog.c comments-dialog.h: New files, invoking
+ * comments-dialog.c comments-dialog.h: New files, invoking
ADD DOCUMENT cmd.
2007-04-30 John Darrington <john@darrington.wattle.id.au>
* var-display.c var-display.h variable-info-dialog.c
- variable-info-dialog.h : New files.
+ variable-info-dialog.h : New files.
- * data-editor.c :
+ * data-editor.c :
* psppire-buttonbox.c psppire-buttonbox.h : Added the "buttons"
property, and optional GOTO and CONTINUE buttons.
2007-04-25 John Darrington <john@darrington.wattle.id.au>
* icons/scalable/splash.c icons/splash.png : More eye candy.
-
+
* main.c psppire.h : new files.
- * psppire.c : Seperated the command line parsing and other
+ * psppire.c : Seperated the command line parsing and other
environment startup from the core psppire code.
2007-04-25 John Darrington <john@darrington.wattle.id.au>
* icons/scalable icons/16x16: new directories.
* psppire.c : Add new icons to factory.
- * dict-display.c: Refactor code get model from modelfilter.
+ * dict-display.c: Refactor code get model from modelfilter.
Added cellrenderer to display icon indicating variables' types.
Displayed the label of variables, if there is one.
builds.
2007-04-13 John Darrington <john@darrington.wattle.id.au>
-
+
* var-type-dialog.c: Added a FMT_DATETIME20 template.
-
+
2007-04-04 John Darrington <john@darrington.wattle.id.au>
* compute-dialog.c compute-dialog.h: New files
- * data-editor.c data-editor.h data-editor.glade : Added Transform
+ * data-editor.c data-editor.h data-editor.glade : Added Transform
menu, and support for Compute dialog
- * glade-register.c psppire-buttonbox.c psppire-buttonbox.h
- psppire-vbottonbox.c psppire-vbuttonbox.h psppire-hbuttonbox.c
- psppire-vbuttonbox.h : Made buttonbox an abstract base class
+ * glade-register.c psppire-buttonbox.c psppire-buttonbox.h
+ psppire-vbottonbox.c psppire-vbuttonbox.h psppire-hbuttonbox.c
+ psppire-vbuttonbox.h : Made buttonbox an abstract base class
and separated it into vbuttonbox and hbuttonbox.
- * psppire-selector.c : Allowed GtkTextView to be the destination
+ * psppire-selector.c : Allowed GtkTextView to be the destination
widget.
- * psppire-keypad.c: Added an "erase" signal. Fixed other
+ * psppire-keypad.c: Added an "erase" signal. Fixed other
minor problems.
2007-04-03 Ben Pfaff <blp@gnu.org>
assert that may or may not trap some Windows-related bugs.
2007-04-03 John Darrington <john@darrington.wattle.id.au>
-
+
* data-editor.c data-editor.glade helper.h syntax-editor.c
syntax-editor.h : Implemented the File->Recently_Used_ menus.
2007-03-31 John Darrington <john@darrington.wattle.id.au>
-
+
* data-editor.c data-editor.glade data-editor.h dialog-common.c
psppire-buttonbox.c psppire-dialog.c psppire-dialog.h
psppire-selector.c psppire-selector.h psppire.c psppire.glade
sort-cases-dialog.c sort-cases-dialog.h split-file-dialog.c
transpose-dialog.c weight-cases-dialog.c : Fixed the Refresh
- button on all the dialogs.
-
+ button on all the dialogs.
+
2007-03-31 John Darrington <john@darrington.wattle.id.au>
-
+
* data-editor.c: Added hooks for the split-file-dialog
* psppire.glade: Added the split file dialog box.
-
+
* split-file-dialog.c split-file-dialog.h: New files.
-
- * dialog-common.c dialog-common.h: New files containing functions
- which seem to be used a lot in dialog box implementations.
+
+ * dialog-common.c dialog-common.h: New files containing functions
+ which seem to be used a lot in dialog box implementations.
* psppire-keypad.c psppire-keypad.h: New files. Implements keypad
- thingumy widget.
+ thingumy widget.
* psppire-selector.c: Made the orientation of the arrow a property
of the widget, so that it can be selected from glade.
conflict with POSIX function of same name.
Tue Mar 13 17:20:05 CET 2007 John Darrington <john@darrington.wattle.id.au>
- * psppire.c: Changed gtk_init to gtk_parse_args, followed by a delayed call to gdk_init, so that psppire --version will succeed, even if it
+ * psppire.c: Changed gtk_init to gtk_parse_args, followed by a delayed call to gdk_init, so that psppire --version will succeed, even if it
cannot connect to a display .
-
+
Wed Mar 7 19:05:12 CET 2007 John Darrington <john@darrington.wattle.id.au>
- * var-sheet.c: Replaced call to nl_langinfo with locale_charset
+ * var-sheet.c: Replaced call to nl_langinfo with locale_charset
from gnulib.
Thu Feb 22 12:27:41 CET 2007 John Darrington <john@darrington.wattle.id.au>
- * data-editor.c : called new gen_quoted_string function to properly
+ * data-editor.c : called new gen_quoted_string function to properly
quote filenames in generated syntax.
- * window-manager.c : Converted name from filename encoding to UTF8
+ * window-manager.c : Converted name from filename encoding to UTF8
before displaying in title bar.
Tue Jan 30 20:13:46 WST 2007 John Darrington <john@darrington.wattle.id.au>
* transpose-dialog.c transpose-dialog.h : New files.
- * psppire-dict.c psppire-dict.h : Added missing GtkTreeModel
+ * psppire-dict.c psppire-dict.h : Added missing GtkTreeModel
interface functions.
- * weight-cases-dialog.c weight-cases-dialog.h : Re-implemented,
+ * weight-cases-dialog.c weight-cases-dialog.h : Re-implemented,
using new PsppireSelector widget.
* dict-display.c dict-display.h : New files.
* helper.c helper.h: New function execute_syntax.
- * syntax-editor.c syntax-editor.glade: Disabled data open/save menu
+ * syntax-editor.c syntax-editor.glade: Disabled data open/save menu
items.
- * data-editor.c data-editor.glade data-editor.h: Enabled data
+ * data-editor.c data-editor.glade data-editor.h: Enabled data
open/save/save_as menu-items.
-
- * window-manager.h window-manager.c (default_window_name) : New
+
+ * window-manager.h window-manager.c (default_window_name) : New
function.
Sat Jan 13 07:47:26 WST 2007 John Darrington <john@darrington.wattle.id.au>
* psppire-case-file.c psppire-data-store.c psppire-dialog.c
- psppire-dict.c psppire-var-select.c : Replaced identifier 'signal'
+ psppire-dict.c psppire-var-select.c : Replaced identifier 'signal'
with 'signals' to avoid conflict with sysv based systems which use
- this identifer for something else.
+ this identifer for something else.
Thanks to Daniel E WILLIAMS for reporting this problem.
Wed Jan 10 07:20:39 WST 2007 John Darrington <john@darrington.wattle.id.au>
* psppire-data-store.c : assertions.
- * psppire.c: Ignore replace source callbacks if the new source is
+ * psppire.c: Ignore replace source callbacks if the new source is
not of storiage_source_class
* syntax-editor.c: Close/Abort source after parsing is complete.
Sun Jan 7 08:38:29 WST 2007 John Darrington <john@darrington.wattle.id.au>
- * psppire-dict.c: Add FILTER_CHANGED and SPLIT_CHANGED signals
+ * psppire-dict.c: Add FILTER_CHANGED and SPLIT_CHANGED signals
corresponding to the callbacks in src/data/dictionary.c
- * data-editor.c : Connect functions to the FILTER_CHANGED and
+ * data-editor.c : Connect functions to the FILTER_CHANGED and
SPLIT_CHANGED signals to update the status bar accordingly.
Mon Jan 1 10:37:07 WST 2007 John Darrington <john@darrington.wattle.id.au>
- * psppire-case-file.c psppire-case-file.h: Changed the backend
+ * psppire-case-file.c psppire-case-file.h: Changed the backend
semantics. An object is now created without any backend. A new function ( psppire_case_file_replace_flexifile ) sets the backend to use.
* psppire-data-store.c : Updated callers accordingly.
- * psppire-dict.c psppire-dict.h : New function
+ * psppire-dict.c psppire-dict.h : New function
(psppire_dict_replace_dictionary) .
- * psppire.c : Updated to use new dataset replace_{source, dictionary}
+ * psppire.c : Updated to use new dataset replace_{source, dictionary}
callbacks.
- * syntax-editor.c : parses in state CMD_STATE_DATA unless there are
+ * syntax-editor.c : parses in state CMD_STATE_DATA unless there are
no variables in the dictionary.
Mon Dec 25 12:38:24 WST 2006 John Darrington <john@darrington.wattle.id.au>
Sun Dec 17 08:26:10 WST 2006 John Darrington <john@darrington.wattle.id.au>
- * syntax-editor-source.c syntax-editor-source.h syntax-editor.h:
- New files.
+ * syntax-editor-source.c syntax-editor-source.h syntax-editor.h:
+ New files.
- * message-dialog.c : Now reports the filename and line number in
+ * message-dialog.c : Now reports the filename and line number in
error messages.
-
- * psppire.c psppire.glade syntax-editor.c: Added the ability to run
+
+ * psppire.c psppire.glade syntax-editor.c: Added the ability to run
syntax from the syntax editor.
-
+
Sat Dec 16 14:13:07 2006 Ben Pfaff <blp@gnu.org>
* psppire-data-store.c (geometry_get_justification): Don't assume
* psppire-variable.c psppire-variable.h: Deleted.
- * psppire-dict.c psppire-dict.h: Removed the caching of the variable
- data, which is now unecessary because src/data/vardict.h maintains
+ * psppire-dict.c psppire-dict.h: Removed the caching of the variable
+ data, which is now unecessary because src/data/vardict.h maintains
an association between variables and their dictionary.
-
- * data-sheet.c menu-actions.c missing-val-dialog.c
- missing-val-dialog.h psppire-data-store.c
- psppire-var-store.c psppire-var-store.h
- sort-cases-dialog.c val-labs-dialog.c val-labs-dialog.h
- var-sheet.c var-type-dialog.c var-type-dialog.h: Dealt with the
- consequences of deleting psppire-variable.[ch].
+
+ * data-sheet.c menu-actions.c missing-val-dialog.c
+ missing-val-dialog.h psppire-data-store.c
+ psppire-var-store.c psppire-var-store.h
+ sort-cases-dialog.c val-labs-dialog.c val-labs-dialog.h
+ var-sheet.c var-type-dialog.c var-type-dialog.h: Dealt with the
+ consequences of deleting psppire-variable.[ch].
Sat Dec 9 20:03:04 2006 Ben Pfaff <blp@gnu.org>
Sat Jul 15 11:27:15 WST 2006 John Darrington <john@darrington.wattle.id.au>
- * psppire.c psppire.glade automake.mk icons/* : Added toolbar icons where
+ * psppire.c psppire.glade automake.mk icons/* : Added toolbar icons where
there's no suitable gtk stock icon.
Tue Jul 4 09:08:38 WST 2006 John Darrington <john@darrington.wattle.id.au>
-
+
* psppire.c: Fixed --help and --version options.
-
+
Sat Jun 24 16:56:22 WST 2006 John Darrington <john@darrington.wattle.id.au>
* menu-actions.c: Added goto case and sort cases dialogs.
* psppire-case-file.c psppire-case-file.h: Added sort function.
- * psppire-data-store.c psppire-variable.c psppire-variable.h:
+ * psppire-data-store.c psppire-variable.c psppire-variable.h:
Renamed psppire_variable_get_index to psppire_variable_get_fv and
dealt with the consequences. Added a psppire_variable_get_index
function which actually does what the name suggests.
* psppire-dict.c psppire-dict.h: Implemented GtkTreeModel interface,
- which allows a dictionary to be displayed in a GtkTreeView.
+ which allows a dictionary to be displayed in a GtkTreeView.
- * psppire.glade: Added dialog boxes for Goto Case and Sort Case.
+ * psppire.glade: Added dialog boxes for Goto Case and Sort Case.
* sort-cases-dialog.c sort-cases-dialog.h (new files).
Mon Jun 19 18:10:53 WST 2006 John Darrington <john@darrington.wattle.id.au>
* psppire-case-file.c psppire-case-file.h (new files)
-
+
* automake.mk data-sheet.c data-sheet.h menu-actions.c
psppire-data-store.c psppire-data-store.h psppire-dict.c
psppire-dict.h psppire-var-store.c psppire.c
-
+
Replaced psppire-case-array.c with psppire-case-file.c, so as to
allow an arbitrary number of cases to be represented.
-
+
Sun Jun 4 15:50:28 WST 2006 John Darrington <john@darrington.wattle.id.au>
- * psppire-var-store.c, psppire.c, var-sheet.c : Unlimited the number of
+ * psppire-var-store.c, psppire.c, var-sheet.c : Unlimited the number of
variables that can be displayed. Minor i18n issues.
Tue May 30 19:53:35 WST 2006 John Darrington <john@darrington.wattle.id.au>
- * menu-actions.c menu-actions.h psppire.c: Fixed up load/new
+ * menu-actions.c menu-actions.h psppire.c: Fixed up load/new
interactions with startup.
* psppire-data-store.c: Fixed bad i18n call.
Sat May 27 16:25:38 WST 2006 John Darrington <john@darrington.wattle.id.au>
- * customentry.c data-sheet.c menu-actions.c message-dialog.c
- missing-val-dialog.c psppire-data-store.c psppire-var-store.c
+ * customentry.c data-sheet.c menu-actions.c message-dialog.c
+ missing-val-dialog.c psppire-data-store.c psppire-var-store.c
psppire.c psppire.glade var-sheet.c: Fixed internationalisation.
Thu May 25 18:01:17 WST 2006 John Darrington <john@darrington.wattle.id.au>
* psppire.c: Allowed user to specify *.sav file on command line.
Mon May 15 20:01:25 WST 2006 John Darrington <john@darrington.wattle.id.au>
-
+
* menu-actions.c psppire-case-array.c psppire-case-array.h
- psppire-data-store.c psppire-dict.c psppire-dict.h
+ psppire-data-store.c psppire-dict.c psppire-dict.h
psppire-variable.c:
Initialised new cases to SYSMIS/blank when inserting in data sheet.
Sat May 13 08:00:50 WST 2006 John Darrington <john@darrington.wattle.id.au>
- * data-sheet.c, helper.c, helper.h, psppire-data-store.c,
+ * data-sheet.c, helper.c, helper.h, psppire-data-store.c,
psppire-var-store.c:
-
- Set free_strings flag so that the gtksheet frees the string data
+
+ Set free_strings flag so that the gtksheet frees the string data
when it's done with them.
Thu May 11 22:25:49 WST 2006 John Darrington <john@darrington.wattle.id.au>
- * data-sheet.c helper.c helper.h psppire-data-store.c psppire-var-store.c
+ * data-sheet.c helper.c helper.h psppire-data-store.c psppire-var-store.c
psppire.c: Converted strings to utf8 before passing to gtksheet.
* psppire-dict.c: Changed buffer to more reasonable length
* var-sheet.c: Changed maximum string length to use macro from
data/values.h
-
+
Sun May 7 10:07:28 WST 2006 John Darrington <john@darrington.wattle.id.au>
* psppire-data-store.c: Fixed buglet initialising string members.
Finish reforming error message support. In this phase, move
message.c into libpspp.
-
+
* automake.mk: (src_ui_gui_psppire_SOURCES) Remove src/message.c.
Tue Apr 25 10:56:53 2006 Ben Pfaff <blp@gnu.org>
Continue reforming error message support. In this phase, get rid
of message "titles" and put the message text in `struct error'.
Now `struct error' encapsulates a message more properly.
-
+
* message-dialog.c: (err_vmsg) Rename err_msg(). Updated
interface.
rid of VM() and the other msg() support for "verbosity", replacing
it by a new function verbose_msg().
- * message-dialog.c: (verbose_msg) New function.
+ * message-dialog.c: (verbose_msg) New function.
(err_cond_fail) Removed (dead code).
(err_failure) Removed (dead code).
* Rename error-dialog.[ch] -> message-dialog.[ch]
* Moved code from the psppire module.
-
+
Sat Jan 28 16:22:23 WST 2006 John Darrington <john@darrington.wattle.id.au>
* Separated the data out of the GtkSheet.
--- /dev/null
+/* PSPPIRE - a graphical user interface for PSPP.
+ Copyright (C) 2007 Free Software Foundation
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <gtksheet/gtksheet.h>
+#include "clipboard.h"
+#include <data/case.h>
+#include "psppire-data-store.h"
+#include <data/casereader.h>
+#include <data/case-map.h>
+#include <libpspp/alloc.h>
+#include <data/casewriter.h>
+#include <data/format.h>
+#include <data/data-out.h>
+#include <stdlib.h>
+
+
+/* A casereader and dictionary holding the data currently in the clip */
+static struct casereader *clip_datasheet = NULL;
+struct dictionary *clip_dict = NULL;
+
+
+
+
+static void data_sheet_update_clipboard (GtkSheet *);
+
+/* Set the clip according to the currently
+ selected range in the data sheet */
+void
+data_sheet_set_clip (GtkSheet *sheet)
+{
+ int i;
+ struct casewriter *writer ;
+ GtkSheetRange range;
+ PsppireDataStore *ds;
+ struct case_map *map = NULL;
+ casenumber max_rows;
+ size_t max_columns;
+
+ ds = PSPPIRE_DATA_STORE (gtk_sheet_get_model (sheet));
+
+ gtk_sheet_get_selected_range (sheet, &range);
+
+ /* If nothing selected, then use active cell */
+ if ( range.row0 < 0 || range.col0 < 0 )
+ {
+ gint row, col;
+ gtk_sheet_get_active_cell (sheet, &row, &col);
+
+ range.row0 = range.rowi = row;
+ range.col0 = range.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 (range.rowi >= max_rows)
+ {
+ if (max_rows == 0)
+ return;
+ range.rowi = max_rows - 1;
+ }
+ max_columns = dict_get_var_cnt (ds->dict->dict);
+ if (range.coli >= max_columns)
+ {
+ if (max_columns == 0)
+ return;
+ range.coli = max_columns - 1;
+ }
+
+ g_return_if_fail (range.rowi >= range.row0);
+ g_return_if_fail (range.row0 >= 0);
+ g_return_if_fail (range.coli >= range.col0);
+ g_return_if_fail (range.col0 >= 0);
+
+ /* 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 ();
+ for (i = range.col0; i <= range.coli; i++)
+ {
+ const struct variable *old = dict_get_var (ds->dict->dict, i);
+ dict_clone_var_assert (clip_dict, old, var_get_name (old));
+ }
+
+ /* Construct clip data. */
+ map = case_map_by_name (ds->dict->dict, clip_dict);
+ writer = autopaging_writer_create (dict_get_next_value_idx (clip_dict));
+ for (i = range.row0; i <= range.rowi ; ++i )
+ {
+ struct ccase old;
+
+ if (psppire_case_file_get_case (ds->case_file, i, &old))
+ {
+ struct ccase new;
+
+ case_map_execute (map, &old, &new);
+ case_destroy (&old);
+ casewriter_write (writer, &new);
+ }
+ 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)
+{
+ char *buf ;
+
+ const struct fmt_spec *fs = var_get_print_format (v);
+ const union value *val = case_data (cc, v);
+ buf = xzalloc (fs->w);
+
+ data_out (val, fs, buf);
+
+ g_string_append_len (string, buf, fs->w);
+
+ g_free (buf);
+}
+
+static GString *
+clip_to_text (void)
+{
+ casenumber r;
+ GString *string;
+
+ const size_t val_cnt = casereader_get_value_cnt (clip_datasheet);
+ const casenumber case_cnt = casereader_get_case_cnt (clip_datasheet);
+
+ string = g_string_sized_new (10 * val_cnt * case_cnt);
+
+ for (r = 0 ; r < case_cnt ; ++r )
+ {
+ int c;
+ struct ccase cc;
+ if ( ! casereader_peek (clip_datasheet, r, &cc))
+ {
+ g_warning ("Clipboard seems to have inexplicably shrunk");
+ break;
+ }
+
+ for (c = 0 ; c < val_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_destroy (&cc);
+ }
+
+ return string;
+}
+
+
+static GString *
+clip_to_html (void)
+{
+ casenumber r;
+ GString *string;
+
+ const size_t val_cnt = casereader_get_value_cnt (clip_datasheet);
+ const casenumber case_cnt = casereader_get_case_cnt (clip_datasheet);
+
+ /* Guestimate the size needed */
+ string = g_string_sized_new (20 * val_cnt * case_cnt);
+
+ g_string_append (string, "<table>\n");
+ for (r = 0 ; r < case_cnt ; ++r )
+ {
+ int c;
+ struct ccase cc;
+ if ( ! casereader_peek (clip_datasheet, r, &cc))
+ {
+ g_warning ("Clipboard seems to have inexplicably shrunk");
+ break;
+ }
+ g_string_append (string, "<tr>\n");
+
+ for (c = 0 ; c < val_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_destroy (&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 void
+data_sheet_update_clipboard (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 =
+ 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);
+}
+