1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * cell.c: Cell content and simple management.
6 * Jody Goldberg 2000-2006 (jody@gnome.org)
7 * Miguel de Icaza 1998, 1999 (miguel@kernel.org)
8 * Copyright (C) 2000-2009 Morten Welinder (terra@gnome.org)
10 #include <gnumeric-config.h>
18 #include "expr-impl.h"
19 #include "rendered-value.h"
23 #include "gnm-format.h"
24 #include "number-match.h"
25 #include "sheet-style.h"
26 #include "parse-util.h"
28 #include <goffice/goffice.h>
39 * - not queued for recalc.
40 * - has no expression.
45 * - unqueue a previously queued recalc.
46 * - Mark sheet as dirty.
49 gnm_cell_cleanout (GnmCell
*cell
)
51 g_return_if_fail (cell
!= NULL
);
53 /* A cell can have either an expression or entered text */
54 if (gnm_cell_has_expr (cell
)) {
55 /* Clipboard cells, e.g., are not attached to a sheet. */
56 if (gnm_cell_expr_is_linked (cell
))
57 dependent_unlink (GNM_CELL_TO_DEP (cell
));
58 gnm_expr_top_unref (cell
->base
.texpr
);
59 cell
->base
.texpr
= NULL
;
62 value_release (cell
->value
);
65 gnm_cell_unrender (cell
);
67 sheet_cell_queue_respan (cell
);
70 /****************************************************************************/
73 * gnm_cell_set_text: Parses the supplied text for storage as a value or
74 * expression. It marks the sheet as dirty.
76 * If the text is an expression it IS queued for recalc.
77 * the format prefered by the expression is stored for later use.
78 * If the text is a value it is rendered and spans are NOT calculated.
79 * the format that matched the text is stored for later use.
81 * WARNING : This is an internal routine that does not queue redraws,
82 * does not auto-resize, and does not calculate spans.
84 * NOTE : This DOES check for array partitioning.
87 gnm_cell_set_text (GnmCell
*cell
, char const *text
)
89 GnmExprTop
const *texpr
;
93 g_return_if_fail (cell
!= NULL
);
94 g_return_if_fail (text
!= NULL
);
95 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
97 parse_text_value_or_expr (parse_pos_init_cell (&pos
, cell
),
100 if (val
!= NULL
) { /* String was a value */
101 gnm_cell_cleanout (cell
);
103 } else { /* String was an expression */
104 gnm_cell_set_expr (cell
, texpr
);
105 gnm_expr_top_unref (texpr
);
110 * gnm_cell_assign_value: Stores (WITHOUT COPYING) the supplied value.
111 * no changes are made to the expression or entered text. This
112 * is for use by routines that wish to store values directly such
113 * as expression calculation or import for array formulas.
115 * WARNING : This is an internal routine that does not
120 * - mark anything as dirty.
122 * NOTE : This DOES NOT check for array partitioning.
125 gnm_cell_assign_value (GnmCell
*cell
, GnmValue
*v
)
127 g_return_if_fail (cell
);
128 g_return_if_fail (v
);
130 value_release (cell
->value
);
135 * gnm_cell_set_value:
138 * Stores (WITHOUT COPYING) the supplied value. It marks the
141 * WARNING : This is an internal routine that does not
147 * NOTE : This DOES check for array partitioning.
150 gnm_cell_set_value (GnmCell
*cell
, GnmValue
*v
)
152 g_return_if_fail (cell
!= NULL
);
153 g_return_if_fail (v
!= NULL
);
154 if (gnm_cell_is_nonsingleton_array (cell
)) {
156 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
159 gnm_cell_cleanout (cell
);
164 * gnm_cell_set_expr_and_value: Stores (WITHOUT COPYING) the supplied value, and
165 * references the supplied expression and links it into the expression
166 * list. It marks the sheet as dirty. It is intended for use by import
167 * routines or operations that do bulk assignment.
169 * WARNING : This is an internal routine that does not queue redraws,
170 * does not auto-resize, does not calculate spans, and does
171 * not render the value.
173 * NOTE : This DOES check for array partitioning.
176 gnm_cell_set_expr_and_value (GnmCell
*cell
, GnmExprTop
const *texpr
, GnmValue
*v
,
179 g_return_if_fail (cell
!= NULL
);
180 g_return_if_fail (texpr
!= NULL
);
181 if (gnm_cell_is_nonsingleton_array (cell
)) {
183 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
186 /* Repeat after me. Ref before unref. */
187 gnm_expr_top_ref (texpr
);
188 gnm_cell_cleanout (cell
);
190 cell
->base
.flags
|= GNM_CELL_HAS_NEW_EXPR
;
191 cell
->base
.texpr
= texpr
;
194 dependent_link (GNM_CELL_TO_DEP (cell
));
198 * cell_set_expr_internal:
199 * @cell: the cell to set the expr for
200 * @expr: an expression
202 * A private internal utility to store an expression.
204 * - check for array subdivision
206 * - render value, calc dimension, compute spans
207 * - link the expression into the master list.
210 cell_set_expr_internal (GnmCell
*cell
, GnmExprTop
const *texpr
)
212 GnmValue
*save_value
;
214 gnm_expr_top_ref (texpr
);
216 /* Don't touch the value. */
217 save_value
= cell
->value
? cell
->value
: value_new_empty ();
219 gnm_cell_cleanout (cell
);
221 cell
->base
.flags
|= GNM_CELL_HAS_NEW_EXPR
;
222 cell
->base
.texpr
= texpr
;
223 cell
->value
= save_value
;
227 * gnm_cell_set_expr_unsafe: Stores and references the supplied expression. It
228 * marks the sheet as dirty. Intented for use by import routines that
229 * do bulk assignment. The resulting cell is NOT linked into the
230 * dependent list. Nor marked for recalc.
232 * WARNING : This is an internal routine that does not queue redraws,
233 * does not auto-resize, and does not calculate spans.
234 * It also DOES NOT CHECK FOR ARRAY DIVISION. Be very careful
238 gnm_cell_set_expr_unsafe (GnmCell
*cell
, GnmExprTop
const *texpr
)
240 g_return_if_fail (cell
!= NULL
);
241 g_return_if_fail (texpr
!= NULL
);
243 cell_set_expr_internal (cell
, texpr
);
247 * gnm_cell_set_expr: Stores and references the supplied expression
248 * marks the sheet as dirty. Intented for use by import routines that
249 * do bulk assignment. The resulting cell _is_ linked into the
250 * dependent list, but NOT marked for recalc.
252 * WARNING : This is an internal routine that does not queue redraws,
253 * does not auto-resize, and does not calculate spans.
254 * Be very careful using this.
257 gnm_cell_set_expr (GnmCell
*cell
, GnmExprTop
const *texpr
)
259 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
260 g_return_if_fail (cell
!= NULL
);
261 g_return_if_fail (texpr
!= NULL
);
263 cell_set_expr_internal (cell
, texpr
);
264 dependent_link (GNM_CELL_TO_DEP (cell
));
268 * gnm_cell_set_array_formula:
269 * @sheet: The sheet to set the expr in.
270 * @cola: The left column in the destination region.
271 * @rowa: The top row in the destination region.
272 * @colb: The right column in the destination region.
273 * @rowb: The bottom row in the destination region.
274 * @texpr: an expression (the inner expression, not a corner or element)
276 * Uses cell_set_expr_internal to store the expr as an
277 * 'array-formula'. The supplied expression is wrapped in an array
278 * operator for each cell in the range and scheduled for recalc.
280 * NOTE : Does not add a reference to the expression. It takes over the
281 * caller's reference.
283 * Does not regenerate spans, dimensions or autosize cols/rows.
285 * DOES NOT CHECK for array partitioning.
288 gnm_cell_set_array_formula (Sheet
*sheet
,
289 int col_a
, int row_a
, int col_b
, int row_b
,
290 GnmExprTop
const *texpr
)
292 int const num_rows
= 1 + row_b
- row_a
;
293 int const num_cols
= 1 + col_b
- col_a
;
296 GnmExprTop
const *wrapper
;
298 g_return_if_fail (sheet
!= NULL
);
299 g_return_if_fail (texpr
!= NULL
);
300 g_return_if_fail (0 <= col_a
);
301 g_return_if_fail (col_a
<= col_b
);
302 g_return_if_fail (col_b
< gnm_sheet_get_max_cols (sheet
));
303 g_return_if_fail (0 <= row_a
);
304 g_return_if_fail (row_a
<= row_b
);
305 g_return_if_fail (row_b
< gnm_sheet_get_max_rows (sheet
));
307 corner
= sheet_cell_fetch (sheet
, col_a
, row_a
);
308 g_return_if_fail (corner
!= NULL
);
310 wrapper
= gnm_expr_top_new_array_corner (num_cols
, num_rows
, gnm_expr_copy (texpr
->expr
));
311 gnm_expr_top_unref (texpr
);
312 cell_set_expr_internal (corner
, wrapper
);
313 gnm_expr_top_unref (wrapper
);
315 for (x
= 0; x
< num_cols
; ++x
) {
316 for (y
= 0; y
< num_rows
; ++y
) {
318 GnmExprTop
const *te
;
320 if (x
== 0 && y
== 0)
323 cell
= sheet_cell_fetch (sheet
, col_a
+ x
, row_a
+ y
);
324 te
= gnm_expr_top_new_array_elem (x
, y
);
325 cell_set_expr_internal (cell
, te
);
326 dependent_link (GNM_CELL_TO_DEP (cell
));
327 gnm_expr_top_unref (te
);
331 dependent_link (GNM_CELL_TO_DEP (corner
));
335 gnm_cell_set_array_formula_cb (GnmSheetRange
const *sr
, GnmExprTop
const *texpr
)
337 sheet_region_queue_recalc (sr
->sheet
, &sr
->range
);
338 gnm_expr_top_ref (texpr
);
339 gnm_cell_set_array_formula (sr
->sheet
,
340 sr
->range
.start
.col
, sr
->range
.start
.row
,
341 sr
->range
.end
.col
, sr
->range
.end
.row
,
343 sheet_region_queue_recalc (sr
->sheet
, &sr
->range
);
344 sheet_flag_status_update_range (sr
->sheet
, &sr
->range
);
345 sheet_queue_respan (sr
->sheet
, sr
->range
.start
.row
, sr
->range
.end
.row
);
349 * gnm_cell_set_array_formula_undo:
353 * Returns: (transfer full): the newly allocated #GOUndo.
356 gnm_cell_set_array_formula_undo (GnmSheetRange
*sr
, GnmExprTop
const *texpr
)
358 gnm_expr_top_ref (texpr
);
359 return go_undo_binary_new (sr
, (gpointer
)texpr
,
360 (GOUndoBinaryFunc
) gnm_cell_set_array_formula_cb
,
361 (GFreeFunc
) gnm_sheet_range_free
,
362 (GFreeFunc
) gnm_expr_top_unref
);
366 * gnm_cell_set_array:
367 * @sheet: The sheet to set the expr in.
368 * @r: The range to set.
369 * @texpr: an expression (the inner expression, not a corner or element)
371 * Set an array expression for a range.
372 * Uses cell_set_expr_internal to store the expr as an
373 * 'array-formula'. The supplied expression is wrapped in an array
374 * operator for each cell in the range and scheduled for recalc.
376 * Returns: TRUE if the operation succeded.
378 * NOTE : This adds a reference to the expression.
380 * Does not regenerate spans, dimensions or autosize cols/rows.
382 * DOES CHECK for array partitioning.
386 gnm_cell_set_array (Sheet
*sheet
,
388 GnmExprTop
const *texpr
)
390 g_return_val_if_fail (sheet
!= NULL
, FALSE
);
391 g_return_val_if_fail (range_is_sane (r
), FALSE
);
392 g_return_val_if_fail (r
->end
.row
< gnm_sheet_get_max_rows (sheet
), FALSE
);
393 g_return_val_if_fail (r
->end
.col
< gnm_sheet_get_max_cols (sheet
), FALSE
);
394 g_return_val_if_fail (texpr
!= NULL
, FALSE
);
396 if (sheet_range_splits_array (sheet
, r
, NULL
, NULL
, NULL
))
399 gnm_expr_top_ref (texpr
);
400 gnm_cell_set_array_formula (sheet
,
401 r
->start
.col
, r
->start
.row
,
402 r
->end
.col
, r
->end
.row
,
407 /***************************************************************************/
413 * If the cell has not been created, or has VALUE_EMPTY.
416 gnm_cell_is_empty (GnmCell
const * cell
)
418 return cell
== NULL
|| VALUE_IS_EMPTY (cell
->value
);
425 * If the cell has not been created, has VALUE_EMPTY, or has a VALUE_STRING == ""
428 gnm_cell_is_blank (GnmCell
const * cell
)
430 return gnm_cell_is_empty (cell
) ||
431 (VALUE_IS_STRING (cell
->value
) &&
432 *value_peek_string (cell
->value
) == '\0');
436 gnm_cell_is_error (GnmCell
const * cell
)
438 g_return_val_if_fail (cell
!= NULL
, NULL
);
439 g_return_val_if_fail (cell
->value
!= NULL
, NULL
);
441 if (VALUE_IS_ERROR (cell
->value
))
447 gnm_cell_is_number (GnmCell
const *cell
)
449 /* FIXME : This does not handle arrays or ranges */
450 return (cell
->value
&& VALUE_IS_NUMBER (cell
->value
));
454 gnm_cell_is_zero (GnmCell
const *cell
)
456 GnmValue
const * const v
= cell
->value
;
457 return v
&& VALUE_IS_NUMBER (v
) && gnm_abs (value_get_as_float (v
)) < 64 * GNM_EPSILON
;
461 gnm_cell_array_bound (GnmCell
const *cell
, GnmRange
*res
)
463 GnmExprTop
const *texpr
;
464 GnmExprArrayCorner
const *array
;
467 if (NULL
== cell
|| !gnm_cell_has_expr (cell
))
470 g_return_val_if_fail (res
!= NULL
, FALSE
);
472 texpr
= cell
->base
.texpr
;
473 if (gnm_expr_top_is_array_elem (texpr
, &x
, &y
)) {
474 cell
= sheet_cell_get (cell
->base
.sheet
, cell
->pos
.col
- x
, cell
->pos
.row
- y
);
476 g_return_val_if_fail (cell
!= NULL
, FALSE
);
477 g_return_val_if_fail (gnm_cell_has_expr (cell
), FALSE
);
479 texpr
= cell
->base
.texpr
;
482 array
= gnm_expr_top_get_array_corner (texpr
);
486 range_init (res
, cell
->pos
.col
, cell
->pos
.row
,
487 cell
->pos
.col
+ array
->cols
- 1,
488 cell
->pos
.row
+ array
->rows
- 1);
492 GnmExprArrayCorner
const *
493 gnm_cell_is_array_corner (GnmCell
const *cell
)
495 return cell
&& gnm_cell_has_expr (cell
)
496 ? gnm_expr_top_get_array_corner (cell
->base
.texpr
)
502 * @cell: #GnmCell const *
504 * Return TRUE is @cell is part of an array
507 gnm_cell_is_array (GnmCell
const *cell
)
509 return cell
!= NULL
&& gnm_cell_has_expr (cell
) &&
510 (gnm_expr_top_is_array_corner (cell
->base
.texpr
) ||
511 gnm_expr_top_is_array_elem (cell
->base
.texpr
, NULL
, NULL
));
515 * gnm_cell_is_nonsingleton_array:
516 * @cell: #GnmCell const *
518 * Return TRUE is @cell is part of an array larger than 1x1
521 gnm_cell_is_nonsingleton_array (GnmCell
const *cell
)
523 GnmExprArrayCorner
const *corner
;
525 if ((cell
== NULL
) || !gnm_cell_has_expr (cell
))
527 if (gnm_expr_top_is_array_elem (cell
->base
.texpr
, NULL
, NULL
))
530 corner
= gnm_expr_top_get_array_corner (cell
->base
.texpr
);
531 return corner
&& (corner
->cols
> 1 || corner
->rows
> 1);
534 /***************************************************************************/
537 * gnm_cell_get_rendered_value: (skip)
543 gnm_cell_get_rendered_value (GnmCell
const *cell
)
545 g_return_val_if_fail (cell
!= NULL
, NULL
);
547 return gnm_rvc_query (cell
->base
.sheet
->rendered_values
, cell
);
551 * gnm_cell_fetch_rendered_value: (skip)
557 gnm_cell_fetch_rendered_value (GnmCell
const *cell
,
558 gboolean allow_variable_width
)
560 GnmRenderedValue
*rv
;
562 g_return_val_if_fail (cell
!= NULL
, NULL
);
564 rv
= gnm_cell_get_rendered_value (cell
);
568 return gnm_cell_render_value (cell
, allow_variable_width
);
572 gnm_cell_unrender (GnmCell
const *cell
)
574 gnm_rvc_remove (cell
->base
.sheet
->rendered_values
, cell
);
578 * gnm_cell_render_value: (skip)
579 * @cell: The cell whose value needs to be rendered
580 * @allow_variable_width: Allow format to depend on column width.
583 gnm_cell_render_value (GnmCell
const *cell
, gboolean allow_variable_width
)
585 GnmRenderedValue
*rv
;
588 g_return_val_if_fail (cell
!= NULL
, NULL
);
590 sheet
= cell
->base
.sheet
;
591 rv
= gnm_rendered_value_new (cell
,
592 sheet
->rendered_values
->context
,
593 allow_variable_width
,
594 sheet
->last_zoom_factor_used
);
596 gnm_rvc_store (sheet
->rendered_values
, cell
, rv
);
602 * gnm_cell_get_rendered_text:
604 * Warning: use this only when you really want what is displayed on the
605 * screen. If the user has decided to display formulas instead of values
606 * then that is what you get.
609 gnm_cell_get_rendered_text (GnmCell
*cell
)
611 GnmRenderedValue
*rv
;
613 g_return_val_if_fail (cell
!= NULL
, g_strdup ("ERROR"));
615 rv
= gnm_cell_fetch_rendered_value (cell
, TRUE
);
617 return g_strdup (gnm_rendered_value_get_text (rv
));
621 * gnm_cell_get_render_color:
622 * @cell: the cell from which we want to pull the color from
624 * The returned value is a pointer to a PangoColor describing
625 * the foreground colour.
628 gnm_cell_get_render_color (GnmCell
const *cell
)
630 GnmRenderedValue
*rv
;
632 g_return_val_if_fail (cell
!= NULL
, GO_COLOR_BLACK
);
634 rv
= gnm_cell_fetch_rendered_value (cell
, TRUE
);
636 return gnm_rendered_value_get_color (rv
);
640 * gnm_cell_get_entered_text:
641 * @cell: the cell from which we want to pull the content from
643 * This returns a g_malloc()ed region of memory with a text representation
644 * of the cell contents.
646 * This will return a text expression if the cell contains a formula, or
647 * a string representation of the value.
650 gnm_cell_get_entered_text (GnmCell
const *cell
)
655 g_return_val_if_fail (cell
!= NULL
, NULL
);
657 sheet
= cell
->base
.sheet
;
659 if (gnm_cell_has_expr (cell
)) {
661 GnmConventionsOut out
;
663 out
.accum
= g_string_new ("=");
664 out
.pp
= parse_pos_init_cell (&pp
, cell
);
665 out
.convs
= sheet
->convs
;
667 gnm_expr_top_as_gstring (cell
->base
.texpr
, &out
);
668 return g_string_free (out
.accum
, FALSE
);
673 GODateConventions
const *date_conv
=
674 workbook_date_conv (sheet
->workbook
);
676 if (VALUE_IS_STRING (v
)) {
677 /* Try to be reasonably smart about adding a leading quote */
678 char const *tmp
= value_peek_string (v
);
680 if (tmp
[0] != '\'' &&
682 !gnm_expr_char_start_p (tmp
)) {
683 GnmValue
*val
= format_match_number
685 gnm_cell_get_format (cell
),
688 return g_strdup (tmp
);
691 return g_strconcat ("\'", tmp
, NULL
);
693 GOFormat
const *fmt
= gnm_cell_get_format (cell
);
694 return format_value (fmt
, v
, -1, date_conv
);
698 g_warning ("A cell with no expression, and no value ??");
699 return g_strdup ("<ERROR>");
703 close_to_int (gnm_float x
, gnm_float eps
)
705 return gnm_abs (x
- gnm_fake_round (x
)) < eps
;
709 guess_time_format (const char *prefix
, gnm_float f
)
712 gnm_float eps
= 1e-6;
713 static int maxdecs
= 6;
714 GString
*str
= g_string_new (prefix
);
718 g_string_append (str
, "hh:mm");
720 g_string_append (str
, "[h]:mm");
722 if (!close_to_int (f
, eps
/ 60)) {
723 g_string_append (str
, ":ss");
725 if (!close_to_int (f
, eps
)) {
726 g_string_append_c (str
, '.');
727 while (decs
< maxdecs
) {
729 g_string_append_c (str
, '0');
731 if (close_to_int (f
, eps
))
737 while (go_format_is_invalid ((fmt
= go_format_new_from_XL (str
->str
))) && decs
> 0) {
738 /* We don't know how many decimals GOFormat allows. */
739 go_format_unref (fmt
);
741 g_string_truncate (str
, str
->len
- 1);
744 g_string_free (str
, TRUE
);
749 * gnm_cell_get_text_for_editing:
750 * @cell: the cell from which we want to pull the content from
752 * The returned value should be g_free'd
754 * Primary user of this function is the formula entry.
755 * This function should return the value most appropriate for
761 gnm_cell_get_text_for_editing (GnmCell
const * cell
, Sheet
*sheet
,
762 gboolean
*quoted
, int *cursor_pos
)
764 GODateConventions
const *date_conv
;
767 g_return_val_if_fail (cell
!= NULL
, NULL
);
768 g_return_val_if_fail (sheet
!= NULL
, NULL
);
773 date_conv
= workbook_date_conv (sheet
->workbook
);
775 if (!gnm_cell_is_array (cell
) &&
776 !gnm_cell_has_expr (cell
) && VALUE_IS_FLOAT (cell
->value
)) {
777 GOFormat
const *fmt
= gnm_cell_get_format (cell
);
778 gnm_float f
= value_get_as_float (cell
->value
);
780 switch (go_format_get_family (fmt
)) {
781 case GO_FORMAT_FRACTION
:
782 text
= gnm_cell_get_entered_text (cell
);
787 case GO_FORMAT_PERCENTAGE
: {
788 GString
*new_str
= g_string_new (NULL
);
789 gnm_render_general (NULL
, new_str
, go_format_measure_zero
,
790 go_font_metrics_unit
, f
* 100,
793 *cursor_pos
= g_utf8_strlen (new_str
->str
, -1);
794 g_string_append_c (new_str
, '%');
795 text
= g_string_free (new_str
, FALSE
);
799 case GO_FORMAT_NUMBER
:
800 case GO_FORMAT_SCIENTIFIC
:
801 case GO_FORMAT_CURRENCY
:
802 case GO_FORMAT_ACCOUNTING
: {
803 GString
*new_str
= g_string_new (NULL
);
804 gnm_render_general (NULL
, new_str
, go_format_measure_zero
,
805 go_font_metrics_unit
, f
,
807 text
= g_string_free (new_str
, FALSE
);
811 case GO_FORMAT_DATE
: {
814 new_fmt
= gnm_format_for_date_editing (cell
);
816 if (!close_to_int (f
, 1e-6 / (24 * 60 * 60))) {
817 GString
*fstr
= g_string_new (go_format_as_XL (new_fmt
));
818 go_format_unref (new_fmt
);
820 g_string_append_c (fstr
, ' ');
821 new_fmt
= guess_time_format
824 g_string_free (fstr
, TRUE
);
827 text
= format_value (new_fmt
, cell
->value
,
829 if (!text
|| text
[0] == 0) {
831 text
= format_value (go_format_general (),
836 go_format_unref (new_fmt
);
840 case GO_FORMAT_TIME
: {
841 GOFormat
*new_fmt
= guess_time_format (NULL
, f
);
843 text
= format_value (new_fmt
, cell
->value
, -1,
845 go_format_unref (new_fmt
);
855 text
= gnm_cell_get_entered_text (cell
);
857 *quoted
= (text
[0] == '\'');
866 * Return the height of the rendered layout after rotation.
869 gnm_cell_rendered_height (GnmCell
const *cell
)
871 const GnmRenderedValue
*rv
;
873 g_return_val_if_fail (cell
!= NULL
, 0);
875 rv
= gnm_cell_get_rendered_value (cell
);
877 ? PANGO_PIXELS (rv
->layout_natural_height
)
882 * Return the width of the rendered layout after rotation.
885 gnm_cell_rendered_width (GnmCell
const *cell
)
887 const GnmRenderedValue
*rv
;
889 g_return_val_if_fail (cell
!= NULL
, 0);
891 rv
= gnm_cell_get_rendered_value (cell
);
893 ? PANGO_PIXELS (rv
->layout_natural_width
)
898 gnm_cell_rendered_offset (GnmCell
const * cell
)
900 const GnmRenderedValue
*rv
;
902 g_return_val_if_fail (cell
!= NULL
, 0);
904 rv
= gnm_cell_get_rendered_value (cell
);
906 ? rv
->indent_left
+ rv
->indent_right
911 gnm_cell_get_style (GnmCell
const *cell
)
913 g_return_val_if_fail (cell
!= NULL
, NULL
);
914 return sheet_style_get (cell
->base
.sheet
,
920 * gnm_cell_get_format_given_style:
924 * Get the display format. If the assigned format is General,
925 * the format of the value will be used.
928 gnm_cell_get_format_given_style (GnmCell
const *cell
, GnmStyle
const *style
)
932 g_return_val_if_fail (cell
!= NULL
, go_format_general ());
935 style
= gnm_cell_get_style (cell
);
937 fmt
= gnm_style_get_format (style
);
939 g_return_val_if_fail (fmt
!= NULL
, go_format_general ());
941 if (go_format_is_general (fmt
) &&
942 cell
->value
!= NULL
&& VALUE_FMT (cell
->value
))
943 fmt
= VALUE_FMT (cell
->value
);
949 * gnm_cell_get_format:
952 * Get the display format. If the assigned format is General,
953 * the format of the value will be used.
956 gnm_cell_get_format (GnmCell
const *cell
)
958 return gnm_cell_get_format_given_style (cell
, NULL
);
962 * gnm_cell_set_format:
964 * Changes the format for CELL to be FORMAT. FORMAT should be
965 * a number display format as specified on the manual
967 * Does not render, redraw, or respan.
970 gnm_cell_set_format (GnmCell
*cell
, char const *format
)
975 g_return_if_fail (cell
!= NULL
);
976 g_return_if_fail (format
!= NULL
);
978 mstyle
= gnm_style_new ();
979 gnm_style_set_format_text (mstyle
, format
);
981 r
.start
= r
.end
= cell
->pos
;
982 sheet_style_apply_range (cell
->base
.sheet
, &r
, mstyle
);
986 cb_set_array_value (GnmCellIter
const *iter
, gpointer user
)
988 GnmValue
const *value
= user
;
989 GnmCell
*cell
= iter
->cell
;
992 /* Clipboard cells, e.g., are not attached to a sheet. */
993 if (gnm_cell_expr_is_linked (cell
))
994 dependent_unlink (GNM_CELL_TO_DEP (cell
));
996 if (!gnm_expr_top_is_array_elem (cell
->base
.texpr
, &x
, &y
))
999 gnm_expr_top_unref (cell
->base
.texpr
);
1000 cell
->base
.texpr
= NULL
;
1001 value_release (cell
->value
);
1002 cell
->value
= value_dup (value_area_get_x_y (value
, x
, y
, NULL
));
1008 * gnm_cell_convert_expr_to_value:
1010 * drops the expression keeps its value. Then uses the formatted
1011 * result as if that had been entered.
1013 * NOTE : the cell's expression cannot be linked into the expression * list.
1015 * The cell is rendered but spans are not calculated, the cell is NOT marked for
1018 * WARNING : This is an internal routine that does not queue redraws,
1019 * does not auto-resize, and does not calculate spans.
1022 gnm_cell_convert_expr_to_value (GnmCell
*cell
)
1024 GnmExprArrayCorner
const *array
;
1026 g_return_if_fail (cell
!= NULL
);
1027 g_return_if_fail (gnm_cell_has_expr (cell
));
1029 /* Clipboard cells, e.g., are not attached to a sheet. */
1030 if (gnm_cell_expr_is_linked (cell
))
1031 dependent_unlink (GNM_CELL_TO_DEP (cell
));
1033 array
= gnm_expr_top_get_array_corner (cell
->base
.texpr
);
1035 sheet_foreach_cell_in_range (cell
->base
.sheet
, CELL_ITER_ALL
,
1036 cell
->pos
.col
, cell
->pos
.row
,
1037 cell
->pos
.col
+ array
->cols
- 1,
1038 cell
->pos
.row
+ array
->rows
- 1,
1042 g_return_if_fail (!gnm_cell_is_array (cell
));
1045 gnm_expr_top_unref (cell
->base
.texpr
);
1046 cell
->base
.texpr
= NULL
;
1049 static gpointer
cell_boxed_copy (gpointer c
) { return c
; }
1050 static void cell_boxed_free (gpointer c
) { }
1053 gnm_cell_get_type (void)
1055 static GType type_cell
= 0;
1058 type_cell
= g_boxed_type_register_static