workbook.c 94 KB
Newer Older
1 2 3 4 5 6
/*
 * workbook.c:  Workbook management (toplevel windows)
 *
 * Author:
 *    Miguel de Icaza (miguel@gnu.org).
 *
7
 * (C) 1998, 1999, 2000 Miguel de Icaza
8
 * (C) 2000 Helix Code, Inc.
9
 */
10
#include <config.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
11
#include <gnome.h>
12
#include <gdk/gdkkeysyms.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
13
#include "gnumeric.h"
14
#include "application.h"
15
#include "eval.h"
16
#include "workbook.h"
17
#include "gnumeric-util.h"
Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
18
#include "sheet-object.h"
19
#include "dialogs.h"
20
#include "main.h"
21
#include "file.h"
22
#include "xml-io.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
23
#include "pixmaps.h"
24
#include "clipboard.h"
25
#include "parse-util.h"
26
#include "widgets/widget-editable-label.h"
27
#include "ranges.h"
Jody Goldberg's avatar
Jody Goldberg committed
28
#include "selection.h"
29
#include "print.h"
30
#include "expr-name.h"
31
#include "value.h"
32 33
#include "widgets/gnumeric-toolbar.h"
#include "workbook-cmd-format.h"
34
#include "workbook-format-toolbar.h"
35
#include "workbook-view.h"
36
#include "command-context-gui.h"
Jody Goldberg's avatar
Jody Goldberg committed
37
#include "commands.h"
38
#include "widgets/gtk-combo-text.h"
39
#include "wizard.h"
40
#include "gutils.h"
Jody Goldberg's avatar
Jody Goldberg committed
41
#include "rendered-value.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
42

43
#ifdef ENABLE_BONOBO
44
#include <bonobo/bonobo-persist-file.h>
45
#include "sheet-object-container.h"
46 47 48
#include "embeddable-grid.h"
#endif

49 50
#include <ctype.h>

51
#include "workbook-private.h"
52

53
/* Persistent attribute ids */
54 55 56 57 58
enum {
	ARG_VIEW_HSCROLLBAR = 1,
	ARG_VIEW_VSCROLLBAR,
	ARG_VIEW_TABS
};
59

60 61 62
/* The locations within the main table in the workbook */
#define WB_EA_LINE   0
#define WB_EA_SHEETS 1
Arturo Espinosa's avatar
Arturo Espinosa committed
63
#define WB_EA_STATUS 2
64 65 66

#define WB_COLS      1

67
static int workbook_count;
68

69 70
static GList *workbook_list = NULL;

71 72
static WORKBOOK_PARENT_CLASS *workbook_parent_class;

73 74
/* Workbook signals */
enum {
75
	SHEET_ENTERED,
76
	CELL_CHANGED,
77 78 79 80
	LAST_SIGNAL
};

static gint workbook_signals [LAST_SIGNAL] = {
81
	0, /* SHEET_ENTERED, CELL_CHANGED */
82 83
};

84 85
static void workbook_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);
static void workbook_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);
86
static void workbook_set_focus (GtkWindow *window, GtkWidget *focus, Workbook *wb);
87
static gboolean workbook_close_if_user_permits (Workbook *wb);
88

Arturo Espinosa's avatar
Arturo Espinosa committed
89
static void
90
new_cmd (void)
Arturo Espinosa's avatar
Arturo Espinosa committed
91
{
92 93 94 95 96 97
	Workbook *wb;
	wb = workbook_new_with_sheets (1);
	gtk_widget_show (wb->toplevel);
}

static void
98
file_open_cmd (GtkWidget *widget, Workbook *wb)
99
{
100 101
	char *fname = dialog_query_load_file (wb);
	Workbook *new_wb;
102

103 104 105
	if (!fname)
		return;

Jon K Hellan's avatar
Jon K Hellan committed
106
	new_wb = workbook_read (workbook_command_context_gui (wb), fname);
107 108

	if (new_wb != NULL) {
109
		gtk_widget_show (new_wb->toplevel);
110

111 112
		/*
		 * If the current workbook is empty and untouched remove it
Jody Goldberg's avatar
Jody Goldberg committed
113 114
		 * in favour of the new book
		 */
115 116
		if (workbook_is_pristine (wb))
			workbook_unref (wb);
117
	}
118
	g_free (fname);
Arturo Espinosa's avatar
Arturo Espinosa committed
119 120 121
}

