Commit 601c3888 authored by Arturo Espinosa's avatar Arturo Espinosa

OK, first version of Gnumeric with cut/copy/paste support.



OK, first version of Gnumeric with cut/copy/paste support.

It has a bug or two that I will fix tomorrow first thing in
the morning.

Tomorrow I will also do the "move" region thingie with the
new fix to the canvas from Federico.

Miguel.
parent 5c4ebb73
......@@ -15,6 +15,8 @@ GNOME_XML_LIB = -lxml
GNUMERIC_BASE_SOURCES = \
cell.h \
cell.c \
clipboard.c \
clipboard.h \
eval.c \
expr.c \
expr.h \
......@@ -24,6 +26,8 @@ GNUMERIC_BASE_SOURCES = \
fn-math.c \
gnumeric-sheet.c \
gnumeric-sheet.h \
gnumeric-util.c \
gnumeric-util.h \
gnumeric.h \
item-bar.c \
item-bar.h \
......
......@@ -156,7 +156,8 @@ cell_copy (Cell *cell)
/* now copy propertly the rest */
string_ref (new_cell->entered_text);
expr_tree_ref (new_cell->parsed_node);
if (new_cell->parsed_node)
expr_tree_ref (new_cell->parsed_node);
string_ref (new_cell->text);
new_cell->style = style_duplicate (new_cell->style);
......
......@@ -54,6 +54,18 @@ typedef struct {
#define CELL_TEXT_GET(cell) ((cell)->text ? cell->text->str : cell->entered_text->str)
#define CELL_IS_FORMULA(cell) (cell->entered_text->str [0] == '=')
typedef struct {
int col_offset, row_offset; /* Position of the cell */
Cell *cell;
} CellCopy;
typedef GList CellCopyList;
typedef struct {
int cols, rows;
CellCopyList *list;
} CellRegion;
void cell_set_text (Cell *cell, char *text);
void cell_set_formula (Cell *cell, char *text);
void cell_calc_dimensions (Cell *cell);
......
......@@ -16,7 +16,7 @@ typedef struct {
CellRegion *r;
} append_cell_closure_t;
int
static int
clipboard_append_cell (Sheet *sheet, int col, int row, Cell *cell, void *user_data)
{
append_cell_closure_t *c = user_data;
......@@ -26,7 +26,7 @@ clipboard_append_cell (Sheet *sheet, int col, int row, Cell *cell, void *user_da
copy->cell = cell_copy (cell);
copy->col_offset = col - c->base_col;
copy->row_offset = col - c->base_col;
copy->row_offset = row - c->base_row;
/* Now clear the traces and dependencies on the copied Cell */
copy->cell->col = NULL;
......@@ -43,29 +43,73 @@ clipboard_copy_cell_range (Sheet *sheet, int start_col, int start_row, int end_c
{
append_cell_closure_t c;
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);
g_return_val_if_fail (sheet != NULL, NULL);
g_return_val_if_fail (IS_SHEET (sheet), NULL);
g_return_val_if_fail (start_col <= end_col, NULL);
g_return_val_if_fail (start_row <= end_row, NULL);
c.r = g_new (CellRegion, 1);
c.r = g_new0 (CellRegion, 1);
c.base_col = start_col;
c.base_row = start_row;
c.r->cols = end_col - start_col + 2;
c.r->rows = end_row - start_row + 2;
c.r->cols = end_col - start_col + 1;
c.r->rows = end_row - start_row + 1;
sheet_cell_foreach_range (
sheet, 1, start_col, start_row, end_col, end_row,
clipboard_append_cell, r);
clipboard_append_cell, &c);
return c.r;
}
void
clipboard_paste_region (CellRegion *region, Sheet *dest_sheet, int dest_col, int_dest_row)
clipboard_paste_region (CellRegion *region, Sheet *dest_sheet, int dest_col, int dest_row, int paste_flags)
{
sheet_clear_region (sheet,
CellCopyList *l;
int paste_formulas = paste_flags & PASTE_FORMULAS;
int paste_formats = paste_formulas & PASTE_FORMATS;
g_return_if_fail (region != NULL);
g_return_if_fail (dest_sheet != NULL);
g_return_if_fail (IS_SHEET (dest_sheet));
/* Clear the region where we will paste */
sheet_clear_region (dest_sheet,
dest_col, dest_row,
dest_col + region->cols,
dest_row + region->row);
dest_col + region->cols - 1,
dest_row + region->rows - 1);
/* Paste each element */
for (l = region->list; l; l = l->next){
CellCopy *c_copy = l->data;
Cell *new_cell;
/* FIXME: create a cell_copy_flags that uses
* the bits more or less like paste_flags
*/
new_cell = cell_copy (c_copy->cell);
sheet_cell_add (dest_sheet, new_cell,
dest_col + c_copy->col_offset,
dest_row + c_copy->row_offset);
}
}
void
clipboard_release (CellRegion *region)
{
CellCopyList *l;
g_return_if_fail (region != NULL);
l = region->list;
for (; l; l = l->next){
CellCopy *this_cell = l->data;
cell_destroy (this_cell->cell);
g_free (this_cell);
}
g_list_free (region->list);
g_free (region);
}
#ifndef CLIPBOARD_H
#define CLIPBOARD_H
typedef struct {
int col_offset, pos_offset; /* Position of the cell */
Cell *cell;
} CellCopy;
enum {
PASTE_TEXT = 0, /* NOte that Text/Formulas are mutually exclusive */
PASTE_FORMULAS = 1,
PASTE_FORMATS = 2,
typedef GList CellRegionList;
/* Operations that can be performed at paste time on a cell */
PASTE_OP_ADD = 4,
PASTE_OP_SUB = 8,
PASTE_OP_MULT = 16,
PASTE_OP_DIV = 32
};
typedef struct {
int cols, rows;
CelLRegionList list;
} CellRegion;
#define PASTE_DEFAULT (PASTE_FORMULAS | PASTE_FORMATS)
#define PASTE_OP_MASK (PASTE_OP_ADD | PASTE_OP_SUB | PASTE_OP_MULT | PASTE_OP_DIV)
CellRegion *clipboard_copy_cell_range (Sheet *sheet,
int start_col, int start_row,
......@@ -20,5 +23,8 @@ CellRegion *clipboard_copy_cell_range (Sheet *sheet,
void clipboard_paste_region (CellRegion *region,
Sheet *dest_sheet,
int dest_col,
int dest_row);
int dest_row,
int paste_flags);
void clipboard_release (CellRegion *region);
#endif
/*
* gnumeric-util.c: Various GUI utility functions.
* (C) 1998 The Free Software Foundation
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
*/
#include <config.h>
#include <gnome.h>
#include "gnumeric.h"
#include "gnumeric-util.h"
void
gnumeric_notice (char *str)
{
GtkWidget *dialog;
GtkWidget *label;
label = gtk_label_new (str);
dialog = gnome_dialog_new (_("Notice"), GNOME_STOCK_BUTTON_OK, NULL);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, TRUE, TRUE, 0);
gtk_widget_show (label);
gnome_dialog_run_modal (GNOME_DIALOG (dialog));
gtk_object_destroy (GTK_OBJECT (dialog));
}
#ifndef GNUMERIC_UTIL_H
#define GNUMERIC_UTIL_H
void gnumeric_notice (char *str);
#endif
......@@ -5,4 +5,5 @@
#include "expr.h"
#include "cell.h"
#include "sheet.h"
#include "clipboard.h"
#include "utils.h"
/*
* gnumeric-util.c: Various GUI utility functions.
* (C) 1998 The Free Software Foundation
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
*/
#include <config.h>
#include <gnome.h>
#include "gnumeric.h"
#include "gnumeric-util.h"
void
gnumeric_notice (char *str)
{
GtkWidget *dialog;
GtkWidget *label;
label = gtk_label_new (str);
dialog = gnome_dialog_new (_("Notice"), GNOME_STOCK_BUTTON_OK, NULL);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, TRUE, TRUE, 0);
gtk_widget_show (label);
gnome_dialog_run_modal (GNOME_DIALOG (dialog));
gtk_object_destroy (GTK_OBJECT (dialog));
}
#ifndef GNUMERIC_UTIL_H
#define GNUMERIC_UTIL_H
void gnumeric_notice (char *str);
#endif
......@@ -11,6 +11,7 @@
#include "gnumeric.h"
#include "gnumeric-sheet.h"
#include "utils.h"
#include "gnumeric-util.h"
static void sheet_selection_col_extend_to (Sheet *sheet, int col);
static void sheet_selection_row_extend_to (Sheet *sheet, int row);
......@@ -1308,16 +1309,11 @@ CRowSort (gconstpointer a, gconstpointer b)
return ca->row->pos - cb->row->pos;
}
Cell *
sheet_cell_new (Sheet *sheet, int col, int row)
void
sheet_cell_add (Sheet *sheet, Cell *cell, int col, int row)
{
Cell *cell;
CellPos *cellref;
g_return_val_if_fail (sheet != NULL, NULL);
g_return_val_if_fail (IS_SHEET (sheet), NULL);
cell = g_new0 (Cell, 1);
cell->sheet = sheet;
cell->col = sheet_col_get (sheet, col);
cell->row = sheet_row_get (sheet, row);
......@@ -1332,6 +1328,18 @@ sheet_cell_new (Sheet *sheet, int col, int row)
g_hash_table_insert (sheet->cell_hash, cellref, cell);
cell->col->data = g_list_insert_sorted (cell->col->data, cell, CRowSort);
}
Cell *
sheet_cell_new (Sheet *sheet, int col, int row)
{
Cell *cell;
g_return_val_if_fail (sheet != NULL, NULL);
g_return_val_if_fail (IS_SHEET (sheet), NULL);
cell = g_new0 (Cell, 1);
sheet_cell_add (sheet, cell, col, row);
return cell;
}
......@@ -1339,7 +1347,7 @@ void
sheet_cell_remove (Sheet *sheet, Cell *cell)
{
CellPos cellref;
g_return_if_fail (sheet != NULL);
g_return_if_fail (cell != NULL);
g_return_if_fail (IS_SHEET (sheet));
......@@ -1349,27 +1357,107 @@ sheet_cell_remove (Sheet *sheet, Cell *cell)
g_hash_table_remove (sheet->cell_hash, &cellref);
cell->col->data = g_list_remove (cell->col->data, cell);
sheet_redraw_cell_region (sheet,
cellref.col, cellref.row,
cellref.col, cellref.row);
}
static int
clear_cell (Sheet *sheet, int col, int row, Cell *cell, void *user_data)
assemble_cell (Sheet *sheet, int col, int row, Cell *cell, void *user_data)
{
sheet_cell_remove (sheet, cell);
cell_destroy (cell);
GList **l = (GList **) user_data;
*l = g_list_prepend (*l, cell);
return TRUE;
}
/*
* Clears are region of cells
*
* We assemble a list of cells to destroy, since we will be making changes
* to the structure being manipulated by the sheet_cell_foreach_range routine
*/
void
sheet_clear_region (Sheet *sheet, int start_col, int start_row, int end_col, int end_row)
{
GList *destroyable_cells, *l;
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);
destroyable_cells = NULL;
sheet_cell_foreach_range (
sheet, TRUE,
start_col, start_row,end_col, end_row,
clear_cell, NULL);
start_col, start_row,
end_col, end_row,
assemble_cell, &destroyable_cells);
for (l = destroyable_cells; l; l = l->next){
Cell *cell = l->data;
sheet_cell_remove (sheet, cell);
cell_destroy (cell);
}
g_list_free (destroyable_cells);
}
void
sheet_selection_copy (Sheet *sheet)
{
SheetSelection *ss;
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
if (g_list_length (sheet->selections) != 1){
gnumeric_notice (_("Can not copy non-contiguous selections"));
return;
}
ss = sheet->selections->data;
if (sheet->workbook->clipboard_contents)
clipboard_release (sheet->workbook->clipboard_contents);
sheet->workbook->clipboard_contents = clipboard_copy_cell_range (
sheet,
ss->start_col, ss->start_row,
ss->end_col, ss->end_row);
}
void
sheet_selection_cut (Sheet *sheet)
{
SheetSelection *ss;
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
if (g_list_length (sheet->selections) != 1){
gnumeric_notice (_("Can not cut non-contiguous selections"));
return;
}
ss = sheet->selections->data;
sheet_selection_copy (sheet);
sheet_clear_region (sheet, ss->start_col, ss->start_row, ss->end_col, ss->end_row);
}
void
sheet_selection_paste (Sheet *sheet, int dest_col, int dest_row, int paste_flags)
{
CellRegion *content;
g_return_if_fail (sheet != NULL);
g_return_if_fail (IS_SHEET (sheet));
content = sheet->workbook->clipboard_contents;
if (!content)
return;
clipboard_paste_region (content, sheet, dest_col, dest_row, paste_flags);
}
......@@ -34,6 +34,9 @@ typedef struct {
GList *eval_queue;
int max_iterations;
guchar generation;
/* The clipboard for this workbook */
CellRegion *clipboard_contents;
} Workbook;
typedef struct {
......@@ -111,12 +114,21 @@ void sheet_selection_append_range (Sheet *sheet,
int start_col, int start_row,
int end_col, int end_row);
/* Cut/Copy/Paste on the workbook selection */
void sheet_selection_copy (Sheet *sheet);
void sheet_selection_cut (Sheet *sheet);
void sheet_selection_paste (Sheet *sheet,
int dest_col, int dest_row,
int paste_flags);
void sheet_selection_extend_horizontal (Sheet *sheet, int count);
void sheet_selection_extend_vertical (Sheet *sheet, int count);
int sheet_selection_is_cell_selected (Sheet *sheet, int col, int row);
/* 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,
......
......@@ -21,11 +21,45 @@ quit_cmd (void)
}
static void
save_cmd (void)
save_cmd (GtkWidget *widget, Workbook *wb)
{
gnumericWriteXmlWorkbook (current_workbook, "default.wb");
}
static void
paste_cmd (GtkWidget *widget, Workbook *wb)
{
Sheet *sheet;
GnumericSheet *gsheet;
sheet = workbook_get_current_sheet (wb);
gsheet = GNUMERIC_SHEET (sheet->sheet_view);
sheet_selection_paste (sheet, gsheet->cursor_col, gsheet->cursor_row, PASTE_DEFAULT);
}
static void
copy_cmd (GtkWidget *widget, Workbook *wb)
{
Sheet *sheet;
sheet = workbook_get_current_sheet (wb);
sheet_selection_copy (sheet);
}
static void
cut_cmd (GtkWidget *widget, Workbook *wb)
{
Sheet *sheet;
sheet = workbook_get_current_sheet (wb);
sheet_selection_cut (sheet);
}
static void
paste_special_cmd (GtkWidget *widget, Workbook *wb)
{
}
static GnomeUIInfo workbook_menu_file [] = {
{ GNOME_APP_UI_ITEM, N_("Save"), NULL, save_cmd, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_SAVE },
......@@ -34,8 +68,21 @@ static GnomeUIInfo workbook_menu_file [] = {
GNOMEUIINFO_END
};
static GnomeUIInfo workbook_menu_edit [] = {
{ GNOME_APP_UI_ITEM, N_("Cut"), NULL, cut_cmd, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_CUT },
{ GNOME_APP_UI_ITEM, N_("Copy"), NULL, copy_cmd, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_COPY },
{ GNOME_APP_UI_ITEM, N_("Paste"), NULL, paste_cmd, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_PASTE },
{ GNOME_APP_UI_ITEM, N_("Paste special"), NULL, paste_special_cmd, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_PASTE },
GNOMEUIINFO_END
};
static GnomeUIInfo workbook_menu [] = {
{ GNOME_APP_UI_SUBTREE, N_("File"), NULL, &workbook_menu_file },
{ GNOME_APP_UI_SUBTREE, N_("Edit"), NULL, &workbook_menu_edit },
GNOMEUIINFO_END
};
......@@ -306,7 +353,7 @@ workbook_new (void)
workbook_setup_edit_area (wb);
workbook_setup_sheets (wb);
gnome_app_set_contents (GNOME_APP (wb->toplevel), wb->table);
gnome_app_create_menus (GNOME_APP (wb->toplevel), workbook_menu);
gnome_app_create_menus_with_data (GNOME_APP (wb->toplevel), workbook_menu, wb);
/* Set the default operation to be performed over selections */
workbook_set_auto_expr (wb, "SUM", "SUM(SELECTION())");
......
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