[gnumeric] Fix undo of Clear->All and Clear->Comments. [#625151]



commit 01e300cef7c7d6654ee90e998f31013fbe0dd65e
Author: Andreas J Guelzow <aguelzow pyrshep ca>
Date:   Sat Jul 24 00:01:59 2010 -0600

    Fix undo of Clear->All and Clear->Comments. [#625151]
    
    2010-07-23  Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* src/clipboard.c (cb_clipboard_copy_range_undo): paste everything back
    	* src/commands.c (cmd_clear_*): delete
    	(cmd_selection_clear): rewrite using GOUndo
    	* src/sheet.c (sheet_clear_region_undo): new
    	(sheet_clear_region_cb): new
    	* src/sheet.h (sheet_clear_region_undo): new

 ChangeLog       |    9 +++
 NEWS            |    1 +
 src/clipboard.c |    3 +-
 src/commands.c  |  172 ++++++++++++-------------------------------------------
 src/sheet.c     |   21 +++++++
 src/sheet.h     |    3 +
 6 files changed, 74 insertions(+), 135 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 3ac1590..d507151 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2010-07-23  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* src/clipboard.c (cb_clipboard_copy_range_undo): paste everything back
+	* src/commands.c (cmd_clear_*): delete
+	(cmd_selection_clear): rewrite using GOUndo
+	* src/sheet.c (sheet_clear_region_undo): new
+	(sheet_clear_region_cb): new
+	* src/sheet.h (sheet_clear_region_undo): new
+
 2010-07-23  Morten Welinder  <terra gnome org>
 
 	* src/func.c (gnm_func_sanity_check1): Make sure argument names,
diff --git a/NEWS b/NEWS
index 6afb762..87a191e 100644
--- a/NEWS
+++ b/NEWS
@@ -45,6 +45,7 @@ Andreas:
 	  names while editing cells (Shift-F4).
 	* Add preference settings whether to show function name and/or
 	  argument tooltips.
+	* Fix undo of Clear->All and Clear->Comments. [#625151]
 
 Jean:
 	* Fix strong/weak cursor display. [#623241]
diff --git a/src/clipboard.c b/src/clipboard.c
index 6b27865..8d94cf0 100644
--- a/src/clipboard.c
+++ b/src/clipboard.c
@@ -687,7 +687,8 @@ cb_clipboard_copy_range_undo (GnmCellRegion *cr, GnmSheetRange *sr,
 		 paste_target_init (&pt,
 				    sr->sheet,
 				    &sr->range,
-				    PASTE_CONTENTS | PASTE_FORMATS),
+				    PASTE_CONTENTS | PASTE_FORMATS | 
+				    PASTE_OBJECTS | PASTE_COMMENTS),
 		 cc);
 }
 
diff --git a/src/commands.c b/src/commands.c
index bb2b2ef..59a67e6 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -1417,154 +1417,42 @@ cmd_delete_rows (WorkbookControl *wbc,
 
 /******************************************************************/
 
-#define CMD_CLEAR_TYPE        (cmd_clear_get_type ())
-#define CMD_CLEAR(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_CLEAR_TYPE, CmdClear))
-
-typedef struct {
-	GnmCommand cmd;
-
-	int	 clear_flags;
-	int	 paste_flags;
-	GSList	  *old_contents;
-	GSList	  *selection;
-} CmdClear;
-
-static void
-cmd_clear_repeat (GnmCommand const *cmd, WorkbookControl *wbc)
-{
-	CmdClear const *orig = (CmdClear const *) cmd;
-	cmd_selection_clear (wbc, orig->clear_flags);
-}
-MAKE_GNM_COMMAND (CmdClear, cmd_clear, cmd_clear_repeat)
-
-static gboolean
-cmd_clear_undo (GnmCommand *cmd, WorkbookControl *wbc)
-{
-	CmdClear *me = CMD_CLEAR (cmd);
-	GSList *ranges;
-
-	g_return_val_if_fail (me != NULL, TRUE);
-	g_return_val_if_fail (me->selection != NULL, TRUE);
-	g_return_val_if_fail (me->old_contents != NULL, TRUE);
-
-	for (ranges = me->selection; ranges != NULL ; ranges = ranges->next) {
-		GnmRange const *r = ranges->data;
-		GnmCellRegion  *c;
-		GnmPasteTarget pt;
-
-		g_return_val_if_fail (me->old_contents != NULL, TRUE);
-
-		c = me->old_contents->data;
-
-		if (me->clear_flags)
-			clipboard_paste_region (c,
-				paste_target_init (&pt, me->cmd.sheet, r, me->paste_flags),
-				GO_CMD_CONTEXT (wbc));
-
-		cellregion_unref (c);
-		me->old_contents = g_slist_remove (me->old_contents, c);
-	}
-	g_return_val_if_fail (me->old_contents == NULL, TRUE);
-
-	select_selection (me->cmd.sheet, me->selection, wbc);
-
-	return FALSE;
-}
-
-static gboolean
-cmd_clear_redo (GnmCommand *cmd, WorkbookControl *wbc)
-{
-	CmdClear *me = CMD_CLEAR (cmd);
-	GSList *l;
-
-	g_return_val_if_fail (me != NULL, TRUE);
-	g_return_val_if_fail (me->selection != NULL, TRUE);
-	g_return_val_if_fail (me->old_contents == NULL, TRUE);
-
-	/* Check for array subdivision */
-	if (sheet_ranges_split_region (me->cmd.sheet, me->selection,
-				       GO_CMD_CONTEXT (wbc), _("Clear")))
-		return TRUE;
-
-	/* Check for locked cells */
-	if (cmd_selection_is_locked_effective (me->cmd.sheet, me->selection, wbc, _("Clear")))
-		return TRUE;
-
-	for (l = me->selection ; l != NULL ; l = l->next) {
-		GnmRange const *r = l->data;
-		me->old_contents =
-			g_slist_prepend (me->old_contents,
-				clipboard_copy_range (me->cmd.sheet, r));
-
-		/* We have already checked the arrays */
-		sheet_clear_region (me->cmd.sheet,
-			r->start.col, r->start.row, r->end.col, r->end.row,
-			me->clear_flags|CLEAR_NOCHECKARRAY|CLEAR_RECALC_DEPS,
-			GO_CMD_CONTEXT (wbc));
-	}
-	me->old_contents = g_slist_reverse (me->old_contents);
-
-	select_selection (me->cmd.sheet, me->selection, wbc);
-
-	return FALSE;
-}
-
-static void
-cmd_clear_finalize (GObject *cmd)
-{
-	CmdClear *me = CMD_CLEAR (cmd);
-
-	if (me->old_contents != NULL) {
-		GSList *l;
-		for (l = me->old_contents ; l != NULL ; l = g_slist_remove (l, l->data))
-			cellregion_unref (l->data);
-		me->old_contents = NULL;
-	}
-	range_fragment_free (me->selection);
-	me->selection = NULL;
-
-	gnm_command_finalize (cmd);
-}
 
 gboolean
 cmd_selection_clear (WorkbookControl *wbc, int clear_flags)
 {
-	CmdClear *me;
-	char *names;
+	char *names, *descriptor;
 	GString *types;
-	int paste_flags;
 	SheetView *sv = wb_control_cur_sheet_view (wbc);
+	GSList	  *selection = selection_get_ranges (sv, FALSE /* No intersection */);
+	Sheet *sheet = sv_sheet (sv);
+	gboolean result;
+	int size;
+	GOUndo *undo = NULL;
+	GOUndo *redo = NULL;
+	GSList *ranges;
 
-	paste_flags = 0;
-	if (clear_flags & CLEAR_VALUES)
-		paste_flags |= PASTE_CONTENTS;
-	if (clear_flags & CLEAR_FORMATS)
-		paste_flags |= PASTE_FORMATS;
-	if (clear_flags & CLEAR_COMMENTS)
-		paste_flags |= PASTE_COMMENTS;
-
-	me = g_object_new (CMD_CLEAR_TYPE, NULL);
-
-	me->clear_flags = clear_flags;
-	me->paste_flags = paste_flags;
-	me->old_contents = NULL;
-	me->selection = selection_get_ranges (sv, FALSE /* No intersection */);
+	/* We should first determine whether we break anything by clearing */
+	/* Check for array subdivision *//* Check for locked cells */
+	if (sheet_ranges_split_region (sheet, selection,
+				       GO_CMD_CONTEXT (wbc), _("Clear")) || 
+	    cmd_selection_is_locked_effective (sheet, selection, wbc, _("Clear"))) {
+		range_fragment_free (selection);
+		return TRUE;
+	}
 
-	me->cmd.sheet = sv_sheet (sv);
-	me->cmd.size = 1;  /* FIXME?  */
 
+	/* We now need to build the descriptor */
 	/* Collect clear types for descriptor */
 	if (clear_flags != (CLEAR_VALUES | CLEAR_FORMATS | CLEAR_COMMENTS)) {
 		GSList *m, *l = NULL;
 		types = g_string_new (NULL);
-
 		if (clear_flags & CLEAR_VALUES)
 			l = g_slist_append (l, g_string_new (_("contents")));
 		if (clear_flags & CLEAR_FORMATS)
 			l = g_slist_append (l, g_string_new (_("formats")));
 		if (clear_flags & CLEAR_COMMENTS)
 			l = g_slist_append (l, g_string_new (_("comments")));
-
 		/* Using a list for this may seem overkill, but is really the only
 		 * right way to do this
 		 */
@@ -1580,18 +1468,34 @@ cmd_selection_clear (WorkbookControl *wbc, int clear_flags)
 		g_slist_free (l);
 	} else
 		types = g_string_new (_("all"));
-
 	/* The range name string will automatically be truncated, we don't
 	 * need to truncate the "types" list because it will not grow
 	 * indefinitely
 	 */
-	names = undo_range_list_name (me->cmd.sheet, me->selection);
-	me->cmd.cmd_descriptor = g_strdup_printf (_("Clearing %s in %s"), types->str, names);
-
+	names = undo_range_list_name (sheet, selection);
+	descriptor = g_strdup_printf (_("Clearing %s in %s"), types->str, names);
 	g_free (names);
 	g_string_free (types, TRUE);
+	size = g_slist_length (selection);
 
-	return gnm_command_push_undo (wbc, G_OBJECT (me));
+	
+	/* We are now ready to build the redo and undo items */
+	for (ranges = selection; ranges != NULL ; ranges = ranges->next) {
+		GnmRange const *r = ranges->data;
+		GnmSheetRange *sr = gnm_sheet_range_new (sheet, r);
+
+		undo = go_undo_combine (undo, clipboard_copy_range_undo (sheet, r));
+		redo =  go_undo_combine 
+			(redo, sheet_clear_region_undo 
+			 (sr, clear_flags | CLEAR_NOCHECKARRAY | CLEAR_RECALC_DEPS));
+	}
+
+	range_fragment_free (selection);
+
+	result = cmd_generic_with_size (wbc, descriptor, size, undo, redo);
+	g_free (descriptor);
+
+	return result;
 }
 
 /******************************************************************/
diff --git a/src/sheet.c b/src/sheet.c
index 72aea45..048beba 100644
--- a/src/sheet.c
+++ b/src/sheet.c
@@ -4293,6 +4293,27 @@ sheet_clear_region (Sheet *sheet,
 	sheet_redraw_all (sheet, FALSE);
 }
 
+static void
+sheet_clear_region_cb (GnmSheetRange *sr, int *flags)
+{
+	sheet_clear_region (sr->sheet,
+			  sr->range.start.col, sr->range.start.row,
+			  sr->range.end.col, sr->range.end.row,
+			  *flags | CLEAR_NOCHECKARRAY, NULL);
+}
+
+GOUndo *sheet_clear_region_undo (GnmSheetRange *sr, int clear_flags)
+{
+	int *flags = g_new(int, 1);
+	*flags = clear_flags;
+	return go_undo_binary_new 
+		(sr, (gpointer)flags, 
+		 (GOUndoBinaryFunc) sheet_clear_region_cb, 
+		 (GFreeFunc) gnm_sheet_range_free, 
+		 (GFreeFunc) g_free);
+}
+
+
 /*****************************************************************************/
 
 void
diff --git a/src/sheet.h b/src/sheet.h
index d8b5745..a79d2f6 100644
--- a/src/sheet.h
+++ b/src/sheet.h
@@ -367,6 +367,9 @@ void  sheet_clear_region (Sheet *sheet,
 			  int end_col, int end_row,
 			  int clear_flags, GOCmdContext *cc);
 
+GOUndo *sheet_clear_region_undo (GnmSheetRange *sr, 
+				 int clear_flags);
+
 SheetView *sheet_get_view (Sheet const *sheet, WorkbookView const *wbv);
 
 #define SHEET_FOREACH_VIEW(sheet, view, code)					\



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]