[yelp] [libyelp] Adding man page support, some formatting still off
- From: Shaun McCance <shaunm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [yelp] [libyelp] Adding man page support, some formatting still off
- Date: Tue, 1 Jun 2010 20:02:56 +0000 (UTC)
commit 78dbed19c11400d1f9b182acc01a7414dadd191f
Author: Shaun McCance <shaunm gnome org>
Date: Tue Jun 1 15:01:57 2010 -0500
[libyelp] Adding man page support, some formatting still off
configure.ac | 1 +
libyelp/Makefile.am | 4 +
libyelp/yelp-document.c | 70 ++--
libyelp/yelp-info-document.h | 1 -
libyelp/yelp-info-parser.c | 5 -
libyelp/yelp-man-document.c | 506 +++++++++++++++++++++++++
libyelp/yelp-man-document.h | 51 +++
{src => libyelp}/yelp-man-parser.c | 126 +++----
{src => libyelp}/yelp-man-parser.h | 4 +-
src/yelp-man.c | 490 ------------------------
src/yelp-man.h | 53 ---
stylesheets/Makefile.am | 1 +
stylesheets/{man2html.xsl => man2html.xsl.in} | 96 ++----
stylesheets/yelp-common.xsl.in | 2 +-
14 files changed, 679 insertions(+), 731 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index c7854a0..3797fb0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -201,6 +201,7 @@ stylesheets/db2html.xsl
stylesheets/db-title.xsl
stylesheets/info2html.xsl
stylesheets/mal2html.xsl
+stylesheets/man2html.xsl
stylesheets/toc2html.xsl
stylesheets/yelp-common.xsl
data/Makefile
diff --git a/libyelp/Makefile.am b/libyelp/Makefile.am
index 077630e..01217d1 100644
--- a/libyelp/Makefile.am
+++ b/libyelp/Makefile.am
@@ -10,6 +10,8 @@ libyelp_la_SOURCES = \
yelp-location-entry.c \
yelp-magic-decompressor.c \
yelp-mallard-document.c \
+ yelp-man-document.c \
+ yelp-man-parser.c \
yelp-marshal.c \
yelp-settings.c \
yelp-simple-document.c \
@@ -23,6 +25,7 @@ EXTRA_DIST = \
yelp-debug.h \
yelp-error.h \
yelp-info-parser.h \
+ yelp-man-parser.h \
yelp-lzma-decompressor.h \
yelp-magic-decompressor.h \
yelp-marshal.list
@@ -53,6 +56,7 @@ libyelp_headers = \
yelp-info-document.h \
yelp-location-entry.h \
yelp-mallard-document.h \
+ yelp-man-document.h \
yelp-settings.h \
yelp-simple-document.h \
yelp-transform.h \
diff --git a/libyelp/yelp-document.c b/libyelp/yelp-document.c
index 4501777..1a1cbb6 100644
--- a/libyelp/yelp-document.c
+++ b/libyelp/yelp-document.c
@@ -30,9 +30,10 @@
#include "yelp-debug.h"
#include "yelp-document.h"
#include "yelp-error.h"
-#include "yelp-info-document.h"
#include "yelp-docbook-document.h"
+#include "yelp-info-document.h"
#include "yelp-mallard-document.h"
+#include "yelp-man-document.h"
#include "yelp-simple-document.h"
typedef struct _Request Request;
@@ -76,6 +77,8 @@ struct _YelpDocumentPriv {
Hash *prev_ids; /* Mapping of page IDs to "previous page" IDs */
Hash *next_ids; /* Mapping of page IDs to "next page" IDs */
Hash *up_ids; /* Mapping of page IDs to "up page" IDs */
+
+ GError *idle_error;
};
G_DEFINE_TYPE (YelpDocument, yelp_document, G_TYPE_OBJECT);
@@ -140,14 +143,14 @@ yelp_document_get_for_uri (YelpUri *uri)
YelpDocument *document = NULL;
if (documents == NULL)
- documents = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
+ documents = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_object_unref);
g_return_val_if_fail (yelp_uri_is_resolved (uri), NULL);
docuri = yelp_uri_get_document_uri (uri);
if (docuri == NULL)
- return NULL;
+ return NULL;
switch (yelp_uri_get_document_type (uri)) {
case YELP_URI_DOCUMENT_TYPE_TEXT:
@@ -170,38 +173,38 @@ yelp_document_get_for_uri (YelpUri *uri)
document = g_hash_table_lookup (documents, docuri);
if (document != NULL) {
- g_free (docuri);
- return g_object_ref (document);
+ g_free (docuri);
+ return g_object_ref (document);
}
switch (yelp_uri_get_document_type (uri)) {
case YELP_URI_DOCUMENT_TYPE_TEXT:
case YELP_URI_DOCUMENT_TYPE_HTML:
case YELP_URI_DOCUMENT_TYPE_XHTML:
- document = yelp_simple_document_new (uri);
- break;
+ document = yelp_simple_document_new (uri);
+ break;
case YELP_URI_DOCUMENT_TYPE_DOCBOOK:
- document = yelp_docbook_document_new (uri);
- break;
+ document = yelp_docbook_document_new (uri);
+ break;
case YELP_URI_DOCUMENT_TYPE_MALLARD:
- document = yelp_mallard_document_new (uri);
- break;
+ document = yelp_mallard_document_new (uri);
+ break;
case YELP_URI_DOCUMENT_TYPE_MAN:
- /* FIXME */
- break;
+ document = yelp_man_document_new (uri);
+ break;
case YELP_URI_DOCUMENT_TYPE_INFO:
- document = yelp_info_document_new (uri);
- break;
+ document = yelp_info_document_new (uri);
+ break;
case YELP_URI_DOCUMENT_TYPE_TOC:
- /* FIXME */
- break;
+ /* FIXME */
+ break;
case YELP_URI_DOCUMENT_TYPE_SEARCH:
- /* FIXME */
- break;
+ /* FIXME */
+ break;
case YELP_URI_DOCUMENT_TYPE_NOT_FOUND:
case YELP_URI_DOCUMENT_TYPE_EXTERNAL:
case YELP_URI_DOCUMENT_TYPE_ERROR:
- break;
+ break;
}
if (document != NULL) {
@@ -847,22 +850,19 @@ yelp_document_signal (YelpDocument *document,
g_mutex_unlock (document->priv->mutex);
}
-void
-yelp_document_error_pending (YelpDocument *document,
- const GError *error)
+static gboolean
+yelp_document_error_pending_idle (YelpDocument *document)
{
YelpDocumentPriv *priv = GET_PRIV (document);
GSList *cur;
Request *request;
- g_assert (document != NULL && YELP_IS_DOCUMENT (document));
-
g_mutex_lock (priv->mutex);
if (priv->reqs_pending) {
for (cur = priv->reqs_pending; cur; cur = cur->next) {
request = cur->data;
- request->error = yelp_error_copy ((GError *) error);
+ request->error = yelp_error_copy ((GError *) priv->idle_error);
request->idle_funcs++;
g_idle_add ((GSourceFunc) request_idle_error, request);
}
@@ -872,6 +872,22 @@ yelp_document_error_pending (YelpDocument *document,
}
g_mutex_unlock (priv->mutex);
+
+ g_object_unref (document);
+ return FALSE;
+}
+
+void
+yelp_document_error_pending (YelpDocument *document,
+ const GError *error)
+{
+ YelpDocumentPriv *priv = GET_PRIV (document);
+
+ g_assert (document != NULL && YELP_IS_DOCUMENT (document));
+
+ g_object_ref (document);
+ priv->idle_error = g_error_copy (error);
+ g_idle_add ((GSourceFunc) yelp_document_error_pending_idle, document);
}
/******************************************************************************/
diff --git a/libyelp/yelp-info-document.h b/libyelp/yelp-info-document.h
index 4013944..a3f4a7b 100644
--- a/libyelp/yelp-info-document.h
+++ b/libyelp/yelp-info-document.h
@@ -36,7 +36,6 @@
typedef struct _YelpInfoDocument YelpInfoDocument;
typedef struct _YelpInfoDocumentClass YelpInfoDocumentClass;
-typedef struct _YelpInfoPriv YelpInfoPriv;
struct _YelpInfoDocument {
YelpDocument parent;
diff --git a/libyelp/yelp-info-parser.c b/libyelp/yelp-info-parser.c
index cbca0e4..3310794 100644
--- a/libyelp/yelp-info-parser.c
+++ b/libyelp/yelp-info-parser.c
@@ -224,11 +224,6 @@ static char
g_string_append_len (string, buf, bytes);
g_object_unref (stream);
- /*
- g_object_unref (converter);
- g_object_unref (file_stream);
- g_object_unref (file);
- */
str = string->str;
diff --git a/libyelp/yelp-man-document.c b/libyelp/yelp-man-document.c
new file mode 100644
index 0000000..14ac8cd
--- /dev/null
+++ b/libyelp/yelp-man-document.c
@@ -0,0 +1,506 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007-2010 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/tree.h>
+
+#include "yelp-error.h"
+#include "yelp-man-document.h"
+#include "yelp-man-parser.h"
+#include "yelp-transform.h"
+#include "yelp-settings.h"
+
+#define STYLESHEET DATADIR"/yelp/xslt/man2html.xsl"
+
+typedef enum {
+ MAN_STATE_BLANK, /* Brand new, run transform as needed */
+ MAN_STATE_PARSING, /* Parsing/transforming document, please wait */
+ MAN_STATE_PARSED, /* All done, if we ain't got it, it ain't here */
+ MAN_STATE_STOP /* Stop everything now, object to be disposed */
+} ManState;
+
+typedef struct _YelpManDocumentPrivate YelpManDocumentPrivate;
+struct _YelpManDocumentPrivate {
+ YelpUri *uri;
+ ManState state;
+
+ GMutex *mutex;
+ GThread *thread;
+
+ xmlDocPtr xmldoc;
+
+ gboolean process_running;
+ gboolean transform_running;
+
+ YelpTransform *transform;
+ guint chunk_ready;
+ guint finished;
+ guint error;
+};
+
+typedef struct _YelpLangEncodings YelpLangEncodings;
+struct _YelpLangEncodings {
+ gchar *language;
+ gchar *encoding;
+};
+/* http://www.w3.org/International/O-charset-lang.html */
+static const YelpLangEncodings langmap[] = {
+ { "C", "ISO-8859-1" },
+ { "af", "ISO-8859-1" },
+ { "ar", "ISO-8859-6" },
+ { "bg", "ISO-8859-5" },
+ { "be", "ISO-8859-5" },
+ { "ca", "ISO-8859-1" },
+ { "cs", "ISO-8859-2" },
+ { "da", "ISO-8859-1" },
+ { "de", "ISO-8859-1" },
+ { "el", "ISO-8859-7" },
+ { "en", "ISO-8859-1" },
+ { "eo", "ISO-8859-3" },
+ { "es", "ISO-8859-1" },
+ { "et", "ISO-8859-15" },
+ { "eu", "ISO-8859-1" },
+ { "fi", "ISO-8859-1" },
+ { "fo", "ISO-8859-1" },
+ { "fr", "ISO-8859-1" },
+ { "ga", "ISO-8859-1" },
+ { "gd", "ISO-8859-1" },
+ { "gl", "ISO-8859-1" },
+ { "hu", "ISO-8859-2" },
+ { "id", "ISO-8859-1" }, /* is this right */
+ { "mt", "ISO-8859-3" },
+ { "is", "ISO-8859-1" },
+ { "it", "ISO-8859-1" },
+ { "iw", "ISO-8859-8" },
+ { "ja", "EUC-JP" },
+ { "ko", "EUC-KR" },
+ { "lt", "ISO-8859-13" },
+ { "lv", "ISO-8859-13" },
+ { "mk", "ISO-8859-5" },
+ { "mt", "ISO-8859-3" },
+ { "no", "ISO-8859-1" },
+ { "pl", "ISO-8859-2" },
+ { "pt_BR", "ISO-8859-1" },
+ { "ro", "ISO-8859-2" },
+ { "ru", "KOI8-R" },
+ { "sl", "ISO-8859-2" },
+ { "sr", "ISO-8859-2" }, /* Latin, not cyrillic */
+ { "sk", "ISO-8859-2" },
+ { "sv", "ISO-8859-1" },
+ { "tr", "ISO-8859-9" },
+ { "uk", "ISO-8859-5" },
+ { "zh_CN", "BIG5" },
+ { "zh_TW", "BIG5" },
+ { NULL, NULL },
+};
+
+static void yelp_man_document_class_init (YelpManDocumentClass *klass);
+static void yelp_man_document_init (YelpManDocument *man);
+static void yelp_man_document_dispose (GObject *object);
+static void yelp_man_document_finalize (GObject *object);
+
+/* YelpDocument */
+static gboolean man_request_page (YelpDocument *document,
+ const gchar *page_id,
+ GCancellable *cancellable,
+ YelpDocumentCallback callback,
+ gpointer user_data);
+
+/* YelpTransform */
+static void transform_chunk_ready (YelpTransform *transform,
+ gchar *chunk_id,
+ YelpManDocument *man);
+static void transform_finished (YelpTransform *transform,
+ YelpManDocument *man);
+static void transform_error (YelpTransform *transform,
+ YelpManDocument *man);
+static void transform_finalized (YelpManDocument *man,
+ gpointer transform);
+
+/* Threaded */
+static void man_document_process (YelpManDocument *man);
+
+static void man_document_disconnect (YelpManDocument *man);
+
+
+G_DEFINE_TYPE (YelpManDocument, yelp_man_document, YELP_TYPE_DOCUMENT);
+#define GET_PRIV(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_MAN_DOCUMENT, YelpManDocumentPrivate))
+
+static void
+yelp_man_document_class_init (YelpManDocumentClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpDocumentClass *document_class = YELP_DOCUMENT_CLASS (klass);
+
+ object_class->dispose = yelp_man_document_dispose;
+ object_class->finalize = yelp_man_document_finalize;
+
+ document_class->request_page = man_request_page;
+
+ g_type_class_add_private (klass, sizeof (YelpManDocumentPrivate));
+}
+
+static void
+yelp_man_document_init (YelpManDocument *man)
+{
+ YelpManDocumentPrivate *priv = GET_PRIV (man);
+
+ priv->state = MAN_STATE_BLANK;
+ priv->mutex = g_mutex_new ();
+}
+
+static void
+yelp_man_document_dispose (GObject *object)
+{
+ YelpManDocumentPrivate *priv = GET_PRIV (object);
+
+ if (priv->uri) {
+ g_object_unref (priv->uri);
+ priv->uri = NULL;
+ }
+
+ G_OBJECT_CLASS (yelp_man_document_parent_class)->dispose (object);
+}
+
+static void
+yelp_man_document_finalize (GObject *object)
+{
+ YelpManDocumentPrivate *priv = GET_PRIV (object);
+
+ if (priv->xmldoc)
+ xmlFreeDoc (priv->xmldoc);
+
+ g_mutex_free (priv->mutex);
+
+ G_OBJECT_CLASS (yelp_man_document_parent_class)->finalize (object);
+}
+
+/******************************************************************************/
+
+YelpDocument *
+yelp_man_document_new (YelpUri *uri)
+{
+ YelpManDocument *man;
+ YelpManDocumentPrivate *priv;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ man = (YelpManDocument *) g_object_new (YELP_TYPE_MAN_DOCUMENT, NULL);
+ priv = GET_PRIV (man);
+
+ priv->uri = g_object_ref (uri);
+
+ return (YelpDocument *) man;
+}
+
+
+/******************************************************************************/
+/** YelpDocument **************************************************************/
+
+static gboolean
+man_request_page (YelpDocument *document,
+ const gchar *page_id,
+ GCancellable *cancellable,
+ YelpDocumentCallback callback,
+ gpointer user_data)
+{
+ YelpManDocumentPrivate *priv = GET_PRIV (document);
+ gchar *docuri;
+ GError *error;
+ gboolean handled;
+
+ if (page_id == NULL)
+ page_id = "//index";
+
+ handled =
+ YELP_DOCUMENT_CLASS (yelp_man_document_parent_class)->request_page (document,
+ page_id,
+ cancellable,
+ callback,
+ user_data);
+ if (handled) {
+ return;
+ }
+
+ g_mutex_lock (priv->mutex);
+
+ switch (priv->state) {
+ case MAN_STATE_BLANK:
+ priv->state = MAN_STATE_PARSING;
+ priv->process_running = TRUE;
+ g_object_ref (document);
+ yelp_document_set_page_id (document, NULL, "//index");
+ yelp_document_set_page_id (document, "//index", "//index");
+ yelp_document_set_root_id (document, "//index", "//index");
+ priv->thread = g_thread_create ((GThreadFunc) man_document_process,
+ document, FALSE, NULL);
+ break;
+ case MAN_STATE_PARSING:
+ break;
+ case MAN_STATE_PARSED:
+ case MAN_STATE_STOP:
+ docuri = yelp_uri_get_document_uri (priv->uri);
+ error = g_error_new (YELP_ERROR, YELP_ERROR_NOT_FOUND,
+ _("The page â??%sâ?? was not found in the document â??%sâ??."),
+ page_id, docuri);
+ g_free (docuri);
+ yelp_document_signal (document, page_id,
+ YELP_DOCUMENT_SIGNAL_ERROR,
+ error);
+ g_error_free (error);
+ break;
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** YelpTransform *************************************************************/
+
+static void
+transform_chunk_ready (YelpTransform *transform,
+ gchar *chunk_id,
+ YelpManDocument *man)
+{
+ YelpManDocumentPrivate *priv = GET_PRIV (man);
+ gchar *content;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == MAN_STATE_STOP) {
+ man_document_disconnect (man);
+ return;
+ }
+
+ content = yelp_transform_take_chunk (transform, chunk_id);
+ yelp_document_give_contents (YELP_DOCUMENT (man),
+ chunk_id,
+ content,
+ "application/xhtml+xml");
+
+ yelp_document_signal (YELP_DOCUMENT (man),
+ chunk_id,
+ YELP_DOCUMENT_SIGNAL_INFO,
+ NULL);
+ yelp_document_signal (YELP_DOCUMENT (man),
+ chunk_id,
+ YELP_DOCUMENT_SIGNAL_CONTENTS,
+ NULL);
+}
+
+static void
+transform_finished (YelpTransform *transform,
+ YelpManDocument *man)
+{
+ YelpManDocumentPrivate *priv = GET_PRIV (man);
+ gchar *docuri;
+ GError *error;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == MAN_STATE_STOP) {
+ man_document_disconnect (man);
+ return;
+ }
+
+ man_document_disconnect (man);
+ priv->state = MAN_STATE_PARSED;
+
+ /* We want to free priv->xmldoc, but we can't free it before transform
+ is finalized. Otherwise, we could crash when YelpTransform frees
+ its libxslt resources.
+ */
+ g_object_weak_ref ((GObject *) transform,
+ (GWeakNotify) transform_finalized,
+ man);
+
+ docuri = yelp_uri_get_document_uri (priv->uri);
+ error = g_error_new (YELP_ERROR, YELP_ERROR_NOT_FOUND,
+ _("The requested page was not found in the document â??%sâ??."),
+ docuri);
+ g_free (docuri);
+ yelp_document_error_pending ((YelpDocument *) man, error);
+ g_error_free (error);
+}
+
+static void
+transform_error (YelpTransform *transform,
+ YelpManDocument *man)
+{
+ YelpManDocumentPrivate *priv = GET_PRIV (man);
+ GError *error;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == MAN_STATE_STOP) {
+ man_document_disconnect (man);
+ return;
+ }
+
+ error = yelp_transform_get_error (transform);
+ yelp_document_error_pending ((YelpDocument *) man, error);
+ g_error_free (error);
+
+ man_document_disconnect (man);
+}
+
+static void
+transform_finalized (YelpManDocument *man,
+ gpointer transform)
+{
+ YelpManDocumentPrivate *priv = GET_PRIV (man);
+
+ if (priv->xmldoc)
+ xmlFreeDoc (priv->xmldoc);
+ priv->xmldoc = NULL;
+}
+
+
+/******************************************************************************/
+/** Threaded ******************************************************************/
+
+static void
+man_document_process (YelpManDocument *man)
+{
+ YelpManDocumentPrivate *priv = GET_PRIV (man);
+ GFile *file = NULL;
+ gchar *filepath = NULL;
+ GError *error;
+ gint params_i = 0;
+ gchar **params = NULL;
+ YelpManParser *parser;
+ const gchar *language, *encoding;
+
+ file = yelp_uri_get_file (priv->uri);
+ if (file == NULL) {
+ error = g_error_new (YELP_ERROR, YELP_ERROR_NOT_FOUND,
+ _("The file does not exist."));
+ yelp_document_error_pending ((YelpDocument *) man, error);
+ g_error_free (error);
+ goto done;
+ }
+
+ filepath = g_file_get_path (file);
+ g_object_unref (file);
+ if (!g_file_test (filepath, G_FILE_TEST_IS_REGULAR)) {
+ error = g_error_new (YELP_ERROR, YELP_ERROR_NOT_FOUND,
+ _("The file â??%sâ?? does not exist."),
+ filepath);
+ yelp_document_error_pending ((YelpDocument *) man, error);
+ g_error_free (error);
+ goto done;
+ }
+
+ /* FIXME: get the language */
+ language = "C";
+
+ /* default encoding if the language doesn't match below */
+ encoding = g_getenv("MAN_ENCODING");
+ if (encoding == NULL)
+ encoding = "ISO-8859-1";
+
+ if (language != NULL) {
+ gint i;
+ for (i = 0; langmap[i].language != NULL; i++) {
+ if (g_str_equal (language, langmap[i].language)) {
+ encoding = langmap[i].encoding;
+ break;
+ }
+ }
+ }
+
+ parser = yelp_man_parser_new ();
+ priv->xmldoc = yelp_man_parser_parse_file (parser, filepath, encoding);
+ yelp_man_parser_free (parser);
+
+ if (priv->xmldoc == NULL) {
+ error = g_error_new (YELP_ERROR, YELP_ERROR_PROCESSING,
+ _("The file â??%sâ?? could not be parsed because it is"
+ " not a well-formed man page."),
+ filepath);
+ yelp_document_error_pending ((YelpDocument *) man, error);
+ }
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == MAN_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+
+ priv->transform = yelp_transform_new (STYLESHEET);
+ priv->chunk_ready =
+ g_signal_connect (priv->transform, "chunk-ready",
+ (GCallback) transform_chunk_ready,
+ man);
+ priv->finished =
+ g_signal_connect (priv->transform, "finished",
+ (GCallback) transform_finished,
+ man);
+ priv->error =
+ g_signal_connect (priv->transform, "error",
+ (GCallback) transform_error,
+ man);
+
+ params = yelp_settings_get_all_params (yelp_settings_get_default (), 0, ¶ms_i);
+
+ priv->transform_running = TRUE;
+ yelp_transform_start (priv->transform,
+ priv->xmldoc,
+ NULL,
+ (const gchar * const *) params);
+ g_strfreev (params);
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ g_free (filepath);
+ priv->process_running = FALSE;
+ g_object_unref (man);
+}
+
+static void
+man_document_disconnect (YelpManDocument *man)
+{
+ YelpManDocumentPrivate *priv = GET_PRIV (man);
+ if (priv->chunk_ready) {
+ g_signal_handler_disconnect (priv->transform, priv->chunk_ready);
+ priv->chunk_ready = 0;
+ }
+ if (priv->finished) {
+ g_signal_handler_disconnect (priv->transform, priv->finished);
+ priv->finished = 0;
+ }
+ if (priv->error) {
+ g_signal_handler_disconnect (priv->transform, priv->error);
+ priv->error = 0;
+ }
+ yelp_transform_cancel (priv->transform);
+ g_object_unref (priv->transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+}
diff --git a/libyelp/yelp-man-document.h b/libyelp/yelp-man-document.h
new file mode 100644
index 0000000..2379f08
--- /dev/null
+++ b/libyelp/yelp-man-document.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2007-2010 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_MAN_DOCUMENT_H__
+#define __YELP_MAN_DOCUMENT_H__
+
+#include <glib-object.h>
+
+#include "yelp-document.h"
+
+#define YELP_TYPE_MAN_DOCUMENT (yelp_man_document_get_type ())
+#define YELP_MAN_DOCUMENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_MAN_DOCUMENT, YelpManDocument))
+#define YELP_MAN_DOCUMENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_MAN_DOCUMENT, YelpManDocumentClass))
+#define YELP_IS_MAN_DOCUMENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_MAN_DOCUMENT))
+#define YELP_IS_MAN_DOCUMENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_MAN_DOCUMENT))
+#define YELP_MAN_DOCUMENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_MAN_DOCUMENT, YelpManDocumentClass))
+
+typedef struct _YelpManDocument YelpManDocument;
+typedef struct _YelpManDocumentClass YelpManDocumentClass;
+
+struct _YelpManDocument {
+ YelpDocument parent;
+};
+
+struct _YelpManDocumentClass {
+ YelpDocumentClass parent_class;
+};
+
+GType yelp_man_document_get_type (void);
+YelpDocument * yelp_man_document_new (YelpUri *uri);
+
+#endif /* __YELP_MAN_DOCUMENT_H__ */
diff --git a/src/yelp-man-parser.c b/libyelp/yelp-man-parser.c
similarity index 94%
rename from src/yelp-man-parser.c
rename to libyelp/yelp-man-parser.c
index 933b358..ef1f4d6 100644
--- a/src/yelp-man-parser.c
+++ b/libyelp/yelp-man-parser.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
- * Copyright (C) 2003 Shaun McCance <shaunm gnome org>
+ * Copyright (C) 2003-2010 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
@@ -17,7 +17,7 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Author: Shaun McCance <shaunm gnome org>
+ * Author: Shaun McCance <shaunm gnome org>
*/
#ifdef HAVE_CONFIG_H
@@ -29,9 +29,8 @@
#include <libxml/tree.h>
#include <string.h>
-#include "yelp-debug.h"
-#include "yelp-io-channel.h"
#include "yelp-man-parser.h"
+#include "yelp-magic-decompressor.h"
#define PARSER_CUR (g_utf8_get_char (parser->cur) != '\0' \
&& (parser->cur - parser->buffer < parser->length))
@@ -69,10 +68,9 @@ struct _YelpManParser {
xmlNodePtr ins; /* The insertion node */
xmlNodePtr th_node; /* The TH node, or NULL if it doesn't exist */
- GIOChannel *channel; /* GIOChannel for the entire document */
-
- gchar *buffer; /* The buffer, line at a time */
- gsize length; /* The buffer length */
+ GDataInputStream *stream; /* The GIO input stream to read from */
+ gchar *buffer; /* The buffer, line at a time */
+ gsize length; /* The buffer length */
gchar *anc; /* The anchor point in the document */
gchar *cur; /* Our current position in the document */
@@ -98,17 +96,18 @@ yelp_man_parser_parse_file (YelpManParser *parser,
gchar *file,
const gchar *encoding)
{
- GError *errormsg = NULL;
- /*gchar *ptr = NULL;*/
-
- g_return_val_if_fail (parser != NULL, NULL);
- g_return_val_if_fail (file != NULL, NULL);
- g_return_val_if_fail (encoding != NULL, NULL);
-
- parser->channel = yelp_io_channel_new_file (file, NULL);
-
- if (!parser->channel)
- return NULL;
+ GFile *gfile;
+ GConverter *converter;
+ GFileInputStream *file_stream;
+ GInputStream *stream;
+ gchar *line;
+ gsize len;
+
+ gfile = g_file_new_for_path (file);
+ file_stream = g_file_read (gfile, NULL, NULL);
+ converter = (GConverter *) yelp_magic_decompressor_new ();
+ stream = g_converter_input_stream_new ((GInputStream *) file_stream, converter);
+ parser->stream = g_data_input_stream_new (stream);
parser->doc = xmlNewDoc (BAD_CAST "1.0");
parser->ins = xmlNewNode (NULL, BAD_CAST "Man");
@@ -116,20 +115,14 @@ yelp_man_parser_parse_file (YelpManParser *parser,
parser->make_links = TRUE;
- while (g_io_channel_read_line (parser->channel,
- &(parser->buffer),
- &(parser->length),
- NULL, &errormsg)
- == G_IO_STATUS_NORMAL) {
-
+ while ((parser->buffer = g_data_input_stream_read_line (parser->stream, &(parser->length), NULL, NULL)) != NULL) {
/* convert this line from the encoding indicated to UTF-8 */
if (!g_str_equal (encoding, "UTF-8")) {
GError *converr = NULL;
gchar *new_buffer = NULL;
gsize bytes_written = 0;
- /* since our encoding is binary (NULL) in g_io_channel, then
- * our returned lined should end with \n. Therefore we are making the
+ /* We are making the
* assumption that there are no partial characters at the end of this
* string, and therefore can use calls like g_convert() which do not
* preserve state - someone tell me if I'm wrong here */
@@ -149,23 +142,13 @@ yelp_man_parser_parse_file (YelpManParser *parser,
parser->buffer = new_buffer;
parser->length = bytes_written;
}
-
- /* for debugging, make sure line is valid UTF-8 */
- /*if (!g_utf8_validate (parser->buffer, (gssize)parser->length, &ptr)) {
- g_print ("str = %s\n", parser->buffer);
- g_print ("str ptr = %p\n", parser->buffer);
- g_print ("invalid char = %p (%c)\n", ptr, *ptr);
- }*/
-
+
parser_parse_line (parser);
g_free (parser->buffer);
}
- if (errormsg)
- g_print ("Error in g_io_channel_read_line()\n");
-
- g_io_channel_shutdown (parser->channel, FALSE, NULL);
+ g_object_unref (parser->stream);
return parser->doc;
}
@@ -173,9 +156,6 @@ yelp_man_parser_parse_file (YelpManParser *parser,
void
yelp_man_parser_free (YelpManParser *parser)
{
- if (parser->channel)
- g_io_channel_unref (parser->channel);
-
g_free (parser);
}
@@ -381,20 +361,20 @@ macro_section_header_handler (YelpManParser *parser, gchar *macro, GSList *args)
{
static gint id = 0;
GIOStatus retval;
- GError **errormsg = NULL;
+ GError *error = NULL;
gchar *str = NULL;
gchar *macro_uc = g_strdup (macro);
gchar *ptr;
gchar idval[20];
if (!args) {
- retval = g_io_channel_read_line (parser->channel,
- &str,
- NULL, NULL, errormsg);
- if (retval != G_IO_STATUS_NORMAL) {
- g_warning ("g_io_channel_read_line != G_IO_STATUS_NORMAL\n");
+ str = g_data_input_stream_read_line (parser->stream, NULL, NULL, &error);
+ if (error) {
+ g_warning ("%s\n", error->message);
+ g_error_free (error);
}
- } else
+ }
+ else
str = args_concat_all (args);
for (ptr = macro_uc; *ptr != '\0'; ptr++)
@@ -459,11 +439,8 @@ macro_tp_handler (YelpManParser *parser, gchar *macro, GSList *args)
g_free (parser->buffer);
- if (g_io_channel_read_line (parser->channel,
- &(parser->buffer),
- &(parser->length),
- NULL, errormsg)
- == G_IO_STATUS_NORMAL) {
+ parser->buffer = g_data_input_stream_read_line (parser->stream, &(parser->length), NULL, NULL);
+ if (parser->buffer != NULL) {
parser->ins = parser_append_node (parser, "Tag");
parser_parse_line (parser);
parser->ins = parser->ins->parent;
@@ -609,7 +586,7 @@ macro_url_handler (YelpManParser *parser, gchar *macro, GSList *args)
tmpNode = parser_stack_pop_node (parser, "UR");
if (tmpNode == NULL)
- debug_print (DB_WARN, "Found unexpected tag: '%s'\n", macro);
+ g_warning ("Found unexpected tag: '%s'\n", macro);
else
parser->ins = tmpNode->parent;
} else
@@ -706,7 +683,7 @@ macro_mandoc_list_handler (YelpManParser *parser, gchar *macro, GSList *args)
tmpNode = parser_stack_pop_node (parser, "Bl");
if (tmpNode == NULL)
- debug_print (DB_WARN, "Found unexpected tag: '%s'\n", macro);
+ g_warning ("Found unexpected tag: '%s'\n", macro);
else
parser->ins = tmpNode->parent;
}
@@ -725,7 +702,7 @@ macro_verbatim_handler (YelpManParser *parser, gchar *macro, GSList *args)
tmpNode = parser_stack_pop_node (parser, "Verbatim");
if (tmpNode == NULL)
- debug_print (DB_WARN, "Found unexpected tag: '%s'\n", macro);
+ g_warning ("Found unexpected tag: '%s'\n", macro);
else
parser->ins = tmpNode->parent;
}
@@ -1269,7 +1246,7 @@ get_argument:
}
else if (g_str_equal (str, "TE")) {
/* We should only see this from within parser_parse_table */
- debug_print (DB_WARN, "Found unexpected tag: '%s'\n", str);
+ g_warning ("Found unexpected tag: '%s'\n", str);
g_free (str);
}
/* "ie" and "if" are conditional macros in groff
@@ -1454,7 +1431,7 @@ parser_append_given_text_handle_escapes (YelpManParser *parser, gchar *text, gbo
if (g_str_equal (str, "fI") || g_str_equal (str, "fB"))
parser->ins = parser_append_node (parser, str);
else if (!g_str_equal (str, "fR") && !g_str_equal (str, "fP"))
- debug_print (DB_WARN, "No rule matching the tag '%s'\n", str);
+ g_warning ("No rule matching the tag '%s'\n", str);
g_free (str);
anc = ptr;
@@ -1754,11 +1731,9 @@ parser_handle_row_options (YelpManParser *parser)
g_free (parser->buffer);
- } while (g_io_channel_read_line (parser->channel,
- &(parser->buffer),
- &(parser->length),
- NULL, NULL)
- == G_IO_STATUS_NORMAL);
+ } while ((parser->buffer =
+ g_data_input_stream_read_line (parser->stream, &(parser->length), NULL, NULL))
+ != NULL);
}
static void
@@ -1769,11 +1744,8 @@ parser_parse_table (YelpManParser *parser)
table_start = parser->ins;
- if (g_io_channel_read_line (parser->channel,
- &(parser->buffer),
- &(parser->length),
- NULL, NULL)
- == G_IO_STATUS_NORMAL) {
+ parser->buffer = g_data_input_stream_read_line (parser->stream, &(parser->length), NULL, NULL);
+ if (parser->buffer != NULL) {
parser->anc = parser->buffer;
parser->cur = parser->buffer;
@@ -1782,11 +1754,8 @@ parser_parse_table (YelpManParser *parser)
if (*(parser->cur) == ';') {
parser_handle_table_options (parser);
- if (g_io_channel_read_line (parser->channel,
- &(parser->buffer),
- &(parser->length),
- NULL, NULL)
- == G_IO_STATUS_NORMAL) {
+ parser->buffer = g_data_input_stream_read_line (parser->stream, &(parser->length), NULL, NULL);
+ if (parser->buffer != NULL) {
parser->anc = parser->buffer;
parser->cur = parser->buffer;
@@ -1798,12 +1767,7 @@ parser_parse_table (YelpManParser *parser)
parser_handle_row_options (parser);
/* Now this is where we go through all the rows */
- while (g_io_channel_read_line (parser->channel,
- &(parser->buffer),
- &(parser->length),
- NULL, NULL)
- == G_IO_STATUS_NORMAL) {
-
+ while ((parser->buffer = g_data_input_stream_read_line (parser->stream, &(parser->length), NULL, NULL)) != NULL) {
parser->anc = parser->buffer;
parser->cur = parser->buffer;
@@ -1814,7 +1778,7 @@ parser_parse_table (YelpManParser *parser)
if (*(parser->buffer + 1) == 'T'
&& *(parser->buffer + 2) == 'E') {
if (parser_stack_pop_node (parser, "TABLE") == NULL)
- debug_print (DB_WARN, "Found unexpected tag: 'TE'\n");
+ g_warning ("Found unexpected tag: 'TE'\n");
else {
parser->ins = table_start;
diff --git a/src/yelp-man-parser.h b/libyelp/yelp-man-parser.h
similarity index 92%
rename from src/yelp-man-parser.h
rename to libyelp/yelp-man-parser.h
index 26976d2..1901f1b 100644
--- a/src/yelp-man-parser.h
+++ b/libyelp/yelp-man-parser.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
- * Copyright (C) 2003 Shaun McCance <shaunm gnome org>
+ * Copyright (C) 2003-2010 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
@@ -17,7 +17,7 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Author: Shaun McCance <shaunm gnome org>
+ * Author: Shaun McCance <shaunm gnome org>
*/
#ifndef __YELP_MAN_PARSER_H__
diff --git a/stylesheets/Makefile.am b/stylesheets/Makefile.am
index 996b0d0..f64d28f 100644
--- a/stylesheets/Makefile.am
+++ b/stylesheets/Makefile.am
@@ -18,5 +18,6 @@ EXTRA_DIST= \
db-title.xsl.in \
info2html.xsl.in \
mal2html.xsl.in \
+ man2html.xsl.in \
toc2html.xsl.in \
yelp-common.xsl.in
diff --git a/stylesheets/man2html.xsl b/stylesheets/man2html.xsl.in
similarity index 80%
rename from stylesheets/man2html.xsl
rename to stylesheets/man2html.xsl.in
index e3dd065..5a028ed 100644
--- a/stylesheets/man2html.xsl
+++ b/stylesheets/man2html.xsl.in
@@ -6,86 +6,40 @@
extension-element-prefixes="yelp"
version="1.0">
-<xsl:output method="html" encoding="UTF-8"/>
-
+<xsl:import href="@XSL_GETTEXT@"/>
+<xsl:import href="@XSL_COLOR@"/>
+<xsl:import href="@XSL_ICONS@"/>
+<xsl:import href="@XSL_HTML@"/>
<xsl:include href="yelp-common.xsl"/>
-<xsl:param name="stylesheet_path" select="''"/>
-<xsl:param name="linktrail"/>
-
-<xsl:param name="yelp.javascript"/>
-
-<xsl:param name="yelp.icon.blockquote"/>
-<xsl:param name="yelp.icon.caution"/>
-<xsl:param name="yelp.icon.important"/>
-<xsl:param name="yelp.icon.note"/>
-<xsl:param name="yelp.icon.programlisting"/>
-<xsl:param name="yelp.icon.tip"/>
-<xsl:param name="yelp.icon.warning"/>
-
-<xsl:param name="theme.color.text"/>
-<xsl:param name="theme.color.background"/>
-<xsl:param name="theme.color.text_light"/>
-<xsl:param name="theme.color.link"/>
-<xsl:param name="theme.color.link_visited"/>
-<xsl:param name="theme.color.gray_background"/>
-<xsl:param name="theme.color.gray_border"/>
-<xsl:param name="theme.color.blue_background"/>
-<xsl:param name="theme.color.blue_border"/>
-<xsl:param name="theme.color.red_background"/>
-<xsl:param name="theme.color.red_border"/>
-<xsl:param name="theme.color.yellow_background"/>
-<xsl:param name="theme.color.yellow_border"/>
-
-<xsl:template match="Man">
- <xsl:choose>
- <xsl:when test="element-available('yelp:document')">
- <yelp:document href="index">
- <xsl:call-template name="html"/>
- </yelp:document>
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="html"/>
- </xsl:otherwise>
- </xsl:choose>
+<xsl:param name="html.basename" select="'//index'"/>
+
+<xsl:param name="linktrail" select="''"/>
+
+<xsl:template mode="html.title.mode" match="Man">
+ <xsl:value-of select="//TH/Title"/>
</xsl:template>
-<xsl:template name="html">
- <html>
- <head>
- <title>
- <xsl:value-of select="//TH/Title"/>
- </title>
- <style type="text/css">
- <xsl:call-template name="html.css"/>
- </style>
- <script type="text/javascript">
- <xsl:attribute name="src">
- <xsl:value-of select="concat('file://', $yelp.javascript)"/>
- </xsl:attribute>
- </script>
- </head>
- <body>
- <xsl:call-template name="html.linktrail"/>
- <div class="body">
- <xsl:apply-templates select="TH"/>
- <xsl:apply-templates select="SH"/>
- </div>
- </body>
- </html>
-</xsl:template>
-
-<xsl:template name="html.css">
- <xsl:call-template name="yelp.common.css"/>
- <xsl:text>
- div[class~="SH"] { margin-left: 1.2em; }
- div[class~="SS"] { margin-left: 1.6em; }
-
- span[class~="R"] { font-family: serif; }
- span[class~="Section"] { margin-left: 0.4em; }
-
- dd { padding-bottom: 10px; }
- </xsl:text>
+<xsl:template mode="html.css.mode" match="Man">
+ <xsl:param name="direction"/>
+ <xsl:param name="left"/>
+ <xsl:param name="right"/>
+<xsl:text>
+body { font-family: monospace; }
+div.SH { margin-</xsl:text><xsl:value-of select="$left"/><xsl:text>: 1.2em; }
+div.SS { margin-</xsl:text><xsl:value-of select="$left"/><xsl:text>: 1.6em; }
+span.Section { margin-</xsl:text><xsl:value-of select="$left"/><xsl:text>: 0.4em; }
+dd { padding-bottom: 10px; }
+</xsl:text>
+</xsl:template>
+
+<xsl:template mode="html.header.mode" match="Man">
+ <xsl:call-template name="html.linktrail"/>
+</xsl:template>
+
+<xsl:template mode="html.body.mode" match="Man">
+ <xsl:apply-templates select="TH"/>
+ <xsl:apply-templates select="SH"/>
</xsl:template>
<xsl:template name="html.linktrail">
diff --git a/stylesheets/yelp-common.xsl.in b/stylesheets/yelp-common.xsl.in
index 6d6f891..306ce44 100644
--- a/stylesheets/yelp-common.xsl.in
+++ b/stylesheets/yelp-common.xsl.in
@@ -30,7 +30,7 @@
</xsl:otherwise>
</xsl:choose>
</xsl:param>
- <yelp:document href="{$node/@id}">
+ <yelp:document href="{$href}">
<xsl:call-template name="html.page">
<xsl:with-param name="node" select="$node"/>
</xsl:call-template>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]