diff options
Diffstat (limited to 'src/yelp-toc-pager.c')
-rw-r--r-- | src/yelp-toc-pager.c | 2473 |
1 files changed, 0 insertions, 2473 deletions
diff --git a/src/yelp-toc-pager.c b/src/yelp-toc-pager.c deleted file mode 100644 index 7e9a132e..00000000 --- a/src/yelp-toc-pager.c +++ /dev/null @@ -1,2473 +0,0 @@ -/* -*- 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 <unistd.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <glib.h> -#include <glib/gstdio.h> -#include <glib/gi18n.h> -#include <gio/gio.h> -#include <libxml/parser.h> -#include <libxml/parserInternals.h> -#include <libxml/xmlreader.h> -#include <libxml/xpath.h> -#include <libxml/xpathInternals.h> -#include <libxml/HTMLtree.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 <spoon.h> -#include <spoon-reg-utils.h> -#include <spoon-info.h> -#include <spoon-man.h> - -#include "yelp-debug.h" -#include "yelp-error.h" -#include "yelp-settings.h" -#include "yelp-toc-pager.h" -#include "yelp-utils.h" -#include "yelp-io-channel.h" - -#define YELP_NAMESPACE "http://www.gnome.org/yelp/ns" - -#define STYLESHEET_PATH DATADIR"/yelp/xslt/" -#define TOC_STYLESHEET STYLESHEET_PATH"toc2html.xsl" - -typedef gboolean (*ProcessFunction) (YelpTocPager *pager); - -#define YELP_TOC_PAGER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_TOC_PAGER, YelpTocPagerPriv)) - -struct _YelpTocPagerPriv { - gboolean sk_docomf; - GSList *omf_pending; /* list of directories which contain omf files - * to process */ - GHashTable *omf_dirhash; /* key = directory name; - value = GSList of omf files to process */ - xmlDocPtr omfindex_xml; /* in memory cache file for omf files */ - xmlNodePtr omf_root; - xmlNodePtr omf_ins; - -#ifdef ENABLE_MAN - gint manpage_count; - xmlNodePtr root; - xmlNodePtr ins; - xmlDocPtr manindex_xml; - GSList *mandir_list; - GSList *mandir_ptr; /* ptr to current entry in mandir_list */ - GSList *mandir_langpath; /* ptr to current entry in mandir_ptr */ - GHashTable *man_secthash; - GHashTable *man_manhash; - GHashTable *man_dirlang; /* key = man page directory, value = language */ -#endif - - xmlDocPtr toc_doc; - xmlDocPtr man_doc; - xmlDocPtr info_doc; - - GHashTable *unique_hash; - GHashTable *category_hash; - - xmlParserCtxtPtr parser; - - ProcessFunction pending_func; - - gboolean cancel; - gint pause_count; - - xsltStylesheetPtr stylesheet; - xsltTransformContextPtr transformContext; - - guint process_id; -}; - -static void toc_pager_class_init (YelpTocPagerClass *klass); -static void toc_pager_init (YelpTocPager *pager); -static void toc_pager_dispose (GObject *gobject); - -static void toc_pager_error (YelpPager *pager); -static void toc_pager_finish (YelpPager *pager); - -static gboolean toc_pager_process (YelpPager *pager); -static void toc_pager_cancel (YelpPager *pager); -static const gchar * toc_pager_resolve_frag (YelpPager *pager, - const gchar *frag_id); -static GtkTreeModel * toc_pager_get_sections (YelpPager *pager); - -static gboolean toc_process_pending (YelpTocPager *pager); - - -static gboolean process_read_menu (YelpTocPager *pager); -static gboolean process_xslt (YelpTocPager *pager); -static gboolean process_read_scrollkeeper (YelpTocPager *pager, - gchar *content_list); -static gboolean process_omf_pending (YelpTocPager *pager); -#ifdef ENABLE_MAN -static gboolean process_mandir_pending (YelpTocPager *pager); -#endif -#ifdef ENABLE_INFO -static gboolean process_info_pending (YelpTocPager *pager); -#endif -static gboolean process_cleanup (YelpTocPager *pager); - -static void toc_add_doc_info (YelpTocPager *pager, - YelpDocInfo *doc_info); -static void toc_remove_doc_info (YelpTocPager *pager, - YelpDocInfo *doc_info); -static void xml_trim_titles (xmlNodePtr node, - xmlChar *nodetype); -static void xslt_yelp_document (xsltTransformContextPtr ctxt, - xmlNodePtr node, - xmlNodePtr inst, - xsltStylePreCompPtr comp); - -static YelpPagerClass *parent_class; - -static YelpTocPager *toc_pager; - -GType -yelp_toc_pager_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (YelpTocPagerClass), - NULL, - NULL, - (GClassInitFunc) toc_pager_class_init, - NULL, - NULL, - sizeof (YelpTocPager), - 0, - (GInstanceInitFunc) toc_pager_init, - }; - type = g_type_register_static (YELP_TYPE_PAGER, - "YelpTocPager", - &info, 0); - } - return type; -} - -static void -toc_pager_class_init (YelpTocPagerClass *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 = toc_pager_dispose; - - pager_class->error = toc_pager_error; - pager_class->cancel = toc_pager_cancel; - pager_class->finish = toc_pager_finish; - - pager_class->process = toc_pager_process; - pager_class->cancel = toc_pager_cancel; - pager_class->resolve_frag = toc_pager_resolve_frag; - pager_class->get_sections = toc_pager_get_sections; - - g_type_class_add_private (klass, sizeof (YelpTocPagerPriv)); -} - -static void -toc_pager_init (YelpTocPager *pager) -{ - YelpTocPagerPriv *priv; - - pager->priv = priv = YELP_TOC_PAGER_GET_PRIVATE (pager); - - priv->parser = xmlNewParserCtxt (); - - priv->unique_hash = g_hash_table_new (g_str_hash, g_str_equal); - priv->category_hash = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - - priv->cancel = 0; - priv->pause_count = 0; - priv->pending_func = NULL; - priv->process_id = 0; -} - -static void -toc_pager_dispose (GObject *object) -{ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -/******************************************************************************/ - -void -yelp_toc_pager_init (void) -{ - YelpDocInfo *doc_info; - - doc_info = yelp_doc_info_get ("x-yelp-toc:", FALSE); - - toc_pager = (YelpTocPager *) g_object_new (YELP_TYPE_TOC_PAGER, - "document-info", doc_info, - NULL); - - yelp_pager_start (YELP_PAGER (toc_pager)); -} - -YelpTocPager * -yelp_toc_pager_get (void) -{ - return toc_pager; -} - -void -yelp_toc_pager_pause (YelpTocPager *pager) -{ - g_return_if_fail (pager != NULL); - - debug_print (DB_FUNCTION, "entering\n"); - debug_print (DB_ARG, " pause_count = %i\n", pager->priv->pause_count + 1); - - pager->priv->pause_count ++; - - debug_print (DB_FUNCTION, "exiting\n"); -} - -void -yelp_toc_pager_unpause (YelpTocPager *pager) -{ - g_return_if_fail (pager != NULL); - - debug_print (DB_FUNCTION, "entering\n"); - debug_print (DB_ARG, " pause_count = %i\n", pager->priv->pause_count - 1); - - pager->priv->pause_count--; - if (pager->priv->pause_count < 0) { - g_warning (_("YelpTocPager: Pause count is negative.")); - pager->priv->pause_count = 0; - } - - if (pager->priv->pause_count < 1 && - pager->priv->process_id == 0) { - pager->priv->process_id = - gtk_idle_add_priority (G_PRIORITY_LOW, - (GtkFunction) toc_process_pending, - pager); - } - - debug_print (DB_FUNCTION, "exiting\n"); -} - -/******************************************************************************/ - -static void -toc_pager_error (YelpPager *pager) -{ - debug_print (DB_FUNCTION, "entering\n"); - yelp_pager_set_state (pager, YELP_PAGER_STATE_ERROR); -} - -static void -toc_pager_cancel (YelpPager *pager) -{ - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - - debug_print (DB_FUNCTION, "entering\n"); - yelp_pager_set_state (pager, YELP_PAGER_STATE_INVALID); - - priv->cancel = TRUE; -} - -static void -toc_pager_finish (YelpPager *pager) -{ - debug_print (DB_FUNCTION, "entering\n"); - yelp_pager_set_state (pager, YELP_PAGER_STATE_FINISHED); -} - -static gboolean -toc_pager_process (YelpPager *pager) -{ - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - - debug_print (DB_FUNCTION, "entering\n"); - - yelp_pager_set_state (pager, YELP_PAGER_STATE_PARSING); - g_signal_emit_by_name (pager, "parse"); - - /* Set it running */ - yelp_pager_set_state (pager, YELP_PAGER_STATE_RUNNING); - g_signal_emit_by_name (pager, "start"); - - priv->pending_func = (ProcessFunction) process_read_menu; - - if (priv->process_id == 0) { - priv->process_id = - gtk_idle_add_priority (G_PRIORITY_LOW, - (GtkFunction) toc_process_pending, - pager); - } - return FALSE; -} - -/* we take advantage of the resolve_frag function to do lazy - * loading of each page the TOC. frag_id is the id attribute - * of the toc element that we want. - * - * yes, this kind of a hack */ -static const gchar * -toc_pager_resolve_frag (YelpPager *pager, const gchar *frag_id) -{ - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - YelpPage *page = NULL; - GError *error = NULL; - xmlDocPtr outdoc = NULL; - gchar **params = NULL; - gint params_i = 0; - gint params_max = 10; - GtkIconInfo *info; - GtkIconTheme *theme = (GtkIconTheme *) yelp_settings_get_icon_theme (); - - if (priv->toc_doc == NULL) - return NULL; - - debug_print (DB_FUNCTION, "entering\n"); - debug_print (DB_ARG, "frag_id = %s\n", frag_id); - - /* if frag_id is NULL, we assume we are loading the top level TOC page */ - if (frag_id == NULL) - frag_id = "index"; - - /* we use the "frag_id" as the page_id here */ - page = (YelpPage *) yelp_pager_get_page_from_id (pager, frag_id); - - /* if we found the page just return */ - if (page != NULL) { - debug_print (DB_DEBUG, "found the frag_id=%s\n", frag_id); - return frag_id; - } - - /* only create and parse the stylesheet on the first call to this function */ - if (!priv->stylesheet) { - priv->stylesheet = xsltParseStylesheetFile (BAD_CAST TOC_STYLESHEET); - } - - if (!priv->stylesheet) { - g_set_error (&error, YELP_ERROR, YELP_ERROR_PROC, - _("The table of contents could not be processed. The " - "file ‘%s’ is either missing or is not a valid XSLT " - "stylesheet."), - TOC_STYLESHEET); - yelp_pager_error (YELP_PAGER (pager), error); - goto done; - } - - priv->transformContext = xsltNewTransformContext (priv->stylesheet, - priv->toc_doc); - priv->transformContext->_private = pager; - xsltRegisterExtElement (priv->transformContext, - BAD_CAST "document", - BAD_CAST YELP_NAMESPACE, - (xsltTransformFunction) xslt_yelp_document); - - params = g_new0 (gchar *, params_max); - yelp_settings_params (¶ms, ¶ms_i, ¶ms_max); - - if ((params_i + 10) >= params_max - 1) { - params_max += 10; - params = g_renew (gchar *, params, params_max); - } - - info = gtk_icon_theme_lookup_icon (theme, "yelp-icon-big", 192, 0); - if (info) { - params[params_i++] = "help_icon"; - params[params_i++] = g_strdup_printf ("\"%s\"", - gtk_icon_info_get_filename (info)); - params[params_i++] = "help_icon_size"; - params[params_i++] = g_strdup_printf ("%i", - gtk_icon_info_get_base_size (info)); - gtk_icon_info_free (info); - } - - /* we specify the id attribute of the toc element that we want to process to - * the stylesheet */ - params[params_i++] = "yelp.toc.id"; - params[params_i++] = g_strdup_printf ("\'%s\'", frag_id); - - params[params_i++] = NULL; - - outdoc = xsltApplyStylesheetUser (priv->stylesheet, - priv->toc_doc, - (const gchar **)params, NULL, NULL, - priv->transformContext); - /* Don't do this */ - g_signal_emit_by_name (pager, "finish"); - - done: - if (params) { - for (params_i = 0; params[params_i] != NULL; params_i++) - if (params_i % 2 == 1) - g_free ((gchar *) params[params_i]); - } - if (outdoc) - xmlFreeDoc (outdoc); - /* with this hack (this function) we can't free the toc_doc */ - /*if (priv->toc_doc) { - xmlFreeDoc (priv->toc_doc); - priv->toc_doc = NULL; - }*/ - if (priv->transformContext) { - xsltFreeTransformContext (priv->transformContext); - priv->transformContext = NULL; - } - - return frag_id; -} - -static GtkTreeModel * -toc_pager_get_sections (YelpPager *pager) -{ - return NULL; -} - -/******************************************************************************/ - -static gboolean -toc_process_pending (YelpTocPager *pager) -{ - gboolean readd; - YelpTocPagerPriv *priv = pager->priv; - static ProcessFunction process_funcs[] = { - process_read_menu, - /*process_omf_pending,*/ -#ifdef ENABLE_MAN - process_mandir_pending, -#endif -#ifdef ENABLE_INFO - process_info_pending, -#endif - /* process_xslt, */ - process_cleanup, - NULL - }; - static gint process_i = 0; - - if (priv->cancel || !priv->pending_func) { - /* FIXME: clean stuff up. */ - priv->process_id = 0; - return FALSE; - } - - readd = priv->pending_func(pager); - - /* if the pending function returned FALSE, then we move on to - * calling the next function */ - if (!readd) - priv->pending_func = process_funcs[++process_i]; - - if (priv->pending_func == NULL) - g_signal_emit_by_name (pager, "finish"); - - if ((priv->pending_func != NULL) && (priv->pause_count < 1)) - return TRUE; - else { - priv->process_id = 0; - return FALSE; - } -} - -/** process_read_scrollkeeper *************************************************/ - -static void -sk_startElement (void *pager, - const xmlChar *name, - const xmlChar **attrs) -{ - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - if (xmlStrEqual((const xmlChar*) name, BAD_CAST "docomf")) - priv->sk_docomf = TRUE; -} - -static void -sk_endElement (void *pager, - const xmlChar *name) -{ - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - if (xmlStrEqual((const xmlChar*) name, BAD_CAST "docomf")) - priv->sk_docomf = FALSE; -} - -static void -sk_characters (void *pager, - const xmlChar *ch, - int len) -{ - gchar *omf; - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - - if (priv->sk_docomf) { - GSList *filelist = NULL; - GSList *ptr = NULL; - gchar *dirname = NULL; - - omf = g_strndup ((gchar *) ch, len); - /* since the directory that the omf file is in can be in any - * order, we use a hash to aggregrate the files by directory. - * We end up with a hash whose key is the dirname, and whose - * values are GSLists of filenames. */ - if (!priv->omf_dirhash) - priv->omf_dirhash = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - - dirname = g_path_get_dirname (omf); - - ptr = g_hash_table_lookup (priv->omf_dirhash, dirname); - - if (!ptr) { - /* this directory is not in the hash; create an entry for it */ - filelist = g_slist_append (filelist, omf); - g_hash_table_insert (priv->omf_dirhash, dirname, filelist); - - /* add the directory name to a list so we can iterate through - * the hash later */ - priv->omf_pending = g_slist_prepend (priv->omf_pending, - g_path_get_dirname(omf)); - } else { - /* prepend to the existing file list for this directory entry */ - ptr = g_slist_prepend (ptr, omf); - /* writes over old value */ - g_hash_table_insert (priv->omf_dirhash, dirname, ptr); - } - - } -} - -static gboolean -process_read_scrollkeeper (YelpTocPager *pager, gchar *content_list) -{ - static xmlSAXHandler sk_sax_handler = { 0, }; - - if (!sk_sax_handler.startElement) { - sk_sax_handler.startElement = sk_startElement; - sk_sax_handler.endElement = sk_endElement; - sk_sax_handler.characters = sk_characters; - sk_sax_handler.initialized = TRUE; - } - - xmlSAXUserParseFile (&sk_sax_handler, pager, content_list); - - return FALSE; -} - -static gboolean -files_are_equivalent (gchar *file1, gchar *file2) -{ - FILE *f1; - FILE *f2; - guint data1; - guint data2; - - f1 = fopen (file1, "r"); - if (!f1) - return FALSE; - - f2 = fopen (file2, "r"); - if (!f2) - return FALSE; - - while (fread (&data1, sizeof (gint), 1, f1)) { - fread (&data2, sizeof (gint), 1, f2); - if (data1 != data2) - return FALSE; - } - - fclose (f1); - fclose (f2); - - return TRUE; -} - -/* returns a newly created hash table with the following keys: - * url, title, description, category, language, seriesid - * caller must free the hash table with g_hash_table_destroy() - * returns NULL on failure */ -static GHashTable * -get_omf_attributes (YelpTocPager *pager, const gchar *omffile) -{ - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - GHashTable *hash = NULL; - xmlXPathContextPtr xpath = NULL; - xmlXPathObjectPtr object = NULL; - xmlDocPtr omf_doc = NULL; - - omf_doc = xmlCtxtReadFile (priv->parser, omffile, NULL, - XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | - XML_PARSE_NOENT | XML_PARSE_NOERROR | - XML_PARSE_NONET ); - - if (!omf_doc) { - g_warning (_("Could not load the OMF file '%s'."), omffile); - return NULL; - } - - hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); - xpath = xmlXPathNewContext (omf_doc); - - object = - xmlXPathEvalExpression (BAD_CAST "string(/omf/resource/identifier/@url)", - xpath); - g_hash_table_insert (hash, "url", g_strdup ((gchar *) object->stringval)); - xmlXPathFreeObject (object); - - object = - xmlXPathEvalExpression (BAD_CAST "string(/omf/resource/title)", - xpath); - g_hash_table_insert (hash, "title", g_strdup ((gchar *) object->stringval)); - xmlXPathFreeObject (object); - - object = - xmlXPathEvalExpression (BAD_CAST "string(/omf/resource/description)", - xpath); - g_hash_table_insert (hash, "description", g_strdup ((gchar *) object->stringval)); - xmlXPathFreeObject (object); - - object = - xmlXPathEvalExpression (BAD_CAST "string(/omf/resource/subject/@category)", - xpath); - g_hash_table_insert (hash, "category", g_strdup ((gchar *) object->stringval)); - xmlXPathFreeObject (object); - - object = - xmlXPathEvalExpression (BAD_CAST "string(/omf/resource/language/@code)", - xpath); - g_hash_table_insert (hash, "language", g_strdup ((gchar *) object->stringval)); - xmlXPathFreeObject (object); - - object = - xmlXPathEvalExpression (BAD_CAST "string(/omf/resource/relation/@seriesid)", - xpath); - g_hash_table_insert (hash, "seriesid", g_strdup ((gchar *) object->stringval)); - xmlXPathFreeObject (object); - - xmlXPathFreeContext (xpath); - xmlFreeDoc (omf_doc); - - return hash; -} - -static void -create_toc_from_omf_cache_file (YelpTocPager *pager, const gchar *index_file) -{ - xmlXPathContextPtr xpath = NULL; - xmlXPathObjectPtr objfiles = NULL; - xmlDocPtr omfindex_xml = NULL; - gint i; - - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - - omfindex_xml = xmlReadFile (index_file, NULL, XML_PARSE_NOCDATA | - XML_PARSE_NOERROR | XML_PARSE_NONET); - - if (omfindex_xml == NULL) { - g_warning ("Unable to parse index file \"%s\"\n" - "try deleting this file and running yelp again.\n", index_file); - return; - } - - xpath = xmlXPathNewContext (omfindex_xml); - - objfiles = xmlXPathEvalExpression (BAD_CAST "/omfindex/dir/omffile", xpath); - - for (i=0; i < objfiles->nodesetval->nodeNr; i++) { - YelpDocInfo *doc_info = NULL; - YelpDocInfo *doc_old = NULL; - xmlXPathObjectPtr objattr = NULL; - xmlNodePtr node = NULL; - xmlChar *attr = NULL; - gchar *id = NULL; - - xpath->node = objfiles->nodesetval->nodeTab[i]; - - objattr = xmlXPathEvalExpression (BAD_CAST "url", xpath); - node = objattr->nodesetval->nodeTab[0]; - attr = xmlNodeListGetString (omfindex_xml, node->xmlChildrenNode, 1); - xmlXPathFreeObject (objattr); - - if (!attr) { - g_warning ("missing required \"url\" element in omf cache file\n"); - continue; - } - - doc_info = yelp_doc_info_get ((const gchar *) attr, TRUE); - xmlFree (attr); - - if (!doc_info) - return; - - objattr = xmlXPathEvalExpression (BAD_CAST "title", xpath); - node = objattr->nodesetval->nodeTab[0]; - attr = xmlNodeListGetString (omfindex_xml, node->xmlChildrenNode, 1); - yelp_doc_info_set_title (doc_info, (gchar *)attr); - xmlXPathFreeObject (objattr); - xmlFree (attr); - - objattr = xmlXPathEvalExpression (BAD_CAST "description", xpath); - node = objattr->nodesetval->nodeTab[0]; - attr = xmlNodeListGetString (omfindex_xml, node->xmlChildrenNode, 1); - yelp_doc_info_set_description (doc_info, (gchar *)attr); - xmlXPathFreeObject (objattr); - xmlFree (attr); - - objattr = xmlXPathEvalExpression (BAD_CAST "category", xpath); - node = objattr->nodesetval->nodeTab[0]; - attr = xmlNodeListGetString (omfindex_xml, node->xmlChildrenNode, 1); - yelp_doc_info_set_category (doc_info, (gchar *)attr); - xmlXPathFreeObject (objattr); - xmlFree (attr); - - objattr = xmlXPathEvalExpression (BAD_CAST "language", xpath); - node = objattr->nodesetval->nodeTab[0]; - attr = xmlNodeListGetString (omfindex_xml, node->xmlChildrenNode, 1); - yelp_doc_info_set_language (doc_info, (gchar *)attr); - xmlXPathFreeObject (objattr); - xmlFree (attr); - - objattr = xmlXPathEvalExpression (BAD_CAST "seriesid", xpath); - node = objattr->nodesetval->nodeTab[0]; - attr = xmlNodeListGetString (omfindex_xml, node->xmlChildrenNode, 1); - id = g_strconcat ("scrollkeeper.", (gchar *) attr, NULL); - yelp_doc_info_set_id (doc_info, (gchar *)id); - xmlXPathFreeObject (objattr); - xmlFree (attr); - - doc_old = g_hash_table_lookup (priv->unique_hash, id); - g_free (id); - - if (doc_old) { - if (yelp_doc_info_cmp_language (doc_info, doc_old) < 0) { - toc_remove_doc_info (YELP_TOC_PAGER (pager), doc_old); - toc_add_doc_info (YELP_TOC_PAGER (pager), doc_info); - } - } else - toc_add_doc_info (YELP_TOC_PAGER (pager), doc_info); - - } - - xmlXPathFreeContext (xpath); - xmlXPathFreeObject (objfiles); - xmlFreeDoc (omfindex_xml); - - return; -} - -/** process_omf_pending *******************************************************/ - -static gboolean -process_omf_pending (YelpTocPager *pager) -{ - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - YelpDocInfo *doc_info; - YelpDocInfo *doc_old; - static gboolean first_call = TRUE; - static gchar *index_file = NULL; - static gchar *content_list = NULL; - static gchar *sk_file = NULL; - GHashTable *omf_hash = NULL; - GSList *filelist = NULL; - GSList *firstfile = NULL; - GSList *first = NULL; - gchar *dir = NULL; - gchar *file = NULL; - gchar *lang = NULL; - gchar *stderr_str = NULL; - gchar *command = NULL; - FILE *newindex = NULL; - - if (!index_file) - index_file = g_build_filename (yelp_dot_dir(), "omfindex.xml", NULL); - - /* on first call to this function, we check for the existence of a - * cache file. If it exists, we get our information from there. If - * it doesn't exist, then we create a list of omf files to process - * with the process_read_scrollkeeper() function */ - if (first_call) { - first_call = FALSE; - - sk_file = g_build_filename (yelp_dot_dir(), "sk-content-list.last", NULL); - - /* get current language */ - const gchar * const * langs = g_get_language_names (); - if (langs && langs[0]) - lang = (gchar *) langs[0]; - else - lang = "C"; - - command = g_strconcat ("scrollkeeper-get-content-list ", lang, NULL); - - if (!g_spawn_command_line_sync (command, &content_list, - &stderr_str, NULL, NULL)) { - g_critical ("scrollkeeper-get-content-list failed: %s", stderr_str); - return FALSE; - } - - /* required to remove LFs and extra whitespace from the filename */ - g_strstrip (content_list); - - g_free (stderr_str); - g_free (command); - - if (g_file_test (index_file, G_FILE_TEST_IS_REGULAR) && - g_file_test (sk_file, G_FILE_TEST_IS_REGULAR)) { - /* the presence of a cache file is not enough. The cache file - * could be outdated since the scrollkeeper database could have - * been rebuilt since the last time the cache file was created. - * We solve this by copying the scrollkeeper content list file - * to ~/.gnome/yelp.d/sk-content-list.last when the - * cache file is originally created. On subsequent runs, we then - * do a byte by byte comparison between the generated content - * list and the old one at ~/.gnome2/yelp.d/ - If they are exactly - * the same, then we use the cache file; otherwise the cache file - * will get rebuilt. Of course this operates under the assumption - * that the contents list generated by scrollkeeper is always the - * same if the scrollkeeper database has not been rebuilt. If that - * ever fails to be the case then we end up rebuilding the cache - * file everytime, so there's no regression of functionality */ - - if (!files_are_equivalent (sk_file, content_list)) { - process_read_scrollkeeper (pager, content_list); - return TRUE; - } - - create_toc_from_omf_cache_file (pager, index_file); - - /* done processing, don't call this function again */ - return FALSE; - } - - process_read_scrollkeeper (pager, content_list); - - /* return true, so that this function is called again to continue - * processing */ - return TRUE; - } - - /* if we've made it to here, that means we need to regenerate the cache - * file, so allocate an in memory XML document here */ - if (!priv->omfindex_xml) { - priv->omfindex_xml = xmlNewDoc (BAD_CAST "1.0"); - priv->omf_root = xmlNewNode (NULL, BAD_CAST "omfindex"); - - xmlDocSetRootElement (priv->omfindex_xml, priv->omf_root); - - xmlAddChild (priv->omf_root, xmlNewText (BAD_CAST "\n ")); - } - - /* get the "first" directory in the GSList "omf_pending" */ - first = priv->omf_pending; - - /* if this is NULL, then we are done processing */ - /* FIXME: cleanup any leftover stuff here */ - if (!first) { - GFile *fromfile = g_file_new_for_uri (content_list); - GFile *tofile = g_file_new_for_uri (sk_file); - gboolean result = FALSE; - - /* create the new cache file */ - if (!(newindex = g_fopen (index_file, "w"))) - g_warning ("Unable to create '%s'\n", index_file); - else { - xmlDocDump (newindex, priv->omfindex_xml); - fclose (newindex); - } - - /* copy the newly created file to ~/.gnome2/yelp.d/omfindex.xml, - * overwriting the old one if necessary */ - result = g_file_copy (fromfile, tofile, G_FILE_COPY_OVERWRITE, - NULL, NULL, NULL, NULL); - - g_object_unref (fromfile); - g_object_unref (tofile); - - if (result != TRUE) - g_critical ("Unable to copy %s to %s\n", content_list, sk_file); - - if (priv->omf_dirhash) - g_hash_table_destroy (priv->omf_dirhash); - - xmlFreeDoc (priv->omfindex_xml); - - return FALSE; - } - - /* remove this "first" directory from our list */ - priv->omf_pending = g_slist_remove_link (priv->omf_pending, first); - dir = (gchar *) first->data; - - priv->omf_ins = xmlNewChild (priv->omf_root, NULL, BAD_CAST "dir", NULL); - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - xmlNewChild (priv->omf_ins, NULL, BAD_CAST "name", BAD_CAST dir); - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - - filelist = g_hash_table_lookup (priv->omf_dirhash, dir); - - while (filelist && filelist->data) { - gchar *id = NULL; - gchar *url = NULL; - - firstfile = filelist; - filelist = g_slist_remove_link (filelist, firstfile); - - file = (gchar *) firstfile->data; - - if (!file || !g_str_has_suffix (file, ".omf")) - goto done; - - omf_hash = get_omf_attributes (pager, file); - - if (!omf_hash) - goto done; - - /* url is required, if it's not present don't even add the - * entry to the cache file */ - url = g_hash_table_lookup (omf_hash, "url"); - if (url == NULL || *url == '\0') - goto done; - - /* this add all the omf information to the xml cache file */ - priv->omf_ins = xmlNewChild (priv->omf_ins, NULL, - BAD_CAST "omffile", NULL); - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - xmlNewChild (priv->omf_ins, NULL, BAD_CAST "path", BAD_CAST file); - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - xmlNewChild (priv->omf_ins, NULL, BAD_CAST "url", - BAD_CAST g_hash_table_lookup (omf_hash, "url")); - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - xmlNewChild (priv->omf_ins, NULL, BAD_CAST "title", - BAD_CAST g_hash_table_lookup (omf_hash, "title")); - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - xmlNewChild (priv->omf_ins, NULL, BAD_CAST "language", - BAD_CAST g_hash_table_lookup (omf_hash, "language")); - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - xmlNewChild (priv->omf_ins, NULL, BAD_CAST "category", - BAD_CAST g_hash_table_lookup (omf_hash, "category")); - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - xmlNewChild (priv->omf_ins, NULL, BAD_CAST "description", - BAD_CAST g_hash_table_lookup (omf_hash, "description")); - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - xmlNewChild (priv->omf_ins, NULL, BAD_CAST "seriesid", - BAD_CAST g_hash_table_lookup (omf_hash, "seriesid")); - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - priv->omf_ins = priv->omf_ins->parent; - - doc_info = - yelp_doc_info_get ((const gchar *) g_hash_table_lookup (omf_hash, "url"), - FALSE); - - if (!doc_info) - goto done; - - yelp_doc_info_set_title (doc_info, g_hash_table_lookup (omf_hash, "title")); - yelp_doc_info_set_language (doc_info, g_hash_table_lookup (omf_hash, "language")); - yelp_doc_info_set_category (doc_info, g_hash_table_lookup (omf_hash, "category")); - yelp_doc_info_set_description (doc_info, g_hash_table_lookup (omf_hash, "description")); - - id = g_strconcat ("scrollkeeper.", - (gchar *) g_hash_table_lookup (omf_hash, "seriesid"), - NULL); - - yelp_doc_info_set_id (doc_info, id); - - doc_old = g_hash_table_lookup (priv->unique_hash, id); - - if (doc_old) { - if (yelp_doc_info_cmp_language (doc_info, doc_old) < 0) { - toc_remove_doc_info (YELP_TOC_PAGER (pager), doc_old); - toc_add_doc_info (YELP_TOC_PAGER (pager), doc_info); - } - } else - toc_add_doc_info (YELP_TOC_PAGER (pager), doc_info); - -done: - if (omf_hash) - g_hash_table_destroy (omf_hash); - g_free (file); - g_slist_free_1 (firstfile); - g_free (id); - - } /* end while */ - - xmlAddChild (priv->omf_ins, xmlNewText (BAD_CAST "\n ")); - - g_free (dir); - g_slist_free_1 (first); - - /* continue processing */ - return TRUE; -} - -#ifdef ENABLE_MAN -static void -add_man_page_to_toc (YelpTocPager *pager, gchar *dirname, gchar *filename) -{ - xmlNodePtr tmp = NULL; - gchar *manname = NULL; - gchar *mansect = NULL; - gchar *manman = NULL; - gchar *c1 = NULL; - gchar *c2 = NULL; - - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - - c1 = g_strrstr (filename, ".bz2"); - - if (c1 && strlen (c1) != 4) - c1 = NULL; - - if (!c1) { - c1 = g_strrstr (filename, ".gz"); - if (c1 && strlen (c1) != 3) - c1 = NULL; - } - - /* c1 points to the file extension, either .gz or .bz2 at this point - * or is NULL if the filename does not have either extension */ - if (c1) - c2 = g_strrstr_len (filename, c1 - filename, "."); - else - c2 = g_strrstr (filename, "."); - - /* c2 points to the period preceding the man page section in the - * filename at this point */ - if (c2) { - manname = g_strndup (filename, c2 - filename); - if (c1) - mansect = g_strndup (c2 + 1, c1 - c2 - 1); - else - mansect = g_strdup (c2 + 1); - } - - /* if filename has no period in it, we have no idea what man - * section to place it in. So just ignore it. */ - else return; - - manman = g_strconcat (manname, ".", mansect, NULL); - - if (g_hash_table_lookup (priv->man_manhash, manman) == NULL) { - tmp = g_hash_table_lookup (priv->man_secthash, mansect); - - if (tmp == NULL && strlen (mansect) > 1) { - gchar *mansect0 = g_strndup (mansect, 1); - tmp = g_hash_table_lookup (priv->man_secthash, mansect0); - g_free (mansect0); - } - - if (tmp) { - gchar *tooltip, *url_full, *url_short; - YelpDocInfo *info; - - url_full = g_strconcat ("man:", dirname, "/", filename, NULL); - url_short = g_strconcat ("man:", manname, ".", mansect, NULL); - info = yelp_doc_info_get (url_full, TRUE); - - if (info) { - gchar *lang = NULL; - - if (priv->man_dirlang) - lang = g_hash_table_lookup (priv->man_dirlang, dirname); - - if (lang) - yelp_doc_info_set_language (info, lang); - - yelp_doc_info_add_uri (info, url_short, YELP_URI_TYPE_MAN); - tmp = xmlNewChild (tmp, NULL, BAD_CAST "doc", NULL); - xmlNewProp (tmp, BAD_CAST "href", BAD_CAST url_full); - xmlNewChild (tmp, NULL, BAD_CAST "title", BAD_CAST manname); - tooltip = g_strdup_printf (_("Read man page for %s"), manname); - xmlNewChild (tmp, NULL, BAD_CAST "tooltip", BAD_CAST tooltip); - - g_free (tooltip); - } - - g_free (url_full); - g_free (url_short); - } else { - d (g_warning ("Could not locate section %s for %s\n", mansect, manman)); - } - - g_hash_table_insert (priv->man_manhash, g_strdup (manman), priv); - } - - g_free (manname); - g_free (mansect); - g_free (manman); -} - -static void -create_manindex_file (gchar *index_file, xmlDocPtr xmldoc) -{ - FILE *newindex = NULL; - - /* check to see if the file already exists, if so rename it */ - /* I only enable this for debugging */ -#if 0 - if (g_file_test (index_file, G_FILE_TEST_EXISTS)) { - struct stat buff; - gchar *backup_file = NULL; - - if (g_stat (index_file, &buff) < 0) - g_warning ("Unable to stat file \"%s\"\n", index_file); - - backup_file = g_strdup_printf ("%s.%d", index_file, (int) buff.st_mtime); - - if (g_rename (index_file, backup_file) < 0) - g_warning ("Unable to rename \"%s\" to \"%s\"\n", index_file, backup_file); - - g_free (backup_file); - } -#endif - - if (!(newindex = g_fopen (index_file, "w"))) - g_warning ("Unable to create '%s'\n", index_file); - else { - xmlDocDump (newindex, xmldoc); - fclose (newindex); - } -} - -/* returns 0 on error, 1 otherwise */ -static int -create_toc_from_index (YelpTocPager *pager, gchar *index_file) -{ - const gchar * const * langs = g_get_language_names (); - xmlXPathContextPtr xpath = NULL; - xmlXPathObjectPtr objsect = NULL; - xmlDocPtr manindex_xml = NULL; - xmlNodePtr root = NULL; - xmlChar *language = NULL; - gint update_flag = 0; - gint i, j; - - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - - manindex_xml = xmlReadFile (index_file, NULL, XML_PARSE_NOCDATA | - XML_PARSE_NOERROR | XML_PARSE_NONET); - - if (manindex_xml == NULL) { - g_warning ("Unable to parse index file \"%s\"\n", index_file); - return 0; - } - - /* check the language that this index file was generated for */ - root = xmlDocGetRootElement (manindex_xml); - language = xmlGetProp (root, BAD_CAST "lang"); - - /* if the language is not the same as the current language (specified - * by the LANGUAGE environment variable) then return so that the index - * is recreated */ - if (language == NULL || !g_str_equal (BAD_CAST language, langs[0])) { - debug_print (DB_INFO, - "LANGUAGE and index file language do not match, " - "index file will be recreated.\n"); - xmlFreeDoc (manindex_xml); - return 0; - } - - xmlFree (language); - - xpath = xmlXPathNewContext (manindex_xml); - objsect = xmlXPathEvalExpression (BAD_CAST "/manindex/mansect", xpath); - - for (i=0; i < objsect->nodesetval->nodeNr; i++) { - xmlXPathObjectPtr objdirs; - - if (!priv->man_manhash) - priv->man_manhash = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - - xpath->node = objsect->nodesetval->nodeTab[i]; - objdirs = xmlXPathEvalExpression (BAD_CAST "dir", xpath); - - for (j=0; j < objdirs->nodesetval->nodeNr; j++) { - xmlNodePtr dirnode = objdirs->nodesetval->nodeTab[j]; - xmlNodePtr node = NULL; - xmlChar *dirname = NULL; - xmlChar *dirmtime = NULL; - xmlChar *lang = NULL; - time_t mtime; - struct stat buf; - - lang = xmlGetProp (dirnode, BAD_CAST "lang"); - dirmtime = xmlGetProp (dirnode, BAD_CAST "mtime"); - - if (lang == NULL) - lang = xmlStrdup (BAD_CAST "C"); - - for (node = dirnode->children; node != NULL; node = node->next) { - if (node->type == XML_ELEMENT_NODE && - g_str_equal ((gchar *)node->name, "name")) { - dirname = xmlNodeGetContent (node); - } - } - - g_hash_table_insert (priv->man_dirlang, g_strdup ((gchar *)dirname), - g_strdup ((gchar *)lang)); - - /* if we can't stat the dirname for some reason, then skip adding - * this directory to the TOC, remove the dirnode, and set the flag - * to rewrite the cache file */ - if (g_stat ((gchar *)dirname, &buf) < 0) { - g_warning ("Unable to stat dir \"%s\", removing from cache file.\n", dirname); - xmlUnlinkNode (dirnode); - xmlFreeNode (dirnode); - update_flag = 1; - continue; - } - - /* FIXME: need some error checking */ - mtime = (time_t) atoi ((gchar *)dirmtime); - - /* see if directory mtime has changed - if so recreate - * the directory node */ - if (buf.st_mtime > mtime) { - GDir *dir; - xmlNodePtr newNode = NULL; - gchar mtime_str[20]; - gchar *filename = NULL; - - /* this means we will rewrite the cache file at the end */ - update_flag = 1; - - if ((dir = g_dir_open ((gchar *)dirname, 0, NULL))) { - g_snprintf (mtime_str, 20, "%u", (guint) buf.st_mtime); - - newNode = xmlNewNode (NULL, BAD_CAST "dir"); - xmlNewProp (newNode, BAD_CAST "mtime", BAD_CAST mtime_str); - xmlAddChild (newNode, xmlNewText (BAD_CAST "\n ")); - xmlNewChild (newNode, NULL, BAD_CAST "name", dirname); - xmlAddChild (newNode, xmlNewText (BAD_CAST "\n ")); - - while ((filename = (gchar *) g_dir_read_name (dir))) { - - xmlNewChild (newNode, NULL, BAD_CAST "page", BAD_CAST filename); - xmlAddChild (newNode, xmlNewText (BAD_CAST "\n ")); - - add_man_page_to_toc (pager, (gchar *)dirname, filename); - priv->manpage_count++; - } - - g_dir_close (dir); - } - - /* we replace the node in the tree */ - xmlReplaceNode (dirnode, newNode); - - /* otherwise just read from the index file */ - } else { - - for (node = dirnode->children; node != NULL; node = node->next) { - xmlChar *manpage = NULL; - - if (node->type == XML_ELEMENT_NODE && - g_str_equal ((gchar *)node->name, "page")) { - manpage = xmlNodeGetContent (node); - add_man_page_to_toc (pager, (gchar *)dirname, (gchar *)manpage); - priv->manpage_count++; - xmlFree (manpage); - } - } - - } - xmlFree (lang); - xmlFree (dirmtime); - xmlFree (dirname); - } - - /* cleanup */ - xmlXPathFreeObject (objdirs); - - if (priv->man_manhash) { - g_hash_table_destroy (priv->man_manhash); - priv->man_manhash = NULL; - } - } - - if (update_flag) { - create_manindex_file (index_file, manindex_xml); - } - - xmlXPathFreeContext (xpath); - xmlXPathFreeObject (objsect); - xmlFreeDoc (manindex_xml); - - return 1; -} - -static int -spoon_add_man_document (SpoonManEntry *entry, void *user_data) -{ - xmlNodePtr node = (xmlNodePtr) user_data; - xmlNodePtr new; - gchar tmp[255]; - new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL); - g_sprintf (&tmp, "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; -} - -static gboolean -process_mandir_pending (YelpTocPager *pager) -{ - xmlNodePtr node = NULL; - xmlNodePtr cat_node = NULL; - xmlNodePtr mynode = NULL; - char **categories = NULL; - char **cat_iter = NULL; - int sectno = 0; - YelpTocPagerPriv * priv = pager->priv; - int i, j; - xmlXPathContextPtr xpath; - xmlXPathObjectPtr obj; - - priv->man_doc = xmlCtxtReadFile (priv->parser, DATADIR "/yelp/man.xml", NULL, - XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | - XML_PARSE_NOENT | XML_PARSE_NOERROR | - XML_PARSE_NONET ); - - xpath = xmlXPathNewContext (priv->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"); - - if (sect) { - gchar **sects = g_strsplit ((gchar *)sect, " ", 0); - - cat_node = xmlNewChild (node, NULL, BAD_CAST "toc", - NULL); - for (j = 0; sects[j] != NULL; j++) - spoon_man_for_each_in_category (sects[j], spoon_add_man_document, node); - g_strfreev (sects); - } - xmlFree (sect); - xml_trim_titles (node, BAD_CAST "title"); - xml_trim_titles (node, BAD_CAST "description"); - } - xmlXPathFreeObject (obj); - xmlXPathFreeContext (xpath); - -#if 0 - static gchar *index_file = NULL; - gchar *filename = NULL; - gchar *dirname = NULL; - GDir *dir = NULL; - gint i, j, k; - - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - - if (!priv->man_doc) { - xmlXPathContextPtr xpath; - xmlXPathObjectPtr obj; - - /* NOTE: this document is free()'d at the end of the process_xslt function */ - priv->man_doc = xmlCtxtReadFile (priv->parser, DATADIR "/yelp/man.xml", NULL, - XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | - XML_PARSE_NOENT | XML_PARSE_NOERROR | - XML_PARSE_NONET ); - priv->man_secthash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - - xpath = xmlXPathNewContext (priv->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"); - - if (sect) { - gchar **sects = g_strsplit ((gchar *)sect, " ", 0); - - for (j = 0; sects[j] != NULL; j++) - g_hash_table_insert (priv->man_secthash, - g_strdup (sects[j]), node); - g_strfreev (sects); - } - xmlFree (sect); - xml_trim_titles (node, BAD_CAST "title"); - xml_trim_titles (node, BAD_CAST "description"); - } - xmlXPathFreeObject (obj); - xmlXPathFreeContext (xpath); - } - - if (!index_file) - index_file = g_build_filename (yelp_dot_dir(), "manindex.xml", NULL); - - /* On first call to this function, create a list of directories that we - * need to process: we actually make a linked list (mandir_list) whose - * members who are linked lists containing directories for a particular - * man directory such as "man1", "man2", etc.. We do this because we - * need a separate hash for every mandir */ - if (!priv->mandir_list) { - const gchar * const * langs = g_get_language_names (); - gchar *manpath = NULL; - gchar **manpaths = NULL; - gchar **mandirs = NULL; - - if (!priv->man_dirlang) - priv->man_dirlang = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_free); - - /* check for the existence of the xml cache file in ~/.gnome2/yelp.d/ - * if it exists, use it as the source for man pages instead of - * searching the hard disk for them - should make startup much faster */ - if (g_file_test (index_file, G_FILE_TEST_IS_REGULAR) && - create_toc_from_index (pager, index_file)) { - xmlNodePtr mynode; - - mynode = xmlCopyNode (xmlDocGetRootElement (priv->man_doc), 1); - xmlAddChild (xmlDocGetRootElement(priv->toc_doc), mynode); - - xmlFreeDoc (priv->man_doc); - - /* we are done processing, return FALSE so we don't call this - * function again. */ - return FALSE; - } - - mandirs = yelp_get_man_paths (); - priv->manindex_xml = xmlNewDoc (BAD_CAST "1.0"); - priv->root = xmlNewNode (NULL, BAD_CAST "manindex"); - xmlNewProp (priv->root, BAD_CAST "lang", BAD_CAST langs[0]); - priv->ins = priv->root; - - xmlDocSetRootElement (priv->manindex_xml, priv->root); - - xmlAddChild (priv->root, xmlNewText (BAD_CAST "\n ")); - - if (!g_spawn_command_line_sync ("manpath", &manpath, NULL, NULL, NULL)) - manpath = g_strdup (g_getenv ("MANPATH")); - - if (!manpath) { - manpath = g_strdup ("/usr/share/man"); - } - - g_strstrip (manpath); - manpaths = g_strsplit (manpath, G_SEARCHPATH_SEPARATOR_S, -1); - g_free (manpath); - - /* order is important here, since we may encounter collisions when adding - * a man page to the hash table "man_manhash". - * - * We want the resulting list to be sorted in order of priority: - * 1) Highest priority is given to the base directory name returned - * from $MANPATH or the manpath program. So if that is - * /usr/local/share:/usr/share then the man page - * /usr/local/share/man/man1/python.1.gz would have precedence over - * /usr/share/man/man1/python.1.gz - * 2) Next highest priority is given to the language. - * 3) Lowest priority is given to the section name, i.e. "man0p" "man1" - * since a man page from one section should never conflict with a man page - * from another section (because of the .0p or .1 section in the filename) - * - * Here is an example of how it should be sorted when - * $MANPATH=/usr/local/share:/usr/share and LANGUAGE="es" - * - * Adding /usr/local/share/man/es/man0p - * Adding /usr/share/man/es/man0p - * Adding /usr/local/share/man/man0p - * Adding /usr/share/man/man0p - * Adding /usr/local/share/man/es/man1 - * Adding /usr/share/man/es/man1 - * Adding /usr/local/share/man/man1 - * Adding /usr/share/man/man1 - */ - - for (i=0; mandirs[i] != NULL; i++) { - GSList *tmplist = NULL; - - for (j=0; langs[j] != NULL; j++) { - for (k=0; manpaths[k] != NULL; k++) { - if (g_str_equal (langs[j], "C")) - dirname = g_build_filename (manpaths[k], mandirs[i], NULL); - else - dirname = g_build_filename (manpaths[k], langs[j], - mandirs[i], - NULL); - - g_hash_table_insert (priv->man_dirlang, g_strdup (dirname), - g_strdup (langs[j])); - - /* prepend to list for speed, reverse it at the end */ - tmplist = g_slist_prepend (tmplist, dirname); - } - } - tmplist = g_slist_reverse (tmplist); - - priv->mandir_list = g_slist_prepend (priv->mandir_list, tmplist); - } - priv->mandir_list = g_slist_reverse (priv->mandir_list); - -#ifdef YELP_DEBUG - /* debugging: print out lists in order */ - GSList *list1 = priv->mandir_list; - GSList *list2 = NULL; - - while (list1 != NULL) { - list2 = list1->data; - while (list2 && list2->data) { - debug_print (DB_INFO, "Dir=%s\n", (gchar *)list2->data); - list2 = g_slist_next (list2); - } - list1 = g_slist_next (list1); - } -#endif - - g_strfreev (manpaths); - - priv->mandir_ptr = priv->mandir_list; - if (priv->mandir_list && priv->mandir_list->data) { - priv->mandir_langpath = priv->mandir_list->data; - } - - /* return TRUE, so that this function is called again.*/ - return TRUE; - } - - /* iterate through our previously created linked lists and create the - * table of contents from them */ - if (priv->mandir_langpath && priv->mandir_langpath->data) { - dirname = priv->mandir_langpath->data; - - if ((dir = g_dir_open (dirname, 0, NULL))) { - struct stat buf; - gchar mtime_str[20]; - gchar *lang = NULL; - - if (g_stat (dirname, &buf) < 0) - debug_print (DB_WARN, "Unable to stat dir: \"%s\"\n", dirname); - - /* check to see if we need create a new hash table */ - if (!priv->man_manhash) { - priv->man_manhash = - g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - - priv->ins = xmlNewChild (priv->root, NULL, BAD_CAST "mansect", NULL); - xmlAddChild (priv->ins, xmlNewText (BAD_CAST "\n ")); - } - - g_snprintf (mtime_str, 20, "%u", (guint) buf.st_mtime); - - lang = g_hash_table_lookup (priv->man_dirlang, dirname); - - priv->ins = xmlNewChild (priv->ins, NULL, BAD_CAST "dir", NULL); - - if (lang == NULL) { - g_print ("dir %s is null\n", dirname); - lang = "C"; - } - - xmlNewProp (priv->ins, BAD_CAST "lang", BAD_CAST lang); - - xmlNewProp (priv->ins, BAD_CAST "mtime", BAD_CAST mtime_str); - xmlAddChild (priv->ins, xmlNewText (BAD_CAST "\n ")); - xmlNewChild (priv->ins, NULL, BAD_CAST "name", BAD_CAST dirname); - xmlAddChild (priv->ins, xmlNewText (BAD_CAST "\n ")); - xmlAddChild (priv->ins->parent, xmlNewText (BAD_CAST "\n ")); - - while ((filename = (gchar *) g_dir_read_name (dir))) { - - xmlNewChild (priv->ins, NULL, BAD_CAST "page", BAD_CAST filename); - xmlAddChild (priv->ins, xmlNewText (BAD_CAST "\n ")); - - add_man_page_to_toc (pager, dirname, filename); - priv->manpage_count++; - } - - priv->ins = priv->ins->parent; - - g_dir_close (dir); - } - - priv->mandir_langpath = g_slist_next (priv->mandir_langpath); - - } else { - priv->mandir_ptr = g_slist_next (priv->mandir_ptr); - - if (priv->mandir_ptr && priv->mandir_ptr->data) { - priv->mandir_langpath = priv->mandir_ptr->data; - - if (priv->man_manhash) { - g_hash_table_destroy (priv->man_manhash); - priv->man_manhash = NULL; - } - } else { /* no more entries to prcoess, write file & cleanup */ - GSList *listptr = priv->mandir_list; - xmlNodePtr copynode; - - while (listptr && listptr->data) { - GSList *langptr = listptr->data; - - while (langptr && langptr->data) { - g_free (langptr->data); - langptr = g_slist_next (langptr); - } - - g_slist_free (listptr->data); - - listptr = g_slist_next (listptr); - } - - g_slist_free (priv->mandir_list); - - create_manindex_file (index_file, priv->manindex_xml); - - xmlFree (priv->manindex_xml); - - copynode = xmlCopyNode (xmlDocGetRootElement (priv->man_doc), 1); - xmlAddChild (xmlDocGetRootElement(priv->toc_doc), copynode); - - xmlFreeDoc (priv->man_doc); - - /* done processing */ - return FALSE; - } - } - - return TRUE; -#endif - - mynode = xmlCopyNode (xmlDocGetRootElement (priv->man_doc), 1); - xmlAddChild (xmlDocGetRootElement (priv->toc_doc), mynode); - - xmlFreeDoc (priv->man_doc); - - return FALSE; -} -#endif // ENABLE_MAN - -#ifdef ENABLE_INFO - -static int -spoon_info_add_document (SpoonInfoEntry *entry, void *user_data) -{ - xmlNodePtr node = (xmlNodePtr) user_data; - xmlNodePtr new; - gchar tmp[255]; - new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL); - if (entry->section) - g_sprintf(&tmp, "info:%s#%s", entry->name, entry->section); - else - g_sprintf(&tmp, "info:%s", entry->name); - xmlNewNsProp (new, NULL, BAD_CAST "href", BAD_CAST tmp); - xmlNewTextChild (new, NULL, BAD_CAST "title", BAD_CAST entry->name); - xmlNewTextChild (new, NULL, BAD_CAST "description", BAD_CAST entry->comment); - return TRUE; - -} - - -static gboolean -process_info_pending (YelpTocPager *pager) -{ - xmlNodePtr node = NULL; - xmlNodePtr cat_node = NULL; - xmlNodePtr mynode = NULL; - char **categories = NULL; - char **cat_iter = NULL; - int sectno = 0; - YelpTocPagerPriv * priv = pager->priv; - int i; - xmlXPathContextPtr xpath; - xmlXPathObjectPtr obj; - - priv->info_doc = xmlCtxtReadFile (priv->parser, - DATADIR "/yelp/info.xml", NULL, - XML_PARSE_NOBLANKS | - XML_PARSE_NOCDATA | - XML_PARSE_NOENT | - XML_PARSE_NOERROR | - XML_PARSE_NONET ); - - xpath = xmlXPathNewContext (priv->info_doc); - obj = xmlXPathEvalExpression (BAD_CAST "//toc", xpath); - node = obj->nodesetval->nodeTab[0]; - for (i=0; i < obj->nodesetval->nodeNr; i++) { - xmlNodePtr tmpnode = obj->nodesetval->nodeTab[i]; - xml_trim_titles (tmpnode, BAD_CAST "title"); - xml_trim_titles (tmpnode, BAD_CAST "description"); - } - xmlXPathFreeObject (obj); - xmlXPathFreeContext (xpath); - - categories = spoon_info_get_categories (); - cat_iter = categories; - - while (cat_iter && *cat_iter) { - char *tmp; - - cat_node = xmlNewChild (node, NULL, BAD_CAST "toc", - NULL); - tmp = g_strdup_printf ("%d", sectno); - xmlNewNsProp (cat_node, NULL, BAD_CAST "sect", - BAD_CAST tmp); - g_free (tmp); - tmp = g_strdup_printf ("infosect%d", sectno); - xmlNewNsProp (cat_node, NULL, BAD_CAST "id", - BAD_CAST tmp); - g_free (tmp); - sectno++; - xmlNewTextChild (cat_node, NULL, BAD_CAST "title", - BAD_CAST *cat_iter); - - spoon_info_for_each_in_category (*cat_iter, spoon_info_add_document, - cat_node); - cat_iter++; - } - - mynode = xmlCopyNode (xmlDocGetRootElement (priv->info_doc), 1); - xmlAddChild (xmlDocGetRootElement (priv->toc_doc), mynode); - - xmlFreeDoc (priv->info_doc); - - -#if 0 - gchar ** info_paths = yelp_get_info_paths (); - int i = 0; - gchar *filename = NULL; - xmlNodePtr mynode = NULL; - - GHashTable *info_parsed = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_free); - GHashTable *categories = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - - YelpTocPagerPriv *priv = YELP_TOC_PAGER (pager)->priv; - xmlNodePtr node = NULL; - printf ("Info parsing\n"); - for (i=0; info_paths[i]; i++) { - filename = g_strconcat (info_paths[i], "/dir", NULL); - - /* Search out the directory listing for info and follow that */ - if (!g_file_test (filename, G_FILE_TEST_EXISTS)) { - g_free (filename); - continue; - } else { - GIOChannel *channel; - gchar *str = NULL; - gsize len; - gchar ** files; - gchar ** ptr; - xmlNodePtr tmp; - xmlNodePtr new_node = NULL; - gboolean menufound = FALSE; - - if (!priv->info_doc) { - xmlXPathContextPtr xpath; - xmlXPathObjectPtr obj; - priv->info_doc = xmlCtxtReadFile (priv->parser, DATADIR "/yelp/info.xml", NULL, - XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | - XML_PARSE_NOENT | XML_PARSE_NOERROR | - XML_PARSE_NONET ); - - xpath = xmlXPathNewContext (priv->info_doc); - obj = xmlXPathEvalExpression (BAD_CAST "//toc", xpath); - node = obj->nodesetval->nodeTab[0]; - for (i=0; i < obj->nodesetval->nodeNr; i++) { - xmlNodePtr tmpnode = obj->nodesetval->nodeTab[i]; - xml_trim_titles (tmpnode, BAD_CAST "title"); - xml_trim_titles (tmpnode, BAD_CAST "description"); - } - xmlXPathFreeObject (obj); - xmlXPathFreeContext (xpath); - } - - channel = yelp_io_channel_new_file (filename, NULL); - g_io_channel_read_to_end (channel, &str, &len, NULL); - g_io_channel_shutdown (channel, FALSE, NULL); - g_io_channel_unref (channel); - - files = g_strsplit (str, "\n", -1); - - for (ptr = files; *ptr != NULL; ptr++) { - if (!menufound) { - if (g_str_has_prefix (*ptr, "* Menu:")) { - menufound = TRUE; - } - } else { - if (g_str_has_prefix (*ptr, "*")) { - /* A menu item */ - gchar *tooltip = NULL; - gchar *fname = NULL; - gchar *desc = NULL; - gchar *part1 = NULL, *part2 = NULL, *part3 = NULL; - gchar *path = *ptr; - gchar **nextline = ptr; - gchar *p = NULL; - nextline++; - /* Due to braindead info stuff, we gotta manually - * split everything up... - */ - path++; - if (!path) - goto done; - part1 = strchr (path, ':'); - if (!part1) - goto done; - part2 = g_strndup (path, part1-path); - p = g_strdup (part2); - p = g_strstrip (p); - tooltip = g_strdup_printf (_("Read info page for %s"), p); - g_free (p); - path = part1+1; - part1 = strchr (path, ')'); - if (!part1) - goto done; - part1 = strchr (part1, '.'); - if (!part1) - goto done; - part3 = g_strndup (path, part1-path); - part1++; - desc = g_strdup (part1); - g_strstrip (desc); - - fname = g_strconcat ("info:", g_strstrip(part3), NULL); - - if (!g_hash_table_lookup (info_parsed, fname)) { - g_hash_table_insert (info_parsed, - g_strdup (fname), - g_strdup (part1)); - - while (*nextline && - g_ascii_isspace (**nextline)) { - gchar *newbit = g_strdup (*nextline); - gchar *olddesc = desc; - g_strstrip (newbit); - desc = g_strconcat (desc, " ",newbit, NULL); - nextline++; - g_free (newbit); - g_free (olddesc); - } - ptr = --nextline; - - tmp = xmlNewChild (new_node, NULL, BAD_CAST "doc", - NULL); - xmlNewNsProp (tmp, NULL, BAD_CAST "href", BAD_CAST fname); - - xmlNewTextChild (tmp, NULL, BAD_CAST "title", - BAD_CAST part2); - xmlNewTextChild (tmp, NULL, BAD_CAST "tooltip", - BAD_CAST tooltip); - - xmlNewTextChild (tmp, NULL, BAD_CAST "description", - BAD_CAST desc); - } - done: - g_free (part2); - g_free (part3); - g_free (tooltip); - g_free (desc); - g_free (fname); - } else if (!g_ascii_isspace (**ptr) && g_ascii_isprint(**ptr)){ - new_node = g_hash_table_lookup (categories, *ptr); - if (!new_node) { - gchar *tmp; - - /* A new section */ - static int sectno = 1; - new_node = xmlNewChild (node, NULL, BAD_CAST "toc", - NULL); - tmp = g_strdup_printf ("%d", sectno); - xmlNewNsProp (new_node, NULL, BAD_CAST "sect", - BAD_CAST tmp); - g_free (tmp); - tmp = g_strdup_printf ("infosect%d", sectno); - xmlNewNsProp (new_node, NULL, BAD_CAST "id", - BAD_CAST tmp); - g_free (tmp); - sectno++; - xmlNewTextChild (new_node, NULL, BAD_CAST "title", - BAD_CAST *ptr); - g_hash_table_insert (categories, - g_strdup (*ptr), - new_node); - } - - } - } - } - g_free (filename); - g_free (str); - g_strfreev (files); - } - } - g_hash_table_destroy (info_parsed); - g_hash_table_destroy (categories); - - mynode = xmlCopyNode (xmlDocGetRootElement (priv->info_doc), 1); - xmlAddChild (xmlDocGetRootElement (priv->toc_doc), mynode); - - xmlFreeDoc (priv->info_doc); - -#endif - return FALSE; -} -#endif /* ENABLE_INFO */ - -static int -spoon_add_document (void *reg, void * user_data) -{ - xmlNodePtr node = (xmlNodePtr) user_data; - SpoonReg *r = (SpoonReg *) reg; - xmlNodePtr new; - gchar tmp[10]; - - new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL); - xmlNewNsProp (new, NULL, BAD_CAST "href", BAD_CAST r->uri); - xmlNewTextChild (new, NULL, BAD_CAST "title", BAD_CAST r->name); - xmlNewTextChild (new, NULL, BAD_CAST "description", BAD_CAST r->comment); - g_sprintf (&tmp, "%d", r->weight); - xmlNewNsProp (new, NULL, BAD_CAST "weight", BAD_CAST tmp); - return FALSE; -} - -static gboolean -process_read_menu (YelpTocPager *pager) -{ - xmlTextReaderPtr reader; - xmlXPathContextPtr xpath; - xmlXPathObjectPtr obj; - GError *error = NULL; - gint i, ret; - - YelpTocPagerPriv *priv = pager->priv; - - priv->toc_doc = xmlCtxtReadFile (priv->parser, DATADIR "/yelp/toc.xml", NULL, - XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | - XML_PARSE_NOENT | XML_PARSE_NOERROR | - XML_PARSE_NONET ); - if (!priv->toc_doc) { - g_set_error (&error, YELP_ERROR, YELP_ERROR_NO_TOC, - _("The table of contents could not be loaded. The file " - "‘%s’ is either missing or is not well-formed XML."), - DATADIR "/yelp/toc.xml"); - yelp_pager_error (YELP_PAGER (pager), error); - priv->cancel = TRUE; - return FALSE; - } - - xpath = xmlXPathNewContext (priv->toc_doc); - obj = xmlXPathEvalExpression (BAD_CAST "//toc", xpath); - for (i = 0; i < obj->nodesetval->nodeNr; i++) { - xmlNodePtr node = obj->nodesetval->nodeTab[i]; - xmlChar *icon = NULL; -#if 0 - xmlChar *id = NULL; - xmlNodePtr cmdhelp; - xmlNodePtr newnode; - id = xmlGetProp (node, BAD_CAST "id"); - if (!xmlStrcmp (id, BAD_CAST "index")) { - cmdhelp = xmlNewChild (node, NULL, BAD_CAST "toc", NULL); - xmlNewNsProp (cmdhelp, NULL, BAD_CAST "id", BAD_CAST "ManInfoHolder"); - xmlNewChild (cmdhelp, NULL, BAD_CAST "title", - BAD_CAST _("Command Line Help")); -#ifdef ENABLE_MAN - newnode = xmlNewChild (cmdhelp, NULL, BAD_CAST "toc", NULL); - xmlNewNsProp (newnode, NULL, BAD_CAST "id", BAD_CAST "Man"); - xmlNewChild (newnode, NULL, BAD_CAST "title", - BAD_CAST _("Manual Pages")); -#endif // ENABLE_MAN -#ifdef ENABLE_INFO - newnode = xmlNewChild (cmdhelp, NULL, BAD_CAST "toc", NULL); - xmlNewNsProp (newnode, NULL, BAD_CAST "id", BAD_CAST "Info"); - xmlNewChild (newnode, NULL, BAD_CAST "title", - BAD_CAST _("GNU Info Pages")); -#endif //ENABLE_INFO - } - xmlFree (id); -#endif //ENABLE_MAN_OR_INFO - - xml_trim_titles (node, BAD_CAST "title"); - xml_trim_titles (node, BAD_CAST "description"); - - icon = xmlGetProp (node, BAD_CAST "icon"); - if (icon) { - GtkIconInfo *info; - GtkIconTheme *theme = - (GtkIconTheme *) yelp_settings_get_icon_theme (); - info = gtk_icon_theme_lookup_icon (theme, (gchar *) icon, 48, 0); - if (info) { - xmlNodePtr new = xmlNewChild (node, NULL, BAD_CAST "icon", - NULL); - xmlNewNsProp (new, NULL, BAD_CAST "file", - BAD_CAST gtk_icon_info_get_filename (info)); - gtk_icon_info_free (info); - } - } - xmlFree (icon); - - } - xmlXPathFreeObject (obj); - - /* here we populate the category_hash structure of the YelpTocPager's - * private data. The hash key is a scrollkeeper category defined in the - * scrollkeeper.xml file and the value is a pointer to the parent node. - */ - reader = xmlReaderForFile (DATADIR "/yelp/scrollkeeper.xml", NULL, - XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | - XML_PARSE_NOENT | XML_PARSE_NOERROR | - XML_PARSE_NONET ); - ret = xmlTextReaderRead (reader); - while (ret == 1) { - if (!xmlStrcmp (xmlTextReaderConstLocalName (reader), - BAD_CAST "toc")) { - xmlChar *id = xmlTextReaderGetAttribute (reader, BAD_CAST "id"); - xmlNodePtr node; - gchar *xpath_s; - - if (!id) { - ret = xmlTextReaderRead (reader); - continue; - } - - xpath_s = g_strdup_printf ("//toc[@id = '%s']", id); - obj = xmlXPathEvalExpression (BAD_CAST xpath_s, xpath); - g_free (xpath_s); - - node = obj->nodesetval->nodeTab[0]; - xmlXPathFreeObject (obj); - - ret = xmlTextReaderRead (reader); - while (ret == 1) { - if (!xmlStrcmp (xmlTextReaderConstLocalName (reader), - BAD_CAST "subject")) { - xmlChar *cat = xmlTextReaderGetAttribute (reader, - BAD_CAST "category"); - /*g_hash_table_insert (priv->category_hash, - g_strdup ((gchar *) cat), - node);*/ - spoon_for_each_in_category (spoon_add_document, - (char *) cat, - (void *) node); - xmlFree (cat); - } - else if (!xmlStrcmp (xmlTextReaderConstLocalName (reader), - BAD_CAST "toc")) { - break; - } - ret = xmlTextReaderRead (reader); - } - - xmlFree (id); - ret = xmlTextReaderRead (reader); - } else { - ret = xmlTextReaderRead (reader); - } - } - xmlFreeTextReader (reader); - xmlXPathFreeContext (xpath); - - return FALSE; -} - -static gboolean -process_xslt (YelpTocPager *pager) -{ - GError *error = NULL; - xmlDocPtr outdoc = NULL; - YelpTocPagerPriv *priv = pager->priv; - gchar **params = NULL; - gint params_i = 0; - gint params_max = 10; - GtkIconInfo *info; - GtkIconTheme *theme = (GtkIconTheme *) yelp_settings_get_icon_theme (); - - if (!priv->toc_doc) - return FALSE; - - /* only create and parse the stylesheet on the first call to this function */ - if (!priv->stylesheet) { - priv->stylesheet = xsltParseStylesheetFile (BAD_CAST TOC_STYLESHEET); - } - - if (!priv->stylesheet) { - g_set_error (&error, YELP_ERROR, YELP_ERROR_PROC, - _("The table of contents could not be processed. The " - "file ‘%s’ is either missing or is not a valid XSLT " - "stylesheet."), - TOC_STYLESHEET); - yelp_pager_error (YELP_PAGER (pager), error); - goto done; - } - - priv->transformContext = xsltNewTransformContext (priv->stylesheet, - priv->toc_doc); - priv->transformContext->_private = pager; - xsltRegisterExtElement (priv->transformContext, - BAD_CAST "document", - BAD_CAST YELP_NAMESPACE, - (xsltTransformFunction) xslt_yelp_document); - - params = g_new0 (gchar *, params_max); - yelp_settings_params (¶ms, ¶ms_i, ¶ms_max); - - if ((params_i + 10) >= params_max - 1) { - params_max += 10; - params = g_renew (gchar *, params, params_max); - } - - info = gtk_icon_theme_lookup_icon (theme, "yelp-icon-big", 192, 0); - if (info) { - params[params_i++] = "help_icon"; - params[params_i++] = g_strdup_printf ("\"%s\"", - gtk_icon_info_get_filename (info)); - params[params_i++] = "help_icon_size"; - params[params_i++] = g_strdup_printf ("%i", - gtk_icon_info_get_base_size (info)); - gtk_icon_info_free (info); - } - - params[params_i++] = NULL; - - outdoc = xsltApplyStylesheetUser (priv->stylesheet, - priv->toc_doc, - (const gchar **)params, NULL, NULL, - priv->transformContext); - /* Don't do this */ - g_signal_emit_by_name (pager, "finish"); - - done: - if (params) { - for (params_i = 0; params[params_i] != NULL; params_i++) - if (params_i % 2 == 1) - g_free ((gchar *) params[params_i]); - } - if (outdoc) - xmlFreeDoc (outdoc); - if (priv->toc_doc) { - xmlFreeDoc (priv->toc_doc); - priv->toc_doc = NULL; - } - if (priv->transformContext) { - xsltFreeTransformContext (priv->transformContext); - priv->transformContext = NULL; - } - - return FALSE; -} - -static gboolean -process_cleanup (YelpTocPager *pager) -{ - YelpTocPagerPriv *priv = pager->priv; - - /* dump the toc_doc if we are debugging */ - /*d (xmlDocDump (stdout, priv->toc_doc)); */ - -#ifdef ENABLE_MAN - /* clean up the man directory language hash table */ - if (priv->man_dirlang) { - g_hash_table_destroy (priv->man_dirlang); - priv->man_dirlang = NULL; - } - - /* clean up the man page section hash table */ - if (priv->man_secthash) { - g_hash_table_destroy (priv->man_secthash); - priv->man_secthash = NULL; - } -#endif - - /* cleanup the stylesheet used to process the toc */ - if (priv->stylesheet) { - xsltFreeStylesheet (priv->stylesheet); - priv->stylesheet = NULL; - } - - /* cleanup the parser context */ - if (priv->parser) { - xmlFreeParserCtxt (priv->parser); - priv->parser = NULL; - } - - /* we only ever want to run this function once, so always return false */ - return FALSE; -} - -static void -toc_add_doc_info (YelpTocPager *pager, YelpDocInfo *doc_info) -{ - xmlNodePtr node; - xmlNodePtr new; - gchar *text; - gchar *category; - - g_return_if_fail (pager != NULL); - if (doc_info == NULL) - return; - - /* check if the document category exists, and return if it does not - * should fix 353554 */ - category = yelp_doc_info_get_category (doc_info); - if (category == NULL) { - debug_print (DB_DEBUG, "Missing category for %s\n", - yelp_doc_info_get_title (doc_info)); - return; - } - - YelpTocPagerPriv *priv = pager->priv; - - g_hash_table_insert (priv->unique_hash, - (gchar *) yelp_doc_info_get_id (doc_info), - doc_info); - - node = g_hash_table_lookup (priv->category_hash, category); - - text = yelp_doc_info_get_uri (doc_info, NULL, YELP_URI_TYPE_FILE); - new = xmlNewChild (node, NULL, BAD_CAST "doc", NULL); - xmlNewNsProp (new, NULL, BAD_CAST "href", BAD_CAST text); - g_free (text); - - text = (gchar *) yelp_doc_info_get_title (doc_info); - xmlNewTextChild (new, NULL, BAD_CAST "title", BAD_CAST text); - - text = (gchar *) yelp_doc_info_get_description (doc_info); - xmlNewTextChild (new, NULL, BAD_CAST "description", BAD_CAST text); -} - -static void -toc_remove_doc_info (YelpTocPager *pager, YelpDocInfo *doc_info) -{ -#if 0 - GSList *category; - YelpTocPagerPriv *priv = pager->priv; - - g_hash_table_remove (pager->priv->unique_hash, meta->id); - - for (category = meta->categories; category; category = category->next) { - gchar *catstr = (gchar *) category->data; - GSList *metas = - (GSList *) g_hash_table_lookup (pager->priv->category_hash, catstr); - - metas = g_slist_remove (metas, meta); - if (metas) - g_hash_table_insert (pager->priv->category_hash, - g_strdup (catstr), metas); - else - g_hash_table_remove (pager->priv->category_hash, catstr); - } - - priv->idx_pending = g_slist_remove (priv->idx_pending, meta); -#endif -} - -static 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; - xmlDtdPtr dtd; - - if (!ctxt || !node || !inst || !comp) - return; - - pager = (YelpPager *) ctxt->_private; - - 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; - } - - 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 = FALSE; - - new_doc = xmlNewDoc (BAD_CAST "1.0"); - dtd = xmlCreateIntSubset (new_doc, - BAD_CAST "html", - BAD_CAST "-//W3C//DTD XHTML 1.0 Strict//EN", - BAD_CAST "http://www.w3.org/TR/" - "xhtml1/DTD/xhtml1-strict.dtd"); - new_doc->intSubset = dtd; - new_doc->extSubset = dtd; - new_doc->charset = XML_CHAR_ENCODING_UTF8; - new_doc->encoding = xmlStrdup (BAD_CAST "utf-8"); - 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); - - xsltSaveResultToString (&page_buf, &buf_size, new_doc, style); - - ctxt->outputFile = old_outfile; - ctxt->output = old_doc; - ctxt->insert = old_insert; - - for (cur = node->children; cur; cur = cur->next) { - if (!xmlStrcmp (cur->name, BAD_CAST "title")) { - page_title = xmlNodeGetContent (cur); - break; - } - } - - page = g_new0 (YelpPage, 1); - - if (page_id) { - page->page_id = g_strdup ((gchar *) page_id); - xmlFree (page_id); - } - if (page_title) { - page->title = g_strdup ((gchar *) page_title); - xmlFree (page_title); - } else { - page->title = g_strdup (_("Help Contents")); - } - page->contents = (gchar *) 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, BAD_CAST "rel"); - - if (!xmlStrcmp (rel, (xmlChar *) "Previous")) - page->prev_id = (gchar *) xmlGetProp (cur, - BAD_CAST "href"); - else if (!xmlStrcmp (rel, (xmlChar *) "Next")) - page->next_id = (gchar *) xmlGetProp (cur, - BAD_CAST "href"); - else if (!xmlStrcmp (rel, (xmlChar *) "Top")) - page->toc_id = (gchar *) xmlGetProp (cur, - BAD_CAST "href"); - - xmlFree (rel); - } - } - break; - } - } - - yelp_pager_add_page (pager, page); - g_signal_emit_by_name (pager, "page", page->page_id); - - done: - if (new_doc) - xmlFreeDoc (new_doc); - if (style) - xsltFreeStylesheet (style); -} - -static void -xml_trim_titles (xmlNodePtr node, xmlChar * nodetype) -{ - xmlNodePtr cur, keep = NULL; - xmlChar *keep_lang = NULL; - int j, keep_pri = INT_MAX; - - const gchar * const * langs = g_get_language_names (); - - for (cur = node->children; cur; cur = cur->next) { - if (!xmlStrcmp (cur->name, nodetype)) { - xmlChar *cur_lang = NULL; - int cur_pri = INT_MAX; - cur_lang = xmlNodeGetLang (cur); - if (cur_lang) { - for (j = 0; langs[j]; j++) { - if (g_str_equal (cur_lang, langs[j])) { - cur_pri = j; - break; - } - } - } else { - cur_pri = INT_MAX - 1; - } - if (cur_pri <= keep_pri) { - if (keep_lang) - xmlFree (keep_lang); - keep_lang = cur_lang; - keep_pri = cur_pri; - keep = cur; - } else { - if (cur_lang) - xmlFree (cur_lang); - } - } - } - cur = node->children; - while (cur) { - xmlNodePtr this = cur; - cur = cur->next; - if (!xmlStrcmp (this->name, nodetype)) { - if (this != keep) { - xmlUnlinkNode (this); - xmlFreeNode (this); - } - } - } - xmlFree (keep_lang); -} |