[yelp] [yelp-help-list] Adding list of all (ghelp) documents



commit 0c2de2a1db2c9162e576ca624f619cf6be4813f1
Author: Shaun McCance <shaunm gnome org>
Date:   Fri Aug 13 16:31:02 2010 -0400

    [yelp-help-list] Adding list of all (ghelp) documents

 libyelp/Makefile.am      |  105 +++++-----
 libyelp/yelp-document.c  |    5 +-
 libyelp/yelp-help-list.c |  527 ++++++++++++++++++++++++++++++++++++++++++++++
 libyelp/yelp-help-list.h |   51 +++++
 libyelp/yelp-uri.c       |   16 ++-
 libyelp/yelp-uri.h       |    2 +-
 src/yelp-window.c        |   16 ++
 7 files changed, 665 insertions(+), 57 deletions(-)
---
diff --git a/libyelp/Makefile.am b/libyelp/Makefile.am
index 7aa7907..30e26b6 100644
--- a/libyelp/Makefile.am
+++ b/libyelp/Makefile.am
@@ -1,34 +1,35 @@
 lib_LTLIBRARIES = libyelp.la
 
-libyelp_la_SOURCES =				\
-	yelp-bookmarks.c			\
-	yelp-debug.c				\
-	yelp-error.c				\
-	yelp-docbook-document.c			\
-	yelp-document.c				\
-	yelp-info-document.c			\
-	yelp-info-parser.c			\
-	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			\
-	yelp-transform.c			\
-	yelp-uri.c				\
-	yelp-types.c				\
+libyelp_la_SOURCES =            \
+	yelp-bookmarks.c            \
+	yelp-debug.c                \
+	yelp-error.c                \
+	yelp-docbook-document.c     \
+	yelp-document.c             \
+	yelp-help-list.c            \
+	yelp-info-document.c        \
+	yelp-info-parser.c          \
+	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      \
+	yelp-transform.c            \
+	yelp-uri.c                  \
+	yelp-types.c                \
 	yelp-view.c
 
-EXTRA_DIST =				\
-	yelp-bz2-decompressor.h		\
-	yelp-debug.h			\
-	yelp-error.h			\
-	yelp-info-parser.h		\
-	yelp-man-parser.h		\
-	yelp-lzma-decompressor.h	\
-	yelp-magic-decompressor.h	\
+EXTRA_DIST =                    \
+	yelp-bz2-decompressor.h     \
+	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
 
 if ENABLE_LZMA
@@ -43,39 +44,37 @@ else
 EXTRA_DIST += yelp-bz2-decompressor.c
 endif
 
-libyelp_la_CFLAGS =				\
-	$(YELP_CFLAGS)				\
-	-DDATADIR=\""$(datadir)"\"		\
+libyelp_la_CFLAGS =                         \
+	$(YELP_CFLAGS)                          \
+	-DDATADIR=\""$(datadir)"\"              \
 	-DYELP_ICON_PATH=\"$(YELP_ICON_PATH)\"
 
-libyelp_la_LIBADD =				\
-	$(YELP_LIBS)
-
-libyelp_headers =				\
-	yelp-bookmarks.h			\
-	yelp-docbook-document.h			\
-	yelp-document.h				\
-	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			\
-	yelp-uri.h				\
+libyelp_la_LIBADD = $(YELP_LIBS)
+
+libyelp_headers =               \
+	yelp-bookmarks.h            \
+	yelp-docbook-document.h     \
+	yelp-document.h             \
+	yelp-help-list.h            \
+	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            \
+	yelp-uri.h                  \
 	yelp-view.h
 
 libyelp_includedir = $(includedir)/libyelp/
 
-libyelp_include_HEADERS =			\
-	$(libyelp_headers)			\
-	yelp-types.h
+libyelp_include_HEADERS = $(libyelp_headers) yelp-types.h
 
