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 "rendered-value.h"
22 #include "gnm-format.h"
23 #include "number-match.h"
24 #include "sheet-style.h"
25 #include "parse-util.h"
27 #include <goffice/goffice.h>
30 * gnm_cell_cleanout: (skip)
40 * - not queued for recalc.
41 * - has no expression.
46 * - unqueue a previously queued recalc.
47 * - Mark sheet as dirty.
50 gnm_cell_cleanout (GnmCell
*cell
)
52 g_return_if_fail (cell
!= NULL
);
54 /* A cell can have either an expression or entered text */
55 if (gnm_cell_has_expr (cell
)) {
56 /* Clipboard cells, e.g., are not attached to a sheet. */
57 if (gnm_cell_expr_is_linked (cell
))
58 dependent_unlink (GNM_CELL_TO_DEP (cell
));
59 gnm_expr_top_unref (cell
->base
.texpr
);
60 cell
->base
.texpr
= NULL
;
63 value_release (cell
->value
);
66 gnm_cell_unrender (cell
);
68 sheet_cell_queue_respan (cell
);
71 /****************************************************************************/
74 * gnm_cell_set_text: (skip)
76 * @text: New contents of cell
78 * Parses the supplied text for storage as a value or
79 * expression. It marks the sheet as dirty.
81 * If the text is an expression it IS queued for recalc.
82 * the format prefered by the expression is stored for later use.
83 * If the text is a value it is rendered and spans are NOT calculated.
84 * the format that matched the text is stored for later use.
86 * WARNING : This is an internal routine that does not queue redraws,
87 * does not auto-resize, and does not calculate spans.
89 * NOTE : This DOES check for array partitioning.
92 gnm_cell_set_text (GnmCell
*cell
, char const *text
)
94 GnmExprTop
const *texpr
;
98 g_return_if_fail (cell
!= NULL
);
99 g_return_if_fail (text
!= NULL
);
100 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
102 parse_text_value_or_expr (parse_pos_init_cell (&pos
, cell
),
105 if (val
!= NULL
) { /* String was a value */
106 gnm_cell_cleanout (cell
);
108 } else { /* String was an expression */
109 gnm_cell_set_expr (cell
, texpr
);
110 gnm_expr_top_unref (texpr
);
115 * gnm_cell_assign_value: (skip)
117 * @v: (transfer full): #GnmValue
119 * Stores, without copying, the supplied value.
120 * no changes are made to the expression or entered text. This
121 * is for use by routines that wish to store values directly such
122 * as expression calculation or import for array formulas.
124 * WARNING : This is an internal routine that does not
129 * - mark anything as dirty.
131 * NOTE : This DOES NOT check for array partitioning.
134 gnm_cell_assign_value (GnmCell
*cell
, GnmValue
*v
)
136 g_return_if_fail (cell
);
137 g_return_if_fail (v
);
139 value_release (cell
->value
);
144 * gnm_cell_set_value: (skip)
146 * @v: (transfer full): #GnmValue
148 * WARNING : This is an internal routine that does not
154 * NOTE : This DOES check for array partitioning.
157 gnm_cell_set_value (GnmCell
*cell
, GnmValue
*v
)
159 g_return_if_fail (cell
!= NULL
);
160 g_return_if_fail (v
!= NULL
);
161 if (gnm_cell_is_nonsingleton_array (cell
)) {
163 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
166 gnm_cell_cleanout (cell
);
171 * gnm_cell_set_expr_and_value: (skip)
172 * @cell: The #GnmCell
173 * @texpr: The #GnmExprTop
174 * @v: (transfer full): The #GnmValue.
175 * @link_expr: If %TRUE, link the expression.
177 * Stores, without copying, the supplied value, and
178 * references the supplied expression and links it into the expression
179 * list. It marks the sheet as dirty. It is intended for use by import
180 * routines or operations that do bulk assignment.
182 * WARNING : This is an internal routine that does not queue redraws,
183 * does not auto-resize, does not calculate spans, and does
184 * not render the value.
186 * NOTE : This DOES check for array partitioning.
189 gnm_cell_set_expr_and_value (GnmCell
*cell
, GnmExprTop
const *texpr
,
190 GnmValue
*v
, gboolean link_expr
)
192 g_return_if_fail (cell
!= NULL
);
193 g_return_if_fail (texpr
!= NULL
);
194 if (gnm_cell_is_nonsingleton_array (cell
)) {
196 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
199 /* Repeat after me. Ref before unref. */
200 gnm_expr_top_ref (texpr
);
201 gnm_cell_cleanout (cell
);
203 cell
->base
.flags
|= GNM_CELL_HAS_NEW_EXPR
;
204 cell
->base
.texpr
= texpr
;
207 dependent_link (GNM_CELL_TO_DEP (cell
));
211 * cell_set_expr_internal: (skip)
212 * @cell: the cell to set the expr for
213 * @expr: an expression
215 * A private internal utility to store an expression.
217 * - check for array subdivision
219 * - render value, calc dimension, compute spans
220 * - link the expression into the master list.
223 cell_set_expr_internal (GnmCell
*cell
, GnmExprTop
const *texpr
)
225 GnmValue
*save_value
;
227 gnm_expr_top_ref (texpr
);
229 /* Don't touch the value. */
230 save_value
= cell
->value
? cell
->value
: value_new_empty ();
232 gnm_cell_cleanout (cell
);
234 cell
->base
.flags
|= GNM_CELL_HAS_NEW_EXPR
;
235 cell
->base
.texpr
= texpr
;
236 cell
->value
= save_value
;
240 * gnm_cell_set_expr_unsafe: (skip)
241 * @cell: The #GnmCell
242 * @texpr: The #GnmExprTop
244 * Stores and references the supplied expression. It
245 * marks the sheet as dirty. Intented for use by import routines that
246 * do bulk assignment. The resulting cell is NOT linked into the
247 * dependent list. Nor marked for recalc.
249 * WARNING : This is an internal routine that does not queue redraws,
250 * does not auto-resize, and does not calculate spans.
251 * It also DOES NOT CHECK FOR ARRAY DIVISION. Be very careful
255 gnm_cell_set_expr_unsafe (GnmCell
*cell
, GnmExprTop
const *texpr
)
257 g_return_if_fail (cell
!= NULL
);
258 g_return_if_fail (texpr
!= NULL
);
260 cell_set_expr_internal (cell
, texpr
);
264 * gnm_cell_set_expr: (skip)
265 * @cell: The #GnmCell
266 * @texpr: The #GnmExprTop
268 * Stores and references the supplied expression
269 * marks the sheet as dirty. Intented for use by import routines that
270 * do bulk assignment. The resulting cell _is_ linked into the
271 * dependent list, but NOT marked for recalc.
273 * WARNING : This is an internal routine that does not queue redraws,
274 * does not auto-resize, and does not calculate spans.
275 * Be very careful using this.
278 gnm_cell_set_expr (GnmCell
*cell
, GnmExprTop
const *texpr
)
280 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell
));
281 g_return_if_fail (cell
!= NULL
);
282 g_return_if_fail (texpr
!= NULL
);
284 cell_set_expr_internal (cell
, texpr
);
285 dependent_link (GNM_CELL_TO_DEP (cell
));
289 * gnm_cell_set_array_formula: (skip)
290 * @sheet: The sheet to set the expr in.
291 * @cola: The left column in the destination region.
292 * @rowa: The top row in the destination region.
293 * @colb: The right column in the destination region.
294 * @rowb: The bottom row in the destination region.
295 * @texpr: an expression (the inner expression, not a corner or element)
297 * Uses cell_set_expr_internal to store the expr as an
298 * 'array-formula'. The supplied expression is wrapped in an array
299 * operator for each cell in the range and scheduled for recalc.
301 * NOTE : Does not add a reference to the expression. It takes over the
302 * caller's reference.
304 * Does not regenerate spans, dimensions or autosize cols/rows.
306 * DOES NOT CHECK for array partitioning.
309 gnm_cell_set_array_formula (Sheet
*sheet
,
310 int col_a
, int row_a
, int col_b
, int row_b
,
311 GnmExprTop
const *texpr
)
313 int const num_rows
= 1 + row_b
- row_a
;
314 int const num_cols
= 1 + col_b
- col_a
;
317 GnmExprTop
const *wrapper
;
319 g_return_if_fail (sheet
!= NULL
);
320 g_return_if_fail (texpr
!= NULL
);
321 g_return_if_fail (0 <= col_a
);
322 g_return_if_fail (col_a
<= col_b
);
323 g_return_if_fail (col_b
< gnm_sheet_get_max_cols (sheet
));
324 g_return_if_fail (0 <= row_a
);
325 g_return_if_fail (row_a
<= row_b
);
326 g_return_if_fail (row_b
< gnm_sheet_get_max_rows (sheet
));
328 corner
= sheet_cell_fetch (sheet
, col_a
, row_a
);
329 g_return_if_fail (corner
!= NULL
);
331 wrapper
= gnm_expr_top_new_array_corner (num_cols
, num_rows
, gnm_expr_copy (texpr
->expr
));
332 gnm_expr_top_unref (texpr
);
333 cell_set_expr_internal (corner
, wrapper
);
334 gnm_expr_top_unref (wrapper
);
336 for (x
= 0; x
< num_cols
; ++x
) {
337 for (y
= 0; y
< num_rows
; ++y
) {
339 GnmExprTop
const *te
;
341 if (x
== 0 && y
== 0)
344 cell
= sheet_cell_fetch (sheet
, col_a
+ x
, row_a
+ y
);
345 te
= gnm_expr_top_new_array_elem (x
, y
);
346 cell_set_expr_internal (cell
, te
);
347 dependent_link (GNM_CELL_TO_DEP (cell
));
348 gnm_expr_top_unref (te
);
352 dependent_link (GNM_CELL_TO_DEP (corner
));
356 gnm_cell_set_array_formula_cb (GnmSheetRange
const *sr
, GnmExprTop
const *texpr
)
358 sheet_region_queue_recalc (sr
->sheet
, &sr
->range
);
359 gnm_expr_top_ref (texpr
);
360 gnm_cell_set_array_formula (sr
->sheet
,
361 sr
->range
.start
.col
, sr
->range
.start
.row
,
362 sr
->range
.end
.col
, sr
->range
.end
.row
,
364 sheet_region_queue_recalc (sr
->sheet
, &sr
->range
);
365 sheet_flag_status_update_range (sr
->sheet
, &sr
->range
);
366 sheet_queue_respan (sr
->sheet
, sr
->range
.start
.row
, sr
->range
.end
.row
);
370 * gnm_cell_set_array_formula_undo:
374 * Returns: (transfer full): the newly allocated #GOUndo.
377 gnm_cell_set_array_formula_undo (GnmSheetRange
*sr
, GnmExprTop
const *texpr
)
379 gnm_expr_top_ref (texpr
);
380 return go_undo_binary_new (sr
, (gpointer
)texpr
,
381 (GOUndoBinaryFunc
) gnm_cell_set_array_formula_cb
,
382 (GFreeFunc
) gnm_sheet_range_free
,
383 (GFreeFunc
) gnm_expr_top_unref
);
387 * gnm_cell_set_array:
388 * @sheet: The sheet to set the expr in.
389 * @r: The range to set.
390 * @texpr: an expression (the inner expression, not a corner or element)
392 * Set an array expression for a range.
393 * Uses cell_set_expr_internal to store the expr as an
394 * 'array-formula'. The supplied expression is wrapped in an array
395 * operator for each cell in the range and scheduled for recalc.
397 * Returns: %TRUE if the operation succeded.
399 * NOTE : This adds a reference to the expression.
401 * Does not regenerate spans, dimensions or autosize cols/rows.
403 * DOES CHECK for array partitioning.
407 gnm_cell_set_array (Sheet
*sheet
,
409 GnmExprTop
const *texpr
)
411 g_return_val_if_fail (sheet
!= NULL
, FALSE
);
412 g_return_val_if_fail (range_is_sane (r
), FALSE
);
413 g_return_val_if_fail (r
->end
.row
< gnm_sheet_get_max_rows (sheet
), FALSE
);
414 g_return_val_if_fail (r
->end
.col
< gnm_sheet_get_max_cols (sheet
), FALSE
);
415 g_return_val_if_fail (texpr
!= NULL
, FALSE
);
417 if (sheet_range_splits_array (sheet
, r
, NULL
, NULL
, NULL
))
420 gnm_expr_top_ref (texpr
);
421 gnm_cell_set_array_formula (sheet
,
422 r
->start
.col
, r
->start
.row
,
423 r
->end
.col
, r
->end
.row
,
428 /***************************************************************************/
432 * @cell: (nullable): #GnmCell
434 * Returns: %TRUE, If the cell has not been created, or has VALUE_EMPTY.
437 gnm_cell_is_empty (GnmCell
const *cell
)
439 return cell
== NULL
|| VALUE_IS_EMPTY (cell
->value
);
444 * @cell: (nullable): #GnmCell
446 * Returns: %TRUE, if the cell has not been created, has VALUE_EMPTY,
447 * or has an empty VALUE_STRING.
450 gnm_cell_is_blank (GnmCell
const * cell
)
452 return gnm_cell_is_empty (cell
) ||
453 (VALUE_IS_STRING (cell
->value
) &&
454 *value_peek_string (cell
->value
) == '\0');
461 * Returns: (nullable) (transfer none): @cell's value if it is an error,
465 gnm_cell_is_error (GnmCell
const *cell
)
467 g_return_val_if_fail (cell
!= NULL
, NULL
);
468 g_return_val_if_fail (cell
->value
!= NULL
, NULL
);
470 if (VALUE_IS_ERROR (cell
->value
))
476 * gnm_cell_is_number:
479 * Returns: %TRUE, if the cell contains a number.
482 gnm_cell_is_number (GnmCell
const *cell
)
484 /* FIXME : This does not handle arrays or ranges */
485 return (cell
->value
&& VALUE_IS_NUMBER (cell
->value
));
492 * Returns: %TRUE, if the cell contains zero.
495 gnm_cell_is_zero (GnmCell
const *cell
)
497 GnmValue
const * const v
= cell
->value
;
498 return v
&& VALUE_IS_NUMBER (v
) && gnm_abs (value_get_as_float (v
)) < 64 * GNM_EPSILON
;
502 * gnm_cell_get_value:
505 * Returns: (transfer none): @cell's value
508 gnm_cell_get_value (GnmCell
const *cell
)
510 g_return_val_if_fail (cell
!= NULL
, NULL
);
515 * gnm_cell_array_bound:
516 * @cell: (nullable): #GnmCell
517 * @res: (out): The range containing an array cell
519 * Returns: %TRUE, if the cell is an array cell
522 gnm_cell_array_bound (GnmCell
const *cell
, GnmRange
*res
)
524 GnmExprTop
const *texpr
;
528 range_init (res
, 0, 0, 0, 0);
530 if (NULL
== cell
|| !gnm_cell_has_expr (cell
))
533 g_return_val_if_fail (res
!= NULL
, FALSE
);
535 texpr
= cell
->base
.texpr
;
536 if (gnm_expr_top_is_array_elem (texpr
, &x
, &y
)) {
537 cell
= sheet_cell_get (cell
->base
.sheet
, cell
->pos
.col
- x
, cell
->pos
.row
- y
);
539 g_return_val_if_fail (cell
!= NULL
, FALSE
);
540 g_return_val_if_fail (gnm_cell_has_expr (cell
), FALSE
);
542 texpr
= cell
->base
.texpr
;
545 if (!gnm_expr_top_is_array_corner (texpr
))
548 gnm_expr_top_get_array_size (texpr
, &cols
, &rows
);
550 range_init (res
, cell
->pos
.col
, cell
->pos
.row
,
551 cell
->pos
.col
+ cols
- 1,
552 cell
->pos
.row
+ rows
- 1);
560 * Returns %TRUE is @cell is part of an array
563 gnm_cell_is_array (GnmCell
const *cell
)
565 return cell
!= NULL
&& gnm_cell_has_expr (cell
) &&
566 (gnm_expr_top_is_array_corner (cell
->base
.texpr
) ||
567 gnm_expr_top_is_array_elem (cell
->base
.texpr
, NULL
, NULL
));
571 * gnm_cell_is_nonsingleton_array:
574 * Returns: %TRUE is @cell is part of an array larger than 1x1
577 gnm_cell_is_nonsingleton_array (GnmCell
const *cell
)
581 if ((cell
== NULL
) || !gnm_cell_has_expr (cell
))
583 if (gnm_expr_top_is_array_elem (cell
->base
.texpr
, NULL
, NULL
))
586 if (!gnm_expr_top_is_array_corner (cell
->base
.texpr
))
589 gnm_expr_top_get_array_size (cell
->base
.texpr
, &cols
, &rows
);
590 return cols
> 1 || rows
> 1;
593 /***************************************************************************/
596 * gnm_cell_get_rendered_value: (skip)
599 * Returns: (transfer none): The #GnmRenderedValue for the cell.
602 gnm_cell_get_rendered_value (GnmCell
const *cell
)
604 g_return_val_if_fail (cell
!= NULL
, NULL
);
606 return gnm_rvc_query (cell
->base
.sheet
->rendered_values
, cell
);
610 * gnm_cell_fetch_rendered_value: (skip)
616 gnm_cell_fetch_rendered_value (GnmCell
const *cell
,
617 gboolean allow_variable_width
)
619 GnmRenderedValue
*rv
;
621 g_return_val_if_fail (cell
!= NULL
, NULL
);
623 rv
= gnm_cell_get_rendered_value (cell
);
627 return gnm_cell_render_value (cell
, allow_variable_width
);
631 gnm_cell_unrender (GnmCell
const *cell
)
633 gnm_rvc_remove (cell
->base
.sheet
->rendered_values
, cell
);
637 * gnm_cell_render_value: (skip)
638 * @cell: The cell whose value needs to be rendered
639 * @allow_variable_width: Allow format to depend on column width.
641 * Returns: (transfer none): The newly #GnmRenderedValue.
644 gnm_cell_render_value (GnmCell
const *cell
, gboolean allow_variable_width
)
646 GnmRenderedValue
*rv
;
649 g_return_val_if_fail (cell
!= NULL
, NULL
);
651 sheet
= cell
->base
.sheet
;
652 rv
= gnm_rendered_value_new (cell
,
653 sheet
->rendered_values
->context
,
654 allow_variable_width
,
655 sheet
->last_zoom_factor_used
);
657 gnm_rvc_store (sheet
->rendered_values
, cell
, rv
);
663 * gnm_cell_get_rendered_text:
665 * Warning: use this only when you really want what is displayed on the
666 * screen. If the user has decided to display formulas instead of values
667 * then that is what you get.
670 gnm_cell_get_rendered_text (GnmCell
*cell
)
672 GnmRenderedValue
*rv
;
674 g_return_val_if_fail (cell
!= NULL
, g_strdup ("ERROR"));
676 rv
= gnm_cell_fetch_rendered_value (cell
, TRUE
);
678 return g_strdup (gnm_rendered_value_get_text (rv
));
682 * gnm_cell_get_render_color:
683 * @cell: the cell from which we want to pull the color from
685 * Returns: A #GOColor used for foreground in @cell.
688 gnm_cell_get_render_color (GnmCell
const *cell
)
690 GnmRenderedValue
*rv
;
692 g_return_val_if_fail (cell
!= NULL
, GO_COLOR_BLACK
);
694 rv
= gnm_cell_fetch_rendered_value (cell
, TRUE
);
696 return gnm_rendered_value_get_color (rv
);
700 * gnm_cell_get_entered_text:
701 * @cell: the cell from which we want to pull the content from
703 * This returns a g_malloc()ed region of memory with a text representation
704 * of the cell contents.
706 * Returns: (transfer full): a text expression if the cell contains a
707 * formula, or a string representation of the value.
710 gnm_cell_get_entered_text (GnmCell
const *cell
)
715 g_return_val_if_fail (cell
!= NULL
, NULL
);
717 sheet
= cell
->base
.sheet
;
719 if (gnm_cell_has_expr (cell
)) {
721 GnmConventionsOut out
;
723 out
.accum
= g_string_new ("=");
724 out
.pp
= parse_pos_init_cell (&pp
, cell
);
725 out
.convs
= sheet
->convs
;
727 gnm_expr_top_as_gstring (cell
->base
.texpr
, &out
);
728 return g_string_free (out
.accum
, FALSE
);
733 GODateConventions
const *date_conv
=
734 sheet_date_conv (sheet
);
736 if (VALUE_IS_STRING (v
)) {
737 /* Try to be reasonably smart about adding a leading quote */
738 char const *tmp
= value_peek_string (v
);
740 if (tmp
[0] != '\'' &&
742 !gnm_expr_char_start_p (tmp
)) {
743 GnmValue
*val
= format_match_number
745 gnm_cell_get_format (cell
),
748 return g_strdup (tmp
);
751 return g_strconcat ("\'", tmp
, NULL
);
753 GOFormat
const *fmt
= gnm_cell_get_format (cell
);
754 return format_value (fmt
, v
, -1, date_conv
);
758 g_warning ("A cell with no expression, and no value ??");
759 return g_strdup ("<ERROR>");
763 close_to_int (gnm_float x
, gnm_float eps
)
765 return gnm_abs (x
- gnm_fake_round (x
)) < eps
;
769 guess_time_format (const char *prefix
, gnm_float f
)
772 gnm_float eps
= 1e-6;
773 static int maxdecs
= 6;
774 GString
*str
= g_string_new (prefix
);
778 g_string_append (str
, "hh:mm");
780 g_string_append (str
, "[h]:mm");
782 if (!close_to_int (f
, eps
/ 60)) {
783 g_string_append (str
, ":ss");
785 if (!close_to_int (f
, eps
)) {
786 g_string_append_c (str
, '.');
787 while (decs
< maxdecs
) {
789 g_string_append_c (str
, '0');
791 if (close_to_int (f
, eps
))
797 while (go_format_is_invalid ((fmt
= go_format_new_from_XL (str
->str
))) && decs
> 0) {
798 /* We don't know how many decimals GOFormat allows. */
799 go_format_unref (fmt
);
801 g_string_truncate (str
, str
->len
- 1);
804 g_string_free (str
, TRUE
);
809 * gnm_cell_get_text_for_editing:
810 * @cell: the cell from which we want to pull the content from
811 * @quoted: (out) (optional): Whether a single quote was used to force
812 * string interpretation
813 * @cursor_pos: (out) (optional): Desired initial cursor position
815 * Returns: (transfer full): A string suitable for editing
817 * Primary user of this function is the formula entry.
818 * This function should return the value most appropriate for
822 gnm_cell_get_text_for_editing (GnmCell
const * cell
,
823 gboolean
*quoted
, int *cursor_pos
)
825 GODateConventions
const *date_conv
;
828 g_return_val_if_fail (cell
!= NULL
, NULL
);
833 date_conv
= sheet_date_conv (cell
->base
.sheet
);
835 if (!gnm_cell_is_array (cell
) &&
836 !gnm_cell_has_expr (cell
) && VALUE_IS_FLOAT (cell
->value
)) {
837 GOFormat
const *fmt
= gnm_cell_get_format (cell
);
838 gnm_float f
= value_get_as_float (cell
->value
);
840 switch (go_format_get_family (fmt
)) {
841 case GO_FORMAT_FRACTION
:
842 text
= gnm_cell_get_entered_text (cell
);
847 case GO_FORMAT_PERCENTAGE
: {
848 GString
*new_str
= g_string_new (NULL
);
849 gnm_render_general (NULL
, new_str
, go_format_measure_zero
,
850 go_font_metrics_unit
, f
* 100,
853 *cursor_pos
= g_utf8_strlen (new_str
->str
, -1);
854 g_string_append_c (new_str
, '%');
855 text
= g_string_free (new_str
, FALSE
);
859 case GO_FORMAT_NUMBER
:
860 case GO_FORMAT_SCIENTIFIC
:
861 case GO_FORMAT_CURRENCY
:
862 case GO_FORMAT_ACCOUNTING
: {
863 GString
*new_str
= g_string_new (NULL
);
864 gnm_render_general (NULL
, new_str
, go_format_measure_zero
,
865 go_font_metrics_unit
, f
,
867 text
= g_string_free (new_str
, FALSE
);
871 case GO_FORMAT_DATE
: {
874 new_fmt
= gnm_format_for_date_editing (cell
);
876 if (!close_to_int (f
, 1e-6 / (24 * 60 * 60))) {
877 GString
*fstr
= g_string_new (go_format_as_XL (new_fmt
));
878 go_format_unref (new_fmt
);
880 g_string_append_c (fstr
, ' ');
881 new_fmt
= guess_time_format
884 g_string_free (fstr
, TRUE
);
887 text
= format_value (new_fmt
, cell
->value
,
889 if (!text
|| text
[0] == 0) {
891 text
= format_value (go_format_general (),
896 go_format_unref (new_fmt
);
900 case GO_FORMAT_TIME
: {
901 GOFormat
*new_fmt
= guess_time_format (NULL
, f
);
903 text
= format_value (new_fmt
, cell
->value
, -1,
905 go_format_unref (new_fmt
);
915 text
= gnm_cell_get_entered_text (cell
);
917 *quoted
= (text
[0] == '\'');
926 * Return the height of the rendered layout after rotation.
929 gnm_cell_rendered_height (GnmCell
const *cell
)
931 const GnmRenderedValue
*rv
;
933 g_return_val_if_fail (cell
!= NULL
, 0);
935 rv
= gnm_cell_get_rendered_value (cell
);
937 ? PANGO_PIXELS (rv
->layout_natural_height
)
942 * Return the width of the rendered layout after rotation.
945 gnm_cell_rendered_width (GnmCell
const *cell
)
947 const GnmRenderedValue
*rv
;
949 g_return_val_if_fail (cell
!= NULL
, 0);
951 rv
= gnm_cell_get_rendered_value (cell
);
953 ? PANGO_PIXELS (rv
->layout_natural_width
)
958 gnm_cell_rendered_offset (GnmCell
const * cell
)
960 const GnmRenderedValue
*rv
;
962 g_return_val_if_fail (cell
!= NULL
, 0);
964 rv
= gnm_cell_get_rendered_value (cell
);
966 ? rv
->indent_left
+ rv
->indent_right
971 * gnm_cell_get_style:
972 * @cell: #GnmCell to query
974 * Returns: (transfer none): the fully qualified style for @cell.
977 gnm_cell_get_style (GnmCell
const *cell
)
979 g_return_val_if_fail (cell
!= NULL
, NULL
);
980 return sheet_style_get (cell
->base
.sheet
,
986 * gnm_cell_get_format_given_style: (skip)
987 * @cell: #GnmCell to query
988 * @style: (nullable): #GnmStyle for @cell.
990 * Returns: (transfer none): the effective format for the cell, i.e., @style's
991 * format unless that is General and the cell value has a format.
994 gnm_cell_get_format_given_style (GnmCell
const *cell
, GnmStyle
const *style
)
998 g_return_val_if_fail (cell
!= NULL
, go_format_general ());
1001 style
= gnm_cell_get_style (cell
);
1003 fmt
= gnm_style_get_format (style
);
1005 g_return_val_if_fail (fmt
!= NULL
, go_format_general ());
1007 if (go_format_is_general (fmt
) &&
1008 cell
->value
!= NULL
&& VALUE_FMT (cell
->value
))
1009 fmt
= VALUE_FMT (cell
->value
);
1015 * gnm_cell_get_format:
1016 * @cell: #GnmCell to query
1018 * Returns: (transfer none): the effective format for the cell, i.e., the
1019 * cell style's format unless that is General and the cell value has a format.
1022 gnm_cell_get_format (GnmCell
const *cell
)
1024 return gnm_cell_get_format_given_style (cell
, NULL
);
1028 cb_set_array_value (GnmCellIter
const *iter
, gpointer user
)
1030 GnmValue
const *value
= user
;
1031 GnmCell
*cell
= iter
->cell
;
1034 /* Clipboard cells, e.g., are not attached to a sheet. */
1035 if (gnm_cell_expr_is_linked (cell
))
1036 dependent_unlink (GNM_CELL_TO_DEP (cell
));
1038 if (!gnm_expr_top_is_array_elem (cell
->base
.texpr
, &x
, &y
))
1041 gnm_expr_top_unref (cell
->base
.texpr
);
1042 cell
->base
.texpr
= NULL
;
1043 value_release (cell
->value
);
1044 cell
->value
= value_dup (value_area_get_x_y (value
, x
, y
, NULL
));
1050 * gnm_cell_convert_expr_to_value:
1052 * drops the expression keeps its value. Then uses the formatted
1053 * result as if that had been entered.
1055 * NOTE : the cell's expression cannot be linked into the expression * list.
1057 * The cell is rendered but spans are not calculated, the cell is NOT marked for
1060 * WARNING : This is an internal routine that does not queue redraws,
1061 * does not auto-resize, and does not calculate spans.
1064 gnm_cell_convert_expr_to_value (GnmCell
*cell
)
1066 GnmExprTop
const *texpr
;
1068 g_return_if_fail (cell
!= NULL
);
1069 g_return_if_fail (gnm_cell_has_expr (cell
));
1071 /* Clipboard cells, e.g., are not attached to a sheet. */
1072 if (gnm_cell_expr_is_linked (cell
))
1073 dependent_unlink (GNM_CELL_TO_DEP (cell
));
1075 texpr
= cell
->base
.texpr
;
1076 if (gnm_expr_top_is_array_corner (texpr
)) {
1079 gnm_expr_top_get_array_size (texpr
, &cols
, &rows
);
1081 sheet_foreach_cell_in_region (cell
->base
.sheet
, CELL_ITER_ALL
,
1082 cell
->pos
.col
, cell
->pos
.row
,
1083 cell
->pos
.col
+ cols
- 1,
1084 cell
->pos
.row
+ rows
- 1,
1086 gnm_expr_top_get_array_value (texpr
));
1088 g_return_if_fail (!gnm_cell_is_array (cell
));
1091 gnm_expr_top_unref (texpr
);
1092 cell
->base
.texpr
= NULL
;
1095 static gpointer
cell_boxed_copy (gpointer c
) { return c
; }
1096 static void cell_boxed_free (gpointer c
) { }
1099 gnm_cell_get_type (void)
1101 static GType type_cell
= 0;
1104 type_cell
= g_boxed_type_register_static