diff --git a/ChangeLog-2000-02-23 b/ChangeLog-2000-02-23 index 73366d17b0ca086926747a226f2ee2ab8ed17872..533f0cb61a25a27d409137849cf3e9d9820086c3 100644 --- a/ChangeLog-2000-02-23 +++ b/ChangeLog-2000-02-23 @@ -1,3 +1,23 @@ +1999-09-30 Miguel de Icaza + + * src/Gnumeric-value.idl: New file, move the value structure + definition here. + + * src/Gnumeric.idl: Add new interface for data access. + + * src/value-sheet.c: New file. Moved here the value code that + uses a Sheet directly. + (value_dump): moved here. + (value_cellrange_get_as_string): ditto. + (encode_cellref): ditto. + (value_area_get_width): ditto. + (value_area_get_height): ditto. + (value_area_get_x_y): ditto. + (constants_init): ditto. + (value_area_foreach): ditto + (wrapper_foreach_cell_in_area_callback): ditto. + (value_area_fetch_x_y): ditto. + 1999-10-04 Jody Goldberg * src/workbook.c (sheet_action_delete_sheet) : Use a diff --git a/OChangeLog-2000-02-23 b/OChangeLog-2000-02-23 index 73366d17b0ca086926747a226f2ee2ab8ed17872..533f0cb61a25a27d409137849cf3e9d9820086c3 100644 --- a/OChangeLog-2000-02-23 +++ b/OChangeLog-2000-02-23 @@ -1,3 +1,23 @@ +1999-09-30 Miguel de Icaza + + * src/Gnumeric-value.idl: New file, move the value structure + definition here. + + * src/Gnumeric.idl: Add new interface for data access. + + * src/value-sheet.c: New file. Moved here the value code that + uses a Sheet directly. + (value_dump): moved here. + (value_cellrange_get_as_string): ditto. + (encode_cellref): ditto. + (value_area_get_width): ditto. + (value_area_get_height): ditto. + (value_area_get_x_y): ditto. + (constants_init): ditto. + (value_area_foreach): ditto + (wrapper_foreach_cell_in_area_callback): ditto. + (value_area_fetch_x_y): ditto. + 1999-10-04 Jody Goldberg * src/workbook.c (sheet_action_delete_sheet) : Use a diff --git a/src/Gnumeric.idl b/src/Gnumeric.idl index f6aa76ab522923fe57fb4a300f674fb734332862..8a6104d959119bf1899032d0c63b8b43a11229b8 100644 --- a/src/Gnumeric.idl +++ b/src/Gnumeric.idl @@ -1,32 +1,9 @@ #include +#include "Gnumeric-value.idl" module GNOME { module Gnumeric { - struct CellRange { - string cell_a; - string cell_b; - }; - - const short VALUE_STRING = 0; - const short VALUE_INTEGER = 1; - const short VALUE_FLOAT = 2; - const short VALUE_CELLRANGE = 3; - const short VALUE_ARRAY = 4; - const short VALUE_BOOLEAN = 5; - const short VALUE_ERROR = 6; - const short VALUE_EMPTY = 7; - - union Value switch(short) { - case VALUE_BOOLEAN: boolean v_bool; - case VALUE_FLOAT: double v_float; - case VALUE_INTEGER: long v_int; - case VALUE_STRING: string str; - case VALUE_ERROR: string error; - case VALUE_ARRAY: string array; - case VALUE_CELLRANGE: CellRange cell_range; - }; - interface Sheet { exception OutOfRange {}; exception ParseError {}; @@ -243,6 +220,9 @@ module GNOME { void show (in boolean show_toplevel); }; + // + // Interfaces for embedding Gnumeric with Bonobo + // interface WorkbookFactory : GNOME::GenericFactory { Workbook read (in string filename); }; @@ -253,5 +233,49 @@ module GNOME { void set_header_visibility (in boolean cols, in boolean rows); void get_header_visibility (out boolean cols, out boolean rows); }; + + // + // Interfaces for accessing value sets from linear arrays. + // Mainly used for graphics. + // + interface DataNotify { + void changed (in short pos); + }; + + interface Data { + exception OutOfRange {}; + + /** + * get: + * @pos: index to fetch + * + * Returns the Value at index position pos + */ + Value get (in short pos) raises (OutOfRange); + + /** + * set: + * @pos: index to modify + * value: value to place + * + * Sets the value at index position @pos to @val + */ + void set (in short pos, in Value val); + + void set_notify (in DataNotify); + + /** + * count: + * + * Returns the number of objects in this collection + */ + short count (void); + }; + }; }; + + + + + diff --git a/src/Makefile.am b/src/Makefile.am index bcb9c95b5040f5c53f97f422aeef85adf0bf4279..57a114a0902aece2c58525130cc974c0d44a61ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -145,6 +145,8 @@ GNUMERIC_BASE_SOURCES = \ utils.h \ value.c \ value.h \ + value-sheet.c \ + value-sheet.h \ workbook.c \ workbook.h \ workbook-cmd-format.c \ @@ -177,12 +179,12 @@ BUILT_SOURCES = $(GNUMERIC_CORBA_GENERATED) Gnumeric-impl.o: Gnumeric.h -CLEANFILES=my_gnumeric_idl +CLEANFILES = my_gnumeric_idl $(GNUMERIC_CORBA_GENERATED): my_gnumeric_idl -my_gnumeric_idl: Gnumeric.idl - orbit-idl -I`$(GNOME_CONFIG) --datadir`/idl $(srcdir)/Gnumeric.idl +my_gnumeric_idl: Gnumeric.idl Gnumeric-value.idl + orbit-idl -I`$(GNOME_CONFIG) --datadir`/idl -I$(srcdir) $(srcdir)/Gnumeric.idl touch my_gnumeric_idl gnumeric_SOURCES = \ @@ -246,7 +248,7 @@ dist-hook: # $(INTLLIBS) idldir = $(datadir)/idl -idl_DATA = Gnumeric.idl +idl_DATA = Gnumeric.idl Gnumeric-value.idl MYHACKAROUNDAUTOMAKE=$(shell echo $(GNUMERIC_CORBA_GENERATED)) diff --git a/src/value-sheet.c b/src/value-sheet.c new file mode 100644 index 0000000000000000000000000000000000000000..aad5e6f48f5b8242c1c03380bb00cfbc94af29f0 --- /dev/null +++ b/src/value-sheet.c @@ -0,0 +1,359 @@ +/* + * value-sheet.c: Utilies for sheet specific value handling + * + * Author: + * Miguel de Icaza (miguel@gnu.org). + */ +#include +#include +#include "value.h" +#include "utils.h" + +/* Debugging utility to print a Value */ +void +value_dump (const Value *value) +{ + switch (value->type){ + case VALUE_EMPTY: + printf ("EMPTY\n"); + break; + + case VALUE_ERROR: + printf ("ERROR: %s\n", value->v.error.mesg->str); + break; + + case VALUE_BOOLEAN: + printf ("BOOLEAN: %s\n", value->v.v_bool ?_("TRUE"):_("FALSE")); + break; + + case VALUE_STRING: + printf ("STRING: %s\n", value->v.str->str); + break; + + case VALUE_INTEGER: + printf ("NUM: %d\n", value->v.v_int); + break; + + case VALUE_FLOAT: + printf ("Float: %f\n", value->v.v_float); + break; + + case VALUE_ARRAY: { + int x, y; + + printf ("Array: { "); + for (y = 0; y < value->v.array.y; y++) + for (x = 0; x < value->v.array.x; x++) + value_dump (value->v.array.vals [x][y]); + printf ("}\n"); + break; + } + case VALUE_CELLRANGE: { + CellRef const *c = &value->v.cell_range.cell_a; + Sheet const *sheet = c->sheet; + + printf ("CellRange\n"); + if (sheet && sheet->name) + printf ("'%s':", sheet->name); + else + printf ("%p :", sheet); + printf ("%s%s%s%d\n", + (c->col_relative ? "":"$"), col_name(c->col), + (c->row_relative ? "":"$"), c->row+1); + c = &value->v.cell_range.cell_b; + if (sheet && sheet->name) + printf ("'%s':", sheet->name); + else + printf ("%p :", sheet); + printf ("%s%s%s%d\n", + (c->col_relative ? "":"$"), col_name(c->col), + (c->row_relative ? "":"$"), c->row+1); + break; + } + default: + printf ("Unhandled item type\n"); + } +} + +static void +encode_cellref (GString *dest, const CellRef *ref, gboolean use_relative_syntax) +{ + if (ref->sheet){ + g_string_append_c (dest, '\''); + g_string_append (dest, ref->sheet->name); + g_string_append (dest, "'!"); + } + if (use_relative_syntax && !ref->col_relative) + g_string_append_c (dest, '$'); + g_string_append (dest, col_name (ref->col)); + + if (use_relative_syntax && !ref->row_relative) + g_string_append_c (dest, '$'); + g_string_sprintfa (dest, "%d", ref->row+1); +} + + +/* + * value_cellrange_get_as_string: + * @value: a value containing a VALUE_CELLRANGE + * @use_relative_syntax: true if you want the result to contain relative indicators + * + * Returns: a string reprensenting the Value, for example: + * use_relative_syntax == TRUE: $a4:$b$1 + * use_relative_syntax == FALSE: a4:b1 + */ +char * +value_cellrange_get_as_string (const Value *value, gboolean use_relative_syntax) +{ + GString *str; + char *ans; + CellRef const * a, * b; + + g_return_val_if_fail (value != NULL, NULL); + g_return_val_if_fail (value->type == VALUE_CELLRANGE, NULL); + + a = &value->v.cell_range.cell_a; + b = &value->v.cell_range.cell_b; + + str = g_string_new (""); + encode_cellref (str, a, use_relative_syntax); + + if ((a->col != b->col) || (a->row != b->row) || + (a->col_relative != b->col_relative) || (a->sheet != b->sheet)){ + g_string_append_c (str, ':'); + + encode_cellref (str, b, use_relative_syntax); + } + ans = str->str; + g_string_free (str, FALSE); + return ans; +} + +guint +value_area_get_width (const EvalPosition *ep, Value const *v) +{ + g_return_val_if_fail (v, 0); + g_return_val_if_fail (v->type == VALUE_ARRAY || + v->type == VALUE_CELLRANGE, 1); + + if (v->type == VALUE_ARRAY) + return v->v.array.x; + else { /* FIXME: 3D references, may not clip correctly */ + Sheet *sheeta = v->v.cell_range.cell_a.sheet ? + v->v.cell_range.cell_a.sheet:ep->sheet; + guint ans = v->v.cell_range.cell_b.col - + v->v.cell_range.cell_a.col + 1; + if (sheeta && sheeta->cols.max_used < ans) /* Clip */ + ans = sheeta->cols.max_used+1; + return ans; + } +} + +guint +value_area_get_height (const EvalPosition *ep, Value const *v) +{ + g_return_val_if_fail (v, 0); + g_return_val_if_fail (v->type == VALUE_ARRAY || + v->type == VALUE_CELLRANGE, 1); + + if (v->type == VALUE_ARRAY) + return v->v.array.y; + else { /* FIXME: 3D references, may not clip correctly */ + Sheet *sheeta = eval_sheet (v->v.cell_range.cell_a.sheet, ep->sheet); + guint ans = v->v.cell_range.cell_b.row - + v->v.cell_range.cell_a.row + 1; + if (sheeta && sheeta->rows.max_used < ans) /* Clip */ + ans = sheeta->rows.max_used + 1; + return ans; + } +} + +/* + * An internal routine to get a cell from an array or range. If any + * problems occur a NULL is returned. + */ +const Value * +value_area_get_x_y (EvalPosition const *ep, Value const *v, guint x, guint y) +{ + g_return_val_if_fail (v, NULL); + g_return_val_if_fail (v->type == VALUE_ARRAY || + v->type == VALUE_CELLRANGE, + NULL); + + if (v->type == VALUE_ARRAY){ + g_return_val_if_fail (x < v->v.array.x && + y < v->v.array.y, + NULL); + return v->v.array.vals [x][y]; + } else { + CellRef const * const a = &v->v.cell_range.cell_a; + CellRef const * const b = &v->v.cell_range.cell_b; + int a_col = a->col; + int a_row = a->row; + int b_col = b->col; + int b_row = b->row; + Cell *cell; + Sheet *sheet; + + /* Handle relative references */ + if (a->col_relative) + a_col += ep->eval_col; + if (a->row_relative) + a_row += ep->eval_row; + if (b->col_relative) + b_col += ep->eval_col; + if (b->row_relative) + b_row += ep->eval_row; + + /* Handle inverted refereneces */ + if (a_row > b_row) { + int tmp = a_row; + a_row = b_row; + b_row = tmp; + } + if (a_col > b_col) { + int tmp = a_col; + a_col = b_col; + b_col = tmp; + } + + a_col += x; + a_row += y; + + /* + * FIXME FIXME FIXME + * This should return NA but some of the math functions may + * rely on this for now. + */ + g_return_val_if_fail (a_row<=b_row, NULL); + g_return_val_if_fail (a_col<=b_col, NULL); + + sheet = a->sheet ? a->sheet : ep->sheet; + g_return_val_if_fail (sheet != NULL, NULL); + + /* Speedup */ + if (sheet->cols.max_used < a_col || + sheet->rows.max_used < a_row) + return NULL; + + cell = sheet_cell_get (sheet, a_col, a_row); + + if (cell && cell->value) + return cell->value; + } + + return NULL; +} + +Value const * +value_area_fetch_x_y (EvalPosition const *ep, Value const *v, guint x, guint y) +{ + Value const * const res = value_area_get_x_y (ep, v, x, y); + static Value *value_zero = NULL; + if (res) + return res; + + if (value_zero == NULL) + value_zero = value_new_int (0); + return value_zero; +} + +typedef struct +{ + value_area_foreach_callback callback; + EvalPosition const *ep; + void *real_data; +} WrapperClosure; + +static Value * +wrapper_foreach_cell_in_area_callback (Sheet *sheet, int col, int row, + Cell *cell, void *user_data) +{ + WrapperClosure * wrap; + if (cell == NULL || cell->value == NULL) + return NULL; + + wrap = (WrapperClosure *)user_data; + return (*wrap->callback)(wrap->ep, cell->value, wrap->real_data); +} + +/** + * value_area_foreach: + * + * For each existing element in an array or range , invoke the + * callback routine. If the only_existing flag is passed, then + * callbacks are only invoked for existing cells. + * + * Return value: + * non-NULL on error, or value_terminate() if some invoked routine requested + * to stop (by returning non-NULL). + */ +Value * +value_area_foreach (EvalPosition const *ep, Value const *v, + value_area_foreach_callback callback, + void *closure) +{ + int x, y; + Value *tmp; + + g_return_val_if_fail (callback != NULL, FALSE); + + if (v->type == VALUE_CELLRANGE) + { + WrapperClosure wrap; + wrap.callback = callback; + wrap.ep = ep; + wrap.real_data = closure; + return sheet_cell_foreach_range ( + eval_sheet (v->v.cell_range.cell_a.sheet, ep->sheet), + TRUE, + v->v.cell_range.cell_a.col, + v->v.cell_range.cell_a.row, + v->v.cell_range.cell_b.col, + v->v.cell_range.cell_b.row, + &wrapper_foreach_cell_in_area_callback, + (void *)&wrap); + } + + /* If not an array, apply callback to singleton */ + if (v->type != VALUE_ARRAY) + return (*callback)(ep, v, closure); + + for (x = v->v.array.x; --x >= 0;) + for (y = v->v.array.y; --y >= 0;) + if ((tmp = (*callback)(ep, v->v.array.vals [x][y], closure)) != NULL) + return tmp; + + return NULL; +} + +/* + * Initialize temporarily with statics. The real versions from the locale + * will be setup in constants_init + */ +char const *gnumeric_err_NULL = "#NULL!"; +char const *gnumeric_err_DIV0 = "#DIV/0!"; +char const *gnumeric_err_VALUE = "#VALUE!"; +char const *gnumeric_err_REF = "#REF!"; +char const *gnumeric_err_NAME = "#NAME?"; +char const *gnumeric_err_NUM = "#NUM!"; +char const *gnumeric_err_NA = "#N/A"; + +void +constants_init (void) +{ + symbol_install (global_symbol_table, "FALSE", SYMBOL_VALUE, + value_new_bool (FALSE)); + symbol_install (global_symbol_table, "TRUE", SYMBOL_VALUE, + value_new_bool (TRUE)); + symbol_install (global_symbol_table, "GNUMERIC_VERSION", SYMBOL_VALUE, + value_new_float (atof (GNUMERIC_VERSION))); + + gnumeric_err_NULL = _("#NULL!"); + gnumeric_err_DIV0 = _("#DIV/0!"); + gnumeric_err_VALUE = _("#VALUE!"); + gnumeric_err_REF = _("#REF!"); + gnumeric_err_NAME = _("#NAME?"); + gnumeric_err_NUM = _("#NUM!"); + gnumeric_err_NA = _("#N/A"); +} diff --git a/src/value.c b/src/value.c index e5a265685763b69832de85c38b8dc1cf794571af..ec713b3810e0b890275b32e1ce6090b5de819577 100644 --- a/src/value.c +++ b/src/value.c @@ -187,72 +187,6 @@ value_release (Value *value) g_free (value); } -/* Debugging utility to print a Value */ -void -value_dump (const Value *value) -{ - switch (value->type){ - case VALUE_EMPTY: - printf ("EMPTY\n"); - break; - - case VALUE_ERROR: - printf ("ERROR: %s\n", value->v.error.mesg->str); - break; - - case VALUE_BOOLEAN: - printf ("BOOLEAN: %s\n", value->v.v_bool ?_("TRUE"):_("FALSE")); - break; - - case VALUE_STRING: - printf ("STRING: %s\n", value->v.str->str); - break; - - case VALUE_INTEGER: - printf ("NUM: %d\n", value->v.v_int); - break; - - case VALUE_FLOAT: - printf ("Float: %f\n", value->v.v_float); - break; - - case VALUE_ARRAY: { - int x, y; - - printf ("Array: { "); - for (y = 0; y < value->v.array.y; y++) - for (x = 0; x < value->v.array.x; x++) - value_dump (value->v.array.vals [x][y]); - printf ("}\n"); - break; - } - case VALUE_CELLRANGE: { - CellRef const *c = &value->v.cell_range.cell_a; - Sheet const *sheet = c->sheet; - - printf ("CellRange\n"); - if (sheet && sheet->name) - printf ("'%s':", sheet->name); - else - printf ("%p :", sheet); - printf ("%s%s%s%d\n", - (c->col_relative ? "":"$"), col_name(c->col), - (c->row_relative ? "":"$"), c->row+1); - c = &value->v.cell_range.cell_b; - if (sheet && sheet->name) - printf ("'%s':", sheet->name); - else - printf ("%p :", sheet); - printf ("%s%s%s%d\n", - (c->col_relative ? "":"$"), col_name(c->col), - (c->row_relative ? "":"$"), c->row+1); - break; - } - default: - printf ("Unhandled item type\n"); - } -} - /* * Makes a copy of a Value */ @@ -520,60 +454,6 @@ value_get_as_float (const Value *v) return 0.0; } -static void -encode_cellref (GString *dest, const CellRef *ref, gboolean use_relative_syntax) -{ - if (ref->sheet){ - g_string_append_c (dest, '\''); - g_string_append (dest, ref->sheet->name); - g_string_append (dest, "'!"); - } - if (use_relative_syntax && !ref->col_relative) - g_string_append_c (dest, '$'); - g_string_append (dest, col_name (ref->col)); - - if (use_relative_syntax && !ref->row_relative) - g_string_append_c (dest, '$'); - g_string_sprintfa (dest, "%d", ref->row+1); -} - - -/* - * value_cellrange_get_as_string: - * @value: a value containing a VALUE_CELLRANGE - * @use_relative_syntax: true if you want the result to contain relative indicators - * - * Returns: a string reprensenting the Value, for example: - * use_relative_syntax == TRUE: $a4:$b$1 - * use_relative_syntax == FALSE: a4:b1 - */ -char * -value_cellrange_get_as_string (const Value *value, gboolean use_relative_syntax) -{ - GString *str; - char *ans; - CellRef const * a, * b; - - g_return_val_if_fail (value != NULL, NULL); - g_return_val_if_fail (value->type == VALUE_CELLRANGE, NULL); - - a = &value->v.cell_range.cell_a; - b = &value->v.cell_range.cell_b; - - str = g_string_new (""); - encode_cellref (str, a, use_relative_syntax); - - if ((a->col != b->col) || (a->row != b->row) || - (a->col_relative != b->col_relative) || (a->sheet != b->sheet)){ - g_string_append_c (str, ':'); - - encode_cellref (str, b, use_relative_syntax); - } - ans = str->str; - g_string_free (str, FALSE); - return ans; -} - /* * Test @v to see if it fits the heurists used to identify the results of * accessing an empty cell. Which are currently @@ -800,102 +680,3 @@ value_array_copy_to (Value *v, const Value *src) } } -typedef struct -{ - value_area_foreach_callback callback; - EvalPosition const *ep; - void *real_data; -} WrapperClosure; - -static Value * -wrapper_foreach_cell_in_area_callback (Sheet *sheet, int col, int row, - Cell *cell, void *user_data) -{ - WrapperClosure * wrap; - if (cell == NULL || cell->value == NULL) - return NULL; - - wrap = (WrapperClosure *)user_data; - return (*wrap->callback)(wrap->ep, cell->value, wrap->real_data); -} - -/** - * value_area_foreach: - * - * For each existing element in an array or range , invoke the - * callback routine. If the only_existing flag is passed, then - * callbacks are only invoked for existing cells. - * - * Return value: - * non-NULL on error, or value_terminate() if some invoked routine requested - * to stop (by returning non-NULL). - */ -Value * -value_area_foreach (EvalPosition const *ep, Value const *v, - value_area_foreach_callback callback, - void *closure) -{ - int x, y; - Value *tmp; - - g_return_val_if_fail (callback != NULL, FALSE); - - if (v->type == VALUE_CELLRANGE) - { - WrapperClosure wrap; - wrap.callback = callback; - wrap.ep = ep; - wrap.real_data = closure; - return sheet_cell_foreach_range ( - eval_sheet (v->v.cell_range.cell_a.sheet, ep->sheet), - TRUE, - v->v.cell_range.cell_a.col, - v->v.cell_range.cell_a.row, - v->v.cell_range.cell_b.col, - v->v.cell_range.cell_b.row, - &wrapper_foreach_cell_in_area_callback, - (void *)&wrap); - } - - /* If not an array, apply callback to singleton */ - if (v->type != VALUE_ARRAY) - return (*callback)(ep, v, closure); - - for (x = v->v.array.x; --x >= 0;) - for (y = v->v.array.y; --y >= 0;) - if ((tmp = (*callback)(ep, v->v.array.vals [x][y], closure)) != NULL) - return tmp; - - return NULL; -} - -/* - * Initialize temporarily with statics. The real versions from the locale - * will be setup in constants_init - */ -char const *gnumeric_err_NULL = "#NULL!"; -char const *gnumeric_err_DIV0 = "#DIV/0!"; -char const *gnumeric_err_VALUE = "#VALUE!"; -char const *gnumeric_err_REF = "#REF!"; -char const *gnumeric_err_NAME = "#NAME?"; -char const *gnumeric_err_NUM = "#NUM!"; -char const *gnumeric_err_NA = "#N/A"; - -void -constants_init (void) -{ - symbol_install (global_symbol_table, "FALSE", SYMBOL_VALUE, - value_new_bool (FALSE)); - symbol_install (global_symbol_table, "TRUE", SYMBOL_VALUE, - value_new_bool (TRUE)); - symbol_install (global_symbol_table, "GNUMERIC_VERSION", SYMBOL_VALUE, - value_new_float (atof (GNUMERIC_VERSION))); - - gnumeric_err_NULL = _("#NULL!"); - gnumeric_err_DIV0 = _("#DIV/0!"); - gnumeric_err_VALUE = _("#VALUE!"); - gnumeric_err_REF = _("#REF!"); - gnumeric_err_NAME = _("#NAME?"); - gnumeric_err_NUM = _("#NUM!"); - gnumeric_err_NA = _("#N/A"); -}