cell.c 20.8 KB
Newer Older
1
/* vim: set sw=8: */
2 3 4 5
/*
 * cell.c: Cell management of the Gnumeric spreadsheet.
 *
 * Author:
6
 *    Jody Goldberg 2000, 2001 (jgoldberg@home.com)
7
 *    Miguel de Icaza 1998, 1999 (miguel@kernel.org)
8
 */
9
#include "config.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
10
#include "gnumeric.h"
11
#include "cell.h"
12
#include "workbook.h"
13
#include "sheet.h"
14
#include "expr.h"
15
#include "rendered-value.h"
16
#include "value.h"
17
#include "style.h"
Jody Goldberg's avatar
Jody Goldberg committed
18
#include "format.h"
19
#include "sheet-object-cell-comment.h"
20 21
#include "eval.h"
#include "sheet-style.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
22

23 24
extern int dependency_debugging;

25 26 27 28 29 30
/**
 * cell_dirty : Mark the sheet containing the cell as being dirty.
 * @cell : the dirty cell.
 *
 * INTERNAL.
 */
31
static inline void
32
cell_dirty (Cell *cell)
33
{
34
	Sheet *sheet = cell->base.sheet;
35 36 37

	/* Cells from the clipboard do not have a sheet attached */
	if (sheet)
38
		sheet_set_dirty(sheet, TRUE);
39 40
}

41 42 43 44 45
/**
 * cell_cleanout :
 *      Empty a cell's
 *      	- value.
 *      	- rendered_value.
46 47
 *      	- expression.
 *      	- parse format.
48
 *
49 50 51
 *      Clears the flags to
 *      	- not queued for recalc.
 *      	- has no expression.
52
 *
53 54 55 56 57 58
 *      Does NOT change
 *      	- Comments.
 *      	- Spans.
 *      	- unqueue a previously queued recalc.
 *      	- Mark sheet as dirty.
 */
Jody Goldberg's avatar
typo.  
Jody Goldberg committed
59
static void
60 61
cell_cleanout (Cell *cell)
{
62 63
	/* A cell can have either an expression or entered text */
	if (cell_has_expr (cell)) {
64
		/* Clipboard cells, e.g., are not attached to a sheet.  */
65
		if (cell_expr_is_linked (cell))
66 67 68
			dependent_unlink (CELL_TO_DEP (cell), &cell->pos);
		expr_tree_unref (cell->base.expression);
		cell->base.expression = NULL;
69 70 71 72 73 74
	}

	if (cell->value) {
		value_release (cell->value);
		cell->value = NULL;
	}
75 76 77 78 79 80 81
	if (cell->rendered_value) {
		rendered_value_destroy (cell->rendered_value);
		cell->rendered_value = NULL;
	}
	if (cell->format) {
		style_format_unref (cell->format);
		cell->format = NULL;
82
	}
83

Jody Goldberg's avatar
Jody Goldberg committed
84
	cell->base.flags &= ~(CELL_HAS_EXPRESSION|DEPENDENT_IN_RECALC_QUEUE|DEPENDENT_NEEDS_RECALC);
85 86
}

87 88 89 90 91
/**
 * cell_copy:
 * @cell: existing cell to duplicate
 *
 * Makes a copy of a Cell.
Michael Meeks's avatar
Michael Meeks committed
92
 *
93
 * Returns a copy of the cell.
Michael Meeks's avatar
Michael Meeks committed
94
 */
