2007-09-18 [colin] 3.0.1cvs2
authorColin Leroy <colin@colino.net>
Tue, 18 Sep 2007 06:58:04 +0000 (06:58 +0000)
committerColin Leroy <colin@colino.net>
Tue, 18 Sep 2007 06:58:04 +0000 (06:58 +0000)
* src/Makefile.am
* src/mainwindow.c
* src/messageview.c
* src/messageview.h
* src/prefs_ext_prog.c
* src/prefs_fonts.c
* src/printing.c
* src/printing.h
* src/summaryview.c
Use GtkPrintOperation by default on GTK+ >= 2.10
Patch by Holger Berndt <hb@claws-mail.org>

12 files changed:
ChangeLog
PATCHSETS
configure.ac
src/Makefile.am
src/mainwindow.c
src/messageview.c
src/messageview.h
src/prefs_ext_prog.c
src/prefs_fonts.c
src/printing.c [new file with mode: 0644]
src/printing.h [new file with mode: 0644]
src/summaryview.c

index 26824c582bb6727d48ef00cc0e275a7c4c9f8f52..a492f04911cb9019204316d1292c9df3ffe2eb5a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2007-09-18 [colin]     3.0.1cvs2
+
+       * src/Makefile.am
+       * src/mainwindow.c
+       * src/messageview.c
+       * src/messageview.h
+       * src/prefs_ext_prog.c
+       * src/prefs_fonts.c
+       * src/printing.c
+       * src/printing.h
+       * src/summaryview.c
+               Use GtkPrintOperation by default on GTK+ >= 2.10
+               Patch by Holger Berndt <hb@claws-mail.org>
+
 2007-09-18 [paul]      3.0.1cvs1
 
        * NEWS
index 9b638b7cbc420c3f29845fc023038c3005052467..29b4c496685ecf1dbe1fd1184d695f1f523bad38 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.207.2.182 -r 1.207.2.183 src/folderview.c;  cvs diff -u -r 1.1.2.19 -r 1.1.2.20 src/image_viewer.c;  cvs diff -u -r 1.75.2.47 -r 1.75.2.48 src/matcher.c;  cvs diff -u -r 1.94.2.150 -r 1.94.2.151 src/messageview.c;  cvs diff -u -r 1.13.2.30 -r 1.13.2.31 src/common/plugin.c;  ) > 3.0.0cvs17.patchset
 ( cvs diff -u -r 1.213.2.160 -r 1.213.2.161 src/folder.c;  ) > 3.0.0cvs18.patchset
 ( cvs diff -u -r 1.42.2.34 -r 1.42.2.35 NEWS;  cvs diff -u -r 1.8.2.41 -r 1.8.2.42 README;  cvs diff -u -r 1.1.2.23 -r 1.1.2.24 RELEASE_NOTES;  cvs diff -u -r 1.654.2.2920 -r 1.654.2.2921 configure.ac;  ) > 3.0.1cvs1.patchset
+( cvs diff -u -r 1.155.2.74 -r 1.155.2.75 src/Makefile.am;  cvs diff -u -r 1.274.2.211 -r 1.274.2.212 src/mainwindow.c;  cvs diff -u -r 1.94.2.151 -r 1.94.2.152 src/messageview.c;  cvs diff -u -r 1.19.2.16 -r 1.19.2.17 src/messageview.h;  cvs diff -u -r 1.3.2.16 -r 1.3.2.17 src/prefs_ext_prog.c;  cvs diff -u -r 1.4.2.20 -r 1.4.2.21 src/prefs_fonts.c;  diff -u /dev/null src/printing.c;  diff -u /dev/null src/printing.h;  cvs diff -u -r 1.395.2.325 -r 1.395.2.326 src/summaryview.c;  ) > 3.0.1cvs2.patchset
index 332dc5acffbe6657638a73098ee629279138190d..ff7b5706e8143760b7f6d4127b56770686e28440 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=0
 MICRO_VERSION=1
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=1
+EXTRA_VERSION=2
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
@@ -843,12 +843,15 @@ fi
 AM_CONDITIONAL(CLAWS_LIBETPAN, test "x$libetpan_result" = "xyes")
 
 
-dnl Libgnomeprint
+dnl Printing support. GTK will be used if present and gnomeprint is not explicitely enabled
+PKG_CHECK_MODULES(GTK210, gtk+-2.0 >= 2.10, ac_cv_have_gtk210=yes, ac_cv_have_gtk210=no)
 AC_MSG_CHECKING([whether to use libgnomeprint])
 AC_ARG_ENABLE(gnomeprint,
        [  --disable-gnomeprint         disable libgnomeprint support],
-       [ac_cv_enable_gnomeprint=$enableval], [ac_cv_enable_gnomeprint=yes])
-if test x$ac_cv_enable_gnomeprint = xyes; then
+       [ac_cv_enable_gnomeprint=$enableval], [ac_cv_enable_gnomeprint=auto])
+if test x$ac_cv_enable_gnomeprint = xyes \
+       -o \( x$ac_cv_enable_gnomeprint = xauto \
+          -a x$ac_cv_have_gtk210 = xno \); then
        AC_MSG_RESULT(yes)
        PKG_CHECK_MODULES(GNOMEPRINT, libgnomeprint-2.2 libgnomeprintui-2.2,
                          ac_cv_enable_gnomeprint=yes, ac_cv_enable_gnomeprint=no)