static void
122 123 124 125
file_import_cmd (GtkWidget *widget, Workbook *wb)
{
	char *fname = dialog_query_load_file (wb);
	Workbook *new_wb;
126

127 128
	if (!fname)
		return;
129

Jon K Hellan's avatar
Jon K Hellan committed
130 131
	new_wb = workbook_import (workbook_command_context_gui (wb), wb,
				  fname);
132
	if (new_wb) {
133
		gtk_widget_show (new_wb->toplevel);
134

135 136
		if (workbook_is_pristine (wb))
			workbook_unref (wb);
137
	}
138
	g_free (fname);
139 140 141 142
}

static void
file_save_cmd (GtkWidget *widget, Workbook *wb)
Arturo Espinosa's avatar
Arturo Espinosa committed
143
{
Jon K Hellan's avatar
Jon K Hellan committed
144
	workbook_save (workbook_command_context_gui (wb), wb);
Arturo Espinosa's avatar
Arturo Espinosa committed
145 146 147
}

static void
148
file_save_as_cmd (GtkWidget *widget, Workbook *wb)
Arturo Espinosa's avatar
Arturo Espinosa committed
149
{
Jon K Hellan's avatar
Jon K Hellan committed
150
	workbook_save_as (workbook_command_context_gui (wb), wb);
Arturo Espinosa's avatar
Arturo Espinosa committed
151 152
}

Michael Meeks's avatar
Michael Meeks committed
153 154 155
static void
summary_cmd (GtkWidget *widget, Workbook *wb)
{
Michael Meeks's avatar
Michael Meeks committed
156
	dialog_summary_update (wb, wb->summary_info);
Michael Meeks's avatar
Michael Meeks committed
157 158
}

159 160 161 162 163 164
static void
autocorrect_cmd (GtkWidget *widget, Workbook *wb)
{
	dialog_autocorrect (wb);
}

165 166 167 168 169 170
static void
autosave_cmd (GtkWidget *widget, Workbook *wb)
{
	dialog_autosave (wb);
}

171 172 173 174 175 176
static void
advanced_filter_cmd (GtkWidget *widget, Workbook *wb)
{
	dialog_advanced_filter (wb);
}

177 178 179
static void
plugins_cmd (GtkWidget *widget, Workbook *wb)
{
180
	dialog_plugin_manager (wb);
181 182
}

183
#ifndef ENABLE_BONOBO
Michael Meeks's avatar
Michael Meeks committed
184
static void
185 186 187 188 189
about_cmd (GtkWidget *widget, Workbook *wb)
{
	dialog_about (wb);
}

190
#else
191
static void
192
create_embedded_component_cmd (GtkWidget *widget, Workbook *wb)
193
{
194
	Sheet *sheet = wb->current_sheet;
195 196

	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_COMPONENT);
197
}
198 199 200 201

static void
create_embedded_item_cmd (GtkWidget *widget, Workbook *wb)
{
202
	Sheet *sheet = wb->current_sheet;
203

204 205
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_CANVAS_ITEM);
}
206 207 208 209 210 211

static void
launch_graphics_wizard_cmd (GtkWidget *widget, Workbook *wb)
{
	graphics_wizard (wb);
}
212
#endif
213

214
#ifdef GNUMERIC_TEST_ACTIVE_OBJECT
215 216 217
static void
create_button_cmd (GtkWidget *widget, Workbook *wb)
{
218
	Sheet *sheet = wb->current_sheet;
219 220 221
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_BUTTON);
}

222 223 224
static void
create_checkbox_cmd (GtkWidget *widget, Workbook *wb)
{
225
	Sheet *sheet wb->current_sheet;
226 227 228 229
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_CHECKBOX);
}
#endif

