1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * print.c: Printing routines for Gnumeric
7 * Miguel de Icaza (miguel@gnu.org)
8 * Morten Welinder (terra@gnome.org)
9 * Andreas J. Guelzow (aguelzow@pyrshep.ca)
11 * Copyright 2007, Andreas J. Guelzow, All Rights Reserved
12 * Copyright (C) 2007-2009 Morten Welinder (terra@gnome.org)
14 * Handles printing of Sheets.
16 #include <gnumeric-config.h>
17 #include "print-cell.h"
24 #include "sheet-object.h"
25 #include "sheet-object-impl.h"
26 #include "selection.h"
28 #include "workbook-control.h"
30 #include "command-context.h"
32 #include "gnumeric-conf.h"
33 #include "libgnumeric.h"
37 #include "print-info.h"
38 #include "application.h"
39 #include "sheet-style.h"
41 #include "parse-util.h"
42 #include "style-font.h"
43 #include "gnumeric-conf.h"
44 #include <goffice/goffice.h>
47 #include <gsf/gsf-meta-names.h>
49 #include <glib/gi18n-lib.h>
50 #include <glib/gstdio.h>
58 /* see bug #533795. */
59 #define PREVIEW_VIA_PDF
62 /* The following structure is used by the printing system */
69 GtkWidget
*button_all_sheets
, *button_selected_sheet
,
71 GtkWidget
*button_selection
, *button_ignore_printarea
, *button_print_hidden_sheets
;
72 GtkWidget
*button_ignore_page_breaks
;
73 GtkWidget
*spin_from
, *spin_to
;
77 guint last_pagination
;
78 GnmPrintHFRenderInfo
*hfi
;
87 gboolean ignore_printarea
;
88 GArray
*column_pagination
;
89 GArray
*row_pagination
;
111 gnm_print_range_get_type (void)
113 static GType etype
= 0;
115 static GEnumValue
const values
[] = {
116 { GNM_PRINT_SAVED_INFO
,
117 "GNM_PRINT_SAVED_INFO",
119 { GNM_PRINT_ACTIVE_SHEET
,
120 "GNM_PRINT_ACTIVE_SHEET",
122 { GNM_PRINT_ALL_SHEETS
,
123 "GNM_PRINT_ALL_SHEETS",
125 { GNM_PRINT_ALL_SHEETS_INCLUDING_HIDDEN
,
126 "GNM_PRINT_ALL_SHEETS_INCLUDING_HIDDEN",
127 "all-sheets-incl-hidden"},
128 { GNM_PRINT_SHEET_RANGE
,
129 "GNM_PRINT_SHEET_RANGE",
131 { GNM_PRINT_SHEET_SELECTION
,
132 "GNM_PRINT_SHEET_SELECTION",
134 { GNM_PRINT_IGNORE_PRINTAREA
,
135 "GNM_PRINT_IGNORE_PRINTAREA",
136 "ignore-print-area"},
137 { GNM_PRINT_SHEET_SELECTION_IGNORE_PRINTAREA
,
138 "GNM_PRINT_SHEET_SELECTION_IGNORE_PRINTAREA",
139 "sheet-selection-ignore-printarea"},
142 etype
= g_enum_register_static ("GnmPrintRange", values
);
148 static PrintingInstance
*
149 printing_instance_new (void)
151 PrintingInstance
* pi
= g_new0 (PrintingInstance
,1);
152 pi
->hfi
= gnm_print_hf_render_info_new ();
160 sheet_print_info_free (gpointer data
)
162 SheetPrintInfo
*spi
= data
;
164 g_array_unref (spi
->column_pagination
);
165 g_array_unref (spi
->row_pagination
);
170 printing_instance_delete (PrintingInstance
*pi
)
172 g_list_free_full (pi
->gnmSheets
, sheet_print_info_free
);
173 gnm_print_hf_render_info_destroy (pi
->hfi
);
175 gtk_widget_destroy (pi
->progress
);
181 gnm_print_sheet_objects (cairo_t
*cr
,
184 double base_x
, double base_y
)
186 GSList
*ptr
, *objects
;
187 double width
, height
;
189 g_return_if_fail (IS_SHEET (sheet
));
190 g_return_if_fail (cr
!= NULL
);
191 g_return_if_fail (range
!= NULL
);
195 height
= sheet_row_get_distance_pts (sheet
, range
->start
.row
,
197 width
= sheet_col_get_distance_pts (sheet
,
198 range
->start
.col
, range
->end
.col
+ 1);
200 if (sheet
->text_is_rtl
)
202 base_x
- width
, base_y
,
210 objects
= g_slist_reverse (g_slist_copy (sheet
->sheet_objects
));
212 for (ptr
= objects
; ptr
; ptr
= ptr
->next
) {
213 SheetObject
*so
= GNM_SO (ptr
->data
);
214 GnmRange
const *r
= &so
->anchor
.cell_bound
;
216 if (!sheet_object_can_print (so
) ||
217 !range_overlap (range
, &so
->anchor
.cell_bound
))
221 /* move to top left */
222 if (sheet
->text_is_rtl
) {
224 switch (so
->anchor
.mode
) {
225 case GNM_SO_ANCHOR_ABSOLUTE
:
226 tr_x
= base_x
- 0.5; /* because of leading gridline */
229 case GNM_SO_ANCHOR_ONE_CELL
:
231 - sheet_col_get_distance_pts (sheet
, 0, r
->start
.col
+1)
232 + sheet_col_get_distance_pts (sheet
, 0, range
->start
.col
);
234 + sheet_row_get_distance_pts (sheet
, 0, r
->start
.row
)
235 - sheet_row_get_distance_pts (sheet
, 0, range
->start
.row
);
239 - sheet_col_get_distance_pts (sheet
, 0, r
->end
.col
+1)
240 + sheet_col_get_distance_pts (sheet
, 0, range
->start
.col
);
242 + sheet_row_get_distance_pts (sheet
, 0, r
->start
.row
)
243 - sheet_row_get_distance_pts (sheet
, 0, range
->start
.row
);
246 cairo_translate (cr
, tr_x
, tr_y
);
248 cairo_translate (cr
, (so
->anchor
.mode
== GNM_SO_ANCHOR_ABSOLUTE
)?
249 base_x
+ 0.5: base_x
+ 0.5
250 + sheet_col_get_distance_pts (sheet
, 0, r
->start
.col
)
251 - sheet_col_get_distance_pts (sheet
, 0,
253 (so
->anchor
.mode
== GNM_SO_ANCHOR_ABSOLUTE
)?
254 base_y
+ 0.5: base_y
+ 0.5
255 + sheet_row_get_distance_pts (sheet
, 0, r
->start
.row
)
256 - sheet_row_get_distance_pts (sheet
, 0,
259 sheet_object_draw_cairo (so
, (gpointer
)cr
, sheet
->text_is_rtl
);
263 g_slist_free (objects
);
269 print_page_cells (G_GNUC_UNUSED GtkPrintContext
*context
,
270 G_GNUC_UNUSED PrintingInstance
* pi
,
271 cairo_t
*cr
, Sheet
const *sheet
, GnmRange
*range
,
272 double base_x
, double base_y
)
274 gnm_gtk_print_cell_range (cr
, sheet
, range
,
276 (GnmPrintInformation
const *) sheet
->print_info
);
277 gnm_print_sheet_objects (cr
, sheet
, range
, base_x
, base_y
);
281 print_header_gtk (GtkPrintContext
*context
, cairo_t
*cr
,
282 double x
, double y
, double w
, double h
,
284 PangoFontDescription
*desc
)
290 cairo_rectangle (cr
, x
, y
, w
, h
);
291 cairo_set_source_rgb (cr
, 0.8, 0.8, 0.8);
294 cairo_set_source_rgb (cr
, 0., 0., 0.);
295 layout
= gtk_print_context_create_pango_layout (context
);
296 pango_layout_set_font_description (layout
, desc
);
298 pango_layout_set_text (layout
, name
, -1);
299 pango_layout_set_width (layout
, w
);
300 pango_layout_set_alignment (layout
, PANGO_ALIGN_CENTER
);
302 pango_layout_get_size (layout
, NULL
, &layout_height
);
303 text_height
= (gdouble
)layout_height
/ PANGO_SCALE
;
305 cairo_move_to (cr
, x
+ w
/2, y
+ (h
- text_height
) / 2);
306 pango_cairo_show_layout (cr
, layout
);
308 g_object_unref (layout
);
313 print_page_col_headers (GtkPrintContext
*context
,
314 G_GNUC_UNUSED PrintingInstance
* pi
,
315 cairo_t
*cr
, Sheet
const *sheet
, GnmRange
*range
,
316 double row_header_width
, double col_header_height
)
318 int start_col
, end_col
;
321 PangoFontDescription
*desc
;
324 g_return_if_fail (IS_SHEET (sheet
));
325 g_return_if_fail (range
!= NULL
);
326 g_return_if_fail (range
->start
.col
<= range
->end
.col
);
328 hscale
= sheet
->display_formulas
? 2 : 1;
329 desc
= pango_font_description_from_string ("sans 12");
331 start_col
= range
->start
.col
;
332 end_col
= range
->end
.col
;
334 x
= (row_header_width
+ GNM_COL_MARGIN
) * (sheet
->text_is_rtl
? -1. : 1.);
336 for (col
= start_col
; col
<= end_col
; col
++) {
337 ColRowInfo
const *ci
= sheet_col_get_info (sheet
, col
);
340 if (sheet
->text_is_rtl
)
341 x
-= ci
->size_pts
* hscale
;
343 print_header_gtk (context
, cr
,
345 ci
->size_pts
* hscale
- 1,
346 col_header_height
- 0.5,
347 col_name (col
), desc
);
349 if (!sheet
->text_is_rtl
)
350 x
+= ci
->size_pts
* hscale
;
354 pango_font_description_free (desc
);
358 print_page_row_headers (GtkPrintContext
*context
,
359 G_GNUC_UNUSED PrintingInstance
* pi
,
360 cairo_t
*cr
, Sheet
const *sheet
, GnmRange
*range
,
361 double row_header_width
, double col_header_height
)
363 int start_row
, end_row
;
366 PangoFontDescription
*desc
;
368 g_return_if_fail (IS_SHEET (sheet
));
369 g_return_if_fail (range
!= NULL
);
370 g_return_if_fail (range
->start
.row
<= range
->end
.row
);
372 desc
= pango_font_description_from_string ("sans 12");
374 start_row
= range
->start
.row
;
375 end_row
= range
->end
.row
;
377 if (sheet
->text_is_rtl
)
378 x
= - (row_header_width
- 0.5);
380 for (row
= start_row
, y
= col_header_height
; row
<= end_row
; row
++) {
381 ColRowInfo
const *ri
= sheet_row_get_info (sheet
, row
);
384 print_header_gtk (context
, cr
,
386 row_header_width
- 0.5,
388 row_name (row
), desc
);
393 pango_font_description_free (desc
);
397 ensure_decoration_layout (GtkPrintContext
*context
)
403 layout
= gtk_print_context_create_pango_layout (context
);
404 style
= gnm_conf_get_printer_decoration_font ();
405 font
= gnm_style_get_font
406 (style
, pango_layout_get_context (layout
));
407 pango_layout_set_font_description (layout
, font
->go
.font
->desc
);
408 gnm_style_unref (style
);
416 * @pj: printing context
421 * Print a header/footer line.
423 * Position at y, and clip to rectangle.
426 print_hf_element (GtkPrintContext
*context
, cairo_t
*cr
,
427 G_GNUC_UNUSED Sheet
const *sheet
,
429 PangoAlignment side
, gdouble width
, gboolean align_bottom
,
430 GnmPrintHFRenderInfo
*hfi
)
434 gdouble text_height
= 0.;
440 text
= gnm_print_hf_format_render (format
, hfi
, HF_RENDER_PRINT
);
445 layout
= ensure_decoration_layout (context
);
447 pango_layout_set_text (layout
, text
, -1);
448 pango_layout_set_width (layout
, width
* PANGO_SCALE
);
449 pango_layout_set_alignment (layout
, side
);
452 gint layout_height
= 0;
453 pango_layout_get_size (layout
, NULL
, &layout_height
);
454 text_height
= (gdouble
)layout_height
/ PANGO_SCALE
;
457 cairo_move_to (cr
, 0., - text_height
);
458 pango_cairo_show_layout (cr
, layout
);
460 g_object_unref (layout
);
466 * @hf: header/footer descriptor
467 * @align_bottom: vertical position (whether to print above or below
468 * @width: width of header line
470 * Print a header/footer line.
474 print_hf_line (GtkPrintContext
*context
, cairo_t
*cr
, Sheet
const *sheet
,
475 GnmPrintHF
const *hf
, gboolean align_bottom
, gdouble width
, GnmPrintHFRenderInfo
*hfi
)
477 print_hf_element (context
, cr
, sheet
, hf
->left_format
, PANGO_ALIGN_LEFT
, width
, align_bottom
, hfi
);
478 print_hf_element (context
, cr
, sheet
, hf
->middle_format
, PANGO_ALIGN_CENTER
, width
, align_bottom
, hfi
);
479 print_hf_element (context
, cr
, sheet
, hf
->right_format
, PANGO_ALIGN_RIGHT
, width
, align_bottom
, hfi
);
486 * @pj: printing context
487 * @gsr: the page information
489 * Excel prints repeated rows like this: Pages up to and including the page
490 * where the first of the repeated rows "naturally" occurs are printed in
491 * the normal way. On subsequent pages, repated rows are printed before the
495 print_page (G_GNUC_UNUSED GtkPrintOperation
*operation
,
496 GtkPrintContext
*context
,
497 PrintingInstance
* pi
,
500 Sheet
*sheet
= gsr
->sheet
;
501 GnmPrintInformation
*pinfo
= sheet
->print_info
;
502 gdouble print_height
, print_width
;
503 gdouble main_height
, main_width
;
504 gdouble header
, footer
, left
, right
;
505 gdouble edge_to_below_header
, edge_to_above_footer
;
510 gdouble col_header_height
= 0.;
511 gdouble row_header_width
= 0.;
512 gdouble rep_row_height
= 0.;
513 gdouble rep_col_width
= 0.;
514 gdouble dir
= (sheet
->text_is_rtl
? -1. : 1.);
515 GnmRange r_repeating_intersect
;
517 px
= pinfo
->scaling
.percentage
.x
/ 100.;
518 py
= pinfo
->scaling
.percentage
.y
/ 100.;
525 cr
= gtk_print_context_get_cairo_context (context
);
526 print_info_get_margins (pinfo
, &header
, &footer
, &left
, &right
,
527 &edge_to_below_header
, &edge_to_above_footer
);
529 if (sheet
->print_info
->print_titles
) {
530 col_header_height
= sheet
->rows
.default_style
.size_pts
;
531 row_header_width
= sheet
->cols
.default_style
.size_pts
;
534 width
= gtk_print_context_get_width (context
);
535 height
= print_info_get_paper_height (pinfo
,GTK_UNIT_POINTS
)
536 - edge_to_below_header
- edge_to_above_footer
;
538 main_height
= sheet_row_get_distance_pts (sheet
, gsr
->range
.start
.row
,
539 gsr
->range
.end
.row
+ 1);
540 main_width
= sheet_col_get_distance_pts (sheet
, gsr
->range
.start
.col
,
541 gsr
->range
.end
.col
+ 1);
542 if (gsr
->n_rep_rows
> 0)
543 rep_row_height
= sheet_row_get_distance_pts
544 (sheet
, gsr
->first_rep_rows
,
545 gsr
->first_rep_rows
+ gsr
->n_rep_rows
);
546 if (gsr
->n_rep_cols
> 0)
547 rep_col_width
= sheet_col_get_distance_pts
548 (sheet
, gsr
->first_rep_cols
,
549 gsr
->first_rep_cols
+ gsr
->n_rep_cols
);
550 if ((gsr
->n_rep_rows
> 0) || (gsr
->n_rep_cols
> 0)) {
551 range_init (&r_repeating_intersect
, gsr
->first_rep_cols
, gsr
->first_rep_rows
,
552 gsr
->first_rep_cols
+ gsr
->n_rep_cols
- 1,
553 gsr
->first_rep_rows
+ gsr
->n_rep_rows
- 1);
556 print_height
= main_height
+ col_header_height
+ rep_row_height
;
557 print_width
= main_width
+ row_header_width
+ rep_col_width
;
559 /* printing header */
561 if (edge_to_below_header
> header
) {
563 print_hf_line (context
, cr
, sheet
, pinfo
->header
,
564 FALSE
, width
, pi
->hfi
);
568 /* printing footer */
570 if (edge_to_above_footer
> footer
) {
572 cairo_translate (cr
, 0, height
+ (edge_to_below_header
- header
) + (edge_to_above_footer
- footer
));
573 print_hf_line (context
, cr
, sheet
, pinfo
->footer
, TRUE
, width
,
578 /* setting up content area */
580 cairo_translate (cr
, sheet
->text_is_rtl
? width
: 0, edge_to_below_header
- header
);
582 if (sheet
->sheet_type
== GNM_SHEET_OBJECT
) {
583 SheetObject
*so
= sheet
->sheet_objects
584 ? sheet
->sheet_objects
->data
587 cairo_scale (cr
, px
, py
);
588 sheet_object_draw_cairo_sized (so
, cr
, width
, height
);
592 if (pinfo
->center_horizontally
== 1 || pinfo
->center_vertically
== 1) {
596 if (pinfo
->center_horizontally
== 1)
597 shift_x
= (width
- print_width
* px
)/2;
598 if (pinfo
->center_vertically
== 1)
599 shift_y
= (height
- print_height
* py
)/2;
600 cairo_translate (cr
, dir
* shift_x
, shift_y
);
602 cairo_scale (cr
, px
, py
);
604 /* printing column and row headers */
606 if (sheet
->print_info
->print_titles
) {
608 if (gsr
->n_rep_cols
> 0) {
609 print_page_col_headers (context
, pi
, cr
, sheet
,
610 &r_repeating_intersect
,
611 row_header_width
, col_header_height
);
612 cairo_translate (cr
, dir
* rep_col_width
, 0 );
614 print_page_col_headers (context
, pi
, cr
, sheet
, &gsr
->range
,
615 row_header_width
, col_header_height
);
618 if (gsr
->n_rep_rows
> 0) {
619 print_page_row_headers (context
, pi
, cr
, sheet
,
620 &r_repeating_intersect
,
621 row_header_width
, col_header_height
);
622 cairo_translate (cr
, 0, rep_row_height
);
624 print_page_row_headers (context
, pi
, cr
, sheet
, &gsr
->range
,
625 row_header_width
, col_header_height
);
627 cairo_translate (cr
, dir
* row_header_width
, col_header_height
);
630 /* printing repeated row/col intersect */
632 if ((gsr
->n_rep_rows
> 0) && (gsr
->n_rep_cols
> 0)) {
633 print_page_cells (context
, pi
, cr
, sheet
,
634 &r_repeating_intersect
,
635 dir
* GNM_COL_MARGIN
, -GNM_ROW_MARGIN
);
638 /* printing repeated rows */
640 if (gsr
->n_rep_rows
> 0) {
642 range_init (&r
, gsr
->range
.start
.col
, gsr
->first_rep_rows
,
643 gsr
->range
.end
.col
, gsr
->first_rep_rows
+ gsr
->n_rep_rows
- 1);
645 if (gsr
->n_rep_cols
> 0)
646 cairo_translate (cr
, dir
* rep_col_width
, 0 );
647 print_page_cells (context
, pi
, cr
, sheet
, &r
,
648 dir
* GNM_COL_MARGIN
, -GNM_ROW_MARGIN
);
650 cairo_translate (cr
, 0, rep_row_height
);
653 /* printing repeated cols */
655 if (gsr
->n_rep_cols
> 0) {
657 range_init (&r
, gsr
->first_rep_cols
, gsr
->range
.start
.row
,
658 gsr
->first_rep_cols
+ gsr
->n_rep_cols
- 1, gsr
->range
.end
.row
);
659 print_page_cells (context
, pi
, cr
, sheet
, &r
,
660 dir
* GNM_COL_MARGIN
, -GNM_ROW_MARGIN
);
661 cairo_translate (cr
, dir
* rep_col_width
, 0 );
664 /* printing page content */
666 print_page_cells (context
, pi
, cr
, sheet
, &gsr
->range
,
667 dir
* GNM_COL_MARGIN
, -GNM_ROW_MARGIN
);
675 * Computes number of rows or columns that fit in @usable starting
676 * at index @start and limited to index @end
679 compute_group (Sheet
const *sheet
,
680 int start
, int end
, double usable
,
681 ColRowInfo
const *(get_info
)(Sheet
const *sheet
, int const p
))
683 double size_pts
= 1.; /* The initial grid line */
686 for (idx
= start
; idx
<= end
; idx
++, count
++) {
687 ColRowInfo
const *info
= (*get_info
) (sheet
, idx
);
689 size_pts
+= info
->size_pts
;
690 if (size_pts
> usable
)
695 /* FIXME : Find a way to inform the user that one of the rows/cols does
700 g_warning (_("Even one cell is too large for this page."));
702 /* If we do not return at least one we are going into an infinite loop! */
710 adjust_repetition (Sheet
const *sheet
,
715 gint
*first_rep_used
,
717 gdouble
*repeating_used
,
718 double (sheet_get_distance_pts
) (Sheet
const *sheet
, int from
, int to
))
721 *first_rep_used
= first_rep
;
722 if (i
- first_rep
< n_rep
) {
723 *n_rep_used
= i
- first_rep
;
724 *repeating_used
= sheet_get_distance_pts
725 (sheet
, first_rep
, first_rep
+ *n_rep_used
);
727 *repeating_used
= repeating
;
734 paginate (GArray
*paginationInfo
,
736 gint start
, gint end
,
737 gdouble usable
, gboolean repeat
, gint repeat_start
, gint repeat_end
,
738 double (sheet_get_distance_pts
) (Sheet
const *sheet
, int from
, int to
),
739 ColRowInfo
const *(get_info
)(Sheet
const *sheet
, int const p
),
740 GnmPageBreaks
*pb
, gboolean store_breaks
)
743 gint n_rep
= 0, first_rep
= 0;
744 gdouble repeating
= 0.;
748 first_rep
= repeat_start
;
749 n_rep
= repeat_end
- first_rep
+ 1;
750 repeating
= sheet_get_distance_pts (sheet
, first_rep
, first_rep
+ n_rep
);
756 n_end
= gnm_page_breaks_get_next_manual_break (pb
, rc
) - 1;
760 while (rc
<= n_end
) {
763 gdouble repeating_used
= 0.;
764 gint n_rep_used
= 0, first_rep_used
= 0;
766 adjust_repetition (sheet
, rc
,
769 &first_rep_used
, &n_rep_used
,
771 sheet_get_distance_pts
);
773 count
= compute_group (sheet
, rc
, n_end
,
774 usable
- repeating_used
,
777 if (paginationInfo
) {
781 item
.first_rep
= first_rep_used
;
782 item
.n_rep
= n_rep_used
;
783 g_array_append_val (paginationInfo
, item
);
788 if (store_breaks
&& (rc
< n_end
))
789 gnm_page_breaks_set_break (pb
, rc
, GNM_PAGE_BREAK_AUTO
);
796 /* computer_scale_fit_to
797 * Computes the scaling needed to fit all the rows or columns into the @usable
799 * This function is called when printing, and the user has selected the 'fit-to'
800 * printing option. It will adjust the internal x and y scaling values to
801 * make the sheet fit the desired number of pages, as suggested by the user.
802 * It will only reduce the scaling to fit inside a page, not enlarge.
805 compute_scale_fit_to (Sheet
const *sheet
,
806 int start
, int end
, double usable
,
807 ColRowInfo
const *(get_info
)(Sheet
const *sheet
, int const p
),
808 double (get_distance_pts
) (Sheet
const *sheet
, int from
, int to
),
809 gint pages
, double max_percent
, double header
,
810 gboolean repeat
, gint repeat_start
, gint repeat_end
, GnmPageBreaks
*pb
)
816 extent
= get_distance_pts (sheet
, start
, end
+ 1);
818 /* If the repeating columns are not included we should add them */
819 if (repeat
&& (repeat_start
< start
))
820 extent
+= get_distance_pts (sheet
, repeat_start
,
821 (repeat_end
< start
) ? (repeat_end
+ 1) : start
);
823 /* This means to take whatever space is needed. */
827 /* We can handle a single page easily: */
829 max_p
= usable
/(header
+ extent
+ 2.);
830 return ((max_p
> max_percent
) ? max_percent
: max_p
);
833 /* There is no easy way to calculate really which percentage is needed */
834 /* without in fact allocating the cols/rows to pages. */
836 /* We first calculate the max percentage needed */
838 max_p
= (pages
* usable
)/(extent
+ pages
* header
);
839 max_p
= CLAMP (max_p
, 0.01, max_percent
);
841 max_pages
= paginate (NULL
, sheet
, start
, end
, usable
/max_p
- header
,
842 repeat
, repeat_start
, repeat_end
,
843 get_distance_pts
, get_info
, pb
, FALSE
);
845 if (max_pages
== pages
)
848 /* The we calculate the min percentage */
850 min_p
= usable
/(extent
+ header
);
851 min_p
= CLAMP (min_p
, 0.01, max_percent
);
853 paginate (NULL
, sheet
, start
, end
, usable
/min_p
- header
,
854 repeat
, repeat_start
, repeat_end
,
855 get_distance_pts
, get_info
, pb
, FALSE
);
858 /* And then we pick the middle until the percentage is within 0.1% of */
859 /* the desired percentage */
861 while (max_p
- min_p
> 0.001) {
862 double cur_p
= (max_p
+ min_p
) / 2.;
863 int cur_pages
= paginate (NULL
, sheet
, start
, end
, usable
/cur_p
- header
,
864 repeat
, repeat_start
, repeat_end
,
865 get_distance_pts
, get_info
, pb
, FALSE
);
867 if (cur_pages
> pages
)
876 #define COL_FIT(col) (MIN (col, gnm_sheet_get_last_col (sheet)))
877 #define ROW_FIT(row) (MIN (row, gnm_sheet_get_last_row (sheet)))
880 compute_sheet_pages_add_sheet (PrintingInstance
* pi
, Sheet
const *sheet
,
882 gboolean ignore_printarea
)
884 SheetPrintInfo
*spi
= g_new0 (SheetPrintInfo
, 1);
886 spi
->sheet
= (Sheet
*) sheet
;
887 spi
->selection
= selection
;
888 spi
->ignore_printarea
= ignore_printarea
;
889 pi
->gnmSheets
= g_list_append(pi
->gnmSheets
, spi
);
893 print_get_sheet (PrintingInstance
*pi
, guint page_no
)
897 for (l
= pi
->gnmSheets
; l
!= NULL
; l
= l
->next
) {
898 SheetPrintInfo
*spi
= l
->data
;
899 if (spi
->pages
> page_no
)
902 page_no
-= spi
->pages
;
908 static SheetPageRange
*
909 print_get_sheet_page_range (PrintingInstance
*pi
, guint page_no
)
913 for (l
= pi
->gnmSheets
; l
!= NULL
; l
= l
->next
) {
914 SheetPrintInfo
*spi
= l
->data
;
915 if (spi
->pages
> page_no
) {
918 PaginationInfo
*c_info
, *r_info
;
919 Sheet
*sheet
= spi
->sheet
;
921 if (sheet
->print_info
->print_across_then_down
) {
922 col
= page_no
% spi
->column_pagination
->len
;
923 row
= page_no
/ spi
->column_pagination
->len
;
925 col
= page_no
/ spi
->row_pagination
->len
;
926 row
= page_no
% spi
->row_pagination
->len
;
928 g_return_val_if_fail (col
< spi
->column_pagination
->len
&&
929 row
< spi
->row_pagination
->len
, NULL
);
930 gsr
= g_new (SheetPageRange
,1);
931 c_info
= &(g_array_index (spi
->column_pagination
,
932 PaginationInfo
, col
));
933 r_info
= &(g_array_index (spi
->row_pagination
,
934 PaginationInfo
, row
));
935 range_init (&gsr
->range
,
936 COL_FIT (c_info
->rc
), ROW_FIT (r_info
->rc
),
937 COL_FIT (c_info
->rc
+ c_info
->count
- 1),
938 ROW_FIT (r_info
->rc
+ r_info
->count
- 1));
939 gsr
->n_rep_cols
= c_info
->n_rep
;
940 gsr
->first_rep_cols
= c_info
->first_rep
;
941 gsr
->n_rep_rows
= r_info
->n_rep
;
942 gsr
->first_rep_rows
= r_info
->first_rep
;
946 page_no
-= spi
->pages
;
953 return TRUE in case of trouble
957 compute_sheet_pages (GtkPrintContext
*context
,
958 PrintingInstance
* pi
,
961 Sheet
*sheet
= spi
->sheet
;
962 GnmPrintInformation
*pinfo
= sheet
->print_info
;
964 GnmRange
const *selection_range
;
966 gdouble col_header_height
= 0.;
967 gdouble row_header_width
= 0.;
968 gdouble page_width
, page_height
;
969 gdouble top_margin
, bottom_margin
, edge_to_below_header
, edge_to_above_footer
;
971 gdouble usable_x
, usable_y
;
972 GArray
*column_pagination
= g_array_sized_new
973 (FALSE
, TRUE
, sizeof (PaginationInfo
), 100);
974 GArray
*row_pagination
= g_array_sized_new
975 (FALSE
, TRUE
, sizeof (PaginationInfo
), 100);
976 gboolean repeat_top_use
, repeat_left_use
;
977 int repeat_top_start
, repeat_top_end
, repeat_left_start
, repeat_left_end
;
978 double const hscale
= sheet
->display_formulas
? 2 : 1;
980 if (pinfo
->print_titles
) {
981 col_header_height
= sheet
->rows
.default_style
.size_pts
;
982 row_header_width
= sheet
->cols
.default_style
.size_pts
;
985 print_area
= sheet_get_printarea (sheet
,
986 pinfo
->print_even_if_only_styles
,
987 spi
->ignore_printarea
);
988 if (spi
->selection
) {
989 selection_range
= selection_first_range
990 (sheet_get_view (sheet
, wb_control_view (pi
->wbc
)),
991 GO_CMD_CONTEXT (pi
->wbc
), _("Print Selection"));
992 if (selection_range
== NULL
)
994 if (spi
->ignore_printarea
) {
995 print_area
= *selection_range
;
997 if (!range_intersection (&r
, selection_range
, &print_area
))
1003 page_width
= gtk_print_context_get_width (context
);
1004 page_height
= gtk_print_context_get_height (context
);
1005 print_info_get_margins (pinfo
, &top_margin
, &bottom_margin
, NULL
, NULL
,
1006 &edge_to_below_header
, &edge_to_above_footer
);
1007 page_height
-= ((edge_to_below_header
- top_margin
)
1008 + (edge_to_above_footer
- bottom_margin
));
1010 repeat_top_use
= print_load_repeat_range (pinfo
->repeat_top
, &r
, sheet
);
1011 repeat_top_start
= repeat_top_use
? r
.start
.row
: 0;
1012 repeat_top_end
= repeat_top_use
? r
.end
.row
: 0;
1014 repeat_left_use
= print_load_repeat_range (pinfo
->repeat_left
, &r
, sheet
);
1015 repeat_left_start
= repeat_left_use
? r
.start
.col
: 0;
1016 repeat_left_end
= repeat_left_use
? r
.end
.col
: 0;
1018 if (!pi
->ignore_pb
) {
1019 if (pinfo
->page_breaks
.h
== NULL
)
1020 print_info_set_breaks (pinfo
,
1021 gnm_page_breaks_new (FALSE
));
1023 gnm_page_breaks_clean (pinfo
->page_breaks
.h
);
1024 if (pinfo
->page_breaks
.v
== NULL
)
1025 print_info_set_breaks (pinfo
,
1026 gnm_page_breaks_new (TRUE
));
1028 gnm_page_breaks_clean (pinfo
->page_breaks
.v
);
1032 if (pinfo
->scaling
.type
== PRINT_SCALE_FIT_PAGES
) {
1033 /* Note that the resulting scale is independent from */
1034 /* whether we print first down or across! */
1037 pxy
= compute_scale_fit_to (sheet
, print_area
.start
.row
, print_area
.end
.row
,
1038 page_height
, sheet_row_get_info
,
1039 sheet_row_get_distance_pts
,
1040 pinfo
->scaling
.dim
.rows
, 1.,
1043 repeat_top_start
, repeat_top_end
,
1044 pi
->ignore_pb
? NULL
: pinfo
->page_breaks
.h
);
1045 pxy
= compute_scale_fit_to (sheet
, print_area
.start
.col
, print_area
.end
.col
,
1046 page_width
, sheet_col_get_info
,
1047 sheet_col_get_distance_pts
,
1048 pinfo
->scaling
.dim
.cols
, pxy
,
1051 repeat_left_start
, repeat_left_end
,
1052 pi
->ignore_pb
? NULL
: pinfo
->page_breaks
.v
);
1054 pinfo
->scaling
.percentage
.x
= pxy
* 100.;
1055 pinfo
->scaling
.percentage
.y
= pxy
* 100.;
1058 px
= pinfo
->scaling
.percentage
.x
/ 100.;
1059 py
= pinfo
->scaling
.percentage
.y
/ 100.;
1066 usable_x
= page_width
/ px
;
1067 usable_y
= page_height
/ py
;
1069 paginate (column_pagination
, sheet
, print_area
.start
.col
, print_area
.end
.col
,
1070 (usable_x
- row_header_width
)/hscale
,
1071 repeat_left_use
, repeat_left_start
, repeat_left_end
,
1072 sheet_col_get_distance_pts
, sheet_col_get_info
,
1073 pi
->ignore_pb
? NULL
: pinfo
->page_breaks
.v
, !pi
->ignore_pb
);
1074 paginate (row_pagination
, sheet
, print_area
.start
.row
, print_area
.end
.row
,
1075 usable_y
- col_header_height
,
1076 repeat_top_use
, repeat_top_start
, repeat_top_end
,
1077 sheet_row_get_distance_pts
, sheet_row_get_info
,
1078 pi
->ignore_pb
? NULL
: pinfo
->page_breaks
.h
, !pi
->ignore_pb
);
1080 spi
->column_pagination
= column_pagination
;
1081 spi
->row_pagination
= row_pagination
;
1082 spi
->pages
= column_pagination
->len
* row_pagination
->len
;
1088 * Computes the pages that will be output by a specific
1092 compute_pages (G_GNUC_UNUSED GtkPrintOperation
*operation
,
1093 PrintingInstance
* pi
)
1095 Workbook
*wb
= pi
->wb
;
1099 PrintRange pr
= pi
->pr
;
1100 guint from
= pi
->from
;
1104 case GNM_PRINT_SAVED_INFO
:
1105 /* This should never happen. */
1106 case GNM_PRINT_ACTIVE_SHEET
:
1107 compute_sheet_pages_add_sheet (pi
, pi
->sheet
, FALSE
, FALSE
);
1109 case GNM_PRINT_ALL_SHEETS
:
1110 n
= workbook_sheet_count (wb
);
1111 for (i
= 0; i
< n
; i
++) {
1112 Sheet
*sheet
= workbook_sheet_by_index (wb
, i
);
1113 if (sheet
->print_info
->do_not_print
)
1115 if (!sheet_is_visible(sheet
))
1117 compute_sheet_pages_add_sheet (pi
, sheet
,
1121 case GNM_PRINT_ALL_SHEETS_INCLUDING_HIDDEN
:
1122 n
= workbook_sheet_count (wb
);
1123 for (i
= 0; i
< n
; i
++) {
1124 Sheet
*sheet
= workbook_sheet_by_index (wb
, i
);
1125 if (sheet
->print_info
->do_not_print
)
1127 compute_sheet_pages_add_sheet (pi
, sheet
,
1131 case GNM_PRINT_SHEET_RANGE
:
1134 n
= workbook_sheet_count (wb
);
1136 for (i
= 0; i
< n
; i
++){
1137 Sheet
*sheet
= workbook_sheet_by_index (wb
, i
);
1138 if (sheet_is_visible(sheet
))
1142 if (sheet
->print_info
->do_not_print
)
1144 if ((ct
>= from
) && (ct
<= to
))
1145 compute_sheet_pages_add_sheet (pi
, sheet
,
1149 case GNM_PRINT_SHEET_SELECTION
:
1150 compute_sheet_pages_add_sheet (pi
, pi
->sheet
, TRUE
, FALSE
);
1152 case GNM_PRINT_IGNORE_PRINTAREA
:
1153 compute_sheet_pages_add_sheet (pi
, pi
->sheet
, FALSE
, TRUE
);
1155 case GNM_PRINT_SHEET_SELECTION_IGNORE_PRINTAREA
:
1156 compute_sheet_pages_add_sheet (pi
, pi
->sheet
, TRUE
, TRUE
);
1164 static PrintJobInfo
*
1165 print_job_info_get (Sheet
*sheet
, PrintRange range
, gboolean
const preview
)
1167 PrintJobInfo
*pj
= g_new0 (PrintJobInfo
, 1);
1169 pj
->gp_config
= print_info_make_config (sheet
->print_info
);
1171 /* Values that should be entered in a dialog box */
1173 pj
->end_page
= workbook_sheet_count (sheet
->workbook
) - 1;
1175 pj
->sorted_print
= TRUE
;
1176 pj
->is_preview
= preview
;
1177 pj
->current_output_sheet
= 0;
1182 pj
->render_info
= gnm_print_hf_render_info_new ();
1183 pj
->render_info
->sheet
= sheet
;
1184 pj
->render_info
->page
= 1;
1190 print_job_info_destroy (PrintJobInfo
*pj
)
1192 g_object_unref (pj
->gp_config
);
1193 gnm_print_hf_render_info_destroy (pj
->render_info
);
1194 if (pj
->decoration_layout
)
1195 g_object_unref (pj
->decoration_layout
);
1196 if (pj
->print_context
)
1197 g_object_unref (pj
->print_context
);
1204 gnm_paginate_cb (GtkPrintOperation
*operation
,
1205 GtkPrintContext
*context
,
1208 PrintingInstance
* pi
= (PrintingInstance
*) user_data
;
1209 guint paginate
= (pi
->last_pagination
)++;
1210 SheetPrintInfo
*spi
;
1212 if (gnm_debug_flag ("print"))
1213 g_printerr ("paginate %d\n", paginate
);
1215 spi
= g_list_nth_data (pi
->gnmSheets
, paginate
);
1216 if (spi
== NULL
) { /*We are done paginating */
1217 /* GTK sends additional pagination requests! */
1218 /* We only need to do this once though! */
1219 if (g_list_nth_data (pi
->gnmSheets
, paginate
- 1) != NULL
) {
1223 for (l
= pi
->gnmSheets
; l
!= NULL
; l
= l
->next
) {
1224 SheetPrintInfo
*spi
= l
->data
;
1225 n_pages
+= spi
->pages
;
1228 if (pi
->preview
&& n_pages
> 1000) {
1231 gtk_print_operation_set_n_pages
1232 (operation
, n_pages
== 0 ? 1 : n_pages
);
1233 for (i
= 0; i
< n_pages
; i
++) {
1234 if (gtk_print_operation_preview_is_selected
1235 (GTK_PRINT_OPERATION_PREVIEW (operation
),
1241 if (count
> 1000 && !go_gtk_query_yes_no
1242 (pi
->progress
!= NULL
?
1243 GTK_WINDOW (pi
->progress
) : wbcg_toplevel (WBC_GTK (pi
->wbc
)),
1245 _("You have chosen more than 1000 pages to preview. "
1246 "This may take a long time. "
1247 "Do you really want to proceed?")))
1251 gtk_print_operation_set_n_pages (operation
, n_pages
== 0 ? 1 : n_pages
);
1252 gtk_print_operation_set_unit (operation
, GTK_UNIT_POINTS
);
1253 pi
->hfi
->pages
= n_pages
;
1255 if (n_pages
== 0) /* gtk+ cannot handle 0 pages */
1256 gtk_print_operation_cancel (operation
);
1261 if (compute_sheet_pages (context
, pi
, spi
)) {
1262 gtk_print_operation_cancel (operation
);
1270 cb_progress_response (G_GNUC_UNUSED GtkDialog
*dialog
,
1271 G_GNUC_UNUSED gint response_id
,
1272 PrintingInstance
*pi
)
1278 cb_progress_delete (G_GNUC_UNUSED GtkWidget
*widget
,
1279 G_GNUC_UNUSED GdkEvent
*event
,
1280 PrintingInstance
*pi
)
1287 gnm_ready_preview_cb (G_GNUC_UNUSED GtkPrintOperation
*operation
,
1288 G_GNUC_UNUSED GtkPrintOperationPreview
*preview
,
1289 G_GNUC_UNUSED GtkPrintContext
*context
,
1290 G_GNUC_UNUSED GtkWindow
*parent
,
1293 PrintingInstance
* pi
= (PrintingInstance
*) user_data
;
1300 gnm_begin_print_cb (GtkPrintOperation
*operation
,
1301 G_GNUC_UNUSED GtkPrintContext
*context
,
1304 PrintingInstance
* pi
= (PrintingInstance
*) user_data
;
1306 if (gnm_debug_flag ("print"))
1307 g_printerr ("begin-print\n");
1310 /* Working around gtk+ bug 423484. */
1311 GtkPrintSettings
*settings
= gtk_print_operation_get_print_settings (operation
);
1312 gtk_print_settings_set_int
1313 (settings
, GNUMERIC_PRINT_SETTING_PRINT_FROM_SHEET_KEY
,
1315 gtk_print_settings_set_int
1316 (settings
, GNUMERIC_PRINT_SETTING_PRINT_TO_SHEET_KEY
,
1318 gtk_print_settings_set_int
1319 (settings
, GNUMERIC_PRINT_SETTING_PRINTRANGE_KEY
, pi
->pr
);
1320 gtk_print_settings_set_int
1321 (settings
, GNUMERIC_PRINT_SETTING_IGNORE_PAGE_BREAKS_KEY
, pi
->ignore_pb
? 1 : 0);
1324 if (NULL
!= pi
->wbc
&& GNM_IS_WBC_GTK(pi
->wbc
)) {
1325 pi
->progress
= gtk_message_dialog_new (wbcg_toplevel (WBC_GTK (pi
->wbc
)),
1327 GTK_DIALOG_DESTROY_WITH_PARENT
,
1330 "%s", /* please clang */
1332 _("Preparing to preview"):
1333 _("Preparing to print"));
1334 g_signal_connect (G_OBJECT (pi
->progress
), "response",
1335 G_CALLBACK (cb_progress_response
), pi
);
1336 g_signal_connect (G_OBJECT (pi
->progress
), "delete-event",
1337 G_CALLBACK (cb_progress_delete
), pi
);
1338 gtk_widget_show_all (pi
->progress
);
1341 compute_pages (operation
, pi
);
1345 gnm_end_print_cb (G_GNUC_UNUSED GtkPrintOperation
*operation
,
1346 G_GNUC_UNUSED GtkPrintContext
*context
,
1347 G_GNUC_UNUSED gpointer user_data
)
1349 if (gnm_debug_flag ("print"))
1350 g_printerr ("end-print\n");
1354 cp_gtk_page_setup (GtkPageSetup
*from
, GtkPageSetup
*to
)
1356 gtk_page_setup_set_paper_size (to
, gtk_page_setup_get_paper_size (from
));
1357 gtk_page_setup_set_orientation (to
,gtk_page_setup_get_orientation (from
));
1358 gtk_page_setup_set_top_margin
1359 (to
, gtk_page_setup_get_top_margin (from
, GTK_UNIT_MM
), GTK_UNIT_MM
);
1360 gtk_page_setup_set_bottom_margin
1361 (to
, gtk_page_setup_get_bottom_margin (from
, GTK_UNIT_MM
), GTK_UNIT_MM
);
1362 gtk_page_setup_set_left_margin
1363 (to
, gtk_page_setup_get_left_margin (from
, GTK_UNIT_MM
), GTK_UNIT_MM
);
1364 gtk_page_setup_set_right_margin
1365 (to
, gtk_page_setup_get_right_margin (from
, GTK_UNIT_MM
), GTK_UNIT_MM
);
1369 gnm_request_page_setup_cb (GtkPrintOperation
*operation
,
1370 G_GNUC_UNUSED GtkPrintContext
*context
,
1372 GtkPageSetup
*setup
,
1375 PrintingInstance
* pi
= (PrintingInstance
*) user_data
;
1377 GtkPrintSettings
* settings
= gtk_print_operation_get_print_settings
1380 g_return_if_fail (pi
!= NULL
);
1382 sheet
= print_get_sheet (pi
, page_nr
);
1384 if (sheet
== NULL
) {
1385 /* g_warning ("Avoiding gtk+ bug 492498"); */
1389 gtk_print_settings_set_use_color (settings
, !sheet
->print_info
->print_black_and_white
);
1390 if (sheet
->print_info
->page_setup
== NULL
)
1391 gnm_print_info_load_defaults (sheet
->print_info
);
1392 if (sheet
->print_info
->page_setup
!= NULL
)
1393 cp_gtk_page_setup (sheet
->print_info
->page_setup
, setup
);
1397 gnm_draw_page_cb (GtkPrintOperation
*operation
,
1398 GtkPrintContext
*context
,
1403 PrintingInstance
* pi
= (PrintingInstance
*) user_data
;
1404 SheetPageRange
* gsr
;
1406 if (gnm_debug_flag ("print"))
1407 g_printerr ("draw-page %d\n", page_nr
);
1410 gtk_print_operation_cancel (operation
);
1411 g_signal_handlers_disconnect_by_func
1412 (G_OBJECT (operation
), G_CALLBACK (gnm_draw_page_cb
), user_data
);
1416 gsr
= print_get_sheet_page_range (pi
, page_nr
);
1421 if (pi
->hfi
->pages
== -1)
1422 text
= g_strdup_printf
1423 (pi
->preview
? _("Creating preview of page %3d")
1424 : _("Printing page %3d"), page_nr
);
1426 text
= g_strdup_printf
1428 ngettext("Creating preview of page %3d of %3d page",
1429 "Creating preview of page %3d of %3d pages",
1431 : ngettext("Printing page %3d of %3d page",
1432 "Printing page %3d of %3d pages",
1434 page_nr
, pi
->hfi
->pages
);
1435 g_object_set (G_OBJECT (pi
->progress
), "text", text
, NULL
);
1438 pi
->hfi
->page
= page_nr
+ 1;
1439 pi
->hfi
->sheet
= gsr
->sheet
;
1440 pi
->hfi
->page_area
= gsr
->range
;
1441 pi
->hfi
->top_repeating
= gsr
->range
.start
;
1442 if (gsr
->n_rep_cols
> 0)
1443 pi
->hfi
->top_repeating
.col
= gsr
->first_rep_cols
;
1444 if (gsr
->n_rep_rows
> 0)
1445 pi
->hfi
->top_repeating
.row
= gsr
->first_rep_rows
;
1446 print_page (operation
, context
, pi
, gsr
);
1452 widget_button_cb (GtkToggleButton
*togglebutton
, GtkWidget
*check
)
1454 gtk_widget_set_sensitive (check
, gtk_toggle_button_get_active (togglebutton
));
1458 workbook_visible_sheet_count (Workbook
*wb
)
1461 guint n
= workbook_sheet_count (wb
);
1464 for (i
= 0; i
< n
; i
++) {
1465 Sheet
*sheet
= workbook_sheet_by_index (wb
, i
);
1466 if (sheet_is_visible(sheet
))
1473 gnm_create_widget_cb (GtkPrintOperation
*operation
, gpointer user_data
)
1475 PrintingInstance
* pi
= (PrintingInstance
*) user_data
;
1477 GtkWidget
*button_all_sheets
, *button_selected_sheet
, *button_spec_sheets
;
1478 GtkWidget
*button_selection
, *button_ignore_printarea
;
1479 GtkWidget
*button_print_hidden_sheets
;
1480 GtkWidget
*label_from
, *label_to
;
1481 GtkWidget
*spin_from
, *spin_to
;
1482 GtkWidget
*button_ignore_page_breaks
;
1483 GtkPrintSettings
* settings
;
1484 guint n_sheets
= workbook_visible_sheet_count (pi
->wb
);
1486 if (gnm_debug_flag ("print"))
1487 g_printerr ("Creating custom print widget\n");
1489 grid
= gtk_grid_new ();
1491 "column-spacing", 12,
1496 button_all_sheets
= gtk_radio_button_new_with_mnemonic (NULL
,
1497 _("_All workbook sheets"));
1498 gtk_widget_set_hexpand (button_all_sheets
, TRUE
);
1499 gtk_grid_attach (GTK_GRID (grid
), button_all_sheets
, 0, 0, 5, 1);
1501 button_print_hidden_sheets
= gtk_check_button_new_with_mnemonic
1502 (_("Also print _hidden sheets"));
1503 g_object_set (button_print_hidden_sheets
,
1507 gtk_grid_attach (GTK_GRID (grid
), button_print_hidden_sheets
, 0, 1, 5, 1);
1509 button_selected_sheet
= gtk_radio_button_new_with_mnemonic_from_widget
1510 (GTK_RADIO_BUTTON (button_all_sheets
), _("A_ctive workbook sheet"));
1511 gtk_widget_set_hexpand (button_selected_sheet
, TRUE
);
1512 gtk_grid_attach (GTK_GRID (grid
), button_selected_sheet
, 0, 2, 5, 1);
1514 button_spec_sheets
= gtk_radio_button_new_with_mnemonic_from_widget
1515 (GTK_RADIO_BUTTON (button_all_sheets
), _("_Workbook sheets:"));
1516 gtk_widget_set_hexpand (button_spec_sheets
, TRUE
);
1517 gtk_grid_attach (GTK_GRID (grid
), button_spec_sheets
, 0, 5, 1, 1);
1519 button_selection
= gtk_check_button_new_with_mnemonic
1520 (_("Current _selection only"));
1521 g_object_set (button_selection
,
1525 gtk_grid_attach (GTK_GRID (grid
), button_selection
, 0, 3, 5, 1);
1527 button_ignore_printarea
= gtk_check_button_new_with_mnemonic
1528 (_("_Ignore defined print area"));
1529 g_object_set (button_ignore_printarea
,
1533 gtk_grid_attach (GTK_GRID (grid
), button_ignore_printarea
, 0, 4, 5, 1);
1535 label_from
= gtk_label_new (_("from:"));
1536 g_object_set (label_from
,
1540 gtk_grid_attach (GTK_GRID (grid
), label_from
, 1, 5, 1, 1);
1542 spin_from
= gtk_spin_button_new_with_range (1, n_sheets
, 1);
1543 gtk_widget_set_hexpand (spin_from
, TRUE
);
1544 gtk_grid_attach (GTK_GRID (grid
), spin_from
, 2, 5, 1, 1);
1546 label_to
= gtk_label_new (_("to:"));
1547 gtk_widget_set_hexpand (label_to
, TRUE
);
1548 gtk_grid_attach (GTK_GRID (grid
), label_to
, 3, 5, 1, 1);
1550 spin_to
= gtk_spin_button_new_with_range (1, n_sheets
, 1);
1551 gtk_widget_set_hexpand (spin_to
, TRUE
);
1552 gtk_grid_attach (GTK_GRID (grid
), spin_to
, 4, 5, 1, 1);
1553 gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_to
), n_sheets
);
1555 button_ignore_page_breaks
= gtk_separator_new (GTK_ORIENTATION_HORIZONTAL
);
1556 gtk_widget_set_hexpand (button_ignore_page_breaks
, TRUE
);
1557 gtk_grid_attach (GTK_GRID (grid
), button_ignore_page_breaks
, 0, 6, 5, 1);
1559 button_ignore_page_breaks
= gtk_check_button_new_with_mnemonic (_("Ignore all _manual page breaks"));
1560 gtk_widget_set_hexpand (button_ignore_page_breaks
, TRUE
);
1561 gtk_grid_attach (GTK_GRID (grid
), button_ignore_page_breaks
, 0, 7, 5, 1);
1562 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_ignore_page_breaks
), TRUE
);
1564 g_signal_connect_after (G_OBJECT (button_selected_sheet
), "toggled",
1565 G_CALLBACK (widget_button_cb
), button_selection
);
1566 g_signal_connect_after (G_OBJECT (button_selected_sheet
), "toggled",
1567 G_CALLBACK (widget_button_cb
), button_ignore_printarea
);
1569 g_signal_connect_after (G_OBJECT (button_all_sheets
), "toggled",
1570 G_CALLBACK (widget_button_cb
), button_print_hidden_sheets
);
1572 g_signal_connect_after (G_OBJECT (button_spec_sheets
), "toggled",
1573 G_CALLBACK (widget_button_cb
), label_from
);
1574 g_signal_connect_after (G_OBJECT (button_spec_sheets
), "toggled",
1575 G_CALLBACK (widget_button_cb
), label_to
);
1576 g_signal_connect_after (G_OBJECT (button_spec_sheets
), "toggled",
1577 G_CALLBACK (widget_button_cb
), spin_from
);
1578 g_signal_connect_after (G_OBJECT (button_spec_sheets
), "toggled",
1579 G_CALLBACK (widget_button_cb
), spin_to
);
1581 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_selected_sheet
), TRUE
);
1583 settings
= gtk_print_operation_get_print_settings (operation
);
1586 switch (gtk_print_settings_get_int_with_default
1587 (settings
, GNUMERIC_PRINT_SETTING_PRINTRANGE_KEY
,
1588 GNM_PRINT_ACTIVE_SHEET
)) {
1589 case GNM_PRINT_SHEET_SELECTION_IGNORE_PRINTAREA
:
1590 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_ignore_printarea
), TRUE
);
1592 case GNM_PRINT_SHEET_SELECTION
:
1593 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_selection
), TRUE
);
1595 case GNM_PRINT_ACTIVE_SHEET
:
1596 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_selected_sheet
), TRUE
);
1598 case GNM_PRINT_IGNORE_PRINTAREA
:
1599 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_ignore_printarea
), TRUE
);
1600 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_selected_sheet
), TRUE
);
1602 case GNM_PRINT_SHEET_RANGE
:
1603 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_spec_sheets
), TRUE
);
1605 case GNM_PRINT_ALL_SHEETS_INCLUDING_HIDDEN
:
1606 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_print_hidden_sheets
), TRUE
);
1608 case GNM_PRINT_ALL_SHEETS
:
1609 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_all_sheets
), TRUE
);
1613 gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_from
),
1614 gtk_print_settings_get_int_with_default
1615 (settings
, GNUMERIC_PRINT_SETTING_PRINT_FROM_SHEET_KEY
,
1617 gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_to
),
1618 gtk_print_settings_get_int_with_default
1619 (settings
, GNUMERIC_PRINT_SETTING_PRINT_TO_SHEET_KEY
,
1621 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_ignore_page_breaks
),
1622 0 != gtk_print_settings_get_int_with_default
1623 (settings
, GNUMERIC_PRINT_SETTING_IGNORE_PAGE_BREAKS_KEY
,
1627 /* We are sending toggled signals to ensure that all widgets are */
1628 /* correctly enabled or disabled. */
1629 gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (button_selected_sheet
));
1630 gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (button_spec_sheets
));
1632 gtk_widget_show_all (grid
);
1634 /* Let's save the widgets */
1635 pi
->button_all_sheets
= button_all_sheets
;
1636 pi
->button_selected_sheet
= button_selected_sheet
;
1637 pi
->button_spec_sheets
= button_spec_sheets
;
1638 pi
->button_selection
= button_selection
;
1639 pi
->button_ignore_printarea
= button_ignore_printarea
;
1640 pi
->button_print_hidden_sheets
= button_print_hidden_sheets
;
1641 pi
->spin_from
= spin_from
;
1642 pi
->spin_to
= spin_to
;
1643 pi
->button_ignore_page_breaks
= button_ignore_page_breaks
;
1645 if (gnm_debug_flag ("print"))
1646 g_printerr ("Done with creating custom print widget\n");
1648 return G_OBJECT (grid
);
1652 gnm_custom_widget_apply_cb (GtkPrintOperation
*operation
,
1653 G_GNUC_UNUSED GtkWidget
*widget
,
1656 PrintingInstance
* pi
= (PrintingInstance
*) user_data
;
1657 GtkPrintSettings
* settings
;
1658 PrintRange pr
= GNM_PRINT_ACTIVE_SHEET
;
1662 settings
= gtk_print_operation_get_print_settings (operation
);
1664 g_return_if_fail (settings
!= NULL
);
1666 from
= gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pi
->spin_from
));
1667 to
= gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pi
->spin_to
));
1669 gtk_print_settings_set_int (settings
,
1670 GNUMERIC_PRINT_SETTING_PRINT_FROM_SHEET_KEY
,
1672 gtk_print_settings_set_int (settings
,
1673 GNUMERIC_PRINT_SETTING_PRINT_TO_SHEET_KEY
,
1678 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pi
->button_all_sheets
))) {
1679 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pi
->button_print_hidden_sheets
)))
1680 pr
= GNM_PRINT_ALL_SHEETS_INCLUDING_HIDDEN
;
1682 pr
= GNM_PRINT_ALL_SHEETS
;
1683 } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pi
->button_spec_sheets
))) {
1684 pr
= GNM_PRINT_SHEET_RANGE
;
1685 } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pi
->button_selected_sheet
))) {
1686 gboolean ignore_printarea
= gtk_toggle_button_get_active
1687 (GTK_TOGGLE_BUTTON (pi
->button_ignore_printarea
));
1688 gboolean selection
= gtk_toggle_button_get_active
1689 (GTK_TOGGLE_BUTTON (pi
->button_selection
));
1690 if (selection
&& ignore_printarea
)
1691 pr
= GNM_PRINT_SHEET_SELECTION_IGNORE_PRINTAREA
;
1693 pr
= GNM_PRINT_SHEET_SELECTION
;
1694 else if (ignore_printarea
)
1695 pr
= GNM_PRINT_IGNORE_PRINTAREA
;
1697 pr
= GNM_PRINT_ACTIVE_SHEET
;
1700 gtk_print_settings_set_int (settings
,
1701 GNUMERIC_PRINT_SETTING_PRINTRANGE_KEY
, pr
);
1705 ignore_pb
= gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pi
->button_ignore_page_breaks
)) ? 1 : 0;
1706 gtk_print_settings_set_int (settings
, GNUMERIC_PRINT_SETTING_IGNORE_PAGE_BREAKS_KEY
,
1708 pi
->ignore_pb
= ignore_pb
;
1712 cb_delete_and_free (char *tmp_file_name
)
1714 if (tmp_file_name
) {
1715 g_unlink (tmp_file_name
);
1716 g_free (tmp_file_name
);
1721 gnm_print_uri_change_extension (char const *uri
, GtkPrintSettings
* settings
)
1723 const gchar
*ext
= gtk_print_settings_get
1725 GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT
);
1730 gint uri_len
= strlen(uri
);
1734 gtk_print_settings_set (settings
,
1735 GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT
,
1739 base
= g_path_get_basename (uri
);
1740 used_ext
= strrchr (base
, '.');
1741 if (used_ext
== NULL
)
1742 return g_strconcat (uri
, ".", ext
, NULL
);
1743 strip
= strlen (base
) - (used_ext
- base
);
1744 res
= g_strndup (uri
, uri_len
- strip
+ 1 + strlen (ext
));
1745 res
[uri_len
- strip
] = '.';
1746 strcpy (res
+ uri_len
- strip
+ 1, ext
);
1751 gnm_print_sheet (WorkbookControl
*wbc
, Sheet
*sheet
,
1752 gboolean preview
, PrintRange default_range
,
1753 GsfOutput
*export_dst
)
1755 GtkPrintOperation
*print
;
1756 GtkPrintOperationResult res
;
1757 GtkPageSetup
*page_setup
;
1758 PrintingInstance
*pi
;
1759 GtkPrintSettings
* settings
;
1760 GtkWindow
*parent
= NULL
;
1761 GtkPrintOperationAction action
;
1762 gchar
*tmp_file_name
= NULL
;
1763 int tmp_file_fd
= -1;
1764 gboolean preview_via_pdf
= FALSE
;
1765 PrintRange pr_translator
[] = {GNM_PRINT_ACTIVE_SHEET
, GNM_PRINT_ALL_SHEETS
,
1766 GNM_PRINT_ALL_SHEETS
, GNM_PRINT_ACTIVE_SHEET
,
1767 GNM_PRINT_SHEET_SELECTION
, GNM_PRINT_ACTIVE_SHEET
,
1768 GNM_PRINT_SHEET_SELECTION_IGNORE_PRINTAREA
};
1770 gchar
*output_uri
= NULL
;
1771 gchar
const *saved_uri
= NULL
;
1773 #ifdef PREVIEW_VIA_PDF
1774 preview_via_pdf
= preview
;
1777 g_return_if_fail (sheet
!= NULL
&& sheet
->workbook
!= NULL
);
1780 g_return_if_fail (!export_dst
&& wbc
);
1782 doc
= GO_DOC (sheet
->workbook
);
1784 print
= gtk_print_operation_new ();
1786 pi
= printing_instance_new ();
1787 pi
->wb
= sheet
->workbook
;
1788 pi
->wbc
= wbc
? GNM_WBC (wbc
) : NULL
;
1790 pi
->preview
= preview
;
1792 settings
= gnm_conf_get_print_settings ();
1793 if (default_range
== GNM_PRINT_SAVED_INFO
) {
1794 gint dr
= print_info_get_printrange (sheet
->print_info
);
1795 if (dr
< 0 || dr
>= (gint
)G_N_ELEMENTS (pr_translator
))
1796 default_range
= GNM_PRINT_ACTIVE_SHEET
;
1798 default_range
= pr_translator
[dr
];
1800 gtk_print_settings_set_int (settings
,
1801 GNUMERIC_PRINT_SETTING_PRINTRANGE_KEY
,
1803 pi
->pr
= default_range
;
1804 gtk_print_settings_set_use_color (settings
,
1805 !sheet
->print_info
->print_black_and_white
);
1806 if (!export_dst
&& !preview_via_pdf
&& !preview
) {
1807 /* We should be setting the output file name to something */
1809 saved_uri
= print_info_get_printtofile_uri (sheet
->print_info
);
1810 if (saved_uri
!= NULL
&&
1811 g_ascii_strncasecmp (doc
->uri
, "file:///", 8) == 0)
1812 output_uri
= gnm_print_uri_change_extension (saved_uri
,
1816 if (output_uri
== NULL
&& doc
->uri
!= NULL
1817 && g_ascii_strncasecmp (doc
->uri
, "file:///", 8) == 0)
1818 output_uri
= gnm_print_uri_change_extension (doc
->uri
,
1820 if (output_uri
!= NULL
) {
1821 gtk_print_settings_set (settings
,
1822 GTK_PRINT_SETTINGS_OUTPUT_URI
,
1824 g_free (output_uri
);
1828 gtk_print_operation_set_print_settings (print
, settings
);
1829 g_object_unref (settings
);
1831 page_setup
= gnm_print_info_get_page_setup (sheet
->print_info
);
1833 gtk_print_operation_set_default_page_setup (print
, page_setup
);
1835 g_signal_connect (print
, "preview", G_CALLBACK (gnm_ready_preview_cb
), pi
);
1836 g_signal_connect (print
, "begin-print", G_CALLBACK (gnm_begin_print_cb
), pi
);
1837 g_signal_connect (print
, "paginate", G_CALLBACK (gnm_paginate_cb
), pi
);
1838 g_signal_connect (print
, "draw-page", G_CALLBACK (gnm_draw_page_cb
), pi
);
1839 g_signal_connect (print
, "end-print", G_CALLBACK (gnm_end_print_cb
), pi
);
1840 g_signal_connect (print
, "request-page-setup", G_CALLBACK (gnm_request_page_setup_cb
), pi
);
1842 gtk_print_operation_set_use_full_page (print
, FALSE
);
1843 gtk_print_operation_set_unit (print
, GTK_UNIT_POINTS
);
1845 if (NULL
!= wbc
&& GNM_IS_WBC_GTK(wbc
))
1846 parent
= wbcg_toplevel (WBC_GTK (wbc
));
1848 if (preview_via_pdf
|| export_dst
) {
1851 tmp_file_fd
= g_file_open_tmp ("gnmXXXXXX.pdf",
1852 &tmp_file_name
, &err
);
1855 gsf_output_set_error (export_dst
, 0,
1856 "%s", err
->message
);
1858 char *text
= g_strdup_printf
1859 (_("Failed to create temporary file for printing: %s"),
1861 go_cmd_context_error_export
1862 (GO_CMD_CONTEXT (wbc
), text
);
1869 action
= GTK_PRINT_OPERATION_ACTION_EXPORT
;
1870 gtk_print_operation_set_export_filename (print
, tmp_file_name
);
1871 gtk_print_operation_set_show_progress (print
, FALSE
);
1874 ? GTK_PRINT_OPERATION_ACTION_PREVIEW
1875 : GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG
;
1876 gtk_print_operation_set_show_progress (print
, FALSE
);
1877 gtk_print_operation_set_custom_tab_label (print
, _("Gnumeric Print Range"));
1878 g_signal_connect (print
, "create-custom-widget", G_CALLBACK (gnm_create_widget_cb
), pi
);
1879 g_signal_connect (print
, "custom-widget-apply", G_CALLBACK (gnm_custom_widget_apply_cb
), pi
);
1882 res
= gtk_print_operation_run (print
, action
, parent
, NULL
);
1885 case GTK_PRINT_OPERATION_RESULT_APPLY
:
1886 if (action
== GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG
) {
1887 char const *printer
;
1888 settings
= gtk_print_operation_get_print_settings (print
);
1889 gnm_conf_set_print_settings (settings
);
1890 gnm_insert_meta_date (doc
, GSF_META_NAME_PRINT_DATE
);
1891 printer
= gtk_print_settings_get_printer (settings
);
1892 if (strcmp (printer
, "Print to File") == 0 ||
1893 strcmp (printer
, _("Print to File")) == 0) {
1894 gchar
*wb_output_uri
=
1895 gnm_print_uri_change_extension (doc
->uri
,
1897 print_info_set_printtofile_from_settings
1898 (sheet
->print_info
, settings
, wb_output_uri
);
1899 g_free (wb_output_uri
);
1902 print_info_set_from_settings
1903 (sheet
->print_info
, settings
);
1905 case GTK_PRINT_OPERATION_RESULT_CANCEL
:
1907 case GTK_PRINT_OPERATION_RESULT_ERROR
:
1909 case GTK_PRINT_OPERATION_RESULT_IN_PROGRESS
:
1910 /* This can only happen if we were allowing asynchronous operation */
1914 printing_instance_delete (pi
);
1916 if (preview_via_pdf
) {
1918 /* For some reason the general code doesn't work for me.
1919 Be brutal, even if this might not work for non-ASCII
1921 int res
= (int)ShellExecute (NULL
, "open",
1926 if (gnm_debug_flag ("preview")) {
1927 g_printerr ("tmp_file_name=%s\n", tmp_file_name
);
1928 g_printerr ("res=%d\n", res
);
1931 GdkScreen
*screen
= parent
1932 ? gtk_widget_get_screen (GTK_WIDGET (parent
))
1934 char *url
= go_filename_to_uri (tmp_file_name
);
1935 go_gtk_url_show (url
, screen
);
1939 /* We hook this up to delete the temp file when the workbook
1940 is closed or when a new preview is done for the same
1941 workbook. That's not perfect, but good enough while
1942 we wait for gtk+ to fix printing. */
1943 g_object_set_data_full (G_OBJECT (wbc
),
1944 "temp-file", tmp_file_name
,
1945 (GDestroyNotify
)cb_delete_and_free
);
1946 tmp_file_name
= NULL
;
1947 } else if (tmp_file_name
) {
1948 char buffer
[64 * 1024];
1951 if (lseek (tmp_file_fd
, 0, SEEK_SET
) < 0)
1954 while ((bytes_read
= read (tmp_file_fd
, buffer
, sizeof (buffer
))) > 0) {
1955 gsf_output_write (export_dst
, bytes_read
, buffer
);
1958 if (bytes_read
< 0) {
1959 int save_errno
= errno
;
1960 if (!gsf_output_error (export_dst
))
1961 gsf_output_set_error (export_dst
,
1962 g_file_error_from_errno (save_errno
),
1963 "%s", g_strerror (save_errno
));
1968 if (tmp_file_fd
>= 0)
1969 close (tmp_file_fd
);
1970 cb_delete_and_free (tmp_file_name
);
1972 g_object_unref (print
);
1976 gnm_draw_so_page_cb (G_GNUC_UNUSED GtkPrintOperation
*operation
,
1977 GtkPrintContext
*context
,
1978 G_GNUC_UNUSED gint page_nr
,
1982 SheetObject
*so
= (SheetObject
*) user_data
;
1983 cairo_t
*cr
= gtk_print_context_get_cairo_context (context
);
1984 Sheet
*sheet
= sheet_object_get_sheet (so
);
1987 cairo_translate (cr
, 0, 0);
1988 sheet_object_draw_cairo (so
, (gpointer
)cr
, sheet
->text_is_rtl
);
1995 * @sos: (element-type SheetObject) (transfer none):
1999 gnm_print_so (WorkbookControl
*wbc
, GPtrArray
*sos
,
2000 GsfOutput
*export_dst
)
2002 GtkPrintOperation
*print
;
2003 GtkPageSetup
*page_setup
;
2004 GtkPrintSettings
* settings
;
2006 GtkWindow
*parent
= NULL
;
2007 GtkPrintOperationAction action
;
2008 gchar
*tmp_file_name
= NULL
;
2009 int tmp_file_fd
= -1;
2012 g_return_if_fail (sos
!= NULL
&& sos
->len
> 0);
2014 /* FIXME: we should print all objects in the array, not just the first! */
2016 so
= g_ptr_array_index (sos
, 0),
2017 sheet
= sheet_object_get_sheet (so
);
2018 if (NULL
!= wbc
&& GNM_IS_WBC_GTK(wbc
))
2019 parent
= wbcg_toplevel (WBC_GTK (wbc
));
2021 print
= gtk_print_operation_new ();
2023 settings
= gnm_conf_get_print_settings ();
2024 gtk_print_settings_set_use_color (settings
,
2025 !sheet
->print_info
->print_black_and_white
);
2026 gtk_print_operation_set_print_settings (print
, settings
);
2027 g_object_unref (settings
);
2029 page_setup
= gnm_print_info_get_page_setup (sheet
->print_info
);
2031 gtk_print_operation_set_default_page_setup (print
, page_setup
);
2033 gtk_print_operation_set_n_pages (print
, 1);
2034 gtk_print_operation_set_embed_page_setup (print
, TRUE
);
2036 g_signal_connect (print
, "draw-page", G_CALLBACK (gnm_draw_so_page_cb
), so
);
2038 gtk_print_operation_set_use_full_page (print
, FALSE
);
2039 gtk_print_operation_set_unit (print
, GTK_UNIT_POINTS
);
2044 tmp_file_fd
= g_file_open_tmp ("gnmXXXXXX.pdf",
2045 &tmp_file_name
, &err
);
2047 gsf_output_set_error (export_dst
, 0,
2048 "%s", err
->message
);
2050 if (tmp_file_fd
>= 0)
2051 close (tmp_file_fd
);
2052 cb_delete_and_free (tmp_file_name
);
2054 g_object_unref (print
);
2057 action
= GTK_PRINT_OPERATION_ACTION_EXPORT
;
2058 gtk_print_operation_set_export_filename (print
, tmp_file_name
);
2059 gtk_print_operation_set_show_progress (print
, FALSE
);
2061 action
= GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG
;
2062 gtk_print_operation_set_show_progress (print
, TRUE
);
2065 gtk_print_operation_run (print
, action
, parent
, NULL
);
2067 if (tmp_file_name
) {
2068 char buffer
[64 * 1024];
2071 if (lseek (tmp_file_fd
, 0, SEEK_SET
) < 0)
2074 while ((bytes_read
= read
2075 (tmp_file_fd
, buffer
, sizeof (buffer
))) > 0) {
2076 gsf_output_write (export_dst
, bytes_read
, buffer
);
2079 if (bytes_read
< 0) {
2080 int save_errno
= errno
;
2081 if (!gsf_output_error (export_dst
))
2082 gsf_output_set_error (export_dst
,
2083 g_file_error_from_errno (save_errno
),
2084 "%s", g_strerror (save_errno
));
2086 close (tmp_file_fd
);
2087 cb_delete_and_free (tmp_file_name
);
2090 g_object_unref (print
);