diff options
author | Don Scorgie <dscorgie@cvs.gnome.org> | 2005-12-11 22:28:54 +0000 |
---|---|---|
committer | Don Scorgie <dscorgie@src.gnome.org> | 2005-12-11 22:28:54 +0000 |
commit | b4211bf00eecfed75260d1e8447adbfe9b6384be (patch) | |
tree | 698a77076302351acbe14617ba7024dac26fd8b6 | |
parent | 3a2985a5a4e5ac67937c7650d469e1acc854c6b3 (diff) | |
download | yelp-b4211bf00eecfed75260d1e8447adbfe9b6384be.tar.gz |
Add printing support
2005-12-11 Don Scorgie <dscorgie@cvs.gnome.org>
* configure.in:
* data/ui/yelp-ui.xml:
* src/Makefile.am:
* src/Yelper.h:
* src/Yelper.cpp:
* src/yelp-db-print-pager.h:
* src/yelp-db-print-pager.c:
* src/yelp-gecko-services.h:
* src/yelp-gecko-services.cpp:
* src/yelp-html.cpp:
* src/yelp-html.h:
* src/yelp-main.c:
* src/yelp-print.c:
* src/yelp-print.h:
* src/yelp-window.c:
Add printing support
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | data/ui/yelp-ui.xml | 3 | ||||
-rw-r--r-- | src/Makefile.am | 13 | ||||
-rw-r--r-- | src/Yelper.cpp | 254 | ||||
-rw-r--r-- | src/Yelper.h | 10 | ||||
-rw-r--r-- | src/yelp-db-print-pager.c | 295 | ||||
-rw-r--r-- | src/yelp-db-print-pager.h | 55 | ||||
-rw-r--r-- | src/yelp-gecko-services.cpp | 243 | ||||
-rw-r--r-- | src/yelp-gecko-services.h | 80 | ||||
-rw-r--r-- | src/yelp-html.cpp | 36 | ||||
-rw-r--r-- | src/yelp-html.h | 11 | ||||
-rw-r--r-- | src/yelp-main.c | 7 | ||||
-rw-r--r-- | src/yelp-print.c | 743 | ||||
-rw-r--r-- | src/yelp-print.h | 90 | ||||
-rw-r--r-- | src/yelp-window.c | 285 |
16 files changed, 2140 insertions, 6 deletions
@@ -1,3 +1,22 @@ +2005-12-11 Don Scorgie <dscorgie@cvs.gnome.org> + + * configure.in: + * data/ui/yelp-ui.xml: + * src/Makefile.am: + * src/Yelper.h: + * src/Yelper.cpp: + * src/yelp-db-print-pager.h: + * src/yelp-db-print-pager.c: + * src/yelp-gecko-services.h: + * src/yelp-gecko-services.cpp: + * src/yelp-html.cpp: + * src/yelp-html.h: + * src/yelp-main.c: + * src/yelp-print.c: + * src/yelp-print.h: + * src/yelp-window.c: + Add printing support + 2005-12-11 Brent Smith <gnome@nextreality.net> * src/yelp-toc-pager.c: (yelp_toc_pager_init), diff --git a/configure.in b/configure.in index 9d14c2aa..d242cb56 100644 --- a/configure.in +++ b/configure.in @@ -65,6 +65,8 @@ PKG_CHECK_MODULES(YELP, [ 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 diff --git a/data/ui/yelp-ui.xml b/data/ui/yelp-ui.xml index b91a5e00..ea2c4abb 100644 --- a/data/ui/yelp-ui.xml +++ b/data/ui/yelp-ui.xml @@ -6,6 +6,9 @@ <separator/> <menuitem action="AboutDocument"/> <separator/> + <menuitem action="PrintPage"/> + <menuitem action="PrintDocument"/> + <separator/> <menuitem action="CloseWindow"/> </menu> <menu action="EditMenu"> diff --git a/src/Makefile.am b/src/Makefile.am index 568032e4..4579779b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,6 +9,7 @@ yelp_SOURCES = \ 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_SOURCES = \ 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 @@ mozilla_include_subdirs = \ webbrwsr \ string \ webshell \ - commandhandler + commandhandler \ + layout \ + uriloader \ + content \ + gfx \ + necko yelp_CPPFLAGS = \ -I$(top_srcdir) \ @@ -114,6 +122,7 @@ test_man_parser_LDFLAGS = $(AM_LDFLAGS) 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 \ diff --git a/src/Yelper.cpp b/src/Yelper.cpp index de2f4f07..e18f1c92 100644 --- a/src/Yelper.cpp +++ b/src/Yelper.cpp @@ -43,6 +43,7 @@ #include <nsIDOMEventTarget.h> #include <nsIDOMNode.h> #include <nsIDOMHTMLAnchorElement.h> +#include <nsIWebBrowserPrint.h> #ifdef TYPEAHEADFIND #include <nsIDocShell.h> @@ -50,9 +51,12 @@ #endif /* TYPEAHEADFIND */ #include <stdlib.h> +#include <unistd.h> #include <gtkmozembed_internal.h> +#include <yelp-gecko-services.h> + #ifdef GNOME_ENABLE_DEBUG #define d(x) x #else @@ -254,3 +258,253 @@ Yelper::ProcessMouseEvent (void* aEvent) g_signal_emit_by_name (mEmbed, "popupmenu_requested", cHref.get()); } + +nsresult +Yelper::Print (YelpPrintInfo *print_info, PRBool preview, int *prev_pages) +{ + nsresult rv; + + nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface (mWebBrowser, &rv)); + NS_ENSURE_SUCCESS (rv, rv); + + nsCOMPtr<nsIPrintSettings> settings; + + rv = print->GetGlobalPrintSettings (getter_AddRefs (settings)); + NS_ENSURE_SUCCESS (rv, rv); + + SetPrintSettings (print_info, settings); + + nsCOMPtr<PrintListener> listener = new PrintListener (print_info, print); + + if (!preview) + rv = print->Print (settings, listener); + else { + rv = print->PrintPreview (settings, mDOMWindow, nsnull); + rv |= print->GetPrintPreviewNumPages (prev_pages); + } + return rv; + +} + +nsresult +Yelper::PrintPreviewNavigate (int page_no) +{ + nsresult rv; + nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface (mWebBrowser, &rv)); + NS_ENSURE_SUCCESS (rv, rv); + + return print->PrintPreviewNavigate (0, page_no); +} + + + +nsresult +Yelper::PrintPreviewEnd () +{ + nsresult rv; + nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface (mWebBrowser, &rv)); + NS_ENSURE_SUCCESS (rv, rv); + + return print->ExitPrintPreview (); + +} + +void +Yelper::SetPrintSettings (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]); + + +} diff --git a/src/Yelper.h b/src/Yelper.h index 9d0d9993..c7b5d48a 100644 --- a/src/Yelper.h +++ b/src/Yelper.h @@ -32,6 +32,8 @@ #else #include <nsIWebBrowserFind.h> #endif +#include <nsIPrintSettings.h> +#include <yelp-print.h> class Yelper { @@ -52,6 +54,12 @@ public: void ProcessMouseEvent (void *aEvent); + nsresult Print (YelpPrintInfo *print_info, PRBool preview, + int *prev_pages); + nsresult PrintPreviewNavigate (int page_no); + nsresult PrintPreviewEnd (); + + private: PRBool mInitialised; GtkMozEmbed *mEmbed; @@ -62,6 +70,8 @@ private: #else nsCOMPtr<nsIWebBrowserFind> mFinder; #endif + + void SetPrintSettings (YelpPrintInfo *settings, nsIPrintSettings *target); }; #endif /* !__YELPER_H__ */ diff --git a/src/yelp-db-print-pager.c b/src/yelp-db-print-pager.c new file mode 100644 index 00000000..8d8dcf7e --- /dev/null +++ b/src/yelp-db-print-pager.c @@ -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 (¶ms, ¶ms_i, ¶ms_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; +} + diff --git a/src/yelp-db-print-pager.h b/src/yelp-db-print-pager.h new file mode 100644 index 00000000..013e8af5 --- /dev/null +++ b/src/yelp-db-print-pager.h @@ -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__ */ diff --git a/src/yelp-gecko-services.cpp b/src/yelp-gecko-services.cpp new file mode 100644 index 00000000..a56c3a3f --- /dev/null +++ b/src/yelp-gecko-services.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2002 Philip Langdale + * Copyright (C) 2003-2004 Christian Persch + * Copyright (C) 2005 Juerg Billeter + * 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. + * + */ + +#include <mozilla-config.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "nsError.h" +#undef MOZILLA_INTERNAL_API +#include <nsEmbedString.h> +#define MOZILLA_INTERNAL_API 1 + +#include "yelp-gecko-services.h" + +#include <nsIPrintSettings.h> +#include <nsCOMPtr.h> +#include <nsIComponentRegistrar.h> +#include <nsIInterfaceRequestorUtils.h> +#include <nsIGenericFactory.h> +#include <nsILocalFile.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; +} + +NS_GENERIC_FACTORY_CONSTRUCTOR(GPrintingPromptService) + +static const nsModuleComponentInfo sAppComps[] = { + { + G_PRINTINGPROMPTSERVICE_CLASSNAME, + G_PRINTINGPROMPTSERVICE_CID, + G_PRINTINGPROMPTSERVICE_CONTRACTID, + GPrintingPromptServiceConstructor + }, +}; + + + +void +yelp_register_printing () +{ + 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; + } + +} diff --git a/src/yelp-gecko-services.h b/src/yelp-gecko-services.h new file mode 100644 index 00000000..66262fe1 --- /dev/null +++ b/src/yelp-gecko-services.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2000 Marco Pesenti Gritti + * 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. + * + */ + +#ifndef __YELP_GECKO_SERVICES_H +#define __YELP_GECKO_SERVICES_H + +#include <nsIPrintingPromptService.h> +#include <nsIWebProgressListener.h> +#include <nsIPrintProgressParams.h> +#include "yelp-print.h" + +#define G_PRINTINGPROMPTSERVICE_CID \ + { /* dbf438d3-5f62-4978-a700-6fc39447477c */ \ + 0xdbf438d3, 0x5f62, 0x4978, \ + { 0xa7, 0x00, 0x6f, 0xc3, 0x94, 0x47, 0x47, 0x7c } } + +#define G_PRINTINGPROMPTSERVICE_CLASSNAME "Yelps Printing Prompt Service" +#define G_PRINTINGPROMPTSERVICE_CONTRACTID "@mozilla.org/embedcomp/printingprompt-service;1" + +void yelp_register_printing (); + +/* 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 diff --git a/src/yelp-html.cpp b/src/yelp-html.cpp index f1513ab8..50ec8416 100644 --- a/src/yelp-html.cpp +++ b/src/yelp-html.cpp @@ -31,9 +31,12 @@ #include "yelp-marshal.h" #include "yelp-gecko-utils.h" #include "yelp-settings.h" +#include "yelp-gecko-services.h" #include "Yelper.h" +#include <libgnome/gnome-init.h> + #ifdef GNOME_ENABLE_DEBUG #define d(x) x #else @@ -130,7 +133,6 @@ html_init (YelpHtml *html) priv->anchor = NULL; priv->yelper = new Yelper (GTK_MOZ_EMBED (html)); - klass = YELP_HTML_GET_CLASS (html); if (!klass->font_handler) { klass->font_handler = @@ -153,6 +155,7 @@ html_init (YelpHtml *html) NULL); html_set_a11y (); } + yelp_register_printing (); } static void @@ -384,6 +387,24 @@ yelp_html_select_all (YelpHtml *html) html->priv->yelper->DoCommand ("cmd_selectAll"); } +void +yelp_html_print (YelpHtml *html, YelpPrintInfo *info, gboolean preview, gint *npages) +{ + html->priv->yelper->Print (info, preview, npages); +} + +void +yelp_html_preview_navigate (YelpHtml *html, gint page_no) +{ + html->priv->yelper->PrintPreviewNavigate (page_no); +} + +void +yelp_html_preview_end (YelpHtml *html) +{ + html->priv->yelper->PrintPreviewEnd (); +} + static void html_set_fonts (void) { @@ -421,3 +442,16 @@ html_set_a11y (void) caret = yelp_settings_get_caret (); yelp_gecko_set_caret (caret); } + +void +yelp_html_initialize (void) +{ + static gboolean initialized = FALSE; + + if (initialized) + return; + initialized = TRUE; + + gtk_moz_embed_set_comp_path (MOZILLA_HOME); + +} diff --git a/src/yelp-html.h b/src/yelp-html.h index 66f1fae4..cd125bac 100644 --- a/src/yelp-html.h +++ b/src/yelp-html.h @@ -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 ()) @@ -98,6 +100,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 #endif /* __YELP_HTML_H__ */ diff --git a/src/yelp-main.c b/src/yelp-main.c index 5ab047ff..225e2180 100644 --- a/src/yelp-main.c +++ b/src/yelp-main.c @@ -37,11 +37,11 @@ #include <libgnomeui/gnome-client.h> #include <string.h> #include <stdlib.h> -#include <gtkmozembed.h> #include "GNOME_Yelp.h" #include "yelp-window.h" #include "yelp-base.h" +#include "yelp-html.h" #define YELP_FACTORY_OAFIID "OAFIID:GNOME_Yelp_Factory" @@ -333,8 +333,8 @@ main (int argc, char **argv) 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, @@ -366,6 +366,7 @@ main (int argc, char **argv) BonoboGenericFactory *factory; char *registration_id; + registration_id = bonobo_activation_make_registration_id ( YELP_FACTORY_OAFIID, gdk_display_get_name (gdk_display_get_default ())); diff --git a/src/yelp-print.c b/src/yelp-print.c new file mode 100644 index 00000000..2dad03cb --- /dev/null +++ b/src/yelp-print.c @@ -0,0 +1,743 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2002 Jorn Baayen + * Copyright (C) 2003, 2004 Christian Persch + * Copyright (C) 2005 Juerg Billeter + * 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. + * + */ + +#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" +#include "yelp-utils.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 (yelp_dot_dir(), "yelp-printing.xml", 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 ( yelp_dot_dir (), "yelp-printing.xml", NULL); + g_file_set_contents (filename, str, -1, NULL); + + g_free (str); + g_free (filename); + +} + +void +yelp_print_info_free (YelpPrintInfo *info) +{ + if (info) { + g_object_unref (info->config); + if (info->tempfile) { + g_unlink (info->tempfile); + g_free (info->tempfile); + } + g_free (info->header_left_string); + g_free (info->header_center_string); + g_free (info->header_right_string); + g_free (info->footer_left_string); + g_free (info->footer_center_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; +} diff --git a/src/yelp-print.h b/src/yelp-print.h new file mode 100644 index 00000000..be3a293e --- /dev/null +++ b/src/yelp-print.h @@ -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 diff --git a/src/yelp-window.c b/src/yelp-window.c index 97b3a4cd..00004120 100644 --- a/src/yelp-window.c +++ b/src/yelp-window.c @@ -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 @@ static void window_add_widget (GtkUIManager *ui_manager, 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); @@ -309,6 +313,16 @@ static const GtkActionEntry entries[] = { "<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, @@ -723,6 +737,7 @@ yelp_window_load (YelpWindow *window, const gchar *uri) YelpWindowPriv *priv; YelpDocInfo *doc_info; gchar *frag_id; + GtkAction *action; g_return_if_fail (YELP_IS_WINDOW (window)); @@ -770,6 +785,11 @@ yelp_window_load (YelpWindow *window, const gchar *uri) if (priv->current_frag) g_free (priv->current_frag); + action = gtk_action_group_get_action (priv->action_group, + "PrintDocument"); + 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); @@ -801,6 +821,7 @@ window_do_load (YelpWindow *window, YelpDocInfo *doc_info, gchar *frag_id) { + GtkAction *action; YelpWindowPriv *priv; GError *error = NULL; gboolean handled = FALSE; @@ -813,6 +834,13 @@ window_do_load (YelpWindow *window, priv = window->priv; + action = gtk_action_group_get_action (priv->action_group, + "PrintDocument"); + 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 @@ -835,6 +863,10 @@ window_do_load (YelpWindow *window, #endif case YELP_DOC_TYPE_DOCBOOK_XML: + 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; @@ -1017,6 +1049,11 @@ window_populate (YelpWindow *window) 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"); + 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); @@ -1935,6 +1972,254 @@ window_new_window_cb (GtkAction *action, YelpWindow *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; + } + g_free (data); +} + +static void +print_pager_page_cb (YelpPager *pager, + gchar *page_id, + gpointer user_data) +{ + PrintStruct *data = user_data; + YelpPage *page; + 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); + + if (result != GNOME_VFS_OK) { + GError *error = NULL; + g_set_error (&error, YELP_ERROR, YELP_ERROR_IO, + _("The file ā%sā could not be read. This file might " + "be missing, or you might not have permissions to " + "read it."), + uri); + window_error (window, error, TRUE); + return; + } + /* 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 window_about_document_cb (GtkAction *action, YelpWindow *window) { |