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

22
23
extern int dependency_debugging;

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

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

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

	if (cell->value) {
		value_release (cell->value);
		cell->value = NULL;
	}
77
78
79
80
81
82
83
	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;
84
	}
85

86
	cell->base.flags &= ~(CELL_HAS_EXPRESSION|DEPENDENT_QUEUED_FOR_RECALC);
87
88
}

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

102
	g_return_val_if_fail (cell != NULL, NULL);
103

104
	new_cell = g_new (Cell, 1);
105

106
107
	/* bitmap copy first */
	*new_cell = *cell;
108

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

113
114
	/* now copy properly the rest */
	if (cell_has_expr (new_cell))
115
		expr_tree_ref (new_cell->base.expression);
116
	else
117
		string_ref (new_cell->entered_text);
118

119
	new_cell->rendered_value = NULL;
120

121
122
123
	new_cell->value = (new_cell->value)
	    ? value_duplicate (new_cell->value)
	    : value_new_empty ();
Morten Welinder's avatar
Morten Welinder committed
124

125
126
127
	if (cell->format)
		style_format_ref (cell->format);

128
129
130
	if (cell->comment) {
		new_cell->comment = NULL;
		cell_set_comment (new_cell, cell->comment->comment->str);
Morten Welinder's avatar
Morten Welinder committed
131
	}
Miguel de Icaza's avatar
New:    
Miguel de Icaza committed
132

133
	return new_cell;
Arturo Espinosa's avatar
Arturo Espinosa committed
134
}
Arturo Espinosa's avatar
Arturo Espinosa committed
135

136
137
138
139
140
141
/**
 * cell_destroy: Frees all resources allocated to the cell's content and marks the
 *     Cell's container as dirty.
 *
 * @cell : The cell to destroy
 */
142
void
143
cell_destroy (Cell *cell)
144
145
146
{
	g_return_if_fail (cell != NULL);

147
148
149
150
	cell_dirty (cell);
	cell_cleanout (cell);
	cell_comment_destroy (cell);
	g_free (cell);
151
}
152

153
/**
154
155
 * cell_eval_content:
 * @cell: the cell to evaluate.
156
 *
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
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
 * This function evaluates the contents of the cell,
 * it should not be used by anyone. It is an internal
 * function.
 **/
void
cell_eval_content (Cell *cell)
{
	Value   *v;
	EvalPos	 pos;

	if (!cell_has_expr (cell))
		return;

#ifdef DEBUG_EVALUATION
	if (dependency_debugging > 1) {
		ParsePos pp;

		char *exprtxt = expr_decode_tree
			(cell->base.expression, parse_pos_init_cell (&pp, cell));
		printf ("Evaluating %s: %s ->\n", cell_name (cell), exprtxt);
		g_free (exprtxt);
	}
#endif

	v = eval_expr (eval_pos_init_cell (&pos, cell),
		       cell->base.expression, EVAL_STRICT);

#ifdef DEBUG_EVALUATION
	if (dependency_debugging > 1) {
		char *valtxt = v
			? value_get_as_string (v)
			: g_strdup ("NULL");
		printf ("Evaluating %s: -> %s\n", cell_name (cell), valtxt);
		g_free (valtxt);
	}
#endif

	if (v == NULL)
		v = value_new_error (&pos, "Internal error");

	cell_assign_value (cell, v, NULL);
	rendered_value_calc_size (cell);
	sheet_redraw_cell (cell);
}

/**
 * cell_content_changed: Queues recalc of all of the cells depends.
204
205
206
 */
void
cell_content_changed (Cell *cell)
207
{
208
	GList   *deps;
209

210
211
	g_return_if_fail (cell != NULL);

212
213
214
	/* Queue all of the dependencies for this cell */
	deps = cell_get_dependencies (cell);
	if (deps)
215
		dependent_queue_recalc_list (deps, TRUE);
216
217
}

218
219
/*
 * cell_relocate:
Jody Goldberg's avatar
Jody Goldberg committed
220
221
 * @cell   : The cell that is changing position
 * @rwinfo : An OPTIONAL pointer to allow for bounds checking and relocation
222
223
224
225
226
227
 *
 * 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
228
cell_relocate (Cell *cell, ExprRewriteInfo *rwinfo)
229
{
230
	g_return_if_fail (cell != NULL);
231

232
233
	/* 1. Tag the cell as dirty */
	cell_dirty (cell);
