Commit 6887a698 authored by Jody Goldberg's avatar Jody Goldberg

Add operator percent.

Fix Bug 1732, 1638.

Add more Biff record types in excel.
parent 2a5c48d4
1999-08-15 Jody Goldberg <jgoldberg@home.com>
* src/format.c (split_time) : Use a float to avoid problems with
rounding when compiling with optimization.
* src/sheet-view.c (vertical_scroll_event, horizontal_scroll_event) :
Only move and append to the selection if the cursor actually moves.
* src/dialog-function-wizard.c (arg_data_list_new) : Constness.
* src/expr.c (eval_expr_real) : Add OPER_PERCENT.
(do_expr_decode_tree) : Ditto.
(expr_dump_tree) : Ditto.
* src/expr.h : Ditto.
* src/parser.y : Add function build_unary_op, and support
exp '%'. Precedence is a GUESS.
1999-08-16 Michael Meeks <michael@imaginator.com>
* src/widget-editable-label.c (el_start_editing): Remove
......
......@@ -21,7 +21,7 @@ Michael:
Jody:
* Enable Array formulas.
* Add VALUE_BOOLEAN, VALUE_ERROR.
* Add VALUE_BOOLEAN, VALUE_ERROR, and OPER_PERCENT
* Added EOMONTH, WORKDAY, NETWORKDAYS.
* Work on functions : ROW, COLUMN, ISLOGICAL, ISERR, ISBLANK,
DATEVALUE
......
1999-08-15 Jody Goldberg <jgoldberg@home.com>
* src/format.c (split_time) : Use a float to avoid problems with
rounding when compiling with optimization.
* src/sheet-view.c (vertical_scroll_event, horizontal_scroll_event) :
Only move and append to the selection if the cursor actually moves.
* src/dialog-function-wizard.c (arg_data_list_new) : Constness.
* src/expr.c (eval_expr_real) : Add OPER_PERCENT.
(do_expr_decode_tree) : Ditto.
(expr_dump_tree) : Ditto.
* src/expr.h : Ditto.
* src/parser.y : Add function build_unary_op, and support
exp '%'. Precedence is a GUESS.
1999-08-16 Michael Meeks <michael@imaginator.com>
* src/widget-editable-label.c (el_start_editing): Remove
......
1999-08-16 Jody Goldberg <jgoldberg@home.com>
* ms-formula-write.c (write_node) : Add OPER_PERCENT
* ms-formula-read.c (ms_excel_parse_formula) : Ditto.
* ms-obj.c : Make less verbose.
* ms-excel-read.c : Add several new biff-types and do more
checking for 'odd-balls' with most significant byte == 1.
Disable the 'blank sheet' optimization for now to avoid memory
errors when a 'blank' sheet gets put into the externsheet hash.
1999-08-16 Jody Goldberg <jgoldberg@home.com>
* ms-formula-write.c (write_node) : correct typo.
......
......@@ -1876,6 +1876,11 @@ ms_excel_biff_dimensions (BiffQuery *q, ExcelWorkbook *wb)
guint32 last_row;
guint16 first_col;
guint16 last_col;
/* What the heck was a 0x00 ? */
if (q->opcode != 0x200)
return;
if (wb->ver >= eBiffV8)
{
first_row = MS_OLE_GET_GUINT32 (q->data);
......
......@@ -2036,6 +2036,25 @@ ms_excel_externname (BiffQuery *q, ExcelSheet *sheet)
static void
ms_excel_read_cell (BiffQuery *q, ExcelSheet *sheet)
{
if (0x1 == q->ms_op) {
switch (q->opcode) {
case BIFF_DV :
case BIFF_DVAL :
{
static gboolean needs_warning = TRUE;
if (needs_warning) {
printf ("TODO : Data validation has not been implemented\n");
needs_warning = FALSE;
}
break;
}
default :
ms_excel_unexpected_biff (q, "Cell");
};
return;
}
switch (q->ls_op) {
case BIFF_BLANK:
#if 0
......@@ -2048,37 +2067,34 @@ ms_excel_read_cell (BiffQuery *q, ExcelSheet *sheet)
break;
case BIFF_MULBLANK:
{
/* S59DA7.HTM is extremely unclear, this is an educated guess */
if (q->opcode == BIFF_DV) {
printf ("Unimplemented DV: data validation criteria, FIXME\n");
break;
} else {
int row, col, lastcol;
int incr;
guint8 const *ptr;
int row, col, lastcol;
int incr;
guint8 const *ptr;
/*
* dump (ptr, q->length);
*/
row = EX_GETROW (q);
col = EX_GETCOL (q);
ptr = (q->data + 4);
lastcol = MS_OLE_GET_GUINT16 (q->data + q->length - 2);
/*
* dump (ptr, q->length);
*/
row = EX_GETROW (q);
col = EX_GETCOL (q);
ptr = (q->data + 4);
lastcol = MS_OLE_GET_GUINT16 (q->data + q->length - 2);
#if 0
printf ("Cells in row %d are blank starting at col %d until col %d (0x%x)\n",
row, col, lastcol, lastcol);
printf ("Cells in row %d are blank starting at col %d until col %d (0x%x)\n",
row, col, lastcol, lastcol);
#endif
incr = (lastcol > col) ? 1 : -1;
while (col != lastcol) {
ms_excel_sheet_insert_val (sheet,
MS_OLE_GET_GUINT16 (ptr),
col, EX_GETROW (q),
value_new_empty());
col += incr;
ptr += 2;
}
incr = (lastcol > col) ? 1 : -1;
while (col != lastcol) {
ms_excel_sheet_insert_val (sheet,
MS_OLE_GET_GUINT16 (ptr),
col, EX_GETROW (q),
value_new_empty());
col += incr;
ptr += 2;
}
break;
}
case BIFF_RSTRING: /* See: S59DDC.HTM */
{
......@@ -2245,13 +2261,42 @@ ms_excel_read_cell (BiffQuery *q, ExcelSheet *sheet)
ms_excel_externname(q, sheet);
break;
default:
switch (q->opcode)
{
case BIFF_NAME:
ms_excel_read_name (q, sheet);
break;
case BIFF_NAME:
ms_excel_read_name (q, sheet);
break;
case BIFF_IMDATA :
#ifndef NO_DEBUG_EXCEL
if (ms_excel_read_debug > 1) {
guint16 const from_env = MS_OLE_GET_GUINT16 (q->data+2);
guint16 const format = MS_OLE_GET_GUINT16 (q->data+2);
char const * from_name, * format_name;
switch (from_env) {
case 1 : from_name = "Windows"; break;
case 2 : from_name = "Macintosh"; break;
default: from_name = "Unknown environment?"; break;
};
switch (format) {
case 0x2 :
format_name = (from_env==1) ? "windows metafile" : "mac pict";
break;
case 0x9 : format_name = "windows native bitmap"; break;
case 0xe : format_name = "'native format'"; break;
default: format_name = "Unknown format?"; break;
};
printf ("Picture from %s in %s format\n",
from_name, format_name);
}
#endif
case BIFF_STANDARDWIDTH :
/* What the heck is the 'standard width dialog' ? */
break;
default:
switch (q->opcode) {
case BIFF_BOOLERR: /* S59D5F.HTM */
{
Value *v;
......@@ -2327,7 +2372,7 @@ ms_excel_read_selection (ExcelSheet *sheet, BiffQuery *q)
static void
ms_excel_read_sheet (ExcelSheet *sheet, BiffQuery *q, ExcelWorkbook *wb)
{
guint32 blankSheetPos = q->streamPos + q->length + 4;
guint32 const blankSheetPos = q->streamPos + q->length + 4;
#ifndef NO_DEBUG_EXCEL
if (ms_excel_read_debug > 1) {
......@@ -2349,7 +2394,7 @@ ms_excel_read_sheet (ExcelSheet *sheet, BiffQuery *q, ExcelWorkbook *wb)
switch (q->ls_op) {
case BIFF_EOF:
if (q->streamPos == blankSheetPos || sheet->blank) {
if (q->streamPos == blankSheetPos) { /* || sheet->blank) { */
#ifndef NO_DEBUG_EXCEL
if (ms_excel_read_debug > 1) {
printf ("Blank sheet\n");
......@@ -2469,15 +2514,40 @@ ms_excel_read_sheet (ExcelSheet *sheet, BiffQuery *q, ExcelWorkbook *wb)
}
break;
case BIFF_HCENTER :
case BIFF_VCENTER :
case BIFF_LEFTMARGIN :
case BIFF_RIGHTMARGIN :
case BIFF_TOPMARGIN :
case BIFF_BOTTOMMARGIN :
{
/* TODO : What to do with this information ? */
double margin;
margin = BIFF_GETDOUBLE(q->data);
break;
}
case BIFF_OBJPROTECT :
case BIFF_PROTECT :
{
/* TODO : What to do with this information ? */
gboolean is_protected;
is_protected = MS_OLE_GET_GUINT16(q->data) == 1;
break;
}
case BIFF_HCENTER :
case BIFF_VCENTER :
case BIFF_PLS :
case BIFF_SETUP :
case BIFF_DEFCOLWIDTH :
case BIFF_SCL :
case BIFF_DIMENSIONS :
break;
case BIFF_DIMENSIONS : /* 2, NOT 1,10 */
ms_excel_biff_dimensions (q, wb);
break;
case BIFF_SCENMAN :
case BIFF_SCENARIO :
case BIFF_MERGECELLS :
break;
......@@ -2773,31 +2843,29 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
printf ("End of worksheet spec.\n");
#endif
break;
case BIFF_BOUNDSHEET:
biff_boundsheet_data_new (wb, q, ver->version);
break;
case BIFF_PALETTE:
wb->palette = ms_excel_palette_new (q);
break;
case BIFF_FONT: /* see S59D8C.HTM */
{
/* BiffFontData *ptr; */
/* printf ("Read Font\n");
dump (q->data, q->length); */
biff_font_data_new (wb, q);
}
case BIFF_FONT: /* see S59D8C.HTM */
biff_font_data_new (wb, q);
break;
case BIFF_PRECISION:
{
{
#if 0
/* FIXME : implement in gnumeric */
/* state of 'Precision as Displayed' option */
guint16 const data = MS_OLE_GET_GUINT16(q->data);
gboolean const prec_as_displayed = (data == 0);
/* FIXME : implement in gnumeric */
/* state of 'Precision as Displayed' option */
guint16 const data = MS_OLE_GET_GUINT16(q->data);
gboolean const prec_as_displayed = (data == 0);
#endif
}
break;
}
case BIFF_XF_OLD: /* see S59E1E.HTM */
case BIFF_XF:
......@@ -2805,60 +2873,64 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
break;
case BIFF_SST: /* see S59DE7.HTM */
{
guint32 length, k, tot_len;
guint8 *tmp;
{
guint32 length, k, tot_len;
guint8 *tmp;
#ifndef NO_DEBUG_EXCEL
if (ms_excel_read_debug>4) {
printf ("SST\n");
dump (q->data, q->length);
}
if (ms_excel_read_debug>4) {
printf ("SST\n");
dump (q->data, q->length);
}
#endif
wb->global_string_max = MS_OLE_GET_GUINT32(q->data+4);
wb->global_strings = g_new (char *, wb->global_string_max);
wb->global_string_max = MS_OLE_GET_GUINT32(q->data+4);
wb->global_strings = g_new (char *, wb->global_string_max);
tmp = q->data + 8;
tot_len = 8;
for (k = 0; k < wb->global_string_max; k++)
tmp = q->data + 8;
tot_len = 8;
for (k = 0; k < wb->global_string_max; k++)
{
guint32 byte_len;
length = MS_OLE_GET_GUINT16 (tmp);
wb->global_strings[k] = biff_get_text (tmp+2, length, &byte_len);
if (wb->global_strings[k] == NULL)
{
guint32 byte_len;
length = MS_OLE_GET_GUINT16 (tmp);
wb->global_strings[k] = biff_get_text (tmp+2, length, &byte_len);
if (wb->global_strings[k] == NULL)
{
#ifdef NO_DEBUG_EXCEL
if (ms_excel_read_debug > 4)
printf ("Blank string in table at : 0x%x with length %d\n",
k, byte_len);
/* FIXME FIXME FIXME : This works for unicode strings. What biff versions
* default to non-unicode ?? */
/* FIXME FIXME FIXME : Will this problem happen anywhere else ?? */
byte_len = 1;
}
#endif
/* FIXME FIXME FIXME : This works for unicode strings. What biff versions
* default to non-unicode ?? */
/* FIXME FIXME FIXME : Will this problem happen anywhere else ?? */
byte_len = 1;
}
#ifdef NO_DEBUG_EXCEL
else if (ms_excel_read_debug > 4)
puts (wb->global_strings[k]);
else if (ms_excel_read_debug > 4)
puts (wb->global_strings[k]);
#endif
tmp += byte_len + 2;
tot_len += byte_len + 2;
if (tot_len > q->length) {
/*
This means that somehow, the string table has been split
Perhaps it is too big for a single biff record, or
perhaps excel is just cussid. Either way a big pain.
*/
printf ("FIXME: Serious SST overrun lost %d of 0x%x strings!\n",
wb->global_string_max - k, wb->global_string_max);
tmp += byte_len + 2;
tot_len += byte_len + 2;
if (tot_len > q->length) {
/*
This means that somehow, the string table has been split
Perhaps it is too big for a single biff record, or
perhaps excel is just cussid. Either way a big pain.
*/
printf ("FIXME: Serious SST overrun lost %d of 0x%x strings!\n",
wb->global_string_max - k, wb->global_string_max);
/* printf ("Last string was '%s' with length 0x%x 0x%x of 0x%x > 0x%x\n",
(wb->global_strings[k-1] ? wb->global_strings[k-1] : "(null)"),
length, byte_len, tot_len, q->length);*/
wb->global_string_max = k;
break;
}
(wb->global_strings[k-1] ? wb->global_strings[k-1] : "(null)"),
length, byte_len, tot_len, q->length);*/
wb->global_string_max = k;
break;
}
break;
}
break;
}
case BIFF_EXTSST: /* See: S59D84 */
/* Can be safely ignored on read side */
break;
......@@ -2883,32 +2955,30 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
/* printf ("SupBook : %d First sheet %d, Last sheet %d\n", MS_OLE_GET_GUINT16(q->data + 2 + cnt*6 + 0),
MS_OLE_GET_GUINT16(q->data + 2 + cnt*6 + 2), MS_OLE_GET_GUINT16(q->data + 2 + cnt*6 + 4)); */
}
}
#ifdef NO_DEBUG_EXCEL
else if (ms_excel_read_debug > 0) {
} else
printf ("ExternSheet : only BIFF8 supported so far...\n");
}
#endif
break;
case BIFF_FORMAT: /* S59D8E.HTM */
{
BiffFormatData *d = g_new(BiffFormatData,1);
/* printf ("Format data 0x%x %d\n", q->ms_op, ver->version);
dump (q->data, q->length);*/
if (ver->version == eBiffV7) { /* Totaly guessed */
d->idx = MS_OLE_GET_GUINT16(q->data);
d->name = biff_get_text(q->data+3, MS_OLE_GET_GUINT8(q->data+2), NULL);
} else if (ver->version == eBiffV8) {
d->idx = MS_OLE_GET_GUINT16(q->data);
d->name = biff_get_text(q->data+4, MS_OLE_GET_GUINT16(q->data+2), NULL);
} else { /* FIXME: mythical old papyrus spec. */
d->name = biff_get_text(q->data+1, MS_OLE_GET_GUINT8(q->data), NULL);
d->idx = g_hash_table_size (wb->format_data) + 0x32;
}
/* printf ("Format data : %d == '%s'\n", d->idx, d->name); */
g_hash_table_insert (wb->format_data, &d->idx, d);
{
BiffFormatData *d = g_new(BiffFormatData,1);
/* printf ("Format data 0x%x %d\n", q->ms_op, ver->version);
dump (q->data, q->length);*/
if (ver->version == eBiffV7) { /* Totaly guessed */
d->idx = MS_OLE_GET_GUINT16(q->data);
d->name = biff_get_text(q->data+3, MS_OLE_GET_GUINT8(q->data+2), NULL);
} else if (ver->version == eBiffV8) {
d->idx = MS_OLE_GET_GUINT16(q->data);
d->name = biff_get_text(q->data+4, MS_OLE_GET_GUINT16(q->data+2), NULL);
} else { /* FIXME: mythical old papyrus spec. */
d->name = biff_get_text(q->data+1, MS_OLE_GET_GUINT8(q->data), NULL);
d->idx = g_hash_table_size (wb->format_data) + 0x32;
}
/* printf ("Format data : %d == '%s'\n", d->idx, d->name); */
g_hash_table_insert (wb->format_data, &d->idx, d);
break;
}
case BIFF_EXTERNCOUNT: /* see S59D7D.HTM */
#ifndef NO_DEBUG_EXCEL
if (ms_excel_read_debug > 0) {
......@@ -2954,7 +3024,14 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
break;
}
case BIFF_OBJPROTECT :
case BIFF_PROTECT :
{
/* TODO : What to do with this information ? */
gboolean is_protected;
is_protected = MS_OLE_GET_GUINT16(q->data) == 1;
break;
}
break;
case BIFF_PASSWORD :
......@@ -3023,6 +3100,7 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
break;
case BIFF_DIMENSIONS : /* 2, NOT 1,10 */
ms_excel_biff_dimensions (q, wb);
break;
case BIFF_OBJ: /* See: ms-obj.c and S59DAD.HTM */
......@@ -3038,6 +3116,16 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
ms_escher_hack_get_drawing (q, wb);
break;
case BIFF_ADDMENU :
#ifndef NO_DEBUG_EXCEL
if (ms_excel_read_debug > 1) {
printf ("%smenu with %d sub items",
(MS_OLE_GET_GUINT8(q->data+6) == 1) ? "" : "Placeholder ",
MS_OLE_GET_GUINT8(q->data+5));
}
#endif
break;
default:
ms_excel_unexpected_biff (q,"Workbook");
break;
......
......@@ -1118,17 +1118,10 @@ ms_excel_parse_formula (ExcelWorkbook *wb, ExcelSheet *sheet, guint8 const *mem,
break;
case FORMULA_PTG_PERCENT:
{
/* FIXME : We need to revisit this when operator % is
* available */
ExprTree * hundred =
expr_tree_new_constant (value_new_float (.01));
parse_list_push (&stack,
expr_tree_new_binary (parse_list_pop (&stack),
OPER_MULT,
hundred));
expr_tree_new_unary (OPER_PERCENT,
parse_list_pop (&stack)));
break;
}
case FORMULA_PTG_PAREN:
/* printf ("Ignoring redundant parenthesis ptg\n") ; */
......
......@@ -481,6 +481,10 @@ write_node (PolishData *pd, ExprTree *tree)
write_node (pd, tree->u.value);
push_guint8 (pd, FORMULA_PTG_U_MINUS);
break;
case OPER_PERCENT:
write_node (pd, tree->u.value);
push_guint8 (pd, FORMULA_PTG_PERCENT);
break;
case OPER_VAR:
write_ref (pd, &tree->u.ref);
break;
......
......@@ -144,7 +144,7 @@ ms_obj_read_text (BiffQuery *q, ExcelWorkbook * wb, int const id)
g_return_if_fail (q->opcode == BIFF_MS_O_DRAWING);
ms_escher_hack_get_drawing (q, wb);
if (ms_excel_read_debug > 0)
if (ms_excel_read_debug > 1)
dump (q->data, q->length);
/* then a TXO, CONTINUE, CONTINUE */
......@@ -166,7 +166,7 @@ ms_obj_read_text (BiffQuery *q, ExcelWorkbook * wb, int const id)
static void
ms_obj_dump (guint8 const * const data, int const len, char const * const name)
{
if (ms_excel_read_debug == 0)
if (ms_excel_read_debug < 2)
return;
printf ("{ %s \n", name);
......
......@@ -75,7 +75,7 @@ arg_data_list_new (State *state)
gchar *copy_args;
const gchar *syntax;
gchar *ptr, *start = NULL;
gchar *type;
gchar const *type;
int optional = 0;
if (!state || !state->fd ||
......
......@@ -75,7 +75,7 @@ arg_data_list_new (State *state)
gchar *copy_args;
const gchar *syntax;
gchar *ptr, *start = NULL;
gchar *type;
gchar const *type;
int optional = 0;
if (!state || !state->fd ||
......
......@@ -75,7 +75,7 @@ arg_data_list_new (State *state)
gchar *copy_args;
const gchar *syntax;
gchar *ptr, *start = NULL;
gchar *type;
gchar const *type;
int optional = 0;
if (!state || !state->fd ||
......
......@@ -996,6 +996,7 @@ eval_expr_real (FunctionEvalInfo *s, ExprTree const *tree)
}
return value_new_error (&s->pos, _("Unknown operator"));
case OPER_PERCENT:
case OPER_NEG:
/* Garantees that a != NULL */
a = eval_expr (s, tree->u.value);
......@@ -1005,12 +1006,15 @@ eval_expr_real (FunctionEvalInfo *s, ExprTree const *tree)
value_release (a);
return value_new_error (&s->pos, gnumeric_err_VALUE);
}
if (a->type == VALUE_INTEGER)
res = value_new_int (-a->v.v_int);
else if (a->type == VALUE_FLOAT)
res = value_new_float (-a->v.v_float);
else
res = value_new_bool (!a->v.v_float);
if (tree->oper == OPER_NEG) {
if (a->type == VALUE_INTEGER)
res = value_new_int (-a->v.v_int);
else if (a->type == VALUE_FLOAT)
res = value_new_float (-a->v.v_float);
else
res = value_new_bool (!a->v.v_float);
} else
res = value_new_float (value_get_as_float (a) * .01);
value_release (a);
return res;
......@@ -1221,6 +1225,7 @@ do_expr_decode_tree (ExprTree *tree, const ParsePosition *pp,
{ NULL, 0, 0, 0 }, /* Constant */
{ NULL, 0, 0, 0 }, /* Var */
{ "-", 5, 0, 0 },
{ "%", 5, 0, 0 },
{ NULL, 0, 0, 0 } /* Array */
};
int op;
......@@ -1258,10 +1263,17 @@ do_expr_decode_tree (ExprTree *tree, const ParsePosition *pp,
a = do_expr_decode_tree (tree->u.value, pp, operations[op].prec);
opname = operations[op].name;
if (prec <= paren_level)
res = g_strconcat ("(", opname, a, ")", NULL);
else
res = g_strconcat (opname, a, NULL);
if (tree->oper == OPER_NEG) {
if (prec <= paren_level)
res = g_strconcat ("(", opname, a, ")", NULL);
else
res = g_strconcat (opname, a, NULL);
} else {
if (prec <= paren_level)
res = g_strconcat ("(", a, opname, ")", NULL);
else
res = g_strconcat (a, opname, NULL);
}
g_free (a);
return res;
}
......@@ -2119,9 +2131,13 @@ expr_dump_tree (const ExprTree *tree)
}
return;
case OPER_PERCENT:
case OPER_NEG:
expr_dump_tree (tree->u.value);
printf ("NEGATIVE\n");
if (tree->oper == OPER_PERCENT)
printf ("PERCENT\n");
else
printf ("NEGATIVE\n");
return;
case OPER_ARRAY:
......
......@@ -37,6 +37,7 @@ typedef enum {
OPER_CONSTANT, /* Constant value */
OPER_VAR, /* Cell content lookup (variable) */
OPER_NEG, /* Sign inversion */
OPER_PERCENT, /* Percentage (value/100) */
OPER_ARRAY /* Array access */
} Operation;
......@@ -45,7 +46,7 @@ typedef enum {
case OPER_LTE: case OPER_NOT_EQUAL: \
case OPER_ADD: case OPER_SUB: case OPER_MULT: case OPER_DIV: \
case OPER_EXP: case OPER_CONCAT
#define OPER_ANY_UNARY OPER_NEG
#define OPER_ANY_UNARY OPER_NEG: case OPER_PERCENT