-BUILT_SOURCES =			\
-	stamp-yelp-marshal.h	\
-	yelp-marshal.c		\
-	yelp-marshal.h		\
-	yelp-types.c		\
+BUILT_SOURCES =              \
+	stamp-yelp-marshal.h     \
+	yelp-marshal.c           \
+	yelp-marshal.h           \
+	yelp-types.c             \
 	yelp-types.h
 
 yelp-marshal.h: stamp-yelp-marshal.h
diff --git a/libyelp/yelp-document.c b/libyelp/yelp-document.c
index 1a1cbb6..215586e 100644
--- a/libyelp/yelp-document.c
+++ b/libyelp/yelp-document.c
@@ -31,6 +31,7 @@
 #include "yelp-document.h"
 #include "yelp-error.h"
 #include "yelp-docbook-document.h"
+#include "yelp-help-list.h"
 #include "yelp-info-document.h"
 #include "yelp-mallard-document.h"
 #include "yelp-man-document.h"
@@ -195,8 +196,8 @@ yelp_document_get_for_uri (YelpUri *uri)
     case YELP_URI_DOCUMENT_TYPE_INFO:
         document = yelp_info_document_new (uri);
         break;
-    case YELP_URI_DOCUMENT_TYPE_TOC:
-        /* FIXME */
+    case YELP_URI_DOCUMENT_TYPE_HELP_LIST:
+        document = yelp_help_list_new (uri);
         break;
     case YELP_URI_DOCUMENT_TYPE_SEARCH:
         /* FIXME */
