cell.c 6.37 KB
Newer Older
1
#include <config.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
2
#include <gnome.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
3 4
#include "gnumeric.h"
#include "eval.h"
5
#include "format.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
6

7 8 9 10 11 12 13 14 15
void
cell_formula_changed (Cell *cell)
{
	g_return_if_fail (cell != NULL);
	
	sheet_cell_formula_link (cell);
	cell_queue_recalc (cell);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
16 17 18 19
void
cell_set_formula (Cell *cell, char *text)
{
	char *error_msg = NULL;
Arturo Espinosa's avatar
Arturo Espinosa committed
20

Arturo Espinosa's avatar
Arturo Espinosa committed
21 22
	g_return_if_fail (cell != NULL);
	g_return_if_fail (text != NULL);
23

Arturo Espinosa's avatar
Arturo Espinosa committed
24 25 26 27 28 29 30 31 32 33
	cell->parsed_node = expr_parse_string (&text [1],
					       cell->col->pos,
					       cell->row->pos,
					       &error_msg);
	if (cell->parsed_node == NULL){
		if (cell->text)
			string_unref_ptr (&cell->text);
		cell->text = string_get (error_msg);
		return;
	}
34
	cell_formula_changed (cell);
Arturo Espinosa's avatar
Arturo Espinosa committed
35
}
Arturo Espinosa's avatar
Arturo Espinosa committed
36

Miguel de Icaza's avatar
Miguel de Icaza committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
/*
 * 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
cell_set_alignment (Cell *cell, int halign, int valign, int orient)
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (cell->style != NULL);

	if ((cell->style->halign == halign) &&
	    (cell->style->halign == valign) &&
	    (cell->style->orientation == orient))
		return;

	cell->style->halign = halign;
	cell->style->valign = valign;
	cell->style->orientation = orient;

	cell_queue_redraw (cell);
}

/*
 * cell_calc_dimensions
 * @cell:  The cell
 *
 * This routine updates the dimensions of the the rendered text of a cell
 */
Arturo Espinosa's avatar
Arturo Espinosa committed
71
void
72
cell_calc_dimensions (Cell *cell)
Arturo Espinosa's avatar
Arturo Espinosa committed
73 74
{
	char    *rendered_text;
75 76 77
	GdkFont *font;

	g_return_if_fail (cell != NULL);
78 79 80 81 82

	if (cell->text){
		rendered_text = CELL_TEXT_GET (cell);

		font = cell->style->font->font;
83
	
84 85 86 87 88
		cell->width = cell->col->margin_a + cell->col->margin_b + 
			gdk_text_width (font, rendered_text, strlen (rendered_text));
		cell->height = font->ascent + font->descent;
	} else
		cell->width = cell->col->margin_a + cell->col->margin_b;
89 90
}

Miguel de Icaza's avatar
Miguel de Icaza committed
91 92 93 94 95 96 97 98
/*
 * 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
99 100 101 102 103 104 105 106 107 108 109 110 111
void
cell_set_rendered_text (Cell *cell, char *rendered_text)
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (rendered_text != NULL);
	
	if (cell->text)
		string_unref (cell->text);

	cell->text = string_get (rendered_text);
	cell_calc_dimensions (cell);
}

Miguel de Icaza's avatar
Miguel de Icaza committed
112 113 114 115 116 117
/*
 * 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
118 119 120 121 122 123 124 125
void
cell_render_value (Cell *cell)
{
	char *str;
	
	g_return_if_fail (cell != NULL);
	g_return_if_fail (cell->value != NULL);

126
	str = format_value (cell->style->format, cell->value, NULL);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
127 128 129 130
	cell_set_rendered_text (cell, str);
	g_free (str);
}

131 132 133
void
cell_set_text (Cell *cell, char *text)
{
Arturo Espinosa's avatar
Arturo Espinosa committed
134 135 136 137
	GList   *deps;
	
	g_return_if_fail (cell != NULL);
	g_return_if_fail (text != NULL);
Arturo Espinosa's avatar
Arturo Espinosa committed
138

Arturo Espinosa's avatar
Arturo Espinosa committed
139 140
	/* The value entered */
	if (cell->entered_text)
141 142
		string_unref (cell->entered_text);

Arturo Espinosa's avatar
Arturo Espinosa committed
143 144 145
	cell->entered_text = string_get (text);
	
	if (cell->parsed_node){
146
		sheet_cell_formula_unlink (cell);
147

Arturo Espinosa's avatar
Arturo Espinosa committed
148
		expr_tree_unref (cell->parsed_node);
149
		cell->parsed_node = NULL;
Arturo Espinosa's avatar
Arturo Espinosa committed
150
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
151
	
Miguel de Icaza's avatar
Miguel de Icaza committed
152
 	if (text [0] == '='){
Arturo Espinosa's avatar
Arturo Espinosa committed
153 154 155 156 157 158 159 160 161 162 163
		cell_set_formula (cell, text); 
	} else {
		Value *v = g_new (Value, 1);
		int is_text = 0, is_float = 0;
		char *p;
		
		for (p = text; *p && !is_text; p++){
			switch (*p){
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
				break;
164 165 166 167 168

			case '-':
				if (p == text)
					break;
				/* falldown */
Arturo Espinosa's avatar
Arturo Espinosa committed
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
				
			case 'E': case 'e': case '+': case ':': case '.':
				is_float = 1;
				break;
			default:
				is_text = 1;
			}
		}
		if (is_text){
			v->type = VALUE_STRING;
			v->v.str = string_get (text);
		} else {
			if (is_float){
				v->type = VALUE_FLOAT;
				float_get_from_range (text, text+strlen(text),
						      &v->v.v_float);
			} else {
				v->type = VALUE_INTEGER;
				int_get_from_range (text, text+strlen (text),
						    &v->v.v_int);
			}
		}
		cell->value = v;
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
192 193
		
		cell_render_value (cell);
Arturo Espinosa's avatar
Arturo Espinosa committed
194
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
195

Arturo Espinosa's avatar
Arturo Espinosa committed
196 197 198 199 200 201
	/* 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);
Arturo Espinosa's avatar
Arturo Espinosa committed
202
}
Arturo Espinosa's avatar
Arturo Espinosa committed
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220

/*
 * Makes a copy of a Cell
 */
Cell *
cell_copy (Cell *cell)
{
	Cell *new_cell;

	g_return_val_if_fail (cell != NULL, NULL);

	new_cell = g_new (Cell, 1);

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

	/* now copy propertly the rest */
	string_ref      (new_cell->entered_text);
221 222
	if (new_cell->parsed_node)
		expr_tree_ref   (new_cell->parsed_node);
Arturo Espinosa's avatar
Arturo Espinosa committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
	string_ref      (new_cell->text);
	
	new_cell->style = style_duplicate (new_cell->style);
	new_cell->value = value_duplicate (new_cell->value);

	return new_cell;
}

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

	if (cell->parsed_node){
		expr_tree_unref (cell->parsed_node);
	}

	string_unref    (cell->entered_text);
	string_unref    (cell->text);
	style_destroy   (cell->style);
	value_release   (cell->value);
}
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
245 246 247 248

void
cell_queue_redraw (Cell *cell)
{
249 250
	g_return_if_fail (cell != NULL);
	
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
251 252 253 254 255 256 257 258
	sheet_redraw_cell_region (cell->sheet,
				  cell->col->pos, cell->row->pos,
				  cell->col->pos, cell->row->pos);
}

void
cell_set_format (Cell *cell, char *format)
{
259 260 261
	g_return_if_fail (cell != NULL);
	g_return_if_fail (format != NULL);
	
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
262 263 264 265 266 267 268 269 270
	if (strcmp (format, cell->style->format->format) == 0)
		return;

	/* Change the format */
	style_format_unref (cell->style->format);
	cell->style->format = style_format_new (format);

	/* re-render the cell text */
	cell_render_value (cell);
271
	cell_queue_redraw (cell);
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
272
}
273

Arturo Espinosa's avatar
Arturo Espinosa committed
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
void
cell_formula_relocate (Cell *cell, int target_col, int target_row)
{
	char *text, *formula;
	
	g_return_if_fail (cell != NULL);
	g_return_if_fail (cell->entered_text);
	
	string_unref (cell->entered_text);
	
	text = expr_decode_tree (cell->parsed_node, target_col, target_row);
	
	formula = g_copy_strings ("=", text, NULL);
	cell->entered_text = string_get (formula);

Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
289 290
	cell_set_formula (cell, formula);
	
Arturo Espinosa's avatar
Arturo Espinosa committed
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
	g_free (formula);
	g_free (text);
	
	cell_formula_changed (cell);
}

/*
 * This routine drops the formula and just keeps the value
 */
void
cell_make_value (Cell *cell)
{
	g_return_if_fail (cell != NULL);
	g_return_if_fail (cell->parsed_node != NULL);

	expr_tree_unref (cell->parsed_node);
	cell->parsed_node = NULL;
	string_unref (cell->entered_text);
	cell->entered_text = string_ref (cell->text);
}