234

235
236
	/* 2. If the cell contains a formula, relocate the formula */
	if (cell_has_expr (cell)) {
237
		ExprTree *expr = cell->base.expression;
Jody Goldberg's avatar
Jody Goldberg committed
238

239
		if (cell_expr_is_linked (cell))
240
			dependent_unlink (CELL_TO_DEP (cell), &cell->pos);
241

242
243
244
245
246
247
248
249
250
		/*
		 * WARNING WARNING WARNING
		 *
		 * This will only work if the new array cell has already
		 * been inserted.
		 *
		 * WARNING WARNING WARNING
		 */
		/* If cell was part of an array, reset the corner pointer */
Jody Goldberg's avatar
Jody Goldberg committed
251
252
253
		if (expr->any.oper == OPER_ARRAY) {
			int const x = expr->array.x;
			int const y = expr->array.y;
254
			if (x != 0 || y != 0)
Jody Goldberg's avatar
Jody Goldberg committed
255
				expr->array.corner.cell =
256
					sheet_cell_get (cell->base.sheet,
257
258
							cell->pos.col - x,
							cell->pos.row - y);
259
		}
260

Jody Goldberg's avatar
Jody Goldberg committed
261
262
263
		/* bounds check, and adjust local references from the cell */
		if (rwinfo != NULL) {
			expr = expr_rewrite (expr, rwinfo);
264

265
			if (expr != NULL) {
266
				/* expression was unlinked above */
267
268
				expr_tree_unref (cell->base.expression);
				cell->base.expression = expr;
269
270
			}
		}
271

272
		/* Relink the expression.  */
273
		dependent_changed (CELL_TO_DEP (cell), &cell->pos, TRUE);
274
275
	}

276
	/* 3. Move any auxiliary canvas items */
277
	if (cell->comment)
278
		cell_comment_reposition (cell);
279
280
}

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/****************************************************************************/

/*
 * cell_set_text : Stores the supplied text as the entered_text, then parses it
 *      for storage as a value or expression.  It marks the sheet as dirty.
 *
 * If the text is an expression it IS queued for recalc.
 *        the format prefered by the expression is stored for later use.
 * If the text is a value it is rendered but spans are not calculated.
 *        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.
 */
297
void
298
cell_set_text (Cell *cell, char const *text)
299
{
300
	StyleFormat *format;
301
302
	Value *val;
	ExprTree *expr;
303
	EvalPos pos;
304

305
	g_return_if_fail (cell != NULL);
306
307
	g_return_if_fail (text != NULL);
	g_return_if_fail (!cell_is_partial_array (cell));
308

309
	format = parse_text_value_or_expr (eval_pos_init_cell (&pos, cell),
Jody Goldberg's avatar
Jody Goldberg committed
310
311
					   text, &val, &expr,
					   NULL /* TODO : Use assigned format ? */);
312

313
314
	if (val != NULL) {	/* String was a value */
		cell_cleanout (cell);
315

316
		cell->base.flags &= ~CELL_HAS_EXPRESSION;
317
		cell->value = val;
318
		cell->entered_text = string_get (text);
319
		cell->format = format;
320
321
		cell_render_value (cell);
	} else {		/* String was an expression */
Jody Goldberg's avatar
Jody Goldberg committed
322
		cell_set_expr (cell, expr, format);
323
		if (format) style_format_unref (format);
324
		expr_tree_unref (expr);
325
	}
326
	cell_dirty (cell);
327
328
}

