[gnumeric] Merged cells: fix problem with clipping due to insert.



commit dd08dd638cd9bacf8269525e59eb24019adcd715
Author: Morten Welinder <terra gnome org>
Date:   Sat Dec 12 17:28:25 2015 -0500

    Merged cells: fix problem with clipping due to insert.
    
    We used to drop clipped merges on the floor.  That's not nice.

 ChangeLog         |    5 ++++
 NEWS              |    1 +
 src/sheet-merge.c |   64 +++++++++++++++++++++++++++++++++++++++++++++++-----
 src/sheet-merge.h |    4 ++-
 src/sheet.c       |    4 +-
 5 files changed, 68 insertions(+), 10 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 9f66e8d..7675891 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2015-12-12  Morten Welinder  <terra gnome org>
+
+       * src/sheet-merge.c (gnm_sheet_merge_relocate): Handling clipping
+       when the merge partially falls off the far end.
+
 2015-12-10  Morten Welinder  <terra gnome org>
 
        * src/gui-util.c (gnm_action_group_add_action): New wrapper to
diff --git a/NEWS b/NEWS
index ace042b..74a9ad1 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ Morten:
        * Fix problem with R.QHYPER
        * Add R.DRAYLEIGH, R.PRAYLEIGH, R.QRAYLEIGH.
        * Fix GUI translation problems.
+       * Fix bug with merged cells.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.24
diff --git a/src/sheet-merge.c b/src/sheet-merge.c
index 23d6f17..c080c8f 100644
--- a/src/sheet-merge.c
+++ b/src/sheet-merge.c
@@ -301,6 +301,34 @@ gnm_sheet_merge_is_corner (Sheet const *sheet, GnmCellPos const *pos)
        return g_hash_table_lookup (sheet->hash_merged, pos);
 }
 
+static void
+cb_restore_merge (Sheet *sheet, GSList *restore)
+{
+       GSList *l;
+       for (l = restore; l; l = l->next) {
+               GnmRange const *r = l->data;
+               GnmRange const *r2 = g_hash_table_lookup (sheet->hash_merged,
+                                                         &r->start);
+               if (r2 && range_equal (r, r2))
+                       continue;
+
+               // The only reason for r2 to be different from r is that we
+               // clipped.  Moving the clipped region back didn't restore
+               // the old state, so we'll have to remove the merge and
+               // create a new.
+               if (r2)
+                       gnm_sheet_merge_remove (sheet, r2, NULL);
+
+               gnm_sheet_merge_add (sheet, r, FALSE, NULL);
+       }
+}
+
+static void
+cb_restore_list_free (GSList *restore)
+{
+       g_slist_free_full (restore, g_free);
+}
+
 /**
  * gnm_sheet_merge_relocate:
  * @ri: Descriptor of what is moving.
@@ -308,9 +336,9 @@ gnm_sheet_merge_is_corner (Sheet const *sheet, GnmCellPos const *pos)
  * Shifts merged regions that need to move.
  */
 void
