1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Shaun McCance <shaunm@gnome.org>
28 #include <glib/gi18n.h>
30 #include <libxml/parser.h>
31 #include <libxml/parserInternals.h>
32 #include <libxml/xinclude.h>
34 #include "yelp-error.h"
35 #include "yelp-mallard-document.h"
36 #include "yelp-settings.h"
37 #include "yelp-transform.h"
38 #include "yelp-debug.h"
40 #define STYLESHEET DATADIR"/yelp/xslt/mal2html.xsl"
41 #define MALLARD_NS "http://projectmallard.org/1.0/"
42 #define MALLARD_FACET_NS "http://projectmallard.org/facet/1.0/"
46 MALLARD_STATE_THINKING
,
52 YelpMallardDocument
*mallard
;
57 YelpTransform
*transform
;
65 xmlXPathContextPtr xpath
;
74 static void yelp_mallard_document_class_init (YelpMallardDocumentClass
*klass
);
75 static void yelp_mallard_document_init (YelpMallardDocument
*mallard
);
76 static void yelp_mallard_document_dispose (GObject
*object
);
77 static void yelp_mallard_document_finalize (GObject
*object
);
79 static gboolean
mallard_request_page (YelpDocument
*document
,
81 GCancellable
*cancellable
,
82 YelpDocumentCallback callback
,
85 static void transform_chunk_ready (YelpTransform
*transform
,
87 MallardPageData
*page_data
);
88 static void transform_finished (YelpTransform
*transform
,
89 MallardPageData
*page_data
);
90 static void transform_error (YelpTransform
*transform
,
91 MallardPageData
*page_data
);
93 static void mallard_think (YelpMallardDocument
*mallard
);
94 static void mallard_try_run (YelpMallardDocument
*mallard
,
95 const gchar
*page_id
);
97 static void mallard_page_data_cancel (MallardPageData
*page_data
);
98 static void mallard_page_data_walk (MallardPageData
*page_data
);
99 static void mallard_page_data_info (MallardPageData
*page_data
,
100 xmlNodePtr info_node
,
101 xmlNodePtr cache_node
);
102 static void mallard_page_data_run (MallardPageData
*page_data
);
103 static void mallard_page_data_free (MallardPageData
*page_data
);
105 static gboolean
xml_node_is_ns_name (xmlNodePtr node
,
107 const xmlChar
*name
);
110 G_DEFINE_TYPE (YelpMallardDocument
, yelp_mallard_document
, YELP_TYPE_DOCUMENT
);
111 #define GET_PRIV(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_MALLARD_DOCUMENT, YelpMallardDocumentPrivate))
113 typedef struct _YelpMallardDocumentPrivate YelpMallardDocumentPrivate
;
114 struct _YelpMallardDocumentPrivate
{
120 gboolean thread_running
;
125 GHashTable
*pages_hash
;
127 xmlXPathCompExprPtr normalize
;
130 /******************************************************************************/
133 yelp_mallard_document_class_init (YelpMallardDocumentClass
*klass
)
135 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
136 YelpDocumentClass
*document_class
= YELP_DOCUMENT_CLASS (klass
);
138 object_class
->dispose
= yelp_mallard_document_dispose
;
139 object_class
->finalize
= yelp_mallard_document_finalize
;
141 document_class
->request_page
= mallard_request_page
;
143 g_type_class_add_private (klass
, sizeof (YelpMallardDocumentPrivate
));
147 yelp_mallard_document_init (YelpMallardDocument
*mallard
)
149 YelpMallardDocumentPrivate
*priv
= GET_PRIV (mallard
);
152 priv
->mutex
= g_mutex_new ();
154 priv
->thread_running
= FALSE
;
156 priv
->cache
= xmlNewDoc (BAD_CAST
"1.0");
157 priv
->cache_ns
= xmlNewNs (NULL
, BAD_CAST MALLARD_NS
, BAD_CAST
"mal");
158 cur
= xmlNewDocNode (priv
->cache
, priv
->cache_ns
, BAD_CAST
"cache", NULL
);
159 xmlDocSetRootElement (priv
->cache
, cur
);
160 priv
->cache_ns
->next
= cur
->nsDef
;
161 cur
->nsDef
= priv
->cache_ns
;
162 priv
->pages_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
164 (GDestroyNotify
) mallard_page_data_free
);
165 priv
->normalize
= xmlXPathCompile ("normalize-space(.)");
169 yelp_mallard_document_dispose (GObject
*object
)
171 G_OBJECT_CLASS (yelp_mallard_document_parent_class
)->dispose (object
);
175 yelp_mallard_document_finalize (GObject
*object
)
177 YelpMallardDocumentPrivate
*priv
= GET_PRIV (object
);
179 g_object_unref (priv
->uri
);
180 g_mutex_free (priv
->mutex
);
181 g_hash_table_destroy (priv
->pages_hash
);
184 xmlXPathFreeCompExpr (priv
->normalize
);
186 G_OBJECT_CLASS (yelp_mallard_document_parent_class
)->finalize (object
);
189 /******************************************************************************/
192 yelp_mallard_document_new (YelpUri
*uri
)
194 YelpMallardDocument
*mallard
;
195 YelpMallardDocumentPrivate
*priv
;
197 g_return_val_if_fail (uri
!= NULL
, NULL
);
199 mallard
= (YelpMallardDocument
*) g_object_new (YELP_TYPE_MALLARD_DOCUMENT
, NULL
);
200 priv
= GET_PRIV (mallard
);
201 priv
->uri
= g_object_ref (uri
);
203 yelp_document_set_page_id ((YelpDocument
*) mallard
, NULL
, "index");
204 yelp_document_set_page_id ((YelpDocument
*) mallard
, "index", "index");
206 return (YelpDocument
*) mallard
;
211 mallard_request_page (YelpDocument
*document
,
212 const gchar
*page_id
,
213 GCancellable
*cancellable
,
214 YelpDocumentCallback callback
,
217 YelpMallardDocumentPrivate
*priv
= GET_PRIV (document
);
222 debug_print (DB_FUNCTION
, "entering\n");
223 debug_print (DB_ARG
, " page_id=\"%s\"\n", page_id
);
229 YELP_DOCUMENT_CLASS (yelp_mallard_document_parent_class
)->request_page (document
,
238 g_mutex_lock (priv
->mutex
);
240 if (priv
->state
== MALLARD_STATE_BLANK
) {
241 priv
->state
= MALLARD_STATE_THINKING
;
242 priv
->thread_running
= TRUE
;
243 g_object_ref (document
);
244 priv
->thread
= g_thread_create ((GThreadFunc
) mallard_think
,
245 document
, FALSE
, NULL
);
248 switch (priv
->state
) {
249 case MALLARD_STATE_THINKING
:
250 priv
->pending
= g_slist_prepend (priv
->pending
, (gpointer
) g_strdup (page_id
));
252 case MALLARD_STATE_IDLE
:
253 mallard_try_run ((YelpMallardDocument
*) document
, page_id
);
255 case MALLARD_STATE_BLANK
:
256 case MALLARD_STATE_STOP
:
257 docuri
= yelp_uri_get_document_uri (priv
->uri
);
258 error
= g_error_new (YELP_ERROR
, YELP_ERROR_NOT_FOUND
,
259 _("The page ‘%s’ was not found in the document ‘%s’."),
262 yelp_document_signal (document
, page_id
,
263 YELP_DOCUMENT_SIGNAL_ERROR
,
265 g_error_free (error
);
269 g_mutex_unlock (priv
->mutex
);
274 /******************************************************************************/
277 mallard_think (YelpMallardDocument
*mallard
)
279 YelpMallardDocumentPrivate
*priv
= GET_PRIV (mallard
);
280 GError
*error
= NULL
;
281 YelpDocument
*document
;
283 gboolean editor_mode
;
288 GFileEnumerator
*children
;
291 editor_mode
= yelp_settings_get_editor_mode (yelp_settings_get_default ());
293 search_path
= yelp_uri_get_search_path (priv
->uri
);
295 if (!search_path
|| search_path
[0] == NULL
||
296 !g_file_test (search_path
[0], G_FILE_TEST_IS_DIR
)) {
297 /* This basically only happens when someone passes an actual directory
298 manually, which will have a singleton search path.
300 error
= g_error_new (YELP_ERROR
, YELP_ERROR_NOT_FOUND
,
301 _("The directory ‘%s’ does not exist."),
303 yelp_document_error_pending ((YelpDocument
*) document
, error
);
304 g_error_free (error
);
308 path
= yelp_uri_get_search_path (priv
->uri
);
309 for (path_i
= 0; path
[path_i
] != NULL
; path_i
++) {
310 gfile
= g_file_new_for_path (path
[path_i
]);
311 children
= g_file_enumerate_children (gfile
,
312 G_FILE_ATTRIBUTE_STANDARD_NAME
,
313 G_FILE_QUERY_INFO_NONE
,
315 while ((pageinfo
= g_file_enumerator_next_file (children
, NULL
, NULL
))) {
316 MallardPageData
*page_data
;
319 filename
= g_file_info_get_attribute_as_string (pageinfo
,
320 G_FILE_ATTRIBUTE_STANDARD_NAME
);
321 if (!g_str_has_suffix (filename
, ".page") &&
322 !(editor_mode
&& g_str_has_suffix (filename
, ".page.stub"))) {
324 g_object_unref (pageinfo
);
327 page_data
= g_new0 (MallardPageData
, 1);
328 page_data
->mallard
= mallard
;
329 pagefile
= g_file_resolve_relative_path (gfile
, filename
);
330 page_data
->filename
= g_file_get_path (pagefile
);
331 mallard_page_data_walk (page_data
);
332 if (page_data
->page_id
== NULL
) {
333 mallard_page_data_free (page_data
);
335 else if (g_hash_table_lookup (priv
->pages_hash
, page_data
->page_id
) != NULL
) {
336 mallard_page_data_free (page_data
);
339 g_mutex_lock (priv
->mutex
);
340 yelp_document_set_root_id ((YelpDocument
*) mallard
,
341 page_data
->page_id
, "index");
342 yelp_document_set_page_id ((YelpDocument
*) mallard
,
343 page_data
->page_id
, page_data
->page_id
);
344 g_hash_table_insert (priv
->pages_hash
, page_data
->page_id
, page_data
);
345 yelp_document_set_page_title ((YelpDocument
*) mallard
,
347 page_data
->page_title
);
348 yelp_document_set_page_desc ((YelpDocument
*) mallard
,
350 page_data
->page_desc
);
351 yelp_document_signal ((YelpDocument
*) mallard
,
353 YELP_DOCUMENT_SIGNAL_INFO
,
355 g_mutex_unlock (priv
->mutex
);
357 g_object_unref (pagefile
);
359 g_object_unref (pageinfo
);
364 g_mutex_lock (priv
->mutex
);
365 priv
->state
= MALLARD_STATE_IDLE
;
366 while (priv
->pending
) {
367 gchar
*page_id
= (gchar
*) priv
->pending
->data
;
368 mallard_try_run (mallard
, page_id
);
370 priv
->pending
= g_slist_delete_link (priv
->pending
, priv
->pending
);
372 g_mutex_unlock (priv
->mutex
);
375 g_object_unref (children
);
376 g_object_unref (gfile
);
378 priv
->thread_running
= FALSE
;
379 g_object_unref (mallard
);
383 mallard_try_run (YelpMallardDocument
*mallard
,
384 const gchar
*page_id
)
386 /* We expect to be in a locked mutex when this function is called. */
387 YelpMallardDocumentPrivate
*priv
= GET_PRIV (mallard
);
388 MallardPageData
*page_data
= NULL
;
389 gchar
*real_id
= NULL
;
392 debug_print (DB_FUNCTION
, "entering\n");
393 debug_print (DB_ARG
, " page_id=\"%s\"\n", page_id
);
396 real_id
= yelp_document_get_page_id ((YelpDocument
*) mallard
, page_id
);
398 if (real_id
!= NULL
) {
399 page_data
= g_hash_table_lookup (priv
->pages_hash
, real_id
);
403 if (page_data
== NULL
) {
404 gchar
*docuri
= yelp_uri_get_document_uri (priv
->uri
);
405 error
= g_error_new (YELP_ERROR
, YELP_ERROR_NOT_FOUND
,
406 _("The page ‘%s’ was not found in the document ‘%s’."),
409 yelp_document_signal ((YelpDocument
*) mallard
, page_id
,
410 YELP_DOCUMENT_SIGNAL_ERROR
,
412 g_error_free (error
);
416 mallard_page_data_run (page_data
);
419 /******************************************************************************/
420 /** MallardPageData ***********************************************************/
423 mallard_page_data_cancel (MallardPageData
*page_data
)
425 if (page_data
->transform
) {
426 if (page_data
->chunk_ready
) {
427 g_signal_handler_disconnect (page_data
->transform
, page_data
->chunk_ready
);
428 page_data
->chunk_ready
= 0;
430 if (page_data
->finished
) {
431 g_signal_handler_disconnect (page_data
->transform
, page_data
->finished
);
432 page_data
->finished
= 0;
434 if (page_data
->error
) {
435 g_signal_handler_disconnect (page_data
->transform
, page_data
->error
);
436 page_data
->error
= 0;
438 yelp_transform_cancel (page_data
->transform
);
439 g_object_unref (page_data
->transform
);
440 page_data
->transform
= NULL
;
445 mallard_page_data_walk (MallardPageData
*page_data
)
447 YelpMallardDocumentPrivate
*priv
= GET_PRIV (page_data
->mallard
);
448 xmlParserCtxtPtr parserCtxt
= NULL
;
451 if (page_data
->cur
== NULL
) {
452 parserCtxt
= xmlNewParserCtxt ();
453 page_data
->xmldoc
= xmlCtxtReadFile (parserCtxt
,
454 (const char *) page_data
->filename
, NULL
,
455 XML_PARSE_DTDLOAD
| XML_PARSE_NOCDATA
|
456 XML_PARSE_NOENT
| XML_PARSE_NONET
);
457 if (page_data
->xmldoc
== NULL
)
459 if (xmlXIncludeProcessFlags (page_data
->xmldoc
,
460 XML_PARSE_DTDLOAD
| XML_PARSE_NOCDATA
|
461 XML_PARSE_NOENT
| XML_PARSE_NONET
)
464 page_data
->cur
= xmlDocGetRootElement (page_data
->xmldoc
);
465 page_data
->cache
= xmlDocGetRootElement (priv
->cache
);
466 page_data
->xpath
= xmlXPathNewContext (page_data
->xmldoc
);
467 mallard_page_data_walk (page_data
);
470 xmlNodePtr child
, oldcur
, oldcache
, info
;
472 id
= xmlGetProp (page_data
->cur
, BAD_CAST
"id");
476 ispage
= xml_node_is_ns_name (page_data
->cur
, MALLARD_NS
, BAD_CAST
"page");
477 if (ispage
&& g_hash_table_lookup (priv
->pages_hash
, id
) != NULL
)
480 page_data
->cache
= xmlNewChild (page_data
->cache
,
482 page_data
->cur
->name
,
488 gchar
*icon
= "help-contents";
489 page_data
->page_id
= g_strdup ((gchar
*) id
);
490 xmlSetProp (page_data
->cache
, BAD_CAST
"id", id
);
491 yelp_document_set_page_id ((YelpDocument
*) page_data
->mallard
,
492 g_strrstr (page_data
->filename
, G_DIR_SEPARATOR_S
),
494 style
= xmlGetProp (page_data
->cur
, BAD_CAST
"style");
497 styles
= g_strsplit (style
, " ", -1);
498 for (i
= 0; styles
[i
] != NULL
; i
++) {
499 if (g_str_equal (styles
[i
], "task")) {
500 icon
= "yelp-page-task";
503 else if (g_str_equal (styles
[i
], "tip")) {
504 icon
= "yelp-page-tip";
507 else if (g_str_equal (styles
[i
], "ui")) {
508 icon
= "yelp-page-ui";
511 else if (g_str_equal (styles
[i
], "video")) {
512 icon
= "yelp-page-video";
518 yelp_document_set_page_icon ((YelpDocument
*) page_data
->mallard
,
519 page_data
->page_id
, icon
);
521 gchar
*newid
= g_strdup_printf ("%s#%s", page_data
->page_id
, id
);
522 xmlSetProp (page_data
->cache
, BAD_CAST
"id", BAD_CAST newid
);
526 info
= xmlNewChild (page_data
->cache
,
528 BAD_CAST
"info", NULL
);
529 page_data
->link_title
= FALSE
;
530 page_data
->sort_title
= FALSE
;
531 for (child
= page_data
->cur
->children
; child
; child
= child
->next
) {
532 if (child
->type
!= XML_ELEMENT_NODE
)
534 if (xml_node_is_ns_name (child
, MALLARD_NS
, BAD_CAST
"info")) {
535 mallard_page_data_info (page_data
, child
, info
);
537 else if (xml_node_is_ns_name (child
, MALLARD_NS
, BAD_CAST
"title")) {
539 xmlNodePtr title_node
= xmlNewChild (page_data
->cache
,
541 BAD_CAST
"title", NULL
);
542 for (node
= child
->children
; node
; node
= node
->next
) {
543 xmlAddChild (title_node
, xmlCopyNode (node
, 1));
545 if (!page_data
->link_title
) {
546 xmlNodePtr title_node
= xmlNewChild (info
,
548 BAD_CAST
"title", NULL
);
549 xmlSetProp (title_node
, BAD_CAST
"type", BAD_CAST
"link");
550 for (node
= child
->children
; node
; node
= node
->next
) {
551 xmlAddChild (title_node
, xmlCopyNode (node
, 1));
554 if (!page_data
->sort_title
) {
555 xmlNodePtr title_node
= xmlNewChild (info
,
557 BAD_CAST
"title", NULL
);
558 xmlSetProp (title_node
, BAD_CAST
"type", BAD_CAST
"sort");
559 for (node
= child
->children
; node
; node
= node
->next
) {
560 xmlAddChild (title_node
, xmlCopyNode (node
, 1));
563 if (page_data
->page_title
== NULL
) {
564 YelpMallardDocumentPrivate
*priv
= GET_PRIV (page_data
->mallard
);
565 xmlXPathObjectPtr obj
;
566 page_data
->xpath
->node
= child
;
567 obj
= xmlXPathCompiledEval (priv
->normalize
, page_data
->xpath
);
568 page_data
->page_title
= g_strdup (obj
->stringval
);
569 xmlXPathFreeObject (obj
);
572 else if (xml_node_is_ns_name (child
, MALLARD_NS
, BAD_CAST
"section")) {
573 oldcur
= page_data
->cur
;
574 oldcache
= page_data
->cache
;
575 page_data
->cur
= child
;
576 mallard_page_data_walk (page_data
);
577 page_data
->cur
= oldcur
;
578 page_data
->cache
= oldcache
;
587 xmlFreeParserCtxt (parserCtxt
);
591 mallard_page_data_info (MallardPageData
*page_data
,
592 xmlNodePtr info_node
,
593 xmlNodePtr cache_node
)
596 gboolean editor_mode
= yelp_settings_get_editor_mode (yelp_settings_get_default ());
598 for (child
= info_node
->children
; child
; child
= child
->next
) {
599 if (xml_node_is_ns_name (child
, MALLARD_NS
, BAD_CAST
"info")) {
600 mallard_page_data_info (page_data
, child
, cache_node
);
602 else if (xml_node_is_ns_name (child
, MALLARD_NS
, BAD_CAST
"title")) {
603 xmlNodePtr node
, title_node
;
604 xmlChar
*type
, *role
;
605 title_node
= xmlCopyNode (child
, 1);
606 xmlAddChild (cache_node
, title_node
);
608 type
= xmlGetProp (child
, BAD_CAST
"type");
609 role
= xmlGetProp (child
, BAD_CAST
"role");
611 if (xmlStrEqual (type
, BAD_CAST
"link") && role
== NULL
)
612 page_data
->link_title
= TRUE
;
613 if (xmlStrEqual (type
, BAD_CAST
"sort"))
614 page_data
->sort_title
= TRUE
;
615 if (xmlStrEqual (type
, BAD_CAST
"text")) {
616 YelpMallardDocumentPrivate
*priv
= GET_PRIV (page_data
->mallard
);
617 xmlXPathObjectPtr obj
;
618 page_data
->xpath
->node
= child
;
619 obj
= xmlXPathCompiledEval (priv
->normalize
, page_data
->xpath
);
620 g_free (page_data
->page_title
);
621 page_data
->page_title
= g_strdup (obj
->stringval
);
622 xmlXPathFreeObject (obj
);
625 else if (xml_node_is_ns_name (child
, MALLARD_NS
, BAD_CAST
"desc")) {
626 YelpMallardDocumentPrivate
*priv
= GET_PRIV (page_data
->mallard
);
627 xmlXPathObjectPtr obj
;
628 page_data
->xpath
->node
= child
;
629 obj
= xmlXPathCompiledEval (priv
->normalize
, page_data
->xpath
);
630 page_data
->page_desc
= g_strdup (obj
->stringval
);
631 xmlXPathFreeObject (obj
);
633 xmlAddChild (cache_node
, xmlCopyNode (child
, 1));
635 else if (xml_node_is_ns_name (child
, MALLARD_NS
, BAD_CAST
"link")) {
636 xmlAddChild (cache_node
, xmlCopyNode (child
, 1));
638 else if (xml_node_is_ns_name (child
, MALLARD_NS
, BAD_CAST
"revision")) {
639 xmlAddChild (cache_node
, xmlCopyNode (child
, 1));
641 else if (xml_node_is_ns_name (child
, MALLARD_FACET_NS
, BAD_CAST
"tag") ||
642 xml_node_is_ns_name (child
, MALLARD_FACET_NS
, BAD_CAST
"match") ||
643 xml_node_is_ns_name (child
, MALLARD_FACET_NS
, BAD_CAST
"choice") ) {
644 xmlAddChild (cache_node
, xmlCopyNode (child
, 1));
650 mallard_page_data_run (MallardPageData
*page_data
)
652 YelpSettings
*settings
= yelp_settings_get_default ();
653 YelpMallardDocumentPrivate
*priv
= GET_PRIV (page_data
->mallard
);
655 gchar
**params
= NULL
;
657 mallard_page_data_cancel (page_data
);
658 page_data
->transform
= yelp_transform_new (STYLESHEET
);
660 page_data
->chunk_ready
=
661 g_signal_connect (page_data
->transform
, "chunk-ready",
662 (GCallback
) transform_chunk_ready
,
664 page_data
->finished
=
665 g_signal_connect (page_data
->transform
, "finished",
666 (GCallback
) transform_finished
,
669 g_signal_connect (page_data
->transform
, "error",
670 (GCallback
) transform_error
,
673 if (g_str_has_suffix (page_data
->filename
, ".page.stub")) {
675 params
= yelp_settings_get_all_params (settings
, 2, &end
);
676 params
[end
++] = g_strdup ("yelp.stub");
677 params
[end
++] = g_strdup ("true()");
680 params
= yelp_settings_get_all_params (settings
, 0, NULL
);
682 yelp_transform_start (page_data
->transform
,
685 (const gchar
* const *) params
);
690 mallard_page_data_free (MallardPageData
*page_data
)
692 mallard_page_data_cancel (page_data
);
693 g_free (page_data
->page_id
);
694 g_free (page_data
->filename
);
695 if (page_data
->xmldoc
)
696 xmlFreeDoc (page_data
->xmldoc
);
697 if (page_data
->xpath
)
698 xmlXPathFreeContext (page_data
->xpath
);
699 g_free (page_data
->page_title
);
700 g_free (page_data
->page_desc
);
704 /******************************************************************************/
705 /** YelpTransform *************************************************************/
708 transform_chunk_ready (YelpTransform
*transform
,
710 MallardPageData
*page_data
)
712 YelpMallardDocumentPrivate
*priv
;
715 debug_print (DB_FUNCTION
, "entering\n");
717 g_assert (page_data
!= NULL
&& page_data
->mallard
!= NULL
&&
718 YELP_IS_MALLARD_DOCUMENT (page_data
->mallard
));
719 g_assert (transform
== page_data
->transform
);
721 priv
= GET_PRIV (page_data
->mallard
);
723 if (priv
->state
== MALLARD_STATE_STOP
) {
724 mallard_page_data_cancel (page_data
);
728 content
= yelp_transform_take_chunk (transform
, chunk_id
);
729 yelp_document_give_contents (YELP_DOCUMENT (page_data
->mallard
),
732 "application/xhtml+xml");
734 yelp_document_signal (YELP_DOCUMENT (page_data
->mallard
),
736 YELP_DOCUMENT_SIGNAL_CONTENTS
,
741 transform_finished (YelpTransform
*transform
,
742 MallardPageData
*page_data
)
744 YelpMallardDocumentPrivate
*priv
;
746 g_assert (page_data
!= NULL
&& page_data
->mallard
!= NULL
&&
747 YELP_IS_MALLARD_DOCUMENT (page_data
->mallard
));
748 g_assert (transform
== page_data
->transform
);
750 priv
= GET_PRIV (page_data
->mallard
);
752 if (priv
->state
== MALLARD_STATE_STOP
) {
753 mallard_page_data_cancel (page_data
);
757 mallard_page_data_cancel (page_data
);
759 if (page_data
->xmldoc
)
760 xmlFreeDoc (page_data
->xmldoc
);
761 page_data
->xmldoc
= NULL
;
765 transform_error (YelpTransform
*transform
,
766 MallardPageData
*page_data
)
768 YelpMallardDocumentPrivate
*priv
;
771 g_assert (page_data
!= NULL
&& page_data
->mallard
!= NULL
&&
772 YELP_IS_MALLARD_DOCUMENT (page_data
->mallard
));
773 g_assert (transform
== page_data
->transform
);
775 priv
= GET_PRIV (page_data
->mallard
);
777 if (priv
->state
== MALLARD_STATE_STOP
) {
778 mallard_page_data_cancel (page_data
);
782 error
= yelp_transform_get_error (transform
);
783 yelp_document_error_pending ((YelpDocument
*) (page_data
->mallard
), error
);
784 g_error_free (error
);
786 mallard_page_data_cancel (page_data
);
790 xml_node_is_ns_name (xmlNodePtr node
,
794 if (node
->ns
== NULL
)
796 else if (ns
!= NULL
&& node
->ns
->href
!= NULL
)
797 return (xmlStrEqual (ns
, node
->ns
->href
) && xmlStrEqual (name
, node
->name
));