Yelp Printing



Hi all again,

Attached is another printing patch for Yelp (using libgnomeprint*).  Its
now in a state that I'm (reasonably) happy with.

Could people please try it out and let me know of any problems?

Known issues:
Printing a TOC page will crash it.  Not entirely certain whats going on
there.

Cancelling a print, doesn't.
https://bugzilla.mozilla.org/show_bug.cgi?id=253926
Instead, mozilla is allowed to continue printing to its temp file and
that is then deleted.

Preview and printing to pdf don't work.

It doesn't have any way to select between color & greyscale.  I wasn't
sure if this is required.  Evince & gedit don't have anywhere (I could
see).  Epiphany does.

Please try it and let me know of any problems.

Cheers
Don
Index: configure.in
===================================================================
RCS file: /cvs/gnome/yelp/configure.in,v
retrieving revision 1.192
diff -u -r1.192 configure.in
--- configure.in	28 Oct 2005 20:37:36 -0000	1.192
+++ configure.in	6 Nov 2005 12:07:59 -0000
@@ -54,6 +54,8 @@
 [
 	gconf-2.0
 	gnome-doc-utils >= 0.3.1
+        libgnomeprint-2.2,
+        libgnomeprintui-2.2,
 	gnome-vfs-2.0 >= 1.1
 	gtk+-2.0 >= 2.5.3
 	libbonobo-2.0 >= 1.108.0
Index: data/ui/yelp-ui.xml
===================================================================
RCS file: /cvs/gnome/yelp/data/ui/yelp-ui.xml,v
retrieving revision 1.11
diff -u -r1.11 yelp-ui.xml
--- data/ui/yelp-ui.xml	28 Oct 2005 20:37:37 -0000	1.11
+++ data/ui/yelp-ui.xml	6 Nov 2005 12:08:02 -0000
@@ -6,6 +6,9 @@
       <separator/>
       <menuitem action="AboutDocument"/>
       <separator/>
+      <menuitem action="PrintPage"/>
+      <menuitem action="PrintDocument"/>
+      <separator/>
       <menuitem action="CloseWindow"/>
     </menu>
     <menu action="EditMenu">
Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/yelp/src/Makefile.am,v
retrieving revision 1.85
diff -u -r1.85 Makefile.am
--- src/Makefile.am	28 Oct 2005 20:37:37 -0000	1.85
+++ src/Makefile.am	6 Nov 2005 12:08:41 -0000
@@ -9,6 +9,7 @@
 	yelp-bookmarks.c 	yelp-bookmarks.h		\
 	yelp-cache.c		yelp-cache.h			\
 	yelp-db-pager.c		yelp-db-pager.h			\
+	yelp-db-print-pager.c	yelp-db-print-pager.h		\
 	yelp-error.c		yelp-error.h			\
 	yelp-gecko-utils.cpp	yelp-gecko-utils.h		\
 	yelp-html.cpp		yelp-html.h			\
@@ -19,7 +20,9 @@
 	yelp-utils.c		yelp-utils.h			\
 	yelp-window.c 		yelp-window.h			\
 	yelp-xslt-pager.c	yelp-xslt-pager.h		\
-	yelp-marshal-main.c	yelp-main.c
+	yelp-marshal-main.c	yelp-main.c			\
+	yelp-print.c		yelp-print.h			\
+	yelp-gecko-services.h   yelp-gecko-services.cpp	
 
 if ENABLE_MAN
 yelp_SOURCES +=					\
@@ -61,7 +64,12 @@
 	webbrwsr	\
 	string		\
 	webshell	\
-	commandhandler
+	commandhandler  \
+	layout		\
+	uriloader	\
+	content		\
+	gfx		\
+	necko
 
 yelp_CPPFLAGS =									\
 	-I$(top_srcdir)								\
@@ -112,6 +120,7 @@
 
 test_pager_SOURCES =						\
 	yelp-db-pager.c		yelp-db-pager.h			\
+	yelp-db-print-pager.c	yelp-db-print-pager.h		\
 	yelp-error.c		yelp-error.h			\
 	yelp-io-channel.c	yelp-io-channel.h		\
 	yelp-man-pager.c	yelp-man-pager.h		\
Index: src/yelp-db-print-pager.c
===================================================================
RCS file: src/yelp-db-print-pager.c
diff -N src/yelp-db-print-pager.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/yelp-db-print-pager.c	6 Nov 2005 12:08:44 -0000
@@ -0,0 +1,295 @@
+/* -*- 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 <glib/gi18n.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xinclude.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-error.h"
+#include "yelp-db-print-pager.h"
+#include "yelp-toc-pager.h"
+#include "yelp-settings.h"
+
+#ifdef YELP_DEBUG
+#define d(x) x
+#else
+#define d(x)
+#endif
+
+#define STYLESHEET_PATH DATADIR"/yelp/xslt/"
+#define DB_STYLESHEET   STYLESHEET_PATH"db2html.xsl"
+#define DB_TITLE        STYLESHEET_PATH"db-title.xsl"
+
+#define BOOK_CHUNK_DEPTH 2
+#define ARTICLE_CHUNK_DEPTH 1
+
+#define EVENTS_PENDING while (yelp_pager_get_state (pager) <= YELP_PAGER_STATE_RUNNING && gtk_events_pending ()) gtk_main_iteration ();
+#define CANCEL_CHECK if (!main_running || yelp_pager_get_state (pager) >= YELP_PAGER_STATE_ERROR) goto done;
+
+extern gboolean main_running;
+
+#define YELP_DB_PRINT_PAGER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_DB_PRINT_PAGER, YelpDBPrintPagerPriv))
+
+struct _YelpDBPrintPagerPriv {
+    gchar          *root_id;
+};
+
+static void           db_print_pager_class_init   (YelpDBPrintPagerClass *klass);
+static void           db_print_pager_init         (YelpDBPrintPager      *pager);
+static void           db_print_pager_dispose      (GObject          *gobject);
+
+static void           db_print_pager_cancel       (YelpPager        *pager);
+static xmlDocPtr      db_print_pager_parse        (YelpPager        *pager);
+static gchar **       db_print_pager_params       (YelpPager        *pager);
+
+static const gchar *  db_print_pager_resolve_frag (YelpPager        *pager,
+					     const gchar      *frag_id);
+static GtkTreeModel * db_print_pager_get_sections (YelpPager        *pager);
+
+static YelpPagerClass *parent_class;
+
+GType
+yelp_db_print_pager_get_type (void)
+{
+    static GType type = 0;
+
+    if (!type) {
+	static const GTypeInfo info = {
+	    sizeof (YelpDBPrintPagerClass),
+	    NULL,
+	    NULL,
+	    (GClassInitFunc) db_print_pager_class_init,
+	    NULL,
+	    NULL,
+	    sizeof (YelpDBPrintPager),
+	    0,
+	    (GInstanceInitFunc) db_print_pager_init,
+	};
+	type = g_type_register_static (YELP_TYPE_XSLT_PAGER,
+				       "YelpDBPrintPager", 
+				       &info, 0);
+    }
+    return type;
+}
+
+static void
+db_print_pager_class_init (YelpDBPrintPagerClass *klass)
+{
+    GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+    YelpPagerClass *pager_class  = YELP_PAGER_CLASS (klass);
+    YelpXsltPagerClass *xslt_class = YELP_XSLT_PAGER_CLASS (klass);
+
+    parent_class = g_type_class_peek_parent (klass);
+
+    object_class->dispose = db_print_pager_dispose;
+
+    pager_class->cancel   = db_print_pager_cancel;
+
+    pager_class->resolve_frag = db_print_pager_resolve_frag;
+
+    xslt_class->parse  = db_print_pager_parse;
+    xslt_class->params = db_print_pager_params;
+
+    xslt_class->stylesheet = DB_STYLESHEET;
+
+    g_type_class_add_private (klass, sizeof (YelpDBPrintPagerPriv));
+}
+
+static void
+db_print_pager_init (YelpDBPrintPager *pager)
+{
+    YelpDBPrintPagerPriv *priv;
+
+    pager->priv = priv = YELP_DB_PRINT_PAGER_GET_PRIVATE (pager);
+
+    pager->priv->root_id = NULL;
+}
+
+static void
+db_print_pager_dispose (GObject *object)
+{
+    YelpDBPrintPager *pager = YELP_DB_PRINT_PAGER (object);
+
+    G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+/******************************************************************************/
+
+YelpPager *
+yelp_db_print_pager_new (YelpDocInfo *doc_info)
+{
+    YelpDBPrintPager *pager;
+
+    g_return_val_if_fail (doc_info != NULL, NULL);
+
+    pager = (YelpDBPrintPager *) g_object_new (YELP_TYPE_DB_PRINT_PAGER,
+					  "document-info", doc_info,
+					  NULL);
+
+    return (YelpPager *) pager;
+}
+
+static xmlDocPtr
+db_print_pager_parse (YelpPager *pager)
+{
+    YelpDBPrintPagerPriv *priv;
+    YelpDocInfo     *doc_info;
+    gchar           *filename = NULL;
+
+    xmlParserCtxtPtr parserCtxt = NULL;
+    xmlDocPtr doc = NULL;
+
+    xmlChar     *id;
+    GError      *error = NULL;
+
+    d (g_print ("db_print_pager_parse\n"));
+
+    doc_info = yelp_pager_get_doc_info (pager);
+
+    g_return_val_if_fail (pager != NULL, NULL);
+    g_return_val_if_fail (YELP_IS_DB_PRINT_PAGER (pager), NULL);
+    priv = YELP_DB_PRINT_PAGER (pager)->priv;
+
+    g_object_ref (pager);
+
+    if (yelp_pager_get_state (pager) >= YELP_PAGER_STATE_ERROR)
+	goto done;
+
+    filename = yelp_doc_info_get_filename (doc_info);
+
+    parserCtxt = xmlNewParserCtxt ();
+    doc = xmlCtxtReadFile (parserCtxt,
+			   (const char *) filename, NULL,
+			   XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+			   XML_PARSE_NOENT   | XML_PARSE_NONET   );
+    if (doc == NULL) {
+	g_set_error (&error, YELP_ERROR, YELP_ERROR_NO_DOC,
+		     _("The file ‘%s’ could not be parsed. Either the file "
+		       "does not exist, or it is not well-formed XML."),
+		     filename);
+	yelp_pager_error (pager, error);
+	goto done;
+    }
+
+    xmlXIncludeProcessFlags (doc,
+			     XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+			     XML_PARSE_NOENT   | XML_PARSE_NONET   );
+
+
+    priv->root_id = g_strdup ("index");
+
+    EVENTS_PENDING;
+    CANCEL_CHECK;
+
+ done:
+    g_free (filename);
+
+    if (parserCtxt)
+	xmlFreeParserCtxt (parserCtxt);
+
+    g_object_unref (pager);
+
+    return doc;
+}
+
+static gchar **
+db_print_pager_params (YelpPager *pager)
+{
+    YelpDBPrintPagerPriv *priv;
+    YelpDocInfo     *doc_info;
+    gchar **params;
+    gint params_i = 0;
+    gint params_max = 20;
+
+    d (g_print ("db_print_pager_process\n"));
+
+    doc_info = yelp_pager_get_doc_info (pager);
+
+    g_return_val_if_fail (pager != NULL, FALSE);
+    g_return_val_if_fail (YELP_IS_DB_PRINT_PAGER (pager), FALSE);
+    priv = YELP_DB_PRINT_PAGER (pager)->priv;
+
+    if (yelp_pager_get_state (pager) >= YELP_PAGER_STATE_ERROR)
+	return NULL;
+
+    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++] = "yelp.javascript";
+    params[params_i++] = g_strdup_printf ("\"%s\"", DATADIR "/yelp/yelp.js");
+
+    params[params_i] = NULL;
+
+    return params;
+}
+
+static void
+db_print_pager_cancel (YelpPager *pager)
+{
+    YelpDBPrintPagerPriv *priv = YELP_DB_PRINT_PAGER (pager)->priv;
+
+    d (g_print ("db_print_pager_cancel\n"));
+
+    yelp_pager_set_state (pager, YELP_PAGER_STATE_INVALID);
+
+    g_free (priv->root_id);
+    priv->root_id = NULL;
+
+    YELP_PAGER_CLASS (parent_class)->cancel (pager);
+}
+
+static const gchar *
+db_print_pager_resolve_frag (YelpPager *pager, const gchar *frag_id)
+{
+    YelpDBPrintPager  *db_print_pager;
+
+    g_return_val_if_fail (pager != NULL, NULL);
+    g_return_val_if_fail (YELP_IS_DB_PRINT_PAGER (pager), NULL);
+
+    db_print_pager = YELP_DB_PRINT_PAGER (pager);
+
+    return frag_id;
+}
+
Index: src/yelp-db-print-pager.h
===================================================================
RCS file: src/yelp-db-print-pager.h
diff -N src/yelp-db-print-pager.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/yelp-db-print-pager.h	6 Nov 2005 12:08:44 -0000
@@ -0,0 +1,55 @@
+/* -*- 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_PRINT_PAGER_H__
+#define __YELP_DB_PRINT_PAGER_H__
+
+#include <glib-object.h>
+
+#include "yelp-pager.h"
+#include "yelp-xslt-pager.h"
+
+#define YELP_TYPE_DB_PRINT_PAGER         (yelp_db_print_pager_get_type ())
+#define YELP_DB_PRINT_PAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_DB_PRINT_PAGER, YelpDBPrintPager))
+#define YELP_DB_PRINT_PAGER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), YELP_TYPE_DB_PRINT_PAGER, YelpDBPrintPagerClass))
+#define YELP_IS_DB_PRINT_PAGER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_DB_PRINT_PAGER))
+#define YELP_IS_DB_PRINT_PAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_DB_PRINT_PAGER))
+#define YELP_DB_PRINT_PAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_DB_PRINT_PAGER, YelpDBPrintPagerClass))
+
+typedef struct _YelpDBPrintPager      YelpDBPrintPager;
+typedef struct _YelpDBPrintPagerClass YelpDBPrintPagerClass;
+typedef struct _YelpDBPrintPagerPriv  YelpDBPrintPagerPriv;
+
+struct _YelpDBPrintPager {
+    YelpXsltPager    parent;
+
+    YelpDBPrintPagerPriv *priv;
+};
+
+struct _YelpDBPrintPagerClass {
+    YelpXsltPagerClass   parent_class;
+};
+
+GType           yelp_db_print_pager_get_type     (void);
+YelpPager *     yelp_db_print_pager_new          (YelpDocInfo *doc_info);
+
+#endif /* __YELP_DB_PRINT_PAGER_H__ */
Index: src/yelp-gecko-services.cpp
===================================================================
RCS file: src/yelp-gecko-services.cpp
diff -N src/yelp-gecko-services.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/yelp-gecko-services.cpp	6 Nov 2005 12:08:44 -0000
@@ -0,0 +1,181 @@
+/*
+ *  Copyright (C) 2005 Don Scorgie <DonScorgie Blueyonder co uk>
+ *
+ *  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, 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: Don Scorgie <DonScorgie Blueyonder co uk>
+ */
+
+#include "mozilla-config.h"
+
+#include "config.h"
+
+#include "yelp-gecko-services.h"
+
+#include <nsIPrintSettings.h>
+#include <nsCOMPtr.h>
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS3(GPrintingPromptService, nsIPrintingPromptService, nsIWebProgressListener, nsIPrintProgressParams)
+
+GPrintingPromptService::GPrintingPromptService()
+{
+	mPrintInfo = NULL;
+}
+
+GPrintingPromptService::~GPrintingPromptService()
+{
+	if (mPrintInfo != NULL)
+	{
+		yelp_print_info_free (mPrintInfo);
+	}
+}
+
+/* void showPrintDialog (in nsIDOMWindow parent, in nsIWebBrowserPrint webBrowserPrint, in nsIPrintSettings printSettings); */
+NS_IMETHODIMP GPrintingPromptService::ShowPrintDialog(nsIDOMWindow *parent, nsIWebBrowserPrint *webBrowserPrint, nsIPrintSettings *printSettings)
+{
+	return NS_OK;
+  
+}
+
+/* void showProgress (in nsIDOMWindow parent, in nsIWebBrowserPrint webBrowserPrint, in nsIPrintSettings printSettings, in nsIObserver openDialogObserver, in boolean isForPrinting, out nsIWebProgressListener webProgressListener, out nsIPrintProgressParams printProgressParams, out boolean notifyOnOpen); */
+NS_IMETHODIMP GPrintingPromptService::ShowProgress(nsIDOMWindow *parent, nsIWebBrowserPrint *webBrowserPrint, nsIPrintSettings *printSettings, nsIObserver *openDialogObserver, PRBool isForPrinting, nsIWebProgressListener **webProgressListener, nsIPrintProgressParams **printProgressParams, PRBool *notifyOnOpen)
+{
+  return NS_OK;
+}
+
+/* void showPageSetup (in nsIDOMWindow parent, in nsIPrintSettings printSettings, in nsIObserver printObserver); */
+NS_IMETHODIMP GPrintingPromptService::ShowPageSetup(nsIDOMWindow *parent, nsIPrintSettings *printSettings, 
+						    nsIObserver *printObserver)
+{
+  return NS_OK;
+}
+
+/* void showPrinterProperties (in nsIDOMWindow parent, in wstring printerName, in nsIPrintSettings printSettings); */
+NS_IMETHODIMP GPrintingPromptService::ShowPrinterProperties(nsIDOMWindow *parent, const PRUnichar *printerName, nsIPrintSettings *printSettings)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */
+NS_IMETHODIMP GPrintingPromptService::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
+{
+	return NS_OK;
+}
+
+/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
+NS_IMETHODIMP GPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
+{
+    return NS_OK;
+}
+
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
+NS_IMETHODIMP GPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
+NS_IMETHODIMP GPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
+NS_IMETHODIMP GPrintingPromptService::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute wstring docTitle; */
+NS_IMETHODIMP GPrintingPromptService::GetDocTitle(PRUnichar * *aDocTitle)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP GPrintingPromptService::SetDocTitle(const PRUnichar * aDocTitle)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute wstring docURL; */
+NS_IMETHODIMP GPrintingPromptService::GetDocURL(PRUnichar * *aDocURL)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP GPrintingPromptService::SetDocURL(const PRUnichar * aDocURL)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMPL_ISUPPORTS1(PrintListener, nsIWebProgressListener)
+
+  PrintListener::PrintListener (YelpPrintInfo *in, nsIWebBrowserPrint *p)
+{
+  info = in;
+  print = p;
+  cancel_happened = FALSE;
+  /*NULL*/
+
+}
+
+PrintListener::~PrintListener ()
+{
+  /*NULL*/
+}
+
+/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */
+NS_IMETHODIMP PrintListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
+NS_IMETHODIMP PrintListener::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
+{
+  yelp_print_update_progress (info, 
+		      (1.0 * aCurTotalProgress) / (aMaxTotalProgress * 1.0));
+
+  if (info->cancelled && !cancel_happened) {
+    /* This doesn't seem to actually cancel anything.
+     * therefore, the best course of action is to ignore it
+     * until we've finished printing to the file
+     * and then free it - Mozilla bug #253926
+     */
+    print->Cancel();
+    cancel_happened = TRUE;
+  }
+  if (aCurTotalProgress == 100 && aMaxTotalProgress == 100) /* 100% finished */
+    yelp_print_moz_finished (info);
+  return NS_OK;
+}
+
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
+NS_IMETHODIMP PrintListener::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
+NS_IMETHODIMP PrintListener::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
+NS_IMETHODIMP PrintListener::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
Index: src/yelp-gecko-services.h
===================================================================
RCS file: src/yelp-gecko-services.h
diff -N src/yelp-gecko-services.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/yelp-gecko-services.h	6 Nov 2005 12:08:44 -0000
@@ -0,0 +1,85 @@
+/*
+ *  Copyright (C) 2005 Don Scorgie <DonScorgie Blueyonder co uk>
+ *
+ *  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, 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: Don Scorgie <DonScorgie Blueyonder co uk>
+ */
+
+#ifndef __YELP_GECKO_SERVICES_H
+#define __YELP_GECKO_SERVICES_H
+
+#include "nsError.h"
+#undef MOZILLA_INTERNAL_API
+#include <nsEmbedString.h>
+#define MOZILLA_INTERNAL_API 1
+
+#include <nsIPrintingPromptService.h>
+#include <nsIWebProgressListener.h>
+#include <nsIPrintProgressParams.h>
+#include "yelp-print.h"
+
+#define G_PRINTINGPROMPTSERVICE_CID		     \
+{ /* 5998a2d3-88ea-4c52-b4bb-4e7abd0d35e0 */         \
+    0x5998a2d3,                                      \
+    0x88ea,                                          \
+    0x4c52,                                          \
+    {0xb4, 0xbb, 0x4e, 0x7a, 0xbd, 0x0d, 0x35, 0xe0} \
+}
+
+#define G_PRINTINGPROMPTSERVICE_CLASSNAME "Yelps Printing Prompt Service"
+#define G_PRINTINGPROMPTSERVICE_CONTRACTID "@mozilla.org/embedcomp/printingprompt-service;1"
+
+/* Overwriting PrintPromptService makes the default mozilla print dialog
+ * not appear.  We already have our print dialog shown
+ */
+class GPrintingPromptService : public nsIPrintingPromptService, nsIWebProgressListener, nsIPrintProgressParams
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPRINTINGPROMPTSERVICE
+  NS_DECL_NSIWEBPROGRESSLISTENER
+  NS_DECL_NSIPRINTPROGRESSPARAMS
+
+  GPrintingPromptService();
+  virtual ~GPrintingPromptService();
+
+protected:
+  YelpPrintInfo *mPrintInfo;
+};
+
+/* The PrintListener allows us to update the progress bars.
+ * Its not much help, but better than nothing
+ */
+class PrintListener : public nsIWebProgressListener
+{
+public:
+  PrintListener (YelpPrintInfo *in, nsIWebBrowserPrint *p);
+  virtual ~PrintListener ();
+
+  NS_DECL_ISUPPORTS
+    NS_DECL_NSIWEBPROGRESSLISTENER
+    
+    protected:
+  YelpPrintInfo *info;
+  nsIWebBrowserPrint *print;
+  gboolean cancel_happened;
+};
+
+
+
+
+
+#endif
Index: src/yelp-html.cpp
===================================================================
RCS file: /cvs/gnome/yelp/src/yelp-html.cpp,v
retrieving revision 1.1
diff -u -r1.1 yelp-html.cpp
--- src/yelp-html.cpp	16 May 2005 21:02:33 -0000	1.1
+++ src/yelp-html.cpp	6 Nov 2005 12:08:45 -0000
@@ -31,9 +31,30 @@
 #include "yelp-marshal.h"
 #include "yelp-gecko-utils.h"
 #include "yelp-settings.h"
