diff options
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | configure.in | 6 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/yelp-mallard.c | 654 | ||||
-rw-r--r-- | src/yelp-mallard.h | 53 | ||||
-rw-r--r-- | src/yelp-settings.c | 40 | ||||
-rw-r--r-- | src/yelp-transform.c | 35 | ||||
-rw-r--r-- | src/yelp-transform.h | 5 | ||||
-rw-r--r-- | src/yelp-utils.c | 54 | ||||
-rw-r--r-- | src/yelp-utils.h | 1 | ||||
-rw-r--r-- | src/yelp-window.c | 17 | ||||
-rw-r--r-- | stylesheets/Makefile.am | 3 | ||||
-rw-r--r-- | stylesheets/mal2html.xsl.in | 74 |
14 files changed, 905 insertions, 45 deletions
@@ -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 (¶ms, ¶ms_i, ¶ms_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> |