Sheet: add new sheet_date_conv convenience function.
[gnumeric.git] / src / cell.c
bloba82a9dec358c899bb5c9a7a9aebb75fac390fb0b
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * cell.c: Cell content and simple management.
5 * Author:
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)
9 */
10 #include <gnumeric-config.h>
11 #include "gnumeric.h"
12 #include "cell.h"
14 #include "gutils.h"
15 #include "workbook.h"
16 #include "sheet.h"
17 #include "expr.h"
18 #include "rendered-value.h"
19 #include "value.h"
20 #include "style.h"
21 #include "ranges.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>
29 /**
30 * gnm_cell_cleanout: (skip)
31 * @cell: The #GnmCell
33 * Empty a cell's
34 * - value.
35 * - rendered_value.
36 * - expression.
37 * - parse format.
39 * Clears the flags to
40 * - not queued for recalc.
41 * - has no expression.
43 * Does NOT change
44 * - Comments.
45 * - Spans.
46 * - unqueue a previously queued recalc.
47 * - Mark sheet as dirty.
49 void
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);
64 cell->value = NULL;
66 gnm_cell_unrender (cell);
68 sheet_cell_queue_respan (cell);
71 /****************************************************************************/
73 /**
74 * gnm_cell_set_text: (skip)
75 * @cell: #GnmCell
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.
91 void
92 gnm_cell_set_text (GnmCell *cell, char const *text)
94 GnmExprTop const *texpr;
95 GnmValue *val;
96 GnmParsePos pos;
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),
103 text, &val, &texpr);
105 if (val != NULL) { /* String was a value */
106 gnm_cell_cleanout (cell);
107 cell->value = val;
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)
116 * @cell: #GnmCell
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
125 * - queue redraws,
126 * - auto-resize
127 * - calculate spans
128 * - does not render.
129 * - mark anything as dirty.
131 * NOTE : This DOES NOT check for array partitioning.
133 void
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);
140 cell->value = v;
144 * gnm_cell_set_value: (skip)
145 * @c: #GnmCell
146 * @v: (transfer full): #GnmValue
148 * WARNING : This is an internal routine that does not
149 * - queue redraws,
150 * - auto-resize
151 * - calculate spans
152 * - does not render.
154 * NOTE : This DOES check for array partitioning.
156 void
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)) {
162 value_release (v);
163 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell));
166 gnm_cell_cleanout (cell);
167 cell->value = v;
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.
188 void
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)) {
195 value_release (v);
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;
205 cell->value = v;
206 if (link_expr)
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.
216 * Does NOT
217 * - check for array subdivision
218 * - queue recalcs.
219 * - render value, calc dimension, compute spans
220 * - link the expression into the master list.
222 static void
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 ();
231 cell->value = NULL;
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
252 * using this.
254 void
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.
277 void
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.
308 void
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;
315 int x, y;
316 GnmCell *corner;
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) {
338 GnmCell *cell;
339 GnmExprTop const *te;
341 if (x == 0 && y == 0)
342 continue;
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));
355 static void
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,
363 texpr);
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:
371 * @sr:
372 * @texpr:
374 * Returns: (transfer full): the newly allocated #GOUndo.
376 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.
406 gboolean
407 gnm_cell_set_array (Sheet *sheet,
408 const GnmRange *r,
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))
418 return FALSE;
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,
424 texpr);
425 return TRUE;
428 /***************************************************************************/
431 * gnm_cell_is_empty:
432 * @cell: (nullable): #GnmCell
434 * Returns: %TRUE, If the cell has not been created, or has VALUE_EMPTY.
436 gboolean
437 gnm_cell_is_empty (GnmCell const *cell)
439 return cell == NULL || VALUE_IS_EMPTY (cell->value);
443 * gnm_cell_is_blank:
444 * @cell: (nullable): #GnmCell
446 * Returns: %TRUE, if the cell has not been created, has VALUE_EMPTY,
447 * or has an empty VALUE_STRING.
449 gboolean
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');
458 * gnm_cell_is_error:
459 * @cell: #GnmCell
461 * Returns: (nullable) (transfer none): @cell's value if it is an error,
462 * or %NULL.
464 GnmValue *
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))
471 return cell->value;
472 return NULL;
476 * gnm_cell_is_number:
477 * @cell: #GnmCell
479 * Returns: %TRUE, if the cell contains a number.
481 gboolean
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));
489 * gnm_cell_is_zero:
490 * @cell: #GnmCell
492 * Returns: %TRUE, if the cell contains zero.
494 gboolean
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:
503 * @cell: #GnmCell
505 * Returns: (transfer none): @cell's value
507 GnmValue *
508 gnm_cell_get_value (GnmCell const *cell)
510 g_return_val_if_fail (cell != NULL, NULL);
511 return cell->value;
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
521 gboolean
522 gnm_cell_array_bound (GnmCell const *cell, GnmRange *res)
524 GnmExprTop const *texpr;
525 int x, y;
526 int cols, rows;
528 range_init (res, 0, 0, 0, 0);
530 if (NULL == cell || !gnm_cell_has_expr (cell))
531 return FALSE;
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))
546 return FALSE;
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);
553 return TRUE;
557 * gnm_cell_is_array:
558 * @cell: #GnmCell
560 * Returns %TRUE is @cell is part of an array
562 gboolean
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:
572 * @cell: #GnmCell
574 * Returns: %TRUE is @cell is part of an array larger than 1x1
576 gboolean
577 gnm_cell_is_nonsingleton_array (GnmCell const *cell)
579 int cols, rows;
581 if ((cell == NULL) || !gnm_cell_has_expr (cell))
582 return FALSE;
583 if (gnm_expr_top_is_array_elem (cell->base.texpr, NULL, NULL))
584 return TRUE;
586 if (!gnm_expr_top_is_array_corner (cell->base.texpr))
587 return FALSE;
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)
597 * @cell: #GnmCell
599 * Returns: (transfer none): The #GnmRenderedValue for the cell.
601 GnmRenderedValue *
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)
611 * @cell: #GnmCell
613 * Returns:
615 GnmRenderedValue *
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);
624 if (rv)
625 return rv;
627 return gnm_cell_render_value (cell, allow_variable_width);
630 void
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.
643 GnmRenderedValue *
644 gnm_cell_render_value (GnmCell const *cell, gboolean allow_variable_width)
646 GnmRenderedValue *rv;
647 Sheet *sheet;
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);
659 return 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.
669 char *
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.
687 GOColor
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.
709 char *
710 gnm_cell_get_entered_text (GnmCell const *cell)
712 GnmValue const *v;
713 Sheet *sheet;
715 g_return_val_if_fail (cell != NULL, NULL);
717 sheet = cell->base.sheet;
719 if (gnm_cell_has_expr (cell)) {
720 GnmParsePos pp;
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);
731 v = cell->value;
732 if (v != NULL) {
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] != '\'' &&
741 tmp[0] != 0 &&
742 !gnm_expr_char_start_p (tmp)) {
743 GnmValue *val = format_match_number
744 (tmp,
745 gnm_cell_get_format (cell),
746 date_conv);
747 if (val == NULL)
748 return g_strdup (tmp);
749 value_release (val);
751 return g_strconcat ("\'", tmp, NULL);
752 } else {
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>");
762 static gboolean
763 close_to_int (gnm_float x, gnm_float eps)
765 return gnm_abs (x - gnm_fake_round (x)) < eps;
768 static GOFormat *
769 guess_time_format (const char *prefix, gnm_float f)
771 int decs = 0;
772 gnm_float eps = 1e-6;
773 static int maxdecs = 6;
774 GString *str = g_string_new (prefix);
775 GOFormat *fmt;
777 if (f >= 0 && f < 1)
778 g_string_append (str, "hh:mm");
779 else
780 g_string_append (str, "[h]:mm");
781 f *= 24 * 60;
782 if (!close_to_int (f, eps / 60)) {
783 g_string_append (str, ":ss");
784 f *= 60;
785 if (!close_to_int (f, eps)) {
786 g_string_append_c (str, '.');
787 while (decs < maxdecs) {
788 decs++;
789 g_string_append_c (str, '0');
790 f *= 10;
791 if (close_to_int (f, eps))
792 break;
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);
800 maxdecs = --decs;
801 g_string_truncate (str, str->len - 1);
804 g_string_free (str, TRUE);
805 return fmt;
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
819 * editing
821 char *
822 gnm_cell_get_text_for_editing (GnmCell const * cell,
823 gboolean *quoted, int *cursor_pos)
825 GODateConventions const *date_conv;
826 gchar *text = NULL;
828 g_return_val_if_fail (cell != NULL, NULL);
830 if (quoted)
831 *quoted = FALSE;
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);
843 g_strchug (text);
844 g_strchomp (text);
845 break;
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,
851 -1, FALSE, 0, 0);
852 if (cursor_pos)
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);
856 break;
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,
866 -1, FALSE, 0, 0);
867 text = g_string_free (new_str, FALSE);
868 break;
871 case GO_FORMAT_DATE: {
872 GOFormat *new_fmt;
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
882 (fstr->str,
883 f - gnm_floor (f));
884 g_string_free (fstr, TRUE);
887 text = format_value (new_fmt, cell->value,
888 -1, date_conv);
889 if (!text || text[0] == 0) {
890 g_free (text);
891 text = format_value (go_format_general (),
892 cell->value,
894 date_conv);
896 go_format_unref (new_fmt);
897 break;
900 case GO_FORMAT_TIME: {
901 GOFormat *new_fmt = guess_time_format (NULL, f);
903 text = format_value (new_fmt, cell->value, -1,
904 date_conv);
905 go_format_unref (new_fmt);
906 break;
909 default:
910 break;
914 if (!text) {
915 text = gnm_cell_get_entered_text (cell);
916 if (quoted)
917 *quoted = (text[0] == '\'');
920 return text;
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);
936 return rv
937 ? PANGO_PIXELS (rv->layout_natural_height)
938 : 0;
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);
952 return rv
953 ? PANGO_PIXELS (rv->layout_natural_width)
954 : 0;
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);
965 return rv
966 ? rv->indent_left + rv->indent_right
967 : 0;
971 * gnm_cell_get_style:
972 * @cell: #GnmCell to query
974 * Returns: (transfer none): the fully qualified style for @cell.
976 GnmStyle const *
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,
981 cell->pos.col,
982 cell->pos.row);
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.
993 GOFormat const *
994 gnm_cell_get_format_given_style (GnmCell const *cell, GnmStyle const *style)
996 GOFormat const *fmt;
998 g_return_val_if_fail (cell != NULL, go_format_general ());
1000 if (style == NULL)
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);
1011 return fmt;
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.
1021 GOFormat const *
1022 gnm_cell_get_format (GnmCell const *cell)
1024 return gnm_cell_get_format_given_style (cell, NULL);
1027 static GnmValue *
1028 cb_set_array_value (GnmCellIter const *iter, gpointer user)
1030 GnmValue const *value = user;
1031 GnmCell *cell = iter->cell;
1032 int x, y;
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))
1039 return NULL;
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));
1046 return NULL;
1050 * gnm_cell_convert_expr_to_value:
1051 * @cell: #GnmCell
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
1058 * recalc.
1060 * WARNING : This is an internal routine that does not queue redraws,
1061 * does not auto-resize, and does not calculate spans.
1063 void
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)) {
1077 int rows, cols;
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,
1085 cb_set_array_value,
1086 gnm_expr_top_get_array_value (texpr));
1087 } else {
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) { }
1098 GType
1099 gnm_cell_get_type (void)
1101 static GType type_cell = 0;
1103 if (!type_cell)
1104 type_cell = g_boxed_type_register_static
1105 ("GnmCell",
1106 cell_boxed_copy,
1107 cell_boxed_free);
1109 return type_cell;