workbook.c 74.9 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 Miguel de Icaza
8
 */
9
#include <config.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
10
#include <gnome.h>
11
#include <gdk/gdkkeysyms.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
12
#include "gnumeric.h"
13
#include "application.h"
14
#include "eval.h"
15
#include "workbook.h"
16
#include "gnumeric-util.h"
Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
17
#include "sheet-object.h"
18
#include "dialogs.h"
19
#include "main.h"
20
#include "file.h"
21
#include "xml-io.h"
22
#include "plugin.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
23
#include "pixmaps.h"
24 25
#include "clipboard.h"
#include "utils.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 31
#include "widgets/gnumeric-toolbar.h"
#include "workbook-cmd-format.h"
32
#include "workbook-format-toolbar.h"
33
#include "workbook-view.h"
34
#include "command-context-gui.h"
Jody Goldberg's avatar
Jody Goldberg committed
35
#include "commands.h"
36
#include "widgets/gtk-combo-text.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
37

38
#ifdef ENABLE_BONOBO
39
#include <bonobo/bonobo-persist-file.h>
40
#include "sheet-object-container.h"
41 42 43
#include "embeddable-grid.h"
#endif

44 45
#include <ctype.h>

46
#include "workbook-private.h"
47

48 49 50
/* 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
51
#define WB_EA_STATUS 2
52 53 54

#define WB_COLS      1

55
static int workbook_count;
56

57 58
static GList *workbook_list = NULL;

59 60
static WORKBOOK_PARENT_CLASS *workbook_parent_class;

61 62 63 64 65 66 67 68 69 70
/* Workbook signals */
enum {
	SHEET_CHANGED,
	LAST_SIGNAL
};

static gint workbook_signals [LAST_SIGNAL] = {
	0, /* SHEET_CHANGED */
};

71
static void workbook_set_focus (GtkWindow *window, GtkWidget *focus, Workbook *wb);
72
static int  workbook_can_close (Workbook *wb);
73

Arturo Espinosa's avatar
Arturo Espinosa committed
74
static void
75
new_cmd (void)
Arturo Espinosa's avatar
Arturo Espinosa committed
76
{
77 78 79 80 81 82
	Workbook *wb;
	wb = workbook_new_with_sheets (1);
	gtk_widget_show (wb->toplevel);
}

static void
83
file_open_cmd (GtkWidget *widget, Workbook *wb)
84
{
85 86
	char *fname = dialog_query_load_file (wb);
	Workbook *new_wb;
87

88 89 90
	if (!fname)
		return;

Jon K Hellan's avatar
Jon K Hellan committed
91
	new_wb = workbook_read (workbook_command_context_gui (wb), fname);
92 93

	if (new_wb != NULL) {
94
		gtk_widget_show (new_wb->toplevel);
95

96
		if (workbook_is_pristine (wb)) {
97
#ifdef ENABLE_BONOBO
98
			bonobo_object_unref (BONOBO_OBJECT (wb));
99
#else
100
			gtk_object_unref (GTK_OBJECT (wb));
101
#endif
102
		}
103
	}
104
	g_free (fname);
Arturo Espinosa's avatar
Arturo Espinosa committed
105 106 107
}

static void
108 109 110 111
file_import_cmd (GtkWidget *widget, Workbook *wb)
{
	char *fname = dialog_query_load_file (wb);
	Workbook *new_wb;
112
	
113 114
	if (!fname)
		return;
115
	
Jon K Hellan's avatar
Jon K Hellan committed
116 117
	new_wb = workbook_import (workbook_command_context_gui (wb), wb,
				  fname);
118
	if (new_wb) {
119
		gtk_widget_show (new_wb->toplevel);
120 121

		if (workbook_is_pristine (wb)) {
122
#ifdef ENABLE_BONOBO
123
			bonobo_object_unref (BONOBO_OBJECT (wb));
124
#else
125
			gtk_object_unref (GTK_OBJECT (wb));
126
#endif
127
		}
128
	}
129
	g_free (fname);
130 131 132 133
}

static void
file_save_cmd (GtkWidget *widget, Workbook *wb)
Arturo Espinosa's avatar
Arturo Espinosa committed
134
{
Jon K Hellan's avatar
Jon K Hellan committed
135
	workbook_save (workbook_command_context_gui (wb), wb);
Arturo Espinosa's avatar
Arturo Espinosa committed
136 137 138
}