230 231 232
static void
create_line_cmd (GtkWidget *widget, Workbook *wb)
{
233
	Sheet *sheet = wb->current_sheet;
234 235 236
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_LINE);
}

237 238 239
static void
create_arrow_cmd (GtkWidget *widget, Workbook *wb)
{
240
	Sheet *sheet = wb->current_sheet;
241 242 243
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_ARROW);
}

244 245 246
static void
create_rectangle_cmd (GtkWidget *widget, Workbook *wb)
{
247
	Sheet *sheet = wb->current_sheet;
248 249 250 251 252 253
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_BOX);
}

static void
create_ellipse_cmd (GtkWidget *widget, Workbook *wb)
{
254
	Sheet *sheet = wb->current_sheet;
255 256 257
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_OVAL);
}

258
static void
Jody Goldberg's avatar
Jody Goldberg committed
259
cb_sheet_destroy_contents (gpointer key, gpointer value, gpointer user_data)
260 261
{
	Sheet *sheet = value;
262
	sheet_destroy_contents (sheet);
263 264
}

Dom Lachowicz's avatar
Dom Lachowicz committed
265 266 267 268 269 270
static void
sheet_order_cmd (GtkWidget *widget, Workbook *wb)
{
        dialog_sheet_order (wb);
}

271 272 273 274 275 276
static void
workbook_do_destroy_private (Workbook *wb)
{
	g_free (wb->priv);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
277
static void
278 279
workbook_do_destroy (Workbook *wb)
{
280 281 282
	gtk_signal_disconnect_by_func (
		GTK_OBJECT (wb->toplevel),
		GTK_SIGNAL_FUNC (workbook_set_focus), wb);
283

284
	wb->priv->during_destruction = TRUE;
285
	workbook_autosave_cancel (wb);
Jon K Hellan's avatar
Jon K Hellan committed
286

Jon K Hellan's avatar
Jon K Hellan committed
287 288 289
	if (wb->file_format_level > FILE_FL_NEW)
		workbook_view_history_update (workbook_list,
					      wb->filename);
290

291 292 293 294
	/*
	 * Do all deletions that leave the workbook in a working
	 * order.
	 */
Arturo Espinosa's avatar
Arturo Espinosa committed
295

296
	summary_info_free (wb->summary_info);
297
	wb->summary_info = NULL;
298

Jody Goldberg's avatar
Jody Goldberg committed
299 300
	command_list_release (wb->undo_commands);
	command_list_release (wb->redo_commands);
301 302
	wb->undo_commands = NULL;
	wb->redo_commands = NULL;
Jody Goldberg's avatar
Jody Goldberg committed
303

304 305
	/* Release the clipboard if it is associated with this workbook */
	{
Jody Goldberg's avatar
Jody Goldberg committed
306
		Sheet *tmp_sheet;
307 308 309 310 311
		if ((tmp_sheet = application_clipboard_sheet_get ()) != NULL &&
		    tmp_sheet->workbook == wb)
			application_clipboard_clear ();
	}

312 313
	workbook_deps_destroy (wb);

314 315 316 317 318 319 320 321 322 323 324
	/*
	 * All formulas are going to be removed.  Unqueue them before removing
	 * the cells so that we need not search the lists.
	 */
	g_list_free (wb->formula_cell_list);
	wb->formula_cell_list = NULL;

	/* Just drop the eval queue.  */
	g_list_free (wb->eval_queue);
	wb->eval_queue = NULL;

325
	/* Erase all cells. */
Jody Goldberg's avatar
Jody Goldberg committed
326
	g_hash_table_foreach (wb->sheets, &cb_sheet_destroy_contents, NULL);
327

328
	if (wb->auto_expr_desc)
329
		string_unref (wb->auto_expr_desc);
Michael Meeks's avatar
Michael Meeks committed
330 331 332
	if (wb->auto_expr) {
		expr_tree_unref (wb->auto_expr);
		wb->auto_expr = NULL;
333
	}
334

335

336
	gtk_window_set_focus (GTK_WINDOW (wb->toplevel), NULL);
337 338 339 340 341
	/* Detach and destroy all sheets.  */
	{
		GList *sheets, *l;

		sheets = workbook_sheets (wb);
342
		for (l = sheets; l; l = l->next){
343 344
			Sheet *sheet = l->data;

345 346 347 348 349
			/*
			 * We need to put this test BEFORE we detach
			 * the sheet from the workbook.  Its ugly, but should
			 * be ok for debug code.
			 */
Michael Meeks's avatar
Michael Meeks committed
350 351
			if (gnumeric_debugging > 0)
				sheet_dump_dependencies (sheet);
352 353 354 355 356 357 358 359
			/*
			 * Make sure we alwayws keep the focus on an
			 * existing widget (otherwise the destruction
			 * code for wb->toplvel will try to focus a
			 * dead widget at the end of this routine)
			 */
			gtk_window_set_focus (GTK_WINDOW (wb->toplevel), NULL);

360
			workbook_detach_sheet (sheet->workbook, sheet, TRUE);
361 362

			gtk_window_set_focus (GTK_WINDOW (wb->toplevel), NULL);
363 364 365 366 367
		}
		g_list_free (sheets);
	}

	/* Remove ourselves from the list of workbooks.  */
368 369 370
	workbook_list = g_list_remove (workbook_list, wb);
	workbook_count--;

371 372 373 374 375 376 377 378
	/* Now do deletions that will put this workbook into a weird
	   state.  Careful here.  */

	g_hash_table_destroy (wb->sheets);

	if (wb->filename)
	       g_free (wb->filename);

Miguel de Icaza's avatar
Miguel de Icaza committed
379
	symbol_table_destroy (wb->symbol_names);
380

381
	expr_name_clean_workbook (wb);
382

Morten Welinder's avatar
Leak.  
Morten Welinder committed
383 384
	gtk_object_unref (GTK_OBJECT (wb->priv->gui_context));

385 386
	workbook_do_destroy_private (wb);

387 388
	if (!GTK_OBJECT_DESTROYED (wb->toplevel))
		gtk_object_destroy (GTK_OBJECT (wb->toplevel));
389

390
	if (initial_worbook_open_complete && workbook_count == 0) {
391
		application_history_write_config ();
392
		gtk_main_quit ();
393
	}
394 395
}

396
static void
397
workbook_destroy (GtkObject *wb_object)
Arturo Espinosa's avatar
Arturo Espinosa committed
398
{
399 400 401 402
	Workbook *wb = WORKBOOK (wb_object);

	workbook_do_destroy (wb);
	GTK_OBJECT_CLASS (workbook_parent_class)->destroy (wb_object);
403 404
}

Michael Meeks's avatar
Michael Meeks committed
405 406 407
static int
workbook_delete_event (GtkWidget *widget, GdkEvent *event, Workbook *wb)
{
408
	return workbook_close_if_user_permits (wb);
Michael Meeks's avatar
Michael Meeks committed
409 410
}

411
static void
412
cb_sheet_mark_dirty (gpointer key, gpointer value, gpointer user_data)
413 414
{
	Sheet *sheet = value;
415
	int dirty = GPOINTER_TO_INT (user_data);
416

417 418 419 420 421 422 423 424 425
	sheet_set_dirty (sheet, dirty);
}

void
workbook_set_dirty (Workbook *wb, gboolean is_dirty)
{
	g_return_if_fail (wb != NULL);

	g_hash_table_foreach (wb->sheets, cb_sheet_mark_dirty, GINT_TO_POINTER (is_dirty));
426 427
}

428
static void
429
cb_sheet_check_dirty (gpointer key, gpointer value, gpointer user_data)
430
{
431 432
	Sheet    *sheet = value;
	gboolean *dirty = user_data;
433

434
	if (*dirty)
Michael Meeks's avatar
Michael Meeks committed
435 436
		return;

437 438
	if (!sheet->modified)
		return;
439

440 441
	*dirty = TRUE;
}
442

443
gboolean
444 445
workbook_is_dirty (Workbook *wb)
{
446
	gboolean dirty = FALSE;
447

448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
	g_return_val_if_fail (wb != NULL, FALSE);

	g_hash_table_foreach (wb->sheets, cb_sheet_check_dirty,
			      &dirty);

	return dirty;
}

static void
cb_sheet_check_pristine (gpointer key, gpointer value, gpointer user_data)
{
	Sheet    *sheet = value;
	gboolean *pristine = user_data;

	if (!sheet_is_pristine (sheet))
		*pristine = FALSE;
}

/**
 * workbook_is_pristine:
468 469
 * @wb:
 *
470 471
 *   This checks to see if the workbook has ever been
 * used ( approximately )
472
 *
473 474 475 476 477 478 479 480 481 482 483 484 485
 * Return value: TRUE if we can discard this workbook.
 **/
gboolean
workbook_is_pristine (Workbook *wb)
{
	gboolean pristine = TRUE;

	g_return_val_if_fail (wb != NULL, FALSE);

	if (workbook_is_dirty (wb))
		return FALSE;

	if (wb->names || wb->formula_cell_list ||
Michael Meeks's avatar
Michael Meeks committed
486
#ifdef ENABLE_BONOBO
487
	    wb->workbook_views ||
Michael Meeks's avatar
Michael Meeks committed
488
#endif
Jon K Hellan's avatar
Jon K Hellan committed
489
	    wb->eval_queue || (wb->file_format_level > FILE_FL_NEW))
490 491 492 493 494 495 496
		return FALSE;

	/* Check if we seem to contain anything */
	g_hash_table_foreach (wb->sheets, cb_sheet_check_pristine,
			      &pristine);

	return pristine;
497 498
}

499 500 501 502 503 504 505 506
/**
 * workbook_close_if_user_permits : If the workbook is dirty the user is
 *  		prompted to see if they should exit.
 *
 * Returns : TRUE is the book remains open.
 *           FALSE if it is closed.
 */
static gboolean
507
workbook_close_if_user_permits (Workbook *wb)
508
{
509 510 511
	gboolean   can_close = TRUE;
	gboolean   done      = FALSE;
	int        iteration = 0;
512
	static int in_can_close;
513

514 515 516
	if (in_can_close)
		return FALSE;
	in_can_close = TRUE;
517

518 519 520
	/* If we were editing when the quit request came in save the edit. */
	workbook_finish_editing (wb, TRUE);

Michael Meeks's avatar
Michael Meeks committed
521 522
	while (workbook_is_dirty (wb) && !done) {

Jon K Hellan's avatar
Jon K Hellan committed
523
		GtkWidget *d, *l, *cancel_button;
524 525 526 527
		int button;
		char *s;

		iteration++;
528

529 530 531 532 533 534
		d = gnome_dialog_new (
			_("Warning"),
			GNOME_STOCK_BUTTON_YES,
			GNOME_STOCK_BUTTON_NO,
			GNOME_STOCK_BUTTON_CANCEL,
			NULL);
Jon K Hellan's avatar
Jon K Hellan committed
535 536
		cancel_button = g_list_last (GNOME_DIALOG (d)->buttons)->data;
		gtk_widget_grab_focus (cancel_button);
537
		gnome_dialog_set_parent (GNOME_DIALOG (d), GTK_WINDOW (wb->toplevel));
538

539 540 541 542 543 544
		if (wb->filename)
			s = g_strdup_printf (
				_("Workbook %s has unsaved changes, save them?"),
				g_basename (wb->filename));
		else
			s = g_strdup (_("Workbook has unsaved changes, save them?"));
545

546 547 548
		l = gtk_label_new (s);
		gtk_widget_show (l);
		g_free (s);
549

550
		gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (d)->vbox), l, TRUE, TRUE, 0);
551

552 553
		gtk_window_set_position (GTK_WINDOW (d), GTK_WIN_POS_MOUSE);
		button = gnome_dialog_run_and_close (GNOME_DIALOG (d));
554

555 556 557
		switch (button) {
			/* YES */
		case 0:
Jon K Hellan's avatar
Jon K Hellan committed
558
			done = workbook_save (workbook_command_context_gui (wb), wb);
559
			break;
560

561 562 563 564
			/* NO */
		case 1:
			can_close = TRUE;
			done      = TRUE;
565
			workbook_set_dirty (wb, FALSE);
566
			break;
567

568 569 570 571 572 573 574 575
			/* CANCEL */
		case -1:
		case 2:
			can_close = FALSE;
			done      = TRUE;
			break;
		}
	}
