Update Spanish translation
[gnumeric.git] / src / value-sheet.c
blob230e93949220da0c37d692fdd7cce5dda3646ecd
2 /*
3 * value-sheet.c: Utilies for sheet specific value handling
5 * Author:
6 * Miguel de Icaza (miguel@gnu.org).
7 */
8 #include <gnumeric-config.h>
9 #include <glib/gi18n-lib.h>
10 #include <gnumeric.h>
12 #include <value.h>
13 #include <gnm-format.h>
14 #include <ranges.h>
15 #include <sheet.h>
16 #include <cell.h>
17 #include <workbook.h>
18 #include <parse-util.h>
19 #include <goffice/goffice.h>
21 /* Debugging utility to print a GnmValue */
22 void
23 value_dump (GnmValue const *value)
25 switch (value->v_any.type){
26 case VALUE_EMPTY:
27 g_print ("EMPTY\n");
28 break;
30 case VALUE_ERROR:
31 g_print ("ERROR: %s\n", value->v_err.mesg->str);
32 break;
34 case VALUE_BOOLEAN:
35 g_print ("BOOLEAN: %s\n", go_locale_boolean_name (value->v_bool.val));
36 break;
38 case VALUE_STRING:
39 g_print ("STRING: %s\n", value->v_str.val->str);
40 break;
42 case VALUE_FLOAT:
43 g_print ("NUMBER: %" GNM_FORMAT_f "\n", value_get_as_float (value));
44 break;
46 case VALUE_ARRAY: {
47 int x, y;
49 g_print ("Array: { ");
50 for (y = 0; y < value->v_array.y; y++)
51 for (x = 0; x < value->v_array.x; x++)
52 value_dump (value->v_array.vals [x][y]);
53 g_print ("}\n");
54 break;
56 case VALUE_CELLRANGE: {
58 * Do NOT normalize the ranges.
59 * Lets see them in their inverted glory if need be.
61 GnmCellRef const *c = &value->v_range.cell.a;
62 Sheet const *sheet = c->sheet;
64 g_print ("CellRange\n");
65 if (sheet && sheet->name_unquoted)
66 g_print ("%s:", sheet->name_quoted);
67 else
68 g_print ("%p :", (void *)sheet);
69 g_print ("%s%s%s%s\n",
70 (c->col_relative ? "":"$"), col_name(c->col),
71 (c->row_relative ? "":"$"), row_name(c->row));
72 c = &value->v_range.cell.b;
73 if (sheet && sheet->name_quoted)
74 g_print ("%s:", sheet->name_unquoted);
75 else
76 g_print ("%p :", (void *)sheet);
77 g_print ("%s%s%s%s\n",
78 (c->col_relative ? "":"$"), col_name(c->col),
79 (c->row_relative ? "":"$"), row_name(c->row));
80 break;
82 default:
83 g_print ("Unhandled item type\n");
87 int
88 value_area_get_width (GnmValue const *v, GnmEvalPos const *ep)
90 g_return_val_if_fail (v, 0);
92 if (VALUE_IS_CELLRANGE (v)) {
93 GnmRange r;
94 Sheet *start_sheet, *end_sheet;
96 g_return_val_if_fail (ep, 0);
97 gnm_rangeref_normalize (&v->v_range.cell, ep, &start_sheet, &end_sheet, &r);
98 return range_width (&r);
99 } else if (VALUE_IS_ARRAY (v))
100 return v->v_array.x;
101 return 1;
105 value_area_get_height (GnmValue const *v, GnmEvalPos const *ep)
107 g_return_val_if_fail (v, 0);
109 if (VALUE_IS_CELLRANGE (v)) {
110 GnmRange r;
111 Sheet *start_sheet, *end_sheet;
113 g_return_val_if_fail (ep, 0);
114 gnm_rangeref_normalize (&v->v_range.cell, ep, &start_sheet, &end_sheet, &r);
115 return range_height (&r);
116 } else if (VALUE_IS_ARRAY (v))
117 return v->v_array.y;
118 return 1;
122 * value_area_fetch_x_y:
123 * @v: const #GnmValue *
124 * @x: column
125 * @y: row
126 * @ep: const #GnmEvalPos *
128 * An internal routine to get a cell from an array or range.
129 * Ensures that elements of CELLRANGE are evaluated
131 * Returns the element if it exists and is non-empty otherwise returns 0
133 GnmValue const *
134 value_area_fetch_x_y (GnmValue const *v, int x, int y, GnmEvalPos const *ep)
136 GnmValue const * const res = value_area_get_x_y (v, x, y, ep);
137 if (VALUE_IS_EMPTY (res))
138 return value_zero;
139 else
140 return res;
144 * value_area_get_x_y:
145 * @v: const #GnmValue *
146 * @x: column
147 * @y: row
148 * @ep: const #GnmEvalPos *
150 * An internal routine to get a cell from an array or range.
151 * Ensures that elements of CELLRANGE are evaluated
153 * If any problems occur a NULL is returned.
155 GnmValue const *
156 value_area_get_x_y (GnmValue const *v, int x, int y, GnmEvalPos const *ep)
158 g_return_val_if_fail (v, NULL);
160 if (VALUE_IS_ARRAY (v)){
161 g_return_val_if_fail (x < v->v_array.x &&
162 y < v->v_array.y,
163 NULL);
164 return v->v_array.vals [x][y];
165 } else if (VALUE_IS_CELLRANGE (v)) {
166 GnmRange r;
167 Sheet *start_sheet, *end_sheet;
168 GnmCell *cell;
170 gnm_rangeref_normalize (&v->v_range.cell, ep,
171 &start_sheet, &end_sheet,
172 &r);
173 if (start_sheet != end_sheet)
174 return NULL;
176 // Full wrap-around
177 x = (r.start.col + x) % gnm_sheet_get_max_cols (start_sheet);
178 y = (r.start.row + y) % gnm_sheet_get_max_rows (start_sheet);
180 /* Speedup */
181 if (start_sheet->cols.max_used < x ||
182 start_sheet->rows.max_used < y)
183 return value_new_empty ();
185 cell = sheet_cell_get (start_sheet, x, y);
186 if (cell != NULL) {
187 gnm_cell_eval (cell);
188 return cell->value;
191 return value_new_empty ();
192 } else
193 return v;
196 typedef struct {
197 GnmValueIter v_iter;
198 GnmValueIterFunc func;
199 int base_col, base_row;
200 gpointer user_data;
201 } WrapperClosure;
203 static GnmValue *
204 cb_wrapper_foreach_cell_in_area (GnmCellIter const *iter, WrapperClosure *wrap)
206 if (iter->cell != NULL) {
207 gnm_cell_eval (iter->cell);
208 wrap->v_iter.v = iter->cell->value;
209 } else
210 wrap->v_iter.v = NULL;
211 wrap->v_iter.x = iter->pp.eval.col - wrap->base_col;
212 wrap->v_iter.y = iter->pp.eval.row - wrap->base_row;
213 wrap->v_iter.cell_iter = iter;
214 return (*wrap->func) (&wrap->v_iter, wrap->user_data);
218 * value_area_foreach:
219 * @v: const #GnmValue
220 * @ep: const #GnmEvalPos
221 * @flags: #CellIterFlags
222 * @func: (scope call): #GnmValueIterFunc
223 * @user_data:
225 * For each existing element in an array or range , invoke the
226 * callback routine.
228 * Returns:
229 * non-%NULL on error, or VALUE_TERMINATE if some the handler requested
230 * to stop (by returning non-%NULL).
232 GnmValue *
233 value_area_foreach (GnmValue const *v, GnmEvalPos const *ep,
234 CellIterFlags flags,
235 GnmValueIterFunc func,
236 gpointer user_data)
238 GnmValueIter v_iter;
239 GnmValue *tmp;
241 g_return_val_if_fail (func != NULL, NULL);
243 if (VALUE_IS_CELLRANGE (v)) {
244 WrapperClosure wrap;
245 GnmRange r;
246 Sheet *start_sheet, *end_sheet;
248 gnm_rangeref_normalize (&v->v_range.cell, ep, &start_sheet, &end_sheet, &r);
250 wrap.v_iter.ep = ep;
251 wrap.v_iter.region = v;
252 wrap.func = func;
253 wrap.user_data = user_data;
254 wrap.base_col = r.start.col;
255 wrap.base_row = r.start.row;
256 return workbook_foreach_cell_in_range (ep, v, flags,
257 (CellIterFunc) cb_wrapper_foreach_cell_in_area, &wrap);
260 v_iter.ep = ep;
261 v_iter.region = v;
262 v_iter.cell_iter = NULL;
264 /* If not an array, apply func to singleton */
265 if (!VALUE_IS_ARRAY (v)) {
266 v_iter.x = v_iter.y = 0;
267 v_iter.v = v;
268 return (*func) (&v_iter, user_data);
271 for (v_iter.x = v->v_array.x; v_iter.x-- > 0;)
272 for (v_iter.y = v->v_array.y; v_iter.y-- > 0;) {
273 v_iter.v = v->v_array.vals [v_iter.x][v_iter.y];
274 if ((tmp = (*func)(&v_iter, user_data)) != NULL)
275 return tmp;
278 return NULL;