summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun McCance <shaunm@src.gnome.org>2004-12-11 21:45:05 +0000
committerShaun McCance <shaunm@src.gnome.org>2004-12-11 21:45:05 +0000
commit2af99169da89e7c83f5874bdfabc186df622dfec (patch)
tree77c4cd6f80ebbeef70ed5948e1c3981a899d144d
parent268641630d06a370c1e5d29496975a9aec7dc06f (diff)
downloadyelp-2af99169da89e7c83f5874bdfabc186df622dfec.tar.gz
- Added yelp-xslt-pager.[ch] to abstract out common pager stuff
* src/Makefile.am: * src/yelp-db-pager.c: * src/yelp-db-pager.h: * src/yelp-window.c: * src/yelp-xslt-pager.c: * src/yelp-xslt-pager.h: - Added yelp-xslt-pager.[ch] to abstract out common pager stuff
-rw-r--r--ChangeLog10
-rw-r--r--src/Makefile.am8
-rw-r--r--src/yelp-db-pager.c409
-rw-r--r--src/yelp-db-pager.h5
-rw-r--r--src/yelp-window.c14
-rw-r--r--src/yelp-xslt-pager.c454
-rw-r--r--src/yelp-xslt-pager.h59
7 files changed, 635 insertions, 324 deletions
diff --git a/ChangeLog b/ChangeLog
index 483fe474..a27bacfb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2004-12-11 Shaun McCance <shaunm@gnome.org>
+
+ * src/Makefile.am:
+ * src/yelp-db-pager.c:
+ * src/yelp-db-pager.h:
+ * src/yelp-window.c:
+ * src/yelp-xslt-pager.c:
+ * src/yelp-xslt-pager.h:
+ - Added yelp-xslt-pager.[ch] to abstract out common pager stuff
+
2004-12-09 Shaun McCance <shaunm@gnome.org>
* src/yelp-base.c:
diff --git a/src/Makefile.am b/src/Makefile.am
index 4f50c2ab..d2fb89bb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
# for debugging
-#YELP_CFLAGS += -DYELP_DEBUG -pedantic -ansi -Werror
+# YELP_CFLAGS += -DYELP_DEBUG -pedantic -ansi -Werror
if ENABLE_MAN
man_sources = yelp-man-parser.c yelp-man-parser.h yelp-man-pager.c yelp-man-pager.h
@@ -57,6 +57,7 @@ test_pager_SOURCES = \
yelp-pager.c yelp-pager.h \
yelp-toc-pager.c yelp-toc-pager.h \
yelp-utils.c yelp-utils.h \
+ yelp-xslt-pager.c yelp-xslt-pager.h \
yelp-marshal-main.c test-pager.c
test_pager_LDADD = @YELP_LIBS@ $(POPT_LIBS) $(Z_LIBS) $(BZ_LIBS)
@@ -74,15 +75,16 @@ yelp_SOURCES = \
yelp-cache.c yelp-cache.h \
yelp-db-pager.c yelp-db-pager.h \
yelp-error.c yelp-error.h \
- yelp-html-gecko.c yelp-html.h \
yelp-gecko-utils.cpp yelp-gecko-utils.h \
+ yelp-html-gecko.c yelp-html.h \
yelp-io-channel.c yelp-io-channel.h \
yelp-pager.c yelp-pager.h \
yelp-settings.c yelp-settings.h \
yelp-toc-pager.c yelp-toc-pager.h \
- yelp-window.c yelp-window.h \
yelp-uri.c yelp-uri.h \
yelp-utils.c yelp-utils.h \
+ yelp-window.c yelp-window.h \
+ yelp-xslt-pager.c yelp-xslt-pager.h \
yelp-marshal-main.c yelp-main.c
yelp_LDADD = @YELP_LIBS@ $(POPT_LIBS) $(Z_LIBS) $(BZ_LIBS) $(MOZILLA_COMPONENT_LIBS)
diff --git a/src/yelp-db-pager.c b/src/yelp-db-pager.c
index a546595b..53da99ab 100644
--- a/src/yelp-db-pager.c
+++ b/src/yelp-db-pager.c
@@ -47,8 +47,6 @@
#define d(x)
#endif
-#define YELP_NAMESPACE "http://www.gnome.org/yelp/ns"
-
#define DB_STYLESHEET_PATH DATADIR"/sgml/docbook/yelp/"
#define DB_STYLESHEET DB_STYLESHEET_PATH"db2html.xsl"
@@ -62,16 +60,9 @@ extern gboolean main_running;
struct _YelpDBPagerPriv {
GtkTreeModel *sects;
-
GHashTable *frags_hash;
gchar *root_id;
-
- xmlDocPtr inputDoc;
- xmlDocPtr outputDoc;
- xmlParserCtxtPtr parserCtxt;
- xsltStylesheetPtr stylesheet;
- xsltTransformContextPtr transformContext;
};
typedef struct _DBWalker DBWalker;
@@ -92,11 +83,10 @@ static void db_pager_class_init (YelpDBPagerClass *klass);
static void db_pager_init (YelpDBPager *pager);
static void db_pager_dispose (GObject *gobject);
-static void db_pager_error (YelpPager *pager);
static void db_pager_cancel (YelpPager *pager);
-static void db_pager_finish (YelpPager *pager);
+static xmlDocPtr db_pager_parse (YelpPager *pager);
+static gchar ** db_pager_params (YelpPager *pager);
-gboolean db_pager_process (YelpPager *pager);
const gchar * db_pager_resolve_frag (YelpPager *pager,
const gchar *frag_id);
GtkTreeModel * db_pager_get_sections (YelpPager *pager);
@@ -108,15 +98,6 @@ static gboolean xml_is_division (xmlNodePtr node);
static gboolean xml_is_info (xmlNodePtr node);
static gchar * xml_get_title (xmlNodePtr node);
-static void xslt_yelp_document (xsltTransformContextPtr ctxt,
- xmlNodePtr node,
- xmlNodePtr inst,
- xsltStylePreCompPtr comp);
-static void xslt_yelp_cache (xsltTransformContextPtr ctxt,
- xmlNodePtr node,
- xmlNodePtr inst,
- xsltStylePreCompPtr comp);
-
static YelpPagerClass *parent_class;
GType
@@ -136,7 +117,7 @@ yelp_db_pager_get_type (void)
0,
(GInstanceInitFunc) db_pager_init,
};
- type = g_type_register_static (YELP_TYPE_PAGER,
+ type = g_type_register_static (YELP_TYPE_XSLT_PAGER,
"YelpDBPager",
&info, 0);
}
@@ -148,18 +129,21 @@ db_pager_class_init (YelpDBPagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
YelpPagerClass *pager_class = YELP_PAGER_CLASS (klass);
+ YelpXsltPagerClass *xslt_class = YELP_XSLT_PAGER_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
object_class->dispose = db_pager_dispose;
- pager_class->error = db_pager_error;
- pager_class->cancel = db_pager_cancel;
- pager_class->finish = db_pager_finish;
+ pager_class->cancel = db_pager_cancel;
- pager_class->process = db_pager_process;
pager_class->resolve_frag = db_pager_resolve_frag;
pager_class->get_sections = db_pager_get_sections;
+
+ xslt_class->parse = db_pager_parse;
+ xslt_class->params = db_pager_params;
+
+ xslt_class->stylesheet = DB_STYLESHEET;
}
static void
@@ -212,65 +196,56 @@ yelp_db_pager_new (YelpDocInfo *doc_info)
return (YelpPager *) pager;
}
-gboolean
-db_pager_process (YelpPager *pager)
+static xmlDocPtr
+db_pager_parse (YelpPager *pager)
{
YelpDBPagerPriv *priv;
YelpDocInfo *doc_info;
gchar *filename;
- gint params_i = 0;
- gint i;
+
+ xmlParserCtxtPtr parserCtxt;
+ xmlDocPtr doc;
DBWalker *walker;
xmlChar *id;
GError *error = NULL;
- GtkIconInfo *icon_info;
- gchar *icon_file;
- gchar *icons[YELP_NUM_ICONS];
-
- const gchar *params[40];
-
- d (g_print ("db_pager_process\n"));
+ d (g_print ("db_pager_parse\n"));
doc_info = yelp_pager_get_doc_info (pager);
- g_return_val_if_fail (pager != NULL, FALSE);
- g_return_val_if_fail (YELP_IS_DB_PAGER (pager), FALSE);
+ g_return_val_if_fail (pager != NULL, NULL);
+ g_return_val_if_fail (YELP_IS_DB_PAGER (pager), NULL);
priv = YELP_DB_PAGER (pager)->priv;
+ g_object_ref (pager);
+
if (yelp_pager_get_state (pager) >= YELP_PAGER_STATE_ERROR)
goto done;
filename = yelp_doc_info_get_filename (doc_info);
- g_object_ref (pager);
- yelp_toc_pager_pause (yelp_toc_pager_get ());
-
- yelp_pager_set_state (pager, YELP_PAGER_STATE_PARSING);
- g_signal_emit_by_name (pager, "parse");
-
- priv->parserCtxt = xmlNewParserCtxt ();
- priv->inputDoc = xmlCtxtReadFile (priv->parserCtxt,
- (const char *) filename, NULL,
- XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
- XML_PARSE_NOENT | XML_PARSE_NONET );
- if (priv->inputDoc == NULL) {
+ parserCtxt = xmlNewParserCtxt ();
+ doc = xmlCtxtReadFile (parserCtxt,
+ (const char *) filename, NULL,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET );
+ if (doc == NULL) {
yelp_set_error (&error, YELP_ERROR_NO_DOC);
yelp_pager_error (pager, error);
goto done;
}
- xmlXIncludeProcessFlags (priv->inputDoc,
+ xmlXIncludeProcessFlags (doc,
XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
XML_PARSE_NOENT | XML_PARSE_NONET );
walker = g_new0 (DBWalker, 1);
walker->pager = YELP_DB_PAGER (pager);
- walker->doc = priv->inputDoc;
+ walker->doc = doc;
walker->cur = xmlDocGetRootElement (walker->doc);
- if (!xmlStrcmp (xmlDocGetRootElement (priv->inputDoc)->name, BAD_CAST "book"))
+ if (!xmlStrcmp (xmlDocGetRootElement (doc)->name, BAD_CAST "book"))
walker->max_depth = BOOK_CHUNK_DEPTH;
else
walker->max_depth = ARTICLE_CHUNK_DEPTH;
@@ -286,28 +261,54 @@ db_pager_process (YelpPager *pager)
walker_walk_xml (walker);
- CANCEL_CHECK;
+ done:
+ g_free (filename);
+ g_free (walker);
- yelp_pager_set_state (pager, YELP_PAGER_STATE_RUNNING);
- g_signal_emit_by_name (pager, "start");
+ if (parserCtxt)
+ xmlFreeParserCtxt (parserCtxt);
- EVENTS_PENDING;
- CANCEL_CHECK;
+ g_object_unref (pager);
- for (i = 0; i < YELP_NUM_ICONS; i++) {
- icon_info = yelp_settings_get_icon (i);
- if (icon_info) {
- icon_file = (gchar *) gtk_icon_info_get_filename (icon_info);
- if (icon_file)
- icons[i] = g_strdup_printf ("\"%s\"", icon_file);
- else
- icons[i] = g_strdup ("\"\"");
- gtk_icon_info_free (icon_info);
- } else {
- icons[i] = g_strdup ("\"\"");
+ return doc;
+}
+
+static gchar **
+db_pager_params (YelpPager *pager)
+{
+ YelpDBPagerPriv *priv;
+ YelpDocInfo *doc_info;
+ gchar *filename;
+ gchar **params;
+ gint params_i = 0;
+ gint params_max = 20;
+
+ GtkIconInfo *icon_info;
+ gchar *icon_file;
+ gint icons_i;
+
+ d (g_print ("db_pager_process\n"));
+
+ doc_info = yelp_pager_get_doc_info (pager);
+
+ g_return_val_if_fail (pager != NULL, FALSE);
+ g_return_val_if_fail (YELP_IS_DB_PAGER (pager), FALSE);
+ priv = YELP_DB_PAGER (pager)->priv;
+
+ if (yelp_pager_get_state (pager) >= YELP_PAGER_STATE_ERROR)
+ return NULL;
+
+ filename = yelp_doc_info_get_filename (doc_info);
+
+ params = g_new0 (gchar *, params_max);
+
+ for (icons_i = 0; icons_i < YELP_NUM_ICONS; icons_i++) {
+ if ((params_i + 1) >= params_max - 1) {
+ params_max += 20;
+ params = g_renew (gchar *, params, params_max);
}
- switch (i) {
+ switch (icons_i) {
case YELP_ICON_BLOCKQUOTE:
params[params_i++] = "yelp.image.blockquote";
break;
@@ -332,9 +333,24 @@ db_pager_process (YelpPager *pager)
default:
g_assert_not_reached ();
}
- params[params_i++] = icons[i];
+
+ icon_info = yelp_settings_get_icon (icons_i);
+ if (icon_info) {
+ icon_file = (gchar *) gtk_icon_info_get_filename (icon_info);
+ if (icon_file)
+ params[params_i++] = g_strdup_printf ("\"%s\"", icon_file);
+ else
+ params[params_i++] = g_strdup ("\"\"");
+ gtk_icon_info_free (icon_info);
+ } else {
+ params[params_i++] = g_strdup ("\"\"");
+ }
}
+ if ((params_i + 10) >= params_max - 1) {
+ params_max += 20;
+ params = g_renew (gchar *, params, params_max);
+ }
params[params_i++] = "stylesheet_path";
params[params_i++] = g_strdup_printf ("\"file://%s\"", DB_STYLESHEET_PATH);
params[params_i++] = "html_extension";
@@ -345,81 +361,7 @@ db_pager_process (YelpPager *pager)
params[params_i++] = g_strdup_printf ("\"file://%s\"", DATADIR "/yelp/icons/");
params[params_i++] = NULL;
- priv->stylesheet = xsltParseStylesheetFile (DB_STYLESHEET);
- if (!priv->stylesheet) {
- yelp_set_error (&error, YELP_ERROR_PROC);
- yelp_pager_error (pager, error);
- goto done;
- }
-
- priv->transformContext = xsltNewTransformContext (priv->stylesheet,
- priv->inputDoc);
- if (!priv->transformContext) {
- yelp_set_error (&error, YELP_ERROR_PROC);
- yelp_pager_error (pager, error);
- goto done;
- }
-
- priv->transformContext->_private = pager;
- xsltRegisterExtElement (priv->transformContext,
- "document",
- YELP_NAMESPACE,
- (xsltTransformFunction) xslt_yelp_document);
- xsltRegisterExtElement (priv->transformContext,
- "cache",
- YELP_NAMESPACE,
- (xsltTransformFunction) xslt_yelp_cache);
-
- EVENTS_PENDING;
- CANCEL_CHECK;
-
- priv->outputDoc = xsltApplyStylesheetUser (priv->stylesheet,
- priv->inputDoc,
- params, NULL, NULL,
- priv->transformContext);
- CANCEL_CHECK;
- g_signal_emit_by_name (pager, "finish");
-
- done:
- for (params_i = 0; params[params_i] != NULL; params_i++)
- if (params_i % 2 == 1)
- g_free (params[params_i]);
- g_free (filename);
- g_free (walker);
-
- if (priv->inputDoc) {
- xmlFreeDoc (priv->inputDoc);
- priv->inputDoc = NULL;
- }
- if (priv->outputDoc) {
- xmlFreeDoc (priv->outputDoc);
- priv->outputDoc = NULL;
- }
- if (priv->parserCtxt) {
- xmlFreeParserCtxt (priv->parserCtxt);
- priv->parserCtxt = NULL;
- }
- if (priv->stylesheet) {
- xsltFreeStylesheet (priv->stylesheet);
- priv->stylesheet = NULL;
- }
- if (priv->transformContext) {
- xsltFreeTransformContext (priv->transformContext);
- priv->transformContext = NULL;
- }
-
- g_object_unref (pager);
-
- return FALSE;
-}
-
-static void
-db_pager_error (YelpPager *pager)
-{
- d (g_print ("db_pager_error\n"));
- yelp_pager_set_state (pager, YELP_PAGER_STATE_ERROR);
- if (yelp_pager_get_state (pager) <= YELP_PAGER_STATE_RUNNING)
- yelp_toc_pager_unpause (yelp_toc_pager_get ());
+ return params;
}
static void
@@ -430,8 +372,6 @@ db_pager_cancel (YelpPager *pager)
d (g_print ("db_pager_cancel\n"));
yelp_pager_set_state (pager, YELP_PAGER_STATE_INVALID);
- if (yelp_pager_get_state (pager) <= YELP_PAGER_STATE_RUNNING)
- yelp_toc_pager_unpause (yelp_toc_pager_get ());
gtk_tree_store_clear (GTK_TREE_STORE (priv->sects));
g_hash_table_foreach_remove (priv->frags_hash, gtk_true, NULL);
@@ -439,35 +379,7 @@ db_pager_cancel (YelpPager *pager)
g_free (priv->root_id);
priv->root_id = NULL;
- if (priv->inputDoc) {
- xmlFreeDoc (priv->inputDoc);
- priv->inputDoc = NULL;
- }
- if (priv->outputDoc) {
- xmlFreeDoc (priv->outputDoc);
- priv->outputDoc = NULL;
- }
- if (priv->parserCtxt) {
- xmlFreeParserCtxt (priv->parserCtxt);
- priv->parserCtxt = NULL;
- }
- if (priv->stylesheet) {
- xsltFreeStylesheet (priv->stylesheet);
- priv->stylesheet = NULL;
- }
- if (priv->transformContext) {
- xsltFreeTransformContext (priv->transformContext);
- priv->transformContext = NULL;
- }
-}
-
-static void
-db_pager_finish (YelpPager *pager)
-{
- d (g_print ("db_pager_finish\n"));
- yelp_pager_set_state (pager, YELP_PAGER_STATE_FINISHED);
- if (yelp_pager_get_state (pager) <= YELP_PAGER_STATE_RUNNING)
- yelp_toc_pager_unpause (yelp_toc_pager_get ());
+ YELP_PAGER_CLASS (parent_class)->cancel (pager);
}
const gchar *
@@ -499,146 +411,7 @@ db_pager_get_sections (YelpPager *pager)
return YELP_DB_PAGER (pager)->priv->sects;
}
-void
-xslt_yelp_document (xsltTransformContextPtr ctxt,
- xmlNodePtr node,
- xmlNodePtr inst,
- xsltStylePreCompPtr comp)
-{
- GError *error;
- YelpPage *page;
- xmlChar *page_id = NULL;
- xmlChar *page_title = NULL;
- xmlChar *page_buf;
- gint buf_size;
- YelpPager *pager;
- xsltStylesheetPtr style = NULL;
- const char *old_outfile;
- xmlDocPtr new_doc = NULL;
- xmlDocPtr old_doc;
- xmlNodePtr old_insert;
- xmlNodePtr cur;
-
- if (!ctxt || !node || !inst || !comp)
- return;
-
- pager = (YelpPager *) ctxt->_private;
-
- EVENTS_PENDING;
- CANCEL_CHECK;
-
- d (g_print ("xslt_yelp_document\n"));
-
- page_id = xsltEvalAttrValueTemplate (ctxt, inst,
- (const xmlChar *) "href",
- NULL);
- if (page_id == NULL) {
- xsltTransformError (ctxt, NULL, inst,
- _("No href attribute found on yelp:document"));
- error = NULL;
- yelp_pager_error (pager, error);
- goto done;
- }
- d (g_print (" page_id = \"%s\"\n", page_id));
-
- old_outfile = ctxt->outputFile;
- old_doc = ctxt->output;
- old_insert = ctxt->insert;
- ctxt->outputFile = (const char *) page_id;
-
- style = xsltNewStylesheet ();
- if (style == NULL) {
- xsltTransformError (ctxt, NULL, inst,
- _("Out of memory"));
- error = NULL;
- yelp_pager_error (pager, error);
- goto done;
- }
-
- style->omitXmlDeclaration = TRUE;
-
- new_doc = xmlNewDoc ("1.0");
- new_doc->charset = XML_CHAR_ENCODING_UTF8;
- new_doc->dict = ctxt->dict;
- xmlDictReference (new_doc->dict);
-
- ctxt->output = new_doc;
- ctxt->insert = (xmlNodePtr) new_doc;
-
- xsltApplyOneTemplate (ctxt, node, inst->children, NULL, NULL);
-
- CANCEL_CHECK;
-
- xsltSaveResultToString (&page_buf, &buf_size, new_doc, style);
-
- ctxt->outputFile = old_outfile;
- ctxt->output = old_doc;
- ctxt->insert = old_insert;
-
- page_title = xml_get_title (node);
-
- CANCEL_CHECK;
-
- if (!page_title)
- page_title = g_strdup ("FIXME");
-
- page = g_new0 (YelpPage, 1);
-
- page->page_id = g_strdup (page_id);
- xmlFree (page_id);
- page_id = NULL;
-
- page->title = page_title;
- page->contents = page_buf;
-
- cur = xmlDocGetRootElement (new_doc);
- for (cur = cur->children; cur; cur = cur->next) {
- if (!xmlStrcmp (cur->name, (xmlChar *) "head")) {
- for (cur = cur->children; cur; cur = cur->next) {
- if (!xmlStrcmp (cur->name, (xmlChar *) "link")) {
- xmlChar *rel = xmlGetProp (cur, "rel");
-
- if (!xmlStrcmp (rel, (xmlChar *) "Previous"))
- page->prev_id = g_strdup (xmlGetProp (cur, "href"));
- else if (!xmlStrcmp (rel, (xmlChar *) "Next"))
- page->next_id = g_strdup (xmlGetProp (cur, "href"));
- else if (!xmlStrcmp (rel, (xmlChar *) "Top"))
- page->toc_id = g_strdup (xmlGetProp (cur, "href"));
-
- xmlFree (rel);
- }
- }
- break;
- }
- }
-
- CANCEL_CHECK;
-
- yelp_pager_add_page (pager, page);
- g_signal_emit_by_name (pager, "page", page->page_id);
-
- EVENTS_PENDING;
- CANCEL_CHECK;
-
- done:
- if (new_doc)
- xmlFreeDoc (new_doc);
- if (style)
- xsltFreeStylesheet (style);
-}
-
-void
-xslt_yelp_cache (xsltTransformContextPtr ctxt,
- xmlNodePtr node,
- xmlNodePtr inst,
- xsltStylePreCompPtr comp)
-{
- xsltApplyOneTemplate (ctxt, node, inst->children, NULL, NULL);
-
- while (gtk_events_pending ())
- gtk_main_iteration ();
- // FIXME : check for cancel
-}
+/******************************************************************************/
static void
walker_walk_xml (DBWalker *walker)
diff --git a/src/yelp-db-pager.h b/src/yelp-db-pager.h
index 899b7ac7..40381278 100644
--- a/src/yelp-db-pager.h
+++ b/src/yelp-db-pager.h
@@ -26,6 +26,7 @@
#include <glib-object.h>
#include "yelp-pager.h"
+#include "yelp-xslt-pager.h"
#define YELP_TYPE_DB_PAGER (yelp_db_pager_get_type ())
#define YELP_DB_PAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_DB_PAGER, YelpDBPager))
@@ -39,13 +40,13 @@ typedef struct _YelpDBPagerClass YelpDBPagerClass;
typedef struct _YelpDBPagerPriv YelpDBPagerPriv;
struct _YelpDBPager {
- YelpPager parent;
+ YelpXsltPager parent;
YelpDBPagerPriv *priv;
};
struct _YelpDBPagerClass {
- YelpPagerClass parent_class;
+ YelpXsltPagerClass parent_class;
};
GType yelp_db_pager_get_type (void);
diff --git a/src/yelp-window.c b/src/yelp-window.c
index e36fba6f..da5a6b6a 100644
--- a/src/yelp-window.c
+++ b/src/yelp-window.c
@@ -257,6 +257,8 @@ struct _YelpWindowPriv {
gulong finish_handler;
guint idle_write;
+ gint toc_pause;
+
GtkActionGroup *action_group;
GtkUIManager *ui_manager;
@@ -1138,8 +1140,13 @@ window_do_load_pager (YelpWindow *window,
G_CALLBACK (pager_finish_cb),
window);
- if (startnow)
+ if (startnow) {
handled = yelp_pager_start (pager);
+ if (handled) {
+ yelp_toc_pager_pause (yelp_toc_pager_get ());
+ priv->toc_pause++;
+ }
+ }
// FIXME: error if !handled
}
@@ -1389,6 +1396,11 @@ window_disconnect (YelpWindow *window)
if (GTK_WIDGET (window)->window)
gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL);
+ if (window->priv->toc_pause > 0) {
+ window->priv->toc_pause--;
+ yelp_toc_pager_unpause (yelp_toc_pager_get ());
+ }
+
if (window->priv->current_doc) {
if (priv->start_handler) {
g_signal_handler_disconnect (pager,
diff --git a/src/yelp-xslt-pager.c b/src/yelp-xslt-pager.c
new file mode 100644
index 00000000..7d448652
--- /dev/null
+++ b/src/yelp-xslt-pager.c
@@ -0,0 +1,454 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003 Shaun McCance <shaunm@gnome.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <libgnome/gnome-i18n.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xinclude.h>
+#include <libxslt/xslt.h>
+#include <libxslt/templates.h>
+#include <libxslt/transform.h>
+#include <libxslt/extensions.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/xsltutils.h>
+
+#include "yelp-error.h"
+#include "yelp-settings.h"
+#include "yelp-xslt-pager.h"
+
+#ifdef YELP_DEBUG
+#define d(x) x
+#else
+#define d(x)
+#endif
+
+#define YELP_NAMESPACE "http://www.gnome.org/yelp/ns"
+
+#define EVENTS_PENDING while (yelp_pager_get_state (pager) <= YELP_PAGER_STATE_RUNNING && gtk_events_pending ()) gtk_main_iteration ();
+#define CANCEL_CHECK if (!main_running || yelp_pager_get_state (pager) >= YELP_PAGER_STATE_ERROR) goto done;
+
+extern gboolean main_running;
+
+struct _YelpXsltPagerPriv {
+ xmlDocPtr inputDoc;
+ xmlDocPtr outputDoc;
+ xsltStylesheetPtr stylesheet;
+ xsltTransformContextPtr transformContext;
+};
+
+static void xslt_pager_class_init (YelpXsltPagerClass *klass);
+static void xslt_pager_init (YelpXsltPager *pager);
+static void xslt_pager_dispose (GObject *gobject);
+
+static void xslt_pager_error (YelpPager *pager);
+static void xslt_pager_cancel (YelpPager *pager);
+static void xslt_pager_finish (YelpPager *pager);
+
+gboolean xslt_pager_process (YelpPager *pager);
+
+static void xslt_yelp_document (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp);
+static void xslt_yelp_cache (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp);
+
+static YelpPagerClass *parent_class;
+
+GType
+yelp_xslt_pager_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpXsltPagerClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) xslt_pager_class_init,
+ NULL,
+ NULL,
+ sizeof (YelpXsltPager),
+ 0,
+ (GInstanceInitFunc) xslt_pager_init,
+ };
+ type = g_type_register_static (YELP_TYPE_PAGER,
+ "YelpXsltPager",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+xslt_pager_class_init (YelpXsltPagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpPagerClass *pager_class = YELP_PAGER_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = xslt_pager_dispose;
+
+ pager_class->error = xslt_pager_error;
+ pager_class->cancel = xslt_pager_cancel;
+ pager_class->finish = xslt_pager_finish;
+
+ pager_class->process = xslt_pager_process;
+}
+
+static void
+xslt_pager_init (YelpXsltPager *pager)
+{
+ YelpXsltPagerPriv *priv;
+
+ priv = g_new0 (YelpXsltPagerPriv, 1);
+ pager->priv = priv;
+}
+
+static void
+xslt_pager_dispose (GObject *object)
+{
+ YelpXsltPager *pager = YELP_XSLT_PAGER (object);
+ YelpXsltPagerPriv *priv = pager->priv;
+
+ if (priv->inputDoc)
+ xmlFreeDoc (priv->inputDoc);
+ if (priv->outputDoc)
+ xmlFreeDoc (priv->outputDoc);
+ if (priv->stylesheet)
+ xsltFreeStylesheet (priv->stylesheet);
+ if (priv->transformContext)
+ xsltFreeTransformContext (priv->transformContext);
+
+ g_free (pager->priv);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+gboolean
+xslt_pager_process (YelpPager *pager)
+{
+ YelpXsltPagerPriv *priv;
+ YelpXsltPagerClass *klass;
+
+ YelpDocInfo *doc_info;
+ gchar *filename;
+
+ gchar **params;
+ gint params_i = 0;
+
+ GError *error = NULL;
+
+ d (g_print ("xslt_pager_process\n"));
+
+ g_return_val_if_fail (pager != NULL, FALSE);
+ g_return_val_if_fail (YELP_IS_XSLT_PAGER (pager), FALSE);
+
+ priv = YELP_XSLT_PAGER (pager)->priv;
+ klass = YELP_XSLT_PAGER_GET_CLASS (pager);
+
+ doc_info = yelp_pager_get_doc_info (pager);
+
+ if (yelp_pager_get_state (pager) >= YELP_PAGER_STATE_ERROR)
+ goto done;
+
+ filename = yelp_doc_info_get_filename (doc_info);
+
+ g_object_ref (pager);
+
+ yelp_pager_set_state (pager, YELP_PAGER_STATE_PARSING);
+ g_signal_emit_by_name (pager, "parse");
+
+ priv->inputDoc = klass->parse (pager);
+
+ if (priv->inputDoc == NULL) {
+ yelp_set_error (&error, YELP_ERROR_NO_DOC);
+ yelp_pager_error (pager, error);
+ goto done;
+ }
+
+ EVENTS_PENDING;
+ CANCEL_CHECK;
+
+ yelp_pager_set_state (pager, YELP_PAGER_STATE_RUNNING);
+ g_signal_emit_by_name (pager, "start");
+
+ EVENTS_PENDING;
+ CANCEL_CHECK;
+
+ params = klass->params (pager);
+
+ priv->stylesheet = xsltParseStylesheetFile (klass->stylesheet);
+ if (!priv->stylesheet) {
+ yelp_set_error (&error, YELP_ERROR_PROC);
+ yelp_pager_error (pager, error);
+ goto done;
+ }
+
+ priv->transformContext = xsltNewTransformContext (priv->stylesheet,
+ priv->inputDoc);
+ if (!priv->transformContext) {
+ yelp_set_error (&error, YELP_ERROR_PROC);
+ yelp_pager_error (pager, error);
+ goto done;
+ }
+
+ priv->transformContext->_private = pager;
+ xsltRegisterExtElement (priv->transformContext,
+ "document",
+ YELP_NAMESPACE,
+ (xsltTransformFunction) xslt_yelp_document);
+ xsltRegisterExtElement (priv->transformContext,
+ "cache",
+ YELP_NAMESPACE,
+ (xsltTransformFunction) xslt_yelp_cache);
+
+ EVENTS_PENDING;
+ CANCEL_CHECK;
+
+ priv->outputDoc = xsltApplyStylesheetUser (priv->stylesheet,
+ priv->inputDoc,
+ (const char **) params,
+ NULL, NULL,
+ priv->transformContext);
+ CANCEL_CHECK;
+ g_signal_emit_by_name (pager, "finish");
+
+ done:
+ for (params_i = 0; params[params_i] != NULL; params_i++)
+ if (params_i % 2 == 1)
+ g_free (params[params_i]);
+ g_free (params);
+ g_free (filename);
+
+ if (priv->inputDoc) {
+ xmlFreeDoc (priv->inputDoc);
+ priv->inputDoc = NULL;
+ }
+ if (priv->outputDoc) {
+ xmlFreeDoc (priv->outputDoc);
+ priv->outputDoc = NULL;
+ }
+ if (priv->stylesheet) {
+ xsltFreeStylesheet (priv->stylesheet);
+ priv->stylesheet = NULL;
+ }
+ if (priv->transformContext) {
+ xsltFreeTransformContext (priv->transformContext);
+ priv->transformContext = NULL;
+ }
+
+ g_object_unref (pager);
+
+ return FALSE;
+}
+
+static void
+xslt_pager_error (YelpPager *pager)
+{
+ d (g_print ("xslt_pager_error\n"));
+ yelp_pager_set_state (pager, YELP_PAGER_STATE_ERROR);
+}
+
+static void
+xslt_pager_cancel (YelpPager *pager)
+{
+ YelpXsltPagerPriv *priv = YELP_XSLT_PAGER (pager)->priv;
+
+ d (g_print ("xslt_pager_cancel\n"));
+
+ yelp_pager_set_state (pager, YELP_PAGER_STATE_INVALID);
+
+ if (priv->inputDoc) {
+ xmlFreeDoc (priv->inputDoc);
+ priv->inputDoc = NULL;
+ }
+ if (priv->outputDoc) {
+ xmlFreeDoc (priv->outputDoc);
+ priv->outputDoc = NULL;
+ }
+ if (priv->stylesheet) {
+ xsltFreeStylesheet (priv->stylesheet);
+ priv->stylesheet = NULL;
+ }
+ if (priv->transformContext) {
+ xsltFreeTransformContext (priv->transformContext);
+ priv->transformContext = NULL;
+ }
+}
+
+static void
+xslt_pager_finish (YelpPager *pager)
+{
+ d (g_print ("xslt_pager_finish\n"));
+ yelp_pager_set_state (pager, YELP_PAGER_STATE_FINISHED);
+}
+
+/** XSLT Extension Elements ***************************************************/
+
+void
+xslt_yelp_document (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp)
+{
+ GError *error;
+ YelpPage *page;
+ xmlChar *page_id = NULL;
+ xmlChar *page_title = NULL;
+ xmlChar *page_buf;
+ gint buf_size;
+ YelpPager *pager;
+ xsltStylesheetPtr style = NULL;
+ const char *old_outfile;
+ xmlDocPtr new_doc = NULL;
+ xmlDocPtr old_doc;
+ xmlNodePtr old_insert;
+ xmlNodePtr cur;
+
+ if (!ctxt || !node || !inst || !comp)
+ return;
+
+ pager = (YelpPager *) ctxt->_private;
+
+ EVENTS_PENDING;
+ CANCEL_CHECK;
+
+ d (g_print ("xslt_yelp_document\n"));
+
+ page_id = xsltEvalAttrValueTemplate (ctxt, inst,
+ (const xmlChar *) "href",
+ NULL);
+ if (page_id == NULL) {
+ xsltTransformError (ctxt, NULL, inst,
+ _("No href attribute found on yelp:document"));
+ error = NULL;
+ yelp_pager_error (pager, error);
+ goto done;
+ }
+ d (g_print (" page_id = \"%s\"\n", page_id));
+
+ old_outfile = ctxt->outputFile;
+ old_doc = ctxt->output;
+ old_insert = ctxt->insert;
+ ctxt->outputFile = (const char *) page_id;
+
+ style = xsltNewStylesheet ();
+ if (style == NULL) {
+ xsltTransformError (ctxt, NULL, inst,
+ _("Out of memory"));
+ error = NULL;
+ yelp_pager_error (pager, error);
+ goto done;
+ }
+
+ style->omitXmlDeclaration = TRUE;
+
+ new_doc = xmlNewDoc ("1.0");
+ new_doc->charset = XML_CHAR_ENCODING_UTF8;
+ new_doc->dict = ctxt->dict;
+ xmlDictReference (new_doc->dict);
+
+ ctxt->output = new_doc;
+ ctxt->insert = (xmlNodePtr) new_doc;
+
+ xsltApplyOneTemplate (ctxt, node, inst->children, NULL, NULL);
+
+ CANCEL_CHECK;
+
+ xsltSaveResultToString (&page_buf, &buf_size, new_doc, style);
+
+ ctxt->outputFile = old_outfile;
+ ctxt->output = old_doc;
+ ctxt->insert = old_insert;
+
+ CANCEL_CHECK;
+
+ if (!page_title)
+ page_title = g_strdup ("FIXME");
+
+ page = g_new0 (YelpPage, 1);
+
+ page->page_id = g_strdup (page_id);
+ xmlFree (page_id);
+ page_id = NULL;
+
+ page->title = page_title;
+ page->contents = page_buf;
+
+ cur = xmlDocGetRootElement (new_doc);
+ for (cur = cur->children; cur; cur = cur->next) {
+ if (!xmlStrcmp (cur->name, (xmlChar *) "head")) {
+ for (cur = cur->children; cur; cur = cur->next) {
+ if (!xmlStrcmp (cur->name, (xmlChar *) "link")) {
+ xmlChar *rel = xmlGetProp (cur, "rel");
+
+ if (!xmlStrcmp (rel, (xmlChar *) "Previous"))
+ page->prev_id = g_strdup (xmlGetProp (cur, "href"));
+ else if (!xmlStrcmp (rel, (xmlChar *) "Next"))
+ page->next_id = g_strdup (xmlGetProp (cur, "href"));
+ else if (!xmlStrcmp (rel, (xmlChar *) "Top"))
+ page->toc_id = g_strdup (xmlGetProp (cur, "href"));
+
+ xmlFree (rel);
+ }
+ }
+ break;
+ }
+ }
+
+ CANCEL_CHECK;
+
+ yelp_pager_add_page (pager, page);
+ g_signal_emit_by_name (pager, "page", page->page_id);
+
+ EVENTS_PENDING;
+ CANCEL_CHECK;
+
+ done:
+ if (new_doc)
+ xmlFreeDoc (new_doc);
+ if (style)
+ xsltFreeStylesheet (style);
+}
+
+void
+xslt_yelp_cache (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp)
+{
+ xsltApplyOneTemplate (ctxt, node, inst->children, NULL, NULL);
+
+ while (gtk_events_pending ())
+ gtk_main_iteration ();
+ // FIXME : check for cancel
+}
diff --git a/src/yelp-xslt-pager.h b/src/yelp-xslt-pager.h
new file mode 100644
index 00000000..b46cced5
--- /dev/null
+++ b/src/yelp-xslt-pager.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003 Shaun McCance <shaunm@gnome.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifndef __YELP_XSLT_PAGER_H__
+#define __YELP_XSLT_PAGER_H__
+
+#include <glib-object.h>
+#include <libxml/parser.h>
+
+#include "yelp-pager.h"
+
+#define YELP_TYPE_XSLT_PAGER (yelp_xslt_pager_get_type ())
+#define YELP_XSLT_PAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_XSLT_PAGER, YelpXsltPager))
+#define YELP_XSLT_PAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_XSLT_PAGER, YelpXsltPagerClass))
+#define YELP_IS_XSLT_PAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_XSLT_PAGER))
+#define YELP_IS_XSLT_PAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_XSLT_PAGER))
+#define YELP_XSLT_PAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_XSLT_PAGER, YelpXsltPagerClass))
+
+typedef struct _YelpXsltPager YelpXsltPager;
+typedef struct _YelpXsltPagerClass YelpXsltPagerClass;
+typedef struct _YelpXsltPagerPriv YelpXsltPagerPriv;
+
+struct _YelpXsltPager {
+ YelpPager parent;
+
+ YelpXsltPagerPriv *priv;
+};
+
+struct _YelpXsltPagerClass {
+ YelpPagerClass parent_class;
+
+ xmlDocPtr (*parse) (YelpPager *pager);
+ gchar ** (*params) (YelpPager *pager);
+
+ gchar *stylesheet;
+};
+
+GType yelp_xslt_pager_get_type (void);
+
+#endif /* __YELP_XSLT_PAGER_H__ */