Пример #1
0
void
row_calc_spans (ColRowInfo *ri, int row, Sheet const *sheet)
{
	int left, right, col;
	GnmRange const *merged;
	GnmCell *cell;
	int const last = sheet->cols.max_used;

	row_destroy_span (ri);
	for (col = 0 ; col <= last ; ) {
		cell = sheet_cell_get (sheet, col, row);
		if (cell == NULL) {
			/* skip segments with no cells */
			if (col == COLROW_SEGMENT_START (col) &&
			    NULL == COLROW_GET_SEGMENT (&(sheet->cols), col))
				col = COLROW_SEGMENT_END (col) + 1;
			else
				col++;
			continue;
		}

		/* render as necessary */
		(void)gnm_cell_fetch_rendered_value (cell, TRUE);

		if (gnm_cell_is_merged (cell)) {
			merged = gnm_sheet_merge_is_corner (sheet, &cell->pos);
			if (NULL != merged) {
				col = merged->end.col + 1;
				continue;
			}
		}

		cell_calc_span (cell, &left, &right);
		if (left != right) {
			cell_register_span (cell, left, right);
			col = right + 1;
		} else
			col++;
	}

	ri->needs_respan = FALSE;
}
Пример #2
0
/* NOTE : Make sure to set up any merged regions in the target range BEFORE
 * this is called.
 */
static void
paste_link (GnmPasteTarget const *pt, int top, int left,
	    GnmCellRegion const *cr)
{
	GnmCellPos pos;
	GnmCellRef source_cell_ref;
	int x, y;

	/* Not possible to link to arbitrary (non gnumeric) sources yet. */
	/* TODO : eventually support interprocess gnumeric links */
	if (cr->origin_sheet == NULL)
		return;

	/* TODO : support relative links ? */
	source_cell_ref.col_relative = 0;
	source_cell_ref.row_relative = 0;
	source_cell_ref.sheet = (cr->origin_sheet != pt->sheet)
		? cr->origin_sheet : NULL;
	pos.col = left;
	for (x = 0 ; x < cr->cols ; x++, pos.col++) {
		source_cell_ref.col = cr->base.col + x;
		pos.row = top;
		for (y = 0 ; y < cr->rows ; y++, pos.row++) {
			GnmExprTop const *texpr;
			GnmCell *cell =
				sheet_cell_fetch (pt->sheet, pos.col, pos.row);

			/* This could easily be made smarter */
			if (!gnm_cell_is_merged (cell) &&
			    gnm_sheet_merge_contains_pos (pt->sheet, &pos))
					continue;
			source_cell_ref.row = cr->base.row + y;
			texpr = gnm_expr_top_new (gnm_expr_new_cellref (&source_cell_ref));
			gnm_cell_set_expr (cell, texpr);
			gnm_expr_top_unref (texpr);
		}
	}
}
Пример #3
0
/*
 * cell_calc_span:
 * @cell:   The cell we will examine
 * @col1:   return value: the first column used by this cell
 * @col2:   return value: the last column used by this cell
 *
 * This routine returns the column interval used by a GnmCell.
 */
