Commit c3a522d6 authored by Arturo Espinosa's avatar Arturo Espinosa

Various little fixes here and there:



Various little fixes here and there:

	- Basic support for dragging the selection is in (still does
	  not do anything, will do the action binding later).

	- Fixes to the cell-selection-code-when-you-type-a-formula code

	- ExprTrees are now properly refcounted (instead of only
	  refcounting the root node).  This is required for the
	  Paste special/with-arithmetic operation feature.

	- Expression decoding (for pasting a formula with relative
	  references) now takes into account operator precedence to
	  avoid cluttering the pasted expression with extra paretheses.

	Other smallish fixes which I forget now.

Miguel.
parent f579db27
1998-08-15 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/item-cursor.c (item_cursor_drag_event): Make the drag cursor
actually dragable.
* src/item-grid.c (item_grid_event): Use the converted cordinates.
(item_grid_find_row, item_grid_find_col): Rename and export these
routines to be used by the ItemCursor.
* src/gnumeric-sheet.c (gnumeric_sheet_key): Do not remove the
selection string when the input has been accepted.
* src/expr.c (expr_tree_ref): Strategy change: Now every ExprTree
node is properly refcounted, as soon we will start sharing parts
of the ExprTree between cells.
(do_expr_decode_tree): Decoding an expression now takes into
account the precedence of the operators and uses paretheses only
when they are actually required.
1998-08-14 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/item-grid.c (item_grid_event): Implemented context sensitive
menu for the grid.
(item_grid_event): Use <control> instead of <shift> for extending
a selection
* src/clipboard.c (clipboard_paste_region): After pasting, trigger
a recalculation.
......
1998-08-15 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/item-cursor.c (item_cursor_drag_event): Make the drag cursor
actually dragable.
* src/item-grid.c (item_grid_event): Use the converted cordinates.
(item_grid_find_row, item_grid_find_col): Rename and export these
routines to be used by the ItemCursor.
* src/gnumeric-sheet.c (gnumeric_sheet_key): Do not remove the
selection string when the input has been accepted.
* src/expr.c (expr_tree_ref): Strategy change: Now every ExprTree
node is properly refcounted, as soon we will start sharing parts
of the ExprTree between cells.
(do_expr_decode_tree): Decoding an expression now takes into
account the precedence of the operators and uses paretheses only
when they are actually required.
1998-08-14 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/item-grid.c (item_grid_event): Implemented context sensitive
menu for the grid.
(item_grid_event): Use <control> instead of <shift> for extending
a selection
* src/clipboard.c (clipboard_paste_region): After pasting, trigger
a recalculation.
......
1998-08-15 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/item-cursor.c (item_cursor_drag_event): Make the drag cursor
actually dragable.
* src/item-grid.c (item_grid_event): Use the converted cordinates.
(item_grid_find_row, item_grid_find_col): Rename and export these
routines to be used by the ItemCursor.
* src/gnumeric-sheet.c (gnumeric_sheet_key): Do not remove the
selection string when the input has been accepted.
* src/expr.c (expr_tree_ref): Strategy change: Now every ExprTree
node is properly refcounted, as soon we will start sharing parts
of the ExprTree between cells.
(do_expr_decode_tree): Decoding an expression now takes into
account the precedence of the operators and uses paretheses only
when they are actually required.
1998-08-14 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/item-grid.c (item_grid_event): Implemented context sensitive
menu for the grid.
(item_grid_event): Use <control> instead of <shift> for extending
a selection
* src/clipboard.c (clipboard_paste_region): After pasting, trigger
a recalculation.
......
1998-08-15 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/item-cursor.c (item_cursor_drag_event): Make the drag cursor
actually dragable.
* src/item-grid.c (item_grid_event): Use the converted cordinates.
(item_grid_find_row, item_grid_find_col): Rename and export these
routines to be used by the ItemCursor.
* src/gnumeric-sheet.c (gnumeric_sheet_key): Do not remove the
selection string when the input has been accepted.
* src/expr.c (expr_tree_ref): Strategy change: Now every ExprTree
node is properly refcounted, as soon we will start sharing parts
of the ExprTree between cells.
(do_expr_decode_tree): Decoding an expression now takes into
account the precedence of the operators and uses paretheses only
when they are actually required.
1998-08-14 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/item-grid.c (item_grid_event): Implemented context sensitive
menu for the grid.
(item_grid_event): Use <control> instead of <shift> for extending
a selection
* src/clipboard.c (clipboard_paste_region): After pasting, trigger
a recalculation.
......
......@@ -397,6 +397,10 @@ workbook_next_generation (Workbook *wb)
wb->generation++;
}
/*
* Computes all of the cells pending computation and
* any dependency.
*/
void
workbook_recalc (Workbook *wb)
{
......@@ -422,3 +426,21 @@ workbook_recalc (Workbook *wb)
g_list_free (deps);
}
}
/*
* Recomputes all of the formulas.
*/
void
workbook_recalc_all (Workbook *workbook)
{
GList *l;
for (l = workbook->formula_cell_list; l; l = l->next){
Cell *cell = l->data;
cell_queue_recalc (cell);
}
workbook_recalc (workbook);
}
......@@ -397,6 +397,10 @@ workbook_next_generation (Workbook *wb)
wb->generation++;
}
/*
* Computes all of the cells pending computation and
* any dependency.
*/
void
workbook_recalc (Workbook *wb)
{
......@@ -422,3 +426,21 @@ workbook_recalc (Workbook *wb)
g_list_free (deps);
}
}
/*
* Recomputes all of the formulas.
*/
void
workbook_recalc_all (Workbook *workbook)
{
GList *l;
for (l = workbook->formula_cell_list; l; l = l->next){
Cell *cell = l->data;
cell_queue_recalc (cell);
}
workbook_recalc (workbook);
}
......@@ -764,6 +764,29 @@ cell_get_abs_col_row (CellRef *cell_ref, int eval_col, int eval_row, int *col, i
*row = cell_ref->row;
}
static int
evaluate_level (Operation x)
{
if (x == OP_EXP)
return 3;
if ((x==OP_MULT) || (x==OP_DIV))
return 2;
if ((x==OP_ADD) || (x==OP_SUB) || (x==OP_CONCAT))
return 1;
return 0;
}
static int
bigger_prec (Operation parent, Operation this)
{
int parent_level, this_level;
parent_level = evaluate_level (parent);
this_level = evaluate_level (this);
return parent_level > this_level;
}
/*
* Converts a parsed tree into its string representation
* assuming that we are evaluating at col, row (This is
......@@ -773,16 +796,14 @@ cell_get_abs_col_row (CellRef *cell_ref, int eval_col, int eval_row, int *col, i
* This routine is pretty simple: it walks the ExprTree and
* create a string representation.
*/
char *
expr_decode_tree (ExprTree *tree, int col, int row)
static char *
do_expr_decode_tree (ExprTree *tree, int col, int row, Operation parent_op)
{
static const char *binary_operation_names [] = {
"=", ">", "<", ">=", "<=", "<>",
"+", "-", "*", "/", "^", "&"
};
g_return_val_if_fail (tree != NULL, NULL);
switch (tree->oper){
/* The binary operations */
......@@ -801,10 +822,15 @@ expr_decode_tree (ExprTree *tree, int col, int row)
char *a, *b, *res;
char const *op;
a = expr_decode_tree (tree->u.binary.value_a, col, row);
b = expr_decode_tree (tree->u.binary.value_b, col, row);
a = do_expr_decode_tree (tree->u.binary.value_a, col, row, tree->oper);
b = do_expr_decode_tree (tree->u.binary.value_b, col, row, tree->oper);
op = binary_operation_names [tree->oper];
res = g_copy_strings ("(", a, op, b, ")", NULL);
if (bigger_prec (parent_op, tree->oper))
res = g_copy_strings ("(", a, op, b, ")", NULL);
else
res = g_copy_strings (a, op, b, NULL);
g_free (a);
g_free (b);
return res;
......@@ -813,7 +839,7 @@ expr_decode_tree (ExprTree *tree, int col, int row)
case OP_NEG: {
char *res, *a;
a = expr_decode_tree (tree->u.value, col, row);
a = do_expr_decode_tree (tree->u.value, col, row, tree->oper);
res = g_copy_strings ("-", a);
g_free (a);
return res;
......@@ -838,7 +864,7 @@ expr_decode_tree (ExprTree *tree, int col, int row)
for (l = arg_list; l; l = l->next){
ExprTree *t = l->data;
args [i] = expr_decode_tree (t, col, row);
args [i] = do_expr_decode_tree (t, col, row, OP_CONSTANT);
len += strlen (args [i]) + 1;
}
len++;
......@@ -889,4 +915,10 @@ expr_decode_tree (ExprTree *tree, int col, int row)
return g_strdup ("0");
}
char *
expr_decode_tree (ExprTree *tree, int col, int row)
{
g_return_val_if_fail (tree != NULL, NULL);
return do_expr_decode_tree (tree, col, row, OP_CONSTANT);
}
......@@ -577,7 +577,6 @@ gnumeric_sheet_key (GtkWidget *widget, GdkEventKey *event)
direction = (event->state & GDK_SHIFT_MASK) ? 0 : 1;
horizontal = (event->keyval == GDK_Tab) ? 1 : 0;
selection_remove_selection_string (gsheet);
walking_selection = sheet_selection_walk_step (
gsheet->sheet, direction, horizontal,
gsheet->cursor_col, gsheet->cursor_row,
......
......@@ -577,7 +577,6 @@ gnumeric_sheet_key (GtkWidget *widget, GdkEventKey *event)
direction = (event->state & GDK_SHIFT_MASK) ? 0 : 1;
horizontal = (event->keyval == GDK_Tab) ? 1 : 0;
selection_remove_selection_string (gsheet);
walking_selection = sheet_selection_walk_step (
gsheet->sheet, direction, horizontal,
gsheet->cursor_col, gsheet->cursor_row,
......
......@@ -138,8 +138,8 @@ item_cursor_configure_bounds (ItemCursor *item_cursor)
extra = 1;
else
extra = 0;
item->x2 = x + w + 1 + extra;
item->y2 = y + h + 1 + extra;
item->x2 = x + w + 2 + extra;
item->y2 = y + h + 2 + extra;
gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
}
......@@ -362,6 +362,10 @@ item_cursor_selection_event (GnomeCanvasItem *item, GdkEvent *event)
convert (canvas, event->button.x, event->button.y, &x, &y);
group = GNOME_CANVAS_GROUP (canvas->root);
/* determine which part of the cursor was clicked:
* the border or the handlebox
*/
if ((x > item->x2 - 6) && (y > item->y2 - 6))
style = ITEM_CURSOR_AUTOFILL;
else
......@@ -402,11 +406,39 @@ item_cursor_do_drop (ItemCursor *item_cursor)
printf ("DROP!\n");
}
static void
item_cursor_set_bounds_visibly (ItemCursor *item_cursor,
int start_col, int start_row,
int end_col, int end_row)
{
GnomeCanvasItem *item = GNOME_CANVAS_ITEM (item_cursor);
GnumericSheet *gsheet = GNUMERIC_SHEET (item->canvas);
int watch_col, watch_row;
item_cursor_set_bounds (item_cursor, start_col, start_row, end_col, end_row);
/* Now, make the range visible as well as we can guess */
if (start_col < item_cursor->start_col)
watch_col = start_col;
else
watch_col = end_col;
if (start_row < item_cursor->start_row)
watch_row = start_row;
else
watch_row = end_row;
gnumeric_sheet_make_cell_visible (gsheet, watch_col, watch_row);
}
static gint
item_cursor_drag_event (GnomeCanvasItem *item, GdkEvent *event)
{
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (item)->canvas;
ItemCursor *item_cursor = ITEM_CURSOR (item);
int x, y, w, h;
int col, row;
switch (event->type){
case GDK_BUTTON_RELEASE:
gnome_canvas_item_ungrab (item, event->button.time);
......@@ -415,11 +447,20 @@ item_cursor_drag_event (GnomeCanvasItem *item, GdkEvent *event)
return TRUE;
case GDK_BUTTON_PRESS:
printf ("Strange. I got a button press\n");
/* We actually never get this event: this kind of
* cursor is created and grabbed
*/
return TRUE;
case GDK_MOTION_NOTIFY:
printf ("Moving!\n");
convert (canvas, event->button.x, event->button.y, &x, &y);
col = item_grid_find_col (item_cursor->item_grid, x, NULL);
row = item_grid_find_row (item_cursor->item_grid, y, NULL);
w = (item_cursor->end_col - item_cursor->start_col);
h = (item_cursor->end_row - item_cursor->start_row);
item_cursor_set_bounds_visibly (item_cursor, col, row, col + w, row + h);
return TRUE;
default:
......@@ -432,7 +473,6 @@ item_cursor_event (GnomeCanvasItem *item, GdkEvent *event)
{
ItemCursor *item_cursor = ITEM_CURSOR (item);
printf ("getting events!\n");
switch (item_cursor->style){
case ITEM_CURSOR_SELECTION:
return item_cursor_selection_event (item, event);
......@@ -511,7 +551,7 @@ item_cursor_class_init (ItemCursorClass *item_cursor_class)
GTK_ARG_WRITABLE, ARG_ITEM_GRID);
gtk_object_add_arg_type ("ItemCursor::Style", GTK_TYPE_INT,
GTK_ARG_WRITABLE, ARG_STYLE);
object_class->set_arg = item_cursor_set_arg;
object_class->destroy = item_cursor_destroy;
......
......@@ -92,10 +92,10 @@ item_grid_reconfigure (GnomeCanvasItem *item)
}
/*
* find_col: return the column where x belongs to
* item_grid_find_col: return the column where x belongs to
*/
static int
find_col (ItemGrid *item_grid, int x, int *col_origin)
int
item_grid_find_col (ItemGrid *item_grid, int x, int *col_origin)
{
int col = item_grid->left_col;
int pixel = item_grid->left_offset;
......@@ -114,10 +114,10 @@ find_col (ItemGrid *item_grid, int x, int *col_origin)
}
/*
* find_row: return the row where y belongs to
* item_grid_find_row: return the row where y belongs to
*/
static int
find_row (ItemGrid *item_grid, int y, int *row_origin)
int
item_grid_find_row (ItemGrid *item_grid, int y, int *row_origin)
{
int row = item_grid->top_row;
int pixel = item_grid->top_offset;
......@@ -150,16 +150,16 @@ static void
item_grid_draw_cell (GdkDrawable *drawable, ItemGrid *item_grid,
int x1, int y1, int width, int height, int col, int row)
{
GnumericSheet *gsheet = GNUMERIC_SHEET (item_grid->sheet->sheet_view);
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (item_grid)->canvas;
GdkFont *font;
GdkGC *gc = item_grid->gc;
GdkGC *white_gc = GTK_WIDGET (canvas)->style->white_gc;
Sheet *sheet = item_grid->sheet;
Cell *cell, *clip_left, *clip_right;
Style *style;
int x_offset, y_offset, text_base, pixels;
GdkRectangle rect;
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (item_grid)->canvas;
GnumericSheet *gsheet = GNUMERIC_SHEET (canvas);
GdkGC *white_gc = GTK_WIDGET (canvas)->style->white_gc;
GdkGC *gc = item_grid->gc;
Sheet *sheet = item_grid->sheet;
GdkFont *font;
Cell *cell, *clip_left, *clip_right;
Style *style;
int x_offset, y_offset, text_base, pixels;
GdkRectangle rect;
#if 0
item_debug_cross (drawable, gc, x1, y1, x1+width, y1+height);
......@@ -314,8 +314,8 @@ item_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int
}
max_paint_col = max_paint_row = 0;
paint_col = find_col (item_grid, x, &x_paint);
paint_row = find_row (item_grid, y, &y_paint);
paint_col = item_grid_find_col (item_grid, x, &x_paint);
paint_row = item_grid_find_row (item_grid, y, &y_paint);
col = paint_col;
......@@ -356,7 +356,7 @@ item_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int
pd.y_paint = -diff_y;
pd.drawable = drawable;
pd.item_grid = item_grid;
pd.gsheet = GNUMERIC_SHEET (item_grid->sheet->sheet_view);
pd.gsheet = GNUMERIC_SHEET (item->canvas);
#if 0
printf ("Painting the (%d,%d)-(%d,%d) region\n",
......@@ -405,6 +405,148 @@ item_grid_translate (GnomeCanvasItem *item, double dx, double dy)
printf ("item_grid_translate %g, %g\n", dx, dy);
}
static void
context_destroy_menu (GtkWidget *widget)
{
gtk_widget_destroy (gtk_widget_get_toplevel (widget));
}
static void
context_cut_cmd (GtkWidget *widget, ItemGrid *item_grid)
{
sheet_selection_cut (item_grid->sheet);
context_destroy_menu (widget);
}
static void
context_copy_cmd (GtkWidget *widget, ItemGrid *item_grid)
{
sheet_selection_copy (item_grid->sheet);
context_destroy_menu (widget);
}
static void
context_paste_cmd (GtkWidget *widget, ItemGrid *item_grid)
{
GnomeCanvasItem *item = GNOME_CANVAS_ITEM (item_grid);
GnumericSheet *gsheet = GNUMERIC_SHEET (item->canvas);
sheet_selection_paste (item_grid->sheet,
gsheet->cursor_col,
gsheet->cursor_row,
PASTE_DEFAULT);
context_destroy_menu (widget);
}
static void
context_paste_special_cmd (GtkWidget *widget, ItemGrid *item_grid)
{
GnomeCanvasItem *item = GNOME_CANVAS_ITEM (item_grid);
GnumericSheet *gsheet = GNUMERIC_SHEET (item->canvas);
int flags;
flags = dialog_paste_special ();
sheet_selection_paste (item_grid->sheet,
gsheet->cursor_col,
gsheet->cursor_row,
flags);
context_destroy_menu (widget);
}
static void
context_insert_cmd (GtkWidget *widget, ItemGrid *item_grid)
{
context_destroy_menu (widget);
}
static void
context_delete_cmd (GtkWidget *widget, ItemGrid *item_grid)
{
context_destroy_menu (widget);
}
static void
context_cell_format_cmd (GtkWidget *widget, ItemGrid *item_grid)
{
context_destroy_menu (widget);
}
typedef enum {
IG_ALWAYS,
IG_HAVE_SELECTION,
IG_SEPARATOR,
} popup_types;
struct {
char *name;
void (*fn)(GtkWidget *widget, ItemGrid *item_grid);
popup_types type;
} item_grid_context_menu [] = {
{ N_("Cut"), context_cut_cmd, IG_ALWAYS },
{ N_("Copy"), context_copy_cmd, IG_ALWAYS },
{ N_("Paste"), context_paste_cmd, IG_HAVE_SELECTION },
{ N_("Paste special"), context_paste_special_cmd, IG_HAVE_SELECTION },
{ "", NULL, IG_SEPARATOR },
{ N_("Insert"), context_insert_cmd, IG_ALWAYS },
{ N_("Delete"), context_delete_cmd, IG_ALWAYS },
{ N_("Cell format"), context_cell_format_cmd, IG_ALWAYS },
{ NULL, NULL, 0 }
};
static GtkWidget *
create_popup_menu (ItemGrid *item_grid, int include_paste)
{
GtkWidget *menu, *item;
int i;
menu = gtk_menu_new ();
item = NULL;
for (i = 0; item_grid_context_menu [i].name; i++){
switch (item_grid_context_menu [i].type){
case IG_SEPARATOR:
item = gtk_menu_item_new ();
break;
case IG_HAVE_SELECTION:
if (!include_paste)
continue;
/* fall down */
case IG_ALWAYS:
item = gtk_menu_item_new_with_label (
_(item_grid_context_menu [i].name));
break;
default:
g_warning ("Never reached");
}
gtk_signal_connect (
GTK_OBJECT (item), "activate",
GTK_SIGNAL_FUNC (item_grid_context_menu [i].fn),
item_grid);
gtk_widget_show (item);
gtk_menu_append (GTK_MENU (menu), item);
}
return menu;
}
static void
item_grid_popup_menu (ItemGrid *item_grid, GdkEvent *event, int col, int row)
{
GtkWidget *menu;
int show_paste;
show_paste = item_grid->sheet->workbook->clipboard_contents != NULL;
menu = create_popup_menu (item_grid, show_paste);
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, event->button.time);
}
/*
* Handle the selection
*/
......@@ -416,13 +558,13 @@ item_grid_event (GnomeCanvasItem *item, GdkEvent *event)
GnomeCanvas *canvas = item->canvas;
ItemGrid *item_grid = ITEM_GRID (item);
Sheet *sheet = item_grid->sheet;
GnumericSheet *gsheet = GNUMERIC_SHEET (sheet->sheet_view);
GnumericSheet *gsheet = GNUMERIC_SHEET (item->canvas);
int col, row, x, y;
int scroll_x, scroll_y;
switch (event->type){
case GDK_BUTTON_RELEASE:
if (event->button == 1){
if (event->button.button == 1){
item_grid->selecting = 0;
gnome_canvas_item_ungrab (item, event->button.time);
return 1;
......@@ -430,7 +572,7 @@ item_grid_event (GnomeCanvasItem *item, GdkEvent *event)
break;
case GDK_MOTION_NOTIFY:
if (event->button == 1){
if (item_grid->selecting){
scroll_x = scroll_y = 0;
if (event->motion.x < 0){
event->motion.x = 0;
......@@ -443,23 +585,23 @@ item_grid_event (GnomeCanvasItem *item, GdkEvent *event)
if (!item_grid->selecting)
return 1;
col = find_col (item_grid, event->motion.x, NULL);
row = find_row (item_grid, event->motion.y, NULL);
col = item_grid_find_col (item_grid, x, NULL);
row = item_grid_find_row (item_grid, y, NULL);
sheet_selection_extend_to (sheet, col, row);
return 1;
}
break;
case GDK_BUTTON_PRESS:
switch (event->button){
switch (event->button.button){
case 1:
convert (canvas, event->button.x, event->button.y, &x, &y);
col = find_col (item_grid, event->button.x, NULL);
row = find_row (item_grid, event->button.y, NULL);
col = item_grid_find_col (item_grid, x, NULL);
row = item_grid_find_row (item_grid, y, NULL);
gnumeric_sheet_accept_pending_output (gsheet);
gnumeric_sheet_cursor_set (gsheet, col, row);
if (!(event->button.state & GDK_SHIFT_MASK))
if (!(event->button.state & GDK_CONTROL_MASK))
sheet_selection_clear_only (sheet);
item_grid->selecting = 1;
......@@ -472,11 +614,18 @@ item_grid_event (GnomeCanvasItem *item, GdkEvent *event)
return 1;
case 3:
convert (canvas, event->button.x, event->button.y, &x, &y);
col = item_grid_find_col (item_grid, x, NULL);
row = item_grid_find_row (item_grid, y, NULL);
item_grid_popup_menu (item_grid, event, col, row);
return 1;
}
default:
return 0;
}
return 0;
}
/*
......
......@@ -30,6 +30,8 @@ typedef struct {
} ItemGrid;
GtkType item_grid_get_type (void);
int item_grid_find_col (ItemGrid *item_grid, int x, int *col_origin);
int item_grid_find_row (ItemGrid *item_grid, int y, int *row_origin);
typedef struct {
GnomeCanvasItemClass parent_class;
......
......@@ -1355,6 +1355,15 @@ gen_col_blanks (Sheet *sheet, int start_col, int end_col,
return TRUE;
}
/*
* sheet_cell_get
* @sheet: The sheet where we want to locate the cell
* @col: the cell column
* @row: the cell row
*
* Return value: a (Cell *) containing the Cell, or NULL if
* the cell does not exist
*/
Cell *
sheet_cell_get (Sheet *sheet, int col, int row)
{
......
......@@ -197,6 +197,14 @@ void sheet_redraw_all (Sheet *sheet);
void sheet_update_auto_expr (Sheet *sheet);
/* Sheet information manipulation */
void sheet_shift_column (Sheet *sheet,
int column, int row,
int count);
void sheet_shift_row (Sheet *sheet,
int column, int row,
int count);
/*
* Workbook
*/
......@@ -214,6 +222,7 @@ int workbook_parse_and_jump (Workbook *wb, char *text);
* Does any pending recalculations
*/
void workbook_recalc (Workbook *wb);
void workbook_recalc_all (Workbook *wb);
/*
* Callback routine: invoked when the first view ItemGrid
......