Example #1
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 */
}
Example #2
0
static void
write_cell (GsfOutput *output, Sheet *sheet, gint row, gint col, html_version_t version, gboolean is_merge)
{
	GnmCell *cell;
	GnmStyle const *style;
	guint r, g, b;

	style = sheet_style_get (sheet, col, row);
	if (style != NULL && version != HTML32 && version != HTML40 &&
	    gnm_style_get_pattern (style) != 0 &&
	    gnm_style_is_element_set (style, MSTYLE_COLOR_BACK)) {
		html_get_back_color (style, &r, &g, &b);
		gsf_output_printf (output, " bgcolor=\"#%02X%02X%02X\"", r, g, b);
	}

	cell = sheet_cell_get (sheet, col, row);
	if (cell != NULL) {

		switch (gnm_style_get_align_v (style)) {
		case GNM_VALIGN_TOP:
			gsf_output_puts (output, " valign=\"top\" ");
			break;
		case GNM_VALIGN_BOTTOM:
			gsf_output_puts (output, " valign=\"bottom\" ");
			break;
		case GNM_VALIGN_DISTRIBUTED:
		case GNM_VALIGN_CENTER:
			gsf_output_puts (output, " valign=\"center\" ");
			break;
		case GNM_VALIGN_JUSTIFY:
			gsf_output_puts (output, " valign=\"baseline\" ");
			break;
		default:
			break;
		}
		switch (gnm_style_default_halign (style, cell)) {
		case GNM_HALIGN_RIGHT:
			gsf_output_puts (output, " align=\"right\" ");
			break;
		case GNM_HALIGN_DISTRIBUTED:
		case GNM_HALIGN_CENTER:
		case GNM_HALIGN_CENTER_ACROSS_SELECTION:
			gsf_output_puts (output, " align=\"center\" ");
			break;
		case GNM_HALIGN_LEFT:
			gsf_output_puts (output, " align=\"left\" ");
			break;
		case GNM_HALIGN_JUSTIFY:
			gsf_output_puts (output, " align=\"justify\" ");
			break;
		default:
			break;
		}

	}
	if (version == HTML40 || version == HTML40F  || version ==XHTML) {
		if (style != NULL) {
			gsf_output_printf (output, " style=\"");
			if (gnm_style_get_pattern (style) != 0 &&
			    gnm_style_is_element_set (style, MSTYLE_COLOR_BACK)) {
				html_get_back_color (style, &r, &g, &b);
				gsf_output_printf (output, "background:#%02X%02X%02X;", r, g, b);
			}
			if (cell != NULL) {
				gint size = (int) (gnm_style_get_font_size (style) + 0.5);
				gsf_output_printf (output, " font-size:%ipt;", size);
				html_get_text_color (cell, style, &r, &g, &b);
				if (r > 0 || g > 0 || b > 0)
					gsf_output_printf (output, " color:#%02X%02X%02X;", r, g, b);
				if (gnm_style_get_contents_hidden (style))
					gsf_output_puts (output, " visibility:hidden;");
			}
			if (is_merge)
				html_write_border_style_40_for_merged_cell (output, style, sheet, row, col);
			else
				html_write_border_style_40 (output, style);
			gsf_output_printf (output, "\"");
		}
	}
	gsf_output_printf (output, ">");
	html_write_cell_content (output, cell, style, version);
	gsf_output_puts (output, "</td>\n");
}