/** * gnm_style_default_halign: * @style: * @c: * * Select the appropriate horizontal alignment depending on the style and cell * value. */ GnmHAlign gnm_style_default_halign (GnmStyle const *style, GnmCell const *c) { GnmHAlign align = gnm_style_get_align_h (style); GnmValue *v; if (align != GNM_HALIGN_GENERAL) return align; g_return_val_if_fail (c != NULL, GNM_HALIGN_RIGHT); if (c->base.sheet && c->base.sheet->display_formulas && gnm_cell_has_expr (c)) return GNM_HALIGN_LEFT; for (v = c->value; v != NULL ; ) switch (v->v_any.type) { case VALUE_BOOLEAN: case VALUE_ERROR: return GNM_HALIGN_CENTER; case VALUE_FLOAT: { double a = gnm_style_get_rotation (style); if (a > 0 && a < 180) return GNM_HALIGN_LEFT; return GNM_HALIGN_RIGHT; } case VALUE_ARRAY: /* Tail recurse into the array */ if (v->v_array.x > 0 && v->v_array.y > 0) { v = v->v_array.vals [0][0]; continue; } default: if (gnm_style_get_rotation (style) > 180) return GNM_HALIGN_RIGHT; return GNM_HALIGN_LEFT; } return GNM_HALIGN_RIGHT; }
/* * 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 */ }
/* * write every sheet of the workbook to a roff file * * FIXME: Should roff quote sheet name (and everything else) */ void roff_file_save (GOFileSaver const *fs, GOIOContext *io_context, WorkbookView const *wb_view, GsfOutput *output) { GSList *sheets, *ptr; GnmCell *cell; int row, col, fontsize, v_size; Workbook *wb = wb_view_get_workbook (wb_view); g_return_if_fail (wb != NULL); gsf_output_printf (output, ".\\\" TROFF file\n"); gsf_output_printf (output, ".fo ''%%''\n"); sheets = workbook_sheets (wb); for (ptr = sheets ; ptr != NULL ; ptr = ptr->next) { Sheet *sheet = ptr->data; GnmRange r = sheet_get_extent (sheet, FALSE, TRUE); gsf_output_printf (output, "%s\n\n", sheet->name_unquoted); gsf_output_printf (output, ".TS H\n"); gsf_output_printf (output, "allbox;\n"); for (row = r.start.row; row <= r.end.row; row++) { ColRowInfo const * ri; ri = sheet_row_get_info (sheet, row); if (ri->needs_respan) row_calc_spans ((ColRowInfo *) ri, row, sheet); if (row > r.start.row) gsf_output_printf (output, ".T&\n"); /* define alignments, bold etc. per cell */ v_size = DEFSIZE; for (col = r.start.col; col <= r.end.col; col++) { cell = sheet_cell_get (sheet, col, row); if (col > r.start.col) gsf_output_printf (output, " "); if (!cell) { gsf_output_printf (output, "l"); } else { GnmStyle const *style = gnm_cell_get_style (cell); if (!style) break; if (gnm_style_get_align_h (style) & GNM_HALIGN_RIGHT) gsf_output_printf (output, "r"); else if (gnm_style_get_align_h (style) == GNM_HALIGN_CENTER || /* FIXME : center across selection is different */ gnm_style_get_align_h (style) == GNM_HALIGN_CENTER_ACROSS_SELECTION || gnm_style_get_align_h (style) == GNM_HALIGN_DISTRIBUTED) gsf_output_printf (output, "c"); else gsf_output_printf (output, "l"); if (font_is_monospaced (style)) { if (gnm_style_get_font_bold (style) && gnm_style_get_font_italic (style)) gsf_output_printf (output, "fCBI"); else if (gnm_style_get_font_bold (style)) gsf_output_printf (output, "fCB"); else if (gnm_style_get_font_italic (style)) gsf_output_printf (output, "fCI"); else gsf_output_printf (output, "fCR"); } else if (font_is_helvetica (style)) { if (gnm_style_get_font_bold (style) && gnm_style_get_font_italic (style)) gsf_output_printf (output, "fHBI"); else if (gnm_style_get_font_bold (style)) gsf_output_printf (output, "fHB"); else if (gnm_style_get_font_italic (style)) gsf_output_printf (output, "fHI"); else gsf_output_printf (output, "fHR"); } else { /* default is times */ if (gnm_style_get_font_bold (style) && gnm_style_get_font_italic (style)) gsf_output_printf (output, "fTBI"); else if (gnm_style_get_font_bold (style)) gsf_output_printf (output, "fTB"); else if (gnm_style_get_font_italic (style)) gsf_output_printf (output, "fTI"); } fontsize = gnm_style_get_font_size (style); if (fontsize) { gsf_output_printf (output, "p%d", fontsize); v_size = v_size > fontsize ? v_size : fontsize; } } } gsf_output_printf (output, ".\n"); gsf_output_printf (output, ".vs %.2fp\n", 2.5 + v_size); for (col = r.start.col; col <= r.end.col; col++) { if (col > r.start.col) gsf_output_printf (output, "\t"); cell = sheet_cell_get (sheet, col, row); if (!cell) { /* empty cell */ gsf_output_printf (output, " "); } else { roff_fprintf (output, cell); } } gsf_output_printf (output, "\n"); if (row == r.start.row) gsf_output_printf (output, ".TH\n"); } gsf_output_printf (output, ".TE\n\n"); } g_slist_free (sheets); }