tomboy r2147 - in trunk: . Tomboy/Addins/PrintNotes po



Author: sharm
Date: Mon Sep 15 16:03:01 2008
New Revision: 2147
URL: http://svn.gnome.org/viewvc/tomboy?rev=2147&view=rev

Log:
* configure.in, po/POTFILES.in, Tomboy/Addins/PrintNotes/COPYING,
  Tomboy/Addins/PrintNotes/gedit-print.c,
  Tomboy/Addins/PrintNotes/gedit-print.h,
  Tomboy/Addins/PrintNotes/gtksourceprintjob.c,
  Tomboy/Addins/PrintNotes/gtksourceprintjob.h,
  Tomboy/Addins/PrintNotes/Makefile.am,
  Tomboy/Addins/PrintNotes/PrintNotes.addin.xml,
  Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs: Revert to old
  (pre-0.11.x) printing add-in, as the Gtk.Print port is not ready
  for release.

Added:
   trunk/Tomboy/Addins/PrintNotes/COPYING
   trunk/Tomboy/Addins/PrintNotes/gedit-print.c   (contents, props changed)
   trunk/Tomboy/Addins/PrintNotes/gedit-print.h   (contents, props changed)
   trunk/Tomboy/Addins/PrintNotes/gtksourceprintjob.c   (contents, props changed)
   trunk/Tomboy/Addins/PrintNotes/gtksourceprintjob.h   (contents, props changed)
Modified:
   trunk/ChangeLog
   trunk/Tomboy/Addins/PrintNotes/Makefile.am
   trunk/Tomboy/Addins/PrintNotes/PrintNotes.addin.xml
   trunk/Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs
   trunk/configure.in
   trunk/po/ChangeLog
   trunk/po/POTFILES.in

Added: trunk/Tomboy/Addins/PrintNotes/COPYING
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/PrintNotes/COPYING	Mon Sep 15 16:03:01 2008
@@ -0,0 +1,344 @@
+The tomboy package is distributed under the LGPL with exception of
+the Printing Support (PrintNotes) Addin.  The PrintNotes Addin is
+distributed under the GPL, which is shown below.
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

Modified: trunk/Tomboy/Addins/PrintNotes/Makefile.am
==============================================================================
--- trunk/Tomboy/Addins/PrintNotes/Makefile.am	(original)
+++ trunk/Tomboy/Addins/PrintNotes/Makefile.am	Mon Sep 15 16:03:01 2008
@@ -9,8 +9,7 @@
 	$(LINK_TOMBOY_EXE)			\
 	$(TOMBOY_LIBS) 				\
 	$(LINK_MONO_ADDINS)			\
-	-r:Mono.Posix				\
-	-r:Mono.Cairo
+	-r:Mono.Posix
 
 ADDIN_NAME = PrintNotes
 TARGET = $(ADDIN_NAME).dll
@@ -19,24 +18,46 @@
 RESOURCES = \
 	-resource:$(srcdir)/$(ADDIN_NAME).addin.xml
 
-$(TARGET).mdb: $(TARGET)
-
 $(TARGET): $(CSFILES) $(top_builddir)/Tomboy/Tomboy.exe
 	$(CSC) -out:$@ $(CSFLAGS) $(ASSEMBLIES) $(CSFILES) $(RESOURCES)
 
 
 addinsdir = $(pkglibdir)/addins
 addins_DATA = 			\
-	$(TARGET)		\
-	$(TARGET).mdb
+	$(TARGET)
 
 EXTRA_DIST =            	\
 	$(CSFILES) \
-	$(srcdir)/$(ADDIN_NAME).addin.xml
+	$(srcdir)/$(ADDIN_NAME).addin.xml \
+	COPYING
 
 CLEANFILES =				\
 	$(TARGET).mdb \
 	$(TARGET)
 
+##
+## Build libprintnotes for gedit print capability
+##
+
+INCLUDES =								\
+	-I$(top_srcdir)						\
+	-DG_LOG_DOMAIN=\"libprintnotes\"	\
+	-DGTK_DISABLE_DEPRECATED			\
+	-DGDK_DISABLE_DEPRECATED			\
+	-DG_DISABLE_DEPRECATED				\
+	$(LIBTOMBOY_CFLAGS)
+
+printnoteslibdir = $(pkglibdir)
+printnoteslib_LTLIBRARIES = libprintnotes.la
+
+libprintnotes_la_SOURCES =				\
+	gedit-print.h						\
+	gedit-print.c						\
+	gtksourceprintjob.h					\
+	gtksourceprintjob.c
+
+libprintnotes_la_LDFLAGS = -export-dynamic -module -avoid-version
+libprintnotes_la_LIBADD = $(LIBTOMBOY_LIBS)
+
 maintainer-clean-local:
 	rm -f Makefile.in

Modified: trunk/Tomboy/Addins/PrintNotes/PrintNotes.addin.xml
==============================================================================
--- trunk/Tomboy/Addins/PrintNotes/PrintNotes.addin.xml	(original)
+++ trunk/Tomboy/Addins/PrintNotes/PrintNotes.addin.xml	Mon Sep 15 16:03:01 2008
@@ -5,7 +5,7 @@
 	description="Allows you to print a note."
 	category="Desktop Integration"
 	defaultEnabled="true"
-	version="0.2">
+	version="0.1">
 
 	<Runtime>
 		<Import assembly="PrintNotes.dll" />

Modified: trunk/Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs
==============================================================================
--- trunk/Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs	(original)
+++ trunk/Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs	Mon Sep 15 16:03:01 2008
@@ -1,27 +1,22 @@
 
 using System;
-using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using Mono.Unix;
 
 using Gtk;
 
 using Tomboy;
- 
+
 namespace Tomboy.PrintNotes
 {
 	public class PrintNotesNoteAddin : NoteAddin
 	{
-		private Gtk.ImageMenuItem item;
-		private int font_size = 12;			
-		private List<int> pageBreaks;
-		private Pango.Layout layout;
-	
+		Gtk.ImageMenuItem item;
+
 		public override void Initialize ()
 		{
 			item = new Gtk.ImageMenuItem (Catalog.GetString ("Print"));
-			item.Image = new Gtk.Image (Gtk.Stock.Print,
-			                            Gtk.IconSize.Menu);
+			item.Image = new Gtk.Image (Gtk.Stock.Print, Gtk.IconSize.Menu);
 			item.Activated += PrintButtonClicked;
 			item.Show ();
 			AddPluginMenuItem (item);
@@ -38,122 +33,17 @@
 		{
 			// Do nothing.
 		}
-		
-		private void PrintButtonClicked (object sender, EventArgs args)
-		{
-			Gtk.PrintOperation op = new PrintOperation ();
-			op.BeginPrint += OnBeginPrint;
-			op.DrawPage += OnDrawPage;
-			op.EndPrint += OnEndPrint;
-			
-			op.Run (Gtk.PrintOperationAction.PrintDialog, this.Window);
-		}
-		
-		private void OnBeginPrint (object sender, Gtk.BeginPrintArgs args)
-		{
-			PrintContext context = args.Context;
-			double height = context.Height;
-			
-			layout = context.CreatePangoLayout ();
-			
-			Pango.FontDescription desc =
-				Pango.FontDescription.FromString ("sans " +
-				                                  font_size);
-			layout.FontDescription = desc;
-			
-			layout.Width = Pango.Units.FromPixels ((int)context.Width);
-			
-			Gtk.TextIter start_iter, end_iter;
-			Buffer.GetBounds (out start_iter, out end_iter);
-			layout.SetText (
-				Buffer.GetText (start_iter, end_iter, false));
-			
-			int numLines = layout.LineCount;
-			
-			pageBreaks = new List<int> ();
-			double pageHeight = 0;
-			
-			for (int i = 0; i < numLines; i++) {
-				Pango.Rectangle inkRect =
-					new Pango.Rectangle ();
-				Pango.Rectangle logicalRect =
-					new Pango.Rectangle ();
-				
-				Pango.LayoutLine layoutLine =
-					layout.GetLine (i);
-				layoutLine.GetExtents (ref inkRect,
-				                       ref logicalRect);
-				
-				double lineHeight = logicalRect.Height / 1024.0;
-				
-				if (pageHeight + lineHeight > height) {
-					pageBreaks.Add (i);
-					pageHeight = 0;
-				}
-				
-				pageHeight += lineHeight;
-			}
-			
-			PrintOperation op = (PrintOperation) sender;
-			op.NPages = pageBreaks.Count + 1;
-		}
-		
-		public void OnDrawPage (object sender, Gtk.DrawPageArgs args)
-		{
-			Cairo.Context cr = args.Context.CairoContext;
-			
-			int start, end, i;
-			
-			if (args.PageNr == 0)
-				start = 0;
-			else
-				start = pageBreaks [args.PageNr - 1];
-			
-			if (pageBreaks.Count <= args.PageNr)
-				end = layout.LineCount;
-			else
-				end = pageBreaks [args.PageNr];
-			
-			i = 0;
-			Pango.LayoutIter iter = layout.Iter;
-			do {
-				if (i >= start) {
-					Pango.LayoutLine line = iter.Line;
-					Pango.Rectangle logicalRect =
-						new Pango.Rectangle ();
-					Pango.Rectangle dummyRect =
-						new Pango.Rectangle ();
-
-					line.GetExtents (ref dummyRect, 
-					                 ref logicalRect);
-					
-					if (i == start) {
-						cr.MoveTo (0, 0);
-					}
-					
-					Pango.CairoHelper.ShowLayoutLine (cr, line);
-					
-					int height, width;
-					layout.GetSize (out width, out height);
-					cr.RelMoveTo (0, (int)
-					              (logicalRect.Height /
-					               Pango.Scale.PangoScale));
-				}
-				
-				i++;
-			}			
-			while (i < end && iter.NextLine ());
-		}
-		
-		private void OnEndPrint (object sender, Gtk.EndPrintArgs args)
+
+		[DllImport("libprintnotes")]
+		static extern void gedit_print (IntPtr text_view_handle);
+
+		//
+		// Handle Print menu item Click
+		//
+
+		void PrintButtonClicked (object sender, EventArgs args)
 		{
-			layout = null;
-			pageBreaks.Clear ();
-			
-			// TODO: How to fix this error when quitting?
-			// "Cairo.Context: called from finalization thread
-			// programmer is missing a call to Dispose"
-			// May be a cairo/pango/gtk-sharp problem?
+			gedit_print (Note.Window.Editor.Handle);
 		}
 	}
 }

Added: trunk/Tomboy/Addins/PrintNotes/gedit-print.c
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/PrintNotes/gedit-print.c	Mon Sep 15 16:03:01 2008
@@ -0,0 +1,466 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gedit-print.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
+ * Copyright (C) 2002  Paolo Maggi  
+ *
+ * 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. 
+ */
+ 
+/*
+ * Modified by the gedit Team, 1998-2002. See the AUTHORS file for a 
+ * list of people on the gedit Team.  
+ * See the ChangeLog files for a list of changes. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>	/* For strlen */
+
+#include <glib/gi18n.h>
+#include <gtk/gtkframe.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkprogressbar.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkwindow.h>
+#include <libgnomeprintui/gnome-print-dialog.h>
+#include <libgnomeprintui/gnome-print-job-preview.h>
+
+#include "gedit-print.h"
+#include "gtksourceprintjob.h"
+
+#ifdef DEBUG
+#  define DEBUG_PRINT "DEBUG_PRINT: %s"
+#  define gedit_debug(x, y) g_warning(x, y)
+#else
+#  define gedit_debug(x, y) do {} while (FALSE);
+#endif
+
+enum
+{
+	PREVIEW_NO,
+	PREVIEW,
+	PREVIEW_FROM_DIALOG
+};
+
+typedef struct _GeditPrintJobInfo	GeditPrintJobInfo;
+
+struct _GeditPrintJobInfo 
+{
+	GtkTextBuffer     *doc;
+	
+	GtkSourcePrintJob *pjob;
+		
+	gint               preview;
+
+	gint               range_type;
+
+	gint               first_line_to_print;
+	gint               last_line_to_print;
+
+	/* Popup dialog */
+	GtkWidget	  *dialog;
+	GtkWidget         *label;
+	GtkWidget         *progressbar;
+
+	GtkWindow	  *parent;
+};
+
+static GeditPrintJobInfo* gedit_print_job_info_new 	(GtkTextView       *view);
+static void gedit_print_job_info_destroy		(GeditPrintJobInfo *pji, 
+							 gboolean           save_config);
+static void gedit_print_real 				(GeditPrintJobInfo *pji, 
+							 GtkTextIter       *start, 
+							 GtkTextIter       *end, 
+							 GtkWindow         *parent);
+static void gedit_print_preview_real 			(GeditPrintJobInfo *pji, 
+							 GtkTextIter       *start, 
+							 GtkTextIter       *end, 
+							 GtkWindow         *parent);
+
+
+static void
+gedit_print_job_info_destroy (GeditPrintJobInfo *pji, gboolean save_config)
+{
+	gedit_debug (DEBUG_PRINT, "");
+
+	g_return_if_fail (pji != NULL);
+
+	if (pji->pjob != NULL)
+		g_object_unref (pji->pjob);
+
+	g_free (pji);
+}
+
+static GtkWidget *
+get_print_dialog (GeditPrintJobInfo *pji, GtkWindow *parent)
+{
+	GtkWidget *dialog;
+	gint selection_flag;
+	gint lines;
+	GnomePrintConfig *config;
+
+	gedit_debug (DEBUG_PRINT, "");
+
+	g_return_val_if_fail (pji != NULL, NULL);
+	
+	if (!gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (pji->doc), NULL, NULL))
+		selection_flag = GNOME_PRINT_RANGE_SELECTION_UNSENSITIVE;
+	else
+		selection_flag = GNOME_PRINT_RANGE_SELECTION;
+	
+	g_return_val_if_fail(pji->pjob != NULL, NULL);
+	config = gtk_source_print_job_get_config (pji->pjob);
+	
+	dialog = g_object_new (GNOME_TYPE_PRINT_DIALOG, "print_config", config, NULL);
+	
+	gnome_print_dialog_construct (GNOME_PRINT_DIALOG (dialog), 
+				      (guchar *) _("Print"),
+			              GNOME_PRINT_DIALOG_RANGE | GNOME_PRINT_DIALOG_COPIES);
+
+	lines = gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (pji->doc));
+
+	gnome_print_dialog_construct_range_any ( GNOME_PRINT_DIALOG (dialog),
+						 (GNOME_PRINT_RANGE_ALL | selection_flag), 
+						 NULL, NULL, NULL);
+
+	gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+
+	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); 
+	gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+
+	return dialog;
+}
+
+static void
+gedit_print_dialog_response (GtkWidget *dialog, int response, GeditPrintJobInfo *pji)
+{
+	GtkTextIter start, end;
+
+	pji->range_type = gnome_print_dialog_get_range (GNOME_PRINT_DIALOG (dialog));
+	gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (pji->doc), &start, &end);
+
+	switch (pji->range_type)
+	{
+	case GNOME_PRINT_RANGE_ALL:
+		break;
+
+	case GNOME_PRINT_RANGE_SELECTION:
+		gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (pji->doc),
+						      &start, &end);
+		break;
+
+	default:
+		g_return_if_reached ();
+	}
+
+	switch (response)
+	{
+	case GNOME_PRINT_DIALOG_RESPONSE_PRINT:
+		gedit_debug (DEBUG_PRINT, "Print button pressed.");
+		pji->preview = PREVIEW_NO;
+		gedit_print_real (pji, &start, &end, 
+				  gtk_window_get_transient_for (GTK_WINDOW (dialog)));
+		gtk_widget_destroy (dialog);
+		break;
+
+	case GNOME_PRINT_DIALOG_RESPONSE_PREVIEW:
+		gedit_debug (DEBUG_PRINT, "Preview button pressed.");
+		pji->preview = PREVIEW_FROM_DIALOG;
+		gedit_print_preview_real (pji, &start, &end, GTK_WINDOW (dialog));
+		break;
+
+	default:
+		gtk_widget_destroy (dialog);
+		gedit_print_job_info_destroy (pji, FALSE);
+        }
+} 
+
+static void
+show_printing_dialog (GeditPrintJobInfo *pji, GtkWindow *parent)
+{
+	GtkWidget *window;
+	GtkWidget *frame;
+	GtkWidget *hbox;
+	GtkWidget *image;
+	GtkWidget *vbox;
+	GtkWidget *label;
+	GtkWidget *progressbar;
+
+	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_modal (GTK_WINDOW (window), TRUE);
+	gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
+	gtk_window_set_destroy_with_parent (GTK_WINDOW (window), TRUE);
+	gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER_ON_PARENT);
+		
+	gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
+	gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE);
+	gtk_window_set_skip_pager_hint (GTK_WINDOW (window), TRUE);
+ 
+	gtk_window_set_transient_for (GTK_WINDOW (window), parent);
+
+	frame = gtk_frame_new (NULL);
+	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
+	gtk_container_add (GTK_CONTAINER (window), frame);
+
+	hbox = gtk_hbox_new (FALSE, 12);
+ 	gtk_container_add (GTK_CONTAINER (frame), hbox);
+	gtk_container_set_border_width (GTK_CONTAINER (hbox), 12);
+
+	image = gtk_image_new_from_stock ("gtk-print", GTK_ICON_SIZE_DIALOG);
+	gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+
+	vbox = gtk_vbox_new (FALSE, 12);
+	gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
+
+	label = gtk_label_new (_("Preparing pages..."));
+	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+	gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+	progressbar = gtk_progress_bar_new ();
+	gtk_box_pack_start (GTK_BOX (vbox), progressbar, FALSE, FALSE, 0);
+	
+	pji->dialog = window;
+	pji->label = label;
+	pji->progressbar = progressbar;
+	
+	gtk_widget_show_all (pji->dialog);
+
+	/* Update UI */
+	while (gtk_events_pending ())
+		gtk_main_iteration ();
+}
+
+static void
+page_cb (GtkSourcePrintJob *job, GeditPrintJobInfo *pji)
+{
+	gchar *str;
+	gint page_num = gtk_source_print_job_get_page (pji->pjob);
+	gint total = gtk_source_print_job_get_page_count (pji->pjob);
+
+	if (pji->preview != PREVIEW_NO)
+		str = g_strdup_printf (_("Rendering page %d of %d..."), page_num, total);
+	else
+		str = g_strdup_printf (_("Printing page %d of %d..."), page_num, total);
+
+	gtk_label_set_label (GTK_LABEL (pji->label), str);
+	g_free (str);
+
+	gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pji->progressbar), 
+				       1.0 * page_num / total);
+
+	/* Update UI */
+	while (gtk_events_pending ())
+		gtk_main_iteration ();
+
+}
+
+static void
+preview_finished_cb (GtkSourcePrintJob *job, GeditPrintJobInfo *pji)
+{
+	GnomePrintJob *gjob;
+	GtkWidget *preview = NULL;
+
+	gjob = gtk_source_print_job_get_print_job (job);
+
+	preview = gnome_print_job_preview_new (gjob, (guchar *) _("Print preview"));
+	if (pji->parent != NULL)
+	{
+		gtk_window_set_transient_for (GTK_WINDOW (preview), pji->parent);
+		gtk_window_set_modal (GTK_WINDOW (preview), TRUE);
+	}
+	
+ 	g_object_unref (gjob);
+
+	gtk_widget_destroy (pji->dialog);
+
+	if (pji->preview == PREVIEW)
+		gedit_print_job_info_destroy (pji, FALSE);
+	else
+	{
+		g_signal_handlers_disconnect_by_func (pji->pjob, (GCallback) page_cb, pji);
+		g_signal_handlers_disconnect_by_func (pji->pjob, (GCallback) preview_finished_cb, pji);
+	}
+	
+	gtk_widget_show (preview);
+}
+
+static void
+print_finished_cb (GtkSourcePrintJob *job, GeditPrintJobInfo *pji)
+{
+	GnomePrintJob *gjob;
+
+	gjob = gtk_source_print_job_get_print_job (job);
+
+	gnome_print_job_print (gjob);
+	
+ 	g_object_unref (gjob);
+
+	gtk_widget_destroy (pji->dialog);
+
+	gedit_print_job_info_destroy (pji, TRUE);
+}
+
+void 
+gedit_print (GtkTextView *view)
+{
+	GeditPrintJobInfo *pji;
+	GtkWidget *dialog;
+
+	gedit_debug (DEBUG_PRINT, "");
+
+	g_return_if_fail (view != NULL);
+
+	pji = gedit_print_job_info_new (view);
+	pji->preview = PREVIEW_NO;
+
+	dialog = get_print_dialog (pji, GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))));
+	
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (gedit_print_dialog_response),
+			  pji);
+
+	gtk_widget_show (dialog);
+}
+
+static void 
+gedit_print_preview_real (GeditPrintJobInfo *pji, 
+			  GtkTextIter       *start, 
+			  GtkTextIter       *end, 
+			  GtkWindow         *parent)
+{
+	show_printing_dialog (pji, parent);
+
+	pji->parent = parent;
+
+	g_signal_connect (pji->pjob, "begin_page", (GCallback) page_cb, pji);
+	g_signal_connect (pji->pjob, "finished", (GCallback) preview_finished_cb, pji);
+
+	if (!gtk_source_print_job_print_range_async (pji->pjob, start, end))
+	{
+		/* FIXME */
+		g_warning ("Async print failed");
+		gtk_widget_destroy (pji->dialog);
+	}
+}
+
+static void 
+gedit_print_real (GeditPrintJobInfo *pji, 
+		  GtkTextIter       *start, 
+		  GtkTextIter       *end, 
+		  GtkWindow         *parent)
+{
+	show_printing_dialog (pji, parent);
+
+	g_signal_connect (pji->pjob, "begin_page", (GCallback) page_cb, pji);
+	g_signal_connect (pji->pjob, "finished", (GCallback) print_finished_cb, pji);
+
+	if (!gtk_source_print_job_print_range_async (pji->pjob, start, end))
+	{
+		/* FIXME */
+		g_warning ("Async print failed");
+		gtk_widget_destroy (pji->dialog);
+	}
+}
+
+void 
+gedit_print_preview (GtkTextView *view)
+{
+	GeditPrintJobInfo *pji;
+	GtkTextIter start, end;
+
+	gedit_debug (DEBUG_PRINT, "");
+		
+	g_return_if_fail (view != NULL);
+
+	pji = gedit_print_job_info_new (view);
+
+	gtk_text_buffer_get_bounds (pji->doc, &start, &end);
+
+	pji->preview = PREVIEW;
+	gedit_print_preview_real (pji, &start, &end, 
+				  GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))));
+}
+
+static GeditPrintJobInfo *
+gedit_print_job_info_new (GtkTextView* view)
+{	
+	GtkSourcePrintJob *pjob;
+	GnomePrintConfig *config;
+	GeditPrintJobInfo *pji;
+	PangoContext *pango_context;
+	PangoFontDescription *font_desc;
+	GtkTextBuffer *buffer;
+	
+	gedit_debug (DEBUG_PRINT, "");
+	
+	g_return_val_if_fail (view != NULL, NULL);
+
+	buffer = gtk_text_view_get_buffer (view);
+	g_return_val_if_fail (buffer != NULL, NULL);
+
+	config = gnome_print_config_default ();
+	g_return_val_if_fail (config != NULL, NULL);
+
+	gnome_print_config_set_int (config, (const guchar *) GNOME_PRINT_KEY_NUM_COPIES, 1);
+	gnome_print_config_set_boolean (config, (const guchar *) GNOME_PRINT_KEY_COLLATE, FALSE);
+
+	pjob = gtk_source_print_job_new_with_buffer (config, buffer);
+	gnome_print_config_unref (config);
+
+	gtk_source_print_job_set_highlight (pjob, TRUE);
+	gtk_source_print_job_set_print_numbers (pjob, FALSE);
+	gtk_source_print_job_set_wrap_mode (pjob, gtk_text_view_get_wrap_mode (view));
+	gtk_source_print_job_set_tabs_width (pjob, 8);
+	
+	gtk_source_print_job_set_footer_format (pjob,
+						_("Page %N of %Q"), 
+						NULL, 
+						/* xgettext:no-c-format */
+						_("%A %x, %X"), 
+						TRUE);
+
+	gtk_source_print_job_set_print_header (pjob, FALSE);
+	gtk_source_print_job_set_print_footer (pjob, TRUE);
+
+	pango_context = gtk_widget_get_pango_context (GTK_WIDGET (view));
+	font_desc = pango_context_get_font_description (pango_context);
+
+	gtk_source_print_job_set_font_desc (pjob, font_desc);
+
+	pji = g_new0 (GeditPrintJobInfo, 1);
+
+	pji->pjob = pjob;
+
+	pji->doc = buffer;
+	pji->preview = PREVIEW_NO;
+	pji->range_type = GNOME_PRINT_RANGE_ALL;
+
+	return pji;
+}
+