+#include "yelp-gecko-services.h"
 
 #include "Yelper.h"
 
+#include <unistd.h>
+#include "gtkmozembed_internal.h"
+#include "nsIWebBrowserPrint.h"
+#include "nsIPrintSettings.h"
+#undef MOZILLA_INTERNAL_API
+#include "nsEmbedString.h"
+#define MOZILLA_INTERNAL_API 1
+#include "nsIInterfaceRequestorUtils.h"
+
+#include <nsMemory.h>
+#include <nsDocShellCID.h>
+#include <nsIGenericFactory.h>
+#include <nsIComponentRegistrar.h>
+#include <nsICategoryManager.h>
+#include <nsCOMPtr.h>
+#include <nsILocalFile.h>
+#include <nsNetCID.h>
+
+#include <libgnome/gnome-init.h>
+
 #ifdef GNOME_ENABLE_DEBUG
 #define d(x) x
 #else
@@ -42,6 +63,9 @@
 
 #define YELP_HTML_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_HTML, YelpHtmlPriv))
 
+#define MOZILLA_PROFILE_DIR  "/mozilla"
+#define MOZILLA_PROFILE_NAME "yelp"
+
 struct _YelpHtmlPriv {
     Yelper      *yelper;
     gchar       *base_uri;
@@ -51,6 +75,11 @@
 static void      html_set_fonts          (void);
 static void      html_set_colors         (void);
 static void      html_set_a11y           (void);
+static void      open_new_window         (GtkMozEmbed **newEmbed, 
+					  guint chrome_mask);
+static void      html_setup_printing     (void);
+static void      html_set_print_settings (YelpPrintInfo * settings,
+					  nsIPrintSettings * target);
 
 enum {
     URI_SELECTED,
@@ -120,6 +149,14 @@
 }
 
 static void
+html_new_window (GtkMozEmbed *embed,
+		 GtkMozEmbed **newEmbed,
+		 guint chrome_mask)
+{
+    open_new_window (newEmbed, chrome_mask);
+}
+
+static void
 html_init (YelpHtml *html)
 {
     YelpHtmlPriv  *priv;
@@ -154,6 +191,7 @@
 				      NULL);
 	html_set_a11y ();
     }
