cell.c 37 KB
Newer Older
1
2
3
4
/*
 * cell.c: Cell management of the Gnumeric spreadsheet.
 *
 * Author:
5
 *    Miguel de Icaza 1998 (miguel@kernel.org)
6
 */
7
#include <config.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
8
#include <gnome.h>
Miguel de Icaza's avatar
Miguel de Icaza committed
9
#include <locale.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
10
#include "gnumeric.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
11
#include "gnumeric-sheet.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
12
#include "eval.h"
13
#include "format.h"
14
#include "color.h"
15
#include "cursors.h"
16
#include "utils.h"
17
#include <ctype.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
18

Michael Meeks's avatar
Michael Meeks committed
19
20
static int         redraws_frozen      = 0;
static int         redraws_deep_frozen = 0;
21
22
static GHashTable *cell_hash_queue;

23
24
25
26
27
28
29
30
31
void
cell_formula_changed (Cell *cell)
{
	g_return_if_fail (cell != NULL);
	
	sheet_cell_formula_link (cell);
	cell_queue_recalc (cell);
}

32
33
34
static inline void
cell_modified (Cell *cell)
{
35
	Sheet *sheet = cell->sheet;
36
37
38
39

	/* Cells from the clipboard do not have a sheet attached */
	if (sheet)
		sheet->modified = TRUE;
40
41
}

Morten Welinder's avatar
Morten Welinder committed
42

Arturo Espinosa's avatar
Arturo Espinosa committed
43
void
44
cell_set_formula (Cell *cell, const char *text)
Arturo Espinosa's avatar
Arturo Espinosa committed
45
{
46
	char *error_msg = _("ERROR");
47
	const char *desired_format = NULL;
Miguel de Icaza's avatar
New:    
Miguel de Icaza committed
48
	
Arturo Espinosa's avatar
Arturo Espinosa committed
49
50
	g_return_if_fail (cell != NULL);
	g_return_if_fail (text != NULL);
51

52
	cell_modified (cell);
Arturo Espinosa's avatar
Arturo Espinosa committed
53
	cell->parsed_node = expr_parse_string (&text [1],
54
					       cell->sheet,
Arturo Espinosa's avatar
Arturo Espinosa committed
55
56
					       cell->col->pos,
					       cell->row->pos,
Miguel de Icaza's avatar
New:    
Miguel de Icaza committed
57
					       &desired_format,
Arturo Espinosa's avatar
Arturo Espinosa committed
58
59
					       &error_msg);
	if (cell->parsed_node == NULL){
60
		cell->flags |= CELL_ERROR;
61
		cell_set_rendered_text (cell, error_msg);
62
63
64
		
		if (cell->value)
			value_release (cell->value);
Arturo Espinosa's avatar
Arturo Espinosa committed
65
		cell->value = NULL;
Arturo Espinosa's avatar
Arturo Espinosa committed
66
		return;
67
68
69
	} else {
		if (cell->flags & CELL_ERROR)
			cell->flags &= ~CELL_ERROR;
Arturo Espinosa's avatar
Arturo Espinosa committed
70
	}
71

Miguel de Icaza's avatar
New:    
Miguel de Icaza committed
72
73
74
75
76
	if (desired_format && strcmp (cell->style->format->format, "General") == 0){
		style_format_unref (cell->style->format);
		cell->style->format = style_format_new (desired_format);
	}

77
	cell_formula_changed (cell);
Arturo Espinosa's avatar
Arturo Espinosa committed
78
}
Arturo Espinosa's avatar
Arturo Espinosa committed
79

Miguel de Icaza's avatar
Miguel de Icaza committed
80
81
82
83
84
85
86
87
88
89
90
/*
 * cell_set_alignment:
 *
 * @cell: the cell to change the alignment of
 * @halign: the horizontal alignemnt
 * @valign: the vertical alignemnt
 * @orient: the text orientation
 *
 * This routine changes the alignment of a cell to those specified.
 */
void
Arturo Espinosa's avatar
Arturo Espinosa committed
91
cell_set_alignment (Cell *cell, int halign, int valign, int orient, int auto_return)
Miguel de Icaza's avatar
Miguel de Icaza committed
92
93
94
95
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (cell->style != NULL);