576

577
	in_can_close = FALSE;
578

579
	if (can_close) {
580
		workbook_unref (wb);
581 582 583
		return FALSE;
	} else
		return TRUE;
Arturo Espinosa's avatar
Arturo Espinosa committed
584 585
}

586 587 588
static void
close_cmd (GtkWidget *widget, Workbook *wb)
{
589
	(void) workbook_close_if_user_permits (wb);
590 591
}

592 593 594 595 596 597 598 599 600 601 602
static void
quit_cmd (void)
{
	GList *l, *n = NULL;

	/*
	 * Duplicate the list as the workbook_list is modified during
	 * workbook destruction
	 */
	for (l = workbook_list; l; l = l->next)
		n = g_list_prepend (n, l->data);
Morten Welinder's avatar
Morten Welinder committed
603

604 605
	for (l = n; l; l = l->next){
		Workbook *wb = l->data;
606
		(void) workbook_close_if_user_permits (wb);
607 608 609
	}

	g_list_free (n);
610 611
}

612 613 614
static gboolean
cb_editline_focus_in (GtkWidget *w, GdkEventFocus *event, Workbook *wb)
{
615 616
	if (!wb->editing)
		workbook_start_editing_at_cursor (wb, FALSE, TRUE);
617 618 619
	return TRUE;
}

