1 
2 /*
3  * wbc-gtk-actions.c: Callbacks and tables for all the menus and stock toolbars
4  *
5  * Copyright (C) 2003-2006 Jody Goldberg (jody@gnome.org)
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) version 3.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
20  * USA
21  *
22  */
23 #include <gnumeric-config.h>
24 #include <gnumeric.h>
25 
26 #include <libgnumeric.h>
27 #include <application.h>
28 #include <gnm-commands-slicer.h>
29 #include <commands.h>
30 #include <clipboard.h>
31 #include <selection.h>
32 #include <search.h>
33 #include <ranges.h>
34 #include <cell.h>
35 #include <stf.h>
36 #include <value.h>
37 #include <gnm-format.h>
38 #include <sheet.h>
39 #include <sort.h>
40 #include <sheet-merge.h>
41 #include <sheet-filter.h>
42 #include <sheet-utils.h>
43 #include <sheet-style.h>
44 #include <style-border.h>
45 #include <style-color.h>
46 #include <tools/filter.h>
47 #include <sheet-control-gui-priv.h>
48 #include <sheet-view.h>
49 #include <cmd-edit.h>
50 #include <workbook.h>
51 #include <workbook-view.h>
52 #include <wbc-gtk-impl.h>
53 #include <workbook-cmd-format.h>
54 #include <dialogs/dialogs.h>
55 #include <sheet-object-image.h>
56 #include <sheet-object-widget.h>
57 #include <gnm-so-filled.h>
58 #include <gnm-so-line.h>
59 #include <sheet-object-graph.h>
60 #include <sheet-object-component.h>
61 #include <gui-util.h>
62 #include <gui-file.h>
63 #include <gnumeric-conf.h>
64 #include <expr.h>
65 #include <print.h>
66 #include <print-info.h>
67 #include <gnm-pane-impl.h>
68 #include <gutils.h>
69 #include <widgets/gnm-fontbutton.h>
70 
71 #include <goffice/goffice.h>
72 #include <goffice/component/goffice-component.h>
73 
74 #include <glib/gi18n-lib.h>
75 #include <gsf/gsf-input.h>
76 #include <string.h>
77 #include <glib/gstdio.h>
78 #include <errno.h>
79 
80 static gboolean
cb_cleanup_sendto(gpointer path)81 cb_cleanup_sendto (gpointer path)
82 {
83 	char *dir = g_path_get_dirname (path);
84 
85 	g_unlink (path);
86 	g_free (path);	/* the attachment */
87 
88 	g_rmdir (dir);
89 	g_free (dir);	/* the tempdir */
90 
91 	return FALSE;
92 }
93 
94 
GNM_ACTION_DEF(cb_file_new)95 static GNM_ACTION_DEF (cb_file_new)
96 {
97 	GdkScreen *screen = gtk_window_get_screen (wbcg_toplevel (wbcg));
98 	Workbook *wb = workbook_new_with_sheets
99 		(gnm_conf_get_core_workbook_n_sheet ());
100 	WBCGtk *new_wbcg = wbc_gtk_new (NULL, wb, screen, NULL);
101 	wbcg_copy_toolbar_visibility (new_wbcg, wbcg);
102 }
103 
GNM_ACTION_DEF(cb_file_open)104 static GNM_ACTION_DEF (cb_file_open)	{ gui_file_open (wbcg, GNM_FILE_OPEN_STYLE_OPEN, NULL); }
GNM_ACTION_DEF(cb_file_save)105 static GNM_ACTION_DEF (cb_file_save)	{ gui_file_save (wbcg, wb_control_view (GNM_WBC (wbcg))); }
GNM_ACTION_DEF(cb_file_save_as)106 static GNM_ACTION_DEF (cb_file_save_as)	{ gui_file_save_as
107 		(wbcg, wb_control_view (GNM_WBC (wbcg)),
108 		 GNM_FILE_SAVE_AS_STYLE_SAVE, NULL); }
109 
GNM_ACTION_DEF(cb_file_sendto)110 static GNM_ACTION_DEF (cb_file_sendto) {
111 	WorkbookControl *wbc = GNM_WBC (wbcg);
112 	WorkbookView *wbv = wb_control_view (wbc);
113 	GOCmdContext *gcc = GO_CMD_CONTEXT (wbcg);
114 	gboolean problem = FALSE;
115 	GOIOContext *io_context;
116 	Workbook *wb;
117 	GOFileSaver *fs;
118 
119 	wb = wb_control_get_workbook (wbc);
120 	g_object_ref (wb);
121 	fs = workbook_get_file_saver (wb);
122 	if (fs == NULL)
123 		fs = go_file_saver_get_default ();
124 
125 	io_context = go_io_context_new (gcc);
126 	if (fs != NULL) {
127 		char *template, *full_name, *uri;
128 		char *basename = g_path_get_basename (go_doc_get_uri (GO_DOC (wb)));
129 
130 		template = g_build_filename (g_get_tmp_dir (),
131 					     ".gnm-sendto-XXXXXX", NULL);
132 		problem = (g_mkdtemp_full (template, 0600) == NULL);
133 
134 		if (problem) {
135 			g_free (template);
136 			goto out;
137 		}
138 
139 		full_name = g_build_filename (template, basename, NULL);
140 		g_free (basename);
141 		uri = go_filename_to_uri (full_name);
142 
143 		workbook_view_save_to_uri (wbv, fs, uri, io_context);
144 
145 		if (go_io_error_occurred (io_context) ||
146 		    go_io_warning_occurred (io_context))
147 			go_io_error_display (io_context);
148 
149 		if (go_io_error_occurred (io_context)) {
150 			problem = TRUE;
151 		} else {
152 			/* mutt does not handle urls with no destination
153 			 * so pick something to arbitrary */
154 			GError *err;
155 			GdkScreen *screen = gtk_window_get_screen (wbcg_toplevel (wbcg));
156 			char *url, *tmp = go_url_encode (full_name, 0);
157 			url = g_strdup_printf ("mailto:someone?attach=%s", tmp);
158 			g_free (tmp);
159 
160 			err = go_gtk_url_show (url, screen);
161 
162 			if (err != NULL) {
163 				go_cmd_context_error (GO_CMD_CONTEXT (io_context), err);
164 				g_error_free (err);
165 				go_io_error_display (io_context);
166 				problem = TRUE;
167 			}
168 		}
169 		g_free (template);
170 		g_free (uri);
171 
172 		if (problem) {
173 			cb_cleanup_sendto (full_name);
174 		} else {
175 			/*
176 			 * We wait a while before we clean up to ensure the file is
177 			 * loaded by the mailer.
178 			 */
179 			g_timeout_add (1000 * 10, cb_cleanup_sendto, full_name);
180 		}
181 	} else {
182 		go_cmd_context_error_export (GO_CMD_CONTEXT (io_context),
183 			_("Default file saver is not available."));
184 		go_io_error_display (io_context);
185 		problem = TRUE;
186 	}
187 
188  out:
189 	g_object_unref (io_context);
190 	g_object_unref (wb);
191 
192 	/* What do we do with "problem"? */
193 }
194 
GNM_ACTION_DEF(cb_file_page_setup)195 static GNM_ACTION_DEF (cb_file_page_setup)
196 {
197 	dialog_printer_setup (wbcg, wbcg_cur_sheet (wbcg));
198 }
199 
GNM_ACTION_DEF(cb_file_print_area_set)200 static GNM_ACTION_DEF (cb_file_print_area_set)
201 {
202 	Sheet *sheet = wbcg_cur_sheet (wbcg);
203 	SheetView *sv = sheet_get_view (sheet, wb_control_view (GNM_WBC (wbcg)));
204 	GnmParsePos pp;
205 	char *message;
206 	char * selection;
207 	GnmRange const *r = selection_first_range (sv,
208 				       GO_CMD_CONTEXT (wbcg), _("Set Print Area"));
209 	if (r != NULL) {
210 		parse_pos_init_sheet (&pp, sheet);
211 		selection = undo_range_name (sheet, r);
212 		message = g_strdup_printf (_("Set Print Area to %s"), selection);
213 		cmd_define_name	(GNM_WBC (wbcg), "Print_Area", &pp,
214 				 gnm_expr_top_new_constant
215 				 (value_new_cellrange_r (NULL, r)),
216 				 message);
217 		g_free (selection);
218 		g_free (message);
219 	}
220 }
221 
GNM_ACTION_DEF(cb_file_print_area_clear)222 static GNM_ACTION_DEF (cb_file_print_area_clear)
223 {
224 	GnmParsePos pp;
225 	Sheet *sheet = wbcg_cur_sheet (wbcg);
226 
227 	parse_pos_init_sheet (&pp, sheet);
228 	cmd_define_name	(GNM_WBC (wbcg), "Print_Area", &pp,
229 			 gnm_expr_top_new_constant
230 			 (value_new_error_REF (NULL)),
231 			 _("Clear Print Area"));
232 }
233 
GNM_ACTION_DEF(cb_file_print_area_show)234 static GNM_ACTION_DEF (cb_file_print_area_show)
235 {
236 	Sheet *sheet = wbcg_cur_sheet (wbcg);
237 	GnmRange *r = sheet_get_nominal_printarea (sheet);
238 
239 	if (r != NULL) {
240 		SheetView *sv = sheet_get_view (sheet,
241 						wb_control_view (GNM_WBC (wbcg)));
242 		wb_control_sheet_focus (GNM_WBC (wbcg), sheet);
243 		sv_selection_reset (sv);
244 		sv_selection_add_range (sv, r);
245 		gnm_sheet_view_make_cell_visible (sv, r->start.col, r->start.row, FALSE);
246 		g_free (r);
247 	}
248 }
249 
GNM_ACTION_DEF(cb_file_print_area_toggle_col)250 static GNM_ACTION_DEF (cb_file_print_area_toggle_col)
251 {
252 	cmd_page_break_toggle (GNM_WBC (wbcg),
253 			       wbcg_cur_sheet (wbcg),
254 			       TRUE);
255 }
GNM_ACTION_DEF(cb_file_print_area_toggle_row)256 static GNM_ACTION_DEF (cb_file_print_area_toggle_row)
257 {
258 	cmd_page_break_toggle (GNM_WBC (wbcg),
259 			       wbcg_cur_sheet (wbcg),
260 			       FALSE);
261 }
262 
GNM_ACTION_DEF(cb_file_print_area_clear_pagebreaks)263 static GNM_ACTION_DEF (cb_file_print_area_clear_pagebreaks)
264 {
265 	cmd_page_breaks_clear (GNM_WBC (wbcg), wbcg_cur_sheet (wbcg));
266 }
267 
GNM_ACTION_DEF(cb_file_print)268 static GNM_ACTION_DEF (cb_file_print)
269 {
270 	gnm_print_sheet (GNM_WBC (wbcg),
271 		wbcg_cur_sheet (wbcg), FALSE, GNM_PRINT_SAVED_INFO, NULL);
272 }
273 
GNM_ACTION_DEF(cb_file_print_preview)274 static GNM_ACTION_DEF (cb_file_print_preview)
275 {
276 	gnm_print_sheet (GNM_WBC (wbcg),
277 		wbcg_cur_sheet (wbcg), TRUE, GNM_PRINT_ACTIVE_SHEET, NULL);
278 }
279 
GNM_ACTION_DEF(cb_doc_meta_data)280 static GNM_ACTION_DEF (cb_doc_meta_data)	{ dialog_doc_metadata_new (wbcg, 0); }
GNM_ACTION_DEF(cb_file_preferences)281 static GNM_ACTION_DEF (cb_file_preferences)	{ dialog_preferences (wbcg, NULL); }
GNM_ACTION_DEF(cb_file_history_full)282 static GNM_ACTION_DEF (cb_file_history_full)    { dialog_recent_used (wbcg); }
GNM_ACTION_DEF(cb_file_close)283 static GNM_ACTION_DEF (cb_file_close)		{ wbc_gtk_close (wbcg); }
284 
GNM_ACTION_DEF(cb_file_quit)285 static GNM_ACTION_DEF (cb_file_quit)
286 {
287 	/* If we are still loading initial files, short circuit */
288 	if (!gnm_app_initial_open_complete ()) {
289 		g_object_set (gnm_app_get_app (), "shutting-down", TRUE, NULL);
290 		return;
291 	}
292 
293 	/* If we were editing when the quit request came in abort the edit. */
294 	wbcg_edit_finish (wbcg, WBC_EDIT_REJECT, NULL);
295 
296 	dialog_quit (wbcg);
297 }
298 
299 /****************************************************************************/
300 
GNM_ACTION_DEF(cb_edit_clear_all)301 static GNM_ACTION_DEF (cb_edit_clear_all)
302 {
303 	cmd_selection_clear (GNM_WBC (wbcg),
304 		CLEAR_VALUES | CLEAR_FORMATS | CLEAR_OBJECTS | CLEAR_COMMENTS);
305 }
306 
GNM_ACTION_DEF(cb_edit_clear_formats)307 static GNM_ACTION_DEF (cb_edit_clear_formats)
308 	{ cmd_selection_clear (GNM_WBC (wbcg), CLEAR_FORMATS); }
GNM_ACTION_DEF(cb_edit_clear_comments)309 static GNM_ACTION_DEF (cb_edit_clear_comments)
310 	{ cmd_selection_clear (GNM_WBC (wbcg), CLEAR_COMMENTS); }
GNM_ACTION_DEF(cb_edit_clear_content)311 static GNM_ACTION_DEF (cb_edit_clear_content)
312 	{ cmd_selection_clear (GNM_WBC (wbcg), CLEAR_VALUES); }
GNM_ACTION_DEF(cb_edit_clear_all_filtered)313 static GNM_ACTION_DEF (cb_edit_clear_all_filtered)
314 {
315 	cmd_selection_clear (GNM_WBC (wbcg),
316 		CLEAR_VALUES | CLEAR_FORMATS | CLEAR_OBJECTS | CLEAR_COMMENTS | CLEAR_FILTERED_ONLY);
317 }
318 
GNM_ACTION_DEF(cb_edit_clear_formats_filtered)319 static GNM_ACTION_DEF (cb_edit_clear_formats_filtered)
320 	{ cmd_selection_clear (GNM_WBC (wbcg), CLEAR_FORMATS | CLEAR_FILTERED_ONLY); }
GNM_ACTION_DEF(cb_edit_clear_comments_filtered)321 static GNM_ACTION_DEF (cb_edit_clear_comments_filtered)
322 	{ cmd_selection_clear (GNM_WBC (wbcg), CLEAR_COMMENTS | CLEAR_FILTERED_ONLY); }
GNM_ACTION_DEF(cb_edit_clear_content_filtered)323 static GNM_ACTION_DEF (cb_edit_clear_content_filtered)
324 	{ cmd_selection_clear (GNM_WBC (wbcg), CLEAR_VALUES | CLEAR_FILTERED_ONLY); }
325 
GNM_ACTION_DEF(cb_edit_delete_rows)326 static GNM_ACTION_DEF (cb_edit_delete_rows)
327 {
328 	WorkbookControl *wbc   = GNM_WBC (wbcg);
329 	SheetView       *sv    = wb_control_cur_sheet_view (wbc);
330 	Sheet           *sheet = wb_control_cur_sheet (wbc);
331 	GnmRange const  *sel;
332 	int rows;
333 
334 	if (!(sel = selection_first_range (sv, GO_CMD_CONTEXT (wbc), _("Delete"))))
335 		return;
336 	rows = range_height (sel);
337 
338 	cmd_delete_rows (wbc, sheet, sel->start.row, rows);
339 }
GNM_ACTION_DEF(cb_edit_delete_columns)340 static GNM_ACTION_DEF (cb_edit_delete_columns)
341 {
342 	WorkbookControl *wbc   = GNM_WBC (wbcg);
343 	SheetView       *sv    = wb_control_cur_sheet_view (wbc);
344 	Sheet           *sheet = wb_control_cur_sheet (wbc);
345 	GnmRange const *sel;
346 	int cols;
347 
348 	if (!(sel = selection_first_range (sv, GO_CMD_CONTEXT (wbc), _("Delete"))))
349 		return;
350 	cols = range_width (sel);
351 
352 	cmd_delete_cols (wbc, sheet, sel->start.col, cols);
353 }
354 
GNM_ACTION_DEF(cb_edit_delete_cells)355 static GNM_ACTION_DEF (cb_edit_delete_cells)
356 {
357 	dialog_delete_cells (wbcg);
358 }
GNM_ACTION_DEF(cb_edit_delete_links)359 static GNM_ACTION_DEF (cb_edit_delete_links)
360 	{
361 		SheetControlGUI *scg = wbcg_cur_scg (wbcg);
362 		GnmStyle *style = gnm_style_new ();
363 		GSList *l;
364 		int n_links = 0;
365 		gchar const *format;
366 		gchar *name;
367 		WorkbookControl *wbc   = GNM_WBC (wbcg);
368 		Sheet *sheet = wb_control_cur_sheet (wbc);
369 
370 		for (l = scg_view (scg)->selections; l != NULL; l = l->next) {
371 			GnmRange const *r = l->data;
372 			GnmStyleList *styles;
373 
374 			styles = sheet_style_collect_hlinks (sheet, r);
375 			n_links += g_slist_length (styles);
376 			style_list_free (styles);
377 		}
378 		format = ngettext ("Remove %d Link", "Remove %d Links", n_links);
379 		name = g_strdup_printf (format, n_links);
380 		gnm_style_set_hlink (style, NULL);
381 		cmd_selection_format (wbc, style, NULL, name);
382 		g_free (name);
383 	}
384 
GNM_ACTION_DEF(cb_edit_select_all)385 static GNM_ACTION_DEF (cb_edit_select_all)
386 {
387 	scg_select_all (wbcg_cur_scg (wbcg));
388 }
GNM_ACTION_DEF(cb_edit_select_row)389 static GNM_ACTION_DEF (cb_edit_select_row)
390 {
391 	sv_select_cur_row (wb_control_cur_sheet_view (GNM_WBC (wbcg)));
392 }
GNM_ACTION_DEF(cb_edit_select_col)393 static GNM_ACTION_DEF (cb_edit_select_col)
394 {
395 	sv_select_cur_col (wb_control_cur_sheet_view (GNM_WBC (wbcg)));
396 }
GNM_ACTION_DEF(cb_edit_select_array)397 static GNM_ACTION_DEF (cb_edit_select_array)
398 {
399 	sv_select_cur_array (wb_control_cur_sheet_view (GNM_WBC (wbcg)));
400 }
GNM_ACTION_DEF(cb_edit_select_depends)401 static GNM_ACTION_DEF (cb_edit_select_depends)
402 {
403 	sv_select_cur_depends (wb_control_cur_sheet_view (GNM_WBC (wbcg)));
404 }
GNM_ACTION_DEF(cb_edit_select_inputs)405 static GNM_ACTION_DEF (cb_edit_select_inputs)
406 {
407 	sv_select_cur_inputs (wb_control_cur_sheet_view (GNM_WBC (wbcg)));
408 }
GNM_ACTION_DEF(cb_edit_select_object)409 static GNM_ACTION_DEF (cb_edit_select_object)
410 {
411 	scg_object_select_next (wbcg_cur_scg (wbcg), FALSE);
412 }
413 
GNM_ACTION_DEF(cb_edit_cut)414 static GNM_ACTION_DEF (cb_edit_cut)
415 {
416 	if (!wbcg_is_editing (wbcg)) {
417 		SheetControlGUI *scg = wbcg_cur_scg (wbcg);
418 		WorkbookControl *wbc = GNM_WBC (wbcg);
419 		SheetView *sv = wb_control_cur_sheet_view (wbc);
420 		if (scg != NULL && scg->selected_objects != NULL)
421 			gnm_app_clipboard_cut_copy_obj (wbc, TRUE, sv,
422 				go_hash_keys (scg->selected_objects));
423 		else
424 			gnm_sheet_view_selection_cut (sv, wbc);
425 	} else
426 		gtk_editable_cut_clipboard (GTK_EDITABLE (wbcg_get_entry (wbcg)));
427 }
428 
GNM_ACTION_DEF(cb_edit_copy)429 static GNM_ACTION_DEF (cb_edit_copy)
430 {
431 	if (!wbcg_is_editing (wbcg)) {
432 		SheetControlGUI *scg = wbcg_cur_scg (wbcg);
433 		WorkbookControl *wbc = GNM_WBC (wbcg);
434 		SheetView *sv = wb_control_cur_sheet_view (wbc);
435 		if (scg != NULL && scg->selected_objects != NULL)
436 			gnm_app_clipboard_cut_copy_obj (wbc, FALSE, sv,
437 				go_hash_keys (scg->selected_objects));
438 		else
439 			gnm_sheet_view_selection_copy (sv, wbc);
440 	} else
441 		gtk_editable_copy_clipboard (GTK_EDITABLE (wbcg_get_entry (wbcg)));
442 }
443 
GNM_ACTION_DEF(cb_edit_paste)444 static GNM_ACTION_DEF (cb_edit_paste)
445 {
446 	if (!wbcg_is_editing (wbcg)) {
447 		WorkbookControl *wbc = GNM_WBC (wbcg);
448 		SheetView *sv = wb_control_cur_sheet_view (wbc);
449 		cmd_paste_to_selection (wbc, sv, PASTE_DEFAULT);
450 	} else
451 		gtk_editable_paste_clipboard (GTK_EDITABLE (wbcg_get_entry (wbcg)));
452 }
453 
GNM_ACTION_DEF(cb_edit_paste_special)454 static GNM_ACTION_DEF (cb_edit_paste_special)
455 {
456 	dialog_paste_special (wbcg);
457 }
458 
GNM_ACTION_DEF(cb_sheet_remove)459 static GNM_ACTION_DEF (cb_sheet_remove)
460 {
461 	SheetControlGUI *scg = wbcg_cur_scg (wbcg);
462 	if (scg)
463 		scg_delete_sheet_if_possible (scg);
464 }
465 
466 static void
common_cell_goto(WBCGtk * wbcg,Sheet * sheet,GnmCellPos const * pos)467 common_cell_goto (WBCGtk *wbcg, Sheet *sheet, GnmCellPos const *pos)
468 {
469 	SheetView *sv;
470 	WorkbookView *wbv;
471 
472 	if (!sheet_is_visible (sheet))
473 		return;
474 
475 	wbv = wb_control_view (GNM_WBC (wbcg));
476 	sv = sheet_get_view (sheet, wbv);
477 	wb_view_sheet_focus (wbv, sheet);
478 	sv_selection_set (sv, pos,
479 		pos->col, pos->row,
480 		pos->col, pos->row);
481 	gnm_sheet_view_make_cell_visible (sv, pos->col, pos->row, FALSE);
482 }
483 
484 static int
cb_edit_search_replace_query(GnmSearchReplaceQuery q,GnmSearchReplace * sr,...)485 cb_edit_search_replace_query (GnmSearchReplaceQuery q, GnmSearchReplace *sr, ...)
486 {
487 	int res;
488 	va_list pvar;
489 	WBCGtk *wbcg = sr->user_data;
490 
491 	va_start (pvar, sr);
492 
493 	switch (q) {
494 	case GNM_SRQ_FAIL: {
495 		GnmCell *cell = va_arg (pvar, GnmCell *);
496 		char const *old_text = va_arg (pvar, char const *);
497 		char const *new_text = va_arg (pvar, char const *);
498 		char *err = g_strdup_printf
499 			(_("In cell %s, the current contents\n"
500 			   "        %s\n"
501 			   "would have been replaced by\n"
502 			   "        %s\n"
503 			   "which is invalid.\n\n"
504 			   "The replace has been aborted "
505 			   "and nothing has been changed."),
506 			 cell_name (cell),
507 			 old_text,
508 			 new_text);
509 
510 		go_gtk_notice_dialog (wbcg_toplevel (wbcg), GTK_MESSAGE_ERROR,
511 				      "%s", err);
512 		g_free (err);
513 		res = GTK_RESPONSE_NO;
514 		break;
515 	}
516 
517 	case GNM_SRQ_QUERY: {
518 		GnmCell *cell = va_arg (pvar, GnmCell *);
519 		char const *old_text = va_arg (pvar, char const *);
520 		char const *new_text = va_arg (pvar, char const *);
521 		Sheet *sheet = cell->base.sheet;
522 		char *pos_name = g_strconcat (sheet->name_unquoted, "!",
523 					      cell_name (cell), NULL);
524 
525 		common_cell_goto (wbcg, sheet, &cell->pos);
526 
527 		res = dialog_search_replace_query (wbcg, sr, pos_name,
528 						   old_text, new_text);
529 		g_free (pos_name);
530 		break;
531 	}
532 
533 	case GNM_SRQ_QUERY_COMMENT: {
534 		Sheet *sheet = va_arg (pvar, Sheet *);
535 		GnmCellPos *cp = va_arg (pvar, GnmCellPos *);
536 		char const *old_text = va_arg (pvar, char const *);
537 		char const *new_text = va_arg (pvar, char const *);
538 		char *pos_name = g_strdup_printf (_("Comment in cell %s!%s"),
539 						  sheet->name_unquoted,
540 						  cellpos_as_string (cp));
541 		common_cell_goto (wbcg, sheet, cp);
542 
543 		res = dialog_search_replace_query (wbcg, sr, pos_name,
544 						   old_text, new_text);
545 		g_free (pos_name);
546 		break;
547 	}
548 
549 	default:
550 		/* Shouldn't really happen.  */
551 		res = GTK_RESPONSE_CANCEL;
552 	}
553 
554 	va_end (pvar);
555 	return res;
556 }
557 
558 static gboolean
cb_edit_search_replace_action(WBCGtk * wbcg,GnmSearchReplace * sr)559 cb_edit_search_replace_action (WBCGtk *wbcg,
560 			       GnmSearchReplace *sr)
561 {
562 	WorkbookControl *wbc = GNM_WBC (wbcg);
563 
564 	sr->query_func = cb_edit_search_replace_query;
565 	sr->user_data = wbcg;
566 
567 	return cmd_search_replace (wbc, sr);
568 }
569 
570 
GNM_ACTION_DEF(cb_edit_search_replace)571 static GNM_ACTION_DEF (cb_edit_search_replace) { dialog_search_replace (wbcg, cb_edit_search_replace_action); }
GNM_ACTION_DEF(cb_edit_search)572 static GNM_ACTION_DEF (cb_edit_search) { dialog_search (wbcg); }
573 
GNM_ACTION_DEF(cb_edit_fill_autofill)574 static GNM_ACTION_DEF (cb_edit_fill_autofill)
575 {
576 	WorkbookControl *wbc = GNM_WBC (wbcg);
577 	SheetView *sv = wb_control_cur_sheet_view (wbc);
578 	Sheet	  *sheet = wb_control_cur_sheet (wbc);
579 
580 	GnmRange const *total = selection_first_range (sv, GO_CMD_CONTEXT (wbc), _("Autofill"));
581 	if (total) {
582 		GnmRange src = *total;
583 		gboolean do_loop;
584 		GSList *merges, *ptr;
585 
586 		if (sheet_range_trim (sheet, &src, TRUE, TRUE))
587 			return; /* Region totally empty */
588 
589 		/* trim is a bit overzealous, it forgets about merges */
590 		do {
591 			do_loop = FALSE;
592 			merges = gnm_sheet_merge_get_overlap (sheet, &src);
593 			for (ptr = merges ; ptr != NULL ; ptr = ptr->next) {
594 				GnmRange const *r = ptr->data;
595 				if (src.end.col < r->end.col) {
596 					src.end.col = r->end.col;
597 					do_loop = TRUE;
598 				}
599 				if (src.end.row < r->end.row) {
600 					src.end.row = r->end.row;
601 					do_loop = TRUE;
602 				}
603 			}
604 		} while (do_loop);
605 
606 		/* Make it autofill in only one direction */
607 		if ((total->end.col - src.end.col) >=
608 		    (total->end.row - src.end.row))
609 			src.end.row = total->end.row;
610 		else
611 			src.end.col = total->end.col;
612 
613 		cmd_autofill (wbc, sheet, FALSE,
614 			      total->start.col, total->start.row,
615 			      src.end.col - total->start.col + 1,
616 			      src.end.row - total->start.row + 1,
617 			      total->end.col, total->end.row,
618 			      FALSE);
619 	}
620 }
621 
GNM_ACTION_DEF(cb_edit_fill_series)622 static GNM_ACTION_DEF (cb_edit_fill_series)
623 {
624 	dialog_fill_series (wbcg);
625 }
626 
GNM_ACTION_DEF(cb_edit_goto_top)627 static GNM_ACTION_DEF (cb_edit_goto_top)
628 {
629 	wb_control_navigate_to_cell (GNM_WBC (wbcg), navigator_top);
630 }
GNM_ACTION_DEF(cb_edit_goto_bottom)631 static GNM_ACTION_DEF (cb_edit_goto_bottom)
632 {
633 	wb_control_navigate_to_cell (GNM_WBC (wbcg), navigator_bottom);
634 }
GNM_ACTION_DEF(cb_edit_goto_first)635 static GNM_ACTION_DEF (cb_edit_goto_first)
636 {
637 	wb_control_navigate_to_cell (GNM_WBC (wbcg), navigator_first);
638 }
GNM_ACTION_DEF(cb_edit_goto_last)639 static GNM_ACTION_DEF (cb_edit_goto_last)
640 {
641 	wb_control_navigate_to_cell (GNM_WBC (wbcg), navigator_last);
642 }
GNM_ACTION_DEF(cb_edit_goto)643 static GNM_ACTION_DEF (cb_edit_goto)
644 {
645 	dialog_goto_cell (wbcg);
646 }
GNM_ACTION_DEF(cb_edit_goto_cell_indicator)647 static GNM_ACTION_DEF (cb_edit_goto_cell_indicator)
648 {
649 	if (GNM_IS_WBC_GTK (wbcg))
650 		wbcg_focus_current_cell_indicator (WBC_GTK (wbcg));
651 }
652 
GNM_ACTION_DEF(cb_edit_recalc)653 static GNM_ACTION_DEF (cb_edit_recalc)
654 {
655 	/* TODO:
656 	 * f9  -  do any necessary calculations across all sheets
657 	 * shift-f9  -  do any necessary calcs on current sheet only
658 	 * ctrl-alt-f9 -  force a full recalc across all sheets
659 	 * ctrl-alt-shift-f9  -  a full-monty super recalc
660 	 */
661 	workbook_recalc_all (wb_control_get_workbook (GNM_WBC (wbcg)));
662 }
663 
GNM_ACTION_DEF(cb_repeat)664 static GNM_ACTION_DEF (cb_repeat)	{ command_repeat (GNM_WBC (wbcg)); }
665 
666 /****************************************************************************/
667 
GNM_ACTION_DEF(cb_direction)668 static GNM_ACTION_DEF (cb_direction)
669 {
670 	Sheet *sheet = wb_control_cur_sheet (GNM_WBC (wbcg));
671 	cmd_toggle_rtl (GNM_WBC (wbcg), sheet);
672 }
673 
GNM_ACTION_DEF(cb_view_zoom_in)674 static GNM_ACTION_DEF (cb_view_zoom_in)
675 {
676 	Sheet *sheet = wb_control_cur_sheet (GNM_WBC (wbcg));
677 	int zoom = (int)(sheet->last_zoom_factor_used * 100. + .5) - 10;
678 	if ((zoom % 15) != 0)
679 		zoom = 15 * (int)(zoom/15);
680 	zoom += 15;
681 	if (zoom <= 390)
682 		cmd_zoom (GNM_WBC (wbcg), g_slist_append (NULL, sheet),
683 			  (double) (zoom + 10) / 100);
684 }
GNM_ACTION_DEF(cb_view_zoom_out)685 static GNM_ACTION_DEF (cb_view_zoom_out)
686 {
687 	Sheet *sheet = wb_control_cur_sheet (GNM_WBC (wbcg));
688 	int zoom = (int)(sheet->last_zoom_factor_used * 100. + .5) - 10;
689 	if ((zoom % 15) != 0)
690 		zoom = 15 * (int)(zoom/15);
691 	else
692 		zoom -= 15;
693 	if (0 <= zoom)
694 		cmd_zoom (GNM_WBC (wbcg), g_slist_append (NULL, sheet),
695 			  (double) (zoom + 10) / 100);
696 }
697 
GNM_ACTION_DEF(cb_view_fullscreen)698 static GNM_ACTION_DEF (cb_view_fullscreen)
699 {
700 	if (wbcg->is_fullscreen)
701 		gtk_window_unfullscreen (wbcg_toplevel (wbcg));
702 	else
703 		gtk_window_fullscreen (wbcg_toplevel (wbcg));
704 }
705 
GNM_ACTION_DEF(cb_view_zoom)706 static GNM_ACTION_DEF (cb_view_zoom)	{ dialog_zoom (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_view_new)707 static GNM_ACTION_DEF (cb_view_new)	{ dialog_new_view (wbcg); }
GNM_ACTION_DEF(cb_view_freeze_panes)708 static GNM_ACTION_DEF (cb_view_freeze_panes)
709 {
710 	WorkbookControl *wbc = GNM_WBC (wbcg);
711 	SheetView *sv = wb_control_cur_sheet_view (wbc);
712 	SheetControlGUI *scg = wbcg_cur_scg (wbcg);
713 
714 	scg_mode_edit (scg);
715 	if (scg->active_panes == 1) {
716 		gboolean center = FALSE;
717 		GnmPane const *pane = scg_pane (scg, 0);
718 		GnmCellPos frozen_tl, unfrozen_tl;
719 
720 		frozen_tl = pane->first;
721 		unfrozen_tl = sv->edit_pos;
722 
723 		if (unfrozen_tl.row == 0 && unfrozen_tl.col == 0) {
724 			GnmRange const *first = selection_first_range (sv, NULL, NULL);
725 			Sheet *sheet = sv_sheet (sv);
726 			gboolean full_rows = range_is_full (first, sheet, TRUE);
727 			gboolean full_cols = range_is_full (first, sheet, FALSE);
728 			if (!full_rows || !full_cols) {
729 				if (!full_rows && !full_cols) {
730 					unfrozen_tl.row = first->end.row + 1;
731 					unfrozen_tl.col = first->end.col + 1;
732 				} else if (full_rows) {
733 					unfrozen_tl.row = first->end.row + 1;
734 					unfrozen_tl.col = 0;
735 				} else {
736 					unfrozen_tl.row = 0;
737 					unfrozen_tl.col = first->end.col + 1;
738 				}
739 			}
740 		}
741 
742                 /* If edit pos is out of visible range */
743 		if (unfrozen_tl.col < pane->first.col ||
744 		    unfrozen_tl.col > pane->last_visible.col ||
745 		    unfrozen_tl.row < pane->first.row ||
746 		    unfrozen_tl.row > pane->last_visible.row)
747 			center = TRUE;
748 
749 		if (unfrozen_tl.col == pane->first.col) {
750 			/* or edit pos is in top left visible cell */
751 			if (unfrozen_tl.row == pane->first.row)
752 				center = TRUE;
753 			else
754 				unfrozen_tl.col = frozen_tl.col = 0;
755 		} else if (unfrozen_tl.row == pane->first.row)
756 			unfrozen_tl.row = frozen_tl.row = 0;
757 
758 		if (center) {
759 			unfrozen_tl.col = (pane->first.col +
760 					   pane->last_visible.col) / 2;
761 			unfrozen_tl.row = (pane->first.row +
762 					   pane->last_visible.row) / 2;
763 		}
764 
765 		g_return_if_fail (unfrozen_tl.col > frozen_tl.col ||
766 				  unfrozen_tl.row > frozen_tl.row);
767 
768 		gnm_sheet_view_freeze_panes (sv, &frozen_tl, &unfrozen_tl);
769 	} else
770 		gnm_sheet_view_freeze_panes (sv, NULL, NULL);
771 }
772 
773 /****************************************************************************/
774 
775 static void
insert_date_time_common(WBCGtk * wbcg,gboolean do_date,gboolean do_time)776 insert_date_time_common (WBCGtk *wbcg, gboolean do_date, gboolean do_time)
777 {
778 	if (wbcg_edit_start (wbcg, FALSE, FALSE)) {
779 		WorkbookControl *wbc = GNM_WBC (wbcg);
780 		SheetView *sv = wb_control_cur_sheet_view (wbc);
781 		Sheet *sheet = sv_sheet (sv);
782 		GnmCell const *cell = sheet_cell_fetch (sheet,
783 							sv->edit_pos.col,
784 							sv->edit_pos.row);
785 		GODateConventions const *date_conv = sheet_date_conv (sheet);
786 		GnmValue *v = value_new_float
787 			(go_date_timet_to_serial_raw (time (NULL), date_conv));
788 		char *txt;
789 		char *dtxt = NULL;
790 		char *ttxt = NULL;
791 		GtkEntry *entry;
792 
793 		if (do_date) {
794 			GOFormat *fmt = gnm_format_for_date_editing (cell);
795 			dtxt = format_value (fmt, v, -1, date_conv);
796 			go_format_unref (fmt);
797 		}
798 
799 		if (do_time) {
800 			GOFormat const *fmt = go_format_default_time ();
801 			ttxt = format_value (fmt, v, -1, date_conv);
802 		}
803 
804 		value_release (v);
805 
806 		if (do_date && do_time) {
807 			txt = g_strconcat (dtxt, " ", ttxt, NULL);
808 			g_free (dtxt);
809 			g_free (ttxt);
810 		} else if (do_date)
811 			txt = dtxt;
812 		else
813 			txt = ttxt;
814 
815 		wb_control_edit_line_set (wbc, txt);
816 		g_free (txt);
817 
818 		// Explicitly place cursor at end.  Otherwise the cursor
819 		// position depends on whether the new contents matches
820 		// the old which is weird.
821 		entry = wbcg_get_entry (wbcg);
822 		gtk_editable_set_position (GTK_EDITABLE (entry), -1);
823 	}
824 }
825 
826 
827 
GNM_ACTION_DEF(cb_insert_current_date_time)828 static GNM_ACTION_DEF (cb_insert_current_date_time)
829 {
830 	insert_date_time_common (wbcg, TRUE, TRUE);
831 }
GNM_ACTION_DEF(cb_insert_current_date)832 static GNM_ACTION_DEF (cb_insert_current_date)
833 {
834 	insert_date_time_common (wbcg, TRUE, FALSE);
835 }
836 
GNM_ACTION_DEF(cb_insert_current_time)837 static GNM_ACTION_DEF (cb_insert_current_time)
838 {
839 	insert_date_time_common (wbcg, FALSE, TRUE);
840 }
841 
GNM_ACTION_DEF(cb_define_name)842 static GNM_ACTION_DEF (cb_define_name)
843 {
844 	dialog_define_names (wbcg);
845 }
GNM_ACTION_DEF(cb_paste_names)846 static GNM_ACTION_DEF (cb_paste_names)
847 {
848 	dialog_paste_names (wbcg);
849 }
850 
GNM_ACTION_DEF(cb_insert_rows)851 static GNM_ACTION_DEF (cb_insert_rows)
852 {
853 	WorkbookControl *wbc = GNM_WBC (wbcg);
854 	Sheet     *sheet = wb_control_cur_sheet (wbc);
855 	SheetView *sv = wb_control_cur_sheet_view (wbc);
856 	GnmRange const *sel;
857 
858 	/* TODO : No need to check simplicty.  XL applies for each non-discrete
859 	 * selected region, (use selection_apply).  Arrays and Merged regions
860 	 * are permitted.
861 	 */
862 	if (!(sel = selection_first_range (sv, GO_CMD_CONTEXT (wbc), _("Insert rows"))))
863 		return;
864 	cmd_insert_rows (wbc, sheet, sel->start.row, range_height (sel));
865 }
866 
GNM_ACTION_DEF(cb_insert_cols)867 static GNM_ACTION_DEF (cb_insert_cols)
868 {
869 	WorkbookControl *wbc = GNM_WBC (wbcg);
870 	Sheet *sheet = wb_control_cur_sheet (wbc);
871 	SheetView *sv = wb_control_cur_sheet_view (wbc);
872 	GnmRange const *sel;
873 
874 	/* TODO : No need to check simplicty.  XL applies for each non-discrete
875 	 * selected region, (use selection_apply).  Arrays and Merged regions
876 	 * are permitted.
877 	 */
878 	if (!(sel = selection_first_range (sv, GO_CMD_CONTEXT (wbc),
879 					   _("Insert columns"))))
880 		return;
881 	cmd_insert_cols (wbc, sheet, sel->start.col, range_width (sel));
882 }
883 
GNM_ACTION_DEF(cb_insert_cells)884 static GNM_ACTION_DEF (cb_insert_cells) { dialog_insert_cells (wbcg); }
885 
GNM_ACTION_DEF(cb_insert_comment)886 static GNM_ACTION_DEF (cb_insert_comment)
887 {
888 	WorkbookControl *wbc = GNM_WBC (wbcg);
889 	Sheet *sheet = wb_control_cur_sheet (wbc);
890 	SheetView *sv = wb_control_cur_sheet_view (wbc);
891 	dialog_cell_comment (wbcg, sheet, &sv->edit_pos);
892 }
893 
894 /****************************************************************************/
895 
GNM_ACTION_DEF(cb_sheet_name)896 static GNM_ACTION_DEF (cb_sheet_name)
897 {
898 	WorkbookControl *wbc = GNM_WBC (wbcg);
899 	Sheet *sheet = wb_control_cur_sheet (wbc);
900 	dialog_sheet_rename (wbcg, sheet);
901 }
902 
GNM_ACTION_DEF(cb_sheet_order)903 static GNM_ACTION_DEF (cb_sheet_order)		{ dialog_sheet_order (wbcg); }
GNM_ACTION_DEF(cb_sheet_resize)904 static GNM_ACTION_DEF (cb_sheet_resize)		{ dialog_sheet_resize (wbcg); }
GNM_ACTION_DEF(cb_format_cells)905 static GNM_ACTION_DEF (cb_format_cells)		{ dialog_cell_format (wbcg, FD_CURRENT, 0); }
GNM_ACTION_DEF(cb_format_cells_cond)906 static GNM_ACTION_DEF (cb_format_cells_cond)    { dialog_cell_format_cond (wbcg); }
GNM_ACTION_DEF(cb_autoformat)907 static GNM_ACTION_DEF (cb_autoformat)		{ dialog_autoformat (wbcg); }
GNM_ACTION_DEF(cb_workbook_attr)908 static GNM_ACTION_DEF (cb_workbook_attr)	{ dialog_workbook_attr (wbcg); }
GNM_ACTION_DEF(cb_tools_plugins)909 static GNM_ACTION_DEF (cb_tools_plugins)	{ dialog_plugin_manager (wbcg); }
GNM_ACTION_DEF(cb_tools_autocorrect)910 static GNM_ACTION_DEF (cb_tools_autocorrect)	{ dialog_preferences (wbcg, "Auto Correct"); }
GNM_ACTION_DEF(cb_tools_auto_save)911 static GNM_ACTION_DEF (cb_tools_auto_save)	{ dialog_autosave (wbcg); }
GNM_ACTION_DEF(cb_tools_goal_seek)912 static GNM_ACTION_DEF (cb_tools_goal_seek)	{ dialog_goal_seek (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_tabulate)913 static GNM_ACTION_DEF (cb_tools_tabulate)	{ dialog_tabulate (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_merge)914 static GNM_ACTION_DEF (cb_tools_merge)		{ dialog_merge (wbcg); }
915 
GNM_ACTION_DEF(cb_tools_solver)916 static GNM_ACTION_DEF (cb_tools_solver)         { dialog_solver (wbcg, wbcg_cur_sheet (wbcg)); }
917 
GNM_ACTION_DEF(cb_tools_scenario_add)918 static GNM_ACTION_DEF (cb_tools_scenario_add)	{ dialog_scenario_add (wbcg); }
GNM_ACTION_DEF(cb_tools_scenarios)919 static GNM_ACTION_DEF (cb_tools_scenarios)	{ dialog_scenarios (wbcg); }
GNM_ACTION_DEF(cb_tools_simulation)920 static GNM_ACTION_DEF (cb_tools_simulation)	{ dialog_simulation (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_compare)921 static GNM_ACTION_DEF (cb_tools_compare)	{ dialog_sheet_compare (wbcg); }
GNM_ACTION_DEF(cb_tools_anova_one_factor)922 static GNM_ACTION_DEF (cb_tools_anova_one_factor) { dialog_anova_single_factor_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_anova_two_factor)923 static GNM_ACTION_DEF (cb_tools_anova_two_factor) { dialog_anova_two_factor_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_chi_square_independence)924 static GNM_ACTION_DEF (cb_tools_chi_square_independence) { dialog_chi_square_tool (wbcg, wbcg_cur_sheet (wbcg), TRUE); }
GNM_ACTION_DEF(cb_tools_chi_square_homogeneity)925 static GNM_ACTION_DEF (cb_tools_chi_square_homogeneity) { dialog_chi_square_tool (wbcg, wbcg_cur_sheet (wbcg), FALSE); }
GNM_ACTION_DEF(cb_tools_correlation)926 static GNM_ACTION_DEF (cb_tools_correlation)	{ dialog_correlation_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_covariance)927 static GNM_ACTION_DEF (cb_tools_covariance)	{ dialog_covariance_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_desc_statistics)928 static GNM_ACTION_DEF (cb_tools_desc_statistics) { dialog_descriptive_stat_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_exp_smoothing)929 static GNM_ACTION_DEF (cb_tools_exp_smoothing)	{ dialog_exp_smoothing_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_average)930 static GNM_ACTION_DEF (cb_tools_average)	{ dialog_average_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_fourier)931 static GNM_ACTION_DEF (cb_tools_fourier)	{ dialog_fourier_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_frequency)932 static GNM_ACTION_DEF (cb_tools_frequency)	{ dialog_frequency_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_histogram)933 static GNM_ACTION_DEF (cb_tools_histogram)	{ dialog_histogram_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_kaplan_meier)934 static GNM_ACTION_DEF (cb_tools_kaplan_meier)	{ dialog_kaplan_meier_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_normality_tests)935 static GNM_ACTION_DEF (cb_tools_normality_tests){ dialog_normality_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_one_mean_test)936 static GNM_ACTION_DEF (cb_tools_one_mean_test)	{ dialog_one_mean_test_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_principal_components)937 static GNM_ACTION_DEF (cb_tools_principal_components)	{ dialog_principal_components_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_ranking)938 static GNM_ACTION_DEF (cb_tools_ranking)	{ dialog_ranking_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_regression)939 static GNM_ACTION_DEF (cb_tools_regression)	{ dialog_regression_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_sampling)940 static GNM_ACTION_DEF (cb_tools_sampling)	{ dialog_sampling_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_sign_test_one_median)941 static GNM_ACTION_DEF (cb_tools_sign_test_one_median)	{ dialog_sign_test_tool (wbcg, wbcg_cur_sheet (wbcg), SIGNTEST); }
GNM_ACTION_DEF(cb_tools_sign_test_two_medians)942 static GNM_ACTION_DEF (cb_tools_sign_test_two_medians)	{ dialog_sign_test_two_tool (wbcg, wbcg_cur_sheet (wbcg), SIGNTEST); }
GNM_ACTION_DEF(cb_tools_wilcoxon_signed_rank_one_median)943 static GNM_ACTION_DEF (cb_tools_wilcoxon_signed_rank_one_median)	{ dialog_sign_test_tool (wbcg, wbcg_cur_sheet (wbcg), SIGNTEST_WILCOXON); }
GNM_ACTION_DEF(cb_tools_wilcoxon_signed_rank_two_medians)944 static GNM_ACTION_DEF (cb_tools_wilcoxon_signed_rank_two_medians)	{ dialog_sign_test_two_tool (wbcg, wbcg_cur_sheet (wbcg), SIGNTEST_WILCOXON); }
GNM_ACTION_DEF(cb_tools_wilcoxon_mann_whitney)945 static GNM_ACTION_DEF (cb_tools_wilcoxon_mann_whitney)	{ dialog_wilcoxon_m_w_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_ttest_paired)946 static GNM_ACTION_DEF (cb_tools_ttest_paired)	{ dialog_ttest_tool (wbcg, wbcg_cur_sheet (wbcg), TTEST_PAIRED); }
GNM_ACTION_DEF(cb_tools_ttest_equal_var)947 static GNM_ACTION_DEF (cb_tools_ttest_equal_var) { dialog_ttest_tool (wbcg, wbcg_cur_sheet (wbcg), TTEST_UNPAIRED_EQUALVARIANCES); }
GNM_ACTION_DEF(cb_tools_ttest_unequal_var)948 static GNM_ACTION_DEF (cb_tools_ttest_unequal_var) { dialog_ttest_tool (wbcg, wbcg_cur_sheet (wbcg), TTEST_UNPAIRED_UNEQUALVARIANCES); }
GNM_ACTION_DEF(cb_tools_ztest)949 static GNM_ACTION_DEF (cb_tools_ztest)		{ dialog_ttest_tool (wbcg, wbcg_cur_sheet (wbcg), TTEST_ZTEST); }
GNM_ACTION_DEF(cb_tools_ftest)950 static GNM_ACTION_DEF (cb_tools_ftest)		{ dialog_ftest_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_random_generator_uncorrelated)951 static GNM_ACTION_DEF (cb_tools_random_generator_uncorrelated) { dialog_random_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_tools_random_generator_correlated)952 static GNM_ACTION_DEF (cb_tools_random_generator_correlated) { dialog_random_cor_tool (wbcg, wbcg_cur_sheet (wbcg)); }
GNM_ACTION_DEF(cb_data_sort)953 static GNM_ACTION_DEF (cb_data_sort)		{ dialog_cell_sort (wbcg); }
GNM_ACTION_DEF(cb_data_shuffle)954 static GNM_ACTION_DEF (cb_data_shuffle)		{ dialog_shuffle (wbcg); }
GNM_ACTION_DEF(cb_data_import_text)955 static GNM_ACTION_DEF (cb_data_import_text)	{ gui_file_open
956 		(wbcg, GNM_FILE_OPEN_STYLE_IMPORT, "Gnumeric_stf:stf_assistant"); }
GNM_ACTION_DEF(cb_data_import_other)957 static GNM_ACTION_DEF (cb_data_import_other)	{ gui_file_open
958 		(wbcg, GNM_FILE_OPEN_STYLE_IMPORT, NULL); }
959 
GNM_ACTION_DEF(cb_auto_filter)960 static GNM_ACTION_DEF (cb_auto_filter)          { cmd_autofilter_add_remove (GNM_WBC (wbcg)); }
GNM_ACTION_DEF(cb_show_all)961 static GNM_ACTION_DEF (cb_show_all)		{ filter_show_all (GNM_WBC (wbcg)); }
GNM_ACTION_DEF(cb_data_filter)962 static GNM_ACTION_DEF (cb_data_filter)		{ dialog_advanced_filter (wbcg); }
GNM_ACTION_DEF(cb_data_validate)963 static GNM_ACTION_DEF (cb_data_validate)	{ dialog_cell_format (wbcg, FD_VALIDATION,
964 								      (1 << FD_VALIDATION) | (1 << FD_INPUT_MSG)); }
GNM_ACTION_DEF(cb_data_text_to_columns)965 static GNM_ACTION_DEF (cb_data_text_to_columns) { stf_text_to_columns (GNM_WBC (wbcg), GO_CMD_CONTEXT (wbcg)); }
GNM_ACTION_DEF(cb_data_consolidate)966 static GNM_ACTION_DEF (cb_data_consolidate)	{ dialog_consolidate (wbcg); }
GNM_ACTION_DEF(cb_data_table)967 static GNM_ACTION_DEF (cb_data_table)		{ dialog_data_table (wbcg); }
GNM_ACTION_DEF(cb_data_slicer_create)968 static GNM_ACTION_DEF (cb_data_slicer_create)	{ dialog_data_slicer (wbcg, TRUE); }
GNM_ACTION_DEF(cb_data_slicer_refresh)969 static GNM_ACTION_DEF (cb_data_slicer_refresh)	{ cmd_slicer_refresh (GNM_WBC (wbcg)); }
GNM_ACTION_DEF(cb_data_slicer_edit)970 static GNM_ACTION_DEF (cb_data_slicer_edit)	{ dialog_data_slicer (wbcg, FALSE); }
GNM_ACTION_DEF(cb_data_export)971 static GNM_ACTION_DEF (cb_data_export)	        { gui_file_save_as
972 		(wbcg, wb_control_view (GNM_WBC (wbcg)),
973 		 GNM_FILE_SAVE_AS_STYLE_EXPORT, NULL); }
GNM_ACTION_DEF(cb_data_export_text)974 static GNM_ACTION_DEF (cb_data_export_text)	        { gui_file_save_as
975 		(wbcg, wb_control_view (GNM_WBC (wbcg)),
976 		 GNM_FILE_SAVE_AS_STYLE_EXPORT, "Gnumeric_stf:stf_assistant"); }
GNM_ACTION_DEF(cb_data_export_csv)977 static GNM_ACTION_DEF (cb_data_export_csv)	        { gui_file_save_as
978 		(wbcg, wb_control_view (GNM_WBC (wbcg)),
979 		 GNM_FILE_SAVE_AS_STYLE_EXPORT, "Gnumeric_stf:stf_csv"); }
GNM_ACTION_DEF(cb_data_export_repeat)980 static GNM_ACTION_DEF (cb_data_export_repeat)	{ gui_file_export_repeat (wbcg); }
981 
982 static void
hide_show_detail_real(WBCGtk * wbcg,gboolean is_cols,gboolean show)983 hide_show_detail_real (WBCGtk *wbcg, gboolean is_cols, gboolean show)
984 {
985 	WorkbookControl *wbc = GNM_WBC (wbcg);
986 	SheetView *sv = wb_control_cur_sheet_view (wbc);
987 	char const *operation = show ? _("Show Detail") : _("Hide Detail");
988 	GnmRange const *r = selection_first_range (sv, GO_CMD_CONTEXT (wbc),
989 						operation);
990 
991 	/* This operation can only be performed on a whole existing group */
992 	if (sheet_colrow_can_group (sv_sheet (sv), r, is_cols)) {
993 		go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbc), operation,
994 			_("can only be performed on an existing group"));
995 		return;
996 	}
997 
998 	cmd_selection_colrow_hide (wbc, is_cols, show);
999 }
1000 
1001 static void
hide_show_detail(WBCGtk * wbcg,gboolean show)1002 hide_show_detail (WBCGtk *wbcg, gboolean show)
1003 {
1004 	WorkbookControl *wbc = GNM_WBC (wbcg);
1005 	SheetView *sv = wb_control_cur_sheet_view (wbc);
1006 	Sheet const *sheet = sv_sheet (sv);
1007 	char const *operation = show ? _("Show Detail") : _("Hide Detail");
1008 	GnmRange const *r = selection_first_range (sv,
1009 		GO_CMD_CONTEXT (wbc), operation);
1010 	gboolean is_cols;
1011 
1012 	/* We only operate on a single selection */
1013 	if (r == NULL)
1014 		return;
1015 
1016 	/* Do we need to ask the user what he/she wants to group/ungroup? */
1017 	if (range_is_full (r, sheet, TRUE) ^ range_is_full (r, sheet, FALSE))
1018 		is_cols = !range_is_full (r, sheet, TRUE);
1019 	else {
1020 		dialog_col_row (wbcg, operation,
1021 			(ColRowCallback_t) hide_show_detail_real,
1022 			GINT_TO_POINTER (show));
1023 		return;
1024 	}
1025 
1026 	hide_show_detail_real (wbcg, is_cols, show);
1027 }
1028 
1029 static void
group_ungroup_colrow(WBCGtk * wbcg,gboolean group)1030 group_ungroup_colrow (WBCGtk *wbcg, gboolean group)
1031 {
1032 	WorkbookControl *wbc = GNM_WBC (wbcg);
1033 	SheetView *sv = wb_control_cur_sheet_view (wbc);
1034 	Sheet const *sheet = sv_sheet (sv);
1035 	char const *operation = group ? _("Group") : _("Ungroup");
1036 	GnmRange const *r = selection_first_range (sv,
1037 		GO_CMD_CONTEXT (wbc), operation);
1038 	gboolean is_cols;
1039 
1040 	/* We only operate on a single selection */
1041 	if (r == NULL)
1042 		return;
1043 
1044 	/* Do we need to ask the user what he/she wants to group/ungroup? */
1045 	if (range_is_full (r, sheet, TRUE) ^ range_is_full (r, sheet, FALSE))
1046 		is_cols = !range_is_full (r, sheet, TRUE);
1047 	else {
1048 		dialog_col_row (wbcg, operation,
1049 			(ColRowCallback_t) cmd_selection_group,
1050 			GINT_TO_POINTER (group));
1051 		return;
1052 	}
1053 
1054 	cmd_selection_group (wbc, is_cols, group);
1055 }
1056 
GNM_ACTION_DEF(cb_data_hide_detail)1057 static GNM_ACTION_DEF (cb_data_hide_detail)	{ hide_show_detail (wbcg, FALSE); }
GNM_ACTION_DEF(cb_data_show_detail)1058 static GNM_ACTION_DEF (cb_data_show_detail)	{ hide_show_detail (wbcg, TRUE); }
GNM_ACTION_DEF(cb_data_group)1059 static GNM_ACTION_DEF (cb_data_group)		{ group_ungroup_colrow (wbcg, TRUE); }
GNM_ACTION_DEF(cb_data_ungroup)1060 static GNM_ACTION_DEF (cb_data_ungroup)		{ group_ungroup_colrow (wbcg, FALSE); }
1061 
GNM_ACTION_DEF(cb_help_function)1062 static GNM_ACTION_DEF (cb_help_function)	{ dialog_function_select_help (wbcg); }
GNM_ACTION_DEF(cb_help_docs)1063 static GNM_ACTION_DEF (cb_help_docs)
1064 {
1065 	char   *argv[] = { NULL, NULL, NULL };
1066 	GError *err = NULL;
1067 
1068 #ifndef G_OS_WIN32
1069 	argv[0] = (char *)"yelp";
1070 	argv[1] = (char *)"help:gnumeric";
1071 	g_spawn_async (NULL, argv, NULL,
1072 		       G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL
1073 		       | G_SPAWN_STDERR_TO_DEV_NULL,
1074 		       NULL, NULL, NULL, &err);
1075 #else
1076 	/* TODO : Should really start in same directory as the gspawn-* helpers
1077 	 * are installed in case they are not in the path */
1078 	argv[0] = (char *)"hh";
1079 	argv[1] = g_build_filename (gnm_sys_data_dir (), "doc", "C",
1080 			"gnumeric.chm", NULL);
1081 	g_spawn_async (NULL, argv, NULL,
1082 		       G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL
1083 		       | G_SPAWN_STDERR_TO_DEV_NULL,
1084 		       NULL, NULL, NULL, &err);
1085 	g_free (argv[1]);
1086 #endif
1087 	if (NULL != err) {
1088 		GOErrorInfo *ei = go_error_info_new_printf
1089 			(_("Unable to start the help browser (%s).\n"
1090 			   "The system error message is: \n\n%s"),
1091 			 argv[0], err->message);
1092 		go_cmd_context_error_info (GO_CMD_CONTEXT (wbcg), ei);
1093 		g_error_free (err);
1094 		g_free (ei);
1095 	}
1096 }
1097 
1098 static void
show_url(WBCGtk * wbcg,const char * url)1099 show_url (WBCGtk *wbcg, const char *url)
1100 {
1101 	GError *err;
1102 	GdkScreen *screen;
1103 
1104 	screen = gtk_window_get_screen (wbcg_toplevel (wbcg));
1105 	err = go_gtk_url_show (url, screen);
1106 	if (err != NULL) {
1107 		go_cmd_context_error (GO_CMD_CONTEXT (wbcg), err);
1108 		g_error_free (err);
1109 	}
1110 }
1111 
1112 
GNM_ACTION_DEF(cb_help_web)1113 static GNM_ACTION_DEF (cb_help_web)
1114 {
1115 	show_url (wbcg, "http://www.gnumeric.org/");
1116 }
1117 
GNM_ACTION_DEF(cb_help_irc)1118 static GNM_ACTION_DEF (cb_help_irc)
1119 {
1120 	show_url (wbcg, "irc://irc.gnome.org/gnumeric");
1121 }
1122 
GNM_ACTION_DEF(cb_help_bug)1123 static GNM_ACTION_DEF (cb_help_bug)
1124 {
1125 	show_url (wbcg, "https://gitlab.gnome.org/GNOME/gnumeric/issues");
1126 }
1127 
GNM_ACTION_DEF(cb_help_about)1128 static GNM_ACTION_DEF (cb_help_about) { dialog_about (wbcg); }
1129 
GNM_ACTION_DEF(cb_autosum)1130 static GNM_ACTION_DEF (cb_autosum)
1131 {
1132 	GtkEntry *entry;
1133 	gchar const *txt;
1134 
1135 	if (wbcg_is_editing (wbcg))
1136 		return;
1137 
1138 	entry = wbcg_get_entry (wbcg);
1139 	txt = gtk_entry_get_text (entry);
1140 	if (strncmp (txt, "=sum(", 5)) {
1141 		if (!wbcg_edit_start (wbcg, TRUE, TRUE))
1142 			return; /* attempt to edit failed */
1143 		gtk_entry_set_text (entry, "=sum()");
1144 		gtk_editable_set_position (GTK_EDITABLE (entry), 5);
1145 	} else {
1146 		if (!wbcg_edit_start (wbcg, FALSE, TRUE))
1147 			return; /* attempt to edit failed */
1148 
1149 		/*
1150 		 * FIXME : This is crap!
1151 		 * When the function druid is more complete use that.
1152 		 */
1153 		gtk_editable_set_position (GTK_EDITABLE (entry),
1154 					   gtk_entry_get_text_length (entry)-1);
1155 	}
1156 }
1157 
GNM_ACTION_DEF(cb_insert_image)1158 static GNM_ACTION_DEF (cb_insert_image)
1159 {
1160 	char *uri = go_gtk_select_image (wbcg_toplevel (wbcg), NULL);
1161 
1162 	if (uri) {
1163 		GError *err = NULL;
1164 		GsfInput *input = go_file_open (uri, &err);
1165 
1166 		if (input != NULL) {
1167 			unsigned len = gsf_input_size (input);
1168 			guint8 const *data = gsf_input_read (input, len, NULL);
1169 			SheetObjectImage *soi = g_object_new (GNM_SO_IMAGE_TYPE, NULL);
1170 			sheet_object_image_set_image (soi, "", data, len);
1171 			wbcg_insert_object (wbcg, GNM_SO (soi));
1172 			g_object_unref (input);
1173 		} else
1174 			go_cmd_context_error (GO_CMD_CONTEXT (wbcg), err);
1175 
1176 		g_free (uri);
1177 	}
1178 }
1179 
GNM_ACTION_DEF(cb_insert_hyperlink)1180 static GNM_ACTION_DEF (cb_insert_hyperlink)	{ dialog_hyperlink (wbcg, GNM_SHEET_CONTROL (wbcg_cur_scg (wbcg))); }
GNM_ACTION_DEF(cb_formula_guru)1181 static GNM_ACTION_DEF (cb_formula_guru)		{ dialog_formula_guru (wbcg, NULL); }
GNM_ACTION_DEF(cb_insert_sort_ascending)1182 static GNM_ACTION_DEF (cb_insert_sort_ascending) { workbook_cmd_wrap_sort (GNM_WBC (wbcg), 1);}
GNM_ACTION_DEF(cb_insert_sort_descending)1183 static GNM_ACTION_DEF (cb_insert_sort_descending){ workbook_cmd_wrap_sort (GNM_WBC (wbcg), 0);}
1184 
1185 static void
sort_by_rows(WBCGtk * wbcg,gboolean descending)1186 sort_by_rows (WBCGtk *wbcg, gboolean descending)
1187 {
1188 	SheetView *sv;
1189 	GnmRange *sel;
1190 	GnmRange tmp_ns ={{0,0},{0,0}}, tmp_s ={{0,0},{0,0}};
1191 	GnmSortData *data;
1192 	GnmSortClause *clause;
1193 	int numclause, i;
1194 	GSList *l;
1195 	int cnt_singletons = 0, cnt_non_singletons = 0;
1196 	gboolean top_to_bottom = TRUE;
1197 	gboolean not_acceptable = FALSE;
1198 
1199 	g_return_if_fail (GNM_IS_WBC_GTK (wbcg));
1200 
1201 	sv = wb_control_cur_sheet_view (GNM_WBC (wbcg));
1202 	for (l = sv->selections; l != NULL; l = l->next) {
1203 		GnmRange const *r = l->data;
1204 		if (range_is_singleton (r)) {
1205 			cnt_singletons++;
1206 			tmp_s = *r;
1207 		} else {
1208 			cnt_non_singletons++;
1209 			tmp_ns = *r;
1210 		}
1211 	}
1212 
1213 	not_acceptable = (cnt_non_singletons > 1 ||
1214 			  (cnt_non_singletons == 0 && cnt_singletons > 1));
1215 
1216 	if (!not_acceptable && cnt_singletons > 0 && cnt_non_singletons == 1) {
1217 		gboolean first = TRUE;
1218 		for (l = sv->selections; l != NULL; l = l->next) {
1219 			GnmRange const *r = l->data;
1220 			gboolean t_b = FALSE, l_r = FALSE;
1221 
1222 			if (!range_is_singleton (r))
1223 				continue;
1224 			t_b = r->start.col >= tmp_ns.start.col &&
1225 				r->end.col <= tmp_ns.end.col;
1226 			l_r = r->start.row >= tmp_ns.start.row &&
1227 				r->end.row <= tmp_ns.end.row;
1228 			if (!t_b && !l_r) {
1229 				not_acceptable = TRUE;
1230 				break;
1231 			}
1232 			if (!t_b || !l_r) {
1233 				if (first) {
1234 					first = FALSE;
1235 					top_to_bottom = t_b;
1236 				} else {
1237 					if ((top_to_bottom && !t_b) ||
1238 					    (!top_to_bottom && !l_r)) {
1239 						not_acceptable = TRUE;
1240 						break;
1241 					}
1242 				}
1243 			}
1244 		}
1245 	}
1246 
1247 	if (not_acceptable) {
1248 		GError *msg = g_error_new (go_error_invalid(), 0,
1249 					   _("%s does not support multiple ranges"),
1250 					   _("Sort"));
1251 		go_cmd_context_error (GO_CMD_CONTEXT (wbcg), msg);
1252 		g_error_free (msg);
1253 		return;
1254 	}
1255 
1256 	if (cnt_singletons == 1 && cnt_non_singletons == 0) {
1257 		Sheet *sheet = sv_sheet (sv);
1258 
1259 		sel = g_new0 (GnmRange, 1);
1260 		range_init_full_sheet (sel, sheet);
1261 		sel->start.row = tmp_s.start.row;
1262 		range_clip_to_finite (sel, sheet);
1263 		numclause = 1;
1264 		clause = g_new0 (GnmSortClause, 1);
1265 		clause[0].offset = tmp_s.start.col - sel->start.col;
1266 		clause[0].asc = descending;
1267 		clause[0].cs = gnm_conf_get_core_sort_default_by_case ();
1268 		clause[0].val = TRUE;
1269 	} else if (cnt_singletons == 0) {
1270 		sel = gnm_range_dup (&tmp_ns);
1271 		range_clip_to_finite (sel, sv_sheet (sv));
1272 
1273 		numclause = range_width (sel);
1274 		clause = g_new0 (GnmSortClause, numclause);
1275 		for (i = 0; i < numclause; i++) {
1276 			clause[i].offset = i;
1277 			clause[i].asc = descending;
1278 			clause[i].cs = gnm_conf_get_core_sort_default_by_case ();
1279 			clause[i].val = TRUE;
1280 		}
1281 	} else /* cnt_singletons > 0 &&  cnt_non_singletons == 1*/ {
1282 		sel = gnm_range_dup (&tmp_ns);
1283 		range_clip_to_finite (sel, sv_sheet (sv));
1284 		numclause = cnt_singletons;
1285 		clause = g_new0 (GnmSortClause, numclause);
1286 		i = numclause - 1;
1287 		for (l = sv->selections; l != NULL; l = l->next) {
1288 			GnmRange const *r = l->data;
1289 			if (!range_is_singleton (r))
1290 				continue;
1291 			if (i >= 0) {
1292 				clause[i].offset = (top_to_bottom) ?
1293 					r->start.col - sel->start.col
1294 					: r->start.row - sel->start.row;
1295 				clause[i].asc = descending;
1296 				clause[i].cs = gnm_conf_get_core_sort_default_by_case ();
1297 				clause[i].val = TRUE;
1298 			}
1299 			i--;
1300 		}
1301 	}
1302 
1303 	data = g_new (GnmSortData, 1);
1304 	data->sheet = sv_sheet (sv);
1305 	data->range = sel;
1306 	data->num_clause = numclause;
1307 	data->clauses = clause;
1308 	data->locale = NULL;
1309 
1310 	data->retain_formats = gnm_conf_get_core_sort_default_retain_formats ();
1311 
1312 	/* Hard code sorting by row.  I would prefer not to, but user testing
1313 	 * indicates
1314 	 * - that the button should always does the same things
1315 	 * - that the icon matches the behavior
1316 	 * - XL does this.
1317 	 */
1318 
1319 	/* Note that if the user specified rows by singleton selection we switch */
1320 	/* to column sorting */
1321 	data->top = top_to_bottom;
1322 
1323 	if (sheet_range_has_heading (data->sheet, data->range, data->top, FALSE))
1324 		data->range->start.row += 1;
1325 
1326 	cmd_sort (GNM_WBC (wbcg), data);
1327 }
GNM_ACTION_DEF(cb_sort_ascending)1328 static GNM_ACTION_DEF (cb_sort_ascending)  { sort_by_rows (wbcg, FALSE); }
GNM_ACTION_DEF(cb_sort_descending)1329 static GNM_ACTION_DEF (cb_sort_descending) { sort_by_rows (wbcg, TRUE); }
1330 
1331 static void
cb_add_graph(GogGraph * graph,gpointer wbcg)1332 cb_add_graph (GogGraph *graph, gpointer wbcg)
1333 {
1334 	GnmGraphDataClosure *data = (GnmGraphDataClosure *) g_object_get_data (G_OBJECT (graph), "data-closure");
1335 	if (data) {
1336 		if (data->new_sheet) {
1337 			WorkbookControl *wbc = GNM_WBC (wbcg);
1338 			Sheet *sheet = wb_control_cur_sheet (wbc);
1339 			WorkbookSheetState *old_state = workbook_sheet_state_new (wb_control_get_workbook (wbc));
1340 			Sheet *new_sheet = workbook_sheet_add_with_type (
1341 				wb_control_get_workbook (wbc),
1342 				GNM_SHEET_OBJECT, -1,
1343 				gnm_sheet_get_max_cols (sheet),
1344 				gnm_sheet_get_max_rows (sheet));
1345 			SheetObject *sog = sheet_object_graph_new (graph);
1346 			print_info_set_paper_orientation (new_sheet->print_info, GTK_PAGE_ORIENTATION_LANDSCAPE);
1347 			sheet_object_set_sheet (sog, new_sheet);
1348 			wb_view_sheet_focus (wb_control_view (wbc), new_sheet);
1349 			cmd_reorganize_sheets (wbc, old_state, sheet);
1350 			g_object_unref (sog);
1351 			return;
1352 		}
1353 	}
1354 	wbcg_insert_object (WBC_GTK (wbcg), sheet_object_graph_new (graph));
1355 }
1356 
GNM_ACTION_DEF(cb_launch_chart_guru)1357 static GNM_ACTION_DEF (cb_launch_chart_guru)
1358 {
1359 	GClosure *closure = g_cclosure_new (G_CALLBACK (cb_add_graph),
1360 					    wbcg, NULL);
1361 	sheet_object_graph_guru (wbcg, NULL, closure);
1362 	g_closure_sink (closure);
1363 }
1364 
1365 static void
cb_add_component_new(GOComponent * component,gpointer wbcg)1366 cb_add_component_new (GOComponent *component, gpointer wbcg)
1367 {
1368 	wbcg_insert_object (WBC_GTK (wbcg), sheet_object_component_new (component));
1369 }
1370 
1371 static void
component_changed_cb(GOComponent * component,gpointer data)1372 component_changed_cb (GOComponent *component, gpointer data)
1373 {
1374 	/* we nedd to ref the component otherwise it will be destroyed when
1375 	 it's editor window will be deleted */
1376 	g_object_ref (component);
1377 	cb_add_component_new (component, data);
1378 }
1379 
GNM_ACTION_DEF(cb_launch_go_component_new)1380 static GNM_ACTION_DEF (cb_launch_go_component_new)
1381 {
1382 	gchar const *mime_type;
1383 	gint result;
1384 	GtkWidget *dialog = go_component_mime_dialog_new ();
1385 	result = gtk_dialog_run (GTK_DIALOG (dialog));
1386 	if (result == GTK_RESPONSE_OK) {
1387 		mime_type = go_component_mime_dialog_get_mime_type ((GOComponentMimeDialog *) dialog);
1388 		if (mime_type) {
1389 			GtkWindow *win;
1390 			GOComponent *component = go_component_new_by_mime_type (mime_type);
1391 			if (component) {
1392 				g_signal_connect (G_OBJECT (component), "changed", G_CALLBACK (component_changed_cb), wbcg);
1393 				win = go_component_edit (component);
1394 				gtk_window_set_transient_for (win, GTK_WINDOW (wbcg_toplevel (wbcg)));
1395 				g_object_set_data_full (G_OBJECT (win), "component", component, g_object_unref);
1396 			}
1397 		}
1398 	}
1399 	gtk_widget_destroy (dialog);
1400 }
1401 
GNM_ACTION_DEF(cb_launch_go_component_from_file)1402 static GNM_ACTION_DEF (cb_launch_go_component_from_file)
1403 {
1404 	GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Choose object file"),
1405 	                                              GTK_WINDOW (wbcg_toplevel (wbcg)),
1406 	                                              GTK_FILE_CHOOSER_ACTION_OPEN,
1407 	                                              GNM_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1408 	                                              GNM_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1409 	                                              NULL);
1410 	go_components_add_filter (GTK_FILE_CHOOSER (dlg));
1411 	if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_ACCEPT) {
1412 		char *uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dlg));
1413 		GOComponent *component;
1414 		component = go_component_new_from_uri (uri);
1415 		g_free (uri);
1416 		if (component)
1417 			wbcg_insert_object (WBC_GTK (wbcg), sheet_object_component_new (component));
1418 	}
1419 	gtk_widget_destroy (dlg);
1420 }
1421 
1422 static void
create_object(WBCGtk * wbcg,GType t,char const * first_property_name,...)1423 create_object (WBCGtk *wbcg, GType t,
1424 	       char const *first_property_name,
1425 	       ...)
1426 {
1427 	va_list	args;
1428 	va_start (args, first_property_name);
1429 	wbcg_insert_object (wbcg, (SheetObject *)
1430 		g_object_new_valist (t, first_property_name, args));
1431 	va_end (args);
1432 }
1433 
GNM_ACTION_DEF(cmd_create_frame)1434 static GNM_ACTION_DEF (cmd_create_frame)
1435 	{ create_object (wbcg, sheet_widget_frame_get_type(), NULL); }
GNM_ACTION_DEF(cmd_create_button)1436 static GNM_ACTION_DEF (cmd_create_button)
1437 	{ create_object (wbcg, sheet_widget_button_get_type(), NULL); }
GNM_ACTION_DEF(cmd_create_radiobutton)1438 static GNM_ACTION_DEF (cmd_create_radiobutton)
1439 	{ create_object (wbcg, sheet_widget_radio_button_get_type(), NULL); }
GNM_ACTION_DEF(cmd_create_scrollbar)1440 static GNM_ACTION_DEF (cmd_create_scrollbar)
1441 	{ create_object (wbcg, sheet_widget_scrollbar_get_type(), NULL); }
GNM_ACTION_DEF(cmd_create_slider)1442 static GNM_ACTION_DEF (cmd_create_slider)
1443 	{ create_object (wbcg, sheet_widget_slider_get_type(), NULL); }
GNM_ACTION_DEF(cmd_create_spinbutton)1444 static GNM_ACTION_DEF (cmd_create_spinbutton)
1445 	{ create_object (wbcg, sheet_widget_spinbutton_get_type(), NULL); }
GNM_ACTION_DEF(cmd_create_checkbox)1446 static GNM_ACTION_DEF (cmd_create_checkbox)
1447 	{ create_object (wbcg, sheet_widget_checkbox_get_type(), NULL); }
GNM_ACTION_DEF(cmd_create_list)1448 static GNM_ACTION_DEF (cmd_create_list)
1449 	{ create_object (wbcg, sheet_widget_list_get_type(), NULL); }
GNM_ACTION_DEF(cmd_create_combo)1450 static GNM_ACTION_DEF (cmd_create_combo)
1451 	{ create_object (wbcg, sheet_widget_combo_get_type(), NULL); }
GNM_ACTION_DEF(cmd_create_line)1452 static GNM_ACTION_DEF (cmd_create_line)
1453 	{ create_object (wbcg, GNM_SO_LINE_TYPE, NULL); }
GNM_ACTION_DEF(cmd_create_arrow)1454 static GNM_ACTION_DEF (cmd_create_arrow) {
1455 	GOArrow arrow;
1456 	go_arrow_init_kite (&arrow, 8., 10., 3.);
1457 	create_object (wbcg, GNM_SO_LINE_TYPE, "end-arrow", &arrow, NULL);
1458 }
GNM_ACTION_DEF(cmd_create_rectangle)1459 static GNM_ACTION_DEF (cmd_create_rectangle)
1460 	{ create_object (wbcg, GNM_SO_FILLED_TYPE, NULL); }
GNM_ACTION_DEF(cmd_create_ellipse)1461 static GNM_ACTION_DEF (cmd_create_ellipse)
1462 	{ create_object (wbcg, GNM_SO_FILLED_TYPE, "is-oval", TRUE, NULL); }
1463 
1464 /*****************************************************************************/
1465 static void
wbcg_set_selection_halign(WBCGtk * wbcg,GnmHAlign halign)1466 wbcg_set_selection_halign (WBCGtk *wbcg, GnmHAlign halign)
1467 {
1468 	WorkbookControl *wbc = GNM_WBC (wbcg);
1469 	WorkbookView	*wb_view;
1470 	GnmStyle *style;
1471 
1472 	if (wbcg->updating_ui)
1473 		return;
1474 
1475 	/* This is a toggle button.  If we are already enabled
1476 	 * then revert to general */
1477 	wb_view = wb_control_view (wbc);
1478 	if (gnm_style_get_align_h (wb_view->current_style) == halign)
1479 		halign = GNM_HALIGN_GENERAL;
1480 
1481 	style = gnm_style_new ();
1482 	gnm_style_set_align_h (style, halign);
1483 	cmd_selection_format (wbc, style, NULL, _("Set Horizontal Alignment"));
1484 }
GNM_ACTION_DEF(cb_align_left)1485 static GNM_ACTION_DEF (cb_align_left)
1486 	{ wbcg_set_selection_halign (wbcg, GNM_HALIGN_LEFT); }
GNM_ACTION_DEF(cb_align_right)1487 static GNM_ACTION_DEF (cb_align_right)
1488 	{ wbcg_set_selection_halign (wbcg, GNM_HALIGN_RIGHT); }
GNM_ACTION_DEF(cb_align_center)1489 static GNM_ACTION_DEF (cb_align_center)
1490 	{ wbcg_set_selection_halign (wbcg, GNM_HALIGN_CENTER); }
GNM_ACTION_DEF(cb_center_across_selection)1491 static GNM_ACTION_DEF (cb_center_across_selection)
1492 	{ wbcg_set_selection_halign (wbcg, GNM_HALIGN_CENTER_ACROSS_SELECTION); }
1493 
1494 /*****************************************************************************/
1495 
1496 static void
wbcg_set_selection_valign(WBCGtk * wbcg,GnmVAlign valign)1497 wbcg_set_selection_valign (WBCGtk *wbcg, GnmVAlign valign)
1498 {
1499 	WorkbookControl *wbc = GNM_WBC (wbcg);
1500 	WorkbookView	*wb_view;
1501 	GnmStyle *style;
1502 
1503 	if (wbcg->updating_ui)
1504 		return;
1505 
1506 	/* This is a toggle button.  If we are already enabled
1507 	 * then revert to general */
1508 	wb_view = wb_control_view (wbc);
1509 	if (gnm_style_get_align_v (wb_view->current_style) == valign) {
1510 		if (valign == GNM_VALIGN_BOTTOM)
1511 			return;
1512 		valign = GNM_VALIGN_BOTTOM;
1513 	}
1514 
1515 	style = gnm_style_new ();
1516 	gnm_style_set_align_v (style, valign);
1517 	cmd_selection_format (wbc, style, NULL, _("Set Vertical Alignment"));
1518 }
GNM_ACTION_DEF(cb_align_top)1519 static GNM_ACTION_DEF (cb_align_top)
1520 	{ wbcg_set_selection_valign (wbcg, GNM_VALIGN_TOP); }
GNM_ACTION_DEF(cb_align_vcenter)1521 static GNM_ACTION_DEF (cb_align_vcenter)
1522 	{ wbcg_set_selection_valign (wbcg, GNM_VALIGN_CENTER); }
GNM_ACTION_DEF(cb_align_bottom)1523 static GNM_ACTION_DEF (cb_align_bottom)
1524 	{ wbcg_set_selection_valign (wbcg, GNM_VALIGN_BOTTOM); }
1525 
1526 /*****************************************************************************/
1527 
GNM_ACTION_DEF(cb_merge_and_center)1528 static GNM_ACTION_DEF (cb_merge_and_center)
1529 {
1530 	WorkbookControl *wbc = GNM_WBC (wbcg);
1531 	GSList *range_list = selection_get_ranges (
1532 		wb_control_cur_sheet_view (wbc), FALSE);
1533 	cmd_merge_cells (wbc, wb_control_cur_sheet (wbc), range_list, TRUE);
1534 	range_fragment_free (range_list);
1535 }
1536 
GNM_ACTION_DEF(cb_merge_cells)1537 static GNM_ACTION_DEF (cb_merge_cells)
1538 {
1539 	WorkbookControl *wbc = GNM_WBC (wbcg);
1540 	GSList *range_list = selection_get_ranges (
1541 		wb_control_cur_sheet_view (wbc), FALSE);
1542 	cmd_merge_cells (wbc, wb_control_cur_sheet (wbc), range_list, FALSE);
1543 	range_fragment_free (range_list);
1544 }
1545 
GNM_ACTION_DEF(cb_unmerge_cells)1546 static GNM_ACTION_DEF (cb_unmerge_cells)
1547 {
1548 	WorkbookControl *wbc = GNM_WBC (wbcg);
1549 	GSList *range_list = selection_get_ranges (
1550 		wb_control_cur_sheet_view (wbc), FALSE);
1551 	cmd_unmerge_cells (wbc, wb_control_cur_sheet (wbc), range_list);
1552 	range_fragment_free (range_list);
1553 }
1554 
GNM_ACTION_DEF(cb_view_statusbar)1555 static GNM_ACTION_DEF (cb_view_statusbar)
1556 {
1557 	wbcg_toggle_visibility (wbcg, GTK_TOGGLE_ACTION (a));
1558 }
1559 
1560 /*****************************************************************************/
1561 
1562 static void
toggle_font_attr(WBCGtk * wbcg,GtkToggleAction * act,GnmStyleElement t,unsigned true_val,unsigned false_val)1563 toggle_font_attr (WBCGtk *wbcg, GtkToggleAction *act,
1564 		  GnmStyleElement t, unsigned true_val, unsigned false_val)
1565 {
1566 	WorkbookControl *wbc = GNM_WBC (wbcg);
1567 	GnmStyle *new_style;
1568 	unsigned val;
1569 
1570 	/* If the user did not initiate this action ignore it.
1571 	 * This happens whenever the ui updates and the current cell makes a
1572 	 * change to the toolbar indicators.
1573 	 */
1574 	if (wbcg->updating_ui)
1575 		return;
1576 
1577 	val = gtk_toggle_action_get_active (act) ? true_val : false_val;
1578 	if (wbcg_is_editing (wbcg)) {
1579 		PangoAttribute *attr = NULL;
1580 		switch (t) {
1581 		default:
1582 		case MSTYLE_FONT_BOLD:
1583 			attr = pango_attr_weight_new (val ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
1584 			break;
1585 		case MSTYLE_FONT_ITALIC:
1586 			attr = pango_attr_style_new (val ?  PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
1587 			break;
1588 		case MSTYLE_FONT_UNDERLINE:
1589 			attr = pango_attr_underline_new
1590 				(gnm_translate_underline_to_pango (val));
1591 			break;
1592 		case MSTYLE_FONT_STRIKETHROUGH:
1593 			attr = pango_attr_strikethrough_new (val);
1594 			break;
1595 		case MSTYLE_FONT_SCRIPT:
1596 			switch (val) {
1597 			default:
1598 			case GO_FONT_SCRIPT_STANDARD:
1599 				wbcg_edit_add_markup
1600 					(wbcg, go_pango_attr_superscript_new (FALSE));
1601 				attr = go_pango_attr_subscript_new (FALSE);
1602 				break;
1603 			case GO_FONT_SCRIPT_SUPER:
1604 				attr = go_pango_attr_superscript_new (TRUE);
1605 				break;
1606 			case GO_FONT_SCRIPT_SUB:
1607 				attr = go_pango_attr_subscript_new (TRUE);
1608 				break;
1609 			}
1610 			break;
1611 		}
1612 		wbcg_edit_add_markup (wbcg, attr);
1613 		return;
1614 	}
1615 
1616 	new_style = gnm_style_new ();
1617 	switch (t) {
1618 	default:
1619 	case MSTYLE_FONT_BOLD:		gnm_style_set_font_bold (new_style, val); break;
1620 	case MSTYLE_FONT_ITALIC:	gnm_style_set_font_italic (new_style, val); break;
1621 	case MSTYLE_FONT_UNDERLINE:	gnm_style_set_font_uline (new_style, val); break;
1622 	case MSTYLE_FONT_STRIKETHROUGH: gnm_style_set_font_strike (new_style, val); break;
1623 	case MSTYLE_FONT_SCRIPT:	gnm_style_set_font_script (new_style, val); break;
1624 	}
1625 
1626 	cmd_selection_format_toggle_font_style (wbc, new_style, t);
1627 }
1628 
cb_font_bold(GtkToggleAction * act,WBCGtk * wbcg)1629 static void cb_font_bold (GtkToggleAction *act, WBCGtk *wbcg)
1630 	{ toggle_font_attr (wbcg, act, MSTYLE_FONT_BOLD, TRUE, FALSE); }
cb_font_italic(GtkToggleAction * act,WBCGtk * wbcg)1631 static void cb_font_italic (GtkToggleAction *act, WBCGtk *wbcg)
1632 	{ toggle_font_attr (wbcg, act, MSTYLE_FONT_ITALIC, TRUE, FALSE); }
cb_font_underline(GtkToggleAction * act,WBCGtk * wbcg)1633 static void cb_font_underline (GtkToggleAction *act, WBCGtk *wbcg)
1634 	{ toggle_font_attr (wbcg, act, MSTYLE_FONT_UNDERLINE, UNDERLINE_SINGLE, UNDERLINE_NONE); }
cb_font_double_underline(GtkToggleAction * act,WBCGtk * wbcg)1635 static void cb_font_double_underline (GtkToggleAction *act, WBCGtk *wbcg)
1636 	{ toggle_font_attr (wbcg, act, MSTYLE_FONT_UNDERLINE, UNDERLINE_DOUBLE, UNDERLINE_NONE); }
cb_font_underline_low(GtkToggleAction * act,WBCGtk * wbcg)1637 static void cb_font_underline_low (GtkToggleAction *act, WBCGtk *wbcg)
1638 	{ toggle_font_attr (wbcg, act, MSTYLE_FONT_UNDERLINE, UNDERLINE_SINGLE_LOW, UNDERLINE_NONE); }
cb_font_double_underline_low(GtkToggleAction * act,WBCGtk * wbcg)1639 static void cb_font_double_underline_low (GtkToggleAction *act, WBCGtk *wbcg)
1640 	{ toggle_font_attr (wbcg, act, MSTYLE_FONT_UNDERLINE, UNDERLINE_DOUBLE_LOW, UNDERLINE_NONE); }
cb_font_strikethrough(GtkToggleAction * act,WBCGtk * wbcg)1641 static void cb_font_strikethrough (GtkToggleAction *act, WBCGtk *wbcg)
1642 	{ toggle_font_attr (wbcg, act, MSTYLE_FONT_STRIKETHROUGH, TRUE, FALSE); }
cb_font_subscript(GtkToggleAction * act,WBCGtk * wbcg)1643 static void cb_font_subscript (GtkToggleAction *act, WBCGtk *wbcg)
1644 	{ toggle_font_attr (wbcg, act, MSTYLE_FONT_SCRIPT, GO_FONT_SCRIPT_SUB, GO_FONT_SCRIPT_STANDARD); }
cb_font_superscript(GtkToggleAction * act,WBCGtk * wbcg)1645 static void cb_font_superscript (GtkToggleAction *act, WBCGtk *wbcg)
1646 	{ toggle_font_attr (wbcg, act, MSTYLE_FONT_SCRIPT, GO_FONT_SCRIPT_SUPER, GO_FONT_SCRIPT_STANDARD); }
1647 
1648 static void
apply_number_format(WBCGtk * wbcg,GOFormat * format,char const * descriptor)1649 apply_number_format (WBCGtk *wbcg,
1650 		     GOFormat *format,
1651 		     char const *descriptor)
1652 {
1653 	GnmStyle *mstyle = gnm_style_new ();
1654 	gnm_style_set_format (mstyle, format);
1655 	cmd_selection_format (GNM_WBC (wbcg), mstyle, NULL, descriptor);
1656 }
1657 
GNM_ACTION_DEF(cb_format_as_general)1658 static GNM_ACTION_DEF (cb_format_as_general)
1659 {
1660 	apply_number_format (wbcg,
1661 			     go_format_general (),
1662 			     _("Format as General"));
1663 }
1664 
GNM_ACTION_DEF(cb_format_as_number)1665 static GNM_ACTION_DEF (cb_format_as_number)
1666 {
1667 	GOFormat *fmt = go_format_new_from_XL ("0");
1668 	apply_number_format (wbcg, fmt, _("Format as Number"));
1669 	go_format_unref (fmt);
1670 }
1671 
GNM_ACTION_DEF(cb_format_as_currency)1672 static GNM_ACTION_DEF (cb_format_as_currency)
1673 {
1674 	GOFormatDetails *details = go_format_details_new (GO_FORMAT_CURRENCY);
1675 	GString *str = g_string_new (NULL);
1676 	GOFormat *fmt;
1677 
1678 	details->currency = go_format_locale_currency ();
1679 	details->num_decimals = 2;
1680 	go_format_generate_str (str, details);
1681 	go_format_details_free (details);
1682 
1683 	fmt = go_format_new_from_XL (str->str);
1684 	g_string_free (str, TRUE);
1685 	apply_number_format (wbcg, fmt, _("Format as Currency"));
1686 	go_format_unref (fmt);
1687 }
1688 
GNM_ACTION_DEF(cb_format_as_accounting)1689 static GNM_ACTION_DEF (cb_format_as_accounting)
1690 {
1691 	apply_number_format (wbcg,
1692 			     go_format_default_accounting (),
1693 			     _("Format as Accounting"));
1694 }
1695 
GNM_ACTION_DEF(cb_format_as_percentage)1696 static GNM_ACTION_DEF (cb_format_as_percentage)
1697 {
1698 	GOFormat *fmt = go_format_new_from_XL ("0%");
1699 	apply_number_format (wbcg, fmt, _("Format as Percentage"));
1700 	go_format_unref (fmt);
1701 }
1702 
GNM_ACTION_DEF(cb_format_as_scientific)1703 static GNM_ACTION_DEF (cb_format_as_scientific)
1704 {
1705 	GOFormat *fmt = go_format_new_from_XL ("0.00E+00");
1706 	apply_number_format (wbcg, fmt, _("Format as Percentage"));
1707 	go_format_unref (fmt);
1708 }
1709 
GNM_ACTION_DEF(cb_format_as_time)1710 static GNM_ACTION_DEF (cb_format_as_time)
1711 {
1712 	apply_number_format (wbcg,
1713 			     go_format_default_time (),
1714 			     _("Format as Time"));
1715 }
1716 
GNM_ACTION_DEF(cb_format_as_date)1717 static GNM_ACTION_DEF (cb_format_as_date)
1718 {
1719 	apply_number_format (wbcg,
1720 			     go_format_default_date (),
1721 			     _("Format as Date"));
1722 }
1723 
1724 /* Adds borders to all the selected regions on the sheet.
1725  * FIXME: This is a little more simplistic then it should be, it always
1726  * removes and/or overwrites any borders. What we should do is
1727  * 1) When adding -> don't add a border if the border is thicker than 'THIN'
1728  * 2) When removing -> don't remove unless the border is 'THIN'
1729  */
1730 static void
mutate_borders(WBCGtk * wbcg,gboolean add)1731 mutate_borders (WBCGtk *wbcg, gboolean add)
1732 {
1733 	GnmBorder *borders [GNM_STYLE_BORDER_EDGE_MAX];
1734 	int i;
1735 
1736 	for (i = GNM_STYLE_BORDER_TOP; i < GNM_STYLE_BORDER_EDGE_MAX; ++i)
1737 		if (i <= GNM_STYLE_BORDER_RIGHT)
1738 			borders[i] = gnm_style_border_fetch (
1739 				add ? GNM_STYLE_BORDER_THIN : GNM_STYLE_BORDER_NONE,
1740 				style_color_black (), gnm_style_border_get_orientation (i));
1741 		else
1742 			borders[i] = NULL;
1743 
1744 	cmd_selection_format (GNM_WBC (wbcg), NULL, borders,
1745 		add ? _("Add Borders") : _("Remove borders"));
1746 }
1747 
GNM_ACTION_DEF(cb_format_add_borders)1748 static GNM_ACTION_DEF (cb_format_add_borders)	{ mutate_borders (wbcg, TRUE); }
GNM_ACTION_DEF(cb_format_clear_borders)1749 static GNM_ACTION_DEF (cb_format_clear_borders)	{ mutate_borders (wbcg, FALSE); }
1750 
1751 static void
modify_format(WBCGtk * wbcg,GOFormat * (* format_modify_fn)(GOFormat const * format),char const * descriptor)1752 modify_format (WBCGtk *wbcg,
1753 	       GOFormat *(*format_modify_fn) (GOFormat const *format),
1754 	       char const *descriptor)
1755 {
1756 	WorkbookControl *wbc = GNM_WBC (wbcg);
1757 	WorkbookView const *wbv;
1758 	GOFormat *new_fmt;
1759 
1760 	wbv = wb_control_view (wbc);
1761 	g_return_if_fail (wbv != NULL);
1762 	g_return_if_fail (wbv->current_style != NULL);
1763 
1764 	new_fmt = (*format_modify_fn) (gnm_style_get_format (wbv->current_style));
1765 	if (new_fmt != NULL) {
1766 		GnmStyle *style = gnm_style_new ();
1767 		gnm_style_set_format (style, new_fmt);
1768 		cmd_selection_format (wbc, style, NULL, descriptor);
1769 		go_format_unref (new_fmt);
1770 	}
1771 }
1772 
1773 static GnmValue *
cb_calc_decs(GnmCellIter const * iter,gpointer user)1774 cb_calc_decs (GnmCellIter const *iter, gpointer user)
1775 {
1776 	int *pdecs = user;
1777 	int decs = 0;
1778 	GnmCell *cell = iter->cell;
1779 	char *text;
1780 	const char *p;
1781 	GString const *dec = go_locale_get_decimal ();
1782 
1783 	if (!cell || !cell->value || !VALUE_IS_NUMBER (cell->value))
1784 		return NULL;
1785 
1786 	/*
1787 	 * If we are displaying an equation, we don't want to look into
1788 	 * the rendered text.
1789 	 */
1790 	if (gnm_cell_has_expr (cell) && cell->base.sheet->display_formulas)
1791 		return NULL;
1792 
1793 	text = gnm_cell_get_rendered_text (cell);
1794 	p = strstr (text, dec->str);
1795 	if (p) {
1796 		p += dec->len;
1797 
1798 		while (g_ascii_isdigit (*p))
1799 			decs++, p++;
1800 	}
1801 
1802 	*pdecs = MAX (*pdecs, decs);
1803 
1804 	g_free (text);
1805 
1806 	return NULL;
1807 }
1808 
1809 static void
inc_dec(WBCGtk * wbcg,int dir,GOFormat * (* format_modify_fn)(GOFormat const * format),char const * descriptor)1810 inc_dec (WBCGtk *wbcg,
1811 	 int dir,
1812 	 GOFormat *(*format_modify_fn) (GOFormat const *format),
1813 	 char const *descriptor)
1814 {
1815 	WorkbookControl *wbc = GNM_WBC (wbcg);
1816 	WorkbookView *wbv = wb_control_view (wbc);
1817 	GOFormat const *fmt = gnm_style_get_format (wbv->current_style);
1818 	SheetView *sv;
1819 	GOFormat *new_fmt;
1820 	GnmStyle *style;
1821 	GSList *l;
1822 	int decs = -2;
1823 	GString *new_fmt_str;
1824 
1825 	if (!go_format_is_general (fmt)) {
1826 		modify_format (wbcg, format_modify_fn, descriptor);
1827 		return;
1828 	}
1829 
1830 	sv = wb_view_cur_sheet_view (wbv);
1831 	if (!sv)
1832 		return;
1833 
1834 	for (l = sv->selections; l ; l = l->next) {
1835 		GnmRange const *r = l->data;
1836 		sheet_foreach_cell_in_range (sv_sheet (sv),
1837 					     CELL_ITER_IGNORE_BLANK |
1838 					     CELL_ITER_IGNORE_HIDDEN,
1839 					     r, cb_calc_decs, &decs);
1840 	}
1841 
1842 	new_fmt_str = g_string_new ("0");
1843 	if (decs + dir > 0) {
1844 		g_string_append_c (new_fmt_str, '.');
1845 		go_string_append_c_n (new_fmt_str, '0', decs + dir);
1846 	}
1847 	new_fmt = go_format_new_from_XL (new_fmt_str->str);
1848 	g_string_free (new_fmt_str, TRUE);
1849 
1850 	style = gnm_style_new ();
1851 	gnm_style_set_format (style, new_fmt);
1852 	cmd_selection_format (wbc, style, NULL, descriptor);
1853 	go_format_unref (new_fmt);
1854 }
1855 
GNM_ACTION_DEF(cb_format_inc_precision)1856 static GNM_ACTION_DEF (cb_format_inc_precision)
1857 	{ inc_dec (wbcg, 1,
1858 		   &go_format_inc_precision, _("Increase precision")); }
GNM_ACTION_DEF(cb_format_dec_precision)1859 static GNM_ACTION_DEF (cb_format_dec_precision)
1860 	{ inc_dec (wbcg, -1,
1861 		   &go_format_dec_precision, _("Decrease precision")); }
GNM_ACTION_DEF(cb_format_with_thousands)1862 static GNM_ACTION_DEF (cb_format_with_thousands)
1863 	{ modify_format (wbcg, &go_format_toggle_1000sep, _("Toggle thousands separator")); }
1864 
GNM_ACTION_DEF(cb_format_dec_indent)1865 static GNM_ACTION_DEF (cb_format_dec_indent) { workbook_cmd_dec_indent (GNM_WBC (wbcg)); }
GNM_ACTION_DEF(cb_format_inc_indent)1866 static GNM_ACTION_DEF (cb_format_inc_indent) { workbook_cmd_inc_indent (GNM_WBC (wbcg)); }
1867 
GNM_ACTION_DEF(cb_copydown)1868 static GNM_ACTION_DEF (cb_copydown)
1869 {
1870 	WorkbookControl  *wbc = GNM_WBC (wbcg);
1871 	cmd_copyrel (wbc, 0, -1, _("Copy down"));
1872 }
1873 
GNM_ACTION_DEF(cb_copyright)1874 static GNM_ACTION_DEF (cb_copyright)
1875 {
1876 	WorkbookControl *wbc = GNM_WBC (wbcg);
1877 	/* xgettext: copy from the cell to the left into current cell --
1878 	   this has nothing whatsoever to do with copyright.  */
1879 	cmd_copyrel (wbc, -1, 0, _("Copy right"));
1880 }
1881 
GNM_ACTION_DEF(cb_format_cells_auto_fit_height)1882 static GNM_ACTION_DEF (cb_format_cells_auto_fit_height)
1883 {
1884 	WorkbookControl *wbc = GNM_WBC (wbcg);
1885 	workbook_cmd_autofit_selection
1886 		(wbc, wb_control_cur_sheet (wbc), FALSE);
1887 }
1888 
GNM_ACTION_DEF(cb_format_cells_auto_fit_width)1889 static GNM_ACTION_DEF (cb_format_cells_auto_fit_width)
1890 {
1891 	WorkbookControl *wbc = GNM_WBC (wbcg);
1892 	workbook_cmd_autofit_selection
1893 		(wbc, wb_control_cur_sheet (wbc), TRUE);
1894 }
1895 
GNM_ACTION_DEF(cb_format_column_auto_fit)1896 static GNM_ACTION_DEF (cb_format_column_auto_fit)
1897 {
1898 	WorkbookControl *wbc = GNM_WBC (wbcg);
1899 	workbook_cmd_resize_selected_colrow (wbc,
1900 		wb_control_cur_sheet (wbc), TRUE, -1);
1901 }
GNM_ACTION_DEF(cb_set_column_width)1902 static GNM_ACTION_DEF (cb_set_column_width)
1903 {
1904 	dialog_col_width (wbcg, FALSE);
1905 }
GNM_ACTION_DEF(cb_format_column_std_width)1906 static GNM_ACTION_DEF (cb_format_column_std_width)
1907 {
1908 	dialog_col_width (wbcg, TRUE);
1909 }
GNM_ACTION_DEF(cb_format_column_hide)1910 static GNM_ACTION_DEF (cb_format_column_hide)
1911 {
1912 	cmd_selection_colrow_hide (GNM_WBC (wbcg), TRUE, FALSE);
1913 }
GNM_ACTION_DEF(cb_format_column_unhide)1914 static GNM_ACTION_DEF (cb_format_column_unhide)
1915 {
1916 	cmd_selection_colrow_hide (GNM_WBC (wbcg), TRUE, TRUE);
1917 }
1918 
GNM_ACTION_DEF(cb_format_row_auto_fit)1919 static GNM_ACTION_DEF (cb_format_row_auto_fit)
1920 {
1921 	WorkbookControl *wbc = GNM_WBC (wbcg);
1922 	workbook_cmd_resize_selected_colrow (wbc,
1923 		wb_control_cur_sheet (wbc), FALSE, -1);
1924 }
GNM_ACTION_DEF(cb_set_row_height)1925 static GNM_ACTION_DEF (cb_set_row_height)
1926 {
1927 	dialog_row_height (wbcg, FALSE);
1928 }
GNM_ACTION_DEF(cb_format_row_std_height)1929 static GNM_ACTION_DEF (cb_format_row_std_height)
1930 {
1931 	dialog_row_height (wbcg, TRUE);
1932 }
GNM_ACTION_DEF(cb_format_row_hide)1933 static GNM_ACTION_DEF (cb_format_row_hide)
1934 {
1935 	cmd_selection_colrow_hide (GNM_WBC (wbcg), FALSE, FALSE);
1936 }
GNM_ACTION_DEF(cb_format_row_unhide)1937 static GNM_ACTION_DEF (cb_format_row_unhide)
1938 {
1939 	cmd_selection_colrow_hide (GNM_WBC (wbcg), FALSE, TRUE);
1940 }
1941 
GNM_ACTION_DEF(cb_file_menu)1942 static GNM_ACTION_DEF (cb_file_menu)
1943 {
1944 	wbc_gtk_load_templates (wbcg);
1945 }
1946 
GNM_ACTION_DEF(cb_insert_menu)1947 static GNM_ACTION_DEF (cb_insert_menu)
1948 {
1949 	GtkAction *action = wbcg_find_action (wbcg, "MenuInsertObject");
1950 	SheetControlGUI	*scg = wbcg_cur_scg (wbcg);
1951 	gtk_action_set_sensitive (action, go_components_get_mime_types () != NULL && scg && scg_sheet (scg)->sheet_type == GNM_SHEET_DATA);
1952 }
1953 
1954 #define TOGGLE_HANDLER(flag,property)					\
1955 static GNM_ACTION_DEF (cb_sheet_pref_ ## flag )				\
1956 {									\
1957 	g_return_if_fail (GNM_IS_WBC_GTK (wbcg));		\
1958 									\
1959 	if (!wbcg->updating_ui) {					\
1960 		Sheet *sheet = wbcg_cur_sheet (wbcg);			\
1961 		go_object_toggle (sheet, property);			\
1962 		sheet_update (sheet);					\
1963 	}								\
1964 }
1965 
1966 TOGGLE_HANDLER (display_formulas, "display-formulas")
1967 TOGGLE_HANDLER (hide_zero, "display-zeros")
1968 TOGGLE_HANDLER (hide_grid, "display-grid")
1969 TOGGLE_HANDLER (hide_col_header, "display-column-header")
1970 TOGGLE_HANDLER (hide_row_header, "display-row-header")
1971 TOGGLE_HANDLER (display_outlines, "display-outlines")
1972 TOGGLE_HANDLER (outline_symbols_below, "display-outlines-below")
1973 TOGGLE_HANDLER (outline_symbols_right, "display-outlines-right")
1974 TOGGLE_HANDLER (use_r1c1, "use-r1c1")
1975 
1976 /* Actions that are always sensitive */
1977 static GnmActionEntry const permanent_actions[] = {
1978 	{ .name = "MenuFile",
1979 	  .label = N_("_File"),
1980 	  .callback = G_CALLBACK (cb_file_menu)
1981 	},
1982 	{ .name = "MenuFileNewFromTemplate",
1983 	  .icon = "document-new",
1984 	  .label = N_("New From Template")
1985 	},
1986 	{ .name = "FileNew",
1987 	  .icon = "document-new",
1988 	  .label = N_("_New"),
1989 	  .accelerator = "<control>n",
1990 	  .tooltip = N_("Create a new workbook"),
1991 	  .callback = G_CALLBACK (cb_file_new)
1992 	},
1993 	{ .name = "FileOpen",
1994 	  .icon = "document-open",
1995 	  .label = GNM_N_STOCK_OPEN,
1996 	  .label_context = GNM_STOCK_LABEL_CONTEXT,
1997 	  .accelerator = "<control>o",
1998 	  .tooltip = N_("Open a file"),
1999 	  .callback = G_CALLBACK (cb_file_open)
2000 	},
2001 	{ .name = "FileSave",
2002 	  .icon = "document-save",
2003 	  .label = GNM_N_STOCK_SAVE,
2004 	  .label_context = GNM_STOCK_LABEL_CONTEXT,
2005 	  .accelerator = "<control>s",
2006 	  .tooltip = N_("Save the current workbook"),
2007 	  .callback = G_CALLBACK (cb_file_save)
2008 	},
2009 	{ .name = "FileSaveAs",
2010 	  .icon = "document-save-as",
2011 	  .label = GNM_N_STOCK_SAVE_AS,
2012 	  .label_context = GNM_STOCK_LABEL_CONTEXT,
2013 	  .accelerator = "<control><shift>s",
2014 	  .tooltip = N_("Save the current workbook with a different name"),
2015 	  .callback = G_CALLBACK (cb_file_save_as)
2016 	},
2017 	{ .name = "FileSend",
2018 	  .icon = "gnumeric-link-email",
2019 	  .label = N_("Sen_d To..."),
2020 	  .tooltip = N_("Send the current file via email"),
2021 	  .callback = G_CALLBACK (cb_file_sendto)
2022 	},
2023 	{ .name = "FilePageSetup",
2024 	  .icon = "document-page-setup",
2025 	  .label = N_("Page Set_up..."),
2026 	  .tooltip = N_("Setup the page settings for your current printer"),
2027 	  .callback = G_CALLBACK (cb_file_page_setup)
2028 	},
2029 	{ .name = "FilePrintPreview",
2030 	  .icon = "document-print-preview",
2031 	  .label = N_("Print Pre_view"),
2032 	  .tooltip = N_("Print preview"),
2033 	  .callback = G_CALLBACK (cb_file_print_preview)
2034 	},
2035 	{ .name = "FilePrint",
2036 	  .icon = "document-print",
2037 	  .label = N_("Print"),
2038 	  .accelerator = "<control>p",
2039 	  .tooltip = N_("Print the current file"),
2040 	  .callback = G_CALLBACK (cb_file_print)
2041 	},
2042 	{ .name = "FilePrintArea",
2043 	  .label = N_("Print Area & Breaks")
2044 	},
2045 	{ .name = "FileHistoryFull",
2046 	  .label = N_("Full _History..."),
2047 	  .tooltip = N_("Access previously used file"),
2048 	  .callback = G_CALLBACK (cb_file_history_full)
2049 	},
2050 	{ .name = "FileClose",
2051 	  .icon = "window-close",
2052 	  .label = N_("_Close"),
2053 	  .accelerator = "<control>w",
2054 	  .tooltip = N_("Close the current file"),
2055 	  .callback = G_CALLBACK (cb_file_close)
2056 	},
2057 	{ .name = "FileQuit",
2058 	  .icon = "application-exit",
2059 	  .label = N_("_Quit"),
2060 	  .accelerator = "<control>q",
2061 	  .tooltip = N_("Quit the application"),
2062 	  .callback = G_CALLBACK (cb_file_quit)
2063 	},
2064 	/* ---------------------------------------- */
2065 	{ .name = "MenuEdit",
2066 	  .label = N_("_Edit")
2067 	},
2068 	{ .name = "MenuEditClear",
2069 	  .icon = "edit-clear",
2070 	  .label = N_("C_lear")
2071 	},
2072 	{ .name = "MenuEditDelete",
2073 	  .icon = "edit-delete",
2074 	  .label = N_("_Delete")
2075 	},
2076 	{ .name = "MenuEditItems",
2077 	  .label = N_("_Modify")
2078 	},
2079 	{ .name = "MenuEditSheet",
2080 	  .label = N_("S_heet")
2081 	},
2082 	{ .name = "MenuEditSelect",
2083 	  .label = N_("_Select")
2084 	},
2085 
2086 	{ .name = "EditCopy",
2087 	  .icon = "edit-copy",
2088 	  .label = N_("_Copy"),
2089 	  .accelerator = "<control>c",
2090 	  .tooltip = N_("Copy the selection"),
2091 	  .callback = G_CALLBACK (cb_edit_copy)
2092 	},
2093 
2094 	/* ---------------------------------------- */
2095 	{ .name = "MenuView",
2096 	  .label = N_("_View")
2097 	},
2098 	{ .name = "MenuViewWindows",
2099 	  .label = N_("_Windows")
2100 	},
2101 	{ .name = "MenuViewToolbars",
2102 	  .label = N_("_Toolbars")
2103 	},
2104 	/* ---------------------------------------- */
2105 	{ .name = "MenuInsert",
2106 	  .label = N_("_Insert"),
2107 	  .callback = G_CALLBACK (cb_insert_menu)
2108 	},
2109 	{ .name = "MenuInsertObject",
2110 	  .label = N_("_Object")
2111 	},
2112 	{ .name = "MenuInsertSpecial",
2113 	  .label = N_("S_pecial")
2114 	},
2115 	{ .name = "MenuInsertFormulaWrap",
2116 	  .icon = "gnumeric-formulaguru",
2117 	  .label = N_("Func_tion Wrapper")
2118 	},
2119 	{ .name = "InsertNames",
2120 	  .label = N_("_Name..."),
2121 	  .accelerator = "F3",
2122 	  .tooltip = N_("Insert a defined name"),
2123 	  .callback = G_CALLBACK (cb_paste_names)
2124 	},
2125 	/* ---------------------------------------- */
2126 	{ .name = "MenuFormat",
2127 	  .label = N_("F_ormat")
2128 	},
2129 	{ .name = "MenuFormatCells",
2130 	  .label = N_("_Cells")
2131 	},
2132 	{ .name = "MenuFormatText",
2133 	  .label = N_("_Text")
2134 	},
2135 	{ .name = "MenuFormatTextUnderline",
2136 	  .label = N_("_Underline")
2137 	},
2138 	{ .name = "MenuFormatColumn",
2139 	  .label = N_("C_olumn")
2140 	},
2141 	{ .name = "MenuFormatRow",
2142 	  .label = N_("_Row")
2143 	},
2144 	{ .name = "MenuFormatSheet",
2145 	  .label = N_("_Sheet")
2146 	},
2147 	/* ---------------------------------------- */
2148 	{ .name = "MenuTools",
2149 	  .label = N_("_Tools")
2150 	},
2151 	{ .name = "MenuToolsScenarios",
2152 	  .label = N_("Sce_narios")
2153 	},
2154 	/* ---------------------------------------- */
2155 	{ .name = "MenuStatistics",
2156 	  .label = N_("_Statistics")
2157 	},
2158 	{ .name = "MenuStatisticsDescriptive",
2159 	  .label = N_("_Descriptive Statistics")
2160 	},
2161 	{ .name = "MenuToolFrequencies",
2162 	  .label = N_("Fre_quency Tables")
2163 	},
2164 	{ .name = "MenuStatisticsTimeSeries",
2165 	  .label = N_("De_pendent Observations")
2166 	},
2167 	{ .name = "MenuToolForecast",
2168 	  .label = N_("F_orecast")
2169 	},
2170 	{ .name = "MenuStatisticsOneSample",
2171 	  .label = N_("_One Sample Tests")
2172 	},
2173 	{ .name = "MenuToolOneMedian",
2174 	  .label = N_("Claims About a Me_dian")
2175 	},
2176 	{ .name = "MenuStatisticsTwoSamples",
2177 	  .label = N_("_Two Sample Tests")
2178 	},
2179 	{ .name = "MenuToolTwoMedians",
2180 	  .label = N_("Claims About Two Me_dians")
2181 	},
2182 	{ .name = "MenuToolTTest",
2183 	  .label = N_("Claims About Two _Means")
2184 	},
2185 	{ .name = "MenuStatisticsMultipleSamples",
2186 	  .label = N_("_Multiple Sample Tests")
2187 	},
2188 	{ .name = "MenuANOVA",
2189 	  .label = N_("_ANOVA")
2190 	},
2191 	{ .name = "MenuContingencyTests",
2192 	  .label = N_("Contin_gency Table")
2193 	},
2194 	/* ---------------------------------------- */
2195 	{ .name = "MenuData",
2196 	  .label = N_("_Data")
2197 	},
2198 	{ .name = "MenuFilter",
2199 	  .label = N_("_Filter")
2200 	},
2201 	{ .name = "MenuEditFill",
2202 	  .label = N_("F_ill")
2203 	},
2204 	{ .name = "MenuRandomGenerator",
2205 	  .label = N_("_Random Generators")
2206 	},
2207 	{ .name = "MenuOutline",
2208 	  .label = N_("_Group and Outline")
2209 	},
2210 	{ .name = "MenuExternalData",
2211 	  .label = N_("Import _Data")
2212 	},
2213 	{ .name = "MenuExportData",
2214 	  .label = N_("E_xport Data")
2215 	},
2216 	{ .name = "MenuSlicer",
2217 	  .label = N_("Data S_licer")
2218 	},
2219 	/* ---------------------------------------- */
2220 	{ .name = "MenuHelp",
2221 	  .label = N_("_Help")
2222 	},
2223 
2224 	{ .name = "HelpDocs",
2225 	  .icon = "help-browser",
2226 	  .label = N_("_Contents"),
2227 	  .accelerator = "F1",
2228 	  .tooltip = N_("Open a viewer for Gnumeric's documentation"),
2229 	  .callback = G_CALLBACK (cb_help_docs)
2230 	},
2231 	{ .name = "HelpFunctions",
2232 	  .icon = "gnumeric-formulaguru",
2233 	  .label = N_("_Functions"),
2234 	  .tooltip = N_("Functions help"),
2235 	  .callback = G_CALLBACK (cb_help_function)
2236 	},
2237 	{ .name = "HelpWeb",
2238 	  .label = N_("Gnumeric on the _Web"),
2239 	  .tooltip = N_("Browse to Gnumeric's website"),
2240 	  .callback = G_CALLBACK (cb_help_web)
2241 	},
2242 	{ .name = "HelpIRC",
2243 	  .label = N_("_Live Assistance"),
2244 	  .tooltip = N_("See if anyone is available to answer questions"),
2245 	  .callback = G_CALLBACK (cb_help_irc)
2246 	},
2247 	{ .name = "HelpBug",
2248 	  .label = N_("Report a _Problem"),
2249 	  .tooltip = N_("Report problem"),
2250 	  .callback = G_CALLBACK (cb_help_bug)
2251 	},
2252 	{ .name = "HelpAbout",
2253 	  .icon = "help-about",
2254 	  .label = N_("_About"),
2255 	  .tooltip = N_("About this application"),
2256 	  .callback = G_CALLBACK (cb_help_about)
2257 	},
2258 };
2259 
2260 /* actions that are sensitive only in data sheets */
2261 static GnmActionEntry const data_only_actions[] = {
2262 	{ .name = "EditCut",
2263 	  .icon = "edit-cut",
2264 	  .label = N_("Cu_t"),
2265 	  .accelerator = "<control>x",
2266 	  .tooltip = N_("Cut the selection"),
2267 	  .callback = G_CALLBACK (cb_edit_cut)
2268 	},
2269 	{ .name = "EditPaste",
2270 	  .icon = "edit-paste",
2271 	  .label = N_("_Paste"),
2272 	  .accelerator = "<control>v",
2273 	  .tooltip = N_("Paste the clipboard"),
2274 	  .callback = G_CALLBACK (cb_edit_paste)
2275 	},
2276 };
2277 
2278 #define FULLSCREEN_ACCEL "F11"
2279 
2280 static GnmActionEntry const semi_permanent_actions[] = {
2281 	/* Edit -> Sheet */
2282 	{ .name = "SheetReorder",
2283 	  .label = N_("_Manage Sheets..."),
2284 	  .tooltip = N_("Manage the sheets in this workbook"),
2285 	  .callback = G_CALLBACK (cb_sheet_order)
2286 	},
2287 	{ .name = "InsertSheet",
2288 	  .label = N_("_Insert"),
2289 	  .tooltip = N_("Insert a new sheet"),
2290 	  .callback = G_CALLBACK (wbcg_insert_sheet)
2291 	},
2292 	/* ICK A DUPLICATE : we have no way to override a label on one proxy */
2293 	{ .name = "SheetInsert",
2294 	  .label = N_("_Sheet"),
2295 	  .tooltip = N_("Insert a new sheet"),
2296 	  .callback = G_CALLBACK (wbcg_insert_sheet)
2297 	},
2298 	{ .name = "InsertSheetAtEnd",
2299 	  .label = N_("_Append"),
2300 	  .tooltip = N_("Append a new sheet"),
2301 	  .callback = G_CALLBACK (wbcg_append_sheet)
2302 	},
2303 	{ .name = "EditDuplicateSheet",
2304 	  .label = N_("_Duplicate"),
2305 	  .tooltip = N_("Make a copy of the current sheet"),
2306 	  .callback = G_CALLBACK (wbcg_clone_sheet)
2307 	},
2308 	{ .name = "SheetRemove",
2309 	  .label = N_("_Remove"),
2310 	  .tooltip = N_("Irrevocably remove an entire sheet"),
2311 	  .callback = G_CALLBACK (cb_sheet_remove)
2312 	},
2313 	{ .name = "SheetChangeName",
2314 	  .label = N_("Re_name..."),
2315 	  .tooltip = N_("Rename the current sheet"),
2316 	  .callback = G_CALLBACK (cb_sheet_name)
2317 	},
2318 	{ .name = "SheetResize",
2319 	  .label = N_("Resize..."),
2320 	  .tooltip = N_("Change the size of the current sheet"),
2321 	  .callback = G_CALLBACK (cb_sheet_resize)
2322 	},
2323 
2324 	/* View */
2325 	{ .name = "ViewNew",
2326 	  .icon = "document-new",
2327 	  .label = N_("_New View..."),
2328 	  .tooltip = N_("Create a new view of the workbook"),
2329 	  .callback = G_CALLBACK (cb_view_new)
2330 	},
2331 
2332 	/* Format */
2333 	{ .name = "FormatWorkbook",
2334 	  .icon = "document-properties",
2335 	  .label = N_("View _Properties..."),
2336 	  .tooltip = N_("Modify the view properties"),
2337 	  .callback = G_CALLBACK (cb_workbook_attr)
2338 	},
2339 
2340 	{ .name = "ViewStatusbar",
2341 	  .toggle = TRUE,
2342 	  .label = N_("View _Statusbar"),
2343 	  .tooltip = N_("Toggle visibility of statusbar"),
2344 	  .callback = G_CALLBACK (cb_view_statusbar),
2345 	  .is_active = TRUE
2346 	},
2347 
2348 	{ .name = "ViewFullScreen",
2349 	  .toggle = TRUE,
2350 	  .icon = "view-fullscreen",
2351 	  .label = N_("F_ull Screen"),
2352 	  .accelerator = FULLSCREEN_ACCEL,
2353 	  .tooltip = N_("Switch to or from full screen mode"),
2354 	  .callback = G_CALLBACK (cb_view_fullscreen)
2355 	},
2356 };
2357 
2358 #define ZOOM_IN_ACCEL NULL
2359 #define ZOOM_OUT_ACCEL NULL
2360 
2361 static GnmActionEntry const actions[] = {
2362 /* File */
2363 	{ .name = "FileMetaData",
2364 	  .icon = "document-properties",
2365 	  .label = N_("Document Proper_ties..."),
2366 	  .tooltip = N_("Edit document properties"),
2367 	  .callback = G_CALLBACK (cb_doc_meta_data)
2368 	},
2369 
2370 /* File->PrintArea */
2371         { .name = "FilePrintAreaSet",
2372 	  .label = N_("Set Print Area"),
2373 	  .tooltip = N_("Use the current selection as print area"),
2374 	  .callback = G_CALLBACK (cb_file_print_area_set)
2375 	},
2376         { .name = "FilePrintAreaClear",
2377 	  .label = N_("Clear Print Area"),
2378 	  .tooltip = N_("Undefine the print area"),
2379 	  .callback = G_CALLBACK (cb_file_print_area_clear)
2380 	},
2381         { .name = "FilePrintAreaShow",
2382 	  .label = N_("Show Print Area"),
2383 	  .tooltip = N_("Select the print area"),
2384 	  .callback = G_CALLBACK (cb_file_print_area_show)
2385 	},
2386         { .name = "FilePrintAreaToggleColPageBreak",
2387 	  .label = N_("Set Column Page Break"),
2388 	  .tooltip = N_("Split the page to the left of this column"),
2389 	  .callback = G_CALLBACK (cb_file_print_area_toggle_col)
2390 	},
2391         { .name = "FilePrintAreaToggleRowPageBreak",
2392 	  .label = N_("Set Row Page Break"),
2393 	  .tooltip = N_("Split the page above this row"),
2394 	  .callback = G_CALLBACK (cb_file_print_area_toggle_row)
2395 	},
2396         { .name = "FilePrintAreaClearAllPageBreak",
2397 	  .label = N_("Clear All Page Breaks"),
2398 	  .tooltip = N_("Remove all manual pagebreaks from this sheet"),
2399 	  .callback = G_CALLBACK (cb_file_print_area_clear_pagebreaks)
2400 	},
2401 
2402 /* Edit -> Clear */
2403 	{ .name = "EditClearAll",
2404 	  .icon = "edit-clear",
2405 	  .label = N_("_All"),
2406 	  .tooltip = N_("Clear the selected cells' formats, comments, and contents"),
2407 	  .callback = G_CALLBACK (cb_edit_clear_all)
2408 	},
2409 	{ .name = "EditClearFormats",
2410 	  .label = N_("_Formats & Hyperlinks"),
2411 	  .tooltip = N_("Clear the selected cells' formats and hyperlinks"),
2412 	  .callback = G_CALLBACK (cb_edit_clear_formats)
2413 	},
2414 	{ .name = "EditClearComments",
2415 	  .icon = "gnumeric-comment-delete",
2416 	  .label = N_("Co_mments"),
2417 	  .tooltip = N_("Delete the selected cells' comments"),
2418 	  .callback = G_CALLBACK (cb_edit_clear_comments)
2419 	},
2420 	{ .name = "EditClearContent",
2421 	  .icon = "edit-clear",
2422 	  .label = N_("_Contents"),
2423 	  .tooltip = N_("Clear the selected cells' contents"),
2424 	  .callback = G_CALLBACK (cb_edit_clear_content)
2425 	},
2426 	{ .name = "EditClearAllFiltered",
2427 	  .icon = "edit-clear",
2428 	  .label = N_("A_ll Filtered Rows"),
2429 	  .tooltip = N_("Clear the selected cells' formats, comments, and contents in the filtered rows"),
2430 	  .callback = G_CALLBACK (cb_edit_clear_all_filtered)
2431 	},
2432 	{ .name = "EditClearFormatsFiltered",
2433 	  .label = N_("F_ormats & Hyperlinks in Filtered Rows"),
2434 	  .tooltip = N_("Clear the selected cells' formats and hyperlinks in the filtered rows"),
2435 	  .callback = G_CALLBACK (cb_edit_clear_formats_filtered)
2436 	},
2437 	{ .name = "EditClearCommentsFiltered",
2438 	  .icon = "gnumeric-comment-delete",
2439 	  .label = N_("Comme_nts in Filtered Rows"),
2440 	  .tooltip = N_("Delete the selected cells' comments in the filtered rows"),
2441 	  .callback = G_CALLBACK (cb_edit_clear_comments_filtered)
2442 	},
2443 	{ .name = "EditClearContentFiltered",
2444 	  .icon = "edit-clear",
2445 	  .label = N_("Content_s of Filtered Rows"),
2446 	  .tooltip = N_("Clear the selected cells' contents in the filtered rows"),
2447 	  .callback = G_CALLBACK (cb_edit_clear_content_filtered)
2448 	},
2449 
2450 /* Edit -> Delete */
2451 	/*Translators: Delete "Rows"*/
2452 	{ .name = "EditDeleteRows",
2453 	  .icon = "gnumeric-row-delete",
2454 	  .label = N_("_Rows"),
2455 	  .tooltip = N_("Delete the row(s) containing the selected cells"),
2456 	  .callback = G_CALLBACK (cb_edit_delete_rows)
2457 	},
2458 	/*Translators: Delete "Columns"*/
2459 	{ .name = "EditDeleteColumns",
2460 	  .icon = "gnumeric-column-delete",
2461 	  .label = N_("_Columns"),
2462 	  .tooltip = N_("Delete the column(s) containing the selected cells"),
2463 	  .callback = G_CALLBACK (cb_edit_delete_columns)
2464 	},
2465 	{ .name = "EditDeleteCells",
2466 	  .label = N_("C_ells..."),
2467 	  .accelerator = "<control>minus",
2468 	  .tooltip = N_("Delete the selected cells, shifting others into their place"),
2469 	  .callback = G_CALLBACK (cb_edit_delete_cells)
2470 	},
2471 	{ .name = "EditClearHyperlinks",
2472 	  .icon = "gnumeric-link-delete",
2473 	  .label = N_("_Hyperlinks"),
2474 	  .tooltip = N_("Delete the selected cells' hyperlinks"),
2475 	  .callback = G_CALLBACK (cb_edit_delete_links)
2476 	},
2477 	/* A duplicate that should not go into the menus, used only for the accelerator */
2478 	{ .name = "EditDeleteCellsXL",
2479 	  .label = N_("C_ells..."),
2480 	  .accelerator = "<control>KP_Subtract",
2481 	  .tooltip = N_("Delete the selected cells, shifting others into their place"),
2482 	  .callback = G_CALLBACK (cb_edit_delete_cells)
2483 	},
2484 
2485 /* Edit -> Select */
2486 
2487 	/* Note : The accelerators involving space are just for display
2488 	 *	purposes.  We actually handle this in
2489 	 *		gnm-pane.c:gnm_pane_key_mode_sheet
2490 	 *	with the rest of the key movement and rangeselection.
2491 	 *	Otherwise input methods would steal them */
2492 	{ .name = "EditSelectAll",
2493 	  .label = N_("_All"),
2494 	  .accelerator = "<control><shift>space",
2495 	  .tooltip = N_("Select all cells in the spreadsheet"),
2496 	  .callback = G_CALLBACK (cb_edit_select_all)
2497 	},
2498 	{ .name = "EditSelectColumn",
2499 	  .label = N_("_Column"),
2500 	  .accelerator = "<control>space",
2501 	  .tooltip = N_("Select an entire column"),
2502 	  .callback = G_CALLBACK (cb_edit_select_col)
2503 	},
2504 	{ .name = "EditSelectRow",
2505 	  .label = N_("_Row"),
2506 	  .accelerator = "<shift>space",
2507 	  .tooltip = N_("Select an entire row"),
2508 	  .callback = G_CALLBACK (cb_edit_select_row)
2509 	},
2510 
2511 	{ .name = "EditSelectArray",
2512 	  .label = N_("Arra_y"),
2513 	  .accelerator = "<control>slash",
2514 	  .tooltip = N_("Select an array of cells"),
2515 	  .callback = G_CALLBACK (cb_edit_select_array)
2516 	},
2517 	{ .name = "EditSelectDepends",
2518 	  .label = N_("_Depends"),
2519 	  .accelerator = "<control>bracketright",
2520 	  .tooltip = N_("Select all the cells that depend on the current edit cell"),
2521 	  .callback = G_CALLBACK (cb_edit_select_depends)
2522 	},
2523 	{ .name = "EditSelectInputs",
2524 	  .label = N_("_Inputs"),
2525 	  .accelerator = "<control>bracketleft",
2526 	  .tooltip = N_("Select all the cells are used by the current edit cell"),
2527 	  .callback = G_CALLBACK (cb_edit_select_inputs)
2528 	},
2529 
2530 	{ .name = "EditSelectObject",
2531 	  .label = N_("Next _Object"),
2532 	  .accelerator = "<control>Tab",
2533 	  .tooltip = N_("Select the next sheet object"),
2534 	  .callback = G_CALLBACK (cb_edit_select_object)
2535 	},
2536 
2537 	{ .name = "EditGotoTop",
2538 	  .icon = "go-top",
2539 	  .label = N_("Go to Top"),
2540 	  .tooltip = N_("Go to the top of the data"),
2541 	  .callback = G_CALLBACK (cb_edit_goto_top)
2542 	},
2543 	{ .name = "EditGotoBottom",
2544 	  .icon = "go-bottom",
2545 	  .label = N_("Go to Bottom"),
2546 	  .tooltip = N_("Go to the bottom of the data"),
2547 	  .callback = G_CALLBACK (cb_edit_goto_bottom)
2548 	},
2549 	{ .name = "EditGotoFirst",
2550 	  .icon = "go-first",
2551 	  .label = N_("Go to First"),
2552 	  .tooltip = N_("Go to the first data cell"),
2553 	  .callback = G_CALLBACK (cb_edit_goto_first)
2554 	},
2555 	{ .name = "EditGotoLast",
2556 	  .icon = "go-last",
2557 	  .label = N_("Go to Last"),
2558 	  .tooltip = N_("Go to the last data cell"),
2559 	  .callback = G_CALLBACK (cb_edit_goto_last)
2560 	},
2561 	{ .name = "EditGoto",
2562 	  .icon = "go-jump",
2563 	  .label = N_("_Go to Cell..."),
2564 	  .accelerator = "<control>g",
2565 	  .tooltip = N_("Jump to a specified cell"),
2566 	  .callback = G_CALLBACK (cb_edit_goto)
2567 	},
2568 	/* This is a navigational aid that is not supposed to appear */
2569 	/* in the menu */
2570 	{ .name = "EditGotoCellIndicator",
2571 	  .label = N_("Go to Current Cell Indicator"),
2572 	  .accelerator = "<shift><control>g",
2573 	  .tooltip = N_("Go to Current Cell Indicator"),
2574 	  .callback = G_CALLBACK (cb_edit_goto_cell_indicator)
2575 	},
2576 
2577 /* Edit */
2578 	{ .name = "Repeat",
2579 	  .label = N_("Repeat"),
2580 	  .accelerator = "F4",
2581 	  .tooltip = N_("Repeat the previous action"),
2582 	  .callback = G_CALLBACK (cb_repeat)
2583 	},
2584 	{ .name = "EditPasteSpecial",
2585 	  .icon = "edit-paste",
2586 	  .label = N_("P_aste Special..."),
2587 	  .accelerator = "<shift><control>v",
2588 	  .tooltip = N_("Paste with optional filters and transformations"),
2589 	  .callback = G_CALLBACK (cb_edit_paste_special)
2590 	},
2591 
2592 	{ .name = "EditComment",
2593 	  .icon = "gnumeric-comment-edit",
2594 	  .label = N_("Co_mment..."),
2595 	  .tooltip = N_("Edit the selected cell's comment"),
2596 	  .callback = G_CALLBACK (cb_insert_comment)
2597 	},
2598 	{ .name = "EditHyperlink",
2599 	  .icon = "gnumeric-link-edit",
2600 	  .label = N_("Hyper_link..."),
2601 	  .accelerator = "<control>K",
2602 	  .tooltip = N_("Edit the selected cell's hyperlink"),
2603 	  .callback = G_CALLBACK (cb_insert_hyperlink)
2604 	},
2605 #if 0
2606 	{ .name = "EditGenerateName",
2607 	  .label = N_("_Auto generate names..."),
2608 	  .tooltip = N_("Use the current selection to create names"),
2609 	  .callback = G_CALLBACK (cb_auto_generate__named_expr)
2610 	},
2611 #endif
2612 
2613 	{ .name = "EditFind",
2614 	  .icon = "edit-find",
2615 	  .label = N_("S_earch..."),
2616 	  .accelerator = "<control>f",
2617 	  .tooltip = N_("Search for something"),
2618 	  .callback = G_CALLBACK (cb_edit_search)
2619 	},
2620 	{ .name = "EditReplace",
2621 	  .icon = "edit-find-replace",
2622 	  .label = N_("Search _& Replace..."),
2623 	  .accelerator = "<control>h",
2624 	  .tooltip = N_("Search for something and replace it with something else"),
2625 	  .callback = G_CALLBACK (cb_edit_search_replace)
2626 	},
2627 
2628 	{ .name = "EditRecalc",
2629 	  .label = N_("Recalculate"),
2630 	  .accelerator = "F9",
2631 	  .tooltip = N_("Recalculate the spreadsheet"),
2632 	  .callback = G_CALLBACK (cb_edit_recalc)
2633 	},
2634 
2635 	{ .name = "EditPreferences",
2636 	  .icon = "preferences-system",
2637 	  .label = N_("Preferences..."),
2638 	  .tooltip = N_("Change Gnumeric Preferences"),
2639 	  .callback = G_CALLBACK (cb_file_preferences)
2640 	},
2641 
2642 /* View */
2643 	{ .name = "ViewFreezeThawPanes",
2644 	  .label = N_("_Freeze Panes"),
2645 	  .tooltip = N_("Freeze the top left of the sheet"),
2646 	  .callback = G_CALLBACK (cb_view_freeze_panes)
2647 	},
2648 	{ .name = "ViewZoom",
2649 	  .icon = "zoom-fit-best", /* dubious */
2650 	  .label = N_("_Zoom..."),
2651 	  .tooltip = N_("Zoom the spreadsheet in or out"),
2652 	  .callback = G_CALLBACK (cb_view_zoom)
2653 	},
2654 	{ .name = "ViewZoomIn",
2655 	  .icon = "zoom-in",
2656 	  .label = N_("Zoom _In"),
2657 	  .accelerator = ZOOM_IN_ACCEL,
2658 	  .tooltip = N_("Increase the zoom to make things larger"),
2659 	  .callback = G_CALLBACK (cb_view_zoom_in)
2660 	},
2661 	{ .name = "ViewZoomOut",
2662 	  .icon = "zoom-out",
2663 	  .label = N_("Zoom _Out"),
2664 	  .accelerator = ZOOM_OUT_ACCEL,
2665 	  .tooltip = N_("Decrease the zoom to make things smaller"),
2666 	  .callback = G_CALLBACK (cb_view_zoom_out)
2667 	},
2668 
2669 /* Insert */
2670 	{ .name = "InsertCells",
2671 	  .label = N_("C_ells..."),
2672 	  .accelerator = "<control>plus",
2673 	  .tooltip = N_("Insert new cells"),
2674 	  .callback = G_CALLBACK (cb_insert_cells)
2675 	},
2676 	/* A duplicate that should not go into the menus, used only for the accelerator */
2677 	{ .name = "InsertCellsXL",
2678 	  .label = N_("C_ells..."),
2679 	  .accelerator = "<control>KP_Add",
2680 	  .tooltip = N_("Insert new cells"),
2681 	  .callback = G_CALLBACK (cb_insert_cells)
2682 	},
2683 	/*Translators: Insert "Columns"*/
2684 	{ .name = "InsertColumns",
2685 	  .icon = "gnumeric-column-add",
2686 	  .label = N_("_Columns"),
2687 	  .tooltip = N_("Insert new columns"),
2688 	  .callback = G_CALLBACK (cb_insert_cols)
2689 	},
2690 	/*Translators: Insert "Rows"*/
2691 	{ .name = "InsertRows",
2692 	  .icon = "gnumeric-row-add",
2693 	  .label = N_("_Rows"),
2694 	  .tooltip = N_("Insert new rows"),
2695 	  .callback = G_CALLBACK (cb_insert_rows)
2696 	},
2697 
2698 	{ .name = "ChartGuru",
2699 	  .icon = "gnumeric-graphguru",
2700 	  .label = N_("C_hart..."),
2701 	  .tooltip = N_("Insert a Chart"),
2702 	  .callback = G_CALLBACK (cb_launch_chart_guru)
2703 	},
2704 	{ .name = "NewGOComponent",
2705 	  .icon = "New Goffice_Component",
2706 	  .label = N_("_New..."),
2707 	  .tooltip = N_("Insert a new Goffice component object"),
2708 	  .callback = G_CALLBACK (cb_launch_go_component_new)
2709 	},
2710 	{ .name = "GOComponentFromFile",
2711 	  .icon = "New Goffice_Component from a file",
2712 	  .label = N_("_From File..."),
2713 	  .tooltip = N_("Insert a new Goffice component object from a file"),
2714 	  .callback = G_CALLBACK (cb_launch_go_component_from_file)
2715 	},
2716 	{ .name = "InsertImage",
2717 	  .icon = "insert-image",
2718 	  .label = N_("_Image..."),
2719 	  .tooltip = N_("Insert an image"),
2720 	  .callback = G_CALLBACK (cb_insert_image)
2721 	},
2722 
2723 	{ .name = "InsertComment",
2724 	  .icon = "gnumeric-comment-add",
2725 	  .label = N_("Co_mment..."),
2726 	  .tooltip = N_("Insert a comment"),
2727 	  .callback = G_CALLBACK (cb_insert_comment)
2728 	},
2729 	{ .name = "InsertHyperlink",
2730 	  .icon = "gnumeric-link-add",
2731 	  .label = N_("Hyper_link..."),
2732 	  .accelerator = "<control>K",
2733 	  .tooltip = N_("Insert a Hyperlink"),
2734 	  .callback = G_CALLBACK (cb_insert_hyperlink)
2735 	},
2736 	{ .name = "InsertSortDecreasing",
2737 	  .icon = "view-sort-descending",
2738 	  .label = N_("Sort (_Descending)"),
2739 	  .tooltip = N_("Wrap with SORT (descending)"),
2740 	  .callback = G_CALLBACK (cb_insert_sort_descending)
2741 	},
2742 	{ .name = "InsertSortIncreasing",
2743 	  .icon = "view-sort-ascending",
2744 	  .label = N_("Sort (_Ascending)"),
2745 	  .tooltip = N_("Wrap with SORT (ascending)"),
2746 	  .callback = G_CALLBACK (cb_insert_sort_ascending)
2747 	},
2748 
2749 /* Insert -> Special */
2750 	{ .name = "InsertCurrentDate",
2751 	  .label = N_("Current _Date"),
2752 	  .accelerator = "<control>semicolon",
2753 	  .tooltip = N_("Insert the current date into the selected cell(s)"),
2754 	  .callback = G_CALLBACK (cb_insert_current_date)
2755 	},
2756 
2757 	{ .name = "InsertCurrentTime",
2758 	  .label = N_("Current _Time"),
2759 	  .accelerator = "<control>colon",
2760 	  .tooltip = N_("Insert the current time into the selected cell(s)"),
2761 	  .callback = G_CALLBACK (cb_insert_current_time)
2762 	},
2763 
2764 	{ .name = "InsertCurrentDateTime",
2765 	  .label = N_("Current D_ate and Time"),
2766 	  .accelerator = "<control>period",
2767 	  .tooltip = N_("Insert the current date and time into the selected cell(s)"),
2768 	  .callback = G_CALLBACK (cb_insert_current_date_time)
2769 	},
2770 
2771 /* Insert -> Name */
2772 	{ .name = "EditNames",
2773 	  .label = N_("_Names..."),
2774 	  .accelerator = "<control>F3",
2775 	  .tooltip = N_("Edit defined names for expressions"),
2776 	  .callback = G_CALLBACK (cb_define_name)
2777 	},
2778 
2779 /* Format */
2780 	{ .name = "FormatAuto",
2781 	  .label = N_("_Autoformat..."),
2782 	  .tooltip = N_("Format a region of cells according to a pre-defined template"),
2783 	  .callback = G_CALLBACK (cb_autoformat)
2784 	},
2785 	{ .name = "SheetDirection",
2786 	  .icon = "format-text-direction-ltr",
2787 	  .label = N_("Direction"),
2788 	  .tooltip = N_("Toggle sheet direction, left-to-right vs right-to-left"),
2789 	  .callback = G_CALLBACK (cb_direction)
2790 	},
2791 
2792 /* Format -> Cells */
2793 	{ .name = "FormatCells",
2794 	  .label = N_("_Format..."),
2795 	  .accelerator = "<control>1",
2796 	  .tooltip = N_("Modify the formatting of the selected cells"),
2797 	  .callback = G_CALLBACK (cb_format_cells)
2798 	},
2799 	{ .name = "FormatCellsCond",
2800 	  .label = N_("_Conditional Formatting..."),
2801 	  .tooltip = N_("Modify the conditional formatting of the selected cells"),
2802 	  .callback = G_CALLBACK (cb_format_cells_cond)
2803 	},
2804 	{ .name = "FormatCellsFitHeight",
2805 	  .icon = "gnumeric-row-size",
2806 	  .label = N_("Auto Fit _Height"),
2807 	  .tooltip = N_("Ensure rows are just tall enough to display content of selection"),
2808 	  .callback = G_CALLBACK (cb_format_cells_auto_fit_height)
2809 	},
2810 	{ .name = "FormatCellsFitWidth",
2811 	  .icon = "gnumeric-column-size",
2812 	  .label = N_("Auto Fit _Width"),
2813 	  .tooltip = N_("Ensure columns are just wide enough to display content of selection"),
2814 	  .callback = G_CALLBACK (cb_format_cells_auto_fit_width)
2815 	},
2816 
2817 
2818 /* Format -> Col */
2819 	{ .name = "ColumnSize",
2820 	  .icon = "gnumeric-column-size",
2821 	  .label = N_("_Width..."),
2822 	  .tooltip = N_("Change width of the selected columns"),
2823 	  .callback = G_CALLBACK (cb_set_column_width)
2824 	},
2825 	{ .name = "ColumnAutoSize",
2826 	  .icon = "gnumeric-column-size",
2827 	  .label = N_("_Auto Fit Width"),
2828 	  .tooltip = N_("Ensure columns are just wide enough to display their content"),
2829 	  .callback = G_CALLBACK (cb_format_column_auto_fit)
2830 	},
2831 	{ .name = "ColumnHide",
2832 	  .icon = "gnumeric-column-hide",
2833 	  .label = N_("_Hide"),
2834 	  .accelerator = "<control>0",
2835 	  .tooltip = N_("Hide the selected columns"),
2836 	  .callback = G_CALLBACK (cb_format_column_hide)
2837 	},
2838 	{ .name = "ColumnUnhide",
2839 	  .icon = "gnumeric-column-unhide",
2840 	  .label = N_("_Unhide"),
2841 	  .accelerator = "<control>parenright",
2842 	  .tooltip = N_("Make any hidden columns in the selection visible"),
2843 	  .callback = G_CALLBACK (cb_format_column_unhide)
2844 	},
2845 	{ .name = "ColumnDefaultSize",
2846 	  .icon = "gnumeric-column-size",
2847 	  .label = N_("_Standard Width"),
2848 	  .tooltip = N_("Change the default column width"),
2849 	  .callback = G_CALLBACK (cb_format_column_std_width)
2850 	},
2851 
2852 /* Format -> Row */
2853 	{ .name = "RowSize",
2854 	  .icon = "gnumeric-row-size",
2855 	  .label = N_("H_eight..."),
2856 	  .tooltip = N_("Change height of the selected rows"),
2857 	  .callback = G_CALLBACK (cb_set_row_height)
2858 	},
2859 	{ .name = "RowAutoSize",
2860 	  .icon = "gnumeric-row-size",
2861 	  .label = N_("_Auto Fit Height"),
2862 	  .tooltip = N_("Ensure rows are just tall enough to display their content"),
2863 	  .callback = G_CALLBACK (cb_format_row_auto_fit)
2864 	},
2865 	{ .name = "RowHide",
2866 	  .icon = "gnumeric-row-hide",
2867 	  .label = N_("_Hide"),
2868 	  .accelerator = "<control>9",
2869 	  .tooltip = N_("Hide the selected rows"),
2870 	  .callback = G_CALLBACK (cb_format_row_hide)
2871 	},
2872 	{ .name = "RowUnhide",
2873 	  .icon = "gnumeric-row-unhide",
2874 	  .label = N_("_Unhide"),
2875 	  .accelerator = "<control>parenleft",
2876 	  .tooltip = N_("Make any hidden rows in the selection visible"),
2877 	  .callback = G_CALLBACK (cb_format_row_unhide)
2878 	},
2879 	{ .name = "RowDefaultSize",
2880 	  .icon = "gnumeric-row-size",
2881 	  .label = N_("_Standard Height"),
2882 	  .tooltip = N_("Change the default row height"),
2883 	  .callback = G_CALLBACK (cb_format_row_std_height)
2884 	},
2885 
2886 /* Tools */
2887 	{ .name = "ToolsPlugins",
2888 	  .label = N_("_Plug-ins..."),
2889 	  .tooltip = N_("Manage available plugin modules"),
2890 	  .callback = G_CALLBACK (cb_tools_plugins)
2891 	},
2892 	{ .name = "ToolsAutoCorrect",
2893 	  .label = N_("Auto _Correct..."),
2894 	  .tooltip = N_("Automatically perform simple spell checking"),
2895 	  .callback = G_CALLBACK (cb_tools_autocorrect)
2896 	},
2897 	{ .name = "ToolsAutoSave",
2898 	  .label = N_("_Auto Save..."),
2899 	  .tooltip = N_("Automatically save the current document at regular intervals"),
2900 	  .callback = G_CALLBACK (cb_tools_auto_save)
2901 	},
2902 	{ .name = "ToolsGoalSeek",
2903 	  .label = N_("_Goal Seek..."),
2904 	  .tooltip = N_("Iteratively recalculate to find a target value"),
2905 	  .callback = G_CALLBACK (cb_tools_goal_seek)
2906 	},
2907 	{ .name = "ToolsSolver",
2908 	  .label = N_("_Solver..."),
2909 	  .tooltip = N_("Iteratively recalculate with constraints to approach a target value"),
2910 	  .callback = G_CALLBACK (cb_tools_solver)
2911 	},
2912 	{ .name = "ToolsSimulation",
2913 	  .label = N_("Si_mulation..."),
2914 	  .tooltip = N_("Test decision alternatives by using Monte Carlo "
2915 		   "simulation to find out probable outputs and risks related to them"),
2916 	  .callback = G_CALLBACK (cb_tools_simulation)
2917 	},
2918 	{ .name = "ToolsCompare",
2919 	  .label = N_("Compare Sheets..."),
2920 	  .tooltip = N_("Find differences between two sheets"),
2921 	  .callback = G_CALLBACK (cb_tools_compare)
2922 	},
2923 
2924 /* Tools -> Scenarios */
2925 	{ .name = "ToolsScenarios",
2926 	  .label = N_("_View..."),
2927 	  .tooltip = N_("View, delete and report different scenarios"),
2928 	  .callback = G_CALLBACK (cb_tools_scenarios)
2929 	},
2930 	{ .name = "ToolsScenarioAdd",
2931 	  .label = N_("_Add..."),
2932 	  .tooltip = N_("Add a new scenario"),
2933 	  .callback = G_CALLBACK (cb_tools_scenario_add)
2934 	},
2935 
2936 /* Statistics */
2937 
2938 	{ .name = "ToolsSampling",
2939 	  .label = N_("_Sampling..."),
2940 	  .tooltip = N_("Periodic and random samples"),
2941 	  .callback = G_CALLBACK (cb_tools_sampling)
2942 	},
2943 
2944 /* Statistics -> Descriptive*/
2945 
2946 	{ .name = "ToolsCorrelation",
2947 	  .label = N_("_Correlation..."),
2948 	  .tooltip = N_("Pearson Correlation"),
2949 	  .callback = G_CALLBACK (cb_tools_correlation)
2950 	},
2951 	{ .name = "ToolsCovariance",
2952 	  .label = N_("Co_variance..."),
2953 	  .tooltip = N_("Covariance"),
2954 	  .callback = G_CALLBACK (cb_tools_covariance)
2955 	},
2956 	{ .name = "ToolsDescStatistics",
2957 	  .label = N_("_Descriptive Statistics..."),
2958 	  .tooltip = N_("Various summary statistics"),
2959 	  .callback = G_CALLBACK (cb_tools_desc_statistics)
2960 	},
2961 
2962 /* Statistics -> Descriptive -> Frequencies */
2963 
2964 	{ .name = "ToolsFrequency",
2965 	  .label = N_("Fre_quency Tables..."),
2966 	  .tooltip = N_("Frequency tables for non-numeric data"),
2967 	  .callback = G_CALLBACK (cb_tools_frequency)
2968 	},
2969 	{ .name = "ToolsHistogram",
2970 	  .label = N_("_Histogram..."),
2971 	  .tooltip = N_("Various frequency tables for numeric data"),
2972 	  .callback = G_CALLBACK (cb_tools_histogram)
2973 	},
2974 	{ .name = "ToolsRanking",
2975 	  .label = N_("Ranks And _Percentiles..."),
2976 	  .tooltip = N_("Ranks, placements and percentiles"),
2977 	  .callback = G_CALLBACK (cb_tools_ranking)
2978 	},
2979 
2980 /* Statistics -> DependentObservations */
2981 
2982 	{ .name = "ToolsFourier",
2983 	  .label = N_("_Fourier Analysis..."),
2984 	  .tooltip = N_("Fourier Analysis"),
2985 	  .callback = G_CALLBACK (cb_tools_fourier)
2986 	},
2987 	{ .name = "ToolsPrincipalComponents",
2988 	  .label =
2989 	  N_("Principal Components Analysis..."),
2990 	  .tooltip = N_("Principal Components Analysis"),
2991 	  .callback = G_CALLBACK (cb_tools_principal_components)
2992 	},
2993 /* Statistics -> DependentObservations -> Forecast*/
2994 
2995 	{ .name = "ToolsExpSmoothing",
2996 	  .label = N_("_Exponential Smoothing..."),
2997 	  .tooltip = N_("Exponential smoothing..."),
2998 	  .callback = G_CALLBACK (cb_tools_exp_smoothing)
2999 	},
3000 	{ .name = "ToolsAverage",
3001 	  .label = N_("_Moving Average..."),
3002 	  .tooltip = N_("Moving average..."),
3003 	  .callback = G_CALLBACK (cb_tools_average)
3004 	},
3005 	{ .name = "ToolsRegression",
3006 	  .label = N_("_Regression..."),
3007 	  .tooltip = N_("Regression Analysis"),
3008 	  .callback = G_CALLBACK (cb_tools_regression)
3009 	},
3010 	{ .name = "ToolsKaplanMeier",
3011 	  .label = N_("_Kaplan-Meier Estimates..."),
3012 	  .tooltip = N_("Creation of Kaplan-Meier Survival Curves"),
3013 	  .callback = G_CALLBACK (cb_tools_kaplan_meier)
3014 	},
3015 
3016 /* Statistics -> OneSample */
3017 
3018 	{ .name = "ToolsNormalityTests",
3019 	  .label = N_("_Normality Tests..."),
3020 	  .tooltip = N_("Testing a sample for normality"),
3021 	  .callback = G_CALLBACK (cb_tools_normality_tests)
3022 	},
3023 	{ .name = "ToolsOneMeanTest",
3024 	  .label = N_("Claims About a _Mean..."),
3025 	  .tooltip = N_("Testing the value of a mean"),
3026 	  .callback = G_CALLBACK (cb_tools_one_mean_test)
3027 	},
3028 
3029 /* Statistics -> OneSample -> OneMedian*/
3030 
3031 	{ .name = "ToolsOneMedianSignTest",
3032 	  .label = N_("_Sign Test..."),
3033 	  .tooltip = N_("Testing the value of a median"),
3034 	  .callback = G_CALLBACK (cb_tools_sign_test_one_median)
3035 	},
3036 	{ .name = "ToolsOneMedianWilcoxonSignedRank",
3037 	  .label = N_("_Wilcoxon Signed Rank Test..."),
3038 	  .tooltip = N_("Testing the value of a median"),
3039 	  .callback = G_CALLBACK (cb_tools_wilcoxon_signed_rank_one_median)
3040 	},
3041 
3042 /* Statistics -> TwoSamples */
3043 
3044 	{ .name = "ToolsFTest",
3045 	  .label = N_("Claims About Two _Variances"),
3046 	  .tooltip = N_("Comparing two population variances"),
3047 	  .callback = G_CALLBACK (cb_tools_ftest)
3048 	},
3049 
3050 /* Statistics -> TwoSamples -> Two Means*/
3051 
3052 	{ .name = "ToolTTestPaired",
3053 	  .label = N_("_Paired Samples..."),
3054 	  .tooltip = N_("Comparing two population means for two paired samples"),
3055 	  .callback = G_CALLBACK (cb_tools_ttest_paired)
3056 	},
3057 
3058 	{ .name = "ToolTTestEqualVar",
3059 	  .label = N_("Unpaired Samples, _Equal Variances..."),
3060 	  .tooltip = N_("Comparing two population means for two unpaired samples from populations with equal variances"),
3061 	  .callback = G_CALLBACK (cb_tools_ttest_equal_var)
3062 	},
3063 
3064 	{ .name = "ToolTTestUnequalVar",
3065 	  .label = N_("Unpaired Samples, _Unequal Variances..."),
3066 	  .tooltip = N_("Comparing two population means for two unpaired samples from populations with unequal variances"),
3067 	  .callback = G_CALLBACK (cb_tools_ttest_unequal_var)
3068 	},
3069 
3070 	{ .name = "ToolZTest",
3071 	  .label = N_("Unpaired Samples, _Known Variances..."),
3072 	  .tooltip = N_("Comparing two population means from populations with known variances"),
3073 	  .callback = G_CALLBACK (cb_tools_ztest)
3074 	},
3075 
3076 /* Statistics -> TwoSamples -> Two Medians*/
3077 
3078 	{ .name = "ToolsTwoMedianSignTest",
3079 	  .label = N_("_Sign Test..."),
3080 	  .tooltip = N_("Comparing the values of two medians of paired observations"),
3081 	  .callback = G_CALLBACK (cb_tools_sign_test_two_medians)
3082 	},
3083 	{ .name = "ToolsTwoMedianWilcoxonSignedRank",
3084 	  .label = N_("_Wilcoxon Signed Rank Test..."),
3085 	  .tooltip = N_("Comparing the values of two medians of paired observations"),
3086 	  .callback = G_CALLBACK (cb_tools_wilcoxon_signed_rank_two_medians)
3087 	},
3088 	{ .name = "ToolsTwoMedianWilcoxonMannWhitney",
3089 	  .label = N_("Wilcoxon-_Mann-Whitney Test..."),
3090 	  .tooltip = N_("Comparing the values of two medians of unpaired observations"),
3091 	  .callback = G_CALLBACK (cb_tools_wilcoxon_mann_whitney)
3092 	},
3093 
3094 /* Statistics -> MultipleSamples */
3095 
3096 /* Statistics -> MultipleSamples -> ANOVA*/
3097 
3098 	{ .name = "ToolsANOVAoneFactor",
3099 	  .label = N_("_One Factor..."),
3100 	  .tooltip = N_("One Factor Analysis of Variance..."),
3101 	  .callback = G_CALLBACK (cb_tools_anova_one_factor)
3102 	},
3103 	{ .name = "ToolsANOVAtwoFactor",
3104 	  .label = N_("_Two Factor..."),
3105 	  .tooltip = N_("Two Factor Analysis of Variance..."),
3106 	  .callback = G_CALLBACK (cb_tools_anova_two_factor)
3107 	},
3108 
3109 /* Statistics -> MultipleSamples -> ContingencyTable*/
3110 
3111 	{ .name = "ToolsHomogeneity",
3112 	  .label = N_("Test of _Homogeneity..."),
3113 	  .tooltip = N_("Chi Squared Test of Homogeneity..."),
3114 	  .callback = G_CALLBACK (cb_tools_chi_square_homogeneity)
3115 	},
3116 	{ .name = "ToolsIndependence",
3117 	  .label = N_("Test of _Independence..."),
3118 	  .tooltip = N_("Chi Squared Test of Independence..."),
3119 	  .callback = G_CALLBACK (cb_tools_chi_square_independence)
3120 	},
3121 
3122 /* Data */
3123 	{ .name = "DataSort",
3124 	  .icon = "view-sort-ascending",
3125 	  .label = N_("_Sort..."),
3126 	  .tooltip = N_("Sort the selected region"),
3127 	  .callback = G_CALLBACK (cb_data_sort)
3128 	},
3129 	{ .name = "DataShuffle",
3130 	  .label = N_("Sh_uffle..."),
3131 	  .tooltip = N_("Shuffle cells, rows or columns"),
3132 	  .callback = G_CALLBACK (cb_data_shuffle)
3133 	},
3134 	{ .name = "DataValidate",
3135 	  .label = N_("_Validate..."),
3136 	  .tooltip = N_("Validate input with preset criteria"),
3137 	  .callback = G_CALLBACK (cb_data_validate)
3138 	},
3139 	{ .name = "DataTextToColumns",
3140 	  .label = N_("T_ext to Columns..."),
3141 	  .tooltip = N_("Parse the text in the selection into data"),
3142 	  .callback = G_CALLBACK (cb_data_text_to_columns)
3143 	},
3144 	{ .name = "DataConsolidate",
3145 	  .label = N_("_Consolidate..."),
3146 	  .tooltip = N_("Consolidate regions using a function"),
3147 	  .callback = G_CALLBACK (cb_data_consolidate)
3148 	},
3149 	{ .name = "DataTable",
3150 	  .label = N_("_Table..."),
3151 	  .tooltip = N_("Create a Data Table to evaluate a function with multiple inputs"),
3152 	  .callback = G_CALLBACK (cb_data_table)
3153 	},
3154 	{ .name = "DataExport",
3155 	  .label = N_("E_xport into Other Format..."),
3156 	  .tooltip = N_("Export the current workbook or sheet"),
3157 	  .callback = G_CALLBACK (cb_data_export)
3158 	},
3159 	{ .name = "DataExportText",
3160 	  .label = N_("Export as _Text File..."),
3161 	  .tooltip = N_("Export the current sheet as a text file"),
3162 	  .callback = G_CALLBACK (cb_data_export_text)
3163 	},
3164 	{ .name = "DataExportCSV",
3165 	  .label = N_("Export as _CSV File..."),
3166 	  .tooltip = N_("Export the current sheet as a csv file"),
3167 	  .callback = G_CALLBACK (cb_data_export_csv)
3168 	},
3169 	{ .name = "DataExportRepeat",
3170 	  .label = N_("Repeat Export"),
3171 	  .accelerator = "<control>E",
3172 	  .tooltip = N_("Repeat the last data export"),
3173 	  .callback = G_CALLBACK (cb_data_export_repeat)
3174 	},
3175 
3176 /* Data -> Fill */
3177 	{ .name = "EditFillAutofill",
3178 	  .label = N_("Auto_fill"),
3179 	  .tooltip = N_("Automatically fill the current selection"),
3180 	  .callback = G_CALLBACK (cb_edit_fill_autofill)
3181 	},
3182 	{ .name = "ToolsMerge",
3183 	  .label = N_("_Merge..."),
3184 	  .tooltip = N_("Merges columnar data into a sheet creating duplicate sheets for each row"),
3185 	  .callback = G_CALLBACK (cb_tools_merge)
3186 	},
3187 	{ .name = "ToolsTabulate",
3188 	  .label = N_("_Tabulate Dependency..."),
3189 	  .tooltip = N_("Make a table of a cell's value as a function of other cells"),
3190 	  .callback = G_CALLBACK (cb_tools_tabulate)
3191 	},
3192 	{ .name = "EditFillSeries",
3193 	  .label = N_("_Series..."),
3194 	  .tooltip = N_("Fill according to a linear or exponential series"),
3195 	  .callback = G_CALLBACK (cb_edit_fill_series)
3196 	},
3197 	{ .name = "RandomGeneratorUncorrelated",
3198 	  .label = N_("_Uncorrelated..."),
3199 	  .tooltip = N_("Generate random numbers of a selection of distributions"),
3200 	  .callback = G_CALLBACK (cb_tools_random_generator_uncorrelated)
3201 	},
3202 	{ .name = "RandomGeneratorCorrelated",
3203 	  .label = N_("_Correlated..."),
3204 	  .tooltip = N_("Generate variates for correlated normal distributed random variables"),
3205 	  .callback = G_CALLBACK (cb_tools_random_generator_correlated)
3206 	},
3207 	{ .name = "CopyDown",
3208 	  .label = N_("Fill Downwards"),
3209 	  .accelerator = "<control>D",
3210 	  .tooltip = N_("Copy the content from the top row to the cells below"),
3211 	  .callback = G_CALLBACK (cb_copydown)
3212 	},
3213 	{ .name = "CopyRight",
3214 	  .label = N_("Fill to Right"),
3215 	  .accelerator = "<control>R",
3216 	  .tooltip = N_("Copy the content from the left column to the cells on the right"),
3217 	  .callback = G_CALLBACK (cb_copyright)
3218 	},
3219 
3220 
3221 /* Data -> Outline */
3222 	{ .name = "DataOutlineHideDetail",
3223 	  .icon = "gnumeric-detail-hide",
3224 	  .label = N_("_Hide Detail"),
3225 	  .tooltip = N_("Collapse an outline group"),
3226 	  .callback = G_CALLBACK (cb_data_hide_detail)
3227 	},
3228 	{ .name = "DataOutlineShowDetail",
3229 	  .icon = "gnumeric-detail-show",
3230 	  .label = N_("_Show Detail"),
3231 	  .tooltip = N_("Uncollapse an outline group"),
3232 	  .callback = G_CALLBACK (cb_data_show_detail)
3233 	},
3234 	{ .name = "DataOutlineGroup",
3235 	  .icon = "gnumeric-group",
3236 	  .label = N_("_Group..."),
3237 	  .accelerator = "<shift><alt>Right",
3238 	  .tooltip = N_("Add an outline group"),
3239 	  .callback = G_CALLBACK (cb_data_group)
3240 	},
3241 	{ .name = "DataOutlineUngroup",
3242 	  .icon = "gnumeric-ungroup",
3243 	  .label = N_("_Ungroup..."),
3244 	  .accelerator = "<shift><alt>Left",
3245 	  .tooltip = N_("Remove an outline group"),
3246 	  .callback = G_CALLBACK (cb_data_ungroup)
3247 	},
3248 
3249 /* Data -> Filter */
3250 	{ .name = "DataAutoFilter",
3251 	  .icon = "gnumeric-autofilter",
3252 	  .label = N_("Add _Auto Filter"),
3253 	  .tooltip = N_("Add or remove a filter"),
3254 	  .callback = G_CALLBACK (cb_auto_filter)
3255 	},
3256 	{ .name = "DataFilterShowAll",
3257 	  .label = N_("_Clear Advanced Filter"),
3258 	  .tooltip = N_("Show all rows hidden by an advanced filter"),
3259 	  .callback = G_CALLBACK (cb_show_all)
3260 	},
3261 	{ .name = "DataFilterAdvancedfilter",
3262 	  .label = N_("Advanced _Filter..."),
3263 	  .tooltip = N_("Filter data with given criteria"),
3264 	  .callback = G_CALLBACK (cb_data_filter)
3265 	},
3266 /* Data -> External */
3267 	{ .name = "DataImportText",
3268 	  .label = N_("Import _Text File..."),
3269 	  .tooltip = N_("Import data from a text file"),
3270 	  .callback = G_CALLBACK (cb_data_import_text)
3271 	},
3272 	{ .name = "DataImportOther",
3273 	  .label = N_("Import _Other File..."),
3274 	  .tooltip = N_("Import data from a file"),
3275 	  .callback = G_CALLBACK (cb_data_import_other)
3276 	},
3277 
3278 /* Data -> Data Slicer */
3279 	/* label and tip are context dependent, see wbcg_menu_state_update */
3280 	{ .name = "DataSlicer",
3281 	  .label = N_("Add _Data Slicer"),
3282 	  .tooltip = N_("Create a data slicer"),
3283 	  .callback = G_CALLBACK (cb_data_slicer_create)
3284 	},
3285 	{ .name = "DataSlicerRefresh",
3286 	  .label = N_("_Refresh"),
3287 	  .tooltip = N_("Regenerate a data slicer from the source data"),
3288 	  .callback = G_CALLBACK (cb_data_slicer_refresh)
3289 	},
3290 	{ .name = "DataSlicerEdit",
3291 	  .label = N_("_Edit Data Slicer..."),
3292 	  .tooltip = N_("Adjust a data slicer"),
3293 	  .callback = G_CALLBACK (cb_data_slicer_edit)
3294 	},
3295 
3296 /* Standard Toolbar */
3297 	{ .name = "AutoSum",
3298 	  .icon = "gnumeric-autosum",
3299 	  .label = N_("Sum"),
3300 	  .accelerator = "<alt>equal",
3301 	  .tooltip = N_("Sum into the current cell"),
3302 	  .callback = G_CALLBACK (cb_autosum)
3303 	},
3304 	{ .name = "InsertFormula",
3305 	  .icon = "gnumeric-formulaguru",
3306 	  .label = N_("_Function..."),
3307 	  .tooltip = N_("Edit a function in the current cell"),
3308 	  .callback = G_CALLBACK (cb_formula_guru)
3309 	},
3310 
3311 	{ .name = "SortAscending",
3312 	  .icon = "view-sort-ascending",
3313 	  .label = N_("Sort Ascending"),
3314 	  .tooltip = N_("Sort the selected region in ascending order based on the first column selected"),
3315 	  .callback = G_CALLBACK (cb_sort_ascending)
3316 	},
3317 	{ .name = "SortDescending",
3318 	  .icon = "view-sort-descending",
3319 	  .label = N_("Sort Descending"),
3320 	  .tooltip = N_("Sort the selected region in descending order based on the first column selected"),
3321 	  .callback = G_CALLBACK (cb_sort_descending)
3322 	},
3323 
3324 /* Object Toolbar */
3325 	{ .name = "CreateFrame",
3326 	  .icon = "gnumeric-object-frame",
3327 	  .label = N_("Frame"),
3328 	  .tooltip = N_("Create a frame"),
3329 	  .callback = G_CALLBACK (cmd_create_frame)
3330 	},
3331 	{ .name = "CreateCheckbox",
3332 	  .icon = "gnumeric-object-checkbox",
3333 	  .label = N_("Checkbox"),
3334 	  .tooltip = N_("Create a checkbox"),
3335 	  .callback = G_CALLBACK (cmd_create_checkbox)
3336 	},
3337 	{ .name = "CreateScrollbar",
3338 	  .icon = "gnumeric-object-scrollbar",
3339 	  .label = N_("Scrollbar"),
3340 	  .tooltip = N_("Create a scrollbar"),
3341 	  .callback = G_CALLBACK (cmd_create_scrollbar)
3342 	},
3343 	{ .name = "CreateSlider",
3344 	  .icon = "gnumeric-object-slider",
3345 	  .label = N_("Slider"),
3346 	  .tooltip = N_("Create a slider"),
3347 	  .callback = G_CALLBACK (cmd_create_slider)
3348 	},
3349 	{ .name = "CreateSpinButton",
3350 	  .icon = "gnumeric-object-spinbutton",
3351 	  .label = N_("SpinButton"),
3352 	  .tooltip = N_("Create a spin button"),
3353 	  .callback = G_CALLBACK (cmd_create_spinbutton)
3354 	},
3355 	{ .name = "CreateList",
3356 	  .icon = "gnumeric-object-list",
3357 	  .label = N_("List"),
3358 	  .tooltip = N_("Create a list"),
3359 	  .callback = G_CALLBACK (cmd_create_list)
3360 	},
3361 	{ .name = "CreateCombo",
3362 	  .icon = "gnumeric-object-combo",
3363 	  .label = N_("Combo Box"),
3364 	  .tooltip = N_("Create a combo box"),
3365 	  .callback = G_CALLBACK (cmd_create_combo)
3366 	},
3367 	{ .name = "CreateLine",
3368 	  .icon = "gnumeric-object-line",
3369 	  .label = N_("Line"),
3370 	  .tooltip = N_("Create a line object"),
3371 	  .callback = G_CALLBACK (cmd_create_line)
3372 	},
3373 	{ .name = "CreateArrow",
3374 	  .icon = "gnumeric-object-arrow",
3375 	  .label = N_("Arrow"),
3376 	  .tooltip = N_("Create an arrow object"),
3377 	  .callback = G_CALLBACK (cmd_create_arrow)
3378 	},
3379 	{ .name = "CreateRectangle",
3380 	  .icon = "gnumeric-object-rectangle",
3381 	  .label = N_("Rectangle"),
3382 	  .tooltip = N_("Create a rectangle object"),
3383 	  .callback = G_CALLBACK (cmd_create_rectangle)
3384 	},
3385 	{ .name = "CreateEllipse",
3386 	  .icon = "gnumeric-object-ellipse",
3387 	  .label = N_("Ellipse"),
3388 	  .tooltip = N_("Create an ellipse object"),
3389 	  .callback = G_CALLBACK (cmd_create_ellipse)
3390 	},
3391 	{ .name = "CreateButton",
3392 	  .icon = "gnumeric-object-button",
3393 	  .label = N_("Button"),
3394 	  .tooltip = N_("Create a button"),
3395 	  .callback = G_CALLBACK (cmd_create_button)
3396 	},
3397 	{ .name = "CreateRadioButton",
3398 	  .icon = "gnumeric-object-radiobutton",
3399 	  .label = N_("RadioButton"),
3400 	  .tooltip = N_("Create a radio button"),
3401 	  .callback = G_CALLBACK (cmd_create_radiobutton)
3402 	},
3403 
3404 /* Format toolbar */
3405 	{ .name = "FormatMergeCells",
3406 	  .icon = "gnumeric-cells-merge",
3407 	  .label = N_("Merge"),
3408 	  .tooltip = N_("Merge a range of cells"),
3409 	  .callback = G_CALLBACK (cb_merge_cells)
3410 	},
3411 	{ .name = "FormatUnmergeCells",
3412 	  .icon = "gnumeric-cells-split",
3413 	  .label = N_("Unmerge"),
3414 	  .tooltip = N_("Split merged ranges of cells"),
3415 	  .callback = G_CALLBACK (cb_unmerge_cells)
3416 	},
3417 
3418 	{ .name = "FormatAsGeneral",
3419 	  .label = N_("General"),
3420 	  .accelerator = "<control>asciitilde",
3421 	  .tooltip = N_("Format the selection as General"),
3422 	  .callback = G_CALLBACK (cb_format_as_general)
3423 	},
3424 	{ .name = "FormatAsNumber",
3425 	  .label = N_("Number"),
3426 	  .accelerator = "<control>exclam",
3427 	  .tooltip = N_("Format the selection as numbers"),
3428 	  .callback = G_CALLBACK (cb_format_as_number)
3429 	},
3430 	{ .name = "FormatAsCurrency",
3431 	  .label = N_("Currency"),
3432 	  .accelerator = "<control>dollar",
3433 	  .tooltip = N_("Format the selection as currency"),
3434 	  .callback = G_CALLBACK (cb_format_as_currency)
3435 	},
3436 	{ .name = "FormatAsAccounting",
3437 	  .icon = "gnumeric-format-accounting",
3438 	  .label = N_("Accounting"),
3439 	  .tooltip = N_("Format the selection as accounting"),
3440 	  .callback = G_CALLBACK (cb_format_as_accounting)
3441 	},
3442 	{ .name = "FormatAsPercentage",
3443 	  .icon = "gnumeric-format-percentage",
3444 	  .label = N_("Percentage"),
3445 	  .accelerator = "<control>percent",
3446 	  .tooltip = N_("Format the selection as percentage"),
3447 	  .callback = G_CALLBACK (cb_format_as_percentage)
3448 	},
3449 	{ .name = "FormatAsScientific",
3450 	  .label = N_("Scientific"),
3451 	  .accelerator = "<control>asciicircum",
3452 	  .tooltip = N_("Format the selection as scientific"),
3453 	  .callback = G_CALLBACK (cb_format_as_scientific)
3454 	},
3455 	{ .name = "FormatAsDate",
3456 	  .label = N_("Date"),
3457 	  .accelerator = "<control>numbersign",
3458 	  .tooltip = N_("Format the selection as date"),
3459 	  .callback = G_CALLBACK (cb_format_as_date)
3460 	},
3461 	{ .name = "FormatAsTime",
3462 	  .label = N_("Time"),
3463 	  .accelerator = "<control>at",
3464 	  .tooltip = N_("Format the selection as time"),
3465 	  .callback = G_CALLBACK (cb_format_as_time)
3466 	},
3467 	{ .name = "FormatAddBorders",
3468 	  .label = N_("AddBorders"),
3469 	  .accelerator = "<control>ampersand",
3470 	  .tooltip = N_("Add a border around the selection"),
3471 	  .callback = G_CALLBACK (cb_format_add_borders)
3472 	},
3473 	{ .name = "FormatClearBorders",
3474 	  .label = N_("ClearBorders"),
3475 	  .accelerator = "<control>underscore",
3476 	  .tooltip = N_("Clear the border around the selection"),
3477 	  .callback = G_CALLBACK (cb_format_clear_borders)
3478 	},
3479 
3480 	{ .name = "FormatWithThousands",
3481 	  .icon = "gnumeric-format-thousand-separator",
3482 	  .label = N_("Thousands Separator"),
3483 	  .tooltip = N_("Set the format of the selected cells to include a thousands separator"),
3484 	  .callback = G_CALLBACK (cb_format_with_thousands)
3485 	},
3486 	{ .name = "FormatIncreasePrecision",
3487 	  .icon = "gnumeric-format-precision-increase",
3488 	  .label = N_("Increase Precision"),
3489 	  .tooltip = N_("Increase the number of decimals displayed"),
3490 	  .callback = G_CALLBACK (cb_format_inc_precision)
3491 	},
3492 	{ .name = "FormatDecreasePrecision",
3493 	  .icon = "gnumeric-format-precision-decrease",
3494 	  .label = N_("Decrease Precision"),
3495 	  .tooltip = N_("Decrease the number of decimals displayed"),
3496 	  .callback = G_CALLBACK (cb_format_dec_precision)
3497 	},
3498 
3499 	/* Gtk marks these accelerators as invalid because they use Tab
3500 	 * enable them manually in gnm-pane.c */
3501 	{ .name = "FormatDecreaseIndent",
3502 	  .icon = "format-indent-less",
3503 	  .accelerator = "<control><alt><shift>Tab",
3504 	  .tooltip = N_("Decrease the indent, and align the contents to the left"),
3505 	  .callback = G_CALLBACK (cb_format_dec_indent)
3506 	},
3507 	{ .name = "FormatIncreaseIndent",
3508 	  .icon = "format-indent-more",
3509 	  .accelerator = "<control><alt>Tab",
3510 	  .tooltip = N_("Increase the indent, and align the contents to the left"),
3511 	  .callback = G_CALLBACK (cb_format_inc_indent)
3512 	},
3513 
3514 	/* ---------------------------------------- */
3515 
3516 	{ .name = "SheetDisplayOutlines",
3517 	  .toggle = TRUE,
3518 	  .label = N_("Display _Outlines"),
3519 	  .accelerator = "<control>8",
3520 	  .tooltip = N_("Toggle whether or not to display outline groups"),
3521 	  .callback = G_CALLBACK (cb_sheet_pref_display_outlines)
3522 	},
3523 	{ .name = "SheetOutlineBelow",
3524 	  .toggle = TRUE,
3525 	  .label = N_("Outlines _Below"),
3526 	  .tooltip = N_("Toggle whether to display row outlines on top or bottom"),
3527 	  .callback = G_CALLBACK (cb_sheet_pref_outline_symbols_below)
3528 	},
3529 	{ .name = "SheetOutlineRight",
3530 	  .toggle = TRUE,
3531 	  .label = N_("Outlines _Right"),
3532 	  .tooltip = N_("Toggle whether to display column outlines on the left or right"),
3533 	  .callback = G_CALLBACK (cb_sheet_pref_outline_symbols_right)
3534 	},
3535 	{ .name = "SheetDisplayFormulas",
3536 	  .toggle = TRUE,
3537 	  .icon = "gnumeric-formulaguru",
3538 	  .label = N_("Display _Formul\303\246"),
3539 	  .accelerator = "<control>quoteleft",
3540 	  .tooltip = N_("Display the value of a formula or the formula itself"),
3541 	  .callback = G_CALLBACK (cb_sheet_pref_display_formulas)
3542 	},
3543 	{ .name = "SheetHideZeros",
3544 	  .toggle = TRUE,
3545 	  .label = N_("_Hide Zeros"),
3546 	  .tooltip = N_("Toggle whether or not to display zeros as blanks"),
3547 	  .callback = G_CALLBACK (cb_sheet_pref_hide_zero)
3548 	},
3549 	{ .name = "SheetHideGridlines",
3550 	  .toggle = TRUE,
3551 	  .label = N_("Hide _Gridlines"),
3552 	  .tooltip = N_("Toggle whether or not to display gridlines"),
3553 	  .callback = G_CALLBACK (cb_sheet_pref_hide_grid)
3554 	},
3555 	{ .name = "SheetHideColHeader",
3556 	  .toggle = TRUE,
3557 	  .label = N_("Hide _Column Headers"),
3558 	  .tooltip = N_("Toggle whether or not to display column headers"),
3559 	  .callback = G_CALLBACK (cb_sheet_pref_hide_col_header)
3560 	},
3561 	{ .name = "SheetHideRowHeader",
3562 	  .toggle = TRUE,
3563 	  .label = N_("Hide _Row Headers"),
3564 	  .tooltip = N_("Toggle whether or not to display row headers"),
3565 	  .callback = G_CALLBACK (cb_sheet_pref_hide_row_header)
3566 	},
3567 
3568 	/* TODO : Make this a sub menu when we have more convention types */
3569 	{ .name = "SheetUseR1C1",
3570 	  .toggle = TRUE,
3571 	  .label = N_("Use R1C1 N_otation "),
3572 	  .tooltip = N_("Display addresses as R1C1 or A1"),
3573 	  .callback = G_CALLBACK (cb_sheet_pref_use_r1c1)
3574 	},
3575 
3576 	{ .name = "AlignLeft",
3577 	  .toggle = TRUE,
3578 	  .icon = "format-justify-left",
3579 	  .label = N_("_Left Align"),
3580 	  .tooltip = N_("Align left"),
3581 	  .callback = G_CALLBACK (cb_align_left)
3582 	},
3583 	{ .name = "AlignCenter",
3584 	  .toggle = TRUE,
3585 	  .icon = "format-justify-center",
3586 	  .label = N_("_Center"),
3587 	  .tooltip = N_("Center horizontally"),
3588 	  .callback = G_CALLBACK (cb_align_center)
3589 	},
3590 	{ .name = "AlignRight",
3591 	  .toggle = TRUE,
3592 	  .icon = "format-justify-right",
3593 	  .label = N_("_Right Align"),
3594 	  .tooltip = N_("Align right"),
3595 	  .callback = G_CALLBACK (cb_align_right)
3596 	},
3597 	{ .name = "CenterAcrossSelection",
3598 	  .toggle = TRUE,
3599 	  .icon = "gnumeric-center-across-selection",
3600 	  .label = N_("_Center Across Selection"),
3601 	  .tooltip = N_("Center horizontally across the selection"),
3602 	  .callback = G_CALLBACK (cb_center_across_selection)
3603 	},
3604 	{ .name = "MergeAndCenter",
3605 	  .toggle = TRUE,
3606 	  .label = N_("_Merge and Center"),
3607 	  .tooltip = N_("Merge the selection into 1 cell, and center horizontally."),
3608 	  .callback = G_CALLBACK (cb_merge_and_center)
3609 	},
3610 #warning "Add justify"
3611 #warning "h/v distributed?"
3612 
3613 #warning "Get vertical alignment icons"
3614 	{ .name = "AlignTop",
3615 	  .toggle = TRUE,
3616 	  .label = N_("Align _Top"),
3617 	  .tooltip = N_("Align Top"),
3618 	  .callback = G_CALLBACK (cb_align_top)
3619 	},
3620 	{ .name = "AlignVCenter",
3621 	  .toggle = TRUE,
3622 	  .label = N_("_Vertically Center"),
3623 	  .tooltip = N_("Vertically Center"),
3624 	  .callback = G_CALLBACK (cb_align_vcenter)
3625 	},
3626 	{ .name = "AlignBottom",
3627 	  .toggle = TRUE,
3628 	  .label = N_("Align _Bottom"),
3629 	  .tooltip = N_("Align Bottom"),
3630 	  .callback = G_CALLBACK (cb_align_bottom)
3631 	},
3632 };
3633 
3634 static GnmActionEntry const font_actions[] = {
3635 	{ .name = "FontBold",
3636 	  .toggle = TRUE,
3637 	  .icon = "format-text-bold",
3638 	  .label = N_("_Bold"),
3639 	  .accelerator = "<control>b",	/* ALSO "<control>2" */
3640 	  .tooltip = N_("Bold"),
3641 	  .callback = G_CALLBACK (cb_font_bold),
3642 	  .is_active = FALSE },
3643 	{ .name = "FontItalic",
3644 	  .toggle = TRUE,
3645 	  .icon = "format-text-italic",
3646 	  .label = N_("_Italic"),
3647 	  .accelerator = "<control>i",	/* ALSO "<control>3" */
3648 	  .tooltip = N_("Italic"),
3649 	  .callback = G_CALLBACK (cb_font_italic),
3650 	  .is_active = FALSE },
3651 	{ .name = "FontUnderline",
3652 	  .toggle = TRUE,
3653 	  .icon = "format-text-underline",
3654 	  .label = N_("_Underline"),
3655 	  .accelerator = "<control>u",	/* ALSO "<control>4" */
3656 	  .tooltip = N_("Underline"),
3657 	  .callback = G_CALLBACK (cb_font_underline),
3658 	  .is_active = FALSE },
3659 	{ .name = "FontDoubleUnderline",
3660 	  .toggle = TRUE,
3661 	  .icon = "stock_text_underlined-double",	/* from icon theme */
3662 	  .label = N_("_Double Underline"),
3663 	  .accelerator = "<control><shift>d",
3664 	  .tooltip = N_("Double Underline"),
3665 	  .callback = G_CALLBACK (cb_font_double_underline),
3666 	  .is_active = FALSE },
3667 	{ .name = "FontSingleLowUnderline",
3668 	  .toggle = TRUE,
3669 	  .label = N_("_Single Low Underline"),
3670 	  .accelerator = "<control><shift>l",
3671 	  .tooltip = N_("Single Low Underline"),
3672 	  .callback = G_CALLBACK (cb_font_underline_low),
3673 	  .is_active = FALSE },
3674 	{ .name = "FontDoubleLowUnderline",
3675 	  .toggle = TRUE,
3676 	  .label = N_("Double _Low Underline"),
3677 	  .tooltip = N_("Double Low Underline"),
3678 	  .callback = G_CALLBACK (cb_font_double_underline_low),
3679 	  .is_active = FALSE },
3680 	{ .name = "FontStrikeThrough",
3681 	  .toggle = TRUE,
3682 	  .icon = "format-text-strikethrough",
3683 	  .label = N_("_Strikethrough"),
3684 	  .accelerator = "<control>5",
3685 	  .tooltip = N_("Strikethrough"),
3686 	  .callback = G_CALLBACK (cb_font_strikethrough),
3687 	  .is_active = FALSE },
3688 	{ .name = "FontSuperscript",
3689 	  .toggle = TRUE,
3690 	  .icon = "gnumeric-superscript",
3691 	  .label = N_("Su_perscript"),
3692 	  .accelerator = "<control>asciicircum",
3693 	  .tooltip = N_("Superscript"),
3694 	  .callback = G_CALLBACK (cb_font_superscript),
3695 	  .is_active = FALSE },
3696 	{ .name = "FontSubscript",
3697 	  .toggle = TRUE,
3698 	  .icon = "gnumeric-subscript",
3699 	  .label = N_("Subscrip_t"),
3700 	  .accelerator = "<control>underscore",
3701 	  .tooltip = N_("Subscript"),
3702 	  .callback = G_CALLBACK (cb_font_subscript), .is_active = FALSE }
3703 };
3704 
3705 /****************************************************************************/
3706 
3707 static GOActionComboPixmapsElement const halignment_combo_info[] = {
3708 	{ N_("Align left"),		"format-justify-left",		GNM_HALIGN_LEFT },
3709 	{ N_("Center horizontally"),	"format-justify-center",	GNM_HALIGN_CENTER },
3710 	{ N_("Align right"),		"format-justify-right",		GNM_HALIGN_RIGHT },
3711 	{ N_("Fill horizontally"),	"gnumeric-format-halign-fill",	GNM_HALIGN_FILL },
3712 	{ N_("Justify horizontally"),	"format-justify-fill",		GNM_HALIGN_JUSTIFY },
3713 	{ N_("Distributed"),		"gnumeric-format-halign-distributed",	GNM_HALIGN_DISTRIBUTED },
3714 	{ N_("Center horizontally across the selection"),
3715 					"gnumeric-center-across-selection", GNM_HALIGN_CENTER_ACROSS_SELECTION },
3716 	{ N_("Align numbers right, and text left"),
3717 					"gnumeric-format-halign-general",	GNM_HALIGN_GENERAL },
3718 	{ NULL, NULL }
3719 };
3720 static GOActionComboPixmapsElement const valignment_combo_info[] = {
3721 	{ N_("Align top"),		"gnumeric-format-valign-top",			GNM_VALIGN_TOP },
3722 	{ N_("Center vertically"),	"gnumeric-format-valign-center",	GNM_VALIGN_CENTER },
3723 	{ N_("Align bottom"),		"gnumeric-format-valign-bottom",		GNM_VALIGN_BOTTOM },
3724 	{ N_("Justify"),		"gnumeric-format-valign-justify",		GNM_VALIGN_JUSTIFY },
3725 	{ N_("Align distributed"),	"gnumeric-format-valign-distributed",		GNM_VALIGN_DISTRIBUTED },
3726 	{ NULL, NULL}
3727 };
3728 
3729 static void
cb_halignment_activated(GOActionComboPixmaps * a,WBCGtk * wbcg)3730 cb_halignment_activated (GOActionComboPixmaps *a, WBCGtk *wbcg)
3731 {
3732 	wbcg_set_selection_halign (wbcg,
3733 		go_action_combo_pixmaps_get_selected (a, NULL));
3734 }
3735 static void
cb_valignment_activated(GOActionComboPixmaps * a,WBCGtk * wbcg)3736 cb_valignment_activated (GOActionComboPixmaps *a, WBCGtk *wbcg)
3737 {
3738 	wbcg_set_selection_valign (wbcg,
3739 		go_action_combo_pixmaps_get_selected (a, NULL));
3740 }
3741 
3742 static void
wbc_gtk_init_alignments(WBCGtk * wbcg)3743 wbc_gtk_init_alignments (WBCGtk *wbcg)
3744 {
3745 	wbcg->halignment = go_action_combo_pixmaps_new ("HAlignmentSelector",
3746 						       halignment_combo_info, 3, 1);
3747 	g_object_set (G_OBJECT (wbcg->halignment),
3748 		      "label", _("Horizontal Alignment"),
3749 		      "tooltip", _("Horizontal Alignment"),
3750 		      NULL);
3751 	g_signal_connect (G_OBJECT (wbcg->halignment),
3752 		"activate",
3753 		G_CALLBACK (cb_halignment_activated), wbcg);
3754 	gnm_action_group_add_action (wbcg->actions, GTK_ACTION (wbcg->halignment));
3755 
3756 	wbcg->valignment = go_action_combo_pixmaps_new ("VAlignmentSelector",
3757 						       valignment_combo_info, 1, 3);
3758 	g_object_set (G_OBJECT (wbcg->valignment),
3759 		      "label", _("Vertical Alignment"),
3760 		      "tooltip", _("Vertical Alignment"),
3761 		      NULL);
3762 	g_signal_connect (G_OBJECT (wbcg->valignment),
3763 		"activate",
3764 		G_CALLBACK (cb_valignment_activated), wbcg);
3765 	gnm_action_group_add_action (wbcg->actions, GTK_ACTION (wbcg->valignment));
3766 }
3767 
3768 /****************************************************************************/
3769 
3770 static void
cb_custom_color_created(GOActionComboColor * caction,GtkWidget * dialog,WBCGtk * wbcg)3771 cb_custom_color_created (GOActionComboColor *caction, GtkWidget *dialog, WBCGtk *wbcg)
3772 {
3773 	wbc_gtk_attach_guru (wbcg, dialog);
3774 	wbcg_set_transient (wbcg, GTK_WINDOW (dialog));
3775 }
3776 
3777 static void
cb_fore_color_changed(GOActionComboColor * a,WBCGtk * wbcg)3778 cb_fore_color_changed (GOActionComboColor *a, WBCGtk *wbcg)
3779 {
3780 	WorkbookControl *wbc = GNM_WBC (wbcg);
3781 	GnmStyle *mstyle;
3782 	GOColor   c;
3783 	gboolean  is_default;
3784 
3785 	if (wbcg->updating_ui)
3786 		return;
3787 	c = go_action_combo_color_get_color (a, &is_default);
3788 
3789 	if (wbcg_is_editing (wbcg)) {
3790 		wbcg_edit_add_markup (wbcg, go_color_to_pango (c, TRUE));
3791 		return;
3792 	}
3793 
3794 	mstyle = gnm_style_new ();
3795 	gnm_style_set_font_color (mstyle, is_default
3796 		? style_color_auto_font ()
3797 		: gnm_color_new_go (c));
3798 	cmd_selection_format (wbc, mstyle, NULL, _("Set Foreground Color"));
3799 }
3800 
3801 static void
wbc_gtk_init_color_fore(WBCGtk * gtk)3802 wbc_gtk_init_color_fore (WBCGtk *gtk)
3803 {
3804 	GnmColor *sc_auto_font = style_color_auto_font ();
3805 	GOColor default_color = sc_auto_font->go_color;
3806 	style_color_unref (sc_auto_font);
3807 
3808 	gtk->fore_color = go_action_combo_color_new ("ColorFore", "gnumeric-font",
3809 		_("Automatic"),	default_color, NULL); /* set group to view */
3810 	go_action_combo_color_set_allow_alpha (gtk->fore_color, TRUE);
3811 	g_object_set (G_OBJECT (gtk->fore_color),
3812 		      "label", _("Foreground"),
3813 		      "tooltip", _("Foreground"),
3814 		      NULL);
3815 	g_signal_connect (G_OBJECT (gtk->fore_color),
3816 		"combo-activate",
3817 		G_CALLBACK (cb_fore_color_changed), gtk);
3818 	g_signal_connect (G_OBJECT (gtk->fore_color),
3819 		"display-custom-dialog",
3820 		G_CALLBACK (cb_custom_color_created), gtk);
3821 	gnm_action_group_add_action (gtk->font_actions,
3822 		GTK_ACTION (gtk->fore_color));
3823 }
3824 
3825 static void
cb_back_color_changed(GOActionComboColor * a,WBCGtk * wbcg)3826 cb_back_color_changed (GOActionComboColor *a, WBCGtk *wbcg)
3827 {
3828 	WorkbookControl *wbc = GNM_WBC (wbcg);
3829 	GnmStyle *mstyle;
3830 	GOColor   c;
3831 	gboolean  is_default;
3832 
3833 	if (wbcg->updating_ui)
3834 		return;
3835 
3836 	c = go_action_combo_color_get_color (a, &is_default);
3837 
3838 	mstyle = gnm_style_new ();
3839 	if (!is_default) {
3840 		/* We need to have a pattern of at least solid to draw a background colour */
3841 		if (!gnm_style_is_element_set  (mstyle, MSTYLE_PATTERN) ||
3842 		    gnm_style_get_pattern (mstyle) < 1)
3843 			gnm_style_set_pattern (mstyle, 1);
3844 
3845 		gnm_style_set_back_color (mstyle, gnm_color_new_go (c));
3846 	} else
3847 		gnm_style_set_pattern (mstyle, 0);	/* Set background to NONE */
3848 	cmd_selection_format (wbc, mstyle, NULL, _("Set Background Color"));
3849 }
3850 
3851 static void
wbc_gtk_init_color_back(WBCGtk * gtk)3852 wbc_gtk_init_color_back (WBCGtk *gtk)
3853 {
3854 	gtk->back_color = go_action_combo_color_new ("ColorBack", "gnumeric-bucket",
3855 		_("Clear Background"), 0, NULL);
3856 	g_object_set (G_OBJECT (gtk->back_color),
3857 		      "label", _("Background"),
3858 		      "tooltip", _("Background"),
3859 		      NULL);
3860 	g_object_connect (G_OBJECT (gtk->back_color),
3861 		"signal::combo-activate", G_CALLBACK (cb_back_color_changed), gtk,
3862 		"signal::display-custom-dialog", G_CALLBACK (cb_custom_color_created), gtk,
3863 		NULL);
3864 	gnm_action_group_add_action (gtk->actions, GTK_ACTION (gtk->back_color));
3865 }
3866 
3867 /****************************************************************************/
3868 
3869 static GOActionComboPixmapsElement const border_combo_info[] = {
3870 	{ N_("Left"),			"gnumeric-format-border-left",			11 },
3871 	{ N_("Clear Borders"),		"gnumeric-format-border-none",			12 },
3872 	{ N_("Right"),			"gnumeric-format-border-right",			13 },
3873 
3874 	{ N_("All Borders"),		"gnumeric-format-border-all",			21 },
3875 	{ N_("Outside Borders"),	"gnumeric-format-border-outside",		22 },
3876 	{ N_("Thick Outside Borders"),	"gnumeric-format-border-thick-outside",		23 },
3877 
3878 	{ N_("Bottom"),			"gnumeric-format-border-bottom",		31 },
3879 	{ N_("Double Bottom"),		"gnumeric-format-border-double-bottom",		32 },
3880 	{ N_("Thick Bottom"),		"gnumeric-format-border-thick-bottom",		33 },
3881 
3882 	{ N_("Top and Bottom"),		"gnumeric-format-border-top-n-bottom",		41 },
3883 	{ N_("Top and Double Bottom"),	"gnumeric-format-border-top-n-double-bottom",	42 },
3884 	{ N_("Top and Thick Bottom"),	"gnumeric-format-border-top-n-thick-bottom",	43 },
3885 
3886 	{ NULL, NULL}
3887 };
3888 
3889 static void
cb_border_activated(GOActionComboPixmaps * a,WorkbookControl * wbc)3890 cb_border_activated (GOActionComboPixmaps *a, WorkbookControl *wbc)
3891 {
3892 	Sheet *sheet = wb_control_cur_sheet (wbc);
3893 	GnmBorder *borders[GNM_STYLE_BORDER_EDGE_MAX];
3894 	int i;
3895 	int index = go_action_combo_pixmaps_get_selected (a, NULL);
3896 
3897 	/* Init the list */
3898 	for (i = GNM_STYLE_BORDER_TOP; i < GNM_STYLE_BORDER_EDGE_MAX; i++)
3899 		borders[i] = NULL;
3900 
3901 	switch (index) {
3902 	case 11 : /* left */
3903 		borders[GNM_STYLE_BORDER_LEFT] = gnm_style_border_fetch (GNM_STYLE_BORDER_THIN,
3904 			 sheet_style_get_auto_pattern_color (sheet),
3905 			 gnm_style_border_get_orientation (GNM_STYLE_BORDER_LEFT));
3906 		break;
3907 
3908 	case 12 : /* none */
3909 		for (i = GNM_STYLE_BORDER_TOP; i < GNM_STYLE_BORDER_EDGE_MAX; i++)
3910 			borders[i] = gnm_style_border_ref (gnm_style_border_none ());
3911 		break;
3912 
3913 	case 13 : /* right */
3914 		borders[GNM_STYLE_BORDER_RIGHT] = gnm_style_border_fetch (GNM_STYLE_BORDER_THIN,
3915 			 sheet_style_get_auto_pattern_color (sheet),
3916 			 gnm_style_border_get_orientation (GNM_STYLE_BORDER_RIGHT));
3917 		break;
3918 
3919 	case 21 : /* all */
3920 		for (i = GNM_STYLE_BORDER_HORIZ; i <= GNM_STYLE_BORDER_VERT; ++i)
3921 			borders[i] = gnm_style_border_fetch (GNM_STYLE_BORDER_THIN,
3922 				sheet_style_get_auto_pattern_color (sheet),
3923 				gnm_style_border_get_orientation (i));
3924 		/* fall through */
3925 
3926 	case 22 : /* outside */
3927 		for (i = GNM_STYLE_BORDER_TOP; i <= GNM_STYLE_BORDER_RIGHT; ++i)
3928 			borders[i] = gnm_style_border_fetch (GNM_STYLE_BORDER_THIN,
3929 				sheet_style_get_auto_pattern_color (sheet),
3930 				gnm_style_border_get_orientation (i));
3931 		break;
3932 
3933 	case 23 : /* thick_outside */
3934 		for (i = GNM_STYLE_BORDER_TOP; i <= GNM_STYLE_BORDER_RIGHT; ++i)
3935 			borders[i] = gnm_style_border_fetch (GNM_STYLE_BORDER_THICK,
3936 				sheet_style_get_auto_pattern_color (sheet),
3937 				gnm_style_border_get_orientation (i));
3938 		break;
3939 
3940 	case 41 : /* top_n_bottom */
3941 	case 42 : /* top_n_double_bottom */
3942 	case 43 : /* top_n_thick_bottom */
3943 		borders[GNM_STYLE_BORDER_TOP] = gnm_style_border_fetch (GNM_STYLE_BORDER_THIN,
3944 			sheet_style_get_auto_pattern_color (sheet),
3945 			gnm_style_border_get_orientation (GNM_STYLE_BORDER_TOP));
3946 	    /* Fall through */
3947 
3948 	case 31 : /* bottom */
3949 	case 32 : /* double_bottom */
3950 	case 33 : /* thick_bottom */
3951 	{
3952 		int const tmp = index % 10;
3953 		GnmStyleBorderType const t =
3954 		    (tmp == 1) ? GNM_STYLE_BORDER_THIN :
3955 		    (tmp == 2) ? GNM_STYLE_BORDER_DOUBLE
3956 		    : GNM_STYLE_BORDER_THICK;
3957 
3958 		borders[GNM_STYLE_BORDER_BOTTOM] = gnm_style_border_fetch (t,
3959 			sheet_style_get_auto_pattern_color (sheet),
3960 			gnm_style_border_get_orientation (GNM_STYLE_BORDER_BOTTOM));
3961 		break;
3962 	}
3963 
3964 	default:
3965 		g_warning ("Unknown border preset selected (%d)", index);
3966 		return;
3967 	}
3968 
3969 	cmd_selection_format (wbc, NULL, borders, _("Set Borders"));
3970 }
3971 
3972 static void
wbc_gtk_init_borders(WBCGtk * wbcg)3973 wbc_gtk_init_borders (WBCGtk *wbcg)
3974 {
3975 	wbcg->borders = go_action_combo_pixmaps_new ("BorderSelector", border_combo_info, 3, 4);
3976 	g_object_set (G_OBJECT (wbcg->borders),
3977 		      "label", _("Borders"),
3978 		      "tooltip", _("Borders"),
3979 		      NULL);
3980 #if 0
3981 	go_combo_pixmaps_select (wbcg->borders, 1); /* default to none */
3982 #endif
3983 	g_signal_connect (G_OBJECT (wbcg->borders),
3984 		"combo-activate",
3985 		G_CALLBACK (cb_border_activated), wbcg);
3986 	gnm_action_group_add_action (wbcg->actions, GTK_ACTION (wbcg->borders));
3987 }
3988 
3989 /****************************************************************************/
3990 
3991 static void
cb_chain_sensitivity(GtkAction * src,G_GNUC_UNUSED GParamSpec * pspec,GtkAction * action)3992 cb_chain_sensitivity (GtkAction *src, G_GNUC_UNUSED GParamSpec *pspec,
3993 		      GtkAction *action)
3994 {
3995 	gboolean old_val = gtk_action_get_sensitive (action);
3996 	gboolean new_val = gtk_action_get_sensitive (src);
3997 	if ((new_val != 0) == (old_val != 0))
3998 		return;
3999 	if (new_val)
4000 		gtk_action_connect_accelerator (action);
4001 	else
4002 		gtk_action_disconnect_accelerator (action);
4003 	g_object_set (action, "sensitive", new_val, NULL);
4004 }
4005 
4006 
4007 static void
create_undo_redo(GOActionComboStack ** haction,char const * hname,GCallback hcb,GtkAction ** vaction,char const * vname,GCallback vcb,WBCGtk * gtk,char const * tooltip,char const * icon_name,char const * accel,const char * alt_accel)4008 create_undo_redo (GOActionComboStack **haction, char const *hname,
4009 		  GCallback hcb,
4010 		  GtkAction **vaction, char const *vname,
4011 		  GCallback vcb,
4012 		  WBCGtk *gtk,
4013 		  char const *tooltip,
4014 		  char const *icon_name,
4015 		  char const *accel, const char *alt_accel)
4016 {
4017 	*haction = g_object_new
4018 		(go_action_combo_stack_get_type (),
4019 		 "name", hname,
4020 		 "tooltip", tooltip,
4021 		 "icon-name", icon_name,
4022 		 "sensitive", FALSE,
4023 		 "visible-vertical", FALSE,
4024 		 NULL);
4025 	gtk_action_group_add_action_with_accel
4026 		(gtk->semi_permanent_actions,
4027 		 GTK_ACTION (*haction),
4028 		 accel);
4029 	g_signal_connect (G_OBJECT (*haction), "activate", hcb, gtk);
4030 
4031 	*vaction = g_object_new
4032 		(GTK_TYPE_ACTION,
4033 		 "name", vname,
4034 		 "tooltip", tooltip,
4035 		 "icon-name", icon_name,
4036 		 "sensitive", FALSE,
4037 		 "visible-horizontal", FALSE,
4038 		 NULL);
4039 	gtk_action_group_add_action_with_accel
4040 		(gtk->semi_permanent_actions,
4041 		 GTK_ACTION (*vaction),
4042 		 alt_accel);
4043 	g_signal_connect_swapped (G_OBJECT (*vaction), "activate", vcb, gtk);
4044 
4045 	g_signal_connect (G_OBJECT (*haction), "notify::sensitive",
4046 		G_CALLBACK (cb_chain_sensitivity), *vaction);
4047 }
4048 
4049 
4050 static void
cb_undo_activated(GOActionComboStack * a,WorkbookControl * wbc)4051 cb_undo_activated (GOActionComboStack *a, WorkbookControl *wbc)
4052 {
4053 	unsigned n = workbook_find_command (wb_control_get_workbook (wbc), TRUE,
4054 		go_action_combo_stack_selection (a));
4055 	while (n-- > 0)
4056 		command_undo (wbc);
4057 }
4058 
4059 static void
cb_redo_activated(GOActionComboStack * a,WorkbookControl * wbc)4060 cb_redo_activated (GOActionComboStack *a, WorkbookControl *wbc)
4061 {
4062 	unsigned n = workbook_find_command (wb_control_get_workbook (wbc), FALSE,
4063 		go_action_combo_stack_selection (a));
4064 	while (n-- > 0)
4065 		command_redo (wbc);
4066 }
4067 
4068 static void
wbc_gtk_init_undo_redo(WBCGtk * gtk)4069 wbc_gtk_init_undo_redo (WBCGtk *gtk)
4070 {
4071 	create_undo_redo (
4072 		&gtk->redo_haction, "Redo", G_CALLBACK (cb_redo_activated),
4073 		&gtk->redo_vaction, "VRedo", G_CALLBACK (command_redo),
4074 		gtk, _("Redo the undone action"),
4075 		"edit-redo", "<control>y", "<control><shift>z");
4076 	create_undo_redo (
4077 		&gtk->undo_haction, "Undo", G_CALLBACK (cb_undo_activated),
4078 		&gtk->undo_vaction, "VUndo", G_CALLBACK (command_undo),
4079 		gtk, _("Undo the last action"),
4080 		"edit-undo", "<control>z", NULL);
4081 }
4082 
4083 /****************************************************************************/
4084 
GNM_ACTION_DEF(cb_zoom_activated)4085 static GNM_ACTION_DEF (cb_zoom_activated)
4086 {
4087 	WorkbookControl *wbc = (WorkbookControl *)wbcg;
4088 	Sheet *sheet = wb_control_cur_sheet (wbc);
4089 	char const *new_zoom;
4090 	int factor;
4091 	char *end;
4092 
4093 	if (sheet == NULL || wbcg->updating_ui || wbcg->snotebook == NULL)
4094 		return;
4095 
4096 	new_zoom = go_action_combo_text_get_entry (wbcg->zoom_haction);
4097 
4098 	errno = 0; /* strtol sets errno, but does not clear it.  */
4099 	factor = strtol (new_zoom, &end, 10);
4100 	if (new_zoom != end && errno != ERANGE && factor == (gnm_float)factor)
4101 		/* The GSList of sheet passed to cmd_zoom will be freed by cmd_zoom,
4102 		 * and the sheet will force an update of the zoom combo to keep the
4103 		 * display consistent
4104 		 */
4105 		cmd_zoom (wbc, g_slist_append (NULL, sheet), factor / 100.);
4106 }
4107 
GNM_ACTION_DEF(cb_vzoom_activated)4108 static GNM_ACTION_DEF (cb_vzoom_activated)
4109 {
4110 	dialog_zoom (wbcg, wbcg_cur_sheet (wbcg));
4111 }
4112 
4113 static void
wbc_gtk_init_zoom(WBCGtk * wbcg)4114 wbc_gtk_init_zoom (WBCGtk *wbcg)
4115 {
4116 #warning TODO : Add zoom to selection
4117 	static char const * const preset_zoom [] = {
4118 		"200%",
4119 		"150%",
4120 		"100%",
4121 		"75%",
4122 		"50%",
4123 		"25%",
4124 		NULL
4125 	};
4126 	int i;
4127 
4128 	/* ----- horizontal ----- */
4129 
4130 	wbcg->zoom_haction =
4131 		g_object_new (go_action_combo_text_get_type (),
4132 			      "name", "Zoom",
4133 			      "label", _("_Zoom"),
4134 			      "visible-vertical", FALSE,
4135 			      "tooltip", _("Zoom"),
4136 			      "stock-id", "zoom-in",
4137 			      NULL);
4138 	go_action_combo_text_set_width (wbcg->zoom_haction, "10000%");
4139 	for (i = 0; preset_zoom[i] != NULL ; ++i)
4140 		go_action_combo_text_add_item (wbcg->zoom_haction,
4141 					       preset_zoom[i]);
4142 
4143 	g_signal_connect (G_OBJECT (wbcg->zoom_haction),
4144 		"activate",
4145 		G_CALLBACK (cb_zoom_activated), wbcg);
4146 	gnm_action_group_add_action (wbcg->actions,
4147 				     GTK_ACTION (wbcg->zoom_haction));
4148 
4149 	/* ----- vertical ----- */
4150 
4151 	wbcg->zoom_vaction =
4152 		g_object_new (GTK_TYPE_ACTION,
4153 			      "name", "VZoom",
4154 			      "tooltip", _("Zoom"),
4155 			      "icon-name", "zoom-in",
4156 			      "visible-horizontal", FALSE,
4157 			      NULL);
4158 	g_signal_connect (G_OBJECT (wbcg->zoom_vaction),
4159 			  "activate",
4160 			  G_CALLBACK (cb_vzoom_activated), wbcg);
4161 	gnm_action_group_add_action (wbcg->actions,
4162 				     GTK_ACTION (wbcg->zoom_vaction));
4163 
4164 	/* ----- chain ----- */
4165 
4166 	g_signal_connect (G_OBJECT (wbcg->zoom_haction), "notify::sensitive",
4167 		G_CALLBACK (cb_chain_sensitivity), wbcg->zoom_vaction);
4168 }
4169 
4170 /****************************************************************************/
4171 
4172 typedef struct { GtkAction base; } GnmFontAction;
4173 typedef struct { GtkActionClass base; } GnmFontActionClass;
4174 
4175 static PangoFontDescription *
gnm_font_action_get_font_desc(GtkAction * act)4176 gnm_font_action_get_font_desc (GtkAction *act)
4177 {
4178 	PangoFontDescription *desc =
4179 		g_object_get_data (G_OBJECT (act), "font-data");
4180 	return desc;
4181 }
4182 
4183 void
wbcg_font_action_set_font_desc(GtkAction * act,PangoFontDescription * desc)4184 wbcg_font_action_set_font_desc (GtkAction *act, PangoFontDescription *desc)
4185 {
4186 	PangoFontDescription *old_desc;
4187 	GSList *p;
4188 
4189 	old_desc = g_object_get_data (G_OBJECT (act), "font-data");
4190 	if (!old_desc) {
4191 		old_desc = pango_font_description_new ();
4192 		g_object_set_data_full (G_OBJECT (act),
4193 					"font-data", old_desc,
4194 					(GDestroyNotify)pango_font_description_free);
4195 	}
4196 	pango_font_description_merge (old_desc, desc, TRUE);
4197 
4198 	for (p = gtk_action_get_proxies (act); p; p = p->next) {
4199 		GtkWidget *w = p->data;
4200 		GtkWidget *child;
4201 		GtkFontChooser *chooser;
4202 
4203 		if (!GTK_IS_BIN (w))
4204 			continue;
4205 
4206 		child = gtk_bin_get_child (GTK_BIN (w));
4207 		if (!GTK_IS_FONT_CHOOSER (child))
4208 			continue;
4209 
4210 		chooser = GTK_FONT_CHOOSER (child);
4211 		gtk_font_chooser_set_font_desc (chooser, old_desc);
4212 	}
4213 }
4214 
4215 static void
cb_font_set(GtkFontChooser * chooser,GtkAction * act)4216 cb_font_set (GtkFontChooser *chooser, GtkAction *act)
4217 {
4218 	PangoFontDescription *desc = gtk_font_chooser_get_font_desc (chooser);
4219 	wbcg_font_action_set_font_desc (act, desc);
4220 	pango_font_description_free (desc);
4221 	gtk_action_activate (act);
4222 }
4223 
4224 static void
cb_font_button_screen_changed(GtkWidget * widget)4225 cb_font_button_screen_changed (GtkWidget *widget)
4226 {
4227 /* Doesn't look right */
4228 #if 0
4229 	GdkScreen *screen = gtk_widget_get_screen (widget);
4230 
4231 	if (screen) {
4232 		int w = gnm_widget_measure_string (widget,
4233 						   "XXMonospace | 99XX");
4234 		gtk_widget_set_size_request (widget, w, -1);
4235 	}
4236 #endif
4237 }
4238 
4239 /* Filter to ignore non-scalable fonts. */
4240 static gboolean
cb_font_filter(G_GNUC_UNUSED const PangoFontFamily * family,const PangoFontFace * face_,gpointer user)4241 cb_font_filter (G_GNUC_UNUSED const PangoFontFamily *family,
4242 		const PangoFontFace *face_,
4243 		gpointer user)
4244 {
4245 	PangoFontFace *face = (PangoFontFace*)face_;
4246 	int n_sizes;
4247 	int *sizes = NULL;
4248 	static int debug = -1;
4249 
4250 	pango_font_face_list_sizes (face, &sizes, &n_sizes);
4251 	g_free (sizes);
4252 
4253 	if (debug == -1)
4254 		debug = gnm_debug_flag ("fonts");
4255 
4256 	if (n_sizes > 0 && debug) {
4257 		PangoFontDescription *desc = pango_font_face_describe (face);
4258 		char *s = pango_font_description_to_string (desc);
4259 		g_printerr ("Ignoring bitmap face %s\n", s);
4260 		g_free (s);
4261 		pango_font_description_free (desc);
4262 	}
4263 
4264 	return n_sizes == 0;
4265 }
4266 
4267 static GtkWidget *
gnm_font_action_create_tool_item(GtkAction * action)4268 gnm_font_action_create_tool_item (GtkAction *action)
4269 {
4270 	GtkWidget *item = g_object_new
4271 		(GTK_TYPE_TOOL_ITEM,
4272 		 NULL);
4273 	GtkWidget *but = g_object_new
4274 		(gnm_font_button_get_type(),
4275 		 "dialog-type", GO_TYPE_FONT_SEL_DIALOG,
4276 		 "show-preview-entry", TRUE,
4277 		 "show-style", FALSE,
4278 		 "relief", gtk_tool_item_get_relief_style (GTK_TOOL_ITEM (item)),
4279 		 "focus-on-click", FALSE,
4280 		 NULL);
4281 	if (0) gtk_font_chooser_set_filter_func (GTK_FONT_CHOOSER (but),
4282 					  cb_font_filter,
4283 					  NULL,
4284 					  NULL);
4285 	gtk_widget_show_all (but);
4286 	gtk_container_add (GTK_CONTAINER (item), but);
4287 	g_signal_connect (but,
4288 			  "font-set", G_CALLBACK (cb_font_set),
4289 			  action);
4290 	g_signal_connect (but,
4291 			  "screen-changed",
4292 			  G_CALLBACK (cb_font_button_screen_changed),
4293 			  action);
4294 	return item;
4295 }
4296 
4297 static void
gnm_font_action_class_init(GObjectClass * gobject_class)4298 gnm_font_action_class_init (GObjectClass *gobject_class)
4299 {
4300 	GtkActionClass *act = GTK_ACTION_CLASS (gobject_class);
4301 
4302 	act->toolbar_item_type = GTK_TYPE_MENU_TOOL_BUTTON;
4303 	act->create_tool_item = gnm_font_action_create_tool_item;
4304 }
4305 
4306 static
GSF_CLASS(GnmFontAction,gnm_font_action,gnm_font_action_class_init,NULL,GTK_TYPE_ACTION)4307 GSF_CLASS (GnmFontAction, gnm_font_action,
4308 	   gnm_font_action_class_init, NULL, GTK_TYPE_ACTION)
4309 #if 0
4310 	;
4311 #endif
4312 #define GNM_FONT_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), gnm_font_action_get_type(), GnmFontAction))
4313 
4314 static void
4315 cb_font_changed (GtkAction *act, WBCGtk *gtk)
4316 {
4317 	PangoFontDescription *desc = gnm_font_action_get_font_desc (act);
4318 	const char *family = pango_font_description_get_family (desc);
4319 	int size = pango_font_description_get_size (desc);
4320 
4321 	/*
4322 	 * Ignore events during destruction.  This is an attempt at avoiding
4323 	 * https://bugzilla.redhat.com/show_bug.cgi?id=803904 for which we
4324 	 * blame gtk.
4325 	 */
4326 	if (gtk->snotebook == NULL)
4327 		return;
4328 
4329 	if (wbcg_is_editing (WBC_GTK (gtk))) {
4330 		wbcg_edit_add_markup (WBC_GTK (gtk),
4331 				      pango_attr_family_new (family));
4332 		wbcg_edit_add_markup (WBC_GTK (gtk),
4333 				      pango_attr_size_new (size));
4334 	} else {
4335 		GnmStyle *style = gnm_style_new ();
4336 		char *font_name = pango_font_description_to_string (desc);
4337 		char *title = g_strdup_printf (_("Setting Font %s"), font_name);
4338 		g_free (font_name);
4339 
4340 		gnm_style_set_font_name (style, family);
4341 		gnm_style_set_font_size (style, size / (double)PANGO_SCALE);
4342 
4343 		cmd_selection_format (GNM_WBC (gtk), style, NULL, title);
4344 		g_free (title);
4345 	}
4346 }
4347 
4348 static void
cb_font_name_vaction_response(GtkDialog * dialog,gint response_id,GtkAction * act)4349 cb_font_name_vaction_response (GtkDialog *dialog,
4350 			       gint       response_id,
4351 			       GtkAction *act)
4352 {
4353 	WBCGtk *wbcg = g_object_get_data (G_OBJECT (act), "wbcg");
4354 
4355 	if (response_id == GTK_RESPONSE_OK) {
4356 		PangoFontDescription *desc = gtk_font_chooser_get_font_desc
4357 			(GTK_FONT_CHOOSER (dialog));
4358 		wbcg_font_action_set_font_desc (act, desc);
4359 		pango_font_description_free (desc);
4360 		cb_font_changed (act, wbcg);
4361 	}
4362 
4363 	gtk_widget_destroy (GTK_WIDGET (dialog));
4364 }
4365 
4366 
4367 static void
cb_font_name_vaction_clicked(GtkAction * act,WBCGtk * wbcg)4368 cb_font_name_vaction_clicked (GtkAction *act, WBCGtk *wbcg)
4369 {
4370 	GtkFontChooser *font_dialog;
4371 	const char *key = "font-name-dialog";
4372 
4373 	if (gnm_dialog_raise_if_exists (wbcg, key))
4374 		return;
4375 
4376 	font_dialog = g_object_new (GO_TYPE_FONT_SEL_DIALOG, NULL);
4377 	gtk_font_chooser_set_font_desc (font_dialog,
4378 					gnm_font_action_get_font_desc (act));
4379 	g_signal_connect (font_dialog, "response",
4380 			  G_CALLBACK (cb_font_name_vaction_response),
4381 			  act);
4382 
4383 	gtk_window_present (GTK_WINDOW (font_dialog));
4384 
4385 	gnm_keyed_dialog (wbcg, GTK_WINDOW (font_dialog), key);
4386 }
4387 
4388 static GtkAction *
wbc_gtk_init_font_name(WBCGtk * gtk,gboolean horiz)4389 wbc_gtk_init_font_name (WBCGtk *gtk, gboolean horiz)
4390 {
4391 	GtkAction *act = g_object_new
4392 		(horiz ? gnm_font_action_get_type () : GTK_TYPE_ACTION,
4393 		 "visible-vertical", !horiz,
4394 		 "visible-horizontal", horiz,
4395 		 "name", (horiz ? "FontName" : "VFontName"),
4396 		 "tooltip", _("Change font"),
4397 		 "icon-name", "gnumeric-font",
4398 		 NULL);
4399 
4400 	g_object_set_data (G_OBJECT (act), "wbcg", gtk);
4401 
4402 	g_signal_connect (G_OBJECT (act),
4403 			  "activate",
4404 			  (horiz
4405 			   ? G_CALLBACK (cb_font_changed)
4406 			   : G_CALLBACK (cb_font_name_vaction_clicked)),
4407 			  gtk);
4408 
4409 	gnm_action_group_add_action (gtk->font_actions, act);
4410 
4411 	return act;
4412 }
4413 
4414 /****************************************************************************/
4415 
4416 static void
list_actions(GtkActionGroup * group)4417 list_actions (GtkActionGroup *group)
4418 {
4419 	GList *actions, *l;
4420 
4421 	if (!group)
4422 		return;
4423 
4424 	actions = gtk_action_group_list_actions (group);
4425 	for (l = actions; l; l = l->next) {
4426 		GtkAction *act = l->data;
4427 		const char *name = gtk_action_get_name (act);
4428 		g_printerr ("Action %s\n", name);
4429 	}
4430 
4431 	g_list_free (actions);
4432 }
4433 
4434 void
wbc_gtk_init_actions(WBCGtk * wbcg)4435 wbc_gtk_init_actions (WBCGtk *wbcg)
4436 {
4437 	static struct {
4438 		char const *name;
4439 		gboolean    is_font;
4440 		unsigned    offset;
4441 	} const toggles[] = {
4442 		{ "FontBold",		   TRUE, G_STRUCT_OFFSET (WBCGtk, font.bold) },
4443 		{ "FontItalic",		   TRUE, G_STRUCT_OFFSET (WBCGtk, font.italic) },
4444 		{ "FontUnderline",	   TRUE, G_STRUCT_OFFSET (WBCGtk, font.underline) },
4445 		{ "FontDoubleUnderline",   TRUE, G_STRUCT_OFFSET (WBCGtk, font.d_underline) },
4446 		{ "FontSingleLowUnderline",TRUE, G_STRUCT_OFFSET (WBCGtk, font.sl_underline) },
4447 		{ "FontDoubleLowUnderline",TRUE, G_STRUCT_OFFSET (WBCGtk, font.dl_underline) },
4448 		{ "FontSuperscript",	   TRUE, G_STRUCT_OFFSET (WBCGtk, font.superscript) },
4449 		{ "FontSubscript",	   TRUE, G_STRUCT_OFFSET (WBCGtk, font.subscript) },
4450 		{ "FontStrikeThrough",	   TRUE, G_STRUCT_OFFSET (WBCGtk, font.strikethrough) },
4451 
4452 		{ "AlignLeft",		   FALSE, G_STRUCT_OFFSET (WBCGtk, h_align.left) },
4453 		{ "AlignCenter",	   FALSE, G_STRUCT_OFFSET (WBCGtk, h_align.center) },
4454 		{ "AlignRight",		   FALSE, G_STRUCT_OFFSET (WBCGtk, h_align.right) },
4455 		{ "CenterAcrossSelection", FALSE, G_STRUCT_OFFSET (WBCGtk, h_align.center_across_selection) },
4456 		{ "AlignTop",		   FALSE, G_STRUCT_OFFSET (WBCGtk, v_align.top) },
4457 		{ "AlignVCenter",	   FALSE, G_STRUCT_OFFSET (WBCGtk, v_align.center) },
4458 		{ "AlignBottom",	   FALSE, G_STRUCT_OFFSET (WBCGtk, v_align.bottom) }
4459 	};
4460 	unsigned i;
4461 
4462 	wbcg->permanent_actions = gtk_action_group_new ("PermanentActions");
4463 	wbcg->actions = gtk_action_group_new ("Actions");
4464 	wbcg->font_actions = gtk_action_group_new ("FontActions");
4465 	wbcg->data_only_actions = gtk_action_group_new ("DataOnlyActions");
4466 	wbcg->semi_permanent_actions = gtk_action_group_new ("SemiPermanentActions");
4467 
4468 	gnm_action_group_add_actions (wbcg->permanent_actions,
4469 		permanent_actions, G_N_ELEMENTS (permanent_actions), wbcg);
4470 	gnm_action_group_add_actions (wbcg->actions,
4471 		actions, G_N_ELEMENTS (actions), wbcg);
4472 	gnm_action_group_add_actions (wbcg->font_actions,
4473 		font_actions, G_N_ELEMENTS (font_actions), wbcg);
4474 	gnm_action_group_add_actions (wbcg->data_only_actions,
4475 		data_only_actions, G_N_ELEMENTS (data_only_actions), wbcg);
4476 	gnm_action_group_add_actions (wbcg->semi_permanent_actions,
4477 		semi_permanent_actions, G_N_ELEMENTS (semi_permanent_actions), wbcg);
4478 
4479 	wbc_gtk_init_alignments (wbcg);
4480 	wbc_gtk_init_color_fore (wbcg);
4481 	wbc_gtk_init_color_back (wbcg);
4482 	wbc_gtk_init_borders (wbcg);
4483 	wbc_gtk_init_undo_redo (wbcg);
4484 	wbc_gtk_init_zoom (wbcg);
4485 	wbcg->font_name_haction = wbc_gtk_init_font_name (wbcg, TRUE);
4486 	wbcg->font_name_vaction = wbc_gtk_init_font_name (wbcg, FALSE);
4487 
4488 	for (i = G_N_ELEMENTS (toggles); i-- > 0 ; ) {
4489 		GtkAction *act = wbcg_find_action (wbcg, toggles[i].name);
4490 		G_STRUCT_MEMBER (GtkToggleAction *, wbcg, toggles[i].offset) =
4491 			(GtkToggleAction*) (act);
4492 	}
4493 
4494 	if (gnm_debug_flag ("actions")) {
4495 		list_actions (wbcg->permanent_actions);
4496 		list_actions (wbcg->actions);
4497 		list_actions (wbcg->font_actions);
4498 		list_actions (wbcg->data_only_actions);
4499 		list_actions (wbcg->semi_permanent_actions);
4500 		list_actions (wbcg->file_history.actions);
4501 		list_actions (wbcg->toolbar.actions);
4502 		list_actions (wbcg->windows.actions);
4503 		list_actions (wbcg->templates.actions);
4504 	}
4505 }
4506