Update Spanish translation
[gnumeric.git] / src / cell.c
blob0fc2feafdb97bfafb836c61bc9c6cf79577cb8a6
1 /*
2 * cell.c: Cell content and simple management.
4 * Author:
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)
8 */
9 #include <gnumeric-config.h>
10 #include <gnumeric.h>
11 #include <cell.h>
13 #include <gutils.h>
14 #include <workbook.h>
15 #include <sheet.h>
16 #include <expr.h>
17 #include <rendered-value.h>
18 #include <value.h>
19 #include <style.h>
20 #include <ranges.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>
28 /**
29 * gnm_cell_cleanout: (skip)
30 * @cell: The #GnmCell
32 * Empty a cell's
33 * - value.
34 * - rendered_value.
35 * - expression.
36 * - parse format.
38 * Clears the flags to
39 * - not queued for recalc.
40 * - has no expression.
42 * Does NOT change
43 * - Comments.
44 * - Spans.
45 * - unqueue a previously queued recalc.
46 * - Mark sheet as dirty.
48 void
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);
63 cell->value = NULL;
65 gnm_cell_unrender (cell);
67 sheet_cell_queue_respan (cell);
70 /****************************************************************************/
72 /**
73 * gnm_cell_set_text: (skip)
74 * @cell: #GnmCell
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.
90 void
91 gnm_cell_set_text (GnmCell *cell, char const *text)
93 GnmExprTop const *texpr;
94 GnmValue *val;
95 GnmParsePos pos;
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),
102 text, &val, &texpr);
104 if (val != NULL) { /* String was a value */
105 gnm_cell_cleanout (cell);
106 cell->value = val;
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)
115 * @cell: #GnmCell
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
124 * - queue redraws,
125 * - auto-resize
126 * - calculate spans
127 * - does not render.
128 * - mark anything as dirty.
130 * NOTE : This DOES NOT check for array partitioning.
132 void
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);
139 cell->value = v;
143 * gnm_cell_set_value: (skip)
144 * @c: #GnmCell
145 * @v: (transfer full): #GnmValue
147 * WARNING : This is an internal routine that does not
148 * - queue redraws,
149 * - auto-resize
150 * - calculate spans
151 * - does not render.
153 * NOTE : This DOES check for array partitioning.
155 void
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)) {
161 value_release (v);
162 g_return_if_fail (!gnm_cell_is_nonsingleton_array (cell));
165 gnm_cell_cleanout (cell);
166 cell->value = v;
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.
187 void
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)) {
194 value_release (v);
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;
204 cell->value = v;
205 if (link_expr)
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.
215 * Does NOT
216 * - check for array subdivision
217 * - queue recalcs.
218 * - render value, calc dimension, compute spans
219 * - link the expression into the master list.
221 static void
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 ();
230 cell->value = NULL;
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
251 * using this.
253 void
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: (transfer none): 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.
276 void
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.
307 void
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;
314 int x, y;
315 GnmCell *corner;
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) {
337 GnmCell *cell;
338 GnmExprTop const *te;
340 if (x == 0 && y == 0)
341 continue;
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));
354 static void
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,
362 texpr);
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:
370 * @sr:
371 * @texpr:
373 * Returns: (transfer full): the newly allocated #GOUndo.
375 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.
405 gboolean
406 gnm_cell_set_array (Sheet *sheet,
407 const GnmRange *r,
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))
417 return FALSE;
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,
423 texpr);
424 return TRUE;
427 /***************************************************************************/
430 * gnm_cell_is_empty:
431 * @cell: (nullable): #GnmCell
433 * Returns: %TRUE, If the cell has not been created, or has VALUE_EMPTY.
435 gboolean
436 gnm_cell_is_empty (GnmCell const *cell)
438 return cell == NULL || VALUE_IS_EMPTY (cell->value);
442 * gnm_cell_is_blank:
443 * @cell: (nullable): #GnmCell
445 * Returns: %TRUE, if the cell has not been created, has VALUE_EMPTY,
446 * or has an empty VALUE_STRING.
448 gboolean
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');
457 * gnm_cell_is_error:
458 * @cell: #GnmCell
460 * Returns: (nullable) (transfer none): @cell's value if it is an error,
461 * or %NULL.
463 GnmValue *
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))
470 return cell->value;
471 return NULL;
475 * gnm_cell_is_number:
476 * @cell: #GnmCell
478 * Returns: %TRUE, if the cell contains a number.
480 gboolean
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));
488 * gnm_cell_is_zero:
489 * @cell: #GnmCell
491 * Returns: %TRUE, if the cell contains zero.
493 gboolean
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:
502 * @cell: #GnmCell
504 * Returns: (transfer none): @cell's value
506 GnmValue *
507 gnm_cell_get_value (GnmCell const *cell)
509 g_return_val_if_fail (cell != NULL, NULL);
510 return cell->value;
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
520 gboolean
521 gnm_cell_array_bound (GnmCell const *cell, GnmRange *res)
523 GnmExprTop const *texpr;
524 int x, y;
525 int cols, rows;
527 range_init (res, 0, 0, 0, 0);
529 if (NULL == cell || !gnm_cell_has_expr (cell))
530 return FALSE;
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))
545 return FALSE;
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);
552 return TRUE;
556 * gnm_cell_is_array:
557 * @cell: #GnmCell
559 * Returns %TRUE is @cell is part of an array
561 gboolean
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:
571 * @cell: #GnmCell
573 * Returns: %TRUE is @cell is part of an array larger than 1x1
575 gboolean
576 gnm_cell_is_nonsingleton_array (GnmCell const *cell)
578 int cols, rows;
580 if ((cell == NULL) || !gnm_cell_has_expr (cell))
581 return FALSE;
582 if (gnm_expr_top_is_array_elem (cell->base.texpr, NULL, NULL))
583 return TRUE;
585 if (!gnm_expr_top_is_array_corner (cell->base.texpr))
586 return FALSE;
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)
596 * @cell: #GnmCell
598 * Returns: (transfer none): The #GnmRenderedValue for the cell.
600 GnmRenderedValue *
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)
610 * @cell: #GnmCell
612 * Returns:
614 GnmRenderedValue *
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);
623 if (rv)
624 return rv;
626 return gnm_cell_render_value (cell, allow_variable_width);
629 void
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.
642 GnmRenderedValue *
643 gnm_cell_render_value (GnmCell const *cell, gboolean allow_variable_width)
645 GnmRenderedValue *rv;
646 Sheet *sheet;
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);
658 return 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.
668 char *
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.
686 GOColor
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.
708 char *
709 gnm_cell_get_entered_text (GnmCell const *cell)
711 GnmValue const *v;
712 Sheet *sheet;
714 g_return_val_if_fail (cell != NULL, NULL);
716 sheet = cell->base.sheet;
718 if (gnm_cell_has_expr (cell)) {
719 GnmParsePos pp;
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);
730 v = cell->value;
731 if (v != NULL) {
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] != '\'' &&
740 tmp[0] != 0 &&
741 !gnm_expr_char_start_p (tmp)) {
742 GnmValue *val = format_match_number
743 (tmp,
744 gnm_cell_get_format (cell),
745 date_conv);
746 if (val == NULL)
747 return g_strdup (tmp);
748 value_release (val);
750 return g_strconcat ("\'", tmp, NULL);
751 } else {
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>");
761 static gboolean
762 close_to_int (gnm_float x, gnm_float eps)
764 return gnm_abs (x - gnm_fake_round (x)) < eps;
767 static GOFormat *
768 guess_time_format (const char *prefix, gnm_float f)
770 int decs = 0;
771 gnm_float eps = 1e-6;
772 static int maxdecs = 6;
773 GString *str = g_string_new (prefix);
774 GOFormat *fmt;
776 if (f >= 0 && f < 1)
777 g_string_append (str, "hh:mm");
778 else
779 g_string_append (str, "[h]:mm");
780 f *= 24 * 60;
781 if (!close_to_int (f, eps / 60)) {
782 g_string_append (str, ":ss");
783 f *= 60;
784 if (!close_to_int (f, eps)) {
785 g_string_append_c (str, '.');
786 while (decs < maxdecs) {
787 decs++;
788 g_string_append_c (str, '0');
789 f *= 10;
790 if (close_to_int (f, eps))
791 break;
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);
799 maxdecs = --decs;
800 g_string_truncate (str, str->len - 1);
803 g_string_free (str, TRUE);
804 return fmt;
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
818 * editing
820 char *
821 gnm_cell_get_text_for_editing (GnmCell const * cell,
822 gboolean *quoted, int *cursor_pos)
824 GODateConventions const *date_conv;
825 gchar *text = NULL;
827 g_return_val_if_fail (cell != NULL, NULL);
829 if (quoted)
830 *quoted = FALSE;
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);
842 g_strchug (text);
843 g_strchomp (text);
844 break;
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,
850 -1, FALSE, 0, 0);
851 if (cursor_pos)
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);
855 break;
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,
865 -1, FALSE, 0, 0);
866 text = g_string_free (new_str, FALSE);
867 break;
870 case GO_FORMAT_DATE: {
871 GOFormat *new_fmt;
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
881 (fstr->str,
882 f - gnm_floor (f));
883 g_string_free (fstr, TRUE);
886 text = format_value (new_fmt, cell->value,
887 -1, date_conv);
888 if (!text || text[0] == 0) {
889 g_free (text);
890 text = format_value (go_format_general (),
891 cell->value,
893 date_conv);
895 go_format_unref (new_fmt);
896 break;
899 case GO_FORMAT_TIME: {
900 GOFormat *new_fmt = guess_time_format (NULL, f);
902 text = format_value (new_fmt, cell->value, -1,
903 date_conv);
904 go_format_unref (new_fmt);
905 break;
908 default:
909 break;
913 if (!text) {
914 text = gnm_cell_get_entered_text (cell);
915 if (quoted)
916 *quoted = (text[0] == '\'');
919 return text;
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);
935 return rv
936 ? PANGO_PIXELS (rv->layout_natural_height)
937 : 0;
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);
951 return rv
952 ? PANGO_PIXELS (rv->layout_natural_width)
953 : 0;
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);
964 return rv
965 ? rv->indent_left + rv->indent_right
966 : 0;
970 * gnm_cell_get_style:
971 * @cell: #GnmCell to query
973 * Returns: (transfer none): the fully qualified style for @cell.
975 GnmStyle const *
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,
980 cell->pos.col,
981 cell->pos.row);
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.
992 GOFormat const *
993 gnm_cell_get_format_given_style (GnmCell const *cell, GnmStyle const *style)
995 GOFormat const *fmt;
997 g_return_val_if_fail (cell != NULL, go_format_general ());
999 if (style == NULL)
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);
1010 return fmt;
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.
1020 GOFormat const *
1021 gnm_cell_get_format (GnmCell const *cell)
1023 return gnm_cell_get_format_given_style (cell, NULL);
1026 static GnmValue *
1027 cb_set_array_value (GnmCellIter const *iter, gpointer user)
1029 GnmValue const *value = user;
1030 GnmCell *cell = iter->cell;
1031 int x, y;
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))
1038 return NULL;
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));
1045 return NULL;
1049 * gnm_cell_convert_expr_to_value:
1050 * @cell: #GnmCell
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
1057 * recalc.
1059 * WARNING : This is an internal routine that does not queue redraws,
1060 * does not auto-resize, and does not calculate spans.
1062 void
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)) {
1076 int rows, cols;
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,
1084 cb_set_array_value,
1085 gnm_expr_top_get_array_value (texpr));
1086 } else {
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) { }
1097 GType
1098 gnm_cell_get_type (void)
1100 static GType type_cell = 0;
1102 if (!type_cell)
1103 type_cell = g_boxed_type_register_static
1104 ("GnmCell",
1105 cell_boxed_copy,
1106 cell_boxed_free);
1108 return type_cell;