4 * ms-container.c: A meta container to handle object import for charts,
5 * workbooks and sheets.
8 * Jody Goldberg (jody@gnome.org)
10 * (C) 2000-2005 Jody Goldberg
13 #include <gnumeric-config.h>
15 #include "ms-container.h"
16 #include "ms-escher.h"
18 #include "ms-excel-util.h"
20 #include <expr-name.h>
23 #include <gsf/gsf-utils.h>
26 ms_container_init (MSContainer
*container
, MSContainerClass
const *vtbl
,
27 MSContainer
*parent
, GnmXLImporter
*importer
)
29 container
->vtbl
= vtbl
;
30 container
->importer
= importer
;
31 container
->free_blips
= TRUE
;
32 container
->blips
= NULL
;
33 container
->obj_queue
= NULL
;
34 container
->parent
= parent
;
36 container
->v7
.externsheets
= NULL
;
37 container
->v7
.externnames
= NULL
;
41 ms_container_finalize (MSContainer
*container
)
45 g_return_if_fail (container
!= NULL
);
47 if (container
->free_blips
&& container
->blips
!= NULL
) {
48 for (i
= container
->blips
->len
; i
-- > 0 ; ) {
49 MSEscherBlip
*blip
= g_ptr_array_index (container
->blips
, i
);
51 ms_escher_blip_free (blip
);
54 g_ptr_array_free (container
->blips
, TRUE
);
55 container
->blips
= NULL
;
58 if (container
->obj_queue
!= NULL
) {
60 for (ptr
= container
->obj_queue
; ptr
!= NULL
; ptr
= ptr
->next
)
61 ms_obj_delete (ptr
->data
);
63 g_slist_free (container
->obj_queue
);
64 container
->obj_queue
= NULL
;
67 if (container
->v7
.externsheets
!= NULL
) {
68 g_ptr_array_free (container
->v7
.externsheets
, TRUE
);
69 container
->v7
.externsheets
= NULL
;
71 if (container
->v7
.externnames
!= NULL
) {
72 for (i
= container
->v7
.externnames
->len
; i
-- > 0 ; )
73 if (g_ptr_array_index (container
->v7
.externnames
, i
) != NULL
) {
74 GnmNamedExpr
*nexpr
= g_ptr_array_index (container
->v7
.externnames
, i
);
76 /* NAME placeholders need removal, EXTERNNAME placeholders
77 * will no be active */
78 if (expr_name_is_active (nexpr
) &&
79 expr_name_is_placeholder (nexpr
) &&
80 /* FIXME: Why do we need this? */
81 nexpr
->ref_count
== 2)
82 expr_name_remove (nexpr
);
83 expr_name_unref (nexpr
);
86 g_ptr_array_free (container
->v7
.externnames
, TRUE
);
87 container
->v7
.externnames
= NULL
;
92 ms_container_add_blip (MSContainer
*container
, MSEscherBlip
*blip
)
94 if (container
->blips
== NULL
)
95 container
->blips
= g_ptr_array_new ();
96 g_ptr_array_add (container
->blips
, blip
);
100 ms_container_get_blip (MSContainer
*container
, int blip_id
)
102 g_return_val_if_fail (container
!= NULL
, NULL
);
103 g_return_val_if_fail (blip_id
>= 0, NULL
);
105 if (container
->parent
!= NULL
&&
106 (container
->blips
== NULL
|| container
->blips
->len
== 0))
107 return ms_container_get_blip (container
->parent
, blip_id
);
109 g_return_val_if_fail (container
->blips
!= NULL
, NULL
);
110 g_return_val_if_fail (blip_id
< (int)container
->blips
->len
, NULL
);
112 return g_ptr_array_index (container
->blips
, blip_id
);
116 ms_container_set_blips (MSContainer
*container
, GPtrArray
*blips
)
118 g_return_if_fail (container
!= NULL
);
119 g_return_if_fail (container
->blips
== NULL
|| container
->blips
== blips
);
121 container
->blips
= blips
;
122 container
->free_blips
= FALSE
;
126 ms_container_add_obj (MSContainer
*container
, MSObj
*obj
)
129 g_warning ("registered obj %d\n", obj
->id
);
131 container
->obj_queue
= g_slist_prepend (container
->obj_queue
, obj
);
135 ms_container_get_obj (MSContainer
*c
, int obj_id
)
139 for (ptr
= c
->obj_queue
; ptr
!= NULL
; ptr
= ptr
->next
) {
140 MSObj
*obj
= ptr
->data
;
141 if (obj
!= NULL
&& obj
->id
== obj_id
)
144 g_warning ("did not find %d\n", obj_id
);
149 * ms_container_realize_objs:
152 * This realizes the objects after the zoom factor has been
156 ms_container_realize_objs (MSContainer
*container
)
160 g_return_if_fail (container
!= NULL
);
161 g_return_if_fail (container
->vtbl
!= NULL
);
162 g_return_if_fail (container
->vtbl
->realize_obj
!= NULL
);
164 for (ptr
= container
->obj_queue
; ptr
!= NULL
; ptr
= ptr
->next
) {
165 MSObj
*obj
= ptr
->data
;
166 if (obj
->gnum_obj
!= NULL
)
167 (void) (*container
->vtbl
->realize_obj
) (container
, obj
);
172 * ms_container_parse_expr:
175 * @data: the encoded expression
176 * @length: the size of the encoded expression
178 * Attempts to parse the encoded expression in the context of the container.
181 ms_container_parse_expr (MSContainer
*c
, guint8
const *data
, int length
)
183 g_return_val_if_fail (c
!= NULL
, NULL
);
184 g_return_val_if_fail (c
->vtbl
!= NULL
, NULL
);
185 g_return_val_if_fail (c
->vtbl
->parse_expr
!= NULL
, NULL
);
188 return (*c
->vtbl
->parse_expr
) (c
, data
, length
);
192 * ms_container_sheet:
197 * This will become dependent_container when that abstraction is added
198 * in the code. We will need it to support tabs with standalone charts.
202 ms_container_sheet (MSContainer
const *c
)
204 g_return_val_if_fail (c
!= NULL
, NULL
);
205 g_return_val_if_fail (c
->vtbl
!= NULL
, NULL
);
206 if (c
->vtbl
->sheet
== NULL
)
208 return (*c
->vtbl
->sheet
) (c
);
212 ms_container_get_fmt (MSContainer
const *c
, unsigned indx
)
214 for ( ; TRUE
; c
= c
->parent
) {
215 g_return_val_if_fail (c
!= NULL
, NULL
);
216 g_return_val_if_fail (c
->vtbl
!= NULL
, NULL
);
217 if (c
->vtbl
->get_fmt
!= NULL
)
220 return (*c
->vtbl
->get_fmt
) (c
, indx
);
224 * ms_container_get_markup :
228 * Return a #PangoAttrList the caller should not modify or free the list.
231 ms_container_get_markup (MSContainer
const *c
, unsigned indx
)
233 for ( ; TRUE
; c
= c
->parent
) {
234 g_return_val_if_fail (c
!= NULL
, NULL
);
235 g_return_val_if_fail (c
->vtbl
!= NULL
, NULL
);
236 if (c
->vtbl
->get_markup
!= NULL
)
239 return (*c
->vtbl
->get_markup
) (c
, indx
);
243 unsigned first
, last
;
244 PangoAttrList
*accum
;
248 append_txorun (PangoAttribute
*src
, TXORun
*run
)
250 PangoAttribute
*dst
= pango_attribute_copy (src
);
251 dst
->start_index
= run
->first
; /* inclusive */
252 dst
->end_index
= run
->last
; /* exclusive */
253 pango_attr_list_change (run
->accum
, dst
);
258 ms_container_read_markup (MSContainer
const *c
,
259 guint8
const *data
, size_t txo_len
,
265 XL_CHECK_CONDITION_VAL (txo_len
>= 16,
266 pango_attr_list_new ()); /* min two records */
268 str_len
= g_utf8_strlen (str
, -1);
270 txo_run
.last
= G_MAXINT
;
271 txo_run
.accum
= NULL
;
272 for (txo_len
-= 16 ; (gssize
)txo_len
>= 0 ; txo_len
-= 8) {
273 guint16 o
= GSF_LE_GET_GUINT16 (data
+ txo_len
);
274 guint16 idx
= GSF_LE_GET_GUINT16 (data
+ txo_len
+ 2);
276 XL_CHECK_CONDITION_VAL (o
<= str_len
, txo_run
.accum
);
277 txo_run
.first
= g_utf8_offset_to_pointer (str
, o
) - str
;
278 XL_CHECK_CONDITION_VAL (txo_run
.first
< txo_run
.last
, txo_run
.accum
);
282 txo_run
.accum
= pango_attr_list_new ();
283 pango_attr_list_filter
284 (ms_container_get_markup (c
, idx
),
285 (PangoAttrFilterFunc
) append_txorun
,
288 txo_run
.last
= txo_run
.first
;
290 return txo_run
.accum
;