95
Cell *
96
cell_copy (Cell const *cell)
Michael Meeks's avatar
Michael Meeks committed
97
{
98
	Cell *new_cell;
Michael Meeks's avatar
Michael Meeks committed
99

100
	g_return_val_if_fail (cell != NULL, NULL);
101

102
	new_cell = g_new (Cell, 1);
103

104 105
	/* bitmap copy first */
	*new_cell = *cell;
106

107
	/* The new cell is not linked into any of the major management structures */
108
	new_cell->base.sheet = NULL;
Jody Goldberg's avatar
Jody Goldberg committed
109
	new_cell->base.flags &= ~(DEPENDENT_IN_RECALC_QUEUE|DEPENDENT_NEEDS_RECALC|CELL_IN_SHEET_LIST|DEPENDENT_IN_EXPR_LIST);
Morten Welinder's avatar
Morten Welinder committed
110

111 112
	/* now copy properly the rest */
	if (cell_has_expr (new_cell))
113
		expr_tree_ref (new_cell->base.expression);
114

115
	new_cell->rendered_value = NULL;
116

117
	new_cell->value = (new_cell->value)
118 119
		? value_duplicate (new_cell->value)
		: value_new_empty ();
Morten Welinder's avatar
Morten Welinder committed
120

121 122 123
	if (cell->format)
		style_format_ref (cell->format);

124
	return new_cell;
Arturo Espinosa's avatar
Arturo Espinosa committed
125
}
Arturo Espinosa's avatar
Arturo Espinosa committed
126

127 128 129 130 131 132
/**
 * cell_destroy: Frees all resources allocated to the cell's content and marks the
 *     Cell's container as dirty.
 *
 * @cell : The cell to destroy
 */
133
void
134
cell_destroy (Cell *cell)
135 136 137
{
	g_return_if_fail (cell != NULL);

138 139 140
	cell_dirty (cell);
	cell_cleanout (cell);
	g_free (cell);
141
}
142

143
/**
144 145
 * cell_eval_content:
 * @cell: the cell to evaluate.
146
 *
147 148 149 150
 * This function evaluates the contents of the cell,
 * it should not be used by anyone. It is an internal
 * function.
 **/
151
gboolean
152 153
cell_eval_content (Cell *cell)
{
154
	static Cell *iterating = NULL;
155 156
	Value   *v;
	EvalPos	 pos;
157
	int	 max_iteration;
158 159

	if (!cell_has_expr (cell))
160
		return TRUE;
161 162

#ifdef DEBUG_EVALUATION
163
	{
164
		ParsePos pp;
165 166
		char *str = expr_tree_as_string (cell->base.expression,
			parse_pos_init_cell (&pp, cell));
167
		printf ("{\nEvaluating %s: %s;\n", cell_name (cell), str);
168
		g_free (str);
169 170 171
	}
#endif

172
	/* This is the bottom of a cycle */
173
	if (cell->base.flags & DEPENDENT_BEING_CALCULATED) {
174 175 176
		if (!cell->base.sheet->workbook->iteration.enabled)
			return TRUE;

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
		/* but not the first bottom */
		if (cell->base.flags & CELL_BEING_ITERATED) {
#ifdef DEBUG_EVALUATION
			printf ("}; /* already-iterate (%d) */\n", iterating == NULL);
#endif
			return iterating == NULL;
		}

		/* if we are still marked as iterating then make this the last
		 * time through.
		 */
		if (iterating == cell) {
#ifdef DEBUG_EVALUATION
			puts ("}; /* NO-iterate (1) */");
#endif
			return TRUE;
		} else if (iterating == NULL) {
			cell->base.flags |= CELL_BEING_ITERATED;
			iterating = cell;
#ifdef DEBUG_EVALUATION
			puts ("}; /* START iterate = TRUE (0) */");
#endif
			return FALSE;
		} else {
#ifdef DEBUG_EVALUATION
			puts ("}; /* other-iterate (0) */");
#endif
			return FALSE;
		}
206 207
	}

208
	/* Prepare to calculate */
209 210
	eval_pos_init_cell (&pos, cell);
	cell->base.flags |= DEPENDENT_BEING_CALCULATED;
211
	max_iteration = cell->base.sheet->workbook->iteration.max_number;
212

213 214 215 216
iterate :
	v = eval_expr (&pos, cell->base.expression, EVAL_STRICT);
	if (v == NULL)
		v = value_new_error (&pos, "Internal error");
217 218

#ifdef DEBUG_EVALUATION
219
	{
220 221 222
		char *valtxt = v
			? value_get_as_string (v)
			: g_strdup ("NULL");
223
		printf ("Evaluation(%d) %s := %s\n", max_iteration, cell_name (cell), valtxt);
224 225 226 227
		g_free (valtxt);
	}
#endif

228 229 230 231 232
	/* The top of a cycle */
	if (cell->base.flags & CELL_BEING_ITERATED) {
		cell->base.flags &= ~CELL_BEING_ITERATED;

		/* We just completed the last iteration, don't change things */
233
		if (iterating && max_iteration-- > 0) {
234
			/* If we are within bounds make this the last round */
235 236
			if (value_diff (cell->value, v) < cell->base.sheet->workbook->iteration.tolerance)
				max_iteration = 0;
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
			else {
#ifdef DEBUG_EVALUATION
				puts ("/* iterate == NULL */");
#endif
				iterating = NULL;
			}
			value_release (cell->value);
			cell->value = v;
#ifdef DEBUG_EVALUATION
			puts ("/* LOOP */");
#endif
			goto iterate;
		}
		g_return_val_if_fail (iterating, TRUE);
		iterating = NULL;
	} else
		cell_assign_value (cell, v, NULL);

	if (iterating == cell)
		iterating = NULL;
257

258 259 260 261
#ifdef DEBUG_EVALUATION
	printf ("} (%d)\n", iterating == NULL);
#endif
	cell->base.flags &= ~DEPENDENT_BEING_CALCULATED;
262
	sheet_redraw_cell (cell);
263
	return iterating == NULL;
264 265
}

