2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
17 * Not Zed <notzed@lostzed.mmc.com.au>
18 * Jepartrey Stedfast <fejj@ximian.com>
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
32 #include <glib/gi18n.h>
34 #include "e-filter-file.h"
35 #include "e-filter-part.h"
36 #include "e-rule-context.h"
44 filter_part_finalize (GObject
*object
)
46 EFilterPart
*part
= E_FILTER_PART (object
);
48 g_list_foreach (part
->elements
, (GFunc
) g_object_unref
, NULL
);
49 g_list_free (part
->elements
);
55 /* Chain up to parent's finalize() method. */
56 G_OBJECT_CLASS (e_filter_part_parent_class
)->finalize (object
);
60 e_filter_part_class_init (EFilterPartClass
*class)
62 GObjectClass
*object_class
;
64 object_class
= G_OBJECT_CLASS (class);
65 object_class
->finalize
= filter_part_finalize
;
69 e_filter_part_init (EFilterPart
*part
)
76 * Create a new EFilterPart object.
78 * Return value: A new #EFilterPart object.
81 e_filter_part_new (void)
83 return g_object_new (E_TYPE_FILTER_PART
, NULL
);
87 e_filter_part_validate (EFilterPart
*part
,
92 g_return_val_if_fail (E_IS_FILTER_PART (part
), FALSE
);
94 /* The part is valid if all of its elements are valid. */
95 for (link
= part
->elements
; link
!= NULL
; link
= g_list_next (link
)) {
96 EFilterElement
*element
= link
->data
;
98 if (!e_filter_element_validate (element
, alert
))
106 e_filter_part_eq (EFilterPart
*part_a
,
109 GList
*link_a
, *link_b
;
111 g_return_val_if_fail (E_IS_FILTER_PART (part_a
), FALSE
);
112 g_return_val_if_fail (E_IS_FILTER_PART (part_b
), FALSE
);
114 if (g_strcmp0 (part_a
->name
, part_b
->name
) != 0)
117 if (g_strcmp0 (part_a
->title
, part_b
->title
) != 0)
120 if (g_strcmp0 (part_a
->code
, part_b
->code
) != 0)
123 link_a
= part_a
->elements
;
124 link_b
= part_b
->elements
;
126 while (link_a
!= NULL
&& link_b
!= NULL
) {
127 EFilterElement
*element_a
= link_a
->data
;
128 EFilterElement
*element_b
= link_b
->data
;
130 if (!e_filter_element_eq (element_a
, element_b
))
133 link_a
= g_list_next (link_a
);
134 link_b
= g_list_next (link_b
);
137 if (link_a
!= NULL
|| link_b
!= NULL
)
144 e_filter_part_xml_create (EFilterPart
*part
,
146 ERuleContext
*context
)
152 g_return_val_if_fail (E_IS_FILTER_PART (part
), FALSE
);
153 g_return_val_if_fail (node
!= NULL
, FALSE
);
154 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), FALSE
);
156 str
= (gchar
*)xmlGetProp (node
, (xmlChar
*)"name");
157 part
->name
= g_strdup (str
);
163 if (!strcmp ((gchar
*)n
->name
, "input")) {
164 type
= (gchar
*)xmlGetProp (n
, (xmlChar
*)"type");
166 && (el
= e_rule_context_new_element (context
, type
)) != NULL
) {
167 e_filter_element_xml_create (el
, n
);
169 part
->elements
= g_list_append (part
->elements
, el
);
171 g_warning ("Invalid xml format, missing/unknown input type");
173 } else if (!strcmp ((gchar
*)n
->name
, "title") ||
174 !strcmp ((gchar
*)n
->name
, "_title")) {
176 str
= (gchar
*) xmlNodeGetContent (n
);
177 part
->title
= g_strdup (str
);
181 } else if (!strcmp ((gchar
*)n
->name
, "code")) {
183 str
= (gchar
*) xmlNodeGetContent (n
);
184 part
->code
= g_strdup (str
);
188 } else if (n
->type
== XML_ELEMENT_NODE
) {
189 g_warning ("Unknown part element in xml: %s\n", n
->name
);
198 e_filter_part_xml_encode (EFilterPart
*part
)
203 g_return_val_if_fail (E_IS_FILTER_PART (part
), NULL
);
205 node
= xmlNewNode (NULL
, (xmlChar
*)"part");
206 xmlSetProp (node
, (xmlChar
*)"name", (xmlChar
*)part
->name
);
208 for (link
= part
->elements
; link
!= NULL
; link
= g_list_next (link
)) {
209 EFilterElement
*element
= link
->data
;
212 value
= e_filter_element_xml_encode (element
);
213 xmlAddChild (node
, value
);
220 e_filter_part_xml_decode (EFilterPart
*part
,
225 g_return_val_if_fail (E_IS_FILTER_PART (part
), -1);
226 g_return_val_if_fail (node
!= NULL
, -1);
228 for (child
= node
->children
; child
!= NULL
; child
= child
->next
) {
229 EFilterElement
*element
;
232 if (strcmp ((gchar
*) child
->name
, "value") != 0)
235 name
= xmlGetProp (child
, (xmlChar
*) "name");
236 element
= e_filter_part_find_element (part
, (gchar
*) name
);
240 e_filter_element_xml_decode (element
, child
);
247 e_filter_part_clone (EFilterPart
*part
)
252 g_return_val_if_fail (E_IS_FILTER_PART (part
), NULL
);
254 clone
= g_object_new (G_OBJECT_TYPE (part
), NULL
, NULL
);
255 clone
->name
= g_strdup (part
->name
);
256 clone
->title
= g_strdup (part
->title
);
257 clone
->code
= g_strdup (part
->code
);
259 for (link
= part
->elements
; link
!= NULL
; link
= g_list_next (link
)) {
260 EFilterElement
*element
= link
->data
;
261 EFilterElement
*clone_element
;
263 clone_element
= e_filter_element_clone (element
);
264 clone
->elements
= g_list_append (clone
->elements
, clone_element
);
270 /* only copies values of matching parts in the right order */
272 e_filter_part_copy_values (EFilterPart
*dst_part
,
273 EFilterPart
*src_part
)
275 GList
*dst_link
, *src_link
;
277 g_return_if_fail (E_IS_FILTER_PART (dst_part
));
278 g_return_if_fail (E_IS_FILTER_PART (src_part
));
280 /* NOTE: we go backwards, it just works better that way */
282 /* for each source type, search the dest type for
283 * a matching type in the same order */
284 src_link
= g_list_last (src_part
->elements
);
285 dst_link
= g_list_last (dst_part
->elements
);
287 while (src_link
!= NULL
&& dst_link
!= NULL
) {
288 EFilterElement
*src_element
= src_link
->data
;
289 GList
*link
= dst_link
;
291 while (link
!= NULL
) {
292 EFilterElement
*dst_element
= link
->data
;
293 GType dst_type
= G_OBJECT_TYPE (dst_element
);
294 GType src_type
= G_OBJECT_TYPE (src_element
);
296 if (dst_type
== src_type
) {
297 e_filter_element_copy_value (
298 dst_element
, src_element
);
299 dst_link
= g_list_previous (link
);
303 link
= g_list_previous (link
);
306 src_link
= g_list_previous (src_link
);
311 e_filter_part_find_element (EFilterPart
*part
,
316 g_return_val_if_fail (E_IS_FILTER_PART (part
), NULL
);
321 for (link
= part
->elements
; link
!= NULL
; link
= g_list_next (link
)) {
322 EFilterElement
*element
= link
->data
;
324 if (g_strcmp0 (element
->name
, name
) == 0)
332 e_filter_part_get_widget (EFilterPart
*part
)
337 g_return_val_if_fail (E_IS_FILTER_PART (part
), NULL
);
339 hbox
= gtk_hbox_new (FALSE
, 3);
341 for (link
= part
->elements
; link
!= NULL
; link
= g_list_next (link
)) {
342 EFilterElement
*element
= link
->data
;
345 widget
= e_filter_element_get_widget (element
);
348 GTK_BOX (hbox
), widget
,
349 E_IS_FILTER_FILE (element
),
350 E_IS_FILTER_FILE (element
), 3);
353 gtk_widget_show_all (hbox
);
359 * e_filter_part_build_code:
363 * Outputs the code of a part.
366 e_filter_part_build_code (EFilterPart
*part
,
371 g_return_if_fail (E_IS_FILTER_PART (part
));
372 g_return_if_fail (out
!= NULL
);
374 if (part
->code
!= NULL
)
375 e_filter_part_expand_code (part
, part
->code
, out
);
377 for (link
= part
->elements
; link
!= NULL
; link
= g_list_next (link
)) {
378 EFilterElement
*element
= link
->data
;
379 e_filter_element_build_code (element
, out
, part
);
384 * e_filter_part_build_code_list:
388 * Construct a list of the filter parts code into
392 e_filter_part_build_code_list (GList
*list
,
397 g_return_if_fail (out
!= NULL
);
399 for (link
= list
; link
!= NULL
; link
= g_list_next (link
)) {
400 EFilterPart
*part
= link
->data
;
402 e_filter_part_build_code (part
, out
);
403 g_string_append (out
, "\n ");
408 * e_filter_part_find_list:
412 * Find a filter part stored in a list.
417 e_filter_part_find_list (GList
*list
,
422 g_return_val_if_fail (name
!= NULL
, NULL
);
424 for (link
= list
; link
!= NULL
; link
= g_list_next (link
)) {
425 EFilterPart
*part
= link
->data
;
427 if (g_strcmp0 (part
->name
, name
) == 0)
435 * e_filter_part_next_list:
437 * @last: The last item retrieved, or NULL to start
438 * from the beginning of the list.
440 * Iterate through a filter part list.
442 * Return value: The next value in the list, or NULL if the
446 e_filter_part_next_list (GList
*list
,
452 link
= g_list_find (list
, last
);
459 return (link
!= NULL
) ? link
->data
: NULL
;
463 * e_filter_part_expand_code:
468 * Expands the variables in string @str based on the values of the part.
471 e_filter_part_expand_code (EFilterPart
*part
,
475 const gchar
*newstart
, *start
, *end
;
476 gchar
*name
= g_alloca (32);
477 gint len
, namelen
= 32;
479 g_return_if_fail (E_IS_FILTER_PART (part
));
480 g_return_if_fail (source
!= NULL
);
481 g_return_if_fail (out
!= NULL
);
485 while (start
&& (newstart
= strstr (start
, "${"))
486 && (end
= strstr (newstart
+2, "}")) ) {
487 EFilterElement
*element
;
489 len
= end
- newstart
- 2;
490 if (len
+ 1 > namelen
) {
491 namelen
= (len
+ 1) * 2;
492 name
= g_alloca (namelen
);
494 memcpy (name
, newstart
+ 2, len
);
497 element
= e_filter_part_find_element (part
, name
);
498 if (element
!= NULL
) {
499 g_string_append_printf (out
, "%.*s", (gint
)(newstart
-start
), start
);
500 e_filter_element_format_sexp (element
, out
);
502 } else if ((val
= g_hash_table_lookup (part
->globals
, name
))) {
503 g_string_append_printf (out
, "%.*s", newstart
-start
, start
);
504 camel_sexp_encode_string (out
, val
);
507 g_string_append_printf (out
, "%.*s", (gint
)(end
-start
+1), start
);
512 g_string_append (out
, start
);