+    html_setup_printing ();
 }
 
 static void
@@ -197,6 +235,7 @@
     moz_embed_class->title = html_title;
     moz_embed_class->dom_mouse_down = html_dom_mouse_down;
     moz_embed_class->open_uri = html_open_uri;
+    moz_embed_class->new_window = html_new_window;
 
     klass->font_handler = 0;
 
@@ -385,6 +424,33 @@
     html->priv->yelper->DoCommand ("cmd_selectAll");
 }
 
+void
+yelp_html_print (YelpHtml *html, YelpPrintInfo *info)
+{
+    /* FIXME: for CUPS printers, print directly instead of to a tmp file? */
+    
+    nsCOMPtr<nsIWebBrowser> webBrowser;
+    
+    gtk_moz_embed_get_nsIWebBrowser  (GTK_MOZ_EMBED (html), 
+				      getter_AddRefs(webBrowser));
+    
+    if (webBrowser) {
+	nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(webBrowser));
+	
+	if (print) {
+	    nsCOMPtr<nsIPrintSettings> settings;
+	    nsCOMPtr<PrintListener> ProgList = new PrintListener(info, print);
+	    
+	    print->GetGlobalPrintSettings (getter_AddRefs (settings));
+
+	    html_set_print_settings (info, settings);
+	    
+	    /* FIXME: Deal with return value */
+	    print->Print (settings, ProgList);
+	}
+    }
+}
+
 static void
 html_set_fonts (void)
 {
@@ -422,3 +488,385 @@
     caret = yelp_settings_get_caret ();
     yelp_gecko_set_caret (caret);
 }
