[gnumeric] xls: improve handling of long strings in formulas.



commit 03266296fe1c0d681f826b4b61a1c97be8e1ea24
Author: Morten Welinder <terra gnome org>
Date:   Fri Feb 21 16:13:28 2014 -0500

    xls: improve handling of long strings in formulas.
    
    The format cannot handle strings longer than 255 characters so do a creative
    rewrite with "&".

 NEWS                             |    1 +
 plugins/excel/ChangeLog          |   11 +++++++++++
 plugins/excel/ms-biff.c          |    1 +
 plugins/excel/ms-excel-write.c   |   28 +++++++++++++++++++++-------
 plugins/excel/ms-formula-write.c |   33 ++++++++++++++++++++++++++++++++-
 5 files changed, 66 insertions(+), 8 deletions(-)
---
diff --git a/NEWS b/NEWS
index e02b1fb..7a8762c 100644
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,7 @@ Morten:
        * Fix xlsx export of underlines.
        * Fix BIFF8 export of diagonal borders.
        * Export headers and footers to xlsx.  [Part of #724516]
+       * Fix xls export of long strings in formulas.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.11
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index 42cdc10..e6ba7ba 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,3 +1,14 @@
+2014-02-21  Morten Welinder  <terra gnome org>
+
+       * ms-biff.c (ms_biff_query_next): Handle CONTINUE record for
+       BIFF_FORMULA_v0 too.
+
+       * ms-excel-write.c (excel_write_string): Improve handling of
+       string overflow.
+
+       * ms-formula-write.c (write_string): Split long strings into 255
+       character chunks: ("s1"&"s2"&...)
+
 2014-02-20  Morten Welinder  <terra gnome org>
 
        * xlsx-write.c (xlsx_write_print_info): First stab at exporting
diff --git a/plugins/excel/ms-biff.c b/plugins/excel/ms-biff.c
index 52a8739..eda7b90 100644
--- a/plugins/excel/ms-biff.c
+++ b/plugins/excel/ms-biff.c
@@ -508,6 +508,7 @@ ms_biff_query_next (BiffQuery *q)
        switch (q->opcode) {
        case BIFF_LABEL_v0:
        case BIFF_LABEL_v2:
+       case BIFF_FORMULA_v0:
                auto_continue = TRUE;
                break;
        case BIFF_CONTINUE:
diff --git a/plugins/excel/ms-excel-write.c b/plugins/excel/ms-excel-write.c
index 5a0fba9..6c6323f 100644
--- a/plugins/excel/ms-excel-write.c
+++ b/plugins/excel/ms-excel-write.c
@@ -313,10 +313,6 @@ excel_write_string (BiffPut *bp, WriteStringFlags flags,
        if (char_len != byte_len || (flags & STR_SUPPRESS_HEADER)) {
                char *tmp;
 
-               /* TODO : think about what to do with LEN_IN_BYTES */
-               if ((flags & STR_LENGTH_MASK) == STR_ONE_BYTE_LENGTH &&
-                   char_len > 0xff)
-                       char_len = 0xff;
                out_bytes = char_len * 2;
 
                /* 2 in case we null terminate, and up to 4 for the length */
@@ -358,9 +354,27 @@ excel_write_string (BiffPut *bp, WriteStringFlags flags,
                                g_warning (_("This is somewhat corrupt.\n"
                                             "We already wrote a length for a string that is being truncated 
due to encoding problems."));
                        break;
-               case STR_ONE_BYTE_LENGTH:  GSF_LE_SET_GUINT8  (bp->buf, output_len); break;
-               case STR_TWO_BYTE_LENGTH:  GSF_LE_SET_GUINT16 (bp->buf, output_len); break;
-               case STR_FOUR_BYTE_LENGTH: GSF_LE_SET_GUINT32 (bp->buf, output_len); break;
+               case STR_ONE_BYTE_LENGTH:
+                       if (output_len > 255) {
+                               g_printerr ("Truncating string of %u %s\n",
+                                           output_len,
+                                           (flags & STR_LEN_IN_BYTES) ? "bytes" : "characters");
+                               output_len = 255;
+                       }
+                       GSF_LE_SET_GUINT8 (bp->buf, output_len);
+                       break;
+               case STR_TWO_BYTE_LENGTH:
+                       if (output_len > 65535) {
+                               g_printerr ("Truncating string of %u %s\n",
+                                           output_len,
+                                           (flags & STR_LEN_IN_BYTES) ? "bytes" : "characters");
+                               output_len = 65535;
+                       }
+                       GSF_LE_SET_GUINT16 (bp->buf, output_len);
+                       break;
+               case STR_FOUR_BYTE_LENGTH:
+                       GSF_LE_SET_GUINT32 (bp->buf, output_len);
+                       break;
                }
 
                output_len = out_bytes;
diff --git a/plugins/excel/ms-formula-write.c b/plugins/excel/ms-formula-write.c
index 000cb09..10df2d8 100644
--- a/plugins/excel/ms-formula-write.c
+++ b/plugins/excel/ms-formula-write.c
@@ -357,13 +357,44 @@ write_cellref_v8 (PolishData *pd, GnmCellRef const *ref,
 }
 
 static void
-write_string (PolishData *pd, gchar const *txt)
+write_string1 (PolishData *pd, gchar const *txt)
 {
        push_guint8 (pd, FORMULA_PTG_STR);
        excel_write_string (pd->ewb->bp, STR_ONE_BYTE_LENGTH, txt);
 }
 
 static void
+write_string (PolishData *pd, gchar const *txt)
+{
+       size_t i, n = 0, len = g_utf8_strlen (txt, -1);
+       const char *p = txt;
+
+       for (i = 0; n == 0 || i < len; ) {
+               if (len - i <= 255) {
+                       write_string1 (pd, p);
+                       i = len;
+               } else {
+                       const char *endcut = g_utf8_offset_to_pointer (p, 255);
+                       size_t cutlen = endcut - p;
+                       char *cut = g_memdup (p, cutlen + 1);
+                       cut[cutlen] = 0;
+                       write_string1 (pd, cut);
+                       g_free (cut);
+
+                       p = endcut;
+                       i += 255;
+               }
+
+               if (n > 0)
+                       push_guint8 (pd, FORMULA_PTG_CONCAT);
+               n++;
+       }
+
+       if (n > 1)
+               push_guint8 (pd, FORMULA_PTG_PAREN);
+}
+
+static void
 excel_formula_write_CELLREF (PolishData *pd, GnmCellRef const *ref,
                             Sheet *sheet_b, XLOpType target_type)
 {


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