Introspection non-fixes.
[gnumeric.git] / src / value-sheet.c
blob051378ebe76e07c5b76844478b80e654e003ce55
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /*
4 * value-sheet.c: Utilies for sheet specific value handling
6 * Author:
7 * Miguel de Icaza (miguel@gnu.org).
8 */
9 #include <gnumeric-config.h>
10 #include <glib/gi18n-lib.h>
11 #include "gnumeric.h"
13 #include "value.h"
14 #include "gnm-format.h"
15 #include "ranges.h"
16 #include "sheet.h"
17 #include "cell.h"
18 #include "workbook.h"
19 #include "parse-util.h"
20 #include <goffice/goffice.h>
22 /* Debugging utility to print a GnmValue */
23 void
24 value_dump (GnmValue const *value)
26 switch (value->v_any.type){
27 case VALUE_EMPTY:
28 g_print ("EMPTY\n");
29 break;
31 case VALUE_ERROR:
32 g_print ("ERROR: %s\n", value->v_err.mesg->str);
33 break;
35 case VALUE_BOOLEAN:
36 g_print ("BOOLEAN: %s\n", go_locale_boolean_name (value->v_bool.val));
37 break;
39 case VALUE_STRING:
40 g_print ("STRING: %s\n", value->v_str.val->str);
41 break;
43 case VALUE_FLOAT:
44 g_print ("NUMBER: %" GNM_FORMAT_f "\n", value_get_as_float (value));
45 break;
47 case VALUE_ARRAY: {
48 int x, y;
50 g_print ("Array: { ");
51 for (y = 0; y < value->v_array.y; y++)
52 for (x = 0; x < value->v_array.x; x++)
53 value_dump (value->v_array.vals [x][y]);
54 g_print ("}\n");
55 break;
57 case VALUE_CELLRANGE: {
59 * Do NOT normalize the ranges.
60 * Lets see them in their inverted glory if need be.
62 GnmCellRef const *c = &value->v_range.cell.a;
63 Sheet const *sheet = c->sheet;
65 g_print ("CellRange\n");
66 if (sheet && sheet->name_unquoted)
67 g_print ("%s:", sheet->name_quoted);
68 else
69 g_print ("%p :", (void *)sheet);
70 g_print ("%s%s%s%s\n",
71 (c->col_relative ? "":"$"), col_name(c->col),
72 (c->row_relative ? "":"$"), row_name(c->row));
73 c = &value->v_range.cell.b;
74 if (sheet && sheet->name_quoted)
75 g_print ("%s:", sheet->name_unquoted);
76 else
77 g_print ("%p :", (void *)sheet);
78 g_print ("%s%s%s%s\n",
79 (c->col_relative ? "":"$"), col_name(c->col),
80 (c->row_relative ? "":"$"), row_name(c->row));
81 break;
83 default:
84 g_print ("Unhandled item type\n");
88 int
89 value_area_get_width (GnmValue const *v, GnmEvalPos const *ep)
91 g_return_val_if_fail (v, 0);
93 if (VALUE_IS_CELLRANGE (v)) {
94 GnmRange r;
95 Sheet *start_sheet, *end_sheet;
97 g_return_val_if_fail (ep, 0);
98 gnm_rangeref_normalize (&v->v_range.cell, ep, &start_sheet, &end_sheet, &r);
99 return range_width (&r);
100 } else if (VALUE_IS_ARRAY (v))
101 return v->v_array.x;
102 return 1;
106 value_area_get_height (GnmValue const *v, GnmEvalPos const *ep)
108 g_return_val_if_fail (v, 0);
110 if (VALUE_IS_CELLRANGE (v)) {
111 GnmRange r;
112 Sheet *start_sheet, *end_sheet;
114 g_return_val_if_fail (ep, 0);
115 gnm_rangeref_normalize (&v->v_range.cell, ep, &start_sheet, &end_sheet, &r);
116 return range_height (&r);
117 } else if (VALUE_IS_ARRAY (v))
118 return v->v_array.y;
119 return 1;
123 * value_area_fetch_x_y:
124 * @v: const #GnmValue *
125 * @x: column
126 * @y: row
127 * @ep: const #GnmEvalPos *
129 * An internal routine to get a cell from an array or range.
130 * Ensures that elements of CELLRANGE are evaluated
132 * Returns the element if it exists and is non-empty otherwise returns 0
134 GnmValue const *
135 value_area_fetch_x_y (GnmValue const *v, int x, int y, GnmEvalPos const *ep)
137 GnmValue const * const res = value_area_get_x_y (v, x, y, ep);
138 if (VALUE_IS_EMPTY (res))
139 return value_zero;
140 else
141 return res;
145 * value_area_get_x_y:
146 * @v: const #GnmValue *
147 * @x: column
148 * @y: row
149 * @ep: const #GnmEvalPos *
151 * An internal routine to get a cell from an array or range.
152 * Ensures that elements of CELLRANGE are evaluated
154 * If any problems occur a NULL is returned.
156 GnmValue const *
157 value_area_get_x_y (GnmValue const *v, int x, int y, GnmEvalPos const *ep)
159 g_return_val_if_fail (v, NULL);
161 if (VALUE_IS_ARRAY (v)){
162 g_return_val_if_fail (x < v->v_array.x &&
163 y < v->v_array.y,
164 NULL);
165 return v->v_array.vals [x][y];
166 } else if (VALUE_IS_CELLRANGE (v)) {
167 GnmRange r;
168 Sheet *start_sheet, *end_sheet;
169 GnmCell *cell;
171 gnm_rangeref_normalize (&v->v_range.cell, ep,
172 &start_sheet, &end_sheet,
173 &r);
174 if (start_sheet != end_sheet)
175 return NULL;
177 // Full wrap-around
178 x = (r.start.col + x) % gnm_sheet_get_max_cols (start_sheet);
179 y = (r.start.row + y) % gnm_sheet_get_max_rows (start_sheet);
181 /* Speedup */
182 if (start_sheet->cols.max_used < x ||
183 start_sheet->rows.max_used < y)
184 return value_new_empty ();
186 cell = sheet_cell_get (start_sheet, x, y);
187 if (cell != NULL) {
188 gnm_cell_eval (cell);
189 return cell->value;
192 return value_new_empty ();
193 } else
194 return v;
197 typedef struct {
198 GnmValueIter v_iter;
199 GnmValueIterFunc func;
200 int base_col, base_row;
201 gpointer user_data;
202 } WrapperClosure;
204 static GnmValue *
205 cb_wrapper_foreach_cell_in_area (GnmCellIter const *iter, WrapperClosure *wrap)
207 if (iter->cell != NULL) {
208 gnm_cell_eval (iter->cell);
209 wrap->v_iter.v = iter->cell->value;
210 } else
211 wrap->v_iter.v = NULL;
212 wrap->v_iter.x = iter->pp.eval.col - wrap->base_col;
213 wrap->v_iter.y = iter->pp.eval.row - wrap->base_row;
214 wrap->v_iter.cell_iter = iter;
215 return (*wrap->func) (&wrap->v_iter, wrap->user_data);
219 * value_area_foreach:
220 * @v: const #GnmValue
221 * @ep: const #GnmEvalPos
222 * @flags: #CellIterFlags
223 * @func: (scope call): #GnmValueIterFunc
224 * @user_data:
226 * For each existing element in an array or range , invoke the
227 * callback routine.
229 * Returns: (transfer none):
230 * non-NULL on error, or VALUE_TERMINATE if some invoked routine requested
231 * to stop (by returning non-NULL).
233 GnmValue *
234 value_area_foreach (GnmValue const *v, GnmEvalPos const *ep,
235 CellIterFlags flags,
236 GnmValueIterFunc func,
237 gpointer user_data)
239 GnmValueIter v_iter;
240 GnmValue *tmp;
242 g_return_val_if_fail (func != NULL, NULL);
244 if (VALUE_IS_CELLRANGE (v)) {
245 WrapperClosure wrap;
246 GnmRange r;
247 Sheet *start_sheet, *end_sheet;
249 gnm_rangeref_normalize (&v->v_range.cell, ep, &start_sheet, &end_sheet, &r);
251 wrap.v_iter.ep = ep;
252 wrap.v_iter.region = v;
253 wrap.func = func;
254 wrap.user_data = user_data;
255 wrap.base_col = r.start.col;
256 wrap.base_row = r.start.row;
257 return workbook_foreach_cell_in_range (ep, v, flags,
258 (CellIterFunc) cb_wrapper_foreach_cell_in_area, &wrap);
261 v_iter.ep = ep;
262 v_iter.region = v;
263 v_iter.cell_iter = NULL;
265 /* If not an array, apply func to singleton */
266 if (!VALUE_IS_ARRAY (v)) {
267 v_iter.x = v_iter.y = 0;
268 v_iter.v = v;
269 return (*func) (&v_iter, user_data);
272 for (v_iter.x = v->v_array.x; v_iter.x-- > 0;)
273 for (v_iter.y = v->v_array.y; v_iter.y-- > 0;) {
274 v_iter.v = v->v_array.vals [v_iter.x][v_iter.y];
275 if ((tmp = (*func)(&v_iter, user_data)) != NULL)
276 return tmp;
279 return NULL;