2 * cell.c: Cell content and simple management.
5 * Jody Goldberg 2000-2006 (jody@gnome.org)
6 * Miguel de Icaza 1998, 1999 (miguel@kernel.org)
7 * Copyright (C) 2000-2009 Morten Welinder (terra@gnome.org)
9 #include <gnumeric-config.h>
17 #include <rendered-value.h>
21 #include <gnm-format.h>
22 #include <number-match.h>
23 #include <sheet-style.h>
24 #include <parse-util.h>
26 #include <goffice/goffice.h>
29 * gnm_cell_cleanout: (skip)
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: (skip)
75 * @text: New contents of cell
77 * Parses the supplied text for storage as a value or
78 * expression. It marks the sheet as dirty.
80 * If the text is an expression it IS queued for recalc.
81 * the format prefered by the expression is stored for later use.
82 * If the text is a value it is rendered and spans are NOT calculated.
83 * the format that matched the text is stored for later use.
85 * WARNING : This is an internal routine that does not queue redraws,
86 * does not auto-resize, and does not calculate spans.
88 * NOTE : This DOES check for array partitioning.
91 gnm_cell_set_text (GnmCell
*cell
, char const *text
)
93 GnmExprTop
const *texpr
;
97 g_return_if_fail (cell
!= NULL
);
98 g_return_if_fail (text
!= NULL
);
99 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
101 parse_text_value_or_expr (parse_pos_init_cell (&pos
, cell
),
104 if (val
!= NULL
) { /* String was a value */
105 gnm_cell_cleanout (cell
);
107 } else { /* String was an expression */
108 gnm_cell_set_expr (cell
, texpr
);
109 gnm_expr_top_unref (texpr
);
114 * gnm_cell_assign_value: (skip)
116 * @v: (transfer full): #GnmValue
118 * Stores, without copying, the supplied value.
119 * no changes are made to the expression or entered text. This
120 * is for use by routines that wish to store values directly such
121 * as expression calculation or import for array formulas.
123 * WARNING : This is an internal routine that does not
128 * - mark anything as dirty.
130 * NOTE : This DOES NOT check for array partitioning.
133 gnm_cell_assign_value (GnmCell
*cell
, GnmValue
*v
)
135 g_return_if_fail (cell
);
136 g_return_if_fail (v
);
138 value_release (cell
->value
);
143 * gnm_cell_set_value: (skip)
145 * @v: (transfer full): #GnmValue
147 * WARNING : This is an internal routine that does not
153 * NOTE : This DOES check for array partitioning.
156 gnm_cell_set_value (GnmCell
*cell
, GnmValue
*v
)
158 g_return_if_fail (cell
!= NULL
);
159 g_return_if_fail (v
!= NULL
);
160 if (gnm_cell_is_nonsingleton_array (cell
)) {
162 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
165 gnm_cell_cleanout (cell
);
170 * gnm_cell_set_expr_and_value: (skip)
171 * @cell: The #GnmCell
172 * @texpr: The #GnmExprTop
173 * @v: (transfer full): The #GnmValue.
174 * @link_expr: If %TRUE, link the expression.
176 * Stores, without copying, the supplied value, and
177 * references the supplied expression and links it into the expression
178 * list. It marks the sheet as dirty. It is intended for use by import
179 * routines or operations that do bulk assignment.
181 * WARNING : This is an internal routine that does not queue redraws,
182 * does not auto-resize, does not calculate spans, and does
183 * not render the value.
185 * NOTE : This DOES check for array partitioning.
188 gnm_cell_set_expr_and_value (GnmCell
*cell
, GnmExprTop
const *texpr
,
189 GnmValue
*v
, gboolean link_expr
)
191 g_return_if_fail (cell
!= NULL
);
192 g_return_if_fail (texpr
!= NULL
);
193 if (gnm_cell_is_nonsingleton_array (cell
)) {
195 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
198 /* Repeat after me. Ref before unref. */
199 gnm_expr_top_ref (texpr
);
200 gnm_cell_cleanout (cell
);
202 cell
->base
.flags
|= GNM_CELL_HAS_NEW_EXPR
;
203 cell
->base
.texpr
= texpr
;
206 dependent_link (GNM_CELL_TO_DEP (cell
));
210 * cell_set_expr_internal: (skip)
211 * @cell: the cell to set the expr for
212 * @expr: an expression
214 * A private internal utility to store an expression.
216 * - check for array subdivision
218 * - render value, calc dimension, compute spans
219 * - link the expression into the master list.
222 cell_set_expr_internal (GnmCell
*cell
, GnmExprTop
const *texpr
)
224 GnmValue
*save_value
;
226 gnm_expr_top_ref (texpr
);
228 /* Don't touch the value. */
229 save_value
= cell
->value
? cell
->value
: value_new_empty ();
231 gnm_cell_cleanout (cell
);
233 cell
->base
.flags
|= GNM_CELL_HAS_NEW_EXPR
;
234 cell
->base
.texpr
= texpr
;
235 cell
->value
= save_value
;
239 * gnm_cell_set_expr_unsafe: (skip)
240 * @cell: The #GnmCell
241 * @texpr: The #GnmExprTop
243 * Stores and references the supplied expression. It
244 * marks the sheet as dirty. Intented for use by import routines that
245 * do bulk assignment. The resulting cell is NOT linked into the
246 * dependent list. Nor marked for recalc.
248 * WARNING : This is an internal routine that does not queue redraws,
249 * does not auto-resize, and does not calculate spans.
250 * It also DOES NOT CHECK FOR ARRAY DIVISION. Be very careful
254 gnm_cell_set_expr_unsafe (GnmCell
*cell
, GnmExprTop
const *texpr
)
256 g_return_if_fail (cell
!= NULL
);
257 g_return_if_fail (texpr
!= NULL
);
259 cell_set_expr_internal (cell
, texpr
);
263 * gnm_cell_set_expr: (skip)
264 * @cell: The #GnmCell
265 * @texpr: The #GnmExprTop
267 * Stores and references the supplied expression
268 * marks the sheet as dirty. Intented for use by import routines that
269 * do bulk assignment. The resulting cell _is_ linked into the
270 * dependent list, but NOT marked for recalc.
272 * WARNING : This is an internal routine that does not queue redraws,
273 * does not auto-resize, and does not calculate spans.
274 * Be very careful using this.
277 gnm_cell_set_expr (GnmCell
*cell
, GnmExprTop
const *texpr
)
279 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
280 g_return_if_fail (cell
!= NULL
);
281 g_return_if_fail (texpr
!= NULL
);
283 cell_set_expr_internal (cell
, texpr
);
284 dependent_link (GNM_CELL_TO_DEP (cell
));
288 * gnm_cell_set_array_formula: (skip)
289 * @sheet: The sheet to set the expr in.
290 * @cola: The left column in the destination region.
291 * @rowa: The top row in the destination region.
292 * @colb: The right column in the destination region.
293 * @rowb: The bottom row in the destination region.
294 * @texpr: an expression (the inner expression, not a corner or element)
296 * Uses cell_set_expr_internal to store the expr as an
297 * 'array-formula'. The supplied expression is wrapped in an array
298 * operator for each cell in the range and scheduled for recalc.
300 * NOTE : Does not add a reference to the expression. It takes over the
301 * caller's reference.
303 * Does not regenerate spans, dimensions or autosize cols/rows.
305 * DOES NOT CHECK for array partitioning.
308 gnm_cell_set_array_formula (Sheet
*sheet
,
309 int col_a
, int row_a
, int col_b
, int row_b
,
310 GnmExprTop
const *texpr
)
312 int const num_rows
= 1 + row_b
- row_a
;
313 int const num_cols
= 1 + col_b
- col_a
;
316 GnmExprTop
const *wrapper
;
318 g_return_if_fail (sheet
!= NULL
);
319 g_return_if_fail (texpr
!= NULL
);
320 g_return_if_fail (0 <= col_a
);
321 g_return_if_fail (col_a
<= col_b
);
322 g_return_if_fail (col_b
< gnm_sheet_get_max_cols (sheet
));
323 g_return_if_fail (0 <= row_a
);
324 g_return_if_fail (row_a
<= row_b
);
325 g_return_if_fail (row_b
< gnm_sheet_get_max_rows (sheet
));
327 corner
= sheet_cell_fetch (sheet
, col_a
, row_a
);
328 g_return_if_fail (corner
!= NULL
);
330 wrapper
= gnm_expr_top_new_array_corner (num_cols
, num_rows
, gnm_expr_copy (texpr
->expr
));
331 gnm_expr_top_unref (texpr
);
332 cell_set_expr_internal (corner
, wrapper
);
333 gnm_expr_top_unref (wrapper
);
335 for (x
= 0; x
< num_cols
; ++x
) {
336 for (y
= 0; y
< num_rows
; ++y
) {
338 GnmExprTop
const *te
;
340 if (x
== 0 && y
== 0)
343 cell
= sheet_cell_fetch (sheet
, col_a
+ x
, row_a
+ y
);
344 te
= gnm_expr_top_new_array_elem (x
, y
);
345 cell_set_expr_internal (cell
, te
);
346 dependent_link (GNM_CELL_TO_DEP (cell
));
347 gnm_expr_top_unref (te
);
351 dependent_link (GNM_CELL_TO_DEP (corner
));
355 gnm_cell_set_array_formula_cb (GnmSheetRange
const *sr
, GnmExprTop
const *texpr
)
357 sheet_region_queue_recalc (sr
->sheet
, &sr
->range
);
358 gnm_expr_top_ref (texpr
);
359 gnm_cell_set_array_formula (sr
->sheet
,
360 sr
->range
.start
.col
, sr
->range
.start
.row
,
361 sr
->range
.end
.col
, sr
->range
.end
.row
,
363 sheet_region_queue_recalc (sr
->sheet
, &sr
->range
);
364 sheet_flag_status_update_range (sr
->sheet
, &sr
->range
);
365 sheet_queue_respan (sr
->sheet
, sr
->range
.start
.row
, sr
->range
.end
.row
);
369 * gnm_cell_set_array_formula_undo:
373 * Returns: (transfer full): the newly allocated #GOUndo.
376 gnm_cell_set_array_formula_undo (GnmSheetRange
*sr
, GnmExprTop
const *texpr
)
378 gnm_expr_top_ref (texpr
);
379 return go_undo_binary_new (sr
, (gpointer
)texpr
,
380 (GOUndoBinaryFunc
) gnm_cell_set_array_formula_cb
,
381 (GFreeFunc
) gnm_sheet_range_free
,
382 (GFreeFunc
) gnm_expr_top_unref
);
386 * gnm_cell_set_array:
387 * @sheet: The sheet to set the expr in.
388 * @r: The range to set.
389 * @texpr: an expression (the inner expression, not a corner or element)
391 * Set an array expression for a range.
392 * Uses cell_set_expr_internal to store the expr as an
393 * 'array-formula'. The supplied expression is wrapped in an array
394 * operator for each cell in the range and scheduled for recalc.
396 * Returns: %TRUE if the operation succeded.
398 * NOTE : This adds a reference to the expression.
400 * Does not regenerate spans, dimensions or autosize cols/rows.
402 * DOES CHECK for array partitioning.
406 gnm_cell_set_array (Sheet
*sheet
,
408 GnmExprTop
const *texpr
)
410 g_return_val_if_fail (sheet
!= NULL
, FALSE
);
411 g_return_val_if_fail (range_is_sane (r
), FALSE
);
412 g_return_val_if_fail (r
->end
.row
< gnm_sheet_get_max_rows (sheet
), FALSE
);
413 g_return_val_if_fail (r
->end
.col
< gnm_sheet_get_max_cols (sheet
), FALSE
);
414 g_return_val_if_fail (texpr
!= NULL
, FALSE
);
416 if (sheet_range_splits_array (sheet
, r
, NULL
, NULL
, NULL
))
419 gnm_expr_top_ref (texpr
);
420 gnm_cell_set_array_formula (sheet
,
421 r
->start
.col
, r
->start
.row
,
422 r
->end
.col
, r
->end
.row
,
427 /***************************************************************************/
431 * @cell: (nullable): #GnmCell
433 * Returns: %TRUE, If the cell has not been created, or has VALUE_EMPTY.
436 gnm_cell_is_empty (GnmCell
const *cell
)
438 return cell
== NULL
|| VALUE_IS_EMPTY (cell
->value
);
443 * @cell: (nullable): #GnmCell
445 * Returns: %TRUE, if the cell has not been created, has VALUE_EMPTY,
446 * or has an empty VALUE_STRING.
449 gnm_cell_is_blank (GnmCell
const * cell
)
451 return gnm_cell_is_empty (cell
) ||
452 (VALUE_IS_STRING (cell
->value
) &&
453 *value_peek_string (cell
->value
) == '\0');
460 * Returns: (nullable) (transfer none): @cell's value if it is an error,
464 gnm_cell_is_error (GnmCell
const *cell
)
466 g_return_val_if_fail (cell
!= NULL
, NULL
);
467 g_return_val_if_fail (cell
->value
!= NULL
, NULL
);
469 if (VALUE_IS_ERROR (cell
->value
))
475 * gnm_cell_is_number:
478 * Returns: %TRUE, if the cell contains a number.
481 gnm_cell_is_number (GnmCell
const *cell
)
483 /* FIXME : This does not handle arrays or ranges */
484 return (cell
->value
&& VALUE_IS_NUMBER (cell
->value
));
491 * Returns: %TRUE, if the cell contains zero.
494 gnm_cell_is_zero (GnmCell
const *cell
)
496 GnmValue
const * const v
= cell
->value
;
497 return v
&& VALUE_IS_NUMBER (v
) && gnm_abs (value_get_as_float (v
)) < 64 * GNM_EPSILON
;
501 * gnm_cell_get_value:
504 * Returns: (transfer none): @cell's value
507 gnm_cell_get_value (GnmCell
const *cell
)
509 g_return_val_if_fail (cell
!= NULL
, NULL
);
514 * gnm_cell_array_bound:
515 * @cell: (nullable): #GnmCell
516 * @res: (out): The range containing an array cell
518 * Returns: %TRUE, if the cell is an array cell
521 gnm_cell_array_bound (GnmCell
const *cell
, GnmRange
*res
)
523 GnmExprTop
const *texpr
;
527 range_init (res
, 0, 0, 0, 0);
529 if (NULL
== cell
|| !gnm_cell_has_expr (cell
))
532 g_return_val_if_fail (res
!= NULL
, FALSE
);
534 texpr
= cell
->base
.texpr
;
535 if (gnm_expr_top_is_array_elem (texpr
, &x
, &y
)) {
536 cell
= sheet_cell_get (cell
->base
.sheet
, cell
->pos
.col
- x
, cell
->pos
.row
- y
);
538 g_return_val_if_fail (cell
!= NULL
, FALSE
);
539 g_return_val_if_fail (gnm_cell_has_expr (cell
), FALSE
);
541 texpr
= cell
->base
.texpr
;
544 if (!gnm_expr_top_is_array_corner (texpr
))
547 gnm_expr_top_get_array_size (texpr
, &cols
, &rows
);
549 range_init (res
, cell
->pos
.col
, cell
->pos
.row
,
550 cell
->pos
.col
+ cols
- 1,
551 cell
->pos
.row
+ rows
- 1);
559 * Returns %TRUE is @cell is part of an array
562 gnm_cell_is_array (GnmCell
const *cell
)
564 return cell
!= NULL
&& gnm_cell_has_expr (cell
) &&
565 (gnm_expr_top_is_array_corner (cell
->base
.texpr
) ||
566 gnm_expr_top_is_array_elem (cell
->base
.texpr
, NULL
, NULL
));
570 * gnm_cell_is_nonsingleton_array:
573 * Returns: %TRUE is @cell is part of an array larger than 1x1
576 gnm_cell_is_nonsingleton_array (GnmCell
const *cell
)
580 if ((cell
== NULL
) || !gnm_cell_has_expr (cell
))
582 if (gnm_expr_top_is_array_elem (cell
->base
.texpr
, NULL
, NULL
))
585 if (!gnm_expr_top_is_array_corner (cell
->base
.texpr
))
588 gnm_expr_top_get_array_size (cell
->base
.texpr
, &cols
, &rows
);
589 return cols
> 1 || rows
> 1;
592 /***************************************************************************/
595 * gnm_cell_get_rendered_value: (skip)
598 * Returns: (transfer none): The #GnmRenderedValue for the cell.
601 gnm_cell_get_rendered_value (GnmCell
const *cell
)
603 g_return_val_if_fail (cell
!= NULL
, NULL
);
605 return gnm_rvc_query (cell
->base
.sheet
->rendered_values
, cell
);
609 * gnm_cell_fetch_rendered_value: (skip)
615 gnm_cell_fetch_rendered_value (GnmCell
const *cell
,
616 gboolean allow_variable_width
)
618 GnmRenderedValue
*rv
;
620 g_return_val_if_fail (cell
!= NULL
, NULL
);
622 rv
= gnm_cell_get_rendered_value (cell
);
626 return gnm_cell_render_value (cell
, allow_variable_width
);
630 gnm_cell_unrender (GnmCell
const *cell
)
632 gnm_rvc_remove (cell
->base
.sheet
->rendered_values
, cell
);
636 * gnm_cell_render_value: (skip)
637 * @cell: The cell whose value needs to be rendered
638 * @allow_variable_width: Allow format to depend on column width.
640 * Returns: (transfer none): The newly #GnmRenderedValue.
643 gnm_cell_render_value (GnmCell
const *cell
, gboolean allow_variable_width
)
645 GnmRenderedValue
*rv
;
648 g_return_val_if_fail (cell
!= NULL
, NULL
);
650 sheet
= cell
->base
.sheet
;
651 rv
= gnm_rendered_value_new (cell
,
652 sheet
->rendered_values
->context
,
653 allow_variable_width
,
654 sheet
->last_zoom_factor_used
);
656 gnm_rvc_store (sheet
->rendered_values
, cell
, rv
);
662 * gnm_cell_get_rendered_text:
664 * Warning: use this only when you really want what is displayed on the
665 * screen. If the user has decided to display formulas instead of values
666 * then that is what you get.
669 gnm_cell_get_rendered_text (GnmCell
*cell
)
671 GnmRenderedValue
*rv
;
673 g_return_val_if_fail (cell
!= NULL
, g_strdup ("ERROR"));
675 rv
= gnm_cell_fetch_rendered_value (cell
, TRUE
);
677 return g_strdup (gnm_rendered_value_get_text (rv
));
681 * gnm_cell_get_render_color:
682 * @cell: the cell from which we want to pull the color from
684 * Returns: A #GOColor used for foreground in @cell.
687 gnm_cell_get_render_color (GnmCell
const *cell
)
689 GnmRenderedValue
*rv
;
691 g_return_val_if_fail (cell
!= NULL
, GO_COLOR_BLACK
);
693 rv
= gnm_cell_fetch_rendered_value (cell
, TRUE
);
695 return gnm_rendered_value_get_color (rv
);
699 * gnm_cell_get_entered_text:
700 * @cell: the cell from which we want to pull the content from
702 * This returns a g_malloc()ed region of memory with a text representation
703 * of the cell contents.
705 * Returns: (transfer full): a text expression if the cell contains a
706 * formula, or a string representation of the value.
709 gnm_cell_get_entered_text (GnmCell
const *cell
)
714 g_return_val_if_fail (cell
!= NULL
, NULL
);
716 sheet
= cell
->base
.sheet
;
718 if (gnm_cell_has_expr (cell
)) {
720 GnmConventionsOut out
;
722 out
.accum
= g_string_new ("=");
723 out
.pp
= parse_pos_init_cell (&pp
, cell
);
724 out
.convs
= sheet
->convs
;
726 gnm_expr_top_as_gstring (cell
->base
.texpr
, &out
);
727 return g_string_free (out
.accum
, FALSE
);
732 GODateConventions
const *date_conv
=
733 sheet_date_conv (sheet
);
735 if (VALUE_IS_STRING (v
)) {
736 /* Try to be reasonably smart about adding a leading quote */
737 char const *tmp
= value_peek_string (v
);
739 if (tmp
[0] != '\'' &&
741 !gnm_expr_char_start_p (tmp
)) {
742 GnmValue
*val
= format_match_number
744 gnm_cell_get_format (cell
),
747 return g_strdup (tmp
);
750 return g_strconcat ("\'", tmp
, NULL
);
752 GOFormat
const *fmt
= gnm_cell_get_format (cell
);
753 return format_value (fmt
, v
, -1, date_conv
);
757 g_warning ("A cell with no expression, and no value ??");
758 return g_strdup ("<ERROR>");
762 close_to_int (gnm_float x
, gnm_float eps
)
764 return gnm_abs (x
- gnm_fake_round (x
)) < eps
;
768 guess_time_format (const char *prefix
, gnm_float f
)
771 gnm_float eps
= 1e-6;
772 static int maxdecs
= 6;
773 GString
*str
= g_string_new (prefix
);
777 g_string_append (str
, "hh:mm");
779 g_string_append (str
, "[h]:mm");
781 if (!close_to_int (f
, eps
/ 60)) {
782 g_string_append (str
, ":ss");
784 if (!close_to_int (f
, eps
)) {
785 g_string_append_c (str
, '.');
786 while (decs
< maxdecs
) {
788 g_string_append_c (str
, '0');
790 if (close_to_int (f
, eps
))
796 while (go_format_is_invalid ((fmt
= go_format_new_from_XL (str
->str
))) && decs
> 0) {
797 /* We don't know how many decimals GOFormat allows. */
798 go_format_unref (fmt
);
800 g_string_truncate (str
, str
->len
- 1);
803 g_string_free (str
, TRUE
);
808 * gnm_cell_get_text_for_editing:
809 * @cell: the cell from which we want to pull the content from
810 * @quoted: (out) (optional): Whether a single quote was used to force
811 * string interpretation
812 * @cursor_pos: (out) (optional): Desired initial cursor position
814 * Returns: (transfer full): A string suitable for editing
816 * Primary user of this function is the formula entry.
817 * This function should return the value most appropriate for
821 gnm_cell_get_text_for_editing (GnmCell
const * cell
,
822 gboolean
*quoted
, int *cursor_pos
)
824 GODateConventions
const *date_conv
;
827 g_return_val_if_fail (cell
!= NULL
, NULL
);
832 date_conv
= sheet_date_conv (cell
->base
.sheet
);
834 if (!gnm_cell_is_array (cell
) &&
835 !gnm_cell_has_expr (cell
) && VALUE_IS_FLOAT (cell
->value
)) {
836 GOFormat
const *fmt
= gnm_cell_get_format (cell
);
837 gnm_float f
= value_get_as_float (cell
->value
);
839 switch (go_format_get_family (fmt
)) {
840 case GO_FORMAT_FRACTION
:
841 text
= gnm_cell_get_entered_text (cell
);
846 case GO_FORMAT_PERCENTAGE
: {
847 GString
*new_str
= g_string_new (NULL
);
848 gnm_render_general (NULL
, new_str
, go_format_measure_zero
,
849 go_font_metrics_unit
, f
* 100,
852 *cursor_pos
= g_utf8_strlen (new_str
->str
, -1);
853 g_string_append_c (new_str
, '%');
854 text
= g_string_free (new_str
, FALSE
);
858 case GO_FORMAT_NUMBER
:
859 case GO_FORMAT_SCIENTIFIC
:
860 case GO_FORMAT_CURRENCY
:
861 case GO_FORMAT_ACCOUNTING
: {
862 GString
*new_str
= g_string_new (NULL
);
863 gnm_render_general (NULL
, new_str
, go_format_measure_zero
,
864 go_font_metrics_unit
, f
,
866 text
= g_string_free (new_str
, FALSE
);
870 case GO_FORMAT_DATE
: {
873 new_fmt
= gnm_format_for_date_editing (cell
);
875 if (!close_to_int (f
, 1e-6 / (24 * 60 * 60))) {
876 GString
*fstr
= g_string_new (go_format_as_XL (new_fmt
));
877 go_format_unref (new_fmt
);
879 g_string_append_c (fstr
, ' ');
880 new_fmt
= guess_time_format
883 g_string_free (fstr
, TRUE
);
886 text
= format_value (new_fmt
, cell
->value
,
888 if (!text
|| text
[0] == 0) {
890 text
= format_value (go_format_general (),
895 go_format_unref (new_fmt
);
899 case GO_FORMAT_TIME
: {
900 GOFormat
*new_fmt
= guess_time_format (NULL
, f
);
902 text
= format_value (new_fmt
, cell
->value
, -1,
904 go_format_unref (new_fmt
);
914 text
= gnm_cell_get_entered_text (cell
);
916 *quoted
= (text
[0] == '\'');
925 * Return the height of the rendered layout after rotation.
928 gnm_cell_rendered_height (GnmCell
const *cell
)
930 const GnmRenderedValue
*rv
;
932 g_return_val_if_fail (cell
!= NULL
, 0);
934 rv
= gnm_cell_get_rendered_value (cell
);
936 ? PANGO_PIXELS (rv
->layout_natural_height
)
941 * Return the width of the rendered layout after rotation.
944 gnm_cell_rendered_width (GnmCell
const *cell
)
946 const GnmRenderedValue
*rv
;
948 g_return_val_if_fail (cell
!= NULL
, 0);
950 rv
= gnm_cell_get_rendered_value (cell
);
952 ? PANGO_PIXELS (rv
->layout_natural_width
)
957 gnm_cell_rendered_offset (GnmCell
const * cell
)
959 const GnmRenderedValue
*rv
;
961 g_return_val_if_fail (cell
!= NULL
, 0);
963 rv
= gnm_cell_get_rendered_value (cell
);
965 ? rv
->indent_left
+ rv
->indent_right
970 * gnm_cell_get_style:
971 * @cell: #GnmCell to query
973 * Returns: (transfer none): the fully qualified style for @cell.
976 gnm_cell_get_style (GnmCell
const *cell
)
978 g_return_val_if_fail (cell
!= NULL
, NULL
);
979 return sheet_style_get (cell
->base
.sheet
,
985 * gnm_cell_get_format_given_style: (skip)
986 * @cell: #GnmCell to query
987 * @style: (nullable): #GnmStyle for @cell.
989 * Returns: (transfer none): the effective format for the cell, i.e., @style's
990 * format unless that is General and the cell value has a format.
993 gnm_cell_get_format_given_style (GnmCell
const *cell
, GnmStyle
const *style
)
997 g_return_val_if_fail (cell
!= NULL
, go_format_general ());
1000 style
= gnm_cell_get_style (cell
);
1002 fmt
= gnm_style_get_format (style
);
1004 g_return_val_if_fail (fmt
!= NULL
, go_format_general ());
1006 if (go_format_is_general (fmt
) &&
1007 cell
->value
!= NULL
&& VALUE_FMT (cell
->value
))
1008 fmt
= VALUE_FMT (cell
->value
);
1014 * gnm_cell_get_format:
1015 * @cell: #GnmCell to query
1017 * Returns: (transfer none): the effective format for the cell, i.e., the
1018 * cell style's format unless that is General and the cell value has a format.
1021 gnm_cell_get_format (GnmCell
const *cell
)
1023 return gnm_cell_get_format_given_style (cell
, NULL
);
1027 cb_set_array_value (GnmCellIter
const *iter
, gpointer user
)
1029 GnmValue
const *value
= user
;
1030 GnmCell
*cell
= iter
->cell
;
1033 /* Clipboard cells, e.g., are not attached to a sheet. */
1034 if (gnm_cell_expr_is_linked (cell
))
1035 dependent_unlink (GNM_CELL_TO_DEP (cell
));
1037 if (!gnm_expr_top_is_array_elem (cell
->base
.texpr
, &x
, &y
))
1040 gnm_expr_top_unref (cell
->base
.texpr
);
1041 cell
->base
.texpr
= NULL
;
1042 value_release (cell
->value
);
1043 cell
->value
= value_dup (value_area_get_x_y (value
, x
, y
, NULL
));
1049 * gnm_cell_convert_expr_to_value:
1051 * drops the expression keeps its value. Then uses the formatted
1052 * result as if that had been entered.
1054 * NOTE : the cell's expression cannot be linked into the expression * list.
1056 * The cell is rendered but spans are not calculated, the cell is NOT marked for
1059 * WARNING : This is an internal routine that does not queue redraws,
1060 * does not auto-resize, and does not calculate spans.
1063 gnm_cell_convert_expr_to_value (GnmCell
*cell
)
1065 GnmExprTop
const *texpr
;
1067 g_return_if_fail (cell
!= NULL
);
1068 g_return_if_fail (gnm_cell_has_expr (cell
));
1070 /* Clipboard cells, e.g., are not attached to a sheet. */
1071 if (gnm_cell_expr_is_linked (cell
))
1072 dependent_unlink (GNM_CELL_TO_DEP (cell
));
1074 texpr
= cell
->base
.texpr
;
1075 if (gnm_expr_top_is_array_corner (texpr
)) {
1078 gnm_expr_top_get_array_size (texpr
, &cols
, &rows
);
1080 sheet_foreach_cell_in_region (cell
->base
.sheet
, CELL_ITER_ALL
,
1081 cell
->pos
.col
, cell
->pos
.row
,
1082 cell
->pos
.col
+ cols
- 1,
1083 cell
->pos
.row
+ rows
- 1,
1085 gnm_expr_top_get_array_value (texpr
));
1087 g_return_if_fail (!gnm_cell_is_array (cell
));
1090 gnm_expr_top_unref (texpr
);
1091 cell
->base
.texpr
= NULL
;
1094 static gpointer
cell_boxed_copy (gpointer c
) { return c
; }
1095 static void cell_boxed_free (gpointer c
) { }
1098 gnm_cell_get_type (void)
1100 static GType type_cell
= 0;
1103 type_cell
= g_boxed_type_register_static