summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun McCance <shaunm@gnome.org>2009-06-01 08:23:50 -0500
committerShaun McCance <shaunm@gnome.org>2009-06-01 08:23:50 -0500
commit567cb6853d3386ae269b80063f2a678e3237be85 (patch)
tree59699c86c01e4916addbe319dad2c729ae99e923
parent01131df242628986266c61fe5a38872310a9bad5 (diff)
downloadyelp-567cb6853d3386ae269b80063f2a678e3237be85.tar.gz
Adding stubs for Mallard support
-rw-r--r--src/Makefile.am2
-rw-r--r--src/yelp-mallard.c735
-rw-r--r--src/yelp-mallard.h53
-rw-r--r--src/yelp-utils.c54
-rw-r--r--src/yelp-utils.h1
-rw-r--r--src/yelp-window.c7
6 files changed, 829 insertions, 23 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 25d678d8..b8b8dccf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,6 +22,7 @@ yelp_SOURCES = \
yelp-toc.h yelp-toc.c \
yelp-docbook.h yelp-docbook.c \
yelp-db-print.c yelp-db-print.h \
+ yelp-mallard.h yelp-mallard.c \
yelp-man-parser.c yelp-man-parser.h \
yelp-man.c yelp-man.h \
yelp-info.c yelp-info.h \
@@ -113,6 +114,7 @@ test_document_SOURCES = \
yelp-document.c yelp-document.h \
yelp-error.c yelp-error.h \
yelp-io-channel.c yelp-io-channel.h \
+ yelp-mallard.c yelp-mallard.h \
yelp-man.c yelp-man.h \
yelp-man-parser.c yelp-man-parser.h \
yelp-page.c yelp-page.h \
diff --git a/src/yelp-mallard.c b/src/yelp-mallard.c
new file mode 100644
index 00000000..82648e92
--- /dev/null
+++ b/src/yelp-mallard.c
@@ -0,0 +1,735 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 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 <gtk/gtk.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xinclude.h>
+
+#include "yelp-error.h"
+#include "yelp-mallard.h"
+#include "yelp-settings.h"
+#include "yelp-transform.h"
+#include "yelp-debug.h"
+
+#define STYLESHEET DATADIR"/yelp/xslt/mal2html.xsl"
+
+#define YELP_MALLARD_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_MALLARD, YelpMallardPriv))
+
+struct _YelpMallardPriv {
+ gchar *directory;
+
+ GMutex *mutex;
+ GThread *thread;
+};
+
+
+static void mallard_class_init (YelpMallardClass *klass);
+static void mallard_init (YelpMallard *mallard);
+static void mallard_try_dispose (GObject *object);
+static void mallard_dispose (GObject *object);
+
+/* YelpDocument */
+static void mallard_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data);
+
+/* YelpTransform */
+static void transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpMallard *mallard);
+static void transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpMallard *mallard);
+static void transform_final_func (YelpTransform *transform,
+ YelpMallard *mallard);
+
+
+static YelpDocumentClass *parent_class;
+
+GType
+yelp_mallard_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpMallardClass),
+ NULL, NULL,
+ (GClassInitFunc) mallard_class_init,
+ NULL, NULL,
+ sizeof (YelpMallard),
+ 0,
+ (GInstanceInitFunc) mallard_init,
+ };
+ type = g_type_register_static (YELP_TYPE_DOCUMENT,
+ "YelpMallard",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+mallard_class_init (YelpMallardClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpDocumentClass *document_class = YELP_DOCUMENT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = mallard_try_dispose;
+
+ document_class->request = mallard_request;
+ document_class->cancel = NULL;
+
+ g_type_class_add_private (klass, sizeof (YelpMallardPriv));
+}
+
+static void
+mallard_init (YelpMallard *mallard)
+{
+ YelpMallardPriv *priv;
+ priv = mallard->priv = YELP_MALLARD_GET_PRIVATE (mallard);
+
+ priv->mutex = g_mutex_new ();
+}
+
+static void
+mallard_try_dispose (GObject *object)
+{
+ YelpMallardPriv *priv;
+
+ g_assert (object != NULL && YELP_IS_MALLARD (object));
+
+ priv = YELP_MALLARD (object)->priv;
+
+ /*
+ g_mutex_lock (priv->mutex);
+ if (priv->process_running || priv->transform_running) {
+ priv->state = DOCBOOK_STATE_STOP;
+ g_idle_add ((GSourceFunc) docbook_try_dispose, object);
+ g_mutex_unlock (priv->mutex);
+ } else {
+ g_mutex_unlock (priv->mutex);
+ docbook_dispose (object);
+ }
+ */
+ mallard_dispose (object);
+}
+
+static void
+mallard_dispose (GObject *object)
+{
+ YelpMallard *mallard = YELP_MALLARD (object);
+
+ g_free (mallard->priv->directory);
+
+ g_mutex_free (mallard->priv->mutex);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpDocument *
+yelp_mallard_new (gchar *directory)
+{
+ YelpMallard *mallard;
+
+ g_return_val_if_fail (directory != NULL, NULL);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " directory = \"%s\"\n", directory);
+
+ mallard = (YelpMallard *) g_object_new (YELP_TYPE_MALLARD, NULL);
+ mallard->priv->directory = g_strdup (directory);
+
+ /*
+ FIXME: find pages, add
+ yelp_document_add_page_id (YELP_DOCUMENT (docbook), "x-yelp-titlepage", "x-yelp-titlepage");
+ */
+
+ return (YelpDocument *) mallard;
+}
+
+
+#if 0
+static void
+docbook_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data)
+{
+ YelpDocbook *docbook;
+ YelpDocbookPriv *priv;
+ YelpError *error;
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " req_id = %i\n", req_id);
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+ g_assert (document != NULL && YELP_IS_DOCBOOK (document));
+
+ if (handled) {
+ return;
+ }
+
+ docbook = YELP_DOCBOOK (document);
+ priv = docbook->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ switch (priv->state) {
+ case DOCBOOK_STATE_BLANK:
+ priv->state = DOCBOOK_STATE_PARSING;
+ priv->process_running = TRUE;
+ priv->thread = g_thread_create ((GThreadFunc) docbook_process,
+ docbook, FALSE, NULL);
+ break;
+ case DOCBOOK_STATE_PARSING:
+ break;
+ case DOCBOOK_STATE_PARSED:
+ case DOCBOOK_STATE_STOP:
+ error = yelp_error_new (_("Page not found"),
+ _("The page %s was not found in the document %s."),
+ page_id, priv->filename);
+ yelp_document_error_request (document, req_id, error);
+ break;
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+/******************************************************************************/
+/** YelpTransform *************************************************************/
+
+static void
+transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpDocbook *docbook)
+{
+ YelpDocbookPriv *priv;
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (docbook != NULL && YELP_IS_DOCBOOK (docbook));
+
+ priv = docbook->priv;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == DOCBOOK_STATE_STOP) {
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ g_free (func_data);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_error_free ((YelpError *) func_data);
+ break;
+ case YELP_TRANSFORM_FINAL:
+ break;
+ }
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ return;
+ }
+
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ transform_page_func (transform, (gchar *) func_data, docbook);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_document_error_pending (YELP_DOCUMENT (docbook), (YelpError *) func_data);
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ break;
+ case YELP_TRANSFORM_FINAL:
+ transform_final_func (transform, docbook);
+ break;
+ }
+}
+
+static void
+transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpDocbook *docbook)
+{
+ YelpDocbookPriv *priv;
+ gchar *content;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = docbook->priv;
+ g_mutex_lock (priv->mutex);
+
+ content = yelp_transform_eat_chunk (transform, page_id);
+ yelp_document_add_page (YELP_DOCUMENT (docbook), page_id, content);
+
+ g_free (page_id);
+
+ g_mutex_unlock (priv->mutex);
+}
+
+static void
+transform_final_func (YelpTransform *transform, YelpDocbook *docbook)
+{
+ YelpError *error;
+ YelpDocbookPriv *priv = docbook->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 document %s."),
+ priv->filename);
+ yelp_document_final_pending (YELP_DOCUMENT (docbook), error);
+
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ priv->state = DOCBOOK_STATE_PARSED;
+
+ if (priv->xmldoc)
+ xmlFreeDoc (priv->xmldoc);
+ priv->xmldoc = NULL;
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** Threaded ******************************************************************/
+
+static void
+docbook_process (YelpDocbook *docbook)
+{
+ YelpDocbookPriv *priv;
+ xmlDocPtr xmldoc = NULL;
+ xmlChar *id = NULL;
+ YelpError *error = NULL;
+ xmlParserCtxtPtr parserCtxt = NULL;
+ YelpDocument *document;
+
+ gint params_i = 0;
+ gint params_max = 10;
+ gchar **params = NULL;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (docbook != NULL && YELP_IS_DOCBOOK (docbook));
+ g_object_ref (docbook);
+ priv = docbook->priv;
+ document = YELP_DOCUMENT (docbook);
+
+ if (!g_file_test (priv->filename, G_FILE_TEST_IS_REGULAR)) {
+ error = yelp_error_new (_("File not found"),
+ _("The file ‘%s’ does not exist."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ parserCtxt = xmlNewParserCtxt ();
+ xmldoc = xmlCtxtReadFile (parserCtxt,
+ (const char *) priv->filename, NULL,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET );
+
+ if (xmldoc == NULL) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The file ‘%s’ could not be parsed because it is"
+ " not a well-formed XML document."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ if (xmlXIncludeProcessFlags (xmldoc,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET )
+ < 0) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The file ‘%s’ could not be parsed because"
+ " one or more of its included files is not"
+ " a well-formed XML document."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ g_mutex_lock (priv->mutex);
+ if (!xmlStrcmp (xmlDocGetRootElement (xmldoc)->name, BAD_CAST "book"))
+ priv->max_depth = 2;
+ else
+ priv->max_depth = 1;
+
+ priv->xmldoc = xmldoc;
+ priv->xmlcur = xmlDocGetRootElement (xmldoc);
+
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+ if (id) {
+ yelp_document_set_root_id (document, (gchar *) id);
+ yelp_document_add_page_id (document, "x-yelp-index", (gchar *) id);
+ yelp_document_add_prev_id (document, (gchar *) id, "x-yelp-titlepage");
+ yelp_document_add_next_id (document, "x-yelp-titlepage", (gchar *) id);
+ }
+ else {
+ yelp_document_set_root_id (document, "x-yelp-index");
+ yelp_document_add_page_id (document, "x-yelp-index", "x-yelp-index");
+ yelp_document_add_prev_id (document, "x-yelp-index", "x-yelp-titlepage");
+ yelp_document_add_next_id (document, "x-yelp-titlepage", "x-yelp-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 (priv->xmlcur, BAD_CAST "id", BAD_CAST "x-yelp-index");
+ }
+ g_mutex_unlock (priv->mutex);
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == DOCBOOK_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+ g_mutex_unlock (priv->mutex);
+
+ docbook_walk (docbook);
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == DOCBOOK_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+ priv->transform = yelp_transform_new (STYLESHEET,
+ (YelpTransformFunc) transform_func,
+ docbook);
+ priv->transform_running = TRUE;
+
+ params = g_new0 (gchar *, params_max);
+ yelp_settings_params (&params, &params_i, &params_max);
+
+
+ if ((params_i + 10) >= params_max - 1) {
+ params_max += 20;
+ params = g_renew (gchar *, params, params_max);
+ }
+ params[params_i++] = "db.chunk.max_depth";
+ params[params_i++] = g_strdup_printf ("%i", docbook->priv->max_depth);
+
+ params[params_i] = NULL;
+
+ yelp_transform_start (priv->transform,
+ priv->xmldoc,
+ params);
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ if (id)
+ xmlFree (id);
+ if (parserCtxt)
+ xmlFreeParserCtxt (parserCtxt);
+
+ priv->process_running = FALSE;
+ g_object_unref (docbook);
+}
+
+
+/******************************************************************************/
+/** Walker ********************************************************************/
+
+static void
+docbook_walk (YelpDocbook *docbook)
+{
+ static gint autoid = 0;
+ gchar autoidstr[20];
+ xmlChar *id = NULL;
+ xmlChar *title = NULL;
+ gchar *old_page_id = NULL;
+ xmlNodePtr cur, old_cur;
+ GtkTreeIter iter;
+ GtkTreeIter *old_iter = NULL;
+ YelpDocbookPriv *priv = docbook->priv;
+ YelpDocument *document = YELP_DOCUMENT (docbook);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_DEBUG, " priv->xmlcur->name: %s\n", priv->xmlcur->name);
+
+ /* check for the yelp:chunk-depth or db.chunk.max_depth processing
+ * instruction and set the max chunk depth accordingly.
+ */
+ if (priv->cur_depth == 0)
+ for (cur = priv->xmlcur; cur; cur = cur->prev)
+ if (cur->type == XML_PI_NODE)
+ if (!xmlStrcmp (cur->name, (const xmlChar *) "yelp:chunk-depth") ||
+ !xmlStrcmp (cur->name, (const xmlChar *) "db.chunk.max_depth")) {
+ gint max = atoi ((gchar *) cur->content);
+ if (max)
+ priv->max_depth = max;
+ break;
+ }
+
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+
+ if (docbook_walk_divisionQ (docbook) && !id) {
+ /* if id attribute is not present, autogenerate a
+ * unique value, and insert it into the in-memory tree */
+ g_snprintf (autoidstr, 20, "_auto-gen-id-%d", ++autoid);
+ xmlNewProp (priv->xmlcur, BAD_CAST "id", BAD_CAST autoidstr);
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+ }
+
+ if (docbook_walk_chunkQ (docbook)) {
+ title = BAD_CAST docbook_walk_get_title (docbook);
+
+ debug_print (DB_DEBUG, " id: \"%s\"\n", id);
+ debug_print (DB_DEBUG, " title: \"%s\"\n", title);
+
+ yelp_document_add_title (document, (gchar *) id, (gchar *) title);
+
+ gdk_threads_enter ();
+ gtk_tree_store_append (GTK_TREE_STORE (priv->sections),
+ &iter,
+ priv->sections_iter);
+ gtk_tree_store_set (GTK_TREE_STORE (priv->sections),
+ &iter,
+ YELP_DOCUMENT_COLUMN_ID, id,
+ YELP_DOCUMENT_COLUMN_TITLE, title,
+ -1);
+ gdk_threads_leave ();
+
+ if (priv->cur_prev_id) {
+ yelp_document_add_prev_id (document, (gchar *) id, priv->cur_prev_id);
+ yelp_document_add_next_id (document, priv->cur_prev_id, (gchar *) id);
+ g_free (priv->cur_prev_id);
+ }
+ priv->cur_prev_id = g_strdup ((gchar *) id);
+
+ if (priv->cur_page_id)
+ yelp_document_add_up_id (document, (gchar *) id, priv->cur_page_id);
+ old_page_id = priv->cur_page_id;
+ priv->cur_page_id = g_strdup ((gchar *) id);
+
+ old_iter = priv->sections_iter;
+ if (priv->xmlcur->parent->type != XML_DOCUMENT_NODE)
+ priv->sections_iter = &iter;
+ }
+
+ old_cur = priv->xmlcur;
+ priv->cur_depth++;
+ if (id && !g_str_equal (id, "x-yelp-index"))
+ yelp_document_add_page_id (document, (gchar *) id, priv->cur_page_id);
+
+ for (cur = priv->xmlcur->children; cur; cur = cur->next) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ priv->xmlcur = cur;
+ docbook_walk (docbook);
+ }
+ }
+ priv->cur_depth--;
+ priv->xmlcur = old_cur;
+
+ if (docbook_walk_chunkQ (docbook)) {
+ priv->sections_iter = old_iter;
+ g_free (priv->cur_page_id);
+ priv->cur_page_id = old_page_id;
+ }
+
+ if (priv->cur_depth == 0) {
+ g_free (priv->cur_prev_id);
+ priv->cur_prev_id = NULL;
+
+ g_free (priv->cur_page_id);
+ priv->cur_page_id = NULL;
+ }
+
+ if (id != NULL)
+ xmlFree (id);
+ if (title != NULL)
+ xmlFree (title);
+}
+
+static gboolean
+docbook_walk_chunkQ (YelpDocbook *docbook)
+{
+ if (docbook->priv->cur_depth <= docbook->priv->max_depth
+ && docbook_walk_divisionQ (docbook))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static gboolean
+docbook_walk_divisionQ (YelpDocbook *docbook)
+{
+ xmlNodePtr node = docbook->priv->xmlcur;
+ 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") );
+}
+
+static gchar *
+docbook_walk_get_title (YelpDocbook *docbook)
+{
+ gchar *infoname = NULL;
+ xmlNodePtr child = NULL;
+ xmlNodePtr title = NULL;
+ xmlNodePtr title_tmp = NULL;
+ YelpDocbookPriv *priv = docbook->priv;
+
+ if (!xmlStrcmp (priv->xmlcur->name, BAD_CAST "refentry")) {
+ /* The title for a refentry element can come from the following:
+ * refmeta/refentrytitle
+ * refentryinfo/title[abbrev]
+ * refnamediv/refname
+ * We take the first one we find.
+ */
+ for (child = priv->xmlcur->children; child; child = child->next) {
+ if (!xmlStrcmp (child->name, BAD_CAST "refmeta")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "refentrytitle"))
+ break;
+ }
+ if (title)
+ goto done;
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "refentryinfo")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "titleabbrev"))
+ break;
+ else if (!xmlStrcmp (title->name, BAD_CAST "title"))
+ title_tmp = title;
+ }
+ if (title)
+ goto done;
+ else if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "refnamediv")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "refname"))
+ break;
+ else if (!xmlStrcmp (title->name, BAD_CAST "refpurpose")) {
+ title = NULL;
+ break;
+ }
+ }
+ if (title)
+ goto done;
+ }
+ else if (!xmlStrncmp (child->name, BAD_CAST "refsect", 7))
+ break;
+ }
+ }
+ else {
+ /* The title for other elements appears in the following:
+ * title[abbrev]
+ * *info/title[abbrev]
+ * blockinfo/title[abbrev]
+ * objectinfo/title[abbrev]
+ * We take them in that order.
+ */
+ xmlNodePtr infos[3] = {NULL, NULL, NULL};
+ int i;
+
+ infoname = g_strdup_printf ("%sinfo", priv->xmlcur->name);
+
+ for (child = priv->xmlcur->children; child; child = child->next) {
+ if (!xmlStrcmp (child->name, BAD_CAST "titleabbrev")) {
+ title = child;
+ goto done;
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "title"))
+ title_tmp = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST infoname))
+ infos[0] = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST "blockinfo"))
+ infos[1] = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST "objectinfo"))
+ infos[2] = child;
+ }
+
+ if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+
+ for (i = 0; i < 3; i++) {
+ child = infos[i];
+ if (child) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "titleabbrev"))
+ goto done;
+ else if (!xmlStrcmp (title->name, BAD_CAST "title"))
+ title_tmp = title;
+ }
+ if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+ }
+ }
+ }
+
+ done:
+ g_free (infoname);
+
+ if (title)
+ return (gchar *) xmlNodeGetContent (title);
+ else
+ return g_strdup (_("Unknown"));
+}
+#endif
diff --git a/src/yelp-mallard.h b/src/yelp-mallard.h
new file mode 100644
index 00000000..ba4899b5
--- /dev/null
+++ b/src/yelp-mallard.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifndef __YELP_MALLARD_H__
+#define __YELP_MALLARD_H__
+
+#include <glib-object.h>
+
+#include "yelp-document.h"
+
+#define YELP_TYPE_MALLARD (yelp_mallard_get_type ())
+#define YELP_MALLARD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_MALLARD, YelpMallard))
+#define YELP_MALLARD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_MALLARD, YelpMallardClass))
+#define YELP_IS_MALLARD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_MALLARD))
+#define YELP_IS_MALLARD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_MALLARD))
+#define YELP_MALLARD_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_MALLARD, YelpMallardClass))
+
+typedef struct _YelpMallard YelpMallard;
+typedef struct _YelpMallardClass YelpMallardClass;
+typedef struct _YelpMallardPriv YelpMallardPriv;
+
+struct _YelpMallard {
+ YelpDocument parent;
+ YelpMallardPriv *priv;
+};
+
+struct _YelpMallardClass {
+ YelpDocumentClass parent_class;
+};
+
+GType yelp_mallard_get_type (void);
+YelpDocument * yelp_mallard_new (gchar *uri);
+
+#endif /* __YELP_MALLARD_H__ */
diff --git a/src/yelp-utils.c b/src/yelp-utils.c
index a0f4e939..34443062 100644
--- a/src/yelp-utils.c
+++ b/src/yelp-utils.c
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2003 Shaun McCance <shaunm@gnome.org>
*
@@ -48,9 +48,6 @@ YelpRrnType resolve_man_page (const gchar *name,
gchar **section);
gchar * resolve_remove_section (const gchar *uri,
const gchar *sect);
-YelpRrnType yelp_uri_resolve (gchar *uri,
- gchar **result,
- gchar **section);
YelpRrnType
resolve_process_ghelp (char *uri, gchar **result)
@@ -175,12 +172,20 @@ resolve_full_file (const gchar *path)
return YELP_RRN_TYPE_ERROR;
}
- if (g_str_equal (mime_type, "text/xml") || g_str_equal (mime_type, "application/docbook+xml") || g_str_equal (mime_type, "application/xml"))
+ if (g_file_test (path, G_FILE_TEST_IS_DIR)) {
+ type = YELP_RRN_TYPE_MAL;
+ }
+ else if (g_str_equal (mime_type, "text/xml") ||
+ g_str_equal (mime_type, "application/docbook+xml") ||
+ g_str_equal (mime_type, "application/xml")) {
type = YELP_RRN_TYPE_DOC;
- else if (g_str_equal (mime_type, "text/html"))
+ }
+ else if (g_str_equal (mime_type, "text/html")) {
type = YELP_RRN_TYPE_HTML;
- else if (g_str_equal (mime_type, "application/xhtml+xml"))
+ }
+ else if (g_str_equal (mime_type, "application/xhtml+xml")) {
type = YELP_RRN_TYPE_XHTML;
+ }
else if (g_str_equal (mime_type, "application/x-gzip")) {
if (g_str_has_suffix (path, ".info.gz")) {
type = YELP_RRN_TYPE_INFO;
@@ -188,25 +193,29 @@ resolve_full_file (const gchar *path)
type = YELP_RRN_TYPE_MAN;
}
- } else if (g_str_equal (mime_type, "application/x-bzip")) {
+ }
+ else if (g_str_equal (mime_type, "application/x-bzip")) {
if (g_str_has_suffix (path, ".info.bz2")) {
type = YELP_RRN_TYPE_INFO;
} else if (resolve_is_man_path (path, "bz2")) {
type = YELP_RRN_TYPE_MAN;
}
- } else if (g_str_equal (mime_type, "application/x-lzma")) {
- if (g_str_has_suffix (path, ".info.lzma")) {
- type = YELP_RRN_TYPE_INFO;
- } else if (resolve_is_man_path (path, "lzma")) {
- type = YELP_RRN_TYPE_MAN;
- }
- } else if (g_str_equal (mime_type, "application/octet-stream")) {
- if (g_str_has_suffix (path, ".info")) {
- type = YELP_RRN_TYPE_INFO;
- } else if (resolve_is_man_path (path, NULL)) {
- type = YELP_RRN_TYPE_MAN;
- }
- } else if (g_str_equal (mime_type, "text/plain")) {
+ }
+ else if (g_str_equal (mime_type, "application/x-lzma")) {
+ if (g_str_has_suffix (path, ".info.lzma")) {
+ type = YELP_RRN_TYPE_INFO;
+ } else if (resolve_is_man_path (path, "lzma")) {
+ type = YELP_RRN_TYPE_MAN;
+ }
+ }
+ else if (g_str_equal (mime_type, "application/octet-stream")) {
+ if (g_str_has_suffix (path, ".info")) {
+ type = YELP_RRN_TYPE_INFO;
+ } else if (resolve_is_man_path (path, NULL)) {
+ type = YELP_RRN_TYPE_MAN;
+ }
+ }
+ else if (g_str_equal (mime_type, "text/plain")) {
if (g_str_has_suffix (path, ".info")) {
type = YELP_RRN_TYPE_INFO;
} else if (resolve_is_man_path (path, NULL)) {
@@ -214,7 +223,8 @@ resolve_full_file (const gchar *path)
} else {
type = YELP_RRN_TYPE_TEXT;
}
- } else {
+ }
+ else {
type = YELP_RRN_TYPE_EXTERNAL;
}
diff --git a/src/yelp-utils.h b/src/yelp-utils.h
index d5e482cc..f0c35cac 100644
--- a/src/yelp-utils.h
+++ b/src/yelp-utils.h
@@ -27,6 +27,7 @@
typedef enum {
YELP_RRN_TYPE_DOC = 0,
+ YELP_RRN_TYPE_MAL,
YELP_RRN_TYPE_MAN,
YELP_RRN_TYPE_INFO,
YELP_RRN_TYPE_TEXT,
diff --git a/src/yelp-window.c b/src/yelp-window.c
index 24d60d7f..ab5f119c 100644
--- a/src/yelp-window.c
+++ b/src/yelp-window.c
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2001-2002 Mikael Hallendal <micke@imendio.com>
* Copyright (C) 2003,2004 Shaun McCance <shaunm@gnome.org>
@@ -42,6 +42,7 @@
#include "yelp-toc.h"
#include "yelp-docbook.h"
#include "yelp-db-print.h"
+#include "yelp-mallard.h"
#include "yelp-window.h"
#include "yelp-print.h"
#include "yelp-debug.h"
@@ -1057,6 +1058,10 @@ yelp_window_load (YelpWindow *window, const gchar *uri)
doc = yelp_toc_get ();
priv->base_uri = g_strdup ("file:///fakefile");
break;
+ case YELP_RRN_TYPE_MAL:
+ priv->base_uri = g_filename_to_uri (real_uri, NULL, NULL);
+ doc = yelp_mallard_new (real_uri);
+ break;
case YELP_RRN_TYPE_MAN:
priv->base_uri = g_filename_to_uri (real_uri, NULL, NULL);
doc = yelp_man_new (real_uri);