static void
139
file_save_as_cmd (GtkWidget *widget, Workbook *wb)
Arturo Espinosa's avatar
Arturo Espinosa committed
140
{
Jon K Hellan's avatar
Jon K Hellan committed
141
	workbook_save_as (workbook_command_context_gui (wb), wb);
Arturo Espinosa's avatar
Arturo Espinosa committed
142 143
}

Michael Meeks's avatar
Michael Meeks committed
144 145 146
static void
summary_cmd (GtkWidget *widget, Workbook *wb)
{
Michael Meeks's avatar
Michael Meeks committed
147
	dialog_summary_update (wb, wb->summary_info);
Michael Meeks's avatar
Michael Meeks committed
148 149
}

150 151 152 153 154 155
static void
autocorrect_cmd (GtkWidget *widget, Workbook *wb)
{
	dialog_autocorrect (wb);
}

156 157 158 159 160 161
static void
autosave_cmd (GtkWidget *widget, Workbook *wb)
{
	dialog_autosave (wb);
}

162 163 164 165 166 167
static void
advanced_filter_cmd (GtkWidget *widget, Workbook *wb)
{
	dialog_advanced_filter (wb);
}

168 169 170
static void
plugins_cmd (GtkWidget *widget, Workbook *wb)
{
171
	GtkWidget *pm = plugin_manager_new (wb);
Arturo Espinosa's avatar
Arturo Espinosa committed
172
	gtk_widget_show (pm);
173 174
}

175
#ifndef ENABLE_BONOBO
Michael Meeks's avatar
Michael Meeks committed
176
static void
177 178 179 180 181
about_cmd (GtkWidget *widget, Workbook *wb)
{
	dialog_about (wb);
}

182
#else
183 184 185
static void
create_graphic_cmd (GtkWidget *widget, Workbook *wb)
{
186
	Sheet *sheet = wb->current_sheet;
187
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_GRAPHIC);
188
}
189 190 191 192

static void
create_embedded_item_cmd (GtkWidget *widget, Workbook *wb)
{
193
	Sheet *sheet = wb->current_sheet;
194 195
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_CANVAS_ITEM);
}
196
#endif
197

198
#ifdef GNUMERIC_TEST_ACTIVE_OBJECT
199 200 201
static void
create_button_cmd (GtkWidget *widget, Workbook *wb)
{
202
	Sheet *sheet = wb->current_sheet;
203 204 205
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_BUTTON);
}

206 207 208
static void
create_checkbox_cmd (GtkWidget *widget, Workbook *wb)
{
209
	Sheet *sheet wb->current_sheet;
210 211 212 213
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_CHECKBOX);
}
#endif

214 215 216
static void
create_line_cmd (GtkWidget *widget, Workbook *wb)
{
217
	Sheet *sheet = wb->current_sheet;
218 219 220
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_LINE);
}

221 222 223
static void
create_arrow_cmd (GtkWidget *widget, Workbook *wb)
{
224
	Sheet *sheet = wb->current_sheet;
225 226 227
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_ARROW);
}

228 229 230
static void
create_rectangle_cmd (GtkWidget *widget, Workbook *wb)
{
231
	Sheet *sheet = wb->current_sheet;
232 233 234 235 236 237
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_BOX);
}

static void
create_ellipse_cmd (GtkWidget *widget, Workbook *wb)
{
238
	Sheet *sheet = wb->current_sheet;
239 240 241
	sheet_set_mode_type (sheet, SHEET_MODE_CREATE_OVAL);
}

242
static void
Jody Goldberg's avatar
Jody Goldberg committed
243
cb_sheet_destroy_contents (gpointer key, gpointer value, gpointer user_data)
244 245
{
	Sheet *sheet = value;
246
	sheet_destroy_contents (sheet);
247 248
}