266 267
/*
 * cell_relocate:
Jody Goldberg's avatar
Jody Goldberg committed
268 269
 * @cell   : The cell that is changing position
 * @rwinfo : An OPTIONAL pointer to allow for bounds checking and relocation
270 271 272 273 274 275
 *
 * This routine is used to move a cell to a different location:
 *
 * Auxiliary items canvas items attached to the cell are moved.
 */
void
Jody Goldberg's avatar
Jody Goldberg committed
276
cell_relocate (Cell *cell, ExprRewriteInfo *rwinfo)
277
{
278
	g_return_if_fail (cell != NULL);
279

280 281
	/* 1. Tag the cell as dirty */
	cell_dirty (cell);
282

283 284
	/* 2. If the cell contains a formula, relocate the formula */
	if (cell_has_expr (cell)) {
285
		ExprTree *expr = cell->base.expression;
Jody Goldberg's avatar
Jody Goldberg committed
286

287
		if (cell_expr_is_linked (cell))
288
			dependent_unlink (CELL_TO_DEP (cell), &cell->pos);
289

Jody Goldberg's avatar
Jody Goldberg committed
290 291 292
		/* bounds check, and adjust local references from the cell */
		if (rwinfo != NULL) {
			expr = expr_rewrite (expr, rwinfo);
293

294
			if (expr != NULL) {
295
				/* expression was unlinked above */
296 297
				expr_tree_unref (cell->base.expression);
				cell->base.expression = expr;
298 299
			}
		}
300

301
		/* Relink the expression.  */
302
		dependent_link (CELL_TO_DEP (cell), &cell->pos);
303 304 305
	}
}

306 307 308
/****************************************************************************/

/*
309 310
 * cell_set_text : Parses the supplied text for storage as a value or
 * 		expression.  It marks the sheet as dirty.
311 312 313
 *
 * If the text is an expression it IS queued for recalc.
 *        the format prefered by the expression is stored for later use.
314
 * If the text is a value it is NOT rendered and spans are NOT calculated.
315 316 317 318 319 320 321
 *        the format that matched the text is stored for later use.
 *
 * WARNING : This is an internal routine that does not queue redraws,
 *           does not auto-resize, and does not calculate spans.
 *
 * NOTE : This DOES check for array partitioning.
 */