Miguel de Icaza's avatar
Miguel de Icaza committed
329
/*
330
331
332
333
334
335
 * cell_set_text_and_value : Stores the supplied text as the entered_text, then
 *      stores (WITHOUT COPYING) the supplied value.
 *      It marks the sheet as dirty. The text is NOT parsed.
 *
 * The cell is rendered but spans are not calculated.
 * If an optional format is supplied it is stored for later use.
Miguel de Icaza's avatar
Miguel de Icaza committed
336
 *
337
338
339
340
 * 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.
Miguel de Icaza's avatar
Miguel de Icaza committed
341
 */
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
342
void
343
cell_set_text_and_value (Cell *cell, String *text,
Jody Goldberg's avatar
Jody Goldberg committed
344
			 Value *v, StyleFormat *opt_fmt)
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
345
{
346
347
348
349
	g_return_if_fail (cell);
	g_return_if_fail (text);
	g_return_if_fail (v);
	g_return_if_fail (!cell_is_partial_array (cell));
Arturo Espinosa's avatar
Arturo Espinosa committed
350

Jody Goldberg's avatar
Jody Goldberg committed
351
352
353
	if (opt_fmt != NULL)
		style_format_ref (opt_fmt);

354
355
	cell_dirty (cell);
	cell_cleanout (cell);
356

Jody Goldberg's avatar
Jody Goldberg committed
357
	cell->format = opt_fmt;
358
	cell->entered_text = string_ref (text);
359
360
	cell->value = v;
	cell_render_value (cell);
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
361
362
}

Michael Meeks's avatar
Michael Meeks committed
363
/*
364
365
366
367
 * 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
368
 *
369
 * The value is rendered but spans are not calculated.
Michael Meeks's avatar
Michael Meeks committed
370
 *
371
 * If an optional format is supplied it is stored for later use.
Michael Meeks's avatar
Michael Meeks committed
372
 *
373
374
375
376
377
 * 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
378
379
 */
void
Jody Goldberg's avatar
Jody Goldberg committed
380
cell_assign_value (Cell *cell, Value *v, StyleFormat *opt_fmt)
Michael Meeks's avatar
Michael Meeks committed
381
382
383
384
{
	g_return_if_fail (cell);
	g_return_if_fail (v);

Jody Goldberg's avatar
Jody Goldberg committed
385
386
387
388
389
	if (cell->format)
		style_format_unref (cell->format);
	if (opt_fmt)
		style_format_ref (opt_fmt);
	cell->format = opt_fmt;
390
391
392

	if (cell->value != NULL)
		value_release (cell->value);
Michael Meeks's avatar
Michael Meeks committed
393
394
395
396
397
	cell->value = v;
	cell_render_value (cell);
}

/*
398
399
400
401
402
 * 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
403
 *
404
405
406
407
408
 * 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.
 *
409
410
411
412
 * 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.
413
414
 *
 * NOTE : This DOES check for array partitioning.
Michael Meeks's avatar
Michael Meeks committed
415
416
 */
void
Jody Goldberg's avatar
Jody Goldberg committed
417
cell_set_value (Cell *cell, Value *v, StyleFormat *opt_fmt)
Michael Meeks's avatar
Michael Meeks committed
418
419
420
{
	g_return_if_fail (cell);
	g_return_if_fail (v);
421
	g_return_if_fail (!cell_is_partial_array (cell));
422

Jody Goldberg's avatar
Jody Goldberg committed
423
424
425
	if (opt_fmt)
		style_format_ref (opt_fmt);

426
427
	cell_dirty (cell);
	cell_cleanout (cell);
Michael Meeks's avatar
Michael Meeks committed
428

Jody Goldberg's avatar
Jody Goldberg committed
429
	cell->format = opt_fmt;
430
431
	cell->value = v;
	cell_render_value (cell);
432
433
434
435
436

	/* Be careful that a value passes as a string stays a string */
	if (v->type == VALUE_STRING) {
		/* TODO : add new string routine to avoid the extra copy */
		char *tmp = g_strconcat ("\'", v->v_str.val->str, NULL);
437
		cell->entered_text = string_get (tmp);
438
		g_free (tmp);
Jody Goldberg's avatar
Jody Goldberg committed
439
440
	} else if (opt_fmt) {
		/* If available use the supplied format */
441
		cell->entered_text = string_get (format_value (opt_fmt, v, NULL, NULL));
442
	} else
Jody Goldberg's avatar
Jody Goldberg committed
443
		/* Fall back on using the format applied to the cell */
444
		cell->entered_text = string_ref (cell->rendered_value->rendered_text);
Michael Meeks's avatar
Michael Meeks committed
445
446
}

