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,11 +2067,8 @@ 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;
......@@ -2077,8 +2093,8 @@ ms_excel_read_cell (BiffQuery *q, ExcelSheet *sheet)
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_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,21 +2843,19 @@ 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); */
case BIFF_FONT: /* see S59D8C.HTM */
biff_font_data_new (wb, q);
}
break;
case BIFF_PRECISION:
{
#if 0
......@@ -2796,8 +2864,8 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
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:
......@@ -2827,8 +2895,11 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
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);
#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 ?? */
......@@ -2859,6 +2930,7 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
}
break;
}
case BIFF_EXTSST: /* See: S59D84 */
/* Can be safely ignored on read side */
break;
......@@ -2883,12 +2955,8 @@ 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 */
......@@ -2908,7 +2976,9 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
}
/* 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 (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 (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,8 +2131,12 @@ expr_dump_tree (const ExprTree *tree)
}
return;
case OPER_PERCENT:
case OPER_NEG:
expr_dump_tree (tree->u.value);
if (tree->oper == OPER_PERCENT)
printf ("PERCENT\n");
else
printf ("NEGATIVE\n");
return;
......
......@@ -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
struct _ArrayRef {
int x, y;
......
......@@ -656,17 +656,17 @@ static struct tm *
split_time (gdouble number)
{
static struct tm tm;
double secs;
float secs;
GDate* date = g_date_new_serial (number);
g_date_to_struct_tm (date, &tm);
secs = (number - floor (number)) * 86400.0;
tm.tm_hour = secs / 3600;
secs -= tm.tm_hour * 3600;
tm.tm_min = secs / 60;
secs -= tm.tm_min * 60;
tm.tm_hour = secs / 3600.;
secs -= tm.tm_hour * 3600.;
tm.tm_min = secs / 60.;
secs -= tm.tm_min * 60.;
tm.tm_sec = floor (secs);
g_date_free (date);
......
......@@ -75,6 +75,16 @@ static ExprTree **parser_result;
#define p_new(type) ((type *) alloc_buffer ((unsigned) sizeof (type)))
static ExprTree *
build_unary_op (Operation op, ExprTree *expr)
{
ExprTree *res = p_new (ExprTree);
res->ref_count = 1;
res->oper = op;
res->u.value = expr;
return res;
}
static ExprTree *
build_binop (ExprTree *l, Operation op, ExprTree *r)
{
......@@ -122,6 +132,7 @@ build_array_formula (ExprTree * func,
%left NEG PLUS
%left '!'
%right '^'
%right '%'
%%
line: exp { *parser_result = $1; }
......@@ -151,16 +162,9 @@ exp: NUMBER { $$ = $1 }
| exp LTE exp { $$ = build_binop ($1, OPER_LTE, $3); }
| '(' exp ')' { $$ = $2; }
| '-' exp %prec NEG {
$$ = p_new (ExprTree);
$$->ref_count = 1;
$$->oper = OPER_NEG;
$$->u.value = $2;
}
| '+' exp %prec PLUS {
$$ = $2;
}
| exp '%' { $$ = build_unary_op (OPER_PERCENT, $1); }
| '-' exp %prec NEG { $$ = build_unary_op (OPER_NEG, $2); }
| '+' exp %prec PLUS { $$ = $2; }
| cellref ':' cellref {
$$ = p_new (ExprTree);
......
......@@ -396,9 +396,13 @@ horizontal_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet
col = GTK_ADJUSTMENT (sheet_view->ha)->value;
gnumeric_sheet_set_top_col (gsheet, col);
if (sheet_view->sheet->cursor_col != col ||
sheet_view->sheet->cursor_row != ss->start_row) {
sheet_cursor_move (sheet_view->sheet, col, ss->start_row);
sheet_selection_append (sheet_view->sheet, col, ss->start_row);
}
}
return FALSE;
}
......@@ -424,9 +428,12 @@ vertical_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet_v
row = GTK_ADJUSTMENT (sheet_view->va)->value;
gnumeric_sheet_set_top_row (gsheet, row);
if (sheet_view->sheet->cursor_col != ss->start_col ||
sheet_view->sheet->cursor_row != row) {
sheet_cursor_move (sheet_view->sheet, ss->start_col, row);
sheet_selection_append (sheet_view->sheet, ss->start_col, row);
}
}
return FALSE;
}
......
......@@ -396,9 +396,13 @@ horizontal_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet
col = GTK_ADJUSTMENT (sheet_view->ha)->value;
gnumeric_sheet_set_top_col (gsheet, col);
if (sheet_view->sheet->cursor_col != col ||
sheet_view->sheet->cursor_row != ss->start_row) {
sheet_cursor_move (sheet_view->sheet, col, ss->start_row);
sheet_selection_append (sheet_view->sheet, col, ss->start_row);
}
}
return FALSE;
}
......@@ -424,9 +428,12 @@ vertical_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet_v
row = GTK_ADJUSTMENT (sheet_view->va)->value;
gnumeric_sheet_set_top_row (gsheet, row);
if (sheet_view->sheet->cursor_col != ss->start_col ||
sheet_view->sheet->cursor_row != row) {
sheet_cursor_move (sheet_view->sheet, ss->start_col, row);
sheet_selection_append (sheet_view->sheet, ss->start_col, row);
}
}
return FALSE;
}
......
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