Commit bb970ba0 authored by Michael Meeks's avatar Michael Meeks

Fixed leak in INDIRECT,

Implemented R1C1 style references in INDIRECT,
Implemented non-relative R1C1 references in expressions.
parent 637e6a62
1999-08-16 Michael Meeks <michael@imaginator.com>
* src/fn-lookup.c (gnumeric_indirect): Fix leak
Update to use new cellref_*_get functions.
* src/parser.y (return_cellref): Use new function.
* src/sheet.c (cellref_get): Implemented
(cellref_a1_get): Snarf from parser.y :-)
(cellref_r1c1_get): Implemented.
1999-08-17 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/workbook.c (workbook_class_init): Added cell_content_changed
......
......@@ -16,8 +16,9 @@ Michael:
* Added GUI for Names.
* Better Excel string importing.
* Fix for padded number insertion ( fixes CSV import )
* Implemented ISREF, improved CELL & INDIRECT.
* Implemented ISREF, INDIRECT improved CELL
* Fixed several database functions.
* Non-relative R1C1 style references.
Jody:
* Enable Array formulas.
......
1999-08-16 Michael Meeks <michael@imaginator.com>
* src/fn-lookup.c (gnumeric_indirect): Fix leak
Update to use new cellref_*_get functions.
* src/parser.y (return_cellref): Use new function.
* src/sheet.c (cellref_get): Implemented
(cellref_a1_get): Snarf from parser.y :-)
(cellref_r1c1_get): Implemented.
1999-08-17 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/workbook.c (workbook_class_init): Added cell_content_changed
......
......@@ -514,11 +514,10 @@ static char *help_indirect = {
static Value *
gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
{
const char* text;
char* text;
gboolean a1_style;
ExprTree *tree;
ParsePosition pp;
Cell *cell;
CellRef ref;
int col, row;
gboolean error = FALSE;
......@@ -528,19 +527,18 @@ gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
else
a1_style = TRUE;
if (error) {/* || !a1_style) { This will be flagged by gnumeric_expr_parser.
g_warning ("R1C1 style unimplemented");*/
if (error)
return value_new_error (&ei->pos, gnumeric_err_REF);
}
pp.col = ei->pos.eval_col;
pp.row = ei->pos.eval_row;
pp.wb = ei->pos.sheet->workbook;
if ((gnumeric_expr_parser (text, &pp, NULL, &tree) != PARSE_OK) ||
!tree || (tree->oper != OPER_VAR))
if (a1_style)
error = !cellref_a1_get (&ref, text, ei->pos.eval_col, ei->pos.eval_row);
else
error = !cellref_r1c1_get (&ref, text, ei->pos.eval_col, ei->pos.eval_row);
if (error)
return value_new_error (&ei->pos, gnumeric_err_REF);
cell_get_abs_col_row (&tree->u.ref, ei->pos.eval_col, ei->pos.eval_row,
cell_get_abs_col_row (&ref, ei->pos.eval_col, ei->pos.eval_row,
&col, &row);
cell = sheet_cell_get (ei->pos.sheet, col, row);
......@@ -548,6 +546,8 @@ gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
return value_new_int (0);
else
return value_duplicate (cell->value);
g_free (text);
}
static char *help_column = {
......
......@@ -514,11 +514,10 @@ static char *help_indirect = {
static Value *
gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
{
const char* text;
char* text;
gboolean a1_style;
ExprTree *tree;
ParsePosition pp;
Cell *cell;
CellRef ref;
int col, row;
gboolean error = FALSE;
......@@ -528,19 +527,18 @@ gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
else
a1_style = TRUE;
if (error) {/* || !a1_style) { This will be flagged by gnumeric_expr_parser.
g_warning ("R1C1 style unimplemented");*/
if (error)
return value_new_error (&ei->pos, gnumeric_err_REF);
}
pp.col = ei->pos.eval_col;
pp.row = ei->pos.eval_row;
pp.wb = ei->pos.sheet->workbook;
if ((gnumeric_expr_parser (text, &pp, NULL, &tree) != PARSE_OK) ||
!tree || (tree->oper != OPER_VAR))
if (a1_style)
error = !cellref_a1_get (&ref, text, ei->pos.eval_col, ei->pos.eval_row);
else
error = !cellref_r1c1_get (&ref, text, ei->pos.eval_col, ei->pos.eval_row);
if (error)
return value_new_error (&ei->pos, gnumeric_err_REF);
cell_get_abs_col_row (&tree->u.ref, ei->pos.eval_col, ei->pos.eval_row,
cell_get_abs_col_row (&ref, ei->pos.eval_col, ei->pos.eval_row,
&col, &row);
cell = sheet_cell_get (ei->pos.sheet, col, row);
......@@ -548,6 +546,8 @@ gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
return value_new_int (0);
else
return value_duplicate (cell->value);
g_free (text);
}
static char *help_column = {
......
......@@ -514,11 +514,10 @@ static char *help_indirect = {
static Value *
gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
{
const char* text;
char* text;
gboolean a1_style;
ExprTree *tree;
ParsePosition pp;
Cell *cell;
CellRef ref;
int col, row;
gboolean error = FALSE;
......@@ -528,19 +527,18 @@ gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
else
a1_style = TRUE;
if (error) {/* || !a1_style) { This will be flagged by gnumeric_expr_parser.
g_warning ("R1C1 style unimplemented");*/
if (error)
return value_new_error (&ei->pos, gnumeric_err_REF);
}
pp.col = ei->pos.eval_col;
pp.row = ei->pos.eval_row;
pp.wb = ei->pos.sheet->workbook;
if ((gnumeric_expr_parser (text, &pp, NULL, &tree) != PARSE_OK) ||
!tree || (tree->oper != OPER_VAR))
if (a1_style)
error = !cellref_a1_get (&ref, text, ei->pos.eval_col, ei->pos.eval_row);
else
error = !cellref_r1c1_get (&ref, text, ei->pos.eval_col, ei->pos.eval_row);
if (error)
return value_new_error (&ei->pos, gnumeric_err_REF);
cell_get_abs_col_row (&tree->u.ref, ei->pos.eval_col, ei->pos.eval_row,
cell_get_abs_col_row (&ref, ei->pos.eval_col, ei->pos.eval_row,
&col, &row);
cell = sheet_cell_get (ei->pos.sheet, col, row);
......@@ -548,6 +546,8 @@ gnumeric_indirect (FunctionEvalInfo *ei, Value **args)
return value_new_int (0);
else
return value_duplicate (cell->value);
g_free (text);
}
static char *help_column = {
......
......@@ -166,6 +166,10 @@ exp: NUMBER { $$ = $1 }
| '-' exp %prec NEG { $$ = build_unary_op (OPER_NEG, $2); }
| '+' exp %prec PLUS { $$ = $2; }
| '+' exp %prec PLUS {
$$ = $2;
}
| cellref ':' cellref {
$$ = p_new (ExprTree);
$$->ref_count = 1;
......@@ -212,63 +216,18 @@ arg_list: exp {
static int
return_cellref (char *p)
{
int col_relative = TRUE;
int row_relative = TRUE;
int col = 0;
int row = 0;
CellRef ref;
ExprTree *e;
CellRef *ref;
/* Try to parse a column */
if (*p == '$'){
col_relative = FALSE;
p++;
}
if (!(toupper (*p) >= 'A' && toupper (*p) <= 'Z'))
return 0;
col = toupper (*p++) - 'A';
if (toupper (*p) >= 'A' && toupper (*p) <= 'Z')
col = (col+1) * ('Z'-'A'+1) + toupper (*p++) - 'A';
/* Try to parse a row */
if (*p == '$'){
row_relative = FALSE;
p++;
}
if (!(*p >= '1' && *p <= '9'))
if (!cellref_get (&ref, p, parser_col, parser_row))
return 0;
while (isdigit ((unsigned char)*p)){
row = row * 10 + *p - '0';
p++;
}
row--;
/* Ok, parsed successfully, create the return value */
e = p_new (ExprTree);
e->ref_count = 1;
e->oper = OPER_VAR;
ref = &e->u.ref;
/* Setup the cell reference information */
if (row_relative)
ref->row = row - parser_row;
else
ref->row = row;
if (col_relative)
ref->col = col - parser_col;
else
ref->col = col;
ref->col_relative = col_relative;
ref->row_relative = row_relative;
ref->sheet = NULL;
e->oper = OPER_VAR;
e->u.ref = ref;
yylval.tree = e;
......
......@@ -6,6 +6,7 @@
*
*/
#include <config.h>
#include <ctype.h>
#include <gnome.h>
#include <string.h>
#include "gnumeric.h"
......@@ -4010,6 +4011,156 @@ cellref_name (CellRef *cell_ref, int eval_col, int eval_row)
}
}
gboolean
cellref_a1_get (CellRef *out, const char *in, int parse_col, int parse_row)
{
int col = 0;
int row = 0;
g_return_val_if_fail (in != NULL, FALSE);
g_return_val_if_fail (out != NULL, FALSE);
/* Try to parse a column */
if (*in == '$'){
out->col_relative = FALSE;
in++;
} else
out->col_relative = TRUE;
if (!(toupper (*in) >= 'A' && toupper (*in) <= 'Z'))
return FALSE;
col = toupper (*in++) - 'A';
if (toupper (*in) >= 'A' && toupper (*in) <= 'Z')
col = (col+1) * ('Z'-'A'+1) + toupper (*in++) - 'A';
/* Try to parse a row */
if (*in == '$'){
out->row_relative = FALSE;
in++;
} else
out->row_relative = TRUE;
if (!(*in >= '1' && *in <= '9'))
return FALSE;
while (isdigit ((unsigned char)*in)){
row = row * 10 + *in - '0';
in++;
}
row--;
if (*in) /* We havn't hit the end yet */
return FALSE;
/* Setup the cell reference information */
if (out->row_relative)
out->row = row - parse_row;
else
out->row = row;
if (out->col_relative)
out->col = col - parse_col;
else
out->col = col;
out->sheet = NULL;
return TRUE;
}
static gboolean
r1c1_get_item (int *num, unsigned char *rel, const char * *const in)
{
gboolean neg = FALSE;
if (**in == '[') {
(*in)++;
*rel = TRUE;
if (!**in)
return FALSE;
if (**in == '+')
(*in)++;
else if (**in == '-') {
neg = TRUE;
(*in)++;
}
}
*num = 0;
while (**in && isdigit (**in)) {
*num = *num * 10 + **in - '0';
(*in)++;
}
if (neg)
*num = -*num;
if (**in == ']')
(*in)++;
return TRUE;
}
gboolean
cellref_r1c1_get (CellRef *out, const char *in, int parse_col, int parse_row)
{
g_return_val_if_fail (in != NULL, FALSE);
g_return_val_if_fail (out != NULL, FALSE);
out->row_relative = FALSE;
out->col_relative = FALSE;
out->col = parse_col;
out->row = parse_row;
out->sheet = NULL;
if (!*in)
return FALSE;
while (*in) {
if (*in == 'R') {
in++;
if (!r1c1_get_item (&out->row, &out->row_relative, &in))
return FALSE;
} else if (*in == 'C') {
in++;
if (!r1c1_get_item (&out->col, &out->col_relative, &in))
return FALSE;
} else
return FALSE;
}
out->col--;
out->row--;
return TRUE;
}
/**
* cellref_get:
* @out: destination CellRef
* @in: reference description text, no leading or trailing
* whitespace allowed.
*
* Converts the char * representation of a Cell reference into
* an internal representation.
*
* Return value: TRUE if no format errors found.
**/
gboolean
cellref_get (CellRef *out, const char *in, int parse_col, int parse_row)
{
g_return_val_if_fail (in != NULL, FALSE);
g_return_val_if_fail (out != NULL, FALSE);
if (cellref_a1_get (out, in, parse_col, parse_row))
return TRUE;
else
return cellref_r1c1_get (out, in, parse_col, parse_row);
}
void
sheet_mark_clean (Sheet *sheet)
{
......
......@@ -368,6 +368,12 @@ void sheet_hide_cursor (Sheet *sheet);
char *cellref_name (CellRef *cell_ref,
int eval_col,
int eval_row);
gboolean cellref_get (CellRef *out, const char *in,
int parse_col, int parse_row);
gboolean cellref_a1_get (CellRef *out, const char *in,
int parse_col, int parse_row);
gboolean cellref_r1c1_get (CellRef *out, const char *in,
int parse_col, int parse_row);
/*
* Sheet, Bobobo objects
......
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