summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDon Scorgie <dscorgie@src.gnome.org>2007-07-08 18:36:53 +0000
committerDon Scorgie <dscorgie@src.gnome.org>2007-07-08 18:36:53 +0000
commit0a0cb63b284761d0e80f79dfb224dc4e4b8c220b (patch)
treef25977bc7b6a7d87269e9afad5c4af51b1bded48
parent6d178b3d134c9a2927505f341a29a72dd86dda6b (diff)
downloadyelp-0a0cb63b284761d0e80f79dfb224dc4e4b8c220b.tar.gz
Make printing (pages and documents) work again. Although, the calling xslt
* src/yelp-window.c: * src/yelp-db-print.c: * src/yelp-db-print.h: * src/Makefile.am: Make printing (pages and documents) work again. Although, the calling xslt needs somewhat cleaned up, it doesn't look particularly appealing atm. svn path=/branches/yelp-spoon/; revision=2834
-rw-r--r--ChangeLog8
-rw-r--r--src/Makefile.am3
-rw-r--r--src/yelp-db-print.c761
-rw-r--r--src/yelp-db-print.h54
-rw-r--r--src/yelp-window.c183
5 files changed, 999 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index a38a5c80..d5f0ec90 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2007-07-08 Don Scorgie <dscorgie@svn.gnome.org>
+ * src/yelp-window.c:
+ * src/yelp-db-print.c:
+ * src/yelp-db-print.h:
+ * src/Makefile.am:
+ Make printing (pages and documents) work again.
+ Although, the calling xslt needs somewhat cleaned
+ up, it doesn't look particularly appealing atm.
+
* configure.in:
Temporarily work around breakage in gnome-doc-utils
diff --git a/src/Makefile.am b/src/Makefile.am
index 16a26642..2de64163 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,7 +20,8 @@ yelp_SOURCES = \
yelp-gecko-services.h yelp-gecko-services.cpp \
yelp-document.h yelp-document.c \
yelp-toc.h yelp-toc.c \
- yelp-docbook.h yelp-docbook.c
+ yelp-docbook.h yelp-docbook.c \
+ yelp-db-print.c yelp-db-print.h
if ENABLE_MAN
yelp_SOURCES += \
diff --git a/src/yelp-db-print.c b/src/yelp-db-print.c
new file mode 100644
index 00000000..494395d0
--- /dev/null
+++ b/src/yelp-db-print.c
@@ -0,0 +1,761 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ * Author: Don Scorgie <Don@Scorgie.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xinclude.h>
+
+#include "yelp-error.h"
+#include "yelp-db-print.h"
+#include "yelp-settings.h"
+#include "yelp-transform.h"
+#include "yelp-debug.h"
+
+#define STYLESHEET DATADIR"/yelp/xslt/db2html.xsl"
+
+#define YELP_DBPRINT_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_DBPRINT, YelpDbprintPriv))
+
+typedef enum {
+ DBPRINT_STATE_BLANK, /* Brand new, run transform as needed */
+ DBPRINT_STATE_PARSING, /* Parsing/transforming document, please wait */
+ DBPRINT_STATE_PARSED, /* All done, if we ain't got it, it ain't here */
+ DBPRINT_STATE_STOP /* Stop everything now, object to be disposed */
+} DbprintState;
+
+struct _YelpDbprintPriv {
+ gchar *filename;
+ DbprintState state;
+
+ GMutex *mutex;
+ GThread *thread;
+
+ gboolean process_running;
+ gboolean transform_running;
+
+ YelpTransform *transform;
+
+ xmlDocPtr xmldoc;
+ xmlNodePtr xmlcur;
+ gint max_depth;
+ gint cur_depth;
+ gchar *cur_page_id;
+ gchar *cur_prev_id;
+};
+
+
+static void dbprint_class_init (YelpDbprintClass *klass);
+static void dbprint_init (YelpDbprint *dbprint);
+static void dbprint_try_dispose (GObject *object);
+static void dbprint_dispose (GObject *object);
+
+/* YelpDocument */
+static void dbprint_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data);
+
+/* YelpTransform */
+static void transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpDbprint *dbprint);
+static void transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpDbprint *dbprint);
+static void transform_final_func (YelpTransform *transform,
+ YelpDbprint *dbprint);
+
+/* Threaded */
+static void dbprint_process (YelpDbprint *dbprint);
+
+#if 0
+/* Walker */
+static void dbprint_walk (YelpDbprint *dbprint);
+static gboolean dbprint_walk_chunkQ (YelpDbprint *dbprint);
+static gboolean dbprint_walk_divisionQ (YelpDbprint *dbprint);
+static gchar * dbprint_walk_get_title (YelpDbprint *dbprint);
+#endif
+
+static YelpDocumentClass *parent_class;
+
+GType
+yelp_dbprint_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (YelpDbprintClass),
+ NULL, NULL,
+ (GClassInitFunc) dbprint_class_init,
+ NULL, NULL,
+ sizeof (YelpDbprint),
+ 0,
+ (GInstanceInitFunc) dbprint_init,
+ };
+ type = g_type_register_static (YELP_TYPE_DOCUMENT,
+ "YelpDbprint",
+ &info, 0);
+ }
+ return type;
+}
+
+static void
+dbprint_class_init (YelpDbprintClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ YelpDocumentClass *document_class = YELP_DOCUMENT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = dbprint_try_dispose;
+
+ document_class->request = dbprint_request;
+ document_class->cancel = NULL;
+
+ g_type_class_add_private (klass, sizeof (YelpDbprintPriv));
+}
+
+static void
+dbprint_init (YelpDbprint *dbprint)
+{
+ YelpDbprintPriv *priv;
+ priv = dbprint->priv = YELP_DBPRINT_GET_PRIVATE (dbprint);
+
+
+ priv->state = DBPRINT_STATE_BLANK;
+
+ priv->mutex = g_mutex_new ();
+}
+
+static void
+dbprint_try_dispose (GObject *object)
+{
+ YelpDbprintPriv *priv;
+
+ g_assert (object != NULL && YELP_IS_DBPRINT (object));
+
+ priv = YELP_DBPRINT (object)->priv;
+
+ g_mutex_lock (priv->mutex);
+ if (priv->process_running || priv->transform_running) {
+ priv->state = DBPRINT_STATE_STOP;
+ g_idle_add ((GSourceFunc) dbprint_try_dispose, object);
+ g_mutex_unlock (priv->mutex);
+ } else {
+ g_mutex_unlock (priv->mutex);
+ dbprint_dispose (object);
+ }
+}
+
+static void
+dbprint_dispose (GObject *object)
+{
+ YelpDbprint *dbprint = YELP_DBPRINT (object);
+
+ g_free (dbprint->priv->filename);
+
+ if (dbprint->priv->xmldoc)
+ xmlFreeDoc (dbprint->priv->xmldoc);
+
+ g_free (dbprint->priv->cur_page_id);
+ g_free (dbprint->priv->cur_prev_id);
+
+ g_mutex_free (dbprint->priv->mutex);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpDocument *
+yelp_dbprint_new (gchar *filename)
+{
+ YelpDbprint *dbprint;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " filename = \"%s\"\n", filename);
+
+ dbprint = (YelpDbprint *) g_object_new (YELP_TYPE_DBPRINT, NULL);
+ dbprint->priv->filename = g_strdup (filename);
+
+ yelp_document_add_page_id (YELP_DOCUMENT (dbprint), "x-yelp-titlepage", "x-yelp-titlepage");
+
+ return (YelpDocument *) dbprint;
+}
+
+
+/******************************************************************************/
+/** YelpDocument **************************************************************/
+
+static void
+dbprint_request (YelpDocument *document,
+ gint req_id,
+ gboolean handled,
+ gchar *page_id,
+ YelpDocumentFunc func,
+ gpointer user_data)
+{
+ YelpDbprint *dbprint;
+ YelpDbprintPriv *priv;
+ YelpError *error;
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_ARG, " req_id = %i\n", req_id);
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+ g_assert (document != NULL && YELP_IS_DBPRINT (document));
+
+ if (handled) {
+ return;
+ }
+
+ dbprint = YELP_DBPRINT (document);
+ priv = dbprint->priv;
+
+ g_mutex_lock (priv->mutex);
+
+ switch (priv->state) {
+ case DBPRINT_STATE_BLANK:
+ priv->state = DBPRINT_STATE_PARSING;
+ priv->process_running = TRUE;
+ priv->thread = g_thread_create ((GThreadFunc) dbprint_process,
+ dbprint, FALSE, NULL);
+ break;
+ case DBPRINT_STATE_PARSING:
+ break;
+ case DBPRINT_STATE_PARSED:
+ case DBPRINT_STATE_STOP:
+ error = yelp_error_new (_("Page not found"),
+ _("The page %s was not found in the document %s."),
+ page_id, priv->filename);
+ yelp_document_error_request (document, req_id, error);
+ break;
+ }
+
+ g_mutex_unlock (priv->mutex);
+}
+
+/******************************************************************************/
+/** YelpTransform *************************************************************/
+
+static void
+transform_func (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ YelpDbprint *dbprint)
+{
+ YelpDbprintPriv *priv;
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (dbprint != NULL && YELP_IS_DBPRINT (dbprint));
+
+ priv = dbprint->priv;
+
+ g_assert (transform == priv->transform);
+
+ if (priv->state == DBPRINT_STATE_STOP) {
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ g_free (func_data);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_error_free ((YelpError *) func_data);
+ break;
+ case YELP_TRANSFORM_FINAL:
+ break;
+ }
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ return;
+ }
+
+ switch (signal) {
+ case YELP_TRANSFORM_CHUNK:
+ transform_page_func (transform, (gchar *) func_data, dbprint);
+ break;
+ case YELP_TRANSFORM_ERROR:
+ yelp_document_error_pending (YELP_DOCUMENT (dbprint), (YelpError *) func_data);
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+ break;
+ case YELP_TRANSFORM_FINAL:
+ transform_final_func (transform, dbprint);
+ break;
+ }
+}
+
+static void
+transform_page_func (YelpTransform *transform,
+ gchar *page_id,
+ YelpDbprint *dbprint)
+{
+ YelpDbprintPriv *priv;
+ gchar *content;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ priv = dbprint->priv;
+ g_mutex_lock (priv->mutex);
+
+ content = yelp_transform_eat_chunk (transform, page_id);
+ yelp_document_add_page (YELP_DOCUMENT (dbprint), page_id, content);
+
+ g_free (page_id);
+
+ g_mutex_unlock (priv->mutex);
+}
+
+static void
+transform_final_func (YelpTransform *transform, YelpDbprint *dbprint)
+{
+ YelpError *error;
+ YelpDbprintPriv *priv = dbprint->priv;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_mutex_lock (priv->mutex);
+
+ error = yelp_error_new (_("Page not found"),
+ _("The requested page was not found in the document %s."),
+ priv->filename);
+ yelp_document_error_pending (YELP_DOCUMENT (dbprint), error);
+
+ yelp_transform_release (transform);
+ priv->transform = NULL;
+ priv->transform_running = FALSE;
+
+ if (priv->xmldoc)
+ xmlFreeDoc (priv->xmldoc);
+ priv->xmldoc = NULL;
+
+ g_mutex_unlock (priv->mutex);
+}
+
+
+/******************************************************************************/
+/** Threaded ******************************************************************/
+
+static void
+dbprint_process (YelpDbprint *dbprint)
+{
+ YelpDbprintPriv *priv;
+ xmlDocPtr xmldoc = NULL;
+ xmlChar *id = NULL;
+ YelpError *error = NULL;
+ xmlParserCtxtPtr parserCtxt = NULL;
+ YelpDocument *document;
+ gchar **params;
+ gint params_i = 0;
+ gint params_max = 20;
+
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ g_assert (dbprint != NULL && YELP_IS_DBPRINT (dbprint));
+ g_object_ref (dbprint);
+ priv = dbprint->priv;
+ document = YELP_DOCUMENT (dbprint);
+
+ if (!g_file_test (priv->filename, G_FILE_TEST_IS_REGULAR)) {
+ error = yelp_error_new (_("File not found"),
+ _("The file ‘%s’ does not exist."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ parserCtxt = xmlNewParserCtxt ();
+ xmldoc = xmlCtxtReadFile (parserCtxt,
+ (const char *) priv->filename, NULL,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET );
+
+ if (xmldoc == NULL) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The file ‘%s’ could not be parsed because it is"
+ " not a well-formed XML document."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ if (xmlXIncludeProcessFlags (xmldoc,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET )
+ < 0) {
+ error = yelp_error_new (_("Could not parse file"),
+ _("The file ‘%s’ could not be parsed because"
+ " one or more of its included files is not"
+ " a well-formed XML document."),
+ priv->filename);
+ yelp_document_error_pending (document, error);
+ goto done;
+ }
+
+ g_mutex_lock (priv->mutex);
+ if (!xmlStrcmp (xmlDocGetRootElement (xmldoc)->name, BAD_CAST "book"))
+ priv->max_depth = 2;
+ else
+ priv->max_depth = 1;
+
+ priv->xmldoc = xmldoc;
+ priv->xmlcur = xmlDocGetRootElement (xmldoc);
+
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+ if (id) {
+ yelp_document_set_root_id (document, (gchar *) id);
+ yelp_document_add_page_id (document, "x-yelp-index", (gchar *) id);
+ yelp_document_add_prev_id (document, (gchar *) id, "x-yelp-titlepage");
+ yelp_document_add_next_id (document, "x-yelp-titlepage", (gchar *) id);
+ }
+ else {
+ yelp_document_set_root_id (document, "x-yelp-index");
+ yelp_document_add_page_id (document, "x-yelp-index", "x-yelp-index");
+ yelp_document_add_prev_id (document, "x-yelp-index", "x-yelp-titlepage");
+ yelp_document_add_next_id (document, "x-yelp-titlepage", "x-yelp-index");
+ /* add the id attribute to the root element with value "index"
+ * so when we try to load the document later, it doesn't fail */
+ xmlNewProp (priv->xmlcur, BAD_CAST "id", BAD_CAST "x-yelp-index");
+ }
+ g_mutex_unlock (priv->mutex);
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == DBPRINT_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+ g_mutex_unlock (priv->mutex);
+
+ g_mutex_lock (priv->mutex);
+ if (priv->state == DBPRINT_STATE_STOP) {
+ g_mutex_unlock (priv->mutex);
+ goto done;
+ }
+ priv->transform = yelp_transform_new (STYLESHEET,
+ (YelpTransformFunc) transform_func,
+ dbprint);
+ priv->transform_running = TRUE;
+ /* FIXME: we probably need to set our own params */
+
+ params = g_new0 (gchar *, params_max);
+
+ yelp_settings_params (&params, &params_i, &params_max);
+
+ if ((params_i + 10) >= params_max - 1) {
+ params_max += 20;
+ params = g_renew (gchar *, params, params_max);
+ }
+ params[params_i++] = "db.chunk.extension";
+ params[params_i++] = g_strdup ("\"\"");
+ params[params_i++] = "db.chunk.info_basename";
+ params[params_i++] = g_strdup ("\"index\"");
+ params[params_i++] = "db.chunk.max_depth";
+ params[params_i++] = g_strdup_printf ("0");
+
+ params[params_i] = NULL;
+
+ yelp_transform_start (priv->transform,
+ priv->xmldoc,
+ params);
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ if (id)
+ xmlFree (id);
+ if (parserCtxt)
+ xmlFreeParserCtxt (parserCtxt);
+
+ priv->process_running = FALSE;
+ g_object_unref (dbprint);
+}
+
+#if 0
+/******************************************************************************/
+/** Walker ********************************************************************/
+
+static void
+dbprint_walk (YelpDbprint *dbprint)
+{
+ static gint autoid = 0;
+ gchar autoidstr[20];
+ xmlChar *id = NULL;
+ xmlChar *title = NULL;
+ gchar *old_page_id = NULL;
+ xmlNodePtr cur, old_cur;
+ GtkTreeIter iter;
+ GtkTreeIter *old_iter = NULL;
+ YelpDbprintPriv *priv = dbprint->priv;
+ YelpDocument *document = YELP_DOCUMENT (dbprint);
+
+ debug_print (DB_FUNCTION, "entering\n");
+ debug_print (DB_DEBUG, " priv->xmlcur->name: %s\n", priv->xmlcur->name);
+
+ /* check for the yelp:chunk-depth or db.chunk.max_depth processing
+ * instruction and set the max chunk depth accordingly.
+ */
+ if (priv->cur_depth == 0)
+ for (cur = priv->xmlcur; cur; cur = cur->prev)
+ if (cur->type == XML_PI_NODE)
+ if (!xmlStrcmp (cur->name, (const xmlChar *) "yelp:chunk-depth") ||
+ !xmlStrcmp (cur->name, (const xmlChar *) "db.chunk.max_depth")) {
+ gint max = atoi ((gchar *) cur->content);
+ if (max)
+ priv->max_depth = max;
+ break;
+ }
+
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+
+ if (dbprint_walk_chunkQ (dbprint)) {
+ title = BAD_CAST dbprint_walk_get_title (dbprint);
+
+ /* if id attribute is not present, autogenerate a
+ * unique value, and insert it into the in-memory tree */
+ if (!id) {
+ g_snprintf (autoidstr, 20, "_auto-gen-id-%d", ++autoid);
+ xmlNewProp (priv->xmlcur, BAD_CAST "id", BAD_CAST autoidstr);
+ id = xmlGetProp (priv->xmlcur, BAD_CAST "id");
+ }
+
+ debug_print (DB_DEBUG, " id: \"%s\"\n", id);
+ debug_print (DB_DEBUG, " title: \"%s\"\n", title);
+
+ yelp_document_add_title (document, (gchar *) id, (gchar *) title);
+
+
+ if (priv->cur_prev_id) {
+ yelp_document_add_prev_id (document, (gchar *) id, priv->cur_prev_id);
+ yelp_document_add_next_id (document, priv->cur_prev_id, (gchar *) id);
+ g_free (priv->cur_prev_id);
+ }
+ priv->cur_prev_id = g_strdup ((gchar *) id);
+
+ if (priv->cur_page_id)
+ yelp_document_add_up_id (document, (gchar *) id, priv->cur_page_id);
+ old_page_id = priv->cur_page_id;
+ priv->cur_page_id = g_strdup ((gchar *) id);
+
+ }
+
+ old_cur = priv->xmlcur;
+ priv->cur_depth++;
+
+ if (id)
+ yelp_document_add_page_id (document, (gchar *) id, priv->cur_page_id);
+
+ for (cur = priv->xmlcur->children; cur; cur = cur->next) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ priv->xmlcur = cur;
+ dbprint_walk (dbprint);
+ }
+ }
+ priv->cur_depth--;
+ priv->xmlcur = old_cur;
+
+ if (dbprint_walk_chunkQ (dbprint)) {
+ priv->sections_iter = old_iter;
+ g_free (priv->cur_page_id);
+ priv->cur_page_id = old_page_id;
+ }
+
+ if (priv->cur_depth == 0) {
+ g_free (priv->cur_prev_id);
+ priv->cur_prev_id = NULL;
+
+ g_free (priv->cur_page_id);
+ priv->cur_page_id = NULL;
+ }
+
+ if (id != NULL)
+ xmlFree (id);
+ if (title != NULL)
+ xmlFree (title);
+}
+
+static gboolean
+dbprint_walk_chunkQ (YelpDbprint *dbprint)
+{
+ if (dbprint->priv->cur_depth <= dbprint->priv->max_depth
+ && dbprint_walk_divisionQ (dbprint))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static gboolean
+dbprint_walk_divisionQ (YelpDbprint *dbprint)
+{
+ xmlNodePtr node = dbprint->priv->xmlcur;
+ 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") );
+}
+
+static gchar *
+dbprint_walk_get_title (YelpDbprint *dbprint)
+{
+ gchar *infoname = NULL;
+ xmlNodePtr child = NULL;
+ xmlNodePtr title = NULL;
+ xmlNodePtr title_tmp = NULL;
+ YelpDbprintPriv *priv = dbprint->priv;
+
+ if (!xmlStrcmp (priv->xmlcur->name, BAD_CAST "refentry")) {
+ /* The title for a refentry element can come from the following:
+ * refmeta/refentrytitle
+ * refentryinfo/title[abbrev]
+ * refnamediv/refname
+ * We take the first one we find.
+ */
+ for (child = priv->xmlcur->children; child; child = child->next) {
+ if (!xmlStrcmp (child->name, BAD_CAST "refmeta")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "refentrytitle"))
+ break;
+ }
+ if (title)
+ goto done;
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "refentryinfo")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "titleabbrev"))
+ break;
+ else if (!xmlStrcmp (title->name, BAD_CAST "title"))
+ title_tmp = title;
+ }
+ if (title)
+ goto done;
+ else if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "refnamediv")) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "refname"))
+ break;
+ else if (!xmlStrcmp (title->name, BAD_CAST "refpurpose")) {
+ title = NULL;
+ break;
+ }
+ }
+ if (title)
+ goto done;
+ }
+ else if (!xmlStrncmp (child->name, BAD_CAST "refsect", 7))
+ break;
+ }
+ }
+ else {
+ /* The title for other elements appears in the following:
+ * title[abbrev]
+ * *info/title[abbrev]
+ * blockinfo/title[abbrev]
+ * objectinfo/title[abbrev]
+ * We take them in that order.
+ */
+ xmlNodePtr infos[3] = {NULL, NULL, NULL};
+ int i;
+
+ infoname = g_strdup_printf ("%sinfo", priv->xmlcur->name);
+
+ for (child = priv->xmlcur->children; child; child = child->next) {
+ if (!xmlStrcmp (child->name, BAD_CAST "titleabbrev")) {
+ title = child;
+ goto done;
+ }
+ else if (!xmlStrcmp (child->name, BAD_CAST "title"))
+ title_tmp = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST infoname))
+ infos[0] = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST "blockinfo"))
+ infos[1] = child;
+ else if (!xmlStrcmp (child->name, BAD_CAST "objectinfo"))
+ infos[2] = child;
+ }
+
+ if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+
+ for (i = 0; i < 3; i++) {
+ child = infos[i];
+ if (child) {
+ for (title = child->children; title; title = title->next) {
+ if (!xmlStrcmp (title->name, BAD_CAST "titleabbrev"))
+ goto done;
+ else if (!xmlStrcmp (title->name, BAD_CAST "title"))
+ title_tmp = title;
+ }
+ if (title_tmp) {
+ title = title_tmp;
+ goto done;
+ }
+ }
+ }
+ }
+
+ done:
+ g_free (infoname);
+
+ if (title)
+ return (gchar *) xmlNodeGetContent (title);
+ else
+ return g_strdup (_("Unknown"));
+}
+#endif
diff --git a/src/yelp-db-print.h b/src/yelp-db-print.h
new file mode 100644
index 00000000..c0ded190
--- /dev/null
+++ b/src/yelp-db-print.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm@gnome.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ * Author: Don Scorgie <Don@Scorgie.org>
+ */
+
+#ifndef __YELP_DB_PRINT_H__
+#define __YELP_DB_PRINT_H__
+
+#include <glib-object.h>
+
+#include "yelp-document.h"
+
+#define YELP_TYPE_DBPRINT (yelp_dbprint_get_type ())
+#define YELP_DBPRINT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_DBPRINT, YelpDbprint))
+#define YELP_DBPRINT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_DBPRINT, YelpDbprintClass))
+#define YELP_IS_DBPRINT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_DBPRINT))
+#define YELP_IS_DBPRINT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_DBPRINT))
+#define YELP_DBPRINT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_DBPRINT, YelpDbprintClass))
+
+typedef struct _YelpDbprint YelpDbprint;
+typedef struct _YelpDbprintClass YelpDbprintClass;
+typedef struct _YelpDbprintPriv YelpDbprintPriv;
+
+struct _YelpDbprint {
+ YelpDocument parent;
+ YelpDbprintPriv *priv;
+};
+
+struct _YelpDbprintClass {
+ YelpDocumentClass parent_class;
+};
+
+GType yelp_dbprint_get_type (void);
+YelpDocument * yelp_dbprint_new (gchar *uri);
+
+#endif /* __YELP_DB_PRINT_H__ */
diff --git a/src/yelp-window.c b/src/yelp-window.c
index b9e3c1df..bd9e49e2 100644
--- a/src/yelp-window.c
+++ b/src/yelp-window.c
@@ -242,6 +242,8 @@ static gboolean tree_model_iter_following (GtkTreeModel *model,
GtkTreeIter *iter);
static void window_write_html (YelpWindow *window,
YelpPage *page);
+static void window_write_print_html (YelpHtml *html,
+ YelpPage *page);
enum {
NEW_WINDOW_REQUESTED,
@@ -2620,12 +2622,10 @@ window_new_window_cb (GtkAction *action, YelpWindow *window)
typedef struct {
- gulong page_handler;
- gulong error_handler;
- gulong cancel_handler;
- gulong finish_handler;
- /*YelpPager *pager;*/
YelpWindow *window;
+ GtkWindow *gtk_win;
+ GtkVBox *vbox;
+ YelpHtml *html;
} PrintStruct;
#if 0
@@ -2744,8 +2744,90 @@ print_pager_finish_cb (YelpPager *pager,
#endif
static void
+window_print_signal (YelpDocument *document,
+ YelpDocumentSignal signal,
+ gint req_id,
+ gpointer *func_data,
+ PrintStruct *print)
+{
+ gchar *contents;
+ YelpPage *page;
+ YelpError *error;
+
+ switch (signal) {
+ case YELP_DOCUMENT_SIGNAL_PAGE:
+ window_write_print_html (print->html, (YelpPage *) func_data);
+
+ yelp_page_free ((YelpPage *) func_data);
+
+ yelp_print_run (print->window, print->html, print->gtk_win, print->vbox);
+ break;
+ case YELP_DOCUMENT_SIGNAL_TITLE:
+ /*printf ("TITLE: %s (%i)\n", (gchar *) func_data, req_id);*/
+ /* We don't need to actually handle title signals as gecko
+ * is wise enough to not annoy me by not handling it
+ */
+ g_free (func_data);
+ break;
+ case YELP_DOCUMENT_SIGNAL_ERROR:
+ error = (YelpError *) func_data;
+ printf ("ERROR: %s\n", yelp_error_get_title (error));
+ printf (" %s\n", yelp_error_get_message (error));
+ yelp_error_free (error);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+}
+
+
+static void
window_print_document_cb (GtkAction *action, YelpWindow *window)
{
+ YelpWindowPriv *priv;
+ GtkWidget *gtk_win;
+ YelpHtml *html;
+ int length, offset;
+ gchar *uri;
+ GtkWidget *vbox = gtk_vbox_new (FALSE, FALSE);
+ PrintStruct *print;
+ YelpDocument *doc = NULL;
+
+ priv = window->priv;
+
+ switch (priv->current_type) {
+ case YELP_RRN_TYPE_DOC:
+ doc = yelp_dbprint_new (priv->uri);
+ break;
+ defualt:
+ printf ("Error...\n");
+ return;
+ }
+
+
+ gtk_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ html = yelp_html_new ();
+
+ gtk_container_add (GTK_CONTAINER (gtk_win), GTK_WIDGET (vbox));
+ gtk_box_pack_end (GTK_BOX (vbox), GTK_WIDGET (html), TRUE, TRUE, 0);
+ gtk_widget_show (gtk_win);
+ gtk_widget_show (vbox);
+ gtk_widget_show (GTK_WIDGET (html));
+ gtk_widget_hide (gtk_win);
+
+ print = g_new0 (PrintStruct, 1);
+
+ print->window = window;
+ print->gtk_win = gtk_win;
+ print->vbox = vbox;
+ print->html = html;
+
+ yelp_document_get_page (doc,
+ "index",
+ window_print_signal,
+ (void *) print);
+
#if 0
PrintStruct *data;
YelpPager *pager;
@@ -2791,14 +2873,15 @@ window_print_document_cb (GtkAction *action, YelpWindow *window)
static void
window_print_page_cb (GtkAction *action, YelpWindow *window)
{
-#if 0
+ YelpWindowPriv *priv;
GtkWidget *gtk_win;
- YelpPager *pager;
- YelpPage *page = NULL;
YelpHtml *html;
int length, offset;
gchar *uri;
GtkWidget *vbox = gtk_vbox_new (FALSE, FALSE);
+ PrintStruct *print;
+
+ priv = window->priv;
gtk_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
html = yelp_html_new ();
@@ -2810,6 +2893,71 @@ window_print_page_cb (GtkAction *action, YelpWindow *window)
gtk_widget_show (GTK_WIDGET (html));
gtk_widget_hide (gtk_win);
+ print = g_new0 (PrintStruct, 1);
+
+ print->window = window;
+ print->gtk_win = gtk_win;
+ print->vbox = vbox;
+ print->html = html;
+
+
+ if (priv->current_document) {
+ /* Need to go through the paging system */
+ yelp_document_get_page (priv->current_document,
+ priv->current_frag,
+ window_print_signal,
+ (void *) print);
+
+ } else {
+ /* HTML file */
+
+ GnomeVFSHandle *handle;
+ GnomeVFSResult result;
+ GnomeVFSFileSize n;
+ gchar buffer[BUFFER_SIZE];
+
+ result = gnome_vfs_open (&handle, priv->uri, GNOME_VFS_OPEN_READ);
+
+ if (result != GNOME_VFS_OK) {
+ /*GError *error = NULL;
+ g_set_error (&error, YELP_ERROR, YELP_ERROR_IO,
+ _("The file ‘%s’ could not be read. This file might "
+ "be missing, or you might not have permissions to "
+ "read it."),
+ uri);
+ window_error (window, error, TRUE);*/
+ /* TODO: Proper errors */
+ printf ("ERRORING OUT. BAD.");
+ return;
+ }
+ /* Assuming the file exists. If it doesn't how did we get this far?
+ * There are more sinister forces at work...
+ */
+
+ switch (priv->current_type) {
+ case YELP_RRN_TYPE_HTML:
+ yelp_html_open_stream (html, "text/html");
+ break;
+ case YELP_RRN_TYPE_XHTML:
+ yelp_html_open_stream (html, "application/xhtml+xml");
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ while ((result = gnome_vfs_read
+ (handle, buffer, BUFFER_SIZE, &n)) == GNOME_VFS_OK) {
+ yelp_html_write (html, buffer, n);
+ }
+
+ yelp_html_close (html);
+
+ yelp_print_run (window, html, gtk_win, vbox);
+
+ }
+
+
+#if 0
pager = yelp_doc_info_get_pager (window->priv->current_doc);
uri = yelp_doc_info_get_uri (window->priv->current_doc, NULL, YELP_URI_TYPE_FILE);
@@ -2864,13 +3012,13 @@ window_print_page_cb (GtkAction *action, YelpWindow *window)
}
yelp_html_close (html);
-
}
g_free (uri);
yelp_print_run (window, html, gtk_win, vbox);
#endif
+
}
static void
@@ -3567,3 +3715,20 @@ window_write_html (YelpWindow *window, YelpPage *page)
} while (read == BUFFER_SIZE);
yelp_html_close (html);
}
+
+static void
+window_write_print_html (YelpHtml *html, YelpPage * page)
+{
+ gsize read;
+ gchar contents[BUFFER_SIZE];
+
+ /* Use a silly fake URI to stop gecko doing silly things */
+ yelp_html_set_base_uri (html, "file:///foobar");
+ yelp_html_open_stream (html, "application/xhtml+xml");
+
+ do {
+ yelp_page_read (page, contents, BUFFER_SIZE, &read, NULL);
+ yelp_html_write (html, contents, read);
+ } while (read == BUFFER_SIZE);
+ yelp_html_close (html);
+}