322
void
323
cell_set_text (Cell *cell, char const *text)
324
{
325
	StyleFormat *format;
326 327
	Value *val;
	ExprTree *expr;
328
	EvalPos pos;
329 330
	MStyle *mstyle;
	StyleFormat *cformat;
331

332
	g_return_if_fail (cell != NULL);
333 334
	g_return_if_fail (text != NULL);
	g_return_if_fail (!cell_is_partial_array (cell));
335

336 337
	mstyle = cell_get_mstyle (cell);
	cformat = mstyle_get_format (mstyle);
338
	format = parse_text_value_or_expr (eval_pos_init_cell (&pos, cell),
339
					   text, &val, &expr, cformat);
340

341 342
	if (val != NULL) {	/* String was a value */
		cell_cleanout (cell);
343

344
		cell->base.flags &= ~CELL_HAS_EXPRESSION;
345
		cell->value = val;
346
		cell->format = format;
347
		cell_render_value (cell, TRUE);
348
	} else {		/* String was an expression */
Jody Goldberg's avatar
Jody Goldberg committed
349
		cell_set_expr (cell, expr, format);
350
		if (format) style_format_unref (format);
351
		expr_tree_unref (expr);
352
	}
353
	cell_dirty (cell);
354 355
}

Michael Meeks's avatar
Michael Meeks committed
356
/*
357 358 359 360
 * cell_assign_value : Stores (WITHOUT COPYING) the supplied value.
 *    no changes are made to the expression or entered text.  This
 *    is for use by routines that wish to store values directly such
 *    as expression calculation or import for array formulas.
Michael Meeks's avatar
Michael Meeks committed
361
 *
362
 * The value is rendered but spans are not calculated.
Michael Meeks's avatar
Michael Meeks committed
363
 *
364
 * If an optional format is supplied it is stored for later use.
Michael Meeks's avatar
Michael Meeks committed
365
 *
366 367 368 369 370
 * WARNING : This is an internal routine that does not queue redraws,
 *           does not auto-resize, does not calculate spans, does
 *           not mark anything as dirty.
 *
 * NOTE : This DOES NOT check for array partitioning.
Michael Meeks's avatar
Michael Meeks committed
371 372
 */
void
Jody Goldberg's avatar
Jody Goldberg committed
373
cell_assign_value (Cell *cell, Value *v, StyleFormat *opt_fmt)
Michael Meeks's avatar
Michael Meeks committed
374 375 376 377
{
	g_return_if_fail (cell);
	g_return_if_fail (v);

Jody Goldberg's avatar
Jody Goldberg committed
378 379 380 381 382
	if (cell->format)
		style_format_unref (cell->format);
	if (opt_fmt)
		style_format_ref (opt_fmt);
	cell->format = opt_fmt;
383 384 385

	if (cell->value != NULL)
		value_release (cell->value);
Michael Meeks's avatar
Michael Meeks committed
386
	cell->value = v;
387
	cell_render_value (cell, TRUE);
Michael Meeks's avatar
Michael Meeks committed
388 389 390
}

/*
391 392 393 394 395
 * cell_set_value : Stores (WITHOUT COPYING) the supplied value.  It marks the
 *          sheet as dirty.
 *
 * The value is rendered but spans are not calculated, then the rendered string
 * is stored as if that is what the user had entered.
Michael Meeks's avatar
Michael Meeks committed
396
 *
397 398 399 400 401
 * If an optional format is supplied it is stored for later use.
 *
 * WARNING : This is an internal routine that does not queue redraws,
 *           does not auto-resize, and does not calculate spans.
 *
402 403 404 405
 * FIXME FIXME FIXME : The current format code only checks against the list of
 * canned formats.  Therefore the rendered string MAY NOT BE PARSEABLE!! if the
 * user has assigned a non-std format.  We need to improve the parser to handle
 * all formats that exist within the workbook.
406 407
 *
 * NOTE : This DOES check for array partitioning.
Michael Meeks's avatar
Michael Meeks committed
408 409
 */