+
+static void
+new_window_orphan_cb (GtkMozEmbedSingle *moz_single,
+		      GtkMozEmbed **newEmbed,
+		      guint chrome_mask,
+		      gpointer user_data)
+{
+    open_new_window (newEmbed, chrome_mask);
+}
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(GPrintingPromptService)
+
+static const nsModuleComponentInfo sAppComps[] = {
+    {
+	G_PRINTINGPROMPTSERVICE_CLASSNAME,
+	G_PRINTINGPROMPTSERVICE_CID,
+	G_PRINTINGPROMPTSERVICE_CONTRACTID,
+	GPrintingPromptServiceConstructor
+    },
+};
+
+
+
+void
+yelp_html_initialize (void)
+{
+    static gboolean initialized = FALSE;
+    GtkMozEmbedSingle *single;
+    char *profile_path;
+
+    if (initialized)
+	return;
+    initialized = TRUE;
+
+    /* get single */
+    single = gtk_moz_embed_single_get ();
+    if (single == NULL) {
+	g_warning ("Failed to get singleton embed object!\n");
+    }
+
+    /* allow creation of orphan windows */
+    g_signal_connect (G_OBJECT (single), "new_window_orphan",
+		      G_CALLBACK (new_window_orphan_cb),
+		      NULL);
+
+    profile_path = g_build_filename (g_get_home_dir (),
+				     GNOME_DOT_GNOME,
+				     "yelp.d",
+				     MOZILLA_PROFILE_DIR, 
+				     NULL);
+    gtk_moz_embed_set_profile_path (profile_path, MOZILLA_PROFILE_NAME);
+
+    g_free (profile_path);
+    
+}
+
+static GtkMozEmbed *new_xul_dialog (void);
+
+static void
+xul_visibility_cb (GtkWidget *embed, gboolean visibility, GtkWidget *window)
+{
+    if (visibility) {
+	gtk_widget_show (window);
+    } else {
+	gtk_widget_hide (window);
+    }
+}
+
+static void
+xul_size_to_cb (GtkWidget *embed, gint width, gint height, gpointer dummy)
+{
+        gtk_widget_set_size_request (embed, width, height);
+}
+
+static void
+xul_new_window_cb (GtkMozEmbed *embed,
+                   GtkMozEmbed **retval,
+                   guint chrome_mask,
+                   gpointer dummy)
+{
+    g_assert (chrome_mask & GTK_MOZ_EMBED_FLAG_OPENASCHROME);
+
+    *retval = new_xul_dialog ();
+}
+
+static void
+xul_title_cb (GtkMozEmbed *embed,
+              GtkWindow *window)
+{
+    char *title;
+
+    title = gtk_moz_embed_get_title (embed);
+    gtk_window_set_title (window, title);
+    g_free (title);
+}
+
+static GtkMozEmbed *
+new_xul_dialog (void)
+{
+    GtkWidget *window, *embed;
+
+    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    embed = gtk_moz_embed_new ();
+    gtk_widget_show (embed);
+    gtk_container_add (GTK_CONTAINER (window), embed);
+
+    g_signal_connect_object (embed, "destroy_browser",
+			     G_CALLBACK (gtk_widget_destroy),
+			     window, G_CONNECT_SWAPPED);
+    g_signal_connect_object (embed, "visibility",
+			     G_CALLBACK (xul_visibility_cb),
+			     window, (GConnectFlags) 0);
+    g_signal_connect_object (embed, "size_to",
+			     G_CALLBACK (xul_size_to_cb),
+			     NULL, (GConnectFlags) 0);
+    g_signal_connect_object (embed, "new_window",
+			     G_CALLBACK (xul_new_window_cb),
+			     NULL, (GConnectFlags) 0);
+    g_signal_connect_object (embed, "title",
+			     G_CALLBACK (xul_title_cb),
+			     window, (GConnectFlags) 0);
+
+    return GTK_MOZ_EMBED (embed);
+}
+
+static void
+open_new_window (GtkMozEmbed **newEmbed,
+		 guint chrome_mask)
+{
+    if (chrome_mask & GTK_MOZ_EMBED_FLAG_OPENASCHROME) {
+	*newEmbed = new_xul_dialog ();
+	return;
+    }
+}
+
+static void 
+html_setup_printing (void)
+{
+    gboolean ret = TRUE;
+    nsresult rv;
+    nsresult result;
+
+    nsCOMPtr<nsIComponentRegistrar> cr;
+    
+    result = NS_GetComponentRegistrar(getter_AddRefs(cr));
+    nsCOMPtr<nsIComponentManager> cm;
+    NS_GetComponentManager (getter_AddRefs (cm));
+    nsCOMPtr<nsIGenericFactory> componentFactory;
+    rv = NS_NewGenericFactory(getter_AddRefs(componentFactory),
+			      &(sAppComps[0]));
+    
+    if (NS_FAILED(rv) || !componentFactory)
+	{
+	    g_warning ("Failed to make a factory for %s\n", sAppComps[0].mDescription);
+	    
+	    ret = FALSE;
+	}
+   
+    rv = cr->RegisterFactory(sAppComps[0].mCID,
+			     sAppComps[0].mDescription,
+			     sAppComps[0].mContractID,
+			     componentFactory);
+    if (NS_FAILED(rv))
+	{
+	    g_warning ("Failed to register %s\n", sAppComps[0].mDescription);
+	    
+	    ret = FALSE;
+	}
+    
+    if (sAppComps[0].mRegisterSelfProc)
+	{
+	    rv = sAppComps[0].mRegisterSelfProc (cm, nsnull, nsnull, nsnull, &sAppComps[0]);
+	    
+	    if (NS_FAILED (rv))
+		{
+		    g_warning ("Failed to register-self for %s\n", sAppComps[0].mDescription);
+		    ret = FALSE;
+		}
+	}
+
+}
+
+
+static void
+html_set_print_settings (YelpPrintInfo * settings, nsIPrintSettings * target)
+{
+    char *base;
+    const char *temp_dir;
+    int fd;
+    const GnomePrintUnit *unit, *inch, *mm;
+    double value;
+    nsEmbedString tmp;
+    
+    const static PRUnichar pName[] = { 'P', 'o', 's', 't', 'S', 'c', 'r', 'i', 'p', 't', '/', 'd', 'e', 'f', 'a', 'u', 'l', 't', '\0' };
+    target->SetPrinterName(nsEmbedString(pName).get());
+    
+    const static int frame_types[] = {
+	nsIPrintSettings::kFramesAsIs,
+	nsIPrintSettings::kSelectedFrame,
+	nsIPrintSettings::kEachFrameSep
+    };
+
+    switch (settings->range)
+	{
+	case GNOME_PRINT_RANGE_CURRENT:
+	case GNOME_PRINT_RANGE_SELECTION_UNSENSITIVE:
+	case GNOME_PRINT_RANGE_ALL:
+	    target->SetPrintRange (nsIPrintSettings::kRangeAllPages);
+	    break;
+	case GNOME_PRINT_RANGE_RANGE:
+	    target->SetPrintRange (nsIPrintSettings::kRangeSpecifiedPageRange);
+	    target->SetStartPageRange (settings->from_page);
+	    target->SetEndPageRange (settings->to_page);
+	    break;
+	case GNOME_PRINT_RANGE_SELECTION:
+	    target->SetPrintRange (nsIPrintSettings::kRangeSelection);
+	    break;
+	}
+    
+    mm = gnome_print_unit_get_by_abbreviation ((const guchar *) "mm");
+    inch = gnome_print_unit_get_by_abbreviation ((const guchar *) "in");
+    g_assert (mm != NULL && inch != NULL);
+    
+    /* top margin */
+    if (gnome_print_config_get_length (settings->config,
+				       (const guchar *) GNOME_PRINT_KEY_PAGE_MARGIN_TOP,
+				       &value, &unit)
+	&& gnome_print_convert_distance (&value, unit, inch))
+	{
+	    target->SetMarginTop (value);
+	}
+    
+    /* bottom margin */
+    if (gnome_print_config_get_length (settings->config,
+				       (const guchar *) GNOME_PRINT_KEY_PAGE_MARGIN_BOTTOM,
+				       &value, &unit)
+	&& gnome_print_convert_distance (&value, unit, inch))
+	{
+	    target->SetMarginBottom (value);
+	}
+    
+    /* left margin */
+    if (gnome_print_config_get_length (settings->config,
+				       (const guchar *) GNOME_PRINT_KEY_PAGE_MARGIN_LEFT,
+				       &value, &unit)
+	&& gnome_print_convert_distance (&value, unit, inch))
+	{
+	    target->SetMarginLeft (value);
+	}
+    
+    /* right margin */
+    if (gnome_print_config_get_length (settings->config,
+				       (const guchar *) GNOME_PRINT_KEY_PAGE_MARGIN_RIGHT,
+				       &value, &unit)
+	&& gnome_print_convert_distance (&value, unit, inch))
+	{
+	    target->SetMarginRight (value);
+	}
+    
+    
+    
+    NS_CStringToUTF16 (nsEmbedCString(settings->header_left_string),
+		       NS_CSTRING_ENCODING_UTF8, tmp);
+    target->SetHeaderStrLeft (tmp.get());
+    
+    NS_CStringToUTF16 (nsEmbedCString(settings->header_center_string),
+		       NS_CSTRING_ENCODING_UTF8, tmp);
+    target->SetHeaderStrCenter (tmp.get());
+    
+    NS_CStringToUTF16 (nsEmbedCString(settings->header_right_string),
+		       NS_CSTRING_ENCODING_UTF8, tmp);
+    target->SetHeaderStrRight (tmp.get());
+    
+    NS_CStringToUTF16 (nsEmbedCString(settings->footer_left_string),
+		       NS_CSTRING_ENCODING_UTF8, tmp); 
+    target->SetFooterStrLeft (tmp.get());
+    
+    NS_CStringToUTF16 (nsEmbedCString(settings->footer_center_string),
+		       NS_CSTRING_ENCODING_UTF8, tmp);
+    target->SetFooterStrCenter(tmp.get());
+    
+    NS_CStringToUTF16 (nsEmbedCString(settings->footer_right_string),
+		       NS_CSTRING_ENCODING_UTF8, tmp);
+    target->SetFooterStrRight(tmp.get());
+    
+    
+    
+    temp_dir = g_get_tmp_dir ();
+    base = g_build_filename (temp_dir, "printXXXXXX", NULL);
+    fd = g_mkstemp (base);
+    close(fd);
+    settings->tempfile = g_strdup (base);
+    
+    g_free (base);
+    
+    
+    NS_CStringToUTF16 (nsEmbedCString(settings->tempfile),
+		       NS_CSTRING_ENCODING_UTF8, tmp);
+    target->SetPrintToFile (PR_TRUE);
+    target->SetToFileName (tmp.get());
+    
+    
+    /* paper size */
+    target->SetPaperSize (nsIPrintSettings::kPaperSizeDefined);
+    target->SetPaperSizeUnit (nsIPrintSettings::kPaperSizeMillimeters);
+    
+    if (gnome_print_config_get_length (settings->config,
+				       (const guchar *) GNOME_PRINT_KEY_PAPER_WIDTH,
+				       &value, &unit)
+	&& gnome_print_convert_distance (&value, unit, mm))
+	{
+	    target->SetPaperWidth (value);	
+	}
+    
+    if (gnome_print_config_get_length (settings->config,
+				       (const guchar *) GNOME_PRINT_KEY_PAPER_HEIGHT,
+				       &value, &unit)
+	&& gnome_print_convert_distance (&value, unit, mm))
+	{
+	    target->SetPaperHeight (value);	
+	}
+    
+    /* Mozilla bug https://bugzilla.mozilla.org/show_bug.cgi?id=307404
+     * means that we cannot actually use any paper sizes except mozilla's
+     * builtin list, and we must refer to them *by name*!
+     */
+#ifndef HAVE_GECKO_1_9
+    /* Gnome-Print names some papers differently than what moz understands */
+    static const struct
+    {
+	const char *gppaper;
+	const char *mozpaper;
+    }
+    paper_table [] =
+	{
+	    { "USLetter", "Letter" },
+	    { "USLegal", "Legal" }
+	};
+#endif /* !HAVE_GECKO_1_9 */
+    
+    /* paper name */
+    char *string = (char *) gnome_print_config_get (settings->config,
+						    (const guchar *) GNOME_PRINT_KEY_PAPER_SIZE);
+    const char *paper = string;
+    
+#ifndef HAVE_GECKO_1_9
+    for (PRUint32 i = 0; i < G_N_ELEMENTS (paper_table); i++)
+	{
+	    if (string != NULL &&
+		g_ascii_strcasecmp (paper_table[i].gppaper, string) == 0)
+		{
+		    paper = paper_table[i].mozpaper;
+		    break;
+		}
+	}
+#endif /* !HAVE_GECKO_1_9 */
+    
+    NS_CStringToUTF16 (nsEmbedCString(paper),
+		       NS_CSTRING_ENCODING_UTF8, tmp);
+    target->SetPaperName (tmp.get());
+    g_free (string);
+    
+    /* paper orientation */
+    string = (char *) gnome_print_config_get (settings->config,
+					      (const guchar *) GNOME_PRINT_KEY_ORIENTATION);
+    if (string == NULL) string = g_strdup ("R0");
+    
+    if (strncmp (string, "R90", 3) == 0 || strncmp (string, "R270", 4) == 0)
+	{
+	    target->SetOrientation (nsIPrintSettings::kLandscapeOrientation);
+	}
+    else
+	{
+	    target->SetOrientation (nsIPrintSettings::kPortraitOrientation);
+	}
+    g_free (string);
+    
+    target->SetPrintInColor (TRUE);
+    target->SetPrintFrameType (frame_types[settings->frame_type]);
+    
+}
+
Index: src/yelp-html.h
===================================================================
RCS file: /cvs/gnome/yelp/src/yelp-html.h,v
retrieving revision 1.30
diff -u -r1.30 yelp-html.h
--- src/yelp-html.h	16 May 2005 21:02:33 -0000	1.30
+++ src/yelp-html.h	6 Nov 2005 12:08:45 -0000
@@ -28,6 +28,8 @@
 #include <gtk/gtkmarshal.h>
 #include <gtkmozembed.h>
 