249 250 251 252 253 254
static void
workbook_do_destroy_private (Workbook *wb)
{
	g_free (wb->priv);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
255
static void
256 257
workbook_do_destroy (Workbook *wb)
{
258 259 260
	gtk_signal_disconnect_by_func (
		GTK_OBJECT (wb->toplevel),
		GTK_SIGNAL_FUNC (workbook_set_focus), wb);
261

262
	workbook_autosave_cancel (wb);
Jon K Hellan's avatar
Jon K Hellan committed
263

264 265 266 267
	/*
	 * Do all deletions that leave the workbook in a working
	 * order.
	 */
Arturo Espinosa's avatar
Arturo Espinosa committed
268

269
	summary_info_free (wb->summary_info);
270
	wb->summary_info = NULL;
271

Jody Goldberg's avatar
Jody Goldberg committed
272 273 274
	command_list_release (wb->undo_commands);
	command_list_release (wb->redo_commands);

275 276
	/* Release the clipboard if it is associated with this workbook */
	{
Jody Goldberg's avatar
Jody Goldberg committed
277
		Sheet *tmp_sheet;
278 279 280 281 282
		if ((tmp_sheet = application_clipboard_sheet_get ()) != NULL &&
		    tmp_sheet->workbook == wb)
			application_clipboard_clear ();
	}

Jody Goldberg's avatar
Jody Goldberg committed
283 284 285 286 287
	/* Erase all cells.  This does NOT remove links between sheets
	 * but we don't care beacuse the other sheets are going to be
	 * deleted too.
	 */
	g_hash_table_foreach (wb->sheets, &cb_sheet_destroy_contents, NULL);
288

289
	if (wb->auto_expr_desc)
290
		string_unref (wb->auto_expr_desc);
Michael Meeks's avatar
Michael Meeks committed
291 292 293
	if (wb->auto_expr) {
		expr_tree_unref (wb->auto_expr);
		wb->auto_expr = NULL;
294
	}
295

296 297 298 299 300 301 302 303 304 305 306 307
	/* Problems with insert/delete column/row caused formula_cell_list
	   to be messed up.  */
	if (wb->formula_cell_list) {
		fprintf (stderr, "Reminder: FIXME in workbook_do_destroy\n");
		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;

308
	gtk_window_set_focus (GTK_WINDOW (wb->toplevel), NULL);
309 310 311 312 313
	/* Detach and destroy all sheets.  */
	{
		GList *sheets, *l;

		sheets = workbook_sheets (wb);
314
		for (l = sheets; l; l = l->next){
315 316
			Sheet *sheet = l->data;

317 318 319 320 321
			/*
			 * 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
322 323
			if (gnumeric_debugging > 0)
				sheet_dump_dependencies (sheet);
324 325 326 327 328 329 330 331
			/*
			 * 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);

332
			workbook_detach_sheet (sheet->workbook, sheet, TRUE);
333 334

			gtk_window_set_focus (GTK_WINDOW (wb->toplevel), NULL);
335 336 337 338 339
		}
		g_list_free (sheets);
	}

	/* Remove ourselves from the list of workbooks.  */
340 341 342
	workbook_list = g_list_remove (workbook_list, wb);
	workbook_count--;

343 344 345 346 347 348 349 350
	/* 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
351
	symbol_table_destroy (wb->symbol_names);
352

353
	expr_name_clean_workbook (wb);
354

355 356
	gtk_object_destroy (GTK_OBJECT (wb->priv->gui_context));
	
357 358
	workbook_do_destroy_private (wb);

359 360 361
	if (!GTK_OBJECT_DESTROYED (wb->toplevel))
		gtk_object_destroy (GTK_OBJECT (wb->toplevel));
	
362 363 364 365
	if (workbook_count == 0)
		gtk_main_quit ();
}

366 367
static void
workbook_destroy (GtkObject *wb_object) 
Arturo Espinosa's avatar
Arturo Espinosa committed
368
{
369 370 371 372
	Workbook *wb = WORKBOOK (wb_object);

	workbook_do_destroy (wb);
	GTK_OBJECT_CLASS (workbook_parent_class)->destroy (wb_object);
373 374
}

Michael Meeks's avatar
Michael Meeks committed
375 376 377
static int
workbook_delete_event (GtkWidget *widget, GdkEvent *event, Workbook *wb)
{
Michael Meeks's avatar
Michael Meeks committed
378
	if (workbook_can_close (wb)) {
Michael Meeks's avatar
Michael Meeks committed
379
#ifdef ENABLE_BONOBO
380
		if (wb->workbook_views) {
Miguel de Icaza's avatar
Miguel de Icaza committed
381 382 383
			gtk_widget_hide (GTK_WIDGET (wb->toplevel));
			return FALSE;
		}
384
		bonobo_object_unref (BONOBO_OBJECT (wb));
Michael Meeks's avatar
Michael Meeks committed
385
#else
Michael Meeks's avatar
Michael Meeks committed
386
		gtk_object_unref   (GTK_OBJECT   (wb));
Michael Meeks's avatar
Michael Meeks committed
387 388 389 390 391 392
#endif
		return FALSE;
	} else
		return TRUE;
}

393
static void
394
cb_sheet_mark_dirty (gpointer key, gpointer value, gpointer user_data)
395 396
{
	Sheet *sheet = value;
397
	int dirty = GPOINTER_TO_INT (user_data);
398

399 400 401 402 403 404 405 406 407
	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));
408 409 410 411 412 413 414
}

void
workbook_mark_clean (Workbook *wb)
{
	g_return_if_fail (wb != NULL);

415
	g_hash_table_foreach (wb->sheets, cb_sheet_mark_dirty, GINT_TO_POINTER (0));
416 417
}

418
static void
419
cb_sheet_check_dirty (gpointer key, gpointer value, gpointer user_data)
420
{
421 422
	Sheet    *sheet = value;
	gboolean *dirty = user_data;
423

424
	if (*dirty)
Michael Meeks's avatar
Michael Meeks committed
425 426
		return;

427 428 429
	if (!sheet->modified)
		return;
/*	{
Michael Meeks's avatar
Michael Meeks committed
430 431
		GtkEntry   *entry;
		const char *txt;
Michael Meeks's avatar
Michael Meeks committed
432 433
		Cell       *cell;

434
		if (sheet != sheet->workbook->current_sheet)
Michael Meeks's avatar
Michael Meeks committed
435 436 437 438
			return;

		entry = GTK_ENTRY (sheet->workbook->ea_input);
		txt   = gtk_entry_get_text (entry);
Michael Meeks's avatar
Michael Meeks committed
439 440 441 442 443 444 445 446 447 448 449 450
		cell = sheet_cell_get (sheet, sheet->cursor_col,
				       sheet->cursor_row);
		if (!cell) {
			if (!strlen (txt))
				return;
		} else {
			char *cell_txt = cell_get_text (cell);
			gboolean same  = !strcmp (txt, cell_txt);
			g_free (cell_txt);
			if (same)
				return;
		}
451 452
		return;
		}*/
453

454 455
	*dirty = TRUE;
}
456

457
gboolean
458 459
workbook_is_dirty (Workbook *wb)
{
460
	gboolean dirty = FALSE;
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
	
	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:
 * @wb: 
 * 
 *   This checks to see if the workbook has ever been
 * used ( approximately )
 * 
 * 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
500
#ifdef ENABLE_BONOBO
501
	    wb->workbook_views ||
Michael Meeks's avatar
Michael Meeks committed
502 503
#endif
	    wb->eval_queue || !wb->needs_name)
504 505 506 507 508 509 510
		return FALSE;

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

	return pristine;
511 512 513 514 515
}

static int
workbook_can_close (Workbook *wb)
{
516 517 518
	gboolean   can_close = TRUE;
	gboolean   done      = FALSE;
	int        iteration = 0;
519
	static int in_can_close;
520

521 522 523 524
	if (in_can_close)
		return FALSE;
	
	in_can_close = TRUE;
Michael Meeks's avatar
Michael Meeks committed
525 526
	while (workbook_is_dirty (wb) && !done) {

Jon K Hellan's avatar
Jon K Hellan committed
527
		GtkWidget *d, *l, *cancel_button;
528 529 530 531 532 533 534 535 536 537 538
		int button;
		char *s;

		iteration++;
		
		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
539 540
		cancel_button = g_list_last (GNOME_DIALOG (d)->buttons)->data;
		gtk_widget_grab_focus (cancel_button);
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
		gnome_dialog_set_parent (GNOME_DIALOG (d), GTK_WINDOW (wb->toplevel));
		
		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?"));
		
		l = gtk_label_new (s);
		gtk_widget_show (l);
		g_free (s);
		
		gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (d)->vbox), l, TRUE, TRUE, 0);
		
		gtk_window_set_position (GTK_WINDOW (d), GTK_WIN_POS_MOUSE);
		button = gnome_dialog_run_and_close (GNOME_DIALOG (d));
		
		switch (button) {
			/* YES */
		case 0:
Jon K Hellan's avatar
Jon K Hellan committed
562
			done = workbook_save (workbook_command_context_gui (wb), wb);
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
			break;
			
			/* NO */
		case 1:
			can_close = TRUE;
			done      = TRUE;
			workbook_mark_clean (wb);
			break;
			
			/* CANCEL */
		case -1:
		case 2:
			can_close = FALSE;
			done      = TRUE;
			break;
		}
	}
	
581 582
	in_can_close = FALSE;
	
583
	return can_close;
Arturo Espinosa's avatar
Arturo Espinosa committed
584 585
}

586 587 588
static void
close_cmd (GtkWidget *widget, Workbook *wb)
{
589 590
	if (workbook_can_close (wb)){
#ifdef ENABLE_BONOBO
591
		bonobo_object_unref (BONOBO_OBJECT (wb));
592 593 594 595
#else
		gtk_object_unref (GTK_OBJECT (wb));
#endif
	}
596 597
}

598 599 600 601 602 603 604 605 606
static void
quit_cmd (void)
{
	GList *l, *n = NULL;

	/*
	 * Duplicate the list as the workbook_list is modified during
	 * workbook destruction
	 */
Morten Welinder's avatar
Morten Welinder committed
607

608 609
	for (l = workbook_list; l; l = l->next)
		n = g_list_prepend (n, l->data);
Morten Welinder's avatar
Morten Welinder committed
610

611 612 613
	for (l = n; l; l = l->next){
		Workbook *wb = l->data;

614 615
		if (workbook_can_close (wb)){
#ifdef ENABLE_BONOBO
616
			bonobo_object_unref (BONOBO_OBJECT (wb));
617 618 619 620
#else
			gtk_object_unref (GTK_OBJECT (wb));
#endif
		}
621 622 623
	}

	g_list_free (n);
624 625
}

626 627 628 629
static void
accept_input (GtkWidget *IGNORED, Workbook *wb)
{
	Sheet *sheet = wb->current_sheet;
630 631 632

	/* Force sheet into edit mode */
	sheet->editing = TRUE;
633 634 635 636 637 638 639 640 641 642 643 644
	sheet_accept_pending_input (sheet);
	workbook_focus_current_sheet (wb);
}

static void
cancel_input (GtkWidget *IGNORED, Workbook *wb)
{
	Sheet *sheet = wb->current_sheet;
	sheet_cancel_pending_input (sheet);
	workbook_focus_current_sheet (wb);
}

645 646 647
static void
undo_cmd (GtkWidget *widget, Workbook *wb)
{
648
	cancel_input (NULL, wb);
Jody Goldberg's avatar
Jody Goldberg committed
649
	command_undo (workbook_command_context_gui (wb), wb);
650 651 652 653 654
}

static void
redo_cmd (GtkWidget *widget, Workbook *wb)
{
655
	cancel_input (NULL, wb);
Jody Goldberg's avatar
Jody Goldberg committed
656
	command_redo (workbook_command_context_gui (wb), wb);
657 658
}

659 660 661
static void
copy_cmd (GtkWidget *widget, Workbook *wb)
{
662
	Sheet *sheet = wb->current_sheet;
663
	sheet_selection_copy (workbook_command_context_gui (wb), sheet);
664 665 666 667 668
}

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

Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
671
	if (sheet->mode == SHEET_MODE_SHEET)
672
		sheet_selection_cut (workbook_command_context_gui (wb), sheet);
Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
673 674
	else {
		if (sheet->current_object){
675 676
			gtk_object_unref (GTK_OBJECT (sheet->current_object));
			sheet->current_object = NULL;
Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
677 678 679 680
			sheet_set_mode_type (sheet, SHEET_MODE_SHEET);
		} else
			printf ("no object selected\n");
	}
681 682
}

