/** * gnm_app_clipboard_cut_copy: * @wbc: the workbook control that requested the operation. * @is_cut: is this a cut or a copy. * @sv: The source sheet for the copy. * @area: A single rectangular range to be copied. * @animate_range: Do we want ot add an animated cursor around things. * * When Cutting we * Clear and free the contents of the clipboard and save the sheet and area * to be cut. DO NOT ACTUALLY CUT! Paste will move the region if this was a * cut operation. * * When Copying we * Clear and free the contents of the clipboard and COPY the designated region * into the clipboard. * * we need to pass @wbc as a control rather than a simple command-context so * that the control can claim the selection. **/ void gnm_app_clipboard_cut_copy (WorkbookControl *wbc, gboolean is_cut, SheetView *sv, GnmRange const *area, gboolean animate_cursor) { Sheet *sheet; g_return_if_fail (IS_SHEET_VIEW (sv)); g_return_if_fail (area != NULL); g_return_if_fail (app != NULL); gnm_app_clipboard_clear (FALSE); sheet = sv_sheet (sv); g_free (app->clipboard_cut_range); app->clipboard_cut_range = gnm_range_dup (area); sv_weak_ref (sv, &(app->clipboard_sheet_view)); if (!is_cut) app->clipboard_copied_contents = clipboard_copy_range (sheet, area); if (animate_cursor) { GList *l = g_list_append (NULL, (gpointer)area); sv_ant (sv, l); g_list_free (l); } if (wb_control_claim_selection (wbc)) { g_signal_emit (G_OBJECT (app), signals[CLIPBOARD_MODIFIED], 0); } else { gnm_app_clipboard_clear (FALSE); g_warning ("Unable to set selection ?"); } }
/** * gnm_app_clipboard_cut_copy_obj: * @wbc: #WorkbookControl * @is_cut: * @sv: #SheetView * @objects: (element-type SheetObject): a list of #SheetObject which is freed * * Different than copying/cutting a region, this can actually cuts an object **/ void gnm_app_clipboard_cut_copy_obj (WorkbookControl *wbc, gboolean is_cut, SheetView *sv, GSList *objects) { g_return_if_fail (IS_SHEET_VIEW (sv)); g_return_if_fail (objects != NULL); g_return_if_fail (app != NULL); gnm_app_clipboard_clear (FALSE); g_free (app->clipboard_cut_range); app->clipboard_cut_range = NULL; sv_weak_ref (sv, &(app->clipboard_sheet_view)); app->clipboard_copied_contents = clipboard_copy_obj (sv_sheet (sv), objects); if (is_cut) { cmd_objects_delete (wbc, objects, _("Cut Object")); objects = NULL; } if (wb_control_claim_selection (wbc)) { g_signal_emit (G_OBJECT (app), signals[CLIPBOARD_MODIFIED], 0); } else { gnm_app_clipboard_clear (FALSE); g_warning ("Unable to set selection ?"); } g_slist_free (objects); }
/** * sv_menu_enable_insert : * @sv : * @col : * @row : * * control whether or not it is ok to insert cols or rows. An internal routine * used by the selection mechanism to avoid erasing the entire sheet when * inserting the wrong dimension. */ static void sv_menu_enable_insert (SheetView *sv, gboolean col, gboolean row) { int flags = 0; g_return_if_fail (IS_SHEET_VIEW (sv)); if (sv->enable_insert_cols != col) { flags |= MS_INSERT_COLS; sv->enable_insert_cols = col; } if (sv->enable_insert_rows != row) { flags |= MS_INSERT_ROWS; sv->enable_insert_rows = row; } if (sv->enable_insert_cells != (col|row)) { flags |= MS_INSERT_CELLS; sv->enable_insert_cells = (col|row); } /* during initialization it does not matter */ if (!flags || sv->sheet == NULL) return; WORKBOOK_VIEW_FOREACH_CONTROL(sv_wbv (sv), wbc, wb_control_menu_state_update (wbc, flags););
/** * sv_selection_row_type : * @sv : * @col : * * Returns How much of column @col is selected in @sv. **/ ColRowSelectionType sv_selection_row_type (SheetView const *sv, int row) { GSList *ptr; GnmRange const *sr; int ret = COL_ROW_NO_SELECTION; g_return_val_if_fail (IS_SHEET_VIEW (sv), COL_ROW_NO_SELECTION); if (sv->selections == NULL) return COL_ROW_NO_SELECTION; for (ptr = sv->selections; ptr != NULL; ptr = ptr->next) { sr = ptr->data; if (sr->start.row > row || sr->end.row < row) continue; if (sr->start.col == 0 && sr->end.col == gnm_sheet_get_last_col (sv->sheet)) return COL_ROW_FULL_SELECTION; ret = COL_ROW_PARTIAL_SELECTION; } return ret; }
/** * sv_is_full_colrow_selected * @sv : * @is_cols : * @index : * * Returns TRUE if all of the selected cols/rows in the selection * are fully selected and the selection contains the specified col. **/ gboolean sv_is_full_colrow_selected (SheetView const *sv, gboolean is_cols, int index) { GSList *l; gboolean found = FALSE; g_return_val_if_fail (IS_SHEET_VIEW (sv), FALSE); for (l = sv->selections; l != NULL; l = l->next){ GnmRange const *r = l->data; if (is_cols) { if (r->start.row > 0 || r->end.row < gnm_sheet_get_last_row (sv->sheet)) return FALSE; if (r->start.col <= index && index <= r->end.col) found = TRUE; } else { if (r->start.col > 0 || r->end.col < gnm_sheet_get_last_col (sv->sheet)) return FALSE; if (r->start.row <= index && index <= r->end.row) found = TRUE; } } return found; }
/** * sv_select_cur_inputs : * @sv: The sheet * * Select all cells that are direct potential inputs to the * current cell. **/ void sv_select_cur_inputs (SheetView *sv) { GnmCell *cell; GSList *ranges, *ptr; GnmEvalPos ep; g_return_if_fail (IS_SHEET_VIEW (sv)); cell = sheet_cell_get (sv->sheet, sv->edit_pos.col, sv->edit_pos.row); if (cell == NULL || !gnm_cell_has_expr (cell)) return; ranges = gnm_expr_top_get_ranges (cell->base.texpr); if (ranges == NULL) return; ep.eval = sv->edit_pos; ep.sheet = sv->sheet; ep.dep = NULL; sv_selection_reset (sv); for (ptr = ranges ; ptr != NULL ; ptr = ptr->next) { GnmValue *v = ptr->data; GnmRangeRef const *r = value_get_rangeref (v); #warning "FIXME: What do we do in these 3D cases?" if (r->a.sheet != r->b.sheet) continue; if (r->a.sheet != NULL && r->a.sheet != sv->sheet) continue; sv_selection_add_full (sv, gnm_cellref_get_col (&r->a, &ep), gnm_cellref_get_row (&r->a, &ep), gnm_cellref_get_col (&r->a, &ep), gnm_cellref_get_row (&r->a, &ep), gnm_cellref_get_col (&r->b, &ep), gnm_cellref_get_row (&r->b, &ep)); value_release (v); } g_slist_free (ranges); sheet_update (sv->sheet); }
/** * sv_select_cur_depends : * @sv: The sheet * * Select all cells that depend on the expression in the current cell. */ void sv_select_cur_depends (SheetView *sv) { GnmCell *cur_cell, dummy; GList *deps = NULL, *ptr = NULL; g_return_if_fail (IS_SHEET_VIEW (sv)); cur_cell = sheet_cell_get (sv->sheet, sv->edit_pos.col, sv->edit_pos.row); if (cur_cell == NULL) { dummy.base.sheet = sv_sheet (sv); dummy.pos = sv->edit_pos; cur_cell = &dummy; } cell_foreach_dep (cur_cell, cb_collect_deps, &deps); if (deps == NULL) return; sv_selection_reset (sv); /* Short circuit */ if (g_list_length (deps) == 1) { GnmCell *cell = deps->data; sv_selection_add_pos (sv, cell->pos.col, cell->pos.row); } else { GnmRange *cur = NULL; ptr = NULL; /* Merge the sorted list of cells into rows */ for (deps = g_list_sort (deps, &cb_compare_deps) ; deps ; ) { GnmCell *cell = deps->data; if (cur == NULL || cur->end.row != cell->pos.row || cur->end.col+1 != cell->pos.col) { if (cur) ptr = g_list_prepend (ptr, cur); cur = g_new (GnmRange, 1); cur->start.row = cur->end.row = cell->pos.row; cur->start.col = cur->end.col = cell->pos.col; } else cur->end.col = cell->pos.col; deps = g_list_remove (deps, cell); } if (cur) ptr = g_list_prepend (ptr, cur); /* Merge the coalesced rows into ranges */ deps = ptr; for (ptr = NULL ; deps ; ) { GnmRange *r1 = deps->data; GList *fwd; for (fwd = deps->next ; fwd ; ) { GnmRange *r2 = fwd->data; if (r1->start.col == r2->start.col && r1->end.col == r2->end.col && r1->start.row-1 == r2->end.row) { r1->start.row = r2->start.row; g_free (fwd->data); fwd = g_list_remove (fwd, r2); } else fwd = fwd->next; } ptr = g_list_prepend (ptr, r1); deps = g_list_remove (deps, r1); } /* now select the ranges */ while (ptr) { sv_selection_add_range (sv, ptr->data); g_free (ptr->data); ptr = g_list_remove (ptr, ptr->data); } } sheet_update (sv->sheet); }