+#include "yelp-print.h"
+
 G_BEGIN_DECLS
 
 #define YELP_TYPE_HTML         (yelp_html_get_type ())
@@ -97,6 +99,11 @@
 void            yelp_html_copy_selection (YelpHtml    *html);
 
 void            yelp_html_select_all     (YelpHtml    *html);
+
+void            yelp_html_print          (YelpHtml    *html,
+					  YelpPrintInfo *info);
+
+void            yelp_html_initialize     (void);
 
 G_END_DECLS
 
Index: src/yelp-main.c
===================================================================
RCS file: /cvs/gnome/yelp/src/yelp-main.c,v
retrieving revision 1.38
diff -u -r1.38 yelp-main.c
--- src/yelp-main.c	6 Mar 2005 20:07:11 -0000	1.38
+++ src/yelp-main.c	6 Nov 2005 12:08:47 -0000
@@ -42,6 +42,7 @@
 #include "GNOME_Yelp.h"
 #include "yelp-window.h"
 #include "yelp-base.h"
+#include "yelp-html.h"
 
 #define YELP_FACTORY_OAFIID "OAFIID:GNOME_Yelp_Factory"
 
@@ -334,7 +335,8 @@
 	gnome_vfs_init ();
 
 	gtk_moz_embed_set_comp_path (MOZILLA_HOME);
