Commit 1bca36de authored by Michael Meeks's avatar Michael Meeks

Finished print setups XML I/O,

Implemented array syntax,
INDEX, MATCH - stab at,
fatal bug in workbook destroy nailed,
initial display of icon fixed,
Printer dialog now updates margins correctly.
parent 78aec907
1999-09-13 Michael Meeks <michael@nuclecu.unam.mx>
* src/parser.y (forget_array): Created. exp: added array_row, array_exp,
array_cols: created. (build_array): Implemented. (v_forget): added.
* src/value.c (value_release): Update Array to only free if != NULL.
* src/functions/fn-lookup.c (lookup_functions_init): add index.
(gnumeric_index): Ghastly placeholder; we need more core functionality.
(gnumeric_lookup): remove redundant value_duplicate fixing leak.
(gnumeric_match): Implement as far as it goes.
* src/workbook.c (workbook_delete_event): Nail fatal bug in #define for bonobo.
* src/dialogs/dialog-printer-setup.c (dialog_print_info_new): Moved things into
constructor and out of (dialog_printer_setup).
(unit_changed): actually update the margin UnitInfo's value...
* src/xml-io.c (xml_read_print_info, xml_write_print_info, xml_get_print_hf),
(xml_set_print_hf): Header / footer, paper size writing.
1999-09-13 Karl Eichwalder <ke@suse.de>
* src/dialogs/hf-config.glade: Add missing `:'. Is this the right
......
......@@ -20,8 +20,9 @@ Michael:
* More intelligent workbook sizing.
* Fixed sheet tab focus / editing.
* Per sheet page setup / preview.
* Excel print setups importing.
* XML load / save some print setups.
* Print setups XML I/O & Excel importing
* Functions MATCH & INDEX started.
* Array input parser.
Miguel:
* Implemented Print Preview
......
1999-09-13 Michael Meeks <michael@nuclecu.unam.mx>
* src/parser.y (forget_array): Created. exp: added array_row, array_exp,
array_cols: created. (build_array): Implemented. (v_forget): added.
* src/value.c (value_release): Update Array to only free if != NULL.
* src/functions/fn-lookup.c (lookup_functions_init): add index.
(gnumeric_index): Ghastly placeholder; we need more core functionality.
(gnumeric_lookup): remove redundant value_duplicate fixing leak.
(gnumeric_match): Implement as far as it goes.
* src/workbook.c (workbook_delete_event): Nail fatal bug in #define for bonobo.
* src/dialogs/dialog-printer-setup.c (dialog_print_info_new): Moved things into
constructor and out of (dialog_printer_setup).
(unit_changed): actually update the margin UnitInfo's value...
* src/xml-io.c (xml_read_print_info, xml_write_print_info, xml_get_print_hf),
(xml_set_print_hf): Header / footer, paper size writing.
1999-09-13 Karl Eichwalder <ke@suse.de>
* src/dialogs/hf-config.glade: Add missing `:'. Is this the right
......
......@@ -500,8 +500,8 @@ gnumeric_lookup (FunctionEvalInfo *ei, Value **args)
return value_duplicate
(value_duplicate(value_area_fetch_x_y
(&ei->pos, dest,
next_largest_x+x_offset,
next_largest_y+y_offset)));
next_largest_x + x_offset,
next_largest_y + y_offset)));
if (compare < 0) {
next_largest = v;
next_largest_x = lpx;
......@@ -525,6 +525,113 @@ gnumeric_lookup (FunctionEvalInfo *ei, Value **args)
}
}
static char *help_match = {
N_("@FUNCTION=MATCH\n"
"@SYNTAX=MATCH(seek,vector1[,type])\n"
"@DESCRIPTION="
"The MATCH function finds the row index of 'value' in @vector1 "
"and returns it."
"If the area is longer than it is wide then the sense of the "
"search is rotated. Alternatively a single array can be used."
"if type = 1, finds largest value <= seek,"
"if type = 0, finds first value == seek,"
"if type = -1, finds smallest value >= seek,"
"\n"
"If LOOKUP can't find @value it uses the next largest value less "
"than value. "
"The data must be sorted. "
"\n"
"If @value is smaller than the first value it returns #N/A"
"\n"
"@EXAMPLES=\n"
"\n"
"@SEEALSO=LOOKUP")
};
/*
* Not very convinced this is accurate.
*/
static Value *
gnumeric_match (FunctionEvalInfo *ei, Value **args)
{
int height, width;
const Value *next_largest = NULL;
int next_largest_x = 0;
int next_largest_y = 0;
int type;
height = value_area_get_height (&ei->pos, args[1]);
width = value_area_get_width (&ei->pos, args[1]);
if (args[2])
type = value_get_as_int (args[2]);
else
type = 1;
if ((args[1]->type == VALUE_ARRAY)) {
if (args[2])
return value_new_error (&ei->pos, _("Type Mismatch"));
} else if (args[1]->type == VALUE_CELLRANGE) {
if (!args[2])
return value_new_error (&ei->pos, _("Invalid number of arguments"));
} else
return value_new_error (&ei->pos, _("Type Mismatch"));
{
int x_offset=0, y_offset=0, lpx, lpy, maxx, maxy;
int tmp, compare, touched;
if (args[1]->type == VALUE_ARRAY) {
if (width > height)
y_offset = 1;
else
x_offset = 1;
}
maxy = value_area_get_height (&ei->pos, args[1]);
maxx = value_area_get_width (&ei->pos, args[1]);
if ((tmp = value_area_get_height (&ei->pos, args[1])) < maxy)
maxy = tmp;
if ((tmp = value_area_get_width (&ei->pos, args[1])) < maxx)
maxx = tmp;
touched = 0;
for (lpx = 0, lpy = 0;lpx < maxx && lpy < maxy;) {
const Value *v = value_area_fetch_x_y (&ei->pos, args[1], lpx, lpy);
compare = lookup_similar (v, args[0], next_largest, 1);
if (compare == 1) {
if (width > height)
return value_new_int (lpx + 1);
else
return value_new_int (lpy + 1);
}
if (compare < 0) {
next_largest = v;
next_largest_x = lpx;
next_largest_y = lpy;
} else
break;
if (width > height)
lpx++;
else
lpy++;
}
if (!next_largest && type != -1)
return value_new_error (&ei->pos, gnumeric_err_NA);
if (width > height)
return value_new_int (lpx + 1);
else
return value_new_int (lpy + 1);
}
}
/***************************************************************************/
static char *help_indirect = {
......@@ -586,6 +693,60 @@ gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
return value_duplicate (cell->value);
}
/*
* FIXME: The concept of multiple range references needs core support.
* hence this whole implementation is a cop-out really.
*/
static char *help_index = {
N_("@FUNCTION=INDEX\n"
"@SYNTAX=INDEX(reference, [row, col, area])\n"
"@DESCRIPTION="
"The INDEX function returns a reference to the cell at a offset "
"into the reference specified by row, col."
"\n"
"If things go wrong returns #REF! "
"\n"
"@EXAMPLES=\n"
"\n"
"@SEEALSO=")
};
static Value *
gnumeric_index (FunctionEvalInfo *ei, Value **args)
{
Value *area = args[0];
int col_off = 0, row_off = 0;
if (args[3] &&
value_get_as_int (args[3]) != 1) {
g_warning ("Multiple range references unimplemented");
return value_new_error (&ei->pos, gnumeric_err_REF);
}
if (args[1])
row_off = value_get_as_int (args[1]) - 1;
if (args[2])
col_off = value_get_as_int (args[2]) - 1;
if (args[0]->type != VALUE_ARRAY) {
g_warning ("Non array indexes unimplemented");
return value_new_error (&ei->pos, gnumeric_err_VALUE);
}
if (col_off < 0 ||
col_off >= value_area_get_width (&ei->pos, area))
return value_new_error (&ei->pos, gnumeric_err_NUM);
if (row_off < 0 ||
row_off >= value_area_get_height (&ei->pos, area))
return value_new_error (&ei->pos, gnumeric_err_REF);
return value_duplicate (value_area_fetch_x_y (&ei->pos, area, col_off, row_off));
}
/***************************************************************************/
static char *help_column = {
......@@ -888,9 +1049,9 @@ void lookup_functions_init()
"row_num,col_num,abs_num,a1,text",
&help_address, gnumeric_address);
function_add_nodes (cat, "choose", 0, "index,value...",
&help_choose, gnumeric_choose);
&help_choose, gnumeric_choose);
function_add_nodes (cat, "column", "?", "ref",
&help_column, gnumeric_column);
&help_column, gnumeric_column);
function_add_args (cat, "columns", "A", "ref",
&help_columns, gnumeric_columns);
function_add_args (cat, "hlookup",
......@@ -901,13 +1062,16 @@ void lookup_functions_init()
&help_hyperlink, gnumeric_hyperlink);
function_add_args (cat, "indirect", "s|b","ref_string,format",
&help_indirect, gnumeric_indirect);
function_add_args (cat, "index", "A|fff","reference,row,col,area",
&help_index, gnumeric_index);
function_add_args (cat, "lookup", "?A|r", "val,range,range",
&help_lookup, gnumeric_lookup);
function_add_args (cat, "offset",
"rff|ff","ref,row,col,hight,width",
&help_offset, gnumeric_offset);
&help_lookup, gnumeric_lookup);
function_add_args (cat, "match", "?A|f", "val,range,approx",
&help_match, gnumeric_match);
function_add_args (cat, "offset", "rff|ff","ref,row,col,hight,width",
&help_offset, gnumeric_offset);
function_add_nodes (cat, "row", "?", "ref",
&help_row, gnumeric_row);
&help_row, gnumeric_row);
function_add_args (cat, "rows", "A", "ref",
&help_rows, gnumeric_rows);
function_add_args (cat, "transpose","A",
......
......@@ -99,7 +99,7 @@ load_image (const char *name)
static void
preview_page_destroy (dialog_print_info_t *dpi)
{
if (dpi->preview.group){
if (dpi->preview.group) {
gtk_object_destroy (GTK_OBJECT (dpi->preview.group));
dpi->preview.group = NULL;
......@@ -148,7 +148,7 @@ preview_page_create (dialog_print_info_t *dpi)
double width, height;
PreviewInfo *pi = &dpi->preview;
width = gnome_paper_pswidth (dpi->paper);
width = gnome_paper_pswidth (dpi->paper);
height = gnome_paper_psheight (dpi->paper);
if (width < height)
......@@ -156,7 +156,7 @@ preview_page_create (dialog_print_info_t *dpi)
else
pi->scale = PAGE_X / width;
pi->offset_x = (PREVIEW_X - (width * pi->scale)) / 2;
pi->offset_x = (PREVIEW_X - (width * pi->scale)) / 2;
pi->offset_y = (PREVIEW_Y - (height * pi->scale)) / 2;
/* pi->offset_x = pi->offset_y = 0; */
x1 = pi->offset_x + 0 * pi->scale;
......@@ -206,7 +206,6 @@ canvas_update (dialog_print_info_t *dpi)
dpi->current_paper = dpi->paper;
preview_page_create (dpi);
}
}
static void
......@@ -262,7 +261,7 @@ add_unit (GtkWidget *menu, int i, void (*convert)(GtkWidget *, UnitInfo *), void
static void
unit_changed (GtkSpinButton *spin_button, UnitInfo *target)
{
target->value = target->adj->value;
}
static GtkWidget *
......@@ -796,6 +795,12 @@ dialog_print_info_new (Sheet *sheet)
dpi->sheet = sheet;
dpi->gui = gui;
dpi->pi = sheet->print_info;
do_setup_main_dialog (dpi);
do_setup_margin (dpi);
do_setup_hf (dpi);
do_setup_page_info (dpi);
do_setup_page (dpi);
return dpi;
}
......@@ -852,10 +857,10 @@ do_fetch_margins (dialog_print_info_t *dpi)
PrintMargins *m = &dpi->pi->margins;
GtkToggleButton *t;
m->top = unit_info_to_print_unit (&dpi->margins.top);
m->top = unit_info_to_print_unit (&dpi->margins.top);
m->bottom = unit_info_to_print_unit (&dpi->margins.bottom);
m->left = unit_info_to_print_unit (&dpi->margins.left);
m->right = unit_info_to_print_unit (&dpi->margins.right);
m->left = unit_info_to_print_unit (&dpi->margins.left);
m->right = unit_info_to_print_unit (&dpi->margins.right);
m->header = unit_info_to_print_unit (&dpi->margins.header);
m->footer = unit_info_to_print_unit (&dpi->margins.footer);
......@@ -940,15 +945,9 @@ dialog_printer_setup (Sheet *sheet)
if (!dpi)
return;
do_setup_main_dialog (dpi);
do_setup_margin (dpi);
do_setup_hf (dpi);
do_setup_page_info (dpi);
do_setup_page (dpi);
v = gnome_dialog_run (GNOME_DIALOG (dpi->dialog));
if (v == 0){
if (v == 0) {
fetch_settings (dpi);
print_info_save (dpi->pi);
}
......@@ -958,8 +957,3 @@ dialog_printer_setup (Sheet *sheet)
dialog_print_info_destroy (dpi);
}
......@@ -500,8 +500,8 @@ gnumeric_lookup (FunctionEvalInfo *ei, Value **args)
return value_duplicate
(value_duplicate(value_area_fetch_x_y
(&ei->pos, dest,
next_largest_x+x_offset,
next_largest_y+y_offset)));
next_largest_x + x_offset,
next_largest_y + y_offset)));
if (compare < 0) {
next_largest = v;
next_largest_x = lpx;
......@@ -525,6 +525,113 @@ gnumeric_lookup (FunctionEvalInfo *ei, Value **args)
}
}
static char *help_match = {
N_("@FUNCTION=MATCH\n"
"@SYNTAX=MATCH(seek,vector1[,type])\n"
"@DESCRIPTION="
"The MATCH function finds the row index of 'value' in @vector1 "
"and returns it."
"If the area is longer than it is wide then the sense of the "
"search is rotated. Alternatively a single array can be used."
"if type = 1, finds largest value <= seek,"
"if type = 0, finds first value == seek,"
"if type = -1, finds smallest value >= seek,"
"\n"
"If LOOKUP can't find @value it uses the next largest value less "
"than value. "
"The data must be sorted. "
"\n"
"If @value is smaller than the first value it returns #N/A"
"\n"
"@EXAMPLES=\n"
"\n"
"@SEEALSO=LOOKUP")
};
/*
* Not very convinced this is accurate.
*/
static Value *
gnumeric_match (FunctionEvalInfo *ei, Value **args)
{
int height, width;
const Value *next_largest = NULL;
int next_largest_x = 0;
int next_largest_y = 0;
int type;
height = value_area_get_height (&ei->pos, args[1]);
width = value_area_get_width (&ei->pos, args[1]);
if (args[2])
type = value_get_as_int (args[2]);
else
type = 1;
if ((args[1]->type == VALUE_ARRAY)) {
if (args[2])
return value_new_error (&ei->pos, _("Type Mismatch"));
} else if (args[1]->type == VALUE_CELLRANGE) {
if (!args[2])
return value_new_error (&ei->pos, _("Invalid number of arguments"));
} else
return value_new_error (&ei->pos, _("Type Mismatch"));
{
int x_offset=0, y_offset=0, lpx, lpy, maxx, maxy;
int tmp, compare, touched;
if (args[1]->type == VALUE_ARRAY) {
if (width > height)
y_offset = 1;
else
x_offset = 1;
}
maxy = value_area_get_height (&ei->pos, args[1]);
maxx = value_area_get_width (&ei->pos, args[1]);
if ((tmp = value_area_get_height (&ei->pos, args[1])) < maxy)
maxy = tmp;
if ((tmp = value_area_get_width (&ei->pos, args[1])) < maxx)
maxx = tmp;
touched = 0;
for (lpx = 0, lpy = 0;lpx < maxx && lpy < maxy;) {
const Value *v = value_area_fetch_x_y (&ei->pos, args[1], lpx, lpy);
compare = lookup_similar (v, args[0], next_largest, 1);
if (compare == 1) {
if (width > height)
return value_new_int (lpx + 1);
else
return value_new_int (lpy + 1);
}
if (compare < 0) {
next_largest = v;
next_largest_x = lpx;
next_largest_y = lpy;
} else
break;
if (width > height)
lpx++;
else
lpy++;
}
if (!next_largest && type != -1)
return value_new_error (&ei->pos, gnumeric_err_NA);
if (width > height)
return value_new_int (lpx + 1);
else
return value_new_int (lpy + 1);
}
}
/***************************************************************************/
static char *help_indirect = {
......@@ -586,6 +693,60 @@ gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
return value_duplicate (cell->value);
}
/*
* FIXME: The concept of multiple range references needs core support.
* hence this whole implementation is a cop-out really.
*/
static char *help_index = {
N_("@FUNCTION=INDEX\n"
"@SYNTAX=INDEX(reference, [row, col, area])\n"
"@DESCRIPTION="
"The INDEX function returns a reference to the cell at a offset "
"into the reference specified by row, col."
"\n"
"If things go wrong returns #REF! "
"\n"
"@EXAMPLES=\n"
"\n"
"@SEEALSO=")
};
static Value *
gnumeric_index (FunctionEvalInfo *ei, Value **args)
{
Value *area = args[0];
int col_off = 0, row_off = 0;
if (args[3] &&
value_get_as_int (args[3]) != 1) {
g_warning ("Multiple range references unimplemented");
return value_new_error (&ei->pos, gnumeric_err_REF);
}
if (args[1])
row_off = value_get_as_int (args[1]) - 1;
if (args[2])
col_off = value_get_as_int (args[2]) - 1;
if (args[0]->type != VALUE_ARRAY) {
g_warning ("Non array indexes unimplemented");
return value_new_error (&ei->pos, gnumeric_err_VALUE);
}
if (col_off < 0 ||
col_off >= value_area_get_width (&ei->pos, area))
return value_new_error (&ei->pos, gnumeric_err_NUM);
if (row_off < 0 ||
row_off >= value_area_get_height (&ei->pos, area))
return value_new_error (&ei->pos, gnumeric_err_REF);
return value_duplicate (value_area_fetch_x_y (&ei->pos, area, col_off, row_off));
}
/***************************************************************************/
static char *help_column = {
......@@ -888,9 +1049,9 @@ void lookup_functions_init()
"row_num,col_num,abs_num,a1,text",
&help_address, gnumeric_address);
function_add_nodes (cat, "choose", 0, "index,value...",
&help_choose, gnumeric_choose);
&help_choose, gnumeric_choose);
function_add_nodes (cat, "column", "?", "ref",
&help_column, gnumeric_column);
&help_column, gnumeric_column);
function_add_args (cat, "columns", "A", "ref",
&help_columns, gnumeric_columns);
function_add_args (cat, "hlookup",
......@@ -901,13 +1062,16 @@ void lookup_functions_init()
&help_hyperlink, gnumeric_hyperlink);
function_add_args (cat, "indirect", "s|b","ref_string,format",
&help_indirect, gnumeric_indirect);
function_add_args (cat, "index", "A|fff","reference,row,col,area",
&help_index, gnumeric_index);
function_add_args (cat, "lookup", "?A|r", "val,range,range",
&help_lookup, gnumeric_lookup);
function_add_args (cat, "offset",
"rff|ff","ref,row,col,hight,width",
&help_offset, gnumeric_offset);
&help_lookup, gnumeric_lookup);
function_add_args (cat, "match", "?A|f", "val,range,approx",
&help_match, gnumeric_match);
function_add_args (cat, "offset", "rff|ff","ref,row,col,hight,width",
&help_offset, gnumeric_offset);
function_add_nodes (cat, "row", "?", "ref",
&help_row, gnumeric_row);
&help_row, gnumeric_row);
function_add_args (cat, "rows", "A", "ref",
&help_rows, gnumeric_rows);
function_add_args (cat, "transpose","A",
......
......@@ -25,9 +25,11 @@ static void register_symbol (Symbol *sym);
static void alloc_clean (void);
static void alloc_glist (GList *l);
static void forget_glist (GList *list);
static void forget_array (GList *array);
static void forget_tree (ExprTree *tree);
static void alloc_list_free (void);
static Value*v_new (void);
static void v_forget (Value *v);
#define ERROR -1
......@@ -110,6 +112,55 @@ build_array_formula (ExprTree * func,
return res;
}
static ExprTree *
build_array (GList *cols)
{
Value *array;
GList *row;
int x, mx, y;
if (!cols) {
parser_error = PARSE_ERR_SYNTAX;
return NULL;
}
mx = 0;
row = cols->data;
while (row) {
mx++;
row = g_list_next (row);
}
array = value_new_array_empty (mx, g_list_length (cols));
y = 0;
while (cols) {
row = cols->data;
x = 0;
while (row && x < mx) {
ExprTree *expr = row->data;
Value *v = expr->u.constant;
g_assert (expr->oper == OPER_CONSTANT);
value_array_set (array, x, y, v);
v_forget (v);
x++;
row = g_list_next (row);
}
if (x < mx || row) {
parser_error = PARSE_ERR_SYNTAX;
value_release (array);
return NULL;
}
y++;
cols = g_list_next (cols);
}
return expr_tree_new_constant (array);
}
%}
%union {
......@@ -118,8 +169,8 @@ build_array_formula (ExprTree * func,
GList *list;
Sheet *sheetref;
}
%type <tree> exp
%type <list> arg_list
%type <tree> exp array_exp
%type <list> arg_list array_row, array_cols
%token <tree> NUMBER STRING FUNCALL CONSTANT CELLREF GTE LTE NE
%token <sheetref> SHEETREF
%token SEPARATOR
......@@ -170,10 +221,15 @@ exp: NUMBER { $$ = $1 }
$$ = $2;
}
| '{' array_cols '}' {
$$ = build_array ($2);
forget_array ($2);
}
| cellref ':' cellref {
$$ = p_new (ExprTree);
$$->ref_count = 1;
$$->oper = OPER_CONSTANT;
$$->ref_count = 1;
$$->oper = OPER_CONSTANT;
$$->u.constant = v_new ();
$$->u.constant->type = VALUE_CELLRANGE;
$$->u.constant->v.cell_range.cell_a = $1->u.ref;
......@@ -211,6 +267,34 @@ arg_list: exp {
}
| { $$ = NULL; }
;
array_exp: NUMBER { $$ = $1 }
| STRING { $$ = $1 }