diff --git a/libyelp/yelp-help-list.c b/libyelp/yelp-help-list.c
new file mode 100644
index 0000000..f1cb09a
--- /dev/null
+++ b/libyelp/yelp-help-list.c
@@ -0,0 +1,527 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 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/gi18n.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <libxml/xpath.h>
+
+#include "yelp-help-list.h"
+#include "yelp-settings.h"
+
+typedef struct _HelpListEntry HelpListEntry;
+
+static void           yelp_help_list_class_init      (YelpHelpListClass     *klass);
+static void           yelp_help_list_init            (YelpHelpList          *list);
+static void           yelp_help_list_dispose         (GObject               *object);
+static void           yelp_help_list_finalize        (GObject               *object);
+
+static gboolean       help_list_request_page         (YelpDocument          *document,
+                                                      const gchar           *page_id,
+                                                      GCancellable          *cancellable,
+                                                      YelpDocumentCallback   callback,
+                                                      gpointer               user_data);
+static void           help_list_think                (YelpHelpList          *list);
+static void           help_list_handle_page          (YelpHelpList          *list,
+                                                      const gchar           *page_id);
+static void           help_list_process_docbook      (YelpHelpList          *list,
+                                                      HelpListEntry         *entry);
+static void           help_list_process_mallard      (YelpHelpList          *list,
+                                                      HelpListEntry         *entry);
+
+struct _HelpListEntry
+{
+    gchar *id;
+    gchar *title;
+    gchar *desc;
+
+    gchar *filename;
+    YelpUriDocumentType type;
+};
+static void
+help_list_entry_free (HelpListEntry *entry)
+{
+    g_free (entry->id);
+    g_free (entry->title);
+    g_free (entry->desc);
+    g_free (entry);
+}
+static gint
+help_list_entry_cmp (HelpListEntry *a, HelpListEntry *b)
+{
+    gchar *as, *bs;
+    as = a->title ? a->title : strchr (a->id, ':') + 1;
+    bs = b->title ? b->title : strchr (b->id, ':') + 1;
+    return g_utf8_collate (as, bs);
+}
+
+G_DEFINE_TYPE (YelpHelpList, yelp_help_list, YELP_TYPE_DOCUMENT);
+#define GET_PRIV(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_HELP_LIST, YelpHelpListPrivate))
+
+typedef struct _YelpHelpListPrivate  YelpHelpListPrivate;
+struct _YelpHelpListPrivate {
+    GMutex        *mutex;
+    GThread       *thread;
+
+    gboolean process_running;
+    gboolean process_ran;
+
+    GHashTable    *entries;
+    GList         *all_entries;
+    GSList        *pending;
+
+    xmlXPathCompExprPtr  get_docbook_title;
+    xmlXPathCompExprPtr  get_mallard_title;
+};
+
+static void
+yelp_help_list_class_init (YelpHelpListClass *klass)
+{
+    GObjectClass      *object_class   = G_OBJECT_CLASS (klass);
+    YelpDocumentClass *document_class = YELP_DOCUMENT_CLASS (klass);
+
+    object_class->dispose = yelp_help_list_dispose;
+    object_class->finalize = yelp_help_list_finalize;
+
+    document_class->request_page = help_list_request_page;
+
+    g_type_class_add_private (klass, sizeof (YelpHelpListPrivate));
+}
+
+static void
+yelp_help_list_init (YelpHelpList *list)
+{
+    YelpHelpListPrivate *priv = GET_PRIV (list);
+
+    priv->mutex = g_mutex_new ();
+    priv->entries = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                           g_free,
+                                           (GDestroyNotify) help_list_entry_free);
+
+    priv->get_docbook_title = xmlXPathCompile ("normalize-space("
+                                               "( /*/title | /*/db:title"
+                                               "| /*/articleinfo/title"
+                                               "| /*/bookinfo/title"
+                                               "| /*/db:info/db:title"
+                                               ")[1])");
+    priv->get_mallard_title = xmlXPathCompile ("normalize-space((/mal:page/mal:info/mal:title[ type='text'] |"
+                                               "                 /mal:page/mal:title)[1])");
+
+    yelp_document_set_page_id ((YelpDocument *) list, NULL, "index");
+    yelp_document_set_page_id ((YelpDocument *) list, "index", "index");
+}
+
+static void
+yelp_help_list_dispose (GObject *object)
+{
+    G_OBJECT_CLASS (yelp_help_list_parent_class)->dispose (object);
+}
+
+static void
+yelp_help_list_finalize (GObject *object)
+{
+    YelpHelpListPrivate *priv = GET_PRIV (object);
+
+    g_hash_table_destroy (priv->entries);
+    g_mutex_free (priv->mutex);
+
+    if (priv->get_docbook_title)
+        xmlXPathFreeCompExpr (priv->get_docbook_title);
+    if (priv->get_mallard_title)
+        xmlXPathFreeCompExpr (priv->get_mallard_title);
+
+    G_OBJECT_CLASS (yelp_help_list_parent_class)->finalize (object);
+}
+
+YelpDocument *
+yelp_help_list_new (YelpUri *uri)
+{
+    return g_object_new (YELP_TYPE_HELP_LIST, NULL);
+}
+
+/******************************************************************************/
+
+static gboolean
+help_list_request_page (YelpDocument          *document,
+                        const gchar           *page_id,
+                        GCancellable          *cancellable,
+                        YelpDocumentCallback   callback,
+                        gpointer               user_data)
+{
+    gboolean handled;
+    YelpHelpListPrivate *priv = GET_PRIV (document);
+
+    if (page_id == NULL)
+        page_id = "index";
+
+    handled =
+        YELP_DOCUMENT_CLASS (yelp_help_list_parent_class)->request_page (document,
+                                                                         page_id,
+                                                                         cancellable,
+                                                                         callback,
+                                                                         user_data);
+    if (handled) {
+        return TRUE;
+    }
+
+    g_mutex_lock (priv->mutex);
+    if (priv->process_ran) {
+        help_list_handle_page ((YelpHelpList *) document, page_id);
+        return TRUE;
+    }
+
+    if (!priv->process_running) {
+        priv->process_running = TRUE;
+        g_object_ref (document);
+        priv->thread = g_thread_create ((GThreadFunc) help_list_think,
+                                        document, FALSE, NULL);
+    }
+    priv->pending = g_slist_prepend (priv->pending, g_strdup (page_id));
+    g_mutex_unlock (priv->mutex);
+    return TRUE;
+}
+
+static void
+help_list_think (YelpHelpList *list)
+{
+    const gchar * const *sdatadirs = g_get_system_data_dirs ();
+    const gchar * const *langs = g_get_language_names ();
+    YelpHelpListPrivate *priv = GET_PRIV (list);
+    /* The strings are still owned by GLib; we just own the array. */
+    gchar **datadirs;
+    gint datadir_i, subdir_i, lang_i;
+    GList *cur;
+
+    datadirs = g_new0 (gchar *, g_strv_length ((gchar **) sdatadirs) + 2);
+    datadirs[0] = (gchar *) g_get_user_data_dir ();
+    for (datadir_i = 0; sdatadirs[datadir_i]; datadir_i++)
+        datadirs[datadir_i + 1] = (gchar *) sdatadirs[datadir_i];
+
+    for (datadir_i = 0; datadirs[datadir_i]; datadir_i++) {
+        gchar *helpdirname = g_build_filename (datadirs[datadir_i], "gnome", "help", NULL);       
+        GFile *helpdir = g_file_new_for_path (helpdirname);
+        GFileEnumerator *children = g_file_enumerate_children (helpdir,
+                                                               G_FILE_ATTRIBUTE_STANDARD_TYPE","
+                                                               G_FILE_ATTRIBUTE_STANDARD_NAME,
+                                                               G_FILE_QUERY_INFO_NONE,
+                                                               NULL, NULL);
+        GFileInfo *child;
+        if (children == NULL) {
+            g_object_unref (helpdir);
+            g_free (helpdirname);
+            continue;
+        }
+        while (child = g_file_enumerator_next_file (children, NULL, NULL)) {
+            gchar *docid;
+            HelpListEntry *entry = NULL;
+
+            if (g_file_info_get_file_type (child) != G_FILE_TYPE_DIRECTORY)
+                continue;
+
+            docid = g_strconcat ("ghelp:", g_file_info_get_name (child), NULL);
+            if (g_hash_table_lookup (priv->entries, docid)) {
+                g_free (docid);
+                g_object_unref (child);
+                continue;
+            }
+
+            for (lang_i = 0; langs[lang_i]; lang_i++) {
+                gchar *filename, *tmp;
+
+                filename = g_build_filename (helpdirname,
+                                            g_file_info_get_name (child),
+                                            langs[lang_i],
+                                            "index.page",
+                                             NULL);
+                if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
+                    entry = g_new0 (HelpListEntry, 1);
+                    entry->id = g_strdup (docid);
+                    entry->filename = filename;
+                    entry->type = YELP_URI_DOCUMENT_TYPE_MALLARD;
+                    break;
+                }
+                g_free (filename);
+
+                tmp = g_strdup_printf ("%s.xml", g_file_info_get_name (child));
+                filename = g_build_filename (helpdirname,
+                                             g_file_info_get_name (child),
+                                             langs[lang_i],
+                                             tmp,
+                                             NULL);
+                g_free (tmp);
+                if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
+                    entry = g_new0 (HelpListEntry, 1);
+                    entry->id = g_strdup (docid);
+                    entry->filename = filename;
+                    entry->type = YELP_URI_DOCUMENT_TYPE_DOCBOOK;
+                    break;
+                }
+                g_free (filename);
+            }
+
+            if (entry != NULL) {
+                g_hash_table_insert (priv->entries, docid, entry);
+                priv->all_entries = g_list_prepend (priv->all_entries, entry);
+            }
+            else
+                g_free (docid);
+            g_object_unref (child);
+        }
+        g_object_unref (children);
+        g_object_unref (helpdir);
+        g_free (helpdirname);
+    }
+    g_free (datadirs);
+
+    for (cur = priv->all_entries; cur != NULL; cur = cur->next) {
+        HelpListEntry *entry = (HelpListEntry *) cur->data;
+        if (entry->type == YELP_URI_DOCUMENT_TYPE_MALLARD)
+            help_list_process_mallard (list, entry);
+        else if (entry->type == YELP_URI_DOCUMENT_TYPE_DOCBOOK)
+            help_list_process_docbook (list, entry);
+    }
+
+    g_mutex_lock (priv->mutex);
+    priv->process_running = FALSE;
+    priv->process_ran = TRUE;
+    while (priv->pending) {
+        gchar *page_id = (gchar *) priv->pending->data;
+        help_list_handle_page (list, page_id);
+        g_free (page_id);
+        priv->pending = g_slist_delete_link (priv->pending, priv->pending);
+    }
+    g_mutex_unlock (priv->mutex);
+
+    g_object_unref (list);
+}
+
+/* This function expects to be called inside a locked mutex */
+static void
+help_list_handle_page (YelpHelpList *list,
+                       const gchar  *page_id)
+{
+    gchar *tmp, *c1, *c2;
+    GList *cur;
+    YelpHelpListPrivate *priv = GET_PRIV (list);
+    YelpSettings *settings = yelp_settings_get_default ();
+    GString *string = g_string_new
+        ("<html><head><style type='text/css'>\n"
+         "html { height: 100%; }\n"
+         "body { margin: 0; padding: 0; max-width: 100%;");
+    c1 = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_BASE);
+    c2 = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_TEXT);
+    tmp = g_markup_printf_escaped ("background-color: %s; color: %s; }\n", c1, c2);
+    g_string_append (string, tmp);
+    g_free (c1); g_free (c2); g_free (tmp);
+
+#if 0
+    "  direction: </xsl:text><xsl:value-of select="$direction"/><xsl:text>;"
+#endif
+    g_string_append (string,
+                     "div.body { margin: 0 12px 0 12px; padding: 0;"
+                     " max-width: 60em; min-height: 20em; }\n"
+                     "div.header { max-width: 100%; width: 100%;"
+                     " padding: 0; margin: 0 0 1em 0; }\n"
+                     "div.footer { max-width: 60em; }\n"
+                     "div.sect { margin-top: 1.72em; }\n"
+                     "div.trails { margin: 0; padding: 0.2em 12px 0 12px;");
+    
+    c1 = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_GRAY_BASE);
+    c2 = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_GRAY_BORDER);
+    tmp = g_markup_printf_escaped (" background-color: %s;"
+                                   " border-bottom: solid 1px %s; }\n",
+                                   c1, c2);
+    g_string_append (string, tmp);
+    g_free (c1); g_free (tmp); /* don't free c2; use it again soon */
+
+    g_string_append (string,
+                     "div.trail { margin: 0 1em 0.2em 1em; padding: 0; text-indent: -1em;");
+
+    c1 = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_TEXT_LIGHT);
+    tmp = g_markup_printf_escaped (" color: %s; }\n", c1);
+    g_string_append (string, tmp);
+    g_free (tmp); /* don't free c1; use it again soon */
+
+    g_string_append (string,
+                     "a.trail { white-space: nowrap; }\n"
+                     "div.hgroup { margin: 0 0 0.5em 0;");
+    
+    tmp = g_markup_printf_escaped (" color: %s;"
+                                   " border-bottom: solid 1px %s; }\n",
+                                   c1, c2);
+    g_string_append (string, tmp);
+    g_free (c2); g_free (tmp); /* free c2; still don't free c1 */
+
+    g_string_append (string,
+                     "h1, h2, h3, h4, h5, h6, h7 { margin: 0; padding: 0; font-weight: bold;");
+
+    tmp = g_markup_printf_escaped (" color: %s; }\n", c1);
+    g_string_append (string, tmp);
+    g_free (c1); g_free (tmp); /* now we free c1 */
+
+    g_string_append (string,
+                     "h1 { font-size: 1.44em; }\n"
+                     "h2 { font-size: 1.2em; }"
+                     "h3.title, h4.title, h5.title, h6.title, h7.title { font-size: 1.2em; }"
+                     "h3, h4, h5, h6, h7 { font-size: 1em; }"
+                     "p { line-height: 1.72em; }"
+                     "div, pre, p { margin: 1em 0 0 0; padding: 0; }"
+                     "div:first-child, pre:first-child, p:first-child { margin-top: 0; }"
+                     "div.inner, div.contents, pre.contents { margin-top: 0; }"
+                     "p img { vertical-align: middle; }"
+                     "a {"
+                     "  text-decoration: none;");
+
+    c1 = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_LINK);
+    c2 = yelp_settings_get_color (settings, YELP_SETTINGS_COLOR_LINK_VISITED);
+    tmp = g_markup_printf_escaped (" color: %s; } a:visited { color: %s; }",
+                                   c1, c2);
+    g_string_append (string, tmp);
+    g_free (c1); g_free (c2); g_free (tmp);
+
+    g_string_append (string,
+                     "a:hover { text-decoration: underline; }\n"
+                     "a img { border: none; }\n"
+                     "</style>\n");
+
+    tmp = g_markup_printf_escaped ("<title>%s</title>",
+                                   _("All Help Documents"));
+    g_string_append (string, tmp);
+    g_free (tmp);
+
+    g_string_append (string,
+                     "</head><body>"
+                     "<div class='header'></div>"
+                     "<div class='body'><div class='hgroup'>");
+    tmp = g_markup_printf_escaped ("<h1>%s</h1></div>\n",
+                                   _("All Help Documents"));
+    g_string_append (string, tmp);
+    g_free (tmp);
+
+    priv->all_entries = g_list_sort (priv->all_entries,
+                                     (GCompareFunc) help_list_entry_cmp);
+    for (cur = priv->all_entries; cur != NULL; cur = cur->next) {
+        HelpListEntry *entry = (HelpListEntry *) cur->data;
+        if (entry->title != NULL)
+            tmp = g_markup_printf_escaped ("<p><a href='%s'>%s</a></p>\n",
+                                           entry->id, entry->title);
+        else
+            tmp = g_markup_printf_escaped ("<p><a href='%s'>%s</a></p>\n",
+                                           entry->id, strchr (entry->id, ':') + 1);
+        g_string_append (string, tmp);
+        g_free (tmp);
+    }
+
+    g_string_append (string,
+                     "</div>"
+                     "<div class='footer'></div>"
+                     "</body></html>");
+
+    yelp_document_give_contents (YELP_DOCUMENT (list), page_id,
+                                 string->str,
+                                 "text/html");
+    g_string_free (string, FALSE);
+    yelp_document_signal (YELP_DOCUMENT (list), page_id,
+                          YELP_DOCUMENT_SIGNAL_CONTENTS, NULL);
+}
+
+
+static void
+help_list_process_docbook (YelpHelpList  *list,
+                           HelpListEntry *entry)
+{
+    xmlParserCtxtPtr parserCtxt;
+    xmlDocPtr xmldoc;
+    xmlXPathContextPtr xpath;
+    xmlXPathObjectPtr obj = NULL;
+    YelpHelpListPrivate *priv = GET_PRIV (list);
+
+    parserCtxt = xmlNewParserCtxt ();
+    xmldoc = xmlCtxtReadFile (parserCtxt,
+                              (const char *) entry->filename, NULL,
+                              XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+                              XML_PARSE_NOENT   | XML_PARSE_NONET   );
+    xmlFreeParserCtxt (parserCtxt);
+    if (xmldoc == NULL)
+        return;
+
+    xmlXIncludeProcessFlags (xmldoc,
+                             XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+                             XML_PARSE_NOENT   | XML_PARSE_NONET   );
+
+    xpath = xmlXPathNewContext (xmldoc);
+    xmlXPathRegisterNs (xpath, BAD_CAST "db",
+                        BAD_CAST "http://docbook.org/ns/docbook";);
+    obj = xmlXPathCompiledEval (priv->get_docbook_title, xpath);
+    if (obj) {
+        if (obj->stringval)
+            entry->title = g_strdup (obj->stringval);
+        xmlXPathFreeObject (obj);
+    }
+
+    if (xmldoc)
+        xmlFreeDoc (xmldoc);
+    if (xpath)
+        xmlXPathFreeContext (xpath);
+}
+
+static void
+help_list_process_mallard (YelpHelpList  *list,
+                           HelpListEntry *entry)
+{
+    xmlParserCtxtPtr parserCtxt;
+    xmlDocPtr xmldoc;
+    xmlXPathContextPtr xpath;
+    xmlXPathObjectPtr obj = NULL;
+    YelpHelpListPrivate *priv = GET_PRIV (list);
+
+    parserCtxt = xmlNewParserCtxt ();
+    xmldoc = xmlCtxtReadFile (parserCtxt,
+                              (const char *) entry->filename, NULL,
+                              XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+                              XML_PARSE_NOENT   | XML_PARSE_NONET   );
+    xmlFreeParserCtxt (parserCtxt);
+    if (xmldoc == NULL)
+        return;
+
+    xmlXIncludeProcessFlags (xmldoc,
+                             XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+                             XML_PARSE_NOENT   | XML_PARSE_NONET   );
+
+    xpath = xmlXPathNewContext (xmldoc);
+    xmlXPathRegisterNs (xpath, BAD_CAST "mal",
+                        BAD_CAST "http://projectmallard.org/1.0/";);
+    obj = xmlXPathCompiledEval (priv->get_mallard_title, xpath);
+    if (obj) {
+        if (obj->stringval)
+            entry->title = g_strdup (obj->stringval);
+        xmlXPathFreeObject (obj);
+    }
+    if (xmldoc)
+        xmlFreeDoc (xmldoc);
+    if (xpath)
+        xmlXPathFreeContext (xpath);
+}
diff --git a/libyelp/yelp-help-list.h b/libyelp/yelp-help-list.h
new file mode 100644
index 0000000..4cfd7e1
--- /dev/null
+++ b/libyelp/yelp-help-list.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 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_HELP_LIST_H__
+#define __YELP_HELP_LIST_H__
+
+#include <glib-object.h>
+
+#include "yelp-document.h"
+
+#define YELP_TYPE_HELP_LIST         (yelp_help_list_get_type ())
+#define YELP_HELP_LIST(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_HELP_LIST, YelpHelpList))
+#define YELP_HELP_LIST_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_HELP_LIST, YelpHelpListClass))
+#define YELP_IS_HELP_LIST(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_HELP_LIST))
+#define YELP_IS_HELP_LIST_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_HELP_LIST))
+#define YELP_HELP_LIST_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_HELP_LIST, YelpHelpListClass))
+
+typedef struct _YelpHelpList      YelpHelpList;
+typedef struct _YelpHelpListClass YelpHelpListClass;
+
+struct _YelpHelpList {
+    YelpDocument      parent;
+};
+
+struct _YelpHelpListClass {
+    YelpDocumentClass parent_class;
+};
+
+GType           yelp_help_list_get_type     (void);
+YelpDocument *  yelp_help_list_new          (YelpUri *uri);
+
+#endif /* __YELP_HELP_LIST_H__ */
diff --git a/libyelp/yelp-uri.c b/libyelp/yelp-uri.c
index 9735b05..7010a24 100644
--- a/libyelp/yelp-uri.c
+++ b/libyelp/yelp-uri.c
@@ -50,6 +50,7 @@ static void           resolve_data_dirs          (YelpUri        *uri,
                                                   gboolean        langfirst);
 static void           resolve_ghelp_uri          (YelpUri        *uri);
 static void           resolve_help_uri           (YelpUri        *uri);