@@ -860,6 +863,7 @@ if test x$ac_cv_enable_gnomeprint = xyes; then
                AC_MSG_WARN([*** using built-in printing support ***])
        fi
 else
+       ac_cv_enable_gnomeprint=no
        AC_MSG_RESULT(no)
 fi
 AM_CONDITIONAL(CLAWS_GNOMEPRINT, test x"$ac_cv_enable_gnomeprint" = x"yes")
index 5483651085e8871e96510ce40518a8448cee6d94..1af608b3bba700eed363eea3b84d5e5868f2a4c6 100644 (file)
@@ -129,6 +129,7 @@ claws_mail_SOURCES = \
        prefs_themes.c \
        prefs_toolbar.c \
        prefs_wrapping.c \
+       printing.c \
        privacy.c \
        procheader.c \
        procmime.c \
@@ -275,6 +276,7 @@ claws_mailinclude_HEADERS = \
        prefs_themes.h \
        prefs_toolbar.h \
        prefs_wrapping.h \
+       printing.h \
        privacy.h \
        procheader.h \
        procmime.h \
index e64040f3dd06f85d57b6ee9da14982de58d87c4e..34354a64e49699934384890ae8805781bf22018e 100644 (file)
@@ -98,6 +98,7 @@
 #include "textview.h"
 #include "imap.h"
 #include "socket.h"
+#include "printing.h"
 
 #define AC_LABEL_WIDTH 240
 
@@ -170,6 +171,12 @@ static void empty_trash_cb  (MainWindow    *mainwin,
 static void save_as_cb          (MainWindow    *mainwin,
                                  guint          action,
                                  GtkWidget     *widget);
+#if GTK_CHECK_VERSION(2,10,0) && !defined(USE_GNOMEPRINT)
+static void page_setup_cb       (MainWindow    *mainwin,
+                                 guint          action,
+                                 GtkWidget     *widget);
+#endif
+
 static void print_cb            (MainWindow    *mainwin,
                                  guint          action,
                                  GtkWidget     *widget);
@@ -536,6 +543,9 @@ static GtkItemFactoryEntry mainwin_entries[] =
        {N_("/_File/Empty all _Trash folders"), "<shift>D", empty_trash_cb, 0, NULL},
        {N_("/_File/---"),                      NULL, NULL, 0, "<Separator>"},
        {N_("/_File/_Save as..."),              "<control>S", save_as_cb, 0, NULL},
+#if GTK_CHECK_VERSION(2,10,0) && !defined(USE_GNOMEPRINT)
+       {N_("/_File/Page setup..."),            NULL, page_setup_cb, 0, NULL},
+#endif
        {N_("/_File/_Print..."),                "<control>P", print_cb, 0, NULL},
        {N_("/_File/---"),                      NULL, NULL, 0, "<Separator>"},
        {N_("/_File/_Work offline"),            "<control>W", toggle_work_offline_cb, 0, "<ToggleItem>"},
@@ -3376,6 +3386,19 @@ static void print_cb(MainWindow *mainwin, guint action, GtkWidget *widget)
        summary_print(mainwin->summaryview);
 }
 