-gnm_sheet_merge_relocate (GnmExprRelocateInfo const *ri)
+gnm_sheet_merge_relocate (GnmExprRelocateInfo const *ri, GOUndo **pundo)
 {
-       GSList   *ptr, *copy, *to_move = NULL;
+       GSList   *ptr, *copy, *to_move = NULL, *restore = NULL;
        GnmRange         dest;
        gboolean change_sheets;
 
@@ -337,13 +365,26 @@ gnm_sheet_merge_relocate (GnmExprRelocateInfo const *ri)
        for (ptr = copy; ptr != NULL ; ptr = ptr->next ) {
                GnmRange const *r = ptr->data;
                if (range_contains (&ri->origin, r->start.col, r->start.row)) {
-                       GnmRange tmp = *r;
+                       GnmRange r2 = *r;
+
+                       if (pundo)
+                               restore = g_slist_prepend (restore, gnm_range_dup (r));
 
-                       /* Toss any merges that would be clipped. */
+                       /*
+                        * Toss any merges that would be clipped to a null
+                        * range or a single cell.
+                        */
                        gnm_sheet_merge_remove (ri->origin_sheet, r, NULL);
-                       if (!range_translate (&tmp, ri->target_sheet,
-                                             ri->col_offset, ri->row_offset))
-                               to_move = g_slist_prepend (to_move, gnm_range_dup (&tmp));
+                       range_translate (&r2, ri->target_sheet,
+                                        ri->col_offset, ri->row_offset);
+                       range_ensure_sanity (&r2, ri->target_sheet);
+
+                       if (range_is_singleton (&r2) ||
+                           r2.start.col > r2.end.col ||
+                           r2.start.row > r2.end.row)
+                               continue;
+
+                       to_move = g_slist_prepend (to_move, gnm_range_dup (&r2));
                } else if (!change_sheets &&
                           range_contains (&dest, r->start.col, r->start.row))
                        gnm_sheet_merge_remove (ri->origin_sheet, r, NULL);
@@ -357,6 +398,15 @@ gnm_sheet_merge_relocate (GnmExprRelocateInfo const *ri)
                g_free (dest);
        }
        g_slist_free (to_move);
+
+       if (restore) {
+               GOUndo *u = go_undo_binary_new
+                       (ri->origin_sheet, restore,
+                        (GOUndoBinaryFunc)cb_restore_merge,
+                        NULL,
+                        (GFreeFunc)cb_restore_list_free);
+               *pundo = go_undo_combine (*pundo, u);
+       }
 }
 
 /**
diff --git a/src/sheet-merge.h b/src/sheet-merge.h
index a4e1275..e985c2f 100644
--- a/src/sheet-merge.h
+++ b/src/sheet-merge.h
@@ -3,6 +3,7 @@
 # define _GNM_SHEET_MERGE_H_
 
 #include "gnumeric.h"
+#include <goffice/goffice.h>
 
 G_BEGIN_DECLS
 
@@ -16,7 +17,8 @@ gboolean     gnm_sheet_merge_remove           (Sheet *sheet,
 GSList      *gnm_sheet_merge_get_overlap       (Sheet const *sheet, GnmRange const *r);
 GnmRange const *gnm_sheet_merge_contains_pos   (Sheet const *sheet, GnmCellPos const *pos);
 GnmRange const *gnm_sheet_merge_is_corner      (Sheet const *sheet, GnmCellPos const *pos);
-void        gnm_sheet_merge_relocate           (GnmExprRelocateInfo const *ri);
+void        gnm_sheet_merge_relocate           (GnmExprRelocateInfo const *ri,
+                                                GOUndo **pundo);
 void        gnm_sheet_merge_find_container     (Sheet const *sheet,
                                                 GnmRange *r);
 void        gnm_sheet_merge_get_adjacent       (Sheet const *sheet,
diff --git a/src/sheet.c b/src/sheet.c
index f5e139a..2707633 100644
--- a/src/sheet.c
+++ b/src/sheet.c
@@ -5076,7 +5076,7 @@ sheet_insdel_colrow (Sheet *sheet, int pos, int count,
        sheet_objects_relocate (&reloc_info, FALSE, pundo);
 
        /* 9. Move merges.  */
-       gnm_sheet_merge_relocate (&reloc_info);
+       gnm_sheet_merge_relocate (&reloc_info, pundo);
 
        /* 10. Move filters.  */
        gnm_sheet_filter_insdel_colrow (sheet, is_cols, is_insert, pos, count, pundo);
@@ -5367,7 +5367,7 @@ sheet_move_range (GnmExprRelocateInfo const *rinfo,
 
        /* 7. Move objects in the range */
        sheet_objects_relocate (rinfo, TRUE, pundo);
-       gnm_sheet_merge_relocate (rinfo);
+       gnm_sheet_merge_relocate (rinfo, pundo);
 
        /* 8. Notify sheet of pending update */
        sheet_flag_recompute_spans (rinfo->origin_sheet);


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