-	
+	yelp_html_initialize ();
+
 	/* Commandline parsing is done here */
 	g_object_get (G_OBJECT (program),
 		      GNOME_PARAM_POPT_CONTEXT, &poptCon,
@@ -365,6 +367,7 @@
 	if (!factory) { /* Not started, start now */ 
 		BonoboGenericFactory *factory;
 		char                 *registration_id;
+
 
 		registration_id = bonobo_activation_make_registration_id (
 					YELP_FACTORY_OAFIID,
Index: src/yelp-print.c
===================================================================
RCS file: src/yelp-print.c
diff -N src/yelp-print.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/yelp-print.c	6 Nov 2005 12:08:49 -0000
@@ -0,0 +1,573 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2005 Don Scorgie <DonScorgie Blueyonder co uk>
+ *
+ * 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: Don Scorgie <DonScorgie Blueyonder co uk>
+ */
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <string.h>
+#include "yelp-print.h"
+#include "yelp-html.h"
+
+static GnomePrintConfig * yelp_print_load_config_from_file ( void );
+static void               yelp_print_save_config_to_file   (GnomePrintConfig *config);
+static void               cancel_print_cb                  (GtkDialog *dialog, 
+							    gint arg1, 
+							    YelpPrintInfo *info);
+static void               parent_destroyed_cb              (GtkWindow *window, 
+							    YelpPrintInfo *info);
+static gboolean           print_jobs_run                   ( void );
+static YelpPrintInfo    * yelp_print_get_print_info        ( void );
+GtkWidget               * yelp_print_dialog_new            (YelpPrintInfo *info);
+void                      yelp_print_info_free             (YelpPrintInfo *info);
+gboolean                  yelp_print_verify_postscript     (GnomePrintDialog *print_dialog);
+void                      yelp_print_present_status_dialog (YelpWindow *window,
+							    YelpPrintInfo *info);
+void                      yelp_print_dialog_response_cb    (GtkDialog *dialog,
+							    int response,
+							    YelpPrintInfo *info);
+static void               print_construct_range_page       (GnomePrintDialog *gpd, 
+							    gint flags,
+							    const guchar *currentlabel, 
+							    const guchar *rangelabel);
+
+
+static GSList * current_jobs = NULL;
+
+static gboolean currently_running = FALSE;
+
+void
+yelp_print_run (YelpWindow *window, gpointer html, gpointer fake_win)
+{
+    GtkWidget *dialog;
+    YelpPrintInfo *info;
+    int ret;
+    
+    info = yelp_print_get_print_info ();
+    info->owner = window;
+    info->html_frame = html;
+    info->fake_win = fake_win;
+
+    dialog = yelp_print_dialog_new (info);
+    while (TRUE) {
+	ret = gtk_dialog_run (GTK_DIALOG (dialog));
+	
+	if (ret != GNOME_PRINT_DIALOG_RESPONSE_PRINT)
+	    break;
+	if (yelp_print_verify_postscript (GNOME_PRINT_DIALOG (dialog)))
+	    break;
+    }
+    gtk_widget_destroy (dialog);
+    if (ret != GNOME_PRINT_DIALOG_RESPONSE_PRINT) {
+	yelp_print_info_free (info);
+	return;
+    }
+    yelp_print_present_status_dialog (window, info);
+    info->cancel_print_id = g_signal_connect (info->owner, "destroy",
+					      G_CALLBACK (parent_destroyed_cb), 
+					      info);
+    
+    current_jobs = g_slist_append (current_jobs, info);
+
+    if (!currently_running) {
+	g_idle_add ((GSourceFunc) print_jobs_run,
+		    NULL);
+	currently_running = TRUE;
+    }
+    
+}
+
+static gboolean 
+print_jobs_run ()
+{
+    YelpPrintInfo * info = current_jobs->data;
+    info->started = TRUE;
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (info->dialog),
+    				      _("Preparing to print"));
+
+    yelp_html_print (info->html_frame, info);
+
+    return FALSE;
+}
+
+static GnomePrintConfig * 
+yelp_print_load_config_from_file ()
+{
+  GnomePrintConfig *config = NULL;
+  gchar *filename, *contents = NULL;
+
+  filename = g_build_filename ( g_get_home_dir (), ".gnome2", 
+				 "yelp-printing", NULL);
+  if (g_file_get_contents (filename, &contents, NULL, NULL)) {
+    config = gnome_print_config_from_string (contents, 0);
+    g_free (contents);
+  } else {
+    config = gnome_print_config_default ();
+
+  }
+  
+  g_free (filename);
+
+  return config;
+}
+
+static void
+yelp_print_save_config_to_file (GnomePrintConfig *config)
+{
+  gchar *filename, *str;
+
+  str = gnome_print_config_to_string (config, 0);
+  if (str == NULL) return;
+
+  filename = g_build_filename ( g_get_home_dir (), ".gnome2", 
+				 "yelp-printing", NULL);
+  g_file_set_contents (filename, str, -1, NULL);
+
+  g_free (str);
+  g_free (filename);
+
+}
+
+void
+yelp_print_info_free (YelpPrintInfo *info)
+{
+    if (info) {
+	if (info->config)
+	    g_object_unref (info->config);
+	if (info->tempfile) {
+	    g_unlink (info->tempfile);
+	    g_free (info->tempfile);
+	}
+	if (info->header_left_string)
+	    g_free (info->header_left_string);
+	if (info->header_center_string)
+	    g_free (info->header_center_string);
+	if (info->header_right_string)
+	    g_free (info->header_right_string);
+	if (info->footer_left_string)
+	    g_free (info->footer_left_string);
+	if (info->footer_center_string)
+	    g_free (info->footer_center_string);
+	if (info->footer_right_string)
+	    g_free (info->footer_right_string);
+	if (info->dialog != NULL) {
+	    gtk_widget_destroy (info->progress);
+	    gtk_widget_destroy (info->dialog);
+	}
+	if (info->fake_win)
+	    gtk_widget_destroy (info->fake_win);
+	if (info->cancel_print_id)
+	    g_signal_handler_disconnect (info->owner, info->cancel_print_id);
+	g_free (info);
+    }
+    
+}
+
+YelpPrintInfo *
+yelp_print_get_print_info ()
+{
+  YelpPrintInfo *info;
+  
+  info = g_new0 (YelpPrintInfo, 1);
+
+  info->config = yelp_print_load_config_from_file ();
+
+  info->range = GNOME_PRINT_RANGE_ALL;
+  info->from_page = 1;
+  info->to_page = 1;
+
+  info->frame_type = 0;
+  info->print_color = FALSE;
+
+  info->cancelled = FALSE;
+  info->moz_finished = FALSE;
+
+  info->dialog = NULL;
+
+  info->header_left_string = g_strdup ("&T");
+  info->header_center_string = g_strdup ("");
+  info->header_right_string = g_strdup ("");
+  info->footer_left_string = g_strdup ("");
+  info->footer_center_string = g_strdup ("&PT");
+  info->footer_right_string = g_strdup ("");
+
+
+  return info;
+}
+
+void
+yelp_print_dialog_response_cb (GtkDialog *dialog,
+			       int response,
+			       YelpPrintInfo *info)
+{
+  if (response == GNOME_PRINT_DIALOG_RESPONSE_PRINT) {
+      info->range = gnome_print_dialog_get_range_page (GNOME_PRINT_DIALOG (dialog),
+						       &info->from_page,
+						       &info->to_page);
+      yelp_print_save_config_to_file (info->config);
+  }
+
+}
+
+
+GtkWidget *
+yelp_print_dialog_new (YelpPrintInfo *info)
+{
+  GtkWidget *dialog;
+
+  dialog= g_object_new (GNOME_TYPE_PRINT_DIALOG, "print_config",
+			info->config, NULL);
+
+  gnome_print_dialog_construct (GNOME_PRINT_DIALOG (dialog),
+				(const guchar *) "Print",
+				GNOME_PRINT_DIALOG_RANGE |
+				GNOME_PRINT_DIALOG_COPIES);
+
+  print_construct_range_page (GNOME_PRINT_DIALOG (dialog),
+			      GNOME_PRINT_RANGE_ALL |
+			      GNOME_PRINT_RANGE_RANGE |
+			      GNOME_PRINT_RANGE_SELECTION,
+			      NULL, (const guchar *) _("Pages"));
+
+  gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+				     GNOME_PRINT_DIALOG_RESPONSE_PREVIEW,
+				     FALSE);
+
+  g_signal_connect (G_OBJECT (dialog), "response",
+		    G_CALLBACK (yelp_print_dialog_response_cb), info);
+
+  return dialog;
+
+}
+
+static gboolean
+using_pdf_printer (GnomePrintConfig *config)
+{
+  const gchar *driver;
+  
+  driver = gnome_print_config_get ( config,
+				    (const guchar *) "Settings."
+				    "Engine.Backend.Driver");
+
+  if (driver) {
+    if (!strcmp ((const gchar *)driver, "gnome-print-pdf"))
+      return TRUE;
+    else
+      return FALSE; 
+  }
+  return FALSE;
+
+}
+
+static gboolean
+using_postscript_printer (GnomePrintConfig *config)
+{
+  const guchar *driver;
+  const guchar *transport;
+
+  driver = gnome_print_config_get ( config,
+				    (const guchar *) "Settings.Engine.Backend.Driver");
+
+  transport = gnome_print_config_get ( config,
+				       (const guchar *) "Settings.Transport.Backend");
+
+  if (driver) {
+    if (strcmp ((const gchar *) driver, "gnome-print-ps") == 0)
+      return TRUE;
+    else
+      return FALSE;
+
+  } else if (transport) {
+    if (strcmp ((const gchar *) transport, "CUPS") == 0)
+      return TRUE;
+    else if (strcmp ((const gchar *) transport, "LPD") == 0)
+      return TRUE;
+
+  }
+  return FALSE;
+
+}
+
+
+
+
+gboolean
+yelp_print_verify_postscript (GnomePrintDialog *print_dialog)
+{
+  GnomePrintConfig *config;
+  GtkWidget *dialog;
+
+  config = gnome_print_dialog_get_config (print_dialog);
+
+  if (using_postscript_printer (config))
+    return TRUE;
+
+  if (using_pdf_printer (config)) {
+    dialog = gtk_message_dialog_new ( GTK_WINDOW (print_dialog),
+				      GTK_DIALOG_MODAL,
+				      GTK_MESSAGE_ERROR,
+				      GTK_BUTTONS_OK,
+				      "Generating PDF is not "
+				      "currently supported");
+
+  } else {
+    dialog = gtk_message_dialog_new ( GTK_WINDOW (print_dialog),
+				      GTK_DIALOG_MODAL,
+				      GTK_MESSAGE_ERROR,
+				      GTK_BUTTONS_OK,
+				      "Printing is not supported on this "
+				      "printer");
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+					      "You were trying to print "
+					      "to a printer using the \""
+					      "%s\" driver.  This program "
+					      "requires a PostScript printer "
+					      "driver.",
+					      gnome_print_config_get (config,
+								      (guchar *) "Settings.Engine.Backend.Driver"));
+
+  }
+  gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_destroy (dialog);
+
+  return FALSE;
+}
+
+static gboolean
+print_idle_cb (YelpPrintInfo *info)
+{
+  GnomePrintJob *job;
+  gint result;
+
+  if (g_file_test (info->tempfile, G_FILE_TEST_EXISTS) == FALSE) return FALSE;
+  
+  /* FIXME: is this actually necessary? libc docs say all streams
+   * are flushed when reading from any stream.
+   */
+  fflush(NULL);
+  
+  job = gnome_print_job_new (info->config);
+  
+  gnome_print_job_set_file (job, info->tempfile);
+  result = gnome_print_job_print (job);
+  g_object_unref (job);
+
+  if (result != GNOME_PRINT_OK) {
+    /*There was an error printing.  Panic.*/
+    GtkWidget *dialog;
+
+    dialog = gtk_message_dialog_new          (NULL,
+					      GTK_DIALOG_MODAL |
+					      GTK_DIALOG_DESTROY_WITH_PARENT,
+					      GTK_MESSAGE_WARNING,
+					      GTK_BUTTONS_OK,
+					      _("An error "
+						"occured while printing")
+					      );
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+					      _("It was not possible to "
+						"print your document"));
+    gtk_dialog_run (GTK_DIALOG (dialog));
+    gtk_widget_hide (dialog);
+    gtk_widget_destroy (dialog);
+  }
+  
+  yelp_print_info_free (info);
+
+  if (g_slist_length (current_jobs) > 0)
+      g_idle_add ((GSourceFunc) print_jobs_run, NULL);
+  else
+      currently_running = FALSE;
+
+  return FALSE;
+
+}
+static void  
+parent_destroyed_cb (GtkWindow *window, YelpPrintInfo *info)
+{
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (info->dialog),
+					      _("Cancelling print"));
+    current_jobs = g_slist_remove (current_jobs, info);
+    if (info->started) {
+	info->cancelled = TRUE;
+	if (info->moz_finished) {
+	    if (info->print_idle_id)
+		g_source_remove (info->print_idle_id);
+	    yelp_print_info_free (info);
+	}
+    } else {
+	yelp_print_info_free (info);
+    }
+}
+
+static void
+cancel_print_cb (GtkDialog *dialog, gint arg1, YelpPrintInfo *info)
+{
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (info->dialog),
+    				      _("Cancelling print"));
+    current_jobs = g_slist_remove (current_jobs, info);
+    if (info->started) {
+	info->cancelled = TRUE;
+	if (info->moz_finished) {
+	    if (info->print_idle_id)
+		g_source_remove (info->print_idle_id);
+	    yelp_print_info_free (info);
+	}
+    } else {
+	yelp_print_info_free (info);
+    }
+}
+
+void 
+yelp_print_moz_finished (YelpPrintInfo *info)
+{
+    info->moz_finished = TRUE;
+
+    if (!info->cancelled) {
+	current_jobs = g_slist_remove (current_jobs, info);
+
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (info->dialog),
+						  _("Printing"));
+	
+	info->print_idle_id = g_idle_add ((GSourceFunc) print_idle_cb,
+				  info);
+
+    } else {
+	if (g_slist_length (current_jobs) == 0) {
+	    currently_running = FALSE; 
+	} else {
+	    g_idle_add ((GSourceFunc) print_jobs_run,
+			NULL);
+	}
+    }
+
+}
+
+void
+yelp_print_present_status_dialog (YelpWindow *window, YelpPrintInfo *info)
+{
+    if (info->dialog != NULL)
+	return;
+    
+    info->dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (window), 
+						       GTK_DIALOG_DESTROY_WITH_PARENT,
+						       GTK_MESSAGE_INFO,
+						       GTK_BUTTONS_CANCEL,
+						       _("<b>Printing</b>"));
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (info->dialog),
+					      _("Waiting to print"));
+    info->progress = gtk_progress_bar_new ();
+    gtk_container_add (GTK_CONTAINER (GTK_DIALOG(info->dialog)->vbox),
+		       info->progress);
+
+    gtk_widget_show (info->progress);
+
+    g_signal_connect (info->dialog, "response",
+		      G_CALLBACK (cancel_print_cb),
+		      (gpointer) info);
+
+    gtk_window_present (GTK_WINDOW (info->dialog));
+}
+
+void 
+yelp_print_cancel (YelpPrintInfo *info)
+{
+    cancel_print_cb (NULL, 0, info);
+}
+
+void
+yelp_print_update_progress (YelpPrintInfo *info, gdouble percentage)
+{
+    /* This is horribly inefficient, but since we're waiting for
+     * mozilla to do its thing, might as well waste a few cycles
+     */
+    YelpPrintInfo * temp;
+    GSList *jobs = current_jobs;
+    while (jobs != NULL) {
+	temp = jobs->data;
+	gtk_progress_bar_pulse (GTK_PROGRESS_BAR (temp->progress));
+	jobs = g_slist_next(jobs);
+    }
+    jobs = g_slist_find (current_jobs, info);
+    temp = jobs->data;
+    if (percentage > 1.0)
+	percentage = 1.0;
+    else if (percentage <0.0)
+	percentage = 0.0;
+    gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (temp->progress), 
+				   percentage);
+
+}
+
+/* Ranges page when we don't actually know the length of the
+ * document
+ */
+static void
+print_construct_range_page (GnomePrintDialog *gpd, gint flags,
+			    const guchar *currentlabel, 
+			    const guchar *rangelabel)
+{
+	GtkWidget *hbox;
+
+	hbox = NULL;
+
+	if (flags & GNOME_PRINT_RANGE_RANGE) {
+		GtkWidget *l, *sb;
+		GtkObject *a;
+		AtkObject *atko;
+
+		hbox = gtk_hbox_new (FALSE, 3);
+		gtk_widget_show (hbox);
+
+		l = gtk_label_new_with_mnemonic (_("_From:"));
+		gtk_widget_show (l);
+		gtk_box_pack_start (GTK_BOX (hbox), l, FALSE, FALSE, 0);
+
+		a = gtk_adjustment_new (1, 1, 9999, 1, 10, 10);
+		g_object_set_data (G_OBJECT (hbox), "from", a);
+		sb = gtk_spin_button_new (GTK_ADJUSTMENT (a), 1, 0.0);
+		gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (sb), TRUE);
+		gtk_widget_show (sb);
+		gtk_box_pack_start (GTK_BOX (hbox), sb, FALSE, FALSE, 0);
+		gtk_label_set_mnemonic_widget ((GtkLabel *) l, sb);
+
+		atko = gtk_widget_get_accessible (sb);
+		atk_object_set_description (atko, _("Sets the start of the range of pages to be printed"));
+
+		l = gtk_label_new_with_mnemonic (_("_To:"));
+		gtk_widget_show (l);
+		gtk_box_pack_start (GTK_BOX (hbox), l, FALSE, FALSE, 0);
+
+		a = gtk_adjustment_new (1, 1, 9999, 1, 10, 10);
+		g_object_set_data (G_OBJECT (hbox), "to", a);
+		sb = gtk_spin_button_new (GTK_ADJUSTMENT (a), 1, 0.0);
+		gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (sb), TRUE);
+		gtk_widget_show (sb);
+		gtk_box_pack_start (GTK_BOX (hbox), sb, FALSE, FALSE, 0);
+		gtk_label_set_mnemonic_widget ((GtkLabel *) l, sb);
+
+		atko = gtk_widget_get_accessible (sb);
+		atk_object_set_description (atko, _("Sets the end of the range of pages to be printed"));
+	}
+
+	gnome_print_dialog_construct_range_any (gpd, flags, hbox, currentlabel, rangelabel);
+}
Index: src/yelp-print.h
===================================================================
RCS file: src/yelp-print.h
diff -N src/yelp-print.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/yelp-print.h	6 Nov 2005 12:08:49 -0000
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2005 Don Scorgie <DonScorgie Blueyonder co uk>
+ *
+ * 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: Don Scorgie <DonScorgie Blueyonder co uk>
+ */
+
+#ifndef YELP_PRINT_H
+#define YELP_PRINT_H
+
+#include <glib.h>
+#define GNOME_PRINT_UNSTABLE_API
+#include <libgnomeprint/gnome-print-config.h>
+#include <libgnomeprintui/gnome-print-dialog.h>
+
+#include "yelp-window.h"
+
+G_BEGIN_DECLS
+
+
+typedef struct _YelpPrintInfo
+{
+    GnomePrintConfig *config;
+    
+    char *tempfile;
+    guint print_idle_id;
+    guint cancel_print_id;
+
+    GnomePrintDialogRangeFlags range;
+    int from_page;
+    int to_page;
+    int frame_type;
+    gboolean print_color;
+    gboolean cancelled;
+    gboolean moz_finished;
+    gboolean started;
+    
+    char *header_left_string;
+    char *header_center_string;
+    char *header_right_string;
+    char *footer_left_string;
+    char *footer_center_string;
+    char *footer_right_string;
+    YelpWindow *owner;
+    GtkWidget *dialog;
+    gpointer html_frame;
+    GtkWidget *progress;
+    GtkWidget *fake_win;
+
+} YelpPrintInfo;
+
+void          yelp_print_run               (YelpWindow *window, 
+					    gpointer html,
+					    gpointer fake_win);
+void          yelp_print_moz_finished      (YelpPrintInfo *info);
+void          yelp_print_cancel            (YelpPrintInfo *info);
+void          yelp_print_info_free         (YelpPrintInfo *info);
+void          yelp_print_update_progress   (YelpPrintInfo *info,
+					    gdouble percentage);
+G_END_DECLS
+
+#endif
Index: src/yelp-window.c
===================================================================
RCS file: /cvs/gnome/yelp/src/yelp-window.c,v
retrieving revision 1.180
diff -u -r1.180 yelp-window.c
--- src/yelp-window.c	2 Nov 2005 21:49:49 -0000	1.180
+++ src/yelp-window.c	6 Nov 2005 12:08:53 -0000
@@ -42,12 +42,14 @@
 
 #include "yelp-bookmarks.h"
 #include "yelp-db-pager.h"