620 621 622
static void
accept_input (GtkWidget *IGNORED, Workbook *wb)
{
Jody Goldberg's avatar
Jody Goldberg committed
623
	workbook_finish_editing (wb, TRUE);
624 625 626 627 628
}

static void
cancel_input (GtkWidget *IGNORED, Workbook *wb)
{
Jody Goldberg's avatar
Jody Goldberg committed
629
	workbook_finish_editing (wb, FALSE);
630 631
}

632 633 634
static void
undo_cmd (GtkWidget *widget, Workbook *wb)
{
635
	workbook_finish_editing (wb, FALSE);
Jody Goldberg's avatar
Jody Goldberg committed
636
	command_undo (workbook_command_context_gui (wb), wb);
637 638 639 640 641
}

static void
redo_cmd (GtkWidget *widget, Workbook *wb)
{
642
	workbook_finish_editing (wb, FALSE);
Jody Goldberg's avatar
Jody Goldberg committed
643
	command_redo (workbook_command_context_gui (wb), wb);
644 645
}

646 647 648
static void
copy_cmd (GtkWidget *widget, Workbook *wb)
{
649
	Sheet *sheet = wb->current_sheet;
650
	sheet_selection_copy (workbook_command_context_gui (wb), sheet);
651 652 653 654 655
}

