summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun McCance <shaunm@src.gnome.org>2003-11-06 17:41:37 +0000
committerShaun McCance <shaunm@src.gnome.org>2003-11-06 17:41:37 +0000
commit3e436f20450845cd7b7a6516ce2e1fdcb8047182 (patch)
tree2c993cf680dd011aa36ecd54af2650ab697cc290
parent6aa64541f5ae6fe36386191bd33b7b1f6e9d3204 (diff)
downloadyelp-3e436f20450845cd7b7a6516ce2e1fdcb8047182.tar.gz
- New GObjectified URI code
* src/test-uri: * src/yelp-uri.c: * src/yelp-uri.h: - New GObjectified URI code * src/test-pager.c: * src/yelp-db-pager.c: * src/yelp-db-pager.h: * src/yelp-pager.c: * src/yelp-pager.h: - New transformation code
-rw-r--r--ChangeLog14
-rw-r--r--src/test-pager.c78
-rw-r--r--src/test-uri.c129
-rw-r--r--src/yelp-db-pager.c580
-rw-r--r--src/yelp-db-pager.h54
-rw-r--r--src/yelp-pager.c535
-rw-r--r--src/yelp-pager.h94
-rw-r--r--src/yelp-uri.c876
-rw-r--r--src/yelp-uri.h85
9 files changed, 1937 insertions, 508 deletions
diff --git a/ChangeLog b/ChangeLog
index fc0a5977..7b6967a1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2003-11-06 Shaun McCance <shaunm@gnome.org>
+
+ * src/test-uri:
+ * src/yelp-uri.c:
+ * src/yelp-uri.h:
+ - New GObjectified URI code
+
+ * src/test-pager.c:
+ * src/yelp-db-pager.c:
+ * src/yelp-db-pager.h:
+ * src/yelp-pager.c:
+ * src/yelp-pager.h:
+ - New transformation code
+
2003-10-12 Shaun McCance <shaunm@gnome.org>
* src/yelp-cache.c:
diff --git a/src/test-pager.c b/src/test-pager.c
new file mode 100644
index 00000000..2fb00335
--- /dev/null
+++ b/src/test-pager.c
@@ -0,0 +1,78 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2002 Shaun McCance
+ *
+ * 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, Cambridge, MA 02139, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+#include "yelp-pager.h"
+#include "yelp-db-pager.h"
+
+void list_sections (YelpPager *pager);
+void save_chunk (YelpPager *pager,
+ gchar *chunk_id);
+
+gint
+main (gint argc, gchar **argv)
+{
+ YelpURI *uri;
+ YelpPager *pager;
+
+ if (argc < 2) {
+ return 1;
+ }
+
+ g_type_init ();
+ g_thread_init (NULL);
+
+ uri = yelp_uri_new (argv[1]);
+ pager = yelp_db_pager_new (uri);
+
+ g_signal_connect (pager,
+ "sections",
+ G_CALLBACK (list_sections),
+ NULL);
+
+ g_signal_connect (pager,
+ "chunk",
+ G_CALLBACK (save_chunk),
+ NULL);
+
+ yelp_pager_start (pager);
+
+ gtk_main ();
+
+ return 0;
+}
+
+void save_chunk (YelpPager *pager, gchar *chunk_id)
+{
+ printf("save_chunk: %s\n", chunk_id);
+}
+
+void
+list_sections (YelpPager *pager)
+{
+ const GtkTreeModel *sections;
+
+ sections = yelp_pager_get_sections (pager);
+
+ printf ("%i\n", gtk_tree_model_get_n_columns (sections));
+}
diff --git a/src/test-uri.c b/src/test-uri.c
index 544db2d2..7f2d16d0 100644
--- a/src/test-uri.c
+++ b/src/test-uri.c
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* Copyright (C) 2002 Mikael Hallendal <micke@imendio.com>
*
@@ -26,68 +26,115 @@
#include <libgnome/gnome-program.h>
#include <libgnomevfs/gnome-vfs.h>
-
#include "yelp-uri.h"
static void
print_uri (YelpURI *uri)
{
- gchar *str_uri;
+ gchar *type;
+ gchar *str_uri;
- g_print ("URI_TYPE : %d\n", yelp_uri_get_type (uri));
- g_print ("URI_PATH : %s\n", yelp_uri_get_path (uri));
- g_print ("URI_SECTION: %s\n", yelp_uri_get_section (uri));
-
- str_uri = yelp_uri_to_string (uri);
- g_print ("URI_TO_STRING: %s\n", str_uri);
- g_free (str_uri);
+ switch (yelp_uri_get_resource_type (uri)) {
+ case YELP_URI_TYPE_UNKNOWN:
+ type = "YELP_URI_TYPE_UNKNOWN";
+ break;
+ case YELP_URI_TYPE_RELATIVE:
+ type = "YELP_URI_TYPE_RELATIVE";
+ break;
+ case YELP_URI_TYPE_DOCBOOK_XML:
+ type = "YELP_URI_TYPE_DOCBOOK_XML";
+ break;
+ case YELP_URI_TYPE_DOCBOOK_SGML:
+ type = "YELP_URI_TYPE_DOCBOOK_SGML";
+ break;
+ case YELP_URI_TYPE_GHELP:
+ type = "YELP_URI_TYPE_GHELP";
+ break;
+ case YELP_URI_TYPE_HTML:
+ type = "YELP_URI_TYPE_HTML";
+ break;
+ case YELP_URI_TYPE_MAN:
+ type = "YELP_URI_TYPE_MAN";
+ break;
+ case YELP_URI_TYPE_INFO:
+ type = "YELP_URI_TYPE_INFO";
+ break;
+ case YELP_URI_TYPE_TOC:
+ type = "YELP_URI_TYPE_TOC";
+ break;
+ case YELP_URI_TYPE_PATH:
+ type = "YELP_URI_TYPE_PATH";
+ break;
+ case YELP_URI_TYPE_FILE:
+ type = "YELP_URI_TYPE_FILE";
+ break;
+ default:
+ type = NULL;
+ break;
+ }
+ g_print ("TYPE : %s\n", type);
+ g_print ("PATH : %s\n", yelp_uri_get_path (uri));
+ if (yelp_uri_get_fragment (uri))
+ g_print ("FRAGMENT : %s\n", yelp_uri_get_fragment (uri));
+ g_print ("\n");
+
+ /*
+ str_uri = yelp_uri_to_string (uri);
+ g_print ("URI_TO_STRING: %s\n", str_uri);
+ g_free (str_uri);
+ */
}
int
main (int argc, char **argv)
{
- GnomeProgram *program;
- YelpURI *uri;
- YelpURI *rel_uri;
+ GnomeProgram *program;
+ YelpURI *uri;
+ YelpURI *rel_uri;
- if (argc < 2) {
- g_print ("Usage: test-uri uri\n");
- return 1;
- }
+ if (argc < 2) {
+ g_print ("Usage: test-uri uri\n");
+ return 1;
+ }
+
+ program = gnome_program_init (PACKAGE, VERSION,
+ LIBGNOME_MODULE,
+ argc, argv,
+ GNOME_PROGRAM_STANDARD_PROPERTIES,
+ NULL);
- program = gnome_program_init (PACKAGE, VERSION,
- LIBGNOME_MODULE,
- argc, argv,
- GNOME_PROGRAM_STANDARD_PROPERTIES,
- NULL);
+ gnome_vfs_init ();
- gnome_vfs_init ();
+ uri = yelp_uri_new (argv[1]);
- uri = yelp_uri_new (argv[1]);
-
- if (!yelp_uri_exists (uri)) {
- g_print ("URI (%s) does not exist\n", argv[1]);
+ /*
+ if (!yelp_uri_exists (uri)) {
+ g_print ("URI (%s) does not exist\n", argv[1]);
- return 1;
- }
+ return 1;
+ }
+ */
- print_uri (uri);
+ g_print ("STRING : %s\n", argv[1]);
+ print_uri (uri);
- g_print ("---------------\n");
+ /*
+ g_print ("---------------\n");
- rel_uri = yelp_uri_get_relative (uri, "?link");
- print_uri (rel_uri);
- yelp_uri_unref (rel_uri);
+ rel_uri = yelp_uri_get_relative (uri, "?link");
+ print_uri (rel_uri);
+ g_object_unref (rel_uri);
- g_print ("---------------\n");
+ g_print ("---------------\n");
- rel_uri = yelp_uri_get_relative (uri, "link");
- print_uri (rel_uri);
- yelp_uri_unref (rel_uri);
+ rel_uri = yelp_uri_get_relative (uri, "link");
+ print_uri (rel_uri);
+ g_object_unref (rel_uri);
+ */
- yelp_uri_unref (uri);
+ g_object_unref (uri);
- gnome_vfs_shutdown ();
+ gnome_vfs_shutdown ();
- return 0;
+ return 0;
}
diff --git a/src/yelp-db-pager.c b/src/yelp-db-pager.c
new file mode 100644
index 00000000..da8a2642
--- /dev/null
+++ b/src/yelp-db-pager.c
@@ -0,0 +1,580 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003 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 <libgnome/gnome-i18n.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxslt/xslt.h>
+#include <libxslt/templates.h>
+#include <libxslt/transform.h>
+#include <libxslt/extensions.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/xsltutils.h>
+
+#include "yelp-db-pager.h"
+
+#define YELP_NAMESPACE "http://www.gnome.org/yelp/ns"
+
+#define DB_STYLESHEET_PATH DATADIR"/sgml/docbook/yelp/"
+#define DB_STYLESHEET DB_STYLESHEET_PATH"db2html.xsl"
+
+#define MAX_CHUNK_DEPTH 2
+
+#define d(x)
+
+struct _YelpDBPagerPriv {
+ GMutex *sects_mutex;
+ GtkTreeModel *sects;
+
+ GMutex *frags_mutex;
+ GHashTable *frags_hash;
+};
+
+typedef struct _DBWalker DBWalker;
+struct _DBWalker {
+ YelpDBPager *pager;
+ gchar *chunk_id;
+
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+
+ GtkTreeIter *iter;
+
+ gint depth;
+};
+
+static void db_pager_class_init (YelpDBPagerClass *klass);
+static void db_pager_init (YelpDBPager *pager);
+static void db_pager_dispose (GObject *gobject);
+
+void db_pager_process (YelpPager *pager);
+void db_pager_cancel (YelpPager *pager);
+const gchar * db_pager_resolve_uri (YelpPager *pager,
+ YelpURI *uri);
+const GtkTreeModel * db_pager_get_sections (YelpPager *pager);
+
+static void walker_walk_xml (DBWalker *walker);
+gboolean walker_is_chunk (DBWalker *walker);
+
+gboolean xml_is_division (xmlNodePtr node);
+gboolean xml_is_info (xmlNodePtr node);
+gchar * xml_get_title (xmlNodePtr node);
+
+void xslt_yelp_document (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp);
+void xslt_yelp_cache (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp);
+
+static YelpPagerClass *parent_class;
+
+GType
+yelp_db_pager_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpDBPagerClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) db_pager_class_init,
+ NULL,
+ NULL,
+ sizeof (YelpDBPager),
+ 0,
+ (GInstanceInitFunc) db_pager_init,
+ };
+ type = g_type_register_static (YELP_TYPE_PAGER,
+ "YelpDBPager",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+db_pager_class_init (YelpDBPagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpPagerClass *pager_class = YELP_PAGER_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = db_pager_dispose;
+
+ pager_class->process = db_pager_process;
+ pager_class->cancel = db_pager_cancel;
+ pager_class->resolve_uri = db_pager_resolve_uri;
+ pager_class->get_sections = db_pager_get_sections;
+}
+
+static void
+db_pager_init (YelpDBPager *pager)
+{
+ YelpDBPagerPriv *priv;
+
+ priv = g_new0 (YelpDBPagerPriv, 1);
+ pager->priv = priv;
+
+ pager->priv->sects_mutex = g_mutex_new ();
+ pager->priv->sects = NULL;
+
+ pager->priv->frags_mutex = g_mutex_new ();
+ pager->priv->frags_hash =
+ g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+}
+
+static void
+db_pager_dispose (GObject *object)
+{
+ YelpDBPager *pager = YELP_DB_PAGER (object);
+
+ g_mutex_free (pager->priv->sects_mutex);
+ g_object_unref (pager->priv->sects);
+
+ g_mutex_free (pager->priv->frags_mutex);
+ g_hash_table_destroy (pager->priv->frags_hash);
+
+ g_free (pager->priv);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+/**
+ * yelp_db_pager_new:
+ * @uri: the URI of the DocBook document to process.
+ *
+ * Creates a new YelpDBPager.
+ **/
+YelpPager *
+yelp_db_pager_new (YelpURI *uri)
+{
+ YelpDBPager *pager;
+
+ g_return_val_if_fail (YELP_IS_URI (uri), NULL);
+
+ pager = (YelpDBPager *) g_object_new (YELP_TYPE_DB_PAGER,
+ "uri", uri,
+ NULL);
+
+ g_mutex_lock (pager->priv->sects_mutex);
+ pager->priv->sects =
+ GTK_TREE_MODEL (gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_STRING));
+ g_mutex_unlock (pager->priv->sects_mutex);
+
+ return (YelpPager *) pager;
+}
+
+void
+db_pager_process (YelpPager *pager)
+{
+ const YelpURI *uri = yelp_pager_get_uri (pager);
+ gchar *uri_str = yelp_uri_get_path ((YelpURI *) uri);
+ DBWalker *walker;
+ GError *error;
+
+ xmlParserCtxtPtr ctxt;
+ xsltStylesheetPtr stylesheet;
+ xsltTransformContextPtr tctxt;
+
+ gchar *uri_slash;
+ gchar *doc_name;
+ gchar *doc_path;
+ const gchar *params[9];
+
+ g_return_if_fail (pager != NULL);
+ g_return_if_fail (YELP_IS_DB_PAGER (pager));
+
+ g_object_ref (pager);
+
+ ctxt = xmlCreateFileParserCtxt (uri_str);
+ ctxt->replaceEntities = TRUE;
+ ctxt->validate = FALSE;
+ ctxt->loadsubset = TRUE;
+ xmlParseDocument (ctxt);
+
+ if (ctxt->myDoc == NULL) {
+ error = NULL;
+ yelp_pager_error (pager, error);
+
+ return;
+ }
+
+ walker = g_new0 (DBWalker, 1);
+ walker->pager = YELP_DB_PAGER (pager);
+ walker->doc = ctxt->myDoc;
+ walker->cur = xmlDocGetRootElement (walker->doc);
+
+ walker_walk_xml (walker);
+
+ yelp_pager_lock_state (pager);
+ g_signal_emit_by_name (pager, "sections");
+ yelp_pager_unlock_state (pager);
+
+ uri_slash = g_strrstr (uri_str, "/");
+ doc_name = g_strndup (uri_str, uri_slash - uri_str + 1);
+ doc_path = g_strdup (uri_slash + 1);
+
+ params[0] = "doc_name";
+ params[1] = g_strconcat("\"", doc_name, "\"", NULL) ;
+ params[2] = "doc_path";
+ params[3] = g_strconcat("\"file://", doc_path, "/\"", NULL) ;
+ params[4] = "stylesheet_path";
+ params[5] = g_strconcat("\"file://", DB_STYLESHEET_PATH, "/\"", NULL) ;
+ params[6] = "chunk_depth";
+ params[7] = "2";
+ params[8] = NULL;
+
+ stylesheet = xsltParseStylesheetFile (DB_STYLESHEET);
+ tctxt = xsltNewTransformContext (stylesheet,
+ ctxt->myDoc);
+ tctxt->_private = pager;
+ xsltRegisterExtElement (tctxt,
+ "document",
+ YELP_NAMESPACE,
+ (xsltTransformFunction) xslt_yelp_document);
+ xsltRegisterExtElement (tctxt,
+ "cache",
+ YELP_NAMESPACE,
+ (xsltTransformFunction) xslt_yelp_cache);
+ xsltApplyStylesheetUser (stylesheet,
+ ctxt->myDoc,
+ params,
+ NULL, NULL,
+ tctxt);
+
+ xsltFreeStylesheet (stylesheet);
+ xmlFreeParserCtxt (ctxt);
+
+ g_free (doc_name);
+ g_free (doc_path);
+
+ yelp_pager_lock_state (pager);
+ yelp_pager_set_state (pager, YELP_PAGER_STATE_FINISH);
+ g_signal_emit_by_name (pager, "finish");
+ yelp_pager_unlock_state (pager);
+
+ g_object_unref (pager);
+}
+
+void
+db_pager_cancel (YelpPager *pager)
+{
+}
+
+const gchar *
+db_pager_resolve_uri (YelpPager *pager, YelpURI *uri)
+{
+ YelpDBPager *db_pager;
+ gchar *frag_id;
+ const gchar *chunk_id;
+
+ g_return_val_if_fail (pager != NULL, NULL);
+ g_return_val_if_fail (YELP_IS_DB_PAGER (pager), NULL);
+
+ db_pager = YELP_DB_PAGER (pager);
+
+ frag_id = yelp_uri_get_fragment (uri);
+
+ g_mutex_lock (db_pager->priv->frags_mutex);
+ chunk_id =
+ (const gchar *) g_hash_table_lookup (db_pager->priv->frags_hash,
+ frag_id);
+ g_mutex_unlock (db_pager->priv->frags_mutex);
+
+ g_free (frag_id);
+ return chunk_id;
+}
+
+const GtkTreeModel *
+db_pager_get_sections (YelpPager *pager)
+{
+ g_return_val_if_fail (pager != NULL, NULL);
+ g_return_val_if_fail (YELP_IS_DB_PAGER (pager), NULL);
+
+ return YELP_DB_PAGER (pager)->priv->sects;
+}
+
+void
+xslt_yelp_document (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp)
+{
+ GError *error;
+ xmlChar *chunk_id = NULL;
+ xmlChar *chunk_buf;
+ gint buf_size;
+ YelpPager *pager;
+ xsltStylesheetPtr style = NULL;
+ const char *old_outfile;
+ xmlDocPtr new_doc, old_doc;
+ xmlNodePtr old_insert;
+
+ if (!ctxt || !node || !inst || !comp)
+ return;
+
+ pager = (YelpPager *) ctxt->_private;
+
+ chunk_id = xsltEvalAttrValueTemplate (ctxt, inst,
+ (const xmlChar *) "href",
+ NULL);
+ if (chunk_id == NULL) {
+ xsltTransformError (ctxt, NULL, inst,
+ _("No href attribute found on yelp:document"));
+ error = NULL;
+ yelp_pager_error (pager, error);
+
+ return;
+ }
+
+ old_outfile = ctxt->outputFile;
+ old_doc = ctxt->output;
+ old_insert = ctxt->insert;
+ ctxt->outputFile = (const char *) chunk_id;
+
+ style = xsltNewStylesheet ();
+ if (style == NULL) {
+ xsltTransformError (ctxt, NULL, inst,
+ _("Out of memory"));
+ error = NULL;
+ yelp_pager_error (pager, error);
+
+ return;
+ }
+
+ style->omitXmlDeclaration = TRUE;
+
+ new_doc = xmlNewDoc ("1.0");
+ new_doc->charset = XML_CHAR_ENCODING_UTF8;
+ ctxt->output = new_doc;
+ ctxt->insert = (xmlNodePtr) new_doc;
+
+ xsltApplyOneTemplate (ctxt, node, inst->children, NULL, NULL);
+
+ xmlDocDumpFormatMemory (new_doc, &chunk_buf, &buf_size, 0);
+
+ ctxt->outputFile = old_outfile;
+ ctxt->output = old_doc;
+ ctxt->insert = old_insert;
+
+ yelp_pager_lock_state (pager);
+
+ yelp_pager_add_chunk (pager, chunk_id, chunk_buf);
+ g_signal_emit_by_name (pager, "chunk", chunk_id);
+
+ yelp_pager_unlock_state (pager);
+
+ xmlFreeDoc (new_doc);
+}
+
+void
+xslt_yelp_cache (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp)
+{
+}
+
+static void
+walker_walk_xml (DBWalker *walker)
+{
+ xmlChar *id = NULL;
+ xmlChar *title = NULL;
+ gchar *old_id;
+ xmlNodePtr cur;
+ xmlNodePtr old_cur;
+ GtkTreeIter iter;
+ GtkTreeIter *old_iter;
+ YelpDBPagerPriv *priv = walker->pager->priv;
+
+ id = xmlGetProp (walker->cur, "id");
+
+ if (walker_is_chunk (walker)) {
+ if (xml_is_info (walker->cur)) {
+ xmlFree (id);
+ id = g_strdup ("titlepage");
+ }
+
+ title = xml_get_title (walker->cur);
+
+ if (id) {
+ gtk_tree_store_append (GTK_TREE_STORE (priv->sects),
+ &iter, walker->iter);
+
+ gtk_tree_store_set (GTK_TREE_STORE (priv->sects),
+ &iter,
+ 0, g_strdup (id),
+ 1, g_strdup (title),
+ -1);
+
+ old_id = walker->chunk_id;
+ walker->chunk_id = id;
+
+ old_iter = walker->iter;
+ walker->iter = &iter;
+ }
+ }
+
+ old_cur = walker->cur;
+ walker->depth++;
+
+ if (id) {
+ g_mutex_lock (priv->frags_mutex);
+ g_hash_table_insert (priv->frags_hash,
+ g_strdup (id),
+ g_strdup (walker->chunk_id));
+ g_mutex_unlock (priv->frags_mutex);
+ }
+
+ cur = walker->cur->children;
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ walker->cur = cur;
+ walker_walk_xml (walker);
+ }
+ cur = cur->next;
+ }
+
+ walker->depth--;
+ walker->cur = old_cur;
+
+ if (walker_is_chunk (walker) && id) {
+ walker->iter = old_iter;
+ walker->chunk_id = old_id;
+ }
+
+ xmlFree (id);
+ xmlFree (title);
+}
+
+gchar *
+xml_get_title (xmlNodePtr node)
+{
+ gchar *title = NULL;
+ xmlNodePtr cur;
+
+ if (xml_is_info (node))
+ title = _("Titlepage");
+ else if (node->parent->type == XML_DOCUMENT_NODE)
+ title = _("Contents");
+ else {
+ cur = node->children;
+ while (cur != NULL) {
+ if (cur->name == (xmlChar *) "title") {
+ if (title)
+ g_free (title);
+ title = xmlNodeGetContent (cur);
+ }
+ else if (cur->name == (xmlChar *) "titleabbrev") {
+ if (title)
+ g_free (title);
+ title = xmlNodeGetContent (cur);
+ break;
+ }
+
+ cur = cur->next;
+ }
+ }
+
+ return title;
+}
+
+gboolean
+walker_is_chunk (DBWalker *walker)
+{
+ if (walker->depth <= MAX_CHUNK_DEPTH) {
+ if (xml_is_division (walker->cur))
+ return TRUE;
+ else if (walker->depth == 1 && xml_is_info (walker->cur))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+gboolean
+xml_is_division (xmlNodePtr node)
+{
+ return (!xmlStrcmp (node->name, (const xmlChar *) "appendix") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "article") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "book") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "bibliography") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "chapter") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "colophon") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "glossary") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "index") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "part") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "preface") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "reference") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refentry") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect1") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect2") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect3") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsection") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect1") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect2") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect3") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect4") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect5") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "section") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "set") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "setindex") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "simplesect") );
+}
+
+gboolean
+xml_is_info (xmlNodePtr node)
+{
+ return (!xmlStrcmp (node->name, (const xmlChar *) "appendixinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "articleinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "bookinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "bibliographyinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "chapterinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "glossaryinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "indexinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "partinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "prefaceinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "referenceinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refentryinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect1info") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect2info") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsect3info") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "refsectioninfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect1info") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect2info") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect3info") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect4info") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sect5info") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "sectioninfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "setinfo") ||
+ !xmlStrcmp (node->name, (const xmlChar *) "setindexinfo") );
+}
diff --git a/src/yelp-db-pager.h b/src/yelp-db-pager.h
new file mode 100644
index 00000000..2cbb2f78
--- /dev/null
+++ b/src/yelp-db-pager.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003 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_DB_PAGER_H__
+#define __YELP_DB_PAGER_H__
+
+#include <glib-object.h>
+
+#include "yelp-pager.h"
+
+#define YELP_TYPE_DB_PAGER (yelp_db_pager_get_type ())
+#define YELP_DB_PAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_DB_PAGER, YelpDBPager))
+#define YELP_DB_PAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_DB_PAGER, YelpDBPagerClass))
+#define YELP_IS_DB_PAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_DB_PAGER))
+#define YELP_IS_DB_PAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_DB_PAGER))
+#define YELP_DB_PAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_DB_PAGER, YelpDBPagerClass))
+
+typedef struct _YelpDBPager YelpDBPager;
+typedef struct _YelpDBPagerClass YelpDBPagerClass;
+typedef struct _YelpDBPagerPriv YelpDBPagerPriv;
+
+struct _YelpDBPager {
+ YelpPager parent;
+
+ YelpDBPagerPriv *priv;
+};
+
+struct _YelpDBPagerClass {
+ YelpPagerClass parent_class;
+};
+
+GType yelp_db_pager_get_type (void);
+YelpPager * yelp_db_pager_new (YelpURI *uri);
+
+#endif /* __YELP_DB_PAGER_H__ */
diff --git a/src/yelp-pager.c b/src/yelp-pager.c
new file mode 100644
index 00000000..c07fa689
--- /dev/null
+++ b/src/yelp-pager.c
@@ -0,0 +1,535 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003 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 <libgnome/gnome-i18n.h>
+
+#include "yelp-pager.h"
+#include "yelp-marshal.h"
+#include "yelp-uri.h"
+
+#define d(x)
+
+struct _YelpPagerPriv {
+ YelpURI *uri;
+
+ GMutex *state_mutex;
+ YelpPagerState state;
+
+ GMutex *error_mutex;
+ GError *error;
+
+ GMutex *chunk_mutex;
+ GHashTable *chunk_hash;
+};
+
+enum {
+ PROP_0,
+ PROP_URI
+};
+
+enum {
+ START,
+ SECTIONS,
+ CHUNK,
+ FINISH,
+ CANCEL,
+ ERROR,
+ LAST_SIGNAL
+};
+
+static void pager_class_init (YelpPagerClass *klass);
+static void pager_init (YelpPager *pager);
+static void pager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void pager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void pager_dispose (GObject *object);
+
+
+static GObjectClass *parent_class;
+static gint signals[LAST_SIGNAL] = { 0 };
+
+GType
+yelp_pager_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpPagerClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) pager_class_init,
+ NULL,
+ NULL,
+ sizeof (YelpPager),
+ 0,
+ (GInstanceInitFunc) pager_init,
+ };
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "YelpPager",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+pager_class_init (YelpPagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->set_property = pager_set_property;
+ object_class->get_property = pager_get_property;
+ object_class->dispose = pager_dispose;
+
+ g_object_class_install_property
+ (object_class,
+ PROP_URI,
+ g_param_spec_object ("uri",
+ _("Document URI"),
+ _("The URI of the document to be processed"),
+ YELP_TYPE_URI,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+
+ signals[START] = g_signal_new
+ ("start",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST, 0,
+ NULL, NULL,
+ yelp_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[SECTIONS] = g_signal_new
+ ("sections",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST, 0,
+ NULL, NULL,
+ yelp_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[CHUNK] = g_signal_new
+ ("chunk",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST, 0,
+ NULL, NULL,
+ yelp_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ signals[FINISH] = g_signal_new
+ ("finish",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST, 0,
+ NULL, NULL,
+ yelp_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[CANCEL] = g_signal_new
+ ("cancel",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST, 0,
+ NULL, NULL,
+ yelp_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[ERROR] = g_signal_new
+ ("error",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST, 0,
+ NULL, NULL,
+ yelp_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+pager_init (YelpPager *pager)
+{
+ YelpPagerPriv *priv;
+
+ priv = g_new0 (YelpPagerPriv, 1);
+ pager->priv = priv;
+
+ pager->priv->uri = NULL;
+ pager->priv->state = YELP_PAGER_STATE_NEW;
+
+ pager->priv->state_mutex = g_mutex_new ();
+ pager->priv->error_mutex = g_mutex_new ();
+ pager->priv->chunk_mutex = g_mutex_new ();
+
+ pager->priv->error = NULL;
+ pager->priv->chunk_hash =
+ g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+}
+
+static void
+pager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ YelpPager *pager = YELP_PAGER (object);
+
+ switch (prop_id) {
+ case PROP_URI:
+ if (pager->priv->uri)
+ g_object_unref (pager->priv->uri);
+ pager->priv->uri = (YelpURI *) g_value_get_object (value);
+ g_object_ref (pager->priv->uri);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+pager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ YelpPager *pager = YELP_PAGER (object);
+
+ switch (prop_id) {
+ case PROP_URI:
+ g_value_set_object (value, pager->priv->uri);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+pager_dispose (GObject *object)
+{
+ YelpPager *pager = YELP_PAGER (object);
+
+ g_object_unref (pager->priv->uri);
+
+ g_mutex_free (pager->priv->state_mutex);
+ g_mutex_free (pager->priv->error_mutex);
+ g_mutex_free (pager->priv->chunk_mutex);
+
+ if (pager->priv->error)
+ g_error_free (pager->priv->error);
+
+ g_hash_table_destroy (pager->priv->chunk_hash);
+
+ g_free (pager->priv);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+/**
+ * yelp_pager_start:
+ * @pager: a #YelpPager.
+ *
+ * Spawns a thread to process the document. If the document has already
+ * been processed, no thread will be spawned, and %FALSE will be returned.
+ **/
+gboolean
+yelp_pager_start (YelpPager *pager)
+{
+ GError *error = NULL;
+
+ g_return_val_if_fail (pager != NULL, FALSE);
+ g_return_val_if_fail (YELP_IS_PAGER (pager), FALSE);
+
+ yelp_pager_lock_state (pager);
+
+ switch (yelp_pager_get_state (pager)) {
+ case YELP_PAGER_STATE_NEW:
+ case YELP_PAGER_STATE_CANCEL:
+ yelp_pager_set_state (pager, YELP_PAGER_STATE_START);
+
+ g_object_ref (pager);
+ g_signal_emit (pager, signals[START], 0);
+
+ g_thread_create ((GThreadFunc) (YELP_PAGER_GET_CLASS (pager)->process),
+ pager, FALSE, &error);
+
+ if (error) {
+ yelp_pager_unlock_state (pager);
+ yelp_pager_error (pager, error);
+ g_object_unref (pager);
+
+ return FALSE;
+ }
+
+ yelp_pager_unlock_state (pager);
+ g_object_unref (pager);
+ return TRUE;
+
+ default:
+ yelp_pager_unlock_state (pager);
+ g_object_unref (pager);
+ return FALSE;
+ }
+}
+
+/**
+ * yelp_pager_cancel:
+ * @pager: a #YelpPager.
+ *
+ * Cancels the document processing. The processing thread may continue
+ * for a short while after this function returns before it recognizes
+ * that it has been cancelled.
+ **/
+void
+yelp_pager_cancel (YelpPager *pager)
+{
+ g_return_if_fail (pager != NULL);
+ g_return_if_fail (YELP_IS_PAGER (pager));
+
+ YELP_PAGER_GET_CLASS (pager)->cancel (pager);
+}
+
+/**
+ * yelp_pager_get_uri:
+ * @pager: a #YelpPager.
+ *
+ * Returns the URI of the documnt @pager is transforming.
+ **/
+const YelpURI *
+yelp_pager_get_uri (YelpPager *pager)
+{
+ g_return_val_if_fail (pager != NULL, FALSE);
+ g_return_val_if_fail (YELP_IS_PAGER (pager), FALSE);
+
+ return (const YelpURI *) (pager->priv->uri);
+}
+
+/**
+ * yelp_pager_get_state:
+ * @pager: a #YelpPager
+ *
+ * Returns the state of @pager. This does not handle locking itself. You
+ * must call yelp_pager_lock_state before and yelp_pager_unlock_state after.
+ **/
+YelpPagerState
+yelp_pager_get_state (YelpPager *pager)
+{
+ g_return_val_if_fail (pager != NULL, 0);
+ g_return_val_if_fail (YELP_IS_PAGER (pager), 0);
+
+ return pager->priv->state;
+}
+
+/**
+ * yelp_pager_set_state:
+ * @pager: a #YelpPager
+ * @state: a #YelpPagerState
+ *
+ * Sets the state of @pager to @state. This does not handle locking itself. You
+ * must call yelp_pager_lock_state before and yelp_pager_unlock_state after.
+ **/
+void
+yelp_pager_set_state (YelpPager *pager, YelpPagerState state)
+{
+ g_return_if_fail (pager != NULL);
+ g_return_if_fail (YELP_IS_PAGER (pager));
+
+ pager->priv->state = state;
+}
+
+/**
+ * yelp_pager_lock_state:
+ * @pager: a #YelpPager.
+ *
+ * Locks the state @pager. You should generally maintain a lock on the state
+ * across most operations on @pager.
+ **/
+void
+yelp_pager_lock_state (YelpPager *pager)
+{
+ g_return_if_fail (pager != NULL);
+ g_return_if_fail (YELP_IS_PAGER (pager));
+
+ g_mutex_lock (pager->priv->state_mutex);
+}
+
+/**
+ * yelp_pager_unlock_state:
+ * @pager: a #YelpPager.
+ *
+ * Releases a lock on the state of @pager.
+ **/
+void
+yelp_pager_unlock_state (YelpPager *pager)
+{
+ g_return_if_fail (pager != NULL);
+ g_return_if_fail (YELP_IS_PAGER (pager));
+
+ g_mutex_unlock (pager->priv->state_mutex);
+}
+
+/**
+ * yelp_pager_get_error:
+ * @pager: a #YelpPager.
+ *
+ * Returns a #GError for the processing error.
+ * The caller is responsible for freeing the #GError.
+ **/
+GError *
+yelp_pager_get_error (YelpPager *pager)
+{
+ GError *error;
+
+ g_return_val_if_fail (pager != NULL, NULL);
+ g_return_val_if_fail (YELP_IS_PAGER (pager), NULL);
+
+ g_mutex_lock (pager->priv->error_mutex);
+
+ if (pager->priv->error)
+ error = g_error_copy (pager->priv->error);
+ else
+ error = NULL;
+
+ g_mutex_unlock (pager->priv->error_mutex);
+
+ return error;
+}
+
+/**
+ * yelp_pager_error:
+ * @pager: a #YelpPager
+ * @error: a #GError
+ *
+ * Sets the error of @pager and emits the "error" signal. You must
+ * release locks on the state before calling this.
+ **/
+void
+yelp_pager_error (YelpPager *pager, GError *error)
+{
+ yelp_pager_lock_state (pager);
+ g_mutex_lock (pager->priv->error_mutex);
+
+ if (pager->priv->error)
+ g_error_free (pager->priv->error);
+ pager->priv->error = error;
+
+ g_mutex_unlock (pager->priv->error_mutex);
+
+ yelp_pager_set_state (pager, YELP_PAGER_STATE_ERROR);
+
+ g_signal_emit_by_name (pager, "error");
+ yelp_pager_unlock_state (pager);
+}
+
+/**
+ * yelp_pager_get_sections:
+ * @pager: a #YelpPager
+ *
+ * Returns a reference to the #GtkTreeModel where the section outline is stored.
+ **/
+const GtkTreeModel *
+yelp_pager_get_sections (YelpPager *pager)
+{
+ g_return_val_if_fail (pager != NULL, NULL);
+ g_return_val_if_fail (YELP_IS_PAGER (pager), NULL);
+
+ return YELP_PAGER_GET_CLASS (pager)->get_sections (pager);
+}
+
+/**
+ * yelp_pager_lookup_chunk:
+ * @pager: a #YelpPager
+ * @uri: a #YelpURI
+ *
+ * Look up and return the appropriate chunk for @uri, automatically resolving
+ * which chunk to use based on the fragment identifier.
+ **/
+const gchar *
+yelp_pager_lookup_chunk (YelpPager *pager, YelpURI *uri)
+{
+ gchar *chunk_id = NULL;
+ gchar *chunk;
+
+ g_return_val_if_fail (pager != NULL, NULL);
+ g_return_val_if_fail (YELP_IS_PAGER (pager), NULL);
+
+ chunk_id = (gchar *) (YELP_PAGER_GET_CLASS (pager)->resolve_uri (pager, uri));
+
+ if (chunk_id)
+ chunk_id = g_strdup (chunk_id);
+ else
+ chunk_id = yelp_uri_get_fragment (uri);
+
+ chunk = (gchar *) yelp_pager_get_chunk (pager, chunk_id);
+
+ g_free (chunk_id);
+
+ return (const gchar *) chunk;
+}
+
+/**
+ * yelp_pager_get_chunk:
+ * @pager: a #YelpPager
+ * @id: the chunk id
+ *
+ * Return the chunk with id @id.
+ **/
+const gchar *
+yelp_pager_get_chunk (YelpPager *pager, gchar *id)
+{
+ gchar *chunk;
+
+ g_return_val_if_fail (pager != NULL, NULL);
+ g_return_val_if_fail (YELP_IS_PAGER (pager), NULL);
+
+ g_mutex_lock (pager->priv->chunk_mutex);
+ chunk = (gchar *) g_hash_table_lookup (pager->priv->chunk_hash, id);
+ g_mutex_unlock (pager->priv->chunk_mutex);
+
+ return (const gchar *) chunk;
+}
+
+/**
+ * yelp_pager_add_chunk:
+ * @pager: a #YelpPager
+ * @id: the id of the new chunk
+ * @chunk: the contents of the new chunk
+ *
+ * Add the chunk @chunk with id @id.
+ **/
+void
+yelp_pager_add_chunk (YelpPager *pager, gchar *id, gchar *chunk)
+{
+ g_return_if_fail (pager != NULL);
+ g_return_if_fail (YELP_IS_PAGER (pager));
+
+ g_mutex_lock (pager->priv->chunk_mutex);
+ g_hash_table_insert (pager->priv->chunk_hash, id, chunk);
+ g_mutex_unlock (pager->priv->chunk_mutex);
+}
diff --git a/src/yelp-pager.h b/src/yelp-pager.h
new file mode 100644
index 00000000..ef8f5f98
--- /dev/null
+++ b/src/yelp-pager.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003 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_PAGER_H__
+#define __YELP_PAGER_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "yelp-uri.h"
+
+#define YELP_TYPE_PAGER (yelp_pager_get_type ())
+#define YELP_PAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_PAGER, YelpPager))
+#define YELP_PAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_PAGER, YelpPagerClass))
+#define YELP_IS_PAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_PAGER))
+#define YELP_IS_PAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_PAGER))
+#define YELP_PAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_PAGER, YelpPagerClass))
+
+typedef struct _YelpPager YelpPager;
+typedef struct _YelpPagerClass YelpPagerClass;
+typedef struct _YelpPagerPriv YelpPagerPriv;
+
+typedef enum {
+ YELP_PAGER_STATE_NEW,
+ YELP_PAGER_STATE_START,
+ YELP_PAGER_STATE_ERROR,
+ YELP_PAGER_STATE_CANCEL,
+ YELP_PAGER_STATE_FINISH
+} YelpPagerState;
+
+struct _YelpPager {
+ GObject parent;
+
+ YelpPagerPriv *priv;
+};
+
+struct _YelpPagerClass {
+ GObjectClass parent_class;
+
+ /* Virtual Functions */
+ void (*process) (YelpPager *pager);
+ void (*cancel) (YelpPager *pager);
+ const gchar * (*resolve_uri) (YelpPager *pager,
+ YelpURI *uri);
+ const GtkTreeModel * (*get_sections) (YelpPager *pager);
+
+};
+
+GType yelp_pager_get_type (void);
+
+gboolean yelp_pager_start (YelpPager *pager);
+void yelp_pager_cancel (YelpPager *pager);
+
+const YelpURI * yelp_pager_get_uri (YelpPager *pager);
+
+YelpPagerState yelp_pager_get_state (YelpPager *pager);
+void yelp_pager_set_state (YelpPager *pager,
+ YelpPagerState state);
+void yelp_pager_lock_state (YelpPager *pager);
+void yelp_pager_unlock_state (YelpPager *pager);
+
+GError * yelp_pager_get_error (YelpPager *pager);
+void yelp_pager_error (YelpPager *pager,
+ GError *error);
+
+const GtkTreeModel * yelp_pager_get_sections (YelpPager *pager);
+
+const gchar * yelp_pager_lookup_chunk (YelpPager *pager,
+ YelpURI *uri);
+const gchar * yelp_pager_get_chunk (YelpPager *pager,
+ gchar *id);
+void yelp_pager_add_chunk (YelpPager *pager,
+ gchar *id,
+ gchar *chunk);
+
+#endif /* __YELP_PAGER_H__ */
diff --git a/src/yelp-uri.c b/src/yelp-uri.c
index 33463c47..2994a9e3 100644
--- a/src/yelp-uri.c
+++ b/src/yelp-uri.c
@@ -1,6 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
- * Copyright (C) 2002 Mikael Hallendal <micke@imendio.com>
+ * Copyright (C) 2003 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,8 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Author: Mikael Hallendal <micke@imendio.com>
+ * Author: Shaun McCance <shaunm@gnome.org>
+ * Based on implementation by Mikael Hallendal <micke@imendio.com>
*/
#include <string.h>
@@ -32,14 +33,14 @@
#define d(x)
-struct _YelpURI {
- YelpURIType type;
- gchar *path;
- gchar *section;
- gint ref_count;
- gboolean exists;
+struct _YelpURIPriv {
+ YelpURIType type;
+ gchar *path;
+ gchar *frag;
+ gboolean exists;
};
+/*
static gchar * uri_get_doc_path (const gchar *str_uri);
static YelpURIType uri_get_doc_type (const gchar *str_uri,
const gchar *doc_path);
@@ -51,167 +52,463 @@ static gchar * uri_locate_help_file (const gchar *path,
static gchar * uri_locate_help_file_with_lang (const gchar *path,
const gchar *file_name,
const gchar *locate);
+*/
-static gchar *
-uri_get_doc_path (const gchar *str_uri)
+
+static void uri_class_init (YelpURIClass *klass);
+static void uri_init (YelpURI *uri);
+static void uri_dispose (GObject *gobject);
+
+static void uri_parse_uri (YelpURI *uri,
+ const gchar *uri_str);
+static void uri_parse_ghelp_uri (YelpURI *uri,
+ const gchar *uri_str);
+static void uri_resource_type (YelpURI *uri);
+static gchar * uri_locate_file (gchar *path,
+ gchar *file);
+static gchar * uri_locate_file_lang (gchar *path,
+ gchar *file,
+ gchar *lang);
+
+static GObjectClass *parent_class;
+
+GType
+yelp_uri_get_type (void)
{
- gchar *no_anchor_uri;
- gchar *ret_val = NULL;
- const gchar *ch = NULL;
-
- /* remove the anchor from the doc path */
- if ((ch = strchr (str_uri, '?')) || (ch = strchr (str_uri, '#'))) {
- no_anchor_uri = g_strndup (str_uri, ch - str_uri);
- } else {
- no_anchor_uri = g_strdup (str_uri);
- }
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpURIClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) uri_class_init,
+ NULL,
+ NULL,
+ sizeof (YelpURI),
+ 0,
+ (GInstanceInitFunc) uri_init,
+ };
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "YelpURI",
+ &info, 0);
+ }
+ return type;
+}
- if (no_anchor_uri[0] == '/') {
- ret_val = g_strdup (no_anchor_uri);
- }
- else if (!g_ascii_strncasecmp (no_anchor_uri, "man:", 4)) {
- ret_val = g_strdup (no_anchor_uri + 4);
- }
- else if (!g_ascii_strncasecmp (no_anchor_uri, "info:", 5)) {
- if (!g_ascii_strncasecmp (no_anchor_uri + 5, "dir", 3)) {
- ret_val = g_strdup ("info");
- } else {
- ret_val = g_strdup (no_anchor_uri + 5);
- }
- }
- else if (!g_ascii_strncasecmp (no_anchor_uri, "toc:", 4)) {
- ret_val = g_strdup (no_anchor_uri + 4);
- }
- else if (!g_ascii_strncasecmp (no_anchor_uri, "index:", 6)) {
- ret_val = g_strdup (no_anchor_uri + 6);
- }
- else if (!g_ascii_strncasecmp (no_anchor_uri, "path:", 5)) {
- ret_val = g_strdup (no_anchor_uri + 5);
- }
- else if (!g_ascii_strncasecmp (no_anchor_uri, "ghelp:", 6)) {
- ret_val = uri_get_path_from_ghelp_uri (no_anchor_uri + 6);
- }
- else if (!g_ascii_strncasecmp (no_anchor_uri, "file:", 5)) {
- ret_val = g_strdup (no_anchor_uri + 5);
- } else {
- ret_val = g_strdup (no_anchor_uri);
- }
-
- g_free (no_anchor_uri);
+static void
+uri_class_init (YelpURIClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- return ret_val;
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = uri_dispose;
}
-static YelpURIType
-uri_get_doc_type (const gchar *str_uri, const gchar *doc_path)
+static void
+uri_init (YelpURI *uri)
{
- YelpURIType ret_val = YELP_URI_TYPE_UNKNOWN;
+ YelpURIPriv *priv;
- if (!g_ascii_strncasecmp (str_uri, "man:", 4)) {
- ret_val = YELP_URI_TYPE_MAN;
- }
- else if (!g_ascii_strncasecmp (str_uri, "info:", 5)) {
- if (!g_ascii_strncasecmp (str_uri + 5, "dir", 3)) {
- ret_val = YELP_URI_TYPE_TOC;
- } else {
- ret_val = YELP_URI_TYPE_INFO;
- }
- }
- else if (!g_ascii_strncasecmp (str_uri, "toc:", 4)) {
- ret_val = YELP_URI_TYPE_TOC;
- }
- else if (!g_ascii_strncasecmp (str_uri, "index:", 6)) {
- ret_val = YELP_URI_TYPE_INDEX;
- }
- else if (!g_ascii_strncasecmp (str_uri, "path:", 5)) {
- ret_val = YELP_URI_TYPE_PATH;
- }
- else if (!g_ascii_strncasecmp (str_uri, "file:", 5) ||
- str_uri[0] == '/') {
- ret_val = YELP_URI_TYPE_FILE;
- }
- else if (!g_ascii_strncasecmp (str_uri, "ghelp:", 6)) {
- gchar *mime_type = NULL;
- gchar *docpath;
+ priv = g_new0 (YelpURIPriv, 1);
+ uri->priv = priv;
- if (doc_path) {
- docpath = (gchar *) doc_path;
- } else {
- docpath = uri_get_doc_path (str_uri);
- }
+ uri->priv->type = YELP_URI_TYPE_UNKNOWN;
+ uri->priv->path = NULL;
+ uri->priv->frag = NULL;
+}
- mime_type = gnome_vfs_get_mime_type (docpath);
-
- if (mime_type) {
- if (!g_strcasecmp (mime_type, "text/xml")) {
- ret_val = YELP_URI_TYPE_DOCBOOK_XML;
- }
- else if (!g_strcasecmp (mime_type, "text/sgml")) {
- ret_val = YELP_URI_TYPE_DOCBOOK_SGML;
- }
- else if (!g_strcasecmp (mime_type, "text/html")) {
- ret_val = YELP_URI_TYPE_HTML;
- }
-
- g_free (mime_type);
- }
-
- if (docpath != doc_path) {
- g_free (docpath);
- }
-
- if (ret_val == YELP_URI_TYPE_UNKNOWN) {
- ret_val = YELP_URI_TYPE_GHELP_OTHER;
- }
- }
+static void
+uri_dispose (GObject *object)
+{
+ YelpURI *uri = YELP_URI (object);
+
+ g_free (uri->priv->path);
+ g_free (uri->priv->frag);
+
+ g_free (uri->priv);
- return ret_val;
+ G_OBJECT_CLASS (parent_class)->dispose (object);
}
-static gchar *
-uri_get_doc_section (const gchar *str_uri)
+/******************************************************************************/
+
+YelpURI *
+yelp_uri_new (const gchar *uri_str)
{
- const gchar *ch = NULL;
+ YelpURI *uri;
+
+ uri = g_object_new (YELP_TYPE_URI, NULL);
+
+ uri_parse_uri (uri, uri_str);
+
+ return uri;
+}
+
+gboolean
+yelp_uri_exists (YelpURI *uri)
+{
+ gboolean exists;
- if ((ch = strchr (str_uri, '?')) || (ch = strchr (str_uri, '#'))) {
- return g_strdup (ch + 1);
- }
+ g_return_val_if_fail (uri != NULL, FALSE);
- return NULL;
+ if (!uri->priv->path)
+ return FALSE;
+
+ switch (uri->priv->type) {
+ case YELP_URI_TYPE_TOC:
+ case YELP_URI_TYPE_MAN:
+ case YELP_URI_TYPE_INFO:
+ case YELP_URI_TYPE_PATH:
+ case YELP_URI_TYPE_UNKNOWN:
+ exists = TRUE;
+ break;
+ case YELP_URI_TYPE_DOCBOOK_XML:
+ case YELP_URI_TYPE_DOCBOOK_SGML:
+ case YELP_URI_TYPE_HTML:
+ case YELP_URI_TYPE_FILE:
+ exists = g_file_test (uri->priv->path, G_FILE_TEST_EXISTS);
+ break;
+ default:
+ exists = FALSE;
+ }
+
+ return exists;
}
-static gchar *
-uri_get_path_from_ghelp_uri (const gchar *path)
+YelpURIType
+yelp_uri_get_resource_type (YelpURI *uri) {
+ g_return_val_if_fail (uri != NULL, YELP_URI_TYPE_UNKNOWN);
+ g_return_val_if_fail (YELP_IS_URI (uri), YELP_URI_TYPE_UNKNOWN);
+
+ return uri->priv->type;
+}
+
+gchar *
+yelp_uri_get_path (YelpURI *uri)
{
- gchar *ret_val = NULL;
- gchar *work_path;
-
- work_path = g_strdup (path);
+ g_return_val_if_fail (uri != NULL, NULL);
+ g_return_val_if_fail (YELP_IS_URI (uri), NULL);
+
+ return g_strdup (uri->priv->path);
+}
+
+gchar * yelp_uri_get_fragment (YelpURI *uri)
+{
+ g_return_val_if_fail (uri != NULL, NULL);
+ g_return_val_if_fail (YELP_IS_URI (uri), NULL);
+
+ return g_strdup (uri->priv->frag);
+}
+
+gchar *
+yelp_uri_to_string (YelpURI *uri)
+{
+ gchar *type;
+ gchar *uri_str = NULL;
- g_strstrip (work_path);
+ g_return_val_if_fail (uri != NULL, NULL);
+ g_return_val_if_fail (YELP_IS_URI (uri), NULL);
- if (path[0] == '/') {
- /* Absolute URL */
- gint i = 1;
- gint len = strlen (work_path);
-
- while (i < len && work_path[i] == '/') {
- ++i;
- }
+ if (uri->priv->type == YELP_URI_TYPE_UNKNOWN) {
+ if (uri->priv->path)
+ return g_strdup (uri->priv->path);
- /* Should we always try to use xml here even if full *
- * path to a sgml or html document is given? */
+ return NULL;
+ }
+
+ switch (uri->priv->type) {
+ case YELP_URI_TYPE_MAN:
+ type = g_strdup ("man:");
+ break;
+ case YELP_URI_TYPE_INFO:
+ type = g_strdup ("info:");
+ break;
+ case YELP_URI_TYPE_DOCBOOK_XML:
+ case YELP_URI_TYPE_DOCBOOK_SGML:
+ case YELP_URI_TYPE_FILE:
+ case YELP_URI_TYPE_HTML:
+ type = g_strdup ("file:");
+ case YELP_URI_TYPE_GHELP:
+ type = g_strdup ("ghelp:");
+ break;
+ case YELP_URI_TYPE_TOC:
+ type = g_strdup ("toc:");
+ break;
+ case YELP_URI_TYPE_PATH:
+ type = g_strdup ("path:");
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (uri->priv->frag)
+ uri_str = g_strconcat (type, uri->priv->path,
+ "#", uri->priv->frag,
+ NULL);
+ else
+ uri_str = g_strconcat (type, uri->priv->path, NULL);
+
+ g_free (type);
+
+ return uri_str;
+}
+
+/******************************************************************************/
- ret_val = g_strdup (work_path + (i - 1));
+static void
+uri_parse_uri (YelpURI *uri, const gchar *uri_str)
+{
+ gchar *c;
+ gchar *scheme = NULL;
+ gchar *path = NULL;
+
+ YelpURIPriv *priv = uri->priv;
+
+ if ((c = strchr (uri_str, '?')) || (c = strchr (uri_str, '#'))) {
+ path = g_strndup (uri_str, c - uri_str);
+ priv->frag = g_strdup (c + 1);
+ } else {
+ path = g_strdup (uri_str);
+ priv->frag = NULL;
+ }
+
+ if ((c = strchr (path, ':'))) {
+ priv->path = g_strdup (c + 1);
+ scheme = g_strndup (path, c - path);
+ } else {
+ priv->type = YELP_URI_TYPE_RELATIVE;
+ priv->path = path;
+ return;
+ }
+
+ g_free (path);
+
+ if (!g_ascii_strcasecmp (scheme, "ghelp") && priv->path[0] != '/') {
+ path = priv->path;
+ priv->path = NULL;
+
+ uri_parse_ghelp_uri (uri, path);
+
+ g_free (path);
+ return;
+ }
+
+ if (!g_ascii_strcasecmp (scheme, "ghelp") ||
+ !g_ascii_strcasecmp (scheme, "file")) {
+
+ uri_resource_type (uri);
+ }
+ else if (!g_ascii_strcasecmp (scheme, "man")) {
+ priv->type = YELP_URI_TYPE_MAN;
+ }
+ else if (!g_ascii_strcasecmp (scheme, "info")) {
+ // FIXME: This just throws away info sections.
+ if (!g_ascii_strncasecmp (priv->path, "dir", 3)) {
+ g_free (priv->path);
+ priv->path = g_strdup ("info");
+ priv->type = YELP_URI_TYPE_TOC;
} else {
- ret_val = uri_get_path_from_relative (path);
+ priv->type = YELP_URI_TYPE_INFO;
+ }
+ }
+ else if (!g_ascii_strcasecmp (scheme, "path")) {
+ priv->type = YELP_URI_TYPE_PATH;
+ }
+ else if (!g_ascii_strcasecmp (scheme, "toc")) {
+ priv->type = YELP_URI_TYPE_TOC;
+ }
+}
+
+static void
+uri_parse_ghelp_uri (YelpURI *uri, const gchar *uri_str)
+{
+ GSList *locations = NULL;
+ GSList *node;
+ gchar *c;
+ gchar *doc;
+ gchar *file;
+
+ YelpURIPriv *priv = uri->priv;
+ GnomeProgram *program = gnome_program_get ();
+
+ if ((c = strchr (uri_str, '/'))) {
+ /* 2: ghelp:AisleRiot2/Klondike */
+ doc = g_strndup (uri_str, c - uri_str);
+ file = g_strdup (c + 1);
+ } else {
+ /* 1: ghelp:nautilus */
+ doc = g_strdup (uri_str);
+ file = g_strdup (uri_str);
+ }
+
+ gnome_program_locate_file (program,
+ GNOME_FILE_DOMAIN_HELP,
+ doc,
+ FALSE,
+ &locations);
+
+ if (!locations) {
+ priv->type = YELP_URI_TYPE_GHELP;
+ priv->path = g_strdup (uri_str);
+ return;
+ }
+
+ for (node = locations; node; node = node->next) {
+ gchar *path;
+
+ path = uri_locate_file ((gchar *) node->data, file);
+
+ if (path) {
+ priv->path = path;
+ uri_resource_type (uri);
+ break;
+ }
+ }
+
+ g_free (doc);
+ g_free (file);
+}
+
+static void
+uri_resource_type (YelpURI *uri)
+{
+ gchar *mime_type = gnome_vfs_get_mime_type (uri->priv->path);
+
+ if (mime_type) {
+ if (!g_strcasecmp (mime_type, "text/xml"))
+ uri->priv->type = YELP_URI_TYPE_DOCBOOK_XML;
+ else if (!g_strcasecmp (mime_type, "text/sgml"))
+ uri->priv->type = YELP_URI_TYPE_DOCBOOK_SGML;
+ else if (!g_strcasecmp (mime_type, "text/html"))
+ uri->priv->type = YELP_URI_TYPE_HTML;
+ }
+
+ g_free (mime_type);
+}
+
+static gchar *
+uri_locate_file (gchar *path, gchar *file)
+{
+ gchar *ret;
+ const GList *langs;
+
+ langs = gnome_i18n_get_language_list ("LC_MESSAGES");
+
+ for (; langs != NULL; langs = langs->next) {
+ gchar *lang = langs->data;
+
+ /* This has to be a valid language AND a language with
+ * no encoding postfix. The language will come up without
+ * encoding next */
+ if (lang == NULL || strchr (lang, '.') != NULL)
+ continue;
+
+ ret = uri_locate_file_lang (path, file, lang);
+
+ if (!ret) {
+ /* Check for index file in wanted locale */
+ ret = uri_locate_file_lang (path, "index", lang);
}
+
+ if (ret)
+ return ret;
+ }
+
+ /* Look in C locale since that exists for almost all documents */
+ ret = uri_locate_file_lang (path, file, "C");
+ if (ret)
+ return ret;
+
+ /* Last chance, look for index-file with C lang */
+ return uri_locate_file_lang (path, "index", "C");
+}
+
+static gchar *
+uri_locate_file_lang (gchar *path, gchar *file, gchar *lang)
+{
+ gchar *exts[] = {".xml", ".docbook", ".sgml", ".html", "", NULL};
+ gint i;
+
+ for (i = 0; exts[i] != NULL; i++) {
+ gchar *full;
+
+ full = g_strconcat (path, "/", lang, "/", file, exts[i], NULL);
+
+ if (g_file_test (full, G_FILE_TEST_EXISTS))
+ return full;
+
+ g_free (full);
+ }
+
+ return NULL;
+}
+
+gboolean
+yelp_uri_equal (YelpURI *uri1, YelpURI *uri2)
+{
+ g_return_val_if_fail (uri1 != NULL, FALSE);
+ g_return_val_if_fail (uri2 != NULL, FALSE);
+
+ if (uri1->priv->type == uri2->priv->type &&
+ yelp_uri_equal_path (uri1, uri2) &&
+ yelp_uri_equal_fragment (uri1, uri2))
+
+ return TRUE;
+ else
+ return FALSE;
+}
+
+gboolean
+yelp_uri_equal_path (YelpURI *uri1, YelpURI *uri2)
+{
+ g_return_val_if_fail (uri1 != NULL, FALSE);
+ g_return_val_if_fail (uri2 != NULL, FALSE);
+
+ if (uri1->priv->path == NULL) {
+ if (uri2->priv->path == NULL)
+ return TRUE;
+ else
+ return FALSE;
+ }
- g_free (work_path);
+ if (uri2->priv->path == NULL)
+ return FALSE;
- return ret_val;
+ if (!strcmp (uri1->priv->path, uri2->priv->path))
+ return TRUE;
+
+ return FALSE;
+}
+
+gboolean
+yelp_uri_equal_fragment (YelpURI *uri1, YelpURI *uri2)
+{
+ g_return_val_if_fail (uri1 != NULL, FALSE);
+ g_return_val_if_fail (uri2 != NULL, FALSE);
+
+ if (uri1->priv->frag == NULL) {
+ if (uri2->priv->frag == NULL)
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ if (uri2->priv->frag == NULL)
+ return FALSE;
+
+ if (!strcmp (uri1->priv->frag, uri2->priv->frag))
+ return TRUE;
+
+ return FALSE;
}
+
+
+
+/******************************************************************************
static gchar *
uri_get_path_from_relative (const gchar *path)
{
@@ -226,11 +523,9 @@ uri_get_path_from_relative (const gchar *path)
program = gnome_program_get ();
if ((ch = strchr (path, '/'))) {
- /* 2: ghelp:AisleRiot2/Klondike */
doc_id = g_strndup (path, ch - path);
file_name = g_strdup (ch + 1);
} else {
- /* 1: ghelp:nautilus */
doc_id = (gchar *)path;
file_name = (gchar *)path;
}
@@ -277,185 +572,11 @@ uri_get_path_from_relative (const gchar *path)
return ret_val;
}
-static gchar *
-uri_locate_help_file (const gchar *path, const gchar *file_name)
-{
- gchar *ret_val;
- const GList *lang_list;
-
- lang_list = gnome_i18n_get_language_list ("LC_MESSAGES");
-
- for (;lang_list != NULL; lang_list = lang_list->next) {
- const gchar *lang = lang_list->data;
-
- d(g_print ("lang: %s\n", lang));
-
- /* This has to be a valid language AND a language with
- * no encoding postfix. The language will come up without
- * encoding next */
- if (lang == NULL || strchr (lang, '.') != NULL) {
- continue;
- }
-
- ret_val = uri_locate_help_file_with_lang (path, file_name,
- lang);
-
- if (!ret_val) {
- /* Check for index file in wanted locale */
- ret_val = uri_locate_help_file_with_lang (path,
- "index",
- lang);
- }
-
- if (ret_val) {
- return ret_val;
- }
- }
-
- /* Look in C locale since that exists for almost all documents */
- ret_val = uri_locate_help_file_with_lang (path, file_name, "C");
-
- if (ret_val) {
- return ret_val;
- }
-
- /* Last chance, look for index-file with C lang */
- return uri_locate_help_file_with_lang (path, "index", "C");
-}
-
-static gchar *
-uri_locate_help_file_with_lang (const gchar *path,
- const gchar *file_name,
- const gchar *lang)
-{
- gchar *exts[] = {".xml", ".docbook", ".sgml", ".html", "", NULL};
- gint i;
-
- for (i = 0; exts[i] != NULL; i++) {
- gchar *full;
-
- full = g_strconcat (path, "/", lang, "/",
- file_name, exts[i], NULL);
-
- if (g_file_test (full, G_FILE_TEST_EXISTS)) {
- return full;
- }
-
- g_free (full);
- }
-
- return NULL;
-}
-
-
-YelpURI *
-yelp_uri_new (const gchar *str_uri)
-{
- YelpURI *uri;
-
- uri = g_new0 (YelpURI, 1);
-
- d(g_print ("New YelpURI: %s\n", str_uri));
-
- uri->path = uri_get_doc_path (str_uri);
- uri->type = uri_get_doc_type (str_uri, uri->path);
- uri->section = uri_get_doc_section (str_uri);
- uri->ref_count = 1;
-
- d(g_print ("Resulting path: %s section: %s\n",
- uri->path,
- uri->section));
-
- return uri;
-}
-
gboolean
yelp_uri_exists (YelpURI *uri)
{
- gboolean ret_val;
- YelpURI *no_index;
-
- g_return_val_if_fail (uri != NULL, FALSE);
-
- if (!uri->path) {
- return FALSE;
- }
-
- switch (uri->type) {
- case YELP_URI_TYPE_TOC:
- case YELP_URI_TYPE_MAN:
- case YELP_URI_TYPE_INFO:
- case YELP_URI_TYPE_PATH:
- case YELP_URI_TYPE_UNKNOWN:
- ret_val = TRUE;
- break;
- case YELP_URI_TYPE_DOCBOOK_XML:
- case YELP_URI_TYPE_DOCBOOK_SGML:
- case YELP_URI_TYPE_HTML:
- case YELP_URI_TYPE_FILE:
- ret_val = g_file_test (uri->path, G_FILE_TEST_EXISTS);
- break;
- case YELP_URI_TYPE_INDEX:
- no_index = yelp_uri_from_index (uri);
- ret_val = yelp_uri_exists (no_index);
- yelp_uri_unref (no_index);
- break;
- default:
- ret_val = FALSE;
- }
-
- return ret_val;
}
-YelpURIType
-yelp_uri_get_type (YelpURI *uri)
-{
- g_return_val_if_fail (uri != NULL, YELP_URI_TYPE_UNKNOWN);
-
- return uri->type;
-}
-
-const gchar *
-yelp_uri_get_path (YelpURI *uri)
-{
- g_return_val_if_fail (uri != NULL, NULL);
-
- return uri->path;
-}
-
-const gchar *
-yelp_uri_get_section (YelpURI *uri)
-{
- g_return_val_if_fail (uri != NULL, NULL);
-
- return uri->section;
-}
-
-YelpURI *
-yelp_uri_ref (YelpURI *uri)
-{
- g_return_val_if_fail (uri != NULL, NULL);
-
- uri->ref_count++;
-
- return uri;
-}
-
-void
-yelp_uri_unref (YelpURI *uri)
-{
- g_return_if_fail (uri != NULL);
-
- uri->ref_count--;
-
- if (uri->ref_count == 0) {
- d(g_print ("Freeing up URI\n"));
-
- g_free (uri->path);
- g_free (uri->section);
- g_free (uri);
- }
-}
YelpURI *
yelp_uri_copy (YelpURI *uri)
@@ -507,127 +628,7 @@ yelp_uri_get_relative (YelpURI *uri, const gchar *link)
return new_uri;
}
-gboolean
-yelp_uri_equal (YelpURI *uri1, YelpURI *uri2)
-{
- if (uri1->type == uri2->type &&
- yelp_uri_equal_path (uri1, uri2) &&
- yelp_uri_equal_section (uri1, uri2)) {
- return TRUE;
- }
-
- return FALSE;
-}
-gboolean
-yelp_uri_equal_path (YelpURI *uri1, YelpURI *uri2)
-{
- g_return_val_if_fail (uri1 != NULL, FALSE);
- g_return_val_if_fail (uri2 != NULL, FALSE);
-
- if (uri1->path == NULL) {
- if (uri2->path == NULL) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
-
- if (uri2->path == NULL) {
- return FALSE;
- }
-
- if (!strcmp (uri1->path, uri2->path)) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-gboolean
-yelp_uri_equal_section (YelpURI *uri1, YelpURI *uri2)
-{
- g_return_val_if_fail (uri1 != NULL, FALSE);
- g_return_val_if_fail (uri2 != NULL, FALSE);
-
- if (uri1->section == NULL) {
- if (uri2->section == NULL) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
-
- if (uri2->section == NULL) {
- return FALSE;
- }
-
- if (!strcmp (uri1->section, uri2->section)) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-gchar *
-yelp_uri_to_string (YelpURI *uri)
-{
- gchar *type;
- gchar *ret_val = NULL;
-
- g_return_val_if_fail (uri != NULL, NULL);
-
- if (uri->type == YELP_URI_TYPE_UNKNOWN) {
- if (uri->path) {
- return g_strdup (uri->path);
- }
-
- return NULL;
- }
-
- switch (uri->type) {
- case YELP_URI_TYPE_MAN:
- type = g_strdup ("man:");
- break;
- case YELP_URI_TYPE_INFO:
- type = g_strdup ("info:");
- break;
- case YELP_URI_TYPE_DOCBOOK_XML:
- case YELP_URI_TYPE_DOCBOOK_SGML:
- case YELP_URI_TYPE_HTML:
- case YELP_URI_TYPE_GHELP_OTHER:
- type = g_strdup ("ghelp:");
- break;
- case YELP_URI_TYPE_TOC:
- type = g_strdup ("toc:");
- break;
- case YELP_URI_TYPE_PATH:
- type = g_strdup ("path:");
- break;
- case YELP_URI_TYPE_FILE:
- type = g_strdup ("file:");
- break;
- case YELP_URI_TYPE_INDEX:
- type = g_strdup ("index:");
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- if (uri->section) {
- ret_val = g_strconcat (type, uri->path, "?", uri->section,
- NULL);
- } else {
- ret_val = g_strconcat (type, uri->path, NULL);
- }
-
- g_free (type);
-
- d(g_print ("URI_TO_STRING: %s\n", ret_val));
-
- return ret_val;
-}
YelpURI *
yelp_uri_to_index (YelpURI *uri)
@@ -667,3 +668,4 @@ yelp_uri_no_path (YelpURI *uri)
return FALSE;
}
+*/
diff --git a/src/yelp-uri.h b/src/yelp-uri.h
index 824365f6..2c46d455 100644
--- a/src/yelp-uri.h
+++ b/src/yelp-uri.h
@@ -1,6 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
- * Copyright (C) 2002 Mikael Hallendal <micke@imendio.com>
+ * Copyright (C) 2003 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,8 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Author: Mikael Hallendal <micke@imendio.com>
+ * Author: Shaun McCance <shaunm@gnome.org>
+ * Based on implementation by Mikael Hallendal <micke@imendio.com>
*/
#ifndef __YELP_URI_H__
@@ -25,47 +26,71 @@
#include <glib.h>
-#define YELP_URI(x) ((YelpURI *) x)
+#define YELP_TYPE_URI (yelp_uri_get_type ())
+#define YELP_URI(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_URI, YelpURI))
+#define YELP_URI_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_URI, YelpURIClass))
+#define YELP_IS_URI(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_URI))
+#define YELP_IS_URI_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_URI))
+#define YELP_URI_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_URI, YelpURIClass))
+
+typedef struct _YelpURI YelpURI;
+typedef struct _YelpURIClass YelpURIClass;
+typedef struct _YelpURIPriv YelpURIPriv;
typedef enum {
- YELP_URI_TYPE_UNKNOWN,
- YELP_URI_TYPE_DOCBOOK_XML,
- YELP_URI_TYPE_DOCBOOK_SGML,
- YELP_URI_TYPE_GHELP_OTHER,
- YELP_URI_TYPE_HTML,
- YELP_URI_TYPE_MAN,
- YELP_URI_TYPE_INFO,
- YELP_URI_TYPE_TOC,
- YELP_URI_TYPE_INDEX,
- YELP_URI_TYPE_PATH,
- YELP_URI_TYPE_FILE
+ YELP_URI_TYPE_UNKNOWN,
+ YELP_URI_TYPE_RELATIVE,
+ YELP_URI_TYPE_DOCBOOK_XML,
+ YELP_URI_TYPE_DOCBOOK_SGML,
+ YELP_URI_TYPE_HTML,
+ YELP_URI_TYPE_MAN,
+ YELP_URI_TYPE_INFO,
+
+ YELP_URI_TYPE_GHELP,
+ YELP_URI_TYPE_GHELP_OTHER,
+ YELP_URI_TYPE_TOC,
+ YELP_URI_TYPE_INDEX,
+ YELP_URI_TYPE_PATH,
+ YELP_URI_TYPE_FILE
} YelpURIType;
-typedef struct _YelpURI YelpURI;
+struct _YelpURI {
+ GObject parent;
+
+ YelpURIPriv *priv;
+};
+
+struct _YelpURIClass {
+ GObjectClass parent_class;
+};
-YelpURI * yelp_uri_new (const gchar *str_uri);
-gboolean yelp_uri_exists (YelpURI *uri);
-YelpURIType yelp_uri_get_type (YelpURI *uri);
-const gchar * yelp_uri_get_path (YelpURI *uri);
-const gchar * yelp_uri_get_section (YelpURI *uri);
+GType yelp_uri_get_type (void);
-YelpURI * yelp_uri_ref (YelpURI *uri);
-void yelp_uri_unref (YelpURI *uri);
+YelpURI * yelp_uri_new (const gchar *uri_str);
+gboolean yelp_uri_exists (YelpURI *uri);
+YelpURIType yelp_uri_get_resource_type (YelpURI *uri);
+gchar * yelp_uri_get_path (YelpURI *uri);
+gchar * yelp_uri_get_fragment (YelpURI *uri);
+
+gchar * yelp_uri_to_string (YelpURI *uri);
+
+gboolean yelp_uri_equal (YelpURI *uri1,
+ YelpURI *uri2);
+gboolean yelp_uri_equal_path (YelpURI *uri1,
+ YelpURI *uri2);
+gboolean yelp_uri_equal_fragment (YelpURI *uri1,
+ YelpURI *uri2);
+
+/*
YelpURI * yelp_uri_copy (YelpURI *uri);
YelpURI * yelp_uri_get_relative (YelpURI *uri,
const gchar *link);
-gboolean yelp_uri_equal (YelpURI *uri1,
- YelpURI *uri2);
-gboolean yelp_uri_equal_path (YelpURI *uri1,
- YelpURI *uri2);
-gboolean yelp_uri_equal_section (YelpURI *uri1,
- YelpURI *uri2);
-gchar * yelp_uri_to_string (YelpURI *uri);
YelpURI * yelp_uri_to_index (YelpURI *uri);
YelpURI * yelp_uri_from_index (YelpURI *uri);
gboolean yelp_uri_no_path (YelpURI *uri);
+*/
#endif /* __YELP_URI_H__ */