From 34d0c263d9a56bb2beb65385c0b03d013d1657e9 Mon Sep 17 00:00:00 2001 From: Don Scorgie Date: Mon, 30 Apr 2007 19:00:37 +0000 Subject: Add in man pages Do an interesting use of the new stuff to run 3 * src/yelp-toc.c: Add in man pages Do an interesting use of the new stuff to run 3 transforms - main, info and man so we quickly get the main page, then get man and info when ready Add myself to authors and copyright * src/yelp-document.h: * src/yelp-document.c: Add yelp_document_has_page that's used in yelp-toc svn path=/branches/yelp-spoon/; revision=2812 --- ChangeLog | 13 ++++ src/yelp-document.c | 9 +++ src/yelp-document.h | 2 + src/yelp-toc.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 224 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 06b4ff29..50396748 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-04-30 Don Scorgie + + * src/yelp-toc.c: + Add in man pages + Do an interesting use of the new stuff to + run 3 transforms - main, info and man so + we quickly get the main page, then get man and info when ready + + * src/yelp-document.h: + * src/yelp-document.c: + Add yelp_document_has_page that's used + in yelp-toc + 2007-04-26 Don Scorgie * src/yelp-toc.c: diff --git a/src/yelp-document.c b/src/yelp-document.c index bce10d05..21a6c041 100644 --- a/src/yelp-document.c +++ b/src/yelp-document.c @@ -460,6 +460,15 @@ yelp_document_add_page (YelpDocument *document, gchar *page_id, const gchar *con g_mutex_unlock (priv->mutex); } +gboolean +yelp_document_has_page (YelpDocument *document, gchar *page_id) +{ + gchar *content; + g_assert (document != NULL && YELP_IS_DOCUMENT (document)); + content = g_hash_table_lookup (document->priv->contents, page_id); + return !(content == NULL); +} + void yelp_document_error_request (YelpDocument *document, gint req_id, YelpError *error) { diff --git a/src/yelp-document.h b/src/yelp-document.h index c550c764..b0bbeb24 100644 --- a/src/yelp-document.h +++ b/src/yelp-document.h @@ -117,6 +117,8 @@ void yelp_document_add_title (YelpDocument *document, void yelp_document_add_page (YelpDocument *document, gchar *page_id, const gchar *contents); +gboolean yelp_document_has_page (YelpDocument *document, + gchar *page_id); void yelp_document_error_request (YelpDocument *document, gint req_id, YelpError *error); diff --git a/src/yelp-toc.c b/src/yelp-toc.c index 40d2f99d..8441502b 100644 --- a/src/yelp-toc.c +++ b/src/yelp-toc.c @@ -1,6 +1,7 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* * Copyright (C) 2003-2007 Shaun McCance + * 2007 Don Scorgie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,6 +19,7 @@ * Boston, MA 02111-1307, USA. * * Author: Shaun McCance + * Don Scorgie */ #ifdef HAVE_CONFIG_H @@ -36,6 +38,10 @@ #include #endif /* ENABLE_INFO */ +#ifdef ENABLE_MAN +#include +#endif /* ENABLE_MAN */ + #include "yelp-error.h" #include "yelp-toc.h" #include "yelp-settings.h" @@ -61,11 +67,17 @@ struct _YelpTocPriv { gboolean process_running; gboolean transform_running; + gboolean man_processed; + gboolean info_processed; YelpTransform *transform; + YelpTransform *info_transform; + YelpTransform *man_transform; xmlDocPtr xmldoc; xmlNodePtr xmlcur; + xmlNodePtr fake_info; + xmlNodePtr fake_man; gchar *cur_page_id; gchar *cur_prev_id; }; @@ -100,6 +112,9 @@ static void toc_process (YelpToc *toc); #ifdef ENABLE_INFO static void toc_process_info (YelpToc *toc); #endif /* ENABLE_INFO */ +#ifdef ENABLE_MAN +static void toc_process_man (YelpToc *toc); +#endif /*ENABLE_MAN */ static void xml_trim_titles (xmlNodePtr node, xmlChar * nodetype); @@ -150,6 +165,9 @@ toc_init (YelpToc *toc) priv->state = TOC_STATE_BLANK; + priv->man_processed = FALSE; + priv->info_processed = FALSE; + priv->mutex = g_mutex_new (); } @@ -270,7 +288,9 @@ transform_func (YelpTransform *transform, priv = toc->priv; - g_assert (transform == priv->transform); + g_assert (transform == priv->transform || + transform == priv->info_transform || + transform == priv->man_transform); if (priv->state == TOC_STATE_STOP) { switch (signal) { @@ -300,7 +320,8 @@ transform_func (YelpTransform *transform, priv->transform_running = FALSE; break; case YELP_TRANSFORM_FINAL: - transform_final_func (transform, toc); + if (priv->man_processed && priv->info_processed) + transform_final_func (transform, toc); break; } } @@ -325,8 +346,25 @@ transform_page_func (YelpTransform *transform, g_file_set_contents (filename, content, -1, NULL); #endif - yelp_document_add_page (YELP_DOCUMENT (toc), page_id, content); + /* We only want to add "Info" and "Man" if they're the + * "true" versions as otherwise they'll be empty + * and people will complain. + * This is a horrific abuse of the wonderful + * system used for generating the TOC + */ + + if ((transform != priv->man_transform && + g_str_equal (page_id, "Man")) || + (transform != priv->info_transform && + g_str_equal (page_id, "Info"))) { + goto done; + } + + if (!yelp_document_has_page (YELP_DOCUMENT (toc), page_id)) { + yelp_document_add_page (YELP_DOCUMENT (toc), page_id, content); + } + done: g_free (page_id); g_mutex_unlock (priv->mutex); @@ -339,15 +377,19 @@ transform_final_func (YelpTransform *transform, YelpToc *toc) YelpTocPriv *priv = toc->priv; debug_print (DB_FUNCTION, "entering\n"); - g_mutex_lock (priv->mutex); error = yelp_error_new (_("Page not found"), _("The requested page was not found in the TOC.")); yelp_document_error_pending (YELP_DOCUMENT (toc), error); - yelp_transform_release (transform); + yelp_transform_release (priv->transform); priv->transform = NULL; + yelp_transform_release (priv->info_transform); + priv->info_transform = NULL; + yelp_transform_release (priv->man_transform); + priv->man_transform = NULL; + priv->transform_running = FALSE; if (priv->xmldoc) @@ -381,11 +423,12 @@ static void toc_process (YelpToc *toc) { YelpTocPriv *priv; - xmlDocPtr xmldoc = NULL; YelpError *error = NULL; xmlParserCtxtPtr parserCtxt = NULL; YelpDocument *document; + GThread *info_thread; + GThread *man_thread; xmlTextReaderPtr reader; xmlXPathContextPtr xpath; xmlXPathObjectPtr obj; @@ -398,12 +441,12 @@ toc_process (YelpToc *toc) document = YELP_DOCUMENT (toc); parserCtxt = xmlNewParserCtxt (); - xmldoc = xmlCtxtReadFile (parserCtxt, + priv->xmldoc = xmlCtxtReadFile (parserCtxt, (const char *) DATADIR "/yelp/toc.xml", NULL, XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA | XML_PARSE_NOENT | XML_PARSE_NONET ); - if (xmldoc == NULL) { + if (priv->xmldoc == NULL) { error = yelp_error_new (_("Could not parse file"), _("The ‘âTOC file€™ " "could not be parsed because it is" @@ -412,7 +455,7 @@ toc_process (YelpToc *toc) goto done; } - xpath = xmlXPathNewContext (xmldoc); + xpath = xmlXPathNewContext (priv->xmldoc); obj = xmlXPathEvalExpression (BAD_CAST "//toc", xpath); for (i = 0; i < obj->nodesetval->nodeNr; i++) { @@ -498,12 +541,43 @@ toc_process (YelpToc *toc) xmlFreeTextReader (reader); xmlXPathFreeContext (xpath); - g_mutex_lock (priv->mutex); + /* g_mutex_lock (priv->mutex); priv->xmldoc = xmldoc; g_mutex_unlock (priv->mutex); - + */ + +#ifdef ENABLE_MAN + priv->fake_man = xmlNewChild (xmlDocGetRootElement (priv->xmldoc), NULL, BAD_CAST "toc", NULL); + xmlNewNsProp (priv->fake_man, NULL, BAD_CAST "id", BAD_CAST "Man"); + xmlNewChild (priv->fake_man, NULL, BAD_CAST "title", + BAD_CAST _("Manual Pages")); + xmlNewNsProp (priv->fake_man, NULL, BAD_CAST "protected", BAD_CAST "1"); +#endif // ENABLE_MAN #ifdef ENABLE_INFO - toc_process_info (toc); + priv->fake_info = xmlNewChild (xmlDocGetRootElement (priv->xmldoc), NULL, BAD_CAST "toc", NULL); + xmlNewNsProp (priv->fake_info, NULL, BAD_CAST "id", BAD_CAST "Info"); + xmlNewChild (priv->fake_info, NULL, BAD_CAST "title", + BAD_CAST _("GNU Info Pages")); + xmlNewNsProp (priv->fake_info, NULL, BAD_CAST "protected", BAD_CAST "1"); +#endif //ENABLE_INFO + +#ifdef ENABLE_MAN + man_thread = g_thread_create ((GThreadFunc) toc_process_man, toc, TRUE, NULL); + if (!man_thread) { + g_warning ("Could not create Man page thread"); + priv->man_processed = TRUE; + } +#else + priv->man_processed = TRUE; +#endif /* ENABLE_INFO */ +#ifdef ENABLE_INFO + info_thread = g_thread_create ((GThreadFunc) toc_process_info, toc, TRUE, NULL); + if (!info_thread) { + g_warning ("Could not create Info page thread"); + priv->info_processed = TRUE; + } +#else + priv->info_processed = TRUE; #endif /* ENABLE_INFO */ g_mutex_lock (priv->mutex); @@ -523,7 +597,6 @@ toc_process (YelpToc *toc) if (parserCtxt) xmlFreeParserCtxt (parserCtxt); - priv->process_running = FALSE; g_object_unref (toc); } @@ -678,14 +751,126 @@ toc_process_info (YelpToc *toc) mynode = xmlCopyNode (xmlDocGetRootElement (info_doc), 1); g_mutex_lock (priv->mutex); - xmlAddChild (xmlDocGetRootElement (priv->xmldoc), mynode); + xmlReplaceNode (priv->fake_info, mynode); + + priv->info_transform = yelp_transform_new (STYLESHEET, + (YelpTransformFunc) transform_func, + toc); + + priv->transform_running = TRUE; + /* FIXME: we probably need to set our own params */ + yelp_transform_start (priv->info_transform, + priv->xmldoc, + NULL); g_mutex_unlock (priv->mutex); xmlFreeDoc (info_doc); + done: if (parserCtxt) xmlFreeParserCtxt (parserCtxt); - + g_mutex_lock (priv->mutex); + priv->info_processed = TRUE; + g_mutex_unlock (priv->mutex); } #endif /* ENABLE_INFO */ + +#ifdef ENABLE_MAN + +static int +spoon_add_man_document (SpoonManEntry *entry, void *user_data) +{ + xmlNodePtr node = (xmlNodePtr) user_data; + xmlNodePtr new; + gchar *tmp; + new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL); + tmp = g_strdup_printf ("man:%s", entry->path); + + xmlNewNsProp (new, NULL, BAD_CAST "href", BAD_CAST tmp); + xmlNewTextChild (new, NULL, BAD_CAST "title", BAD_CAST entry->name); + if (entry->comment) + xmlNewTextChild (new, NULL, BAD_CAST "description", BAD_CAST entry->comment); + return TRUE; +} + +void +toc_process_man (YelpToc *toc) +{ + xmlNodePtr cat_node = NULL; + xmlNodePtr mynode = NULL; + YelpTocPriv * priv = toc->priv; + int i, j; + xmlXPathContextPtr xpath; + xmlXPathObjectPtr obj; + xmlDocPtr man_doc; + xmlParserCtxtPtr parserCtxt = NULL; + + debug_print (DB_FUNCTION, "entering\n"); + + parserCtxt = xmlNewParserCtxt (); + + man_doc = xmlCtxtReadFile (parserCtxt, DATADIR "/yelp/man.xml", NULL, + XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | + XML_PARSE_NOENT | XML_PARSE_NOERROR | + XML_PARSE_NONET ); + if (!man_doc) { + g_warning ("Could not process man TOC"); + goto done; + } + + xpath = xmlXPathNewContext (man_doc); + obj = xmlXPathEvalExpression (BAD_CAST "//toc", xpath); + + for (i = 0; i < obj->nodesetval->nodeNr; i++) { + xmlNodePtr node = obj->nodesetval->nodeTab[i]; + xmlChar *sect = xmlGetProp (node, BAD_CAST "sect"); + xmlChar *id = xmlGetProp (node, BAD_CAST "id"); + + if (sect) { + gchar **sects = g_strsplit ((gchar *)sect, " ", 0); + + g_mutex_lock (priv->mutex); + yelp_document_add_page_id (YELP_DOCUMENT (toc), (gchar *) id, (gchar *) id); + g_mutex_unlock (priv->mutex); + + cat_node = xmlNewChild (node, NULL, BAD_CAST "toc", + NULL); + for (j = 0; sects[j] != NULL; j++) + spoon_man_for_each_in_category (sects[j], (SpoonManForeachFunc) spoon_add_man_document, node); + g_strfreev (sects); + } + xmlFree (sect); + xmlFree (id); + xml_trim_titles (node, BAD_CAST "title"); + xml_trim_titles (node, BAD_CAST "description"); + } + xmlXPathFreeObject (obj); + xmlXPathFreeContext (xpath); + + mynode = xmlCopyNode (xmlDocGetRootElement (man_doc), 1); + + g_mutex_lock (priv->mutex); + xmlReplaceNode (priv->fake_man, mynode); + + priv->man_transform = yelp_transform_new (STYLESHEET, + (YelpTransformFunc) transform_func, + toc); + + priv->transform_running = TRUE; + /* FIXME: we probably need to set our own params */ + yelp_transform_start (priv->man_transform, + priv->xmldoc, + NULL); + g_mutex_unlock (priv->mutex); + + xmlFreeDoc (man_doc); + + done: + if (parserCtxt) + xmlFreeParserCtxt (parserCtxt); + g_mutex_lock (priv->mutex); + priv->man_processed = TRUE; + g_mutex_unlock (priv->mutex); +} +#endif /* ENABLE_MAN */ -- cgit v1.2.1