Commit 6c31ed7f authored by Jody Goldberg's avatar Jody Goldberg

- Correct XF indexing by merging style & cell records.

- Hopefully correct name problem for pre-biff7 by making the zero based.
- Const.
- Handle unhandled builtin functions too.
- Fix array handling.
parent 8f6a8c43
1999-07-12 Jody Goldberg <jgoldberg@home.com>
* ms-excel-read.[ch] : Remove XF_style_records. All XF records are
kept in one list. The fixes the indexing problems we've been
having with XF records. No more XF_MAGIC_OFFSET !!
(biff_name_data_get_name) : Pre-Biff5 seems to use 0 based names, post
seems to be 1 base ?? Check this.
* ms-formula-read.c (excel_formula_build_dummy_handler) : New function.
(make_function) : split out from here and used for external and builtin
functions.
(MATCH) : correct the number of arguments.
(ms_excel_parse_formula) : The size of the array is stored at the end
too. This fixes formulas with multiple arrays.
* *.[ch] make the data streams const while reading.
1999-07-12 Jody Goldberg <jgoldberg@home.com>
* ms-excel-read.c (biff_name_data_get_name) : Off by one error in the
......
......@@ -14,10 +14,6 @@
#include "utils.h" /* for cell_name */
/* This many styles are reserved */
/* FIXME FIXME FIXME : Is this version specific ?? Older biffs may need more */
#define XF_MAGIC_OFFSET (16 + 4)
/* #define NO_DEBUG_EXCEL */
/* Used in src/main.c to toggle debug messages on & off */
......@@ -81,7 +77,7 @@ biff_guint32_equal (const guint32 *a, const guint32 *b)
* and sets various flags from it
**/
static gboolean
biff_string_get_flags (guint8 *ptr,
biff_string_get_flags (guint8 const *ptr,
gboolean *word_chars,
gboolean *extended,
gboolean *rich)
......@@ -113,11 +109,11 @@ biff_string_get_flags (guint8 *ptr,
* FIXME: see S59D47.HTM for full description
**/
char *
biff_get_text (guint8 *pos, guint32 length, guint32 *byte_length)
biff_get_text (guint8 const *pos, guint32 length, guint32 *byte_length)
{
guint32 lp;
char *ans;
guint8 *ptr;
guint8 const *ptr;
guint32 byte_len;
gboolean header;
gboolean high_byte;
......@@ -598,7 +594,7 @@ biff_name_data_new (ExcelWorkbook *wb, char *name,
}
ExprTree *
biff_name_data_get_name (ExcelSheet *sheet, guint16 idx)
biff_name_data_get_name (ExcelSheet *sheet, int idx)
{
BiffNameData *bnd;
GPtrArray *a;
......@@ -608,7 +604,12 @@ biff_name_data_get_name (ExcelSheet *sheet, guint16 idx)
a = sheet->wb->name_data;
if (a && 0 < idx && idx <= a->len && (bnd = g_ptr_array_index (a, idx-1))) {
/* FIXME : This is a guess. Pre XL95 seems to be zero based, anyone
* have some confirmation ? */
if (sheet->ver >= eBiffV5)
--idx;
if (a && 0 <= idx && idx < a->len && (bnd = g_ptr_array_index (a, idx))) {
if (bnd->type == BNDStore && bnd->v.store.data) {
char *duff = "Some Error";
ExprTree *tree;
......@@ -643,7 +644,7 @@ biff_name_data_get_name (ExcelSheet *sheet, guint16 idx)
return expr_tree_new_constant (value_new_string (bnd->name));
} else
{
g_warning ("EXCEL : %x (of %x) UNKNOWN name\n", idx-1, a->len);
g_warning ("EXCEL : %x (of %x) UNKNOWN name\n", idx, a->len);
return expr_tree_new_constant (value_new_string("Unknown name"));
}
}
......@@ -918,11 +919,10 @@ ms_excel_set_cell_font (ExcelSheet *sheet, Cell *cell, BiffXFData const *xf)
}
static BiffXFData const *
ms_excel_get_xf (ExcelSheet *sheet, int const xfidx, Cell *cell)
ms_excel_get_xf (ExcelSheet *sheet, int const xfidx)
{
BiffXFData const *xf;
GPtrArray const * const p = sheet->wb->XF_cell_records;
int const idx = xfidx - XF_MAGIC_OFFSET;
/* Normal cell formatting */
if (xfidx == 0)
......@@ -932,15 +932,8 @@ ms_excel_get_xf (ExcelSheet *sheet, int const xfidx, Cell *cell)
if (xfidx == 15)
return NULL;
/* FIXME : Put in some verbose debug until we figure this out */
if (p == NULL || 0 > idx || idx >= p->len)
{
printf ("%s : MISSING XF. requested %d out of %d\n",
cell_name(cell->col->pos, cell->row->pos),
idx, p->len);
}
g_return_val_if_fail (p && 0 <= idx && idx < p->len, NULL);
xf = g_ptr_array_index (p, idx);
g_return_val_if_fail (p && 0 <= xfidx && xfidx < p->len, NULL);
xf = g_ptr_array_index (p, xfidx);
g_return_val_if_fail (xf, NULL);
g_return_val_if_fail (xf->xftype == eBiffXCell, NULL);
......@@ -950,7 +943,7 @@ ms_excel_get_xf (ExcelSheet *sheet, int const xfidx, Cell *cell)
static void
ms_excel_set_cell_xf (ExcelSheet *sheet, Cell *cell, guint16 xfidx)
{
BiffXFData const *xf = ms_excel_get_xf (sheet, xfidx, cell);
BiffXFData const *xf = ms_excel_get_xf (sheet, xfidx);
StyleColor *fore, *back, *basefore;
int back_index;
......@@ -1282,13 +1275,7 @@ biff_xf_data_new (ExcelWorkbook *wb, BiffQuery *q, eBiff_version ver)
xf->border_color[STYLE_RIGHT] = (subdata & 0x7f);
}
if (xf->xftype == eBiffXCell) {
/*printf ("Inserting into Cell XF hash with : %d\n", wb->XF_cell_records->len); */
g_ptr_array_add (wb->XF_cell_records, xf);
} else {
/* printf ("Inserting into style XF hash with : %d\n", wb->XF_style_records->len); */
g_ptr_array_add (wb->XF_style_records, xf);
}
g_ptr_array_add (wb->XF_cell_records, xf);
#ifndef NO_DEBUG_EXCEL
if (ms_excel_read_debug > 2) {
printf ("XF : Fore %d, Back %d\n",
......@@ -1688,7 +1675,6 @@ ms_excel_workbook_new (eBiff_version ver)
ans->font_data = g_hash_table_new ((GHashFunc)biff_guint16_hash,
(GCompareFunc)biff_guint16_equal);
ans->excel_sheets = g_ptr_array_new ();
ans->XF_style_records = g_ptr_array_new ();
ans->XF_cell_records = g_ptr_array_new ();
ans->name_data = g_ptr_array_new ();
ans->chart.series = NULL; /* Init if/when its needed */
......@@ -1750,10 +1736,6 @@ ms_excel_workbook_destroy (ExcelWorkbook *wb)
wb);
g_hash_table_destroy (wb->boundsheet_data_by_index);
g_hash_table_destroy (wb->boundsheet_data_by_stream);
if (wb->XF_style_records)
for (lp=0;lp<wb->XF_style_records->len;lp++)
biff_xf_data_destroy (g_ptr_array_index (wb->XF_style_records, lp));
g_ptr_array_free (wb->XF_style_records, TRUE);
if (wb->XF_cell_records)
for (lp=0;lp<wb->XF_cell_records->len;lp++)
biff_xf_data_destroy (g_ptr_array_index (wb->XF_cell_records, lp));
......@@ -1797,7 +1779,7 @@ ms_excel_workbook_destroy (ExcelWorkbook *wb)
* Unpacks a MS Excel RK structure,
**/
static Value *
biff_get_rk (guint8 *ptr)
biff_get_rk (guint8 const *ptr)
{
gint32 number;
enum eType {
......@@ -1856,7 +1838,7 @@ ms_excel_read_name (BiffQuery *q, ExcelSheet *sheet)
guint8 help_txt_len = BIFF_GET_GUINT8 (q->data + 12);
guint8 status_txt_len = BIFF_GET_GUINT8 (q->data + 13);
char *name, *menu_txt, *descr_txt, *help_txt, *status_txt;
guint8 *ptr;
guint8 const *ptr;
/* g_assert (ixals==sheet_idx); */
ptr = q->data + 14;
......@@ -1985,7 +1967,7 @@ ms_excel_read_cell (BiffQuery *q, ExcelSheet *sheet)
} else {
int row, col, lastcol;
int incr;
guint8 *ptr;
guint8 const *ptr;
/*
* dump (ptr, q->length);
......@@ -2067,7 +2049,7 @@ ms_excel_read_cell (BiffQuery *q, ExcelSheet *sheet)
* calibrated against.
* 2) the docs say charwidth not height. Is this correct ?
*/
if ((xf = ms_excel_get_xf (sheet, cols_xf, NULL)) != NULL &&
if ((xf = ms_excel_get_xf (sheet, cols_xf)) != NULL &&
(fd = ms_excel_get_font (sheet, xf->font_idx))) {
divisor = fd->height / 10;
} else
......@@ -2102,7 +2084,7 @@ ms_excel_read_cell (BiffQuery *q, ExcelSheet *sheet)
case BIFF_MULRK: /* S59DA8.HTM */
{
guint32 col, row, lastcol;
guint8 *ptr = q->data;
guint8 const *ptr = q->data;
Value *v;
/* printf ("MULRK\n");
......
......@@ -84,7 +84,6 @@ typedef struct _ExcelWorkbook
GHashTable *boundsheet_data_by_stream;
GHashTable *boundsheet_data_by_index;
GPtrArray *XF_cell_records;
GPtrArray *XF_style_records;
GHashTable *font_data;
GHashTable *format_data; /* leave as a hash */
GPtrArray *name_data;
......@@ -109,9 +108,9 @@ typedef struct _ExcelWorkbook
} ExcelWorkbook;
extern Sheet* biff_get_externsheet_name (ExcelWorkbook *wb, guint16 idx, gboolean get_first);
extern char* biff_get_text (guint8 *ptr, guint32 length, guint32 *byte_length);
extern char* biff_get_text (guint8 const *ptr, guint32 length, guint32 *byte_length);
extern const char* biff_get_error_text (const guint8 err);
extern ExprTree* biff_name_data_get_name (ExcelSheet *sheet, guint16 idx);
extern ExprTree* biff_name_data_get_name (ExcelSheet *sheet, int idx);
extern BIFF_BOF_DATA * ms_biff_bof_data_new (BiffQuery * q);
extern void ms_biff_bof_data_destroy (BIFF_BOF_DATA * data);
......
......@@ -129,7 +129,7 @@ FormulaFuncData formula_func_data[FORMULA_FUNC_DATA_LEN] =
/* 61 */ { "MIRR", 3 },
/* 62 */ { "IRR", -1 }, /* guess is optional */
/* 63 */ { "RAND", 0 },
/* 64 */ { "MATCH", -1 },/* match_type is optional */
/* 64 */ { "MATCH", 3 },/* match_type is optional */
/* 65 */ { "DATE", 3 },
/* 66 */ { "TIME", 3 },
/* 67 */ { "DAY", 1 },
......@@ -140,7 +140,7 @@ FormulaFuncData formula_func_data[FORMULA_FUNC_DATA_LEN] =
/* 72 */ { "MINUTE", 1 },
/* 73 */ { "SECOND", 1 },
/* 74 */ { "NOW", 0 },
/* 75 */ { "AREAS", 1 },
/* 75 */ { "AREAS", -1 },
/* 76 */ { "ROWS", 1 },
/* 77 */ { "COLUMNS", 1 },
/* 78 */ { "OFFSET", -1 },
......@@ -637,6 +637,35 @@ unknownFunctionHandler (FunctionEvalInfo *ei, GList *expr_node_list)
return function_error (ei, gnumeric_err_NAME);
}
static Symbol *
excel_formula_build_dummy_handler(char const * const name,
char const * const type)
{
Symbol * symbol = symbol_lookup (global_symbol_table, name);
if (!symbol) {
FunctionCategory *cat =
function_get_category (_("Unknown Function"));
/*
* TODO TODO TODO : should add a
* function_add_{nodes,args}_fake
* This will allow a user to load a missing
* plugin to supply missing functions.
*/
function_add_nodes (cat, g_strdup (name),
"", "...", NULL,
&unknownFunctionHandler);
symbol = symbol_lookup (global_symbol_table,
name);
/* We just added it, it better be there */
g_assert (symbol);
/* WISHLIST : it would be nice to have a log if these. */
g_warning ("EXCEL unknown %sfunction : %s", type, name);
}
return symbol;
}
static gboolean
make_function (ParseList **stack, int fn_idx, int numargs)
{
......@@ -665,27 +694,9 @@ make_function (ParseList **stack, int fn_idx, int numargs)
f_name = tmp->u.constant->v.str->str;
name = symbol_lookup (global_symbol_table, f_name);
if (!name) {
FunctionCategory *cat =
function_get_category (_("Unknown Function"));
/*
* TODO TODO TODO : should add a
* function_add_{nodes,args}_fake
* This will allow a user to load a missing
* plugin to supply missing functions.
*/
function_add_nodes (cat, g_strdup (f_name),
"", "...", NULL,
&unknownFunctionHandler);
name = symbol_lookup (global_symbol_table,
f_name);
if (!name)
name = excel_formula_build_dummy_handler(f_name, "");
/* We just added it, it better be there */
g_assert (name);
/* WISHLIST : it would be nice to have a log if these. */
g_warning ("EXCEL unknown function : %s", f_name);
}
expr_tree_unref (tmp);
symbol_ref (name);
parse_list_push (stack, expr_tree_new_funcall (name, args));
......@@ -713,7 +724,9 @@ make_function (ParseList **stack, int fn_idx, int numargs)
args = parse_list_last_n (stack, numargs);
if (fd->prefix)
name = symbol_lookup (global_symbol_table, fd->prefix);
name = excel_formula_build_dummy_handler(fd->prefix,
"Builtin ");
/* This should not happen */
if (!name) {
char *txt;
txt = g_strdup_printf ("[Function '%s']",
......@@ -749,15 +762,18 @@ make_function (ParseList **stack, int fn_idx, int numargs)
* Return a dynamicly allocated ExprTree containing the formula, or NULL
**/
ExprTree *
ms_excel_parse_formula (ExcelWorkbook *wb, ExcelSheet *sheet, guint8 *mem,
ms_excel_parse_formula (ExcelWorkbook *wb, ExcelSheet *sheet, guint8 const *mem,
int fn_col, int fn_row, gboolean const shared,
guint16 length,
gboolean *const array_element)
{
/* so that the offsets and lengths match the documentation */
guint8 *cur = mem + 1 ;
guint8 const *cur = mem + 1 ;
/* Array sizes and values are stored at the end of the stream */
guint8 const *array_data = mem + length;
int len_left = length ;
guint8 *array_data = mem + 3 + length; /* Sad but true */
ParseList *stack = NULL;
gboolean error = FALSE ;
......@@ -922,13 +938,13 @@ ms_excel_parse_formula (ExcelWorkbook *wb, ExcelSheet *sheet, guint8 *mem,
}
case FORMULA_PTG_ARRAY:
{
Value *v;
guint32 cols=BIFF_GET_GUINT8(cur+0)+1; /* NB. the spec. is wrong here, these */
guint32 rows=BIFF_GET_GUINT16(cur+1)+1; /* are zero offset numbers */
/* NB. the spec. is wrong here, these are zero offset */
guint32 const cols=BIFF_GET_GUINT8(array_data)+1;
guint32 const rows=BIFF_GET_GUINT16(array_data+1)+1;
guint16 lpx,lpy;
v = value_array_new (cols, rows);
Value *v = value_array_new (cols, rows);
ptg_length = 7;
#ifndef NO_DEBUG_EXCEL
if (ms_excel_formula_debug > 1) {
printf ("An Array how interesting: (%d,%d)\n",
......@@ -936,6 +952,7 @@ ms_excel_parse_formula (ExcelWorkbook *wb, ExcelSheet *sheet, guint8 *mem,
dump (mem, length);
}
#endif
array_data += 3;
for (lpy=0;lpy<rows;lpy++) {
for (lpx=0;lpx<cols;lpx++) {
Value *set_val=0;
......@@ -946,7 +963,8 @@ ms_excel_parse_formula (ExcelWorkbook *wb, ExcelSheet *sheet, guint8 *mem,
}
#endif
if (opts == 1) {
set_val = value_new_float (BIFF_GETDOUBLE(array_data+1));
double const v = BIFF_GETDOUBLE(array_data+1);
set_val = value_new_float (v);
array_data+=9;
} else if (opts == 2) {
guint32 len;
......@@ -974,7 +992,9 @@ ms_excel_parse_formula (ExcelWorkbook *wb, ExcelSheet *sheet, guint8 *mem,
} else
set_val = value_new_string ("");
} else {
printf ("FIXME: Duff array item type\n");
printf ("FIXME: Duff array item type %d @ %s%d\n",
opts, col_name(fn_col), fn_row+1);
dump (array_data+1, 8);
error = TRUE;
goto really_duff;
break;
......@@ -1143,7 +1163,7 @@ ms_excel_parse_formula (ExcelWorkbook *wb, ExcelSheet *sheet, guint8 *mem,
} else if (grbit & 0x04) { /* AttrChoose 'optimised' my foot. */
guint16 len, lp;
guint32 offset=0;
guint8 *data=cur+3;
guint8 const *data=cur+3;
ExprTree *tr;
#ifndef NO_DEBUG_EXCEL
......
......@@ -13,7 +13,8 @@
#include "ms-biff.h"
ExprTree *
ms_excel_parse_formula (ExcelWorkbook *wb, ExcelSheet *sheet, guint8 *mem,
ms_excel_parse_formula (ExcelWorkbook *wb, ExcelSheet *sheet,
guint8 const *mem,
int fn_col, int fn_row,
gboolean const shared, guint16 length,
gboolean *const array_element) ;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment