Yelp Printing



Hi all,

I've attached (yet another) printing-in-Yelp patch.  This fixes a crash
if you try and do something crazy (like say cancelling a print or
something...) and *should* stop mozilla complaining when trying to print
with an open print preview.

It still crashes when trying to print a TOC page but it should now work
with Mozilla 1.7 branch as well as later (1.8 and 1.9)

Once again, anyone with a (working) printer, please try it out.

A couple of questions:
1. Does it need a "Page Setup" menu option.  As far as I can figure, all
necessary stuff is in the Print dialog, except choosing color /
greyscale.  Is this necessary?
2. Whats the best way to put in a Print Preview menu option?  Since
there are 2 print options (Print page and Print Document) and preview
works in the print dialog, can I just ignore this menu option?

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	22 Nov 2005 16:18:16 -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	22 Nov 2005 16:20:56 -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	22 Nov 2005 16:21:36 -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	22 Nov 2005 16:21:38 -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	22 Nov 2005 16:21:38 -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	22 Nov 2005 16:21:38 -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	22 Nov 2005 16:21:38 -0000
@@ -0,0 +1,86 @@
+/*
+ *  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;
+  gboolean called_finish;
+};
+
+
+
+
+
+#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	22 Nov 2005 16:21:40 -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;
@@ -131,7 +168,6 @@
     priv->anchor = NULL;
 
     priv->yelper = new Yelper (GTK_MOZ_EMBED (html));
-
     klass = YELP_HTML_GET_CLASS (html);
     if (!klass->font_handler) {
 	klass->font_handler =
@@ -154,6 +190,7 @@
 				      NULL);
 	html_set_a11y ();
     }
+    html_setup_printing ();
 }
 
 static void
@@ -197,6 +234,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 +423,77 @@
     html->priv->yelper->DoCommand ("cmd_selectAll");
 }
 
+void
+yelp_html_print (YelpHtml *html, YelpPrintInfo *info, gboolean preview, gint *npages)
+{
+    /* 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 */
+	    if (!preview) {
+		print->Print (settings, ProgList);
+	    } else {
+		nsIDOMWindow *cwin; 
+		webBrowser->GetContentDOMWindow (&cwin);
+		print->PrintPreview (settings, cwin, NULL);
+		print->GetPrintPreviewNumPages (npages);
+	    }
+	}
+    }
+}
+
+void
+yelp_html_preview_navigate (YelpHtml *html, gint page_no)
+{
+    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) {
+	    /* 0 is supposed to be PRINTPREVIEW_GOTO_PAGENUM */
+	    print->PrintPreviewNavigate (0, page_no);
+	}
+    }
+}
+
+void
+yelp_html_preview_end (YelpHtml *html)
+{
+    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) {
+	    
+	    print->ExitPrintPreview ();
+	}
+    }
+
+}
+
 static void
 html_set_fonts (void)
 {
@@ -421,4 +530,386 @@
 
     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 ();
+    g_print ("Embed is being shown now\n");
+    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	22 Nov 2005 16:21:40 -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,15 @@
 void            yelp_html_copy_selection (YelpHtml    *html);
 
 void            yelp_html_select_all     (YelpHtml    *html);
+
+void            yelp_html_print          (YelpHtml    *html,
+					  YelpPrintInfo *info,
+					  gboolean preview,
+					  gint *npages);
+void            yelp_html_preview_end    (YelpHtml    *html);
+void            yelp_html_preview_navigate (YelpHtml *html,
+					    gint page_no);
+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	22 Nov 2005 16:21:41 -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	22 Nov 2005 16:21:43 -0000
@@ -0,0 +1,749 @@
+/* -*- 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 );
+void                      print_present_config_dialog      (YelpPrintInfo *info);
+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);
+gboolean                 yelp_print_preview                (YelpPrintInfo *info);
+
+gboolean                 print_preview_finished_cb         (GtkWindow     *win,
+							    GdkEvent      *ev,
+							    YelpPrintInfo *info);
+void                     preview_go_first                  (GtkToolButton *b,
+							    YelpPrintInfo *info);
+void                     preview_go_back                   (GtkToolButton *b,
+							    YelpPrintInfo *info);
+void                     preview_go_forward                (GtkToolButton *b,
+							    YelpPrintInfo *info);
+void                     preview_go_last                   (GtkToolButton *b,
+							    YelpPrintInfo *info);
+void                     preview_close                     (GtkToolButton *b,
+							    YelpPrintInfo *info);
+gboolean                 print_free_idle_cb                (YelpPrintInfo *info);
+
+static GSList * current_jobs = NULL;
+
+static gboolean currently_running = FALSE;
+
+void
+yelp_print_run (YelpWindow *window, gpointer html, gpointer fake_win, 
+		gpointer content_box)
+{
+    YelpPrintInfo *info;
+    
+    info = yelp_print_get_print_info ();
+    info->owner = window;
+    info->html_frame = html;
+    info->fake_win = fake_win;
+    info->content_box = content_box;
+
+    print_present_config_dialog (info);
+    
+}
+
+void
+print_present_config_dialog (YelpPrintInfo *info)
+{
+    GtkWidget *dialog;
+    int ret;
+
+    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_PREVIEW) {
+	g_idle_add ((GSourceFunc) yelp_print_preview, info);
+	return;
+    }
+    if (ret != GNOME_PRINT_DIALOG_RESPONSE_PRINT) {
+	yelp_print_info_free (info);
+	return;
+    }
+    yelp_print_present_status_dialog (info->owner, 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, FALSE, NULL);
+
+    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 ||
+      response == GNOME_PRINT_DIALOG_RESPONSE_PREVIEW) {
+      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"));
+
+  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 = (gchar *) 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)
+{
+    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_widget_hide (info->dialog);
+    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 {
+	current_jobs = g_slist_remove (current_jobs, info);
+	yelp_print_info_free (info);
+    }
+}
+
+void 
+yelp_print_moz_finished (YelpPrintInfo *info)
+{
+    info->moz_finished = TRUE;
+
+    current_jobs = g_slist_remove (current_jobs, info);
+
+    if (!info->cancelled) {
+	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);
+	}
+	g_idle_add ((GSourceFunc) print_free_idle_cb, info);
+    }
+
+}
+
+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 (g_slist_length (jobs) != 0) {
+	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);
+}
+
+gboolean
+yelp_print_preview (YelpPrintInfo *info)
+{
+    gint width, height;
+    /* Add some funky nav widgets to the fake_win since we're gonna
+     * have to actually show it now :(
+     */
+    if (!info->previewed) {
+	info->previewed = TRUE;
+	GtkWidget *box = gtk_toolbar_new ();
+	
+	gtk_box_pack_start (GTK_BOX (info->content_box), box, FALSE, FALSE, 0);
+	info->GoFirst = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_GOTO_FIRST));
+	gtk_container_add (GTK_CONTAINER (box), info->GoFirst);
+	g_signal_connect (info->GoFirst, "clicked",
+			  G_CALLBACK (preview_go_first),
+			  info);
+	gtk_widget_show (info->GoFirst);
+	
+	info->GoBack = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK));
+	gtk_container_add (GTK_CONTAINER (box), info->GoBack);
+	g_signal_connect (info->GoBack, "clicked",
+			  G_CALLBACK (preview_go_back),
+			  info);
+	gtk_widget_show (info->GoBack);
+	
+	info->GoForward = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD));
+	gtk_container_add (GTK_CONTAINER (box), info->GoForward);
+	g_signal_connect (info->GoForward, "clicked",
+			  G_CALLBACK (preview_go_forward),
+			  info);
+	gtk_widget_show (info->GoForward);
+	
+	info->GoLast = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_GOTO_LAST));
+	gtk_container_add (GTK_CONTAINER (box), info->GoLast);
+	g_signal_connect (info->GoLast, "clicked",
+			  G_CALLBACK (preview_go_last),
+			  info);
+	gtk_widget_show (info->GoLast);
+	
+	info->Close = GTK_WIDGET (gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE));
+	gtk_container_add (GTK_CONTAINER (box), info->Close);
+	g_signal_connect (info->Close, "clicked",
+			  G_CALLBACK (preview_close),
+			  info);
+	gtk_widget_show (info->Close);
+	
+	gtk_widget_show (box);
+    }
+    gtk_window_set_modal (GTK_WINDOW (info->fake_win), TRUE);
+    gtk_widget_set_sensitive (info->GoFirst, FALSE);
+    gtk_widget_set_sensitive (info->GoBack, FALSE);
+    info->currentpage = 1;
+    yelp_html_print (info->html_frame, info, TRUE, &(info->npages));
+
+    if (info->npages == 1) { /*Desensitise all buttons */
+	gtk_widget_set_sensitive (info->GoForward, FALSE);
+	gtk_widget_set_sensitive (info->GoLast, FALSE);
+    }
+    g_signal_connect (info->fake_win, "delete-event",
+		      G_CALLBACK (print_preview_finished_cb),
+		      info);
+    
+    /* Set the preview window to the same size as the real window */
+    gtk_window_get_size (GTK_WINDOW (info->owner), &width, &height);
+    gtk_window_resize (GTK_WINDOW (info->fake_win), width, height);
+
+    gtk_widget_show (GTK_WIDGET (info->fake_win));
+
+    return FALSE;
+}
+
+gboolean
+print_preview_finished_cb (GtkWindow *win, GdkEvent *ev, YelpPrintInfo *info)
+{
+    gtk_widget_hide (GTK_WIDGET (info->fake_win));
+    yelp_html_preview_end (info->html_frame);
+    print_present_config_dialog (info);
+    return TRUE;
+}
+
+void
+preview_go_first (GtkToolButton *b, YelpPrintInfo *info)
+{
+    info->currentpage = 1;
+    yelp_html_preview_navigate (info->html_frame, info->currentpage);
+
+    /* Reset sensitives */
+    gtk_widget_set_sensitive (info->GoBack, FALSE);
+    gtk_widget_set_sensitive (info->GoFirst, FALSE);
+    gtk_widget_set_sensitive (info->GoForward, TRUE);
+    gtk_widget_set_sensitive (info->GoLast, TRUE);
+}
+
+void
+preview_go_back (GtkToolButton *b, YelpPrintInfo *info)
+{
+    info->currentpage--;
+    yelp_html_preview_navigate (info->html_frame, info->currentpage);
+
+    /* Reset sensitives */
+    gtk_widget_set_sensitive (info->GoForward, TRUE);
+    gtk_widget_set_sensitive (info->GoLast, TRUE);
+
+    if (info->currentpage == 1) {
+	gtk_widget_set_sensitive (info->GoBack, FALSE);
+	gtk_widget_set_sensitive (info->GoFirst, FALSE);
+    }
+}
+
+void
+preview_go_forward (GtkToolButton *b, YelpPrintInfo *info)
+{
+    info->currentpage++;
+    yelp_html_preview_navigate (info->html_frame, info->currentpage);
+    /* Reset sensitives */
+    gtk_widget_set_sensitive (info->GoBack, TRUE);
+    gtk_widget_set_sensitive (info->GoFirst, TRUE);
+
+    if (info->currentpage == info->npages) {
+	gtk_widget_set_sensitive (info->GoForward, FALSE);
+	gtk_widget_set_sensitive (info->GoLast, FALSE);
+    }
+}
+
+void
+preview_go_last (GtkToolButton *b, YelpPrintInfo *info)
+{
+    info->currentpage=info->npages;
+    yelp_html_preview_navigate (info->html_frame, info->currentpage);
+    
+    /* Reset sensitives */
+    gtk_widget_set_sensitive (info->GoBack, TRUE);
+    gtk_widget_set_sensitive (info->GoFirst, TRUE);
+    gtk_widget_set_sensitive (info->GoForward, FALSE);
+    gtk_widget_set_sensitive (info->GoLast, FALSE);
+
+}
+
+void 
+preview_close (GtkToolButton *b, YelpPrintInfo *info)
+{
+    print_preview_finished_cb (NULL, NULL, info);
+}
+
+gboolean
+print_free_idle_cb (YelpPrintInfo *info)
+{
+    yelp_print_info_free (info);
+    return FALSE;
+}
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	22 Nov 2005 16:21:43 -0000
@@ -0,0 +1,90 @@
+/* -*- 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;
+    gboolean previewed;
+    
+    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;
+    GtkWidget *content_box;
+
+    /* Preview buttons */
+    GtkWidget *GoBack;
+    GtkWidget *GoForward;
+    GtkWidget *GoFirst;
+    GtkWidget *GoLast;
+    GtkWidget *Close;
+    gint npages;
+    gint currentpage;
+
+
+} YelpPrintInfo;
+
+void          yelp_print_run               (YelpWindow *window, 
+					    gpointer html,
+					    gpointer fake_win,
+					    gpointer content_box);
+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	22 Nov 2005 16:21:48 -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,251 @@
     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;