683 684 685
static void
paste_cmd (GtkWidget *widget, Workbook *wb)
{
686
	Sheet *sheet = wb->current_sheet;
687

688
	sheet_selection_paste (workbook_command_context_gui (wb), sheet,
689
			       sheet->cursor_col, sheet->cursor_row,
690 691 692
			       PASTE_DEFAULT, GDK_CURRENT_TIME);
}

693 694 695
static void
paste_special_cmd (GtkWidget *widget, Workbook *wb)
{
696
	Sheet *sheet = wb->current_sheet;
697 698
	int flags;

699 700 701
	/* These menu items should be insensitive when there is nothing to paste */
	g_return_if_fail (!application_clipboard_is_empty ());

702
	flags = dialog_paste_special (wb);
703
	if (flags != 0)
704
		sheet_selection_paste (workbook_command_context_gui (wb), sheet,
705
				       sheet->cursor_col, sheet->cursor_row,
706
				       flags, GDK_CURRENT_TIME);
Morten Welinder's avatar
Morten Welinder committed
707

708 709
}

710 711 712
static void
delete_cells_cmd (GtkWidget *widget, Workbook *wb)
{
713
	dialog_delete_cells (wb, wb->current_sheet);
714
}
715

716 717 718 719 720 721
static void
sheet_action_delete_sheet (GtkWidget *ignored, Sheet *current_sheet);