447
/*
448
 * cell_set_expr_and_value : Stores (WITHOUT COPYING) the supplied value, and
449
450
451
 *        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.
452
 *
453
 * If an optional format is supplied it is stored for later use.
454
 *
455
456
 * The cell is rendered but spans are not calculated,  the cell is NOT marked for
 * recalc.
457
 *
458
459
 * 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
460
 *
461
 * NOTE : This DOES check for array partitioning.
462
 */
463
void
464
cell_set_expr_and_value (Cell *cell, ExprTree *expr, Value *v)
465
{
Arturo Espinosa's avatar
Arturo Espinosa committed
466
	g_return_if_fail (cell != NULL);
467
468
469
470
471
	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);
Arturo Espinosa's avatar
Arturo Espinosa committed
472

473
	cell_dirty (cell);
474
	cell_cleanout (cell);
475

476
	cell->base.expression = expr;
477
	cell->base.flags |= CELL_HAS_EXPRESSION;
478
	dependent_link (CELL_TO_DEP (cell), &cell->pos);
479
480
481
482
483
484
485
#if 0
	/* TODO : Should we add this for consistancy ? */
	cell->format = fmt;
#endif
	cell->value = v;
	cell_render_value (cell);
}
486

487
488
/**
 * cell_set_expr_internal:
489
 * @cell: the cell to set the formula to
490
 * @expr: an expression tree with the formula
491
 * opt_fmt: an optional format to apply to the cell.
492
493
494
495
496
497
 *
 * A private internal utility to store an expression.
 * Does NOT
 * 	- check for array subdivision
 * 	- queue recalcs.
 * 	- render value, calc dimension, compute spans
498
 * 	- link the expression into the master list.
499
 */
Jody Goldberg's avatar
Jody Goldberg committed
500
static void
Jody Goldberg's avatar
Jody Goldberg committed
501
cell_set_expr_internal (Cell *cell, ExprTree *expr, StyleFormat *opt_fmt)
502
{
Jody Goldberg's avatar
Jody Goldberg committed
503
504
	if (opt_fmt != NULL)
		style_format_ref (opt_fmt);
505

506
	expr_tree_ref (expr);
507

508
509
	cell_dirty (cell);
	cell_cleanout (cell);
510

511
512
	if (cell->base.expression)
		expr_tree_unref (cell->base.expression);
513

Jody Goldberg's avatar
Jody Goldberg committed
514
	cell->format = opt_fmt;
515
	cell->base.expression = expr;
516
	cell->base.flags |= CELL_HAS_EXPRESSION;
517

518
519
	/* Until the value is recomputed, we put in this value.  */
	cell->value = value_new_error (NULL, gnumeric_err_RECALC);
520
521
522
}

/*
Jody Goldberg's avatar
Jody Goldberg committed
523
524
525
 * 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.
526
527
528
529
530
531
532
 *
 * The cell IS marked for recalc.
 *
 * 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
533
534
 *           It also DOES NOT CHECK FOR ARRAY DIVISION.  Be very careful
 *           using this.
535
536
 */
void
Jody Goldberg's avatar
Jody Goldberg committed
537
cell_set_expr_unsafe (Cell *cell, ExprTree *expr, StyleFormat *opt_fmt)
538
539
{
	g_return_if_fail (cell != NULL);
540
	g_return_if_fail (expr != NULL);
541

Jody Goldberg's avatar
Jody Goldberg committed
542
	cell_set_expr_internal (cell, expr, opt_fmt);
543
	dependent_changed (CELL_TO_DEP (cell), &cell->pos, TRUE);
544
545
}