void
Jody Goldberg's avatar
Jody Goldberg committed
410
cell_set_value (Cell *cell, Value *v, StyleFormat *opt_fmt)
Michael Meeks's avatar
Michael Meeks committed
411 412 413
{
	g_return_if_fail (cell);
	g_return_if_fail (v);
414
	g_return_if_fail (!cell_is_partial_array (cell));
415

Jody Goldberg's avatar
Jody Goldberg committed
416 417 418
	if (opt_fmt)
		style_format_ref (opt_fmt);

419 420
	cell_dirty (cell);
	cell_cleanout (cell);
Michael Meeks's avatar
Michael Meeks committed
421

422
	/* TODO : It would be nice to standardize on NULL == General */
423 424
	cell->format = (opt_fmt == NULL || style_format_is_general (opt_fmt))
		? NULL : opt_fmt;
425
	cell->value = v;
Michael Meeks's avatar
Michael Meeks committed
426 427
}

428
/*
429
 * cell_set_expr_and_value : Stores (WITHOUT COPYING) the supplied value, and
430 431 432
 *        references the supplied expression and links it into the expression
 *        list.  It marks the sheet as dirty. It is intended for use by import
 *        routines or operations that do bulk assignment.
433
 *
434
 * If an optional format is supplied it is stored for later use.
435
 *
436
 * WARNING : This is an internal routine that does not queue redraws,
437 438
 *           does not auto-resize, does not calculate spans, and does
 *           not render the value.
Jody Goldberg's avatar
Jody Goldberg committed
439
 *
440
 * NOTE : This DOES check for array partitioning.
441
 */
442
void
443
cell_set_expr_and_value (Cell *cell, ExprTree *expr, Value *v,
444
			 StyleFormat *opt_fmt, gboolean link_expr)
445
{
Arturo Espinosa's avatar
Arturo Espinosa committed
446
	g_return_if_fail (cell != NULL);
447 448 449 450 451
	g_return_if_fail (expr != NULL);
	g_return_if_fail (!cell_is_partial_array (cell));

	/* Repeat after me.  Ref before unref. */
	expr_tree_ref (expr);
452 453
	if (opt_fmt != NULL)
		style_format_ref (opt_fmt);
Arturo Espinosa's avatar
Arturo Espinosa committed
454

455
	cell_dirty (cell);
456
	cell_cleanout (cell);
457

458
	cell->format = opt_fmt;
459
	cell->base.expression = expr;
460
	cell->base.flags |= CELL_HAS_EXPRESSION;
461
	cell->value = v;
462 463
	if (link_expr)
		dependent_link (CELL_TO_DEP (cell), &cell->pos);
464
}
465

466 467
/**
 * cell_set_expr_internal:
468
 * @cell: the cell to set the formula to
469
 * @expr: an expression tree with the formula
470
 * opt_fmt: an optional format to apply to the cell.
471 472 473 474 475 476
 *
 * A private internal utility to store an expression.
 * Does NOT
 * 	- check for array subdivision
 * 	- queue recalcs.
 * 	- render value, calc dimension, compute spans
477
 * 	- link the expression into the master list.
478
 */
Jody Goldberg's avatar
Jody Goldberg committed
479
static void
Jody Goldberg's avatar
Jody Goldberg committed
480
cell_set_expr_internal (Cell *cell, ExprTree *expr, StyleFormat *opt_fmt)
481
{
482
	expr_tree_ref (expr);
Jody Goldberg's avatar
Jody Goldberg committed
483 484
	if (opt_fmt != NULL)
		style_format_ref (opt_fmt);
485

486 487
	cell_dirty (cell);
	cell_cleanout (cell);
488

Jody Goldberg's avatar
Jody Goldberg committed
489
	cell->format = opt_fmt;
490
	cell->base.expression = expr;
491
	cell->base.flags |= CELL_HAS_EXPRESSION;
492

493
	/* Until the value is recomputed, we put in this value.  */
494
	cell->value = value_new_empty ();
495 496 497
}

/*
Jody Goldberg's avatar
Jody Goldberg committed
498 499 500
 * cell_set_expr_unsafe : Stores and references the supplied expression.  It
 *         marks the sheet as dirty.  Intented for use by import routines that
 *         do bulk assignment.
501
 *
502
 * The cell is NOT marked for recalc.
503 504 505 506 507
 *
 * If an optional format is supplied it is stored for later use.
 *
 * WARNING : This is an internal routine that does not queue redraws,
 *           does not auto-resize, and does not calculate spans.
Jody Goldberg's avatar
Jody Goldberg committed
508 509
 *           It also DOES NOT CHECK FOR ARRAY DIVISION.  Be very careful
 *           using this.
510 511
 */