static void
cut_cmd (GtkWidget *widget, Workbook *wb)
{
656
	Sheet *sheet = wb->current_sheet;
Morten Welinder's avatar
Morten Welinder committed
657

Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
658
	if (sheet->mode == SHEET_MODE_SHEET)
659
		sheet_selection_cut (workbook_command_context_gui (wb), sheet);
Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
660 661
	else {
		if (sheet->current_object){
662 663
			gtk_object_unref (GTK_OBJECT (sheet->current_object));
			sheet->current_object = NULL;
Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
664 665 666 667
			sheet_set_mode_type (sheet, SHEET_MODE_SHEET);
		} else
			printf ("no object selected\n");
	}
668 669
}

670 671 672
static void
paste_cmd (GtkWidget *widget, Workbook *wb)
{
673
	Sheet *sheet = wb->current_sheet;
674

675
	sheet_selection_paste (workbook_command_context_gui (wb), sheet,
676
			       sheet->cursor.edit_pos.col, sheet->cursor.edit_pos.row,
677 678 679
			       PASTE_DEFAULT, GDK_CURRENT_TIME);
}

680 681 682
static void
paste_special_cmd (GtkWidget *widget, Workbook *wb)
{
683
	Sheet *sheet = wb->current_sheet;
684 685
	int flags;

686 687 688
	/* These menu items should be insensitive when there is nothing to paste */
	g_return_if_fail (!application_clipboard_is_empty ());

689
	flags = dialog_paste_special (wb);
690
	if (flags != 0)
691
		sheet_selection_paste (workbook_command_context_gui (wb), sheet,
692
				       sheet->cursor.edit_pos.col, sheet->cursor.edit_pos.row,
693
				       flags, GDK_CURRENT_TIME);
Morten Welinder's avatar
Morten Welinder committed
694

695 696
}