Jody Goldberg's avatar
Jody Goldberg committed
546
547
548
549
550
/**
 * 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
551
cell_set_expr (Cell *cell, ExprTree *expr, StyleFormat *opt_fmt)
Jody Goldberg's avatar
Jody Goldberg committed
552
553
554
{
	g_return_if_fail (!cell_is_partial_array (cell));

Jody Goldberg's avatar
Jody Goldberg committed
555
	cell_set_expr_unsafe (cell, expr, opt_fmt);
Jody Goldberg's avatar
Jody Goldberg committed
556
557
}

558
559
560
561
562
563
564
565
/**
 * 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
566
567
 * @queue_recalc : A flag that if true indicates that the cells should be
 *                 queued for recalc.
568
 *
569
 * Uses cell_set_expr_internal to store the formula as an
570
571
572
 * '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
573
574
 * put it at the head of the recalc queue if recalcs are requested.
 *
Jody Goldberg's avatar
Jody Goldberg committed
575
576
577
 * NOTE : Does not add a reference to the expression.  It takes over the callers
 *        reference.
 *
578
579
580
 * Does not regenerate spans, dimensions or autosize cols/rows.
 *
 * DOES NOT CHECK for array partitioning.
581
582
583
584
 */
void
cell_set_array_formula (Sheet *sheet,
			int row_a, int col_a, int row_b, int col_b,
585
			ExprTree *formula,
586
			gboolean queue_recalc)
587
588
589
590
591
{
	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);
592
	ExprTree *wrapper;
593
594
595
596
597

	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
598
599
	g_return_if_fail (col_a <= col_b);
	g_return_if_fail (row_a <= row_b);
600

601
602
603
	wrapper = expr_tree_new_array (0, 0, num_rows, num_cols);
	wrapper->array.corner.func.value = NULL;
	wrapper->array.corner.func.expr = formula;
604
	cell_set_expr_internal (corner, wrapper, NULL);
605
	expr_tree_unref (wrapper);
606
607

	for (x = 0; x < num_cols; ++x)
608
		for (y = 0; y < num_rows; ++y) {
609
610
			Cell *cell;

611
612
			if (x == 0 && y == 0)
				continue;
613

Michael Meeks's avatar
Michael Meeks committed
614
			cell = sheet_cell_fetch (sheet, col_a + x, row_a + y);
615
616
			wrapper = expr_tree_new_array (x, y, num_rows, num_cols);
			wrapper->array.corner.cell = corner;
617
			cell_set_expr_internal (cell, wrapper, NULL);
618
619
			dependent_changed (CELL_TO_DEP (cell),
					   &cell->pos, queue_recalc);
620
			expr_tree_unref (wrapper);
621
622
623
		}

	/* Put the corner at the head of the recalc list */
624
	dependent_changed (CELL_TO_DEP (corner), &corner->pos, queue_recalc);
625
626
}

627
/***************************************************************************/
Arturo Espinosa's avatar
Arturo Espinosa committed
628

629
gboolean
630
cell_is_blank (Cell const * cell)
Arturo Espinosa's avatar
Arturo Espinosa committed
631
{
632
633
	return (cell == NULL || cell->value == NULL ||
		cell->value->type == VALUE_EMPTY);
Arturo Espinosa's avatar
Arturo Espinosa committed
634
}
635

636
Value *
637
cell_is_error (Cell const * cell)
638
{
639
640
	g_return_val_if_fail (cell != NULL, NULL);
	g_return_val_if_fail (cell->value != NULL, NULL);
641

642
643
644
	if (cell->value->type == VALUE_ERROR)
		return cell->value;
	return NULL;
645
646
}

647
gboolean
648
cell_is_number (Cell const *cell)
649
{
650
651
	/* FIXME : This does not handle arrays or ranges */
	return (cell->value && VALUE_IS_NUMBER (cell->value));
652
}
653

654
gboolean
655
cell_is_zero (Cell const *cell)
656
657
658
659
660
{
	Value const * const v = cell->value;
	if (v == NULL)
		return FALSE;
	switch (v->type) {
661
662
	case VALUE_BOOLEAN : return !v->v_bool.val;
	case VALUE_INTEGER : return v->v_int.val == 0;
663
664
	case VALUE_FLOAT :
	{
665
		double const res = v->v_float.val;
666
667
668
669
670
671
672
		return (-1e-10 < res && res < 1e-10);
	}

	default :
		return FALSE;
	}
}
673

674
ExprArray const *
675
cell_is_array (Cell const *cell)
676
{
677
	if (cell != NULL && cell_has_expr (cell) &&
678
679
	    cell->base.expression->any.oper == OPER_ARRAY)
		return &cell->base.expression->array;
680
	return NULL;
681
682
}

