[gnumeric] Lotus: import extended floats.



commit f1dc6af0a9080d95171382cdd62d700ccdb89b85
Author: Morten Welinder <terra gnome org>
Date:   Thu Nov 6 10:18:35 2014 -0500

    Lotus: import extended floats.

 NEWS                            |    3 +++
 plugins/lotus-123/ChangeLog     |    5 +++++
 plugins/lotus-123/lotus-types.h |    1 +
 plugins/lotus-123/lotus.c       |   27 +++++++++++++++++++++++++++
 plugins/lotus-123/lotus.h       |    1 +
 5 files changed, 37 insertions(+), 0 deletions(-)
---
diff --git a/NEWS b/NEWS
index a7b80bc..3612af2 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,9 @@ Morten:
        * Plug leaks.
        * Pay more attention to union access rules.
 
+Thomas Kluyver:
+       * Fix import of extended floats from wk4 files.  [#739697]
+
 --------------------------------------------------------------------------
 Gnumeric 1.12.18
 
diff --git a/plugins/lotus-123/ChangeLog b/plugins/lotus-123/ChangeLog
index e7f6c5d..965dcb8 100644
--- a/plugins/lotus-123/ChangeLog
+++ b/plugins/lotus-123/ChangeLog
@@ -1,3 +1,8 @@
+2014-11-06  Morten Welinder  <terra gnome org>
+
+       * lotus.c (lotus_read_new): Handle extended floats.  Patch from
+       Thomas Kluyver, see bug 739679.
+
 2014-09-25  Morten Welinder <terra gnome org>
 
        * Release 1.12.18
diff --git a/plugins/lotus-123/lotus-types.h b/plugins/lotus-123/lotus-types.h
index dd33bba..a5af4ae 100644
--- a/plugins/lotus-123/lotus-types.h
+++ b/plugins/lotus-123/lotus-types.h
@@ -47,6 +47,7 @@
 #define LOTUS_ERRCELL                0x14
 #define LOTUS_NACELL                 0x15
 #define LOTUS_LABEL2                 0x16
+#define LOTUS_EXTENDED_FLOAT         0x17    /* wk4...  */
 #define LOTUS_SMALLNUM               0x18    /* wk3,wk4 */
 #define LOTUS_FORMULA3               0x19    /* wk3,wk4 */
 #define LOTUS_STYLE                  0x1b
diff --git a/plugins/lotus-123/lotus.c b/plugins/lotus-123/lotus.c
index 7687a7d..e3f74f9 100644
--- a/plugins/lotus-123/lotus.c
+++ b/plugins/lotus-123/lotus.c
@@ -905,6 +905,23 @@ lotus_smallnum (signed int d)
                return value_new_int (d >> 1);
 }
 
+GnmValue *
+lotus_extfloat (guint64 mant, guint16 signexp)
+{
+       int exp = (signexp & 0x7fff) - 16383;
+       int sign = (signexp & 0x8000) ? -1 : 1;
+       /* FIXME: Special values may indicate NaN, +/- inf */
+       /*
+        * NOTE: if gnm_float is "double", then passing the first argument
+        * to gnm_ldexp will perform rounding from 64-bit integer to
+        * 53-bit mantissa in a double.
+        *
+        * NOTE: the gnm_ldexp may under- or overflow.  That ought to do
+        * the right thing.
+        */
+       return lotus_value (sign * gnm_ldexp (mant, exp - 63));
+}
+
 static GnmValue *
 lotus_treal (const record_t *r, int ofs)
 {
@@ -1961,6 +1978,16 @@ lotus_read_new (LotusState *state, record_t *r)
                        break;
                }
 
+               case LOTUS_EXTENDED_FLOAT: CHECK_RECORD_SIZE (>= 14) {
+                       int row = GSF_LE_GET_GUINT16 (r->data);
+                       Sheet *sheet = lotus_get_sheet (state->wb, r->data[2]);
+                       int col = r->data[3];
+                       GnmValue *v = lotus_extfloat (GSF_LE_GET_GUINT64 (r->data + 4),
+                                                     GSF_LE_GET_GUINT16 (r->data + 12));
+                       (void)insert_value (state, sheet, col, row, v);
+                       break;
+               }
+
                case LOTUS_STYLE: CHECK_RECORD_SIZE (>= 2) {
                        guint16 subtype = GSF_LE_GET_GUINT16 (r->data);
                        switch (subtype) {
diff --git a/plugins/lotus-123/lotus.h b/plugins/lotus-123/lotus.h
index 4526633..3649ad0 100644
--- a/plugins/lotus-123/lotus.h
+++ b/plugins/lotus-123/lotus.h
@@ -38,6 +38,7 @@ GnmValue *lotus_new_string (gchar const *data, int def_group);
 gboolean  lotus_read      (LotusState *state);
 GnmValue *lotus_unpack_number (guint32 u);
 GnmValue *lotus_smallnum (signed int d);
+GnmValue *lotus_extfloat (guint64 mant, guint16 signexp);
 
 void lmbcs_init (void);
 void lmbcs_shutdown (void);


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