lotus.c (gnumeric-1.12.49.tar.xz) | : | lotus.c (gnumeric-1.12.50.tar.xz) | ||
---|---|---|---|---|
/** | /** | |||
* lotus.c: Lotus 123 support for Gnumeric | * lotus.c: Lotus 123 support for Gnumeric | |||
* | * | |||
* Authors: | * Authors: | |||
* See: README | * See: README | |||
* Michael Meeks (mmeeks@gnu.org) | * Michael Meeks (mmeeks@gnu.org) | |||
* Stephen Wood (saw@genhomepage.com) | * Stephen Wood (saw@genhomepage.com) | |||
* Morten Welinder (terra@gnome.org) | * Morten Welinder (terra@gnome.org) | |||
* | ||||
* Docs are scarce. | ||||
* https://www.mettalogic.co.uk/tim/l123/l123r4.html | ||||
**/ | **/ | |||
#include <gnumeric-config.h> | #include <gnumeric-config.h> | |||
#include <gnumeric.h> | #include <gnumeric.h> | |||
#include "lotus.h" | #include "lotus.h" | |||
#include "lotus-types.h" | #include "lotus-types.h" | |||
#include "lotus-formula.h" | #include "lotus-formula.h" | |||
#include <workbook.h> | #include <workbook.h> | |||
#include <cell.h> | #include <cell.h> | |||
#include <expr.h> | #include <expr.h> | |||
#include <value.h> | #include <value.h> | |||
#include <gutils.h> | #include <gutils.h> | |||
#include <ranges.h> | #include <ranges.h> | |||
#include <mstyle.h> | #include <mstyle.h> | |||
#include <style-color.h> | #include <style-color.h> | |||
#include <style-font.h> | #include <style-font.h> | |||
#include <parse-util.h> | #include <parse-util.h> | |||
#include <sheet-style.h> | #include <sheet-style.h> | |||
#include <sheet-object-cell-comment.h> | #include <sheet-object-cell-comment.h> | |||
#include <sheet-view.h> | ||||
#include <selection.h> | ||||
#include <gsf/gsf-input.h> | #include <gsf/gsf-input.h> | |||
#include <gsf/gsf-utils.h> | #include <gsf/gsf-utils.h> | |||
#include <gsf/gsf-msole-utils.h> | #include <gsf/gsf-msole-utils.h> | |||
#include <string.h> | #include <string.h> | |||
#define LOTUS_DEBUG 0 | #define LOTUS_DEBUG 0 | |||
#undef DEBUG_RLDB | #undef DEBUG_RLDB | |||
#undef DEBUG_STYLE | #undef DEBUG_STYLE | |||
#undef DEBUG_FORMAT | #undef DEBUG_FORMAT | |||
skipping to change at line 932 | skipping to change at line 937 | |||
: lotus_value ((gnm_float)mant / -f); | : lotus_value ((gnm_float)mant / -f); | |||
} else | } else | |||
return value_new_int (d >> 1); | return value_new_int (d >> 1); | |||
} | } | |||
static GnmValue * | static GnmValue * | |||
lotus_extfloat (guint64 mant, guint16 signexp) | lotus_extfloat (guint64 mant, guint16 signexp) | |||
{ | { | |||
int exp = (signexp & 0x7fff) - 16383; | int exp = (signexp & 0x7fff) - 16383; | |||
int sign = (signexp & 0x8000) ? -1 : 1; | int sign = (signexp & 0x8000) ? -1 : 1; | |||
/* FIXME: Special values may indicate NaN, +/- inf */ | ||||
/* | /* | |||
* NOTE: if gnm_float is "double", then passing the first argument | * NOTE: if gnm_float is "double", then passing the first argument | |||
* to gnm_ldexp will perform rounding from 64-bit integer to | * to gnm_ldexp will perform rounding from 64-bit integer to | |||
* 53-bit mantissa in a double. | * 53-bit mantissa in a double. | |||
* | * | |||
* NOTE: the gnm_ldexp may under- or overflow. That ought to do | * NOTE: the gnm_ldexp may under- or overflow. That ought to do | |||
* the right thing. | * the right thing. | |||
*/ | */ | |||
return lotus_value (sign * gnm_ldexp (mant, exp - 63)); | return lotus_value (sign * gnm_ldexp (mant, exp - 63)); | |||
} | } | |||
GnmValue * | GnmValue * | |||
lotus_load_treal (gconstpointer p) | lotus_load_treal (gconstpointer p) | |||
{ | { | |||
const guint8 *pc = p; | ||||
if (pc[9] == 0xff && pc[8] == 0xff) { | ||||
switch (pc[7]) { | ||||
case 0x00: return value_new_empty (); | ||||
case 0xc0: return value_new_error_VALUE (NULL); | ||||
case 0xd0: return value_new_error_NA (NULL); | ||||
case 0xe0: return value_new_string (""); // Supplied in FORMULAST | ||||
RING | ||||
} | ||||
} | ||||
return lotus_extfloat (GSF_LE_GET_GUINT64 (p), | return lotus_extfloat (GSF_LE_GET_GUINT64 (p), | |||
GSF_LE_GET_GUINT16 ((const char *)p + 8)); | GSF_LE_GET_GUINT16 (pc + 8)); | |||
} | } | |||
static GnmValue * | static GnmValue * | |||
lotus_treal (const record_t *r, int ofs) | lotus_treal (const record_t *r, int ofs) | |||
{ | { | |||
g_return_val_if_fail (ofs + 10 <= r->len, NULL); | g_return_val_if_fail (ofs + 10 <= r->len, NULL); | |||
return lotus_load_treal (r->data + ofs); | return lotus_load_treal (r->data + ofs); | |||
} | } | |||
skipping to change at line 1952 | skipping to change at line 1967 | |||
do { | do { | |||
switch (r->type) { | switch (r->type) { | |||
case LOTUS_BOF: CHECK_RECORD_SIZE (>= 18) { | case LOTUS_BOF: CHECK_RECORD_SIZE (>= 18) { | |||
state->lmbcs_group = GSF_LE_GET_GUINT8 (r->data + 16); | state->lmbcs_group = GSF_LE_GET_GUINT8 (r->data + 16); | |||
break; | break; | |||
} | } | |||
case LOTUS_EOF: | case LOTUS_EOF: | |||
goto done; | goto done; | |||
case LOTUS_SHEETCELLPTR: CHECK_RECORD_SIZE (== 16) { | ||||
Sheet *sheet = lotus_get_sheet (state->wb, r->data[0]); | ||||
int row = GSF_LE_GET_GUINT16 (r->data + 4); | ||||
int col = r->data[6]; | ||||
int left = r->data[7]; | ||||
int top = GSF_LE_GET_GUINT16 (r->data + 8); | ||||
SheetView *sv = sheet_get_view (sheet, state->wbv); | ||||
GnmCellPos edit; | ||||
edit.col = col; | ||||
edit.row = row; | ||||
sv_selection_set (sv, &edit, col, row, col, row); | ||||
gnm_sheet_view_set_initial_top_left (sv, left, top); | ||||
break; | ||||
} | ||||
case LOTUS_SHEETLAYOUT: CHECK_RECORD_SIZE (== 5) { | ||||
// Despite the name, this stores default col width | ||||
Sheet *sheet = lotus_get_sheet (state->wb, r->data[0]); | ||||
guint8 chars = r->data[4]; | ||||
// Very approximate | ||||
double size = lotus_twips_to_points (chars * (20 * 72 / 1 | ||||
1)); | ||||
sheet_col_set_default_size_pts (sheet, size); | ||||
break; | ||||
} | ||||
case LOTUS_COLW4: CHECK_RECORD_SIZE (>= 4) { | ||||
Sheet *sheet = lotus_get_sheet (state->wb, r->data[0]); | ||||
int i, n = (r->len - 4) / 2; | ||||
for (i = 0; i < n; i++) { | ||||
guint8 col = r->data[4 + 2 * i]; | ||||
guint8 chars = r->data[5 + 2 * i]; | ||||
gboolean value_set = TRUE; | ||||
// Very approximate | ||||
double size = lotus_twips_to_points (chars * (20 | ||||
* 72 / 11)); | ||||
sheet_col_set_size_pts (sheet, col, size, value_s | ||||
et); | ||||
} | ||||
break; | ||||
} | ||||
case LOTUS_FORMAT: CHECK_RECORD_SIZE (>= 2) { | case LOTUS_FORMAT: CHECK_RECORD_SIZE (>= 2) { | |||
Sheet *sheet = lotus_get_sheet (state->wb, r->data[0]); | Sheet *sheet = lotus_get_sheet (state->wb, r->data[0]); | |||
guint8 subtype = GSF_LE_GET_GUINT8 (r->data + 1); | guint8 subtype = GSF_LE_GET_GUINT8 (r->data + 1); | |||
switch (subtype) { | switch (subtype) { | |||
case 0: CHECK_RECORD_SIZE (>= 4) { // FORMAT | case 0: CHECK_RECORD_SIZE (>= 4) { // FORMAT | |||
int row = GSF_LE_GET_GUINT16 (r->data + 2); | int row = GSF_LE_GET_GUINT16 (r->data + 2); | |||
int col = 0, o; | int col = 0, o; | |||
for (o = 4; o + 4 <= r->len; o += 4) { | for (o = 4; o + 4 <= r->len; o += 4) { | |||
guint32 frmt = GSF_LE_GET_GUINT32 (r->dat a + o); | guint32 frmt = GSF_LE_GET_GUINT32 (r->dat a + o); | |||
gboolean rep = (frmt & 0x80000000u) && (o + 4 < r->len); | gboolean rep = (frmt & 0x80000000u) && (o + 4 < r->len); | |||
skipping to change at line 2184 | skipping to change at line 2238 | |||
gnm_style_dump (style); | gnm_style_dump (style); | |||
#endif | #endif | |||
g_hash_table_insert (state->style_pool, | g_hash_table_insert (state->style_pool, | |||
GUINT_TO_POINTER ((guint)sty leid), | GUINT_TO_POINTER ((guint)sty leid), | |||
style); | style); | |||
g_free (fontname); | g_free (fontname); | |||
break; | break; | |||
} | } | |||
case 0x36b0: CHECK_RECORD_SIZE (> 5) { | ||||
// Sheet name | ||||
guint8 sheetno = GSF_LE_GET_GUINT8 (r->data + 2); | ||||
char *name = g_strndup (r->data + 4, r->len - 5); | ||||
Sheet *sheet = lotus_get_sheet (state->wb, sheetn | ||||
o); | ||||
g_object_set (sheet, "name", name, NULL); | ||||
g_free (name); | ||||
break; | ||||
} | ||||
default: | default: | |||
g_printerr ("Unknown style record 0x%x/%04x of le ngth %d.\n", | g_printerr ("Unknown style record 0x%x/%04x of le ngth %d.\n", | |||
r->type, subtype, | r->type, subtype, | |||
r->len); | r->len); | |||
case 0xfab: /* Edge style */ | case 0x07d7: // Row height | |||
case 0xfb4: /* Interior style */ | case 0x0fab: // Edge style | |||
case 0xfc9: /* Frame style */ | case 0x0fb4: // Interior style | |||
case 0xfe6: /* Named style */ | case 0x0fc9: // Frame style | |||
case 0xffa: /* Style pool */ | case 0x0fe6: // Background style | |||
case 0x0ff0: // Text style | ||||
case 0x0ffa: // Style pool | ||||
case 0x32e7: // Named style | ||||
break; | break; | |||
} | } | |||
break; | break; | |||
} | } | |||
case LOTUS_PACKED_NUMBER: CHECK_RECORD_SIZE (== 8) { | case LOTUS_PACKED_NUMBER: CHECK_RECORD_SIZE (== 8) { | |||
int row = GSF_LE_GET_GUINT16 (r->data); | int row = GSF_LE_GET_GUINT16 (r->data); | |||
Sheet *sheet = lotus_get_sheet (state->wb, r->data[2]); | Sheet *sheet = lotus_get_sheet (state->wb, r->data[2]); | |||
int col = r->data[3]; | int col = r->data[3]; | |||
GnmValue *val = lotus_unpack_number (GSF_LE_GET_GUINT32 ( r->data + 4)); | GnmValue *val = lotus_unpack_number (GSF_LE_GET_GUINT32 ( r->data + 4)); | |||
skipping to change at line 2277 | skipping to change at line 2344 | |||
cell = lotus_cell_fetch (state, sheet, col, row); | cell = lotus_cell_fetch (state, sheet, col, row); | |||
if (cell) | if (cell) | |||
gnm_cell_set_expr_and_value (cell, texpr, curval, TRUE); | gnm_cell_set_expr_and_value (cell, texpr, curval, TRUE); | |||
else | else | |||
value_release (curval); | value_release (curval); | |||
gnm_expr_top_unref (texpr); | gnm_expr_top_unref (texpr); | |||
break; | break; | |||
} | } | |||
case LOTUS_FORMULASTRING: CHECK_RECORD_SIZE (>= 5) { | ||||
int row = GSF_LE_GET_GUINT16 (r->data); | ||||
Sheet *sheet = lotus_get_sheet (state->wb, r->data[2]); | ||||
int col = r->data[3]; | ||||
char *s = g_strndup (r->data + 4, r->len - 5); | ||||
GnmCell *cell = lotus_cell_fetch (state, sheet, col, row) | ||||
; | ||||
gnm_cell_assign_value (cell, value_new_string_nocopy (s)) | ||||
; | ||||
break; | ||||
} | ||||
case LOTUS_CA_DB: | case LOTUS_CA_DB: | |||
case LOTUS_DEFAULTS_DB: | case LOTUS_DEFAULTS_DB: | |||
case LOTUS_NAMED_STYLE_DB: | case LOTUS_NAMED_STYLE_DB: | |||
break; | break; | |||
case LOTUS_RLDB_PACKINFO: CHECK_RECORD_SIZE (>= 4 + rllsize) { | case LOTUS_RLDB_PACKINFO: CHECK_RECORD_SIZE (>= 4 + rllsize) { | |||
int ndims = GSF_LE_GET_GUINT16 (r->data + 2); | int ndims = GSF_LE_GET_GUINT16 (r->data + 2); | |||
int *dims, i; | int *dims, i; | |||
if (rldb) { | if (rldb) { | |||
End of changes. 9 change blocks. | ||||
7 lines changed or deleted | 91 lines changed or added |