diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | libyelp/Makefile.am | 4 | ||||
-rw-r--r-- | libyelp/yelp-document.c | 70 | ||||
-rw-r--r-- | libyelp/yelp-info-document.h | 1 | ||||
-rw-r--r-- | libyelp/yelp-info-parser.c | 5 | ||||
-rw-r--r-- | libyelp/yelp-man-document.c | 506 | ||||
-rw-r--r-- | libyelp/yelp-man-document.h | 51 | ||||
-rw-r--r-- | libyelp/yelp-man-parser.c (renamed from src/yelp-man-parser.c) | 126 | ||||
-rw-r--r-- | libyelp/yelp-man-parser.h (renamed from src/yelp-man-parser.h) | 4 | ||||
-rw-r--r-- | src/yelp-man.c | 490 | ||||
-rw-r--r-- | src/yelp-man.h | 53 | ||||
-rw-r--r-- | stylesheets/Makefile.am | 1 | ||||
-rw-r--r-- | stylesheets/man2html.xsl.in (renamed from stylesheets/man2html.xsl) | 106 | ||||
-rw-r--r-- | stylesheets/yelp-common.xsl.in | 2 |
14 files changed, 684 insertions, 736 deletions
diff --git a/configure.ac b/configure.ac index c7854a00..3797fb03 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 077630eb..01217d16 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 45017775..1a1cbb65 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 40139446..a3f4a7bd 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 cbca0e47..33107948 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 00000000..14ac8cd0 --- /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 00000000..2379f081 --- /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 index 933b3589..ef1f4d66 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 index 26976d2a..1901f1b2 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/src/yelp-man.c b/src/yelp-man.c deleted file mode 100644 index 1e6fc562..00000000 --- a/src/yelp-man.c +++ /dev/null @@ -1,490 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * Copyright (C) 2007 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.h" -#include "yelp-man-parser.h" -#include "yelp-transform.h" -#include "yelp-debug.h" -#include "yelp-settings.h" - -#define STYLESHEET DATADIR"/yelp/xslt/man2html.xsl" - -#define YELP_MAN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_MAN, YelpManPriv)) - -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; - -struct _YelpManPriv { - gchar *filename; - ManState state; - - GMutex *mutex; - GThread *thread; - - xmlDocPtr xmldoc; - - gboolean process_running; - gboolean transform_running; - - YelpTransform *transform; -}; - -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 man_class_init (YelpManClass *klass); -static void man_init (YelpMan *man); -static void man_try_dispose (GObject *object); -static void man_dispose (GObject *object); - -/* YelpDocument */ -static void man_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, - YelpMan *man); -static void transform_page_func (YelpTransform *transform, - gchar *page_id, - YelpMan *man); -static void transform_final_func (YelpTransform *transform, - YelpMan *man); - -/* Threaded */ -static void man_process (YelpMan *man); - -static YelpDocumentClass *parent_class; - -GType -yelp_man_get_type (void) -{ - static GType type = 0; - if (!type) { - static const GTypeInfo info = { - sizeof (YelpManClass), - NULL, NULL, - (GClassInitFunc) man_class_init, - NULL, NULL, - sizeof (YelpMan), - 0, - (GInstanceInitFunc) man_init, - }; - type = g_type_register_static (YELP_TYPE_DOCUMENT, - "YelpMan", - &info, 0); - } - return type; -} - -static void -man_class_init (YelpManClass *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 = man_try_dispose; - - document_class->request = man_request; - document_class->cancel = NULL; - - g_type_class_add_private (klass, sizeof (YelpManPriv)); -} - -static void -man_init (YelpMan *man) -{ - YelpManPriv *priv; - - priv = man->priv = YELP_MAN_GET_PRIVATE (man); - - priv->state = MAN_STATE_BLANK; - - priv->mutex = g_mutex_new (); -} - -static void -man_try_dispose (GObject *object) -{ - YelpManPriv *priv; - - g_assert (object != NULL && YELP_IS_MAN (object)); - priv = YELP_MAN (object)->priv; - g_mutex_lock (priv->mutex); - if (priv->process_running || priv->transform_running) { - priv->state = MAN_STATE_STOP; - g_idle_add ((GSourceFunc) man_try_dispose, object); - g_mutex_unlock (priv->mutex); - } else { - g_mutex_unlock (priv->mutex); - man_dispose (object); - } -} - -static void -man_dispose (GObject *object) -{ - YelpMan *man = YELP_MAN (object); - - g_free (man->priv->filename); - - if (man->priv->xmldoc) - xmlFreeDoc (man->priv->xmldoc); - - g_mutex_free (man->priv->mutex); - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -/******************************************************************************/ - -YelpDocument * -yelp_man_new (gchar *filename) -{ - YelpMan *man; - - g_return_val_if_fail (filename != NULL, NULL); - - man = (YelpMan *) g_object_new (YELP_TYPE_MAN, NULL); - man->priv->filename = g_strdup (filename); - - debug_print (DB_FUNCTION, "entering\n"); - debug_print (DB_ARG, " filename = \"%s\"\n", filename); - - yelp_document_add_page_id (YELP_DOCUMENT (man), "x-yelp-index", "index"); - - return (YelpDocument *) man; -} - - -/******************************************************************************/ -/** YelpDocument **************************************************************/ - -static void -man_request (YelpDocument *document, - gint req_id, - gboolean handled, - gchar *page_id, - YelpDocumentFunc func, - gpointer user_data) -{ - YelpMan *man; - YelpManPriv *priv; - YelpError *error; - - debug_print (DB_FUNCTION, "entering\n"); - debug_print (DB_ARG, " req_id = %i\n", req_id); - debug_print (DB_ARG, " page_id = \"%s\"\n", page_id); - - g_assert (document != NULL && YELP_IS_MAN (document)); - - if (handled) - return; - - man = YELP_MAN (document); - priv = man->priv; - - g_mutex_lock (priv->mutex); - - switch (priv->state) { - case MAN_STATE_BLANK: - priv->state = MAN_STATE_PARSING; - priv->process_running = TRUE; - priv->thread = g_thread_create ((GThreadFunc) man_process, man, FALSE, NULL); - break; - case MAN_STATE_PARSING: - break; - case MAN_STATE_PARSED: - case MAN_STATE_STOP: - error = yelp_error_new (_("Page not found"), - _("The page %s was not found in the document %s."), - page_id, priv->filename); - yelp_document_error_request (document, req_id, error); - break; - } - - g_mutex_unlock (priv->mutex); -} - - -/******************************************************************************/ -/** YelpTransform *************************************************************/ - -static void -transform_func (YelpTransform *transform, - YelpTransformSignal signal, - gpointer func_data, - YelpMan *man) -{ - YelpManPriv *priv; - - debug_print (DB_FUNCTION, "entering\n"); - - g_assert (man != NULL && YELP_IS_MAN (man)); - - priv = man->priv; - - g_assert (transform == priv->transform); - - if (priv->state == MAN_STATE_STOP) { - switch (signal) { - case YELP_TRANSFORM_CHUNK: - g_free (func_data); - break; - case YELP_TRANSFORM_ERROR: - yelp_error_free ((YelpError *) func_data); - break; - case YELP_TRANSFORM_FINAL: - break; - } - yelp_transform_release (transform); - priv->transform = NULL; - priv->transform_running = FALSE; - return; - } - - switch (signal) { - case YELP_TRANSFORM_CHUNK: - transform_page_func (transform, (gchar *) func_data, man); - break; - case YELP_TRANSFORM_ERROR: - yelp_document_error_pending (YELP_DOCUMENT (man), (YelpError *) func_data); - yelp_transform_release (transform); - priv->transform = NULL; - priv->transform_running = FALSE; - break; - case YELP_TRANSFORM_FINAL: - transform_final_func (transform, man); - break; - } -} - -static void -transform_page_func (YelpTransform *transform, - gchar *page_id, - YelpMan *man) -{ - YelpManPriv *priv; - gchar *content; - - debug_print (DB_FUNCTION, "entering\n"); - - priv = man->priv; - g_mutex_lock (priv->mutex); - - content = yelp_transform_eat_chunk (transform, page_id); - - yelp_document_add_page (YELP_DOCUMENT (man), page_id, content); - - g_free (page_id); - - g_mutex_unlock (priv->mutex); -} - -static void -transform_final_func (YelpTransform *transform, YelpMan *man) -{ - YelpError *error; - YelpManPriv *priv = man->priv; - - debug_print (DB_FUNCTION, "entering\n"); - g_mutex_lock (priv->mutex); - error = yelp_error_new (_("Page not found"), - _("The requested page was not found in the document %s."), - priv->filename); - yelp_document_final_pending (YELP_DOCUMENT (man), error); - - yelp_transform_release (transform); - priv->transform = NULL; - priv->transform_running = FALSE; - priv->state = MAN_STATE_PARSED; - - if (priv->xmldoc) - xmlFreeDoc (priv->xmldoc); - priv->xmldoc = NULL; - - g_mutex_unlock (priv->mutex); -} - - -/******************************************************************************/ -/** Threaded ******************************************************************/ - -static void -man_process (YelpMan *man) -{ - YelpManPriv *priv; - const gchar *language; - const gchar *encoding; - YelpManParser *parser; - YelpError *error = NULL; - YelpDocument *document; - gint i; - - gint params_i = 0; - gint params_max = 10; - gchar **params = NULL; - - debug_print (DB_FUNCTION, "entering\n"); - - g_assert (man != NULL && YELP_IS_MAN (man)); - g_object_ref (man); - priv = man->priv; - document = YELP_DOCUMENT (man); - - if (!g_file_test (priv->filename, G_FILE_TEST_IS_REGULAR)) { - error = yelp_error_new (_("File not found"), - _("The file ‘%s’ does not exist."), - priv->filename); - yelp_document_error_pending (document, error); - goto done; - } - - /* 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) { - 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, priv->filename, encoding); - yelp_man_parser_free (parser); - - if (priv->xmldoc == NULL) { - error = yelp_error_new (_("Could not parse file"), - _("The file ‘%s’ could not be parsed because it is" - " not a well-formed man page."), - priv->filename); - yelp_document_error_pending (document, 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, - (YelpTransformFunc) transform_func, - man); - priv->transform_running = TRUE; - - params = g_new0 (gchar *, params_max); - yelp_settings_params (¶ms, ¶ms_i, ¶ms_max); - - params[params_i] = NULL; - - yelp_transform_start (priv->transform, - priv->xmldoc, - params); - g_strfreev (params); - g_mutex_unlock (priv->mutex); - - done: - priv->process_running = FALSE; - g_object_unref (man); -} diff --git a/src/yelp-man.h b/src/yelp-man.h deleted file mode 100644 index 844c44ab..00000000 --- a/src/yelp-man.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * Copyright (C) 2007 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_H__ -#define __YELP_MAN_H__ - -#include <glib-object.h> - -#include "yelp-document.h" - -#define YELP_TYPE_MAN (yelp_man_get_type ()) -#define YELP_MAN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_MAN, YelpMan)) -#define YELP_MAN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_MAN, YelpManClass)) -#define YELP_IS_MAN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_MAN)) -#define YELP_IS_MAN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_MAN)) -#define YELP_MAN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_MAN, YelpManClass)) - -typedef struct _YelpMan YelpMan; -typedef struct _YelpManClass YelpManClass; -typedef struct _YelpManPriv YelpManPriv; - -struct _YelpMan { - YelpDocument parent; - YelpManPriv *priv; -}; - -struct _YelpManClass { - YelpDocumentClass parent_class; -}; - -GType yelp_man_get_type (void); -YelpDocument * yelp_man_new (gchar *uri); - -#endif /* __YELP_MAN_H__ */ diff --git a/stylesheets/Makefile.am b/stylesheets/Makefile.am index 996b0d07..f64d28fa 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 index e3dd0654..5a028edf 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 6d6f8919..306ce446 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> |