1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * commands.c: Handlers to undo & redo commands
6 * Copyright (C) 1999-2008 Jody Goldberg (jody@gnome.org)
7 * Copyright (C) 2002-2008 Morten Welinder (terra@gnome.org)
9 * Contributors : Almer S. Tigelaar (almer@gnome.org)
10 * Andreas J. Guelzow (aguelzow@taliesin.ca)
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) version 3.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
27 #include <gnumeric-config.h>
28 #include <glib/gi18n-lib.h>
31 #include "gnm-command-impl.h"
33 #include "application.h"
35 #include "sheet-view.h"
36 #include "sheet-style.h"
37 #include "gnm-format.h"
38 #include "format-template.h"
39 #include "command-context.h"
40 #include "workbook-control.h"
41 #include "workbook-view.h"
42 #include "workbook-priv.h" /* For the undo/redo queues and the FOREACH */
45 #include "dependent.h"
49 #include "expr-name.h"
51 #include "sheet-merge.h"
52 #include "parse-util.h"
53 #include "print-info.h"
54 #include "clipboard.h"
55 #include "selection.h"
57 #include "style-border.h"
58 #include "auto-correct.h"
59 #include "sheet-autofill.h"
64 #include "sheet-object-cell-comment.h"
65 #include "sheet-object-widget.h"
66 #include "sheet-object.h"
67 #include "sheet-object-component.h"
68 #include "sheet-object-graph.h"
69 #include "sheet-control.h"
70 #include "sheet-control-gui.h"
71 #include "sheet-utils.h"
72 #include "style-color.h"
73 #include "sheet-filter.h"
74 #include "auto-format.h"
75 #include "tools/dao.h"
76 #include "gnumeric-conf.h"
77 #include "scenarios.h"
78 #include "data-shuffling.h"
79 #include "tools/tabulate.h"
83 #include <goffice/goffice.h>
84 #include <gsf/gsf-doc-meta-data.h>
87 #define UNICODE_ELLIPSIS "\xe2\x80\xa6"
91 * There are several distinct stages to wrapping each command.
93 * 1) Find the appropriate place(s) in the catch all calls to activations
94 * of this logical function. Be careful. This should only be called by
95 * user initiated actions, not internal commands.
97 * 2) Copy the boiler plate code into place and implement the descriptor.
99 * 3) Implement the guts of the support functions.
101 * That way undo redo just become applications of the old or the new styles.
104 * 1) redo : this should be renamed 'exec' and should be the place that the
105 * the actual command executes. This avoid duplicating the code for
106 * application and re-application.
108 * 2) The command objects are responsible for generating recalc and redraw
109 * events. None of the internal utility routines should do so. Those are
110 * expensive events and should only be done once per command to avoid
111 * duplicating work. The lower levels can queue redraws if they must, and
112 * flag state changes but the call to gnm_app_recalc and sheet_update is
115 * FIXME: Filter the list of commands when a sheet is deleted.
117 * TODO : Possibly clear lists on save.
119 * TODO : Reqs for selective undo
122 * - undoable preference setting ? XL does not have this. Do we want it ?
124 /******************************************************************/
126 #define GNM_COMMAND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GNM_COMMAND_TYPE, GnmCommand))
127 #define GNM_COMMAND_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GNM_COMMAND_TYPE, GnmCommandClass))
128 #define GNM_IS_COMMAND(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNM_COMMAND_TYPE))
129 #define CMD_CLASS(o) GNM_COMMAND_CLASS (G_OBJECT_GET_CLASS(cmd))
131 GSF_CLASS (GnmCommand
, gnm_command
, NULL
, NULL
, G_TYPE_OBJECT
)
134 gnm_command_finalize (GObject
*obj
)
136 GnmCommand
*cmd
= GNM_COMMAND (obj
);
137 GObjectClass
*parent
;
139 /* The const was to avoid accidental changes elsewhere */
140 g_free ((gchar
*)cmd
->cmd_descriptor
);
141 cmd
->cmd_descriptor
= NULL
;
143 parent
= g_type_class_peek (g_type_parent(G_TYPE_FROM_INSTANCE (obj
)));
144 (*parent
->finalize
) (obj
);
147 /******************************************************************/
150 gnm_cmd_trunc_descriptor (GString
*src
, gboolean
*truncated
)
152 int max_len
= gnm_conf_get_undo_max_descriptor_width ();
159 while ((pos
= strchr(src
->str
, '\n')) != NULL
||
160 (pos
= strchr(src
->str
, '\r')) != NULL
)
163 len
= g_utf8_strlen (src
->str
, -1);
166 *truncated
= (len
> max_len
);
169 gchar
* last
= g_utf8_offset_to_pointer (src
->str
,
171 g_string_truncate (src
, last
- src
->str
);
172 g_string_append (src
, UNICODE_ELLIPSIS
);
179 * cmd_cell_range_is_locked_effective:
182 * @wbc: #WorkbookControl
183 * @cmd_name: the command name.
185 * checks whether the cells are effectively locked
187 * static gboolean cmd_cell_range_is_locked_effective
190 * Do not use this function unless the sheet is part of the
191 * workbook with the given wbc (otherwise the results may be strange)
194 cmd_cell_range_is_locked_effective (Sheet
*sheet
, GnmRange
*range
,
195 WorkbookControl
*wbc
, char const *cmd_name
)
198 WorkbookView
*wbv
= wb_control_view (wbc
);
200 if (wbv
->is_protected
|| sheet
->is_protected
)
201 for (i
= range
->start
.row
; i
<= range
->end
.row
; i
++)
202 for (j
= range
->start
.col
; j
<= range
->end
.col
; j
++)
203 if (gnm_style_get_contents_locked (sheet_style_get (sheet
, j
, i
))) {
204 char *r
= global_range_name (sheet
, range
);
205 char *text
= g_strdup_printf (wbv
->is_protected
?
206 _("%s is locked. Unprotect the workbook to enable editing.") :
207 _("%s is locked. Unprotect the sheet to enable editing."),
209 go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbc
),
219 * checks whether the cells are effectively locked
221 * static gboolean cmd_dao_is_locked_effective
224 * Do not use this function unless the sheet is part of the
225 * workbook with the given wbcg (otherwise the results may be strange)
230 cmd_dao_is_locked_effective (data_analysis_output_t
*dao
,
231 WorkbookControl
*wbc
, char const *cmd_name
)
234 range_init (&range
, dao
->start_col
, dao
->start_row
,
235 dao
->start_col
+ dao
->cols
- 1, dao
->start_row
+ dao
->rows
- 1);
236 return (dao
->type
!= NewWorkbookOutput
&&
237 cmd_cell_range_is_locked_effective (dao
->sheet
, &range
, wbc
, cmd_name
));
241 * cmd_selection_is_locked_effective: (skip)
242 * checks whether the selection is effectively locked
244 * static gboolean cmd_selection_is_locked_effective
247 * Do not use this function unless the sheet is part of the
248 * workbook with the given wbcg (otherwise the results may be strange)
252 cmd_selection_is_locked_effective (Sheet
*sheet
, GSList
*selection
,
253 WorkbookControl
*wbc
, char const *cmd_name
)
255 for (; selection
; selection
= selection
->next
) {
256 GnmRange
*range
= selection
->data
;
257 if (cmd_cell_range_is_locked_effective (sheet
, range
, wbc
, cmd_name
))
264 * A helper routine to select a range and make sure the top-left
268 select_range (Sheet
*sheet
, const GnmRange
*r
, WorkbookControl
*wbc
)
272 if (sheet
->workbook
!= wb_control_get_workbook (wbc
)) {
274 * We could try to pick a random wbc for the sheet's
275 * workbook. But not right now.
280 wb_control_sheet_focus (wbc
, sheet
);
281 sv
= sheet_get_view (sheet
, wb_control_view (wbc
));
282 sv_selection_reset (sv
);
283 sv_selection_add_range (sv
, r
);
284 sv_make_cell_visible (sv
, r
->start
.col
, r
->start
.row
, FALSE
);
288 * A helper routine to select a list of ranges and make sure the top-left
289 * corner of the last is visible.
292 select_selection (Sheet
*sheet
, GSList
*selection
, WorkbookControl
*wbc
)
294 SheetView
*sv
= sheet_get_view (sheet
, wb_control_view (wbc
));
295 const GnmRange
*r0
= NULL
;
298 g_return_if_fail (selection
!= NULL
);
300 wb_control_sheet_focus (wbc
, sheet
);
301 sv_selection_reset (sv
);
302 for (l
= selection
; l
; l
= l
->next
) {
303 GnmRange
const *r
= l
->data
;
304 sv_selection_add_range (sv
, r
);
307 sv_make_cell_visible (sv
, r0
->start
.col
, r0
->start
.row
, FALSE
);
312 * with a list of commands.
313 * @cmd_list: The command list to check.
315 * Utility routine to get the descriptor associated
316 * Returns : A static reference to a descriptor. DO NOT free this.
319 get_menu_label (GSList
*cmd_list
)
321 if (cmd_list
!= NULL
) {
322 GnmCommand
*cmd
= GNM_COMMAND (cmd_list
->data
);
323 return cmd
->cmd_descriptor
;
330 * undo_redo_menu_labels:
331 * @wb: The book whose undo/redo queues we are modifying
333 * Another utility to set the menus correctly.
336 undo_redo_menu_labels (Workbook
*wb
)
338 char const *undo_label
= get_menu_label (wb
->undo_commands
);
339 char const *redo_label
= get_menu_label (wb
->redo_commands
);
341 WORKBOOK_FOREACH_CONTROL (wb
, view
, control
,
342 wb_control_undo_redo_labels (control
, undo_label
, redo_label
);
347 update_after_action (Sheet
*sheet
, WorkbookControl
*wbc
)
352 g_return_if_fail (IS_SHEET (sheet
));
354 sheet_mark_dirty (sheet
);
355 sheet_update (sheet
);
357 if (sheet
->workbook
== wb_control_get_workbook (wbc
))
358 WORKBOOK_VIEW_FOREACH_CONTROL (wb_control_view (wbc
), control
,
359 wb_control_sheet_focus (control
, sheet
););
360 } else if (wbc
!= NULL
) {
361 Sheet
*sheet
= wb_control_cur_sheet (wbc
);
363 sheet_update (sheet
);
370 * @wbc: The workbook control which issued the request.
371 * Any user level errors generated by undoing will be reported
374 * Undo the last command executed.
377 command_undo (WorkbookControl
*wbc
)
380 GnmCommandClass
*klass
;
381 Workbook
*wb
= wb_control_get_workbook (wbc
);
383 g_return_if_fail (wb
!= NULL
);
384 g_return_if_fail (wb
->undo_commands
!= NULL
);
386 cmd
= GNM_COMMAND (wb
->undo_commands
->data
);
387 g_return_if_fail (cmd
!= NULL
);
389 klass
= CMD_CLASS (cmd
);
390 g_return_if_fail (klass
!= NULL
);
394 /* TRUE indicates a failure to undo. Leave the command where it is */
395 if (!klass
->undo_cmd (cmd
, wbc
)) {
396 gboolean undo_cleared
;
398 update_after_action (cmd
->sheet
, wbc
);
400 if (!cmd
->workbook_modified_before_do
)
401 go_doc_set_dirty (GO_DOC (wb
), FALSE
);
404 * A few commands clear the undo queue. For those, we do not
405 * want to stuff the cmd object on the redo queue.
407 undo_cleared
= (wb
->undo_commands
== NULL
);
410 wb
->undo_commands
= g_slist_remove (wb
->undo_commands
, cmd
);
411 wb
->redo_commands
= g_slist_prepend (wb
->redo_commands
, cmd
);
413 WORKBOOK_FOREACH_CONTROL (wb
, view
, control
, {
414 wb_control_undo_redo_pop (control
, TRUE
);
415 wb_control_undo_redo_push (control
, FALSE
, cmd
->cmd_descriptor
, cmd
);
417 undo_redo_menu_labels (wb
);
418 /* TODO : Should we mark the workbook as clean or pristine too */
422 g_object_unref (cmd
);
427 * @wbc: The workbook control which issued the request.
429 * Redo the last command that was undone.
430 * Any user level errors generated by redoing will be reported
434 command_redo (WorkbookControl
*wbc
)
437 GnmCommandClass
*klass
;
438 Workbook
*wb
= wb_control_get_workbook (wbc
);
440 g_return_if_fail (wb
);
441 g_return_if_fail (wb
->redo_commands
);
443 cmd
= GNM_COMMAND (wb
->redo_commands
->data
);
444 g_return_if_fail (cmd
!= NULL
);
446 klass
= CMD_CLASS (cmd
);
447 g_return_if_fail (klass
!= NULL
);
451 cmd
->workbook_modified_before_do
=
452 go_doc_is_dirty (wb_control_get_doc (wbc
));
454 /* TRUE indicates a failure to redo. Leave the command where it is */
455 if (!klass
->redo_cmd (cmd
, wbc
)) {
456 gboolean redo_cleared
;
458 update_after_action (cmd
->sheet
, wbc
);
461 * A few commands clear the undo queue. For those, we do not
462 * want to stuff the cmd object on the redo queue.
464 redo_cleared
= (wb
->redo_commands
== NULL
);
467 wb
->redo_commands
= g_slist_remove (wb
->redo_commands
, cmd
);
468 wb
->undo_commands
= g_slist_prepend (wb
->undo_commands
, cmd
);
470 WORKBOOK_FOREACH_CONTROL (wb
, view
, control
, {
471 wb_control_undo_redo_push (control
, TRUE
, cmd
->cmd_descriptor
, cmd
);
472 wb_control_undo_redo_pop (control
, FALSE
);
474 undo_redo_menu_labels (wb
);
478 g_object_unref (cmd
);
483 * @wbc: The workbook control which issued the request.
485 * Repeat the last command (if possible)
487 * Any user level errors generated by redoing will be reported
491 command_repeat (WorkbookControl
*wbc
)
494 GnmCommandClass
*klass
;
495 Workbook
*wb
= wb_control_get_workbook (wbc
);
497 g_return_if_fail (wb
);
498 g_return_if_fail (wb
->undo_commands
);
500 cmd
= GNM_COMMAND (wb
->undo_commands
->data
);
501 g_return_if_fail (cmd
!= NULL
);
503 klass
= CMD_CLASS (cmd
);
504 g_return_if_fail (klass
!= NULL
);
506 if (klass
->repeat_cmd
!= NULL
)
507 (*klass
->repeat_cmd
) (cmd
, wbc
);
511 * command_setup_combos :
514 * Initialize the combos to correspond to the current undo/redo state.
517 command_setup_combos (WorkbookControl
*wbc
)
519 char const *undo_label
= NULL
, *redo_label
= NULL
;
521 Workbook
*wb
= wb_control_get_workbook (wbc
);
523 g_return_if_fail (wb
);
525 wb_control_undo_redo_truncate (wbc
, 0, TRUE
);
526 tmp
= g_slist_reverse (wb
->undo_commands
);
527 for (ptr
= tmp
; ptr
!= NULL
; ptr
= ptr
->next
) {
528 undo_label
= get_menu_label (ptr
);
529 wb_control_undo_redo_push (wbc
, TRUE
, undo_label
, ptr
->data
);
531 if (g_slist_reverse (tmp
)) {} /* ignore, list is in undo_commands */
533 wb_control_undo_redo_truncate (wbc
, 0, FALSE
);
534 tmp
= g_slist_reverse (wb
->redo_commands
);
535 for (ptr
= tmp
; ptr
!= NULL
; ptr
= ptr
->next
) {
536 redo_label
= get_menu_label (ptr
);
537 wb_control_undo_redo_push (wbc
, FALSE
, redo_label
, ptr
->data
);
539 if (g_slist_reverse (tmp
)) {} /* ignore, list is in redo_commands */
541 /* update the menus too */
542 wb_control_undo_redo_labels (wbc
, undo_label
, redo_label
);
546 * command_list_release:
547 * @cmds: (element-type GObject): the set of commands to free.
549 * command_list_release : utility routine to free the resources associated
550 * with a list of commands.
552 * NOTE : remember to NULL the list when you are done.
555 command_list_release (GSList
*cmd_list
)
557 while (cmd_list
!= NULL
) {
558 GObject
*cmd
= G_OBJECT (cmd_list
->data
);
560 g_return_if_fail (cmd
!= NULL
);
562 g_object_unref (cmd
);
563 cmd_list
= g_slist_remove (cmd_list
, cmd_list
->data
);
568 * Each undo item has a certain size. The size of typing a value into
569 * a cell is the unit size. A large autoformat could have a size of
570 * hundreds or even thousands.
572 * We wish to have the same undo behaviour across platforms, so please
573 * don't use sizeof in computing the undo size.
576 #undef DEBUG_TRUNCATE_UNDO
579 * Truncate the undo list if it is too big.
581 * Returns -1 if no truncation was done, or else the number of elements
585 truncate_undo_info (Workbook
*wb
)
592 size_left
= gnm_conf_get_undo_size ();
593 max_num
= gnm_conf_get_undo_maxnum ();
595 #ifdef DEBUG_TRUNCATE_UNDO
596 g_printerr ("Undo sizes:");
599 for (l
= wb
->undo_commands
, prev
= NULL
, ok_count
= 0;
601 prev
= l
, l
= l
->next
, ok_count
++) {
603 GnmCommand
*cmd
= GNM_COMMAND (l
->data
);
604 int size
= cmd
->size
;
608 * We could g_assert, but that would cause data loss.
609 * Instead, just continue.
611 g_warning ("Faulty undo_size_func, please report.");
615 #ifdef DEBUG_TRUNCATE_UNDO
616 g_printerr (" %d", size
);
619 /* Keep at least one undo item. */
620 if (ok_count
>= max_num
|| (size
> size_left
&& ok_count
>= 1)) {
621 /* Current item is too big; truncate list here. */
622 command_list_release (l
);
626 wb
->undo_commands
= NULL
;
627 #ifdef DEBUG_TRUNCATE_UNDO
628 g_printerr ("[trunc]\n");
634 * In order to allow a series of useful small items behind
635 * a big item, leave at least 10% of current item's size.
637 min_leave
= size
/ 10;
638 size_left
= MAX (size_left
- size
, min_leave
);
641 #ifdef DEBUG_TRUNCATE_UNDO
649 * command_register_undo:
650 * @wbc: The workbook control that issued the command.
651 * @cmd: The new command to add.
653 * An internal utility to tack a new command
654 * onto the undo list.
657 command_register_undo (WorkbookControl
*wbc
, GObject
*obj
)
663 g_return_if_fail (wbc
!= NULL
);
664 wb
= wb_control_get_workbook (wbc
);
666 cmd
= GNM_COMMAND (obj
);
667 g_return_if_fail (cmd
!= NULL
);
669 command_list_release (wb
->redo_commands
);
670 wb
->redo_commands
= NULL
;
672 g_object_ref (obj
); /* keep a ref in case it gets truncated away */
673 wb
->undo_commands
= g_slist_prepend (wb
->undo_commands
, cmd
);
674 undo_trunc
= truncate_undo_info (wb
);
676 WORKBOOK_FOREACH_CONTROL (wb
, view
, control
, {
677 wb_control_undo_redo_push (control
, TRUE
, cmd
->cmd_descriptor
, cmd
);
679 wb_control_undo_redo_truncate (control
, undo_trunc
, TRUE
);
680 wb_control_undo_redo_truncate (control
, 0, FALSE
);
682 undo_redo_menu_labels (wb
);
683 g_object_unref (obj
);
688 * gnm_command_push_undo:
689 * @wbc: The workbook control that issued the command.
690 * @obj: The new command to add.
692 * An internal utility to tack a new command
693 * onto the undo list.
695 * returns : TRUE if there was an error.
698 gnm_command_push_undo (WorkbookControl
*wbc
, GObject
*obj
)
702 GnmCommandClass
*klass
;
704 g_return_val_if_fail (wbc
!= NULL
, TRUE
);
706 cmd
= GNM_COMMAND (obj
);
707 cmd
->workbook_modified_before_do
=
708 go_doc_is_dirty (wb_control_get_doc (wbc
));
710 g_return_val_if_fail (cmd
!= NULL
, TRUE
);
712 klass
= CMD_CLASS (cmd
);
713 g_return_val_if_fail (klass
!= NULL
, TRUE
);
715 /* TRUE indicates a failure to do the command */
716 trouble
= klass
->redo_cmd (cmd
, wbc
);
717 update_after_action (cmd
->sheet
, wbc
);
720 command_register_undo (wbc
, obj
);
722 g_object_unref (obj
);
728 * command_undo_sheet_delete deletes the sheet without deleting the current cmd.
729 * returns true if is indeed deleted the sheet.
730 * Note: only call this for a sheet of your current workbook from the undo procedure
734 command_undo_sheet_delete (Sheet
* sheet
)
736 Workbook
*wb
= sheet
->workbook
;
738 g_return_val_if_fail (IS_SHEET (sheet
), FALSE
);
740 if (wb
->redo_commands
!= NULL
) {
741 command_list_release (wb
->redo_commands
);
742 wb
->redo_commands
= NULL
;
743 WORKBOOK_FOREACH_CONTROL (wb
, view
, ctl
,
744 wb_control_undo_redo_truncate (ctl
, 0, FALSE
););
745 undo_redo_menu_labels (wb
);
748 workbook_sheet_delete (sheet
);
753 /******************************************************************/
756 cmd_set_text_full_check_texpr (GnmCellIter
const *iter
, GnmExprTop
const *texpr
)
758 if (iter
->cell
== NULL
||
759 !gnm_expr_top_equal (iter
->cell
->base
.texpr
, texpr
))
760 return VALUE_TERMINATE
;
765 cmd_set_text_full_check_text (GnmCellIter
const *iter
, char *text
)
769 gboolean quoted
= FALSE
;
771 if (gnm_cell_is_blank (iter
->cell
))
772 return ((text
== NULL
|| text
[0] == '\0') ? NULL
: VALUE_TERMINATE
);
774 if (text
== NULL
|| text
[0] == '\0')
775 return VALUE_TERMINATE
;
777 old_text
= gnm_cell_get_text_for_editing (iter
->cell
, NULL
, "ed
);
778 same
= g_strcmp0 (old_text
, text
) == 0;
780 if (!same
&& !quoted
&& iter
->cell
->value
&& VALUE_IS_STRING (iter
->cell
->value
)
782 same
= g_strcmp0 (old_text
, text
+ 1) == 0;
786 return (same
? NULL
: VALUE_TERMINATE
);
790 cmd_set_text_full_check_markup (GnmCellIter
const *iter
, PangoAttrList
*markup
)
792 PangoAttrList
const *old_markup
= NULL
;
793 gboolean same_markup
;
795 g_return_val_if_fail (iter
->cell
!= NULL
, NULL
);
797 if (iter
->cell
->value
&& VALUE_IS_STRING (iter
->cell
->value
)) {
798 const GOFormat
*fmt
= VALUE_FMT (iter
->cell
->value
);
799 if (fmt
&& go_format_is_markup (fmt
)) {
800 old_markup
= go_format_get_markup (fmt
);
801 if (go_pango_attr_list_is_empty (old_markup
))
806 same_markup
= gnm_pango_attr_list_equal (old_markup
, markup
);
808 return same_markup
? NULL
: VALUE_TERMINATE
;
814 * the caller is expected to have ensured:
816 * 1) that no array is being split
817 * 2) that the range is not locked.
820 * We will free the selection but nothing else.
825 cmd_set_text_full (WorkbookControl
*wbc
, GSList
*selection
, GnmEvalPos
*ep
,
826 char const *new_text
, PangoAttrList
*markup
,
827 gboolean autocorrect
)
830 char const *expr_txt
;
831 GnmExprTop
const *texpr
= NULL
;
834 gboolean result
, autofit_col
= FALSE
, same_text_and_not_same_markup
= FALSE
;
837 Sheet
*sheet
= ep
->sheet
;
839 ColRowIndexList
*cri_col_list
= NULL
, *cri_row_list
= NULL
;
840 GOFormat
const *format
= gnm_style_get_format
841 (sheet_style_get (sheet
, ep
->eval
.col
, ep
->eval
.row
));
843 g_return_val_if_fail (selection
!= NULL
, TRUE
);
845 parse_pos_init_evalpos (&pp
, ep
);
846 name
= undo_range_list_name (sheet
, selection
);
848 if ((format
== NULL
) || !go_format_is_text (format
)) {
849 expr_txt
= gnm_expr_char_start_p (new_text
);
850 if (expr_txt
!= NULL
)
851 texpr
= gnm_expr_parse_str
852 (expr_txt
, &pp
, GNM_EXPR_PARSE_DEFAULT
,
853 sheet_get_conventions (sheet
), NULL
);
858 GnmStyle
*new_style
= NULL
;
859 gboolean same_texpr
= TRUE
;
861 /* We should check whether we are in fact changing anything: */
862 for (l
= selection
; l
!= NULL
&& same_texpr
; l
= l
->next
) {
863 GnmRange
*r
= l
->data
;
865 sheet_foreach_cell_in_range
866 (sheet
, CELL_ITER_ALL
,
867 r
->start
.col
, r
->start
.row
,
868 r
->end
.col
, r
->end
.row
,
869 (CellIterFunc
) cmd_set_text_full_check_texpr
,
872 same_texpr
= (val
!= VALUE_TERMINATE
);
873 if (val
!= NULL
&& same_texpr
)
878 gnm_expr_top_unref (texpr
);
880 range_fragment_free (selection
);
884 text
= g_strdup_printf (_("Inserting expression in %s"), name
);
886 if (go_format_is_general (format
)) {
887 sf
= gnm_auto_style_format_suggest (texpr
, ep
);
889 new_style
= gnm_style_new ();
890 gnm_style_set_format (new_style
, sf
);
891 go_format_unref (sf
);
895 for (l
= selection
; l
!= NULL
; l
= l
->next
) {
897 undo
= go_undo_combine
898 (undo
, clipboard_copy_range_undo (sheet
, l
->data
));
899 sr
= gnm_sheet_range_new (sheet
, l
->data
);
900 redo
= go_undo_combine
901 (redo
, sheet_range_set_expr_undo (sr
, texpr
));
903 sr
= gnm_sheet_range_new (sheet
, l
->data
);
904 redo
= go_undo_combine
905 (redo
, sheet_apply_style_undo (sr
, new_style
));
909 gnm_style_unref (new_style
);
910 gnm_expr_top_unref (texpr
);
914 PangoAttrList
*adj_markup
= NULL
;
916 gboolean same_text
= TRUE
;
917 gboolean same_markup
= TRUE
;
919 if (new_text
== NULL
)
921 else if (autocorrect
)
922 corrected
= autocorrect_tool (new_text
);
924 corrected
= g_strdup (new_text
);
926 if (corrected
&& (corrected
[0] == '\'') && corrected
[1] == '\0') {
928 corrected
= g_strdup ("");
931 /* We should check whether we are in fact changing anything: */
933 for (l
= selection
; l
!= NULL
&& same_text
; l
= l
->next
) {
934 GnmRange
*r
= l
->data
;
936 sheet_foreach_cell_in_range
937 (sheet
, CELL_ITER_ALL
,
938 r
->start
.col
, r
->start
.row
,
939 r
->end
.col
, r
->end
.row
,
940 (CellIterFunc
) cmd_set_text_full_check_text
,
941 (gpointer
) corrected
);
943 same_text
= (val
!= VALUE_TERMINATE
);
944 if (val
!= NULL
&& same_text
)
948 if (go_pango_attr_list_is_empty (markup
))
950 if (markup
&& corrected
&& corrected
[0] == '\'') {
951 markup
= adj_markup
= pango_attr_list_copy (markup
);
952 go_pango_attr_list_erase (adj_markup
, 0, 1);
956 for (l
= selection
; l
!= NULL
&& same_text
; l
= l
->next
) {
957 GnmRange
*r
= l
->data
;
959 sheet_foreach_cell_in_range
960 (sheet
, CELL_ITER_IGNORE_BLANK
,
961 r
->start
.col
, r
->start
.row
,
962 r
->end
.col
, r
->end
.row
,
963 (CellIterFunc
) cmd_set_text_full_check_markup
,
966 same_markup
= (val
!= VALUE_TERMINATE
);
967 if (val
!= NULL
&& same_markup
)
974 range_fragment_free (selection
);
976 pango_attr_list_unref (adj_markup
);
980 text
= g_strdup_printf (_("Editing style of %s"), name
);
982 text_str
= gnm_cmd_trunc_descriptor (g_string_new (corrected
), NULL
);
983 text
= g_strdup_printf (_("Typing \"%s\" in %s"), text_str
->str
, name
);
984 g_string_free (text_str
, TRUE
);
987 for (l
= selection
; l
!= NULL
; l
= l
->next
) {
989 undo
= go_undo_combine
990 (undo
, clipboard_copy_range_undo (sheet
, l
->data
));
992 sr
= gnm_sheet_range_new (sheet
, l
->data
);
993 redo
= go_undo_combine
994 (redo
, sheet_range_set_text_undo
998 sr
= gnm_sheet_range_new (sheet
, l
->data
);
999 /* Note: order of combination matters!! */
1000 redo
= go_undo_combine
1001 (sheet_range_set_markup_undo (sr
, markup
), redo
);
1006 pango_attr_list_unref (adj_markup
);
1009 same_text_and_not_same_markup
= (same_text
&& !same_markup
);
1013 /* We are combining this since we don't want to apply and undo twice.*/
1014 if (same_text_and_not_same_markup
|| !autofit_col
) {
1015 GnmCell
*cell
= sheet_cell_fetch
1016 (sheet
, ep
->eval
.col
, ep
->eval
.row
);
1019 go_undo_undo (redo
);
1020 nvis
= !VALUE_IS_STRING (cell
->value
);
1023 if (same_text_and_not_same_markup
)
1024 /* We only have to do something if at least one cell */
1025 /* now contains a string, but they contain all the same thing. */
1026 same_text_and_not_same_markup
= nvis
;
1027 go_undo_undo (undo
);
1029 if (same_text_and_not_same_markup
) {
1030 /*We had the same text and different markup but we are not entering strings. */
1031 g_object_unref (undo
);
1032 g_object_unref (redo
);
1034 range_fragment_free (selection
);
1037 for (l
= selection
; l
!= NULL
; l
= l
->next
) {
1038 GnmRange
*r
= l
->data
;
1041 new_r
= g_new (GnmRange
, 1);
1043 redo
= go_undo_combine
1046 (GOUndoBinaryFunc
) colrow_autofit_row
,
1049 cri_row_list
= colrow_get_index_list
1050 (r
->start
.row
, r
->end
.row
, cri_row_list
);
1053 new_r
= g_new (GnmRange
, 1);
1055 redo
= go_undo_combine
1058 (GOUndoBinaryFunc
) colrow_autofit_col
,
1061 cri_col_list
= colrow_get_index_list
1062 (r
->start
.col
, r
->end
.col
, cri_col_list
);
1065 undo
= go_undo_combine (undo
,
1066 gnm_undo_colrow_restore_state_group_new
1069 colrow_get_sizes (sheet
, TRUE
,
1070 cri_col_list
, -1)));
1071 undo
= go_undo_combine (undo
,
1072 gnm_undo_colrow_restore_state_group_new
1075 colrow_get_sizes (sheet
, FALSE
,
1076 cri_row_list
, -1)));
1079 result
= cmd_generic (wbc
, text
, undo
, redo
);
1081 range_fragment_free (selection
);
1088 * the caller is expected to have ensured:
1090 * 1) that no array is being split
1091 * 2) that the range is not locked.
1096 cmd_area_set_text (WorkbookControl
*wbc
, SheetView
*sv
,
1097 char const *new_text
, PangoAttrList
*markup
)
1101 GSList
*selection
= selection_get_ranges (sv
, FALSE
);
1103 eval_pos_init_editpos (&ep
, sv
);
1104 result
= cmd_set_text_full (wbc
, selection
, &ep
,
1105 new_text
, markup
, TRUE
);
1110 cmd_set_text (WorkbookControl
*wbc
,
1111 Sheet
*sheet
, GnmCellPos
const *pos
,
1112 char const *new_text
,
1113 PangoAttrList
*markup
,
1114 gboolean autocorrect
)
1116 GnmCell
const *cell
;
1122 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
1123 g_return_val_if_fail (new_text
!= NULL
, TRUE
);
1125 /* Ensure that we are not splitting up an array */
1126 cell
= sheet_cell_get (sheet
, pos
->col
, pos
->row
);
1127 if (gnm_cell_is_nonsingleton_array (cell
)) {
1128 gnm_cmd_context_error_splits_array (GO_CMD_CONTEXT (wbc
),
1129 _("Set Text"), NULL
);
1133 eval_pos_init_pos (&ep
, sheet
, pos
);
1134 r
= g_new (GnmRange
, 1);
1135 r
->start
= r
->end
= *pos
;
1136 selection
= g_slist_prepend (NULL
, r
);
1137 result
= cmd_set_text_full (wbc
, selection
, &ep
,
1138 new_text
, markup
, autocorrect
);
1144 * cmd_area_set_array_expr
1146 * the caller is expected to have ensured:
1148 * 1) that no array is being split
1149 * 2) that the selection consists of a single range
1150 * 3) that the range is not locked.
1155 cmd_area_set_array_expr (WorkbookControl
*wbc
, SheetView
*sv
,
1156 GnmExprTop
const *texpr
)
1158 GSList
*selection
= selection_get_ranges (sv
, FALSE
);
1159 GOUndo
*undo
= NULL
;
1160 GOUndo
*redo
= NULL
;
1162 Sheet
*sheet
= sv_sheet (sv
);
1166 GnmRange
*r_1
, *r_2
, *r
;
1167 ColRowIndexList
*cri_col_list
;
1168 ColRowIndexList
*cri_row_list
;
1170 g_return_val_if_fail (selection
!= NULL
, TRUE
);
1171 g_return_val_if_fail (selection
->next
== NULL
, TRUE
);
1173 name
= undo_range_list_name (sheet
, selection
);
1174 text
= g_strdup_printf (_("Inserting array expression in %s"), name
);
1177 r
= selection
->data
;
1179 cri_row_list
= colrow_get_index_list
1180 (r
->start
.row
, r
->end
.row
, NULL
);
1181 cri_col_list
= colrow_get_index_list
1182 (r
->start
.col
, r
->end
.col
, NULL
);
1183 undo
= clipboard_copy_range_undo (sheet
, selection
->data
);
1184 undo
= go_undo_combine (undo
,
1185 gnm_undo_colrow_restore_state_group_new
1188 colrow_get_sizes (sheet
, TRUE
,
1189 cri_col_list
, -1)));
1190 undo
= go_undo_combine (undo
,
1191 gnm_undo_colrow_restore_state_group_new
1194 colrow_get_sizes (sheet
, FALSE
,
1195 cri_row_list
, -1)));
1197 sr
= gnm_sheet_range_new (sheet
, r
);
1198 r_1
= g_new (GnmRange
, 1);
1200 r_2
= g_new (GnmRange
, 1);
1202 redo
= gnm_cell_set_array_formula_undo (sr
, texpr
);
1203 redo
= go_undo_combine
1206 (GOUndoBinaryFunc
) colrow_autofit_col
,
1209 redo
= go_undo_combine
1212 (GOUndoBinaryFunc
) colrow_autofit_row
,
1216 range_fragment_free (selection
);
1217 result
= cmd_generic (wbc
, text
, undo
, redo
);
1223 * cmd_create_data_table
1225 * the caller is expected to have ensured:
1227 * 1) that no array is being split
1228 * 2) that the range is not locked.
1232 cmd_create_data_table (WorkbookControl
*wbc
, Sheet
*sheet
, GnmRange
const *r
,
1233 char const *col_input
, char const *row_input
)
1235 GOUndo
*undo
= NULL
;
1236 GOUndo
*redo
= NULL
;
1242 GnmExprTop
const *texpr
;
1244 name
= undo_range_name (sheet
, r
);
1245 text
= g_strdup_printf (_("Creating a Data Table in %s"), name
);
1248 undo
= clipboard_copy_range_undo (sheet
, r
);
1250 sr
= gnm_sheet_range_new (sheet
, r
);
1251 parse_pos_init (&pp
, NULL
, sheet
, r
->start
.col
, r
->start
.row
);
1252 name
= g_strdup_printf ("TABLE(%s,%s)", row_input
, col_input
);
1253 texpr
= gnm_expr_parse_str
1254 (name
, &pp
, GNM_EXPR_PARSE_DEFAULT
,
1255 sheet_get_conventions (sheet
), NULL
);
1258 if (texpr
== NULL
) {
1259 g_object_unref (undo
);
1264 redo
= gnm_cell_set_array_formula_undo (sr
, texpr
);
1265 gnm_expr_top_unref (texpr
);
1267 result
= cmd_generic (wbc
, text
, undo
, redo
);
1272 /******************************************************************/
1274 #define CMD_INS_DEL_COLROW_TYPE (cmd_ins_del_colrow_get_type ())
1275 #define CMD_INS_DEL_COLROW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_INS_DEL_COLROW_TYPE, CmdInsDelColRow))
1286 GnmRange
*cutcopied
;
1287 SheetView
*cut_copy_view
;
1289 gboolean (*redo_action
) (Sheet
*sheet
, int col
, int count
,
1290 GOUndo
**pundo
, GOCmdContext
*cc
);
1292 gboolean (*repeat_action
) (WorkbookControl
*wbc
, Sheet
*sheet
,
1293 int start
, int count
);
1299 cmd_ins_del_colrow_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
)
1301 CmdInsDelColRow
const *orig
= (CmdInsDelColRow
const *) cmd
;
1302 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
1303 Sheet
*sheet
= sv_sheet (sv
);
1304 GnmRange
const *r
= selection_first_range (sv
,
1305 GO_CMD_CONTEXT (wbc
), _("Ins/Del Column/Row"));
1312 start
= r
->start
.col
, count
= range_width (r
);
1314 start
= r
->start
.row
, count
= range_height (r
);
1316 orig
->repeat_action (wbc
, sheet
, start
, count
);
1319 MAKE_GNM_COMMAND (CmdInsDelColRow
, cmd_ins_del_colrow
, cmd_ins_del_colrow_repeat
)
1322 cmd_ins_del_colrow_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
1324 CmdInsDelColRow
*me
= CMD_INS_DEL_COLROW (cmd
);
1327 go_undo_undo (me
->undo
);
1328 g_object_unref (me
->undo
);
1332 /* Ins/Del Row/Col re-ants things completely to account
1333 * for the shift of col/rows.
1335 if (me
->cutcopied
!= NULL
&& me
->cut_copy_view
!= NULL
)
1336 gnm_app_clipboard_cut_copy (wbc
, me
->is_cut
, me
->cut_copy_view
,
1337 me
->cutcopied
, FALSE
);
1343 cmd_ins_del_colrow_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
1345 CmdInsDelColRow
*me
= CMD_INS_DEL_COLROW (cmd
);
1346 GOCmdContext
*cc
= GO_CMD_CONTEXT (wbc
);
1347 int idx
= me
->index
;
1348 int count
= me
->count
;
1350 if (me
->redo_action (me
->sheet
, idx
, count
, &me
->undo
, cc
)) {
1355 /* Ins/Del Row/Col re-ants things completely to account
1356 * for the shift of col/rows. */
1357 if (me
->cutcopied
!= NULL
&& me
->cut_copy_view
!= NULL
) {
1359 GnmRange s
= *me
->cutcopied
;
1360 int key
= me
->is_insert
? count
: -count
;
1361 int threshold
= me
->is_insert
? idx
: idx
+ 1;
1364 * Really only applies if the regions that are
1365 * inserted/deleted are above the cut/copied region.
1368 if (threshold
<= s
.start
.col
) {
1372 } else if (threshold
<= s
.start
.row
) {
1377 gnm_app_clipboard_cut_copy (wbc
, me
->is_cut
,
1381 gnm_app_clipboard_unant ();
1388 cmd_ins_del_colrow_finalize (GObject
*cmd
)
1390 CmdInsDelColRow
*me
= CMD_INS_DEL_COLROW (cmd
);
1393 g_object_unref (me
->undo
);
1395 g_free (me
->cutcopied
);
1397 sv_weak_unref (&(me
->cut_copy_view
));
1399 gnm_command_finalize (cmd
);
1403 cmd_ins_del_colrow (WorkbookControl
*wbc
,
1405 gboolean is_cols
, gboolean is_insert
,
1406 char const *descriptor
, int index
, int count
)
1408 CmdInsDelColRow
*me
;
1412 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
1413 g_return_val_if_fail (count
> 0, TRUE
);
1415 me
= g_object_new (CMD_INS_DEL_COLROW_TYPE
, NULL
);
1418 me
->is_cols
= is_cols
;
1419 me
->is_insert
= is_insert
;
1422 me
->redo_action
= me
->is_insert
1423 ? (me
->is_cols
? sheet_insert_cols
: sheet_insert_rows
)
1424 : (me
->is_cols
? sheet_delete_cols
: sheet_delete_rows
);
1425 me
->repeat_action
= me
->is_insert
1426 ? (me
->is_cols
? cmd_insert_cols
: cmd_insert_rows
)
1427 : (me
->is_cols
? cmd_delete_cols
: cmd_delete_rows
);
1429 /* Range that will get deleted. */
1430 first
= me
->is_insert
1431 ? colrow_max (is_cols
, sheet
) - count
1433 last
= first
+ count
- 1;
1434 (is_cols
? range_init_cols
: range_init_rows
) (&r
, sheet
, first
, last
);
1436 /* Note: redo_action checks for array subdivision. */
1438 /* Check for locks */
1439 if (cmd_cell_range_is_locked_effective (sheet
, &r
, wbc
, descriptor
)) {
1440 g_object_unref (me
);
1444 /* We store the cut or/copied range if applicable */
1445 if (!gnm_app_clipboard_is_empty () &&
1446 gnm_app_clipboard_area_get () &&
1447 sheet
== gnm_app_clipboard_sheet_get ()) {
1448 me
->cutcopied
= gnm_range_dup (gnm_app_clipboard_area_get ());
1449 me
->is_cut
= gnm_app_clipboard_is_cut ();
1450 sv_weak_ref (gnm_app_clipboard_sheet_view_get (),
1451 &(me
->cut_copy_view
));
1453 me
->cutcopied
= NULL
;
1455 me
->cmd
.sheet
= sheet
;
1456 me
->cmd
.size
= count
* 10; /* FIXME? */
1457 me
->cmd
.cmd_descriptor
= descriptor
;
1459 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
1463 cmd_insert_cols (WorkbookControl
*wbc
,
1464 Sheet
*sheet
, int start_col
, int count
)
1469 range_init_full_sheet (&r
, sheet
);
1470 r
.start
.col
= r
.end
.col
- count
+ 1;
1472 if (!sheet_range_trim (sheet
, &r
, FALSE
, FALSE
)) {
1473 go_gtk_notice_dialog (wbcg_toplevel (WBC_GTK (wbc
)), GTK_MESSAGE_ERROR
,
1474 ngettext ("Inserting %i column before column %s would push data off the sheet. "
1475 "Please enlarge the sheet first.",
1476 "Inserting %i columns before column %s would push data off the sheet. "
1477 "Please enlarge the sheet first.",
1479 count
, col_name (start_col
));
1483 mesg
= g_strdup_printf
1484 (ngettext ("Inserting %d column before %s",
1485 "Inserting %d columns before %s",
1487 count
, col_name (start_col
));
1488 return cmd_ins_del_colrow (wbc
, sheet
, TRUE
, TRUE
, mesg
, start_col
, count
);
1492 cmd_insert_rows (WorkbookControl
*wbc
,
1493 Sheet
*sheet
, int start_row
, int count
)
1498 range_init_full_sheet (&r
, sheet
);
1499 r
.start
.row
= r
.end
.row
- count
+ 1;
1501 if (!sheet_range_trim (sheet
, &r
, FALSE
, FALSE
)) {
1502 go_gtk_notice_dialog (wbcg_toplevel (WBC_GTK (wbc
)), GTK_MESSAGE_ERROR
,
1503 ngettext ("Inserting %i row before row %s would push data off the sheet. "
1504 "Please enlarge the sheet first.",
1505 "Inserting %i rows before row %s would push data off the sheet. "
1506 "Please enlarge the sheet first.",
1508 count
, row_name (start_row
));
1512 mesg
= g_strdup_printf
1513 (ngettext ("Inserting %d row before %s",
1514 "Inserting %d rows before %s",
1516 count
, row_name (start_row
));
1517 return cmd_ins_del_colrow (wbc
, sheet
, FALSE
, TRUE
, mesg
, start_row
, count
);
1521 cmd_delete_cols (WorkbookControl
*wbc
,
1522 Sheet
*sheet
, int start_col
, int count
)
1524 char *mesg
= g_strdup_printf ((count
> 1)
1525 ? _("Deleting columns %s")
1526 : _("Deleting column %s"),
1527 cols_name (start_col
, start_col
+ count
- 1));
1528 return cmd_ins_del_colrow (wbc
, sheet
, TRUE
, FALSE
, mesg
, start_col
, count
);
1532 cmd_delete_rows (WorkbookControl
*wbc
,
1533 Sheet
*sheet
, int start_row
, int count
)
1535 char *mesg
= g_strdup_printf ((count
> 1)
1536 ? _("Deleting rows %s")
1537 : _("Deleting row %s"),
1538 rows_name (start_row
, start_row
+ count
- 1));
1539 return cmd_ins_del_colrow (wbc
, sheet
, FALSE
, FALSE
, mesg
, start_row
, count
);
1542 /******************************************************************/
1547 } cmd_selection_clear_row_handler_t
;
1550 cmd_selection_clear_row_handler (GnmColRowIter
const *iter
,
1551 cmd_selection_clear_row_handler_t
*data
)
1553 if ((!iter
->cri
->in_filter
) || iter
->cri
->visible
) {
1554 GnmRange
*r
= gnm_range_dup (data
->r
);
1555 r
->start
.row
= r
->end
.row
= iter
->pos
;
1556 data
->selection
= g_slist_prepend (data
->selection
, r
);
1562 cmd_selection_clear (WorkbookControl
*wbc
, int clear_flags
)
1564 char *names
, *descriptor
;
1566 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
1567 GSList
*selection
= selection_get_ranges (sv
, FALSE
/* No intersection */);
1568 Sheet
*sheet
= sv_sheet (sv
);
1571 GOUndo
*undo
= NULL
;
1572 GOUndo
*redo
= NULL
;
1575 if ((clear_flags
& CLEAR_FILTERED_ONLY
) != 0 && sheet
->filters
!= NULL
) {
1576 /* We need to modify the selection to only include filtered rows. */
1577 cmd_selection_clear_row_handler_t data
;
1578 data
.selection
= selection
;
1579 for (ranges
= selection
; ranges
!= NULL
; ranges
= ranges
->next
) {
1581 data
.r
= ranges
->data
;
1582 filter
= gnm_sheet_filter_intersect_rows
1583 (sheet
, data
.r
->start
.row
, data
.r
->end
.row
);
1585 colrow_foreach (&sheet
->rows
, data
.r
->start
.row
, data
.r
->end
.row
,
1586 (ColRowHandler
) cmd_selection_clear_row_handler
, &data
);
1587 g_free (ranges
->data
);
1588 ranges
->data
= NULL
;
1591 selection
= g_slist_remove_all (data
.selection
, NULL
);
1594 /* We should first determine whether we break anything by clearing */
1595 /* Check for array subdivision *//* Check for locked cells */
1596 if (sheet_ranges_split_region (sheet
, selection
,
1597 GO_CMD_CONTEXT (wbc
), _("Clear")) ||
1598 cmd_selection_is_locked_effective (sheet
, selection
, wbc
, _("Clear"))) {
1599 range_fragment_free (selection
);
1604 /* We now need to build the descriptor */
1605 /* Collect clear types for descriptor */
1606 if (clear_flags
!= (CLEAR_VALUES
| CLEAR_FORMATS
| CLEAR_COMMENTS
)) {
1607 GSList
*m
, *l
= NULL
;
1608 types
= g_string_new (NULL
);
1609 if (clear_flags
& CLEAR_VALUES
)
1610 l
= g_slist_append (l
, g_string_new (_("contents")));
1611 if (clear_flags
& CLEAR_FORMATS
)
1612 l
= g_slist_append (l
, g_string_new (_("formats")));
1613 if (clear_flags
& CLEAR_COMMENTS
)
1614 l
= g_slist_append (l
, g_string_new (_("comments")));
1615 /* Using a list for this may seem overkill, but is really the only
1616 * right way to do this
1618 for (m
= l
; m
!= NULL
; m
= m
->next
) {
1619 GString
*s
= m
->data
;
1621 g_string_append_len (types
, s
->str
, s
->len
);
1622 g_string_free (s
, TRUE
);
1625 g_string_append (types
, ", ");
1629 types
= g_string_new (_("all"));
1630 /* The range name string will automatically be truncated, we don't
1631 * need to truncate the "types" list because it will not grow
1634 names
= undo_range_list_name (sheet
, selection
);
1635 descriptor
= g_strdup_printf (_("Clearing %s in %s"), types
->str
, names
);
1637 g_string_free (types
, TRUE
);
1638 size
= g_slist_length (selection
);
1640 clear_flags
|= CLEAR_NOCHECKARRAY
;
1642 if (clear_flags
& (CLEAR_VALUES
| CLEAR_FORMATS
))
1643 clear_flags
|= CLEAR_RECALC_DEPS
;
1645 /* We are now ready to build the redo and undo items */
1646 for (ranges
= selection
; ranges
!= NULL
; ranges
= ranges
->next
) {
1647 GnmRange
const *r
= ranges
->data
;
1648 GnmSheetRange
*sr
= gnm_sheet_range_new (sheet
, r
);
1650 undo
= go_undo_combine (undo
, clipboard_copy_range_undo (sheet
, r
));
1651 redo
= go_undo_combine
1652 (redo
, sheet_clear_region_undo
1656 range_fragment_free (selection
);
1658 result
= cmd_generic_with_size (wbc
, descriptor
, size
, undo
, redo
);
1659 g_free (descriptor
);
1664 /******************************************************************/
1666 #define CMD_FORMAT_TYPE (cmd_format_get_type ())
1667 #define CMD_FORMAT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_FORMAT_TYPE, CmdFormat))
1671 GnmStyleList
*styles
;
1672 ColRowIndexList
*rows
;
1673 ColRowStateGroup
*old_heights
;
1674 } CmdFormatOldStyle
;
1680 GnmStyle
*new_style
;
1681 GnmBorder
**borders
;
1685 cmd_format_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
)
1687 CmdFormat
const *orig
= (CmdFormat
const *) cmd
;
1690 if (orig
->new_style
)
1691 gnm_style_ref (orig
->new_style
);
1693 for (i
= GNM_STYLE_BORDER_TOP
; i
< GNM_STYLE_BORDER_EDGE_MAX
; i
++)
1694 gnm_style_border_ref (orig
->borders
[i
]);
1696 cmd_selection_format (wbc
, orig
->new_style
, orig
->borders
, NULL
);
1698 MAKE_GNM_COMMAND (CmdFormat
, cmd_format
, cmd_format_repeat
)
1701 cmd_format_undo (GnmCommand
*cmd
,
1702 G_GNUC_UNUSED WorkbookControl
*wbc
)
1704 CmdFormat
*me
= CMD_FORMAT (cmd
);
1706 g_return_val_if_fail (me
!= NULL
, TRUE
);
1708 if (me
->old_styles
) {
1709 GSList
*rstyles
= g_slist_reverse (g_slist_copy (me
->old_styles
));
1710 GSList
*rsel
= g_slist_reverse (g_slist_copy (me
->selection
));
1713 for (l1
= rstyles
, l2
= rsel
; l1
; l1
= l1
->next
, l2
= l2
->next
) {
1714 CmdFormatOldStyle
*os
= l1
->data
;
1715 GnmRange
const *r
= l2
->data
;
1716 GnmSpanCalcFlags flags
= sheet_style_set_list
1718 &os
->pos
, os
->styles
, NULL
, NULL
);
1720 if (os
->old_heights
) {
1721 colrow_restore_state_group (me
->cmd
.sheet
, FALSE
,
1724 colrow_state_group_destroy (os
->old_heights
);
1725 os
->old_heights
= NULL
;
1726 colrow_index_list_destroy (os
->rows
);
1730 sheet_range_calc_spans (me
->cmd
.sheet
, r
, flags
);
1731 sheet_flag_style_update_range (me
->cmd
.sheet
, r
);
1734 sheet_redraw_all (me
->cmd
.sheet
, FALSE
);
1735 g_slist_free (rstyles
);
1736 g_slist_free (rsel
);
1739 select_selection (me
->cmd
.sheet
, me
->selection
, wbc
);
1745 cmd_format_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
1747 CmdFormat
*me
= CMD_FORMAT (cmd
);
1749 gboolean re_fit_height
;
1751 g_return_val_if_fail (me
!= NULL
, TRUE
);
1753 /* Check for locked cells */
1754 if (cmd_selection_is_locked_effective (me
->cmd
.sheet
, me
->selection
,
1755 wbc
, _("Changing Format")))
1758 re_fit_height
= me
->new_style
&&
1759 (GNM_SPANCALC_ROW_HEIGHT
& gnm_style_required_spanflags (me
->new_style
));
1761 for (l1
= me
->old_styles
, l2
= me
->selection
; l2
; l1
= l1
->next
, l2
= l2
->next
) {
1762 CmdFormatOldStyle
*os
= l1
->data
;
1763 GnmRange
const *r
= l2
->data
;
1766 sheet_apply_border (me
->cmd
.sheet
, r
, me
->borders
);
1767 if (me
->new_style
) {
1768 gnm_style_ref (me
->new_style
);
1769 sheet_apply_style (me
->cmd
.sheet
, r
, me
->new_style
);
1771 colrow_autofit (me
->cmd
.sheet
, r
, FALSE
, FALSE
,
1773 &os
->rows
, &os
->old_heights
);
1776 sheet_flag_style_update_range (me
->cmd
.sheet
, r
);
1778 sheet_redraw_all (me
->cmd
.sheet
, FALSE
);
1779 sheet_mark_dirty (me
->cmd
.sheet
);
1781 select_selection (me
->cmd
.sheet
, me
->selection
, wbc
);
1787 cmd_format_finalize (GObject
*cmd
)
1789 CmdFormat
*me
= CMD_FORMAT (cmd
);
1793 gnm_style_unref (me
->new_style
);
1794 me
->new_style
= NULL
;
1797 for (i
= GNM_STYLE_BORDER_TOP
; i
< GNM_STYLE_BORDER_EDGE_MAX
; i
++)
1798 gnm_style_border_unref (me
->borders
[i
]);
1799 g_free (me
->borders
);
1803 if (me
->old_styles
!= NULL
) {
1806 for (l
= me
->old_styles
; l
!= NULL
; l
= g_slist_remove (l
, l
->data
)) {
1807 CmdFormatOldStyle
*os
= l
->data
;
1809 style_list_free (os
->styles
);
1810 colrow_index_list_destroy (os
->rows
);
1811 colrow_state_group_destroy (os
->old_heights
);
1814 me
->old_styles
= NULL
;
1817 range_fragment_free (me
->selection
);
1818 me
->selection
= NULL
;
1820 gnm_command_finalize (cmd
);
1825 * @wbc: the workbook control.
1827 * @style: style to apply to the selection
1828 * @borders: borders to apply to the selection
1829 * @opt_translated_name: An optional name to use in place of 'Format Cells'
1831 * If borders is non NULL, then the GnmBorder references are passed,
1832 * the GnmStyle reference is also passed.
1834 * It absorbs the reference to the style.
1836 * Return value: TRUE if there was a problem
1839 cmd_selection_format (WorkbookControl
*wbc
,
1840 GnmStyle
*style
, GnmBorder
**borders
,
1841 char const *opt_translated_name
)
1845 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
1847 me
= g_object_new (CMD_FORMAT_TYPE
, NULL
);
1849 me
->selection
= selection_get_ranges (sv
, FALSE
); /* TRUE ? */
1850 me
->new_style
= style
;
1852 me
->cmd
.sheet
= sv_sheet (sv
);
1853 me
->cmd
.size
= 1; /* Updated below. */
1855 me
->old_styles
= NULL
;
1856 for (l
= me
->selection
; l
; l
= l
->next
) {
1857 GnmRange
const *sel_r
= l
->data
;
1858 GnmRange range
= *sel_r
;
1859 CmdFormatOldStyle
*os
;
1861 /* Store the containing range to handle borders */
1862 if (borders
!= NULL
) {
1863 if (range
.start
.col
> 0) range
.start
.col
--;
1864 if (range
.start
.row
> 0) range
.start
.row
--;
1865 if (range
.end
.col
< gnm_sheet_get_last_col (me
->cmd
.sheet
)) range
.end
.col
++;
1866 if (range
.end
.row
< gnm_sheet_get_last_row (me
->cmd
.sheet
)) range
.end
.row
++;
1869 os
= g_new (CmdFormatOldStyle
, 1);
1871 os
->styles
= sheet_style_get_range (me
->cmd
.sheet
, &range
);
1872 os
->pos
= range
.start
;
1874 os
->old_heights
= NULL
;
1876 me
->cmd
.size
+= g_slist_length (os
->styles
);
1877 me
->old_styles
= g_slist_append (me
->old_styles
, os
);
1883 me
->borders
= g_new (GnmBorder
*, GNM_STYLE_BORDER_EDGE_MAX
);
1884 for (i
= GNM_STYLE_BORDER_TOP
; i
< GNM_STYLE_BORDER_EDGE_MAX
; i
++)
1885 me
->borders
[i
] = borders
[i
];
1889 if (opt_translated_name
== NULL
) {
1890 char *names
= undo_range_list_name (me
->cmd
.sheet
, me
->selection
);
1892 me
->cmd
.cmd_descriptor
= g_strdup_printf (_("Changing format of %s"), names
);
1895 me
->cmd
.cmd_descriptor
= g_strdup (opt_translated_name
);
1897 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
1900 /******************************************************************/
1903 cmd_selection_format_toggle_font_style_filter (PangoAttribute
*attribute
, PangoAttrType
*pt
)
1905 return ((attribute
->klass
->type
== *pt
) ||
1906 ((PANGO_ATTR_RISE
== *pt
) && (attribute
->klass
->type
== PANGO_ATTR_SCALE
)));
1915 cmd_selection_format_toggle_font_style_cb (GnmCellIter
const *iter
, csftfs
*closure
)
1917 if (iter
->cell
&& iter
->cell
->value
&& VALUE_IS_STRING (iter
->cell
->value
)) {
1918 const GOFormat
*fmt
= VALUE_FMT (iter
->cell
->value
);
1919 if (fmt
&& go_format_is_markup (fmt
)) {
1920 const PangoAttrList
*old_markup
=
1921 go_format_get_markup (fmt
);
1922 PangoAttrList
*new_markup
= pango_attr_list_copy ((PangoAttrList
*)old_markup
);
1923 PangoAttrList
*other
= pango_attr_list_filter
1925 (PangoAttrFilterFunc
) cmd_selection_format_toggle_font_style_filter
,
1927 if (other
!= NULL
) {
1930 range_init_cellpos (&r
, &iter
->pp
.eval
);
1931 sr
= gnm_sheet_range_new (iter
->pp
.sheet
, &r
);
1932 closure
->undo
= go_undo_combine (closure
->undo
,
1933 sheet_range_set_markup_undo (sr
, new_markup
));
1935 pango_attr_list_unref (new_markup
);
1936 pango_attr_list_unref (other
);
1943 cmd_selection_format_toggle_font_style (WorkbookControl
*wbc
,
1944 GnmStyle
*style
, GnmStyleElement t
)
1946 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
1947 Sheet
*sheet
= sv
->sheet
;
1948 GSList
*selection
= selection_get_ranges (sv
, FALSE
), *l
;
1951 GOUndo
*undo
= NULL
;
1952 GOUndo
*redo
= NULL
;
1957 case MSTYLE_FONT_BOLD
:
1958 pt
= PANGO_ATTR_WEIGHT
;
1960 case MSTYLE_FONT_ITALIC
:
1961 pt
= PANGO_ATTR_STYLE
;
1963 case MSTYLE_FONT_UNDERLINE
:
1964 pt
= PANGO_ATTR_UNDERLINE
;
1966 case MSTYLE_FONT_STRIKETHROUGH
:
1967 pt
= PANGO_ATTR_STRIKETHROUGH
;
1969 case MSTYLE_FONT_SCRIPT
:
1970 pt
= PANGO_ATTR_RISE
; /* and PANGO_ATTR_SCALE (see ) */
1973 pt
= PANGO_ATTR_INVALID
;
1978 name
= undo_range_list_name (sheet
, selection
);
1979 text
= g_strdup_printf (_("Setting Font Style of %s"), name
);
1982 for (l
= selection
; l
!= NULL
; l
= l
->next
) {
1984 undo
= go_undo_combine
1985 (undo
, clipboard_copy_range_undo (sheet
, l
->data
));
1986 sr
= gnm_sheet_range_new (sheet
, l
->data
);
1987 redo
= go_undo_combine
1988 (redo
, sheet_apply_style_undo (sr
, style
));
1989 if (pt
!= PANGO_ATTR_INVALID
) {
1991 closure
.undo
= NULL
;
1993 sheet_foreach_cell_in_range (sheet
, CELL_ITER_IGNORE_BLANK
,
1994 sr
->range
.start
.col
, sr
->range
.start
.row
,
1995 sr
->range
.end
.col
, sr
->range
.end
.row
,
1996 (CellIterFunc
) cmd_selection_format_toggle_font_style_cb
,
1998 redo
= go_undo_combine (redo
, closure
.undo
);
2001 gnm_style_unref (style
);
2002 result
= cmd_generic (wbc
, text
, undo
, redo
);
2004 range_fragment_free (selection
);
2010 /******************************************************************/
2014 cmd_resize_colrow (WorkbookControl
*wbc
, Sheet
*sheet
,
2015 gboolean is_cols
, ColRowIndexList
*selection
,
2020 GOUndo
*undo
= NULL
;
2021 GOUndo
*redo
= NULL
;
2022 gboolean is_single
, result
;
2024 ColRowStateGroup
*saved_state
;
2026 list
= colrow_index_list_to_string (selection
, is_cols
, &is_single
);
2027 gnm_cmd_trunc_descriptor (list
, NULL
);
2032 ? g_strdup_printf (_("Autofitting column %s"), list
->str
)
2033 : g_strdup_printf (_("Autofitting row %s"), list
->str
);
2034 else if (new_size
> 0)
2036 ? g_strdup_printf (ngettext ("Setting width of column %s to %d pixel",
2037 "Setting width of column %s to %d pixels",
2039 list
->str
, new_size
)
2040 : g_strdup_printf (ngettext ("Setting height of row %s to %d pixel",
2041 "Setting height of row %s to %d pixels",
2043 list
->str
, new_size
);
2045 ? g_strdup_printf (_("Setting width of column %s to default"),
2048 _("Setting height of row %s to default"), list
->str
);
2052 ? g_strdup_printf (_("Autofitting columns %s"), list
->str
)
2053 : g_strdup_printf (_("Autofitting rows %s"), list
->str
);
2054 else if (new_size
> 0)
2056 ? g_strdup_printf (ngettext("Setting width of columns %s to %d pixel",
2057 "Setting width of columns %s to %d pixels",
2059 list
->str
, new_size
)
2060 : g_strdup_printf (ngettext("Setting height of rows %s to %d pixel",
2061 "Setting height of rows %s to %d pixels",
2063 list
->str
, new_size
);
2066 _("Setting width of columns %s to default"), list
->str
)
2068 _("Setting height of rows %s to default"), list
->str
);
2070 g_string_free (list
, TRUE
);
2072 saved_state
= colrow_get_sizes (sheet
, is_cols
, selection
, new_size
);
2073 undo
= gnm_undo_colrow_restore_state_group_new
2074 (sheet
, is_cols
, colrow_index_list_copy (selection
), saved_state
);
2076 redo
= gnm_undo_colrow_set_sizes_new (sheet
, is_cols
, selection
, new_size
, NULL
);
2078 result
= cmd_generic_with_size (wbc
, text
, size
, undo
, redo
);
2085 cmd_autofit_selection (WorkbookControl
*wbc
, SheetView
*sv
, Sheet
*sheet
, gboolean fit_width
,
2086 ColRowIndexList
*selectionlist
)
2088 GOUndo
*undo
= NULL
;
2089 GOUndo
*redo
= NULL
;
2091 ColRowStateGroup
*saved_state
;
2092 GSList
*l
, *selection
= selection_get_ranges (sv
, TRUE
);
2093 gchar
*names
= undo_range_list_name (sheet
, selection
);
2094 gchar
const *format
= fit_width
?
2095 N_("Autofitting width of %s") : N_("Autofitting height of %s");
2096 gchar
*text
= g_strdup_printf (_(format
), names
);
2100 saved_state
= colrow_get_sizes (sheet
, fit_width
, selectionlist
, -1);
2101 undo
= gnm_undo_colrow_restore_state_group_new
2102 (sheet
, fit_width
, colrow_index_list_copy (selectionlist
), saved_state
);
2104 for (l
= selection
; l
!= NULL
; l
= l
->next
)
2105 redo
= go_undo_combine
2106 (redo
, gnm_undo_colrow_set_sizes_new
2107 (sheet
, fit_width
, NULL
, -1, l
->data
));
2109 result
= cmd_generic (wbc
, text
, undo
, redo
);
2115 /******************************************************************/
2117 #define CMD_SORT_TYPE (cmd_sort_get_type ())
2118 #define CMD_SORT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SORT_TYPE, CmdSort))
2125 GnmCellRegion
*old_contents
;
2128 MAKE_GNM_COMMAND (CmdSort
, cmd_sort
, NULL
)
2131 cmd_sort_finalize (GObject
*cmd
)
2133 CmdSort
*me
= CMD_SORT (cmd
);
2135 if (me
->data
!= NULL
)
2136 gnm_sort_data_destroy (me
->data
);
2138 if (me
->old_contents
!= NULL
)
2139 cellregion_unref (me
->old_contents
);
2141 gnm_command_finalize (cmd
);
2145 cmd_sort_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
2147 CmdSort
*me
= CMD_SORT (cmd
);
2148 GnmSortData
*data
= me
->data
;
2151 paste_target_init (&pt
, data
->sheet
, data
->range
,
2152 PASTE_CONTENTS
| PASTE_FORMATS
|
2153 (data
->retain_formats
? PASTE_FORMATS
: 0));
2154 clipboard_paste_region (me
->old_contents
,
2156 GO_CMD_CONTEXT (wbc
));
2162 cmd_sort_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
2164 CmdSort
*me
= CMD_SORT (cmd
);
2165 GnmSortData
*data
= me
->data
;
2167 /* Check for locks */
2168 if (cmd_cell_range_is_locked_effective
2169 (data
->sheet
, data
->range
, wbc
, _("Sorting")))
2173 gnm_sort_position (data
, me
->perm
, GO_CMD_CONTEXT (wbc
));
2176 clipboard_copy_range (data
->sheet
, data
->range
);
2177 me
->cmd
.size
= cellregion_cmd_size (me
->old_contents
);
2178 me
->perm
= gnm_sort_contents (data
, GO_CMD_CONTEXT (wbc
));
2185 cmd_sort (WorkbookControl
*wbc
, GnmSortData
*data
)
2190 g_return_val_if_fail (data
!= NULL
, TRUE
);
2192 desc
= g_strdup_printf (_("Sorting %s"), range_as_string (data
->range
));
2193 if (sheet_range_contains_merges_or_arrays (data
->sheet
, data
->range
, GO_CMD_CONTEXT (wbc
), desc
, TRUE
, TRUE
)) {
2194 gnm_sort_data_destroy (data
);
2199 me
= g_object_new (CMD_SORT_TYPE
, NULL
);
2203 me
->cmd
.sheet
= data
->sheet
;
2204 me
->cmd
.size
= 1; /* Changed in initial redo. */
2205 me
->cmd
.cmd_descriptor
= desc
;
2207 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
2210 /******************************************************************/
2212 #define CMD_COLROW_HIDE_TYPE (cmd_colrow_hide_get_type ())
2213 #define CMD_COLROW_HIDE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_COLROW_HIDE_TYPE, CmdColRowHide))
2219 ColRowVisList
*hide
, *show
;
2223 cmd_colrow_hide_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
)
2225 CmdColRowHide
const *orig
= (CmdColRowHide
const *) cmd
;
2226 cmd_selection_colrow_hide (wbc
, orig
->is_cols
, orig
->show
!= NULL
);
2228 MAKE_GNM_COMMAND (CmdColRowHide
, cmd_colrow_hide
, cmd_colrow_hide_repeat
)
2231 * cmd_colrow_hide_correct_selection :
2233 * Try to ensure that the selection/cursor is set to a visible row/col
2235 * Added to fix bug 38179
2236 * Removed because the result is irritating and the bug is actually XL
2240 cmd_colrow_hide_correct_selection (G_GNUC_UNUSED CmdColRowHide
*me
, G_GNUC_UNUSED WorkbookControl
*wbc
)
2244 SheetView
*sv
= sheet_get_view (me
->cmd
.sheet
,
2245 wb_control_view (wbc
));
2247 index
= colrow_find_adjacent_visible (me
->cmd
.sheet
, me
->is_cols
,
2248 me
->is_cols
? sv
->edit_pos
.col
: sv
->edit_pos
.row
,
2251 x
= me
->is_cols
? sv
->edit_pos
.row
: index
;
2252 y
= me
->is_cols
? index
: sv
->edit_pos
.col
;
2255 sv_selection_reset (sv
);
2257 sv_selection_add_full (sv
, y
, x
, y
, 0,
2258 y
, gnm_sheet_get_last_row (sheet
),
2259 GNM_SELECTION_MODE_ADD
);
2261 sv_selection_add_full (sv
, y
, x
, 0, x
,
2262 gnm_sheet_get_last_col (sheet
), x
,
2263 GNM_SELECTION_MODE_ADD
);
2269 cmd_colrow_hide_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
2271 CmdColRowHide
*me
= CMD_COLROW_HIDE (cmd
);
2273 g_return_val_if_fail (me
!= NULL
, TRUE
);
2275 colrow_set_visibility_list (me
->cmd
.sheet
, me
->is_cols
,
2277 colrow_set_visibility_list (me
->cmd
.sheet
, me
->is_cols
,
2280 if (me
->show
!= NULL
)
2281 cmd_colrow_hide_correct_selection (me
, wbc
);
2287 cmd_colrow_hide_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
2289 CmdColRowHide
*me
= CMD_COLROW_HIDE (cmd
);
2291 g_return_val_if_fail (me
!= NULL
, TRUE
);
2293 colrow_set_visibility_list (me
->cmd
.sheet
, me
->is_cols
,
2295 colrow_set_visibility_list (me
->cmd
.sheet
, me
->is_cols
,
2298 if (me
->hide
!= NULL
)
2299 cmd_colrow_hide_correct_selection (me
, wbc
);
2305 cmd_colrow_hide_finalize (GObject
*cmd
)
2307 CmdColRowHide
*me
= CMD_COLROW_HIDE (cmd
);
2308 colrow_vis_list_destroy (me
->hide
);
2310 colrow_vis_list_destroy (me
->show
);
2312 gnm_command_finalize (cmd
);
2316 cmd_selection_colrow_hide (WorkbookControl
*wbc
,
2317 gboolean is_cols
, gboolean visible
)
2320 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
2323 GSList
*show
= NULL
, *hide
= NULL
;
2326 show
= colrow_get_visiblity_toggle (sv
, is_cols
, TRUE
);
2328 hide
= colrow_get_visiblity_toggle (sv
, is_cols
, FALSE
);
2329 n
= colrow_vis_list_length (hide
) + colrow_vis_list_length (show
);
2330 sheet
= sv_sheet (sv
);
2333 /* If these are the last colrows to hide, check with the user */
2336 int i
, max
= gnm_sheet_get_max_cols (sheet
);
2338 for (i
= 0 ; i
< max
; i
++)
2340 (ci
= sheet_col_get (sheet
, i
)) ||
2344 int i
, max
= gnm_sheet_get_max_rows (sheet
);
2346 for (i
= 0 ; i
< max
; i
++)
2348 (ci
= sheet_row_get (sheet
, i
)) ||
2353 gchar
const *text
= is_cols
?
2354 _("Are you sure that you want to hide all columns? "
2355 "If you do so you can unhide them with the "
2356 "'Format\342\206\222Column\342\206\222Unhide' "
2358 _("Are you sure that you want to hide all rows? "
2359 "If you do so you can unhide them with the "
2360 "'Format\342\206\222Row\342\206\222Unhide' "
2362 if (!go_gtk_query_yes_no (wbcg_toplevel (WBC_GTK (wbc
)),
2363 FALSE
, "%s", text
)) {
2364 colrow_vis_list_destroy (show
);
2365 colrow_vis_list_destroy (hide
);
2371 me
= g_object_new (CMD_COLROW_HIDE_TYPE
, NULL
);
2374 me
->is_cols
= is_cols
;
2375 me
->cmd
.sheet
= sheet
;
2376 me
->cmd
.size
= 1 + g_slist_length (hide
) + g_slist_length (show
);
2377 me
->cmd
.cmd_descriptor
= g_strdup (is_cols
2378 ? (visible
? _("Unhide columns") : _("Hide columns"))
2379 : (visible
? _("Unhide rows") : _("Hide rows")));
2381 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
2385 cmd_selection_outline_change (WorkbookControl
*wbc
,
2386 gboolean is_cols
, int index
, int depth
)
2389 ColRowInfo
const *cri
;
2390 int first
= -1, last
= -1;
2391 gboolean visible
= FALSE
;
2393 Sheet
*sheet
= wb_control_cur_sheet (wbc
);
2394 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
2396 cri
= sheet_colrow_get_info (sheet
, index
, is_cols
);
2398 d
= cri
->outline_level
;
2402 /* Nodes only collapse when selected directly, selecting at a lower
2403 * level is a standard toggle. */
2405 if ((is_cols
? sheet
->outline_symbols_right
: sheet
->outline_symbols_below
)) {
2407 ColRowInfo
const *prev
=
2408 sheet_colrow_get (sheet
, index
-1, is_cols
);
2410 if (prev
!= NULL
&& prev
->outline_level
> d
) {
2411 visible
= (depth
== d
&& cri
->is_collapsed
);
2413 first
= colrow_find_outline_bound (sheet
, is_cols
,
2417 } else if (index
+1 < colrow_max (is_cols
, sheet
)) {
2418 ColRowInfo
const *next
=
2419 sheet_colrow_get (sheet
, index
+1, is_cols
);
2421 if (next
!= NULL
&& next
->outline_level
> d
) {
2422 visible
= (depth
== d
&& cri
->is_collapsed
);
2424 last
= colrow_find_outline_bound (sheet
, is_cols
,
2430 /* If nothing done yet do a simple collapse */
2431 if (first
< 0 && cri
->outline_level
> 0) {
2434 first
= colrow_find_outline_bound (sheet
, is_cols
, index
, depth
, FALSE
);
2435 last
= colrow_find_outline_bound (sheet
, is_cols
, index
, depth
, TRUE
);
2438 if (first
== last
&& depth
> cri
->outline_level
)
2442 if (first
< 0 || last
< 0)
2445 me
= g_object_new (CMD_COLROW_HIDE_TYPE
, NULL
);
2447 me
->is_cols
= is_cols
;
2448 me
->hide
= me
->show
= NULL
;
2450 me
->show
= colrow_get_outline_toggle (sv_sheet (sv
), is_cols
,
2453 me
->hide
= colrow_get_outline_toggle (sv_sheet (sv
), is_cols
,
2454 FALSE
, first
, last
);
2456 me
->cmd
.sheet
= sv_sheet (sv
);
2457 me
->cmd
.size
= 1 + g_slist_length (me
->show
) + g_slist_length (me
->hide
);
2458 me
->cmd
.cmd_descriptor
= g_strdup (is_cols
2459 ? (visible
? _("Expand columns") : _("Collapse columns"))
2460 : (visible
? _("Expand rows") : _("Collapse rows")));
2462 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
2466 cmd_global_outline_change (WorkbookControl
*wbc
, gboolean is_cols
, int depth
)
2469 ColRowVisList
*hide
, *show
;
2470 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
2472 colrow_get_global_outline (sv_sheet (sv
), is_cols
, depth
, &show
, &hide
);
2474 if (show
== NULL
&& hide
== NULL
)
2477 me
= g_object_new (CMD_COLROW_HIDE_TYPE
, NULL
);
2478 me
->is_cols
= is_cols
;
2481 me
->cmd
.sheet
= sv_sheet (sv
);
2482 me
->cmd
.size
= 1 + g_slist_length (me
->show
) + g_slist_length (me
->hide
);
2483 me
->cmd
.cmd_descriptor
= g_strdup_printf (is_cols
2484 ? _("Show column outline %d") : _("Show row outline %d"), depth
);
2486 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
2489 /******************************************************************/
2491 #define CMD_GROUP_TYPE (cmd_group_get_type ())
2492 #define CMD_GROUP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_GROUP_TYPE, CmdGroup))
2503 cmd_group_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
)
2505 CmdGroup
const *orig
= (CmdGroup
const *) cmd
;
2506 cmd_selection_group (wbc
, orig
->is_cols
, orig
->group
);
2508 MAKE_GNM_COMMAND (CmdGroup
, cmd_group
, cmd_group_repeat
)
2511 cmd_group_undo (GnmCommand
*cmd
,
2512 G_GNUC_UNUSED WorkbookControl
*wbc
)
2514 CmdGroup
const *me
= CMD_GROUP (cmd
);
2515 sheet_colrow_group_ungroup (me
->cmd
.sheet
,
2516 &me
->range
, me
->is_cols
, !me
->group
);
2521 cmd_group_redo (GnmCommand
*cmd
,
2522 G_GNUC_UNUSED WorkbookControl
*wbc
)
2524 CmdGroup
const *me
= CMD_GROUP (cmd
);
2525 sheet_colrow_group_ungroup (me
->cmd
.sheet
,
2526 &me
->range
, me
->is_cols
, me
->group
);
2531 cmd_group_finalize (GObject
*cmd
)
2533 gnm_command_finalize (cmd
);
2537 cmd_selection_group (WorkbookControl
*wbc
,
2538 gboolean is_cols
, gboolean group
)
2544 g_return_val_if_fail (wbc
!= NULL
, TRUE
);
2546 sv
= wb_control_cur_sheet_view (wbc
);
2547 r
= *selection_first_range (sv
, NULL
, NULL
);
2549 /* Check if this really is possible and display an error if it's not */
2550 if (sheet_colrow_can_group (sv
->sheet
, &r
, is_cols
) != group
) {
2552 go_cmd_context_error_system (GO_CMD_CONTEXT (wbc
), is_cols
2553 ? _("Those columns are already grouped")
2554 : _("Those rows are already grouped"));
2558 /* see if the user selected the col/row with the marker too */
2560 if (r
.start
.col
!= r
.end
.col
) {
2561 if (sv
->sheet
->outline_symbols_right
)
2567 if (r
.start
.row
!= r
.end
.row
) {
2568 if (sv
->sheet
->outline_symbols_below
)
2575 if (sheet_colrow_can_group (sv
->sheet
, &r
, is_cols
) != group
) {
2576 go_cmd_context_error_system (GO_CMD_CONTEXT (wbc
), is_cols
2577 ? _("Those columns are not grouped, you can't ungroup them")
2578 : _("Those rows are not grouped, you can't ungroup them"));
2583 me
= g_object_new (CMD_GROUP_TYPE
, NULL
);
2584 me
->is_cols
= is_cols
;
2588 me
->cmd
.sheet
= sv
->sheet
;
2590 me
->cmd
.cmd_descriptor
= is_cols
2591 ? g_strdup_printf (group
? _("Group columns %s") : _("Ungroup columns %s"),
2592 cols_name (me
->range
.start
.col
, me
->range
.end
.col
))
2593 : g_strdup_printf (group
? _("Group rows %d:%d") : _("Ungroup rows %d:%d"),
2594 me
->range
.start
.row
+ 1, me
->range
.end
.row
+ 1);
2596 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
2599 /******************************************************************/
2601 #define CMD_PASTE_CUT_TYPE (cmd_paste_cut_get_type ())
2602 #define CMD_PASTE_CUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_PASTE_CUT_TYPE, CmdPasteCut))
2607 GnmExprRelocateInfo info
;
2608 GSList
*paste_contents
;
2610 gboolean move_selection
;
2611 ColRowStateList
*saved_sizes
;
2613 /* handle redo-ing an undo with contents from a deleted sheet */
2614 GnmCellRegion
*deleted_sheet_contents
;
2617 MAKE_GNM_COMMAND (CmdPasteCut
, cmd_paste_cut
, NULL
)
2621 GnmCellRegion
*contents
;
2625 * cmd_paste_cut_update :
2627 * Utility routine to update things when we are transfering between sheets and
2631 cmd_paste_cut_update (GnmExprRelocateInfo
const *info
,
2632 G_GNUC_UNUSED WorkbookControl
*wbc
)
2634 Sheet
*o
= info
->origin_sheet
;
2635 Sheet
*t
= info
->target_sheet
;
2637 /* Dirty and update both sheets */
2638 sheet_mark_dirty (t
);
2641 if (IS_SHEET (o
) && o
!= t
) {
2642 sheet_mark_dirty (o
);
2648 cmd_paste_cut_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
2650 CmdPasteCut
*me
= CMD_PASTE_CUT (cmd
);
2651 GnmExprRelocateInfo reverse
;
2653 g_return_val_if_fail (me
!= NULL
, TRUE
);
2654 g_return_val_if_fail (me
->paste_contents
!= NULL
, TRUE
);
2655 g_return_val_if_fail (me
->deleted_sheet_contents
== NULL
, TRUE
);
2657 reverse
.reloc_type
= GNM_EXPR_RELOCATE_MOVE_RANGE
;
2658 reverse
.target_sheet
= me
->info
.origin_sheet
;
2659 reverse
.origin_sheet
= me
->info
.target_sheet
;
2660 reverse
.origin
= me
->info
.origin
;
2661 range_translate (&reverse
.origin
,
2662 me
->info
.origin_sheet
, /* FIXME: What sheet? */
2663 me
->info
.col_offset
,
2664 me
->info
.row_offset
);
2665 reverse
.col_offset
= -me
->info
.col_offset
;
2666 reverse
.row_offset
= -me
->info
.row_offset
;
2668 /* Move things back being careful NOT to invalidate the src region */
2669 if (IS_SHEET (me
->info
.origin_sheet
))
2670 sheet_move_range (&reverse
, NULL
, GO_CMD_CONTEXT (wbc
));
2672 me
->deleted_sheet_contents
= clipboard_copy_range (
2673 reverse
.origin_sheet
, &reverse
.origin
);
2675 /* Restore the original row heights */
2676 colrow_set_states (me
->info
.target_sheet
, FALSE
,
2677 reverse
.origin
.start
.row
, me
->saved_sizes
);
2678 colrow_state_list_destroy (me
->saved_sizes
);
2679 me
->saved_sizes
= NULL
;
2681 if (me
->reloc_undo
) {
2682 go_undo_undo (me
->reloc_undo
);
2683 g_object_unref (me
->reloc_undo
);
2684 me
->reloc_undo
= NULL
;
2687 while (me
->paste_contents
) {
2688 PasteContent
*pc
= me
->paste_contents
->data
;
2689 me
->paste_contents
= g_slist_remove (me
->paste_contents
, pc
);
2691 clipboard_paste_region (pc
->contents
, &pc
->pt
, GO_CMD_CONTEXT (wbc
));
2692 cellregion_unref (pc
->contents
);
2696 /* Force update of the status area */
2697 sheet_flag_status_update_range (me
->info
.target_sheet
, NULL
);
2699 cmd_paste_cut_update (&me
->info
, wbc
);
2701 /* Select the original region */
2702 if (me
->move_selection
&& IS_SHEET (me
->info
.origin_sheet
))
2703 select_range (me
->info
.origin_sheet
,
2711 cmd_paste_cut_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
2713 CmdPasteCut
*me
= CMD_PASTE_CUT (cmd
);
2716 g_return_val_if_fail (me
!= NULL
, TRUE
);
2717 g_return_val_if_fail (me
->paste_contents
== NULL
, TRUE
);
2719 tmp
= me
->info
.origin
;
2720 range_translate (&tmp
, me
->info
.origin_sheet
, /* FIXME: What sheet? */
2721 me
->info
.col_offset
, me
->info
.row_offset
);
2722 range_normalize (&tmp
);
2724 g_return_val_if_fail (range_is_sane (&tmp
), TRUE
);
2726 if (me
->info
.origin_sheet
!= me
->info
.target_sheet
||
2727 !range_overlap (&me
->info
.origin
, &tmp
)) {
2728 PasteContent
*pc
= g_new (PasteContent
, 1);
2729 paste_target_init (&pc
->pt
, me
->info
.target_sheet
, &tmp
, PASTE_ALL_TYPES
);
2730 pc
->contents
= clipboard_copy_range (me
->info
.target_sheet
, &tmp
);
2731 me
->paste_contents
= g_slist_prepend (me
->paste_contents
, pc
);
2733 /* need to store any portions of the paste target
2734 * that do not overlap with the source.
2736 GSList
*ptr
, *frag
= range_split_ranges (&me
->info
.origin
, &tmp
);
2737 for (ptr
= frag
; ptr
!= NULL
; ptr
= ptr
->next
) {
2738 GnmRange
*r
= ptr
->data
;
2740 if (!range_overlap (&me
->info
.origin
, r
)) {
2741 PasteContent
*pc
= g_new (PasteContent
, 1);
2742 paste_target_init (&pc
->pt
, me
->info
.target_sheet
, r
, PASTE_ALL_TYPES
);
2743 pc
->contents
= clipboard_copy_range (me
->info
.target_sheet
, r
);
2744 me
->paste_contents
= g_slist_prepend (me
->paste_contents
, pc
);
2748 g_slist_free (frag
);
2751 /* rare corner case. If the origin sheet has been deleted */
2752 if (!IS_SHEET (me
->info
.origin_sheet
)) {
2754 paste_target_init (&pt
, me
->info
.target_sheet
, &tmp
, PASTE_ALL_TYPES
);
2755 sheet_clear_region (pt
.sheet
,
2756 tmp
.start
.col
, tmp
.start
.row
, tmp
.end
.col
, tmp
.end
.row
,
2757 CLEAR_VALUES
| CLEAR_MERGES
| CLEAR_NOCHECKARRAY
| CLEAR_RECALC_DEPS
,
2758 GO_CMD_CONTEXT (wbc
));
2759 clipboard_paste_region (me
->deleted_sheet_contents
,
2760 &pt
, GO_CMD_CONTEXT (wbc
));
2761 cellregion_unref (me
->deleted_sheet_contents
);
2762 me
->deleted_sheet_contents
= NULL
;
2764 sheet_move_range (&me
->info
, &me
->reloc_undo
, GO_CMD_CONTEXT (wbc
));
2766 cmd_paste_cut_update (&me
->info
, wbc
);
2768 /* Backup row heights and adjust row heights to fit */
2769 me
->saved_sizes
= colrow_get_states (me
->info
.target_sheet
, FALSE
, tmp
.start
.row
, tmp
.end
.row
);
2770 rows_height_update (me
->info
.target_sheet
, &tmp
, FALSE
);
2772 /* Make sure the destination is selected */
2773 if (me
->move_selection
)
2774 select_range (me
->info
.target_sheet
, &tmp
, wbc
);
2780 cmd_paste_cut_finalize (GObject
*cmd
)
2782 CmdPasteCut
*me
= CMD_PASTE_CUT (cmd
);
2784 if (me
->saved_sizes
)
2785 me
->saved_sizes
= colrow_state_list_destroy (me
->saved_sizes
);
2786 while (me
->paste_contents
) {
2787 PasteContent
*pc
= me
->paste_contents
->data
;
2788 me
->paste_contents
= g_slist_remove (me
->paste_contents
, pc
);
2789 cellregion_unref (pc
->contents
);
2792 if (me
->reloc_undo
) {
2793 g_object_unref (me
->reloc_undo
);
2794 me
->reloc_undo
= NULL
;
2796 if (me
->deleted_sheet_contents
) {
2797 cellregion_unref (me
->deleted_sheet_contents
);
2798 me
->deleted_sheet_contents
= NULL
;
2801 gnm_command_finalize (cmd
);
2805 cmd_paste_cut (WorkbookControl
*wbc
, GnmExprRelocateInfo
const *info
,
2806 gboolean move_selection
, char *descriptor
)
2812 g_return_val_if_fail (info
!= NULL
, TRUE
);
2814 /* This is vacuous */
2815 if (info
->origin_sheet
== info
->target_sheet
&&
2816 info
->col_offset
== 0 && info
->row_offset
== 0)
2819 /* FIXME: Do we want to show the destination range as well ? */
2820 where
= undo_range_name (info
->origin_sheet
, &info
->origin
);
2821 if (descriptor
== NULL
)
2822 descriptor
= g_strdup_printf (_("Moving %s"), where
);
2825 g_return_val_if_fail (info
!= NULL
, TRUE
);
2828 if (range_translate (&r
, info
->target_sheet
,
2829 info
->col_offset
, info
->row_offset
)) {
2831 go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbc
), descriptor
,
2832 _("is beyond sheet boundaries"));
2833 g_free (descriptor
);
2837 /* Check array subdivision & merged regions */
2838 if (sheet_range_splits_region (info
->target_sheet
, &r
,
2839 (info
->origin_sheet
== info
->target_sheet
)
2840 ? &info
->origin
: NULL
, GO_CMD_CONTEXT (wbc
), descriptor
)) {
2841 g_free (descriptor
);
2845 me
= g_object_new (CMD_PASTE_CUT_TYPE
, NULL
);
2848 me
->paste_contents
= NULL
;
2849 me
->deleted_sheet_contents
= NULL
;
2850 me
->reloc_undo
= NULL
;
2851 me
->move_selection
= move_selection
;
2852 me
->saved_sizes
= NULL
;
2854 me
->cmd
.sheet
= NULL
; /* we have potentially two different. */
2855 me
->cmd
.size
= 1; /* FIXME? */
2856 me
->cmd
.cmd_descriptor
= descriptor
;
2858 /* NOTE : if the destination workbook is different from the source
2859 * workbook should we have undo elements in both menus ?? It seems
2860 * poor form to hit undo in 1 window and effect another...
2862 * Maybe queue it as two different commands, as a clear in one book
2863 * and a paste in the other. This is not symmetric though. What
2864 * happens to the cells in the original sheet that now reference the
2865 * cells in the other? When do they reset to the original?
2867 * Probably when the clear in the original is undone.
2870 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
2873 /******************************************************************/
2876 warn_if_date_trouble (WorkbookControl
*wbc
, GnmCellRegion
*cr
)
2878 Workbook
*wb
= wb_control_get_workbook (wbc
);
2879 const GODateConventions
*wb_date_conv
= workbook_date_conv (wb
);
2881 if (cr
->date_conv
== NULL
)
2883 if (go_date_conv_equal (cr
->date_conv
, wb_date_conv
))
2886 /* We would like to show a warning, but it seems we cannot via a context. */
2889 err
= g_error_new (go_error_invalid(), 0,
2890 _("Copying between files with different date conventions.\n"
2891 "It is possible that some dates could be copied\n"
2893 go_cmd_context_error (GO_CMD_CONTEXT (wbc
), err
);
2899 #define CMD_PASTE_COPY_TYPE (cmd_paste_copy_get_type ())
2900 #define CMD_PASTE_COPY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_PASTE_COPY_TYPE, CmdPasteCopy))
2905 GnmCellRegion
*contents
;
2906 GSList
*pasted_objects
,*orig_contents_objects
;
2908 gboolean has_been_through_cycle
;
2909 gboolean only_objects
;
2910 ColRowStateGroup
*saved_sizes_rows
;
2911 ColRowStateGroup
*saved_sizes_cols
;
2912 ColRowIndexList
*saved_list_rows
;
2913 ColRowIndexList
*saved_list_cols
;
2914 gboolean single_merge_to_single_merge
;
2918 cmd_paste_copy_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
)
2920 CmdPasteCopy
const *orig
= (CmdPasteCopy
const *) cmd
;
2921 GnmPasteTarget new_dst
;
2922 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
2923 GnmRange
const *r
= selection_first_range (sv
,
2924 GO_CMD_CONTEXT (wbc
), _("Paste Copy"));
2925 GnmCellRegion
*newcr
;
2930 paste_target_init (&new_dst
, sv_sheet (sv
), r
, orig
->dst
.paste_flags
);
2931 newcr
= clipboard_copy_range (orig
->dst
.sheet
, &orig
->dst
.range
);
2932 cmd_paste_copy (wbc
, &new_dst
, newcr
);
2933 cellregion_unref (newcr
);
2935 MAKE_GNM_COMMAND (CmdPasteCopy
, cmd_paste_copy
, cmd_paste_copy_repeat
)
2938 by_addr (gconstpointer a
, gconstpointer b
)
2940 if (GPOINTER_TO_UINT (a
) < GPOINTER_TO_UINT (b
))
2942 if (GPOINTER_TO_UINT (a
) > GPOINTER_TO_UINT (b
))
2948 get_new_objects (Sheet
*sheet
, GSList
*old
)
2950 GSList
*objs
= g_slist_sort (g_slist_copy (sheet
->sheet_objects
),
2952 GSList
*p
= objs
, *last
= NULL
;
2956 while (p
&& (c
= by_addr (p
->data
, old
->data
)) < 0) {
2964 GSList
*next
= p
->next
;
2978 cmd_paste_copy_select_obj (SheetObject
*so
, SheetControlGUI
*scg
)
2980 scg_object_select (scg
, so
);
2984 cmd_paste_copy_impl (GnmCommand
*cmd
, WorkbookControl
*wbc
,
2987 CmdPasteCopy
*me
= CMD_PASTE_COPY (cmd
);
2988 GnmCellRegion
*contents
;
2989 GSList
*old_objects
;
2990 GnmPasteTarget actual_dst
;
2992 g_return_val_if_fail (me
!= NULL
, TRUE
);
2993 g_return_val_if_fail (me
->contents
!= NULL
, TRUE
);
2995 g_slist_foreach (me
->pasted_objects
,
2996 (GFunc
)sheet_object_clear_sheet
,
2998 g_slist_free_full (me
->pasted_objects
, (GDestroyNotify
)g_object_unref
);
2999 me
->pasted_objects
= NULL
;
3000 old_objects
= get_new_objects (me
->dst
.sheet
, NULL
);
3002 contents
= clipboard_copy_range (me
->dst
.sheet
, &me
->dst
.range
);
3003 if (me
->has_been_through_cycle
)
3004 me
->dst
.paste_flags
= PASTE_CONTENTS
|
3005 (me
->dst
.paste_flags
& PASTE_ALL_TYPES
);
3006 actual_dst
= me
->dst
;
3007 if (clipboard_paste_region (me
->contents
, &actual_dst
, GO_CMD_CONTEXT (wbc
))) {
3008 /* There was a problem, avoid leaking */
3009 cellregion_unref (contents
);
3010 g_slist_free (old_objects
);
3014 me
->pasted_objects
= get_new_objects (me
->dst
.sheet
, old_objects
);
3015 g_slist_foreach (me
->pasted_objects
, (GFunc
)g_object_ref
, NULL
);
3016 g_slist_free (old_objects
);
3019 colrow_restore_state_group (me
->dst
.sheet
, FALSE
,
3020 me
->saved_list_rows
, me
->saved_sizes_rows
);
3021 colrow_state_group_destroy (me
->saved_sizes_rows
);
3022 me
->saved_sizes_rows
= NULL
;
3023 colrow_index_list_destroy (me
->saved_list_rows
);
3024 me
->saved_list_rows
= NULL
;
3025 colrow_restore_state_group (me
->dst
.sheet
, TRUE
,
3026 me
->saved_list_cols
, me
->saved_sizes_cols
);
3027 colrow_state_group_destroy (me
->saved_sizes_cols
);
3028 me
->saved_sizes_cols
= NULL
;
3029 colrow_index_list_destroy (me
->saved_list_cols
);
3030 me
->saved_list_cols
= NULL
;
3032 colrow_autofit (me
->dst
.sheet
, &me
->dst
.range
, FALSE
, FALSE
,
3034 &me
->saved_list_rows
, &me
->saved_sizes_rows
);
3035 colrow_autofit (me
->dst
.sheet
, &me
->dst
.range
, TRUE
, TRUE
,
3037 &me
->saved_list_cols
, &me
->saved_sizes_cols
);
3041 * We cannot use the random set of objects at the target location.
3042 * See http://bugzilla.gnome.org/show_bug.cgi?id=308300
3044 g_slist_free_full (contents
->objects
, (GDestroyNotify
)g_object_unref
);
3045 contents
->objects
= is_undo
3046 ? go_slist_map (me
->orig_contents_objects
,
3047 (GOMapFunc
)sheet_object_dup
)
3050 cellregion_unref (me
->contents
);
3051 me
->contents
= contents
;
3052 me
->has_been_through_cycle
= TRUE
;
3054 /* Select the newly pasted contents (this queues a redraw) */
3055 if (me
->only_objects
&& GNM_IS_WBC_GTK (wbc
)) {
3056 SheetControlGUI
*scg
=
3057 wbcg_get_nth_scg (WBC_GTK (wbc
),
3058 cmd
->sheet
->index_in_wb
);
3059 scg_object_unselect (scg
, NULL
);
3060 g_slist_foreach (me
->pasted_objects
,
3061 (GFunc
) cmd_paste_copy_select_obj
, scg
);
3063 select_range (me
->dst
.sheet
, &me
->dst
.range
, wbc
);
3069 cmd_paste_copy_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
3071 return cmd_paste_copy_impl (cmd
, wbc
, TRUE
);
3075 cmd_paste_copy_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
3077 return cmd_paste_copy_impl (cmd
, wbc
, FALSE
);
3081 cmd_paste_copy_finalize (GObject
*cmd
)
3083 CmdPasteCopy
*me
= CMD_PASTE_COPY (cmd
);
3085 me
->saved_sizes_rows
= colrow_state_group_destroy (me
->saved_sizes_rows
);
3086 colrow_index_list_destroy (me
->saved_list_rows
);
3087 me
->saved_list_rows
= NULL
;
3088 me
->saved_sizes_cols
= colrow_state_group_destroy (me
->saved_sizes_cols
);
3089 colrow_index_list_destroy (me
->saved_list_cols
);
3090 me
->saved_list_cols
= NULL
;
3092 cellregion_unref (me
->contents
);
3093 me
->contents
= NULL
;
3095 g_slist_free_full (me
->pasted_objects
, (GDestroyNotify
)g_object_unref
);
3096 g_slist_free_full (me
->orig_contents_objects
, (GDestroyNotify
)g_object_unref
);
3097 gnm_command_finalize (cmd
);
3101 * cmd_paste_copy will ref cr as needed.
3104 cmd_paste_copy (WorkbookControl
*wbc
,
3105 GnmPasteTarget
const *pt
, GnmCellRegion
*cr
)
3108 int n_r
= 1, n_c
= 1;
3110 GnmRange
const *merge_src
;
3112 g_return_val_if_fail (pt
!= NULL
, TRUE
);
3113 g_return_val_if_fail (IS_SHEET (pt
->sheet
), TRUE
);
3114 g_return_val_if_fail (cr
!= NULL
, TRUE
);
3116 cellregion_ref (cr
);
3118 me
= g_object_new (CMD_PASTE_COPY_TYPE
, NULL
);
3120 me
->cmd
.sheet
= pt
->sheet
;
3121 me
->cmd
.size
= 1; /* FIXME? */
3123 range_name
= undo_range_name (pt
->sheet
, &pt
->range
);
3124 me
->cmd
.cmd_descriptor
= g_strdup_printf (_("Pasting into %s"),
3126 g_free (range_name
);
3130 me
->has_been_through_cycle
= FALSE
;
3131 me
->only_objects
= (cr
->cols
< 1 || cr
->rows
< 1);
3132 me
->saved_sizes_rows
= NULL
;
3133 me
->saved_sizes_cols
= NULL
;
3134 me
->saved_list_rows
= NULL
;
3135 me
->saved_list_cols
= NULL
;
3136 me
->pasted_objects
= NULL
;
3137 me
->orig_contents_objects
=
3138 go_slist_map (cr
->objects
, (GOMapFunc
)sheet_object_dup
);
3139 me
->single_merge_to_single_merge
= FALSE
;
3141 /* If the input is only objects ignore all this range stuff */
3142 if (!me
->only_objects
) {
3143 /* see if we need to do any tiling */
3144 GnmRange
*r
= &me
->dst
.range
;
3145 if (g_slist_length (cr
->merged
) == 1 &&
3146 (NULL
!= (merge_src
= cr
->merged
->data
)) &&
3147 range_height (merge_src
) == cr
->rows
&&
3148 range_width (merge_src
) == cr
->cols
) {
3149 /* We are copying from a single merge */
3150 GnmRange
const *merge
= gnm_sheet_merge_is_corner (pt
->sheet
, &r
->start
);
3151 if (merge
!= NULL
&& range_equal (r
, merge
)) {
3152 /* To a single merge */
3153 me
->single_merge_to_single_merge
= TRUE
;
3155 me
->dst
.paste_flags
|= PASTE_DONT_MERGE
;
3160 if (pt
->paste_flags
& PASTE_TRANSPOSE
) {
3161 n_c
= range_width (r
) / cr
->rows
;
3162 if (n_c
< 1) n_c
= 1;
3163 r
->end
.col
= r
->start
.col
+ n_c
* cr
->rows
- 1;
3165 n_r
= range_height (r
) / cr
->cols
;
3166 if (n_r
< 1) n_r
= 1;
3167 r
->end
.row
= r
->start
.row
+ n_r
* cr
->cols
- 1;
3169 /* Before looking for tiling if we are not transposing,
3170 * allow pasting a full col or row from a single cell */
3171 n_c
= range_width (r
);
3172 if (n_c
== 1 && cr
->cols
== gnm_sheet_get_max_cols (me
->cmd
.sheet
)) {
3174 r
->end
.col
= gnm_sheet_get_last_col (me
->cmd
.sheet
);
3177 if (n_c
< 1) n_c
= 1;
3178 r
->end
.col
= r
->start
.col
+ n_c
* cr
->cols
- 1;
3181 n_r
= range_height (r
);
3182 if (n_r
== 1 && cr
->rows
== gnm_sheet_get_max_rows (me
->cmd
.sheet
)) {
3184 r
->end
.row
= gnm_sheet_get_last_row (me
->cmd
.sheet
);
3187 if (n_r
< 1) n_r
= 1;
3188 r
->end
.row
= r
->start
.row
+ n_r
* cr
->rows
- 1;
3192 if (cr
->cols
!= 1 || cr
->rows
!= 1) {
3193 /* Note: when the source is a single cell, a single target merge is special */
3194 /* see clipboard.c (clipboard_paste_region) */
3195 GnmRange
const *merge
= gnm_sheet_merge_is_corner (pt
->sheet
, &r
->start
);
3196 if (merge
!= NULL
&& range_equal (r
, merge
)) {
3197 /* destination is a single merge */
3198 /* enlarge it such that the source fits */
3199 if (pt
->paste_flags
& PASTE_TRANSPOSE
) {
3200 if ((r
->end
.col
- r
->start
.col
+ 1) < cr
->rows
)
3201 r
->end
.col
= r
->start
.col
+ cr
->rows
- 1;
3202 if ((r
->end
.row
- r
->start
.row
+ 1) < cr
->cols
)
3203 r
->end
.row
= r
->start
.row
+ cr
->cols
- 1;
3205 if ((r
->end
.col
- r
->start
.col
+ 1) < cr
->cols
)
3206 r
->end
.col
= r
->start
.col
+ cr
->cols
- 1;
3207 if ((r
->end
.row
- r
->start
.row
+ 1) < cr
->rows
)
3208 r
->end
.row
= r
->start
.row
+ cr
->rows
- 1;
3214 if (n_c
* (gnm_float
)n_r
> 10000.) {
3215 char *number
= g_strdup_printf ("%0.0" GNM_FORMAT_f
,
3216 (gnm_float
)n_c
* (gnm_float
)n_r
);
3217 gboolean result
= go_gtk_query_yes_no (wbcg_toplevel (WBC_GTK (wbc
)), FALSE
,
3218 _("Do you really want to paste "
3219 "%s copies?"), number
);
3222 g_object_unref (me
);
3228 /* Use translate to do a quiet sanity check */
3229 if (range_translate (&me
->dst
.range
, pt
->sheet
, 0, 0)) {
3230 go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbc
),
3231 me
->cmd
.cmd_descriptor
,
3232 _("is beyond sheet boundaries"));
3233 g_object_unref (me
);
3237 /* no need to test if all we have are objects or are copying from */
3238 /*a single merge to a single merge*/
3239 if ((!me
->only_objects
) && (!me
->single_merge_to_single_merge
)&&
3240 sheet_range_splits_region (pt
->sheet
, &me
->dst
.range
,
3241 NULL
, GO_CMD_CONTEXT (wbc
), me
->cmd
.cmd_descriptor
)) {
3242 g_object_unref (me
);
3246 warn_if_date_trouble (wbc
, cr
);
3248 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
3251 /******************************************************************/
3253 #define CMD_AUTOFILL_TYPE (cmd_autofill_get_type ())
3254 #define CMD_AUTOFILL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_AUTOFILL_TYPE, CmdAutofill))
3259 GnmCellRegion
*contents
;
3262 int base_col
, base_row
, w
, h
, end_col
, end_row
;
3263 gboolean default_increment
;
3264 gboolean inverse_autofill
;
3265 ColRowIndexList
*columns
;
3266 ColRowStateGroup
*old_widths
;
3270 cmd_autofill_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
)
3272 CmdAutofill
const *orig
= (CmdAutofill
const *) cmd
;
3273 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
3274 GnmRange
const *r
= selection_first_range (sv
,
3275 GO_CMD_CONTEXT (wbc
), _("Autofill"));
3280 cmd_autofill (wbc
, sv_sheet (sv
), orig
->default_increment
,
3281 r
->start
.col
, r
->start
.row
, range_width (r
), range_height (r
),
3282 r
->start
.col
+ (orig
->end_col
- orig
->base_col
),
3283 r
->start
.row
+ (orig
->end_row
- orig
->base_row
),
3284 orig
->inverse_autofill
);
3286 MAKE_GNM_COMMAND (CmdAutofill
, cmd_autofill
, cmd_autofill_repeat
)
3289 cmd_autofill_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
3291 CmdAutofill
*me
= CMD_AUTOFILL (cmd
);
3294 g_return_val_if_fail (wbc
!= NULL
, TRUE
);
3295 g_return_val_if_fail (me
!= NULL
, TRUE
);
3296 g_return_val_if_fail (me
->contents
!= NULL
, TRUE
);
3298 res
= clipboard_paste_region (me
->contents
, &me
->dst
, GO_CMD_CONTEXT (wbc
));
3299 cellregion_unref (me
->contents
);
3300 me
->contents
= NULL
;
3302 if (me
->old_widths
) {
3303 colrow_restore_state_group (me
->cmd
.sheet
, TRUE
,
3306 colrow_state_group_destroy (me
->old_widths
);
3307 me
->old_widths
= NULL
;
3308 colrow_index_list_destroy (me
->columns
);
3315 select_range (me
->dst
.sheet
, &me
->src
, wbc
);
3321 cmd_autofill_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
3323 CmdAutofill
*me
= CMD_AUTOFILL (cmd
);
3326 g_return_val_if_fail (me
!= NULL
, TRUE
);
3327 g_return_val_if_fail (me
->contents
== NULL
, TRUE
);
3329 me
->contents
= clipboard_copy_range (me
->dst
.sheet
, &me
->dst
.range
);
3331 g_return_val_if_fail (me
->contents
!= NULL
, TRUE
);
3333 /* FIXME : when we split autofill to support hints and better validation
3334 * move this in there.
3336 /* MW: May 2006: we support hints now. What's this about? */
3337 sheet_clear_region (me
->dst
.sheet
,
3338 me
->dst
.range
.start
.col
, me
->dst
.range
.start
.row
,
3339 me
->dst
.range
.end
.col
, me
->dst
.range
.end
.row
,
3340 CLEAR_VALUES
| CLEAR_MERGES
| CLEAR_NOCHECKARRAY
| CLEAR_RECALC_DEPS
,
3341 GO_CMD_CONTEXT (wbc
));
3343 if (me
->cmd
.size
== 1)
3344 me
->cmd
.size
+= cellregion_cmd_size (me
->contents
);
3345 if (me
->inverse_autofill
)
3346 gnm_autofill_fill (me
->dst
.sheet
, me
->default_increment
,
3347 me
->end_col
, me
->end_row
, me
->w
, me
->h
,
3348 me
->base_col
, me
->base_row
);
3350 gnm_autofill_fill (me
->dst
.sheet
, me
->default_increment
,
3351 me
->base_col
, me
->base_row
, me
->w
, me
->h
,
3352 me
->end_col
, me
->end_row
);
3354 colrow_autofit (me
->cmd
.sheet
, &me
->dst
.range
, TRUE
, TRUE
,
3356 &me
->columns
, &me
->old_widths
);
3358 sheet_region_queue_recalc (me
->dst
.sheet
, &me
->dst
.range
);
3359 sheet_range_calc_spans (me
->dst
.sheet
, &me
->dst
.range
, GNM_SPANCALC_RENDER
);
3360 sheet_flag_status_update_range (me
->dst
.sheet
, &me
->dst
.range
);
3362 r
= range_union (&me
->dst
.range
, &me
->src
);
3363 select_range (me
->dst
.sheet
, &r
, wbc
);
3369 cmd_autofill_finalize (GObject
*cmd
)
3371 CmdAutofill
*me
= CMD_AUTOFILL (cmd
);
3374 cellregion_unref (me
->contents
);
3375 me
->contents
= NULL
;
3377 colrow_index_list_destroy (me
->columns
);
3378 colrow_state_group_destroy (me
->old_widths
);
3379 gnm_command_finalize (cmd
);
3383 cmd_autofill (WorkbookControl
*wbc
, Sheet
*sheet
,
3384 gboolean default_increment
,
3385 int base_col
, int base_row
,
3386 int w
, int h
, int end_col
, int end_row
,
3387 gboolean inverse_autofill
)
3390 GnmRange target
, src
;
3392 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
3394 /* This would be meaningless */
3395 if (base_col
+w
-1 == end_col
&& base_row
+h
-1 == end_row
)
3398 if (inverse_autofill
) {
3399 if (end_col
!= base_col
+ w
- 1) {
3400 range_init (&target
, base_col
, base_row
,
3401 end_col
- w
, end_row
);
3402 range_init (&src
, end_col
- w
+ 1, base_row
,
3405 range_init (&target
, base_col
, base_row
,
3406 end_col
, end_row
- h
);
3407 range_init (&src
, base_col
, end_row
- h
+ 1,
3411 if (end_col
!= base_col
+ w
- 1) {
3412 range_init (&target
, base_col
+ w
, base_row
,
3414 range_init (&src
, base_col
, base_row
,
3415 base_col
+ w
- 1, end_row
);
3417 range_init (&target
, base_col
, base_row
+ h
,
3419 range_init (&src
, base_col
, base_row
,
3420 end_col
, base_row
+ h
- 1);
3424 /* We don't support clearing regions, when a user uses the autofill
3425 * cursor to 'shrink' a selection
3427 if (target
.start
.col
> target
.end
.col
|| target
.start
.row
> target
.end
.row
)
3430 /* Check arrays or merged regions in src or target regions */
3431 if (sheet_range_splits_region (sheet
, &target
, NULL
, GO_CMD_CONTEXT (wbc
), _("Autofill")) ||
3432 sheet_range_splits_region (sheet
, &src
, NULL
, GO_CMD_CONTEXT (wbc
), _("Autofill")))
3435 me
= g_object_new (CMD_AUTOFILL_TYPE
, NULL
);
3437 me
->contents
= NULL
;
3438 me
->dst
.sheet
= sheet
;
3439 me
->dst
.paste_flags
= PASTE_CONTENTS
| PASTE_FORMATS
;
3440 me
->dst
.range
= target
;
3443 me
->base_col
= base_col
;
3444 me
->base_row
= base_row
,
3447 me
->end_col
= end_col
;
3448 me
->end_row
= end_row
;
3449 me
->default_increment
= default_increment
;
3450 me
->inverse_autofill
= inverse_autofill
;
3452 me
->cmd
.sheet
= sheet
;
3453 me
->cmd
.size
= 1; /* Changed in initial redo. */
3454 me
->cmd
.cmd_descriptor
= g_strdup_printf (_("Autofilling %s"),
3455 range_as_string (&me
->dst
.range
));
3457 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
3460 /******************************************************************/
3462 #define CMD_COPYREL_TYPE (cmd_copyrel_get_type ())
3463 #define CMD_COPYREL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_COPYREL_TYPE, CmdCopyRel))
3469 GnmPasteTarget dst
, src
;
3475 cmd_copyrel_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
)
3477 CmdCopyRel
const *orig
= (CmdCopyRel
const *) cmd
;
3478 cmd_copyrel (wbc
, orig
->dx
, orig
->dy
, orig
->name
);
3480 MAKE_GNM_COMMAND (CmdCopyRel
, cmd_copyrel
, cmd_copyrel_repeat
)
3483 cmd_copyrel_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
3485 CmdCopyRel
*me
= CMD_COPYREL (cmd
);
3487 g_return_val_if_fail (wbc
!= NULL
, TRUE
);
3488 g_return_val_if_fail (me
!= NULL
, TRUE
);
3489 g_return_val_if_fail (me
->undo
!= NULL
, TRUE
);
3491 go_undo_undo (me
->undo
);
3493 /* Select the newly pasted contents (this queues a redraw) */
3494 select_range (me
->dst
.sheet
, &me
->dst
.range
, wbc
);
3500 cmd_copyrel_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
3502 CmdCopyRel
*me
= CMD_COPYREL (cmd
);
3503 GnmCellRegion
*contents
;
3506 g_return_val_if_fail (me
!= NULL
, TRUE
);
3508 sheet_clear_region (me
->dst
.sheet
,
3509 me
->dst
.range
.start
.col
, me
->dst
.range
.start
.row
,
3510 me
->dst
.range
.end
.col
, me
->dst
.range
.end
.row
,
3511 CLEAR_VALUES
| CLEAR_MERGES
| CLEAR_NOCHECKARRAY
| CLEAR_RECALC_DEPS
,
3512 GO_CMD_CONTEXT (wbc
));
3514 contents
= clipboard_copy_range (me
->src
.sheet
, &me
->src
.range
);
3515 res
= clipboard_paste_region (contents
, &me
->dst
, GO_CMD_CONTEXT (wbc
));
3516 cellregion_unref (contents
);
3520 sheet_region_queue_recalc (me
->dst
.sheet
, &me
->dst
.range
);
3521 sheet_range_calc_spans (me
->dst
.sheet
, &me
->dst
.range
, GNM_SPANCALC_RENDER
);
3522 sheet_flag_status_update_range (me
->dst
.sheet
, &me
->dst
.range
);
3524 /* Select the newly pasted contents (this queues a redraw) */
3525 select_range (me
->dst
.sheet
, &me
->dst
.range
, wbc
);
3531 cmd_copyrel_finalize (GObject
*cmd
)
3533 CmdCopyRel
*me
= CMD_COPYREL (cmd
);
3536 g_object_unref (me
->undo
);
3538 gnm_command_finalize (cmd
);
3542 cmd_copyrel (WorkbookControl
*wbc
,
3547 GnmRange target
, src
;
3548 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
3549 Sheet
*sheet
= sv
->sheet
;
3550 GnmRange
const *selr
=
3551 selection_first_range (sv
, GO_CMD_CONTEXT (wbc
), name
);
3553 g_return_val_if_fail (dx
== 0 || dy
== 0, TRUE
);
3559 range_normalize (&target
);
3560 src
.start
= src
.end
= target
.start
;
3563 src
.end
.col
= target
.end
.col
;
3564 if (target
.start
.row
!= target
.end
.row
)
3567 src
.start
.row
= src
.end
.row
= (target
.start
.row
+ dy
);
3571 src
.end
.row
= target
.end
.row
;
3572 if (target
.start
.col
!= target
.end
.col
)
3575 src
.start
.col
= src
.end
.col
= (target
.start
.col
+ dx
);
3578 if (src
.start
.col
< 0 || src
.start
.col
>= gnm_sheet_get_max_cols (sheet
) ||
3579 src
.start
.row
< 0 || src
.start
.row
>= gnm_sheet_get_max_rows (sheet
))
3582 /* Check arrays or merged regions in src or target regions */
3583 if (sheet_range_splits_region (sheet
, &target
, NULL
, GO_CMD_CONTEXT (wbc
), name
) ||
3584 sheet_range_splits_region (sheet
, &src
, NULL
, GO_CMD_CONTEXT (wbc
), name
))
3587 me
= g_object_new (CMD_COPYREL_TYPE
, NULL
);
3589 me
->dst
.sheet
= sheet
;
3590 me
->dst
.paste_flags
= PASTE_CONTENTS
| PASTE_FORMATS
;
3591 me
->dst
.range
= target
;
3592 me
->src
.sheet
= sheet
;
3593 me
->src
.paste_flags
= PASTE_CONTENTS
| PASTE_FORMATS
;
3594 me
->src
.range
= src
;
3598 me
->undo
= clipboard_copy_range_undo (me
->dst
.sheet
, &me
->dst
.range
);
3600 me
->cmd
.sheet
= sheet
;
3602 me
->cmd
.cmd_descriptor
= g_strdup (name
);
3604 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
3607 /******************************************************************/
3610 #define CMD_AUTOFORMAT_TYPE (cmd_autoformat_get_type ())
3611 #define CMD_AUTOFORMAT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_AUTOFORMAT_TYPE, CmdAutoFormat))
3615 GnmStyleList
*styles
;
3616 } CmdAutoFormatOldStyle
;
3621 GSList
*selection
; /* Selections on the sheet */
3622 GSList
*old_styles
; /* Older styles, one style_list per selection range*/
3624 GnmFT
*ft
; /* Template that has been applied */
3628 cmd_autoformat_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
)
3630 CmdAutoFormat
const *orig
= (CmdAutoFormat
const *) cmd
;
3631 cmd_selection_autoformat (wbc
, gnm_ft_clone (orig
->ft
));
3633 MAKE_GNM_COMMAND (CmdAutoFormat
, cmd_autoformat
, cmd_autoformat_repeat
)
3636 cmd_autoformat_undo (GnmCommand
*cmd
,
3637 G_GNUC_UNUSED WorkbookControl
*wbc
)
3639 CmdAutoFormat
*me
= CMD_AUTOFORMAT (cmd
);
3641 g_return_val_if_fail (me
!= NULL
, TRUE
);
3643 if (me
->old_styles
) {
3644 GSList
*l1
= me
->old_styles
;
3645 GSList
*l2
= me
->selection
;
3647 for (; l1
; l1
= l1
->next
, l2
= l2
->next
) {
3649 CmdAutoFormatOldStyle
*os
= l1
->data
;
3650 GnmSpanCalcFlags flags
= sheet_style_set_list (me
->cmd
.sheet
,
3651 &os
->pos
, os
->styles
, NULL
, NULL
);
3653 g_return_val_if_fail (l2
&& l2
->data
, TRUE
);
3656 sheet_range_calc_spans (me
->cmd
.sheet
, r
, flags
);
3657 if (flags
!= GNM_SPANCALC_SIMPLE
)
3658 rows_height_update (me
->cmd
.sheet
, r
, TRUE
);
3666 cmd_autoformat_redo (GnmCommand
*cmd
,
3667 G_GNUC_UNUSED WorkbookControl
*wbc
)
3669 CmdAutoFormat
*me
= CMD_AUTOFORMAT (cmd
);
3671 g_return_val_if_fail (me
!= NULL
, TRUE
);
3673 gnm_ft_apply_to_sheet_regions (me
->ft
,
3674 me
->cmd
.sheet
, me
->selection
);
3680 cmd_autoformat_finalize (GObject
*cmd
)
3682 CmdAutoFormat
*me
= CMD_AUTOFORMAT (cmd
);
3684 if (me
->old_styles
!= NULL
) {
3687 for (l
= me
->old_styles
; l
!= NULL
; l
= g_slist_remove (l
, l
->data
)) {
3688 CmdAutoFormatOldStyle
*os
= l
->data
;
3691 style_list_free (os
->styles
);
3696 me
->old_styles
= NULL
;
3699 range_fragment_free (me
->selection
);
3700 me
->selection
= NULL
;
3702 gnm_ft_free (me
->ft
);
3704 gnm_command_finalize (cmd
);
3708 * cmd_selection_autoformat:
3709 * @wbc: the context.
3710 * @ft: The format template that was applied
3712 * Return value: TRUE if there was a problem
3715 cmd_selection_autoformat (WorkbookControl
*wbc
, GnmFT
*ft
)
3720 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
3722 me
= g_object_new (CMD_AUTOFORMAT_TYPE
, NULL
);
3724 me
->selection
= selection_get_ranges (sv
, FALSE
); /* Regions may overlap */
3726 me
->cmd
.sheet
= sv_sheet (sv
);
3727 me
->cmd
.size
= 1; /* FIXME? */
3729 if (!gnm_ft_check_valid (ft
, me
->selection
, GO_CMD_CONTEXT (wbc
))) {
3730 g_object_unref (me
);
3734 me
->old_styles
= NULL
;
3735 for (l
= me
->selection
; l
; l
= l
->next
) {
3736 CmdFormatOldStyle
*os
;
3737 GnmRange range
= *((GnmRange
const *) l
->data
);
3739 /* Store the containing range to handle borders */
3740 if (range
.start
.col
> 0) range
.start
.col
--;
3741 if (range
.start
.row
> 0) range
.start
.row
--;
3742 if (range
.end
.col
< gnm_sheet_get_last_col (sv
->sheet
)) range
.end
.col
++;
3743 if (range
.end
.row
< gnm_sheet_get_last_row (sv
->sheet
)) range
.end
.row
++;
3745 os
= g_new (CmdFormatOldStyle
, 1);
3747 os
->styles
= sheet_style_get_range (me
->cmd
.sheet
, &range
);
3748 os
->pos
= range
.start
;
3750 me
->old_styles
= g_slist_append (me
->old_styles
, os
);
3753 names
= undo_range_list_name (me
->cmd
.sheet
, me
->selection
);
3754 me
->cmd
.cmd_descriptor
= g_strdup_printf (_("Autoformatting %s"),
3758 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
3761 /******************************************************************/
3763 #define CMD_UNMERGE_CELLS_TYPE (cmd_unmerge_cells_get_type ())
3764 #define CMD_UNMERGE_CELLS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_UNMERGE_CELLS_TYPE, CmdUnmergeCells))
3770 GArray
*unmerged_regions
;
3775 cmd_unmerge_cells_repeat (G_GNUC_UNUSED GnmCommand
const *cmd
, WorkbookControl
*wbc
)
3777 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
3778 GSList
*range_list
= selection_get_ranges (sv
, FALSE
);
3779 cmd_unmerge_cells (wbc
, sv_sheet (sv
), range_list
);
3780 range_fragment_free (range_list
);
3782 MAKE_GNM_COMMAND (CmdUnmergeCells
, cmd_unmerge_cells
, cmd_unmerge_cells_repeat
)
3785 cmd_unmerge_cells_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
3787 CmdUnmergeCells
*me
= CMD_UNMERGE_CELLS (cmd
);
3790 g_return_val_if_fail (me
!= NULL
, TRUE
);
3791 g_return_val_if_fail (me
->unmerged_regions
!= NULL
, TRUE
);
3793 for (i
= 0 ; i
< me
->unmerged_regions
->len
; ++i
) {
3794 GnmRange
const *tmp
= &(g_array_index (me
->unmerged_regions
, GnmRange
, i
));
3795 sheet_redraw_range (me
->cmd
.sheet
, tmp
);
3796 gnm_sheet_merge_add (me
->cmd
.sheet
, tmp
, TRUE
, GO_CMD_CONTEXT (wbc
));
3797 sheet_range_calc_spans (me
->cmd
.sheet
, tmp
, GNM_SPANCALC_RE_RENDER
);
3800 g_array_free (me
->unmerged_regions
, TRUE
);
3801 me
->unmerged_regions
= NULL
;
3807 cmd_unmerge_cells_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
3809 CmdUnmergeCells
*me
= CMD_UNMERGE_CELLS (cmd
);
3812 g_return_val_if_fail (me
!= NULL
, TRUE
);
3813 g_return_val_if_fail (me
->unmerged_regions
== NULL
, TRUE
);
3815 me
->unmerged_regions
= g_array_new (FALSE
, FALSE
, sizeof (GnmRange
));
3816 for (i
= 0 ; i
< me
->ranges
->len
; ++i
) {
3817 GSList
*ptr
, *merged
= gnm_sheet_merge_get_overlap (me
->cmd
.sheet
,
3818 &(g_array_index (me
->ranges
, GnmRange
, i
)));
3819 for (ptr
= merged
; ptr
!= NULL
; ptr
= ptr
->next
) {
3820 GnmRange
const *pr
= ptr
->data
;
3821 GnmRange
const tmp
= *pr
;
3822 g_array_append_val (me
->unmerged_regions
, tmp
);
3823 gnm_sheet_merge_remove (me
->cmd
.sheet
, &tmp
);
3824 sheet_range_calc_spans (me
->cmd
.sheet
, &tmp
,
3825 GNM_SPANCALC_RE_RENDER
);
3827 g_slist_free (merged
);
3834 cmd_unmerge_cells_finalize (GObject
*cmd
)
3836 CmdUnmergeCells
*me
= CMD_UNMERGE_CELLS (cmd
);
3838 if (me
->unmerged_regions
!= NULL
) {
3839 g_array_free (me
->unmerged_regions
, TRUE
);
3840 me
->unmerged_regions
= NULL
;
3842 if (me
->ranges
!= NULL
) {
3843 g_array_free (me
->ranges
, TRUE
);
3847 gnm_command_finalize (cmd
);
3851 * cmd_unmerge_cells:
3852 * @wbc: the context.
3854 * @selection: (element-type GnmRange): selection.
3856 * Return value: TRUE if there was a problem
3859 cmd_unmerge_cells (WorkbookControl
*wbc
, Sheet
*sheet
, GSList
const *selection
)
3861 CmdUnmergeCells
*me
;
3864 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
3866 me
= g_object_new (CMD_UNMERGE_CELLS_TYPE
, NULL
);
3868 me
->cmd
.sheet
= sheet
;
3871 names
= undo_range_list_name (sheet
, selection
);
3872 me
->cmd
.cmd_descriptor
= g_strdup_printf (_("Unmerging %s"), names
);
3875 me
->unmerged_regions
= NULL
;
3876 me
->ranges
= g_array_new (FALSE
, FALSE
, sizeof (GnmRange
));
3877 for ( ; selection
!= NULL
; selection
= selection
->next
) {
3878 GSList
*merged
= gnm_sheet_merge_get_overlap (sheet
, selection
->data
);
3879 if (merged
!= NULL
) {
3880 g_array_append_val (me
->ranges
, *(GnmRange
*)selection
->data
);
3881 g_slist_free (merged
);
3885 if (me
->ranges
->len
<= 0) {
3886 g_object_unref (me
);
3890 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
3893 /******************************************************************/
3895 #define CMD_MERGE_CELLS_TYPE (cmd_merge_cells_get_type ())
3896 #define CMD_MERGE_CELLS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_MERGE_CELLS_TYPE, CmdMergeCells))
3901 GSList
*old_contents
;
3906 cmd_merge_cells_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
);
3908 MAKE_GNM_COMMAND (CmdMergeCells
, cmd_merge_cells
, cmd_merge_cells_repeat
)
3911 cmd_merge_cells_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
)
3913 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
3914 GSList
*range_list
= selection_get_ranges (sv
, FALSE
);
3915 cmd_merge_cells (wbc
, sv_sheet (sv
), range_list
,
3916 CMD_MERGE_CELLS (cmd
)->center
);
3917 range_fragment_free (range_list
);
3921 cmd_merge_cells_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
3923 CmdMergeCells
*me
= CMD_MERGE_CELLS (cmd
);
3926 g_return_val_if_fail (me
!= NULL
, TRUE
);
3928 for (i
= 0 ; i
< me
->ranges
->len
; ++i
) {
3929 GnmRange
const *r
= &(g_array_index (me
->ranges
, GnmRange
, i
));
3930 gnm_sheet_merge_remove (me
->cmd
.sheet
, r
);
3933 /* Avoid pasting comments that are at 0,0. Redo copies the target
3934 * region (including all comments) . If there was a comment in the top
3935 * left we would end up duplicating it. */
3936 flags
= PASTE_CONTENTS
| PASTE_FORMATS
| PASTE_COMMENTS
|
3937 PASTE_IGNORE_COMMENTS_AT_ORIGIN
;
3939 flags
|= PASTE_FORMATS
;
3940 for (i
= 0 ; i
< me
->ranges
->len
; ++i
) {
3941 GnmRange
const *r
= &(g_array_index (me
->ranges
, GnmRange
, i
));
3945 g_return_val_if_fail (me
->old_contents
!= NULL
, TRUE
);
3947 c
= me
->old_contents
->data
;
3948 clipboard_paste_region (c
,
3949 paste_target_init (&pt
, me
->cmd
.sheet
, r
, flags
),
3950 GO_CMD_CONTEXT (wbc
));
3951 cellregion_unref (c
);
3952 me
->old_contents
= g_slist_remove (me
->old_contents
, c
);
3954 g_return_val_if_fail (me
->old_contents
== NULL
, TRUE
);
3960 cmd_merge_cells_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
3962 CmdMergeCells
*me
= CMD_MERGE_CELLS (cmd
);
3963 GnmStyle
*align_center
= NULL
;
3967 g_return_val_if_fail (me
!= NULL
, TRUE
);
3970 align_center
= gnm_style_new ();
3971 gnm_style_set_align_h (align_center
, GNM_HALIGN_CENTER
);
3973 sheet
= me
->cmd
.sheet
;
3974 for (i
= 0 ; i
< me
->ranges
->len
; ++i
) {
3975 GnmRange
const *r
= &(g_array_index (me
->ranges
, GnmRange
, i
));
3976 GSList
*ptr
, *merged
= gnm_sheet_merge_get_overlap (sheet
, r
);
3978 /* save contents before removing contained merged regions */
3979 me
->old_contents
= g_slist_prepend (me
->old_contents
,
3980 clipboard_copy_range (sheet
, r
));
3981 for (ptr
= merged
; ptr
!= NULL
; ptr
= ptr
->next
)
3982 gnm_sheet_merge_remove (sheet
, ptr
->data
);
3983 g_slist_free (merged
);
3985 gnm_sheet_merge_add (sheet
, r
, TRUE
, GO_CMD_CONTEXT (wbc
));
3987 sheet_apply_style (me
->cmd
.sheet
, r
, align_center
);
3991 gnm_style_unref (align_center
);
3992 me
->old_contents
= g_slist_reverse (me
->old_contents
);
3997 cmd_merge_cells_finalize (GObject
*cmd
)
3999 CmdMergeCells
*me
= CMD_MERGE_CELLS (cmd
);
4001 if (me
->old_contents
!= NULL
) {
4003 for (l
= me
->old_contents
; l
!= NULL
; l
= g_slist_remove (l
, l
->data
))
4004 cellregion_unref (l
->data
);
4005 me
->old_contents
= NULL
;
4008 if (me
->ranges
!= NULL
) {
4009 g_array_free (me
->ranges
, TRUE
);
4013 gnm_command_finalize (cmd
);
4018 * @wbc: the context.
4020 * @selection: (element-type GnmRange): selection.
4023 * Return value: %TRUE if there was a problem
4026 cmd_merge_cells (WorkbookControl
*wbc
, Sheet
*sheet
, GSList
const *selection
,
4032 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
4034 me
= g_object_new (CMD_MERGE_CELLS_TYPE
, NULL
);
4036 me
->cmd
.sheet
= sheet
;
4039 names
= undo_range_list_name (sheet
, selection
);
4040 me
->cmd
.cmd_descriptor
=
4041 g_strdup_printf ((center
? _("Merge and Center %s") :_("Merging %s")), names
);
4044 me
->center
= center
;
4045 me
->ranges
= g_array_new (FALSE
, FALSE
, sizeof (GnmRange
));
4046 for ( ; selection
!= NULL
; selection
= selection
->next
) {
4047 GnmRange
const *exist
;
4048 GnmRange
const *r
= selection
->data
;
4049 if (range_is_singleton (selection
->data
))
4051 if (NULL
!= (exist
= gnm_sheet_merge_is_corner (sheet
, &r
->start
)) &&
4052 range_equal (r
, exist
))
4054 g_array_append_val (me
->ranges
, *(GnmRange
*)selection
->data
);
4057 if (me
->ranges
->len
<= 0) {
4058 g_object_unref (me
);
4062 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
4065 /******************************************************************/
4067 #define CMD_SEARCH_REPLACE_TYPE (cmd_search_replace_get_type())
4068 #define CMD_SEARCH_REPLACE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SEARCH_REPLACE_TYPE, CmdSearchReplace))
4072 GnmSearchReplace
*sr
;
4075 * Undo/redo use this list of SearchReplaceItems to do their
4076 * work. Note, that it is possible for a cell to occur
4077 * multiple times in the list.
4082 MAKE_GNM_COMMAND (CmdSearchReplace
, cmd_search_replace
, NULL
)
4084 typedef enum { SRI_text
, SRI_comment
} SearchReplaceItemType
;
4088 SearchReplaceItemType old_type
, new_type
;
4093 } SearchReplaceItem
;
4097 cmd_search_replace_update_after_action (CmdSearchReplace
*me
,
4098 WorkbookControl
*wbc
)
4101 Sheet
*last_sheet
= NULL
;
4103 for (tmp
= me
->cells
; tmp
; tmp
= tmp
->next
) {
4104 SearchReplaceItem
*sri
= tmp
->data
;
4105 if (sri
->pos
.sheet
!= last_sheet
) {
4106 last_sheet
= sri
->pos
.sheet
;
4107 update_after_action (last_sheet
, wbc
);
4114 cmd_search_replace_undo (GnmCommand
*cmd
,
4115 WorkbookControl
*wbc
)
4117 CmdSearchReplace
*me
= CMD_SEARCH_REPLACE (cmd
);
4120 /* Undo does replacements backwards. */
4121 for (tmp
= g_list_last (me
->cells
); tmp
; tmp
= tmp
->prev
) {
4122 SearchReplaceItem
*sri
= tmp
->data
;
4123 switch (sri
->old_type
) {
4126 GnmCell
*cell
= sheet_cell_get (sri
->pos
.sheet
,
4129 sheet_cell_set_text (cell
, sri
->old
.text
, NULL
);
4134 GnmComment
*comment
=
4135 sheet_get_comment (sri
->pos
.sheet
,
4138 cell_comment_text_set (comment
, sri
->old
.comment
);
4140 g_warning ("Undo/redo broken.");
4146 cmd_search_replace_update_after_action (me
, wbc
);
4152 cmd_search_replace_redo (GnmCommand
*cmd
,
4153 WorkbookControl
*wbc
)
4155 CmdSearchReplace
*me
= CMD_SEARCH_REPLACE (cmd
);
4158 /* Redo does replacements forward. */
4159 for (tmp
= me
->cells
; tmp
; tmp
= tmp
->next
) {
4160 SearchReplaceItem
*sri
= tmp
->data
;
4161 switch (sri
->new_type
) {
4164 GnmCell
*cell
= sheet_cell_get (sri
->pos
.sheet
,
4167 sheet_cell_set_text (cell
, sri
->new.text
, NULL
);
4172 GnmComment
*comment
=
4173 sheet_get_comment (sri
->pos
.sheet
,
4176 cell_comment_text_set (comment
, sri
->new.comment
);
4178 g_warning ("Undo/redo broken.");
4184 cmd_search_replace_update_after_action (me
, wbc
);
4190 cmd_search_replace_do_cell (CmdSearchReplace
*me
, GnmEvalPos
*ep
,
4193 GnmSearchReplace
*sr
= me
->sr
;
4195 GnmSearchReplaceCellResult cell_res
;
4196 GnmSearchReplaceCommentResult comment_res
;
4198 if (gnm_search_replace_cell (sr
, ep
, TRUE
, &cell_res
)) {
4199 GnmExprTop
const *texpr
;
4204 parse_pos_init_evalpos (&pp
, ep
);
4205 parse_text_value_or_expr (&pp
, cell_res
.new_text
, &val
, &texpr
);
4208 * FIXME: this is a hack, but parse_text_value_or_expr
4209 * does not have a better way of signaling an error.
4212 gnm_expr_char_start_p (cell_res
.new_text
) &&
4213 !go_format_is_text (gnm_cell_get_format (cell_res
.cell
)));
4214 value_release (val
);
4215 if (texpr
) gnm_expr_top_unref (texpr
);
4219 gnm_search_replace_query_fail (sr
, &cell_res
);
4220 g_free (cell_res
.old_text
);
4221 g_free (cell_res
.new_text
);
4224 switch (sr
->error_behaviour
) {
4225 case GNM_SRE_ERROR
: {
4226 GnmExprTop
const *ee
=
4228 (gnm_expr_new_funcall1
4229 (gnm_func_lookup ("ERROR", NULL
),
4230 gnm_expr_new_constant
4231 (value_new_string_nocopy (cell_res
.new_text
))));
4232 GnmConventionsOut out
;
4234 out
.accum
= g_string_new ("=");
4236 out
.convs
= pp
.sheet
->convs
;
4237 gnm_expr_top_as_gstring (ee
, &out
);
4238 gnm_expr_top_unref (ee
);
4239 cell_res
.new_text
= g_string_free (out
.accum
, FALSE
);
4243 case GNM_SRE_STRING
: {
4244 GString
*s
= g_string_new ("'");
4245 g_string_append (s
, cell_res
.new_text
);
4246 g_free (cell_res
.new_text
);
4247 cell_res
.new_text
= g_string_free (s
, FALSE
);
4252 g_assert_not_reached ();
4260 if (!err
&& !test_run
) {
4261 int res
= gnm_search_replace_query_cell
4263 gboolean doit
= (res
== GTK_RESPONSE_YES
);
4265 if (res
== GTK_RESPONSE_CANCEL
) {
4266 g_free (cell_res
.old_text
);
4267 g_free (cell_res
.new_text
);
4272 SearchReplaceItem
*sri
= g_new (SearchReplaceItem
, 1);
4274 sheet_cell_set_text (cell_res
.cell
, cell_res
.new_text
, NULL
);
4277 sri
->old_type
= sri
->new_type
= SRI_text
;
4278 sri
->old
.text
= cell_res
.old_text
;
4279 sri
->new.text
= cell_res
.new_text
;
4280 me
->cells
= g_list_prepend (me
->cells
, sri
);
4282 cell_res
.old_text
= cell_res
.new_text
= NULL
;
4286 g_free (cell_res
.new_text
);
4287 g_free (cell_res
.old_text
);
4291 gnm_search_replace_comment (sr
, ep
, TRUE
, &comment_res
)) {
4292 int res
= gnm_search_replace_query_comment
4293 (sr
, ep
, &comment_res
);
4294 gboolean doit
= (res
== GTK_RESPONSE_YES
);
4297 SearchReplaceItem
*sri
= g_new (SearchReplaceItem
, 1);
4299 sri
->old_type
= sri
->new_type
= SRI_comment
;
4300 sri
->old
.comment
= g_strdup (comment_res
.old_text
);
4301 sri
->new.comment
= comment_res
.new_text
;
4302 me
->cells
= g_list_prepend (me
->cells
, sri
);
4304 cell_comment_text_set (comment_res
.comment
, comment_res
.new_text
);
4306 g_free (comment_res
.new_text
);
4307 if (res
== GTK_RESPONSE_CANCEL
)
4317 cmd_search_replace_do (CmdSearchReplace
*me
, gboolean test_run
,
4318 WorkbookControl
*wbc
)
4320 GnmSearchReplace
*sr
= me
->sr
;
4322 gboolean result
= FALSE
;
4326 switch (sr
->error_behaviour
) {
4330 case GNM_SRE_STRING
:
4331 /* An error is not a problem. */
4339 cells
= gnm_search_collect_cells (sr
);
4341 for (i
= 0; i
< cells
->len
; i
++) {
4342 GnmEvalPos
*ep
= g_ptr_array_index (cells
, i
);
4344 if (cmd_search_replace_do_cell (me
, ep
, test_run
)) {
4350 gnm_search_collect_cells_free (cells
);
4353 /* Cells were added in the wrong order. Correct. */
4354 me
->cells
= g_list_reverse (me
->cells
);
4356 cmd_search_replace_update_after_action (me
, wbc
);
4364 cmd_search_replace_finalize (GObject
*cmd
)
4366 CmdSearchReplace
*me
= CMD_SEARCH_REPLACE (cmd
);
4369 for (tmp
= me
->cells
; tmp
; tmp
= tmp
->next
) {
4370 SearchReplaceItem
*sri
= tmp
->data
;
4371 switch (sri
->old_type
) {
4373 g_free (sri
->old
.text
);
4376 g_free (sri
->old
.comment
);
4379 switch (sri
->new_type
) {
4381 g_free (sri
->new.text
);
4384 g_free (sri
->new.comment
);
4389 g_list_free (me
->cells
);
4390 g_object_unref (me
->sr
);
4392 gnm_command_finalize (cmd
);
4396 cmd_search_replace (WorkbookControl
*wbc
, GnmSearchReplace
*sr
)
4398 CmdSearchReplace
*me
;
4400 g_return_val_if_fail (sr
!= NULL
, TRUE
);
4402 me
= g_object_new (CMD_SEARCH_REPLACE_TYPE
, NULL
);
4405 me
->sr
= g_object_ref (sr
);
4407 me
->cmd
.sheet
= NULL
;
4408 me
->cmd
.size
= 1; /* Corrected below. */
4409 me
->cmd
.cmd_descriptor
= g_strdup (_("Search and Replace"));
4411 if (cmd_search_replace_do (me
, TRUE
, wbc
)) {
4412 /* There was an error and nothing was done. */
4413 g_object_unref (me
);
4417 cmd_search_replace_do (me
, FALSE
, wbc
);
4418 me
->cmd
.size
+= g_list_length (me
->cells
);
4420 command_register_undo (wbc
, G_OBJECT (me
));
4424 /******************************************************************/
4426 #define CMD_COLROW_STD_SIZE_TYPE (cmd_colrow_std_size_get_type ())
4427 #define CMD_COLROW_STD_SIZE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_COLROW_STD_SIZE_TYPE, CmdColRowStdSize))
4438 MAKE_GNM_COMMAND (CmdColRowStdSize
, cmd_colrow_std_size
, NULL
)
4441 cmd_colrow_std_size_undo (GnmCommand
*cmd
,
4442 G_GNUC_UNUSED WorkbookControl
*wbc
)
4444 CmdColRowStdSize
*me
= CMD_COLROW_STD_SIZE (cmd
);
4446 g_return_val_if_fail (me
!= NULL
, TRUE
);
4447 g_return_val_if_fail (me
->old_default
!= 0, TRUE
);
4450 sheet_col_set_default_size_pts (me
->sheet
, me
->old_default
);
4452 sheet_row_set_default_size_pts (me
->sheet
, me
->old_default
);
4454 me
->old_default
= 0;
4460 cmd_colrow_std_size_redo (GnmCommand
*cmd
,
4461 G_GNUC_UNUSED WorkbookControl
*wbc
)
4463 CmdColRowStdSize
*me
= CMD_COLROW_STD_SIZE (cmd
);
4465 g_return_val_if_fail (me
!= NULL
, TRUE
);
4466 g_return_val_if_fail (me
->old_default
== 0, TRUE
);
4469 me
->old_default
= sheet_col_get_default_size_pts (me
->sheet
);
4470 sheet_col_set_default_size_pts (me
->sheet
, me
->new_default
);
4472 me
->old_default
= sheet_row_get_default_size_pts (me
->sheet
);
4473 sheet_row_set_default_size_pts (me
->sheet
, me
->new_default
);
4479 cmd_colrow_std_size_finalize (GObject
*cmd
)
4481 gnm_command_finalize (cmd
);
4485 cmd_colrow_std_size (WorkbookControl
*wbc
, Sheet
*sheet
,
4486 gboolean is_cols
, double new_default
)
4488 CmdColRowStdSize
*me
;
4490 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
4492 me
= g_object_new (CMD_COLROW_STD_SIZE_TYPE
, NULL
);
4495 me
->is_cols
= is_cols
;
4496 me
->new_default
= new_default
;
4497 me
->old_default
= 0;
4499 me
->cmd
.sheet
= sheet
;
4500 me
->cmd
.size
= 1; /* Changed in initial redo. */
4501 me
->cmd
.cmd_descriptor
= is_cols
4502 ? g_strdup_printf (_("Setting default width of columns to %.2fpts"), new_default
)
4503 : g_strdup_printf (_("Setting default height of rows to %.2fpts"), new_default
);
4505 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
4508 /******************************************************************/
4510 #define CMD_ZOOM_TYPE (cmd_zoom_get_type ())
4511 #define CMD_ZOOM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_ZOOM_TYPE, CmdZoom))
4518 double *old_factors
;
4521 MAKE_GNM_COMMAND (CmdZoom
, cmd_zoom
, NULL
)
4524 cmd_zoom_undo (GnmCommand
*cmd
,
4525 G_GNUC_UNUSED WorkbookControl
*wbc
)
4527 CmdZoom
*me
= CMD_ZOOM (cmd
);
4531 g_return_val_if_fail (me
!= NULL
, TRUE
);
4532 g_return_val_if_fail (me
->sheets
!= NULL
, TRUE
);
4533 g_return_val_if_fail (me
->old_factors
!= NULL
, TRUE
);
4535 for (i
= 0, l
= me
->sheets
; l
!= NULL
; l
= l
->next
, i
++) {
4536 Sheet
*sheet
= l
->data
;
4537 g_object_set (sheet
, "zoom-factor", me
->old_factors
[i
], NULL
);
4544 cmd_zoom_redo (GnmCommand
*cmd
,
4545 G_GNUC_UNUSED WorkbookControl
*wbc
)
4547 CmdZoom
*me
= CMD_ZOOM (cmd
);
4550 g_return_val_if_fail (me
!= NULL
, TRUE
);
4551 g_return_val_if_fail (me
->sheets
!= NULL
, TRUE
);
4553 for (l
= me
->sheets
; l
!= NULL
; l
= l
->next
) {
4554 Sheet
*sheet
= l
->data
;
4555 g_object_set (sheet
, "zoom-factor", me
->new_factor
, NULL
);
4562 cmd_zoom_finalize (GObject
*cmd
)
4564 CmdZoom
*me
= CMD_ZOOM (cmd
);
4566 g_slist_free (me
->sheets
);
4567 g_free (me
->old_factors
);
4569 gnm_command_finalize (cmd
);
4574 * @wbc: #WorkbookControl
4575 * @sheets: (element-type Sheet) (transfer container):
4580 cmd_zoom (WorkbookControl
*wbc
, GSList
*sheets
, double factor
)
4587 g_return_val_if_fail (wbc
!= NULL
, TRUE
);
4588 g_return_val_if_fail (sheets
!= NULL
, TRUE
);
4590 me
= g_object_new (CMD_ZOOM_TYPE
, NULL
);
4592 me
->sheets
= sheets
;
4593 me
->old_factors
= g_new0 (double, g_slist_length (sheets
));
4594 me
->new_factor
= factor
;
4596 /* Make a list of all sheets to zoom and save zoom factor for each */
4597 namelist
= g_string_new (NULL
);
4598 for (i
= 0, l
= me
->sheets
; l
!= NULL
; l
= l
->next
, i
++) {
4599 Sheet
*sheet
= l
->data
;
4601 g_string_append (namelist
, sheet
->name_unquoted
);
4602 me
->old_factors
[i
] = sheet
->last_zoom_factor_used
;
4605 g_string_append (namelist
, ", ");
4608 /* Make sure the string doesn't get overly wide */
4609 gnm_cmd_trunc_descriptor (namelist
, NULL
);
4611 me
->cmd
.sheet
= NULL
;
4613 me
->cmd
.cmd_descriptor
=
4614 g_strdup_printf (_("Zoom %s to %.0f%%"), namelist
->str
, factor
* 100);
4616 g_string_free (namelist
, TRUE
);
4618 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
4621 /******************************************************************/
4623 #define CMD_OBJECTS_DELETE_TYPE (cmd_objects_delete_get_type ())
4624 #define CMD_OBJECTS_DELETE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_OBJECTS_DELETE_TYPE, CmdObjectsDelete))
4632 MAKE_GNM_COMMAND (CmdObjectsDelete
, cmd_objects_delete
, NULL
)
4635 cmd_objects_delete_redo (GnmCommand
*cmd
,
4636 G_GNUC_UNUSED WorkbookControl
*wbc
)
4638 CmdObjectsDelete
*me
= CMD_OBJECTS_DELETE (cmd
);
4639 g_slist_foreach (me
->objects
, (GFunc
) sheet_object_clear_sheet
, NULL
);
4644 cmd_objects_restore_location (SheetObject
*so
, gint location
)
4646 gint loc
= sheet_object_get_stacking (so
);
4647 if (loc
!= location
)
4648 sheet_object_adjust_stacking(so
, location
- loc
);
4652 cmd_objects_delete_undo (GnmCommand
*cmd
,
4653 G_GNUC_UNUSED WorkbookControl
*wbc
)
4655 CmdObjectsDelete
*me
= CMD_OBJECTS_DELETE (cmd
);
4659 g_slist_foreach (me
->objects
,
4660 (GFunc
) sheet_object_set_sheet
, me
->cmd
.sheet
);
4662 for (l
= me
->objects
, i
= 0; l
; l
= l
->next
, i
++)
4663 cmd_objects_restore_location (GNM_SO (l
->data
),
4664 g_array_index(me
->location
,
4670 cmd_objects_delete_finalize (GObject
*cmd
)
4672 CmdObjectsDelete
*me
= CMD_OBJECTS_DELETE (cmd
);
4673 g_slist_free_full (me
->objects
, g_object_unref
);
4675 g_array_free (me
->location
, TRUE
);
4676 me
->location
= NULL
;
4678 gnm_command_finalize (cmd
);
4682 cmd_objects_store_location (SheetObject
*so
, GArray
*location
)
4684 gint loc
= sheet_object_get_stacking (so
);
4685 g_array_append_val (location
, loc
);
4689 * cmd_objects_delete:
4690 * @wbc: #WorkbookControl
4691 * @objects: (element-type SheetObject) (transfer container): the objects to
4695 * Absorbs the list, adding references to the contents.
4698 cmd_objects_delete (WorkbookControl
*wbc
, GSList
*objects
,
4701 CmdObjectsDelete
*me
;
4703 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
4704 g_return_val_if_fail (objects
!= NULL
, TRUE
);
4706 me
= g_object_new (CMD_OBJECTS_DELETE_TYPE
, NULL
);
4708 me
->objects
= objects
;
4709 g_slist_foreach (me
->objects
, (GFunc
) g_object_ref
, NULL
);
4711 me
->location
= g_array_new (FALSE
, FALSE
, sizeof (gint
));
4712 g_slist_foreach (me
->objects
, (GFunc
) cmd_objects_store_location
,
4715 me
->cmd
.sheet
= sheet_object_get_sheet (objects
->data
);
4717 me
->cmd
.cmd_descriptor
= g_strdup (name
? name
: _("Delete Object"));
4719 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
4722 /******************************************************************/
4726 * @wbc: #WorkbookControl
4727 * @objects: (element-type SheetObject) (transfer container): the objects to move.
4728 * @anchors: (element-type SheetObjectAnchor) (transfer full): the anchors for the objects.
4734 cmd_objects_move (WorkbookControl
*wbc
, GSList
*objects
, GSList
*anchors
,
4735 gboolean objects_created
, char const *name
)
4737 GOUndo
*undo
= NULL
;
4738 GOUndo
*redo
= NULL
;
4739 gboolean result
= TRUE
;
4741 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
4743 undo
= sheet_object_move_undo (objects
, objects_created
);
4744 redo
= sheet_object_move_do (objects
, anchors
, objects_created
);
4746 result
= cmd_generic (wbc
, name
, undo
, redo
);
4748 g_slist_free (objects
);
4749 g_slist_free_full (anchors
, g_free
);
4754 /******************************************************************/
4756 #define CMD_REORGANIZE_SHEETS_TYPE (cmd_reorganize_sheets_get_type ())
4757 #define CMD_REORGANIZE_SHEETS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_REORGANIZE_SHEETS_TYPE, CmdReorganizeSheets))
4762 WorkbookSheetState
*old
;
4763 WorkbookSheetState
*new;
4767 } CmdReorganizeSheets
;
4769 MAKE_GNM_COMMAND (CmdReorganizeSheets
, cmd_reorganize_sheets
, NULL
)
4772 cmd_reorganize_sheets_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
4774 CmdReorganizeSheets
*me
= CMD_REORGANIZE_SHEETS (cmd
);
4775 workbook_sheet_state_restore (me
->wb
, me
->old
);
4776 if (me
->undo_sheet
) {
4777 WORKBOOK_VIEW_FOREACH_CONTROL (wb_control_view (wbc
), control
,
4778 wb_control_sheet_focus (control
, me
->undo_sheet
););
4784 cmd_reorganize_sheets_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
4786 CmdReorganizeSheets
*me
= CMD_REORGANIZE_SHEETS (cmd
);
4791 workbook_sheet_state_restore (me
->wb
, me
->new);
4792 if (me
->redo_sheet
) {
4793 WORKBOOK_VIEW_FOREACH_CONTROL (wb_control_view (wbc
), control
,
4794 wb_control_sheet_focus (control
, me
->redo_sheet
););
4802 cmd_reorganize_sheets_finalize (GObject
*cmd
)
4804 CmdReorganizeSheets
*me
= CMD_REORGANIZE_SHEETS (cmd
);
4807 workbook_sheet_state_free (me
->old
);
4809 workbook_sheet_state_free (me
->new);
4811 gnm_command_finalize (cmd
);
4815 cmd_reorganize_sheets (WorkbookControl
*wbc
,
4816 WorkbookSheetState
*old_state
,
4819 CmdReorganizeSheets
*me
;
4820 Workbook
*wb
= wb_control_get_workbook (wbc
);
4822 me
= g_object_new (CMD_REORGANIZE_SHEETS_TYPE
, NULL
);
4824 me
->old
= old_state
;
4825 me
->new = workbook_sheet_state_new (me
->wb
);
4827 me
->undo_sheet
= undo_sheet
;
4828 me
->redo_sheet
= wb_control_cur_sheet (wbc
);
4830 me
->cmd
.sheet
= NULL
;
4831 me
->cmd
.size
= workbook_sheet_state_size (me
->old
) +
4832 workbook_sheet_state_size (me
->new);
4833 me
->cmd
.cmd_descriptor
=
4834 workbook_sheet_state_diff (me
->old
, me
->new);
4836 if (me
->cmd
.cmd_descriptor
)
4837 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
4840 g_object_unref (me
);
4844 /******************************************************************/
4847 cmd_rename_sheet (WorkbookControl
*wbc
,
4849 char const *new_name
)
4851 WorkbookSheetState
*old_state
;
4854 g_return_val_if_fail (new_name
!= NULL
, TRUE
);
4855 g_return_val_if_fail (sheet
!= NULL
, TRUE
);
4857 if (*new_name
== 0) {
4858 go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbc
), _("Name"), _("Sheet names must be non-empty."));
4862 collision
= workbook_sheet_by_name (sheet
->workbook
, new_name
);
4863 if (collision
&& collision
!= sheet
) {
4864 GError
*err
= g_error_new (go_error_invalid(), 0,
4865 _("A workbook cannot have two sheets with the same name."));
4866 go_cmd_context_error (GO_CMD_CONTEXT (wbc
), err
);
4871 old_state
= workbook_sheet_state_new (sheet
->workbook
);
4872 g_object_set (sheet
, "name", new_name
, NULL
);
4873 return cmd_reorganize_sheets (wbc
, old_state
, sheet
);
4876 /******************************************************************/
4878 #define CMD_RESIZE_SHEETS_TYPE (cmd_resize_sheets_get_type ())
4879 #define CMD_RESIZE_SHEETS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_RESIZE_SHEETS_TYPE, CmdResizeSheets))
4888 MAKE_GNM_COMMAND (CmdResizeSheets
, cmd_resize_sheets
, NULL
)
4891 cmd_resize_sheets_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
4893 CmdResizeSheets
*me
= CMD_RESIZE_SHEETS (cmd
);
4894 GOCmdContext
*cc
= GO_CMD_CONTEXT (wbc
);
4896 go_undo_undo_with_data (me
->undo
, cc
);
4897 g_object_unref (me
->undo
);
4904 cmd_resize_sheets_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
4906 CmdResizeSheets
*me
= CMD_RESIZE_SHEETS (cmd
);
4907 GOCmdContext
*cc
= GO_CMD_CONTEXT (wbc
);
4910 for (l
= me
->sheets
; l
; l
= l
->next
) {
4911 Sheet
*sheet
= l
->data
;
4913 GOUndo
*u
= gnm_sheet_resize (sheet
, me
->cols
, me
->rows
,
4915 me
->undo
= go_undo_combine (me
->undo
, u
);
4919 go_undo_undo_with_data (me
->undo
, cc
);
4928 cmd_resize_sheets_finalize (GObject
*cmd
)
4930 CmdResizeSheets
*me
= CMD_RESIZE_SHEETS (cmd
);
4932 g_slist_free (me
->sheets
);
4934 g_object_unref (me
->undo
);
4938 gnm_command_finalize (cmd
);
4942 * cmd_resize_sheets:
4943 * @wbc: #WorkbookControl
4944 * @sheets: (element-type Sheet) (transfer container): the sheets to resize.
4945 * @cols: new columns number.
4946 * @rows: new rows number.
4950 cmd_resize_sheets (WorkbookControl
*wbc
,
4954 CmdResizeSheets
*me
;
4956 me
= g_object_new (CMD_RESIZE_SHEETS_TYPE
, NULL
);
4957 me
->sheets
= sheets
;
4960 me
->cmd
.sheet
= sheets
? sheets
->data
: NULL
;
4962 me
->cmd
.cmd_descriptor
= g_strdup (_("Resizing sheet"));
4965 gnm_sheet_valid_size (cols
, rows
))
4966 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
4969 g_object_unref (me
);
4973 /******************************************************************/
4975 #define CMD_SET_COMMENT_TYPE (cmd_set_comment_get_type ())
4976 #define CMD_SET_COMMENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SET_COMMENT_TYPE, CmdSetComment))
4987 PangoAttrList
*old_attributes
;
4988 PangoAttrList
*new_attributes
;
4991 MAKE_GNM_COMMAND (CmdSetComment
, cmd_set_comment
, NULL
)
4994 cmd_set_comment_apply (Sheet
*sheet
, GnmCellPos
*pos
,
4995 char const *text
, PangoAttrList
*attributes
,
4998 GnmComment
*comment
;
4999 Workbook
*wb
= sheet
->workbook
;
5001 comment
= sheet_get_comment (sheet
, pos
);
5004 g_object_set (G_OBJECT (comment
), "text", text
,
5006 "markup", attributes
, NULL
);
5010 mr
= gnm_sheet_merge_contains_pos (sheet
, pos
);
5013 sheet_objects_clear (sheet
, mr
, GNM_CELL_COMMENT_TYPE
, NULL
);
5016 r
.start
= r
.end
= *pos
;
5017 sheet_objects_clear (sheet
, &r
, GNM_CELL_COMMENT_TYPE
, NULL
);
5020 } else if (text
&& (strlen (text
) > 0)) {
5021 cell_set_comment (sheet
, pos
, author
, text
, attributes
);
5023 sheet_mark_dirty (sheet
);
5025 WORKBOOK_FOREACH_CONTROL (wb
, view
, ctl
,
5026 wb_control_menu_state_update (ctl
, MS_COMMENT_LINKS
););
5032 cmd_set_comment_undo (GnmCommand
*cmd
,
5033 G_GNUC_UNUSED WorkbookControl
*wbc
)
5035 CmdSetComment
*me
= CMD_SET_COMMENT (cmd
);
5037 return cmd_set_comment_apply (me
->sheet
, &me
->pos
,
5038 me
->old_text
, me
->old_attributes
,
5043 cmd_set_comment_redo (GnmCommand
*cmd
,
5044 G_GNUC_UNUSED WorkbookControl
*wbc
)
5046 CmdSetComment
*me
= CMD_SET_COMMENT (cmd
);
5048 return cmd_set_comment_apply (me
->sheet
, &me
->pos
,
5049 me
->new_text
, me
->new_attributes
,
5054 cmd_set_comment_finalize (GObject
*cmd
)
5056 CmdSetComment
*me
= CMD_SET_COMMENT (cmd
);
5058 g_free (me
->new_text
);
5059 me
->new_text
= NULL
;
5061 g_free (me
->old_text
);
5062 me
->old_text
= NULL
;
5064 g_free (me
->new_author
);
5065 me
->new_author
= NULL
;
5067 g_free (me
->old_author
);
5068 me
->old_author
= NULL
;
5070 if (me
->old_attributes
!= NULL
) {
5071 pango_attr_list_unref (me
->old_attributes
);
5072 me
->old_attributes
= NULL
;
5075 if (me
->new_attributes
!= NULL
) {
5076 pango_attr_list_unref (me
->new_attributes
);
5077 me
->new_attributes
= NULL
;
5080 gnm_command_finalize (cmd
);
5084 cmd_set_comment (WorkbookControl
*wbc
,
5085 Sheet
*sheet
, GnmCellPos
const *pos
,
5086 char const *new_text
,
5087 PangoAttrList
*attr
,
5088 char const *new_author
)
5091 GnmComment
*comment
;
5094 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
5095 g_return_val_if_fail (new_text
!= NULL
, TRUE
);
5097 me
= g_object_new (CMD_SET_COMMENT_TYPE
, NULL
);
5099 me
->cmd
.sheet
= sheet
;
5101 if (strlen (new_text
) < 1)
5102 me
->new_text
= NULL
;
5104 me
->new_text
= g_strdup (new_text
);
5105 if (strlen (new_author
) < 1)
5106 me
->new_author
= NULL
;
5108 me
->new_author
= g_strdup (new_author
);
5110 pango_attr_list_ref (attr
);
5111 me
->new_attributes
= attr
;
5112 where
= undo_cell_pos_name (sheet
, pos
);
5113 me
->cmd
.cmd_descriptor
=
5114 g_strdup_printf (me
->new_text
== NULL
?
5115 _("Clearing comment of %s") :
5116 _("Setting comment of %s"),
5119 me
->old_text
= NULL
;
5120 me
->old_author
= NULL
;
5121 me
->old_attributes
= NULL
;
5124 comment
= sheet_get_comment (sheet
, pos
);
5126 g_object_get (G_OBJECT (comment
),
5127 "text", &(me
->old_text
),
5128 "author", &(me
->old_author
),
5129 "markup", &(me
->old_attributes
), NULL
);
5130 if (me
->old_attributes
!= NULL
)
5131 pango_attr_list_ref (me
->old_attributes
);
5132 me
->old_text
= g_strdup (me
->old_text
);
5133 me
->old_author
= g_strdup (me
->old_author
);
5136 /* Register the command object */
5137 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
5140 /******************************************************************/
5142 #define CMD_ANALYSIS_TOOL_TYPE (cmd_analysis_tool_get_type ())
5143 #define CMD_ANALYSIS_TOOL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_ANALYSIS_TOOL_TYPE, CmdAnalysis_Tool))
5148 data_analysis_output_t
*dao
;
5150 gboolean specs_owned
;
5151 analysis_tool_engine engine
;
5152 data_analysis_output_type_t type
;
5154 ColRowStateList
*col_info
;
5155 ColRowStateList
*row_info
;
5157 GnmCellRegion
*old_contents
;
5158 GSList
*newSheetObjects
;
5161 MAKE_GNM_COMMAND (CmdAnalysis_Tool
, cmd_analysis_tool
, NULL
)
5164 cmd_analysis_tool_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
5166 CmdAnalysis_Tool
*me
= CMD_ANALYSIS_TOOL (cmd
);
5169 g_return_val_if_fail (me
!= NULL
, TRUE
);
5171 /* The old view might not exist anymore */
5175 case NewSheetOutput
:
5176 if (!command_undo_sheet_delete (me
->dao
->sheet
))
5178 me
->dao
->sheet
= NULL
;
5180 case NewWorkbookOutput
:
5181 g_warning ("How did we get here?");
5186 sheet_clear_region (me
->dao
->sheet
,
5187 me
->old_range
.start
.col
, me
->old_range
.start
.row
,
5188 me
->old_range
.end
.col
, me
->old_range
.end
.row
,
5189 CLEAR_COMMENTS
| CLEAR_FORMATS
| CLEAR_NOCHECKARRAY
|
5190 CLEAR_RECALC_DEPS
| CLEAR_VALUES
| CLEAR_MERGES
,
5191 GO_CMD_CONTEXT (wbc
));
5192 clipboard_paste_region (me
->old_contents
,
5193 paste_target_init (&pt
, me
->dao
->sheet
, &me
->old_range
, PASTE_ALL_TYPES
),
5194 GO_CMD_CONTEXT (wbc
));
5195 cellregion_unref (me
->old_contents
);
5196 me
->old_contents
= NULL
;
5198 dao_set_colrow_state_list (me
->dao
, TRUE
, me
->col_info
);
5199 me
->col_info
= colrow_state_list_destroy (me
->col_info
);
5202 dao_set_colrow_state_list (me
->dao
, FALSE
, me
->row_info
);
5203 me
->row_info
= colrow_state_list_destroy (me
->row_info
);
5205 if (me
->newSheetObjects
== NULL
)
5206 me
->newSheetObjects
= dao_surrender_so (me
->dao
);
5207 g_slist_foreach (me
->newSheetObjects
, (GFunc
)sheet_object_clear_sheet
, NULL
);
5208 sheet_update (me
->dao
->sheet
);
5215 cmd_analysis_tool_draw_old_so (SheetObject
*so
, data_analysis_output_t
*dao
)
5218 dao_set_sheet_object (dao
, 0, 1, so
);
5222 cmd_analysis_tool_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
5224 gpointer continuity
= NULL
;
5225 CmdAnalysis_Tool
*me
= CMD_ANALYSIS_TOOL (cmd
);
5226 GOCmdContext
*cc
= GO_CMD_CONTEXT (wbc
);
5228 g_return_val_if_fail (me
!= NULL
, TRUE
);
5230 /* The old view might not exist anymore */
5234 me
->col_info
= colrow_state_list_destroy (me
->col_info
);
5235 me
->col_info
= dao_get_colrow_state_list (me
->dao
, TRUE
);
5237 me
->row_info
= colrow_state_list_destroy (me
->row_info
);
5238 me
->row_info
= dao_get_colrow_state_list (me
->dao
, FALSE
);
5240 if (me
->engine (cc
, me
->dao
, me
->specs
, TOOL_ENGINE_PREPARE_OUTPUT_RANGE
, NULL
)
5241 || me
->engine (cc
, me
->dao
, me
->specs
, TOOL_ENGINE_UPDATE_DESCRIPTOR
,
5242 &me
->cmd
.cmd_descriptor
)
5243 || cmd_dao_is_locked_effective (me
->dao
, wbc
, me
->cmd
.cmd_descriptor
)
5244 || me
->engine (cc
, me
->dao
, me
->specs
, TOOL_ENGINE_LAST_VALIDITY_CHECK
, &continuity
))
5248 case NewSheetOutput
:
5249 me
->old_contents
= NULL
;
5251 case NewWorkbookOutput
:
5252 /* No undo in this case (see below) */
5253 me
->old_contents
= NULL
;
5257 range_init (&me
->old_range
, me
->dao
->start_col
, me
->dao
->start_row
,
5258 me
->dao
->start_col
+ me
->dao
->cols
- 1,
5259 me
->dao
->start_row
+ me
->dao
->rows
- 1);
5260 me
->old_contents
= clipboard_copy_range (me
->dao
->sheet
, &me
->old_range
);
5264 if (me
->newSheetObjects
!= NULL
)
5265 dao_set_omit_so (me
->dao
, TRUE
);
5267 if (me
->engine (cc
, me
->dao
, me
->specs
, TOOL_ENGINE_FORMAT_OUTPUT_RANGE
, NULL
))
5270 if (me
->engine (cc
, me
->dao
, me
->specs
, TOOL_ENGINE_PERFORM_CALC
, &continuity
)) {
5271 if (me
->type
== RangeOutput
) {
5272 g_warning ("This is too late for failure! The target region has "
5273 "already been formatted!");
5277 if (me
->newSheetObjects
!= NULL
)
5279 GSList
*l
= g_slist_reverse
5280 (g_slist_copy (me
->newSheetObjects
));
5282 dao_set_omit_so (me
->dao
, FALSE
);
5284 (GFunc
) cmd_analysis_tool_draw_old_so
,
5290 g_warning ("There shouldn't be any data left in here!");
5293 dao_autofit_columns (me
->dao
);
5294 sheet_mark_dirty (me
->dao
->sheet
);
5295 sheet_update (me
->dao
->sheet
);
5297 /* The concept of an undo if we create a new worksheet is extremely strange,
5298 * since we have separate undo/redo queues per worksheet.
5299 * Users can simply delete the worksheet if they so desire.
5302 return (me
->type
== NewWorkbookOutput
);
5306 cmd_analysis_tool_finalize (GObject
*cmd
)
5308 CmdAnalysis_Tool
*me
= CMD_ANALYSIS_TOOL (cmd
);
5311 me
->col_info
= colrow_state_list_destroy (me
->col_info
);
5313 me
->row_info
= colrow_state_list_destroy (me
->row_info
);
5315 me
->engine (NULL
, me
->dao
, me
->specs
, TOOL_ENGINE_CLEAN_UP
, NULL
);
5317 if (me
->specs_owned
) {
5321 if (me
->old_contents
)
5322 cellregion_unref (me
->old_contents
);
5324 g_slist_free_full (me
->newSheetObjects
, g_object_unref
);
5326 gnm_command_finalize (cmd
);
5330 * cmd_analysis_tool: (skip)
5331 * Note: this takes ownership of specs and dao if and if only the command
5335 cmd_analysis_tool (WorkbookControl
*wbc
, G_GNUC_UNUSED Sheet
*sheet
,
5336 data_analysis_output_t
*dao
, gpointer specs
,
5337 analysis_tool_engine engine
, gboolean always_take_ownership
)
5339 CmdAnalysis_Tool
*me
;
5341 GOCmdContext
*cc
= GO_CMD_CONTEXT (wbc
);
5343 g_return_val_if_fail (dao
!= NULL
, TRUE
);
5344 g_return_val_if_fail (specs
!= NULL
, TRUE
);
5345 g_return_val_if_fail (engine
!= NULL
, TRUE
);
5347 me
= g_object_new (CMD_ANALYSIS_TOOL_TYPE
, NULL
);
5351 /* Store the specs for the object */
5353 me
->specs_owned
= always_take_ownership
;
5355 me
->engine
= engine
;
5356 me
->cmd
.cmd_descriptor
= NULL
;
5357 if (me
->engine (cc
, me
->dao
, me
->specs
, TOOL_ENGINE_UPDATE_DAO
, NULL
)) {
5358 g_object_unref (me
);
5361 me
->engine (cc
, me
->dao
, me
->specs
, TOOL_ENGINE_UPDATE_DESCRIPTOR
,
5362 &me
->cmd
.cmd_descriptor
);
5363 me
->cmd
.sheet
= NULL
;
5364 me
->type
= dao
->type
;
5365 me
->row_info
= NULL
;
5366 me
->col_info
= NULL
;
5368 /* We divide by 2 since many cells will be empty*/
5369 me
->cmd
.size
= 1 + dao
->rows
* dao
->cols
/ 2;
5371 /* Register the command object */
5372 trouble
= gnm_command_push_undo (wbc
, G_OBJECT (me
));
5375 me
->specs_owned
= TRUE
;
5380 /******************************************************************/
5382 #define CMD_MERGE_DATA_TYPE (cmd_merge_data_get_type ())
5383 #define CMD_MERGE_DATA(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_MERGE_DATA_TYPE, CmdMergeData))
5387 GnmValue
*merge_zone
;
5388 GSList
*merge_fields
;
5395 MAKE_GNM_COMMAND (CmdMergeData
, cmd_merge_data
, NULL
)
5398 cmd_merge_data_delete_sheets (gpointer data
, gpointer success
)
5400 Sheet
*sheet
= data
;
5402 if (!command_undo_sheet_delete (sheet
))
5403 *(gboolean
*)success
= FALSE
;
5407 cmd_merge_data_undo (GnmCommand
*cmd
,
5408 G_GNUC_UNUSED WorkbookControl
*wbc
)
5410 CmdMergeData
*me
= CMD_MERGE_DATA (cmd
);
5411 gboolean success
= TRUE
;
5413 g_slist_foreach (me
->sheet_list
, cmd_merge_data_delete_sheets
, &success
);
5414 g_slist_free (me
->sheet_list
);
5415 me
->sheet_list
= NULL
;
5421 cmd_merge_data_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
5423 CmdMergeData
*me
= CMD_MERGE_DATA (cmd
);
5425 GnmCellRegion
*merge_contents
;
5426 GnmRangeRef
*cell
= &me
->merge_zone
->v_range
.cell
;
5428 GSList
*this_field
= me
->merge_fields
;
5429 GSList
*this_data
= me
->merge_data
;
5430 Sheet
*source_sheet
= cell
->a
.sheet
;
5431 GSList
*target_sheet
;
5432 GnmRange target_range
;
5433 ColRowStateList
*state_col
;
5434 ColRowStateList
*state_row
;
5436 range_init (&target_range
, cell
->a
.col
, cell
->a
.row
,
5437 cell
->b
.col
, cell
->b
.row
);
5438 merge_contents
= clipboard_copy_range (source_sheet
, &target_range
);
5439 state_col
= colrow_get_states (source_sheet
, TRUE
, target_range
.start
.col
,
5440 target_range
.end
.col
);
5441 state_row
= colrow_get_states (source_sheet
, FALSE
, target_range
.start
.row
,
5442 target_range
.end
.row
);
5444 for (i
= 0; i
< me
->n
; i
++) {
5447 new_sheet
= workbook_sheet_add (me
->sheet
->workbook
, -1,
5448 gnm_sheet_get_max_cols (me
->sheet
),
5449 gnm_sheet_get_max_rows (me
->sheet
));
5450 me
->sheet_list
= g_slist_prepend (me
->sheet_list
, new_sheet
);
5452 colrow_set_states (new_sheet
, TRUE
, target_range
.start
.col
, state_col
);
5453 colrow_set_states (new_sheet
, FALSE
, target_range
.start
.row
, state_row
);
5454 sheet_objects_dup (source_sheet
, new_sheet
, &target_range
);
5455 clipboard_paste_region (merge_contents
,
5456 paste_target_init (&pt
, new_sheet
, &target_range
, PASTE_ALL_TYPES
),
5457 GO_CMD_CONTEXT (wbc
));
5459 cellregion_unref (merge_contents
);
5460 me
->sheet_list
= g_slist_reverse (me
->sheet_list
);
5461 colrow_state_list_destroy (state_col
);
5462 colrow_state_list_destroy (state_row
);
5464 while (this_field
) {
5465 int col_source
, row_source
;
5466 int col_target
, row_target
;
5468 g_return_val_if_fail (this_data
!= NULL
, TRUE
);
5469 cell
= &((GnmValue
*)this_field
->data
)->v_range
.cell
;
5470 col_target
= cell
->a
.col
;
5471 row_target
= cell
->a
.row
;
5473 cell
= &((GnmValue
*)this_data
->data
)->v_range
.cell
;
5474 col_source
= cell
->a
.col
;
5475 row_source
= cell
->a
.row
;
5476 source_sheet
= cell
->a
.sheet
;
5478 target_sheet
= me
->sheet_list
;
5479 while (target_sheet
) {
5480 GnmCell
*source_cell
= sheet_cell_get (source_sheet
,
5481 col_source
, row_source
);
5482 if (source_cell
== NULL
) {
5483 GnmCell
*target_cell
= sheet_cell_get ((Sheet
*)target_sheet
->data
,
5484 col_target
, row_target
);
5485 if (target_cell
!= NULL
)
5486 gnm_cell_set_value (target_cell
,
5487 value_new_empty ());
5489 GnmCell
*target_cell
= sheet_cell_fetch ((Sheet
*)target_sheet
->data
,
5490 col_target
, row_target
);
5491 gnm_cell_set_value (target_cell
,
5492 value_dup (source_cell
->value
));
5494 target_sheet
= target_sheet
->next
;
5498 this_field
= this_field
->next
;
5499 this_data
= this_data
->next
;
5506 cmd_merge_data_finalize (GObject
*cmd
)
5508 CmdMergeData
*me
= CMD_MERGE_DATA (cmd
);
5510 value_release (me
->merge_zone
);
5511 me
->merge_zone
= NULL
;
5512 range_list_destroy (me
->merge_data
);
5513 me
->merge_data
= NULL
;
5514 range_list_destroy (me
->merge_fields
);
5515 me
->merge_fields
= NULL
;
5516 g_slist_free (me
->sheet_list
);
5517 me
->sheet_list
= NULL
;
5520 gnm_command_finalize (cmd
);
5525 * @wbc: #WorkbookControl
5527 * @merge_zone: (transfer full): #GnmValue
5528 * @merge_fields: (element-type GnmRange) (transfer full):
5529 * @merge_data: (element-type GnmRange) (transfer full):
5533 cmd_merge_data (WorkbookControl
*wbc
, Sheet
*sheet
,
5534 GnmValue
*merge_zone
, GSList
*merge_fields
, GSList
*merge_data
)
5539 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
5540 g_return_val_if_fail (merge_zone
!= NULL
, TRUE
);
5541 g_return_val_if_fail (merge_fields
!= NULL
, TRUE
);
5542 g_return_val_if_fail (merge_data
!= NULL
, TRUE
);
5544 me
= g_object_new (CMD_MERGE_DATA_TYPE
, NULL
);
5546 me
->cmd
.sheet
= sheet
;
5548 me
->cmd
.size
= 1 + g_slist_length (merge_fields
);
5549 me
->cmd
.cmd_descriptor
=
5550 g_strdup_printf (_("Merging data into %s"), value_peek_string (merge_zone
));
5552 me
->merge_zone
= merge_zone
;
5553 me
->merge_fields
= merge_fields
;
5554 me
->merge_data
= merge_data
;
5555 me
->sheet_list
= NULL
;
5557 cell
= &((GnmValue
*)merge_data
->data
)->v_range
.cell
;
5558 me
->n
= cell
->b
.row
- cell
->a
.row
+ 1;
5560 /* Register the command object */
5561 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
5564 /******************************************************************/
5566 #define CMD_CHANGE_META_DATA_TYPE (cmd_change_summary_get_type ())
5567 #define CMD_CHANGE_META_DATA(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_CHANGE_META_DATA_TYPE, CmdChangeMetaData))
5571 GSList
*changed_props
;
5572 GSList
*removed_names
;
5573 } CmdChangeMetaData
;
5575 MAKE_GNM_COMMAND (CmdChangeMetaData
, cmd_change_summary
, NULL
)
5578 cmd_change_summary_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
5580 CmdChangeMetaData
*me
= CMD_CHANGE_META_DATA (cmd
);
5581 GsfDocMetaData
*meta
= go_doc_get_meta_data (wb_control_get_doc (wbc
));
5582 GSList
*ptr
, *old_vals
= NULL
, *dropped
= NULL
;
5586 for (ptr
= me
->removed_names
; ptr
!= NULL
; ptr
= ptr
->next
) {
5587 if (NULL
!= (prop
= gsf_doc_meta_data_steal (meta
, ptr
->data
)))
5588 old_vals
= g_slist_prepend (old_vals
, prop
);
5591 g_slist_free (me
->removed_names
);
5593 for (ptr
= me
->changed_props
; ptr
!= NULL
; ptr
= ptr
->next
) {
5594 name
= gsf_doc_prop_get_name (ptr
->data
);
5595 if (NULL
!= (prop
= gsf_doc_meta_data_steal (meta
, name
)))
5596 old_vals
= g_slist_prepend (old_vals
, prop
);
5598 dropped
= g_slist_prepend (old_vals
, g_strdup (name
));
5599 gsf_doc_meta_data_store (meta
, ptr
->data
);
5601 g_slist_free (me
->changed_props
);
5603 me
->removed_names
= dropped
;
5604 me
->changed_props
= old_vals
;
5605 go_doc_update_meta_data (wb_control_get_doc (wbc
));
5611 cmd_change_summary_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
5613 return cmd_change_summary_undo (cmd
, wbc
);
5617 cmd_change_summary_finalize (GObject
*cmd
)
5619 CmdChangeMetaData
*me
= CMD_CHANGE_META_DATA (cmd
);
5621 g_slist_free_full (me
->changed_props
, (GDestroyNotify
)gsf_doc_prop_free
);
5622 me
->changed_props
= NULL
;
5623 g_slist_free_full (me
->removed_names
, g_free
);
5624 me
->removed_names
= NULL
;
5626 gnm_command_finalize (cmd
);
5630 * cmd_change_meta_data:
5631 * @wbc: #WorkbookControl
5632 * @changes: (element-type GsfDocMetaData) (transfer full): the changed metadata.
5633 * @removed: (element-type GsfDocMetaData) (transfer full): the removed metadata.
5637 cmd_change_meta_data (WorkbookControl
*wbc
, GSList
*changes
, GSList
*removed
)
5639 CmdChangeMetaData
*me
= g_object_new (CMD_CHANGE_META_DATA_TYPE
, NULL
);
5641 me
->changed_props
= changes
;
5642 me
->removed_names
= removed
;
5643 me
->cmd
.sheet
= NULL
;
5645 me
->cmd
.size
= g_slist_length (changes
) + g_slist_length (removed
);
5646 me
->cmd
.cmd_descriptor
= g_strdup_printf (
5647 _("Changing workbook properties"));
5648 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
5651 /******************************************************************/
5653 #define CMD_OBJECT_RAISE_TYPE (cmd_object_raise_get_type ())
5654 #define CMD_OBJECT_RAISE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_OBJECT_RAISE_TYPE, CmdObjectRaise))
5659 CmdObjectRaiseSelector dir
;
5660 gint changed_positions
;
5663 MAKE_GNM_COMMAND (CmdObjectRaise
, cmd_object_raise
, NULL
)
5666 cmd_object_raise_redo (GnmCommand
*cmd
,
5667 G_GNUC_UNUSED WorkbookControl
*wbc
)
5669 CmdObjectRaise
*me
= CMD_OBJECT_RAISE (cmd
);
5671 case cmd_object_pull_to_front
:
5672 me
->changed_positions
= sheet_object_adjust_stacking (me
->so
, G_MAXINT
/2);
5674 case cmd_object_pull_forward
:
5675 me
->changed_positions
= sheet_object_adjust_stacking (me
->so
, 1);
5677 case cmd_object_push_backward
:
5678 me
->changed_positions
= sheet_object_adjust_stacking (me
->so
, -1);
5680 case cmd_object_push_to_back
:
5681 me
->changed_positions
= sheet_object_adjust_stacking (me
->so
, G_MININT
/2);
5688 cmd_object_raise_undo (GnmCommand
*cmd
,
5689 G_GNUC_UNUSED WorkbookControl
*wbc
)
5691 CmdObjectRaise
*me
= CMD_OBJECT_RAISE (cmd
);
5692 if (me
->changed_positions
!= 0)
5693 sheet_object_adjust_stacking (me
->so
, - me
->changed_positions
);
5698 cmd_object_raise_finalize (GObject
*cmd
)
5700 CmdObjectRaise
*me
= CMD_OBJECT_RAISE (cmd
);
5701 g_object_unref (me
->so
);
5702 gnm_command_finalize (cmd
);
5706 cmd_object_raise (WorkbookControl
*wbc
, SheetObject
*so
, CmdObjectRaiseSelector dir
)
5710 g_return_val_if_fail (GNM_IS_SO (so
), TRUE
);
5712 me
= g_object_new (CMD_OBJECT_RAISE_TYPE
, NULL
);
5717 me
->cmd
.sheet
= sheet_object_get_sheet (so
);
5720 case cmd_object_pull_to_front
:
5721 me
->cmd
.cmd_descriptor
= g_strdup (_("Pull Object to the Front"));
5723 case cmd_object_pull_forward
:
5724 me
->cmd
.cmd_descriptor
= g_strdup (_("Pull Object Forward"));
5726 case cmd_object_push_backward
:
5727 me
->cmd
.cmd_descriptor
= g_strdup (_("Push Object Backward"));
5729 case cmd_object_push_to_back
:
5730 me
->cmd
.cmd_descriptor
= g_strdup (_("Push Object to the Back"));
5734 me
->changed_positions
= 0;
5736 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
5739 /******************************************************************/
5741 #define CMD_PRINT_SETUP_TYPE (cmd_print_setup_get_type ())
5742 #define CMD_PRINT_SETUP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_PRINT_SETUP_TYPE, CmdPrintSetup))
5748 GnmPrintInformation
*new_pi
;
5751 MAKE_GNM_COMMAND (CmdPrintSetup
, cmd_print_setup
, NULL
)
5754 update_sheet_graph_cb (Sheet
*sheet
)
5756 g_return_if_fail (IS_SHEET (sheet
) && sheet
->sheet_type
== GNM_SHEET_OBJECT
);
5758 sheet_object_graph_ensure_size (GNM_SO (sheet
->sheet_objects
->data
));
5762 cmd_print_setup_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
5764 CmdPrintSetup
*me
= CMD_PRINT_SETUP (cmd
);
5769 g_return_val_if_fail (me
->old_pi
!= NULL
, TRUE
);
5771 if (me
->cmd
.sheet
) {
5772 GnmPrintInformation
*pi
= me
->old_pi
->data
;
5773 gnm_print_info_free (me
->cmd
.sheet
->print_info
);
5774 me
->cmd
.sheet
->print_info
= gnm_print_info_dup (pi
);
5775 if (me
->cmd
.sheet
->sheet_type
== GNM_SHEET_OBJECT
)
5776 update_sheet_graph_cb (me
->cmd
.sheet
);
5778 book
= wb_control_get_workbook(wbc
);
5779 n
= workbook_sheet_count (book
);
5781 g_return_val_if_fail (g_slist_length (infos
) == n
, TRUE
);
5783 for (i
= 0 ; i
< n
; i
++) {
5784 GnmPrintInformation
*pi
= infos
->data
;
5785 Sheet
*sheet
= workbook_sheet_by_index (book
, i
);
5787 g_return_val_if_fail (infos
!= NULL
, TRUE
);
5789 gnm_print_info_free (sheet
->print_info
);
5790 sheet
->print_info
= gnm_print_info_dup (pi
);
5791 if (sheet
->sheet_type
== GNM_SHEET_OBJECT
)
5792 update_sheet_graph_cb (sheet
);
5793 infos
= infos
->next
;
5800 cmd_print_setup_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
5802 CmdPrintSetup
*me
= CMD_PRINT_SETUP (cmd
);
5805 gboolean save_pis
= (me
->old_pi
== NULL
);
5807 if (me
->cmd
.sheet
) {
5809 me
->old_pi
= g_slist_append (me
->old_pi
, me
->cmd
.sheet
->print_info
);
5811 gnm_print_info_free (me
->cmd
.sheet
->print_info
);
5812 me
->cmd
.sheet
->print_info
= gnm_print_info_dup (me
->new_pi
);
5813 if (me
->cmd
.sheet
->sheet_type
== GNM_SHEET_OBJECT
)
5814 update_sheet_graph_cb (me
->cmd
.sheet
);
5816 book
= wb_control_get_workbook(wbc
);
5817 n
= workbook_sheet_count (book
);
5818 for (i
= 0 ; i
< n
; i
++) {
5819 Sheet
*sheet
= workbook_sheet_by_index (book
, i
);
5820 sheet_mark_dirty (sheet
);
5822 me
->old_pi
= g_slist_prepend (me
->old_pi
, sheet
->print_info
);
5824 gnm_print_info_free (sheet
->print_info
);
5825 sheet
->print_info
= gnm_print_info_dup (me
->new_pi
);
5826 if (sheet
->sheet_type
== GNM_SHEET_OBJECT
)
5827 update_sheet_graph_cb (sheet
);
5830 me
->old_pi
= g_slist_reverse (me
->old_pi
);
5836 cmd_print_setup_finalize (GObject
*cmd
)
5838 CmdPrintSetup
*me
= CMD_PRINT_SETUP (cmd
);
5839 GSList
*list
= me
->old_pi
;
5842 gnm_print_info_free (me
->new_pi
);
5843 for (; list
; list
= list
->next
)
5844 gnm_print_info_free ((GnmPrintInformation
*) list
->data
);
5845 g_slist_free (me
->old_pi
);
5846 gnm_command_finalize (cmd
);
5850 cmd_print_setup (WorkbookControl
*wbc
, Sheet
*sheet
, GnmPrintInformation
const *pi
)
5854 me
= g_object_new (CMD_PRINT_SETUP_TYPE
, NULL
);
5856 me
->cmd
.sheet
= sheet
;
5859 me
->cmd
.cmd_descriptor
=
5860 g_strdup_printf (_("Page Setup For %s"), sheet
->name_unquoted
);
5862 me
->cmd
.cmd_descriptor
= g_strdup (_("Page Setup For All Sheets"));
5864 me
->new_pi
= gnm_print_info_dup (pi
);
5866 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
5869 /******************************************************************/
5871 #define CMD_DEFINE_NAME_TYPE (cmd_define_name_get_type ())
5872 #define CMD_DEFINE_NAME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_DEFINE_NAME_TYPE, CmdDefineName))
5879 GnmExprTop
const *texpr
;
5881 gboolean placeholder
;
5884 MAKE_GNM_COMMAND (CmdDefineName
, cmd_define_name
, NULL
)
5887 cmd_define_name_undo (GnmCommand
*cmd
,
5888 WorkbookControl
*wbc
)
5890 CmdDefineName
*me
= CMD_DEFINE_NAME (cmd
);
5891 GnmNamedExpr
*nexpr
= expr_name_lookup (&(me
->pp
), me
->name
);
5892 GnmExprTop
const *texpr
= nexpr
->texpr
;
5894 gnm_expr_top_ref (texpr
);
5896 expr_name_remove (nexpr
);
5897 else if (me
->placeholder
)
5898 expr_name_downgrade_to_placeholder (nexpr
);
5900 expr_name_set_expr (nexpr
, me
->texpr
); /* restore old def */
5904 WORKBOOK_FOREACH_VIEW (wb_control_get_workbook (wbc
), each_wbv
, {
5905 wb_view_menus_update (each_wbv
);
5911 cmd_define_name_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
5913 CmdDefineName
*me
= CMD_DEFINE_NAME (cmd
);
5914 GnmNamedExpr
*nexpr
= expr_name_lookup (&(me
->pp
), me
->name
);
5916 me
->new_name
= (nexpr
== NULL
);
5917 me
->placeholder
= (nexpr
!= NULL
)
5918 && expr_name_is_placeholder (nexpr
);
5920 if (me
->new_name
|| me
->placeholder
) {
5922 nexpr
= expr_name_add (&me
->pp
, me
->name
, me
->texpr
, &err
, TRUE
, NULL
);
5923 if (nexpr
== NULL
) {
5924 go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbc
), _("Name"), err
);
5929 } else { /* changing the definition */
5930 GnmExprTop
const *tmp
= nexpr
->texpr
;
5931 gnm_expr_top_ref (tmp
);
5932 expr_name_set_expr (nexpr
, me
->texpr
);
5933 me
->texpr
= tmp
; /* store the old definition */
5935 WORKBOOK_FOREACH_VIEW (wb_control_get_workbook (wbc
), each_wbv
, {
5936 wb_view_menus_update (each_wbv
);
5943 cmd_define_name_finalize (GObject
*cmd
)
5945 CmdDefineName
*me
= CMD_DEFINE_NAME (cmd
);
5947 g_free (me
->name
); me
->name
= NULL
;
5950 gnm_expr_top_unref (me
->texpr
);
5954 gnm_command_finalize (cmd
);
5962 * @texpr: absorbs a ref to the texpr.
5963 * @descriptor: optional descriptor.
5965 * If the @name has never been defined in context @pp create a new name
5966 * If its a placeholder assign @texpr to it and make it real
5967 * If it already exists as a real name just assign @expr.
5969 * Returns TRUE on error
5972 cmd_define_name (WorkbookControl
*wbc
, char const *name
,
5973 GnmParsePos
const *pp
, GnmExprTop
const *texpr
,
5974 char const *descriptor
)
5977 GnmNamedExpr
*nexpr
;
5980 g_return_val_if_fail (name
!= NULL
, TRUE
);
5981 g_return_val_if_fail (pp
!= NULL
, TRUE
);
5982 g_return_val_if_fail (texpr
!= NULL
, TRUE
);
5984 if (name
[0] == '\0') {
5985 go_cmd_context_error_invalid
5986 (GO_CMD_CONTEXT (wbc
), _("Defined Name"),
5987 _("An empty string is not allowed as defined name."));
5988 gnm_expr_top_unref (texpr
);
5992 sheet
= wb_control_cur_sheet (wbc
);
5993 if (!expr_name_validate (name
)) {
5994 gchar
*err
= g_strdup_printf
5995 (_("'%s' is not allowed as defined name."), name
);
5996 go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbc
),
5997 _("Defined Name"), err
);
5999 gnm_expr_top_unref (texpr
);
6003 if (expr_name_check_for_loop (name
, texpr
)) {
6004 go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbc
), name
,
6005 _("has a circular reference"));
6006 gnm_expr_top_unref (texpr
);
6009 nexpr
= expr_name_lookup (pp
, name
);
6010 if (nexpr
!= NULL
&& !expr_name_is_placeholder (nexpr
) &&
6011 gnm_expr_top_equal (texpr
, nexpr
->texpr
)) {
6012 gnm_expr_top_unref (texpr
);
6013 return FALSE
; /* expr is not changing, do nothing */
6016 me
= g_object_new (CMD_DEFINE_NAME_TYPE
, NULL
);
6017 me
->name
= g_strdup (name
);
6021 me
->cmd
.sheet
= sheet
;
6024 if (descriptor
== NULL
) {
6028 /* Underscores need to be doubled. */
6029 res
= g_string_new (NULL
);
6030 for (tmp
= name
; *tmp
; tmp
++) {
6032 g_string_append_c (res
, '_');
6033 g_string_append_c (res
, *tmp
);
6036 nexpr
= expr_name_lookup (pp
, name
);
6037 if (nexpr
== NULL
|| expr_name_is_placeholder (nexpr
))
6038 me
->cmd
.cmd_descriptor
=
6039 g_strdup_printf (_("Define Name %s"), res
->str
);
6041 me
->cmd
.cmd_descriptor
=
6042 g_strdup_printf (_("Update Name %s"), res
->str
);
6043 g_string_free (res
, TRUE
);
6045 me
->cmd
.cmd_descriptor
= g_strdup (descriptor
);
6047 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6050 /******************************************************************/
6052 #define CMD_REMOVE_NAME_TYPE (cmd_remove_name_get_type ())
6053 #define CMD_REMOVE_NAME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_REMOVE_NAME_TYPE, CmdRemoveName))
6059 GnmNamedExpr
*nexpr
;
6060 const GnmExprTop
*texpr
;
6063 MAKE_GNM_COMMAND (CmdRemoveName
, cmd_remove_name
, NULL
)
6066 cmd_remove_name_undo (GnmCommand
*cmd
,
6067 G_GNUC_UNUSED WorkbookControl
*wbc
)
6069 CmdRemoveName
*me
= CMD_REMOVE_NAME (cmd
);
6070 GnmNamedExpr
*nexpr
=
6071 expr_name_add (&me
->nexpr
->pos
, expr_name_name (me
->nexpr
),
6072 me
->texpr
, NULL
, TRUE
, NULL
);
6075 expr_name_ref (nexpr
);
6076 expr_name_unref (me
->nexpr
);
6080 g_warning ("Redefining name failed.");
6086 cmd_remove_name_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
6088 CmdRemoveName
*me
= CMD_REMOVE_NAME (cmd
);
6090 me
->texpr
= me
->nexpr
->texpr
;
6091 gnm_expr_top_ref (me
->texpr
);
6092 expr_name_downgrade_to_placeholder (me
->nexpr
);
6098 cmd_remove_name_finalize (GObject
*cmd
)
6100 CmdRemoveName
*me
= CMD_REMOVE_NAME (cmd
);
6102 expr_name_unref (me
->nexpr
);
6105 gnm_expr_top_unref (me
->texpr
);
6109 gnm_command_finalize (cmd
);
6115 * @nexpr: name to remove.
6117 * Returns TRUE on error
6120 cmd_remove_name (WorkbookControl
*wbc
, GnmNamedExpr
*nexpr
)
6124 g_return_val_if_fail (wbc
!= NULL
, TRUE
);
6125 g_return_val_if_fail (nexpr
!= NULL
, TRUE
);
6126 g_return_val_if_fail (!expr_name_is_placeholder (nexpr
), TRUE
);
6128 expr_name_ref (nexpr
);
6130 me
= g_object_new (CMD_REMOVE_NAME_TYPE
, NULL
);
6133 me
->cmd
.sheet
= wb_control_cur_sheet (wbc
);
6135 me
->cmd
.cmd_descriptor
= g_strdup_printf (_("Remove Name %s"),
6136 expr_name_name (nexpr
));
6138 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6141 /******************************************************************/
6143 #define CMD_RESCOPE_NAME_TYPE (cmd_rescope_name_get_type ())
6144 #define CMD_RESCOPE_NAME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_RESCOPE_NAME_TYPE, CmdRescopeName))
6148 GnmNamedExpr
*nexpr
;
6152 MAKE_GNM_COMMAND (CmdRescopeName
, cmd_rescope_name
, NULL
)
6155 cmd_rescope_name_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
6157 CmdRescopeName
*me
= CMD_RESCOPE_NAME (cmd
);
6158 Sheet
*old_scope
= me
->nexpr
->pos
.sheet
;
6160 GnmParsePos pp
= me
->nexpr
->pos
;
6162 pp
.sheet
= me
->scope
;
6163 err
= expr_name_set_pos (me
->nexpr
, &pp
);
6166 go_cmd_context_error_invalid (GO_CMD_CONTEXT (wbc
), _("Change Scope of Name"), err
);
6171 me
->scope
= old_scope
;
6176 cmd_rescope_name_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
6178 return cmd_rescope_name_redo (cmd
, wbc
);
6183 cmd_rescope_name_finalize (GObject
*cmd
)
6185 CmdRescopeName
*me
= CMD_RESCOPE_NAME (cmd
);
6187 expr_name_unref (me
->nexpr
);
6188 gnm_command_finalize (cmd
);
6192 * cmd_rescope_name :
6194 * @nexpr: name to rescope.
6196 * Returns TRUE on error
6199 cmd_rescope_name (WorkbookControl
*wbc
, GnmNamedExpr
*nexpr
, Sheet
*scope
)
6203 g_return_val_if_fail (wbc
!= NULL
, TRUE
);
6204 g_return_val_if_fail (nexpr
!= NULL
, TRUE
);
6205 g_return_val_if_fail (!expr_name_is_placeholder (nexpr
), TRUE
);
6207 expr_name_ref (nexpr
);
6209 me
= g_object_new (CMD_RESCOPE_NAME_TYPE
, NULL
);
6212 me
->cmd
.sheet
= wb_control_cur_sheet (wbc
);
6214 me
->cmd
.cmd_descriptor
= g_strdup_printf (_("Change Scope of Name %s"),
6215 expr_name_name (nexpr
));
6217 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6219 /******************************************************************/
6221 #define CMD_SCENARIO_ADD_TYPE (cmd_scenario_add_get_type ())
6222 #define CMD_SCENARIO_ADD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SCENARIO_ADD_TYPE, CmdScenarioAdd))
6226 GnmScenario
*scenario
;
6229 MAKE_GNM_COMMAND (CmdScenarioAdd
, cmd_scenario_add
, NULL
)
6232 cmd_scenario_add_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
6234 CmdScenarioAdd
*me
= CMD_SCENARIO_ADD (cmd
);
6235 GnmScenario
*sc
= g_object_ref (me
->scenario
);
6236 gnm_sheet_scenario_add (sc
->sheet
, sc
);
6241 cmd_scenario_add_undo (GnmCommand
*cmd
,
6242 G_GNUC_UNUSED WorkbookControl
*wbc
)
6244 CmdScenarioAdd
*me
= CMD_SCENARIO_ADD (cmd
);
6245 GnmScenario
*sc
= me
->scenario
;
6246 gnm_sheet_scenario_remove (sc
->sheet
, sc
);
6251 cmd_scenario_add_finalize (GObject
*cmd
)
6253 CmdScenarioAdd
*me
= CMD_SCENARIO_ADD (cmd
);
6255 g_object_unref (me
->scenario
);
6256 gnm_command_finalize (cmd
);
6260 cmd_scenario_add (WorkbookControl
*wbc
, GnmScenario
*s
, Sheet
*sheet
)
6264 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
6265 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
6267 me
= g_object_new (CMD_SCENARIO_ADD_TYPE
, NULL
);
6269 me
->scenario
= s
; /* Take ownership */
6270 me
->cmd
.sheet
= sheet
;
6272 me
->cmd
.cmd_descriptor
= g_strdup (_("Add scenario"));
6274 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6277 /******************************************************************/
6279 #define CMD_SCENARIO_MNGR_TYPE (cmd_scenario_mngr_get_type ())
6280 #define CMD_SCENARIO_MNGR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SCENARIO_MNGR_TYPE, CmdScenarioMngr))
6288 MAKE_GNM_COMMAND (CmdScenarioMngr
, cmd_scenario_mngr
, NULL
)
6291 cmd_scenario_mngr_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
6293 CmdScenarioMngr
*me
= CMD_SCENARIO_MNGR (cmd
);
6295 me
->undo
= gnm_scenario_apply (me
->sc
);
6300 cmd_scenario_mngr_undo (GnmCommand
*cmd
,
6301 G_GNUC_UNUSED WorkbookControl
*wbc
)
6303 CmdScenarioMngr
*me
= CMD_SCENARIO_MNGR (cmd
);
6304 go_undo_undo_with_data (me
->undo
, GO_CMD_CONTEXT (wbc
));
6305 g_object_unref (me
->undo
);
6311 cmd_scenario_mngr_finalize (GObject
*cmd
)
6313 CmdScenarioMngr
*me
= CMD_SCENARIO_MNGR (cmd
);
6315 g_object_unref (me
->sc
);
6317 g_object_unref (me
->undo
);
6319 gnm_command_finalize (cmd
);
6323 cmd_scenario_mngr (WorkbookControl
*wbc
, GnmScenario
*sc
, GOUndo
*undo
)
6325 CmdScenarioMngr
*me
;
6327 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
6328 g_return_val_if_fail (GNM_IS_SCENARIO (sc
), TRUE
);
6330 me
= g_object_new (CMD_SCENARIO_MNGR_TYPE
, NULL
);
6332 me
->sc
= g_object_ref (sc
);
6333 me
->undo
= g_object_ref (undo
);
6334 me
->cmd
.sheet
= sc
->sheet
;
6336 me
->cmd
.cmd_descriptor
= g_strdup (_("Scenario Show"));
6338 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6341 /******************************************************************/
6343 #define CMD_DATA_SHUFFLE_TYPE (cmd_data_shuffle_get_type ())
6344 #define CMD_DATA_SHUFFLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_DATA_SHUFFLE_TYPE, CmdDataShuffle))
6348 data_shuffling_t
*ds
;
6351 MAKE_GNM_COMMAND (CmdDataShuffle
, cmd_data_shuffle
, NULL
)
6354 cmd_data_shuffle_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
6356 CmdDataShuffle
*me
= CMD_DATA_SHUFFLE (cmd
);
6358 data_shuffling_redo (me
->ds
);
6363 cmd_data_shuffle_undo (GnmCommand
*cmd
,
6364 G_GNUC_UNUSED WorkbookControl
*wbc
)
6366 CmdDataShuffle
*me
= CMD_DATA_SHUFFLE (cmd
);
6368 data_shuffling_redo (me
->ds
);
6373 cmd_data_shuffle_finalize (GObject
*cmd
)
6375 CmdDataShuffle
*me
= CMD_DATA_SHUFFLE (cmd
);
6377 data_shuffling_free (me
->ds
);
6378 gnm_command_finalize (cmd
);
6382 cmd_data_shuffle (WorkbookControl
*wbc
, data_shuffling_t
*sc
, Sheet
*sheet
)
6386 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
6387 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
6389 me
= g_object_new (CMD_DATA_SHUFFLE_TYPE
, NULL
);
6392 me
->cmd
.sheet
= sheet
;
6394 me
->cmd
.cmd_descriptor
= g_strdup (_("Shuffle Data"));
6396 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6399 /******************************************************************/
6401 #define CMD_TEXT_TO_COLUMNS_TYPE (cmd_text_to_columns_get_type ())
6402 #define CMD_TEXT_TO_COLUMNS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_TEXT_TO_COLUMNS_TYPE, CmdTextToColumns))
6407 GnmCellRegion
*contents
;
6411 ColRowStateList
*saved_sizes
;
6414 MAKE_GNM_COMMAND (CmdTextToColumns
, cmd_text_to_columns
, NULL
)
6417 cmd_text_to_columns_impl (GnmCommand
*cmd
, WorkbookControl
*wbc
,
6420 CmdTextToColumns
*me
= CMD_TEXT_TO_COLUMNS (cmd
);
6421 GnmCellRegion
*contents
;
6423 g_return_val_if_fail (me
!= NULL
, TRUE
);
6424 g_return_val_if_fail (me
->contents
!= NULL
, TRUE
);
6426 contents
= clipboard_copy_range (me
->dst
.sheet
, &me
->dst
.range
);
6427 if (clipboard_paste_region (me
->contents
, &me
->dst
, GO_CMD_CONTEXT (wbc
))) {
6428 /* There was a problem, avoid leaking */
6429 cellregion_unref (contents
);
6433 cellregion_unref (me
->contents
);
6436 colrow_set_states (me
->dst
.sheet
, FALSE
,
6437 me
->dst
.range
.start
.row
, me
->saved_sizes
);
6438 colrow_state_list_destroy (me
->saved_sizes
);
6439 me
->saved_sizes
= NULL
;
6441 me
->saved_sizes
= colrow_get_states (me
->dst
.sheet
,
6442 FALSE
, me
->dst
.range
.start
.row
, me
->dst
.range
.end
.row
);
6443 rows_height_update (me
->dst
.sheet
, &me
->dst
.range
, FALSE
);
6446 me
->contents
= contents
;
6448 /* Select the newly pasted contents (this queues a redraw) */
6449 select_range (me
->dst
.sheet
, &me
->dst
.range
, wbc
);
6455 cmd_text_to_columns_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
6457 return cmd_text_to_columns_impl (cmd
, wbc
, TRUE
);
6461 cmd_text_to_columns_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
6463 return cmd_text_to_columns_impl (cmd
, wbc
, FALSE
);
6467 cmd_text_to_columns_finalize (GObject
*cmd
)
6469 CmdTextToColumns
*me
= CMD_TEXT_TO_COLUMNS (cmd
);
6471 if (me
->saved_sizes
)
6472 me
->saved_sizes
= colrow_state_list_destroy (me
->saved_sizes
);
6474 cellregion_unref (me
->contents
);
6475 me
->contents
= NULL
;
6477 gnm_command_finalize (cmd
);
6481 cmd_text_to_columns (WorkbookControl
*wbc
,
6482 GnmRange
const *src
, Sheet
*src_sheet
,
6483 GnmRange
const *target
, Sheet
*target_sheet
,
6484 GnmCellRegion
*contents
)
6486 CmdTextToColumns
*me
;
6487 char *src_range_name
, *target_range_name
;
6489 g_return_val_if_fail (contents
!= NULL
, TRUE
);
6491 src_range_name
= undo_range_name (src_sheet
, src
);
6492 target_range_name
= undo_range_name (target_sheet
, target
);
6494 me
= g_object_new (CMD_TEXT_TO_COLUMNS_TYPE
, NULL
);
6496 me
->cmd
.sheet
= (src_sheet
== target_sheet
? src_sheet
: NULL
);
6497 me
->cmd
.size
= 1; /* FIXME? */
6498 me
->cmd
.cmd_descriptor
= g_strdup_printf (_("Text (%s) to Columns (%s)"),
6501 me
->dst
.range
= *target
;
6502 me
->dst
.sheet
= target_sheet
;
6503 me
->dst
.paste_flags
= PASTE_CONTENTS
| PASTE_FORMATS
;
6505 me
->src_sheet
= src_sheet
;
6506 me
->contents
= contents
;
6507 me
->saved_sizes
= NULL
;
6509 g_free (src_range_name
);
6510 g_free (target_range_name
);
6512 /* Check array subdivision & merged regions */
6513 if (sheet_range_splits_region (target_sheet
, &me
->dst
.range
,
6514 NULL
, GO_CMD_CONTEXT (wbc
), me
->cmd
.cmd_descriptor
)) {
6515 g_object_unref (me
);
6519 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6522 /******************************************************************/
6524 #define CMD_GENERIC_TYPE (cmd_generic_get_type ())
6525 #define CMD_GENERIC(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_GENERIC_TYPE, CmdGeneric))
6529 GOUndo
*undo
, *redo
;
6532 MAKE_GNM_COMMAND (CmdGeneric
, cmd_generic
, NULL
)
6535 cmd_generic_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
6537 CmdGeneric
*me
= CMD_GENERIC (cmd
);
6538 go_undo_undo_with_data (me
->undo
, GO_CMD_CONTEXT (wbc
));
6543 cmd_generic_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
6545 CmdGeneric
*me
= CMD_GENERIC (cmd
);
6546 go_undo_undo_with_data (me
->redo
, GO_CMD_CONTEXT (wbc
));
6551 cmd_generic_finalize (GObject
*cmd
)
6553 CmdGeneric
*me
= CMD_GENERIC (cmd
);
6555 g_object_unref (me
->undo
);
6556 g_object_unref (me
->redo
);
6558 gnm_command_finalize (cmd
);
6562 cmd_generic_with_size (WorkbookControl
*wbc
, const char *txt
,
6564 GOUndo
*undo
, GOUndo
*redo
)
6568 g_return_val_if_fail (GO_IS_UNDO (undo
), TRUE
);
6569 g_return_val_if_fail (GO_IS_UNDO (redo
), TRUE
);
6571 me
= g_object_new (CMD_GENERIC_TYPE
, NULL
);
6573 me
->cmd
.sheet
= wb_control_cur_sheet (wbc
);
6574 me
->cmd
.size
= size
;
6575 me
->cmd
.cmd_descriptor
= g_strdup (txt
);
6580 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6584 cmd_generic (WorkbookControl
*wbc
, const char *txt
, GOUndo
*undo
, GOUndo
*redo
)
6586 return cmd_generic_with_size (wbc
, txt
, 1, undo
, redo
);
6589 /******************************************************************/
6591 #define CMD_GOAL_SEEK_TYPE (cmd_goal_seek_get_type ())
6592 #define CMD_GOAL_SEEK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_GOAL_SEEK_TYPE, CmdGoalSeek))
6602 MAKE_GNM_COMMAND (CmdGoalSeek
, cmd_goal_seek
, NULL
)
6605 cmd_goal_seek_impl (GnmCell
*cell
, GnmValue
*value
)
6607 sheet_cell_set_value (cell
, value_dup(value
));
6613 cmd_goal_seek_undo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
6615 CmdGoalSeek
*me
= CMD_GOAL_SEEK (cmd
);
6617 return cmd_goal_seek_impl (me
->cell
, me
->ov
);
6621 cmd_goal_seek_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
6623 CmdGoalSeek
*me
= CMD_GOAL_SEEK (cmd
);
6625 return cmd_goal_seek_impl (me
->cell
, me
->nv
);
6629 cmd_goal_seek_finalize (GObject
*cmd
)
6631 CmdGoalSeek
*me
= CMD_GOAL_SEEK (cmd
);
6633 value_release (me
->ov
);
6635 value_release (me
->nv
);
6638 gnm_command_finalize (cmd
);
6642 cmd_goal_seek (WorkbookControl
*wbc
, GnmCell
*cell
, GnmValue
*ov
, GnmValue
*nv
)
6647 g_return_val_if_fail (cell
!= NULL
, TRUE
);
6648 g_return_val_if_fail (ov
!= NULL
|| nv
!= NULL
, TRUE
);
6650 me
= g_object_new (CMD_GOAL_SEEK_TYPE
, NULL
);
6652 me
->cmd
.sheet
= cell
->base
.sheet
;
6654 range_init_cellpos (&range
, &cell
->pos
);
6655 me
->cmd
.cmd_descriptor
= g_strdup_printf
6656 (_("Goal Seek (%s)"), undo_range_name (cell
->base
.sheet
, &range
));
6663 me
->ov
= value_dup (cell
->value
);
6665 me
->nv
= value_dup (cell
->value
);
6667 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6670 /******************************************************************/
6673 #define CMD_FREEZE_PANES_TYPE (cmd_freeze_panes_get_type ())
6674 #define CMD_FREEZE_PANES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_FREEZE_PANES_TYPE, CmdFreezePanes))
6683 MAKE_GNM_COMMAND (CmdFreezePanes
, cmd_freeze_panes
, NULL
)
6686 cmd_freeze_panes_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
6688 CmdFreezePanes
*me
= CMD_FREEZE_PANES (cmd
);
6694 cmd_freeze_panes_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
6696 CmdFreezePanes
*me
= CMD_FREEZE_PANES (cmd
);
6702 cmd_freeze_panes_finalize (GObject
*cmd
)
6704 CmdFreezePanes
*me
= CMD_FREEZE_PANES (cmd
);
6706 gnm_command_finalize (cmd
);
6710 * cmd_freeze_panes :
6711 * @wbc: where to report errors
6712 * @sv: the view to freeze
6716 * Returns TRUE on error
6719 cmd_freeze_panes (WorkbookControl
*wbc
, SheetView
*sv
,
6720 GnmCellPos
const *frozen
, GnmCellPos
const *unfrozen
)
6724 g_return_val_if_fail (name
!= NULL
, TRUE
);
6725 g_return_val_if_fail (pp
!= NULL
, TRUE
);
6726 g_return_val_if_fail (expr
!= NULL
, TRUE
);
6728 me
= g_object_new (CMD_FREEZE_PANES_TYPE
, NULL
);
6731 me
->unfrozen
= expr
;
6732 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6738 /******************************************************************/
6741 #define CMD_TABULATE_TYPE (cmd_tabulate_get_type ())
6742 #define CMD_TABULATE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_TABULATE_TYPE, CmdTabulate))
6747 GnmTabulateInfo
*data
;
6750 MAKE_GNM_COMMAND (CmdTabulate
, cmd_tabulate
, NULL
)
6753 cmd_tabulate_cmp_f (gconstpointer a
,
6756 guint
const a_val
= GPOINTER_TO_INT (a
);
6757 guint
const b_val
= GPOINTER_TO_INT (b
);
6767 cmd_tabulate_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
6769 CmdTabulate
*me
= CMD_TABULATE (cmd
);
6771 gboolean res
= TRUE
;
6773 me
->sheet_idx
= g_slist_sort (me
->sheet_idx
,
6774 cmd_tabulate_cmp_f
);
6776 for (l
= me
->sheet_idx
; l
!= NULL
; l
= l
->next
) {
6777 int i
= GPOINTER_TO_INT (l
->data
);
6779 workbook_sheet_by_index (wb_control_get_workbook (wbc
),
6781 res
= res
&& command_undo_sheet_delete (new_sheet
);
6787 cmd_tabulate_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
6789 CmdTabulate
*me
= CMD_TABULATE (cmd
);
6791 g_slist_free (me
->sheet_idx
);
6792 me
->sheet_idx
= do_tabulation (wbc
, me
->data
);
6794 return (me
->sheet_idx
== NULL
);
6798 cmd_tabulate_finalize (GObject
*cmd
)
6800 CmdTabulate
*me
= CMD_TABULATE (cmd
);
6802 g_free (me
->data
->cells
);
6803 g_free (me
->data
->minima
);
6804 g_free (me
->data
->maxima
);
6805 g_free (me
->data
->steps
);
6807 gnm_command_finalize (cmd
);
6811 cmd_tabulate (WorkbookControl
*wbc
, gpointer data
)
6815 g_return_val_if_fail (data
!= NULL
, TRUE
);
6817 me
= g_object_new (CMD_TABULATE_TYPE
, NULL
);
6819 me
->cmd
.sheet
= NULL
;
6821 me
->cmd
.cmd_descriptor
=
6822 g_strdup_printf (_("Tabulating Dependencies"));
6824 me
->sheet_idx
= NULL
;
6826 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6829 /******************************************************************/
6831 #define CMD_SO_GRAPH_CONFIG_TYPE (cmd_so_graph_config_get_type ())
6832 #define CMD_SO_GRAPH_CONFIG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_GRAPH_CONFIG_TYPE, CmdSOGraphConfig))
6837 GogGraph
*new_graph
;
6838 GogGraph
*old_graph
;
6841 MAKE_GNM_COMMAND (CmdSOGraphConfig
, cmd_so_graph_config
, NULL
)
6844 cmd_so_graph_config_redo (GnmCommand
*cmd
,
6845 G_GNUC_UNUSED WorkbookControl
*wbc
)
6847 CmdSOGraphConfig
*me
= CMD_SO_GRAPH_CONFIG (cmd
);
6848 sheet_object_graph_set_gog (me
->so
, me
->new_graph
);
6853 cmd_so_graph_config_undo (GnmCommand
*cmd
,
6854 G_GNUC_UNUSED WorkbookControl
*wbc
)
6856 CmdSOGraphConfig
*me
= CMD_SO_GRAPH_CONFIG (cmd
);
6857 sheet_object_graph_set_gog (me
->so
, me
->old_graph
);
6862 cmd_so_graph_config_finalize (GObject
*cmd
)
6864 CmdSOGraphConfig
*me
= CMD_SO_GRAPH_CONFIG (cmd
);
6866 g_object_unref (me
->so
);
6867 g_object_unref (me
->new_graph
);
6868 g_object_unref (me
->old_graph
);
6870 gnm_command_finalize (cmd
);
6874 cmd_so_graph_config (WorkbookControl
*wbc
, SheetObject
*so
,
6875 GObject
*n_graph
, GObject
*o_graph
)
6877 CmdSOGraphConfig
*me
;
6879 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
6880 g_return_val_if_fail (GNM_IS_SO_GRAPH (so
), TRUE
);
6881 g_return_val_if_fail (GOG_IS_GRAPH (n_graph
), TRUE
);
6882 g_return_val_if_fail (GOG_IS_GRAPH (o_graph
), TRUE
);
6884 me
= g_object_new (CMD_SO_GRAPH_CONFIG_TYPE
, NULL
);
6889 me
->new_graph
= GOG_GRAPH (n_graph
);
6890 g_object_ref (me
->new_graph
);
6891 me
->old_graph
= GOG_GRAPH (o_graph
);
6892 g_object_ref (me
->old_graph
);
6894 me
->cmd
.sheet
= sheet_object_get_sheet (so
);
6896 me
->cmd
.cmd_descriptor
= g_strdup (_("Reconfigure Graph"));
6898 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6901 /******************************************************************/
6903 #define CMD_SO_COMPONENT_CONFIG_TYPE (cmd_so_component_config_get_type ())
6904 #define CMD_SO_COMPONENT_CONFIG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_COMPONENT_CONFIG_TYPE, CmdSOComponentConfig))
6909 GOComponent
*new_obj
;
6910 GOComponent
*old_obj
;
6911 } CmdSOComponentConfig
;
6913 MAKE_GNM_COMMAND (CmdSOComponentConfig
, cmd_so_component_config
, NULL
)
6916 cmd_so_component_config_redo (GnmCommand
*cmd
,
6917 G_GNUC_UNUSED WorkbookControl
*wbc
)
6919 CmdSOComponentConfig
*me
= CMD_SO_COMPONENT_CONFIG (cmd
);
6920 sheet_object_component_set_component (me
->so
, me
->new_obj
);
6925 cmd_so_component_config_undo (GnmCommand
*cmd
,
6926 G_GNUC_UNUSED WorkbookControl
*wbc
)
6928 CmdSOComponentConfig
*me
= CMD_SO_COMPONENT_CONFIG (cmd
);
6929 sheet_object_component_set_component (me
->so
, me
->old_obj
);
6934 cmd_so_component_config_finalize (GObject
*cmd
)
6936 CmdSOComponentConfig
*me
= CMD_SO_COMPONENT_CONFIG (cmd
);
6938 g_object_unref (me
->so
);
6939 g_object_unref (me
->new_obj
);
6940 g_object_unref (me
->old_obj
);
6942 gnm_command_finalize (cmd
);
6946 cmd_so_component_config (WorkbookControl
*wbc
, SheetObject
*so
,
6947 GObject
*n_obj
, GObject
*o_obj
)
6949 CmdSOComponentConfig
*me
;
6951 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
6952 g_return_val_if_fail (GNM_IS_SO_COMPONENT (so
), TRUE
);
6953 g_return_val_if_fail (GO_IS_COMPONENT (n_obj
), TRUE
);
6954 g_return_val_if_fail (GO_IS_COMPONENT (o_obj
), TRUE
);
6956 me
= g_object_new (CMD_SO_COMPONENT_CONFIG_TYPE
, NULL
);
6961 me
->new_obj
= GO_COMPONENT (g_object_ref (n_obj
));
6962 me
->old_obj
= GO_COMPONENT (g_object_ref (o_obj
));
6964 me
->cmd
.sheet
= sheet_object_get_sheet (so
);
6966 me
->cmd
.cmd_descriptor
= g_strdup (_("Reconfigure Object"));
6968 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
6971 /******************************************************************/
6973 #define CMD_TOGGLE_RTL_TYPE (cmd_toggle_rtl_get_type ())
6974 #define CMD_TOGGLE_RTL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_TOGGLE_RTL_TYPE, CmdToggleRTL))
6976 typedef GnmCommand CmdToggleRTL
;
6978 MAKE_GNM_COMMAND (CmdToggleRTL
, cmd_toggle_rtl
, NULL
)
6981 cmd_toggle_rtl_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
6983 go_object_toggle (cmd
->sheet
, "text-is-rtl");
6988 cmd_toggle_rtl_undo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
6990 return cmd_toggle_rtl_redo (cmd
, wbc
);
6994 cmd_toggle_rtl_finalize (GObject
*cmd
)
6996 gnm_command_finalize (cmd
);
7000 cmd_toggle_rtl (WorkbookControl
*wbc
, Sheet
*sheet
)
7004 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
7005 g_return_val_if_fail (IS_SHEET (sheet
), TRUE
);
7007 me
= g_object_new (CMD_TOGGLE_RTL_TYPE
, NULL
);
7010 me
->cmd_descriptor
= g_strdup (sheet
->text_is_rtl
? _("Left to Right") : _("Right to Left"));
7012 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
7015 /******************************************************************/
7017 #define CMD_SO_SET_VALUE_TYPE (cmd_so_set_value_get_type ())
7018 #define CMD_SO_SET_VALUE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_SET_VALUE_TYPE, CmdSOSetValue))
7027 MAKE_GNM_COMMAND (CmdSOSetValue
, cmd_so_set_value
, NULL
)
7030 cmd_so_set_value_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7032 CmdSOSetValue
*me
= CMD_SO_SET_VALUE (cmd
);
7033 Sheet
*sheet
= me
->ref
.sheet
;
7034 GnmCell
*cell
= sheet_cell_fetch (sheet
, me
->ref
.col
, me
->ref
.row
);
7036 sheet_cell_set_value (cell
, value_dup (me
->val
));
7037 sheet_update (sheet
);
7043 cmd_so_set_value_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
7045 CmdSOSetValue
*me
= CMD_SO_SET_VALUE (cmd
);
7047 go_undo_undo_with_data (me
->undo
, GO_CMD_CONTEXT (wbc
));
7053 cmd_so_set_value_finalize (GObject
*cmd
)
7055 CmdSOSetValue
*me
= CMD_SO_SET_VALUE (cmd
);
7057 value_release (me
->val
);
7058 g_object_unref (me
->undo
);
7060 gnm_command_finalize (cmd
);
7064 cmd_so_set_value (WorkbookControl
*wbc
,
7066 const GnmCellRef
*pref
,
7073 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
7075 r
.start
.col
= r
.end
.col
= pref
->col
;
7076 r
.start
.row
= r
.end
.row
= pref
->row
;
7078 me
= g_object_new (CMD_SO_SET_VALUE_TYPE
, NULL
);
7079 me
->cmd
.sheet
= sheet
;
7081 me
->cmd
.cmd_descriptor
= g_strdup (text
);
7084 me
->undo
= clipboard_copy_range_undo (pref
->sheet
, &r
);
7086 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
7089 /******************************************************************/
7091 #define CMD_HYPERLINK_TYPE (cmd_hyperlink_get_type ())
7092 #define CMD_HYPERLINK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_HYPERLINK_TYPE, CmdHyperlink))
7097 GnmStyle
*new_style
;
7100 gboolean update_size
;
7104 cmd_hyperlink_repeat (GnmCommand
const *cmd
, WorkbookControl
*wbc
)
7106 CmdHyperlink
const *orig
= (CmdHyperlink
const *) cmd
;
7108 if (orig
->new_style
)
7109 gnm_style_ref (orig
->new_style
);
7111 cmd_selection_hyperlink (wbc
, orig
->new_style
, NULL
,
7112 g_strdup (orig
->opt_content
));
7114 MAKE_GNM_COMMAND (CmdHyperlink
, cmd_hyperlink
, cmd_hyperlink_repeat
)
7117 cmd_hyperlink_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
7119 CmdHyperlink
*me
= CMD_HYPERLINK (cmd
);
7120 Workbook
*wb
= wb_control_get_workbook (wbc
);
7123 go_undo_undo (me
->undo
);
7124 g_clear_object (&me
->undo
);
7127 select_selection (me
->cmd
.sheet
, me
->selection
, wbc
);
7129 WORKBOOK_FOREACH_CONTROL (wb
, view
, ctl
, {
7130 wb_control_menu_state_update (ctl
, MS_COMMENT_LINKS
);
7137 cb_hyperlink_set_text (GnmCellIter
const *iter
, gpointer user
)
7139 CmdHyperlink
*me
= user
;
7140 GnmCell
*cell
= iter
->cell
;
7143 cell
= sheet_cell_fetch (iter
->pp
.sheet
,
7147 /* We skip non-empty cells. */
7148 if (gnm_cell_is_empty (cell
) &&
7149 !gnm_cell_is_nonsingleton_array (cell
)) {
7150 sheet_cell_set_value (cell
, value_new_string (me
->opt_content
));
7151 if (me
->update_size
)
7159 cmd_hyperlink_redo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
7161 CmdHyperlink
*me
= CMD_HYPERLINK (cmd
);
7163 Workbook
*wb
= wb_control_get_workbook (wbc
);
7166 g_return_val_if_fail (me
!= NULL
, TRUE
);
7168 sheet
= me
->cmd
.sheet
;
7170 /* Check for locked cells */
7171 if (cmd_selection_is_locked_effective (sheet
, me
->selection
,
7172 wbc
, _("Changing Hyperlink")))
7175 me
->undo
= clipboard_copy_ranges_undo (sheet
, me
->selection
);
7177 for (l
= me
->selection
; l
; l
= l
->next
) {
7178 GnmRange
const *r
= l
->data
;
7180 if (me
->new_style
) {
7181 gnm_style_ref (me
->new_style
);
7182 sheet_apply_style (sheet
, r
, me
->new_style
);
7183 sheet_flag_style_update_range (sheet
, r
);
7186 if (me
->opt_content
) {
7187 sheet_foreach_cell_in_range (sheet
, CELL_ITER_ALL
,
7188 r
->start
.col
, r
->start
.row
,
7189 r
->end
.col
, r
->end
.row
,
7190 cb_hyperlink_set_text
,
7194 me
->update_size
= FALSE
;
7196 sheet_redraw_all (sheet
, FALSE
);
7197 sheet_mark_dirty (sheet
);
7199 select_selection (sheet
, me
->selection
, wbc
);
7201 WORKBOOK_FOREACH_CONTROL (wb
, view
, ctl
,
7202 wb_control_menu_state_update (ctl
, MS_COMMENT_LINKS
););
7208 cmd_hyperlink_finalize (GObject
*cmd
)
7210 CmdHyperlink
*me
= CMD_HYPERLINK (cmd
);
7212 g_clear_object (&me
->undo
);
7215 gnm_style_unref (me
->new_style
);
7216 me
->new_style
= NULL
;
7218 range_fragment_free (me
->selection
);
7219 me
->selection
= NULL
;
7221 g_free (me
->opt_content
);
7223 gnm_command_finalize (cmd
);
7227 * cmd_selection_hyperlink:
7228 * @wbc: the workbook control.
7229 * @style: style to apply to the selection
7230 * @opt_translated_name: An optional name to use in place of 'Hyperlink Cells'
7231 * @opt_content: optional content for otherwise empty cells.
7233 * If borders is non NULL, then the GnmBorder references are passed,
7234 * the GnmStyle reference is also passed.
7236 * It absorbs the reference to the style.
7238 * Return value: TRUE if there was a problem
7241 cmd_selection_hyperlink (WorkbookControl
*wbc
,
7243 char const *opt_translated_name
,
7247 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
7249 me
= g_object_new (CMD_HYPERLINK_TYPE
, NULL
);
7251 me
->selection
= selection_get_ranges (sv
, FALSE
); /* TRUE ? */
7252 me
->new_style
= style
;
7254 me
->cmd
.sheet
= sv_sheet (sv
);
7255 me
->cmd
.size
= 1; /* Updated later. */
7256 me
->update_size
= TRUE
;
7258 me
->opt_content
= opt_content
;
7260 if (opt_translated_name
== NULL
) {
7261 char *names
= undo_range_list_name (me
->cmd
.sheet
, me
->selection
);
7263 me
->cmd
.cmd_descriptor
= g_strdup_printf (_("Changing hyperlink of %s"), names
);
7266 me
->cmd
.cmd_descriptor
= g_strdup (opt_translated_name
);
7269 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
7272 /******************************************************************/
7275 #define CMD_SO_SET_LINKS_TYPE (cmd_so_set_links_get_type ())
7276 #define CMD_SO_SET_LINKS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_SET_LINKS_TYPE, CmdSOSetLink))
7281 GnmExprTop
const *output
;
7282 GnmExprTop
const *content
;
7286 MAKE_GNM_COMMAND (CmdSOSetLink
, cmd_so_set_links
, NULL
)
7289 cmd_so_set_links_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7291 CmdSOSetLink
*me
= CMD_SO_SET_LINKS (cmd
);
7292 GnmExprTop
const *old_output
;
7293 GnmExprTop
const *old_content
;
7294 gboolean old_as_index
;
7296 old_content
= sheet_widget_list_base_get_content_link (me
->so
);
7297 old_output
= sheet_widget_list_base_get_result_link (me
->so
);
7298 old_as_index
= sheet_widget_list_base_result_type_is_index (me
->so
);
7300 sheet_widget_list_base_set_links
7301 (me
->so
, me
->output
, me
->content
);
7302 if (old_as_index
!= me
->as_index
) {
7303 sheet_widget_list_base_set_result_type (me
->so
, me
->as_index
);
7304 me
->as_index
= old_as_index
;
7307 gnm_expr_top_unref (me
->output
);
7309 gnm_expr_top_unref (me
->content
);
7310 me
->output
= old_output
;
7311 me
->content
= old_content
;
7317 cmd_so_set_links_undo (GnmCommand
*cmd
, WorkbookControl
*wbc
)
7319 return cmd_so_set_links_redo (cmd
, wbc
);
7323 cmd_so_set_links_finalize (GObject
*cmd
)
7325 CmdSOSetLink
*me
= CMD_SO_SET_LINKS (cmd
);
7328 gnm_expr_top_unref (me
->output
);
7330 gnm_expr_top_unref (me
->content
);
7331 gnm_command_finalize (cmd
);
7335 cmd_so_set_links (WorkbookControl
*wbc
,
7337 GnmExprTop
const *output
,
7338 GnmExprTop
const *content
,
7343 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
7345 me
= g_object_new (CMD_SO_SET_LINKS_TYPE
, NULL
);
7346 me
->cmd
.sheet
= sheet_object_get_sheet (so
);
7348 me
->cmd
.cmd_descriptor
= g_strdup (_("Configure List"));
7350 me
->output
= output
;
7351 me
->content
= content
;
7352 me
->as_index
= as_index
;
7354 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
7357 /******************************************************************/
7361 #define CMD_SO_SET_FRAME_LABEL_TYPE (cmd_so_set_frame_label_get_type ())
7362 #define CMD_SO_SET_FRAME_LABEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_SET_FRAME_LABEL_TYPE, CmdSOSetFrameLabel))
7369 } CmdSOSetFrameLabel
;
7371 MAKE_GNM_COMMAND (CmdSOSetFrameLabel
, cmd_so_set_frame_label
, NULL
)
7374 cmd_so_set_frame_label_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7376 CmdSOSetFrameLabel
*me
= CMD_SO_SET_FRAME_LABEL (cmd
);
7378 sheet_widget_frame_set_label (me
->so
, me
->new_label
);
7384 cmd_so_set_frame_label_undo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7386 CmdSOSetFrameLabel
*me
= CMD_SO_SET_FRAME_LABEL (cmd
);
7388 sheet_widget_frame_set_label (me
->so
, me
->old_label
);
7394 cmd_so_set_frame_label_finalize (GObject
*cmd
)
7396 CmdSOSetFrameLabel
*me
= CMD_SO_SET_FRAME_LABEL (cmd
);
7398 g_free (me
->old_label
);
7399 me
->old_label
= NULL
;
7401 g_free (me
->new_label
);
7402 me
->new_label
= NULL
;
7404 gnm_command_finalize (cmd
);
7408 cmd_so_set_frame_label (WorkbookControl
*wbc
,
7410 char *old_label
, char *new_label
)
7412 CmdSOSetFrameLabel
*me
;
7414 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
7416 me
= g_object_new (CMD_SO_SET_FRAME_LABEL_TYPE
, NULL
);
7417 me
->cmd
.sheet
= sheet_object_get_sheet (so
);
7419 me
->cmd
.cmd_descriptor
= g_strdup (_("Set Frame Label"));
7421 me
->old_label
= old_label
;
7422 me
->new_label
= new_label
;
7424 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
7427 /******************************************************************/
7428 #define CMD_SO_SET_BUTTON_TYPE (cmd_so_set_button_get_type ())
7429 #define CMD_SO_SET_BUTTON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_SET_BUTTON_TYPE, CmdSOSetButton))
7434 GnmExprTop
const *new_link
;
7435 GnmExprTop
const *old_link
;
7440 MAKE_GNM_COMMAND (CmdSOSetButton
, cmd_so_set_button
, NULL
)
7443 cmd_so_set_button_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7445 CmdSOSetButton
*me
= CMD_SO_SET_BUTTON (cmd
);
7447 sheet_widget_button_set_link (me
->so
, me
->new_link
);
7448 sheet_widget_button_set_label (me
->so
, me
->new_label
);
7454 cmd_so_set_button_undo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7456 CmdSOSetButton
*me
= CMD_SO_SET_BUTTON (cmd
);
7458 sheet_widget_button_set_link (me
->so
, me
->old_link
);
7459 sheet_widget_button_set_label (me
->so
, me
->old_label
);
7465 cmd_so_set_button_finalize (GObject
*cmd
)
7467 CmdSOSetButton
*me
= CMD_SO_SET_BUTTON (cmd
);
7470 gnm_expr_top_unref (me
->new_link
);
7472 gnm_expr_top_unref (me
->old_link
);
7473 g_free (me
->old_label
);
7474 g_free (me
->new_label
);
7475 gnm_command_finalize (cmd
);
7479 cmd_so_set_button (WorkbookControl
*wbc
,
7480 SheetObject
*so
, GnmExprTop
const *lnk
,
7481 char *old_label
, char *new_label
)
7485 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
7487 me
= g_object_new (CMD_SO_SET_BUTTON_TYPE
, NULL
);
7488 me
->cmd
.sheet
= sheet_object_get_sheet (so
);
7490 me
->cmd
.cmd_descriptor
= g_strdup (_("Configure Button"));
7493 me
->old_label
= old_label
;
7494 me
->new_label
= new_label
;
7496 me
->old_link
= sheet_widget_button_get_link (so
);
7498 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
7501 /******************************************************************/
7502 #define CMD_SO_SET_RADIO_BUTTON_TYPE (cmd_so_set_radio_button_get_type ())
7503 #define CMD_SO_SET_RADIO_BUTTON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_SET_RADIO_BUTTON_TYPE, CmdSOSetRadioButton))
7508 GnmExprTop
const *new_link
;
7509 GnmExprTop
const *old_link
;
7512 GnmValue
*old_value
;
7513 GnmValue
*new_value
;
7514 } CmdSOSetRadioButton
;
7516 MAKE_GNM_COMMAND (CmdSOSetRadioButton
, cmd_so_set_radio_button
, NULL
)
7519 cmd_so_set_radio_button_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7521 CmdSOSetRadioButton
*me
= CMD_SO_SET_RADIO_BUTTON (cmd
);
7523 sheet_widget_radio_button_set_link (me
->so
, me
->new_link
);
7524 sheet_widget_radio_button_set_label (me
->so
, me
->new_label
);
7525 sheet_widget_radio_button_set_value (me
->so
, me
->new_value
);
7531 cmd_so_set_radio_button_undo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7533 CmdSOSetRadioButton
*me
= CMD_SO_SET_RADIO_BUTTON (cmd
);
7535 sheet_widget_radio_button_set_link (me
->so
, me
->old_link
);
7536 sheet_widget_radio_button_set_label (me
->so
, me
->old_label
);
7537 sheet_widget_radio_button_set_value (me
->so
, me
->old_value
);
7543 cmd_so_set_radio_button_finalize (GObject
*cmd
)
7545 CmdSOSetRadioButton
*me
= CMD_SO_SET_RADIO_BUTTON (cmd
);
7548 gnm_expr_top_unref (me
->new_link
);
7550 gnm_expr_top_unref (me
->old_link
);
7551 g_free (me
->old_label
);
7552 g_free (me
->new_label
);
7553 value_release (me
->old_value
);
7554 value_release (me
->new_value
);
7555 gnm_command_finalize (cmd
);
7559 cmd_so_set_radio_button (WorkbookControl
*wbc
,
7560 SheetObject
*so
, GnmExprTop
const *lnk
,
7561 char *old_label
, char *new_label
,
7562 GnmValue
*old_value
, GnmValue
*new_value
)
7564 CmdSOSetRadioButton
*me
;
7566 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
7568 me
= g_object_new (CMD_SO_SET_RADIO_BUTTON_TYPE
, NULL
);
7569 me
->cmd
.sheet
= sheet_object_get_sheet (so
);
7571 me
->cmd
.cmd_descriptor
= g_strdup (_("Configure Radio Button"));
7574 me
->old_label
= old_label
;
7575 me
->new_label
= new_label
;
7576 me
->old_value
= old_value
;
7577 me
->new_value
= new_value
;
7579 me
->old_link
= sheet_widget_radio_button_get_link (so
);
7581 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
7584 /******************************************************************/
7585 #define CMD_SO_SET_CHECKBOX_TYPE (cmd_so_set_checkbox_get_type ())
7586 #define CMD_SO_SET_CHECKBOX(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_SET_CHECKBOX_TYPE, CmdSOSetCheckbox))
7591 GnmExprTop
const *new_link
;
7592 GnmExprTop
const *old_link
;
7597 MAKE_GNM_COMMAND (CmdSOSetCheckbox
, cmd_so_set_checkbox
, NULL
)
7600 cmd_so_set_checkbox_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7602 CmdSOSetCheckbox
*me
= CMD_SO_SET_CHECKBOX (cmd
);
7604 sheet_widget_checkbox_set_link (me
->so
, me
->new_link
);
7605 sheet_widget_checkbox_set_label (me
->so
, me
->new_label
);
7611 cmd_so_set_checkbox_undo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7613 CmdSOSetCheckbox
*me
= CMD_SO_SET_CHECKBOX (cmd
);
7615 sheet_widget_checkbox_set_link (me
->so
, me
->old_link
);
7616 sheet_widget_checkbox_set_label (me
->so
, me
->old_label
);
7622 cmd_so_set_checkbox_finalize (GObject
*cmd
)
7624 CmdSOSetCheckbox
*me
= CMD_SO_SET_CHECKBOX (cmd
);
7627 gnm_expr_top_unref (me
->new_link
);
7629 gnm_expr_top_unref (me
->old_link
);
7630 g_free (me
->old_label
);
7631 g_free (me
->new_label
);
7632 gnm_command_finalize (cmd
);
7636 cmd_so_set_checkbox (WorkbookControl
*wbc
,
7637 SheetObject
*so
, GnmExprTop
const *lnk
,
7638 char *old_label
, char *new_label
)
7640 CmdSOSetCheckbox
*me
;
7642 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
7644 me
= g_object_new (CMD_SO_SET_CHECKBOX_TYPE
, NULL
);
7645 me
->cmd
.sheet
= sheet_object_get_sheet (so
);
7647 me
->cmd
.cmd_descriptor
= g_strdup (_("Configure Checkbox"));
7650 me
->old_label
= old_label
;
7651 me
->new_label
= new_label
;
7653 me
->old_link
= sheet_widget_checkbox_get_link (so
);
7655 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
7658 /******************************************************************/
7660 #define CMD_SO_SET_ADJUSTMENT_TYPE (cmd_so_set_adjustment_get_type ())
7661 #define CMD_SO_SET_ADJUSTMENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_SO_SET_ADJUSTMENT_TYPE, CmdSOSetAdjustment))
7666 GnmExprTop
const *new_link
;
7667 GnmExprTop
const *old_link
;
7672 gboolean old_horizontal
;
7673 } CmdSOSetAdjustment
;
7675 MAKE_GNM_COMMAND (CmdSOSetAdjustment
, cmd_so_set_adjustment
, NULL
)
7678 cmd_so_set_adjustment_adj (CmdSOSetAdjustment
*me
)
7680 GtkAdjustment
*adj
= sheet_widget_adjustment_get_adjustment (me
->so
);
7682 double old_lower
= gtk_adjustment_get_lower (adj
);
7683 double old_upper
= gtk_adjustment_get_upper (adj
);
7684 double old_step
= gtk_adjustment_get_step_increment (adj
);
7685 double old_page
= gtk_adjustment_get_page_increment (adj
);
7686 gboolean old_horizontal
;
7687 g_object_get (G_OBJECT (me
->so
), "horizontal", &old_horizontal
, NULL
);
7689 gtk_adjustment_configure (adj
,
7690 gtk_adjustment_get_value (adj
),
7695 gtk_adjustment_get_page_size (adj
));
7696 g_object_set (G_OBJECT (me
->so
), "horizontal", me
->old_horizontal
, NULL
);
7698 me
->old_lower
= old_lower
;
7699 me
->old_upper
= old_upper
;
7700 me
->old_step
= old_step
;
7701 me
->old_page
= old_page
;
7702 me
->old_horizontal
= old_horizontal
;
7706 cmd_so_set_adjustment_redo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7708 CmdSOSetAdjustment
*me
= CMD_SO_SET_ADJUSTMENT (cmd
);
7710 sheet_widget_adjustment_set_link (me
->so
, me
->new_link
);
7711 cmd_so_set_adjustment_adj (me
);
7716 cmd_so_set_adjustment_undo (GnmCommand
*cmd
, G_GNUC_UNUSED WorkbookControl
*wbc
)
7718 CmdSOSetAdjustment
*me
= CMD_SO_SET_ADJUSTMENT (cmd
);
7720 sheet_widget_adjustment_set_link (me
->so
, me
->old_link
);
7721 cmd_so_set_adjustment_adj (me
);
7727 cmd_so_set_adjustment_finalize (GObject
*cmd
)
7729 CmdSOSetAdjustment
*me
= CMD_SO_SET_ADJUSTMENT (cmd
);
7732 gnm_expr_top_unref (me
->new_link
);
7734 gnm_expr_top_unref (me
->old_link
);
7735 gnm_command_finalize (cmd
);
7739 cmd_so_set_adjustment (WorkbookControl
*wbc
,
7740 SheetObject
*so
, GnmExprTop
const *lnk
,
7741 gboolean horizontal
,
7742 int lower
, int upper
,
7744 char const *undo_label
)
7746 CmdSOSetAdjustment
*me
;
7748 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
7750 me
= g_object_new (CMD_SO_SET_ADJUSTMENT_TYPE
, NULL
);
7751 me
->cmd
.sheet
= sheet_object_get_sheet (so
);
7753 me
->cmd
.cmd_descriptor
= g_strdup ((undo_label
== NULL
) ?
7754 _("Configure Adjustment") : _(undo_label
));
7757 me
->old_lower
= lower
;
7758 me
->old_upper
= upper
;
7759 me
->old_step
= step
;
7760 me
->old_page
= page
;
7761 me
->old_horizontal
= horizontal
;
7763 me
->old_link
= sheet_widget_adjustment_get_link (so
);
7765 return gnm_command_push_undo (wbc
, G_OBJECT (me
));
7768 /******************************************************************/
7771 cmd_autofilter_add_remove (WorkbookControl
*wbc
)
7773 SheetView
*sv
= wb_control_cur_sheet_view (wbc
);
7774 GnmFilter
*f
= sv_editpos_in_filter (sv
);
7775 gboolean add
= (f
== NULL
);
7776 char *descr
= NULL
, *name
= NULL
;
7777 GOUndo
*undo
= NULL
;
7778 GOUndo
*redo
= NULL
;
7784 GnmRange
const *src
= selection_first_range (sv
,
7785 GO_CMD_CONTEXT (wbc
), _("Add Filter"));
7786 GnmFilter
*f_old
= NULL
;
7791 f_old
= gnm_sheet_filter_intersect_rows
7792 (sv
->sheet
, src
->start
.row
, src
->end
.row
);
7794 if (f_old
!= NULL
) {
7795 GnmRange
*r
= gnm_sheet_filter_can_be_extended
7796 (sv
->sheet
, f_old
, src
);
7799 name
= undo_range_name (sv
->sheet
, &(f_old
->r
));
7800 error
= g_strdup_printf
7801 (_("Auto Filter blocked by %s"),
7804 go_cmd_context_error_invalid
7805 (GO_CMD_CONTEXT (wbc
),
7806 _("AutoFilter"), error
);
7810 /* extending existing filter. */
7811 undo
= go_undo_binary_new
7812 (gnm_filter_ref (f_old
), sv
->sheet
,
7813 (GOUndoBinaryFunc
) gnm_filter_attach
,
7814 (GFreeFunc
) gnm_filter_unref
,
7816 redo
= go_undo_unary_new
7817 (gnm_filter_ref (f_old
),
7818 (GOUndoUnaryFunc
) gnm_filter_remove
,
7819 (GFreeFunc
) gnm_filter_unref
);
7820 gnm_filter_remove (f_old
);
7824 /* if only one row is selected
7825 * assume that the user wants to
7826 * filter the region below this row. */
7828 if (src
->start
.row
== src
->end
.row
)
7829 gnm_sheet_guess_region (sv
->sheet
, ®ion
);
7830 if (region
.start
.row
== region
.end
.row
) {
7831 go_cmd_context_error_invalid
7832 (GO_CMD_CONTEXT (wbc
),
7834 _("Requires more than 1 row"));
7838 f
= gnm_filter_new (sv
->sheet
, ®ion
);
7840 go_cmd_context_error_invalid
7841 (GO_CMD_CONTEXT (wbc
),
7843 _("Unable to create Autofilter"));
7845 gnm_filter_attach (f_old
, sv
->sheet
);
7849 gnm_filter_remove (f
);
7851 gnm_filter_attach (f_old
, sv
->sheet
);
7853 redo
= go_undo_combine (go_undo_binary_new
7854 (gnm_filter_ref (f
), sv
->sheet
,
7855 (GOUndoBinaryFunc
) gnm_filter_attach
,
7856 (GFreeFunc
) gnm_filter_unref
,
7858 undo
= go_undo_combine (undo
,
7861 (GOUndoUnaryFunc
) gnm_filter_remove
,
7862 (GFreeFunc
) gnm_filter_unref
));
7864 name
= undo_range_name (sv
->sheet
, &(f
->r
));
7865 descr
= g_strdup_printf
7866 ((f_old
== NULL
) ? _("Add Autofilter to %s")
7867 : _("Extend Autofilter to %s"),
7870 undo
= go_undo_binary_new
7871 (gnm_filter_ref (f
), sv
->sheet
,
7872 (GOUndoBinaryFunc
) gnm_filter_attach
,
7873 (GFreeFunc
) gnm_filter_unref
,
7875 redo
= go_undo_unary_new
7876 (gnm_filter_ref (f
),
7877 (GOUndoUnaryFunc
) gnm_filter_remove
,
7878 (GFreeFunc
) gnm_filter_unref
);
7879 name
= undo_range_name (sv
->sheet
, &(f
->r
));
7880 descr
= g_strdup_printf (_("Remove Autofilter from %s"),
7883 result
= cmd_generic (wbc
, descr
, undo
, redo
);
7891 /******************************************************************/
7893 gboolean
cmd_autofilter_set_condition (WorkbookControl
*wbc
,
7894 GnmFilter
*filter
, unsigned i
,
7895 GnmFilterCondition
*cond
)
7897 char *descr
= NULL
, *name
= NULL
;
7898 GOUndo
*undo
= NULL
;
7899 GOUndo
*redo
= NULL
;
7902 undo
= gnm_undo_filter_set_condition_new (filter
, i
,
7904 g_return_val_if_fail (undo
!= NULL
, TRUE
);
7905 redo
= gnm_undo_filter_set_condition_new (filter
, i
,
7907 g_return_val_if_fail (redo
!= NULL
, TRUE
);
7909 name
= undo_range_name (filter
->sheet
, &(filter
->r
));
7910 descr
= g_strdup_printf (_("Change filter condition for %s"),
7913 result
= cmd_generic (wbc
, descr
, undo
, redo
);
7921 /******************************************************************/
7924 cmd_page_breaks_set_breaks (Sheet
*sheet
,
7925 GnmPageBreaks
const *breaks
)
7927 print_info_set_breaks (sheet
->print_info
, gnm_page_breaks_dup (breaks
));
7929 SHEET_FOREACH_CONTROL (sheet
, sv
, sc
, wb_control_menu_state_update (sc_wbc (sc
), MS_PAGE_BREAKS
););
7933 cmd_page_breaks_clear (WorkbookControl
*wbc
, Sheet
*sheet
)
7935 GOUndo
*undo
= NULL
;
7936 GOUndo
*redo
= NULL
;
7938 g_return_val_if_fail (GNM_IS_WBC (wbc
), TRUE
);
7939 g_return_val_if_fail (sheet
!= NULL
, TRUE
);
7941 if (sheet
->print_info
->page_breaks
.v
!= NULL
) {
7942 redo
= go_undo_binary_new
7944 gnm_page_breaks_new (TRUE
),
7945 (GOUndoBinaryFunc
) cmd_page_breaks_set_breaks
,
7947 (GFreeFunc
) gnm_page_breaks_free
);
7948 undo
= go_undo_binary_new
7951 (sheet
->print_info
->page_breaks
.v
),
7952 (GOUndoBinaryFunc
) cmd_page_breaks_set_breaks
,
7954 (GFreeFunc
) gnm_page_breaks_free
);
7957 if (sheet
->print_info
->page_breaks
.h
!= NULL
) {
7958 redo
= go_undo_combine
7962 gnm_page_breaks_new (FALSE
),
7963 (GOUndoBinaryFunc
) cmd_page_breaks_set_breaks
,
7965 (GFreeFunc
) gnm_page_breaks_free
));
7967 undo
= go_undo_combine
7972 (sheet
->print_info
->page_breaks
.h
),
7973 (GOUndoBinaryFunc
) cmd_page_breaks_set_breaks
,
7975 (GFreeFunc
) gnm_page_breaks_free
));
7979 return cmd_generic (wbc
, _("Clear All Page Breaks"), undo
, redo
);
7985 cmd_page_break_toggle (WorkbookControl
*wbc
, Sheet
*sheet
, gboolean is_vert
)
7987 SheetView
const *sv
= wb_control_cur_sheet_view (wbc
);
7988 gint col
= sv
->edit_pos
.col
;
7989 gint row
= sv
->edit_pos
.row
;
7990 int rc
= is_vert
? col
: row
;
7991 GnmPageBreaks
*old
, *new, *target
;
7992 GnmPageBreakType type
;
7997 target
= is_vert
? sheet
->print_info
->page_breaks
.v
7998 : sheet
->print_info
->page_breaks
.h
;
8000 old
= (target
== NULL
) ? gnm_page_breaks_new (is_vert
)
8001 : gnm_page_breaks_dup (target
);
8002 new = gnm_page_breaks_dup (old
);
8004 if (gnm_page_breaks_get_break (new, rc
) != GNM_PAGE_BREAK_MANUAL
) {
8005 type
= GNM_PAGE_BREAK_MANUAL
;
8006 label
= is_vert
? _("Remove Column Page Break") : _("Remove Row Page Break");
8008 type
= GNM_PAGE_BREAK_NONE
;
8009 label
= is_vert
? _("Add Column Page Break") : _("Add Row Page Break");
8012 gnm_page_breaks_set_break (new, rc
, type
);
8014 redo
= go_undo_binary_new
8016 (GOUndoBinaryFunc
) cmd_page_breaks_set_breaks
,
8018 (GFreeFunc
) gnm_page_breaks_free
);
8019 undo
= go_undo_binary_new
8021 (GOUndoBinaryFunc
) cmd_page_breaks_set_breaks
,
8023 (GFreeFunc
) gnm_page_breaks_free
);
8025 return cmd_generic (wbc
, label
, undo
, redo
);
8028 /******************************************************************/