static void
delete_sheet_cmd (GtkWidget *widget, Workbook *wb)
{
722
	sheet_action_delete_sheet (widget, wb->current_sheet);
723 724
}

725 726 727
static void
select_all_cmd (GtkWidget *widget, Workbook *wb)
{
728
	Sheet *sheet = wb->current_sheet;
729 730 731 732 733

	sheet_select_all (sheet);
	sheet_redraw_all (sheet);
}

734
static void
735
goto_cell_cmd (GtkWidget *unused, Workbook *wb)
736 737 738 739
{
	dialog_goto_cell (wb);
}

740
static void
741
define_cell_cmd (GtkWidget *unused, Workbook *wb)
742 743 744 745
{
	dialog_define_names (wb);
}

746
static void
747
insert_sheet_cmd (GtkWidget *unused, Workbook *wb)
748 749 750 751 752 753 754
{
	Sheet *sheet;
	char *name;

	name = workbook_sheet_get_free_name (wb);
	sheet = sheet_new (wb, name);
	g_free (name);
Morten Welinder's avatar
Morten Welinder committed
755

756 757 758
	workbook_attach_sheet (wb, sheet);
}

Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
759
static void
760
insert_cells_cmd (GtkWidget *unused, Workbook *wb)
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
761
{
762
	Sheet *sheet = wb->current_sheet;
763
	dialog_insert_cells (wb, sheet);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
764 765 766
}

