[gnumeric] .gnumeric: if we see a shared array formula, fix it.



commit d78f0b632330554ab91ba6cd92c4261eebbf397e
Author: Morten Welinder <terra gnome org>
Date:   Wed Apr 25 18:23:32 2018 -0400

    .gnumeric: if we see a shared array formula, fix it.

 ChangeLog                      |    7 +++++
 NEWS                           |    1 +
 samples/formula-tests.gnumeric |  Bin 4330 -> 5051 bytes
 src/xml-sax-read.c             |   48 +++++++++++++++++++++++++---------------
 4 files changed, 38 insertions(+), 18 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0b79669..993aeed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2018-04-25  Morten Welinder  <terra gnome org>
+
+       * src/xml-sax-read.c (xml_sax_cell_content): Read shared array
+       expressions as we used to, but immediately unshare.  I had an old
+       file with such a thing and it not supposed to happen.  That
+       formula would likely have been created in early 2007.
+
 2018-04-24  Morten Welinder  <terra gnome org>
 
        * src/commands.c (cmd_paste_copy_impl): Simplify now that
diff --git a/NEWS b/NEWS
index af5b16f..ac9d265 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,7 @@ Morten:
        * Fix problem with image pasting.
        * Allow pasting an image into Gnumeric.  [#366816]
        * Full-column paste includes column width.  [#121722]
+       * Auto-fix shared array formulas in gnumeric files.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.39
diff --git a/samples/formula-tests.gnumeric b/samples/formula-tests.gnumeric
index c0b27cd..d408cf8 100644
Binary files a/samples/formula-tests.gnumeric and b/samples/formula-tests.gnumeric differ
diff --git a/src/xml-sax-read.c b/src/xml-sax-read.c
index 71a6418..e6c1a03 100644
--- a/src/xml-sax-read.c
+++ b/src/xml-sax-read.c
@@ -2115,7 +2115,7 @@ xml_sax_cell_content (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
        int const row = state->cell.row;
        int const array_cols = state->array_cols;
        int const array_rows = state->array_rows;
-       int const expr_id = state->expr_id;
+       int expr_id = state->expr_id;
        int const value_type = state->value_type;
        gboolean const seen_contents = state->seen_cell_contents;
        GOFormat *value_fmt = state->value_fmt;
@@ -2162,7 +2162,9 @@ xml_sax_cell_content (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
                g_return_if_fail (content[0] == '=');
                xml_cell_set_array_expr (state, cell, cc, content + 1,
                                         array_cols, array_rows);
-               goto done;
+               texpr = cell->base.texpr;
+               if (texpr) gnm_expr_top_ref (texpr);
+               goto store_shared;
        }
 
        // ----------------------------------------
@@ -2180,7 +2182,14 @@ xml_sax_cell_content (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
                texpr = g_hash_table_lookup (state->expr_map,
                                             GINT_TO_POINTER (expr_id));
 
-               if (!texpr) {
+               if (texpr && gnm_expr_top_is_array_corner (texpr)) {
+                       g_printerr ("Shared array formula -- how did that happen?\n");
+                       texpr = gnm_expr_top_new (gnm_expr_copy (texpr->expr));
+                       expr_id = -1;
+               } else if (texpr) {
+                       gnm_expr_top_ref (texpr);
+                       expr_id = -1;
+               } else {
                        char *msg = g_strdup_printf
                                ("Looking up shared expression id %d",
                                 expr_id);
@@ -2189,11 +2198,7 @@ xml_sax_cell_content (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
                        g_free (msg);
 
                        texpr = gnm_expr_top_new_constant (value_new_string_nocopy (s));
-                       g_hash_table_insert (state->expr_map,
-                                            GINT_TO_POINTER (expr_id),
-                                            (gpointer)texpr);
                }
-               gnm_expr_top_ref (texpr);
                goto assign_and_done;
        }
 
@@ -2249,13 +2254,11 @@ xml_sax_cell_content (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
                        gpointer id = GINT_TO_POINTER (expr_id);
                        GnmExprTop const *texpr0 =
                                g_hash_table_lookup (state->expr_map, id);
-                       if (!texpr0) {
-                               gnm_expr_top_ref (texpr);
-                               g_hash_table_insert (state->expr_map,
-                                                    id,
-                                                    (gpointer)texpr);
-                       } else if (!is_post_52_array)
-                               g_warning ("XML-IO : Duplicate shared expression");
+                       if (texpr0) {
+                               if (!is_post_52_array)
+                                       g_warning ("XML-IO: Duplicate shared expression");
+                               expr_id = -1;
+                       }
                }
        }
 
@@ -2264,17 +2267,26 @@ assign_and_done:
                v = value_new_empty ();
        if (cell) {
                // Regular case
-               if (texpr) {
+               if (texpr)
                        gnm_cell_set_expr_and_value (cell, texpr, v, TRUE);
-                       gnm_expr_top_unref (texpr);
-               } else
+               else
                        gnm_cell_set_value (cell, v);
        } else {
                // Clipboard case
-               cc->texpr = texpr;
+               cc->texpr = texpr ? gnm_expr_top_ref (texpr) : NULL;
                cc->val = v;
        }
 
+store_shared:
+       if (texpr) {
+               if (expr_id > 0)
+                       g_hash_table_insert (state->expr_map,
+                                            GINT_TO_POINTER (expr_id),
+                                            (gpointer)texpr);
+               else
+                       gnm_expr_top_unref (texpr);
+       }
+
 done:
        go_format_unref (value_fmt);
        g_free (value_result);


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