[gnumeric] xls: reverse ("aaa"&""bbb"&...) hack for long strings when we read



commit 5803bf7f31341faa3ce3f1536f6d0d77ea528b8e
Author: Morten Welinder <terra gnome org>
Date:   Sat Feb 22 15:31:04 2014 -0500

    xls: reverse ("aaa"&""bbb"&...) hack for long strings when we read
    
    This way, formulae with string constants longer than 255 characters will
    appear to save perfectly fine in xls format.

 plugins/excel/ChangeLog         |    3 +
 plugins/excel/ms-formula-read.c |  100 +++++++++++++++++++++++++++++----------
 2 files changed, 78 insertions(+), 25 deletions(-)
---
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index 6e2f843..8319f02 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,5 +1,8 @@
 2014-02-22  Morten Welinder  <terra gnome org>
 
+       * ms-formula-read.c (undo_save_hacks): Undo the
+       long-string-constant hack in write_string.
+
        * ms-excel-write.c (excel_convert_string): New function.
        (excel_write_comments_biff7): Avoid infinite loop when a comment
        contains characters that cannot be represented in the codepage.
diff --git a/plugins/excel/ms-formula-read.c b/plugins/excel/ms-formula-read.c
index fa7b58e..5af84e9 100644
--- a/plugins/excel/ms-formula-read.c
+++ b/plugins/excel/ms-formula-read.c
@@ -795,6 +795,48 @@ make_function (GnmExprList **stack, int fn_idx, int numargs, Workbook *wb)
        return FALSE;
 }
 
+static int
+is_string_concats (GnmExpr const *e, GString *accum)
+{
+       GnmValue const *v = gnm_expr_get_constant (e);
+       if (v && VALUE_IS_STRING (v)) {
+               if (accum)
+                       g_string_append (accum, value_peek_string (v));
+               return 1;
+       }
+
+       if (GNM_EXPR_GET_OPER(e) == GNM_EXPR_OP_CAT) {
+               int l, r;
+
+               l = is_string_concats (e->binary.value_a, accum);
+               if (!l)
+                       return 0;
+
+               r = is_string_concats (e->binary.value_b, accum);
+               if (!r)
+                       return 0;
+
+               return l + r;
+       }
+
+       return 0;
+}
+
+static GnmExpr const *
+undo_save_hacks (GnmExpr const *e)
+{
+       if (GNM_EXPR_GET_OPER(e) == GNM_EXPR_OP_PAREN &&
+           is_string_concats (e->unary.value, NULL) >= 2) {
+               GString *accum = g_string_new (NULL);
+               (void)is_string_concats (e->unary.value, accum);
+               gnm_expr_free (e);
+               return gnm_expr_new_constant (value_new_string_nocopy (g_string_free (accum, FALSE)));
+       }
+
+       return e;
+}
+
+
 /**
  * ms_excel_dump_cellname : internal utility to dump the current location safely.
  */
@@ -1059,7 +1101,7 @@ excel_parse_formula1 (MSContainer const *container,
                        break;
                }
 
-               case FORMULA_PTG_TBL : {
+               case FORMULA_PTG_TBL: {
                        XLDataTable *dt;
                        GnmCellPos top_left;
 
@@ -1088,15 +1130,19 @@ excel_parse_formula1 (MSContainer const *container,
                        return NULL;
                }
 
-               case FORMULA_PTG_ADD :  case FORMULA_PTG_SUB :
-               case FORMULA_PTG_MULT : case FORMULA_PTG_DIV :
-               case FORMULA_PTG_EXP :
-               case FORMULA_PTG_CONCAT :
-               case FORMULA_PTG_LT : case FORMULA_PTG_LTE :
-               case FORMULA_PTG_EQUAL :
-               case FORMULA_PTG_GTE : case FORMULA_PTG_GT :
-               case FORMULA_PTG_NOT_EQUAL :
-               case FORMULA_PTG_INTERSECT : {
+               case FORMULA_PTG_ADD:
+               case FORMULA_PTG_SUB:
+               case FORMULA_PTG_MULT:
+               case FORMULA_PTG_DIV:
+               case FORMULA_PTG_EXP:
+               case FORMULA_PTG_CONCAT:
+               case FORMULA_PTG_LT:
+               case FORMULA_PTG_LTE:
+               case FORMULA_PTG_EQUAL:
+               case FORMULA_PTG_GTE:
+               case FORMULA_PTG_GT:
+               case FORMULA_PTG_NOT_EQUAL:
+               case FORMULA_PTG_INTERSECT: {
                        GnmExpr const *r = parse_list_pop (&stack);
                        GnmExpr const *l = parse_list_pop (&stack);
                        parse_list_push (&stack, gnm_expr_new_binary (
@@ -1106,7 +1152,7 @@ excel_parse_formula1 (MSContainer const *container,
                        break;
                }
 
-               case FORMULA_PTG_RANGE : {
+               case FORMULA_PTG_RANGE: {
                        GnmExpr const *r = parse_list_pop (&stack);
                        GnmExpr const *l = parse_list_pop (&stack);
                        parse_list_push (&stack,
@@ -1114,7 +1160,7 @@ excel_parse_formula1 (MSContainer const *container,
                        break;
                }
 
-               case FORMULA_PTG_UNION : {
+               case FORMULA_PTG_UNION: {
                        GnmExpr const *r = parse_list_pop (&stack);
                        GnmExpr const *l = parse_list_pop (&stack);
 
@@ -1138,21 +1184,25 @@ excel_parse_formula1 (MSContainer const *container,
                        break;
                }
 
-               case FORMULA_PTG_U_PLUS :
-               case FORMULA_PTG_U_MINUS :
-               case FORMULA_PTG_PERCENT :
-               case FORMULA_PTG_PAREN:
-                       parse_list_push (&stack, gnm_expr_new_unary (
-                               unary_ops [ptgbase - FORMULA_PTG_U_PLUS],
-                               parse_list_pop (&stack)));
+               case FORMULA_PTG_U_PLUS:
+               case FORMULA_PTG_U_MINUS:
+               case FORMULA_PTG_PERCENT:
+               case FORMULA_PTG_PAREN: {
+                       GnmExpr const *e = gnm_expr_new_unary
+                               (unary_ops [ptgbase - FORMULA_PTG_U_PLUS],
+                                parse_list_pop (&stack));
+                       e = undo_save_hacks (e);
+                       parse_list_push (&stack, e);
                        break;
+               }
 
                case FORMULA_PTG_MISSARG:
                        parse_list_push_raw (&stack, value_new_empty ());
                        ptg_length = 0;
                        break;
 
-               case FORMULA_PTG_ATTR : { /* FIXME: not fully implemented */
+               case FORMULA_PTG_ATTR: {
+                       /* FIXME: not fully implemented */
                        guint8 grbit;
                        guint16 w;
                        if (ver >= MS_BIFF_V3) {
@@ -1269,7 +1319,7 @@ excel_parse_formula1 (MSContainer const *container,
                        break;
                }
 
-               case FORMULA_PTG_EXTENDED : { /* Extended Ptgs for Biff8 */
+               case FORMULA_PTG_EXTENDED: { /* Extended Ptgs for Biff8 */
                        CHECK_FORMULA_LEN(1);
                        switch ((eptg = GSF_LE_GET_GUINT8 (cur))) {
                        default :
@@ -1370,7 +1420,7 @@ excel_parse_formula1 (MSContainer const *container,
                }
                break;
 
-               case FORMULA_PTG_ARRAY : {
+               case FORMULA_PTG_ARRAY: {
                        unsigned cols, rows;
                        unsigned lpx, lpy;
                        GnmValue *v = NULL;
@@ -1640,7 +1690,7 @@ excel_parse_formula1 (MSContainer const *container,
                        CHECK_FORMULA_LEN(2);
                        break;
 
-               case FORMULA_PTG_NAME_X : {
+               case FORMULA_PTG_NAME_X: {
                        guint16 name_idx; /* 1 based */
                        GPtrArray    *names = NULL;
                        GnmExpr const*name;
@@ -1711,7 +1761,7 @@ excel_parse_formula1 (MSContainer const *container,
                }
                break;
 
-               case FORMULA_PTG_REF_3D : { /* see S59E2B.HTM */
+               case FORMULA_PTG_REF_3D: { /* see S59E2B.HTM */
                        GnmCellRef first, last;
                        if (ver >= MS_BIFF_V8) {
                                CHECK_FORMULA_LEN(6);
@@ -1738,7 +1788,7 @@ excel_parse_formula1 (MSContainer const *container,
                        break;
                }
 
-               case FORMULA_PTG_AREA_3D : { /* see S59E2B.HTM */
+               case FORMULA_PTG_AREA_3D: { /* see S59E2B.HTM */
                        /* See comments in FORMULA_PTG_REF_3D for correct handling of external references */
                        GnmCellRef first, last;
 


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