697 698 699
static void
delete_cells_cmd (GtkWidget *widget, Workbook *wb)
{
700
	dialog_delete_cells (wb, wb->current_sheet);
701
}
702

703
static void sheet_action_delete_sheet (GtkWidget *ignored, Sheet *current_sheet);
704 705 706 707

static void
delete_sheet_cmd (GtkWidget *widget, Workbook *wb)
{
708
	sheet_action_delete_sheet (widget, wb->current_sheet);
709 710
}

711 712 713
static void
select_all_cmd (GtkWidget *widget, Workbook *wb)
{
714
	Sheet *sheet = wb->current_sheet;
715 716 717 718 719

	sheet_select_all (sheet);
	sheet_redraw_all (sheet);
}

720
static void
721
goto_cell_cmd (GtkWidget *unused, Workbook *wb)
722 723 724 725
{
	dialog_goto_cell (wb);
}

726
static void
727
define_cell_cmd (GtkWidget *unused, Workbook *wb)
728 729 730 731
{
	dialog_define_names (wb);
}

732
static void
733
insert_sheet_cmd (GtkWidget *unused, Workbook *wb)
734 735 736 737
{
	Sheet *sheet;
	char *name;

738
	name = workbook_sheet_get_free_name (wb, _("Sheet"), TRUE);
739 740
	sheet = sheet_new (wb, name);
	g_free (name);
Morten Welinder's avatar
Morten Welinder committed
741

742
	workbook_attach_sheet (wb, sheet);
Jody Goldberg's avatar
Jody Goldberg committed
743
	sheet_set_dirty (sheet, TRUE);
744 745
}

Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
746
static void
747
insert_cells_cmd (GtkWidget *unused, Workbook *wb)
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
748
{
749
	Sheet *sheet = wb->current_sheet;
750
	dialog_insert_cells (wb, sheet);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
751 752 753
}

static void
754
insert_cols_cmd (GtkWidget *unused, Workbook *wb)
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
755
{
756 757
	SheetSelection *ss;
	int cols;
758
	Sheet *sheet = wb->current_sheet;
Morten Welinder's avatar
Morten Welinder committed
759

760
	/* TODO : No need to check simplicty.  XL applies for each
761
	 * non-discrete selected region, (use selection_apply) */
762
	if (!selection_is_simple (workbook_command_context_gui (wb), sheet, _("Insert cols")))
763
		return;
Morten Welinder's avatar
Morten Welinder committed
764

765
	ss = sheet->selections->data;
766

767 768 769 770 771
	/* TODO : Have we have selected rows rather than columns
	 * This menu item should be disabled when a full row is selected
	 *
	 * at minimum a warning if things are about to be cleared ?
	 */
772
	cols = ss->user.end.col - ss->user.start.col + 1;
Jody Goldberg's avatar
Jody Goldberg committed
773 774
	cmd_insert_cols (workbook_command_context_gui (wb), sheet,
			 ss->user.start.col, cols);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
775 776 777
}

