Commit 536fa980 authored by Miguel de Icaza's avatar Miguel de Icaza Committed by Arturo Espinosa

Return false if the cell name is outside the boundaries of the

1999-05-17  Miguel de Icaza  <miguel@nuclecu.unam.mx>

	* src/utils.c (parse_cell_name): Return false if the cell name is
	outside the boundaries of the spreadsheet.

	* src/corba-sheet.c (Sheet_range_set_text): Implement.
	(Sheet_range_set_formula): Implement.
	(Sheet_range_set_format): Implement.

	* src/ranges.c (range_parse, range_list_parse, range_list_destroy,
	range_list_foreach_full, range_list_foreach_all,
	range_list_foreach, range_set_style): New functions.  Used by the
	corba-sheet code.

	* src/corba-sheet.c (Sheet_range_get_values): Implement
	vector-based result return.

	* src/xml-io.c (xmlSetGnomeCanvasPoints): use g_malloc instead of alloc.

	* src/dialog-solver.c (constr_add_click): Use g_malloc instead of
	alloc.  Use g_new instead of malloc.

	* src/utils.c (parse_cell_name_list): Add parameter checking.  Use Migueestyle.
parent 08f616b9
1999-05-17 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/utils.c (parse_cell_name): Return false if the cell name is
outside the boundaries of the spreadsheet.
* src/corba-sheet.c (Sheet_range_set_text): Implement.
(Sheet_range_set_formula): Implement.
(Sheet_range_set_format): Implement.
* src/ranges.c (range_parse, range_list_parse, range_list_destroy,
range_list_foreach_full, range_list_foreach_all,
range_list_foreach, range_set_style): New functions. Used by the
corba-sheet code.
* src/corba-sheet.c (Sheet_range_get_values): Implement
vector-based result return.
* src/xml-io.c (xmlSetGnomeCanvasPoints): use g_malloc instead of alloc.
* src/dialog-solver.c (constr_add_click): Use g_malloc instead of
alloc. Use g_new instead of malloc.
* src/utils.c (parse_cell_name_list): Add parameter checking. Use Migueestyle.
1999-05-16 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/corba-workbook.c (Workbook_corba_class_init): Make it work
......
1999-05-17 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/utils.c (parse_cell_name): Return false if the cell name is
outside the boundaries of the spreadsheet.
* src/corba-sheet.c (Sheet_range_set_text): Implement.
(Sheet_range_set_formula): Implement.
(Sheet_range_set_format): Implement.
* src/ranges.c (range_parse, range_list_parse, range_list_destroy,
range_list_foreach_full, range_list_foreach_all,
range_list_foreach, range_set_style): New functions. Used by the
corba-sheet code.
* src/corba-sheet.c (Sheet_range_get_values): Implement
vector-based result return.
* src/xml-io.c (xmlSetGnomeCanvasPoints): use g_malloc instead of alloc.
* src/dialog-solver.c (constr_add_click): Use g_malloc instead of
alloc. Use g_new instead of malloc.
* src/utils.c (parse_cell_name_list): Add parameter checking. Use Migueestyle.
1999-05-16 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/corba-workbook.c (Workbook_corba_class_init): Make it work
......
1999-05-17 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/utils.c (parse_cell_name): Return false if the cell name is
outside the boundaries of the spreadsheet.
* src/corba-sheet.c (Sheet_range_set_text): Implement.
(Sheet_range_set_formula): Implement.
(Sheet_range_set_format): Implement.
* src/ranges.c (range_parse, range_list_parse, range_list_destroy,
range_list_foreach_full, range_list_foreach_all,
range_list_foreach, range_set_style): New functions. Used by the
corba-sheet code.
* src/corba-sheet.c (Sheet_range_get_values): Implement
vector-based result return.
* src/xml-io.c (xmlSetGnomeCanvasPoints): use g_malloc instead of alloc.
* src/dialog-solver.c (constr_add_click): Use g_malloc instead of
alloc. Use g_new instead of malloc.
* src/utils.c (parse_cell_name_list): Add parameter checking. Use Migueestyle.
1999-05-16 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/corba-workbook.c (Workbook_corba_class_init): Make it work
......
1999-05-17 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/utils.c (parse_cell_name): Return false if the cell name is
outside the boundaries of the spreadsheet.
* src/corba-sheet.c (Sheet_range_set_text): Implement.
(Sheet_range_set_formula): Implement.
(Sheet_range_set_format): Implement.
* src/ranges.c (range_parse, range_list_parse, range_list_destroy,
range_list_foreach_full, range_list_foreach_all,
range_list_foreach, range_set_style): New functions. Used by the
corba-sheet code.
* src/corba-sheet.c (Sheet_range_get_values): Implement
vector-based result return.
* src/xml-io.c (xmlSetGnomeCanvasPoints): use g_malloc instead of alloc.
* src/dialog-solver.c (constr_add_click): Use g_malloc instead of
alloc. Use g_new instead of malloc.
* src/utils.c (parse_cell_name_list): Add parameter checking. Use Migueestyle.
1999-05-16 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/corba-workbook.c (Workbook_corba_class_init): Make it work
......
......@@ -33,25 +33,30 @@ gnumeric_choose (Sheet *sheet, GList *expr_node_list, int eval_col, int eval_row
int index;
int argc;
Value *v;
GList *l=expr_node_list;
GList *l = expr_node_list;
argc = g_list_length(l);
if (argc<1 || !l->data) {
argc = g_list_length (l);
if (argc < 1 || !l->data){
*error_string = _("#ARG!");
return NULL;
}
v = eval_expr (sheet, l->data, eval_col, eval_row, error_string);
if (!v) return NULL;
if (v->type != VALUE_INTEGER &&
v->type != VALUE_FLOAT) {
if (!v)
return NULL;
if ((v->type != VALUE_INTEGER) && (v->type != VALUE_FLOAT)){
*error_string = _("#VALUE!");
value_release (v);
return NULL;
}
index = value_get_as_int(v);
value_release (v);
l = g_list_next (l);
while (l) {
while (l){
index--;
if (!index)
return eval_expr (sheet, l->data, eval_col, eval_row, error_string);
......@@ -89,56 +94,58 @@ lookup_similar (const Value *data, const Value *templ, const Value *next_largest
switch (templ->type){
case VALUE_INTEGER:
case VALUE_FLOAT:
{
float_t a, b;
a = value_get_as_float (data);
b = value_get_as_float (templ);
/* printf ("Num: %f %f %f\n", a, b, next_largest?value_get_as_float (next_largest):9999.0) ; */
if (a == b)
return 1;
else if (approx && a < b){
if (!next_largest)
return -1;
else if (value_get_as_float (next_largest) <= a)
return -1;
}
return 0;
break;
{
float_t a, b;
a = value_get_as_float (data);
b = value_get_as_float (templ);
if (a == b)
return 1;
else if (approx && a < b){
if (!next_largest)
return -1;
else if (value_get_as_float (next_largest) <= a)
return -1;
}
return 0;
break;
}
case VALUE_STRING:
default:
{
char *a, *b;
a = value_get_as_string (data);
b = value_get_as_string (templ);
if (approx){
ans = strcasecmp (a,b);
if (approx && ans < 0){
if (next_largest){
char *c = value_get_as_string (next_largest);
int cmp = strcasecmp (a,c);
g_free (c);
if (cmp >= 0) {
g_free (a);
g_free (b);
return -1;
}
} else {
{
char *a, *b;
a = value_get_as_string (data);
b = value_get_as_string (templ);
if (approx){
ans = strcasecmp (a,b);
if (approx && ans < 0){
if (next_largest){
char *c = value_get_as_string (next_largest);
int cmp = strcasecmp (a,c);
g_free (c);
if (cmp >= 0) {
g_free (a);
g_free (b);
return -1;
}
} else {
g_free (a);
g_free (b);
return -1;
}
}
else
ans = strcmp (a, b);
g_free (a);
g_free (b);
return (ans == 0);
break;
}
else
ans = strcmp (a, b);
g_free (a);
g_free (b);
return (ans == 0);
break;
}
}
return 0;
}
......@@ -182,7 +189,6 @@ gnumeric_vlookup (struct FunctionDefinition *i, Value *argv [], char **error_str
g_return_val_if_fail (v != NULL, NULL);
compare = lookup_similar (v, argv[0], next_largest, approx);
/* printf ("Compare '%s' with '%s' : %d (%d)\n", value_get_as_string (cell->value), value_get_as_string (argv[0]), compare, approx); */
if (compare == 1){
const Value *v;
......@@ -265,7 +271,6 @@ gnumeric_hlookup (struct FunctionDefinition *i, Value *argv [], char **error_str
g_return_val_if_fail (v != NULL, NULL);
compare = lookup_similar (v, argv[0], next_largest, approx);
/* printf ("Compare '%s' with '%s' : %d (%d)\n", value_get_as_string (cell->value), value_get_as_string (argv[0]), compare, approx); */
if (compare == 1){
const Value *v;
......@@ -475,23 +480,28 @@ gnumeric_offset (struct FunctionDefinition *i, Value *argv [], char **error_stri
CellRef b;
int tw, th;
g_return_val_if_fail (argv[0]->type == VALUE_CELLRANGE, NULL);
memcpy (&a, &argv[0]->v.cell_range.cell_a, sizeof(CellRef));
a.row+=value_get_as_int(argv[1]);
a.col+=value_get_as_int(argv[2]);
g_return_val_if_fail (argv [0]->type == VALUE_CELLRANGE, NULL);
memcpy (&a, &argv[0]->v.cell_range.cell_a, sizeof (CellRef));
a.row += value_get_as_int (argv[1]);
a.col += value_get_as_int (argv[2]);
memcpy (&b, &a, sizeof(CellRef));
tw = value_get_as_int(argv[3]);
th = value_get_as_int(argv[4]);
tw = value_get_as_int (argv[3]);
th = value_get_as_int (argv[4]);
if (tw < 0 || th < 0) {
*error_string = _("#VALUE!");
return NULL;
} else if (a.row<0 || a.col < 0) {
} else if (a.row < 0 || a.col < 0) {
*error_string = _("#REF!");
return NULL;
}
b.row+=tw;
b.col+=th;
b.row += tw;
b.col += th;
return value_new_cellrange (&a, &b);
}
......@@ -526,6 +536,7 @@ gnumeric_row (Sheet *sheet, GList *expr_node_list, int eval_col, int eval_row, c
*error_string = _("Arrays not yet supported");
value_release (v);
return NULL;
case VALUE_ARRAY:
*error_string = _("Unimplemented");
value_release (v);
......
......@@ -112,6 +112,8 @@ GNUMERIC_BASE_SOURCES = \
plugin.c \
plugin.h \
plugin-manager.c \
ranges.c \
ranges.h \
render-ascii.c \
render-ascii.h \
sheet.c \
......
......@@ -13,6 +13,7 @@
#include "Gnumeric.h"
#include "corba.h"
#include "utils.h"
#include "ranges.h"
#define verify(cond) if (!(cond)){ out_of_range (ev); return; }
#define verify_val(cond,val) if (!(cond)){ out_of_range (ev); return (val); }
......@@ -25,6 +26,12 @@
verify(c1 <= c2);\
verify (r1 <= r2);
#define verify_range(sheet,range,l) \
if (!corba_range_parse (sheet,range,l)) { out_of_range (ev); return; }
#define verify_range_val(sheet,range,l,val) \
if (!corba_range_parse (sheet,range,l)) { out_of_range (ev); return (val); }
static POA_GNOME_Gnumeric_Sheet__vepv gnome_gnumeric_sheet_vepv;
static POA_GNOME_Gnumeric_Sheet__epv gnome_gnumeric_sheet_epv;
......@@ -39,6 +46,28 @@ out_of_range (CORBA_Environment *ev)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_GNOME_Gnumeric_Sheet_OutOfRange, NULL);
}
/*
* Parses a list of ranges, returns a GList containing pointers to
* Value structures. Sets the return_list pointer to point to a
* a listof those values.
*
* Returns TRUE on successfully parsing the string, FALSE otherwise
*/
static gboolean
corba_range_parse (Sheet *sheet, const char *range_spec, GSList **return_list)
{
GSList *list;
list = range_list_parse (sheet, range_spec);
if (list){
*return_list = list;
return TRUE;
} else {
*return_list = NULL;
return FALSE;
}
}
static inline Sheet *
sheet_from_servant (PortableServer_Servant servant)
{
......@@ -263,6 +292,7 @@ Sheet_cell_set_value (PortableServer_Servant servant,
}
case GNOME_Gnumeric_VALUE_ARRAY:
v = NULL;
g_error ("FIXME: Implement me");
break;
......@@ -274,20 +304,14 @@ Sheet_cell_set_value (PortableServer_Servant servant,
cell_set_value (cell, v);
}
static GNOME_Gnumeric_Value *
Sheet_cell_get_value (PortableServer_Servant servant,
const CORBA_long col, const CORBA_long row,
CORBA_Environment * ev)
static void
fill_corba_value (GNOME_Gnumeric_Value *value, Sheet *sheet, CORBA_long col, CORBA_long row)
{
Sheet *sheet = sheet_from_servant (servant);
GNOME_Gnumeric_Value *value;
Cell *cell;
verify_col_val (col, NULL);
verify_row_val (row, NULL);
value = GNOME_Gnumeric_Value__alloc ();
g_assert (value != NULL);
g_assert (sheet != NULL);
cell = sheet_cell_get (sheet, col, row);
if (cell && cell->value){
switch (cell->value->type){
......@@ -328,6 +352,22 @@ Sheet_cell_get_value (PortableServer_Servant servant,
value->_u.v_int = 0;
}
}
static GNOME_Gnumeric_Value *
Sheet_cell_get_value (PortableServer_Servant servant,
const CORBA_long col, const CORBA_long row,
CORBA_Environment * ev)
{
Sheet *sheet = sheet_from_servant (servant);
GNOME_Gnumeric_Value *value;
verify_col_val (col, NULL);
verify_row_val (row, NULL);
value = GNOME_Gnumeric_Value__alloc ();
fill_corba_value (value, sheet, col, row);
return value;
}
......@@ -804,6 +844,146 @@ Sheet_shift_cols (PortableServer_Servant servant,
sheet_shift_cols (sheet, col, start_row, end_row, count);
}
static GNOME_Gnumeric_Sheet_ValueVector *
Sheet_range_get_values (PortableServer_Servant servant, const CORBA_char *range, CORBA_Environment *ev)
{
GNOME_Gnumeric_Sheet_ValueVector *vector;
Sheet *sheet = sheet_from_servant (servant);
GSList *ranges, *l;
int size, i;
verify_range_val (sheet, range, &ranges, NULL);
/*
* Find out how big is the array we need to return
*/
size = 0;
for (l = ranges; l; l = l->next){
Value *value = l->data;
CellRef a, b;
int cols, rows;
g_assert (value->type == VALUE_CELLRANGE);
a = value->v.cell_range.cell_a;
b = value->v.cell_range.cell_b;
cols = abs (b.col - a.col) + 1;
rows = abs (b.row - a.row) + 1;
size += cols * rows;
}
vector = GNOME_Gnumeric_Sheet_ValueVector__alloc ();
vector->_buffer = CORBA_sequence_GNOME_Gnumeric_Value_allocbuf (size);
/* No memory, return an empty vector */
if (vector->_buffer == NULL){
vector->_length = 0;
vector->_maximum = 0;
return vector;
}
/*
* Fill in the vector
*/
for (i = 0, l = ranges; l; l = l->next, i++){
Value *value = l->data;
CellRef a, b;
int col, row;
a = value->v.cell_range.cell_a;
b = value->v.cell_range.cell_b;
for (col = a.col; col <= b.col; col++)
for (row = a.row; row < b.row; row++)
fill_corba_value (&vector->_buffer [i], sheet, col, row);
}
range_list_destroy (ranges);
return vector;
}
static void
cb_range_set_text (Cell *cell, void *data)
{
cell_set_text (cell, data);
}
static void
Sheet_range_set_text (PortableServer_Servant servant,
const CORBA_char *range,
const CORBA_char *text,
CORBA_Environment * ev)
{
Sheet *sheet = sheet_from_servant (servant);
GSList *ranges, *l;
verify_range (sheet, range, &ranges);
range_list_foreach_all (ranges, cb_range_set_text, text);
range_list_destroy (ranges);
}
static void
cb_range_set_formula (Cell *cell, void *data)
{
cell_set_formula (cell, data);
}
static void
Sheet_range_set_formula (PortableServer_Servant servant,
const CORBA_char *range,
const CORBA_char *formula,
CORBA_Environment * ev)
{
Sheet *sheet = sheet_from_servant (servant);
GSList *ranges, *l;
verify_range (sheet, range, &ranges);
range_list_foreach_all (ranges, cb_range_set_formula, formula);
range_list_destroy (ranges);
}
static void
cb_range_set_format (Cell *cell, void *data)
{
cell_set_format (cell, data);
}
static void
Sheet_range_set_format (PortableServer_Servant servant,
const CORBA_char *range,
const CORBA_char *format,
CORBA_Environment * ev)
{
Sheet *sheet = sheet_from_servant (servant);
GSList *ranges, *l;
Style *style;
verify_range (sheet, range, &ranges);
cell_freeze_redraws ();
/*
* Create a style for the region
*/
style = style_new_empty ();
style->valid_flags = STYLE_FORMAT;
style->format = style_format_new (format);
/* Apply the style */
range_set_style (ranges, style);
range_list_foreach (ranges, cb_range_set_format, format);
cell_thaw_redraws ();
range_list_destroy (ranges);
}
static void
Sheet_corba_class_init (void)
......@@ -832,6 +1012,10 @@ Sheet_corba_class_init (void)
gnome_gnumeric_sheet_epv.clear_region_content = Sheet_clear_region_content;
gnome_gnumeric_sheet_epv.clear_region_comments = Sheet_clear_region_comments;
gnome_gnumeric_sheet_epv.clear_region_formats = Sheet_clear_region_formats;
/*
* Cell based routines
*/
gnome_gnumeric_sheet_epv.cell_set_value = Sheet_cell_set_value;
gnome_gnumeric_sheet_epv.cell_get_value = Sheet_cell_get_value;
gnome_gnumeric_sheet_epv.cell_set_text = Sheet_cell_set_text;
......@@ -850,7 +1034,14 @@ Sheet_corba_class_init (void)
gnome_gnumeric_sheet_epv.cell_set_alignment = Sheet_cell_set_alignment;
gnome_gnumeric_sheet_epv.cell_get_alignment = Sheet_cell_get_alignment;
/*
* Region based routines
*/
gnome_gnumeric_sheet_epv.range_get_values = Sheet_range_get_values;
gnome_gnumeric_sheet_epv.range_set_text = Sheet_range_set_text;
gnome_gnumeric_sheet_epv.range_set_formula = Sheet_range_set_formula;
gnome_gnumeric_sheet_epv.range_set_format = Sheet_range_set_format;
gnome_gnumeric_sheet_epv.set_dirty = Sheet_set_dirty;
}
......
......@@ -87,8 +87,10 @@ arg_data_list_new (State *state)
type = state->fd->args;
if (!type){
int lp;
for (lp=0;lp<INPUTS_FOR_MULTI_ARG;lp++){
for (lp = 0; lp < INPUTS_FOR_MULTI_ARG; lp++){
ARG_DATA *ad;
ad = g_new (ARG_DATA, 1);
ad->arg_name = g_strdup ("Value");
ad->wb = state->wb;
......@@ -109,15 +111,16 @@ arg_data_list_new (State *state)
ptr = copy_args;
while (*ptr){
if (*ptr=='(' && !start)
if (*ptr == '(' && !start)
start = ptr+1;
if (*ptr=='[' || *ptr==']'){
if (*ptr == '[' || *ptr == ']'){
*ptr = '\0';
if (start == ptr) start++;
if (start == ptr)
start++;
ptr++;
continue;
}
if (*ptr==',' || *ptr==')'){
if (*ptr == ',' || *ptr == ')'){
if (*type=='|'){
type++;
optional = 1;
......@@ -148,11 +151,15 @@ arg_data_list_destroy (State *state)
int lp;
GPtrArray *pa;
if (!state) return;
if (!state)
return;
pa = state->args;
if (!pa) return;
for (lp=0;lp<pa->len;lp++){
if (!pa)
return;
for (lp = 0; lp < pa->len; lp++){
ARG_DATA *ad;
ad = g_ptr_array_index (pa, 0);
g_free (ad->arg_name);
g_free (ad);
......@@ -168,9 +175,12 @@ function_input (GtkWidget *widget, ARG_DATA *ad)
gchar *txt;
int pos;
if (!fd) return;
if (!fd)
return;
txt = dialog_function_wizard (ad->wb, fd);
if (!txt || !ad->wb || !ad->wb->ea_input) return;
if (!txt || !ad->wb || !ad->wb->ea_input)
return;
pos = gtk_editable_get_position (GTK_EDITABLE(entry));
......@@ -256,10 +266,11 @@ function_wizard_create (State *state)
g_return_if_fail (state->args);
vbox = gtk_vbox_new (0, 2);
for (lp=0;lp<state->args->len;lp++){
GtkWidget *widg;
widg = function_type_input (g_ptr_array_index (state->args, lp));
gtk_box_pack_start (state->dialog_box, widg,
for (lp = 0; lp < state->args->len; lp++){
GtkWidget *widget;
widget = function_type_input (g_ptr_array_index (state->args, lp));
gtk_box_pack_start (state->dialog_box, widget,
FALSE, FALSE, 0);
}
......@@ -284,10 +295,12 @@ get_text_value (State *state)
g_return_val_if_fail (state->args, NULL);
txt = g_strconcat (state->fd->name, "(", NULL);
for (lp=0;lp<state->args->len;lp++){
for (lp = 0; lp < state->args->len; lp++){
int comma;
ARG_DATA *ad = g_ptr_array_index (state->args, lp);
gchar *val = gtk_entry_get_text (ad->entry);
if (!ad->optional || strlen(val)){
txt2 = txt;
txt = g_strconcat (txt2, lp?",":"", val, NULL);
......
......@@ -274,7 +274,7 @@ add_dialog:
type_str);
strcat(constraint_buf, cell_name(rhs_col, rhs_row));
gtk_clist_append (constraint_dialog->clist, constraint_str);
constraint = (SolverConstraint *) malloc (sizeof(SolverConstraint));
constraint = g_new (SolverConstraint, 1);
constraint->lhs = sheet_cell_get (constraint_dialog->sheet,
lhs_col, lhs_row);
if (constraint->lhs == NULL) {
......@@ -289,9 +289,9 @@ add_dialog:
rhs_col, rhs_row);
cell_set_text (constraint->rhs, "");
}
constraint->type = (char *) malloc (strlen(type_str) + 1);
constraint->type = g_malloc (strlen (type_str) + 1);
strcpy (constraint->type, type_str);
constraint->str = (char *) malloc (strlen(constraint_buf)+1);
constraint->str = g_malloc (strlen (constraint_buf)+1);
strcpy (constraint->str, constraint_buf);
constraint_dialog->constraints =
g_slist_append(constraint_dialog->constraints,
......
......@@ -87,8 +87,10 @@ arg_data_list_new (State *state)
type = state->fd->args;
if (!type){
int lp;
for (lp=0;lp<INPUTS_FOR_MULTI_ARG;lp++){
for (lp = 0; lp < INPUTS_FOR_MULTI_ARG; lp++){
ARG_DATA *ad;
ad = g_new (ARG_DATA, 1);
ad->arg_name = g_strdup ("Value");
ad->wb = state->wb;
......@@ -109,15 +111,16 @@ arg_data_list_new (State *state)
ptr = copy_args;
while (*ptr){
if (*ptr=='(' && !start)
if (*ptr == '(' && !start)
start = ptr+1;
if (*ptr=='[' || *ptr==']'){
if (*ptr == '[' || *ptr == ']'){
*ptr = '\0';
if (start == ptr) start++;
if (start == ptr)
start++;