1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * value-sheet.c: Utilies for sheet specific value handling
7 * Miguel de Icaza (miguel@gnu.org).
9 #include <gnumeric-config.h>
10 #include <glib/gi18n-lib.h>
14 #include "gnm-format.h"
19 #include "parse-util.h"
20 #include <goffice/goffice.h>
22 /* Debugging utility to print a GnmValue */
24 value_dump (GnmValue
const *value
)
26 switch (value
->v_any
.type
){
32 g_print ("ERROR: %s\n", value
->v_err
.mesg
->str
);
36 g_print ("BOOLEAN: %s\n", go_locale_boolean_name (value
->v_bool
.val
));
40 g_print ("STRING: %s\n", value
->v_str
.val
->str
);
44 g_print ("NUMBER: %" GNM_FORMAT_f
"\n", value_get_as_float (value
));
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
]);
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
);
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
);
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
));
84 g_print ("Unhandled item type\n");
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
)) {
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
))
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
)) {
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
))
123 * value_area_fetch_x_y:
124 * @v: const #GnmValue *
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
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
))
145 * value_area_get_x_y:
146 * @v: const #GnmValue *
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.
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
&&
165 return v
->v_array
.vals
[x
][y
];
166 } else if (VALUE_IS_CELLRANGE (v
)) {
168 Sheet
*start_sheet
, *end_sheet
;
171 gnm_rangeref_normalize (&v
->v_range
.cell
, ep
,
172 &start_sheet
, &end_sheet
,
174 if (start_sheet
!= end_sheet
)
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
);
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
);
188 gnm_cell_eval (cell
);
192 return value_new_empty ();
199 GnmValueIterFunc func
;
200 int base_col
, base_row
;
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
;
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
226 * For each existing element in an array or range , invoke the
229 * Returns: (transfer none):
230 * non-NULL on error, or VALUE_TERMINATE if some invoked routine requested
231 * to stop (by returning non-NULL).
234 value_area_foreach (GnmValue
const *v
, GnmEvalPos
const *ep
,
236 GnmValueIterFunc func
,
242 g_return_val_if_fail (func
!= NULL
, NULL
);
244 if (VALUE_IS_CELLRANGE (v
)) {
247 Sheet
*start_sheet
, *end_sheet
;
249 gnm_rangeref_normalize (&v
->v_range
.cell
, ep
, &start_sheet
, &end_sheet
, &r
);
252 wrap
.v_iter
.region
= v
;
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
);
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;
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
)