void
Jody Goldberg's avatar
Jody Goldberg committed
512
cell_set_expr_unsafe (Cell *cell, ExprTree *expr, StyleFormat *opt_fmt)
513 514
{
	g_return_if_fail (cell != NULL);
515
	g_return_if_fail (expr != NULL);
516

Jody Goldberg's avatar
Jody Goldberg committed
517
	cell_set_expr_internal (cell, expr, opt_fmt);
518
	dependent_link (CELL_TO_DEP (cell), &cell->pos);
519 520
}

Jody Goldberg's avatar
Jody Goldberg committed
521 522 523 524 525
/**
 * cell_set_expr : A utility wrapper for cell_set_expr_unsafe.  That adds
 *      checks for array subdivision.
 */
void
Jody Goldberg's avatar
Jody Goldberg committed
526
cell_set_expr (Cell *cell, ExprTree *expr, StyleFormat *opt_fmt)
Jody Goldberg's avatar
Jody Goldberg committed
527 528 529
{
	g_return_if_fail (!cell_is_partial_array (cell));

Jody Goldberg's avatar
Jody Goldberg committed
530
	cell_set_expr_unsafe (cell, expr, opt_fmt);
Jody Goldberg's avatar
Jody Goldberg committed
531 532
}

533 534 535 536 537 538 539 540
/**
 * cell_set_array_formula:
 * @sheet:   The sheet to set the formula to.
 * @row_a:   The top row in the destination region.
 * @col_a:   The left column in the destination region.
 * @row_b:   The bottom row in the destination region.
 * @col_b:   The right column in the destination region.
 * @formula: an expression tree with the formula
541 542
 * @queue_recalc : A flag that if true indicates that the cells should be
 *                 queued for recalc.
543
 *
544
 * Uses cell_set_expr_internal to store the formula as an
545 546 547
 * 'array-formula'.  The supplied expression is wrapped in an array
 * operator for each cell in the range and scheduled for recalc.  The
 * upper left corner is handled as a special case and care is taken to
548 549
 * put it at the head of the recalc queue if recalcs are requested.
 *
Jody Goldberg's avatar
Jody Goldberg committed
550 551 552
 * NOTE : Does not add a reference to the expression.  It takes over the callers
 *        reference.
 *
553 554 555
 * Does not regenerate spans, dimensions or autosize cols/rows.
 *
 * DOES NOT CHECK for array partitioning.
556 557 558
 */
void
cell_set_array_formula (Sheet *sheet,
559 560
			int col_a, int row_a, int col_b, int row_b,
			ExprTree *formula)
561 562 563 564 565
{
	int const num_rows = 1 + row_b - row_a;
	int const num_cols = 1 + col_b - col_a;
	int x, y;
	Cell * const corner = sheet_cell_fetch (sheet, col_a, row_a);
566
	ExprTree *wrapper;
567 568 569 570 571

	g_return_if_fail (num_cols > 0);
	g_return_if_fail (num_rows > 0);
	g_return_if_fail (formula != NULL);
	g_return_if_fail (corner != NULL);
Jody Goldberg's avatar
Jody Goldberg committed
572 573
	g_return_if_fail (col_a <= col_b);
	g_return_if_fail (row_a <= row_b);
574

575
	wrapper = expr_tree_new_array (0, 0, num_rows, num_cols);
576 577
	wrapper->array.corner.value = NULL;
	wrapper->array.corner.expr = formula;
578
	cell_set_expr_internal (corner, wrapper, NULL);
579
	expr_tree_unref (wrapper);
580 581

	for (x = 0; x < num_cols; ++x)
582
		for (y = 0; y < num_rows; ++y) {
583 584
			Cell *cell;

585 586
			if (x == 0 && y == 0)
				continue;
587

Michael Meeks's avatar
Michael Meeks committed
588
			cell = sheet_cell_fetch (sheet, col_a + x, row_a + y);
589
			wrapper = expr_tree_new_array (x, y, num_rows, num_cols);
590
			cell_set_expr_internal (cell, wrapper, NULL);
591
			dependent_link (CELL_TO_DEP (cell), &cell->pos);
592
			expr_tree_unref (wrapper);
593 594
		}

595
	dependent_link (CELL_TO_DEP (corner), &corner->pos);
596 597
}