96
97
98
	if ((cell->style->halign      == halign) &&
	    (cell->style->valign      == valign) &&
	    (cell->style->fit_in_cell == auto_return) &&
Miguel de Icaza's avatar
Miguel de Icaza committed
99
100
101
	    (cell->style->orientation == orient))
		return;

102
103
	cell_modified (cell);

Arturo Espinosa's avatar
Arturo Espinosa committed
104
105
	cell_queue_redraw (cell);
	
Miguel de Icaza's avatar
Miguel de Icaza committed
106
107
108
	cell->style->halign = halign;
	cell->style->valign = valign;
	cell->style->orientation = orient;
Arturo Espinosa's avatar
Arturo Espinosa committed
109
110
111
	cell->style->fit_in_cell = auto_return;
	
	cell_calc_dimensions (cell);
112

Miguel de Icaza's avatar
Miguel de Icaza committed
113
114
115
	cell_queue_redraw (cell);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
116
117
118
119
120
void
cell_set_halign (Cell *cell, StyleHAlignFlags halign)
{
	g_return_if_fail (cell != NULL);

121
	if (((unsigned int)cell->style->halign) == ((unsigned int) halign))
Arturo Espinosa's avatar
Arturo Espinosa committed
122
123
		return;

124
125
	cell_modified (cell);

Arturo Espinosa's avatar
Arturo Espinosa committed
126
127
128
129
130
131
132
	cell_queue_redraw (cell);
	cell->style->halign = halign;

	cell_calc_dimensions (cell);
	cell_queue_redraw (cell);
}

133
134
135
136
137
138
void
cell_set_font_from_style (Cell *cell, StyleFont *style_font)
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (style_font != NULL);

139
140
	cell_modified (cell);

Arturo Espinosa's avatar
Arturo Espinosa committed
141
142
	cell_queue_redraw (cell);
	
143
144
145
146
147
	style_font_unref (cell->style->font);
	style_font_ref (style_font);
	
	cell->style->font = style_font;

Arturo Espinosa's avatar
Arturo Espinosa committed
148
	cell_calc_dimensions (cell);
149
150
151
152
153
	
	cell_queue_redraw (cell);
}

void
154
cell_set_font (Cell *cell, const char *font_name)
155
156
157
158
159
160
161
162
163
164
165
166
{
	StyleFont *style_font;

	g_return_if_fail (cell != NULL);
	g_return_if_fail (font_name != NULL);

	style_font = style_font_new (font_name, 1);

	if (style_font)
		cell_set_font_from_style (cell, style_font);
}

167
168
169
170
171
172
void
cell_set_style (Cell *cell, Style *reference_style)
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (reference_style != NULL);

173
174
	cell_modified (cell);

175
	cell_queue_redraw (cell);
Miguel de Icaza's avatar
New:    
Miguel de Icaza committed
176
	style_destroy (cell->style);
177
	cell->style = style_duplicate (reference_style);
178
179
	if (cell->value)
		cell_render_value (cell);
180
181
182
183
	cell_calc_dimensions (cell);
	cell_queue_redraw (cell);
}

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
void
cell_comment_destroy (Cell *cell)
{
	CellComment *comment;
	GList *l;
	
	g_return_if_fail (cell != NULL);

	comment = cell->comment;
	if (!comment)
		return;
	cell->comment = NULL;

	/* Free resources */
	string_unref (comment->comment);
199
200
201
202
203
204

	if (comment->timer_tag != -1)
		gtk_timeout_remove (comment->timer_tag);

	if (comment->window)
		gtk_object_destroy (GTK_OBJECT (comment->window));
205
206
207
208
209
210
211
	
	for (l = comment->realized_list; l; l = l->next)
		gtk_object_destroy (l->data);
	
	g_free (comment);
}

212
213
214
215
216
217
218
219
220
221
static void
cell_comment_cancel_timer (Cell *cell)
{
	if (cell->comment->timer_tag != -1){
		gtk_timeout_remove (cell->comment->timer_tag);
		cell->comment->timer_tag = -1;
	}
		
}
      
