summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS5
-rw-r--r--configure.in6
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/yelp-mallard.c654
-rw-r--r--src/yelp-mallard.h53
-rw-r--r--src/yelp-settings.c40
-rw-r--r--src/yelp-transform.c35
-rw-r--r--src/yelp-transform.h5
-rw-r--r--src/yelp-utils.c54
-rw-r--r--src/yelp-utils.h1
-rw-r--r--src/yelp-window.c17
-rw-r--r--stylesheets/Makefile.am3
-rw-r--r--stylesheets/mal2html.xsl.in74
14 files changed, 905 insertions, 45 deletions
diff --git a/NEWS b/NEWS
index 88c2ff29..b369964d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+Changes in 2.27.1:
+------------------
+* Added experimental support for Mallard
+* Fixed various color theme issues
+
Changes in 2.26.0:
------------------
* Don't assume order of certain man macros, bug #568066 (Andy Owen)
diff --git a/configure.in b/configure.in
index 4dc488aa..2e6b6c1f 100644
--- a/configure.in
+++ b/configure.in
@@ -1,4 +1,4 @@
-AC_INIT([Yelp],[2.26.0],[http://bugzilla.gnome.org/enter_bug.cgi?product=yelp],[yelp])
+AC_INIT([Yelp],[2.27.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=yelp],[yelp])
GNOME_COMMON_INIT
@@ -93,6 +93,9 @@ AC_SUBST(DB_TITLE)
DB2HTML="`$PKG_CONFIG --variable=db2xhtml gnome-doc-utils`"
AC_SUBST(DB2HTML)
+MAL2HTML="`$PKG_CONFIG --variable=mal2xhtml gnome-doc-utils`"
+AC_SUBST(MAL2HTML)
+
GDU_GETTEXT="`$PKG_CONFIG --variable=gettext gnome-doc-utils`"
AC_SUBST(GDU_GETTEXT)
@@ -269,6 +272,7 @@ src/Makefile
stylesheets/Makefile
stylesheets/db2html.xsl
stylesheets/db-title.xsl
+stylesheets/mal2html.xsl
stylesheets/toc2html.xsl
data/Makefile
data/icons/Makefile
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 61defb21..73583acd 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -18,6 +18,7 @@ src/yelp-error.c
src/yelp-info.c
src/yelp-io-channel.c
src/yelp-main.c
+src/yelp-mallard.c
src/yelp-man.c
src/yelp-page.c
src/yelp-print.c
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..65304a66
--- /dev/null
+++ b/src/yelp-mallard.c
@@ -0,0 +1,654 @@
+/* -*- 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 MALLARD_NS "http://projectmallard.org/1.0/"
+
+#define YELP_MALLARD_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_MALLARD, YelpMallardPriv))
+
+typedef enum {
+ MALLARD_STATE_BLANK,
+ MALLARD_STATE_THINKING,
+ MALLARD_STATE_IDLE,
+ MALLARD_STATE_STOP
+} MallardState;
+
+typedef struct {
+ YelpMallard *mallard;
+ gchar *page_id;
+ gchar *filename;
+ xmlDocPtr xmldoc;
+ YelpTransform *transform;
+
+ xmlNodePtr cur;
+ xmlNodePtr cache;
+ gboolean link_title;
+ gboolean sort_title;
+} MallardPageData;
+
+struct _YelpMallardPriv {
+ gchar *directory;
+ MallardState state;
+
+ GMutex *mutex;
+ GThread *thread;
+ gboolean thread_running;
+ gint transforms_running;
+ GSList *pending;
+
+ xmlDocPtr cache;
+ xmlNsPtr cache_ns;
+ GHashTable *pages_hash;
+};
+
+
+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,
+ MallardPageData *page_data);
+static void transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ MallardPageData *page_data);
+static void transform_final_func (YelpTransform *transform,
+ MallardPageData *page_data);
+/* Other */
+static void mallard_think (YelpMallard *mallard);
+static void mallard_try_run (YelpMallard *mallard,
+ gchar *page_id);
+
+static void mallard_page_data_walk (MallardPageData *page_data);
+static void mallard_page_data_info (MallardPageData *page_data,
+ xmlNodePtr info_node,
+ xmlNodePtr cache_node);
+static void mallard_page_data_run (MallardPageData *page_data);
+static void mallard_page_data_free (MallardPageData *page_data);
+
+
+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;
+ xmlNodePtr cur;
+ priv = mallard->priv = YELP_MALLARD_GET_PRIVATE (mallard);
+
+ priv->mutex = g_mutex_new ();
+
+ priv->thread_running = FALSE;
+ priv->transforms_running = 0;
+
+ priv->cache = xmlNewDoc (BAD_CAST "1.0");
+ priv->cache_ns = xmlNewNs (NULL, BAD_CAST MALLARD_NS, BAD_CAST "mal");
+ cur = xmlNewDocNode (priv->cache, priv->cache_ns, BAD_CAST "cache", NULL);
+ xmlDocSetRootElement (priv->cache, cur);
+ priv->cache_ns->next = cur->nsDef;
+ cur->nsDef = priv->cache_ns;
+ priv->pages_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL,
+ (GDestroyNotify) mallard_page_data_free);
+}
+
+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->thread_running || priv->transforms_running > 0) {
+ priv->state = MALLARD_STATE_STOP;
+ g_idle_add ((GSourceFunc) mallard_try_dispose, object);
+ g_mutex_unlock (priv->mutex);
+ } else {
+ g_mutex_unlock (priv->mutex);
+ 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_hash_table_destroy (mallard->priv->pages_hash);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpDocument *
+yelp_mallard_new (gchar *directory)
+{
+ YelpMallard *mallard;
+ YelpDocument *document;
+
+ 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);
+
+ document = (YelpDocument *) mallard;
+ yelp_document_set_root_id (document, "index");
+ yelp_document_add_page_id (document, "x-yelp-index", "index");
+
+ return document;
+}
+
+
+static void
+mallard_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data)
+{
+ YelpMallard *mallard;
+ YelpMallardPriv *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 (G_TYPE_CHECK_INSTANCE_TYPE ((document), YELP_TYPE_MALLARD));
+ g_assert (document != NULL && YELP_IS_MALLARD (document));
+
+ if (handled) {
+ return;
+ }
+
+ mallard = YELP_MALLARD (document);
+ priv = mallard->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ if (priv->state == MALLARD_STATE_BLANK) {
+ priv->state = MALLARD_STATE_THINKING;
+ priv->thread_running = TRUE;
+ priv->thread = g_thread_create ((GThreadFunc) mallard_think,
+ mallard, FALSE, NULL);
+ }
+
+ switch (priv->state) {
+ case MALLARD_STATE_THINKING:
+ priv->pending = g_slist_prepend (priv->pending, (gpointer) g_strdup (page_id));
+ break;
+ case MALLARD_STATE_IDLE:
+ mallard_try_run (mallard, page_id);
+ break;
+ case MALLARD_STATE_BLANK:
+ case MALLARD_STATE_STOP:
+ error = yelp_error_new (_("Page not found"),
+ _("The page %s was not found in the document %s."),
+ page_id, priv->directory);
+ yelp_document_error_request (document, req_id, error);
+ break;
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+/******************************************************************************/
+
+static void
+mallard_think (YelpMallard *mallard)
+{
+ YelpMallardPriv *priv;
+ YelpError *error = NULL;
+ YelpDocument *document;
+
+ GFile *gfile;
+ GFileEnumerator *children;
+ GFileInfo *pageinfo;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (mallard != NULL && YELP_IS_MALLARD (mallard));
+ g_object_ref (mallard);
+ priv = mallard->priv;
+ document = YELP_DOCUMENT (mallard);
+
+ if (!g_file_test (priv->directory, G_FILE_TEST_IS_DIR)) {
+ error = yelp_error_new (_("Directory not found"),
+ _("The directory ā€˜%sā€™ does not exist."),
+ priv->directory);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ gfile = g_file_new_for_path (priv->directory);
+ children = g_file_enumerate_children (gfile,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ while ((pageinfo = g_file_enumerator_next_file (children, NULL, NULL))) {
+ MallardPageData *page_data;
+ gchar *filename;
+ GFile *pagefile;
+ filename = g_file_info_get_attribute_as_string (pageinfo,
+ G_FILE_ATTRIBUTE_STANDARD_NAME);
+ if (!g_str_has_suffix (filename, ".page")) {
+ g_free (filename);
+ g_object_unref (pageinfo);
+ continue;
+ }
+ page_data = g_new0 (MallardPageData, 1);
+ page_data->mallard = mallard;
+ pagefile = g_file_resolve_relative_path (gfile, filename);
+ page_data->filename = g_file_get_path (pagefile);
+ mallard_page_data_walk (page_data);
+ if (page_data->page_id == NULL) {
+ mallard_page_data_free (page_data);
+ } else {
+ g_mutex_lock (priv->mutex);
+ g_hash_table_insert (priv->pages_hash, page_data->page_id, page_data);
+ g_mutex_unlock (priv->mutex);
+ }
+ g_object_unref (pagefile);
+ g_free (filename);
+ g_object_unref (pageinfo);
+ }
+
+ g_mutex_lock (priv->mutex);
+ priv->state = MALLARD_STATE_IDLE;
+ while (priv->pending) {
+ gchar *page_id;
+ page_id = (gchar *) priv->pending->data;
+ mallard_try_run (mallard, page_id);
+ g_free (page_id);
+ priv->pending = g_slist_delete_link (priv->pending, priv->pending);
+ }
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ g_object_unref (children);
+ g_object_unref (gfile);
+
+ priv->thread_running = FALSE;
+ g_object_unref (mallard);
+}
+
+static void
+mallard_try_run (YelpMallard *mallard,
+ gchar *page_id)
+{
+ /* We expect to be in a locked mutex when this function is called. */
+ MallardPageData *page_data;
+
+ page_data = g_hash_table_lookup (mallard->priv->pages_hash, page_id);
+ if (page_data == NULL) {
+ printf ("FIXME: page not found\n");
+ return;
+ }
+
+ mallard_page_data_run (page_data);
+}
+
+/******************************************************************************/
+/** MallardPageData ***********************************************************/
+
+static void
+mallard_page_data_walk (MallardPageData *page_data)
+{
+ xmlParserCtxtPtr parserCtxt = NULL;
+ xmlChar *id;
+
+ if (page_data->cur == NULL) {
+ parserCtxt = xmlNewParserCtxt ();
+ page_data->xmldoc = xmlCtxtReadFile (parserCtxt,
+ (const char *) page_data->filename, NULL,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET );
+ if (page_data->xmldoc == NULL)
+ goto done;
+ page_data->cur = xmlDocGetRootElement (page_data->xmldoc);
+ page_data->cache = xmlDocGetRootElement (page_data->mallard->priv->cache);
+ mallard_page_data_walk (page_data);
+ } else {
+ xmlNodePtr child, oldcur, oldcache, info;
+
+ id = xmlGetProp (page_data->cur, BAD_CAST "id");
+ if (id == NULL)
+ goto done;
+
+ page_data->cache = xmlNewChild (page_data->cache,
+ page_data->mallard->priv->cache_ns,
+ page_data->cur->name,
+ NULL);
+
+ if (xmlStrEqual (page_data->cur->name, BAD_CAST "page")) {
+ page_data->page_id = g_strdup ((gchar *) id);
+ xmlSetProp (page_data->cache, BAD_CAST "id", id);
+ } else {
+ gchar *newid = g_strdup_printf ("%s#%s", page_data->page_id, id);
+ xmlSetProp (page_data->cache, BAD_CAST "id", BAD_CAST newid);
+ g_free (newid);
+ }
+
+ info = xmlNewChild (page_data->cache,
+ page_data->mallard->priv->cache_ns,
+ BAD_CAST "info", NULL);
+ page_data->link_title = FALSE;
+ page_data->sort_title = FALSE;
+ for (child = page_data->cur->children; child; child = child->next) {
+ if (child->type != XML_ELEMENT_NODE)
+ continue;
+ if (xmlStrEqual (child->name, BAD_CAST "info")) {
+ mallard_page_data_info (page_data, child, info);
+ }
+ else if (xmlStrEqual (child->name, BAD_CAST "title")) {
+ xmlNodePtr node;
+ xmlNodePtr title_node = xmlNewChild (page_data->cache,
+ page_data->mallard->priv->cache_ns,
+ BAD_CAST "title", NULL);
+ for (node = child->children; node; node = node->next) {
+ xmlAddChild (title_node, xmlCopyNode (node, 1));
+ }
+ if (!page_data->link_title) {
+ xmlNodePtr title_node = xmlNewChild (info,
+ page_data->mallard->priv->cache_ns,
+ BAD_CAST "title", NULL);
+ xmlSetProp (title_node, BAD_CAST "type", BAD_CAST "link");
+ for (node = child->children; node; node = node->next) {
+ xmlAddChild (title_node, xmlCopyNode (node, 1));
+ }
+ }
+ if (!page_data->sort_title) {
+ xmlNodePtr title_node = xmlNewChild (info,
+ page_data->mallard->priv->cache_ns,
+ BAD_CAST "title", NULL);
+ xmlSetProp (title_node, BAD_CAST "type", BAD_CAST "sort");
+ for (node = child->children; node; node = node->next) {
+ xmlAddChild (title_node, xmlCopyNode (node, 1));
+ }
+ }
+ }
+ else if (xmlStrEqual (child->name, BAD_CAST "section")) {
+ oldcur = page_data->cur;
+ oldcache = page_data->cache;
+ page_data->cur = child;
+ mallard_page_data_walk (page_data);
+ page_data->cur = oldcur;
+ page_data->cache = oldcache;
+ }
+ }
+ }
+
+ done:
+ if (id)
+ xmlFree (id);
+ if (parserCtxt)
+ xmlFreeParserCtxt (parserCtxt);
+}
+
+static void
+mallard_page_data_info (MallardPageData *page_data,
+ xmlNodePtr info_node,
+ xmlNodePtr cache_node)
+{
+ xmlNodePtr child;
+
+ for (child = info_node->children; child; child = child->next) {
+ if (xmlStrEqual (child->name, BAD_CAST "info")) {
+ mallard_page_data_info (page_data, child, cache_node);
+ }
+ else if (xmlStrEqual (child->name, BAD_CAST "title")) {
+ xmlNodePtr node, title_node;
+ xmlChar *type, *role;
+ title_node = xmlNewChild (cache_node,
+ page_data->mallard->priv->cache_ns,
+ BAD_CAST "title", NULL);
+ for (node = child->children; node; node = node->next) {
+ xmlAddChild (title_node, xmlCopyNode (node, 1));
+ }
+
+ type = xmlGetProp (child, BAD_CAST "type");
+ role = xmlGetProp (child, BAD_CAST "role");
+
+ if (xmlStrEqual (type, BAD_CAST "link") && role == NULL)
+ page_data->link_title = TRUE;
+ if (xmlStrEqual (type, BAD_CAST "sort"))
+ page_data->sort_title = TRUE;
+
+ if (type) {
+ xmlSetProp (title_node, BAD_CAST "type", BAD_CAST type);
+ xmlFree (type);
+ }
+ if (role) {
+ xmlSetProp (title_node, BAD_CAST "role", BAD_CAST type);
+ xmlFree (role);
+ }
+ }
+ else if (xmlStrEqual (child->name, BAD_CAST "desc") ||
+ xmlStrEqual (child->name, BAD_CAST "link")) {
+ xmlAddChild (cache_node, xmlCopyNode (child, 1));
+ }
+ }
+}
+
+static void
+mallard_page_data_run (MallardPageData *page_data)
+{
+ gint params_i = 0;
+ gint params_max = 10;
+ gchar **params = NULL;
+ page_data->transform = yelp_transform_new (STYLESHEET,
+ (YelpTransformFunc) transform_func,
+ page_data);
+ page_data->mallard->priv->transforms_running++;
+
+ params = g_new0 (gchar *, params_max);
+ yelp_settings_params (&params, &params_i, &params_max);
+ params[params_i] = NULL;
+
+ yelp_transform_set_input (page_data->transform,
+ page_data->mallard->priv->cache);
+
+ yelp_transform_start (page_data->transform,
+ page_data->xmldoc,
+ params);
+}
+
+static void
+mallard_page_data_free (MallardPageData *page_data)
+{
+ g_free (page_data->page_id);
+ g_free (page_data->filename);
+ if (page_data->xmldoc)
+ xmlFreeDoc (page_data->xmldoc);
+ if (page_data->transform)
+ yelp_transform_release (page_data->transform);
+ g_free (page_data);
+}
+
+/******************************************************************************/
+/** YelpTransform *************************************************************/
+
+static void
+transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ MallardPageData *page_data)
+{
+ YelpMallardPriv *priv;
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (page_data != NULL && page_data->mallard != NULL &&
+ YELP_IS_MALLARD (page_data->mallard));
+ g_assert (transform == page_data->transform);
+
+ priv = page_data->mallard->priv;
+
+ if (priv->state == MALLARD_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);
+ page_data->transform = NULL;
+ priv->transforms_running--;
+ return;
+ }
+
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ transform_page_func (transform, (gchar *) func_data, page_data);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_document_error_pending (YELP_DOCUMENT (page_data->mallard), (YelpError *) func_data);
+ yelp_transform_release (transform);
+ page_data->transform = NULL;
+ priv->transforms_running -= 1;
+ break;
+ case YELP_TRANSFORM_FINAL:
+ transform_final_func (transform, page_data);
+ break;
+ }
+}
+
+static void
+transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ MallardPageData *page_data)
+{
+ YelpMallardPriv *priv;
+ gchar *content;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = page_data->mallard->priv;
+ g_mutex_lock (priv->mutex);
+
+ content = yelp_transform_eat_chunk (transform, page_id);
+ yelp_document_add_page (YELP_DOCUMENT (page_data->mallard), page_id, content);
+
+ g_free (page_id);
+
+ g_mutex_unlock (priv->mutex);
+}
+
+static void
+transform_final_func (YelpTransform *transform, MallardPageData *page_data)
+{
+ YelpMallardPriv *priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = page_data->mallard->priv;
+ g_mutex_lock (priv->mutex);
+
+ yelp_transform_release (transform);
+ page_data->transform = NULL;
+ priv->transforms_running -= 1;
+
+ if (page_data->xmldoc)
+ xmlFreeDoc (page_data->xmldoc);
+ page_data->xmldoc = NULL;
+
+ g_mutex_unlock (priv->mutex);
+}
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-settings.c b/src/yelp-settings.c
index fd41b653..12137584 100644
--- a/src/yelp-settings.c
+++ b/src/yelp-settings.c
@@ -733,9 +733,9 @@ settings_update (YelpSettingsType type)
style->text[GTK_STATE_NORMAL].green / 65535.0,
style->text[GTK_STATE_NORMAL].blue / 65535.0,
&text_h, &text_l, &text_s);
- rgb_to_hls (style->bg[GTK_STATE_NORMAL].red / 65535.0,
- style->bg[GTK_STATE_NORMAL].green / 65535.0,
- style->bg[GTK_STATE_NORMAL].blue / 65535.0,
+ rgb_to_hls (style->base[GTK_STATE_NORMAL].red / 65535.0,
+ style->base[GTK_STATE_NORMAL].green / 65535.0,
+ style->base[GTK_STATE_NORMAL].blue / 65535.0,
&base_h, &base_l, &base_s);
/* YELP_COLOR_FG */
@@ -779,44 +779,44 @@ settings_update (YelpSettingsType type)
g_object_unref (widget);
hls_to_hex (text_h,
- text_l - ((text_l - base_l) * 0.4),
+ text_l - ((text_l - base_l) * 0.25),
text_s,
YELP_COLOR_FG_LIGHT);
hls_to_hex (base_h,
- base_l - ((base_l - text_l) * 0.05),
+ base_l - ((base_l - text_l) * 0.03),
base_s,
YELP_COLOR_GRAY_BG);
hls_to_hex (base_h,
- base_l - ((base_l - text_l) * 0.1),
+ base_l - ((base_l - text_l) * 0.25),
base_s,
YELP_COLOR_GRAY_BORDER);
- hls_to_hex (base_h,
- base_l - ((base_l - text_l) * 0.05),
- 0.6,
+ hls_to_hex (204,
+ base_l - ((base_l - text_l) * 0.03),
+ 0.75,
YELP_COLOR_BLUE_BG);
- hls_to_hex (base_h,
- base_l - ((base_l - text_l) * 0.1),
- 0.6,
+ hls_to_hex (204,
+ base_l - ((base_l - text_l) * 0.25),
+ 0.75,
YELP_COLOR_BLUE_BORDER);
hls_to_hex (0,
- base_l - ((base_l - text_l) * 0.05),
- 0.6,
+ base_l - ((base_l - text_l) * 0.03),
+ 0.75,
YELP_COLOR_RED_BG);
hls_to_hex (0,
- base_l - ((base_l - text_l) * 0.1),
- 0.6,
+ base_l - ((base_l - text_l) * 0.25),
+ 0.75,
YELP_COLOR_RED_BORDER);
hls_to_hex (60,
- base_l - ((base_l - text_l) * 0.05),
- 0.6,
+ base_l - ((base_l - text_l) * 0.03),
+ 0.75,
YELP_COLOR_YELLOW_BG);
hls_to_hex (60,
- base_l - ((base_l - text_l) * 0.1),
- 0.6,
+ base_l - ((base_l - text_l) * 0.25),
+ 0.75,
YELP_COLOR_YELLOW_BORDER);
g_object_unref (G_OBJECT (style));
diff --git a/src/yelp-transform.c b/src/yelp-transform.c
index 3e33f3c0..01a42a54 100644
--- a/src/yelp-transform.c
+++ b/src/yelp-transform.c
@@ -29,6 +29,8 @@
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <libxml/xinclude.h>
+#include <libxml/xpathInternals.h>
+#include <libxslt/documents.h>
#include <libxslt/xslt.h>
#include <libexslt/exslt.h>
#include <libxslt/templates.h>
@@ -62,6 +64,8 @@ static void xslt_yelp_cache (xsltTransformContextPtr ctxt,
xmlNodePtr node,
xmlNodePtr inst,
xsltStylePreCompPtr comp);
+static void xslt_yelp_input (xmlXPathParserContextPtr ctxt,
+ int nargs);
/******************************************************************************/
@@ -98,6 +102,13 @@ YelpTransform
}
void
+yelp_transform_set_input (YelpTransform *transform,
+ xmlDocPtr input)
+{
+ transform->input = input;
+}
+
+void
yelp_transform_start (YelpTransform *transform,
xmlDocPtr document,
gchar **params)
@@ -130,6 +141,10 @@ yelp_transform_start (YelpTransform *transform,
BAD_CAST "cache",
BAD_CAST YELP_NAMESPACE,
(xsltTransformFunction) xslt_yelp_cache);
+ xsltRegisterExtFunction (transform->context,
+ BAD_CAST "input",
+ BAD_CAST YELP_NAMESPACE,
+ (xmlXPathFunction) xslt_yelp_input);
transform->mutex = g_mutex_new ();
g_mutex_lock (transform->mutex);
@@ -224,6 +239,8 @@ transform_free (YelpTransform *transform)
}
g_mutex_lock (transform->mutex);
+ if (transform->input_xslt)
+ transform->input_xslt->doc = NULL;
if (transform->outputDoc)
xmlFreeDoc (transform->outputDoc);
if (transform->stylesheet)
@@ -431,3 +448,21 @@ xslt_yelp_cache (xsltTransformContextPtr ctxt,
xsltStylePreCompPtr comp)
{
}
+
+static void
+xslt_yelp_input (xmlXPathParserContextPtr ctxt, int nargs)
+{
+ xsltTransformContextPtr tctxt;
+ xmlXPathObjectPtr ret;
+ YelpTransform *transform;
+
+ tctxt = xsltXPathGetTransformContext (ctxt);
+ transform = (YelpTransform *) tctxt->_private;
+
+ /* FIXME: pretty sure this eats transform->input, memory corruption will follow */
+ transform->input_xslt = xsltNewDocument (tctxt, transform->input);
+
+ ret = xmlXPathNewNodeSet (xmlDocGetRootElement (transform->input));
+ xsltExtensionInstructionResultRegister (tctxt, ret);
+ valuePush (ctxt, ret);
+}
diff --git a/src/yelp-transform.h b/src/yelp-transform.h
index e1262e39..131f866a 100644
--- a/src/yelp-transform.h
+++ b/src/yelp-transform.h
@@ -49,6 +49,9 @@ struct _YelpTransform {
xsltStylesheetPtr stylesheet;
xsltTransformContextPtr context;
+ xmlDocPtr input;
+ xsltDocumentPtr input_xslt;
+
YelpTransformFunc func;
gchar **params;
@@ -74,6 +77,8 @@ YelpTransform *yelp_transform_new (gchar *stylesheet,
void yelp_transform_start (YelpTransform *transform,
xmlDocPtr document,
gchar **params);
+void yelp_transform_set_input (YelpTransform *transform,
+ xmlDocPtr input);
gchar * yelp_transform_eat_chunk (YelpTransform *transform,
gchar *chunk_id);
void yelp_transform_release (YelpTransform *transform);
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..a59e91d9 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);
@@ -1135,6 +1140,7 @@ yelp_window_load (YelpWindow *window, const gchar *uri)
}
if (doc) {
+ gchar *slash;
gboolean need_hist = FALSE;
if (!frag_id)
frag_id = g_strdup ("x-yelp-index");
@@ -1146,6 +1152,15 @@ yelp_window_load (YelpWindow *window, const gchar *uri)
window_setup_window (window, type, real_uri, frag_id,
(gchar *) uri, current_base, need_hist);
+ /* FIXME: Super hacky. We want the part before the slash for mallard IDs,
+ because right now we're outputting "#page_id/section_id". We ought to
+ be scrolling to the section as well. I happen to know that get_page is
+ just going to strdup the string, and we free frag_id itself immediately
+ after this, so this is safe. It just sucks.
+ */
+ slash = strchr (frag_id, '/');
+ if (slash)
+ *slash = '\0';
priv->current_request = yelp_document_get_page (doc,
frag_id,
(YelpDocumentFunc) page_request_cb,
diff --git a/stylesheets/Makefile.am b/stylesheets/Makefile.am
index c6b6b060..09ccf408 100644
--- a/stylesheets/Makefile.am
+++ b/stylesheets/Makefile.am
@@ -5,10 +5,11 @@ xsldir=$(datadir)/yelp/xslt
xsl_DATA = \
db2html.xsl \
db-title.xsl \
+ mal2html.xsl \
info2html.xsl \
man2html.xsl \
search2html.xsl \
toc2html.xsl \
yelp-common.xsl
-EXTRA_DIST=$(xsl_DATA) db2html.xsl.in db-title.xsl.in toc2html.xsl.in
+EXTRA_DIST=$(xsl_DATA) db2html.xsl.in db-title.xsl.in mal2html.xsl.in toc2html.xsl.in
diff --git a/stylesheets/mal2html.xsl.in b/stylesheets/mal2html.xsl.in
new file mode 100644
index 00000000..a8af26a0
--- /dev/null
+++ b/stylesheets/mal2html.xsl.in
@@ -0,0 +1,74 @@
+<?xml version='1.0' encoding='UTF-8'?><!-- -*- indent-tabs-mode: nil -*- -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:yelp="http://www.gnome.org/yelp/ns"
+ xmlns:mal="http://www.gnome.org/~shaunm/mallard"
+ xmlns="http://www.w3.org/1999/xhtml"
+ extension-element-prefixes="yelp"
+ version="1.0">
+
+<xsl:import href="@MAL2HTML@"/>
+
+<xsl:include href="yelp-common.xsl"/>
+
+<xsl:param name="yelp.javascript"/>
+
+
+<xsl:param name="mal.chunk.chunk_top" select="true()"/>
+<xsl:param name="mal.chunk.extension" select="''"/>
+
+<xsl:param name="mal.cache" select="yelp:input()"/>
+<xsl:key name="mal.cache.key" match="mal:page | mal:section" use="@id"/>
+
+
+<!-- == mal.chunk == -->
+<xsl:template name="mal.chunk">
+ <xsl:param name="node" select="."/>
+ <xsl:param name="href" select="concat($node/@id, $mal.chunk.extension)"/>
+ <yelp:document href="{$href}">
+ <xsl:apply-templates mode="mal.chunk.content.mode" select="$node"/>
+ </yelp:document>
+</xsl:template>
+
+<!-- == mal.link.target == -->
+<xsl:template name="mal.link.target">
+ <xsl:param name="link" select="."/>
+ <xsl:param name="xref" select="$link/@xref"/>
+ <xsl:param name="href" select="$link/@href"/>
+ <xsl:choose>
+ <xsl:when test="string($xref) = ''">
+ <xsl:value-of select="$href"/>
+ </xsl:when>
+ <xsl:when test="contains($xref, '/')">
+ <xsl:value-of select="$href"/>
+ </xsl:when>
+ <xsl:when test="contains($xref, '#')">
+ <xsl:variable name="pageid" select="substring-before($xref, '#')"/>
+ <xsl:variable name="sectionid" select="substring-after($xref, '#')"/>
+ <xsl:value-of select="concat('#', $pageid, '/', $sectionid)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('#', $xref)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- == mal2html.css.custom == -->
+<xsl:template name="mal2html.css.custom">
+ <xsl:call-template name="yelp.common.css"/>
+ <xsl:text>
+body { padding: 0; }
+div.head {
+ padding: 0.2em 0 0 0;
+ margin: 0 0 1em 0;
+ background-color: </xsl:text>
+ <xsl:value-of select="$theme.color.gray_background"/><xsl:text>;
+ border-bottom: solid 1px </xsl:text>
+ <xsl:value-of select="$theme.color.gray_border"/><xsl:text>;
+}
+div.body {
+ margin: 0 12px 0 12px;
+}
+ </xsl:text>
+</xsl:template>
+
+</xsl:stylesheet>