Whitespace.
[gnumeric.git] / src / cell.c
blobfc9632423140f206fbdddef86738a83f3f71ecb5
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 * The returned value is a pointer to a PangoColor describing
686 * the foreground colour.
688 GOColor
689 gnm_cell_get_render_color (GnmCell const *cell)
691 GnmRenderedValue *rv;
693 g_return_val_if_fail (cell != NULL, GO_COLOR_BLACK);
695 rv = gnm_cell_fetch_rendered_value (cell, TRUE);
697 return gnm_rendered_value_get_color (rv);
701 * gnm_cell_get_entered_text:
702 * @cell: the cell from which we want to pull the content from
704 * This returns a g_malloc()ed region of memory with a text representation
705 * of the cell contents.
707 * Returns: (transfer full): a text expression if the cell contains a
708 * formula, or a string representation of the value.
710 char *
711 gnm_cell_get_entered_text (GnmCell const *cell)
713 GnmValue const *v;
714 Sheet *sheet;
716 g_return_val_if_fail (cell != NULL, NULL);
718 sheet = cell->base.sheet;
720 if (gnm_cell_has_expr (cell)) {
721 GnmParsePos pp;
722 GnmConventionsOut out;
724 out.accum = g_string_new ("=");
725 out.pp = parse_pos_init_cell (&pp, cell);
726 out.convs = sheet->convs;
728 gnm_expr_top_as_gstring (cell->base.texpr, &out);
729 return g_string_free (out.accum, FALSE);
732 v = cell->value;
733 if (v != NULL) {
734 GODateConventions const *date_conv =
735 workbook_date_conv (sheet->workbook);
737 if (VALUE_IS_STRING (v)) {
738 /* Try to be reasonably smart about adding a leading quote */
739 char const *tmp = value_peek_string (v);
741 if (tmp[0] != '\'' &&
742 tmp[0] != 0 &&
743 !gnm_expr_char_start_p (tmp)) {
744 GnmValue *val = format_match_number
745 (tmp,
746 gnm_cell_get_format (cell),
747 date_conv);
748 if (val == NULL)
749 return g_strdup (tmp);
750 value_release (val);
752 return g_strconcat ("\'", tmp, NULL);
753 } else {
754 GOFormat const *fmt = gnm_cell_get_format (cell);
755 return format_value (fmt, v, -1, date_conv);
759 g_warning ("A cell with no expression, and no value ??");
760 return g_strdup ("<ERROR>");
763 static gboolean
764 close_to_int (gnm_float x, gnm_float eps)
766 return gnm_abs (x - gnm_fake_round (x)) < eps;
769 static GOFormat *
770 guess_time_format (const char *prefix, gnm_float f)
772 int decs = 0;
773 gnm_float eps = 1e-6;
774 static int maxdecs = 6;
775 GString *str = g_string_new (prefix);
776 GOFormat *fmt;
778 if (f >= 0 && f < 1)
779 g_string_append (str, "hh:mm");
780 else
781 g_string_append (str, "[h]:mm");
782 f *= 24 * 60;
783 if (!close_to_int (f, eps / 60)) {
784 g_string_append (str, ":ss");
785 f *= 60;
786 if (!close_to_int (f, eps)) {
787 g_string_append_c (str, '.');
788 while (decs < maxdecs) {
789 decs++;
790 g_string_append_c (str, '0');
791 f *= 10;
792 if (close_to_int (f, eps))
793 break;
798 while (go_format_is_invalid ((fmt = go_format_new_from_XL (str->str))) && decs > 0) {
799 /* We don't know how many decimals GOFormat allows. */
800 go_format_unref (fmt);
801 maxdecs = --decs;
802 g_string_truncate (str, str->len - 1);
805 g_string_free (str, TRUE);
806 return fmt;
810 * gnm_cell_get_text_for_editing:
811 * @cell: the cell from which we want to pull the content from
812 * @quoted: (out) (optional): Whether a single quote was used to force
813 * string interpretation
814 * @cursor_pos: (out) (optional): Desired initial cursor position
816 * Returns: (transfer full): A string suitable for editing
818 * Primary user of this function is the formula entry.
819 * This function should return the value most appropriate for
820 * editing
822 char *
823 gnm_cell_get_text_for_editing (GnmCell const * cell,
824 gboolean *quoted, int *cursor_pos)
826 GODateConventions const *date_conv;
827 gchar *text = NULL;
829 g_return_val_if_fail (cell != NULL, NULL);
831 if (quoted)
832 *quoted = FALSE;
834 date_conv = workbook_date_conv (cell->base.sheet->workbook);
836 if (!gnm_cell_is_array (cell) &&
837 !gnm_cell_has_expr (cell) && VALUE_IS_FLOAT (cell->value)) {
838 GOFormat const *fmt = gnm_cell_get_format (cell);
839 gnm_float f = value_get_as_float (cell->value);
841 switch (go_format_get_family (fmt)) {
842 case GO_FORMAT_FRACTION:
843 text = gnm_cell_get_entered_text (cell);
844 g_strchug (text);
845 g_strchomp (text);
846 break;
848 case GO_FORMAT_PERCENTAGE: {
849 GString *new_str = g_string_new (NULL);
850 gnm_render_general (NULL, new_str, go_format_measure_zero,
851 go_font_metrics_unit, f * 100,
852 -1, FALSE, 0, 0);
853 if (cursor_pos)
854 *cursor_pos = g_utf8_strlen (new_str->str, -1);
855 g_string_append_c (new_str, '%');
856 text = g_string_free (new_str, FALSE);
857 break;
860 case GO_FORMAT_NUMBER:
861 case GO_FORMAT_SCIENTIFIC:
862 case GO_FORMAT_CURRENCY:
863 case GO_FORMAT_ACCOUNTING: {
864 GString *new_str = g_string_new (NULL);
865 gnm_render_general (NULL, new_str, go_format_measure_zero,
866 go_font_metrics_unit, f,
867 -1, FALSE, 0, 0);
868 text = g_string_free (new_str, FALSE);
869 break;
872 case GO_FORMAT_DATE: {
873 GOFormat *new_fmt;
875 new_fmt = gnm_format_for_date_editing (cell);
877 if (!close_to_int (f, 1e-6 / (24 * 60 * 60))) {
878 GString *fstr = g_string_new (go_format_as_XL (new_fmt));
879 go_format_unref (new_fmt);
881 g_string_append_c (fstr, ' ');
882 new_fmt = guess_time_format
883 (fstr->str,
884 f - gnm_floor (f));
885 g_string_free (fstr, TRUE);
888 text = format_value (new_fmt, cell->value,
889 -1, date_conv);
890 if (!text || text[0] == 0) {
891 g_free (text);
892 text = format_value (go_format_general (),
893 cell->value,
895 date_conv);
897 go_format_unref (new_fmt);
898 break;
901 case GO_FORMAT_TIME: {
902 GOFormat *new_fmt = guess_time_format (NULL, f);
904 text = format_value (new_fmt, cell->value, -1,
905 date_conv);
906 go_format_unref (new_fmt);
907 break;
910 default:
911 break;
915 if (!text) {
916 text = gnm_cell_get_entered_text (cell);
917 if (quoted)
918 *quoted = (text[0] == '\'');
921 return text;
927 * Return the height of the rendered layout after rotation.
930 gnm_cell_rendered_height (GnmCell const *cell)
932 const GnmRenderedValue *rv;
934 g_return_val_if_fail (cell != NULL, 0);
936 rv = gnm_cell_get_rendered_value (cell);
937 return rv
938 ? PANGO_PIXELS (rv->layout_natural_height)
939 : 0;
943 * Return the width of the rendered layout after rotation.
946 gnm_cell_rendered_width (GnmCell const *cell)
948 const GnmRenderedValue *rv;
950 g_return_val_if_fail (cell != NULL, 0);
952 rv = gnm_cell_get_rendered_value (cell);
953 return rv
954 ? PANGO_PIXELS (rv->layout_natural_width)
955 : 0;
959 gnm_cell_rendered_offset (GnmCell const * cell)
961 const GnmRenderedValue *rv;
963 g_return_val_if_fail (cell != NULL, 0);
965 rv = gnm_cell_get_rendered_value (cell);
966 return rv
967 ? rv->indent_left + rv->indent_right
968 : 0;
972 * gnm_cell_get_style:
973 * @cell: #GnmCell to query
975 * Returns: (transfer none): the fully qualified style for @cell.
977 GnmStyle const *
978 gnm_cell_get_style (GnmCell const *cell)
980 g_return_val_if_fail (cell != NULL, NULL);
981 return sheet_style_get (cell->base.sheet,
982 cell->pos.col,
983 cell->pos.row);
987 * gnm_cell_get_format_given_style: (skip)
988 * @cell: #GnmCell to query
989 * @style: (nullable): #GnmStyle for @cell.
991 * Returns: (transfer none): the effective format for the cell, i.e., @style's
992 * format unless that is General and the cell value has a format.
994 GOFormat const *
995 gnm_cell_get_format_given_style (GnmCell const *cell, GnmStyle const *style)
997 GOFormat const *fmt;
999 g_return_val_if_fail (cell != NULL, go_format_general ());
1001 if (style == NULL)
1002 style = gnm_cell_get_style (cell);
1004 fmt = gnm_style_get_format (style);
1006 g_return_val_if_fail (fmt != NULL, go_format_general ());
1008 if (go_format_is_general (fmt) &&
1009 cell->value != NULL && VALUE_FMT (cell->value))
1010 fmt = VALUE_FMT (cell->value);
1012 return fmt;
1016 * gnm_cell_get_format:
1017 * @cell: #GnmCell to query
1019 * Returns: (transfer none): the effective format for the cell, i.e., the
1020 * cell style's format unless that is General and the cell value has a format.
1022 GOFormat const *
1023 gnm_cell_get_format (GnmCell const *cell)
1025 return gnm_cell_get_format_given_style (cell, NULL);
1028 static GnmValue *
1029 cb_set_array_value (GnmCellIter const *iter, gpointer user)
1031 GnmValue const *value = user;
1032 GnmCell *cell = iter->cell;
1033 int x, y;
1035 /* Clipboard cells, e.g., are not attached to a sheet. */
1036 if (gnm_cell_expr_is_linked (cell))
1037 dependent_unlink (GNM_CELL_TO_DEP (cell));
1039 if (!gnm_expr_top_is_array_elem (cell->base.texpr, &x, &y))
1040 return NULL;
1042 gnm_expr_top_unref (cell->base.texpr);
1043 cell->base.texpr = NULL;
1044 value_release (cell->value);
1045 cell->value = value_dup (value_area_get_x_y (value, x, y, NULL));
1047 return NULL;
1051 * gnm_cell_convert_expr_to_value:
1052 * @cell: #GnmCell
1053 * drops the expression keeps its value. Then uses the formatted
1054 * result as if that had been entered.
1056 * NOTE : the cell's expression cannot be linked into the expression * list.
1058 * The cell is rendered but spans are not calculated, the cell is NOT marked for
1059 * recalc.
1061 * WARNING : This is an internal routine that does not queue redraws,
1062 * does not auto-resize, and does not calculate spans.
1064 void
1065 gnm_cell_convert_expr_to_value (GnmCell *cell)
1067 GnmExprTop const *texpr;
1069 g_return_if_fail (cell != NULL);
1070 g_return_if_fail (gnm_cell_has_expr (cell));
1072 /* Clipboard cells, e.g., are not attached to a sheet. */
1073 if (gnm_cell_expr_is_linked (cell))
1074 dependent_unlink (GNM_CELL_TO_DEP (cell));
1076 texpr = cell->base.texpr;
1077 if (gnm_expr_top_is_array_corner (texpr)) {
1078 int rows, cols;
1080 gnm_expr_top_get_array_size (texpr, &cols, &rows);
1082 sheet_foreach_cell_in_range (cell->base.sheet, CELL_ITER_ALL,
1083 cell->pos.col, cell->pos.row,
1084 cell->pos.col + cols - 1,
1085 cell->pos.row + rows - 1,
1086 cb_set_array_value,
1087 gnm_expr_top_get_array_value (texpr));
1088 } else {
1089 g_return_if_fail (!gnm_cell_is_array (cell));
1092 gnm_expr_top_unref (texpr);
1093 cell->base.texpr = NULL;
1096 static gpointer cell_boxed_copy (gpointer c) { return c; }
1097 static void cell_boxed_free (gpointer c) { }
1099 GType
1100 gnm_cell_get_type (void)
1102 static GType type_cell = 0;
1104 if (!type_cell)
1105 type_cell = g_boxed_type_register_static
1106 ("GnmCell",
1107 cell_boxed_copy,
1108 cell_boxed_free);
1110 return type_cell;