222
223
224
225
226
227
228
229
static void
cell_display_comment (Cell *cell)
{
	GtkWidget *window, *label;
	int x, y;
	
	g_return_if_fail (cell != NULL);

230
231
	cell_comment_cancel_timer (cell);
	
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
	window = gtk_window_new (GTK_WINDOW_POPUP);
	label = gtk_label_new (cell->comment->comment->str);
	gtk_container_add (GTK_CONTAINER (window), label);

	gdk_window_get_pointer (NULL, &x, &y, NULL);
	gtk_widget_set_uposition (window, x+10, y+10);

	gtk_widget_show_all (window);

	cell->comment->window = window;
}

static gint
cell_popup_comment (gpointer data)
{
	Cell *cell = data;
	
	cell->comment->timer_tag = -1;

	cell_display_comment (cell);
	return FALSE;
}

static int
cell_comment_clicked (GnomeCanvasItem *item, GdkEvent *event, Cell *cell)
{
	GnomeCanvas *canvas = item->canvas;

	switch (event->type){
	case GDK_BUTTON_RELEASE:
		if (event->button.button != 1)
			return FALSE;
		if (cell->comment->window)
			return FALSE;
		cell_display_comment (cell);
		break;

	case GDK_BUTTON_PRESS:
		if (event->button.button != 1)
			return FALSE;
		break;
		
	case GDK_ENTER_NOTIFY:
		cell->comment->timer_tag = gtk_timeout_add (1000, cell_popup_comment, cell);
		cursor_set_widget (canvas, GNUMERIC_CURSOR_ARROW);
		break;

	case GDK_LEAVE_NOTIFY:
280
		cell_comment_cancel_timer (cell);
281
282
283
284
285
286
287
288
289
290
291
292
		if (cell->comment->window){
			gtk_object_destroy (GTK_OBJECT (cell->comment->window));
			cell->comment->window = NULL;
		}
		break;
		
	default:
		return FALSE;
	}
	return TRUE;
}

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
static void
cell_comment_realize (Cell *cell)
{
	GList *l;

	g_return_if_fail (cell->comment != NULL);

	sheet_cell_comment_link (cell);
	for (l = ((Sheet *)cell->sheet)->sheet_views; l; l = l->next){
		SheetView *sheet_view = SHEET_VIEW (l->data);
		GnomeCanvasItem *o;
		
		o = sheet_view_comment_create_marker (
			sheet_view, 
			cell->col->pos, cell->row->pos);

		cell->comment->realized_list = g_list_prepend (
			cell->comment->realized_list, o);

		gtk_signal_connect (GTK_OBJECT (o), "event",
				    GTK_SIGNAL_FUNC (cell_comment_clicked), cell);
	}
}

static void
cell_comment_unrealize (Cell *cell)
{
	GList *l;

	g_return_if_fail (cell->comment != NULL);

	sheet_cell_comment_unlink (cell);
	for (l = cell->comment->realized_list; l; l = l->next){
		GnomeCanvasItem *o = l->data;

		gtk_object_destroy (GTK_OBJECT (o));
	}
	g_list_free (cell->comment->realized_list);
	cell->comment->realized_list = NULL;
}

void
cell_realize (Cell *cell)
{
	g_return_if_fail (cell != NULL);

	if (cell->comment)
		cell_comment_realize (cell);
}

void
cell_unrealize (Cell *cell)
{
	g_return_if_fail (cell != NULL);

	if (cell->comment)
		cell_comment_unrealize (cell);
}

352
void
353
cell_set_comment (Cell *cell, const char *str)
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
{
	int had_comments = FALSE;
	
	g_return_if_fail (cell != NULL);
	g_return_if_fail (str != NULL);

	cell_modified (cell);

	cell_comment_destroy (cell);

	cell->comment = g_new (CellComment, 1);
	cell->comment->realized_list = NULL;
	cell->comment->timer_tag = -1;
	cell->comment->window = NULL;
	
	cell->comment->comment = string_get (str);

	if (had_comments)
		cell_queue_redraw (cell);

374
375
	if (cell->sheet)
		cell_comment_realize (cell);
376
377
}

378
379
380
381
void
cell_set_foreground (Cell *cell, gushort red, gushort green, gushort blue)
{
	g_return_if_fail (cell != NULL);
382
383

	cell_modified (cell);
384
385
386
387
388
389
390
391
392
393
	
	if (cell->style->valid_flags & STYLE_FORE_COLOR)
		style_color_unref (cell->style->fore_color);

	cell->style->valid_flags |= STYLE_FORE_COLOR;
	cell->style->fore_color = style_color_new (red, green, blue);

	cell_queue_redraw (cell);
}