+	GtkWidget *vbox = gtk_vbox_new (FALSE, FALSE);
+	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 (vbox));
+	gtk_box_pack_end (GTK_BOX (vbox), GTK_WIDGET (html), TRUE, TRUE, 0);
+
+	gtk_widget_show (gtk_window);
+	gtk_widget_show (GTK_WIDGET (html));
+	gtk_widget_show (vbox);
+	gtk_widget_hide (gtk_window);
+	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, vbox);
+
+	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)
+{
+    GtkWidget *gtk_win;
+    YelpPager  *pager;
+    YelpPage   *page  = NULL;
+    YelpHtml *html;
+    int length, offset;
+    gchar *uri;
+    GtkWidget *vbox = gtk_vbox_new (FALSE, FALSE);
+
+    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);
+
+    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);
+    
+    yelp_html_set_base_uri (html, uri);
+
+    if (pager) {
+	page = (YelpPage *) yelp_pager_get_page (pager, window->priv->current_frag);
+	
+	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);
+    } else { /*html file.  Dump file to window the easy way*/
+	GnomeVFSHandle  *handle;
+	GnomeVFSResult   result;
+	GnomeVFSFileSize n;
+	gchar            buffer[BUFFER_SIZE];	
+
+	result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
+
+	/* Assuming the file exists.  If it doesn't how did we get this far?
+	 * There are more sinister forces at work...
+	 */
+
+	switch (yelp_doc_info_get_type (window->priv->current_doc)) {
+	case YELP_DOC_TYPE_HTML:
+	    yelp_html_open_stream (html, "text/html");
+	    break;
+	case YELP_DOC_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);
+
+	
+    
+    }
+    g_free (uri);
+    yelp_print_run (window, html, gtk_win, vbox);
 }
 
 static void


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