static void
778
insert_rows_cmd (GtkWidget *unused, Workbook *wb)
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
779
{
780 781
	SheetSelection *ss;
	int rows;
782
	Sheet *sheet = wb->current_sheet;
Morten Welinder's avatar
Morten Welinder committed
783

784
	/* TODO : No need to check simplicty.  XL applies for each
785
	 * non-discrete selected region, (use selection_apply) */
786
	if (!selection_is_simple (workbook_command_context_gui (wb), sheet, _("Insert rows")))
787 788 789
		return;

	ss = sheet->selections->data;
790

791 792 793 794 795
	/* TODO : Have we have selected columns rather than rows
	 * This menu item should be disabled when a full column is selected
	 *
	 * at minimum a warning if things are about to be cleared ?
	 */
796
	rows = ss->user.end.row - ss->user.start.row + 1;
Jody Goldberg's avatar
Jody Goldberg committed
797 798
	cmd_insert_rows (workbook_command_context_gui (wb), sheet,
			 ss->user.start.row, rows);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
799 800
}

Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
801 802 803
static void
clear_all_cmd (GtkWidget *widget, Workbook *wb)
{
804
	cmd_clear_selection (workbook_command_context_gui (wb),
805 806
			     wb->current_sheet,
			     CLEAR_VALUES | CLEAR_FORMATS | CLEAR_COMMENTS);
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
807 808 809 810 811
}

static void
clear_formats_cmd (GtkWidget *widget, Workbook *wb)
{
812
	cmd_clear_selection (workbook_command_context_gui (wb),
813 814
			     wb->current_sheet,
			     CLEAR_FORMATS);
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
815 816
}

817 818 819
static void
clear_comments_cmd (GtkWidget *widget, Workbook *wb)
{
820
	cmd_clear_selection (workbook_command_context_gui (wb),
821 822
			     wb->current_sheet,
			     CLEAR_COMMENTS);
823 824
}

Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
825 826 827
static void
clear_content_cmd (GtkWidget *widget, Workbook *wb)
{
828
	cmd_clear_selection (workbook_command_context_gui (wb),
829 830
			     wb->current_sheet,
			     CLEAR_VALUES);
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
831 832 833 834 835
}

static void
zoom_cmd (GtkWidget *widget, Workbook *wb)
{
836
	Sheet *sheet = wb->current_sheet;
837
	dialog_zoom (wb, sheet);
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
838 839
}

840 841 842
static void
cb_cell_rerender (gpointer cell, gpointer data)
{
Jody Goldberg's avatar
Jody Goldberg committed
843
        cell_render_value (cell);
844
        sheet_redraw_cell (cell);
845 846
}

847 848 849
/***********************************************************************/
/* Sheet preferences */

850
static void
851
cb_sheet_pref_display_formulas (GtkWidget *widget, Workbook *wb)
852
{
853
	Sheet *sheet = wb->current_sheet;
854
	sheet->display_formulas = !sheet->display_formulas;
Jody Goldberg's avatar
Jody Goldberg committed
855 856 857
	g_list_foreach (wb->formula_cell_list, &cb_cell_rerender, NULL);
}
static void
858 859
cb_sheet_pref_hide_zeros (GtkWidget *widget, Workbook *wb)
{
860
	Sheet *sheet = wb->current_sheet;
861 862 863 864 865
	sheet->display_zero = ! sheet->display_zero;
	sheet_redraw_all (sheet);
}
static void
cb_sheet_pref_hide_grid_lines (GtkWidget *widget, Workbook *wb)
Jody Goldberg's avatar
Jody Goldberg committed
866
{
867
	Sheet *sheet = wb->current_sheet;
Jody Goldberg's avatar
Jody Goldberg committed
868
	sheet->show_grid = !sheet->show_grid;
869 870 871 872 873
	sheet_redraw_all (sheet);
}
static void
cb_sheet_pref_hide_col_header (GtkWidget *widget, Workbook *wb)
{
874
	Sheet *sheet = wb->current_sheet;
875 876 877 878 879 880
	sheet->show_col_header = ! sheet->show_col_header;
	sheet_adjust_preferences (sheet);
}
static void
cb_sheet_pref_hide_row_header (GtkWidget *widget, Workbook *wb)
{
881
	Sheet *sheet = wb->current_sheet;
882 883
	sheet->show_row_header = ! sheet->show_row_header;
	sheet_adjust_preferences (sheet);
884 885
}

886
static void