static void
767
insert_cols_cmd (GtkWidget *unused, Workbook *wb)
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
768
{
769 770
	SheetSelection *ss;
	int cols;
771
	Sheet *sheet = wb->current_sheet;
Morten Welinder's avatar
Morten Welinder committed
772

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

778
	ss = sheet->selections->data;
779

780 781 782 783 784
	/* 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 ?
	 */
785
	cols = ss->user.end.col - ss->user.start.col + 1;
Jody Goldberg's avatar
Jody Goldberg committed
786 787
	cmd_insert_cols (workbook_command_context_gui (wb), sheet,
			 ss->user.start.col, cols);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
788 789 790
}

static void
791
insert_rows_cmd (GtkWidget *unused, Workbook *wb)
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
792
{
793 794
	SheetSelection *ss;
	int rows;
795
	Sheet *sheet = wb->current_sheet;
Morten Welinder's avatar
Morten Welinder committed
796

797
	/* TODO : No need to check simplicty.  XL applies for each
798
	 * non-discrete selected region, (use selection_apply) */
799
	if (!selection_is_simple (workbook_command_context_gui (wb), sheet, _("Insert rows")))
800 801 802
		return;

	ss = sheet->selections->data;
803

804 805 806 807 808
	/* 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 ?
	 */
809
	rows = ss->user.end.row - ss->user.start.row + 1;
Jody Goldberg's avatar
Jody Goldberg committed
810 811
	cmd_insert_rows (workbook_command_context_gui (wb), sheet,
			 ss->user.start.row, rows);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
812 813
}

Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
814 815 816
static void
clear_all_cmd (GtkWidget *widget, Workbook *wb)
{
Jody Goldberg's avatar
Jody Goldberg committed
817
	cmd_clear_selection (workbook_command_context_gui (wb), 
818 819
			     wb->current_sheet,
			     CLEAR_VALUES | CLEAR_FORMATS | CLEAR_COMMENTS);
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
820 821 822 823 824
}

static void
clear_formats_cmd (GtkWidget *widget, Workbook *wb)
{
Jody Goldberg's avatar
Jody Goldberg committed
825
	cmd_clear_selection (workbook_command_context_gui (wb), 
826 827
			     wb->current_sheet,
			     CLEAR_FORMATS);
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
828 829
}

830 831 832
static void
clear_comments_cmd (GtkWidget *widget, Workbook *wb)
{
Jody Goldberg's avatar
Jody Goldberg committed
833
	cmd_clear_selection (workbook_command_context_gui (wb), 
834 835
			     wb->current_sheet,
			     CLEAR_COMMENTS);
836 837
}

Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
838 839 840
static void
clear_content_cmd (GtkWidget *widget, Workbook *wb)
{
Jody Goldberg's avatar
Jody Goldberg committed
841
	cmd_clear_selection (workbook_command_context_gui (wb), 
842 843
			     wb->current_sheet,
			     CLEAR_VALUES);
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
844 845 846 847 848
}

static void
zoom_cmd (GtkWidget *widget, Workbook *wb)
{
849
	Sheet *sheet = wb->current_sheet;
850
	dialog_zoom (wb, sheet);
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
851 852
}

853 854 855
static void
cb_cell_rerender (gpointer cell, gpointer data)
{
Jody Goldberg's avatar
Jody Goldberg committed
856 857
        cell_render_value (cell);
        cell_queue_redraw (cell);
858 859
}