+#include "yelp-db-print-pager.h"
 #include "yelp-error.h"
 #include "yelp-html.h"
 #include "yelp-pager.h"
 #include "yelp-settings.h"
 #include "yelp-toc-pager.h"
 #include "yelp-window.h"
+#include "yelp-print.h"
 
 #ifdef ENABLE_MAN
 #include "yelp-man-pager.h"
@@ -160,6 +162,8 @@
 					 GtkWidget    *vbox);
 static void    window_new_window_cb     (GtkAction *action, YelpWindow *window);
 static void    window_about_document_cb (GtkAction *action, YelpWindow *window);
+static void    window_print_document_cb (GtkAction *action, YelpWindow *window);
+static void    window_print_page_cb    (GtkAction *action, YelpWindow *window);
 static void    window_open_location_cb  (GtkAction *action, YelpWindow *window);
 static void    window_close_window_cb   (GtkAction *action, YelpWindow *window);
 static void    window_copy_cb           (GtkAction *action, YelpWindow *window);
@@ -308,6 +312,16 @@
       "<Control>N",
       NULL,
       G_CALLBACK (window_new_window_cb) },
+    { "PrintDocument", NULL,
+      N_("Print This Document"),
+      NULL,
+      NULL,
+      G_CALLBACK (window_print_document_cb) },
+    { "PrintPage", NULL,
+      N_("Print This Page"),
+      NULL,
+      NULL,
+      G_CALLBACK (window_print_page_cb) },
     { "AboutDocument", NULL,
       N_("About This Document"),
       NULL,
@@ -715,6 +729,7 @@
     YelpWindowPriv *priv;
     YelpDocInfo    *doc_info;
     gchar          *frag_id;
+    GtkAction      *action;
 
     g_return_if_fail (YELP_IS_WINDOW (window));
 
@@ -762,6 +777,12 @@
     if (priv->current_frag)
 	g_free (priv->current_frag);
 
+    action = gtk_action_group_get_action (priv->action_group, 
+						  "PrintDocument");
+    if (action)
+	g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
+
+
     priv->current_doc  = yelp_doc_info_ref (doc_info);
     priv->current_frag = g_strdup (frag_id);
 
@@ -793,6 +814,7 @@
 		YelpDocInfo *doc_info,
 		gchar       *frag_id)
 {
+    GtkAction      *action;
     YelpWindowPriv *priv;
     GError         *error = NULL;
     gboolean        handled = FALSE;
@@ -805,6 +827,14 @@
 
     priv = window->priv;
 
+    action = gtk_action_group_get_action (priv->action_group, 
+					  "PrintDocument");
+    if (action)
+	g_object_set (G_OBJECT (action),
+		      "sensitive",
+		      FALSE,
+		      NULL);
+    
     switch (yelp_doc_info_get_type (doc_info)) {
     case YELP_DOC_TYPE_MAN:
 #ifdef ENABLE_MAN
@@ -827,6 +857,11 @@
 #endif
 
     case YELP_DOC_TYPE_DOCBOOK_XML:
+	if (action)
+	    g_object_set (G_OBJECT (action),
+			  "sensitive",
+			  TRUE,
+			  NULL);
     case YELP_DOC_TYPE_TOC:
 	handled = window_do_load_pager (window, doc_info, frag_id);
 	break;
@@ -1009,6 +1044,12 @@
     action = gtk_action_group_get_action (priv->action_group, "GoForward");
     if (action)
 	g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
+
+    action = gtk_action_group_get_action (priv->action_group, 
+						  "PrintDocument");
+    if (action)
+	g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
+
     priv->popup = gtk_ui_manager_get_widget(priv->ui_manager, "ui/main_popup");
     priv->maillink = gtk_ui_manager_get_widget(priv->ui_manager, "ui/mail_popup");
     priv->merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
@@ -1925,6 +1966,180 @@
     g_return_if_fail (YELP_IS_WINDOW (window));
 
     g_signal_emit (window, signals[NEW_WINDOW_REQUESTED], 0, NULL);
+}
+
+typedef struct {
+    gulong page_handler;
+    gulong error_handler;
+    gulong cancel_handler;
+    gulong finish_handler;
+    YelpPager *pager;
+    YelpWindow *window;
+} PrintStruct;
+
+static void
+print_disconnect (PrintStruct *data)
+{
+    d(g_print ("print disconnect\n"));
+    if (data->page_handler) {
+	g_signal_handler_disconnect (data->pager,
+				     data->page_handler);
+	data->page_handler = 0;
+    }
+    if (data->error_handler) {
+	g_signal_handler_disconnect (data->pager,
+				     data->error_handler);
+	data->error_handler = 0;
+    }
+    if (data->cancel_handler) {
+	g_signal_handler_disconnect (data->pager,
+				     data->cancel_handler);
+	data->cancel_handler = 0;
+    }
+    if (data->finish_handler) {
+	g_signal_handler_disconnect (data->pager,
+				     data->finish_handler);
+	data->finish_handler = 0;
+    }
+#if 0
+    if (data) {
+	if (data->pager)
+	    g_object_unref (data->pager);
+    }
+#endif
+    g_free (data);
+}
+
+static void
+print_pager_page_cb (YelpPager *pager,
+		     gchar     *page_id,
+		     gpointer   user_data)
+{
+    PrintStruct *data = user_data;
+    YelpPage    *page;
+    static int pgno=0;
+    d (g_print ("print_pager_page_cb\n"));
+    d (g_print ("  page_id=\"%s\"\n", page_id));
+
+    page = (YelpPage *) yelp_pager_get_page (pager, page_id);
+
+    if (page) {
+	YelpHtml *html;
+	GtkWidget *gtk_window;
+	int length, offset;
+	char *uri;
+	d(g_print (page->contents));
+
+	gtk_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	html = yelp_html_new ();
+	gtk_container_add (GTK_CONTAINER (gtk_window), GTK_WIDGET (html));
+	gtk_widget_realize (gtk_window);
+	gtk_widget_realize (GTK_WIDGET (html));
+
+
+	uri = yelp_doc_info_get_uri (yelp_pager_get_doc_info (pager),
+				     page_id,
+				     YELP_URI_TYPE_FILE);
+
+	d (g_print ("  uri            = %s\n", uri));
+
+	yelp_html_set_base_uri (html, uri);
+	g_free (uri);
+
+	yelp_html_open_stream (html, "application/xhtml+xml");
+	for (length = strlen (page->contents), offset = 0; length > 0; length -= BUFFER_SIZE, offset += BUFFER_SIZE) {
+	    d(g_print ("data: %.*s\n", MIN (length, BUFFER_SIZE), page->contents + offset));
+	    yelp_html_write (html, page->contents + offset, MIN (length, BUFFER_SIZE));
+	}
+	yelp_html_close (html);
+
+	yelp_print_run (data->window, html, gtk_window);
+
+	print_disconnect (data);
+
+    }
+}
+
+static void
+print_pager_error_cb (YelpPager   *pager,
+		      gpointer     user_data)
+{
+    PrintStruct *data = user_data;
+    /*     GError *error = yelp_pager_get_error (pager);*/
+
+    d (g_print ("print_pager_error_cb\n"));
+
+    print_disconnect (data);
+}
+
+static void
+print_pager_cancel_cb (YelpPager   *pager,
+		       gpointer     user_data)
+{
+    PrintStruct *data = user_data;
+    d (g_print ("print_pager_cancel_cb\n"));
+
+    print_disconnect (data);
+}
+
+static void
+print_pager_finish_cb (YelpPager   *pager,
+		       gpointer     user_data)
+{
+    PrintStruct *data = user_data;
+
+    d (g_print ("print_pager_finish_cb\n"));
+
+    print_disconnect (data);
+}
+
+static void
+window_print_document_cb (GtkAction *action, YelpWindow *window)
+{
+    PrintStruct *data;
+    YelpPager *pager;
+
+    if (!window->priv->current_doc)
+	return;
+
+    pager = yelp_db_print_pager_new (window->priv->current_doc);
+
+    if (!pager) {
+	return;
+    }
+
+    data = g_new0 (PrintStruct, 1);
+    data->pager = pager;
+    data->window = window;
+
+    data->page_handler =
+	g_signal_connect (data->pager,
+			  "page",
+			  G_CALLBACK (print_pager_page_cb),
+			  data);
+    data->error_handler =
+	g_signal_connect (data->pager,
+			  "error",
+			  G_CALLBACK (print_pager_error_cb),
+			  data);
+    data->cancel_handler =
+	g_signal_connect (data->pager,
+			  "error",
+			  G_CALLBACK (print_pager_cancel_cb),
+			  data);
+    data->finish_handler =
+	g_signal_connect (data->pager,
+			  "finish",
+			  G_CALLBACK (print_pager_finish_cb),
+			  data);
+
+    /* handled = */ yelp_pager_start (data->pager);
+}
+
+static void
+window_print_page_cb (GtkAction *action, YelpWindow *window)
+{
+    yelp_print_run (window, window->priv->html_view, NULL);
 }
 
 static void


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