[gnumeric] xls: fix import of names containing array constants.



commit d7fa62bcd3d2edf9d0d698afa860ab62a8c031ab
Author: Morten Welinder <terra gnome org>
Date:   Mon Apr 15 20:07:40 2013 -0400

    xls: fix import of names containing array constants.
    
    At the same time, fix import of array constants containing booleans,
    errors, or empties.

 NEWS                             |  2 ++
 plugins/excel/ChangeLog          | 10 ++++++++++
 plugins/excel/ms-excel-read.c    | 19 ++++++++++++++-----
 plugins/excel/ms-formula-read.c  |  7 +++++++
 plugins/excel/ms-formula-write.c |  6 +++++-
 5 files changed, 38 insertions(+), 6 deletions(-)
---
diff --git a/NEWS b/NEWS
index b8dfed7..21c327c 100644
--- a/NEWS
+++ b/NEWS
@@ -43,6 +43,8 @@ Morten:
        * Add new test for a collection of special functions.
        * Fix xls writing of non-ascii names.  [#608780]
        * Improve entry of non-locale currency amounts.  [#577768]
+       * Fix XL import of names with array constants.  [#654211]
+       * Fix XL import of booleans/error/empties in array constants.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.1
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index abb3b9f..510eca4 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,3 +1,13 @@
+2013-04-15  Morten Welinder  <terra gnome org>
+
+       * ms-formula-write.c (write_arrays): Handle empty values properly.
+
+       * ms-formula-read.c (excel_parse_formula1): Handle empty values in
+       array constants.  Fix handling of booleans and errors in array
+       constants.
+       (excel_parse_name): Add argument for array data length.  All
+       callers changed.  Fixes #654211.
+
 2013-04-14  Morten Welinder  <terra gnome org>
 
        * ms-excel-write.c (excel_write_NAME): Store the name's length in
diff --git a/plugins/excel/ms-excel-read.c b/plugins/excel/ms-excel-read.c
index 1d0312f..afa8ceb 100644
--- a/plugins/excel/ms-excel-read.c
+++ b/plugins/excel/ms-excel-read.c
@@ -3644,6 +3644,7 @@ excel_builtin_name (guint8 const *ptr)
 static GnmNamedExpr *
 excel_parse_name (GnmXLImporter *importer, Sheet *sheet, char *name,
                  guint8 const *expr_data, unsigned expr_len,
+                 unsigned array_data_len,
                  gboolean link_to_container,
                  GnmNamedExpr *stub)
 {
@@ -3661,7 +3662,8 @@ excel_parse_name (GnmXLImporter *importer, Sheet *sheet, char *name,
                texpr = gnm_expr_top_new_constant (value_new_error_NAME (NULL));
        } else {
                texpr = excel_parse_formula (&importer->container, NULL, 0, 0,
-                                            expr_data, expr_len, 0 /* FIXME? */,
+                                            expr_data, expr_len,
+                                            array_data_len,
                                             TRUE, NULL);
 
                if (texpr == NULL) {
@@ -3781,6 +3783,7 @@ excel_read_EXTERNNAME (BiffQuery *q, MSContainer *container)
        MsBiffVersion const ver = container->importer->ver;
        GnmNamedExpr *nexpr = NULL;
        char *name = NULL;
+       unsigned array_data_len = 0;  /* Is this always true? */
 
        d (2, {
                        g_printerr ("EXTERNNAME\n");
@@ -3822,19 +3825,22 @@ excel_read_EXTERNNAME (BiffQuery *q, MSContainer *container)
                                       name ? name : "NULL");
 
                nexpr = excel_parse_name (container->importer, NULL,
-                                         name, expr_data, expr_len, FALSE, NULL);
+                                         name, expr_data, expr_len,
+                                         array_data_len, FALSE, NULL);
        } else if (ver >= MS_BIFF_V5) {
                XL_CHECK_CONDITION (q->length >= 7);
 
                name = excel_biff_text_1 (container->importer, q, 6);
                nexpr = excel_parse_name (container->importer, NULL,
-                                         name, NULL, 0, FALSE, NULL);
+                                         name, NULL, 0, array_data_len,
+                                         FALSE, NULL);
        } else {
                XL_CHECK_CONDITION (q->length >= 3);
 
                name = excel_biff_text_1 (container->importer, q, 2);
                nexpr = excel_parse_name (container->importer, NULL,
-                                         name, NULL, 0, FALSE, NULL);
+                                         name, NULL, 0, array_data_len,
+                                         FALSE, NULL);
        }
 
        /* nexpr is potentially NULL if there was an error */
@@ -3951,6 +3957,7 @@ excel_read_NAME (BiffQuery *q, GnmXLImporter *importer, ExcelReadSheet *esheet)
        data += name_len;
 
        if (name != NULL) {
+               unsigned array_data_len;
                Sheet *sheet = NULL;
                d (1, g_printerr ("NAME=%s, sheet_index=%d  flags=0x%x\n",
                                  name, sheet_index, flags););
@@ -3976,8 +3983,10 @@ excel_read_NAME (BiffQuery *q, GnmXLImporter *importer, ExcelReadSheet *esheet)
                        nexpr = g_ptr_array_index (importer->names, importer->num_name_records);
 
                XL_NEED_BYTES (expr_len);
+               array_data_len = expr_len ? q->length - (data - q->data) : 0;
                nexpr = excel_parse_name (importer, sheet,
-                                         name, data, expr_len, TRUE, nexpr);
+                                         name, data, expr_len,
+                                         array_data_len, TRUE, nexpr);
                g_free (name);
                data += expr_len;
 
diff --git a/plugins/excel/ms-formula-read.c b/plugins/excel/ms-formula-read.c
index 44992fa..b85da80 100644
--- a/plugins/excel/ms-formula-read.c
+++ b/plugins/excel/ms-formula-read.c
@@ -1343,6 +1343,11 @@ excel_parse_formula1 (MSContainer const *container,
                                        }
 #endif
                                        switch (val_type) {
+                                       case 0:
+                                               CHECK_FORMULA_ARRAY_LEN(8);
+                                               elem = value_new_empty ();
+                                               array_data += 8;
+                                               break;
                                        case 1:
                                                CHECK_FORMULA_ARRAY_LEN(8);
                                                elem = value_new_float (gsf_le_get_double (array_data));
@@ -1383,10 +1388,12 @@ excel_parse_formula1 (MSContainer const *container,
                                        case 4:
                                                CHECK_FORMULA_ARRAY_LEN(8);
                                                elem = value_new_bool (array_data[0] ? TRUE : FALSE);
+                                               array_data += 8;
                                                break;
                                        case 16:
                                                CHECK_FORMULA_ARRAY_LEN(8);
                                                elem = xls_value_new_err (NULL, array_data[0]);
+                                               array_data += 8;
                                                break;
 
                                        default :
diff --git a/plugins/excel/ms-formula-write.c b/plugins/excel/ms-formula-write.c
index 6f43d3f..1dc50df 100644
--- a/plugins/excel/ms-formula-write.c
+++ b/plugins/excel/ms-formula-write.c
@@ -942,7 +942,11 @@ write_arrays (PolishData *pd)
                        for (x = 0; x < array->v_array.x; x++) {
                                GnmValue const *v = array->v_array.vals[x][y];
 
-                               if (VALUE_IS_BOOLEAN (v)) {
+                               if (VALUE_IS_EMPTY (v)) {
+                                       push_guint8 (pd, 0);
+                                       push_guint32 (pd, 0);
+                                       push_guint32 (pd, 0);
+                               } else if (VALUE_IS_BOOLEAN (v)) {
                                        push_guint8 (pd, 4);
                                        push_guint32 (pd, v->v_bool.val ? 1 : 0);
                                        push_guint32 (pd, 0);


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