Commit 80a73121 authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg

support named expressions. (oo_cell_start) : support merged ranges.

2002-10-08  Jody Goldberg <jody@gnome.org>

	* openoffice-read.c (oo_named_expr) : support named expressions.
	(oo_cell_start) : support merged ranges.


2002-10-08  Jody Goldberg <jody@gnome.org>

	* src/parser.y (parser_lookup_name) : default the placeholder to be at
	  workbook scope.

	* src/cellspan.c (row_calc_spans) : new.

	* src/dependent.c (cell_eval_content) : flag the row as needing
	  respan.  I'll probably want to distinguish between span and render
	  somehow.

	* src/sheet.c (sheet_update_only_grid) : test a new idea for doing
	  just in time spanning.  It does not support a true model view split
	  of the rendering.  However, it does delay the render & span until
	  the row is visible, and as a result it is feasible to support
	  spanning expressions.  The key is to flag the row as needing
	  respanning then doing the entire row in the redraw loop.
	* src/item-grid.c (item_grid_draw) : do a span recalc if necessary
	* src/print-cell.c (print_cell_range) : ditto.

	* src/workbook.c (workbook_init) : fix warning.

	* src/parser.y (parser_lookup_name) : remove implicit conversion of
	  unquoted strings that are not names into string values.  Replace it
	  with the creation of a placeholder name.  This is useful for parsing
	  expressions before a name has been declared.

	* src/cell.c (cell_set_value) : fix docs.