683
gboolean
684
cell_is_partial_array (Cell const *cell)
685
{
686
	ExprArray const *ref = cell_is_array (cell);
687
	return ref != NULL && (ref->cols > 1 || ref->rows > 1);
688
689
}

690
/***************************************************************************/
691
692

/*
693
694
 * cell_render_value
 * @cell: The cell whose value needs to be rendered
695
 *
696
697
698
699
700
 * TODO :
 * There is no reason currently for this to allocate the rendered value as
 * seperate entity.  However, in the future I'm thinking of referencing them
 * akin to strings.  We need to do some profiling of how frequently things
 * are shared.
701
702
 */
void
703
cell_render_value (Cell *cell)
704
{
705
	RenderedValue *rv;
706
707
	g_return_if_fail (cell != NULL);

708
	rv = rendered_value_new (cell, NULL);
709
710
711
	if (cell->rendered_value)
		rendered_value_destroy (cell->rendered_value);
	cell->rendered_value = rv;
712
713
}

714

715
MStyle *
716
cell_get_mstyle (Cell const *cell)
717
{
718
	return sheet_style_compute (cell->base.sheet,
719
720
				    cell->pos.col,
				    cell->pos.row);
721
722
723
}

void
724
cell_set_mstyle (Cell const *cell, MStyle *mstyle)
725
726
727
{
	Range         range;

728
729
	range.start = cell->pos;
	range.end   = range.start;
730

731
	sheet_style_attach (cell->base.sheet, range, mstyle);
732
733
}

Morten Welinder's avatar
Morten Welinder committed
734
char *
735
cell_get_format (Cell const *cell)
Morten Welinder's avatar
Morten Welinder committed
736
{
737
	char   *result = NULL;
Jody Goldberg's avatar
Jody Goldberg committed
738
739
740
741
742
	MStyle *mstyle;
	
	g_return_val_if_fail (cell != NULL, g_strdup ("General"));

	mstyle = cell_get_mstyle (cell);
Morten Welinder's avatar
Morten Welinder committed
743
744

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

Morten Welinder's avatar
Morten Welinder committed
747
		/* FIXME: we really should distinguish between "not assigned"
Jody Goldberg's avatar
Jody Goldberg committed
748
749
750
751
		 * and "assigned General".
		 *
		 * 8/20/00 JEG : Do we still need this test ?
		 */
752
753
754
755
		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
756
757
758
759
760
			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);
			}
761
762
		}
	}
Morten Welinder's avatar
Morten Welinder committed
763
764
765
766

	mstyle_unref (mstyle);
	return result;
}
767
768
769
770
771
772

/*
 * cell_set_format:
 *
 * Changes the format for CELL to be FORMAT.  FORMAT should be
 * a number display format as specified on the manual
773
774
 *
 * Does not render, redraw, or respan.
775
776
 */
void
777
cell_set_format (Cell *cell, char const *format)
778
{
Jody Goldberg's avatar
Jody Goldberg committed
779
	MStyle *mstyle = mstyle_new ();
780
781
782

	g_return_if_fail (mstyle != NULL);

783
	mstyle_set_format_text (mstyle, format);
784
785
786
787
	cell_set_mstyle (cell, mstyle);
	cell_dirty (cell);
}

Jody Goldberg's avatar
Jody Goldberg committed
788
789
790
791
792
793
794
795
796
797
798
799
800
/**
 * cell_make_value : drops the expression keeps its value.  Then uses the formatted
 *      result as if that had been entered.
 *
 * NOTE : the cell's expression can not be linked into the expression * list.
 *
 * 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.
801
802
803
804
805
806
807
 */
void
cell_make_value (Cell *cell)
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (cell_has_expr(cell));

808
809
	expr_tree_unref (cell->base.expression);
	cell->base.expression = NULL;
810
	cell->base.flags &= ~CELL_HAS_EXPRESSION;
Jody Goldberg's avatar
Jody Goldberg committed
811
812
813
814
815
816

	if (cell->rendered_value == NULL)
		cell_render_value (cell);

	g_return_if_fail (cell->rendered_value != NULL);

817
	cell->entered_text = string_ref (cell->rendered_value->rendered_text);
818
819
	cell_dirty (cell);
}