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
JP Rosevear's avatar
JP Rosevear committed
887
format_cells_cmd (GtkWidget *widget, Workbook *wb)
888
{
JP Rosevear's avatar
JP Rosevear committed
889
890
	Sheet *sheet = wb->current_sheet;
	dialog_cell_format (wb, sheet);
891
892
}

Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
893
static void
JP Rosevear's avatar
JP Rosevear committed
894
workbook_attr_cmd (GtkWidget *widget, Workbook *wb)
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
895
{
JP Rosevear's avatar
JP Rosevear committed
896
	dialog_workbook_attr (wb);
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
897
898
}

899
900
901
static void
sort_cells_cmd (GtkWidget *widget, Workbook *wb)
{
902
	Sheet *sheet = wb->current_sheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
903
	dialog_cell_sort (wb, sheet);
904
905
}

Arturo Espinosa's avatar
Arturo Espinosa committed
906
static void
907
908
909
recalc_cmd (GtkWidget *widget, Workbook *wb)
{
	workbook_recalc_all (wb);
910
	sheet_update (wb->current_sheet);
911
912
913
914
915
}

static void
insert_current_date_cmd (GtkWidget *widget, Workbook *wb)
{
916
	Sheet *sheet = wb->current_sheet;
917
918
	cmd_set_date_time (workbook_command_context_gui (wb),
			   sheet, &sheet->cursor.edit_pos, TRUE);
919
920
921
922
923
}

static void
insert_current_time_cmd (GtkWidget *widget, Workbook *wb)
{
924
	Sheet *sheet = wb->current_sheet;
925
926
	cmd_set_date_time (workbook_command_context_gui (wb),
			   sheet, &sheet->cursor.edit_pos, FALSE);
927
928
}

929
930
931
static void
workbook_edit_comment (GtkWidget *widget, Workbook *wb)
{
932
	Sheet *sheet = wb->current_sheet;
933
	Cell *cell;
Morten Welinder's avatar
Morten Welinder committed
934

935
936
937
	cell = sheet_cell_get (sheet,
			       sheet->cursor.edit_pos.col,
			       sheet->cursor.edit_pos.row);
938

Jody Goldberg's avatar
Jody Goldberg committed
939
	if (!cell) {
940
941
942
		cell = sheet_cell_new (sheet,
				       sheet->cursor.edit_pos.col,
				       sheet->cursor.edit_pos.row);
943
		sheet_cell_set_value (cell, value_new_empty (), NULL);
944
	}
Miguel de Icaza's avatar
Miguel de Icaza committed
945
946

	dialog_cell_comment (wb, cell);
947
948
}