598
/***************************************************************************/
Arturo Espinosa's avatar
Arturo Espinosa committed
599

600
gboolean
601
cell_is_blank (Cell const * cell)
Arturo Espinosa's avatar
Arturo Espinosa committed
602
{
603 604
	return (cell == NULL || cell->value == NULL ||
		cell->value->type == VALUE_EMPTY);
Arturo Espinosa's avatar
Arturo Espinosa committed
605
}
606

607
Value *
608
cell_is_error (Cell const * cell)
609
{
610 611
	g_return_val_if_fail (cell != NULL, NULL);
	g_return_val_if_fail (cell->value != NULL, NULL);
612

613 614 615
	if (cell->value->type == VALUE_ERROR)
		return cell->value;
	return NULL;
616 617
}

618
gboolean
619
cell_is_number (Cell const *cell)
620
{
621 622
	/* FIXME : This does not handle arrays or ranges */
	return (cell->value && VALUE_IS_NUMBER (cell->value));
623
}
624

625
gboolean
626
cell_is_zero (Cell const *cell)
627 628 629 630 631
{
	Value const * const v = cell->value;
	if (v == NULL)
		return FALSE;
	switch (v->type) {
632 633
	case VALUE_BOOLEAN : return !v->v_bool.val;
	case VALUE_INTEGER : return v->v_int.val == 0;
634 635
	case VALUE_FLOAT :
	{
636
		double const res = v->v_float.val;
637 638 639 640 641 642 643
		return (-1e-10 < res && res < 1e-10);
	}

	default :
		return FALSE;
	}
}
644

645
ExprArray const *
646
cell_is_array (Cell const *cell)
647
{
648
	if (cell != NULL && cell_has_expr (cell) &&
649 650
	    cell->base.expression->any.oper == OPER_ARRAY)
		return &cell->base.expression->array;
651
	return NULL;
652 653
}

654
gboolean
655
cell_is_partial_array (Cell const *cell)
656
{
657
	ExprArray const *ref = cell_is_array (cell);
658
	return ref != NULL && (ref->cols > 1 || ref->rows > 1);
659 660
}

661
/***************************************************************************/
662

663 664
/**
 * cell_render_value :
665
 * @cell: The cell whose value needs to be rendered
666
 * @dynamic_width : Allow format to depend on column width.
667
 *
668
 * TODO :
669 670 671 672
 * The reason the rendered values are stored seperately from the Cell is
 * that in the future only visible cells will be rendered.  The render
 * will be SheetControl specific to allow for multiple zooms and different
 * display resolutions.
673 674
 */
void
675
cell_render_value (Cell *cell, gboolean dynamic_width)
676
{
677
	RenderedValue *rv;
678
	MStyle *mstyle;
679

680 681
	g_return_if_fail (cell != NULL);

682 683 684
	mstyle = cell_get_mstyle (cell);

	rv = rendered_value_new (cell, mstyle, dynamic_width);
685 686 687
	if (cell->rendered_value)
		rendered_value_destroy (cell->rendered_value);
	cell->rendered_value = rv;
688 689

	rendered_value_calc_size_ext (cell, mstyle);
690 691
}

692

693
MStyle *
694
cell_get_mstyle (Cell const *cell)
695
{
696 697 698 699
	g_return_val_if_fail (cell != NULL, NULL);
	return sheet_style_get (cell->base.sheet,
				cell->pos.col,
				cell->pos.row);
700 701
}