Added: trunk/Tomboy/Addins/PrintNotes/gedit-print.h
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/PrintNotes/gedit-print.h	Mon Sep 15 16:03:01 2008
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * gedit-print.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi 
+ *
+ * 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. 
+ */
+ 
+/*
+ * Modified by the gedit Team, 1998-2001. See the AUTHORS file for a 
+ * list of people on the gedit Team.  
+ * See the ChangeLog files for a list of changes. 
+ */
+
+#ifndef __GEDIT_PRINT_H__
+#define __GEDIT_PRINT_H__
+
+#include <gtk/gtktextview.h>
+
+void gedit_print 		(GtkTextView* view);
+void gedit_print_preview	(GtkTextView* view);
+
+#endif /* __GEDIT_PRINT_H__ */

Added: trunk/Tomboy/Addins/PrintNotes/gtksourceprintjob.c
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/PrintNotes/gtksourceprintjob.c	Mon Sep 15 16:03:01 2008
@@ -0,0 +1,3144 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
+/*
+ * gtksourceprintjob.c
+ * This file is part of GtkSourceView
+ *
+ * Derived from gedit-print.c
+ *
+ * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
+ * Copyright (C) 2002  Paolo Maggi  
+ * Copyright (C) 2003  Gustavo GirÃldez
+ * Copyright (C) 2004  Red Hat, Inc.
+ *
+ * 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. 
+ */
+ 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <time.h>
+
+#include "gtksourceprintjob.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtktextview.h>
+#include <libgnomeprint/gnome-print-pango.h>
+
+#ifdef ENABLE_PROFILE
+#define PROFILE(x) x
+#else
+#define PROFILE(x)
+#endif
+
+#ifdef ENABLE_DEBUG
+#define DEBUG(x) x
+#else
+#define DEBUG(x)
+#endif
+
+
+#define DEFAULT_FONT_NAME   "Monospace 10"
+#define DEFAULT_COLOR       0x000000ff
+
+#define CM(v) ((v) * 72.0 / 2.54)
+#define A4_WIDTH (210.0 * 72 / 25.4)
+#define A4_HEIGHT (297.0 * 72 / 25.4)
+
+#define NUMBERS_TEXT_SEPARATION CM(0.5)
+
+#define HEADER_FOOTER_SIZE      2.5
+#define SEPARATOR_SPACING       1.5
+#define SEPARATOR_LINE_WIDTH    1.0
+
+
+typedef struct _TextSegment TextSegment;
+typedef struct _Paragraph   Paragraph;
+typedef struct _TextStyle   TextStyle;
+
+/* a piece of text (within a paragraph) of the same style */
+struct _TextSegment
+{
+	TextSegment             *next;
+	TextStyle               *style;
+	gchar                   *text;
+};
+
+/* a printable line */
+struct _Paragraph
+{
+	guint                    line_number;
+	TextSegment             *segment;
+};
+
+/* the style of a TextSegment */
+struct _TextStyle
+{
+	PangoFontDescription    *font_desc;
+	GdkColor                *foreground;
+	GdkColor                *background;
+	gdouble                  scale;
+	gboolean                 strikethrough;
+	PangoUnderline           underline;
+};
+
+
+struct _GtkSourcePrintJobPrivate
+{
+	/* General job configuration */
+	GnomePrintConfig 	*config;
+	GtkTextBuffer           *buffer;
+	guint			 tabs_width;
+	GtkWrapMode		 wrap_mode;
+	gboolean                 highlight;
+	PangoLanguage           *language;
+	PangoFontDescription	*font;
+	PangoFontDescription	*numbers_font;
+	guint 			 print_numbers;
+	gdouble                  margin_top;
+	gdouble                  margin_bottom;
+	gdouble                  margin_left;
+	gdouble                  margin_right;
+
+	/* Default header and footer configuration */
+	gboolean                 print_header;
+	gboolean                 print_footer;
+	PangoFontDescription	*header_footer_font;
+	gchar                   *header_format_left;
+	gchar                   *header_format_center;
+	gchar                   *header_format_right;
+	gboolean                 header_separator;
+	gchar                   *footer_format_left;
+	gchar                   *footer_format_center;
+	gchar                   *footer_format_right;
+	gboolean                 footer_separator;
+
+	/* Job data */
+	guint                    first_line_number;
+	guint                    last_line_number;
+	GSList                  *paragraphs;
+
+	/* Job state */
+	gboolean                 printing;
+	guint                    idle_printing_tag;
+	GnomePrintContext	*print_ctxt;
+	GnomePrintJob           *print_job;
+	PangoContext            *pango_context;
+	PangoTabArray           *tab_array;
+	gint                     page;
+	gint                     page_count;
+	gdouble                  available_height;
+	GSList                  *current_paragraph;
+	gint                     current_paragraph_line;
+	guint                    printed_lines;
+
+	/* Cached information - all this information is obtained from
+	 * other fields in the configuration */
+	GHashTable              *tag_styles;
+
+	gdouble			 page_width;
+	gdouble			 page_height;
+	/* outer margins */
+	gdouble			 doc_margin_top;
+	gdouble			 doc_margin_left;
+	gdouble			 doc_margin_right;
+	gdouble			 doc_margin_bottom;
+
+	gdouble                  header_height;
+	gdouble                  footer_height;
+	gdouble                  numbers_width;
+
+	/* printable (for the document itself) size */
+	gdouble                  text_width;
+	gdouble                  text_height;
+};
+
+
+enum
+{
+	PROP_0,
+	PROP_CONFIG,
+	PROP_BUFFER,
+	PROP_TABS_WIDTH,
+	PROP_WRAP_MODE,
+	PROP_HIGHLIGHT,
+	PROP_FONT,
+	PROP_FONT_DESC,
+	PROP_NUMBERS_FONT,
+	PROP_NUMBERS_FONT_DESC,
+	PROP_PRINT_NUMBERS,
+	PROP_PRINT_HEADER,
+	PROP_PRINT_FOOTER,
+	PROP_HEADER_FOOTER_FONT,
+	PROP_HEADER_FOOTER_FONT_DESC
+};
+
+enum
+{
+	BEGIN_PAGE = 0,
+	FINISHED,
+	LAST_SIGNAL
+};
+
+static GObjectClass *parent_class = NULL;
+static guint 	     print_job_signals [LAST_SIGNAL] = { 0 };
+
+static void     gtk_source_print_job_class_init    (GtkSourcePrintJobClass *klass);
+static void     gtk_source_print_job_instance_init (GtkSourcePrintJob      *job);
+static void     gtk_source_print_job_finalize      (GObject                *object);
+static void     gtk_source_print_job_get_property  (GObject                *object,
+						    guint                   property_id,
+						    GValue                 *value,
+						    GParamSpec             *pspec);
+static void     gtk_source_print_job_set_property  (GObject                *object,
+						    guint                   property_id,
+						    const GValue           *value,
+						    GParamSpec             *pspec);
+static void     gtk_source_print_job_begin_page    (GtkSourcePrintJob      *job);
+
+static void     default_print_header               (GtkSourcePrintJob      *job,
+						    gdouble                 x,
+						    gdouble                 y);
+static void     default_print_footer               (GtkSourcePrintJob      *job,
+						    gdouble                 x,
+						    gdouble                 y);
+
+
+GType
+gtk_source_print_job_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (our_type == 0)
+	{
+		static const GTypeInfo our_info = {
+			sizeof (GtkSourcePrintJobClass),
+			NULL,	/* base_init */
+			NULL,	/* base_finalize */
+			(GClassInitFunc) gtk_source_print_job_class_init,
+			NULL,	/* class_finalize */
+			NULL,	/* class_data */
+			sizeof (GtkSourcePrintJob),
+			0,	/* n_preallocs */
+			(GInstanceInitFunc) gtk_source_print_job_instance_init
+		};
+
+		our_type = g_type_register_static (G_TYPE_OBJECT,
+						   "GtkSourcePrintJob",
+						   &our_info, 
+						   0);
+	}
+	
+	return our_type;
+}
+	
+static void
+gtk_source_print_job_class_init (GtkSourcePrintJobClass *klass)
+{
+	GObjectClass *object_class;
+
+	object_class = G_OBJECT_CLASS (klass);
+	parent_class = g_type_class_peek_parent (klass);
+		
+	object_class->finalize	   = gtk_source_print_job_finalize;
+	object_class->get_property = gtk_source_print_job_get_property;
+	object_class->set_property = gtk_source_print_job_set_property;
+
+	klass->begin_page = gtk_source_print_job_begin_page;
+	klass->finished = NULL;
+	
+	g_object_class_install_property (object_class,
+					 PROP_CONFIG,
+					 g_param_spec_object ("config",
+							      _("Configuration"),
+							      _("Configuration options for "
+								"the print job"),
+							      GNOME_TYPE_PRINT_CONFIG,
+							      G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_BUFFER,
+					 g_param_spec_object ("buffer",
+							      _("Source Buffer"),
+							      _("GtkTextBuffer object to print"),
+							      GTK_TYPE_TEXT_BUFFER,
+							      G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_TABS_WIDTH,
+					 g_param_spec_uint ("tabs_width",
+							    _("Tabs Width"),
+							    _("Width in equivalent space "
+							      "characters of tabs"),
+							    0, 100, 8,
+							    G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_WRAP_MODE,
+					 g_param_spec_enum ("wrap_mode",
+							    _("Wrap Mode"),
+							    _("Word wrapping mode"),
+							    GTK_TYPE_WRAP_MODE,
+							    GTK_WRAP_NONE,
+							    G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_HIGHLIGHT,
+					 g_param_spec_boolean ("highlight",
+							       _("Highlight"),
+							       _("Whether to print the "
+								 "document with highlighted "
+								 "syntax"),
+							       TRUE,
+							       G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_FONT,
+					 g_param_spec_string ("font",
+							      _("Font"),
+							      _("GnomeFont name to use for the "
+								"document text (deprecated)"),
+							      NULL,
+							      G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_FONT_DESC,
+					 g_param_spec_boxed ("font_desc",
+							     _("Font Description"),
+							     _("Font to use for the document text "
+							       "(e.g. \"Monospace 10\")"),
+							     PANGO_TYPE_FONT_DESCRIPTION,
+							      G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_NUMBERS_FONT,
+					 g_param_spec_string ("numbers_font",
+							      _("Numbers Font"),
+							      _("GnomeFont name to use for the "
+								"line numbers (deprecated)"),
+							      NULL,
+							      G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_NUMBERS_FONT_DESC,
+					 g_param_spec_boxed ("numbers_font_desc",
+							     _("Numbers Font"),
+							     _("Font description to use for the "
+							       "line numbers"),
+							     PANGO_TYPE_FONT_DESCRIPTION,
+							      G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_PRINT_NUMBERS,
+					 g_param_spec_uint ("print_numbers",
+							    _("Print Line Numbers"),
+							    _("Interval of printed line numbers "
+							      "(0 means no numbers)"),
+							    0, 100, 1,
+							    G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_PRINT_HEADER,
+					 g_param_spec_boolean ("print_header",
+							       _("Print Header"),
+							       _("Whether to print a header "
+								 "in each page"),
+							       FALSE,
+							       G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_PRINT_FOOTER,
+					 g_param_spec_boolean ("print_footer",
+							       _("Print Footer"),
+							       _("Whether to print a footer "
+								 "in each page"),
+							       FALSE,
+							       G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_HEADER_FOOTER_FONT,
+					 g_param_spec_string ("header_footer_font",
+							      _("Header and Footer Font"),
+							      _("GnomeFont name to use for the header "
+								"and footer (deprecated)"),
+							      NULL,
+							      G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_HEADER_FOOTER_FONT_DESC,
+					 g_param_spec_boxed ("header_footer_font_desc",
+							     _("Header and Footer Font Description"),
+							     _("Font to use for headers and footers "
+							       "(e.g. \"Monospace 10\")"),
+							     PANGO_TYPE_FONT_DESCRIPTION,
+							     G_PARAM_READWRITE));
+	
+	print_job_signals [BEGIN_PAGE] =
+	    g_signal_new ("begin_page",
+			  G_OBJECT_CLASS_TYPE (object_class),
+			  G_SIGNAL_RUN_LAST,
+			  G_STRUCT_OFFSET (GtkSourcePrintJobClass, begin_page),
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__VOID,
+			  G_TYPE_NONE, 
+			  0);
+	print_job_signals [FINISHED] =
+	    g_signal_new ("finished",
+			  G_OBJECT_CLASS_TYPE (object_class),
+			  G_SIGNAL_RUN_FIRST,
+			  G_STRUCT_OFFSET (GtkSourcePrintJobClass, finished),
+			  NULL, NULL,
+			  g_cclosure_marshal_VOID__VOID,
+			  G_TYPE_NONE, 
+			  0);
+}
+
+static void
+gtk_source_print_job_instance_init (GtkSourcePrintJob *job)
+{
+	GtkSourcePrintJobPrivate *priv;
+
+	priv = g_new0 (GtkSourcePrintJobPrivate, 1);
+	job->priv = priv;
+
+	/* default job configuration */
+	priv->config = NULL;
+	priv->buffer = NULL;
+
+	priv->tabs_width = 8;
+	priv->wrap_mode = GTK_WRAP_NONE;
+	priv->highlight = TRUE;
+	priv->language = gtk_get_default_language ();
+	priv->font = NULL;
+	priv->numbers_font = NULL;
+	priv->print_numbers = 1;
+	priv->margin_top = 0.0;
+	priv->margin_bottom = 0.0;
+	priv->margin_left = 0.0;
+	priv->margin_right = 0.0;
+
+	priv->print_header = FALSE;
+	priv->print_footer = FALSE;
+	priv->header_footer_font = NULL;
+	priv->header_format_left = NULL;
+	priv->header_format_center = NULL;
+	priv->header_format_right = NULL;
+	priv->header_separator = FALSE;
+	priv->footer_format_left = NULL;
+	priv->footer_format_center = NULL;
+	priv->footer_format_right = NULL;
+	priv->footer_separator = FALSE;
+
+	/* initial state */
+	priv->printing = FALSE;
+	priv->print_ctxt = NULL;
+	priv->print_job = NULL;
+	priv->page = 0;
+	priv->page_count = 0;
+
+	priv->first_line_number = 0;
+	priv->paragraphs = NULL;
+	priv->tag_styles = NULL;
+
+	/* some default, sane values */
+	priv->page_width = A4_WIDTH;
+	priv->page_height = A4_HEIGHT;
+	priv->doc_margin_top = CM (1);
+	priv->doc_margin_left = CM (1);
+	priv->doc_margin_right = CM (1);
+	priv->doc_margin_bottom = CM (1);
+}
+
+static void
+free_paragraphs (GSList *paras)
+{
+	while (paras != NULL)
+	{
+		Paragraph *para = paras->data;
+		TextSegment *seg =  para->segment;
+		while (seg != NULL)
+		{
+			TextSegment *next = seg->next;
+			g_free (seg->text);
+			g_free (seg);
+			seg = next;
+		}
+		g_free (para);
+		paras = g_slist_delete_link (paras, paras);
+	}
+}
+
+static void
+gtk_source_print_job_finalize (GObject *object)
+{
+	GtkSourcePrintJob *job;
+	GtkSourcePrintJobPrivate *priv;
+	
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (object));
+	
+	job = GTK_SOURCE_PRINT_JOB (object);
+	priv = job->priv;
+	
+	if (priv != NULL)
+	{
+		if (priv->config != NULL)
+			gnome_print_config_unref (priv->config);
+		if (priv->buffer != NULL)
+			g_object_unref (priv->buffer);
+		if (priv->font != NULL)
+			pango_font_description_free (priv->font);
+		if (priv->numbers_font != NULL)
+			pango_font_description_free (priv->numbers_font);
+		if (priv->header_footer_font != NULL)
+			pango_font_description_free (priv->header_footer_font);
+		g_free (priv->header_format_left);
+		g_free (priv->header_format_right);
+		g_free (priv->header_format_center);
+		g_free (priv->footer_format_left);
+		g_free (priv->footer_format_right);
+		g_free (priv->footer_format_center);
+		
+		if (priv->print_ctxt != NULL)
+			g_object_unref (priv->print_ctxt);
+		if (priv->print_job != NULL)
+			g_object_unref (priv->print_job);
+		if (priv->pango_context != NULL)
+			g_object_unref (priv->pango_context);
+		if (priv->tab_array != NULL)
+			pango_tab_array_free (priv->tab_array);
+
+		if (priv->paragraphs != NULL)
+			free_paragraphs (priv->paragraphs);
+		if (priv->tag_styles != NULL)
+			g_hash_table_destroy (priv->tag_styles);
+		
+		g_free (priv);
+		job->priv = NULL;
+	}
+	
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void 
+gtk_source_print_job_get_property (GObject    *object,
+				   guint       prop_id,
+				   GValue     *value,
+				   GParamSpec *pspec)
+{
+	GtkSourcePrintJob *job = GTK_SOURCE_PRINT_JOB (object);
+
+	switch (prop_id)
+	{
+		case PROP_CONFIG:
+			g_value_set_object (value, job->priv->config);
+			break;
+			
+		case PROP_BUFFER:
+			g_value_set_object (value, job->priv->buffer);
+			break;
+
+		case PROP_TABS_WIDTH:
+			g_value_set_uint (value, job->priv->tabs_width);
+			break;
+			
+		case PROP_WRAP_MODE:
+			g_value_set_enum (value, job->priv->wrap_mode);
+			break;
+
+		case PROP_HIGHLIGHT:
+			g_value_set_boolean (value, job->priv->highlight);
+			break;
+			
+		case PROP_FONT:
+			g_value_take_string (value, gtk_source_print_job_get_font (job));
+			break;
+			
+		case PROP_FONT_DESC:
+			g_value_set_boxed (value, gtk_source_print_job_get_font_desc (job));
+			break;
+			
+		case PROP_NUMBERS_FONT:
+ 			g_value_take_string (value, gtk_source_print_job_get_numbers_font (job));
+			break;
+			
+		case PROP_NUMBERS_FONT_DESC:
+ 			g_value_set_boxed (value, gtk_source_print_job_get_numbers_font_desc (job));
+			break;
+			
+		case PROP_PRINT_NUMBERS:
+			g_value_set_uint (value, job->priv->print_numbers);
+			break;
+			
+		case PROP_PRINT_HEADER:
+			g_value_set_boolean (value, job->priv->print_header);
+			break;
+			
+		case PROP_PRINT_FOOTER:
+			g_value_set_boolean (value, job->priv->print_footer);
+			break;
+			
+		case PROP_HEADER_FOOTER_FONT:
+			g_value_take_string (value,
+					     gtk_source_print_job_get_header_footer_font (job));
+			break;
+			
+		case PROP_HEADER_FOOTER_FONT_DESC:
+			g_value_set_boxed (value,
+					   gtk_source_print_job_get_header_footer_font_desc (job));
+			break;
+			
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void 
+gtk_source_print_job_set_property (GObject      *object,
+				   guint         prop_id,
+				   const GValue *value,
+				   GParamSpec   *pspec)
+{
+	GtkSourcePrintJob *job = GTK_SOURCE_PRINT_JOB (object);
+
+	switch (prop_id)
+	{
+		case PROP_CONFIG:
+			gtk_source_print_job_set_config (job, g_value_get_object (value));
+			break;
+			
+		case PROP_BUFFER:
+			gtk_source_print_job_set_buffer (job, g_value_get_object (value));
+			break;
+			
+		case PROP_TABS_WIDTH:
+			gtk_source_print_job_set_tabs_width (job, g_value_get_uint (value));
+			break;
+			
+		case PROP_WRAP_MODE:
+			gtk_source_print_job_set_wrap_mode (job, g_value_get_enum (value));
+			break;
+
+		case PROP_HIGHLIGHT:
+			gtk_source_print_job_set_highlight (job, g_value_get_boolean (value));
+			break;
+
+		case PROP_FONT:
+			gtk_source_print_job_set_font (job, g_value_get_string (value));
+			break;
+
+		case PROP_FONT_DESC:
+			gtk_source_print_job_set_font_desc (job, g_value_get_boxed (value));
+			break;
+			
+		case PROP_NUMBERS_FONT:
+			gtk_source_print_job_set_numbers_font (job, g_value_get_string (value));
+			break;
+			
+		case PROP_NUMBERS_FONT_DESC:
+			gtk_source_print_job_set_numbers_font_desc (job, g_value_get_boxed (value));
+			break;
+
+		case PROP_PRINT_NUMBERS:
+			gtk_source_print_job_set_print_numbers (job, g_value_get_uint (value));
+			break;
+			
+		case PROP_PRINT_HEADER:
+			gtk_source_print_job_set_print_header (job, g_value_get_boolean (value));
+			break;
+
+		case PROP_PRINT_FOOTER:
+			gtk_source_print_job_set_print_footer (job, g_value_get_boolean (value));
+			break;
+
+		case PROP_HEADER_FOOTER_FONT:
+			gtk_source_print_job_set_header_footer_font (job,
+								     g_value_get_string (value));
+			break;
+			
+		case PROP_HEADER_FOOTER_FONT_DESC:
+			gtk_source_print_job_set_header_footer_font_desc (job,
+									  g_value_get_boxed (value));
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void 
+gtk_source_print_job_begin_page (GtkSourcePrintJob *job)
+{
+	g_return_if_fail (job->priv->printing);
+	
+	if (job->priv->print_header && job->priv->header_height > 0)
+	{
+		gdouble x, y;
+
+		x = job->priv->doc_margin_left + job->priv->margin_left;
+		y = job->priv->page_height - job->priv->doc_margin_top - job->priv->margin_top;
+		default_print_header (job, x, y);
+	}
+
+	if (job->priv->print_footer && job->priv->footer_height > 0)
+	{
+		gdouble x, y;
+
+		x = job->priv->doc_margin_left + job->priv->margin_left;
+		y = job->priv->doc_margin_bottom +
+			job->priv->margin_bottom +
+			job->priv->footer_height;
+		default_print_footer (job, x, y);
+	}
+}
+
+/* ---- gnome-print / Pango convenience functions */
+
+/* Gets the width of a layout in gnome-print coordinates */
+static gdouble
+get_layout_width (PangoLayout *layout)
+{
+	gint layout_width;
+
+	pango_layout_get_size (layout, &layout_width, NULL);
+	return (gdouble) layout_width / PANGO_SCALE;
+}
+
+/* Gets the ascent/descent of a font in gnome-print coordinates */
+static void
+get_font_ascent_descent (GtkSourcePrintJob    *job,
+			 PangoFontDescription *desc,
+			 gdouble              *ascent,
+			 gdouble              *descent)
+{
+	PangoFontMetrics *metrics;
+	
+	metrics = pango_context_get_metrics (job->priv->pango_context,
+					     desc,
+					     job->priv->language);
+
+	if (ascent)
+		*ascent = (gdouble) pango_font_metrics_get_ascent (metrics) / PANGO_SCALE;
+	if (descent)
+		*descent = (gdouble) pango_font_metrics_get_descent (metrics) / PANGO_SCALE;
+
+	pango_font_metrics_unref (metrics);
+}
+
+/* Draws the first line in a layout; we use this for one-line layouts
+ * to get baseline alignment */
+static void
+show_first_layout_line (GnomePrintContext *print_ctxt,
+			PangoLayout       *layout)
+{
+	PangoLayoutLine *line;
+
+	line = pango_layout_get_lines (layout)->data;
+	gnome_print_pango_layout_line (print_ctxt, line);
+}
+
+static PangoLayout *
+get_line_number_layout (GtkSourcePrintJob *job,
+			guint              line_number)
+{
+	PangoLayout *layout;
+	gchar *num_str;
+
+	num_str = g_strdup_printf ("%d", line_number);
+	layout = pango_layout_new (job->priv->pango_context);
+	pango_layout_set_font_description (layout, job->priv->numbers_font);
+	pango_layout_set_text (layout, num_str, -1);
+	g_free (num_str);
+
+	return layout;
+}
+
+/* ---- Configuration functions */
+
+static void
+ensure_print_config (GtkSourcePrintJob *job)
+{
+	if (job->priv->config == NULL)
+		job->priv->config = gnome_print_config_default ();
+	if (job->priv->font == NULL)
+		job->priv->font = pango_font_description_from_string (DEFAULT_FONT_NAME);
+}
+
+static gboolean
+update_page_size_and_margins (GtkSourcePrintJob *job)
+{
+	PangoLayout *layout;
+	gdouble ascent, descent;
+	
+	gnome_print_job_get_page_size_from_config (job->priv->config, 
+						   &job->priv->page_width,
+						   &job->priv->page_height);
+
+	gnome_print_config_get_length (job->priv->config, 
+				       (const guchar *) GNOME_PRINT_KEY_PAGE_MARGIN_TOP,
+				       &job->priv->doc_margin_top, NULL);
+	gnome_print_config_get_length (job->priv->config, 
+				       (const guchar *) GNOME_PRINT_KEY_PAGE_MARGIN_BOTTOM,
+				       &job->priv->doc_margin_bottom, NULL);
+	gnome_print_config_get_length (job->priv->config, 
+				       (const guchar *) GNOME_PRINT_KEY_PAGE_MARGIN_LEFT,
+				       &job->priv->doc_margin_left, NULL);
+	gnome_print_config_get_length (job->priv->config, 
+				       (const guchar *) GNOME_PRINT_KEY_PAGE_MARGIN_RIGHT,
+				       &job->priv->doc_margin_right, NULL);
+
+	/* set default fonts for numbers and header/footer */
+	if (job->priv->numbers_font == NULL)
+		job->priv->numbers_font = pango_font_description_copy (job->priv->font);
+	
+	if (job->priv->header_footer_font == NULL)
+		job->priv->header_footer_font = pango_font_description_copy (job->priv->font);
+	
+	/* calculate numbers width */
+	if (job->priv->print_numbers > 0)
+	{
+		layout = get_line_number_layout (job, job->priv->last_line_number);
+		job->priv->numbers_width = get_layout_width (layout) + NUMBERS_TEXT_SEPARATION;
+		g_object_unref (layout);
+	}
+	else
+		job->priv->numbers_width = 0.0;
+
+	get_font_ascent_descent (job, job->priv->header_footer_font, &ascent, &descent);
+
+	/* calculate header/footer height */
+	if (job->priv->print_header &&
+	    (job->priv->header_format_left != NULL ||
+	     job->priv->header_format_center != NULL ||
+	     job->priv->header_format_right != NULL))
+		job->priv->header_height = HEADER_FOOTER_SIZE * (ascent + descent);
+	else
+		job->priv->header_height = 0.0;
+
+	if (job->priv->print_footer &&
+	    (job->priv->footer_format_left != NULL ||
+	     job->priv->footer_format_center != NULL ||
+	     job->priv->footer_format_right != NULL))
+		job->priv->footer_height = HEADER_FOOTER_SIZE * (ascent + descent);
+	else
+		job->priv->footer_height = 0.0;
+
+	/* verify that the user provided margins are not too excesive
+	 * and that we still have room for the text */
+	job->priv->text_width = (job->priv->page_width -
+				 job->priv->doc_margin_left - job->priv->doc_margin_right -
+				 job->priv->margin_left - job->priv->margin_right -
+				 job->priv->numbers_width);
+	
+	job->priv->text_height = (job->priv->page_height -
+				  job->priv->doc_margin_top - job->priv->doc_margin_bottom -
+				  job->priv->margin_top - job->priv->margin_bottom -
+				  job->priv->header_height - job->priv->footer_height);
+
+	/* FIXME: put some saner values than 5cm - Gustavo */
+	g_return_val_if_fail (job->priv->text_width > CM(5.0), FALSE);
+	g_return_val_if_fail (job->priv->text_height > CM(5.0), FALSE);
+
+	return TRUE;
+}
+
+/* We want a uniform tab width for the entire job without regard to style
+ * See comments in gtksourceview.c:calculate_real_tab_width
+ */
+static gint
+calculate_real_tab_width (GtkSourcePrintJob *job, guint tab_size, gchar c)
+{
+	PangoLayout *layout;
+	gchar *tab_string;
+	gint tab_width = 0;
+
+	if (tab_size == 0)
+		return -1;
+
+	tab_string = g_strnfill (tab_size, c);
+	layout = pango_layout_new (job->priv->pango_context);
+	pango_layout_set_text (layout, tab_string, -1);
+	g_free (tab_string);
+
+	pango_layout_get_size (layout, &tab_width, NULL);
+	g_object_unref (G_OBJECT (layout));
+	
+	return tab_width;
+}
+
+static gboolean
+setup_pango_context (GtkSourcePrintJob *job)
+{
+	PangoFontMap *font_map;
+	gint real_tab_width;
+
+	if (!job->priv->pango_context)
+	{
+		font_map = gnome_print_pango_get_default_font_map ();
+		job->priv->pango_context = gnome_print_pango_create_context (font_map);
+	}
+
+	pango_context_set_language (job->priv->pango_context, job->priv->language);
+	pango_context_set_font_description (job->priv->pango_context, job->priv->font);
+
+	if (job->priv->tab_array)
+	{
+		pango_tab_array_free (job->priv->tab_array);
+		job->priv->tab_array = NULL;
+	}
+	
+	real_tab_width = calculate_real_tab_width (job, job->priv->tabs_width, ' ');
+	if (real_tab_width > 0)
+	{
+		job->priv->tab_array = pango_tab_array_new (1, FALSE);
+		pango_tab_array_set_tab (job->priv->tab_array, 0, PANGO_TAB_LEFT, real_tab_width);
+	}
+	
+	return TRUE;
+}
+
+/* ----- Helper functions */
+
+static gchar * 
+font_description_to_gnome_font_name (PangoFontDescription *desc)
+{
+	GnomeFontFace *font_face;
+	gchar *retval;
+
+	/* Will always return some font */
+	font_face = gnome_font_face_find_closest_from_pango_description (desc);
+
+	retval = g_strdup_printf("%s %f",
+				 gnome_font_face_get_name (font_face),
+				 (double) pango_font_description_get_size (desc) / PANGO_SCALE);
+	g_object_unref (font_face);
+
+	return retval;
+}
+
+/*
+ * The following routines are duplicated in gedit/gedit/gedit-prefs-manager.c
+ */
+
+/* Do this ourselves since gnome_font_find_closest() doesn't call
+ * gnome_font_face_find_closest() (probably a gnome-print bug)
+ */
+static void
+face_and_size_from_full_name (const gchar   *name,
+			      GnomeFontFace **face,
+			      gdouble        *size)
+{
+	char *copy;
+	char *str_size;
+
+	copy = g_strdup (name);
+	str_size = strrchr (copy, ' ');
+	if (str_size)
+	{
+		*str_size = 0;
+		str_size ++;
+		*size = atof (str_size);
+	}
+	else
+	{
+		*size = 12;
+	}
+
+	*face = gnome_font_face_find_closest ((const guchar *) copy);
+	g_free (copy);
+}
+
+static PangoFontDescription *
+font_description_from_gnome_font_name (const char *font_name)
+{
+	GnomeFontFace *face;
+	PangoFontDescription *desc;
+	PangoStyle style;
+	PangoWeight weight;
+	gdouble size;
+
+	face_and_size_from_full_name (font_name, &face, &size);
+
+	/* Pango and GnomePrint have basically the same numeric weight values */
+	weight = (PangoWeight) gnome_font_face_get_weight_code (face);
+	style = gnome_font_face_is_italic (face) ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
+
+	desc = pango_font_description_new ();
+	pango_font_description_set_family (desc, 
+					   (const char *) gnome_font_face_get_family_name (face));
+	pango_font_description_set_weight (desc, weight);
+	pango_font_description_set_style (desc, style);
+	pango_font_description_set_size (desc, size * PANGO_SCALE);
+
+	g_object_unref (face);
+
+	return desc;
+}
+
+/* ---- TextStyle functions */
+
+static TextStyle * 
+text_style_new (GtkSourcePrintJob *job, GtkTextTag *tag)
+{
+	TextStyle *style;
+	gboolean bg_set, fg_set;
+	
+	g_return_val_if_fail (tag != NULL && GTK_IS_TEXT_TAG (tag), NULL);
+
+	style = g_new0 (TextStyle, 1);
+
+	g_object_get (G_OBJECT (tag),
+		      "background_set", &bg_set,
+		      "foreground_set", &fg_set,
+		      "font_desc", &style->font_desc,
+		      "scale", &style->scale,
+		      "underline", &style->underline,
+		      "strikethrough", &style->strikethrough,
+		      NULL);
+
+	if (fg_set)
+		g_object_get (G_OBJECT (tag), "foreground_gdk", &style->foreground, NULL);
+
+	if (bg_set)
+		g_object_get (G_OBJECT (tag), "background_gdk", &style->background, NULL);
+	
+	return style;
+}
+
+static void
+text_style_free (TextStyle *style)
+{
+	pango_font_description_free (style->font_desc);
+	if (style->foreground)
+		gdk_color_free (style->foreground);
+	if (style->background)
+		gdk_color_free (style->background);
+	g_free (style);
+}
+
+static TextStyle * 
+get_style (GtkSourcePrintJob *job, const GtkTextIter *iter)
+{
+	GSList *tags, *t;
+	GtkTextTag *tag = NULL;
+	TextStyle *style = NULL;
+	
+	if (job->priv->tag_styles == NULL)
+	{
+		job->priv->tag_styles = g_hash_table_new_full (
+			g_direct_hash, g_direct_equal,
+			NULL, (GDestroyNotify) text_style_free);
+	}
+	
+	/* get the tags at iter */
+	tags = gtk_text_iter_get_tags (iter);
+
+	/* now find the GtkSourceTag (if any) which applies at iter */
+	/* FIXME: this makes the assumption that the style at a given
+	 * iter is only determined by one GtkSourceTag (the one with
+	 * highest priority).  This is true for now, but could change
+	 * in the future - Gustavo */
+	t = tags;
+	while (t != NULL)
+	{
+		if (GTK_IS_TEXT_TAG (t->data))
+			tag = t->data;
+		t = g_slist_next (t);
+	}
+	g_slist_free (tags);
+
+	/* now we lookup the tag style in the cache */
+	if (tag != NULL)
+	{
+		style = g_hash_table_lookup (job->priv->tag_styles, tag);
+		if (style == NULL)
+		{
+			/* create a style for the tag and cache it */
+			style = text_style_new (job, tag);
+			g_hash_table_insert (job->priv->tag_styles, tag, style);
+		}
+	}
+
+	return style;
+}
+
+/* ----- Text fetching functions */
+
+static gboolean 
+get_text_simple (GtkSourcePrintJob *job,
+		 GtkTextIter       *start,
+		 GtkTextIter       *end)
+{
+	GtkTextIter iter;
+
+	while (gtk_text_iter_compare (start, end) < 0)
+	{
+		Paragraph *para;
+		TextSegment *seg;
+		
+		/* get a line of text */
+		iter = *start;
+		if (!gtk_text_iter_ends_line (&iter))
+			gtk_text_iter_forward_to_line_end (&iter);
+		
+		if (gtk_text_iter_compare (&iter, end) > 0)
+			iter = *end;
+
+		
+		seg = g_new0 (TextSegment, 1);
+		seg->next = NULL;  /* only one segment per line, since there's no style change */
+		seg->style = NULL; /* use default style */
+		/* FIXME: handle invisible text properly.  This also
+		 * assumes the text has no embedded images and
+		 * stuff */
+		seg->text = gtk_text_iter_get_slice (start, &iter);
+
+		para = g_new0 (Paragraph, 1);
+		para->segment = seg;
+
+		/* add the line of text to the job */
+		job->priv->paragraphs = g_slist_prepend (job->priv->paragraphs, para);
+
+		gtk_text_iter_forward_line (&iter);
+		
+		/* advance to next line */
+		*start = iter;
+	}
+	job->priv->paragraphs = g_slist_reverse (job->priv->paragraphs);
+
+	return TRUE;
+}
+
+static gboolean 
+get_text_with_style (GtkSourcePrintJob *job,
+		     GtkTextIter       *start,
+		     GtkTextIter       *end)
+{
+	GtkTextIter limit, next_toggle;
+	gboolean have_toggle;
+	
+	/* make sure the region to print is highlighted */
+	/*_gtk_source_buffer_highlight_region (job->priv->buffer, start, end, TRUE); */
+
+	next_toggle = *start;
+	have_toggle = gtk_text_iter_forward_to_tag_toggle (&next_toggle, NULL);
+	
+	/* FIXME: handle invisible text properly.  This also assumes
+	 * the text has no embedded images and stuff */
+	while (gtk_text_iter_compare (start, end) < 0)
+	{
+		TextStyle *style;
+		TextSegment *seg;
+		Paragraph *para;
+		
+		para = g_new0 (Paragraph, 1);
+
+		/* get the style at the start of the line */
+		style = get_style (job, start);
+
+		/* get a line of text - limit points to the end of the line */
+		limit = *start;
+		if (!gtk_text_iter_ends_line (&limit))
+			gtk_text_iter_forward_to_line_end (&limit);
+		
+		if (gtk_text_iter_compare (&limit, end) > 0)
+			limit = *end;
+
+		/* create the first segment for the line */
+		para->segment = seg = g_new0 (TextSegment, 1);
+		seg->style = style;
+
+		/* while the next tag toggle is within the line, we check to see
+		 * if the style has changed at each tag toggle position, and if so,
+		 * create new segments */
+		while (have_toggle && gtk_text_iter_compare (&next_toggle, &limit) < 0)
+		{
+			/* check style changes */
+			style = get_style (job, &next_toggle);
+			if (style != seg->style)
+			{
+				TextSegment *new_seg;
+				
+				/* style has changed, thus we need to
+				 * create a new segment */
+				/* close the current segment */
+				seg->text = gtk_text_iter_get_slice (start, &next_toggle);
+				*start = next_toggle;
+				
+				new_seg = g_new0 (TextSegment, 1);
+				seg->next = new_seg;
+				seg = new_seg;
+				seg->style = style;
+			}
+
+			have_toggle = gtk_text_iter_forward_to_tag_toggle (&next_toggle, NULL);			
+		}
+		
+		/* close the line */
+		seg->next = NULL;
+		seg->text = gtk_text_iter_get_slice (start, &limit);
+
+		/* add the line of text to the job */
+		job->priv->paragraphs = g_slist_prepend (job->priv->paragraphs, para);
+
+		/* advance to next line */
+		*start = limit;
+		gtk_text_iter_forward_line (start);
+
+		if (gtk_text_iter_compare (&next_toggle, start) < 0) {
+			next_toggle = *start;
+			have_toggle = gtk_text_iter_forward_to_tag_toggle (&next_toggle, NULL);
+		}
+	}
+	job->priv->paragraphs = g_slist_reverse (job->priv->paragraphs);
+
+	return TRUE;
+}
+
+static gboolean 
+get_text_to_print (GtkSourcePrintJob *job,
+		   const GtkTextIter *start,
+		   const GtkTextIter *end)
+{
+	GtkTextIter _start, _end;
+	gboolean retval;
+	
+	g_return_val_if_fail (start != NULL && end != NULL, FALSE);
+	g_return_val_if_fail (job->priv->buffer != NULL, FALSE);
+
+	_start = *start;
+	_end = *end;
+
+	/* erase any previous data */
+	if (job->priv->paragraphs != NULL)
+	{
+		free_paragraphs (job->priv->paragraphs);
+		job->priv->paragraphs = NULL;
+	}
+	if (job->priv->tag_styles != NULL)
+	{
+		g_hash_table_destroy (job->priv->tag_styles);
+		job->priv->tag_styles = NULL;
+	}
+
+	/* provide ordered iters */
+	gtk_text_iter_order (&_start, &_end);
+
+	/* save the first and last line numbers for future reference */
+	job->priv->first_line_number = gtk_text_iter_get_line (&_start) + 1;
+	job->priv->last_line_number = gtk_text_iter_get_line (&_end) + 1;
+
+	if (!job->priv->highlight)
+		retval = get_text_simple (job, &_start, &_end);
+	else
+		retval = get_text_with_style (job, &_start, &_end);
+
+	if (retval && job->priv->paragraphs == NULL)
+	{
+		Paragraph *para;
+		TextSegment *seg;
+		
+		/* add an empty line to allow printing empty documents */
+		seg = g_new0 (TextSegment, 1);
+		seg->next = NULL;
+		seg->style = NULL; /* use default style */
+		seg->text = g_strdup ("");
+
+		para = g_new0 (Paragraph, 1);
+		para->segment = seg;
+
+		job->priv->paragraphs = g_slist_prepend (job->priv->paragraphs, para);
+	}
+
+	return retval;
+}
+
+/* ----- Pagination functions */
+
+static void
+add_attribute_to_list (PangoAttribute *attr, 
+		       PangoAttrList  *list,
+		       guint           index,
+		       gsize           len)
+{
+	attr->start_index = index;
+	attr->end_index = index + len;
+	pango_attr_list_insert (list, attr);
+}
+
+static PangoLayout *
+create_layout_for_para (GtkSourcePrintJob *job,
+			Paragraph         *para)
+{
+	GString *text;
+	PangoLayout *layout;
+	PangoAttrList *attrs;
+	TextSegment *seg;
+	gint index;
+
+	text = g_string_new (NULL);
+	attrs = pango_attr_list_new ();
+	
+	seg = para->segment;
+	index = 0;
+
+	while (seg != NULL)
+	{
+		gsize seg_len = strlen (seg->text);
+		g_string_append (text, seg->text);
+
+		if (seg->style)
+		{
+			PangoAttribute *attr;
+
+			attr = pango_attr_font_desc_new (seg->style->font_desc);
+			add_attribute_to_list (attr, attrs, index, seg_len);
+
+			if (seg->style->scale != PANGO_SCALE_MEDIUM) 
+			{
+				attr = pango_attr_scale_new (seg->style->scale);
+				add_attribute_to_list (attr, attrs, index, seg_len);
+			}
+
+			if (seg->style->foreground)
+			{
+				attr = pango_attr_foreground_new (seg->style->foreground->red,
+								  seg->style->foreground->green,
+								  seg->style->foreground->blue);
+				add_attribute_to_list (attr, attrs, index, seg_len);
+			}
+
+			if (seg->style->background)
+			{
+				attr = pango_attr_background_new (seg->style->background->red,
+								  seg->style->background->green,
+								  seg->style->background->blue);
+				add_attribute_to_list (attr, attrs, index, seg_len);
+			}
+
+			if (seg->style->strikethrough)
+			{
+				attr = pango_attr_strikethrough_new (TRUE);
+				add_attribute_to_list (attr, attrs, index, seg_len);
+			}
+
+			if (seg->style->underline != PANGO_UNDERLINE_NONE &&
+			    seg->style->underline != PANGO_UNDERLINE_ERROR)
+			{
+				attr = pango_attr_underline_new (seg->style->underline);
+				add_attribute_to_list (attr, attrs, index, seg_len);
+			}
+		}
+
+		index += seg_len;
+		seg = seg->next;
+	}
+
+	layout = pango_layout_new (job->priv->pango_context);
+	
+/*	if (job->priv->wrap_mode != GTK_WRAP_NONE)*/
+		pango_layout_set_width (layout, job->priv->text_width * PANGO_SCALE);
+	
+	switch (job->priv->wrap_mode)	{
+	case GTK_WRAP_CHAR:
+		pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
+		break;
+	case GTK_WRAP_WORD:
+		pango_layout_set_wrap (layout, PANGO_WRAP_WORD);
+		break;
+	case GTK_WRAP_WORD_CHAR:
+		pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
+		break;
+	case GTK_WRAP_NONE:
+		/* FIXME: hack 
+		 * Ellipsize the paragraph when text wrapping is disabled.
+		 * Another possibility would be to set the width so the text 
+		 * breaks into multiple lines, and paginate/render just the 
+		 * first one.
+		 * See also Comment #23 by Owen on bug #143874.
+		 */
+
+		/* orph says to comment this out and commit it.
+		   PANGO_ELLIPSIZE_END is not available in pango
+		   1.4.1, at least, and he says this code is never
+		   used. */
+		/*pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);*/
+
+		break;
+	}
+
+	if (job->priv->tab_array)
+		pango_layout_set_tabs (layout, job->priv->tab_array);
+	
+	pango_layout_set_text (layout, text->str, text->len);
+	pango_layout_set_attributes (layout, attrs);
+
+	/* FIXME: <horrible-hack> 
+	 * For empty paragraphs, pango_layout_iter_get_baseline() returns 0,
+	 * so I check this condition and add a space character to force 
+	 * the calculation of the baseline. I don't like that, but I
+	 * didn't find a better way to do it. Note that a paragraph is 
+	 * considered empty either when it has no characters, or when 
+	 * it only has tabs.
+	 * See comment #22 and #23 on bug #143874.
+	 */
+	if (job->priv->print_numbers > 0)
+	{
+		PangoLayoutIter *iter;
+		iter = pango_layout_get_iter (layout);
+		if (pango_layout_iter_get_baseline (iter) == 0)
+		{
+			g_string_append_c (text, ' ');
+			pango_layout_set_text (layout, text->str, text->len);
+		}
+		pango_layout_iter_free (iter);
+	}
+	/* FIXME: </horrible-hack> */
+	
+	g_string_free (text, TRUE);
+	pango_attr_list_unref (attrs);
+
+	return layout;
+}
+
+/* The break logic in this function needs to match that in print_paragraph */
+static void
+paginate_paragraph (GtkSourcePrintJob *job,
+		    Paragraph         *para)
+{
+	PangoLayout *layout;
+	PangoLayoutIter *iter;
+	PangoRectangle logical_rect;
+	gdouble max;
+	gdouble page_skip;
+
+	layout = create_layout_for_para (job, para);
+
+	iter = pango_layout_get_iter (layout);
+
+	max = 0;
+	page_skip = 0;
+
+	do
+	{
+		pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+		max = (gdouble) (logical_rect.y + logical_rect.height) / PANGO_SCALE;
+		
+		if (max - page_skip > job->priv->available_height)
+		{
+			/* "create" a new page */
+			job->priv->page_count++;
+			job->priv->available_height = job->priv->text_height;
+			page_skip = (gdouble) logical_rect.y / PANGO_SCALE;
+		}
+
+	}
+	while (pango_layout_iter_next_line (iter));
+
+	job->priv->available_height -= max - page_skip;
+	
+	pango_layout_iter_free (iter);
+	g_object_unref (layout);
+}
+
+static gboolean 
+paginate_text (GtkSourcePrintJob *job)
+{
+	GSList *l;
+	guint line_number;
+	
+	/* set these to zero so the first break_line creates a new page */
+	job->priv->page_count = 0;
+	job->priv->available_height = 0;
+	line_number = job->priv->first_line_number;
+	l = job->priv->paragraphs;
+	while (l != NULL)
+	{
+		Paragraph *para = l->data;
+
+		para->line_number = line_number;
+		paginate_paragraph (job, para);
+		
+		line_number++;
+		l = g_slist_next (l);
+	}
+
+	/* FIXME: do we have any error condition which can force us to
+	 * return %FALSE? - Gustavo */
+	return TRUE;
+}
+
+/* ---- Printing functions */
+
+static void
+begin_page (GtkSourcePrintJob *job)
+{
+	gnome_print_beginpage (job->priv->print_ctxt, NULL);
+
+	g_signal_emit (job, print_job_signals [BEGIN_PAGE], 0);
+}
+
+static void
+end_page (GtkSourcePrintJob *job)
+{
+	gnome_print_showpage (job->priv->print_ctxt);
+}
+
+static void 
+print_line_number (GtkSourcePrintJob *job,
+		   guint              line_number,
+		   gdouble            x,
+		   gdouble            y)
+{
+	PangoLayout *layout;
+
+	layout = get_line_number_layout (job, line_number);
+
+	x = x + job->priv->numbers_width - get_layout_width (layout) - NUMBERS_TEXT_SEPARATION;
+	gnome_print_moveto (job->priv->print_ctxt, x, y);
+	
+	show_first_layout_line (job->priv->print_ctxt, layout);
+	
+	g_object_unref (layout);
+}	
+
+/* The break logic in this function needs to match that in paginate_paragraph
+ *
+ * @start_line is the first line in the paragraph to print
+ * @y is updated to the position after the portion of the paragraph we printed
+ * @baseline_out is set to the baseline of the first line of the paragraph
+ *   if we printed it. (And not set otherwise)
+ * 
+ * Returns the first unprinted line in the paragraph (unprinted because it
+ * flowed onto the next page) or -1 if the entire paragraph was printed.
+ */
+static gint
+print_paragraph (GtkSourcePrintJob *job,
+		 Paragraph         *para,
+		 gint               start_line,
+		 gdouble            x,
+		 gdouble           *y,
+		 gdouble           *baseline_out,
+		 gboolean           force_fit)
+{
+	PangoLayout *layout;
+	PangoLayoutIter *iter;
+	PangoRectangle logical_rect;
+	int current_line;
+	gdouble max;
+	gdouble page_skip;
+	gdouble baseline;
+	int result = -1;
+	
+	layout = create_layout_for_para (job, para);
+
+	iter = pango_layout_get_iter (layout);
+
+	/* Skip over lines already printed on previous page(s) */
+	for (current_line = 0; current_line < start_line; current_line++)
+		pango_layout_iter_next_line (iter);
+
+	max = 0;
+	page_skip = 0;
+	
+	do
+	{
+		pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+		max = (gdouble) (logical_rect.y + logical_rect.height) / PANGO_SCALE;
+		
+		if (current_line == start_line)
+			page_skip = (gdouble) logical_rect.y / PANGO_SCALE;
+
+		if (max - page_skip > job->priv->available_height)
+		{
+			result = current_line; /* Save position for next page */
+			break;
+		}
+
+		baseline = (gdouble) pango_layout_iter_get_baseline (iter) / PANGO_SCALE;
+		baseline = *y + page_skip - baseline; /* Adjust to global coordinates */
+		if (current_line == 0)
+			*baseline_out = baseline;
+		
+		gnome_print_moveto (job->priv->print_ctxt,
+				    x + (gdouble) logical_rect.x / PANGO_SCALE,
+				    baseline);
+		gnome_print_pango_layout_line (job->priv->print_ctxt,
+					       pango_layout_iter_get_line (iter));
+
+		current_line++;
+	}
+	while (pango_layout_iter_next_line (iter));
+
+	job->priv->available_height -= max - page_skip;
+	*y -= max - page_skip;
+
+	pango_layout_iter_free (iter);
+	g_object_unref (layout);
+	
+	return result;
+}
+
+static void
+print_page (GtkSourcePrintJob *job)
+{
+	GSList *l;
+	gdouble x, y;
+	gint line;
+	gboolean force_fit = TRUE;
+	
+	job->priv->page++;
+	
+	
+	begin_page (job);
+	job->priv->available_height = job->priv->text_height;
+
+	y = job->priv->page_height -
+		job->priv->doc_margin_top - job->priv->margin_top -
+		job->priv->header_height;
+	x = job->priv->doc_margin_left + job->priv->margin_left +
+		job->priv->numbers_width;
+	l = job->priv->current_paragraph;
+	line = job->priv->current_paragraph_line;
+
+	while (l != NULL)
+	{
+		Paragraph *para = l->data;
+		gdouble baseline = 0;
+		gint last_line = line;
+		
+		line = print_paragraph (job, para, line, x, &y, &baseline, force_fit);
+
+		if (last_line == 0 && line != 0)
+		{
+			/* We printed the first line of a paragraph */
+			if (job->priv->print_numbers > 0 &&
+			    ((para->line_number % job->priv->print_numbers) == 0))
+				print_line_number (job,
+						   para->line_number,
+						   job->priv->doc_margin_left +
+						   job->priv->margin_left,
+						   baseline);
+
+			job->priv->printed_lines++;
+		}
+
+		if (line >= 0)
+			break;	/* Didn't all fit on this page */
+		
+		l = l->next;
+		line = 0;
+		force_fit = FALSE;
+	}
+	end_page (job);
+	job->priv->current_paragraph = l;
+	job->priv->current_paragraph_line = line;
+}
+
+static void
+setup_for_print (GtkSourcePrintJob *job)
+{
+	job->priv->current_paragraph = job->priv->paragraphs;
+	job->priv->page = 0;
+	job->priv->printed_lines = 0;
+
+	if (job->priv->print_job != NULL)
+		g_object_unref (job->priv->print_job);
+	if (job->priv->print_ctxt != NULL)
+		g_object_unref (job->priv->print_ctxt);
+	
+	job->priv->print_job = gnome_print_job_new (job->priv->config);
+	job->priv->print_ctxt = gnome_print_job_get_context (job->priv->print_job);
+
+	gnome_print_pango_update_context (job->priv->pango_context, job->priv->print_ctxt);
+}
+
+static void
+print_job (GtkSourcePrintJob *job)
+{
+	while (job->priv->current_paragraph != NULL)
+		print_page (job);
+
+	gnome_print_job_close (job->priv->print_job);
+}
+
+static gboolean
+idle_printing_handler (GtkSourcePrintJob *job)
+{
+	g_assert (job->priv->current_paragraph != NULL);
+
+	print_page (job);
+
+	if (job->priv->current_paragraph == NULL)
+	{
+		gnome_print_job_close (job->priv->print_job);
+		job->priv->printing = FALSE;
+		job->priv->idle_printing_tag = 0;
+
+		g_signal_emit (job, print_job_signals [FINISHED], 0);
+		/* after this the print job object is possibly
+		 * destroyed (common use case) */
+		
+		return FALSE;
+	}
+	return TRUE;
+}
+
+
+/* Public API ------------------- */
+
+/**
+ * gtk_source_print_job_new:
+ * @config: an optional #GnomePrintConfig object.
+ * 
+ * Creates a new print job object, initially setting the print configuration.
+ * 
+ * Return value: the new print job object.
+ **/
+GtkSourcePrintJob *
+gtk_source_print_job_new (GnomePrintConfig  *config)
+{
+	GtkSourcePrintJob *job;
+
+	g_return_val_if_fail (config == NULL || GNOME_IS_PRINT_CONFIG (config), NULL);
+
+	job = GTK_SOURCE_PRINT_JOB (g_object_new (GTK_TYPE_SOURCE_PRINT_JOB, NULL));
+	if (config != NULL)
+		gtk_source_print_job_set_config (job, config);
+
+	return job;
+}
+
+/**
+ * gtk_source_print_job_new_with_buffer:
+ * @config: an optional #GnomePrintConfig.
+ * @buffer: the #GtkTextBuffer to print (might be %NULL).
+ * 
+ * Creates a new print job to print @buffer.
+ * 
+ * Return value: a new print job object.
+ **/
+GtkSourcePrintJob *
+gtk_source_print_job_new_with_buffer (GnomePrintConfig  *config,
+				      GtkTextBuffer   *buffer)
+{
+	GtkSourcePrintJob *job;
+
+	g_return_val_if_fail (config == NULL || GNOME_IS_PRINT_CONFIG (config), NULL);
+	g_return_val_if_fail (buffer == NULL || GTK_IS_TEXT_BUFFER (buffer), NULL);
+
+	job = gtk_source_print_job_new (config);
+	if (buffer != NULL)
+		gtk_source_print_job_set_buffer (job, buffer);
+
+	return job;
+}
+
+/* --- print job basic configuration */
+
+/**
+ * gtk_source_print_job_set_config:
+ * @job: a #GtkSourcePrintJob.
+ * @config: a #GnomePrintConfig object to get printing configuration from.
+ * 
+ * Sets the print configuration for the job.  If you don't set a
+ * configuration object for the print job, when needed one will be
+ * created with gnome_print_config_default().
+ **/
+void
+gtk_source_print_job_set_config (GtkSourcePrintJob *job,
+				 GnomePrintConfig  *config)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (GNOME_IS_PRINT_CONFIG (config));
+	g_return_if_fail (!job->priv->printing);
+	
+	if (config == job->priv->config)
+		return;
+	
+	if (job->priv->config != NULL)
+		gnome_print_config_unref (job->priv->config);
+
+	job->priv->config = config;
+	gnome_print_config_ref (config);
+
+	g_object_notify (G_OBJECT (job), "config");
+}
+
+/**
+ * gtk_source_print_job_get_config:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Gets the current #GnomePrintConfig the print job will use.  If not
+ * previously set, this will create a default configuration and return
+ * it.  The returned object reference is owned by the print job.
+ * 
+ * Return value: the #GnomePrintConfig for the print job.
+ **/
+GnomePrintConfig * 
+gtk_source_print_job_get_config (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+
+	ensure_print_config (job);
+	
+	return job->priv->config;
+}
+
+/**
+ * gtk_source_print_job_set_buffer:
+ * @job: a #GtkSourcePrintJob.
+ * @buffer: a #GtkTextBuffer.
+ * 
+ * Sets the #GtkTextBuffer the print job will print.  You need to
+ * specify a buffer to print, either by the use of this function or by
+ * creating the print job with gtk_source_print_job_new_with_buffer().
+ **/
+void 
+gtk_source_print_job_set_buffer (GtkSourcePrintJob *job,
+				 GtkTextBuffer   *buffer)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+	g_return_if_fail (!job->priv->printing);
+
+	if (buffer == job->priv->buffer)
+		return;
+	
+	if (job->priv->buffer != NULL)
+		g_object_unref (job->priv->buffer);
+
+	job->priv->buffer = buffer;
+	g_object_ref (buffer);
+
+	g_object_notify (G_OBJECT (job), "buffer");
+}
+
+/**
+ * gtk_source_print_job_get_buffer:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Gets the #GtkTextBuffer the print job would print.  The returned
+ * object reference (if non %NULL) is owned by the job object and
+ * should not be unreferenced.
+ * 
+ * Return value: the #GtkTextBuffer to print.
+ **/
+GtkTextBuffer *
+gtk_source_print_job_get_buffer (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+
+	return job->priv->buffer;
+}
+
+/* --- print job layout and style configuration */
+
+/**
+ * gtk_source_print_job_set_tabs_width:
+ * @job: a #GtkSourcePrintJob.
+ * @tabs_width: the number of equivalent spaces for a tabulation.
+ * 
+ * Sets the width (in equivalent spaces) of tabulations for the
+ * printed text.  The width in printing units will be calculated as
+ * the width of a string containing @tabs_width spaces of the default
+ * font.  Tabulation stops are set for the full width of printed text.
+ **/
+void 
+gtk_source_print_job_set_tabs_width (GtkSourcePrintJob *job,
+				     guint              tabs_width)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	if (tabs_width == job->priv->tabs_width)
+		return;
+	
+	job->priv->tabs_width = tabs_width;
+
+	g_object_notify (G_OBJECT (job), "tabs_width");
+}
+
+/**
+ * gtk_source_print_job_get_tabs_width:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the configured width (in equivalent spaces) of
+ * tabulations.  The default value is 8.
+ * 
+ * Return value: the width (in equivalent spaces) of a tabulation.
+ **/
+guint 
+gtk_source_print_job_get_tabs_width (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), 0);
+
+	return job->priv->tabs_width;
+}
+
+/**
+ * gtk_source_print_job_set_wrap_mode:
+ * @job: a #GtkSourcePrintJob.
+ * @wrap: the wrap mode.
+ * 
+ * Sets the wrap mode for lines of text larger than the printable
+ * width.  See #GtkWrapMode for a definition of the possible values.
+ **/
+void 
+gtk_source_print_job_set_wrap_mode (GtkSourcePrintJob *job,
+				    GtkWrapMode        wrap)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	if (wrap == job->priv->wrap_mode)
+		return;
+	
+	job->priv->wrap_mode = wrap;
+
+	g_object_notify (G_OBJECT (job), "wrap_mode");
+}
+
+/**
+ * gtk_source_print_job_get_wrap_mode:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the wrapping style for text lines wider than the
+ * printable width.  The default is no wrapping.
+ * 
+ * Return value: the current wrapping mode for the print job.
+ **/
+GtkWrapMode 
+gtk_source_print_job_get_wrap_mode (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), GTK_WRAP_NONE);
+
+	return job->priv->wrap_mode;
+}
+
+/**
+ * gtk_source_print_job_set_highlight:
+ * @job: a #GtkSourcePrintJob.
+ * @highlight: %TRUE if the printed text should be highlighted.
+ * 
+ * Sets whether the printed text will be highlighted according to the
+ * buffer rules.  Both color and font style are applied.
+ **/
+void 
+gtk_source_print_job_set_highlight (GtkSourcePrintJob *job,
+				    gboolean           highlight)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	highlight = (highlight != FALSE);
+	
+	if (highlight == job->priv->highlight)
+		return;
+	
+	job->priv->highlight = highlight;
+
+	g_object_notify (G_OBJECT (job), "highlight");
+}
+
+/**
+ * gtk_source_print_job_get_highlight:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines if the job is configured to print the text highlighted
+ * with colors and font styles.  Note that highlighting will happen
+ * only if the buffer to print has highlighting activated.
+ * 
+ * Return value: %TRUE if the printed output will be highlighted.
+ **/
+gboolean 
+gtk_source_print_job_get_highlight (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), FALSE);
+
+	return job->priv->highlight;
+}
+
+/**
+ * gtk_source_print_job_set_font_desc:
+ * @job: a #GtkSourcePrintJob.
+ * @desc: the #PangoFontDescription for the default font
+ * 
+ * Sets the default font for the printed text.
+ **/
+void 
+gtk_source_print_job_set_font_desc (GtkSourcePrintJob    *job,
+				    PangoFontDescription *desc)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (desc != NULL);
+	g_return_if_fail (!job->priv->printing);
+
+	desc = pango_font_description_copy (desc);
+	if (job->priv->font != NULL)
+		pango_font_description_free (job->priv->font);
+	job->priv->font = desc;
+	g_object_freeze_notify (G_OBJECT (job));
+	g_object_notify (G_OBJECT (job), "font");
+	g_object_notify (G_OBJECT (job), "font_desc");
+	g_object_thaw_notify (G_OBJECT (job));
+}
+
+/**
+ * gtk_source_print_job_set_font:
+ * @job: a #GtkSourcePrintJob.
+ * @font_name: the name of the default font.
+ * 
+ * Sets the default font for the printed text.  @font_name should be a
+ * <emphasis>full font name</emphasis> GnomePrint can understand
+ * (e.g. &quot;Monospace Regular 10.0&quot;).
+ *
+ * Note that @font_name is a #GnomeFont name not a Pango font
+ * description string. This function is deprecated since #GnomeFont is
+ * no longer used when implementing printing for GtkSourceView; you
+ * should use gtk_source_print_job_set_font_desc() instead.
+ **/
+void 
+gtk_source_print_job_set_font (GtkSourcePrintJob *job,
+			       const gchar       *font_name)
+{
+	PangoFontDescription *desc;
+	
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (font_name != NULL);
+	g_return_if_fail (!job->priv->printing);
+
+	desc = font_description_from_gnome_font_name (font_name);
+	if (desc)
+	{
+		gtk_source_print_job_set_font_desc (job, desc);
+		pango_font_description_free (desc);
+	}
+}
+
+/**
+ * gtk_source_print_job_get_font_desc:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the default font to be used for the printed text.  The
+ * returned string is of the form &quot;Fontfamily Style Size&quot;,
+ * for example &quot;Monospace Regular 10.0&quot;.  The returned value
+ * should be freed when no longer needed.
+ * 
+ * Return value: the current text font description. This value is
+ *  owned by the job and must not be modified or freed.
+ **/
+PangoFontDescription *
+gtk_source_print_job_get_font_desc (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+
+	ensure_print_config (job);
+	
+	return job->priv->font;
+}
+
+/**
+ * gtk_source_print_job_get_font:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the default font to be used for the printed text.  The
+ * returned string is of the form &quot;Fontfamily Style Size&quot;,
+ * for example &quot;Monospace Regular 10.0&quot;.  The returned value
+ * should be freed when no longer needed.
+ * 
+ * Note that the result is a #GnomeFont name not a Pango font
+ * description string. This function is deprecated since #GnomeFont is
+ * no longer used when implementing printing for GtkSourceView; you
+ * should use gtk_source_print_job_get_font_desc() instead.
+ *
+ * Return value: a newly allocated string with the name of the current
+ * text font.
+ **/
+gchar *
+gtk_source_print_job_get_font (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+
+	ensure_print_config (job);
+	
+	return font_description_to_gnome_font_name (job->priv->font);
+}
+
+/**
+ * gtk_source_print_job_setup_from_view:
+ * @job: a #GtkSourcePrintJob.
+ * @view: a #GtkSourceView to get configuration from.
+ * 
+ * Convenience function to set several configuration options at once,
+ * so that the printed output matches @view.  The options set are
+ * buffer (if not set already), tabs width, highlighting, wrap mode
+ * and default font.
+ **/
+void 
+gtk_source_print_job_setup_from_view (GtkSourcePrintJob *job,
+				      GtkTextView       *view)
+{
+	GtkTextBuffer *buffer = NULL;
+	PangoContext *pango_context;
+	
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (GTK_IS_TEXT_VIEW (view));
+	g_return_if_fail (!job->priv->printing);
+
+	buffer = gtk_text_view_get_buffer (view);
+	
+	if (job->priv->buffer == NULL && buffer != NULL)
+		gtk_source_print_job_set_buffer (job, buffer);
+
+	/* gtk_source_print_job_set_tabs_width (job, gtk_source_view_get_tabs_width (view)); */
+	gtk_source_print_job_set_highlight (job, TRUE);
+	gtk_source_print_job_set_wrap_mode (job, gtk_text_view_get_wrap_mode (view));
+
+	pango_context = gtk_widget_get_pango_context (GTK_WIDGET (view));
+	gtk_source_print_job_set_font_desc (job, 
+					    pango_context_get_font_description (pango_context));
+}
+
+/**
+ * gtk_source_print_job_set_numbers_font_desc:
+ * @job: a #GtkSourcePrintJob.
+ * @desc: the #PangoFontDescription for the font for line numbers, or %NULL
+ * 
+ * Sets the font for printing line numbers on the left margin.  If
+ * NULL is supplied, the default font (i.e. the one being used for the
+ * text) will be used instead.
+ **/
+void 
+gtk_source_print_job_set_numbers_font_desc (GtkSourcePrintJob    *job,
+					    PangoFontDescription *desc)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+	
+	if (desc)
+		desc = pango_font_description_copy (desc);
+	if (job->priv->numbers_font != NULL)
+		pango_font_description_free (job->priv->numbers_font);
+	job->priv->numbers_font = desc;
+	g_object_freeze_notify (G_OBJECT (job));
+	g_object_notify (G_OBJECT (job), "numbers_font");
+	g_object_notify (G_OBJECT (job), "numbers_font_desc");
+	g_object_thaw_notify (G_OBJECT (job));
+}
+
+/**
+ * gtk_source_print_job_set_numbers_font:
+ * @job: a #GtkSourcePrintJob.
+ * @font_name: the full name of the font for line numbers, or %NULL.
+ * 
+ * Sets the font for printing line numbers on the left margin.  If
+ * %NULL is supplied, the default font (i.e. the one being used for the
+ * text) will be used instead.
+ *
+ * Note that @font_name is a #GnomeFont name not a Pango font
+ * description string. This function is deprecated since #GnomeFont is
+ * no longer used when implementing printing for GtkSourceView; you
+ * should use gtk_source_print_job_set_numbers_font_desc() instead.
+ **/
+void 
+gtk_source_print_job_set_numbers_font (GtkSourcePrintJob *job,
+				       const gchar       *font_name)
+{
+	PangoFontDescription *desc;
+	
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	if (font_name != NULL)
+	{
+		desc = font_description_from_gnome_font_name (font_name);
+		if (desc)
+		{
+			gtk_source_print_job_set_numbers_font_desc (job, desc);
+			pango_font_description_free (desc);
+		}
+	}
+	else
+		gtk_source_print_job_set_numbers_font (job, NULL);
+}
+
+/**
+ * gtk_source_print_job_get_numbers_font_desc:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the font to be used for the line numbers. This function
+ * might return %NULL if a specific font for numbers has not been set.
+ * 
+ * Return value: the line numbers font description or %NULL. This value is
+ * owned by the job and must not be modified or freed.
+ **/
+PangoFontDescription *
+gtk_source_print_job_get_numbers_font_desc (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+
+	return job->priv->numbers_font;
+}
+
+/**
+ * gtk_source_print_job_get_numbers_font:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the font to be used for the line numbers.  The returned
+ * string is of the form &quot;Fontfamily Style Size&quot;, for
+ * example &quot;Monospace Regular 10.0&quot;.  The returned value
+ * should be freed when no longer needed.  This function might return
+ * %NULL if a specific font for numbers has not been set.
+ * 
+ * Note that the result is a #GnomeFont name not a Pango font
+ * description string. This function is deprecated since #GnomeFont is
+ * no longer used when implementing printing for GtkSourceView; you
+ * should use gtk_source_print_job_get_numbers_font_desc() instead.
+ *
+ * Return value: a newly allocated string with the name of the current
+ * line numbers font, or %NULL.
+ **/
+gchar *
+gtk_source_print_job_get_numbers_font (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+
+	if (job->priv->numbers_font != NULL)
+		return font_description_to_gnome_font_name (job->priv->numbers_font);
+	else
+		return NULL;
+}
+
+/**
+ * gtk_source_print_job_set_print_numbers:
+ * @job: a #GtkSourcePrintJob.
+ * @interval: interval for printed line numbers.
+ * 
+ * Sets the interval for printed line numbers.  If @interval is 0 no
+ * numbers will be printed.  If greater than 0, a number will be
+ * printed every @interval lines (i.e. 1 will print all line numbers).
+ **/
+void 
+gtk_source_print_job_set_print_numbers (GtkSourcePrintJob *job,
+					guint              interval)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	if (interval == job->priv->print_numbers)
+		return;
+	
+	job->priv->print_numbers = interval;
+
+	g_object_notify (G_OBJECT (job), "print_numbers");
+}
+
+/**
+ * gtk_source_print_job_get_print_numbers:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the interval used for line number printing.  If the
+ * value is 0, no line numbers will be printed.  The default value is
+ * 1 (i.e. numbers printed in all lines).
+ * 
+ * Return value: the interval of printed line numbers.
+ **/
+guint 
+gtk_source_print_job_get_print_numbers (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), 0);
+
+	return job->priv->print_numbers;
+}
+
+/**
+ * gtk_source_print_job_set_text_margins:
+ * @job: a #GtkSourcePrintJob.
+ * @top: the top user margin.
+ * @bottom: the bottom user margin.
+ * @left: the left user margin.
+ * @right: the right user margin.
+ * 
+ * Sets the four user margins for the print job.  These margins are in
+ * addition to the document margins provided in the #GnomePrintConfig
+ * and will not be used for headers, footers or line numbers (those
+ * are calculated separatedly).  You can print in the space allocated
+ * by these margins by connecting to the <link
+ * linkend="GtkSourcePrintJob-begin-page">&quot;begin_page&quot;</link> signal.  The
+ * space is around the printed text, and inside the margins specified
+ * in the #GnomePrintConfig.
+ *
+ * The margin numbers are given in device units.  If any of the given
+ * values is less than 0, that particular margin is not altered by
+ * this function.
+ **/
+void 
+gtk_source_print_job_set_text_margins (GtkSourcePrintJob *job,
+				       gdouble            top,
+				       gdouble            bottom,
+				       gdouble            left,
+				       gdouble            right)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	if (top >= 0)
+		job->priv->margin_top = top;
+	if (bottom >= 0)
+		job->priv->margin_bottom = bottom;
+	if (left >= 0)
+		job->priv->margin_left = left;
+	if (right >= 0)
+		job->priv->margin_right = right;
+}
+
+/**
+ * gtk_source_print_job_get_text_margins:
+ * @job: a #GtkSourcePrintJob.
+ * @top: a pointer to a #gdouble to return the top margin.
+ * @bottom: a pointer to a #gdouble to return the bottom margin.
+ * @left: a pointer to a #gdouble to return the left margin.
+ * @right: a pointer to a #gdouble to return the right margin.
+ * 
+ * Determines the user set margins for the job.  This function
+ * retrieves the values previously set by
+ * gtk_source_print_job_set_text_margins().  The default for all four
+ * margins is 0.  Any of the pointers can be %NULL if you want to
+ * ignore that value.
+ **/
+void 
+gtk_source_print_job_get_text_margins (GtkSourcePrintJob *job,
+				       gdouble           *top,
+				       gdouble           *bottom,
+				       gdouble           *left,
+				       gdouble           *right)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+
+	if (top != NULL)
+		*top = job->priv->margin_top;
+	if (bottom != NULL)
+		*bottom = job->priv->margin_bottom;
+	if (left != NULL)
+		*left = job->priv->margin_left;
+	if (right != NULL)
+		*right = job->priv->margin_right;
+}
+
+/* --- printing operations */
+
+static gboolean
+gtk_source_print_job_prepare (GtkSourcePrintJob *job,
+			      const GtkTextIter *start,
+			      const GtkTextIter *end)
+{
+	PROFILE (GTimer *timer);
+	
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), FALSE);
+	g_return_val_if_fail (!job->priv->printing, FALSE);
+	g_return_val_if_fail (job->priv->buffer != NULL, FALSE);
+	g_return_val_if_fail (start != NULL && end != NULL, FALSE);
+
+	/* make sure we have a sane configuration to start printing */
+	ensure_print_config (job);
+
+	PROFILE (timer = g_timer_new ());
+
+	/* get the text to print */
+	if (!get_text_to_print (job, start, end))
+		return FALSE;
+
+	PROFILE (g_message ("get_text_to_print: %.2f", g_timer_elapsed (timer, NULL)));
+
+	if (!setup_pango_context (job))
+		return FALSE;
+
+	/* check margins */
+	if (!update_page_size_and_margins (job))
+		return FALSE;
+
+	/* split the document in pages */
+	if (!paginate_text (job))
+		return FALSE;
+
+	PROFILE ({
+		g_message ("paginate_text: %.2f", g_timer_elapsed (timer, NULL));
+		g_timer_destroy (timer);
+	});
+
+	return TRUE;
+}
+
+/**
+ * gtk_source_print_job_print:
+ * @job: a configured #GtkSourcePrintJob.
+ * 
+ * Produces a #GnomePrintJob with the printed document.  The whole
+ * contents of the configured #GtkTextBuffer are printed.  The
+ * returned job is already closed and ready to be previewed (using
+ * gnome_print_job_preview_new()) or printed directly.  The caller of
+ * this function owns a reference to the returned object, so @job can
+ * be destroyed and the output will still be valid, or the document
+ * can be printed again with different settings.
+ * 
+ * Return value: a closed #GnomePrintJob with the printed document, or
+ * %NULL if printing could not be completed.
+ **/
+GnomePrintJob *
+gtk_source_print_job_print (GtkSourcePrintJob *job)
+{
+	GtkTextIter start, end;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+	g_return_val_if_fail (!job->priv->printing, NULL);
+	g_return_val_if_fail (job->priv->buffer != NULL, NULL);
+
+	gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (job->priv->buffer), &start, &end);
+
+	return gtk_source_print_job_print_range (job, &start, &end);
+}
+
+/**
+ * gtk_source_print_job_print_range:
+ * @job: a configured #GtkSourcePrintJob.
+ * @start: the start of the region of text to print.
+ * @end: the end of the region of text to print.
+ * 
+ * Similar to gtk_source_print_job_print(), except you can specify a
+ * range of text to print.  The passed #GtkTextIter values might be
+ * out of order.
+ * 
+ * Return value: a closed #GnomePrintJob with the text from @start to
+ * @end printed, or %NULL if @job could not print.
+ **/
+GnomePrintJob *
+gtk_source_print_job_print_range (GtkSourcePrintJob *job,
+				  const GtkTextIter *start,
+				  const GtkTextIter *end)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+	g_return_val_if_fail (!job->priv->printing, NULL);
+	g_return_val_if_fail (job->priv->buffer != NULL, NULL);
+	g_return_val_if_fail (start != NULL && end != NULL, NULL);
+	g_return_val_if_fail (gtk_text_iter_get_buffer (start) ==
+			      GTK_TEXT_BUFFER (job->priv->buffer) &&
+			      gtk_text_iter_get_buffer (end) ==
+			      GTK_TEXT_BUFFER (job->priv->buffer), NULL);
+
+	if (!gtk_source_print_job_prepare (job, start, end))
+		return NULL;
+
+	/* real work starts here */
+	setup_for_print (job);
+
+	job->priv->printing = TRUE;
+	print_job (job);
+	job->priv->printing = FALSE;
+
+	g_object_ref (job->priv->print_job);
+	return job->priv->print_job;
+}
+
+/* --- asynchronous printing */
+
+/**
+ * gtk_source_print_job_print_range_async:
+ * @job: a configured #GtkSourcePrintJob.
+ * @start: the start of the region of text to print.
+ * @end: the end of the region of text to print.
+ * 
+ * Starts to print @job asynchronously.  This function will ready the
+ * @job for printing and install an idle handler that will render one
+ * page at a time.
+ *
+ * This function will not return immediatly, as only page rendering is
+ * done asynchronously.  Text retrieval and paginating happens within
+ * this function.  Also, if highlighting is enabled, the whole buffer
+ * needs to be highlighted first.
+ *
+ * To get notification when the job has finished, you must connect to
+ * the <link
+ * linkend="GtkSourcePrintJob-finished">&quot;finished&quot;</link>
+ * signal.  After this signal is emitted you can retrieve the
+ * resulting #GnomePrintJob with gtk_source_print_job_get_print_job().
+ * You may cancel the job with gtk_source_print_job_cancel().
+ *
+ * Return value: %TRUE if the print started.
+ **/
+gboolean 
+gtk_source_print_job_print_range_async (GtkSourcePrintJob *job,
+					const GtkTextIter *start,
+					const GtkTextIter *end)
+{
+	GSource *idle_source;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), FALSE);
+	g_return_val_if_fail (!job->priv->printing, FALSE);
+	g_return_val_if_fail (job->priv->buffer != NULL, FALSE);
+	g_return_val_if_fail (start != NULL && end != NULL, FALSE);
+	g_return_val_if_fail (gtk_text_iter_get_buffer (start) ==
+			      GTK_TEXT_BUFFER (job->priv->buffer) &&
+			      gtk_text_iter_get_buffer (end) ==
+			      GTK_TEXT_BUFFER (job->priv->buffer), FALSE);
+
+	if (!gtk_source_print_job_prepare (job, start, end))
+		return FALSE;
+
+	/* real work starts here */
+	setup_for_print (job);
+	if (job->priv->current_paragraph == NULL)
+		return FALSE;
+	
+	/* setup the idle handler to print each page at a time */
+	idle_source = g_idle_source_new ();
+	g_source_set_priority (idle_source, GTK_SOURCE_PRINT_JOB_PRIORITY);
+	g_source_set_closure (idle_source,
+			      g_cclosure_new_object ((GCallback) idle_printing_handler,
+						     G_OBJECT (job)));
+	job->priv->idle_printing_tag = g_source_attach (idle_source, NULL);
+	g_source_unref (idle_source);
+
+	job->priv->printing = TRUE;
+
+	return TRUE;
+}
+
+/**
+ * gtk_source_print_job_cancel:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Cancels an asynchronous printing operation.  This will remove any
+ * pending print idle handler and unref the current #GnomePrintJob.
+ *
+ * Note that if you got a reference to the job's #GnomePrintJob (using
+ * gtk_source_print_job_get_print_job()) it will not be destroyed
+ * (since you hold a reference to it), but it will not be closed
+ * either.  If you wish to show or print the partially printed
+ * document you need to close it yourself.
+ *
+ * This function has no effect when called from a non-asynchronous
+ * print operation.
+ **/
+void 
+gtk_source_print_job_cancel (GtkSourcePrintJob *job)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (job->priv->printing);
+
+	if (job->priv->idle_printing_tag > 0)
+	{
+		g_source_remove (job->priv->idle_printing_tag);
+		job->priv->current_paragraph = NULL;
+		job->priv->idle_printing_tag = 0;
+		job->priv->printing = FALSE;
+		g_object_unref (job->priv->print_job);
+		g_object_unref (job->priv->print_ctxt);
+		job->priv->print_job = NULL;
+		job->priv->print_ctxt = NULL;
+	}
+}
+
+/**
+ * gtk_source_print_job_get_print_job:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Gets a reference to the #GnomePrintJob which the @job is printing
+ * or has recently finished printing.  You need to unref the returned
+ * object.
+ *
+ * You may call this function in the middle of an asynchronous
+ * printing operation, but the returned #GnomePrintJob will not be
+ * closed until the last page is printed and the <link
+ * linkend="GtkSourcePrintJob-finished">&quot;finished&quot;</link>
+ * signal is emitted.
+ * 
+ * Return value: a new reference to the @job's #GnomePrintJob, or
+ * %NULL.
+ **/
+GnomePrintJob *
+gtk_source_print_job_get_print_job (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+
+	if (job->priv->print_job)
+		g_object_ref (job->priv->print_job);
+	
+	return job->priv->print_job;
+}
+
+/* --- information for asynchronous ops and headers and footers callback */
+
+/**
+ * gtk_source_print_job_get_page:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the currently printing page number.  This function is
+ * only valid while printing (either synchronously or asynchronously).
+ * 
+ * Return value: the current page number.
+ **/
+guint 
+gtk_source_print_job_get_page (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), 0);
+	g_return_val_if_fail (job->priv->printing, 0);
+
+	return job->priv->page;
+}
+
+/**
+ * gtk_source_print_job_get_page_count:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the total number of pages the job will print.  The
+ * returned value is only meaninful after pagination has finished.  In
+ * practice, for synchronous printing this means when <link
+ * linkend="GtkSourcePrintJob-begin-page">&quot;begin_page&quot;</link>
+ * is emitted, or after gtk_source_print_job_print_range_async() has
+ * returned.
+ * 
+ * Return value: the number of pages of the printed job.
+ **/
+guint 
+gtk_source_print_job_get_page_count (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), 0);
+
+	return job->priv->page_count;
+}
+
+/**
+ * gtk_source_print_job_get_print_context:
+ * @job: a printing #GtkSourcePrintJob.
+ * 
+ * Determines the #GnomePrintContext of the current job.  This
+ * function is only valid while printing.  Normally you would use this
+ * function to print in the margins set by
+ * gtk_source_print_job_set_margins() in a handler for the <link
+ * linkend="GtkSourcePrintJob-begin-page">&quot;begin_page&quot;</link>
+ * signal.
+ * 
+ * Return value: the current #GnomePrintContext.  The returned object
+ * is owned by @job.
+ **/
+GnomePrintContext *
+gtk_source_print_job_get_print_context (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+	g_return_val_if_fail (job->priv->printing, NULL);
+
+	return job->priv->print_ctxt;
+}
+
+/* ---- Header and footer (default implementation) */
+
+/* Most of this code taken from GLib's g_date_strftime() in gdate.c
+ * GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald */
+
+static gchar *
+strdup_strftime (const gchar *format, const struct tm *tm)
+{
+	gsize locale_format_len = 0;
+	gchar *locale_format;
+	gsize tmplen;
+	gchar *tmpbuf;
+	gsize tmpbufsize;
+	gchar *convbuf;
+	gsize convlen = 0;
+	GError *error = NULL;
+
+	g_return_val_if_fail (format != NULL, NULL);
+	g_return_val_if_fail (tm != NULL, NULL);
+
+	locale_format = g_locale_from_utf8 (format, -1, NULL, &locale_format_len, &error);
+
+	if (error)
+	{
+		g_warning (G_STRLOC "Error converting format to locale encoding: %s",
+			   error->message);
+		g_error_free (error);
+		
+		return NULL;
+	}
+
+	tmpbufsize = MAX (128, locale_format_len * 2);
+	while (TRUE)
+	{
+		tmpbuf = g_malloc (tmpbufsize);
+		
+		/* Set the first byte to something other than '\0', to be able to
+		 * recognize whether strftime actually failed or just returned "".
+		 */
+		tmpbuf[0] = '\1';
+		tmplen = strftime (tmpbuf, tmpbufsize, locale_format, tm);
+		
+		if (tmplen == 0 && tmpbuf[0] != '\0')
+		{
+			g_free (tmpbuf);
+			tmpbufsize *= 2;
+			
+			if (tmpbufsize > 65536)
+			{
+				g_warning (G_STRLOC "Maximum buffer size for strdup_strftime "
+					   "exceeded: giving up");
+				g_free (locale_format);
+				return NULL;
+			}
+		}
+		else
+			break;
+	}
+	g_free (locale_format);
+
+	convbuf = g_locale_to_utf8 (tmpbuf, tmplen, NULL, &convlen, &error);
+	g_free (tmpbuf);
+
+	if (error)
+	{
+		g_warning (G_STRLOC "Error converting results of strftime to UTF-8: %s",
+			   error->message);
+		g_error_free (error);
+		
+		return NULL;
+	}
+
+	return convbuf;
+}
+
+static gchar *
+evaluate_format_string (GtkSourcePrintJob *job, const gchar *format)
+{
+	GString *eval;
+	gchar *eval_str, *retval;
+	const struct tm *tm;
+	time_t now;
+	gunichar ch;
+	
+	/* get time */
+	time (&now);
+	tm = localtime (&now);
+
+	/* analyze format string and replace the codes we know */
+	eval = g_string_new_len (NULL, strlen (format));
+	ch = g_utf8_get_char (format);
+	while (ch != 0)
+	{
+		if (ch == '%')
+		{
+			format = g_utf8_next_char (format);
+			ch = g_utf8_get_char (format);
+			if (ch == 'N')
+				g_string_append_printf (eval, "%d", job->priv->page);
+			else if (ch == 'Q')
+				g_string_append_printf (eval, "%d", job->priv->page_count);
+			else
+			{
+				g_string_append_c (eval, '%');
+				g_string_append_unichar (eval, ch);
+			}
+		}
+		else
+			g_string_append_unichar (eval, ch);
+
+		format = g_utf8_next_char (format);
+		ch = g_utf8_get_char (format);
+	}
+
+	eval_str = g_string_free (eval, FALSE);
+	retval = strdup_strftime (eval_str, tm);
+	g_free (eval_str);
+
+	return retval;
+}
+
+static void
+print_header_footer_string (GtkSourcePrintJob *job,
+			    const gchar       *format,
+			    gdouble            x_align,
+			    gdouble            x,
+			    gdouble            y)
+{
+	PangoLayout *layout;
+	gchar *text;
+	gdouble width;
+	gdouble xx;
+	
+	width = job->priv->text_width + job->priv->numbers_width;
+	
+	text = evaluate_format_string (job, format);
+	if (text != NULL)
+	{
+		layout = pango_layout_new (job->priv->pango_context);
+		pango_layout_set_font_description (layout, job->priv->header_footer_font);
+		pango_layout_set_text (layout, text, -1);
+		
+		xx = x + x_align * (width - get_layout_width (layout));
+		gnome_print_moveto (job->priv->print_ctxt, xx, y);
+		show_first_layout_line (job->priv->print_ctxt, layout);
+		
+		g_free (text);
+		g_object_unref (layout);
+	}
+}
+
+static void 
+default_print_header (GtkSourcePrintJob *job,
+		      gdouble            x,
+		      gdouble            y)
+{
+	gdouble width;
+	gdouble yy;
+	gdouble ascent, descent;
+	
+	width = job->priv->text_width + job->priv->numbers_width;
+
+	get_font_ascent_descent (job, job->priv->header_footer_font, &ascent, &descent);
+
+	yy = y - ascent;
+
+	/* left format */
+	if (job->priv->header_format_left != NULL)
+		print_header_footer_string (job, job->priv->header_format_left, 0.0, x, yy);
+	
+	/* right format */
+	if (job->priv->header_format_right != NULL)
+		print_header_footer_string (job, job->priv->header_format_right, 1.0, x, yy);
+
+	/* center format */
+	if (job->priv->header_format_center != NULL)
+		print_header_footer_string (job, job->priv->header_format_center, 0.5, x, yy);
+
+	/* separator */
+	if (job->priv->header_separator)
+	{
+		yy = y - (SEPARATOR_SPACING * (ascent + descent));
+		gnome_print_setlinewidth (job->priv->print_ctxt, SEPARATOR_LINE_WIDTH);
+		gnome_print_moveto (job->priv->print_ctxt, x, yy);
+		gnome_print_lineto (job->priv->print_ctxt, x + width, yy);
+		gnome_print_stroke (job->priv->print_ctxt);
+	}
+}
+
+static void 
+default_print_footer (GtkSourcePrintJob *job,
+		      gdouble            x,
+		      gdouble            y)
+{
+	gdouble width;
+	gdouble yy;
+	gdouble ascent, descent;
+	
+	width = job->priv->text_width + job->priv->numbers_width;
+
+	get_font_ascent_descent (job, job->priv->header_footer_font, &ascent, &descent);
+
+	yy = y - job->priv->footer_height + descent;
+
+	/* left format */
+	if (job->priv->footer_format_left != NULL)
+		print_header_footer_string (job, job->priv->footer_format_left, 0.0, x, yy);
+	
+	/* right format */
+	if (job->priv->footer_format_right != NULL)
+		print_header_footer_string (job, job->priv->footer_format_right, 1.0, x, yy);
+
+	/* center format */
+	if (job->priv->footer_format_center != NULL)
+		print_header_footer_string (job, job->priv->footer_format_center, 0.5, x, yy);
+
+	/* separator */
+	if (job->priv->footer_separator)
+	{
+		yy = y - job->priv->footer_height +
+			(SEPARATOR_SPACING * (ascent + descent));
+		gnome_print_setlinewidth (job->priv->print_ctxt, SEPARATOR_LINE_WIDTH);
+		gnome_print_moveto (job->priv->print_ctxt, x, yy);
+		gnome_print_lineto (job->priv->print_ctxt, x + width, yy);
+		gnome_print_stroke (job->priv->print_ctxt);
+	}
+}
+
+/**
+ * gtk_source_print_job_set_print_header:
+ * @job: a #GtkSourcePrintJob.
+ * @setting: %TRUE if you want the header to be printed.
+ * 
+ * Sets whether you want to print a header in each page.  The default
+ * header consists of three pieces of text and an optional line
+ * separator, configurable with
+ * gtk_source_print_job_set_header_format().
+ *
+ * Note that by default the header format is unspecified, and if it's
+ * empty it will not be printed, regardless of this setting.
+ **/
+void 
+gtk_source_print_job_set_print_header (GtkSourcePrintJob *job,
+				       gboolean           setting)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	setting = (setting != FALSE);
+	
+	if (setting == job->priv->print_header)
+		return;
+	
+	job->priv->print_header = setting;
+
+	g_object_notify (G_OBJECT (job), "print_header");
+}
+
+/**
+ * gtk_source_print_job_get_print_header:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines if a header is set to be printed for each page.  A
+ * header will be printed if this function returns %TRUE
+ * <emphasis>and</emphasis> some format strings have been specified
+ * with gtk_source_print_job_set_header_format().
+ * 
+ * Return value: %TRUE if the header is set to be printed.
+ **/
+gboolean 
+gtk_source_print_job_get_print_header (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), FALSE);
+
+	return job->priv->print_header;
+}
+
+/**
+ * gtk_source_print_job_set_print_footer:
+ * @job: a #GtkSourcePrintJob.
+ * @setting: %TRUE if you want the footer to be printed.
+ * 
+ * Sets whether you want to print a footer in each page.  The default
+ * footer consists of three pieces of text and an optional line
+ * separator, configurable with
+ * gtk_source_print_job_set_footer_format().
+ *
+ * Note that by default the footer format is unspecified, and if it's
+ * empty it will not be printed, regardless of this setting.
+ **/
+void 
+gtk_source_print_job_set_print_footer (GtkSourcePrintJob *job,
+				       gboolean           setting)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	setting = (setting != FALSE);
+	
+	if (setting == job->priv->print_footer)
+		return;
+	
+	job->priv->print_footer = setting;
+
+	g_object_notify (G_OBJECT (job), "print_footer");
+}
+
+/**
+ * gtk_source_print_job_get_print_footer:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines if a footer is set to be printed for each page.  A
+ * footer will be printed if this function returns %TRUE
+ * <emphasis>and</emphasis> some format strings have been specified
+ * with gtk_source_print_job_set_footer_format().
+ * 
+ * Return value: %TRUE if the footer is set to be printed.
+ **/
+gboolean 
+gtk_source_print_job_get_print_footer (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), FALSE);
+
+	return job->priv->print_footer;
+}
+
+/**
+ * gtk_source_print_job_set_header_footer_font_desc:
+ * @job: a #GtkSourcePrintJob.
+ * @desc: the #PangoFontDescription for the font to be used in headers and footers, or %NULL.
+ * 
+ * Sets the font for printing headers and footers.  If %NULL is
+ * supplied, the default font (i.e. the one being used for the text)
+ * will be used instead.
+ **/
+void 
+gtk_source_print_job_set_header_footer_font_desc (GtkSourcePrintJob    *job,
+						  PangoFontDescription *desc)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+	
+	if (desc)
+		desc = pango_font_description_copy (desc);
+	if (job->priv->header_footer_font != NULL)
+		pango_font_description_free (job->priv->header_footer_font);
+	job->priv->header_footer_font = desc;
+	g_object_freeze_notify (G_OBJECT (job));
+	g_object_notify (G_OBJECT (job), "header_footer_font");
+	g_object_notify (G_OBJECT (job), "header_footer_font_desc");
+	g_object_thaw_notify (G_OBJECT (job));
+}
+
+/**
+ * gtk_source_print_job_set_header_footer_font:
+ * @job: a #GtkSourcePrintJob.
+ * @font_name: the full name of the font to be used in headers and footers, or %NULL.
+ * 
+ * Sets the font for printing headers and footers.  If %NULL is
+ * supplied, the default font (i.e. the one being used for the text)
+ * will be used instead.
+ *
+ * Note that @font_name is a #GnomeFont name not a Pango font
+ * description string. This function is deprecated since #GnomeFont is
+ * no longer used when implementing printing for GtkSourceView; you
+ * should use gtk_source_print_job_set_header_footer_font_desc() instead.
+ **/
+void 
+gtk_source_print_job_set_header_footer_font (GtkSourcePrintJob *job,
+					     const gchar       *font_name)
+{
+	PangoFontDescription *desc;
+	
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	if (font_name != NULL)
+	{
+		desc = font_description_from_gnome_font_name (font_name);
+		if (desc)
+		{
+			gtk_source_print_job_set_header_footer_font_desc (job, desc);
+			pango_font_description_free (desc);
+		}
+	}
+	else
+		gtk_source_print_job_set_header_footer_font_desc (job, NULL);
+}
+
+/**
+ * gtk_source_print_job_get_header_footer_font_desc:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the font to be used for the header and footer.  This function
+ * might return %NULL if a specific font has not been set.
+ * 
+ * Return value: the header and footer font description or %NULL. This value is
+ * owned by the job and must not be modified or freed.
+ **/
+PangoFontDescription *
+gtk_source_print_job_get_header_footer_font_desc (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+
+	return job->priv->header_footer_font;
+}
+
+/**
+ * gtk_source_print_job_get_header_footer_font:
+ * @job: a #GtkSourcePrintJob.
+ * 
+ * Determines the font to be used for the header and footer.  The
+ * returned string is of the form &quot;Fontfamily Style Size&quot;,
+ * for example &quot;Monospace Regular 10.0&quot;.  The returned value
+ * should be freed when no longer needed.  This function might return
+ * %NULL if a specific font has not been set.
+ * 
+ * Note that the result is a #GnomeFont name not a Pango font
+ * description string. This function is deprecated since #GnomeFont is
+ * no longer used when implementing printing for GtkSourceView; you
+ * should use gtk_source_print_job_get_header_footer_font_desc() instead.
+ *
+ * Return value: a newly allocated string with the name of the current
+ * header and footer font, or %NULL.
+ **/
+gchar *
+gtk_source_print_job_get_header_footer_font (GtkSourcePrintJob *job)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_PRINT_JOB (job), NULL);
+
+	if (job->priv->header_footer_font != NULL)
+		return font_description_to_gnome_font_name (job->priv->header_footer_font);
+	else
+		return NULL;
+}
+
+/**
+ * gtk_source_print_job_set_header_format:
+ * @job: a #GtkSourcePrintJob.
+ * @left: a format string to print on the left of the header.
+ * @center: a format string to print on the center of the header.
+ * @right: a format string to print on the right of the header.
+ * @separator: %TRUE if you want a separator line to be printed.
+ * 
+ * Sets strftime like header format strings, to be printed on the
+ * left, center and right of the top of each page.  The strings may
+ * include strftime(3) codes which will be expanded at print time.
+ * All strftime() codes are accepted, with the addition of %N for the
+ * page number and %Q for the page count.
+ *
+ * @separator specifies if a solid line should be drawn to separate
+ * the header from the document text.
+ *
+ * If %NULL is given for any of the three arguments, that particular
+ * string will not be printed.  For the header to be printed, in
+ * addition to specifying format strings, you need to enable header
+ * printing with gtk_source_print_job_set_print_header().
+ **/
+void 
+gtk_source_print_job_set_header_format (GtkSourcePrintJob *job,
+					const gchar       *left,
+					const gchar       *center,
+					const gchar       *right,
+					gboolean           separator)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	/* FIXME: validate given strings? */
+	g_free (job->priv->header_format_left);
+	g_free (job->priv->header_format_center);
+	g_free (job->priv->header_format_right);
+	job->priv->header_format_left = g_strdup (left);
+	job->priv->header_format_center = g_strdup (center);
+	job->priv->header_format_right = g_strdup (right);
+	job->priv->header_separator = separator;
+}
+
+/**
+ * gtk_source_print_job_set_footer_format:
+ * @job: a #GtkSourcePrintJob.
+ * @left: a format string to print on the left of the footer.
+ * @center: a format string to print on the center of the footer.
+ * @right: a format string to print on the right of the footer.
+ * @separator: %TRUE if you want a separator line to be printed.
+ * 
+ * Like gtk_source_print_job_set_header_format(), but for the footer.
+ **/
+void 
+gtk_source_print_job_set_footer_format (GtkSourcePrintJob *job,
+					const gchar       *left,
+					const gchar       *center,
+					const gchar       *right,
+					gboolean           separator)
+{
+	g_return_if_fail (GTK_IS_SOURCE_PRINT_JOB (job));
+	g_return_if_fail (!job->priv->printing);
+
+	/* FIXME: validate given strings? */
+	g_free (job->priv->footer_format_left);
+	g_free (job->priv->footer_format_center);
+	g_free (job->priv->footer_format_right);
+	job->priv->footer_format_left = g_strdup (left);
+	job->priv->footer_format_center = g_strdup (center);
+	job->priv->footer_format_right = g_strdup (right);
+	job->priv->footer_separator = separator;
+}