+static void           resolve_help_list_uri      (YelpUri        *uri);
 static void           resolve_man_uri            (YelpUri        *uri);
 static void           resolve_info_uri           (YelpUri        *uri);
 static void           resolve_xref_uri           (YelpUri        *uri);
@@ -263,6 +264,9 @@ resolve_async (YelpUri *uri)
     else if (g_str_has_prefix (priv->res_arg, "help:")) {
         resolve_help_uri (uri);
     }
+    else if (g_str_has_prefix (priv->res_arg, "help-list:")) {
+        resolve_help_list_uri (uri);
+    }
     else if (g_str_has_prefix (priv->res_arg, "file:")) {
         resolve_file_uri (uri);
     }
@@ -295,7 +299,7 @@ resolve_async (YelpUri *uri)
         case YELP_URI_DOCUMENT_TYPE_XHTML:
             resolve_file_path (uri);
             break;
-        case YELP_URI_DOCUMENT_TYPE_TOC:
+        case YELP_URI_DOCUMENT_TYPE_HELP_LIST:
             /* FIXME: what do we do? */
             break;
         case YELP_URI_DOCUMENT_TYPE_SEARCH:
@@ -795,6 +799,16 @@ resolve_help_uri (YelpUri *uri)
 }
 
 static void
+resolve_help_list_uri (YelpUri *uri)
+{
+    YelpUriPrivate *priv = GET_PRIV (uri);
+    priv->docuri = g_strdup ("help-list:");
+    priv->fulluri = g_strdup (priv->res_arg);
+    priv->page_id = g_strdup ("index");
+    priv->tmptype = YELP_URI_DOCUMENT_TYPE_HELP_LIST;
+}
+
+static void
 resolve_man_uri (YelpUri *uri)
 {
     YelpUriPrivate *priv = GET_PRIV (uri);
diff --git a/libyelp/yelp-uri.h b/libyelp/yelp-uri.h
index 13aa73b..86d7ae5 100644
--- a/libyelp/yelp-uri.h
+++ b/libyelp/yelp-uri.h
@@ -46,7 +46,7 @@ typedef enum {
     YELP_URI_DOCUMENT_TYPE_TEXT,
     YELP_URI_DOCUMENT_TYPE_HTML,
     YELP_URI_DOCUMENT_TYPE_XHTML,
-    YELP_URI_DOCUMENT_TYPE_TOC,
+    YELP_URI_DOCUMENT_TYPE_HELP_LIST,
     YELP_URI_DOCUMENT_TYPE_SEARCH,
     YELP_URI_DOCUMENT_TYPE_NOT_FOUND,
     YELP_URI_DOCUMENT_TYPE_EXTERNAL,
diff --git a/src/yelp-window.c b/src/yelp-window.c
index 1cc0df7..62cf04d 100644
--- a/src/yelp-window.c
+++ b/src/yelp-window.c
@@ -71,6 +71,8 @@ static void          window_drag_received         (YelpWindow         *window,
 static gboolean      window_resize_signal         (YelpWindow         *window);
 static void          window_close                 (GtkAction          *action,
                                                    YelpWindow         *window);
+static void          window_go_all                (GtkAction          *action,
+                                                   YelpWindow         *window);
 static void          window_add_bookmark          (GtkAction          *action,
                                                    YelpWindow         *window);
 static void          window_edit_bookmarks        (GtkAction          *action,
@@ -196,6 +198,8 @@ static const gchar *YELP_UI =
     "<separator/>"
     "<menuitem action='YelpViewGoPrevious'/>"
     "<menuitem action='YelpViewGoNext'/>"
+    "<separator/>"
+    "<menuitem action='GoAll'/>"
     "</menu>"
     "<menu action='BookmarksMenu'>"
     "<menuitem action='AddBookmark'/>"
@@ -275,6 +279,10 @@ static const GtkActionEntry entries[] = {
       "<Control>W",
       NULL,
       G_CALLBACK (window_close) },
+    { "GoAll", NULL,
+      N_("_All Documents"),
+      NULL, NULL,
+      G_CALLBACK (window_go_all) },
     { "AddBookmark", NULL,
       N_("_Add Bookmark"),
       "<Control>D",
@@ -747,6 +755,14 @@ window_close (GtkAction *action, YelpWindow *window)
 }
 
 static void
+window_go_all (GtkAction  *action,
+               YelpWindow *window)
+{
+    YelpWindowPrivate *priv = GET_PRIV (window);
+    yelp_view_load (priv->view, "help-list:");
+}
+
+static void
 window_add_bookmark (GtkAction  *action,
                      YelpWindow *window)
 {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]