/** * 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; }
GnmRange * range_init_rows (GnmRange *r, Sheet const *sheet, int start_row, int end_row) { r->start.col = 0; r->start.row = start_row; r->end.col = gnm_sheet_get_last_col (sheet); r->end.row = end_row; return r; }
/** * range_ensure_sanity : * @range : the range to check * @sheet : the sheet in which @range lives * * Silently clip a range to ensure that it does not contain areas * outside the valid bounds. Does NOT fix inverted ranges. **/ void range_ensure_sanity (GnmRange *range, Sheet const *sheet) { range->start.col = MAX (0, range->start.col); range->end.col = MIN (range->end.col, gnm_sheet_get_last_col (sheet)); range->start.row = MAX (0, range->start.row); range->end.row = MIN (range->end.row, gnm_sheet_get_last_row (sheet)); }
GnmRange * range_init_full_sheet (GnmRange *r, Sheet const *sheet) { r->start.col = 0; r->start.row = 0; r->end.col = gnm_sheet_get_last_col (sheet); r->end.row = gnm_sheet_get_last_row (sheet); return r; }
/** * range_is_full : * @r : the range. * @sheet : the sheet in which @r lives * @horiz : TRUE to check for a horizontal full ref (_cols_ [0..MAX)) * * This determines whether @r completely spans a sheet * in the dimension specified by @horiz. * * Return value: TRUE if it is infinite else FALSE **/ gboolean range_is_full (GnmRange const *r, Sheet const *sheet, gboolean horiz) { if (horiz) return (r->start.col <= 0 && r->end.col >= gnm_sheet_get_last_col (sheet)); else return (r->start.row <= 0 && r->end.row >= gnm_sheet_get_last_row (sheet)); }
/** * sv_select_cur_row: * @sv: The sheet * * Selects an entire row */ void sv_select_cur_row (SheetView *sv) { GnmRange const *sel = selection_first_range (sv, NULL, NULL); if (sel != NULL) { GnmRange r = *sel; sv_selection_reset (sv); sv_selection_add_full (sv, sv->edit_pos.col, sv->edit_pos.row, 0, r.start.row, gnm_sheet_get_last_col (sv->sheet), r.end.row); sheet_update (sv->sheet); } }
/* * sv_is_colrow_selected : * @sv : containing the selection * @colrow: The column or row number we are interested in. * @is_col: A flag indicating whether this it is a column or a row. * * Searches the selection list to see whether the entire col/row specified is * contained by the section regions. Since the selection is stored as the set * overlapping user specifed regions we can safely search for the range directly. * * Eventually to be completely correct and deal with the case of someone manually * selection an entire col/row, in separate chunks, we will need to do something * more advanced. */ gboolean sv_is_colrow_selected (SheetView const *sv, int colrow, gboolean is_col) { GSList *l; for (l = sv->selections; l != NULL; l = l->next) { GnmRange const *ss = l->data; if (is_col) { if (ss->start.row == 0 && ss->end.row >= gnm_sheet_get_last_row (sv->sheet) && ss->start.col <= colrow && colrow <= ss->end.col) return TRUE; } else { if (ss->start.col == 0 && ss->end.col >= gnm_sheet_get_last_col (sv->sheet) && ss->start.row <= colrow && colrow <= ss->end.row) return TRUE; } } return FALSE; }
/** * cmd_shift_rows: * @wbc : The error context. * @sheet the sheet * @col column marking the start of the shift * @start_row first row * @end_row end row * @count numbers of columns to shift. negative numbers will * delete count columns, positive number will insert * count columns. * * Takes the cells in the region (col,start_row):(MAX_COL,end_row) * and copies them @count units (possibly negative) to the right. **/ void cmd_shift_rows (WorkbookControl *wbc, Sheet *sheet, int col, int start_row, int end_row, int count) { GnmExprRelocateInfo rinfo; char *desc; rinfo.reloc_type = GNM_EXPR_RELOCATE_MOVE_RANGE; rinfo.col_offset = count; rinfo.row_offset = 0; rinfo.origin_sheet = rinfo.target_sheet = sheet; rinfo.origin.start.row = start_row; rinfo.origin.start.col = col; rinfo.origin.end.row = end_row; rinfo.origin.end.col = gnm_sheet_get_last_col (sheet); if (count > 0) rinfo.origin.end.col -= count; desc = g_strdup_printf ((start_row != end_row) ? _("Shift rows %s") : _("Shift row %s"), rows_name (start_row, end_row)); cmd_paste_cut (wbc, &rinfo, FALSE, desc); }
/** * pg_get_col_offset: * @x: offset * @col_origin: if not null the origin of the column containing pixel @x is put here * * Return value: Column containing pixel x (and origin in @col_origin) **/ static int pg_get_col_offset (GnmPreviewGrid *pg, int const x, int *col_origin) { int col = 0; int pixel = 1; int w; g_return_val_if_fail (pg != NULL, 0); do { w = pg->defaults.col_width; if (x <= (pixel + w) || w == 0) { if (col_origin) *col_origin = pixel; return col; } pixel += w; } while (++col < gnm_sheet_get_max_cols (pg->sheet)); if (col_origin) *col_origin = pixel; return gnm_sheet_get_last_col (pg->sheet); }
/** * colrow_set_sizes: * @sheet: #Sheet * @is_cols: * @src: * @new_size: * @from: * @to: * * Returns: (transfer full): **/ ColRowStateGroup * colrow_set_sizes (Sheet *sheet, gboolean is_cols, ColRowIndexList *src, int new_size, int from, int to) /* from & to are used to restrict fitting to that range. Pass 0, -1 if you want to use the */ /* whole row/column */ { int i; ColRowStateGroup *res = NULL; ColRowIndexList *ptr; for (ptr = src; ptr != NULL ; ptr = ptr->next) { ColRowIndex const *index = ptr->data; res = g_slist_prepend (res, colrow_get_states (sheet, is_cols, index->first, index->last)); /* FIXME : * If we are changing the size of more than half of the rows/col to * something specific (not autosize) we should change the default * row/col size instead. However, it is unclear how to handle * hard sizing. * * we need better management of rows/cols. Currently if they are all * defined calculation speed grinds to a halt. */ if (new_size > 0 && index->first == 0 && (index->last+1) >= colrow_max (is_cols, sheet)) { struct resize_closure closure; ColRowRLEState *rles = g_new0 (ColRowRLEState, 1); rles->length = -1; /* Flag as changing the default */ closure.sheet = sheet; closure.new_size = new_size; closure.is_cols = is_cols; if (is_cols) { rles->state.size_pts = sheet_col_get_default_size_pts (sheet); sheet_col_set_default_size_pixels (sheet, new_size); colrow_foreach (&sheet->cols, 0, gnm_sheet_get_last_col (sheet), &cb_set_colrow_size, &closure); } else { rles->state.size_pts = sheet_row_get_default_size_pts (sheet); sheet_row_set_default_size_pixels (sheet, new_size); colrow_foreach (&sheet->rows, 0, gnm_sheet_get_last_row (sheet), &cb_set_colrow_size, &closure); } /* force a re-render of cells with expanding formats */ if (is_cols) sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK, 0, 0, gnm_sheet_get_last_col (sheet), gnm_sheet_get_last_row (sheet), (CellIterFunc) &cb_clear_variable_width_content, NULL); /* Result is a magic 'default' record + >= 1 normal */ return g_slist_prepend (res, g_slist_append (NULL, rles)); } if (is_cols) { /* force a re-render of cells with expanding formats */ sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK, index->first, 0, index->last, gnm_sheet_get_last_row (sheet), (CellIterFunc) &cb_clear_variable_width_content, NULL); /* In order to properly reposition cell comments in * merged cells that cross the boundary we need to do * everything. Remove this when comments are handled * properly */ sheet->priv->reposition_objects.col = 0; } for (i = index->first ; i <= index->last ; ++i) { int tmp = new_size; if (tmp < 0) { int max = is_cols ? gnm_sheet_get_last_row (sheet) : gnm_sheet_get_last_col (sheet); if (from < 0) from = 0; if (to < 0 || to > max) to = max; if (from > max) from = to; /* Fall back to assigning the default if it is empty */ tmp = (is_cols) ? sheet_col_size_fit_pixels (sheet, i, from, to, FALSE) : sheet_row_size_fit_pixels (sheet, i, from, to, FALSE); } if (tmp > 0) { if (is_cols) sheet_col_set_size_pixels (sheet, i, tmp, new_size > 0); else sheet_row_set_size_pixels (sheet, i, tmp, new_size > 0); } else if (sheet_colrow_get (sheet, i, is_cols) != NULL) { if (is_cols) sheet_col_set_size_pixels (sheet, i, sheet_col_get_default_size_pixels (sheet), FALSE); else sheet_row_set_size_pixels (sheet, i, sheet_row_get_default_size_pixels (sheet), FALSE); } } } return res; }
/** * range_transpose: * @range: The range. * @sheet : the sheet in which @range lives * @boundary: The box to transpose inside * * Effectively mirrors the ranges in 'boundary' around a * leading diagonal projected from offset. * * Return value: whether we clipped the range. **/ gboolean range_transpose (GnmRange *range, Sheet const *sheet, GnmCellPos const *origin) { gboolean clipped = FALSE; GnmRange src; int t; int last_col = gnm_sheet_get_last_col (sheet); int last_row = gnm_sheet_get_last_row (sheet); g_return_val_if_fail (range != NULL, TRUE); src = *range; /* Start col */ t = origin->col + (src.start.row - origin->row); if (t > last_col) { clipped = TRUE; range->start.col = last_col; } else if (t < 0) { clipped = TRUE; range->start.col = 0; } range->start.col = t; /* Start row */ t = origin->row + (src.start.col - origin->col); if (t > last_row) { clipped = TRUE; range->start.row = last_row; } else if (t < 0) { clipped = TRUE; range->start.row = 0; } range->start.row = t; /* End col */ t = origin->col + (src.end.row - origin->row); if (t > last_col) { clipped = TRUE; range->end.col = last_col; } else if (t < 0) { clipped = TRUE; range->end.col = 0; } range->end.col = t; /* End row */ t = origin->row + (src.end.col - origin->col); if (t > last_row) { clipped = TRUE; range->end.row = last_row; } else if (t < 0) { clipped = TRUE; range->end.row = 0; } range->end.row = t; g_assert (range_valid (range)); return clipped; }