void
cell_calc_span (GnmCell const *cell, int *col1, int *col2)
{
	Sheet *sheet;
	int h_align, v_align, left, max_col, min_col;
	int row, pos;
	int cell_width_pixel, indented_w;
	GnmStyle const *style;
	ColRowInfo const *ci;
	GnmRange const *merge_left;
	GnmRange const *merge_right;

	g_return_if_fail (cell != NULL);

	sheet = cell->base.sheet;
	style = gnm_cell_get_style (cell);
	h_align = gnm_style_default_halign (style, cell);

        /*
	 * Report only one column is used if
	 *	- Cell is in a hidden col
	 *	- Cell is a number
	 *	- Cell is the top left of a merged cell
	 *	- The text fits inside column (for non center across selection)
	 *	- The alignment mode are set to "justify"
	 */
	if (sheet != NULL &&
	    h_align != HALIGN_CENTER_ACROSS_SELECTION &&
	    (gnm_cell_is_merged (cell) ||
	     (!sheet->display_formulas && gnm_cell_is_number (cell)))) {
		*col1 = *col2 = cell->pos.col;
		return;
	}

	v_align = gnm_style_get_align_v (style);
	row   = cell->pos.row;
	indented_w = cell_width_pixel = gnm_cell_rendered_width (cell);
	if (h_align == HALIGN_LEFT || h_align == HALIGN_RIGHT) {
		indented_w += gnm_cell_rendered_offset (cell);
		if (sheet->text_is_rtl)
			h_align = (h_align == HALIGN_LEFT) ? HALIGN_RIGHT : HALIGN_LEFT;
	}

	ci = sheet_col_get_info	(sheet, cell->pos.col);
	if (gnm_cell_is_empty (cell) ||
	    !ci->visible ||
	    (h_align != HALIGN_CENTER_ACROSS_SELECTION &&
		 (gnm_style_get_wrap_text (style) ||
		  indented_w <= COL_INTERNAL_WIDTH (ci))) ||
	    h_align == HALIGN_JUSTIFY ||
	    h_align == HALIGN_FILL ||
	    h_align == HALIGN_DISTRIBUTED ||
	    v_align == VALIGN_JUSTIFY ||
	    v_align == VALIGN_DISTRIBUTED) {
		*col1 = *col2 = cell->pos.col;
		return;
	}

	gnm_sheet_merge_get_adjacent (sheet, &cell->pos, &merge_left, &merge_right);
	min_col = (merge_left != NULL) ? merge_left->end.col : -1;
	max_col = (merge_right != NULL) ? merge_right->start.col : gnm_sheet_get_max_cols (sheet);

	*col1 = *col2 = cell->pos.col;
	switch (h_align) {
	case HALIGN_LEFT:
		pos = cell->pos.col + 1;
		left = indented_w - COL_INTERNAL_WIDTH (ci);

		for (; left > 0 && pos < max_col; pos++){
			ColRowInfo const *ci = sheet_col_get_info (sheet, pos);

			if (ci->visible) {
				if (!cellspan_is_empty (pos, cell))
					return;

				/* The space consumed is:
				 *   - The margin_b from the last column
				 *   - The width of the cell
				 */
				left -= ci->size_pixels - 1;
				*col2 = pos;
			}
		}
		return;

	case HALIGN_RIGHT:
		pos = cell->pos.col - 1;
		left = indented_w - COL_INTERNAL_WIDTH (ci);

		for (; left > 0 && pos > min_col; pos--){
			ColRowInfo const *ci = sheet_col_get_info (sheet, pos);

			if (ci->visible) {
				if (!cellspan_is_empty (pos, cell))
					return;

				/* The space consumed is:
				 *   - The margin_a from the last column
				 *   - The width of this cell
				 */
				left -= ci->size_pixels - 1;
				*col1 = pos;
			}
		}
		return;

	case HALIGN_CENTER: {
		int remain_left, remain_right;
		int pos_l, pos_r;

		pos_l = pos_r = cell->pos.col;
		left = cell_width_pixel - COL_INTERNAL_WIDTH (ci);

		remain_left  = left / 2 + (left % 2);
		remain_right = left / 2;

		for (; remain_left > 0 || remain_right > 0;){
			ColRowInfo const *ci;

			if (--pos_l > min_col){
				ci = sheet_col_get_info (sheet, pos_l);

				if (ci->visible) {
					if (cellspan_is_empty (pos_l, cell)) {
						remain_left -= ci->size_pixels - 1;
						*col1 = pos_l;
					} else
						remain_left = 0;
				}
			} else
				remain_left = 0;

			if (++pos_r < max_col){
				ci = sheet_col_get_info (sheet, pos_r);

				if (ci->visible) {
					if (cellspan_is_empty (pos_r, cell)) {
						remain_right -= ci->size_pixels - 1;
						*col2 = pos_r;
					} else
						max_col = remain_right = 0;
				}
			} else
				remain_right = 0;
		} /* for */
		break;
	} /* case HALIGN_CENTER */

	case HALIGN_CENTER_ACROSS_SELECTION: {
		int const row = cell->pos.row;
		int pos_l, pos_r;

		pos_l = pos_r = cell->pos.col;
		while (--pos_l > min_col) {
			ColRowInfo const *ci = sheet_col_get_info (sheet, pos_l);
			if (ci->visible) {
				if (cellspan_is_empty (pos_l, cell)) {
					GnmStyle const * const style =
						sheet_style_get (cell->base.sheet, pos_l, row);

					if (gnm_style_get_align_h (style) != HALIGN_CENTER_ACROSS_SELECTION)
						break;
					*col1 = pos_l;
				} else
					break;
			}
		}
		while (++pos_r < max_col) {
			ColRowInfo const *ci = sheet_col_get_info (sheet, pos_r);
			if (ci->visible) {
				if (cellspan_is_empty (pos_r, cell)) {
					GnmStyle const * const style =
						sheet_style_get (cell->base.sheet, pos_r, row);

					if (gnm_style_get_align_h (style) != HALIGN_CENTER_ACROSS_SELECTION)
						break;
					*col2 = pos_r;
				} else
					break;
			}
		}
		break;
	}

	default:
		g_warning ("Unknown horizontal alignment type %x.", h_align);
	} /* switch */
}