Morten Welinder's avatar
Morten Welinder committed
702
char *
703
cell_get_format (Cell const *cell)
Morten Welinder's avatar
Morten Welinder committed
704
{
705
	char   *result = NULL;
Jody Goldberg's avatar
Jody Goldberg committed
706
	MStyle *mstyle;
707

Jody Goldberg's avatar
Jody Goldberg committed
708 709 710
	g_return_val_if_fail (cell != NULL, g_strdup ("General"));

	mstyle = cell_get_mstyle (cell);
Morten Welinder's avatar
Morten Welinder committed
711 712

	if (mstyle_is_element_set (mstyle, MSTYLE_FORMAT)) {
Jody Goldberg's avatar
Jody Goldberg committed
713
		StyleFormat const *format = mstyle_get_format (mstyle);
714

Morten Welinder's avatar
Morten Welinder committed
715
		/* FIXME: we really should distinguish between "not assigned"
Jody Goldberg's avatar
Jody Goldberg committed
716 717 718 719
		 * and "assigned General".
		 *
		 * 8/20/00 JEG : Do we still need this test ?
		 */
720 721 722 723
		if (format) {
			/* If the format is General it may have been over
			 * ridden by the format used to parse the input text.
			 */
Jody Goldberg's avatar
Jody Goldberg committed
724 725 726 727 728
			result = style_format_as_XL (format, FALSE);
			if (!strcmp (result, "General") != 0 && cell->format != NULL) {
				g_free (result);
				result = style_format_as_XL (cell->format, FALSE);
			}
729 730
		}
	}
Morten Welinder's avatar
Morten Welinder committed
731 732 733

	return result;
}
734 735 736 737 738 739

/*
 * cell_set_format:
 *
 * Changes the format for CELL to be FORMAT.  FORMAT should be
 * a number display format as specified on the manual
740 741
 *
 * Does not render, redraw, or respan.
742 743
 */
void
744
cell_set_format (Cell *cell, char const *format)
745
{
746
	Range r;
Jody Goldberg's avatar
Jody Goldberg committed
747
	MStyle *mstyle = mstyle_new ();
748 749 750 751

	g_return_if_fail (mstyle != NULL);

	cell_dirty (cell);
752 753 754 755
	mstyle_set_format_text (mstyle, format);

	r.start = r.end = cell->pos;
	sheet_style_apply_range (cell->base.sheet, &r, mstyle);
756 757
}

Jody Goldberg's avatar
Jody Goldberg committed
758
/**
759
 * cell_convert_expr_to_value : drops the expression keeps its value.  Then uses the formatted
Jody Goldberg's avatar
Jody Goldberg committed
760 761
 *      result as if that had been entered.
 *
Morten Welinder's avatar
Morten Welinder committed
762
 * NOTE : the cell's expression cannot be linked into the expression * list.
Jody Goldberg's avatar
Jody Goldberg committed
763 764 765 766 767 768 769 770
 *
 * The cell is rendered but spans are not calculated,  the cell is NOT marked for
 * recalc.
 *
 * WARNING : This is an internal routine that does not queue redraws,
 *           does not auto-resize, and does not calculate spans.
 *
 * NOTE : This DOES NOT check for array partitioning.
771 772
 */
void
773
cell_convert_expr_to_value (Cell *cell)
774 775 776 777
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (cell_has_expr(cell));

778 779 780 781
	/* Clipboard cells, e.g., are not attached to a sheet.  */
	if (cell_expr_is_linked (cell))
		dependent_unlink (CELL_TO_DEP (cell), &cell->pos);

782 783
	expr_tree_unref (cell->base.expression);
	cell->base.expression = NULL;
784
	cell->base.flags &= ~CELL_HAS_EXPRESSION;
Jody Goldberg's avatar
Jody Goldberg committed
785 786

	if (cell->rendered_value == NULL)
787
		cell_render_value (cell, TRUE);
Jody Goldberg's avatar
Jody Goldberg committed
788

789 790
	cell_dirty (cell);
}
791

792 793 794 795 796 797 798 799 800 801