1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * graph.c: The gnumeric specific data wrappers for GOffice
5 * Copyright (C) 2003-2005 Jody Goldberg (jody@gnome.org)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) version 3.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
22 #include <gnumeric-config.h>
24 #include "dependent.h"
28 #include "number-match.h"
33 #include "gnm-format.h"
34 #include "auto-format.h"
36 #include "parse-util.h"
37 #include "expr-impl.h"
38 #include <goffice/goffice.h>
40 #include <gsf/gsf-impl-utils.h>
43 /* ------------------------------------------------------------------------- */
46 get_pending_str (const GOData
*data
)
48 return g_object_get_data (G_OBJECT (data
), "unserialize");
51 static GnmConventions
*
52 get_pending_convs (const GOData
*data
)
54 return g_object_get_data (G_OBJECT (data
), "unserialize-convs");
58 set_pending_str (const GOData
*data
, const char *str
)
60 g_object_set_data_full (G_OBJECT (data
),
61 "unserialize", g_strdup (str
),
66 set_pending_convs (GOData
*data
, const GnmConventions
*convs
)
68 g_object_set_data_full (G_OBJECT (data
),
70 gnm_conventions_ref ((gpointer
)convs
),
71 (GDestroyNotify
)gnm_conventions_unref
);
74 /* ------------------------------------------------------------------------- */
77 render_val (GnmValue
const *v
, int i
, int j
,
78 GOFormat
const *fmt
, GnmEvalPos
const *ep
)
80 GODateConventions
const *date_conv
;
85 date_conv
= ep
->sheet
? sheet_date_conv (ep
->sheet
) : NULL
;
88 g_printerr ("Rendering %s with fmt=%s\n",
89 value_peek_string (v
),
90 fmt
? go_format_as_XL (fmt
) : "-");
93 if (VALUE_IS_CELLRANGE (v
)) {
94 Sheet
*start_sheet
, *end_sheet
;
98 gnm_rangeref_normalize (&v
->v_range
.cell
, ep
,
99 &start_sheet
, &end_sheet
, &r
);
102 cell
= sheet_cell_get (start_sheet
, r
.start
.col
, r
.start
.row
);
105 gnm_cell_eval (cell
);
109 fmt
= gnm_cell_get_format (cell
);
110 } else if (VALUE_IS_ARRAY (v
))
111 v
= value_area_get_x_y (v
, i
, j
, ep
);
113 return format_value (fmt
, v
, -1, date_conv
);
116 /* ------------------------------------------------------------------------- */
118 static GnmDependent
*gnm_go_data_get_dep (GOData
const *obj
);
121 gnm_go_data_dup (GOData
const *src
)
123 GOData
*dst
= g_object_new (G_OBJECT_TYPE (src
), NULL
);
124 GnmDependent
const *src_dep
= gnm_go_data_get_dep (src
);
125 GnmDependent
*dst_dep
= gnm_go_data_get_dep (dst
);
127 dst_dep
->texpr
= src_dep
->texpr
;
129 gnm_expr_top_ref (dst_dep
->texpr
);
132 dependent_set_sheet (dst_dep
, src_dep
->sheet
);
134 if (dst_dep
->texpr
== NULL
) {
135 set_pending_str (dst
, get_pending_str (src
));
136 set_pending_convs (dst
, get_pending_convs (src
));
139 return GO_DATA (dst
);
143 gnm_go_data_eq (GOData
const *data_a
, GOData
const *data_b
)
145 GnmDependent
const *a
= gnm_go_data_get_dep (data_a
);
146 GnmDependent
const *b
= gnm_go_data_get_dep (data_b
);
148 if (a
->texpr
== NULL
&& b
->texpr
== NULL
) {
149 if (go_str_compare (get_pending_str (data_a
),
150 get_pending_str (data_b
)))
152 if (get_pending_convs (data_a
) != get_pending_convs (data_b
))
157 return a
->texpr
&& b
->texpr
&& gnm_expr_top_equal (a
->texpr
, b
->texpr
);
161 gnm_go_data_preferred_fmt (GOData
const *dat
)
164 GnmDependent
const *dep
= gnm_go_data_get_dep (dat
);
166 g_return_val_if_fail (dep
!= NULL
, NULL
);
168 eval_pos_init_dep (&ep
, dep
);
170 ? (GOFormat
*)gnm_auto_style_format_suggest (dep
->texpr
, &ep
)
174 static GODateConventions
const *
175 gnm_go_data_date_conv (GOData
const *dat
)
177 GnmDependent
const *dep
= gnm_go_data_get_dep (dat
);
179 g_return_val_if_fail (dep
!= NULL
, NULL
);
184 return sheet_date_conv (dep
->sheet
);
188 gnm_go_data_serialize (GOData
const *dat
, gpointer user
)
191 GnmConventions
const *convs
= user
;
192 GnmDependent
const *dep
= gnm_go_data_get_dep (dat
);
194 if (dep
->sheet
== NULL
)
195 return g_strdup ("No sheet for GnmGOData");
197 g_warning ("NULL convs in gnm_go_data_serialize");
198 convs
= gnm_conventions_default
;
201 res
= gnm_expr_top_as_string (dep
->texpr
,
202 parse_pos_init_dep (&pp
, dep
),
205 g_printerr ("Serializing %s\n", res
);
211 gnm_go_data_unserialize (GOData
*dat
, char const *str
, gpointer user
)
213 GnmConventions
const *convs
= user
;
214 GnmExprTop
const *texpr
;
216 GnmDependent
*dep
= gnm_go_data_get_dep (dat
);
219 g_warning ("NULL convs in gnm_go_data_serialize");
220 convs
= gnm_conventions_default
;
223 /* It is too early in the life cycle to know where we
224 * are. Wait until later when we parse the sheet */
225 if (dep
->sheet
== NULL
) {
226 set_pending_str (dat
, str
);
227 /* Ugh. We assume that convs will stay valid. */
228 set_pending_convs (dat
, convs
);
232 parse_pos_init_dep (&pp
, dep
);
233 texpr
= gnm_expr_parse_str (str
, &pp
, (GO_IS_DATA_VECTOR (dat
))?
234 GNM_EXPR_PARSE_PERMIT_MULTIPLE_EXPRESSIONS
:
235 GNM_EXPR_PARSE_DEFAULT
,
238 dependent_set_expr (dep
, texpr
);
239 gnm_expr_top_unref (texpr
);
246 gnm_go_data_set_sheet (GOData
*dat
, Sheet
*sheet
)
248 GnmDependent
*dep
= gnm_go_data_get_dep (dat
);
253 if (dependent_is_linked (dep
)) {
254 dependent_unlink (dep
);
262 * Do we need to parse one now that we have more context ? */
263 if (dep
->texpr
== NULL
) {
264 char const *str
= get_pending_str (dat
);
265 GnmConventions
*convs
= get_pending_convs (dat
);
266 if (str
!= NULL
) { /* bingo */
267 dep
->sheet
= sheet
; /* cheat a bit */
268 if (gnm_go_data_unserialize (dat
, str
, convs
)) {
269 set_pending_str (dat
, NULL
);
270 set_pending_convs (dat
, NULL
);
271 go_data_emit_changed (GO_DATA (dat
));
277 dependent_set_sheet (dep
, sheet
);
281 * gnm_go_data_get_sheet:
284 * Returns: (transfer none): the sheet.
287 gnm_go_data_get_sheet (GOData
const *dat
)
289 GnmDependent
*dep
= gnm_go_data_get_dep (dat
);
290 g_return_val_if_fail (dep
!= NULL
, NULL
);
295 gnm_go_data_get_expr (GOData
const *dat
)
297 GnmDependent
*dep
= gnm_go_data_get_dep (dat
);
304 * gnm_go_data_foreach_dep:
307 * @func: (scope call):
312 gnm_go_data_foreach_dep (GOData
*dat
, SheetObject
*so
,
313 SheetObjectForeachDepFunc func
, gpointer user
)
315 GnmDependent
*dep
= gnm_go_data_get_dep (dat
);
317 func (dep
, so
, user
);
320 /**************************************************************************/
322 struct _GnmGODataScalar
{
328 typedef GODataScalarClass GnmGODataScalarClass
;
330 #define DEP_TO_SCALAR(d_ptr) (GnmGODataScalar *)(((char *)d_ptr) - G_STRUCT_OFFSET (GnmGODataScalar, dep))
332 static GObjectClass
*scalar_parent_klass
;
335 scalar_get_val (GnmGODataScalar
*scalar
)
337 if (scalar
->val
!= NULL
) {
338 value_release (scalar
->val
);
340 g_free (scalar
->val_str
);
341 scalar
->val_str
= NULL
;
343 if (scalar
->val
== NULL
) {
344 if (scalar
->dep
.texpr
!= NULL
) {
347 eval_pos_init_dep (&pos
, &scalar
->dep
);
349 scalar
->val
= gnm_expr_top_eval
350 (scalar
->dep
.texpr
, &pos
,
351 GNM_EXPR_EVAL_PERMIT_EMPTY
);
353 scalar
->val
= value_new_empty ();
359 gnm_go_data_scalar_eval (GnmDependent
*dep
)
361 GnmGODataScalar
*scalar
= DEP_TO_SCALAR (dep
);
363 value_release (scalar
->val
);
365 g_free (scalar
->val_str
);
366 scalar
->val_str
= NULL
;
367 go_data_emit_changed (GO_DATA (scalar
));
371 gnm_go_data_scalar_finalize (GObject
*obj
)
373 GnmGODataScalar
*scalar
= (GnmGODataScalar
*)obj
;
375 dependent_set_expr (&scalar
->dep
, NULL
);
376 value_release (scalar
->val
);
378 g_free (scalar
->val_str
);
379 scalar
->val_str
= NULL
;
381 scalar_parent_klass
->finalize (obj
);
385 gnm_go_data_scalar_get_value (GODataScalar
*dat
)
387 return value_get_as_float (scalar_get_val ((GnmGODataScalar
*)dat
));
391 gnm_go_data_scalar_get_str (GODataScalar
*dat
)
393 GnmGODataScalar
*scalar
= (GnmGODataScalar
*)dat
;
394 GOFormat
const *fmt
= NULL
;
396 if (scalar
->val_str
== NULL
) {
399 eval_pos_init_dep (&ep
, &scalar
->dep
);
400 if (scalar
->dep
.texpr
)
401 fmt
= gnm_auto_style_format_suggest (scalar
->dep
.texpr
, &ep
);
403 render_val (scalar_get_val (scalar
), 0, 0, fmt
, &ep
);
405 go_format_unref (fmt
);
406 return scalar
->val_str
;
409 static PangoAttrList
const *
410 gnm_go_data_scalar_get_markup (GODataScalar
*dat
)
412 PangoAttrList
const *res
= NULL
;
413 GOFormat
const *fmt
= gnm_go_data_preferred_fmt (GO_DATA (dat
));
414 if (fmt
&& go_format_is_markup (fmt
))
415 res
= go_format_get_markup (fmt
);
416 go_format_unref (fmt
);
421 gnm_go_data_scalar_class_init (GObjectClass
*gobject_klass
)
423 GODataClass
*godata_klass
= (GODataClass
*) gobject_klass
;
424 GODataScalarClass
*scalar_klass
= (GODataScalarClass
*) gobject_klass
;
426 scalar_parent_klass
= g_type_class_peek_parent (gobject_klass
);
427 gobject_klass
->finalize
= gnm_go_data_scalar_finalize
;
428 godata_klass
->dup
= gnm_go_data_dup
;
429 godata_klass
->eq
= gnm_go_data_eq
;
430 godata_klass
->preferred_fmt
= gnm_go_data_preferred_fmt
;
431 godata_klass
->date_conv
= gnm_go_data_date_conv
;
432 godata_klass
->serialize
= gnm_go_data_serialize
;
433 godata_klass
->unserialize
= gnm_go_data_unserialize
;
434 scalar_klass
->get_value
= gnm_go_data_scalar_get_value
;
435 scalar_klass
->get_str
= gnm_go_data_scalar_get_str
;
436 scalar_klass
->get_markup
= gnm_go_data_scalar_get_markup
;
440 gnm_go_data_scalar_debug_name (GnmDependent
const *dep
, GString
*target
)
442 g_string_append_printf (target
, "GraphScalar%p", (void *)dep
);
445 static DEPENDENT_MAKE_TYPE (gnm_go_data_scalar
, NULL
)
448 gnm_go_data_scalar_init (GObject
*obj
)
450 GnmGODataScalar
*scalar
= (GnmGODataScalar
*)obj
;
451 scalar
->dep
.flags
= gnm_go_data_scalar_get_dep_type ();
454 GSF_CLASS (GnmGODataScalar
, gnm_go_data_scalar
,
455 gnm_go_data_scalar_class_init
, gnm_go_data_scalar_init
,
459 gnm_go_data_scalar_new_expr (Sheet
*sheet
, GnmExprTop
const *texpr
)
461 GnmGODataScalar
*res
= g_object_new (gnm_go_data_scalar_get_type (), NULL
);
462 res
->dep
.texpr
= texpr
;
463 res
->dep
.sheet
= sheet
;
464 return GO_DATA (res
);
467 /**************************************************************************/
469 struct _GnmGODataVector
{
477 typedef GODataVectorClass GnmGODataVectorClass
;
479 #define DEP_TO_VECTOR(d_ptr) (GnmGODataVector *)(((char *)d_ptr) - G_STRUCT_OFFSET (GnmGODataVector, dep))
481 static GObjectClass
*vector_parent_klass
;
484 gnm_go_data_vector_eval (GnmDependent
*dep
)
486 GnmGODataVector
*vec
= DEP_TO_VECTOR (dep
);
488 value_release (vec
->val
);
491 g_ptr_array_free (vec
->markup
, TRUE
);
495 g_ptr_array_free (vec
->strs
, TRUE
);
498 go_data_emit_changed (GO_DATA (vec
));
502 gnm_go_data_vector_finalize (GObject
*obj
)
504 GnmGODataVector
*vec
= (GnmGODataVector
*)obj
;
506 dependent_set_expr (&vec
->dep
, NULL
);
507 value_release (vec
->val
);
510 g_free (vec
->base
.values
);
511 vec
->base
.values
= NULL
;
513 g_ptr_array_free (vec
->markup
, TRUE
);
517 g_ptr_array_free (vec
->strs
, TRUE
);
521 vector_parent_klass
->finalize (obj
);
525 gnm_go_data_vector_load_len (GODataVector
*dat
)
527 GnmGODataVector
*vec
= (GnmGODataVector
*)dat
;
530 Sheet
*start_sheet
, *end_sheet
;
531 int old_len
= dat
->len
;
534 eval_pos_init_dep (&ep
, &vec
->dep
);
535 if (vec
->val
== NULL
&& vec
->dep
.texpr
!= NULL
) {
537 if (GNM_EXPR_GET_OPER (vec
->dep
.texpr
->expr
) == GNM_EXPR_OP_SET
&&
538 gnm_expr_is_rangeref (vec
->dep
.texpr
->expr
) &&
539 ((l
= gnm_expr_top_get_ranges (vec
->dep
.texpr
))) &&
541 unsigned len
= g_slist_length (l
);
544 vec
->val
= value_new_array_empty (len
, 1);
545 for (i
= 0; i
< len
; i
++) {
546 vec
->val
->v_array
.vals
[i
][0] = cur
->data
;
552 for (cur
= l
; cur
!= NULL
; cur
= cur
->next
)
553 value_release (cur
->data
);
555 vec
->val
= gnm_expr_top_eval (vec
->dep
.texpr
, &ep
,
556 GNM_EXPR_EVAL_PERMIT_NON_SCALAR
| GNM_EXPR_EVAL_PERMIT_EMPTY
| GNM_EXPR_EVAL_ARRAY_CONTEXT
);
561 if (vec
->val
!= NULL
) {
562 switch (vec
->val
->v_any
.type
) {
563 case VALUE_CELLRANGE
:
564 gnm_rangeref_normalize (&vec
->val
->v_range
.cell
, &ep
,
565 &start_sheet
, &end_sheet
, &r
);
567 /* add +1 to max_used so that we can have matrices with
568 * empty cells at the end, see #684072 */
569 if (r
.end
.col
> start_sheet
->cols
.max_used
)
570 r
.end
.col
= start_sheet
->cols
.max_used
+ 1;
571 if (r
.end
.row
> start_sheet
->rows
.max_used
)
572 r
.end
.row
= start_sheet
->rows
.max_used
+ 1;
574 if (r
.end
.col
>= r
.start
.col
&& r
.end
.row
>= r
.start
.row
) {
575 guint w
= range_width (&r
);
576 guint h
= range_height (&r
);
578 new_len
= (guint64
)h
* w
* (end_sheet
->index_in_wb
- start_sheet
->index_in_wb
+ 1);
586 for (j
= 0; j
< vec
->val
->v_array
.y
; j
++)
587 for (i
= 0; i
< vec
->val
->v_array
.x
; i
++) {
588 v
= vec
->val
->v_array
.vals
[i
][j
];
589 if (VALUE_IS_CELLRANGE (v
)) {
590 gnm_rangeref_normalize (&v
->v_range
.cell
, &ep
,
591 &start_sheet
, &end_sheet
, &r
);
592 new_len
+= (guint64
)range_width (&r
) * range_height (&r
)
593 * (end_sheet
->index_in_wb
- start_sheet
->index_in_wb
+ 1);
597 vec
->as_col
= (vec
->val
->v_array
.y
> vec
->val
->v_array
.x
);
611 /* Protect against overflow in ->len as well as when allocating ->values. */
612 new_len
= MIN (new_len
, (gint64
)(G_MAXINT
/ sizeof (dat
->values
[0])));
615 if (dat
->values
!= NULL
&& old_len
!= dat
->len
) {
616 g_free (dat
->values
);
619 dat
->base
.flags
|= GO_DATA_VECTOR_LEN_CACHED
;
622 struct assign_closure
{
623 const GODateConventions
*date_conv
;
624 double minimum
, maximum
;
632 cb_assign_val (GnmCellIter
const *iter
, struct assign_closure
*dat
)
637 if ((gssize
)dat
->i
>= dat
->vals_len
)
640 if (iter
->cell
!= NULL
) {
641 gnm_cell_eval (iter
->cell
);
642 v
= iter
->cell
->value
;
646 if (VALUE_IS_EMPTY_OR_ERROR (v
)) {
647 dat
->vals
[dat
->i
++] = go_nan
;
652 if (VALUE_IS_STRING (v
)) {
653 v
= format_match_number (value_peek_string (v
), NULL
,
656 dat
->vals
[dat
->i
++] = go_nan
;
659 res
= value_get_as_float (v
);
662 res
= value_get_as_float (v
);
664 dat
->vals
[dat
->i
++] = res
;
665 if (dat
->minimum
> res
)
667 if (dat
->maximum
< res
)
673 gnm_go_data_vector_load_values (GODataVector
*dat
)
675 GnmGODataVector
*vec
= (GnmGODataVector
*)dat
;
678 Sheet
*start_sheet
, *end_sheet
;
679 double *vals
, minimum
, maximum
;
681 struct assign_closure closure
;
683 (void)go_data_vector_get_len (dat
); /* force calculation */
685 if (dat
->len
<= 0 || !vec
->dep
.sheet
) {
687 dat
->minimum
= go_nan
;
688 dat
->maximum
= go_nan
;
689 dat
->base
.flags
|= GO_DATA_CACHE_IS_VALID
;
693 closure
.date_conv
= sheet_date_conv (vec
->dep
.sheet
);
695 if (dat
->values
== NULL
)
696 dat
->values
= g_new (double, dat
->len
);
698 switch (vec
->val
->v_any
.type
) {
699 case VALUE_CELLRANGE
:
700 gnm_rangeref_normalize (&vec
->val
->v_range
.cell
,
701 eval_pos_init_dep (&ep
, &vec
->dep
),
702 &start_sheet
, &end_sheet
, &r
);
704 /* clip here rather than relying on sheet_foreach
705 * because that only clips if we ignore blanks
706 * but add +1 to max_used so that we can have matrices with
707 * empty cells at the end, see #684072 */
708 if (r
.end
.row
> start_sheet
->rows
.max_used
)
709 r
.end
.row
= start_sheet
->rows
.max_used
+ 1;
710 if (r
.end
.col
> start_sheet
->cols
.max_used
)
711 r
.end
.col
= start_sheet
->cols
.max_used
+ 1;
713 /* In case the sheet is empty */
714 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
) {
715 closure
.maximum
= - G_MAXDOUBLE
;
716 closure
.minimum
= G_MAXDOUBLE
;
717 closure
.vals
= dat
->values
;
718 closure
.vals_len
= dat
->len
;
721 if (start_sheet
!= end_sheet
)
722 workbook_foreach_cell_in_range (&ep
, vec
->val
,
723 CELL_ITER_IGNORE_FILTERED
,
724 (CellIterFunc
)cb_assign_val
,
727 sheet_foreach_cell_in_range
728 (start_sheet
, CELL_ITER_IGNORE_FILTERED
,
730 (CellIterFunc
)cb_assign_val
, &closure
);
731 dat
->len
= closure
.last
+ 1; /* clip */
732 minimum
= closure
.minimum
;
733 maximum
= closure
.maximum
;
735 minimum
= maximum
= vals
[0] = go_nan
;
739 guint64 last
= 0, max
= dat
->len
;
740 int len
= vec
->val
->v_array
.y
* vec
->val
->v_array
.x
;
741 int x
= 0, y
= vec
->val
->v_array
.y
;
743 maximum
= - G_MAXDOUBLE
;
744 minimum
= G_MAXDOUBLE
;
747 x
= vec
->val
->v_array
.x
;
751 v
= vec
->val
->v_array
.vals
[x
][y
];
753 if (VALUE_IS_CELLRANGE (v
)) {
754 gnm_rangeref_normalize (&v
->v_range
.cell
,
755 eval_pos_init_dep (&ep
, &vec
->dep
),
756 &start_sheet
, &end_sheet
, &r
);
758 /* clip here rather than relying on sheet_foreach
759 * because that only clips if we ignore blanks */
760 if (r
.end
.row
> start_sheet
->rows
.max_used
)
761 r
.end
.row
= start_sheet
->rows
.max_used
;
762 if (r
.end
.col
> start_sheet
->cols
.max_used
)
763 r
.end
.col
= start_sheet
->cols
.max_used
;
765 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
) {
766 closure
.maximum
= - G_MAXDOUBLE
;
767 closure
.minimum
= G_MAXDOUBLE
;
768 closure
.vals
= dat
->values
;
769 closure
.vals_len
= max
;
770 closure
.last
= last
- 1;
772 if (start_sheet
!= end_sheet
)
773 workbook_foreach_cell_in_range (&ep
, vec
->val
,
774 CELL_ITER_IGNORE_FILTERED
,
775 (CellIterFunc
)cb_assign_val
,
778 sheet_foreach_cell_in_range (start_sheet
,
779 CELL_ITER_IGNORE_FILTERED
,
781 (CellIterFunc
)cb_assign_val
, &closure
);
782 last
= dat
->len
= closure
.last
+ 1; /* clip */
783 if (minimum
> closure
.minimum
)
784 minimum
= closure
.minimum
;
785 if (maximum
< closure
.maximum
)
786 maximum
= closure
.maximum
;
789 } else if (VALUE_IS_EMPTY_OR_ERROR (v
)) {
792 } else if (VALUE_IS_STRING (v
)) {
793 GnmValue
*tmp
= format_match_number
794 (value_peek_string (v
), NULL
,
800 vals
[len
] = value_get_as_float (tmp
);
803 vals
[len
] = value_get_as_float (v
);
804 if (minimum
> vals
[len
])
806 if (maximum
< vals
[len
])
813 v
= format_match_number (value_peek_string (vec
->val
),
817 minimum
= maximum
= vals
[0] = value_get_as_float (v
);
821 /* fall through to errors */
825 minimum
= maximum
= vals
[0] = go_nan
;
828 minimum
= maximum
= vals
[0] = value_get_as_float (vec
->val
);
833 dat
->minimum
= minimum
;
834 dat
->maximum
= maximum
;
835 dat
->base
.flags
|= GO_DATA_CACHE_IS_VALID
;
839 gnm_go_data_vector_get_value (GODataVector
*dat
, unsigned i
)
841 GnmGODataVector
*vec
= (GnmGODataVector
*)dat
;
844 gboolean valid
= FALSE
;
846 if (vec
->val
== NULL
)
847 gnm_go_data_vector_load_len (dat
);
849 if (VALUE_IS_ARRAY (vec
->val
)) {
850 if ((dat
->base
.flags
& GO_DATA_CACHE_IS_VALID
) == 0)
851 gnm_go_data_vector_load_values (dat
);
852 return dat
->values
[i
];
854 eval_pos_init_dep (&ep
, &vec
->dep
);
855 v
= value_dup (vec
->as_col
856 ? value_area_get_x_y (vec
->val
, 0, i
, &ep
)
857 : value_area_get_x_y (vec
->val
, i
, 0, &ep
));
861 v
= value_coerce_to_number (v
, &valid
, &ep
);
863 gnm_float res
= value_get_as_float (v
);
873 struct string_closure
{
875 GODateConventions
const *date_conv
;
879 cb_assign_string (GnmCellIter
const *iter
, struct string_closure
*closure
)
884 if (iter
->cell
!= NULL
) {
885 gnm_cell_eval (iter
->cell
);
886 v
= iter
->cell
->value
;
889 str
= format_value (gnm_cell_get_format (iter
->cell
), v
, -1, closure
->date_conv
);
890 g_ptr_array_add (closure
->strs
, str
);
896 gnm_go_data_vector_get_str (GODataVector
*dat
, unsigned i
)
898 GnmGODataVector
*vec
= (GnmGODataVector
*)dat
;
901 GOFormat
const *fmt
= NULL
;
905 if (vec
->val
== NULL
)
906 gnm_go_data_vector_load_len (dat
);
907 g_return_val_if_fail (vec
->val
!= NULL
, NULL
);
909 eval_pos_init_dep (&ep
, &vec
->dep
);
910 if (VALUE_IS_ARRAY (vec
->val
)) {
911 /* we need to cache the strings if needed */
912 if (vec
->strs
== NULL
) {
913 int len
= vec
->val
->v_array
.y
* vec
->val
->v_array
.x
;
914 int x
= 0, y
= vec
->val
->v_array
.y
;
915 struct string_closure closure
;
916 closure
.strs
= vec
->strs
= g_ptr_array_new_with_free_func (g_free
);
917 closure
.date_conv
= ep
.sheet
? sheet_date_conv (ep
.sheet
) : NULL
;
920 x
= vec
->val
->v_array
.x
;
924 v
= vec
->val
->v_array
.vals
[x
][y
];
926 if (VALUE_IS_CELLRANGE (v
)) {
927 /* actually we only need to cache in that case */
928 Sheet
*start_sheet
, *end_sheet
;
930 gnm_rangeref_normalize (&v
->v_range
.cell
,
931 eval_pos_init_dep (&ep
, &vec
->dep
),
932 &start_sheet
, &end_sheet
, &r
);
934 /* clip here rather than relying on sheet_foreach
935 * because that only clips if we ignore blanks */
936 if (r
.end
.row
> start_sheet
->rows
.max_used
)
937 r
.end
.row
= start_sheet
->rows
.max_used
;
938 if (r
.end
.col
> start_sheet
->cols
.max_used
)
939 r
.end
.col
= start_sheet
->cols
.max_used
;
941 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
)
942 sheet_foreach_cell_in_range (start_sheet
,
943 CELL_ITER_IGNORE_FILTERED
,
945 (CellIterFunc
)cb_assign_string
, &closure
);
949 if (vec
->strs
&& vec
->strs
->len
> i
)
950 ret
= g_ptr_array_index (vec
->strs
, i
);
952 return g_strdup (ret
);
953 } else if (VALUE_IS_CELLRANGE (vec
->val
)) {
954 Sheet
*start_sheet
, *end_sheet
;
956 if (vec
->strs
== NULL
) {
957 struct string_closure closure
;
958 closure
.strs
= vec
->strs
= g_ptr_array_new_with_free_func (g_free
);
959 closure
.date_conv
= ep
.sheet
? sheet_date_conv (ep
.sheet
) : NULL
;
960 gnm_rangeref_normalize (&vec
->val
->v_range
.cell
,
961 eval_pos_init_dep (&ep
, &vec
->dep
),
962 &start_sheet
, &end_sheet
, &r
);
964 /* clip here rather than relying on sheet_foreach
965 * because that only clips if we ignore blanks */
966 if (r
.end
.row
> start_sheet
->rows
.max_used
)
967 r
.end
.row
= start_sheet
->rows
.max_used
;
968 if (r
.end
.col
> start_sheet
->cols
.max_used
)
969 r
.end
.col
= start_sheet
->cols
.max_used
;
971 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
)
972 sheet_foreach_cell_in_range (start_sheet
,
973 CELL_ITER_IGNORE_FILTERED
,
975 (CellIterFunc
)cb_assign_string
, &closure
);
977 if (vec
->strs
&& vec
->strs
->len
> i
)
978 ret
= g_ptr_array_index (vec
->strs
, i
);
980 return g_strdup (ret
);
986 ret
= render_val (((v
!= NULL
)? v
: vec
->val
), i
, j
, fmt
, &ep
);
991 cond_pango_attr_list_unref (PangoAttrList
*al
)
994 pango_attr_list_unref (al
);
998 cb_assign_markup (GnmCellIter
const *iter
, GPtrArray
*markup
)
1000 PangoAttrList
const *l
= NULL
;
1002 if (iter
->cell
!= NULL
) {
1003 GOFormat
const *fmt
= gnm_cell_get_format (iter
->cell
);
1004 if (go_format_is_markup (fmt
))
1005 l
= go_format_get_markup (fmt
);
1007 g_ptr_array_add (markup
,
1008 l
? pango_attr_list_ref ((PangoAttrList
*)l
) : NULL
);
1013 static PangoAttrList
*
1014 gnm_go_data_vector_get_markup (GODataVector
*dat
, unsigned i
)
1016 GnmGODataVector
*vec
= (GnmGODataVector
*)dat
;
1018 if (vec
->markup
== NULL
) {
1022 Sheet
*start_sheet
, *end_sheet
;
1025 go_data_vector_get_len (dat
); /* force calculation */
1026 if (dat
->len
<= 0 || !vec
->dep
.sheet
)
1028 vec
->markup
= g_ptr_array_new_with_free_func
1029 ((GDestroyNotify
)cond_pango_attr_list_unref
);
1030 switch (vec
->val
->v_any
.type
) {
1031 case VALUE_CELLRANGE
:
1032 gnm_rangeref_normalize (&vec
->val
->v_range
.cell
,
1033 eval_pos_init_dep (&ep
, &vec
->dep
),
1034 &start_sheet
, &end_sheet
, &r
);
1036 /* clip here rather than relying on sheet_foreach
1037 * because that only clips if we ignore blanks */
1038 if (r
.end
.row
> start_sheet
->rows
.max_used
)
1039 r
.end
.row
= start_sheet
->rows
.max_used
;
1040 if (r
.end
.col
> start_sheet
->cols
.max_used
)
1041 r
.end
.col
= start_sheet
->cols
.max_used
;
1043 /* In case the sheet is empty */
1044 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
) {
1045 sheet_foreach_cell_in_range (start_sheet
,
1048 (CellIterFunc
)cb_assign_markup
, vec
->markup
);
1053 int len
= vec
->as_col
? vec
->val
->v_array
.y
: vec
->val
->v_array
.x
;
1056 ? vec
->val
->v_array
.vals
[0][len
]
1057 : vec
->val
->v_array
.vals
[len
][0];
1059 if (VALUE_IS_CELLRANGE (v
)) {
1060 gnm_rangeref_normalize (&v
->v_range
.cell
,
1061 eval_pos_init_dep (&ep
, &vec
->dep
),
1062 &start_sheet
, &end_sheet
, &r
);
1064 /* clip here rather than relying on sheet_foreach
1065 * because that only clips if we ignore blanks */
1066 if (r
.end
.row
> start_sheet
->rows
.max_used
)
1067 r
.end
.row
= start_sheet
->rows
.max_used
;
1068 if (r
.end
.col
> start_sheet
->cols
.max_used
)
1069 r
.end
.col
= start_sheet
->cols
.max_used
;
1071 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
)
1072 sheet_foreach_cell_in_range (start_sheet
,
1075 (CellIterFunc
)cb_assign_markup
, vec
->markup
);
1086 return pango_attr_list_copy ((vec
->markup
->len
> i
)?
1087 g_ptr_array_index (vec
->markup
, i
): NULL
);
1091 gnm_go_data_vector_class_init (GObjectClass
*gobject_klass
)
1093 GODataClass
*godata_klass
= (GODataClass
*) gobject_klass
;
1094 GODataVectorClass
*vector_klass
= (GODataVectorClass
*) gobject_klass
;
1096 vector_parent_klass
= g_type_class_peek_parent (gobject_klass
);
1097 gobject_klass
->finalize
= gnm_go_data_vector_finalize
;
1098 godata_klass
->dup
= gnm_go_data_dup
;
1099 godata_klass
->eq
= gnm_go_data_eq
;
1100 godata_klass
->preferred_fmt
= gnm_go_data_preferred_fmt
;
1101 godata_klass
->date_conv
= gnm_go_data_date_conv
;
1102 godata_klass
->serialize
= gnm_go_data_serialize
;
1103 godata_klass
->unserialize
= gnm_go_data_unserialize
;
1104 vector_klass
->load_len
= gnm_go_data_vector_load_len
;
1105 vector_klass
->load_values
= gnm_go_data_vector_load_values
;
1106 vector_klass
->get_value
= gnm_go_data_vector_get_value
;
1107 vector_klass
->get_str
= gnm_go_data_vector_get_str
;
1108 vector_klass
->get_markup
= gnm_go_data_vector_get_markup
;
1112 gnm_go_data_vector_debug_name (GnmDependent
const *dep
, GString
*target
)
1114 g_string_append_printf (target
, "GraphVector%p", (void *)dep
);
1116 static DEPENDENT_MAKE_TYPE (gnm_go_data_vector
, NULL
)
1119 gnm_go_data_vector_init (GObject
*obj
)
1121 GnmGODataVector
*vec
= (GnmGODataVector
*)obj
;
1122 vec
->dep
.flags
= gnm_go_data_vector_get_dep_type ();
1125 GSF_CLASS (GnmGODataVector
, gnm_go_data_vector
,
1126 gnm_go_data_vector_class_init
, gnm_go_data_vector_init
,
1127 GO_TYPE_DATA_VECTOR
)
1130 gnm_go_data_vector_new_expr (Sheet
*sheet
, GnmExprTop
const *texpr
)
1132 GnmGODataVector
*res
= g_object_new (gnm_go_data_vector_get_type (), NULL
);
1133 res
->dep
.texpr
= texpr
;
1134 res
->dep
.sheet
= sheet
;
1135 return GO_DATA (res
);
1138 /**************************************************************************/
1140 struct _GnmGODataMatrix
{
1145 typedef GODataMatrixClass GnmGODataMatrixClass
;
1147 #define DEP_TO_MATRIX(d_ptr) (GnmGODataMatrix *)(((char *)d_ptr) - G_STRUCT_OFFSET (GnmGODataMatrix, dep))
1149 static GObjectClass
*matrix_parent_klass
;
1152 gnm_go_data_matrix_eval (GnmDependent
*dep
)
1154 GnmGODataMatrix
*mat
= DEP_TO_MATRIX (dep
);
1156 value_release (mat
->val
);
1158 go_data_emit_changed (GO_DATA (mat
));
1162 gnm_go_data_matrix_finalize (GObject
*obj
)
1164 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)obj
;
1166 dependent_set_expr (&mat
->dep
, NULL
);
1167 value_release (mat
->val
);
1170 g_free (mat
->base
.values
);
1171 mat
->base
.values
= NULL
;
1173 matrix_parent_klass
->finalize (obj
);
1177 gnm_go_data_matrix_load_size (GODataMatrix
*dat
)
1179 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)dat
;
1182 Sheet
*start_sheet
, *end_sheet
;
1184 int old_rows
= dat
->size
.rows
, old_columns
= dat
->size
.columns
;
1186 eval_pos_init_dep (&ep
, &mat
->dep
);
1187 if (mat
->val
== NULL
) {
1188 mat
->val
= gnm_expr_top_eval (mat
->dep
.texpr
, &ep
,
1189 GNM_EXPR_EVAL_PERMIT_NON_SCALAR
| GNM_EXPR_EVAL_PERMIT_EMPTY
);
1192 if (mat
->val
!= NULL
) {
1193 switch (mat
->val
->v_any
.type
) {
1194 case VALUE_CELLRANGE
:
1195 gnm_rangeref_normalize (&mat
->val
->v_range
.cell
, &ep
,
1196 &start_sheet
, &end_sheet
, &r
);
1197 if (r
.end
.col
> start_sheet
->cols
.max_used
)
1198 r
.end
.col
= start_sheet
->cols
.max_used
;
1199 if (r
.end
.row
> start_sheet
->rows
.max_used
)
1200 r
.end
.row
= start_sheet
->rows
.max_used
;
1202 if (r
.end
.col
>= r
.start
.col
&& r
.end
.row
>= r
.start
.row
) {
1203 w
= range_width (&r
);
1204 h
= range_height (&r
);
1205 if (w
> 0 && h
> 0) {
1207 dat
->size
.columns
= w
;
1211 dat
->size
.columns
= 0;
1215 dat
->size
.columns
= 0;
1220 dat
->size
.rows
= mat
->val
->v_array
.y
;
1221 dat
->size
.columns
= mat
->val
->v_array
.x
;
1226 dat
->size
.columns
= 1;
1230 dat
->size
.columns
= 0;
1232 if (dat
->values
!= NULL
&&
1233 (old_rows
!= dat
->size
.rows
|| old_columns
!= dat
->size
.columns
)) {
1234 g_free (dat
->values
);
1237 dat
->base
.flags
|= GO_DATA_MATRIX_SIZE_CACHED
;
1240 struct assign_matrix_closure
{
1241 const GODateConventions
*date_conv
;
1242 double minimum
, maximum
;
1244 int first_row
, first_col
;
1245 int last_row
, last_col
;
1246 int row
, col
, columns
, k
;
1250 cb_assign_matrix_val (GnmCellIter
const *iter
,
1251 struct assign_matrix_closure
*dat
)
1256 if (dat
->first_col
== -1)
1257 dat
->first_col
= iter
->pp
.eval
.col
;
1258 dat
->col
= iter
->pp
.eval
.col
- dat
->first_col
;
1259 if (dat
->first_row
== -1)
1260 dat
->first_row
= iter
->pp
.eval
.row
;
1261 dat
->row
= iter
->pp
.eval
.row
- dat
->first_row
;
1263 if (iter
->cell
!= NULL
) {
1264 gnm_cell_eval (iter
->cell
);
1265 v
= iter
->cell
->value
;
1270 if (VALUE_IS_EMPTY_OR_ERROR (v
)) {
1271 dat
->vals
[dat
->row
* dat
->columns
+ dat
->col
] = go_nan
;
1275 if (dat
->last_row
< dat
->row
)
1276 dat
->last_row
= dat
->row
;
1277 if (dat
->last_col
< dat
->col
)
1278 dat
->last_col
= dat
->col
;
1280 if (VALUE_IS_STRING (v
)) {
1281 v
= format_match_number (value_peek_string (v
), NULL
,
1284 dat
->vals
[dat
->row
* dat
->columns
+ dat
->col
] = go_nan
;
1285 /* may be go_pinf should be more appropriate? */
1288 res
= value_get_as_float (v
);
1291 res
= value_get_as_float (v
);
1293 dat
->vals
[dat
->row
* dat
->columns
+ dat
->col
] = res
;
1294 if (dat
->minimum
> res
)
1296 if (dat
->maximum
< res
)
1302 gnm_go_data_matrix_load_values (GODataMatrix
*dat
)
1304 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)dat
;
1307 Sheet
*start_sheet
, *end_sheet
;
1308 GODataMatrixSize size
= go_data_matrix_get_size (dat
); /* force calculation */
1309 double *vals
, minimum
, maximum
;
1312 struct assign_matrix_closure closure
;
1314 if (size
.rows
<= 0 || size
.columns
<= 0) {
1316 dat
->minimum
= go_nan
;
1317 dat
->maximum
= go_nan
;
1318 dat
->base
.flags
|= GO_DATA_CACHE_IS_VALID
;
1322 closure
.date_conv
= sheet_date_conv (mat
->dep
.sheet
);
1324 if (dat
->values
== NULL
)
1325 dat
->values
= g_new (double, size
.rows
* size
.columns
);
1327 switch (mat
->val
->v_any
.type
) {
1328 case VALUE_CELLRANGE
:
1329 gnm_rangeref_normalize (&mat
->val
->v_range
.cell
,
1330 eval_pos_init_dep (&ep
, &mat
->dep
),
1331 &start_sheet
, &end_sheet
, &r
);
1333 /* In case the sheet is empty */
1334 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
) {
1335 closure
.maximum
= - G_MAXDOUBLE
;
1336 closure
.minimum
= G_MAXDOUBLE
;
1337 closure
.vals
= dat
->values
;
1338 closure
.first_row
= closure
.last_row
= -1;
1339 closure
.first_col
= closure
.last_col
= -1;
1340 closure
.row
= closure
.col
= 0;
1341 closure
.columns
= dat
->size
.columns
;
1342 sheet_foreach_cell_in_region (start_sheet
, CELL_ITER_ALL
,
1343 r
.start
.col
, r
.start
.row
,
1344 r
.start
.col
+ dat
->size
.columns
- 1,
1345 r
.start
.row
+ dat
->size
.rows
- 1,
1346 (CellIterFunc
)cb_assign_matrix_val
, &closure
);
1347 #warning "Should we clip the matrix?"
1348 minimum
= closure
.minimum
;
1349 maximum
= closure
.maximum
;
1350 if (minimum
> maximum
)
1351 minimum
= maximum
= go_nan
;
1353 minimum
= maximum
= vals
[0] = go_nan
;
1357 maximum
= - G_MAXDOUBLE
;
1358 minimum
= G_MAXDOUBLE
;
1359 for (col
= 0; col
< size
.columns
; col
++)
1360 for (row
= 0; row
< size
.rows
; row
++) {
1361 v
= mat
->val
->v_array
.vals
[col
][row
];
1362 cur
= col
* size
.rows
+ row
;
1363 if (VALUE_IS_EMPTY_OR_ERROR (v
)) {
1364 vals
[row
* size
.columns
+ col
] = go_nan
;
1366 } else if (VALUE_IS_STRING (v
)) {
1367 GnmValue
*tmp
= format_match_number
1368 (value_peek_string (v
), NULL
,
1374 vals
[cur
] = value_get_as_float (tmp
);
1375 value_release (tmp
);
1377 vals
[cur
] = value_get_as_float (v
);
1378 if (minimum
> vals
[cur
])
1379 minimum
= vals
[cur
];
1380 if (maximum
< vals
[cur
])
1381 maximum
= vals
[cur
];
1383 if (minimum
> maximum
)
1384 minimum
= maximum
= go_nan
;
1388 v
= format_match_number (value_peek_string (mat
->val
),
1392 vals
[0] = value_get_as_float (v
);
1393 minimum
= maximum
= go_nan
;
1397 /* fall through to errors */
1401 minimum
= maximum
= vals
[0] = go_nan
;
1404 vals
[0] = value_get_as_float (mat
->val
);
1405 minimum
= maximum
= go_nan
;
1410 dat
->minimum
= minimum
;
1411 dat
->maximum
= maximum
;
1412 dat
->base
.flags
|= GO_DATA_CACHE_IS_VALID
;
1416 gnm_go_data_matrix_get_value (GODataMatrix
*dat
, unsigned i
, unsigned j
)
1418 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)dat
;
1423 if (mat
->val
== NULL
)
1424 gnm_go_data_matrix_load_size (dat
);
1426 eval_pos_init_dep (&ep
, &mat
->dep
);
1427 /* i is row and j is column */
1428 v
= value_dup (value_area_get_x_y (mat
->val
, j
, i
, &ep
));
1432 v
= value_coerce_to_number (v
, &valid
, &ep
);
1434 gnm_float res
= value_get_as_float (v
);
1443 gnm_go_data_matrix_get_str (GODataMatrix
*dat
, unsigned i
, unsigned j
)
1445 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)dat
;
1447 GOFormat
const *fmt
= NULL
;
1449 if (mat
->val
== NULL
)
1450 gnm_go_data_matrix_load_size (dat
);
1451 g_return_val_if_fail (mat
->val
!= NULL
, NULL
);
1453 eval_pos_init_dep (&ep
, &mat
->dep
);
1454 return render_val (mat
->val
, i
, j
, fmt
, &ep
);
1458 gnm_go_data_matrix_class_init (GObjectClass
*gobject_klass
)
1460 GODataClass
*godata_klass
= (GODataClass
*) gobject_klass
;
1461 GODataMatrixClass
*matrix_klass
= (GODataMatrixClass
*) gobject_klass
;
1463 matrix_parent_klass
= g_type_class_peek_parent (gobject_klass
);
1464 gobject_klass
->finalize
= gnm_go_data_matrix_finalize
;
1465 godata_klass
->dup
= gnm_go_data_dup
;
1466 godata_klass
->eq
= gnm_go_data_eq
;
1467 godata_klass
->preferred_fmt
= gnm_go_data_preferred_fmt
;
1468 godata_klass
->date_conv
= gnm_go_data_date_conv
;
1469 godata_klass
->serialize
= gnm_go_data_serialize
;
1470 godata_klass
->unserialize
= gnm_go_data_unserialize
;
1471 matrix_klass
->load_size
= gnm_go_data_matrix_load_size
;
1472 matrix_klass
->load_values
= gnm_go_data_matrix_load_values
;
1473 matrix_klass
->get_value
= gnm_go_data_matrix_get_value
;
1474 matrix_klass
->get_str
= gnm_go_data_matrix_get_str
;
1478 gnm_go_data_matrix_debug_name (GnmDependent
const *dep
, GString
*target
)
1480 g_string_append_printf (target
, "GraphMatrix%p", (void *)dep
);
1482 static DEPENDENT_MAKE_TYPE (gnm_go_data_matrix
, NULL
)
1485 gnm_go_data_matrix_init (GObject
*obj
)
1487 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)obj
;
1488 mat
->dep
.flags
= gnm_go_data_matrix_get_dep_type ();
1491 GSF_CLASS (GnmGODataMatrix
, gnm_go_data_matrix
,
1492 gnm_go_data_matrix_class_init
, gnm_go_data_matrix_init
,
1493 GO_TYPE_DATA_MATRIX
)
1496 gnm_go_data_matrix_new_expr (Sheet
*sheet
, GnmExprTop
const *texpr
)
1498 GnmGODataMatrix
*res
= g_object_new (gnm_go_data_matrix_get_type (), NULL
);
1499 res
->dep
.texpr
= texpr
;
1500 res
->dep
.sheet
= sheet
;
1501 return GO_DATA (res
);
1504 /*******************************************************************************/
1506 static GnmDependent
*
1507 gnm_go_data_get_dep (GOData
const *dat
)
1509 if (GNM_IS_GO_DATA_SCALAR (dat
))
1510 return &((GnmGODataScalar
*)dat
)->dep
;
1511 if (GNM_IS_GO_DATA_VECTOR (dat
))
1512 return &((GnmGODataVector
*)dat
)->dep
;
1513 if (GNM_IS_GO_DATA_MATRIX (dat
))
1514 return &((GnmGODataMatrix
*)dat
)->dep
;