2 * graph.c: The gnumeric specific data wrappers for GOffice
4 * Copyright (C) 2003-2005 Jody Goldberg (jody@gnome.org)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) version 3.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21 #include <gnumeric-config.h>
23 #include <dependent.h>
27 #include <number-match.h>
32 #include <gnm-format.h>
33 #include <auto-format.h>
35 #include <parse-util.h>
36 #include <expr-impl.h>
37 #include <goffice/goffice.h>
39 #include <gsf/gsf-impl-utils.h>
42 /* ------------------------------------------------------------------------- */
45 get_pending_str (const GOData
*data
)
47 return g_object_get_data (G_OBJECT (data
), "unserialize");
50 static GnmConventions
*
51 get_pending_convs (const GOData
*data
)
53 return g_object_get_data (G_OBJECT (data
), "unserialize-convs");
57 set_pending_str (const GOData
*data
, const char *str
)
59 g_object_set_data_full (G_OBJECT (data
),
60 "unserialize", g_strdup (str
),
65 set_pending_convs (GOData
*data
, const GnmConventions
*convs
)
67 g_object_set_data_full (G_OBJECT (data
),
69 gnm_conventions_ref ((gpointer
)convs
),
70 (GDestroyNotify
)gnm_conventions_unref
);
73 /* ------------------------------------------------------------------------- */
76 render_val (GnmValue
const *v
, int i
, int j
,
77 GOFormat
const *fmt
, GnmEvalPos
const *ep
)
79 GODateConventions
const *date_conv
;
84 date_conv
= ep
->sheet
? sheet_date_conv (ep
->sheet
) : NULL
;
87 g_printerr ("Rendering %s with fmt=%s\n",
88 value_peek_string (v
),
89 fmt
? go_format_as_XL (fmt
) : "-");
92 if (VALUE_IS_CELLRANGE (v
)) {
93 Sheet
*start_sheet
, *end_sheet
;
97 gnm_rangeref_normalize (&v
->v_range
.cell
, ep
,
98 &start_sheet
, &end_sheet
, &r
);
101 cell
= sheet_cell_get (start_sheet
, r
.start
.col
, r
.start
.row
);
104 gnm_cell_eval (cell
);
108 fmt
= gnm_cell_get_format (cell
);
109 } else if (VALUE_IS_ARRAY (v
))
110 v
= value_area_get_x_y (v
, i
, j
, ep
);
112 return format_value (fmt
, v
, -1, date_conv
);
115 /* ------------------------------------------------------------------------- */
117 static GnmDependent
*gnm_go_data_get_dep (GOData
const *obj
);
120 gnm_go_data_dup (GOData
const *src
)
122 GOData
*dst
= g_object_new (G_OBJECT_TYPE (src
), NULL
);
123 GnmDependent
const *src_dep
= gnm_go_data_get_dep (src
);
124 GnmDependent
*dst_dep
= gnm_go_data_get_dep (dst
);
126 dst_dep
->texpr
= src_dep
->texpr
;
128 gnm_expr_top_ref (dst_dep
->texpr
);
131 dependent_set_sheet (dst_dep
, src_dep
->sheet
);
133 if (dst_dep
->texpr
== NULL
) {
134 set_pending_str (dst
, get_pending_str (src
));
135 set_pending_convs (dst
, get_pending_convs (src
));
138 return GO_DATA (dst
);
142 gnm_go_data_eq (GOData
const *data_a
, GOData
const *data_b
)
144 GnmDependent
const *a
= gnm_go_data_get_dep (data_a
);
145 GnmDependent
const *b
= gnm_go_data_get_dep (data_b
);
147 if (a
->texpr
== NULL
&& b
->texpr
== NULL
) {
148 if (go_str_compare (get_pending_str (data_a
),
149 get_pending_str (data_b
)))
151 if (get_pending_convs (data_a
) != get_pending_convs (data_b
))
156 return a
->texpr
&& b
->texpr
&& gnm_expr_top_equal (a
->texpr
, b
->texpr
);
160 gnm_go_data_preferred_fmt (GOData
const *dat
)
163 GnmDependent
const *dep
= gnm_go_data_get_dep (dat
);
165 g_return_val_if_fail (dep
!= NULL
, NULL
);
167 eval_pos_init_dep (&ep
, dep
);
169 ? (GOFormat
*)gnm_auto_style_format_suggest (dep
->texpr
, &ep
)
173 static GODateConventions
const *
174 gnm_go_data_date_conv (GOData
const *dat
)
176 GnmDependent
const *dep
= gnm_go_data_get_dep (dat
);
178 g_return_val_if_fail (dep
!= NULL
, NULL
);
183 return sheet_date_conv (dep
->sheet
);
187 gnm_go_data_serialize (GOData
const *dat
, gpointer user
)
190 GnmConventions
const *convs
= user
;
191 GnmDependent
const *dep
= gnm_go_data_get_dep (dat
);
193 if (dep
->sheet
== NULL
)
194 return g_strdup ("No sheet for GnmGOData");
196 g_warning ("NULL convs in gnm_go_data_serialize");
197 convs
= gnm_conventions_default
;
200 res
= gnm_expr_top_as_string (dep
->texpr
,
201 parse_pos_init_dep (&pp
, dep
),
204 g_printerr ("Serializing %s\n", res
);
210 gnm_go_data_unserialize (GOData
*dat
, char const *str
, gpointer user
)
212 GnmConventions
const *convs
= user
;
213 GnmExprTop
const *texpr
;
215 GnmDependent
*dep
= gnm_go_data_get_dep (dat
);
218 g_warning ("NULL convs in gnm_go_data_serialize");
219 convs
= gnm_conventions_default
;
222 /* It is too early in the life cycle to know where we
223 * are. Wait until later when we parse the sheet */
224 if (dep
->sheet
== NULL
) {
225 set_pending_str (dat
, str
);
226 /* Ugh. We assume that convs will stay valid. */
227 set_pending_convs (dat
, convs
);
231 parse_pos_init_dep (&pp
, dep
);
232 texpr
= gnm_expr_parse_str (str
, &pp
, (GO_IS_DATA_VECTOR (dat
))?
233 GNM_EXPR_PARSE_PERMIT_MULTIPLE_EXPRESSIONS
:
234 GNM_EXPR_PARSE_DEFAULT
,
237 dependent_set_expr (dep
, texpr
);
238 gnm_expr_top_unref (texpr
);
245 gnm_go_data_set_sheet (GOData
*dat
, Sheet
*sheet
)
247 GnmDependent
*dep
= gnm_go_data_get_dep (dat
);
252 if (dependent_is_linked (dep
)) {
253 dependent_unlink (dep
);
261 * Do we need to parse one now that we have more context ? */
262 if (dep
->texpr
== NULL
) {
263 char const *str
= get_pending_str (dat
);
264 GnmConventions
*convs
= get_pending_convs (dat
);
265 if (str
!= NULL
) { /* bingo */
266 dep
->sheet
= sheet
; /* cheat a bit */
267 if (gnm_go_data_unserialize (dat
, str
, convs
)) {
268 set_pending_str (dat
, NULL
);
269 set_pending_convs (dat
, NULL
);
270 go_data_emit_changed (GO_DATA (dat
));
276 dependent_set_sheet (dep
, sheet
);
280 * gnm_go_data_get_sheet:
283 * Returns: (transfer none): the sheet.
286 gnm_go_data_get_sheet (GOData
const *dat
)
288 GnmDependent
*dep
= gnm_go_data_get_dep (dat
);
289 g_return_val_if_fail (dep
!= NULL
, NULL
);
294 gnm_go_data_get_expr (GOData
const *dat
)
296 GnmDependent
*dep
= gnm_go_data_get_dep (dat
);
303 * gnm_go_data_foreach_dep:
306 * @func: (scope call):
311 gnm_go_data_foreach_dep (GOData
*dat
, SheetObject
*so
,
312 SheetObjectForeachDepFunc func
, gpointer user
)
314 GnmDependent
*dep
= gnm_go_data_get_dep (dat
);
316 func (dep
, so
, user
);
319 /**************************************************************************/
321 struct _GnmGODataScalar
{
327 typedef GODataScalarClass GnmGODataScalarClass
;
329 #define DEP_TO_SCALAR(d_ptr) (GnmGODataScalar *)(((char *)d_ptr) - G_STRUCT_OFFSET (GnmGODataScalar, dep))
331 static GObjectClass
*scalar_parent_klass
;
334 scalar_get_val (GnmGODataScalar
*scalar
)
336 if (scalar
->val
!= NULL
) {
337 value_release (scalar
->val
);
339 g_free (scalar
->val_str
);
340 scalar
->val_str
= NULL
;
342 if (scalar
->val
== NULL
) {
343 if (scalar
->dep
.texpr
!= NULL
) {
346 eval_pos_init_dep (&pos
, &scalar
->dep
);
348 scalar
->val
= gnm_expr_top_eval
349 (scalar
->dep
.texpr
, &pos
,
350 GNM_EXPR_EVAL_PERMIT_EMPTY
);
352 scalar
->val
= value_new_empty ();
358 gnm_go_data_scalar_eval (GnmDependent
*dep
)
360 GnmGODataScalar
*scalar
= DEP_TO_SCALAR (dep
);
362 value_release (scalar
->val
);
364 g_free (scalar
->val_str
);
365 scalar
->val_str
= NULL
;
366 go_data_emit_changed (GO_DATA (scalar
));
370 gnm_go_data_scalar_finalize (GObject
*obj
)
372 GnmGODataScalar
*scalar
= (GnmGODataScalar
*)obj
;
374 dependent_set_expr (&scalar
->dep
, NULL
);
375 value_release (scalar
->val
);
377 g_free (scalar
->val_str
);
378 scalar
->val_str
= NULL
;
380 scalar_parent_klass
->finalize (obj
);
384 gnm_go_data_scalar_get_value (GODataScalar
*dat
)
386 return value_get_as_float (scalar_get_val ((GnmGODataScalar
*)dat
));
390 gnm_go_data_scalar_get_str (GODataScalar
*dat
)
392 GnmGODataScalar
*scalar
= (GnmGODataScalar
*)dat
;
393 GOFormat
const *fmt
= NULL
;
395 if (scalar
->val_str
== NULL
) {
398 eval_pos_init_dep (&ep
, &scalar
->dep
);
399 if (scalar
->dep
.texpr
)
400 fmt
= gnm_auto_style_format_suggest (scalar
->dep
.texpr
, &ep
);
402 render_val (scalar_get_val (scalar
), 0, 0, fmt
, &ep
);
404 go_format_unref (fmt
);
405 return scalar
->val_str
;
408 static PangoAttrList
const *
409 gnm_go_data_scalar_get_markup (GODataScalar
*dat
)
411 PangoAttrList
const *res
= NULL
;
412 GOFormat
const *fmt
= gnm_go_data_preferred_fmt (GO_DATA (dat
));
413 if (fmt
&& go_format_is_markup (fmt
))
414 res
= go_format_get_markup (fmt
);
415 go_format_unref (fmt
);
420 gnm_go_data_scalar_class_init (GObjectClass
*gobject_klass
)
422 GODataClass
*godata_klass
= (GODataClass
*) gobject_klass
;
423 GODataScalarClass
*scalar_klass
= (GODataScalarClass
*) gobject_klass
;
425 scalar_parent_klass
= g_type_class_peek_parent (gobject_klass
);
426 gobject_klass
->finalize
= gnm_go_data_scalar_finalize
;
427 godata_klass
->dup
= gnm_go_data_dup
;
428 godata_klass
->eq
= gnm_go_data_eq
;
429 godata_klass
->preferred_fmt
= gnm_go_data_preferred_fmt
;
430 godata_klass
->date_conv
= gnm_go_data_date_conv
;
431 godata_klass
->serialize
= gnm_go_data_serialize
;
432 godata_klass
->unserialize
= gnm_go_data_unserialize
;
433 scalar_klass
->get_value
= gnm_go_data_scalar_get_value
;
434 scalar_klass
->get_str
= gnm_go_data_scalar_get_str
;
435 scalar_klass
->get_markup
= gnm_go_data_scalar_get_markup
;
439 gnm_go_data_scalar_debug_name (GnmDependent
const *dep
, GString
*target
)
441 g_string_append_printf (target
, "GraphScalar%p", (void *)dep
);
444 static DEPENDENT_MAKE_TYPE (gnm_go_data_scalar
, NULL
)
447 gnm_go_data_scalar_init (GObject
*obj
)
449 GnmGODataScalar
*scalar
= (GnmGODataScalar
*)obj
;
450 scalar
->dep
.flags
= gnm_go_data_scalar_get_dep_type ();
453 GSF_CLASS (GnmGODataScalar
, gnm_go_data_scalar
,
454 gnm_go_data_scalar_class_init
, gnm_go_data_scalar_init
,
458 gnm_go_data_scalar_new_expr (Sheet
*sheet
, GnmExprTop
const *texpr
)
460 GnmGODataScalar
*res
= g_object_new (gnm_go_data_scalar_get_type (), NULL
);
461 res
->dep
.texpr
= texpr
;
462 res
->dep
.sheet
= sheet
;
463 return GO_DATA (res
);
466 /**************************************************************************/
468 struct _GnmGODataVector
{
476 typedef GODataVectorClass GnmGODataVectorClass
;
478 #define DEP_TO_VECTOR(d_ptr) (GnmGODataVector *)(((char *)d_ptr) - G_STRUCT_OFFSET (GnmGODataVector, dep))
480 static GObjectClass
*vector_parent_klass
;
483 gnm_go_data_vector_eval (GnmDependent
*dep
)
485 GnmGODataVector
*vec
= DEP_TO_VECTOR (dep
);
487 value_release (vec
->val
);
490 g_ptr_array_free (vec
->markup
, TRUE
);
494 g_ptr_array_free (vec
->strs
, TRUE
);
497 go_data_emit_changed (GO_DATA (vec
));
501 gnm_go_data_vector_finalize (GObject
*obj
)
503 GnmGODataVector
*vec
= (GnmGODataVector
*)obj
;
505 dependent_set_expr (&vec
->dep
, NULL
);
506 value_release (vec
->val
);
509 g_free (vec
->base
.values
);
510 vec
->base
.values
= NULL
;
512 g_ptr_array_free (vec
->markup
, TRUE
);
516 g_ptr_array_free (vec
->strs
, TRUE
);
520 vector_parent_klass
->finalize (obj
);
524 gnm_go_data_vector_load_len (GODataVector
*dat
)
526 GnmGODataVector
*vec
= (GnmGODataVector
*)dat
;
529 Sheet
*start_sheet
, *end_sheet
;
530 int old_len
= dat
->len
;
533 eval_pos_init_dep (&ep
, &vec
->dep
);
534 if (vec
->val
== NULL
&& vec
->dep
.texpr
!= NULL
) {
536 if (GNM_EXPR_GET_OPER (vec
->dep
.texpr
->expr
) == GNM_EXPR_OP_SET
&&
537 gnm_expr_is_rangeref (vec
->dep
.texpr
->expr
) &&
538 ((l
= gnm_expr_top_get_ranges (vec
->dep
.texpr
))) &&
540 unsigned len
= g_slist_length (l
);
543 vec
->val
= value_new_array_empty (len
, 1);
544 for (i
= 0; i
< len
; i
++) {
545 vec
->val
->v_array
.vals
[i
][0] = cur
->data
;
551 for (cur
= l
; cur
!= NULL
; cur
= cur
->next
)
552 value_release (cur
->data
);
554 vec
->val
= gnm_expr_top_eval (vec
->dep
.texpr
, &ep
,
555 GNM_EXPR_EVAL_PERMIT_NON_SCALAR
| GNM_EXPR_EVAL_PERMIT_EMPTY
| GNM_EXPR_EVAL_ARRAY_CONTEXT
);
560 if (vec
->val
!= NULL
) {
561 switch (vec
->val
->v_any
.type
) {
562 case VALUE_CELLRANGE
:
563 gnm_rangeref_normalize (&vec
->val
->v_range
.cell
, &ep
,
564 &start_sheet
, &end_sheet
, &r
);
566 /* add +1 to max_used so that we can have matrices with
567 * empty cells at the end, see #684072 */
568 if (r
.end
.col
> start_sheet
->cols
.max_used
)
569 r
.end
.col
= start_sheet
->cols
.max_used
+ 1;
570 if (r
.end
.row
> start_sheet
->rows
.max_used
)
571 r
.end
.row
= start_sheet
->rows
.max_used
+ 1;
573 if (r
.end
.col
>= r
.start
.col
&& r
.end
.row
>= r
.start
.row
) {
574 guint w
= range_width (&r
);
575 guint h
= range_height (&r
);
577 new_len
= (guint64
)h
* w
* (end_sheet
->index_in_wb
- start_sheet
->index_in_wb
+ 1);
585 for (j
= 0; j
< vec
->val
->v_array
.y
; j
++)
586 for (i
= 0; i
< vec
->val
->v_array
.x
; i
++) {
587 v
= vec
->val
->v_array
.vals
[i
][j
];
588 if (VALUE_IS_CELLRANGE (v
)) {
589 gnm_rangeref_normalize (&v
->v_range
.cell
, &ep
,
590 &start_sheet
, &end_sheet
, &r
);
591 new_len
+= (guint64
)range_width (&r
) * range_height (&r
)
592 * (end_sheet
->index_in_wb
- start_sheet
->index_in_wb
+ 1);
596 vec
->as_col
= (vec
->val
->v_array
.y
> vec
->val
->v_array
.x
);
610 /* Protect against overflow in ->len as well as when allocating ->values. */
611 new_len
= MIN (new_len
, (gint64
)(G_MAXINT
/ sizeof (dat
->values
[0])));
614 if (dat
->values
!= NULL
&& old_len
!= dat
->len
) {
615 g_free (dat
->values
);
618 dat
->base
.flags
|= GO_DATA_VECTOR_LEN_CACHED
;
621 struct assign_closure
{
622 const GODateConventions
*date_conv
;
623 double minimum
, maximum
;
631 cb_assign_val (GnmCellIter
const *iter
, struct assign_closure
*dat
)
636 if ((gssize
)dat
->i
>= dat
->vals_len
)
639 if (iter
->cell
!= NULL
) {
640 gnm_cell_eval (iter
->cell
);
641 v
= iter
->cell
->value
;
645 if (VALUE_IS_EMPTY_OR_ERROR (v
)) {
646 dat
->vals
[dat
->i
++] = go_nan
;
651 if (VALUE_IS_STRING (v
)) {
652 v
= format_match_number (value_peek_string (v
), NULL
,
655 dat
->vals
[dat
->i
++] = go_nan
;
658 res
= value_get_as_float (v
);
661 res
= value_get_as_float (v
);
663 dat
->vals
[dat
->i
++] = res
;
664 if (dat
->minimum
> res
)
666 if (dat
->maximum
< res
)
672 gnm_go_data_vector_load_values (GODataVector
*dat
)
674 GnmGODataVector
*vec
= (GnmGODataVector
*)dat
;
677 Sheet
*start_sheet
, *end_sheet
;
678 double *vals
, minimum
, maximum
;
680 struct assign_closure closure
;
682 (void)go_data_vector_get_len (dat
); /* force calculation */
684 if (dat
->len
<= 0 || !vec
->dep
.sheet
) {
686 dat
->minimum
= go_nan
;
687 dat
->maximum
= go_nan
;
688 dat
->base
.flags
|= GO_DATA_CACHE_IS_VALID
;
692 closure
.date_conv
= sheet_date_conv (vec
->dep
.sheet
);
694 if (dat
->values
== NULL
)
695 dat
->values
= g_new (double, dat
->len
);
697 switch (vec
->val
->v_any
.type
) {
698 case VALUE_CELLRANGE
:
699 gnm_rangeref_normalize (&vec
->val
->v_range
.cell
,
700 eval_pos_init_dep (&ep
, &vec
->dep
),
701 &start_sheet
, &end_sheet
, &r
);
703 /* clip here rather than relying on sheet_foreach
704 * because that only clips if we ignore blanks
705 * but add +1 to max_used so that we can have matrices with
706 * empty cells at the end, see #684072 */
707 if (r
.end
.row
> start_sheet
->rows
.max_used
)
708 r
.end
.row
= start_sheet
->rows
.max_used
+ 1;
709 if (r
.end
.col
> start_sheet
->cols
.max_used
)
710 r
.end
.col
= start_sheet
->cols
.max_used
+ 1;
712 /* In case the sheet is empty */
713 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
) {
714 closure
.maximum
= - G_MAXDOUBLE
;
715 closure
.minimum
= G_MAXDOUBLE
;
716 closure
.vals
= dat
->values
;
717 closure
.vals_len
= dat
->len
;
720 if (start_sheet
!= end_sheet
)
721 workbook_foreach_cell_in_range (&ep
, vec
->val
,
722 CELL_ITER_IGNORE_FILTERED
,
723 (CellIterFunc
)cb_assign_val
,
726 sheet_foreach_cell_in_range
727 (start_sheet
, CELL_ITER_IGNORE_FILTERED
,
729 (CellIterFunc
)cb_assign_val
, &closure
);
730 dat
->len
= closure
.last
+ 1; /* clip */
731 minimum
= closure
.minimum
;
732 maximum
= closure
.maximum
;
734 minimum
= maximum
= vals
[0] = go_nan
;
738 guint64 last
= 0, max
= dat
->len
;
739 int len
= vec
->val
->v_array
.y
* vec
->val
->v_array
.x
;
740 int x
= 0, y
= vec
->val
->v_array
.y
;
742 maximum
= - G_MAXDOUBLE
;
743 minimum
= G_MAXDOUBLE
;
746 x
= vec
->val
->v_array
.x
;
750 v
= vec
->val
->v_array
.vals
[x
][y
];
752 if (VALUE_IS_CELLRANGE (v
)) {
753 gnm_rangeref_normalize (&v
->v_range
.cell
,
754 eval_pos_init_dep (&ep
, &vec
->dep
),
755 &start_sheet
, &end_sheet
, &r
);
757 /* clip here rather than relying on sheet_foreach
758 * because that only clips if we ignore blanks */
759 if (r
.end
.row
> start_sheet
->rows
.max_used
)
760 r
.end
.row
= start_sheet
->rows
.max_used
;
761 if (r
.end
.col
> start_sheet
->cols
.max_used
)
762 r
.end
.col
= start_sheet
->cols
.max_used
;
764 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
) {
765 closure
.maximum
= - G_MAXDOUBLE
;
766 closure
.minimum
= G_MAXDOUBLE
;
767 closure
.vals
= dat
->values
;
768 closure
.vals_len
= max
;
769 closure
.last
= last
- 1;
771 if (start_sheet
!= end_sheet
)
772 workbook_foreach_cell_in_range (&ep
, vec
->val
,
773 CELL_ITER_IGNORE_FILTERED
,
774 (CellIterFunc
)cb_assign_val
,
777 sheet_foreach_cell_in_range (start_sheet
,
778 CELL_ITER_IGNORE_FILTERED
,
780 (CellIterFunc
)cb_assign_val
, &closure
);
781 last
= dat
->len
= closure
.last
+ 1; /* clip */
782 if (minimum
> closure
.minimum
)
783 minimum
= closure
.minimum
;
784 if (maximum
< closure
.maximum
)
785 maximum
= closure
.maximum
;
788 } else if (VALUE_IS_EMPTY_OR_ERROR (v
)) {
791 } else if (VALUE_IS_STRING (v
)) {
792 GnmValue
*tmp
= format_match_number
793 (value_peek_string (v
), NULL
,
799 vals
[len
] = value_get_as_float (tmp
);
802 vals
[len
] = value_get_as_float (v
);
803 if (minimum
> vals
[len
])
805 if (maximum
< vals
[len
])
812 v
= format_match_number (value_peek_string (vec
->val
),
816 minimum
= maximum
= vals
[0] = value_get_as_float (v
);
820 /* fall through to errors */
824 minimum
= maximum
= vals
[0] = go_nan
;
827 minimum
= maximum
= vals
[0] = value_get_as_float (vec
->val
);
832 dat
->minimum
= minimum
;
833 dat
->maximum
= maximum
;
834 dat
->base
.flags
|= GO_DATA_CACHE_IS_VALID
;
838 gnm_go_data_vector_get_value (GODataVector
*dat
, unsigned i
)
840 GnmGODataVector
*vec
= (GnmGODataVector
*)dat
;
843 gboolean valid
= FALSE
;
845 if (vec
->val
== NULL
)
846 gnm_go_data_vector_load_len (dat
);
848 if (VALUE_IS_ARRAY (vec
->val
)) {
849 if ((dat
->base
.flags
& GO_DATA_CACHE_IS_VALID
) == 0)
850 gnm_go_data_vector_load_values (dat
);
851 return dat
->values
[i
];
853 eval_pos_init_dep (&ep
, &vec
->dep
);
854 v
= value_dup (vec
->as_col
855 ? value_area_get_x_y (vec
->val
, 0, i
, &ep
)
856 : value_area_get_x_y (vec
->val
, i
, 0, &ep
));
860 v
= value_coerce_to_number (v
, &valid
, &ep
);
862 gnm_float res
= value_get_as_float (v
);
872 struct string_closure
{
874 GODateConventions
const *date_conv
;
878 cb_assign_string (GnmCellIter
const *iter
, struct string_closure
*closure
)
883 if (iter
->cell
!= NULL
) {
884 gnm_cell_eval (iter
->cell
);
885 v
= iter
->cell
->value
;
888 str
= format_value (gnm_cell_get_format (iter
->cell
), v
, -1, closure
->date_conv
);
889 g_ptr_array_add (closure
->strs
, str
);
895 gnm_go_data_vector_get_str (GODataVector
*dat
, unsigned i
)
897 GnmGODataVector
*vec
= (GnmGODataVector
*)dat
;
900 GOFormat
const *fmt
= NULL
;
904 if (vec
->val
== NULL
)
905 gnm_go_data_vector_load_len (dat
);
906 g_return_val_if_fail (vec
->val
!= NULL
, NULL
);
908 eval_pos_init_dep (&ep
, &vec
->dep
);
909 if (VALUE_IS_ARRAY (vec
->val
)) {
910 /* we need to cache the strings if needed */
911 if (vec
->strs
== NULL
) {
912 int len
= vec
->val
->v_array
.y
* vec
->val
->v_array
.x
;
913 int x
= 0, y
= vec
->val
->v_array
.y
;
914 struct string_closure closure
;
915 closure
.strs
= vec
->strs
= g_ptr_array_new_with_free_func (g_free
);
916 closure
.date_conv
= ep
.sheet
? sheet_date_conv (ep
.sheet
) : NULL
;
919 x
= vec
->val
->v_array
.x
;
923 v
= vec
->val
->v_array
.vals
[x
][y
];
925 if (VALUE_IS_CELLRANGE (v
)) {
926 /* actually we only need to cache in that case */
927 Sheet
*start_sheet
, *end_sheet
;
929 gnm_rangeref_normalize (&v
->v_range
.cell
,
930 eval_pos_init_dep (&ep
, &vec
->dep
),
931 &start_sheet
, &end_sheet
, &r
);
933 /* clip here rather than relying on sheet_foreach
934 * because that only clips if we ignore blanks */
935 if (r
.end
.row
> start_sheet
->rows
.max_used
)
936 r
.end
.row
= start_sheet
->rows
.max_used
;
937 if (r
.end
.col
> start_sheet
->cols
.max_used
)
938 r
.end
.col
= start_sheet
->cols
.max_used
;
940 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
)
941 sheet_foreach_cell_in_range (start_sheet
,
942 CELL_ITER_IGNORE_FILTERED
,
944 (CellIterFunc
)cb_assign_string
, &closure
);
948 if (vec
->strs
&& vec
->strs
->len
> i
)
949 ret
= g_ptr_array_index (vec
->strs
, i
);
951 return g_strdup (ret
);
952 } else if (VALUE_IS_CELLRANGE (vec
->val
)) {
953 Sheet
*start_sheet
, *end_sheet
;
955 if (vec
->strs
== NULL
) {
956 struct string_closure closure
;
957 closure
.strs
= vec
->strs
= g_ptr_array_new_with_free_func (g_free
);
958 closure
.date_conv
= ep
.sheet
? sheet_date_conv (ep
.sheet
) : NULL
;
959 gnm_rangeref_normalize (&vec
->val
->v_range
.cell
,
960 eval_pos_init_dep (&ep
, &vec
->dep
),
961 &start_sheet
, &end_sheet
, &r
);
963 /* clip here rather than relying on sheet_foreach
964 * because that only clips if we ignore blanks */
965 if (r
.end
.row
> start_sheet
->rows
.max_used
)
966 r
.end
.row
= start_sheet
->rows
.max_used
;
967 if (r
.end
.col
> start_sheet
->cols
.max_used
)
968 r
.end
.col
= start_sheet
->cols
.max_used
;
970 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
)
971 sheet_foreach_cell_in_range (start_sheet
,
972 CELL_ITER_IGNORE_FILTERED
,
974 (CellIterFunc
)cb_assign_string
, &closure
);
976 if (vec
->strs
&& vec
->strs
->len
> i
)
977 ret
= g_ptr_array_index (vec
->strs
, i
);
979 return g_strdup (ret
);
985 ret
= render_val (((v
!= NULL
)? v
: vec
->val
), i
, j
, fmt
, &ep
);
990 cond_pango_attr_list_unref (PangoAttrList
*al
)
993 pango_attr_list_unref (al
);
997 cb_assign_markup (GnmCellIter
const *iter
, GPtrArray
*markup
)
999 PangoAttrList
const *l
= NULL
;
1001 if (iter
->cell
!= NULL
) {
1002 GOFormat
const *fmt
= gnm_cell_get_format (iter
->cell
);
1003 if (go_format_is_markup (fmt
))
1004 l
= go_format_get_markup (fmt
);
1006 g_ptr_array_add (markup
,
1007 l
? pango_attr_list_ref ((PangoAttrList
*)l
) : NULL
);
1012 static PangoAttrList
*
1013 gnm_go_data_vector_get_markup (GODataVector
*dat
, unsigned i
)
1015 GnmGODataVector
*vec
= (GnmGODataVector
*)dat
;
1017 if (vec
->markup
== NULL
) {
1021 Sheet
*start_sheet
, *end_sheet
;
1024 go_data_vector_get_len (dat
); /* force calculation */
1025 if (dat
->len
<= 0 || !vec
->dep
.sheet
)
1027 vec
->markup
= g_ptr_array_new_with_free_func
1028 ((GDestroyNotify
)cond_pango_attr_list_unref
);
1029 switch (vec
->val
->v_any
.type
) {
1030 case VALUE_CELLRANGE
:
1031 gnm_rangeref_normalize (&vec
->val
->v_range
.cell
,
1032 eval_pos_init_dep (&ep
, &vec
->dep
),
1033 &start_sheet
, &end_sheet
, &r
);
1035 /* clip here rather than relying on sheet_foreach
1036 * because that only clips if we ignore blanks */
1037 if (r
.end
.row
> start_sheet
->rows
.max_used
)
1038 r
.end
.row
= start_sheet
->rows
.max_used
;
1039 if (r
.end
.col
> start_sheet
->cols
.max_used
)
1040 r
.end
.col
= start_sheet
->cols
.max_used
;
1042 /* In case the sheet is empty */
1043 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
) {
1044 sheet_foreach_cell_in_range (start_sheet
,
1047 (CellIterFunc
)cb_assign_markup
, vec
->markup
);
1052 int len
= vec
->as_col
? vec
->val
->v_array
.y
: vec
->val
->v_array
.x
;
1055 ? vec
->val
->v_array
.vals
[0][len
]
1056 : vec
->val
->v_array
.vals
[len
][0];
1058 if (VALUE_IS_CELLRANGE (v
)) {
1059 gnm_rangeref_normalize (&v
->v_range
.cell
,
1060 eval_pos_init_dep (&ep
, &vec
->dep
),
1061 &start_sheet
, &end_sheet
, &r
);
1063 /* clip here rather than relying on sheet_foreach
1064 * because that only clips if we ignore blanks */
1065 if (r
.end
.row
> start_sheet
->rows
.max_used
)
1066 r
.end
.row
= start_sheet
->rows
.max_used
;
1067 if (r
.end
.col
> start_sheet
->cols
.max_used
)
1068 r
.end
.col
= start_sheet
->cols
.max_used
;
1070 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
)
1071 sheet_foreach_cell_in_range (start_sheet
,
1074 (CellIterFunc
)cb_assign_markup
, vec
->markup
);
1085 return pango_attr_list_copy ((vec
->markup
->len
> i
)?
1086 g_ptr_array_index (vec
->markup
, i
): NULL
);
1090 gnm_go_data_vector_class_init (GObjectClass
*gobject_klass
)
1092 GODataClass
*godata_klass
= (GODataClass
*) gobject_klass
;
1093 GODataVectorClass
*vector_klass
= (GODataVectorClass
*) gobject_klass
;
1095 vector_parent_klass
= g_type_class_peek_parent (gobject_klass
);
1096 gobject_klass
->finalize
= gnm_go_data_vector_finalize
;
1097 godata_klass
->dup
= gnm_go_data_dup
;
1098 godata_klass
->eq
= gnm_go_data_eq
;
1099 godata_klass
->preferred_fmt
= gnm_go_data_preferred_fmt
;
1100 godata_klass
->date_conv
= gnm_go_data_date_conv
;
1101 godata_klass
->serialize
= gnm_go_data_serialize
;
1102 godata_klass
->unserialize
= gnm_go_data_unserialize
;
1103 vector_klass
->load_len
= gnm_go_data_vector_load_len
;
1104 vector_klass
->load_values
= gnm_go_data_vector_load_values
;
1105 vector_klass
->get_value
= gnm_go_data_vector_get_value
;
1106 vector_klass
->get_str
= gnm_go_data_vector_get_str
;
1107 vector_klass
->get_markup
= gnm_go_data_vector_get_markup
;
1111 gnm_go_data_vector_debug_name (GnmDependent
const *dep
, GString
*target
)
1113 g_string_append_printf (target
, "GraphVector%p", (void *)dep
);
1115 static DEPENDENT_MAKE_TYPE (gnm_go_data_vector
, NULL
)
1118 gnm_go_data_vector_init (GObject
*obj
)
1120 GnmGODataVector
*vec
= (GnmGODataVector
*)obj
;
1121 vec
->dep
.flags
= gnm_go_data_vector_get_dep_type ();
1124 GSF_CLASS (GnmGODataVector
, gnm_go_data_vector
,
1125 gnm_go_data_vector_class_init
, gnm_go_data_vector_init
,
1126 GO_TYPE_DATA_VECTOR
)
1129 gnm_go_data_vector_new_expr (Sheet
*sheet
, GnmExprTop
const *texpr
)
1131 GnmGODataVector
*res
= g_object_new (gnm_go_data_vector_get_type (), NULL
);
1132 res
->dep
.texpr
= texpr
;
1133 res
->dep
.sheet
= sheet
;
1134 return GO_DATA (res
);
1137 /**************************************************************************/
1139 struct _GnmGODataMatrix
{
1144 typedef GODataMatrixClass GnmGODataMatrixClass
;
1146 #define DEP_TO_MATRIX(d_ptr) (GnmGODataMatrix *)(((char *)d_ptr) - G_STRUCT_OFFSET (GnmGODataMatrix, dep))
1148 static GObjectClass
*matrix_parent_klass
;
1151 gnm_go_data_matrix_eval (GnmDependent
*dep
)
1153 GnmGODataMatrix
*mat
= DEP_TO_MATRIX (dep
);
1155 value_release (mat
->val
);
1157 go_data_emit_changed (GO_DATA (mat
));
1161 gnm_go_data_matrix_finalize (GObject
*obj
)
1163 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)obj
;
1165 dependent_set_expr (&mat
->dep
, NULL
);
1166 value_release (mat
->val
);
1169 g_free (mat
->base
.values
);
1170 mat
->base
.values
= NULL
;
1172 matrix_parent_klass
->finalize (obj
);
1176 gnm_go_data_matrix_load_size (GODataMatrix
*dat
)
1178 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)dat
;
1181 Sheet
*start_sheet
, *end_sheet
;
1183 int old_rows
= dat
->size
.rows
, old_columns
= dat
->size
.columns
;
1185 eval_pos_init_dep (&ep
, &mat
->dep
);
1186 if (mat
->val
== NULL
) {
1187 mat
->val
= gnm_expr_top_eval (mat
->dep
.texpr
, &ep
,
1188 GNM_EXPR_EVAL_PERMIT_NON_SCALAR
| GNM_EXPR_EVAL_PERMIT_EMPTY
);
1191 if (mat
->val
!= NULL
) {
1192 switch (mat
->val
->v_any
.type
) {
1193 case VALUE_CELLRANGE
:
1194 gnm_rangeref_normalize (&mat
->val
->v_range
.cell
, &ep
,
1195 &start_sheet
, &end_sheet
, &r
);
1196 if (r
.end
.col
> start_sheet
->cols
.max_used
)
1197 r
.end
.col
= start_sheet
->cols
.max_used
;
1198 if (r
.end
.row
> start_sheet
->rows
.max_used
)
1199 r
.end
.row
= start_sheet
->rows
.max_used
;
1201 if (r
.end
.col
>= r
.start
.col
&& r
.end
.row
>= r
.start
.row
) {
1202 w
= range_width (&r
);
1203 h
= range_height (&r
);
1204 if (w
> 0 && h
> 0) {
1206 dat
->size
.columns
= w
;
1210 dat
->size
.columns
= 0;
1214 dat
->size
.columns
= 0;
1219 dat
->size
.rows
= mat
->val
->v_array
.y
;
1220 dat
->size
.columns
= mat
->val
->v_array
.x
;
1225 dat
->size
.columns
= 1;
1229 dat
->size
.columns
= 0;
1231 if (dat
->values
!= NULL
&&
1232 (old_rows
!= dat
->size
.rows
|| old_columns
!= dat
->size
.columns
)) {
1233 g_free (dat
->values
);
1236 dat
->base
.flags
|= GO_DATA_MATRIX_SIZE_CACHED
;
1239 struct assign_matrix_closure
{
1240 const GODateConventions
*date_conv
;
1241 double minimum
, maximum
;
1243 int first_row
, first_col
;
1244 int last_row
, last_col
;
1245 int row
, col
, columns
, k
;
1249 cb_assign_matrix_val (GnmCellIter
const *iter
,
1250 struct assign_matrix_closure
*dat
)
1255 if (dat
->first_col
== -1)
1256 dat
->first_col
= iter
->pp
.eval
.col
;
1257 dat
->col
= iter
->pp
.eval
.col
- dat
->first_col
;
1258 if (dat
->first_row
== -1)
1259 dat
->first_row
= iter
->pp
.eval
.row
;
1260 dat
->row
= iter
->pp
.eval
.row
- dat
->first_row
;
1262 if (iter
->cell
!= NULL
) {
1263 gnm_cell_eval (iter
->cell
);
1264 v
= iter
->cell
->value
;
1269 if (VALUE_IS_EMPTY_OR_ERROR (v
)) {
1270 dat
->vals
[dat
->row
* dat
->columns
+ dat
->col
] = go_nan
;
1274 if (dat
->last_row
< dat
->row
)
1275 dat
->last_row
= dat
->row
;
1276 if (dat
->last_col
< dat
->col
)
1277 dat
->last_col
= dat
->col
;
1279 if (VALUE_IS_STRING (v
)) {
1280 v
= format_match_number (value_peek_string (v
), NULL
,
1283 dat
->vals
[dat
->row
* dat
->columns
+ dat
->col
] = go_nan
;
1284 /* may be go_pinf should be more appropriate? */
1287 res
= value_get_as_float (v
);
1290 res
= value_get_as_float (v
);
1292 dat
->vals
[dat
->row
* dat
->columns
+ dat
->col
] = res
;
1293 if (dat
->minimum
> res
)
1295 if (dat
->maximum
< res
)
1301 gnm_go_data_matrix_load_values (GODataMatrix
*dat
)
1303 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)dat
;
1306 Sheet
*start_sheet
, *end_sheet
;
1307 GODataMatrixSize size
= go_data_matrix_get_size (dat
); /* force calculation */
1308 double *vals
, minimum
, maximum
;
1311 struct assign_matrix_closure closure
;
1313 if (size
.rows
<= 0 || size
.columns
<= 0) {
1315 dat
->minimum
= go_nan
;
1316 dat
->maximum
= go_nan
;
1317 dat
->base
.flags
|= GO_DATA_CACHE_IS_VALID
;
1321 closure
.date_conv
= sheet_date_conv (mat
->dep
.sheet
);
1323 if (dat
->values
== NULL
)
1324 dat
->values
= g_new (double, size
.rows
* size
.columns
);
1326 switch (mat
->val
->v_any
.type
) {
1327 case VALUE_CELLRANGE
:
1328 gnm_rangeref_normalize (&mat
->val
->v_range
.cell
,
1329 eval_pos_init_dep (&ep
, &mat
->dep
),
1330 &start_sheet
, &end_sheet
, &r
);
1332 /* In case the sheet is empty */
1333 if (r
.start
.col
<= r
.end
.col
&& r
.start
.row
<= r
.end
.row
) {
1334 closure
.maximum
= - G_MAXDOUBLE
;
1335 closure
.minimum
= G_MAXDOUBLE
;
1336 closure
.vals
= dat
->values
;
1337 closure
.first_row
= closure
.last_row
= -1;
1338 closure
.first_col
= closure
.last_col
= -1;
1339 closure
.row
= closure
.col
= 0;
1340 closure
.columns
= dat
->size
.columns
;
1341 sheet_foreach_cell_in_region (start_sheet
, CELL_ITER_ALL
,
1342 r
.start
.col
, r
.start
.row
,
1343 r
.start
.col
+ dat
->size
.columns
- 1,
1344 r
.start
.row
+ dat
->size
.rows
- 1,
1345 (CellIterFunc
)cb_assign_matrix_val
, &closure
);
1346 #warning "Should we clip the matrix?"
1347 minimum
= closure
.minimum
;
1348 maximum
= closure
.maximum
;
1349 if (minimum
> maximum
)
1350 minimum
= maximum
= go_nan
;
1352 minimum
= maximum
= vals
[0] = go_nan
;
1356 maximum
= - G_MAXDOUBLE
;
1357 minimum
= G_MAXDOUBLE
;
1358 for (col
= 0; col
< size
.columns
; col
++)
1359 for (row
= 0; row
< size
.rows
; row
++) {
1360 v
= mat
->val
->v_array
.vals
[col
][row
];
1361 cur
= col
* size
.rows
+ row
;
1362 if (VALUE_IS_EMPTY_OR_ERROR (v
)) {
1363 vals
[row
* size
.columns
+ col
] = go_nan
;
1365 } else if (VALUE_IS_STRING (v
)) {
1366 GnmValue
*tmp
= format_match_number
1367 (value_peek_string (v
), NULL
,
1373 vals
[cur
] = value_get_as_float (tmp
);
1374 value_release (tmp
);
1376 vals
[cur
] = value_get_as_float (v
);
1377 if (minimum
> vals
[cur
])
1378 minimum
= vals
[cur
];
1379 if (maximum
< vals
[cur
])
1380 maximum
= vals
[cur
];
1382 if (minimum
> maximum
)
1383 minimum
= maximum
= go_nan
;
1387 v
= format_match_number (value_peek_string (mat
->val
),
1391 vals
[0] = value_get_as_float (v
);
1392 minimum
= maximum
= go_nan
;
1396 /* fall through to errors */
1400 minimum
= maximum
= vals
[0] = go_nan
;
1403 vals
[0] = value_get_as_float (mat
->val
);
1404 minimum
= maximum
= go_nan
;
1409 dat
->minimum
= minimum
;
1410 dat
->maximum
= maximum
;
1411 dat
->base
.flags
|= GO_DATA_CACHE_IS_VALID
;
1415 gnm_go_data_matrix_get_value (GODataMatrix
*dat
, unsigned i
, unsigned j
)
1417 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)dat
;
1422 if (mat
->val
== NULL
)
1423 gnm_go_data_matrix_load_size (dat
);
1425 eval_pos_init_dep (&ep
, &mat
->dep
);
1426 /* i is row and j is column */
1427 v
= value_dup (value_area_get_x_y (mat
->val
, j
, i
, &ep
));
1431 v
= value_coerce_to_number (v
, &valid
, &ep
);
1433 gnm_float res
= value_get_as_float (v
);
1442 gnm_go_data_matrix_get_str (GODataMatrix
*dat
, unsigned i
, unsigned j
)
1444 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)dat
;
1446 GOFormat
const *fmt
= NULL
;
1448 if (mat
->val
== NULL
)
1449 gnm_go_data_matrix_load_size (dat
);
1450 g_return_val_if_fail (mat
->val
!= NULL
, NULL
);
1452 eval_pos_init_dep (&ep
, &mat
->dep
);
1453 return render_val (mat
->val
, i
, j
, fmt
, &ep
);
1457 gnm_go_data_matrix_class_init (GObjectClass
*gobject_klass
)
1459 GODataClass
*godata_klass
= (GODataClass
*) gobject_klass
;
1460 GODataMatrixClass
*matrix_klass
= (GODataMatrixClass
*) gobject_klass
;
1462 matrix_parent_klass
= g_type_class_peek_parent (gobject_klass
);
1463 gobject_klass
->finalize
= gnm_go_data_matrix_finalize
;
1464 godata_klass
->dup
= gnm_go_data_dup
;
1465 godata_klass
->eq
= gnm_go_data_eq
;
1466 godata_klass
->preferred_fmt
= gnm_go_data_preferred_fmt
;
1467 godata_klass
->date_conv
= gnm_go_data_date_conv
;
1468 godata_klass
->serialize
= gnm_go_data_serialize
;
1469 godata_klass
->unserialize
= gnm_go_data_unserialize
;
1470 matrix_klass
->load_size
= gnm_go_data_matrix_load_size
;
1471 matrix_klass
->load_values
= gnm_go_data_matrix_load_values
;
1472 matrix_klass
->get_value
= gnm_go_data_matrix_get_value
;
1473 matrix_klass
->get_str
= gnm_go_data_matrix_get_str
;
1477 gnm_go_data_matrix_debug_name (GnmDependent
const *dep
, GString
*target
)
1479 g_string_append_printf (target
, "GraphMatrix%p", (void *)dep
);
1481 static DEPENDENT_MAKE_TYPE (gnm_go_data_matrix
, NULL
)
1484 gnm_go_data_matrix_init (GObject
*obj
)
1486 GnmGODataMatrix
*mat
= (GnmGODataMatrix
*)obj
;
1487 mat
->dep
.flags
= gnm_go_data_matrix_get_dep_type ();
1490 GSF_CLASS (GnmGODataMatrix
, gnm_go_data_matrix
,
1491 gnm_go_data_matrix_class_init
, gnm_go_data_matrix_init
,
1492 GO_TYPE_DATA_MATRIX
)
1495 gnm_go_data_matrix_new_expr (Sheet
*sheet
, GnmExprTop
const *texpr
)
1497 GnmGODataMatrix
*res
= g_object_new (gnm_go_data_matrix_get_type (), NULL
);
1498 res
->dep
.texpr
= texpr
;
1499 res
->dep
.sheet
= sheet
;
1500 return GO_DATA (res
);
1503 /*******************************************************************************/
1505 static GnmDependent
*
1506 gnm_go_data_get_dep (GOData
const *dat
)
1508 if (GNM_IS_GO_DATA_SCALAR (dat
))
1509 return &((GnmGODataScalar
*)dat
)->dep
;
1510 if (GNM_IS_GO_DATA_VECTOR (dat
))
1511 return &((GnmGODataVector
*)dat
)->dep
;
1512 if (GNM_IS_GO_DATA_MATRIX (dat
))
1513 return &((GnmGODataMatrix
*)dat
)->dep
;