Commit 89dcab7c authored by Arturo Espinosa's avatar Arturo Espinosa

Today:



Today:

	- Finally implemented the selection correctly using the
	  cool techniques Raster and Owen described to me on my
	  visit to cool RHAD-land.

	  This basically means Gnumeric does not look sharewareish
	  when you select a range of cells.

	- Zoom dialog box (copy from Excel)

	- Various other sheet-editing facilities are now in place.

	- Scrol-bar fixes and feature additions.

Next:

	I really need to do the file load/save code.
	I really need some sane font code.

15,011
parent 1abfce71
1998-08-26 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/sheet.c (sheet_clear_region_content): New function to remove
the contents of a region of cells.
* src/dialog-zoom.c (dialog_zoom): Add Zoom window.
* src/style.c (style_color_new, style_color_ref,
style_color_unref): New functions. Color for a cell will be kept
as part of the style. Hack note: if valid_flags reports
......@@ -12,7 +17,8 @@
smartly. Now we invert the resulting area (this works for my
16-bpp display, have to try the XOR trick tomorrow on a paletted
display).
(context_clear_cmd): New context command that clears the content
of a cell region.
1998-08-25 Miguel de Icaza <miguel@nuclecu.unam.mx>
......
1998-08-26 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/sheet.c (sheet_clear_region_content): New function to remove
the contents of a region of cells.
* src/dialog-zoom.c (dialog_zoom): Add Zoom window.
* src/style.c (style_color_new, style_color_ref,
style_color_unref): New functions. Color for a cell will be kept
as part of the style. Hack note: if valid_flags reports
......@@ -12,7 +17,8 @@
smartly. Now we invert the resulting area (this works for my
16-bpp display, have to try the XOR trick tomorrow on a paletted
display).
(context_clear_cmd): New context command that clears the content
of a cell region.
1998-08-25 Miguel de Icaza <miguel@nuclecu.unam.mx>
......
1998-08-26 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/sheet.c (sheet_clear_region_content): New function to remove
the contents of a region of cells.
* src/dialog-zoom.c (dialog_zoom): Add Zoom window.
* src/style.c (style_color_new, style_color_ref,
style_color_unref): New functions. Color for a cell will be kept
as part of the style. Hack note: if valid_flags reports
......@@ -12,7 +17,8 @@
smartly. Now we invert the resulting area (this works for my
16-bpp display, have to try the XOR trick tomorrow on a paletted
display).
(context_clear_cmd): New context command that clears the content
of a cell region.
1998-08-25 Miguel de Icaza <miguel@nuclecu.unam.mx>
......
1998-08-26 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/sheet.c (sheet_clear_region_content): New function to remove
the contents of a region of cells.
* src/dialog-zoom.c (dialog_zoom): Add Zoom window.
* src/style.c (style_color_new, style_color_ref,
style_color_unref): New functions. Color for a cell will be kept
as part of the style. Hack note: if valid_flags reports
......@@ -12,7 +17,8 @@
smartly. Now we invert the resulting area (this works for my
16-bpp display, have to try the XOR trick tomorrow on a paletted
display).
(context_clear_cmd): New context command that clears the content
of a cell region.
1998-08-25 Miguel de Icaza <miguel@nuclecu.unam.mx>
......
......@@ -22,6 +22,7 @@ GNUMERIC_BASE_SOURCES = \
dialog-insert-cells.c \
dialog-delete-cells.c \
dialog-paste-special.c \
dialog-zoom.c \
dialogs.h \
eval.c \
expr.c \
......
/*
* dialog-insert-cells.c: Insert a number of cells.
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
*/
#include <config.h>
#include <gnome.h>
#include "gnumeric.h"
#include "gnumeric-util.h"
#include "dialogs.h"
void
dialog_zoom (Sheet *sheet)
{
char *custom;
int state [7];
char *ret;
char buffer [40];
double zoom;
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
memset (&state, 0, sizeof (state));
sprintf (buffer, "%d", (int) sheet->last_zoom_factor_used * 100);
if (sheet->last_zoom_factor_used == 4.0)
state [0] = 1;
else if (sheet->last_zoom_factor_used == 2.0)
state [1] = 1;
else if (sheet->last_zoom_factor_used == 1.0)
state [2] = 1;
else if (sheet->last_zoom_factor_used == 0.75)
state [3] = 1;
else if (sheet->last_zoom_factor_used == 0.50)
state [4] = 1;
else
state [5] = 1;
custom = buffer;
ret = gtk_dialog_cauldron (
_("Zoom"),
GTK_CAULDRON_DIALOG,
"( %[ ( %Rd / %Rd // %Rd // %Rd // %Rd // ( %R | %Ee | %Lfx )) ] / ( %Bqrg || %Bqrg ) )",
_("Zoom"),
"400%", &state[0],
"200%", &state[1],
"100%", &state[2],
"75%", &state[3],
"50%", &state[4],
_("Custom"), &state[5],
&custom,
"%",
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL);
if (strcmp (ret, GNOME_STOCK_BUTTON_CANCEL) == 0)
return;
if (state [0])
zoom = 4.0;
else if (state [1])
zoom = 2.0;
else if (state [2])
zoom = 1.0;
else if (state [3])
zoom = 0.75;
else if (state [4])
zoom = 0.50;
else if (state [5]){
zoom = atof (custom) / 100;
} else
zoom = 1.0;
g_free (custom);
if (zoom < 0.25){
gnumeric_notice (_("Zoom factor should be at least 50%"));
return;
}
if (zoom > 9000){
gnumeric_notice (_("Zoom factor should be at most 900%"));
return;
}
sheet_set_zoom_factor (sheet, zoom);
}
......@@ -6,5 +6,5 @@ void dialog_cell_format (Sheet *sheet);
int dialog_paste_special (void);
void dialog_insert_cells (Sheet *sheet);
void dialog_delete_cells (Sheet *sheet);
void dialog_zoom (Sheet *sheet);
#endif
/*
* dialog-insert-cells.c: Insert a number of cells.
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
*/
#include <config.h>
#include <gnome.h>
#include "gnumeric.h"
#include "gnumeric-util.h"
#include "dialogs.h"
void
dialog_zoom (Sheet *sheet)
{
char *custom;
int state [7];
char *ret;
char buffer [40];
double zoom;
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
memset (&state, 0, sizeof (state));
sprintf (buffer, "%d", (int) sheet->last_zoom_factor_used * 100);
if (sheet->last_zoom_factor_used == 4.0)
state [0] = 1;
else if (sheet->last_zoom_factor_used == 2.0)
state [1] = 1;
else if (sheet->last_zoom_factor_used == 1.0)
state [2] = 1;
else if (sheet->last_zoom_factor_used == 0.75)
state [3] = 1;
else if (sheet->last_zoom_factor_used == 0.50)
state [4] = 1;
else
state [5] = 1;
custom = buffer;
ret = gtk_dialog_cauldron (
_("Zoom"),
GTK_CAULDRON_DIALOG,
"( %[ ( %Rd / %Rd // %Rd // %Rd // %Rd // ( %R | %Ee | %Lfx )) ] / ( %Bqrg || %Bqrg ) )",
_("Zoom"),
"400%", &state[0],
"200%", &state[1],
"100%", &state[2],
"75%", &state[3],
"50%", &state[4],
_("Custom"), &state[5],
&custom,
"%",
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL);
if (strcmp (ret, GNOME_STOCK_BUTTON_CANCEL) == 0)
return;
if (state [0])
zoom = 4.0;
else if (state [1])
zoom = 2.0;
else if (state [2])
zoom = 1.0;
else if (state [3])
zoom = 0.75;
else if (state [4])
zoom = 0.50;
else if (state [5]){
zoom = atof (custom) / 100;
} else
zoom = 1.0;
g_free (custom);
if (zoom < 0.25){
gnumeric_notice (_("Zoom factor should be at least 50%"));
return;
}
if (zoom > 9000){
gnumeric_notice (_("Zoom factor should be at most 900%"));
return;
}
sheet_set_zoom_factor (sheet, zoom);
}
......@@ -6,5 +6,5 @@ void dialog_cell_format (Sheet *sheet);
int dialog_paste_special (void);
void dialog_insert_cells (Sheet *sheet);
void dialog_delete_cells (Sheet *sheet);
void dialog_zoom (Sheet *sheet);
#endif
......@@ -53,10 +53,25 @@ gnumeric_sheet_create (Sheet *sheet, GtkWidget *entry)
void
gnumeric_sheet_cursor_set (GnumericSheet *gsheet, int col, int row)
{
GtkAdjustment *ha, *va;
Sheet *sheet;
g_return_if_fail (GNUMERIC_IS_SHEET (gsheet));
gsheet->cursor_col = col;
gsheet->cursor_row = row;
sheet = gsheet->sheet;
if (sheet->ha){
ha = GTK_ADJUSTMENT (sheet->ha);
va = GTK_ADJUSTMENT (sheet->va);
ha->value = col;
va->value = row;
gtk_adjustment_value_changed (ha);
gtk_adjustment_value_changed (va);
}
}
void
......@@ -203,7 +218,7 @@ move_cursor (GnumericSheet *gsheet, int col, int row, int clear_selection)
gnumeric_sheet_cursor_set (gsheet, col, row);
if (clear_selection)
sheet_selection_clear_only (gsheet->sheet);
sheet_selection_reset_only (gsheet->sheet);
if (clear_selection)
sheet_selection_append (gsheet->sheet, col, row);
......
......@@ -53,10 +53,25 @@ gnumeric_sheet_create (Sheet *sheet, GtkWidget *entry)
void
gnumeric_sheet_cursor_set (GnumericSheet *gsheet, int col, int row)
{
GtkAdjustment *ha, *va;
Sheet *sheet;
g_return_if_fail (GNUMERIC_IS_SHEET (gsheet));
gsheet->cursor_col = col;
gsheet->cursor_row = row;
sheet = gsheet->sheet;
if (sheet->ha){
ha = GTK_ADJUSTMENT (sheet->ha);
va = GTK_ADJUSTMENT (sheet->va);
ha->value = col;
va->value = row;
gtk_adjustment_value_changed (ha);
gtk_adjustment_value_changed (va);
}
}
void
......@@ -203,7 +218,7 @@ move_cursor (GnumericSheet *gsheet, int col, int row, int clear_selection)
gnumeric_sheet_cursor_set (gsheet, col, row);
if (clear_selection)
sheet_selection_clear_only (gsheet->sheet);
sheet_selection_reset_only (gsheet->sheet);
if (clear_selection)
sheet_selection_append (gsheet->sheet, col, row);
......
......@@ -37,8 +37,10 @@ item_grid_destroy (GtkObject *object)
static void
item_grid_realize (GnomeCanvasItem *item)
{
ItemGrid *item_grid;
GnomeCanvas *canvas = item->canvas;
GdkVisual *visual;
GdkWindow *window;
ItemGrid *item_grid;
GdkGC *gc;
if (GNOME_CANVAS_ITEM_CLASS (item_grid_parent_class)->realize)
......@@ -67,6 +69,21 @@ item_grid_realize (GnomeCanvasItem *item)
gdk_gc_set_foreground (item_grid->fill_gc, &item_grid->background);
gdk_gc_set_background (item_grid->fill_gc, &item_grid->grid_color);
/* Find out how we need to draw the selection with the current visual */
visual = gtk_widget_get_visual (GTK_WIDGET (canvas));
switch (visual->type){
case GDK_VISUAL_STATIC_GRAY:
case GDK_VISUAL_TRUE_COLOR:
case GDK_VISUAL_STATIC_COLOR:
item_grid->visual_is_paletted = 0;
break;
default:
item_grid->visual_is_paletted = 1;
}
}
static void
......@@ -194,27 +211,6 @@ item_grid_draw_cell (GdkDrawable *drawable, ItemGrid *item_grid,
style = cell->style;
font = style->font->font;
#if 0
/* Code to test the different alignements, hardcoded for now */
switch (col){
case 0:
style->halign = HALIGN_GENERAL;
break;
case 1:
style->halign = HALIGN_LEFT;
break;
case 2:
style->halign = HALIGN_RIGHT;
break;
case 3:
style->halign = HALIGN_CENTER;
break;
case 4:
style->halign = HALIGN_FILL;
break;
}
#endif
/*
* General Alignement is a special case: it means
* left alignment for text and right alignment for
......@@ -271,7 +267,8 @@ item_grid_draw_cell (GdkDrawable *drawable, ItemGrid *item_grid,
text_base = y1 + cell->row->pixels - cell->row->margin_b - font->descent + 1;
gdk_gc_set_foreground (gc, &item_grid->default_color);
gdk_gc_set_function (gc, GDK_COPY);
if (clip_left || clip_right){
rect.x = x1;
rect.y = y1;
......@@ -306,12 +303,21 @@ item_grid_draw_cell (GdkDrawable *drawable, ItemGrid *item_grid,
} while (style->halign == HALIGN_FILL &&
pixels < cell->col->pixels);
/*
* If the cell is selected, turn the inverse video on
*/
if (cell_is_selected){
if (gsheet->cursor_col == col && gsheet->cursor_row == row)
return;
if (item_grid->visual_is_paletted){
gdk_gc_set_function (gc, GDK_XOR);
gdk_gc_set_foreground (gc, &gs_white);
} else {
gdk_gc_set_function (gc, GDK_INVERT);
gdk_gc_set_foreground (gc, &gs_black);
}
gdk_gc_set_function (gc, GDK_INVERT);
gdk_gc_set_foreground (gc, &gs_black);
gdk_draw_rectangle (drawable, gc, TRUE,
x1 + 1,
y1 + 1,
......@@ -496,6 +502,13 @@ context_delete_cmd (GtkWidget *widget, ItemGrid *item_grid)
context_destroy_menu (widget);
}
static void
context_clear_cmd (GtkWidget *widget, ItemGrid *item_grid)
{
sheet_selection_clear_content (item_grid->sheet);
context_destroy_menu (widget);
}
static void
context_cell_format_cmd (GtkWidget *widget, ItemGrid *item_grid)
{
......@@ -521,6 +534,8 @@ struct {
{ "", NULL, IG_SEPARATOR },
{ N_("Insert"), context_insert_cmd, IG_ALWAYS },
{ N_("Delete"), context_delete_cmd, IG_ALWAYS },
{ N_("Erase content"), context_clear_cmd, IG_ALWAYS },
{ "", NULL, IG_SEPARATOR },
{ N_("Cell format"), context_cell_format_cmd, IG_ALWAYS },
{ NULL, NULL, 0 }
};
......@@ -634,7 +649,7 @@ item_grid_event (GnomeCanvasItem *item, GdkEvent *event)
gnumeric_sheet_accept_pending_output (gsheet);
gnumeric_sheet_cursor_set (gsheet, col, row);
if (!(event->button.state & GDK_CONTROL_MASK))
sheet_selection_clear_only (sheet);
sheet_selection_reset_only (sheet);
item_grid->selecting = 1;
sheet_selection_append (sheet, col, row);
......
......@@ -27,6 +27,8 @@ typedef struct {
GdkColor background;
GdkColor grid_color;
GdkColor default_color;
int visual_is_paletted;
} ItemGrid;
GtkType item_grid_get_type (void);
......
......@@ -130,7 +130,7 @@ sheet_col_selection_changed (ItemBar *item_bar, int column, int reset, Sheet *sh
if (reset){
sheet_cursor_set (sheet, column, 0, column, SHEET_MAX_ROWS - 1);
sheet_selection_clear_only (sheet);
sheet_selection_reset_only (sheet);
sheet_selection_append_range (sheet,
column, 0,
column, 0,
......@@ -156,7 +156,7 @@ sheet_row_selection_changed (ItemBar *item_bar, int row, int reset, Sheet *sheet
if (reset){
sheet_cursor_set (sheet, 0, row, SHEET_MAX_COLS-1, row);
sheet_selection_clear_only (sheet);
sheet_selection_reset_only (sheet);
sheet_selection_append_range (sheet,
0, row,
0, row,
......@@ -307,8 +307,8 @@ sheet_size_allocate (GtkWidget *widget, GtkAllocation *alloc, Sheet *sheet)
GtkAdjustment *va = GTK_ADJUSTMENT (sheet->va);
GtkAdjustment *ha = GTK_ADJUSTMENT (sheet->ha);
GnumericSheet *gsheet = GNUMERIC_SHEET (sheet->sheet_view);
int last_col = gsheet->last_visible_col;
int last_row = gsheet->last_visible_row;
int last_col = gsheet->last_full_col;
int last_row = gsheet->last_full_row;
va->upper = MAX (last_row, sheet->max_row_used);
va->page_size = last_row - gsheet->top_row;
......@@ -553,7 +553,7 @@ sheet_col_add (Sheet *sheet, ColRowInfo *cp)
sheet->max_col_used = cp->pos;
if (sheet->max_col_used > ha->upper){
ha->upper = sheet->max_col_used;
gtk_adjustment_value_changed (ha);
gtk_adjustment_changed (ha);
}
}
sheet->cols_info = g_list_insert_sorted (sheet->cols_info, cp, CRsort);
......@@ -568,7 +568,7 @@ sheet_row_add (Sheet *sheet, ColRowInfo *rp)
sheet->max_row_used = rp->pos;
if (sheet->max_row_used > va->upper){
va->upper = sheet->max_row_used;
gtk_adjustment_value_changed (va);
gtk_adjustment_changed (va);
}
}
sheet->rows_info = g_list_insert_sorted (sheet->rows_info, rp, CRsort);
......@@ -1000,7 +1000,7 @@ sheet_select_all (Sheet *sheet)
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
sheet_selection_clear_only (sheet);
sheet_selection_reset_only (sheet);
sheet_cursor_set (sheet, 0, 0, SHEET_MAX_COLS-1, SHEET_MAX_ROWS-1);
sheet_selection_append_range (sheet, 0, 0, 0, 0,
SHEET_MAX_COLS-1, SHEET_MAX_ROWS-1);
......@@ -1198,7 +1198,7 @@ clean_bar_selection (GList *list)
}
/*
* sheet_selection_clear
* sheet_selection_reset
* sheet: The sheet
*
* Clears all of the selection ranges.
......@@ -1206,7 +1206,7 @@ clean_bar_selection (GList *list)
* be taken care on the calling routine.
*/
void
sheet_selection_clear_only (Sheet *sheet)
sheet_selection_reset_only (Sheet *sheet)
{
GnumericSheet *gsheet;
GList *list = sheet->selections;
......@@ -1239,14 +1239,14 @@ sheet_selection_clear_only (Sheet *sheet)
}
/*
* sheet_selection_clear
* sheet_selection_reset
* sheet: The sheet
*
* Clears all of the selection ranges and resets it to a
* selection that only covers the cursor
*/
void
sheet_selection_clear (Sheet *sheet)
sheet_selection_reset (Sheet *sheet)
{
GnumericSheet *gsheet;
......@@ -1255,7 +1255,7 @@ sheet_selection_clear (Sheet *sheet)
gsheet = GNUMERIC_SHEET (sheet->sheet_view);
sheet_selection_clear_only (sheet);
sheet_selection_reset_only (sheet);
sheet_selection_append (sheet, gsheet->cursor_col, gsheet->cursor_row);
}
......@@ -1856,7 +1856,7 @@ sheet_destroy (Sheet *sheet)
g_assert (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
sheet_selection_clear (sheet);
sheet_selection_reset (sheet);
g_free (sheet->name);
g_hash_table_foreach (sheet->cell_hash, cell_hash_free_key, NULL);
......@@ -1904,6 +1904,104 @@ sheet_clear_region (Sheet *sheet, int start_col, int start_row, int end_col, int
g_list_free (destroyable_cells);
}
void
sheet_selection_clear (Sheet *sheet)
{
GList *l;
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
for (l = sheet->selections; l; l = l->next){
SheetSelection *ss = l->data;
sheet_clear_region (sheet,
ss->start_col, ss->start_row,
ss->end_col, ss->end_row);
}
}
static int
clear_cell_content (Sheet *sheet, int col, int row, Cell *cell, void *user_data)
{
cell_set_text (cell, "");
return TRUE;
}
/*
* Clears the contents in a region of cells
*/
void
sheet_clear_region_content (Sheet *sheet, int start_col, int start_row, int end_col, int end_row)
{
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
g_return_if_fail (start_col <= end_col);
g_return_if_fail (start_row <= end_row);
sheet_cell_foreach_range (
sheet, TRUE,
start_col, start_row,
end_col, end_row,
clear_cell_content, NULL);
}
void
sheet_selection_clear_content (Sheet *sheet)
{
GList *l;
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
for (l = sheet->selections; l; l = l->next){
SheetSelection *ss = l->data;
sheet_clear_region_content (sheet,
ss->start_col, ss->start_row,
ss->end_col, ss->end_row);
}
}
static int
clear_cell_format (Sheet *sheet, int col, int row, Cell *cell, void *user_data)
{
cell_set_format (cell, "General");
return TRUE;
}
void
sheet_clear_region_formats (Sheet *sheet, int start_col, int start_row, int end_col, int end_row)
{
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
g_return_if_fail (start_col <= end_col);
g_return_if_fail (start_row <= end_row);
sheet_cell_foreach_range (
sheet, TRUE,
start_col, start_row,
end_col, end_row,
clear_cell_format, NULL);
}
void
sheet_selection_clear_formats (Sheet *sheet)
{
GList *l;
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
for (l = sheet->selections; l; l = l->next){
SheetSelection *ss = l->data;
sheet_clear_region_formats (sheet,
ss->start_col, ss->start_row,
ss->end_col, ss->end_row);
}
}
gboolean
sheet_verify_selection_simple (Sheet *sheet, char *command_name)
{
......@@ -2004,7 +2102,7 @@ sheet_selection_paste (Sheet *sheet, int dest_col, int dest_row, int paste_flags
paste_width, paste_height, paste_flags);
sheet_cursor_set (sheet, dest_col, dest_row, end_col, end_row);
sheet_selection_clear_only (sheet);
sheet_selection_reset_only (sheet);
sheet_selection_append (sheet, dest_col, dest_row);
sheet_selection_extend_to (sheet, end_col, end_row);
}
......
......@@ -131,8 +131,8 @@ void sheet_cursor_move (Sheet *sheet, int col, int row);
void sheet_select_all (Sheet *sheet);
void sheet_selection_append (Sheet *sheet, int col, int row);
void sheet_selection_extend_to (Sheet *sheet, int col, int row);
void sheet_selection_clear (Sheet *sheet);
void sheet_selection_clear_only (Sheet *sheet);
void sheet_selection_reset (Sheet *sheet);
void sheet_selection_reset_only (Sheet *sheet);
int sheet_selection_equal (SheetSelection *a, SheetSelection *b);
void sheet_selection_append_range (Sheet *sheet,
int base_col, int base_row,
......@@ -140,6 +140,11 @@ void sheet_selection_append_range (Sheet *sheet,
int end_col, int end_row);
CellList *sheet_selection_to_list (Sheet *sheet);
/* Operations on the selection */
void sheet_selection_clear_content (Sheet *sheet);
void sheet_selection_clear_formats (Sheet *sheet);
void sheet_selection_clear (Sheet *sheet);
/* Cut/Copy/Paste on the workbook selection */
gboolean sheet_selection_copy (Sheet *sheet);
gboolean sheet_selection_cut (Sheet *sheet);
......@@ -157,86 +162,92 @@ int sheet_selection_is_cell_selected (Sheet *sheet, int col, int row);
gboolean sheet_verify_selection_simple (Sheet *sheet, char *command_name);
/* Cell management */
Cell *sheet_cell_new (Sheet *sheet, int col, int row);
void sheet_cell_add (Sheet *sheet, Cell *cell,
int col, int row);
void sheet_cell_remove (Sheet *sheet, Cell *cell);
int sheet_cell_foreach_range (Sheet *sheet, int only_existing,
int start_col, int start_row,
int end_col, int end_row,
sheet_cell_foreach_callback callback,
void *closure);
Cell *sheet_cell_get (Sheet *sheet, int col, int row);
void sheet_cell_formula_link (Cell *cell);
void sheet_cell_formula_unlink (Cell *cell);
Cell *sheet_cell_new (Sheet *sheet, int col, int row);