clipboard.c 3.67 KB
Newer Older
Arturo Espinosa's avatar
Arturo Espinosa committed
1 2 3 4 5 6 7 8 9 10 11
/*
 * Clipboard.c: Implements the copy/paste operations
 * (C) 1998 The Free Software Foundation.
 *
 * Author:
 *  MIguel de Icaza (miguel@gnu.org)
 *
 */
#include <config.h>
#include <gnome.h>
#include "gnumeric.h"
12
#include "gnumeric-util.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
13
#include "clipboard.h"
14
#include "eval.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
15 16 17 18 19 20

typedef struct {
	int        base_col, base_row;
	CellRegion *r;
} append_cell_closure_t;

21
static int
Arturo Espinosa's avatar
Arturo Espinosa committed
22 23 24 25 26 27 28 29 30
clipboard_append_cell (Sheet *sheet, int col, int row, Cell *cell, void *user_data)
{
	append_cell_closure_t *c = user_data;
	CellCopy *copy;

	copy = g_new (CellCopy, 1);

	copy->cell = cell_copy (cell);
	copy->col_offset  = col - c->base_col;
31
	copy->row_offset  = row - c->base_row;
Arturo Espinosa's avatar
Arturo Espinosa committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
	
	/* Now clear the traces and dependencies on the copied Cell */
	copy->cell->col   = NULL;
	copy->cell->row   = NULL;
	copy->cell->sheet = NULL;
	
	c->r->list = g_list_prepend (c->r->list, copy);

	return TRUE;
}

CellRegion *
clipboard_copy_cell_range (Sheet *sheet, int start_col, int start_row, int end_col, int end_row)
{
	append_cell_closure_t c;

48 49 50 51
	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);
Arturo Espinosa's avatar
Arturo Espinosa committed
52
	
53
	c.r = g_new0 (CellRegion, 1);
Arturo Espinosa's avatar
Arturo Espinosa committed
54 55 56

	c.base_col = start_col;
	c.base_row = start_row;
57 58
	c.r->cols = end_col - start_col + 1;
	c.r->rows = end_row - start_row + 1;
Arturo Espinosa's avatar
Arturo Espinosa committed
59 60 61
	
	sheet_cell_foreach_range (
		sheet, 1, start_col, start_row, end_col, end_row,
62 63 64
		clipboard_append_cell, &c);

	return c.r;
Arturo Espinosa's avatar
Arturo Espinosa committed
65 66
}

Arturo Espinosa's avatar
Arturo Espinosa committed
67 68 69 70
static int
paste_cell (Sheet *dest_sheet, Cell *new_cell, int target_col, int target_row, int paste_flags)
{
	sheet_cell_add (dest_sheet, new_cell, target_col, target_row);
Miguel de Icaza's avatar
Miguel de Icaza committed
71
	
Arturo Espinosa's avatar
Arturo Espinosa committed
72 73 74 75 76 77 78 79
	if (!(paste_flags & PASTE_FORMULAS)){
		if (new_cell->parsed_node){
			expr_tree_unref (new_cell->parsed_node);
			new_cell->parsed_node = NULL;
		}
	}
	
	if (new_cell->parsed_node){
Arturo Espinosa's avatar
Arturo Espinosa committed
80 81 82 83
		if (paste_flags & PASTE_FORMULAS)
			cell_formula_relocate (new_cell, target_col, target_row);
		else 
			cell_make_value (new_cell);
Arturo Espinosa's avatar
Arturo Espinosa committed
84
	}
Miguel de Icaza's avatar
Miguel de Icaza committed
85 86

	cell_render_value (new_cell);
Arturo Espinosa's avatar
Arturo Espinosa committed
87 88 89
	
	if (!(paste_flags & PASTE_FORMULAS)){
		string_unref (new_cell->entered_text);
Miguel de Icaza's avatar
Miguel de Icaza committed
90
		new_cell->entered_text = string_ref (new_cell->text);
Arturo Espinosa's avatar
Arturo Espinosa committed
91
	}
Miguel de Icaza's avatar
Miguel de Icaza committed
92

Arturo Espinosa's avatar
Arturo Espinosa committed
93 94 95 96 97 98 99
	sheet_redraw_cell_region (dest_sheet,
				  target_col, target_row,
				  target_col, target_row);

	return new_cell->parsed_node != 0;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
100
void
101
clipboard_paste_region (CellRegion *region, Sheet *dest_sheet, int dest_col, int dest_row, int paste_flags)
Arturo Espinosa's avatar
Arturo Espinosa committed
102
{
103
	CellCopyList *l;
Arturo Espinosa's avatar
Arturo Espinosa committed
104
	int formulas = 0;
105 106 107 108 109 110 111
	
	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,
Arturo Espinosa's avatar
Arturo Espinosa committed
112
			    dest_col, dest_row,
113 114 115
			    dest_col + region->cols - 1,
			    dest_row + region->rows - 1);

Arturo Espinosa's avatar
Arturo Espinosa committed
116 117 118 119 120 121
	/* If no operations are defined, we clear the area */
	if (!(paste_flags & PASTE_OP_MASK))
		sheet_redraw_cell_region (dest_sheet,
					  dest_col, dest_row,
					  dest_col + region->cols - 1,
					  dest_row + region->rows - 1);
122
	
123 124 125 126
	/* Paste each element */
	for (l = region->list; l; l = l->next){
		CellCopy *c_copy = l->data;
		Cell *new_cell;
127
		int target_col, target_row;
128

129 130 131
		target_col = dest_col + c_copy->col_offset;
		target_row = dest_row + c_copy->row_offset;
		
132
		new_cell = cell_copy (c_copy->cell);
133

Arturo Espinosa's avatar
Arturo Espinosa committed
134
		formulas |= paste_cell (dest_sheet, new_cell, target_col, target_row, paste_flags);
135
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
136 137 138 139

	/* Trigger a recompute */
	if (formulas)
		workbook_recalc (dest_sheet->workbook);
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
}

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);
Arturo Espinosa's avatar
Arturo Espinosa committed
159
}
160

161