diff options
Diffstat (limited to 'src/yelp-db-pager.c')
-rw-r--r-- | src/yelp-db-pager.c | 605 |
1 files changed, 0 insertions, 605 deletions
diff --git a/src/yelp-db-pager.c b/src/yelp-db-pager.c deleted file mode 100644 index 800ff5f0..00000000 --- a/src/yelp-db-pager.c +++ /dev/null @@ -1,605 +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 <glib.h> -#include <glib/gi18n.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-db-pager.h" -#include "yelp-toc-pager.h" -#include "yelp-settings.h" -#include "yelp-debug.h" - -#define STYLESHEET_PATH DATADIR"/yelp/xslt/" -#define DB_STYLESHEET STYLESHEET_PATH"db2html.xsl" - -#define BOOK_CHUNK_DEPTH 2 -#define ARTICLE_CHUNK_DEPTH 1 - -#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; - -#define YELP_DB_PAGER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_DB_PAGER, YelpDBPagerPriv)) - -struct _YelpDBPagerPriv { - GtkTreeModel *sects; - GHashTable *frags_hash; - - gint max_depth; - gchar *root_id; -}; - -typedef struct _DBWalker DBWalker; -struct _DBWalker { - YelpDBPager *pager; - gchar *page_id; - - xmlDocPtr doc; - xmlNodePtr cur; - - GtkTreeIter *iter; - - gint depth; - gint max_depth; - -}; - -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_cancel (YelpPager *pager); -static xmlDocPtr db_pager_parse (YelpPager *pager); -static gchar ** db_pager_params (YelpPager *pager); - -static const gchar * db_pager_resolve_frag (YelpPager *pager, - const gchar *frag_id); -static GtkTreeModel * db_pager_get_sections (YelpPager *pager); - -static void walker_walk_xml (DBWalker *walker); - -static gboolean node_is_chunk (DBWalker *walker); -static gboolean node_is_division (DBWalker *walker); -static gchar * node_get_title (DBWalker *walker, - gchar *type); - -xmlNodePtr node_find_child (xmlNodePtr parent, - gchar *child_name); - -static YelpPagerClass *parent_class; - -GType -yelp_db_pager_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (YelpDBPagerClass), - NULL, - NULL, - (GClassInitFunc) db_pager_class_init, - NULL, - NULL, - sizeof (YelpDBPager), - 0, - (GInstanceInitFunc) db_pager_init, - }; - type = g_type_register_static (YELP_TYPE_XSLT_PAGER, - "YelpDBPager", - &info, 0); - } - return type; -} - -static void -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->cancel = db_pager_cancel; - - 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; - - g_type_class_add_private (klass, sizeof (YelpDBPagerPriv)); -} - -static void -db_pager_init (YelpDBPager *pager) -{ - pager->priv = YELP_DB_PAGER_GET_PRIVATE (pager); - - pager->priv->sects = NULL; - - pager->priv->frags_hash = - g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - pager->priv->root_id = NULL; -} - -static void -db_pager_dispose (GObject *object) -{ - YelpDBPager *pager = YELP_DB_PAGER (object); - - g_object_unref (pager->priv->sects); - g_hash_table_destroy (pager->priv->frags_hash); - - g_free (pager->priv->root_id); - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -/******************************************************************************/ - -YelpPager * -yelp_db_pager_new (YelpDocInfo *doc_info) -{ - YelpDBPager *pager; - - g_return_val_if_fail (doc_info != NULL, NULL); - - pager = (YelpDBPager *) g_object_new (YELP_TYPE_DB_PAGER, - "document-info", doc_info, - NULL); - - g_hash_table_insert (pager->priv->frags_hash, - g_strdup ("x-yelp-titlepage"), - g_strdup ("x-yelp-titlepage")); - - if (!pager->priv->sects) - pager->priv->sects = - GTK_TREE_MODEL (gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_STRING)); - - return (YelpPager *) pager; -} - -static xmlDocPtr -db_pager_parse (YelpPager *pager) -{ - YelpDBPagerPriv *priv; - YelpDocInfo *doc_info; - gchar *filename = NULL; - - xmlParserCtxtPtr parserCtxt = NULL; - xmlDocPtr doc = NULL; - - DBWalker *walker = NULL; - xmlChar *id; - GError *error = NULL; - - debug_print (DB_FUNCTION, "entering\n"); - - doc_info = yelp_pager_get_doc_info (pager); - - 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); - - parserCtxt = xmlNewParserCtxt (); - doc = xmlCtxtReadFile (parserCtxt, - (const char *) filename, NULL, - XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA | - XML_PARSE_NOENT | XML_PARSE_NONET ); - if (doc == NULL) { - g_set_error (&error, YELP_GERROR, YELP_ERROR_NO_DOC, - _("The file ā%sā could not be parsed. Either the file " - "does not exist, or it is not well-formed XML."), - filename); - yelp_pager_error (pager, error); - goto done; - } - - 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 = doc; - walker->cur = xmlDocGetRootElement (walker->doc); - - if (!xmlStrcmp (xmlDocGetRootElement (doc)->name, BAD_CAST "book")) - priv->max_depth = walker->max_depth = BOOK_CHUNK_DEPTH; - else - priv->max_depth = walker->max_depth = ARTICLE_CHUNK_DEPTH; - - id = xmlGetProp (walker->cur, BAD_CAST "id"); - if (id) - priv->root_id = g_strdup ((gchar *) id); - else { - priv->root_id = g_strdup ("index"); - /* add the id attribute to the root element with value "index" - * so when we try to load the document later, it doesn't fail */ - xmlNewProp (walker->cur, BAD_CAST "id", BAD_CAST "index"); - } - - EVENTS_PENDING; - CANCEL_CHECK; - - walker_walk_xml (walker); - - done: - g_free (walker); - - g_free (filename); - - if (parserCtxt) - xmlFreeParserCtxt (parserCtxt); - - g_object_unref (pager); - - return doc; -} - -static gchar ** -db_pager_params (YelpPager *pager) -{ - YelpDBPagerPriv *priv; - gchar **params; - gint params_i = 0; - gint params_max = 20; - - debug_print (DB_FUNCTION, "entering\n"); - - 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; - - params = g_new0 (gchar *, params_max); - - yelp_settings_params (¶ms, ¶ms_i, ¶ms_max); - - if ((params_i + 10) >= params_max - 1) { - params_max += 20; - params = g_renew (gchar *, params, params_max); - } - params[params_i++] = "db.chunk.extension"; - params[params_i++] = g_strdup ("\"\""); - params[params_i++] = "db.chunk.info_basename"; - params[params_i++] = g_strdup ("\"x-yelp-titlepage\""); - params[params_i++] = "db.chunk.max_depth"; - params[params_i++] = g_strdup_printf ("%i", priv->max_depth); - params[params_i++] = "yelp.javascript"; - params[params_i++] = g_strdup_printf ("\"%s\"", DATADIR "/yelp/yelp.js"); - - params[params_i] = NULL; - - return params; -} - -static void -db_pager_cancel (YelpPager *pager) -{ - YelpDBPagerPriv *priv = YELP_DB_PAGER (pager)->priv; - - debug_print (DB_FUNCTION, "entering\n"); - - yelp_pager_set_state (pager, YELP_PAGER_STATE_INVALID); - - gtk_tree_store_clear (GTK_TREE_STORE (priv->sects)); - g_hash_table_foreach_remove (priv->frags_hash, (GHRFunc) gtk_true, NULL); - - g_free (priv->root_id); - priv->root_id = NULL; - - YELP_PAGER_CLASS (parent_class)->cancel (pager); -} - -static const gchar * -db_pager_resolve_frag (YelpPager *pager, const gchar *frag_id) -{ - YelpDBPager *db_pager; - gchar *page_id = NULL; - - g_return_val_if_fail (pager != NULL, NULL); - g_return_val_if_fail (YELP_IS_DB_PAGER (pager), NULL); - - db_pager = YELP_DB_PAGER (pager); - - if (frag_id) - page_id = g_hash_table_lookup (db_pager->priv->frags_hash, - frag_id); - else - page_id = db_pager->priv->root_id; - - return (const gchar *) page_id; -} - -static GtkTreeModel * -db_pager_get_sections (YelpPager *pager) -{ - g_return_val_if_fail (pager != NULL, NULL); - g_return_val_if_fail (YELP_IS_DB_PAGER (pager), NULL); - - return YELP_DB_PAGER (pager)->priv->sects; -} - -/******************************************************************************/ - -static void -walker_walk_xml (DBWalker *walker) -{ - static gint autoid = 0; - gchar autoidstr[20]; - xmlChar *id = NULL; - xmlChar *title = NULL; - gchar *old_id = NULL; - xmlNodePtr cur; - xmlNodePtr old_cur; - GtkTreeIter iter; - GtkTreeIter *old_iter = NULL; - YelpDBPagerPriv *priv = walker->pager->priv; - - /* check for the yelp:chunk-depth processing instruction and set - * the max chunk depth accordingly */ - if (walker->depth == 0) { - cur = walker->cur; - for ( ; cur; cur = cur->prev) - if (cur->type == XML_PI_NODE) - if (!xmlStrcmp (cur->name, - (const xmlChar *) "yelp:chunk-depth")) { - gint max = atoi ((gchar *) cur->content); - if (max) - priv->max_depth = walker->max_depth = max; - break; - } - } - - id = xmlGetProp (walker->cur, BAD_CAST "id"); - if (!id && walker->cur->parent->type == XML_DOCUMENT_NODE) { - id = xmlStrdup (BAD_CAST "__yelp_toc"); - } - - if (node_is_chunk (walker)) { - title = BAD_CAST node_get_title (walker, "titleabbrev"); - if (!title) - title = BAD_CAST node_get_title (walker, "title"); - - /* if id attribute is not present, autogenerate a - * unique value, and insert it into the in-memory tree */ - if (!id) { - g_snprintf (autoidstr, 20, "_auto-gen-id-%d", ++autoid); - xmlNewProp (walker->cur, BAD_CAST "id", BAD_CAST autoidstr); - id = xmlGetProp (walker->cur, BAD_CAST "id"); - } - - if (id) { - gtk_tree_store_append (GTK_TREE_STORE (priv->sects), - &iter, walker->iter); - - gtk_tree_store_set (GTK_TREE_STORE (priv->sects), - &iter, - YELP_PAGER_COLUMN_ID, id, - YELP_PAGER_COLUMN_TITLE, title, - -1); - - old_id = walker->page_id; - walker->page_id = (gchar *) id; - - old_iter = walker->iter; - - if (walker->cur->parent->type != XML_DOCUMENT_NODE) - walker->iter = &iter; - } - } - - while (gtk_events_pending ()) - gtk_main_iteration (); - /* FIXME : check for cancel */ - - old_cur = walker->cur; - walker->depth++; - - if (id) { - g_hash_table_insert (priv->frags_hash, - g_strdup ((gchar *) id), - g_strdup (walker->page_id)); - } - - cur = walker->cur->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - walker->cur = cur; - walker_walk_xml (walker); - } - cur = cur->next; - } - - walker->depth--; - walker->cur = old_cur; - - if (node_is_chunk (walker) && id) { - walker->iter = old_iter; - - walker->page_id = old_id; - } - - if (id != NULL) - xmlFree (id); - if (title != NULL) - xmlFree (title); -} - -xmlNodePtr -node_find_child (xmlNodePtr parent, gchar *child_name) -{ - xmlNodePtr child = (xmlNodePtr) parent->children; - - while (child) { - if (!xmlStrcmp (child->name, BAD_CAST child_name)) - break; - child = child->next; - } - return child; -} - - -static gchar * -node_get_title (DBWalker *walker, gchar *type) -{ - gchar *title = NULL; - xmlChar *node_name = (xmlChar *) walker->cur->name; - xmlNodePtr child = NULL; - xmlNodePtr title_node = NULL; - - if (xmlStrcmp (node_name, BAD_CAST "refentry")) { - /*refentry is special cased below */ - title_node = node_find_child (walker->cur, type); - if (!title_node) { - /* Gotta look for some other way of getting the title */ - gchar *looking_for = g_strdup_printf ("%sinfo", node_name); - - child = node_find_child (walker->cur, looking_for); - g_free (looking_for); - - if (child) - title_node = node_find_child (child, type); - } - } else { - /* Refentry */ - xmlNodePtr refentry = NULL; - xmlNodePtr refmeta = NULL; - xmlNodePtr refnamediv = NULL; - xmlNodePtr child = walker->cur->children; - - while (child) { - if (!xmlStrcmp (child->name, BAD_CAST "refmeta")) - refmeta = child; - else if (!xmlStrcmp (child->name, BAD_CAST "refentryinfo")) - refentry = child; - else if (!xmlStrcmp (child->name, BAD_CAST "refnamediv")) - refnamediv = child; - else if (!xmlStrncmp (child->name, BAD_CAST "refsect", 7)) - break; - child = child->next; - - } - if (refmeta) { - xmlNodePtr tmp = node_find_child (refmeta, "refentrytitle"); - title_node = node_find_child (tmp, type); - } - if (!title_node && refentry) { - title_node = node_find_child (refentry, type); - } - if (!title_node) { - title_node = node_find_child (refnamediv, "refname"); - } - - } - /* Something pretty seriously screwy happened - * Try the fallback options - */ - if (!title_node) { - xmlNodePtr block = node_find_child (walker->cur, "blockinfo"); - if (block) { - title_node = node_find_child (block, type); - } - if (!title_node) { - xmlNodePtr obj = node_find_child (walker->cur, "objectinfo"); - if (obj) - title_node = node_find_child (obj, type); - } - } - - title = (gchar *) xmlNodeGetContent (title_node); - - return title; -} - -static gboolean -node_is_chunk (DBWalker *walker) -{ - if (walker->depth <= walker->max_depth) { - if (node_is_division (walker)) - return TRUE; - } - return FALSE; -} - -static gboolean -node_is_division (DBWalker *walker) -{ - xmlNodePtr node = walker->cur; - return (!xmlStrcmp (node->name, (const xmlChar *) "appendix") || - !xmlStrcmp (node->name, (const xmlChar *) "article") || - !xmlStrcmp (node->name, (const xmlChar *) "book") || - !xmlStrcmp (node->name, (const xmlChar *) "bibliography") || - !xmlStrcmp (node->name, (const xmlChar *) "chapter") || - !xmlStrcmp (node->name, (const xmlChar *) "colophon") || - !xmlStrcmp (node->name, (const xmlChar *) "glossary") || - !xmlStrcmp (node->name, (const xmlChar *) "index") || - !xmlStrcmp (node->name, (const xmlChar *) "part") || - !xmlStrcmp (node->name, (const xmlChar *) "preface") || - !xmlStrcmp (node->name, (const xmlChar *) "reference") || - !xmlStrcmp (node->name, (const xmlChar *) "refentry") || - !xmlStrcmp (node->name, (const xmlChar *) "refsect1") || - !xmlStrcmp (node->name, (const xmlChar *) "refsect2") || - !xmlStrcmp (node->name, (const xmlChar *) "refsect3") || - !xmlStrcmp (node->name, (const xmlChar *) "refsection") || - !xmlStrcmp (node->name, (const xmlChar *) "sect1") || - !xmlStrcmp (node->name, (const xmlChar *) "sect2") || - !xmlStrcmp (node->name, (const xmlChar *) "sect3") || - !xmlStrcmp (node->name, (const xmlChar *) "sect4") || - !xmlStrcmp (node->name, (const xmlChar *) "sect5") || - !xmlStrcmp (node->name, (const xmlChar *) "section") || - !xmlStrcmp (node->name, (const xmlChar *) "set") || - !xmlStrcmp (node->name, (const xmlChar *) "setindex") || - !xmlStrcmp (node->name, (const xmlChar *) "simplesect") ); -} |