Added: trunk/Tomboy/Addins/PrintNotes/gtksourceprintjob.h
==============================================================================
--- (empty file)
+++ trunk/Tomboy/Addins/PrintNotes/gtksourceprintjob.h	Mon Sep 15 16:03:01 2008
@@ -0,0 +1,164 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
+/*
+ * gtksourceprintjob.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2003  Gustavo GirÃldez
+ *
+ * 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. 
+ */
+ 
+#ifndef __GTK_SOURCE_PRINT_JOB_H__
+#define __GTK_SOURCE_PRINT_JOB_H__
+
+#include <libgnomeprint/gnome-print-config.h>
+#include <libgnomeprint/gnome-print-job.h>
+#include <gtk/gtktextbuffer.h>
+//#include <gtksourceview/gtksourceview.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_PRINT_JOB            (gtk_source_print_job_get_type ())
+#define GTK_SOURCE_PRINT_JOB(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_PRINT_JOB, GtkSourcePrintJob))
+#define GTK_SOURCE_PRINT_JOB_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_PRINT_JOB, GtkSourcePrintJobClass))
+#define GTK_IS_SOURCE_PRINT_JOB(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_PRINT_JOB))
+#define GTK_IS_SOURCE_PRINT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_PRINT_JOB))
+#define GTK_SOURCE_PRINT_JOB_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_PRINT_JOB, GtkSourcePrintJobClass))
+
+typedef struct _GtkSourcePrintJob         GtkSourcePrintJob;
+typedef struct _GtkSourcePrintJobClass    GtkSourcePrintJobClass;
+typedef struct _GtkSourcePrintJobPrivate  GtkSourcePrintJobPrivate;
+
+struct _GtkSourcePrintJob
+{
+	GObject parent_instance;
+
+	GtkSourcePrintJobPrivate *priv;
+};
+
+struct _GtkSourcePrintJobClass
+{
+	GObjectClass parent_class;
+
+	void   (* begin_page)    (GtkSourcePrintJob  *job);
+	void   (* finished)      (GtkSourcePrintJob  *job);
+};
+
+/* we want the idle handler to run before the view validation, but do
+ * not interfere with ui updates */
+#define GTK_SOURCE_PRINT_JOB_PRIORITY ((GDK_PRIORITY_REDRAW + GTK_TEXT_VIEW_PRIORITY_VALIDATE) / 2)
+
+GType              gtk_source_print_job_get_type               (void) G_GNUC_CONST;
+
+/* constructor functions */
+GtkSourcePrintJob *gtk_source_print_job_new                    (GnomePrintConfig  *config);
+GtkSourcePrintJob *gtk_source_print_job_new_with_buffer        (GnomePrintConfig  *config,
+								GtkTextBuffer   *buffer);
+/* print job basic configuration */
+void               gtk_source_print_job_set_config             (GtkSourcePrintJob *job,
+								GnomePrintConfig  *config);
+GnomePrintConfig  *gtk_source_print_job_get_config             (GtkSourcePrintJob *job);
+void               gtk_source_print_job_set_buffer             (GtkSourcePrintJob *job,
+								GtkTextBuffer   *buffer);
+GtkTextBuffer   *gtk_source_print_job_get_buffer             (GtkSourcePrintJob *job);
+
+/* print job layout and style configuration */
+//void               gtk_source_print_job_setup_from_view        (GtkSourcePrintJob *job,
+//								GtkSourceView     *view);
+void               gtk_source_print_job_set_tabs_width         (GtkSourcePrintJob *job,
+								guint              tabs_width);
+guint              gtk_source_print_job_get_tabs_width         (GtkSourcePrintJob *job);
+void               gtk_source_print_job_set_wrap_mode          (GtkSourcePrintJob *job,
+								GtkWrapMode        wrap);
+GtkWrapMode        gtk_source_print_job_get_wrap_mode          (GtkSourcePrintJob *job);
+void               gtk_source_print_job_set_highlight          (GtkSourcePrintJob *job,
+								gboolean           highlight);
+gboolean           gtk_source_print_job_get_highlight          (GtkSourcePrintJob *job);
+void               gtk_source_print_job_set_font               (GtkSourcePrintJob *job,
+								const gchar       *font_name);
+gchar             *gtk_source_print_job_get_font               (GtkSourcePrintJob *job);
+void               gtk_source_print_job_set_numbers_font       (GtkSourcePrintJob *job,
+								const gchar       *font_name);
+gchar             *gtk_source_print_job_get_numbers_font       (GtkSourcePrintJob *job);
+void               gtk_source_print_job_set_print_numbers      (GtkSourcePrintJob *job,
+								guint              interval);
+guint              gtk_source_print_job_get_print_numbers      (GtkSourcePrintJob *job);
+void               gtk_source_print_job_set_text_margins       (GtkSourcePrintJob *job,
+								gdouble            top,
+								gdouble            bottom,
+								gdouble            left,
+								gdouble            right);
+void               gtk_source_print_job_get_text_margins       (GtkSourcePrintJob *job,
+								gdouble           *top,
+								gdouble           *bottom,
+								gdouble           *left,
+								gdouble           *right);
+
+/* New non-deprecated font-setting API */
+void                   gtk_source_print_job_set_font_desc               (GtkSourcePrintJob    *job,
+									 PangoFontDescription *desc);
+PangoFontDescription  *gtk_source_print_job_get_font_desc               (GtkSourcePrintJob    *job);
+void                   gtk_source_print_job_set_numbers_font_desc       (GtkSourcePrintJob    *job,
+									 PangoFontDescription *desc);
+PangoFontDescription  *gtk_source_print_job_get_numbers_font_desc       (GtkSourcePrintJob    *job);
+void                   gtk_source_print_job_set_header_footer_font_desc (GtkSourcePrintJob    *job,
+									 PangoFontDescription *desc);
+PangoFontDescription  *gtk_source_print_job_get_header_footer_font_desc (GtkSourcePrintJob    *job);
+
+/* printing operations */
+GnomePrintJob     *gtk_source_print_job_print                  (GtkSourcePrintJob *job);
+GnomePrintJob     *gtk_source_print_job_print_range            (GtkSourcePrintJob *job,
+								const GtkTextIter *start,
+								const GtkTextIter *end);
+
+/* asynchronous printing */
+gboolean           gtk_source_print_job_print_range_async      (GtkSourcePrintJob *job,
+								const GtkTextIter *start,
+								const GtkTextIter *end);
+void               gtk_source_print_job_cancel                 (GtkSourcePrintJob *job);
+GnomePrintJob     *gtk_source_print_job_get_print_job          (GtkSourcePrintJob *job);
+
+/* information for asynchronous ops and headers and footers callback */
+guint              gtk_source_print_job_get_page               (GtkSourcePrintJob *job);
+guint              gtk_source_print_job_get_page_count         (GtkSourcePrintJob *job);
+GnomePrintContext *gtk_source_print_job_get_print_context      (GtkSourcePrintJob *job);
+
+
+/* header and footer */
+void               gtk_source_print_job_set_print_header       (GtkSourcePrintJob *job,
+								gboolean           setting);
+gboolean           gtk_source_print_job_get_print_header       (GtkSourcePrintJob *job);
+void               gtk_source_print_job_set_print_footer       (GtkSourcePrintJob *job,
+								gboolean           setting);
+gboolean           gtk_source_print_job_get_print_footer       (GtkSourcePrintJob *job);
+void               gtk_source_print_job_set_header_footer_font (GtkSourcePrintJob *job,
+								const gchar       *font_name);
+gchar             *gtk_source_print_job_get_header_footer_font (GtkSourcePrintJob *job);
+/* format strings are strftime like */
+void               gtk_source_print_job_set_header_format      (GtkSourcePrintJob *job,
+								const gchar       *left,
+								const gchar       *center,
+								const gchar       *right,
+								gboolean           separator);
+void               gtk_source_print_job_set_footer_format      (GtkSourcePrintJob *job,
+								const gchar       *left,
+								const gchar       *center,
+								const gchar       *right,
+								gboolean           separator);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_PRINT_JOB_H__ */

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Mon Sep 15 16:03:01 2008
@@ -48,6 +48,8 @@
 ATK_MINIMUM_VERSION=1.2.4
 
 PKG_CHECK_MODULES(LIBTOMBOY, 
+		  libgnomeprint-2.2
+		  libgnomeprintui-2.2
 		  gdk-2.0 >= $GDK20_MINIMUM_VERSION
 		  gtk+-2.0 >= $GTK20_MINIMUM_VERSION
 		  atk >= $ATK_MINIMUM_VERSION)

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Mon Sep 15 16:03:01 2008
@@ -31,6 +31,8 @@
 Tomboy/Addins/NoteOfTheDay/NoteOfTheDay.addin.xml
 Tomboy/Addins/PrintNotes/PrintNotesNoteAddin.cs
 Tomboy/Addins/PrintNotes/PrintNotes.addin.xml
+Tomboy/Addins/PrintNotes/gedit-print.c
+Tomboy/Addins/PrintNotes/gtksourceprintjob.c
 Tomboy/Addins/Sketching/SketchingNoteAddin.cs
 Tomboy/Addins/SshSyncService/SshSyncServiceAddin.cs
 Tomboy/Addins/SshSyncService/SshSyncService.addin.xml



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