860 861 862
/***********************************************************************/
/* Sheet preferences */

863
static void
864
cb_sheet_pref_display_formulas (GtkWidget *widget, Workbook *wb)
865
{
866
	Sheet *sheet = wb->current_sheet;
867
	sheet->display_formulas = !sheet->display_formulas;
Jody Goldberg's avatar
Jody Goldberg committed
868 869 870
	g_list_foreach (wb->formula_cell_list, &cb_cell_rerender, NULL);
}
static void
871 872
cb_sheet_pref_hide_zeros (GtkWidget *widget, Workbook *wb)
{
873
	Sheet *sheet = wb->current_sheet;
874 875 876 877 878
	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
879
{
880
	Sheet *sheet = wb->current_sheet;
Jody Goldberg's avatar
Jody Goldberg committed
881
	sheet->show_grid = !sheet->show_grid;
882 883 884 885 886
	sheet_redraw_all (sheet);
}
static void
cb_sheet_pref_hide_col_header (GtkWidget *widget, Workbook *wb)
{
887
	Sheet *sheet = wb->current_sheet;
888 889 890 891 892 893
	sheet->show_col_header = ! sheet->show_col_header;
	sheet_adjust_preferences (sheet);
}
static void
cb_sheet_pref_hide_row_header (GtkWidget *widget, Workbook *wb)
{
894
	Sheet *sheet = wb->current_sheet;
895 896
	sheet->show_row_header = ! sheet->show_row_header;
	sheet_adjust_preferences (sheet);
897 898
}

899 900 901 902 903 904 905
/***********************************************************************/
/* Workbook level preferences */

static void
cb_wb_pref_hide_hscroll (GtkWidget *widget, Workbook *wb)
{
	wb->show_horizontal_scrollbar = ! wb->show_horizontal_scrollbar;
Jody Goldberg's avatar
Jody Goldberg committed
906
	workbook_view_pref_visibility (wb);
907 908 909 910 911 912
}

static void
cb_wb_pref_hide_vscroll (GtkWidget *widget, Workbook *wb)
{
	wb->show_vertical_scrollbar = ! wb->show_vertical_scrollbar;
Jody Goldberg's avatar
Jody Goldberg committed
913
	workbook_view_pref_visibility (wb);
914 915 916 917 918
}

static void
cb_wb_pref_hide_tabs (GtkWidget *widget, Workbook *wb)
{
Jody Goldberg's avatar
Jody Goldberg committed
919 920
	wb->show_notebook_tabs = ! wb->show_notebook_tabs;
	workbook_view_pref_visibility (wb);
921 922 923 924
}

/***********************************************************************/

Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
925 926 927
static void
format_cells_cmd (GtkWidget *widget, Workbook *wb)
{
928
	Sheet *sheet = wb->current_sheet;
929
	dialog_cell_format (wb, sheet);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
930 931
}

932 933 934
static void
sort_cells_cmd (GtkWidget *widget, Workbook *wb)
{
935
	Sheet *sheet = wb->current_sheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
936
	dialog_cell_sort (wb, sheet);
937 938
}

Arturo Espinosa's avatar
Arturo Espinosa committed
939
static void
940 941 942 943 944 945 946 947
recalc_cmd (GtkWidget *widget, Workbook *wb)
{
	workbook_recalc_all (wb);
}

static void
insert_current_date_cmd (GtkWidget *widget, Workbook *wb)
{
948
	Sheet *sheet = wb->current_sheet;
949 950
	cmd_set_date_time (workbook_command_context_gui (wb), TRUE,
			   sheet, sheet->cursor_col, sheet->cursor_row);
951 952 953 954 955
}

static void
insert_current_time_cmd (GtkWidget *widget, Workbook *wb)
{
956
	Sheet *sheet = wb->current_sheet;
957 958
	cmd_set_date_time (workbook_command_context_gui (wb), TRUE,
			   sheet, sheet->cursor_col, sheet->cursor_row);
959 960
}

961 962 963
static void
workbook_edit_comment (GtkWidget *widget, Workbook *wb)
{
964
	Sheet *sheet = wb->current_sheet;
965
	Cell *cell;
Morten Welinder's avatar
Morten Welinder committed
966

967 968
	cell = sheet_cell_get (sheet, sheet->cursor_col, sheet->cursor_row);

Jody Goldberg's avatar
Jody Goldberg committed
969
	if (!cell) {
970
		cell = sheet_cell_new (sheet, sheet->cursor_col, sheet->cursor_row);
971
		cell_set_value (cell, value_new_empty ());
972
	}
Miguel de Icaza's avatar
Miguel de Icaza committed
973 974

	dialog_cell_comment (wb, cell);
975 976
}

977 978 979
static void
goal_seek_cmd (GtkWidget *widget, Workbook *wb)
{
980
	Sheet *sheet = wb->current_sheet;
981
	dialog_goal_seek (wb, sheet);
982 983 984 985 986
}

static void
solver_cmd (GtkWidget *widget, Workbook *wb)
{
987
	Sheet *sheet = wb->current_sheet;
988 989 990
	dialog_solver (wb, sheet);
}

991 992 993
static void
data_analysis_cmd (GtkWidget *widget, Workbook *wb)
{
994
	Sheet *sheet = wb->current_sheet;
995 996 997
	dialog_data_analysis (wb, sheet);
}

998 999 1000
static void
print_setup_cmd (GtkWidget *widget, Workbook *wb)
{
1001
	Sheet *sheet = wb->current_sheet;
1002
	dialog_printer_setup (wb, sheet);
1003 1004 1005
}

static void
1006
file_print_cmd (GtkWidget *widget, Workbook *wb)
1007
{
1008
	Sheet *sheet = wb->current_sheet;
1009
	sheet_print (sheet, FALSE, PRINT_ACTIVE_SHEET);
1010 1011 1012 1013 1014
}

static void
file_print_preview_cmd (GtkWidget *widget, Workbook *wb)
{
1015
	Sheet *sheet = wb->current_sheet;
1016
	sheet_print (sheet, TRUE, PRINT_ACTIVE_SHEET);
1017 1018
}

1019 1020 1021 1022
#ifdef ENABLE_BONOBO
static void
insert_object_cmd (GtkWidget *widget, Workbook *wb)
{
1023
	Sheet *sheet = wb->current_sheet;
1024
	char *goadid;
1025

1026 1027 1028
	goadid = gnome_bonobo_select_goad_id (_("Select an object"), NULL);
	if (goadid != NULL)
		sheet_insert_object (sheet, goadid);
1029 1030 1031
}
#endif

Arturo Espinosa's avatar
Arturo Espinosa committed
1032 1033
/* File menu */

Arturo Espinosa's avatar
Arturo Espinosa committed
1034
static GnomeUIInfo workbook_menu_file [] = {
1035
        GNOMEUIINFO_MENU_NEW_ITEM(N_("_New"), N_("Create a new spreadsheet"),
Morten Welinder's avatar
Morten Welinder committed
1036
				  new_cmd, NULL),
1037

1038
	GNOMEUIINFO_MENU_OPEN_ITEM(file_open_cmd, NULL),
Karl Eichwalder's avatar
Karl Eichwalder committed
1039
	GNOMEUIINFO_ITEM_STOCK (N_("_Import..."), N_("Imports a file"),
1040
				file_import_cmd, GNOME_STOCK_MENU_OPEN),
1041
	GNOMEUIINFO_MENU_SAVE_ITEM(file_save_cmd, NULL),
1042

1043
	GNOMEUIINFO_MENU_SAVE_AS_ITEM(file_save_as_cmd, NULL),
Arturo Espinosa's avatar
Arturo Espinosa committed
1044

Michael Meeks's avatar
Michael Meeks committed
1045 1046
	{ GNOME_APP_UI_ITEM, N_("Su_mmary..."), N_("Summary information"),
	  summary_cmd },
Arturo Espinosa's avatar
Arturo Espinosa committed
1047

Michael Meeks's avatar
Michael Meeks committed
1048
	GNOMEUIINFO_SEPARATOR,
1049

1050 1051
	{ GNOME_APP_UI_ITEM, N_("Plu_g-ins..."), N_("Gnumeric plugins"),
	  plugins_cmd },
Arturo Espinosa's avatar
Arturo Espinosa committed
1052 1053 1054

	GNOMEUIINFO_SEPARATOR,

1055
	GNOMEUIINFO_MENU_PRINT_SETUP_ITEM(print_setup_cmd, NULL),
1056
	GNOMEUIINFO_MENU_PRINT_ITEM(file_print_cmd, NULL),
1057 1058 1059
	{ GNOME_APP_UI_ITEM, N_("Print pre_view"), N_("Print preview"),
	  file_print_preview_cmd },
	
1060
	GNOMEUIINFO_SEPARATOR,
1061 1062

	GNOMEUIINFO_MENU_CLOSE_ITEM(close_cmd, NULL