394
395
396
397
398
void
cell_set_background (Cell *cell, gushort red, gushort green, gushort blue)
{
	g_return_if_fail (cell != NULL);
	
399
400
	cell_modified (cell);

401
402
403
404
405
406
407
408
409
	if (cell->style->valid_flags & STYLE_BACK_COLOR)
		style_color_unref (cell->style->back_color);

	cell->style->valid_flags |= STYLE_BACK_COLOR;
	cell->style->back_color = style_color_new (red, green, blue);

	cell_queue_redraw (cell);
}

410
411
412
413
414
415
416
417
418
419
420
421
422
/**
 * Null pointers unset the style.
 **/
void
cell_set_color_from_style (Cell *cell, StyleColor *foreground,
			   StyleColor *background)
{
	g_return_if_fail (cell != NULL);
	
	cell_modified (cell);

	if (cell->style->valid_flags & STYLE_FORE_COLOR)
	{
Arturo Espinosa's avatar
Arturo Espinosa committed
423
		cell->style->valid_flags ^= STYLE_FORE_COLOR;
424
425
426
427
428
		style_color_unref (cell->style->fore_color);
	}

	if (cell->style->valid_flags & STYLE_BACK_COLOR)
	{ 
Arturo Espinosa's avatar
Arturo Espinosa committed
429
		cell->style->valid_flags ^= STYLE_BACK_COLOR;
430
431
432
433
434
435
		style_color_unref (cell->style->back_color);
	}

	if (background)
	{
		cell->style->valid_flags |= STYLE_BACK_COLOR;
Arturo Espinosa's avatar
Arturo Espinosa committed
436
		style_color_ref (background);
437
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
438
	cell->style->back_color = background;
439
440
441
442

	if (foreground)
	{
		cell->style->valid_flags |= STYLE_FORE_COLOR;
Arturo Espinosa's avatar
Arturo Espinosa committed
443
		style_color_ref (foreground);
444
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
445
	cell->style->fore_color = foreground;
446
447
448
449

	cell_queue_redraw (cell);
}

450
451
452
453
454
455

void
cell_set_pattern (Cell *cell, int pattern)
{
	g_return_if_fail (cell != NULL);

456
457
	cell_modified (cell);

458
459
460
461
462
463
	cell->style->valid_flags |= STYLE_PATTERN;
	cell->style->pattern = pattern;

	cell_queue_redraw (cell);
}

464
465
466
467
468
/**
 * cell_set_border:
 * @cell: the cell
 * @border_type: an array containing the borders for the cell
 * @border_color: an array of StyleColors with the 
469
470
471
 * NB. don't unref the StyleColor *s you pass.
 */
void
472
473
474
cell_set_border (Cell *cell,
		 StyleBorderType  border_type[4],
		 StyleColor      *border_color[4])
475
476
477
478
479
480
{
	g_return_if_fail (cell != NULL);

	cell_modified (cell);
	
  	if (cell->style->valid_flags & STYLE_BORDER)
481
		style_border_unref (cell->style->border);
482
483

	cell->style->valid_flags |= STYLE_BORDER;
484
	cell->style->border = style_border_new (border_type, border_color);
485
486
487
488

	cell_queue_redraw (cell);
}

Miguel de Icaza's avatar
Miguel de Icaza committed
489
490
491
492
493
494
495
496
/*
 * cell_set_rendered_text
 * @cell:          the cell we will modify
 * @rendered_text: the text we will display
 *
 * This routine sets the rendered text field of the cell
 * it recomputes the bounding box for the cell as well
 */
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
497
void
498
cell_set_rendered_text (Cell *cell, const char *rendered_text)
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
499
{
500
501
	String *oldtext;
	
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
502
503
	g_return_if_fail (cell != NULL);
	g_return_if_fail (rendered_text != NULL);
504

505
	cell_modified (cell);
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
506

507
	oldtext = cell->text;
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
508
	cell->text = string_get (rendered_text);
509
510
511
	if (oldtext)
		string_unref (oldtext);
	
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
512
513
514
	cell_calc_dimensions (cell);
}

Miguel de Icaza's avatar
Miguel de Icaza committed
515
516
517
518
519
520
/*
 * cell_render_value
 * @cell: The cell whose value needs to be rendered
 *
 * The value of the cell is formated according to the format style
 */
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
521
522
523
void
cell_render_value (Cell *cell)
{
524
	StyleColor *color;
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
525
526
527
528
529
	char *str;
	
	g_return_if_fail (cell != NULL);
	g_return_if_fail (cell->value != NULL);

530
531
532
533
	if (cell->render_color){
		style_color_unref (cell->render_color);
		cell->render_color = NULL;
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
534

535
536
537
	str = format_value (cell->style->format, cell->value, &color);
	cell->render_color = color;
	
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
538
539
540
541
	cell_set_rendered_text (cell, str);
	g_free (str);
}

Michael Meeks's avatar
Michael Meeks committed
542
543
544
545
546
547
548
549
550
551
552
553
554
555
/*
 * Sets the value for a cell:
 *
 * This is kind of an internal function and should be only called by
 * routines that know what they are doing.  These are the important
 * differences from cell_set_value:
 *
 *    - It does not queue redraws (so you have to queue the redraw yourself
 *      or queue a full redraw).
 *
 *    - It does not queue any recomputations.  You have to queue the recompute
 *      yourself.
 */
void
Morten Welinder's avatar
Morten Welinder committed
556
cell_set_value_simple (Cell *cell, Value *v)
Michael Meeks's avatar
Michael Meeks committed
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
{
	struct lconv *lconv;
	
	g_return_if_fail (cell);
	g_return_if_fail (v);

	cell_modified (cell);

	if (cell->entered_text)
		string_unref (cell->entered_text);
	cell->entered_text = NULL;
					 
	if (cell->value)
		value_release (cell->value);
	
	if (cell->parsed_node){
		sheet_cell_formula_unlink (cell);

		expr_tree_unref (cell->parsed_node);
		cell->parsed_node = NULL;
	}

	cell->value = v;
	cell_render_value (cell);
}

/*
 * cell_set_value
 *
 * Changes the value of a cell
 */
void
Morten Welinder's avatar
Morten Welinder committed
589
cell_set_value (Cell *cell, Value *v)
Michael Meeks's avatar
Michael Meeks committed
590
591
592
593
594
595
596
597
598
599
600
601
{
	g_return_if_fail (cell);
	g_return_if_fail (v);
	
	cell_queue_redraw (cell);

	cell_set_value_simple (cell, v);
	cell_content_changed (cell);

	cell_queue_redraw (cell);
}

602
603
604
605
606
607
608
609
610
611
612
613
614
/*
 * Sets the text for a cell:
 *
 * This is kind of an internal function and should be only called by
 * routines that know what they are doing.  These are the important
 * differences from cell_set_text:
 *
 *    - It does not queue redraws (so you have to queue the redraw yourself
 *      or queue a full redraw).
 *
 *    - It does not queue any recomputations.  You have to queue the recompute
 *      yourself.
 */
615
void
616
cell_set_text_simple (Cell *cell, const char *text)
617
{
618
619
	struct lconv *lconv;
	
Arturo Espinosa's avatar
Arturo Espinosa committed
620
621
	g_return_if_fail (cell != NULL);
	g_return_if_fail (text != NULL);
Arturo Espinosa's avatar
Arturo Espinosa committed
622

623
624
	cell_modified (cell);

625
626
627
628
	if (cell->entered_text)
		string_unref (cell->entered_text);
	cell->entered_text = string_get (text);
					 
Miguel de Icaza's avatar
New:    
Miguel de Icaza committed
629
630
631
632
	if (cell->value){
		value_release (cell->value);
		cell->value = NULL;
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
633
634
	
	if (cell->parsed_node){
635
		sheet_cell_formula_unlink (cell);
636

Arturo Espinosa's avatar
Arturo Espinosa committed
637
		expr_tree_unref (cell->parsed_node);
638
		cell->parsed_node = NULL;
Arturo Espinosa's avatar
Arturo Espinosa committed
639
	}
640

641
 	if (text [0] == '=' && text [1] != 0){
Arturo Espinosa's avatar
Arturo Espinosa committed
642
643
		cell_set_formula (cell, text); 
	} else {
644
		const char *p;
645
646
		char *end;
		long l;
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
		/* Skip spaces, just in case.  */
		p = text;
		while (isspace (*p)) p++;

		l = strtol (p, &end, 10);
		if (p != end && *end == 0) {
			/* It is an int.  FIXME: long/int confusion here.  */
			cell->value = value_new_int (l);
		} else {
			double d;
			d = strtod (p, &end);
			if (p != end && *end == 0) {
				/* It is a floating point number.  */
				cell->value = value_new_float ((float_t)d);
Arturo Espinosa's avatar
Arturo Espinosa committed
662
			} else {
663
664
				/* It is text.  */
				cell->value = value_new_string (text);
Arturo Espinosa's avatar
Arturo Espinosa committed
665
666
			}
		}
667

Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
668
		cell_render_value (cell);
Michael Meeks's avatar
Michael Meeks committed
669
	}	
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
}

/*
 * cell_content_changed:
 *
 * Call this routine if you modify the contents of a cell
 * to trigger a recompute on any dependencies
 */
void
cell_content_changed (Cell *cell)
{
	GList   *deps;

	g_return_if_fail (cell != NULL);

Arturo Espinosa's avatar
Arturo Espinosa committed
685
686
687
688
689
690
	/* Queue all of the dependencies for this cell */
	deps = cell_get_dependencies (cell->sheet,
				      cell->col->pos,
				      cell->row->pos);
	if (deps)
		cell_queue_recalc_list (deps);
691
692
693
694
695
696
697
698
}

/*
 * cell_set_text
 *
 * Changes the content of a cell
 */
void
699
cell_set_text (Cell *cell, const char *text)
700
701
702
703
704
705
706
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (text != NULL);
	
	cell_queue_redraw (cell);

	cell_set_text_simple (cell, text);
707
	cell_content_changed (cell);
708

709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
	cell_queue_redraw (cell);
}

/**
 * cell_set_formula_tree_simple:
 * @cell:    the cell to set the formula to
 * @formula: an expression tree with the formula
 *
 * This is an internal function.  It should be only called by routines that
 * know what they are doing.  These are the important differences from
 * cell_set_formula:
 *
 *   - It does not queue redraws (so you have to queue the redraw yourself
 *     or queue a full redraw).
 *
 *   - It does not queue any recomputations.  YOu have to queue the
 *     recompute yourself. 
 */
void
cell_set_formula_tree_simple (Cell *cell, ExprTree *formula)
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (formula != NULL);

	cell_modified (cell);

Michael Meeks's avatar
Michael Meeks committed
735
736
	if (cell->parsed_node) {
		sheet_cell_formula_unlink (cell);
737
		expr_tree_unref (cell->parsed_node);
Michael Meeks's avatar
Michael Meeks committed
738
	}
739
740
741
742
743
744
745
746
747
748
749
750
751
752

	cell->parsed_node = formula;
	expr_tree_ref (formula);
	cell_formula_changed (cell);
}

void
cell_set_formula_tree (Cell *cell, ExprTree *formula)
{
	g_return_if_fail (cell != NULL);

	cell_queue_redraw (cell);

	cell_set_formula_tree_simple (cell, formula);
753
	cell_content_changed (cell);
Arturo Espinosa's avatar
Today:    
Arturo Espinosa committed
754
755

	cell_queue_redraw (cell);
Arturo Espinosa's avatar
Arturo Espinosa committed
756
}
Arturo Espinosa's avatar
Arturo Espinosa committed
757

758
759
760
761
762
763
764
765
/**
 * cell_copy:
 * @cell: existing cell to duplicate
 *
 * Makes a copy of a Cell.  
 *
 * Returns a copy of the cell.  Note that the col, row and sheet
 * fields are set to NULL.
Arturo Espinosa's avatar
Arturo Espinosa committed
766
767
 */
Cell *
768
cell_copy (const Cell *cell)
Arturo Espinosa's avatar
Arturo Espinosa committed
769
770
771
772
773
774
775
776
777
778
{
	Cell *new_cell;

	g_return_val_if_fail (cell != NULL, NULL);

	new_cell = g_new (Cell, 1);

	/* bitmap copy first */
	*new_cell = *cell;

779
780
781
	new_cell->col   = NULL;
	new_cell->row   = NULL;
	new_cell->sheet = NULL;
Morten Welinder's avatar
Morten Welinder committed
782
	new_cell->flags &= ~CELL_QUEUED_FOR_RECALC;
783

Morten Welinder's avatar
Morten Welinder committed
784
	/* now copy properly the rest */
785
	if (new_cell->parsed_node)
Morten Welinder's avatar
Morten Welinder committed
786
787
788
789
		expr_tree_ref (new_cell->parsed_node);

	if (new_cell->text)
		string_ref (new_cell->text);
790
791
792
793

	if (new_cell->entered_text)
		string_ref (new_cell->entered_text);

Morten Welinder's avatar
Morten Welinder committed
794
795
796
797
798
	if (new_cell->style)
		new_cell->style = style_duplicate (new_cell->style);

	if (new_cell->render_color)
		style_color_ref (new_cell->render_color);
799
800
801
802
803
804
805

	/*
	 * The cell->value can be NULL if the cell contains
	 * an error
	 */
	if (new_cell->value)
		new_cell->value = value_duplicate (new_cell->value);
Arturo Espinosa's avatar
Arturo Espinosa committed
806

Morten Welinder's avatar
Morten Welinder committed
807
808
	if (cell->comment) {
		new_cell->comment = NULL;
809
		cell_set_comment (new_cell, cell->comment->comment->str);
Morten Welinder's avatar
Morten Welinder committed
810
	}
811

Arturo Espinosa's avatar
Arturo Espinosa committed
812
813
814
815
816
817
818
819
	return new_cell;
}

void
cell_destroy (Cell *cell)
{
	g_return_if_fail (cell != NULL);

Morten Welinder's avatar
Morten Welinder committed
820
821
822
823
824
825
	if (cell_hash_queue && g_hash_table_lookup (cell_hash_queue, cell)) {
		g_warning ("FIXME: Deleting cell %s which was queued for redraw",
			   cell_name (cell->col->pos, cell->row->pos));
		g_hash_table_remove (cell_hash_queue, cell);
	}

826
827
	cell_modified (cell);

Morten Welinder's avatar
Morten Welinder committed
828
	if (cell->parsed_node)
Arturo Espinosa's avatar
Arturo Espinosa committed
829
		expr_tree_unref (cell->parsed_node);
Morten Welinder's avatar
Morten Welinder committed
830
	cell->parsed_node = (void *)0xdeadbeef;
Arturo Espinosa's avatar
Arturo Espinosa committed
831

832
833
	if (cell->render_color)
		style_color_unref (cell->render_color);
Morten Welinder's avatar
Morten Welinder committed
834
	cell->render_color = (void *)0xdeadbeef;
835

836
	cell_comment_destroy (cell);
837
838

	if (cell->text)
839
		string_unref (cell->text);
Morten Welinder's avatar
Morten Welinder committed
840
841
	cell->text = (void *)0xdeadbeef;

842
843
	if (cell->entered_text)
		string_unref (cell->entered_text);
Morten Welinder's avatar
Morten Welinder committed
844
	cell->entered_text = (void *)0xdeadbeef;
845

846
	style_destroy (cell->style);
Morten Welinder's avatar
Morten Welinder committed
847
	cell->style = (void *)0xdeadbeef;
848
849
850

	if (cell->value)
		value_release (cell->value);
Morten Welinder's avatar
Morten Welinder committed
851
	cell->value = (void *)0xdeadbeef;
852
853

	g_free (cell);
Arturo Espinosa's avatar
Arturo Espinosa committed
854
}
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
855

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
void
cell_freeze_redraws (void)
{
	redraws_frozen++;
	if (redraws_frozen == 1)
		cell_hash_queue = g_hash_table_new (g_direct_hash, g_direct_equal);
}

static void
call_cell_queue_redraw (gpointer key, gpointer value, gpointer user_data)
{
	cell_queue_redraw (value);
}

void
cell_thaw_redraws (void)
{
	redraws_frozen--;
	if (redraws_frozen < 0){
		g_warning ("unbalanced freeze/thaw\n");
		return;
	}
	if (redraws_frozen == 0){
		g_hash_table_foreach (cell_hash_queue, call_cell_queue_redraw, NULL);
		g_hash_table_destroy (cell_hash_queue);
		cell_hash_queue = NULL;
	}
}
Michael Meeks's avatar
Michael Meeks committed
884
885
886
887
888
889
890
891
892
893
894
895
896
void
cell_deep_freeze_redraws (void)
{
	redraws_deep_frozen++;
}

void
cell_deep_thaw_redraws (void)
{
	redraws_deep_frozen--;
	if (redraws_frozen < 0)
		g_warning ("unbalanced deep freeze/thaw\n");
}
897
898
899
900
901
902
903
904
905

static void
queue_cell (Cell *cell)
{
	if (g_hash_table_lookup (cell_hash_queue, cell))
		return;
	g_hash_table_insert (cell_hash_queue, cell, cell);
}

Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
906
907
908
void
cell_queue_redraw (Cell *cell)
{
Michael Meeks's avatar
Michael Meeks committed
909
910
911
912
	/* You wake up dead after a deep freeze */
	if (redraws_deep_frozen>0)
		return;

913
	g_return_if_fail (cell != NULL);
914
915
916
917
918

	if (redraws_frozen){
		queue_cell (cell);
		return;
	}
Morten Welinder's avatar
Morten Welinder committed
919

Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
920
921
922
923
924
	sheet_redraw_cell_region (cell->sheet,
				  cell->col->pos, cell->row->pos,
				  cell->col->pos, cell->row->pos);
}

925
926
927
928
929
930
931
932
933
/*
 * cell_set_format_simple:
 *
 * This routine is similar to cell_set_format, but it does not queue
 * any redraws, nor expects the cell to have a value.
 *
 * Make sure you queue a draw in the future for this cell.
 */
void
934
cell_set_format_simple (Cell *cell, const char *format)
935
936
937
938
939
940
941
942
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (format != NULL);
	
	if (strcmp (format, cell->style->format->format) == 0)
		return;

	/* Change the format */
943
	cell_modified (cell);
944
945
	style_format_unref (cell->style->format);
	cell->style->format = style_format_new (format);
946
	cell->flags |= CELL_FORMAT_SET;
947
948
}

949
950
951
952
953
954
/*
 * cell_set_format:
 *
 * Changes the format for CELL to be FORMAT.  FORMAT should be
 * a number display format as specified on the manual
 */
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
955
void
956
cell_set_format (Cell *cell, const char *format)
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
957
{
958
959
	g_return_if_fail (cell != NULL);
	
960
	cell_set_format_simple (cell, format);
Arturo Espinosa's avatar
Arturo Espinosa committed
961
	
962
963
964
	/* re-render the cell text */
	cell_render_value (cell);
	cell_queue_redraw (cell);
965
966
967
968
969
}

void
cell_set_format_from_style (Cell *cell, StyleFormat *style_format)
{
Arturo Espinosa's avatar
Arturo Espinosa committed
970
971
972
	g_return_if_fail (cell != NULL);
	g_return_if_fail (cell->value);
	g_return_if_fail (style_format != NULL);
973
974
975
976
977
978
	
	cell_modified (cell);
	cell_queue_redraw (cell);
	
	/* Change the format */
	style_format_unref (cell->style->format);
Arturo Espinosa's avatar
Arturo Espinosa committed
979
	style_format_ref (style_format);
980

Arturo Espinosa's avatar
Arturo Espinosa committed
981
	cell->style->format = style_format;
982
	cell->flags |= CELL_FORMAT_SET;
983
	
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
984
985
	/* re-render the cell text */
	cell_render_value (cell);
986
	cell_queue_redraw (cell);
Miguel de Icaza's avatar
Today:    
Miguel de Icaza committed
987
}
988

989
990
991
992
993
994
995
996
997
998
999
1000
void
cell_comment_reposition (Cell *cell)
{
	GList *l;
	
	g_return_if_fail (cell != NULL);
	g_return_if_fail (cell->comment != NULL);
	
	for (l = cell->comment->realized_list; l; l = l->next){
		GnomeCanvasItem *o = l->data;
		SheetView *sheet_view = GNUMERIC_SHEET (o->canvas)->sheet_view;