+#if GTK_CHECK_VERSION(2,10,0) && !defined(USE_GNOMEPRINT)
+static void page_setup_cb(MainWindow *mainwin, guint action, GtkWidget *widget)
+{
+       MainWindow *mainwindow;
+       GtkWindow *win;
+
+       mainwindow = mainwindow_get_mainwindow();
+       win = (mainwindow ? GTK_WINDOW(mainwindow->window) : NULL);
+
+       printing_page_setup(win);
+}
+#endif
+
 static void app_exit_cb(MainWindow *mainwin, guint action, GtkWidget *widget)
 {
        if (prefs_common.confirm_on_exit) {
index 028f0d07e6b51b6900bff7d937000ef41be47abf..8bbea0c036938f507a4759330b0168e28f4fc0fa 100644 (file)
@@ -67,6 +67,7 @@
 #include "inc.h"
 #include "log.h"
 #include "combobox.h"
+#include "printing.h"
 
 static GList *messageview_list = NULL;
 
@@ -94,6 +95,11 @@ static void partial_recv_unmark_clicked (NoticeView  *noticeview,
 static void save_as_cb                 (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
+#if GTK_CHECK_VERSION(2,10,0) && !defined(USE_GNOMEPRINT)
+static void page_setup_cb              (gpointer        data,
+                                        guint           action,
+                                        GtkWidget      *widget);
+#endif
 static void print_cb                   (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
@@ -163,6 +169,9 @@ static GtkItemFactoryEntry msgview_entries[] =
 {
        {N_("/_File"),                  NULL, NULL, 0, "<Branch>"},
        {N_("/_File/_Save as..."),      "<control>S", save_as_cb, 0, NULL},
+#if GTK_CHECK_VERSION(2,10,0) && !defined(USE_GNOMEPRINT)
+       {N_("/_File/Page setup..."),    NULL, page_setup_cb, 0, NULL},
+#endif
        {N_("/_File/_Print..."),        "<control>P", print_cb, 0, NULL},
        {N_("/_File/---"),              NULL, NULL, 0, "<Separator>"},
        {N_("/_File/_Close"),           "<control>W", close_cb, 0, NULL},
@@ -1500,9 +1509,12 @@ static void save_as_cb(gpointer data, guint action, GtkWidget *widget)
        messageview_save_as(messageview);
 }
 
-#ifdef USE_GNOMEPRINT
+#if defined(USE_GNOMEPRINT) || GTK_CHECK_VERSION(2,10,0)
 static void print_mimeview(MimeView *mimeview, gint sel_start, gint sel_end, gint partnum) 
 {
+#if !defined(USE_GNOMEPRINT) && GTK_CHECK_VERSION(2,10,0)
+       MainWindow *mainwin;
+#endif
        if (!mimeview 
        ||  !mimeview->textview
        ||  !mimeview->textview->text)
@@ -1529,8 +1541,15 @@ static void print_mimeview(MimeView *mimeview, gint sel_start, gint sel_end, gin
                        gtk_text_buffer_get_iter_at_offset(buffer, &end, sel_end);
                        gtk_text_buffer_select_range(buffer, &start, &end);
                }
-
+#if defined(USE_GNOMEPRINT)
                gedit_print(GTK_TEXT_VIEW(mimeview->textview->text));
+#else
+               /* TODO: Get the real parent window, not the main window */
+               mainwin = mainwindow_get_mainwindow();
+               printing_print(GTK_TEXT_VIEW(mimeview->textview->text),
+                              mainwin ? GTK_WINDOW(mainwin->window) : NULL,
+                               sel_start, sel_end);
+#endif
        }
 }
 
@@ -1564,10 +1583,19 @@ void messageview_print(MsgInfo *msginfo, gboolean all_headers,
 }
 #endif
 
+#if GTK_CHECK_VERSION(2,10,0) && !defined(USE_GNOMEPRINT)
+static void page_setup_cb(gpointer data, guint action, GtkWidget *widget)
+{
+       MessageView *messageview = (MessageView *)data;
+       printing_page_setup(messageview ?
+                           GTK_WINDOW(messageview->window) : NULL);
+}
+#endif
+
 static void print_cb(gpointer data, guint action, GtkWidget *widget)
 {
        MessageView *messageview = (MessageView *)data;
-#ifndef USE_GNOMEPRINT
+#if !defined(USE_GNOMEPRINT) && !GTK_CHECK_VERSION(2,10,0)
        gchar *cmdline = NULL;
        gchar *p;
 #else
@@ -1575,9 +1603,10 @@ static void print_cb(gpointer data, guint action, GtkWidget *widget)
 #endif
 
        if (!messageview->msginfo) return;
-#ifndef USE_GNOMEPRINT
+
+#if !defined(USE_GNOMEPRINT) && !GTK_CHECK_VERSION(2,10,0)
        cmdline = input_dialog(_("Print"),
-                              _("Enter the print command line:\n"
+                              _("Ente the print command line:\n"
                                 "('%s' will be replaced with file name)"),
                               prefs_common.print_cmd);
        if (!cmdline) return;
index 7a5c578627d911ed1b35df7ad916184f51183942..b02c37fdbf3668eae67d4d92fb0814b47ff935b3 100644 (file)
@@ -116,7 +116,7 @@ gchar *messageview_get_selection            (MessageView    *msgview);
 void messageview_set_menu_sensitive            (MessageView    *msgview);
 void messageview_learn                         (MessageView    *msgview,
                                                 gboolean is_spam);
-#ifdef USE_GNOMEPRINT
+#if defined(USE_GNOMEPRINT) || GTK_CHECK_VERSION(2,10,0)
 void messageview_print                         (MsgInfo        *msginfo,
                                                 gboolean        all_headers,
                                                 gint            sel_start,
index fe11ead979827f22e6972dace1c1ca17270ce757..f90c95ad19e7fc82dd200b0027600f60ac9d7870 100644 (file)
@@ -200,9 +200,9 @@ static void prefs_ext_prog_create_widget(PrefsPage *_page, GtkWindow *window,
                           prefs_common.mime_textviewer ? prefs_common.mime_textviewer : "");
 
        printcmd_label = gtk_label_new (_("Print command"));
-       #ifndef USE_GNOMEPRINT
-               gtk_widget_show(printcmd_label);
-       #endif
+#if !defined(USE_GNOMEPRINT) && !GTK_CHECK_VERSION(2,10,0)
+       gtk_widget_show(printcmd_label);
+#endif
        gtk_table_attach(GTK_TABLE (table2), printcmd_label, 0, 1, 3, 4,
                         (GtkAttachOptions) (GTK_FILL),
                         (GtkAttachOptions) (0), 0, 2);
@@ -210,9 +210,9 @@ static void prefs_ext_prog_create_widget(PrefsPage *_page, GtkWindow *window,
        gtk_misc_set_alignment(GTK_MISC (printcmd_label), 1, 0.5);
 
        printcmd_entry = gtk_entry_new ();
-       #ifndef USE_GNOMEPRINT
-               gtk_widget_show(printcmd_entry);
-       #endif
+#if !defined(USE_GNOMEPRINT) && !GTK_CHECK_VERSION(2,10,0)
+       gtk_widget_show(printcmd_entry);
+#endif
        gtk_table_attach(GTK_TABLE (table2), printcmd_entry, 1, 2, 3, 4,
                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                         (GtkAttachOptions) (0), 0, 0);
index 7f1fa1c7f8baa8814a3e5b6db4c29620067befd6..573671d5ed5818719bfaf0daef28af69eb19b7f5 100644 (file)
@@ -44,7 +44,7 @@ typedef struct _FontsPage
 
        GtkWidget *entry_folderviewfont;
        GtkWidget *entry_messageviewfont;
-#ifdef USE_GNOMEPRINT
+#if defined(USE_GNOMEPRINT) || GTK_CHECK_VERSION(2,10,0)
        GtkWidget *print_checkbutton;
        GtkWidget *entry_messageprintfont;
 #endif
@@ -59,7 +59,7 @@ static void prefs_fonts_create_widget(PrefsPage *_page, GtkWindow *window,
        GtkWidget *entry_folderviewfont;
        GtkWidget *entry_messageviewfont;
        GtkWidget *tmplabel;
-#ifdef USE_GNOMEPRINT
+#if defined(USE_GNOMEPRINT) || GTK_CHECK_VERSION(2,10,0)
        GtkWidget *entry_messageprintfont;
        GtkWidget *print_checkbutton;
 #endif
@@ -105,7 +105,7 @@ static void prefs_fonts_create_widget(PrefsPage *_page, GtkWindow *window,
                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                         (GtkAttachOptions) (0), 0, 0);
 
-#ifdef USE_GNOMEPRINT
+#if defined(USE_GNOMEPRINT) || GTK_CHECK_VERSION(2,10,0)
        /* print check button */
        print_checkbutton = gtk_check_button_new_with_label(_("Use different font for printing"));
        gtk_widget_show(print_checkbutton);
@@ -146,7 +146,7 @@ static void prefs_fonts_create_widget(PrefsPage *_page, GtkWindow *window,
        prefs_fonts->window                     = GTK_WIDGET(window);
        prefs_fonts->entry_folderviewfont       = entry_folderviewfont;
        prefs_fonts->entry_messageviewfont      = entry_messageviewfont;
-#ifdef USE_GNOMEPRINT
+#if defined(USE_GNOMEPRINT) || GTK_CHECK_VERSION(2,10,0)
        prefs_fonts->entry_messageprintfont     = entry_messageprintfont;
        prefs_fonts->print_checkbutton          = print_checkbutton;
 #endif
@@ -170,7 +170,7 @@ static void prefs_fonts_save(PrefsPage *_page)
        prefs_common.textfont   = g_strdup(gtk_font_button_get_font_name
                (GTK_FONT_BUTTON(fonts->entry_messageviewfont)));
 
-#ifdef USE_GNOMEPRINT
+#if defined(USE_GNOMEPRINT) || GTK_CHECK_VERSION(2,10,0)
        g_free(prefs_common.printfont);         
        prefs_common.printfont   = g_strdup(gtk_font_button_get_font_name
                (GTK_FONT_BUTTON(fonts->entry_messageprintfont)));
diff --git a/src/printing.c b/src/printing.c
new file mode 100644 (file)
index 0000000..c36ffed
--- /dev/null
@@ -0,0 +1,475 @@
+/* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2007 Holger Berndt <hb@claws-mail.org> 
+ * and the Claws Mail team
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "printing.h"
+
+#if GTK_CHECK_VERSION(2,10,0) && !defined(HAVE_GNOMEPRINT)
+
+#include "prefs_common.h"
+
+#include <glib/gi18n.h>
+#include <pango/pango.h>
+#include <string.h>
+
+typedef struct {
+  PangoLayout *layout;
+  PangoContext *pango_context;
+  char *text;
+  GList *page_breaks;
+  GtkTextBuffer *buffer;
+  gint sel_start;
+  gint sel_end;
+} PrintData;
+
+
+/* callbacks */
+static void cb_begin_print(GtkPrintOperation*, GtkPrintContext*, gpointer);
+static void cb_draw_page(GtkPrintOperation*, GtkPrintContext*, gint, gpointer);
+
+/* variables */
+static GtkPrintSettings *settings   = NULL;
+static GtkPageSetup     *page_setup = NULL;
+
+/* other static functions */
+static void     printing_layout_set_text_attributes(PrintData*);
+static gboolean printing_is_pango_gdk_color_equal(PangoColor*, GdkColor*); 
+static gint     printing_text_iter_get_offset_bytes(PrintData *, const GtkTextIter*);
+
+void printing_print(GtkTextView *text_view, GtkWindow *parent, gint sel_start, gint sel_end)
+{
+  GtkPrintOperation *op;
+  GtkPrintOperationResult res;
+  PrintData *print_data;
+  GtkTextIter start, end;
+  GtkTextBuffer *buffer;
+
+  op = gtk_print_operation_new();
+
+  print_data = g_new0(PrintData,1);
+
+  print_data->pango_context=gtk_widget_get_pango_context(GTK_WIDGET(text_view));
+
+  /* get text */
+  buffer = gtk_text_view_get_buffer(text_view);
+  print_data->buffer = buffer;
+  print_data->sel_start = sel_start;
+  print_data->sel_end = sel_end;
+  if (print_data->sel_start < 0 || print_data->sel_end <= print_data->sel_start) {
+    gtk_text_buffer_get_start_iter(buffer, &start);
+    gtk_text_buffer_get_end_iter(buffer, &end);
+  } else {
+    gtk_text_buffer_get_iter_at_offset(buffer, &start, print_data->sel_start);
+    gtk_text_buffer_get_iter_at_offset(buffer, &end, print_data->sel_end);
+  }
+
+  print_data->text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+
+  /* Config for printing */
+  if(settings != NULL)
+    gtk_print_operation_set_print_settings(op, settings);
+  if(page_setup != NULL)
+    gtk_print_operation_set_default_page_setup(op, page_setup);
+
+  /* signals */
+  g_signal_connect(op, "begin_print", G_CALLBACK(cb_begin_print), print_data);
+  g_signal_connect(op, "draw_page", G_CALLBACK(cb_draw_page), print_data);
+
+  /* Start printing process */
+  res = gtk_print_operation_run(op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+                               parent, NULL);
+
+  if(res == GTK_PRINT_OPERATION_RESULT_ERROR) {
+    GError *error = NULL;
+    gtk_print_operation_get_error(op, &error);
+    debug_print("Error printing message: %s",
+           error ? error->message : "no details");
+  }
+  else if(res == GTK_PRINT_OPERATION_RESULT_APPLY) {
+    /* store settings for next printing session */
+    if(settings != NULL)
+      g_object_unref(settings);
+    settings = g_object_ref(gtk_print_operation_get_print_settings(op));
+  }
+
+  if(print_data->text)
+    g_free(print_data->text);
+  g_list_free(print_data->page_breaks);
+  if(print_data->layout)
+    g_object_unref(print_data->layout);
+  g_free(print_data);
+
+  g_object_unref(op);
+  debug_print("printing_print finished\n");
+}
+
+void printing_page_setup(GtkWindow *parent)
+{
+  GtkPageSetup *new_page_setup;
+
+  if(settings == NULL)
+    settings = gtk_print_settings_new();
+
+  new_page_setup = gtk_print_run_page_setup_dialog(parent,page_setup,settings);
+
+  if(page_setup)
+    g_object_unref(page_setup);
+
+  page_setup = new_page_setup;
+}
+
+static void cb_begin_print(GtkPrintOperation *op, GtkPrintContext *context,
+                          gpointer user_data)
+{
+  double width, height;
+  int num_lines, line;
+  double page_height;
+  GList *page_breaks;
+  PrintData *print_data;
+  PangoLayoutLine *layout_line;
+  PangoFontDescription *desc;
+
+  debug_print("Preparing print job...\n");
+       
+  print_data = (PrintData*) user_data;
+  width  = gtk_print_context_get_width(context);
+  height = gtk_print_context_get_height(context);
+
+  print_data->layout = gtk_print_context_create_pango_layout(context);
+       
+  if(prefs_common.use_different_print_font)
+    desc = pango_font_description_from_string(prefs_common.printfont);
+  else
+    desc = pango_font_description_copy(
+               pango_context_get_font_description(print_data->pango_context));
+
+  pango_layout_set_font_description(print_data->layout, desc);
+  pango_font_description_free(desc);
+
+  pango_layout_set_width(print_data->layout, width * PANGO_SCALE);
+  pango_layout_set_text(print_data->layout, print_data->text, -1);
+
+  printing_layout_set_text_attributes(print_data);
+
+  num_lines = pango_layout_get_line_count(print_data->layout);
+
+  page_breaks = NULL;
+  page_height = 0;
+  for(line = 0; line < num_lines; line++) {
+    PangoRectangle ink_rect, logical_rect;
+    double line_height;
+
+#define PANGO_HAS_READONLY 0
+#if defined(PANGO_VERSION_CHECK)
+#if PANGO_VERSION_CHECK(1,16,0)
+#define PANGO_HAS_READONLY 1
+#endif
+#endif
+
+#if PANGO_HAS_READONLY
+    layout_line = pango_layout_get_line_readonly(print_data->layout, line);
+#else
+    layout_line = pango_layout_get_line(print_data->layout, line);
+#endif
+    pango_layout_line_get_extents(layout_line, &ink_rect, &logical_rect);
+
+    line_height = ((double)logical_rect.height) / PANGO_SCALE;
+
+    /* TODO: Check if there is a pixbuf in that line */
+    
+    if((page_height + line_height) > height) {
+      page_breaks = g_list_prepend(page_breaks, GINT_TO_POINTER(line));
+      page_height = 0;
+    }
+
+    page_height += line_height;
+  }
+
+  page_breaks = g_list_reverse(page_breaks);
+  gtk_print_operation_set_n_pages(op, g_list_length(page_breaks) + 1);
+       
+  print_data->page_breaks = page_breaks;
+
+  debug_print("Starting print job...\n");
+}
+
+static void cb_draw_page(GtkPrintOperation *op, GtkPrintContext *context,
+                        int page_nr, gpointer user_data)
+{
+  cairo_t *cr;
+  PrintData *print_data;
+  int start, end, ii;
+  GList *pagebreak;
+  PangoLayoutIter *iter;
+  double start_pos;
+       
+  print_data = (PrintData*) user_data;
+
+  if (page_nr == 0)
+    start = 0;
+  else {
+    pagebreak = g_list_nth(print_data->page_breaks, page_nr - 1);
+    start = GPOINTER_TO_INT(pagebreak->data);
+  }
+
+  pagebreak = g_list_nth(print_data->page_breaks, page_nr);
+  if(pagebreak == NULL)
+    end = pango_layout_get_line_count(print_data->layout);
+  else
+    end = GPOINTER_TO_INT(pagebreak->data);
+
+  cr = gtk_print_context_get_cairo_context(context);
+  cairo_set_source_rgb(cr, 0., 0., 0.);
+
+  ii = 0;
+  start_pos = 0.;
+  iter = pango_layout_get_iter(print_data->layout);
+  do {
+    PangoRectangle logical_rect;
+    PangoLayoutLine *line;
+    int baseline;
+
+    if(ii >= start) {
+      line = pango_layout_iter_get_line(iter);
+
+      pango_layout_iter_get_line_extents(iter, NULL, &logical_rect);
+      baseline = pango_layout_iter_get_baseline(iter);
+
+      if(ii == start)
+       start_pos = ((double)logical_rect.y) / PANGO_SCALE;
+      
+      cairo_move_to(cr,
+                   ((double)logical_rect.x) / PANGO_SCALE,
+                   ((double)baseline) / PANGO_SCALE - start_pos);
+      pango_cairo_show_layout_line(cr, line);
+    }
+    ii++;
+  } while(ii < end && pango_layout_iter_next_line(iter));
+
+  pango_layout_iter_free(iter);
+       
+  debug_print("Sent page %d to printer\n", page_nr+1);
+}
+
+static void printing_layout_set_text_attributes(PrintData *print_data)
+{
+  GtkTextIter iter;
+  PangoAttrList *attr_list;
+  PangoAttribute *attr;
+  GSList *open_attrs, *attr_walk;
+
+  attr_list = pango_attr_list_new();
+  if (print_data->sel_start < 0 || print_data->sel_end <= print_data->sel_start) {
+    gtk_text_buffer_get_start_iter(print_data->buffer, &iter);
+  } else {
+    gtk_text_buffer_get_iter_at_offset(print_data->buffer, &iter, print_data->sel_start);
+  }
+
+  open_attrs = NULL;
+  do {
+    gboolean fg_set, bg_set, under_set, strike_set;
+    GSList *tags, *tag_walk;
+    GtkTextTag *tag;
+    GdkColor *color;
+    PangoUnderline underline;
+    gboolean strikethrough;
+
+    if(gtk_text_iter_ends_tag(&iter, NULL)) {
+      PangoAttrColor *attr_color;
+      PangoAttrInt   *attr_int;
+
+      tags = gtk_text_iter_get_toggled_tags(&iter, FALSE);
+      for(tag_walk = tags; tag_walk != NULL; tag_walk = tag_walk->next) {
+       gboolean found;
+
+       tag = GTK_TEXT_TAG(tag_walk->data);
+       g_object_get(G_OBJECT(tag),
+                    "background-set", &bg_set,
+                    "foreground-set", &fg_set,
+                    "underline-set",&under_set,
+                    "strikethrough-set", &strike_set,
+                    NULL);
+
+       if(fg_set) {
+         found = FALSE;
+         for(attr_walk = open_attrs; attr_walk != NULL; attr_walk = attr_walk->next) {
+           attr = (PangoAttribute*)attr_walk->data;
+           if(attr->klass->type == PANGO_ATTR_FOREGROUND) {
+             attr_color = (PangoAttrColor*) attr;
+             g_object_get(G_OBJECT(tag), "foreground_gdk", &color, NULL);
+             if(printing_is_pango_gdk_color_equal(&(attr_color->color), color)) {
+               attr->end_index = printing_text_iter_get_offset_bytes(print_data, &iter);
+               pango_attr_list_insert(attr_list, attr);
+               found = TRUE;
+               open_attrs = g_slist_delete_link(open_attrs, attr_walk);
+               break;
+             }
+           }
+         }
+         if(!found)
+           debug_print("Error generating attribute list.\n");
+       }
+
+       if(bg_set) {
+         found = FALSE;
+         for(attr_walk = open_attrs; attr_walk != NULL; attr_walk = attr_walk->next) {
+           attr = (PangoAttribute*)attr_walk->data;
+           if(attr->klass->type == PANGO_ATTR_BACKGROUND) {
+             attr_color = (PangoAttrColor*) attr;
+             g_object_get(G_OBJECT(tag), "background-gdk", &color, NULL);
+             if(printing_is_pango_gdk_color_equal(&(attr_color->color), color)) {
+               attr->end_index = printing_text_iter_get_offset_bytes(print_data, &iter);
+               pango_attr_list_insert(attr_list, attr);
+               found = TRUE;
+               open_attrs = g_slist_delete_link(open_attrs, attr_walk);
+               break;
+             }
+           }
+         }
+         if(!found)
+           debug_print("Error generating attribute list.\n");
+       }
+
+       if(under_set) {
+         found = FALSE;
+         for(attr_walk = open_attrs; attr_walk != NULL; attr_walk = attr_walk->next) {
+           attr = (PangoAttribute*)attr_walk->data;
+           if(attr->klass->type == PANGO_ATTR_UNDERLINE) {
+             attr_int = (PangoAttrInt*)attr;
+             g_object_get(G_OBJECT(tag), "underline", &underline, NULL);
+             if(attr_int->value == underline) {
+               attr->end_index = printing_text_iter_get_offset_bytes(print_data, &iter);
+               pango_attr_list_insert(attr_list, attr);
+               found = TRUE;
+               open_attrs = g_slist_delete_link(open_attrs, attr_walk);
+               break;
+             }
+           }
+         }
+         if(!found)
+           debug_print("Error generating attribute list.\n");
+       }
+
+       if(strike_set) {
+         found = FALSE;
+         for(attr_walk = open_attrs; attr_walk != NULL; attr_walk = attr_walk->next) {
+           attr = (PangoAttribute*)attr_walk->data;
+           if(attr->klass->type == PANGO_ATTR_STRIKETHROUGH) {
+             attr_int = (PangoAttrInt*)attr;
+             g_object_get(G_OBJECT(tag), "strikethrough", &strikethrough, NULL);
+             if(attr_int->value == strikethrough) {
+               attr->end_index = printing_text_iter_get_offset_bytes(print_data, &iter);
+               pango_attr_list_insert(attr_list, attr);
+               found = TRUE;
+               open_attrs = g_slist_delete_link(open_attrs, attr_walk);
+               break;
+             }
+           }
+         }
+         if(!found)
+           debug_print("Error generating attribute list.\n");
+       }
+
+      }
+      g_slist_free(tags);
+    }
+
+    if(gtk_text_iter_begins_tag(&iter, NULL)) {
+      tags = gtk_text_iter_get_toggled_tags(&iter, TRUE);
+      for(tag_walk = tags; tag_walk != NULL; tag_walk = tag_walk->next) {
+       tag = GTK_TEXT_TAG(tag_walk->data);
+       g_object_get(G_OBJECT(tag),
+                    "background-set", &bg_set,
+                    "foreground-set", &fg_set,
+                    "underline-set", &under_set,
+                    "strikethrough-set", &strike_set,
+                    NULL);
+       if(fg_set) {
+         g_object_get(G_OBJECT(tag), "foreground-gdk", &color, NULL);
+         attr = pango_attr_foreground_new(color->red,color->green,color->blue);
+         attr->start_index = printing_text_iter_get_offset_bytes(print_data, &iter);
+         open_attrs = g_slist_prepend(open_attrs, attr);
+       }
+       if(bg_set) {
+         g_object_get(G_OBJECT(tag), "background-gdk", &color, NULL);
+         attr = pango_attr_background_new(color->red,color->green,color->blue);
+         attr->start_index = printing_text_iter_get_offset_bytes(print_data, &iter);
+         open_attrs = g_slist_prepend(open_attrs, attr);
+       }
+       if(under_set) {
+         g_object_get(G_OBJECT(tag), "underline", &underline, NULL);
+         attr = pango_attr_underline_new(underline);
+         attr->start_index = printing_text_iter_get_offset_bytes(print_data, &iter);
+         open_attrs = g_slist_prepend(open_attrs, attr);         
+       }
+       if(strike_set) {
+         g_object_get(G_OBJECT(tag), "strikethrough", &strikethrough, NULL);
+         attr = pango_attr_strikethrough_new(strikethrough);
+         attr->start_index = printing_text_iter_get_offset_bytes(print_data, &iter);
+         open_attrs = g_slist_prepend(open_attrs, attr);         
+       }
+      }
+      g_slist_free(tags);
+    }
+    
+  } while(!gtk_text_iter_is_end(&iter) && gtk_text_iter_forward_to_tag_toggle(&iter, NULL));
+         
+  /* close all open attributes */
+  for(attr_walk = open_attrs; attr_walk != NULL; attr_walk = attr_walk->next) {
+    attr = (PangoAttribute*) attr_walk->data;
+    attr->end_index = printing_text_iter_get_offset_bytes(print_data, &iter);
+    pango_attr_list_insert(attr_list, attr);
+  }
+  g_slist_free(open_attrs);
+
+  pango_layout_set_attributes(print_data->layout, attr_list);
+  pango_attr_list_unref(attr_list);
+}
+
+static gboolean printing_is_pango_gdk_color_equal(PangoColor *p, GdkColor *g)
+{
+  return ((p->red == g->red) && (p->green == g->green) && (p->blue == g->blue));
+}
+
+/* Pango has it's attribute in bytes, but GtkTextIter gets only an offset
+ * in characters, so here we're returning an offset in bytes. 
+ */
+static gint printing_text_iter_get_offset_bytes(PrintData *print_data, const GtkTextIter *iter)
+{
+  gint off_chars;
+  gint off_bytes;
+  gchar *text;
+  GtkTextIter start;
+
+  off_chars = gtk_text_iter_get_offset(iter);
+  if (print_data->sel_start < 0 || print_data->sel_end <= print_data->sel_start) {
+    gtk_text_buffer_get_start_iter(gtk_text_iter_get_buffer(iter), &start);
+  } else {
+    gtk_text_buffer_get_iter_at_offset(gtk_text_iter_get_buffer(iter), &start, print_data->sel_start);
+  }
+  text = gtk_text_iter_get_slice(&start, iter);
+  off_bytes = strlen(text);
+  g_free(text);
+  return off_bytes;
+}
+
+#endif /* GTK+ >= 2.10.0 */
diff --git a/src/printing.h b/src/printing.h
new file mode 100644 (file)
index 0000000..d65bbd8
--- /dev/null
@@ -0,0 +1,36 @@
+/* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2007 Holger Berndt <hb@claws-mail.org> 
+ * and the Claws Mail team
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ * 
+ */
+
+#ifndef __PRINTING_H__
+#define __PRINTING_H__
+
+#include <gtk/gtk.h>
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#if GTK_CHECK_VERSION(2,10,0) && !defined(HAVE_GNOMEPRINT)
+
+void printing_print(GtkTextView*, GtkWindow*, gint, gint);
+void printing_page_setup(GtkWindow*);
+
+#endif /* GTK+ >= 2.10.0 */
+
+#endif /* __PRINTING_H__ */
index fb3ba1dcb062725b323b7cab951e173187aa5695..39a1ec205de3785ad993c9f36db7e0bc49d4a3aa 100644 (file)
@@ -4449,7 +4449,7 @@ void summary_save_as(SummaryView *summaryview)
 void summary_print(SummaryView *summaryview)
 {
        GtkCList *clist = GTK_CLIST(summaryview->ctree);
-#ifndef USE_GNOMEPRINT
+#if !defined(USE_GNOMEPRINT) && !GTK_CHECK_VERSION(2,10,0)
        GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
        MsgInfo *msginfo;
        gchar *cmdline = NULL;
@@ -4469,7 +4469,7 @@ void summary_print(SummaryView *summaryview)
        g_free(msg);
 
        if (clist->selection == NULL) return;
-#ifndef USE_GNOMEPRINT
+#if !defined(USE_GNOMEPRINT) && !GTK_CHECK_VERSION(2,10,0)
        cmdline = input_dialog(_("Print"),
                               _("Enter the print command line:\n"
                                 "('%s' will be replaced with file name)"),