parent df8ac4c1
......@@ -135,9 +135,6 @@ Misc stuff that should be fixed
- The max row/col canvas scroll size is still hard coded.
- calculated cells do not span.
: this is by design, we'll fix it when we move to just in time rendering.
- Formats
: support negative durations with [h]
: Why does the number matching bother comparing against formats that are
......
2002-10-07 Jody Goldberg <jody@gnome.org>
2002-10-08 Jody Goldberg <jody@gnome.org>
* src/parser.y (parser_lookup_name) : default the placeholder to be at
workbook scope.
* src/cellspan.c (row_calc_spans) : new.
* src/dependent.c (cell_eval_content) : flag the row as needing
respan. I'll probably want to distinguish between span and render
somehow.
* src/sheet.c (sheet_update_only_grid) : test a new idea for doing
just in time spanning. It does not support a true model view split
of the rendering. However, it does delay the render & span until
the row is visible, and as a result it is feasible to support
spanning expressions. The key is to flag the row as needing
respanning then doing the entire row in the redraw loop.
* src/item-grid.c (item_grid_draw) : do a span recalc if necessary
* src/print-cell.c (print_cell_range) : ditto.
* src/workbook.c (workbook_init) : fix warning.
* src/parser.y (parser_lookup_name) : remove implicit conversion of
unquoted strings that are not names into string values. Replace it
with the creation of a placeholder name. This is useful for parsing
expressions before a name has been declared.
* src/cell.c (cell_set_value) : fix docs.
......
......@@ -25,6 +25,8 @@ Jody:
* Make named expression ids case sensitive.
* Port cell format dialog to TreeView.
* Handle encryption from 'Tools -> Protection -> Workbook Protected'
* Remove implicit conversion of unquoted strings that are not names
* Import named expressions, arrays and merged regions from OpenCalc
Morten:
* Port search center from gal's e-table to gtk's treeview.
......
2002-10-07 Jody Goldberg <jody@gnome.org>
2002-10-08 Jody Goldberg <jody@gnome.org>
* src/parser.y (parser_lookup_name) : default the placeholder to be at
workbook scope.
* src/cellspan.c (row_calc_spans) : new.
* src/dependent.c (cell_eval_content) : flag the row as needing
respan. I'll probably want to distinguish between span and render
somehow.
* src/sheet.c (sheet_update_only_grid) : test a new idea for doing
just in time spanning. It does not support a true model view split
of the rendering. However, it does delay the render & span until
the row is visible, and as a result it is feasible to support
spanning expressions. The key is to flag the row as needing
respanning then doing the entire row in the redraw loop.
* src/item-grid.c (item_grid_draw) : do a span recalc if necessary
* src/print-cell.c (print_cell_range) : ditto.
* src/workbook.c (workbook_init) : fix warning.
* src/parser.y (parser_lookup_name) : remove implicit conversion of
unquoted strings that are not names into string values. Replace it
with the creation of a placeholder name. This is useful for parsing
expressions before a name has been declared.
* src/cell.c (cell_set_value) : fix docs.
......
2002-10-07 Jody Goldberg <jody@gnome.org>
2002-10-08 Jody Goldberg <jody@gnome.org>
* src/parser.y (parser_lookup_name) : default the placeholder to be at
workbook scope.
* src/cellspan.c (row_calc_spans) : new.
* src/dependent.c (cell_eval_content) : flag the row as needing
respan. I'll probably want to distinguish between span and render
somehow.
* src/sheet.c (sheet_update_only_grid) : test a new idea for doing
just in time spanning. It does not support a true model view split
of the rendering. However, it does delay the render & span until
the row is visible, and as a result it is feasible to support
spanning expressions. The key is to flag the row as needing
respanning then doing the entire row in the redraw loop.
* src/item-grid.c (item_grid_draw) : do a span recalc if necessary
* src/print-cell.c (print_cell_range) : ditto.
* src/workbook.c (workbook_init) : fix warning.
* src/parser.y (parser_lookup_name) : remove implicit conversion of
unquoted strings that are not names into string values. Replace it
with the creation of a placeholder name. This is useful for parsing
expressions before a name has been declared.
* src/cell.c (cell_set_value) : fix docs.
......
2002-10-08 Jody Goldberg <jody@gnome.org>
* openoffice-read.c (oo_named_expr) : support named expressions.
(oo_cell_start) : support merged ranges.
2002-10-07 Jody Goldberg <jody@gnome.org>
* openoffice-read.c (oo_table_start) : fix accidental offset of 1,1.
......
......@@ -27,9 +27,13 @@
#include <workbook-view.h>
#include <workbook.h>
#include <sheet.h>
#include <sheet-merge.h>
#include <ranges.h>
#include <cell.h>
#include <value.h>
#include <expr.h>
#include <expr-impl.h>
#include <expr-name.h>
#include <parse-util.h>
#include <datetime.h>
#include <style-color.h>
......@@ -206,6 +210,12 @@ oo_attr_enum (OOParseState *state, xmlChar const * const *attrs,
return FALSE;
}
#define oo_expr_parse_str(str, pp, flags, err) \
gnm_expr_parse_str (str, pp, \
GNM_EXPR_PARSE_USE_OPENCALC_CONVENTIONS | \
GNM_EXPR_PARSE_CREATE_PLACEHOLDER_FOR_UNKNOWN_FUNC | \
flags, &oo_rangeref_parse, err)
/****************************************************************************/
static void
......@@ -290,8 +300,7 @@ oo_cellref_parse (CellRef *ref, char const *start, ParsePos const *pp)
/* OpenCalc does not pre-declare its sheets, but it does have a
* nice unambiguous format. So if we find a name that has not
* been added yet add it.
* TODO : worry about order
* been added yet add it. Reorder below.
*/
ref->sheet = workbook_sheet_by_name (pp->wb, name);
if (ref->sheet == NULL) {
......@@ -347,6 +356,7 @@ oo_cell_start (GsfXmlSAXState *gsf_state, xmlChar const **attrs)
gboolean bool_val;
gnum_float float_val;
int array_cols = -1, array_rows = -1;
int merge_cols = -1, merge_rows = -1;
MStyle *style = NULL;
state->col_inc = 1;
......@@ -373,11 +383,8 @@ oo_cell_start (GsfXmlSAXState *gsf_state, xmlChar const **attrs)
else {
ParseError perr;
parse_error_init (&perr);
expr = gnm_expr_parse_str (expr_string, &state->pos,
GNM_EXPR_PARSE_USE_OPENCALC_CONVENTIONS |
GNM_EXPR_PARSE_CREATE_PLACEHOLDER_FOR_UNKNOWN_FUNC,
&oo_rangeref_parse,
&perr);
expr = oo_expr_parse_str (expr_string,
&state->pos, 0, &perr);
if (expr == NULL) {
oo_warning (state, _("Unable to parse '%s' because '%s'"),
attrs[1], perr.message);
......@@ -403,6 +410,10 @@ oo_cell_start (GsfXmlSAXState *gsf_state, xmlChar const **attrs)
;
else if (oo_attr_int (state, attrs, "table:number-matrix-rows-spanned", &array_rows))
;
else if (oo_attr_int (state, attrs, "table:number-columns-spanned", &merge_cols))
;
else if (oo_attr_int (state, attrs, "table:number-rows-spanned", &merge_rows))
;
else if (!strcmp (attrs[0], "table:style-name")) {
style = g_hash_table_lookup (state->styles, attrs[1]);
}
......@@ -455,6 +466,15 @@ oo_cell_start (GsfXmlSAXState *gsf_state, xmlChar const **attrs)
} else if (!state->error_content)
/* store the content as a string */
state->simple_content = TRUE;
if (merge_cols > 0 && merge_rows > 0) {
Range r;
range_init (&r,
state->pos.eval.col, state->pos.eval.row,
state->pos.eval.col + merge_cols - 1,
state->pos.eval.row + merge_rows - 1);
sheet_merge_add (NULL, state->pos.sheet, &r, FALSE);
}
}
static void
......@@ -467,7 +487,6 @@ oo_cell_end (GsfXmlSAXState *gsf_state)
static void
oo_cell_content_end (GsfXmlSAXState *gsf_state)
{
/* <text:p>EQUAL</text:p> */
OOParseState *state = (OOParseState *)gsf_state;
if (state->simple_content || state->error_content) {
......@@ -570,6 +589,65 @@ oo_style_prop (GsfXmlSAXState *gsf_state, xmlChar const **attrs)
mstyle_set_align_h (style, h_align_is_valid ? h_align : HALIGN_GENERAL);
}
static void
oo_named_expr (GsfXmlSAXState *gsf_state, xmlChar const **attrs)
{
OOParseState *state = (OOParseState *)gsf_state;
xmlChar const *name = NULL;
xmlChar const *base_str = NULL;
xmlChar const *expr_str = NULL;
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
if (!strcmp (attrs[0], "table:name"))
name = attrs[1];
else if (!strcmp (attrs[0], "table:base-cell-address"))
base_str = attrs[1];
else if (!strcmp (attrs[0], "table:expression"))
expr_str = attrs[1];
if (name != NULL && base_str != NULL && expr_str != NULL) {
ParseError perr;
ParsePos pp;
GnmExpr const *expr;
char *tmp = g_strconcat ("[", base_str, "]", NULL);
parse_error_init (&perr);
parse_pos_init (&pp, state->pos.wb, NULL, 0, 0);
expr = oo_expr_parse_str (tmp, &pp,
GNM_EXPR_PARSE_FORCE_EXPLICIT_SHEET_REFERENCES,
&perr);
g_free (tmp);
if (expr == NULL || expr->any.oper != GNM_EXPR_OP_CELLREF) {
oo_warning (state, _("Unable to parse position for expression '%s' @ '%s' because '%s'"),
name, base_str, perr.message);
parse_error_free (&perr);
if (expr != NULL)
gnm_expr_unref (expr);
} else {
CellRef const *ref = &expr->cellref.ref;
parse_pos_init (&pp, state->pos.wb, ref->sheet,
ref->col, ref->row);
gnm_expr_unref (expr);
expr = oo_expr_parse_str (expr_str, &pp, 0, &perr);
if (expr == NULL) {
oo_warning (state, _("Unable to parse position for expression '%s' with value '%s' because '%s'"),
name, expr_str, perr.message);
parse_error_free (&perr);
} else {
GnmNamedExpr *nexpr = expr_name_lookup (&pp, name);
pp.sheet = NULL;
if (nexpr == NULL)
expr_name_add (&pp, name, expr, NULL);
else
expr_name_set_expr (nexpr, expr, NULL);
}
}
}
}
static GsfXmlSAXNode opencalc_dtd[] = {
GSF_XML_SAX_NODE (START, START, NULL, FALSE, NULL, NULL, 0),
GSF_XML_SAX_NODE (START, OFFICE, "office:document-content", FALSE, NULL, NULL, 0),
......@@ -630,7 +708,7 @@ GSF_XML_SAX_NODE (START, OFFICE, "office:document-content", FALSE, NULL, NULL, 0
GSF_XML_SAX_NODE (TABLE_ROW_GROUP, TABLE_ROW_GROUP, "table:table-row-group", FALSE, NULL, NULL, 0),
GSF_XML_SAX_NODE (TABLE_ROW_GROUP, TABLE_ROW, "table:table-row", FALSE, NULL, NULL, 0), /* 2nd def */
GSF_XML_SAX_NODE (OFFICE_BODY, NAMED_EXPRS, "table:named-expressions", FALSE, NULL, NULL, 0),
GSF_XML_SAX_NODE (NAMED_EXPRS, NAMED_EXPR, "table:named-expression", FALSE, NULL, NULL, 0),
GSF_XML_SAX_NODE (NAMED_EXPRS, NAMED_EXPR, "table:named-expression", FALSE, &oo_named_expr, NULL, 0),
{ NULL }
};
......
......@@ -210,7 +210,6 @@ cell_calc_span (Cell const *cell, int *col1, int *col2)
/*
* Report only one column is used if
* - Cell has an expression
* - Cell is in a hidden col
* - Cell is a number
* - Cell is the top left of a merged cell
......@@ -231,8 +230,7 @@ cell_calc_span (Cell const *cell, int *col1, int *col2)
if (align == HALIGN_LEFT || align == HALIGN_RIGHT)
indented_w += cell_rendered_offset (cell);
if (cell_has_expr (cell) ||
cell_is_blank (cell) ||
if (cell_is_blank (cell) ||
!cell->col_info->visible ||
(align != HALIGN_CENTER_ACROSS_SELECTION &&
(mstyle_get_wrap_text (mstyle) ||
......@@ -387,3 +385,38 @@ cell_calc_span (Cell const *cell, int *col1, int *col2)
g_warning ("Unknown horizontal alignment type %d.", align);
} /* switch */
}
void
row_calc_spans (ColRowInfo *rinfo, Sheet const *sheet)
{
int left, right, col, row = rinfo->pos;
Range const *merged;
Cell *cell;
row_destroy_span (rinfo);
for (col = 0 ; col < SHEET_MAX_COLS ; ) {
cell = sheet_cell_get (sheet, col, row);
if (cell == NULL) {
col++;
continue;
}
if (cell_is_merged (cell)) {
merged = sheet_merge_is_corner (sheet, &cell->pos);
if (NULL != merged) {
col = merged->end.col + 1;
continue;
}
}
cell_render_value ((Cell *)cell, TRUE);
cell_calc_span (cell, &left, &right);
if (left != right) {
cell_register_span (cell, left, right);
col = right + 1;
} else
col++;
}
rinfo->needs_respan = FALSE;
}
......@@ -8,13 +8,15 @@ typedef struct {
int left, right;
} CellSpanInfo;
/* Information about cells whose contents span columns */
CellSpanInfo const * row_span_get (ColRowInfo const *ri, int col);
void cell_calc_span (Cell const *cell, int *col1, int *col2);
/* Management routines for spans */
void cell_register_span (Cell const *cell, int left, int right);
void cell_unregister_span (Cell const *cell);
void row_destroy_span (ColRowInfo *ri);
CellSpanInfo const *row_span_get (ColRowInfo const *ri, int col);
void row_destroy_span (ColRowInfo *ri);
void row_calc_spans (ColRowInfo *ri, Sheet const *sheet);
#endif /* GNUMERIC_CELLSPAN_H */
......@@ -29,6 +29,9 @@
#include "parse-util.h"
#include "selection.h"
#include "ranges.h"
#include "sheet-merge.h"
#include "cell.h"
#include "cellspan.h"
void
colrow_compute_pixels_from_pts (ColRowInfo *cri,
......
......@@ -21,6 +21,7 @@ struct _ColRowInfo {
unsigned visible : 1; /* visible */
unsigned filtered : 1; /* hidden as a result of a filter (requires !visible) */
unsigned in_filter : 1; /* filtered */
unsigned needs_respan : 1; /* mark a row as needing span generation */
/* TODO : Add per row/col min/max */
......@@ -116,5 +117,4 @@ int colrow_find_adjacent_visible (Sheet *sheet, gboolean is_col,
void rows_height_update (Sheet *sheet, Range const *range,
gboolean shrink);
#endif /* GNUMERIC_COLROW_H */
......@@ -1102,6 +1102,7 @@ iterate :
printf ("} (%d)\n", iterating == NULL);
#endif
cell->base.flags &= ~DEPENDENT_BEING_CALCULATED;
cell->row_info->needs_respan = TRUE;
return iterating == NULL;
}
......
......@@ -460,6 +460,12 @@ item_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
}
}
/* its safe to const_cast because only the a non-default row
* will ever get flagged.
*/
if (ri->needs_respan)
row_calc_spans ((ColRowInfo *)ri, sheet);
for (col = start_col, x = diff_x; col <= end_col ; col++) {
MStyle const *style;
CellSpanInfo const *span;
......
......@@ -388,25 +388,28 @@ parse_string_as_value (GnmExpr *str)
}
/**
* parse_string_as_value_or_name :
* parser_lookup_name :
* @str : An expression with oper constant, whose value is a string.
*
* Check to see if a string is a name
* if it is not check to see if it can be parsed as a value
* if it is not create a placeholder for it.
*/
static GnmExpr *
parse_string_as_value_or_name (GnmExpr *str)
parser_lookup_name (GnmExpr *str)
{
GnmNamedExpr *expr_name;
expr_name = expr_name_lookup (state->pos, str->constant.value->v_str.val->str);
if (expr_name != NULL) {
unregister_allocation (str);
gnm_expr_unref (str);
return register_expr_allocation (gnm_expr_new_name (expr_name, NULL, NULL));
char const *name = str->constant.value->v_str.val->str;
GnmNamedExpr *nexpr;
nexpr = expr_name_lookup (state->pos, name);
if (nexpr == NULL) {
ParsePos pp = *state->pos;
pp.sheet = NULL;
nexpr = expr_name_add (&pp, name, NULL, NULL);
}
return parse_string_as_value (str);
unregister_allocation (str);
gnm_expr_unref (str);
return register_expr_allocation (gnm_expr_new_name (nexpr, NULL, NULL));
}
static Sheet *
......@@ -490,7 +493,7 @@ opt_exp : opt_exp exp SEPARATOR {
exp: CONSTANT { $$ = $1; }
| QUOTED_STRING { $$ = $1; }
| STRING { $$ = parse_string_as_value_or_name ($1); }
| STRING { $$ = parser_lookup_name ($1); }
| cellref { $$ = $1; }
| exp '+' exp { $$ = build_binop ($1, GNM_EXPR_OP_ADD, $3); }
| exp '-' exp { $$ = build_binop ($1, GNM_EXPR_OP_SUB, $3); }
......@@ -540,8 +543,8 @@ exp: CONSTANT { $$ = $1; }
}
| function
| sheetref string_opt_quote {
GnmNamedExpr *expr_name = NULL;
| sheetref STRING {
GnmNamedExpr *nexpr = NULL;
char const *name = $2->constant.value->v_str.val->str;
ParsePos pos = *state->pos;
......@@ -554,22 +557,22 @@ exp: CONSTANT { $$ = $1; }
name),
state->expr_text - state->expr_backup + 1, strlen (name));
else {
expr_name = expr_name_lookup (&pos, name);
if (expr_name == NULL)
nexpr = expr_name_lookup (&pos, name);
if (nexpr == NULL)
gnumeric_parse_error (state, PERR_UNKNOWN_NAME,
g_strdup_printf (_("Name '%s' does not exist in sheet '%s'"),
name, pos.sheet->name_quoted),
state->expr_text - state->expr_backup + 1, strlen (name));
}
if (expr_name == NULL) {
if (nexpr == NULL) {
YYERROR;
}
unregister_allocation ($2); gnm_expr_unref ($2);
$$ = register_expr_allocation (gnm_expr_new_name (expr_name, $1.first, NULL));
$$ = register_expr_allocation (gnm_expr_new_name (nexpr, $1.first, NULL));
}
| '[' string_opt_quote ']' string_opt_quote {
GnmNamedExpr *expr_name;
| '[' string_opt_quote ']' STRING {
GnmNamedExpr *nexpr;
char *name = $4->constant.value->v_str.val->str;
char *wb_name = $2->constant.value->v_str.val->str;
ParsePos pos = *state->pos;
......@@ -584,8 +587,8 @@ exp: CONSTANT { $$ = $1; }
YYERROR;
}
expr_name = expr_name_lookup (&pos, name);
if (expr_name == NULL) {
nexpr = expr_name_lookup (&pos, name);
if (nexpr == NULL) {
gnumeric_parse_error (state, PERR_UNKNOWN_NAME,
g_strdup_printf (_("Name '%s' does not exist in workbook '%s'"),
name, wb_name),
......@@ -595,7 +598,7 @@ exp: CONSTANT { $$ = $1; }
unregister_allocation ($4); gnm_expr_unref ($4);
unregister_allocation ($2); gnm_expr_unref ($2);
}
$$ = register_expr_allocation (gnm_expr_new_name (expr_name, NULL, pos.wb));
$$ = register_expr_allocation (gnm_expr_new_name (nexpr, NULL, pos.wb));
}
;
......
......@@ -688,6 +688,12 @@ print_cell_range (GnomePrintContext *context,
}
}
/* its safe to const_cast because only the a non-default row
* will ever get flagged.
*/
if (ri->needs_respan)
row_calc_spans ((ColRowInfo *)ri, sheet);
for (col = start_col, x = base_x; col <= end_col ; col++) {
MStyle const *style;
CellSpanInfo const *span;
......
......@@ -1085,7 +1085,7 @@ global_range_parse (Sheet *sheet, char const *str)
&rangeref_parse, NULL);
if (expr != NULL) {
Value * value = gnm_expr_get_range (expr);
Value *value = gnm_expr_get_range (expr);
gnm_expr_unref (expr);
return value;
}
......
......@@ -484,6 +484,7 @@ sheet_row_new (Sheet *sheet)
g_return_val_if_fail (IS_SHEET (sheet), NULL);
*ri = sheet->rows.default_style;
ri->needs_respan = TRUE;
return ri;
}
......@@ -641,6 +642,13 @@ sheet_colrow_fit_gutter (Sheet const *sheet, gboolean is_cols)
return outline_level;
}
static gboolean
cb_recalc_spans (ColRowInfo *ri, gpointer user)
{
ri->needs_respan = TRUE;
return FALSE;
}
/**
* sheet_update_only_grid :
*
......@@ -695,9 +703,13 @@ sheet_update_only_grid (Sheet const *sheet)
* col flag. Then add a flag clearing loop after the
* sheet_calc_span.
*/
#if 0
sheet_calc_spans (sheet, SPANCALC_RESIZE|SPANCALC_RE_RENDER |
(p->recompute_visibility ?
SPANCALC_NO_DRAW : SPANCALC_SIMPLE));
#endif
colrow_foreach (&sheet->rows, 0, SHEET_MAX_ROWS-1,
&cb_recalc_spans, NULL);
}
if (p->reposition_objects.row < SHEET_MAX_ROWS ||
......
......@@ -327,7 +327,7 @@ workbook_init (GObject *object)
wb->iteration.enabled = FALSE;
wb->iteration.max_number = 100;
wb->iteration.tolerance = .001;
wb->auto_recalc;
wb->auto_recalc = TRUE;
wb->file_format_level = FILE_FL_NEW;
wb->file_saver = NULL;
......
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